home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume22
/
elm2.3
/
part15
< prev
next >
Wrap
Text File
|
1990-06-07
|
51KB
|
1,787 lines
Subject: v22i074: ELM mail syste, release 2.3, Part15/26
Newsgroups: comp.sources.unix
Approved: rsalz@uunet.UU.NET
X-Checksum-Snefru: 118986f3 ccb18622 cf2fa780 2f06860a
Submitted-by: Syd Weinstein <syd@dsinc.dsi.com>
Posting-number: Volume 22, Issue 74
Archive-name: elm2.3/part15
---- Cut Here and unpack ----
#!/bin/sh
# this is part 15 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file src/expires.c continued
#
CurArch=15
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/expires.c"
sed 's/^X//' << 'SHAR_EOF' >> src/expires.c
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
echo "File src/expires.c is complete"
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 4.1 90/04/28 22:43: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 Coordinator
X * elm@DSI.COM dsinc!elm
X *
X *******************************************************************************
X * $Log: file.c,v $
X * Revision 4.1 90/04/28 22:43:02 syd
X * checkin of Elm 2.3 as of Release PL0
X *
X *
X ******************************************************************************/
X
X/** File I/O routines, mostly the save to file command...
X
X**/
X
X#ifdef PWDINSYS
X# include <sys/pwd.h>
X#else
X# include <pwd.h>
X#endif
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[LONG_STRING], buffer[LONG_STRING];
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 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, FALSE);
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) && (!appending))
X sleep(2);
X}
X
Xint
Xexpand_filename(filename, use_cursor_control)
Xchar *filename;
Xint use_cursor_control;
X{
X /** Expands ~/ to the current user's home directory
X ~user/ to the home directory of "user"
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],
X env_value[SLEN], logname[SLEN], *ptr;
X register int iindex;
X struct passwd *pass, *getpwnam();
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 /** Strip off any trailing backslashes **/
X while (lastch(temp_filename) == '\\')
X lastch(temp_filename) = '\0';
X
X if (temp_filename[0] == '~') {
X if(temp_filename[1] == '/')
X sprintf(filename, "%s%s%s",
X home, (lastch(home) != '/' ? "/" : ""), &temp_filename[2]);
X else {
X for(ptr = &temp_filename[1], iindex = 0; *ptr && *ptr != '/'; ptr++, iindex++)
X logname[iindex] = *ptr;
X logname[iindex] = '\0';
X if((pass = getpwnam(logname)) == NULL) {
X dprint(3,(debugfile,
X "Error: Can't get home directory for %s (%s)\n",
X logname, "expand_filename"));
X if(use_cursor_control)
X error1("Don't know what the home directory of \"%s\" is!",
X logname);
X else
X printf(
X "\n\rDon't know what the home directory of \"%s\" is!\n\r",
X logname);
X return(0);
X }
X sprintf(filename, "%s%s", pass->pw_dir, ptr);
X }
X
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 for(ptr = &temp_filename[1], iindex = 0; isalnum(*ptr); ptr++, iindex++)
X varname[iindex] = *ptr;
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 (*ptr != '/' && lastch(env_value) != '/')? "/" : "", ptr);
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 4.1 90/04/28 22:43:04 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: file_util.c,v $
X * Revision 4.1 90/04/28 22:43:04 syd
X * checkin of Elm 2.3 as of Release PL0
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 struct stat stat_buf;
X void _exit(), exit();
X#if defined(BSD) && !defined(WEXITSTATUS)
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#ifdef VFORK
X if ((pid = vfork()) == 0) {
X#else
X if ((pid = fork()) == 0) {
X#endif
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#if defined(WEXITSTATUS)
X /* Use POSIX macro if defined */
X the_stat = WEXITSTATUS(status);
X#else
X#ifdef BSD
X the_stat = status.w_retcode;
X#else
X the_stat = status >> 8;
X#endif
X#endif /*WEXITSTATUS*/
X
X signal(SIGINT, istat);
X signal(SIGQUIT, qstat);
X if (the_stat == 0) {
X if (stat(file, &stat_buf) == 0) {
X w = stat_buf.st_mode & S_IFMT;
X#ifdef S_IFLNK
X if (w != S_IFREG && w != S_IFLNK)
X#else
X if (w != S_IFREG)
X#endif
X the_stat = 1;
X }
X }
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#if defined(BSD) && !defined(WEXITSTATUS)
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#ifdef VFORK
X if ((pid = vfork()) == 0) {
X#else
X if ((pid = fork()) == 0) {
X#endif
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 WEXITSTATUS
X the_stat = WEXITSTATUS(status);
X#else
X#ifdef BSD
X the_stat = status.w_retcode;
X#else
X the_stat = status >> 8;
X#endif
X#endif /*WEXITSTATUS*/
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 if (fputs(buffer, to_file) == EOF) {
X Write_to_screen("\n\rWrite failed to tempfile in copy\n\r", 0);
X perror(to);
X fclose(to_file);
X fclose(from_file);
X return(1);
X }
X fclose(from_file);
X if (fclose(to_file) == EOF) {
X Write_to_screen("\n\rClose failed on tempfile in copy\n\r", 0);
X perror(to);
X return(1);
X }
X chown( to, userid, groupid);
X
X return(0);
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 if (fputs(buffer, fd) == EOF) {
X Write_to_screen("\n\rWrite failed to tempfile in append\n\r", 0);
X perror(filename);
X rm_temps_exit();
X }
X
X if (fclose(my_fd) == EOF) {
X Write_to_screen("\n\rClose failed on tempfile in append\n\r", 0);
X perror(filename);
X rm_temps_exit();
X }
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(fileno(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 4.1 90/04/28 22:43: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: fileio.c,v $
X * Revision 4.1 90/04/28 22:43:06 syd
X * checkin of Elm 2.3 as of Release PL0
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(), *index();
X
Xcopy_message(prefix, dest_file, remove_header, remote, update_status, mmdf_head)
Xchar *prefix;
XFILE *dest_file;
Xint remove_header, remote, update_status, mmdf_head;
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.
X
X If "update_status" is true then it will write a new Status:
X line at the end of the headers. It never copies an 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#ifdef MMDF
X if (mmdf_head && strcmp(buffer, MSG_SEPERATOR) == 0)
X continue;
X#endif /* MMDF */
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 }
X else if (!isspace(*buffer)
X && index(buffer, ':') == NULL
X#ifdef MMDF
X && strcmp(buffer, MSG_SEPERATOR) != 0
X#endif /* MMDF */
X ) {
X in_header = 0;
X end_header = 1;
X } else if (in_header && remote && first_word(buffer, "Sender:")) {
X continue;
X }
X if (end_header) {
X if (update_status) {
X if (isoff(current_header->status, NEW)) {
X if (ison(current_header->status, UNREAD)) {
X if (fprintf(dest_file, "%sStatus: O\n", prefix) == EOF) {
X Write_to_screen("\n\rWrite in copy_message failed\n\r", 0);
X dprint(1, (debugfile,"\n*** Fprint failed on copy_message;\n"));
X rm_temps_exit();
X }
X } else /* read */
X#ifdef BSD
X if (fprintf(dest_file, "%sStatus: OR\n", prefix) == EOF) {
X#else
X if (fprintf(dest_file, "%sStatus: RO\n", prefix) == EOF) {
X#endif
X Write_to_screen("\n\rWrite in copy_message failed\n\r", 0);
X dprint(1, (debugfile,"\n*** Fprint failed on copy_message;\n"));
X rm_temps_exit();
X }
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 /*
X * add the missing newline for RFC 822
X */
X if (end_header > 0) {
X /* add the missing newline for RFC 822 */
X if (fprintf(dest_file, "\n") == EOF) {
X Write_to_screen("\n\rWrite in copy_message failed\n\r", 0);
X dprint(1, (debugfile,"\n*** Fprint failed on copy_message;\n"));
X rm_temps_exit();
X }
X }
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#ifndef MMDF
X if (fprintf(dest_file, "%s%s remote from %s\n",
X prefix, buffer, hostname) == EOF) {
X Write_to_screen("\n\rWrite in copy_message failed\n\r", 0);
X dprint(1, (debugfile,"\n*** Fprint failed on copy_message;\n"));
X rm_temps_exit();
X }
X#else
X if (first_word(buffer, "From ")) {
X if (fprintf(dest_file, "%s%s remote from %s\n",
X prefix, buffer, hostname) == EOF) {
X Write_to_screen("\n\rWrite in copy_message failed\n\r", 0);
X dprint(1, (debugfile,"\n*** Fprint failed on copy_message;\n"));
X rm_temps_exit();
X }
X } else {
X if (fprintf(dest_file, "%s%s\n", prefix, buffer) == EOF) {
X Write_to_screen("\n\rWrite in copy_message failed\n\r", 0);
X dprint(1, (debugfile,"\n*** Fprint failed on copy_message;\n"));
X rm_temps_exit();
X }
X }
X#endif /* MMDF */
X first_line = FALSE;
X continue;
X }
X
X if (!forwarding) {
X if(! first_word(buffer, "Status:")) {
X if (fprintf(dest_file, "%s%s", prefix, buffer) == EOF) {
X dprint(1, (debugfile,"\n*** Fprint failed on copy_message;\n"));
X rm_temps_exit();
X }
X continue;
X } else {
X ignoring = TRUE;
X continue; /* we will output a new Status: line later, if desired. */
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 if (fprintf(dest_file, "%s%s", prefix, buffer) == EOF) {
X dprint(1, (debugfile,"\n*** Fprint failed on copy_message;\n"));
X rm_temps_exit();
X }
X }
X }
X else { /* not in header */
X /* Process checks that occur after the header area */
X
X#ifndef MMDF
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#endif /* MMDF */
X
X if (fprintf(dest_file, "%s%s", prefix, buffer) == EOF) {
X Write_to_screen("\n\rWrite in copy_message failed\n\r", 0);
X dprint(1, (debugfile,"\n*** Fprint failed on copy_message;\n"));
X rm_temps_exit();
X }
X }
X }
X#ifndef MMDF
X if (strlen(buffer) + strlen(prefix) > 1)
X if (fprintf(dest_file, "\n") == EOF) { /* blank line to keep mailx happy *sigh* */
X Write_to_screen("\n\rWrite in copy_message failed\n\r", 0);
X dprint(1, (debugfile,"\n*** Fprint failed on copy_message;\n"));
X rm_temps_exit();
X }
X#endif /* MMDF */
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 4.1 90/04/28 22:43: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: forms.c,v $
X * Revision 4.1 90/04/28 22:43:08 syd
X * checkin of Elm 2.3 as of Release PL0
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%s%d", temp_dir, 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);
X}
X
Xint
Xmail_filled_in_form(address, subject)
Xchar *address, *subject;
X{
X /** This is the interesting routine. This one will read the
X message and prompt the user, line by line, for each of
X the fields...returns non-zero if it succeeds
X **/
X
X FILE *fd;
X register int lines = 0, count;
X char buffer[SLEN], *ptr;
X
X dprint(4, (debugfile,
X "replying to form with;\n\taddress=%s and\n\t subject=%s\n",
X address, subject));
X
X if (fseek(mailfile, headers[current-1]->offset, 0) == -1) {
X dprint(1, (debugfile,
X "Error: seek %ld resulted in errno %s (%s)\n",
X headers[current-1]->offset, error_name(errno),
X "mail_filled_in_form"));
X error2("ELM [seek] couldn't read %d bytes into file (%s).",
X headers[current-1]->offset, error_name(errno));
X return(0);
X }
X
X /* now we can fly along and get to the message body... */
X
X while ((ptr = fgets(buffer, SLEN, mailfile)) != NULL) {
X if (strlen(buffer) == 1) /* <return> only */
X break;
X else if (strncmp(buffer,"From ", 5) == 0 && lines++ > 0) {
X error("No form in this message!?");
X return(0);
X }
X }
X
X if (ptr == NULL) {
X error("No form in this message!?");
X return(0);
X }
X
X dprint(6, (debugfile, "- past header of form message -\n"));
X
X /* at this point we're at the beginning of the body of the message */
X
X /* now we can skip to the FORM-IMAGE section by reading through a
X line with a triple asterisk... */
X
X while ((ptr = fgets(buffer, SLEN, mailfile)) != NULL) {
X if (strcmp(buffer, "***\n") == 0)
X break; /* we GOT it! It's a miracle! */
X else if (strncmp(buffer, "From ",5) == 0) {
X error("Badly constructed form. Can't reply!");
X return(0);
X }
X }
X
X if (ptr == NULL) {
X error("Badly constructed form. Can't reply!");
X return(0);
X }
X
X dprint(6, (debugfile, "- skipped the non-forms-image stuff -\n"));
X
X /* one last thing - let's open the tempfile for output... */
X
X sprintf(buffer, "%s%s%d", temp_dir, temp_form_file, getpid());
X
X dprint(2, (debugfile,"-- forms sending using file %s --\n", buffer));
X
X if ((fd = fopen(buffer,"w")) == NULL) {
X error2("Can't open \"%s\" as output file! (%s).", buffer,
X error_name(errno));
X dprint(1, (debugfile,
X "** Error %s encountered trying to open temp file %s;\n",
X error_name(errno), buffer));
X return(0);
X }
X
X /* NOW we're ready to read the form image in and start prompting... */
X
X Raw(OFF);
X ClearScreen();
X
X while ((ptr = fgets(buffer, SLEN, mailfile)) != NULL) {
X dprint(9, (debugfile, "- read %s", buffer));
X if (strcmp(buffer, "***\n") == 0) /* end of form! */
X break;
X
X switch ((count = occurances_of(COLON, buffer))) {
X case 0 : printf("%s", buffer); /* output line */
X fprintf(fd, "%s", buffer);
X break;
X case 1 : if (buffer[0] == COLON) {
X printf(
X"(Enter as many lines as needed, ending with a '.' by itself on a line)\n");
X while (fgets(buffer, SLEN, stdin) != NULL) {
X no_ret(buffer);
X if (strcmp(buffer, ".") == 0)
X break;
X else
X fprintf(fd,"%s\n", buffer);
X }
X }
X else
X prompt_for_entries(buffer, fd, count);
X break;
X default: prompt_for_entries(buffer, fd, count);
X }
X }
X
X Raw(ON);
X fclose(fd);
X
X /** let's just mail this off now... **/
X
X mail_form(address, subject);
X
X return(1);
X}
X
Xprompt_for_entries(buffer, fd, entries)
Xchar *buffer;
XFILE *fd;
Xint entries;
X{
X /** deals with lines that have multiple colons on them. It must first
X figure out how many spaces to allocate for each field then prompts
X the user, line by line, for the entries...
X **/
X
X char mybuffer[SLEN], prompt[SLEN], spaces[SLEN];
X register int field_size, i, j, offset = 0, extra_tabs = 0;
X
X dprint(7, (debugfile,
X "prompt-for-multiple [%d] -entries \"%s\"\n", entries,
X buffer));
X
X strcpy(prompt, "No Prompt Available:");
X
X while (entries--) {
X j=0;
X i = chloc((char *) buffer + offset, COLON) + 1;
X while (j < i - 1) {
X prompt[j] = buffer[j+offset];
X j++;
X }
X prompt[j] = '\0';
X
X field_size = 0;
X
X while (whitespace(buffer[i+offset])) {
X if (buffer[i+offset] == TAB) {
X field_size += 8 - (i % 8);
X extra_tabs += (8 - (i % 8)) - 1;
X }
X else
X field_size += 1;
X i++;
X }
X
X offset += i;
X
X if (field_size == 0) /* probably last prompt in line... */
X field_size = 78 - (offset + extra_tabs);
X
X prompt_for_sized_entry(prompt, mybuffer, field_size);
X
X spaces[0] = ' '; /* always at least ONE trailing space... */
X spaces[1] = '\0';
X
X /* field_size-1 for the space spaces[] starts with */
X for (j = strlen(mybuffer); j < field_size-1; j++)
X strcat(spaces, " ");
X
X fprintf(fd, "%s: %s%s", prompt, mybuffer, spaces);
X fflush(fd);
X }
X
X fprintf(fd, "\n");
X}
X
Xprompt_for_sized_entry(prompt, buffer, field_size)
Xchar *prompt, *buffer;
Xint field_size;
X{
X /* This routine prompts for an entry of the size specified. */
X
X register int i;
X
X dprint(7, (debugfile, "prompt-for-sized-entry \"%s\" %d chars\n",
X prompt, field_size));
X
X printf("%s: ", prompt);
X
X for (i=0;i<field_size; i++)
X putchar('_');
X for (i=0;i<field_size; i++)
X putchar(BACKSPACE);
X fflush(stdout);
X
X fgets(buffer, SLEN, stdin);
X no_ret(buffer);
X
X if (strlen(buffer) > field_size) buffer[field_size-1] = '\0';
X}
SHAR_EOF
chmod 0444 src/forms.c || echo "restore of src/forms.c fails"
echo "x - extracting src/hdrconfg.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > src/hdrconfg.c &&
X
Xstatic char rcsid[] = "@(#)$Id: hdrconfg.c,v 4.1 90/04/28 22:43:10 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: hdrconfg.c,v $
X * Revision 4.1 90/04/28 22:43:10 syd
X * checkin of Elm 2.3 as of Release PL0
X *
X *
X ******************************************************************************/
X
X/** This file contains the routines necessary to be able to modify
X the mail headers of messages on the way off the machine. The
X headers currently supported for modification are:
X
X Subject:
X To:
X Cc:
X Bcc:
X Reply-To:
X Expires:
X Priority:
X In-Reply-To:
X Action:
X
X <user defined>
X**/
X
X#include "headers.h"
X
X#include <ctype.h>
X
X#ifdef BSD
X#undef toupper
X#undef tolower
X#endif
X
X/*
X * Allow three lines for To and Cc.
X * Allow two lines for Bcc, Subject and In-reply-to.
X * Allow one line for all others.
X */
X#define TO_LINE 2
X#define CC_LINE 5
X#define BCC_LINE 8
X#define SUBJECT_LINE 10
X#define REPLY_TO_LINE 12
X#define ACTION_LINE 13
X#define EXPIRES_LINE 14
X#define PRIORITY_LINE 15
X#define IN_REPLY_TO_LINE 16
X#define USER_DEFINED_HDR_LINE 18
X#define INSTRUCT_LINE LINES-4
X#define EXTRA_PROMPT_LINE LINES-3
X#define INPUT_LINE LINES-2
X#define ERROR_LINE LINES-1
X
Xstatic put_header();
X
X#define put_to() put_header(TO_LINE, 3, "To", expanded_to)
X#define put_cc() put_header(CC_LINE, 3, "Cc", expanded_cc)
X#define put_bcc() put_header(BCC_LINE, 2, "Bcc", expanded_bcc)
X#define put_subject() put_header(SUBJECT_LINE, 2, "Subject", subject)
X#define put_replyto() put_header(REPLY_TO_LINE, 1, "Reply-to", reply_to)
X#define put_action() put_header(ACTION_LINE, 1, "Action", action)
X#define put_expires() put_header(EXPIRES_LINE, 1, "Expires", expires)
X#define put_priority() put_header(PRIORITY_LINE, 1, "Priority", priority)
X#define put_inreplyto() put_header(IN_REPLY_TO_LINE, 2, \
X "In-reply-to", in_reply_to)
X#define put_userdefined() put_header(USER_DEFINED_HDR_LINE, 1, \
X (char *) NULL, user_defined_header)
X
X/* these are all defined in the mailmsg file! */
Xextern char subject[SLEN], in_reply_to[SLEN], expires[SLEN],
X action[SLEN], priority[SLEN], reply_to[SLEN], to[VERY_LONG_STRING],
X cc[VERY_LONG_STRING], expanded_to[VERY_LONG_STRING],
X expanded_cc[VERY_LONG_STRING], user_defined_header[SLEN],
X bcc[VERY_LONG_STRING], expanded_bcc[VERY_LONG_STRING];
X
Xchar *strip_commas(), *strcpy();
X
Xedit_headers()
X{
X /** Edit headers. **/
X int c, displayed_error = NO;
X
X /* Expand address-type headers for main part of display */
X /* (Unexpanded ones are used on the 'edit-line') */
X (void) build_address(strip_commas(to), expanded_to);
X (void) build_address(strip_commas(cc), expanded_cc);
X (void) build_address(strip_commas(bcc), expanded_bcc);
X
X display_headers();
X
X clearerr(stdin);
X
X while (TRUE) { /* forever */
X PutLine0(INPUT_LINE,0,"Choice: ");
X if (displayed_error)
X displayed_error = NO;
X else
X CleartoEOS();
X c = getchar();
X if (isupper(c))
X c = tolower(c);
X clear_error();
X if (c == EOF)
X return(0);
X switch (c) {
X case RETURN:
X case LINE_FEED:
X case 'q' : MoveCursor(INSTRUCT_LINE, 0);
X CleartoEOS();
X return(0);
X
X case ctrl('L') :
X display_headers();
X break;
X
X case 't' : PutLine0(INPUT_LINE, 0, "To: "); CleartoEOLN();
X if (optionally_enter(to, INPUT_LINE, 4, TRUE, FALSE) == -1)
X return(0);
X (void) build_address(strip_commas(to), expanded_to);
X put_to();
X break;
X
X case 's' : PutLine0(INPUT_LINE, 0, "Subject: "); CleartoEOLN();
X if (optionally_enter(subject,
X INPUT_LINE, 9, FALSE, FALSE) == -1)
X return(0);
X put_subject();
X break;
X
X case 'b' : PutLine0(INPUT_LINE, 0, "Bcc: "); CleartoEOLN();
X if (optionally_enter(bcc,
X INPUT_LINE, 5, TRUE, FALSE) == -1)
X return(0);
X (void) build_address(strip_commas(bcc), expanded_bcc);
X put_bcc();
X break;
X
X case 'c' : PutLine0(INPUT_LINE, 0, "Cc: "); CleartoEOLN();
X if (optionally_enter(cc, INPUT_LINE, 4, TRUE, FALSE) == -1)
X return(0);
SHAR_EOF
echo "End of part 15"
echo "File src/hdrconfg.c is continued in part 16"
echo "16" > s2_seq_.tmp
exit 0
exit 0 # Just in case...