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

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

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

#! /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 6 (of 8)."
# Contents:  alias.c buildall.bat comport.h edit.c getwork.c hsearch.3
#   kproto.ms mailsh.c mbox.c params.c path.c screen.h setup.c str.c
#   termcap/README termcap/console.c
# Wrapped by wietse@eutwc1 on Wed Apr 20 16:45:28 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f alias.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"alias.c\"
else
echo shar: Extracting \"alias.c\" \(3315 characters\)
sed "s/^X//" >alias.c <<'END_OF_alias.c'
X/*++
X/* NAME
X/*	alias
X/* SUMMARY
X/*	manipulate alias data base
X/* PROJECT
X/*	pc-mail
X/* PACKAGE
X/*	mailsh
X/* SYNOPSIS
X/*	#include "alias.h"
X/*
X/*	int alias()
X/* DESCRIPTION
X/*	The alias data base is a text file. Each line is of the form
X/*
X/*		alias	replacement
X/*
X/*	where a replacement may consist of several words, which may
X/*	be aliases themselves. Comma, blank and tab are separators.
X/*	Leading or trailing blanks are ignored. If an alias is defined
X/*	more than once, only the last definition will be effective.
X/*
X/*	alias() is invoked from the main menu and displays the contents
X/*	of the alias data base. An editor is invoked if the user wants
X/*	to make changes.
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/*	alias data base file in spool directory
X/* SEE ALSO
X/*      pager(3), pager(5), kbdinp(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/*	Wed Apr  6 20:21:35 MET 1988
X/* LAST MODIFICATION
X/*	Wed Apr  6 20:21:35 MET 1988
X/* VERSION/RELEASE
X/*	1.0
X/*--*/
X
X#include <errno.h>
X#include "defs.h"
X#include "path.h"
X#include "pager.h"
X#include "mailsh.h"
X#include "screen.h"
X#include "status.h"
X
X/* forward declarations */
X
Xhidden int edit_alias();
Xhidden void junk_alias();
Xhidden int show_alias();
X
Xhidden File *afile = 0;			/* pager file */
X
X/* alias - display alias data base */
X
Xpublic int alias()
X{
X    static Screen screen[] = {
X	'C',	"Close",	0,	initscreen,
X	'E',	"Edit",		edit_alias,"Edit alias data base",
X	'P',	"Print",	print,	"Print alias data base",
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_alias,
X	"(Reading alias database)",
X    };
X
X    kbdinp(screen);				/* ask disposition */
X    junk_alias();				/* forget alias display */
X    return(S_REDRAW);				/* say screen was changed */
X}
X
X/* show_alias - show alias data base or error message in middle window */
X
Xhidden int show_alias()
X{
X    static char *noalias[] = {			/* Ha ha ha ho ho hum */
X	"",
X	"The alias data base is empty. Normally it holds lines of the form",
X	"",
X	"	alias-name   one-or-more-mail-addresses",
X	"",
X	"You can create and change the alias data base with the E command.",
X	0,
X    };
X    if (afile) {				/* check pager file exists */
X	set_pager(afile);			/* select existing display */
X    } else if (rd_pager(afile = open_pager(),aliases())) {
X	mesg_pager(afile,noalias);		/* no alias database */
X    }
X    ds_pager();					/* (re)draw display */
X    return(0);					/* screen is up-to-date */
X}
X
X/* junk_alias - destroy alias data base display */
X
Xhidden void junk_alias()
X{
X    if (afile) {				/* no-op if no display */
X	close_pager(afile);			/* release memory */
X	afile = 0;				/* say it is gone */
X    }
X}
X
X/* edit_alias - edit or create alias data base */
X
Xhidden int edit_alias()
X{
X    register int stat;
X
X    if (stat = edit(aliases(),TMPALIAS))
X	errdisp(stat);				/* edit() had a problem */
X    junk_alias();				/* force new display */
X    return(S_REDRAW);				/* say screen has changed */
X}
END_OF_alias.c
if test 3315 -ne `wc -c <alias.c`; then
    echo shar: \"alias.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f buildall.bat -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"buildall.bat\"
else
echo shar: Extracting \"buildall.bat\" \(3399 characters\)
sed "s/^X//" >buildall.bat <<'END_OF_buildall.bat'
Xrem build file for microsoft c if you don't have a unix-compatible make tool
Xrem edit this if you don't have ms-dos versions of mv and rm.
X
Xcl -Gs -c mailsh.c
Xmv mailsh.obj mailsh.o
Xcl -Gs -c call.c
Xmv call.obj call.o
Xcl -Gs -c email.c
Xmv email.obj email.o
Xcl -Gs -c file.c
Xmv file.obj file.o
Xcl -Gs -c screen.c
Xmv screen.obj screen.o
Xcl -Gs -c mbox.c
Xmv mbox.obj mbox.o
Xcl -Gs -c desk.c
Xmv desk.obj desk.o
Xrm -f shlib1.lib
Xlib shlib1.lib call.o email.o file.o screen.o mbox.o desk.o ;
Xcl -Gs -c kbdinp.c
Xmv kbdinp.obj kbdinp.o
Xcl -Gs -c pager.c
Xmv pager.obj pager.o
Xcl -Gs -c window.c
Xmv window.obj window.o
Xcl -Gs -c setup.c
Xmv setup.obj setup.o
Xcl -Gs -c errdisp.c
Xmv errdisp.obj errdisp.o
Xcl -Gs -c invoke.c
Xmv invoke.obj invoke.o
Xrm -f shlib2.lib
Xlib shlib2.lib kbdinp.o pager.o window.o setup.o errdisp.o invoke.o ;
Xcl -Gs -c makework.c
Xmv makework.obj makework.o
Xcl -Gs -c mailfile.c
Xmv mailfile.obj mailfile.o
Xcl -Gs -c deskutil.c
Xmv deskutil.obj deskutil.o
Xcl -Gs -c submit.c
Xmv submit.obj submit.o
Xcl -Gs -c edit.c
Xmv edit.obj edit.o
Xcl -Gs -c alias.c
Xmv alias.obj alias.o
Xrm -f shlib3.lib
Xlib shlib3.lib makework.o mailfile.o deskutil.o submit.o edit.o alias.o ;
Xcl -Gs -c dir.c
Xmv dir.obj dir.o
Xcl -Gs -c myalloc.c
Xmv myalloc.obj myalloc.o
Xcl -Gs -c params.c
Xmv params.obj params.o
Xcl -Gs -c path.c
Xmv path.obj path.o
Xcl -Gs -c newseqno.c
Xmv newseqno.obj newseqno.o
Xcl -Gs -c ascf.c
Xmv ascf.obj ascf.o
Xcl -Gs -c spoolfil.c
Xmv spoolfil.obj spoolfil.o
Xcl -Gs -c str.c
Xmv str.obj str.o
Xrm -f libgen.lib
Xlib libgen dir.o myalloc.o params.o path.o newseqno.o ascf.o spoolfil.o  str.o ;
Xcl -F 2000 -o mail mailsh.o -link shlib1.lib shlib2.lib shlib3.lib libgen.lib \lib\termcap
Xexepack mail.exe junk
Xmv junk mail.exe
Xcl -Gs -c smail.c
Xmv smail.obj smail.o
Xcl -Gs -c unalias.c
Xmv unalias.obj unalias.o
Xcl -Gs -c hsearch.c
Xmv hsearch.obj hsearch.o
Xcl -F 2000 -o smail smail.o unalias.o hsearch.o -link libgen.lib
Xexepack smail.exe junk
Xmv junk smail.exe
Xcl -Gs -c rmail.c
Xmv rmail.obj rmail.o
Xcl -F 2000 -o rmail rmail.o -link libgen.lib
Xexepack rmail.exe junk
Xmv junk rmail.exe
Xcl -Gs -c cico.c
Xmv cico.obj cico.o
Xmasm comport.s ;
Xmv comport.obj comport.o
Xcl -Gs -c comm.c
Xmv comm.obj comm.o
Xcl -Gs -c connect.c
Xmv connect.obj connect.o
Xcl -Gs -c getwork.c
Xmv getwork.obj getwork.o
Xcl -Gs -c kphys.c
Xmv kphys.obj kphys.o
Xcl -Gs -c kpres.c
Xmv kpres.obj kpres.o
Xcl -Gs -c ktrans.c
Xmv ktrans.obj ktrans.o
Xcl -Gs -c logs.c
Xmv logs.obj logs.o
Xrm -f cilib1.lib
Xlib cilib1 comm.o connect.o getwork.o kphys.o kpres.o ktrans.o logs.o ;
Xcl -Gs -c protomsg.c
Xmv protomsg.obj protomsg.o
Xcl -Gs -c rmtname.c
Xmv rmtname.obj rmtname.o
Xcl -Gs -c scanwork.c
Xmv scanwork.obj scanwork.o
Xcl -Gs -c sendwork.c
Xmv sendwork.obj sendwork.o
Xcl -Gs -c startup.c
Xmv startup.obj startup.o
Xrm -f cilib2.lib
Xlib cilib2 newseqno.o protomsg.o rmtname.o scanwork.o sendwork.o startup.o ;
Xcl -Gs -c switcher.c
Xmv switcher.obj switcher.o
Xcl -Gs -c xpres.c
Xmv xpres.obj xpres.o
Xcl -Gs -c gpres.c
Xmv gpres.obj gpres.o
Xcl -Gs -c gtrans.c
Xmv gtrans.obj gtrans.o
Xcl -Gs -c gphys.c
Xmv gphys.obj gphys.o
Xrm -f cilib3.lib
Xlib cilib3 switcher.o xpres.o gpres.o gtrans.o gphys.o ;
Xcl -F 2000 -o junk cico.o comport.o -link cilib1.lib cilib2.lib cilib3.lib libgen
Xexepack junk.exe cico.exe 
Xrm -f junk.exe
Xcl -Gs -c cmail.c
Xmv cmail.obj cmail.o
Xcl -F 2000 -o cmail cmail.o invoke.o -link libgen.lib
Xexepack cmail.exe junk
Xmv junk cmail.exe
END_OF_buildall.bat
if test 3399 -ne `wc -c <buildall.bat`; then
    echo shar: \"buildall.bat\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f comport.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"comport.h\"
