syd@dsinc.UUCP (Syd Weinstein) (12/13/88)
---- Cut Here and unpack ----
#!/bin/sh
# this is part 14 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file src/leavembox.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/leavembox.c"
sed 's/^X//' << 'SHAR_EOF' >> src/leavembox.c
X * Fix for bug when you leave an empty mailfile for a non-existent one
X *
X * 88/08/27 ssw
X * add deluth patches
X *
X * 88/08/27 nicmad!brown (Mike Brown)
X * move extern int errno out of BSD ifdef
X *
X * 88/08/27 ssw
X * Changes due to alpha testing at dsinc
X * remove header file unistd - not present and not used
X *
X * Revision 2.2 88/07/21 09:58:48 edc
X * Final hacks and cleanup to the 2.1 alpha test release.
X *
X * Revision 2.1 88/06/28 12:52:07 edc
X * Added NOUTIMBUF define. Automatically defines utimbuf on non-bsd systems if
X * set. This is checked for in Configure.sh since it seems that many systems
X * don't define utimbuf for some non-obvious reason.
X *
X *
X * Revision 2.0 88/06/27 17:25:13 edc
X * The original 2.0 gamma sources as leaked from HP
X *
X *
X *
X ******************************************************************************/
X
X/** leave current mailbox, updating etc. as needed...
X
X**/
X
X#include "headers.h"
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <sys/file.h>
X#include <errno.h>
X
X#define ECHOIT 1 /* echo on for prompting! */
X
X/**********
X Since a number of machines don't seem to bother to define the utimbuf
X structure for some *very* obscure reason....
X
X Suprise, though, BSD has a different utime() entirely...*sigh*
X**********/
X
X#ifndef BSD
X# ifdef NOUTIMBUF
X
Xstruct utimbuf {
X time_t actime; /** access time **/
X time_t modtime; /** modification time **/
X };
X
X
X# endif NOUTIMBUF
X#endif BSD
X
Xextern int errno;
X
Xchar *error_name(), *error_description(), *strcpy();
Xunsigned short getegid();
Xunsigned long sleep();
X
Xint
Xleave_mbox(quitting)
Xint quitting;
X{
X /** Exit, saving files into mbox and deleting specified, or simply
X delete specified mail... If "quitting" is true, then output status
X regardless of what happens. Returns 1 iff mailfile was
X changed (ie messages deleted from file), 0 if not, and -1 if new
X mail has arrived in the meantime...
X **/
X
X FILE *temp;
X char outfile[SLEN], buffer[SLEN];
X struct stat buf; /* stat command */
X#ifdef BSD
X time_t utime_buffer[2]; /* utime command */
X#else
X struct utimbuf utime_buffer; /* utime command */
X#endif
X register int to_delete = 0, to_save = 0, i,
X pending = 0, number_saved = 0, last_sortby;
X char answer;
X long bytes();
X
X dprint(1, (debugfile, "\n\n-- leaving_mailbox --\n\n"));
X
X if (message_count == 0) {
X if (mbox_specified == 0) /* null mailbox lock? */
X unlock();
X
X return(FALSE); /* nothing changed */
X }
X
X for (i = 0; i < message_count; i++)
X if (ison(header_table[i].status, DELETED)) to_delete++;
X else to_save++;
X
X dprint(2, (debugfile,
X "Count: %d to delete and %d to save\n", to_delete, to_save));
X
X if (mbox_specified == 0)
X update_mailtime();
X
X if (hp_softkeys && question_me) {
X define_softkeys(YESNO); /* YES or NO on softkeys */
X softkeys_on();
X }
X
X if (to_delete) {
X if (always_del) /* set up the default answer... */
X answer = 'y';
X else
X answer = 'n';
X
X if (to_save) {
X if (question_me) {
X fflush(stdin);
X sprintf(buffer, "Delete message%s? (y/n) ", plural(to_delete));
X answer = want_to(buffer, answer, ECHOIT);
X }
X if (answer != 'y') {
X if (mbox_specified == 0) unlock(); /* remove lock! */
X dprint(3, (debugfile, "\tDelete message%s? - answer was NO\n",
X plural(to_delete)));
X error("Nothing deleted");
X return(FALSE); /* nothing was deleted! */
X }
X }
X else if (! to_save) { /* nothing to save!! */
X if (question_me) {
X fflush(stdin);
X answer = want_to("Delete all mail? (y/n) ", answer, ECHOIT);
X }
X if (answer != 'y') {
X if (mbox_specified == 0) unlock(); /* remove lock! */
X dprint(3, (debugfile, "Delete all mail? - answer was NO\n"));
X error("Nothing deleted");
X return(FALSE); /* nothing was deleted */
X }
X }
X }
X
X /** we have to check to see what the sorting order was...so that
X the order of saved messages is the same as the order of the
X messages originally (a subtle point...) **/
X
X if (sortby != RECEIVED_DATE) { /* what we want anyway! */
X last_sortby = sortby;
X sortby = RECEIVED_DATE;
X sort_mailbox(message_count, FALSE);
X sortby = last_sortby;
X }
X
X if (to_save && mbox_specified == 0) {
X if (always_leave) /* set up default answer */
X answer = 'y';
X else
X answer = 'n';
X if (question_me) {
X fflush(stdin);
X answer = want_to("Keep mail in incoming mailbox? (y/n) ",
X answer, ECHOIT);
X }
X if (answer == 'y') {
X if (to_delete) /* okay - keep undeleted as pending! */
X pending++;
X else { /* gag! nothing to delete, don't save! */
X unlock(); /* remove mailfile lock! */
X dprint(3, (debugfile,
X "Keep mail in incoming mailbox? -- answer was YES\n"));
X error("Mailbox unchanged");
X return(FALSE); /* nothing changed! */
X }
X }
X }
X
X /** next, let's lock the file up and make one last size check **/
X
X if (mbox_specified == 0) lock(OUTGOING);
X
X if (mailfile_size != bytes(infile)) {
X unlock();
X error("New mail has just arrived - resyncing");
X return(-1);
X }
X
X /** okay...now lets do it! **/
X
X if (to_save > 0) {
X if (to_delete > 0)
X sprintf(buffer ,"[%s %d message%s, and deleting %d]",
X pending? "keeping" : "storing",
X to_save, plural(to_save), to_delete);
X else if (quitting)
X sprintf(buffer,"[%s %s]",
X pending? "keeping" : "storing",
X to_save > 1? "all messages" : "message");
X else
X buffer[0] = '\0'; /* no string! */
X }
X else {
X if (to_delete > 0)
X sprintf(buffer, "[deleting all messages]");
X else if (quitting)
X sprintf(buffer, "[no messages to %s, and none to delete]",
X pending? "keep" : "save");
X else
X buffer[0] = '\0';
X }
X
X dprint(2, (debugfile, "Action: %s\n", buffer));
X
X error(buffer);
X
X if (! mbox_specified) {
X if (pending) { /* keep some messages pending! */
X sprintf(outfile,"%s%d", temp_mbox, getpid());
X unlink(outfile);
X }
X else if (mailbox_defined) /* save to specified mailbox */
X strcpy(outfile, mailbox);
X else /* save to $home/mbox */
X sprintf(outfile,"%s/mbox", home);
X }
X else {
X if (! to_delete) return(FALSE); /* no work to do! */
X sprintf(outfile, "%s%d", temp_file, getpid());
X unlink(outfile); /* ensure it's empty! */
X }
X
X if (to_save) {
X if ((errno = can_open(outfile, "a"))) {
X error1(
X "Permission to append to %s denied! Leaving mailbox intact\n",
X outfile);
X dprint(1, (debugfile,
X "Error: Permission to append to outfile %s denied!! (%s)\n",
X outfile, "leavembox"));
X dprint(1, (debugfile, "** %s - %s **\n", error_name(errno),
X error_description(errno)));
X unlock();
X return(0);
X }
X if ((temp = fopen(outfile,"a")) == NULL) {
X if (mbox_specified == 0)
X unlock(); /* remove mailfile lock! */
X dprint(1, (debugfile, "Error: could not append to file %s\n",
X outfile));
X dprint(1, (debugfile, "** %s - %s **\n", error_name(errno),
X error_description(errno)));
X sprintf(buffer, " Could not append to file %s! ",
X outfile);
X Centerline(LINES-1, buffer);
X emergency_exit();
X }
X
X for (i = 0; i < message_count; i++)
X if (! (header_table[i].status & DELETED)) {
X current = i+1;
X if (! number_saved++) {
X dprint(3, (debugfile, "Saving message%s #%d, ",
X plural(to_save), current));
X }
X else {
X dprint(3, (debugfile, "#%d, ", current));
X }
X copy_message("", temp, FALSE, FALSE);
X }
X fclose(temp);
X dprint(2, (debugfile, "\n\n"));
X }
X
X /* remove source file...either default mailbox or original copy of
X specified one! */
X
X if (stat(infile, &buf) != 0) { /* grab original times... */
X dprint(1, (debugfile, "Error: errno %s attempting to stat file %s\n",
X error_name(errno), infile));
X error3("Error %s (%s) on stat(%s)", error_name(errno),
X error_description(errno), infile);
X }
X
X fclose(mailfile); /* close the baby... */
X
X if (mailfile_size != bytes(infile)) {
X sort_mailbox(message_count, FALSE); /* display sorting order! */
X unlock();
X error("New mail has just arrived - resyncing...");
X return(-1);
X }
X
X
X if (infile != NULL)
X unlink(infile); /* and BLAMO! */
X
X if (to_save && (mbox_specified || pending)) {
X if (link(outfile, infile) != 0)
X if (errno == EXDEV ||
X errno == EEXIST ) { /** different file devices! Use copy! **/
X if (copy(outfile, infile) != 0) {
X dprint(1, (debugfile, "leavembox: copy(%s, %s) failed;",
X outfile, infile));
X dprint(1, (debugfile, "** %s - %s **\n", error_name(errno),
X error_description(errno)));
X error("couldn't modify mail file!");
X sleep(1);
X sprintf(infile,"%s/%s", home, unedited_mail);
X if (copy(outfile, infile) != 0) {
X dprint(1, (debugfile,
X "leavembox: couldn't copy to %s either!! Help;",
X infile));
X dprint(1, (debugfile, "** %s - %s **\n", error_name(errno),
X error_description(errno)));
X error("something godawful is happening to me!!!");
X emergency_exit();
X }
X else {
X dprint(1, (debugfile,
X "\nWoah! Confused - Saved mail in %s (leavembox)\n",
X infile));
X error1("saved mail in %s", infile);
X }
X }
X }
X else {
X dprint(1, (debugfile, "link(%s, %s) failed (leavembox)\n",
X outfile, infile));
X dprint(1, (debugfile, "** %s - %s **\n", error_name(errno),
X error_description(errno)));
X error2("link failed! %s - %s", error_name(errno),
X error_description(errno));
X emergency_exit();
X }
X
X unlink(outfile);
X restore_file_stats(infile);
X }
X else if (keep_empty_files) {
X sleep(1);
X error1("..keeping empty mail file '%s'..", infile);
X temp = fopen(infile, "w");
X fclose(temp);
X restore_file_stats(infile);
X }
X
X if (mbox_specified == 0) {
X if (! pending) { /* if none still being saved */
X temp = fopen(infile, "w");
X fclose(temp);
X }
X
X restore_file_stats(infile);
X
X /* let's set the access times of the new mail file to be
X the same as the OLD one (still sitting in 'buf') ! */
X
X#ifdef BSD
X utime_buffer[0] = buf.st_atime;
X utime_buffer[1] = buf.st_mtime;
X#else
X utime_buffer.actime = buf.st_atime;
X utime_buffer.modtime= buf.st_mtime;
X#endif
X
X#ifdef BSD
X if (utime(infile, utime_buffer) != 0) {
X#else
X if (utime(infile, &utime_buffer) != 0) {
X#endif
X dprint(1, (debugfile,
X "Error: encountered error doing utime (leavmbox)\n"));
X dprint(1, (debugfile, "** %s - %s **\n", error_name(errno),
X error_description(errno)));
X error2("Error %s trying to change file %s access time",
X error_name(errno), infile);
X }
X
X unlock(); /* remove the lock on the file ASAP! */
X
X /** finally, let's change the ownership of the default
X outgoing mailbox, if needed **/
X
X if (to_save)
X chown(outfile, userid, groupid);
X }
X
X mailfile_size = bytes(infile);
X return(to_delete);
X}
X
Xchar lock_name[SLEN];
Xint we_created_lock = 0; /* set to true iff we create it */
X
Xlock(direction)
Xint direction;
X{
X /** Create lock file to ensure that we don't get any mail
X while altering the mailbox contents!
X If it already exists sit and spin until
X either the lock file is removed...indicating new mail
X or
X we have iterated MAX_ATTEMPTS times, in which case we
X either fail or remove it and make our own (determined
X by if REMOVE_AT_LAST is defined in header file
X
X If direction == INCOMING then DON'T remove the lock file
X on the way out! (It'd mess up whatever created it!).
X **/
X
X register int iteration = 0, lock_fd;
X
X sys_lock_file(lock_name, username);
X lock_fd = open(lock_name, O_WRONLY | O_CREAT | O_EXCL, 0777);
X
X if (lock_fd < 0 && errno == EACCES) {
X if (direction == OUTGOING) {
X dprint(1, (debugfile,
X "Error encountered attempting to create lock %s\n",
X lock_name));
X dprint(1, (debugfile, "** %s - %s **\n", error_name(errno),
X error_description(errno)));
X MoveCursor(LINES, 0);
X printf(
X "\n\rError encountered while attempting to create lock file %s;\n\r",
X lock_name);
X printf("** %s - %s **\n\r\n\r", error_name(errno),
X error_description(errno));
X leave();
X }
X else { /* permission denied in the middle? Odd... */
X dprint(1, (debugfile,
X "Can't create lock file: creat(%s) raises error %s (lock)\n",
X lock_name, error_name(errno)));
X leave(error1(
X "Can't create lock file! I need write permission in \"%s\"\n\r",
X mailhome));
X }
X }
X
X /** if lock_fd is not a valid file descriptor at this point, it
X means that we're circling because someone *else* has the
X file descriptor. We'll keep iterating until something
X new and exciting happens or we give up.
X **/
X
X while (lock_fd < 0 && iteration++ < MAX_ATTEMPTS) {
X
X dprint(2, (debugfile,"File '%s' already exists! Waiting...(lock)\n",
X lock_name));
X
X if (direction == INCOMING) {
X if (iteration == 1)
X PutLine0(LINES, 0, "Mail being received...\t\twaiting...1 ");
X else
X printf("%d ", iteration);
X fflush(stdout);
X }
X else
X error1(" Attempt #%d: Mail being received...waiting ", iteration);
X sleep(5);
X
X lock_fd = open(lock_name, O_WRONLY | O_CREAT | O_EXCL, 0777);
X }
X
X if (lock_fd < 0) { /* we tried. We really did. But noooo */
X
X#ifdef REMOVE_AT_LAST
X
X /** time to waste the lock file! Must be there in error! **/
X
X dprint(2, (debugfile,
X "Warning: I'm giving up waiting - removing lock file(lock)\n"));
X if (direction == INCOMING)
X PutLine0(LINES, 0,"\nTimed out - removing current lock file...");
X else
X error("Throwing away the current lock file!");
X
X if (unlink(lock_name) != 0) {
X dprint(1, (debugfile,
X "Error %s (%s)\n\ttrying to unlink file %s (%s)\n",
X error_name(errno), error_description(errno), lock_name));
X PutLine1(LINES, 0,
X "\n\rI couldn't remove the current lock file %s\n\r",
X lock_name);
X PutLine2(LINES, 0, "** %s - %s **\n\r", error_name(errno),
X error_description(errno));
X if (direction == INCOMING)
X leave();
X else
X emergency_exit();
X }
X
X /* everything is okay, so lets act as if nothing had happened... */
X
X#else
X
X /* Okay...we die and leave, not updating the mailfile mbox or
X any of those! */
X
X if (direction == INCOMING) {
X PutLine1(LINES, 0, "\n\r\n\rGiving up after %d iterations...\n\r",
X iteration);
X PutLine0(LINES, 0,
X "\n\rPlease try to read your mail again in a few minutes.\n\r\n\r");
X dprint(1, (debugfile,
X "Warning: bailing out after %d iterations...(lock)\n",
X iteration));
X leave_locked(0);
X }
X else {
X dprint(1, (debugfile,
X "Warning: after %d iterations, timed out! (lock)\n",
X iteration));
X leave(error("Timed out on lock file reads. Leaving program."));
X }
X
X#endif
X }
X
X /* if we get here we've created the lock file, so lets just split */
X
X close(lock_fd); /* close it. We don't want to KEEP the thing! */
X}
X
Xunlock()
X{
X /** Remove the lock file! This must be part of the interrupt
X processing routine to ensure that the lock file is NEVER
X left sitting in the mailhome directory! **/
X
X (void) unlink(lock_name);
X}
SHAR_EOF
echo "File src/leavembox.c is complete"
chmod 0444 src/leavembox.c || echo "restore of src/leavembox.c fails"
echo "x - extracting src/limit.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > src/limit.c &&
X
Xstatic char rcsid[] = "@(#)$Id: limit.c,v 2.1 88/07/21 09:58:51 edc Exp $";
X
X/*******************************************************************************
X * The Elm Mail System - $Revision: 2.1 $ $State: Exp $
X *
X * Copyright (c) 1986 Dave Taylor
X *******************************************************************************
X * Bug reports, patches, comments, suggetions should be sent to:
X *
X * Syd Weinstein, Elm Corrdinator
X * syd@dsinc.UUCP dsinc!syd
X *
X *******************************************************************************
X * $Log: limit.c,v $
X * Revision 2.1 88/07/21 09:58:51 edc
X * checked in with -k by syd at 88.09.15.20.28.48.
X *
X * Revision 2.1 88/07/21 09:58:51 edc
X * Final hacks and cleanup to the 2.1 alpha test release.
X *
X * Revision 2.0 88/06/27 17:25:14 edc
X * The original 2.0 gamma sources as leaked from HP
X *
X *
X *
X ******************************************************************************/
X
X/** This stuff is inspired by MH and dmail and is used to 'select'
X a subset of the existing mail in the folder based on one of a
X number of criteria. The basic tricks are pretty easy - we have
X as status of VISIBLE associated with each header stored in the
X (er) mind of the computer (!) and simply modify the commands to
X check that flag...the global variable `selected' is set to the
X number of messages currently selected, or ZERO if no select.
X**/
X
X#include "headers.h"
X
X#define TO 1
X#define FROM 2
X
Xchar *shift_lower();
X
Xint
Xlimit()
X{
X /** returns non-zero if we did enough to redraw the screen **/
X
X char criteria[STRING], first[STRING], rest[STRING];
X int last_current;
X
X if (selected) {
X PutLine1(LINES-2, 0,
X "Already have selection criteria - add more? (y/n) n%c",
X BACKSPACE);
X criteria[0] = ReadCh();
X if (tolower(criteria[0]) == 'y')
X PutLine0(LINES-3, COLUMNS-30, "Adding criteria...");
X else {
X selected = 0;
X PutLine0(LINES-3, COLUMNS-30, "Use '?' for help");
X }
X
X }
X
X PutLine1(LINES-2, 0, "Enter criteria: ");
X CleartoEOLN();
X
X criteria[0] = '\0';
X optionally_enter(criteria, LINES-2, 16, FALSE);
X
X if (strlen(criteria) == 0) return(0);
X
X split_word(criteria, first, rest);
X
X if (equal(first, "all")) {
X selected = 0;
X return(TRUE);
X }
X
X last_current = current;
X current = -1;
X
X if (equal(first, "subj") || equal(first, "subject"))
X selected = limit_selection(SUBJECT, rest, selected);
X else if (equal(first, "to"))
X selected = limit_selection(TO, rest, selected);
X else if (equal(first, "from"))
X selected = limit_selection(FROM, rest, selected);
X else {
X selected = 0;
X error1("Don't understand \"%s\" as a selection criteria!", first);
X sleep(2);
X }
X
X if (! selected)
X current = last_current;
X else
X current = visible_to_index(1)+1; /* map it and shift up 1 */
X
X if (! selected)
X set_error("no items selected");
X else {
X sprintf(first, "%d items selected", selected);
X set_error(first);
X }
X
X return(selected);
X}
X
Xint
Xlimit_selection(based_on, pattern, additional_criteria)
Xint based_on, additional_criteria;
Xchar *pattern;
X{
X /** Given the type of criteria, and the pattern, mark all
X non-matching headers as ! VISIBLE. If additional_criteria,
X don't mark as visible something that isn't currently!
X **/
X
X register int index, count = 0;
X
X dprint(2, (debugfile, "\n\n\n**limit on %d - '%s' - (%s) **\n\n",
X based_on, pattern, additional_criteria?"add'tl":"base"));
X
X if (based_on == SUBJECT) {
X for (index = 0; index < message_count; index++)
X if (! in_string(shift_lower(header_table[index].subject), pattern))
X header_table[index].status &= ~VISIBLE;
X else if (additional_criteria &&
X header_table[index].status | VISIBLE)
X header_table[index].status &= ~VISIBLE; /* shut down! */
X else { /* mark it as readable */
X header_table[index].status |= VISIBLE;
X count++;
X dprint(5, (debugfile,
X " Message %d (%s from %s) marked as visible\n",
X index, header_table[index].subject,
X header_table[index].from));
X }
X }
X else if (based_on == FROM) {
X for (index = 0; index < message_count; index++)
X if (! in_string(shift_lower(header_table[index].from), pattern))
X header_table[index].status &= ~VISIBLE;
X else if (additional_criteria &&
X header_table[index].status | VISIBLE)
X header_table[index].status &= ~VISIBLE; /* shut down! */
X else { /* mark it as readable */
X header_table[index].status |= VISIBLE;
X count++;
X dprint(5, (debugfile,
X " Message %d (%s from %s) marked as visible\n",
X index, header_table[index].subject,
X header_table[index].from));
X }
X }
X else if (based_on == TO) {
X for (index = 0; index < message_count; index++)
X if (! in_string(shift_lower(header_table[index].to), pattern))
X header_table[index].status &= ~VISIBLE;
X else if (additional_criteria &&
X header_table[index].status | VISIBLE)
X header_table[index].status &= ~VISIBLE; /* shut down! */
X else { /* mark it as readable */
X header_table[index].status |= VISIBLE;
X count++;
X dprint(5, (debugfile,
X " Message %d (%s from %s) marked as visible\n",
X index, header_table[index].subject,
X header_table[index].from));
X }
X }
X
X dprint(4, (debugfile, "\n** returning %d selected **\n\n\n", count));
X
X return(count);
X}
X
Xint
Xnext_visible(index)
Xint index;
X{
X /** Given 'index', this routine will return the actual index into the
X array of the NEXT visible message, or '-1' if none are visible
X **/
X
X register int remember_for_debug;
X remember_for_debug = index;
X
X index--; /* shift from 'current' to actual index */
X index++; /* make sure we don't bump into ourself! */
X
X while (index < message_count) {
X if (header_table[index].status & VISIBLE) {
X dprint(9, (debugfile, "[Next visible: given %d returning %d]\n",
X remember_for_debug, index+1));
X return(index+1);
X }
X index++;
X }
X
X return(-1);
X}
X
Xint
Xprevious_visible(index)
Xint index;
X{
X /** Just like 'next-visible', but backwards FIRST... */
X
X register int remember_for_debug;
X remember_for_debug = index;
X
X index -= 2; /* shift from 'current' to actual index, and skip us! */
X
X while (index > -1) {
X if (header_table[index].status & VISIBLE) {
X dprint(9, (debugfile, "[previous visible: given %d returning %d]",
X remember_for_debug, index+1));
X return(index+1);
X }
X index--;
X }
X
X return(-1);
X}
X
Xint
Xcompute_visible(message)
Xint message;
X{
X /** return the 'virtual' index of the specified message in the
X set of messages - that is, if we have the 25th message as
X the current one, but it's #2 based on our limit criteria,
X this routine, given 25, will return 2.
X **/
X
X register int index, count = 0;
X
X if (! selected) return(message);
X
X if (message < 0) message = 0; /* normalize */
X
X for (index = 0; index <= message; index++)
X if (header_table[index].status & VISIBLE)
X count++;
X
X dprint(4, (debugfile,
X "[compute-visible: displayed message %d is actually %d]\n",
X count, message));
X
X return(count);
X}
X
Xint
Xvisible_to_index(message)
Xint message;
X{
X /** Given a 'virtual' index, return a real one. This is the
X flip-side of the routine above, and returns (message_count+1)
X if it cannot map the virtual index requested (too big)
X **/
X
X register int index = 0, count = 0;
X
X for (index = 0; index < message_count; index++) {
X if (header_table[index].status & VISIBLE)
X count++;
X if (count == message) {
X dprint(4, (debugfile,
X "visible-to-index: (up) index %d is displayed as %d\n",
X message, index));
X return(index);
X }
X }
X
X dprint(4, (debugfile, "index %d is NOT displayed!\n", message));
X
X return(message_count+1);
X}
SHAR_EOF
chmod 0444 src/limit.c || echo "restore of src/limit.c fails"
echo "x - extracting src/mailmsg1.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > src/mailmsg1.c &&
X
Xstatic char rcsid[] = "@(#)$Id: mailmsg1.c,v 2.1 88/09/15 20:28:51 syd Exp $";
X
X/*******************************************************************************
X * The Elm Mail System - $Revision: 2.1 $ $State: Exp $
X *
X * Copyright (c) 1986 Dave Taylor
X *******************************************************************************
X * Bug reports, patches, comments, suggetions should be sent to:
X *
X * Syd Weinstein, Elm Corrdinator
X * syd@dsinc.UUCP dsinc!syd
X *
X *******************************************************************************
X * $Log: mailmsg1.c,v $
X * Revision 2.1 88/09/15 20:28:51 syd
X * checked in with -k by syd at 88.09.15.20.28.51.
X *
X * 88/09/13 Rob Bernardo <rob@pbhyf.PacBell.COM >
X * fixes how elm knows when to repaint the screen or not.
X *
X * 88/08/27 ssw
X * add deluth patches
X * add bcc strings always
X *
X * 88/08/27 ssw
X * split tolower and ReadCh due to macro calls
X *
X * Revision 2.1 88/07/21 09:58:53 edc
X * Final hacks and cleanup to the 2.1 alpha test release.
X *
X * Revision 2.0 88/06/27 17:25:15 edc
X * The original 2.0 gamma sources as leaked from HP
X *
X *
X *
X ******************************************************************************/
X
X/** Interface to allow mail to be sent to users. Part of ELM **/
X
X
X#include "headers.h"
X
X/** strings defined for the hdrconfg routines **/
X
Xchar 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 *format_long(), *strip_commas(), *tail_of_string(), *strcpy();
Xunsigned long sleep();
X
Xint
Xsendmsg(given_to, given_cc, given_subject, edit_message, form_letter, replying)
Xchar *given_to, *given_cc, *given_subject;
Xint edit_message, form_letter, replying;
X{
X /** Prompt for fields and then call mail() to send the specified
X message. If 'edit_message' is true then don't allow the
X message to be edited. 'form_letter' can be "YES" "NO" or "MAYBE".
X if YES, then add the header. If MAYBE, then add the M)ake form
X option to the last question (see mailsg2.c) etc. etc.
X if (replying) then add an In-Reply-To: header...
X Return TRUE if the main part of the screen has been changed
X (useful for knowing whether a redraw is needed.
X **/
X
X int copy_msg = FALSE, is_a_response = FALSE;
X
X /* First: zero all current global message strings */
X
X cc[0] = reply_to[0] = expires[0] = '\0';
X
X#ifdef ALLOW_BCC
X bcc[0] = expanded_bcc[0] = '\0';
X#endif
X
X in_reply_to[0] = expanded_to[0] = expanded_cc[0] = '\0';
X
X strcpy(subject, given_subject); /* copy given subject */
X strcpy(to, given_to); /* copy given to: */
X strcpy(cc, given_cc); /* and so on.. */
X
X /******* And now the real stuff! *******/
X
X copy_msg=copy_the_msg(&is_a_response); /* copy msg into edit buffer? */
X
X if (get_to(to, expanded_to) == 0) /* get the To: address and expand */
X return(0);
X
X /** are we by any chance just checking the addresses? **/
X
X if (check_only) {
X printf("Expands to: %s\n", format_long(expanded_to, 12));
X putchar('\r'); /* don't ask... */
X leave();
X }
X
X /** if we're batchmailing, let's send it and GET OUTTA HERE! **/
X
X if (mail_only && strlen(batch_subject) > 0) {
X strcpy(subject, batch_subject); /* get the batch subject */
X return(mail(FALSE, FALSE, TRUE, form_letter));
X }
X
X display_to(expanded_to); /* display the To: field on screen... */
X
X dprint(3, (debugfile, "\nMailing to %s\n", expanded_to));
X
X if (get_subject(subject) == 0) /* get the Subject: field */
X return(0);
X
X dprint(4, (debugfile, "Subject is %s\n", subject));
X
X if (prompt_for_cc) {
X if (get_copies(cc, expanded_to, expanded_cc, copy_msg) == 0)
X return(0);
X
X if (strlen(cc) > 0)
X dprint(4, (debugfile, "Copies to %s\n", expanded_cc));
X }
X
X if (mail_only) /* indicate next step... */
X printf("\n\r");
X else
X MoveCursor(LINES,0); /* so you know you've hit <return> ! */
X
X /** generate the In-Reply-To: header... **/
X
X if (is_a_response && replying)
X generate_reply_to(current-1);
X
X /* and mail that puppy outta here! */
X
X return(mail(copy_msg, edit_message, FALSE, form_letter));
X}
X
Xget_to(to_field, address)
Xchar *to_field, *address;
X{
X /** prompt for the "To:" field, expanding into address if possible.
X This routine returns ZERO if errored, or non-zero if okay **/
X
X if (strlen(to_field) == 0) {
X if (user_level < 2) {
X PutLine0(LINES-2, 0, "Send the message to: ");
X (void) optionally_enter(to_field, LINES-2, 21, FALSE);
X }
X else {
X PutLine0(LINES-2, 0, "To: ");
X (void) optionally_enter(to_field, LINES-2, 4, FALSE);
X }
X if (strlen(to_field) == 0) {
X ClearLine(LINES-2);
X return(0);
X }
X (void) build_address(strip_commas(to_field), address);
X }
X else if (mail_only)
X (void) build_address(strip_commas(to_field), address);
X else
X strcpy(address, to_field);
X
X if (strlen(address) == 0) { /* bad address! Removed!! */
X if (! mail_only)
X ClearLine(LINES-2);
X return(0);
X }
X
X return(1); /* everything is okay... */
X}
X
Xget_subject(subject_field)
Xchar *subject_field;
X{
X char ch;
X
X /** get the subject and return non-zero if all okay... **/
X int len = 9;
X
X if (mail_only) {
X printf("Subject: ");
X fflush(stdout);
X }
X else
X if (user_level == 0) {
X PutLine0(LINES-2,0,"Subject of message: ");
X len = 20;
X }
X else
X PutLine0(LINES-2,0,"Subject: ");
X
X CleartoEOLN();
X
X if (optionally_enter(subject_field, LINES-2, len, TRUE) == -1) {
X /** User hit the BREAK key! **/
X MoveCursor(LINES-2,0);
X CleartoEOLN();
X error("mail not sent");
X return(0);
X }
X
X if (strlen(subject_field) == 0) { /* zero length subject?? */
X if (mail_only)
X {
X printf("\n\rNo subject - Continue with message? (y/n) n%c",
X BACKSPACE);
X fflush(stdout);
X }
X else
X PutLine1(LINES-2,0,"No subject - Continue with message? (y/n) n%c",
X BACKSPACE);
X
X ch = ReadCh();
X if (tolower(ch) != 'y') { /* user says no! */
X if (mail_only) {
X printf("\n\r\n\rMail Cancelled!\n\r");
X fflush(stdout);
X return(0);
X }
X ClearLine(LINES-2);
X error("mail not sent");
X return(0);
X }
X else if (! mail_only) {
X PutLine0(LINES-2,0,"Subject: <none>");
X CleartoEOLN();
X }
X }
X
X return(1); /** everything is cruising along okay **/
X}
X
Xget_copies(cc_field, address, addressII, copy_message)
Xchar *cc_field, *address, *addressII;
Xint copy_message;
X{
X /** Get the list of people that should be cc'd, returning ZERO if
X any problems arise. Address and AddressII are for expanding
X the aliases out after entry!
X If 'bounceback' is nonzero, add a cc to ourselves via the remote
X site, but only if hops to machine are > bounceback threshold.
X If copy-message, that means that we're going to have to invoke
X a screen editor, so we'll need to delay after displaying the
X possibly rewritten Cc: line...
X **/
X
X if (mail_only)
X printf("\n\rCopies To: ");
X else
X PutLine0(LINES-1,0,"Copies To: ");
X
X fflush(stdout);
X
X if (optionally_enter(cc_field, LINES-1, 11, FALSE) == -1) {
X if (mail_only) {
X printf("\n\r\n\rMail not sent!\n\r");
X return(0);
X }
X ClearLine(LINES-2);
X ClearLine(LINES-1);
X
X error("mail not sent");
X return(0);
X }
X
X /** The following test is that if the build_address routine had
X reason to rewrite the entry given, then, if we're mailing only
X print the new Cc line below the old one. If we're not, then
X assume we're in screen mode and replace the incorrect entry on
X the line above where we are (e.g. where we originally prompted
X for the Cc: field).
X **/
X
X if (build_address(strip_commas(cc_field), addressII))
X if (mail_only) {
X printf("\rCopies To: %s\r\n", format_long(addressII, 4));
X fflush(stdout);
X }
X else {
X PutLine1(LINES-1, 11, "%s", addressII);
X if ((strcmp(editor, "builtin") != 0 && strcmp(editor, "none") != 0)
X || copy_message)
X sleep(2);
X }
X
X if (strlen(address) + strlen(addressII) > VERY_LONG_STRING) {
X dprint(2, (debugfile,
X "String length of \"To:\" + \"Cc\" too long! (get_copies)\n"));
X error("Too many people. Copies ignored");
X sleep(2);
X cc_field[0] = '\0';
X }
X
X return(1); /* everything looks okay! */
X}
X
Xint
Xcopy_the_msg(is_a_response)
Xint *is_a_response;
X{
X /** Returns True iff the user wants to copy the message being
X replied to into the edit buffer before invoking the editor!
X Sets "is_a_response" to true if message is a response...
X **/
X
X int answer = FALSE;
X
X if (strlen(to) > 0 && !mail_only) { /* predefined 'to' line! */
X if (auto_copy)
X answer = TRUE;
X else
X answer = (want_to("Copy message? (y/n) ", 'n', TRUE) == 'y');
X *is_a_response = TRUE;
X }
X else
X if (strlen(subject) > 0) /* predefined 'subject' (Forward) */
X answer = TRUE;
X
X return(answer);
X}
X
Xdisplay_to(address)
Xchar *address;
X{
X /** Simple routine to display the "To:" line according to the
X current configuration (etc)
X **/
X register int open_paren;
X
X if (mail_only)
X printf("To: %s\n\r", format_long(address, 3));
X else {
X if (names_only)
X if ((open_paren = chloc(address, '(')) > 0) {
X if (open_paren < chloc(address, ')')) {
X output_abbreviated_to(address);
X return;
X }
X }
X if (strlen(address) > 45)
X PutLine1(LINES-3, COLUMNS-50, "To: (%s)",
X tail_of_string(address, 40));
X else {
X if (strlen(address) > 30)
X PutLine1(LINES-3, COLUMNS-50, "To: %s", address);
X else
X PutLine1(LINES-3, COLUMNS-50, " To: %s", address);
X CleartoEOLN();
X }
X }
X}
X
Xoutput_abbreviated_to(address)
Xchar *address;
X{
X /** Output just the fields in parens, separated by commas if need
X be, and up to COLUMNS-50 characters...This is only used if the
X user is at level BEGINNER.
X **/
X
X char newaddress[LONG_STRING];
X register int index, newindex = 0, in_paren = 0;
X
X index = 0;
X
X while (newindex < 55 && index < strlen(address)) {
X if (address[index] == '(') in_paren++;
X else if (address[index] == ')') {
X in_paren--;
X if (index < strlen(address)-4) {
X newaddress[newindex++] = ',';
X newaddress[newindex++] = ' ';
X }
X }
X
X if (in_paren && address[index] != '(')
X newaddress[newindex++] = address[index];
X
X index++;
X }
X
X newaddress[newindex] = '\0';
X
X if (strlen(newaddress) > 50)
X PutLine1(LINES-3, COLUMNS-50, "To: (%s)",
X tail_of_string(newaddress, 40));
X else {
X if (strlen(newaddress) > 30)
X PutLine1(LINES-3, COLUMNS-50, "To: %s", newaddress);
X else
X PutLine1(LINES-3, COLUMNS-50, " To: %s", newaddress);
X CleartoEOLN();
X }
X
X return;
X}
SHAR_EOF
chmod 0444 src/mailmsg1.c || echo "restore of src/mailmsg1.c fails"
echo "x - extracting src/mailmsg2.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > src/mailmsg2.c &&
X
Xstatic char rcsid[] = "@(#)$Id: mailmsg2.c,v 2.1 88/09/15 20:28:54 syd Exp $";
X
X/*******************************************************************************
X * The Elm Mail System - $Revision: 2.1 $ $State: Exp $
X *
X * Copyright (c) 1986 Dave Taylor
X *******************************************************************************
X * Bug reports, patches, comments, suggetions should be sent to:
X *
X * Syd Weinstein, Elm Corrdinator
X * syd@dsinc.UUCP dsinc!syd
X *
X *******************************************************************************
X * $Log: mailmsg2.c,v $
X * Revision 2.1 88/09/15 20:28:54 syd
X * checked in with -k by syd at 88.09.15.20.28.55.
X *
X * 88/09/13 Rob Bernardo <rob@pbhyf.PacBell.COM >
X * fixes how elm knows when to repaint the screen or not.
X *
X * 88/09/02 Syd Weinstein
X * added version buffer
X *
X * 88/08/27 ssw
X * add deluth patches
X *
X * 88/08/27 ssw
X * split tolower and ReadCh due to macro calls
X *
X * Revision 2.1 88/07/21 09:58:55 edc
X * Final hacks and cleanup to the 2.1 alpha test release.
X *
X * Revision 2.0 88/06/27 17:25:17 edc
X * The original 2.0 gamma sources as leaked from HP
X *
X *
X *
X ******************************************************************************/
X
X/** Interface to allow mail to be sent to users. Part of ELM **/
X
X
X#include "headers.h"
X#include <errno.h>
X
Xextern int errno;
Xextern char version_buff[];
X
Xchar *error_name(), *error_description(), *strip_parens();
Xchar *strcat(), *strcpy();
Xchar *format_long(), *strip_commas(), *tail_of_string();
X
Xunsigned long sleep();
X
X#ifdef SITE_HIDING
X char *get_ctime_date();
X#endif
XFILE *write_header_info();
X
X/* these are all defined in the mailmsg1.c file! */
X
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
X#ifdef ALLOW_BCC
Xchar bcc[VERY_LONG_STRING], expanded_bcc[VERY_LONG_STRING];
X#endif
X
Xint gotten_key = 0;
X
Xchar *bounce_off_remote();
X
Xmail(copy_msg, edit_message, batch, form)
Xint copy_msg, edit_message, batch, form;
X{
X /** Given the addresses and various other miscellany (specifically,
X 'copy-msg' indicates whether a copy of the current message should
X be included, 'edit_message' indicates whether the message should
X be edited and 'batch' indicates that the message should be read
X from stdin) this routine will invoke an editor for the user and
X then actually mail off the message. 'form' can be YES, NO, or
X MAYBE. YES=add "Content-Type: mailform" header, MAYBE=add the
X M)ake form option to last question, and NO=don't worry about it!
X Also, if 'copy_msg' = FORM, then grab the form temp file and use
X that...
X Return TRUE if the main part of the screen has been changed
X (useful for knowing whether a redraw is needed.
X **/
X
X FILE *reply, *real_reply; /* second is post-input buffer */
X char filename[SLEN], filename2[SLEN], fname[SLEN],
X very_long_buffer[VERY_LONG_STRING];
X int ch;
X register int retransmit = FALSE;
X int already_has_text = FALSE; /* we need an ADDRESS */
X int old_raw;
X int need_redraw = 0;
X
X static int cancelled_msg = 0;
X
X dprint(4, (debugfile, "\nMailing to \"%s\" (with%s editing)\n",
X expanded_to, edit_message? "" : "out"));
X
X /** first generate the temporary filename **/
X
X sprintf(filename,"%s%d",temp_file, getpid());
X
X /** if possible, let's try to recall the last message? **/
X
X if (! batch && copy_msg != FORM && user_level != 0)
X retransmit = recall_last_msg(filename, copy_msg, &cancelled_msg,
X &already_has_text);
X
X /** if we're not retransmitting, create the file.. **/
X
X if (! retransmit)
X if ((reply = fopen(filename,"w")) == NULL) {
X dprint(1, (debugfile,
X "Attempt to write to temp file %s failed with error %s (mail)\n",
X filename, error_name(errno)));
X error2("Could not create file %s (%s)",filename,
X error_name(errno));
X return(need_redraw);
X }
X
X chown (filename, userid, groupid);
X
X if (batch) {
X Raw(OFF);
X if (isatty(fileno(stdin))) {
X fclose(reply); /* let edit-the-message open it! */
X printf("To: %s\nSubject: %s\n", expanded_to, subject);
X strcpy(editor, "none"); /* force inline editor */
X if (no_editor_edit_the_message(filename))
X return(need_redraw);/* confused? edit_the_msg returns 1 if bad */
X
X batch = FALSE; /* we've done it... **/
X edit_message = FALSE;
X
X Raw(ON);
X goto top_of_verify_loop;
X }
X else {
X while (gets(very_long_buffer) != NULL)
X fprintf(reply, "%s\n", very_long_buffer);
X }
X }
X
X if (copy_msg == FORM) {
X sprintf(fname, "%s%d", temp_form_file, getpid());
X fclose(reply); /* we can't retransmit a form! */
X if (access(fname,ACCESS_EXISTS) != 0) {
X error("couldn't find forms file!");
X return(need_redraw);
X }
X unlink(filename);
X dprint(4, (debugfile, "-- linking existing file %s to file %s --\n",
X fname, filename));
X link(fname, filename);
X unlink(fname);
X }
X else if (copy_msg && ! retransmit) /* if retransmit we have it! */
X if (edit_message) {
X copy_message(prefixchars, reply, noheader, FALSE);
X already_has_text = TRUE; /* we just added it, right? */
X }
X else
X copy_message("", reply, noheader, FALSE);
X
X if (!batch && ! retransmit && signature && copy_msg != FORM) {
X fprintf(reply, "\n--\n"); /* News 2.11 compatibility? */
X if (chloc(expanded_to, '!') == -1 && chloc(expanded_to, '@') == -1) {
X if (strlen(local_signature) > 0) {
X if (local_signature[0] != '/')
X sprintf(filename2, "%s/%s", home, local_signature);
X else
X strcpy(filename2, local_signature);
X (void) append(reply, filename2);
X already_has_text = TRUE; /* added signature... */
X }
X }
X else {
X if (remote_signature[0] != '/')
X sprintf(filename2, "%s/%s", home, remote_signature);
X else
X strcpy(filename2, remote_signature);
X (void) append(reply, filename2);
X already_has_text = TRUE; /* added signature... */
X }
X }
X
X if (! retransmit && copy_msg != FORM)
X if (reply != NULL)
X (void) fclose(reply); /* on replies, it won't be open! */
X
X /** Edit the message **/
X
X if (edit_message)
X create_readmsg_file(); /* for "readmsg" routine */
X
Xtop_of_verify_loop:
X
X ch = edit_message? 'e' : ' '; /* drop through if needed... */
X
X if (! batch) {
X do {
X switch (ch) {
X case 'e': if (edit_the_message(filename, already_has_text)) {
X cancelled_msg = TRUE;
X return(need_redraw);
X }
X need_redraw++;
X break;
X
X case 'h': if (mail_only)
X batch_header_editor();
X else
X edit_headers();
X need_redraw++;
X break;
X
X default : /* do nothing */ ;
X }
X
X /** ask that silly question again... **/
X
X if ((ch = verify_transmission(filename, &form)) == 'f') {
X cancelled_msg = TRUE;
X return(need_redraw);
X }
X
X } while (ch != 's');
X
X if (form == YES)
X if (format_form(filename) < 1) {
X cancelled_msg = TRUE;
X return(need_redraw);
X }
X
X if ((reply = fopen(filename,"r")) == NULL) {
X dprint(1, (debugfile,
X "Attempt to open file %s for reading failed with error %s (mail)\n",
X filename, error_name(errno)));
X error1("Could not open reply file (%s)", error_name(errno));
X return(need_redraw);
X }
X }
X else if ((reply = fopen(filename,"r")) == NULL) {
X dprint(1, (debugfile,
X "Attempt to open file %s for reading failed with error %s (mail)\n",
X filename, error_name(errno)));
X error1("Could not open reply file (%s)", error_name(errno));
X return(need_redraw);
X }
X
X cancelled_msg = FALSE; /* it ain't cancelled, is it? */
X
X /** ask about bounceback if the user wants us to.... **/
X
X if (uucp_hops(to) > bounceback && bounceback > 0 && copy_msg != FORM)
X if (verify_bounceback() == TRUE) {
X if (strlen(cc) > 0) strcat(expanded_cc, ", ");
X strcat(expanded_cc, bounce_off_remote(to));
X }
X
X /** grab a copy if the user so desires... **/
X
X if (auto_cc)
X save_copy(subject, expanded_to, expanded_cc, filename, to);
X
X /** write all header information into real_reply **/
X
X sprintf(filename2,"%s%d",temp_file, getpid()+1);
X
X /** try to write headers to new temp file **/
X
X dprint(6, (debugfile, "Composition file='%s' and mail buffer='%s'\n",
X filename, filename2));
X
X#ifdef ALLOW_BCC
X dprint(2,(debugfile,"--\nTo: %s\nCc: %s\nBcc: %s\nSubject: %s\n---\n",
X expanded_to, expanded_cc, expanded_bcc, subject));
X#else
X dprint(2,(debugfile,"---\nTo: %s\nCc: %s\nSubject: %s\n---\n",
X expanded_to, expanded_cc, subject));
X#endif
X
X if ((real_reply=write_header_info(filename2, expanded_to, expanded_cc,
X#ifdef ALLOW_BCC
X expanded_bcc,
X#endif
X form == YES)) == NULL) {
X
X /** IT FAILED!! MEIN GOTT! Use a dumb mailer instead! **/
X
X dprint(3, (debugfile, "** write_header failed: %s\n",
X error_name(errno)));
X
X if (cc[0] != '\0') /* copies! */
X sprintf(expanded_to,"%s %s", expanded_to, expanded_cc);
X
X sprintf(very_long_buffer, "( (%s -s \"%s\" %s ; %s %s) & ) < %s",
X mailx, subject, strip_parens(strip_commas(expanded_to)),
X remove, filename, filename);
X
X error1("Message sent using dumb mailer - %s", mailx);
X sleep(2); /* ensure time to see this prompt! */
X
X }
X else {
X copy_message_across(reply, real_reply);
X
X fclose(real_reply);
X
X if (cc[0] != '\0') /* copies! */
X sprintf(expanded_to,"%s %s", expanded_to, expanded_cc);
X
X#ifdef ALLOW_BCC
X if (bcc[0] != '\0') {
X strcat(expanded_to, " ");
X strcat(expanded_to, expanded_bcc);
X }
X#endif
X
X if (access(sendmail, EXECUTE_ACCESS) == 0
X#ifdef SITE_HIDING
X && ! is_a_hidden_user(username))
X#else
X )
X#endif
X if (!sendmail_verbose)
X {
X
X sprintf(very_long_buffer,"( (%s %s %s ; %s %s) & ) < %s",
X sendmail, smflags, strip_parens(strip_commas(expanded_to)),
X remove, filename2, filename2);
X }
X else
X {
X
X sprintf(very_long_buffer,"( (%s %s %s ; %s %s) & ) < %s",
X sendmail, smflagsv, strip_parens(strip_commas(expanded_to)),
X remove, filename2, filename2);
X }
X else /* oh well, use default mailer... */
X sprintf(very_long_buffer,"( (%s %s ; %s %s) & ) < %s",
X mailer, strip_parens(strip_commas(expanded_to)),
X remove, filename2, filename2);
X }
X
X fclose(reply);
X
X if (mail_only) {
X printf("sending mail...");
X fflush(stdout);
X }
X else {
X PutLine0(LINES,0,"sending mail...");
X CleartoEOLN();
X }
X
X system_call(very_long_buffer, SH);
X
X if (mail_only)
X printf("\rmail sent! \n\r");
X else
X set_error("Mail sent!");
X
X return(need_redraw);
X}
X
Xmail_form(address, subj)
Xchar *address, *subj;
X{
X /** copy the appropriate variables to the shared space... */
X
X strcpy(subject, subj);
X strcpy(to, address);
X strcpy(expanded_to, address);
X
X return(mail(FORM, NO, NO, NO));
X}
X
Xint
Xrecall_last_msg(filename, copy_msg, cancelled_msg, already_has_text)
Xchar *filename;
Xint copy_msg, *cancelled_msg, *already_has_text;
X{
X char ch;
X
X /** If filename exists and we've recently cancelled a message,
X the ask if the user wants to use that message instead! This
X routine returns TRUE if the user wants to retransmit the last
X message, FALSE otherwise...
X **/
X
X register int retransmit = FALSE;
X
X if (access(filename, EDIT_ACCESS) == 0 && *cancelled_msg) {
X Raw(ON);
X CleartoEOLN();
X if (copy_msg)
X PutLine1(LINES-1,0,"Recall last kept message instead? (y/n) y%c",
X BACKSPACE);
X else
X PutLine1(LINES-1,0,"Recall last kept message? (y/n) y%c",
X BACKSPACE);
X fflush(stdout);
X ch = ReadCh();
X if (tolower(ch) != 'n') {
X Write_to_screen("Yes",0);
X retransmit++;
X *already_has_text = TRUE;
X }
X else
X Write_to_screen("No",0);
X
X fflush(stdout);
X
X *cancelled_msg = 0;
X }
X
X return(retransmit);
X}
X
Xint
Xverify_transmission(filename, form_letter)
Xchar *filename;
Xint *form_letter;
X{
X /** Ensure the user wants to send this. This routine returns
X the character entered. Modified compliments of Steve Wolf
X to add the'dead.letter' feature.
X Also added form letter support...
X **/
X
X FILE *deadfd, *messagefd;
X char ch, buffer[LONG_SLEN], fname[SLEN];
X
X if (mail_only) {
X if (isatty(fileno(stdin))) {
Xbatch_reprompt:
X printf("\n\rYour options now are:\n\r");
X printf(
X "S)end the message, E)dit it again, change/add H)eaders or F)orget it\n\r");
X printf("\n\rWhat is your choice? s%c", BACKSPACE);
X fflush(stdin); /* wait for answer! */
X fflush(stdout);
X ch = ReadCh();
X ch = tolower(ch);
X
X if (ch == 'f') { /* forget this message! */
X printf("Forget\n\r\n\r");
X /** try to save it as a dead letter file **/
SHAR_EOF
echo "End of part 14"
echo "File src/mailmsg2.c is continued in part 15"
echo "15" > s2_seq_.tmp
exit 0
--
=====================================================================
Sydney S. Weinstein, CDP, CCP Elm Coordinator
Datacomp Systems, Inc. Voice: (215) 947-9900
{allegra,bellcore,bpa,vu-vlsi}!dsinc!syd FAX: (215) 938-0235