[comp.sources.misc] v18i069: mush - Mail User's Shell, Part12/22

argv@zipcode.com (Dan Heller) (04/22/91)

Submitted-by: Dan Heller <argv@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@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.