else
echo shar: Extracting \"comport.h\" \(3203 characters\)
sed "s/^X//" >comport.h <<'END_OF_comport.h'
X/*
X * Comport.h
X *
X * defines the bit masking for the get_mcr()
X *
X * @(#) comport.h	Version hoptoad-1.3	87/03/24
X *
X * Copyright (C) Tim M. Pozar 1987
X * Anyone can use this code for anything, but it is copyright by Tim
X * and you must leave his copyright in the code.
X *
X */
X
X/*
X * get_msr()
X *   Function to read (get) the byte located in the Modem Status 
X * Register (3FEh).  The table below describes the byte returned.
X *   bit  description
X *    0   Delta Clear to Send (DCTS)
X *        Indicates that the !CTS input to the chip has changed state
X *        since the last time it was read by the processor.
X *    1   Delta Data Set Ready (DDSR)
X *        Indicates that the !DRS input to the chip has changed since 
X *        last time it was read by the processor.
X *    2   Trailing Edge Ring Indicator (TERI)
X *        Indicates that the !RI input to the chip has changed from
X *        an on (logical 1) to an off (logical 0) condition.
X *    3   Delta Rx Line Signal detect (DRLSD)
X *        Indicates that the !RLSD input to the chip has changed state.
X * NOTE: Whenever bit 0, 1, 2, or 3 is set to a logical 1, a modem status
X *       interrupt is generated.
X *
X *    4   Clear to Send (CTS)
X *        This bit is the complement of the clear to send (!CTS) input.
X *        If bit 4 (LOOP) of the MCR is set to a logical 1, this is 
X *        equivalent to RTS in the MCR.
X *    5   Data Set Ready (DSR)
X *        This bit is the complement of the data set ready (!DSR) input.
X *        If bit 4 (LOOP) of the MCR is set to a logical 1, this is 
X *        equivalent to DTR in the MCR.
X *    6   Ring Indicator (RI)
X *        This bit is the complement of the ring indicator (!RI) input.
X *        If bit 4 (LOOP) of the MCR is set to a logical 1, this is 
X *        equivalent to OUT 1 in the MCR.
X *    7   Receive Line Signal Detect (RLSD) or Carrier Detect (CD).
X *        This bit is the complement of the received line signal detect
X *        (!RLSD) input. If bit 4 (LOOP) of the MCR is set to a logical 1,
X *        this is equivalent to OUT 2 in the MCR.
X */
X
X#define  DCTS       1
X#define  DDSR       2
X#define  TERI       4
X#define  DRLSD      8
X#define  CTS       16
X#define  DST       32
X#define  RI        64
X#define  RLSD     128   /* Also known as ... */
X#define  CD       128   
X#define  set_tty        SET_TTY     /* find current settings, and initialize */
X#define  reset_tty      RESET_TTY   /* reset to settings that set_tty() found */
X#define  get_msr        GET_MSR     /* get MSR byte from port. */
X#define  init_comm      INIT_COMM   /* initialize the comm port interupts, */
X#define  uninit_comm    UNINIT_COMM /* remove initialization, */
X#define  set_xoff       SET_XOFF    /* enable/disable XON/XOFF, */
X#define  get_xoff       GET_XOFF    /* read XON/XOFF state, */
X#define  rcvd_xoff      RCVD_XOFF   /* returns true if XOFF rcvd, */
X#define  sent_xoff      SENT_XOFF   /* true if XOFF sent, */
X#define  inp_cnt        INP_CNT     /* returns count of rcv chars, */
X#define  inp_char       INP_CHAR    /* get one char from buffer, */
X#define  inp_flush      INP_FLUSH   /* flush input buffer, */
X#define  outp_char      OUTP_CHAR   /* output a character, */
END_OF_comport.h
if test 3203 -ne `wc -c <comport.h`; then
    echo shar: \"comport.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f edit.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"edit.c\"
