[comp.sys.m6809] dcp bugs in last source/ fixes

sampson@killer.UUCP (Steve Sampson) (05/08/88)

The last posting by Pete contained some bugs.  The program was tested
so far in slave mode.  Still debugging master (connection problems).


#! /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 shell archive."
# Contents:  Makefile README uucp.h uucico.c mail.c rmail.c uuxqt.c
# Wrapped by sampson@killer on Sat May  7 21:42:47 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f Makefile -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"Makefile\"
else
echo shar: Extracting \"Makefile\" \(1732 characters\)
sed "s/^X//" >Makefile <<'END_OF_Makefile'
X#
X#	Makefile for Unix(tm) <-> UniFLEX(tm) Mail
X#
X#	+O is for Optimize, +Q is for don't align on quad word boundry.
X#
X#	You should be super-user when running this!
X#
X#	This is for GIMIX Micro-20 68020 UniFLEX
X#
X
XCFLAGS	= +OQ
X
Xinstall:
X	move /usr/bin/mail /usr/bin/lmail
X	perms o-w u+rwx s+ /usr/bin/lmail
X	owner system /usr/bin/lmail
X	/etc/addusr uucp
X	crdir /gen/spooler/uucp
X	crdir /gen/spooler/uucp/.Log
X	owner uucp /gen/spooler/uucp /gen/spooler/uucp/.Log
X	move .Systems /gen/spooler/uucp
X	move .Devices /gen/spooler/uucp
X	move .Config /gen/spooler/uucp
X	owner uucp /gen/spooler/uucp/.Systems
X	owner uucp /gen/spooler/uucp/.Devices
X	owner uucp /gen/spooler/uucp/.Config
X	make uucico
X	make uuxqt
X	make mail
X	make rmail
X#	make strip
X#	make clean
X	echo "++\n++ Now edit the password file. Change the 'uucp' default\n"
X	echo "++ shell to 'uucico slave'\n++\n"
X
Xuucico:	uucico.r
X	cc $(CFLAGS) uucico.r +o=/etc/uucico
X	owner uucp /etc/uucico
X	perms o-rwx u+rwx s+ /etc/uucico
X
Xuuxqt:	uuxqt.r
X	cc $(CFLAGS) uuxqt.r +o=/etc/uuxqt
X	owner uucp /etc/uuxqt
X	perms o-rwx u+rwx s+ /etc/uuxqt
X
Xmail:	mail.r
X	cc $(CFLAGS) mail.r +o=/usr/bin/mail
X	owner system /usr/bin/mail
X	perms o-w o+rx u+rwx /usr/bin/mail
X
Xrmail:	rmail.r
X	cc $(CFLAGS) rmail.r +o=/usr/bin/rmail
X	owner uucp /usr/bin/rmail
X	perms o-w o+rx u+rwx s+ /usr/bin/rmail
X
X#
X#	Get rid of symbol table from binaries when debugging complete
X#
Xstrip:
X	strip /etc/uucico /etc/uuxqt /usr/bin/mail /usr/bin/rmail
X
X#
X#	Remove the object files from the work directory
X#
Xclean:
X	kill *.r
X
X#
X#	Dependencies
X#
Xuucico.r: uucico.c uucp.h
Xuuxqt.r:  uuxqt.c uucp.h
Xmail.r:   mail.c uucp.h
Xrmail.r:  rmail.c uucp.h
X
X# EOF
X
END_OF_Makefile
echo shar: 1 control character may be missing from \"Makefile\"
if test 1732 -ne `wc -c <Makefile`; then
    echo shar: \"Makefile\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f README -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"README\"
else
echo shar: Extracting \"README\" \(3781 characters\)
sed "s/^X//" >README <<'END_OF_README'
X
X		    Unix to UniFLEX Mail Machine
X		       Version 2.3, May 1988
X			   S. R. Sampson
X
X
XThis archive of files is the basis for sending mail from a UniFLEX(tm)
Xoperating system to the Unix(tm) operating system, using the uucp 'G'
XProtocol.  It is based on the DCP program by Richard Lamb as posted on
XUsenet.
X
XThe files are:
X
XREADME		This file
Xuucp1.doc	An information file on the G protocol
Xuucp2.doc	An information file on Unix UUCP
XMakefile	All encompassing build instructions
Xuucp.h		Header file for Operating System specifics
Xmail.c		Remote/Local mail front-end
Xrmail.c		Remote mail work file generator (simple bang mode)
Xuucico.c	G Protocol dialup machine
Xuuxqt.c		Work file execution machine
X.Systems	A sample dialing directory
X.Devices	A sample dialing port setup
X.Config		A sample configuration setup
X
X
XI've been doing some minor testing on this code and would like others to
Xplay around and improve it.  It may be an useful start for other machines.
X
XPut the files in a source code directory and simply execute 'make'.
XThis will almost completely build the mail machine.  You will have to
Xmanualy edit the /etc/log/password file to change the default shell to
X'/etc/uucico'.  Then run 'password uucp' and assign the account a password.
XFollowing that, find a Unix machine to talk to and setup the .Config,
X.Systems, and .Devices files for your serial ports.
X
XThe format for the .Devices file is:
X
X/dev/ttyxx Baudrate Type Status
X
XWhere:	xx is the TTY number
X	Baudrate is the setting of the port
X	Type is MODEM or DIRECT
X	Status is FREE or USED
X
XYou initially create the file with everything FREE.  I'm using a GMX Micro-20
Xand have it set up like so:
X
X/dev/tty03 1200 MODEM FREE
X/dev/tty02 2400 DIRECT FREE
X/dev/tty01 2400 DIRECT FREE
X
XThe format for the .Systems file is:
X
XMachine-Name Call-Time Baudrate Type Dialup-Sequence
X
XWher:	Machine-name is 6 character significance
X	Call-Time is Any (Not implemented)
X	Baudrate is the machines (or your modems) maximum speed
X	Type is MODEM or DIRECT which is used when looking for a port
X	Dialup-Sequence is a send/receive sequence for logging on
X
XThe format for the .Config file is:
X
XUser-Name	(The owner of the files (eg. 'uucp'))
XMachine-Name	(6 character significance (eg. 'test'))
XError-Name	(Who gets mail when problems are found (eg. 'root', 'system'))
X
X
XThe uucp directory will contain all the work files to be sent and received.
XThe log file will contain information written by the programs as they run.
XThis information can be useful when debugging.  Remember to purge this stuff
Xwhen disk space starts filling up.
X
XThis UniFLEX version will automatically run in the slave mode upon login to
Xthe uucp account.  An example cron entry to run uucico in the master mode with
Xa debug level 9 would look like so:
X
X0 * * * * /etc/uucico master 9
X
XIf you have problems check on all permissions and ownership:
X
X/usr/bin/mail			system	 rwxr-x
X/usr/bin/lmail			system	 rwxr-x	SUID
X/usr/bin/rmail			uucp	 rwxr-x	SUID
X/etc/uucico			uucp	 rwx---	SUID
X/etc/uuxqt			uucp	 rwx--- SUID
X/gen/spooler/uucp		uucp	drwxr-x
X/gen/spooler/uucp/.Log		uucp	drwx---
X/gen/spooler/uucp/.Systems	uucp	 rw----
X/gen/spooler/uucp/.Devices	uucp	 rw----
X/gen/spooler/uucp/.Config	uucp	 rw----
X
XSometimes the .Devices file may become corrupt.  Make sure you view it for
Xproblems such as no FREE device, or missplaced writes.
X
XTo send remote mail try something like:
X
Xmail myconnect!ihnp4!killer!sampson
XThis is a test
X[] <- Type a Control-D for EOF and mail will be spooled.
X
XWhere myconnect is the name of the Unix machine you dial up.
X
Xsampson@killer.UUCP	ihnp4!killer!sampson
XSteve Sampson, Box 45668 (AWACS), Tinker AFB, OK 73145
X
X/* EOF */
X
END_OF_README
echo shar: 1 control character may be missing from \"README\"
if test 3781 -ne `wc -c <README`; then
    echo shar: \"README\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f uucp.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"uucp.h\"
else
echo shar: Extracting \"uucp.h\" \(1045 characters\)
sed "s/^X//" >uucp.h <<'END_OF_uucp.h'
X/*
X *	uucp.h
X *
X *	Header file for Unix(tm) to UniFLEX(tm) mail machine
X */
X
X/*
X *	Spool Directory
X */
X
X#define SPOOLDIR	"/gen/spooler/uucp"
X
X/*
X *	Configuration file (in spooldir directory) format
X *
X *	1.	user			uucp
X *	2.	myname			test
X *	3.	errorname		system
X */
X
X#define	CONFIG		"/gen/spooler/uucp/.Config"
X
X/*
X *	Systems file (in spooldir directory) format
X *
X *	1.	rmtname		ihnp4
X *	2.	cctime		2300-2359
X *	3.	ttype		MODEM
X *	4.	tspeed		2400
X *	5.	loginseq	xx gin: uucp\n sword: secret\n
X */
X
X#define	SYSTEMS		".Systems"	/* file with calling info	     */
X
X/*
X *	Devices file (in spooldir directory) format
X *
X *	1.	Name		/dev/ttyxx
X *	2.	Max-Speed	75 - 19200 Baud
X *	3.	Type		MODEM or DIRECT
X *	4.	Status		USED or FREE
X */
X
X#define	DEVICES		".Devices"	/* file with terminal info	     */
X
X
X/*
X *	Error log files (relative to spooldir)
X */
X
X#define	SYSLOG		".Log/uucico"	/* error log file for uucico	     */
X#define	XQTLOG		".Log/uuxqt"	/* error log file for uuxqt	     */
X
X/* EOF */
X
END_OF_uucp.h
echo shar: 1 control character may be missing from \"uucp.h\"
if test 1045 -ne `wc -c <uucp.h`; then
    echo shar: \"uucp.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f uucico.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"uucico.c\"
