home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-01-24 | 63.1 KB | 2,275 lines |
- Newsgroups: comp.sources.misc
- subject: v10i038: PC-MAIL release 2, 6/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 38
- Submitted-by: wswietse@lso.win.tue.nl (Wietse Venema)
- Archive-name: pcmail2/part06
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 6 (of 11)."
- # Contents: main/connect.c main/email.c main/gmail.c main/gphys.c
- # main/gpres.c main/mbox.c main/nmail.c main/startup.c main/str.c
- # Wrapped by wswietse@tuewsa on Mon Jan 22 17:27:18 1990
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f main/connect.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"main/connect.c\"
- else
- echo shar: Extracting \"main/connect.c\" \(6857 characters\)
- sed "s/^X//" >main/connect.c <<'END_OF_main/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 UUCP-like send/expect script facility is used. Thus a login
- X/* sequence might look like:
- X/*
- X/* send expect send expect ...
- X/*
- X/* The program will send the first "send" string, then expect the
- X/* first "expect" string, and so on.
- X/*
- X/* Alternative expect/send sequences can be specified in the usual manner:
- X/*
- X/* expect-send-expect-send-expect...
- X/*
- X/* If the first expect string fails, the alternative send string is
- X/* transmitted and the alternative expect is tried, and so on, until
- X/* an expect string succeeds, or until the list of alternatives is
- X/* exhausted.
- X/*
- X/* After the dial-up script has completed the program
- X/* proceeds with the following build-in send/expect sequence:
- X/*
- X/* ogin: your_login_name\\r ssword: your_password\\r
- 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/* .fi
- X/*
- X/* In addition, the following "send" strings are given special
- X/* treatment:
- X/*
- X/* .nf
- X/* BREAK send a null character
- X/* EOT send Control-D
- X/* FUNCTIONS AND MACROS
- X/* xwrite(), xgetc(), trap(), debug(4)(), log(), split()
- 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/* 90/01/22 13:01:26
- X/* VERSION/RELEASE
- X/* 2.1
- X/*--*/
- X
- X#include <stdio.h>
- X#include <setjmp.h>
- X#include <ctype.h>
- X
- 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 with 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 char *seq = DIAL_SEQUENCE;
- 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 /* optional dial-up sequence */
- X
- X for (cp = split(&seq, blnk); cp; cp = split(&seq, blnk)) {
- X conn_send(escape(cp));
- X if (cp = split(&seq, blnk))
- X conn_xpct(escape(cp));
- X }
- X
- X /* mandatory login sequence; hack this for non-UNIX hosts */
- 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 - send BREAK, EOT or string literal */
- X
- Xhidden void conn_send(s)
- Xregister char *s;
- X{
- X static char null = '\0';
- X static char eot = '\04';
- X
- X sleep(1);
- X
- X if (*s) {
- X debug(4) ("Sending: %S\n", s);
- X if (strcmp(s, "BREAK") == 0) {
- X xwrite(ttfd, &null, 1);
- X } else if (strcmp(s, "EOT") == 0) {
- X xwrite(ttfd, &eot, 1);
- X } else {
- X while (*s) {
- X delay();
- X xwrite(ttfd, s++, 1);
- X }
- X }
- X }
- X}
- X
- X/* conn_xpct - pattern matching without meta characters */
- X
- Xhidden void conn_xpct(s)
- Xchar *s;
- X{
- X int c;
- X int i;
- X int n;
- X char *xp;
- X char *sp;
- X
- X /*
- X * Keep listening until we time out or until we receive the expected
- X * string (thus, if the other end keeps sending garbage we will never
- X * terminate). Make sure that we do not overrun our buffer. Parity bits
- X * are ignored. If we do not succeed, try alternative sequences if they
- X * are specified.
- X */
- X
- X for (xp = split(&s, "-"); xp; xp = split(&s, "-")) {
- X
- X debug(4) ("Expecting: %S\nReceiving: ", xp);
- X
- X if (((n = strlen(xp)) > MSGBUF))
- X n = MSGBUF;
- X for (i = 0; (c = xgetc()) != EOF; /* void */ ) {
- X msgin[i++] = (c &= 0177);
- X debug(4) ("%C", c);
- X if (i >= n && strncmp(xp, &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
- X /* try alternative sequence, if specified, else fail */
- X
- X if (sp = split(&s, "-")) {
- X conn_send(sp);
- X } else {
- X trap(E_NOLINE, "LOGIN FAILED (at \"%S\")", xp);
- X }
- X }
- X}
- X
- X/* escape - interpret backslash sequences */
- X
- Xhidden char *escape(s)
- Xregister char *s;
- X{
- X static char buf[BUFSIZ];
- X register char *cp = buf;
- X register char ch;
- X int c;
- X int i;
- X
- X while (*s && cp < buf + sizeof(buf) - 1) { /* don't overflow the buffer */
- X
- X if (*s != '\\') { /* ordinary character */
- X *cp++ = *s++;
- X } else if (isdigit(*++s) && *s < '8') { /* \nnn octal code */
- 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_main/connect.c
- if test 6857 -ne `wc -c <main/connect.c`; then
- echo shar: \"main/connect.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f main/email.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"main/email.c\"
- else
- echo shar: Extracting \"main/email.c\" \(6160 characters\)
- sed "s/^X//" >main/email.c <<'END_OF_main/email.c'
- X/*++
- X/* NAME
- X/* email 3
- X/* SUMMARY
- X/* manipulate one message in preparation
- X/* PROJECT
- X/* pc-mail
- X/* PACKAGE
- X/* mail
- X/* SYNOPSIS
- X/* #include "mail.h"
- X/*
- X/* int work()
- X/*
- X/* int work_disp(def_addr)
- X/* char *def_addr;
- X/* DESCRIPTION
- X/* The functions in this module are responsible for manipulations
- X/* on mail messages in preparation.
- X/*
- X/* work() should be invoked when the user has selected an existing
- X/* message in preparation. It does some initializations and invokes
- X/* the work_disp() function.
- X/*
- X/* work_disp() allows the user to specify the disposition of a
- X/* mail message in preparation. It should be used after the user has
- X/* created a message, or after the user has selected a message in
- X/* preparation.
- X/*
- X/* The message file is displayed on the screen and user the
- X/* can choose to print, mail, edit or delete etc. the message.
- X/*
- X/* The def_addr argument contains a default mail destination: for example,
- X/* an address extracted from a message being replied to. It should be an
- X/* e-mail address or an empty string.
- X/*
- X/* The code in this module is a little tricky, to avoid "orphan" work
- X/* files (message file without a metafile).
- X/* COMMANDS
- X/* The program specified in the EDITOR environment variable,
- X/* or a system-dependent default.
- X/* FILES
- X/* mail.msg, file being edited in the 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/* 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/* 90/01/22 13:01:35
- X/* VERSION/RELEASE
- X/* 2.1
- X/*--*/
- X
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X
- X#include <errno.h>
- X#include "defs.h"
- X#include "path.h"
- X#include "pager.h"
- X#include "screen.h"
- X#include "mail.h"
- X#include "status.h"
- X
- X/* forward declarations */
- X
- Xhidden void junk_work();
- Xhidden int edit_work();
- Xhidden int show_work();
- Xhidden int hold_work();
- Xhidden int send_work();
- Xhidden int queue_work();
- X
- Xpublic char address[MAXLINE]; /* default destination */
- Xhidden File *workfile = 0; /* pager file */
- X
- X/* work - user selected message in preparation */
- X
- Xpublic int work()
- X{
- X return (work_disp(""));
- X}
- X
- X/* work_disp - ask disposition of a message in preparation */
- X
- Xpublic int work_disp(def_addr)
- Xchar *def_addr;
- X{
- X static Screen screen[] = {
- X 'C', "Close",hold_work,"Send message later, return to message-selection menu",
- X#ifdef ATTACH
- X 'A', "Attach",attach", "Attach file to message",
- X#endif
- 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 strcpy(address, def_addr); /* set up default address */
- 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 message in preparation or error message in middle window */
- X
- Xhidden int show_work()
- X{
- X if (workfile) { /* check pager file exists */
- X set_pager(workfile); /* select existing display */
- X } else if (rd_pager(workfile = open_pager(), message)) {
- 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 message in preparation 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 a message in preparation */
- X
- Xhidden int edit_work()
- X{
- X register int stat;
- X
- X if (stat = edit(message, MAILFILE)) /* try to edit the message */
- X errdisp(stat); /* edit() had a problem */
- X junk_work(); /* force new message display */
- X return (S_REDRAW); /* say screen has changed */
- X}
- X
- Xhidden int label_work();
- X
- X/* hold_work - stop editing but do not yet mail a message in preparation */
- 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 does not yet want to send the message off. The purpose of the
- X * following code is to ask for a one-line summary, but only if such a
- X * comment does not yet exist. The summary is used to identify the
- X * message in preparation in the message- selection display.
- X */
- X
- X if (stat(message, &s) || !stat(comment, &s)) {
- 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(comment, string, (char *) 0)) {
- 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 message in preparation, ask for destination */
- X
- Xhidden int send_work()
- X{
- X static Screen screen[] = {
- X EDIT, 0, queue_work, address,
- X 0, 0, when,
- X "Press ESC to cancel. Send message to:",
- X };
- X
- X return (kbdinp(screen) | S_REDRAW);
- X}
- X
- X/* queue_work - spool mail, delete message in preparation 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_main/email.c
- if test 6160 -ne `wc -c <main/email.c`; then
- echo shar: \"main/email.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f main/gmail.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"main/gmail.c\"
- else
- echo shar: Extracting \"main/gmail.c\" \(6153 characters\)
- sed "s/^X//" >main/gmail.c <<'END_OF_main/gmail.c'
- X/*++
- X/* NAME
- X/* gmail 1
- X/* SUMMARY
- X/* deliver unsent mail via gnuucp
- X/* PROJECT
- X/* pc-mail
- X/* PACKAGE
- X/* gnu
- X/* SYNOPSIS
- X/* gmail [-d debuglevel]
- X/* DESCRIPTION
- X/* This program replaces the sending function of the pc-mail "cico"
- X/* program, on systems that use GNUUCP for message transport.
- X/*
- X/* gmail searches the pc-mail message data base for unsent mail
- X/* (with the "Out" status) and queues it for transmission via GNUUCP.
- X/* When a message has been queued it is renamed to reflect
- X/* the "Sent" status.
- X/*
- X/* This program is intended to be called via the MAILCMD environment
- X/* variable, so that it is invoked upon exit from the mail user
- X/* interface program.
- X/*
- X/* In order to avoid corruption of the message data base, control-c
- X/* interrupts are disabled while this program executes.
- X/* ENVIRONMENT
- X/* MAILDIR, path to pc-mail message data base
- X/* COMMANDS
- X/* rmail, the gnuucp mailer
- X/* FILES
- X/* In the spool directory:
- X/* d<seqno> unsent mail, message body
- X/* x<seqno> unsent mail, destination and subject
- X/* q<seqno> sent mail, message body
- X/* r<seqno> sent mail, destination and subject
- X/* SEE ALSO
- X/* path(5) spool directory, file name formats
- X/* DIAGNOSTICS
- X/* Problems are reported on the standard error output, and cause the
- X/* program to terminate with a nonzero exit status.
- X/* BUGS
- X/* It is left up to GNUUCP to determine what to do with undeliverable mail.
- X/* AUTHOR(S)
- X/* W.Z. Venema
- X/* Eindhoven University of Technology
- X/* Department of Mathematics and Computer Science
- X/* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
- X/* CREATION DATE
- X/* Wed Jan 3 22:16:28 MET 1990
- X/* LAST MODIFICATION
- X/* 90/01/22 13:01:40
- X/* VERSION/RELEASE
- X/* 2.1
- X/*--*/
- X
- X#include <stdio.h>
- X#include <signal.h>
- X#include <time.h>
- X#include <varargs.h>
- X
- X#include "defs.h"
- X#include "ndir.h"
- X#include "path.h"
- X
- X#ifndef RMAIL
- X#define RMAIL "rmail"
- X#endif
- X
- X/* Forward declarations */
- X
- Xhidden char *get_dest();
- Xhidden int uuqueue();
- Xhidden void error();
- Xhidden void frename();
- Xhidden void parse_args();
- Xhidden void scanmail();
- Xhidden void usage();
- X
- X#define debug if (dflag) (void) printf
- X
- Xhidden int dflag = 0; /* debugging option */
- X
- Xpublic char *progname = "gmail"; /* for diagnostics */
- X
- X/* .. */
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar **argv;
- X{
- X (void) signal(SIGINT, SIG_IGN); /* disable ctrl-c */
- X if (pathinit()) /* get path info */
- X error("no mail directory or MAILDIR environment variable not set");
- X parse_args(argc, argv); /* parse command args */
- X scanmail(); /* search for unsent 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 dflag++;
- X break;
- X default: /* unknown option */
- X usage("invalid option: -%c", **argv);
- X break;
- X }
- X }
- X
- X /* check for extraneous arguments */
- X
- X if (argc > 0)
- X usage("unexpected argument: %s", *argv);
- X}
- X
- X/* scan for unsent mail */
- X
- Xhidden void scanmail()
- X{
- X unsigned msgno; /* message sequence number */
- X register DIR *dp;
- X struct direct *de;
- X char *dest;
- X
- X debug("directory: \"%s\"\n", maildir);
- X
- X /*
- X * Scan the spool directory for unsent mail. After the message has been
- X * piped through rmail, rename it to reflect the "Sent" status. Do not give
- X * up if a file cannot be opened; just proceed with the next message.
- X */
- X
- X if ((dp = opendir(maildir)) == 0)
- X error("cannot read the mail directory: %s", maildir);
- X
- X while (de = readdir(dp)) {
- X debug("file: \"%s\"\n", de->d_name);
- X if (de->d_name[0] == OUT_META && (msgno = seqno(de->d_name))
- X && (dest = get_dest(msgno)) && uuqueue(msgno, dest)) {
- X frename(out_mesg(msgno), sent_mesg(msgno));
- X frename(out_meta(msgno), sent_meta(msgno));
- X }
- X }
- X closedir(dp);
- X}
- X
- X/* uuqueue - queue one message */
- X
- Xhidden int uuqueue(msgno, dest)
- Xunsigned msgno;
- Xchar *dest;
- X{
- X char cmd[BUFSIZ];
- X char *path;
- X char *rcpt;
- X static char sep[] = " \t\r\n";
- X
- X if (access(path = out_mesg(msgno), 04)) {
- X debug("%s: cannot read message file: %s\n", path, sys_errlist[errno]);
- X return (0);
- X } else {
- X
- X /*
- X * The GNUUCP rmail program has to invoked for each recipient. rmail
- X * will have to deal with undeliverable mail anyway, so we ignore
- X * that class of errors.
- X */
- X
- X for (rcpt = strtok(dest, sep); rcpt; rcpt = strtok((char *) 0, sep)) {
- X (void) sprintf(cmd, "%s %s <%s", RMAIL, rcpt, path);
- X debug("command: %s\n", cmd);
- X if (system(cmd) == 127)
- X error("could not invoke the shell");
- X }
- X return (1);
- X }
- X}
- X
- X/* get_dest - extract recipients */
- X
- Xhidden char *get_dest(msgno)
- Xunsigned msgno;
- X{
- X static char buf[MAXLINE];
- X FILE *fp;
- X char *ret;
- X char *path;
- X
- X if ((fp = fopen(path = out_meta(msgno), "r")) == 0) {
- X debug("%s: cannot open: %s\n", path, sys_errlist[errno]);
- X return (0);
- X } else {
- X if ((ret = fgets(buf, sizeof(buf), fp)) == 0)
- X debug("%s: no recipients found\n", path);
- X (void) fclose(fp);
- X return (ret);
- X }
- X}
- X
- X/* frename - forcibly change the name of a file */
- X
- Xhidden void frename(from, to)
- Xchar *from;
- Xchar *to;
- X{
- X debug("rename: %s -> %s\n", from, to);
- X
- X if (chmod(to, 0600) == 0)
- X (void) unlink(to);
- X if (rename(from, to))
- X error("cannot rename %s to %s: %s", from, to, sys_errlist[errno]);
- X}
- X
- X/* error - complain */
- X
- X/* VARARGS */
- X
- Xhidden void error(va_alist)
- Xva_dcl
- X{
- X va_list ap;
- X char *fmt;
- X
- X (void) fprintf(stderr, "%s: ", progname);
- X va_start(ap);
- X fmt = va_arg(ap, char *);
- X (void) vfprintf(stderr, fmt, ap);
- X va_end(ap);
- X (void) putc('\n', stderr);
- X exit(2);
- X}
- X
- X/* usage - explain what is wrong */
- X
- X/* VARARGS */
- X
- Xhidden void usage(va_alist)
- Xva_dcl
- X{
- X va_list ap;
- X char *fmt;
- X
- X (void) fprintf(stderr, "%s: ", progname);
- X va_start(ap);
- X fmt = va_arg(ap, char *);
- X (void) vfprintf(stderr, fmt, ap);
- X va_end(ap);
- X (void) fprintf(stderr, "\nusage: gmail [-d]\n");
- X exit(2);
- X}
- END_OF_main/gmail.c
- if test 6153 -ne `wc -c <main/gmail.c`; then
- echo shar: \"main/gmail.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f main/gphys.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"main/gphys.c\"
- else
- echo shar: Extracting \"main/gphys.c\" \(6844 characters\)
- sed "s/^X//" >main/gphys.c <<'END_OF_main/gphys.c'
- X/*++
- X/* NAME
- X/* gphys 3
- X/* SUMMARY
- X/* g protocol packet input/output
- X/* PROJECT
- X/* pc-mail
- X/* PACKAGE
- X/* cico
- X/* SYNOPSIS
- X/* #include "gp.h"
- X/*
- X/* void gsctrl(fd,c)
- X/* int fd,c;
- X/*
- X/* void gsdata(fd,pk,c)
- X/* int fd,c;
- X/* Packet *pk;
- X/*
- X/* int grpack(fd,pk)
- X/* int fd;
- X/* Packet *pk;
- X/* DESCRIPTION
- X/* The functions in this module send and receive packets. Interfacing
- X/* is based on Packet structures. Messages are interpreted elsewhere.
- X/*
- X/* gsctrl() sends a control packet to the remote receiver (no data
- X/* segment).
- X/*
- X/* gsdata() sends a data packet to the remote receiver.
- X/* The Packet structure is completed with a 16-bit checksum.
- X/* This function expects read/write sequence information in
- X/* the c parameter.
- X/*
- X/* grpack() receives a packet from the remote transmitter and checks
- X/* its integrity. It fills in the k, c, len and check fields of the
- X/* Packet structure and returns the type of message (DATA, SHORT,
- X/* CLOSE, RJ, RR, etcetera).
- X/* DIAGNOSTICS
- X/* grpack() returns FAIL if a corrupted packet was received, and
- X/* TIME if no packet was received within the time-out interval.
- X/* BUGS
- X/* No data re-reading in case of transmission errors.
- 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 11:39:27 GMT+1:00 1987
- X/* LAST MODIFICATION
- X/* 90/01/22 13:01:42
- X/* VERSION/RELEASE
- X/* 2.1
- X/*--*/
- X
- X#include <signal.h>
- X#include <setjmp.h>
- X#include "gp.h"
- X
- X/* local and forward declarations */
- X
- Xstatic jmp_buf timebuf;
- Xstatic int chksum(),readhead(),readdata(),clkint();
- X
- X#define READ(fd,cp,n) { if (read(fd,cp,n) != n) clkint(); }
- X
- X/*
- X* "A six byte framing envelope is constructed using the control"
- X* "byte C of a packet and five other bytes as depicted below."
- X* <DLE><k><c0><c1><C><x>
- X* "The <DLE> symbol denotes the ASCII ctrl/P character. If the"
- X* "envelope is to be followed by a data segment, <k> has the"
- X* "value log2(size)-4; i.e. 1 <= k < 8. If k is 9, then the"
- X* "envelope represents a control packet. The <c0> and <c1>"
- X* "bytes are the low-order and high-order bytes respectively of"
- X* "0xAAA minus a 16-bit checksum. For control packets, this"
- X* "16-bit checksum is the same as the control byte C. For data"
- X* "packets, the checksum is calculated by the program below."
- X* "The <x> byte is the exclusive-or of <k><c0><c1><C>. Error"
- X* "control is accomplished by checking a received framing"
- X* "envelope for compliance with the definition, and comparing a"
- X* "checksum function of the data segment with <c0><c1>."
- X*/
- X
- X/* gsctrl - send control packet (no data segment) */
- X
- Xvoid gsctrl(fd,c)
- Xint fd,c;
- X{
- X char header[6];
- X register char chkhdr;
- X register char *cp = header;
- X int cksm = MAGIC-c; /* do checksum */
- X
- X *cp++ = CTRL('P'); /* start of header */
- X chkhdr = *cp++ = KCTRL; /* k byte (control) */
- X chkhdr ^= *cp++ = cksm; /* c0 byte (checksum lsb) */
- X chkhdr ^= *cp++ = cksm>>8; /* c1 byte (checksum msb) */
- X chkhdr ^= *cp++ = c; /* message|sequence info */
- X *cp = chkhdr; /* header checksum */
- X
- X write(fd,header,sizeof(header)); /* send header */
- X DEBUG(9,"xmt: %o\n",c&0377); /* show header */
- X}
- X
- X/* gsdata - send data packet */
- X
- Xvoid gsdata(fd,pk,c)
- Xint fd,c;
- Xregister Packet *pk;
- X{
- X char header[6];
- X register char chkhdr;
- X register char *cp = header;
- X int cval = pk->c|(c&077); /* fold in sequence info */
- X
- X pk->chk = MAGIC-(chksum(pk->data,pk->len)^(0377&cval));
- X
- X *cp++ = CTRL('P'); /* start of header */
- X chkhdr = *cp++ = pk->k; /* k byte (message length) */
- X chkhdr ^= *cp++ = pk->chk; /* c0 byte (checksum lsb) */
- X chkhdr ^= *cp++ = pk->chk>>8; /* c1 byte (checksum msb) */
- X chkhdr ^= *cp++ = cval; /* data|sequence info */
- X *cp = chkhdr; /* header checksum */
- X
- X write(fd,header,sizeof(header)); /* send header */
- X DEBUG(9,"xmt: %o\n",cval&0377); /* show header */
- X
- X write(fd,pk->data,pk->len); /* send data segment */
- X DEBUG(9,"xmt: data %d bytes\n",pk->segl); /* show data */
- X}
- X
- X/* grpack - receive one data or control packet; return packet type info */
- X
- Xint grpack(fd,pk)
- Xint fd;
- Xregister Packet *pk;
- X{
- X if (setjmp(timebuf)) /* in case we time out */
- X return(TIME); /* it just happened */
- X signal(SIGALRM,clkint); /* alarm clock response */
- X alarm(ALARM); /* set alarm clock */
- X
- X if (readhead(fd,pk)) { /* read packet header */
- X DEBUG(7,"rcv: bad header\n","");
- X alarm(0); /* turn timer off */
- X return(FAIL); /* header checksum error */
- X } else if (pk->k == KCTRL) {
- X alarm(0); /* turn timer off */
- X return(MESG(pk->c)); /* CLOSE | RJ | RR etcetera */
- X } else if (readdata(fd,pk)) {
- X DEBUG(7,"rcv: bad data\n","");
- X alarm(0); /* turn timer off */
- X return(FAIL); /* data checksum error */
- X } else {
- X alarm(0); /* turn timer off */
- X return(TYPE(pk->c)); /* DATA | SHORT */
- X }
- X}
- X
- X/* readhead - read header and check header checksum */
- X
- Xstatic int readhead(fd,pk)
- Xint fd;
- Xregister Packet *pk;
- X{
- X char header[5];
- X int ok;
- X register char chkhdr;
- X register char *cp = header;
- X
- X do { /* start reading */
- X READ(fd,cp,1); /* skip all garbage */
- X } while (*cp != CTRL('P')); /* up to packet header */
- X
- X READ(fd,header,sizeof(header)); /* read packet header */
- X
- X chkhdr = pk->k = *cp++; /* data length or control */
- X chkhdr ^= pk->chk = *cp++&0377; /* data checksum lsb */
- X chkhdr ^= *cp;
- X pk->chk |= (*cp++&0377)<<8; /* data checksum msb */
- X chkhdr ^= pk->c = *cp++; /* control packet or data */
- X if (ok = (chkhdr == *cp))
- X DEBUG(9,"rcv: %o\n",pk->c&0377);
- X return(!ok); /* check the checksum */
- X}
- X
- X/* readdata - read data segment and check data checksum */
- X
- Xstatic int readdata(fd,pk)
- Xint fd;
- Xregister Packet *pk;
- X{
- X if (seglen[pk->k] > pk->len) {
- X DEBUG(7,"rcv: data %d bytes too big\n",seglen[pk->k]);
- X return(1);
- X } else {
- X register int i;
- X DEBUG(9,"rcv: data %d bytes\n",pk->len = seglen[pk->k]);
- X for (i = 0; i < pk->len; i++) {
- X READ(fd,&pk->data[i],1);
- X }
- X return(pk->chk+(chksum(pk->data,pk->len)^(pk->c&0377)) != MAGIC);
- X }
- X}
- X
- X/* clkint - tiny time-out routine */
- X
- Xstatic int clkint()
- X{
- X DEBUG(9,"rcv: timed out\n","");
- X longjmp(timebuf,1);
- X /* NOTREACHED */
- X}
- X
- X/* chksum - unix packet driver checksum algorithm */
- X
- Xstatic int chksum(s,n)
- Xregister char *s;
- Xregister n;
- X{
- X register short sum;
- X register unsigned short t;
- X register short x;
- X
- X sum = -1;
- X x = 0;
- X do {
- X if (sum < 0) {
- X sum <<= 1;
- X sum++;
- X } else
- X sum <<= 1;
- X t = sum;
- X sum += (unsigned)*s++ & 0377;
- X x += sum ^ n;
- X if ((unsigned short)sum <= t) {
- X sum ^= x;
- X }
- X } while (--n > 0);
- X
- X return(sum);
- X}
- END_OF_main/gphys.c
- if test 6844 -ne `wc -c <main/gphys.c`; then
- echo shar: \"main/gphys.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f main/gpres.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"main/gpres.c\"
- else
- echo shar: Extracting \"main/gpres.c\" \(6380 characters\)
- sed "s/^X//" >main/gpres.c <<'END_OF_main/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/* 90/01/22 13:01:43
- X/* VERSION/RELEASE
- X/* 2.1
- 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_main/gpres.c
- if test 6380 -ne `wc -c <main/gpres.c`; then
- echo shar: \"main/gpres.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f main/mbox.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"main/mbox.c\"
- else
- echo shar: Extracting \"main/mbox.c\" \(6112 characters\)
- sed "s/^X//" >main/mbox.c <<'END_OF_main/mbox.c'
- X/*++
- X/* NAME
- X/* mbox 3
- X/* SUMMARY
- X/* display and manipulate one non-work message
- X/* PROJECT
- X/* pc-mail
- X/* PACKAGE
- X/* mail
- X/* SYNOPSIS
- X/* int mbox(meta,msgid)
- X/* int meta;
- X/* unsigned msgid;
- X/* DESCRIPTION
- X/* mbox() is invoked when the user has selected a non-work mail message.
- X/* It instructs the pager to display the selected mail message.
- X/* The user has the usual options for manipulating the message
- X/* being displayed.
- X/*
- X/* The meta parameter indicates the message type,
- X/* and msgid is the numerical message id. If the message file is being
- X/* read for the first time (meta == NEW_META), it will be marked as read
- X/* by renaming the meta file.
- X/*
- X/* Message header lines can be suppressed selectively (see setup).
- X/* FILES
- X/* $MAILDIR/?nnnnn, message and meta files
- X/* SEE ALSO
- X/* pager(3), pager(5), kbdinp(3)
- X/* DIAGNOSTICS
- X/* If a selected mail message could not be found an error message
- X/* is displayed instead.
- X/* AUTHOR(S)
- X/* W.Z. Venema
- X/* Eindhoven University of Technology
- X/* Department of Mathematics and Computer Science
- X/* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
- X/* CREATION DATE
- X/* Sun Apr 5 13:01:12 GMT+1:00 1987
- X/* LAST MODIFICATION
- X/* 90/01/22 13:02:11
- X/* VERSION/RELEASE
- X/* 2.1
- X/*--*/
- X
- X#include <stdio.h>
- X#include <ctype.h>
- X
- X#include "defs.h"
- X#include "path.h"
- X#include "pager.h"
- X#include "screen.h"
- X#include "mail.h"
- X#include "ascf.h"
- X#include "params.h"
- X#include "ms_parse.h"
- X
- X /*
- X * Storage for header lines to be ignored. Both the strings with header
- X * names, and the pointers to these strings, are kept together.
- X */
- X
- Xstruct ignore {
- X char strs[BUFSIZ]; /* null-terminated strings */
- X char *ptrs[BUFSIZ / 2]; /* null-terminated list of pointers */
- X};
- X
- Xhidden void ign_init(); /* forward declarations */
- Xhidden int ign_header();
- Xhidden int mbox_filter();
- X
- Xhidden File *letter = 0; /* pager file */
- X
- X/* show_letter - display selected mail message */
- X
- Xhidden int show_letter()
- X{
- X set_pager(letter); /* select message display */
- X ds_pager(); /* put it on the screen */
- X return (0); /* say screen is ok */
- X}
- X
- X/* mbox - user has selected a message file */
- X
- Xpublic int mbox(meta, id)
- Xint meta;
- Xunsigned id;
- X{
- X static Screen screen[] = {
- X 'C', "Close",0, initscreen,
- X 'D', "Delete",delete, delcurr,
- X 'M', "Mail", mailfile, "Mail a copy of this message",
- X 'P', "Print",print, printcurr,
- X 'R', "Reply",reply, "Create reply to sender",
- X 'S', "Save", save, "Save this message to ordinary file",
- X 'W', "Work", makework, "Save this message to work file",
- X '|', "|", filter, "Filter this message through command",
- X PGUP, PgUp, pu_pager, pageup,
- X PGDN, PgDn, pd_pager, pagedn,
- X UP, "Up", up_pager, csrup,
- X DOWN, "Down", dn_pager, csrdn,
- X 0, 0, show_letter, "(Reading a mail message)",
- X };
- X char *seen;
- X
- X /*
- X * Mail being read for the first time is renamed to reflect the
- X * status change.
- X */
- X
- X if (mbox_filter(letter = open_pager(), message)) {
- X mesg_pager(letter, m_msgread); /* no file or read error */
- X } else if (meta != NEW_META) { /* unread message? */
- X /* void */ ; /* no */
- X } else if (rename(comment, seen = old_meta(id)) == 0) {
- X strcpy(comment, seen); /* mark message as read */
- X junk_desk(); /* say desk-top outdated */
- X }
- X kbdinp(screen); /* look at the screen */
- X close_pager(letter), letter = 0; /* destroy the display */
- X return (S_REDRAW); /* force screen redrawing */
- X}
- X
- X/* mbox_filter - suppress some message-header lines */
- X
- Xhidden int mbox_filter(pp, path)
- XFile *pp;
- Xchar *path;
- X{
- X#if (defined(lint) && defined(iAPX286))
- X static
- X#endif
- X struct ignore ignore;
- X FILE *fp;
- X
- X if ((fp = ascopen(path, "r")) == 0) {
- X return (1);
- X } else {
- X char buf[BUFSIZ];
- X int ig_flag = 0;
- X int ret;
- X int context = MS_UUCP;
- X
- X ign_init(&ignore); /* initialize filter */
- X
- X /*
- X * The header-line suppression algorithm is effective for RFC822-like
- X * headers lines only. Its main use is to get rid of the "Received:"
- X * lines that frequently show up in non-local mail.
- X */
- X
- X while (ascgets(buf, sizeof(buf), fp)) {
- X switch (context = ms_parse(context, buf)) {
- X case MS_UUCP:
- X app_pager(pp, buf);
- X break;
- X case MS_HEADER:
- X if ((ig_flag = (ign_header(buf, &ignore))) == 0)
- X app_pager(pp, buf);
- X break;
- X case MS_CONT:
- X if (ig_flag == 0)
- X app_pager(pp, buf);
- X break;
- X case MS_BODY:
- X app_pager(pp, buf);
- X break;
- X }
- X }
- X ret = ferror(fp);
- X ascclose(fp);
- X return (ret);
- X }
- X}
- X
- X/* ign_init - setup header lines to be ignored */
- X
- Xhidden void ign_init(ig)
- Xstruct ignore *ig;
- X{
- X Info *ip = getparams() + P_IGNORE;/* what to ignore */
- X char *sp = ":, "; /* string separators */
- X char **lp = ig->ptrs; /* separated strings */
- X
- X /*
- X * This function takes, from the pc-mail setup file, a (blank or
- X * comma)-separated list with names of mail headers to be ignored when a
- X * message is displayed. The list of names is broken up into separate
- X * strings. The result, a null-terminated list of string pointers, is
- X * stored in the ig argument. We use strtok() for string splitting. Since
- X * that function destroys its input, and since the user may change the
- X * setup at any time, we keep in the ig argument a copy of the relevant
- X * setup information.
- X */
- X
- X if (ip->strval == 0) { /* nothing to ignore */
- X *lp = 0;
- X } else { /* copy, then split */
- X (void) strncpy(ig->strs, ip->strval, sizeof(ig->strs));
- X for (*lp = strtok(ig->strs, sp); *lp; *lp = strtok((char *) 0, sp))
- X lp++;
- X }
- X}
- X
- X/* ign_header - do we ignore this header line */
- X
- Xhidden int ign_header(buf, ig)
- Xregister char *buf;
- Xstruct ignore *ig;
- X{
- X register int l; /* header name length */
- X register char **list; /* ptr to ignored header names */
- X
- X /* Make sure that the header name is followed by a colon */
- X
- X for (list = ig->ptrs; *list; list++) {
- X if (buf[l = strlen(*list)] == ':' && istrncmp(buf, *list, l) == 0)
- X return (1);
- X }
- X return (0);
- X}
- END_OF_main/mbox.c
- if test 6112 -ne `wc -c <main/mbox.c`; then
- echo shar: \"main/mbox.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f main/nmail.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"main/nmail.c\"
- else
- echo shar: Extracting \"main/nmail.c\" \(6579 characters\)
- sed "s/^X//" >main/nmail.c <<'END_OF_main/nmail.c'
- X/*++
- X/* NAME
- X/* nmail
- X/* SUMMARY
- X/* extract originator and subject from new mail received by cico
- X/* PROJECT
- X/* pc-mail
- X/* PACKAGE
- X/* nmail
- X/* SYNOPSIS
- X/* nmail [-d debuglevel]
- X/* DESCRIPTION
- X/* nmail searches for new mail files received by cico and extracts
- X/* the originator's name, and message subject for later use by the
- X/* mail visual shell.
- X/*
- X/* Return address formats we understand (in order of preference):
- X/* .nf
- X/*
- X/* From: address (full_name) (take full_name)
- X/* From: full_name <address> (take full_name)
- X/* From: address (take address)
- X/* >From address (take address)
- X/* From address (take address)
- 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/* while this program executes.
- X/* FILES
- X/* In the spool directory:
- X/* n<seqno> received mail message
- X/* h<seqno> extracted originator name, subject
- X/* SEE ALSO
- X/* path(5) spool directory, file names
- X/* cico(1) network process
- X/* mail(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/* 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/* 90/01/22 13:02:20
- X/* VERSION/RELEASE
- X/* 2.1
- X/*--*/
- X
- X#include <stdio.h>
- X#include <signal.h>
- X#include <time.h>
- X#include <ctype.h>
- X#include <varargs.h>
- X
- X#include "defs.h"
- X#include "ndir.h"
- X#include "path.h"
- X#include "status.h"
- X#include "ms_parse.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
- Xhidden int dflag = 0; /* debugging option */
- X
- X#define debug if (dflag) printf
- X
- Xpublic char *progname = "nmail";
- 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 if (pathinit()) /* get path info */
- X exit(E_NOSPOOL); /* bad MAILDIR variable */
- 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 if ((dflag = atoi(*++argv)) < 0 || dflag > 9)
- X dflag = 0;
- X break;
- X default: /* unknown option */
- X usage("invalid option: -%c", **argv);
- X break;
- X }
- X }
- X
- X /* check for extraneous arguments */
- X
- X if (argc > 0)
- X usage("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 DIR *dp;
- X struct direct *de;
- X unsigned msgno;
- X
- X debug("directory: \"%s\"\n", maildir);
- X
- X /*
- X * Scan the spool directory for newly-arrived mail.
- X *
- X * Incoming mail message files have a name of "n<seqno>". The originator
- X * name is normally present in files with names "h<seqno>" or "o<seqno>".
- X * The presence of an "o" file implies that the file "n<seqno>" has been
- X * read by the user. An "h" file means that the user has not yet read the
- X * message file.
- X *
- X * If a message file has no corresponding "h" or "o" file we assume it is a
- X * new mail message and create an "h" file with the name of the
- X * originator and the subject of the message.
- X */
- X
- X if ((dp = opendir(maildir)) == 0)
- X exit(E_NOSPOOL);
- X
- X while (de = readdir(dp)) {
- X debug("nmail: file \"%s\"\n", de->d_name);
- X if (de->d_name[0] == NEW_MESG
- X && (msgno = seqno(de->d_name))) {
- X if (access(old_meta(msgno), 4) == 0) {
- X /* already marked as read */ ;
- X } else if (access(new_meta(msgno), 4) == 0) {
- X /* already marked as unread */ ;
- X } else { /* create meta file */
- X extract(new_mesg(msgno), new_meta(msgno));
- X }
- X }
- X }
- X closedir(dp);
- X}
- X
- X/* extract - extract originator and subject info from mail file to meta file */
- X
- Xhidden void extract(mail, meta)
- Xchar *mail;
- Xchar *meta;
- X{
- X FILE *mesgfp,
- X *metafp;
- X char line[MAXLINE];
- X char from[MAXLINE]; /* name of sender */
- X char subj[MAXLINE]; /* message subject */
- X int context = MS_UUCP;
- 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 subj[0] = '\0'; /* initialize subject */
- X
- X /*
- X * Some mailers generate real headers, separated from the message body by
- X * an empty line. So we stop when we find an empty line. Other mailers
- X * have no headers, so we stop when we see no header line. The following
- X * algorithm tries to extract the real user name if possible, otherwise
- X * it takes whatever it can get.
- X */
- X
- X while ((context != MS_BODY) && fgets(line, sizeof(line), mesgfp)) {
- X switch (context = ms_parse(context, line)) {
- X case MS_UUCP:
- X if (sscanf(line, "%*[>] From %s", from) != 1)
- X (void) sscanf(line, "From %s", from);
- X break;
- X case MS_HEADER:
- X if (hscanf(line, "Subject:", " %[^\n]", subj) == 0
- X && hscanf(line, "From:", " %*s ( %[^)] )", from) == 0)
- X (void) hscanf(line, "From:", " %[^<] <", from);
- X break;
- X }
- 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%s\n", from, subj); /* write originator, subject */
- X if (ferror(metafp)) {
- X (void) fclose(metafp); /* ms-dog needs this! */
- X (void) chmod(meta, 0666); /* sorry, write problem */
- X (void) unlink(meta); /* delete metafile */
- X exit(E_WRITERR);
- X }
- X (void) fclose(mesgfp);
- X (void) fclose(metafp);
- X}
- X
- X/* usage - explain what is wrong */
- X
- X/* VARARGS */
- X
- Xhidden void usage(va_alist)
- Xva_dcl
- X{
- X va_list ap;
- X char *fmt;
- X
- X va_start(ap);
- X fmt = va_arg(ap, char *);
- X vfprintf(stderr, fmt, ap);
- X va_end(ap);
- X fprintf(stderr, "\nusage: nmail [-d debugging_level]\n");
- X exit(2);
- X}
- END_OF_main/nmail.c
- if test 6579 -ne `wc -c <main/nmail.c`; then
- echo shar: \"main/nmail.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f main/startup.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"main/startup.c\"
- else
- echo shar: Extracting \"main/startup.c\" \(6115 characters\)
- sed "s/^X//" >main/startup.c <<'END_OF_main/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/* 90/01/22 13:02:41
- X/* VERSION/RELEASE
- X/* 2.1
- X/*--*/
- X
- X#include <stdio.h>
- X#include <setjmp.h>
- X
- 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 ptbl[] = {
- 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 /* 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
- X /* some uucico implementations seem to have problems with debug level 0 */
- X
- X send(strcons("S%s -x%d", LOGIN_NAME, MAX(dflag, 1)));
- 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 = ptbl; pp->name && !index(cp, pp->name); pp++)
- X /* void */ ;
- X if (pp->name == 0) { /* no common protocol */
- X send("UN");
- 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 /* finish up */
- 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; /* save exception handler */
- X jmp_buf mytrap;
- X int status;
- X
- X if (Close) /* check there is one */
- X CALL(Close) (ttfd); /* turn protocol off */
- X send("OOOOOO"); /* byebye */
- X
- X /* Don\'t wait for the other side\'s OOOOOO, just sleep and quit. */
- X
- X (void) sleep(1);
- X log("OK (conversation complete)");
- 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, or until a complete message has been
- X * received. Consider the link as lost in case of time out. Assume we are
- X * rejected if the received message differs from what was expected.
- X */
- X
- X debug(4) ("xpct: %S\n", pat);
- X
- X for (;;) {
- X if ((c = xgetc()) == EOF) {
- X trap(E_LOST, "FAILED (protocol handshake)");
- X /* NOTREACHED */
- X } else if ((c &= 0177) == '\020') {
- X debug(4) (" got sync\n"); /* got start of message */
- X p = msgin; /* reset */
- X inmsg = 1;
- X } else if (inmsg == 0) {
- X debug(4) ("%C", c); /* don\'t store, just debug */
- X } else if (*p++ = ((c == '\n') ? '\0' : c)) {
- X debug(4) ("%C", c); /* store and debug */
- X if (p >= msgin + MSGBUF) { /* spurious Ctrl-P seen? */
- X p = msgin; /* reset */
- X inmsg = 0; /* reset */
- X }
- X } else if ((debug(4) ("\n")), strncmp(pat, msgin, strlen(pat)) == 0) {
- X return (msgin); /* expect succeeded */
- X } else {
- X msgin[30] = '\0'; /* truncate to 30 */
- X trap(E_REJECT, "FAILED (%S)", msgin);
- X /* NOTREACHED */
- X }
- X }
- X}
- END_OF_main/startup.c
- if test 6115 -ne `wc -c <main/startup.c`; then
- echo shar: \"main/startup.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- if test -f main/str.c -a "${1}" != "-c" ; then
- echo shar: Will not over-write existing file \"main/str.c\"
- else
- echo shar: Extracting \"main/str.c\" \(6415 characters\)
- sed "s/^X//" >main/str.c <<'END_OF_main/str.c'
- X/*++
- X/* NAME
- X/* strcons,istrcmp,strvec,vecstr,split 3
- X/* SUMMARY
- X/* string utility routines
- X/* PROJECT
- X/* pc-mail
- X/* PACKAGE
- X/* general stuff
- X/* SYNOPSIS
- X/* #include "defs.h"
- X/*
- X/* char *strcons(format,args)
- X/* char *format;
- X/*
- X/* char *split(cpp, sep)
- X/* char **cpp;
- X/* char *sep;
- X/*
- X/* int istrncmp(s1,s2,n)
- X/* char *s1,s2;
- X/* int n;
- X/*
- X/* int istrcmp(s1,s2)
- X/* char *s1,s2;
- X/*
- X/* char **strvec(string,separ)
- X/* char *string;
- X/* char *separ;
- X/*
- X/* freevec(vec)
- X/* char **vec;
- X/*
- X/* char *vecstr(vector,separ)
- X/* char **vector;
- X/* char *separ;
- X/* DESCRIPTION
- X/* strcons() produces a formatted string, using printf()-like
- X/* arguments. Basically it is an sprintf() that returns a
- X/* pointer to the result. memory for the result is taken from
- X/* a small memory pool that is recycled upon successive calls.
- X/*
- X/* split() searches the string pointed to by cpp for the occurrance
- X/* of the text token (a string not containing any of the characters
- X/* given in the "sep" argument). *cpp is updated if a token is
- X/* found; a null pointer is returned otherwise. This function
- X/* is an attempt to improve upon the strtok() function, which
- X/* can parse only one string at a time. It still modifies its
- X/* arguments, however.
- X/*
- X/* istrcmp() is a case-insensitive version of the strcmp() function.
- X/*
- X/* istrncmp() is a case-insensitive version of the strncmp() function.
- X/*
- X/* strvec() breaks a null-terminated string using the separators given
- X/* in separ, and returns a null-terminated vector of pointers to the
- X/* resulting substrings. Memory for the vector and substrings are
- X/* allocated in dynamic memory. The original string is not modified.
- X/*
- X/* freevec() frees storage allocated by strvec().
- X/*
- X/* vecstr() takes a null-terminated vector of string pointers
- X/* and builds a string from the strings pointed to by the vector
- X/* argument, separated by the string in the separ argument.
- X/* Memory for the result is allocated in dynamic memory.
- X/* FUNCTIONS AND MACROS
- X/* strtok(), malloc(), memcpy(), sprintf()
- X/* DIAGNOSTICS
- X/* strvec(), vecstr() return a null pointer if there was not enough memory
- X/* avaliable to hold the result.
- X/* BUGS
- X/* strcons() does not do smart garbage collection; it just uses
- X/* a circular buffer. The present implementation is not portable
- X/* to machines that pass arguments via registers.
- X/*
- X/* strvec() cannot handle strings with more than BUFSIZ words.
- X/* strvec() uses strtok(), which may have side effects.
- X/* AUTHOR(S)
- X/* W.Z. Venema
- X/* Eindhoven University of Technology
- X/* Department of Mathematics and Computer Science
- X/* Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
- X/* CREATION DATE
- X/* Tue Apr 5 20:59:29 MET 1988
- X/* LAST MODIFICATION
- X/* 90/01/22 13:02:43
- X/* VERSION/RELEASE
- X/* 2.1
- X/*--*/
- X
- X#include <stdio.h>
- X#include <ctype.h>
- X#include <varargs.h>
- X
- X#include "defs.h"
- X
- X#define NBUF 4
- X
- X/* strcons - quick-and-dirty string constructor */
- X
- X/* VARARGS */
- X
- Xchar *strcons(va_alist)
- Xva_dcl
- X{
- X va_list ap;
- X static char strbuf[NBUF][BUFSIZ];
- X static int where = 0;
- X register char *cp;
- X char *fmt;
- X
- X va_start(ap);
- X fmt = va_arg(ap, char *);
- X (void) vsprintf(cp = strbuf[where = (where + 1) % NBUF], fmt, ap);
- X va_end(ap);
- X return (cp);
- X}
- X
- X/* istrcmp - case-insensitive string comparison */
- X
- X#define LOW(c) (isascii(c)&&isupper(c)?tolower(c):(c))
- X
- Xint istrcmp(s1, s2)
- Xregister char *s1;
- Xregister char *s2;
- X{
- X while (*s1 && (LOW(*s1) == LOW(*s2)))
- X s1++, s2++;
- X return (LOW(*s1) - LOW(*s2));
- X}
- X
- X/* istrncmp - case-insensitive string comparison */
- X
- X#define LOW(c) (isascii(c)&&isupper(c)?tolower(c):(c))
- X
- Xint istrncmp(s1, s2, n)
- Xregister char *s1;
- Xregister char *s2;
- Xregister int n;
- X{
- X while (n > 0 && *s1 && (LOW(*s1) == LOW(*s2)))
- X n--, s1++, s2++;
- X return (n > 0 ? LOW(*s1) - LOW(*s2) : 0);
- X}
- X
- X/* strvec - make vector of substring pointers */
- X
- Xchar **strvec(str, sep)
- Xchar *str;
- Xchar *sep;
- X{
- X#ifdef lint
- X static
- X#endif
- X char *tmp[BUFSIZ]; /* scratch substring pointer storage */
- X register char **cpp = tmp;
- X char *sp; /* ptr to private copy of original */
- X register int bytec;
- X
- X /* make a copy of the original string */
- X
- X if ((sp = malloc(strlen(str) + 1)) == 0)
- X return (0);
- X (void) strcpy(sp, str);
- X
- X /* chop our copy at sequences of one or more separators */
- X
- X for (*cpp = strtok(sp, sep); *cpp; *++cpp = strtok((char *) 0, sep))
- X /* void */ ;
- X
- X /* now construct the vector of pointers to the substrings */
- X
- X if ((cpp = (char **) malloc(bytec = (cpp - tmp + 1) * sizeof(*cpp))) == 0)
- X return (0);
- X return ((char **) memcpy((char *) cpp, (char *) tmp, bytec));
- X}
- X
- X/* freevec - release storage allocated by strvec() */
- X
- Xfreevec(vec)
- Xchar **vec;
- X{
- X free(vec[0]);
- X free((char *) vec);
- X}
- X
- X/* vecstr - from null-terminated vector of string pointers to one flat string */
- X
- Xpublic char *vecstr(vec, sep)
- Xchar **vec;
- Xchar *sep;
- X{
- X register char **cpp;
- X register int len = 0; /* length of final string */
- X register char *cp;
- X register int flen = strlen(sep); /* filler between substrings */
- X
- X /* find out how big the resulting string will be */
- X
- X for (cpp = vec; *cpp; cpp++)
- X len += strlen(*cpp) + flen;
- X
- X /* allocate and initialize the result string */
- X
- X if ((cp = malloc(len + 1)) == 0)
- X return (0);
- X *cp = '\0';
- X
- X /* fill the resulting string */
- X
- X for (cpp = vec; *cpp; cpp++) {
- X (void) strcat(cp, *cpp);
- X (void) strcat(cp, sep);
- X }
- X return (cp);
- X}
- X
- X/* split - return next token in *cpp, update cpp */
- X
- Xpublic char *split(cpp, sep)
- Xregister char **cpp;
- Xregister char *sep;
- X{
- X register char *start;
- X char *end;
- X char *strpbrk();
- X
- X /*
- X * Find the beginning of the first token. If none is found, just return a
- X * null value. Otherwise, if there is a separator that follows the token,
- X * nullify it and advance *cpp to the first character after the nullified
- X * separator. If the token is not followed by a separator advance *cpp to
- X * the null byte that follows the token.
- X */
- X
- X start = *cpp + strspn(*cpp, sep);
- X
- X if (start[0] == 0) {
- X return (0); /* no token */
- X } else if (end = strpbrk(start, sep)) { /* look for separator */
- X *end = '\0'; /* nullify */
- X *cpp = end + 1; /* advance beyond end */
- X return (start); /* return token */
- X } else {
- X *cpp = start + strlen(start); /* advance to terminator */
- X return (start); /* return token */
- X }
- X}
- END_OF_main/str.c
- if test 6415 -ne `wc -c <main/str.c`; then
- echo shar: \"main/str.c\" unpacked with wrong size!
- fi
- # end of overwriting check
- fi
- echo shar: End of archive 6 \(of 11\).
- cp /dev/null ark6isdone
- 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
-
-