uucp over TCP/IP
Chip Rosenthal
chip at chinacat.unicom.com
Wed Jun 12 03:55:22 AEST 1991
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 at 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 at 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 at 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 at 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 at chinacat.Unicom.COM> | Don't play that
Unicom Systems Development 512-482-8260 | loud, Mr. Collins.
More information about the Alt.sources
mailing list