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

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

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

#! /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 3 (of 8)."
# Contents:  Installation cmail.c dir.c file.c gphys.c kphys.c
#   makefile.uts xpres.c
# Wrapped by wietse@eutwc1 on Wed Apr 20 16:45:16 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f Installation -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"Installation\"
else
echo shar: Extracting \"Installation\" \(7515 characters\)
sed "s/^X//" >Installation <<'END_OF_Installation'
XTHE UNIX SIDE OF THE CONNECTION
X
XThe pc-mail programs will need a UNIX host to  exchange  messages
Xwith.  This  automatically gives access to other networks. I sug-
Xgest the following strategy:
X
X - Get a uucp login, say, uuxyz on a UNIX system. This will  also
Xbecome the uucp-node name of the pc. The file /usr/lib/uucp/L.sys
Xshould be extended with an entry, e.g.
X
X uuxyz Passive
X
X(on some systems one has to use `Never' instead of `Passive'). It
Xmay also be necessary to update the /usr/lib/uucp/USERFILE.
X
X - Have all mail for user uuxyz forwarded to  uuxyz!somebody.  On
XBSD  UNIX  systems,  this  is  achieved  by  placing  the address
X`uuxyz!somebody' in  a  file  ~uuxyz/.forward;  on  System-V  one
Xshould  put  the  text  `Forward  to  uuxyz!somebody' in the file
X/usr/mail/uuxyz, which should be read/writeable by group mail.
X
XIn the above examples, somebody is a  name  that  can  be  freely
Xchosen;  it  will  not  be used by the pc. Of course, mail can be
Xforwarded to uuxyz!somebody from other accounts as well.
X
XThe result of all this is that you can send mail to any  user  on
Xthe UNIX host by just specifying her login name; the host name of
Xyour pc will not appear in mail headers. People can send mail  to
Xyou  by  specifying an address on the UNIX host. There is no need
Xto register the pc in the uucp maps.
X
XIf the above strategy is not what you  like,  you  will  have  to
Xoperate  as  a  "real"  uucp node and should #define UUCP_HOST in
Xsendwork.c. You should also be registered as a uucp  node.  There
Xis more discussion about this in sendwork.c
X
XAs a minimum, the UNIX host should support the standard uucp  `g'
Xprotocol.  This  protocol was developed for eight-bit data paths.
XUnfortunately, modern networks often eat up  XON/XOFF  and  other
Xcontrol characters.
X
XTo handle non-transparent networks  I  have  written  a  protocol
Xcalled  `k'. It has been used with the Eindhoven University Sytek
Xnetwork for over two years and is part of the  pc-mail  distribu-
Xtion.  If  you're  really  desperate (and have UNIX source) build
Xthis protocol into the uucico program  by  adding  the  following
Xline to struct Proto Ptbl[] in cntrl.c:
X
X 'k', kturnon, krdmsg, kwrmsg, krddata, kwrdata, kturnoff,
X
Xand linking the uucico objects with kio.c  kp.h  kphys.c  kpres.c
Xand ktrans.c.
X
XTHE PC SIDE OF THE CONNECTION
X
XTo bring pc-mail up, edit the makefile to reflect the system  you
Xare  using  (there  are  separate makefiles for UNIX and MS-DOS).
XThe MS-DOS makefile is for a UNIX-compatible make utility  posted
Xto  usenet  near  the  end of 1986. There is a batch command file
X(buidall.bat) for those who do not have  a  unix-compatible  make
Xutility.  For testing purposes it is convenient to run this stuff
Xon a UNIX host.
X
XSaying `make' should produce five programs:
X
X - mail, the menu-driven user interface
X - cmail, a program that checks if there is new mail
X - smail, a program that queues messages for  transmission  after
X          doing alias substitution on mail addresses
X - cico, the program that performs dialups and file transfers
X - rmail, extracts "From" info from mail received by cico
X
XThe programs access a common data base in the  form  of  a  spool
Xdirectory  with  setup  file,  logfile  and  message files. There
Xshould be no  other  files  in  the  spool  directory,  to  avoid
Xconfusion.  You  will  have  to  create  the spool directory; the
Xprograms will not do that.
X
XYou will have to set some environment  variables  before  running
Xthe mail program.
X
X - MAILDIR, the absolute path to your spool directory
X - EDITOR, the name of your favourite editor program
X - PATH, in order locate the executables
X
XThe editor command may be an MS-DOS batch file; in that case  you
Xshould include the '.bat' suffix in the command name.
X
XThe following two environment variables are optional.
X
X - MAILPRN, if printer output should not go to PRN
X - MAILCMD, command that is executed when the mail program  exits
X
XAlso,  make  sure  that  the limit on the number of open files is
Xlarge enough (20 or so). On MS-DOS, this is  handled  by  a  line
X`files=20' in the CONFIG.SYS file.
X
XRun the interactive mail program and choose the setup command. On
XMS-DOS  systems  only  the  com1  port  is  supported  (see  file
Xcomport.s). Here is my setup (some  names  changed)  for  getting
Xthrough the TUE port selector:
X
X    communications_port: com1
X    baud_rate:           1200
X    remote_host_name:    eutwc1
X    login_name:          uutest
X    dialup_sequence:     atm\r OK atdt455215\r CONNECT \0 ease: xyz\r ease: 
Xxyz\r choice: 1\r called: b076\r CLOSED \r
X    disconnect_sequence: \0
X
XAll entries must be filled or the  cico  program  will  complain.
XThe MS-DOS version supports the com1 port only.
X
XThe dial-up sequence requires some explanation. Basically it is a
Xlist  of words separated by whitespace. The first word is sent to
Xthe comm. port. The program  will  wait  until  it  receives  the
Xsecond word. And so on. Unlike real uucp (or kermit), there is no
Xretry facility. The backslash escape sequences  are  stolen  from
Xthe c programming language, with some extensions:
X
X \b	backspace
X \f	formfeed
X \n	linefeed
X \r	carriage return
X \s	blank
X \t	tab
X \\	backslash
X \nnn	octal code for a character
X
XIn order to send or expect an empty string, use the \0 sequence.
X
XIt is not possible to send null characters. The dial-up  sequence
Xshould terminate when the UNIX host displays its "login:" prompt;
Xthe remainder of the dialup sequence is built into the  software.
XThis,  and  having  (pc  node  name)  == (uucp login name) are to
Xprevent fraud. Thus,  assuming  a  Hayes-compatible  modem,  your
Xdialup sequence could be as simple as:
X
X    atm\r OK atdt455215\r CONNECT \0 
X
XWhen this dialup sequence succeeds, the  program  continues  with
Xits built-in sequence:
X
X    ogin: login_name\r ssword: your_password\r
X
XThe disconnect sequence uses the same  escape  sequences  as  the
Xdial-up  sequence,  but does not use the send/expect protocol. In
Xthe above sequence, the disconnect sequence is an empty string.
X
XIf the cico program has problems communicating with the UNIX host
Xyou can run it by hand, for example:
X
X cico -d 9 -p your_password
X
Xwhich will  produce  a  lot  of  debugging  output.  Setting  the
Xdebugging  level  to less than 9 produces less output. Level 4 is
Xsufficient to monitor the dial-up and login sequence.
X
XALIAS DATABASE
X
XThe user can define aliases for (groups of) mail  addresses.  The
Xformat  of  the alias data base is simple: it is a text file with
Xon each line:
X
X alias replacement part
X
XThe replacement  part  may  be  one  or  more  words;  words  are
Xseparated  by  blanks,  tabs  or commas. Whenever the smail (mail
Xspooler) program recognizes an  alias,  it  is  replaced  by  the
X`replacement'  part.  Aliases  may  be  defined in terms of other
Xaliases; also the order in which they appear in  the  alias  data
Xbase  is not important (except when an alias is defined more than
Xonce; the program  remembers  only  the  last  definition  of  an
Xalias).  The  alias  expansion software is smart enough to detect
Xinfinite loops and to suppress multiple occurrances of  the  same
Xrecipient. Alias substitution is not case-sensitive.
X
XBATCH-MODE OPERATION
X
XThe cmail program can be run from a batch file (say each time the
Xpc  is  turned on), contact the UNIX host, and report if there is
Xnew mail. Also, you may want to auto-execute  the  cmail  command
Xwhen exiting from the interactive mail shell. See the manual page
Xin the cmail.c source.
X
END_OF_Installation
if test 7515 -ne `wc -c <Installation`; then
    echo shar: \"Installation\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f cmail.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"cmail.c\"
else
echo shar: Extracting \"cmail.c\" \(3509 characters\)
sed "s/^X//" >cmail.c <<'END_OF_cmail.c'
X/*++
X/* NAME
X/*	cmail 1
X/* SUMMARY
X/*	report if there are unread messages
X/* PROJECT
X/*	pc-mail
X/* PACKAGE
X/*	cmail
X/* SYNOPSIS
X/*	cmail [-p password]
X/* DESCRIPTION
X/*	cmail reports if there are unread mail messages in the
X/*	pc-mail spool directory.
X/*	
X/*	If the -p option is present, cmail first invokes the cico
X/*	program to contact the mail server host.
X/*
X/*	Typically cmail is run immediately after system startup,
X/*	while you are getting your first cup of coffee.
X/*
X/*	The program returns a nonzero exit status if it could not 
X/*	find any mail.
X/* COMMANDS
X/*	cico	file transfer program
X/*	rmail	processes new mail
X/* FILES
X/*	Various files in the spool directory
X/*
X/*	LOGFILE system status messages
X/*	n<seqno> mail messages
X/*	h<seqno> header line of new mail
X/*	o<seqno> header line of old mail
X/* DIAGNOSTICS
X/*	Error messages in case the environment is not properly set up.
X/* BUGS
X/*	Invites people to put their mail password into the autoexec file.
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  3 19:34:57 MET 1988
X/* LAST MODIFICATION
X/*	Wed Apr  6 00:18:45 MET 1988
X/* VERSION/RELEASE
X/*	1.3
X/*--*/
X
X#include <signal.h>
X
X#include "defs.h"
X#include "dir.h"
X#include "path.h"
X#include "status.h"
X
Xhidden void parse_args();		/* forward declarations */
Xhidden void usage();
Xhidden void error();
Xhidden int newmail();
X
Xhidden char *password = 0;		/* set by the -p option */
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    if (pathinit())			/* check path info */
X	error("cmail: bad MAILDIR environment variable");
X    if (password && *password && 
X	invokelp(CICO,"-p",password,(char *)0) == E_NOPROG)
X	error("cmail: cannot execute the CICO program");
X    if (invokelp(RMAIL,(char *)0) == E_NOPROG)
X	error("cmail: cannot execute the RMAIL program");
X    exit(newmail() == 0);				/* look for new mail */
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 'p':					/* call cico first */
X	    if (--argc == 0)
X		usage("missing password");
X	    password = *++argv;
X	    break;
X	default:					/* unknown option */
X	    usage(strcons("invalid option: -%s",*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 unread mail */
X
Xhidden int newmail()
X{
X    register int dd;
X    int pfxlen = sizeof(HDRPFX)-1;
X    char *f;
X    FILE *fp;
X    char from[BUFSIZ];
X    register int msgcount = 0;
X
X    /*
X    * Scan the spool directory for unread messages and extract
X    * the originator address from the corresponding meta file.
X    */
X
X    for (dd = opendir(maildir); f = readdir(dd); /* void */) {
X	int seqno;
X	if (strncmp(f,HDRPFX,pfxlen) == 0 && sscanf(f+pfxlen,"%d",&seqno)) {
X	    if (fp = fopen(new_meta(seqno),"r")) {
X		fgets(from,BUFSIZ,fp);
X		printf("You have new mail from %s",from);
X		msgcount++;
X		fclose(fp);
X	    }
X	}
X    }
X    closedir(dd);
X    return(msgcount);
X}
X
Xhidden void error(str)
Xchar *str;
X{
X    fprintf(stderr,"%s\n",str);
X    exit(1);
X}
X
Xhidden void usage(str)
Xchar *str;
X{
X    fprintf(stderr,"%s\nusage: cmail [-p password]\n",str);
X    exit(1);
X}
END_OF_cmail.c
if test 3509 -ne `wc -c <cmail.c`; then
    echo shar: \"cmail.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f dir.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"dir.c\"
else
echo shar: Extracting \"dir.c\" \(6998 characters\)
sed "s/^X//" >dir.c <<'END_OF_dir.c'
X/*++
X/* NAME
X/*      opendir,readdir,closedir 3
X/* SUMMARY
X/*      directory search functions
X/* PROJECT
X/*      dos/unix compatibility
X/* PACKAGE
X/*      library routines
X/* SYNOPSIS
X/*      int opendir(path)
X/*      char *path;
X/*
X/*      char *readdir(id)
X/*      int dir;
X/*
X/*      closedir(id)
X/*      int id;
X/* DESCRIPTION
X/*      This package provides a system-independent interface to the file system
X/*      that allows a program to simultaneously scan one or more directories.
X/*
X/*	The MS-DOS version accepts both forward and backward slash as
X/*	field delimiter in path names.
X/*
X/*      opendir() accepts a valid path and returns an id which should be used 
X/*      in subsequent calls of readdir()....closedir().
X/*
X/*      readdir() returns a pointer to a character string with the next file in
X/*      the directory associated with id, or a null pointer. 
X/*
X/*      closedir() terminates the directory search and deallocates
X/*      memory used to keep track of `certain important data'.
X/* FUNCTIONS AND MACROS
X/*      myalloc()
X/* DIAGNOSTICS
X/*      opendir() returns -1 if all slots are in use.
X/*      Specifying a wrong id is considered a fatal error condition.
X/*      Memory allocation errors cause the program to terminate.
X/* BUGS
X/*      readdir() returns a pointer to memory
X/*      whose contents is overwritten with each call.
X/*
X/*	Despite whatthe names suggest, these functions are not compatible
X/*	with the BSD directory access routines.
X/*
X/*	Does not work with unix file systems that have variable-length
X/*	directory entries (BSD).
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 Nov 17 19:38:19 GMT+1:00 1986
X/* LAST MODIFICATION
X/*	Mon Apr  4 23:38:43 MET 1988
X/* VERSION/RELEASE
X/*	1.3
X/*--*/
X
X#include "defs.h"
X#include "dir.h"
X
X#ifdef	unix
X#   include <sys/types.h>
X#   include <sys/dir.h>
X#endif
X
X#ifdef	MSDOS
X#   include <dos.h>
X#   include <ctype.h>
X
Xhidden void badslot();			/* forward declarations */
Xhidden void lowcpy();
X
X/* 
X* The Disk Transfer Area as used by MS-DOS when it finds a file name 
X* during a wild-card scan.
X*/
X
X#define MAXNAME         13      /* max size of MS-DOS file name + null byte */
X
Xtypedef struct Dta {
X    char reserved[21];          /* start of dta buffer */ 
X    char found;                 /* attribute found */
X    short time;                 /* file's time */
X    short date;                 /* file's date */
X    int losize;                 /* low order file size */
X    int hisize;                 /* high-order file size */
X    char name[MAXNAME];         /* name of file terminated by zero byte */
X} Dta;
X
X/* macros for easy access to registers with MS-DOS system calls */
X
X#define AH              regs.h.ah               /* ah register */
X#define BX              regs.x.bx               /* bx register */
X#define CX              regs.x.cx               /* cx register */
X#define DX              regs.x.dx               /* dx register */
X#define CF              regs.x.cflag            /* cflag register */
X#define INT             intdos(&regs,&regs)     /* dos system call */
X#define WORD            (unsigned)              /* cast */
X
X#define SET_DTA(d)      { AH = 0x1a; DX = WORD d; INT; }
X#define GET_DTA(d)      { AH = 0x2f; INT; d = BX; }
X#define GET_1ST(f,n)    { AH = 0x4e; CX = 0x10; DX = WORD n; INT; f = CF; }
X#define GET_NXT(f)      { AH = 0x4f; CX = 0x10; INT; f = CF; }
X
X/* information about directory accesses is kept in a table with initially */
X/* empty slots */
X
X#define MAXSLOT 20              /* nbr of directories that can be processed */
X
Xtypedef struct Slot {
X    unsigned int dsave;         /* temp storage for disk transfer address */
X    unsigned int cstat;         /* MS-DOS system call return status */
X    Dta dta;                    /* disk transfer area */
X} Slot;
X
Xhidden Slot *dirslots[20];      /* slots with pointers */
X
X#endif	/* MSDOS */
X
X/* opendir - set up for directory search */
X
X#ifdef	MSDOS
X
Xpublic int opendir(name)
Xchar *name;
X{
X    register int id;
X    register Slot *q;
X    char buf[BUFSIZ];
X    union REGS regs;                    /* cpu registers in system call */
X    char lch;
X
X    for (id = 0; id < MAXSLOT && dirslots[id]; id++)
X	;                               /* search first free slot */
X    if (id < MAXSLOT) {                 /* found a free slot */
X	dirslots[id] = q = (Slot *) myalloc(sizeof(Slot));
X	GET_DTA(q->dsave);              /* save dta address */
X	SET_DTA(&q->dta);               /* set to current dta */
X	strcpy(buf,name);               /* construct search path */
X	if (*name && index("\\/:",name[strlen(name)-1]) == 0)
X	    strcat(buf,"/");
X	strcat(buf,"*.*");              /* append wildest possible file name */
X	GET_1ST(q->cstat,buf);          /* start search (read one name ahead) */
X	SET_DTA(q->dsave);              /* restore dta address */
X	return(id);                     /* return offset in slots table */
X    } else {
X	return(-1);                     /* no free slot available */
X    }
X}
X
X#endif	/* MSDOS */
X
X/* readdir - return next file in directory or null string */
X
X#ifdef	unix
X
Xpublic char *readdir(id)
Xint id;
X{
X    static struct direct ent[2];
X
X    for (;;) {
X	if (read(id,(char *) ent,sizeof(*ent)) != sizeof(*ent))
X	    return(0);
X	if (ent[0].d_ino != 0)
X	    return(ent[0].d_name);
X    }
X}
X
X#endif	/* unix */
X
X#ifdef	MSDOS
X
Xpublic char *readdir(id)
Xint id;
X{
X    register Slot *q;
X    union REGS regs;
X    static char buf[MAXNAME];
X
X    if (id < 0 || id >= MAXSLOT || (q = dirslots[id]) == 0) {
X	badslot("readdir",id);		/* serves you well! */
X	/* NOTREACHED */
X    } else if (q->cstat) {
X	return(0);			/* no name found */
X    } else {
X	lowcpy(buf,q->dta.name);        /* keep name (lower case) */
X	GET_DTA(q->dsave);              /* save dta address */
X	SET_DTA(&q->dta);               /* setup to search */
X	GET_NXT(q->cstat);              /* for the next entry */
X	SET_DTA(q->dsave);              /* in the directory */
X	return buf;                     /* return name */
X    }
X}
X
X#endif	/* MSDOS */
X
X/* closedir - release directory access slot */
X
X#ifdef	MSDOS
X
Xpublic int closedir(id)
Xint id;
X{
X    register Slot **p;
X
X    if (id < 0 || id >= MAXSLOT || *(p = dirslots+id) == 0) {
X	badslot("closedir",id);
X	/* NOTREACHED */
X    } else {
X	free((char *)*p);               /* deallocate slot */
X	*p = 0;                         /* mark as unused */
X	return(0);
X    }
X}
X
X#endif	/* MSDOS */
X
X#ifdef	MSDOS
X
X/* badslot - the program is obviously corrupted. stop it. */
X
Xhidden void badslot(name,id)
Xchar *name;
Xint id;
X{
X    fatal("%s: bad slot: %d\n",name,id);
X}
X
X/* lowcpy - copy string and map to lower case */
X
Xhidden void lowcpy(out,in)
Xchar *out;
Xchar *in;
X{
X    register char *d = out;
X    register char c;
X    register char *s = in;
X
X    while (c = *s++)
X	*d++ = isupper(c) ? tolower(c) : c;
X    *d = '\0';
X}
X
X#endif	/* MSDOS */
END_OF_dir.c
if test 6998 -ne `wc -c <dir.c`; then
    echo shar: \"dir.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f file.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"file.c\"
else
echo shar: Extracting \"file.c\" \(6599 characters\)
sed "s/^X//" >file.c <<'END_OF_file.c'
X/*++
X/* NAME
X/*      file 3
X/* SUMMARY
X/*      manipulate ordinary files
X/* PROJECT
X/*      pc-mail
X/* PACKAGE
X/*      mailsh
X/* SYNOPSIS
X/*      int file()
X/*
X/*	int junk_file()
X/* DESCRIPTION
X/*      file() is called when the user selected the "file" option
X/*	in the main menu. The pager displays a directory listing on the
X/*      screen. The user may then walk through the file display and
X/*	select a file or directory. 
X/*
X/*	In case a regular file is selected the user may specify
X/*	an action (send file as mail, delete file, display
X/*	file, print file, copy file to workfile for subsequent
X/*	editing etc.).
X/*
X/*	junk_file() should be invoked when the file display is no longer
X/*	valid.
X/* FILES
X/*      By selecting directory files the user can walk through the whole
X/*      file system.
X/* SEE ALSO
X/*      kbdinp(3), pager(3)
X/* BUGS
X/*	On some MS-DOS systems, we never get the ".." entry.
X/*	This is an unsolved problem.
X/*
X/*	Changing the current directory may cause problems if
X/*	the MAILDIR and EDITOR environment variables hold
X/*	relative path names.
X/*
X/*	No provision to change default drive on MS-DOS systems.
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  5 17:18:06 GMT+1:00 1987
X/* LAST MODIFICATION
X/*	Mon Apr  4 23:40:13 MET 1988
X/* VERSION/RELEASE
X/*	1.3
X/*--*/
X
X#include <time.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <ctype.h>
X#include "defs.h"
X#include "screen.h"
X#include "pager.h"
X#include "mailsh.h"
X#include "dir.h"
X#include "path.h"
X#include "status.h"
X#include "window.h"
X
Xextern struct tm *localtime();          /* std C library */
X
Xhidden File *bldlist();			/* forward declaration */
Xhidden int show_list();
Xhidden int pick_file();
Xhidden int delfile();
Xhidden int show_file();
Xhidden int rmfile();
X
Xhidden File *dfile = 0;			/* file listing */
Xhidden File *dirfile = 0;               /* directory listing */
X
X/* file - called from keyboard interpreter, call keyboard driver */
X
Xpublic int file()
X{
X    static Screen screen[] = {
X	'C',	"Close",        0,      initscreen,
X	'P',	"Print",        print,	"Print file listing",
X	'S',	"Save",         save,	"Save file listing to ordinary file",
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	ENTER,	"Enter",        pick_file,"Display file at cursor",
X	0,	0,              show_list,
X	"To display a file, select it with cursor keys, then press ENTER",
X    };
X
X    kbdinp(screen);			/* set up dialogue */
X    close_pager(dirfile);		/* deallocate pager file */
X    dirfile = 0;			/* say it's gone */
X    return(S_REDRAW);			/* force screen update */
X}
X
X/* show_list - create or refresh file listing */
X
Xhidden int show_list()
X{
X    if (dirfile == 0) {			/* no pager file? */
X	patience();
X	dirfile = bldlist();		/* create one */
X    } else {
X	set_pager(dirfile);		/* select existing pager file */
X    }
X    ds_pager();				/* display the thing */
X    return(0);				/* say screen is up-to-date */
X}
X
X/* bldlist - build file listing display */
X
Xhidden File *bldlist()
X{
X    register int dd = opendir(THISDIR);	/* start directory search */
X    register File *pp = open_pager();	/* allocate pager file */
X    register char *f;			/* file name pointer */
X
X    while (f = readdir(dd)) {		/* read next file name */
X	struct stat s;
X	if (stat(f,&s) == 0) {		/* get file info (size, date) */
X	    app_pager(pp,strcons("%-20s %9ld %s",f,
X		s.st_size,tstamp(&s.st_mtime)));
X	} else {
X	    app_pager(pp,f);
X	}
X    }
X    sort_pager(pp,FORW_SORT);		/* sort by file name */
X    closedir(dd);			/* directory search done */
X    return(pp);				/* current pager file */
X}
X
X/* pick_file - display selected file or change directory */
X
Xhidden int pick_file()
X{
X    static char botline[80];
X    static Screen screen[] = {
X	'C',	"Close",        0,      "Return to file listing",
X	'D',	"Delete",	delfile,"Delete this file",
X	'M',	"Mail",		mailfile,"Mail a copy of this file",
X	'P',	"Print",        print,	"Print this file",
X	'S',	"Save",         save,	"Save a copy to an ordinary file",
X	'W',	"Work",		makework,"Save a copy to a work file",
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_file,
X	botline,
X    };
X    struct stat s;
X
X    if (scan_pager(dirfile,"%s",message) == 0) {	/* cannot read name */
X	beep();						/* "notify" user */
X	return(0);					/* nothing happened */
X    } else if (access(message,04) || stat(message,&s)) {/* cannot read file */
X	beep();						/* "notify" user */
X	return(0);					/* nothing happened */
X    } else if ((s.st_mode&S_IFMT) == S_IFDIR) {         /* directory file */
X	chdir(message);					/* change directory */
X	close_pager(dirfile);				/* purge display */
X	dirfile = bldlist();				/* new file display */
X	return(S_REDRAW);				/* update display */
X    } else {                                            /* ordinary file */
X 	sprintf(botline,"(Reading file \"%s\")",message);
X	kbdinp(screen);					/* look at screen */
X	close_pager(dfile);				/* and forget it */
X	dfile = 0;					/* say it's gone */
X	return(S_REDRAW);                               /* force redrawing */
X    }
X}
X
X/* show_file - create or refresh display of selected file */
X
Xhidden int show_file()
X{
X    if (dfile) {
X	set_pager(dfile);				/* select dispay */
X    } else {
X	if (rd_pager(dfile = open_pager(),message))	/* try to read file */
X	    mesg_pager(dfile,m_msgread);		/* read error */
X    }
X    ds_pager();						/* rewrite screen */
X    return(0);						/* screen up-to-date */
X}
X
X/* delfile - ask confirmation before removing a file */
X
Xhidden int delfile()
X{
X    static Screen screen[] = {
X	ESCCR,	0,		rmfile,int_error,
X	0,	0,		0,
X	"Press ESC to cancel. Confirm with ENTER",
X    };
X
X    return(kbdinp(screen)|S_REDRAW);		/* "are you sure?" */
X}
X
X/* rmfile - actually remove file */
X
Xhidden int rmfile()
X{
X    if (unlink(message)) {			/* try to remove file */
X	errdisp(E_UNLINK);			/* notify the user */
X	return(S_BREAK|S_REDRAW);		/* redisplay, stop caller */
X    } else {
X	junk_file();				/* say file display outdated */
X	return(S_BREAK);			/* terminate caller */
X    }
X}
X
X/* junk_file - directory listing is no longer up to date */
X
Xpublic int junk_file()
X{
X    if (dirfile) {
X	close_pager(dirfile);			/* close pager file */
X	dirfile = 0;				/* say it is gone */
X    }
X    return(0);					/* in case we need that */
X}
END_OF_file.c
if test 6599 -ne `wc -c <file.c`; then
    echo shar: \"file.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f gphys.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"gphys.c\"
else
echo shar: Extracting \"gphys.c\" \(6855 characters\)
sed "s/^X//" >gphys.c <<'END_OF_gphys.c'
X/*++
X/* NAME
X/*	gphys 3
X/* SUMMARY
X/*	g protocol packet input/output
X/* PROJECT
X/*	pc-mail
X/* PACKAGE
X/*	cico
X/* SYNOPSIS
X/*	#include "gp.h"
X/*
X/*	void gsctrl(fd,c)
X/*	int fd,c;
X/*
X/*	void gsdata(fd,pk,c)
X/*	int fd,c;
X/*	Packet *pk;
X/*
X/*	int grpack(fd,pk)
X/*	int fd;
X/*	Packet *pk;
X/* DESCRIPTION
X/*	The functions in this module send and receive packets. Interfacing
X/*	is based on Packet structures. Messages are interpreted elsewhere.
X/*
X/*	gsctrl() sends a control packet to the remote receiver (no data
X/*	segment).
X/*
X/*	gsdata() sends a data packet to the remote receiver. 
X/*	The Packet structure is completed with a 16-bit checksum.
X/*	This function expects read/write sequence information in 
X/*	the c parameter.
X/*
X/*	grpack() receives a packet from the remote transmitter and checks
X/*	its integrity. It fills in the k, c, len and check fields of the 
X/*	Packet structure and returns the type of message (DATA, SHORT, 
X/*	CLOSE, RJ, RR, etcetera).
X/* DIAGNOSTICS
X/*	grpack() returns FAIL if a corrupted packet was received, and
X/*	TIME if no packet was received within the time-out interval.
X/* BUGS
X/*	No data re-reading in case of transmission errors.
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 11:39:27 GMT+1:00 1987
X/* LAST MODIFICATION
X/*	Mon Apr  4 23:41:15 MET 1988
X/* VERSION/RELEASE
X/*	1.3
X/*--*/
X
X#include <signal.h>
X#include <setjmp.h>
X#include "gp.h"
X
X/* local and forward declarations */
X
Xstatic jmp_buf timebuf;
Xstatic int chksum(),readhead(),readdata(),clkint();
X
X#define	READ(fd,cp,n)	{ if (read(fd,cp,n) != n) clkint(); }
X
X/*
X* "A six byte framing envelope is constructed using the control"
X* "byte C of a packet and five other bytes as depicted below."
X*		<DLE><k><c0><c1><C><x>
X* "The <DLE> symbol denotes the ASCII ctrl/P character. If the"
X* "envelope is to be followed by a data segment, <k> has the"
X* "value log2(size)-4; i.e. 1 <= k < 8. If k is 9, then the"
X* "envelope represents a control packet. The <c0> and <c1>"
X* "bytes are the low-order and high-order bytes respectively of"
X* "0xAAA minus a 16-bit checksum. For control packets, this"
X* "16-bit checksum is the same as the control byte C. For data"
X* "packets, the checksum is calculated by the program below."
X* "The <x> byte is the exclusive-or of <k><c0><c1><C>. Error"
X* "control is accomplished by checking a received framing"
X* "envelope for compliance with the definition, and comparing a"
X* "checksum function of the data segment with <c0><c1>."
X*/
X
X/* gsctrl - send control packet (no data segment) */
X
Xvoid gsctrl(fd,c)
Xint fd,c;
X{
X    char header[6];
X    register char chkhdr;
X    register char *cp = header;
X    int cksm = MAGIC-c;				/* do checksum */
X
X    *cp++ = CTRL('P');				/* start of header */
X    chkhdr  = *cp++ = KCTRL;			/* k byte (control) */
X    chkhdr ^= *cp++ = cksm;			/* c0 byte (checksum lsb) */
X    chkhdr ^= *cp++ = cksm>>8;			/* c1 byte (checksum msb) */
X    chkhdr ^= *cp++ = c;			/* message|sequence info */
X    *cp = chkhdr;				/* header checksum */
X
X    write(fd,header,sizeof(header));		/* send header */
X    DEBUG(9,"xmt: %o\n",c&0377);		/* show header */
X}
X
X/* gsdata - send data packet */
X
Xvoid gsdata(fd,pk,c)
Xint fd,c;
Xregister Packet *pk;
X{
X    char header[6];
X    register char chkhdr;
X    register char *cp = header;
X    int cval = pk->c|(c&077);			/* fold in sequence info */
X
X    pk->chk = MAGIC-(chksum(pk->data,pk->len)^(0377&cval));
X
X    *cp++ = CTRL('P');				/* start of header */
X    chkhdr  = *cp++ = pk->k;			/* k byte (message length) */
X    chkhdr ^= *cp++ = pk->chk;			/* c0 byte (checksum lsb) */
X    chkhdr ^= *cp++ = pk->chk>>8;		/* c1 byte (checksum msb) */
X    chkhdr ^= *cp++ = cval;			/* data|sequence info */
X    *cp = chkhdr;				/* header checksum */
X
X    write(fd,header,sizeof(header));		/* send header */
X    DEBUG(9,"xmt: %o\n",cval&0377);		/* show header */
X
X    write(fd,pk->data,pk->len);			/* send data segment */
X    DEBUG(9,"xmt: data %d bytes\n",pk->segl);	/* show data */
X}
X
X/* grpack - receive one data or control packet; return packet type info */
X
Xint grpack(fd,pk)
Xint fd;
Xregister Packet *pk;
X{
X    if (setjmp(timebuf))			/* in case we time out */
X	return(TIME);				/* it just happened */
X    signal(SIGALRM,clkint);			/* alarm clock response */
X    alarm(ALARM);				/* set alarm clock */
X
X    if (readhead(fd,pk)) {			/* read packet header */
X	DEBUG(7,"rcv: bad header\n","");
X	alarm(0);				/* turn timer off */
X	return(FAIL);				/* header checksum error */
X    } else if (pk->k == KCTRL) {
X	alarm(0);				/* turn timer off */
X	return(MESG(pk->c));			/* CLOSE | RJ | RR etcetera */
X    } else if (readdata(fd,pk)) {
X	DEBUG(7,"rcv: bad data\n","");
X	alarm(0);				/* turn timer off */
X	return(FAIL);				/* data checksum error */
X    } else {
X	alarm(0);				/* turn timer off */
X	return(TYPE(pk->c));			/* DATA | SHORT */
X    }
X}
X
X/* readhead - read header and check header checksum */
X
Xstatic int readhead(fd,pk)
Xint fd;
Xregister Packet *pk;
X{
X    char header[5];
X    int ok;
X    register char chkhdr;
X    register char *cp = header;
X
X    do {					/* start reading */
X	READ(fd,cp,1);				/* skip all garbage */
X    } while (*cp != CTRL('P'));			/* up to packet header */
X
X    READ(fd,header,sizeof(header));		/* read packet header */
X
X    chkhdr  = pk->k = *cp++;			/* data length or control */
X    chkhdr ^= pk->chk = *cp++&0377;		/* data checksum lsb */
X    chkhdr ^= *cp;
X    pk->chk |= (*cp++&0377)<<8;	/* data checksum msb */
X    chkhdr ^= pk->c = *cp++;			/* control packet or data */
X    if (ok = (chkhdr == *cp))
X	DEBUG(9,"rcv: %o\n",pk->c&0377);
X    return(!ok);				/* check the checksum */
X}
X
X/* readdata - read data segment and check data checksum */
X
Xstatic int readdata(fd,pk)
Xint fd;
Xregister Packet *pk;
X{
X    if (seglen[pk->k] > pk->len) {
X	DEBUG(7,"rcv: data %d bytes too big\n",seglen[pk->k]);
X	return(1);
X    } else {
X	register int i;
X	DEBUG(9,"rcv: data %d bytes\n",pk->len = seglen[pk->k]);
X	for (i = 0; i < pk->len; i++) {
X	    READ(fd,&pk->data[i],1);
X	}
X	return(pk->chk+(chksum(pk->data,pk->len)^(pk->c&0377)) != MAGIC);
X    }
X}
X
X/* clkint - tiny time-out routine */
X
Xstatic int clkint()
X{
X    DEBUG(9,"rcv: timed out\n","");
X    longjmp(timebuf,1);
X    /* NOTREACHED */
X}
X
X/* chksum - unix packet driver checksum algorithm */
X
Xstatic int chksum(s,n)
Xregister char *s;
Xregister n;
X{
X    register short sum;
X    register unsigned short t;
X    register short x;
X
X    sum = -1;
X    x = 0;
X    do {
X	if (sum < 0) {
X	    sum <<= 1;
X	    sum++;
X	} else
X	    sum <<= 1;
X	t = sum;
X	sum += (unsigned)*s++ & 0377;
X	x += sum ^ n;
X	if ((unsigned short)sum <= t) {
X	    sum ^= x;
X	}
X    } while (--n > 0);
X
X    return(sum);
X}
END_OF_gphys.c
if test 6855 -ne `wc -c <gphys.c`; then
    echo shar: \"gphys.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f kphys.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"kphys.c\"
else
echo shar: Extracting \"kphys.c\" \(7524 characters\)
sed "s/^X//" >kphys.c <<'END_OF_kphys.c'
X/*++
X/* NAME
X/*      kphys 3
X/* SUMMARY
X/*      k protocol packet exchange
X/* PACKAGE
X/*      uucp across the TUEnet
X/* SYNOPSIS
X/*      #include "kp.h"
X/*
X/*      kspack(fd,type,num,size,data) 
X/*      int fd, num, size;
X/*      char type, data[MAXPACKSIZ];
X/*
X/*      krpack(fd,num,size,data)
X/*      int fd, *num, *size;
X/*      char data[MAXPACKSIZ];
X/* DESCRIPTION
X/*      The functions in this file take care of data framing and verification. 
X/*
X/*      Kspack() sends a packet of the specified type and number,
X/*      and with len data bytes.
X/*
X/*      Krpack() tries to receive a packet and returns: the packet type plus
X/*      size and data, or TIME (no packet) or FAIL (bad checksum).
X/*
X/*      The data format has been derived from kermit implementations:
X/*
X/* .nf
X/* .in +5
X/*      SOH     packet header, ASCII control-P
X/*      len     (size of data, low 6 bits) + 32
X/*      len     (size of data, high 6 bits) + 32
X/*      num     (packet number mod 64) + 32
X/*      type    packet type
X/*      check   one-byte type-1 kermit checksum
X/*
X/*      The header is followed by checksummed data if len >0:
X/*
X/* .nf
X/* .in +5
X/*      data    len data bytes
X/*      check1  (upper 2 bits of type-3 kermit 16-bit checksum) + 32
X/*      check2  (middle 6 bits of type-3 kermit 16-bit checksum) + 32
X/*      check3  (lower 6 bits of type-3 kermit 16-bit checksum) + 32
X/*
X/*      Every packet is followed by an ASCII carriage return, which is
X/*      ignored upon reception of a packet. It prevents timeout errors
X/*      when one byte gets lost (the most common case).
X/* BUGS
X/*      It is yet another convention for data framing.
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:38:14 MET 1986
X/* LAST MODIFICATION
X/*	Mon Apr  4 23:43:13 MET 1988
X/* VERSION/RELEASE
X/*	1.5
X/*--*/
X
X#include <signal.h>
X#include <setjmp.h>
X#include "kp.h"
X
X#define READS(fd,ch)    {if (read(fd,&ch,1) < 0) clkint(); if ((ch &= 0177) == SOH) goto SYNC;}
X
Xjmp_buf env;                /* Environment ptr for timeout longjump */
X
Xclkint()                                /* Timer interrupt handler */
X{
X    longjmp(env,TRUE);                  /* Tell krpack to give up */
X}
X
Xkspack(fd,type,num,len,data)
Xint fd;
Xchar type, *data;
Xint num, len;
X{
X    char chksum, header[6], chk[3];     /* Checksums, header */
X
X    DEBUG(7,"xmt: type %c\n",type);
X    if (len > 0)
X	DEBUG(7,"xmt: data %d\n",len);
X
X    header[0] = SOH;                    /* Packet marker (SOH) */
X    header[1] = tosix(len);             /* Send the character count */
X    chksum    = header[1];              /* Initialize the checksum */
X    header[2] = tosix(len>>OUT);        /* Send the character count */
X    chksum   += header[2];              /* Update checksum */
X    header[3] = tochar(num);            /* Packet number */
X    chksum   += header[3];              /* Update checksum */
X    header[4] = type;                   /* Packet type */
X    chksum   += header[4];              /* Update checksum */
X    chksum    = (((chksum&0300) >> 6)+chksum)&077; /* Compute header checksum */
X    header[5] = tochar(chksum);         /* Put it in the packet */
X    write(fd,header,6);                /* Send the header */
X
X    if (len > 0) {                      /* Make data packet */
X	write(fd,data,len);           /* Send data */
X	chk3(data,len,chk);           /* Compute 16-bit checksum */
X	write(fd,chk,3);              /* Send checksum */
X    }
X    write(fd,"\r",1);                   /* Extra-packet line terminator */
X}
X
Xkrpack(fd,num,len,data)
Xint fd;
Xint *num;                               /* Packet number */
Xint *len;                               /* Packet length */
Xchar *data;                             /* Packet data */
X{
X    int i;                              /* Data character number, loop exit */
X    char t,                             /* Current input character */
X    type,                           /* Packet type */
X    rchk[3],                        /* Data checksum from host */
X    cchk[3],                        /* Data checksum computed here */
X    cchksum,                        /* Our (computed) checksum */
X    rchksum;                        /* Header checksum from other host */
X
X    if (setjmp(env)) {
X	DEBUG(7,"rcv: timed out\n","");
X	return TIME;                    /* Timed out */
X    }
X    signal(SIGALRM,clkint);             /* Setup the timeout */
X    alarm(TIMEOUT);
X
X    for (;;)                            /* Wait for packet header */
X	READS(fd,t);
XSYNC:                                   /* Got SOH */
X    alarm(TIMEOUT);
X    DEBUG(7,"rcv: found sync\n","");
X    READS(fd,t);                        /* Get character */
X    cchksum = t;                        /* Start the checksum */
X    *len = unchar(t);                   /* Character count, low six bits */
X
X    READS(fd,t);                        /* Get character */
X    cchksum += t;                       /* Update checksum */
X    *len += (unchar(t)<<OUT);           /* Character count, high six bits */
X
X    READS(fd,t);                        /* Get character */
X    cchksum += t;                       /* Update checksum */
X    *num = unchar(t);                   /* Packet number */
X
X    READS(fd,t);                        /* Get character */
X    cchksum += t;                       /* Update checksum */
X    type = t;                           /* Packet type */
X
X    READS(fd,t);                        /* Get header checksum */
X    rchksum = unchar(t);                /* Convert to numeric */
X    /* Fold in bits 7,8 to compute */
X    cchksum = (((cchksum&0300) >> 6)+cchksum)&077; /* header checksum */
X
X    if (cchksum != rchksum) {
X	DEBUG(7,"rcv: bad header\n","");
X	alarm(0);                       /* Disable the timer interrupt */
X	return FAIL;
X    } 
X    DEBUG(7,"rcv: type %c\n",type);
X
X    if ((*len > 0) && (data != NULLP))
X    {
X	for (i=0; i<*len; i++)          /* The data itself, if any */
X	{                               /* Loop for character count */
X	    READS(fd,t);                /* Get character */
X	    data[i] = t;                /* Keep data */
X	}
X
X	for (i=0; i<3; i++)             /* 16-bit CRC checksum */
X	{
X	    READS(fd,t);                /* Get character */
X	    rchk[i] = t;                /* Keep data */
X	}
X
X	chk3(data,*len,cchk);           /* Compute CRC */
X	if (strncmp(rchk,cchk,3)) {     /* Check with received CRC */
X	    DEBUG(7,"rcv: bad data\n","");
X	    alarm(0);                   /* Disable the timer interrupt */
X	    return FAIL;
X	}
X	DEBUG(7,"rcv: data %d\n",*len);
X    }
X    alarm(0);				/* Disable the timer interrupt */
X    return(type);                       /* All OK, return packet type */
X}
X
X/*  C H K 3  --  Compute a type-3 Kermit block check.  */
X/*
XCalculate the 16-bit CRC of a string using a byte-oriented
Xtableless algorithm invented by Andy Lowry (Columbia University).  The
Xmagic number 010201 is derived from the CRC-CCITT polynomial x^16+x^12+x^5+1.
X*/
Xstatic chk3(s,len,chk) 
Xchar *s, *chk; 
Xint len; 
X{
X    unsigned int c, q;
X    long crc = 0;
X
X    while (len--) {
X	c = *s++;
X	q = (crc ^ c) & 017;            /* Low-order nibble */
X	crc = (crc >> 4) ^ (q * 010201);
X	q = (crc ^ (c >> 4)) & 017;     /* High order nibble */
X	crc = (crc >> 4) ^ (q * 010201);
X    }
X    *chk++ = tochar(((unsigned)(crc & 0170000)) >> 12);
X    *chk++ = tochar((crc & 07700) >> 6);
X    *chk++ = tochar(crc & 077);
X}
END_OF_kphys.c
if test 7524 -ne `wc -c <kphys.c`; then
    echo shar: \"kphys.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f makefile.uts -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"makefile.uts\"
else
echo shar: Extracting \"makefile.uts\" \(6491 characters\)
sed "s/^X//" >makefile.uts <<'END_OF_makefile.uts'
X# c compiler flags
X# -DSIII	for AT&T unix System-III or System-V
X#		for V7, BSD
XCFLAGS	= -DSIII -g
X
X# library options
X# -lcurses	for AT&T unix
X# -ltermcap	for V7, BSD
XLIBS	= -lcurses
X
X# lint options
X# -ML		for Microport
XLINTFL	= -Ml
X
XRETRIEVE= retrieve -d .arch
X
XSOURCES	= README ascf.c ascf.h call.c cico.c cmail.c comm.c comm.h \
X	connect.c defs.h desk.c deskutil.c dir.c \
X	dir.h email.c errdisp.c file.c getwork.c gp.h \
X	gphys.c gpres.c gtrans.c invoke.c kbdinp.c kio.c kp.h \
X	kphys.c kpres.c ktrans.c logs.c logs.h mailfile.c \
X	mailsh.c makework.c mbox.c myalloc.c \
X	newseqno.c pager.c pager.h params.c params.h path.c path.h \
X	protomsg.c rmail.c rmtname.c scanwork.c screen.c screen.h \
X	sendwork.c setup.c smail.c spoolfil.c startup.c \
X	status.h switcher.c sysdep.h window.c window.h \
X	work.h xpres.c comport.s str.c alias.c edit.c submit.c \
X	unalias.c hsearch.c hsearch.h clmap.h comport.h hsearch.3 \
X	buildall.bat kproto.ms Watchit makefile.uts makefile.msc \
X	mailsh.h srctoman.sh Installation Implementation termcap
X
XSHSRC	= mailsh.c call.c desk.c file.c screen.c mbox.c kbdinp.c \
X	pager.c window.c setup.c errdisp.c invoke.c path.c myalloc.c \
X	dir.c params.c newseqno.c email.c spoolfil.c ascf.c \
X	makework.c mailfile.c deskutil.c str.c alias.c edit.c submit.c
X
XSHOBJ	= mailsh.o call.o desk.o file.o screen.o mbox.o kbdinp.o \
X	pager.o window.o setup.o errdisp.o invoke.o path.o myalloc.o \
X	dir.o params.o newseqno.o email.o spoolfil.o ascf.o \
X	makework.o mailfile.o deskutil.o str.o alias.o edit.o submit.o
X
XSMSRC	= smail.c path.c dir.c newseqno.c ascf.c spoolfil.c str.c \
X	unalias.c hsearch.c
XSMOBJ	= smail.o path.o dir.o newseqno.o ascf.o spoolfil.o str.o \
X	unalias.o hsearch.o
X
XRMSRC	= rmail.c path.c dir.c str.c
XRMOBJ	= rmail.o path.o dir.o str.o
X
XCMSRC	= cmail.c path.c dir.c invoke.c str.c
XCMOBJ	= cmail.o path.o dir.o invoke.o str.o
X
XCISRC	= dir.c comm.c connect.c getwork.c kphys.c kpres.c ktrans.c logs.c \
X	cico.c myalloc.c newseqno.c params.c path.c protomsg.c rmtname.c \
X	scanwork.c sendwork.c startup.c switcher.c xpres.c \
X	gpres.c gtrans.c gphys.c str.c
X
XCIOBJ	= dir.o comm.o connect.o getwork.o kphys.o kpres.o ktrans.o logs.o \
X	cico.o myalloc.o newseqno.o params.o path.o protomsg.o rmtname.o \
X	scanwork.o sendwork.o startup.o switcher.o xpres.o \
X	gpres.o gtrans.o gphys.o str.o
X
Xall:	mail smail rmail cico cmail
X
X$(SOURCES):
X	$(RETRIEVE) $(SOURCES)
X
Xmail:	$(SHOBJ)
X	cc $(CFLAGS) -o mail $(SHOBJ) $(LIBS)
X
Xsmail:	$(SMOBJ)
X	cc $(CFLAGS) -o smail $(SMOBJ)
X
Xrmail:	$(RMOBJ)
X	cc $(CFLAGS) -o rmail $(RMOBJ)
X
Xcmail:	$(CMOBJ)
X	cc $(CFLAGS) -o cmail $(CMOBJ)
X
Xcico:	$(CIOBJ)
X	cc $(CFLAGS) -o cico $(CIOBJ)
X
Xmlint:
X	lint $(LINTFL) $(CFLAGS) $(SHSRC)
X
Xrlint:
X	lint $(LINTFL) $(CFLAGS) $(RMSRC)
X
Xslint:
X	lint $(LINTFL) $(CFLAGS) $(SMSRC)
X
Xclint:
X	lint $(LINTFL) $(CFLAGS) $(CISRC)
X
Xtar:	$(SOURCES)
X	tar cv $(SOURCES)
X
Xshar:	$(SOURCES)
X	find $(SOURCES) -print | makekit
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.uts
if test 6491 -ne `wc -c <makefile.uts`; then
    echo shar: \"makefile.uts\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f xpres.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"xpres.c\"
else
echo shar: Extracting \"xpres.c\" \(6821 characters\)
sed "s/^X//" >xpres.c <<'END_OF_xpres.c'
X/*++
X/* NAME
X/*      xpres 3
X/* SUMMARY
X/*      communications port i/o
X/* PROJECT
X/*      pc-mail
X/* PACKAGE
X/*      cico
X/* SYNOPSIS
X/*      xopen()
X/*
X/*      xclose()
X/*
X/*      xread(dummy,buf,len)
X/*      int dummy,len;
X/*      char *buf;
X/*
X/*      xwrite(dummy,buf,len)
X/*      int dummy,len;
X/*      char *buf;
X/*
X/*      xioctl(flag)
X/*      int flag;
X/* DESCRIPTION
X/*      The functions in this module perform functions analogous
X/*      to unix system calls, for the serial port of IBM-PC workalikes.
X/*
X/*      xopen() initializes a serial port. Also needed under UNIX.
X/*
X/*      xclose() closes a port.
X/*
X/*      xread(), xwrite() do not use their first argument. Under UNIX
X/*	one should use the standard read() and write() system calls.
X/*
X/*      xioctl() enables xon/xoff flow control if its argument
X/*      is nonzero. Not used under UNIX.
X/* SEE ALSO
X/*      comport.asm, IBM-PC comm routines by Tim Pozar
X/* DIAGNOSTICS
X/*      The read functions returns EOF in case of timeout; the write
X/*      function never detects any failure.
X/* BUGS
X/*      The xioctl() function is utterly primitive.
X/* AUTHOR(S)
X/*      MS-DOS parts derived from uuslave software (John Gilmore)
X/*	published on usenet early 1987. Bugs fixed & severely hacked by
X/*
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 23:01:43 GMT+1:00 1987
X/* LAST MODIFICATION
X/*	Mon Apr  4 23:51:55 MET 1988
X/* VERSION/RELEASE
X/*	1.3
X/*--*/
X
X#include "defs.h"
X#include "params.h"
X#include "comm.h"			/* baud rates, tty ports,... */
X#include "status.h"
X#include "sysdep.h"			/* other system dependencies */
X#include "logs.h"
X
X#ifdef	unix
X#   include <sgtty.h>
X#   include <signal.h>
X#   include <setjmp.h>
X#endif
X
X#ifdef	MSDOS
X#   define B(x)	(115200/(x))
X    static int sigint();
X    static void get_time();
X#endif
X
Xtypedef struct {			/* baud-rate lookup table */
X    char *name;
X    int code;
X} Baud_table;
X
XBaud_table btable[] = {
X#ifdef	unix
X    "50",	B50,
X    "75",	B75,
X    "110",	B110,
X    "134",	B134,
X    "150",	B150,
X    "300",	B300,
X    "600",	B600,
X    "1200",	B1200,
X    "1800",	B1800,
X    "2400",	B2400,
X    "4800",	B4800,
X    "9600",	B9600,
X#endif
X#ifdef	MSDOS
X    "50",	B(50),
X    "75",	B(75),
X    "110",	B(110),
X    "134",	B(134),
X    "150",	B(150),
X    "300",	B(300),
X    "600",	B(600),
X    "1200",	B(1200),
X    "1800",	B(1800),
X    "2400",	B(2400),
X    "4800",	B(4800),
X    "9600",	B(9600),
X#endif
X	0,		0,
X};
X
X/* xopen - open communications port; parameters taken from setup table */
X
Xxopen()
X{
X    register Baud_table *bp;
X#ifdef	unix
X    struct sgttyb ttmode;
X#endif
X
X    for (bp = btable; bp->name; bp++)		/* look up baud rate */
X	if (strcmp(bp->name,COMM_RATE) == 0)
X	    break;
X    if (bp->name == 0) {			/* bad baud rate in setup */
X	debug(4)("Invalid baud rate %s\n",COMM_RATE);
X	exit(E_BADSETUP);
X    }
X
X#ifdef	unix
X    if ((ttfd = open(COMM_LINE,2)) < 0) {	/* try to access port */
X	debug(4)("Cannot access %s\n",COMM_LINE);
X	exit(E_BADSETUP);
X    }
X#ifndef SIII
X    if (ioctl(ttfd,TIOCEXCL))			/* exclusive access */
X	exit(E_BADSETUP);			/* not a terminal */
X#endif
X    ioctl(ttfd,TIOCHPCL);			/* hangup when done */
X    gtty(ttfd,&ttmode);				/* get port status */
X    ttmode.sg_ispeed = ttmode.sg_ospeed = bp->code;/* set baud rate */
X    ttmode.sg_flags |= (RAW);			/* raw mode */
X#ifdef	SIII
X    ttmode.sg_flags &= ~ECHO;
X#else
X    ttmode.sg_flags &= ~(ECHO|TANDEM|CBREAK);	/* no echo, crlf, flow ctrl */
X#endif
X    stty(ttfd,&ttmode);
X#endif
X
X#ifdef MSDOS
X    set_tty(bp->code);				/* set baud rate, DTR */
X    init_comm();				/* turn interrupts on */
X    signal(SIGINT,sigint);			/* must reset tty */
X    inp_flush();				/* flush garbage */
X    sleep(3);
X#endif
X}
X
X/* xclose - release the communications port */
X
Xxclose()
X{
X#ifdef	unix
X    close(ttfd);
X#endif
X
X#ifdef MSDOS
X    uninit_comm();
X#endif
X}
X
X/* xread - read from the serial port */
X
X#ifdef	MSDOS
X
Xxread(fd,buf,cnt)
Xint fd;
Xchar *buf;
Xregister int cnt;
X{
X    register char *p = buf;
X    register int c;
X
X    while (cnt > 0 && (c = xgetc()) != EOF) {
X	*p++ = c;
X	cnt--;
X    }
X    return(p-buf ? p-buf : -1);
X}
X#endif	/* MSDOS xwrite() */
X
X/* xgetc - read one character from serial port */
X
X#ifdef	unix
Xjmp_buf xbuf;
X
Xstatic timeout()				/* aux function for xgetc */
X{
X    longjmp(xbuf,1);
X}
X
Xxgetc()						/* return next char */
X{
X    char ch;
X
X    if (setjmp(xbuf))				/* in case we time out */
X	return(EOF);				/* we just did */
X    signal(SIGALRM,timeout);			/* set timer response */
X    alarm(BYTE_TIMEOUT);			/* set timer */
X
X    read(ttfd,&ch,1);				/* go wait for character */
X    alarm(0);					/* turn timer off */
X    return(ch&0377);				/* successfull termination */
X}
X#endif	/* unix xgetc() */
X
X#ifdef MSDOS
X
Xxgetc()
X{
X    char data;
X
X    int i;
X    unsigned s;
X    TIME n;
X
X    i = 0;
X    get_time(&n);
X    s = n.sec;
X
X    /*
X    * Implement timeouts by staring at the clock while we wait.
X    * When the second hand moves, bump our counter.  This is a lot
X    * easier than figuring out the time when we'd time out (in hours,
X    * minutes, and seconds!) and comparing against that, which is
X    * what people tend to do in Unix where the time is just an integer
X    * number of seconds.
X    */
X    while (i < BYTE_TIMEOUT) {
X	while (s == n.sec) {
X	    if(inp_cnt() != 0) {
X		data = inp_char();
X		return (data & 0xFF);
X	    }
X	    get_time (&n);
X	}
X	s = n.sec;
X	++i;
X    }
X    return(EOF);
X}
X
X/* xwrite - write buffer to serial port */
X
Xxwrite(fd,buf,ctr)
Xint fd;
Xregister char *buf;
Xint ctr;
X{
X    register int i = ctr;
X
X    while (i-- > 0)
X	outp_char(*buf++);
X    return ctr;
X}
X
X/*
X* Routines specific to MS-DOS
X* 
X* xioctl()	enable xon/xoff
X* get_timer()	read current time
X* sigint()	clean up interrupt handler and exit
X* sleep()	unix lookalike
X*/
X
X/* xioctl - enable xon/xoff protocol */
X
Xxioctl(flag)
Xint flag;
X{
X    set_xoff(flag);     /* Enable (flag != 0) or disable flow control */
X}
X
X/* sigint - restore terminal settings on dialout line */
X
Xstatic int sigint()
X{
X    uninit_comm();
X    reset_tty();
X    exit(0);
X}
X
X/* get_time - read time with dos call */
X
Xstatic void get_time(n)
XTIME_PTR n;
X{
X    union REGS inregs;
X    union REGS outregs;
X
X    inregs.h.ah = 0x2c;		/* Please make a #define for this, Tim */
X
X    int86(0x21, &inregs, &outregs);/* Please #define the 0x21 too */
X
X    n->hour = outregs.h.ch;
X    n->minute  = outregs.h.cl;
X    n->sec  = outregs.h.dh;
X    n->hsec = outregs.h.dl;
X}
X
X#define	get_sec(n)	(get_time(&n),n.sec)
X
Xsleep(x)
Xint x;
X{
X    TIME n;               /* current time record */
X    unsigned s = get_sec(n);
X
X    while (x-- > 0) {
X	while (s == get_sec(n))
X	    /* void */ ;
X	s = n.sec;
X    }
X}
X
X#endif /* MSDOS */
END_OF_xpres.c
if test 6821 -ne `wc -c <xpres.c`; then
    echo shar: \"xpres.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 3 \(of 8\).
cp /dev/null ark3isdone
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.