sources-request@mirror.UUCP (07/02/86)
Submitted by: Dave Taylor <pyramid!hplabs!hpldat!taylor> Mod.sources: Volume 6, Issue 39 Archive-name: elm/Part14 [ Last time, when MSG was posted, the moderator posted copies of the documentation. With Dave's cooperation, this time we are making available laser-printer hardcopy. People in the Northeast corner of North America can get copies by mailing me their name and postal address; I will send out a copy, and forward their name on to Dave so he can maintain a list of users. People in other parts of the world should send Dave their address; he will add other "regional distributors" as necessary. --r$ ] # Continuation of Shell Archive, created by hpldat!taylor # This is part 14 # 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 if [ ! -d utils ] then echo creating directory utils mkdir utils fi # ---------- file utils/readmsg.c ---------- filename="utils/readmsg.c" if [ -f $filename ] then echo File \"$filename\" already exists\! Skipping... filename=/dev/null # throw it away else echo extracting file utils/readmsg.c... fi cat << 'END-OF-FILE' > $filename /** readmsg.c **/ /** This routine adds the functionality of the "~r" command to the Elm mail system while still allowing the user to use the editor of their choice. The program, without any arguments, tries to read a file in the users home directory called ".readmsg" (actually defined in the sysdefs.h system defines file) and if it finds it reads the current message. If it doesn't find it, it will return a usage error. The program can also be called with an explicit message number, list of message numbers, or a string to match in the message (including the header). NOTE that when you use the string matching option it will match the first message containing that EXACT (case sensitive) string and then exit. Changed 5/86 to SORT the input list of message numbers to ensure that they're in first-to-last order... Added the "weed" option as the default. This is inspired by the mail system used at NASA RIACS. If THEY can do it, so can we!! (C) Copyright 1985, Dave Taylor **/ #include <stdio.h> #include <ctype.h> #include "defs.h" /** three defines for what level of headers to display **/ #define ALL 1 #define WEED 2 #define NONE 3 static char ident[] = { WHAT_STRING }; #define MAX_LIST 25 /* largest single list of arguments */ #define LAST_MESSAGE 9999 /* last message in list ('$' char) */ #define LAST_CHAR '$' /* char to delimit last message.. */ int read_message[MAX_LIST]; /* list of messages to read */ int messages = 0; /* index into list of messages */ int numcmp(); /* strcmp, but for numbers */ char *words(); /* function defined below... */ #define DONE 0 /* for use with the getopt */ #define ERROR -1 /* library call... */ extern char *optional_arg; /* for parsing the ... */ extern int opt_index; /* .. starting arguments */ main(argc, argv) int argc; char *argv[]; { FILE *file; /* generic file descriptor! */ char filename[SLEN], /* filename buffer */ infile[SLEN], /* input filename */ buffer[SLEN], /* file reading buffer */ string[SLEN]; /* string match buffer */ int current_in_queue = 0, /* these are used for... */ current = 0, /* ...going through msgs */ num, /* for argument parsing */ page_breaks = 0, /* use "^L" breaks?? */ total, /* number of msgs current */ include_headers = WEED, /* flag: include msg header? */ last_message = 0, /* flag: read last message? */ not_in_header = 0, /* flag: in msg header? */ string_match = 0; /* flag: using string match? */ /**** start of the actual program ****/ while ((num = get_options(argc, argv, "nhf:p")) > 0) { switch (num) { case 'n' : include_headers = NONE; break; case 'h' : include_headers = ALL; break; case 'f' : strcpy(infile, optional_arg); break; case 'p' : page_breaks++; break; } } if (num == ERROR) { printf("Usage: %s [-n|-h] [-f filename] [-p] <message list>\n", argv[0]); exit(1); } /** whip past the starting arguments so that we're pointing to the right stuff... **/ *argv++; /* past the program name... */ while (opt_index-- > 1) { *argv++; argc--; } /** now let's figure out the parameters to the program... **/ if (argc == 1) { /* no arguments... called from 'Elm'? */ sprintf(filename, "%s/%s", getenv("HOME"), readmsg_file); if ((file = fopen(filename, "r")) != NULL) { fscanf(file, "%d", &(read_message[messages++])); fclose(file); } else { /* no arguments AND no .readmsg file!! */ fprintf(stderr, "Usage: readmsg [-n|-h] [-f filename] [-p] <message list>\n"); exit(1); } } else if (! isdigit(*argv[0]) && *argv[0] != LAST_CHAR) { string_match++; while (*argv) sprintf(string, "%s%s%s", string, string[0] == '\0'? "" : " ", *argv++); } else { /* list of nums */ while (--argc > 0) { num = -1; sscanf(*argv,"%d", &num); if (num < 0) { if (*argv[0] == LAST_CHAR) { last_message++; num = LAST_MESSAGE; } else { fprintf(stderr,"I don't understand what '%s' means...\n", *argv); exit(1); } } else if (num == 0) { /* another way to say "last" */ last_message++; num = LAST_MESSAGE; } *argv++; read_message[messages++] = num; } /** and now sort 'em to ensure they're in a reasonable order... **/ qsort(read_message, messages, sizeof(int), numcmp); } /** Now let's get to the mail file... **/ if (strlen(infile) == 0) sprintf(infile, "%s/%s", mailhome, getenv("LOGNAME")); if ((file = fopen(infile, "r")) == NULL) { printf("But you have no mail!\n"); exit(0); } /** Now it's open, let's display some 'ole messages!! **/ if (string_match || last_message) { /* pass through it once */ if (last_message) { total = count_messages(file); /* instantiate count */ for (num=0; num < messages; num++) if (read_message[num] == LAST_MESSAGE) read_message[num] = total; } else if (string_match) match_string(file, string); /* stick msg# in list */ if (total == 0 && ! string_match) { printf("There aren't any messages to read!\n"); exit(0); } } /** now let's have some fun! **/ while (fgets(buffer, SLEN, file) != NULL) { if (strncmp(buffer, "From ", 5) == 0) { if (current == read_message[current_in_queue]) current_in_queue++; if (current_in_queue >= messages) exit(0); current++; if (current == read_message[current_in_queue] && page_breaks && current_in_queue > 0) putchar(FORMFEED); not_in_header = 0; /* we're in the header! */ } if ((current == read_message[current_in_queue])) if (include_headers==ALL || not_in_header) printf("%s", buffer); else if (strlen(buffer) < 2) { not_in_header++; if (include_headers==WEED) list_saved_headers(); } else if (include_headers==WEED) possibly_save(buffer); /* check to see if we want this */ } exit(0); } int count_messages(file) FILE *file; { /** Returns the number of messages in the file **/ char buffer[SLEN]; int count = 0; while (fgets(buffer, SLEN, file) != NULL) if (strncmp(buffer, "From ", 5) == 0) count++; rewind( file ); return( count ); } match_string(mailfile, string) FILE *mailfile; char *string; { /** Increment "messages" and put the number of the message in the message_count[] buffer until we match the specified string... **/ char buffer[SLEN]; int message_count; while (fgets(buffer, SLEN, mailfile) != NULL) { if (strncmp(buffer, "From ", 5) == 0) message_count++; if (in_string(buffer, string)) { read_message[messages++] = message_count; rewind(mailfile); return; } } fprintf(stderr,"Couldn't find message containing '%s'\n", string); exit(1); } int in_string(buffer, pattern) char *buffer, *pattern; { /** Returns TRUE iff pattern occurs IN IT'S ENTIRETY in buffer. **/ register int i = 0, j = 0; while (buffer[i] != '\0') { while (buffer[i++] == pattern[j++]) if (pattern[j] == '\0') return(TRUE); i = i - j + 1; j = 0; } return(FALSE); } int numcmp(a, b) int *a, *b; { /** compare 'a' to 'b' returning less than, equal, or greater than, accordingly. **/ return(*a - *b); } static char from[SLEN], subject[SLEN], date[SLEN]; possibly_save(buffer) char *buffer; { /** Check to see what "buffer" is...save it if it looks interesting... We'll always try to get SOMETHING by tearing apart the "From " line... **/ if (strncmp(buffer, "Date:", 5) == 0) strcpy(date, buffer); else if (strncmp(buffer, "Subject:", 8) == 0) strcpy(subject,buffer); else if (strncmp(buffer,"From:", 5) == 0) strcpy(from, buffer); else if (strncmp(buffer,"From ", 5) == 0) { sprintf(from, "From: %s\n", words(2,1, buffer)); sprintf(date,"Date: %s", words(3,7, buffer)); } } list_saved_headers() { /** This routine will display the information saved from the message being listed...If it displays anything it'll end with a blank line... **/ register int displayed_line = FALSE; if (strlen(from) > 0) { printf("%s", from); displayed_line++;} if (strlen(subject) > 0) { printf("%s", subject); displayed_line++;} if (strlen(date) > 0) { printf("%s", date); displayed_line++;} if (displayed_line) putchar('\n'); } char *words(word, num_words, buffer) int word, num_words; char *buffer; { /** Return a buffer starting at 'word' and containing 'num_words' words from buffer. Assume white space will delimit each word. **/ static char internal_buffer[SLEN]; char *wordptr, *bufptr, mybuffer[SLEN], *strtok(); int wordnumber = 0, copying_words = 0; internal_buffer[0] = '\0'; /* initialize */ strcpy(mybuffer, buffer); bufptr = (char *) mybuffer; /* and setup */ while ((wordptr = strtok(bufptr, " \t")) != NULL) { if (++wordnumber == word) { strcpy(internal_buffer, wordptr); copying_words++; num_words--; } else if (copying_words) { strcat(internal_buffer, " "); strcat(internal_buffer, wordptr); num_words--; } if (num_words < 1) return((char *) internal_buffer); bufptr = NULL; } return( (char *) internal_buffer); } END-OF-FILE if [ "$filename" != "/dev/null" ] then size=`wc -c < $filename` if [ $size != 9564 ] then echo $filename changed - should be 9564 bytes, not $size bytes fi chmod 666 $filename fi # ---------- file utils/Makefile ---------- filename="utils/Makefile" if [ -f $filename ] then echo File \"$filename\" already exists\! Skipping... filename=/dev/null # throw it away else echo extracting file utils/Makefile... fi cat << 'END-OF-FILE' > $filename # # Makefile for the MSG system utilities # # (C) Copyright 1986, Dave Taylor # # Last modification: March 5th, 1986 SHELL=/bin/sh ############################## # # if on a BSD system; # DEFINE=-DBSD # LIB2 = -lcurses # else if on a UTS system; # DEFINE=-DUTS # LIB2 = -la # else if on a SUN system; # DEFINE=-DBSD -DSUN # LIB2 = -lcurses # else if on a Pyramid system; # DEFINE=-DBSD -DNO_VAR_ARGS # LIB2 = -lcurses # else DEFINE= LIB2 = ############################## CFLAGS= -O -I../hdrs CC= /bin/cc RM= /bin/rm ECHO= /bin/echo OBJS= ../bin/newalias ../bin/from ../bin/newmail ../bin/answer \ ../bin/printmail ../bin/fastmail ../bin/readmsg \ ../bin/checkalias ../bin/arepdaemon ../bin/autoreply ../bin/wnewmail all: ${OBJS} ../bin/newalias: ../hdrs/defs.h newalias.c ../src/validname.o \ ../src/opt_utils.o ${CC} ${CFLAGS} ${DEFINE} newalias.c ../src/validname.o \ ../src/opt_utils.o -o ../bin/newalias ../bin/from: from.c ../src/opt_utils.o ../src/string2.o ${CC} ${CFLAGS} ${DEFINE} from.c ../src/opt_utils.o \ ../src/string2.o -o ../bin/from ../bin/newmail: ../src/opt_utils.c newmail.c ../src/string2.o ${CC} ${CFLAGS} ${DEFINE} newmail.c \ ../src/string2.o -o ../bin/newmail ../bin/wnewmail: ../src/opt_utils.c wnewmail.c ../src/string2.o ${CC} ${CFLAGS} ${DEFINE} ../src/opt_utils.o \ ../src/string2.o wnewmail.c -o ../bin/wnewmail ../bin/answer: answer.c ../src/opt_utils.o ${CC} ${CFLAGS} ${DEFINE} answer.c ../src/opt_utils.o -o ../bin/answer ../bin/printmail: printmail.c ../src/opt_utils.o ${CC} ${CFLAGS} ${DEFINE} printmail.c ../src/opt_utils.o \ -o ../bin/printmail ../bin/fastmail: fastmail.c ${CC} ${CFLAGS} ${DEFINE} fastmail.c ../src/opt_utils.o \ -o ../bin/fastmail ../bin/readmsg: readmsg.c ../src/getopt.o ../src/opt_utils.o ${CC} ${CFLAGS} ${DEFINE} readmsg.c ../src/getopt.o \ ../src/opt_utils.o -o ../bin/readmsg ../bin/arepdaemon: arepdaemon.c ${CC} ${CFLAGS} ${DEFINE} arepdaemon.c -o ../bin/arepdaemon ../bin/autoreply: autoreply.c ../src/opt_utils.o ${CC} ${CFLAGS} ${DEFINE} autoreply.c ../src/opt_utils.o \ -o ../bin/autoreply ../bin/checkalias: @echo '#!/bin/sh' > ../bin/checkalias @echo 'if [ -z "$$*" ]; then' >> ../bin/checkalias @echo ' echo Usage: checkalias alias \[or aliases\]' >> \ ../bin/checkalias @echo ' exit 1' >> ../bin/checkalias @echo 'fi' >> ../bin/checkalias @echo ' ' >> ../bin/checkalias @echo 'exec elm -c $*' >> ../bin/checkalias @chmod +x ../bin/checkalias ../src/validname.o: ../src/validname.c @(cd ../src; ${CC} -c ${CFLAGS} ${DEFINE} validname.c; cd ../utils) ../src/opt_utils.o: ../src/opt_utils.c @(cd ../src; ${CC} -c ${CFLAGS} ${DEFINE} opt_utils.c; cd ../utils) ../src/getopt.o: ../src/getopt.c @(cd ../src; ${CC} -c ${CFLAGS} ${DEFINE} getopt.c; cd ../utils) ../src/string2.o: ../src/string2.c @(cd ../src; ${CC} -c ${CFLAGS} ${DEFINE} string2.c; cd ../utils) clean: ${RM} *.o ${OBJS} lint: lint -p -I../hdrs *.c > LINT.OUT END-OF-FILE if [ "$filename" != "/dev/null" ] then size=`wc -c < $filename` if [ $size != 3031 ] then echo $filename changed - should be 3031 bytes, not $size bytes fi chmod 666 $filename fi # ---------- file utils/breakup.c ---------- filename="utils/breakup.c" if [ -f $filename ] then echo File \"$filename\" already exists\! Skipping... filename=/dev/null # throw it away else echo extracting file utils/breakup.c... fi cat << 'END-OF-FILE' > $filename /** breakup.c **/ /** This program reads in a rather LARGE number of mail files (folders) from a directory OTHER THAN THE CURRENT ONE and breaks each into a file per message (each message being put into the directory MESSAGES) and adds entries for each message in a mailbox with the same name as the source mailbox. The format of each new mailbox is; FILE: <filename> SUBJECT: <subject> FROM: <from> TO: <to> SENT: <sent date> RECEIVED: <received date> (enough information so that indexes can be generated without actually having to reference the files in question...) filename is "YY-MM-DD.number" where YY-MM-DD is the date the message was received (in this order for sorting) from is the persons name or machine!user address ONLY dates are MM-DD-YY, HH:MM ONLY. (C) Copyright 1986, Dave Taylor **/ #include <stdio.h> #include <errno.h> #include "defs.h" static int ident[] = { WHAT_STRING }; extern int errno; #define first_word(s,w) strncmp(s, w, strlen(w)) #define MESSAGES "MESSAGES" #define seqfile "MESSAGES/.msg_sequence" #define SLEN 80 char *monthnames[] = { "month-zero", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", "month-thirteen" }; FILE *boxfd; int messagenum = 1; char *strtok(); main(argc, argv) int argc; char *argv[]; { FILE *fd, *outfd; char filename[SLEN], *basename(), *box_name; int start; if (argc == 1) exit(printf("Usage: breakup <list of files>\n")); if (access(MESSAGES, 00) == -1) exit(printf("Need 'MESSAGES' directory in this directory!\n")); if ((fd = fopen(seqfile, "r")) == NULL) printf("Warning: No sequence file. Starting with sequence #1\n"); else { fscanf(fd,"%d", &messagenum); printf("Starting sequencing with #%d\n", messagenum); fclose(fd); } *argv++; start = messagenum; while (--argc) { if ((fd = fopen(*argv, "r")) == NULL) leave(printf("\nCouldn't open file '%s' for reading!\n", *argv)); box_name = basename(*argv); if ((boxfd = fopen(box_name, "w")) == NULL) leave(printf("\nCouldn't open box '%s' for writing!\n", box_name)); printf("%s...", *argv); fflush(stdout); break_up(fd, &messagenum); *argv++; fclose(boxfd); fclose(fd); } printf("\nSuccessfully broke into %d messages!\n", messagenum - start); leave(); } leave() { /** leave, updating messagenum **/ FILE *fd; if ((fd = fopen(seqfile, "w")) == NULL) printf("Warning: couldn't update sequence file '%s'\n", seqfile); else { fprintf(fd, "%d", messagenum); fclose(fd); } exit(0); } break_up(msgfd, messagenum) FILE *msgfd; int *messagenum; { /** break up the mailbox into it's component messages, writing each one to a file as we go along **/ FILE *outfd; char filename[SLEN], buffer[SLEN], save_buffer[SLEN]; char *get_fdate(), *get_sdate(), *get_rdate(); char *extract_from(), *extract_date(); int in_header = 0, file_open = 0, from_obtained=0; int date_obtained = 0; while (fgets(buffer, SLEN, msgfd) != NULL) { if (first_word(buffer, "From ") == 0) { sprintf(filename, "%s/%s.%d", MESSAGES, get_fdate(buffer, '/'), (*messagenum)++); if (file_open) fclose(outfd); check_for_dirs(filename); if ((outfd = fopen(filename, "w")) == NULL) leave(printf("Could not open file '%s' as message file!\n", filename)); fprintf(outfd, "%s", buffer); fprintf(boxfd, "\nFile: %s\nReceived: %s\n", filename, get_rdate(buffer)); file_open++; in_header++; date_obtained = 0; from_obtained = 0; strcpy(save_buffer, buffer); } else if (file_open) { if (in_header) { if (first_word(buffer, "Subject:") == 0) fprintf(boxfd, "%s", buffer); else if (first_word(buffer, "Date:") == 0) { date_obtained++; fprintf(boxfd, "Sent: %s\n", get_sdate()); } else if (first_word(buffer, "From:") == 0) { from_obtained++; fprintf(boxfd, "%s", buffer); } else if (first_word(buffer,">From") == 0) strcpy(save_buffer, buffer); else if (strlen(buffer) < 2) { in_header = 0; if (! from_obtained) fprintf(boxfd, "%s\n", extract_from(save_buffer)); if (! date_obtained) fprintf(boxfd, "Sent: %s\n", extract_date(save_buffer)); } } fprintf(outfd, "%s", buffer); } } if (file_open) { if (! from_obtained) fprintf(boxfd, "From: %s", extract_from(save_buffer)); if (! date_obtained) fprintf(boxfd, "Date: %s", extract_date(save_buffer)); fclose(msgfd); } } char *get_fdate(buffer, separator) char *buffer, separator; { /** given a "From xyz" buffer, return the date in the format YY?MM?DD for filenaming, where ? = the separator char. **/ static char mybuf[SLEN]; char monthname[SLEN]; int month=0, day=0, year=0; sscanf(buffer, "%*s %*s %*s %s %d %*s %d", monthname, &day, &year); year = year % 1900; switch (tolower(monthname[0])) { case 'j' : if (tolower(monthname[1]) == 'a') month = 1; else if (tolower(monthname[2]) == 'n') month = 6; else month = 7; break; case 'f' : month = 2; break; case 'm' : if (tolower(monthname[2]) == 'r') month = 3; else month = 5; break; case 'a' : if (tolower(monthname[1]) == 'p') month = 4; else month = 8; break; case 's' : month = 9; break; case 'o' : month = 10; break; case 'n' : month = 11; break; case 'd' : month = 12; break; } sprintf(mybuf, "%d%c%s%c%d", year+1900, separator, monthnames[month], separator, day); return( (char *) mybuf); } char *get_rdate(buffer) char *buffer; { /** return buffer "From xyz <date>" in the format: MM-DD-YY, HH:MM **/ static char mybuf[SLEN]; char monthname[20]; int month=0, day=0, year=0, hour, minute; sscanf(buffer, "%*s %*s %*s %s %d %d:%d:%*d %d", monthname, &day, &hour, &minute, &year); year = year % 1900; switch (tolower(monthname[0])) { case 'j' : if (tolower(monthname[1]) == 'a') month = 1; else if (tolower(monthname[2]) == 'n') month = 6; else month = 7; break; case 'f' : month = 2; break; case 'm' : if (tolower(monthname[2]) == 'r') month = 3; else month = 5; break; case 'a' : if (tolower(monthname[1]) == 'p') month = 4; else month = 8; break; case 's' : month = 9; break; case 'o' : month = 10; break; case 'n' : month = 11; break; case 'd' : month = 12; break; } sprintf(mybuf, "%d-%d-%d, %d:%d", month, day, year, hour, minute); return( (char *) mybuf); } char *get_sdate() { return( NULL ); } char *extract_from(buffer) char *buffer; { /** extract machine!userid from ">From buffer.. and return From: x!z **/ /** if userid = To: <someone>, then return that field instead **/ static char mybuf[SLEN]; char name[SLEN], machine[SLEN]; sscanf(buffer,"%*s %s %*s %*s %*s %*s %*s %*s %*s %s", name, machine); if (strncmp(name, "To:", 3) == 0) strcpy(mybuf, name); else if (strlen(machine) > 0) sprintf(mybuf, "From: %s!%s", machine, name); else sprintf(mybuf, "From: ", name); return( (char *) mybuf); } char *extract_date(buffer) char *buffer; { /** extract the date, mm/dd/yy, hh:mm from the '>From' buffer **/ static char mybuf[SLEN]; char month[10], time[10]; int day, year; sscanf(buffer, "%*s %*s %*s %s %d %s %d", month, &day, time, &year); year = year % 1900; sprintf(mybuf,"%s %d %d, %s", month, day, year, time); return( (char *) mybuf); } check_for_dirs(fname) char *fname; { /** Given a filename of the form x/y/z check for the existence of the directories 'x' and 'y', and create them if they're not currently there! **/ char buffer[SLEN], *dirname, dirbuf[SLEN], *bufptr; int loc, i; strcpy(buffer, fname); for (loc = strlen(fname)-1; buffer[loc] != '/'; loc--) ; buffer[loc] = '\0'; /* broken into directories only! */ bufptr = (char *) buffer; dirbuf[0]= '\0'; while ((dirname = strtok(bufptr,"/")) != NULL) { if (strlen(dirbuf) > 0) strcat(dirbuf, "/"); strcat(dirbuf, dirname); if (access(dirbuf, 00) == -1) mkdir(dirbuf, 0700); bufptr = NULL; } } char *basename(filename) char *filename; { /** returns a string that is the BASENAME of the filename! **/ static char mybuffer[SLEN]; register int loc, firstch = 0; for (loc = 0; filename[loc] != '\0'; loc++) if (filename[loc] == '/') firstch = loc+1; loc = 0; while (filename[firstch] != '\0') mybuffer[loc++] = filename[firstch++]; mybuffer[loc] = '\0'; return ( (char *) mybuffer); } END-OF-FILE if [ "$filename" != "/dev/null" ] then size=`wc -c < $filename` if [ $size != 8868 ] then echo $filename changed - should be 8868 bytes, not $size bytes fi chmod 666 $filename fi # ---------- file utils/mailrc.awk ---------- filename="utils/mailrc.awk" if [ -f $filename ] then echo File \"$filename\" already exists\! Skipping... filename=/dev/null # throw it away else echo extracting file utils/mailrc.awk... fi cat << 'END-OF-FILE' > $filename BEGIN { print "# MSG alias_text file, from a .mailrc file..." print "" } next_line == 1 { next_line = 0; group = "" for (i = 1; i <= NF; i++) { if (i == NF && $i == "\\") sep = "" else sep = ", " if ($i == "\\") { group = sprintf("%s,", group) next_line = 1; } else if (length(group) > 0) group = sprintf("%s%s%s", group, sep, $i); else group = $i; } print "\t" group } $1 ~ /[Aa]lias|[Gg]roup/ { if ( NF == 3) print $2 " : user alias : " $3; else { group = "" for (i = 3; i <= NF; i++) { if (i == NF && $i == "\\") sep = "" else sep = ", " if ($i == "\\") { group = sprintf("%s,", group) next_line = 1; } else if (length(group) > 0) group = sprintf("%s%s%s", group, sep, $i); else group = $i; } print $2 " : group alias : " group; } } END-OF-FILE if [ "$filename" != "/dev/null" ] then size=`wc -c < $filename` if [ $size != 930 ] then echo $filename changed - should be 930 bytes, not $size bytes fi chmod 666 $filename fi # ---------- file utils/wnewmail.c ---------- filename="utils/wnewmail.c" if [ -f $filename ] then echo File \"$filename\" already exists\! Skipping... filename=/dev/null # throw it away else echo extracting file utils/wnewmail.c... fi cat << 'END-OF-FILE' > $filename /** wnewmail.c **/ /** Same as newmail.c but for a windowing system... (C) Copyright 1986, Dave Taylor **/ #ifdef AUTO_BACKGROUND #include <signal.h> /* background jobs ignore some signals... */ #endif #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include "defs.h" static char ident[] = { WHAT_STRING }; #define LINEFEED (char) 10 #define BEGINNING 0 /* seek fseek(3S) */ #define SLEEP_TIME 10 #define NO_SUBJECT "(No Subject Specified)" FILE *mailfile; long bytes(); char *getusername(); main(argc, argv) int argc; char *argv[]; { char filename[LONG_SLEN]; long size, newsize; if (argc > 2) fprintf(stderr, "Usage: %s [filename] &\n", argv[0]); else if (argc == 2) { strcpy(filename, argv[1]); if (access(filename, ACCESS_EXISTS) == -1) { fprintf(stderr,"%s: Can't open file %s to keep track of!\n", argv[0], filename); exit(1); } } else sprintf(filename,"%s%s",mailhome, getusername()); #ifdef AUTO_BACKGROUND if (fork()) /* automatically puts this task in background! */ exit(0); signal(SIGINT, SIG_IGN); signal(SIGQUIT, SIG_IGN); signal(SIGHUP, SIG_DFL); /* so we exit when logged out */ #endif size = bytes(filename); mailfile = (FILE *) NULL; printf("Incoming Mail;\n"); while (1) { #ifndef AUTO_BACKGROUND /* won't work if we're nested this deep! */ if (getppid() == 1) /* we've lost our shell! */ exit(); #endif /** Note the lack of error checking on the fopen() (Philip Peake did!) - this is okay since if it fails we don't have any mail and we can sleep(60) and try again later... **/ if (mailfile == (FILE *) NULL) mailfile = fopen(filename,"r"); if ((newsize = bytes(filename)) > size) { /* new mail */ fseek(mailfile, size, BEGINNING); /* skip all current mail */ size = newsize; printf("%c", 007); /* beep for new mail! */ read_headers(); } else if (newsize != size) { size = newsize; /* mail's been removed... */ (void) fclose(mailfile); /* close it and ... */ mailfile = (FILE *) NULL; /* let's reopen the file */ } sleep(SLEEP_TIME); } } int read_headers() { /** read the headers, output as found **/ 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) { in_header = 0; /* in body of message! */ show_header(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(from, subject) 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 if (chloc(from,'!') != -1 && in_string(from, BOGUS_INTERNET)) from[strlen(from) - strlen(BOGUS_INTERNET)] = '\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'; strcpy(from, buffer); } if (strlen(subject) < 2) strcpy(subject, NO_SUBJECT); if (strlen(from) > 0) /* last final check... */ printf("Mail from %s -- %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); } long bytes(name) char *name; { /** return the number of bytes in the specified file. This is to check to see if new mail has arrived.... **/ int ok = 1; extern int errno; /* system error number! */ struct stat buffer; if (stat(name, &buffer) != 0) if (errno != 2) exit(fprintf(stderr,"Error %d attempting fstat on %s", errno, name)); else ok = 0; return(ok ? (long) buffer.st_size : 0L); } char *getusername() { /** Getting the username on some systems is a real pain, so... This routine is guaranteed to return a usable username **/ char *return_value, *cuserid(), *getlogin(); if ((return_value = cuserid(NULL)) == NULL) if ((return_value = getlogin()) == NULL) exit(printf("Newmail: I can't get username!\n")); return( (char *) return_value); } END-OF-FILE if [ "$filename" != "/dev/null" ] then size=`wc -c < $filename` if [ $size != 7804 ] then echo $filename changed - should be 7804 bytes, not $size bytes fi chmod 666 $filename fi # ---------- file utils/page.c ---------- filename="utils/page.c" if [ -f $filename ] then echo File \"$filename\" already exists\! Skipping... filename=/dev/null # throw it away else echo extracting file utils/page.c... fi cat << 'END-OF-FILE' > $filename /** page.c **/ /** This is an alternative method of wandering through a file and is essentially a "read-only" editor. This is part of the Elm mail system, although it can be used by itself... The functions available are; h help -,b back a page u back 1/2 a page ^M,+,f forward a page d forward 1/2 a page r reread file (start over) / skip forward to pattern ? skip backwards to pattern (with no arg, same as "h") q quit The starting flags are: -s Use scrolling rather than paging Page is also smart enough to know that if it's reading stdin that it needs to open a temp file to stream the input into to allow paging AND also knows that it then needs to read /dev/tty rather than stdin (think about it). (C) Copyright 1986 Dave Taylor **/ #include <stdio.h> #define SLEN 100 #define TOP_OF_PAGE 0 #define MIDDLE_OF_PAGE 1 #define MAX_PAGES 200 /* indicates how far back we'll remember */ #define MIDDLE 0 #define END 1 #define TEMPFILENAME "/tmp/page." FILE *keyboard; /* always read keyboard with this... */ FILE *infile; /* the file we're reading... */ FILE *tempfile; /* temp file for streaming input */ int scrolling = 0, /* Flag: should we scroll instead of page? */ streaming = 0; /* Flag: are we reading stdin for file? */ long offsets[2][MAX_PAGES]; /* offsets into file as we go along */ long current_offset; /* offset into file currently */ int current_page, /* what page we're on... */ loc_on_page, /* where are we (HALF ON, or FULLY ON) */ line_on_page, /* what line on the page (Screen) */ lines_per_page = 24; /* lines per page on terminal */ main(argc, argv) int argc; char *argv[]; { char filename[SLEN], buffer[SLEN]; if (argc > 1) { strcpy(filename, argv[1]); keyboard = stdin; } else if (isatty(fileno(stdin))) exit(printf("Nothing to page through!\n")); else { sprintf(filename, "%s.%d", TEMPFILENAME, getpid()); streaming++; keyboard = fopen("/dev/tty", "r"); } /** now let's open the file accordingly... **/ if (streaming) { infile = stdin; if ((tempfile = fopen(filename, "w")) == NULL) exit(printf("Can't open tempfile %s for paging!\n", filename)); } else { if ((infile = fopen(filename, "r")) == NULL) exit(printf("Can't open file %s for reading!\n", filename)); } /** initialize our variables... **/ current_page = 0; current_offset = 0L; line_on_page = 0; loc_on_page = TOP_OF_PAGE; if (getenv("LINES") != NULL) lines_per_page = atoi(getenv("LINES")) - 2; offsets[TOP_OF_PAGE][current_page] = current_offset; /* init */ while (gets(buffer, SLEN, infile) != NULL) { line_on_page++; if (line_on_page == (int) (lines_per_page / 2)) offsets[MIDDLE_OF_PAGE][current_page] = current_offset; else if (line_on_page == lines_per_page) { offsets[TOP_OF_PAGE][++current_page] = current_offset; next_page(MIDDLE); /* could do a "seek" remember! */ } } next_page(END); exit(0); } next_page(where) int where; { /** End of page processing..where is either "MIDDLE", indicating that we're in the middle of a file, or "END", indicating that we've already hit the EOF mark **/ char buffer[3]; top: printf("\n%s Command? ", where == MIDDLE? "More..." : "End of Message -"); fgets(buffer,2, keyboard); line_on_page = 0; switch (buffer[0]) { case '+' : case 'f' : case '\n' : return; /* scroll to next page */ case 'd' : line_on_page = (int) (lines_per_page / 2); return; /* scroll 1/2 next page */ case 'u' : getto(offsets[MIDDLE_OF_PAGE][current_page-1]); return; case 'b' : case '-' : getto(offsets[TOP_OF_PAGE][current_page-1]); return; case 'q' : exit(0); /* we're outta here!! */ case 'h' : help(); goto top; /* this again? */ default : printf("Unknown command. Please use \"h\" for help\n"); goto top; } } getto(offset) long offset; { /** This routine seeks to the specified point in the file and sets current page accordingly... **/ if (fseek(infile, offset, 0) != -1) current_offset = offset; /* whee! */ } help() { printf("\nThe following options are available;\n\n"); printf(" h help\n\n"); printf(" -,b back a page\n"); printf(" u back 1/2 a page\n\n"); printf(" <return>,+,f forward a page\n"); printf(" d forward 1/2 a page\n\n"); printf(" r reread file (start over)\n\n"); printf(" / skip forward to pattern\n"); printf(" ? skip backwards to pattern (with no arg, same as \"h\")\n\n"); printf(" q quit\n\n"); } END-OF-FILE if [ "$filename" != "/dev/null" ] then size=`wc -c < $filename` if [ $size != 4759 ] then echo $filename changed - should be 4759 bytes, not $size bytes fi chmod 666 $filename fi echo done exit 0