else
echo shar: Extracting \"uucico.c\" \(41611 characters\)
sed "s/^X//" >uucico.c <<'END_OF_uucico.c'
X/*
X *      uucico.c
X *
X *      Copy In - Copy Out 'G' Protocol
X *
X *      68020 UniFLEX(tm) Version 2.3, May 1988
X *
X *      Based on dcp.c Copyright (c) 1985, 1986, 1987 by Richard H. Lamb
X *      Changes are Public Domain by S. R. Sampson
X *
X *      Called by 'cron', 'at', or 'uucp login'.
X *
X *      Define DEBUG to prevent unlinking of C. files
X */
X
X/* Includes */
X
X#include "uucp.h"
X
X#include <sys/signal.h>
X#include <sys/sgtty.h>
X#include <sys/modes.h>
X#include <sys/dir.h>
X#include <string.h>
X#include <setjmp.h>
X#include <errno.h>
X#include <ctype.h>
X#include <stdio.h>
X#include <time.h>
X#include <pwd.h>
X
X/* General purpose defines */
X
X#define FALSE           0
X#define TRUE            ~FALSE
X
X#define ERROR           FALSE
X#define OK              TRUE
X
X#define MAXLINE         132
X#define MAXLOGTRY         4
X#define MSGTIME          20
X#define MAXTRY            5
X#define PKTTIME          10
X#define PKTSIZE          64
X#define PKTSIZ2           2
X#define HDRSIZE           6
X#define WNDSIZE           1
X#define DLE              16
X
X/* Main Switching states */
X
X#define INITIAL         000
X#define DEVICE          001
X#define LOGIN           002
X#define HANDSHAKE       003
X#define MASTER          004
X#define SLAVE           005
X#define END             006
X#define ABORT           007
X
X/* Master/Slave states */
X
X#define MS_INIT         020
X#define MS_SCANDIR      021
X#define MS_SEND         022
X#define MS_HANGUP       023
X#define MS_RECEIVE      024
X#define MS_ABORT        025
X#define MS_CHKWORK      026
X#define MS_END          027
X
X/* Switching States */
X
X#define SS_HEADER       030
X#define SS_DATA         031
X#define SS_EOF          032
X#define SS_END          033
X#define SS_ABORT        034
X
X/*
X *      Control Packet Defines
X *
X *      xxx     name    yyy
X *
X *      001     CLOSE   n/a
X *      002     RJ      last correctly received sequence number
X *      004     RR      last correctly received sequence number
X *      005     INITC   window size
X *      006     INITB   data seqment size
X *      007     INITA   window size
X */
X
X#define DATA            000     /* The packet is data */
X#define CLOSE           001     /* CLOSE, Comunications complete */
X#define RJ              002     /* RJ Reject, detected an error */
X#define RR              004     /* RR Receiver ready, detected no errors */
X#define INITC           005
X#define INITB           006
X#define INITA           007
X
X#define MODEM           000     /* TTY device types */
X#define DIRECT          001
X
X/* Global Variables */
X
Xstruct passwd   *pw;
X
Xstruct  {
X        int     baudrate;
X        char    *code;
X} rates[] = {                   /* what I use the most */
X    B300,       "300",
X    B1200,      "1200",
X    B2400,      "2400",
X    B9600,      "9600",
X    B19200,     "19200",
X    0,          ""
X};
X
X#define DEFAULT_BAUD    B1200
X
Xstruct  sgttyb  NewSetting,
X                OldSetting;
X
Xlong    Dpos;
X
XFILE    *fd,
X        *fdC,
X        *log,
X        *input,
X        *output;
X
Xint     type,
X        size,
X        pkrec,
X        pksent,
X        pknerr,
X        master,
X        debug_level;
X
Xchar    InPacket[PKTSIZE],
X        OutPacket[PKTSIZE],
X        Filename[MAXLINE],
X        Cfilename[MAXNAMLEN+1],         /* defined in dir.h */
X        Loginseq[64],
X        Rmtname[8],
X        Device[16],
X        myname[8],
X        user[8],
X        speed[8];
X
Xchar    *rcverr[] = {
X        "Input Buffer Empty",
X        "Bad Header",
X        "Packet Timeout",
X        "Checksum Error",
X        "Wrong Packet Size"
X};
X
X/* Forward Declarations */
X
Xunsigned checksum();
Xchar     *mfgets(), *gtime();
Xjmp_buf  env;
X
X/*
X *      Usage:
X *        uucico mode debug
X *
X *        Where mode is 'master' or 'slave'
X *        And debug is an integer from 0 to 9
X *
X *        Defaults are slave mode and level 0 debug
X */
X
Xmain(argc, argv)
Xint     argc;
Xchar    **argv;
X{
X        register int    state;
X
X        /*
X         *      Read Configuration file
X         *
X         *      The UniFLEX 2.3 C Compiler would not compile this
X         *      correctly from an include file.
X         */
X
X#undef CONFIG
X#define CONFIG "/gen/spooler/uucp/.Config"
X
X        if ((log = fopen(CONFIG, "r")) != (FILE *)NULL)  {
X                mfgets(user, sizeof user, log);
X                mfgets(myname, sizeof myname, log);
X                fclose(log);
X        }
X        else
X                exit(1);
X
X        /*
X         *      Change to the spool directory
X         */
X
X        chdir(SPOOLDIR);
X
X        /*
X         *      Open the error log file
X         */
X
X        log = fopen(SYSLOG, "w");
X        setbuf(log, (char *)NULL);      /* log file should be unbuffered */
X
X        /*
X         *      Setup defaults
X         */
X
X        master = FALSE;
X        debug_level = 0;
X        fd = fdC = (FILE *)NULL;
X
X        /*
X         *      Process the two command line arguments
X         *      The first is "master" or "slave", the second
X         *      is an integer debug level between 0 and 9.
X         */
X
X        if (argc > 1 && strcmp(argv[1], "master") == 0)
X                master = TRUE;
X
X        if (argc > 2)  {
X                debug_level = abs(atoi(argv[2]));
X                if (debug_level > 9)
X                        debug_level = 9;
X        }
X
X        state = INITIAL;
X        while (TRUE)  {
X                switch(state)  {
X                        case INITIAL:
X                                if (master)
X                                        state = GetSystem();
X                                else
X                                        state = HandShake();
X                                break;
X                        case DEVICE:
X                                state = GetTTY();
X                                if (state == ABORT)
X                                  fprintf(log,"Main(): No Device Available %s",
X                                                        gtime());
X                                break;
X                        case LOGIN:
X                                state = Login();
X                                break;
X                        case HANDSHAKE:
X                                state = HandShake();
X                                break;
X                        case MASTER:
X                                state = Master();
X                                break;
X                        case SLAVE:
X                                state = Slave();
X                                break;
X                        case END:
X                                state = SendOO();
X                }
X
X                if (state == ABORT)
X                        break;
X        }
X
X        if (master)
X                CloseTTY();
X
X        fclose(log);
X
X        /* go execute any transfered work files */
X
X        execl("/etc/uuxqt", "uuxqt", (char *)NULL);
X}
X
X
X/*-------------------------
X *      uucico Subroutines
X *-------------------------
X */
X
XGetReply(string)
Xregister char   *string;
X{
X        register int    i, len;
X        char            c[MAXLINE];
X
X        len = strlen(string);
X        c[len--] = 0;
X
X        while (strcmp(string, c) != 0)  {
X                for (i = 0; i < len; i++)
X                        c[i] = c[i+1];
X
X                if (ReadTTY(&c[i], 1, MSGTIME) == 0)  {
X                       fprintf(log,"GetReply(): Input timed out %s", gtime());
X                       fprintf(log," Wanted %s got %s\n", string, c);
X                       return ERROR;
X                }
X
X                toascii(c[i]);
X        }
X
X        return OK;
X}
X
X
X/*
X *      mfgets (modified fgets)
X *
X *      Same as fgets() only this version deletes '\n'
X */
X
Xchar *mfgets(s, n, iop)
Xregister char   *s;
Xregister int    n;
Xregister FILE   *iop;
X{
X        register int    c;
X        register char   *cs;
X
X        cs = s;
X        while (--n > 0 && (c = getc(iop)) != EOF)  {
X                if (c == 0x0D)  {
X                        *cs = '\0';
X                        break;
X                }
X                else
X                        *cs++ = c;
X        }
X
X        return((c == EOF && cs == s) ? (char *)NULL : s);
X}
X
X
Xchar *gtime()
X{
X        long    value;
X
X        time(&value);
X        return(ctime(&value));
X}
X
X
XCheckName()
X{
X        register FILE   *fdsys;
X        char            line[MAXLINE], tmp[16];
X
X        if ((fdsys = fopen(SYSTEMS, "r")) == NULL)  {
X                fprintf(log,"CheckName(): Can't open %s %s", SYSTEMS, gtime());
X                return ERROR;
X        }
X
X        while (mfgets(line, sizeof line, fdsys) != (char *)NULL)  {
X                sscanf(line, "%s ", tmp);
X
X                if (strncmp(Rmtname, tmp, 6) == 0)  {
X                        fclose(fdsys);
X                        return OK;
X                }
X        }
X
X        fclose(fdsys);
X        fprintf(log, "CheckName(): Unknown system %s attempted login %s",
X                                Rmtname, gtime());
X        return ERROR;
X}
X
X
XCheckTime(time)
Xregister char   *time;
X{
X        return OK;
X}
X
X
X/*-------------------------------------------------
X *      uucico High Level State Switching routines
X *-------------------------------------------------
X */
X
XGetSystem()
X{
X        register FILE   *fdsys;
X        char            line[MAXLINE], ttype[8], cctime[16];
X
X        if ((fdsys = fopen(SYSTEMS, "r")) == NULL)  {
X                fprintf(log,"GetSystem(): Can't open %s %s", SYSTEMS, gtime());
X                return ABORT;
X        }
X
X        do {
X                if (fgets(line, sizeof line, fdsys) == (char *)NULL)  {
X                        fclose(fdsys);
X                        return ABORT;           /* no more systems */
X                }
X
X                sscanf(line, "%s %s %s %s %s",
X                        Rmtname, cctime, ttype, speed, Loginseq);
X                type = strcmp(ttype, "MODEM") ? DIRECT : MODEM;
X        } while ( !strcmp(cctime, "Slave") || !CheckTime(cctime) );
X
X        fclose(fdsys);
X
X        return DEVICE;                  /* go get a device and login */
X}
X
X
X/*
X *      Find the next device of the type and speed requested
X *      in the DEVICES file
X */
X
XGetTTY()
X{
X        register FILE   *fdtty;
X        int             Type, Used;
X        char            line[MAXLINE], Types[8], Useds[8], Bauds[8];
X
X        if ((fdtty = fopen(DEVICES, "r+")) == (FILE *)NULL)  {
X                fprintf(log,"GetTTY(): Can't open %s %s", DEVICES, gtime());
X                return ABORT;
X        }
X
X        do  {
X                if (mfgets(line, sizeof line, fdtty) == (char *)NULL)  {
X                        fprintf(log,"GetTTY(): No devices available %s",
X                                                        gtime());
X                        fclose(fdtty);
X                        return ABORT;
X                }
X
X                sscanf(line, "%s %s %s %s", Device, Bauds, Types, Useds);
X                Type = strcmp(Types, "MODEM") ? DIRECT : MODEM;
X                Used = strcmp(Useds, "FREE");
X        } while (Type != type || strcmp(Bauds, speed) || Used);
X
X        /*
X         *      This is a hack until I figure out what I'm doing...
X         */
X
X        fseek(fdtty, -5L, 1);
X        Dpos = ftell(fdtty);            /* Dpos is used in CloseTTY() */
X        fputs("USED", fdtty);
X        fclose(fdtty);
X
X        if (OpenTTY() == ERROR)
X                return ABORT;
X
X        return LOGIN;
X}
X
X
XLogin()
X{
X        register int    k, j, trys;
X        register char   *last;
X        char            buffer[MAXLINE];
X        int             flag;
X
X        j = k = 0;
X
X        /*
X         *      First move everything to 'buffer', changing text
X         *      newlines to binary
X         */
X
X        while(Loginseq[j] != '\0')  {
X                if (Loginseq[j] == '\\' && Loginseq[j+1] == 'n')  {
X                        buffer[k++] = '\n';
X                        j += 2;
X                        continue;
X                }
X
X                buffer[k++] = Loginseq[j++];
X        }
X
X        buffer[k] = j = 0;
X        flag = TRUE;    /* start by sending */
X
X        while (buffer[j])  {
X                k = j;
X
X                while (buffer[k] != '-' && buffer[k] != '\0')
X                        k++;
X
X                if (buffer[k] == '\0')
X                        buffer[k+1] = '\0';
X
X                buffer[k] = '\0';
X
X                if (flag)  {
X                        last = &buffer[j];
X                        WriteString(&buffer[j], FALSE);
X                        flag = FALSE;
X                } else  {
X                        trys = 1;
X                        while (GetReply(&buffer[j]) == ERROR)  {
X                           if (trys >= MAXLOGTRY)  {
X                              fprintf(log,"Login(): Failed login on remote %s",
X                                                                gtime());
X                              return ABORT;
X                           }
X
X                           /* try resending the last sequence */
X
X                           trys++;
X                           WriteString(last, FALSE);
X                        }
X
X                        flag = TRUE;
X                }
X
X                j = k + 1;
X        }
X
X        return HANDSHAKE;
X}
X
X
XHandShake()
X{
X        char    t1[16], t2[16];
X
X        if (master)  {
X                if (ReadString(InPacket, MSGTIME) == 0)
X                        return ABORT;
X
X                if (strncmp(InPacket + 6, Rmtname, 6))  {
X                        fprintf(log,"HandShake(): System name match error %s",
X                                                gtime());
X                        return ABORT;
X                }
X
X                sprintf(OutPacket, "S%.6s", myname);
X                WriteString(OutPacket, TRUE);
X
X                if (ReadString(InPacket, MSGTIME) == 0)
X                        return ABORT;
X
X                if (strncmp(InPacket + 1, "OK", 2))  {
Xhserr1:                 fprintf(log,"HandShake(): Don't like name %s",gtime());
X                        return ABORT;
X                }
X
X                if (ReadString(InPacket, MSGTIME) == 0)
X                        return ABORT;
X
X                if (InPacket[0] != 'P' && strchr(InPacket[1], 'g') == 0)  {
X                        WriteString("UN", TRUE);
Xhserr2:                 fprintf(log,"HandShake(): G Protocol not available %s",
X                                                        gtime());
X                        return ABORT;
X                }
X
X                WriteString("Ug", TRUE);
X                return MASTER;
X        } else {
X                input = stdin;
X                output = stdout;
X
X                SetTTY(fileno(input), 0);
X                SetTTY(fileno(output), 0);
X
X                sprintf(OutPacket, "Shere=%.6s", myname);
X                WriteString(OutPacket, TRUE);
X
X                if (ReadString(InPacket, MSGTIME) == 0)
X                        return ABORT;
X
X                sscanf(InPacket, "S%s %s %s", Rmtname, t1, t2);
X                sscanf(t2, "-x%d", &debug_level);
X
X                if (CheckName() == ERROR)
X                        goto hserr1;
X
X                WriteString("ROK", TRUE);
X                WriteString("Pg", TRUE);
X
X                if (ReadString(InPacket, MSGTIME) == 0)
X                        return ABORT;
X
X                if (strcmp(InPacket, "Ug") != 0)
X                        goto hserr2;
X
X                return SLAVE;
X        }
X}
X
X
XSendOO()
X{
X        register int    i;
X        char            msg[MAXLINE];
X
X        msg[1] = 0;
X        for (i = 0; ((msg[1] != 'O') && (i < MAXTRY)); i++)  {
X                WriteString("OOOOOO", TRUE);
X
X                if (ReadString(msg, MSGTIME) == 0)
X                        break;
X        }
X
X        if (i == MAXTRY)  {
X                fprintf(log, "SendOO(): Can't \"Over and Out\" with %s %s",
X                  Rmtname, gtime());
X                return ABORT;
X        }
X
X        WriteString("OOOOOO", TRUE);    /* one last time for mama */
X
X        if (master)
X                return INITIAL;
X        else
X                return ABORT;
X}
X
X
X/*---------------------------------------------------
X *      uucico Medium Level State Switching routines
X *---------------------------------------------------
X */
X
XMaster()
X{
X        register int    state;
X
X        state = MS_INIT;
X
X        while (TRUE)  {
X                switch (state)  {
X                case MS_INIT:
X                        state = SendInit();
X                        break;
X                case MS_SCANDIR:
X                        state = ScanDirectory();
X                        break;
X                case MS_SEND:
X                        state = Send();
X                        break;
X                case MS_HANGUP:
X                        state = MasterHangup();
X                        break;
X                case MS_RECEIVE:
X                        state = Receive();
X                        break;
X                case MS_ABORT:
X                        return ABORT;
X                case MS_END:
X                        return END;
X                }
X        }
X}
X
X
XSlave()
X{
X        register int    state;
X
X        state = MS_INIT;
X
X        while (TRUE)  {
X                switch (state)  {
X                case MS_INIT:
X                        state = RcvInit();
X                        break;
X                case MS_RECEIVE:
X                        state = Receive();
X                        break;
X                case MS_CHKWORK:
X                        state = CheckForWork();
X                        break;
X                case MS_HANGUP:
X                        state = SlaveHangup();
X                        break;
X                case MS_SCANDIR:
X                        state = ScanDirectory();
X                        break;
X                case MS_SEND:
X                        state = Send();
X                        break;
X                case MS_ABORT:
X                        return ABORT;
X                case MS_END:
X                        return END;
X                }
X        }
X}
X
X
X/*------------------------------------------------
X *      uucico Low Level State Switching routines
X *------------------------------------------------
X */
X
XSend()
X{
X        register int    state;
X
X        state = SS_HEADER;
X
X        while (TRUE)  {         /* Do this as long as necessary */
X                switch (state)  {
X                case SS_HEADER:
X                        if (fd != (FILE *)NULL)  {
X                                fprintf(log,
X                                  "Send(): File already open in SS_HEADER %s",
X                                    gtime());
X                                state = SS_ABORT;
X                        }
X                        else
X                                state = SendFileHeader();
X                        break;
X                case SS_DATA:
X                        state = SendData();
X                        break;
X                case SS_EOF:
X                        state = SendEof();
X                        break;
X                case SS_END:
X                        fclose(fdC);
X#ifndef DEBUG
X                        unlink(Cfilename);
X#endif
X                        fdC = (FILE *)NULL;
X                        return MS_SCANDIR;
X                case SS_ABORT:
X                        return MS_ABORT;
X                }
X        }
X}
X
X
XReceive()
X{
X        register int    state;
X
X        state = SS_HEADER;
X
X        while (TRUE)  {
X                switch (state)  {
X                case SS_HEADER:
X                        state = RcvFileHeader();
X                        break;
X                case SS_DATA:
X                        state = RcvData();
X                        break;
X                case SS_ABORT:
X                        return MS_ABORT;
X                case SS_END:
X                        return MS_CHKWORK;
X                }
X        }
X}
X
X
XMasterHangup()
X{
X        int     len;
X
X        strcpy(OutPacket, "H");
X        if (SendPacket(OutPacket, PKTSIZE, TRUE) == ERROR)
X                return ABORT;
X
X        if (RcvPacket(InPacket, &len) == ERROR)
X                return ABORT;
X
X        if (strncmp(InPacket, "HN", 2) != 0)
X                return MS_RECEIVE;
X
X        return MS_END;
X}
X
X
XSlaveHangup()
X{
X        strcpy(OutPacket, "HY");
X        SendPacket(OutPacket, PKTSIZE, 2); /* don't wait for Acknowledge */
X        ClosePacket();
X
X        return MS_END;
X}
X
X
XGetFile(header)
Xregister char   *header;
X{
X        register int    i;
X        char            line[MAXLINE];
X
X        if (mfgets(line, sizeof line, fdC) == (char *)NULL)  {
X                fprintf(log,"GetFile(): Unexpected End Of File %s", gtime());
X                return ERROR;
X        }
X
X        sscanf(&line[2], "%s ", Filename);
X
X        for (i = 0; line[i]; i++)
X                if (strncmp(&line[i], "066", 3) == 0)
X                        break;
X
X        line[i+4] = '\0';
X        strcpy(header, line);   /* now contains the whole line up past 066x */
X
X        return OK;
X}
X
X
XCheckForWork()
X{
X        register int    c;
X
X        c = ScanDirectory();
X        if (c == MS_ABORT)
X                return MS_ABORT;
X
X        if (c == MS_SEND)  {
X                strcpy(OutPacket, "HN");
X                if (SendPacket(OutPacket, PKTSIZE, TRUE) == ERROR)
X                        return MS_ABORT;
X                else
X                        return MS_SEND;
X        }
X        else /* c == MS_END */
X                return MS_HANGUP;
X}
X
X
XScanDirectory()
X{
X        register DIR            *dir;
X        register struct direct  *pdir;
X
X        strcpy(Cfilename, "C.");
X        strncat(Cfilename, Rmtname, 6);
X
X        if ((dir = opendir(SPOOLDIR)) == (DIR *)NULL)  {
X                fprintf(log, "ScanDirectory(): Could not open %s %s",
X                                        SPOOLDIR, gtime());
X                return MS_ABORT;
X        }
X
X        while ((pdir = readdir(dir)) != (struct direct *)NULL)  {
X                if (strncmp(pdir->d_name, Cfilename, MAXNAMLEN) == 0) {
X                        strncpy(Cfilename, pdir->d_name,(int)(pdir->d_namlen));
X                        closedir(dir);
X
X                        if (fdC == (FILE *)NULL)  {
X                           if ((fdC = fopen(Cfilename, "r")) == (FILE *)NULL) {
X                             fprintf(log,
X                                "ScanDirectory(): Could not open %s %s",
X                                Cfilename, gtime());
X                                  return MS_ABORT;
X                           }
X                        } else  {
X                                fprintf(log,
X                                   "ScanDirectory(): File already open %s",
X                                      gtime());
X                                return MS_ABORT;
X                        }
X
X                        return MS_SEND;
X                }
X        }
X
X        closedir(dir);
X        return MS_END;
X}
X
X
X/*---------------------------------------------------
X *      uucico G protocol High Level packet routines
X *---------------------------------------------------
X */
X
XSendInit()
X{
X        if (OpenPacket() == ERROR)
X                return MS_ABORT;
X        else
X                return MS_SEND;
X}
X
X
XRcvInit()
X{
X        if (OpenPacket() == ERROR)
X                return MS_ABORT;
X        else
X                return MS_RECEIVE;
X}
X
X
XSendFileHeader()
X{
X        int     len;
X        char    header[MAXLINE];
X
X        /* get next file from current work */
X
X        if (GetFile(header) == ERROR)
X                return SS_END;                  /* end sending session */
X
X        if ((fd = fopen(Filename, "r")) == NULL)  {
X                fprintf(log, "SendFileHeader(): Can't open %s %s", Filename,
X                                                gtime());
X                return SS_ABORT;
X        }
X
X        /*
X         *      Send the header
X         */
X
X        if (SendPacket(header, PKTSIZE, TRUE) == ERROR)
X                return SS_ABORT;
X
X        /*
X         *      Get the reply from remote
X         */
X
X        if (RcvPacket(InPacket, &len) == ERROR)
X                return SS_ABORT;
X
X        /*
X         *      Abort if remote doesn't say yes
X         */
X
X        if (strncmp(InPacket, "SY", 2) != 0)  {
X                fprintf(log,"SendFileHeader(): Remote refused request %s",
X                                                gtime());
X                return SS_ABORT;
X        }
X
X        /*
X         *      Scoop some poop
X         */
X
X        size = fread(OutPacket, sizeof(char), PKTSIZE, fd);
X
X        /*
X         *      Change to DATA state
X         */
X
X        return SS_DATA;
X}
X
X
XRcvFileHeader()
X{
X        int     len;
X        char    fromfile[MAXLINE];
X
X        if (RcvPacket(InPacket, &len) == ERROR)
X                return SS_ABORT;
X
X        if (InPacket[0] == 'H')
X                return SS_END;
X
X        sscanf(&InPacket[2], "%s %s ", fromfile, Filename);
X
X        if ((fd = fopen(Filename, "w")) == (FILE *)NULL)  {
X                fprintf(log, "RcvFileHeader(): Can't create %s %s", Filename,
X                                                                gtime());
X                strcpy(OutPacket, "SN4");
X                if (SendPacket(OutPacket, PKTSIZE, TRUE) == ERROR)
X                        return SS_ABORT;
X                else
X                        return SS_HEADER;
X        }
X
X
X        strcpy(OutPacket, "SY");
X        if (SendPacket(OutPacket, PKTSIZE, TRUE) == ERROR)
X                return SS_ABORT;
X
X        /*
X         *      Change to DATA state
X         */
X
X        return SS_DATA;
X}
X
X
XSendData()
X{
X        if (SendPacket(OutPacket, size, FALSE) == ERROR)
X                return SS_ABORT;
X
X        /* Get data from file */
X
X        if ((size = fread(OutPacket, sizeof(char), PKTSIZE, fd)) < 1)
X                return SS_EOF;
X
X        return SS_DATA;
X}
X
X
XSendEof()
X{
X        int     len;
X
X        OutPacket[0] = '\0';
X        if (SendPacket(OutPacket, 0, FALSE) == ERROR)
X                return SS_ABORT;
X
X        if (RcvPacket(InPacket, &len) == ERROR)
X                return SS_ABORT;        /* rec CY or CN */
X
X        fclose(fd);
X        fd = (FILE *)NULL;
X
X        if (strncmp(InPacket, "CY", 2) != 0)  {
X                fprintf(log, "SendEof(): Rcvd %s expected CY %s",
X                                        InPacket, gtime());
X                return SS_ABORT;
X        }
X
X        return SS_HEADER;               /* go get the next file to send */
X}
X
X
XRcvData()
X{
X        int     len;
X
X        if (RcvPacket(InPacket, &len) == ERROR)
X                return SS_ABORT;
X
X        if (len == 0)  {
X                fclose(fd);
X                fd = (FILE *)NULL;
X
X                strcpy(OutPacket, "CY");
X                if (SendPacket(OutPacket, PKTSIZE, TRUE) == ERROR)
X                        return SS_ABORT;
X
X                return SS_HEADER;
X        }
X
X        fwrite(InPacket, sizeof(char), len, fd);
X
X        return SS_DATA;
X}
X
X
X/*-----------------------------------------------------
X *      uucico G protocol Medium Level packet routines
X *-----------------------------------------------------
X */
X
XClosePacket()
X{
X        char    tmp[PKTSIZE];
X
X        spack(CLOSE, 0, 0, 0, tmp);
X        spack(CLOSE, 0, 0, 0, tmp);
X}
X
X
X/*
X *      INITA - INITC Handshake
X */
X
XOpenPacket()
X{
X        register int    i, j;
X        unsigned int    npkrec, npksent, len;
X        char            tmp[PKTSIZE];
X
X        pkrec   = 0;
X        pksent  = 1;
X        pknerr  = 0;
X
X        for (j = INITA; j >= INITC; j--)  {
X                for (i = 0; i < MAXTRY; i++)  {
X                        spack(j, 0, 0, 0, tmp);
X                        if (rpack(&npkrec, &npksent, &len, tmp) == j)
X                                goto nextinit;
X                }
X
X                fprintf(log,"OpenPacket(): Could not INIT Handshake %s",
X                                                gtime());
X                return ERROR;
Xnextinit:;
X        }
X
X        return OK;
X}
X
X
XRcvPacket(data, len)
Xregister char   *data;
Xregister int    *len;
X{
X        register int    i;
X        unsigned int    npkrec, npksent, nlen, nakflg, val;
X        char            tmp[PKTSIZE];
X
X        nakflg = FALSE;
X
X        for (i = 0; i < MAXTRY; i++)  {
X                switch (val = rpack(&npkrec, &npksent, &nlen, data))  {
X                case DATA:
X                        pkrec = (pkrec + 1) % 8;
X                        if (npksent != pkrec)
X                                break;
X
X                        *len = nlen;
X
X                        if (nakflg)
X                                spack(RJ, pkrec, 0, 0, tmp);
X                        else
X                                spack(RR, pkrec, 0, 0, tmp);
X
X                        return OK;
X                case CLOSE:
X                        fprintf(log,"RcvPacket(): Rcvd CLOSE from remote %s",
X                                                gtime());
X                        return ERROR;
X                default:
X                        nakflg = TRUE;
X                        fprintf(log,
X                          "RcvPacket(): rpack() returned %s %s",
X                           rcverr[abs(val) - 1], gtime());
X                }
X        }
X
X        if (++pknerr >= MAXTRY)  {
X                fprintf(log,"RcvPacket(): Too many packet errors %s",
X                                                gtime());
X                return ERROR;
X        }
X
X        return OK;
X}
X
X
X/*
X *      flg = 2      Just send the packet with no wait for ACK.
X *      flg = TRUE   Zero out the unused part of the buffer (for "msg" pkts).
X *      flg = FALSE  Normal data
X */
X
XSendPacket(data, len, flg)
Xregister char   *data;
Xregister int    len, flg;
X{
X        register int    i;
X        unsigned int    nlen, npkrec, npksent, val;
X        char            tmp[PKTSIZE];
X
X        /*
X         *      If Flag set then NULL fill to PKTSIZE
X         */
X
X        if (flg)
X                for (i = strlen(data); i < PKTSIZE; i++)
X                        data[i] = '\0';
X
X        for (i = 0; i < MAXTRY; i++)  {
X                spack(DATA, pkrec, pksent, len, data);
X
X                if (flg == 2)
X                        return OK;
X
X                switch (val = rpack(&npkrec, &npksent, &nlen, tmp))  {
X                case RR:
X                case RJ:
X                        if (npkrec != pksent)
X                                break;  /* Retry on wrong Packet Numbers */
X
X                        pksent = (pksent + 1) % 8;
X                        return OK;
X                case CLOSE:
X                        fprintf(log,"SendPacket(): Rcvd CLOSE from remote %s",
X                                                        gtime());
X                        return ERROR;
X                default:
X                        fprintf(log,"SendPacket(): rpack() returned %s %s", rcverr[abs(val) - 1], gtime());
X                }
X        }
X
X        if (++pknerr >= MAXTRY)  {
X                fprintf(log,"SendPacket(): Too many packet errors %s",
X                                                gtime());
X                return ERROR;
X        }
X
X        return OK;
X}
X
X
X/*
X *      Send a Packet
X */
X
Xspack(type, npkrec, npksent, len, packet)
Xunsigned  type, npkrec, npksent, len;
Xchar      *packet;
X{
X        unsigned int    c, check, i;
X        char            pkt[HDRSIZE];
X
X        if (len == 0)
X                *packet = '\0';
X
X        pkt[0] = DLE;
X        pkt[4] = (type << 3) & 0xFF;
X        type  &= 0x07;
X
X        switch (type)  {
X                case CLOSE:
X                        break;
X                case RR:
X                case RJ:
X                        pkt[4] |= npkrec;
X                        break;
X                case INITA:
X                case INITC:
X                        pkt[4] |= WNDSIZE;      /* window size */
X                        break;
X                case INITB:
X                        pkt[4] |= 1;            /* segment size (1 = 64) */
X                        break;
X                case DATA:
X                        pkt[4] = (0x80 | (npksent << 3) | npkrec) & 0xFF;
X
X                        /*
X                         *      If packet length is less than 64
X                         *      then first byte needs to indicate the
X                         *      difference.  So shift everything right
X                         *      and put the difference in first byte
X                         */
X
X                        if (c = PKTSIZE - len)  {
X                                pkt[4] = (pkt[4] | 0x40) & 0xFF;
X                                for (i = PKTSIZE - 1; i > 0; i--)
X                                        packet[i] = packet[i - 1];
X
X                                packet[0] = c & 0xFF;
X                        }
X        }
X
X        if (type != DATA)  {
X                pkt[1] = 9;             /* control packet, size = 0 */
X                check = pkt[4] & 0xFF;
X        } else {
X                pkt[1] = PKTSIZ2;       /* data packet, size = 64 */
X                check = checksum(packet, PKTSIZE) & 0xFFFF;
X                check = (check ^ (pkt[4] & 0xFF)) & 0xFFFF;
X        }
X
X        check  = (0xAAAA - check) & 0xFFFF;
X        pkt[2] = check & 0xFF;
X        pkt[3] = (check >> 8) & 0xFF;
X        pkt[5] = (pkt[1] ^ pkt[2] ^ pkt[3] ^ pkt[4]) & 0xFF;
X
X        WriteTTY(pkt, HDRSIZE);       /* header is 6-bytes long */
X
X        if (pkt[1] != 9)
X                WriteTTY(packet, PKTSIZE);   /* data is always 64 bytes long */
X}
X
X
X/*
X *      Read Packet
X *
X *      Returns:
X *      +n      Okey-Dokey;
X *      -1      Input buffer empty;
X *      -2      Bad header;
X *      -3      Lost packet timeout;
X *      -4      Checksum error;
X *      -5      Wrong packet size
X */
X
Xrpack(npkrec, npksent, len, packet)
Xregister unsigned int   *npkrec, *npksent, *len;
Xregister char           *packet;
X{
X        register unsigned type, check, checkchk;
X        register int      i;
X        char              c, pkt[HDRSIZE];
X
X        c = 0;
X        while ((c & 0x7F) != DLE)
X                if (ReadTTY(&c, 1, PKTTIME) == 0)
X                        return(-1);     /* input buffer empty */
X
X        if (ReadTTY(&pkt[1], HDRSIZE - 1, PKTTIME) < (HDRSIZE - 1))
X                return(-1);             /* input buffer empty */
X
X        /* header is 6-bytes long */
X
X        if ((pkt[1] ^ pkt[2] ^ pkt[3] ^ pkt[4] ^ pkt[5]) & 0xFF)
X                return(-2);             /* bad header */
X
X        if ((pkt[1] & 0x7F) == 9)  {    /* control packet */
X                *len     = 0;
X                type     = ((unsigned)pkt[4] >> 3) & 0x7F;
X                *npkrec  = pkt[4] & 0x07;
X                *npksent = *packet = check = checkchk = 0;
X        }
X        else {                          /* data packet */
X                if (pkt[1] != PKTSIZ2)
X                        return(-5);   /* can't handle other than size 64 */
X
X                type     = DATA;
X                c        = pkt[4] & 0x3F;
X                *npksent = ((unsigned)c >> 3) & 0x07;
X                *npkrec  = c & 0x07;
X
X                if (ReadTTY(packet, PKTSIZE, PKTTIME) < PKTSIZE)
X                        return(-3);     /* packet timeout */
X
X                /* 64 byte packets even if partial */
X
X                check    = ((pkt[3] << 8) | (pkt[2] & 0xFF)) & 0xFFFF;
X                checkchk = checksum(packet, PKTSIZE) & 0xFFFF;
X                checkchk = 0xAAAA-(checkchk^((pkt[4] | 0x80) & 0xFF)) & 0xFFFF;
X
X                if (checkchk != check)
X                        return(-4);
X
X                /*
X                 *      See if a "short" packet was received
X                 *      If so, delete the size difference in first byte
X                 */
X
X                if (pkt[4] & 0x40)  {
X                        *len = PKTSIZE - *packet;
X                        for (i = 0; i < *len; i++)
X                                packet[i] = packet[i + 1];
X                }
X                else
X                        *len = PKTSIZE;
X
X                packet[*len] = '\0';
X        }
X
X        return type;
X}
X
X
Xunsigned checksum(data, n)
Xregister char   *data;
Xregister int    n;
X{
X        register unsigned short t;
X        register short          sum, x;
X
X        sum = -1;
X        x = 0;
X
X        do  {
X                if (sum < 0)  {
X                        sum <<= 1;
X                        sum++;
X                }
X                else
X                        sum <<= 1;
X
X                t    = sum;
X                sum += (unsigned short)(*data++ & 0xFF);
X                x   += sum ^ n;
X
X                if ((unsigned short)sum <= t)
X                        sum ^= x;
X
X        } while (--n > 0);
X
X        return (unsigned)sum;
X}
X
X
X/*--------------------------------------------------
X *      uucico G protocol Low Level packet routines
X *--------------------------------------------------
X */
X
XWriteString(msg, syn)
Xregister char   *msg;
Xregister int    syn;
X{
X        if (syn)
X                WriteTTY("\020", 1);
X
X        WriteTTY(msg, strlen(msg));
X
X        if (syn)
X                WriteTTY("", 1);
X}
X
X
XReadString(msg, seconds)
Xregister char   *msg;
Xregister int    seconds;
X{
X        register int    i;
X        char            c;
X
X        do {
X                if (ReadTTY(&c, 1, seconds) == 0)  {
Xrperr:                  fprintf(log, "ReadString(): Input timed out %s",
X                                                gtime());
X                        return 0;
X                }
X        } while ((c = toascii(c)) != DLE);
X
X        for (i = 0; i < MAXLINE && c ; i++)  {
X                if (ReadTTY(&c, 1, seconds) == 0)
X                        goto rperr;
X
X                if ((c = toascii(c)) == '\n')
X                        msg[i] = c = '\0';
X                else
X                        msg[i] = c;
X        }
X
X        return(strlen(msg));
X}
X
X
X/*------------------------------
X *      uucico TTY I/O routines
X *------------------------------
X */
X
XReadTTY(data, len, seconds)
Xregister char   *data;
Xregister int    len, seconds;
X{
X        register int    count;
X        int             ClkInt();
X
X        if (setjmp(env))
X                return 0;
X
X        signal(SIGALRM, ClkInt);        /* execute ClkInt() if alarm         */
X        alarm(seconds);                 /*      goes off                     */
X
X        if ((count = fread(data, sizeof(char), len, input)) < 1)  {
X                alarm(0);
X                return 0;
X        }
X
X        alarm(0);
X        return count;
X}
X
X
XWriteTTY(data, len)
Xregister char   *data;
Xregister int    len;
X{
X        fwrite(data, sizeof(char), len, output);
X}
X
X
XClkInt()
X{
X        longjmp(env, 1);
X}
X
X
XOpenTTY()
X{
X        register int    i, baud;
X
X        i = 0;
X        baud = DEFAULT_BAUD;
X
X        /*
X         *      Check baud rate entry against table
X         *      change 'baud' to new code
X         */
X
X        do  {
X                if (strcmp(speed, rates[i].code) == 0)  {
X                        baud = rates[i].baudrate;
X                        break;
X                }
X        } while (rates[++i].baudrate != 0);
X
X        input  = fopen(Device, "r");
X        output = fopen(Device, "w");
X
X        if (input == NULL || output == NULL)  {
X                fprintf(log, "OpenTTY(): Failure opening device %s %s",
X                                        Device, gtime());
X                return ERROR;
X        }
X
X        SetTTY(fileno(input), baud);
X        SetTTY(fileno(output), baud);
X
X        return OK;
X}
X
X
XCloseTTY()
X{
X        register FILE   *fdtty;
X
X        stty(fileno(input), &OldSetting);
X        stty(fileno(output), &OldSetting);
X
X        fclose(input);
X        fclose(output);
X
X        if ((fdtty = fopen(DEVICES, "r+")) == (FILE *)NULL)  {
X                fprintf(log, "CloseTTY(): Can't re-open %s %s", DEVICES, gtime());
X                return;
X        }
X
X        fseek(fdtty, Dpos, 0);  /* Dpos is computed in GetTTY() */
X        fputs("FREE", fdtty);
X        fclose(fdtty);
X}
X
X
XSetTTY(tty, baud)
Xregister int    tty, baud;
X{
X        gtty(tty, &OldSetting);                 /* get the TTY settings      */
X        gtty(tty, &NewSetting);                 /* copy old settings to new  */
X
X        NewSetting.sg_speed = D8S1NONE;         /* 8 Bits No Parity One Stop */
X        NewSetting.sg_flag  = RAW & ~ECHO;      /* no echo and no processing */
X
X        if (baud)                               /* 0 Means Slave Mode        */
X           NewSetting.sg_prot  = baud & 0x0F;   /* slap in the given baud    */
X
X        stty(tty, &NewSetting);                 /* set the TTY new settings  */
X}
X
X/* EOF */
X
END_OF_uucico.c
echo shar: 1 control character may be missing from \"uucico.c\"
if test 41611 -ne `wc -c <uucico.c`; then
    echo shar: \"uucico.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f mail.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"mail.c\"
