syd@dsinc.UUCP (Syd Weinstein) (12/16/88)
---- Cut Here and unpack ---- #!/bin/sh # this is part 22 of a multipart archive # do not concatenate these parts, unpack them in order with /bin/sh # file utils/newmail.c continued # CurArch=22 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/newmail.c" sed 's/^X//' << 'SHAR_EOF' >> utils/newmail.c 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 /* 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} X Xlong Xbytes(name) Xchar *name; X{ X /** return the number of bytes in the specified file. This X is to check to see if new mail has arrived.... **/ X X int ok = 1; X extern int errno; /* system error number! */ X struct stat buffer; X X if (stat(name, &buffer) != 0) X if (errno != 2) { X fprintf(stderr,"Error %d attempting fstat on %s", errno, name); X exit(1); X } X else X ok = 0; X X return(ok ? buffer.st_size : 0); X} X Xchar *getusername() X{ X /** Getting the username on some systems is a real pain, so... X This routine is guaranteed to return a usable username **/ X X char *return_value, *getlogin(); X X if ((return_value = getlogin()) == NULL) X if ((return_value = getlogin()) == NULL) { X printf("Newmail: I can't get username!\n"); X exit(1); X } X X return( (char *) return_value); X} X Xusage() X{ X /* print a nice friendly usage message */ X X fprintf(stderr, X"\nUsage: %s [-d] [-i interval] [-w] {folders}\n"); X fprintf(stderr, "\nWhere:\n"); X fprintf(stderr, " -d\tturns on debugging output\n"); X fprintf(stderr, X" -i D\tsets the interval checking time to 'D' seconds\n"); X fprintf(stderr, X" -w\tforces 'window'-style output, and bypasses auto-background\n\n"); X fprintf(stderr, X"folders can be specified by relative or absolute path names, can be the name\n"); X fprintf(stderr, X"of a mailbox in the incoming mail directory to check, or can have one of the\n"); X fprintf(stderr, X"standard Elm mail directory prefix chars (e.g. '+', '=' or '%').\n"); X fprintf(stderr, X"Furthermore, any folder can have '=string' as a suffix to indicate a folder\n"); X fprintf(stderr, X"identifier other than the basename of the file\n\n"); X} X X Xexpand_filename(name, store_space) Xchar *name, *store_space; X{ X strcpy(store_space, name); X if (expand(store_space) == 0) { X fprintf(stderr,"Sorry, but I couldn't expand \"%s\"\n",name); X exit(1); X } X} X Xpad_prefixes() X{ X /** This simple routine is to ensure that we have a nice X output format. What it does is whip through the different X prefix strings we've been given, figures out the maximum X length, then space pads the other prefixes to match. X **/ X X register int i, j, len = 0; X X for (i=0; i < total_folders; i++) X if (len < (j=strlen(folders[i].prefix))) X len = j; X X for (i=0; i < total_folders; i++) X for (j = strlen(folders[i].prefix); j < len; j++) X strcat(folders[i].prefix, " "); X} SHAR_EOF echo "File utils/newmail.c is complete" chmod 0444 utils/newmail.c || echo "restore of utils/newmail.c fails" echo "x - extracting utils/postmail.c (Text)" sed 's/^X//' << 'SHAR_EOF' > utils/postmail.c && X Xstatic char rcsid[] = "@(#)$Id: postmail.c,v 2.1 88/09/15 21:07:37 syd Exp $"; X X/******************************************************************************* X * The Elm Mail System - $Revision: 2.1 $ $State: Exp $ X * X * (C) Copyright 1987, Dave Taylor X * (C) Copyright 1987, Hewlett-Packard Labs 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: postmail.c,v $ X * Revision 2.1 88/09/15 21:07:37 syd X * checked in with -k by syd at 88.09.15.21.07.37. X * X * Revision 2.1 88/07/21 10:01:57 edc X * Final hacks and cleanup to the 2.1 alpha test release X * X * Revision 2.0 88/06/27 16:54:13 edc X * The original 2.0 gamma sources as leaked from HP X * X * X * X ******************************************************************************/ X X/** This program is designed to allow mailing lists to easily gateway into X netnews groups by accepting from stdin a mail message, reformatting it, X and invoking "inews" to submit it to the specified newsgroup. Over X and above other programs of this nature, this preserves the following X header information if present: X X Organization: X X and rewrites the From: field to properly fit in with the inews X perception of what it should look like (e.g user@hostname.domain). X The actual return address will be included as the "Reply-To:" X header. X X This program will also be able to scan the subject line and compare X it to other notes posted to the specified group, extracting X references if possible... X X**/ X X#include <stdio.h> X#include <ctype.h> X#include <errno.h> X X#define SLEN 256 X#define NLEN 40 X X#define INEWS "/usr/local/lib/news/inews" X X#define TEMPFILE "/tmp/postmail." X X#define BOGUS_ADDRESS "@hplabs.HP.COM" X#define UUCP_HOSTNAME "hplabs" X X#define DEFAULT_DOMAIN ".HPL.HP.COM" X X/** if these are going into a moderated group, then you'll want to X define "INCLUDE_APPROPED_LINE" to have it add an appropriate X header to the posting. X**/ X X#define INCLUDE_APPROVED_LINE X X#ifdef INCLUDE_APPROVED_LINE X#define APPROVAL "postmail@hplabs" X#endif X X/** and some headers for future reference and all... **/ X X#define FROM "From:" X#define FROMLEN 5 X X#define SUBJ "Subj:" X#define SUBJLEN 5 X X#define SUBJECT "Subject:" X#define SUBJECTLEN 8 X X#define ORGANIZATION "Organization" X#define ORGANISATION "Organisation" X#define ORGLEN 12 X X#define FULLNAME "Fullname:" X#define FULLNAMELEN 9 X X#define equal(a,b,c) (strncmp(a,b,c) == 0) X#define whitespace(c) (c == ' ' || c == '\t') X#define valid_char(c) ( isalnum(c) || c == '_' || c == '-' || c == '.') X Xint debug = 0; /* shall we output debugging info? */ Xchar from_line[SLEN], /* space to save the From: line */ X fullname[SLEN], /* and the fullname piece of it */ X alt_fullname[SLEN], /* ...the Fullname: line */ X clunky_from_line[SLEN], /* ... the From_ line */ X subject_line[SLEN], /* ... the Subject: line */ X organization[SLEN]; /* and the Organization: line */ X Xextern int errno; X Xmain(argc, argv) Xchar *argv[]; X{ X FILE *outfd; /* tempfile file descriptor */ X char newsgroup[NLEN], /* what netnews group to post to? */ X buffer[SLEN], /* buffer for reading message */ X tempfilename[NLEN], /* some space for temp storage... */ X c; /* for starting arg parsing */ X register int lines = 0, /* number of lines in message */ X in_headers = 1; /* for breaking message into 2 pts */ X X extern int optind; /* for starting argument parsing.. */ X X /** get the starting parameters... **/ X X while ((c = getopt(argc, argv, "d")) != EOF) { X switch (c) { X case 'd' : debug++; break; X case '?' : printf("Usage: %s [-d] newsgroup < mail-message\n", X argv[0]); X exit(1); X } X } X X /** did the user remember to specify a newsgroup? **/ X X if (optind != argc-1) { X printf("You need to specify a newsgroup to post this to;\n"); X printf("Usage: %s [-d] newsgroup < mail-message\n", argv[0]); X exit(1); X } X X strcpy(newsgroup, argv[optind]); X X /** now let's see if it's a valid newsgroup... **/ X X if (! valid_newsgroup(newsgroup)) { X printf("Sorry, but \"%s\" isn't a valid newsgroup!\n", newsgroup); X exit(1); X } X X /** now let's open a tempfile and, extract the headers we're X interested in, save the message to it... **/ X X sprintf(tempfilename, "%s%d", TEMPFILE, getpid()); X X if ((outfd = fopen(tempfilename, "w")) == NULL) { X printf("Sorry, but I couldn't open \"%s\" for writing...\n", X tempfilename); X exit(1); X } X X while (gets(buffer) != NULL) { X if (in_headers) { X if (lines++ == 0) X strcpy(clunky_from_line, buffer); /* always .. */ X if (equal(buffer, FROM, FROMLEN)) X strcpy(from_line, buffer); /* what a deal! */ X else if (equal(buffer, SUBJ, SUBJLEN) || X equal(buffer, SUBJECT, SUBJECTLEN)) X strcpy(subject_line, buffer); X else if (equal(buffer, ORGANIZATION, ORGLEN) || X equal(buffer, ORGANISATION, ORGLEN)) X strcpy(organization, buffer); /* got it too! */ X else if (equal(buffer, FULLNAME, FULLNAMELEN)) X strcpy(alt_fullname, (char *) buffer + FULLNAMELEN + 1); X else if (strlen(buffer) < 2) X break; X } X } X X /** We'll leave the file descriptor there while we go and figure X out how to format these headers and add them to the temporary X output file... X **/ X X /** The order of our headers lines will be: X From: X Newsgroups: X Subject: X Reply-To: X Organization: X Approved: X **/ X X output_from_line(clunky_from_line, from_line, outfd); X X fprintf(outfd, "Newsgroups: %s\n", newsgroup); X X if (strlen(subject_line) > 0) X fprintf(outfd, "%s\n", subject_line); X else X fprintf(outfd, "Subject: <none>\n"); X X output_reply_to(clunky_from_line, outfd); X X if (strlen(organization) > 0) X fprintf(outfd, "%s\n", organization); X X#ifdef INCLUDE_APPROVED_LINE X fprintf(outfd, "Approved: %s\n\n", APPROVAL); X#else X fprintf(outfd, "\n"); X#endif X X while (gets(buffer) != NULL) X fprintf(outfd, "%s\n", buffer); X fclose(outfd); X X /** now we've a temp file that is all ready to post, so X let's go ahead and post it! X **/ X X sprintf(buffer, "%s -M -h -n %s < %s", INEWS, newsgroup, tempfilename); X X if (system(buffer) != 0) { X fprintf(stderr,"Postmail failed! Got error #%d trying:\n", errno); X fprintf(stderr,"> %s\n", buffer); X } X else X (void) unlink(tempfilename); X X exit(0); X} X Xint Xvalid_newsgroup(newsgroup) Xchar *newsgroup; X{ X /* this will check to see if it's a valid newsgroup or not */ X X return(1); X} X Xoutput_from_line(from_, from_colon, outfd) Xchar *from_, *from_colon; XFILE *outfd; X{ X /** given the From_ and From: lines from the message, try to X figure out the optimal `user@hostname.domain (fullname)' X style From: line to output to the file, and do so. X **/ X X char raw_address[SLEN], *p, *p2; X register int i = 0, j = 0; X X fullname[0] = raw_address[0] = '\0'; X X if (strlen(from_colon) == 0) X sscanf(from_, "%*s %s", raw_address); X else { X p = from_colon + strlen(from_colon) - 1; X if (*p == '>') { X while (*p != '<') p--; X p++; /* skip the leading '<' please */ X for (p2 = from_colon + FROMLEN; *p2 != '<'; ) X if (i == 0 && whitespace(*p2)) X p2++; X else X fullname[i++] = *p2++; X while (*p != '>') X if (j == 0 && whitespace(*p)) X p++; X else X raw_address[j++] = *p++; X } X else { X for (p2 = from_colon + FROMLEN; *p2 != '(' && *p2 > '\0'; ) X if (j == 0 && whitespace(*p2)) X p2++; X else X raw_address[j++] = *p2++; X if (*p2 == '(') X while (*++p2 != ')') X fullname[i++] = *p2; X } X fullname[i] = raw_address[j] = '\0'; X X /** let's remove trailing white space, if any **/ X X for (p = fullname + strlen(fullname) - 1; whitespace(*p); X *p-- ='\0') ; X X for (p = raw_address + strlen(raw_address) - 1; whitespace(*p); X *p-- ='\0') ; X X /** and now for debugging purposes... **/ X X if (debug) X printf("got fullname=\"%s\" and raw_address=\"%s\"\n", X fullname, raw_address); X } X X clean_up_raw_address(raw_address); X X if (strlen(alt_fullname) > 0) X strcpy(fullname, alt_fullname); X X if (strlen(fullname) > 0) X fprintf(outfd, "From: %s (%s)\n", raw_address, fullname); X else X fprintf(outfd, "From: %s\n", raw_address); X} X Xoutput_reply_to(clunky_from_line, outfd) Xchar *clunky_from_line; XFILE *outfd; X{ X /** Output a Reply-To: line that is the return address of the mail **/ X X char buffer[SLEN], newbuffer[SLEN], *p; X X sscanf(clunky_from_line, "%*s %s", buffer); X X if (occurances_of('!', buffer) && occurances_of('@', buffer)) { X for (p = buffer + strlen(buffer) - 1; *p != '@'; p--) ; X if (strcmp(p, BOGUS_ADDRESS) == 0) { X *p = '\0'; X sprintf(newbuffer, "%s!%s", UUCP_HOSTNAME, buffer); X strcpy(buffer, newbuffer); X } X } X X if (strlen(fullname) > 0) X fprintf(outfd, "Reply-To: %s (%s)\n", buffer, fullname); X else X fprintf(outfd, "Reply-To: %s\n", buffer); X} X X#define no ! X Xclean_up_raw_address(address) Xchar *address; X{ X /** This turns out to be an interesting routine: it takes an X address of any form and attempts to extract the user@host X core of it. When it has done this, it will then check to X see if the host had a domain specified with it. If so, then X it will simply return "user@host.domain", otherwise it will X append the default domain to the host and return something X more on the order of "user@host.<domain>". X X (this algorithm is out of the HP Labs PostOffice system) X X ========================================================== X X Given an email address this routine will attempt to prune X it down to a base user@host or host!user format. The X possible address formats include: X X # example input desired output X --- ------------------------ ---------------- X 1. hosta!hostb!hostc!user <hostc!user> X 2. hosta!hostb!user@hostd <hostb!user> [*] X 3. user%hosta%hostb@hostc <user%hosta@hostb> X 4. @hosta:user@hostb <user@hostb> X X [*] note that we consider all mixed mode addresses to have X the UUCP notational part added first... X **/ X X char username[SLEN], hostname[SLEN], new_address[SLEN]; X register int i, j = 0, bangs_in_address, at_signs_in_address, X percents_in_address; X X bangs_in_address = occurances_of('!', address); X at_signs_in_address = occurances_of('@', address); X percents_in_address = occurances_of('%', address); X X /* this deals with mixed mode addresses and all... */ X X if (bangs_in_address && at_signs_in_address == 1) { X /* remove the entire @host and/or %host@host part */ X for (i=strlen(address); address[i] != '!'; i--) ; X i++; /* skip past the '!' please */ X while (valid_char(address[i])) i++; X address[i] = '\0'; X percents_in_address = at_signs_in_address = 0; X i = 0; X } X X if (debug) X printf("! count = %d, @ count = %d, %% count = %d\n", X bangs_in_address, at_signs_in_address, percents_in_address); X X /* and now to the normal test and testing, please */ X X if (no at_signs_in_address) { /* #1: pure 'uucp' address */ X if (bangs_in_address > 1) { X for (i=strlen(address); address[i] != '!'; i--) ; X i--; /* skip this bang */ X while (address[i] != '!') i--; X j = 0; X for (i++; address[i] != '\0'; new_address[j++] = address[i++]) ; X new_address[j] = '\0'; X } X else /* simple too - only one hop */ X strcpy(new_address, address); X } X else { X if (no percents_in_address) { /* either #2 or #4..same algorithm */ X for (i=strlen(address); address[i] != '@'; i--) ; X i--; /* back up to before the '@' sign too */ X while (valid_char(address[i]) && i > -1) i--; X j = 0; X for (++i; address[i] != '\0'; new_address[j++] = address[i++]) ; X new_address[j] = '\0'; X } X else { /* case #3, of course... */ X /** get to the leftmost percent sign... **/ X for (i=0; address[i] != '%'; i++) ; X /** now back up to include username... **/ X i--; /* include this percent sign */ X while (valid_char(address[i]) && i > -1) i--; X i++; j = 0; X /* now copy over until we hit the an '@' sign... */ X while (address[i] != '@') X new_address[j++] = address[i++]; X new_address[j] = '\0'; X /** finally, back up and change the rightmost '%' to an '@' **/ X while (new_address[j] != '%') j--; X new_address[j] = '@'; /* replace '%' with '@' please */ X } X } X X if (occurances_of('!', new_address) != 0) { X for (i=0; new_address[i] != '!'; i++) X hostname[i] = new_address[i]; X hostname[i] = '\0'; X j = 0; X while (new_address[++i] != '\0') X username[j++] = new_address[i]; X username[j] = '\0'; X sprintf(new_address, "%s@%s", username, hostname); X } X X if (occurances_of('@', new_address) == 0) /* NONE? */ X strcat(new_address, BOGUS_ADDRESS); X X if (occurances_of('.', new_address) == 0) X strcat(new_address, DEFAULT_DOMAIN); X X if (debug) X printf("ended up with base address: \"%s\"\n", new_address); X X strcpy(address, new_address); X} X Xint Xoccurances_of(c, string) Xchar c, *string; X{ X /** returns the number of times 'c' occurs in the string **/ X X register int i, count = 0; X X for (i=0; i < strlen(string); i++) X if (string[i] == c) count++; X X return(count); X} SHAR_EOF chmod 0444 utils/postmail.c || echo "restore of utils/postmail.c fails" echo "x - extracting utils/readmsg.c (Text)" sed 's/^X//' << 'SHAR_EOF' > utils/readmsg.c && X Xstatic char rcsid[] = "@(#)$Id: readmsg.c,v 2.1 88/09/15 21:07:39 syd Exp $"; X X/******************************************************************************* X * The Elm Mail System - $Revision: 2.1 $ $State: Exp $ X * X * Copyright (c) 1985 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: readmsg.c,v $ X * Revision 2.1 88/09/15 21:07:39 syd X * checked in with -k by syd at 88.09.15.21.07.39. X * X * Revision 2.1 88/07/21 10:02:00 edc X * Final hacks and cleanup to the 2.1 alpha test release X * X * Revision 2.0 88/06/27 16:54:14 edc X * The original 2.0 gamma sources as leaked from HP X * X * X * X ******************************************************************************/ X X/** This routine adds the functionality of the "~r" command to the Elm mail X system while still allowing the user to use the editor of their choice. X X The program, without any arguments, tries to read a file in the users home X directory called ".readmsg" (actually defined in the sysdefs.h system X defines file) and if it finds it reads the current message. If it doesn't X find it, it will return a usage error. X X The program can also be called with an explicit message number, list of X message numbers, or a string to match in the message (including the header). X NOTE that when you use the string matching option it will match the first X message containing that EXACT (case sensitive) string and then exit. X X Changed 5/86 to SORT the input list of message numbers to ensure that X they're in first-to-last order... X X Added the "weed" option as the default. This is inspired by the mail X system used at NASA RIACS. If THEY can do it, so can we!! X X Also added '*' as a flag - indicating ALL messages in the mailbox. X X**/ X X#include <stdio.h> X#include <ctype.h> X X#include "defs.h" X X/** three defines for what level of headers to display **/ X X#define ALL 1 X#define WEED 2 X#define NONE 3 X X#define metachar(c) (c == '=' || c == '+' || c == '%') X Xstatic char ident[] = { WHAT_STRING }; X X#define MAX_LIST 25 /* largest single list of arguments */ X X#define LAST_MESSAGE 9999 /* last message in list ('$' char) */ X#define LAST_CHAR '$' /* char to delimit last message.. */ X#define STAR '*' /* char to delimit all messages... */ X Xint read_message[MAX_LIST]; /* list of messages to read */ Xint messages = 0; /* index into list of messages */ X Xint numcmp(); /* strcmp, but for numbers */ Xchar *words(), /* function defined below... */ X *expand_define(); /* ditto... */ X X#define DONE 0 /* for use with the getopt */ X#define ERROR -1 /* library call... */ X Xextern char *optional_arg; /* for parsing the ... */ Xextern int opt_index; /* .. starting arguments */ X Xchar *getenv(); /* keep lint happy */ X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X FILE *file; /* generic file descriptor! */ X char filename[SLEN], /* filename buffer */ X infile[SLEN], /* input filename */ X buffer[SLEN], /* file reading buffer */ X string[SLEN]; /* string match buffer */ X X int current_in_queue = 0, /* these are used for... */ X current = 0, /* ...going through msgs */ X list_all_messages = 0, /* just list 'em all?? */ X num, /* for argument parsing */ X page_breaks = 0, /* use "^L" breaks?? */ X total, /* number of msgs current */ X include_headers = WEED, /* flag: include msg header? */ X last_message = 0, /* flag: read last message? */ X not_in_header = 0, /* flag: in msg header? */ X string_match = 0; /* flag: using string match? */ X X /**** start of the actual program ****/ X X while ((num = get_options(argc, argv, "nhf:p")) > 0) { X switch (num) { X case 'n' : include_headers = NONE; break; X case 'h' : include_headers = ALL; break; X case 'f' : strcpy(infile, optional_arg); X if (metachar(infile[0])) X if (expand(infile) == 0) X printf("%s: couldn't expand filename %s!\n", X argv[0], infile); X break; X case 'p' : page_breaks++; break; X } X } X X if (num == ERROR) { X printf("Usage: %s [-n|-h] [-f filename] [-p] <message list>\n", X argv[0]); X exit(1); X } X X /** whip past the starting arguments so that we're pointing X to the right stuff... **/ X X *argv++; /* past the program name... */ X X while (opt_index-- > 1) { X *argv++; X argc--; X } X X /** now let's figure out the parameters to the program... **/ X X if (argc == 1) { /* no arguments... called from 'Elm'? */ X sprintf(filename, "%s/%s", getenv("HOME"), readmsg_file); X if ((file = fopen(filename, "r")) != NULL) { X fscanf(file, "%d", &(read_message[messages++])); X fclose(file); X } X else { /* no arguments AND no .readmsg file!! */ X fprintf(stderr, X "Usage: readmsg [-n|-h] [-f filename] [-p] <message list>\n"); X exit(1); X } X } X else if (! isdigit(*argv[0]) && *argv[0] != LAST_CHAR && X *argv[0] != STAR) { X string_match++; X X while (*argv) X sprintf(string, "%s%s%s", string, string[0] == '\0'? "" : " ", X *argv++); X } X else if (*argv[0] == STAR) /* all messages.... */ X list_all_messages++; X else { /* list of nums */ X X while (--argc > 0) { X num = -1; X X sscanf(*argv,"%d", &num); X X if (num < 0) { X if (*argv[0] == LAST_CHAR) { X last_message++; X num = LAST_MESSAGE; X } X else { X fprintf(stderr,"I don't understand what '%s' means...\n", X *argv); X exit(1); X } X } X else if (num == 0) { /* another way to say "last" */ X last_message++; X num = LAST_MESSAGE; X } X X *argv++; X X read_message[messages++] = num; X } X X /** and now sort 'em to ensure they're in a reasonable order... **/ X X qsort(read_message, messages, sizeof(int), numcmp); X } X X /** Now let's get to the mail file... **/ X X if (strlen(infile) == 0) X sprintf(infile, "%s/%s", mailhome, getenv("LOGNAME")); X X if ((file = fopen(infile, "r")) == NULL) { X printf("But you have no mail! [ file = %d ]\n", infile); X exit(0); X } X X /** Now it's open, let's display some 'ole messages!! **/ X X if (string_match || last_message) { /* pass through it once */ X X if (last_message) { X total = count_messages(file); /* instantiate count */ X for (num=0; num < messages; num++) X if (read_message[num] == LAST_MESSAGE) X read_message[num] = total; X } X else if (string_match) X match_string(file, string); /* stick msg# in list */ X X if (total == 0 && ! string_match) { X printf("There aren't any messages to read!\n"); X exit(0); X } X } X X /** now let's have some fun! **/ X X while (fgets(buffer, SLEN, file) != NULL) { X if (strncmp(buffer, "From ", 5) == 0) { X if (! list_all_messages) { X if (current == read_message[current_in_queue]) X current_in_queue++; X if (current_in_queue >= messages) X exit(0); X } X current++; X not_in_header = 0; /* we're in the header! */ X } X if (current == read_message[current_in_queue] || list_all_messages) X if (include_headers==ALL || not_in_header) X printf("%s", buffer); X else if (strlen(buffer) < 2) { X not_in_header++; X if (include_headers==WEED) X list_saved_headers(page_breaks); X } X else if (include_headers==WEED) X possibly_save(buffer); /* check to see if we want this */ X } X X exit(0); X} X Xint Xcount_messages(file) XFILE *file; X{ X /** Returns the number of messages in the file **/ X X char buffer[SLEN]; X int count = 0; X X while (fgets(buffer, SLEN, file) != NULL) X if (strncmp(buffer, "From ", 5) == 0) X count++; X X rewind( file ); X return( count ); X} X Xmatch_string(mailfile, string) XFILE *mailfile; Xchar *string; X{ X /** Increment "messages" and put the number of the message X in the message_count[] buffer until we match the specified X string... **/ X X char buffer[SLEN]; X int message_count; X X while (fgets(buffer, SLEN, mailfile) != NULL) { X if (strncmp(buffer, "From ", 5) == 0) X message_count++; X X if (in_string(buffer, string)) { X read_message[messages++] = message_count; X rewind(mailfile); X return; X } X } X X fprintf(stderr,"Couldn't find message containing '%s'\n", string); X exit(1); X} X Xint Xnumcmp(a, b) Xint *a, *b; X{ X /** compare 'a' to 'b' returning less than, equal, or greater X than, accordingly. X **/ X X return(*a - *b); X} X Xstatic char from[SLEN], subject[SLEN], date[SLEN], to[SLEN]; X Xpossibly_save(buffer) Xchar *buffer; X{ X /** Check to see what "buffer" is...save it if it looks X interesting... We'll always try to get SOMETHING X by tearing apart the "From " line... **/ X X if (strncmp(buffer, "Date:", 5) == 0) X strcpy(date, buffer); X else if (strncmp(buffer, "Subject:", 8) == 0) X strcpy(subject,buffer); X else if (strncmp(buffer,"From:", 5) == 0) X strcpy(from, buffer); X else if (strncmp(buffer,"To: ", 3) == 0) X strncpy(to, buffer, SLEN); X else if (strncmp(buffer,"From ", 5) == 0) { X sprintf(from, "From: %s\n", words(2,1, buffer)); X sprintf(date,"Date: %s", words(3,7, buffer)); X to[0] = '\0'; X } X} X Xlist_saved_headers(page_break) Xint page_break; X{ X /** This routine will display the information saved from the X message being listed...If it displays anything it'll end X with a blank line... **/ X X register int displayed_line = FALSE; X static int messages_listed = 0; X X if (messages_listed++) X if (page_break) X putchar(FORMFEED); X else X printf( X"\n--------------------------------------------------------------------\n\n\n"); X X if (strlen(from) > 0) { printf("%s", from); displayed_line++;} X if (strlen(subject) > 0) { printf("%s", subject); displayed_line++;} X if (strlen(to) > 0) { printf("%s", to); displayed_line++;} X if (strlen(date) > 0) { printf("%s", date); displayed_line++;} X X if (displayed_line) X putchar('\n'); X} X Xchar *words(word, num_words, buffer) Xint word, num_words; Xchar *buffer; X{ X /** Return a buffer starting at 'word' and containing 'num_words' X words from buffer. Assume white space will delimit each word. X **/ X X static char internal_buffer[SLEN]; X char *wordptr, *bufptr, mybuffer[SLEN], *strtok(); X int wordnumber = 0, copying_words = 0; X X internal_buffer[0] = '\0'; /* initialize */ X X strcpy(mybuffer, buffer); X bufptr = (char *) mybuffer; /* and setup */ X X while ((wordptr = strtok(bufptr, " \t")) != NULL) { X if (++wordnumber == word) { X strcpy(internal_buffer, wordptr); X copying_words++; X num_words--; X } X else if (copying_words) { X strcat(internal_buffer, " "); X strcat(internal_buffer, wordptr); X num_words--; X } X X if (num_words < 1) X return((char *) internal_buffer); X X bufptr = NULL; X } X X return( (char *) internal_buffer); X} X Xint Xexpand(infile) Xchar *infile; X{ X /** Expand the filename since the first character is a meta- X character that should expand to the "maildir" variable X in the users ".elmrc" file... X X Note: this is a brute force way of getting the entry out X of the .elmrc file, and isn't recommended for the faint X of heart! X **/ X X FILE *rcfile; X char buffer[SLEN], *expanded_dir, *home, *getenv(), *bufptr; X int foundit = 0; X X bufptr = (char *) buffer; /* same address */ X X if ((home = getenv("HOME")) == NULL) { X printf( X "Can't expand environment variable $HOME to find .elmrc file!\n"); X exit(1); X } X X sprintf(buffer, "%s/%s", home, elmrcfile); X X if ((rcfile = fopen(buffer, "r")) == NULL) { X printf("Can't open your \".elmrc\" file (%s) for reading!\n", X buffer); X exit(1); X } X X while (fgets(buffer, SLEN, rcfile) != NULL && ! foundit) { X if (strncmp(buffer, "maildir", 7) == 0 || X strncmp(buffer, "folders", 7) == 0) { X while (*bufptr != '=' && *bufptr) X bufptr++; X bufptr++; /* skip the equals sign */ X while (whitespace(*bufptr) && *bufptr) X bufptr++; X home = bufptr; /* remember this address */ X X while (! whitespace(*bufptr) && *bufptr != '\n') X bufptr++; X X *bufptr = '\0'; /* remove trailing space */ X foundit++; X } X } X X fclose(rcfile); /* be nice... */ X X if (! foundit) { X printf("Couldn't find \"maildir\" in your .elmrc file!\n"); X exit(1); X } X X /** Home now points to the string containing your maildir, with X no leading or trailing white space... X **/ X X expanded_dir = expand_define(home); X X sprintf(buffer, "%s%s%s", expanded_dir, X (expanded_dir[strlen(expanded_dir)-1] == '/' || X infile[0] == '/') ? "" : "/", (char *) infile+1); X X strcpy(infile, buffer); X} X Xchar *expand_define(maildir) Xchar *maildir; X{ X /** This routine expands any occurances of "~" or "$var" in X the users definition of their maildir directory out of X their .elmrc file. X X Again, another routine not for the weak of heart or staunch X of will! X **/ X X static char buffer[SLEN]; /* static buffer AIEE!! */ X char name[SLEN], /* dynamic buffer!! (?) */ X *nameptr, /* pointer to name?? */ X *value; /* char pointer for munging */ X X if (*maildir == '~') X sprintf(buffer, "%s%s", getenv("HOME"), ++maildir); X else if (*maildir == '$') { /* shell variable */ X X /** break it into a single word - the variable name **/ X X strcpy(name, (char *) maildir + 1); /* hurl the '$' */ X nameptr = (char *) name; X while (*nameptr != '/' && *nameptr) nameptr++; X *nameptr = '\0'; /* null terminate */ X X /** got word "name" for expansion **/ X X if ((value = getenv(name)) == NULL) { X printf("Couldn't expand shell variable $%s in .elmrc!\n", name); X exit(1); X } X sprintf(buffer, "%s%s", value, maildir + strlen(name) + 1); X } X else X strcpy(buffer, maildir); X X return( ( char *) buffer); X} X SHAR_EOF chmod 0444 utils/readmsg.c || echo "restore of utils/readmsg.c fails" rm -f s2_seq_.tmp echo "You have unpacked the last part" 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