home *** CD-ROM | disk | FTP | other *** search
- /* $Header: copymsg.c,v 1.1 88/06/06 09:38:13 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 1.1 88/06/06 09:38:13 chip
- * Initial revision
- *
- */
-
- #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] == ' ')
-
- /*
- * Local functions.
- */
-
- static char *tempfile();
- static int tcreate();
-
- /*----------------------------------------------------------------------
- * 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, *fsender, *fremote, *osender, *oremote;
- long now;
- int t, b, empty_line;
- int ret = 0;
-
- /*
- * Create temporary files to hold the header and message body.
- */
-
- for (t = 0; t < T_MAX; ++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_HEADER], tfile[T_BODY]);
- }
-
- /*
- * If there is a From_ line, find the sender name therein.
- */
-
- fsender = fremote = NULL;
-
- b = (fgets(buf, GETSIZE(buf), stdin) ? TRUE : FALSE);
-
- if (b && ISFROM(buf) && (p = strchr(buf, '\n')) != NULL)
- {
- b = FALSE; /* Don't output two From_ lines */
- *p = 0;
-
- /* Find sender */
-
- for (fsender = buf + 5; isspace(*fsender); ++fsender)
- ; /* until sender */
- for (p = fsender; *p && !isspace(*p); ++p)
- ; /* until end of sender */
- if (*p)
- *p++ = '\0';
-
- /* Find 'remote from' phrase (if any) */
-
- for (fremote = p;
- (fremote = strchr(fremote, 'r')) != NULL;
- ++fremote)
- {
- if (strncmp(fremote, "remote from", 11) == 0)
- {
- fremote += 11;
- while (isspace(*fremote))
- ++fremote;
- break;
- }
- }
- }
-
- /*
- * Write a From_ line to the header file.
- * If the user specified a sender name, use it;
- * else if we found a From_ line, use the sender found therein;
- * else use the user name of our real UID.
- */
-
- if (sender && *sender)
- {
- osender = sender;
- oremote = NULL;
- }
- else if (fsender)
- {
- osender = fsender;
- oremote = fremote;
- }
- else
- {
- osender = real_ct->name;
- oremote = NULL;
- }
-
- (void) fputs("From ", dfp[T_HEADER]);
- if (oremote)
- {
- (void) fputs(oremote, dfp[T_HEADER]);
- (void) fputc('!', dfp[T_HEADER]);
- }
- (void) fputs(osender, dfp[T_HEADER]);
- (void) fputc(' ', dfp[T_HEADER]);
- (void) time(&now);
- (void) fputs(ctime(&now), dfp[T_HEADER]);
-
- /*
- * Copy the rest of the header (if any).
- */
-
- for (; !feof(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_HEADER]);
- 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_HEADER]);
- }
-
- /*
- * 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_HEADER]);
-
- /*
- * Copy the body (if any).
- */
-
- empty_line = FALSE;
- for (; !feof(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)
- && 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 = 0; t < T_MAX; ++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;
- }
-
- /*----------------------------------------------------------------------
- * Return a pointer to a temporary filename, or NULL if error.
- */
-
- static char *
- tempfile()
- {
- static char template[] = "/tmp/dl.XXXXXX";
- char *f;
-
- f = zalloc(32);
- (void) strcpy(f, template);
- if (mktemp(f) == NULL)
- {
- error("can't create temporary file");
- return NULL;
- }
- return f;
- }
-
- /*----------------------------------------------------------------------
- * Create a file, or complain if it doesn't work.
- */
-
- static int
- tcreate(name)
- char *name;
- {
- int fd;
-
- if ((fd = open(name, O_RDWR|O_CREAT|O_EXCL, 0600)) == -1)
- {
- syserr("can't create %s", name);
- return -1;
- }
-
- return fd;
- }
-
-