else
echo shar: Extracting \"edit.c\" \(3259 characters\)
sed "s/^X//" >edit.c <<'END_OF_edit.c'
X/*++
X/* NAME
X/*	edit 3
X/* SUMMARY
X/*	edit a file
X/* PROJECT
X/*	pc-mail
X/* PACKAGE
X/*	mailsh
X/* SYNOPSIS
X/*	#include "edit.h"
X/*
X/*	int edit(fname,tname)
X/*	char *fname,*tname;
X/* DESCRIPTION
X/*	edit() copies the file in fname to the file tname,
X/*	invokes the editor, and copies the result back.
X/* COMMANDS
X/*	the program specified in the EDITOR environment variable,
X/*	or a system-dependent default.
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/*	Wed Apr  6 20:21:35 MET 1988
X/* LAST MODIFICATION
X/*	Wed Apr  6 20:21:35 MET 1988
X/* VERSION/RELEASE
X/*	1.0
X/*--*/
X
X#include <errno.h>
X#include "defs.h"
X#include "path.h"
X#include "mailsh.h"
X#include "status.h"
X
X#ifdef MSDOS
X#   include <fcntl.h>
X#endif
X
X/* edit - edit or create a file */
X
X/*
X* Some editors (wordstar) do not accept path names. grrrr. 
X* So we copy the edit file to a temp file in the current directory.
X* After editing, the temp file is copied back. We do not move files, 
X* since current dir and the spool dir may be in different file systems, 
X* and people might turn off the machine and lose their edites.
X*/
X
Xpublic int edit(fname,tname)
Xchar *fname,*tname;
X{
X    register int stat = 0;
X    register FILE *fp;
X
X    /*
X    * First make sure that we can get write permission on the permanent file
X    * and temporary file (if they exist). 
X    * Create an empty temp file if we are not editing an existing file.
X    */
X
X    if (chmod(fname,0666) && errno != ENOENT) {
X	stat = E_WRITERR;			/* original file is protected */
X    } else if (chmod(tname,0666) && errno != ENOENT) {
X	stat = E_WRITERR;			/* scratch file is protected */
X    } else if ((fp = fopen(fname,"a")) == 0) {
X	stat = E_WRITERR;			/* file system is protected? */
X    } else if (fclose(fp),stat = cpfile(fname,tname)) {
X	/* void */;				/* could not make edit copy */
X    } else {
X	patience();				/* this may take some time */
X	kbdrest();				/* reset tty modes */
X	if (stat = invokelp(editor,tname,(char *) 0))/* call editor */
X	    stat = (stat == E_NOPROG ? stat : E_UNKNOWN);
X	else
X	    stat = cpfile(tname,fname);		/* copy back */
X	kbdinit();				/* set tty modes */
X	unlink(tname);				/* don't check status */
X    }
X    chmod(fname,0444);				/* protect destination file */
X    return(stat);
X}
X
X/* cpfile - yet another file copy function */
X
Xhidden int cpfile(from,to)
Xchar *from,*to;
X{
X    register FILE *in,*out;			/* file pointers */
X    int stat = 0;				/* error status */
X
X    if ((in = fopen(from,"r")) == 0) {		/* cannot read source */
X	return(E_READERR);
X    } else if ((out = fopen(to,"w")) == 0) {	/* cannot write destination */
X	fclose(in);
X	return(E_WRITERR);
X    } else {
X	register int c;				/* character buffer */
X#ifdef O_BINARY
X	setmode(fileno(in),O_BINARY);		/* get rid of the */
X	setmode(fileno(out),O_BINARY);		/* crlf translation */
X#endif
X	while ((c = getc(in)) != EOF)
X	   putc(c,out);
X	if (ferror(in))				/* check read error status */
X	    stat = E_READERR;
X	else if (ferror(out))			/* check write error status */
X	    stat = E_WRITERR;
X	fclose(in);
X	fclose(out);
X	return(stat);				/* at most one type of error */
X    }
X}
END_OF_edit.c
if test 3259 -ne `wc -c <edit.c`; then
    echo shar: \"edit.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f getwork.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"getwork.c\"
else
echo shar: Extracting \"getwork.c\" \(2772 characters\)
sed "s/^X//" >getwork.c <<'END_OF_getwork.c'
X/*++
X/* NAME
X/*	getwork 3
X/* SUMMARY
X/*	receive work from remote system
X/* PROJECT
X/*	pc-mail
X/* PACKAGE
X/*	cico
X/* SYNOPSIS
X/*	#include "work.h"
X/*
X/*      work *rmtwork(rqst)
X/*      char *rqst;
X/*
X/*	void getwork(wrk)
X/*	work *wrk;
X/* DESCRIPTION
X/*      rmtwork() parses a remote Send request. A suitable destination
X/*	file is opened. The resulting work structure is for use by 
X/*	getwork().
X/*
X/*	getwork() receives a file from the remote system, after the
X/*	necessary preparations have been done by rmtwork().
X/*	The file is deleted in case of transmission failure.
X/* FUNCTIONS AND MACROS
X/*	trap(), locname()
X/* SEE ALSO
X/*	sendwork(), scanwork()
X/* DIAGNOSTICS
X/*	Exceptions are handled with longjmp(systrap,errorcode).
X/*
X/*	rmtwork() traps in case of invalid requests or if the destination
X/*	file could not be opened.
X/*
X/*	getwork() traps in case of read/write errors.
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 16:57:57 GMT+1:00 1987
X/* LAST MODIFICATION
X/*	Mon Apr  4 23:40:43 MET 1988
X/* VERSION/RELEASE
X/*	1.3
X/*--*/
X
X#include "defs.h"
X#include "logs.h"
X#include "status.h"
X#include "work.h"
X#include "params.h"
X#include "comm.h"
X
X/* rmtwork - parse remote S request and open destination file */
X
Xpublic work *rmtwork(rqst)
Xchar *rqst;
X{
X    static work wrk;
X    char path[BUFSIZ];
X
X    if (sscanf(rqst,"S %*s %s",path) != 1)	/* pick destination file name */
X	trap(E_LOST,"BAD REQUEST FORMAT");
X    debug(5)("rmtwork: path %s\n",path);
X    strcpy(wrk.path,locname(path));		/* convert to local name */
X    debug(5)("rmtwork: file %s\n",wrk.path);
X    if ((wrk.fp = fopen(wrk.path,"w")) == 0)	/* try to open that file */
X	trap(E_WRITERR,"CAN'T CREATE FILE (%s)",sys_errlist[errno]);
X    return(&wrk);
X}
X
X/* getwork - receive file from remote host */
X
Xpublic void getwork(wrk)
Xregister work *wrk;
X{
X    char buf[BUFSIZ];
X    register int nread;
X    register int werror;
X
X    while ((nread = CALL(Read)(ttfd,buf,BUFSIZ)) > 0 &&
X	fwrite(buf,sizeof(*buf),nread,wrk->fp) == nread)
X	/* void */ ;
X    werror = ferror(wrk->fp);			/* record error status */
X    fclose(wrk->fp);
X
X    if (nread < 0) {				/* did the protocol fail? */
X	chmod(wrk->path,0666);			/* make file deletable */
X	unlink(wrk->path);			/* remove file */
X	trap(E_LOST,"FAILED (lost link)");	/* handle exception */
X	/* NOTREACHED */
X    } else if (werror) {			/* file write error? */
X	chmod(wrk->path,0666);			/* make file deletable */
X	unlink(wrk->path);			/* remove file */
X	trap(E_WRITERR,"FILE WRITE ERROR (%s)",sys_errlist[errno]);
X	/* NOTREACHED */
X    } else {
X	chmod(wrk->path,0444);			/* protect the file */
X    }
X}
END_OF_getwork.c
if test 2772 -ne `wc -c <getwork.c`; then
    echo shar: \"getwork.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f hsearch.3 -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"hsearch.3\"
