home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume9
/
elm2
/
part05
< prev
next >
Wrap
Text File
|
1987-03-08
|
58KB
|
1,975 lines
Subject: v09i005: ELM Mail System, Part05/19
Newsgroups: mod.sources
Approved: rs@mirror.TMC.COM
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 archive.
exit 0