home *** CD-ROM | disk | FTP | other *** search
- Subject: v18i093: Elm mail system, release 2.2, Part14/24
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: dsinc!syd@uunet.UU.NET (Syd Weinstein)
- Posting-number: Volume 18, Issue 93
- Archive-name: elm2.2/part14
-
- #!/bin/sh
- # this is part 14 of a multipart archive
- # do not concatenate these parts, unpack them in order with /bin/sh
- # file src/elm.c continued
- #
- CurArch=14
- 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 src/elm.c"
- sed 's/^X//' << 'SHAR_EOF' >> src/elm.c
- X current);
- X
- X Write_to_screen("Lines : %-5d\t\t\tStatus: A C D E F N O P T U V\n\r", 1,
- X current_header->lines);
- X Write_to_screen(" \t\t\t c o e x o e l r a r i\n\r", 0);
- X Write_to_screen(" \t\t\t t n l p r w d i g g s\n\r", 0);
- X Write_to_screen(" \t\t\t n f d d m v d n i\n\r", 0);
- X
- X sprintf(buffer,
- X "\n\rOffset: %ld\t\t\t %d %d %d %d %d",
- X current_header->offset,
- X (current_header->status & ACTION) != 0,
- X (current_header->status & CONFIDENTIAL) != 0,
- X (current_header->status & DELETED) != 0,
- X (current_header->status & EXPIRED) != 0,
- X (current_header->status & FORM_LETTER) != 0);
- X sprintf(buffer + strlen(buffer),
- X " %d %d %d %d %d %d\n",
- X (current_header->status & NEW) != 0,
- X (current_header->status & UNREAD) != 0,
- X (current_header->status & PRIVATE) != 0,
- X (current_header->status & TAGGED) != 0,
- X (current_header->status & URGENT) != 0,
- X (current_header->status & VISIBLE) != 0);
- X
- X Write_to_screen(buffer, 0);
- X
- X sprintf(buffer, "\n\rReceived on: %d/%d/%d at %d:%02d\n\r",
- X current_header->received.month+1,
- X current_header->received.day,
- X current_header->received.year,
- X current_header->received.hour,
- X current_header->received.minute);
- X Write_to_screen(buffer, 0);
- X
- X sprintf(buffer, "Message sent on: %s, %s %s, %s at %s\n\r",
- X current_header->dayname,
- X current_header->month,
- X current_header->day,
- X current_header->year,
- X current_header->time);
- X Write_to_screen(buffer, 0);
- X
- X Write_to_screen("From: %s\n\rSubject: %s", 2,
- X current_header->from,
- X current_header->subject);
- X
- X Write_to_screen("\n\rPrimary Recipient: %s\nInternal Index Reference Number = %d\n\r", 2,
- X current_header->to,
- X current_header->index_number);
- X
- X Write_to_screen("Message-ID: %s\n\r", 1,
- X strlen(current_header->messageid) > 0 ?
- X current_header->messageid : "<none>");
- X
- X Write_to_screen("Status: %s\n\r", 1, current_header->mailx_status);
- X
- X Raw(ON);
- X
- X PutLine0(LINES,0,"Please Press any key to return.");
- X (void) ReadCh();
- X}
- SHAR_EOF
- echo "File src/elm.c is complete"
- chmod 0444 src/elm.c || echo "restore of src/elm.c fails"
- echo "x - extracting src/encode.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > src/encode.c &&
- X
- Xstatic char rcsid[] = "@(#)$Id: encode.c,v 2.9 89/03/25 21:46:13 syd Exp $";
- X
- X/*******************************************************************************
- X * The Elm Mail System - $Revision: 2.9 $ $State: Exp $
- X *
- X * Copyright (c) 1986, 1987 Dave Taylor
- X * Copyright (c) 1988, 1989 USENET Community Trust
- X *******************************************************************************
- X * Bug reports, patches, comments, suggestions should be sent to:
- X *
- X * Syd Weinstein, Elm Coordinator
- X * elm@dsinc.UUCP dsinc!elm
- X *
- X *******************************************************************************
- X * $Log: encode.c,v $
- X * Revision 2.9 89/03/25 21:46:13 syd
- X * Initial 2.2 Release checkin
- X *
- X *
- X ******************************************************************************/
- X
- X/** This is a heavily mangled version of the 'cypher' program written by
- X person or persons unknown.
- X
- X**/
- X
- X#include "headers.h"
- X
- X#define RS 94
- X#define RN 4
- X#define RMASK 0x7fff /* use only 15 bits */
- X
- Xstatic char r[RS][RN]; /* rotors */
- Xstatic char ir[RS][RN]; /* inverse rotors */
- Xstatic char h[RS]; /* half rotor */
- Xstatic char s[RS]; /* shuffle vector */
- Xstatic int p[RN]; /* rotor indices */
- X
- Xstatic char the_key[SLEN]; /* unencrypted key */
- Xstatic char *encrypted_key; /* encrypted key */
- X
- Xchar *strncpy(), *strcpy();
- Xunsigned long sleep();
- X
- X#define DECRYPT_PROMPT "Enter decryption key: "
- X#define FIRST_ENC_PROMPT "Enter encryption key: "
- X#define SECOND_ENC_PROMPT "Please enter it again: "
- X#define PROMPT_LINE LINES-1
- X
- Xgetkey(send)
- Xint send;
- X{
- X /** this routine prompts for and returns an encode/decode
- X key for use in the rest of the program. **/
- X
- X char buffer[2][NLEN];
- X
- X while (1) {
- X PutLine0(PROMPT_LINE, 0, (send ? FIRST_ENC_PROMPT : DECRYPT_PROMPT));
- X CleartoEOLN();
- X optionally_enter(buffer[0], PROMPT_LINE,
- X strlen(send ? FIRST_ENC_PROMPT : DECRYPT_PROMPT), FALSE, TRUE);
- X if (send) {
- X PutLine0(PROMPT_LINE, 0, SECOND_ENC_PROMPT);
- X CleartoEOLN();
- X optionally_enter(buffer[1], PROMPT_LINE, strlen(SECOND_ENC_PROMPT),
- X FALSE, TRUE);
- X if(strcmp(buffer[0], buffer[1]) != 0) {
- X error("Your keys were not the same!");
- X sleep(1);
- X clear_error();
- X continue;
- X }
- X }
- X break;
- X }
- X strcpy(the_key, buffer[0]); /* save unencrypted key */
- X makekey(buffer[0]);
- X
- X setup(); /** initialize the rotors etc. **/
- X
- X ClearLine(PROMPT_LINE);
- X clear_error();
- X}
- X
- Xget_key_no_prompt()
- X{
- X /** This performs the same action as get_key, but assumes that
- X the current value of 'the_key' is acceptable. This is used
- X when a message is encrypted twice... **/
- X
- X char buffer[SLEN];
- X
- X strcpy(buffer, the_key);
- X
- X makekey( buffer );
- X
- X setup();
- X}
- X
- Xencode(line)
- Xchar *line;
- X{
- X /** encrypt or decrypt the specified line. Uses the previously
- X entered key... **/
- X
- X register int i, iindex, j, ph = 0;
- X
- X for (iindex=0; iindex < strlen(line); iindex++) {
- X i = (int) line[iindex];
- X
- X if ( (i >= ' ') && (i < '~') ) {
- X i -= ' ';
- X
- X for ( j = 0; j < RN; j++ ) /* rotor forwards */
- X i = r[(i+p[j])%RS][j];
- X
- X i = ((h[(i+ph)%RS])-ph+RS)%RS; /* half rotor */
- X
- X for ( j-- ; j >= 0; j-- ) /* rotor backwards */
- X i = (ir[i][j]+RS-p[j])%RS;
- X
- X j = 0; /* rotate rotors */
- X p[0]++;
- X while ( p[j] == RS ) {
- X p[j] = 0;
- X j++;
- X if ( j == RN ) break;
- X p[j]++;
- X }
- X
- X if ( ++ph == RS )
- X ph = 0;
- X
- X i += ' ';
- X }
- X
- X line[iindex] = (char) i; /* replace with altered one */
- X }
- X}
- X
- X
- Xmakekey( rkey)
- Xchar *rkey;
- X{
- X /** encrypt the key using the system routine 'crypt' **/
- X
- X char key[9], salt[2], *crypt();
- X
- X strncpy( key, rkey, 8);
- X key[8] = '\0';
- X salt[0] = key[0];
- X salt[1] = key[1];
- X#ifdef CRYPT
- X encrypted_key = crypt( key, salt);
- X#else
- X encrypted_key = key;
- X#endif
- X}
- X
- X/*
- X * shuffle rotors.
- X * shuffle each of the rotors indiscriminately. shuffle the half-rotor
- X * using a special obvious and not very tricky algorithm which is not as
- X * sophisticated as the one in crypt(1) and Oh God, I'm so depressed.
- X * After all this is done build the inverses of the rotors.
- X */
- X
- Xsetup()
- X{
- X register long i, j, k, temp;
- X long seed;
- X
- X for ( j = 0; j < RN; j++ ) {
- X p[j] = 0;
- X for ( i = 0; i < RS; i++ )
- X r[i][j] = i;
- X }
- X
- X seed = 123;
- X for ( i = 0; i < 13; i++) /* now personalize the seed */
- X seed = (seed*encrypted_key[i] + i) & RMASK;
- X
- X for ( i = 0; i < RS; i++ ) /* initialize shuffle vector */
- X h[i] = s[i] = i;
- X
- X for ( i = 0; i < RS; i++) { /* shuffle the vector */
- X seed = (5 * seed + encrypted_key[i%13]) & RMASK;;
- X k = ((seed % 65521) & RMASK) % RS;
- X temp = s[k];
- X s[k] = s[i];
- X s[i] = temp;
- X }
- X
- X for ( i = 0; i < RS; i += 2 ) { /* scramble the half-rotor */
- X temp = h[s[i]]; /* swap rotor elements ONCE */
- X h[s[i]] = h[s[i+1]];
- X h[s[i+1]] = temp;
- X }
- X
- X for ( j = 0; j < RN; j++) { /* select a rotor */
- X
- X for ( i = 0; i < RS; i++) { /* shuffle the vector */
- X seed = (5 * seed + encrypted_key[i%13]) & RMASK;;
- X k = ((seed % 65521) & RMASK) % RS;
- X temp = r[i][j];
- X r[i][j] = r[k][j];
- X r[k][j] = temp;
- X }
- X
- X for ( i = 0; i < RS; i++) /* create inverse rotors */
- X ir[r[i][j]][j] = i;
- X }
- X}
- SHAR_EOF
- chmod 0444 src/encode.c || echo "restore of src/encode.c fails"
- echo "x - extracting src/errno.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > src/errno.c &&
- X
- Xstatic char rcsid[] = "@(#)$Id: errno.c,v 2.3 89/03/25 21:46:14 syd Exp $";
- X
- X/*******************************************************************************
- X * The Elm Mail System - $Revision: 2.3 $ $State: Exp $
- X *
- X * Copyright (c) 1986, 1987 Dave Taylor
- X * Copyright (c) 1988, 1989 USENET Community Trust
- X *******************************************************************************
- X * Bug reports, patches, comments, suggestions should be sent to:
- X *
- X * Syd Weinstein, Elm Coordinator
- X * elm@dsinc.UUCP dsinc!elm
- X *
- X *******************************************************************************
- X * $Log: errno.c,v $
- X * Revision 2.3 89/03/25 21:46:14 syd
- X * Initial 2.2 Release checkin
- X *
- X *
- X ******************************************************************************/
- X
- X/** This routine maps error numbers to error names and error messages.
- X These are all directly ripped out of the include file errno.h, and
- X are HOPEFULLY standardized across the different breeds of Unix!!
- X
- X If (alas) yours are different, you should be able to use awk to
- X mangle your errno.h file quite simply...
- X
- X**/
- X
- X#include "headers.h"
- X
- Xchar *err_name[] = {
- X/* 0 */ "NOERROR", "No error status currently",
- X/* 1 */ "EPERM", "Not super-user",
- X/* 2 */ "ENOENT", "No such file or directory",
- X/* 3 */ "ESRCH", "No such process",
- X/* 4 */ "EINTR", "Interrupted system call",
- X/* 5 */ "EIO", "I/O error",
- X/* 6 */ "ENXIO", "No such device or address",
- X/* 7 */ "E2BIG", "Arg list too long",
- X/* 8 */ "ENOEXEC", "Exec format error",
- X/* 9 */ "EBADF", "Bad file number",
- X/* 10 */ "ECHILD", "No children",
- X/* 11 */ "EAGAIN", "No more processes",
- X/* 12 */ "ENOMEM", "Not enough core",
- X/* 13 */ "EACCES", "Permission denied",
- X/* 14 */ "EFAULT", "Bad address",
- X/* 15 */ "ENOTBLK", "Block device required",
- X/* 16 */ "EBUSY", "Mount device busy",
- X/* 17 */ "EEXIST", "File exists",
- X/* 18 */ "EXDEV", "Cross-device link",
- X/* 19 */ "ENODEV", "No such device",
- X/* 20 */ "ENOTDIR", "Not a directory",
- X/* 21 */ "EISDIR", "Is a directory",
- X/* 22 */ "EINVAL", "Invalid argument",
- X/* 23 */ "ENFILE", "File table overflow",
- X/* 24 */ "EMFILE", "Too many open files",
- X/* 25 */ "ENOTTY", "Not a typewriter",
- X/* 26 */ "ETXTBSY", "Text file busy",
- X/* 27 */ "EFBIG", "File too large",
- X/* 28 */ "ENOSPC", "No space left on device",
- X/* 29 */ "ESPIPE", "Illegal seek",
- X/* 30 */ "EROFS", "Read only file system",
- X/* 31 */ "EMLINK", "Too many links",
- X/* 32 */ "EPIPE", "Broken pipe",
- X/* 33 */ "EDOM", "Math arg out of domain of func",
- X/* 34 */ "ERANGE", "Math result not representable",
- X/* 35 */ "ENOMSG", "No message of desired type",
- X/* 36 */ "EIDRM", "Identifier removed"
- X };
- X
- Xchar *strcpy();
- X
- Xchar *error_name(errnumber)
- Xint errnumber;
- X{
- X static char buffer[50];
- X
- X if (errnumber < 0 || errnumber > 36)
- X sprintf(buffer,"ERR-UNKNOWN (%d)", errnumber);
- X else
- X strcpy(buffer, err_name[2*errnumber]);
- X
- X return( (char *) buffer);
- X}
- X
- Xchar *error_description(errnumber)
- Xint errnumber;
- X{
- X static char buffer[50];
- X
- X if (errnumber < 0 || errnumber > 36)
- X sprintf(buffer,"Unknown error - %d - No description", errnumber);
- X else
- X strcpy(buffer, err_name[2*errnumber + 1]);
- X
- X return ( (char *) buffer);
- X}
- SHAR_EOF
- chmod 0444 src/errno.c || echo "restore of src/errno.c fails"
- echo "x - extracting src/expires.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > src/expires.c &&
- X
- Xstatic char rcsid[] = "@(#)$Id: expires.c,v 2.5 89/03/25 21:46:16 syd Exp $";
- X
- X/*******************************************************************************
- X * The Elm Mail System - $Revision: 2.5 $ $State: Exp $
- X *
- X * Copyright (c) 1986, 1987 Dave Taylor
- X * Copyright (c) 1988, 1989 USENET Community Trust
- X *******************************************************************************
- X * Bug reports, patches, comments, suggestions should be sent to:
- X *
- X * Syd Weinstein, Elm Coordinator
- X * elm@dsinc.UUCP dsinc!elm
- X *
- X *******************************************************************************
- X * $Log: expires.c,v $
- X * Revision 2.5 89/03/25 21:46:16 syd
- X * Initial 2.2 Release checkin
- X *
- X *
- X ******************************************************************************/
- X
- X/** This routine is written to deal with the Expires: header on the
- X individual mail coming in. What it does is to look at the date,
- X compare it to todays date, then set the EXPIRED flag on the
- X current message if it is true...
- X**/
- X
- X#include "headers.h"
- X
- X#ifdef BSD
- X# ifdef TMINSYS
- X# include <sys/time.h>
- X# else
- X# include <time.h>
- X# include <sys/types.h>
- X# include <sys/timeb.h>
- X# endif
- X#else
- X# include <time.h>
- X#endif
- X
- X#include <ctype.h>
- X
- X#ifdef BSD
- X#undef toupper
- X#undef tolower
- X#endif
- X
- Xprocess_expiration_date(date, message_status)
- Xchar *date;
- Xint *message_status;
- X{
- X struct tm *timestruct, *localtime();
- X long thetime, time();
- X char word1[WLEN], word2[WLEN], word3[WLEN], word4[WLEN], word5[WLEN];
- X int month = 0, day = 0, year = 0, hour = 0, minute = 0;
- X
- X /** first step is to break down the date given into MM DD YY HH MM
- X format: The possible formats for this field are, by example:
- X
- X (1) Mon, Jun 11, 87
- X (2) Mon, 11 Jun 87
- X (3) Jun 11, 87
- X (4) 11 Jun 87
- X (5) 11/06/87 <- ambiguous - will be ignored!!
- X (6) 8711061248GMT
- X (7) Mon, Jun 11, 87 12:48:35 GMT
- X
- X The reason #5 is considered ambiguous will be made clear
- X if we consider a message to be expired on Jan 4, 88:
- X 01/04/88 in the United States
- X 04/01/88 in Europe
- X so is the first field the month or the day? Standard prob.
- X **/
- X
- X sscanf(date, "%s %s %s %s %s",
- X word1, word2, word3, word4, word5);
- X
- X if (strlen(word5) != 0) { /* we have form #7 */
- X day = atoi(word1);
- X month = month_number(word2);
- X year = atoi(word3);
- X sscanf(word4, "%02d%*c%02d",
- X &hour, &minute);
- X }
- X else if (strlen(word2) == 0) { /* we have form #6 or form #5 */
- X if (isdigit(word1[1]) && isdigit(word1[2])) /* form #6 */
- X sscanf(word1, "%02d%02d%02d%02d%02d%*c",
- X &year, &month, &day, &hour, &minute);
- X }
- X else if (strlen(word4) != 0) { /* form #1 or form #2 */
- X if(isdigit(word2[0])) { /* form #2 */
- X month = month_number(word3);
- X day = atoi(word2);
- X year = atoi(word4);
- X } else { /* form #1 */
- X month = month_number(word2);
- X day = atoi(word3);
- X year = atoi(word4);
- X }
- X }
- X else if (! isdigit(word1[0])) { /* form #3 */
- X month = month_number(word1);
- X day = atoi(word2);
- X year = atoi(word3);
- X }
- X else { /* form #4 */
- X day = atoi(word1);
- X month = month_number(word2);
- X year = atoi(word3);
- X }
- X
- X if (day == 0 || year == 0)
- X return; /* we didn't get a valid date */
- X
- X /** next let's get the current time and date, please **/
- X
- X thetime = time((long *) 0);
- X
- X timestruct = localtime(&thetime);
- X
- X /** and compare 'em **/
- X
- X if (year > timestruct->tm_year)
- X return;
- X else if (year < timestruct->tm_year)
- X goto expire_message;
- X
- X if (month > timestruct->tm_mon)
- X return;
- X else if (month < timestruct->tm_mon)
- X goto expire_message;
- X
- X if (day > timestruct->tm_mday)
- X return;
- X else if (day < timestruct->tm_mday)
- X goto expire_message;
- X
- X if (hour > timestruct->tm_hour)
- X return;
- X else if (hour < timestruct->tm_hour)
- X goto expire_message;
- X
- X if (minute > timestruct->tm_min)
- X return;
- X
- Xexpire_message:
- X
- X /** it's EXPIRED! Yow!! **/
- X
- X (*message_status) |= EXPIRED;
- X}
- SHAR_EOF
- chmod 0444 src/expires.c || echo "restore of src/expires.c fails"
- echo "x - extracting src/file.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > src/file.c &&
- X
- Xstatic char rcsid[] = "@(#)$Id: file.c,v 2.19 89/03/25 21:46:17 syd Exp $";
- X
- X/*******************************************************************************
- X * The Elm Mail System - $Revision: 2.19 $ $State: Exp $
- X *
- X * Copyright (c) 1986, 1987 Dave Taylor
- X * Copyright (c) 1988, 1989 USENET Community Trust
- X *******************************************************************************
- X * Bug reports, patches, comments, suggestions should be sent to:
- X *
- X * Syd Weinstein, Elm Coordinator
- X * elm@dsinc.UUCP dsinc!elm
- X *
- X *******************************************************************************
- X * $Log: file.c,v $
- X * Revision 2.19 89/03/25 21:46:17 syd
- X * Initial 2.2 Release checkin
- X *
- X *
- X ******************************************************************************/
- X
- X/** File I/O routines, mostly the save to file command...
- X
- X**/
- X
- X#include "headers.h"
- X#include <ctype.h>
- X#include <errno.h>
- X
- X#ifdef BSD
- X#undef tolower
- X#endif
- X
- Xextern int errno;
- X
- Xchar *error_name(), *error_description(), *strcpy(), *getenv(), *nameof();
- Xunsigned long sleep();
- X
- Xint
- Xsave(redraw, silently, delete)
- Xint *redraw, silently, delete;
- X{
- X /** Save all tagged messages + current in a folder. If no messages
- X are tagged, save the current message instead! This routine
- X will return ZERO if the operation failed.
- X 'redraw' is set to TRUE iff we use the '?' and mess up
- X the screen. Pretty reasonable, eh? If "silently" is set,
- X then don't output the "D" character upon marking for
- X deletion...
- X If delete is set, then delete the saved messages, else
- X we are just copying the messages without deletion.
- X **/
- X
- X register int tagged = 0, i, oldstat, appending = 0;
- X int mesgnum; /* message whose address is used for save-by-name fn */
- X char filename[SLEN], address[SLEN], buffer[SLEN];
- X static char helpmsg[LONG_STRING];
- X FILE *save_file;
- X
- X oldstat = headers[current-1]->status; /* remember */
- X *redraw = FALSE;
- X
- X for (i=0; i < message_count; i++) {
- X if (ison(headers[i]->status, TAGGED)) {
- X if(!tagged)
- X mesgnum = i; /* first tagged msg - use this one for
- X * save-by-name folder name */
- X tagged++;
- X }
- X }
- X
- X if (tagged == 0) {
- X mesgnum = current-1; /* use this one for save-by-name folder name */
- X tagged = 1;
- X setit(headers[current-1]->status, TAGGED);
- X }
- X
- X dprint(4, (debugfile, "%d message%s tagged for saving (save)\n", tagged,
- X plural(tagged)));
- X
- X while (1) {
- X
- X PutLine2(LINES-2, 0, "%s message%s to: ",
- X (delete ? "Save" : "Copy"), plural(tagged));
- X
- X if (save_by_name) {
- X /** build default filename to save to **/
- X get_return(address, mesgnum);
- X get_return_name(address, buffer, TRUE);
- X if(strcmp(buffer, username) == 0) {
- X get_existing_address(address, mesgnum);
- X get_return_name(address, buffer, TRUE);
- X }
- X sprintf(filename, "=%s", buffer);
- X }
- X else
- X filename[0] = '\0';
- X
- X if (tagged > 1)
- X optionally_enter(filename, LINES-2, 19, FALSE, FALSE);
- X else
- X optionally_enter(filename, LINES-2, 18, FALSE, FALSE);
- X
- X
- X if (strlen(filename) == 0) { /** <return> means 'cancel', right? **/
- X headers[current-1]->status = oldstat; /* BACK! */
- X return(0);
- X }
- X
- X if (strcmp(filename,"?") == 0) { /* user asked for listing */
- X *redraw = TRUE; /* set the flag so we know what to do later */
- X if(!*helpmsg) { /* format helpmsg if not yet done */
- X
- X strcpy(helpmsg, "\n\r\n\rEnter: <nothing> to not ");
- X strcat(helpmsg, (delete ? "save" : "copy"));
- X strcat(helpmsg, " your message");
- X strcat(helpmsg, (plural(tagged) ? "s" : ""));
- X strcat(helpmsg, "\n\r '>' to ");
- X strcat(helpmsg, (delete ? "save" : "copy"));
- X strcat(helpmsg, " your message");
- X strcat(helpmsg, (plural(tagged) ? "s" : ""));
- X strcat(helpmsg, " to your \"received\" folder (");
- X strcat(helpmsg, nameof(recvd_mail));
- X strcat(helpmsg, ")\n\r '<' to ");
- X strcat(helpmsg, (delete ? "save" : "copy"));
- X strcat(helpmsg, " your message");
- X strcat(helpmsg, (plural(tagged) ? "s" : ""));
- X strcat(helpmsg, " to your \"sent\" folder (");
- X strcat(helpmsg, nameof(sent_mail));
- X strcat(helpmsg, ") \n\r a filename");
- X strcat(helpmsg, " (leading '=' denotes your folder directory ");
- X strcat(helpmsg, folders);
- X strcat(helpmsg, ").\n\r");
- X }
- X
- X list_folders(4, helpmsg);
- X continue;
- X }
- X
- X /* else - got a folder name - check it out */
- X if (! expand_filename(filename, TRUE)) {
- X dprint(2, (debugfile,
- X "Error: Failed on expansion of filename %s (save)\n",
- X filename));
- X continue;
- X }
- X if ((errno = can_open(filename, "a"))) {
- X error2("Cannot %s message to folder %s!",
- X delete ? "save":"copy", filename);
- X continue;
- X }
- X break; /* got a valid filename */
- X }
- X
- X save_file_stats(filename);
- X
- X if (access(filename,ACCESS_EXISTS)== 0) /* already there!! */
- X appending = 1;
- X
- X dprint(4,(debugfile, "Saving mail to folder '%s'...\n", filename));
- X
- X if ((save_file = fopen(filename,"a")) == NULL) {
- X dprint(2, (debugfile,
- X "Error: couldn't append to specified folder %s (save)\n",
- X filename));
- X error1("Couldn't append to folder %s!", filename);
- X headers[current-1]->status = oldstat; /* BACK! */
- X return(0);
- X }
- X
- X /* if we need a redraw that means index screen no longer present
- X * so whatever silently was, now it's true - we can't show those
- X * delete markings.
- X */
- X if(*redraw) silently = TRUE;
- X
- X for (i=0; i < message_count; i++) /* save each tagged msg */
- X if (headers[i]->status & TAGGED)
- X save_message(i, filename, save_file, (tagged > 1), appending++,
- X silently, delete);
- X
- X fclose(save_file);
- X
- X restore_file_stats(filename);
- X
- X if (tagged > 1)
- X error2("Message%s %s.", plural(tagged), delete ? "saved": "copied");
- X return(1);
- X}
- X
- Xint
- Xsave_message(number, filename, fd, pause, appending, silently, delete)
- Xint number, pause, appending, silently, delete;
- Xchar *filename;
- XFILE *fd;
- X{
- X /** Save an actual message to a folder. This is called by
- X "save()" only! The parameters are the message number,
- X and the name and file descriptor of the folder to save to.
- X If 'pause' is true, a sleep(2) will be done after the
- X saved message appears on the screen...
- X 'appending' is only true if the folder already exists
- X If 'delete' is true, mark the message for deletion.
- X **/
- X
- X register int save_current, is_new;
- X
- X dprint(4, (debugfile, "\tSaving message %d to folder...\n", number));
- X
- X save_current = current;
- X current = number+1;
- X
- X /* change status from NEW before copy and reset to what it was
- X * so that copy doesn't look new, but we can preserve new status
- X * of message in this mailfile. This is important because if
- X * user does a resync, we don't want NEW status to be lost.
- X * I.e. NEW becomes UNREAD when we "really" leave a mailfile.
- X */
- X if(is_new = ison(headers[number]->status, NEW))
- X clearit(headers[number]->status, NEW);
- X copy_message("", fd, FALSE, FALSE, TRUE);
- X if(is_new)
- X setit(headers[number]->status, NEW);
- X current = save_current;
- X
- X if (delete)
- X setit(headers[number]->status, DELETED); /* deleted, but ... */
- X clearit(headers[number]->status, TAGGED); /* not tagged anymore */
- X
- X if (appending)
- X error2("Message %d appended to folder %s.", number+1, filename);
- X else
- X error3("Message %d %s to folder %s.", number+1,
- X delete ? "saved" : "copied", filename);
- X
- X if (! silently)
- X show_new_status(number); /* update screen, if needed */
- X
- X if (pause && ! silently) sleep(2);
- X}
- X
- Xint
- Xexpand_filename(filename, use_cursor_control)
- Xchar *filename;
- Xint use_cursor_control;
- X{
- X /** Expands ~ to the user's home directory
- X =,+,% to the user's folder's directory
- X ! to the user's incoming mailbox
- X > to the user's received folder
- X < to the user's sent folder
- X shell variables (begun with $)
- X
- X Returns 1 upon proper expansions
- X 0 upon failed expansions
- X **/
- X
- X char temp_filename[SLEN], varname[SLEN], env_value[SLEN], *ptr;
- X register int i = 1, iindex = 0;
- X char *getenv();
- X
- X ptr = filename;
- X while (*ptr == ' ') ptr++; /* leading spaces GONE! */
- X strcpy(temp_filename, ptr);
- X
- X /** New stuff - make sure no illegal char as last **/
- X if (lastch(temp_filename) == '\n' || lastch(temp_filename) == '\r')
- X lastch(temp_filename) = '\0';
- X
- X if (temp_filename[0] == '~') {
- X sprintf(filename, "%s%s%s", home,
- X (temp_filename[1] != '/' && lastch(folders) != '/')? "/" : "",
- X &temp_filename[1]);
- X }
- X else if (temp_filename[0] == '=' || temp_filename[0] == '+' ||
- X temp_filename[0] == '%') {
- X sprintf(filename, "%s%s%s", folders,
- X (temp_filename[1] != '/' && lastch(folders) != '/')? "/" : "",
- X &temp_filename[1]);
- X }
- X else if (temp_filename[0] == '$') { /* env variable! */
- X while (isalnum(temp_filename[i]))
- X varname[iindex++] = temp_filename[i++];
- X varname[iindex] = '\0';
- X
- X env_value[0] = '\0'; /* null string for strlen! */
- X if (getenv(varname) != NULL)
- X strcpy(env_value, getenv(varname));
- X
- X if (strlen(env_value) == 0) {
- X dprint(3,(debugfile,
- X "Error: Can't expand environment variable $%s (%s)\n",
- X varname, "expand_filename"));
- X if(use_cursor_control)
- X error1("Don't know what the value of $%s is!", varname);
- X else
- X printf("\n\rDon't know what the value of $%s is!\n\r", varname);
- X return(0);
- X }
- X
- X sprintf(filename, "%s%s%s", env_value,
- X (temp_filename[i] != '/' && lastch(env_value) != '/')? "/" : "",
- X &temp_filename[1]);
- X
- X } else if (strcmp(temp_filename, "!") == 0) {
- X strcpy(filename, defaultfile);
- X } else if (strcmp(temp_filename, ">") == 0) {
- X strcpy(filename, recvd_mail);
- X } else if (strcmp(temp_filename, "<") == 0) {
- X strcpy(filename, sent_mail);
- X } else
- X strcpy(filename, temp_filename);
- X
- X return(1);
- X}
- SHAR_EOF
- chmod 0444 src/file.c || echo "restore of src/file.c fails"
- echo "x - extracting src/file_util.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > src/file_util.c &&
- X
- Xstatic char rcsid[] = "@(#)$Id: file_util.c,v 2.8 89/03/25 21:46:19 syd Exp $";
- X
- X/*******************************************************************************
- X * The Elm Mail System - $Revision: 2.8 $ $State: Exp $
- X *
- X * Copyright (c) 1986, 1987 Dave Taylor
- X * Copyright (c) 1988, 1989 USENET Community Trust
- X *******************************************************************************
- X * Bug reports, patches, comments, suggestions should be sent to:
- X *
- X * Syd Weinstein, Elm Coordinator
- X * elm@dsinc.UUCP dsinc!elm
- X *
- X *******************************************************************************
- X * $Log: file_util.c,v $
- X * Revision 2.8 89/03/25 21:46:19 syd
- X * Initial 2.2 Release checkin
- X *
- X *
- X ******************************************************************************/
- X
- X/** File oriented utility routines for ELM
- X
- X**/
- X
- X#include "headers.h"
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <ctype.h>
- X#include <errno.h>
- X
- X#ifdef BSD
- X# undef tolower
- X#endif
- X
- X#include <signal.h>
- X#include <errno.h>
- X
- X#ifdef BSD
- X# include <sys/wait.h>
- X#endif
- X
- Xextern int errno; /* system error number */
- X
- Xchar *error_name(), *error_description(), *strcpy(), *getlogin();
- Xlong fsize();
- X
- Xlong
- Xbytes(name)
- Xchar *name;
- X{
- X /** return the number of bytes in the specified file. This
- X is to check to see if new mail has arrived.... (also
- X see "fsize()" to see how we can get the same information
- X on an opened file descriptor slightly more quickly)
- X **/
- X
- X int ok = 1;
- X extern int errno; /* system error number! */
- X struct stat buffer;
- X
- X if (stat(name, &buffer) != 0)
- X if (errno != 2) {
- X dprint(1,(debugfile,
- X "Error: errno %s on fstat of file %s (bytes)\n",
- X error_name(errno), name));
- X Write_to_screen("\n\rError attempting fstat on file %s!\n\r",
- X 1, name);
- X Write_to_screen("** %s - %s. **\n\r", 2, error_name(errno),
- X error_description(errno));
- X emergency_exit();
- X }
- X else
- X ok = 0;
- X
- X return(ok ? (long) buffer.st_size : 0L);
- X}
- X
- Xint
- Xcan_access(file, mode)
- Xchar *file;
- Xint mode;
- X{
- X /** returns ZERO iff user can access file or "errno" otherwise **/
- X
- X int the_stat = 0, pid, w;
- X void _exit(), exit();
- X#ifdef BSD
- X union wait status;
- X#else
- X int status;
- X#endif
- X#ifdef VOIDSIG
- X register void (*istat)(), (*qstat)();
- X#else
- X register int (*istat)(), (*qstat)();
- X#endif
- X
- X if ((pid = vfork()) == 0) {
- X setgid(groupid);
- X setuid(userid); /** back to normal userid **/
- X
- X errno = 0;
- X
- X if (access(file, mode) == 0)
- X _exit(0);
- X else
- X _exit(errno != 0? errno : 1); /* never return zero! */
- X _exit(127);
- X }
- X
- X istat = signal(SIGINT, SIG_IGN);
- X qstat = signal(SIGQUIT, SIG_IGN);
- X
- X while ((w = wait(&status)) != pid && w != -1)
- X ;
- X
- X#ifdef BSD
- X the_stat = status.w_retcode;
- X#else
- X the_stat = status >> 8;
- X#endif
- X
- X signal(SIGINT, istat);
- X signal(SIGQUIT, qstat);
- X
- X return(the_stat);
- X}
- X
- Xint
- Xcan_open(file, mode)
- Xchar *file, *mode;
- X{
- X /** Returns 0 iff user can open the file. This is not
- X the same as can_access - it's used for when the file might
- X not exist... **/
- X
- X FILE *fd;
- X int the_stat = 0, pid, w, preexisted = 0;
- X void _exit(), exit();
- X#ifdef BSD
- X union wait status;
- X#else
- X int status;
- X#endif
- X#ifdef VOIDSIG
- X register void (*istat)(), (*qstat)();
- X#else
- X register int (*istat)(), (*qstat)();
- X#endif
- X
- X if ((pid = vfork()) == 0) {
- X setgid(groupid);
- X setuid(userid); /** back to normal userid **/
- X errno = 0;
- X if (access(file, ACCESS_EXISTS) == 0)
- X preexisted = 1;
- X if ((fd = fopen(file, mode)) == NULL)
- X _exit(errno);
- X else {
- X fclose(fd); /* don't just leave it open! */
- X if(!preexisted) /* don't leave it if this test created it! */
- X unlink(file);
- X _exit(0);
- X }
- X _exit(127);
- X }
- X
- X istat = signal(SIGINT, SIG_IGN);
- X qstat = signal(SIGQUIT, SIG_IGN);
- X
- X while ((w = wait(&status)) != pid && w != -1)
- X ;
- X
- X#ifdef BSD
- X the_stat = status.w_retcode;
- X#else
- X the_stat = status >> 8;
- X#endif
- X
- X signal(SIGINT, istat);
- X signal(SIGQUIT, qstat);
- X
- X return(the_stat);
- X}
- X
- Xint
- Xcopy(from, to)
- Xchar *from, *to;
- X{
- X /** this routine copies a specified file to the destination
- X specified. Non-zero return code indicates that something
- X dreadful happened! **/
- X
- X FILE *from_file, *to_file;
- X char buffer[VERY_LONG_STRING];
- X
- X if ((from_file = fopen(from, "r")) == NULL) {
- X dprint(1, (debugfile, "Error: could not open %s for reading (copy)\n",
- X from));
- X error1("Could not open file %s.", from);
- X return(1);
- X }
- X
- X if ((to_file = fopen(to, "w")) == NULL) {
- X dprint(1, (debugfile, "Error: could not open %s for writing (copy)\n",
- X to));
- X error1("Could not open file %s.", to);
- X return(1);
- X }
- X
- X while (fgets(buffer, VERY_LONG_STRING, from_file) != NULL)
- X fputs(buffer, to_file);
- X
- X fclose(from_file);
- X fclose(to_file);
- X chown( to, userid, groupid);
- X
- X return(0);
- X}
- X
- Xmove(from, to)
- Xchar *from, *to;
- X{
- X /** This routine moves a specified file to the destination
- X specified. It starts by trying to it all by link'ing.
- X **/
- X
- X FILE *from_file, *to_file;
- X char buffer[VERY_LONG_STRING];
- X
- X if (access(from, ACCESS_EXISTS) == -1) /* doesn't exist? */
- X return;
- X
- X /** does the dest file exist?? **/
- X
- X if (access(to, ACCESS_EXISTS) != -1) { /* dest DOES exist! */
- X printf("File %s already exists! Overwriting...\n", to);
- X (void) unlink(to);
- X }
- X
- X /** first off, let's try to link() it **/
- X
- X if (link(from, to) != -1) { /* yeah! */
- X return;
- X }
- X
- X /** nope. Let's open 'em both up and move the data... **/
- X
- X if ((from_file = fopen(from, "r")) == NULL) {
- X dprint(1, (debugfile, "Error: could not open %s for reading (copy)\n",
- X from));
- X printf("Could not open file %s for reading\n", from);
- X return;
- X }
- X
- X if ((to_file = fopen(to, "w")) == NULL) {
- X dprint(1, (debugfile, "Error: could not open %s for writing (copy)\n",
- X to));
- X printf("Could not open file %s for writing\n", to);
- X return;
- X }
- X
- X while (fgets(buffer, VERY_LONG_STRING, from_file) != NULL)
- X fputs(buffer, to_file);
- X
- X fclose(from_file);
- X fclose(to_file);
- X chown( to, userid, groupid);
- X
- X return;
- X}
- X
- X
- Xint
- Xappend(fd, filename)
- XFILE *fd;
- Xchar *filename;
- X{
- X /** This routine appends the specified file to the already
- X open file descriptor.. Returns non-zero if fails. **/
- X
- X FILE *my_fd;
- X char buffer[VERY_LONG_STRING];
- X
- X if ((my_fd = fopen(filename, "r")) == NULL) {
- X dprint(1, (debugfile,
- X "Error: could not open %s for reading (append)\n", filename));
- X return(1);
- X }
- X
- X while (fgets(buffer, VERY_LONG_STRING, my_fd) != NULL)
- X fputs(buffer, fd);
- X
- X fclose(my_fd);
- X
- X return(0);
- X}
- X
- X#define FORWARDSIGN "Forward to "
- Xint
- Xcheck_mailfile_size(mfile)
- Xchar *mfile;
- X{
- X /** Check to ensure we have mail. Only used with the '-z'
- X starting option. So we output a diagnostic if there is
- X no mail to read (including forwarding).
- X Return 0 if there is mail,
- X <0 if no permission to check,
- X 1 if no mail,
- X 2 if no mail because mail is being forwarded.
- X **/
- X
- X char firstline[SLEN];
- X int retcode;
- X struct stat statbuf;
- X FILE *fp;
- X
- X /* see if file exists first */
- X if (access(mfile, ACCESS_EXISTS) != 0)
- X retcode = 1; /* no file */
- X
- X /* exists - now see if user has read access */
- X else if (can_access(mfile, READ_ACCESS) != 0)
- X retcode = -1; /* no perm */
- X
- X /* read access - now see if file has a reasonable size */
- X else if ((fp = fopen(mfile, "r")) == NULL)
- X retcode = -1; /* no perm? should have detected this above! */
- X else if (fstat(fileno(fp), &statbuf) == -1)
- X retcode = -1; /* arg error! */
- X else if (statbuf.st_size < 2)
- X retcode = 1; /* empty or virtually empty, e.g. just a newline */
- X
- X /* file has reasonable size - see if forwarding */
- X else if (fgets (firstline, SLEN, fp) == NULL)
- X retcode = 1; /* empty? should have detected this above! */
- X else if (first_word(firstline, FORWARDSIGN))
- X retcode = 2; /* forwarding */
- X
- X /* not forwarding - so file must have some mail in it */
- X else
- X retcode = 0;
- X
- X /* now display the appropriate message if there isn't mail in it */
- X switch(retcode) {
- X
- X case -1: printf("You have no permission to read %s!\n\r", mfile);
- X break;
- X case 1: printf("You have no mail.\n\r");
- X break;
- X case 2: no_ret(firstline) /* remove newline before using */
- X printf("Your mail is being forwarded to %s.\n\r",
- X firstline + strlen(FORWARDSIGN));
- X break;
- X }
- X return(retcode);
- X}
- X
- Xcreate_readmsg_file()
- X{
- X /** Creates the file ".current" in the users home directory
- X for use with the "readmsg" program.
- X **/
- X
- X FILE *fd;
- X char buffer[SLEN];
- X
- X sprintf(buffer,"%s/%s", home, readmsg_file);
- X
- X if ((fd = fopen (buffer, "w")) == NULL) {
- X dprint(1, (debugfile,
- X "Error: couldn't create file %s - error %s (%s)\n",
- X buffer, error_name(errno), "create_readmsg_file"));
- X return; /* no error to user */
- X }
- X
- X if (current)
- X fprintf(fd, "%d\n", headers[current-1]->index_number);
- X else
- X fprintf(fd, "\n");
- X
- X fclose(fd);
- X chown( buffer, userid, groupid);
- X}
- X
- Xlong fsize(fd)
- XFILE *fd;
- X{
- X /** return the size of the current file pointed to by the given
- X file descriptor - see "bytes()" for the same function with
- X filenames instead of open files...
- X **/
- X
- X struct stat buffer;
- X
- X (void) fstat(fd, &buffer);
- X
- X return( (long) buffer.st_size );
- X}
- SHAR_EOF
- chmod 0444 src/file_util.c || echo "restore of src/file_util.c fails"
- echo "x - extracting src/fileio.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > src/fileio.c &&
- X
- Xstatic char rcsid[] = "@(#)$Id: fileio.c,v 2.16 89/03/25 21:46:21 syd Exp $";
- X
- X/*******************************************************************************
- X * The Elm Mail System - $Revision: 2.16 $ $State: Exp $
- X *
- X * Copyright (c) 1986, 1987 Dave Taylor
- X * Copyright (c) 1988, 1989 USENET Community Trust
- X *******************************************************************************
- X * Bug reports, patches, comments, suggestions should be sent to:
- X *
- X * Syd Weinstein, Elm Coordinator
- X * elm@dsinc.UUCP dsinc!elm
- X *
- X *******************************************************************************
- X * $Log: fileio.c,v $
- X * Revision 2.16 89/03/25 21:46:21 syd
- X * Initial 2.2 Release checkin
- X *
- X *
- X ******************************************************************************/
- X
- X/** File I/O routines, including deletion from the folder!
- X
- X**/
- X
- X#include "headers.h"
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <ctype.h>
- X#include <errno.h>
- X
- X#ifdef BSD
- X#undef tolower
- X#endif
- X
- Xextern int errno;
- X
- Xchar *error_name();
- X
- Xcopy_message(prefix, dest_file, remove_header, remote, update_status)
- Xchar *prefix;
- XFILE *dest_file;
- Xint remove_header, remote, update_status;
- X{
- X /** Copy current message to destination file, with optional 'prefix'
- X as the prefix for each line. If remove_header is true, it will
- X skip lines in the message until it finds the end of header line...
- X then it will start copying into the file... If remote is true
- X then it will append "remote from <hostname>" at the end of the
- X very first line of the file (for remailing)
- X
- X If "forwarding" is true then it'll do some nice things to
- X ensure that the forwarded message looks pleasant (e.g. remove
- X stuff like ">From " lines and "Received:" lines, and prefix
- X the entire message with "Forwarded message:\n" etc etc)
- X
- X If "update_status" is true then it will write a new Status:
- X line at the end of the headers and not copy any existing one.
- X **/
- X
- X char buffer[SLEN];
- X register struct header_rec *current_header = headers[current-1];
- X register int lines, front_line, next_front,
- X in_header = 1, first_line = TRUE, ignoring = FALSE;
- X int end_header = 0;
- X
- X /** get to the first line of the message desired **/
- X
- X if (fseek(mailfile, current_header->offset, 0) == -1) {
- X dprint(1, (debugfile,
- X "ERROR: Attempt to seek %d bytes into file failed (%s)",
- X current_header->offset, "copy_message"));
- X error1("ELM [seek] failed trying to read %d bytes into file.",
- X current_header->offset);
- X return;
- X }
- X
- X /* how many lines in message? */
- X
- X lines = current_header->lines;
- X
- X /* set up for forwarding just in case... */
- X
- X if (forwarding)
- X remove_header = FALSE;
- X
- X /* now while not EOF & still in message... copy it! */
- X
- X next_front = TRUE;
- X
- X while (lines) {
- X if (fgets(buffer, SLEN, mailfile) == NULL)
- X break;
- X
- X front_line = next_front;
- X
- X if(buffer[strlen(buffer)-1] == '\n') {
- X lines--; /* got a full line */
- X next_front = TRUE;
- X }
- X else
- X next_front = FALSE;
- X
- X if (front_line && ignoring)
- X ignoring = whitespace(buffer[0]);
- X
- X if (ignoring)
- X continue;
- X
- X if (first_line && forwarding) {
- X first_line = FALSE;
- X fprintf(dest_file, "Forwarded message:\n\n");
- X }
- X
- X /* are we still in the header? */
- X
- X if (in_header && front_line) {
- X if (strlen(buffer) < 2) {
- X in_header = 0;
- X end_header = -1;
- X } else if ((!isspace(*buffer)) && strchr(buffer, ':') == NULL) {
- X in_header = 0;
- X end_header = 1;
- X }
- X if (end_header) {
- X if (update_status) {
- X if (isoff(current_header->status, NEW)) {
- X if (ison(current_header->status, UNREAD))
- X fprintf(dest_file, "%sStatus: O\n", prefix);
- X else /* read */
- X#ifdef BSD
- X fprintf(dest_file, "%sStatus: OR\n", prefix);
- X#else
- X fprintf(dest_file, "%sStatus: RO\n", prefix);
- X#endif
- X update_status = FALSE; /* do it only once */
- X } /* else if NEW - indicate NEW with no Status: line. This is
- X * important if we resync a mailfile - we don't want
- X * NEW status lost when we copy each message out.
- X * It is the responsibility of the function that calls
- X * this function to unset NEW as appropriate to its
- X * reason for using this function to copy a message
- X */
- X
- X if (end_header > 0)
- X fprintf(dest_file, "\n"); /* add the missing newline for RFC 822 */
- X }
- X }
- X }
- X
- X if (in_header) {
- X /* Process checks while in header area */
- X
- X if (remove_header) {
- X ignoring = TRUE;
- X continue;
- X }
- X
- X /* add remote on to front? */
- X if (first_line && remote) {
- X no_ret(buffer);
- X fprintf(dest_file, "%s%s remote from %s\n",
- X prefix, buffer, hostname);
- X first_line = FALSE;
- X continue;
- X }
- X
- X if (!forwarding) {
- X if(! first_word(buffer, "Status:")) {
- X fprintf(dest_file, "%s%s", prefix, buffer);
- X continue;
- X }
- X else if (update_status) {
- X ignoring = TRUE;
- X continue; /* we will output a new Status: line later. */
- X } else {
- X fprintf(dest_file, "%sStatus: %s\n", prefix, buffer);
- X continue;
- X }
- X }
- X else { /* forwarding */
- X
- X if (first_word(buffer, "Received:" ) ||
- X first_word(buffer, ">From" ) ||
- X first_word(buffer, "Status:" ) ||
- X first_word(buffer, "Return-Path:"))
- X ignoring = TRUE;
- X else
- X fprintf(dest_file, "%s%s", prefix, buffer);
- X }
- X }
- X else { /* not in header */
- X /* Process checks that occur after the header area */
- X
- X if(first_word(buffer, "From ") && (real_from(buffer, NULL))) {
- X dprint(1, (debugfile,
- X "\n*** Internal Problem...Tried to add the following;\n"));
- X dprint(1, (debugfile,
- X " '%s'\nto output file (copy_message) ***\n", buffer));
- X break; /* STOP NOW! */
- X }
- X
- X fprintf(dest_file, "%s%s", prefix, buffer);
- X }
- X }
- X if (strlen(buffer) + strlen(prefix) > 1)
- X fprintf(dest_file, "\n"); /* blank line to keep mailx happy *sigh* */
- X}
- X
- X
- Xstatic struct stat saved_buf;
- Xstatic char saved_fname[SLEN];
- X
- Xint
- Xsave_file_stats(fname)
- Xchar *fname;
- X{
- X /* if fname exists, save the owner, group, mode and filename.
- X * otherwise flag nothing saved. Return 0 if saved, else -1.
- X */
- X
- X if(stat(fname, &saved_buf) != -1) {
- X (void)strcpy(saved_fname, fname);
- X dprint(2, (debugfile,
- X "** saved stats for file owner = %d group = %d mode = %o %s **\n",
- X saved_buf.st_uid, saved_buf.st_gid, saved_buf.st_mode, fname));
- X return(0);
- X }
- X dprint(2, (debugfile,
- X "** couldn't save stats for file %s [errno=%d] **\n",
- X fname, errno));
- X return(-1);
- X
- X}
- X
- Xrestore_file_stats(fname)
- Xchar *fname;
- X{
- X /* if fname matches the saved file name, set the owner and group
- X * of fname to the saved owner, group and mode,
- X * else to the userid and groupid of the user and to 700.
- X * Return -1 if the either mode or owner/group not set
- X * 0 if the default values were used
- X * 1 if the saved values were used
- X */
- X
- X int old_umask, i, new_mode, new_owner, new_group, ret_code;
- X
- X
- X new_mode = 0600;
- X new_owner = userid;
- X new_group = groupid;
- X ret_code = 0;
- X
- X if(strcmp(fname, saved_fname) == 0) {
- X new_mode = saved_buf.st_mode;
- X new_owner = saved_buf.st_uid;
- X new_group = saved_buf.st_gid;
- X ret_code = 1;
- X }
- X dprint(2, (debugfile, "** %s file stats for %s **\n",
- X (ret_code ? "restoring" : "setting"), fname));
- X
- X old_umask = umask(0);
- X if((i = chmod(fname, new_mode & 0777)) == -1)
- X ret_code = -1;
- X
- X dprint(2, (debugfile, "** chmod(%s, %.3o) returns %d [errno=%d] **\n",
- X fname, new_mode & 0777, i, errno));
- X
- X (void) umask(old_umask);
- X
- X#ifdef BSD
- X /*
- X * Chown is restricted to root on BSD unix
- X */
- X (void) chown(fname, new_owner, new_group);
- X#else
- X if((i = chown(fname, new_owner, new_group)) == -1)
- X ret_code = -1;
- X
- X dprint(2, (debugfile, "** chown(%s, %d, %d) returns %d [errno=%d] **\n",
- X fname, new_owner, new_group, i, errno));
- X#endif
- X
- X return(ret_code);
- X
- X}
- X
- X/** and finally, here's something for that evil trick: site hiding **/
- X
- X#ifdef SITE_HIDING
- X
- Xint
- Xis_a_hidden_user(specific_username)
- Xchar *specific_username;
- X{
- X /** Returns true iff the username is present in the list of
- X 'hidden users' on the system.
- X **/
- X
- X FILE *hidden_users;
- X char buffer[SLEN];
- X
- X /*
- X this line is deliberately inserted to ensure that you THINK
- X about what you're doing, and perhaps even contact the author
- X of Elm before you USE this option...
- X */
- X
- X if ((hidden_users = fopen (HIDDEN_SITE_USERS,"r")) == NULL) {
- X dprint(1, (debugfile,
- X "Couldn't open hidden site file %s [%s]\n",
- X HIDDEN_SITE_USERS, error_name(errno)));
- X return(FALSE);
- X }
- X
- X while (fscanf(hidden_users, "%s", buffer) != EOF)
- X if (strcmp(buffer, specific_username) == 0) {
- X dprint(3, (debugfile, "** Found user '%s' in hidden site file!\n",
- X specific_username));
- X fclose(hidden_users);
- X return(TRUE);
- X }
- X
- X fclose(hidden_users);
- X dprint(3, (debugfile,
- X "** Couldn't find user '%s' in hidden site file!\n",
- X specific_username));
- X
- X return(FALSE);
- X}
- X
- X#endif
- SHAR_EOF
- chmod 0444 src/fileio.c || echo "restore of src/fileio.c fails"
- echo "x - extracting src/forms.c (Text)"
- sed 's/^X//' << 'SHAR_EOF' > src/forms.c &&
- X
- Xstatic char rcsid[] = "@(#)$Id: forms.c,v 2.7 89/03/25 21:46:23 syd Exp $";
- X
- X/*******************************************************************************
- X * The Elm Mail System - $Revision: 2.7 $ $State: Exp $
- X *
- X * Copyright (c) 1986, 1987 Dave Taylor
- X * Copyright (c) 1988, 1989 USENET Community Trust
- X *******************************************************************************
- X * Bug reports, patches, comments, suggestions should be sent to:
- X *
- X * Syd Weinstein, Elm Coordinator
- X * elm@dsinc.UUCP dsinc!elm
- X *
- X *******************************************************************************
- X * $Log: forms.c,v $
- X * Revision 2.7 89/03/25 21:46:23 syd
- X * Initial 2.2 Release checkin
- X *
- X *
- X ******************************************************************************/
- X
- X/** This set of files supports the 'forms' options (AT&T Mail Forms) to
- X the mail system. The specs are drawn from a document from AT&T entitled
- X "Standard for Exchanging Forms on AT&T Mail", version 1.9.
- X
- X**/
- X
- X/** Some notes on the format of a FORM;
- X
- X First off, in AT&T Mail parlance, this program only supports SIMPLE
- X forms, currently. This means that while each form must have three
- X sections;
- X
- X [options-section]
- X ***
- X [form-image]
- X ***
- X [rules-section]
- X
- X this program will ignore the first and third sections completely. The
- X program will assume that the user merely enteres the form-image section,
- X and will append and prepend the triple asterisk sequences that *MUST*
- X be part of the message. The messages are also expected to have a
- X specific header - "Content-Type: mailform" - which will be added on all
- X outbound mail and checked on inbound...
- X**/
- X
- X#include "headers.h"
- X#include <errno.h>
- X
- Xextern int errno;
- X
- Xchar *error_name(), *strcat(), *strcpy();
- X
- Xcheck_form_file(filename)
- Xchar *filename;
- X{
- X /** This routine returns the number of fields in the specified file,
- X or -1 if an error is encountered. **/
- X
- X FILE *form;
- X char buffer[SLEN];
- X register int field_count = 0;
- X
- X if ((form = fopen(filename, "r")) == NULL) {
- X error2("Error %s trying to open %s to check fields!",
- X error_name(errno), filename);
- X return(-1);
- X }
- X
- X while (fgets(buffer, SLEN, form) != NULL) {
- X field_count += occurances_of(COLON, buffer);
- X }
- X
- X fclose(form);
- X
- X return(field_count);
- X}
- X
- Xformat_form(filename)
- Xchar *filename;
- X{
- X /** This routine accepts a validated file that is the middle
- X section of a form message and prepends and appends the appropriate
- X instructions. It's pretty simple.
- X This returns the number of forms in the file, or -1 on errors
- X **/
- X
- X FILE *form, *newform;
- X char newfname[SLEN], buffer[SLEN];
- X register form_count = 0;
- X
- X dprint(4, (debugfile, "Formatting form file '%s'\n", filename));
- X
- X /** first off, let's open the files... **/
- X
- X if ((form = fopen(filename, "r")) == NULL) {
- X error("Can't read the message to validate the form!");
- X dprint(1, (debugfile,
- X "** Error encountered opening file \"%s\" - %s (check_form) **\n",
- X filename, error_name(errno)));
- X return(-1);
- X }
- X
- X sprintf(newfname, "%s%d", temp_form_file, getpid());
- X
- X if ((newform = fopen(newfname, "w")) == NULL) {
- X error("Couldn't open newform file for form output!");
- X dprint(1, (debugfile,
- X "** Error encountered opening file \"%s\" - %s (check_form) **\n",
- X newfname, error_name(errno)));
- X return(-1);
- X }
- X
- X /** the required header... **/
- X
- X /* these are actually the defaults, but let's be sure, okay? */
- X
- X fprintf(newform, "WIDTH=78\nTYPE=SIMPLE\nOUTPUT=TEXT\n***\n");
- X
- X /** and let's have some fun transfering the stuff across... **/
- X
- X while (fgets(buffer, SLEN, form) != NULL) {
- X fputs(buffer, newform);
- X form_count += occurances_of(COLON, buffer);
- X }
- X
- X fprintf(newform, "***\n"); /* that closing bit! */
- X
- X fclose(form);
- X fclose(newform);
- X
- X if (form_count > 0) {
- X if (unlink(filename) != 0) {
- X error2("Error %s unlinking file %s.", error_name(errno), filename);
- X return(-1);
- X }
- X if (link(newfname, filename)) {
- X error3("Error %s linking %s to %s.", error_name(errno),
- X newfname, filename);
- X return(-1);
- X }
- X }
- X
- X if (unlink(newfname)) {
- X error2("Error %s unlinking file %s.", error_name(errno), newfname);
- X return(-1);
- X }
- X
- X return(form_count);
- SHAR_EOF
- echo "End of part 14"
- echo "File src/forms.c is continued in part 15"
- echo "15" > s2_seq_.tmp
- exit 0
-
-