Пример #1
0
/*
 * Reply to a series of messages by simply mailing to the senders
 * and not messing around with the To: and Cc: lists as in normal
 * reply.
 */
int
doRespond(int *msgvec)
{
    struct header head;
    struct message *mp;
    int *ap;
    char *cp, *mid;

    head.h_to = NULL;
    for (ap = msgvec; *ap != 0; ap++) {
        mp = &message[*ap - 1];
        touch(mp);
        dot = mp;
        if ((cp = skin(hfield("from", mp))) == NULL)
            cp = skin(nameof(mp, 2));
        head.h_to = cat(head.h_to, extract(cp, GTO));
        mid = skin(hfield("message-id", mp));
    }
    if (head.h_to == NULL)
        return (0);
    mp = &message[msgvec[0] - 1];
    if ((head.h_subject = hfield("subject", mp)) == NULL)
        head.h_subject = hfield("subj", mp);
    head.h_subject = reedit(head.h_subject);
    head.h_cc = NULL;
    head.h_bcc = NULL;
    head.h_smopts = NULL;
    head.h_replyto = value("REPLYTO");
    head.h_inreplyto = mid;
    mail1(&head, 1);
    return (0);
}
Пример #2
0
int
matchfield(char *str, int mesg)
{
	struct message *mp;
	char *cp, *cp2;

	str++;
	if (*str == '\0')
		str = lastscan;
	else
		strlcpy(lastscan, str, sizeof(lastscan));
	mp = &message[mesg-1];

	/*
	 * Now look, ignoring case, for the word in the string.
	 */

	if (value("searchheaders") && (cp = strchr(str, ':')) != NULL) {
		/* Check for special case "/to:" */
		if (strncmp(str, "to:", 3) == 0)
			return (matchto(cp, mesg));
		*cp++ = '\0';
		cp2 = hfield(*str != '\0' ? str : "subject", mp);
		cp[-1] = ':';
		str = cp;
		cp = cp2;
	} else
		cp = hfield("subject", mp);

	if (cp == NULL)
		return (0);

	return (strcasestr(cp, str) != NULL);
}
Пример #3
0
/*
 * Reply to a list of messages.  Extract each name from the
 * message header and send them off to mail1()
 */
int
dorespond(int *msgvec)
{
    struct message *mp;
    char *cp, *rcv, *replyto;
    char **ap;
    struct name *np;
    struct header head;

    if (msgvec[1] != 0) {
        printf("Sorry, can't reply to multiple messages at once\n");
        return (1);
    }
    mp = &message[msgvec[0] - 1];
    touch(mp);
    dot = mp;
    if ((rcv = skin(hfield("from", mp))) == NULL)
        rcv = skin(nameof(mp, 1));
    if ((replyto = skin(hfield("reply-to", mp))) != NULL)
        np = extract(replyto, GTO);
    else if ((cp = skin(hfield("to", mp))) != NULL)
        np = extract(cp, GTO);
    else
        np = NULL;
    np = elide(np);
    /*
     * Delete my name from the reply list,
     * and with it, all my alternate names.
     */
    np = delname(np, myname);
    if (altnames)
        for (ap = altnames; *ap != NULL; ap++)
            np = delname(np, *ap);
    if (np != NULL && replyto == NULL)
        np = cat(np, extract(rcv, GTO));
    else if (np == NULL) {
        if (replyto != NULL)
            printf("Empty reply-to field -- replying to author\n");
        np = extract(rcv, GTO);
    }
    head.h_to = np;
    if ((head.h_subject = hfield("subject", mp)) == NULL)
        head.h_subject = hfield("subj", mp);
    head.h_subject = reedit(head.h_subject);
    if (replyto == NULL && (cp = skin(hfield("cc", mp))) != NULL) {
        np = elide(extract(cp, GCC));
        np = delname(np, myname);
        if (altnames != 0)
            for (ap = altnames; *ap != NULL; ap++)
                np = delname(np, *ap);
        head.h_cc = np;
    } else
        head.h_cc = NULL;
    head.h_bcc = NULL;
    head.h_smopts = NULL;
    head.h_replyto = value("REPLYTO");
    head.h_inreplyto = skin(hfield("message-id", mp));
    mail1(&head, 1);
    return (0);
}
Пример #4
0
void 
receipt(struct message *mp)
{
	char	head[LINESIZE];
	char	buf[BUFSIZ];
	FILE	*pp, *fp;
	char	*mail, *s;


	if ((mail = value("sendmail")) == 0)
#ifdef SENDMAIL
		mail = SENDMAIL;
#else
		mail = MAIL;
#endif
	if (icsubstr(hfield("default-options", mp, addone), "/receipt")
	 || icsubstr(hfield(">to", mp, addto), "/receipt")) {
		snprintf(buf, sizeof (buf), "%s %s", mail, skin(nameof(mp)));
		if (pp = npopen(buf, "w")) {
			headline_t *hl;

			if (headline_alloc(&hl) != 0) {
				err(1, "could not allocate memory");
			}

			fp = setinput(mp);
			readline(fp, head);
			if (parse_headline(head, hl) != 0) {
				headline_reset(hl);
			}
			if (custr_len(hl->hl_date) > 0) {
				fprintf(pp, "Original-Date: %s\n",
				    custr_cstr(hl->hl_date));
			}
			if (s = hfield("message-id", mp, addone))
				fprintf(pp, "Original-Message-ID: %s\n", s);
			s = hfield("subject", mp, addone);
			fprintf(pp, "Subject: RR: %s\n", s ? s : "(none)");
			npclose(pp);
			headline_free(hl);
		}
	}
}
Пример #5
0
/*
 * Print out the header of a specific message.
 * This is a slight improvement to the standard one.
 */