else
echo shar: Extracting \"hsearch.3\" \(3042 characters\)
sed "s/^X//" >hsearch.3 <<'END_OF_hsearch.3'
X.TH HSEARCH 3c local
X.SH NAME
Xhsearch, hcreate, hdestroy \- manage hash search tables
X.SH SYNOPSIS
X.nf
X.ft B
Xtypedef struct entry {
X	char *key;
X	char *data;
X	} ENTRY;
X
Xtypedef enum {
X	FIND,
X	ENTER
X	} ACTION;
X
XENTRY *hsearch (item, action)
XENTRY item;
XACTION action;
X
Xint hcreate (nel)
Xunsigned int nel;
X
Xvoid hdestroy ();
X.br
X.ft R
X.fi
X.SH DESCRIPTION
X.I Hsearch
Xis a simple, public domain, reimplementation of the routine of the same
Xname in
X.SM UNIX
XSystem V.
X.PP
X.I Hsearch
Xreturns a pointer into a hash table where a given element can be found.
XAn
X.I item
Xto be stored in the table is of type ENTRY.
X.I Item.key
Xpoints to the key used for comparison, while
X.I item.data
Xpoints to the data to be associated with the key.
XIf the data pointed to is not a character string, it should be cast
Xto type pointer-to-character before being assigned.
XNote that
X.I item
Xis a structure, and
X.I not
Xa pointer to a structure.
XIf the value of
X.I action
Xis FIND,
X.I hsearch
Xwill return a pointer to the item in the table, if it is there, otherwise
Xit will return NULL.  If the action is ENTER, it will return a pointer
Xto the new item, or NULL if it could not add the item to the table.
XNote that if the action is ENTER, and the item was already in the table, the
X.I data
Xfield will be updated from the new
X.IR item .
X.PP
X.I Hsearch
Xdoes not provide all the (compile-time) options of the original routine;
Xinstead it uses a
X.I remainder modulo table size
Xhashing algorithm,
X.I chaining
X(linked lists) to resolve collisions, with new entries being placed at
Xthe end, and
X.IR strcmp (3)
Xfor the comparison function.
XIt was felt that a simple reimplementation was called for,
Xinstead of a brand new hash table package,
Xsince the interface provided is a clean one,
Xbut the original source code is not publicly available.
X.PP
X.I Hcreate
Xcreates the hash table, allocating enough space for it.  It must be
Xcalled before
X.IR hsearch .
X.I Nel
Xis an estimate of the number of hash buckets that will be needed;
Xthe table size will be adjusted up to the next largest prime number.  If
X.I nel
Xis larger than the largest prime known to
X.IR hcreate , " nel"
Xwill be used directly.
X.PP
X.I Hdestroy
Xdestroys the hash table, freeing up all its storage.  It may be followed
Xby another call to
X.IR hcreate .
X.SH SEE ALSO
X.IR malloc (3),
X.IR strcmp (3),
Xthe various other searching routines available with System V.
X.SH DIAGNOSTICS
X.I Hsearch
Xreturns NULL
Xif either the action was FIND and the item is not in the table, or
Xthe action was ENTER but the item could not be inserted.
X.PP
X.I Hcreate
Xreturns zero if it could not create the initial table; it returns
Xone if all went well.
X.SH BUGS
X.PP
XOnly one hash table may be active at a given time.
X.PP
XNot as flexible as the original System V implementation.
X.SH AUTHOR
X.nf
XArnold Robbins
XSchool of Information and Computer Science
XGeorgia Institute of Technology
XAtlanta, Georgia   30332
X
XCSNET:	arnold@gatech
XARPA:	arnold%gatech.csnet@csnet-relay.arpa
XUUCP:	{ akgua, allegra, hplabs, ihnp4, seismo, ut-sally }!gatech!arnold
END_OF_hsearch.3
if test 3042 -ne `wc -c <hsearch.3`; then
    echo shar: \"hsearch.3\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f kproto.ms -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"kproto.ms\"
else
echo shar: Extracting \"kproto.ms\" \(2984 characters\)
sed "s/^X//" >kproto.ms <<'END_OF_kproto.ms'
X.TL
Xuucp k protocol description
X.AU
XW.Z. Venema
XEindhoven University of Technology
X.AE
X.NH
XIntroduction
X.LP
XThe k protocol has been developed for the Sytek Localnet local area
Xnetwork at the Eindhoven University of Technology (TUE).
XMain features of this network are:
X.IP     1
XNetwork partners may talk at different baudrates. This implies that the network
Xdoes some buffering. This may cause timing
Xproblems (e.g. a system sending at 9600 baud to a system reading at 1200 baud).
X.IP     2
XThe network needs a flow control mechanism. Usually this is
Xbased on the XON/XOFF protocol. Other control character sequences are used
Xfor commands to the network.
X.IP     3
XSome network stations are connected to telephone modems.
X.LP
XFor these reasons, the k protocol must (i) cope with on XON/XOFF flow
Xcontrol, (ii) be suitable for 7-bit data paths, (iii) avoid
Xcontrol characters and (iv) provide reliable operation
Xover telephone lines as well as over the local area network.
X.NH
XPackets
X.LP
XData are sent as checksummed 256-byte packets, terminated by an
XASCII CR. Except for the packet header (^P), the k protocol only uses
XASCII codes 040 through 0137. Three data bytes are expanded to four
Xbytes upon transmission. Theoretically, this reduces throughput by 25 percent.
XAt 1200 baud, actual performances are:
X.DS
Xuucp, g protocol	110 cps
Xuucp, k protocol	74 cps
Xc-kermit		67 cps
X.DE
XNote that the values for c-kermit are for text files, with repeat-count
Xcompression enabled.
X.PP
XThe packet types are a subset of those used in the kermit programs:
X.DS
XD packets contain data.
XY packets are sent when a correct data packet was received.
XN packets are sent when incorrect data was received.
XA packets are sent to shut down the k protocol.
X.DE
XA packet always begins with a header:
X.DS
XSOH     packet header, ASCII control-P
Xlen     (size of data, low 6 bits) + 32
Xlen     (size of data, high 6 bits) + 32
Xnum     (packet number mod 64) + 32
Xtype    packet type
Xcheck   one-byte type-1 kermit checksum
X.DE
X.LP
XThe header is followed by checksummed data if len > 0:
X.DS
Xdata    len data bytes
Xcheck1  (upper 2 bits of type-3 kermit 16-bit checksum) + 32
Xcheck2  (middle 6 bits of type-3 kermit 16-bit checksum) + 32
Xcheck3  (lower 6 bits of type-3 kermit 16-bit checksum) + 32
X.DE
X.LP
XEvery packet is followed by an ASCII carriage return, which is
Xignored upon reception of a packet. It prevents timeout errors
Xwhen one byte gets lost (the most common case).
X.NH
XHandshake
X.LP
XHandshake is on a per-packet basis; a transmitter will not send
Xanother data packet before it knows that the receiver got the data
Xin good condition. There are various ways to obtain that knowledge:
Xthe receiver may send an ACK message (usual case), or a NAK for
Xthe next data packet, or a data packet with the next sequence number.
X.PP
XThe protocol is aborted when an unexpected
Xpacket type or when a packet out of sequence is received.
XSince 'A' packets are never expected, they always cause a protocol
Xfault.
END_OF_kproto.ms
if test 2984 -ne `wc -c <kproto.ms`; then
    echo shar: \"kproto.ms\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f mailsh.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"mailsh.c\"
else
echo shar: Extracting \"mailsh.c\" \(3963 characters\)
sed "s/^X//" >mailsh.c <<'END_OF_mailsh.c'
X/*++
X/* NAME
X/*      mailsh
X/* SUMMARY
X/*      visual mail-shell
X/* PROJECT
X/*      pc-mail
X/* PACKAGE
X/*      mail
X/* SYNOPSIS
X/*      mail
X/* DESCRIPTION
X/*      mail is an interactive program for reading, receiving
X/*      and producing electronic mail. Actually, most of the work
X/*	is done by programs called by the mail program.
X/*
X/*      By default, the program presents the user display of a list of
X/*      mail messages in the form of one-line summaries. Single-key 
X/*	commands are available to select and manipulate mail messages.
X/*	Mail messages are created with an editor chosen by the user.
X/*
X/*      The name of the spool directory, printer program and editor
X/*      are taken from the environment, or assume system-dependent defaults.
X/* ENVIRONMENT
X/*      MAILDIR		name of spool directory
X/*      EDITOR          name of program to create mail
X/*	MAILPRN		name of program/file to print with/to
X/*	MAILCMD		command to execute upon termination
X/* COMMANDS
X/*      cico            network communications program
X/*      rmail           postprocessor for mail received by cico
X/* FILES
X/*      The mail system maintains various files in a spool directory,
X/*      as well as a logfile of all network transactions.
X/* SEE ALSO
X/*      path(3)         system-dependent path names
X/* DIAGNOSTICS
X/*      Error messages should be self-explanatory.
X/* BUGS
X/*      The user has to explicitly tell the system to contact a remote
X/*	mail host. This is a limitation of MS-DOS, not of the program.
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/*      Thu Apr  2 21:54:08 GMT+1:00 1987
X/* LAST MODIFICATION
X/*	Mon Apr  4 23:44:44 MET 1988
X/* VERSION/RELEASE
X/*	1.3
X/*--*/
X
X#include <signal.h>
X#include "defs.h"
X#include "path.h"
X#include "status.h"
X#include "mailsh.h"
X#include "window.h"
X
X/* forward declarations */
X
Xhidden int checkfiles();
X
X/* for now, don't even try to look at command args */
X
Xpublic main(argc,argv)
Xint argc;
Xchar **argv;
X{
X    register int stat;
X
X    /* 
X    * Initializations: get screen control and function-key codes (wininit).
X    * check if the limit on the number of open files is ok (checkfiles),
X    * get the values from environment variables (pathinit), set the
X    * terminal driver to the desired mode (kbdinit), check for partally
X    * processed new mail with the rmail program.
X    * Also make sure that our file permissions are safe (umask).
X    */
X
X    if (!isatty(fileno(stdin))) {
X	perror("mail: standard input");
X	exit(1);
X    }
X
X    umask(022);				/* avoid problems */
X    wininit();                          /* do termcap stuff */
X    clrscreen();                         /* clear screen */
X    (stat = checkfiles())		/* get max nbr of open files */
X    || (stat = pathinit())		/* get spool, printer, editor */
X    || (stat = invokelp(RMAIL,(char *)0));/* just in case there's mail */
X    kbdinit();                          /* set to tty RAW, NOECHO */
X    if (stat)
X	errdisp(stat);			/* we have a problem */
X
X    /* enter the main command loop */
X
X    desk();				/* start the machine */
X
X    /* finalizations */
X
X    kbdrest();                          /* restore tty driver */
X    clrscreen();                         /* clear screen */
X    fflush(stdout);
X    onexit(mailcmd);			/* do exit command */
X    exit(0);                            /* huh?? */
X    /* NOTREACHED */
X}
X
X/* checkfiles - make sure we can open as many files as we want */
X
Xhidden int checkfiles()
X{
X    register int i;
X    int fds[MINFILES];
X    register int stat;
X
X    for (i = 0; i < MINFILES; i++)              /* try to open many files */
X	if ((fds[i] = open(NULLDEV,0)) < 0)
X	    break;
X
X    stat = (i < MINFILES ? E_FILENO : 0);	/* did we fail? */
X
X    while (--i >= 0)                            /* release files */
X	close(fds[i]);
X    return(stat);
X}
END_OF_mailsh.c
if test 3963 -ne `wc -c <mailsh.c`; then
    echo shar: \"mailsh.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f mbox.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"mbox.c\"
