+ int length = strlen(comp); /* convenience copy */
+ int count = 1; /* Number of matching header line. */
+ int c, n;
+ char *cp;
+ char *field = NULL;
+ int field_size = 256;
+ FILE *fp;
+
+ /*
+ ** We're going to need to copy some of the message file to the
+ ** temporary file while examining the contents. Convert the
+ ** message file descriptor to a file pointer since it's a lot
+ ** easier and more efficient to use stdio for this. Also allocate
+ ** a buffer to hold the header components as they're read in.
+ ** This buffer is grown as needed later.
+ */
+ if ((fp = fdopen(fd, "r")) == NULL) {
+ adios(EX_IOERR, NULL, "unable to fdopen file.");
+ }
+ field = mh_xcalloc(field_size, sizeof(char));
+
+ /*
+ ** Copy lines from the input file to the temporary file
+ ** until we either find the one that we're looking
+ ** for (which we don't copy) or we reach the end of
+ ** the headers. Both a blank line and a line beginning
+ ** with a - terminate the headers so that we can handle
+ ** both drafts and RFC-2822 format messages.
+ */
+ do {
+ /*
+ ** Get a line from the input file, growing the
+ ** field buffer as needed. We do this so that
+ ** we can fit an entire line in the buffer making
+ ** it easy to do a string comparison on both the
+ ** field name and the field body which might be
+ ** a long path name.
+ */
+ for (n=0, cp=field; (c=getc(fp)) != EOF; *cp++ = c) {
+ if (c == '\n') {
+ ungetc((c = getc(fp)), fp);
+ if (c != ' ' && c != '\t') {
+ c = '\n';
+ break;
+ }
+ c = '\n';
+ }
+
+ if (++n >= field_size - 1) {
+ field = mh_xrealloc(field, field_size *= 2);
+ cp = field + n - 1;
+ }
+ }
+ *cp = '\0';
+
+ if (strncasecmp(field, comp, length)==0 &&
+ field[length] == ':') {
+ /*
+ ** This component matches and thus is a candidate.
+ ** We delete the line by not copying it to the
+ ** temporary file. Thus:
+ ** - Break if we've found the one to delete.
+ ** - Continue if this is one to delete, but
+ ** there'll be further ones.
+ */
+
+ if (!number && !text) {
+ /* this first one is it */
+ break;
+ }
+
+ if (number == -1) {
+ /* delete all of them */
+ continue;
+ } else if (number == count++) {
+ /* delete this specific one */
+ break;
+ }
+
+ if (text) {
+ /* delete the first matching one */
+ cp = field+length+1;
+ while (*cp==' ' || *cp=='\t') {
+ cp++; /* eat leading whitespace */
+ }
+ if (*text == '/' && strcmp(text, cp)==0) {
+ break; /* full path matches */
+ } else if (strcmp(text, mhbasename(cp))==0) {
+ break; /* basename matches */
+ }
+ }
+ /*
+ ** Although the compoment name mached, it
+ ** wasn't the right one.
+ */
+ }
+
+ /* Copy it. */
+ if ((n = fputs(field, tmp)) == EOF ||
+ (c=='\n' && fputc('\n', tmp)==EOF)) {
+ adios(EX_CANTCREAT, NULL, "unable to write temporary file.");
+ }
+
+ } while (*field && *field != '-');
+
+ mh_free0(&field);
+
+ fflush(tmp);
+ fflush(fp); /* The underlying fd will be closed by lkclose() */
+
+ /*
+ ** We've been messing with the input file position. Move the
+ ** input file descriptor to the current place in the file
+ ** because the stock data copying routine uses the descriptor,
+ ** not the pointer.
+ */
+ if (lseek(fd, (off_t)ftell(fp), SEEK_SET) == (off_t)-1) {
+ adios(EX_IOERR, NULL, "can't seek.");
+ }
+}
+
+
+static void
+doadd(int fd, unsigned char *comp, char *text, FILE *tmp, int datesw,
+ int append)
+{
+ char *cp, *sp;
+ int c;
+ FILE *fp = NULL;
+
+ if (append) {
+ /*
+ ** We're going to need to copy some of the message
+ ** file to the temporary file while examining the
+ ** contents. Convert the message file descriptor to
+ ** a file pointer since it's a lot easier and more
+ ** efficient to use stdio for this. Also allocate
+ ** a buffer to hold the header components as they're
+ ** read in. This buffer is grown as needed later.
+ */
+ if ((fp = fdopen(fd, "r")) == NULL) {
+ adios(EX_IOERR, NULL, "unable to fdopen file.");
+ }
+ /* Find the end of the headers. */
+ if ((c = getc(fp)) == '\n') {
+ /* Special check for no headers is needed. */
+ rewind(fp);
+ } else {
+ /*
+ ** Copy lines from the input file to the
+ ** temporary file until we reach the end
+ ** of the headers.
+ */
+ putc(c, tmp);
+ while ((c = getc(fp)) != EOF) {
+ putc(c, tmp);
+ if (c == '\n') {
+ ungetc(c = getc(fp), fp);
+ if (c == '\n' || c == '-') {
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ if (datesw) {
+ fprintf(tmp, "%s: %s\n", comp, dtimenow());
+ }
+ if ((cp = text)) {
+ /* Add body text header */
+ do {
+ while (*cp == ' ' || *cp == '\t') {
+ cp++;
+ }
+ sp = cp;
+ while (*cp && *cp++ != '\n') {
+ continue;
+ }
+ if (cp - sp) {
+ fprintf(tmp, "%s: %*.*s", comp,
+ (int)(cp - sp),
+ (int)(cp - sp), sp);
+ }
+ } while (*cp);
+ if (cp[-1] != '\n' && cp != text) {
+ putc('\n', tmp);
+ }
+ }
+ fflush(tmp);
+
+ /*
+ ** We've been messing with the input file position. Move the
+ ** input file descriptor to the current place in the file
+ ** because the stock data copying routine uses the descriptor,
+ ** not the pointer.
+ */
+ if (append) {
+ if (lseek(fd, (off_t)ftell(fp), SEEK_SET) == (off_t)-1) {
+ adios(EX_IOERR, NULL, "can't seek.");
+ }
+ }