void
printhead(int mesg)
{
	struct message *mp;
	char headline[LINESIZE], wcount[LINESIZE], *subjline, dispc, curind;
	char pbuf[BUFSIZ];
	struct headline hl;
	int subjlen;
	char *name;

	mp = &message[mesg-1];
	(void)readline(setinput(mp), headline, LINESIZE);
	if ((subjline = hfield("subject", mp)) == NULL)
		subjline = hfield("subj", mp);
	/*
	 * Bletch!
	 */
	curind = dot == mp ? '>' : ' ';
	dispc = ' ';
	if (mp->m_flag & MSAVED)
		dispc = '*';
	if (mp->m_flag & MPRESERVE)
		dispc = 'P';
	if ((mp->m_flag & (MREAD|MNEW)) == MNEW)
		dispc = 'N';
	if ((mp->m_flag & (MREAD|MNEW)) == 0)
		dispc = 'U';
	if (mp->m_flag & MBOX)
		dispc = 'M';
	parse(headline, &hl, pbuf);
	sprintf(wcount, "%3ld/%-5ld", mp->m_lines, mp->m_size);
	subjlen = screenwidth - 50 - strlen(wcount);
	name = value("show-rcpt") != NULL ?
		skin(hfield("to", mp)) : nameof(mp, 0);
	if (subjline == NULL || subjlen < 0)		/* pretty pathetic */
		printf("%c%c%3d %-20.20s  %16.16s %s\n",
			curind, dispc, mesg, name, hl.l_date, wcount);
	else
		printf("%c%c%3d %-20.20s  %16.16s %s \"%.*s\"\n",
			curind, dispc, mesg, name, hl.l_date, wcount,
			subjlen, subjline);
}
Пример #6
0
int
matchto(char *str, int mesg)
{
    struct message *mp;
    char *cp, **to;

    str++;

    if (*str == 0)	/* null string matches nothing instead of everything */
        return(0);

    mp = &message[mesg-1];

    for (to = to_fields; *to; to++) {
        cp = hfield(*to, mp);
        if (cp != NULL && strcasestr(cp, str) != NULL)
            return(1);
    }
    return(0);
}
Пример #7
0
static struct message *
getsig(struct message *m, int n, NSSCMSMessage **msg)
{
	struct message	*x;
	char	*ct, *pt, *boundary = NULL, *cte;
	char	*buf = NULL;
	size_t	bufsize = 0, buflen, count, boundlen = -1;
	int	part;
	FILE	*fp;
	NSSCMSDecoderContext	*decctx;
	struct str	in, out;
	char	*to, *cc;
	int	inhdr, binary;
	int	detached = 1;

loop:	if ((ct = hfield("content-type", m)) == NULL)
		goto not;
	if (strncmp(ct, "application/x-pkcs7-mime", 24) == 0 ||
			strncmp(ct, "application/pkcs7-mime", 22) == 0) {
		to = hfield("to", m);
		cc = hfield("cc", m);
		if ((x = smime_decrypt(m, to, cc, 1)) == NULL)
			return NULL;
		if (x != (struct message *)-1) {
			m = x;
			goto loop;
		}
		detached = 0;
	} else if (strncmp(ct, "multipart/signed", 16) ||
			(pt = mime_getparam("protocol", ct)) == NULL ||
			strcmp(pt, "application/x-pkcs7-signature") &&
			 strcmp(pt, "application/pkcs7-signature") ||
			(boundary = mime_getboundary(ct)) == NULL) {
	not:	fprintf(stderr,
			"Message %d is not an S/MIME signed message.\n", n);
		return NULL;
	} else
		boundlen = strlen(boundary);
	if ((decctx = NSS_CMSDecoder_Start(NULL, NULL, NULL,
					password_cb, "Pass phrase:",
					NULL, NULL)) == NULL) {
		fprintf(stderr, "Cannot start decoder.\n");
		return NULL;
	}
	if ((fp = setinput(&mb, m, NEED_BODY)) == NULL) {
		return NULL;
	}
	count = m->m_size;
	part = 0;
	inhdr = 1;
	binary = 0;
	while (fgetline(&buf, &bufsize, &count, &buflen, fp, 0) != NULL) {
		if (detached && boundary && buflen >= boundlen + 1 &&
				strncmp(buf, boundary, boundlen) == 0) {
			if (buf[boundlen] == '\n') {
				part++;
				inhdr = 1;
				binary = 0;
				if (part >= 3) {
					fprintf(stderr, "Message %d has too "
							"many parts.\n", n);
					free(buf);
					return NULL;
				}
				continue;
			}
			if (buf[boundlen] == '-' && buf[boundlen+1] == '-' &&
					buf[boundlen+2] == '\n')
				break;
		} else if (buf[0] == '\n') {
			inhdr = 0;
			continue;
		}
		if ((!detached || part == 2) && inhdr == 0) {
			if (binary)
				NSS_CMSDecoder_Update(decctx, buf, buflen);
			else {
				in.s = buf;
				in.l = buflen;
				mime_fromb64_b(&in, &out, 0, fp);
				NSS_CMSDecoder_Update(decctx, out.s, out.l);
				free(out.s);
			}
		}
		if (buflen == 1 && buf[0] == '\n')
			inhdr = 0;
		if (inhdr && (cte = thisfield(buf, "content-transfer-encoding"))
				!= NULL && ascncasecmp(cte, "binary", 7) == 0)
			binary = 1;
	}
	free(buf);
	if ((*msg = NSS_CMSDecoder_Finish(decctx)) == NULL) {
		fprintf(stderr, "Failed to decode signature for message %d.\n",
				n);
		return NULL;
	}
	return m;
}
Пример #8
0
static enum okay
getdig(struct message *m, int n, SECItem ***digests,
		PLArenaPool **poolp, SECAlgorithmID **algids)
{
	char	*ct, *pt, *boundary;
	char	*buf = NULL;
	size_t	bufsize = 0, buflen, count, boundlen;
	int	part;
	int	nl;
	FILE	*fp;
	NSSCMSDigestContext	*digctx;

	*poolp = PORT_NewArena(1024);
	if ((ct = hfield("content-type", m)) == NULL ||
			strncmp(ct, "multipart/signed", 16) ||
			(pt = mime_getparam("protocol", ct)) == NULL ||
			strcmp(pt, "application/x-pkcs7-signature") &&
			 strcmp(pt, "application/pkcs7-signature") ||
			(boundary = mime_getboundary(ct)) == NULL) {
		fprintf(stderr,
			"Message %d is not an S/MIME signed message.\n", n);
		return STOP;
	}
	boundlen = strlen(boundary);
	if ((digctx = NSS_CMSDigestContext_StartMultiple(algids)) == NULL) {
		fprintf(stderr, "Cannot start digest computation.\n");
		return STOP;
	}
	if ((fp = setinput(&mb, m, NEED_BODY)) == NULL) {
		return STOP;
	}
	count = m->m_size;
	part = 0;
	nl = 0;
	while (fgetline(&buf, &bufsize, &count, &buflen, fp, 0) != NULL) {
		if (buflen >= boundlen + 1 &&
				strncmp(buf, boundary, boundlen) == 0) {
			if (buf[boundlen] == '\n') {
				if (++part >= 2)
					break;
				continue;
			}
			if (buf[boundlen] == '-' && buf[boundlen+1] == '-' &&
					buf[boundlen+2] == '\n')
				break;
		}
		if (part == 1) {
			if (nl) {
				NSS_CMSDigestContext_Update(digctx,
						(unsigned char *)"\r\n", 2);
				nl = 0;
			}
			if (buf[buflen-1] == '\n') {
				nl = 1;
				buflen--;
			}
			NSS_CMSDigestContext_Update(digctx,
					(unsigned char *)buf, buflen);
			continue;
		}
	}
	free(buf);
	if (NSS_CMSDigestContext_FinishMultiple(digctx,
				*poolp, digests) != SECSuccess) {
		fprintf(stderr, "Error creating digest for message %d\n", n);
		return STOP;
	}
	return OKAY;
}
Пример #9
0
FILE *
collect(struct header *hp, int printheaders, struct message *mp,
		char *quotefile, int doprefix, int tflag)
{
	FILE *fbuf;
	struct ignoretab *quoteig;
	int lc, cc, escape, eofcount;
	int c, t;
	char *linebuf = NULL, *cp, *quote = NULL;
	size_t linesize;
	char *tempMail = NULL;
	int getfields;
	sigset_t oset, nset;
	long count;
	enum sendaction	action;
	sighandler_type	savedtop;
	const char tildehelp[] =
"-------------------- ~ ESCAPES ----------------------------\n\
~~              Quote a single tilde\n\
~@ [file ...]   Edit attachment list\n\
~b users        Add users to \"blind\" cc list\n\
~c users        Add users to cc list\n\
~d              Read in dead.letter\n\
~e              Edit the message buffer\n\
~f messages     Read in messages without indenting lines\n\
~F messages     Same as ~f, but keep all header lines\n\
~h              Prompt for to list, subject, cc, and \"blind\" cc list\n\
~r file         Read a file into the message buffer\n\
~p              Print the message buffer\n\
~q              Abort message composition and save text to dead.letter\n\
~m messages     Read in messages with each line indented\n\
~M messages     Same as ~m, but keep all header lines\n\
~s subject      Set subject\n\
~t users        Add users to to list\n\
~v              Invoke display editor on message\n\
~w file         Write message onto file\n\
~x              Abort message composition and discard text written so far\n\
~!command       Invoke the shell\n\
~:command       Execute a regular command\n\
-----------------------------------------------------------\n";

	(void) &escape;
	(void) &eofcount;
	(void) &getfields;
	(void) &tempMail;
	(void) &tflag;
	(void) &quote;

	collf = NULL;
	/*
	 * Start catching signals from here, but we're still die on interrupts
	 * until we're in the main loop.
	 */
	sigemptyset(&nset);
	sigaddset(&nset, SIGINT);
	sigaddset(&nset, SIGHUP);
	sigprocmask(SIG_BLOCK, &nset, &oset);
	handlerpush(collint);
	if ((saveint = safe_signal(SIGINT, SIG_IGN)) != SIG_IGN)
		safe_signal(SIGINT, collint);
	if ((savehup = safe_signal(SIGHUP, SIG_IGN)) != SIG_IGN)
		safe_signal(SIGHUP, collhup);
	savetstp = safe_signal(SIGTSTP, collstop);
	savettou = safe_signal(SIGTTOU, collstop);
	savettin = safe_signal(SIGTTIN, collstop);
	if (sigsetjmp(collabort, 1)) {
		if (tempMail != NULL) {
			rm(tempMail);
			Ftfree(&tempMail);
		}
		goto err;
	}
	if (sigsetjmp(colljmp, 1)) {
		if (tempMail != NULL) {
			rm(tempMail);
			Ftfree(&tempMail);
		}
		goto err;
	}
	sigprocmask(SIG_SETMASK, &oset, (sigset_t *)NULL);

	noreset++;
	if ((collf = Ftemp(&tempMail, "Rs", "w+", 0600, 1)) == NULL) {
		perror(catgets(catd, CATSET, 51, "temporary mail file"));
		goto err;
	}
	unlink(tempMail);
	Ftfree(&tempMail);

	if ((cp = value("MAILX_HEAD")) != NULL) {
		if (is_a_tty[0])
			putesc(cp, stdout);
		putesc(cp, collf);
	}

	/*
	 * If we are going to prompt for a subject,
	 * refrain from printing a newline after
	 * the headers (since some people mind).
	 */
	getfields = 0;
	if (!tflag) {
		t = GTO|GSUBJECT|GCC|GNL;
		if (value("fullnames"))
			t |= GCOMMA;
		if (hp->h_subject == NULL && value("interactive") != NULL &&
			    (value("ask") != NULL || value("asksub") != NULL))
			t &= ~GNL, getfields |= GSUBJECT;
		if (hp->h_to == NULL && value("interactive") != NULL)
			t &= ~GNL, getfields |= GTO;
		if (value("bsdcompat") == NULL && value("askatend") == NULL &&
				value("interactive")) {
			if (hp->h_bcc == NULL && value("askbcc"))
				t &= ~GNL, getfields |= GBCC;
			if (hp->h_cc == NULL && value("askcc"))
				t &= ~GNL, getfields |= GCC;
		}
		if (printheaders) {
			puthead(hp, stdout, t, SEND_TODISP, CONV_NONE,
					NULL, NULL);
			fflush(stdout);
		}
	}

	/*
	 * Quote an original message
	 */
	if (mp != NULL && (doprefix || (quote = value("quote")) != NULL)) {
		quoteig = allignore;
		action = SEND_QUOTE;
		if (doprefix) {
			quoteig = fwdignore;
			if ((cp = value("fwdheading")) == NULL)
				cp = "-------- Original Message --------";
			if (*cp) {
				fprintf(collf, "%s\n", cp);
				fprintf(stdout, "%s\n", cp);
			}
		} else if (strcmp(quote, "noheading") == 0) {
			/*EMPTY*/;
		} else if (strcmp(quote, "headers") == 0) {
			quoteig = ignore;
		} else if (strcmp(quote, "allheaders") == 0) {
			quoteig = NULL;
			action = SEND_QUOTE_ALL;
		} else {
			cp = hfield("from", mp);
			if (cp != NULL) {
				mime_write(cp, strlen(cp),
						collf, CONV_FROMHDR, TD_NONE,
						NULL, (size_t) 0,
						NULL, NULL);
				mime_write(cp, strlen(cp),
						stdout, CONV_FROMHDR, TD_NONE,
						NULL, (size_t) 0,
						NULL, NULL);
				fwrite(catgets(catd, CATSET, 52,
					" wrote:\n\n"), sizeof(char), 9, collf);
				fwrite(catgets(catd, CATSET, 52,
					" wrote:\n\n"), sizeof(char), 9, stdout);
			}
		}
		cp = value("indentprefix");
		if (cp != NULL && *cp == '\0')
			cp = "\t";
		send(mp, collf, quoteig, doprefix ? NULL : cp, action, NULL);
		send(mp, stdout, quoteig, doprefix ? NULL : cp, action, NULL);
	}

	if ((cp = value("escape")) != NULL)
		escape = *cp;
	else
		escape = ESCAPE;
	eofcount = 0;
	hadintr = 0;

	if (!sigsetjmp(colljmp, 1)) {
		if (getfields)
			grabh(hp, getfields, 1);
		if (quotefile != NULL) {
			if (include_file(NULL, quotefile, &lc, &cc, 1) != 0)
				goto err;
		}
	} else {
		/*
		 * Come here for printing the after-signal message.
		 * Duplicate messages won't be printed because
		 * the write is aborted if we get a SIGTTOU.
		 */
cont:
		if (hadintr) {
			fflush(stdout);
			fprintf(stderr, catgets(catd, CATSET, 53,
				"\n(Interrupt -- one more to kill letter)\n"));
		} else {
			printf(catgets(catd, CATSET, 54, "(continue)\n"));
			fflush(stdout);
		}
	}
	if (value("interactive") == NULL && tildeflag <= 0 && !is_a_tty[0] &&
			!tflag) {
		/*
		 * No tilde escapes, interrupts not expected. Copy
		 * standard input the simple way.
		 */
		linebuf = srealloc(linebuf, linesize = BUFSIZ);
		while ((count = fread(linebuf, sizeof *linebuf,
						linesize, stdin)) > 0) {
			if (fwrite(linebuf, sizeof *linebuf,
						count, collf) != count)
				goto err;
		}
		goto out;
	}
	for (;;) {
		colljmp_p = 1;
		count = readline(stdin, &linebuf, &linesize);
		colljmp_p = 0;
		if (count < 0) {
			if (value("interactive") != NULL &&
			    value("ignoreeof") != NULL && ++eofcount < 25) {
				printf(catgets(catd, CATSET, 55,
					"Use \".\" to terminate letter\n"));
				continue;
			}
			break;
		}
		if (tflag && count == 0) {
			rewind(collf);
			if (makeheader(collf, hp) != OKAY)
				goto err;
			rewind(collf);
			tflag = 0;
			continue;
		}
		eofcount = 0;
		hadintr = 0;
		if (linebuf[0] == '.' && linebuf[1] == '\0' &&
		    value("interactive") != NULL &&
		    (value("dot") != NULL || value("ignoreeof") != NULL))
			break;
		if (linebuf[0] != escape || (value("interactive") == NULL &&
					tildeflag == 0 ||
					tildeflag < 0)) {
			if (putline(collf, linebuf, count) < 0)
				goto err;
			continue;
		}
		c = linebuf[1];
		switch (c) {
		default:
			/*
			 * On double escape, just send the single one.
			 * Otherwise, it's an error.
			 */
			if (c == escape) {
				if (putline(collf, &linebuf[1], count - 1) < 0)
					goto err;
				else
					break;
			}
			printf(catgets(catd, CATSET, 56,
					"Unknown tilde escape.\n"));
			break;
#ifdef	DEBUG_COMMANDS
		case 'C':
			/*
			 * Dump core.
			 */
			core(NULL);
			break;
#endif	/* DEBUG_COMMANDS */
		case '!':
			/*
			 * Shell escape, send the balance of the
			 * line to sh -c.
			 */
			shell(&linebuf[2]);
			break;
		case ':':
		case '_':
			/*
			 * Escape to command mode, but be nice!
			 */
			inhook = 0;
			execute(&linebuf[2], 1, count - 2);
			goto cont;
		case '.':
			/*
			 * Simulate end of file on input.
			 */
			goto out;
		case 'x':
			/*
			 * Same as 'q', but no dead.letter saving.
			 */
			hadintr++;
			collint(0);
			exit(1);
			/*NOTREACHED*/
		case 'q':
			/*
			 * Force a quit of sending mail.
			 * Act like an interrupt happened.
			 */
			hadintr++;
			collint(SIGINT);
			exit(1);
			/*NOTREACHED*/
		case 'h':
			/*
			 * Grab a bunch of headers.
			 */
			do
				grabh(hp, GTO|GSUBJECT|GCC|GBCC,
						value("bsdcompat") != NULL &&
						value("bsdorder") != NULL);
			while (hp->h_to == NULL);
			goto cont;
		case 'H':
			/*
			 * Grab extra headers.
			 */
			do
				grabh(hp, GEXTRA, 0);
			while (check_from_and_sender(hp->h_from, hp->h_sender));
			goto cont;
		case 't':
			/*
			 * Add to the To list.
			 */
			while ((hp->h_to = checkaddrs(cat(hp->h_to,
					sextract(&linebuf[2], GTO|GFULL))))
				== NULL);
			break;
		case 's':
			/*
			 * Set the Subject list.
			 */
			cp = &linebuf[2];
			while (whitechar(*cp & 0377))
				cp++;
			hp->h_subject = savestr(cp);
			break;
		case '@':
			/*
			 * Edit the attachment list.
			 */
			if (linebuf[2] != '\0')
				hp->h_attach = append_attachments(hp->h_attach,
						&linebuf[2]);
			else
				hp->h_attach = edit_attachments(hp->h_attach);
			break;
		case 'c':
			/*
			 * Add to the CC list.
			 */
			hp->h_cc = checkaddrs(cat(hp->h_cc,
				sextract(&linebuf[2], GCC|GFULL)));
			break;
		case 'b':
			/*
			 * Add stuff to blind carbon copies list.
			 */
			hp->h_bcc = checkaddrs(cat(hp->h_bcc,
				sextract(&linebuf[2], GBCC|GFULL)));
			break;
		case 'd':
			strncpy(linebuf + 2, getdeadletter(), linesize - 2);
			linebuf[linesize-1]='\0';
			/*FALLTHRU*/
		case 'r':
		case '<':
			/*
			 * Invoke a file:
			 * Search for the file name,
			 * then open it and copy the contents to collf.
			 */
			cp = &linebuf[2];
			while (whitechar(*cp & 0377))
				cp++;
			if (*cp == '\0') {
				printf(catgets(catd, CATSET, 57,
						"Interpolate what file?\n"));
				break;
			}
			if (*cp == '!') {
				insertcommand(collf, cp + 1);
				break;
			}
			cp = expand(cp);
			if (cp == NULL)
				break;
			if (is_dir(cp)) {
				printf(catgets(catd, CATSET, 58,
						"%s: Directory\n"), cp);
				break;
			}
			if ((fbuf = Fopen(cp, "r")) == NULL) {
				perror(cp);
				break;
			}
			printf(catgets(catd, CATSET, 59, "\"%s\" "), cp);
			fflush(stdout);
			if (include_file(fbuf, cp, &lc, &cc, 0) != 0)
				goto err;
			printf(catgets(catd, CATSET, 60, "%d/%d\n"), lc, cc);
			break;
		case 'i':
			/*
			 * Insert an environment variable into the file.
			 */
			cp = &linebuf[2];
			while (whitechar(*cp & 0377))
				cp++;
			if ((cp = value(cp)) == NULL || *cp == '\0')
				break;
			if (is_a_tty[0])
				putesc(cp, stdout);
			putesc(cp, collf);
			break;
		case 'a':
		case 'A':
			/*
			 * Insert the contents of a signature variable.
			 */
			if ((cp = value(c == 'a' ? "sign" : "Sign")) != NULL &&
					*cp != '\0') {
				if (is_a_tty[0])
					putesc(cp, stdout);
				putesc(cp, collf);
			}
			break;
		case 'w':
			/*
			 * Write the message on a file.
			 */
			cp = &linebuf[2];
			while (blankchar(*cp & 0377))
				cp++;
			if (*cp == '\0') {
				fprintf(stderr, catgets(catd, CATSET, 61,
						"Write what file!?\n"));
				break;
			}
			if ((cp = expand(cp)) == NULL)
				break;
			rewind(collf);
			exwrite(cp, collf, 1);
			break;
		case 'm':
		case 'M':
		case 'f':
		case 'F':
			/*
			 * Interpolate the named messages, if we
			 * are in receiving mail mode.  Does the
			 * standard list processing garbage.
			 * If ~f is given, we don't shift over.
			 */
			if (forward(linebuf + 2, collf, c) < 0)
				goto err;
			goto cont;
		case '?':
			fputs(tildehelp, stdout);
			break;
		case 'p':
			/*
			 * Print out the current state of the
			 * message without altering anything.
			 */
			print_collf(collf, hp);
			goto cont;
		case '|':
			/*
			 * Pipe message through command.
			 * Collect output as new message.
			 */
			rewind(collf);
			mespipe(&linebuf[2]);
			goto cont;
		case 'v':
		case 'e':
			/*
			 * Edit the current message.
			 * 'e' means to use EDITOR
			 * 'v' means to use VISUAL
			 */
			rewind(collf);
			mesedit(c, value("editheaders") ? hp : NULL);
			goto cont;
		}
	}
	goto out;
err:
	if (collf != NULL) {
		Fclose(collf);
		collf = NULL;
	}
out:
	if (collf != NULL) {
		if ((cp = value("MAILX_TAIL")) != NULL) {
			if (is_a_tty[0])
				putesc(cp, stdout);
			fflush(collf);
			putesc(cp, collf);
		}
		rewind(collf);
	}
	handlerpop();
	noreset--;
	sigemptyset(&nset);
	sigaddset(&nset, SIGINT);
	sigaddset(&nset, SIGHUP);
#ifndef OLDBUG
	sigprocmask(SIG_BLOCK, &nset, (sigset_t *)NULL);
#else
	sigprocmask(SIG_BLOCK, &nset, &oset);
#endif
	safe_signal(SIGINT, saveint);
	safe_signal(SIGHUP, savehup);
	safe_signal(SIGTSTP, savetstp);
	safe_signal(SIGTTOU, savettou);
	safe_signal(SIGTTIN, savettin);
	sigprocmask(SIG_SETMASK, &oset, (sigset_t *)NULL);
	return collf;
}
Пример #10
0
/*
 * Terminate an editing session by attempting to write out the user's
 * file from the temporary.  Save any new stuff appended to the file.
 */
