[comp.sources.misc] v03i005: uucp mail for pc's

wswietse@eutrc3.UUCP (Wietse Venema) (04/20/88)

comp.sources.misc: Volume 3, Issue 5
Submitted-By: "Wietse Venema" <wswietse@eutrc3.UUCP>
Archive-Name: pcmail/Part4

#! /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 4 (of 8)."
# Contents:  Watchit cico.c connect.c email.c gp.h gpres.c ktrans.c
#   makefile.msc rmail.c startup.c
# Wrapped by wietse@eutwc1 on Wed Apr 20 16:45:16 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f Watchit -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"Watchit\"
else
echo shar: Extracting \"Watchit\" \(649 characters\)
sed "s/^X//" >Watchit <<'END_OF_Watchit'
XMicrosoft decided to change the order of function arguments of
Xthe rename() function. Check the source against the documentation
Xof your compiler.
X
XSome functions are used in all programs. Therefore, everything has to 
Xbe compiled with the same memory model.
X
XSince the assembly-language serial port driver assumes a small
Xmemory model, all programs have to be compiled with the small memory
Xmodel.
X
XThe MAILDIR, EDITOR environment variables should hold absolute path
Xnames. On MS-DOS systems (floppies!) it is a good idea to include
Xthe drive name as well.
X
XOn some MS-DOS systems the directory listing (file command) does
Xnot show the ".." entry.
END_OF_Watchit
if test 649 -ne `wc -c <Watchit`; then
    echo shar: \"Watchit\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f cico.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"cico.c\"
else
echo shar: Extracting \"cico.c\" \(4984 characters\)
sed "s/^X//" >cico.c <<'END_OF_cico.c'
X/*++
X/* NAME
X/*      cico 1
X/* SUMMARY
X/*      uucp file transfer
X/* PROJECT
X/*      pc-mail
X/* PACKAGE
X/*      cico
X/* SYNOPSIS
X/*      cico -p password [-d debuglevel]
X/* DESCRIPTION
X/*      cico is a program that connects to a real unix host
X/*      for exchange of spool files. It is a simplified
X/*	version of the unix uucico (copy-in-copy-out) program.
X/*
X/*	Options:
X/* .TP
X/*	-p password
X/*	The password that cico will use when logging in on the
X/*	unix host.
X/* .TP
X/*	-d debuglevel
X/*      Set the debugging level. It makes both the local cico
X/*      and the remote uucico more verbose. Default debugging
X/*	level is 0.
X/* FILES
X/*      cico manipulates various files in the spool directory.
X/*	See path(5) for the implementation of the message data base.
X/*
X/*      LOGFILE         transaction logging
X/*	s00000		communications parameters
X/* SEE ALSO
X/*      comm(5)		communications parameters
X/*	status(5)	error returns
X/* DIAGNOSTICS
X/*      The program terminates with a non-zero exit status if there
X/*      were problems. The error status codes can be translated
X/*	to meaningful messages (see status(5)).
X/*      More technical messages are written to the logfile.
X/* BUGS
X/*	cico only supports the functions needed for exchange of
X/*	electronic mail. Every incoming data file is treated as
X/*	if it were a mail message for the user of the pc.
X/* AUTHOR(S)
X/*      W.Z. Venema
X/*      Eindhoven University of Technology
X/*      Department of Mathematics and Computer Science
X/*      Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
X/* CREATION DATE
X/*      Sat Mar 28 19:58:06 GMT+1:00 1987
X/* LAST MODIFICATION
X/*	Wed Apr  6 00:18:29 MET 1988
X/* VERSION/RELEASE
X/*	1.6
X/*--*/
X
X#include <setjmp.h>
X#include "defs.h"
X#include "logs.h"
X#include "params.h"
X#include "comm.h"
X#include "status.h"
X#include "path.h"
X
Xpublic int *systrap;                            /* panic button */
Xpublic int dflag = 0;                           /* debug flag */
X#ifdef	unix
X    public int Debug = 0;			/* UUCP compatibility */
X#endif
X
Xhidden void parse_args(),sanity();              /* forward declarations */
X
X/* main program - parse command line options and pull the ropes */
X
Xmain(argc,argv)
Xint argc;
Xchar **argv;
X{
X    register int status;                        /* most recent error code */
X    jmp_buf mainbuf;                            /* catch-all */
X
X    parse_args(argc,argv);                      /* process cmd arguments */
X
X    sanity();                                   /* check systems parameters */
X
X    if (setjmp(systrap = mainbuf))              /* safety net in case of */
X	exit(E_CONFUSED);                       /* too many long jumps */
X
X    xopen();                                    /* init comm. line */
X    if ((status = connect()) == 0               /* login on remote system */
X    && (status = startproto()) == 0) {          /* start comm. protocol */
X	status = switcher(MASTER);              /* use the protocol */
X	endproto();                             /* terminate the protocol */
X    }                                           /* (ignore errors) */
X    disconnect();                               /* as it says */
X    xclose();                                   /* close comm. line */
X
X    exit(status);
X    /* NOTREACHED */
X}
X
X/* parse_args - take care of command-line arguments */
X
Xhidden void parse_args(argc,argv)
Xint argc;
Xchar **argv;
X{
X    while (--argc && *++argv && **argv == '-') {
X	switch (*++*argv) {
X	case 'p':
X	    if (--argc == 0)
X		usage("missing password argument");
X	    password = *++argv;
X	    break;
X	case 'd':
X	    if (--argc == 0)
X		usage("missing debugging level argument");
X	    sscanf(*++argv,"%d",&dflag);
X#ifdef	unix
X	    Debug = 
X#endif
X	    dflag = ((dflag < 0 ? 0 : dflag) > 10 ? 10 : dflag);
X	    break;
X	default:
X	    usage(strcons("invalid option: -%s",*argv));
X	    break;
X	}
X    }
X    if (argc > 0)
X	usage(strcons("unexpected argument: %s",*argv));
X}
X
X/* sanity - some preliminary work; mainly checks on sanity */
X
Xhidden void sanity()
X{
X    register int status;
X    register Info *ip;
X
X    if (status = pathinit())                            /* check environment */
X	exit(status);                                   /* bad environment */
X
X    if (status = open_log())                            /* check the logfile */
X	exit(status);                                   /* cannot write */
X
X    for (ip = comm = getparams(); ip->ident; ip++) {    /* check param. file */
X	if (ip->strval == 0 || ip->strval[0] == '\0')
X	    exit(E_BADSETUP);                           /* incomplete setup */
X	debug(6)("%s %s\n",ip->ident,ip->strval ? ip->strval : "");
X    }
X    if (password == 0 || *password == 0) 
X	usage("no password specified");                 /* no password */
X
X    strcpy(rmthost,ip[P_HOST].strval);			/* remote host name */
X}
X
X/* usage - print error message and usage string */
X
Xusage(str)
Xchar *str;
X{
X    fprintf(stderr,"%s\nusage: cico -p password [-d debuglevel]\n",str);
X    exit(2);
X}
END_OF_cico.c
if test 4984 -ne `wc -c <cico.c`; then
    echo shar: \"cico.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f connect.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"connect.c\"
