home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume10
/
pcmail2
/
part05
< prev
next >
Wrap
Text File
|
1990-01-24
|
65KB
|
2,216 lines
Newsgroups: comp.sources.misc
subject: v10i037: PC-MAIL release 2, 5/11
from: wswietse@lso.win.tue.nl (Wietse Venema)
Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
Posting-number: Volume 10, Issue 37
Submitted-by: wswietse@lso.win.tue.nl (Wietse Venema)
Archive-name: pcmail2/part05
#! /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 11)."
# Contents: main/GNUUCP.ins main/SLAVE.ins main/ascf.c main/gp.h
# main/kio.c main/kpres.c main/ktrans.c main/logs.c main/path.h
# main/reply.c main/spoolfil.c
# Wrapped by wswietse@tuewsa on Mon Jan 22 17:27:17 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f main/GNUUCP.ins -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"main/GNUUCP.ins\"
else
echo shar: Extracting \"main/GNUUCP.ins\" \(4914 characters\)
sed "s/^X//" >main/GNUUCP.ins <<'END_OF_main/GNUUCP.ins'
X@(#) GNUUCP.ins 2.1 90/01/22 13:01:07
X
XThis document describes how to install the PC-mail software in an
Xenvironment that uses GNUUCP as the message transport mechanism. GNUUCP
Xruns under more operating systems than just UNIX and MS-DOS, and offers
Xfar more features than the rather minimal "cico" program for dial-up
Xand file transfer. The programs that interface between GNUUCP and PC-mail
Xhave undergone only little testing.
X
XIn order to use PC-mail in combination with GNUUCP, edit the makefile
Xaccording to the directions given in that file (or execute the commands
Xin the GNUUCP.bat file if you are using MS-DOS and do not have a decent
Xmake program). This disables several features in the user interface
Xprogram that are not needed when GNUUCP takes care of message transport.
XUnder MS-DOS, make sure that the large memory model is selected.
X
XSaying `make' should produce the following programs:
X
X - mail, the menu-driven user interface
X - cmail, a program that checks if there is new mail
X - smail, a program that queues messages for transmission after
X doing alias substitution on mail addresses
X - nmail, extracts "From" and "Subject" info from new mail
X - gmail, searches the PC-mail messade data base for unsent mail,
X and gives it to GNUUCP for delivery. This program should
X be invoked upon exit from the "mail" program (see the
X description of the MAILCMD enverionment variable lateron).
X - lmail, installs mail received via GNUUCP into the PC-mail data base
X Since this program is to invoked by the GNUUCP "rmail" program,
X instead of the name "lmail" the program will probably have
X to be given a different name; this depends on how the GNUUCP
X "rmail" is configured.
X
XThe programs access a common data base in the form of a spool directory
Xwith a setup file and message files. Optionally there may be an alias
Xfile, and header and trailer files to generate template messages. There
Xshould be no other files in the spool directory, to avoid confusion.
XThe spool directory should be created by hand; the PC-mail programs will
Xnot do that.
X
XYou will have to set some environment variables before running the mail
Xprograms.
X
X - MAILDIR, the location of your mail data base directory
X - EDITOR, the name of your favourite editor program
X - PATH, in order locate the PC-mail executables, and your editor
X
XIt is advised to use absolute path names that include the drive name.
XThe editor command may be an MS-DOS batch file; in that case you should
Xinclude the '.bat' suffix in the command name.
X
XThe following two environment variables are optional.
X
X - MAILPRN, the name of a file, if printer output should not go to
X the default printer.
X - MAILCMD, a command that is executed on exit from the mail
X program. If this is an MS-DOS batch file you should
X include the `.bat' suffix in the command name.
X
XAt our site, these two variables are used to collect printer output in
Xone file, and to send it to a networked printer upon exit from the
Xprogram. The MAILCMD feature can also be used to invoke the gmail
Xprogram described above.
X
XMake sure that the limit on the number of open files is large enough (20
Xor so). On MS-DOS, this is handled by a line with `files=20' in the
XCONFIG.SYS file.
X
XOn MS-DOS, the mail user interface requires the ANSI.SYS driver. The
XCONFIG.SYS file should specify a line with "device=ansi.sys".
X
XALIAS DATABASE
X
XThe user can define aliases for (groups of) mail addresses. The alias
Xdata base is a text file with on each line:
X
X alias replacement_part
X
XThe alias should be a single word; words are separated by blanks, tabs
Xor commas. The replacement part may be one or more words. Whenever the
Xsmail (mail spooler) program recognizes an alias, it is replaced by the
X`replacement part'. Aliases may be defined in terms of other aliases;
Xthe order in which they appear in the alias data base is not important
X(except when an alias is defined more than once; the program remembers
Xonly the last definition of an alias). The alias expansion software is
Xsmart enough to detect infinite loops and to eliminate multiple
Xoccurrances of the same recipient. Alias substitution is not case
Xsensitive.
X
XBATCH-MODE OPERATION
X
XThe cmail program can be run from a batch file (say, each time the PC is
Xturned on), to report if there is new mail. On multi-tasking machines,
Xyou may want to auto-execute the cmail command when exiting from the
Xinteractive mail shell (using the MAILCMD environment variable described
Xabove).
X
XTEMPLATE FILES
X
XThe user can provide message templates with standard header and trailer
Xlines. If the file "header" is present in the mail directory, its
Xcontents will be included at the beginning of every mail message created
Xby the user. Similarly, the contents of a file "trailer" will be
Xincluded at the end of mail messages. The "header" and "trailer" files
Xshould be ordinary text files.
END_OF_main/GNUUCP.ins
if test 4914 -ne `wc -c <main/GNUUCP.ins`; then
echo shar: \"main/GNUUCP.ins\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f main/SLAVE.ins -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"main/SLAVE.ins\"
else
echo shar: Extracting \"main/SLAVE.ins\" \(5277 characters\)
sed "s/^X//" >main/SLAVE.ins <<'END_OF_main/SLAVE.ins'
X@(#) SLAVE.ins 2.1 90/01/22 13:01:12
X
XThis document describes how to install an MS-DOS pc-mail user in an
Xenvironment where the user's mail directories are mounted from a UNIX
Xfile server, and where PC/NFS is used for file access. It is assumed
Xthat the UNIX host uses sendmail for message routing. You will have to
Xadapt the examples if you are using different mechanisms for remote file
Xaccess or message routing.
X
XTHE UNIX SIDE
X
XThe installation of daemon programs on the file server is documented
Xwith the source of the pc-mail and pc-maild programs (these are provided
Xin the `daemon' subdirectory. The following text assumes that the
Xdaemon programs have already been installed.
X
XAdd the user to the password data base. In the pc-mail spool area on
Xthe server, create a subdirectory for the pc-mail user. The directory
Xmust be owned by that user; for reasons of privacy, mode 0700 is
Xrecommended. In the following example, replace username by the actual
Xlogin name of the user, and the name of the spool area by its actual
Xname.
X
X # mkdir /var/spool/pc-mail/username
X # chown username /var/spool/pc-mail/username
X # chmod 700 /var/spool/pc-mail/username
X
XThe next step is to inform the UNIX mailer of how to deliver mail for
Xthis user. This is described in the documentation of the pc-mail
Xand pc-maild programs.
X
XAfter the list of pc-mail users has been updated, kill the sendmail
Xdaemon and restart it.
X
XNote that the sendmail program ON THE NFS SERVER will not read the
Xuser's .forward file. The file will still be useful, however, if the
Xuser's home directory is exported to OTHER hosts running sendmail. In
Xthat case you will want to create a .forward file in the user's home
Xdirectory containing
X
X username@fully-qualified-hostname-of-the-mail-server
X
XThe same effect can be achieved with an alias in a network-wide alias
Xdata base.
X
XTHE PC SIDE
X
XCopy the appropriate makefile.whatever file to makefile and edit it.
XMake sure that the DAEMON macro is defined, and that the large memory
Xmodel is selected. You may also use the SLAVE.bat file if no decent
Xmake utility is available.
X
XTyping `make' should produce the following programs:
X
X mail, the user interface program
X cmail, checks for new mail
X nmail, extracts sender and subject from new mail
X smail, performs alias expansion and queues outgoing messages
X
XCreate a dedicated directory on the file server to install the mail
Xbinaries.
X
XOn the PC, adjust the AUTOEXEC.BAT, NETWORK.BAT or DRIVES.BAT files so
Xthat the following commands are executed upon startup (replace `server'
Xby the name of the NFS server host, and replace `username' by the login
Xname of the actual user):
X
X net name username *
X net use m: \\server\var\spool\pc-mail\username
X set MAILDIR=m:\
X
XThe trailing \ in the last command is needed, or the mail program will
Xcomplain that it "cannot access some essential data files".
X
XOther environment variables that need to be set are:
X
X PATH, should include the location of the pc-mail binaries
X EDITOR, the editor command to be used; if this is a batch
X file, the `.bat' suffix should be included.
X
XIt is advisable to specify absolute path names, including drive names.
X
XOptional environment variables are:
X
X MAILPRN, destination of printed output
X MAILCMD, command to be executed upon exit from the mail program.
X At our site, MAILPRN is the name of a file, and MAILCMD is
X the command that sends that file to a postscript printer. If
X this is a batch file, the `.bat' suffix should be included.
X
XReboot the pc.
X
XTest the mail programs by creating a small mail message addressed to
Xyourself. Since the message will automatically be picked up by the
Xpc-maild daemon program on the server, the message may arrive before you
Xhad a chance to type a DIR command!
X
XALIAS DATABASE
X
XThe user can define aliases for (groups of) mail addresses. The alias
Xdata base is a text file with on each line:
X
X alias replacement_part
X
XThe alias should be a single word; words are separated by blanks, tabs
Xor commas. The replacement part may be one or more words. Whenever the
Xsmail (mail spooler) program recognizes an alias, it is replaced by the
X`replacement part'. Aliases may be defined in terms of other aliases;
Xthe order in which they appear in the alias data base is not important
X(except when an alias is defined more than once; the program remembers
Xonly the last definition of an alias). The alias expansion software is
Xsmart enough to detect infinite loops and to suppress multiple
Xoccurrances of the same recipient. Alias substitution is not case
Xsensitive.
X
XBATCH-MODE OPERATION
X
XThe cmail program can be run from a batch file (say, each time the PC is
Xturned on), to report if there is new mail. Also, you may want to
Xauto-execute the cmail command when exiting from the interactive mail
Xshell (using the MAILCMD environment variable described above).
X
XTEMPLATE FILES
X
XThe user can provide message templates with standard header and trailer
Xlines. If the file "header" is present in the mail directory, its
Xcontents will be included at the beginning of every mail message created
Xby the user. Similarly, the contents of a file "trailer" will be
Xincluded at the end of mail messages. The "header" and "trailer" files
Xshould be ordinary text files.
END_OF_main/SLAVE.ins
if test 5277 -ne `wc -c <main/SLAVE.ins`; then
echo shar: \"main/SLAVE.ins\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f main/ascf.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"main/ascf.c\"
else
echo shar: Extracting \"main/ascf.c\" \(5357 characters\)
sed "s/^X//" >main/ascf.c <<'END_OF_main/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/* #include <stdio.h>
X/* #include "ascf.h"
X/*
X/* FILE *ascopen(name,mode)
X/* char *name;
X/* char *mode;
X/*
X/* int ascget(fp)
X/* FILE *fp;
X/*
X/* ascpbk(c,fp)
X/* int c;
X/* FILE *fp;
X/*
X/* char *ascgets(buf,buflen,fp);
X/* char *buf;
X/* int buflen;
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/* 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 and backspace,
X/* control characters are filtered out. A newline
X/* character is appended to the last line of a file if that file
X/* does not terminate on a newline character.
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. A "feature" of the ascopen()
X/* function is that it interprets a file name "-" as standard
X/* input (and ignores the mode argument in that case).
X/*
X/* ascpbk() pushes back the last character read with ascget().
X/*
X/* ascgets() reads one string and strips trailing newline or carriage
X/* return characters. A null pointer is returned if no string could
X/* be read, otherwise ascgets() returns a pointer to the buffer.
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 well with wordstar or clean ascii files only.
X/*
X/* Only "r" modes are supported.
X/*
X/* There is no way to seek() a filtered stream.
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/* 90/01/22 13:01:14
X/* VERSION/RELEASE
X/* 2.1
X/*--*/
X
X#include <stdio.h>
X#include <ctype.h>
X
X#include "defs.h"
X#include "ascf.h"
X
X/* some systems do not define _NFILE in stdio.h; not that they should, but.. */
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 stdio streams"
X# endif
X#endif
X
X#define CTL(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 (*mode != 'r') /* Cannot do filtered writes */
X return(0);
X
X if (fp = (strcmp(file, "-") ? fopen(file,mode) : stdin)) {
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 (void) 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 - the actual filter, fill one 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; /* initialize write pointer */
X register int c; /* single-character input buffer */
X int d; /* look-ahead character */
X
X while (cp < ap->buf+BUFSIZ && (c = getc(fp)) != EOF) {
X if ((c &= 0177) == ' ' || isprint(c) || c == '\t' || c == '\b') {
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 == CTL('_')) {
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 ap->nlf = cp[-1]; /* remember last character */
X return(ascget(fp)); /* and return first character */
X } else if (ap->nlf != '\n') { /* make sure file ends with \n */
X return(ap->nlf = '\n'); /* append newline */
X } else { /* now we're really done */
X return(EOF); /* that's it. */
X }
X}
X
X/* ascgets - read string, strip crlf */
X
Xpublic char *ascgets(buf, buflen, fp)
Xchar *buf;
Xint buflen;
XFILE *fp;
X{
X register int c;
X register char *cp = buf;
X register char *ce = buf + buflen - 1;
X
X while ((c = ascget(fp)) != EOF) {
X if (c == '\n') { /* suppress crlf */
X break;
X } else if (cp < ce) { /* will fit */
X *cp++ = c;
X } else { /* push back */
X ascpbk(c, fp);
X break;
X }
X }
X *cp = 0;
X return ((c == EOF && cp == buf) ? 0 : buf);
X}
END_OF_main/ascf.c
if test 5357 -ne `wc -c <main/ascf.c`; then
echo shar: \"main/ascf.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f main/gp.h -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"main/gp.h\"
else
echo shar: Extracting \"main/gp.h\" \(5614 characters\)
sed "s/^X//" >main/gp.h <<'END_OF_main/gp.h'
X/*++
X/* NAME
X/* gp 5
X/* SUMMARY
X/* g-protocol internal definitions
X/* PROJECT
X/* pc-mail
X/* PACKAGE
X/* cico
X/* SYNOPSIS
X/* #include "gp.h"
X/* DESCRIPTION
X/* .nf
X
X /* include-once file */
X
X#ifndef GP
X#define GP
X
X#include <stdio.h> /* needed for stderr */
X
X#define MAXTRY 10 /* max nr of retries */
X#define CTRL(x) ((x)^0100) /* for ascii control characters */
X#define MIN(x,y) ((x) < (y) ? (x) : (y))
X#define MAX(x,y) ((x) > (y) ? (x) : (y))
X
X#define ALARM 10 /* time-out interval */
X#define MAGIC 0xAAAA /* checksum magic number */
X#define KCTRL 9 /* control packet */
X
X#define FAIL (-1) /* corrupted packet */
X#define TIME (-2) /* timed out */
X
X /*
X * The protocol is defined in terms of message transmissions of 8-bit
X * bytes. Each message includes one control byte plus a data segment
X * of zero or more information bytes. (...)
X * The control byte is partitioned into three fields as depicted below.
X * bit 7 6 5 4 3 2 1 0
X * t t x x x y y y
X * The t bits indicate a packet type and determine the interpretation
X * to be placed on the xxx and yyy the fields. The various interpretations
X * are as follows:
X * tt interpretation
X * 00 control packet
X * 10 data packet
X * 11 short data packet
X * 01 alternate channel
X * A data segment accompanies all non-control packets. (...) Type 01 packets
X * are never used by UUCP (...)
X */
X
X#define TYPE(x) ((x)&0300) /* extract message field */
X
X#define CONTROL 0000 /* control message */
X#define DATA 0200 /* data, fixed size */
X#define SHORT 0300 /* short (variable) length data */
X#define ALTCH 0100 /* alternate channel (unused) */
X
X /*
X * The sequence number of a non-control packet is given by the xxx field.
X * Control packets are not sequenced. The newest sequence number,
X * excluding duplicate transmissions, accepted by a receiver is placed in
X * the yyy field of non-control packets sent to the `other' receiver.
X */
X
X#define TVAL(x) (((x)&0377)>>6) /* extract message type */
X#define MVAL(x) (((x)&070)>>3) /* extract control message */
X#define SVAL(x) (((x)&070)>>3) /* extract S(equence) value */
X#define RVAL(x) ((x)&07) /* extract R(received) value */
X#define IVAL(x) ((x)&07) /* extract init value */
X#define SFLD(x) (((x)&07)<<3) /* create S(equence) field */
X#define RFLD(x) ((x)&07) /* create R(received) field */
X#define IFLD(x) ((x)&07) /* create init field */
X
X /*
X * There are no data bytes associated with a control packet, the xxx field
X * is interpreted as a control message, and the yyy field is a value
X * accompanying the control message. The control messages are listed
X * below in decreasing priority. That is, if several control messags
X * are to be sent, the lower-numbered ones are sent first.
X * xxx name yyy
X * 1 CLOSE n/a
X * 2 RJ last correctly received sequence number
X * 3 SRJ sequence number to retransmit
X * 4 RR last correctly received sequence number
X * 5 INITC window size
X * 6 INITB data segment size
X * 7 INITA window size
X */
X
X#define MESG(x) ((x)&070) /* extract control message field */
X
X#define CLOSE 0010 /* close message */
X#define RJ 0020 /* reject message */
X#define SRJ 0030 /* selective-reject message (unused) */
X#define RR 0040 /* received ok message */
X#define INITC 0050 /* initialization message */
X#define INITB 0060 /* initialization message */
X#define INITA 0070 /* initialization message */
X
X /* declarations for tiny systems without tty driver, timer support etc. */
X
X#ifndef unix
X
X#define read xread
X#define write xwrite
X#define alarm(x) /* nothing */
X#define signal(x,y) /* nothing */
X#define DEBUG(x,y,z) if (dflag >= x) printf(y,z)
X
Xextern int dflag;
X
X#else
X
X#define DEBUG(l,f,s) if (Debug >= l) fprintf(stderr,f,s)
X
Xextern int Debug;
X
X#endif
X
X /*
X * We use one data structre for communication between various levels
X * of the g-protocol implementation. Fields in parentheses are relevant
X * only when a packet holds data.
X * field meaning set by
X * c message type gwrite(), grpack()
X * (k data segment length galloc(), grpack())
X * (chk 16-bit checksum packet i/o functions)
X * (len max. data segment length galloc(), gwrite(), grpack())
X * (data start of "len" bytes this field is fixed)
X * (segl nbr of data bytes left gread())
X * (segp start of "segl" bytes gread())
X */
X
X /* structure for communication between various program layers */
X
Xtypedef struct {
X char k; /* message segment size */
X char c; /* message type */
X int chk; /* data checksum */
X short segl; /* nr of data bytes left */
X char *segp; /* start of the "segl" bytes */
X short len; /* maximum data segment size */
X char data[1]; /* actually a lot of characters */
X} Packet;
X
X /* functions that manipulate packets */
X
Xextern Packet *grproto(); /* take packet from input queue */
Xextern void gfree(); /* release input packet */
Xextern Packet *galloc(); /* allocate output packet */
Xextern void gwproto(); /* place packet in output queue */
Xextern void gfail(); /* panic button */
Xextern void gsctrl(); /* send one control packet */
Xextern void gsdata(); /* send one data packet */
Xextern int grpack(); /* receive one packet */
X
Xextern int seglen[]; /* data segment size table */
X
X /* standard unix library */
X
Xextern char *malloc();
X
X#endif /* GP */
X/* AUTHOR(S)
X/* W.Z. Venema
X/* Eindhoven University of Technology
X/* Department of Mathematics and Computer Science
X/* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
X/* CREATION DATE
X/* Sun Apr 19 12:41:37 GMT+1:00 1987
X/* LAST MODIFICATION
X/* 90/01/22 13:01:41
X/* VERSION/RELEASE
X/* 2.1
X/*--*/
END_OF_main/gp.h
if test 5614 -ne `wc -c <main/gp.h`; then
echo shar: \"main/gp.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f main/kio.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"main/kio.c\"
else
echo shar: Extracting \"main/kio.c\" \(4773 characters\)
sed "s/^X//" >main/kio.c <<'END_OF_main/kio.c'
X/*++
X/* NAME
X/* kio 3
X/* SUMMARY
X/* interface between uucico and k-protocol driver
X/* PACKAGE
X/* uucp on the TUEnet
X/* SYNOPSIS
X/* kturnon()
X/*
X/* kwrmsg(type,str,fn)
X/* char type, *str;
X/* int fn;
X/*
X/* krdmsg(str,fn)
X/* char *str;
X/* int fn;
X/*
X/* krddata(fn,fp)
X/* int fn;
X/* FILE *fp;
X/*
X/* kwrdata(fp,fn)
X/* FILE *fp;
X/* int fn;
X/*
X/* kturnoff()
X/* IMPLICIT INPUTS
X/* Ifn, Ofn, file descriptors
X/* Debug, debugging level
X/* DESCRIPTION
X/* The k protocol has been developed for the Sytek Localnet local area
X/* network at the Eindhoven University of Technology (THE).
X/* Main features of this network are:
X/*
X/* .IP o
X/* Network partners may talk at different baudrates. This implies
X/* that the network does some buffering and that it needs flow control.
X/* .IP o
X/* The network is normally not transparent for some control
X/* characters (XON,XOFF and locally-defined others), independent
X/* of the value of the eigth bit.
X/* .IP o
X/* Some network stations are connected to telephone modems.
X/*
X/* For these reasons, the k protocol must (i) rely on XON/XOFF flow
X/* control, (ii) be suitable for 7-bit data paths, (iii) avoid
X/* sending of control characters and (iv) provide reliable operation
X/* over dial-in and dial-out telephone lines.
X/*
X/* Data are sent as checksummed 512-byte packets, terminated by an
X/* ASCII CR. Except for packet headers (^P), the k protocol only uses
X/* ASCII codes 040 through 0137. Three data bytes are expanded to four
X/* bytes upon transmission.
X/*
X/* The functions in kio.c form the interface between the uucico
X/* controlling functions, and the k-protocol packet driver.
X/*
X/* kturnon() sets the terminal line characteristics (XON/XOFF). Always
X/* returns zero status.
X/*
X/* krdmsg(), kwrmsg() exchange null-terminated strings.
X/* Exit status zero, or FAIL.
X/*
X/* krddata(), kwrdata() perform file i/o, and accounting. Exit status
X/* zero or FAIL.
X/*
X/* kturnoff() sends a protocol abort sequence. Always returns zero
X/* status.
X/* FUNCTIONS AND MACROS
X/* kread, kread, kwrite, kclose, k-protocol presentation layer
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 10:13:34 MET 1986
X/* LAST MODIFICATION
X/* 90/01/22 13:01:54
X/* VERSION/RELEASE
X/* 2.1
X/*--*/
X
X#include "uucp.h"
X
X#define BUFLEN BUFSIZ
X
Xkturnon()
X{
X kopen(Ifn);
X return 0;
X}
X
X
Xkturnoff()
X{
X kclose(Ofn);
X return 0;
X}
X
X
Xkwrmsg(type,str,fn)
Xchar type,*str;
Xint fn;
X{
X char bufr[BUFSIZ],*s;
X
X bufr[0] = type;
X s = &bufr[1];
X while (*str)
X *s++ = *str++;
X *s = '\0';
X if (*(--s) == '\n')
X *s = '\0';
X DEBUG(6," kwrmsg: \"%s\"\n",bufr);
X
X return (kwrite(fn,bufr,strlen(bufr)+1) > 0 ? 0 : FAIL);
X}
X
X
Xkrdmsg(str,fn)
Xchar *str;
Xint fn;
X{
X int len;
X
X for (;;) {
X if ((len = kread(fn,str,BUFSIZ)) == 0) {
X continue;
X } else if (len > 0) {
X str[len] = 0;
X DEBUG(6," krdmsg: \"%s\"\n",str);
X str += len;
X if (str[-1] == '\0')
X return 0;
X } else {
X return FAIL;
X }
X }
X}
X
X
Xkwrdata(fp1,fn)
XFILE *fp1;
X{
X char bufr[BUFLEN];
X int len;
X int ret;
X time_t t1,t2;
X long bytes;
X char text[BUFSIZ];
X
X ret = FAIL;
X bytes = 0L;
X time(&t1);
X while ((len = fread(bufr,sizeof (char),BUFLEN,fp1)) > 0) {
X bytes += len;
X if (kwrblk(bufr,len,fn) != len)
X goto acct;
X if (len != BUFLEN)
X break;
X }
X ret = kwrblk(bufr,0,fn);
Xacct:
X time(&t2);
X sprintf(text,ret == 0 ?
X "sent data %ld bytes %ld secs" :
X "send failed after %ld bytes",
X bytes,t2 - t1);
X DEBUG(1,"%s\n",text);
X syslog(text);
X sysacct(bytes,t2 - t1);
X if (ret)
X sysaccf(NULL); /* force accounting */
X return ret;
X}
X
X
Xkrddata(fn,fp2)
XFILE *fp2;
X{
X int len,ret;
X char bufr[BUFLEN];
X time_t t1,t2;
X long bytes;
X char text[BUFSIZ];
X
X ret = FAIL;
X bytes = 0L;
X time(&t1);
X for (;;) {
X len = krdblk(bufr,BUFLEN,fn);
X if (len < 0)
X goto acct;
X bytes += len;
X if (fwrite(bufr,sizeof (char),len,fp2) != len)
X goto acct;
X if (len < BUFLEN)
X break;
X }
X ret = 0;
Xacct:
X time(&t2);
X sprintf(text,ret == 0 ?
X "received data %ld bytes %ld secs" :
X "receive failed after %ld bytes",
X bytes,t2 - t1);
X DEBUG(1,"%s\n",text);
X syslog(text);
X sysacct(bytes,t2 - t1);
X if (ret)
X sysaccf(NULL); /* force accounting */
X return ret;
X}
X
X
Xkrdblk(blk,len, fn)
Xchar *blk;
Xint len,fn;
X{
X int i,ret;
X
X for (i = 0; i < len; i += ret) {
X if ((ret = kread(fn,blk,len-i)) == 0) {
X break;
X } else if (ret > 0) {
X blk += ret;
X } else {
X return FAIL;
X }
X }
X return i;
X}
X
X
Xkwrblk(blk,len,fn)
Xchar *blk;
Xint len,fn;
X{
X return kwrite(fn,blk,len);
X}
END_OF_main/kio.c
if test 4773 -ne `wc -c <main/kio.c`; then
echo shar: \"main/kio.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f main/kpres.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"main/kpres.c\"
else
echo shar: Extracting \"main/kpres.c\" \(4940 characters\)
sed "s/^X//" >main/kpres.c <<'END_OF_main/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/* 90/01/22 13:01:57
X/* VERSION/RELEASE
X/* 2.1
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_main/kpres.c
if test 4940 -ne `wc -c <main/kpres.c`; then
echo shar: \"main/kpres.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f main/ktrans.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"main/ktrans.c\"
else
echo shar: Extracting \"main/ktrans.c\" \(4972 characters\)
sed "s/^X//" >main/ktrans.c <<'END_OF_main/ktrans.c'
X/*++
X/* NAME
X/* ktrans 3
X/* SUMMARY
X/* k-protocol strategy routines
X/* PACKAGE
X/* uucp across the TUEnet
X/* SYNOPSIS
X/* #include "kp.h"
X/*
X/* krproto(fd,data,size)
X/* int fd, *size;
X/* char data[MAXPACKSIZ];
X/*
X/* kwproto(fd,data,size)
X/* int fd, size;
X/* char data[MAXPACKSIZ];
X/*
X/* kclsproto(fd)
X/* int fd;
X/* DESCRIPTION
X/* The functions in this file take care of handshake and error
X/* detection/recovery. The read/write functions return through an
X/* external function kfail() in case of fatal errors, or protocol
X/* termination by the network partner.
X/*
X/* The following packet types are used:
X/*
X/* .nf
X/* .in +5
X/* D packets contain data.
X/* Y packets are sent when a correct data packet was received.
X/* N packets are sent when incorrect data was received.
X/* A packets are sent to shut down the k protocol.
X/* .fi
X/*
X/* Krproto() sends the data and either returns normally, or through
X/* kfail().
X/*
X/* Kwproto() returns the received data or returns through kfail().
X/*
X/* Kclsproto() sends the protocol termination sequence to the other
X/* side, either to signal the end of transfers, or to confirm
X/* reception of an end-of-protocol sequence.
X/*
X/* The strategy for sending data is as follows:
X/*
X/* Send packet.
X/* If (ACK for last packet) or (NAK for next packet) received, terminate.
X/* If (NAK for last packet) or no response received, retransmit.
X/* If data received with previous packet nr, ignore and wait for NAK.
X/* If data received with next packet nr, NAK that data and terminate.
X/* Otherwise (bad packet number, unexpected packet type) abort.
X/*
X/* The strategy for receiving data is complementary:
X/*
X/* Wait for packet
X/* If expected packet received, ACK it and terminate.
X/* If previous data packet received, ACK it and wait for next packet.
X/* If bad packet received, send NAK for expected packet.
X/* If nothing received, wait for another packet.
X/* Otherwise (bad packet number, unexpected packet type) abort.
X/* FUNCTIONS AND MACROS
X/* kspack, krpack, kfail
X/* AUTHOR(S)
X/* Wietse Venema
X/* Eindhoven University of Technology
X/* Department of Mathematics and Computer Science
X/* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
X/* CREATION DATE
X/* Mon Feb 3 13:12:08 MET 1986
X/* LAST MODIFICATION
X/* 90/01/22 13:01:59
X/* VERSION/RELEASE
X/* 2.1
X/*--*/
X
X#include "kp.h"
X
Xstatic char recpkt[MAXPACKSIZ]; /* receive packet buffer */
Xstatic int n = 0; /* packet number */
X
Xkwproto( fd, packet, size)
Xint fd;
Xchar *packet;
Xint size;
X{
X int num, numtry; /* Packet number, tries */
X int len;
X
X kspack(fd, 'D',n,size,packet); /* Send a D packet */
X
X for (numtry = 0; numtry < MAXTRY; numtry++) {
X switch(krpack(fd,&num,&len,recpkt)) /* What was the reply? */
X {
X case 'D': /* DATA */
X if ((num+1)%64 == n) { /* Previous packet ? */
X numtry = 0; /* Reset counter */
X break; /* Don't ack it; read again */
X } else if (num != (n+1)%64) /* Fatal error, unless it */
X kfail(); /* carries next packet number */
X kspack(fd,'N',num,0,NULLP); /* Can't use data now */
X
X case 'N': /* NAK */
X if (n == num) { /* Send another one, */
X kspack(fd, 'D',n,size,packet);
X break;
X }
X num = (--num<0 ? 63:num); /* unless NAK for next packet */
X
X case 'Y': /* ACK */
X if (n != num) kfail(); /* If wrong ACK, fail */
X n = (n+1)%64; /* Bump packet count */
X return;
X
X case TIME: /* No response */
X case FAIL: /* Bad packet */
X kspack(fd, 'D',n,size,packet);
X break; /* Send data packet again */
X
X default:
X kfail(); /* Something else, abort */
X }
X }
X kfail(); /* Too may retries, abort */
X}
X
Xkrproto( fd, packet, size)
Xint fd;
Xchar *packet;
Xint *size;
X{
X int num, numtry; /* Packet number, tries */
X
X for (numtry = 0; numtry < MAXTRY; numtry++)
X {
X switch (krpack(fd,&num,size,packet)) /* Get packet */
X {
X case 'D':
X if (num == n) { /* Right packet? */
X kspack(fd,'Y',n,0,NULLP); /* Acknowledge the packet */
X n = (n+1)%64; /* Bump packet number, mod 64 */
X return;
X } else if (num == ((n==0) ? 63:n-1)) { /* Previous packet? */
X kspack(fd,'Y',num,0,NULLP); /* Re-ack previous packet */
X numtry = 0; /* Reset counter */
X break; /* Read another packet */
X } else
X kfail(); /* Sorry, wrong number */
X
X case TIME: /* No packet */
X break; /* Don't NAK */
X
X case FAIL: /* Bad packet */
X kspack(fd,'N',n,0,NULLP); /* Return a NAK */
X break; /* Read another packet */
X
X default:
X kfail(); /* Something else, abort */
X }
X }
X kfail(); /* Too may retries, abort */
X}
X
Xkclsproto( fd)
Xint fd;
X{
X kspack( fd, 'A', 0, 0, NULLP); /* Send an 'A' packet */
X kspack( fd, 'A', 0, 0, NULLP); /* and another two since */
X kspack( fd, 'A', 0, 0, NULLP); /* we won't get ACKs */
X return 0;
X}
END_OF_main/ktrans.c
if test 4972 -ne `wc -c <main/ktrans.c`; then
echo shar: \"main/ktrans.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f main/logs.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"main/logs.c\"
else
echo shar: Extracting \"main/logs.c\" \(5603 characters\)
sed "s/^X//" >main/logs.c <<'END_OF_main/logs.c'
X/*++
X/* NAME
X/* logs 3
X/* SUMMARY
X/* exception handling, error logging, status reports, debugging
X/* PROJECT
X/* pc-mail
X/* PACKAGE
X/* cico
X/* SYNOPSIS
X/* int 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/* 90/01/22 13:02:01
X/* VERSION/RELEASE
X/* 2.1
X/*--*/
X
X#include <stdio.h>
X#include <setjmp.h>
X#include <ctype.h>
X#include <varargs.h>
X#include <time.h>
X
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
X * function */
X
X/* now - write current time */
X
Xhidden void now(fp)
XFILE *fp;
X{
X struct tm *localtime();
X char *asctime();
X long time();
X long t;
X
X t = time((long *) 0);
X fprintf(fp, "%.15s ", asctime(localtime(&t)) + 4);
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 /*
X * As long as we have to use old C, use two versions of variadic functions,
X * one for real use, and one for checking with lint.
X */
X
X#ifndef lint
X
X/* dbg - write debugging info to the debugging output */
X
Xpublic int dbg(va_alist)
Xva_dcl
X{
X va_list s;
X register char *fmt;
X
X va_start(s);
X fmt = va_arg(s, char *);
X dprintf(dbgout, fmt, s);
X va_end(s);
X}
X
X/* log - write status info to the log file */
X
Xpublic void log(va_alist)
Xva_dcl
X{
X va_list s;
X register char *fmt;
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 now(logfp);
X va_start(s);
X fmt = va_arg(s, char *);
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 fmt = va_arg(s, char *);
X dprintf(dbgout, fmt, s);
X putc('\n', dbgout);
X va_end(s);
X }
X}
X
X/* trap - exception handler */
X
Xpublic void trap(va_alist)
Xva_dcl
X{
X va_list s;
X int code;
X char *fmt;
X
X /* write exception record to log file */
X
X now(logfp);
X va_start(s);
X code = va_arg(s, int);
X fmt = va_arg(s, char *);
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 code = va_arg(s, int);
X fmt = va_arg(s, char *);
X dprintf(dbgout, fmt, s);
X putc('\n', dbgout);
X va_end(s);
X }
X longjmp(systrap, code);
X}
X
X#else
X
X/* VARARGS1 */
X
Xpublic int dbg(fmt)
Xchar *fmt;
X{
X}
X
X/* VARARGS2 */
X
Xpublic void trap(err, fmt)
Xint err;
Xchar *fmt;
X{
X}
X
X/* VARARGS1 */
X
Xpublic void log(fmt)
Xchar *fmt;
X{
X}
X
X#endif
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
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 (void) fflush(fp);
X}
END_OF_main/logs.c
if test 5603 -ne `wc -c <main/logs.c`; then
echo shar: \"main/logs.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f main/path.h -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"main/path.h\"
else
echo shar: Extracting \"main/path.h\" \(5231 characters\)
sed "s/^X//" >main/path.h <<'END_OF_main/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 PATHSEP "/" /* path-element separator */
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 PATHSEP "\\" /* path-element separator */
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 print 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#if (!defined(unix)&& !defined(MSDOS))
X"Specify here how things should be handled with your compiler"
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 NMAIL "nmail" /* extract originator address */
X
X /*
X * The spool directory is used for storage of all files manipulated by the
X * mail programs. Message files should always have a meta file with
X * 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. The
X * following definitions are for the <letter> part of spool files.
X */
X
X#define LOGFILE "LOGFILE" /* transaction logs */
X#define HEADER "header" /* template message header */
X#define TRAILER "trailer" /* template message trailer */
X
X#define NEW_MESG 'n' /* received message */
X#define NEW_META 'h' /* originator of new mail */
X
X#define OLD_MESG 'n' /* received message */
X#define OLD_META 'o' /* originator of old mail */
X
X#define OUT_MESG 'd' /* message ready to be sent */
X#define OUT_META 'x' /* its destination */
X
X#define SENT_MESG 'q' /* delivered message */
X#define SENT_META 'r' /* its destination */
X
X#define WORK_MESG 'e' /* message being worked on */
X#define WORK_META 'c' /* its description */
X
X#define SETUP 's' /* system parameter file */
X
X#define ALIAS 'a' /* alias data base */
X
X#define SPOOLFMT "%c%05u" /* spool-file name format */
X#define NAMELEN 6 /* length of spool file name */
X
Xunsigned newseqno(); /* generate sequence number */
Xunsigned seqno(); /* extract seq. nr. from name */
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,OUT_MESG,OUT_META)
X#define workon(fname,meta) spoolfil(fname,meta,WORK_MESG,WORK_META)
X
X#define parm_file() fspool(strcons(SPOOLFMT,SETUP,0))
X#define aliases() fspool(strcons(SPOOLFMT,ALIAS,0))
X#define logfile() fspool(LOGFILE)
X#define header_file() fspool(HEADER)
X#define trailer_file() fspool(TRAILER)
X
X#define meta_file(type,id) fspool(strcons(SPOOLFMT,type,id))
X#define mesg_file(type,id) fspool(strcons(SPOOLFMT,type,id))
X
X#define work_meta(id) fspool(strcons(SPOOLFMT,WORK_META,id))
X#define work_mesg(id) fspool(strcons(SPOOLFMT,WORK_MESG,id))
X
X#define old_mesg(id) fspool(strcons(SPOOLFMT,OLD_MESG,id))
X#define old_meta(id) fspool(strcons(SPOOLFMT,OLD_META,id))
X
X#define new_mesg(id) fspool(strcons(SPOOLFMT,NEW_MESG,id))
X#define new_meta(id) fspool(strcons(SPOOLFMT,NEW_META,id))
X
X#define out_mesg(id) fspool(strcons(SPOOLFMT,OUT_MESG,id))
X#define out_meta(id) fspool(strcons(SPOOLFMT,OUT_META,id))
X
X#define sent_mesg(id) fspool(strcons(SPOOLFMT,SENT_MESG,id))
X#define sent_meta(id) fspool(strcons(SPOOLFMT,SENT_META,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
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/* 90/01/22 13:02:27
X/* VERSION/RELEASE
X/* 2.1
X/*--*/
END_OF_main/path.h
if test 5231 -ne `wc -c <main/path.h`; then
echo shar: \"main/path.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f main/reply.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"main/reply.c\"
else
echo shar: Extracting \"main/reply.c\" \(5418 characters\)
sed "s/^X//" >main/reply.c <<'END_OF_main/reply.c'
X/*++
X/* NAME
X/* reply 3
X/* SUMMARY
X/* reply to a message
X/* PROJECT
X/* pc-mail
X/* PACKAGE
X/* mail
X/* SYNOPSIS
X/* int reply()
X/* DESCRIPTION
X/* reply() is invoked when the user has selected a mail message
X/* and wants to send a reply.
X/*
X/* If possible, the reply address and subject are extracted from
X/* the original message file. Reply-To: addresses are given precedence
X/* over From: addresses.
X/*
X/* The reply may include a quoted copy of the body of the original
X/* message.
X/*
X/* After editing the reply, the user gets a chance to modify the
X/* extracted reply address.
X/* FILES
X/* mail.msg, file being edited (in current directory)
X/* $MAILDIR/ennnnn, message file (body)
X/* $MAILDIR/cnnnnn, meta file (summary)
X/* $MAILDIR/header, template mail header file
X/* $MAILDIR/trailer, template signature file
X/* SEE ALSO
X/* email(3)
X/* DIAGNOSTICS
X/* If i/o errors are detected, an error message to that effect is
X/* displayed.
X/* BUGS
X/* Only understands From: and Reply-To: addresses. Reply-To: has higher
X/* precedence. No attempt is made to reconstruct BANG paths from
X/* successive UUCP-style From_ lines.
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 Dec 10 15:48:35 MET 1989
X/* LAST MODIFICATION
X/* 90/01/22 13:02:29
X/* VERSION/RELEASE
X/* 2.1
X/*--*/
X
X#include <stdio.h>
X
X#include "defs.h"
X#include "path.h"
X#include "pager.h"
X#include "screen.h"
X#include "status.h"
X#include "mail.h"
X#include "ascf.h"
X#include "ms_parse.h"
X
X/* forward declarations */
X
Xhidden int make_reply();
Xhidden int init_reply();
Xhidden void doquote();
Xhidden int getsubfrom();
X
Xhidden char original[BUFSIZ]; /* file name of original message */
X
X#define LINE 256 /* max. line length supported here */
X
Xhidden char from[LINE]; /* reply address */
X
X/* reply - user wants to reply to a message */
X
Xpublic int reply()
X{
X static Screen screen[] = {
X YESNO, 0, init_reply, int_error,
X 0, 0, 0,
X "Press ESC to cancel. Include original message?",
X };
X
X kbdinp(screen);
X return(S_BREAK);
X}
X
X/* init_reply - initial reply handling */
X
Xhidden int init_reply(need_quote)
Xregister int need_quote;
X{
X register unsigned msgno;
X register int stat;
X
X strcpy(original, message); /* keep original message name */
X msgno = newseqno();
X strcpy(message, work_mesg(msgno)); /* create message file name */
X strcpy(comment, work_meta(msgno)); /* create meta file name */
X
X if ((stat = make_reply(need_quote)) /* create template message */
X ||(stat = edit(message, MAILFILE))) /* and invoke editor */
X errdisp(stat);
X work_disp(from); /* ask disposition */
X return (S_REDRAW | S_BREAK); /* say screen was changed */
X}
X
X/* make_reply - create response file */
X
Xhidden int make_reply(need_quote)
Xint need_quote;
X{
X register FILE *out;
X char subj[LINE];
X int err;
X
X if (getsubfrom(original, subj, from)) { /* extract subject and sender */
X return (E_READERR);
X } else if (out = fopen(message, "w")) { /* build response file */
X (void) fprintf(out, "Subject: Re: %s\n", subj[0] ? subj : "");
X (void) textcopy(header_file(), out); /* append custom headers */
X (void) putc('\n', out);
X if (need_quote) {
X doquote(original, out); /* quote original text */
X (void) putc('\n', out);
X }
X (void) textcopy(trailer_file(), out); /* append custom signature */
X
X err = (fflush(out) || ferror(out)); /* do limited error checking */
X (void) fclose(out);
X return (err ? E_WRITERR : 0);
X } else {
X return (E_WRITERR);
X }
X}
X
X/* getsubfrom - extract Sender and Subject from original message */
X
Xhidden int getsubfrom(original, subj, from)
Xchar *original;
Xchar *subj;
Xchar *from;
X{
X FILE *in;
X char line[LINE];
X int context = MS_UUCP;
X int err = 0;
X
X /*
X * Reply-To: addresses have higher precedence than From: addresses. Skip
X * "Re: " at the beginning of a subject.
X */
X
X subj[0] = from[0] = 0;
X
X if (in = ascopen(original, "r")) {
X while ((context != MS_BODY) && ascgets(line, sizeof(line), in)) {
X if ((context = ms_parse(context, line)) == MS_HEADER) {
X /* Process From: only if we did not see Reply-To: */
X if (from[0] == 0
X && !hscanf(line, "From:", " %*[^<] < %[^>]", from))
X (void) hscanf(line, "From:", "%s", from);
X /* Process Reply-To: even if we found a From: address */
X if (!hscanf(line, "Subject: Re:", " %[^\n]", subj)
X && !hscanf(line, "Subject:", " %[^\n]", subj)
X && !hscanf(line, "Reply-To:", " %*[^<] < %[^>]", from))
X (void) hscanf(line, "Reply-To:", " %s", from);
X }
X }
X err = ferror(in);
X (void) ascclose(in);
X }
X return (err);
X}
X
X/* doquote - quote text from original message */
X
Xhidden void doquote(original, out)
Xchar *original;
XFILE *out;
X{
X int context = MS_UUCP;
X char line[LINE];
X FILE *in;
X
X /* Suppress the first line of the message body if it is empty. */
X
X if (in = ascopen(original, "r")) {
X while (ascgets(line, sizeof(line), in)) {
X switch (context = ms_parse(context, line)) {
X case MS_BODY:
X context++; /* hack */
X if (line[0] == 0) /* hack */
X break;
X /* FALLTHROUGH */
X case MS_BODY + 1: /* hack */
X fprintf(out, ">%s\n", line);
X break;
X }
X }
X (void) ascclose(in);
X }
X}
END_OF_main/reply.c
if test 5418 -ne `wc -c <main/reply.c`; then
echo shar: \"main/reply.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f main/spoolfil.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"main/spoolfil.c\"
else
echo shar: Extracting \"main/spoolfil.c\" \(5014 characters\)
sed "s/^X//" >main/spoolfil.c <<'END_OF_main/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(path,meta_info,mesg_prefix,meta_prefix)
X/* char *path;
X/* char *meta_info;
X/* int mesg_prefix;
X/* int meta_prefix;
X/*
X/* int metafile(path,string,...,(char *) 0)
X/* char *path;
X/* char *string;
X/* DESCRIPTION
X/* spoolfil() creates a (message, meta) file pair in the spool
X/* directory.
X/*
X/* "path" 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 written to
X/* the first line of a meta file (usually name of mail recipient, mail
X/* originator or a comment describing the contents of the message file).
X/* There should not be any embedded newline characters in this string.
X/*
X/* "mesg_prefix," "meta_prefix" are prefixes that will be used for building
X/* names for files in the spool directory.
X/*
X/* If the message file given to spoolfil() looks like a mail message, a
X/* line with Subject: information, extracted from the message, will be
X/* appended to the meta file.
X/*
X/* metafile() creates a file, writes the successive string arguments to
X/* that file, each followed by a newline character. This function is
X/* typically used to create a file with meta information (originator,
X/* subject 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/* 90/01/22 13:02:40
X/* VERSION/RELEASE
X/* 2.1
X/*--*/
X
X#include <stdio.h>
X#include <varargs.h>
X
X#include "defs.h"
X#include "path.h"
X#include "ascf.h"
X#include "status.h"
X#include "ms_parse.h"
X
X/* metafile - create a meta file */
X
X/* VARARGS */
X
Xpublic int metafile(va_alist)
Xva_dcl
X{
X char *path;
X char *string;
X FILE *fp;
X va_list ap;
X int ret = 0;
X
X va_start(ap);
X path = va_arg(ap, char *);
X
X if ((fp = fopen(path, "w")) == 0) {
X ret = E_WRITERR;
X } else {
X while ((string = va_arg(ap, char *)) != 0)
X (void) fprintf(fp, "%s\n", string);
X if (fflush(fp) || ferror(fp))
X ret = E_WRITERR;
X (void) fclose(fp);
X }
X va_end(ap);
X return (ret);
X}
X
X/* spoolfil - make arbitrary spool file */
X
Xpublic int spoolfil(fname, meta, msgpfx, auxpfx)
Xchar *fname;
Xchar *meta;
Xint msgpfx;
Xint 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 char subj[BUFSIZ]; /* subject: info */
X
X msgpath = mesg_file(msgpfx, newid); /* message file name */
X auxpath = meta_file(auxpfx, newid); /* meta file name */
X
X /* copy input file to spool file, try to get subject, check for errors */
X
X if (stat = copyfile(fname, msgpath, subj)) {/* read/write error */
X (void) unlink(msgpath); /* delete msg file */
X return (stat); /* notify caller */
X }
X /* create file for meta information, check for errors */
X
X if (stat = metafile(auxpath, meta, subj, (char *) 0)) {
X (void) unlink(msgpath); /* delete msg file */
X (void) unlink(auxpath); /* delete meta file */
X return (stat); /* notify caller */
X }
X /* when nothing went wrong */
X
X (void) chmod(msgpath, 0444); /* make message read-only */
X (void) chmod(auxpath, 0444); /* make metafile read-only */
X return (0); /* own error handling */
X}
X
X/* copyfile - copy a file, filter it, optionally extract subject: info */
X
Xpublic int copyfile(from, to, subj)
Xchar *from;
Xchar *to;
Xchar *subj; /* may be a null pointer */
X{
X register FILE *in,
X *out; /* file pointers */
X int ret = 0; /* 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 (void) ascclose(in);
X return (E_WRITERR);
X } else {
X char buf[BUFSIZ];
X register int context = MS_UUCP;
X
X if (subj)
X *subj = 0;
X
X while (ascgets(buf, sizeof(buf), in)) {
X (void) fputs(buf, out);
X (void) putc('\n', out);
X
X /* extract the subject "on the fly" */
X
X if (subj != 0 && *subj == 0
X && (context = ms_parse(context, buf)) == MS_HEADER)
X (void) hscanf(buf, "Subject:", " %[^\n]", subj);
X }
X
X /* perform the usual error checking */
X
X if (ferror(in))
X ret = E_READERR;
X else if (fflush(out) || ferror(out))
X ret = E_WRITERR;
X (void) ascclose(in);
X (void) fclose(out);
X return (ret);
X }
X}
END_OF_main/spoolfil.c
if test 5014 -ne `wc -c <main/spoolfil.c`; then
echo shar: \"main/spoolfil.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 5 \(of 11\).
cp /dev/null ark5isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 11 archives.
rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0