else
echo shar: Extracting \"mbox.c\" \(2946 characters\)
sed "s/^X//" >mbox.c <<'END_OF_mbox.c'
X/*++
X/* NAME
X/*      mbox 3
X/* SUMMARY
X/*      display incoming/outgoing mail messages
X/* PROJECT
X/*      pc-mail
X/* PACKAGE
X/*      mailsh
X/* SYNOPSIS
X/*	#include "pager.h"
X/*	#include "mbox.h"
X/*
X/*      int mbox(type,msgid)
X/*	char *type;
X/*	int msgid;
X/* DESCRIPTION
X/*      mbox() is invoked when the user has selected an incoming or
X/*	outgoing mail message (not a message in preparation)
X/*	from the main mail box menu. It instructs the pager to display 
X/*	the selected mail message. The message type parameter is 
X/*	a string with the type of message
X/*	(see screen.h), msgid is the numerical message id. If the file is
X/*	read for the first time (type == "New"), it will be marked as read.
X/*
X/*      The user has the usual options for manipulating the message
X/*	being displayed.
X/* FILES
X/*      mail header files in the spool directory
X/* SEE ALSO
X/*      pager(3), pager(5), kbdinp(3)
X/* DIAGNOSTICS
X/*      If a selected mail message could not be found an error message
X/*      is displayed instead.
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 13:01:12 GMT+1:00 1987
X/* LAST MODIFICATION
X/*	Mon Apr  4 23:45:14 MET 1988
X/* VERSION/RELEASE
X/*	1.3
X/*--*/
X
X#include "defs.h"
X#include "path.h"
X#include "pager.h"
X#include "screen.h"
X#include "mailsh.h"
X
Xhidden File *letter = 0;			/* pager file */
X
X/* show_letter - display selected mail message */
X
Xhidden int show_letter()
X{
X    set_pager(letter);				/* select message display */
X    ds_pager();					/* put it on the screen */
X    return(0);					/* say screen is ok */
X}
X
X/* mbox - user has selected a non-work mail message file */
X
Xpublic int mbox(type,id)
Xchar *type;
Xint id;
X{
X    static Screen screen[] = {
X	'C',	"Close",        0,      initscreen,
X	'D',	"Delete",       delete,	delcurr,
X	'M',	"Mail",		mailfile,"Mail a copy of this message",
X	'P',	"Print",        print,	printcurr,
X	'S',	"Save",         save,	"Save this message to ordinary file",
X	'W',	"Work",		makework,"Save this message to 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_letter,"(Reading a mail message)",
X    };
X    register char *seen;
X
X    if (rd_pager(letter = open_pager(),message)) {
X	mesg_pager(letter,m_msgread);		/* no file or read error */
X    } else if (strcmp(type,"New")) {		/* !!ANONYMOUS CONSTANT!! */
X	/* void */ ;				/* not a new message */
X    } else if (rename(comment,seen = in_meta(id)) == 0) {
X	strcpy(comment,seen);			/* mark message as read */
X	junk_desk();				/* say desk-top outdated */
X    }
X    kbdinp(screen);				/* look at the screen */
X    close_pager(letter),letter = 0;		/* destroy the display */
X    return(S_REDRAW);				/* force screen redrawing */
X}
END_OF_mbox.c
if test 2946 -ne `wc -c <mbox.c`; then
    echo shar: \"mbox.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f params.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"params.c\"
else
echo shar: Extracting \"params.c\" \(3012 characters\)
sed "s/^X//" >params.c <<'END_OF_params.c'
X/*++
X/* NAME
X/*	params 3
X/* SUMMARY
X/*	communication parameter access
X/* PROJECT
X/*	pc-mail
X/* PACKAGE
X/*	library
X/* SYNOPSIS
X/*	#include "params.h"
X/*
X/*	Info *getparams();
X/* DESCRIPTION
X/*	getparams() returns a pointer to a table with communications
X/*	parameters. Usually communications parameters are set with the
X/*	"setup" option in the main menu of the interactive mail program.
X/*
X/*	First getparams() attempts to read from the setup file.
X/*	If that fails it creates an empty parameter table with
X/*	null string pointers as parameter values.
X/* FUNCTIONS AND MACROS
X/*	myalloc()
X/* BUGS
X/*	getparams() silently ignores any information in the
X/*	parameter file that it does not recognize.
X/*	getparams() will read the parameter file upon each call, even
X/*	if nothing has changed since the last read. Let us say that
X/*	it anticipates on multi-user environments.
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/*	Wed Apr  8 15:39:23 GMT+1:00 1987
X/* LAST MODIFICATION
X/*	Mon Apr  4 23:46:51 MET 1988
X/* VERSION/RELEASE
X/*	1.3
X/*--*/
X
X#include <ctype.h>
X#include "defs.h"
X#include "path.h"
X#include "params.h"
X
X/* Storage area for setup parameters */
X
Xhidden Info params[] = {
X    /* name */	/* name length */	/* string value */
X    PORT,	sizeof(PORT)-1,		0,
X    BAUD,	sizeof(BAUD)-1,		0,
X    HOST,	sizeof(HOST)-1,		0,
X    LOGIN,	sizeof(LOGIN)-1,	0,
X    DIAL,	sizeof(DIAL)-1,		0,
X    DISC,	sizeof(DISC)-1,		0,
X    0,		0,			0,
X};
X
Xhidden char *hackstr();				/* forward declaration */
X
X/* getparams - try to get info from file, else make empty table */
X
Xpublic Info *getparams()
X{
X    char line[BUFSIZ];
X    register Info *ip;
X    FILE *fp;
X
X    /* for cleanliness, we first clear all table entries */
X
X    for (ip = params; ip->ident; ip++) {
X	if (ip->strval)
X	    free(ip->strval);
X	ip->strval = NULL;
X    }
X
X    /* then, try to copy parameter file info to the table */
X
X    if (fp = fopen(parm_file(),"r")) {
X	while (fgets(line,BUFSIZ,fp)) {
X	    for(ip = params; ip->ident; ip++) {
X		if (strncmp(ip->ident,line,ip->length) == 0) {
X		    ip->strval = hackstr(line+ip->length);
X		    break;
X		}
X	    }
X	}
X	fclose(fp);
X    }
X    return(params);
X}
X
X/* hackstr - cut away blanks around string and make copy */
X
Xhidden char *hackstr(s)
Xregister char *s;
X{
X    register char *r;
X    int len;
X
X    while (*s && isspace(*s))				/* trim leading blks */
X	s++;
X    for (r = s+strlen(s); r > s && isspace(r[-1]); r--)	/* trim trailing blks */
X	/* void */ ;
X
X    /*
X    * s is at the terminator or first non-blank char.
X    * r is at the terminator or first blank after the last non-blank char.
X    * Thus, the actual string length is r-s. We add one for the terminator.
X    * We don't allocate memory if the string is empty.
X    */
X
X    if (len = r-s) {
X	char *cp = strncpy(myalloc(len+1),s,len);
X	cp[len] = '\0';
X	return(cp);
X    } else {
X	return(NULL);
X    }
X}
END_OF_params.c
if test 3012 -ne `wc -c <params.c`; then
    echo shar: \"params.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f path.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"path.c\"
