chip@chinacat.unicom.com (Chip Rosenthal) (06/12/91)
I've now received about two dozen requests for this, so I figure it would be best to post. The following package implements `uucp' over TCP/IP. It is useful for systems which do not provide this capability. There are two general methods for this: TLI uucp and Berkeley uucpd. This supports the second method. This package has been tested with SCO XENIX (TCP 1.0) and SCO UNIX (TCP 1.1). I'll gladly accept bug reports/fixes/hacks. #! /bin/sh # this is a "shar" archive - run through "/bin/sh" to extract 4 files: # README uucpm.c uucpd.c Makefile # Wrapped by chip@chinacat on Tue Jun 11 12:45:53 CDT 1991 # Unpacking this archive requires: sed test wc (possibly mkdir) # Existing files will not be clobbered unless "-c" is specified on the cmd line. if test -f README -a "$1" != "-c" ; then echo "README: file exists - will not be overwritten" else echo "x - README (file 1 of 4, 5277 chars)" sed -e 's/^X//' << 'END_OF_FILE_README' > README X X *** uucp over SCO UNIX/XENIX TCP/IP *** X XSUMMARY X X This package provides two daemon to allow Berkeley-style uucp X transfers over TCP/IP for SCO UNIX and SCO XENIX systems. The X `uucpd' daemon is a BSD UNIX program (version 5.9 6/1/90), ported X to SCO. It implements the slave (i.e. responding) end of the X transfer. The `uucpm' daemon was written specifically for this X package. It implements the master (i.e. initiating) end of the X transfer. X XINSTALLATION X X - Edit the site-specific customizations at the top of the `Makefile'. X X - Run `make'. X X - Install the `uucpd' and `uucpm' binaries. I place them in a X directory called `/etc/local'. They may reside anywhere, but X the rest of these directions assume that's where they are. X X - Add a line to `/etc/inetd.conf' which says: X X uucp stream tcp nowait root /etc/local/uucpd uucpd X X Yes, `uucpd' does need to run as root. X X - Decide how many outgoing TCP/IP connections you want to support, X and which pty(s) you wish to allocate to them. Myself, I only X support a single connection, and allocate the /dev/[pt]typ7 X pair. The rest of these notes assume that configuration. X X - Add the commands to start the `uucpm' daemon. You could put them X into `/etc/tcp' but I prefer not to since the `mkdev tcp' will X trounce that script if you rerun it. I add the command: X X /etc/local/uucpm /dev/ptyp7 X X to an appropriate /etc/rc.d (XENIX) or /etc/rc2.d (UNIX) file. X If you want to support multiple sessions, you will need to start X a `uucpm' daemon upon each of the pty's selected. X X - Declare the pty device(s) available for uucp. This may be done with X an entry in your /usr/lib/uucp/Devices file such as: X X TCPIP ttyp7 - 19200 direct X X Note that `uucpm' was started on the master end of the pty X (ptyp7), but here we give the slave end (ttyp7). If you are X supporting multiple sessions, provide similar entries for all X of the pty's. X X - Finally, enter the /usr/lib/uucp/Systems information for machines X on the network: X X coldsnap Any TCPIP Any - "" coldsnap gin: NAME word: PASSWORD X ^^^^^^^^^^^ X X The highlighted portion of the chat script is where the connection X to the remote machine is established. All you need to do is X send out the machine name, and the `uucpm' daemon will establish X a socket to the specified machine. If there is no password on X the account, `uucpd' will not prompt for one, and thus it may X be left off. Also note that for security reasons, `uucpd' X insists that the login shell is `/usr/lib/uucp/uucico'. X X - You are now ready to roll. Remember - to test this stuff out X you will need to either: (1) `kill -1' the init process and X manually start the `uucpm' daemon, or (2) reboot the system. X `uucpm' has an undocumented `-D' switch to run in a debugging X (non-daemon) mode. X X XTHEORY OF OPERATION - SLAVE SIDE X X When a connection is established upon port 540, the `well known X port' for uucp, the `inetd' superserver starts up the `uucpd' X program. This program prompts for and receives (through the X network) the username and password for a uucp login. It does the X loginish things, like setup an environment and make /etc/wtmp X entries. Then, it forks off a child to run `uucico' for the remote X system. When `uucico' terminates `uucpd' cleans up (i.e. makes X the logout entry into /etc/wtmp, shuts down the socket, etc.) and X terminates. X X XTHEORY OF OPERATION - MASTER SIDE X X The `uucpm' daemon sits upon the master end of a pty, waiting for X an incoming request. When `uucico' attempts a connection to a X networked system, it selects one of the TCPIP devices - the slave X end of the pty. `uucpm' reads one CR delimited line - the name X of the remote system. The chat script shown above starts with an X `expect nothing/send system name' sequence, which provides `uucpm' X the information it requires. `uucpm' then attempts to establish X a socket to port 540 on the named system, and if successful just X passes data between the pty and the socket. When either the socket X shuts down (i.e. the remote slave uucico finishes) or the pty X shuts down (i.e. the local master uucico finishes), `uucpm' closes X up everything and reopens the pty awaiting another request. X X XWISHLIST X X I am particularly unhappy with the way `uucpd' handles the /etc/wtmp X file. I think it could record more useful information. It's also X crummy that you always get a logout entry made - even if the login X wasn't successful. Unfortunately - this is extremely difficult X to fix and still maintain compatibility with the non-inetd form X of `uucpd'. I'm tempted to rip that out and fix the wtmp stuff. X X If somebody wanted to get fancy, it is theoretically possible to X do a version of `uucpm' run as an SCO binary dialer. That would X avoid having to have a daemon laying around. I'm not sure it's X is worth it - it's certainly of no use on non-SCO systems. X X XChip Rosenthal X<chip@chinacat.unicom.com> XUnicom Systems Development, Inc. X X@(#) README 1.1 91/06/07 01:27:43 X END_OF_FILE_README size="`wc -c < README`" if test 5277 -ne "$size" ; then echo "README: extraction error - got $size chars" fi fi if test -f uucpm.c -a "$1" != "-c" ; then echo "uucpm.c: file exists - will not be overwritten" else echo "x - uucpm.c (file 2 of 4, 7915 chars)" sed -e 's/^X//' << 'END_OF_FILE_uucpm.c' > uucpm.c X/* X * uucpm - daemon to run master uucico process over TCP/IP network X * X * Chip Rosenthal <chip@chinacat.unicom.com> X * Unicom Systems Development, Inc. X * X * This program detatches itself to become a daemon, and then runs through X * an infinite loop - one iteration per uucico invocation. At the top of X * the loop, it opens the master end of a pty. When a uucico process opens X * the slave end, this program reads in the name of the target machine, X * establishes a socket to "uucpd" on that machine, and then passes data X * between the socket and pty. When EOF is reached upon either the socket X * or the pty, both are shutdown, and the pty is reopened to await another X * uucico invocation. X */ X X#ifndef lint Xstatic char SCCSID[] = "@(#) uucpm.c 1.2 91/06/11 12:45:16"; X#endif X X#include <sys/types.h> X#include <sys/socket.h> X#include <netinet/in.h> X#include <netdb.h> X#include <syslog.h> X#include <signal.h> X#include <stdio.h> X#include <fcntl.h> X X#define USAGE "usage: %s master_pty\n" X Xextern int errno; Xextern char *sys_errlist[]; X#define errmssg sys_errlist[errno] X X#define Dprintf if ( !Debug ) ; else fprintf Xint Debug = 0; X Xsigcatcher(sig) Xint sig; X{ X syslog(LOG_INFO, "caught signal %d - terminating", sig); X exit(0); X} X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X int sfd, pfd, numfd, n; X char host[64], buf[512], *ptypath; X struct sockaddr_in sin; X struct servent *sp; X struct hostent *hp; X fd_set fdset; X X /* X * Crack command line. X */ X if ( argc == 2 ) { X ptypath = argv[1]; X } else if ( argc == 3 && strcmp(argv[1], "-D") == 0 ) { X ++Debug; X ptypath = argv[2]; X } else { X fprintf(stderr, USAGE, argv[0]); X exit(1); X } X X /* X * Verify the pty exists. X */ X if ( access(ptypath, 06) != 0 ) { X fprintf(stderr, "%s: can't access '%s' [%s]\n", X argv[0], ptypath, errmssg); X exit(1); X } X X openlog("uucpm", LOG_PID|LOG_CONS, LOG_DAEMON); X X /* X * Setup as daemon. X */ X if ( !Debug ) { X X /* X * Fork off child process. X */ X switch ( fork() ) { X case -1: syslog(LOG_ERR, "fork failed [%s]", errmssg); exit(1); X case 0: break; X default: exit(0); X } X X /* X * Detatch from controlling terminal. X */ X if ( setpgrp() < 0 ) { X syslog(LOG_ERR, "process group detatch failed [%s]", errmssg); X exit(1); X } X for ( n = 1 ; n <= NSIG ; ++n ) { X switch ( n ) { X case SIGHUP: (void) signal(n, SIG_IGN); break; X case SIGCLD: (void) signal(n, SIG_DFL); break; X default: (void) signal(n, sigcatcher); break; X } X } X (void) close(0); X (void) close(1); X (void) close(2); X (void) chdir("/"); X (void) umask(0); X X /* X * Fork again so we become owned by init. X */ X switch ( fork() ) { X case -1: syslog(LOG_ERR, "fork failed [%s]", errmssg); exit(1); X case 0: break; X default: exit(0); X } X X } X X /* X * Once through loop per uucp connection request. X */ X syslog(LOG_INFO, "daemon running on '%s'", ptypath); X sfd = pfd = -1; X for (;;) { X X /* X * Shutdown any fd's open from last time. Pause when shutting down X * pty to allow uucico to close down and release the slave end. The X * sleep is ugly, but the alternatives (I can think of) are even X * uglier (e.g. find the PID which has it locked and busy wait until X * that PID terminates). X */ X if ( sfd >= 0 ) { X (void) close(sfd); X sfd = -1; X } X if ( pfd >= 0 ) { X (void) close(pfd); X pfd = -1; X sleep(5); X } X X /* X * Open up the master side of the pty. X */ X if ( (pfd=open(ptypath, O_RDWR)) < 0 ) { X syslog(LOG_ERR, "open '%s' failed [%s]", ptypath, errmssg); X exit(1); X } X X /* X * Block until the slave side is opened, i.e. the pty is writeable. X */ X Dprintf(stderr, "opened pty '%s' - blocking for slave\n", ptypath); X FD_ZERO(&fdset); X FD_SET(pfd, &fdset); X if ( select(pfd+1, (fd_set *)0, &fdset, (fd_set *)0, X (struct timeval *)0) < 0 || !FD_ISSET(pfd, &fdset) ) { X syslog(LOG_ERR, "select failed [%s]", errmssg); X continue; X } X X /* X * Read in the host name. X */ X Dprintf(stderr, "slave active - waiting for uucp request\n"); X if ( rdline(pfd, host, sizeof(host)) < 0 ) { X syslog(LOG_ERR, "host name read on '%s' failed [%s]", X ptypath, errmssg); X continue; X } X X /* X * Get the host and service information. X */ X if ( (hp=gethostbyname(host)) == NULL ) { X syslog(LOG_ERR, "host '%s' lookup failed", host); X sprintf(buf, "error - unknown host '%s'\n", host); X (void) wrbuf(pfd, "pty", buf, strlen(buf)); X continue; X } X if ( (sp=getservbyname("uucp", "tcp")) == NULL ) { X syslog(LOG_ERR, "service 'uucp/tcp' lookup failed"); X exit(1); X } X Dprintf(stderr, "attempting connection - host %s, addr %s, port %d\n", X host, X inet_ntoa(*((struct in_addr *)hp->h_addr)), X ntohs(sp->s_port) X ); X X /* X * Setup the socket to "uucpd" on the slave system. X */ X bzero((char *)&sin, sizeof(sin)); X bcopy(hp->h_addr, (char*)&sin.sin_addr , hp->h_length); X sin.sin_family = hp->h_addrtype; X sin.sin_port = sp->s_port; X if ( (sfd=socket(AF_INET, SOCK_STREAM, 0)) < 0 ) { X syslog(LOG_ERR, "socket create failed [%s]", errmssg); X continue; X } X if ( connect(sfd, (char *)&sin, sizeof(sin)) < 0 ) { X syslog(LOG_ERR, "socket connect failed [%s]", errmssg); X continue; X } X X /* X * Multiplex the data between the local and remote uucico's. X */ X numfd = ( pfd > sfd ? pfd : sfd ) + 1; X Dprintf(stderr, "connect successful\n"); X for (;;) { X X /* X * Wait for some data to read. X */ X FD_ZERO(&fdset); X FD_SET(pfd, &fdset); X FD_SET(sfd, &fdset); X if ( select(numfd, &fdset, (fd_set *)0, (fd_set *)0, X (struct timeval *)0) < 0 ) { X syslog(LOG_ERR, "select failed [%s]", errmssg); X break; X } X X /* X * Pass data from the pty to the socket. X */ X if ( FD_ISSET(pfd, &fdset) ) { X if ( (n=rdbuf(pfd, "pty", buf, sizeof(buf))) <= 0 ) X break; X if ( wrbuf(sfd, "socket", buf, n) < 0 ) X break; X continue; X } X X /* X * Pass data from the socket to the pty. X */ X if ( FD_ISSET(sfd, &fdset) ) { X if ( (n=rdbuf(sfd, "socket", buf, sizeof(buf))) <= 0 ) X break; X if ( wrbuf(pfd, "pty", buf, n) < 0 ) X break; X continue; X } X X /* why did we wakeup?? */ X X } X X /* X * The uucico session is complete. Loop back to wait for another X * session. The pty and socket fd's will be shutdown at the top X * of the loop. X */ X X } X X /*NOTREACHED*/ X X} X X X/* X * Read in a CR-terminated line of text. X * Return 0 upon success, -1 upon failure. X */ Xint rdline(fd, buf, n) Xint fd; /* file descriptor to read from */ Xchar *buf; /* place to stick the text */ Xint n; /* maximum number of chars to read */ X{ X while ( --n > 0 ) { X if ( read(fd, buf, 1) != 1 ) X return -1; X if ( *buf == '\r' ) X break; X ++buf; X } X *buf = '\0'; X return 0; X} X X X/* X * Read in a bufferful of data. X * Returns number of bytes read, 0 upon EOF, -1 upon error. X */ Xint rdbuf(fd, name, buf, buflen) Xint fd; /* file descriptor to read from */ Xchar *name; /* name to use in diagnostics */ Xchar *buf; /* place to stick the data */ Xint buflen; /* maximum number of bytes to read */ X{ X register int n; X X if ( (n=read(fd, buf, (unsigned)buflen)) < 0 ) { X syslog(LOG_ERR, "%s read error [%s]", name, errmssg); X return -1; X } X if ( n == 0 ) { X Dprintf(stderr, "hangup on %s\n", name); X return 0; X } X Dprintf(stderr, "read from %s %d bytes\n", name, n); X return n; X} X X X/* X * Write out a bufferful of data. X * Returns 0 upon success, -1 upon error. X */ Xint wrbuf(fd, name, buf, buflen) Xint fd; /* file descriptor to write to */ Xchar *name; /* name to use in diagnostics */ Xregister char *buf; /* the data to write out */ Xregister int buflen; /* number of bytes to write */ X{ X register int n; X X while ( buflen > 0 ) { X if ( (n=write(fd, buf, (unsigned)buflen)) < 0 ) { X syslog(LOG_ERR, "%s write error [%s]", name, errmssg); X return -1; X } X Dprintf(stderr, "write to %s %d bytes\n", name, n); X buflen -= n; X buf += n; X } X return 0; X} X END_OF_FILE_uucpm.c size="`wc -c < uucpm.c`" if test 7915 -ne "$size" ; then echo "uucpm.c: extraction error - got $size chars" fi fi if test -f uucpd.c -a "$1" != "-c" ; then echo "uucpd.c: file exists - will not be overwritten" else echo "x - uucpd.c (file 3 of 4, 8481 chars)" sed -e 's/^X//' << 'END_OF_FILE_uucpd.c' > uucpd.c X/* X * @(#) uucpd.c 1.1 91/06/07 01:33:44 X * X * Chip Rosenthal <chip@chinacat.unicom.com> X * Unicom Systems Development, Inc. X * X * Ported to System Vr3.2 and XENIX V. Compile with -DSYSV defined. X * Tested on SCO XENIX (TCP 1.0.1h) and SCO UNIX (TCP 1.1.3x). X * Compile with -DLAI_TCP defined. X * Only tested under "inetd". Compile with -DBSDINET defined. X * Made "lastlog" logging optional. Omit by -DNO_LASTLOG. X * Made "(struct utmp *)->ut_host" optional. Omit with -DNO_UTHOST. X * Added support to obtain password from "/etc/shadow". Define -DSHADOWPWD. X * Support for the SCO/Secureware wretched monstrosity. Use -DSECURECRAP. X */ X X/* X * Copyright (c) 1985 The Regents of the University of California. X * All rights reserved. X * X * This code is derived from software contributed to Berkeley by X * Rick Adams. X * X * Redistribution and use in source and binary forms are permitted X * provided that: (1) source distributions retain this entire copyright X * notice and comment, and (2) distributions including binaries display X * the following acknowledgement: ``This product includes software X * developed by the University of California, Berkeley and its contributors'' X * in the documentation or other materials provided with the distribution X * and in all advertising materials mentioning features or use of this X * software. Neither the name of the University nor the names of its X * contributors may be used to endorse or promote products derived X * from this software without specific prior written permission. X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED X * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. X */ X X#ifndef lint Xchar copyright[] = X"@(#) Copyright (c) 1985 The Regents of the University of California.\n\ X All rights reserved.\n"; X#endif /* not lint */ X X#ifndef lint Xstatic char sccsid[] = "@(#)uucpd.c 5.9 (Berkeley) 6/1/90"; X#endif /* not lint */ X X/* X * 4.2BSD TCP/IP server for uucico X * uucico's TCP channel causes this server to be run at the remote end. X */ X X#include <sys/types.h> X#include <sys/socket.h> X#ifdef SYSV X#include <fcntl.h> X#else X#include <sys/wait.h> X#include <sys/ioctl.h> X#include <sys/file.h> X#endif X#include <netinet/in.h> X#include <netdb.h> X#include <signal.h> X#include <errno.h> X#include <pwd.h> X#include <stdio.h> X#ifdef SHADOWPWD X#include <shadow.h> X#endif X#ifdef SECURECRAP X#define SecureWare X#include <sys/security.h> X#include <prot.h> X#endif X#ifdef SYSV X#define _PATH_UUCICO "/usr/lib/uucp/uucico" X#define _PATH_WTMP "/etc/wtmp" X#else X#include "pathnames.h" X#endif X Xstruct sockaddr_in hisctladdr; Xint hisaddrlen = sizeof hisctladdr; Xstruct sockaddr_in myctladdr; Xint mypid; X Xchar Username[64]; Xchar *nenv[] = { X Username, X NULL, X}; Xextern char **environ; X Xmain(argc, argv) Xint argc; Xchar **argv; X{ X#ifndef BSDINETD X register int s, tcp_socket; X struct servent *sp; X#endif /*!BSDINETD*/ X extern int errno; X int dologout(); X X#ifdef SECURECRAP X setluid(getuid()); X#endif X X environ = nenv; X#ifdef BSDINETD X close(1); close(2); X dup(0); dup(0); X hisaddrlen = sizeof (hisctladdr); X if (getpeername(0, &hisctladdr, &hisaddrlen) < 0) { X fprintf(stderr, "%s: ", argv[0]); X perror("getpeername"); X _exit(1); X } X if (fork() == 0) { X doit(&hisctladdr); X exit(1); X } X dologout(); X exit(1); X#else /*!BSDINETD*/ X sp = getservbyname("uucp", "tcp"); X if (sp == NULL){ X perror("uucpd: getservbyname"); X exit(1); X } X if (fork()) X exit(0); X if ((s=open(_PATH_TTY, 2)) >= 0){ X ioctl(s, TIOCNOTTY, (char *)0); X close(s); X } X X bzero((char *)&myctladdr, sizeof (myctladdr)); X myctladdr.sin_family = AF_INET; X myctladdr.sin_port = sp->s_port; X#ifdef BSD4_2 X tcp_socket = socket(AF_INET, SOCK_STREAM, 0); X if (tcp_socket < 0) { X perror("uucpd: socket"); X exit(1); X } X if (bind(tcp_socket, (char *)&myctladdr, sizeof (myctladdr)) < 0) { X perror("uucpd: bind"); X exit(1); X } X listen(tcp_socket, 3); /* at most 3 simultaneuos uucp connections */ X signal(SIGCHLD, dologout); X X for(;;) { X s = accept(tcp_socket, &hisctladdr, &hisaddrlen); X if (s < 0){ X if (errno == EINTR) X continue; X perror("uucpd: accept"); X exit(1); X } X if (fork() == 0) { X close(0); close(1); close(2); X dup(s); dup(s); dup(s); X close(tcp_socket); close(s); X doit(&hisctladdr); X exit(1); X } X close(s); X } X#endif /*BSD4_2*/ X X#endif /*!BSDINETD*/ X} X Xdoit(sinp) Xstruct sockaddr_in *sinp; X{ X char user[64], passwd[64]; X char *xpasswd, *crypt(); X struct passwd *pw, *getpwnam(); X X alarm(60); X printf("login: "); fflush(stdout); X if (readline(user, sizeof user) < 0) { X fprintf(stderr, "user read\n"); X return; X } X /* truncate username to 8 characters */ X user[8] = '\0'; X pw = getpwnam(user); X if (pw == NULL) { X fprintf(stderr, "user unknown\n"); X return; X } X#ifdef SHADOWPWD /*{*/ X { X struct spwd *spw; X if ( (spw=getspnam(user)) == NULL ) { X fprintf(stderr, "user unknown\n"); X return; X } X pw->pw_passwd = spw->sp_pwdp; X } X#endif /*}SHADOWPWD*/ X#ifdef SECURECRAP /*{*/ X { X struct pr_passwd *prpw; X static char *av[] = { "uucpd", NULL }; X set_auth_parameters(1,av); X if ( (prpw=getprpwnam(user)) == NULL ) { X fprintf(stderr, "user unknown\n"); X return; X } X pw->pw_passwd = prpw->ufld.fd_encrypt; X } X#endif /*}SECURECRAP*/ X if (strcmp(pw->pw_shell, _PATH_UUCICO)) { X fprintf(stderr, "Login incorrect.\n"); X return; X } X if (pw->pw_passwd && *pw->pw_passwd != '\0') { X printf("Password: "); fflush(stdout); X if (readline(passwd, sizeof passwd) < 0) { X fprintf(stderr, "passwd read\n"); X return; X } X xpasswd = crypt(passwd, pw->pw_passwd); X if (strcmp(xpasswd, pw->pw_passwd)) { X fprintf(stderr, "Login incorrect.\n"); X return; X } X } X alarm(0); X sprintf(Username, "USER=%s", user); X dologin(pw, sinp); X setgid(pw->pw_gid); X#ifdef BSD4_2 X initgroups(pw->pw_name, pw->pw_gid); X#endif /*BSD4_2*/ X chdir(pw->pw_dir); X setuid(pw->pw_uid); X#ifdef BSD4_2 X execl(UUCICO, "uucico", (char *)0); X#endif /*BSD4_2*/ X#ifdef SYSV X execl(_PATH_UUCICO, "uucico", (char *)0); X#endif X perror("uucico server: execl"); X} X Xreadline(p, n) Xregister char *p; Xregister int n; X{ X char c; X X while (n-- > 0) { X if (read(0, &c, 1) <= 0) X return(-1); X c &= 0177; X if (c == '\n' || c == '\r') { X *p = '\0'; X return(0); X } X *p++ = c; X } X return(-1); X} X X#include <utmp.h> X#ifdef BSD4_2 X#include <fcntl.h> X#endif /*BSD4_2*/ X X#define SCPYN(a, b) strncpy(a, b, sizeof (a)) X Xstruct utmp utmp; X Xdologout() X{ X#ifdef SYSV X int status; X#else X union wait status; X#endif X char line[32]; X int pid, wtmp; X X#ifdef BSDINETD X while ((pid=wait(&status)) > 0) { X#else /*!BSDINETD*/ X while ((pid=wait3(&status,WNOHANG,0)) > 0) { X#endif /*!BSDINETD*/ X wtmp = open(_PATH_WTMP, O_WRONLY|O_APPEND); X if (wtmp >= 0) { X sprintf(line, "uucp%.04d", pid%10000); X SCPYN(utmp.ut_line, line); X SCPYN(utmp.ut_name, ""); X#ifndef NO_UTHOST X SCPYN(utmp.ut_host, ""); X#endif X (void) time(&utmp.ut_time); X#ifdef SYSV X utmp.ut_type = DEAD_PROCESS; X utmp.ut_pid = getpid(); X utmp.ut_exit.e_termination = status & 0xFF; X utmp.ut_exit.e_exit = (status>>8) & 0xFF; X#endif X (void) write(wtmp, (char *)&utmp, sizeof (utmp)); X (void) close(wtmp); X } X } X} X X/* X * Record login in wtmp file. X */ Xdologin(pw, sin) Xstruct passwd *pw; Xstruct sockaddr_in *sin; X{ X char line[32]; X char remotehost[32]; X int wtmp; X#ifndef NO_LASTLOG X int f; X#endif X struct hostent *hp = gethostbyaddr(&sin->sin_addr, X sizeof (struct in_addr), AF_INET); X X if (hp) { X strncpy(remotehost, hp->h_name, sizeof (remotehost)); X endhostent(); X } else X strncpy(remotehost, inet_ntoa(sin->sin_addr), X sizeof (remotehost)); X wtmp = open(_PATH_WTMP, O_WRONLY|O_APPEND); X if (wtmp >= 0) { X /* hack, but must be unique and no tty line */ X sprintf(line, "uucp%.04d", getpid()%10000); X SCPYN(utmp.ut_line, line); X SCPYN(utmp.ut_name, pw->pw_name); X#ifndef NO_UTHOST X SCPYN(utmp.ut_host, remotehost); X#endif X time(&utmp.ut_time); X#ifdef SYSV X utmp.ut_type = USER_PROCESS; X utmp.ut_pid = getpid(); X utmp.ut_exit.e_termination = 0; X utmp.ut_exit.e_exit = 0; X#endif X (void) write(wtmp, (char *)&utmp, sizeof (utmp)); X (void) close(wtmp); X } X#ifndef NO_LASTLOG X if ((f = open(_PATH_LASTLOG, O_RDWR)) >= 0) { X struct lastlog ll; X X time(&ll.ll_time); X lseek(f, (long)pw->pw_uid * sizeof(struct lastlog), 0); X strcpy(line, remotehost); X SCPYN(ll.ll_line, line); X SCPYN(ll.ll_host, remotehost); X (void) write(f, (char *) &ll, sizeof ll); X (void) close(f); X } X#endif X} END_OF_FILE_uucpd.c size="`wc -c < uucpd.c`" if test 8481 -ne "$size" ; then echo "uucpd.c: extraction error - got $size chars" fi fi if test -f Makefile -a "$1" != "-c" ; then echo "Makefile: file exists - will not be overwritten" else echo "x - Makefile (file 4 of 4, 1784 chars)" sed -e 's/^X//' << 'END_OF_FILE_Makefile' > Makefile X# @(#) Makefile 1.2 91/06/11 12:45:15 X XSHELL = /bin/sh XCC = cc XALL = uucpm uucpd XLINT = uucpm.lint uucpd.lint XSRCS = README uucpm.c uucpd.c Makefile X Xall: $(ALL) Xlint: $(LINT) X X############################################################################## X# X# Site-specific customizations. X# X X# X# Site-specific definitions for networking. SCO needs "-DLAI_TCP". X# XSITEDEFS = -DLAI_TCP X X# X# Enable the following for SCO UNIX. X# X#SECURECRAP = -DSECURECRAP X#LDPROT = -lprot X X# X# Enable the following for /etc/shadow support. X# XSHADOWPWD = -DSHADOWPWD XLDSHADOW = -lshadow X X# X# Define to point to your socket library - maybe "-lsocket", maybe "-linet". X# XLDSOCKET = -lsocket X X# X# Define to point to your crypt library - usually "-lcrypt". X# XLDCRYPT = -lcrypt X X# X# You probably want to define the following as "cp". X# XINST = inst -D X X# X# Enable the following if files are checked into SCCS. X# X$(SRCS) : SCCS/s.$$@ ; sccs get $@ Xclobber : clean ; sccs clean ; sccs get Makefile X X# X############################################################################## X X XDEFS_M = $(SITEDEFS) XDEFS_D = -DSYSV -DBSDINETD -DNO_LASTLOG -DNO_UTHOST \ X $(SITEDEFS) $(SHADOWPWD) $(SECURECRAP) XLIBS_M = $(LDSOCKET) XLIBS_D = $(LDSOCKET) $(LDCRYPT) $(LDSHADOW) $(LDPROT) X Xclean: X rm -f $(ALL) $(LINT) *.o a.out core X Xinstall: all X $(INST) uucpm /etc/local/uucpm X $(INST) uucpd /etc/local/uucpd X Xuucpm: uucpm.o X $(CC) -o uucpm uucpm.o $(LIBS_M) X Xuucpd: uucpd.o X $(CC) -o uucpd uucpd.o $(LIBS_D) X Xuucpm.o: uucpm.c X $(CC) -O -c $(DEFS_M) uucpm.c X Xuucpd.o: uucpd.c X $(CC) -O -c $(DEFS_D) uucpd.c X Xuucpm.lint: uucpm X lint -DNO_PROTOTYPE $(DEFS_M) uucpm.c $(LIBS_M) >$@ X Xuucpd.lint: uucpd X lint -DNO_PROTOTYPE $(DEFS_D) uucpd.c $(LIBS_D) >$@ X XSHAR = uucpm.shar Xshar : $(SHAR) X$(SHAR) : $(SRCS) ; shar $(SRCS) >$@ X END_OF_FILE_Makefile size="`wc -c < Makefile`" if test 1784 -ne "$size" ; then echo "Makefile: extraction error - got $size chars" fi fi echo "done - 4 files extracted" exit 0 -- Chip Rosenthal <chip@chinacat.Unicom.COM> | Don't play that Unicom Systems Development 512-482-8260 | loud, Mr. Collins.