BSD Networking commands for UNIX PC STARLAN. Part 2 of 3.

Roger Florkowski roger at taliesin.UUCP
Thu Sep 20 15:11:48 AEST 1990


#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 2 (of 3)."
# Contents:  lib/openslan.c lib/rcmd.c man/rshd.8 remsh.c rexecd.c
#   rmtd.c rshd.c
# Wrapped by roger at taliesin on Wed Sep 19 23:37:51 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f lib/openslan.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"lib/openslan.c\"
else
echo shar: Extracting \"lib/openslan.c\" \(5094 characters\)
sed "s/^X//" >lib/openslan.c <<'END_OF_lib/openslan.c'
X/* $Id: openslan.c,v 1.1 90/09/19 23:24:59 roger C_1 $
X *
X *	openslan.c: prepare a starlan stream for communications.
X *
X *	Roger Florkowski
X *	cs.utexas.edu!taliesin!roger
X */
X
X/* 
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X *	
X * Purpose of this file is to provide routines for opening starlan
X * in connection-less, connection-orientated (block mode), or 
X * connection-orientated (character mode),  and a quicker way
X * to connect to a remote listener.
X *
X * NOTE: try as I might, I could not get connection-less mode
X *	to transfer data on my system (t_sndudata and t_rcvudata).
X *	remstat reported that packets were being transfered and
X *	received (at the starlan level), but t_rcudata *NEVER*
X *	returned back to me.
X */
X
X/* don't wait for a reply from the remote listener */
X#define NOREPLY
X
X#include <net/sys/tiuser.h>
X#include <net/sys/stropts.h>
X#include <net/listen.h>
X#include <stdio.h>
X#include <fcntl.h>
X#include "rcmds.h"
X
X#define STARLAN "/dev/starlan"
X
Xextern errno, t_errno;
Xint _protocol;		/* hack to muck with protocols */
X
X/* open starlan */
Xint
Xopenslan(dev, oflag, service)
Xchar *dev;
Xint oflag;
Xint service;
X{
X    int fd;
X
X    if ((fd = open(dev == NULL ? STARLAN : dev, oflag)) < 0) 
X	return (-1);
X
X    /* Look in /usr/net/tli/t_config
X     * I could read/parse that file, but why bother?  unixpc slan is a dead
X     * issue.
X     */
X
X    /* default transport end always starts with ccmod */
X    if (ioctl (fd, I_PUSH, "ccmod"))
X	goto failure;
X
X    switch (service) {
X	case T_CLTS:	/* connectionless.  No further modules to push */
X	    break;
X	case T_COTS:	/* connection-mode. (block mode) */
X	    if (ioctl (fd, I_PUSH, "urpmod")) 
X		goto failure;
X	    break;
X	case T_CCOTS:	/* connection-mode (character mode) */
X	    if (ioctl (fd, I_PUSH, "curpmod")) 
X		goto failure;
X	    break;
X	case T_COTS_ORD:	/* connection-mode, orderly release */
X	default:
X	    t_errno = TNOTSUPPORT;
X	    goto failure;
X    }
X
X    if (t_sync(fd) >= 0) 
X	return (fd);
Xfailure:
X    close (fd);
X    return (-1);
X}
X
X/* open and bind to default starlan endpoint */
Xint
Xopenbind(service, retbind)
Xint service;
Xstruct t_bind *retbind;
X{
X    struct t_bind *lret;
X    int fd;
X
X    /* open starlan */
X    if ((fd = openslan(NULL, O_RDWR, service)) < 0) {
X	DEBUG2("openslan failed. errno %d t_errno %d\n", errno, t_errno);
X	return (-1);
X    }
X    DEBUG1("open returned %d\n", fd);
X
X    /* bind to local communications endpoint */
X    if (retbind == NULL) {
X	if ((lret = (struct t_bind *)t_alloc (fd,T_BIND,T_ALL)) == NULL)
X	    return (-1);
X    } else
X	lret = retbind;
X    if (t_bind (fd, NULL, lret)) {
X	DEBUG2("t_bind failed. errno %d t_errno %d\n", errno, t_errno);
X	return (-1);
X    }
X    DEBUG3("bound to %*.*s\n", lret->addr.len, lret->addr.len,
X	    lret->addr.buf);
X    if (retbind == NULL)
X	t_free (lret, T_BIND);
X    return (fd);
X}
X
X
X/* connect to the listener on the remote machine */
Xint 
Xconnect_to(host, port, service)
Xchar *host;	/* remote host */
Xint port, 	/* remote port */
X    service;	/* connection service */
X{
X    struct t_call *call;
X    char buf[80];
X    int fd, buflen, rcvflags;
X
X    if (service != T_COTS && service != T_CCOTS) {
X	t_errno = TNOTSUPPORT;
X	return (-1);
X    }
X
X    /* listener listens to <hostname>.serve */
X    sprintf (buf, "%s.serve", host);
X
X    if ((fd = openbind(service, NULL)) < 0)
X	return (-1);
X
X    if ((call = (struct t_call *)t_alloc (fd,T_CALL,T_ALL)) == NULL)
X	return (-1);
X    call->addr.len = strlen(buf);
X    strncpy (call->addr.buf, buf, call->addr.len);
X    DEBUG3("about to connect to %*.*s\n", call->addr.len, call->addr.len,
X	    call->addr.buf);
X    if (!lname2addr (fd, &(call->addr))){
X	DEBUG2("lname2addr failed. errno %d t_errno %d\n", errno, t_errno);
X	return (-1);
X    }
X    if (t_connect (fd, call, NULL)) {
X	DEBUG2("t_connect failed. errno %d t_errno %d\n", errno, t_errno);
X	if (t_errno == TLOOK) {
X	    int look;
X	    if (look = t_look (fd)) 
X		DEBUG2("t_look failed. errno %d t_errno %d\n", errno, t_errno);
X	    else
X		DEBUG1("t_look returned %d\n", look);
X	}
X	return (-1);
X    }
X    t_free (call, T_CALL);
X
X    /* now tell the listener what service we want */
X#ifdef NOREPLY
X    /* NOTE: if we run with nls_v2p_msg, listener will respond back.
X     *		For speed purposes, we just don't care.  Basically
X     *		I think the listener will tell us if the port_service
X     *		is started or unknown.  Big deal.
X     */
X    sprintf (buf, nls_prot_msg, port);
X#else
X    sprintf (buf, nls_v2p_msg, port);
X#endif
X    buflen = strlen (buf)+1;
X    DEBUG1("sending %s to listener\n", buf);
X    if (t_snd (fd, buf, buflen, NULL) < buflen)
X	return (-1);
X#ifndef NOREPLY
X    if ((buflen = t_rcv (fd, buf, buflen, &rcvflags)) < 0)
X	return (-1);
X    DEBUG1("listener echoed back %*.*s\n", buflen, buflen, buf);
X#endif
X    
X    return (fd);
X}
X
X/*
X** disconnect from STARLAN 
X*/
X
Xvoid disconnect(fd)
Xint fd;
X{
X    t_snddis(fd, (char *)NULL);
X    t_unbind(fd);
X    t_close(fd);
X}
X
END_OF_lib/openslan.c
if test 5094 -ne `wc -c <lib/openslan.c`; then
    echo shar: \"lib/openslan.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f lib/rcmd.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"lib/rcmd.c\"