else
echo shar: Extracting \"connect.c\" \(5702 characters\)
sed "s/^X//" >connect.c <<'END_OF_connect.c'
X/*++
X/* NAME
X/*      connect 3
X/* SUMMARY
X/*      pre- and post protocol host access
X/* PROJECT
X/*      pc-mail
X/* PACKAGE
X/*      cico
X/* SYNOPSIS
X/*      int connect()
X/*
X/*      int disconnect()
X/* DESCRIPTION
X/*      connect() tries to make a connection to the remote host
X/*      and to log on, using the dial-up script and login-name 
X/*	entries in the communications parameter file, and the password
X/*	provided as command-line parameter to the cico program. 
X/*	A simple send-expect script facility is used (no retries 
X/*	or delays). After the dial-up script has completed the program 
X/*	proceeds by expecting the login: prompt and does the final login.
X/*
X/*      disconnect() tries to break a connection, using the disconnect
X/*      entry in the communications parameter file. Unlike connect() 
X/*	this function is not driven by a send-expect script.
X/*
X/*	The following escape sequences are recognized in send or expect
X/*	strings:
X/*
X/* .nf
X/*	\\b	backspace
X/*	\\r	carriage return
X/*	\\n	newline
X/*	\\t	tab
X/*	\\s	space
X/*	\\f	form feed
X/*	\\nnn	octal character value
X/*	\\\\	a real backslash
X/* FUNCTIONS AND MACROS
X/*      xwrite(), xgetc(), trap(), debug(4)(), log()
X/* FILES
X/*      $MAILDIR/s00000		communications parameter file
X/*	$MAILDIR/LOGFILE	system logfile
X/* SEE ALSO
X/*      params(5)       communications parameter file entries
X/* DIAGNOSTICS
X/*      connect() returns a status E_BADSETUP if the systems parameter
X/*	file contains bad data, and E_NOLINE if the login script fails.
X/* AUTHOR(S)
X/*      W.Z. Venema
X/*      Eindhoven University of Technology
X/*      Department of Mathematics and Computer Science
X/*      Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
X/* CREATION DATE
X/*      Fri Mar 27 17:11:12 GMT+1:00 1987
X/* LAST MODIFICATION
X/*	Wed Apr  6 00:19:26 MET 1988
X/* VERSION/RELEASE
X/*	1.4
X/*--*/
X
X#include <setjmp.h>
X#include <ctype.h>
X#include "defs.h"
X#include "params.h"
X#include "status.h"
X#include "comm.h"
X#include "logs.h"
X#include "sysdep.h"
X
Xhidden char *blnk = " \t";			/* send/expect separators */
X
X/* forward declarations */
X
Xhidden void conn_send();
Xhidden void conn_xpct();
Xhidden char *escape();
X
X/* connect - connect to remote system; simple script processing (no retries) */
X
Xpublic int connect()
X{
X    int *savetrap = systrap;                    /* save exception handler */
X    jmp_buf mytrap;				/* our exception handler */
X    int retval;					/* completion code */
X    register char *cp;
X
X    /* set up exception handler */
X
X    if (retval = setjmp(systrap = mytrap)) {	/* get here if expect fails */
X	systrap = savetrap;			/* it just happened */
X	return(retval);
X    }
X
X    /* optional dial-up sequence */
X
X    for (cp = strtok(DIAL_SEQUENCE,blnk); cp; cp = strtok((char *)0,blnk)) {
X	conn_send(escape(cp));
X	if (cp = strtok((char *)0,blnk))
X	    conn_xpct(escape(cp));
X    }
X
X    /* mandatory login sequence */
X
X    conn_xpct("ogin:");
X    conn_send(strcons("%s\r",LOGIN_NAME));
X    conn_xpct("ssword:");
X    conn_send(strcons("%s\r",password));
X
X    /* restore exception handler */
X
X    systrap = savetrap;                         /* get here if expect wins */
X    return(0);					/* say no problems... */
X}
X
X/* disconnect - disconnect line */
X
Xpublic int disconnect()
X{
X    conn_send(escape(DISC_SEQUENCE));		/* send disconnect sequence */
X    return(0);					/* always succeeds... */
X}
X
X/* conn_send - quick-and-dirty output function */
X
Xhidden void conn_send(s)
Xregister char *s;
X{
X    sleep(1);
X
X    if (*s) {
X	debug(4)("Sending: %S\n",s);
X	while (*s) {
X	    delay();
X	    xwrite(ttfd,s++,1);
X	}
X    }
X}
X
X/* conn_xpct - primitive pattern matching without meta characters */
X
Xhidden void conn_xpct(s)
Xchar *s;
X{
X    register int c,i;
X    register int n = strlen(s);
X
X    /*
X    * Keep listening until we time out or until we receive the 
X    * expected string. Make sure that we do not overrun our buffer.
X    * Parity bits are ignored.
X    */
X
X    if (n) {
X	debug(4)("Expecting: %S\nReceiving: ",s);
X
X	if (n > MSGBUF) n = MSGBUF;
X
X	for (i = 0; (c = xgetc()) != EOF; ) {
X	    msgin[i++] = (c &= 0177);
X	    debug(4)("%C",c);
X	    if (i >= n && strncmp(s,&msgin[i-n],n) == 0) {
X		debug(4)(" ok!\n");
X		return;
X	    } else if (i >= MSGBUF) {
X		strncpy(msgin,&msgin[i-(n-1)],n-1);
X		i = n-1;
X	    }
X	}
X	debug(4)(" failed!\n");
X	trap(E_NOLINE,"LOGIN FAILED (at \"%S\")",s);
X    }
X}
X
X/* escape - interpret backslash sequences (this function is too big) */
X
Xhidden char *escape(s)
Xregister char *s;
X{
X    static char buf[BUFSIZ];
X    register char *cp = buf;
X
X    while (*s && cp < buf+BUFSIZ-1) {           /* don't overflow the buffer */
X	register char ch;
X	if (*s != '\\') {                       /* ordinary character */
X	    *cp++ = *s++;
X	} else if (isdigit(*++s) && *s < '8') { /* \nnn octal code */
X	    int c, i;
X	    sscanf(s,"%3o",&c);
X	    *cp++ = c;
X	    i = 1;
X            s++;
X	    while (i++ < 3 && isdigit(*s) && *s <'8')
X		s++;
X	} else if ((ch = *s++) == 0) {          /* at string terminator */
X	    break;
X	} else if (ch == 'b') {                 /* \b becomes backspace */
X	    *cp++ = '\b';
X	} else if (ch == 'f') {                 /* \f becomes formfeed */
X	    *cp++ = '\f';
X	} else if (ch == 'n') {                 /* \n becomes newline */
X	    *cp++ = '\n';
X	} else if (ch == 'r') {                 /* \r becomes carriage ret */
X	    *cp++ = '\r';
X	} else if (ch == 's') {                 /* \s becomes blank */
X	    *cp++ = ' ';
X	} else if (ch == 't') {                 /* \t becomes tab */
X	    *cp++ = '\t';
X	} else {                                /* \any becomes any */
X	    *cp++ = ch;
X	}
X    }
X    *cp = '\0';                                 /* terminate the result */
X    return(buf);
X}
END_OF_connect.c
if test 5702 -ne `wc -c <connect.c`; then
    echo shar: \"connect.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f email.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"email.c\"
