Purchase | Copyright © 2002 Paul Sheer. Click here for copying permissions. | Home |
uucp is a command to copy a file from one UNIX system to another. uux executes a command on another UNIX system, even if that command is receiving data through stdin on the local system. uux is extremely useful for automating many kinds of distributed functions, like mail and news.
The uucp and uux commands both come as part of the uucp (Unix-to-Unix Copy) package. uucp may sound ridiculous considering the availability of modern commands like rcp, rsh, or even FTP transfers (which accomplish the same thing), but uucp has features that these do not, making it an essential, albeit antiquated, utility. For instance, uucp never executes jobs immediately. It will, for example, queue a file copy for later processing and then dial the remote machine during the night to complete the operation.
uucp predates the Internet: It was originally used to implement a mail system, using only modems and telephone lines. It hence has sophisticated protocols for ensuring that your file/command really does get there, with the maximum possible fault tolerance and the minimum of retransmission. This is why it should always be used for automated tasks wherever there are unreliable (i.e., modem) connections. The uucp version that comes with most LINUX distributions is called Taylor UUCP after its author.
Especially important is that when a uucp operation is interrupted by a line break, the connection time is not wasted: uucp will not have discarded any partially transmitted data. This means that no matter how slow or error prone the connection, progress is always made. Compare this to an SMTP or POP3/IMAP connection: Any line break halfway through a large mail message will necessitate that the entire operation to be restarted from scratch.
To copy a file from one machine to another, simply enter
|
uucp <filename> <machine>!<path> |
You can also run commands on the remote system, like
|
echo -n 'Hi, this is a short message\n\n-paul' | \ uux - 'cericon!rmail' 'john' |
which runs rmail on the remote system cericon, feeding some text to the rmail program. Note how you should quote the ! character to prevent it from being interpreted by the shell. (These commands will almost always fail with permission denied by remote. The error will come in a mail message to the user that ran the command.)
uucp comes with comprehensive documentation in HTML format ( /usr/doc/uucp-version /uucp.html or /usr/share/...) on RedHat, and info format on Debian and RedHat. Here, I sketch a basic and typical configuration.
The uucp package has a long history of revisions, beginning with the first modem-based mail networks. The latest GNU editions that come with LINUX distributions have a configuration file format that will probably differ from that which old uucp hands are used to.
Dialup networks today typically use uucp in combination with normal PPP dialup, probably not using uucp's dial-in facilities at all. For example, if you are deploying a number of remote hosts that are using modems, these hosts should always use uucp to upload and retrieve mail, rather than POP3/IMAP or straight SMTP, because of the retransmission problem discussed above. In other words, uucp is really working as an ordinary TCP service, albeit with far more fault tolerance.
To make uucp into a TCP server, place it into /etc/inetd.conf as follows
|
uucp stream tcp nowait uucp /usr/sbin/tcpd /usr/lib/uucp/uucico -l |
being also very careful to limit the hosts that can connect by using the techniques discussed in Chapter 29. Similarly for xinetd, create a file /etc/xinetd.d/uucp containing,
5 10 |
service uucp { only_from = 127.0.0.1 192.168.0.0/16 socket_type = stream wait = no user = uucp server = /usr/lib/uucp/uucico server_args = -l disable = no } |
uucp configuration files are stored under /etc/uucp/. Now we configure a client machine, machine1.cranzgot.co.za, to send mail through server1.cranzgot.co.za, where server1.cranzgot.co.za is running the uucico service above.
uucp has an antiquated authentication mechanism that uses its own list of users and passwords completely distinct from those of ordinary UNIX accounts. We must first add a common ``user'' and password to both machines for authentication purposes. For machine1.cranzgot.co.za, we can add to the file /etc/uucp/call the line
|
server1 machine1login pAsSwOrD123 |
which tells uucp to use the login machine1login whenever trying to speak to server1. On server1.cranzgot.co.za we can add to the file /etc/uucp/passwd the line,
|
machine1login pAsSwOrD123 |
Note that the uucp name server1 was chosen for the machine server1.cranzgot.co.za for convenience. uucp names, however, have nothing to do with domain names.
Next, we need to tell uucp about the intentions of machine1. Any machine that you might connect to or from must be listed in the /etc/uucp/sys file. Our entry looks like
5 |
system machine1 call-login * call-password * commands rmail protocol t |
and can have as many entries as we like. The only things server1 has to know about machine1 are the user and password and the preferred protocol. The *'s mean to look up the user and password in the /etc/uucp/passwd file, and protocol t means to use a simple non-error, correcting protocol (as appropriate for use over TCP). The commands option takes a space-separated list of permitted commands--for security reasons, commands not in this list cannot be executed. (This is why I stated above that commands will almost always fail with permission denied by remote--they are usually not listed under commands.)
The /etc/uucp/sys file on machine1 will contain:
5 |
system server1 call-login * call-password * time any port TCP address 192.168.3.2 protocol t |
Here time any specifies which times of the day uucp may make calls to server1. The default is time Never. [See the uucp documentation under Time Strings for more info.] The option port TCP means that we are using a modem named TCP to execute the dialout. All modems are defined in the file /etc/uucp/port. We can add our modem entry to /etc/uucp/port as follows,
|
port TCP type tcp |
which clearly is not really a modem at all.
Finally, we can queue a mail transfer job with
|
echo -e 'Hi Jack\n\nHow are you?\n\n-jill" | \ uux - --nouucico 'server1!rmail' 'jack@beanstalk.com' |
and copy a file with
|
uucp --nouucico README 'cericon!/var/spool/uucppublic' |
Note that /var/spool/uucppublic/ is the only directory you are allowed access to by default. You should probably keep it this way for security.
Although we have queued a job for processing, nothing will transfer until the program uucico (which stands for Unix-to-Unix copy in copy out) is run. The idea is that both server1 and machine1 may have queued a number of jobs; then when uucico is running on both machines and talking to each other, all jobs on both machines are processed in turn, regardless of which machine initiated the connection.
Usually uucico is run from a crond script every hour. (Even having run uucico, nothing will transfer if the time of day does not come within the ranges specified under time ....) Here we can run tail -f /var/log/uucp/Log while running uucico manually as follows:
|
uucico --debug 3 --force --system server1 |
The higher the debug level, the more verbose output you will see in the Log file. This will --forceably dial the --system server1 regardless of when it last dialed (usually there are constraints on calling soon after a failed call: --force overrides this).
If your mail server on server1 is configured correctly, it should now have queued the message on the remote side.
If you are really going to use uucp the old-fashioned way, you can use mgetty to answer uucp calls on server1 by adding the following to your /etc/inittab file:
|
S0:2345:respawn:/sbin/mgetty -s 57600 ttyS0 |
And then add the line
|
machine1login uucp machine1login /usr/sbin/uucico -l -u machine1login |
to the file /etc/mgetty+sendfax/login.config ( /etc/mgetty/login.config for Debian). You will then also have to add a UNIX account machine1login with password pAsSwOrD123. This approach works is because mgetty and uucico have the same login prompt and password prompt, but mgetty uses /etc/passwd instead of /etc/uucp/passwd to authenticate. Also, for a modem connection, protocol t is error prone: change it to protocol g, which has small packet sizes and error correction.
Note that the above configuration also supports faxes, logins, voice, and PPP (see Section 41.4) on the same modem, because mgetty only starts uucico if the user name is machine1login.
To dial out from machine1, you first need to add a modem device (besides TCP) to your /etc/uucp/port file:
5 |
port ACU type modem device /dev/ttyS0 dialer mymodem speed 57600 |
ACU is antiquated terminology and stands for Automatic Calling Unit (i.e., a modem). We have to specify the usual types of things for serial ports, like the device ( /dev/ttyS0 for a modem on COM1) and speed of the serial line. We also must specify a means to initialize the modem: the dialer mymodem option. A file /etc/uucp/dial should then contain an entry for our type of modem matching `` mymodem'' as follows: [This example assumes that an initialization string of AT&F1 is sufficient. See Section 3.5.]
5 10 |
dialer mymodem chat "" AT&F1\r\d\c OK\r ATDT\D CONNECT chat-fail RING chat-fail NO\sCARRIER chat-fail ERROR chat-fail NO\sDIALTONE chat-fail BUSY chat-fail NO\sANSWER chat-fail VOICE complete \d\d+++\d\dATH\r\c abort \d\d+++\d\dATH\r\c |
More about modems and dialing is covered with pppd in Chapter 41.
With the modem properly specified, we can change our entry in the sys file to
5 |
system server1 call-login * call-password * time any port ACU phone 555-6789 protocol g |
The same uux commands should now work over dialup.
I hinted about lock files in Section 33.2. A more detailed explanation follows.
You will have noticed by now that several services use serial devices, and many of them can use the same device at different times. This creates a possible conflict should two services wish to use the same device at the same time. For instance, what if someone wants to send a fax, while another person is dialing in?
The solution is the UUCP lock file. This is a file created by a process in /var/lock/ of the form LCK..device that indicates the serial port is being used by that process. For instance, when running sendfax through a modem connected on /dev/ttyS0, a file /var/lock/LCK..ttyS0 suddenly appears. This is because sendfax, along with all other mgetty programs, obeys the UUCP lock file convention. The contents of this file actually contain the process ID of the program using the serial device, so it is easy to check whether the lock file is bogus. A lock file of such a dead process is called a stale lock file and can be removed manually.
uucp implementations rarely run smoothly the first time. Fortunately, you have available a variety of verbose debugging options. uucico takes the --debug option to specify the level of debug output. You should examine the files /var/log/uucp/Log, /var/log/uucp/Debug, and /var/log/uucp/Stats to get an idea about what is going on in the background. Also important is the spool directory /var/spool/uucp/. You can specify the debugging level with --debug level where level is in the range of 0 through 11. You can also use --debug chat to only see modem communication details. A full description of other options follows [Credits to the uucp documentation.]:
On machine1 we would like exim to spool all mail through uucp. Using uucp requires a pipe transport ( exim transports are discussed in Section 30.3.2). exim merely sends mail through stdin of the uux command and then forgets about it. uux is then responsible for executing rmail on server1. The complete exim.conf file is simply as follows.
5 10 15 20 25 30 35 40 |
#################### MAIN CONFIGURATION SETTINGS ##################### log_subject errors_address = admin local_domains = localhost : ${primary_hostname} : machine1 : \ machine1.cranzgot.co.za host_accept_relay = 127.0.0.1 : localhost : ${primary_hostname} : \ machine1 : machine1.cranzgot.co.za never_users = root exim_user = mail exim_group = mail end ###################### TRANSPORTS CONFIGURATION ###################### uucp: driver = pipe user = nobody command = "/usr/bin/uux - --nouucico ${host}!rmail \ ${local_part}@${domain}" return_fail_output = true local_delivery: driver = appendfile file = /var/spool/mail/${local_part} delivery_date_add envelope_to_add return_path_add group = mail mode_fail_narrower = mode = 0660 end ###################### DIRECTORS CONFIGURATION ####################### localuser: driver = localuser transport = local_delivery end ###################### ROUTERS CONFIGURATION ######################### touucp: driver = domainlist route_list = "* server1" transport = uucp end ###################### RETRY CONFIGURATION ########################### * * F,2m,1m end |
On machine server1, exim must however be running as a full-blown mail server to properly route the mail elsewhere. Of course, on server1, rmail is the sender; hence, it appears to exim that the mail is coming from the local machine. This means that no extra configuration is required to support mail coming from a uux command.
Note that you can add further domains to your route_list so that your dialouts occur directly to the recipient's machine. For instance:
5 |
route_list = "machine2.cranzgot.co.za machine2 ; \ machine2 machine2 ; \ machine3.cranzgot.co.za machine3 ; \ machine3 machine3 ; \ * server1" |
You can then add further entries to your /etc/uucp/sys file as follows:
5 10 15 |
system machine2 call-login * call-password * time any port ACU phone 555-6789 protocol g system machine3 call-login * call-password * time any port ACU phone 554-3210 protocol g |
The exim.conf file on server1 must also have a router to get mail back to machine1. The router will look like this:
5 10 |
###################### ROUTERS CONFIGURATION ######################### touucp: driver = domainlist route_list = "machine2.cranzgot.co.za machine2 ; \ machine2 machine2 ; \ machine3.cranzgot.co.za machine3 ; \ machine3 machine3" transport = uucp lookuphost: driver = lookuphost transport = remote_smtp end |
This router sends all mail matching our dial-in hosts through the uucp transport while all other mail (destined for the Internet) falls through to the lookuphost router.
Above, we used uucico only manually. uucico does not operate as a daemon process on its own and must be invoked by crond. All systems that use uucp have a /etc/crontab entry or a script under /etc/cron.hourly.
A typical /etc/crontab for machine1 might contain:
|
45 * * * * uucp /usr/lib/uucp/uucico --master 40 8,13,18 * * * root /usr/bin/uux -r server1! |
The option --master tells uucico to loop through all pending jobs and call any machines for which jobs are queued. It does this every hour. The second line queues a null command three times daily for the machine server1. This will force uucico to dial out to server1 at least three times a day on the appearance of real work to be done. The point of this to pick up any jobs coming the other way. This process is known as creating a poll file.
Clearly, you can use uucp over a TCP link initiated by pppd. If a dial link is running in demand mode, a uucp call will trigger a dialout and make a straight TCP connection through to the remote host. A common situation occurs when a number of satellite systems are dialing an ISP that has no uucp facility. To service the satellite machines, a separate uucp server is deployed that has no modems of its own. The server will have a permanent Internet connection and listen on TCP for uucp transfers.