else
echo shar: Extracting \"lib/rcmd.c\" \(5644 characters\)
sed "s/^X//" >lib/rcmd.c <<'END_OF_lib/rcmd.c'
X/* $Id: rcmd.c,v 1.1 90/09/19 23:24:59 roger C_1 $
X *
X *	rcmd.c: open a communications channel and execute
X *		a remote command.
X *
X *	Roger Florkowski
X *	cs.utexas.edu!taliesin!roger
X */
X
X/*
X * Copyright (c) 1983 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice and this paragraph are
X * duplicated in all such forms and that any documentation,
X * advertising materials, and other materials related to such
X * distribution and use acknowledge that the software was developed
X * by the University of California, Berkeley.  The name of the
X * University may not 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 MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X */
X
X#if defined(LIBC_SCCS) && !defined(lint)
Xstatic char sccsid[] = "@(#)rcmd.c	5.20 (Berkeley) 1/24/89";
X#endif /* LIBC_SCCS and not lint */
X
X#include <net/sys/tiuser.h>
X#include <stdio.h>
X#include <ctype.h>
X#include <pwd.h>
X#include <sys/param.h>
X#include <sys/file.h>
X#include <sys/stat.h>
X#include <sys/utsname.h>
X#include "rcmds.h"
X
X#include <errno.h>
X
X#define MAXPATHLEN	512	/* value from MAXNAMLEN in dirent pkg */
X
Xvoid disconnect();
Xchar *strcpy(), *malloc();
X
Xextern	int _protocol;
X
Xrcmd (ahost, rport, luser, ruser, cmd, fd2p)
Xchar *ahost;
Xint rport;
Xchar *luser, *ruser, *cmd;
Xint *fd2p;
X{
X    int s, s2, rcvflags;
X    char c, locuser[80], remuser[80];
X    struct utsname utsname;
X
X    /* nls routines use the passwd routines, which messes up pw->pw_name */
X    strncpy (locuser, luser, sizeof (locuser));
X    strncpy (remuser, ruser, sizeof (remuser));
X
X    /* unixpc starlan hack. Need to tell remote who we are,
X     * since remote can't figure out who the call came from.
X     */
X    if (uname(&utsname) < 0) {
X	fprintf (stderr, "Can't determine local hostname\n");
X	exit (1);
X    }
X
X    /* connect to service rport on ahost */
X    fprintf (stderr, "Trying %s...", ahost);
X    if ((s = connect_to (ahost, rport, _protocol ? _protocol : T_COTS)) < 0) {
X	fprintf (stderr, "Connection Failed (%s not listening?)\n", ahost);
X	return (s);
X    }
X    DEBUG1("connected to %s\n", ahost);
X
X    /* client might want the server to fire up a signal monitor */
X    if (fd2p) { 
X	DEBUG("trying to connect to signal port\n");
X	(void) t_snd (s, "\1", 1, NULL);
X	if ((s2 = rsignalPort (s)) < 0) {
X	    fprintf (stderr, "Can't establish signal port\n");
X	    DEBUG("signal port connection failed\n");
X	    disconnect (s);
X	    exit (1);
X	}
X	*fd2p = s2;
X    }
X    else 
X	(void) t_snd (s, "\0", 1, NULL);
X
X    /* tell remote who we are, user info, and command */
X    (void) t_snd(s, utsname.nodename, strlen(utsname.nodename)+1, NULL);
X    (void) t_snd(s, locuser, strlen(locuser)+1, NULL);
X    (void) t_snd(s, remuser, strlen(remuser)+1, NULL);
X    (void) t_snd(s, cmd, strlen(cmd)+1, NULL);
X    DEBUG3("host: %s\nlocuser: %s\nremuser: %s\n", utsname.nodename,
X	    locuser, remuser);
X    DEBUG1("cmd: %s\n", cmd);
X
X    /* read a single NULL char as an ack */
X    if (t_rcv (s, &c, 1, &rcvflags) != 1) {
X	perror (ahost);
X	goto bad;
X    }
X    /* oops, not an ack.  Read in error message from remote */
X    if (c != 0) {
X	while (t_rcv(s, &c, 1, &rcvflags) == 1) {
X	    (void) write(2, &c, 1);
X	    if (c == '\n')
X		break;
X	}
X	goto bad;
X    }
X    fprintf (stderr, "Connected\n");
X    return (s);
Xbad:
X    (void) disconnect (s);
X    return (-1);
X}
X
Xint	_check_rhosts_file = 1;
X
Xruserok(rhost, superuser, ruser, luser)
X	char *rhost;
X	int superuser;
X	char *ruser, *luser;
X{
X	FILE *hostf;
X	int first = 1;
X	int baselen = -1;
X
X	hostf = superuser ? (FILE *)0 : fopen("/etc/hosts.equiv", "r");
Xagain:
X	if (hostf) {
X		if (!_validuser(hostf, rhost, luser, ruser, baselen)) {
X			(void) fclose(hostf);
X			return(0);
X		}
X		(void) fclose(hostf);
X	}
X	if (first == 1 && (_check_rhosts_file || superuser)) {
X		struct stat sbuf;
X		struct passwd *pwd;
X		char pbuf[MAXPATHLEN];
X
X		first = 0;
X		if ((pwd = (struct passwd *)getpwnam(luser)) == NULL)
X			return(-1);
X		(void)strcpy(pbuf, pwd->pw_dir);
X		(void)strcat(pbuf, "/.rhosts");
X		if ((hostf = fopen(pbuf, "r")) == NULL)
X			return(-1);
X		/*
X		 * if owned by someone other than user or root or if
X		 * writeable by anyone but the owner, quit
X		 */
X		if (fstat(fileno(hostf), &sbuf) ||
X		    sbuf.st_uid && sbuf.st_uid != pwd->pw_uid ||
X		    sbuf.st_mode&022) {
X			fclose(hostf);
X			return(-1);
X		}
X		goto again;
X	}
X	return (-1);
X}
X
X/* don't make static, used by lpd(8) */
X_validuser(hostf, rhost, luser, ruser, baselen)
X	char *rhost, *luser, *ruser;
X	FILE *hostf;
X	int baselen;
X{
X	char *user;
X	char ahost[16];
X	register char *p;
X
X	while (fgets(ahost, sizeof (ahost), hostf)) {
X		p = ahost;
X		while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') {
X			*p = isupper(*p) ? tolower(*p) : *p;
X			p++;
X		}
X		if (*p == ' ' || *p == '\t') {
X			*p++ = '\0';
X			while (*p == ' ' || *p == '\t')
X				p++;
X			user = p;
X			while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0')
X				p++;
X		} else
X			user = p;
X		*p = '\0';
X		if (_checkhost(rhost, ahost, baselen) &&
X		    !strcmp(ruser, *user ? user : luser)) {
X			return (0);
X		}
X	}
X	return (-1);
X}
X
Xstatic
X_checkhost(rhost, lhost, len)
X	char *rhost, *lhost;
X	int len;
X{
X	if (len == -1)
X		return(!strcmp(rhost, lhost));
X	if (strncmp(rhost, lhost, len))
X		return(0);
X	if (!strcmp(rhost, lhost))
X		return(1);
X	if (*(lhost + len) != '\0')
X		return(0);
X	return(0);
X}
END_OF_lib/rcmd.c
if test 5644 -ne `wc -c <lib/rcmd.c`; then
    echo shar: \"lib/rcmd.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f man/rshd.8 -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"man/rshd.8\"