else
echo shar: Extracting \"mail.c\" \(3462 characters\)
sed "s/^X//" >mail.c <<'END_OF_mail.c'
X/*
X *      mail.c
X *
X *      UniFLEX(tm) Version 2.3, May 1988
X *      Public Domain by S. R. Sampson
X *
X *      This program checks for local or remote indication
X *      and sends mail using rmail or lmail.
X */
X
X/* Defines */
X
X#define FALSE   0
X#define TRUE    ~FALSE
X
X/* Includes */
X
X#include "uucp.h"
X
X#include <string.h>
X#include <stdio.h>
X#include <errno.h>
X#include <time.h>
X#include <pwd.h>
X
X/* Globals */
X
Xlong    stamp;
Xchar    dfile[140], from[16], tmp[140];
Xint     remote;
X
X/* The program */
X
Xmain(argc, argv)
Xint     argc;
Xchar    *argv[];
X{
X        register FILE   *fdfile;
X        register char   *ptr;
X        struct passwd   *name;
X
X        if (argc == 1)  {
X                execl("/usr/bin/lmail", "mail", (char *)NULL);
X                exit(-1);
X        }
X
X        strcpy(dfile, "/tmp/msXXXXXX");
X        mktemp(dfile);
X
X        if ((fdfile = fopen(dfile, "w")) == (FILE *)NULL)  {
X                perror("mail 1");
X                exit(-1);
X        }
X
X        /*
X         *      If address has a '!' character flag address as remote
X         *      else local.
X         */
X
X        if ((ptr = strchr(argv[1], '!')) == (char *)NULL)
X                remote = FALSE;
X        else
X                remote = TRUE;
X
X        /*
X         *      Find out who we are and generate the required
X         *      "From name date" line
X         */
X
X        if (remote)  {
X                name = getpwuid(getuid());
X                strcpy(from, name->pw_name);
X                endpwent();
X
X                time(&stamp);
X                sprintf(tmp, "From %s %s", from, ctime(&stamp));
X
X                fwrite(tmp, sizeof(char), strlen(tmp), fdfile);
X        }
X
X        /*
X         *      Copy stdin to a /tmp file
X         */
X
X        for (;;)  {
X                if (fgets(tmp, sizeof tmp, stdin) == (char *)NULL)
X                        break;
X
X                fwrite(tmp, sizeof(char), strlen(tmp), fdfile);
X        }
X
X        fflush(fdfile);
X        fclose(fdfile);
X
X        if (remote)  {
X                uufix(dfile);        /* Change UniFLEX CR to Unix LF */
X                sprintf(tmp, "rmail %s <%s >/dev/null", argv[1], dfile);
X        } else
X                sprintf(tmp, "lmail %s <%s >/dev/null", argv[1], dfile);
X
X        if (system(tmp) != 0)  {
X                fprintf(stderr, "mail: Fatal - Could not exec() mailer\n");
X                exit(-1);
X        }
X
X#ifndef DEBUG
X        unlink(dfile);
X#endif
X}
X
X
Xuufix(file)
Xregister char   *file;
X{
X        register FILE   *fd, *temp;
X        register int    scoop;
X        char            name[32];
X
X        strcpy(name, "/tmp/uufixXXXXXX");
X        mktemp(name);
X
X        if ((fd = fopen(file, "r")) == (FILE *)NULL)  {
X                fprintf(stderr, "mail: File '%s' not found\n", file);
X                exit(-1);
X        }
X
X        if ((temp = fopen(name, "w")) == (FILE *)NULL)  {
X                fprintf(stderr, "mail: Unable to open temp file '%s'\n", name);
X                exit(-1);
X        }
X
X        while ((scoop = getc(fd)) != EOF)  {
X                if (scoop == 0x0D)
X                        putc(0x0A, temp);
X                else
X                        putc(scoop, temp);
X        }
X
X        fflush(temp);
X        fclose(temp);
X        fclose(fd);
X
X        unlink(file);
X        link(name, file);
X        unlink(name);
X}
X
X/* EOF */
X
END_OF_mail.c
echo shar: 1 control character may be missing from \"mail.c\"
if test 3462 -ne `wc -c <mail.c`; then
    echo shar: \"mail.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f rmail.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"rmail.c\"
