schaefer@ogccse.ogc.edu (Barton E. Schaefer) (04/29/89)
Part 2 of the Mush 6.5 Upgrade Kit. Read the instructions in part 1. --------------------------------------------------------------------------- Prereq: Part1 *** mush-6.4/kit.check Tue Apr 18 17:29:04 1989 --- kit.check Tue Apr 18 17:29:04 1989 *************** *** 1 **** ! Part1 --- 1 ---- ! Part1-check *** mush-6.4/mail.c Fri Mar 24 10:15:22 1989 --- mail.c Thu Apr 13 16:52:40 1989 *************** *** 11,17 **** * 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 --- 11,17 ---- * 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, ! * add_headers() adds all headers to a FILE * * rm_edfile() signals are directed here. remove letter, longjmp * * The flow of control in this file is NOT obvious to allow for both text *************** *** 32,38 **** 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; --- 32,39 ---- static int killme; static u_long flags; static SIGRET (*oldterm)(), (*oldint)(), (*oldquit)(); ! static int send_it(); ! static long add_headers(); static jmp_buf cntrl_c_buf; FILE *ed_fp; char *edfile; *************** *** 184,196 **** } 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) --- 185,199 ---- } to += Strcpy(to, buf); if (firstchar == 'R') { ! if (pcc = cc_to(n, buf)) { ! /* if there was a previous cc, append ", " */ ! if (cc != Cc) ! *cc++ = ',', *cc++ = ' '; 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) *************** *** 340,346 **** Bcc[0] = '\0'; if (ison(glob_flags, REDIRECT)) { ! send_it(); /* doesn't return */ return 0; } /* if (!*to) then prompting will be done */ --- 343,349 ---- Bcc[0] = '\0'; if (ison(glob_flags, REDIRECT)) { ! (void) send_it(); return 0; } /* if (!*to) then prompting will be done */ *************** *** 418,423 **** --- 421,433 ---- oldterm = signal(SIGTERM, rm_edfile); } + if ((isoff(flags, FORWARD) || ison(flags, EDIT)) && + do_set(set_options, "edit_hdrs")) { + turnon(flags, EDIT_HDRS); + if (add_headers(NULL, &ed_fp, 1, flags) == (long) -1) + return -1; + } + /* 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); *************** *** 458,464 **** #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", --- 468,474 ---- #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", *************** *** 472,496 **** #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 --- 482,510 ---- #endif /* SUNTOOL */ /* do an "if" again in case editor not found and EDIT turned off */ ison(flags, EDIT)) { ! char **argv, *edit; ! int argc; ! if (!(edit = do_set(set_options, "visual")) || !*edit) ! edit = DEF_EDITOR; ! (void) sprintf(line, "%s %s", edit, edfile); ! if ((argv = mk_argv(line, &argc, FALSE)) && argc > 0) { ! print("Starting \"%s\"...\n", argv[0]); ! fclose(ed_fp); ! ed_fp = NULL_FILE; ! execute(argv); ! free_vec(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); ! } else ! print("Unable to start \"%s\"\n", edit); puts("continue editing letter or ^D to send"); } else if (ison(flags, FORWARD) && #ifdef SUNTOOL *************** *** 554,559 **** --- 568,574 ---- ":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 !].", + "|cmd\t\tPipe the message through the unix command \"cmd\".", 0 }; *************** *** 625,631 **** 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' : --- 640,646 ---- p = &line[2]; skipspaces(0); switch (line[1]) { ! case 'v' : case 'p': case 'e' : case '|' : { if (!*p || *p == 'i' && !p[1]) switch (line[1]) { case 'p' : *************** *** 636,674 **** 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 '$': { --- 651,700 ---- when 'v' : if (p = do_set(set_options, "visual")) break; + /* else fall through */ default : if (!(p = do_set(set_options, "editor")) || !*p) p = DEF_EDITOR; + when '|' : + wprint("No command for pipe\n"); + return 1; } ! if (line[1] == 'p' || line[1] == '|') { rewind(ed_fp); (void) do_pager(p, TRUE); /* start the pager "p" */ ! if (isoff(flags, EDIT_HDRS)) { ! 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; ! int argc; ! (void) sprintf(buf, "%s %s", p, edfile); ! if ((argv = mk_argv(buf, &argc, FALSE)) && argc > 0) { ! fclose(ed_fp); ! ed_fp = NULL_FILE; ! execute(argv); ! free_vec(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; ! } ! } else ! wprint("Unable to start \"%s\"\n", p); } } when '$': { *************** *** 742,747 **** --- 768,777 ---- char *h = (line[1] == 't')? To : (line[1] == 'c')? Cc : Bcc; char *Prompt = line[1] == 't'? "To: " : line[1] == 'c'? "Cc: " : "Bcc: "; + if (ison(flags, EDIT_HDRS)) { + wprint("You must use an editor to change your headers.\n"); + break; + } #ifdef SUNTOOL if (!*p && istool) { turnon(get_hdr_field, CC_FIELD); *************** *** 773,778 **** --- 803,812 ---- } } when 's': + if (ison(flags, EDIT_HDRS)) { + wprint("You must use an editor to change your headers.\n"); + break; + } #ifdef SUNTOOL if (!*p && istool) { turnon(get_hdr_field, SUBJECT); *************** *** 788,793 **** --- 822,831 ---- else (void) strcpy(Subject, p); when 'h': + if (ison(flags, EDIT_HDRS)) { + wprint("You must use an editor to change your headers.\n"); + break; + } #ifdef SUNTOOL if (istool) { turnon(get_hdr_field, TO_FIELD); *************** *** 913,918 **** --- 951,960 ---- } /* break; not here cuz of "return" (lint). */ case 'E': + if (ison(flags, EDIT_HDRS)) { + wprint("You must use an editor to empty the message buffer.\n"); + break; + } if (*p != '!' && !do_set(set_options, "nosave")) dead_letter(); if (emptyfile(&ed_fp, edfile) == -1) *************** *** 987,993 **** /* forwarded mail has no additional personalized text */ if (ison(flags, FORWARD)) { ! send_it(); turnoff(glob_flags, IS_GETTING); return 1; } --- 1029,1035 ---- /* forwarded mail has no additional personalized text */ if (ison(flags, FORWARD)) { ! (void) send_it(); turnoff(glob_flags, IS_GETTING); return 1; } *************** *** 994,1008 **** 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; --- 1036,1045 ---- if (isoff(glob_flags, REDIRECT)) { if (!istool) { ! if (isoff(flags, EDIT_HDRS) && do_set(set_options, "askcc")) { if (p = set_header("Cc: ", Cc, 1)) (void) strcpy(Cc, p); } } /* ~v on the Cc line asks for verification, first initialize p! */ p = NULL; *************** *** 1054,1060 **** if (istool) lock_cursors(); #endif /* SUNTOOL */ ! send_it(); turnoff(glob_flags, IS_GETTING); return 1; } --- 1091,1098 ---- if (istool) lock_cursors(); #endif /* SUNTOOL */ ! if (!send_it()) ! return 0; turnoff(glob_flags, IS_GETTING); return 1; } *************** *** 1069,1075 **** * 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; --- 1107,1113 ---- * 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 int send_it() { register char *p, *b, *addr_list; *************** *** 1076,1085 **** --- 1114,1128 ---- #ifdef MAXFILES register int size = MAXFILES - 1; FILE *files[MAXFILES]; + char *names[MAXFILES]; #else register int size = getdtablesize() - 1; FILE *files[30]; /* 30 should be sufficiently large enough */ + char *names[30]; #endif /* MAXFILES */ + #ifdef VERBOSE_ARG + SIGRET (*oldchld)(); + #endif /* VERBOSE_ARG */ 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]; *************** *** 1086,1091 **** --- 1129,1164 ---- char expand = !do_set(set_options, "no_expand"); int fork_err = 0; + /* If edit_hdrs, make sure the correct headers exist and are intact + * before bothering to continue (return 0 to allow user to correct errors). + */ + if (ison(flags, EDIT_HDRS)) { + /* fool header_field into thinking that the file is the folder */ + FILE *save_tmpf = tmpf; + long old_offset = msg[msg_cnt].m_offset; + int err = 0; + + tmpf = ed_fp; + msg[msg_cnt].m_offset = 0L; + if (!(p = header_field(msg_cnt, "to"))) { + wprint("You must have a To: header to send mail.\n(continue)\n"); + err++; + } else { + (void) strcpy(To, p); + Cc[0] = Bcc[0] = 0; + if (p = header_field(msg_cnt, "cc")) + (void) strcpy(Cc, p); + if (p = header_field(msg_cnt, "bcc")) + (void) strcpy(Bcc, p); + if (p = header_field(msg_cnt, "fcc")) + (void) strcat(Bcc, p); + } + msg[msg_cnt].m_offset = old_offset; + tmpf = save_tmpf; + if (err) + return 0; + } + if (!istool) { (void) signal(SIGINT, oldint); (void) signal(SIGQUIT, oldquit); *************** *** 1096,1108 **** 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 --- 1169,1183 ---- p = MAIL_DELIVERY; #ifdef VERBOSE_ARG ! if (ison(flags, VERBOSE) || do_set(set_options, "verbose")) { ! turnon(flags, VERBOSE); /* prevent fork when "verbose" has changed */ ! oldchld = signal(SIGCHLD, SIG_DFL); /* let pclose() do the wait() */ #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 *************** *** 1127,1143 **** 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); } --- 1202,1223 ---- print("address expansion failed for To: line.\n"); rm_edfile(-1); } else { ! next_file += ! find_files(p, files+next_file, names+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) ! if (names[next_file]) { ! close_lock(names[next_file], files[next_file]); ! xfree(names[next_file]); ! } else ! pclose(files[next_file]); rm_edfile(-2); ! return 0; } b += Strcpy(b, p); } *************** *** 1145,1154 **** 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); --- 1225,1239 ---- if (!(p = alias_to_address(Cc))) { print("address expansion failed for Cc: line.\n"); while (--next_file > 0) ! if (names[next_file]) { ! close_lock(names[next_file], files[next_file]); ! xfree(names[next_file]); ! } else ! pclose(files[next_file]); rm_edfile(-1); } else { ! next_file += ! find_files(p, files+next_file, names+next_file, size-next_file); if (expand) (void) strcpy(Cc, p); rm_cmts_in_addr(p); *************** *** 1171,1180 **** 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); --- 1256,1270 ---- if (!(p = alias_to_address(Bcc))) { print("address expansion failed for Bcc: line.\n"); while (--next_file > 0) ! if (names[next_file]) { ! close_lock(names[next_file], files[next_file]); ! xfree(names[next_file]); ! } else ! pclose(files[next_file]); rm_edfile(-1); } else { ! next_file += ! find_files(p, files+next_file, names+next_file, size-next_file); (void) strcpy(Bcc, p); rm_cmts_in_addr(p); skipspaces(0); *************** *** 1202,1212 **** 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); --- 1292,1302 ---- case 0: /* the child will send the letter. ignore signals */ #ifdef SYSV if (setpgrp() == -1) ! #else /* SYSV */ ! if (setpgrp(0, getpid()) == -1) #endif /* SYSV */ ! error("setpgrp"); (void) signal(SIGCHLD, SIG_DFL); (void) signal(SIGINT, SIG_IGN); (void) signal(SIGHUP, SIG_IGN); (void) signal(SIGQUIT, SIG_IGN); *************** *** 1238,1249 **** } #endif /* SUNTOOL */ while (--next_file > 0) ! fclose(files[next_file]); ! #ifdef MMDF ! if (!fork_err) ! (void) wait((int *) 0); ! #endif /* MMDF */ ! return; } #ifdef MMDF --- 1328,1339 ---- } #endif /* SUNTOOL */ while (--next_file > 0) ! if (names[next_file]) { ! close_lock(names[next_file], files[next_file]); ! xfree(names[next_file]); ! } else ! pclose(files[next_file]); ! return 1; } #ifdef MMDF *************** *** 1256,1262 **** if (isoff(flags, VERBOSE) && debug < 3) exit(-1); else ! return; } if (ison(flags, VERBOSE)) --- 1346,1352 ---- if (isoff(flags, VERBOSE) && debug < 3) exit(-1); else ! return 1; } if (ison(flags, VERBOSE)) *************** *** 1275,1283 **** 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; } --- 1365,1377 ---- if (p = do_set(set_options, "logfile")) { if (!*p) p = "~/mail.log"; ! if (!index("~|/+", *p)) ! (void) sprintf(buf, "%s/%s", do_set(set_options, "cwd"), p); ! else ! (void) strcpy(buf, p); log_file = next_file; ! next_file += ! find_files(buf, files+next_file, names+next_file, size-next_file); if (log_file == next_file) log_file = -1; } *************** *** 1286,1382 **** * 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); --- 1380,1412 ---- * the letter in a format such that mail can be read from it */ if (p = do_set(set_options, "record")) { + int foundit; if (!*p) p = "~/record"; ! if (!index("~|/+", *p)) ! (void) sprintf(buf, "%s/%s", do_set(set_options, "cwd"), p); ! else ! (void) strcpy(buf, p); ! next_file += ! find_files(buf, files+next_file, names+next_file, size-next_file); } ! /* First, put the message separator in... */ ! for (size = 1; size < next_file; size++) #ifndef MSG_SEPARATOR ! { ! time_t t; ! (void) time(&t); ! 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 */ /* if redirection, ed_fp = stdin, else rewind the file just made */ if (isoff(glob_flags, REDIRECT)) rewind(ed_fp); *************** *** 1383,1399 **** 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) --- 1413,1438 ---- else ed_fp = stdin; + { + long offset = add_headers(ed_fp, files, next_file, flags); + if (offset == -1) + offset = 0L; + (void) fseek(ed_fp, offset, L_SET); + } + /* 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. */ #ifndef MSG_SEPARATOR + /* If forwarding, skip the leading From_ line of the forwarded message. + * (this isn't done for edit_hdrs since FORWARD wouldn't be set.) + */ 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) *************** *** 1402,1408 **** 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) --- 1441,1466 ---- if (!strncmp(buf, "From ", 5)) fputc('>', files[size]); #endif /* MSG_SEPARATOR */ ! if (fputs(buf, files[size]) == EOF) { ! if (size == 0) { ! error("Lost connection to MTA"); ! dead_letter(); ! break; ! } else { ! /* Drop this file, but continue writing others */ ! error("Write failed"); ! if (names[size]) { ! close_lock(names[size], files[size]); ! xfree(names[size]); ! } ! if (size < --next_file) { ! names[size] = names[next_file]; ! files[size--] = files[next_file]; ! } ! files[next_file] = NULL_FILE; ! names[next_file] = NULL; ! } ! } } /* loop thru the open files (except for the first: the mail delivery agent) *************** *** 1410,1446 **** * 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 */ --- 1468,1723 ---- * Then close the files. If the file was a popened program, the sigchld * that the program generates will close the file. */ for (size = 1; size < next_file; size++) { + #ifdef END_MSG_SEP fputs(END_MSG_SEP, files[size]); #endif /* END_MSG_SEP */ + if (names[size]) { + #ifndef END_MSG_SEP + fputc('\n', files[size]); + #endif /* !END_MSG_SEP */ + close_lock(names[size], files[size]); + xfree(names[size]); + } else + pclose(files[size]); + } if (debug < 3) { int reply_code = pclose(files[0]); Debug("pclose reply_code = %d\n", reply_code); ! rm_edfile((reply_code == (MTA_EXIT << 8))? 0 : -1); } else rm_edfile(0); + #ifdef VERBOSE_ARG + if (ison(flags, VERBOSE)) + (void) signal(SIGCHLD, oldchld); + #endif /* VERBOSE_ARG */ + if ((ison(flags, VERBOSE) || debug > 2) && isoff(glob_flags, REDIRECT)) wprint("sent.\n"); else exit(0); /* not a user exit -- a child exit */ + return 1; + } + + /* + * Add the necessary headers to make a file a legitimate mail message. + * This could be for a file which the user will edit (via edit_hdrs) or + * for delivery to an MTA. + * Make folders conform to RFC-822 by adding From: and Date: headers. + * Prefix certain header with the "Resent-" prefix when forwarding. + * Return offset of fp if we're parsing it for headers (for delivery to MTA). + */ + static long + add_headers(fp, files, size, flags) + FILE *fp, *files[]; + int size; + u_long flags; + { + char buf[256], From_buf[256], *pF = From_buf, date_str[64]; + char *host = NULL, *p, *subj = NULL; + int i, for_editor = (fp == NULL_FILE); + int got_date = for_editor, got_from = for_editor; + + buf[0] = 0; + if (ourname) + host = ourname[0]; + if (for_editor) + turnoff(flags,FORWARD); /* forwarded messages must not be edited */ + + /* [Re]create a From: header -- if not for the editor, use this to check + * to see if the user has changed the previously created one in the editor. + * If his is not legitimate, warn user and use this header. + */ + 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")) || + (p = do_set(set_options, "name"))) + pF += strlen(sprintf(pF, " (%s)", p)); + *pF++ = '\n', *pF++ = 0; + + if (for_editor) { + for (i = 0; i < size; i++) { + fputs(From_buf, files[i]); + fprintf(files[i], "%sDate: %s\n", + ison(flags, FORWARD) ? "Resent-" : "", rfc_date(date_str)); + if (*in_reply_to) + fprintf(files[i], "In-Reply-To: %s\n", in_reply_to); + } + + /* 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 (i = 0; i < size; i++) { + p = opts->value; + skipspaces(0); + if (*p) + fprintf(files[i], "%s %s\n", opts->option, p); + } + } + + if (!do_set(set_options, "no_expand")) { + /* for edit_hdrs, print the headers followed by a blank line */ + if (!(p = alias_to_address(To))) { + wprint("To: alias expansion failed.\n"); + return -1; + } else + (void) strcpy(To, p); + if (Cc[0]) + if (!(p = alias_to_address(Cc))) { + wprint("Cc: alias expansion failed.\n"); + return -1; + } else + (void) strcpy(Cc, p); + if (Bcc[0]) + if (!(p = alias_to_address(Bcc))) { + wprint("Bcc: alias expansion failed.\n"); + return -1; + } else + (void) strcpy(Bcc, p); + } + } else + /* if not for the editor and the user doesn't use edit_hdrs, + * add his own_hdrs by hand here. (also take care of in-reply-to) + */ + if (isoff(flags, EDIT_HDRS) && own_hdrs && + !do_set(set_options, "no_hdrs")) { + struct options *opts; + for (opts = own_hdrs; opts; opts = opts->next) + for (i = 0; i < size; i++) { + p = opts->value; + skipspaces(0); + /* user can't set his own from: and date: headers */ + if (*p && lcase_strncmp(opts->option, "from:", 5) && + lcase_strncmp(opts->option, "date:", 5)) + fprintf(files[i], "%s %s\n", opts->option, p); + } + if (*in_reply_to) + for (i = 0; i < size; i++) + fprintf(files[i], "In-Reply-To: %s\n", in_reply_to); + } + + if (!for_editor && ison(flags, EDIT_HDRS)) { + /* + * copy the headers of the message removing special headers. + */ + int print_hdr = FALSE; + rewind(fp); + while (fgets(buf, sizeof(buf), fp)) { + (void) no_newln(buf); + if (!buf[0]) + break; + /* if the first char is NOT a space, it MUST be a new header. + * Otherwise, it is considered part of the message body. + */ + if (!isspace(buf[0])) { + print_hdr = TRUE; + if (!(p = any(buf, " \t:")) || isspace(*p)) + break; /* this is not a legitimate header */ + skipspaces(1); + if (!*p) + print_hdr = FALSE; /* blank headers are not allowed */ + p = buf; + if (!lcase_strncmp(buf, "resent-", 7)) { + if (ison(flags, EDIT_HDRS)) + wprint("You can't use \"Resent-\" headers in edited messages."); + p += 7; + } + if (!lcase_strncmp(p, "to:", 3) || + !lcase_strncmp(p, "cc:", 3) || + !lcase_strncmp(p, "bcc:", 4) || + !lcase_strncmp(p, "fcc:", 4) || + !lcase_strncmp(p, "x-mailer:", 9) || + !lcase_strncmp(p, "status:", 7)) + print_hdr = FALSE; + else if (!lcase_strncmp(p, "date:", 5)) + if (got_date) + wprint("You can't change or add date headers.\n"); + else { + got_date = TRUE; + (void) sprintf(buf, "%sDate: %s", ison(flags, FORWARD)? + "Resent-" : "", rfc_date(date_str)); + } + else if (!lcase_strncmp(p, "subject:", 8)) + (print_hdr = FALSE), strdup(subj, p); + else if (!lcase_strncmp(p, "from:", 5)) { + if (got_from) { + wprint("You can't set your own From: header.\n"); + print_hdr = FALSE; + } else { + (void) strcpy(buf, From_buf); + (void) no_newln(buf); + got_from = TRUE; + #ifdef PICKY_MAILER + /* don't send From: to mta -- fool "for loop" below + * by initializing the loop at files[1], not files[0] + */ + if (!for_editor) + print_hdr = 2; + #endif /* PICKY_MAILER */ + } + } + } + if (print_hdr) + /* print_hdr will be 2 for From: header */ + for (i = print_hdr-1; i < size; i++) + fputs(buf, files[i]), fputc('\n', files[i]); + } + } + /* now do the required (or changed) headers (Date, To, Cc) */ + wrap_addrs(To, 80); + wrap_addrs(Cc, 80); + wrap_addrs(Bcc, 80); + for (i = 0; i < size; i++) { + if (!for_editor && !got_date) + #ifdef PICKY_MAILER + if (i > 0) + #endif /* PICKY_MAILER */ + fprintf(files[i], "%sDate: %s\n", + ison(flags, FORWARD) ? "Resent-" : "", rfc_date(date_str)); + fprintf(files[i], "X-Mailer: %s\n", VERSION); + if (!got_from) + fputs(From_buf, files[i]); + fprintf(files[i], "%sTo: %s\n", + ison(flags, FORWARD) ? "Resent-" : "", To); + if (for_editor || isoff(flags, EDIT_HDRS)) { + if (*Subject && isoff(flags, FORWARD)) + fprintf(files[i], "Subject: %s\n", Subject); + } else if (subj && *subj) + fputs(subj, files[i]), fputc('\n', files[i]); + if (*Cc || for_editor && do_set(set_options, "askcc")) + fprintf(files[i], "%sCc: %s\n", + ison(flags, FORWARD) ? "Resent-" : "", Cc); + if (i > 0 || for_editor) + /* Do not send these to mail transfer agent */ + if (*Bcc) + fprintf(files[i], "%sBcc: %s\n", + ison(flags, FORWARD) ? "Resent-" : "", Bcc); + if (i > 0) + fprintf(files[i], "Status: OR\n"); + } + for (i = 0; i < size; i++) + fflush(files[i]); + if (buf[0]) /* last attempted header read was a line of msg text */ + for (i = 0; i < size; i++) + fputs(buf, files[i]), fputc('\n', files[i]), fflush(files[i]); + else + if (isoff(flags, FORWARD)) + for (i = 0; i < size; i++) + fputc('\n', files[i]), fflush(files[i]); + return fp? ftell(fp) : (long)TRUE; } /* ARGSUSED */ *** mush-6.4/kit.check Tue Apr 18 17:29:04 1989 --- kit.check Tue Apr 18 17:29:04 1989 *************** *** 1 **** ! Part1-check --- 1 ---- ! Part2 -- Bart Schaefer "And if you believe that, you'll believe anything." -- DangerMouse CSNET / Internet schaefer@cse.ogc.edu UUCP ...{sun,tektronix,verdix}!ogccse!schaefer