v03i005: uucp mail for pc's (4 of 8)
Wietse Venema
wswietse at eutrc3.UUCP
Thu Apr 21 02:47:52 AEST 1988
comp.sources.misc: Volume 3, Issue 5
Submitted-By: "Wietse Venema" <wswietse at eutrc3.UUCP>
Archive-Name: pcmail/Part4
#! /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 4 (of 8)."
# Contents: Watchit cico.c connect.c email.c gp.h gpres.c ktrans.c
# makefile.msc rmail.c startup.c
# Wrapped by wietse at eutwc1 on Wed Apr 20 16:45:16 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f Watchit -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"Watchit\"
else
echo shar: Extracting \"Watchit\" \(649 characters\)
sed "s/^X//" >Watchit <<'END_OF_Watchit'
XMicrosoft decided to change the order of function arguments of
Xthe rename() function. Check the source against the documentation
Xof your compiler.
X
XSome functions are used in all programs. Therefore, everything has to
Xbe compiled with the same memory model.
X
XSince the assembly-language serial port driver assumes a small
Xmemory model, all programs have to be compiled with the small memory
Xmodel.
X
XThe MAILDIR, EDITOR environment variables should hold absolute path
Xnames. On MS-DOS systems (floppies!) it is a good idea to include
Xthe drive name as well.
X
XOn some MS-DOS systems the directory listing (file command) does
Xnot show the ".." entry.
END_OF_Watchit
if test 649 -ne `wc -c <Watchit`; then
echo shar: \"Watchit\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f cico.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"cico.c\"
else
echo shar: Extracting \"cico.c\" \(4984 characters\)
sed "s/^X//" >cico.c <<'END_OF_cico.c'
X/*++
X/* NAME
X/* cico 1
X/* SUMMARY
X/* uucp file transfer
X/* PROJECT
X/* pc-mail
X/* PACKAGE
X/* cico
X/* SYNOPSIS
X/* cico -p password [-d debuglevel]
X/* DESCRIPTION
X/* cico is a program that connects to a real unix host
X/* for exchange of spool files. It is a simplified
X/* version of the unix uucico (copy-in-copy-out) program.
X/*
X/* Options:
X/* .TP
X/* -p password
X/* The password that cico will use when logging in on the
X/* unix host.
X/* .TP
X/* -d debuglevel
X/* Set the debugging level. It makes both the local cico
X/* and the remote uucico more verbose. Default debugging
X/* level is 0.
X/* FILES
X/* cico manipulates various files in the spool directory.
X/* See path(5) for the implementation of the message data base.
X/*
X/* LOGFILE transaction logging
X/* s00000 communications parameters
X/* SEE ALSO
X/* comm(5) communications parameters
X/* status(5) error returns
X/* DIAGNOSTICS
X/* The program terminates with a non-zero exit status if there
X/* were problems. The error status codes can be translated
X/* to meaningful messages (see status(5)).
X/* More technical messages are written to the logfile.
X/* BUGS
X/* cico only supports the functions needed for exchange of
X/* electronic mail. Every incoming data file is treated as
X/* if it were a mail message for the user of the pc.
X/* AUTHOR(S)
X/* W.Z. Venema
X/* Eindhoven University of Technology
X/* Department of Mathematics and Computer Science
X/* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
X/* CREATION DATE
X/* Sat Mar 28 19:58:06 GMT+1:00 1987
X/* LAST MODIFICATION
X/* Wed Apr 6 00:18:29 MET 1988
X/* VERSION/RELEASE
X/* 1.6
X/*--*/
X
X#include <setjmp.h>
X#include "defs.h"
X#include "logs.h"
X#include "params.h"
X#include "comm.h"
X#include "status.h"
X#include "path.h"
X
Xpublic int *systrap; /* panic button */
Xpublic int dflag = 0; /* debug flag */
X#ifdef unix
X public int Debug = 0; /* UUCP compatibility */
X#endif
X
Xhidden void parse_args(),sanity(); /* forward declarations */
X
X/* main program - parse command line options and pull the ropes */
X
Xmain(argc,argv)
Xint argc;
Xchar **argv;
X{
X register int status; /* most recent error code */
X jmp_buf mainbuf; /* catch-all */
X
X parse_args(argc,argv); /* process cmd arguments */
X
X sanity(); /* check systems parameters */
X
X if (setjmp(systrap = mainbuf)) /* safety net in case of */
X exit(E_CONFUSED); /* too many long jumps */
X
X xopen(); /* init comm. line */
X if ((status = connect()) == 0 /* login on remote system */
X && (status = startproto()) == 0) { /* start comm. protocol */
X status = switcher(MASTER); /* use the protocol */
X endproto(); /* terminate the protocol */
X } /* (ignore errors) */
X disconnect(); /* as it says */
X xclose(); /* close comm. line */
X
X exit(status);
X /* NOTREACHED */
X}
X
X/* parse_args - take care of command-line arguments */
X
Xhidden void parse_args(argc,argv)
Xint argc;
Xchar **argv;
X{
X while (--argc && *++argv && **argv == '-') {
X switch (*++*argv) {
X case 'p':
X if (--argc == 0)
X usage("missing password argument");
X password = *++argv;
X break;
X case 'd':
X if (--argc == 0)
X usage("missing debugging level argument");
X sscanf(*++argv,"%d",&dflag);
X#ifdef unix
X Debug =
X#endif
X dflag = ((dflag < 0 ? 0 : dflag) > 10 ? 10 : dflag);
X break;
X default:
X usage(strcons("invalid option: -%s",*argv));
X break;
X }
X }
X if (argc > 0)
X usage(strcons("unexpected argument: %s",*argv));
X}
X
X/* sanity - some preliminary work; mainly checks on sanity */
X
Xhidden void sanity()
X{
X register int status;
X register Info *ip;
X
X if (status = pathinit()) /* check environment */
X exit(status); /* bad environment */
X
X if (status = open_log()) /* check the logfile */
X exit(status); /* cannot write */
X
X for (ip = comm = getparams(); ip->ident; ip++) { /* check param. file */
X if (ip->strval == 0 || ip->strval[0] == '\0')
X exit(E_BADSETUP); /* incomplete setup */
X debug(6)("%s %s\n",ip->ident,ip->strval ? ip->strval : "");
X }
X if (password == 0 || *password == 0)
X usage("no password specified"); /* no password */
X
X strcpy(rmthost,ip[P_HOST].strval); /* remote host name */
X}
X
X/* usage - print error message and usage string */
X
Xusage(str)
Xchar *str;
X{
X fprintf(stderr,"%s\nusage: cico -p password [-d debuglevel]\n",str);
X exit(2);
X}
END_OF_cico.c
if test 4984 -ne `wc -c <cico.c`; then
echo shar: \"cico.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f connect.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"connect.c\"
else
echo shar: Extracting \"connect.c\" \(5702 characters\)
sed "s/^X//" >connect.c <<'END_OF_connect.c'
X/*++
X/* NAME
X/* connect 3
X/* SUMMARY
X/* pre- and post protocol host access
X/* PROJECT
X/* pc-mail
X/* PACKAGE
X/* cico
X/* SYNOPSIS
X/* int connect()
X/*
X/* int disconnect()
X/* DESCRIPTION
X/* connect() tries to make a connection to the remote host
X/* and to log on, using the dial-up script and login-name
X/* entries in the communications parameter file, and the password
X/* provided as command-line parameter to the cico program.
X/* A simple send-expect script facility is used (no retries
X/* or delays). After the dial-up script has completed the program
X/* proceeds by expecting the login: prompt and does the final login.
X/*
X/* disconnect() tries to break a connection, using the disconnect
X/* entry in the communications parameter file. Unlike connect()
X/* this function is not driven by a send-expect script.
X/*
X/* The following escape sequences are recognized in send or expect
X/* strings:
X/*
X/* .nf
X/* \\b backspace
X/* \\r carriage return
X/* \\n newline
X/* \\t tab
X/* \\s space
X/* \\f form feed
X/* \\nnn octal character value
X/* \\\\ a real backslash
X/* FUNCTIONS AND MACROS
X/* xwrite(), xgetc(), trap(), debug(4)(), log()
X/* FILES
X/* $MAILDIR/s00000 communications parameter file
X/* $MAILDIR/LOGFILE system logfile
X/* SEE ALSO
X/* params(5) communications parameter file entries
X/* DIAGNOSTICS
X/* connect() returns a status E_BADSETUP if the systems parameter
X/* file contains bad data, and E_NOLINE if the login script fails.
X/* AUTHOR(S)
X/* W.Z. Venema
X/* Eindhoven University of Technology
X/* Department of Mathematics and Computer Science
X/* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
X/* CREATION DATE
X/* Fri Mar 27 17:11:12 GMT+1:00 1987
X/* LAST MODIFICATION
X/* Wed Apr 6 00:19:26 MET 1988
X/* VERSION/RELEASE
X/* 1.4
X/*--*/
X
X#include <setjmp.h>
X#include <ctype.h>
X#include "defs.h"
X#include "params.h"
X#include "status.h"
X#include "comm.h"
X#include "logs.h"
X#include "sysdep.h"
X
Xhidden char *blnk = " \t"; /* send/expect separators */
X
X/* forward declarations */
X
Xhidden void conn_send();
Xhidden void conn_xpct();
Xhidden char *escape();
X
X/* connect - connect to remote system; simple script processing (no retries) */
X
Xpublic int connect()
X{
X int *savetrap = systrap; /* save exception handler */
X jmp_buf mytrap; /* our exception handler */
X int retval; /* completion code */
X register char *cp;
X
X /* set up exception handler */
X
X if (retval = setjmp(systrap = mytrap)) { /* get here if expect fails */
X systrap = savetrap; /* it just happened */
X return(retval);
X }
X
X /* optional dial-up sequence */
X
X for (cp = strtok(DIAL_SEQUENCE,blnk); cp; cp = strtok((char *)0,blnk)) {
X conn_send(escape(cp));
X if (cp = strtok((char *)0,blnk))
X conn_xpct(escape(cp));
X }
X
X /* mandatory login sequence */
X
X conn_xpct("ogin:");
X conn_send(strcons("%s\r",LOGIN_NAME));
X conn_xpct("ssword:");
X conn_send(strcons("%s\r",password));
X
X /* restore exception handler */
X
X systrap = savetrap; /* get here if expect wins */
X return(0); /* say no problems... */
X}
X
X/* disconnect - disconnect line */
X
Xpublic int disconnect()
X{
X conn_send(escape(DISC_SEQUENCE)); /* send disconnect sequence */
X return(0); /* always succeeds... */
X}
X
X/* conn_send - quick-and-dirty output function */
X
Xhidden void conn_send(s)
Xregister char *s;
X{
X sleep(1);
X
X if (*s) {
X debug(4)("Sending: %S\n",s);
X while (*s) {
X delay();
X xwrite(ttfd,s++,1);
X }
X }
X}
X
X/* conn_xpct - primitive pattern matching without meta characters */
X
Xhidden void conn_xpct(s)
Xchar *s;
X{
X register int c,i;
X register int n = strlen(s);
X
X /*
X * Keep listening until we time out or until we receive the
X * expected string. Make sure that we do not overrun our buffer.
X * Parity bits are ignored.
X */
X
X if (n) {
X debug(4)("Expecting: %S\nReceiving: ",s);
X
X if (n > MSGBUF) n = MSGBUF;
X
X for (i = 0; (c = xgetc()) != EOF; ) {
X msgin[i++] = (c &= 0177);
X debug(4)("%C",c);
X if (i >= n && strncmp(s,&msgin[i-n],n) == 0) {
X debug(4)(" ok!\n");
X return;
X } else if (i >= MSGBUF) {
X strncpy(msgin,&msgin[i-(n-1)],n-1);
X i = n-1;
X }
X }
X debug(4)(" failed!\n");
X trap(E_NOLINE,"LOGIN FAILED (at \"%S\")",s);
X }
X}
X
X/* escape - interpret backslash sequences (this function is too big) */
X
Xhidden char *escape(s)
Xregister char *s;
X{
X static char buf[BUFSIZ];
X register char *cp = buf;
X
X while (*s && cp < buf+BUFSIZ-1) { /* don't overflow the buffer */
X register char ch;
X if (*s != '\\') { /* ordinary character */
X *cp++ = *s++;
X } else if (isdigit(*++s) && *s < '8') { /* \nnn octal code */
X int c, i;
X sscanf(s,"%3o",&c);
X *cp++ = c;
X i = 1;
X s++;
X while (i++ < 3 && isdigit(*s) && *s <'8')
X s++;
X } else if ((ch = *s++) == 0) { /* at string terminator */
X break;
X } else if (ch == 'b') { /* \b becomes backspace */
X *cp++ = '\b';
X } else if (ch == 'f') { /* \f becomes formfeed */
X *cp++ = '\f';
X } else if (ch == 'n') { /* \n becomes newline */
X *cp++ = '\n';
X } else if (ch == 'r') { /* \r becomes carriage ret */
X *cp++ = '\r';
X } else if (ch == 's') { /* \s becomes blank */
X *cp++ = ' ';
X } else if (ch == 't') { /* \t becomes tab */
X *cp++ = '\t';
X } else { /* \any becomes any */
X *cp++ = ch;
X }
X }
X *cp = '\0'; /* terminate the result */
X return(buf);
X}
END_OF_connect.c
if test 5702 -ne `wc -c <connect.c`; then
echo shar: \"connect.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f email.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"email.c\"
else
echo shar: Extracting \"email.c\" \(5428 characters\)
sed "s/^X//" >email.c <<'END_OF_email.c'
X/*++
X/* NAME
X/* email
X/* SUMMARY
X/* manipulate work files (mail in preparation)
X/* PROJECT
X/* pc-mail
X/* PACKAGE
X/* mailsh
X/* SYNOPSIS
X/* #include "email.h"
X/*
X/* int mail()
X/* DESCRIPTION
X/* The functions in this module are responsible for manipulations
X/* on work files and other mail messages in preparation.
X/*
X/* mail() can be called either when the user has selected a work file in
X/* the mail box display or when the user wants to create a new letter.
X/*
X/* The message file is displayed on the screen and the can choose
X/* to print, mail, edit or delete etc. the message.
X/*
X/* The code in this module is a little tricky, to avoid that a work
X/* file exists without a metafile (for the mail box display).
X/* COMMANDS
X/* the program specified in the EDITOR environment variable,
X/* or a system-dependent default.
X/* FILES
X/* temporary edit file in current directory
X/* work file and meta file in spool directory
X/* SEE ALSO
X/* pager(3), pager(5), kbdinp(3), edit(3)
X/* AUTHOR(S)
X/* W.Z. Venema
X/* Eindhoven University of Technology
X/* Department of Mathematics and Computer Science
X/* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
X/* CREATION DATE
X/* Tue May 12 15:35:20 GMT+1:00 1987
X/* LAST MODIFICATION
X/* Mon Apr 4 23:39:13 MET 1988
X/* VERSION/RELEASE
X/* 1.3
X/*--*/
X
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <errno.h>
X#include "defs.h"
X#include "path.h"
X#include "dir.h"
X#include "pager.h"
X#include "screen.h"
X#include "mailsh.h"
X#include "status.h"
X
X/* forward declarations */
X
Xhidden void junk_work();
Xhidden int queue_work();
Xhidden int edit_work();
Xhidden int show_work();
Xhidden int send_work();
Xhidden int hold_work();
Xhidden int label_work();
X
Xhidden File *workfile = 0; /* pager file */
X
X/* mail - user has made a choice. show message at cursor */
X
Xpublic int mail()
X{
X static Screen screen[] = {
X 'C', "Close", hold_work,"Send message later, return to main menu",
X 'D', "Delete", delete, delcurr,
X 'E', "Edit", edit_work,"Edit this message",
X 'M', "Mail", send_work,"Send this message to destination",
X 'P', "Print", print, printcurr,
X PGUP, PgUp, pu_pager,pageup,
X PGDN, PgDn, pd_pager,pagedn,
X UP, "Up", up_pager,csrup,
X DOWN, "Down", dn_pager,csrdn,
X 0, 0, show_work,
X "(Reading a message in preparation)",
X };
X struct stat s;
X
X if (stat(message,&s) && errno == ENOENT) /* if new message file */
X edit_work(); /* invoke editor first */
X kbdinp(screen); /* ask disposition */
X junk_work(); /* destroy mail pager file */
X return(S_REDRAW); /* say screen was changed */
X}
X
X/* show_work - show work file or error message in middle window */
X
Xhidden int show_work()
X{
X if (workfile) { /* check pager file exists */
X set_pager(workfile); /* select existent display */
X } else if (rd_pager(workfile = open_pager(),message)) {/* create display */
X mesg_pager(workfile,m_msgread); /* cannot display message */
X }
X ds_pager(); /* (re)draw display */
X return(0); /* screen is up-to-date */
X}
X
X/* junk_work - destroy work file display */
X
Xhidden void junk_work()
X{
X if (workfile) { /* no-op if no display */
X close_pager(workfile); /* release memory */
X workfile = 0; /* say it is gone */
X }
X}
X
X/* edit_work - edit or create a work file */
X
Xhidden int edit_work()
X{
X register int stat;
X
X if (stat = edit(message,MAILFILE))
X errdisp(stat); /* edit() had a problem */
X junk_work(); /* force new message display */
X return(S_REDRAW); /* say screen has changed */
X}
X
X/* hold_work - stop editing but do not yet mail a work file */
X
Xhidden int hold_work()
X{
X static Screen screen[] = {
X STRING, 0, label_work,int_error,
X 0, 0, 0,
X getsummary,
X };
X struct stat s;
X
X /*
X * The user has terminated an editor session, but does not yet want
X * to send the message off. The purpose of the following code is to
X * ask for a one-line summary, but only if such a comment does not yet
X * exist. The summary is used to identify the work file in the main
X * mail box display.
X */
X
X if (stat(message,&s) || !stat(comment,&s)) {/* no msg, or comment exists */
X return(S_BREAK); /* we are done here */
X } else {
X return(kbdinp(screen)|S_REDRAW); /* ask for a summary */
X }
X}
X
X/* label_work - save summary line to meta file */
X
Xhidden label_work(string)
Xchar *string;
X{
X register int stat;
X
X if (stat = metafile(string,comment)) { /* try to create meta file */
X errdisp(stat); /* oops, notify the user */
X return(S_REDRAW); /* say screen has changed */
X } else {
X chmod(comment,0444); /* make comments read-only */
X junk_desk(); /* say mail box has changed */
X return(S_BREAK); /* say no more work */
X }
X}
X
X/* send_work - user wants to send work file, ask for destination */
X
Xhidden int send_work()
X{
X static Screen screen[] = {
X STRING, 0, queue_work,int_error,
X 0, 0, when,
X "Press ESC to cancel. Send message to:",
X };
X return(kbdinp(screen)|S_REDRAW);
X}
X
X/* queue_work - spool mail, delete work file and meta file */
X
Xhidden int queue_work(to)
Xchar *to;
X{
X register int stat;
X
X if (stat = submit(message,to)) {
X errdisp(stat); /* cannot queue message */
X return(S_REDRAW); /* say screen has changed */
X } else {
X return(unspool()|S_BREAK); /* remove work and meta file */
X }
X}
END_OF_email.c
if test 5428 -ne `wc -c <email.c`; then
echo shar: \"email.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f gp.h -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"gp.h\"
else
echo shar: Extracting \"gp.h\" \(5523 characters\)
sed "s/^X//" >gp.h <<'END_OF_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/* Mon Apr 4 23:40:57 MET 1988
X/* VERSION/RELEASE
X/* 1.3
X/*--*/
END_OF_gp.h
if test 5523 -ne `wc -c <gp.h`; then
echo shar: \"gp.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f gpres.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"gpres.c\"
else
echo shar: Extracting \"gpres.c\" \(6391 characters\)
sed "s/^X//" >gpres.c <<'END_OF_gpres.c'
X/*++
X/* NAME
X/* gpres.c 3
X/* SUMMARY
X/* g-protocol general interface
X/* PROJECT
X/* pc-mail
X/* PACKAGE
X/* cico
X/* SYNOPSIS
X/* int gopen(fd);
X/* int fd;
X/*
X/* int gwrite(fd,buf,len)
X/* int fd,len;
X/* char *buf;
X/*
X/* int gread(fd,buf,len)
X/* int fd,len;
X/* char *buf;
X/*
X/* int gclose(fd)
X/* int fd;
X/* DESCRIPTION
X/* The functions in this module present an interface that closely
X/* resembles the unix kernel i/o interface.
X/*
X/* gopen() handles the initial message exchange. fd should be
X/* connected to a tty line. gopen() normally returns a zero value.
X/*
X/* gwrite() returns the number of bytes `written' to the remote system.
X/* It should be considered an error if this is not equal to the number
X/* of bytes requested.
X/* A zero-length write should be used to indicate EOF during file transfer.
X/*
X/* gread() returns the requested number of bytes or the number of
X/* bytes sent by the remote system, whichever is smaller.
X/* A zero-length read indicates EOF during file transfer.
X/*
X/* gclose() shuts the protocol down, but does not otherwise change
X/* communications line parameters. It normally returns a zero value.
X/* FUNCTIONS AND MACROS
X/* galloc(), gfree(), gsproto(), grproto()
X/* DIAGNOSTICS
X/* All functions return -1 in case of unrecoverable problems.
X/* BUGS
X/* All g protocol routines assume that the XON/XOFF flow control
X/* has been turned off.
X/* Some parts of the code rely on 8-bit bytes, 16-bit short integers.
X/* AUTHOR(S)
X/* W.Z. Venema
X/* Eindhoven University of Technology
X/* Department of Mathematics and Computer Science
X/* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
X/* CREATION DATE
X/* Sun Apr 19 12:41:37 GMT+1:00 1987
X/* LAST MODIFICATION
X/* Mon Apr 4 23:41:36 MET 1988
X/* VERSION/RELEASE
X/* 1.3
X/*--*/
X
X#include <setjmp.h>
X#include "gp.h"
X
X/* local and forward declarations */
X
Xstatic jmp_buf failbuf;
Xstatic void gpeek(),gpoke(),memcpy();
X
X/* gfail - exception handling */
X
Xvoid gfail()
X{
X longjmp(failbuf,1);
X}
X
X/* gopen - not quite an analogon of unix open(2) */
X
Xint gopen(fd)
Xint fd;
X{
X return(ginit(fd)); /* do packet stuff elsewhere */
X}
X
X/* gwrite - g-protocol analogon of unix write(2) */
X
Xgwrite(fd,data,len)
Xint fd,len;
Xchar *data;
X{
X /* set up exception handling */
X
X if (setjmp(failbuf)) /* in case gsproto fails */
X return(FAIL); /* it just did */
X
X /* handle special case of zero-length writes separately */
X
X if (len <= 0) { /* end-of-file message */
X register Packet *pk = galloc(); /* allocate output packet */
X gpoke(pk,data,len); /* make null-data packet */
X gsproto(fd,pk); /* send to other side */
X } else { /* true data message */
X register int shot; /* quantum size */
X register int rest; /* amount left to do */
X for (rest = len; rest > 0; rest -= shot,data += shot) {
X register Packet *pk = galloc(); /* allocate output packet */
X gpoke(pk,data,shot = MIN(pk->len,rest));/* fill the packet */
X gsproto(fd,pk);
X }
X }
X return(len); /* no problems detected */
X}
X
X/* gread - g-protocol analogon of unix read(2) */
X
Xgread(fd,data,len)
Xint fd,len;
Xchar *data;
X{
X static Packet *pk; /* our byte stock */
X register int igot; /* our return value */
X
X /* set up exception handling */
X
X if (setjmp(failbuf)) /* in case grproto fails */
X return(FAIL); /* it just did */
X
X /* if no bytes in stock, get some fresh ones and see how much we got */
X
X if (pk == 0 || pk->segl <= 0) /* we are out of data */
X gpeek(pk = grproto(fd)); /* get fresh packet */
X
X /* return as many bytes as asked, or as in stock, whichever is less */
X
X if ((igot = MIN(len,pk->segl)) > 0) {
X memcpy(data,pk->segp,igot); /* copy to caller's buffer */
X pk->segp += igot; /* update stock pointer */
X pk->segl -= igot; /* update stock count */
X }
X if (pk->segl <= 0) /* if we exhausted the stock */
X gfree(pk); /* release packet */
X return(igot); /* no problems detected */
X}
X
X/* gclose - turn g protocol off */
X
Xgclose(fd)
Xint fd;
X{
X return(gfinit(fd)); /* not here! */
X}
X
X/*
X* "Each transmitter is constrained to observe the maximum data segment"
X* "size established during initial synchronization by the receiver that"
X* "it sends to. (...) `short' packets have zero or more data bytes but less"
X* "than the maximum. The first one or two bytes of the data segment of"
X* "a short packet are `count' bytes that indicate the difference between"
X* "the maximum size and the number of bytes in the short segment. If the"
X* "difference is less than 127, one count byte is used. If the difference"
X* "exceeds 127, then the low-order seven bits of the difference are put"
X* "in the first data byte and the remaining high-order bit is set as an"
X* "indication that the remaining bits of the difference are in the second"
X* "byte.
X*/
X
X/* gpoke - prepare packet for transmission */
X
Xstatic void gpoke(pk,data,len)
Xregister Packet *pk;
Xint len;
Xchar *data;
X{
X register int diff = pk->len-len; /* packet/data size mismatch */
X
X pk->segp = pk->data; /* set up write pointer */
X pk->segl = len; /* actual segment length */
X if (diff < 0 || len < 0) {
X DEBUG(7,"gpoke: trouble\n",""); /* something very wrong */
X gfail();
X /* NOTREACHED */
X } else if (diff == 0) {
X pk->c = DATA; /* long data segment */
X } else if (diff <= 127) {
X pk->c = SHORT; /* short data segment */
X *pk->segp++ = diff; /* one difference byte */
X } else if (diff > 127) {
X pk->c = SHORT; /* tiny data segment */
X *pk->segp++ = diff|0200; /* two difference bytes */
X *pk->segp++ = diff>>7;
X }
X memcpy(pk->segp,data,pk->segl); /* copy data into packet */
X}
X
X/* gpeek - prepare newly packet for reading */
X
Xstatic void gpeek(pk)
Xregister Packet *pk;
X{
X register int diff;
X
X pk->segp = pk->data; /* set up read pointer */
X if (TYPE(pk->c) == DATA) {
X diff = 0; /* long data segment */
X } else if (TYPE(pk->c) != SHORT) {
X DEBUG(7,"gread: trouble\n",""); /* something funny */
X gfail();
X /* NOTREACHED */
X } else if ((diff = *pk->segp++&0377)&0200) {/* short data segment */
X diff = (diff&0177)|((*pk->segp++&0377)<<7);
X }
X pk->segl = pk->len-diff; /* actual segment size */
X DEBUG(9,"rcv: data %d bytes\n",pk->segl);
X}
X
X/* memcpy - not-so-efficient implementation */
X
Xstatic void memcpy(dst,src,len)
Xregister char *dst,*src;
Xregister int len;
X{
X while (len-- > 0)
X *dst++ = *src++;
X}
END_OF_gpres.c
if test 6391 -ne `wc -c <gpres.c`; then
echo shar: \"gpres.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f ktrans.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"ktrans.c\"
else
echo shar: Extracting \"ktrans.c\" \(4983 characters\)
sed "s/^X//" >ktrans.c <<'END_OF_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/* Mon Apr 4 23:43:42 MET 1988
X/* VERSION/RELEASE
X/* 1.4
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_ktrans.c
if test 4983 -ne `wc -c <ktrans.c`; then
echo shar: \"ktrans.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f makefile.msc -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"makefile.msc\"
else
echo shar: Extracting \"makefile.msc\" \(5643 characters\)
sed "s/^X//" >makefile.msc <<'END_OF_makefile.msc'
XRM = rm -f
XMV = mv
XCC = cl
XAS = masm
X
XSHOBJ1 = call.o email.o file.o screen.o mbox.o desk.o
XSHOBJ2 = kbdinp.o pager.o window.o setup.o errdisp.o invoke.o
XSHOBJ3 = makework.o mailfile.o deskutil.o submit.o edit.o alias.o
XSHLIBS = shlib1.lib shlib2.lib shlib3.lib
X
XSMOBJ = smail.o unalias.o hsearch.o
X
XRMOBJ = rmail.o
X
XCMOBJ = cmail.o invoke.o
X
XCIOBJ1 = comm.o connect.o getwork.o kphys.o kpres.o ktrans.o logs.o
XCIOBJ2 = newseqno.o protomsg.o rmtname.o scanwork.o sendwork.o startup.o
XCIOBJ3 = switcher.o xpres.o gpres.o gtrans.o gphys.o
XCILIBS = cilib1.lib cilib2.lib cilib3.lib
X
XGENSRC = dir.c myalloc.c params.c path.c newseqno.c ascf.c spoolfil.c \
X str.c
XGENOBJ = dir.o myalloc.o params.o path.o newseqno.o ascf.o spoolfil.o \
X str.o
X
XCFLAGS = -Gs
XLDFLAGS = -F 2000
X
X.s.o:
X $(AS) $*.s ;
X $(MV) $*.obj $*.o
X
X.c.o:
X $(CC) $(CFLAGS) -c $*.c
X $(MV) $*.obj $*.o
X
Xall: mail.exe smail.exe rmail.exe cico.exe cmail.exe
X
Xmail.exe: mailsh.o $(SHLIBS) libgen.lib
X $(CC) $(LDFLAGS) -o mail mailsh.o -link $(SHLIBS) libgen.lib \lib\termcap
X -exepack mail.exe junk
X $(MV) junk mail.exe
X
Xsmail.exe: $(SMOBJ) libgen.lib
X $(CC) $(LDFLAGS) -o smail $(SMOBJ) -link libgen.lib
X -exepack smail.exe junk
X $(MV) junk smail.exe
X
Xcmail.exe: cmail.o libgen.lib
X $(CC) $(LDFLAGS) -o cmail cmail.o invoke.o -link libgen.lib
X -exepack cmail.exe junk
X $(MV) junk cmail.exe
X
Xrmail.exe: rmail.o libgen.lib
X $(CC) $(LDFLAGS) -o rmail rmail.o -link libgen.lib
X -exepack rmail.exe junk
X $(MV) junk rmail.exe
X
Xcico.exe: cico.o comport.o $(CILIBS)
X $(CC) $(LDFLAGS) -o junk cico.o comport.o -link $(CILIBS) libgen
X -exepack junk.exe cico.exe
X $(RM) junk.exe
X
Xshlib1.lib: $(SHOBJ1)
X $(RM) shlib1.lib
X lib shlib1.lib $(SHOBJ1) ;
X
Xshlib2.lib: $(SHOBJ2)
X $(RM) shlib2.lib
X lib shlib2.lib $(SHOBJ2) ;
X
Xshlib3.lib: $(SHOBJ3)
X $(RM) shlib3.lib
X lib shlib3.lib $(SHOBJ3) ;
X
Xlibgen.lib: $(GENOBJ)
X $(RM) $@
X lib libgen $(GENOBJ) ;
X
Xcilib1.lib: $(CIOBJ1)
X $(RM) $@
X lib cilib1 $(CIOBJ1) ;
X
Xcilib2.lib: $(CIOBJ2)
X $(RM) $@
X lib cilib2 $(CIOBJ2) ;
X
Xcilib3.lib: $(CIOBJ3)
X $(RM) $@
X lib cilib3 $(CIOBJ3) ;
X
Xdepend:
X @grep '^# *include *"' *.c|sed 's/c:# *include *"\([^"]*\)".*/o: \1/g'
X
Xalias.o: defs.h
Xalias.o: path.h
Xalias.o: pager.h
Xalias.o: mailsh.h
Xalias.o: screen.h
Xalias.o: status.h
Xascf.o: defs.h
Xascf.o: ascf.h
Xcall.o: defs.h
Xcall.o: path.h
Xcall.o: screen.h
Xcall.o: pager.h
Xcall.o: mailsh.h
Xcico.o: defs.h
Xcico.o: logs.h
Xcico.o: params.h
Xcico.o: comm.h
Xcico.o: status.h
Xcico.o: path.h
Xcmail.o: defs.h
Xcmail.o: dir.h
Xcmail.o: path.h
Xcmail.o: status.h
Xcomm.o: defs.h
Xcomm.o: params.h
Xcomm.o: comm.h
Xconnect.o: defs.h
Xconnect.o: params.h
Xconnect.o: status.h
Xconnect.o: comm.h
Xconnect.o: logs.h
Xconnect.o: sysdep.h
Xdesk.o: defs.h
Xdesk.o: mailsh.h
Xdesk.o: path.h
Xdesk.o: dir.h
Xdesk.o: pager.h
Xdesk.o: screen.h
Xdesk.o: status.h
Xdesk.o: window.h
Xdeskutil.o: defs.h
Xdeskutil.o: pager.h
Xdeskutil.o: mailsh.h
Xdeskutil.o: screen.h
Xdeskutil.o: status.h
Xdir.o: defs.h
Xdir.o: dir.h
Xedit.o: defs.h
Xedit.o: path.h
Xedit.o: mailsh.h
Xedit.o: status.h
Xemail.o: defs.h
Xemail.o: path.h
Xemail.o: dir.h
Xemail.o: pager.h
Xemail.o: screen.h
Xemail.o: mailsh.h
Xemail.o: status.h
Xerrdisp.o: defs.h
Xerrdisp.o: screen.h
Xerrdisp.o: pager.h
Xerrdisp.o: status.h
Xerrdisp.o: window.h
Xfile.o: defs.h
Xfile.o: screen.h
Xfile.o: pager.h
Xfile.o: mailsh.h
Xfile.o: dir.h
Xfile.o: path.h
Xfile.o: status.h
Xfile.o: window.h
Xgetwork.o: defs.h
Xgetwork.o: logs.h
Xgetwork.o: status.h
Xgetwork.o: work.h
Xgetwork.o: params.h
Xgetwork.o: comm.h
Xgphys.o: gp.h
Xgpres.o: gp.h
Xgtrans.o: gp.h
Xhsearch.o: hsearch.h
Xinvoke.o: defs.h
Xinvoke.o: status.h
Xkbdinp.o: defs.h
Xkbdinp.o: mailsh.h
Xkbdinp.o: screen.h
Xkbdinp.o: window.h
Xkphys.o: kp.h
Xkpres.o: kp.h
Xktrans.o: kp.h
Xlogs.o: defs.h
Xlogs.o: logs.h
Xlogs.o: path.h
Xlogs.o: status.h
Xmailfile.o: defs.h
Xmailfile.o: path.h
Xmailfile.o: screen.h
Xmailfile.o: mailsh.h
Xmailsh.o: defs.h
Xmailsh.o: path.h
Xmailsh.o: status.h
Xmailsh.o: mailsh.h
Xmailsh.o: window.h
Xmakework.o: defs.h
Xmakework.o: path.h
Xmakework.o: screen.h
Xmakework.o: mailsh.h
Xmbox.o: defs.h
Xmbox.o: path.h
Xmbox.o: pager.h
Xmbox.o: screen.h
Xmbox.o: mailsh.h
Xmyalloc.o: defs.h
Xnewseqno.o: defs.h
Xnewseqno.o: path.h
Xnewseqno.o: dir.h
Xpager.o: defs.h
Xpager.o: window.h
Xpager.o: pager.h
Xpager.o: path.h
Xpager.o: ascf.h
Xparams.o: defs.h
Xparams.o: path.h
Xparams.o: params.h
Xpath.o: defs.h
Xpath.o: path.h
Xpath.o: status.h
Xprotomsg.o: defs.h
Xprotomsg.o: params.h
Xprotomsg.o: comm.h
Xprotomsg.o: logs.h
Xprotomsg.o: status.h
Xrmail.o: defs.h
Xrmail.o: dir.h
Xrmail.o: path.h
Xrmail.o: status.h
Xrmtname.o: defs.h
Xrmtname.o: params.h
Xrmtname.o: comm.h
Xrmtname.o: logs.h
Xrmtname.o: status.h
Xrmtname.o: path.h
Xscanwork.o: defs.h
Xscanwork.o: params.h
Xscanwork.o: comm.h
Xscanwork.o: work.h
Xscanwork.o: path.h
Xscanwork.o: dir.h
Xscanwork.o: logs.h
Xscreen.o: defs.h
Xscreen.o: screen.h
Xsendwork.o: defs.h
Xsendwork.o: work.h
Xsendwork.o: logs.h
Xsendwork.o: status.h
Xsendwork.o: params.h
Xsendwork.o: comm.h
Xsetup.o: defs.h
Xsetup.o: path.h
Xsetup.o: screen.h
Xsetup.o: mailsh.h
Xsetup.o: pager.h
Xsetup.o: params.h
Xsetup.o: status.h
Xsetup.o: window.h
Xsmail.o: defs.h
Xsmail.o: path.h
Xsmail.o: status.h
Xspoolfil.o: defs.h
Xspoolfil.o: path.h
Xspoolfil.o: ascf.h
Xspoolfil.o: status.h
Xstartup.o: defs.h
Xstartup.o: params.h
Xstartup.o: comm.h
Xstartup.o: logs.h
Xstartup.o: status.h
Xstartup.o: sysdep.h
Xstr.o: defs.h
Xsubmit.o: defs.h
Xsubmit.o: path.h
Xswitcher.o: defs.h
Xswitcher.o: work.h
Xswitcher.o: params.h
Xswitcher.o: comm.h
Xswitcher.o: logs.h
Xswitcher.o: status.h
Xunalias.o: defs.h
Xunalias.o: hsearch.h
Xunalias.o: path.h
Xunalias.o: ascf.h
Xwindow.o: defs.h
Xwindow.o: window.h
Xxpres.o: defs.h
Xxpres.o: params.h
Xxpres.o: comm.h
Xxpres.o: status.h
Xxpres.o: sysdep.h
Xxpres.o: logs.h
END_OF_makefile.msc
if test 5643 -ne `wc -c <makefile.msc`; then
echo shar: \"makefile.msc\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f rmail.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"rmail.c\"
else
echo shar: Extracting \"rmail.c\" \(6168 characters\)
sed "s/^X//" >rmail.c <<'END_OF_rmail.c'
X/*++
X/* NAME
X/* rmail
X/* SUMMARY
X/* extract originator from new mail received by cico
X/* PROJECT
X/* pc-mail
X/* PACKAGE
X/* rmail
X/* SYNOPSIS
X/* rmail
X/* DESCRIPTION
X/* rmail searches for new mail files received by cico and extracts
X/* the originator's name, for later use by the mail visual shell.
X/*
X/* Return address formats we understand (in order of preference):
X/* .nf
X/*
X/* From: address (full_name) (accept the full_name)
X/* From: address (accept the address)
X/* >From address (take address and keep scanning)
X/* From address (take address and keep scanning)
X/*
X/* .fi
X/* To avoid tampering, new files will have read-only permission.
X/*
X/* In order to avoid corruption, control-c interrupts are disabled.
X/* FILES
X/* In the spool directory:
X/* n<seqno> received mail message
X/* h<seqno> extracted originator address
X/* SEE ALSO
X/* path(5) spool directory, file names
X/* cico(1) network process
X/* mailsh(1) visual mail shell
X/* DIAGNOSTICS
X/* Exit status zero when no errors were detected, nonzero in case of file
X/* access errors. See status(5) for error codes.
X/* BUGS
X/* Note that the format "From: full_name <address>" is not
X/* recognized. The program will just pick up the first word from
X/* full_name.
X/*
X/* Does not really do a good job when parsing the mail headers.
X/* At least, not good enough to extract a return path.
X/* AUTHOR(S)
X/* W.Z. Venema
X/* Eindhoven University of Technology
X/* Department of Mathematics and Computer Science
X/* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
X/* CREATION DATE
X/* Tue Mar 31 20:14:11 GMT+1:00 1987
X/* LAST MODIFICATION
X/* Wed Apr 6 00:21:54 MET 1988
X/* VERSION/RELEASE
X/* 1.4
X/*--*/
X
X#include <setjmp.h>
X#include <signal.h>
X#include <time.h>
X#include <ctype.h>
X#include "defs.h"
X#include "dir.h"
X#include "path.h"
X#include "status.h"
X
Xextern struct tm *localtime(); /* system functions */
X
Xhidden void parse_args(); /* forward declarations */
Xhidden void newmail();
Xhidden void extract();
Xhidden void usage();
X
X#define HLEN 20 /* nbr of header lines scanned */
X
Xhidden int dflag = 0; /* debugging option */
X
X#define debug if (dflag) printf
X
Xmain(argc,argv)
Xint argc;
Xchar **argv;
X{
X signal(SIGINT,SIG_IGN); /* disable ctrl-c */
X parse_args(argc,argv); /* parse command args */
X pathinit(); /* get path info */
X umask(0222); /* make files read-only */
X newmail(); /* get headers from new mail */
X exit(0);
X /* NOTREACHED */
X}
X
X/* parse_args - process command-line arguments */
X
Xhidden void parse_args(argc,argv)
Xint argc;
Xchar **argv;
X{
X while (--argc && *++argv && **argv == '-') { /* process options */
X switch (*++*argv) {
X case 'd': /* turn debugging on */
X if (--argc == 0)
X usage("missing debugging level argument");
X sscanf(*++argv,"%d",&dflag);
X if (dflag < 0 || dflag > 9)
X dflag = 0;
X break;
X default: /* unknown option */
X usage(strcons("invalid option: -%c",**argv));
X break;
X }
X }
X
X /* check for extraneous arguments */
X
X if (argc > 0)
X usage(strcons("unexpected argument: %s",*argv));
X}
X
X/* scan for new mail that hasn't gotten yet a metafile */
X
Xhidden void newmail()
X{
X register int dd;
X int pfxlen = sizeof(NEWPFX)-1;
X char *f;
X
X debug("directory: \"%s\"\n",maildir); /* verify */
X
X /*
X * Scan the spool directory for newly-arrived mail.
X *
X * Incoming mail message files have a name of "n<seqno>".
X * The originator name is normally present in files with names
X * "h<seqno>" or "o<seqno>".
X * The presence of an "o" file implies that the file "n<seqno>"
X * has been read by the user. An "h" file means that the user
X * has not yet read the message file.
X *
X * If a message file has no corresponding "h" or "o" file we
X * assume it is a new mail message and create an "h" file with
X * the name of the originator.
X */
X
X for (dd = opendir(maildir); f = readdir(dd); /* void */) {
X int seqno;
X debug("rmail: file \"%s\"\n",f);
X if (strncmp(f,NEWPFX,pfxlen) == 0 && sscanf(f+pfxlen,"%d",&seqno)) {
X if (access(in_meta(seqno),4) == 0) { /* message already */
X /* void */ ; /* marked as read */
X } else if (access(new_meta(seqno),4) == 0) {/* message already */
X /* void */ ; /* marked as unread */
X } else { /* create meta file */
X extract(new_mesg(seqno),new_meta(seqno));
X }
X }
X }
X closedir(dd);
X}
X
X/* extract - extract originator info from mail file to meta file */
X
Xhidden void extract(mail,meta)
Xchar *mail;
Xchar *meta;
X{
X FILE *mesgfp,*metafp;
X char line[BUFSIZ];
X char from[BUFSIZ];
X int n;
X
X debug("-- \"%s\" -> \"%s\"\n",mail,meta);
X
X if ((mesgfp = fopen(mail,"r")) == NULL) /* cannot open existing file */
X exit(E_SYSFAIL);
X
X strcpy(from,"Somewhere"); /* default originator */
X
X /*
X * Some mailers generate real headers, separated from the message
X * body by an empty line. So we stop when we find an empty line.
X * Other mailers have no headers, so we stop after HLEN lines.
X * The following algorithm tries to extract the real user name
X * if possible, otherwise it takes whatever it can get.
X */
X
X for (n = 0; n < HLEN && fgets(line,BUFSIZ,mesgfp) && *line != '\n'; n++) {
X if (sscanf(line,"From: %*s ( %[^)] )",from) == 1)
X break;
X if (sscanf(line,"From: %s",from) == 1)
X break;
X sscanf(line,"%*[>] From %s",from) || sscanf(line,"From %s",from);
X }
X
X /* carefully check all went well */
X
X if (ferror(mesgfp)) /* sorry, read problem */
X exit(E_READERR);
X if ((metafp = fopen(meta,"w")) == NULL) /* cannot create metafile */
X exit(E_WRITERR);
X fprintf(metafp,"%s\n",from); /* write originator */
X if (ferror(metafp)) {
X fclose(metafp); /* ms-dog needs this! */
X chmod(meta,0666); /* sorry, write problem */
X unlink(meta); /* delete metafile */
X exit(E_WRITERR);
X }
X fclose(mesgfp);
X fclose(metafp);
X}
X
X/* usage - explain what is wrong */
X
Xhidden void usage(str)
Xchar *str;
X{
X fprintf(stderr,"%s\nusage: rmail [-d debugging_level]\n",str);
X exit(2);
X}
END_OF_rmail.c
if test 6168 -ne `wc -c <rmail.c`; then
echo shar: \"rmail.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f startup.c -a "${1}" != "-c" ; then
echo shar: Will not over-write existing file \"startup.c\"
else
echo shar: Extracting \"startup.c\" \(6331 characters\)
sed "s/^X//" >startup.c <<'END_OF_startup.c'
X/*++
X/* NAME
X/* startup 3
X/* SUMMARY
X/* startup/terminate network protocol
X/* PROJECT
X/* pc-mail
X/* PACKAGE
X/* cico
X/* SYNOPSIS
X/* startproto()
X/*
X/* endproto()
X/* DESCRIPTION
X/* startproto() should be called after a successfull login on a remote
X/* host. It performs the primary handshake with the other system
X/* (call accepted/locked) and negotiates a communications protocol.
X/* It then sets the function pointers Close/Read/Write to the
X/* appropriate values. Until endproto() is called, all i/o to the
X/* remote host should proceed through the functions pointed to by
X/* Read/Write.
X/*
X/* endproto() turns the protocol off, and sends the silly "OO" message
X/* to the remote system. It does not disconnect, nor does it change
X/* the state of the communications port.
X/* FUNCTIONS AND MACROS
X/* xgetc(), xwrite(), trap()
X/* DIAGNOSTICS
X/* The process of negotiation is shown when debugging is enabled.
X/* startproto() and endproto() return 0 in case of success, E_LOST
X/* if no response arrived and E_REJECT if the response differed
X/* from the expected response.
X/* BUGS
X/* startproto() assumes that the local system is the calling system.
X/* AUTHOR(S)
X/* W.Z. Venema
X/* Eindhoven University of Technology
X/* Department of Mathematics and Computer Science
X/* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
X/* CREATION DATE
X/* Fri Mar 27 13:43:00 GMT+1:00 1987
X/* LAST MODIFICATION
X/* Wed Apr 6 00:22:51 MET 1988
X/* VERSION/RELEASE
X/* 1.4
X/*--*/
X
X#include <setjmp.h>
X#include "defs.h"
X#include "params.h"
X#include "comm.h"
X#include "logs.h"
X#include "status.h"
X#include "sysdep.h"
X
X/* forward declarations */
X
Xhidden char *xpct(); /* expect a string */
Xhidden char *send(); /* send a string */
X
X/* the functions that inplement the various protocols */
X
Xextern kopen(),kclose(),kread(),kwrite(); /* k protocol */
Xextern gopen(),gclose(),gread(),gwrite(); /* g protocol */
X
Xtypedef struct proto {
X char name; /* name of the protocol */
X int (*open)(); /* the open function */
X int (*close)(); /* the close function */
X int (*read)(); /* the read function */
X int (*write)(); /* the write function */
X};
X
X/* the order of protocols is significant! */
X
Xhidden struct proto ptable[] = {
X 'k', kopen, kclose, kread, kwrite, /* try this first */
X 'g', gopen, gclose, gread, gwrite, /* then this one */
X /* add your protocols at the appropriate place */
X 0, /* terminator! */
X};
X
X/* startproto - do primary handshake, establish protocol and turn it on */
X
Xpublic startproto()
X{
X int *savetrap = systrap;
X jmp_buf mytrap;
X register struct proto *pp;
X register char *cp;
X int status;
X
X if (status = setjmp(systrap = mytrap)) { /* get here if expect fails */
X systrap = savetrap;
X return(status);
X }
X
X /* the primary handshake: who are we and is it ok we call right now */
X
X sscanf(xpct("Shere"),"Shere=%s",rmthost); /* try to get host name */
X log("SUCCEEDED (call to %s)",rmthost);
X send(strcons("S%s -x%d",LOGIN_NAME,MAX(dflag,1))); /* name + debug level */
X xpct("ROK"); /* we're accepted or rejected */
X
X /* choose a protocol from the list offered by the other side */
X
X for (cp = xpct("P")+1,pp = ptable; pp->name && !index(cp,pp->name); pp++)
X /* void */ ;
X if (pp->name == 0) { /* no common protocol */
X send("N");
X trap(E_REJECT,"FAILED (no common protocol in \"%s\")",cp);
X /* NOTREACHED */
X }
X send(strcons("U%c",pp->name)); /* my choice of protocol */
X
X /* install protocol */
X
X Close = pp->close; /* for endproto() */
X Read = pp->read;
X Write = pp->write;
X if (pp->open && CALL(pp->open)(ttfd)) /* start up a protocol */
X trap(E_LOST,"FAILED (startup)");
X
X log("OK (startup)");
X systrap = savetrap; /* get here if expect wins */
X return(0);
X}
X
X/* endproto - terminate protocol */
X
Xpublic endproto()
X{
X int *savetrap = systrap;
X jmp_buf mytrap;
X int status;
X
X if (status = setjmp(systrap = mytrap)) { /* get here if expect fails */
X systrap = savetrap;
X return(status);
X }
X if (Close) /* check there is one */
X CALL(Close)(ttfd); /* turn protocol off */
X send("OOOOOO"); /* byebye */
X xpct("OO"); /* bye */
X log("OK (conversation complete)");
X
X systrap = savetrap; /* get here if expect wins */
X return(0);
X}
X
X/* send - write message to remote host and return pointer to message */
X
Xhidden char *send(str)
Xchar *str;
X{
X xwrite(ttfd,"\020",1); /* message header */
X xwrite(ttfd,str,strlen(str)+1); /* include trailing null */
X debug(4)("send: %S\n",str);
X return(str); /* return the message */
X}
X
X/* xpct - read message from host in "^Pmessage[\0\n]" format; trap on errors */
X
Xhidden char *xpct(pat)
Xchar *pat;
X{
X register int c;
X register char *p = msgin;
X register int inmsg = 0;
X
X /*
X * Keep reading until we time out, the buffer is full, or until a
X * complete message has been received. Consider the link as lost
X * in case of time out or buffer overflow. Assume we are rejected
X * if the received message differs from what was expected.
X */
X
X while (p < msgin+MSGBUF && (c = xgetc()) != EOF) {
X if ((c &= 0177) == '\020') { /* got start of message */
X debug(4)(" got sync\n");
X p = msgin; /* clear msg buffer */
X inmsg = 1;
X } else if (inmsg == 0 || (*p++ = (c == '\n' ? 0 : c))) {
X debug(4)("%C",c);
X } else { /* message completed */
X debug(4)("\n");
X if (strncmp(pat,msgin,strlen(pat))) /* compare prefix only */
X break;
X return(msgin);
X }
X }
X trap((c == EOF || p >= msgin+MSGBUF ? E_LOST : E_REJECT),
X "FAILED (%s)",msgin);
X /* NOTREACHED */
X}
END_OF_startup.c
if test 6331 -ne `wc -c <startup.c`; then
echo shar: \"startup.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of archive 4 \(of 8\).
cp /dev/null ark4isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 8 archives.
rm -f ark[1-9]isdone
else
echo You still need to unpack the following archives:
echo " " ${MISSING}
fi
## End of shell archive.
exit 0
--
uucp: mcvax!eutrc3!wswietse | Eindhoven University of Technology
bitnet: wswietse at heithe5 | Dept. of Mathematics and Computer Science
surf: tuerc5::wswietse | Eindhoven, The Netherlands.
More information about the Comp.sources.misc
mailing list