else
echo shar: Extracting \"email.c\" \(5428 characters\)
sed "s/^X//" >email.c <<'END_OF_email.c'
X/*++
X/* NAME
X/*	email
X/* SUMMARY
X/*	manipulate work files (mail in preparation)
X/* PROJECT
X/*	pc-mail
X/* PACKAGE
X/*	mailsh
X/* SYNOPSIS
X/*	#include "email.h"
X/*
X/*	int mail()
X/* DESCRIPTION
X/*      The functions in this module are responsible for manipulations 
X/*	on work files and other mail messages in preparation.
X/*
X/*      mail() can be called either when the user has selected a work file in
X/*	the mail box display or when the user wants to create a new letter.
X/*
X/*	The message file is displayed on the screen and the can choose
X/*	to print, mail, edit or delete etc. the message.
X/*
X/*	The code in this module is a little tricky, to avoid that a work
X/*	file exists without a metafile (for the mail box display). 
X/* COMMANDS
X/*	the program specified in the EDITOR environment variable,
X/*	or a system-dependent default.
X/* FILES
X/*      temporary edit file in current directory
X/*	work file and meta file in spool directory
X/* SEE ALSO
X/*      pager(3), pager(5), kbdinp(3), edit(3)
X/* AUTHOR(S)
X/*      W.Z. Venema
X/*      Eindhoven University of Technology
X/*      Department of Mathematics and Computer Science
X/*      Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
X/* CREATION DATE
X/*	Tue May 12 15:35:20 GMT+1:00 1987
X/* LAST MODIFICATION
X/*	Mon Apr  4 23:39:13 MET 1988
X/* VERSION/RELEASE
X/*	1.3
X/*--*/
X
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <errno.h>
X#include "defs.h"
X#include "path.h"
X#include "dir.h"
X#include "pager.h"
X#include "screen.h"
X#include "mailsh.h"
X#include "status.h"
X
X/* forward declarations */
X
Xhidden void junk_work();
Xhidden int queue_work();
Xhidden int edit_work();
Xhidden int show_work();
Xhidden int send_work();
Xhidden int hold_work();
Xhidden int label_work();
X
Xhidden File *workfile = 0;			/* pager file */
X
X/* mail - user has made a choice. show message at cursor */
X
Xpublic int mail()
X{
X    static Screen screen[] = {
X	'C',	"Close",	hold_work,"Send message later, return to main menu",
X	'D',	"Delete",       delete,	delcurr,
X	'E',	"Edit",		edit_work,"Edit this message",
X	'M',	"Mail",		send_work,"Send this message to destination",
X	'P',	"Print",	print,	printcurr,
X	PGUP,	PgUp,		pu_pager,pageup,
X	PGDN,	PgDn,		pd_pager,pagedn,
X	UP,	"Up",           up_pager,csrup,
X	DOWN,	"Down",         dn_pager,csrdn,
X	0,	0,              show_work,
X	"(Reading a message in preparation)",
X    };
X    struct stat s;
X
X    if (stat(message,&s) && errno == ENOENT)	/* if new message file */
X	edit_work();				/* invoke editor first */
X    kbdinp(screen);				/* ask disposition */
X    junk_work();				/* destroy mail pager file */
X    return(S_REDRAW);				/* say screen was changed */
X}
X
X/* show_work - show work file or error message in middle window */
X
Xhidden int show_work()
X{
X    if (workfile) {				/* check pager file exists */
X	set_pager(workfile);			/* select existent display */
X    } else if (rd_pager(workfile = open_pager(),message)) {/* create display */
X	mesg_pager(workfile,m_msgread);		/* cannot display message */
X    }
X    ds_pager();					/* (re)draw display */
X    return(0);					/* screen is up-to-date */
X}
X
X/* junk_work - destroy work file display */
X
Xhidden void junk_work()
X{
X    if (workfile) {				/* no-op if no display */
X	close_pager(workfile);			/* release memory */
X	workfile = 0;				/* say it is gone */
X    }
X}
X
X/* edit_work - edit or create a work file */
X
Xhidden int edit_work()
X{
X    register int stat;
X
X    if (stat = edit(message,MAILFILE)) 
X	errdisp(stat);				/* edit() had a problem */
X    junk_work();				/* force new message display */
X    return(S_REDRAW);				/* say screen has changed */
X}
X
X/* hold_work - stop editing but do not yet mail a work file */
X
Xhidden int hold_work()
X{
X    static Screen screen[] = {
X	STRING,	0,              label_work,int_error,
X	0,	0,              0,
X	getsummary,
X    };
X    struct stat s;
X
X    /*
X    * The user has terminated an editor session, but does not yet want
X    * to send the message off. The purpose of the following code is to
X    * ask for a one-line summary, but only if such a comment does not yet
X    * exist. The summary is used to identify the work file in the main
X    * mail box display.
X    */
X
X    if (stat(message,&s) || !stat(comment,&s)) {/* no msg, or comment exists */
X	return(S_BREAK);			/* we are done here */
X    } else {
X	return(kbdinp(screen)|S_REDRAW);	/* ask for a summary */
X    }
X}
X
X/* label_work - save summary line to meta file */
X
Xhidden label_work(string)
Xchar *string;
X{
X    register int stat;
X
X    if (stat = metafile(string,comment)) {	/* try to create meta file */
X	errdisp(stat);				/* oops, notify the user */
X	return(S_REDRAW);			/* say screen has changed */
X    } else {
X	chmod(comment,0444);			/* make comments read-only */
X	junk_desk();				/* say mail box has changed */
X	return(S_BREAK);			/* say no more work */
X    }
X}
X
X/* send_work - user wants to send work file, ask for destination */
X
Xhidden int send_work()
X{
X    static Screen screen[] = {
X	STRING,	0,              queue_work,int_error,
X	0,	0,              when,
X	"Press ESC to cancel. Send message to:",
X    };
X    return(kbdinp(screen)|S_REDRAW);
X}
X
X/* queue_work - spool mail, delete work file and meta file */
X
Xhidden int queue_work(to)
Xchar *to;
X{
X    register int stat;
X
X    if (stat = submit(message,to)) {
X	errdisp(stat);				/* cannot queue message */
X	return(S_REDRAW);			/* say screen has changed */
X    } else {
X	return(unspool()|S_BREAK);		/* remove work and meta file */
X    }
X}
END_OF_email.c
if test 5428 -ne `wc -c <email.c`; then
    echo shar: \"email.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f gp.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"gp.h\"
else
echo shar: Extracting \"gp.h\" \(5523 characters\)
sed "s/^X//" >gp.h <<'END_OF_gp.h'
X/*++
X/* NAME
X/*	gp 5
X/* SUMMARY
X/*	g-protocol internal definitions
X/* PROJECT
X/*	pc-mail
X/* PACKAGE
X/*	cico
X/* SYNOPSIS
X/*	#include "gp.h"
X/* DESCRIPTION
X/* .nf
X
X/* /* include-once file */
X
X#ifndef	GP
X#define	GP
X
X#include <stdio.h>			/* needed for stderr */
X
X#define	MAXTRY		10		/* max nr of retries */
X#define	CTRL(x)		((x)^0100)	/* for ascii control characters */
X#define	MIN(x,y)	((x) < (y) ? (x) : (y))
X#define	MAX(x,y)	((x) > (y) ? (x) : (y))
X
X#define	ALARM		10		/* time-out interval */
X#define	MAGIC		0xAAAA		/* checksum magic number */
X#define	KCTRL		9		/* control packet */
X
X#define	FAIL		(-1)		/* corrupted packet */
X#define	TIME		(-2)		/* timed out */
X
X/* 
X* The protocol is defined in terms of message transmissions of 8-bit
X* bytes. Each message includes one control byte plus a data segment
X* of zero or more information bytes. (...)
X* The control byte is partitioned into three fields as depicted below.
X*	bit	7	6	5	4	3	2	1	0
X*		t	t	x	x	x	y	y	y
X* The t bits indicate a packet type and determine the interpretation
X* to be placed on the xxx and yyy the fields. The various interpretations
X* are as follows:
X*	tt	interpretation
X*	00	control packet
X*	10	data packet
X*	11	short data packet
X*	01	alternate channel
X* A data segment accompanies all non-control packets. (...) Type 01 packets
X* are never used by UUCP (...)
X*/
X
X#define	TYPE(x)		((x)&0300)	/* extract message field */
X
X#define	CONTROL		0000		/* control message */
X#define	DATA		0200		/* data, fixed size */
X#define	SHORT		0300		/* short (variable) length data */
X#define	ALTCH		0100		/* alternate channel (unused) */
X
X/*
X* The sequence number of a non-control packet is given by the xxx field.
X* Control packets are not sequenced. The newest sequence number,
X* excluding duplicate transmissions, accepted by a receiver is placed in 
X* the yyy field of non-control packets sent to the `other' receiver.
X*/
X
X#define	TVAL(x)		(((x)&0377)>>6)	/* extract message type */
X#define	MVAL(x)		(((x)&070)>>3)	/* extract control message */
X#define	SVAL(x)		(((x)&070)>>3)	/* extract S(equence) value */
X#define	RVAL(x)		((x)&07)	/* extract R(received) value */
X#define	IVAL(x)		((x)&07)	/* extract init value */
X#define	SFLD(x)		(((x)&07)<<3)	/* create S(equence) field */
X#define	RFLD(x)		((x)&07)	/* create R(received) field */
X#define	IFLD(x)		((x)&07)	/* create init field */
X
X/*
X* There are no data bytes associated with a control packet, the xxx field
X* is interpreted as a control message, and the yyy field is a value 
X* accompanying the control message. The control messages are listed
X* below in decreasing priority. That is, if several control messags
X* are to be sent, the lower-numbered ones are sent first.
X*	xxx	name	yyy
X*	1	CLOSE	n/a
X*	2	RJ	last correctly received sequence number
X*	3	SRJ	sequence number to retransmit
X*	4	RR	last correctly received sequence number
X*	5	INITC	window size
X*	6	INITB	data segment size
X*	7	INITA	window size
X*/
X
X#define	MESG(x)		((x)&070)	/* extract control message field */
X
X#define	CLOSE		0010		/* close message */
X#define	RJ		0020		/* reject message */
X#define	SRJ		0030		/* selective-reject message (unused) */
X#define	RR		0040		/* received ok message */
X#define	INITC		0050		/* initialization message */
X#define	INITB		0060		/* initialization message */
X#define	INITA		0070		/* initialization message */
X
X/* declarations for tiny systems without tty driver, timer support etc. */
X
X#ifndef	unix
X
X#define	read		xread
X#define	write		xwrite
X#define	alarm(x)	/* nothing */
X#define	signal(x,y)	/* nothing */
X#define	DEBUG(x,y,z)	if (dflag >= x) printf(y,z)
X
Xextern int dflag;
X
X#else
X
X#define	DEBUG(l,f,s)	if (Debug >= l) fprintf(stderr,f,s)
X
Xextern int Debug;
X
X#endif
X
X/* 
X* We use one data structre for communication between various levels
X* of the g-protocol implementation. Fields in parentheses are relevant
X* only when a packet holds data.
X*	field	meaning				set by
X*	c	message type			gwrite(), grpack()
X*	(k	data segment length		galloc(), grpack())
X*	(chk	16-bit checksum			packet i/o functions)
X*	(len	max. data segment length	galloc(), gwrite(), grpack())
X*	(data	start of "len" bytes		this field is fixed)
X*	(segl	nbr of data bytes left		gread())
X*	(segp	start of "segl" bytes		gread())
X*/
X
X/* structure for communication between various program layers */
X
Xtypedef struct {
X    char k;				/* message segment size */
X    char c;				/* message type */
X    int chk;				/* data checksum */
X    short segl;				/* nr of data bytes left */
X    char *segp;				/* start of the "segl" bytes */
X    short len;				/* maximum data segment size */
X    char data[1];			/* actually a lot of characters */
X} Packet;
X
X/* functions that manipulate packets */
X
Xextern Packet *grproto();		/* take packet from input queue */
Xextern void gfree();			/* release input packet */
Xextern Packet *galloc();		/* allocate output packet */
Xextern void gwproto();			/* place packet in output queue */
Xextern void gfail();			/* panic button */
Xextern void gsctrl();			/* send one control packet */
Xextern void gsdata();			/* send one data packet */
Xextern int grpack();			/* receive one packet */
X
Xextern int seglen[];			/* data segment size table */
X
X/* standard unix library */
X
Xextern char *malloc();
X
X#endif	/* GP */
X/* AUTHOR(S)
X/*	W.Z. Venema
X/*	Eindhoven University of Technology
X/*	Department of Mathematics and Computer Science
X/*	Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
X/* CREATION DATE
X/*	Sun Apr 19 12:41:37 GMT+1:00 1987
X/* LAST MODIFICATION
X/*	Mon Apr  4 23:40:57 MET 1988
X/* VERSION/RELEASE
X/*	1.3
X/*--*/
END_OF_gp.h
if test 5523 -ne `wc -c <gp.h`; then
    echo shar: \"gp.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f gpres.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"gpres.c\"
