v03i006: uucp mail for pc's (5 of 8)
Wietse Venema
wswietse at eutrc3.UUCP
Thu Apr 21 02:50:16 AEST 1988
comp.sources.misc: Volume 3, Issue 6
Submitted-By: "Wietse Venema" <wswietse at eutrc3.UUCP>
Archive-Name: pcmail/Part5
#! /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 5 (of 8)."
# Contents: ascf.c comm.h deskutil.c invoke.c kpres.c logs.c path.h
# sendwork.c spoolfil.c srctoman.sh switcher.c unalias.c
# Wrapped by wietse at eutwc1 on Wed Apr 20 16:45:27 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f ascf.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"ascf.c\"
else
echo shar: Extracting \"ascf.c\" \(4105 characters\)
sed "s/^X//" >ascf.c <<'END_OF_ascf.c'
X/*++
X/* NAME
X/* ascf 3
X/* SUMMARY
X/* stdio-like ascii filter
X/* PROJECT
X/* pc-mail
X/* PACKAGE
X/* ascii filtering
X/* SYNOPSIS
X/* FILE *ascopen(name,mode)
X/* char *name;
X/* char *mode;
X/*
X/* int ascget(fp)
X/* FILE *fp;
X/*
X/* int ascclose(fp)
X/* FILE *fp;
X/* DESCRIPTION
X/* The functions in this module provide filtered stream i/o for
X/* textfiles produced by word processors. Their calling sequence
X/* has been modelled after the standard i/o library routines.
X/*
X/* ascopen() is the analogon of fopen(3), ascget() returns the next
X/* character in the filtered input stream, and ascclose() closes
X/* the stream. ascget() is a macro.
X/*
X/* The following mappings are done: cr/lf, cr, lf, lf/cr are
X/* replaced by newline; all high bits are stripped off; wordstar
X/* hyphens are converted to normal hyphens. Except for tabs,
X/* all control characters are suppressed in the output.
X/* In order to avoid problems in mailers, a newline
X/* character is appended to the last line of each file.
X/* SEE ALSO
X/* stdio(3) standard i/o library interface.
X/* DIAGNOSTICS
X/* ascopen() returns a null pointer on failure; ascget() returns
X/* the value EOF when the end of a stream is reached. ascclose()
X/* returns whatever fclose() returns.
X/* BUGS
X/* Actually works with wordstar or clean ascii files only.
X/* No character pushback.
X/* Although allowed by ascopen(), the "w" file open mode is
X/* of no use.
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/* Mon Jul 6 16:03:41 GMT+1:00 1987
X/* LAST MODIFICATION
X/* Mon Apr 4 23:34:46 MET 1988
X/* VERSION/RELEASE
X/* 1.4
X/*--*/
X
X#include <ctype.h>
X
X#include "defs.h"
X#include "ascf.h"
X
X/* some systems do not define _NFILE in stdio.h */
X
X#ifndef _NFILE
X# include <sys/param.h> /* maybe we are a sun */
X# ifdef NOFILE
X# define _NFILE NOFILE
X# else
X"ERROR: cannot get max nr of open files"
X# endif
X#endif
X
X#define CTRL(x) ((x)^0100) /* ASCII control characters */
X
X#ifdef MSDOS
X#include <fcntl.h> /* to turn cr/lf mapping off */
X#endif
X
Xpublic Asc asc[_NFILE]; /* one filter structure per file */
X
X/* ascopen - open stream, initialize intermediate buffer */
X
Xpublic FILE *ascopen(file,mode)
Xchar *file,*mode;
X{
X register FILE *fp;
X
X if (fp = fopen(file,mode)) { /* if file is accessable */
X register Asc *ap = asc+fileno(fp);
X if (ap->buf = malloc(BUFSIZ)) { /* if buffer available */
X ap->cnt = 0; /* init buffer count */
X ap->nlf = 0; /* no newline appended yet */
X#ifdef O_BINARY
X setmode(fileno(fp),O_BINARY);
X#endif
X } else {
X fclose(fp); /* no room for that buffer */
X fp = 0;
X }
X }
X return(fp);
X}
X
X/* ascclose - release intermediate buffer and close the stream */
X
Xpublic int ascclose(fp)
Xregister FILE *fp;
X{
X free(asc[fileno(fp)].buf);
X return(fclose(fp));
X}
X
X/* ascbuf - ascii filter, make new buffer of text */
X
Xpublic int ascbuf(fp)
XFILE *fp;
X{
X register Asc *ap = asc+fileno(fp); /* intermediate buffer access */
X register char *cp = ap->buf; /* init write pointer */
X register int c; /* single-character input buffer */
X int d; /* look-ahead character */
X
X while (cp < ap->buf+BUFSIZ &&
X (c = getc(fp)) != EOF && (c &= 0177) != CTRL('Z')) {
X if (c == ' ' || isprint(c) || c == '\t') {
X *cp++ = c; /* accept character */
X } else if ((c == '\r' && ((d = getc(fp)) == '\n' || (ungetc(d,fp),1)))
X || (c == '\n' && ((d = getc(fp)) == '\r' || (ungetc(d,fp),1)))) {
X *cp++ = '\n'; /* terminate line */
X } else if (c == CTRL('_')) {
X *cp++ = '-'; /* wordstar hyphen */
X } else {
X continue; /* ignore other characters */
X }
X }
X if (ap->cnt = cp-ap->buf) { /* anything in the buffer? */
X ap->ptr = ap->buf; /* yes, set read pointer */
X return(ascget(fp)); /* and return first character */
X } else if (ap->nlf == 0) { /* make sure file ends with \n */
X return(ap->nlf = '\n'); /* append newline first */
X } else { /* now we're really done */
X return(EOF); /* that's it. */
X }
X}
END_OF_ascf.c
if test 4105 -ne `wc -c <ascf.c`; then
echo shar: \"ascf.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f comm.h -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"comm.h\"
else
echo shar: Extracting \"comm.h\" \(1967 characters\)
sed "s/^X//" >comm.h <<'END_OF_comm.h'
X/*++
X/* NAME
X/* comm 5
X/* SUMMARY
X/* cico systems parameters
X/* PROJECT
X/* pc-mail
X/* PACKAGE
X/* cico
X/* SYNOPSIS
X/* #include "params.h"
X/* #include "comm.h"
X/* DESCRIPTION
X/* .nf
X
X/* /* roles and other behavioural codes */
X
X#define MASTER 1 /* who sends files */
X#define SLAVE 2 /* who receives files */
X#define DONE 3 /* no more files */
X
X#define YES 'Y'
X#define NO 'N'
X
X/* /* communications parameters (see params.h) */
X
X#define COMM_LINE (comm[P_PORT].strval)
X#define COMM_RATE (comm[P_BAUD].strval)
X#define DIAL_SEQUENCE (comm[P_DIAL].strval)
X#define LOGIN_NAME (comm[P_LOGIN].strval)
X#define DISC_SEQUENCE (comm[P_DISC].strval)
X
X/* /* related info */
X
Xextern int ttfd; /* comm. port */
Xextern Info *comm; /* comm. info */
Xextern char *password; /* password */
Xextern char rmthost[]; /* remote system name */
X
X/* /* functions that use the above */
X
Xextern char *rmtname(); /* make remote spool-file name */
Xextern char *locname(); /* make local spool-file name */
X
X/* /* protocol function pointers */
X
Xextern int (*Read)(); /* protocol read */
Xextern int (*Write)(); /* protocol write */
Xextern int (*Close)(); /* protocol close */
X
X/* /* use these at your own risk */
X
X#define MSGBUF 4096 /* message buffer size */
X
Xextern char msgin[MSGBUF]; /* message receive buffer */
Xextern char msgout[MSGBUF]; /* message send buffer */
X
X/* /* message i/o functions */
X
Xextern int isok(); /* do request; get yes or no */
Xextern char *talk(); /* send message */
Xextern char *hear(); /* receive message */
X/* SEE ALSO
X/* comm(3) implementation module
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 12 13:52:39 GMT+1:00 1987
X/* LAST MODIFICATION
X/* Mon Apr 4 23:36:42 MET 1988
X/* VERSION/RELEASE
X/* 1.3
X/*--*/
END_OF_comm.h
if test 1967 -ne `wc -c <comm.h`; then
echo shar: \"comm.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f deskutil.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"deskutil.c\"
else
echo shar: Extracting \"deskutil.c\" \(4943 characters\)
sed "s/^X//" >deskutil.c <<'END_OF_deskutil.c'
X/*++
X/* NAME
X/* deskutil 3
X/* SUMMARY
X/* utility functions
X/* PROJECT
X/* pc-mail
X/* PACKAGE
X/* mailsh
X/* SYNOPSIS
X/* #include "mailsh.h"
X/*
X/* void patience()
X/*
X/* int when()
X/*
X/* int delete()
X/*
X/* int unspool()
X/*
X/* int print()
X/*
X/* int save()
X/*
X/* char *tstamp(ltime)
X/* long *ltime()
X/* DESCRIPTION
X/* tstamp() converts absolute time to a string. If called with
X/* recent time argument (less than 100 days ago) the string will
X/* be of the form "Sun Apr 17 12:50", otherwise "Sun Apr 17 1988".
X/*
X/* delete() gives the user another chance before a message is deleted.
X/*
X/* unspool() actually deletes a message. As a side effect it destroys
X/* the current mail box display so that the next display will
X/* reflect the actual status of the spool directory.
X/* The affected message and meta file names are taken from the
X/* global "message" and "commant" string variables.
X/*
X/* print() copies a pager file to the printer.
X/*
X/* save() asks where the pager file should be saved.
X/*
X/* when() should be called after the user has entered a mail destination
X/* address. It informs the user that messages are not sent right away,
X/* but after selection of the Network option in the main menu.
X/*
X/* patience() prints a 'one moment please' message in the middle
X/* screen window. As a side effect, the current pager file is set
X/* to none.
X/* FILES
X/* mail header files in the 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/* Tue May 12 15:35:20 GMT+1:00 1987
X/* LAST MODIFICATION
X/* Mon Apr 4 23:38:26 MET 1988
X/* VERSION/RELEASE
X/* 1.3
X/*--*/
X
X#include <errno.h>
X
X#include "defs.h"
X#include "pager.h"
X#include "mailsh.h"
X#include "screen.h"
X#include "status.h"
X
Xhidden int save_desk();
X
X/* patience - say this will take some time */
X
Xpublic void patience()
X{
X static char *m_wait[] = {
X "",
X "One moment please...",
X 0,
X };
X
X register File *pp = open_pager(); /* create pager file */
X
X mesg_pager(pp,m_wait); /* write pager file */
X ds_pager(); /* show om middle window */
X close_pager(pp); /* forget pager file */
X}
X
X/* delete - user wants to delete a message; ask for confirmation */
X
Xpublic int delete()
X{
X static Screen screen[] = {
X ESCCR, "Enter", unspool,int_error,
X 0, 0, 0,
X "Press ESC to cancel. Confirm with ENTER",
X };
X
X return(kbdinp(screen)|S_REDRAW);
X}
X
X/* unspool - actually delete a message; force mail box display rebuild */
X
Xpublic int unspool()
X{
X if (((chmod(message,0666) || unlink(message)) && errno != ENOENT)
X || ((chmod(comment,0666) || unlink(comment)) && errno != ENOENT)) {
X errdisp(E_UNLINK); /* notify user of problem */
X return(S_REDRAW); /* say screen has changed */
X } else {
X junk_desk(); /* say mail box has changed */
X return(S_BREAK); /* no more work to do */
X }
X}
X
X/* print - print pager display on default printer */
X
Xpublic int print()
X{
X return(pr_pager() ? (errdisp(E_PRINTERR),S_REDRAW) : 0);
X}
X
X/* save - ask where pager display should be copied to */
X
Xpublic int save()
X{
X static Screen screen[] = {
X STRING, 0, save_desk,int_error,
X 0, 0, 0,
X "Press ESC to cancel. Save to file:",
X };
X
X kbdinp(screen); /* prompt for file name, then copy */
X return(S_REDRAW); /* force screen repaint */
X}
X
X/* save_desk - copy pager file to ordinary file */
X
Xhidden int save_desk(to)
Xchar *to;
X{
X if (cp_pager(to)) { /* if file copy failed */
X unlink(to); /* remove that file */
X errdisp(E_WRITERR); /* notify the user */
X return(S_BREAK|S_REDRAW); /* redisplay, terminate caller */
X } else {
X junk_file(); /* say file display maybe outdated */
X return(S_BREAK); /* terminate caller */
X }
X}
X
X/* when - say when mail will actually be sent */
X
Xpublic int when()
X{
X static char *msg[] = {
X "",
X "To send messages through the network, use the Network",
X "option in the main menu.",
X 0,
X };
X File *pp = open_pager(); /* open new pager file */
X
X mesg_pager(pp,msg); /* fill pager file */
X ds_pager(); /* display the file */
X close_pager(pp); /* forget pager file */
X return(0); /* don't care value */
X}
X
X/* tstamp - time format as produced by the ls(1) command */
X
Xpublic char *tstamp(ltime)
Xlong *ltime;
X{
X static char buf[25];
X
X /*
X * Output from asctime() is of the form
X * "Sun Apr 17 13:34:35 1988"
X * Depending on how recent the time in question is, we
X * supress the time or year field.
X */
X
X (void) strcpy(buf,asctime(localtime(ltime)));
X if (time((long *)0)-*ltime > 60L*60L*24L*100L) {
X buf[24] = '\0'; /* remove the \n */
X (void) strcpy(buf+11,buf+19); /* old file, show year */
X } else
X buf[16] = '\0'; /* recent, show time */
X return(buf);
X}
END_OF_deskutil.c
if test 4943 -ne `wc -c <deskutil.c`; then
echo shar: \"deskutil.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f invoke.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"invoke.c\"
else
echo shar: Extracting \"invoke.c\" \(4946 characters\)
sed "s/^X//" >invoke.c <<'END_OF_invoke.c'
X/*++
X/* NAME
X/* invoke 3
X/* SUMMARY
X/* system-dependent process control stuff
X/* PROJECT
X/* pc-mail
X/* PACKAGE
X/* mailsh
X/* SYNOPSIS
X/* #include "status.h"
X/*
X/* int invokelp(arg0,arg1,...)
X/* char *arg0,*arg1,...
X/*
X/* int invokevp(argv)
X/* char **argv;
X/*
X/* int onexit(command)
X/* char *command;
X/* DESCRIPTION
X/* invokelp() creates a child process to execute a command.
X/* arg0, arg1,... is a null-terminated list of string pointers,
X/* the first being the name of the program. Use is made
X/* of the search path to locate the program in arg0.
X/*
X/* invokevp() is similar to invokelp; the difference is that
X/* argv is an array of pointers to arguments.
X/*
X/* onexit() executes a command, thereby terminating the current process.
X/* DIAGNOSTICS
X/* invokelp(), invokevp() return the exit status of the child process,
X/* E_SYSFAIL if there were insufficient resources, and
X/* E_NOPROG if the program in arg0 or argv[0] could not be found.
X/*
X/* onexit() return -1 if there were problems.
X/* BUGS
X/* The invokexx() functions should not be used if the command needs to
X/* be handled by a command-language processor (e.g. shell built-ins,
X/* or i/o redirection).
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:19:56 MET 1988
X/* VERSION/RELEASE
X/* 1.4
X/*--*/
X
X#include <errno.h>
X#include "defs.h"
X#include "status.h"
X
X#ifdef MSDOS
X#include <process.h>
X#endif
X
X/* invokelp - create child process to execute command */
X
X/* VARARGS2 */
X
Xpublic int invokelp(arg0,arg1,arg2,arg3,arg4)
Xchar *arg0,*arg1,*arg2,*arg3,*arg4;
X{
X /*
X * On unix systems we fork a process and overlay the child with
X * the desired program.
X * This means we get -1 if the fork did not succeed, otherwise
X * the exit status if the child process. The code is a bit elaborate
X * since we want to handle various error conditions.
X */
X#ifdef unix
X register int pid;
X
X if ((pid = fork()) < 0) { /* fork off a process */
X return(E_SYSFAIL); /* resources exhausted */
X } else if (pid == 0) { /* this is the child process */
X execlp(arg0,arg0,arg1,arg2,arg3,arg4);/* try to replace it */
X _exit(errno == ENOENT ? E_NOPROG : E_SYSFAIL); /* sorry, failed */
X /* NOTREACHED */
X } else {
X int xstat,wstat; /* wait till above child terminates */
X while ((wstat = wait(&xstat)) != -1 && wstat != pid)
X /* void */ ;
X if (wstat == -1) {
X return(E_SYSFAIL); /* oops: no child! */
X } else if (xstat&0377) {
X return(E_UNKNOWN); /* child was killed */
X } else {
X return(xstat>>8); /* child died naturally */
X }
X /* NOTREACHED */
X }
X#endif
X
X /*
X * On MS-DOS systems we try to avoid the command.com shell because
X * it always returns a zero status code.
X */
X#ifdef MSDOS
X int stat;
X char *p;
X
X if ((stat = spawnlp(P_WAIT,arg0,arg0,arg1,arg2,arg3,arg4)) < 0
X && errno == ENOENT
X && (strcmp(p = arg0+strlen(arg0)-4,".bat") == 0 || strcmp(p,".BAT") == 0))
X stat = spawnlp(P_WAIT,"command","command","/c",arg0,arg1,arg2,arg3,arg4);
X return(stat >= 0 ? stat : (errno == ENOENT ? E_NOPROG : E_SYSFAIL));
X#endif
X}
X
X/* invokelp - create child process to execute command */
X
Xpublic int invokevp(argv)
Xchar **argv;
X{
X /*
X * On unix systems we fork a process and overlay the child with
X * the desired program.
X * This means we get -1 if the fork did not succeed, otherwise
X * the exit status if the child process. The code is a bit elaborate
X * since we want to handle various error conditions.
X */
X#ifdef unix
X register int pid;
X
X if ((pid = fork()) < 0) { /* fork off a process */
X return(E_SYSFAIL); /* resources exhausted */
X } else if (pid == 0) { /* this is the child process */
X execvp(*argv,argv); /* try to replace it */
X _exit(errno == ENOENT ? E_NOPROG : E_SYSFAIL); /* sorry, failed */
X /* NOTREACHED */
X } else {
X int xstat,wstat; /* wait till above child terminates */
X while ((wstat = wait(&xstat)) != -1 && wstat != pid)
X /* void */ ;
X if (wstat == -1) {
X return(E_SYSFAIL); /* oops: no child! */
X } else if (xstat&0377) {
X return(E_UNKNOWN); /* child was killed */
X } else {
X return(xstat>>8); /* child died naturally */
X }
X /* NOTREACHED */
X }
X#endif
X
X /*
X * On MS-DOS systems we try to avoid the command.com shell because
X * it always returns a zero status code.
X */
X#ifdef MSDOS
X int stat;
X
X return((stat = spawnvp(P_WAIT,*argv,argv)) >= 0 ?
X stat : (errno == ENOENT ? E_NOPROG : E_SYSFAIL));
X#endif
X}
X
X/* onexit - exec another command */
X
Xint onexit(command)
Xchar *command;
X{
X if (command && *command) {
X#ifdef unix
X return(execlp("/bin/sh","sh","-c",command));
X#endif
X
X#ifdef MSDOS
X return(system(command));
X#endif
X }
X}
END_OF_invoke.c
if test 4946 -ne `wc -c <invoke.c`; then
echo shar: \"invoke.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f kpres.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"kpres.c\"
else
echo shar: Extracting \"kpres.c\" \(4951 characters\)
sed "s/^X//" >kpres.c <<'END_OF_kpres.c'
X/*++
X/* NAME
X/* kpres
X/* SUMMARY
X/* k-protocol presentation layer
X/* PACKAGE
X/* uucp across thenet
X/* SYNOPSIS
X/* #include "kp.h"
X/*
X/* kopen(fd)
X/* int fd;
X/*
X/* kwrite(fd,buf,len)
X/* int fd,len;
X/* char *buf;
X/*
X/* kread(fd,buf,len)
X/* int fd,len;
X/* char *buf;
X/*
X/* kclose(fd)
X/* int fd;
X/* DESCRIPTION
X/* This section contains functions that imitate standard unix
X/* unbuffered i/o facilities. A status code of FAIL is returned when
X/* the network partner wants to terminate the protocol, or when the
X/* the transmission error rate is excessive.
X/*
X/* Eight-bit data bytes are transported as harmless six-bit data bytes
X/* in the ASCII range 32 through 95. This introduces an overhead of 33%.
X/* For textfiles, this is hardly worse than kermit (typical overhead
X/* 10 %). For binary files the overhead is much less than with kermit
X/* (typical overhead 60%).
X/*
X/* Kopen() sets up the terminal characteristics of the specified file
X/* descriptors (no echo, raw, tandem). Always returns zero status.
X/*
X/* Kwrite() attempts to send the bytes in buf. A zero-length buffer
X/* should be written to indicate an end-of-file condition. Return status:
X/* the number of bytes requested, or FAIL.
X/*
X/* Kread() attempts to read the requested number of bytes. Status code:
X/* the number of bytes actually read, or FAIL. A read of zero bytes
X/* normally indicates an end-of-file condition (see kwrite).
X/*
X/* Kclose() sends a protocol abort sequence to the network partner.
X/* This function should be called to terminate the k protocol driver
X/* at the other end, or to confirm reception of a protocol abort sequence.
X/* Kclose always returns zero exit status.
X/*
X/* The function kfail() is called by the strategy layer functions to
X/* indicate protocol failure or termination.
X/* FUNCTIONS AND MACROS
X/* kwproto, krproto, kclsproto
X/* BUGS
X/* Zero byte read/writes are a clumsy way to handle end-of-files.
X/* They have been implemented for the sake of compatibility with uucico.
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 11:14:13 MET 1986
X/* LAST MODIFICATION
X/* Mon Apr 4 23:43:28 MET 1988
X/* VERSION/RELEASE
X/* 1.3
X/*--*/
X
X#ifdef unix
X# ifdef SIII
X# include <termio.h>
X# else
X# include <sgtty.h>
X# endif
X#endif
X#include <setjmp.h>
X#include "kp.h"
X
Xstatic jmp_buf Failbuf;
X
Xkfail()
X{
X longjmp(Failbuf,TRUE);
X}
X
Xkopen(fd)
Xint fd;
X{
X#ifdef unix
X# ifdef SIII
X struct termio ttymode;
X
X ioctl(fd,TCGETA,&ttymode);
X ttymode.c_iflag = IXOFF|IXON|ISTRIP;
X ttymode.c_cc[VMIN] = 1;
X ttymode.c_cc[VTIME] = 0;
X ioctl(fd,TCSETA,&ttymode);
X# else
X struct sgttyb ttymode;
X
X gtty(fd,&ttymode);
X ttymode.sg_flags |= (TANDEM|RAW);
X ttymode.sg_flags &= ~(ECHO|CBREAK);
X stty(fd,&ttymode);
X# endif
X#else
X xioctl(1);
X#endif
X return 0;
X}
X
Xkwrite(fd,buf,len)
Xint fd;
Xregister char *buf;
Xregister int len;
X{
X static char packbuf[MAXPACKSIZ];
X static char *packptr = packbuf;
X register int c,i,rest,shift;
X
X /* set error trap */
X
X if (setjmp(Failbuf))
X return FAIL;
X
X /* if 'end of data' send null packet */
X
X if (len <= 0) {
X kwproto(fd,NULLP,0);
X return 0;
X
X /* expand 3 eight-bit bytes to four six-bit bytes */
X
X } else {
X for (rest = shift = i = 0; i < len; shift = (shift+STEP)%OUT,i++) {
X
X c = *buf++ & 0377; /* No sign extension */
X *packptr++ = tosix(rest|(c << shift)); /* Assemble byte */
X rest = (c >> (OUT-shift)); /* Save unused bits */
X
X if (shift == (OUT-STEP)) { /* At byte boundary? */
X *packptr++ = tosix(rest); /* Make 'fourth' byte */
X rest = 0; /* No unused bits now */
X if (packptr-packbuf > PACKSIZ-4) { /* Check packet size */
X kwproto(fd,packbuf,packptr-packbuf);
X packptr = packbuf;
X }
X }
X }
X if (shift) { /* Any bits left? */
X *packptr++ = tosix(rest); /* Put them there */
X }
X if (packptr > packbuf) { /* Flush buffer */
X kwproto(fd,packbuf,packptr-packbuf); /* Ship it off */
X packptr = packbuf;
X }
X return i;
X }
X}
X
Xkread(fd,buf,len)
Xint fd;
Xchar *buf;
Xint len;
X{
X static char packbuf[MAXPACKSIZ] = "";
X static char *packptr = packbuf;
X static int packsiz = 0;
X register int i,c;
X static int shift,rest;
X
X /* set error trap */
X
X if (setjmp(Failbuf))
X return FAIL;
X
X /* read packet if buffer is empty */
X
X if (packsiz <= 0) {
X krproto(fd,packptr = packbuf,&packsiz);
X rest = shift = 0;
X }
X
X /* unpack (remainder of) buffer; return 0 if empty packet received */
X
X for (i = 0; (i < len) && packsiz--; shift = (shift+STEP)%IN)
X {
X c = unsix(*packptr++);
X if (shift)
X buf[i++] = (rest | (c << (IN-shift)));
X rest = (c >> shift);
X }
X return i;
X}
X
Xkclose(fd)
Xint fd;
X{
X /* not here - pass job to the lower layer that understands packet types */
X
X kclsproto(fd);
X return 0;
X}
X
X
END_OF_kpres.c
if test 4951 -ne `wc -c <kpres.c`; then
echo shar: \"kpres.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f logs.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"logs.c\"
else
echo shar: Extracting \"logs.c\" \(4714 characters\)
sed "s/^X//" >logs.c <<'END_OF_logs.c'
X/*++
X/* NAME
X/* logs 3
X/* SUMMARY
X/* error logging, status reports, debugging
X/* PROJECT
X/* pc-mail
X/* PACKAGE
X/* cico
X/* SYNOPSIS
X/* void dbg(fmt[,args]);
X/* char *fmt;
X/*
X/* int open_log();
X/*
X/* void log(fmt[,args]);
X/* char *fmt;
X/*
X/* void trap(code,fmt[,args]);
X/* char *fmt;
X/* DESCRIPTION
X/* All functions in this module do some form of logging, and accept
X/* printf-like format strings with %s, %c, and %S, %C. The latter
X/* two cause output mapping of arbitrary byte values to printable codes.
X/*
X/* dbg() formats its arguments and writes the result to the standard
X/* output.
X/*
X/* open_log() tries to open the logfile for writing. It returns
X/* a status E_WRITERR if the file could not be opened or created.
X/*
X/* log() writes status info to the log file. If debugging is enabled,
X/* the message is also written to the standard output.
X/*
X/* trap() writes a message to the log file and performs a longjmp call
X/* (systrap) with the status as given in the code parameter. If
X/* debugging is enabled, the message is also written to the standard
X/* output.
X/* FUNCTIONS AND MACROS
X/* longjmp()
X/* FILES
X/* LOGFILE status reports
X/* BUGS
X/* Logfile info may be lost if the program terminates abnormally.
X/* We do not open/close the with each log() call since that would
X/* slow down performance on floppy-based systems dramatically.
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 Mar 26 17:45:19 GMT+1:00 1987
X/* LAST MODIFICATION
X/* Mon Apr 4 23:44:00 MET 1988
X/* VERSION/RELEASE
X/* 1.3
X/*--*/
X
X#include <setjmp.h>
X#include <ctype.h>
X#include <varargs.h>
X#include "defs.h"
X#include "logs.h"
X#include "path.h"
X#include "status.h"
X
X#define dbgout stdout /* where debugging output should go */
X
Xhidden FILE *logfp = NULL; /* log file file pointer */
Xhidden char *visible(); /* map characters to readable codes */
Xhidden void dprintf(); /* special-purpose formatting function */
X
X/* dbg - write debugging info to the debugging output */
X
X/* VARARGS1 */
X
Xpublic void dbg(fmt,va_alist)
Xregister char *fmt;
Xva_dcl
X{
X va_list s;
X
X va_start(s);
X dprintf(dbgout,fmt,s);
X va_end(s);
X}
X
X/* open_log - check the logfile can be written */
X
Xpublic int open_log()
X{
X if (logfp == NULL && (logfp = fopen(logfile(),"a")) == NULL)
X return(E_WRITERR);
X else
X return(0);
X}
X
X/* log - write status info to the log file */
X
X/* VARARGS1 */
X
Xpublic void log(fmt,va_alist)
Xregister char *fmt;
Xva_dcl
X{
X va_list s;
X
X /* log file should be open! */
X
X if (logfp == NULL)
X exit(E_CONFUSED);
X
X /* write status record to log file */
X
X va_start(s);
X dprintf(logfp,fmt,s);
X putc('\n',logfp);
X va_end(s);
X
X /* if debugging on, write also to debugging output */
X
X if (dflag) {
X va_start(s);
X dprintf(dbgout,fmt,s);
X putc('\n',dbgout);
X va_end(s);
X }
X}
X
X/* trap - exception handler */
X
X/* VARARGS2 */
X
Xpublic void trap(code,fmt,va_alist)
Xint code;
Xchar *fmt;
Xva_dcl
X{
X va_list s;
X
X /* write exception record to log file */
X
X va_start(s);
X dprintf(logfp,fmt,s);
X putc('\n',logfp);
X va_end(s);
X
X /* if debugging on, write also to debugging output */
X
X if (dflag) {
X va_start(s);
X dprintf(dbgout,fmt,s);
X putc('\n',logfp);
X va_end(s);
X }
X longjmp(systrap,code);
X}
X
X/* visible - turn arbitrary character into something visible */
X
Xstatic char *visible(c)
Xregister int c;
X{
X static char buf[5];
X
X switch(c&=0377) {
X default:
X sprintf(buf,isascii(c) && isprint(c) ? "%c" : "\\%03o",c);
X return(buf);
X case ' ':
X return("\\s");
X case '\b':
X return("\\b");
X case '\t':
X return("\\t");
X case '\r':
X return("\\r");
X case '\n':
X return("\\n");
X case '\f':
X return("\\f");
X case '\\':
X return("\\\\");
X }
X}
X
X/* dprintf - handle %s, %c, %S and %C format requests */
X
Xstatic void dprintf(fp,fmt,s)
Xregister FILE *fp;
Xregister char *fmt;
Xva_list s;
X{
X register int c;
X
X for (/* void */; c = *fmt; fmt++) {
X if (c != '%') {
X putc(c,fp);
X } else if ((c = *++fmt) == 'S') { /* %S: translated */
X register char *cp = va_arg(s,char *);
X while(*cp)
X fputs(visible(*cp++&0377),fp);
X } else if (c == 'C') { /* %C: translated */
X fputs(visible(va_arg(s,int)),fp);
X } else if (c == 's') { /* %s: string, as is */
X fputs(va_arg(s,char *),fp);
X } else if (c == 'c') { /* %c: char, as is */
X putc(va_arg(s,int),fp);
X } else if (c == '%') { /* real % character */
X putc(c,fp);
X }
X }
X}
END_OF_logs.c
if test 4714 -ne `wc -c <logs.c`; then
echo shar: \"logs.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f path.h -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"path.h\"
else
echo shar: Extracting \"path.h\" \(4342 characters\)
sed "s/^X//" >path.h <<'END_OF_path.h'
X/*++
X/* NAME
X/* path
X/* SUMMARY
X/* system-dependent file name definitions
X/* PROJECT
X/* pc-mail
X/* PACKAGE
X/* general
X/* SYNOPSIS
X/* #include "path.h"
X/* DESCRIPTION
X/* File-system dependent definitions should be changed here.
X/* .nf
X
X/* /* the minmal number of open files we think we need */
X
X#define MINFILES 10
X
X/* /* system-dependent defaults */
X
X#ifdef unix
X#define THISDIR "." /* current directory */
X#define DEFSPOOL "./spool" /* default spool directory */
X#define DEFEDIT "vi" /* default editor */
X#ifdef SIII
X#define DEFPRINT "lp" /* printer spooler */
X#else
X#define DEFPRINT "lpr" /* printer spooler */
X#endif
X#define MAILFILE "mail.msg" /* temporary message file */
X#define TMPALIAS "tmp.alias" /* temp alias file */
X#define NULLDEV "/dev/null" /* bit dump */
X#endif
X
X#ifdef MSDOS
X#define THISDIR "." /* current directory */
X#define DEFSPOOL "\\spool" /* spool directory */
X#define DEFEDIT "edlin" /* default editor */
X#define DEFPRINT "PRN" /* default printer */
X#define MAILFILE "mail.msg" /* temp message file */
X#define TMPALIAS "alias.tmp" /* temp alias file */
X#define NULLDEV "NUL" /* bit dump */
X#endif
X
X/* /* system-dependent function calls for file & printer access */
X
X#ifdef unix
X#define propen() popen(mailprn,"w") /* open printe stream */
X#define prclose(p) pclose(p) /* close print stream */
X#define fspool(file) strcons("%s/%s",maildir,file)
X#endif
X
X#ifdef MSDOS
X#define propen() fopen(mailprn,"a") /* open print stream */
X#define prclose(p) (putc('\014',p),fclose(p)) /* close print stream */
X#define fspool(file) strcons("%s\\%s",maildir,file)
X#endif
X
X/* /* system-independent file names */
X
X#define SMAIL "smail" /* queues a mail message */
X#define CICO "cico" /* file transfer program */
X#define RMAIL "rmail" /* extract originator address */
X
X/* /*
X* The spool directory is used for storage of all files manipulated
X* by the mail programs. Message files should always have a meta file
X* with information about the destination or origin of a message file.
X*
X* Message/meta file names are of the form <letter><sequence number>.
X* Corresponding message/meta files have the same sequene number.
X* The following definitions are for the <letter> part of spool files.
X*/
X
X#define LOGFILE "LOGFILE" /* transaction logs */
X
X#define NEWPFX "n" /* received message */
X#define HDRPFX "h" /* originator of new mail */
X#define OLDPFX "o" /* originator of old mail */
X
X#define MSGPFX "d" /* message ready to be sent */
X#define XQTPFX "x" /* its destination */
X
X#define EDTPFX "e" /* message being worked on */
X#define COMPFX "c" /* its description */
X
X#define SETPFX "s" /* system parameter file */
X
X#define ALIPFX "a" /* alias data base */
X
X#define SPLFMT "%s%05d" /* spool-file name format */
X
X/* /*
X* The following macros provide convenient access of spool files, so we
X* don't have to remember the spool file name format and prefix stuff.
X*/
X
X#define sendmail(file,to) spoolfil(file,to,MSGPFX,XQTPFX)
X#define workon(fname,meta) spoolfil(fname,meta,EDTPFX,COMPFX)
X
X#define parm_file() fspool(strcons(SPLFMT,SETPFX,0))
X#define aliases() fspool(strcons(SPLFMT,ALIPFX,0))
X#define logfile() fspool(LOGFILE)
X
X#define meta_file(type,id) fspool(strcons(SPLFMT,type,id))
X#define mesg_file(type,id) fspool(strcons(SPLFMT,type,id))
X
X#define work_meta(id) fspool(strcons(SPLFMT,COMPFX,id))
X#define work_mesg(id) fspool(strcons(SPLFMT,EDTPFX,id))
X
X#define in_mesg(id) fspool(strcons(SPLFMT,NEWPFX,id))
X#define in_meta(id) fspool(strcons(SPLFMT,OLDPFX,id))
X
X#define new_mesg(id) fspool(strcons(SPLFMT,NEWPFX,id))
X#define new_meta(id) fspool(strcons(SPLFMT,HDRPFX,id))
X
X#define out_mesg(id) fspool(strcons(SPLFMT,MSGPFX,id))
X#define out_meta(id) fspool(strcons(SPLFMT,XQTPFX,id))
X
X/* /* stuff taken from the environment */
X
Xextern char *editor; /* path to editor */
Xextern char *maildir; /* spool directory */
Xextern char *mailprn; /* how to print */
Xextern char *mailcmd; /* do this on exit */
X
Xextern int pathinit(); /* get path info from environment */
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:23:45 GMT+1:00 1987
X/* LAST MODIFICATION
X/* Wed Apr 6 00:21:29 MET 1988
X/* VERSION/RELEASE
X/* 1.4
X/*--*/
END_OF_path.h
if test 4342 -ne `wc -c <path.h`; then
echo shar: \"path.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f sendwork.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"sendwork.c\"
else
echo shar: Extracting \"sendwork.c\" \(4326 characters\)
sed "s/^X//" >sendwork.c <<'END_OF_sendwork.c'
X/*++
X/* NAME
X/* sendwork 3
X/* SUMMARY
X/* send local work to remote system
X/* PROJECT
X/* pc-mail
X/* PACKAGE
X/* cico
X/* SYNOPSIS
X/* #include "work.h"
X/*
X/* void sendwork(wrk)
X/* work *wrk;
X/* DESCRIPTION
X/* sendwork converts names and contents of local work files,
X/* sends them to the remote system and deletes the files after
X/* successfull transfer.
X/*
X/* In particular, it generates appropriate "From " lines at the
X/* beginning of an outgoing mail message.
X/* FUNCTIONS AND MACROS
X/* rmtname()
X/* SEE ALSO
X/* scanwork(3) locates work in the spool directory
X/* rmtname(3) rules for remote file name construction
X/* DIAGNOSTICS
X/* sendwork() returns via longjmp(systrap,errorcode) in case
X/* of unrecoverable problems.
X/*
X/* The error codes are: E_CONFUSED (unexpected work type),
X/* E_LOST (timed out), E_READERR (file read error).
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 Mar 26 11:32:23 GMT+1:00 1987
X/* LAST MODIFICATION
X/* Wed Apr 6 00:22:23 MET 1988
X/* VERSION/RELEASE
X/* 1.4
X/*--*/
X
X#include <time.h>
X#include "defs.h"
X#include "work.h"
X#include "logs.h"
X#include "status.h"
X#include "params.h"
X#include "comm.h"
X
Xextern struct tm *localtime(); /* std C library */
X
X/*
X* A pc-mail system can connect to the UNIX net in at least two modes:
X*
X* 1. As a real UUCP node, with it's own node name. This node name will
X* have to appear in the "From " lines of outgoing mail. A consequence
X* is that the pc mail node name should be known in mailer routing tables.
X* Obviously this implies some administrative work when a pc mail node
X* is added to the net or taken out of operation.
X*
X* 2. As an ordinary user. The program lets the UNIX host believe that
X* mail messages come from an ordinary user. Recipients of mail will
X* not be able to see that the mail came from the pc. Only the UNIX host
X* knows it should forward mail for unixhost!xyz to the pc-mail node.
X* This approach has the advantage that adding/deleting pc-mail nodes
X* is simpler.
X*/
X
X#ifdef UUCP_NODE /* case 1 */
X# define U_USER "root" /* use current user's name */
X# define U_HOST LOGIN_NAME /* use pc host name */
X#else /* case 2 */
X# define U_USER LOGIN_NAME /* use remote login name */
X# define U_HOST rmthost /* use remote host name */
X#endif
X
X/* sendwork - adapt file contents for remote host */
X
Xpublic sendwork(wrk)
Xwork *wrk;
X{
X register char *date;
X long secs;
X
X switch (wrk->type) {
X
X /*
X * Local D files contain the mail message, nothing more, nothing less.
X * We add a "From " line with originator/date/system.
X * Otherwise, D files can be sent as is.
X */
X
X case 'D':
X secs = time((long *)0);
X (date = asctime(localtime(&secs)))[24] = '\0';
X say(strcons("From %s %s remote from %s\n",U_USER,date,U_HOST));
X send_file(wrk->fp);
X break;
X
X /*
X * Local X files contain the destination network address only.
X * Therefore we must mock up some extra info to make the
X * remote uuxqt program happy.
X */
X
X case 'X':
X say(strcons("U %s %s\n",U_USER,U_HOST)); /* U user system */
X say(strcons("F %s\n",rmtname('D',wrk->tail))); /* F D.rmtsysGnumber */
X say(strcons("I %s\n",rmtname('D',wrk->tail))); /* I D.rmtsysGnumber */
X say("C rmail "); /* C rmail */
X send_file(wrk->fp); /* send destination */
X break;
X
X default:
X trap(E_CONFUSED,"INTERNAL ERROR (unexpected work type: %c)",wrk->type);
X }
X}
X
X/* say - write string to host */
X
Xhidden say(str)
Xchar *str;
X{
X if (CALL(Write)(ttfd,str,strlen(str)) < 0)
X trap(E_LOST,"FAILED (link lost)");
X}
X
X/* send_file - do the nitty-gritty of file transfer; traps on all errors */
X
Xhidden send_file(fp)
Xregister FILE *fp;
X{
X register int nread,nwrite = 0;
X char buf[BUFSIZ];
X register int rerror;
X
X while ((nread = fread(buf,sizeof(*buf),sizeof(buf),fp)) > 0 &&
X (nwrite = CALL(Write)(ttfd,buf,nread)) == nread)
X /* empty */;
X rerror = ferror(fp);
X fclose(fp);
X
X if (rerror) {
X trap(E_READERR,"FILE READ ERROR (%s)",sys_errlist[errno]);
X /* NOTREACHED */
X } else if (nwrite < 0 || CALL(Write)(ttfd,buf,0) != 0) {
X trap(E_LOST,"FAILED (link lost)");
X /* NOTREACHED */
X }
X}
END_OF_sendwork.c
if test 4326 -ne `wc -c <sendwork.c`; then
echo shar: \"sendwork.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f spoolfil.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"spoolfil.c\"
else
echo shar: Extracting \"spoolfil.c\" \(4020 characters\)
sed "s/^X//" >spoolfil.c <<'END_OF_spoolfil.c'
X/*++
X/* NAME
X/* spoolfil,metafile 3
X/* SUMMARY
X/* create message file and meta file
X/* PROJECT
X/* pc-mail
X/* PACKAGE
X/* general utilities
X/* SYNOPSIS
X/* int spoolfil(mesg,meta_info,mesg_prefix,meta_prefix)
X/* char *mesg;
X/* char *meta_info;
X/* char *mesg_prefix;
X/* char *meta_prefix;
X/*
X/* int metafile(string,path)
X/* char *string;
X/* char *path;
X/* DESCRIPTION
X/* spoolfil() creates a message, meta file pair in the spool
X/* directory.
X/*
X/* "mesg" should be null-terminated string with the name of an existing
X/* file. The contents of that file are filtered to produce a
X/* clean ASCII file.
X/*
X/* "meta-info" is a string with additional information that is
X/* written to a meta file (usually name of mail recipient, mail
X/* originator or a comment describing the contents of the message file).
X/*
X/* "mesg_prefix," "meta_prefix" are strings that will be used for building
X/* names for files in the spool directory.
X/*
X/* metafile() creates a file, writes a string to it and terminates
X/* the file with a newline character. This function is typically used
X/* to create a file with meta information (mail originator, message
X/* summary etc.).
X/* FUNCTIONS AND MACROS
X/* ascopen(), ascget(), ascclose(), newseqno()
X/* DIAGNOSTICS
X/* A nonzero return value indicates an error condition (see status.h)
X/* SEE ALSO
X/* status(5) return values
X/* ascf(3) ASCII filter
X/* BUGS
X/* Wordprocessor control codes etc will be lost when spoolfil copies
X/* a 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/* Mon May 18 18:45:10 GMT+1:00 1987
X/* LAST MODIFICATION
X/* Mon Apr 4 23:50:14 MET 1988
X/* VERSION/RELEASE
X/* 1.3
X/*--*/
X
X#include "defs.h"
X#include "path.h"
X#include "ascf.h"
X#include "status.h"
X
X/* metafile - create a one-liner file */
X
Xpublic int metafile(string,file)
Xchar *string;
Xchar *file;
X{
X register FILE *fp;
X
X if ((fp = fopen(file,"w")) == 0) {
X return(E_WRITERR);
X } else if (fprintf(fp,"%s\n",string),ferror(fp)) {
X fclose(fp);
X return(E_WRITERR);
X } else {
X fclose(fp);
X return(0);
X }
X}
X
X/* spoolfil - make arbitrary spool file */
X
Xpublic int spoolfil(fname,meta,msgpfx,auxpfx)
Xchar *fname;
Xchar *meta;
Xchar *msgpfx;
Xchar *auxpfx;
X{
X register int newid = newseqno(); /* new message id */
X register int stat; /* some status */
X char *msgpath; /* new message file */
X char *auxpath; /* new meta file */
X
X msgpath = mesg_file(msgpfx,newid); /* message file path */
X auxpath = meta_file(auxpfx,newid); /* meta file path */
X
X /* copy disk file to spool file, check for errors */
X
X if (stat = copyfile(fname,msgpath)) { /* read/write error */
X unlink(msgpath); /* delete msg file */
X return(stat); /* notify caller */
X
X /* create file for meta information, check for errors */
X
X } else if (stat = metafile(meta,auxpath)) { /* metafile error */
X unlink(msgpath); /* delete msg file */
X unlink(auxpath); /* delete meta file */
X return(stat); /* notify caller */
X
X /* when nothing went wrong */
X
X } else {
X chmod(msgpath,0444); /* message read-only */
X chmod(auxpath,0444); /* metafile read-only */
X return(0); /* own error handling */
X }
X}
X
X/* copyfile - copy a file and filter it */
X
Xpublic int copyfile(from,to)
Xchar *from;
Xchar *to;
X{
X register FILE *in,*out; /* file pointers */
X int rerr,werr; /* error status */
X
X if ((in = ascopen(from,"r")) == 0) { /* cannot read ?? */
X return(E_READERR);
X } else if ((out = fopen(to,"w")) == 0) { /* cannot write */
X ascclose(in);
X return(E_WRITERR);
X } else {
X register int c;
X while ((c = ascget(in)) != EOF) /* ASCII filter */
X putc(c,out);
X rerr = ferror(in); /* check read status */
X werr = ferror(out); /* check write status */
X ascclose(in);
X fclose(out);
X if (rerr) {
X return(E_READERR);
X } else if (werr) {
X return(E_WRITERR);
X } else {
X return(0);
X }
X }
X}
END_OF_spoolfil.c
if test 4020 -ne `wc -c <spoolfil.c`; then
echo shar: \"spoolfil.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f srctoman.sh -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"srctoman.sh\"
else
echo shar: Extracting \"srctoman.sh\" \(4444 characters\)
sed "s/^X//" >srctoman.sh <<'END_OF_srctoman.sh'
X: srctoman - see comment below
X
X: process arguments
X
Xwhile :
Xdo
X case $1 in
X [0-9]) SECT=$1;;
X -) LANG=$1; B='[#:]';;
X -awk) LANG=$1; B='#';;
X -c) LANG=$1; B='\/\*';;
X -f) LANG=$1; B='[Cc]';;
X -mk) LANG=$1; B='#';;
X -n|-t) LANG=$1; B='\\"';;
X -p) LANG=$1; B='{';;
X -r) LANG=$1; B='#';;
X -C) LANG=$1; B=$2; shift;;
X -*) ERROR="unknown option: $1"; break;;
X "") ERROR="missing file argument"; break;;
X *) break;;
X esac
X shift
Xdone
X
X: check error status
X
Xcase $ERROR in
X"") ;;
X *) echo "$0: $ERROR" 1>&2
X echo "usage: $0 [-|-awk|-c|-f|-mk|-n|-p|-t|-r] [section] file(s)" 1>&2; exit 1;;
Xesac
X
X: set up for file suffix processing
X
Xcase $LANG in
X"") sh='[:#]'; r='#'; rh=$r; awk='#'; mk='#';
X c='\/\*'; h=$c; y=$c; l=$c;
X f='[Cc]'; fh=$f; p='{'; ph=$p;
X ms='\\"'; nr=$ms; mn=$ms; man=$ms;
Xesac
X
X: extract comments
X
Xfor i in $*
Xdo
X case $LANG in
X "") eval B\="\$`expr $i : '^.*\.\([^.]*\)$'`"
X test "$B" || { echo "$0: unknown suffix: $i; assuming c" 1>&2; B=$c; }
X esac
X sed '
X /^'"$B"'++/,/^'"$B"'--/!d
X /^'"$B"'++/d
X /^'"$B"'--/d
X s/[ ]*$//
X /^'"$B"' \([A-Z]\)/{
X s//\1/
X /^NAME/{
X N
X s/^.*\n'"$B"'[ ]*//
X h
X y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
X s/^.*$/.TH & '"$SECT"'\
X.ad\
X.fi\
X.SH NAME/
X p
X g
X s/ [0-9]$//
X a\
X\\-
X p
X d
X }
X /^SUMMARY/d
X /^DESCRIPTION/s//.SH &\
X.ad\
X.fi/
X /^BUGS/s//.SH &\
X.ad\
X.fi/
X /^DIAGNOSTICS/s//.SH &\
X.ad\
X.fi/
X /^[A-Z][A-Z][A-Z][^a-z]*$/s//.SH &\
X.na\
X.nf/
X p
X d
X }
X s/^'"$B"'[ ]*//
X s/^[ ]*$//
X' $i
Xdone
X
Xexit
X
X:++
X: NAME
X: srctoman 1
X: SUMMARY
X: extract manual page from source file comment
X: PACKAGE
X: source file maintentance tools
X: SYNOPSIS
X: srctoman [-|-awk|-c|-f|-mk|-m|-n|-p|-t|-r] [section] file(s)
X: DESCRIPTION
X: Srctoman converts comments in various programming languages to
X: UNIX-style manual pages.
X: The command processes comments in the style of newsource(1);
X: its standard output is suitable for formatting with nroff(1) or
X: troff(1) using the "-man" macro package.
X: Typically, srctoman is integrated with make(1) scripts.
X:
X: Source files are processed in the indicated order; if no
X: files argument the command produces no output.
X:
X: The source file language can be specified through a command-line
X: option, or can be implied by the filename suffix.
X: The expected start-of-comment symbol is shown in the last column.
X:
X: .nf
X option language comment
X
X - shell [:#]
X -awk awk #
X -c c /*
X -f fortran [Cc]
X -mk make #
X -n nroff \\"
X -p pascal {
X -t troff \\"
X -r ratfor #
X -C any language next argument
X: .fi
X:
X: .nf
X suffix language comment
X
X .awk awk #
X .c c /*
X .f fortran [Cc]
X .fh fortran [Cc]
X .h c /*
X .l lex /*
X .man nroff,troff \\"
X .mk make #
X .me nroff,troff \\"
X .ms nroff,troff \\"
X .nr nroff,troff \\"
X .p pascal {
X .ph pascal {
X .r ratfor #
X .rh ratfor #
X .sh shell [:#]
X .y yacc /*
X: .fi
X:
X: The required format of comments is discussed below, where SOC
X: stands for the start-of-comment symbol of the language being used.
X:
X: 1) Start of manual: SOC, followed by `++'.
X:
X: 2) Section heading: SOC, blank, section name in upper case.
X:
X: 3) New paragraph: empty line or line with SOC only.
X:
X: 4) All other text: SOC and subsequent blanks or tabs are removed.
X: Lines that do not start with SOC are left unchanged (useful for
X: inclusion of program text).
X:
X: 5) End of manual: SOC, followed by `--'.
X: An end-of-comment may follow if the source file language requires this.
X:
X: The following manual sections receive a special treatment:
X: NAME and SUMMARY should appear at the beginning and in
X: this order; DESCRIPTION, DIAGNOSTICS and BUGS will be
X: right-margin adjusted.
X: Other sections may be added freely without confusing srctoman.
X: COMMANDS
X: sh(1), sed(1), expr(1)
X: SEE ALSO
X: newsource(1), modsource(1), xman(1)
X: The earlier commands new(1), mod(1), mkman(1) and dssman(1)
X: by Ruud Zwart and Ben Noordzij (Erasmus University, Rotterdam)
X: DIAGNOSTICS
X: The program complains if an unknown language is specified
X: or if the language cannot be deduced from the file suffix.
X: AUTHOR(S)
X: W.Z. Venema
X: Eindhoven University of Technology
X: Department of Mathematics and Computer Science
X: Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
X: CREATION DATE
X: Fri Jan 17 22:59:27 MET 1986
X: LAST MODIFICATION
X: Thu Mar 10 20:08:15 MET 1988
X: VERSION/RELEASE
X: 1.20
X:--
X
X
END_OF_srctoman.sh
if test 4444 -ne `wc -c <srctoman.sh`; then
echo shar: \"srctoman.sh\" unpacked with wrong size!
fi
chmod +x srctoman.sh
# end of overwriting check
fi
if test -f switcher.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"switcher.c\"
else
echo shar: Extracting \"switcher.c\" \(4041 characters\)
sed "s/^X//" >switcher.c <<'END_OF_switcher.c'
X/*++
X/* NAME
X/* switcher 3
X/* SUMMARY
X/* master/slave protocol control switcher
X/* PROJECT
X/* pc-mail
X/* PACKAGE
X/* cico
X/* SYNOPSIS
X/* int switcher(role)
X/* int role;
X/* DESCRIPTION
X/* switcher() takes care of the high-level protocol on top of
X/* the packet protocol.
X/*
X/* The system is in one of two roles: MASTER or SLAVE. In MASTER
X/* mode (initial mode of the caller) a system scans its local
X/* spool directory for work until no more is found, and then
X/* sends a H (hangup) request. The slave will respond with HY
X/* if it has no work, otherwise it will respond with HN and
X/* the two systems switch roles.
X/*
X/* Work can be of the form of S (send) requests or R (receive)
X/* requests. The slave responds with SY (RY) or SN (RN), depending on
X/* whether it is willing to process the request. The recipient
X/* of a message sends a CY or CN message, depending on whether
X/* transmission was successfull.
X/*
X/* Only H(angup) and S(end) requests are implemented here. This is
X/* for security reasons. Thus, the only way to exchange data is
X/* through electronic mail.
X/* FUNCTIONS AND MACROS
X/* isok, talk(), hear(), trap(), scanwork(), sendwork()
X/* rmtwork(), getwork()
X/* DIAGNOSTICS
X/* Various nonzero status codes are returned in case of problems.
X/* AUTHOR(S)
X/* W.Z. Venema
X/* Eindhoven University of Technology
X/* Department of Mathematics and Computer Science
X/* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
X/* CREATION DATE
X/* Fri Mar 27 21:49:16 GMT+1:00 1987
X/* LAST MODIFICATION
X/* Wed Apr 6 00:23:14 MET 1988
X/* VERSION/RELEASE
X/* 1.4
X/*--*/
X
X#include <setjmp.h>
X#include "defs.h"
X#include "work.h"
X#include "params.h"
X#include "comm.h"
X#include "logs.h"
X#include "status.h"
X
X/* switcher - handles master/slave role swicthing until all work is done */
X
Xpublic switcher(role)
Xregister int role;
X{
X int *savetrap = systrap;
X jmp_buf mytrap;
X int status;
X
X if (status = setjmp(systrap = mytrap)) {
X systrap = savetrap; /* get here on fatal errors */
X return(status);
X }
X
X /* switch roles until both ends out of work */
X
X while (role != DONE) {
X switch (role) {
X case MASTER:
X role = master();
X break;
X case SLAVE:
X role = slave();
X break;
X default:
X trap(E_CONFUSED,"INTERNAL ERROR (unexpected role: %d)",role);
X }
X }
X systrap = savetrap; /* get here if no fatal errors */
X return(0);
X}
X
X/* master - process local work; when done, switch roles or finish */
X
Xhidden int master()
X{
X register work *wrk;
X register char *resp;
X
X while (wrk = scanwork()) { /* scan for work */
X log("REQUEST (%s)",wrk->rqst);
X if (wrk->fp == 0) { /* check file exists */
X log("CAN'T READ DATA (%s)",sys_errlist[errno]);
X } else if (isok(wrk->rqst) == NO) { /* check xfer allowed */
X log("PERMISSION (DENIED)");
X } else { /* adapt + send data */
X sendwork(wrk);
X log("REQUESTED (%s)",resp = hear());
X if (strcmp(resp,"CY")) /* check sucessfull */
X trap(E_REJECT,"FAILED"); /* completion */
X chmod(wrk->path,0666); /* delete workfile */
X unlink(wrk->path); /* only if all well */
X }
X }
X
X /* switch roles or finish if slave has no work */
X
X return(isok("H") == YES ? (talk("HY"),DONE) : SLAVE);
X}
X
X/* slave - process remote work; accept H and S requests only */
X
Xhidden int slave()
X{
X register char *cmnd;
X register work *wrk;
X
X for (;;) {
X switch ((cmnd = hear())[0]) {
X case 'S': /* master wants to send */
X log("REQUESTED (%s)",cmnd); /* log the request */
X wrk = rmtwork(cmnd); /* parse the request */
X talk("SY"); /* say ok */
X getwork(wrk); /* receive work */
X talk("CY"); /* we never copy */
X log("COPY (SUCCEEDED)");
X break;
X case 'H': /* master is out of work */
X return(scanwork() ? (talk("HN"),MASTER) : (talk("HY"),DONE));
X default:
X talk(strcons("%cN",cmnd[0])); /* refuse other type of work */
X break;
X }
X }
X}
END_OF_switcher.c
if test 4041 -ne `wc -c <switcher.c`; then
echo shar: \"switcher.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f unalias.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"unalias.c\"
else
echo shar: Extracting \"unalias.c\" \(4581 characters\)
sed "s/^X//" >unalias.c <<'END_OF_unalias.c'
X/*++
X/* NAME
X/* unalias 3
X/* SUMMARY
X/* alias processing
X/* PROJECT
X/* pc-mail
X/* PACKAGE
X/* smail
X/* SYNOPSIS
X/* char **unalias(namevec)
X/* char **namevec;
X/* DESCRIPTION
X/* unalias() takes an array of string pointers and returns a vector
X/* with string pointers to their alias expansions. The resulting
X/* vector is in static memory.
X/*
X/* After alias expansion, all addresses are sorted and duplicate
X/* names are eliminated. The algorithms for alias expansion and
X/* duplicate elimination are case-insensitive.
X/*
X/* unalias() accesses the alias data base through the ascf ASCII
X/* filter.
X/* DIAGNOSTICS
X/* unalias() returns a null pointer in case of memory-allocation problems.
X/*
X/* unalias() terminates prematurely when the alias expansion has
X/* produced BUFSIZ recipients. This provides some defense against
X/* cycles in the alias data base. It is up to the caller to
X/* recognize this condition.
X/* BUGS
X/* The overflow/cycle detection algorithm is inelegant.
X/* FILES
X/* Alias data base in spool directory
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 "defs.h"
X#include "hsearch.h"
X#include "path.h"
X#include "ascf.h"
X
X/* forward declarations */
X
Xhidden int hash_alias();
Xhidden void sort_alias();
Xhidden void uniq_alias();
Xhidden char **find_alias();
X
X/* unalias - replace aliases by their equivalents */
X
Xpublic char **unalias(names)
Xchar **names;
X{
X static int dohash = 1; /* hash table not yet made */
X static char *recp[BUFSIZ+1]; /* the result of alias expansion */
X char **stop = recp+BUFSIZ; /* overflow limit */
X
X if (dohash && (dohash = hash_alias())) /* build the hash table */
X return(0);
X if (stop > find_alias(names,recp,stop)) { /* build vector of addresses */
X sort_alias(recp); /* sort the recp list */
X uniq_alias(recp); /* squeeze out identical addresses */
X }
X return(recp);
X}
X
X/* hash_alias - copy alias data base to hash table */
X
Xhidden int hash_alias()
X{
X register FILE *fp;
X char buf[BUFSIZ];
X
X /* initialize the hash table */
X
X if (hcreate(BUFSIZ) == 0)
X return(-1);
X
X /*
X * Lines in the alias data base are of the form
X *
X * <left-hand part> <right-hand part>
X *
X * where the l.h. part is an alias, and the r.h. part one or more
X * words. Of course, those words can be aliases. The order in which
X * aliases are defined is not important. The alias data base is used
X * only after it has been loaded into memory.
X *
X * Each l.h. part is used as the key for finding the r.h. part in the
X * hash table. The r.h. part is stored as a vector of pointers to strings.
X */
X
X if (fp = ascopen(aliases(),"r")) { /* read through ASCII filter */
X while (fgets(buf,BUFSIZ,fp)) { /* read alias entry */
X register char **cpp;
X ENTRY e;
X if ((cpp = strvec(buf,", \t\r\n")) == 0) /* split alias entry */
X return(-1);
X if ((e.key = *cpp) /* left-hand part exists */
X && (e.data = (char *) (cpp+1)) /* right-hand part exists */
X && (hsearch(e,ENTER) == 0)) /* enter hash table */
X return(-1);
X }
X ascclose(fp);
X }
X return(0);
X}
X
X/* find_alias - recursively expand aliases */
X
Xhidden char **find_alias(from,to,stop)
Xchar **from;
Xregister char **to;
Xregister char **stop;
X{
X register char **cpp;
X register ENTRY *sp;
X
X /* recursively replace aliases, but don't crash in case of cycles */
X
X for (cpp = from; *cpp && (to < stop); cpp++) {
X ENTRY e;
X e.key = *cpp;
X if (sp = hsearch(e,FIND)) {
X to = find_alias((char **)sp->data,to,stop);
X } else {
X *to++ = *cpp;
X }
X }
X *to = 0;
X return(to);
X}
X
X/* Istrcmp - interface between qsort and istrcmp */
X
Xhidden int Istrcmp(p1,p2)
Xchar **p1,**p2;
X{
X return(istrcmp(*p1,*p2));
X}
X
X/* sort_alias - sort the addresses after alias substitutions */
X
Xhidden void sort_alias(to)
Xchar **to;
X{
X register char **cpp;
X int istrcmp();
X
X /* find out length of the list */
X
X for (cpp = to; *cpp; cpp++)
X /* void */ ;
X
X /* sort the list */
X
X qsort((char *)to,cpp-to,sizeof(*to),Istrcmp);
X}
X
X/* uniq_alias - collapse sequences of identical addresses */
X
Xhidden void uniq_alias(to)
Xchar **to;
X{
X register char **in = to;
X register char **out = to;
X
X while (*out = *in) {
X while (*++in && istrcmp(*out,*in) == 0) {
X /* void */ ;
X }
X ++out;
X }
X}
END_OF_unalias.c
if test 4581 -ne `wc -c <unalias.c`; then
echo shar: \"unalias.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 5 \(of 8\).
cp /dev/null ark5isdone
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 at heithe5 | Dept. of Mathematics and Computer Science
surf: tuerc5::wswietse | Eindhoven, The Netherlands.
More information about the Comp.sources.misc
mailing list