else
echo shar: Extracting \"rmail.c\" \(14828 characters\)
sed "s/^X//" >rmail.c <<'END_OF_rmail.c'
X/*
X *      rmail.c
X *
X *      Mini Remote Mail Handler
X *
X *      Version 2.3, Public Domain May 1988
X *
X *      This program is executed by either 'mail' or 'uuxqt'.
X *
X *      The standard UniFLEX(tm) mail doesn't handle remote addresses
X *      so I made a new program called mail and renamed the old
X *      mail to lmail.  Now if the new mail finds a remote address
X *      it calls rmail, else lmail.
X *
X *      UniFLEX has a different End of Line convention than Unix
X *      does.  Therefore rmail will need to fix the transfered
X *      files before sending to mail.
X *
X *      Usage:
X *        rmail remotesystem!remoteuser myname (test myname)
X *        rmail remotesystem!remoteuser (.Config myname)
X *        rmail localuser
X *
X *      Limitation:
X *        Will only do bang '!' addresses.
X */
X
X/* Defines */
X
X#define FALSE   0
X#define TRUE    ~FALSE
X
X/* Includes */
X
X#include "uucp.h"
X
X#include <sys/modes.h>
X#include <sys/dir.h>
X#include <string.h>
X#include <stdio.h>
X#include <errno.h>
X#include <time.h>
X#include <pwd.h>
X
X/* Globals */
X
Xextern  char    *tzname[2];             /* contains two strings CDT or CST   */
Xextern  int     daylight;               /* array index for above             */
X
Xstruct  passwd  *names;
X
Xlong    stamp;
Xint     remote;
Xchar    bfile[32], cfile[32], dfile[32], xfile[32];
Xchar    rmtname[16], rmtuser[128], myname[16], user[16];
Xchar    datetime[48], ofrom[256], from[256], tmp[256], sys[32];
Xchar    errorname[8], *p, *ptr, *mfgets(), *fgets();
X
XFILE    *fbfile, *fcfile, *fdfile;
X
X/* The program */
X
Xmain(argc, argv)
Xint     argc;
Xchar    *argv[];
X{
X        if (argc < 2 || argc > 3)  {
X                fprintf(stderr, "Usage: rmail [remote!]user [testname]\n");
X                exit(-1);
X        }
X
X        /*
X         *      Read Configuration file
X         *
X         *      The UniFLEX 2.3 C Compiler would not compile this
X         *      correctly from an include file.
X         */
X
X#undef CONFIG
X#define CONFIG "/gen/spooler/uucp/.Config"
X
X        if ((fcfile = fopen(CONFIG, "r")) != (FILE *)NULL)  {
X                mfgets(user, sizeof user, fcfile);
X                mfgets(myname, sizeof myname, fcfile);
X                mfgets(errorname, sizeof errorname, fcfile);
X                fclose(fcfile);
X        }
X        else
X                exit(-1);
X
X        if (argc == 3)                  /* useful for debuging               */
X                strcpy(myname, argv[2]);
X
X        /*
X         *      If address has a '!' character flag address as remote
X         *      else local.
X         */
X
X        if ((ptr = strchr(argv[1], '!')) == (char *)NULL)
X                remote = FALSE;
X        else  {
X                *ptr = '\0';
X                remote = TRUE;
X        }
X
X        /*
X         *      Change file creation mask to rwx------
X         */
X
X        umask(S_IOREAD | S_IOWRITE | S_IOEXEC);
X
X        /*
X         *      Change to working directory
X         */
X
X        chdir(SPOOLDIR);
X
X        /*
X         *      Calculate the time
X         */
X
X        time(&stamp);
X        strcpy(datetime, ctime(&stamp));
X        datetime[strlen(datetime) - 1] = '\0';
X        strcat(datetime, " ");
X        strcat(datetime, tzname[daylight]);     /* add in CDT or CST         */
X
X        /*
X         *      See if this mail was generated locally
X         *      or came from somewhere else.  Local mail
X         *      has a "From x y" header, remote has a 
X         *      "From x y remote from z" header.
X         */
X
X        strcpy(from, "");
X        strcpy(ofrom, "");
X
X        fgets(tmp, sizeof tmp, stdin);  /* get a line from stdin             */
X
X        /*
X         *  First line should be a From line.  Our goal is to change from this:
X         *
X         *      From a!b (date) remote from c
X         *
X         *  To this:
X         *
X         *      From c!a!b (date) remote from d
X         *
X         *  Alternatively we may get a line from mail:
X         *
X         *      From a (date)
X         *
X         *  Now we must add on the machine name:
X         *
X         *      From a (date) remote from b
X         *
X         *  No 'from line' causes an error
X         */
X
X        if (strncmp(tmp, "From ", 5) != 0 && strncmp(tmp, ">From ", 6) != 0)  {
X                strcpy(dfile, "/tmp/rmXXXXXX");
X                mktemp(dfile);
X
X                if ((fdfile = fopen(dfile, "w")) == (FILE *)NULL)  {
X                        perror("rmail 1");
X                        exit(-1);
X                }
X
X                /* write out old 'from' line */
X
X                fwrite(tmp, sizeof(char), strlen(tmp), fdfile);
X
X                /*
X                 *      Copy file from stdin to the temporary file
X                 */
X
X                for (;;)  {
X                        if (fgets(tmp, sizeof tmp, stdin) == (char *)NULL)
X                                break;
X
X                        fwrite(tmp, sizeof(char), strlen(tmp), fdfile);
X                }
X
X                fflush(fdfile);
X                fclose(fdfile);
X
X                /*
X                 *      Send a letter to manager about this
X                 */
X
X                SendMail("No From Line\012\012", TRUE);
X                exit(0);
X        }
X
X        /*
X         *  Get the (now) garbage "From" into sys
X         *  and the remote address into ofrom
X         */
X
X        sscanf(tmp, "%s %s ", sys, ofrom);
X        p = tmp;
X
X        /*
X         *  Parse line to seek out "remote from"
X         */
X
X        for (;;)  {
X                p = strchr(p + 1, 'r');
X                if (p == NULL)  {
X
X                        /*
X                         * You get here after parsing to the end of the string
X                         * and didn't find "remote from" text.  The only other
X                         * option is the basic "From" from mail.
X                         */
X
X                        break;
X                }
X
X                if (strncmp(p, "remote from ", 12) == 0)
X                        break;
X        }
X
X        if (p == NULL)
X                strcat(from, ofrom);
X        else  {
X                sscanf(p, "remote from %s", from);
X                strcat(from, "!");
X                strcat(from, ofrom);
X        }
X
X        if (remote)  {
X
X                /* spool a remote file */
X
X                strcpy(rmtname, argv[1]);
X                strcpy(rmtuser, ptr + 1);
X
X                sprintf(dfile, "D.%.6sXXXXXX", myname);
X                mktemp(dfile);
X
X                if ((fdfile = fopen(dfile, "w")) == (FILE *)NULL)  {
X                        perror("rmail 2");
X                        exit(-1);
X                }
X
X                sprintf(tmp, "From %s %s remote from %s\012",
X                                                     from, datetime, myname);
X
X                /* put out new from */
X
X                fwrite(tmp, sizeof(char), strlen(tmp), fdfile);
X
X                sprintf(tmp, "Received: by %s on %s\012", myname, datetime);
X                fwrite(tmp, sizeof(char), strlen(tmp), fdfile);
X
X        } else  {
X        
X                /* set up a local file */
X
X                strcpy(dfile, "/tmp/rmXXXXXX");
X                mktemp(dfile);
X
X                if ((fdfile = fopen(dfile, "w")) == (FILE *)NULL)  {
X                        perror("rmail 3");
X                        exit(-1);
X                }
X
X                fwrite(">", sizeof(char), 1, fdfile);
X                fwrite(tmp, sizeof(char), strlen(tmp), fdfile);
X        }
X
X        /*
X         *      uuxqt and mail will call with:
X         *      "rmail [remote!]user <D.xxx >/dev/null"
X         *
X         *      Copy the stdin to the spool or /tmp file
X         */
X
X        for (;;)  {
X                if (fgets(tmp, sizeof tmp, stdin) == (char *)NULL)
X                        break;
X
X                fwrite(tmp, sizeof(char), strlen(tmp), fdfile);
X        }
X
X        if (!remote)  {
X                fflush(fdfile);
X                fclose(fdfile);
X
X                /*
X                 *      See if destination user name exists on this machine
X                 */
X
X                names = getpwnam(argv[1]);
X                endpwent();
X
X                if (names == (struct passwd *)NULL)  {
X                        SendMail("Unknown User\012\012", FALSE);
X                        exit(0);
X                }
X                else  {
X                        uufix(dfile);   /* Change LF to CR */
X                        sprintf(tmp, "mail %s <%s", argv[1], dfile);
X                }
X
X                if (system(tmp) != 0)
X                        execerr();
X
X#ifndef DEBUG
X                unlink(dfile);
X#endif
X        }  else  {
X                fclose(fdfile);
X
X                /*
X                 *      Now forward the mail, if user does not exist
X                 *      or the remote machine is not known
X                 *      then send mail to system manager and sender
X                 *
X                 *      The senders name is now in the global from[] string
X                 */
X
X
X                /*
X                 *      See if we talk to requested remote machine
X                 */
X
X                if (CheckLegalName(rmtname) == FALSE)  {
X                        SendMail("Unknown Machine\012\012", FALSE);
X                        exit(0);
X                }
X
X                /* make the spool files for uucico */
X
X                sprintf(bfile, "B.%.6sXXXXXX", rmtname);
X                mktemp(bfile);
X
X                if ((fbfile = fopen(bfile, "w")) == (FILE *)NULL)  {
X                        perror("rmail 4");
X                        exit(-1);
X                }
X
X                sprintf(tmp, "U %s %s\012F %s\012I %s\012C rmail %s\012",
X                  user, myname, dfile, dfile, rmtuser);
X                fwrite(tmp, sizeof(char), strlen(tmp), fbfile);
X
X                fclose(fbfile);
X
X                sprintf(xfile, "X.%.6sXXXXXX", rmtname);
X                sprintf(cfile, "C.%.6sXXXXXX", myname);
X                mktemp(xfile);
X                mktemp(cfile);
X
X                if ((fcfile = fopen(cfile, "w")) == (FILE *)NULL)  {
X                        perror("rmail 5");
X                        exit(-1);
X                }
X
X                sprintf(tmp,"S %s %s %s - %s 0666\012S %s %s %s - %s 0666\012",
X                  dfile, dfile, user, dfile, bfile, xfile, user, bfile);
X                fwrite(tmp, sizeof(char), strlen(tmp), fcfile);
X
X                fclose(fcfile);
X        }
X}
X
X
Xexecerr()
X{
X        fprintf(stderr, "rmail: Fatal - Could not exec() mailer\n");
X        exit(-1);
X}
X
X
X/*
X *      Send mail to system manager upon errors
X *
X *      Mail is contained in a file referenced
X *      by Global variable 'dfile'
X */
X
XSendMail(str, mgronly)
Xchar    *str;
Xint     mgronly;
X{
X        strcpy(cfile, "/tmp/rmtXXXXXX");
X        mktemp(cfile);
X
X        fcfile = fopen(cfile, "w");
X        fdfile = fopen(dfile, "r");
X
X        strcpy(tmp, "Subject: ");
X        strcat(tmp, str);
X
X        fwrite(tmp, sizeof(char), strlen(tmp), fcfile);
X
X        while (fgets(tmp, sizeof tmp, fdfile) != (char *)NULL)  {
X                fwrite("> ", sizeof(char), 2, fcfile);
X                fwrite(tmp, sizeof(char), strlen(tmp), fcfile);
X        }
X
X        fflush(fcfile);
X        fclose(fcfile);
X        fclose(fdfile);
X
X#ifndef DEBUG
X        unlink(dfile);
X#endif
X        /*
X         *      Return mail to system manager
X         *      (and sender if mgronly == FALSE)
X         */
X
X        uufix(cfile);           /* Change LF to CR */
X
X        if (!mgronly)  {
X                sprintf(tmp, "mail %s <%s", from, cfile);
X                if (system(tmp) != 0)
X                        execerr();
X        }
X
X        sprintf(tmp, "mail %s <%s", errorname, cfile);
X
X        if (system(tmp) != 0)
X                execerr();
X
X#ifndef DEBUG
X        unlink(cfile);
X#endif
X}
X
X
X/*
X *      Check the machine name by reading the SYSTEMS file
X *
X *      returns FALSE if not found, else TRUE
X *
X */
X
XCheckLegalName(name)
Xregister char   *name;
X{
X        register FILE   *fd;
X        char            line[132], tmp[16];
X
X        if ((fd = fopen(SYSTEMS, "r")) == (FILE *)NULL)
X                return(FALSE);
X
X        while (fgets(line, sizeof line, fd) != NULL)  {
X                sscanf(line, "%s ", tmp);
X
X                if (strncmp(name, tmp, 6) == 0)  {
X                        fclose(fd);
X                        return(TRUE);
X                }
X        }
X
X        fclose(fd);
X
X        return(FALSE);
X}
X
X
X/*
X *      mfgets (modified fgets)
X *
X *      Same as fgets() only this version deletes '\n'
X */
X
Xchar *mfgets(s, n, iop)
Xregister char   *s;
Xregister int    n;
Xregister FILE   *iop;
X{
X        register int    c;
X        register char   *cs;
X
X        cs = s;
X        while (--n > 0 && (c = getc(iop)) != EOF)  {
X                if (c == 0x0D)  {
X                        *cs = '\0';
X                        break;
X                } else
X                        *cs++ = c;
X        }
X
X        return((c == EOF && cs == s) ? (char *)NULL : s);
X}
X
X
X/*
X *      UniFLEX uses CR instead of LF (Just to be different I guess)
X */
X
Xchar *fgets(s, n, iop)
Xregister char   *s;
Xregister int    n;
Xregister FILE   *iop;
X{
X        register int    c;
X        register char   *cs;
X
X        cs = s;
X        while (--n > 0 && (c = getc(iop)) != EOF)  {
X                *cs++ = c;
X                if (c == 0x0A)
X                        break;
X        }
X
X        *cs = '\0';
X        return((c == EOF && cs == s) ? (char *)NULL : s);
X}
X
X
X/*
X *      Change Unix LF to UniFLEX CR
X */
X
Xuufix(file)
Xregister char   *file;
X{
X        register FILE   *fd, *temp;
X        register int    scoop;
X        char            name[32];
X
X        strcpy(name, "/tmp/uufixXXXXXX");
X        mktemp(name);
X
X        if ((fd = fopen(file, "r")) == (FILE *)NULL)  {
X                fprintf(stderr, "rmail: File '%s' not found\n", file);
X                exit(-1);
X        }
X
X        if ((temp = fopen(name, "w")) == (FILE *)NULL)  {
X                fprintf(stderr,"rmail: Unable to open temp file '%s'\n", name);
X                exit(-1);
X        }
X
X        while ((scoop = getc(fd)) != EOF)  {
X                if (scoop == 0x0A)
X                        putc(0x0D, temp);
X                else
X                        putc(scoop, temp);
X        }
X
X        fclose(temp);
X        fclose(fd);
X
X        unlink(file);
X        link(name, file);
X        unlink(name);
X}
X
X/* EOF */
X
END_OF_rmail.c
echo shar: 1 control character may be missing from \"rmail.c\"
if test 14828 -ne `wc -c <rmail.c`; then
    echo shar: \"rmail.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f uuxqt.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"uuxqt.c\"
