/* * 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); }
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); }
/* * 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); }
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); } } }
/* * 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); }
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); }
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; }
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; }
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) "e; 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; }
/* * 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); }
/* * 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); }
/* * 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(); }
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); }
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); }
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); }