int
edstop(
    int noremove	/* don't allow the file to be removed, trunc instead */
)
{
	register int gotcha, c;
	register struct message *mp;
	FILE *obuf, *ibuf, *tbuf = 0, *readstat;
	struct stat statb;
	char tempname[STSIZ], *id;
	int tmpfd = -1;

	if (readonly)
		return (0);
	holdsigs();
	if (Tflag != NOSTR) {
		if ((readstat = fopen(Tflag, "w")) == NULL)
			Tflag = NOSTR;
	}
	for (mp = &message[0], gotcha = 0; mp < &message[msgCount]; mp++) {
		if (mp->m_flag & MNEW) {
			mp->m_flag &= ~MNEW;
			mp->m_flag |= MSTATUS;
		}
		if (mp->m_flag & (MODIFY|MDELETED|MSTATUS))
			gotcha++;
		if (Tflag != NOSTR && (mp->m_flag & (MREAD|MDELETED)) != 0) {
			if ((id = hfield("article-id", mp, addone)) != NOSTR)
				fprintf(readstat, "%s\n", id);
		}
	}
	if (Tflag != NOSTR)
		fclose(readstat);
	if (!gotcha || Tflag != NOSTR)
		goto done;
	if ((ibuf = fopen(editfile, "r+")) == NULL) {
		perror(editfile);
		relsesigs();
		longjmp(srbuf, 1);
	}
	lock(ibuf, "r+", 1);
	if (fstat(fileno(ibuf), &statb) >= 0 && statb.st_size > mailsize) {
		nstrcpy(tempname, STSIZ, "/tmp/mboxXXXXXX");
		if ((tmpfd = mkstemp(tempname)) == -1) {
			perror(tempname);
			fclose(ibuf);
			relsesigs();
			longjmp(srbuf, 1);
		}
		if ((obuf = fdopen(tmpfd, "w")) == NULL) {
			perror(tempname);
			fclose(ibuf);
			removefile(tempname);
			relsesigs();
			(void) close(tmpfd);
			longjmp(srbuf, 1);
		}
		fseek(ibuf, mailsize, 0);
		while ((c = getc(ibuf)) != EOF)
			putc(c, obuf);
		fclose(obuf);
		if ((tbuf = fopen(tempname, "r")) == NULL) {
			perror(tempname);
			fclose(ibuf);
			removefile(tempname);
			relsesigs();
			longjmp(srbuf, 1);
		}
		removefile(tempname);
	}
	if ((obuf = fopen(editfile, "r+")) == NULL) {
		if ((obuf = fopen(editfile, "w")) == NULL) {
			perror(editfile);
			fclose(ibuf);
			if (tbuf)
				fclose(tbuf);
			relsesigs();
			longjmp(srbuf, 1);
		}
	}
	printf("\"%s\" ", editfile);
	flush();
	c = 0;
	for (mp = &message[0]; mp < &message[msgCount]; mp++) {
		if ((mp->m_flag & MDELETED) != 0)
			continue;
		c++;
		if (msend(mp, obuf, 0, fputs) < 0) {
			perror(editfile);
			fclose(ibuf);
			fclose(obuf);
			if (tbuf)
				fclose(tbuf);
			relsesigs();
			longjmp(srbuf, 1);
		}
	}
	gotcha = (c == 0 && tbuf == NULL);
	if (tbuf != NULL) {
		while ((c = getc(tbuf)) != EOF)
			putc(c, obuf);
		fclose(tbuf);
	}
	fflush(obuf);
	if (fferror(obuf)) {
		perror(editfile);
		fclose(ibuf);
		fclose(obuf);
		relsesigs();
		longjmp(srbuf, 1);
	}
	if (gotcha && !noremove && (value("keep") == NOSTR)) {
		removefile(editfile);
		printf(gettext("removed.\n"));
	}
	else
		printf(gettext("updated.\n"));
	fclose(ibuf);
	trunc(obuf);
	fclose(obuf);
	flush();

done:
	relsesigs();
	return (1);
}
Пример #11
0
/*
 * Save all of the undetermined messages at the top of "mbox"
 * Save all untouched messages back in the system mailbox.
 * Remove the system mailbox, if none saved there.
 */