else
echo shar: Extracting \"gpres.c\" \(6391 characters\)
sed "s/^X//" >gpres.c <<'END_OF_gpres.c'
X/*++
X/* NAME
X/*	gpres.c 3
X/* SUMMARY
X/*	g-protocol general interface
X/* PROJECT
X/*	pc-mail
X/* PACKAGE
X/*	cico
X/* SYNOPSIS
X/*	int gopen(fd);
X/*	int fd;
X/*
X/*	int gwrite(fd,buf,len)
X/*	int fd,len;
X/*	char *buf;
X/*
X/*	int gread(fd,buf,len)
X/*	int fd,len;
X/*	char *buf;
X/*
X/*	int gclose(fd)
X/*	int fd;
X/* DESCRIPTION
X/*	The functions in this module present an interface that closely
X/*	resembles the unix kernel i/o interface.
X/*
X/*	gopen() handles the initial message exchange. fd should be
X/*	connected to a tty line. gopen() normally returns a zero value.
X/*
X/*	gwrite() returns the number of bytes `written' to the remote system.
X/*	It should be considered an error if this is not equal to the number
X/*	of bytes requested.
X/*	A zero-length write should be used to indicate EOF during file transfer.
X/*
X/*	gread() returns the requested number of bytes or the number of
X/*	bytes sent by the remote system, whichever is smaller.
X/*	A zero-length read indicates EOF during file transfer.
X/*
X/*	gclose() shuts the protocol down, but does not otherwise change
X/*	communications line parameters. It normally returns a zero value.
X/* FUNCTIONS AND MACROS
X/*	galloc(), gfree(), gsproto(), grproto()
X/* DIAGNOSTICS
X/*	All functions return -1 in case of unrecoverable problems.
X/* BUGS
X/*	All g protocol routines assume that the XON/XOFF flow control
X/*	has been turned off.
X/*	Some parts of the code rely on 8-bit bytes, 16-bit short integers.
X/* AUTHOR(S)
X/*	W.Z. Venema
X/*	Eindhoven University of Technology
X/*	Department of Mathematics and Computer Science
X/*	Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
X/* CREATION DATE
X/*	Sun Apr 19 12:41:37 GMT+1:00 1987
X/* LAST MODIFICATION
X/*	Mon Apr  4 23:41:36 MET 1988
X/* VERSION/RELEASE
X/*	1.3
X/*--*/
X
X#include <setjmp.h>
X#include "gp.h"
X
X/* local and forward declarations */
X
Xstatic jmp_buf failbuf;
Xstatic void gpeek(),gpoke(),memcpy();
X
X/* gfail - exception handling */
X
Xvoid gfail()
X{
X    longjmp(failbuf,1);
X}
X
X/* gopen - not quite an analogon of unix open(2) */
X
Xint gopen(fd)
Xint fd;
X{
X    return(ginit(fd));		/* do packet stuff elsewhere */
X}
X
X/* gwrite - g-protocol analogon of unix write(2) */
X
Xgwrite(fd,data,len)
Xint fd,len;
Xchar *data;
X{
X    /* set up exception handling */
X
X    if (setjmp(failbuf))			/* in case gsproto fails */
X	return(FAIL);				/* it just did */
X
X    /* handle special case of zero-length writes separately */
X
X    if (len <= 0) {				/* end-of-file message */
X	register Packet *pk = galloc();		/* allocate output packet */
X	gpoke(pk,data,len);			/* make null-data packet */
X	gsproto(fd,pk);				/* send to other side */
X    } else {					/* true data message */
X	register int shot;			/* quantum size */
X	register int rest;			/* amount left to do */
X	for (rest = len; rest > 0; rest -= shot,data += shot) {
X	    register Packet *pk = galloc();	/* allocate output packet */
X	    gpoke(pk,data,shot = MIN(pk->len,rest));/* fill the packet */
X	    gsproto(fd,pk);
X	}
X    }
X    return(len);				/* no problems detected */
X}
X
X/* gread - g-protocol analogon of unix read(2) */
X
Xgread(fd,data,len)
Xint fd,len;
Xchar *data;
X{
X    static Packet *pk;				/* our byte stock */
X    register int igot;				/* our return value */
X
X    /* set up exception handling */
X
X    if (setjmp(failbuf))			/* in case grproto fails */
X	return(FAIL);				/* it just did */
X
X    /* if no bytes in stock, get some fresh ones and see how much we got */
X
X    if (pk == 0 || pk->segl <= 0)		/* we are out of data */
X	gpeek(pk = grproto(fd));		/* get fresh packet */
X
X    /* return as many bytes as asked, or as in stock, whichever is less */
X
X    if ((igot = MIN(len,pk->segl)) > 0) {
X	memcpy(data,pk->segp,igot);		/* copy to caller's buffer */
X	pk->segp += igot;			/* update stock pointer */
X	pk->segl -= igot;			/* update stock count */
X    }
X    if (pk->segl <= 0)				/* if we exhausted the stock */
X	gfree(pk);				/* release packet */
X    return(igot);				/* no problems detected */
X}
X
X/* gclose - turn g protocol off */
X
Xgclose(fd)
Xint fd;
X{
X    return(gfinit(fd));				/* not here! */
X}
X
X/* 
X* "Each transmitter is constrained to observe the maximum data segment"
X* "size established during initial synchronization by the receiver that"
X* "it sends to. (...) `short' packets have zero or more data bytes but less"
X* "than the maximum. The first one or two bytes of the data segment of"
X* "a short packet are `count' bytes that indicate the difference between"
X* "the maximum size and the number of bytes in the short segment. If the"
X* "difference is less than 127, one count byte is used. If the difference"
X* "exceeds 127, then the low-order seven bits of the difference are put"
X* "in the first data byte and the remaining high-order bit is set as an"
X* "indication that the remaining bits of the difference are in the second"
X* "byte.
X*/
X
X/* gpoke - prepare packet for transmission */
X
Xstatic void gpoke(pk,data,len)
Xregister Packet *pk;
Xint len;
Xchar *data;
X{
X    register int diff = pk->len-len;		/* packet/data size mismatch */
X
X    pk->segp = pk->data;			/* set up write pointer */
X    pk->segl = len;				/* actual segment length */
X    if (diff < 0 || len < 0) {
X	DEBUG(7,"gpoke: trouble\n","");		/* something very wrong */
X	gfail();
X	/* NOTREACHED */
X    } else if (diff == 0) {
X	pk->c = DATA;				/* long data segment */
X    } else if (diff <= 127) {
X	pk->c = SHORT;				/* short data segment */
X	*pk->segp++ = diff;			/* one difference byte */
X    } else if (diff > 127) {
X	pk->c = SHORT;				/* tiny data segment */
X	*pk->segp++ = diff|0200;		/* two difference bytes */
X	*pk->segp++ = diff>>7;
X    }
X    memcpy(pk->segp,data,pk->segl);		/* copy data into packet */
X}
X
X/* gpeek - prepare newly packet for reading */
X
Xstatic void gpeek(pk)
Xregister Packet *pk;
X{
X    register int diff;
X
X    pk->segp = pk->data;			/* set up read pointer */
X    if (TYPE(pk->c) == DATA) {
X	diff = 0;				/* long data segment */
X    } else if (TYPE(pk->c) != SHORT) {
X	DEBUG(7,"gread: trouble\n","");		/* something funny */
X	gfail();
X	/* NOTREACHED */
X    } else if ((diff = *pk->segp++&0377)&0200) {/* short data segment */
X	diff = (diff&0177)|((*pk->segp++&0377)<<7);
X    }
X    pk->segl = pk->len-diff;			/* actual segment size */
X    DEBUG(9,"rcv: data %d bytes\n",pk->segl);
X}
X
X/* memcpy - not-so-efficient implementation */
X
Xstatic void memcpy(dst,src,len)
Xregister char *dst,*src;
Xregister int len;
X{
X    while (len-- > 0)
X	*dst++ = *src++;
X}
END_OF_gpres.c
if test 6391 -ne `wc -c <gpres.c`; then
    echo shar: \"gpres.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f ktrans.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"ktrans.c\"
