home *** CD-ROM | disk | FTP | other *** search
- /*--------------------------------------------------------------------*/
- /* Changes Copyright (c) 1989, 1991 Andrew H. Derbyshire */
- /*--------------------------------------------------------------------*/
-
- /*
- mail.c - Mailer User-Agent (UA)
-
- version 1.0 Stuart Lynne
- version 1.5 Samuel Lam <skl@van-bc.UUCP> August/87
-
- version 1.6 Drew Derbyshire May/89
- Support for single user aliases, -u option for reading
- alternate mailboxes, parsing addresses via external routine,
- parsing Resent- fields, suppressing Received: fields,
- automatic positioning to next message. ahd
- 23 Sep 89 Version 1.07a
- Support lists in aliases ahd
-
- 29 Sep 89 Version 1.07b
- Add prompting for subject in outgoing mail. ahd
- 01 Oct 89 Add additional function prototypes to catch bad calls ahd
- 02 Oct 89 Alter large strings/structures to use malloc()/free() ahd
- 12 Oct 89 Version 1.07d
- Correct free() of line in Send_Mail
- 12 Dec 89 Version 1.07g
- Various spelling corrections
- 18 Mar 90 Version 1.07i
- Add ~user support for save/write command
- Add ignore list for user
- Shorten lines printed by aborting from a print command ahd
- 30 Apr 90 Add autoedit support for sending mail ahd
- 2 May 90 Add support for options= flags ahd
- 3 May 90 Split selected subroutines into maillib.c ahd
- 4 May 90 Add 'save' option. ahd
- 8 May 90 Add 'pager' option ahd
- 10 May 90 Add 'purge' option ahd
- 13 May 90 Alter logging so that no numbers are printed on console ahd
- * Additions for unofficial version 1.07k, Philip David Meese June 1990
- * 16 June 90
- * -added mail command: Copy current (without delete) pdm
- * -altered calls to Collect_Mail to support mail subcmds pdm
- * -added handling of '+' to indicate "relative to home
- * directory" for BSD like mail users. pdm
- * 12 Feb 91 rewrite parser a for more BSD like syntax
- */
-
- #include <ctype.h>
- #include <stdio.h>
- #include <io.h>
- #include <stdlib.h>
- #include <string.h>
- #include <limits.h>
- #include <time.h>
- #include <dos.h>
- #include <direct.h>
-
- #include "lib.h"
- #include "address.h"
- #include "alias.h" /* ahd */
- #include "dater.h"
- #include "expath.h"
- #include "getopt.h"
- #include "hlib.h"
- #include "mail.h"
- #include "mailblib.h"
- #include "maillib.h" /* ahd */
- #include "mailsend.h"
- #include "mlib.h"
- #include "pushpop.h"
- #include "stater.h"
- #include "timestmp.h"
-
- currentfile();
-
- static char *tmailbox;
- static char mfilename[FILENAME_MAX];
- int letternum = 0;
-
- static boolean useto = FALSE;
-
- FILE *fmailbox;
-
- #define MAXLETTERS 100
-
- static int maxletters = MAXLETTERS;
-
- struct ldesc *letters;
-
- /*--------------------------------------------------------------------*/
- /* Local procedure names */
- /*--------------------------------------------------------------------*/
-
- static void Cleanup(void);
-
- static void Interactive_Mail(int argc , char *argv[]) ;
-
- static void PrintSubject(int msgnum, int letternum);
-
- static void UpdateMailbox(int letternum, boolean postoffice);
-
- static int CreateBox(FILE *rmailbox,
- FILE *fmailbox,
- const char *tmailbox);
-
- /*--------------------------------------------------------------------*/
- /* Global variables */
- /*--------------------------------------------------------------------*/
-
- static char *replytolist[] = { "Resent-Reply-To:",
- "Resent-From:",
- "Reply-To:",
- "From:",
- NULL };
-
- static char *fromlist[] = { "Resent-From:",
- "From:",
- NULL};
-
- static char *tolist[] = { "Resent-To:",
- "To:",
- NULL};
-
- static char *subjectlist[] = { "Resent-Subject:",
- "Subject:",
- NULL };
-
- static char *datelist[] = { "Resent-Date:",
- "Date:" ,
- NULL} ;
-
-
- /*--------------------------------------------------------------------*/
- /* Information on existing mailbox */
- /*--------------------------------------------------------------------*/
-
- static long mboxsize = 0;
- static time_t mboxage = 0;
-
- /*--------------------------------------------------------------------*/
- /* Command parsing table */
- /*--------------------------------------------------------------------*/
-
- #define NUMERIC_CMD "9999"
- #define EMPTY_CMD ""
-
- static struct CommandTable {
- char *sym;
- ACTION verb;
- unsigned int bits;
- char *help;
- } table[] = {
- EMPTY_CMD, M_EMPTY, NODISPLAY | NO_OPERANDS | AUTOPRINT ,
- NULL,
- "!", M_SYSTEM, STRING_OP,
- "Execute DOS command",
- "+", M_DOWN, INTEGER_OP | AUTOPRINT,
- "Alias for next",
- "-", M_UP, INTEGER_OP | AUTOPRINT,
- "Alias for up",
- "?", M_FASTHELP, NO_OPERANDS,
- "Print this help",
- "alias", M_ALIAS, TOKEN_OP,
- "Print user alias",
- "copy", M_COPY, LETTER_OP | FILE_OP ,
- "Copy item to file",
- "delete", M_DELETE, LETTER_OP | POSITION | AUTOPRINT ,
- "Delete mail item",
- "debug", M_DEBUG, INTEGER_OP,
- "Enable debug output",
- "dquit", M_DELETEQ, LETTER_OP ,
- "Delete then quit",
- "exit", M_EXIT, NO_OPERANDS,
- "Exit without updating mailbox",
- "forward", M_FORWARD, LETTER_OP | USER_OP,
- "Resend item to others",
- "go", M_GOTO, LETTER_OP | AUTOPRINT ,
- "Go to item",
- "Headers", M_HEADERS, LETTER_OP | POSITION ,
- "Print specified item summary",
- "headers", M_HEADERS, NO_OPERANDS,
- "Print all item summaries",
- "help", M_HELP, NO_OPERANDS,
- "Print long help text",
- "mail", M_MAIL, USER_OP,
- "Compose and send mail",
- "next", M_DOWN, INTEGER_OP | AUTOPRINT ,
- "Move to next item",
- "print", M_EXTPRINT, LETTER_OP | POSITION ,
- "Print item (condensed)",
- "Print", M_INTPRINT, LETTER_OP | POSITION ,
- "Print item (condensed)",
- "previous", M_UP, INTEGER_OP | AUTOPRINT ,
- "Alias for up",
- "quit", M_QUIT, NO_OPERANDS,
- "Update mailbox, exit",
- "reply", M_REPLY, LETTER_OP | POSITION ,
- "Reply to sender of item",
- "save", M_SAVE, LETTER_OP | FILE_OP | POSITION | AUTOPRINT ,
- "Copy item, delete",
- "set", M_SET, STRING_OP,
- "Print/set boolean options",
- "status", M_STATUS, NO_OPERANDS,
- "Report version/status info",
- "type", M_EXTTYPE, LETTER_OP | POSITION,
- "Print item with all headers",
- "Type", M_INTTYPE, LETTER_OP | POSITION,
- "Print item with all headers",
- "undelete", M_UNDELETE, LETTER_OP | POSITION | AUTOPRINT ,
- "Rescue item after save/delete",
- "write", M_WRITE, LETTER_OP | FILE_OP | POSITION | AUTOPRINT ,
- "Copy item w/o header, delete",
- "xit", M_EXIT, NO_OPERANDS,
- "alias for exit",
- NUMERIC_CMD, M_GOTO, NODISPLAY | INTEGER_OP | AUTOPRINT ,
- NULL,
- NULL, M_INVALID, NODISPLAY | STRING_OP,
- NULL } ;
-
- /*--------------------------------------------------------------------*/
- /* m a i n */
- /* */
- /* Main program */
- /*--------------------------------------------------------------------*/
-
- void main(int argc, char **argv)
- {
- logfile = fopen("NUL","w"); /* Skip log file in mail ahd */
- logecho = TRUE; /* Print log info on console ahd */
-
-
- #if defined(__CORE__)
- copywrong = strdup(copyright);
- checkref(copywrong);
- #endif
-
- banner( argv );
-
- if (!configure( B_MUA ))
- exit(1); /* system configuration failed */
- if (!InitRouter())
- exit(1); /* system configuration failed */
-
- tmailbox = mktempname(NULL, "TMP");
- tzset(); /* Set up time zone information */
- PushDir(".");
-
- if (argc == 1 || (argv[1][0] == '-') && (argv[1][1] != 's'))
- Interactive_Mail(argc, argv);
- else
- Collect_Mail(stdin, argc - 1 , &argv[1], -1, FALSE);
-
- Cleanup();
- PopDir();
- exit(0);
-
- } /*mailmain*/
-
- /*--------------------------------------------------------------------*/
- /* C l e a n u p */
- /* */
- /* Remove temporary files when exiting */
- /*--------------------------------------------------------------------*/
-
- void Cleanup()
- {
-
- unlink(tmailbox);
-
- } /*Cleanup*/
-
-
- /*--------------------------------------------------------------------*/
- /* I n t e r a c t i v e _ M a i l */
- /* */
- /* main procedure for reading mail */
- /*--------------------------------------------------------------------*/
-
- void Interactive_Mail(int argc, char *argv[])
- {
- char resp[LSIZE];
- int option;
- int current = 0; /* ahd */
- boolean done = FALSE; /* ahd */
- boolean modified;
- boolean PrintOnly = FALSE;
- boolean postoffice = TRUE; /* ahd */
- FILE *rmailbox;
-
- /*--------------------------------------------------------------------*/
- /* get mailbox file name */
- /*--------------------------------------------------------------------*/
-
- mkmailbox(mfilename , mailbox);
-
- /*--------------------------------------------------------------------*/
- /* parse arguments */
- /*--------------------------------------------------------------------*/
-
- while ((option = getopt(argc, argv, "f:ptu:x:")) != EOF)
- switch (option) {
- case 'f':
- if (*optarg == '=') /* relative to home directory? */
- {
- printf("Syntax is obsolete ... use \"~/%s\" for file name",
- optarg + 1 );
- return;
- }
- else {
- char oname[FILENAME_MAX];
- strcpy( mfilename, optarg );
- if (expand_path( mfilename , NULL, homedir , E_mailext ) == NULL )
- return;
-
- /*--------------------------------------------------------------------*/
- /* This next one is a little tricky ... If we log outgoing */
- /* mail, we copy the name of the outgoing mail file into a */
- /* temporary buffer, and expand the name of the file to include */
- /* the path name. If this name is the same as the current */
- /* file, flip-flip the useto flag which says use the To: */
- /* related fields when scanning headers, not the From: related */
- /* fields. */
- /*--------------------------------------------------------------------*/
-
- if (( E_filesent != NULL ) &&
- (expand_path( strcpy( oname, E_filesent) ,
- homedir, homedir , E_mailext ) != NULL ) &&
- equali( oname , mfilename ))
- /* Our outgoing filename? */
- useto = ! useto; /* Yes --> Automatically switch */
- }
- postoffice = FALSE;
- break;
-
- case 'p':
- PrintOnly = TRUE;
- break;
-
- case 'u': /* Read alternate mailbox? */
- mkmailbox(mfilename, optarg);
- postoffice = FALSE;
- break;
-
- case 'x':
- debuglevel = atoi(optarg);
- break;
-
- case 't':
- useto = ! useto;
- break;
-
- case '?':
- puts("\nUsage:\tmail [-s subject] recipient ... \
- [-c recipient ...] [-b receipient ...]");
- puts("\tmail [-f mailbox] [-u user] [-t] [-p] [-x debug]");
- return;
- }
-
- argv = &argv[optind];
-
- /*--------------------------------------------------------------------*/
- /* Open real and temporary mailbox files */
- /*--------------------------------------------------------------------*/
-
- if ((rmailbox = FOPEN(mfilename, "r", TEXT)) == nil(FILE)) {
- printf("No mail in %s\n", mfilename);
- return;
- }
-
- mboxage = stater( mfilename, &mboxsize );
- /* Remember mailbox information */
-
- if ((fmailbox = FOPEN(tmailbox, "w", BINARY)) == nil(FILE)) {
- printerr(tmailbox);
- return;
- }
-
- letters = calloc(maxletters,sizeof(letters[0]));
- checkref(letters);
-
- /*--------------------------------------------------------------------*/
- /* Copy real mailbox to temporary one */
- /*--------------------------------------------------------------------*/
-
- setvbuf(rmailbox, NULL, _IOFBF, 8192);
- setvbuf(fmailbox, NULL, _IOFBF, 8192);
- letternum = CreateBox(rmailbox, fmailbox, tmailbox);
-
- if (letternum < 1) /* Did we find any mail in the box? */
- { /* No --> Return to caller */
- if (letternum == 0)
- printf("No mail in %s\n", mfilename);
- return;
- }
-
- /*--------------------------------------------------------------------*/
- /* Shrink mailbox status array to what we actually need */
- /*--------------------------------------------------------------------*/
-
- letters = realloc( letters, (letternum + 1) * sizeof(letters[0]));
- checkref(letters);
-
- fmailbox = FOPEN(tmailbox, "r", BINARY);
-
- if (fmailbox == NULL)
- {
- printerr(tmailbox);
- panic();
- } /* if */
- setvbuf(fmailbox, NULL, _IOFBF, 8192);
-
- modified = postoffice && (!PrintOnly);
-
- if (PrintOnly) {
- int j = 0;
- while (j < letternum)
- {
- Pager(j, TRUE, noreceived, !j );
- j++ ;
- }
- return;
- }
-
- PrintSubject(-1,letternum); /* print all subjects */
-
- /*--------------------------------------------------------------------*/
- /* Determine first letter in to prompt at */
- /*--------------------------------------------------------------------*/
-
- if (letternum == 0)
- current = -1;
- else
- current = 0;
-
- /*--------------------------------------------------------------------*/
- /* Begin main command loop for reading the mail */
- /*--------------------------------------------------------------------*/
-
- if (!bflag[F_EXPERT])
- printf("Enter \"?\" for short help or \"help\" for long help.\n");
-
- while( ! done )
- {
- char *command, *operand;
- int integer;
- boolean first_pass = TRUE;
- int previous = current;
- struct CommandTable *cmd_ptr = table;
- boolean success = TRUE;
-
- printf("%d%s",current + 1,
- (letters[current].status == M_DELETED) ? "*" : " ");
- if (!Console_fgets(resp, LSIZE, "? ")) /* End of file? */
- {
- done = TRUE;
- continue; /* Yes --> Exit loop */
- }
- PageReset();
-
- /*--------------------------------------------------------------------*/
- /* Locate command to execute */
- /*--------------------------------------------------------------------*/
-
- integer = strlen( resp );
- if (integer && ( resp[ integer - 1 ] == '\n'))
- resp[ integer - 1 ] = '\0'; /* Trim newline, if any */
-
- operand = command = strtok( resp, WHITESPACE );
- if ( command == NULL )
- command = EMPTY_CMD;
- else if (Numeric(command))
- command = NUMERIC_CMD;
-
- while( cmd_ptr->sym != NULL)
- {
- if (equaln(command, cmd_ptr->sym, strlen(command)))
- break; /* Exit if we have a hit */
- cmd_ptr++; /* Examine next command */
- } /* while */
-
- /*--------------------------------------------------------------------*/
- /* Get rest of command line, and trim leading spaces from it */
- /*--------------------------------------------------------------------*/
-
- if (!equal(command, NUMERIC_CMD) && (operand != NULL))
- {
- operand = strtok( NULL , "");
- /* Save rest of string for later */
- if ( operand != NULL )
- {
- while( isspace( *operand ))
- operand++ ;
-
- if (*operand == '\0')
- operand = NULL ;
- } /* if */
- }
-
- /*--------------------------------------------------------------------*/
- /* Parse items to be selected from mailbox for command */
- /*--------------------------------------------------------------------*/
-
- if (cmd_ptr->bits & (LETTER_OP) )
- success = SelectItems( &operand, current, cmd_ptr->bits);
-
- /*--------------------------------------------------------------------*/
- /* Process the operands in the list */
- /*--------------------------------------------------------------------*/
-
- while( success &&
- Get_Operand( &integer, &operand, cmd_ptr->bits, first_pass) )
- {
- switch( cmd_ptr->verb )
- {
- case M_ALIAS:
- ShowAlias( operand );
- break;
-
- case M_COPY:
- success = SaveItem( integer,
- FALSE, /* Do not delete */
- seperators, /* Do save headers */
- (operand == NULL) ? "PRN" : operand ,
- cmd_ptr->verb );
- break;
-
- case M_DEBUG:
- debuglevel = integer;
- printmsg(0,"Debug set to %d",debuglevel);
- break;
-
- case M_DELETEQ:
- done = TRUE;
- case M_DELETE:
- if (letters[integer].status < M_DELETED)
- letters[integer].status = M_DELETED;
- printf("Deleting item %d\n",integer + 1 );
- modified = TRUE;
- break;
-
- case M_DOWN:
- current = Position( 0 , integer , current );
- break;
-
- case M_EMPTY:
- if ( bflag[F_DOSKEY] && !bflag[F_EXPERT] )
- {
- printf("DOSKEY active, empty line ignored\n");
- PrintSubject( current , letternum );
- success = FALSE;
- }
- else if (letters[current].status == M_UNREAD)
- success = Pager( current , TRUE, noreceived, first_pass);
- else
- current = Position( 0 , 1 , current );
- break;
-
- case M_EXIT:
- modified = FALSE;
- done = TRUE;
- break;
-
- case M_EXTPRINT:
- success = Pager( integer , TRUE, noreceived, first_pass);
- break;
-
- case M_EXTTYPE:
- success = Pager( integer , TRUE, noseperator, first_pass);
- break;
-
- case M_FASTHELP:
- {
- size_t subscript = 0;
- size_t column = 0;
- fputs("Valid commands are:\n",stdout);
- while( table[subscript].sym != NULL)
- {
- if ( !(table[subscript].bits & NODISPLAY ))
- {
- fputc( ( column++ % 2 ) ? ' ' : '\n' , stdout );
- printf("%-9s%-30s",table[subscript].sym,
- table[subscript].help );
- } /* if */
- subscript ++;
- } /* while */
- fputs("\n\nEnter \"help\" for additional information.\n",
- stdout);
- break;
- } /* case */
-
- case M_FORWARD:
- success = ForwardItem( integer, operand);
- break;
-
- case M_GOTO:
- current = Position( integer, 0, current );
- break;
-
- case M_HEADERS:
- PrintSubject( (cmd_ptr->bits & NO_OPERANDS) ?
- -1 : integer, letternum );
- break;
-
- case M_HELP:
- {
- char filename[FILENAME_MAX];
- mkfilename(filename, confdir, "mail.hlp");
- Sub_Pager(filename, TRUE );
- break;
- }
-
- case M_INTPRINT:
- success = Pager( integer , FALSE, noreceived, first_pass);
- break;
-
- case M_INTTYPE:
- success = Pager( integer , FALSE, noseperator, first_pass);
- break;
-
- case M_INVALID:
- printf("Invalid command \"%s\". Enter \"?\" for help.\n",
- command);
- break;
-
- case M_MAIL:
- success = DeliverMail( operand , current);
- break;
-
- case M_NOOP:
- break;
-
- case M_REPLY:
- success = Reply( integer );
- break;
-
- case M_QUIT:
- done = TRUE;
- break;
-
- case M_SAVE:
- success = SaveItem( integer,
- TRUE, /* Do delete */
- seperators, /* Do save headers */
- operand ,
- cmd_ptr->verb );
- modified = TRUE;
- break;
-
- case M_SET:
- if (operand == NULL)
- sayoptions( configFlags);
- else
- options(operand, USER_CONFIG, configFlags, bflag);
- break;
-
- case M_SYSTEM:
- subshell( operand );
- break;
-
- case M_UNDELETE:
- letters[integer].status = M_UNREAD;
- break;
-
- case M_UP:
- current = Position( 0 , - integer , current );
- break;
-
- case M_STATUS:
- printf("%s:\t%s created %s %s running under %s %d.%02d\n",
- compilep, compilev, compiled, compilet,
- #ifdef __TURBOC__
- "MS-DOS",
- #else
- (_osmode == DOS_MODE) ? "MS-DOS" : "OS/2" ,
- #endif
- _osmajor, _osminor);
- printf("Return address:\t\"%s\" <%s@%s>\n\
- Domain name:\t%s\tNodename:\t%s\n",
- name, mailbox, fdomain, domain, nodename );
- printf("Current File:\t%s\nFile size:\t%ld bytes\tLast updated:\t%s",
- mfilename, mboxsize , ctime( & mboxage ) );
- break;
-
- case M_WRITE:
- success = SaveItem( integer,
- TRUE, /* Do delete */
- noheader, /* Do not save headers */
- operand,
- cmd_ptr->verb );
- modified = TRUE;
- } /* switch */
- first_pass = FALSE;
- } /* while */
-
- success = ! first_pass; /* If first_pass not run, then
- Get_Operand failed */
-
- if ( success && !done )
- {
- if (cmd_ptr->bits & POSITION)
- current = Position( 0 , 0 , integer );
-
- if ( current != previous )
- {
- if ( (cmd_ptr->bits & AUTOPRINT ) &&
- bflag[F_AUTOPRINT] &&
- (letters[current].status != M_DELETED) )
- Pager( current , TRUE, noreceived, TRUE);
- else
- PrintSubject( current , letternum );
- } /* if */
- } /* if */
- } /* while */
-
- /*--------------------------------------------------------------------*/
- /* End main command loop */
- /*--------------------------------------------------------------------*/
-
- if (modified)
- UpdateMailbox(letternum, postoffice);
-
-
- free(letters);
-
- } /*Interactive_Mail*/
-
- /*--------------------------------------------------------------------*/
- /* C r e a t e B o x */
- /* */
- /* Creates the temporary mailbox and related tables */
- /*--------------------------------------------------------------------*/
-
- int CreateBox(FILE *rmailbox, FILE *fmailbox , const char *tmailbox)
- {
-
- /*--------------------------------------------------------------------*/
- /* Copy real mailbox file to temporary mailbox file */
- /*--------------------------------------------------------------------*/
-
- int letternum = 0;
- boolean inheader = FALSE;
- long position;
- char line[LSIZE];
- char **list;
- size_t replyprior;
- size_t dateprior;
- size_t subjectprior;
- size_t fromprior;
-
- struct ldesc *letter = NULL;
-
- while ((fgets(line, LSIZE, rmailbox) != nil(char)) ){
-
- if (inheader)
- {
- if (*line == '\n')
- inheader = FALSE;
- } /* inheader */
- else { /* Determine if starting new message */
- if (equal(line,MESSAGESEP) ||
- (bflag[F_FROMSEP] && equaln(line, "From ", 5)))
- {
- while (equal(line,MESSAGESEP))
- if (fgets(line, LSIZE, rmailbox) == NULL)
- {
- printerr(mfilename);
- panic();
- } /* if */
-
-
- /*--------------------------------------------------------------------*/
- /* Make the mailbox bigger if we need to */
- /*--------------------------------------------------------------------*/
-
- position = ftell(fmailbox);
- if ( (letternum+1) == maxletters )
- {
- maxletters = max((int) ((maxletters * mboxsize) / position),
- (letternum * 11) / 10 );
- printmsg(2,"Reallocating mailbox array from %d to %d entries",
- letternum+1, maxletters );
- letters = realloc( letters, maxletters * sizeof(letters[0]));
- checkref( letters );
- }
-
- /*--------------------------------------------------------------------*/
- /* Initialize this entry in th mailbox array */
- /*--------------------------------------------------------------------*/
-
- letter = &letters[letternum++];
-
- fromprior = subjectprior = replyprior = dateprior = INT_MAX;
- letter->from = letter->subject = letter->date =
- letter->replyto = MISSING;
- letter->adr = position;
- letter->status = M_UNREAD;
- letter->lines = 0L;
- inheader = TRUE;
- printf("Reading message %d\r",letternum);
- }
- else
- {
- if(letter == NULL) /* Did we find first letter? */
- { /* No --> Abort with message */
- fprintf(stderr,"%s %s\n\a",
- "This mailbox is not in UUPC/extended format!",
- bflag[F_FROMSEP] ?
- "Messages must be seperated by From lines!" :
- "(Try \"options=fromsep\" in your configuration file)");
- panic();
- } /* if */
-
- letter->lines++;
- } /* else */
- } /* else */
-
- if (inheader)
- {
- size_t priority = 0;
-
- /*--------------------------------------------------------------------*/
- /* Search for the best Date: related field */
- /*--------------------------------------------------------------------*/
-
- while ( (dateprior > priority) && (datelist[priority] != NULL ))
- {
- if (equalni(line, datelist[priority],
- strlen(datelist[priority]) ) )
- {
- letter->date = ftell(fmailbox);
- dateprior = priority;
- }
- priority++;
- }
-
- /*--------------------------------------------------------------------*/
- /* Search for the best Subject: related field */
- /*--------------------------------------------------------------------*/
-
- priority = 0;
- while ( (subjectprior > priority) &&
- (subjectlist[priority] != NULL ))
- {
- if (equalni(line, subjectlist[priority],
- strlen(subjectlist[priority]) ) )
- {
- letter->subject = ftell(fmailbox);
- subjectprior = priority;
- }
- priority++;
- }
-
- /*--------------------------------------------------------------------*/
- /* Search for the best From: header related field */
- /*--------------------------------------------------------------------*/
-
- list = (useto) ? tolist : fromlist;
- priority = 0;
- while ( (fromprior > priority) && (list[priority] != NULL ))
- {
- if (equalni(line, list[priority],
- strlen(list[priority]) ) )
- {
- letter->from = ftell(fmailbox);
- fromprior = priority;
- }
- priority++;
- } /* while */
-
- /*--------------------------------------------------------------------*/
- /* Search for the best Reply-To related field */
- /*--------------------------------------------------------------------*/
-
- priority = 0;
- while ( (replyprior > priority) &&
- (replytolist[priority] != NULL ))
- {
- if (equalni(line, replytolist[priority],
- strlen(replytolist[priority]) ) )
- {
- letter->replyto = ftell(fmailbox);
- replyprior = priority;
- } /* if */
- priority++;
- } /* while */
- } /* inheader */
-
- if (fputs(line, fmailbox) == EOF )
- {
- printerr(tmailbox);
- panic();
- } /* if */
-
-
- } /* while */
-
- letters[letternum].adr = ftell(fmailbox);
- letters[letternum].status = M_DELETED;
-
- /*--------------------------------------------------------------------*/
- /* close mailbox files */
- /*--------------------------------------------------------------------*/
-
- fclose(rmailbox);
- fclose(fmailbox);
-
- return letternum;
-
- } /* CreateBox */
-
- /*--------------------------------------------------------------------*/
- /* P r i n t S u j e c t */
- /* */
- /* Print the subject line of one or all messages in the mailbox */
- /*--------------------------------------------------------------------*/
-
- void PrintSubject(int msgnum,int letternum)
- {
- struct ldesc *ld;
- char from[LSIZE];
- char subject[LSIZE];
- char date[LSIZE];
- char line[LSIZE];
-
- int k, mink, maxk;
-
- if (msgnum == -1)
- { /* print all of them? */
- sprintf(line," %d messages in file\n",letternum);
- PageLine(line);
- mink = 0;
- maxk = letternum - 1;
- } else
- mink = maxk = msgnum;
-
- for (k = mink ; k <= maxk ; k++) {
-
- ld = &letters[k];
- if ((ld->status == M_DELETED) && (msgnum == -1))
- continue;
-
- ReturnAddress(from,ld); /* Get return address for letter */
-
- /* Date: Wed May 13 23:59:53 1987 */
- *date = '\0'; /* default date to null */
- if (RetrieveLine(ld->date, date, LSIZE)) {
- sscanf(date, "%*s %*s %s %s", line, subject);
- sprintf(date, "%s %s", line, subject);
- }
-
- strcpy(subject, "--- no subject ---");
- if (RetrieveLine(ld->subject, line, LSIZE)) {
- register char *sp;
- sp = line;
- while (!isspace(*sp))
- sp++;
- while (isspace(*sp))
- sp++;
- strcpy(subject, sp);
- }
-
- /* make sure the fields aren't too long */
-
- from[25] = '\0';
- date[6] = '\0';
- subject[30] = '\0';
-
- sprintf(line, "%3d%c %6s %-25s %-30s (%5ld)\n", k + 1,
- ((ld->status == M_DELETED) ? '*' : ' '),
- date, from, subject, ld->lines);
-
- if (PageLine(line))
- break;
-
- }
-
- } /*PrintSubject*/
-
-
- /*--------------------------------------------------------------------*/
- /* U p d a t e M a i l b o x */
- /* */
- /* Update the permanent mailbox for the user */
- /*--------------------------------------------------------------------*/
-
- void UpdateMailbox(int letternum, boolean postoffice)
- {
- int current;
- boolean changed = FALSE;
- boolean problem = FALSE;
- FILE *fmailbag;
- FILE *mbox = NULL;
- char *mboxname;
- long newsize;
- time_t newage;
- size_t msave = 0;
- size_t psave = 0;
-
- /*--------------------------------------------------------------------*/
- /* Auto save into user's home directory mailbox if we were */
- /* reading the system mailbox and the user specified the */
- /* 'save' option. */
- /*--------------------------------------------------------------------*/
-
- postoffice = postoffice && bflag[F_SAVE];
-
- /*--------------------------------------------------------------------*/
- /* Determine if anything was actually changed in the mailbox */
- /*--------------------------------------------------------------------*/
-
- for (current = 0;
- (current < letternum) && (! changed);
- current++)
- {
- if (letters[current].status == M_DELETED)
- changed = TRUE;
-
- if (postoffice && (letters[current].status != M_UNREAD))
- changed = TRUE;
- }
-
- if (!changed)
- return;
-
- /*--------------------------------------------------------------------*/
- /* Determine if the mailbox has changed since we built our */
- /* temporary file */
- /*--------------------------------------------------------------------*/
-
- newage = stater( mfilename , &newsize );
-
- if ( mboxsize != newsize )
- {
- printf("%s size has changed from %ld to %ld bytes\n",
- mfilename, mboxsize, newsize );
- problem = TRUE;
- }
-
- if ( mboxage != newage )
- {
- char mboxbuf[DATEBUF];
- char newbuf[DATEBUF];
- printf("%s date stamp has changed from %s to %s\n",
- mfilename, dater(mboxage, mboxbuf), dater(newage, newbuf) );
- problem = TRUE;
- }
-
- while ( problem )
- {
- int c;
-
- printf("WARNING! File %s has changed, data may be lost if updated!\n",
- mfilename);
- fputs("Update anyway? ",stdout);
-
- c = Get_One();
-
- switch (tolower( c ))
- {
- case 'y':
- puts("Yes");
- problem = FALSE;
- break;
-
- case 'n':
- printf("No\nUpdate aborted, %s left unchanged.\n",
- mfilename);
- return;
-
- default:
- printf("%c - Invalid Response\n",c);
- break;
- } /* switch */
- } /* while ( problem ) */
-
- /*--------------------------------------------------------------------*/
- /* Allocate auto save related variables */
- /*--------------------------------------------------------------------*/
-
- if (postoffice)
- {
- mboxname = malloc(FILENAME_MAX);
- checkref(mboxname);
- strcpy( mboxname, "mbox" );
- expand_path( mboxname, homedir, homedir, E_mailext );
- } /* if (postoffice) */
-
- /*--------------------------------------------------------------------*/
- /* Create a backup file if needed */
- /*--------------------------------------------------------------------*/
-
- if ( bflag[F_BACKUP] )
- {
- char fdrive[FILENAME_MAX];
- char fpath[FILENAME_MAX];
- char fname[FILENAME_MAX];
- char ftype[FILENAME_MAX];
- char backup[FILENAME_MAX];
-
- if ( E_backup == NULL )
- E_backup = ".BAK";
-
- #ifdef __TURBOC__
- fnsplit( mfilename, fdrive, fpath, fname, ftype );
- if ( *E_backup != '.' )
- E_backup = strcat( strcpy(ftype, ".") , E_backup );
- fnmerge( backup, fdrive, fpath, fname, E_backup );
- #else
- _splitpath( mfilename , fdrive, fpath, fname, ftype );
- _makepath( backup , fdrive, fpath, fname, E_backup );
- #endif /* __TURBOC__ */
-
- remove( backup );
-
- if (rename( mfilename, backup ))
- {
- perror( backup );
- printf("Unable to rename %s to %s\n", mfilename, backup );
- } /* if (rename( mfilename, backup )) */
- } /* if ( bflag[F_BACKUP] ) */
-
- /*--------------------------------------------------------------------*/
- /* Begin re-writing the mailbox */
- /*--------------------------------------------------------------------*/
-
- if ((fmailbag = FOPEN(mfilename, "w", TEXT)) == nil(FILE))
- {
- printf("UpdateMailbox: can't rewrite %s.\n", mfilename);
- Cleanup();
- } /* if */
-
- setvbuf(fmailbag, NULL, _IOFBF, 8192);
-
- /*--------------------------------------------------------------------*/
- /* We got the files open, now actually loop through copying */
- /* data from our temporary mailbox back into the permenent one, */
- /* or in the user's mbox if he read the message and the post */
- /* office is open. */
- /*--------------------------------------------------------------------*/
-
- printf("Cleaning up ", current+ 1);
-
- for (current = 0; current < letternum; current++)
- {
- if (letters[current].status == M_DELETED)
- {
- /* No operation */
- fputc('.', stdout);
- }
- else if (postoffice && (letters[current].status != M_UNREAD))
- {
-
- if ( mbox == NULL ) /* Mailbox already open? */
- { /* No --> Do so now */
- mbox = FOPEN(mboxname, "a", TEXT);
- if (mbox == NULL) /* Open fail? */
- { /* Yes --> Disable postoffice autosave*/
- printf("\nUpdateMailbox: can't append to %s.\n", mboxname);
- postoffice = FALSE;
- current--; /* Process this entry again */
- } /* if */
- else
- setvbuf(mbox, NULL, _IOFBF, 8192);
- } /* if ( mbox == NULL ) */
-
- if ( mbox != NULL )
- {
- fputc('+', stdout);
- CopyMsg(current, mbox, seperators, FALSE);
- msave++;
- } /* mbox */
- }
- else {
- fputc('*', stdout);
- CopyMsg(current, fmailbag, seperators, FALSE);
- psave ++;
- } /* else */
-
- } /* for */
- fputs(" done!\n", stdout);
-
- /*--------------------------------------------------------------------*/
- /* Close the post office. We close the 'mbox' in the user's */
- /* home directory, report if any data was saved in it, and */
- /* then free the storage associated with the postoffice processing.*/
- /*--------------------------------------------------------------------*/
-
- if ( postoffice )
- {
-
- if (msave > 0) /* Did we write data into mailbox? */
- { /* Yes --> Report it */
- fclose(mbox);
- printf("%d letter%s saved in %s%s",
- msave,
- (msave > 1) ? "s" : "" ,
- mboxname,
- (psave > 0) ? ", " : ".\n");
- }
-
- free(mboxname);
- } /* if (postoffice) */
-
- /*--------------------------------------------------------------------*/
- /* Now, clean up after the input mailbox. We close it, and */
- /* report when anything was saved into it. If nothing was */
- /* saved, we delete the file if the 'purge' option is active. */
- /*--------------------------------------------------------------------*/
-
- fclose(fmailbag);
-
- if (psave > 0)
- printf("%d letter%s held in %s.\n",
- psave ,
- (psave > 1) ? "s" : "" , mfilename);
- else if (bflag[F_PURGE] )
- {
- remove(mfilename);
- printf("Empty mail box %s has been deleted.\n", mfilename);
- }
-
- } /* UpdateMailbox */
-