void
quit(void)
{
    int mcount, p, modify, autohold, anystat, holdbit, nohold;
    FILE *ibuf, *obuf, *fbuf, *rbuf, *readstat, *abuf;
    struct message *mp;
    int c, fd;
    struct stat minfo;
    char *mbox, tempname[PATHSIZE];

    /*
     * If we are read only, we can't do anything,
     * so just return quickly.
     */
    if (readonly)
        return;
    /*
     * If editing (not reading system mail box), then do the work
     * in edstop()
     */
    if (edit) {
        edstop();
        return;
    }

    /*
     * See if there any messages to save in mbox.  If no, we
     * can save copying mbox to /tmp and back.
     *
     * Check also to see if any files need to be preserved.
     * Delete all untouched messages to keep them out of mbox.
     * If all the messages are to be preserved, just exit with
     * a message.
     */

    fbuf = Fopen(mailname, "r");
    if (fbuf == NULL)
        goto newmail;
    flock(fileno(fbuf), LOCK_EX);
    rbuf = NULL;
    if (fstat(fileno(fbuf), &minfo) >= 0 && minfo.st_size > mailsize) {
        printf("New mail has arrived.\n");
        snprintf(tempname, sizeof(tempname), "%s/mail.RqXXXXXXXXXX",
                 tmpdir);
        if ((fd = mkstemp(tempname)) == -1 ||
                (rbuf = Fdopen(fd, "w")) == NULL)
            goto newmail;
#ifdef APPEND
        fseeko(fbuf, mailsize, SEEK_SET);
        while ((c = getc(fbuf)) != EOF)
            putc(c, rbuf);
#else
        p = minfo.st_size - mailsize;
        while (p-- > 0) {
            c = getc(fbuf);
            if (c == EOF)
                goto newmail;
            putc(c, rbuf);
        }
#endif
        Fclose(rbuf);
        if ((rbuf = Fopen(tempname, "r")) == NULL)
            goto newmail;
        rm(tempname);
    }

    /*
     * Adjust the message flags in each message.
     */

    anystat = 0;
    autohold = value("hold") != NULL;
    holdbit = autohold ? MPRESERVE : MBOX;
    nohold = MBOX|MSAVED|MDELETED|MPRESERVE;
    if (value("keepsave") != NULL)
        nohold &= ~MSAVED;
    for (mp = &message[0]; mp < &message[msgCount]; mp++) {
        if (mp->m_flag & MNEW) {
            mp->m_flag &= ~MNEW;
            mp->m_flag |= MSTATUS;
        }
        if (mp->m_flag & MSTATUS)
            anystat++;
        if ((mp->m_flag & MTOUCH) == 0)
            mp->m_flag |= MPRESERVE;
        if ((mp->m_flag & nohold) == 0)
            mp->m_flag |= holdbit;
    }
    modify = 0;
    if (Tflag != NULL) {
        if ((readstat = Fopen(Tflag, "w")) == NULL)
            Tflag = NULL;
    }
    for (c = 0, p = 0, mp = &message[0]; mp < &message[msgCount]; mp++) {
        if (mp->m_flag & MBOX)
            c++;
        if (mp->m_flag & MPRESERVE)
            p++;
        if (mp->m_flag & MODIFY)
            modify++;
        if (Tflag != NULL && (mp->m_flag & (MREAD|MDELETED)) != 0) {
            char *id;

            if ((id = hfield("article-id", mp)) != NULL)
                fprintf(readstat, "%s\n", id);
        }
    }
    if (Tflag != NULL)
        Fclose(readstat);
    if (p == msgCount && !modify && !anystat) {
        printf("Held %d message%s in %s\n",
               p, p == 1 ? "" : "s", mailname);
        Fclose(fbuf);
        return;
    }
    if (c == 0) {
        if (p != 0) {
            writeback(rbuf);
            Fclose(fbuf);
            return;
        }
        goto cream;
    }

    /*
     * Create another temporary file and copy user's mbox file
     * darin.  If there is no mbox, copy nothing.
     * If he has specified "append" don't copy his mailbox,
     * just copy saveable entries at the end.
     */

    mbox = expand("&");
    mcount = c;
    if (value("append") == NULL) {
        snprintf(tempname, sizeof(tempname), "%s/mail.RmXXXXXXXXXX",
                 tmpdir);
        if ((fd = mkstemp(tempname)) == -1 ||
                (obuf = Fdopen(fd, "w")) == NULL) {
            warn("%s", tempname);
            Fclose(fbuf);
            return;
        }
        if ((ibuf = Fopen(tempname, "r")) == NULL) {
            warn("%s", tempname);
            rm(tempname);
            Fclose(obuf);
            Fclose(fbuf);
            return;
        }
        rm(tempname);
        if ((abuf = Fopen(mbox, "r")) != NULL) {
            while ((c = getc(abuf)) != EOF)
                putc(c, obuf);
            Fclose(abuf);
        }
        if (ferror(obuf)) {
            warnx("%s", tempname);
            Fclose(ibuf);
            Fclose(obuf);
            Fclose(fbuf);
            return;
        }
        Fclose(obuf);
        close(open(mbox, O_CREAT | O_TRUNC | O_WRONLY, 0600));
        if ((obuf = Fopen(mbox, "r+")) == NULL) {
            warn("%s", mbox);
            Fclose(ibuf);
            Fclose(fbuf);
            return;
        }
    }
    if (value("append") != NULL) {
        if ((obuf = Fopen(mbox, "a")) == NULL) {
            warn("%s", mbox);
            Fclose(fbuf);
            return;
        }
        fchmod(fileno(obuf), 0600);
    }
    for (mp = &message[0]; mp < &message[msgCount]; mp++)
        if (mp->m_flag & MBOX)
            if (sendmessage(mp, obuf, saveignore, NULL) < 0) {
                warnx("%s", mbox);
                Fclose(ibuf);
                Fclose(obuf);
                Fclose(fbuf);
                return;
            }

    /*
     * Copy the user's old mbox contents back
     * to the end of the stuff we just saved.
     * If we are appending, this is unnecessary.
     */

    if (value("append") == NULL) {
        rewind(ibuf);
        c = getc(ibuf);
        while (c != EOF) {
            putc(c, obuf);
            if (ferror(obuf))
                break;
            c = getc(ibuf);
        }
        Fclose(ibuf);
    }
    fflush(obuf);
    trunc(obuf);
    if (ferror(obuf)) {
        warn("%s", mbox);
        Fclose(obuf);
        Fclose(fbuf);
        return;
    }
    Fclose(obuf);
    if (mcount == 1)
        printf("Saved 1 message in mbox\n");
    else
        printf("Saved %d messages in mbox\n", mcount);

    /*
     * Now we are ready to copy back preserved files to
     * the system mailbox, if any were requested.
     */

    if (p != 0) {
        writeback(rbuf);
        Fclose(fbuf);
        return;
    }

    /*
     * Finally, remove his /var/mail file.
     * If new mail has arrived, copy it back.
     */

cream:
    if (rbuf != NULL) {
        abuf = Fopen(mailname, "r+");
        if (abuf == NULL)
            goto newmail;
        while ((c = getc(rbuf)) != EOF)
            putc(c, abuf);
        Fclose(rbuf);
        trunc(abuf);
        Fclose(abuf);
        alter(mailname);
        Fclose(fbuf);
        return;
    }
    demail();
    Fclose(fbuf);
    return;

newmail:
    printf("Thou hast new mail.\n");
    if (fbuf != NULL)
        Fclose(fbuf);
}
Пример #12
0
/*
 * Terminate an editing session by attempting to write out the user's
 * file from the temporary.  Save any new stuff appended to the file.
 */
