home *** CD-ROM | disk | FTP | other *** search
- /* $Header: copymsg.c,v 2.4 90/02/06 11:56:38 chip Exp $
- *
- * Take the message from standard input and write it to two temp files,
- * one for the header (including the empty line) and one for the body.
- *
- * $Log: copymsg.c,v $
- * Revision 2.4 90/02/06 11:56:38 chip
- * Enforce MBX_MODE regardless of UMASK.
- * Enforce ordered logging with a log lockfile.
- * Revise log format.
- *
- * Revision 2.3 89/11/27 14:18:29 network
- * Strip trailing spaces from date on From_ line.
- *
- * Revision 2.2 89/09/29 18:17:53 network
- * Save message when delivery file produces no output,
- * unless delivery file output the "DROP" string.
- * Don't recopy temp files for sys and post-user delfiles.
- *
- * Revision 2.1 89/06/09 12:25:16 network
- * Update RCS revisions.
- *
- * Revision 1.9 89/06/09 12:23:40 network
- * Baseline for 2.0 release.
- *
- */
-
- #include "deliver.h"
-
- /*
- * Macros.
- */
-
- /* Does a string start with "From "? */
-
- #define ISFROM(p) ((p)[0] == 'F' && (p)[1] == 'r' && (p)[2] == 'o' \
- && (p)[3] == 'm' && (p)[4] == ' ')
-
- /*----------------------------------------------------------------------
- * Copy the message on the standard input to two temp files:
- * one for the header and one for the body.
- */
-
- int
- copy_message()
- {
- char buf[BUFSIZ];
- FILE *dfp[T_MAX];
- char *p, *from_line, *fsender, *fdate, *fremote;
- int t, b, empty_line;
- int ret = 0;
-
- /*
- * Create temporary files to hold the header and message body.
- */
-
- for (t = T_HDR; t <= T_BODY; ++t)
- {
- int fd;
-
- tfile[t] = tempfile();
- if ((tfd[t] = tcreate(tfile[t])) == -1)
- return -1;
-
- if ((fd = dup(tfd[t])) == -1)
- {
- syserr("dup %s fd", ttype[t]);
- return -1;
- }
- (void) lseek(fd, 0L, 0);
- if ((dfp[t] = fdopen(fd, "r+")) == NULL)
- {
- error("can't fdopen %s fd", ttype[t]);
- return -1;
- }
- }
-
- /* Debugging message for later examination of temp files. */
-
- if (verbose)
- {
- message("header=%s, body=%s\n",
- tfile[T_HDR], tfile[T_BODY]);
- }
-
- /*
- * If there is a From_ line, find the sender name therein.
- */
-
- from_line = NULL;
- fsender = fdate = fremote = NULL;
-
- b = (fgets(buf, GETSIZE(buf), stdin) ? TRUE : FALSE);
-
- if (b && ISFROM(buf) && (p = strchr(buf, '\n')) != NULL)
- {
- b = FALSE;
-
- /* Make a mungable copy of the From_ line */
-
- from_line = copystr(buf);
- if ((p = strchr(from_line, '\n')) != NULL)
- *p = 0;
-
- /* Find sender */
-
- p = from_line + 5;
- while (*p && isspace(*p))
- ++p;
- fsender = p;
- while (*p && !isspace(*p))
- ++p;
- if (*p)
- *p++ = 0;
-
- /* Date received should be around here somewhere */
-
- fdate = p;
-
- /* Find 'remote from' phrase (if any) */
-
- for (; (p = strchr(p, 'r')) != NULL; ++p)
- {
- if (strncmp(p, "remote from", 11) == 0)
- {
- *p = 0;
- p += 11;
- while (*p && isspace(*p))
- ++p;
- if (*p)
- fremote = p;
- break;
- }
- }
-
- /*
- * Advance to first non-space in date.
- * Strip trailing spaces from date.
- * If there is no date, clear the date pointer.
- */
-
- while (*fdate && isspace(*fdate))
- ++fdate;
- p = fdate + strlen(fdate);
- while (p > fdate && isspace(*(p - 1)))
- *--p = 0;
- if (*fdate == 0)
- fdate = NULL;
-
- /*
- * If sender is missing, or if date is invalid,
- * we consider the entire From_ line invalid.
- */
-
- if (*fsender == 0
- || (fdate != NULL && unctime(fdate) == -1) )
- {
- /* Ignore everything we found. */
-
- fsender = fdate = fremote = NULL;
-
- /* Print invalid From_ line in a harmless way. */
-
- (void) strcpy(from_line, buf);
- (void) strcpy(buf, "Invalid-UUCP-From: ");
- (void) strcat(buf, from_line);
- b = TRUE;
- }
- }
-
- /*
- * Write a From_ line to the header file.
- */
-
- /* if caller specified sender, use it */
- if (sender)
- ; /* fine */
-
- /* else if we found a From_ line, use it */
- else if (fsender)
- {
- if (fremote)
- {
- sender = zalloc(strlen(fremote) + sizeof("!")
- + strlen(fsender));
- (void) sprintf(sender, "%s!%s", fremote, fsender);
- }
- else
- sender = copystr(fsender);
- }
-
- /* else use our real ID */
- else
- sender = real_ct->ct_name;
-
- /* debugging message */
-
- if (verbose)
- message("copy_msg: sender is \"%s\"\n", sender);
-
- /*
- * Finally! Write the From_ line.
- */
-
- (void) fputs("From ", dfp[T_HDR]);
- (void) fputs(sender, dfp[T_HDR]);
- (void) fputc(' ', dfp[T_HDR]);
- if (fdate)
- {
- (void) fputs(fdate, dfp[T_HDR]);
- (void) fputc('\n', dfp[T_HDR]);
- }
- else
- {
- time_t now;
-
- (void) time(&now);
- (void) fputs(ctime(&now), dfp[T_HDR]);
- }
-
- /*
- * Free the From_ line if we allocated a copy of it.
- */
-
- if (from_line)
- free(from_line);
-
- /*
- * Copy the rest of the header (if any).
- */
-
- for (; !feof(stdin) && !ferror(stdin); b = FALSE)
- {
- if (!b)
- {
- if (fgets(buf, GETSIZE(buf), stdin))
- b = TRUE;
- else
- break;
- }
-
- /* Empty line means "end of header" */
-
- if (buf[0] == '\n')
- {
- b = FALSE; /* Don't put this line in the body. */
- break;
- }
-
- /*
- * A line too long to fit in buf[] can't be a header line.
- * At least, that's my opinion... :-)
- */
-
- if (!strchr(buf, '\n'))
- break;
-
- /*
- * If line begins with whitespace, it's a continuation.
- * Else if line begins with From_ or '>', prepend '>'.
- * Else if line doesn't look like a header, this must
- * be the beginning of the body.
- */
-
- if (isspace(buf[0]))
- ; /* continuation */
- else if (ISFROM(buf) || (buf[0] == '>'))
- (void) fputc('>', dfp[T_HDR]);
- else
- {
- /* look for the colon on a header label */
-
- p = buf;
- while (isalpha(*p) || *p == '-')
- ++p;
- if ((p == buf) || (*p != ':'))
- break; /* Not a header line! */
- }
-
- /* Write the line to the header file. */
-
- (void) fputs(buf, dfp[T_HDR]);
- }
-
- /*
- * End the header file with a blank line.
- * This enables us to simply concatenate it with the body file
- * to produce a valid message.
- */
-
- (void) fputc('\n', dfp[T_HDR]);
-
- /*
- * Copy the body (if any).
- */
-
- empty_line = FALSE;
- for (; !feof(stdin) && !ferror(stdin); b = FALSE)
- {
- if (!b)
- {
- if (fgets(buf, GETSIZE(buf), stdin))
- b = TRUE;
- else
- break;
- }
-
- if (ISFROM(buf))
- (void) fputc('>', dfp[T_BODY]);
- (void) fputs(buf, dfp[T_BODY]);
-
- empty_line = (buf[0] == '\n');
-
- /*
- * Output the rest of a very long line.
- * We do this here, instead of going around the loop,
- * in order to avoid misinterpreting From_ strings
- * that may be found in long lines.
- */
-
- while (!strchr(buf, '\n')
- && !feof(stdin)
- && !ferror(stdin)
- && fgets(buf, GETSIZE(buf), stdin))
- (void) fputs(buf, dfp[T_BODY]);
- }
-
- /* Ensure that the body ends with a blank line. */
-
- if (! empty_line)
- (void) fputc('\n', dfp[T_BODY]);
-
- /*
- * If we encountered any trouble writing to the temp files,
- * let's not keep it secret.
- */
-
- for (t = T_HDR; t <= T_BODY; ++t)
- {
- if (ferror(dfp[t]))
- {
- error("error writing to %s file %s\n",
- ttype[t], tfile[t]);
- ret = -1;
- }
-
- (void) fclose(dfp[t]);
- }
-
- /* Return error/success. */
-
- return ret;
- }
-
- /*----------------------------------------------------------------------
- * Don't bother copying message.
- * Put the original names in the environment.
- */
-
- int
- dont_copy()
- {
- int r, t;
-
- for (r = T_HDR, t = T_HDRCOPY; r <= T_BODY; ++r, ++t)
- {
- if (tenv[t] && tfile[r])
- alloc_env(tenv[t], tfile[r]);
- }
-
- if (verbose)
- {
- message("dont_copy: header is %s, body is %s\n",
- tfile[T_HDR], tfile[T_BODY]);
- }
-
- return 0;
- }
-
- /*----------------------------------------------------------------------
- * Create another copy of each temp file, for security reasons.
- * Also, put the names of the copies in the environment.
- */
-
- int
- copy_again()
- {
- int r, t;
-
- for (r = T_HDR, t = T_HDRCOPY; r <= T_BODY; ++r, ++t)
- {
- /*
- * If the file exists, remove it but keep its name.
- * Otherwise, make a new name and put that name in
- * the environment.
- */
-
- if (tfile[t])
- (void) unlink(tfile[t]);
- else
- {
- tfile[t] = tempfile();
- if (tenv[t])
- alloc_env(tenv[t], tfile[t]);
- }
-
- /*
- * Create the file and copy the contents of the
- * original file to it.
- */
-
- if (tfd[t] != -1)
- (void) close(tfd[t]);
-
- if ((tfd[t] = tcreate(tfile[t])) == -1)
- return -1;
-
- (void) lseek(tfd[r], 0L, 0);
- if (copyfd(tfd[r], tfd[t]) < 0)
- return -1;
- }
-
- if (verbose)
- {
- message("copy_again: header to %s, body to %s\n",
- tfile[T_HDRCOPY], tfile[T_BODYCOPY]);
- }
-
- return 0;
- }
-
- /*----------------------------------------------------------------------
- * Copy a file via file descriptors.
- */
-
- int
- copyfd(src_fd, dest_fd)
- int src_fd;
- int dest_fd;
- {
- char buf[BUFSIZ];
- int rd, wr;
-
- while ((rd = read(src_fd, buf, sizeof(buf))) > 0)
- {
- if ((wr = write(dest_fd, buf, (unsigned) rd)) != rd)
- {
- if (wr == -1)
- syserr("can't write in copyfd");
- else
- error("write error -- disk full?\n");
- return -1;
- }
- }
-
- return 0;
- }
-
-