else
echo shar: Extracting \"path.c\" \(3402 characters\)
sed "s/^X//" >path.c <<'END_OF_path.c'
X/*++
X/* NAME
X/*      path 3
X/* SUMMARY
X/*      system-dependent file name stuff
X/* PROJECT
X/*      pc-mail
X/* PACKAGE
X/*      general
X/* SYNOPSIS
X/*	#include "str.h"
X/*      #include "path.h"
X/*
X/*      int pathinit()
X/*
X/*      FILE *propen()
X/*
X/*      char *fspool(file)
X/*      char *file;
X/* DESCRIPTION
X/*      The routines in this module know the system-dependent rules
X/*      for file names and printers.
X/*
X/*      pathinit() extracts the values of the environment variables
X/*      MAILDIR, MAILPRN, MAILCMD and EDITOR, and assumes system-dependent 
X/*	defaults for undefined environment variables. It checks for the 
X/*      existence of the spool directory.
X/*
X/*	Under Unix, the MAILPRN environment variable should be the name
X/*	of a command. Under MS-DOS, it should be the name of a device or file.
X/*
X/*      propen() returns stream to print to.
X/*
X/*      fspool() constructs a path name from the spool directory and 
X/*	the file name in its argument.
X/*	Real unix uses uucp spool file names of the form 
X/*
X/*		<letter> . <system> <grade> <sequencenr>
X/*
X/*	This is problematic for MS-DOS and similar systems that
X/*	only allow three characters after the dot. Instead of building
X/*	a tiny file system on top of MS-DOS, the pc-mail programs
X/*	use a different way of spool file naming:
X/*
X/*		<letter> <sequencenr>
X/*
X/*	This scheme assumes that the pc has access to exactly one unix
X/*	host, since the host name is not part of spool file names.
X/* COMMANDS
X/*      lp(1)  (under unix) printer spooler program
X/* FILES
X/*      PRN     under MS-DOS
X/* DIAGNOSTICS
X/*      pathinit() returns a nonzero value (see status(5)) if one of the 
X/*	environment variables (or defaults) are incorrect.
X/*
X/*      File open functions return a null pointer when a file could not
X/*      be opened.
X/* BUGS
X/*	pathinit() only verifies the MAILDIR name.
X/*
X/*      fspool() returns a pointer to static memory.
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 15:27:37 GMT+1:00 1987
X/* LAST MODIFICATION
X/*	Wed Apr  6 00:21:17 MET 1988
X/* VERSION/RELEASE
X/*	1.4
X/*--*/
X
X#include <sys/types.h>
X#include <sys/stat.h>
X#include "defs.h"
X#include "path.h"
X#include "status.h"
X
X/*
X* Environment variables are loaded here. Most of them have a default;
X* We only check the validity of the MAILDIR variable.
X*/
X
Xpublic char *maildir = DEFSPOOL;		/* spool directory */
Xpublic char *editor  = DEFEDIT;			/* editor program */
Xpublic char *mailprn = DEFPRINT;		/* where to print to */
Xpublic char *mailcmd = 0;			/* do this on exit */
X
Xtypedef struct {
X    char *vname;
X    char **ptr;
X} Environ;
X
Xstatic Environ env[] = {
X    "SPOOL",	&maildir,			/* backwards compatibility... */
X    "MAILDIR",	&maildir,
X    "EDITOR",	&editor,
X    "MAILPRN",	&mailprn,
X    "MAILCMD",	&mailcmd,
X    0,		0,
X};
X
X/* pathinit - consult the environment; checks existence of spool directory */
X
Xpublic int pathinit()
X{
X    register char *cp;
X    struct stat s;
X    register Environ *ep;
X
X    /* load environment variables */
X
X    for (ep = env; ep->vname; ep++)
X	if (cp = getenv(ep->vname))
X	    *(ep->ptr) = cp;
X
X    /* check existence of the spool directory */
X
X    return(stat(maildir,&s) || (s.st_mode&S_IFMT) != S_IFDIR ? E_NOSPOOL : 0);
X}
END_OF_path.c
if test 3402 -ne `wc -c <path.c`; then
    echo shar: \"path.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f screen.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"screen.h\"
else
echo shar: Extracting \"screen.h\" \(4000 characters\)
sed "s/^X//" >screen.h <<'END_OF_screen.h'
X/*++
X/* NAME
X/*	screen
X/* SUMMARY
X/*	structure of mail shell command windows
X/* PROJECT
X/*	pc-mail
X/* PACKAGE
X/*	mailsh
X/* SYNOPSIS
X/*	#include "screen.h"
X/* DESCRIPTION
X/*	The data structures in this file are used by the interactive shell to 
X/*	define what a screen looks like, and what commands the user can give.
X/*
X/*	For each screen, one has to define a table of (selector, command name, 
X/*	help string, and function pointer) tuples.
X/*	The command names are listed in the top window. If the user enters
X/*	the type of input specified by the selector, the associated function
X/*	is called. A null function pointer means go back to the calling screen. 
X/*
X/*	The table is terminated with a null selector entry; its help 
X/*	string is displayed in the bottom window (as a prompt), and the 
X/*	associated function is invoked upon entry of the screen.
X/*
X/*	The return value of an action function determines what happens next.
X/*	An action function can signal an error condition, that the screen
X/*	needs to be redrawn, and whether the calling screen should terminate.
X/*
X/*	User input can be of various forms: single-character, string or
X/*	escape/enter.
X/*
X/*	In case of single-character input the selector fields should contain 
X/*	for each key the (upper case) key code,
X/*	a label that is displayed at the top of the screen, and a help
X/*	text that explains the key's function. 
X/*
X/*	In case of string input the associated function is called with the 
X/*	string input as argument. If that function returns an error status the
X/*	text in the help field is printed in the error window and the 
X/*	user is given another chance.
X/*
X/*	In case of escape/enter the interpreter invokes the action function when
X/*	the user presses enter, and does nothing when escape is pressed. 
X/* .nf
X
X/* /* there is a Screen structure for each command for each screen */
X
Xtypedef struct {
X    short key;			/* type of input */
X    char *name;			/* key label (for top window) */
X    int  (*action)();		/* action when command is selected */
X    char *help;			/* explanation (for H command) */
X} Screen;
X
X/* /* action function return masks */
X
X#define	S_BREAK		1	/* return immediately after action */
X#define	S_REDRAW	2	/* redraw screen */
X#define	S_ERROR		4	/* action failed */
X
X/* /* input types: ordinary character keys are encoded as themselves */
X
X#define	BS	'\010'
X#define	ENTER	'\015'
X#define	ESC	'\033'
X#define	DEL	'\177'
X
X#define	ANY	256		/* press any key */
X#define	UP	257		/* up-arrow key */
X#define	DOWN	258		/* down-arrow key */
X#define	LEFT	259		/* left-arrow key */
X#define	RIGHT	260		/* right-arrow key */
X#define	PGUP	261		/* page-up */
X#define	PGDN	262		/* page-down */
X#define	STRING	263		/* string input, ESC to quit */
X#define	ESCCR	264		/* CR to confirm, ESC to quit */
X
X#define	iskey(key)	(key > 0 && key < STRING)
X
X/* /* system-dependent function-key labels */
X
X#ifdef unix
X#   define PgUp	"F1"
X#   define PgDn "F2"
X#endif
X
X#ifdef MSDOS
X#   define PgUp "PgUp"
X#   define PgDn "PgDn"
X#endif
X
X/* /* often-used strings and messages */
X
Xextern char initscreen[];	/* Return to initial screen */
Xextern char int_error[];	/* The program is confused */
Xextern char pageup[];		/* Move screen one page upwards */
Xextern char pagedn[];		/* Move screen one page downwards */
Xextern char csrup[];		/* Move cursor upwards */
Xextern char csrdn[];		/* Move cursor downwards */
Xextern char getsummary[];	/* Press ESC to cancel.. */
Xextern char printcurr[];	/* Print current message */
Xextern char delcurr[];		/* Delete current message */
Xextern char *m_msgread[];	/* Cannot read that message */
X/* SEE ALSO
X/*	screen(3)	screen table implementation
X/*	kbdinp(3)	screen table interpreter
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/*	Wed Apr  1 21:14:53 GMT+1:00 1987
X/* LAST MODIFICATION
X/*	Mon Apr  4 23:49:07 MET 1988
X/* VERSION/RELEASE
X/*	1.3
X/*--*/
END_OF_screen.h
if test 4000 -ne `wc -c <screen.h`; then
    echo shar: \"screen.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f setup.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"setup.c\"