static void
edstop(void)
{
    int gotcha, c;
    struct message *mp;
    FILE *obuf, *ibuf, *readstat;
    struct stat statb;
    char tempname[PATHSIZE];

    if (readonly)
        return;
    holdsigs();
    if (Tflag != NULL) {
        if ((readstat = Fopen(Tflag, "w")) == NULL)
            Tflag = NULL;
    }
    for (mp = &message[0], gotcha = 0; mp < &message[msgCount]; mp++) {
        if (mp->m_flag & MNEW) {
            mp->m_flag &= ~MNEW;
            mp->m_flag |= MSTATUS;
        }
        if (mp->m_flag & (MODIFY|MDELETED|MSTATUS))
            gotcha++;
        if (Tflag != NULL && (mp->m_flag & (MREAD|MDELETED)) != 0) {
            char *id;

            if ((id = hfield("article-id", mp)) != NULL)
                fprintf(readstat, "%s\n", id);
        }
    }
    if (Tflag != NULL)
        Fclose(readstat);
    if (!gotcha || Tflag != NULL)
        goto done;
    ibuf = NULL;
    if (stat(mailname, &statb) >= 0 && statb.st_size > mailsize) {
        int fd;

        snprintf(tempname, sizeof(tempname), "%s/mbox.XXXXXXXXXX",
                 tmpdir);
        if ((fd = mkstemp(tempname)) == -1 ||
                (obuf = Fdopen(fd, "w")) == NULL) {
            warn("%s", tempname);
            relsesigs();
            reset(0);
        }
        if ((ibuf = Fopen(mailname, "r")) == NULL) {
            warn("%s", mailname);
            Fclose(obuf);
            rm(tempname);
            relsesigs();
            reset(0);
        }
        fseeko(ibuf, mailsize, SEEK_SET);
        while ((c = getc(ibuf)) != EOF)
            putc(c, obuf);
        Fclose(ibuf);
        Fclose(obuf);
        if ((ibuf = Fopen(tempname, "r")) == NULL) {
            warn("%s", tempname);
            rm(tempname);
            relsesigs();
            reset(0);
        }
        rm(tempname);
    }
    printf("\"%s\" ", mailname);
    fflush(stdout);
    if ((obuf = Fopen(mailname, "r+")) == NULL) {
        warn("%s", mailname);
        relsesigs();
        reset(0);
    }
    trunc(obuf);
    c = 0;
    for (mp = &message[0]; mp < &message[msgCount]; mp++) {
        if ((mp->m_flag & MDELETED) != 0)
            continue;
        c++;
        if (sendmessage(mp, obuf, NULL, NULL) < 0) {
            warnx("%s", mailname);
            relsesigs();
            reset(0);
        }
    }
    gotcha = (c == 0 && ibuf == NULL);
    if (ibuf != NULL) {
        while ((c = getc(ibuf)) != EOF)
            putc(c, obuf);
        Fclose(ibuf);
    }
    fflush(obuf);
    if (ferror(obuf)) {
        warn("%s", mailname);
        relsesigs();
        reset(0);
    }
    Fclose(obuf);
    if (gotcha) {
        rm(mailname);
        printf("removed\n");
    } else
        printf("complete\n");
    fflush(stdout);

done:
    relsesigs();
}
Пример #13
0
static void
hprf(const char *fmt, int mesg, FILE *f, int threaded, const char *attrlist)
{
	struct message	*mp = &message[mesg-1];
	char	*headline = NULL, *subjline, *name, *cp, *pbuf = NULL;
	struct headline	hl;
	size_t	headsize = 0;
	const char	*fp;
	int	B, c, i, n, s;
	int	headlen = 0;
	struct str	in, out;
	int	subjlen = scrnwidth, fromlen, isto = 0, isaddr = 0;
	FILE	*ibuf;

	if ((mp->m_flag & MNOFROM) == 0) {
		if ((ibuf = setinput(&mb, mp, NEED_HEADER)) == NULL)
			return;
		if ((headlen = readline(ibuf, &headline, &headsize)) < 0)
			return;
	}
	if ((subjline = hfield("subject", mp)) == NULL)
		subjline = hfield("subj", mp);
	if (subjline == NULL) {
		out.s = NULL;
		out.l = 0;
	} else {
		in.s = subjline;
		in.l = strlen(subjline);
		mime_fromhdr(&in, &out, TD_ICONV | TD_ISPR);
		subjline = out.s;
	}
	if ((mp->m_flag & MNOFROM) == 0) {
		pbuf = ac_alloc(headlen + 1);
		parse(headline, headlen, &hl, pbuf);
	} else {
		hl.l_from = /*fakefrom(mp);*/NULL;
		hl.l_tty = NULL;
		hl.l_date = fakedate(mp->m_time);
	}
	if (value("datefield") && (cp = hfield("date", mp)) != NULL)
		hl.l_date = fakedate(rfctime(cp));
	if (Iflag) {
		if ((name = hfield("newsgroups", mp)) == NULL)
			if ((name = hfield("article-id", mp)) == NULL)
				name = "<>";
		name = prstr(name);
	} else if (value("show-rcpt") == NULL) {
		name = name1(mp, 0);
		isaddr = 1;
		if (value("showto") && name && is_myname(skin(name))) {
			if ((cp = hfield("to", mp)) != NULL) {
				name = cp;
				isto = 1;
			}
		}
	} else {
		isaddr = 1;
		if ((name = hfield("to", mp)) != NULL)
			isto = 1;
	}
	if (name == NULL) {
		name = "";
		isaddr = 0;
	}
	if (isaddr) {
		if (value("showname"))
			name = realname(name);
		else {
			name = prstr(skin(name));
		}
	}
	for (fp = fmt; *fp; fp++) {
		if (*fp == '%') {
			if (*++fp == '-') {
				fp++;
			} else if (*fp == '+')
				fp++;
			while (digitchar(*fp&0377))
				fp++;
			if (*fp == '\0')
				break;
		} else {
#if defined (HAVE_MBTOWC) && defined (HAVE_WCWIDTH)
			if (mb_cur_max > 1) {
				wchar_t	wc;
				if ((s = mbtowc(&wc, fp, mb_cur_max)) < 0)
					n = s = 1;
				else {
					if ((n = wcwidth(wc)) < 0)
						n = 1;
				}
			} else
#endif  /* HAVE_MBTOWC && HAVE_WCWIDTH */
			{
				n = s = 1;
			}
			subjlen -= n;
			while (--s > 0)
				fp++;
		}
	}
	for (fp = fmt; *fp; fp++) {
		if (*fp == '%') {
			B = 0;
			n = 0;
			s = 1;
			if (*++fp == '-') {
				s = -1;
				fp++;
			} else if (*fp == '+')
				fp++;
			if (digitchar(*fp&0377)) {
				do
					n = 10*n + *fp - '0';
				while (fp++, digitchar(*fp&0377));
			}
			if (*fp == '\0')
				break;
			n *= s;
			switch (*fp) {
			case '%':
				putc('%', f);
				subjlen--;
				break;
			case '>':
			case '<':
				c = dot == mp ? *fp&0377 : ' ';
				putc(c, f);
				subjlen--;
				break;
			case 'a':
				c = dispc(mp, attrlist);
				putc(c, f);
				subjlen--;
				break;
			case 'm':
				if (n == 0) {
					n = 3;
					if (threaded)
						for (i=msgCount; i>999; i/=10)
							n++;
				}
				subjlen -= fprintf(f, "%*d", n, mesg);
				break;
			case 'f':
				if (n <= 0)
					n = 18;
				fromlen = n;
				if (isto)
					fromlen -= 3;
				fprintf(f, "%s%s", isto ? "To " : "",
						colalign(name, fromlen, 1));
				subjlen -= n;
				break;
			case 'd':
				if (n <= 0)
					n = 16;
				subjlen -= fprintf(f, "%*.*s", n, n, hl.l_date);
				break;
			case 'l':
				if (n == 0)
					n = 4;
				if (mp->m_xlines)
					subjlen -= fprintf(f, "%*ld", n,
							mp->m_xlines);
				else {
					subjlen -= n;
					while (n--)
						putc(' ', f);
				}
				break;
			case 'o':
				if (n == 0)
					n = -5;
				subjlen -= fprintf(f, "%*lu", n,
						(long)mp->m_xsize);
				break;
			case 'i':
				if (threaded)
					subjlen -= putindent(f, mp,
							scrnwidth - 60);
				break;
			case 'S':
				B = 1;
				/*FALLTHRU*/
			case 's':
				n = n>0 ? n : subjlen - 2;
				if (B)
					n -= 2;
				if (subjline != NULL && n >= 0) {
					/* pretty pathetic */
					fprintf(f, B ? "\"%s\"" : "%s",
						colalign(subjline, n, 0));
				}
				break;
			case 'U':
				if (n == 0)
					n = 9;
				subjlen -= fprintf(f, "%*lu", n, mp->m_uid);
				break;
			case 'e':
				if (n == 0)
					n = 2;
				subjlen -= fprintf(f, "%*u", n, threaded == 1 ?
						mp->m_level : 0);
				break;
			case 't':
				if (n == 0) {
					n = 3;
					if (threaded)
						for (i=msgCount; i>999; i/=10)
							n++;
				}
				fprintf(f, "%*ld", n, threaded ?
						mp->m_threadpos : mesg);
				subjlen -= n;
				break;
			case 'c':
				if (n == 0)
					n = 6;
				subjlen -= fprintf(f, "%*g", n, mp->m_score);
				break;
			}
		} else
			putc(*fp&0377, f);
	}
	putc('\n', f);
	if (out.s)
		free(out.s);
	if (headline)
		free(headline);
	if (pbuf)
		ac_free(pbuf);
}
Пример #14
0
void 
quit(
    int noremove	/* don't remove system mailbox, trunc it instead */
)
{
	int mcount, p, modify, autohold, anystat, holdbit, nohold, fd;
	FILE *ibuf, *obuf, *fbuf, *readstat;
	register struct message *mp;
	register int c;
	char *id;
	int appending;
	char *mbox = Getf("MBOX");

	/*
	 * If we are read only, we can't do anything,
	 * so just return quickly.
	 */

	mcount = 0;
	if (readonly)
		return;
	/*
	 * See if there any messages to save in mbox.  If no, we
	 * can save copying mbox to /tmp and back.
	 *
	 * Check also to see if any files need to be preserved.
	 * Delete all untouched messages to keep them out of mbox.
	 * If all the messages are to be preserved, just exit with
	 * a message.
	 *
	 * If the luser has sent mail to himself, refuse to do
	 * anything with the mailbox, unless mail locking works.
	 */

#ifndef CANLOCK
	if (selfsent) {
		printf(gettext("You have new mail.\n"));
		return;
	}
#endif

	/*
	 * Adjust the message flags in each message.
	 */

	anystat = 0;
	autohold = value("hold") != NOSTR;
	appending = value("append") != NOSTR;
	holdbit = autohold ? MPRESERVE : MBOX;
	nohold = MBOXED|MBOX|MSAVED|MDELETED|MPRESERVE;
	if (value("keepsave") != NOSTR)
		nohold &= ~MSAVED;
	for (mp = &message[0]; mp < &message[msgCount]; mp++) {
		if (mp->m_flag & MNEW) {
			receipt(mp);
			mp->m_flag &= ~MNEW;
			mp->m_flag |= MSTATUS;
		}
		if (mp->m_flag & MSTATUS)
			anystat++;
		if ((mp->m_flag & MTOUCH) == 0)
			mp->m_flag |= MPRESERVE;
		if ((mp->m_flag & nohold) == 0)
			mp->m_flag |= holdbit;
	}
	modify = 0;
	if (Tflag != NOSTR) {
		if ((readstat = fopen(Tflag, "w")) == NULL)
			Tflag = NOSTR;
	}
	for (c = 0, p = 0, mp = &message[0]; mp < &message[msgCount]; mp++) {
		if (mp->m_flag & MBOX)
			c++;
		if (mp->m_flag & MPRESERVE)
			p++;
		if (mp->m_flag & MODIFY)
			modify++;
		if (Tflag != NOSTR && (mp->m_flag & (MREAD|MDELETED)) != 0) {
			id = hfield("message-id", mp, addone);
			if (id != NOSTR)
				fprintf(readstat, "%s\n", id);
			else {
				id = hfield("article-id", mp, addone);
				if (id != NOSTR)
					fprintf(readstat, "%s\n", id);
			}
		}
	}
	if (Tflag != NOSTR)
		fclose(readstat);
	if (p == msgCount && !modify && !anystat) {
		if (p == 1)
			printf(gettext("Held 1 message in %s\n"), mailname);
		else
			printf(gettext("Held %d messages in %s\n"), p,
			    mailname);
		return;
	}
	if (c == 0) {
		writeback(noremove);
		return;
	}

	/*
	 * Create another temporary file and copy user's mbox file
	 * therein.  If there is no mbox, copy nothing.
	 * If s/he has specified "append" don't copy the mailbox,
	 * just copy saveable entries at the end.
	 */

	mcount = c;
	if (!appending) {
		if ((fd = open(tempQuit, O_RDWR|O_CREAT|O_EXCL, 0600)) < 0 ||
		(obuf = fdopen(fd, "w")) == NULL) {
			perror(tempQuit);
			return;
		}
		if ((ibuf = fopen(tempQuit, "r")) == NULL) {
			perror(tempQuit);
			removefile(tempQuit);
			fclose(obuf);
			return;
		}
		removefile(tempQuit);
		if ((fbuf = fopen(mbox, "r")) != NULL) {
			while ((c = getc(fbuf)) != EOF)
				putc(c, obuf);
			fclose(fbuf);
		}
		fflush(obuf);
		if (fferror(obuf)) {
			perror(tempQuit);
			fclose(ibuf);
			fclose(obuf);
			return;
		}
		fclose(obuf);
		if ((fd = open(mbox, O_RDWR|O_CREAT|O_TRUNC, MBOXPERM)) < 0 ||
		    (obuf = fdopen(fd, "r+")) == NULL) {
			perror(mbox);
			fclose(ibuf);
			return;
		}
		if (issysmbox)
			touchlock();
	} else {	/* we are appending */
		if ((fd = open(mbox, O_RDWR|O_CREAT, MBOXPERM)) < 0 ||
		    (obuf = fdopen(fd, "a")) == NULL) {
			perror(mbox);
			return;
		}
	}
	for (mp = &message[0]; mp < &message[msgCount]; mp++)
		if (mp->m_flag & MBOX) {
			if (msend(mp, obuf, (int)value("alwaysignore") ?
			    M_IGNORE|M_SAVING : M_SAVING, fputs) < 0) {
				perror(mbox);
				if (!appending)
					fclose(ibuf);
				fclose(obuf);
				return;
			}
			mp->m_flag &= ~MBOX;
			mp->m_flag |= MBOXED;
			if (issysmbox)
				touchlock();
		}

	/*
	 * Copy the user's old mbox contents back
	 * to the end of the stuff we just saved.
	 * If we are appending, this is unnecessary.
	 */

	if (!appending) {
		rewind(ibuf);
		c = getc(ibuf);
		while (c != EOF) {
			putc(c, obuf);
			if (ferror(obuf))
				break;
			c = getc(ibuf);
		}
		fclose(ibuf);
		fflush(obuf);
	}
	trunc(obuf);
	if (fferror(obuf)) {
		perror(mbox);
		fclose(obuf);
		return;
	}
	fclose(obuf);
	if (mcount == 1)
		printf(gettext("Saved 1 message in %s\n"), mbox);
	else
		printf(gettext("Saved %d messages in %s\n"), mcount, mbox);

	/*
	 * Now we are ready to copy back preserved files to
	 * the system mailbox, if any were requested.
	 */
	writeback(noremove);
}
Пример #15
0
quit()
{
	int mcount, p, modify, autohold, anystat, holdbit, nohold;
	FILE *ibuf, *obuf, *fbuf, *rbuf, *readstat, *abuf;
	register struct message *mp;
	register int c;
	extern char tempQuit[], tempResid[];
	struct stat minfo;
	char *id;

	/*
	 * If we are read only, we can't do anything,
	 * so just return quickly.
	 */

	if (readonly)
		return;
	/*
	 * See if there any messages to save in mbox.  If no, we
	 * can save copying mbox to /tmp and back.
	 *
	 * Check also to see if any files need to be preserved.
	 * Delete all untouched messages to keep them out of mbox.
	 * If all the messages are to be preserved, just exit with
	 * a message.
	 *
	 * If the luser has sent mail to himself, refuse to do
	 * anything with the mailbox, unless mail locking works.
	 */

	fbuf = fopen(mailname, "r");
	if (fbuf == NULL)
		goto newmail;
	flock(fileno(fbuf), LOCK_EX);
#ifndef CANLOCK
	if (selfsent) {
		printf("You have new mail.\n");
		fclose(fbuf);
		return;
	}
#endif
	rbuf = NULL;
	if (fstat(fileno(fbuf), &minfo) >= 0 && minfo.st_size > mailsize) {
		printf("New mail has arrived.\n");
		rbuf = fopen(tempResid, "w");
		if (rbuf == NULL || fbuf == NULL)
			goto newmail;
#ifdef APPEND
		fseek(fbuf, mailsize, 0);
		while ((c = getc(fbuf)) != EOF)
			putc(c, rbuf);
#else
		p = minfo.st_size - mailsize;
		while (p-- > 0) {
			c = getc(fbuf);
			if (c == EOF)
				goto newmail;
			putc(c, rbuf);
		}
#endif
		fclose(rbuf);
		if ((rbuf = fopen(tempResid, "r")) == NULL)
			goto newmail;
		remove(tempResid);
	}

	/*
	 * Adjust the message flags in each message.
	 */

	anystat = 0;
	autohold = value("hold") != NOSTR;
	holdbit = autohold ? MPRESERVE : MBOX;
	nohold = MBOX|MSAVED|MDELETED|MPRESERVE;
	if (value("keepsave") != NOSTR)
		nohold &= ~MSAVED;
	for (mp = &message[0]; mp < &message[msgCount]; mp++) {
		if (mp->m_flag & MNEW) {
			mp->m_flag &= ~MNEW;
			mp->m_flag |= MSTATUS;
		}
		if (mp->m_flag & MSTATUS)
			anystat++;
		if ((mp->m_flag & MTOUCH) == 0)
			mp->m_flag |= MPRESERVE;
		if ((mp->m_flag & nohold) == 0)
			mp->m_flag |= holdbit;
	}
	modify = 0;
	if (Tflag != NOSTR) {
		if ((readstat = fopen(Tflag, "w")) == NULL)
			Tflag = NOSTR;
	}
	for (c = 0, p = 0, mp = &message[0]; mp < &message[msgCount]; mp++) {
		if (mp->m_flag & MBOX)
			c++;
		if (mp->m_flag & MPRESERVE)
			p++;
		if (mp->m_flag & MODIFY)
			modify++;
		if (Tflag != NOSTR && (mp->m_flag & (MREAD|MDELETED)) != 0) {
			id = hfield("article-id", mp);
			if (id != NOSTR)
				fprintf(readstat, "%s\n", id);
		}
	}
	if (Tflag != NOSTR)
		fclose(readstat);
	if (p == msgCount && !modify && !anystat) {
		if (p == 1)
			printf("Held 1 message in %s\n", mailname);
		else
			printf("Held %2d messages in %s\n", p, mailname);
		fclose(fbuf);
		return;
	}
	if (c == 0) {
		if (p != 0) {
			writeback(rbuf);
			fclose(fbuf);
			return;
		}
		goto cream;
	}

	/*
	 * Create another temporary file and copy user's mbox file
	 * darin.  If there is no mbox, copy nothing.
	 * If he has specified "append" don't copy his mailbox,
	 * just copy saveable entries at the end.
	 */

	mcount = c;
	if (value("append") == NOSTR) {
		if ((obuf = fopen(tempQuit, "w")) == NULL) {
			perror(tempQuit);
			fclose(fbuf);
			return;
		}
		if ((ibuf = fopen(tempQuit, "r")) == NULL) {
			perror(tempQuit);
			remove(tempQuit);
			fclose(obuf);
			fclose(fbuf);
			return;
		}
		remove(tempQuit);
		if ((abuf = fopen(mbox, "r")) != NULL) {
			while ((c = getc(abuf)) != EOF)
				putc(c, obuf);
			fclose(abuf);
		}
		if (ferror(obuf)) {
			perror(tempQuit);
			fclose(ibuf);
			fclose(obuf);
			fclose(fbuf);
			return;
		}
		fclose(obuf);
		close(creat(mbox, 0600));
		if ((obuf = fopen(mbox, "r+")) == NULL) {
			perror(mbox);
			fclose(ibuf);
			fclose(fbuf);
			return;
		}
	}
	if (value("append") != NOSTR) {
		if ((obuf = fopen(mbox, "a")) == NULL) {
			perror(mbox);
			fclose(fbuf);
			return;
		}
		fchmod(fileno(obuf), 0600);
	}
	for (mp = &message[0]; mp < &message[msgCount]; mp++)
		if (mp->m_flag & MBOX)
			if (send(mp, obuf, 0) < 0) {
				perror(mbox);
				fclose(ibuf);
				fclose(obuf);
				fclose(fbuf);
				return;
			}

	/*
	 * Copy the user's old mbox contents back
	 * to the end of the stuff we just saved.
	 * If we are appending, this is unnecessary.
	 */

	if (value("append") == NOSTR) {
		rewind(ibuf);
		c = getc(ibuf);
		while (c != EOF) {
			putc(c, obuf);
			if (ferror(obuf))
				break;
			c = getc(ibuf);
		}
		fclose(ibuf);
		fflush(obuf);
	}
	trunc(obuf);
	if (ferror(obuf)) {
		perror(mbox);
		fclose(obuf);
		fclose(fbuf);
		return;
	}
	fclose(obuf);
	if (mcount == 1)
		printf("Saved 1 message in mbox\n");
	else
		printf("Saved %d messages in mbox\n", mcount);

	/*
	 * Now we are ready to copy back preserved files to
	 * the system mailbox, if any were requested.
	 */

	if (p != 0) {
		writeback(rbuf);
		fclose(fbuf);
		return;
	}

	/*
	 * Finally, remove his /usr/mail file.
	 * If new mail has arrived, copy it back.
	 */

cream:
	if (rbuf != NULL) {
		abuf = fopen(mailname, "r+");
		if (abuf == NULL)
			goto newmail;
		while ((c = getc(rbuf)) != EOF)
			putc(c, abuf);
		fclose(rbuf);
		trunc(abuf);
		fclose(abuf);
		alter(mailname);
		fclose(fbuf);
		return;
	}
	demail();
	fclose(fbuf);
	return;

newmail:
	printf("Thou hast new mail.\n");
	if (fbuf != NULL)
		fclose(fbuf);
}