v18i069: mush - Mail User's Shell, Part12/22
Dan Heller
argv at zipcode.com
Mon Apr 22 10:04:12 AEST 1991
Submitted-by: Dan Heller <argv at zipcode.com>
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 SWNTOOL
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 nm 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 at 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 at uunet.uu.net.
More information about the Comp.sources.misc
mailing list