home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-01-24 | 63.3 KB | 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
-
-