From pa.dec.com!decwrl!sun-barr!olivea!uunet!sparky!kent Wed Apr 24 18:37:38 PDT 1991 Article: 2244 of comp.sources.misc Path: pa.dec.com!decwrl!sun-barr!olivea!uunet!sparky!kent From: argv@zipcode.com (Dan Heller) Newsgroups: comp.sources.misc Subject: v18i069: mush - Mail User's Shell, Part12/22 Message-ID: <1991Apr22.000412.18858@sparky.IMD.Sterling.COM> Date: 22 Apr 91 00:04:12 GMT Sender: kent@sparky.IMD.Sterling.COM (Kent Landfield) Organization: Sterling Software, IMD Lines: 1653 Approved: kent@sparky.imd.sterling.com X-Checksum-Snefru: e46a1855 4e24d409 846c84c5 a349d102 Submitted-by: Dan Heller Posting-number: Volume 18, Issue 69 Archive-name: mush/part12 Supersedes: mush: Volume 12, Issue 28-47 #!/bin/sh # do not concatenate these parts, unpack them in order with /bin/sh # file mail.c continued # if test ! -r _shar_seq_.tmp; then echo 'Please unpack part 1 first!' exit 1 fi (read Scheck if test "$Scheck" != 12; then echo Please unpack part "$Scheck" next! exit 1 else exit 0 fi ) < _shar_seq_.tmp || exit 1 if test ! -f _shar_wnt_.tmp; then echo 'x - still skipping mail.c' else echo 'x - continuing file mail.c' sed 's/^X//' << 'SHAR_EOF' >> 'mail.c' && X case 'x': X /* don't save dead.letter -- simulate normal rm_edfile() call */ X rm_edfile(0); X return -1; X /* break; (not specified for lint) */ X default: X if (line[1] == *escape) { X (void) fputs(&line[1], ed_fp); X (void) fputc('\n', ed_fp); X (void) fflush(ed_fp); X return 1; X } else if (line[1] == '?') { X register int x; X (void) do_pager(NULL, TRUE); /* start pager */ X for (x = 0; tilde_commands[x]; x++) { X if (ison(flags, EDIT_HDRS) && TC_EDIT(x)) X continue; X (void) sprintf(buf, "%s%s\n", escape, tilde_commands[x]); X if (do_pager(buf, FALSE) == EOF) X break; X } X if (tilde_commands[x] == NULL) { X (void) sprintf(buf, X "%s%s\t\tBegin a line with a single %s\n", X escape, escape, escape); X (void) do_pager(buf, FALSE); X } X (void) do_pager(NULL, FALSE); /* end pager */ X } else X print("`%c': unknown %c escape. Use %c? for help.\n", X line[1], *escape, *escape); X return 1; X } X if (ed_fp) X (void) fseek(ed_fp, 0L, 2); X if (!istool) X wprint("(continue editing letter)\n"); X return 1; } X /* X * finish up the letter. ask for the cc line, if verify is set, ask to X * verify sending, continue editing, or to dump the whole idea. X * Then check for signature and fortune. Finally, pass it to send_it() X * to actually send it off. X * Return 0 on success, -1 on failure. X */ static int finish_up_letter() { X register char *p; X int c; X char buf[MAXPATHLEN]; X X /* forwarded mail has no additional personalized text */ X if (ison(flags, FORWARD)) { X if (send_it() == -1) { X wprint("Message not sent!\n"); X return -1; X } X turnoff(glob_flags, IS_GETTING); X return 0; X } X X /* REDIRECT should never be on here, but just in case */ X if (isoff(glob_flags, REDIRECT)) { X if (!istool) { X if (isoff(flags, EDIT_HDRS) && do_set(set_options, "askcc")) { X if (p = set_header("Cc: ", Cc, 1)) X (void) strcpy(Cc, p); X } X } X /* ~v on the Cc line asks for verification, first initialize p! */ X p = NULL; X if (!strncmp(Cc, "~v", 2) || X /* Flashy test for $verify either empty or set to "mail" */ X glob(p = do_set(set_options, "verify"), X "{,{,*[ \\,]}mail{,[ \\,]*}}")) { X if (!p) /* so we don't Cc to ~v! */ X *Cc = 0; X for (;;) { #ifdef SUNTOOL X if (istool) X c = (ask("Send Message?") == TRUE)? 's' : 'c'; X else #endif /* SUNTOOL */ X { X print("send, continue editing, discard [s,c,d]? "); X c = Getstr(buf, sizeof(buf), 0); X if (c < 0) X putchar('\n'); X else if (!istool) X c = lower(*buf); X } X if (c == 'd') { X rm_edfile(-2); X return 0; X } else if (c == 'c') { X wprint("(continue editing letter)\n"); X return -1; X } else if (c == 's') X break; X } X } X } X X if (send_it() == -1) { X if (isoff(flags, SEND_NOW)) X wprint("(continue)\n"); X return -1; X } X return 0; } X /* X * actually send the letter. X * 1. reset all the signals because of fork. X * 2. determine recipients (users, address, files, programs) X * 3. determine mailer, fork and return (if not verbose). X * 4. popen mailer, $record, and other files specified in step 1. X * 5. make the headers; this includes To: line, and user set headers, etc... X * 6. copy the letter right into the array of file pointers (step 1). X * 7. close the mailer and other files (step 1) and remove the edit-file. X * return -1 if mail wasn't sent. could be user error, could be the system. X * allow user to try again or to save message to file and abort message. X * return 0 if successful. X */ static int send_it() { X register char *p, *b, *addr_list; #ifdef MAXFILES X register int size = MAXFILES - 1; X FILE *files[MAXFILES]; X char *names[MAXFILES]; #else X register int size = getdtablesize() - 1; X FILE *files[30]; /* 30 should be sufficiently large enough */ X char *names[30]; #endif /* MAXFILES */ #if defined(VERBOSE_ARG) X SIGRET (*oldchld)(); #endif /* VERBOSE_ARG */ X int next_file = 1; /* reserve files[0] for the mail delivery program */ X int log_file = -1; /* the index into the files array for mail logging */ X char buf[3*HDRSIZ]; X char *orig_to, *orig_cc, *orig_bcc; /* save originals to restore on error */ X char expand = !do_set(set_options, "no_expand"); X int fork_pid; X X names[0] = names[1] = NULL; /* for free_vec() */ X /* If edit_hdrs, make sure the correct headers exist and are intact X * before bothering to continue. X */ X if (ison(flags, EDIT_HDRS)) { X /* fool header_field into thinking that the file is the folder */ X FILE *save_tmpf = tmpf; X long old_offset = msg[msg_cnt].m_offset; X X if (!ed_fp) { X wprint("No file for headers!\n"); X return -1; X } X Debug("Getting headers from file ... "); X X tmpf = ed_fp; X msg[msg_cnt].m_offset = 0L; X if (p = header_field(msg_cnt, "to")) { X (void) strcpy(To, p); X Cc[0] = Bcc[0] = 0; X if (p = header_field(msg_cnt, "cc")) X (void) strcpy(Cc, p); X if (p = header_field(msg_cnt, "bcc")) X (void) strcpy(Bcc, p); X if (p = header_field(msg_cnt, "fcc")) X next_file += find_files(p, names+next_file, size-next_file, 1); X } else X *To = 0; /* Error caught below */ X msg[msg_cnt].m_offset = old_offset; X tmpf = save_tmpf; X Debug("\n"); X } X if (!*To) { X wprint("You must have a To: recipient to send mail.\n"); X if (!istool) { X (void) signal(SIGINT, oldint); X (void) signal(SIGQUIT, oldquit); X (void) signal(SIGTERM, oldterm); X } X free_vec(&names[1]); X return -1; X } X X if (!(p = do_set(set_options, "sendmail"))) X p = MAIL_DELIVERY; X #ifdef VERBOSE_ARG X /* Tool mode can't do verbosity -- no window for the MTA output */ X if (!istool && (ison(flags, VERBOSE) || do_set(set_options, "verbose"))) { X turnon(flags, VERBOSE); /* prevent fork when "verbose" has changed */ X oldchld = signal(SIGCHLD, SIG_DFL); /* let pclose() do the wait() */ #ifdef MMDF X b = &buf[strlen(sprintf(buf, "%s%s", p, VERBOSE_ARG))]; #else /* MMDF */ X b = &buf[strlen(sprintf(buf, "%s %s", p, VERBOSE_ARG))]; #endif /* MMDF */ X } else #endif /* VERBOSE_ARG */ X b = buf + Strcpy(buf, p); #ifdef METOO_ARG X if (!strcmp(p, MAIL_DELIVERY) && do_set(set_options, "metoo")) X b += strlen(sprintf(b, " %s", METOO_ARG)); #endif /* METOO_ARG */ X *b++ = ' ', *b = 0; /* strcat(b, " "); */ X addr_list = b; /* save this position to check for addresses later */ X X /* save original list. If alias expansion fails, replace address lists X * with what was originally typed so user can fix it. This isn't necessary X * if the lists are already in the file the user is editing (edit_hdrs). X */ X if (isoff(flags, EDIT_HDRS)) X orig_to = savestr(To); X /* X * Build the address lines to give to the mail transfer system. This X * address line cannot contain comment fields! First, expand aliases X * since they may contain comment fields within addresses. Copy this X * result back into the Buffer since this will go into the header ... X * Next, remove all comments so the buffer contains ONLY valid addresses. X * Next, strip off any filenames/programs which might occur in the list. X * Finally, add this information to the command line buffer (buf). X * Remove commas if necessary (see ifdefs). In the event of errors, X * force a dead letter by rm_edfile(-1). X */ X if (!(p = alias_to_address(To))) { X print("address expansion failed for To: list.\n"); X free_vec(&names[1]); X if (isoff(flags, EDIT_HDRS)) X strcpy(To, orig_to), xfree(orig_to); X return -1; X } else { X next_file += find_files(p, names+next_file, size-next_file, 0); X if (expand) X (void) strcpy(To, p); X rm_cmts_in_addr(p); X skipspaces(0); X b += Strcpy(b, p); X } X if (isoff(flags, EDIT_HDRS)) X orig_cc = savestr(Cc); X if (*Cc) { X if (!(p = alias_to_address(Cc))) { X wprint("address expansion failed for Cc: list.\n"); X free_vec(&names[1]); X if (isoff(flags, EDIT_HDRS)) { X strcpy(To, orig_to), xfree(orig_to); X strcpy(Cc, orig_cc), xfree(orig_cc); X } X return -1; X } else { X next_file += find_files(p, names+next_file, size-next_file, 0); X if (expand) X (void) strcpy(Cc, p); X rm_cmts_in_addr(p); X skipspaces(0); X if (*p) { X *b++ = ',', *b++ = ' '; X b += Strcpy(b, p); X } X } X } X X /* expand Bcc addrs, but don't add to list yet. sign letter first */ X if (isoff(flags, EDIT_HDRS)) X orig_bcc = savestr(Bcc); X if (*Bcc) { X if (p = alias_to_address(Bcc)) X p = strcpy(Bcc, p); X else { X wprint("address expansion failed for Bcc: list.\n"); X free_vec(&names[1]); X /* rm_edfile(-1); */ X if (isoff(flags, EDIT_HDRS)) { X strcpy(To, orig_to), xfree(orig_to); X strcpy(Cc, orig_cc), xfree(orig_cc); X strcpy(Bcc, orig_bcc), xfree(orig_bcc); X } X return -1; X } X } else X p = NULL; X X /* Sign the letter before adding the Bcc list since they aren't X * considered when adding a signature. X */ X if (*addr_list && ison(flags, SIGN|DO_FORTUNE) && X isoff(glob_flags, REDIRECT) && isoff(flags, FORWARD)) X sign_letter(addr_list, flags, ed_fp); X X if (p) { /* p still points to expanded Bcc list */ X next_file += find_files(p, names+next_file, size-next_file, 0); X rm_cmts_in_addr(p); X skipspaces(0); X if (*p) { X *b++ = ',', *b++ = ' '; X b += Strcpy(b, p); X } X } X if (!*addr_list && next_file == 1) { X wprint("There must be at least 1 legal recipient.\n"); X if (isoff(flags, EDIT_HDRS)) { X strcpy(To, orig_to), xfree(orig_to); X strcpy(Cc, orig_cc), xfree(orig_cc); X strcpy(Bcc, orig_bcc), xfree(orig_bcc); X } X return -1; X } X #ifdef NO_COMMAS X for (p = buf; p = index(p, ','); p++) X *p = ' '; #endif /* NO_COMMAS */ X X Debug("mail command: %s\n", buf); X X if (isoff(flags, VERBOSE) && debug < 3) X switch (fork_pid = fork()) { X case 0: /* the child will send the letter. ignore signals */ #if defined(SYSV) && !defined(AUX) X if (setpgrp() == -1) #else /* !SYSV || AUX */ X if (setpgrp(0, getpid()) == -1) #endif /* SYSV && !AUX */ X error("setpgrp"); X /* NOTE: No special case needed for tool here because X * this is the sending child -- it's going to pclose() X * and then exit(), so who cares about the notifier? X */ X (void) signal(SIGCHLD, SIG_DFL); X (void) signal(SIGTERM, SIG_IGN); X (void) signal(SIGINT, SIG_IGN); X (void) signal(SIGHUP, SIG_IGN); X (void) signal(SIGQUIT, SIG_IGN); #ifdef SIGTTIN X (void) signal(SIGTTOU, SIG_IGN); X (void) signal(SIGTTIN, SIG_IGN); #endif /* SIGTTIN */ #ifdef SIGCONT X (void) signal(SIGCONT, SIG_IGN); X (void) signal(SIGTSTP, SIG_IGN); #endif /* SIGCONT */ X turnon(glob_flags, IGN_SIGS); X when -1: X error("fork failed trying to send mail"); X if (isoff(flags, EDIT_HDRS)) { X strcpy(To, orig_to); X strcpy(Cc, orig_cc); X strcpy(Bcc, orig_bcc); X } X /* fall thru */ X default: X if (fork_pid > 0) { #ifdef SUNTOOL X /* If we're a tool, we have to register a handler X * for the fork_pid. Otherwise, it's used only as X * an error indicator, so reset it to zero. X */ X if (istool) X notify_set_wait3_func(mfprint_sw, my_wait3, fork_pid); #endif /* SUNTOOL */ X fork_pid = 0; X } X /* istool doesn't need ed_fp, so don't keep it around */ X if (istool || !fork_pid && isoff(glob_flags, REDIRECT)) X (void) fclose(ed_fp), ed_fp = NULL_FILE; X free_vec(&names[1]); X if (isoff(flags, EDIT_HDRS)) X xfree(orig_to), xfree(orig_cc), xfree(orig_bcc); X if (!istool) { X (void) signal(SIGINT, oldint); X (void) signal(SIGQUIT, oldquit); X (void) signal(SIGTERM, oldterm); X } X return fork_pid; X } X #ifdef MMDF X *(addr_list-1) = '\0'; #endif /* MMDF */ X if (debug > 2) { X files[0] = stdout; X if (!*addr_list) X addr_list = "[no recipients]"; X } else if (*addr_list) { X if (!(files[0] = open_file(buf, TRUE, FALSE))) { X rm_edfile(-1); /* force saving of undeliverable mail */ X if (isoff(flags, VERBOSE) && debug < 3) X exit(-1); X else X return 0; X } X } else X files[0] = NULL_FILE; X X if (ison(flags, VERBOSE)) X wprint("Sending letter ... "), (void) fflush(stdout); #ifdef MMDF X /* give address list to submit */ X for (p = addr_list; *p && (p = any(p, ",<")); p++) X if (*p == ',') X *p = '\n'; X else X p = index(p, '>'); X if (*addr_list) X (void) fprintf(files[0], "%s\n\n", addr_list); #endif /* MMDF */ X X /* see if log is set. This is just to add message headers. No msg body. */ X if (p = do_set(set_options, "logfile")) { X if (!*p) X p = "~/mail.log"; X if (!index("~|/+", *p)) X (void) sprintf(buf, "%s/%s", do_set(set_options, "cwd"), p); X else X (void) strcpy(buf, p); X log_file = next_file; X next_file += find_files(buf, names+next_file, size-next_file, 0); X if (log_file == next_file) X log_file = -1; X } X X /* see if record is set. If so, open that file for appending and add X * the letter in a format such that mail can be read from it X */ X if (p = do_set(set_options, "record")) { X if (!*p) X p = "~/record"; X if (!index("~|/+", *p)) X (void) sprintf(buf, "%s/%s", do_set(set_options, "cwd"), p); X else X (void) strcpy(buf, p); X next_file += find_files(buf, names+next_file, size-next_file, 0); X } X X /* Don't need to open names[0] as files[0], so skip those */ X next_file = 1 + open_list(names + 1, files + 1, next_file - 1); X X /* First, put the message separator in... */ X for (size = 1; size < next_file; size++) #ifndef MSG_SEPARATOR X { X time_t t; X (void) time(&t); X (void) fprintf(files[size], "From %s %s", login, ctime(&t)); X } #else /* MSG_SEPARATOR */ #ifdef MMDF X (void) fputs(MSG_SEPARATOR, files[size]); #else /* MMDF */ X (void) fprintf(files[size], "%s\n", MSG_SEPARATOR); #endif /* MMDF */ #endif /* MSG_SEPARATOR */ X X /* if redirection, ed_fp = stdin, else rewind the file just made */ X if (isoff(glob_flags, REDIRECT)) X rewind(ed_fp); X else X ed_fp = stdin; X #ifndef MSG_SEPARATOR X /* If forwarding or reading a draft, skip the leading From_ line. X * This is done for drafts so that messages saved by dead_letter() X * can be read back in as a draft; in other cases, this isn't done X * for edit_hdrs because FORWARD wouldn't be set. X */ X if (ison(flags, FORWARD|SEND_NOW) && fgets(buf, sizeof buf, ed_fp) && X strncmp(buf, "From ", 5) != 0) X rewind(ed_fp); /* No From_ line (should never happen) */ #endif /* MSG_SEPARATOR */ X { X long offset = add_headers(ed_fp, files, next_file, flags); X if (offset == -1) X offset = 0L; X (void) fseek(ed_fp, offset, L_SET); X } X X /* Read from stdin or the edfile till EOF and send it all to the mailer X * and other open files/folders/programs. Check for "From " at the X * beginnings of these lines to prevent creating new messages in folders. X */ X while (fgets(buf, sizeof buf, ed_fp)) X for (size = 0; size < next_file; size++) { X if (!files[size]) /* files[0] will be NULL if not calling MTA */ X continue; X if (size == log_file) X continue; #ifndef MSG_SEPARATOR X if (!strncmp(buf, "From ", 5)) X (void) fputc('>', files[size]); #endif /* MSG_SEPARATOR */ X if (fputs(buf, files[size]) == EOF) { X if (size == 0) { X error("Lost connection to MTA"); X dead_letter(-1); X break; X } else { X /* Drop this file, but continue writing others */ X if (names[size]) { X error("Write failed: %s", names[size]); X (void) close_lock(names[size], files[size]); X xfree(names[size]); X } else X error("Write failed"); X if (size < --next_file) { X names[size] = names[next_file]; X files[size--] = files[next_file]; X } X files[next_file] = NULL_FILE; X names[next_file] = NULL; X } X } X } X X /* loop thru the open files (except for the first: the mail delivery agent) X * and append a blank line so that ucb-mail can read these folders. X * Then close the files. X */ X for (size = 1; size < next_file; size++) { #ifdef END_MSG_SEP X (void) fputs(END_MSG_SEP, files[size]); #endif /* END_MSG_SEP */ X if (names[size]) { #ifndef END_MSG_SEP X (void) fputc('\n', files[size]); #endif /* !END_MSG_SEP */ X if (close_lock(names[size], files[size]) == EOF) { X error("Warning: Close failed: %s", names[size]); X } X xfree(names[size]); X } else { X if (debug < 3) X (void) fclose(files[size]); /* Don't mess with pclose() */ X else X (void) pclose(files[size]); /* unless we never forked */ X } X } X X if (debug < 3) { X int reply_code = files[0]? pclose(files[0]) : (MTA_EXIT << 8); X Debug("pclose reply_code = %d\n", reply_code); X rm_edfile((reply_code == (MTA_EXIT << 8))? 0 : -1); X } else X rm_edfile(0); X #ifdef VERBOSE_ARG X if (!istool && ison(flags, VERBOSE)) X (void) signal(SIGCHLD, oldchld); #endif /* VERBOSE_ARG */ X X if (ison(flags, VERBOSE) || debug > 2) { X if (isoff(glob_flags, REDIRECT)) X wprint("sent.\n"); X if (!istool) { X (void) signal(SIGINT, oldint); X (void) signal(SIGQUIT, oldquit); X (void) signal(SIGTERM, oldterm); X } X } else X exit(0); /* not a user exit -- a child exit */ X return 0; } X /* X * Add the necessary headers to make a file a legitimate mail message. X * This could be for a file which the user will edit (via edit_hdrs) or X * for delivery to an MTA. X * Make folders conform to RFC-822 by adding From: and Date: headers. X * Prefix certain header with the "Resent-" prefix when forwarding. X * Return offset of fp if we're parsing it for headers (for delivery to MTA). X */ static long add_headers(fp, files, size, flags) FILE *fp, *files[]; int size; u_long flags; { X char buf[BUFSIZ], From_buf[256], *pF = From_buf, date_str[64]; X char *host = NULL, *p, *subj = NULL, *own_from = NULL; /* See WARNING */ X int i, for_editor = (fp == NULL_FILE); X int got_date = for_editor, got_from = for_editor; X struct options *opts; X X if (for_editor && hfile) { X i = file_to_fp(hfile, files[0], "r"); X xfree(hfile), hfile = NULL; X return (i < 0 ? -1 : TRUE); X } X X buf[0] = 0; X if (ourname) X host = ourname[0]; X if (for_editor) X turnoff(flags,FORWARD); /* forwarded messages must not be edited */ X X /* [Re]create a From: header -- check first to see if the user has X * created a From: header with the my_hdr command (the own_hdrs list). X * If his is not legitimate, warn user and use the other header. X */ X if ((for_editor || isoff(flags, EDIT_HDRS)) && X own_hdrs && !do_set(set_options, "no_hdrs")) { X for (opts = own_hdrs; opts; opts = opts->next) X if (!strcmp(opts->option, "From:")) { X p = opts->value; X skipspaces(0); X sprintf(buf, "%sFrom: %s\n", X ison(flags, FORWARD)? "Resent-" : "", p); X own_from = buf; X /* WARNING: the above depends on the following facts: X * 1. If for_editor, own_from will be output immediately, X * so buf will not be overwritten; X * 2. If !for_editor but EDIT_HDRS, the "real" from line X * will be read from the file so own_from isn't needed; X * 3. If neither, From: is the first line output, so X * buf will not be overwritten. X * Any change in the above means a new buffer for own_from X * may be needed. Check carefully. X */ X } X } X if (ison(flags, FORWARD)) X pF += Strcpy(From_buf, "Resent-"); X pF += Strcpy(pF, "From: "); #ifdef UUCP X if (host && *host) X pF += strlen(sprintf(pF, "%s!", host)); #endif /* UUCP */ X pF += Strcpy(pF, login); #ifndef UUCP X if (host && *host) X pF += strlen(sprintf(pF, "@%s", host)); #endif /* UUCP */ X if ((p = do_set(set_options, "realname")) || X (p = do_set(set_options, "name"))) X pF += strlen(sprintf(pF, " (%s)", p)); X *pF++ = '\n', *pF++ = 0; X X /* First print From, Date, In-Reply-To */ X for (i = 0; i < size; i++) { X if (!files[i]) X continue; X if (for_editor) X if (own_from) X (void) fputs(own_from, files[i]); X else X (void) fputs(From_buf, files[i]); X else if (isoff(flags, EDIT_HDRS)) { #ifdef PICKY_MAILER X if (i > 0) #endif /* PICKY_MAILER */ X if (own_from) X (void) fputs(own_from, files[i]); X else X (void) fputs(From_buf, files[i]); X got_from = TRUE; X } X if (for_editor || isoff(flags, EDIT_HDRS)) { #ifdef PICKY_MAILER X if (i > 0 && !for_editor) #endif /* PICKY_MAILER */ X (void) fprintf(files[i], "%sDate: %s\n", X ison(flags, FORWARD) ? "Resent-" : "", rfc_date(date_str)); X got_date = TRUE; X if (*in_reply_to) X fprintf(files[i], "In-Reply-To: %s\n", in_reply_to); X } X } X if (own_from) X *own_from = 0; /* buf[0] must be 0 below */ X /* next print user's own message headers */ X if (for_editor || isoff(flags, EDIT_HDRS)) X if (own_hdrs && !do_set(set_options, "no_hdrs")) { X for (opts = own_hdrs; opts; opts = opts->next) { X if (!strcmp(opts->option, "From:")) X continue; X for (i = 0; i < size; i++) { X if (!files[i]) X continue; X p = opts->value; X skipspaces(0); X fprintf(files[i], "%s %s\n", opts->option, p); X } X } X } X X /* X * Now either prepare to put the rest of the headers into the file X * or (when sending edited headers) copy them back out of the file X */ X if (for_editor) { X char *orig = NULL; X /* for edit_hdrs, print the headers followed by a blank line */ X if (To[0]) { X orig = savestr(To); X if (!(p = alias_to_address(To))) { X wprint("To: list unmodified.\n"); X p = orig; X } X (void) strcpy(To, p); X } X if (Cc[0]) { X strdup(orig, Cc); X if (!(p = alias_to_address(Cc))) { X wprint("Cc: list unmodified.\n"); X p = orig; X } X (void) strcpy(Cc, p); X } X if (Bcc[0]) { X strdup(orig, Bcc); X if (!(p = alias_to_address(Bcc))) { X wprint("Bcc: list unmodified.\n"); X p = orig; X } X (void) strcpy(Bcc, p); X } X xfree(orig); X } else if (ison(flags, EDIT_HDRS)) { X /* copy the headers of the message removing special headers */ X int print_hdr = FALSE; X if (isoff(flags, SEND_NOW)) X rewind(fp); /* Drafts may have had fp positioned */ X while (fgets(buf, sizeof(buf), fp)) { X (void) no_newln(buf); X if (!buf[0]) X break; X /* if the first char is NOT a space, it MUST be a new header. X * Otherwise, it is considered part of the message body. X */ X if (!isspace(buf[0])) { X print_hdr = TRUE; X if (!(p = any(buf, " \t:")) || isspace(*p)) X break; /* this is not a legitimate header */ X skipspaces(1); X if (!*p) X print_hdr = FALSE; /* blank headers are not allowed */ X p = buf; X if (!lcase_strncmp(buf, "resent-", 7)) { X if (ison(flags, EDIT_HDRS)) X wprint("You can't use \"Resent-\" headers in edited messages.\n"); X p += 7; X } X if (!lcase_strncmp(p, "to:", 3) || X !lcase_strncmp(p, "cc:", 3) || X !lcase_strncmp(p, "bcc:", 4) || X !lcase_strncmp(p, "fcc:", 4) || X !lcase_strncmp(p, "x-mailer:", 9) || X !lcase_strncmp(p, "status:", 7)) X print_hdr = FALSE; X else if (!lcase_strncmp(p, "date:", 5)) X if (got_date) X wprint("You can't change or add date headers.\n"); X else { X got_date = TRUE; X (void) sprintf(buf, "Date: %s", rfc_date(date_str)); X p = buf; X } X else if (!lcase_strncmp(p, "subject:", 8)) X (print_hdr = FALSE), strdup(subj, p); X else if (!lcase_strncmp(p, "from:", 5)) { X char not_me[BUFSIZ]; X (void) strcpy(not_me, buf + 5); X take_me_off(not_me); X if (*not_me) { X /* Ignore bogus From: if we have a good one */ X if (got_from) X print_hdr = FALSE; X /* otherwise, output a good one */ X else { X (void) strcpy(buf, From_buf); X (void) no_newln(buf); X } X } X got_from = TRUE; #ifdef PICKY_MAILER X /* don't send From: to mta -- fool "for loop" below X * by initializing the loop at files[1], not files[0] X */ X if (!for_editor) X print_hdr = 2; #endif /* PICKY_MAILER */ X } X } X if (print_hdr) X /* print_hdr may be 2 for From: header */ X for (i = print_hdr-1; i < size; i++) X if (files[i]) { X (void) fputs(buf, files[i]); X (void) fputc('\n', files[i]); X } X } X } X /* Finally, do the required (or changed) headers (Date, To, Cc) */ X (void) wrap_addrs(To, 80); X (void) wrap_addrs(Cc, 80); X (void) wrap_addrs(Bcc, 80); X for (i = 0; i < size; i++) { X if (!files[i]) X continue; #ifdef PICKY_MAILER X if (i > 0) { #endif /* PICKY_MAILER */ X if (!got_from) X (void) fputs(From_buf, files[i]); X if (!got_date) X (void) fprintf(files[i], "%sDate: %s\n", X ison(flags, FORWARD) ? "Resent-" : "", rfc_date(date_str)); #ifdef PICKY_MAILER X } #endif /* PICKY_MAILER */ X (void) fprintf(files[i], "X-Mailer: %s\n", check_internal("version")); X (void) fprintf(files[i], "%sTo: %s\n", X ison(flags, FORWARD) ? "Resent-" : "", To); X if (for_editor || isoff(flags, EDIT_HDRS)) { X if (isoff(flags, FORWARD) && X (*Subject || for_editor && (do_set(set_options, "ask") || X do_set(set_options, "asksub")))) X (void) fprintf(files[i], "Subject: %s\n", Subject); X } else if (subj && *subj && strlen(subj) > 9) X (void) (fputs(subj, files[i]), fputc('\n', files[i])); X if (*Cc || for_editor && do_set(set_options, "askcc")) X (void) fprintf(files[i], "%sCc: %s\n", X ison(flags, FORWARD) ? "Resent-" : "", Cc); X if (i > 0 || for_editor) X /* Do not send these to mail transfer agent */ X if (*Bcc) X (void) fprintf(files[i], "%sBcc: %s\n", X ison(flags, FORWARD) ? "Resent-" : "", Bcc); X if (i > 0) X (void) fprintf(files[i], "Status: OR\n"); X } X for (i = 0; i < size; i++) X if (files[i]) X (void) fflush(files[i]); X if (buf[0]) /* last attempted header read was a line of msg text */ X for (i = 0; i < size; i++) { X if (files[i]) { X (void) fputs(buf, files[i]); X (void) fputc('\n', files[i]); X (void) fflush(files[i]); X } X } X else X if (isoff(flags, FORWARD)) X for (i = 0; i < size; i++) X if (files[i]) { X (void) fputc('\n', files[i]); X (void) fflush(files[i]); X } X return fp? ftell(fp) : (long)TRUE; } X /* ARGSUSED */ SIGRET rm_edfile(sig) { X if (sig > 0) { X char *fix; X if (ison(glob_flags, IGN_SIGS)) X return; X /* wrapcolumn may have been trashed -- restore it */ X if ((fix = do_set(set_options, "wrapcolumn")) && *fix) X wrapcolumn = atoi(fix); X mac_flush(); /* abort pending macros */ X } X /* now check whether we should abort the letter */ X if (sig > 0 && !killme && ison(glob_flags, IS_GETTING)) { X if (!istool) X (void) signal(sig, rm_edfile); X killme = 1; X print("\n** interrupt -- one more to kill letter **\n"); X longjmp(cntrl_c_buf, 1); X } X killme = 0; X /* if sig == -1, force a save into dead.letter. X * else, check for nosave not being set and save anyway if it's not set X * sig == 0 indicates normal exit (or ~x), so don't save a dead letter. X */ X if (sig == -1 || sig != 0 && !do_set(set_options, "nosave")) X dead_letter(sig); X if (isoff(glob_flags, REDIRECT) && ed_fp) /* ed_fp may be null in toolmode*/ X (void) fclose(ed_fp), ed_fp = NULL_FILE; X (void) unlink(edfile); X X turnoff(glob_flags, IS_GETTING); X if (sig == -1) X return; X X if (sig == SIGHUP) X cleanup(0); X if (!istool) { X (void) signal(SIGINT, oldint); X (void) signal(SIGQUIT, oldquit); X (void) signal(SIGTERM, oldterm); X } X X if (sig == 0 || sig == -2 || istool) /* make sure sigchld is reset first */ X return; X X if (isoff(glob_flags, DO_SHELL)) { /* If we're not in a shell, exit */ X puts("exiting"); X echo_on(); X exit(1); X } X longjmp(jmpbuf, 1); } X /* save letter into dead letter */ dead_letter(sig) int sig; /* signal passed to rm_edfile() or 0 */ { X char *p, buf[BUFSIZ]; X long t; X FILE *dead; X X if (ison(glob_flags, REDIRECT)) { X print("input redirected -- can't save dead letter.\n"); X return; X } X /* If the file doesn't exist, get outta here. File may not exist if X * user generated a ^C from a promptable header and catch sent us here. X */ X if (!ed_fp && Access(edfile, R_OK) != 0) X return; X /* User may have killed mush via a signal while he was in an editor. X * ed_fp will be NULL in this case. Since the file does exist (above), X * open it so we can copy it to dead letter. X */ X if (!ed_fp && !(ed_fp = fopen(edfile, "r"))) { X error("can't save dead letter from %s", edfile); X return; X } X /* don't save a dead letter if there's nothing to save. */ X if (fseek(ed_fp, 0L, 2) || ftell(ed_fp) <= 1L) X return; X if (!(p = do_set(set_options, "dead"))) X p = "~/dead.letter"; X if (!(dead = open_file(p + (*p == '|'), (*p == '|'), TRUE))) X return; X (void) time (&t); X (void) fflush(ed_fp); X rewind(ed_fp); #ifdef MSG_SEPARATOR X (void) fputs(MSG_SEPARATOR, dead); #ifndef MMDF X (void) fputc('\n', dead); #endif /* MMDF */ #else /* MSG_SEPARATOR */ X (void) fprintf(dead, "From %s %s", login, ctime(&t)); #endif /* MSG_SEPARATOR */ X (void) fprintf(dead, "From: %s\nTo: %s\nSubject: %s\n", login, To, Subject); X (void) fprintf(dead, "Date: %s\n", rfc_date(buf)); X if (*Cc) X (void) fprintf(dead, "Cc: %s\n", Cc); X if (*Bcc) X (void) fprintf(dead, "Bcc: %s\n", Bcc); X (void) fputc('\n', dead); X while (fgets(buf, sizeof(buf), ed_fp)) X (void) fputs(buf, dead); X (void) fputc('\n', dead); #ifdef END_MSG_SEP X (void) fputs(END_MSG_SEP, dead); #endif /* END_MSG_SEP */ X if (*p != '|') X (void) close_lock(p, dead); X else X (void) pclose(dead); X wprint("Saved%s letter in %s.\n", sig > 0? " unfinished" : "", p); } SHAR_EOF echo 'File mail.c is complete' && chmod 0644 mail.c || echo 'restore of mail.c failed' Wc_c="`wc -c < 'mail.c'`" test 57669 -eq "$Wc_c" || echo 'mail.c: original size 57669, current size' "$Wc_c" rm -f _shar_wnt_.tmp fi # ============= mail.icon.1 ============== if test -f 'mail.icon.1' -a X"$1" != X"-c"; then echo 'x - skipping mail.icon.1 (File already exists)' rm -f _shar_wnt_.tmp else > _shar_wnt_.tmp echo 'x - extracting mail.icon.1 (Text)' sed 's/^X//' << 'SHAR_EOF' > 'mail.icon.1' && /* Format_version=1, Width=64, Height=64, Depth=1, Valid_bits_per_item=16 X */ X 0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x8000,0x0000,0x0000,0x0001, X 0x8000,0x0000,0x0000,0x0001,0x8000,0x0000,0x0000,0x0001, X 0x8000,0x0000,0x0000,0x0001,0x8000,0x0000,0x0000,0x0001, X 0x8000,0x0000,0x0000,0x0001,0x8000,0x0000,0x0000,0x0001, X 0x8000,0x0000,0x0000,0x0001,0x8000,0x1FFF,0xFFFF,0xFE01, X 0x8000,0xFE00,0x0000,0x0181,0x8007,0x01C0,0x0000,0x0061, X 0x8018,0x0030,0x0000,0x0011,0x8020,0x7008,0x0000,0x0011, X 0x80C1,0xFC06,0x0000,0x0009,0x8101,0xFC01,0x0000,0x0009, X 0x8103,0xFE01,0x0000,0x0005,0x8203,0xFE00,0x8000,0x0005, X 0x8403,0xFE00,0x4000,0x0005,0x8401,0xFC00,0x4000,0x0005, X 0x8801,0xFC00,0x2000,0x0005,0x8800,0x7000,0x2000,0x0005, X 0x8800,0x0000,0x3000,0x0005,0x9000,0x0000,0x1000,0x0005, X 0x9000,0x0000,0x1000,0x0005,0x93FF,0xFFFF,0x9000,0x0025, X 0xA200,0x0000,0x9000,0x00E5,0xA200,0x0000,0x9000,0x03A5, X 0xA200,0x0000,0x9000,0x0625,0xA3FF,0xFFFF,0x9000,0x1C25, X 0xA000,0x0000,0x1000,0x3425,0xA000,0x0000,0x1000,0xC425, X 0xA000,0x0000,0x1003,0x8425,0xA000,0x0000,0x1006,0x0425, X 0xA000,0x0000,0x101C,0x0425,0xA000,0x0000,0x11F0,0x0425, X 0xA000,0x0000,0x13E0,0x0445,0xA000,0x0000,0x13E0,0x0585, X 0xA000,0x0000,0x13E0,0x0605,0xA000,0x0000,0x11C0,0x0405, X 0xA000,0x0000,0x1000,0x000D,0xA000,0x0000,0x1000,0x0011, X 0xA000,0x0000,0x1000,0x0021,0xA000,0x0000,0x1000,0x00C1, X 0xA000,0x0000,0x1000,0x0101,0xA000,0x0000,0x1000,0x0601, X 0xA000,0x0000,0x1000,0x0801,0xA000,0x0000,0x1000,0x3801, X 0xA000,0x0000,0x1000,0x4801,0xA000,0x0000,0x1000,0x8801, X 0xA000,0x0000,0x1003,0x0801,0xA000,0x0000,0x1004,0x0801, X 0xA000,0x0000,0x101C,0x0801,0xA000,0x0000,0x1024,0x0801, X 0xA000,0x0000,0x1044,0x0801,0xA000,0x0000,0x1184,0x0801, X 0xA000,0x0000,0x1204,0x0801,0xA000,0x0000,0x1404,0x0801, X 0xBFFF,0xFFFF,0xF804,0x0801,0x8000,0x0000,0x0004,0x0801, X 0x8000,0x0000,0x0004,0x0801,0x8000,0x0000,0x0004,0x0801, X 0x8000,0x0000,0x0004,0x0801,0xFFFF,0xFFFF,0xFFFF,0xFFFF SHAR_EOF chmod 0644 mail.icon.1 || echo 'restore of mail.icon.1 failed' Wc_c="`wc -c < 'mail.icon.1'`" test 1933 -eq "$Wc_c" || echo 'mail.icon.1: original size 1933, current size' "$Wc_c" rm -f _shar_wnt_.tmp fi # ============= mail.icon.2 ============== if test -f 'mail.icon.2' -a X"$1" != X"-c"; then echo 'x - skipping mail.icon.2 (File already exists)' rm -f _shar_wnt_.tmp else > _shar_wnt_.tmp echo 'x - extracting mail.icon.2 (Text)' sed 's/^X//' << 'SHAR_EOF' > 'mail.icon.2' && /* Format_version=1, Width=64, Height=64, Depth=1, Valid_bits_per_item=16 X */ X 0xFFFF,0xFFFF,0xFFFF,0xFFFF,0x8000,0x0000,0x0000,0x0001, X 0x8000,0x0000,0x0000,0x0001,0x8000,0x0000,0x00E0,0x0001, X 0x8000,0x0000,0x00DE,0x0001,0x8000,0x0000,0x00C1,0xE001, X 0x8000,0x0000,0x00C0,0x1801,0x8000,0x0000,0x00C0,0x0801, X 0x8000,0x0000,0x00C0,0x0801,0x8000,0x1FFF,0xFFC0,0x0E01, X 0x8000,0xFE00,0x00C0,0x0981,0x8007,0x01C0,0x00C0,0x0861, X 0x8018,0x0030,0x00C0,0x0811,0x8020,0x7008,0x00C0,0x0811, X 0x80C1,0xFC06,0x00C0,0x1809,0x8101,0xBC01,0x00C0,0x6009, X 0x8103,0x1E01,0x00C1,0x8005,0x8202,0x0E00,0x80C6,0x0005, X 0x8404,0x0400,0x40D8,0x0005,0x8408,0x0200,0x40E0,0x0005, X 0x8810,0x0100,0x20C0,0x0005,0x8820,0x6080,0x20C0,0x0005, X 0x8840,0x4040,0x30C0,0x0005,0x9081,0x3020,0x10C0,0x0005, X 0x9041,0x9C10,0x10C0,0x0005,0x93E0,0x8A0F,0x90C0,0x0005, X 0xA210,0x6404,0x90C0,0x0005,0xA208,0x3002,0x90C0,0x0005, X 0xA204,0x1401,0x90C0,0x0005,0xA3FF,0xFFFF,0x90C0,0x0005, X 0xA000,0x0000,0x10C0,0x0005,0xA000,0x0000,0x10C0,0x0005, X 0xA000,0x0000,0x10C0,0x0005,0xA000,0x0000,0x10C0,0x0005, X 0xA000,0x0000,0x10C0,0x0005,0xA000,0x0000,0x11C0,0x0005, X 0xA000,0x0000,0x13E0,0x0005,0xA000,0x0000,0x13E0,0x0005, X 0xA000,0x0000,0x13E0,0x0005,0xA000,0x0000,0x11C0,0x0005, X 0xA000,0x0000,0x1000,0x000D,0xA000,0x0000,0x1000,0x0011, X 0xA000,0x0000,0x1000,0x0021,0xA000,0x0000,0x1000,0x00C1, X 0xA000,0x0000,0x1000,0x0101,0xA000,0x0000,0x1000,0x0601, X 0xA000,0x0000,0x1000,0x0801,0xA000,0x0000,0x1000,0x3001, X 0xA000,0x0000,0x1000,0x4001,0xA000,0x0000,0x1000,0x8001, X 0xA000,0x0000,0x1003,0x8001,0xA000,0x0000,0x1004,0x8001, X 0xA000,0x0000,0x1018,0x8001,0xA000,0x0000,0x1020,0x8001, X 0xA000,0x0000,0x1060,0x8001,0xA000,0x0000,0x1180,0x8001, X 0xA000,0x0000,0x1280,0x8001,0xA000,0x0000,0x1480,0x8001, X 0xBFFF,0xFFFF,0xFC80,0x8001,0x8000,0x0000,0x0080,0x8001, X 0x8000,0x0000,0x0080,0x8001,0x8000,0x0000,0x0080,0x8001, X 0x8000,0x0000,0x0080,0x8001,0xFFFF,0xFFFF,0xFFFF,0xFFFF SHAR_EOF chmod 0644 mail.icon.2 || echo 'restore of mail.icon.2 failed' Wc_c="`wc -c < 'mail.icon.2'`" test 1933 -eq "$Wc_c" || echo 'mail.icon.2: original size 1933, current size' "$Wc_c" rm -f _shar_wnt_.tmp fi # ============= main.c ============== if test -f 'main.c' -a X"$1" != X"-c"; then echo 'x - skipping main.c (File already exists)' rm -f _shar_wnt_.tmp else > _shar_wnt_.tmp echo 'x - extracting main.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'main.c' && /* @(#)main.c (c) copyright 10/18/86 (Dan Heller) */ X #include "mush.h" #include "options.h" X #if defined(sun) && defined(M_DEBUG) cpu() { X print("CPU time limit exceeded!\n"); } #endif /* sun && DEBUG */ X #ifdef LCKDFLDIR extern char *lckdfldir; #endif /* LCKDFLDIR */ X #ifdef DOT_LOCK int sgid; #ifdef BSD int rgid; #endif /* BSD */ #endif /* DOT_LOCK */ X /*ARGSUSED*/ /* we ignore envp */ main(argc, argv) int argc; char *argv[]; { X int n; X char buf[MAXPATHLEN]; X register char *p; X struct mush_flags Flags; X #ifndef INTERNAL_MALLOC X extern char *stackbottom; /* used by xfree() */ X X stackbottom = (char *) &argc; #endif /* INTERNAL_MALLOC */ X #ifdef AUX X set42sig(); /* Use 4.2 BSD signal handling conventions */ #endif /* AUX */ X #ifdef LCKDFLDIR X lckdfldir = LCKDFLDIR; #endif /* LCKDFLDIR */ X prog_name = basename(*argv); X X (void) signal(SIGBUS, bus_n_seg); X (void) signal(SIGSEGV, bus_n_seg); X (void) signal(SIGPIPE, SIG_IGN); /* if pager is terminated before end */ X #if defined(sun) && defined(M_DEBUG) X (void) signal(SIGXCPU, cpu); X X if (p = getenv("MALLOC_DEBUG")) X malloc_debug(atoi(p)); X else X malloc_debug(0); #endif /* sun && debug */ X X if (!isatty(0)) X turnon(glob_flags, REDIRECT); X else X (void) setbuf(stdin, NULL); X X init(); /* must be done before checking mail since "login" is set here */ X mailfile = ""; #ifdef HOMEMAIL X { X char *home = do_set(set_options, "home"); X if (!home) X home = ALTERNATE_HOME; X strdup(spoolfile, sprintf(buf, "%s/%s", home, MAILFILE)); X } #else /* HOMEMAIL */ X strdup(spoolfile, sprintf(buf, "%s/%s", MAILDIR, login)); #endif /* HOMEMAIL */ X X n = preparse_opts(&argc,argv); X X /* check for any mail at all and exit if we're not continuing */ X if (!n) { X struct stat statb; X if (stat(spoolfile, &statb) || statb.st_size == 0) { X (void) printf("No mail for %s.\n", login); X exit(0); X } X } X #ifdef DOT_LOCK X sgid = getegid(); #ifdef BSD X rgid = getgid(); X setregid(sgid, rgid); #else X setgid(getgid()); #endif /* BSD */ #endif /* DOT_LOCK */ X X parse_options(&argv, &Flags); X X (void) cmd_line(strcpy(buf, "set cmd_help"), NULL); #ifdef SUNTOOL X if (istool) X (void) cmd_line(strcpy(buf, "set tool_help"), NULL); #endif /* SUNTOOL */ X X set_cwd(); X X if (Flags.init_file) X (void) cmd_line(sprintf(buf, "source %s", Flags.init_file), msg_list); X if (Flags.source_rc > 0) { X /* use cmd_line() in case DEFAULT_RC has expandable chars */ X (void) cmd_line(sprintf(buf, "source %s", DEFAULT_RC), msg_list); X } X if (Flags.source_rc > -1) X (void) source(0, DUBL_NULL); X mailfile = Flags.folder; X X if (*spoolfile != '/') { X n = 1; X p = getpath(spoolfile, &n); X if (n == -1) X (void) fputs(p, stderr), exit(1); X else if (n) X (void) fprintf(stderr, "\"%s\" is a directory.\n", p), exit(1); X else if (*p != '/') { X /* if it still isn't a full path, make it one */ X char *wd = do_set(set_options, "cwd"); X if (*wd) { X (void) sprintf(buf, "%s/%s", wd, p); X strdup(spoolfile, buf); X } else X strdup(spoolfile, p); X } else X strdup(spoolfile, p); X } X #ifdef SUNTOOL X if (istool) { X make_tool(); X turnon(glob_flags, DO_SHELL); X turnoff(glob_flags, REDIRECT); /* -- SunOS-4.0 has a problem here */ X } #endif /* SUNTOOL */ X X /* now we're ready for I/O */ X if (isoff(glob_flags, REDIRECT)) { X /* make sure we can always recover from no echo mode */ X (void) signal(SIGINT, catch); X (void) signal(SIGQUIT, catch); X (void) signal(SIGHUP, catch); X if (istool) X turnon(glob_flags, ECHO_FLAG); X tty_settings(); #ifdef SIGCONT X (void) signal(SIGTSTP, stop_start); /* this will take care of SIGCONT */ #endif /* SIGCONT */ X /* echo_off() checks to see if echo_flg is set, so don't worry */ X echo_off(); X } X X if (!istool && ison(glob_flags, IS_SENDING)) { X char recipients[BUFSIZ], *mailv[16]; X (void) argv_to_string(recipients, argv); X fix_up_addr(recipients); X mailv[0] = "mail"; X n = 1; X if (ison(Flags.flg, VERBOSE)) X mailv[n++] = "-v"; X if (Flags.Subj && *(Flags.Subj)) { X mailv[n++] = "-s"; X mailv[n++] = Flags.Subj; X } X if (Flags.Cc && *(Flags.Cc)) { X fix_up_addr(Flags.Cc); X mailv[n++] = "-c"; X mailv[n++] = Flags.Cc; X } X if (Flags.Bcc && *(Flags.Bcc)) { X fix_up_addr(Flags.Bcc); X mailv[n++] = "-b"; X mailv[n++] = Flags.Bcc; X } X if (ison(Flags.flg, NO_SIGN)) X mailv[n++] = "-u"; X if (ison(Flags.flg, SEND_NOW)) X mailv[n++] = "-U"; X if (Flags.draft) { X if (isoff(Flags.flg, SEND_NOW)) X mailv[n++] = "-E"; X mailv[n++] = "-h"; X mailv[n++] = Flags.draft; X } X mailv[n++] = recipients; X mailv[n] = NULL; X /* set now in case user is not running shell, but is running debug */ X if (!istool) X (void) signal(SIGCHLD, sigchldcatcher); X if (!setjmp(jmpbuf)) X (void) do_mail(n, mailv, msg_list); X /* do shell set from above: "mush -S user" perhaps */ X if (isoff(glob_flags, DO_SHELL) && !*mailfile) { X if (isoff(glob_flags, REDIRECT)) X echo_on(); X exit(0); X } X } X turnoff(glob_flags, IS_SENDING); /* no longer sending mail; running shell */ X X if (ison(glob_flags, REDIRECT) X && (!Flags.src_file || !Flags.src_n_exit)) { X puts("You can't redirect input unless you're sending mail."); X puts("If you want to run a shell with redirection, use \"-i\""); X cleanup(0); X } X if (!*mailfile) { X strdup(mailfile, spoolfile); X if (!mail_size() && isoff(glob_flags, DO_SHELL)) { X /* we know it's not the spool file here */ X (void) printf("No mail in %s.\n", mailfile); X echo_on(), exit(0); X } X } X X if (!hdrs_only) { X /* catch will test DO_SHELL and try to longjmp if set. this is a X * transition state from no-shell to do-shell to ignore sigs to X * avoid a longjmp botch. Note setjmp isn't called until do_loop(). X */ X turnon(glob_flags, IGN_SIGS); #ifdef CURSES X if (ison(glob_flags, PRE_CURSES)) X (void) curses_init(0, DUBL_NULL); X turnoff(glob_flags, PRE_CURSES); #endif /* CURSES */ X } X X /* find a free tmpfile */ X if (!(p = getdir(do_set(set_options, "tmpdir")))) alted: X p = ALTERNATE_HOME; X { X int pid = getpid(); X while (!Access(sprintf(tempfile, "%s/.%s%d", p, prog_name, pid++), F_OK)) X ; X } X /* just create the file, make sure it's empty. It'll close later and X * be reopened for reading only. X */ X if (!(tmpf = mask_fopen(tempfile, "w"))) { X if (strcmp(p, ALTERNATE_HOME)) X goto alted; X error("Can't create tempfile %s", tempfile); X cleanup(0); X } X X /* do pseudo-intelligent stuff with certain signals */ X (void) signal(SIGINT, catch); X (void) signal(SIGQUIT, catch); X (void) signal(SIGHUP, catch); X X if (!hdrs_only && !istool && (!Flags.src_file || !Flags.src_n_exit) && X !glob(do_set(set_options, "quiet"), "{,{,*[ \\,]}startup{,[ \\,]*}}")) X (void) printf("%s: Type '?' for help.\n", check_internal("version")); X X (void) sprintf(buf, "folder %s %s", Flags.f_flags, mailfile); X if ((argv = mk_argv(buf, &argc, TRUE)) && argc > 0) { X if (folder(argc, argv, NULL) == -1 && isoff(glob_flags, DO_SHELL)) { X if (iscurses) X putchar('\n'); X turnoff(glob_flags, IGN_SIGS), cleanup(0); X } #ifdef CURSES X if (iscurses) X (void) curses_help_msg(TRUE); #endif /* CURSES */ X free_vec(argv); X } X X if (hdrs_only) { X (void) sprintf(buf, "headers %s", hdrs_only); X if (argv = make_command(buf, TRPL_NULL, &argc)) X (void) do_hdrs(argc, argv, NULL); X cleanup(0); X } X X turnon(glob_flags, DO_SHELL); X X /* finally, if the user wanted to source a file to execute, do it now */ X if (Flags.src_file) { X char *s_argv[2]; X s_argv[1] = Flags.src_file; X (void) source(2, s_argv); X if (!istool && Flags.src_n_exit) X cleanup(0); X } X #ifdef SUNTOOL X if (istool) { X char buf[16]; X n = 0; X if (time_out < 30) X time_out = 30; X turnoff(glob_flags, IGN_SIGS); X (void) do_hdrs(0, DUBL_NULL, NULL); X timerclear(&(mail_timer.it_interval)); X timerclear(&(mail_timer.it_value)); X X /* Reload time with value of timeout upon timer expiration. */ X mail_timer.it_interval.tv_sec = time_out; X X mail_timer.it_value.tv_sec = time_out; X (void) notify_set_itimer_func(tool, do_check, X ITIMER_REAL, &mail_timer, (struct itimerval *) 0); X timeout_cursors(FALSE); X window_main_loop(tool); X cleanup(0); X } #endif /* SUNTOOL */ X do_loop(); } X do_version() { X print("%s\n", check_internal("version")); X return -1; } X /* set the current working directory */ set_cwd() { X char cwd[MAXPATHLEN]; X X if (GetCwd(cwd, MAXPATHLEN) == NULL) { X error("set_cwd: %s", cwd); X (void) un_set(&set_options, "cwd"); X } else { X char *argv[4]; X argv[0] = "cwd"; X argv[1] = "="; X argv[2] = cwd; X argv[3] = NULL; X (void) add_option(&set_options, argv); X } } SHAR_EOF chmod 0644 main.c || echo 'restore of main.c failed' Wc_c="`wc -c < 'main.c'`" test 8757 -eq "$Wc_c" || echo 'main.c: original size 8757, current size' "$Wc_c" rm -f _shar_wnt_.tmp fi # ============= makefile.bsd ============== if test -f 'makefile.bsd' -a X"$1" != X"-c"; then echo 'x - skipping makefile.bsd (File already exists)' rm -f _shar_wnt_.tmp else > _shar_wnt_.tmp echo 'x - extracting makefile.bsd (Text)' sed 's/^X//' << 'SHAR_EOF' > 'makefile.bsd' && # makefile.bsd (c) copyright 1991 (Dan Heller) # SunOS users should add -DSUN_3_5, -DSUN_4_0, or -DSUN_4_1 to CFLAGS. # HDRS= mush.h config.h-dist strings.h bindings.h options.h version.h glob.h X SRCS= main.c init.c misc.c mail.c hdrs.c execute.c commands.c print.c dates.c \ X signals.c setopts.c msgs.c pick.c sort.c expr.c folders.c \ X loop.c viewopts.c curses.c curs_io.c bind.c file.c strings.c \ X lock.c macros.c options.c addrs.c malloc.c glob.c command2.c OBJS= main.o init.o misc.o mail.o hdrs.o execute.o commands.o print.o file.o \ X signals.o setopts.o msgs.o pick.o sort.o expr.o strings.o \ X folders.o dates.o loop.o viewopts.o curses.o curs_io.o bind.o \ X lock.o macros.o options.o addrs.o malloc.o glob.o command2.o X HELP_FILES= README README-7.0 README-7.1 README-7.2.0 README-7.2.2 mush.1 \ X cmd_help Mushrc Mailrc Gnurc sample.mushrc advanced.mushrc digestify X MAKES= makefile.bsd makefile.xenix makefile.sys.v makefile.hpux makefile.sun X # See the README for changes needed to compile under Ultrix. # In particular, you may need -DSIGRET=void and/or -ltermcap. CFLAGS= -O -DCURSES -DBSD LDFLAGS= LINTFLAGS= -bxah -Dlint -DCURSES -DBSD LIBES= -lcurses -ltermlib OTHERLIBS= # Use some variant of this one if you #define MMDF in config.h #OTHERLIBS=/usr/src/mmdf/lib/libmmdf.a X mush: $(OBJS) X @echo loading... X @cc $(LDFLAGS) $(OBJS) $(LIBES) $(OTHERLIBS) -o mush X $(OBJS): config.h mush.h loop.o: version.h X tape: X @tar cv $(MAKES) $(HDRS) $(SRCS) $(HELP_FILES) X tar: X @tar fcv MUSH $(MAKES) $(HDRS) $(SRCS) $(HELP_FILES) X tarmail: X tar fcv - $(MAKES) $(HDRS) $(SRCS) $(HELP_FILES) | \ X compress | btoa > mush.tarmail X lint: X lint $(LINTFLAGS) $(SRCS) X clean: X rm -f *.o core mush X BINDIR= /usr/local/bin LIBDIR= /usr/local/lib MRCDIR= /usr/lib MANDIR= /usr/local/man/man1 MANEXT= 1 X install: mush X mv mush $(BINDIR) X strip $(BINDIR)/mush X chmod 0755 $(BINDIR)/mush X cp mush.1 $(MANDIR)/mush.$(MANEXT) X chmod 0644 $(MANDIR)/mush.$(MANEXT) X cp cmd_help $(LIBDIR) X chmod 0644 $(LIBDIR)/cmd_help X cp Mushrc $(MRCDIR)/Mushrc X chmod 0644 $(MRCDIR)/Mushrc SHAR_EOF chmod 0644 makefile.bsd || echo 'restore of makefile.bsd failed' Wc_c="`wc -c < 'makefile.bsd'`" test 2096 -eq "$Wc_c" || echo 'makefile.bsd: original size 2096, current size' "$Wc_c" rm -f _shar_wnt_.tmp fi # ============= makefile.hpux ============== if test -f 'makefile.hpux' -a X"$1" != X"-c"; then echo 'x - skipping makefile.hpux (File already exists)' rm -f _shar_wnt_.tmp else > _shar_wnt_.tmp echo 'x - extracting makefile.hpux (Text)' sed 's/^X//' << 'SHAR_EOF' > 'makefile.hpux' && # Mush makefile for HP/UX. # HDRS1= mush.h config.h HDRS2= strings.h options.h HDRS3= bindings.h glob.h HDRS4= version.h SRCS1= commands.c dates.c execute.c expr.c folders.c \ X hdrs.c init.c loop.c mail.c main.c misc.c msgs.c pick.c \ X print.c setopts.c signals.c sort.c viewopts.c options.c lock.c SRCS2= bind.c curs_io.c curses.c file.c strings.c macros.c \ X addrs.c malloc.c glob.c command2.c X OBJS1= commands.o dates.o execute.o expr.o folders.o \ X hdrs.o init.o loop.o mail.o main.o misc.o msgs.o pick.o \ X print.o setopts.o signals.o sort.o viewopts.o options.o lock.o OBJS2= bind.o curs_io.o curses.o file.o strings.o macros.o \ X addrs.o malloc.o glob.o command2.o X HELP_FILES= README README-7.0 README-7.1 README-7.2.0 README-7.2.2 mush.1 \ X cmd_help Mushrc Mailrc Gnurc sample.mushrc advanced.mushrc digestify X # If your HP-UX version is older than 6.5, you will need remove -DDIRECTORY X HPFLAGS= -DHPUX -DSELECT -DDIRECTORY CFLAGS= -O -DSYSV -DUSG -DCURSES -DREGCMP -DSIGRET=void $(HPFLAGS) LDFLAGS= LIBS= -lcurses -lPW -lmalloc OTHERLIBS= # Use some variant of this one if you #define MMDF in config.h #OTHERLIBS=/usr/src/mmdf/lib/libmmdf.a PROG= mush X $(PROG): $(OBJS1) $(OBJS2) X @echo loading... X @$(CC) $(LDFLAGS) $(OBJS1) $(OBJS2) -o $(PROG) $(LIBS) $(OTHERLIBS) X $(OBJS1): $(HDRS1) $(HDRS2) $(OBJS2): $(HDRS1) $(HDRS2) $(HDRS3) loop.o: version.h X BINDIR= /usr/local/bin LIBDIR= /usr/local/lib MRCDIR= /usr/lib MANDIR= /usr/local/man/man1 MANEXT= 1 X install: mush X cp mush $(BINDIR) X strip $(BINDIR)/mush X chmod 0755 $(BINDIR)/mush X cp mush.1 $(MANDIR)/mush.$(MANEXT) X chmod 0644 $(MANDIR)/mush.$(MANEXT) X cp cmd_help $(LIBDIR) X chmod 0644 $(LIBDIR)/cmd_help X cp Mushrc $(MRCDIR)/Mushrc X chmod 0644 $(MRCDIR)/Mushrc SHAR_EOF chmod 0644 makefile.hpux || echo 'restore of makefile.hpux failed' Wc_c="`wc -c < 'makefile.hpux'`" test 1735 -eq "$Wc_c" || echo 'makefile.hpux: original size 1735, current size' "$Wc_c" rm -f _shar_wnt_.tmp fi # ============= makefile.sun ============== if test -f 'makefile.sun' -a X"$1" != X"-c"; then echo 'x - skipping makefile.sun (File already exists)' rm -f _shar_wnt_.tmp else > _shar_wnt_.tmp echo 'x - extracting makefile.sun (Text)' sed 's/^X//' << 'SHAR_EOF' > 'makefile.sun' && # makefile.sun (c) copyright 1986 (Dan Heller) SHAR_EOF true || echo 'restore of makefile.sun failed' fi echo 'End of part 12' echo 'File makefile.sun is continued in part 13' echo 13 > _shar_seq_.tmp exit 0 exit 0 # Just in case... -- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM Sterling Software, IMD UUCP: uunet!sparky!kent Phone: (402) 291-8300 FAX: (402) 291-4362 Please send comp.sources.misc-related mail to kent@uunet.uu.net.