rsalz@uunet.uu.net (Rich Salz) (05/26/90)
Submitted-by: Syd Weinstein <syd@dsinc.dsi.com>
Posting-number: Volume 22, Issue 68
Archive-name: elm2.3/part09
---- Cut Here and unpack ----
#!/bin/sh
# this is part 9 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file filter/filter.c continued
#
CurArch=9
if test ! -r s2_seq_.tmp
then echo "Please unpack part 1 first!"
exit 1; fi
( read Scheck
if test "$Scheck" != $CurArch
then echo "Please unpack part $Scheck next!"
exit 1;
else exit 0; fi
) < s2_seq_.tmp || exit 1
echo "x - Continuing file filter/filter.c"
sed 's/^X//' << 'SHAR_EOF' >> filter/filter.c
X#include "defs.h"
X#ifdef I_TIME
X# include <time.h>
X#endif
X#ifdef I_SYSTIME
X# include <sys/time.h>
X#endif
X#include <fcntl.h>
X
X#define MAIN_ROUTINE /* for the filter.h file, of course! */
X#include "filter.h"
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X extern char *optarg;
X FILE *fd; /* for output to temp file! */
X struct passwd *passwd_entry;
X#ifndef _POSIX_SOURCE
X struct passwd *getpwuid(); /* for /etc/passwd */
X#endif
X char filename[SLEN], /* name of the temp file */
X buffer[MAX_LINE_LEN]; /* input buffer space */
X int in_header = TRUE, /* for header parsing */
X in_to = FALSE, /* are we on 'n' line To: ? */
X summary = FALSE, /* a summary is requested? */
X c; /* var for getopt routine */
X
X /* first off, let's get the info from /etc/passwd */
X
X if ((passwd_entry = getpwuid(getuid())) == NULL)
X leave("Cannot get password entry for this uid!");
X
X strcpy(home, passwd_entry->pw_dir);
X strcpy(username, passwd_entry->pw_name);
X outfname[0] = to[0] = '\0'; /* nothing read in yet, right? */
X
X#ifdef HOSTCOMPILED
X strncpy(hostname, HOSTNAME, sizeof(hostname));
X#else
X gethostname(hostname, sizeof(hostname));
X#endif
X
X /* now parse the starting arguments... */
X
X while ((c = getopt(argc, argv, "clno:rSsv")) != EOF) {
X switch (c) {
X case 'c' : clear_logs = TRUE; break;
X case 'l' : log_actions_only = TRUE; break;
X case 'o' : strcpy(outfname, optarg); break;
X case 'r' : printing_rules = TRUE; break;
X
X case 's' : summary = TRUE; break;
X case 'S' : long_summary = TRUE; break;
X
X case 'n' : show_only = TRUE; break;
X case 'v' : verbose = TRUE; break;
X case '?' : fprintf(stderr,
X "Usage: | filter [-nrv]\n or: filter [-c] -[s|S]\n");
X exit(1);
X }
X }
X
X if (c < 0) {
X }
X
X /* let's open our outfd logfile as needed... */
X
X if (outfname[0] == '\0') /* default is stdout */
X outfd = stdout;
X else
X if ((outfd = fopen(outfname, "a")) == NULL) {
X if (isatty(fileno(stderr)))
X fprintf(stderr,"filter (%s): couldn't open log file %s\n",
X username, outfname);
X }
X
X if (summary || long_summary) {
X if (get_filter_rules() == -1) {
X exit(1);
X if (outfd != NULL) fclose(outfd);
X }
X show_summary();
X if (outfd != NULL) fclose(outfd);
X exit(0);
X }
X
X if (printing_rules) {
X if (get_filter_rules() == -1)
X fprintf(outfd,"filter (%s): Couldn't get rules!\n", username);
X else
X print_rules();
X if (outfd != NULL) fclose(outfd);
X exit(0);
X }
X
X /* next, create the tempfile and save the incoming message */
X
X sprintf(filename, "%s.%d", filter_temp, getpid());
X
X if ((fd = fopen(filename,"w")) == NULL)
X leave("Cannot open temporary file!");
X
X while (fgets(buffer, MAX_LINE_LEN, stdin) != NULL) {
X
X remove_return(buffer);
X
X if (in_header) {
X
X if (! whitespace(buffer[0]))
X in_to = FALSE;
X
X if (the_same(buffer, "From "))
X save_from(buffer);
X else if (the_same(buffer, "Subject:"))
X save_subject(buffer);
X else if (the_same(buffer, "To:") || the_same(buffer, "Cc:")) {
X in_to++;
X save_to(buffer);
X }
X else if (the_same(buffer, "X-Filtered-By:"))
X already_been_forwarded++; /* could be a loop here! */
X#ifdef USE_EMBEDDED_ADDRESSES
X else if (the_same(buffer, "From:"))
X save_embedded_address(buffer, "From:");
X else if (the_same(buffer, "Reply-To:"))
X save_embedded_address(buffer, "Reply-To:");
X#endif
X else if (strlen(buffer) < 2)
X in_header = 0;
X else if (whitespace(buffer[0]) && in_to)
X strcat(to, buffer);
X }
X
X fprintf(fd, "%s\n", buffer); /* and save it regardless! */
X fflush(fd);
X lines++;
X }
X
X fclose(fd);
X
X /** next let's see if the user HAS a filter file, and if so what's in
X it (and so on) **/
X
X if (get_filter_rules() == -1)
X mail_message(username);
X else {
X switch (action_from_ruleset()) {
X
X case DELETE_MSG : if (verbose && outfd != NULL)
X fprintf(outfd, "filter (%s): Message deleted\n",
X username);
X log(DELETE_MSG); break;
X
X case SAVE : if (save_message(rules[rule_choosen].argument2)) {
X mail_message(username);
X log(FAILED_SAVE);
X }
X else
X log(SAVE); break;
X
X case SAVECC : if (save_message(rules[rule_choosen].argument2))
X log(FAILED_SAVE);
X else
X log(SAVECC);
X mail_message(username); break;
X
X case FORWARD: mail_message(rules[rule_choosen].argument2);
X log(FORWARD); break;
X
X case EXEC : execute(rules[rule_choosen].argument2);
X log(EXEC); break;
X
X case LEAVE : mail_message(username);
X log(LEAVE); break;
X }
X }
X
X (void) unlink(filename); /* remove the temp file, please! */
X if (outfd != NULL) fclose(outfd);
X exit(0);
X}
X
Xsave_from(buffer)
Xchar *buffer;
X{
X /** save the SECOND word of this string as FROM **/
X
X register char *f = from;
X
X while (*buffer != ' ')
X buffer++; /* get to word */
X
X for (buffer++; *buffer != ' ' && *buffer; buffer++, f++)
X *f = *buffer; /* copy it and */
X
X *f = '\0'; /* Null terminate! */
X}
X
Xsave_subject(buffer)
Xchar *buffer;
X{
X /** save all but the word "Subject:" for the subject **/
X
X register int skip = 8; /* skip "Subject:" initially */
X
X while (buffer[skip] == ' ') skip++;
X
X strcpy(subject, (char *) buffer + skip);
X}
X
Xsave_to(buffer)
Xchar *buffer;
X{
X /** save all but the word "To:" or "Cc:" for the to list **/
X
X register int skip = 3; /* skip "To:" or "Cc:" initially */
X
X while (buffer[skip] == ' ') skip++;
X
X strcat(to, (char *) buffer + skip);
X}
X
X#ifdef USE_EMBEDDED_ADDRESSES
X
Xsave_embedded_address(buffer, fieldname)
Xchar *buffer, *fieldname;
X{
X /** this will replace the 'from' address with the one given,
X unless the address is from a 'reply-to' field (which overrides
X the From: field). The buffer given to this routine can have one
X of three forms:
X fieldname: username <address>
X fieldname: address (username)
X fieldname: address
X **/
X
X static int processed_a_reply_to = 0;
X char address[LONG_STRING];
X register int i, j = 0;
X
X /** first let's extract the address from this line.. **/
X
X if (buffer[strlen(buffer)-1] == '>') { /* case #1 */
X for (i=strlen(buffer)-1; buffer[i] != '<' && i > 0; i--)
X /* nothing - just move backwards .. */ ;
X i++; /* skip the leading '<' symbol */
X while (buffer[i] != '>')
X address[j++] = buffer[i++];
X address[j] = '\0';
X }
X else { /* get past "from:" and copy until white space or paren hit */
X for (i=strlen(fieldname); whitespace(buffer[i]); i++)
X /* skip past that... */ ;
X while (buffer[i] != '(' && ! whitespace(buffer[i]) && buffer[i]!='\0')
X address[j++] = buffer[i++];
X address[j] = '\0';
X }
X
X /** now let's see if we should overwrite the existing from address
X with this one or not.. **/
X
X if (processed_a_reply_to)
X return; /* forget it! */
X
X strcpy(from, address); /* replaced!! */
X
X if (strcmp(fieldname, "Reply-To:") == 0)
X processed_a_reply_to++;
X}
X#endif
SHAR_EOF
echo "File filter/filter.c is complete"
chmod 0444 filter/filter.c || echo "restore of filter/filter.c fails"
echo "x - extracting filter/lock.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > filter/lock.c &&
X
Xstatic char rcsid[] ="@(#)$Id: lock.c,v 4.1 90/04/28 22:41:57 syd Exp $";
X
X/*******************************************************************************
X * The Elm Mail System - $Revision: 4.1 $ $State: Exp $
X *
X * Copyright (c) 1986, 1987 Dave Taylor
X * Copyright (c) 1988, 1989, 1990 USENET Community Trust
X *******************************************************************************
X * Bug reports, patches, comments, suggestions should be sent to:
X *
X * Syd Weinstein - elm@DSI.COM
X * dsinc!elm
X *
X *******************************************************************************
X * $Log: lock.c,v $
X * Revision 4.1 90/04/28 22:41:57 syd
X * checkin of Elm 2.3 as of Release PL0
X *
X *
X ******************************************************************************/
X
X
X/** The lock() and unlock() routines herein duplicate exactly the
X equivalent routines in the Elm Mail System, and should also be
X compatible with sendmail, rmail, etc etc.
X
X
X**/
X
X#include <stdio.h>
X#include <fcntl.h>
X#include <errno.h>
X#include "defs.h"
X#include "filter.h"
X
Xstatic int we_locked_it;
Xstatic char lockfile[SLEN];
X
X#ifdef LOCK_BY_FLOCK
X#include <sys/types.h>
X#include <sys/file.h>
Xstatic flock_fd = -1;
Xstatic char flock_name[SLEN];
X#endif
X
Xextern int errno;
X
Xint
Xlock()
X{
X /** This routine will return 1 if we could lock the mailfile,
X zero otherwise.
X **/
X
X int attempts = 0, ret;
X
X#ifndef LOCK_FLOCK_ONLY /* { !LOCK_FLOCK_ONLY */
X sprintf(lockfile, "%s%s.lock", mailhome, username);
X#ifdef PIDCHECK
X /** first, try to read the lock file, and if possible, check the pid.
X If we can validate that the pid is no longer active, then remove
X the lock file.
X **/
X if((ret=open(lockfile,O_RDONLY)) != -1) {
X char pid_buffer[SHORT];
X if (read(ret, pid_buffer, SHORT) > 0) {
X attempts = atoi(pid_buffer);
X if (attempts) {
X if (kill(attempts, 0)) {
X close(ret);
X if (unlink(lockfile) != 0)
X return(1);
X }
X }
X }
X attempts = 0;
X }
X#endif
X
X while ((ret = open(lockfile, O_WRONLY | O_CREAT | O_EXCL, 0444)) < 0
X && attempts++ < 10) {
X sleep(3); /* wait three seconds each pass, okay?? */
X }
X
X if (ret >= 0) {
X we_locked_it++;
X close(ret); /* no need to keep it open! */
X ret = 1;
X } else {
X ret = 0;
X }
X
X#endif /* } !LOCK_FLOCK_ONLY */
X#ifdef LOCK_BY_FLOCK /* { LOCK_BY_FLOCK */
X (void)sprintf(flock_name,"%s%s",mailhome,username);
X flock_fd = open(flock_name,O_RDONLY);
X if ( flock_fd >= 0 )
X for (attempts = 0; attempts < 10; attempts++) {
X if ( (ret = flock(flock_fd,LOCK_NB|LOCK_EX)) != -1 )
X break;
X if ( errno != EWOULDBLOCK && errno != EAGAIN )
X break;
X (void)sleep((unsigned)3);
X }
X if ( flock_fd >= 0 && ret == 0 ) {
X we_locked_it++;
X ret = 1;
X } else {
X we_locked_it = 0;
X if ( lockfile[0] ) {
X (void)unlink(lockfile);
X lockfile[0] = 0;
X }
X if ( flock_fd >= 0 ) {
X (void)close(flock_fd);
X flock_fd = -1;
X }
X ret = 0;
X }
X#endif
X return(ret);
X}
X
Xunlock()
X{
X /** this routine will remove the lock file, but only if we were
X the people that locked it in the first place... **/
X
X#ifndef LOCK_FLOCK_ONLY
X if (we_locked_it && lockfile[0]) {
X unlink(lockfile); /* blamo! */
X lockfile[0] = 0;
X }
X#endif
X#ifdef LOCK_BY_FLOCK
X if (we_locked_it && flock_fd >= 0) {
X (void)close(flock_fd);
X flock_fd = -1;
X }
X#endif
X we_locked_it = 0;
X}
SHAR_EOF
chmod 0444 filter/lock.c || echo "restore of filter/lock.c fails"
echo "x - extracting filter/parse.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > filter/parse.c &&
X
Xstatic char rcsid[] ="@(#)$Id: parse.c,v 4.1 90/04/28 22:41:58 syd Exp $";
X
X/*******************************************************************************
X * The Elm Mail System - $Revision: 4.1 $ $State: Exp $
X *
X * Copyright (c) 1986, 1987 Dave Taylor
X * Copyright (c) 1988, 1989, 1990 USENET Community Trust
X *******************************************************************************
X * Bug reports, patches, comments, suggestions should be sent to:
X *
X * Syd Weinstein - elm@DSI.COM
X * dsinc!elm
X *
X *******************************************************************************
X * $Log: parse.c,v $
X * Revision 4.1 90/04/28 22:41:58 syd
X * checkin of Elm 2.3 as of Release PL0
X *
X *
X ******************************************************************************/
X
X
X/** This is the parser for the filter program. It accepts a wide variety of
X constructs, building the ruleset table as it goes along. Check the
X data structure in filter.h for more information on how the rules are
X stored. The parser is a cunning state-table based program.
X
X**/
X
X#include <stdio.h>
X#include <ctype.h>
X
X#include "defs.h"
X#include "filter.h"
X
X#define NONE 0
X#define AND 10
X
X#define NEXT_CONDITION 0
X#define GETTING_OP 1
X#define READING_ARGUMENT 2
X#define READING_ACTION 3
X#define ACTION_ARGUMENT 4
X
Xchar *strtok(), *whatname(), *actionname();
X
Xint
Xget_filter_rules()
X{
X /** Given the users home directory, open and parse their rules table,
X building the data structure as we go along.
X returns -1 if we hit an error of any sort...
X **/
X
X FILE *fd; /* the file descriptor */
X char buffer[SLEN], /* fd reading buffer */
X *str, /* ptr to read string */
X *word, /* ptr to 'token' */
X filename[SLEN], /* the name of the ruleset */
X action_argument[SLEN], /* action arg, per rule */
X cond_argument[SLEN]; /* cond arg, per condition */
X int not_condition = FALSE, /* are we in a "not" ?? */
X type=NONE, /* what TYPE of condition? */
X lasttype, /* and the previous TYPE? */
X state = NEXT_CONDITION, /* the current state */
X in_single, in_double, /* for handling spaces. */
X i, /* misc integer for loops */
X relop = NONE, /* relational operator */
X action, /* the current action type */
X buflen, /* the length of buffer */
X line = 0; /* line number we're on */
X
X struct condition_rec *cond, *newcond;
X
X sprintf(filename,"%s/%s", home, filterfile);
X
X if ((fd = fopen(filename,"r")) == NULL) {
X if (outfd != NULL)
X fprintf(outfd,"filter (%s): Couldn't read user filter rules file!\n",
X username);
X return(-1);
X }
X
X cond_argument[0] = action_argument[0] = '\0';
X
X /* Now, for each line... **/
X
X if ((cond = (struct condition_rec *)
X malloc(sizeof(struct condition_rec))) == NULL) {
X if (outfd != NULL)
X fprintf(outfd,"filter (%s): couldn't malloc first condition rec!\n",
X username);
X return(-1);
X }
X
X rules[total_rules].condition = cond; /* hooked in! */
X
X while (fgets(buffer, SLEN, fd) != NULL) {
X line++;
X
X if (buffer[0] == '#' || (buflen = strlen(buffer)) < 2)
X continue; /* nothing to look at! */
X
X in_single = in_double = 0;
X
X for (i=0; i < buflen; i++) {
X if (buffer[i] == '"')
X in_double = ! in_double;
X else if (buffer[i] == '\'')
X in_single = ! in_single;
X if ((in_double || in_single) && buffer[i] == ' ')
X buffer[i] = '_';
X }
X
X lasttype = type;
X type = NONE;
X str = (char *) buffer;
X
X /** Three pieces to this loop - get the `field', the 'relop' (if
X there) then, if needed, get the argument to check against (not
X needed for errors or the AND, of course)
X **/
X
X while ((word = strtok(str, " ()[]:\t\n")) != NULL) {
X
X str = (char *) NULL; /* we can startFrom syd@dsinc.dsi.com Sat Apr 28 23:37:13 1990
Received: from BBN.COM by pineapple.bbn.com id <AA11646@pineapple.bbn.com>; Sat, 28 Apr 90 23:36:26 -0400
Received: from dsinc.dsi.com by BBN.COM id aa11584; 28 Apr 90 23:34 EDT
Received: by dsinc.dsi.com (/\=-/\ Smail3.1.18.1 #18.14)
id <m0hP53M-0000K8C@dsinc.dsi.com>; Sat, 28 Apr 90 23:34 EDT
Message-Id: <m0hP53M-0000K8C@dsinc.dsi.com>
Date: Sat, 28 Apr 90 23:34 EDT
From: Syd Weinstein <syd@dsinc.dsi.com>
To: rsalz@BBN.COM
Subject: Elm 2.3 PL 0 release for comp.sources.unix, Part 10/26
---- Cut Here and unpack ----
#!/bin/sh
# this is part 10 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file hdrs/defs.h continued
#
CurArch=10
if test ! -r s2_seq_.tmp
then echo "Please unpack part 1 first!"
exit 1; fi
( read Scheck
if test "$Scheck" != $CurArch
then echo "Please unpack part $Scheck next!"
exit 1;
else exit 0; fi
) < s2_seq_.tmp || exit 1
echo "x - Continuing file hdrs/defs.h"
sed 's/^X//' << 'SHAR_EOF' >> hdrs/defs.h
X/** a few for the usage of function keys... **/
X
X#define f1 1
X#define f2 2
X#define f3 3
X#define f4 4
X#define f5 5
X#define f6 6
X#define f7 7
X#define f8 8
X
X#define MAIN 0
X#define ALIAS 1
X#define YESNO 2
X#define CHANGE 3
X#define READ 4
X
X#define MAIN_HELP 0
X#define OPTIONS_HELP 1
X#define ALIAS_HELP 2
X#define PAGER_HELP 3
X
X/** types of folders **/
X#define NO_NAME 0 /* variable contains no file name */
X#define NON_SPOOL 1 /* mailfile not in mailhome */
X#define SPOOL 2 /* mailfile in mailhome */
X
X/* the following is true if the current mailfile is the user's spool file*/
X#define USERS_SPOOL (strcmp(cur_folder, defaultfile) == 0)
X
X/** some possible sort styles... **/
X
X#define REVERSE - /* for reverse sorting */
X#define SENT_DATE 1 /* the date message was sent */
X#define RECEIVED_DATE 2 /* the date message was received */
X#define SENDER 3 /* the name/address of sender */
X#define SIZE 4 /* the # of lines of the message */
X#define SUBJECT 5 /* the subject of the message */
X#define STATUS 6 /* the status (deleted, etc) */
X#define MAILBOX_ORDER 7 /* the order it is in the file */
X
X/* some stuff for our own malloc call - pmalloc */
X
X#define PMALLOC_THRESHOLD 256 /* if greater, then just use malloc */
X#define PMALLOC_BUFFER_SIZE 2048 /* internal [memory] buffer size... */
X
X/** the following macro is as suggested by Larry McVoy. Thanks! **/
X
X# ifdef DEBUG
X# define dprint(n,x) { \
X if (debug >= n) { \
X fprintf x ; \
X fflush(debugfile); \
X } \
X }
X# else
X# define dprint(n,x)
X# endif
X
X/* some random structs... */
X
Xstruct date_rec {
X int month; /** this record stores a **/
X int day; /** specific date and **/
X int year; /** time... **/
X int hour;
X int minute;
X };
X
Xstruct header_rec {
X int lines; /** # of lines in the message **/
X int status; /** Urgent, Deleted, Expired? **/
X int index_number; /** relative loc in file... **/
X int encrypted; /** whether msg has encryption **/
X int exit_disposition; /** whether to keep, store, delete **/
X int status_chgd; /** whether became read or old, etc. **/
X long offset; /** offset in bytes of message **/
X struct date_rec received; /** when elm received here **/
X char from[STRING]; /** who sent the message? **/
X char to[STRING]; /** who it was sent to **/
X char messageid[STRING]; /** the Message-ID: value **/
X char dayname[8]; /** when the **/
X char month[10]; /** message **/
X char day[3]; /** was **/
X char year[5]; /** sent **/
X char time[NLEN]; /** to you! **/
X char time_zone[12]; /** incl. tz */
X long time_sent; /** gmt when sent for sorting **/
X char subject[STRING]; /** The subject of the mail **/
X char mailx_status[WLEN];/** mailx status flags (RO...) **/
X };
X
Xstruct alias_rec {
X char name[NLEN]; /* alias name */
X long byte; /* offset into data file for address */
X };
X
Xstruct lsys_rec {
X char name[NLEN]; /* name of machine connected to */
X struct lsys_rec *next; /* linked list pointer to next */
X };
X
Xstruct addr_rec {
X char address[NLEN]; /* machine!user you get mail as */
X struct addr_rec *next; /* linked list pointer to next */
X };
X
X#ifdef SHORTNAMES /* map long names to shorter ones */
X# include <shortname.h>
X#endif
X
X/** Let's make sure that we're not going to have any annoying problems with
X int pointer sizes versus char pointer sizes by guaranteeing that every-
X thing vital is predefined... (Thanks go to Detlev Droege for this one)
X**/
X
X#ifdef STRINGS
X# include <strings.h>
X#else
X# include <string.h>
X#endif
X
X/*
X * Macros for network/external number representation conversion.
X */
X#ifdef NETWORK_ORDER
Xunsigned short ntohs(), htons();
Xunsigned long ntohl(), htonl();
X#else
X#define ntohl(x) (x)
X#define ntohs(x) (x)
X#define htonl(x) (x)
X#define htons(x) (x)
X#endif
X
Xchar *argv_zero();
Xchar *bounce_off_remote();
Xchar *ctime();
Xchar *error_description();
Xchar *error_name();
Xchar *error_number();
Xchar *expand_address();
Xchar *expand_domain();
Xchar *expand_group();
Xchar *expand_logname();
Xchar *expand_system();
Xchar *find_path_to();
Xchar *format_long();
Xchar *get_alias_address();
Xchar *get_arpa_date();
Xchar *get_ctime_date();
Xchar *get_date();
Xchar *get_token();
Xchar *getenv();
Xchar *getlogin();
Xchar *level_name();
Xchar *match_and_expand_domain();
Xchar *shift_lower();
Xchar *strip_commas();
Xchar *strip_parens();
Xchar *strpbrk();
Xchar *strtok();
Xchar *tail_of_string();
Xchar *tgetstr();
Xchar *pmalloc();
X
Xlong lseek();
Xlong times();
Xlong ulimit();
SHAR_EOF
echo "File hdrs/defs.h is complete"
chmod 0444 hdrs/defs.h || echo "restore of hdrs/defs.h fails"
echo "x - extracting hdrs/elm.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > hdrs/elm.h &&
X
X/* $Id: elm.h,v 4.1 90/04/28 22:42:08 syd Exp $ */
X
X/*******************************************************************************
X * The Elm Mail System - $Revision: 4.1 $ $State: Exp $
X *
X * Copyright (c) 1986, 1987 Dave Taylor
X * Copyright (c) 1988, 1989, 1990 USENET Community Trust
X *******************************************************************************
X * Bug reports, patches, comments, suggestions should be sent to:
X *
X * Syd Weinstein, Elm Coordinator
X * elm@DSI.COM dsinc!elm
X *
X *******************************************************************************
X * $Log: elm.h,v $
X * Revision 4.1 90/04/28 22:42:08 syd
X * checkin of Elm 2.3 as of Release PL0
X *
X *
X ******************************************************************************/
X
X/** Main header file for ELM mail system. **/
X
X
X#include <stdio.h>
X#include <fcntl.h>
X#include <errno.h>
X
X#include "../hdrs/curses.h"
X#include "../hdrs/defs.h"
X
X#ifdef BSD
X#include <setjmp.h>
X#endif
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[] = {
X "@(#) (C) Copyright 1986, 1987, Dave Taylor\n@(#) (C) Copyright 1988, 1989, 1990, The Usenet Community Trust\n" };
X
X/******** global variables accessable by all pieces of the program *******/
X
Xint check_size = 0; /* don't start mailer if no mail */
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 */
Xint original_umask = 0; /* original umask, for restore before subshell */
Xint sendmail_verbose = 0; /* Extended mail debugging */
Xchar cur_folder[SLEN]; /* name of current folder */
Xchar cur_tempfolder[SLEN]; /* name of temp folder open for a mailbox */
Xchar defaultfile[SLEN]; /* name of default folder */
Xchar temp_dir[SLEN] = {0}; /* name of temp directory */
Xchar hostname[SLEN]; /* name of machine we're on*/
Xchar hostdomain[SLEN]; /* name of domain we're in */
Xchar hostfullname[SLEN]; /* name of FQDN we're in */
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 raw_folders[SLEN]; /* unexpanded folder home directory */
Xchar recvd_mail[SLEN]; /* folder for storing received mail */
Xchar raw_recvdmail[SLEN]; /* unexpanded recvd_mail name */
Xchar editor[SLEN]; /* editor for outgoing mail*/
Xchar raw_editor[SLEN]; /* unexpanded editor for outgoing mail*/
Xchar alternative_editor[SLEN]; /* alternative editor... */
Xchar printout[SLEN]; /* how to print messages */
Xchar raw_printout[SLEN]; /* unexpanded how to print messages */
Xchar sent_mail[SLEN]; /* name of file to save copies to */
Xchar raw_sentmail[SLEN]; /* unexpanded name of file to save to */
Xchar calendar_file[SLEN]; /* name of file for clndr */
Xchar raw_calendar_file[SLEN]; /* unexpanded name of file for clndr */
Xchar attribution[SLEN]; /* attribution string for replies */
Xchar prefixchars[SLEN] = "> "; /* prefix char(s) for msgs */
Xchar shell[SLEN]; /* current system shell */
Xchar raw_shell[SLEN]; /* unexpanded current system shell */
Xchar pager[SLEN]; /* what pager to use */
Xchar raw_pager[SLEN]; /* unexpanded what pager to use */
Xchar batch_subject[SLEN]; /* subject buffer for batchmail */
Xchar local_signature[SLEN]; /* local msg signature file */
Xchar raw_local_signature[SLEN]; /* unexpanded local msg signature file */
Xchar remote_signature[SLEN]; /* remote msg signature file */
Xchar raw_remote_signature[SLEN];/* unexpanded remote msg signature file */
Xchar version_buff[SLEN]; /* version buffer */
X
Xchar backspace, /* the current backspace char */
X escape_char = TILDE_ESCAPE,/* '~' or something else.. */
X kill_line; /* the current kill-line char */
X
Xchar up[SHORT], down[SHORT], /* cursor control seq's */
X left[SHORT], right[SHORT];
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 mini_menu = 1; /* flag: menu specified? */
Xint prompt_after_pager = 1; /* flag: prompt after pager exits */
Xint folder_type = 0; /* flag: type of folder */
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 forwarding = 0; /* flag: are we forwarding the msg? */
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 force_name = 0; /* flag: save by name forced? */
Xint mail_only = 0; /* flag: send mail then leave? */
Xint check_only = 0; /* flag: check aliases then leave? */
Xint batch_only = 0; /* flag: send without prompting? */
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 always_keep = 1; /* flag: always keep unread msgs? */
Xint always_store = 0; /* flag: always store read msgs? */
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 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 folder files? */
Xint clear_pages = 0; /* flag: act like "page" (more -c)? */
Xint prompt_for_cc = 1; /* flag: ask user for "cc:" value? */
Xint sig_dashes = 1; /* flag: include dashes above sigs? */
X
Xint sortby = REVERSE SENT_DATE; /* how to sort incoming mail... */
X
Xlong timeout = 600L; /* timeout (secs) on main prompt */
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 folder */
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 **headers; /* array of header structure pointers */
X
Xstruct alias_rec user_hash_table[MAX_UALIASES];
Xstruct alias_rec system_hash_table[MAX_SALIASES];
X
Xstruct lsys_rec *talk_to_sys = NULL; /* what machines do we talk to? */
X
Xstruct addr_rec *alternative_addresses; /* how else do we get mail? */
X
Xint system_data = -1; /* fileno of system data file */
Xint user_data = -1; /* fileno of user data file */
X
Xint userid; /* uid for current user */
Xint groupid; /* groupid for current user */
X
X#ifdef BSD
Xjmp_buf GetPromptBuf; /* setjmp buffer */
Xint InGetPrompt; /* set if in GetPrompt() in read() */
X#endif
SHAR_EOF
chmod 0444 hdrs/elm.h || echo "restore of hdrs/elm.h fails"
echo "x - extracting hdrs/filter.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > hdrs/filter.h &&
X
X/* $Id: filter.h,v 4.1 90/04/28 22:42:09 syd Exp $ */
X
X/*******************************************************************************
X * The Elm Mail System - $Revision: 4.1 $ $State: Exp $
X *
X * Copyright (c) 1986, 1987 Dave Taylor
X * Copyright (c) 1988, 1989, 1990 USENET Community Trust
X *******************************************************************************
X * Bug reports, patches, comments, suggestions should be sent to:
X *
X * Syd Weinstein, Elm Coordinator
X * elm@DSI.COM dsinc!elm
X *
X *******************************************************************************
X * $Log: filter.h,v $
X * Revision 4.1 90/04/28 22:42:09 syd
X * checkin of Elm 2.3 as of Release PL0
X *
X *
X ******************************************************************************/
X
X/** Headers for the filter program.
X
X**/
X
X#ifdef BSD
X# undef tolower
X#endif
X
X/** define a few handy macros for later use... **/
X
X#define the_same(a,b) (strncmp(a,b,strlen(b)) == 0)
X
X#define relationname(x) (x == 1?"<=":x==2?"<":x==3?">=":x==4?">":x==5?"!=":"=")
X
X#define quoteit(x) (x == LINES? "" : "\"")
X
X#define remove_return(s) { if (s[strlen(s)-1] == '\n') \
X s[strlen(s)-1] = '\0'; \
X }
X
X/** some of the files we'll be using, where they are, and so on... **/
X
X#define filter_temp "/tmp/filter"
X#define filterfile ".elm/filter-rules"
X#define filterlog ".elm/filterlog"
X#define filtersum ".elm/filtersum"
X
X#define EMERGENCY_MAILBOX "EMERGENCY_MBOX"
X#define EMERG_MBOX "MBOX.EMERGENCY"
X
X/** and now the hardwired constraint of the program.. **/
X
X#define MAXRULES 25 /* can't have more den dis, boss! */
X
X/** some random defines for mnemonic stuff in the program... **/
X
X#ifdef SUBJECT
X# undef SUBJECT
X#endif
X
X#define TO 1
X#define FROM 2
X#define LINES 3
X#define SUBJECT 4
X#define CONTAINS 5
X#define ALWAYS 6
X
X#define DELETE_MSG 7
X#define SAVE 8
X#define SAVECC 9
X#define FORWARD 10
X#define LEAVE 11
X#define EXEC 12
X
X#define FAILED_SAVE 20
X
X/** Some conditionals... **/
X
X#define LE 1
X#define LT 2
X#define GE 3
X#define GT 4
X#define NE 5
X#define EQ 6
X
X/** A funky way to open a file using open() to avoid file locking hassles **/
X
X#define FOLDERMODE O_WRONLY | O_APPEND | O_CREAT | O_SYNCIO
X
X/** cheap but easy way to have two files share the same #include file **/
X
X#ifdef MAIN_ROUTINE
X
Xchar home[SLEN], /* the users home directory */
X hostname[SLEN], /* the machine name... */
X username[SLEN]; /* the users login name... */
X
Xchar to[VERY_LONG_STRING],
X from[LONG_STRING],
X subject[LONG_STRING]; /* from current message */
X
XFILE *outfd;
Xchar outfname[SLEN];
X
Xint total_rules = 0, /* how many rules to check */
X show_only = FALSE, /* just for show? */
X long_summary = FALSE, /* what sorta summary?? */
X verbose = FALSE, /* spit out lots of stuff */
X lines = 0, /* lines in message.. */
X clear_logs = FALSE, /* clear files after sum? */
X already_been_forwarded = FALSE, /* has this been filtered? */
X log_actions_only = FALSE, /* log actions | everything */
X printing_rules = FALSE, /* are we just using '-r'? */
X rule_choosen; /* which one we choose */
X
X#else
X
Xextern char home[SLEN], /* the users home directory */
X hostname[SLEN], /* the machine name... */
X username[SLEN]; /* the users login name... */
X
Xextern char to[VERY_LONG_STRING],
X from[LONG_STRING],
X subject[LONG_STRING]; /* from current message */
X
Xextern FILE *outfd;
Xextern char outfname[SLEN];
X
Xextern int total_rules, /* how many rules to check */
X show_only, /* just for show? */
X long_summary, /* what sorta summary?? */
X verbose, /* spit out lots of stuff */
X lines, /* lines in message.. */
X clear_logs, /* clear files after sum? */
X already_been_forwarded, /* has this been filtered? */
X log_actions_only, /* log actions | everything */
X printing_rules, /* are we just using '-r'? */
X rule_choosen; /* which one we choose */
X#endif
X
X/** and our ruleset record structure... **/
X
Xstruct condition_rec {
X int matchwhat; /* type of 'if' clause */
X int relation; /* type of match (eq, etc) */
X char argument1[SLEN]; /* match against this */
X struct condition_rec *next; /* next condition... */
X };
X
Xstruct ruleset_record {
X char printable[SLEN]; /* straight from file... */
X struct condition_rec *condition;
X int action; /* what action to take */
X char argument2[SLEN]; /* argument for action */
X };
X
X#ifdef MAIN_ROUTINE
X struct ruleset_record rules[MAXRULES];
X#else
X extern struct ruleset_record rules[MAXRULES];
X#endif
X
X/** finally let's keep LINT happy with the return values of all these pups! ***/
X
Xchar *itoa();
X
X#ifdef _POSIX_SOURCE /*{_POSIX_SOURCE*/
X#include <string.h>
X#include <unistd.h>
X#include <stdlib.h>
X#else /*}_POSIX_SOURCE{*/
Xunsigned short getuid();
X
Xunsigned long sleep();
X
Xchar *malloc(), *strcpy(), *strcat();
X
Xvoid exit();
X
X#ifdef BSD
X
X FILE *popen();
X
X#ifdef MAIN_ROUTINE
X char _vbuf[5*BUFSIZ]; /* space for file buffering */
X#else
X extern char _vbuf[5*BUFSIZ]; /* space for file buffering */
X#endif
X
X#ifndef _IOFBF
X# define _IOFBF 0 /* doesn't matter - ignored */
X#endif
X
X# define setvbuf(fd,a,b,c) setbuffer(fd, _vbuf, 5*BUFSIZ)
X
X#endif
X#endif /*}_POSIX_SOURCE*/
SHAR_EOF
chmod 0444 hdrs/filter.h || echo "restore of hdrs/filter.h fails"
echo "x - extracting hdrs/headers.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > hdrs/headers.h &&
X
X/* $Id: headers.h,v 4.1 90/04/28 22:42:11 syd Exp $ */
X
X/*******************************************************************************
X * The Elm Mail System - $Revision: 4.1 $ $State: Exp $
X *
X * Copyright (c) 1986, 1987 Dave Taylor
X * Copyright (c) 1988, 1989, 1990 USENET Community Trust
X *******************************************************************************
X * Bug reports, patches, comments, suggestions should be sent to:
X *
X * Syd Weinstein, Elm Coordinator
X * elm@DSI.COM dsinc!elm
X *
X *******************************************************************************
X * $Log: headers.h,v $
X * Revision 4.1 90/04/28 22:42:11 syd
X * checkin of Elm 2.3 as of Release PL0
X *
X *
X ******************************************************************************/
X
X/** This is the header file for ELM mail system. **/
X
X
X#include <stdio.h>
X#include <fcntl.h>
X
X#include "curses.h"
X#include "defs.h"
X
X#ifdef BSD
X#include <setjmp.h>
X#endif
X
X#ifndef clearerr
X#define clearerr(p) (void)((p)->_flag &= ~(_IOERR|_IOEOF))
X#endif
X
X/******** global variables accessable by all pieces of the program *******/
X
Xextern int check_size; /* don't start mailer if no mail */
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 int original_umask; /* original umask, for restore before subshell */
Xextern int sendmail_verbose; /* Allow extended debugging on sendmail */
Xextern char cur_folder[SLEN]; /* name of current folder */
Xextern char cur_tempfolder[SLEN]; /* name of temp folder open for a mailbox */
Xextern char defaultfile[SLEN]; /* name of default folder */
Xextern char temp_dir[SLEN]; /* name of temp directory */
Xextern char hostname[SLEN]; /* name of machine we're on*/
Xextern char hostdomain[SLEN]; /* name of domain we're in */
Xextern char hostfullname[SLEN]; /* name of FQDN we're in */
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 raw_folders[SLEN]; /* unexpanded folder home directory */
Xextern char recvd_mail[SLEN]; /* folder for storing received mail */
Xextern char raw_recvdmail[SLEN];/* unexpanded recvd_mail name */
Xextern char editor[SLEN]; /* default editor for mail */
Xextern char raw_editor[SLEN]; /* unexpanded default editor for mail */
Xextern char alternative_editor[SLEN];/* the 'other' editor */
Xextern char printout[SLEN]; /* how to print messages */
Xextern char raw_printout[SLEN]; /* unexpanded how to print messages */
Xextern char sent_mail[SLEN]; /* name of file to save copies to */
Xextern char raw_sentmail[SLEN]; /* unexpanded name of file to save to */
Xextern char calendar_file[SLEN];/* name of file for clndr */
Xextern char raw_calendar_file[SLEN];/* unexpanded name of file for clndr */
Xextern char attribution[SLEN]; /* attribution string for replies */
Xextern char prefixchars[SLEN]; /* prefix char(s) for msgs */
Xextern char shell[SLEN]; /* default system shell */
Xextern char raw_shell[SLEN]; /* unexpanded default system shell */
Xextern char pager[SLEN]; /* what pager to use... */
Xextern char raw_pager[SLEN]; /* unexpanded what pager to use... */
Xextern char batch_subject[SLEN];/* subject buffer for batchmail */
Xextern char local_signature[SLEN];/* local msg signature file */
Xextern char raw_local_signature[SLEN];/* unexpanded local msg signature file */
Xextern char remote_signature[SLEN];/* remote msg signature file */
Xextern char raw_remote_signature[SLEN];/* unexpanded remote msg signature file*/
X
Xextern char backspace, /* the current backspace char */
X escape_char, /* '~' or something else... */
X kill_line; /* the current kill_line char */
X
Xextern char up[SHORT],
X down[SHORT],
X left[SHORT],
X right[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 prompt_after_pager; /* flag: prompt after pager exits */
Xextern int mini_menu; /* flag: display menu? */
Xextern int folder_type; /* flag: type of folder */
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 forwarding; /* flag: are we forwarding the msg? */
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 force_name; /* flag: save by name forced? */
Xextern int mail_only; /* flag: send mail then leave? */
Xextern int check_only; /* flag: check aliases and leave? */
Xextern int batch_only; /* flag: send without prompting? */
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 always_keep; /* flag: always keep unread msgs? */
Xextern int always_store; /* flag: always store read mail? */
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 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?? */
Xextern int clear_pages; /* flag: clear screen w/ builtin pgr? */
Xextern int prompt_for_cc; /* flag: prompt user for 'cc' value? */
Xextern int sig_dashes; /* flag: put dashes above signature? */
X
Xextern int sortby; /* how to sort folders */
X
Xextern long timeout; /* seconds for main level timeout */
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 folder */
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 **headers; /* array of header structure pointers */
X
Xextern struct alias_rec user_hash_table [MAX_UALIASES];
Xextern struct alias_rec system_hash_table[MAX_SALIASES];
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_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 */
X
X#ifdef BSD
Xextern jmp_buf GetPromptBuf; /* setjmp buffer */
Xextern int InGetPrompt; /* set if in GetPrompt() in read() */
X#endif
SHAR_EOF
chmod 0444 hdrs/headers.h || echo "restore of hdrs/headers.h fails"
echo "x - extracting hdrs/patchlevel.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > hdrs/patchlevel.h &&
X#define PATCHLEVEL 0
SHAR_EOF
chmod 0666 hdrs/patchlevel.h || echo "restore of hdrs/patchlevel.h fails"
echo "x - extracting hdrs/save_opts.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > hdrs/save_opts.h &&
X
X/* @(#)$Id: save_opts.h,v 4.1 90/04/28 22:42:12 syd Exp $ */
X
X/*******************************************************************************
X * The Elm Mail System - $Revision: 4.1 $ $State: Exp $
X *
X * Copyright (c) 1986, 1987 Dave Taylor
X * Copyright (c) 1988, 1989, 1990 USENET Community Trust
X *******************************************************************************
X * Bug reports, patches, comments, suggestions should be sent to:
X *
X * Syd Weinstein, Elm Coordinator
X * elm@DSI.COM dsinc!elm
X *
X *******************************************************************************
X * $Log: save_opts.h,v $
X * Revision 4.1 90/04/28 22:42:12 syd
X * checkin of Elm 2.3 as of Release PL0
X *
X *
X ******************************************************************************/
X
X/** Some crazy includes for the save-opts part of the Elm program!
X
X**/
X
X#define ALTERNATIVES 0
X#define ALWAYSDELETE 1
X#define ALWAYSKEEP 2
X#define ALWAYSSTORE 3
X#define ARROW 4
X#define ASK 5
X#define ASKCC 6
X#define ATTRIBUTION 7
X#define AUTOCOPY 8
X#define BOUNCEBACK 9
X#define CALENDAR 10
X#define COPY 11
X#define EDITOR 12
X#define ESCAPECHAR 13
X#define FORCENAME 14
X#define FORMS 15
X#define FULLNAME 16
X#define KEEPEMPTY 17
X#define KEYPAD 18
X#define LOCALSIGNATURE 19
X#define MAILDIR 20
X#define MENU 21
X#define MOVEPAGE 22
X#define NAMES 23
X#define NOHEADER 24
X#define PAGER 25
X#define POINTNEW 26
X#define PREFIX 27
X#define PRINT 28
X#define PROMPTAFTER 29
X#define RECEIVEDMAIL 30
X#define REMOTESIGNATURE 31
X#define RESOLVE 32
X#define SAVENAME 33
X#define SENTMAIL 34
X#define SHELL 35
X#define SIGDASHES 36
X#define SIGNATURE 37
X#define SOFTKEYS 38
X#define SORTBY 39
X#define TIMEOUT 40
X#define TITLES 41
X#define TMPDIR 42
X#define USERLEVEL 43
X#define WARNINGS 44
X#define WEED 45
X#define WEEDOUT 46
X
X#define NUMBER_OF_SAVEABLE_OPTIONS WEEDOUT+1
X
Xstruct save_info_recs {
X char name[NLEN]; /* name of instruction */
X long offset; /* offset into elmrc-info file */
X } save_info[NUMBER_OF_SAVEABLE_OPTIONS] =
X{
X { "alternatives", -1L },
X { "alwaysdelete", -1L },
X { "alwayskeep", -1L },
X { "alwaysstore", -1L },
X { "arrow", -1L},
X { "ask", -1L },
X { "askcc", -1L },
X { "attribution", -1L },
X { "autocopy", -1L },
X { "bounceback", -1L },
X { "calendar", -1L },
X { "copy", -1L },
X { "editor", -1L },
X { "escape", -1L },
X { "forcename", -1L },
X { "forms", -1L },
X { "fullname", -1L },
X { "keepempty", -1L },
X { "keypad", -1L },
X { "localsignature", -1L },
X { "maildir", -1L },
X { "menu", -1L },
X { "movepage", -1L },
X { "names", -1L },
X { "noheader", -1L },
X { "pager", -1L },
X { "pointnew", -1L},
X { "prefix", -1L },
X { "print", -1L },
X { "promptafter", -1L },
X { "receivedmail", -1L },
X { "remotesignature",-1L},
X { "resolve", -1L },
X { "savename", -1L },
X { "sentmail", -1L },
X { "shell", -1L },
X { "sigdashes", -1L },
X { "signature", -1L },
X { "softkeys", -1L },
X { "sortby", -1L },
X { "timeout", -1L },
X { "titles", -1L },
X { "tmpdir", -1L },
X { "userlevel", -1L },
X { "warnings", -1L },
X { "weed", -1L },
X { "weedout", -1L },
X};
SHAR_EOF
chmod 0444 hdrs/save_opts.h || echo "restore of hdrs/save_opts.h fails"
echo "x - extracting hdrs/sysdefs.SH (Text)"
sed 's/^X//' << 'SHAR_EOF' > hdrs/sysdefs.SH &&
Xcase $CONFIG in
X'')
X if test ! -f config.sh; then
X ln ../config.sh . || \
X ln ../../config.sh . || \
X ln ../../../config.sh . || \
X (echo "Can't find config.sh."; exit 1)
X echo "Using config.sh from above..."
X fi
X . ./config.sh
X ;;
Xesac
Xecho "Extracting hdrs/sysdefs.h (with variable substitutions)"
Xsed <<!GROK!THIS! >sysdefs.h -e 's!^#undef!/\*#undef!'
X/* $Id: sysdefs.SH,v 4.1 90/04/28 22:42:14 syd Exp $ */
X/*******************************************************************************
X * The Elm Mail System - $Revision: 4.1 $ $State: Exp $
X *
X * Copyright (c) 1986, 1987 Dave Taylor
X * Copyright (c) 1988, 1989, 1990 USENET Community Trust
X *******************************************************************************
X * Bug reports, patches, comments, suggestions should be sent to:
X *
X * Syd Weinstein, Elm Coordinator
X * elm@DSI.COM dsinc!elm
X *
X *******************************************************************************
X * $Log: sysdefs.SH,v $
X * Revision 4.1 90/04/28 22:42:14 syd
X * checkin of Elm 2.3 as of Release PL0
X *
X *
X ******************************************************************************/
X
X/** System level, configurable, defines for the ELM mail system. **/
X
X
X#define FIND_DELTA 10 /* byte region where the binary search
X on the path alias file is fruitless
X (can't be within this boundary) */
X
X#define MAX_IN_WEEDLIST 150 /* max headers to weed out */
X
X#define MAX_HOPS 35 /* max hops in return addr to E)veryone */
X
X#define DEFAULT_BATCH_SUBJECT "$defbatsub"
X
X#define DEFAULT_DOMAIN "$mydomain" /* if mydomain file is missing */
X
X/** If you want to implement 'site hiding' in the mail, then you'll need to
X uncomment the following lines and set them to reasonable values. See
X the configuration guide for more details....(actually these are undoc-
X umented because they're fairly dangerous to use. Just ignore 'em and
X perhaps one day you'll find out what they do, ok?)
X**/
X
X/****************************************************************************
X
X#define SITE_HIDING
X#define HIDDEN_SITE_NAME "fake-machine-name"
X#define HIDDEN_SITE_USERS "/usr/mail/lists/hidden_site_users"
X
X****************************************************************************/
X
X#define system_text_file "$lib/aliases.text"
X#define system_hash_file "$lib/aliases.hash"
X#define system_data_file "$lib/aliases.data"
X
X#define ALIAS_TEXT ".elm/aliases.text"
X#define ALIAS_HASH ".elm/aliases.hash"
X#define ALIAS_DATA ".elm/aliases.data"
X
X#define pathfile "$pathalias"
X#define domains "$domains"
X#define hostdomfile "$lib/domain"
X
X/** where to put the output of the elm -d command... (in home dir) **/
X#define DEBUGFILE "ELM:debug.info"
X#define OLDEBUG "ELM:debug.last"
X
X#define default_temp "$tmpdir/"
X#define temp_file "snd."
X#define temp_form_file "form."
X#define temp_mbox "mbox."
X#define temp_print "print."
X#define temp_edit "elm-edit"
X#define temp_uuname "uuname."
X#define readmsg_file ".elm/readmsg"
X
X#define emacs_editor "$emacs"
X
X#define default_editor "$defeditor"
X#define mailhome "$maildir/"
X
X#define default_shell "$prefshell"
X#define default_pager "$pager"
X#define default_printout "$cat %s | $linepr"
X
X#define sendmail "$sendmail"
X#define smflags "-oi -oem" /* ignore dots and mail back errors */
X#define smflagsv "-oi -oem -v" /* Verbose voyuer mode */
X#define mailer "$mailer"
X
X#define mailx "$mailx"
X
X#define helphome "$lib"
X#define helpfile "elm-help"
X
X#define ELMRC_INFO "$lib/elmrc-info"
X
X#define elmrcfile ".elm/elmrc"
X#define old_elmrcfile ".elm/elmrc.old"
X#define mailheaders ".elm/elmheaders"
X#define dead_letter "Cancelled.mail"
X
X#define unedited_mail "emergency.mbox"
X
X#define newalias "newalias 1>&2 > /dev/null"
X#define readmsg "readmsg"
X
X#define remove_cmd "$rm -f" /* how to remove a file */
X#define cat "$cat" /* how to display files */
X#define sed_cmd "$sed" /* how to access sed */
X#define move_cmd "$mv" /* how to access sed */
X#define uuname "$uuname" /* how to get a uuname */
X
X#define MSG_SEPERATOR "\001\001\001\001\n" /* mmdf message seperator */
X!GROK!THIS!
SHAR_EOF
chmod 0444 hdrs/sysdefs.SH || echo "restore of hdrs/sysdefs.SH fails"
echo "x - extracting src/Makefile.SH (Text)"
sed 's/^X//' << 'SHAR_EOF' > src/Makefile.SH &&
Xcase $CONFIG in
X'')
X if test ! -f config.sh; then
X ln ../config.sh . || \
X ln ../../config.sh . || \
X ln ../../../config.sh . || \
X (echo "Can't find config.sh."; exit 1)
X fi
X . ./config.sh
X ;;
Xesac
Xcase "$0" in
X*/*) cd `expr X$0 : 'X\(.*\)/'` ;;
Xesac
X
Xecho "Extracting src/Makefile (with variable substitutions)"
Xcat >Makefile <<!GROK!THIS!
X# $Id: Makefile.SH,v 4.1 90/04/28 22:42:16 syd Exp $
X#
X# Makefile for the ELM mail program.
X#
X# Copyright (c) 1986, 1987 Dave Taylor
X# Copyright (c) 1988, 1989, 1990 USENET Community Trust
X#
X# Bug reports, patches, comments, suggestions should be sent to:
X#
X# Syd Weinstein - elm@DSI.COM
X# dsinc!elm
X#
X# $Log: Makefile.SH,v $
X# Revision 4.1 90/04/28 22:42:16 syd
X# checkin of Elm 2.3 as of Release PL0
X#
X#
X# Variables
X# Variables established by Configure
XCC = $cc
XCCFLAGS = $ccflags $xencf
XCHGRP = $chgrp
XCHMOD = $chmod
XCP = $cp
XDEST = $bin
XECHO = $echo
XLFLAGS = $ldflags $xenlf
XLIB = $lib
XLIB2 = $libs
XLIBS = $cryptlib $termlib $dbm
XLINT = $lint
XMAILGRP = $mailgrp
XMAILERMODE = $mailermode
XMV = $mv
XOPTIMIZE = $optimize
XRM = $rm -f
XTOUCH = $touch
X
X!GROK!THIS!
X
Xcat >>Makefile <<'!NO!SUBS!'
X
X# Variables you may want to manually edit
X# If you want debug logging then you'll
X# want to uncomment the following.
X#DEBUG = -DDEBUG
X
X# If you're on an ACSnet system (Australia) then
X# you'll want to uncomment the following.
X# DACSNET = -DACSNET
X
X# Other general variables
XBIN = ../bin
XCFLAGS = $(CCFLAGS) $(OPTIMIZE) -I$(INCLDIR) $(DEBUG) $(DACSNET)
XINCLDIR = ../hdrs
XLINTFLAGS = -I$(INCLDIR)
XSHELL = /bin/sh
X
X# Lists
XELM_SRC = addr_util.c \
X alias.c \
X aliasdb.c \
X aliaslib.c \
X args.c \
X bouncebk.c \
X builtin.c \
X calendar.c \
X conn_to.c \
X curses.c \
X date.c \
X delete.c \
X domains.c \
X edit.c \
X editmsg.c \
X elm.c \
X encode.c \
X errno.c \
X exitprog.c \
X expires.c \
X file.c \
X file_util.c \
X fileio.c \
X forms.c \
X hdrconfg.c \
X help.c \
X init.c \
X in_utils.c \
X leavembox.c \
X limit.c \
X mailmsg1.c \
X mailmsg2.c \
X mailtime.c \
X mkhdrs.c \
X newmbox.c \
X opt_utils.c \
X options.c \
X out_utils.c \
X pattern.c \
X pmalloc.c \
X quit.c \
X read_rc.c \
X remail.c \
X reply.c \
X returnadd.c \
X save_opts.c \
X savecopy.c \
X screen.c \
X showmsg.c \
X showmsg_c.c \
X signals.c \
X softkeys.c \
X sort.c \
X string2.c \
X strings.c \
X syscall.c \
X utils.c \
X validname.c
X
XELM_OBJ = addr_util.o \
X alias.o \
X aliasdb.o \
X aliaslib.o \
X args.o \
X bouncebk.o \
X builtin.o \
X calendar.o \
X conn_to.o \
X curses.o \
X date.o \
X delete.o \
X domains.o \
X edit.o \
X editmsg.o \
X elm.o \
X encode.o \
X errno.o \
X exitprog.o \
X expires.o \
X file.o \
X file_util.o \
X fileio.o \
X forms.o \
X hdrconfg.o \
X help.o \
X init.o \
X in_utils.o \
X leavembox.o \
X limit.o \
X mailmsg1.o \
X mailmsg2.o \
X mailtime.o \
X mkhdrs.o \
X newmbox.o \
X opt_utils.o \
X options.o \
X out_utils.o \
X pattern.o \
X pmalloc.o \
X quit.o \
X read_rc.o \
X remail.o \
X reply.o \
X returnadd.o \
X save_opts.o \
X savecopy.o \
X screen.o \
X showmsg.o \
X showmsg_c.o \
X signals.o \
X softkeys.o \
X sort.o \
X string2.o \
X strings.o \
X syscall.o \
X utils.o \
X validname.o
X
X# Standard targets
Xall: $(BIN)/elm
X
Xinstall: $(DEST)/elm
X
Xuninstall:
X $(RM) $(DEST)/elm
X
X# This is the only target that gets installed even if not out-of-date
X# with respect the files from which it is installed.
Xrmt-install: rmt-defined
X -$(MV) $(DEST)/elm $(DEST)/elm.old
X -$(RM) $(DEST)/elm.old
X $(CP) $(REMOTE)$(DEST)/elm $(DEST)/elm
X $(CHGRP) $(MAILGRP) $(DEST)/elm
X $(CHMOD) $(MAILERMODE) $(DEST)/elm
X
Xrmt-defined:
X @(if [ "$(REMOTE)" = "" ];\
X then\
X $(ECHO) "You need to define 'REMOTE' as the remote file system";\
X $(ECHO) "for this particular command. The easiest way to do this";\
X $(ECHO) "to type:";\
X $(ECHO) " make REMOTE=<remote file system> rmt-install";\
X exit 1;\
X fi);
X
Xlint:
X $(LINT) $(LINTFLAGS) $(ELM_SRC) > LINT.OUT
X
Xclean:
X $(RM) $(ELM_OBJ) $(BIN)/elm
X
X# Dependencies and rules
X# Dependencies of header files upon other header files they include
X.PRECIOUS: $(INCLDIR)/defs.h $(INCLDIR)/elm.h $(INCLDIR)/headers.h
X
X$(INCLDIR)/defs.h: $(INCLDIR)/../config.h $(INCLDIR)/sysdefs.h
X $(CHMOD) u+w $@
X $(TOUCH) $@
X
X$(INCLDIR)/elm.h: $(INCLDIR)/curses.h $(INCLDIR)/defs.h
X $(CHMOD) u+w $@
X $(TOUCH) $@
X
X$(INCLDIR)/headers.h: $(INCLDIR)/curses.h $(INCLDIR)/defs.h
X $(CHMOD) u+w $@
X $(TOUCH) $@
X
X# Dependencies of C object files
Xaddr_util.o: $(INCLDIR)/headers.h
Xalias.o: $(INCLDIR)/headers.h
Xaliasdb.o: $(INCLDIR)/headers.h
Xaliaslib.o: $(INCLDIR)/headers.h
Xargs.o: $(INCLDIR)/headers.h $(INCLDIR)/patchlevel.h
Xbouncebk.o: $(INCLDIR)/headers.h
Xbuiltin.o: $(INCLDIR)/headers.h
Xcalendar.o: $(INCLDIR)/headers.h
Xconn_to.o: $(INCLDIR)/headers.h
Xcurses.o: $(INCLDIR)/headers.h
Xdate.o: $(INCLDIR)/headers.h
Xdelete.o: $(INCLDIR)/headers.h
Xdomains.o: $(INCLDIR)/headers.h
Xedit.o: $(INCLDIR)/headers.h
Xeditmsg.o: $(INCLDIR)/headers.h
Xelm.o: $(INCLDIR)/elm.h
Xencode.o: $(INCLDIR)/headers.h
Xerrno.o: $(INCLDIR)/headers.h
Xexitprog.o: $(INCLDIR)/headers.h
Xexpires.o: $(INCLDIR)/headers.h
Xfile.o: $(INCLDIR)/headers.h
Xfile_util.o: $(INCLDIR)/headers.h
Xfileio.o: $(INCLDIR)/headers.h
Xforms.o: $(INCLDIR)/headers.h
Xhdrconfg.o: $(INCLDIR)/headers.h
Xhelp.o: $(INCLDIR)/headers.h
Xin_utils.o: $(INCLDIR)/headers.h
Xinit.o: $(INCLDIR)/headers.h $(INCLDIR)/patchlevel.h
Xleavembox.o: $(INCLDIR)/headers.h
Xlimit.o: $(INCLDIR)/headers.h
Xmailmsg1.o: $(INCLDIR)/headers.h
Xmailmsg2.o: $(INCLDIR)/headers.h
Xmailtime.o: $(INCLDIR)/headers.h
Xmkhdrs.o: $(INCLDIR)/headers.h
Xnewmbox.o: $(INCLDIR)/headers.h
Xopt_utils.o: $(INCLDIR)/headers.h
Xoptions.o: $(INCLDIR)/headers.h
Xout_utils.o: $(INCLDIR)/headers.h
Xpattern.o: $(INCLDIR)/headers.h
Xpmalloc.o: $(INCLDIR)/defs.h
Xquit.o: $(INCLDIR)/headers.h
Xread_rc.o: $(INCLDIR)/headers.h
Xremail.o: $(INCLDIR)/headers.h
Xreply.o: $(INCLDIR)/headers.h
Xreturnadd.o: $(INCLDIR)/headers.h
Xsave_opts.o: $(INCLDIR)/save_opts.h $(INCLDIR)/headers.h
Xsavecopy.o: $(INCLDIR)/headers.h
Xscreen.o: $(INCLDIR)/headers.h
Xshowmsg.o: $(INCLDIR)/headers.h
Xshowmsg_c.o: $(INCLDIR)/headers.h
Xsignals.o: $(INCLDIR)/headers.h
Xsoftkeys.o: $(INCLDIR)/headers.h
Xsort.o: $(INCLDIR)/headers.h
Xstring2.o: $(INCLDIR)/headers.h
Xstrings.o: $(INCLDIR)/headers.h
Xsyscall.o: $(INCLDIR)/headers.h
Xutils.o: $(INCLDIR)/headers.h
Xvalidname.o: $(INCLDIR)/defs.h
X
X# Dependencies and rules for compiling C programs
X$(BIN)/elm: $& $(ELM_OBJ)
X $(CC) $(LFLAGS) -o $@ $(ELM_OBJ) $(LIBS) $(LIB2)
X
X# Dependencies and rules for installing C programs
X$(DEST)/elm: $(BIN)/elm
X -$(MV) $@ $@.old
X -$(RM) $@.old
X $(CP) $(BIN)/elm $@
X $(CHGRP) $(MAILGRP) $@
X $(CHMOD) $(MAILERMODE) $@
X
X!NO!SUBS!
SHAR_EOF
chmod 0444 src/Makefile.SH || echo "restore of src/Makefile.SH fails"
echo "x - extracting src/addr_util.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > src/addr_util.c &&
X
Xstatic char rcsid[] = "@(#)$Id: addr_util.c,v 4.1 90/04/28 22:42:21 syd Exp $";
X
X/*******************************************************************************
X * The Elm Mail System - $Revision: 4.1 $ $State: Exp $
X *
X * Copyright (c) 1986, 1987 Dave Taylor
X * Copyright (c) 1988, 1989, 1990 USENET Community Trust
X *******************************************************************************
X * Bug reports, patches, comments, suggestions should be sent to:
X *
X * Syd Weinstein, Elm Coordinator
X * elm@DSI.COM dsinc!elm
X *
X *******************************************************************************
X * $Log: addr_util.c,v $
X * Revision 4.1 90/04/28 22:42:21 syd
X * checkin of Elm 2.3 as of Release PL0
X *
X *
X ******************************************************************************/
X
X/** This file contains addressing utilities
X
X**/
X
X#include "headers.h"
X
X#include <sys/types.h>
X#include <sys/stat.h>
X#ifdef PWDINSYS
X# include <sys/pwd.h>
X#else
X# include <pwd.h>
X#endif
X
X#include <ctype.h>
X
X#ifdef BSD
X#undef tolower
X#undef toupper
X#endif
X
Xchar *get_alias_address(), *get_token();
Xchar *strtok(), *strcpy(), *strcat(), *strncpy(), *index(), *rindex();
X
X
X#define SKIP_WS(p) while (isspace(*p)) p++
X#define SKIP_ALPHA(p) while (isalpha(*p)) p++
X#define SKIP_DIGITS(p) while (isdigit(*p)) p++
X
Xstatic char *day_name[8] = {
X "sun", "mon", "tue", "wed", "thu", "fri", "sat", 0
X};
X
Xstatic char *month_name[13] = {
X "jan", "feb", "mar", "apr",
X "may", "jun", "jul", "aug",
X "sep", "oct", "nov", "dec", 0
X};
X
Xstatic int month_len[12] = {
X 31, 28, 31, 30, 31, 30, 31,
X 31, 30, 31, 30, 31 };
X
X/* The following time zones are taken from a variety of sources. They
X * are by no means exhaustive, but seem to include most of those
X * in common usage. A comprehensive list is impossible, since the same
X * abbreviation is sometimes used to mean different things in different
X * parts of the world.
X */
Xstatic struct tzone {
X char *str;
X int offset; /* offset, in minutes, EAST of GMT */
X} tzone_info[] = {
X /* the following are from rfc822 */
X "ut", 0, "gmt", 0,
X "est", -5*60, "edt", -4*60,
X "cst", -6*60, "cdt", -5*60,
X "mst", -7*60, "mdt", -6*60,
X "pst", -8*60, "pdt", -7*60,
X "z", 0, /* zulu time (the rest of the military codes are bogus) */
X
X /* these are also popular in Europe */
X "wet", 0*60, "wet dst", 1*60, /* western european */
X "met", 1*60, "met dst", 2*60, /* middle european */
X "eet", 2*60, "eet dst", 3*60, /* eastern european */
X "bst", 1*60, /* ??? british summer time (=+0100) */
X
X /* ... and Canada */
X "ast", -4*60, "adt", -3*60, /* atlantic */
X "nst", -3*60-30, "ndt", -2*60-30, /* newfoundland */
X "yst", -9*60, "ydt", -8*60, /* yukon */
X "hst", -10*60, /* hawaii (not really canada) */
X
X /* ... and Asia */
X "jst", 9*60, /* japan */
X "sst", 8*60, /* singapore */
X
X /* ... and the South Pacific */
X "nzst", 12*60, "nzdt", 13*60, /* new zealand */
X "wst", 8*60, "wdt", 9*60, /* western australia */
X /* there's also central and eastern australia, but they insist on using
X * cst, est, etc., which would be indistinguishable for the us zones */
X (char *) 0, 0
X};
X
Xchar *
Xgcos_name(gcos_field, logname)
Xchar *logname, *gcos_field;
X{
X /** Return the full name found in a passwd file gcos field **/
X
X#ifdef BERKNAMES
X
X static char fullname[SLEN];
X register char *fncp, *gcoscp, *lncp, *end;
X
X
X /* full name is all chars up to first ',' (or whole gcos, if no ',') */
X /* replace any & with logname in upper case */
X
X for(fncp = fullname, gcoscp= gcos_field, end = fullname + SLEN - 1;
X (*gcoscp != ',' && *gcoscp != '\0' && fncp != end);
X gcoscp++) {
X
X if(*gcoscp == '&') {
X for(lncp = logname; *lncp; fncp++, lncp++)
X *fncp = toupper(*lncp);
X } else {
X *fncp++ = *gcoscp;
X }
X }
X
X *fncp = '\0';
X return(fullname);
X#else
X#ifdef USGNAMES
X
X char *firstcp, *lastcp;
X
X /* The last character of the full name is the one preceding the first
X * '('. If there is no '(', then the full name ends at the end of the
X * gcos field.
X */
X if(lastcp = index(gcos_field, '('))
X *lastcp = '\0';
X
X /* The first character of the full name is the one following the
X * last '-' before that ending character. NOTE: that's why we
X * establish the ending character first!
X * If there is no '-' before the ending character, then the fullname
X * begins at the beginning of the gcos field.
X */
X if(firstcp = rindex(gcos_field, '-'))
X firstcp++;
X else
X firstcp = gcos_field;
X
X return(firstcp);
X
X#else
X /* use full gcos field */
X return(gcos_field);
X#endif
X#endif
X}
X
Xchar *
Xget_full_name(logname)
Xchar *logname;
X{
X /* return a pointer to the full user name for the passed logname
X * or NULL if cannot be found
X * If PASSNAMES get it from the gcos field, otherwise get it
X * from ~/.fullname.
X */
X
X#ifndef PASSNAMES
X FILE *fp;
X char fullnamefile[SLEN];
X#endif
X static char fullname[SLEN];
X struct passwd *getpwnam(), *pass;
X
X if((pass = getpwnam(logname)) == NULL)
X return(NULL);
X#ifdef PASSNAMES /* get full_username from gcos field */
X strcpy(fullname, gcos_name(pass->pw_gecos, logname));
X#else /* get full_username from ~/.fullname file */
X sprintf(fullnamefile, "%s/.fullname", pass->pw_dir);
SHAR_EOF
echo "End of part 10"
echo "File src/addr_util.c is continued in part 11"
echo "11" > s2_seq_.tmp
exit 0
exit 0 # Just in case...
--
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.rsalz@bbn.com (Rich Salz) (05/31/90)
Submitted-by: Syd Weinstein <syd@dsinc.dsi.com>
Posting-number: Volume 22, Issue 68
Archive-name: elm2.3/part09
#!/bin/sh
# this is part 9 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file filter/filter.c continued
#
CurArch=9
if test ! -r s2_seq_.tmp
then echo "Please unpack part 1 first!"
exit 1; fi
( read Scheck
if test "$Scheck" != $CurArch
then echo "Please unpack part $Scheck next!"
exit 1;
else exit 0; fi
) < s2_seq_.tmp || exit 1
echo "x - Continuing file filter/filter.c"
sed 's/^X//' << 'SHAR_EOF' >> filter/filter.c
X#include "defs.h"
X#ifdef I_TIME
X# include <time.h>
X#endif
X#ifdef I_SYSTIME
X# include <sys/time.h>
X#endif
X#include <fcntl.h>
X
X#define MAIN_ROUTINE /* for the filter.h file, of course! */
X#include "filter.h"
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X extern char *optarg;
X FILE *fd; /* for output to temp file! */
X struct passwd *passwd_entry;
X#ifndef _POSIX_SOURCE
X struct passwd *getpwuid(); /* for /etc/passwd */
X#endif
X char filename[SLEN], /* name of the temp file */
X buffer[MAX_LINE_LEN]; /* input buffer space */
X int in_header = TRUE, /* for header parsing */
X in_to = FALSE, /* are we on 'n' line To: ? */
X summary = FALSE, /* a summary is requested? */
X c; /* var for getopt routine */
X
X /* first off, let's get the info from /etc/passwd */
X
X if ((passwd_entry = getpwuid(getuid())) == NULL)
X leave("Cannot get password entry for this uid!");
X
X strcpy(home, passwd_entry->pw_dir);
X strcpy(username, passwd_entry->pw_name);
X outfname[0] = to[0] = '\0'; /* nothing read in yet, right? */
X
X#ifdef HOSTCOMPILED
X strncpy(hostname, HOSTNAME, sizeof(hostname));
X#else
X gethostname(hostname, sizeof(hostname));
X#endif
X
X /* now parse the starting arguments... */
X
X while ((c = getopt(argc, argv, "clno:rSsv")) != EOF) {
X switch (c) {
X case 'c' : clear_logs = TRUE; break;
X case 'l' : log_actions_only = TRUE; break;
X case 'o' : strcpy(outfname, optarg); break;
X case 'r' : printing_rules = TRUE; break;
X
X case 's' : summary = TRUE; break;
X case 'S' : long_summary = TRUE; break;
X
X case 'n' : show_only = TRUE; break;
X case 'v' : verbose = TRUE; break;
X case '?' : fprintf(stderr,
X "Usage: | filter [-nrv]\n or: filter [-c] -[s|S]\n");
X exit(1);
X }
X }
X
X if (c < 0) {
X }
X
X /* let's open our outfd logfile as needed... */
X
X if (outfname[0] == '\0') /* default is stdout */
X outfd = stdout;
X else
X if ((outfd = fopen(outfname, "a")) == NULL) {
X if (isatty(fileno(stderr)))
X fprintf(stderr,"filter (%s): couldn't open log file %s\n",
X username, outfname);
X }
X
X if (summary || long_summary) {
X if (get_filter_rules() == -1) {
X exit(1);
X if (outfd != NULL) fclose(outfd);
X }
X show_summary();
X if (outfd != NULL) fclose(outfd);
X exit(0);
X }
X
X if (printing_rules) {
X if (get_filter_rules() == -1)
X fprintf(outfd,"filter (%s): Couldn't get rules!\n", username);
X else
X print_rules();
X if (outfd != NULL) fclose(outfd);
X exit(0);
X }
X
X /* next, create the tempfile and save the incoming message */
X
X sprintf(filename, "%s.%d", filter_temp, getpid());
X
X if ((fd = fopen(filename,"w")) == NULL)
X leave("Cannot open temporary file!");
X
X while (fgets(buffer, MAX_LINE_LEN, stdin) != NULL) {
X
X remove_return(buffer);
X
X if (in_header) {
X
X if (! whitespace(buffer[0]))
X in_to = FALSE;
X
X if (the_same(buffer, "From "))
X save_from(buffer);
X else if (the_same(buffer, "Subject:"))
X save_subject(buffer);
X else if (the_same(buffer, "To:") || the_same(buffer, "Cc:")) {
X in_to++;
X save_to(buffer);
X }
X else if (the_same(buffer, "X-Filtered-By:"))
X already_been_forwarded++; /* could be a loop here! */
X#ifdef USE_EMBEDDED_ADDRESSES
X else if (the_same(buffer, "From:"))
X save_embedded_address(buffer, "From:");
X else if (the_same(buffer, "Reply-To:"))
X save_embedded_address(buffer, "Reply-To:");
X#endif
X else if (strlen(buffer) < 2)
X in_header = 0;
X else if (whitespace(buffer[0]) && in_to)
X strcat(to, buffer);
X }
X
X fprintf(fd, "%s\n", buffer); /* and save it regardless! */
X fflush(fd);
X lines++;
X }
X
X fclose(fd);
X
X /** next let's see if the user HAS a filter file, and if so what's in
X it (and so on) **/
X
X if (get_filter_rules() == -1)
X mail_message(username);
X else {
X switch (action_from_ruleset()) {
X
X case DELETE_MSG : if (verbose && outfd != NULL)
X fprintf(outfd, "filter (%s): Message deleted\n",
X username);
X log(DELETE_MSG); break;
X
X case SAVE : if (save_message(rules[rule_choosen].argument2)) {
X mail_message(username);
X log(FAILED_SAVE);
X }
X else
X log(SAVE); break;
X
X case SAVECC : if (save_message(rules[rule_choosen].argument2))
X log(FAILED_SAVE);
X else
X log(SAVECC);
X mail_message(username); break;
X
X case FORWARD: mail_message(rules[rule_choosen].argument2);
X log(FORWARD); break;
X
X case EXEC : execute(rules[rule_choosen].argument2);
X log(EXEC); break;
X
X case LEAVE : mail_message(username);
X log(LEAVE); break;
X }
X }
X
X (void) unlink(filename); /* remove the temp file, please! */
X if (outfd != NULL) fclose(outfd);
X exit(0);
X}
X
Xsave_from(buffer)
Xchar *buffer;
X{
X /** save the SECOND word of this string as FROM **/
X
X register char *f = from;
X
X while (*buffer != ' ')
X buffer++; /* get to word */
X
X for (buffer++; *buffer != ' ' && *buffer; buffer++, f++)
X *f = *buffer; /* copy it and */
X
X *f = '\0'; /* Null terminate! */
X}
X
Xsave_subject(buffer)
Xchar *buffer;
X{
X /** save all but the word "Subject:" for the subject **/
X
X register int skip = 8; /* skip "Subject:" initially */
X
X while (buffer[skip] == ' ') skip++;
X
X strcpy(subject, (char *) buffer + skip);
X}
X
Xsave_to(buffer)
Xchar *buffer;
X{
X /** save all but the word "To:" or "Cc:" for the to list **/
X
X register int skip = 3; /* skip "To:" or "Cc:" initially */
X
X while (buffer[skip] == ' ') skip++;
X
X strcat(to, (char *) buffer + skip);
X}
X
X#ifdef USE_EMBEDDED_ADDRESSES
X
Xsave_embedded_address(buffer, fieldname)
Xchar *buffer, *fieldname;
X{
X /** this will replace the 'from' address with the one given,
X unless the address is from a 'reply-to' field (which overrides
X the From: field). The buffer given to this routine can have one
X of three forms:
X fieldname: username <address>
X fieldname: address (username)
X fieldname: address
X **/
X
X static int processed_a_reply_to = 0;
X char address[LONG_STRING];
X register int i, j = 0;
X
X /** first let's extract the address from this line.. **/
X
X if (buffer[strlen(buffer)-1] == '>') { /* case #1 */
X for (i=strlen(buffer)-1; buffer[i] != '<' && i > 0; i--)
X /* nothing - just move backwards .. */ ;
X i++; /* skip the leading '<' symbol */
X while (buffer[i] != '>')
X address[j++] = buffer[i++];
X address[j] = '\0';
X }
X else { /* get past "from:" and copy until white space or paren hit */
X for (i=strlen(fieldname); whitespace(buffer[i]); i++)
X /* skip past that... */ ;
X while (buffer[i] != '(' && ! whitespace(buffer[i]) && buffer[i]!='\0')
X address[j++] = buffer[i++];
X address[j] = '\0';
X }
X
X /** now let's see if we should overwrite the existing from address
X with this one or not.. **/
X
X if (processed_a_reply_to)
X return; /* forget it! */
X
X strcpy(from, address); /* replaced!! */
X
X if (strcmp(fieldname, "Reply-To:") == 0)
X processed_a_reply_to++;
X}
X#endif
SHAR_EOF
echo "File filter/filter.c is complete"
chmod 0444 filter/filter.c || echo "restore of filter/filter.c fails"
echo "x - extracting filter/lock.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > filter/lock.c &&
X
Xstatic char rcsid[] ="@(#)$Id: lock.c,v 4.1 90/04/28 22:41:57 syd Exp $";
X
X/*******************************************************************************
X * The Elm Mail System - $Revision: 4.1 $ $State: Exp $
X *
X * Copyright (c) 1986, 1987 Dave Taylor
X * Copyright (c) 1988, 1989, 1990 USENET Community Trust
X *******************************************************************************
X * Bug reports, patches, comments, suggestions should be sent to:
X *
X * Syd Weinstein - elm@DSI.COM
X * dsinc!elm
X *
X *******************************************************************************
X * $Log: lock.c,v $
X * Revision 4.1 90/04/28 22:41:57 syd
X * checkin of Elm 2.3 as of Release PL0
X *
X *
X ******************************************************************************/
X
X
X/** The lock() and unlock() routines herein duplicate exactly the
X equivalent routines in the Elm Mail System, and should also be
X compatible with sendmail, rmail, etc etc.
X
X
X**/
X
X#include <stdio.h>
X#include <fcntl.h>
X#include <errno.h>
X#include "defs.h"
X#include "filter.h"
X
Xstatic int we_locked_it;
Xstatic char lockfile[SLEN];
X
X#ifdef LOCK_BY_FLOCK
X#include <sys/types.h>
X#include <sys/file.h>
Xstatic flock_fd = -1;
Xstatic char flock_name[SLEN];
X#endif
X
Xextern int errno;
X
Xint
Xlock()
X{
X /** This routine will return 1 if we could lock the mailfile,
X zero otherwise.
X **/
X
X int attempts = 0, ret;
X
X#ifndef LOCK_FLOCK_ONLY /* { !LOCK_FLOCK_ONLY */
X sprintf(lockfile, "%s%s.lock", mailhome, username);
X#ifdef PIDCHECK
X /** first, try to read the lock file, and if possible, check the pid.
X If we can validate that the pid is no longer active, then remove
X the lock file.
X **/
X if((ret=open(lockfile,O_RDONLY)) != -1) {
X char pid_buffer[SHORT];
X if (read(ret, pid_buffer, SHORT) > 0) {
X attempts = atoi(pid_buffer);
X if (attempts) {
X if (kill(attempts, 0)) {
X close(ret);
X if (unlink(lockfile) != 0)
X return(1);
X }
X }
X }
X attempts = 0;
X }
X#endif
X
X while ((ret = open(lockfile, O_WRONLY | O_CREAT | O_EXCL, 0444)) < 0
X && attempts++ < 10) {
X sleep(3); /* wait three seconds each pass, okay?? */
X }
X
X if (ret >= 0) {
X we_locked_it++;
X close(ret); /* no need to keep it open! */
X ret = 1;
X } else {
X ret = 0;
X }
X
X#endif /* } !LOCK_FLOCK_ONLY */
X#ifdef LOCK_BY_FLOCK /* { LOCK_BY_FLOCK */
X (void)sprintf(flock_name,"%s%s",mailhome,username);
X flock_fd = open(flock_name,O_RDONLY);
X if ( flock_fd >= 0 )
X for (attempts = 0; attempts < 10; attempts++) {
X if ( (ret = flock(flock_fd,LOCK_NB|LOCK_EX)) != -1 )
X break;
X if ( errno != EWOULDBLOCK && errno != EAGAIN )
X break;
X (void)sleep((unsigned)3);
X }
X if ( flock_fd >= 0 && ret == 0 ) {
X we_locked_it++;
X ret = 1;
X } else {
X we_locked_it = 0;
X if ( lockfile[0] ) {
X (void)unlink(lockfile);
X lockfile[0] = 0;
X }
X if ( flock_fd >= 0 ) {
X (void)close(flock_fd);
X flock_fd = -1;
X }
X ret = 0;
X }
X#endif
X return(ret);
X}
X
Xunlock()
X{
X /** this routine will remove the lock file, but only if we were
X the people that locked it in the first place... **/
X
X#ifndef LOCK_FLOCK_ONLY
X if (we_locked_it && lockfile[0]) {
X unlink(lockfile); /* blamo! */
X lockfile[0] = 0;
X }
X#endif
X#ifdef LOCK_BY_FLOCK
X if (we_locked_it && flock_fd >= 0) {
X (void)close(flock_fd);
X flock_fd = -1;
X }
X#endif
X we_locked_it = 0;
X}
SHAR_EOF
chmod 0444 filter/lock.c || echo "restore of filter/lock.c fails"
echo "x - extracting filter/parse.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > filter/parse.c &&
X
Xstatic char rcsid[] ="@(#)$Id: parse.c,v 4.1 90/04/28 22:41:58 syd Exp $";
X
X/*******************************************************************************
X * The Elm Mail System - $Revision: 4.1 $ $State: Exp $
X *
X * Copyright (c) 1986, 1987 Dave Taylor
X * Copyright (c) 1988, 1989, 1990 USENET Community Trust
X *******************************************************************************
X * Bug reports, patches, comments, suggestions should be sent to:
X *
X * Syd Weinstein - elm@DSI.COM
X * dsinc!elm
X *
X *******************************************************************************
X * $Log: parse.c,v $
X * Revision 4.1 90/04/28 22:41:58 syd
X * checkin of Elm 2.3 as of Release PL0
X *
X *
X ******************************************************************************/
X
X
X/** This is the parser for the filter program. It accepts a wide variety of
X constructs, building the ruleset table as it goes along. Check the
X data structure in filter.h for more information on how the rules are
X stored. The parser is a cunning state-table based program.
X
X**/
X
X#include <stdio.h>
X#include <ctype.h>
X
X#include "defs.h"
X#include "filter.h"
X
X#define NONE 0
X#define AND 10
X
X#define NEXT_CONDITION 0
X#define GETTING_OP 1
X#define READING_ARGUMENT 2
X#define READING_ACTION 3
X#define ACTION_ARGUMENT 4
X
Xchar *strtok(), *whatname(), *actionname();
X
Xint
Xget_filter_rules()
X{
X /** Given the users home directory, open and parse their rules table,
X building the data structure as we go along.
X returns -1 if we hit an error of any sort...
X **/
X
X FILE *fd; /* the file descriptor */
X char buffer[SLEN], /* fd reading buffer */
X *str, /* ptr to read string */
X *word, /* ptr to 'token' */
X filename[SLEN], /* the name of the ruleset */
X action_argument[SLEN], /* action arg, per rule */
X cond_argument[SLEN]; /* cond arg, per condition */
X int not_condition = FALSE, /* are we in a "not" ?? */
X type=NONE, /* what TYPE of condition? */
X lasttype, /* and the previous TYPE? */
X state = NEXT_CONDITION, /* the current state */
X in_single, in_double, /* for handling spaces. */
X i, /* misc integer for loops */
X relop = NONE, /* relational operator */
X action, /* the current action type */
X buflen, /* the length of buffer */
X line = 0; /* line number we're on */
X
X struct condition_rec *cond, *newcond;
X
X sprintf(filename,"%s/%s", home, filterfile);
X
X if ((fd = fopen(filename,"r")) == NULL) {
X if (outfd != NULL)
X fprintf(outfd,"filter (%s): Couldn't read user filter rules file!\n",
X username);
X return(-1);
X }
X
X cond_argument[0] = action_argument[0] = '\0';
X
X /* Now, for each line... **/
X
X if ((cond = (struct condition_rec *)
X malloc(sizeof(struct condition_rec))) == NULL) {
X if (outfd != NULL)
X fprintf(outfd,"filter (%s): couldn't malloc first condition rec!\n",
X username);
X return(-1);
X }
X
X rules[total_rules].condition = cond; /* hooked in! */
X
X while (fgets(buffer, SLEN, fd) != NULL) {
X line++;
X
X if (buffer[0] == '#' || (buflen = strlen(buffer)) < 2)
X continue; /* nothing to look at! */
X
X in_single = in_double = 0;
X
X for (i=0; i < buflen; i++) {
X if (buffer[i] == '"')
X in_double = ! in_double;
X else if (buffer[i] == '\'')
X in_single = ! in_single;
X if ((in_double || in_single) && buffer[i] == ' ')
X buffer[i] = '_';
X }
X
X lasttype = type;
X type = NONE;
X str = (char *) buffer;
X
X /** Three pieces to this loop - get the `field', the 'relop' (if
X there) then, if needed, get the argument to check against (not
X needed for errors or the AND, of course)
X **/
X
X while ((word = strtok(str, " ()[]:\t\n")) != NULL) {
X
X str = (char *) NULL; /* we can start stomping! */
X
X lowercase(word);
X
X if (strcmp(word, "if") == 0) { /* only ONE 'if' allowed */
X if ((word = strtok(str, " ()[]:\t\n")) == NULL) /* NEXT! */
X continue;
X lowercase(word);
X }
X
X if (state == NEXT_CONDITION) {
X lasttype = type;
X type = NONE;
X
X if (the_same(word, "not") || the_same(word, "!")) {
X not_condition = TRUE;
X if ((word = strtok(str, " ()[]'\"\t\n")) == NULL)
X continue;
X }
X
X if (the_same(word, "from")) type = FROM;
X else if (the_same(word, "to")) type = TO;
X else if (the_same(word, "subject")) type = SUBJECT;
X else if (the_same(word, "lines")) type = LINES;
X else if (the_same(word, "contains")) type = CONTAINS;
X else if (the_same(word, "and") ||
X the_same(word, "&&")) type = AND;
X
X else if (the_same(word,"?") || the_same(word, "then") ||
X the_same(word, "always")) {
X
X /** shove THIS puppy into the structure and let's continue! **/
X
X if (lasttype == AND) {
X if (outfd != NULL)
X fprintf(outfd,
X "filter (%s): Error reading line %d of rules - badly placed \"and\"\n",
X username, line);
X return(-1);
X }
X
X if (the_same(word, "always"))
X cond->matchwhat = ALWAYS; /* so it's a hack... */
X else
X cond->matchwhat = lasttype;
X
X if (relop == NONE) relop = EQ; /* otherwise can't do -relop */
X cond->relation = (not_condition? - (relop) : relop);
X
X for (i=strlen(cond_argument); --i >= 0;)
X if (cond_argument[i] == '_') cond_argument[i] = ' ';
X
X strcpy(cond->argument1, cond_argument);
X if ((newcond = (struct condition_rec *)
X malloc(sizeof(struct condition_rec))) == NULL) {
X if (outfd != NULL)
X fprintf(outfd,
X "filter (%s): Couldn't malloc new cond rec!!\n",
X username);
X return(-1);
X }
X cond->next = NULL;
X
X relop = EQ; /* default relational condition */
X
X state = READING_ACTION;
X if ((word = strtok(str, " ()[]'\"\t\n")) == NULL)
X continue;
X goto get_outta_loop;
X }
X
X if (type == NONE) {
X if (outfd != NULL)
X fprintf(outfd,
X "filter (%s): Error reading line %d of rules - field \"%s\" unknown!\n",
X username, line, word);
X return(-1);
X }
X
X if (type == AND) {
X
X /** shove THIS puppy into the structure and let's continue! **/
X
X cond->matchwhat = lasttype;
X cond->relation = (not_condition? - (relop) : relop);
X strcpy(cond->argument1, cond_argument);
X if ((newcond = (struct condition_rec *)
X malloc(sizeof(struct condition_rec))) == NULL) {
X if (outfd != NULL)
X fprintf(outfd,
X "filter (%s): Couldn't malloc new cond rec!!\n",
X username);
X return(-1);
X }
X cond->next = newcond;
X cond = newcond;
X cond->next = NULL;
X
X not_condition = FALSE;
X state = NEXT_CONDITION;
X }
X else {
X state = GETTING_OP;
X }
X }
X
Xget_outta_loop: /* jump out when we change state, if needed */
X
X if (state == GETTING_OP) {
X
X if ((word = strtok(str, " ()[]'\"\t\n")) == NULL)
X continue;
X
X lowercase(word);
X
X relop = NONE;
X
X if (the_same(word, "=") || the_same(word, "in") ||
X the_same(word, "contains")) {
X state = READING_ARGUMENT;
X relop = EQ;
X }
X else {
X if (the_same(word, "<=")) relop = LE;
X else if (the_same(word, ">=")) relop = GE;
X else if (the_same(word, ">")) relop = GT;
X else if (the_same(word, "<>")||
X the_same(word, "!=")) relop = NE;
X else if (the_same(word, "<")) relop = LT;
X
X /* maybe there isn't a relop at all!! */
X
X state=READING_ARGUMENT;
X
X }
X }
X
X if (state == READING_ARGUMENT) {
X if (relop != NONE) {
X if ((word = strtok(str, " ()[]'\"\t\n")) == NULL)
X continue;
X }
X for (i=strlen(word); --i>=0;)
X if (word[i] == '_') word[i] = ' ';
X
X strcpy(cond_argument, word);
X state = NEXT_CONDITION;
X }
X
X if (state == READING_ACTION) {
X action = NONE;
X
X not_condition = FALSE;
X
X if (the_same(word, "delete")) action = DELETE_MSG;
X else if (the_same(word, "savec")) action = SAVECC;
X else if (the_same(word, "save")) action = SAVE;
X else if (the_same(word, "forward")) action = FORWARD;
X else if (the_same(word, "exec")) action = EXEC;
X else if (the_same(word, "leave")) action = LEAVE;
X else {
X if (outfd != NULL)
X fprintf(outfd,
X "filter (%s): Error on line %d of rules - action \"%s\" unknown\n",
X username, line, word);
X }
X
X if (action == DELETE_MSG || action == LEAVE) {
X /** add this to the rules section and alloc next... **/
X
X rules[total_rules].action = action;
X rules[total_rules].argument2[0] = '\0'; /* nothing! */
X total_rules++;
X
X if ((cond = (struct condition_rec *)
X malloc(sizeof(struct condition_rec))) == NULL) {
X if (outfd != NULL)
X fprintf(outfd,
X "filter (%s): couldn't malloc first condition rec!\n",
X username);
X return(-1);
X }
X
X rules[total_rules].condition = cond; /* hooked in! */
X state = NEXT_CONDITION;
X }
X else {
X state = ACTION_ARGUMENT;
X }
X
X if ((word = strtok(str, " ()[]'\"\t\n")) == NULL)
X continue;
X
X }
X
X if (state == ACTION_ARGUMENT) {
X strcpy(action_argument, word);
X
X /** add this to the rules section and alloc next... **/
X
X rules[total_rules].action = action;
X expand_macros(action_argument, rules[total_rules].argument2,line,
X printing_rules);
X total_rules++;
X
X if ((cond = (struct condition_rec *)
X malloc(sizeof(struct condition_rec))) == NULL) {
X if (outfd != NULL)
X fprintf(outfd,
X "filter (%s): couldn't malloc first condition rec!\n",
X username);
X return(-1);
X }
X
X rules[total_rules].condition = cond; /* hooked in! */
X
X state = NEXT_CONDITION;
X if ((word = strtok(str, " ()[]'\"\t\n")) == NULL)
X continue;
X }
X }
X }
X
X return(0);
X}
SHAR_EOF
chmod 0444 filter/parse.c || echo "restore of filter/parse.c fails"
echo "x - extracting filter/rules.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > filter/rules.c &&
X
Xstatic char rcsid[] ="@(#)$Id: rules.c,v 4.1 90/04/28 22:42:00 syd Exp $";
X
X/*******************************************************************************
X * The Elm Mail System - $Revision: 4.1 $ $State: Exp $
X *
X * Copyright (c) 1986, 1987 Dave Taylor
X * Copyright (c) 1988, 1989, 1990 USENET Community Trust
X *******************************************************************************
X * Bug reports, patches, comments, suggestions should be sent to:
X *
X * Syd Weinstein - elm@DSI.COM
X * dsinc!elm
X *
X *******************************************************************************
X * $Log: rules.c,v $
X * Revision 4.1 90/04/28 22:42:00 syd
X * checkin of Elm 2.3 as of Release PL0
X *
X *
X ******************************************************************************/
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**/
X
X#include <stdio.h>
X#include <pwd.h>
X#include <ctype.h>
X#include "defs.h"
X#ifdef I_TIME
X# include <time.h>
X#endif
X#ifdef I_SYSTIME
X# include <sys/time.h>
X#endif
X#include <fcntl.h>
X
X#include "filter.h"
X
Xchar *listrule();
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 iindex = 0, not, relation, try_next_rule, x;
X struct condition_rec *cond;
X
X while (iindex < total_rules) {
X cond = rules[iindex].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: if (outfd != NULL) fprintf(outfd,
X "filter (%s): Error: rules based on 'contains' are not implemented!\n",
X username);
X if (outfd != NULL) fclose(outfd);
X exit(0);
X
X case ALWAYS: not = FALSE; x = TRUE; break;
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 = iindex;
X return(rules[rule_choosen].action);
X }
X iindex++;
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, display)
Xchar *word, *buffer;
Xint line, display;
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. If "display" is set then
X instead it puts "<day-of-month>" etc. etc. in the output.
X **/
X
X#ifndef _POSIX_SOURCE
X struct tm *localtime();
X long time();
X#endif
X struct tm *timerec;
X long thetime;
X register int i, j=0, gotten_time = 0, reading_a_percent_sign = 0, len;
X
X for (i = 0, len = strlen(word); i < len; 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 if (display)
X strcat(buffer, "<return-address>");
X else
X strcat(buffer, from);
X j = strlen(buffer);
X break;
X
X case 's' : buffer[j] = '\0';
X if (display)
X strcat(buffer, "<subject>");
X else {
X strcat(buffer, "\"");
X strcat(buffer, subject);
X strcat(buffer, "\"");
X }
X j = strlen(buffer);
X break;
X
X case 'S' : buffer[j] = '\0';
X if (display)
X strcat(buffer, "<Re: subject>");
X else {
X if (! the_same(subject, "Re:"))
X strcat(buffer, "\"Re: ");
X strcat(buffer, subject);
X strcat(buffer, "\"");
X }
X j = strlen(buffer);
X break;
X
X case 'd' : get_the_time(); buffer[j] = '\0';
X if (display)
X strcat(buffer, "<day-of-month>");
X else
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 if (display)
X strcat(buffer, "<day-of-week>");
X else
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 if (display)
X strcat(buffer, "<month>");
X else
X strcat(buffer, itoa(timerec->tm_mon+1,FALSE));
X j = strlen(buffer);
X break;
X
X case 'y' : get_the_time(); buffer[j] = '\0';
X if (display)
X strcat(buffer, "<year>");
X else
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 if (display)
X strcat(buffer, "<hour>");
X else
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 if (display)
X strcat(buffer, "<time>");
X else {
X strcat(buffer, itoa(timerec->tm_hour,FALSE));
X strcat(buffer, ":");
X strcat(buffer, itoa(timerec->tm_min,TRUE));
X }
X j = strlen(buffer);
X break;
X
X default : if (outfd != NULL) fprintf(outfd,
X "filter (%s): Error on line %d translating %%%c macro in word \"%s\"!\n",
X username, line, word[i], word);
X if (outfd != NULL) fclose(outfd);
X exit(1);
X }
X }
X else if (word[i] == '%')
X reading_a_percent_sign++;
X else
X buffer[j++] = (word[i] == '_' ? ' ' : 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 if (outfd == NULL) return; /* why are we here, then? */
X
X while (++i < total_rules) {
X if (rules[i].condition->matchwhat == ALWAYS) {
X fprintf(outfd, "\nRule %d: ** always ** \n\t%s %s\n", i+1,
X actionname(rules[i].action), listrule(rules[i].argument2));
X continue;
X }
X
X fprintf(outfd, "\nRule %d: if (", i+1);
X
X cond = rules[i].condition;
X
X while (cond != NULL) {
X if (cond->relation < 0)
X fprintf(outfd, "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 fprintf(outfd, "%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) fprintf(outfd, " and ");
X }
X
X fprintf(outfd, ") then\n\t %s %s\n",
X actionname(rules[i].action),
X listrule(rules[i].argument2));
X }
X fprintf(outfd, "\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_MSG : 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}
X
Xchar *listrule(rule)
Xchar *rule;
X{
X /** simply translates all underscores into spaces again on the
X way past... **/
X
X static char buffer[SLEN];
X register int i;
X
X i = strlen(rule);
X buffer[i] = '\0';
X while (--i >= 0)
X buffer[i] = (rule[i] == '_' ? ' ' : rule[i]);
X
X return( (char *) buffer);
X}
SHAR_EOF
chmod 0444 filter/rules.c || echo "restore of filter/rules.c fails"
echo "x - extracting filter/summarize.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > filter/summarize.c &&
X
Xstatic char rcsid[] ="@(#)$Id: summarize.c,v 4.1 90/04/28 22:42:02 syd Exp $";
X
X/*******************************************************************************
X * The Elm Mail System - $Revision: 4.1 $ $State: Exp $
X *
X * Copyright (c) 1986, 1987 Dave Taylor
X * Copyright (c) 1988, 1989, 1990 USENET Community Trust
X *******************************************************************************
X * Bug reports, patches, comments, suggestions should be sent to:
X *
X * Syd Weinstein - elm@DSI.COM
X * dsinc!elm
X *
X *******************************************************************************
X * $Log: summarize.c,v $
X * Revision 4.1 90/04/28 22:42:02 syd
X * checkin of Elm 2.3 as of Release PL0
X *
X *
X ******************************************************************************/
X
X/** This routine is called from the filter program (or can be called
X directly with the correct arguments) and summarizes the users filterlog
X file. To be honest, there are two sorts of summaries that are
X available - either the '.filterlog' file can be output (filter -S)
X or a summary by rule and times acted upon can be output (filter -s).
X Either way, this program will delete the two associated files each
X time ($HOME/.filterlog and $HOME/.filtersum) *if* the -c option is
X used to the program (e.g. clear_logs is set to TRUE).
X
X**/
X
X#include <stdio.h>
X
X#include "defs.h"
X
X#include "filter.h"
X
Xshow_summary()
X{
X /* Summarize usage of the program... */
X
X FILE *fd; /* for output to temp file! */
X char filename[SLEN], /* name of the temp file */
X buffer[SLEN]; /* input buffer space */
X int erroneous_rules = 0,
X default_rules = 0,
X messages_filtered = 0, /* how many have we touched? */
X rule,
X applied[MAXRULES];
X
X sprintf(filename, "%s/%s", home, filtersum);
X
X if ((fd = fopen(filename, "r")) == NULL) {
X if (outfd != NULL)
X fprintf(outfd,"filter (%s): Can't open filtersum file %s!\n",
X
X username, filename);
X if (outfd != NULL) fclose(outfd);
X exit(1);
X }
X
X for (rule=0;rule < MAXRULES; rule++)
X applied[rule] = 0; /* initialize it all! */
X
X /** Next we need to read it all in, incrementing by which rule
X was used. The format is simple - each line represents a
X single application of a rule, or '-1' if the default action
X was taken. Simple stuff, eh? But oftentimes the best.
X **/
X
X while (fgets(buffer, SLEN, fd) != NULL) {
X if ((rule = atoi(buffer)) > total_rules || rule < -1) {
X if (outfd != NULL)
X fprintf(outfd,
X "filter (%s): Warning - rule #%d is invalid data for short summary!!\n",
X username, rule);
X erroneous_rules++;
X }
X else if (rule == -1)
X default_rules++;
X else
X applied[rule]++;
X messages_filtered++;
X }
X
X fclose(fd);
X
X /** now let's summarize the data... **/
X
X if (outfd == NULL) return; /* no reason to go further */
X
X fprintf(outfd,
X "\n\t\t\tA Summary of Filter Activity\n");
X fprintf(outfd,
X "\t\t\t----------------------------\n\n");
X
X fprintf(outfd,"A total of %d message%s %s filtered:\n\n",
X messages_filtered, plural(messages_filtered),
X messages_filtered > 1 ? "were" : "was");
X
X if (erroneous_rules)
X fprintf(outfd,
X "[Warning: %d erroneous rule%s logged and ignored!]\n\n",
X erroneous_rules, erroneous_rules > 1? "s were" : " was");
X
X if (default_rules) {
X fprintf(outfd,
X "The default rule of putting mail into your mailbox\n");
X fprintf(outfd, "\tapplied %d time%s (%d%%)\n\n",
X default_rules, plural(default_rules),
X (default_rules*100+(messages_filtered>>1))/messages_filtered
X );
X }
X
X /** and now for each rule we used... **/
X
X for (rule = 0; rule < total_rules; rule++) {
X if (applied[rule]) {
X fprintf(outfd, "Rule #%d: ", rule+1);
X switch (rules[rule].action) {
X case LEAVE: fprintf(outfd, "(leave mail in mailbox)");
X break;
X case DELETE_MSG: fprintf(outfd, "(delete message)");
X break;
X case SAVE : fprintf(outfd, "(save in \"%s\")",
X rules[rule].argument2); break;
X case SAVECC: fprintf(outfd,
X "(left in mailbox and saved in \"%s\")",
X rules[rule].argument2); break;
X case FORWARD: fprintf(outfd, "(forwarded to \"%s\")",
X rules[rule].argument2); break;
X case EXEC : fprintf(outfd, "(given to command \"%s\")",
X rules[rule].argument2); break;
X }
X fprintf(outfd, "\n\tapplied %d time%s (%d%%)\n\n",
X applied[rule], plural(applied[rule]),
X (applied[rule]*100+(messages_filtered>>1))/messages_filtered
X );
X }
X }
X
X if (long_summary) {
X
X /* next, after a ^L, include the actual log file... */
X
X sprintf(filename, "%s/%s", home, filterlog);
X
X if ((fd = fopen(filename, "r")) == NULL) {
X fprintf(outfd,"filter (%s): Can't open filterlog file %s!\n",
X username, filename);
X }
X else {
X fprintf(outfd, "\n\n\n%c\n\nExplicit log of each action;\n\n",
X (char) 12);
X while (fgets(buffer, SLEN, fd) != NULL)
X fprintf(outfd, "%s", buffer);
X fprintf(outfd, "\n-----\n");
X fclose(fd);
X }
X }
X
X /* now remove the log files, please! */
X
X if (clear_logs) {
X sprintf(filename, "%s/%s", home, filterlog);
X unlink(filename);
X sprintf(filename, "%s/%s", home, filtersum);
X unlink(filename);
X }
X
X return;
X}
SHAR_EOF
chmod 0444 filter/summarize.c || echo "restore of filter/summarize.c fails"
echo "x - extracting filter/utils.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > filter/utils.c &&
X
Xstatic char rcsid[] ="@(#)$Id: utils.c,v 4.1 90/04/28 22:42:03 syd Exp $";
X
X/*******************************************************************************
X * The Elm Mail System - $Revision: 4.1 $ $State: Exp $
X *
X * Copyright (c) 1986, 1987 Dave Taylor
X * Copyright (c) 1988, 1989, 1990 USENET Community Trust
X *******************************************************************************
X * Bug reports, patches, comments, suggestions should be sent to:
X *
X * Syd Weinstein - elm@DSI.COM
X * dsinc!elm
X *
X *******************************************************************************
X * $Log: utils.c,v $
X * Revision 4.1 90/04/28 22:42:03 syd
X * checkin of Elm 2.3 as of Release PL0
X *
X *
X ******************************************************************************/
X
X/** Utility routines for the filter program...
X
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
Xleave(reason)
Xchar *reason;
X{
X if (outfd != NULL)
X fprintf(outfd,"filter (%s): LEAVE %s\n", username, reason);
X if (outfd != NULL) fclose(outfd);
X exit(1);
X}
X
Xlog(what)
Xint what;
X{
X /** make an entry in the log files for the specified entry **/
X
X FILE *fd;
X char filename[SLEN];
X
X if (! show_only) {
X sprintf(filename, "%s/%s", home, filtersum); /* log action once! */
X if ((fd = fopen(filename, "a")) == NULL) {
X if (outfd != NULL)
X fprintf(outfd, "filter (%s): Couldn't open log file %s\n",
X filename);
X fd = stdout;
X }
X fprintf(fd, "%d\n", rule_choosen);
X fclose(fd);
X }
X
X sprintf(filename, "%s/%s", home, filterlog);
X
X if (show_only)
X fd = stdout;
X else if ((fd = fopen(filename, "a")) == NULL) {
X if (outfd != NULL)
X fprintf(outfd, "filter (%s): Couldn't open log file %s\n",
X filename);
X fd = stdout;
X }
X
X#ifdef _IOFBF
X setvbuf(fd, NULL, _IOFBF, BUFSIZ);
X#endif
X
X if (strlen(from) + strlen(subject) > 60)
X fprintf(fd, "\nMail from %s\n\tabout %s\n", from, subject);
X else
X fprintf(fd, "\nMail from %s about %s\n", from, subject);
X
X if (rule_choosen != -1)
X if (rules[rule_choosen].condition->matchwhat == TO)
X fprintf(fd, "\t(addressed to %s)\n", to);
X
X switch (what) {
X case DELETE_MSG : fprintf(fd, "\tDELETED"); break;
X case SAVE : fprintf(fd, "\tSAVED in file \"%s\"",
X rules[rule_choosen].argument2); break;
X case SAVECC : fprintf(fd,"\tSAVED in file \"%s\" AND PUT in mailbox",
X rules[rule_choosen].argument2); break;
X case FORWARD : fprintf(fd, "\tFORWARDED to \"%s\"",
X rules[rule_choosen].argument2); break;
X case EXEC : fprintf(fd, "\tEXECUTED \"%s\"",
X rules[rule_choosen].argument2); break;
X case LEAVE : fprintf(fd, "\tPUT in mailbox"); break;
X }
X
X if (rule_choosen != -1)
X fprintf(fd, " by rule #%d\n", rule_choosen+1);
X else
X fprintf(fd, ": the default action\n");
X
X fflush(fd);
X fclose(fd);
X}
X
Xint
Xcontains(string, pattern)
Xchar *string, *pattern;
X{
X /** Returns TRUE iff pattern occurs IN IT'S ENTIRETY in buffer. **/
X
X register int i = 0, j = 0;
X
X while (string[i] != '\0') {
X while (tolower(string[i++]) == tolower(pattern[j++]))
X if (pattern[j] == '\0')
X return(TRUE);
X i = i - j + 1;
X j = 0;
X }
X return(FALSE);
X}
X
Xchar *itoa(i, two_digit)
Xint i, two_digit;
X{
X /** return 'i' as a null-terminated string. If two-digit use that
X size field explicitly! **/
X
X static char value[10];
X
X if (two_digit)
X sprintf(value, "%02d", i);
X else
X sprintf(value, "%d", i);
X
X return( (char *) value);
X}
X
Xlowercase(string)
Xchar *string;
X{
X /** translate string into all lower case **/
X
X register int i;
X
X for (i= strlen(string); --i >= 0; )
X if (isupper(string[i]))
X string[i] = tolower(string[i]);
X}
SHAR_EOF
chmod 0444 filter/utils.c || echo "restore of filter/utils.c fails"
echo "x - extracting hdrs/curses.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > hdrs/curses.h &&
X
X/* $Id: curses.h,v 4.1 90/04/28 22:42:05 syd Exp $ */
X
X/*******************************************************************************
X * The Elm Mail System - $Revision: 4.1 $ $State: Exp $
X *
X * Copyright (c) 1986, 1987 Dave Taylor
X * Copyright (c) 1988, 1989, 1990 USENET Community Trust
X *******************************************************************************
X * Bug reports, patches, comments, suggestions should be sent to:
X *
X * Syd Weinstein, Elm Coordinator
X * elm@DSI.COM dsinc!elm
X *
X *******************************************************************************
X * $Log: curses.h,v $
X * Revision 4.1 90/04/28 22:42:05 syd
X * checkin of Elm 2.3 as of Release PL0
X *
X *
X ******************************************************************************/
X
X /*** Include file for seperate compilation. ***/
X
X#define OFF 0
X#define ON 1
X
Xint InitScreen(), /* This must be called before anything else!! */
X
X ClearScreen(), CleartoEOLN(),
X
X MoveCursor(),
X
X StartBold(), EndBold(),
X StartUnderline(), EndUnderline(),
X StartHalfbright(), EndHalfbright(),
X StartInverse(), EndInverse(),
X
X transmit_functions(),
X
X Raw(), RawState(),
X ReadCh();
X
Xchar *return_value_of();
SHAR_EOF
chmod 0444 hdrs/curses.h || echo "restore of hdrs/curses.h fails"
echo "x - extracting hdrs/defs.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > hdrs/defs.h &&
X
X/* $Id: defs.h,v 4.1 90/04/28 22:42:06 syd Exp $ */
X
X/*******************************************************************************
X * The Elm Mail System - $Revision: 4.1 $ $State: Exp $
X *
X * Copyright (c) 1986, 1987 Dave Taylor
X * Copyright (c) 1988, 1989, 1990 USENET Community Trust
X *******************************************************************************
X * Bug reports, patches, comments, suggestions should be sent to:
X *
X * Syd Weinstein, Elm Coordinator
X * elm@DSI.COM dsinc!elm
X *
X *******************************************************************************
X * $Log: defs.h,v $
X * Revision 4.1 90/04/28 22:42:06 syd
X * checkin of Elm 2.3 as of Release PL0
X *
X *
X ******************************************************************************/
X
X/** define file for ELM mail system. **/
X
X
X#include "../config.h"
X#include "sysdefs.h" /* system/configurable defines */
X
X
X# define VERSION "2.3" /* Version number... */
X# define VERS_DATE "May 1, 1990" /* for elm -v option */
X# define WHAT_STRING \
X "@(#) Version 2.3, USENET supported version, released May 1990"
X
X#define KLICK 25
X
X#define SLEN 256 /* long for ensuring no overwrites... */
X#define SHORT 10 /* super short strings! */
X#define NLEN 48 /* name length for aliases */
X#define WLEN 20
X#define STRING 128 /* reasonable string length for most.. */
X#define LONG_STRING 512 /* even longer string for group expansion */
X#define VERY_LONG_STRING 2560 /* huge string for group alias expansion */
X#define MAX_LINE_LEN 5120 /* even bigger string for "filter" prog.. */
X
X#define BREAK '\0' /* default interrupt */
X#define BACKSPACE '\b' /* backspace character */
X#define TAB '\t' /* tab character */
X#define RETURN '\r' /* carriage return char */
X#define LINE_FEED '\n' /* line feed character */
X#define FORMFEED '\f' /* form feed (^L) char */
X#define COMMA ',' /* comma character */
X#define SPACE ' ' /* space character */
X#define DOT '.' /* period/dot character */
X#define BANG '!' /* exclaimation mark! */
X#define AT_SIGN '@' /* at-sign character */
X#define PERCENT '%' /* percent sign char. */
X#define COLON ':' /* the colon .. */
X#define BACKQUOTE '`' /* backquote character */
X#define TILDE_ESCAPE '~' /* escape character~ */
X#define ESCAPE '\033' /* the escape */
X
X#define NO_OP_COMMAND '\0' /* no-op for timeouts */
X
X#define STANDARD_INPUT 0 /* file number of stdin */
X
X#ifndef TRUE
X#define TRUE 1
X#define FALSE 0
X#endif
X
X#define NO 0
X#define YES 1
X#define MAYBE 2 /* a definite define, eh? */
X#define FORM 3 /* <nevermind> */
X#define PREFORMATTED 4 /* forwarded form... */
X
X#define SAME_PAGE 1 /* redraw current only */
X#define NEW_PAGE 2 /* redraw message list */
X#define ILLEGAL_PAGE 0 /* error in page list, punt */
X
X#define PAD 0 /* for printing name of */
X#define FULL 1 /* the sort we're using */
X
X#define OUTGOING 0 /* defines for lock file */
X#define INCOMING 1 /* creation..see lock() */
X
X#define SH 0 /* defines for system_call */
X#define USER_SHELL 1 /* to work correctly! */
X
X#define EXECUTE_ACCESS 01 /* These five are */
X#define WRITE_ACCESS 02 /* for the calls */
X#define READ_ACCESS 04 /* to access() */
X#define ACCESS_EXISTS 00 /* <etc> */
X#define EDIT_ACCESS 06 /* (this is r+w access) */
X
X#define BIG_NUM 999999 /* big number! */
X#define BIGGER_NUM 9999999 /* bigger number! */
X
X#define START_ENCODE "[encode]"
X#define END_ENCODE "[clear]"
X
X#define DONT_SAVE "[no save]"
X#define DONT_SAVE2 "[nosave]"
X
X#define alias_file ".aliases"
X#define group_file ".groups"
X#define system_file ".systems"
X
X#define default_folders "Mail"
X#define default_recvdmail "=received"
X#define default_sentmail "=sent"
X
X/** some defines for the 'userlevel' variable... **/
X
X#define RANK_AMATEUR 0
X#define AMATEUR 1
X#define OKAY_AT_IT 2
X#define GOOD_AT_IT 3
X#define EXPERT 4
X#define SUPER_AT_IT 5
X
X/** some defines for the "status" field of the header record **/
X
X#define ACTION 1 /* bit masks, of course */
X#define CONFIDENTIAL 2
X#define DELETED 4
X#define EXPIRED 8
X#define FORM_LETTER 16
X#define NEW 32
X#define PRIVATE 64
X#define TAGGED 128
X#define URGENT 256
X#define VISIBLE 512
X#define UNREAD 1024
X#define STATUS_CHANGED 2048
X
X#define UNDELETE 0 /* purely for ^U function... */
X
X/** values for headers exit_disposition field */
X#define UNSET 0
X#define KEEP 1
X#define STORE 2
X#define DELETE 3
X
X/** some months... **/
X
X#define JANUARY 0 /* months of the year */
X#define FEBRUARY 1
X#define MARCH 2
X#define APRIL 3
X#define MAY 4
X#define JUNE 5
X#define JULY 6
X#define AUGUST 7
X#define SEPTEMBER 8
X#define OCTOBER 9
X#define NOVEMBER 10
X#define DECEMBER 11
X
X#define equal(s,w) (strcmp(s,w) == 0)
X#define min(a,b) a < b? a : b
X#define ctrl(c) c - 'A' + 1 /* control character mapping */
X#define plural(n) n == 1 ? "" : "s"
X#define lastch(s) s[strlen(s)-1]
X
X/* find tab stops preceding or following a given column position 'a', where
X * the column position starts counting from 1, NOT 0!
X * The external integer "tabspacing" must be declared to use this. */
X#define prev_tab(a) (((((a-1)/tabspacing))*tabspacing)+1)
X#define next_tab(a) (((((a-1)/tabspacing)+1)*tabspacing)+1)
X
X#define movement_command(c) (c == 'j' || c == 'k' || c == ' ' || \
X c == BACKSPACE || c == ESCAPE || c == '*' || \
X c == '-' || c == '+' || c == '=' || \
X c == '#' || c == '@' || c == 'x' || \
X c == 'a' || c == 'q')
X
X#define no_ret(s) { register int xyz; /* varname is for lint */ \
X for (xyz=strlen(s)-1; xyz >= 0 && \
X (s[xyz] == '\r' || s[xyz] == '\n'); ) \
X s[xyz--] = '\0'; \
X }
X
X#define first_word(s,w) (strncmp(s,w, strlen(w)) == 0)
X#define ClearLine(n) MoveCursor(n,0); CleartoEOLN()
X#define whitespace(c) (c == ' ' || c == '\t')
X#define ok_rc_char(c) (isalnum(c) || c == '-' || c == '_')
X#define ok_alias_char(c) (isalnum(c) || c == '-' || c == '_' || c == '.')
X#define quote(c) (c == '"' || c == '\'')
X#define onoff(n) (n == 0 ? "OFF" : "ON")
X
X/** The next function is so certain commands can be processed from the showmsg
X routine without rewriting the main menu in between... **/
X
X#define special(c) (c == 'j' || c == 'k')
X
X/** and a couple for dealing with status flags... **/
X
X#define ison(n,mask) (n & mask)
X#define isoff(n,mask) (!ison(n, mask))
X
X#define setit(n,mask) n |= mask
X#define clearit(n, mask) n &= ~mask
X
SHAR_EOF
echo "End of part 9"
echo "File hdrs/defs.h is continued in part 10"
echo "10" > s2_seq_.tmp
exit 0
--
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.