else
echo shar: Extracting \"ktrans.c\" \(4983 characters\)
sed "s/^X//" >ktrans.c <<'END_OF_ktrans.c'
X/*++
X/* NAME
X/*	ktrans 3
X/* SUMMARY
X/*	k-protocol strategy routines
X/* PACKAGE
X/*	uucp across the TUEnet
X/* SYNOPSIS
X/*	#include "kp.h"
X/*
X/*	krproto(fd,data,size) 
X/*	int fd, *size;
X/*	char data[MAXPACKSIZ];
X/*
X/*	kwproto(fd,data,size) 
X/*	int fd, size;
X/*	char data[MAXPACKSIZ];
X/*
X/*	kclsproto(fd)
X/*	int fd;
X/* DESCRIPTION
X/*	The functions in this file take care of handshake and error
X/*	detection/recovery. The read/write functions return through an
X/*	external function kfail() in case of fatal errors, or protocol 
X/*	termination by the network partner.
X/*
X/*	The following packet types are used:
X/*
X/* .nf
X/* .in +5
X/*	D packets contain data.
X/*	Y packets are sent when a correct data packet was received.
X/*	N packets are sent when incorrect data was received.
X/*	A packets are sent to shut down the k protocol.
X/* .fi
X/*
X/*	Krproto() sends the data and either returns normally, or through 
X/*	kfail().
X/*
X/*	Kwproto() returns the received data or returns through kfail().
X/*
X/*	Kclsproto() sends the protocol termination sequence to the other 
X/*	side, either to signal the end of transfers, or to confirm
X/*	reception of an end-of-protocol sequence.
X/*
X/*	The strategy for sending data is as follows:
X/*
X/*	Send packet.
X/*	If (ACK for last packet) or (NAK for next packet) received, terminate.
X/*	If (NAK for last packet) or no response received, retransmit.
X/*	If data received with previous packet nr, ignore and wait for NAK.
X/*	If data received with next packet nr, NAK that data and terminate.
X/*	Otherwise (bad packet number, unexpected packet type) abort.
X/*
X/*	The strategy for receiving data is complementary:
X/*
X/*	Wait for packet
X/*	If expected packet received, ACK it and terminate.
X/*	If previous data packet received, ACK it and wait for next packet.
X/*	If bad packet received, send NAK for expected packet.
X/*	If nothing received, wait for another packet.
X/*	Otherwise (bad packet number, unexpected packet type) abort.
X/* FUNCTIONS AND MACROS
X/*	kspack, krpack, kfail
X/* AUTHOR(S)
X/*	Wietse Venema
X/*	Eindhoven University of Technology
X/*	Department of Mathematics and Computer Science
X/*	Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
X/* CREATION DATE
X/*	Mon Feb  3 13:12:08 MET 1986
X/* LAST MODIFICATION
X/*	Mon Apr  4 23:43:42 MET 1988
X/* VERSION/RELEASE
X/*	1.4
X/*--*/
X
X#include "kp.h"
X
Xstatic char recpkt[MAXPACKSIZ];			/* receive packet buffer */
Xstatic int  n = 0;				/* packet number */
X
Xkwproto( fd, packet, size)
Xint fd;
Xchar *packet;
Xint size;
X{
X    int num, numtry;                        	/* Packet number, tries */
X    int len;
X
X    kspack(fd, 'D',n,size,packet);      	/* Send a D packet */
X
X    for (numtry = 0; numtry < MAXTRY; numtry++) {
X	switch(krpack(fd,&num,&len,recpkt)) 	/* What was the reply? */
X	{
X	case 'D':			    	/* DATA */
X	    if ((num+1)%64 == n) {		/* Previous packet ? */
X		numtry = 0;			/* Reset counter */
X		break;				/* Don't ack it; read again */
X	    } else if (num != (n+1)%64)    	/* Fatal error, unless it */
X		kfail();		    	/* carries next packet number */
X	    kspack(fd,'N',num,0,NULLP);   	/* Can't use data now */
X
X	case 'N':                       	/* NAK */
X	    if (n == num) {			/* Send another one, */
X		kspack(fd, 'D',n,size,packet);
X		break;
X	    }
X	    num = (--num<0 ? 63:num); 	/* unless NAK for next packet */
X
X	case 'Y':                       	/* ACK */
X	    if (n != num) kfail();      	/* If wrong ACK, fail */
X	    n = (n+1)%64;               	/* Bump packet count */
X	    return;
X
X	case TIME:				/* No response */
X	case FAIL:				/* Bad packet */
X	    kspack(fd, 'D',n,size,packet);
X	    break;  		    	/* Send data packet again */
X
X	default: 
X	    kfail();               	    	/* Something else, abort */
X	}
X    }
X    kfail();				    	/* Too may retries, abort */
X}
X
Xkrproto( fd, packet, size)
Xint fd;
Xchar *packet;
Xint *size;
X{
X    int num, numtry;                        	/* Packet number, tries */
X
X    for (numtry = 0; numtry < MAXTRY; numtry++) 
X    {
X	switch (krpack(fd,&num,size,packet))	/* Get packet */
X	{
X	case 'D':
X	    if (num == n) {			/* Right packet? */
X		kspack(fd,'Y',n,0,NULLP);	/* Acknowledge the packet */
X		n = (n+1)%64;			/* Bump packet number, mod 64 */
X		return;
X	    } else if (num == ((n==0) ? 63:n-1)) { /* Previous packet? */
X		kspack(fd,'Y',num,0,NULLP);	/* Re-ack previous packet */
X		numtry = 0;	    	    	/* Reset counter */
X		break;				/* Read another packet */
X	    } else
X		kfail();			/* Sorry, wrong number */
X
X	case TIME:				/* No packet */
X	    break;				/* Don't NAK */
X
X	case FAIL:				/* Bad packet */
X	    kspack(fd,'N',n,0,NULLP);		/* Return a NAK */
X	    break;				/* Read another packet */
X
X	default:
X	    kfail();				/* Something else, abort */
X	}
X    }
X    kfail();				    	/* Too may retries, abort */
X}
X
Xkclsproto( fd)
Xint fd;
X{
X    kspack( fd, 'A', 0, 0, NULLP);		/* Send an 'A' packet */
X    kspack( fd, 'A', 0, 0, NULLP);		/* and another two since */
X    kspack( fd, 'A', 0, 0, NULLP);		/* we won't get ACKs */
X    return 0;
X}
END_OF_ktrans.c
if test 4983 -ne `wc -c <ktrans.c`; then
    echo shar: \"ktrans.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f makefile.msc -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"makefile.msc\"
