taylor@hpldat.UUCP (Dave Taylor) (04/28/87)
There were a couple of problems with the 'from' command, and there was an entire algorithm that was rather sub-optimal, so here's a completely new version of "utils/from.c" to replace the existing one with. -- Dave Taylor ps: expect extensive "patch" format changes to show up starting in a few days... --- Shell Archive of "from.c" # Shell Archive created by hpldat!taylor at Mon Apr 27 18:44:51 1987 # To unpack the enclosed files, please use this file as input to the # Bourne (sh) shell. This can be most easily done by the command; # sh < thisfilename # This archive contains; # utils/from.c if [ ! -d utils ] then echo creating directory utils mkdir utils fi # ---------- file utils/from.c ---------- filename="utils/from.c" if [ -f $filename ] then echo File \"$filename\" already exists\! Skipping... filename=/dev/null # throw it away else echo extracting file utils/from.c... fi cat << 'END-OF-FILE' > $filename /** from.c **/ /** print out whom each message is from in the pending folder or specified one, including a subject line if available.. Added PREFER_UUCP knowledge 6/86 Added "-n" flag, 9/86 Added "-v" flag, 3/87 (C) Copyright 1986 Dave Taylor **/ #include <stdio.h> #include "defs.h" static char ident[] = { WHAT_STRING }; #define LINEFEED (char) 10 #define metachar(c) (c == '=' || c == '+' || c == '%') FILE *mailfile; char *expand_define(); int number = 0, /* should we number the messages?? */ verbose = 0; /* and should we prepend a header? */ main(argc, argv) int argc; char *argv[]; { char infile[LONG_SLEN], username[SLEN], c; int multiple_files = 0, output_files = 0; extern int opt_index; while ((c = get_options(argc, argv, "nv")) > 0) switch (c) { case 'n': number++; break; case 'v': verbose++; break; } if (c == -1) { printf("Usage: %s [-n] {filename | username}\n", argv[0]); exit(1); } if (opt_index == argc) { strcpy(username, getlogin()); if (strlen(username) == 0) cuserid(username); sprintf(infile,"%s%s",mailhome, username); opt_index -= 1; /* ensure one pass through loop */ } multiple_files = (argc - opt_index > 1); while (opt_index < argc) { if (multiple_files) { strcpy(infile, argv[opt_index]); printf("%s%s: \n", output_files++ > 0 ? "\n":"", infile); } else if (infile[0] == '\0') strcpy(infile, argv[opt_index]); if (metachar(infile[0])) { if (expand(infile) == 0) { fprintf(stderr, "%s: couldn't expand filename %s!\n", argv[0], infile); exit(1); } } if ((mailfile = fopen(infile,"r")) == NULL) { if (opt_index+1 == argc) printf("No mail\n"); else { if (infile[0] == '/') printf("Couldn't open folder \"%s\".\n", infile); else { sprintf(infile,"%s%s", mailhome, argv[opt_index]); if ((mailfile = fopen(infile,"r")) == NULL) printf("Couldn't open folders \"%s\" or \"%s\".\n", argv[opt_index], infile); else if (read_headers()==0) printf("No messages in that folder!\n"); } } } else if (read_headers(opt_index+1 == argc)==0) if (opt_index+1 == argc) printf("No mail\n"); else printf("No messages in that folder!\n"); opt_index++; } } int read_headers(user_mailbox) int user_mailbox; { /** Read the headers, output as found. User-Mailbox is to guarantee that we get a reasonably sensible message from the '-v' option **/ char buffer[LONG_SLEN], from_whom[SLEN], subject[SLEN]; register int subj = 0, in_header = 1, count = 0; while (fgets(buffer, LONG_SLEN, mailfile) != NULL) { if (first_word(buffer,"From ")) { if (real_from(buffer, from_whom)) { subj = 0; in_header = 1; } } else if (in_header) { if (first_word(buffer,">From")) forwarded(buffer, from_whom); /* return address */ else if (first_word(buffer,"Subject:") || first_word(buffer,"Re:")) { if (! subj++) { remove_first_word(buffer); strcpy(subject, buffer); } } else if (first_word(buffer,"From:")) parse_arpa_from(buffer, from_whom); else if (buffer[0] == LINEFEED) { if (verbose && count == 0) printf("%s contains the following messages:\n\n", user_mailbox?"Your mailbox" : "Folder"); in_header = 0; /* in body of message! */ show_header(count+1, from_whom, subject); from_whom[0] = 0; subject[0] = 0; count++; } } } return(count); } int real_from(buffer, who) char *buffer, *who; { /***** returns true iff 's' has the seven 'from' fields, initializing the who to the sender *****/ char junk[80]; junk[0] = '\0'; sscanf(buffer, "%*s %s %*s %*s %*s %*s %s", who, junk); return(junk[0] != '\0'); } forwarded(buffer, who) char *buffer, *who; { /** change 'from' and date fields to reflect the ORIGINATOR of the message by iteratively parsing the >From fields... **/ char machine[80], buff[80]; machine[0] = '\0'; sscanf(buffer, "%*s %s %*s %*s %*s %*s %*s %*s %*s %s", who, machine); if (machine[0] == '\0') /* try for srm address */ sscanf(buffer, "%*s %s %*s %*s %*s %*s %*s %*s %s", who, machine); if (machine[0] == '\0') sprintf(buff,"anonymous"); else sprintf(buff,"%s!%s", machine, who); strncpy(who, buff, 80); } remove_first_word(string) char *string; { /** removes first word of string, ie up to first non-white space following a white space! **/ register int loc; for (loc = 0; string[loc] != ' ' && string[loc] != '\0'; loc++) ; while (string[loc] == ' ' || string[loc] == '\t') loc++; move_left(string, loc); } move_left(string, chars) char string[]; int chars; { /** moves string chars characters to the left DESTRUCTIVELY **/ register int i; chars--; /* index starting at zero! */ for (i=chars; string[i] != '\0' && string[i] != '\n'; i++) string[i-chars] = string[i]; string[i-chars] = '\0'; } show_header(count, from, subject) int count; char *from, *subject; { /** output header in clean format, including abbreviation of return address if more than one machine name is contained within it! **/ char buffer[SLEN]; int loc, i=0, exc=0; #ifdef PREFER_UUCP char *p; if (chloc(from,'!') != -1 && chloc(from,'@') > 0) for (p=from;*p != '@'; p++) ; *p = '\0'; #endif loc = strlen(from); while (exc < 2 && loc > 0) if (from[--loc] == '!') exc++; if (exc == 2) { /* lots of machine names! Get last one */ loc++; while (loc < strlen(from) && loc < SLEN) buffer[i++] = from[loc++]; buffer[i] = '\0'; if (number) printf("%3d: %-20s %s\n", count, buffer, subject); else printf("%-20s %s\n", buffer, subject); } else if (number) printf("%3d: %-20s %s\n", count, from, subject); else printf("%-20s %s\n", from, subject); } parse_arpa_from(buffer, newfrom) char *buffer, *newfrom; { /** try to parse the 'From:' line given... It can be in one of two formats: From: Dave Taylor <hpcnou!dat> or From: hpcnou!dat (Dave Taylor) Change 'newfrom' ONLY if sucessfully parsed this entry and the resulting name is non-null! **/ char temp_buffer[SLEN], *temp; register int i, j = 0; temp = (char *) temp_buffer; temp[0] = '\0'; no_ret(buffer); /* blow away '\n' char! */ if (lastch(buffer) == '>') { for (i=strlen("From: "); buffer[i] != '\0' && buffer[i] != '<' && buffer[i] != '('; i++) temp[j++] = buffer[i]; temp[j] = '\0'; } else if (lastch(buffer) == ')') { for (i=strlen(buffer)-2; buffer[i] != '\0' && buffer[i] != '(' && buffer[i] != '<'; i--) temp[j++] = buffer[i]; temp[j] = '\0'; reverse(temp); } if (strlen(temp) > 0) { /* mess with buffer... */ /* remove leading spaces... */ while (whitespace(temp[0])) temp = (char *) (temp + 1); /* increment address! */ /* remove trailing spaces... */ i = strlen(temp) - 1; while (whitespace(temp[i])) temp[i--] = '\0'; /* if anything is left, let's change 'from' value! */ if (strlen(temp) > 0) strcpy(newfrom, temp); } } reverse(string) char *string; { /** reverse string... pretty trivial routine, actually! **/ char buffer[SLEN]; register int i, j = 0; for (i = strlen(string)-1; i >= 0; i--) buffer[j++] = string[i]; buffer[j] = '\0'; strcpy(string, buffer); } int expand(infile) char *infile; { /** Expand the filename since the first character is a meta- character that should expand to the "maildir" variable in the users ".elmrc" file... Note: this is a brute force way of getting the entry out of the .elmrc file, and isn't recommended for the faint of heart! **/ FILE *rcfile; char buffer[SLEN], *expanded_dir, *home, *getenv(), *bufptr; int foundit = 0; bufptr = (char *) buffer; /* same address */ if ((home = getenv("HOME")) == NULL) { printf( "Can't expand environment variable $HOME to find .elmrc file!\n"); exit(1); } sprintf(buffer, "%s/%s", home, elmrcfile); if ((rcfile = fopen(buffer, "r")) == NULL) { printf("Can't open your \".elmrc\" file (%s) for reading!\n", buffer); exit(1); } while (fgets(buffer, SLEN, rcfile) != NULL && ! foundit) { if (strncmp(buffer, "maildir", 7) == 0 || strncmp(buffer, "folders", 7) == 0) { while (*bufptr != '=' && *bufptr) bufptr++; bufptr++; /* skip the equals sign */ while (whitespace(*bufptr) && *bufptr) bufptr++; home = bufptr; /* remember this address */ while (! whitespace(*bufptr) && *bufptr != '\n') bufptr++; *bufptr = '\0'; /* remove trailing space */ foundit++; } } fclose(rcfile); /* be nice... */ if (! foundit) { printf("Couldn't find \"maildir\" in your .elmrc file!\n"); exit(1); } /** Home now points to the string containing your maildir, with no leading or trailing white space... **/ expanded_dir = expand_define(home); sprintf(buffer, "%s%s%s", expanded_dir, (expanded_dir[strlen(expanded_dir)-1] == '/' || infile[0] == '/') ? "" : "/", (char *) infile+1); strcpy(infile, buffer); } char *expand_define(maildir) char *maildir; { /** This routine expands any occurances of "~" or "$var" in the users definition of their maildir directory out of their .elmrc file. Again, another routine not for the weak of heart or staunch of will! **/ static char buffer[SLEN]; /* static buffer AIEE!! */ char name[SLEN], /* dynamic buffer!! (?) */ *nameptr, /* pointer to name?? */ *value; /* char pointer for munging */ if (*maildir == '~') sprintf(buffer, "%s%s", getenv("HOME"), ++maildir); else if (*maildir == '$') { /* shell variable */ /** break it into a single word - the variable name **/ strcpy(name, (char *) maildir + 1); /* hurl the '$' */ nameptr = (char *) name; while (*nameptr != '/' && *nameptr) nameptr++; *nameptr = '\0'; /* null terminate */ /** got word "name" for expansion **/ if ((value = getenv(name)) == NULL) { printf("Couldn't expand shell variable $%s in .elmrc!\n", name); exit(1); } sprintf(buffer, "%s%s", value, maildir + strlen(name) + 1); } else strcpy(buffer, maildir); return( ( char *) buffer); } END-OF-FILE if [ "$filename" != "/dev/null" ] then size=`wc -c < $filename` if [ $size != 10520 ] then echo $filename changed - should be 10520 bytes, not $size bytes fi chmod 666 $filename fi echo done exit 0