static bool write_header(rc_t status, readfunc_t rf, void *rfarg) { ssize_t rd; char *out; bool hadlf = true; bool seen_subj = false; bool seen_place_header = false; int bogolen = strlen(spam_header_name); const char *subjstr = "Subject:"; int subjlen = strlen(subjstr); eol = NULL; /* print headers */ while ((rd = rf(&out, rfarg)) > 0) { if (eol == NULL) { if (memcmp(out+rd-1, NL, 1) == 0) eol = NL; if (rd >=2 && memcmp(out+rd-2, CRLF, 2) == 0) eol = CRLF; } /* skip over spam_header_name ("X-Bogosity:") lines */ while (rd >= bogolen && memcmp(out, spam_header_name, bogolen) == 0) { while (((rd = rf(&out, rfarg)) > 0) && (out[0] == ' ' || out[0] == '\t') ) /* empty loop */ ; } /* detect spam_header_place line */ if ( !seen_place_header && *spam_header_place != '\0' && memcmp(out, spam_header_place, strlen(spam_header_place)) == 0) { seen_place_header = true; write_spam_info(); } /* detect end of headers */ if (is_eol(out, rd) || is_hb_delim(out, rd, have_body)) /* check for non-empty blank line */ break; /* rewrite "Subject: " line */ if (!seen_subj && rd >= subjlen) { const char *tag = NULL; if (status == RC_SPAM && spam_subject_tag != NULL) tag = spam_subject_tag; if (status == RC_UNSURE && unsure_subject_tag != NULL) tag = unsure_subject_tag; if (tag != NULL && strncasecmp(out, subjstr, subjlen) == 0) { seen_subj = true; (void) fprintf(fpo, "%.*s %s", subjlen, out, tag); if (out[subjlen] != ' ') fputc(' ', fpo); (void) fwrite(out + subjlen, 1, rd - subjlen, fpo); continue; } } hadlf = (out[rd-1] == '\n'); (void) fwrite(out, 1, rd, fpo); if (ferror(fpo)) cleanup_exit(EX_ERROR, 1); } if (!seen_place_header) write_spam_info(); if (!hadlf) (void) fputs(eol, fpo); return seen_subj; }
void write_message(rc_t status) { ssize_t rd; readfunc_t rf = NULL; /* assignment to quench warning */ void *rfarg = 0; /* assignment to quench warning */ char *out; textdata_t *text; int seen_subj = 0; if (passthrough) { int hadlf = 1; int bogolen = strlen(spam_header_name); const char *subjstr = "Subject:"; int subjlen = strlen(subjstr); /* initialize */ switch (passmode) { case PASS_MEM: rf = read_mem; text = textblock_head(); rfarg = &text; break; case PASS_SEEK: rf = read_seek; rfarg = fpin; rewind(rfarg); break; default: abort(); } /* print headers */ while ((rd = rf(&out, rfarg)) > 0) { /* skip over spam_header ("X-Bogosity:") lines */ while (rd >= bogolen && memcmp(out, spam_header_name, bogolen) == 0) { while (((rd = rf(&out, rfarg)) > 0) && (out[0] == ' ' || out[0] == '\t') ) /* empty loop */ ; } /* detect end of headers */ if (is_eol(out, rd) || is_hb_delim(out, rd, have_body)) /* check for non-empty blank line */ break; /* rewrite "Subject: " line */ if (status == RC_SPAM && rd >= subjlen && spam_subject_tag != NULL && strncasecmp(out, subjstr, subjlen) == 0) { (void) fprintf(fpo, "%.*s %s", subjlen, out, spam_subject_tag); if (out[subjlen] != ' ') fputc(' ', fpo); (void) fwrite(out + subjlen, 1, rd - subjlen, fpo); seen_subj = 1; continue; } hadlf = (out[rd-1] == '\n'); (void) fwrite(out, 1, rd, fpo); if (ferror(fpo)) cleanup_exit(2, 1); } if (!hadlf) fputc('\n', fpo); } if (passthrough || verbose || terse) { typedef char *formatter(char *buff, size_t size); formatter *fcn = terse ? format_terse : format_header; char buff[256]; /* print spam-status at the end of the header * then mark the beginning of the message body */ (*fcn)(buff, sizeof(buff)); fputs (buff, fpo); fputs ("\n", fpo); } if (verbose || passthrough || Rtable) { verbose += passthrough; print_stats( stdout ); verbose -= passthrough; } if (passthrough && !seen_subj && status == RC_SPAM && spam_subject_tag != NULL) { (void) fprintf(fpo, "Subject: %s\n", spam_subject_tag); } if (passthrough) { int hadlf = 1; /* If the message terminated early (without body or blank * line between header and body), enforce a blank line to * prevent anything past us from choking. */ (void)fputc('\n', fpo); /* print body */ while ((rd = rf(&out, rfarg)) > 0) { (void) fwrite(out, 1, rd, fpo); hadlf = (out[rd-1] == '\n'); if (ferror(fpo)) cleanup_exit(2, 1); } if (!hadlf) fputc('\n', fpo); if (fflush(fpo) || ferror(fpo) || (fpo != stdout && fclose(fpo))) { cleanup_exit(2, 1); } } }