else
echo shar: Extracting \"makefile.msc\" \(5643 characters\)
sed "s/^X//" >makefile.msc <<'END_OF_makefile.msc'
XRM	= rm -f
XMV	= mv
XCC	= cl
XAS	= masm
X
XSHOBJ1	= call.o email.o file.o screen.o mbox.o desk.o
XSHOBJ2	= kbdinp.o pager.o window.o setup.o errdisp.o invoke.o
XSHOBJ3	= makework.o mailfile.o deskutil.o submit.o edit.o alias.o
XSHLIBS	= shlib1.lib shlib2.lib shlib3.lib
X
XSMOBJ	= smail.o unalias.o hsearch.o
X
XRMOBJ	= rmail.o
X
XCMOBJ	= cmail.o invoke.o
X
XCIOBJ1	= comm.o connect.o getwork.o kphys.o kpres.o ktrans.o logs.o
XCIOBJ2	= newseqno.o protomsg.o rmtname.o scanwork.o sendwork.o startup.o
XCIOBJ3	= switcher.o xpres.o gpres.o gtrans.o gphys.o
XCILIBS	= cilib1.lib cilib2.lib cilib3.lib
X
XGENSRC	= dir.c myalloc.c params.c path.c newseqno.c ascf.c spoolfil.c \
X	str.c
XGENOBJ	= dir.o myalloc.o params.o path.o newseqno.o ascf.o spoolfil.o \
X	str.o
X
XCFLAGS	= -Gs
XLDFLAGS	= -F 2000
X
X.s.o:
X	$(AS) $*.s ;
X	$(MV) $*.obj $*.o
X
X.c.o:
X	$(CC) $(CFLAGS) -c $*.c
X	$(MV) $*.obj $*.o
X
Xall:	mail.exe smail.exe rmail.exe cico.exe cmail.exe
X
Xmail.exe: mailsh.o $(SHLIBS) libgen.lib
X	$(CC) $(LDFLAGS) -o mail mailsh.o -link $(SHLIBS) libgen.lib \lib\termcap
X	-exepack mail.exe junk
X	$(MV) junk mail.exe
X
Xsmail.exe: $(SMOBJ) libgen.lib
X	$(CC) $(LDFLAGS) -o smail $(SMOBJ) -link libgen.lib
X	-exepack smail.exe junk
X	$(MV) junk smail.exe
X
Xcmail.exe: cmail.o libgen.lib
X	$(CC) $(LDFLAGS) -o cmail cmail.o invoke.o -link libgen.lib
X	-exepack cmail.exe junk
X	$(MV) junk cmail.exe
X
Xrmail.exe: rmail.o libgen.lib
X	$(CC) $(LDFLAGS) -o rmail rmail.o -link libgen.lib
X	-exepack rmail.exe junk
X	$(MV) junk rmail.exe
X
Xcico.exe: cico.o comport.o $(CILIBS)
X	$(CC) $(LDFLAGS) -o junk cico.o comport.o -link $(CILIBS) libgen
X	-exepack junk.exe cico.exe 
X	$(RM) junk.exe
X
Xshlib1.lib: $(SHOBJ1)
X	$(RM) shlib1.lib
X	lib shlib1.lib $(SHOBJ1) ;
X
Xshlib2.lib: $(SHOBJ2)
X	$(RM) shlib2.lib
X	lib shlib2.lib $(SHOBJ2) ;
X
Xshlib3.lib: $(SHOBJ3)
X	$(RM) shlib3.lib
X	lib shlib3.lib $(SHOBJ3) ;
X
Xlibgen.lib: $(GENOBJ)
X	$(RM) $@
X	lib libgen $(GENOBJ) ;
X
Xcilib1.lib: $(CIOBJ1)
X	$(RM) $@
X	lib cilib1 $(CIOBJ1) ;
X
Xcilib2.lib: $(CIOBJ2)
X	$(RM) $@
X	lib cilib2 $(CIOBJ2) ;
X
Xcilib3.lib: $(CIOBJ3)
X	$(RM) $@
X	lib cilib3 $(CIOBJ3) ;
X
Xdepend:
X	@grep '^# *include *"' *.c|sed 's/c:# *include *"\([^"]*\)".*/o:	\1/g'
X
Xalias.o:	defs.h
Xalias.o:	path.h
Xalias.o:	pager.h
Xalias.o:	mailsh.h
Xalias.o:	screen.h
Xalias.o:	status.h
Xascf.o:	defs.h
Xascf.o:	ascf.h
Xcall.o:	defs.h
Xcall.o:	path.h
Xcall.o:	screen.h
Xcall.o:	pager.h
Xcall.o:	mailsh.h
Xcico.o:	defs.h
Xcico.o:	logs.h
Xcico.o:	params.h
Xcico.o:	comm.h
Xcico.o:	status.h
Xcico.o:	path.h
Xcmail.o:	defs.h
Xcmail.o:	dir.h
Xcmail.o:	path.h
Xcmail.o:	status.h
Xcomm.o:	defs.h
Xcomm.o:	params.h
Xcomm.o:	comm.h
Xconnect.o:	defs.h
Xconnect.o:	params.h
Xconnect.o:	status.h
Xconnect.o:	comm.h
Xconnect.o:	logs.h
Xconnect.o:	sysdep.h
Xdesk.o:	defs.h
Xdesk.o:	mailsh.h
Xdesk.o:	path.h
Xdesk.o:	dir.h
Xdesk.o:	pager.h
Xdesk.o:	screen.h
Xdesk.o:	status.h
Xdesk.o:	window.h
Xdeskutil.o:	defs.h
Xdeskutil.o:	pager.h
Xdeskutil.o:	mailsh.h
Xdeskutil.o:	screen.h
Xdeskutil.o:	status.h
Xdir.o:	defs.h
Xdir.o:	dir.h
Xedit.o:	defs.h
Xedit.o:	path.h
Xedit.o:	mailsh.h
Xedit.o:	status.h
Xemail.o:	defs.h
Xemail.o:	path.h
Xemail.o:	dir.h
Xemail.o:	pager.h
Xemail.o:	screen.h
Xemail.o:	mailsh.h
Xemail.o:	status.h
Xerrdisp.o:	defs.h
Xerrdisp.o:	screen.h
Xerrdisp.o:	pager.h
Xerrdisp.o:	status.h
Xerrdisp.o:	window.h
Xfile.o:	defs.h
Xfile.o:	screen.h
Xfile.o:	pager.h
Xfile.o:	mailsh.h
Xfile.o:	dir.h
Xfile.o:	path.h
Xfile.o:	status.h
Xfile.o:	window.h
Xgetwork.o:	defs.h
Xgetwork.o:	logs.h
Xgetwork.o:	status.h
Xgetwork.o:	work.h
Xgetwork.o:	params.h
Xgetwork.o:	comm.h
Xgphys.o:	gp.h
Xgpres.o:	gp.h
Xgtrans.o:	gp.h
Xhsearch.o:	hsearch.h
Xinvoke.o:	defs.h
Xinvoke.o:	status.h
Xkbdinp.o:	defs.h
Xkbdinp.o:	mailsh.h
Xkbdinp.o:	screen.h
Xkbdinp.o:	window.h
Xkphys.o:	kp.h
Xkpres.o:	kp.h
Xktrans.o:	kp.h
Xlogs.o:	defs.h
Xlogs.o:	logs.h
Xlogs.o:	path.h
Xlogs.o:	status.h
Xmailfile.o:	defs.h
Xmailfile.o:	path.h
Xmailfile.o:	screen.h
Xmailfile.o:	mailsh.h
Xmailsh.o:	defs.h
Xmailsh.o:	path.h
Xmailsh.o:	status.h
Xmailsh.o:	mailsh.h
Xmailsh.o:	window.h
Xmakework.o:	defs.h
Xmakework.o:	path.h
Xmakework.o:	screen.h
Xmakework.o:	mailsh.h
Xmbox.o:	defs.h
Xmbox.o:	path.h
Xmbox.o:	pager.h
Xmbox.o:	screen.h
Xmbox.o:	mailsh.h
Xmyalloc.o:	defs.h
Xnewseqno.o:	defs.h
Xnewseqno.o:	path.h
Xnewseqno.o:	dir.h
Xpager.o:	defs.h
Xpager.o:	window.h
Xpager.o:	pager.h
Xpager.o:	path.h
Xpager.o:	ascf.h
Xparams.o:	defs.h
Xparams.o:	path.h
Xparams.o:	params.h
Xpath.o:	defs.h
Xpath.o:	path.h
Xpath.o:	status.h
Xprotomsg.o:	defs.h
Xprotomsg.o:	params.h
Xprotomsg.o:	comm.h
Xprotomsg.o:	logs.h
Xprotomsg.o:	status.h
Xrmail.o:	defs.h
Xrmail.o:	dir.h
Xrmail.o:	path.h
Xrmail.o:	status.h
Xrmtname.o:	defs.h
Xrmtname.o:	params.h
Xrmtname.o:	comm.h
Xrmtname.o:	logs.h
Xrmtname.o:	status.h
Xrmtname.o:	path.h
Xscanwork.o:	defs.h
Xscanwork.o:	params.h
Xscanwork.o:	comm.h
Xscanwork.o:	work.h
Xscanwork.o:	path.h
Xscanwork.o:	dir.h
Xscanwork.o:	logs.h
Xscreen.o:	defs.h
Xscreen.o:	screen.h
Xsendwork.o:	defs.h
Xsendwork.o:	work.h
Xsendwork.o:	logs.h
Xsendwork.o:	status.h
Xsendwork.o:	params.h
Xsendwork.o:	comm.h
Xsetup.o:	defs.h
Xsetup.o:	path.h
Xsetup.o:	screen.h
Xsetup.o:	mailsh.h
Xsetup.o:	pager.h
Xsetup.o:	params.h
Xsetup.o:	status.h
Xsetup.o:	window.h
Xsmail.o:	defs.h
Xsmail.o:	path.h
Xsmail.o:	status.h
Xspoolfil.o:	defs.h
Xspoolfil.o:	path.h
Xspoolfil.o:	ascf.h
Xspoolfil.o:	status.h
Xstartup.o:	defs.h
Xstartup.o:	params.h
Xstartup.o:	comm.h
Xstartup.o:	logs.h
Xstartup.o:	status.h
Xstartup.o:	sysdep.h
Xstr.o:	defs.h
Xsubmit.o:	defs.h
Xsubmit.o:	path.h
Xswitcher.o:	defs.h
Xswitcher.o:	work.h
Xswitcher.o:	params.h
Xswitcher.o:	comm.h
Xswitcher.o:	logs.h
Xswitcher.o:	status.h
Xunalias.o:	defs.h
Xunalias.o:	hsearch.h
Xunalias.o:	path.h
Xunalias.o:	ascf.h
Xwindow.o:	defs.h
Xwindow.o:	window.h
Xxpres.o:	defs.h
Xxpres.o:	params.h
Xxpres.o:	comm.h
Xxpres.o:	status.h
Xxpres.o:	sysdep.h
Xxpres.o:	logs.h
END_OF_makefile.msc
if test 5643 -ne `wc -c <makefile.msc`; then
    echo shar: \"makefile.msc\" 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\" \(6168 characters\)