else
echo shar: Extracting \"setup.c\" \(4003 characters\)
sed "s/^X//" >setup.c <<'END_OF_setup.c'
X/*++
X/* NAME
X/*	setup 3
X/* SUMMARY
X/*	edit/display configuration parameters
X/* PROJECT
X/*	pc-mail
X/* PACKAGE
X/*	mailsh
X/* SYNOPSIS
X/*	#include "mailsh.h"
X/*
X/*	int setup()
X/* DESCRIPTION
X/*	The functions in this module handle the configurations file with 
X/*	communications parameters.
X/*
X/*	setup() starts a dialogue with the user. It allows the user to
X/*	select a parameter and enter a new value. All modifications are
X/*	done in core (pager file). Upon exit, the setup is written to 
X/*	disk if any changes were made.
X/* FUNCTIONS AND MACROS
X/*	open_pager(), app_pager(), gets_pager(), puts_pager()
X/*	kbdinp()
X/* FILES
X/*	In the spool directory: the configuration file s00000.
X/* SEE ALSO
X/*	cico(1)	communications program.
X/* DIAGNOSTICS
X/*	An error message if the setup file could not be created.
X/* BUGS
X/*	Does not check parameter values at all, just like the UUCP 
X/*	configurations files L.sys etcetera.
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/*	Wed Apr  8 15:16:18 GMT+1:00 1987
X/* LAST MODIFICATION
X/*	Mon Apr  4 23:49:37 MET 1988
X/* VERSION/RELEASE
X/*	1.3
X/*--*/
X
X#include "defs.h"
X#include "path.h"
X#include "screen.h"
X#include "mailsh.h"
X#include "pager.h"
X#include "params.h"
X#include "status.h"
X#include "window.h"
X
Xhidden void make_setup();			/* forward declarations */
Xhidden int change_setup();
Xhidden int pick_setup();
Xhidden int show_setup();
X
Xhidden File *setfile = 0;			/* memory! */
Xhidden Info *prmtable = 0;			/* more memory */
Xhidden int chgflag = 0;				/* more flags! */
X
X/* setup - start dialogue */
X
Xpublic int setup()
X{
X    static Screen screen[] = {
X	'C',	"Close",        0,      initscreen,
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_setup,"Modify selected parameter",
X	0,	0,              show_setup,
X	"Select communications parameter with cursor keys, then press ENTER",
X    };
X
X    kbdinp(screen);				/* start dialogue */
X    if (chgflag && cp_pager(parm_file())) {
X	errdisp(E_WRITERR);			/* save failed */
X    } else {
X	chgflag = 0;				/* save succeeded */
X    }
X    close_pager(setfile);
X    setfile = 0;
X    return(S_REDRAW);				/* refresh screen */
X}
X
X/* show_setup - make setup display or use existing one */
X
Xhidden int show_setup()
X{
X    if (setfile == 0 || prmtable == 0) {	/* no setup display */
X	prmtable = getparams();
X	setfile = open_pager();
X	make_setup();
X    } else {					/* use existing display */
X	set_pager(setfile);
X    }
X    ds_pager();					/* display it */
X    return(0);
X}
X
X/* make_setup - create setup display */
X
Xhidden void make_setup()
X{
X    register File *f = setfile;
X    register Info *i;
X
X    for (i = prmtable; i->ident; i++)
X	app_pager(f,strcons("%-20s %s",i->ident,i->strval ? i->strval : ""));
X}
X
X/* pick_setup - user has selected one parameter */
X
Xhidden int pick_setup()
X{
X    static Screen screen[] = {
X	STRING,	0,              change_setup,int_error,
X	0,	0,              0,
X	"Press ESC to cancel. New parameter value:"
X    };
X    register char *sp = gets_pager();
X    register Info *ip;
X
X    for (ip = prmtable; ip->ident; ip++)		/* check id string */
X	if (strncmp(ip->ident,sp,ip->length) == 0)
X	    break;
X    if (ip) {
X	kbdinp(screen);					/* ask for new value */
X	return(S_REDRAW);
X    } else {
X	beep();						/* bad id string */
X	return(0);
X    }
X}
X
X/* change_setup - enter new communications parameter value */
X
Xhidden int change_setup(newval)
Xchar *newval;
X{
X    register char *sp = gets_pager();			/* read from display */
X    register Info *ip;
X
X    for (ip = prmtable; ip->ident; ip++) {		/* check id string */
X	if (strncmp(ip->ident,sp,ip->length) == 0) {
X	    puts_pager(strcons("%-20s %s",ip->ident,newval)); /* new entry */
X	    chgflag = 1;				/* say change made */
X	}
X    }
X    return(S_BREAK|S_REDRAW);				/* screen changed */
X}
END_OF_setup.c
if test 4003 -ne `wc -c <setup.c`; then
    echo shar: \"setup.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f str.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"str.c\"
