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