else
echo shar: Extracting \"man/rshd.8\" \(5350 characters\)
sed "s/^X//" >man/rshd.8 <<'END_OF_man/rshd.8'
X.\" Copyright (c) 1983 The Regents of the University of California.
X.\" All rights reserved.
X.\"
X.\" Redistribution and use in source and binary forms are permitted
X.\" provided that the above copyright notice and this paragraph are
X.\" duplicated in all such forms and that any documentation,
X.\" advertising materials, and other materials related to such
X.\" distribution and use acknowledge that the software was developed
X.\" by the University of California, Berkeley.  The name of the
X.\" University may not 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 MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X.\"
X.\"	@(#)rshd.8	6.5 (Berkeley) 9/19/88
X.\"
X.TH RSHD 8 "September 19, 1988"
X.UC 5
X.SH NAME
Xrshd \- remote shell server
X.SH SYNOPSIS
X.B /etc/rshd
X.SH DESCRIPTION
X.I Rshd
Xis the server for the 
X.IR rcmd (3X)
Xroutine and, consequently, for the
X.IR rsh (1C)
Xprogram.  The server provides remote execution facilities
Xwith authentication based on privileged port numbers from trusted hosts.
X.PP
X.I Rshd
Xlistens for service requests at the port indicated in
Xthe ``cmd'' service specification; see
X.IR services (5).
XWhen a service request is received the following protocol
Xis initiated:
X.IP 1)
XThe server checks the client's source port.
XIf the port is not in the range 0-1023, the server
Xaborts the connection.
X.IP 2)
XThe server reads characters from the socket up
Xto a null (`\e0') byte.  The resultant string is
Xinterpreted as an ASCII number, base 10.
X.IP 3)
XIf the number received in step 2 is non-zero,
Xit is interpreted as the port number of a secondary
Xstream to be used for the 
X.BR stderr .
XA second connection is then created to the specified
Xport on the client's machine.  The source port of this
Xsecond connection is also in the range 0-1023.
X.IP 4)
XThe server checks the client's source address
Xand requests the corresponding host name (see
X.IR gethostbyaddr (3N),
X.IR hosts (5)
Xand
X.IR named (8)).
XIf the hostname cannot be determined,
Xthe dot-notation representation of the host address is used.
X.IP 5)
XA null terminated user name of at most 16 characters
Xis retrieved on the initial socket.  This user name
Xis interpreted as the user identity on the
X.BR client 's
Xmachine.
X.IP 6)
XA null terminated user name of at most 16 characters
Xis retrieved on the initial socket.  This user name
Xis interpreted as a user identity to use on the
X.BR server 's
Xmachine.
X.IP 7)
XA null terminated command to be passed to a
Xshell is retrieved on the initial socket.  The length of
Xthe command is limited by the upper bound on the size of
Xthe system's argument list.  
X.IP 8)
X.I Rshd
Xthen validates the user according to the following steps.
XThe local (server-end) user name is looked up in the password file
Xand a
X.I chdir
Xis performed to the user's home directory.  If either
Xthe lookup or 
X.I chdir
Xfail, the connection is terminated.
XIf the user is not the super-user, (user id 0), the file 
X.I /etc/hosts.equiv
Xis consulted for a list of hosts considered ``equivalent''.
XIf the client's host name is present in this file, the
Xauthentication is considered successful.  If the lookup
Xfails, or the user is the super-user, then the file
X.I .rhosts
Xin the home directory of the remote user is checked for
Xthe machine name and identity of the user on the client's
Xmachine.  If this lookup fails, the connection is terminated.
X.IP 9)
XA null byte is returned on the initial socket
Xand the command line is passed to the normal login
Xshell of the user.  The
Xshell inherits the network connections established
Xby
X.IR rshd .
X.SH DIAGNOSTICS
XExcept for the last one listed below,
Xall diagnostic messages
Xare returned on the initial socket,
Xafter which any network connections are closed.
XAn error is indicated by a leading byte with a value of
X1 (0 is returned in step 9 above upon successful completion
Xof all the steps prior to the execution of the login shell).
X.PP
X.B ``locuser too long''
X.br
XThe name of the user on the client's machine is
Xlonger than 16 characters.
X.PP
X.B ``remuser too long''
X.br
XThe name of the user on the remote machine is
Xlonger than 16 characters.
X.PP
X.B ``command too long ''
X.br
XThe command line passed exceeds the size of the argument
Xlist (as configured into the system).
X.PP
X.B ``Login incorrect.''
X.br
XNo password file entry for the user name existed.
X.PP
X.B ``No remote directory.''
X.br
XThe 
X.I chdir
Xcommand to the home directory failed.
X.PP
X.B ``Permission denied.''
X.br
XThe authentication procedure described above failed.
X.PP
X.B ``Can't make pipe.''
X.br
XThe pipe needed for the 
X.BR stderr ,
Xwasn't created.
X.PP
X.B ``Try again.''
X.br
XA
X.I fork
Xby the server failed.
X.PP
X.B ``<shellname>: ...''
X.br
XThe user's login shell could not be started.  This message is returned
Xon the connection associated with the
X.BR stderr ,
Xand is not preceded by a flag byte.
X.SH SEE ALSO
Xrsh(1), rcmd(3)
X.SH BUGS
XThe authentication procedure used here assumes the integrity
Xof each client machine and the connecting medium.  This is
Xinsecure, but is useful in an ``open'' environment.
X.PP
XA facility to allow all data exchanges to be encrypted should be
Xpresent.
X.PP
XA more extensible protocol should be used.
END_OF_man/rshd.8
if test 5350 -ne `wc -c <man/rshd.8`; then
    echo shar: \"man/rshd.8\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f remsh.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"remsh.c\"
else
echo shar: Extracting \"remsh.c\" \(5663 characters\)
sed "s/^X//" >remsh.c <<'END_OF_remsh.c'
X/* $Id: remsh.c,v 1.1 90/09/19 23:27:24 roger C_1 $
X *
X *	This is a UnixPC STARLAN port of BSD's rsh.
X *	(renamed remsh so as not to conflict with /bin/rsh)
X *	Roger Florkowski
X *	cs.utexas.edu!taliesin!roger
X */
X
X/*
X * Copyright (c) 1983 The Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice and this paragraph are
X * duplicated in all such forms and that any documentation,
X * advertising materials, and other materials related to such
X * distribution and use acknowledge that the software was developed
X * by the University of California, Berkeley.  The name of the
X * University may not 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 MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X */
X
X#ifndef lint
Xchar copyright[] =
X"@(#) Copyright (c) 1983 The Regents of the University of California.\n\
X All rights reserved.\n";
X#endif /* not lint */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#)rsh.c	5.7 (Berkeley) 9/20/88";
X#endif /* not lint */
X
X#include <net/sys/poll.h>
X#include <net/sys/tiuser.h>
X#include <sys/types.h>
X#include <sys/ioctl.h>
X#include <sys/file.h>
X#include <fcntl.h>
X
X#include <stdio.h>
X#include <errno.h>
X#include <signal.h>
X#include <pwd.h>
X#include "rcmds.h"
X
X/*
X * rsh - remote shell
X */
X/* VARARGS */
Xint	error();
Xchar	*malloc(), *strcpy(), *strrchr();
X
Xstruct	passwd *getpwuid();
X
Xextern errno, t_errno;
Xextern int	_protocol;	/* in rcmd.c */
Xint	rem, rfd2;
Xint	nflag;
Xint	sendsig();
X
X#define PROGNAME "remsh"
XFILE *debug;
X
Xmain(argc, argv0)
X	int argc;
X	char **argv0;
X{
X	int pid;
X	char *host, *cp, **ap, buf[BUFSIZ], *args, **argv = argv0, *user = 0;
X	register int cc;
X	int asrsh = 0;
X	struct passwd *pwd;
X	int readfrom;
X	int one = 1;
X
X	host = strrchr(argv[0], '/');
X	if (host)
X		host++;
X	else
X		host = argv[0];
X	argv++, --argc;
X	if (!strcmp(host, PROGNAME)) {
X		host = *argv++, --argc;
X		asrsh = 1;
X	}
Xanother:
X	if (argc > 0 && !strcmp(*argv, "-l")) {
X		argv++, argc--;
X		if (argc > 0)
X			user = *argv++, argc--;
X		goto another;
X	}
X	if (argc > 0 && !strcmp(*argv, "-n")) {
X		argv++, argc--;
X		nflag++;
X		goto another;
X	}
X	/*
X	 * Ignore the -L, -w, -e and -8 flags to allow aliases with rlogin
X	 * to work
X	 *
X	 * There must be a better way to do this! -jmb
X	 */
X	if (argc > 0 && !strncmp(*argv, "-L", 2)) {
X		argv++, argc--;
X		goto another;
X	}
X	if (argc > 0 && !strncmp(*argv, "-w", 2)) {
X		argv++, argc--;
X		goto another;
X	}
X	if (argc > 0 && !strncmp(*argv, "-e", 2)) {
X		argv++, argc--;
X		goto another;
X	}
X	if (argc > 0 && !strncmp(*argv, "-8", 2)) {
X		argv++, argc--;
X		goto another;
X	}
X	if (host == 0)
X		goto usage;
X	if (argv[0] == 0) {
X#ifdef future
X		if (asrsh)
X			*argv0 = "rlogin";
X		execv("/usr/ucb/rlogin", argv0);
X		perror("/usr/ucb/rlogin");
X		exit(1);
X#else
X		exit(1);
X#endif
X	}
X#ifdef DO_DEBUG
X	debug = fopen("/tmp/remsh.out", "a");
X	if (debug == 0)
X	    exit(1);
X	(void) setbuf(debug, (char *)0);
X	DEBUG1("remsh [%d] started\n", getpid());
X#endif
X	pwd = getpwuid(getuid());
X
X	if (pwd == 0) {
X		fprintf(stderr, "who are you?\n");
X		exit(1);
X	}
X	cc = 0;
X	for (ap = argv; *ap; ap++)
X		cc += strlen(*ap) + 1;
X	cp = args = malloc(cc);
X	for (ap = argv; *ap; ap++) {
X		(void) strcpy(cp, *ap);
X		while (*cp)
X			cp++;
X		if (ap[1])
X			*cp++ = ' ';
X	}
X	_protocol = T_CCOTS;	/* connection-orientated, character mode */
X        rem = rcmd(host, RSHD_PORT, pwd->pw_name,
X	    user ? user : pwd->pw_name, args, &rfd2);
X        if (rem < 0)
X                exit(1);
X
X	(void) setuid(getuid());
X	signal(SIGINT, sendsig);
X	signal(SIGQUIT, sendsig);
X	signal(SIGTERM, sendsig);
X	if (nflag == 0) {
X		pid = fork();
X		if (pid < 0) {
X			perror("fork");
X			exit(1);
X		}
X	}
X
X	/* child, and we are running a command */
X	/* child reads from stdin, writes to remote */
X        if (nflag == 0 && pid == 0) {
X		char *bp; int wc, wflags;
X	reread:
X		errno = 0;
X		wflags = 0;
X		cc = read(0, buf, sizeof buf);
X		if (cc <= 0) {
X		    DEBUG("child: stdin closed, ending\n");
X		    goto done;
X		}
X		bp = buf;
X	rewrite:
X		/* can't poll for output on unixpc :-( */
X		errno = 0;
X		t_errno = 0;
X		wc = t_snd (rem, bp, cc, wflags);
X		if (wc < 0) {
X
X		    /* check for a stream that can't accept any data */
X		    DEBUG2("child: t_snd failed, errno %d, t_errno %d\n",
X				errno, t_errno);
X		    if (t_errno == TFLOW)
X			goto rewrite;
X		    goto done;
X		}
X		cc -= wc; bp += wc;
X		if (cc == 0)
X			goto reread;
X		wflags = T_MORE;
X		goto rewrite;
X	done:
X		(void) disconnect (rem);
X		(void) disconnect (rfd2);
X		exit (0);
X	}
X
X	/* parent.  reads from remote for input, and writes to stdout */
X	readfrom = 1;
X	do {
X	    int rcvflags;
X
X	    errno = 0;
X	    t_errno = 0;
X	    rcvflags = 0;
X
X	    cc = t_rcv (rem, buf, sizeof (buf), &rcvflags);
X	    if (cc <= 0) {
X		DEBUG2("parent: t_rcv failed, errno %d, t_errno %d\n",
X			    errno, t_errno);
X		if (t_errno != TNODATA || cc == 0) 
X		    readfrom = 0;
X	    } else
X		(void) write(1, buf, cc);
X	    if (rcvflags & T_MORE) 
X		continue;
X        } while (readfrom);
X
X	(void) disconnect (rem);
X	(void) disconnect (rfd2);
X	if (nflag == 0)
X	    (void) kill(pid, SIGKILL);
X	exit(0);
Xusage:
X	fprintf(stderr,
X	    "usage: remsh host [ -l login ] [ -n ] command\n");
X	exit(1);
X}
X
Xsendsig(signo)
X	char signo;
X{
X    DEBUG1("sending sig %d\n", signo);
X    t_snd (rfd2, &signo, 1, NULL);
X    t_snd (rfd2, &signo, 1, NULL);
X    (void) disconnect (rem);
X    (void) disconnect (rfd2);
X    exit (0);
X}
END_OF_remsh.c
if test 5663 -ne `wc -c <remsh.c`; then
    echo shar: \"remsh.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f rexecd.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"rexecd.c\"
else
echo shar: Extracting \"rexecd.c\" \(5462 characters\)
sed "s/^X//" >rexecd.c <<'END_OF_rexecd.c'
X/* $Id: rexecd.c,v 1.1 90/09/19 23:27:25 roger C_1 $
X *
X *	This is a UnixPC STARLAN port of BSD's rexecd.
X *
X *	Roger Florkowski
X *	cs.utexas.edu!taliesin!roger
X */
X
X/*
X * Copyright (c) 1983 The Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice and this paragraph are
X * duplicated in all such forms and that any documentation,
X * advertising materials, and other materials related to such
X * distribution and use acknowledge that the software was developed
X * by the University of California, Berkeley.  The name of the
X * University may not 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 MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X */
X
X#ifndef lint
Xchar copyright[] =
X"@(#) Copyright (c) 1983 The Regents of the University of California.\n\
X All rights reserved.\n";
X#endif /* not lint */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#)rexecd.c	5.7 (Berkeley) 1/4/89";
X#endif /* not lint */
X
X#include <net/sys/tiuser.h>
X#include <sys/ioctl.h>
X#include <sys/param.h>
X
X#include <stdio.h>
X#include <errno.h>
X#include <pwd.h>
X#include <signal.h>
X#include "rcmds.h"
X
Xextern	errno, t_errno;
Xstruct	passwd *getpwnam();
Xchar	*crypt(), *strrchr(), *strncat();
X/*VARARGS1*/
Xint	error();
Xint	cleanup();
XFILE *debug;
X
Xtypedef int		gid_t;	/* missing from types.h */
Xtypedef int		uid_t;
X
X/*
X * remote execute server:
X *	[port]\0		* 0 == no, 1 == yes.  unixpc hack *
X *	username\0
X *	password\0
X *	command\0
X *	data
X */
X/*ARGSUSED*/
Xmain(argc, argv)
X	int argc;
X	char **argv;
X{
X#ifdef DO_DEBUG
X    debug = fopen("/tmp/rexecd.out", "a");
X    if (debug == 0)
X	exit(1);
X    (void) setbuf(debug, (char *)0);
X#endif
X    DEBUG1("rexecd [%d] started\n", getpid());
X    /* sync up starlan communications */
X    if (t_sync(0) != T_DATAXFER) 
X	exit(1);
X
X    doit();
X}
X
Xchar	username[20] = "LOGNAME=";
Xchar	homedir[64] = "HOME=";
Xchar	shell[64] = "SHELL=";
Xchar	*envinit[] =
X	    {homedir, shell, "PATH=:/usr/ucb:/bin:/usr/bin", username, 0};
Xextern	char	**environ;
Xint 	rfd2;
X
Xdoit()
X{
X	char cmdbuf[NCARGS+1], *cp, *namep, c, sig;
X	char user[16], pass[16];
X	struct passwd *pwd;
X	int pid, cc, rcvflags;
X
X	(void) signal(SIGINT, SIG_DFL);
X	(void) signal(SIGQUIT, SIG_DFL);
X	(void) signal(SIGTERM, SIG_DFL);
X	(void) signal(SIGCLD, cleanup);
X
X	/* read initial char from remote.  If our char != 0, then the
X	 * remote wants to establish a second connection to us for
X	 * signal monitoring.
X	 */
X	if ((cc = t_rcv (0, &c, 1, &rcvflags)) != 1) {
X	    t_unbind (0);
X	    t_close (0);
X	    exit (1);
X	}
X	if (c != 0) 
X	    if ((rfd2 = signalPort (0, RSHD_PORT)) < 0) {
X		DEBUG2("signalPort failed. errno %d, t_errno %d\n",
X			errno, t_errno);
X		cleanup (0);
X	    }
X
X	getstr(user, sizeof(user), "username");
X	getstr(pass, sizeof(pass), "password");
X	getstr(cmdbuf, sizeof(cmdbuf), "command");
X	setpwent();
X	pwd = getpwnam(user);
X	if (pwd == NULL) {
X		error("Login incorrect.\n");
X		exit(1);
X	}
X	endpwent();
X	if (*pwd->pw_passwd != '\0') {
X		namep = crypt(pass, pwd->pw_passwd);
X		if (strcmp(namep, pwd->pw_passwd)) {
X			error("Password incorrect.\n");
X			exit(1);
X		}
X	}
X	if (chdir(pwd->pw_dir) < 0) {
X		error("No remote directory.\n");
X		exit(1);
X	}
X
X	/* write ack */
X	(void) t_snd(0, "\0", 1, NULL);
X
X	if (rfd2) {
X	    pid = fork();
X	    if (pid == -1)  {
X		error("Try again.\n");
X		exit(1);
X	    }
X	    /* signal Monitor.  Parent hangs out, sole purpose 
X	     * is to wait for a kill signal from the remote.
X	     */
X	    if (pid) {
X
X		for (;;) {
X		    DEBUG("signald, waiting to receive\n");
X		    if (t_rcv (rfd2, &sig, 1, &rcvflags) < 0) {
X			DEBUG2("t_rcv failed, errno %d, t_errno %d\n",
X				errno, t_errno);
X			if (t_errno == TLOOK) {
X			    int look;
X			    if (!(look = t_look (rfd2))) 
X				DEBUG1("t_look returned %d\n", look);
X			}
X			kill (pid, 9);	/* rude and abrupt.  Too bad */
X			cleanup (0);
X		    } else {
X			DEBUG2("received sig %d, killing %d\n",sig, pid);
X			kill (pid, sig);	/* we'll exit when child dies*/
X		    }
X		}
X	    }
X	}
X
X	if (*pwd->pw_shell == '\0')
X		pwd->pw_shell = "/bin/sh";
X	(void) setgid((gid_t)pwd->pw_gid);
X	(void) setuid((uid_t)pwd->pw_uid);
X	environ = envinit;
X	strncat(homedir, pwd->pw_dir, sizeof(homedir)-6);
X	strncat(shell, pwd->pw_shell, sizeof(shell)-7);
X	strncat(username, pwd->pw_name, sizeof(username)-9);
X	cp = strrchr(pwd->pw_shell, '/');
X	if (cp)
X		cp++;
X	else
X		cp = pwd->pw_shell;
X	execl(pwd->pw_shell, cp, "-c", cmdbuf, 0);
X	perror(pwd->pw_shell);
X	exit(1);
X}
X
X/*VARARGS1*/
Xerror(fmt, a1, a2, a3)
X	char *fmt;
X	int a1, a2, a3;
X{
X    char buf[BUFSIZ];
X
X    buf[0] = 1;
X    (void) sprintf(buf+1, fmt, a1, a2, a3);
X    (void) t_snd(0, buf, strlen(buf), NULL);
X    sleep (1);	/* make sure remote reads full error msg */
X    if (rfd2) {
X	t_unbind (rfd2);
X	t_close (rfd2);
X    }
X    t_unbind (0);
X    t_close (0);
X}
X
Xgetstr(buf, cnt, err)
X	char *buf;
X	int cnt;
X	char *err;
X{
X	int rcvflags;
X	char c;
X
X	do {
X		if (t_rcv(0, &c, 1, &rcvflags) != 1)
X			exit(1);
X		*buf++ = c;
X		if (--cnt == 0) {
X			error("%s too long\n", err);
X			exit(1);
X		}
X	} while (c != 0);
X}
X
Xcleanup (signo)
Xint signo;
X{
X    if (rfd2) {
X	t_unbind (rfd2);
X	t_close (rfd2);
X    }
X    t_unbind (0);
X    t_close (0);
X    exit (0);
X}
END_OF_rexecd.c
if test 5462 -ne `wc -c <rexecd.c`; then
    echo shar: \"rexecd.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f rmtd.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"rmtd.c\"
else
echo shar: Extracting \"rmtd.c\" \(5515 characters\)
sed "s/^X//" >rmtd.c <<'END_OF_rmtd.c'
X/* $Id: rmtd.c,v 1.1 90/09/19 23:27:26 roger C_1 $
X *
X *	This is a UnixPC STARLAN port of BSD's rmt.
X *	Roger Florkowski
X *	cs.utexas.edu!taliesin!roger
X */
X
X/*
X * Copyright (c) 1983 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice and this paragraph are
X * duplicated in all such forms and that any documentation,
X * advertising materials, and other materials related to such
X * distribution and use acknowledge that the software was developed
X * by the University of California, Berkeley.  The name of the
X * University may not 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 MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X */
X
X#ifndef lint
Xchar copyright[] =
X"@(#) Copyright (c) 1983 Regents of the University of California.\n\
X All rights reserved.\n";
X#endif /* not lint */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#)rmt.c	5.4 (Berkeley) 6/29/88";
X#endif /* not lint */
X
X/*
X * rmtd
X */
X#include <net/sys/tiuser.h>
X#include <stdio.h>
X#include <sgtty.h>
X#include <sys/types.h>
X#include <errno.h>
X#include "rcmds.h"
X
Xint	tape = -1;
X
Xchar	*record;
Xint	maxrecsize = -1;
Xchar	*checkbuf();
X
X#define COUNTMAX	18		/* we'll sleep up to 3 minutes */
X#define TAPEDEVP	"/dev/rft"	/* hack, tape device prefix */
X#define	SSIZE		64
X
Xchar	device[SSIZE];
Xchar	count[SSIZE], mode[SSIZE], pos[SSIZE], op[SSIZE];
X
Xextern	errno, t_errno;
Xchar	*sys_errlist[];
Xchar	resp[BUFSIZ];
X
Xlong	lseek();
X
XFILE	*debug;
X
Xmain(argc, argv)
Xint argc;
Xchar **argv;
X{
X    int rval;
X    char c, ret;
X    int n, i, cc, rcvflags;
X
X    argc--, argv++;
X    if (argc > 0) {
X	debug = fopen(*argv, "w");
X	if (debug == 0)
X	    exit(1);
X	(void) setbuf(debug, (char *)0);
X    }
X    DEBUG1("rmtd [%d] started\n", getpid());
X    /* sync up starlan communications */
X    if ((ret = t_sync(0)) != T_DATAXFER) {
X	DEBUG1("t_sync returned wrong state [%d]", ret);
X	exit(1);
X    }
Xtop:
X    errno = 0;
X    rval = 0;
X    if (t_rcv(0, &c, 1, &rcvflags) != 1) {
X	DEBUG("stream read error, terminating\n");
X/*	t_snddis (0, NULL);	/* probably already disconnected */
X	if (debug)
X	    close (debug);
X	exit(0);
X    }
X
X    switch (c) {
X
X	/* open device request */
X	case 'O':
X	    {
X		int count, tpdevice;
X
X		count = 0;
X		if (tape >= 0)
X			(void) close(tape);
X		getstring(device); getstring(mode);
X		tpdevice = !strncmp (TAPEDEVP, device, strlen(TAPEDEVP));
X		DEBUG2("rmtd: O %s %s\n", device, mode);
Xopenagain:
X		errno = 0;
X		tape = open(device, atoi(mode));
X
X		/* tape retension hack */
X		if (tpdevice &&  errno == EBUSY) {
X		    DEBUG("device is busy.  Sleep wait\n");
X		    sleep (10);
X		    count++;
X		    if (count < COUNTMAX)
X			goto openagain;
X		}
X		if (tape < 0)
X			goto ioerror;
X		goto respond;
X	    }
X
X	/* close device request */
X	case 'C':
X		DEBUG("rmtd: C\n");
X		getstring(device);		/* discard */
X		if (close(tape) < 0)
X			goto ioerror;
X		tape = -1;
X		goto respond;
X
X	/* seek request */
X	case 'L':
X		getstring(count); getstring(pos);
X		DEBUG2("rmtd: L %s %s\n", count, pos);
X		rval = lseek(tape, (long) atoi(count), atoi(pos));
X		if (rval < 0)
X			goto ioerror;
X		goto respond;
X
X	/* write request */
X	case 'W':
X		errno = 0;
X		getstring(count);
X		n = atoi(count);
X		DEBUG1("rmtd: W %s\n", count);
X		record = checkbuf(record, n);
X
X		/* read async chunks from stream */
X		for (i = 0; i < n; i += cc) {
X			cc = t_rcv (0, &record[i], n - i, &rcvflags);
X			if (cc <= 0) {
X				DEBUG("rmtd: premature eof\n");
X				exit(2);
X			}
X		}
X		rval = write(tape, record, n);
X		if (rval < 0 || errno == ENXIO)
X			goto ioerror;
X		goto respond;
X
X	/* read request */
X	case 'R':
X		errno = 0;
X		getstring(count);
X		DEBUG1("rmtd: R %s\n", count);
X		n = atoi(count);
X		record = checkbuf(record, n);
X		rval = read(tape, record, n);
X		if (rval < 0 || errno == ENXIO)
X			goto ioerror;
X		(void) sprintf(resp, "A%d\n", rval);
X		DEBUG1("rmtd: A %d\n", rval);
X		if (t_snd (0, resp, strlen(resp), NULL) <= 0)
X		    goto ioerror;
X		if (rval)	/* change of media, rval might == 0 */
X		    if (t_snd (0, record, rval, NULL) <= 0)
X			goto ioerror;
X		goto top;
X
X	default:
X		DEBUG1("rmtd: garbage command %c\n", c);
X		t_snddis (0, NULL);
X		if (debug)
X		    close (debug);
X		exit(3);
X	}
Xrespond:
X	DEBUG1("rmtd: A %d\n", rval);
X	(void) sprintf(resp, "A%d\n", rval);
X	if (t_snd (0, resp, strlen(resp), NULL) < 0)
X	    goto ioerror;
X	goto top;
Xioerror:
X	/* check on starlan communications */
X	if ((ret = t_getstate(0)) != T_DATAXFER) {
X	    DEBUG1("t_getstate returned wrong state [%d]\n", ret);
X	    if (debug)
X		close (debug);
X	    exit(1);
X	}
X	error(errno);
X	goto top;
X}
X
Xgetstring(bp)
X	char *bp;
X{
X	int i;
X	char *cp = bp;
X
X	for (i = 0; i < SSIZE; i++) {
X		if (read(0, cp+i, 1) != 1)
X			exit(0);
X		if (cp[i] == '\n')
X			break;
X	}
X	cp[i] = '\0';
X}
X
Xchar *
Xcheckbuf(record, size)
X	char *record;
X	int size;
X{
X	extern char *malloc();
X
X	if (size <= maxrecsize)
X		return (record);
X	if (record != 0)
X		free(record);
X	record = malloc(size);
X	if (record == 0) {
X		DEBUG("rmtd: cannot allocate buffer space\n");
X		exit(4);
X	}
X	maxrecsize = size;
X	return (record);
X}
X
Xerror(num)
X	int num;
X{
X
X	DEBUG3("rmtd: E %d t_errno=%d (%s)\n", num, t_errno, sys_errlist[num]);
X	(void) sprintf(resp, "E%d\n%s\n", num, sys_errlist[num]);
X	(void) t_snd(0, resp, strlen (resp), NULL);
X}
END_OF_rmtd.c
if test 5515 -ne `wc -c <rmtd.c`; then
    echo shar: \"rmtd.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f rshd.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"rshd.c\"
else
echo shar: Extracting \"rshd.c\" \(5817 characters\)
sed "s/^X//" >rshd.c <<'END_OF_rshd.c'
X/* $Id: rshd.c,v 1.1 90/09/19 23:27:27 roger C_1 $
X *
X *	This is a UnixPC STARLAN port of BSD's rshd.
X *	Roger Florkowski
X *	cs.utexas.edu!taliesin!roger
X */
X
X/*
X * Copyright (c) 1983, 1988 The Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice and this paragraph are
X * duplicated in all such forms and that any documentation,
X * advertising materials, and other materials related to such
X * distribution and use acknowledge that the software was developed
X * by the University of California, Berkeley.  The name of the
X * University may not 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 MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X */
X
X#ifndef lint
Xchar copyright[] =
X"@(#) Copyright (c) 1983, 1988 The Regents of the University of California.\n\
X All rights reserved.\n";
X#endif /* not lint */
X
X#ifndef lint
Xstatic char sccsid[] = "@(#)rshd.c	5.17.1.2 (Berkeley) 2/7/89";
X#endif /* not lint */
X
X/*
X * remote shell server:
X *	[port]\0		* 0 == no, 1 == yes.  unixpc hack *
X *	remhost\0		* unixpc starlan hack *
X *	remuser\0
X *	locuser\0
X *	command\0
X *	data
X */
X#include <net/sys/tiuser.h>
X#include <net/sys/stropts.h>
X#include <sys/param.h>
X#include <sys/utsname.h>
X
X#include <stdio.h>
X#include <pwd.h>
X#include <signal.h>
X#include "rcmds.h"
X
Xextern errno, t_errno;
X
Xtypedef int		gid_t;	/* missing from types.h */
Xtypedef int		uid_t;
X
Xchar	*strrchr(), *strncat();
X/*VARARGS1*/
Xint	error();
Xint	cleanup();
XFILE *debug;
X
X/*ARGSUSED*/
Xmain(argc, argv)
X	int argc;
X	char **argv;
X{
X#ifdef DO_DEBUG
X    debug = fopen("/tmp/rshd.out", "a");
X    if (debug == 0)
X	exit(1);
X    (void) setbuf(debug, (char *)0);
X#endif
X    DEBUG1("rshd [%d] started\n", getpid());
X    /* sync up starlan communications */
X    if (t_sync(0) != T_DATAXFER) 
X	exit(1);
X
X    doit();
X}
X
Xchar	username[64] = "LOGNAME=";
Xchar	homedir[64] = "HOME=";
Xchar	shell[64] = "SHELL=";
Xchar	*envinit[] = {
X	    homedir,
X	    shell, 
X	    "PATH=/bin:/usr/bin:/usr/local/bin:/usr/lbin:/usr/net/bin:", 
X	    username,
X	    0
X	};
Xextern	char	**environ;
Xint rfd2;
X
Xdoit()
X{
X	char cmdbuf[NCARGS+1], buf[BUFSIZ], *cp;
X	char c, sig, locuser[16], remuser[16], hostname[16];
X	struct passwd *pwd;
X	int pid, cc, rcvflags;
X
X	(void) signal(SIGINT, SIG_DFL);
X	(void) signal(SIGQUIT, SIG_DFL);
X	(void) signal(SIGTERM, SIG_DFL);
X	(void) signal(SIGCLD, cleanup);
X
X	/* read initial char from remote.  If our char != 0, then the
X	 * remote wants to establish a second connection to us for
X	 * signal monitoring.
X	 */
X	if ((cc = t_rcv (0, &c, 1, &rcvflags)) != 1) {
X	    t_unbind (0);
X	    t_close (0);
X	    exit (1);
X	}
X	if (c != 0) 
X	    if ((rfd2 = signalPort (0, RSHD_PORT)) < 0) {
X		DEBUG2("signalPort failed. errno %d, t_errno %d\n",
X			errno, t_errno);
X		cleanup (0);
X	    }
X
X	getstr(hostname, sizeof(hostname), "remhost");	/* unixpc Hack */
X	getstr(remuser, sizeof(remuser), "remuser");
X	getstr(locuser, sizeof(locuser), "locuser");
X	getstr(cmdbuf, sizeof(cmdbuf), "command");
X
X	setpwent();
X	pwd = (struct passwd *)getpwnam(locuser);
X	if (pwd == NULL) {
X		error("Login incorrect.\n");
X		exit(1);
X	}
X	endpwent();
X	if (chdir(pwd->pw_dir) < 0) {
X		(void) chdir("/");
X		error("No remote directory.\n");
X		exit(1);
X	}
X
X	if (pwd->pw_passwd != 0 && *pwd->pw_passwd != '\0' &&
X	    ruserok(hostname, pwd->pw_uid == 0, remuser, locuser) < 0) {
X		error("Permission denied.\n");
X		exit(1);
X	}
X
X	if (pwd->pw_uid && !access("/etc/nologin", 00)) {
X		error("Logins currently disabled.\n");
X		exit(1);
X	}
X	/* write ack */
X	(void) t_snd(0, "\0", 1, NULL);
X
X	if (rfd2) {
X	    pid = fork();
X	    if (pid == -1)  {
X		error("Try again.\n");
X		exit(1);
X	    }
X	    /* signal Monitor.  Parent hangs out, sole purpose 
X	     * is to wait for a kill signal from the remote.
X	     */
X	    if (pid) {
X
X		for (;;) {
X		    DEBUG("signald, waiting to receive\n");
X		    if (t_rcv (rfd2, &sig, 1, &rcvflags) < 0) {
X			DEBUG2("t_rcv failed, errno %d, t_errno %d\n",
X				errno, t_errno);
X			if (t_errno == TLOOK) {
X			    int look;
X			    if (!(look = t_look (rfd2))) 
X				DEBUG1("t_look returned %d\n", look);
X			}
X			kill (pid, 9);	/* rude and abrupt.  Too bad */
X			cleanup (0);
X		    } else {
X			DEBUG2("received sig %d, killing %d\n",sig, pid);
X			kill (pid, sig);	/* we'll exit when child dies*/
X		    }
X		}
X	    }
X	}
X
X	if (*pwd->pw_shell == '\0')
X		pwd->pw_shell = "/bin/sh";
X	(void) setgid((gid_t)pwd->pw_gid);
X	(void) setuid((uid_t)pwd->pw_uid);
X	environ = envinit;
X	strncat(homedir, pwd->pw_dir, sizeof(homedir)-6);
X	strncat(shell, pwd->pw_shell, sizeof(shell)-7);
X	strncat(username, pwd->pw_name, sizeof(username)-9);
X	cp = strrchr(pwd->pw_shell, '/');
X	if (cp)
X		cp++;
X	else
X		cp = pwd->pw_shell;
X	sleep (1);
X	execl(pwd->pw_shell, cp, "-c", cmdbuf, 0);
X	perror(pwd->pw_shell);
X	cleanup (0);
X	/* NOTREACHED */
X}
X
X/*VARARGS1*/
Xerror(fmt, a1, a2, a3)
X	char *fmt;
X	int a1, a2, a3;
X{
X    char buf[BUFSIZ];
X
X    buf[0] = 1;
X    (void) sprintf(buf+1, fmt, a1, a2, a3);
X    (void) t_snd(0, buf, strlen(buf), NULL);
X    sleep (1);	/* make sure remote reads full error msg */
X    if (rfd2) {
X	t_unbind (rfd2);
X	t_close (rfd2);
X    }
X    t_unbind (0);
X    t_close (0);
X}
X
Xgetstr(buf, cnt, err)
X	char *buf;
X	int cnt;
X	char *err;
X{
X	int rcvflags;
X	char c;
X
X	do {
X		if (t_rcv(0, &c, 1, &rcvflags) != 1)
X			exit(1);
X		*buf++ = c;
X		if (--cnt == 0) {
X			error("%s too long\n", err);
X			exit(1);
X		}
X	} while (c != 0);
X}
X
Xcleanup (signo)
Xint signo;
X{
X    if (rfd2) {
X	t_unbind (rfd2);
X	t_close (rfd2);
X    }
X    t_unbind (0);
X    t_close (0);
X    exit (0);
X}
END_OF_rshd.c
if test 5817 -ne `wc -c <rshd.c`; then
    echo shar: \"rshd.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 2 \(of 3\).
cp /dev/null ark2isdone
MISSING=""
for I in 1 2 3 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 3 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0

-- 
Roger Florkowski                                 ~!cs.utexas.edu!taliesin!roger



More information about the Comp.sys.att mailing list