else
echo shar: Extracting \"str.c\" \(3979 characters\)
sed "s/^X//" >str.c <<'END_OF_str.c'
X/*++
X/* NAME
X/*	strcons,istrcmp,strvec,vecstr 3
X/* SUMMARY
X/*	string utility routines
X/* PROJECT
X/*	pc-mail
X/* PACKAGE
X/*	general stuff
X/* SYNOPSIS
X/*	char *strcons(format,args)
X/*	char *format;
X/*
X/*	int istrcmp(s1,s2)
X/*	char *s1,s2;
X/*
X/*	char **strvec(string,separ)
X/*	char *string;
X/*	char *separ;
X/*
X/*	char *vecstr(vector,separ)
X/*	char **vector;
X/*	char *separ;
X/* DESCRIPTION
X/*	strcons() produces a formatted string, using printf()-like
X/*	arguments. Basically it is an sprintf() that returns a 
X/*	pointer to the result.
X/*
X/*	istrcmp() is a case-insensitive versions of the strcmp() functions.
X/*
X/*	strvec() breaks a null-terminated string using the separators given 
X/*	in separ, and returns a null-terminated vector of pointers to the 
X/*	resulting substrings. Memory for the vector and substrings are 
X/*	allocated in dynamic memory. The original string is not modified.
X/*
X/*	vecstr() takes a null-terminated vector of string pointers
X/*	and builds a string from the strings pointed to by the vector
X/*	argument, separated by the string in the separ argument.
X/*	Memory for the result is allocated in dynamic memory.
X/* FUNCTIONS AND MACROS
X/*	strtok(), malloc(), memcpy(), sprintf()
X/* DIAGNOSTICS
X/*	strvec(), vecstr() return a null pointer if there was not enough memory
X/*	avaliable to hold the result.
X/* BUGS
X/*	strcons() does not do smart garbage collection; it just uses
X/*	a circular buffer. The present implementation is not portable 
X/*	to machines that pass arguments via registers.
X/*
X/*	strvec() cannot handle strings with more than BUFSIZ words.
X/*	strvec() uses strtok(), which may have side effects.
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 Apr  5 20:59:29 MET 1988
X/* LAST MODIFICATION
X/*	Wed Apr  6 00:23:08 MET 1988
X/* VERSION/RELEASE
X/*	1.1
X/*--*/
X
X#include <ctype.h>
X
X#include "defs.h"
X
X#define	NBUF	4
X
X/* strcons - quick-and-dirty string constructor */
X
X/* VARARGS1 */
X
Xchar *strcons(fmt,a1,a2,a3,a4)
Xchar *fmt;
Xlong a1,a2,a3,a4;
X{
X    static char strbuf[NBUF][BUFSIZ];
X    static int where = 0;
X    register char *cp;
X
X    sprintf(cp = strbuf[where = (where+1)%NBUF],fmt,a1,a2,a3,a4);
X    return(cp);
X}
X
X/* istrcmp - case-insensitive string comparison */
X
X#define	LOW(c)	(isascii(c)&&isupper(c)?tolower(c):(c))
X
Xint istrcmp(s1,s2)
Xregister char *s1,*s2;
X{
X    while (*s1 && (LOW(*s1) == LOW(*s2)))
X	s1++,s2++;
X    return(LOW(*s1)-LOW(*s2));
X}
X
X/* strvec - make vector of substring pointers */
X
Xchar **strvec(str,sep)
Xchar *str;
Xchar *sep;
X{
X    char *tmp[BUFSIZ];			/* scratch substring pointer storage */
X    register char **cpp = tmp;
X    char *sp;				/* ptr to private copy of original */
X    register int bytec;
X
X    /* make a copy of the original string */
X
X    if ((sp = malloc(strlen(str)+1)) == 0)
X	return(0);
X    strcpy(sp,str);
X
X    /* chop our copy at sequences of one or more separators */
X
X    for (*cpp = strtok(sp,sep); *cpp; *++cpp = strtok((char *)0,sep))
X	/* void */ ;
X
X    /* now construct the vector of pointers to the substrings */
X
X    if ((cpp = (char **) malloc(bytec = (cpp-tmp+1)*sizeof(*cpp))) == 0)
X	return(0);
X    return((char **)memcpy((char *)cpp,(char *)tmp,bytec));
X}
X
X/* vecstr - null-terminated vector of string pointers to one flat string */
X
Xpublic char *vecstr(vec,sep)
Xchar **vec;
Xchar *sep;
X{
X    register char **cpp;
X    register int len = 0;		/* length of final string */
X    register char *cp;
X    register int flen = strlen(sep);	/* filler between substrings */
X
X    /* find out how big the resulting string will be */
X
X    for (cpp = vec; *cpp; cpp++)
X	len += strlen(*cpp)+flen;
X
X    /* allocate and initialize the result string */
X
X    if ((cp = malloc(len+1)) == 0)
X	return(0);
X    *cp = '\0';
X
X    /* fill the resulting string */
X
X    for (cpp = vec; *cpp; cpp++) {
X	strcat(cp,*cpp);
X	strcat(cp,sep);
X    }
X    return(cp);
X}
END_OF_str.c
if test 3979 -ne `wc -c <str.c`; then
    echo shar: \"str.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f termcap/README -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"termcap/README\"
else
echo shar: Extracting \"termcap/README\" \(393 characters\)
sed "s/^X//" >termcap/README <<'END_OF_termcap/README'
XMS-DOS Implementation notes, W.Z. Venema, Eindhoven University of Technology
X
XThe functions presented here implement UNIX-style terminal-independent
Xoperation routines for cursor addressing, video attributes etc.
X
XThe functions are effective for the ibm pc console, and assume that the 
XMS-DOS driver ANSI.SYS is loaded. The capabilities for the console are
Xstored in a static data structure.
END_OF_termcap/README
if test 393 -ne `wc -c <termcap/README`; then
    echo shar: \"termcap/README\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f termcap/console.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"termcap/console.c\"
else
echo shar: Extracting \"termcap/console.c\" \(2788 characters\)
sed "s/^X//" >termcap/console.c <<'END_OF_termcap/console.c'
X/*++
X/* NAME
X/*      console 3
X/* SUMMARY
X/*      encoded ibm pc console terminal capabilities
X/* PROJECT
X/*       ms-dos/unix compatibility
X/* PACKAGE
X/*      termcap
X/* SYNOPSIS
X/*      #include "termcap.h"
X/* DESCRIPTION
X/*      The terminal capabilities for the ibm pc ANSI.SYS console driver
X/*      are stored in a static data structure named "_console". 
X/*      User access proceeds through the tget{num|str|flag} functions.
X/*
X/*      The escape character at the start of function key codes are
X/*      imaginary; the PC hardware actually returns a nul byte.
X/* SEE ALSO
X/*      tgetnum(3), tgetstr(3), tgetflag(3).
X/*      termcap(3), Berkeley extensions to UNIX.
X/* FILES
X/*      ANSI.SYS, ibm pc console driver.
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/*      Wed Jan  1 19:01:13 GMT+1:00 1986
X/* LAST MODIFICATION
X/*      Wed Jan  1 19:01:13 GMT+1:00 1986
X/* VERSION/RELEASE
X/*      1.0
X/*--*/
X
X#include "termcap.h"
X
XCap _console[] = {
X        "am",   0,                      /* auto CR-LF at right margin */
X        "bs",   0,                      /* terminal can backspace */
X        "cd",   "\033[J",               /* clear to end of screen */
X        "ce",   "\033[K",               /* clear to end of line */
X        "cl",   "\033[;H\033[2J",       /* clear whole screen */
X        "cm",   "\033[%i%d;%dH",        /* cursor movement */
X        "co",   "80",                   /* nbr of columns on screen */
X        "cr",   "\r",                   /* carriage-return */
X        "do",   "\033[B",               /* cursor down */
X        "ku",   "\033H",                /* up-arrow key */
X        "kd",   "\033P",                /* down-arrow key */
X        "kl",   "\033L",                /* left-arrow key */
X        "kr",   "\033N",                /* right-arrow key */
X        "le",   "\010",                 /* cursor left */
X        "li",   "25",                   /* nbr of lines on screen */
X        "nd",   "\033[C",               /* cursor right */
X        "nl",   "\n",                   /* linefeed character */
X        "pt",   "",                     /* has hardware tabs */
X        "PU",   "\033I",                /* page up key */
X        "PD",   "\033Q",                /* page down key */
X        "se",   "\033[m",               /* end standout mode */
X        "so",   "\033[1m",              /* enter standout (bold) mode */
X        "ue",   "\033[m",               /* end underscore mode */
X        "up",   "\033[A",               /* cursor up */
X        "us",   "\033[4m",              /* enter underscore mode */
X        0,      0,                      /* terminator */
X};
X
END_OF_termcap/console.c
if test 2788 -ne `wc -c <termcap/console.c`; then
    echo shar: \"termcap/console.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 6 \(of 8\).
cp /dev/null ark6isdone
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.