home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume18
/
mush6.4
/
part16
/
mail.c
Wrap
C/C++ Source or Header
|
1989-03-12
|
47KB
|
1,568 lines
/* @(#)mail.c (c) copyright 1986 (Dan Heller) */
#include "mush.h"
/*
* mail.c --
* do_mail() invoked from within mail. see function for description.
* abort_mail() suntools specific: resets panel items and so forth.
* start_file() creates the editing file and reset signal catching.
* mail_someone() called from do_mail() or from the shell.
* add_to_letter() adds the next line to letter --determine ~ escapes.
* finish_up_letter() prompts for Cc:, verifies user really wants to send
* send_it() invokes mailer, sends to record file, expands aliases,
* adds own_hdrs.
* rm_edfile() signals are directed here. remove letter, longjmp
*
* The flow of control in this file is NOT obvious to allow for both text
* and suntools _event driven_ attributes. In text, the flow is far more
* obvious because it is sequential. In suntools, each function is called
* from outside this module. Keystrokes are interpreted individually and
* queued up in "rite.c". select.c calls add_to_letter when a \n is entered
* passing the string stored in rite.c. If you're trying to follow the flow
* of control for suntools, keep the event drivers in mind and follow select.c
* and rite.c
*/
#define TO_FIELD 1
#define SUBJECT 2
#define CC_FIELD 3
#define BC_FIELD 4
static char Subject[BUFSIZ],To[HDRSIZ],Cc[HDRSIZ],Bcc[HDRSIZ],in_reply_to[256];
static int killme;
static u_long flags;
static SIGRET (*oldterm)(), (*oldint)(), (*oldquit)();
static void send_it();
static jmp_buf cntrl_c_buf;
FILE *ed_fp;
char *edfile;
/* argc, and argv could be null if coming from compose */
do_mail(n, argv, list)
register int n; /* no need for "argc", so use the space for a variable */
register char **argv, *list;
{
char firstchar = (argv)? **argv: 'm';
char *to = NULL, *cc = NULL, *addcc = NULL, *bcc = NULL, *subj = NULL;
char *route = NULL;
char inc_list[MAXMSGS_BITS], buf[HDRSIZ];
u_long flgs = 0;
if (ison(glob_flags, IS_GETTING)) {
print("You must finish the letter you are editing first.\n");
return -1;
}
if (ison(glob_flags, DO_PIPE)) {
print("You can't pipe through the mail command.\n");
return -1;
}
turnon(flgs, NO_IGNORE); /* if we include a message, include all hdrs */
clear_msg_list(inc_list);
if (do_set(set_options, "autoedit"))
turnon(flgs, EDIT);
#ifdef VERBOSE_ARG
if (do_set(set_options, "verbose"))
turnon(flgs, VERBOSE);
#endif /* VERBOSE_ARG */
if (do_set(set_options, "autosign"))
turnon(flgs, SIGN);
/* If piped to mail, include the messages piped */
if (ison(glob_flags, IS_PIPE) ||
(lower(firstchar) == 'r' && do_set(set_options, "autoinclude"))) {
turnon(flgs, INCLUDE);
bitput(list, inc_list, msg_cnt, =);
}
while (argv && *argv && *++argv && **argv == '-') {
n = 1;
while (n && argv[0][n])
switch (argv[0][n]) {
#ifdef VERBOSE_ARG
case 'v': turnon(flgs, VERBOSE); n++; break;
#endif /* VERBOSE_ARG */
case 'e': turnon(flgs, EDIT); n++;
when 'F': turnon(flgs, DO_FORTUNE); n++;
when 'b':
if (argv[1]) {
n = 0, bcc = *++argv;
fix_up_addr(bcc);
} else {
print("Must specify blind-carbon list\n");
return -1;
}
when 'c':
if (argv[1]) {
n = 0, addcc = *++argv;
fix_up_addr(addcc);
} else {
print("Must specify carbon-copy list\n");
return -1;
}
when 's':
if (argv[1])
n = 0, subj = *++argv;
else
n++, turnon(flgs, NEW_SUBJECT);
when 'i': case 'h': case 'f': {
int m;
if (!msg_cnt) {
print("No message to include!\n");
return -1;
}
if (argv[0][n] == 'i') {
turnon(flgs, INCLUDE);
turnoff(flgs, INCLUDE_H);
turnoff(flgs, FORWARD);
} else if (argv[0][n] == 'h') {
turnon(flgs, INCLUDE_H);
turnoff(flgs, INCLUDE);
turnoff(flgs, FORWARD);
} else if (argv[0][n] == 'f') {
turnon(flgs, FORWARD);
turnoff(flgs, INCLUDE_H);
turnoff(flgs, INCLUDE);
}
/* "-i 3-5" or "-i3-5" Consider the latter case first */
if (!argv[0][++n])
argv++, n = 0;
(*argv) += n;
m = get_msg_list(argv, inc_list);
(*argv) -= n;
if (m == -1)
return -1;
/* if there were args, then go back to the first char
* in the next argv
*/
if (m)
n = 0;
if (!n) /* n may be 0 from above! */
argv += (m-1);
}
when 'r':
if (lower(firstchar) == 'r') {
route = *++argv;
n = 0;
break;
}
/* fall thru */
default:
if (argv[0][n] != '?')
wprint("%c: unknown option\n", argv[0][n]);
wprint("available options\n");
#ifdef VERBOSE_ARG
wprint("v verbose (passed to mail delivery system)\n");
#endif /* VERBOSE_ARG */
wprint("e immediately enter editor (autoedit)\n");
wprint("F add fortune to the end of message.\n");
wprint("s [subject] prompt for or set subject.\n");
wprint("c cc-addrs set carbon-copy recipients.\n");
wprint("b bcc-addrs set blind-carbon-copy recipients.\n");
wprint("i [msg#'s] include msg_list into letter.\n");
wprint("h [msg#'s] include msg_list with headers.\n");
wprint("f [msg#'s] forward msg_list (not indented).\n");
return -1;
}
}
*in_reply_to = *To = *Subject = *Cc = *Bcc = 0;
if (lower(firstchar) == 'r') {
char *old_fmt = hdr_format, *pcc = NULL;
to = To, cc = Cc;
/*
* Generate a reply to all the messages passed to respond(). This
* list is different than the include-msg list above. Get info about
* whom the messages were sent to for reply-all.
* BUG: currently, redundant addresses aren't pruned from Bcc list!
*/
for (n = 0; n < msg_cnt; n++)
if (msg_bit(list, n)) {
if (to != To)
*to++ = ',', *to++ = ' ';
(void) reply_to(n, (firstchar == 'R'), buf);
if (strlen(buf) + (to - To) > sizeof(To) - 1) {
print("# recipients exceeded at msg %d\n", n);
break;
}
to += Strcpy(to, buf);
if (firstchar == 'R') {
if (pcc) /* if there was a previous cc, append ", " */
*cc++ = ',', *cc++ = ' ';
if (pcc = cc_to(n, buf))
if (strlen(pcc) + (cc - Cc) > sizeof(Cc) - 1)
print("# Cc's exceeded at msg %d\n", n);
else
cc += Strcpy(cc, pcc);
}
/* remove redundant addresses now, or headers could get too
* long before the list runs out (it still might)
*/
rm_redundant_addrs(To, Cc);
to = To + strlen(To);
cc = Cc + strlen(Cc);
}
/* clean up end of Cc line for replyall's */
while (*cc == ' ' || *cc == ',')
*cc-- = '\0';
to = To, cc = Cc;
if (route || (route = do_set(set_options, "auto_route")))
/* careful! This routine could add lots-o-bytes and lose addresses
* to avoid writing out of segment.
*/
route_addresses(To, Cc, route);
if (hdr_format = do_set(set_options, "in_reply_to"))
/* "9" here is a magic # --see compose_hdr() */
(void) strcpy(in_reply_to, compose_hdr(current_msg)+9);
hdr_format = old_fmt;
}
if (ison(flgs, FORWARD) && ison(flgs, EDIT) ||
lower(firstchar) == 'r' && isoff(flgs, NEW_SUBJECT)) {
turnoff(flgs, NEW_SUBJECT);
if (subj = subject_to(current_msg, buf))
subj = strcpy(Subject, buf + 4*(lower(firstchar) != 'r'));
} else if (isoff(flgs, NEW_SUBJECT) && isoff(flgs, FORWARD) &&
(do_set(set_options, "ask") || do_set(set_options, "asksub")))
turnon(flgs, NEW_SUBJECT);
if (argv && *argv) {
char buf[HDRSIZ];
(void) argv_to_string(buf, argv);
fix_up_addr(buf);
to = &To[strlen(To)];
if (*To)
*to++ = ',', *to++ = ' ';
(void) strcpy(to, buf);
to = To;
}
if (addcc && *addcc) {
cc = &Cc[strlen(Cc)];
if (*Cc)
*cc++ = ',', *cc++ = ' ';
(void) strcpy(cc, addcc); /* addcc has already been fixed up */
cc = Cc;
}
/* remove any redundant addresses that just got added */
rm_redundant_addrs(To, Cc);
if (bcc && *bcc)
(void) strncpy(Bcc, bcc, sizeof(Bcc)); /* bcc already fixed up */
bcc = Bcc;
if (do_set(set_options, "fortune"))
turnon(flgs, DO_FORTUNE);
#ifdef SUNTOOL
if (istool) {
do_clear();
panel_set(abort_item, PANEL_SHOW_ITEM, TRUE, 0);
panel_set(comp_item, PANEL_SHOW_ITEM, FALSE, 0);
panel_set(read_item, PANEL_SHOW_ITEM, FALSE, 0);
panel_set(respond_item, PANEL_SHOW_ITEM, FALSE, 0);
}
#endif /* SUNTOOL */
return mail_someone(to, subj, cc, bcc, flgs, inc_list);
}
#ifdef SUNTOOL
/* panel item selection -- it's here because of local (static) variables */
abort_mail(item, value)
Panel_item item;
{
get_hdr_field = 0;
if (item == abort_item && value != 2) {
print("Aborted letter.");
killme = 1, rm_edfile(SIGINT);
flags = 0;
}
panel_set(comp_item, PANEL_SHOW_ITEM, TRUE, 0);
panel_set(send_item, PANEL_SHOW_ITEM, FALSE, 0);
panel_set(edit_item, PANEL_SHOW_ITEM, FALSE, 0);
panel_set(abort_item, PANEL_SHOW_ITEM, FALSE, 0);
panel_set(read_item, PANEL_SHOW_ITEM, TRUE, 0);
panel_set(respond_item, PANEL_SHOW_ITEM, TRUE, 0);
turnoff(glob_flags, IS_GETTING);
unlock_cursors();
}
#endif /* SUNTOOL */
mail_someone(to, subject, cc, bcc, flgs, list)
register char *to, *subject, *cc, *bcc, *list;
u_long flgs;
{
register char *p;
flags = flgs;
#ifdef SUNTOOL
if (istool)
rite(_tty.sg_kill), do_clear();
#endif /* SUNTOOL */
if (to && *to) {
if (!*To)
(void) strncpy(To, to, sizeof(To));
if (istool)
wprint("To: %s\n", To);
} else
#ifdef SUNTOOL
if (istool)
turnon(get_hdr_field, TO_FIELD);
else
#endif /* SUNTOOL */
to = NO_STRING;
if (subject && *subject) {
if (!*Subject)
(void) strncpy(Subject, subject, sizeof(Subject));
if (istool)
wprint("Subject: %s\n", Subject);
} else
#ifdef SUNTOOL
if (istool && !*Subject && ison(flags, NEW_SUBJECT))
turnon(get_hdr_field, SUBJECT);
else
#endif /* SUNTOOL */
subject = NO_STRING;
if (cc && *cc) {
if (!*Cc)
(void) strncpy(Cc, cc, sizeof(Cc));
if (istool)
wprint("Cc: %s\n", Cc);
} else
#ifdef SUNTOOL /* get_hdr_field -- prevents prompting on reply and forward */
if (istool && get_hdr_field && do_set(set_options, "askcc"))
turnon(get_hdr_field, CC_FIELD);
else
#endif /* SUNTOOL */
Cc[0] = '\0';
if (bcc && *bcc) {
if (!*Bcc)
(void) strncpy(Bcc, bcc, sizeof(Bcc));
if (istool)
wprint("Bcc: %s\n", Bcc);
} else
#ifdef SUNTOOL /* get_hdr_field -- prevents prompting on reply and forward */
if (istool && get_hdr_field)
turnon(get_hdr_field, BC_FIELD);
else
#endif /* SUNTOOL */
Bcc[0] = '\0';
if (ison(glob_flags, REDIRECT)) {
send_it(); /* doesn't return */
return 0;
}
/* if (!*to) then prompting will be done */
if (!istool) {
if (!(p = set_header("To: ", to, !*to)) || !*p) {
puts("No recipients, can't mail.");
return -1;
}
if (!*to) /* if user typed To-line here, fix up the address line */
fix_up_addr(p);
(void) strcpy(To, p);
/* don't prompt for subject if forwarding mail */
if (isoff(flags, FORWARD) &&
(p = set_header("Subject: ", subject,
!*subject && ison(flags, NEW_SUBJECT))))
(void) strcpy(Subject, p);
if (*Cc)
printf("Cc: %s\n", Cc);
if (*Bcc)
printf("Bcc: %s\n", Bcc);
putchar('\n');
}
#ifdef SUNTOOL
else if (!get_hdr_field) {
panel_set(send_item, PANEL_SHOW_ITEM, TRUE, 0);
panel_set(edit_item, PANEL_SHOW_ITEM, TRUE, 0);
} else if (ison(flags, FORWARD) && ison(flags, EDIT) &&
ison(get_hdr_field, TO_FIELD)) {
print("Specify recipient(s) to forward in tool mode.\n");
return -1;
}
#endif /* SUNTOOL */
/* If forwarding w/o editing, start a new file for each */
if (ison(flags, FORWARD) && isoff(flags, EDIT)) {
char fwd[MAXMSGS_BITS];
register int i;
clear_msg_list(fwd);
for (i = 0; i < msg_cnt; i++)
if (msg_bit(list, i)) {
set_msg_bit(fwd, i);
if (start_file(fwd) < 0)
return -1;
clear_msg_list(fwd);
}
} else
return start_file(list);
}
start_file(list)
char *list;
{
register char *dir;
register int i;
char line[MAXPATHLEN];
if (!(dir = do_set(set_options, "tmpdir")) &&
!(dir = do_set(set_options, "home")))
alted:
dir = ALTERNATE_HOME;
(void) mktemp(sprintf(line, "%s/%s", dir, EDFILE));
strdup(edfile, line);
if (!(ed_fp = mask_fopen(edfile, "w+"))) {
if (strcmp(dir, ALTERNATE_HOME))
goto alted;
#ifdef SUNTOOL
if (istool)
abort_mail(NO_ITEM, 0);
#endif /* SUNTOOL */
error("can't create %s", edfile);
return -1;
}
if (!istool) {
oldint = signal(SIGINT, rm_edfile);
oldquit = signal(SIGQUIT, rm_edfile);
oldterm = signal(SIGTERM, rm_edfile);
}
/* if flags call for it, include current message (with header?) */
if (ison(flags, INCLUDE) || ison(flags,FORWARD) || ison(flags,INCLUDE_H)) {
long copy_flgs = 0, is_forw = ison(flags, FORWARD);
char buf[sizeof(To)];
if (is_forw)
turnon(copy_flgs, FORWARD);
else
turnon(copy_flgs, INDENT);
if (ison(flags, INCLUDE))
turnon(copy_flgs, NO_HEADER);
if (ison(flags, INCLUDE) || is_forw)
turnon(copy_flgs, NO_IGNORE);
#ifdef MMDF
turnon(copy_flgs, NO_SEPARATOR);
#endif /* MMDF */
#ifdef SUNTOOL
if (istool)
lock_cursors();
#endif /* SUNTOOL */
for (i = 0; i < msg_cnt; i++)
if (msg_bit(list, i)) {
if (is_forw && ison(flags, EDIT)) {
(void) reply_to(i, FALSE, buf);
fprintf(ed_fp, "--- Forwarded mail from %s\n\n", buf);
}
wprint("%sing message %d ...",
is_forw? "forward" : "includ", i+1);
wprint("(%d lines)\n", copy_msg(i, ed_fp, copy_flgs));
set_isread(i); /* if we included it, we read it, right? */
if (is_forw && ison(flags, EDIT))
fprintf(ed_fp,
"\n--- End of forwarded message from %s\n", buf);
}
fflush(ed_fp);
#ifdef SUNTOOL
if (istool)
unlock_cursors();
#endif /* SUNTOOL */
}
if (ison(glob_flags, WARNING)) {
if (escape && !strncmp(escape, DEF_ESCAPE, 1))
wprint("(escape character is set to `%c')\n", *escape);
if (wrapcolumn && wrapcolumn < 20)
wprint("(warning: wrapping only %d columns from the left!)\n",
wrapcolumn);
}
turnon(glob_flags, IS_GETTING);
/* enter editor if autoedit and not toolmode */
if (
#ifdef SUNTOOL
(!istool || !get_hdr_field) &&
#endif /* SUNTOOL */
/* do an "if" again in case editor not found and EDIT turned off */
ison(flags, EDIT)) {
char *argv[3];
if (!(argv[0] = do_set(set_options, "visual")) || !*argv[0])
argv[0] = DEF_EDITOR;
argv[1] = edfile;
argv[2] = NULL;
print("Starting \"%s\"...\n", argv[0]);
fclose(ed_fp);
ed_fp = NULL_FILE;
execute(argv);
turnoff(flags, EDIT);
turnoff(flags, FORWARD); /* forwarded messages must be unedited */
/* upon exit of editor, user must now type ^D or "." to send */
if (istool)
return 0;
if (!(ed_fp = fopen(edfile, "r+"))) {
error("can't reopen %s", edfile);
return -1;
}
(void) fseek(ed_fp, 0L, 2);
puts("continue editing letter or ^D to send");
} else if (ison(flags, FORWARD) &&
#ifdef SUNTOOL
(!istool || !get_hdr_field) &&
#endif /* SUNTOOL */
finish_up_letter())
return 0; /* if forwarding mail, check to see if tool requires To: */
#ifdef SUNTOOL
if (istool) {
/* If toolmode, we're ready for IO. Give first prompt if not given */
if (ison(get_hdr_field, TO_FIELD))
wprint("To: ");
else if (ison(get_hdr_field, SUBJECT))
wprint("Subject: ");
else if (ison(get_hdr_field, CC_FIELD))
wprint("Cc: ");
type_cursor(PIX_SRC);
win_setcursor(msg_sw->ts_windowfd, &write_cursor);
return 0;
}
#endif /* SUNTOOL */
i = 0;
do {
/* If the user hits ^C in cbreak mode, mush will return to
* Getstr and not clear the buffer. whatever is typed next will
* be appended to the line. jumping here will force the line to
* be cleared cuz it's a new call.
*/
(void) setjmp(cntrl_c_buf);
while (Getstr(line, sizeof(line), 0) > -1) {
if (!istool) /* toolmode checks on a timer -- don't do it here */
(void) check_new_mail(); /* if new mail comes in, get it */
if ((i = add_to_letter(line)) <= 0)
break;
}
} while (i >= 0 && !finish_up_letter());
return i; /* return -1 if ~x or ~q to terminate letter */
}
char *tilde_commands[] = {
"commands: [OPTIONAL argument]",
"e [editor]\tEnter editor. Editor used: \"set editor\", env EDITOR, vi",
"v [editor]\tEnter visual editor. \"set visual\", env VISUAL, vi",
"p [pager]\tPage message; pager used: \"set pager\", env. PAGER, more",
"i [msg#'s]\tInclude current msg body [msg#'s] indented by \"indent_str\"",
"H [msg#'s]\tSame, but include the message headers from included messages",
"f [msg#'s]\tForward mail. Not indented, but marked as \"forwarded mail\"",
"t [list]\tChange list of recipients",
"s [subject]\tModify [set] subject header",
"c [cc list]\tModify [set] carbon copy recipients",
"b [bcc list]\tModify [set] blind carbon recipients",
"h\t\tModify all message headers",
"S[!]\t\tInclude Signature file [suppress file]",
"F[!]\t\tAdd a fortune at end of letter [don't add]",
"w file\t\tWrite msg buffer to file name",
"a file\t\tAppend msg buffer to file name",
"r file\t\tRead filename into message buffer",
"q \t\tQuit message; save in dead.letter (unless \"nosave\" is set).",
"x \t\tQuit message; don't save in dead.letter.",
"$variable\tInsert the string value for \"variable\" into message.",
":cmd\t\tRun the mail command \"cmd\".",
"u\t\tedit previous line in file.",
"E[!]\t\tClear contents of letter after saving to dead.letter [unless !].",
0
};
/*
* Add the line (char *) parameter to the letter. Determine tilde
* escapes and determine what to do. This function returns 0 to
* indicate user wants to end the letter, -1 if the letter cannot
* be sent (~q, ~x no buffer after editor, etc...) or 1 to indicate
* successful addition of the line to the letter.
*/
add_to_letter(line)
char line[];
{
register char *p;
char buf[BUFSIZ];
killme = 0;
(void) fseek(ed_fp, 0L, 2);
#ifdef SUNTOOL
if (get_hdr_field) {
/* These are received in order by design! */
if (ison(get_hdr_field, TO_FIELD)) {
if (!line[0]) {
wprint("There must be a recipient!\nTo: ");
return 1;
}
fix_up_addr(line);
(void) strcpy(To, line), turnoff(get_hdr_field, TO_FIELD);
} else if (ison(get_hdr_field, SUBJECT)) {
(void) strcpy(Subject, line);
turnoff(get_hdr_field, SUBJECT);
} else if (ison(get_hdr_field, CC_FIELD)) {
fix_up_addr(line);
(void) strcpy(Cc, line);
turnoff(get_hdr_field, CC_FIELD);
} else if (ison(get_hdr_field, BC_FIELD)) {
fix_up_addr(line);
(void) strcpy(Bcc, line);
turnoff(get_hdr_field, BC_FIELD);
}
if (ison(get_hdr_field, SUBJECT))
(void) set_header("Subject: ", Subject, 1);
else if (ison(get_hdr_field, CC_FIELD))
(void) set_header("Cc: ", Cc, 1);
else if (ison(get_hdr_field, BC_FIELD))
(void) set_header("Bcc: ", Bcc, 1);
panel_set(send_item, PANEL_SHOW_ITEM, (get_hdr_field==0), 0);
panel_set(edit_item, PANEL_SHOW_ITEM, (get_hdr_field==0), 0);
if (!get_hdr_field) {
wprint("\n");
if (ison(flags, EDIT)) {
(void) add_to_letter(sprintf(line, "%cv", *escape));
turnoff(flags, EDIT);
}
}
return 1;
}
#endif /* SUNTOOL */
if (!strcmp(line, ".") && (istool || do_set(set_options, "dot")))
return 0;
if (line[0] != *escape) {
fputs(line, ed_fp), fputc('\n', ed_fp), fflush(ed_fp);
return 1;
}
/* all commands are "~c" (where 'c' is the command). set p = first
* character after 'c' and skip whitespace
*/
p = &line[2];
skipspaces(0);
switch (line[1]) {
case 'v' : case 'p': case 'e': {
if (!*p || *p == 'i' && !p[1])
switch (line[1]) {
case 'p' :
if (!*p && !(p = do_set(set_options, "pager")))
p = DEF_PAGER;
if (!*p || !strcmp(p, "internal"))
p = NULL;
when 'v' :
if (p = do_set(set_options, "visual"))
break;
default :
if (!(p = do_set(set_options, "editor")) || !*p)
p = DEF_EDITOR;
}
if (line[1] == 'p') {
rewind(ed_fp);
(void) do_pager(p, TRUE); /* start the pager "p" */
do_pager(sprintf(buf, "To: %s\n", To), FALSE);
if (Subject[0])
do_pager(sprintf(buf, "Subject: %s\n", Subject), FALSE);
if (Cc[0])
do_pager(sprintf(buf, "Cc: %s\n", Cc), FALSE);
if (Bcc[0])
do_pager(sprintf(buf, "Bcc: %s\n", Bcc), FALSE);
do_pager(strcpy(buf, "--------\nMessage contains:\n"), FALSE);
while (fgets(buf, sizeof(buf), ed_fp))
if (do_pager(buf, FALSE) == EOF)
break;
(void) do_pager(NULL, FALSE); /* end pager */
} else {
char *argv[3];
argv[0] = p;
argv[1] = edfile;
argv[2] = NULL;
fclose(ed_fp);
ed_fp = NULL_FILE;
execute(argv); /* tool will return even tho editor isn't done */
if (istool)
return 1;
if (!(ed_fp = fopen(edfile, "r+"))) {
error("can't reopen %s", edfile);
return -1;
}
}
}
when '$': {
register char *p2;
if (!(p2 = do_set(set_options, p)))
wprint("(%s isn't set)\n", p);
else
putstring(p2, ed_fp);
}
when ':': {
char new[MAXMSGS_BITS];
u_long save_flags = glob_flags;
turnon(glob_flags, IGN_SIGS);
turnon(glob_flags, IGN_BANG);
turnoff(glob_flags, DO_PIPE);
turnoff(glob_flags, IS_PIPE);
(void) cmd_line(p, new);
glob_flags = save_flags;
#ifdef SUNTOOL
if (istool && msg_pix) /* the command was to read a message */
return 1;
#endif /* SUNTOOL */
}
when 'i': case 'f': case 'H': case 'm': {
int n;
long copy_flgs = 0;
char list[MAXMSGS_BITS];
if (!msg_cnt) {
print("No messages.\n");
break;
}
clear_msg_list(list);
if (line[1] != 'f')
turnon(copy_flgs, INDENT);
if (line[1] == 'i')
turnon(copy_flgs, NO_HEADER);
#ifdef MMDF
turnon(copy_flgs, NO_SEPARATOR);
#endif /* MMDF */
if (!*p)
set_msg_bit(list, current_msg);
else if (!do_range(p, list))
return 1;
#ifdef SUNTOOL
if (istool)
lock_cursors();
#endif /* SUNTOOL */
for (n = 0; n < msg_cnt; n++)
if (msg_bit(list, n)) {
if (line[1] == 'f') {
(void) reply_to(n, FALSE, buf);
fprintf(ed_fp, "--- Forwarded mail from %s\n\n", buf);
}
wprint("Including message %d ... ", n+1);
wprint("(%d lines)\n", copy_msg(n, ed_fp, copy_flgs));
set_isread(n);
if (line[1] == 'f')
fprintf(ed_fp,"\n--- End of forwarded message from %s\n\n",buf);
}
#ifdef SUNTOOL
if (istool)
unlock_cursors();
#endif /* SUNTOOL */
}
/* To: Cc: and Bcc: headers */
when 'b':
case 't':
case 'c': {
char *h = (line[1] == 't')? To : (line[1] == 'c')? Cc : Bcc;
char *Prompt = line[1] == 't'? "To: " :
line[1] == 'c'? "Cc: " : "Bcc: ";
#ifdef SUNTOOL
if (!*p && istool) {
turnon(get_hdr_field, CC_FIELD);
(void) set_header(Prompt, h, 1);
panel_set(send_item, PANEL_SHOW_ITEM, FALSE, 0);
panel_set(edit_item, PANEL_SHOW_ITEM, FALSE, 0);
return 1;
}
#endif /* SUNTOOL */
if (*p) {
fix_up_addr(p);
if (*h)
(void) sprintf(h+strlen(h), ", %s", p);
else
(void) strcpy(h, p);
} else if (!(p = set_header(Prompt, h, TRUE)) || !*p)
if (line[1] == 't') {
wprint("There must be a recipient!\n");
#ifdef SUNTOOL
turnoff(get_hdr_field, TO_FIELD);
panel_set(send_item, PANEL_SHOW_ITEM, TRUE, 0);
panel_set(edit_item, PANEL_SHOW_ITEM, TRUE, 0);
#endif /* SUNTOOL */
} else
*h = 0;
else {
fix_up_addr(p);
(void) strcpy(h, p);
}
}
when 's':
#ifdef SUNTOOL
if (!*p && istool) {
turnon(get_hdr_field, SUBJECT);
panel_set(send_item, PANEL_SHOW_ITEM, FALSE, 0);
panel_set(edit_item, PANEL_SHOW_ITEM, FALSE, 0);
(void) set_header("Subject: ", Subject, 1);
return 1;
}
#endif /* SUNTOOL */
if (*p || (p = set_header("Subject: ", Subject, 1)))
if (!*p)
Subject[0] = 0;
else
(void) strcpy(Subject, p);
when 'h':
#ifdef SUNTOOL
if (istool) {
turnon(get_hdr_field, TO_FIELD);
turnon(get_hdr_field, SUBJECT);
turnon(get_hdr_field, CC_FIELD);
turnon(get_hdr_field, BC_FIELD);
(void) set_header("To: ", To, 1);
panel_set(send_item, PANEL_SHOW_ITEM, FALSE, 0);
panel_set(edit_item, PANEL_SHOW_ITEM, FALSE, 0);
return 1;
}
#endif /* SUNTOOL */
while ((p = set_header("To: ", To, 1)) && !*p)
wprint("(There must be a recipient.)\n");
(void) strcpy(To, p);
if (p = set_header("Subject: ", Subject, 1))
if (!*p)
Subject[0] = 0;
else
(void) strcpy(Subject, p);
if (p = set_header("Cc: ", Cc, 1))
if (!*p)
Cc[0] = 0;
else {
fix_up_addr(p);
(void) strcpy(Cc, p);
}
if (p = set_header("Bcc: ", Bcc, 1))
if (!*p)
Bcc[0] = 0;
else {
fix_up_addr(p);
(void) strcpy(Bcc, p);
}
when 'S':
if (*p == '!')
turnoff(flags, SIGN), wprint("not ");
else
turnon(flags, SIGN);
wprint("adding signature file at end of message.\n");
when 'F':
if (*p == '!')
turnoff(flags, DO_FORTUNE), wprint("not ");
else
turnon(flags, DO_FORTUNE);
wprint("adding fortune at end of message.\n");
when 'w': case 'a': case 'r':
if (!*p) {
wprint("(you must specify a filename)\n");
return 1;
}
(void) fseek(ed_fp, 0L, 2); /* append */
file_to_fp(p, ed_fp, (line[1] == 'r')? "r":
(line[1] == 'w')? "w": "a");
/* go up one line in the message file and allow the user to edit it */
when 'u': {
long newpos, pos = ftell(ed_fp);
char oldline[256];
if (istool) {
wprint("(Not available in tool mode.)\n");
return 1;
}
if (pos <= 0L) { /* pos could be -1 if ftell() failed */
wprint("(No previous line in file.)\n");
return 1;
}
/* get the last 256 bytes written and read backwards from the
* current place until '\n' is found. Start by moving past the
* first \n which is at the end of the line we want to edit
*/
newpos = max(0, pos - 256L);
(void) fseek(ed_fp, newpos, L_SET);
/* don't fgets -- it'll stop at a \n */
(void) fread(line, sizeof(char), (int)(pos-newpos), ed_fp);
pos--;
/* the last char in line should be a \n cuz it was last input */
if (line[(int)(pos-newpos)] != '\n')
wprint("I don't know how, but your last line ended with %c.\n",
line[(int)(pos-newpos)]);
else
line[(int)(pos-newpos)] = 0; /* null terminate \n for ^H-ing */
for (pos--; pos > newpos && line[(int)(pos-newpos)] != '\n'; pos--)
;
/* we've gone back to the end of the second previous line. Check
* to see if the char we're pointing to is a \n. It should be, but
* if it's not, we moved back to the first line of the file.
*/
if (line[(int)(pos-newpos)] == '\n')
++pos;
/* save the old line that's there in case the user boo-boos */
(void) strcpy(oldline, &line[(int)(pos-newpos)]);
/* let set header print out the line and get the input */
if (!(p = set_header("", &line[(int)(pos-newpos)], TRUE))) {
wprint("Something bad happened and I don't know what it is.\n");
p = oldline;
} else if (*p == *escape)
wprint("(Warning: %c escapes ignored on %cu lines.)\n",
*escape, *escape);
/* seek to to the position where the new line will go */
(void) fseek(ed_fp, pos, L_SET);
/* put the newly typed line */
(void) fputs(p, ed_fp); /* don't add \n. padding may be necessary */
/* if the new line is less than the old line, we're going to do
* one of two things. The best thing to do is to truncate the
* file to the end of the new line. Sys-v can't do that, so we
* pad the line with blanks. May be messy in some cases, but...
*/
if ((pos = strlen(p) - strlen(oldline)) < 0) {
#ifndef SYSV
/* add the \n, flush the file, truncate to the current pos */
fputc('\n', ed_fp), fflush(ed_fp);
(void) ftruncate(fileno(ed_fp), (int)ftell(ed_fp));
#else
/* pad with blanks to the length of the old line. add \n */
while (pos++ < 0)
fputc(' ', ed_fp);
fputc('\n', ed_fp), fflush(ed_fp);
#endif /* SYSV */
} else
/* the new line is >= the old line, add \n -- no trunc req. */
fputc('\n', ed_fp);
return 1;
}
/* break; not here cuz of "return" (lint). */
case 'E':
if (*p != '!' && !do_set(set_options, "nosave"))
dead_letter();
if (emptyfile(&ed_fp, edfile) == -1)
error(edfile);
else
wprint("Message buffer empty\n");
when 'q':
/* save in dead.letter if nosave not set -- rm_edfile(-2). */
rm_edfile(-2); /* doesn't return out of tool mode */
return -1;
/* break; not stated cuz of "return" (lint) */
case 'x':
/* don't save dead.letter -- simulate normal rm_edfile() call */
rm_edfile(0);
#ifdef SUNTOOL
if (istool) {
wprint("*Letter aborted*");
type_cursor(PIX_CLR);
}
#endif /* SUNTOOL */
return -1;
/* break; (not specified for lint) */
default:
if (line[1] == *escape) {
fputs(&line[1], ed_fp), fputc('\n', ed_fp), fflush(ed_fp);
return 1;
} else if (line[1] == '?') {
register int x;
if (!istool)
(void) do_pager(NULL, TRUE); /* start pager */
for (x = 0; tilde_commands[x]; x++) {
(void) sprintf(buf, "%s%s\n", escape, tilde_commands[x]);
if (!istool) {
if (do_pager(buf, FALSE))
break;
} else
wprint(buf);
}
(void) sprintf(buf, "%s%s\t\tbegin a line with a single %s\n",
escape, escape, escape);
if (istool)
wprint(buf);
else {
if (tilde_commands[x] == NULL)
(void) do_pager(buf, FALSE);
(void) do_pager(NULL, FALSE); /* end pager */
}
#ifdef SUNTOOL
if (istool)
(void) help(0, "compose", tool_help);
#endif /* SUNTOOL */
} else
wprint("`%c': unknown %c escape. Use %c? for help.\n",
line[1], *escape, *escape);
}
(void) fseek(ed_fp, 0L, 2); /* seek to end of file in case there's more */
wprint("(continue editing letter)\n");
return 1;
}
/*
* finish up the letter. ask for the cc line, if verify is set, ask to
* verify sending, continue editing, or to dump the whole idea.
* Then check for signature and fortune. Finally, pass it to send_it()
* to actually send it off.
*/
finish_up_letter()
{
register char *p;
int c;
char buf[MAXPATHLEN];
/* forwarded mail has no additional personalized text */
if (ison(flags, FORWARD)) {
send_it();
turnoff(glob_flags, IS_GETTING);
return 1;
}
if (isoff(glob_flags, REDIRECT)) {
if (!istool) {
if (do_set(set_options, "askcc")) {
if (p = set_header("Cc: ", Cc, 1))
(void) strcpy(Cc, p);
}
#ifdef MMDF
/* Give some sort of indication that the end was seen */
else
wprint("EOT\n");
#endif /* MMDF */
}
/* ~v on the Cc line asks for verification, first initialize p! */
p = NULL;
if (!strncmp(Cc, "~v", 2) || (p = do_set(set_options, "verify"))) {
if (!p) /* so we don't Cc to ~v! */
*Cc = 0;
for (;;) {
#ifdef SUNTOOL
if (istool) {
type_cursor(PIX_CLR);
print("Send, Continue, Discard [Left, Middle, Right]?");
c = confirm(msg_sw->ts_windowfd);
clr_bot_line(); /* really: clears print window */
if (isascii(c))
Lower(c);
else switch(c) {
when MS_LEFT : c = 's';
when MS_MIDDLE : c = 'c';
when MS_RIGHT : c = 'd';
otherwise: c = 0;
}
} else
#endif /* SUNTOOL */
{
print("send, continue editing, discard [s,c,d]? ");
c = Getstr(buf, sizeof(buf), 0);
}
if (c < 0)
putchar('\n');
else if (!istool)
c = lower(*buf);
if (c == 'd') {
rm_edfile(-2);
return 1;
} else if (c == 'c') {
wprint("(continue editing letter)\n");
#ifdef SUNTOOL
if (istool)
type_cursor(PIX_SRC);
#endif /* SUNTOOL */
return 0;
} else if (c == 's')
break;
}
}
}
#ifdef SUNTOOL
if (istool)
lock_cursors();
#endif /* SUNTOOL */
send_it();
turnoff(glob_flags, IS_GETTING);
return 1;
}
/*
* actually send the letter.
* 1. reset all the signals because of fork.
* 2. determine recipients (users, address, files, programs)
* 3. determine mailer, fork and return (if not verbose).
* 4. popen mailer, $record, and other files specified in step 1.
* 5. make the headers; this includes To: line, and user set headers, etc...
* 6. copy the letter right into the array of file pointers (step 1).
* 7. close the mailer and other files (step 1) and remove the edit-file.
*/
static void
send_it()
{
register char *p, *b, *addr_list;
#ifdef MAXFILES
register int size = MAXFILES - 1;
FILE *files[MAXFILES];
#else
register int size = getdtablesize() - 1;
FILE *files[30]; /* 30 should be sufficiently large enough */
#endif /* MAXFILES */
int next_file = 1; /* reserve files[0] for the mail delivery program */
int log_file = -1; /* the index into the files array for mail logging */
char buf[3*HDRSIZ];
char expand = !do_set(set_options, "no_expand");
int fork_err = 0;
if (!istool) {
(void) signal(SIGINT, oldint);
(void) signal(SIGQUIT, oldquit);
(void) signal(SIGTERM, oldterm);
}
if (!(p = do_set(set_options, "sendmail")))
p = MAIL_DELIVERY;
#ifdef VERBOSE_ARG
if (ison(flags, VERBOSE) || do_set(set_options, "verbose"))
#ifdef MMDF
b = &buf[strlen(sprintf(buf, "%s%s", p, VERBOSE_ARG))];
#else /* MMDF */
b = &buf[strlen(sprintf(buf, "%s %s", p, VERBOSE_ARG))];
#endif /* MMDF */
else
#endif /* VERBOSE_ARG */
b = buf + Strcpy(buf, p);
#ifdef METOO_ARG
if (!strcmp(p, MAIL_DELIVERY) && do_set(set_options, "metoo"))
b += strlen(sprintf(b, " %s", METOO_ARG));
#endif /* METOO_ARG */
*b++ = ' ', *b = 0; /* strcat(b, " "); */
addr_list = b; /* save this position to check for addresses later */
/*
* Build the address lines to give to the mail transfer system. This
* address line cannot contain comment fields! First, expand aliases
* since they may contain comment fields within addresses. Copy this
* result back into the Buffer since this will go into the header ...
* Next, remove all comments so the buffer contains ONLY valid addresses.
* Next, strip off any filenames/programs which might occur in the list.
* Finally, add this information to the command line buffer (buf).
* Remove commas if necessary (see ifdefs). In the event of errors,
* force a dead letter by rm_edfile(-1).
*/
if (!(p = alias_to_address(To))) {
print("address expansion failed for To: line.\n");
rm_edfile(-1);
} else {
next_file += find_files(p, files+next_file, size - next_file);
if (expand)
(void) strcpy(To, p);
rm_cmts_in_addr(p);
skipspaces(0);
if (!*p) {
print("There must be at least 1 legal recipient on the To line\n");
while (--next_file > 0)
fclose(files[next_file]);
rm_edfile(-2);
return;
}
b += Strcpy(b, p);
}
if (*Cc) {
if (!(p = alias_to_address(Cc))) {
print("address expansion failed for Cc: line.\n");
while (--next_file > 0)
fclose(files[next_file]);
rm_edfile(-1);
} else {
next_file += find_files(p, files+next_file, size - next_file);
if (expand)
(void) strcpy(Cc, p);
rm_cmts_in_addr(p);
skipspaces(0);
if (*p) {
*b++ = ',', *b++ = ' ';
b += Strcpy(b, p);
}
}
}
/* Sign the letter before adding the Bcc list since they aren't
* considered when adding a signature.
*/
if ((ison(flags, SIGN) || ison(flags, DO_FORTUNE)) &&
isoff(glob_flags, REDIRECT) && isoff(flags, FORWARD))
sign_letter(addr_list, flags, ed_fp);
if (*Bcc) {
if (!(p = alias_to_address(Bcc))) {
print("address expansion failed for Bcc: line.\n");
while (--next_file > 0)
fclose(files[next_file]);
rm_edfile(-1);
} else {
next_file += find_files(p, files+next_file, size - next_file);
(void) strcpy(Bcc, p);
rm_cmts_in_addr(p);
skipspaces(0);
if (*p) {
*b++ = ',', *b++ = ' ';
b += Strcpy(b, p);
}
}
}
#ifdef NO_COMMAS
for (p = buf; p = index(p, ','); p++)
*p = ' ';
#endif /* NO_COMMAS */
Debug("mail command: %s\n", buf);
#ifdef SUNTOOL
if (istool)
abort_mail(NO_ITEM, 0);
#endif /* SUNTOOL */
if (isoff(flags, VERBOSE) && debug < 3)
switch (fork()) {
case 0: /* the child will send the letter. ignore signals */
#ifdef SYSV
if (setpgrp() == -1)
error("setpgrp");
#endif /* SYSV */
#ifdef MMDF
(void) signal(SIGCHLD, SIG_DFL);
#endif /* MMDF */
(void) signal(SIGINT, SIG_IGN);
(void) signal(SIGHUP, SIG_IGN);
(void) signal(SIGQUIT, SIG_IGN);
(void) signal(SIGTERM, SIG_IGN);
#ifdef SIGTTIN
(void) signal(SIGTTOU, SIG_IGN);
(void) signal(SIGTTIN, SIG_IGN);
#endif /* SIGTTIN */
#ifdef SIGCONT
(void) signal(SIGCONT, SIG_IGN);
(void) signal(SIGTSTP, SIG_IGN);
#endif /* SIGCONT */
turnon(glob_flags, IGN_SIGS);
when -1:
error("fork failed trying to send mail");
fork_err++;
rm_edfile(-1);
/* fall thru */
default:
if (!fork_err && isoff(glob_flags, REDIRECT))
fclose(ed_fp);
#ifdef SUNTOOL
if (istool) {
if (!fork_err) {
wprint("Letter sent.");
print("Letter sent.");
}
type_cursor(PIX_CLR);
}
#endif /* SUNTOOL */
while (--next_file > 0)
fclose(files[next_file]);
#ifdef MMDF
if (!fork_err)
(void) wait((int *) 0);
#endif /* MMDF */
return;
}
#ifdef MMDF
*(addr_list-1) = '\0';
#endif /* MMDF */
if (debug > 2)
files[0] = stdout;
else if (!(files[0] = open_file(buf, TRUE))) {
rm_edfile(-1); /* force saving of undeliverable mail */
if (isoff(flags, VERBOSE) && debug < 3)
exit(-1);
else
return;
}
if (ison(flags, VERBOSE))
wprint("Sending letter ... "), fflush(stdout);
#ifdef MMDF
/* give address list to submit */
for (p = addr_list; p && (p = any(p, ",<")); p++)
if (*p == ',')
*p = '\n';
else
p = index(p, '>');
fprintf(files[0], "%s\n\n", addr_list);
#endif /* MMDF */
/* see if log is set. This is just to add message headers. No msg body. */
if (p = do_set(set_options, "logfile")) {
if (!*p)
p = "~/mail.log";
(void) strcpy(buf, p);
log_file = next_file;
next_file += find_files(buf, files+next_file, size - next_file);
if (log_file == next_file)
log_file = -1;
}
/* see if record is set. If so, open that file for appending and add
* the letter in a format such that mail can be read from it
*/
if (p = do_set(set_options, "record")) {
if (!*p)
p = "~/record";
(void) strcpy(buf, p);
next_file += find_files(buf, files+next_file, size - next_file);
}
/* Make folders conform to RFC-822 by adding From: and Date: headers.
* Some older mailers (binmail, execmail, delivermail), don't add
* these headers, so add them for #define OLD_MAILER. Also add them
* with the "Resent-" prefix when forwarding.
*/
{
time_t t;
char From_buf[256], *pF = From_buf, date_str[64];
char *host = NULL;
if (ourname)
host = ourname[0];
if (ison(flags, FORWARD))
pF += Strcpy(From_buf, "Resent-");
pF += Strcpy(pF, "From: ");
#ifdef UUCP
if (host && *host)
pF += strlen(sprintf(pF, "%s!", host));
#endif /* UUCP */
pF += Strcpy(pF, login);
#ifndef UUCP
if (host && *host)
pF += strlen(sprintf(pF, "@%s", host));
#endif /* UUCP */
if (p = do_set(set_options, "realname"))
pF += strlen(sprintf(pF, " (%s)", p));
*pF++ = '\n', *pF++ = 0;
(void) time(&t);
for (size = 0; size < next_file; size++) {
#ifndef OLD_MAILER
if (size == 0 && isoff(flags, FORWARD))
continue;
#endif /* OLD_MAILER */
if (size > 0) {
#ifndef MSG_SEPARATOR
fprintf(files[size], "From %s %s", login, ctime(&t));
#else /* MSG_SEPARATOR */
#ifdef MMDF
fputs(MSG_SEPARATOR, files[size]);
#else /* MMDF */
fprintf(files[size], "%s\n", MSG_SEPARATOR);
#endif /* MMDF */
#endif /* MSG_SEPARATOR */
}
fputs(From_buf, files[size]);
fprintf(files[size], "%sDate: %s\n",
ison(flags, FORWARD) ? "Resent-" : "", rfc_date(date_str));
}
}
/* first print users own message headers */
if (own_hdrs && !do_set(set_options, "no_hdrs")) {
struct options *opts;
for (opts = own_hdrs; opts; opts = opts->next)
for (size = 0; size < next_file; size++)
fprintf(files[size], "%s %s\n", opts->option, opts->value);
}
wrap_addrs(To, 80);
wrap_addrs(Cc, 80);
wrap_addrs(Bcc, 80);
/* send the header stuff to sendmail and end header with a blank line */
for (size = 0; size < next_file; size++) {
if (*in_reply_to)
fprintf(files[size], "In-Reply-To: %s\n", in_reply_to);
fprintf(files[size], "X-Mailer: %s\n", VERSION);
fprintf(files[size], "%sTo: %s\n",
ison(flags, FORWARD) ? "Resent-" : "", To);
if (*Subject && isoff(flags, FORWARD))
fprintf(files[size], "Subject: %s\n", Subject);
if (*Cc)
fprintf(files[size], "%sCc: %s\n",
ison(flags, FORWARD) ? "Resent-" : "", Cc);
if (size > 0) {
/* Do not send these to mail transfer agent */
if (*Bcc)
fprintf(files[size], "%sBcc: %s\n",
ison(flags, FORWARD) ? "Resent-" : "", Bcc);
fprintf(files[size], "Status: OR\n");
}
if (isoff(flags, FORWARD))
fputc('\n', files[size]);
}
/* if redirection, ed_fp = stdin, else rewind the file just made */
if (isoff(glob_flags, REDIRECT))
rewind(ed_fp);
else
ed_fp = stdin;
/* Read from stdin or the edfile till EOF and send it all to the mailer
* and other open files/folders/programs. Check for "From " at the
* beginnings of these lines to prevent creating new messages in folders.
* If forwarding, skip the leading From_ line of the forwarded message.
*/
#ifndef MSG_SEPARATOR
if (ison(flags, FORWARD) && fgets(buf, sizeof buf, ed_fp)) {
if (strncmp(buf, "From ", 5) != 0)
rewind(ed_fp); /* No From_ line (should never happen) */
}
#endif /* !MSG_SEPARATOR */
while (fgets(buf, sizeof buf, ed_fp))
for (size = 0; size < next_file; size++) {
if (size == log_file)
continue;
#ifndef MSG_SEPARATOR
if (!strncmp(buf, "From ", 5))
fputc('>', files[size]);
#endif /* MSG_SEPARATOR */
fputs(buf, files[size]);
}
/* loop thru the open files (except for the first: the mail delivery agent)
* and append a blank line so that ucb-mail can read these folders.
* Then close the files. If the file was a popened program, the sigchld
* that the program generates will close the file.
*/
#ifdef END_MSG_SEP
for (size = 1; size < next_file; size++) {
fputs(END_MSG_SEP, files[size]);
if (files[size])
fclose(files[size]);
}
#else /* !END_MSG_SEP */
for (size = 1; size < next_file; size++)
if (files[size]) {
fputc('\n', files[size]);
fclose(files[size]);
}
#endif /* END_MSG_SEP */
#ifdef MMDF
if (debug < 3) {
int reply_code = pclose(files[0]);
Debug("pclose reply_code = %d\n", reply_code);
rm_edfile((reply_code >> 8) == 9 ? 0 : -1);
} else
rm_edfile(0);
#else /* MMDF */
rm_edfile(0);
if (debug < 3)
(void) pclose(files[0]);
#endif /* MMDF */
if ((ison(flags, VERBOSE) || debug > 2) && isoff(glob_flags, REDIRECT))
wprint("sent.\n");
else
exit(0); /* not a user exit -- a child exit */
}
/* ARGSUSED */
SIGRET
rm_edfile(sig)
{
if (sig > 0) {
/* wrapcolumn may have been trashed -- restore it */
char *fix = do_set(set_options, "wrapcolumn");
if (fix && *fix)
wrapcolumn = atoi(fix);
mac_flush(); /* abort pending macros */
}
/* now check whether we should abort the letter */
if (sig > 0 && !killme) {
if (!istool)
(void) signal(sig, rm_edfile);
killme = 1;
wprint("\n** interrupt -- one more to kill letter **\n");
#ifdef SUNTOOL
if (istool) {
type_cursor(PIX_SRC);
return;
}
#endif /* SUNTOOL */
longjmp(cntrl_c_buf, 1);
}
killme = 0;
/* if sig == -1, force a save into dead.letter.
* else, check for nosave not being set and save anyway if it's not set
* sig == 0 indicates normal exit (or ~x), so don't save a dead letter.
*/
if (sig == -1 || sig != 0 && !do_set(set_options, "nosave"))
dead_letter();
if (isoff(glob_flags, REDIRECT))
fclose(ed_fp);
(void) unlink(edfile);
turnoff(glob_flags, IS_GETTING);
if (sig == -1)
return;
#ifdef SUNTOOL
if (sig && istool > 1) {
wprint("*Letter aborted*");
abort_mail(abort_item, 2);
}
#endif /* SUNTOOL */
if (sig == SIGHUP)
cleanup(0);
if (!istool) {
(void) signal(SIGINT, oldint);
(void) signal(SIGQUIT, oldquit);
(void) signal(SIGTERM, oldterm);
}
if (sig == 0)
return;
if (istool || sig == -2) /* make sure sigchld is reset first */
return;
if (isoff(glob_flags, DO_SHELL)) { /* If we're not in a shell, exit */
puts("exiting");
echo_on();
exit(1);
}
longjmp(jmpbuf, 1);
}
/* save letter into dead letter */
dead_letter()
{
char *p, buf[BUFSIZ];
long t;
FILE *dead;
if (ison(glob_flags, REDIRECT)) {
print("input redirected -- can't save dead letter.\n");
return;
}
/* If the file doesn't exist, get outta here. File may not exist if
* user generated a ^C from a promptable header and catch sent us here.
*/
if (Access(edfile, R_OK))
return;
/* User may have killed mush via a signal while he was in an editor.
* ed_fp will be NULL in this case. Since the file does exist (above),
* open it so we can copy it to dead letter.
*/
if (!ed_fp && !(ed_fp = fopen(edfile, "r"))) {
error("can't save dead letter from %s", edfile);
return;
}
/* don't save a dead letter if there's nothing to save. */
if (fseek(ed_fp, 0L, 2) || ftell(ed_fp) <= 1L)
return;
if (!(p = do_set(set_options, "dead")))
p = "~/dead.letter";
if (!(dead = open_file(p, FALSE)))
return;
(void) time (&t);
fflush(ed_fp);
rewind(ed_fp);
#ifdef MSG_SEPARATOR
fputs(MSG_SEPARATOR, dead);
#else /* MSG_SEPARATOR */
fprintf(dead, "From %s %s", login, ctime(&t));
#endif /* MSG_SEPARATOR */
fprintf(dead, "To: %s\nSubject: %s\n", To, Subject);
fprintf(dead, "Date: %s\n", rfc_date(buf));
if (*Cc)
fprintf(dead, "Cc: %s\n", Cc);
if (*Bcc)
fprintf(dead, "Bcc: %s\n", Bcc);
(void) fputc('\n', dead);
while (fgets(buf, sizeof(buf), ed_fp))
(void) fputs(buf, dead);
(void) fputc('\n', dead);
#ifdef END_MSG_SEP
fputs(END_MSG_SEP, dead);
#endif /* END_MSG_SEP */
(void) fclose(dead);
print("Saved unfinished letter in %s.\n", p);
}