sed "s/^X//" >rmail.c <<'END_OF_rmail.c'
X/*++
X/* NAME
X/*      rmail
X/* SUMMARY
X/*      extract originator from new mail received by cico
X/* PROJECT
X/*      pc-mail
X/* PACKAGE
X/*      rmail
X/* SYNOPSIS
X/*      rmail
X/* DESCRIPTION
X/*      rmail searches for new mail files received by cico and extracts
X/*	the originator's name, for later use by the mail visual shell.
X/*
X/* 	Return address formats we understand (in order of preference):
X/* .nf
X/*
X/*	From: address (full_name)	(accept the full_name)
X/*	From: address			(accept the address)
X/*	>From address			(take address and keep scanning)
X/*	From address			(take address and keep scanning)
X/*
X/* .fi
X/*      To avoid tampering, new files will have read-only permission.
X/*
X/*      In order to avoid corruption, control-c interrupts are disabled.
X/* FILES
X/*      In the spool directory:
X/*	n<seqno>	received mail message
X/*	h<seqno>	extracted originator address
X/* SEE ALSO
X/*      path(5)         spool directory, file names
X/*      cico(1)         network process
X/*      mailsh(1)       visual mail shell
X/* DIAGNOSTICS
X/*      Exit status zero when no errors were detected, nonzero in case of file
X/*      access errors. See status(5) for error codes.
X/* BUGS
X/*	Note that the format "From: full_name <address>" is not 
X/*	recognized. The program will just pick up the first word from
X/*	full_name.
X/*
X/*      Does not really do a good job when parsing the mail headers.
X/*	At least, not good enough to extract a return path.
X/* AUTHOR(S)
X/*      W.Z. Venema
X/*      Eindhoven University of Technology
X/*      Department of Mathematics and Computer Science
X/*      Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
X/* CREATION DATE
X/*      Tue Mar 31 20:14:11 GMT+1:00 1987
X/* LAST MODIFICATION
X/*	Wed Apr  6 00:21:54 MET 1988
X/* VERSION/RELEASE
X/*	1.4
X/*--*/
X
X#include <setjmp.h>
X#include <signal.h>
X#include <time.h>
X#include <ctype.h>
X#include "defs.h"
X#include "dir.h"
X#include "path.h"
X#include "status.h"
X
Xextern struct tm *localtime();		/* system functions */
X
Xhidden void parse_args();		/* forward declarations */
Xhidden void newmail();
Xhidden void extract();
Xhidden void usage();
X
X#define HLEN            20		/* nbr of header lines scanned */
X
Xhidden int dflag = 0;			/* debugging option */
X
X#define debug	if (dflag) printf
X
Xmain(argc,argv)
Xint argc;
Xchar **argv;
X{
X    signal(SIGINT,SIG_IGN);		/* disable ctrl-c */
X    parse_args(argc,argv);		/* parse command args */
X    pathinit();				/* get path info */
X    umask(0222);			/* make files read-only */
X    newmail();				/* get headers from new mail */
X    exit(0);
X    /* NOTREACHED */
X}
X
X/* parse_args - process command-line arguments */
X
Xhidden void parse_args(argc,argv)
Xint argc;
Xchar **argv;
X{
X    while (--argc && *++argv && **argv == '-') {	/* process options */
X	switch (*++*argv) {
X	case 'd':					/* turn debugging on */
X	    if (--argc == 0)
X		usage("missing debugging level argument");
X	    sscanf(*++argv,"%d",&dflag);
X	    if (dflag < 0 || dflag > 9)
X		dflag = 0;
X	    break;
X	default:					/* unknown option */
X	    usage(strcons("invalid option: -%c",**argv));
X	    break;
X	}
X    }
X
X    /* check for extraneous arguments */
X
X    if (argc > 0)
X	usage(strcons("unexpected argument: %s",*argv));
X}
X
X/* scan for new mail that hasn't gotten yet a metafile */
X
Xhidden void newmail()
X{
X    register int dd;
X    int pfxlen = sizeof(NEWPFX)-1;
X    char *f;
X
X    debug("directory: \"%s\"\n",maildir);		/* verify */
X
X    /*
X    * Scan the spool directory for newly-arrived mail.
X    *
X    * Incoming mail message files have a name of "n<seqno>". 
X    * The originator name is normally present in files with names
X    * "h<seqno>" or "o<seqno>".
X    * The presence of an "o" file implies that the file "n<seqno>"
X    * has been read by the user. An "h" file means that the user
X    * has not yet read the message file.
X    *
X    * If a message file has no corresponding "h" or "o" file we
X    * assume it is a new mail message and create an "h" file with 
X    * the name of the originator.
X    */
X
X    for (dd = opendir(maildir); f = readdir(dd); /* void */) {
X	int seqno;
X	debug("rmail: file \"%s\"\n",f);
X	if (strncmp(f,NEWPFX,pfxlen) == 0 && sscanf(f+pfxlen,"%d",&seqno)) {
X	    if (access(in_meta(seqno),4) == 0) {	/* message already */
X		/* void */ ;				/* marked as read */
X	    } else if (access(new_meta(seqno),4) == 0) {/* message already */
X		/* void */ ;				/* marked as unread */
X	    } else {					/* create meta file */
X		extract(new_mesg(seqno),new_meta(seqno));
X	    }
X	}
X    }
X    closedir(dd);
X}
X
X/* extract - extract originator info from mail file to meta file */
X
Xhidden void extract(mail,meta)
Xchar *mail;
Xchar *meta;
X{
X    FILE *mesgfp,*metafp;
X    char line[BUFSIZ];
X    char from[BUFSIZ];
X    int n;
X
X    debug("-- \"%s\" -> \"%s\"\n",mail,meta);
X
X    if ((mesgfp = fopen(mail,"r")) == NULL)	/* cannot open existing file */
X	exit(E_SYSFAIL);
X
X    strcpy(from,"Somewhere");			/* default originator */
X
X    /*
X    * Some mailers generate real headers, separated from the message
X    * body by an empty line. So we stop when we find an empty line.
X    * Other mailers have no headers, so we stop after HLEN lines.
X    * The following algorithm tries to extract the real user name
X    * if possible, otherwise it takes whatever it can get.
X    */
X
X    for (n = 0; n < HLEN && fgets(line,BUFSIZ,mesgfp) && *line != '\n'; n++) {
X	if (sscanf(line,"From: %*s ( %[^)] )",from) == 1)
X	    break;
X	if (sscanf(line,"From: %s",from) == 1)
X	    break;
X	sscanf(line,"%*[>] From %s",from) || sscanf(line,"From %s",from);
X    }
X
X    /* carefully check all went well */
X
X    if (ferror(mesgfp))				/* sorry, read problem */
X	exit(E_READERR);
X    if ((metafp = fopen(meta,"w")) == NULL)	/* cannot create metafile */
X	exit(E_WRITERR);
X    fprintf(metafp,"%s\n",from);		/* write originator */
X    if (ferror(metafp)) {
X	fclose(metafp);				/* ms-dog needs this! */
X	chmod(meta,0666);			/* sorry, write problem */
X	unlink(meta);				/* delete metafile */
X	exit(E_WRITERR);
X    }
X    fclose(mesgfp);
X    fclose(metafp);
X}
X
X/* usage - explain what is wrong */
X
Xhidden void usage(str)
Xchar *str;
X{
X    fprintf(stderr,"%s\nusage: rmail [-d debugging_level]\n",str);
X    exit(2);
X}
END_OF_rmail.c
if test 6168 -ne `wc -c <rmail.c`; then
    echo shar: \"rmail.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f startup.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"startup.c\"
