syd@dsinc.UUCP (Syd Weinstein) (12/16/88)
---- Cut Here and unpack ---- #!/bin/sh # this is part 21 of a multipart archive # do not concatenate these parts, unpack them in order with /bin/sh # file utils/fastmail.c continued # CurArch=21 if test ! -r s2_seq_.tmp then echo "Please unpack part 1 first!" exit 1; fi ( read Scheck if test "$Scheck" != $CurArch then echo "Please unpack part $Scheck next!" exit 1; else exit 0; fi ) < s2_seq_.tmp || exit 1 echo "x - Continuing file utils/fastmail.c" sed 's/^X//' << 'SHAR_EOF' >> utils/fastmail.c Xint argc; Xchar *argv[], *options; X{ X /** Returns the character argument next, and optionally instantiates X "argument" to the argument associated with the particular option X **/ X X char *word, *strchr(); X X if (_indx >= strlen(argv[_argnum])) { X _argnum++; X _indx = 1; /* zeroeth char is '-' */ X } X X if (_argnum >= argc) { X opt_index = argc; X return(DONE); X } X X if (argv[_argnum][0] != '-') { X opt_index = _argnum; X return(DONE); X } X X word = strchr(options, argv[_argnum][_indx++]); X X if (strlen(word) == 0) X return(ERROR); X X if (word[1] == ':') { X X /** Two possibilities - either tailing end of this argument or the X next argument in the list **/ X X if (_indx < strlen(argv[_argnum])) { /* first possibility */ X optional_arg = (char *) (argv[_argnum] + _indx); X _argnum++; X _indx = 1; X } X else { /* second choice */ X if (++_argnum >= argc) X return(ERROR); /* no argument!! */ X X optional_arg = (char *) argv[_argnum++]; X _indx = 1; X } X } X X return((int) word[0]); X} SHAR_EOF echo "File utils/fastmail.c is complete" chmod 0444 utils/fastmail.c || echo "restore of utils/fastmail.c fails" echo "x - extracting utils/from.c (Text)" sed 's/^X//' << 'SHAR_EOF' > utils/from.c && X Xstatic char rcsid[] = "@(#)$Id: from.c,v 2.1 88/09/15 21:07:30 syd Exp $"; X X/******************************************************************************* X * The Elm Mail System - $Revision: 2.1 $ $State: Exp $ X * X * Copyright (c) 1986 Dave Taylor X ******************************************************************************* X * Bug reports, patches, comments, suggetions should be sent to: X * X * Eric D. Christensen - edc@altnet.ALTOS.COM X * uunet!altnet!edc X * X ******************************************************************************* X * $Log: from.c,v $ X * Revision 2.1 88/09/15 21:07:30 syd X * checked in with -k by syd at 88.09.15.21.07.30. X * X * 88/08/27 Rob Bernardo <gatech!pbhyf.PacBell.COM!rob> X * fixes for non tty processes, unreferenced variable X * X * Revision 2.1 88/07/21 10:01:31 edc X * Final hacks and cleanup to the 2.1 alpha test release X * X * Revision 2.0 88/06/27 16:54:07 edc X * The original 2.0 gamma sources as leaked from HP X * X * X * X ******************************************************************************/ X X/** print out whom each message is from in the pending folder or specified X one, including a subject line if available.. X X Added PREFER_UUCP knowledge 6/86 X Added "-n" flag, 9/86 X Added "-v" flag, 3/87 X X**/ X X#include <stdio.h> X#include "defs.h" X Xstatic char ident[] = { WHAT_STRING }; X X#define LINEFEED (char) 10 X X#define metachar(c) (c == '=' || c == '+' || c == '%') X XFILE *mailfile; X Xchar *expand_define(); Xint number = 0, /* should we number the messages?? */ X verbose = 0; /* and should we prepend a header? */ X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X char infile[LONG_SLEN], username[SLEN]; X int multiple_files = 0, output_files = 0, c; X X extern int opt_index; X X while ((c = get_options(argc, argv, "nv")) > 0) X switch (c) { X case (int)'n': number++; break; X case (int)'v': verbose++; break; X } X X if (c == -1) { X printf("Usage: %s [-n] [-v] {filename | username}\n", argv[0]); X exit(1); X } X X infile[0] = '\0'; X if (opt_index == argc) { X if (getlogin()) X strcpy(username, getlogin()); X if (strlen(username) == 0) X cuserid(username); X sprintf(infile,"%s%s",mailhome, username); X opt_index -= 1; /* ensure one pass through loop */ X } X X multiple_files = (argc - opt_index > 1); X X while (opt_index < argc) { X X if (multiple_files) { X strcpy(infile, argv[opt_index]); X printf("%s%s: \n", output_files++ > 0 ? "\n":"", infile); X } X else if (infile[0] == '\0') X strcpy(infile, argv[opt_index]); X X if (metachar(infile[0])) { X if (expand(infile) == 0) { X fprintf(stderr, "%s: couldn't expand filename %s!\n", X argv[0], infile); X exit(1); X } X } X X if ((mailfile = fopen(infile,"r")) == NULL) { X if (opt_index+1 == argc) X printf("No mail\n"); X else { X if (infile[0] == '/') X printf("Couldn't open folder \"%s\".\n", infile); X else { X sprintf(infile,"%s%s", mailhome, argv[opt_index]); X if ((mailfile = fopen(infile,"r")) == NULL) X printf("Couldn't open folders \"%s\" or \"%s\".\n", X argv[opt_index], infile); X else if (read_headers()==0) X printf("No messages in that folder!\n"); X } X } X } X else X if (read_headers(opt_index+1 == argc)==0) X if (opt_index+1 == argc) X printf("No mail\n"); X else X printf("No messages in that folder!\n"); X X opt_index++; X } X exit(0); X} X Xint Xread_headers(user_mailbox) Xint user_mailbox; X{ X /** Read the headers, output as found. User-Mailbox is to guarantee X that we get a reasonably sensible message from the '-v' option X **/ X X char buffer[LONG_SLEN], from_whom[SLEN], subject[SLEN]; X register int subj = 0, in_header = 0, count = 0; X X while (fgets(buffer, LONG_SLEN, mailfile) != NULL) { X if (first_word(buffer,"From ")) { X if (real_from(buffer, from_whom)) { X subj = 0; X in_header = 1; X } X } X else if (in_header) { X if (first_word(buffer,">From ")) X forwarded(buffer, from_whom); /* return address */ X else if (first_word(buffer,"Subject:") || X first_word(buffer,"Re:")) { X if (! subj++) { X remove_first_word(buffer); X strcpy(subject, buffer); X } X } X else if (first_word(buffer,"From:") || X first_word(buffer, ">From:")) X parse_arpa_from(buffer, from_whom); X else if (buffer[0] == LINEFEED) { X if (verbose && count == 0) X printf("%s contains the following messages:\n\n", X user_mailbox?"Your mailbox" : "Folder"); X in_header = 0; /* in body of message! */ X show_header(count+1, from_whom, subject); X from_whom[0] = 0; X subject[0] = 0; X count++; X } X } X } X return(count); X} X Xint Xreal_from(buffer, who) Xchar *buffer, *who; X{ X /***** returns true iff 's' has the seven 'from' fields, X initializing the who to the sender *****/ X X char junk[80]; X X junk[0] = '\0'; X sscanf(buffer, "%*s %s %*s %*s %*s %*s %s", X who, junk); X return(junk[0] != '\0'); X} X Xforwarded(buffer, who) Xchar *buffer, *who; X{ X /** change 'from' and date fields to reflect the ORIGINATOR of X the message by iteratively parsing the >From fields... **/ X X char machine[80], buff[80]; X X machine[0] = '\0'; X sscanf(buffer, "%*s %s %*s %*s %*s %*s %*s %*s %*s %s", X who, machine); X X if (machine[0] == '\0') /* try for srm address */ X sscanf(buffer, "%*s %s %*s %*s %*s %*s %*s %*s %s", X who, machine); X X if (machine[0] == '\0') X sprintf(buff,"anonymous"); X else X sprintf(buff,"%s!%s", machine, who); X X strncpy(who, buff, 80); X} X Xremove_first_word(string) Xchar *string; X{ /** removes first word of string, ie up to first non-white space X following a white space! **/ X X register int loc; X X for (loc = 0; string[loc] != ' ' && string[loc] != '\0'; loc++) X ; X X while (string[loc] == ' ' || string[loc] == '\t') X loc++; X X move_left(string, loc); X} X Xmove_left(string, chars) Xchar string[]; Xint chars; X{ X /** moves string chars characters to the left DESTRUCTIVELY **/ X X register int i; X X chars--; /* index starting at zero! */ X X for (i=chars; string[i] != '\0' && string[i] != '\n'; i++) X string[i-chars] = string[i]; X X string[i-chars] = '\0'; X} X Xshow_header(count, from, subject) Xint count; Xchar *from, *subject; X{ X /** output header in clean format, including abbreviation X of return address if more than one machine name is X contained within it! **/ X X char buffer[SLEN]; X int loc, i=0, exc=0; X X#ifdef PREFER_UUCP X char *p; X X if (chloc(from,'!') != -1 && chloc(from,'@') > 0) { X for (p=from;*p != '@'; p++) ; X *p = '\0'; X } X#endif X X loc = strlen(from); X X while (exc < 2 && loc > 0) X if (from[--loc] == '!') X exc++; X X if (exc == 2) { /* lots of machine names! Get last one */ X loc++; X while (loc < strlen(from) && loc < SLEN) X buffer[i++] = from[loc++]; X buffer[i] = '\0'; X if (number) X printf("%3d: %-20s %s\n", count, buffer, subject); X else X printf("%-20s %s\n", buffer, subject); X } X else X if (number) X printf("%3d: %-20s %s\n", count, from, subject); X else X printf("%-20s %s\n", from, subject); X} X Xparse_arpa_from(buffer, newfrom) Xchar *buffer, *newfrom; X{ X /** try to parse the 'From:' line given... It can be in one of X two formats: X From: Dave Taylor <hpcnou!dat> X or From: hpcnou!dat (Dave Taylor) X Change 'newfrom' ONLY if sucessfully parsed this entry and X the resulting name is non-null! X **/ X X char temp_buffer[SLEN], *temp; X register int i, j = 0; X X temp = (char *) temp_buffer; X temp[0] = '\0'; X X no_ret(buffer); /* blow away '\n' char! */ X X if (lastch(buffer) == '>') { X for (i=strlen("From: "); buffer[i] != '\0' && buffer[i] != '<' && X buffer[i] != '('; i++) X temp[j++] = buffer[i]; X temp[j] = '\0'; X } X else if (lastch(buffer) == ')') { X for (i=strlen(buffer)-2; buffer[i] != '\0' && buffer[i] != '(' && X buffer[i] != '<'; i--) X temp[j++] = buffer[i]; X temp[j] = '\0'; X reverse(temp); X } X X if (strlen(temp) > 0) { /* mess with buffer... */ X X /* remove leading spaces... */ X X while (whitespace(temp[0])) X temp = (char *) (temp + 1); /* increment address! */ X X /* remove trailing spaces... */ X X i = strlen(temp) - 1; X X while (whitespace(temp[i])) X temp[i--] = '\0'; X X /* remove surrounding paired quotation marks */ X if((temp[i] == '"') & (*temp == '"')) { X temp[i] = '\0'; X temp++; X } X X /* if anything is left, let's change 'from' value! */ X X if (strlen(temp) > 0) X strcpy(newfrom, temp); X } X} X Xreverse(string) Xchar *string; X{ X /** reverse string... pretty trivial routine, actually! **/ X X char buffer[SLEN]; X register int i, j = 0; X X for (i = strlen(string)-1; i >= 0; i--) X buffer[j++] = string[i]; X X buffer[j] = '\0'; X X strcpy(string, buffer); X} SHAR_EOF chmod 0444 utils/from.c || echo "restore of utils/from.c fails" echo "x - extracting utils/getopt.c (Text)" sed 's/^X//' << 'SHAR_EOF' > utils/getopt.c && X Xstatic char rcsid[] = "@(#)$Id: getopt.c,v 2.1 88/09/15 21:07:32 syd Exp $"; X X/******************************************************************************* X * The Elm Mail System - $Revision: 2.1 $ $State: Exp $ X * X ******************************************************************************* X * Bug reports, patches, comments, suggetions should be sent to: X * X * Eric D. Christensen - edc@altnet.ALTOS.COM X * uunet!altnet!edc X * X ******************************************************************************* X * $Log: getopt.c,v $ X * Revision 2.1 88/09/15 21:07:32 syd X * checked in with -k by syd at 88.09.15.21.07.32. X * X * Revision 2.1 88/07/21 10:01:34 edc X * Final hacks and cleanup to the 2.1 alpha test release X * X * Revision 2.0 88/06/27 16:54:08 edc X * The original 2.0 gamma sources as leaked from HP X * X * X * X ******************************************************************************/ X X/*LINTLIBRARY*/ X#define NULL 0 X#define EOF (-1) X#define ERR(s, c) if(opterr){\ X extern int strlen(), write();\ X char errbuf[2];\ X errbuf[0] = c; errbuf[1] = '\n';\ X (void) write(2, argv[0], (unsigned)strlen(argv[0]));\ X (void) write(2, s, (unsigned)strlen(s));\ X (void) write(2, errbuf, 2);} X Xextern int strcmp(); Xextern char *index(); X Xint opterr = 1; Xint optind = 1; Xint optopt; Xchar *optarg; X Xint Xgetopt(argc, argv, opts) Xint argc; Xchar **argv, *opts; X{ X static int sp = 1; X register int c; X register char *cp; X X if(sp == 1) X if(optind >= argc || X argv[optind][0] != '-' || argv[optind][1] == '\0') X return(EOF); X else if(strcmp(argv[optind], "--") == NULL) { X optind++; X return(EOF); X } X optopt = c = argv[optind][sp]; X if(c == ':' || (cp=index(opts, c)) == NULL) { X ERR(": illegal option -- ", c); X if(argv[optind][++sp] == '\0') { X optind++; X sp = 1; X } X return('?'); X } X if(*++cp == ':') { X if(argv[optind][sp+1] != '\0') X optarg = &argv[optind++][sp+1]; X else if(++optind >= argc) { X ERR(": option requires an argument -- ", c); X sp = 1; X return('?'); X } else X optarg = argv[optind++]; X sp = 1; X } else { X if(argv[optind][++sp] == '\0') { X sp = 1; X optind++; X } X optarg = NULL; X } X return(c); X} X SHAR_EOF chmod 0444 utils/getopt.c || echo "restore of utils/getopt.c fails" echo "x - extracting utils/listalias.c (Text)" sed 's/^X//' << 'SHAR_EOF' > utils/listalias.c && X Xstatic char rcsid[] = "@(#)$Id: listalias.c,v 2.1 88/09/15 21:07:33 syd Exp $"; X X/******************************************************************************* X * The Elm Mail System - $Revision: 2.1 $ $State: Exp $ X * X * Copyright (c) 1986 Dave Taylor X ******************************************************************************* X * Bug reports, patches, comments, suggetions should be sent to: X * X * Eric D. Christensen - edc@altnet.ALTOS.COM X * uunet!altnet!edc X * X ******************************************************************************* X * $Log: listalias.c,v $ X * Revision 2.1 88/09/15 21:07:33 syd X * checked in with -k by syd at 88.09.15.21.07.33. X * X * Revision 2.1 88/07/21 10:01:36 edc X * Final hacks and cleanup to the 2.1 alpha test release X * X * Revision 2.0 88/06/27 16:54:09 edc X * The original 2.0 gamma sources as leaked from HP X * X * X * X ******************************************************************************/ X X/** Program that lists all the available aliases. This one uses the pipe X command, feeding the stuff to egrep then sort, or just sort. X X**/ X X#include <stdio.h> X#include <fcntl.h> X X#include "defs.h" X#include "sysdefs.h" X X#ifdef BSD X FILE *popen(); X#endif X Xchar *getenv(); X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X FILE *datafile, *fd_pipe; X struct alias_rec hash_record; X int hashfile, count = 0; X char buffer[LONG_SLEN], fd_hash[SLEN], X fd_data[SLEN], *home; X X if (argc > 2) { X printf("Usage: listalias <optional-regular-expression>\n"); X exit(1); X } X X home = getenv("HOME"); X X sprintf(fd_hash, "%s/%s", home, ALIAS_HASH); X sprintf(fd_data, "%s/%s", home, ALIAS_DATA); X X if (argc > 1) X sprintf(buffer, "egrep \"%s\" | sort", argv[1]); X else X sprintf(buffer, "sort"); X X if ((fd_pipe = popen(buffer, "w")) == NULL) { X if (argc > 1) X printf("cannot open pipe to egrep program for expressions!\n"); X fd_pipe = stdout; X } X X do { X X if ((hashfile = open(fd_hash, O_RDONLY)) > 0) { X if ((datafile = fopen(fd_data, "r")) == NULL) { X printf("Opened %s hash file, but couldn't open data file!\n", X count? "system" : "user"); X goto next_file; X } X X /** Otherwise let us continue... **/ X X while (read(hashfile, &hash_record, sizeof (hash_record)) != 0) { X if (strlen(hash_record.name) > 0) { X fseek(datafile, hash_record.byte, 0L); X fgets(buffer, LONG_SLEN, datafile); X fprintf(fd_pipe, "%-15s %s", hash_record.name, buffer); X } X } X } X Xnext_file: strcpy(fd_hash, system_hash_file); X strcpy(fd_data, system_data_file); X X } while (++count < 2); X X pclose(fd_pipe); X X exit(0); X} SHAR_EOF chmod 0444 utils/listalias.c || echo "restore of utils/listalias.c fails" echo "x - extracting utils/mailrc.awk (Text)" sed 's/^X//' << 'SHAR_EOF' > utils/mailrc.awk && X# X# @(#)$Id: mailrc.awk,v 2.1 88/09/15 21:08:13 syd Exp $ X# X# $Log: mailrc.awk,v $ X# Revision 2.1 88/09/15 21:08:13 syd X# Initial 2.1 Release X# X# Revision 2.0 88/06/27 16:54:15 edc X# The original 2.0 gamma sources as leaked from HP X# X# X# X X XBEGIN { X print "# MSG alias_text file, from a .mailrc file..." X print "" X } X Xnext_line == 1 { X X next_line = 0; X group = "" X for (i = 1; i <= NF; i++) { X if (i == NF && $i == "\\") sep = "" X else sep = ", " X X if ($i == "\\") { X group = sprintf("%s,", group) X next_line = 1; X } X else if (length(group) > 0) X group = sprintf("%s%s%s", group, sep, $i); X else X group = $i; X } X print "\t" group X X } X X$1 ~ /[Aa]lias|[Gg]roup/ { X X if ( NF == 3) X print $2 " : user alias : " $3; X else { X group = "" X for (i = 3; i <= NF; i++) { X if (i == NF && $i == "\\") sep = "" X else sep = ", " X X if ($i == "\\") { X group = sprintf("%s,", group) X next_line = 1; X } X else if (length(group) > 0) X group = sprintf("%s%s%s", group, sep, $i); X else X group = $i; X } X print $2 " : group alias : " group; X } X } SHAR_EOF chmod 0444 utils/mailrc.awk || echo "restore of utils/mailrc.awk fails" echo "x - extracting utils/newalias.c (Text)" sed 's/^X//' << 'SHAR_EOF' > utils/newalias.c && X Xstatic char rcsid[] = "@(#)$Id: newalias.c,v 2.2 88/09/15 21:07:34 syd Exp $"; X X/******************************************************************************* X * The Elm Mail System - $Revision: 2.2 $ $State: Exp $ X * X * Copyright (c) 1986 Dave Taylor X ******************************************************************************* X * Bug reports, patches, comments, suggetions should be sent to: X * X * Eric D. Christensen - edc@altnet.ALTOS.COM X * uunet!altnet!edc X * X ******************************************************************************* X * $Log: newalias.c,v $ X * Revision 2.2 88/09/15 21:07:34 syd X * checked in with -k by syd at 88.09.15.21.07.34. X * X * Revision 2.2 88/07/21 10:01:38 edc X * Final hacks and cleanup to the 2.1 alpha test release X * X * Revision 2.1 88/06/28 12:59:44 edc X * Added code to support systems with no mkdir() call available. This code X * is used if NOMKDIR is defined in sysdefs.h. (Configure.sh checks this X * out for us.) X * X * Revision 2.0 88/06/27 16:54:10 edc X * The original 2.0 gamma sources as leaked from HP X * X * X * X ******************************************************************************/ X X/** Install a new set of aliases for the 'Elm' mailer. X X If invoked with a specific filename, it assumes that X it is working with an individual users alias tables, and X generates the .alias.hash and .alias.data files in their X home directory. X If, however, it is invoked with no arguments, then X it assumes that the user is updating the system alias X file and uses the defaults for everything. X X The format for the input file is; X alias1, alias2, ... = username = address Xor alias1, alias2, ... = groupname= member, member, member, ... X member, member, member, ... X X "-q" flag added: 6/17/86 X modified for X.400 support: 21-09-87 GND X**/ X X#ifdef BSD X# include <sys/file.h> X#else X# include <fcntl.h> X#endif X X#include <stdio.h> X#include "defs.h" X#include "sysdefs.h" /* ELM system definitions */ X Xstatic char ident[] = { WHAT_STRING }; X X#define group(string) (strpbrk(string,", ") != NULL) X Xstruct alias_rec Xshash_table[MAX_SALIASES]; /* the actual hash table */ X Xstruct alias_rec Xuhash_table[MAX_UALIASES]; /* the actual hash table */ X Xint hash_table_loaded=0; /* is system table actually loaded? */ X Xint buff_loaded; /* for file input overlap... */ Xint error= 0; /* if errors, don't save! */ Xint is_system=0; /* system file updating? */ Xint count=0; /* how many aliases so far? */ Xlong offset = 0L; /* data file line offset! */ Xchar home[SLEN]; /* the users home directory */ X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X FILE *in, *data; X char inputname[SLEN], hashname[SLEN], dataname[SLEN]; X char buffer[LONG_STRING]; X int hash, count = 0, owner, quiet = 0; X X if (argc != 1) X if (strcmp(argv[1], "-q") == 0) X quiet++; X else X exit(printf("Usage: %s [-q]\n", argv[0])); X X owner = getuid(); X X if (owner == 0 && ! quiet) { /* being run by root! */ X printf("Would you like to update the system aliases? (y/n)"); X gets(buffer); X if (buffer[0] == 'y' || buffer[0] == 'Y') { X printf("Updating the system alias file...\n"); X X strcpy(inputname, system_text_file); X strcpy(hashname, system_hash_file); X strcpy(dataname, system_data_file); X is_system++; X init_table(shash_table, MAX_SALIASES); X } X else X printf("Updating your personal alias file...\n"); X } X X if (! is_system) { X if (strcpy(home, getenv("HOME")) == NULL) X exit(printf("I'm confused - no HOME variable in environment!\n")); X X sprintf(inputname, "%s/%s", home, ALIAS_TEXT); X sprintf(hashname, "%s/%s", home, ALIAS_HASH); X sprintf(dataname, "%s/%s", home, ALIAS_DATA); X X init_table(uhash_table, MAX_UALIASES); X X read_in_system(shash_table, sizeof shash_table); X } X X if ((in = fopen(inputname,"r")) == NULL) { X /** let's see if they have the files in the old place... **/ X sprintf(buffer, "%s/.alias_text", home); X if (access(buffer, ACCESS_EXISTS) != -1) { X update_alias_file_locations(); X in = fopen(inputname, "r"); X } X else { X printf("Couldn't open %s for input!\n", inputname); X exit(1); X } X } X X if ((hash = open(hashname, O_WRONLY | O_CREAT, 0644)) == -1) X exit(printf("Couldn't open %s for output!\n", hashname)); X X if ((data = fopen(dataname,"w")) == NULL) X exit(printf("Couldn't open %s for output!\n", dataname)); X X buff_loaded = 0; /* file buffer empty right now! */ X X while (get_alias(in, buffer) != -1) { X if (is_system) X put_alias(data, buffer, shash_table, MAX_SALIASES); X else X put_alias(data, buffer, uhash_table, MAX_UALIASES); X count++; X } X X if (error) { X printf("\n** Not saving tables! Please fix and re-run %s!\n", X argv[0]); X exit(1); X } X else { X if (is_system) X write(hash, shash_table, sizeof shash_table); X else X write(hash, uhash_table, sizeof uhash_table); X X close(hash); X fclose(data); X close(in); X X printf("Processed %d aliases\n", count); X exit(0); X } X} X Xint Xget_alias(file, buffer) XFILE *file; Xchar *buffer; X{ X /* load buffer with the next complete alias from the file. X (this can include reading in multiple lines and appending X them all together!) Returns EOF after last entry in file. X X Lines that start with '#' are assumed to be comments and are X ignored. White space as the first field of a line is taken X to indicate that this line is a continuation of the previous. */ X X static char mybuffer[SLEN]; X int done = 0, first_read = 1; X X /** get the first line of the entry... **/ X X buffer[0] = '\0'; /* zero out line */ X X do { X if (get_line(file, mybuffer, first_read) == -1) X return(-1); X first_read = 0; X if (mybuffer[0] != '#') X strcpy(buffer, mybuffer); X } while (strlen(buffer) == 0); X X /** now read in the rest (if there is any!) **/ X X do { X if (get_line(file, mybuffer, first_read) == -1) { X buff_loaded = 0; /* force a read next pass! */ X return(0); /* okay. let's just hand 'buffer' back! */ X } X done = (! whitespace(mybuffer[0])); X if (! done) X strcat(buffer, mybuffer); X done = (done && mybuffer[0] != '#'); X } while (! done); X X return(0); /* no sweat! */ X} X Xput_alias(data, buffer, table, size) XFILE *data; Xchar *buffer; Xstruct alias_rec table[]; Xint size; X{ X /** break buffer down into three pieces: aliases, comment, and address. X Make the appropriate entries in the table (size) X **/ X X char aliases[LONG_STRING], address[LONG_STRING]; X char comment[LONG_STRING]; X int first, last, i = 0, j = 0; X X remove_all(' ', TAB, buffer); X X for (i=0; buffer[i] != '=' && i < LONG_STRING; i++) X aliases[i] = buffer[i]; X aliases[i] = '\0'; X X for (i=strlen(buffer)-1; buffer[i] != '=' && i > 0; i--) X address[j++] = buffer[i]; X address[j] = '\0'; X X comment[0] = '\0'; /* default to nothing at all... */ X X if ((first=strlen(aliases)+1) < (last=(strlen(buffer) - j))) { X extract_comment(comment, buffer, first, last); X } X X reverse(address); X X add_to_table(data, aliases, comment, address, table, size); X} X Xint Xget_line(file, buffer, first_line) XFILE *file; Xchar *buffer; Xint first_line; X{ X /** read line from file. If first_line and buff_loaded, X then just return! **/ X X int stat; X X if (first_line && buff_loaded) { X buff_loaded = 1; X return(0); X } X X buff_loaded = 1; /* we're going to get SOMETHING in the buffer */ X X stat = fgets(buffer, SLEN, file) == NULL ? -1 : 0; X X if (stat != -1) X no_ret(buffer); X X return(stat); X} X Xreverse(string) Xchar *string; X{ X /** reverse the order of the characters in string... X uses a bubble-sort type of algorithm! **/ X X register int f, l; X char c; X X f = 0; X l = strlen(string) - 1; X X while (f < l) { X c = string[f]; X string[f] = string[l]; X string[l] = c; X f++; X l--; X } X} X Xadd_to_table(data, aliases, comment, address, table, size) XFILE *data; Xchar *aliases, *comment, *address; Xstruct alias_rec table[]; Xint size; X{ X /** add address + comment to datafile, incrementing offset count X (bytes), then for each alias in the aliases string, add to the X hash table, with the associated pointer value! **/ X X static char buf[SLEN], *word; X long additive = 1L; X X word = buf; /* use the allocated space! */ X X if (group(address)) { X check_group(address, aliases); X if (error) return; /* don't do work if we aren't to save it! */ X fprintf(data, "!%s\n", address); X additive = 2L; X } X else { X if (error) return; /* don't do work if we aren't to save it! */ X if (strlen(comment) > 0) { X fprintf(data, "%s (%s)\n", address, comment); X additive = (long) (strlen(comment) + 4); X } X else X fprintf(data, "%s\n", address, comment); X } X X while ((word = (char *) strtok(aliases,", ")) != NULL) { X add_to_hash_table(word, offset, table, size); X aliases = NULL; /* let's get ALL entries via 'strtok' */ X count++; X } X X if ( is_system ? count > MAX_SALIASES-35 : count > MAX_UALIASES-21) { X printf("** Too many aliases in file! **\n"); X error++; X } X X offset = (offset + (long) strlen(address) + additive); X} X Xremove_all(c1, c2, string) Xchar c1, c2, *string; X{ X /* Remove all occurances of character 'c1' or 'c2' from the string. X Hacked (literally) to NOT remove ANY characters from within the X equals fields. This will only be used if the line contains TWO X equalss (and comments with equalss in them are the kiss of death!) X */ X X char buffer[LONG_STRING]; X register int i = 0, j = 0, first_equals = -1, last_equals = -1; X X for (i = 0; string[i] != '\0' && i < LONG_STRING; i++) { X if (string[i] != c1 && string[i] != c2) X buffer[j++] = string[i]; X X if (first_equals == -1 && string[i] == '=') { X first_equals = i; X for (last_equals=strlen(string);string[last_equals] != '='; X last_equals--) ; X } X else if (i > first_equals && i < last_equals) X if (string[i] == c1 || string[i] == c2) X buffer[j++] = string[i]; X } X X buffer[j] = '\0'; X strcpy(string, buffer); X} X Xadd_to_hash_table(word, offset, table, size) Xchar *word; Xlong offset; Xstruct alias_rec table[]; Xint size; X{ X /** add word and offset to current hash table. **/ X register int loc; X X if (strlen(word) > 20) X exit(printf("Bad alias name: %s. Too long.\n", word)); X X loc = hash_it(word, size); X X while (table[loc].name[0] != '\0' && strcmp(table[loc].name, word) != 0) X loc = loc + 1 % size; X X if (table[loc].name[0] == '\0') { X strcpy(table[loc].name, word); X table[loc].byte = offset; X } X else X printf("** Duplicate alias '%s' in file. Multiples ignored.\n", X word); X} X Xint Xhash_it(string, table_size) Xchar *string; X{ X /** compute the hash function of the string, returning X it (mod table_size) **/ X X register int i, sum = 0; X X for (i=0; string[i] != '\0'; i++) X sum += (int) string[i]; X X return(sum % table_size); X} X Xinit_table(table, size) Xstruct alias_rec table[]; Xint size; X{ X /** initialize hash table! **/ X X register int i; X X for (i=0; i < size; i++) X table[i].name[0] = '\0'; X} X Xread_in_system(table, size) Xstruct alias_rec table[]; Xint size; X{ X /** read in the system hash table...to check for group aliases X from the user alias file (to ensure that there are no names X in the user group files that are not purely contained within X either alias table) **/ X X int fd; X char fname[SLEN]; X X sprintf(fname, "%s/%s", mailhome, ALIAS_HASH); X X if ((fd = open(fname, O_RDONLY)) == -1) X return; /* no sweat: flag 'hash_table_loaded' not set! */ X X (void) read(fd, table, size); X close(fd); X hash_table_loaded++; X} X Xcheck_group(names, groupname) Xchar *names, *groupname; X{ X /** one by one make sure each name in the group is defined X in either the system alias file or the user alias file. X This search is linearly dependent, so all group aliases X in the source file should appear LAST, after all the user X aliases! **/ X X char *word, *bufptr, buffer[LONG_STRING]; X X strcpy(buffer, names); X bufptr = (char *) buffer; X X while ((word = (char *) strtok(bufptr,", ")) != NULL) { X if (! can_find(word)) X if (! valid_name(word)) { X error++; X printf("** Alias %s in group %s is bad!\n", word, groupname); X } X bufptr = NULL; X } X} X Xint Xcan_find(name) Xchar *name; X{ X /** find name in either hash table...use 'is_system' variable to X determine if we should look in both or just system.... **/ X X register int loc; X X if (strlen(name) > 20) { X error++; X printf("** Bad alias name: %s. Too long.\n", name); X return(1); /* fake out: don't want 2 error messages! */ X } X X /** system alias table... **/ X if (hash_table_loaded || is_system) { X loc = hash_it(name, MAX_SALIASES); X X while (strcmp(name, shash_table[loc].name) != 0 && X shash_table[loc].name[0] != '\0') X loc = (loc + 1) % MAX_SALIASES; X X if (strcmp(name, shash_table[loc].name) == 0) X return(1); /* found it! */ X } X X if (! is_system) { /* okay! Let's check the user alias file! */ X loc = hash_it(name, MAX_UALIASES); X X while (strcmp(name, uhash_table[loc].name) != 0 && X uhash_table[loc].name[0] != '\0') X loc = (loc + 1) % MAX_UALIASES; X X if (strcmp(name, uhash_table[loc].name) == 0) X return(1); /* found it! */ X } X X return(0); X} X Xextract_comment(comment, buffer, first, last) Xchar *comment, *buffer; Xint first, last; X{ X /** Buffer contains a comment, located between the first and last X values. Copy that into 'comment', but remove leading and X trailing white space. Note also that it doesn't copy past X a comma, so `unpublishable' comments can be of the form; X dave: Dave Taylor, HP Labs : taylor@hplabs X and the output will be "taylor@hplabs (Dave Taylor)". X **/ X X register int loc = 0; X X /** first off, skip the LEADING white space... **/ X X while (whitespace(buffer[first])) first++; X X /** now let's backup the 'last' value until we hit a non-whitespace **/ X X last -= 2; /* starts at ch AFTER equals.. */ X while (whitespace(buffer[last])) last--; X X /** now a final check to make sure we're still talking about a X reasonable string (rather than a "joe :: joe@dec" type string) **/ X X if (first < last) { X /* one more check - let's find the comma, if present... */ X for (loc=first; loc < last; loc++) X if (buffer[loc] == ',') { X last = loc-1; X break; X } X loc = 0; X while (first <= last) X comment[loc++] = buffer[first++]; X comment[loc] = '\0'; X } X} X Xupdate_alias_file_locations() X{ X /** a short-term routine to ensure that the data files are X moved into the correct directory... **/ X X char source[SLEN], dest[SLEN]; X X /** first let's create the directory if it ain't there... **/ X X sprintf(source, "%s/.elm", home); X X /** Some systems don't have a mkdir call - how inconvienient! **/ X#ifdef NOMKDIR X system("mkdir $HOME/.elm"); X system("chmod 700 $HOME/.elm"); X#else X (void) mkdir(source, 0700); X#endif NOMKDIR X X /** now *link* the files... **/ X X sprintf(source, "%s/.alias_text", home); X sprintf(dest, "%s/%s", home, ALIAS_TEXT); X link(source, dest); X X sprintf(source, "%s/.alias_hash", home); X sprintf(dest, "%s/%s", home, ALIAS_HASH); X link(source, dest); X X sprintf(source, "%s/.alias_data", home); X sprintf(dest, "%s/%s", home, ALIAS_DATA); X link(source, dest); X X printf("\n*** Moved all data files into %s/.elm directory ***\n\n", X home); X} SHAR_EOF chmod 0444 utils/newalias.c || echo "restore of utils/newalias.c fails" echo "x - extracting utils/newmail.c (Text)" sed 's/^X//' << 'SHAR_EOF' > utils/newmail.c && X Xstatic char rcsid[] = "@(#)$Id: newmail.c,v 2.1 88/09/15 21:07:35 syd Exp $"; X X/******************************************************************************* X * The Elm Mail System - $Revision: 2.1 $ $State: Exp $ X * X * Copyright (c) 1986 Dave Taylor X ******************************************************************************* X * Bug reports, patches, comments, suggetions should be sent to: X * X * Eric D. Christensen - edc@altnet.ALTOS.COM X * uunet!altnet!edc X * X ******************************************************************************* X * $Log: newmail.c,v $ X * Revision 2.1 88/09/15 21:07:35 syd X * checked in with -k by syd at 88.09.15.21.07.35. X * X * 88/09/01 Rob Bernardo <gatech!pbhyf.PacBell.COM!rob> X * The buffer that contains the prefix string of a file spec was X * undersized. X * X * 88/08/27 nicmad!brown (Mike Brown) X * add extern int errno for BSD ifdef X * X * Revision 2.1 88/07/21 10:01:54 edc X * Final hacks and cleanup to the 2.1 alpha test release X * X * Revision 2.0 88/06/27 16:54:11 edc X * The original 2.0 gamma sources as leaked from HP X * X * X * X ******************************************************************************/ X X/** This is actually two programs folded into one - 'newmail()' and X 'wnewmail()'. They perform essentially the same function, to X monitor the mail arriving in a set of/a mailbox or folder, but X newmail is designed to run in background on a terminal, and X wnewmail is designed to have a window of its own to run in. X X The main difference is that wnewmail checks for mail more often. X X The usage parameters are: X X -i <interval> how often to check for mail X (default: 60 secs if newmail, X 10 secs if wnewmail) X X <filename> name of a folder to monitor X (can prefix with '+'/'=', or can X default to the incoming mailbox) X X <filename>=prefix file to monitor, output with specified X prefix when mail arrives. X X If we're monitoring more than one mailbox the program will prefix X each line output (if 'newmail') or each cluster of mail (if 'wnewmail') X with the basename of the folder the mail has arrived in. In the X interest of exhaustive functionality, you can also use the "=prefix" X suffix (eh?) to specify your own strings to prefix messages with. X X The output format is either: X X newmail: X >> New mail from <user> - <subject> X >> Priority mail from <user> - <subject> X X >> <folder>: from <user> - <subject> X >> <folder>: Priority from <user> - <subject> X X wnewmail: X <user> - <subject> X Priority: <user> - <subject> X X <folder>: <user> - <subject> X <folder>: Priority: <user> - <subject>\fR X X**/ X X#include <stdio.h> X#include <errno.h> X#include <sys/types.h> X#include <sys/stat.h> X X#include "defs.h" X X#ifdef AUTO_BACKGROUND X#include <signal.h> /* background jobs ignore some signals... */ X#endif X Xstatic char ident[] = { WHAT_STRING }; X X#define LINEFEED (char) 10 X#define BEGINNING 0 /* seek fseek(3S) */ X#define DEFAULT_INTERVAL 60 X X#define MAX_FOLDERS 25 /* max we can keep track of */ X X#define NO_SUBJECT "(No Subject Specified)" X X#define metachar(c) (c == '+' || c == '=' || c == '%') X Xchar *getusername(); Xlong bytes(); X Xstruct folder_struct { X char foldername[SLEN]; X char prefix[SHORT_SLEN]; X FILE *fd; X long filesize; X } folders[MAX_FOLDERS]; X Xint interval_time; /* how long to sleep between checks */ X debug = 0, /* include verbose debug output? */ X in_window = 0; /* are we running as 'wnewmail'? */ X total_folders = 0, /* # of folders we're monitoring */ X current_folder = 0; /* struct pointer for looping */ X X#ifdef BSD Xextern int errno; X#endif X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X extern char *optarg; X extern int optind, opterr; X char *ptr; X int c, i, done; X long lastsize, X newsize; /* file size for comparison.. */ X X interval_time = DEFAULT_INTERVAL; X opterr = 0; X X /** let's see if the first character of the basename of the X command invoked is a 'w' (e.g. have we been called as X 'wnewmail' rather than just 'newmail'?) X **/ X X for (i=0, ptr=(argv[0] + strlen(argv[0])-1); !i && ptr > argv[0]; ptr--) X if (*ptr == '/') { X in_window = (*(ptr+1) == 'w'); X i++; X } X X if (ptr == argv[0] && i == 0 && argv[0][0] == 'w') X in_window = 1; X X while ((c = getopt(argc, argv, "di:w")) != EOF) { X switch (c) { X case 'd' : debug++; break; X case 'i' : interval_time = atoi(optarg); break; X case 'w' : in_window = 1; break; X default : usage(); exit(1); X } X } X X if (interval_time < 10) X fprintf(stderr, X"Warning: interval set to %d second%s. I hope you know what you're doing!\n", X interval_time, interval_time == 1 ? "" : "s"); X X /* now let's parse the foldernames, if any are given */ X X if (optind >= argc) /* get default */ X add_default_folder(); X else { X while (optind < argc) X add_folder(argv[optind++]); X pad_prefixes(); /* for nice output...*/ X } X X#ifdef AUTO_BACKGROUND X if (! in_window) { X if (fork()) /* automatically puts this task in background! */ X exit(0); X X signal(SIGINT, SIG_IGN); X signal(SIGQUIT, SIG_IGN); X } X#endif X X if (in_window && ! debug) X printf("Incoming mail:\n"); X X while (1) { X X#ifndef AUTO_BACKGROUND /* won't work if we're nested this deep! */ X if (getppid() == 1) /* we've lost our shell! */ X exit(); X#endif X if (! isatty(1)) /* we're not sending output to a tty any more */ X exit(); X X if (debug) printf("\n----\n"); X X for (i = 0; i < total_folders; i++) { X X if (debug) X printf("[checking folder #%d: %s]\n", i, folders[i].foldername); X X if (folders[i].fd == (FILE *) NULL) { X X if ((folders[i].fd = fopen(folders[i].foldername,"r")) == NULL) X if (errno == EACCES) { X fprintf(stderr, "\nPermission to monitor %s denied!\n\n", X folders[i].foldername); X sleep(5); X exit(1); X } X } X X if ((newsize = bytes(folders[i].foldername)) > X folders[i].filesize) { /* new mail has arrived! */ X X if (debug) X printf( X "\tnew mail has arrived! old size = %ld, new size=%ld\n", X folders[i].filesize, newsize); X X /* skip what we've read already... */ X X if (fseek(folders[i].fd, folders[i].filesize, X BEGINNING) != 0) X perror("fseek()"); X X folders[i].filesize = newsize; X X if (in_window) X putchar((char) 007); /* BEEP!*/ X else X printf("\n\r"); /* blank lines surrounding message */ X X read_headers(i); /* read and display new mail! */ X X if (! in_window) X printf("\n\r"); X } X else if (newsize != folders[i].filesize) { /* file SHRUNK! */ X X folders[i].filesize = bytes(folders[i].foldername); X (void) fclose(folders[i].fd); /* close it and ... */ X folders[i].fd = (FILE *) NULL; /* let's reopen the file */ X X lastsize = folders[i].filesize; X done = 0; X X while (! done) { X sleep(0); /* basically gives up our CPU slice */ X newsize = bytes(folders[i].foldername); X if (newsize != lastsize) X lastsize = newsize; X else X done++; X } X X folders[i].filesize = newsize; X } X } X X sleep(interval_time); X } X} X Xint Xread_headers(current_folder) Xint current_folder; X{ X /** read the headers, output as found given current_folder, X the prefix of that folder, and whether we're in a window X or not. X **/ X X char buffer[LONG_SLEN], from_whom[SLEN], subject[SLEN]; X register int subj = 0, in_header = 1, count = 0, priority=0; X X while (fgets(buffer, LONG_SLEN, folders[current_folder].fd) != NULL) { X if (first_word(buffer,"From ")) { X if (real_from(buffer, from_whom)) { X subj = 0; X in_header = 1; X } X } X else if (in_header) { X if (first_word(buffer,">From")) X forwarded(buffer, from_whom); /* return address */ X else if (first_word(buffer,"Subject:") || X first_word(buffer,"Re:")) { X if (! subj++) { X remove_first_word(buffer); X strcpy(subject, buffer); X } X } X else if (first_word(buffer,"Priority:")) X priority++; X else if (first_word(buffer,"From:")) X parse_arpa_from(buffer, from_whom); X else if (buffer[0] == LINEFEED) { X in_header = 0; /* in body of message! */ X show_header(priority, from_whom, subject, current_folder); X from_whom[0] = 0; X subject[0] = 0; X count++; X } X } X } X return(count); X} X Xadd_folder(name) Xchar *name; X{ X /* add the specified folder to the list of folders...ignore any X problems we may having finding it (user could be monitoring X a mailbox that doesn't currently exist, for example) X */ X X char *cp, buf[SLEN]; X X if (current_folder > MAX_FOLDERS) { X fprintf(stderr, X "Sorry, but I can only keep track of %d folders.\n", MAX_FOLDERS); X exit(1); X } X X /* now let's rip off the suffix "=<string>" if it's there... */ X X for (cp = name + strlen(name); cp > name+1 && *cp != '=' ; cp--) X /* just keep stepping backwards */ ; X X /* if *cp isn't pointing to the first character we'e got something! */ X X if (cp > name+1) { X X *cp++ = '\0'; /* null terminate the filename & get prefix */ X X if (metachar(*cp)) cp++; X X strcpy(folders[current_folder].prefix, cp); X } X else { /* nope, let's get the basename of the file */ X for (cp = name + strlen(name); cp > name && *cp != '/'; cp--) X /* backing up a bit... */ ; X X if (metachar(*cp)) cp++; X if (*cp == '/') cp++; X X strcpy(folders[current_folder].prefix, cp); X } X X /* and next let's see what kind of weird prefix chars this user X might be testing us with. We can have '+'|'='|'%' to expand X or a file located in the incoming mail dir... X */ X X if (metachar(name[0])) X expand_filename(name, folders[current_folder].foldername); X else if (access(name, 00) == -1) { X /* let's try it in the mail home directory */ X sprintf(buf, "%s%s", mailhome, name); X if (access(buf, 00) != -1) /* aha! */ X strcpy(folders[current_folder].foldername, buf); X else X strcpy(folders[current_folder].foldername, name); X } X else X strcpy(folders[current_folder].foldername, name); X X /* now let's try to actually open the file descriptor and grab X a size... */ X X if ((folders[current_folder].fd = X fopen(folders[current_folder].foldername, "r")) == NULL) X if (errno == EACCES) { X fprintf(stderr, "\nPermission to monitor \"%s\" denied!\n\n", X folders[current_folder].foldername); X exit(1); X } X X folders[current_folder].filesize = X bytes(folders[current_folder].foldername); X X /* and finally let's output what we did */ X X if (debug) X printf("folder %d: \"%s\" <%s> %s, size = %ld\n", X current_folder, X folders[current_folder].foldername, X folders[current_folder].prefix, X folders[current_folder].fd == NULL? "not found" : "opened", X folders[current_folder].filesize); X X /* and increment current-folder please! */ X X current_folder++; X total_folders++; X} X Xadd_default_folder() X{ X /* this routine will add the users home mailbox as the folder X to monitor. Since there'll only be one folder we'll never X prefix it either... X */ X X sprintf(folders[0].foldername, "%s%s", mailhome, getusername()); X X folders[0].fd = fopen(folders[0].foldername, "r"); X folders[0].filesize = bytes(folders[0].foldername); X X if (debug) X printf("default folder: \"%s\" <%s> %s, size = %ld\n", X folders[0].foldername, X folders[0].prefix, X folders[0].fd == NULL? "not found" : "opened", X folders[0].filesize); X X total_folders = 1; X} X Xint Xreal_from(buffer, who) Xchar *buffer, *who; X{ X /***** returns true iff 's' has the seven 'from' fields, X initializing the who to the sender *****/ X X char junk[80]; X X junk[0] = '\0'; X sscanf(buffer, "%*s %s %*s %*s %*s %*s %s", X who, junk); X return(junk[0] != '\0'); X} X Xforwarded(buffer, who) Xchar *buffer, *who; X{ X /** change 'from' and date fields to reflect the ORIGINATOR of X the message by iteratively parsing the >From fields... **/ X X char machine[80], buff[80]; X X machine[0] = '\0'; X sscanf(buffer, "%*s %s %*s %*s %*s %*s %*s %*s %*s %s", X who, machine); X X if (machine[0] == '\0') /* try for srm address */ X sscanf(buffer, "%*s %s %*s %*s %*s %*s %*s %*s %s", X who, machine); X X if (machine[0] == '\0') X sprintf(buff,"anonymous"); X else X sprintf(buff,"%s!%s", machine, who); X X strncpy(who, buff, 80); X} X X Xremove_first_word(string) Xchar *string; X{ /** removes first word of string, ie up to first non-white space X following a white space! **/ X X register int loc; X X for (loc = 0; string[loc] != ' ' && string[loc] != '\0'; loc++) X ; X X while (string[loc] == ' ' || string[loc] == '\t') X loc++; X X move_left(string, loc); X} X Xmove_left(string, chars) Xchar string[]; Xint chars; X{ X /** moves string chars characters to the left DESTRUCTIVELY **/ X X register int i; X X chars--; /* index starting at zero! */ X X for (i=chars; string[i] != '\0' && string[i] != '\n'; i++) X string[i-chars] = string[i]; X X string[i-chars] = '\0'; X} X Xshow_header(priority, from, subject, current_folder) Xint priority; Xchar *from, *subject; Xint current_folder; X{ X /** output header in clean format, including abbreviation X of return address if more than one machine name is X contained within it! **/ X char buffer[SLEN]; X int loc, i=0, exc=0; X X#ifdef PREFER_UUCP X X if (chloc(from, '!') != -1 && in_string(from, BOGUS_INTERNET)) X from[strlen(from) - strlen(BOGUS_INTERNET)] = '\0'; X X#endif X X loc = strlen(from); X X while (exc < 2 && loc > 0) X if (from[--loc] == '!') X exc++; X X if (exc == 2) { /* lots of machine names! Get last one */ X loc++; X while (loc < strlen(from) && loc < SLEN) X buffer[i++] = from[loc++]; X buffer[i] = '\0'; X strcpy(from, buffer); X } X X if (strlen(subject) < 2) X strcpy(subject, NO_SUBJECT); X X if (in_window) X if (total_folders > 1) X printf("%s: %s%s -- %s\n", X folders[current_folder].prefix, X priority? "Priority " : "", from, subject); X else X printf("%s%s -- %s\n", X priority? "Priority " : "", from, subject); X else X if (total_folders > 1) X printf(">> %s: %sail from %s - %s\n\r", X folders[current_folder].prefix, X priority? "Priority m" : "M", from, subject); X else X printf(">> %sail from %s - %s\n\r", X priority? "Priority m" : "M", from, subject); X} X Xparse_arpa_from(buffer, newfrom) Xchar *buffer, *newfrom; X{ X /** try to parse the 'From:' line given... It can be in one of X two formats: X From: Dave Taylor <hpcnou!dat> X or From: hpcnou!dat (Dave Taylor) X Change 'newfrom' ONLY if sucessfully parsed this entry and X the resulting name is non-null! X **/ X X char temp_buffer[SLEN], *temp; X register int i, j = 0; X X temp = (char *) temp_buffer; X temp[0] = '\0'; X X no_ret(buffer); /* blow away '\n' char! */ X X if (lastch(buffer) == '>') { X for (i=strlen("From: "); buffer[i] != '\0' && buffer[i] != '<' && SHAR_EOF echo "End of part 21" echo "File utils/newmail.c is continued in part 22" echo "22" > s2_seq_.tmp exit 0 -- ===================================================================== Sydney S. Weinstein, CDP, CCP Elm Coordinator Datacomp Systems, Inc. Voice: (215) 947-9900 {allegra,bellcore,bpa,vu-vlsi}!dsinc!syd FAX: (215) 938-0235