else
echo shar: Extracting \"uuxqt.c\" \(5910 characters\)
sed "s/^X//" >uuxqt.c <<'END_OF_uuxqt.c'
X/*
X *      uuxqt.c
X *
X *      Command File Execute
X *
X *      UniFLEX(tm) Version 2.3 May 1988
X *
X *      Based on dcp.c Copyright (c) 1985, 1986, 1987 by Richard H. Lamb
X *      Changes are Public Domain by S. R. Sampson
X *
X *      This program searches for work files in the spool directory and
X *      executes them.  Work files have a X. prefix.
X *
X *      It is executed by 'uucico', 'cron', or 'at'
X */
X
X/* Includes */
X
X#include "uucp.h"
X
X#include <sys/modes.h>
X#include <sys/fcntl.h>
X#include <sys/dir.h>            /* defines MAXNAMLEN and directory stuff */
X#include <string.h>
X#include <stdio.h>
X#include <time.h>
X#include <pwd.h>
X
X/* Defines */
X
X#define MAXLINE         256
X
X/* Globals */
X
Xlong    stamp;
Xchar    command[MAXLINE], input[MAXLINE], output[MAXLINE], line[MAXLINE];
Xchar    Cfilename[MAXNAMLEN+1], filename[MAXNAMLEN+1], ltime[32];
Xchar    systemname[16], username[16], user[16];
X
X/* Forward Declarations */
X
Xchar    *mfgets();
X
X
Xmain(argc, argv)
Xint     argc;
Xchar    **argv;
X{
X        register char           *p;
X        register FILE           *fdC, *log;
X        register DIR            *dd;
X        register struct direct  *dir;
X        struct   passwd         *pw;
X        int                     inull, onull;
X
X        /*
X         *      Read Configuration file
X         *
X         *      The UniFLEX 2.3 C Compiler would not compile this
X         *      correctly from an include file.
X         */
X
X#undef CONFIG
X#define CONFIG "/gen/spooler/uucp/.Config"
X
X        if ((log = fopen(CONFIG, "r")) != (FILE *)NULL)  {
X                mfgets(user, sizeof user, log);
X                fclose(log);
X        }
X        else
X                exit(1);
X
X        /*
X         *      Change to spool directory
X         */
X
X        chdir(SPOOLDIR);
X
X        if ((dd = opendir(SPOOLDIR)) == (DIR *)NULL)
X                exit(1);
X
X        while ((dir = readdir(dd)) != (struct direct *)NULL)  {
X                if (strncmp(dir->d_name, "X.", 2) != 0)
X                        continue;
X
X                strncpy(Cfilename, dir->d_name, dir->d_namlen);
X
X                if ((fdC = fopen(Cfilename, "r")) == (FILE *)NULL)
X                        continue;
X
X                inull = onull = TRUE;
X
X                while (mfgets(line, sizeof line, fdC) != NULL)  {
X                        switch (line[0])  {
X                        case 'C':
X                                strcpy(command, &line[2]);
X                                break;
X
X                        /*
X                         *      See if all required files are present
X                         */
X
X                        case 'F':
X                                strcpy(filename, &line[2]);
X                                p = filename;
X
X                                while ((*p != ' ') && *p)
X                                        p++;
X
X                                *p = '\0';
X
X                                if (access(filename, 0) == -1)  {
X
X                                        /*
X                                         * All files not present, go check
X                                         * other work files and give up
X                                         * on this one till next time
X                                         */
X
X                                        goto not_ready;
X                                }
X
X                                break;
X
X                        case 'I':
X                                strcpy(input, &line[2]);
X                                inull = FALSE;
X                                break;
X
X                        case 'O':
X                                strcpy(output, &line[2]);
X                                onull = FALSE;
X                                break;
X
X                        case 'U':
X                                strcpy(username, &line[2]);
X                                p = username;
X
X                                while ((*p != ' ') && *p)
X                                        p++;
X
X                                *p++ = '\0';
X                                strcpy(systemname, p);
X                                break;
X                        }
X                }
X
X                if (inull)
X                        strcpy(input, "/dev/null");
X
X                if (onull)
X                        strcpy(output, "/dev/null");
X
X                sprintf(line,"%s <%s >%s", command, input, output);
X
X                if ((log = fopen(XQTLOG, "a")) != (FILE *)NULL)  {
X                        time(&stamp);
X                        strcpy(ltime, ctime(&stamp));
X                        ltime[strlen(ltime) - 1] = '\0';
X
X                        fprintf(log, "%s %s %s %s\n",
X                                ltime, systemname, username, line);
X
X                        fclose(log);
X                }
X
X                if (system(line) != -1)  {
X#ifndef DEBUG
X                        unlink(Cfilename);
X
X                        if (!inull)
X                                unlink(input);
X
X                        if (!onull)
X                                unlink(output);
X#endif
X                }
X
Xnot_ready:      fclose(fdC);
X
X        }
X
X        closedir(dd);
X}
X
X
X/*
X *      mfgets (modified fgets)
X *
X *      Same as fgets() only this version deletes '\n'
X */
X
Xchar *mfgets(s, n, iop)
Xregister char   *s;
Xregister int    n;
Xregister FILE   *iop;
X{
X        register int    c;
X        register char   *cs;
X
X        cs = s;
X        while (--n > 0 && (c = getc(iop)) != EOF)  {
X                if (c == '\012')  {
X                        *cs = '\0';
X                        break;
X                } else
X                        *cs++ = c;
X        }
X
X        return((c == EOF && cs == s) ? (char *)NULL : s);
X}
X
X/* EOF */
X
END_OF_uuxqt.c
echo shar: 1 control character may be missing from \"uuxqt.c\"
if test 5910 -ne `wc -c <uuxqt.c`; then
    echo shar: \"uuxqt.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of shell archive.
exit 0

/*---------That is All (M.A.S.H.)---------------*/