sources-request@mirror.TMC.COM (03/09/87)
Submitted by: Dave Taylor <hplabs!taylor> Mod.sources: Volume 9, Issue 5 Archive-name: elm2/Part05 #! /bin/sh # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # If this archive is complete, you will see the message: # "End of archive 5 (of 19)." # Contents: filter/actions.c filter/rules.c hdrs/elm.h hdrs/headers.h # src/calendar.c src/hdrconfg.c src/help.c src/pattern.c src/utils.c PATH=/bin:/usr/bin:/usr/ucb ; export PATH echo shar: Extracting \"filter/actions.c\" \(5857 characters\) if test -f filter/actions.c ; then echo shar: Will not over-write existing file \"filter/actions.c\" else sed "s/^X//" >filter/actions.c <<'END_OF_filter/actions.c' X/** actions.c **/ X X/** RESULT oriented routines *chuckle*. These routines implement the X actions that result from either a specified rule being true or from X the default action being taken. X X (C) Copyright 1986, Dave Taylor X**/ X X#include <stdio.h> X#include <pwd.h> X#include <ctype.h> X#include <fcntl.h> X X#include "defs.h" X#include "filter.h" X Xmail_message(address) Xchar *address; X{ X /** Called with an address to send mail to. For various reasons X that are too disgusting to go into herein, we're going to actually X open the users mailbox and by hand add this message. Yech. X NOTE, of course, that if we're going to MAIL the message to someone X else, that we'll try to do nice things with it on the fly... X **/ X X FILE *pipefd, *tempfd, *mailfd; X int attempts = 0, ret, in_header = TRUE, line_count = 0; X char tempfile[SLEN], mailbox[SLEN], lockfile[SLEN], X buffer[VERY_LONG_STRING]; X X if (verbose && ! log_actions_only) X printf("%sfilter (%s): Mailing message to %s\n", X BEEP, username, address); X X if (! show_only) { X sprintf(tempfile, "%s.%d", filter_temp, getpid()); X X if ((tempfd = fopen(tempfile, "r")) < 0) { X fprintf(stderr, "%sfilter (%s): Can't open temp file %s!!\n", X BEEP, username, tempfile); X exit(1); X } X X if (strcmp(address, username) != 0) { /* mailing to someone else */ X X if (already_been_forwarded) { /* potential looping! */ X if (contains(from, username)) { X fprintf(stderr, X "%sfilter (%s): Filter loop detected! Message left in file %s.%d\n", X BEEP, username, filter_temp, getpid()); X exit(0); X } X } X X sprintf(buffer, "%s %s %s", sendmail, smflags, address); X X if ((pipefd = popen(buffer, "w")) == NULL) { X fprintf(stderr, "%sfilter (%s): popen %s failed!\n", X BEEP, buffer); X sprintf(buffer, "((%s %s %s ; %s %s) & ) < %s &", X sendmail , smflags, address, remove, tempfile, tempfile); X system(buffer); X return; X } X X fprintf(pipefd, "Subject: \"%s\"\n", subject); X fprintf(pipefd, "From: The Filter of %s@%s <%s>\n", X username, hostname, username); X fprintf(pipefd, "To: %s\n", address); X fprintf(pipefd, "X-Filtered-By: filter, version %s\n\n", VERSION); X X fprintf(pipefd, "-- Begin filtered message --\n\n"); X X while (fgets(buffer, LONG_SLEN, tempfd) != NULL) X if (already_been_forwarded && in_header) X in_header = (strlen(buffer) == 1? 0 : in_header); X else X fprintf(pipefd," %s", buffer); X X fprintf(pipefd, "\n-- End of filtered message --\n"); X fclose(pipefd); X fclose(tempfd); X X return; /* YEAH! Wot a slick program, eh? */ X X } X X /** else it is to the current user... **/ X X sprintf(mailbox, "%s%s", mailhome, username); X sprintf(lockfile, "%s%s.lock", mailhome, username); X X while ((ret=creat(lockfile, 0777)) < 0 && attempts++ < 10) X sleep(2); /* wait two seconds, okay?? */ X X if (ret < 0) { X fprintf(stderr, "%sfilter (%s): Couldn't create lockfile %s\n", X BEEP, username, lockfile); X strcpy(mailbox,"[due to lock not being allowed]"); X /* doing that copy will make sure the next 'open' fails... */ X } X X if (mailbox[0] == '[' || (mailfd=fopen(mailbox,"a")) == NULL) { X X fprintf(stderr, "%sfilter (%s): Can't open mailbox %s!\n", X BEEP, username, mailbox); X X sprintf(mailbox, "%s/%s", home, EMERGENCY_MAILBOX); X if ((mailfd=fopen(mailbox, "a")) == NULL) { X fprintf(stderr,"%sfilter (%s): Can't open %s either!!\n", X BEEP, username, mailbox); X X sprintf(mailbox,"%s/%s", home, EMERG_MBOX); X if ((mailfd = fopen(mailbox, "a")) == NULL) { X fprintf(stderr,"%sfilter (%s): Can't open %s either!!!!\n", X BEEP, username, mailbox); X fprintf(stderr, X "%sfilter (%s): I can't open ANY mailboxes! Augh!!\n", X BEEP, username); X fclose(tempfd); X unlink(lockfile); X leave("Cannot open any mailbox"); /* DIE DIE DIE DIE!! */ X } X else X fprintf(stderr,"%sfilter (%s): Using %s as emergency mailbox\n", X BEEP, username, mailbox); X } X else X fprintf(stderr,"%sfilter (%s): Using %s as emergency mailbox\n", X BEEP, username, mailbox); X } X X while (fgets(buffer, sizeof(buffer), tempfd) != NULL) { X line_count++; X if (the_same(buffer, "From ") && line_count > 1) X fprintf(mailfd, ">%s", buffer); X else X fputs(buffer, mailfd); X } X X fclose(mailfd); X unlink(lockfile); /* blamo! */ X fclose(tempfd); X } X} X Xsave_message(foldername) Xchar *foldername; X{ X /** Save the message in a folder. Use full file buffering to X make this work without contention problems **/ X X FILE *fd, *tempfd; X char filename[SLEN], buffer[LONG_SLEN]; X X if (verbose) X printf("%sfilter (%s): Message saved in folder %s\n", X BEEP, username, foldername); X X if (!show_only) { X sprintf(filename, "%s.%d", filter_temp, getpid()); X X if ((fd = fopen(foldername, "a")) == NULL) { X fprintf(stderr, X "%sfilter (%s): can't save message to requested folder %s!\n", X BEEP, username, foldername); X return(1); X } X X if ((tempfd = fopen(filename, "r")) == NULL) { X fprintf(stderr, X "%sfilter (%s): can't open temp file for reading!\n", X BEEP, username); X return(1); X } X X while (fgets(buffer, sizeof(buffer), tempfd) != NULL) X fputs(buffer, fd); X X fclose(fd); X fclose(tempfd); X } X X return(0); X} X Xexecute(command) Xchar *command; X{ X /** execute the indicated command, feeding as standard input the X message we have. X **/ X X char buffer[LONG_SLEN]; X X if (verbose) X printf("%sfilter (%s): Executing %s\n", X BEEP, username, command); X X if (! show_only) { X sprintf(buffer, "%s %s.%d | %s", cat, filter_temp, getpid(), command); X system(buffer); X } X} END_OF_filter/actions.c if test 5857 -ne `wc -c <filter/actions.c`; then echo shar: \"filter/actions.c\" unpacked with wrong size!? fi # end of overwriting check fi echo shar: Extracting \"filter/rules.c\" \(6383 characters\) if test -f filter/rules.c ; then echo shar: Will not over-write existing file \"filter/rules.c\" else sed "s/^X//" >filter/rules.c <<'END_OF_filter/rules.c' X/** rules.c **/ X X/** This file contains all the rule routines, including those that apply the X specified rules and the routine to print the rules out. X X (C) Copyright 1986, Dave Taylor X**/ X X#include <stdio.h> X#include <pwd.h> X#include <ctype.h> X#ifdef BSD X# include <sys/time.h> X#else X# include <time.h> X#endif X#include <fcntl.h> X X#include "defs.h" X#include "filter.h" X Xint Xaction_from_ruleset() X{ X /** Given the set of rules we've read in and the current to, from, X and subject, try to match one. Return the ACTION of the match X or LEAVE if none found that apply. X **/ X X register int index = 0, not, relation, try_next_rule, x; X struct condition_rec *cond; X X while (index < total_rules) { X cond = rules[index].condition; X try_next_rule = 0; X X while (cond != NULL && ! try_next_rule) { X X not = (cond->relation < 0); X relation = abs(cond->relation); X X switch (cond->matchwhat) { X X case TO : x = contains(to, cond->argument1); break; X case FROM : x = contains(from, cond->argument1); break; X case SUBJECT: x = contains(subject, cond->argument1); break; X case LINES : x = compare(lines, relation, cond->argument1);break; X X case CONTAINS: fprintf(stderr, X "%sfilter (%s): Error: rules based on 'contains' are not implemented!\n", X BEEP, username); X exit(0); X } X X if ((not && x) || ((! not) && (! x))) /* this test failed (LISP?) */ X try_next_rule++; X else X cond = cond->next; /* next condition, if any? */ X } X X if (! try_next_rule) { X rule_choosen = index; X return(rules[rule_choosen].action); X } X index++; X } X X rule_choosen = -1; X return(LEAVE); X} X X#define get_the_time() if (!gotten_time) { \ X thetime = time( (long *) 0); \ X timerec = localtime(&thetime); \ X gotten_time++; \ X } X Xexpand_macros(word, buffer, line) Xchar *word, *buffer; Xint line; X{ X /** expand the allowable macros in the word; X %d = day of the month X %D = day of the week X %h = hour (0-23) X %m = month of the year X %r = return address of sender X %s = subject of message X %S = "Re: subject of message" (only add Re: if not there) X %t = hour:minute X %y = year X or simply copies word into buffer. X **/ X X struct tm *localtime(), *timerec; X long time(), thetime; X register int i, j=0, gotten_time = 0, reading_a_percent_sign = 0; X X for (i = 0; i < strlen(word); i++) { X if (reading_a_percent_sign) { X reading_a_percent_sign = 0; X switch (word[i]) { X X case 'r' : buffer[j] = '\0'; X strcat(buffer, from); X j = strlen(buffer); X break; X X case 's' : buffer[j] = '\0'; X strcat(buffer, subject); X j = strlen(buffer); X break; X X case 'S' : buffer[j] = '\0'; X if (! the_same(subject, "Re:")) X strcat(buffer, subject); X strcat(buffer, subject); X j = strlen(buffer); X break; X X case 'd' : get_the_time(); buffer[j] = '\0'; X strcat(buffer, itoa(timerec->tm_mday,FALSE)); X j = strlen(buffer); X break; X X case 'D' : get_the_time(); buffer[j] = '\0'; X strcat(buffer, itoa(timerec->tm_wday,FALSE)); X j = strlen(buffer); X break; X X case 'm' : get_the_time(); buffer[j] = '\0'; X strcat(buffer, itoa(timerec->tm_mon,FALSE)); X j = strlen(buffer); X break; X X case 'y' : get_the_time(); buffer[j] = '\0'; X strcat(buffer, itoa(timerec->tm_year,FALSE)); X j = strlen(buffer); X break; X X case 'h' : get_the_time(); buffer[j] = '\0'; X strcat(buffer, itoa(timerec->tm_hour,FALSE)); X j = strlen(buffer); X break; X X case 't' : get_the_time(); buffer[j] = '\0'; X strcat(buffer, itoa(timerec->tm_hour,FALSE)); X strcat(buffer, ":"); X strcat(buffer, itoa(timerec->tm_min,TRUE)); X j = strlen(buffer); X break; X X default : fprintf(stderr, X "%sfilter (%s): Error on line %d translating %%%c macro in word \"%s\"!\n", X BEEP, username, line, word[i], word); X exit(1); X } X } X else if (word[i] == '%') X reading_a_percent_sign++; X else X buffer[j++] = word[i]; X } X buffer[j] = '\0'; X} X Xprint_rules() X{ X /** print the rules out. A double check, of course! **/ X X register int i = -1; X char *whatname(), *actionname(); X struct condition_rec *cond; X X while (++i < total_rules) { X printf("\nRule %d: if (", i+1); X X cond = rules[i].condition; X X while (cond != NULL) { X if (cond->relation < 0) X printf("not %s %s %s%s%s", X whatname(cond->matchwhat), X relationname(- (cond->relation)), X quoteit(cond->matchwhat), X cond->argument1, X quoteit(cond->matchwhat)); X else X printf("%s %s %s%s%s", X whatname(cond->matchwhat), X relationname(cond->relation), X quoteit(cond->matchwhat), X cond->argument1, X quoteit(cond->matchwhat)); X X cond = cond->next; X X if (cond != NULL) printf(" and "); X } X X printf(") then\n\t %s %s\n", X actionname(rules[i].action), X rules[i].argument2); X } X printf("\n"); X} X Xchar *whatname(n) Xint n; X{ X static char buffer[10]; X X switch(n) { X case FROM : return("from"); X case TO : return("to"); X case SUBJECT: return("subject"); X case LINES : return ("lines"); X case CONTAINS: return("contains"); X default : sprintf(buffer, "?%d?", n); return((char *)buffer); X } X} X Xchar *actionname(n) Xint n; X{ X switch(n) { X case DELETE : return("Delete"); X case SAVE : return("Save"); X case SAVECC : return("Copy and Save"); X case FORWARD : return("Forward"); X case LEAVE : return("Leave"); X case EXEC : return("Execute"); X default : return("?action?"); X } X} X Xint Xcompare(line, relop, arg) Xint line, relop; Xchar *arg; X{ X /** Given the actual number of lines in the message, the relop X relation, and the number of lines in the rule, as a string (!), X return TRUE or FALSE according to which is correct. X **/ X X int rule_lines; X X rule_lines = atoi(arg); X X switch (relop) { X case LE: return(line <= rule_lines); X case LT: return(line < rule_lines); X case GE: return(line >= rule_lines); X case GT: return(line > rule_lines); X case NE: return(line != rule_lines); X case EQ: return(line == rule_lines); X } X return(-1); X} END_OF_filter/rules.c if test 6383 -ne `wc -c <filter/rules.c`; then echo shar: \"filter/rules.c\" unpacked with wrong size!? fi # end of overwriting check fi echo shar: Extracting \"hdrs/elm.h\" \(5581 characters\) if test -f hdrs/elm.h ; then echo shar: Will not over-write existing file \"hdrs/elm.h\" else sed "s/^X//" >hdrs/elm.h <<'END_OF_hdrs/elm.h' X/** elm.h **/ X X/** Main header file for ELM mail system. **/ X X/** (C) Copyright 1986, Dave Taylor **/ X X#include <stdio.h> X#include <fcntl.h> X X#include "../hdrs/curses.h" X#include "../hdrs/defs.h" X X/******** static character string containing the version number *******/ X Xstatic char ident[] = { WHAT_STRING }; X X/******** and another string for the copyright notice ********/ X Xstatic char copyright[] = { "@(#) (C) Copyright 1986, Dave Taylor" }; X X/******** global variables accessable by all pieces of the program *******/ X Xint current = 0; /* current message number */ Xint header_page = 0; /* current header page */ Xint last_header_page = -1; /* last header page */ Xint message_count = 0; /* max message number */ Xint headers_per_page; /* number of headers/page */ Xchar infile[SLEN]; /* name of current mailbox */ Xchar hostname[SLEN]; /* name of machine we're on*/ Xchar username[SLEN]; /* return address name! */ Xchar full_username[SLEN]; /* Full username - gecos */ Xchar home[SLEN]; /* home directory of user */ Xchar folders[SLEN]; /* folder home directory */ Xchar mailbox[SLEN]; /* mailbox name if defined */ Xchar editor[SLEN]; /* editor for outgoing mail*/ Xchar alternative_editor[SLEN]; /* alternative editor... */ Xchar printout[SLEN]; /* how to print messages */ Xchar savefile[SLEN]; /* name of file to save to */ Xchar calendar_file[SLEN]; /* name of file for clndr */ Xchar prefixchars[SLEN]; /* prefix char(s) for msgs */ Xchar shell[SLEN]; /* current system shell */ Xchar pager[SLEN]; /* what pager to use */ Xchar batch_subject[SLEN]; /* subject buffer for batchmail */ Xchar local_signature[SLEN]; /* local msg signature file */ Xchar remote_signature[SLEN]; /* remote msg signature file */ X Xchar backspace, /* the current backspace char */ X kill_line; /* the current kill-line char */ X Xchar up[SHORT], down[SHORT]; /* cursor control seq's */ Xint cursor_control = FALSE; /* cursor control avail? */ X Xchar start_highlight[SHORT], X end_highlight[SHORT]; /* stand out mode... */ X Xint has_highlighting = FALSE; /* highlighting available? */ X Xchar *weedlist[MAX_IN_WEEDLIST]; Xint weedcount; X Xint allow_forms = NO; /* flag: are AT&T Mail forms okay? */ Xint file_changed = 0; /* flag: true if infile changed */ Xint mini_menu = 1; /* flag: menu specified? */ Xint mbox_specified = 0; /* flag: specified alternate mbox? */ Xint check_first = 1; /* flag: verify mail to be sent! */ Xint auto_copy = 0; /* flag: automatically copy source? */ Xint filter = 1; /* flag: weed out header lines? */ Xint resolve_mode = 1; /* flag: delete saved mail? */ Xint auto_cc = 0; /* flag: mail copy to user? */ Xint noheader = 1; /* flag: copy + header to file? */ Xint title_messages = 1; /* flag: title message display? */ Xint edit_outbound = 0; /* flag: edit outbound headers? */ Xint hp_terminal = 0; /* flag: are we on HP term? */ Xint hp_softkeys = 0; /* flag: are there softkeys? */ Xint save_by_name = 1; /* flag: save mail by login name? */ Xint mail_only = 0; /* flag: send mail then leave? */ Xint check_only = 0; /* flag: check aliases then leave? */ Xint move_when_paged = 0; /* flag: move when '+' or '-' used? */ Xint point_to_new = 1; /* flag: start pointing at new msg? */ Xint bounceback = 0; /* flag: bounce copy off remote? */ Xint signature = 0; /* flag: include $home/.signature? */ Xint always_leave = 0; /* flag: always leave msgs pending? */ Xint always_del = 0; /* flag: always delete marked msgs? */ Xint arrow_cursor = 0; /* flag: use "->" cursor regardless?*/ Xint debug = 0; /* flag: default is no debug! */ Xint read_in_aliases = 0; /* flag: have we read in aliases?? */ Xint warnings = 1; /* flag: output connection warnings?*/ Xint user_level = 0; /* flag: how good is the user? */ Xint selected = 0; /* flag: used for select stuff */ Xint names_only = 1; /* flag: display user names only? */ Xint question_me = 1; /* flag: ask questions as we leave? */ Xint keep_empty_files = 0; /* flag: leave empty mailbox files? */ X X#ifdef UTS X int isatube = 0; /* flag: are we on an IBM 3270? */ X#endif X Xint sortby = REVERSE SENT_DATE; /* how to sort incoming mail... */ X Xlong timeout = 600L; /* timeout (secs) on main prompt */ X Xint mailbox_defined = 0; /** mailbox specified? **/ X X/** set up some default values for a 'typical' terminal *snicker* **/ X Xint LINES=23; /** lines per screen **/ Xint COLUMNS=80; /** columns per page **/ X Xlong size_of_pathfd; /** size of pathfile, 0 if none **/ X XFILE *mailfile; /* current mailbox file */ XFILE *debugfile; /* file for debug output */ XFILE *pathfd; /* path alias file */ XFILE *domainfd; /* domain file */ X Xlong mailfile_size; /* size of current mailfile */ X Xint max_headers; /* number of headers allocated */ X Xstruct header_rec *header_table; X Xstruct alias_rec user_hash_table[MAX_UALIASES]; Xstruct alias_rec system_hash_table[MAX_SALIASES]; X Xstruct date_rec last_read_mail; /* last time we read mailbox */ X Xstruct lsys_rec *talk_to_sys; /* what machines do we talk to? */ X Xstruct addr_rec *alternative_addresses; /* how else do we get mail? */ X Xint system_files = 0; /* do we have system aliases? */ Xint user_files = 0; /* do we have user aliases? */ X Xint system_data; /* fileno of system data file */ Xint user_data; /* fileno of user data file */ X Xint userid; /* uid for current user */ Xint groupid; /* groupid for current user */ END_OF_hdrs/elm.h if test 5581 -ne `wc -c <hdrs/elm.h`; then echo shar: \"hdrs/elm.h\" unpacked with wrong size!? fi # end of overwriting check fi echo shar: Extracting \"hdrs/headers.h\" \(5735 characters\) if test -f hdrs/headers.h ; then echo shar: Will not over-write existing file \"hdrs/headers.h\" else sed "s/^X//" >hdrs/headers.h <<'END_OF_hdrs/headers.h' X/** headers.h **/ X X/** header file for ELM mail system. **/ X X/** (C) Copyright 1985, Dave Taylor **/ X X#include <stdio.h> X#include <fcntl.h> X X#include "curses.h" X#include "defs.h" X X/******** global variables accessable by all pieces of the program *******/ X Xextern int current; /* current message number */ Xextern int header_page; /* current header page */ Xextern int last_header_page; /* last header page */ Xextern int message_count; /* max message number */ Xextern int headers_per_page; /* number of headers/page */ Xextern char infile[SLEN]; /* name of current mailbox */ Xextern char hostname[SLEN]; /* name of machine we're on*/ Xextern char username[SLEN]; /* return address name! */ Xextern char full_username[SLEN];/* Full username - gecos */ Xextern char home[SLEN]; /* home directory of user */ Xextern char folders[SLEN]; /* folder home directory */ Xextern char mailbox[SLEN]; /* mailbox name if defined */ Xextern char editor[SLEN]; /* default editor for mail */ Xextern char alternative_editor[SLEN];/* the 'other' editor */ Xextern char printout[SLEN]; /* how to print messages */ Xextern char savefile[SLEN]; /* name of file to save to */ Xextern char calendar_file[SLEN];/* name of file for clndr */ Xextern char prefixchars[SLEN]; /* prefix char(s) for msgs */ Xextern char shell[SLEN]; /* default system shell */ Xextern char pager[SLEN]; /* what pager to use... */ Xextern char batch_subject[SLEN];/* subject buffer for batchmail */ Xextern char local_signature[SLEN];/* local msg signature file */ Xextern char remote_signature[SLEN];/* remote msg signature file */ X Xextern char backspace, /* the current backspace char */ X kill_line; /* the current kill_line char */ X Xextern char up[SHORT], X down[SHORT]; /* cursor control seq's */ Xextern int cursor_control; /* cursor control avail? */ X Xextern char start_highlight[SHORT], X end_highlight[SHORT]; /* standout mode... */ X Xextern int has_highlighting; /* highlighting available? */ X X/** the following two are for arbitrary weedout lists.. **/ X Xextern char *weedlist[MAX_IN_WEEDLIST]; Xextern int weedcount; /* how many headers to check? */ X Xextern int allow_forms; /* flag: are AT&T Mail forms okay? */ Xextern int file_changed; /* flag: true iff infile changed */ Xextern int mini_menu; /* flag: display menu? */ Xextern int mbox_specified; /* flag: specified alternate mailbox? */ Xextern int check_first; /* flag: verify mail to be sent! */ Xextern int auto_copy; /* flag: auto copy source into reply? */ Xextern int filter; /* flag: weed out header lines? */ Xextern int resolve_mode; /* flag: resolve before moving mode? */ Xextern int auto_cc; /* flag: mail copy to yourself? */ Xextern int noheader; /* flag: copy + header to file? */ Xextern int title_messages; /* flag: title message display? */ Xextern int edit_outbound; /* flag: edit outbound headers? */ Xextern int hp_terminal; /* flag: are we on an hp terminal? */ Xextern int hp_softkeys; /* flag: are there softkeys? */ Xextern int save_by_name; /* flag: save mail by login name? */ Xextern int mail_only; /* flag: send mail then leave? */ Xextern int check_only; /* flag: check aliases and leave? */ Xextern int move_when_paged; /* flag: move when '+' or '-' used? */ Xextern int point_to_new; /* flag: start pointing at new msgs? */ Xextern int bounceback; /* flag: bounce copy off remote? */ Xextern int signature; /* flag: include $home/.signature? */ Xextern int always_leave; /* flag: always leave mail pending? */ Xextern int always_del; /* flag: always delete marked msgs? */ Xextern int arrow_cursor; /* flag: use "->" regardless? */ Xextern int debug; /* flag: debugging mode on? */ Xextern int read_in_aliases; /* flag: have we read in aliases yet? */ Xextern int warnings; /* flag: output connection warnings? */ Xextern int user_level; /* flag: how knowledgable is user? */ Xextern int selected; /* flag: used for select stuff */ Xextern int names_only; /* flag: display names but no addrs? */ Xextern int question_me; /* flag: ask questions as we leave? */ Xextern int keep_empty_files; /* flag: keep empty files?? */ X X#ifdef UTS Xextern int isatube; /* flag: are we on an IBM 3270 tube? */ X#endif X Xextern int sortby; /* how to sort mailboxes */ X Xextern long timeout; /* seconds for main level timeout */ X Xextern int mailbox_defined; /** specified mailbox? **/ X Xextern int LINES; /** lines per screen **/ Xextern int COLUMNS; /** columns per line **/ X Xextern long size_of_pathfd; /** size of pathfile, 0 if none **/ X Xextern FILE *mailfile; /* current mailbox file */ Xextern FILE *debugfile; /* file for debut output */ Xextern FILE *pathfd; /* path alias file */ Xextern FILE *domainfd; /* domains file */ X Xextern long mailfile_size; /* size of current mailfile */ X Xextern int max_headers; /* number of headers currently allocated */ X Xextern struct header_rec *header_table; X Xextern struct alias_rec user_hash_table [MAX_UALIASES]; Xextern struct alias_rec system_hash_table[MAX_SALIASES]; X Xextern struct date_rec last_read_mail; X Xextern struct lsys_rec *talk_to_sys; /* who do we talk to? */ X Xextern struct addr_rec *alternative_addresses; /* how else do we get mail? */ X Xextern int system_files; /* do we have system aliases? */ Xextern int user_files; /* do we have user aliases? */ X Xextern int system_data; /* fileno of system data file */ Xextern int user_data; /* fileno of user data file */ X Xextern int userid; /* uid for current user */ Xextern int groupid; /* groupid for current user */ END_OF_hdrs/headers.h if test 5735 -ne `wc -c <hdrs/headers.h`; then echo shar: \"hdrs/headers.h\" unpacked with wrong size!? fi # end of overwriting check fi echo shar: Extracting \"src/calendar.c\" \(5495 characters\) if test -f src/calendar.c ; then echo shar: Will not over-write existing file \"src/calendar.c\" else sed "s/^X//" >src/calendar.c <<'END_OF_src/calendar.c' X/** calendar.c **/ X X/** This routine implements a rather snazzy idea suggested by Warren X Carithers of the Rochester Institute of Technology that allows X mail to contain entries formatted in a manner that will allow direct X copying into a users calendar program. X X Never able to leave good-enough alone, I've extended this idea to a X further one - the knowledge of a different type of calendar program X too. Specifically, the current message can contain either of; X X -> Mon 04/21 1:00p meet with chairman candidate X X or X X - >April 21 X - X - 1:00 pm: Meet with Chairman Candidate X - X X The first type will have the leading '->' removed and all subsequent X white space, creating a simple one-line entry in the users calendar X file. The second type will remove the '-' and the leading white X spaces and leave everything else intact (that is, the file in the X second example would be appended with ">April 21" followed by a X blank line, the 1:00 pm meeting info, and another blank line. X X The file to include this in is either the default as defined in the X sysdefs.h file (see CALENDAR_FILE) or a filename contained in the X users ".elmrc" file, "calendar= <filename>". X X (C) Copyright 1986 Dave Taylor X**/ X X#include "headers.h" X X#ifdef ENABLE_CALENDAR /* if not defined, this will be an empty file */ X X#include <errno.h> X Xextern int errno; X Xchar *error_name(), *error_description(), *strcpy(); X Xscan_calendar() X{ X FILE *calendar; X int count; X X /* First step is to open the celendar file for appending... **/ X X if (can_open(calendar_file, "a") != 0) { X dprint1(2, "Error: wrong permissions to append to calendar %s\n", X calendar_file); X dprint2(2, "** %s - %s **\n", X error_name(errno), error_description(errno)); X error1("Not able to append to file %s!", calendar_file); X return; X } X X if ((calendar = fopen(calendar_file,"a")) == NULL) { X dprint1(2, "Error: couldn't append to calendar file %s (save)\n", X calendar_file); X dprint2(2, "** %s - %s **\n", X error_name(errno), error_description(errno)); X error1("Couldn't append to file %s!", calendar_file); X return; X } X X count = extract_info(calendar); X X fclose(calendar); X X chown(calendar_file, userid, groupid); /* ensure owned by user */ X X if (count > 0) X error2("%d entr%s saved in calendar file", X count, count > 1 ? "ies" : "y"); X else X error("No calendar entries found in that message"); X X return; X} X Xint Xextract_info(save_to_fd) XFILE *save_to_fd; X{ X /** Save the relevant parts of the current message to the given X calendar file. The only parameter is an opened file X descriptor, positioned at the end of the existing file **/ X X register int entries = 0, ok = 1, lines, index, in_entry = FALSE; X char buffer[SLEN]; X X /** get to the first line of the message desired **/ X X if (fseek(mailfile, header_table[current-1].offset, 0) == -1) { X dprint2(1,"ERROR: Attempt to seek %d bytes into file failed (%s)", X header_table[current-1].offset, "extract_info"); X error1("ELM [seek] failed trying to read %d bytes into file", X header_table[current-1].offset); X return(0); X } X X /* how many lines in message? */ X X lines = header_table[current-1].lines; X X /* now while not EOF & still in message... scan it! */ X X while (ok && lines--) { X ok = (int) (fgets(buffer, LONG_SLEN, mailfile) != NULL); X X /* now let's see if it matches the basic pattern... */ X X if ((index = calendar_line(buffer)) > -1) { X X if (buffer[index] == '>') { /* single line entry */ X if (remove_through_ch(buffer, '>')) { X fprintf(save_to_fd,"%s", buffer); X entries++; X } X } X else { /* multi-line entry */ X fprintf(save_to_fd, "%s", (char *) (buffer + index + 1)); X in_entry = TRUE; X } X } X else if (in_entry) { X in_entry = FALSE; X entries++; X } X } X X dprint2(4,"Got %d calender entr%s.\n", entries, entries > 1? "ies":"y"); X X return(entries); X} X Xint Xcalendar_line(string) Xchar *string; X{ X /** Iff the input line is of the form; X X {white space} <one or more '-'> X X this routine will return the index of the NEXT character X after the dashed sequence...If this pattern doesn't occur, X or if any other problems are encountered, it'll return "-1" X **/ X X register int loc = 0; X X if (chloc(string,'-') == -1) /* no dash??? */ X return(-1); /* that was easy! */ X X /** skip leading white space... **/ X X while (whitespace(string[loc])) loc++; /* MUST have '-' too! */ X X if (string[loc] != '-') return(-1); /* nice try, sleazo! */ X X while (string[loc] == '-') loc++; X X if (loc >= strlen(string)) return(-1); /* Empty line... */ X X /* otherwise.... */ X X return(loc); X} X X Xint Xremove_through_ch(string, ch) Xchar *string; Xchar ch; X{ X /** removes all characters from zero to ch in the string, and X any 'white-space' following the 'n'th char... if it hits a X NULL string, it returns FALSE, otherwise it'll return TRUE! X **/ X X char buffer[SLEN]; X register int index = 0, i = 0; X X while (string[index] != ch && string[index] != '\0') X index++; X X if (index >= strlen(string)) X return(FALSE); /* crash! burn! */ X X index++; /* get past the 'ch' character... */ X X while (whitespace(string[index])) index++; X X while (index < strlen(string)) X buffer[i++] = string[index++]; X X buffer[i] = '\0'; X X strcpy(string, buffer); X X return(TRUE); X} X X#endif END_OF_src/calendar.c if test 5495 -ne `wc -c <src/calendar.c`; then echo shar: \"src/calendar.c\" unpacked with wrong size!? fi # end of overwriting check fi echo shar: Extracting \"src/hdrconfg.c\" \(5434 characters\) if test -f src/hdrconfg.c ; then echo shar: Will not over-write existing file \"src/hdrconfg.c\" else sed "s/^X//" >src/hdrconfg.c <<'END_OF_src/hdrconfg.c' X/** hdrconfg.c **/ X X/** This file contains the routines necessary to be able to modify X the mail headers of messages on the way off the machine. The X headers currently supported for modification are: X X Subject: X To: X Cc: X Bcc: X Reply-To: X X Expiration-Date: X Priority: X In-Reply-To: X Action: X X <user defined> X X (C) Copyright 1985, Dave Taylor X**/ X X#include <stdio.h> X#include "headers.h" X X#include <ctype.h> X X#ifdef BSD X#undef toupper X#endif X X/* these are all defined in the mailmsg file! */ X Xextern char subject[SLEN], action[SLEN], in_reply_to[SLEN], expires[SLEN], X priority[SLEN], reply_to[SLEN], to[VERY_LONG_STRING], X cc[VERY_LONG_STRING], expanded_to[VERY_LONG_STRING], X expanded_cc[VERY_LONG_STRING], user_defined_header[SLEN]; X X#ifdef ALLOW_BCC Xextern char bcc[VERY_LONG_STRING], expanded_bcc[VERY_LONG_STRING]; X#endif X Xchar *strip_commas(), *strcpy(); X Xedit_headers() X{ X /** Edit headers. **/ X X int unexpanded_to = TRUE, unexpanded_cc = TRUE; X#ifdef ALLOW_BCC X int unexpanded_bcc = TRUE; X#endif X char c; X X if (mail_only) goto outta_here; /* how did we get HERE??? */ X X display_headers(); X X while (TRUE) { /* forever */ X PutLine0(LINES-1,0,"Choice: "); X CleartoEOLN(); X c = toupper(getchar()); X clear_error(); X switch (c) { X case RETURN: X case LINE_FEED: X case 'Q' : goto outta_here; X case ctrl('L') : display_headers(); X break; X case 'T' : if (optionally_enter(to, 2, 5, TRUE) == -1) X goto outta_here; X build_address(strip_commas(to), expanded_to); X unexpanded_to = FALSE; X break; X case 'S' : if (optionally_enter(subject, 7, 9, FALSE) == -1) X goto outta_here; X break; X#ifdef ALLOW_BCC X case 'B' : if (optionally_enter(bcc, 4, 5, TRUE) == -1) X goto outta_here; X build_address(strip_commas(bcc), expanded_bcc); X unexpanded_bcc = FALSE; X break; X#endif X case 'C' : if (optionally_enter(cc, 3, 5, TRUE) == -1) X goto outta_here; X build_address(strip_commas(cc), expanded_cc); X unexpanded_cc = FALSE; X break; X case 'R' : if (optionally_enter(reply_to, 5, 10, FALSE) == -1) X goto outta_here; X break; X case 'A' : if (optionally_enter(action, 9, 9, FALSE) == -1) X goto outta_here; X break; X case 'E' : enter_date(10, 17, expires); X break; X case 'P' : if (optionally_enter(priority, 11,10, FALSE) == -1) X goto outta_here; X break; X case 'U' : if (optionally_enter(user_defined_header,14,0,FALSE)==-1) X goto outta_here; X else X check_user_header(user_defined_header); X break; X case 'I' : if (strlen(in_reply_to) > 0) { X if (optionally_enter(in_reply_to, 12,13, FALSE) == -1) X goto outta_here; X break; X } X /** else fall through as an error **/ X default : error("Unknown header being specified!"); X } X } X Xoutta_here: /* this section re-expands aliases before we leave... */ X X if (unexpanded_to) X build_address(strip_commas(to), expanded_to); X if (unexpanded_cc) X build_address(strip_commas(cc), expanded_cc); X#ifdef ALLOW_BCC X if (unexpanded_bcc) X build_address(strip_commas(bcc), expanded_bcc); X#endif X} X Xdisplay_headers() X{ X ClearScreen(); X X Centerline(0,"Message Header Edit Screen"); X X PutLine1(2,0,"To : %s", to); X PutLine1(3,0,"Cc : %s", cc); CleartoEOLN(); X#ifdef ALLOW_BCC X PutLine1(4,0,"Bcc: %s", bcc); CleartoEOLN(); X#endif X PutLine1(5,0,"Reply-To: %s", reply_to); CleartoEOS(); X X PutLine1(7,0,"Subject: %s", subject); X PutLine1(9,0,"Action : %s", action); X PutLine1(10,0,"Expiration-Date: %s", expires); X PutLine1(11,0,"Priority: %s", priority); X if (strlen(in_reply_to) > 0) X PutLine1(12,0,"In-Reply-To: %s", in_reply_to); X X if (strlen(user_defined_header) > 0) X PutLine1(14,0, "%s", user_defined_header); X X Centerline(LINES-5, X"Choose first letter of existing header, U)ser defined header, or <return>"); X} X Xenter_date(x, y, buffer) Xint x, y; Xchar *buffer; X{ X /** Enter the number of days this message is valid for, then X display at (x,y) the actual date of expiration. This X routine relies heavily on the routine 'days_ahead()' in X the file date.c X **/ X X int days; X X PutLine0(LINES-1,0, "How many days in the future should it expire? "); X CleartoEOLN(); X Raw(OFF); X gets(buffer); X Raw(ON); X sscanf(buffer, "%d", &days); X if (days < 1) X error("That doesn't make sense!"); X else if (days > 14) X error("Expiration date must be within two weeks of today"); X else { X days_ahead(days, buffer); X PutLine0(x, y, buffer); X } X} X Xcheck_user_header(header) Xchar *header; X{ X /** check the header format...if bad print error and erase! **/ X X register int i = -1; X X if (strlen(header) == 0) X return; X X if (whitespace(header[0])) { X error ("you can't have leading white space in a header!"); X header[0] = '\0'; X ClearLine(14); X return; X } X X if (header[0] == ':') { X error ("you can't have a colon as the first character!"); X header[0] = '\0'; X ClearLine(14); X return; X } X X while (header[++i] != ':') { X if (header[i] == '\0') { X error("you need a colon ending the field!"); X header[0] = '\0'; X ClearLine(14); X return; X } X else if (whitespace(header[i])) { X error("You can't have white space imbedded in the header name!"); X header[0] = '\0'; X ClearLine(14); X return; X } X } X X return; X} END_OF_src/hdrconfg.c if test 5434 -ne `wc -c <src/hdrconfg.c`; then echo shar: \"src/hdrconfg.c\" unpacked with wrong size!? fi # end of overwriting check fi echo shar: Extracting \"src/help.c\" \(5969 characters\) if test -f src/help.c ; then echo shar: Will not over-write existing file \"src/help.c\" else sed "s/^X//" >src/help.c <<'END_OF_src/help.c' X/** help.c **/ X X/*** help routine for ELM program X X (C) Copyright 1985, Dave Taylor X X***/ X X#include <ctype.h> X X#ifdef BSD X# undef tolower X#endif X X#include "headers.h" X Xhelp() X{ X /** Process the request for help [section] from the user **/ X X char ch; /* character buffer for input */ X char *s; /* string pointer... */ X X MoveCursor(LINES-7,0); X CleartoEOS(); X X Centerline(LINES-7, "ELM Help System"); X Centerline(LINES-5, X "Press keys you want help for, '?' for a list, or '.' to end"); X X PutLine0(LINES-3, 0, "Help on key: "); X X do { X MoveCursor(LINES-3, strlen("Help on key: ")); X ch = tolower(ReadCh()); X X if (ch == '.') return(0); /* zero means footer rewrite only */ X X s = "Unknown command. Use '?' for a list of commands..."; X X switch (ch) { X X case '?': display_helpfile(MAIN_HELP); return(1); X X case '$': s = X "$ = Force a resync of the current mailbox. This will 'purge' deleted mail"; X break; X X case '!': s = X "! = Escape to the Unix shell of your choice, or just to enter commands"; X break; X case '@': s = X "@ = Debug - display a summary of the messages on the header page"; X break; X case '|': s = X "| = Pipe the current message or tagged messages to the command specified"; X break; X case '#': s = X "# = Debug - display all information known about current message"; X break; X case '%': s = X "% = Debug - display the computed return address of the current message"; X break; X case '*': s = "* = Go to the last message in the current mailbox"; X break; X case '-': s = X "- = Go to the previous page of messages in the current mailbox"; X break; X case '=': s = X "'=' = Go to the first message in the current mailbox"; X break; X case ' ': X case '+': s = X "+ = Go to the next page of messages in the current mailbox"; X break; X case '/': s = "/ = Search for specified pattern in mailbox"; X break; X case '<': s = X "< = Scan current message for calendar entries (if enabled)"; X break; X case '>': s = X "> = Save current message or tagged messages to specified file"; X break; X case '^': s = X "^ = Toggle the Delete/Undelete status of the current message"; X break; X case 'a': s = X "a = Enter the alias sub-menu section. Create and display aliases"; X break; X case 'b': s = X "b = Bounce (remail) a message to someone as if you have never seen it"; X break; X case 'c': s = X "c = Change mailboxes, leaving the current mailbox as if 'quitting'"; X break; X case 'd': s = "d = Mark the current message for future deletion"; X break; X case ctrl('D') : X s = "^D = Mark for deletion all messages with the specified pattern"; X break; X case 'e': s = X "e = Invoke the editor on the entire mailbox, resync'ing when done"; X break; X case 'f': s = X "f = Forward the current message to someone, return address is yours"; X break; X case 'g': s = X "g = Group reply not only to the sender, but to everyone who received msg"; X break; X case 'h': s = X "h = Display message with all Headers (ignore weedout list)"; X break; X case 'j': s = X "j = Go to the next message. This is the same as the DOWN arrow"; X break; X case 'k': s = X "k = Go to the previous message. This is the same as the UP arrow"; X break; X case 'm': s = X "m = Create and send mail to the specified person or persons"; X break; X case 'n': s = X "n = Read the current message, then move current to next messge"; X break; X case 'o': s = "o = Go to the options submenu"; X break; X case 'p': s = X "p = Print the current message or the tagged messages"; X break; X case 'q': s = X "q = Quit the mailer, asking about deletion, saving, etc"; X break; X case 'r': s = X "r = Reply to the message. This only sends to the originator of the message"; X break; X case 's': s = X "s = Save current message or tagged messages to specified file"; X break; X case 't': s = X "t = Tag a message for further operations (or untag if tagged)"; X break; X case ctrl('T') : X s = "^T = tag all messages with the specified pattern"; X break; X case 'u': X s = "u = Undelete - remove the deletion mark on the message"; X break; X case 'x': s = "x = Exit the mail system quickly"; X break; X X case '\n': X case '\r': s = "<return> = Read the current message"; X break; X X case ctrl('L'): s = "^L = Rewrite the screen"; X break; X case ctrl('?'): /* DEL */ X case ctrl('Q'): s = "Exit the mail system quickly"; X break; X default : if (isdigit(ch)) X s = "<number> = Make specified number the current message"; X } X X ClearLine(LINES-1); X Centerline(LINES-1, s); X X } while (ch != '.'); X X /** we'll never actually get here, but that's okay... **/ X X return(0); X} X Xdisplay_helpfile(section) Xint section; X{ X /*** Help me! Read file 'helpfile.<section>' and echo to screen ***/ X X FILE *hfile; X char buffer[SLEN]; X int lines=0; X X sprintf(buffer, "%s/%s.%d", helphome, helpfile, section); X if ((hfile = fopen(buffer,"r")) == NULL) { X dprint1(1,"Error: Couldn't open helpfile %s (help)\n", buffer); X error1("couldn't open helpfile %s",buffer); X return(FALSE); X } X X ClearScreen(); X X while (fgets(buffer, SLEN, hfile) != NULL) { X if (lines > LINES-3) { X PutLine0(LINES,0,"Press any key to continue: "); X (void) ReadCh(); X lines = 0; X ClearScreen(); X Write_to_screen("%s\r", 1, buffer); X } X else X Write_to_screen("%s\r", 1, buffer); X X lines++; X } X X PutLine0(LINES,0,"Press any key to return: "); X X (void) ReadCh(); X clear_error(); X X return(TRUE); X} END_OF_src/help.c if test 5969 -ne `wc -c <src/help.c`; then echo shar: \"src/help.c\" unpacked with wrong size!? fi # end of overwriting check fi echo shar: Extracting \"src/pattern.c\" \(5598 characters\) if test -f src/pattern.c ; then echo shar: Will not over-write existing file \"src/pattern.c\" else sed "s/^X//" >src/pattern.c <<'END_OF_src/pattern.c' X/** pattern.c **/ X X/** General pattern matching for the ELM mailer. X X (C) Copyright 1986 Dave Taylor X**/ X X#include <errno.h> X X#include "headers.h" X Xstatic char pattern[SLEN] = { "" }; Xstatic char alt_pattern[SLEN] = { "" }; X Xextern int errno; X Xchar *error_name(), *shift_lower(), *strcpy(); X Xmeta_match(function) Xint function; X{ X /** Perform specific function based on whether an entered string X matches either the From or Subject lines.. X **/ X X register int i, tagged=0, count=0; X static char meta_pattern[SLEN]; X X PutLine1(LINES-3, strlen("Command: "), X "%s messages that match pattern...", X function==TAGGED?"Tag": function==DELETED?"Delete":"Undelete"); X X if (function == TAGGED) { /* are messages already tagged??? */ X for (i=0; i < message_count; i++) X if (ison(header_table[i].status,TAGGED)) X tagged++; X X if (tagged) { X if (tagged > 2) X PutLine0(LINES-2,0, "Some messages are already tagged"); X else X PutLine0(LINES-2,0, "A message is already tagged"); X X Write_to_screen("- Remove tag%s? y%c", 2, plural(tagged),BACKSPACE); X X if (tolower(ReadCh()) != 'n') { /* remove tags... */ X for (i=0; i < message_count; i++) { X clearit(header_table[i].status,TAGGED); X show_new_status(i); X } X } X } X } X X PutLine0(LINES-2,0, "Enter pattern: "); CleartoEOLN(); X X optionally_enter(meta_pattern, LINES-2,strlen("Enter pattern: "),FALSE); X X if (strlen(meta_pattern) == 0) { X ClearLine(LINES-2); X return(0); X } X X strcpy(meta_pattern, shift_lower(meta_pattern)); /* lowercase it */ X X for (i = 0; i < message_count; i++) { X if (from_matches(i, meta_pattern)) { X if ((selected && header_table[i].status & VISIBLE) || ! selected) { X if (function == UNDELETE) X clearit(header_table[i].status, DELETED); X else X setit(header_table[i].status, function); X show_new_status(i); X count++; X } X } X else if (subject_matches(i, meta_pattern)) { X if ((selected && header_table[i].status & VISIBLE) || ! selected) { X if (function == UNDELETE) X clearit(header_table[i].status, DELETED); X else X setit(header_table[i].status, function); X show_new_status(i); X count++; X } X } X } X X ClearLine(LINES-2); /* remove "pattern: " prompt */ X X if (count > 0) X error3("%s %d messsage%s", X function==TAGGED? "tagged" : X function==DELETED? "marked for deletion" : "undeleted", X count, plural(count)); X else X error1("no matches - no messages %s", X function==TAGGED? "tagged" : X function==DELETED? "marked for deletion": "undeleted"); X X return(0); X} X Xint Xpattern_match() X{ X /** Get a pattern from the user and try to match it with the X from/subject lines being displayed. If matched (ignoring X case), move current message pointer to that message, if X not, error and return ZERO **/ X X register int i; X X PutLine0(LINES-3,40,"/ = match anywhere in messages"); X X PutLine0(LINES-1,0, "Match Pattern:"); X X if (pattern_enter(pattern, alt_pattern, LINES-1, 16, X "Match Pattern (in entire mailbox):")) X if (strlen(alt_pattern) > 0) { X strcpy(alt_pattern, shift_lower(alt_pattern)); X return(match_in_message(alt_pattern)); X } X else X return(1); X X if (strlen(pattern) == 0) X return(0); X else X strcpy(pattern, shift_lower(pattern)); X X for (i = current; i < message_count; i++) { X if (from_matches(i, pattern)) { X if (!selected || (selected && header_table[i].status & VISIBLE)) { X current = ++i; X return(1); X } X } X else if (subject_matches(i, pattern)) { X if (!selected || (selected && header_table[i].status & VISIBLE)) { X current = ++i; X return(1); X } X } X } X X return(0); X} X Xint Xfrom_matches(message_number, pat) Xint message_number; Xchar *pat; X{ X /** Returns true iff the pattern occurs in it's entirety X in the from line of the indicated message **/ X X return( in_string(shift_lower(header_table[message_number].from), X pat) ); X} X Xint Xsubject_matches(message_number, pat) Xint message_number; Xchar *pat; X{ X /** Returns true iff the pattern occurs in it's entirety X in the subject line of the indicated message **/ X X return( in_string(shift_lower(header_table[message_number].subject), X pat) ); X} X Xmatch_in_message(pat) Xchar *pat; X{ X /** Match a string INSIDE a message...starting at the current X message read each line and try to find the pattern. As X soon as we do, set current and leave! X Returns 1 if found, 0 if not X **/ X X char buffer[LONG_STRING]; X int message_number, lines, line; X X message_number = current-1; X X error("searching mailbox for pattern..."); X X while (message_number < message_count) { X X if (fseek(mailfile, header_table[message_number].offset, 0L) != 0) { X X dprint3(1,"Error: seek %ld bytes into file failed. errno %d (%s)\n", X header_table[message_number].offset, errno, X "match_in_message"); X error2("ELM [match] failed looking %ld bytes into file (%s)", X header_table[message_number].offset, error_name(errno)); X return(1); /* fake it out to avoid replacing error message */ X } X X line = 0; X lines = header_table[message_number].lines; X X while (fgets(buffer, LONG_STRING, mailfile) != NULL && line < lines) { X X line++; X X if (in_string(shift_lower(buffer), pat)) { X current = message_number+1; X clear_error(); X return(1); X } X } X X /** now we've passed the end of THIS message...increment and X continue the search with the next message! **/ X X message_number++; X } X X return(0); X} END_OF_src/pattern.c if test 5598 -ne `wc -c <src/pattern.c`; then echo shar: \"src/pattern.c\" unpacked with wrong size!? fi # end of overwriting check fi echo shar: Extracting \"src/utils.c\" \(5852 characters\) if test -f src/utils.c ; then echo shar: Will not over-write existing file \"src/utils.c\" else sed "s/^X//" >src/utils.c <<'END_OF_src/utils.c' X/** utils.c **/ X X/** Utility routines for ELM X X All routines herein: (C) Copyright 1985 Dave Taylor X**/ X X#include "headers.h" X#include <sys/types.h> X#include <sys/stat.h> X#include <ctype.h> X#include <errno.h> X X#ifdef BSD X#undef tolower X#endif X X#include <signal.h> X Xextern int errno; X Xchar *error_name(); Xvoid exit(); X Xshow_mailfile_stats() X{ X /** when we're about to die, let's try to dump lots of good stuff X to the debug file... **/ X X struct stat buffer; X X if (debug == 0) return; /* Damn! Can't do it! */ X X if (fstat(fileno(mailfile), &buffer) == 0) { X dprint1(1,"\nDump of stats for mailfile %s;\n", infile); X X dprint3(1, "\tinode: %d, mode: %o, uid: %d, ", X buffer.st_ino, buffer.st_mode, buffer.st_uid); X dprint2(1,"gid: %d, size: %d\n\n", buffer.st_gid, buffer.st_size); X X dprint1(1,"\toffset into file = %l\n", ftell(mailfile)); X } X else X dprint2(1,"\nfstat on mailfile '%s' failed with error %s!!\n\n", X infile, error_name(errno)); X} X Xemergency_exit() X{ X /** used in dramatic cases when we must leave without altering X ANYTHING about the system... **/ X X dprint0(1, X "\nERROR: Something dreadful is happening! Taking emergency exit!!\n\n"); X dprint0(1," possibly leaving behind the following files;\n"); X dprint2(1," The mailbox tempfile : %s%s\n", temp_mbox, username); X dprint2(1," The mailbox lock file: %s%s.lock\n", mailhome, username); X dprint2(1," The composition file : %s%d\n", temp_file, getpid()); X dprint2(1," The header comp file : %s%d\n", temp_file, getpid()+1); X dprint2(1," The readmsg data file: %s/%s\n", home, readmsg_file); X X Raw(OFF); X if (cursor_control) transmit_functions(OFF); X if (hp_terminal) softkeys_off(); X X if (cursor_control) X MoveCursor(LINES, 0); X X PutLine0(LINES,0, "\nEmergency Exit taken! All temp files intact!\n\n"); X X exit(1); X} X X/*ARGSUSED*/ X/*VARARGS0*/ X Xleave(val) Xint val; /* not used, placeholder for signal catching! */ X{ X char buffer[SLEN]; X X dprint0(2,"\nLeaving mailer normally (leave)\n"); X X Raw(OFF); X if (cursor_control) transmit_functions(OFF); X if (hp_terminal) softkeys_off(); X X sprintf(buffer,"%s%d",temp_file, getpid()); /* editor buffer */ X (void) unlink(buffer); X X sprintf(buffer,"%s%d",temp_file, getpid()+1); /* editor buffer */ X (void) unlink(buffer); X X sprintf(buffer,"%s%s",temp_mbox, username); /* temp mailbox */ X (void) unlink(buffer); X X sprintf(buffer,"%s/%s", home, readmsg_file); /* readmsg temp */ X (void) unlink(buffer); X X sprintf(buffer,"%s%s.lock",mailhome, username); /* lock file */ X (void) unlink(buffer); X X if (! mail_only) { X MoveCursor(LINES,0); X Writechar('\n'); X } X X exit(0); X} X Xsilently_exit() X{ X /** This is the same as 'leave', but it doesn't remove any non-pid X files. It's used when we notice that we're trying to create a X temp mail file and one already exists!! X **/ X char buffer[SLEN]; X X dprint0(2,"\nLeaving mailer quietly (silently_exit)\n"); X X Raw(OFF); X if (cursor_control) transmit_functions(OFF); X if (hp_terminal) softkeys_off(); X X sprintf(buffer,"%s%d",temp_file, getpid()); /* editor buffer */ X (void) unlink(buffer); X X sprintf(buffer,"%s%d",temp_file, getpid()+1); /* editor buffer */ X (void) unlink(buffer); X X if (! mail_only) { X MoveCursor(LINES,0); X Writechar('\n'); X } X X exit(0); X} X X/*ARGSUSED0*/ X Xleave_locked(val) Xint val; /* not used, placeholder for signal catching! */ X{ X /** same as leave routine, but don't disturb lock file **/ X X char buffer[SLEN]; X X dprint0(3, X "\nLeaving mailer due to presence of lock file (leave_locked)\n"); X X Raw(OFF); X if (cursor_control) transmit_functions(OFF); X if (hp_terminal) softkeys_off(); X X sprintf(buffer,"%s%d",temp_file, getpid()); /* editor buffer */ X (void) unlink(buffer); X X sprintf(buffer,"%s%d",temp_file, getpid()+1); /* editor buffer */ X (void) unlink(buffer); X X sprintf(buffer,"%s%s",temp_mbox, username); /* temp mailbox */ X (void) unlink(buffer); X X MoveCursor(LINES,0); X Writechar('\n'); X X exit(0); X} X Xint Xget_page(msg_pointer) Xint msg_pointer; X{ X /** Ensure that 'current' is on the displayed page, X returning non-zero iff the page changed! **/ X X register int first_on_page, last_on_page; X X dprint1(6,"* get_page(%d) returns...", msg_pointer); X X first_on_page = (header_page * headers_per_page) + 1; X X last_on_page = first_on_page + headers_per_page - 1; X X dprint2(8,"[first-on-page=%d, last-on-page=%d]", X first_on_page, last_on_page); X X if (selected) /* but what is it on the SCREEN??? */ X msg_pointer = compute_visible(msg_pointer-1); X X if (selected && msg_pointer > selected) { X dprint0(6,"FALSE - too far!\n"); X return(FALSE); /* too far - page can't change! */ X } X X if (msg_pointer > last_on_page) { X header_page = (int) (msg_pointer-(selected? 0:1)) / headers_per_page; X dprint3(6,"TRUE (%d > %d New hp=%d)!\n", X msg_pointer, last_on_page, header_page); X return(1); X } X else if (msg_pointer < first_on_page) { X header_page = (int) (msg_pointer-1) / headers_per_page; X dprint3(6,"TRUE (%d < %d New hp=%d)!\n", X msg_pointer, first_on_page, header_page); X return(1); X } X else { X dprint2(6,"FALSE [first=%d last=%d]\n", X first_on_page, last_on_page); X return(0); X } X} X Xchar *nameof(filename) Xchar *filename; X{ X /** checks to see if 'filename' has any common prefixes, if X so it returns a string that is the same filename, but X with '=' as the folder directory, or '~' as the home X directory.. X **/ X X static char buffer[STRING]; X register int i = 0, index = 0; X X if (strncmp(filename, folders, strlen(folders)) == 0) { X buffer[i++] = '='; X index = strlen(folders); X } X else if (strncmp(filename, home, strlen(home)) == 0) { X buffer[i++] = '~'; X index = strlen(home); X } X else index = 0; X X while (filename[index] != '\0') X buffer[i++] = filename[index++]; X buffer[i] = '\0'; X X return( (char *) buffer); X} END_OF_src/utils.c if test 5852 -ne `wc -c <src/utils.c`; then echo shar: \"src/utils.c\" unpacked with wrong size!? fi # end of overwriting check fi echo shar: End of archive 5 \(of 19\). cp /dev/null ark5isdone DONE=true for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do if test ! -f ark${I}isdone ; then echo shar: You still need to run archive ${I}. DONE=false fi done if test "$DONE" = "true" ; then echo You have unpacked all 19 archives. echo "See the Instructions file" rm -f ark[1-9]isdone ark[1-9][0-9]isdone fi ## End of shell archivenlCopyrp_