/* * Send message described by the passed pointer to the * passed output buffer. Return -1 on error. * Adjust the status: field if need be. * If doign is given, suppress ignored header fields. * prefix is a string to prepend to each output line. */ int sendmessage(struct message *mp, FILE *obuf, struct ignoretab *doign, char *prefix) { int count; FILE *ibuf; char line[LINESIZE]; char visline[4 * LINESIZE - 3]; int ishead, infld, ignoring = 0, dostat, firstline; char *cp, *cp2; int c = 0; int length; int prefixlen = 0; int rval; int dovis; struct sigaction act, saveint; sigset_t oset; sendsignal = 0; rval = -1; dovis = isatty(fileno(obuf)); sigemptyset(&act.sa_mask); act.sa_flags = SA_RESTART; act.sa_handler = sendint; (void)sigaction(SIGINT, &act, &saveint); (void)sigprocmask(SIG_UNBLOCK, &intset, &oset); /* * Compute the prefix string, without trailing whitespace */ if (prefix != NULL) { cp2 = 0; for (cp = prefix; *cp; cp++) if (*cp != ' ' && *cp != '\t') cp2 = cp; prefixlen = cp2 == 0 ? 0 : cp2 - prefix + 1; } ibuf = setinput(mp); count = mp->m_size; ishead = 1; dostat = doign == 0 || !isign("status", doign); infld = 0; firstline = 1; /* * Process headers first */ while (count > 0 && ishead) { if (fgets(line, sizeof(line), ibuf) == NULL) break; count -= length = strlen(line); if (firstline) { /* * First line is the From line, so no headers * there to worry about */ firstline = 0; ignoring = doign == ignoreall; } else if (line[0] == '\n') { /* * If line is blank, we've reached end of * headers, so force out status: field * and note that we are no longer in header * fields */ if (dostat) { if (statusput(mp, obuf, prefix) == -1) goto out; dostat = 0; } ishead = 0; ignoring = doign == ignoreall; } else if (infld && (line[0] == ' ' || line[0] == '\t')) { /* * If this line is a continuation (via space or tab) * of a previous header field, just echo it * (unless the field should be ignored). * In other words, nothing to do. */ } else { /* * Pick up the header field if we have one. */ for (cp = line; (c = *cp++) && c != ':' && !isspace(c);) ; cp2 = --cp; while (isspace(*cp++)) ; if (cp[-1] != ':') { /* * Not a header line, force out status: * This happens in uucp style mail where * there are no headers at all. */ if (dostat) { if (statusput(mp, obuf, prefix) == -1) goto out; dostat = 0; } if (doign != ignoreall) /* add blank line */ (void)putc('\n', obuf); ishead = 0; ignoring = 0; } else { /* * If it is an ignored field and * we care about such things, skip it. */ *cp2 = 0; /* temporarily null terminate */ if (doign && isign(line, doign)) ignoring = 1; else if (strcasecmp(line, "status") == 0) { /* * If the field is "status," go compute * and print the real Status: field */ if (dostat) { if (statusput(mp, obuf, prefix) == -1) goto out; dostat = 0; } ignoring = 1; } else { ignoring = 0; *cp2 = c; /* restore */ } infld = 1; } } if (!ignoring) { /* * Strip trailing whitespace from prefix * if line is blank. */ if (prefix != NULL) { if (length > 1) fputs(prefix, obuf); else (void)fwrite(prefix, sizeof(*prefix), prefixlen, obuf); } if (dovis) { length = strvis(visline, line, VIS_SAFE|VIS_NOSLASH); (void)fwrite(visline, sizeof(*visline), length, obuf); } else (void)fwrite(line, sizeof(*line), length, obuf); if (ferror(obuf)) goto out; } if (sendsignal == SIGINT) goto out; } /* * Copy out message body */ if (doign == ignoreall) count--; /* skip final blank line */ while (count > 0) { if (fgets(line, sizeof(line), ibuf) == NULL) { c = 0; break; } count -= c = strlen(line); if (prefix != NULL) { /* * Strip trailing whitespace from prefix * if line is blank. */ if (c > 1) fputs(prefix, obuf); else (void)fwrite(prefix, sizeof(*prefix), prefixlen, obuf); } /* * We can't read the record file (or inbox for recipient) * properly with 'From ' lines in the message body (from * forwarded messages or sentences starting with "From "), * so we will prepend those lines with a '>'. */ if (strncmp(line, "From ", 5) == 0) (void)fwrite(">", 1, 1, obuf); /* '>' before 'From ' */ if (dovis) { length = strvis(visline, line, VIS_SAFE|VIS_NOSLASH); (void)fwrite(visline, sizeof(*visline), length, obuf); } else (void)fwrite(line, sizeof(*line), c, obuf); if (ferror(obuf) || sendsignal == SIGINT) goto out; } if (doign == ignoreall && c > 0 && line[c - 1] != '\n') /* no final blank line */ if ((c = getc(ibuf)) != EOF && putc(c, obuf) == EOF) goto out; rval = 0; out: sendsignal = 0; (void)sigprocmask(SIG_SETMASK, &oset, NULL); (void)sigaction(SIGINT, &saveint, NULL); return(rval); }
/* * Send message described by the passed pointer to the * passed output buffer. Return -1 on error. * Adjust the status: field if need be. * If doign is given, suppress ignored header fields. * prefix is a string to prepend to each output line. */ int sendmessage(struct message *mp, FILE *obuf, struct ignoretab *doign, char *prefix) { long count; FILE *ibuf; char *cp, *cp2, line[LINESIZE]; int ishead, infld, ignoring, dostat, firstline; int c = 0, length, prefixlen; /* * Compute the prefix string, without trailing whitespace */ if (prefix != NULL) { cp2 = 0; for (cp = prefix; *cp != '\0'; cp++) if (*cp != ' ' && *cp != '\t') cp2 = cp; prefixlen = cp2 == NULL ? 0 : cp2 - prefix + 1; } ibuf = setinput(mp); count = mp->m_size; ishead = 1; dostat = doign == 0 || !isign("status", doign); infld = 0; firstline = 1; /* * Process headers first */ while (count > 0 && ishead) { if (fgets(line, sizeof(line), ibuf) == NULL) break; count -= length = strlen(line); if (firstline) { /* * First line is the From line, so no headers * there to worry about */ firstline = 0; ignoring = doign == ignoreall; } else if (line[0] == '\n') { /* * If line is blank, we've reached end of * headers, so force out status: field * and note that we are no longer in header * fields */ if (dostat) { statusput(mp, obuf, prefix); dostat = 0; } ishead = 0; ignoring = doign == ignoreall; } else if (infld && (line[0] == ' ' || line[0] == '\t')) { /* * If this line is a continuation (via space or tab) * of a previous header field, just echo it * (unless the field should be ignored). * In other words, nothing to do. */ } else { /* * Pick up the header field if we have one. */ for (cp = line; (c = *cp++) != '\0' && c != ':' && !isspace((unsigned char)c);) ; cp2 = --cp; while (isspace((unsigned char)*cp++)) ; if (cp[-1] != ':') { /* * Not a header line, force out status: * This happens in uucp style mail where * there are no headers at all. */ if (dostat) { statusput(mp, obuf, prefix); dostat = 0; } if (doign != ignoreall) /* add blank line */ (void)putc('\n', obuf); ishead = 0; ignoring = 0; } else { /* * If it is an ignored field and * we care about such things, skip it. */ *cp2 = '\0'; /* temporarily null terminate */ if (doign && isign(line, doign)) ignoring = 1; else if ((line[0] == 's' || line[0] == 'S') && strcasecmp(line, "status") == 0) { /* * If the field is "status," go compute * and print the real Status: field */ if (dostat) { statusput(mp, obuf, prefix); dostat = 0; } ignoring = 1; } else { ignoring = 0; *cp2 = c; /* restore */ } infld = 1; } } if (!ignoring) { /* * Strip trailing whitespace from prefix * if line is blank. */ if (prefix != NULL) { if (length > 1) fputs(prefix, obuf); else (void)fwrite(prefix, sizeof(*prefix), prefixlen, obuf); } (void)fwrite(line, sizeof(*line), length, obuf); if (ferror(obuf)) return (-1); } } /* * Copy out message body */ if (doign == ignoreall) count--; /* skip final blank line */ if (prefix != NULL) while (count > 0) { if (fgets(line, sizeof(line), ibuf) == NULL) { c = 0; break; } count -= c = strlen(line); /* * Strip trailing whitespace from prefix * if line is blank. */ if (c > 1) fputs(prefix, obuf); else (void)fwrite(prefix, sizeof(*prefix), prefixlen, obuf); (void)fwrite(line, sizeof(*line), c, obuf); if (ferror(obuf)) return (-1); } else while (count > 0) { c = count < LINESIZE ? count : LINESIZE; if ((c = fread(line, sizeof(*line), c, ibuf)) <= 0) break; count -= c; if (fwrite(line, sizeof(*line), c, obuf) != c) return (-1); } if (doign == ignoreall && c > 0 && line[c - 1] != '\n') /* no final blank line */ if ((c = getc(ibuf)) != EOF && putc(c, obuf) == EOF) return (-1); return (0); }
/* * Send message described by the passed pointer to the * passed output buffer. Return -1 on error, but normally * the number of lines written. Adjust the status: field * if need be. If doign is set, suppress ignored header fields. * Call (*fp)(line, obuf) to print the line. */ long msend( struct message *mailp, FILE *obuf, int flag, int (*fp)(const char *, FILE *)) { register struct message *mp; long clen, n, c; FILE *ibuf; char line[LINESIZE], field[BUFSIZ]; int ishead, infld, fline, dostat, doclen, nread, unused; char *cp, *cp2; int doign = flag & M_IGNORE; int oldign = 0; /* previous line was ignored */ long lc; mp = mailp; if (mp->m_clen == 0) setclen(mp); ibuf = setinput(mp); c = mp->m_size; ishead = 1; dostat = 1; doclen = 1; infld = 0; fline = 1; lc = 0; clearerr(obuf); while (c > 0L) { nread = getaline(line, LINESIZE, ibuf, &unused); c -= nread; lc++; if (ishead) { /* * First line is the From line, so no headers * there to worry about */ if (fline) { fline = 0; goto writeit; } /* * If line is blank, we've reached end of * headers, so force out status: field * and note that we are no longer in header * fields. Also force out Content-Length: field. */ if (line[0] == '\n') { if (dostat) { statusput(mailp, obuf, doign, fp); dostat = 0; } if (doclen && !isign("content-length", flag&M_SAVING)) { snprintf(field, sizeof (field), "Content-Length: %ld\n", mp->m_clen - 1); (*fp)(field, obuf); if (ferror(obuf)) return(-1); doclen = 0; } ishead = 0; goto writeit; } /* * If this line is a continuation * of a previous header field, just echo it. */ if (isspace(line[0]) && infld) if (oldign) continue; else goto writeit; infld = 0; /* * If we are no longer looking at real * header lines, force out status: * This happens in uucp style mail where * there are no headers at all. */ if (!headerp(line)) { if (dostat) { statusput(mailp, obuf, doign, fp); dostat = 0; } (*fp)("\n", obuf); ishead = 0; goto writeit; } infld++; /* * Pick up the header field. * If it is an ignored field and * we care about such things, skip it. */ cp = line; cp2 = field; while (*cp && *cp != ':' && !isspace(*cp)) *cp2++ = *cp++; *cp2 = 0; oldign = doign && isign(field, flag&M_SAVING); if (oldign) continue; /* * If the field is "status," go compute and print the * real Status: field */ if (icequal(field, "status")) { if (dostat) { statusput(mailp, obuf, doign, fp); dostat = 0; } continue; } if (icequal(field, "content-length")) { if (doclen) { snprintf(line, sizeof (line), "Content-Length: %ld\n", mp->m_clen - 1); (*fp)(line, obuf); if (ferror(obuf)) return(-1); doclen = 0; } continue; } } writeit: if (!ishead && !mp->m_text && mp->m_clen != 0) { if (line[0] == '\n') putc('\n', obuf); clen = mp->m_clen-1; for (;;) { n = clen < sizeof line ? clen : sizeof line; if ((n = fread(line, 1, (int)n, ibuf)) <= 0) { fprintf(stderr, gettext( "\t(Unexpected end-of-file).\n")); clen = 0; } else { if (fwrite(line, 1, (int)n, obuf) != n) { fprintf(stderr, gettext( "\tError writing to the new file.\n")); fflush(obuf); if (fferror(obuf)) return (-1); } } clen -= n; if (clen <= 0) { break; } } c = 0L; } else { (*fp)(line, obuf); if (ferror(obuf)) return(-1); } } fflush(obuf); if (ferror(obuf)) return(-1); if (ishead && (mailp->m_flag & MSTATUS)) printf(gettext("failed to fix up status field\n")); return(lc); }