else
echo shar: Extracting \"startup.c\" \(6331 characters\)
sed "s/^X//" >startup.c <<'END_OF_startup.c'
X/*++
X/* NAME
X/*      startup 3
X/* SUMMARY
X/*      startup/terminate network protocol 
X/* PROJECT
X/*      pc-mail
X/* PACKAGE
X/*      cico
X/* SYNOPSIS
X/*      startproto()
X/*
X/*      endproto()
X/* DESCRIPTION
X/*      startproto() should be called after a successfull login on a remote
X/*      host. It performs the primary handshake with the other system 
X/*      (call accepted/locked) and negotiates a communications protocol.
X/*      It then sets the function pointers Close/Read/Write to the
X/*      appropriate values. Until endproto() is called, all i/o to the
X/*      remote host should proceed through the functions pointed to by
X/*      Read/Write.
X/*
X/*      endproto() turns the protocol off, and sends the silly "OO" message
X/*      to the remote system. It does not disconnect, nor does it change
X/*      the state of the communications port.
X/* FUNCTIONS AND MACROS
X/*      xgetc(), xwrite(), trap()
X/* DIAGNOSTICS
X/*      The process of negotiation is shown when debugging is enabled.
X/*      startproto() and endproto() return 0 in case of success, E_LOST
X/*      if no response arrived and E_REJECT if the response differed
X/*      from the expected response.
X/* BUGS
X/*      startproto() assumes that the local system is the calling system.
X/* AUTHOR(S)
X/*      W.Z. Venema
X/*      Eindhoven University of Technology
X/*      Department of Mathematics and Computer Science
X/*      Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
X/* CREATION DATE
X/*      Fri Mar 27 13:43:00 GMT+1:00 1987
X/* LAST MODIFICATION
X/*	Wed Apr  6 00:22:51 MET 1988
X/* VERSION/RELEASE
X/*	1.4
X/*--*/
X
X#include <setjmp.h>
X#include "defs.h"
X#include "params.h"
X#include "comm.h"
X#include "logs.h"
X#include "status.h"
X#include "sysdep.h"
X
X/* forward declarations */
X
Xhidden char *xpct();                            /* expect a string */
Xhidden char *send();                            /* send a string */
X
X/* the functions that inplement the various protocols */
X
Xextern kopen(),kclose(),kread(),kwrite();       /* k protocol */
Xextern gopen(),gclose(),gread(),gwrite();       /* g protocol */
X
Xtypedef struct proto {
X    char name;                                  /* name of the protocol */
X    int (*open)();                              /* the open function */
X    int (*close)();                             /* the close function */
X    int (*read)();                              /* the read function */
X    int (*write)();                             /* the write function */
X};
X
X/* the order of protocols is significant! */
X
Xhidden struct proto ptable[] = {
X    'k',        kopen,  kclose, kread,  kwrite, /* try this first */
X    'g',        gopen,  gclose, gread,  gwrite, /* then this one */
X    /* add your protocols at the appropriate place */
X    0,                                          /* terminator! */
X};
X
X/* startproto - do primary handshake, establish protocol and turn it on */
X
Xpublic startproto()
X{
X    int *savetrap = systrap;
X    jmp_buf mytrap;
X    register struct proto *pp;
X    register char *cp;
X    int status;
X
X    if (status = setjmp(systrap = mytrap)) {    /* get here if expect fails */
X	systrap = savetrap;
X	return(status);
X    }
X
X    /* the primary handshake: who are we and is it ok we call right now */
X
X    sscanf(xpct("Shere"),"Shere=%s",rmthost);   /* try to get host name */
X    log("SUCCEEDED (call to %s)",rmthost);
X    send(strcons("S%s -x%d",LOGIN_NAME,MAX(dflag,1))); /* name + debug level */
X    xpct("ROK");                                /* we're accepted or rejected */
X
X    /* choose a protocol from the list offered by the other side */
X
X    for (cp = xpct("P")+1,pp = ptable; pp->name && !index(cp,pp->name); pp++)
X	/* void */ ;
X    if (pp->name == 0) {                        /* no common protocol */
X	send("N");
X	trap(E_REJECT,"FAILED (no common protocol in \"%s\")",cp);
X	/* NOTREACHED */
X    }
X    send(strcons("U%c",pp->name));		/* my choice of protocol */
X
X    /* install protocol */
X
X    Close = pp->close;                          /* for endproto() */
X    Read  = pp->read;
X    Write = pp->write;
X    if (pp->open && CALL(pp->open)(ttfd))  	/* start up a protocol */
X	trap(E_LOST,"FAILED (startup)");
X
X    log("OK (startup)");
X    systrap = savetrap;                         /* get here if expect wins */
X    return(0);
X}
X
X/* endproto - terminate protocol */
X
Xpublic endproto()
X{
X    int *savetrap = systrap;
X    jmp_buf mytrap;
X    int status;
X
X    if (status = setjmp(systrap = mytrap)) {    /* get here if expect fails */
X	systrap = savetrap;
X	return(status);
X    }
X    if (Close)                                  /* check there is one */
X	CALL(Close)(ttfd);                      /* turn protocol off */
X    send("OOOOOO");                             /* byebye */
X    xpct("OO");                                 /* bye */
X    log("OK (conversation complete)");
X
X    systrap = savetrap;                         /* get here if expect wins */
X    return(0);
X}
X
X/* send - write message to remote host and return pointer to message */
X
Xhidden char *send(str)
Xchar *str;
X{
X    xwrite(ttfd,"\020",1);			/* message header */
X    xwrite(ttfd,str,strlen(str)+1);		/* include trailing null */
X    debug(4)("send: %S\n",str);
X    return(str);				/* return the message */
X}
X
X/* xpct - read message from host in "^Pmessage[\0\n]" format; trap on errors */
X
Xhidden char *xpct(pat)
Xchar *pat;
X{
X    register int c;
X    register char *p = msgin;
X    register int inmsg = 0;
X
X    /*
X    * Keep reading until we time out, the buffer is full, or until a 
X    * complete message has been received. Consider the link as lost
X    * in case of time out or buffer overflow. Assume we are rejected
X    * if the received message differs from what was expected.
X    */
X
X    while (p < msgin+MSGBUF && (c = xgetc()) != EOF) {      
X	if ((c &= 0177) == '\020') {            /* got start of message */
X	    debug(4)(" got sync\n");
X	    p = msgin;                          /* clear msg buffer */
X	    inmsg = 1;
X	} else if (inmsg == 0 || (*p++ = (c == '\n' ? 0 : c))) {
X	    debug(4)("%C",c);
X	} else {                                /* message completed */
X	    debug(4)("\n");
X	    if (strncmp(pat,msgin,strlen(pat))) /* compare prefix only */
X		break;
X	    return(msgin);
X	}
X    }
X    trap((c == EOF || p >= msgin+MSGBUF ? E_LOST : E_REJECT),
X	"FAILED (%s)",msgin);
X    /* NOTREACHED */
X}
END_OF_startup.c
if test 6331 -ne `wc -c <startup.c`; then
    echo shar: \"startup.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 4 \(of 8\).
cp /dev/null ark4isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 8 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
-- 
uucp:	mcvax!eutrc3!wswietse	| Eindhoven University of Technology
bitnet:	wswietse@heithe5	| Dept. of Mathematics and Computer Science
surf:	tuerc5::wswietse	| Eindhoven, The Netherlands.