|
Home | Switchboard | Unix Administration | Red Hat | TCP/IP Networks | Neoliberalism | Toxic Managers |
(slightly skeptical) Educational society promoting "Back to basics" movement against IT overcomplexity and bastardization of classic Unix |
|
|
Q. I deleted update-rc.d, how can I get it back again?
A. Go here http://www.debian.org/distrib/packages and then choose the textbox to search for files in packages... easy if you know :-) Usually this package is called something like sysv-rc. Now download this package. Then comes the tricky part because without update-rc.d installing a package is not trivial. A chicken and egg problem. Use the ar program to extract the contents of the package (ar xv sysv-rc), then extract the contents of the resulting files. Somewhere in this mess you will find update-rc.d, which you should copy to /usr/sbin/. Now the normal debian package managers will probably work again.
Q. How do I install a System-V style init script ?
A. As root (through su, sudo, etc.) run:
$ update-rc.d script_name defaults
Q. How do I remove a System-V init script ?
A. First you most remove the original script in /etc/init.d. Then, to remove the links in /etc/rcrunlevel.d run (as root):
$ update-rc.d script_name remove
Q. What does the argument defaults do?
A. If defaults is used, update-rc.d will make links to start the service in runlevels 2345, and stop the service in runlevels 016.
Q. Are there any other arguments?
A. Yes, you can use the arguments start and stop, followed by NN (where NN are the desired runlevels) to specify which runlevels the script will start and stop in.
Q. Can you provide an example with the start and stop arguments?
A. To start the script folding in runlevels 0123 and stop in 456, run (as root):
$ update-rc.d folding start 0123 stop 456
update-rc.d is the Debian utility to install and remove System-V style init script links. Other distributions (such as Red Hat) use chkconfig. With update-rc.d, you can schedule tasks to be started when you boot your computer, for example the ssh service.
Q. I deleted update-rc.d, how can I get it back again?
A. Go here http://www.debian.org/distrib/packages and then choose the textbox to search for files in packages... easy if you know :-) Usually this package is called something like sysv-rc. Now download this package. Then comes the tricky part because without update-rc.d installing a package is not trivial. A chicken and egg problem. Use the ar program to extract the contents of the package (ar xv sysv-rc), then extract the contents of the resulting files. Somewhere in this mess you will find update-rc.d, which you should copy to /usr/sbin/. Now the normal debian package managers will probably work again.
Q. How do I install a System-V style init script ?
A. As root (through su, sudo, etc.) run:
$ update-rc.d script_name defaults
Q. How do I remove a System-V init script ?
A. First you most remove the original script in /etc/init.d. Then, to remove the links in /etc/rcrunlevel.d run (as root):
$ update-rc.d script_name remove
Q. What does the argument defaults do?
A. If defaults is used, update-rc.d will make links to start the service in runlevels 2345, and stop the service in runlevels 016.
Q. Are there any other arguments?
A. Yes, you can use the arguments start and stop, followed by NN (where NN are the desired runlevels) to specify which runlevels the script will start and stop in.
Q. Can you provide an example with the start and stop arguments?
A. To start the script folding in runlevels 0123 and stop in 456, run (as root):
$ update-rc.d folding start 0123 stop 456
unthu Server - Linux - UNIX Forum
There is no /etc/rc.conf under any Linux distribution as Linux uses sys v style
stuff. To turn on service on boot, enter: update-rc.d ssh defaultsOR Code: sudo update-rc.d ssh defaultsFollowing FAQ has more info: Debian or Ubuntu Linux runlevel configuration tool to start service |
Of course, in this post, I’m only gong to worry about Ubuntu runlevels. If you’re curious about the runlevels on other systems, there is a great page here dscribing the differences.
So, let’s look at the runlevels that affect Ubuntu. They are as follows:
0: Halt / Shut down. All processes are stopped, all filesystems are unmounted, and all users taken offline. Power can now be safely removed. 1: Single user mode. Only root allowed login (requires password). All filesystems listed in /etc/fstab are mounted. Limited set of services started. 2-5: Multi-user mode. All filesystems listed in /etc/fstab mounted, graphical environment (if installed) brought up. Full standard operational mode. 6: Reboot. As with runlevel 0, all processes stopped, all filesystems unmounted, all users taken offline, the box rebooted, and taken to the default runlevel.
Ubuntu does have one extra special runlevel that in processed before entering any of the regular runlevels above. It’s known as ’sulogin’, and it is considered an emergency mode if the system will not boot, or there are other troubles. it is denoted by “S” as it’s runlevel characterization. We will not worry about runlevel S in this post.
Each Unix and Linux operating system has a default runlevel in which it will boot into. If init is the daemon manager for your system, then you will find an /etc/inittab file that will specify your default runlevel. However, Ubuntu has replaced init with Upstart, an event-driven daemon manager. As such, there is no /etc/inittab file. However, there is an /etc/event.d/rc-default file, which as probably guessed, specifies your default runlevel. Let’s take a look at the file:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
aaron@kratos:~ 1346 % cat /etc/event.d/rc-default # rc - runlevel compatibility # # This task guesses what the "default runlevel" should be and starts the # appropriate script. start on stopped rcS script runlevel --reboot || true if grep -q -w -- "-s\|single\|S" /proc/cmdline; then telinit S elif [ -r /etc/inittab ]; then RL="$(sed -n -e "/^id:[0-9]*:initdefault:/{s/^id://;s/:.*//;p}" /etc/inittab || true)" if [ -n "$RL" ]; then telinit $RL else telinit 2 fi else telinit 2 fi end script |
Parsing through that file, we see that first, it tests to see if we are running in runlevel S, or ’sulogin’. If not, then we have a series of checks to find our default runlevel. The first check is to see if there is in fact an /etc/inittab file existing. If so, we look for the line that says “id:?:initdefault:”, where “?” could be any valid number 0 through 9. If that number exists, it is our default runlevel, otherwise, runlevel 2 will be our default, as none of the checks would pass.
So, as discovered, runlevel 2 is the default runlevel on Ubuntu. Furthermore, runlevels 2 through 5 are all exactly the same by default. Thus, entering runlevel 4 will have no effect on your box if already running in runlevel 2. What’s the point of having so many if they’re the same then? Well, a few reasons. First, if you followed that link above, showing the different runlevels on different systems, 0 through 6 is not uncommon, and many of the Unices and Linuxes take advantage of every one of them. So, I guess you could say they’re present for historical reasons. However, having that many runlevels gives the system administrator the flexibility to manage a specific runlevel at his/her convenience. For example, maybe runlevel 2 should be treated differently than 3 through 5, starting a different set of services than the rest. Maybe I don’t want runlevel 2 to start the graphical mode, but keep it text-based only. This could be useful in troubleshooting my graphical display without it running. You get the idea.
Ok, fine. The next question inevitably asked, is how can I tell what runlevel I’m currently in? Simple, just run the ‘runlevel’ command:
aaron@kratos:~ 1347 % runlevel N 2
“N” tells me that there was “None” for my previous runlevel. In other words, this box was just booted into my current runlevel, which I can see as the 2nd identifier, “2″. This is one thing that you may like or hate about the ‘runlevel’ command, but it only shows you your current runlevel and the previous runlevel. No more, no less. However, generally, this is sufficient.
As such, the next question you are probably asking yourself, is how do I change runlevels? This is done with the ‘telinit’ command. The command tells Upstart, our services manager, what services to stop and start when we enter a specific runlevel. For example, if I wanted to reboot my box from the command line, knowing that runlevel 6 is a reboot, I could enter, as root:
aaron@kratos:~ 1348 % sudo telinit 6 Password:
Ok. So, now we’ve learned what runlevels are, how to check my current running runlevel, and even how to change to a different runlevel. The next concept in this post is to see what runlevels are doing to the system under the hood. In other words, how does the system know that I want to knock everyone off the box except for root in runlevel 1? How does the system know to start the graphical display in runlevels 2 through 5? The answers to these questions lie in simple shell scripts.
Each runlevel has it’s own directory, which contains what we call “K-scripts” and “S-scripts”. These directories reside in /etc. In fact, let’s get back to our terminal, and type the following, noticing the output:
aaron@kratos:~ 1349 % ls -ld /etc/rc*/ drwxr-xr-x 2 root root 4096 2008-02-16 18:06 /etc/rc0.d/ drwxr-xr-x 2 root root 4096 2008-02-16 18:06 /etc/rc1.d/ drwxr-xr-x 2 root root 4096 2008-02-16 18:06 /etc/rc2.d/ drwxr-xr-x 2 root root 4096 2008-02-16 18:06 /etc/rc3.d/ drwxr-xr-x 2 root root 4096 2008-02-16 18:06 /etc/rc4.d/ drwxr-xr-x 2 root root 4096 2008-02-16 18:06 /etc/rc5.d/ drwxr-xr-x 2 root root 4096 2008-02-16 18:06 /etc/rc6.d/ drwxr-xr-x 2 root root 4096 2007-10-15 17:36 /etc/rcS.d/
That’s interesting. I have directories that have the same number as runlevels. Could this be a coincidence? Hardly. When I enter “telinit 4″ on the command line, for example, I’m telling Upstart to enter /etc/rc4.d, and execute the K-scripts and S-scripts found in that directory in a specific order. Same goes for entering “telinit 2″, “telinit 0″ or “telinit 6″. Every directory having a specific set of shell scripts that it’s going to execute. So, let’s dig into one of these directories. Let’s start with /etc/rc0.d/:
aaron@kratos:~ 1350 % ls /etc/rc0.d/ K01gdm K20postfix S15wpa-ifupdown K01usplash K25hwclock.sh S20sendsigs K16avahi-daemon K50alsa-utils S30urandom K16dhcdbd K59mountoverflowtmp S31umountnfs.sh K18consolekit K99laptop-mode S40umountfs K19sendmail README S60umountroot K20apport S01linux-restricted-modules-common S90halt
Here, I can see only 20 scripts and a README file listed. I notice further that I have my K-scripts and S-scripts that I’ve mentioned earlier. In fact, the K-scripts and S-scripts are numbered. This has to do with order in which to execute those scripts. Let’s look at them in detail. First, Upstart is going to execute the K-scripts then it will execute the S-scripts. K-scripts stop a service, while S-scripts start a service. So, the first script it will execute when it enters this directory is “K01gdm”. This script manages my graphical display. In other words, I’m going to kill my X session before doing anything else. Next, I’ll stop usplash followed my avahi-doemon, etc.
Once all the K-scripts are executed, then I execute the S-scripts. Just as with the K-scripts, they are also executed in order. So, the first script I start is “S01-linux-restricted-modules-common”. This script manages my restricted drivers for the kernel, returning nothing more than the exit code for /sbin/lrm-manager, and logging the result. Looking further, I have “S15wpa-ifupdown” which is managing my WPA helper library for wireless devices. We notice further that the last script executed in this directory is “S90halt”, which shuts the box down fully. Each of those scripts, as mentioned before, are just shell scripts, and can be opened with any text editor. If you’re curious about what a script is doing, open it up and read it.
Let’s look at runlevel 2 this time:
aaron@kratos:~ 1351 % ls /etc/rc2.d README S20hotkey-setup S30gdm S05vbesave S20makedev S50ntp S10acpid S20nvidia-kernel S89anacron S10powernowd.early S20postfix S89atd S10sysklogd S20powernowd S89cron S10xserver-xorg-input-wacom S20rsync S98usplash S11klogd S21sendmail S99acpi-support S12dbus S22consolekit S99laptop-mode S12hal S24avahi-daemon S99rc.local S19cupsys S24dhcdbd S99rmnologin S20apport S25bluetooth S99stop-readahead
First off, we may notice that there are no K-scripts in the runlevel 2 directory. In other words, we aren’t interested in stopping any services when we enter runlevel 2. Rather, we are only interested in starting services. Second, we may notice a logical order to the scripts. For example, we start power management right out the gate with S10acpid and S10powernowd.early. Next, we start S10sysklogd, which is our generic logging daemon for logging services. It makes sense to start this daemon before starting specific services, as if they fail to start, I will have a log as to the reason. Also notice that anacron is starting before cron (S89anacron to S89cron). This makes sense, as we want to run any cron jobs that weren’t run before running them again. The other daemons start in their numerical order as specified.
Looking in that directory is a bit deceptive, however. Although we see our K-scripts and S-scripts in each directory, they are actually not separate scripts. They are one script actually residing in /etc/init.d/. Let’s take a look:
aaron@kratos:~ 1352 % ls -l /etc/rc2.d total 4 -rw-r--r-- 1 root root 556 2007-10-04 05:17 README lrwxrwxrwx 1 root root 17 2008-01-09 00:45 S05vbesave -> ../init.d/vbesave lrwxrwxrwx 1 root root 15 2008-01-09 00:45 S10acpid -> ../init.d/acpid lrwxrwxrwx 1 root root 25 2008-01-09 00:45 S10powernowd.early -> ../init.d/powernowd.early lrwxrwxrwx 1 root root 18 2008-01-09 00:45 S10sysklogd -> ../init.d/sysklogd lrwxrwxrwx 1 root root 34 2008-01-09 00:45 S10xserver-xorg-input-wacom -> ../init.d/xserver-xorg-input-wacom lrwxrwxrwx 1 root root 15 2008-01-09 00:45 S11klogd -> ../init.d/klogd lrwxrwxrwx 1 root root 14 2008-01-09 00:45 S12dbus -> ../init.d/dbus lrwxrwxrwx 1 root root 13 2008-01-09 00:45 S12hal -> ../init.d/hal lrwxrwxrwx 1 root root 16 2008-01-09 00:45 S19cupsys -> ../init.d/cupsys lrwxrwxrwx 1 root root 16 2008-01-09 00:45 S20apport -> ../init.d/apport lrwxrwxrwx 1 root root 22 2008-01-09 00:45 S20hotkey-setup -> ../init.d/hotkey-setup lrwxrwxrwx 1 root root 17 2008-01-09 00:45 S20makedev -> ../init.d/makedev lrwxrwxrwx 1 root root 23 2008-01-09 00:45 S20nvidia-kernel -> ../init.d/nvidia-kernel lrwxrwxrwx 1 root root 17 2008-02-16 15:44 S20postfix -> ../init.d/postfix lrwxrwxrwx 1 root root 19 2008-01-09 00:45 S20powernowd -> ../init.d/powernowd lrwxrwxrwx 1 root root 15 2008-01-09 00:45 S20rsync -> ../init.d/rsync lrwxrwxrwx 1 root root 18 2008-02-16 18:06 S21sendmail -> ../init.d/sendmail lrwxrwxrwx 1 root root 20 2008-01-09 00:45 S22consolekit -> ../init.d/consolekit lrwxrwxrwx 1 root root 22 2008-01-09 00:45 S24avahi-daemon -> ../init.d/avahi-daemon lrwxrwxrwx 1 root root 16 2008-01-09 00:45 S24dhcdbd -> ../init.d/dhcdbd lrwxrwxrwx 1 root root 19 2008-01-09 00:45 S25bluetooth -> ../init.d/bluetooth lrwxrwxrwx 1 root root 13 2008-01-09 00:45 S30gdm -> ../init.d/gdm lrwxrwxrwx 1 root root 13 2008-01-12 13:41 S50ntp -> ../init.d/ntp lrwxrwxrwx 1 root root 17 2008-01-09 00:45 S89anacron -> ../init.d/anacron lrwxrwxrwx 1 root root 13 2008-01-09 00:45 S89atd -> ../init.d/atd lrwxrwxrwx 1 root root 14 2008-01-09 00:45 S89cron -> ../init.d/cron lrwxrwxrwx 1 root root 17 2008-01-09 00:45 S98usplash -> ../init.d/usplash lrwxrwxrwx 1 root root 22 2008-01-09 00:45 S99acpi-support -> ../init.d/acpi-support lrwxrwxrwx 1 root root 21 2008-01-09 00:45 S99laptop-mode -> ../init.d/laptop-mode lrwxrwxrwx 1 root root 18 2008-01-09 00:45 S99rc.local -> ../init.d/rc.local lrwxrwxrwx 1 root root 19 2008-01-09 00:45 S99rmnologin -> ../init.d/rmnologin lrwxrwxrwx 1 root root 24 2008-01-09 00:45 S99stop-readahead -> ../init.d/stop-readahead
Ahh. We can see that each script in the /etc/rc2.d/ directory is actually a soft link pointing to a script of the same name in the /etc/init.d/ directory. This is consistent with /etc/rc[0-6].d/ directories as well. Every file in those directories just pointing to a single script residing in /etc/init.d/. This makes it easy to manage runlevels, as I’m sure you could guess. Because there is only one script, I can create symbolic links in each runlevel directory to start and stop that specific service. As mentioned before, if it’s a K-script, it will stop the service in /etc/init.d/, if it’s an S-script, it will start the service in /etc/init.d/. This would be the same as calling the script directly:
aaron@kratos:~ 1353 % sudo /etc/init.d/sendmail start Password: * Starting Mail Transport Agent (MTA) sendmail [ OK ]
The above is exactly the same as S21sendmail in the /etc/rc2.d/ directory. In fact, if you call the script directly, with no arguments, you can see that it contains a list of valid options, where start and stop are the only requirements:
aaron@kratos:~ 1354 % sudo /etc/init.d/sendmail Password: Invalid command <> Usage: /etc/init.d/sendmail <command> Where <command> is one of the following start|stop|restart|restart-if-running reload-if-running|reload|force-reload newaliases|hoststat|purgestat|mailstats|mailq|runq|control status|debug|clean
As we can see, the sendmail script has start, stop, restart, restart-if-running, reload-if-running, reload, force-reload, newaliases, hoststat, purgestat, mailstats, mailq, runq, control, status, debug and clean as valid arguments. However, we’ll talk more about the /etc/init.d/ directory in the next post in this series. For now, suffice it to say that the /etc/init.d/ directory contains all my shell scripts that a bunch of soft links point to from /etc/rc[0-6].d/. Specifying a runlevel to enter just means to either call the /etc/init.d/ script with a start option, or with a stop option, pending on whether or not it is an S-script or K-script respectively.
This is a good stopping point before continuing on to the next part of the series: Controlling Runlevels. Hopefully now, you understand the different runlevels, how to enter a runlevel, and what a specific runlevel is doing to your box. We looked at the various commands for identifying what runlevel the box is running in and how to change runlevels. We looked at some shell scripts, seeing what arguments are available when calling a daemon directly, and we found out how to tell what our default runlevel is. In other words, you should be fairly fluent on identifying runlevels now.
For the second post in this series, we’ll talk about how to manage those runlevels, giving us the flexibility to control exactly what is started and stopped when I enter a specific runlevel. We’ll pretty much be spending our entire time on one command, running through lots of examples.
I now have some homework for you to familiarize yourself with the concept of runlevels:
1) Spend some time looking through the various /etc/rc[0-6].d/ directories, identifying K-scripts and S-scripts. Do not make any changes or modify any files. 2) Open up and read the shell scripts found in those directories, and see if you can figure out what is happening with each daemon when that script stops or starts the service. 3) Spend some time changing runlevels with the 'telinit' command, and see how it affects your box. 4) Change your default runlevel by changing the /etc/event.d/rc-default file (MAKE A BACKUP BEFORE CHANGING THE FILE). Reboot your box, to see if it worked. 5) If you have access to a Fedora or Red Hat-based distribution, see how the runlevels differ, and see if you can do the previous 4 steps with that distro as well.
Society
Groupthink : Two Party System as Polyarchy : Corruption of Regulators : Bureaucracies : Understanding Micromanagers and Control Freaks : Toxic Managers : Harvard Mafia : Diplomatic Communication : Surviving a Bad Performance Review : Insufficient Retirement Funds as Immanent Problem of Neoliberal Regime : PseudoScience : Who Rules America : Neoliberalism : The Iron Law of Oligarchy : Libertarian Philosophy
Quotes
War and Peace : Skeptical Finance : John Kenneth Galbraith :Talleyrand : Oscar Wilde : Otto Von Bismarck : Keynes : George Carlin : Skeptics : Propaganda : SE quotes : Language Design and Programming Quotes : Random IT-related quotes : Somerset Maugham : Marcus Aurelius : Kurt Vonnegut : Eric Hoffer : Winston Churchill : Napoleon Bonaparte : Ambrose Bierce : Bernard Shaw : Mark Twain Quotes
Bulletin:
Vol 25, No.12 (December, 2013) Rational Fools vs. Efficient Crooks The efficient markets hypothesis : Political Skeptic Bulletin, 2013 : Unemployment Bulletin, 2010 : Vol 23, No.10 (October, 2011) An observation about corporate security departments : Slightly Skeptical Euromaydan Chronicles, June 2014 : Greenspan legacy bulletin, 2008 : Vol 25, No.10 (October, 2013) Cryptolocker Trojan (Win32/Crilock.A) : Vol 25, No.08 (August, 2013) Cloud providers as intelligence collection hubs : Financial Humor Bulletin, 2010 : Inequality Bulletin, 2009 : Financial Humor Bulletin, 2008 : Copyleft Problems Bulletin, 2004 : Financial Humor Bulletin, 2011 : Energy Bulletin, 2010 : Malware Protection Bulletin, 2010 : Vol 26, No.1 (January, 2013) Object-Oriented Cult : Political Skeptic Bulletin, 2011 : Vol 23, No.11 (November, 2011) Softpanorama classification of sysadmin horror stories : Vol 25, No.05 (May, 2013) Corporate bullshit as a communication method : Vol 25, No.06 (June, 2013) A Note on the Relationship of Brooks Law and Conway Law
History:
Fifty glorious years (1950-2000): the triumph of the US computer engineering : Donald Knuth : TAoCP and its Influence of Computer Science : Richard Stallman : Linus Torvalds : Larry Wall : John K. Ousterhout : CTSS : Multix OS Unix History : Unix shell history : VI editor : History of pipes concept : Solaris : MS DOS : Programming Languages History : PL/1 : Simula 67 : C : History of GCC development : Scripting Languages : Perl history : OS History : Mail : DNS : SSH : CPU Instruction Sets : SPARC systems 1987-2006 : Norton Commander : Norton Utilities : Norton Ghost : Frontpage history : Malware Defense History : GNU Screen : OSS early history
Classic books:
The Peter Principle : Parkinson Law : 1984 : The Mythical Man-Month : How to Solve It by George Polya : The Art of Computer Programming : The Elements of Programming Style : The Unix Hater’s Handbook : The Jargon file : The True Believer : Programming Pearls : The Good Soldier Svejk : The Power Elite
Most popular humor pages:
Manifest of the Softpanorama IT Slacker Society : Ten Commandments of the IT Slackers Society : Computer Humor Collection : BSD Logo Story : The Cuckoo's Egg : IT Slang : C++ Humor : ARE YOU A BBS ADDICT? : The Perl Purity Test : Object oriented programmers of all nations : Financial Humor : Financial Humor Bulletin, 2008 : Financial Humor Bulletin, 2010 : The Most Comprehensive Collection of Editor-related Humor : Programming Language Humor : Goldman Sachs related humor : Greenspan humor : C Humor : Scripting Humor : Real Programmers Humor : Web Humor : GPL-related Humor : OFM Humor : Politically Incorrect Humor : IDS Humor : "Linux Sucks" Humor : Russian Musical Humor : Best Russian Programmer Humor : Microsoft plans to buy Catholic Church : Richard Stallman Related Humor : Admin Humor : Perl-related Humor : Linus Torvalds Related humor : PseudoScience Related Humor : Networking Humor : Shell Humor : Financial Humor Bulletin, 2011 : Financial Humor Bulletin, 2012 : Financial Humor Bulletin, 2013 : Java Humor : Software Engineering Humor : Sun Solaris Related Humor : Education Humor : IBM Humor : Assembler-related Humor : VIM Humor : Computer Viruses Humor : Bright tomorrow is rescheduled to a day after tomorrow : Classic Computer Humor
The Last but not Least Technology is dominated by two types of people: those who understand what they do not manage and those who manage what they do not understand ~Archibald Putt. Ph.D
Copyright © 1996-2021 by Softpanorama Society. www.softpanorama.org was initially created as a service to the (now defunct) UN Sustainable Development Networking Programme (SDNP) without any remuneration. This document is an industrial compilation designed and created exclusively for educational use and is distributed under the Softpanorama Content License. Original materials copyright belong to respective owners. Quotes are made for educational purposes only in compliance with the fair use doctrine.
FAIR USE NOTICE This site contains copyrighted material the use of which has not always been specifically authorized by the copyright owner. We are making such material available to advance understanding of computer science, IT technology, economic, scientific, and social issues. We believe this constitutes a 'fair use' of any such copyrighted material as provided by section 107 of the US Copyright Law according to which such material can be distributed without profit exclusively for research and educational purposes.
This is a Spartan WHYFF (We Help You For Free) site written by people for whom English is not a native language. Grammar and spelling errors should be expected. The site contain some broken links as it develops like a living tree...
|
You can use PayPal to to buy a cup of coffee for authors of this site |
Disclaimer:
The statements, views and opinions presented on this web page are those of the author (or referenced source) and are not endorsed by, nor do they necessarily reflect, the opinions of the Softpanorama society. We do not warrant the correctness of the information provided or its fitness for any purpose. The site uses AdSense so you need to be aware of Google privacy policy. You you do not want to be tracked by Google please disable Javascript for this site. This site is perfectly usable without Javascript.
Last modified: March, 12, 2019