home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume16 / deliver / part02 / copymsg.c < prev    next >
C/C++ Source or Header  |  1988-11-14  |  6KB  |  315 lines

  1. /* $Header: copymsg.c,v 1.1 88/06/06 09:38:13 chip Exp $
  2.  *
  3.  * Take the message from standard input and write it to two temp files,
  4.  * one for the header (including the empty line) and one for the body.
  5.  *
  6.  * $Log:    copymsg.c,v $
  7.  * Revision 1.1  88/06/06  09:38:13  chip
  8.  * Initial revision
  9.  * 
  10.  */
  11.  
  12. #include "deliver.h"
  13.  
  14. /*
  15.  * Macros.
  16.  */
  17.  
  18. /* Does a string start with "From "? */
  19.  
  20. #define ISFROM(p) ((p)[0] == 'F' && (p)[1] == 'r' && (p)[2] == 'o' \
  21.         && (p)[3] == 'm' && (p)[4] == ' ')
  22.  
  23. /*
  24.  * Local functions.
  25.  */
  26.  
  27. static  char    *tempfile();
  28. static  int     tcreate();
  29.  
  30. /*----------------------------------------------------------------------
  31.  * Copy the message on the standard input to two temp files:
  32.  * one for the header and one for the body.
  33.  */
  34.  
  35. int
  36. copy_message()
  37. {
  38.     char    buf[BUFSIZ];
  39.     FILE    *dfp[T_MAX];
  40.     char    *p, *fsender, *fremote, *osender, *oremote;
  41.     long    now;
  42.     int     t, b, empty_line;
  43.     int     ret = 0;
  44.  
  45.     /*
  46.      * Create temporary files to hold the header and message body.
  47.      */
  48.  
  49.     for (t = 0; t < T_MAX; ++t)
  50.     {
  51.         int     fd;
  52.  
  53.         tfile[t] = tempfile();
  54.         if ((tfd[t] = tcreate(tfile[t])) == -1)
  55.             return -1;
  56.  
  57.         if ((fd = dup(tfd[t])) == -1)
  58.         {
  59.             syserr("dup %s fd", ttype[t]);
  60.             return -1;
  61.         }
  62.         (void) lseek(fd, 0L, 0);
  63.         if ((dfp[t] = fdopen(fd, "r+")) == NULL)
  64.         {
  65.             error("can't fdopen %s fd", ttype[t]);
  66.             return -1;
  67.         }
  68.     }
  69.  
  70.     /* Debugging message for later examination of temp files. */
  71.  
  72.     if (verbose)
  73.     {
  74.         message("header=%s, body=%s\n",
  75.             tfile[T_HEADER], tfile[T_BODY]);
  76.     }
  77.  
  78.     /*
  79.      * If there is a From_ line, find the sender name therein.
  80.      */
  81.  
  82.     fsender = fremote = NULL;
  83.  
  84.     b = (fgets(buf, GETSIZE(buf), stdin) ? TRUE : FALSE);
  85.  
  86.     if (b && ISFROM(buf) && (p = strchr(buf, '\n')) != NULL)
  87.     {
  88.         b = FALSE;      /* Don't output two From_ lines */
  89.         *p = 0;
  90.  
  91.         /* Find sender */
  92.  
  93.         for (fsender = buf + 5; isspace(*fsender); ++fsender)
  94.             ; /* until sender */
  95.         for (p = fsender; *p && !isspace(*p); ++p)
  96.             ; /* until end of sender */
  97.         if (*p)
  98.             *p++ = '\0';
  99.  
  100.         /* Find 'remote from' phrase (if any) */
  101.  
  102.         for (fremote = p;
  103.              (fremote = strchr(fremote, 'r')) != NULL;
  104.              ++fremote)
  105.         {
  106.             if (strncmp(fremote, "remote from", 11) == 0)
  107.             {
  108.                 fremote += 11;
  109.                 while (isspace(*fremote))
  110.                     ++fremote;
  111.                 break;
  112.             }
  113.         }
  114.     }
  115.  
  116.     /*
  117.      * Write a From_ line to the header file.
  118.      * If the user specified a sender name, use it;
  119.      * else if we found a From_ line, use the sender found therein;
  120.      * else use the user name of our real UID.
  121.      */
  122.  
  123.     if (sender && *sender)
  124.     {
  125.         osender = sender;
  126.         oremote = NULL;
  127.     }
  128.     else if (fsender)
  129.     {
  130.         osender = fsender;
  131.         oremote = fremote;
  132.     }
  133.     else
  134.     {
  135.         osender = real_ct->name;
  136.         oremote = NULL;
  137.     }
  138.  
  139.     (void) fputs("From ", dfp[T_HEADER]);
  140.     if (oremote)
  141.     {
  142.         (void) fputs(oremote, dfp[T_HEADER]);
  143.         (void) fputc('!', dfp[T_HEADER]);
  144.     }
  145.     (void) fputs(osender, dfp[T_HEADER]);
  146.     (void) fputc(' ', dfp[T_HEADER]);
  147.     (void) time(&now);
  148.     (void) fputs(ctime(&now), dfp[T_HEADER]);
  149.  
  150.     /*
  151.      * Copy the rest of the header (if any).
  152.      */
  153.  
  154.     for (; !feof(stdin); b = FALSE)
  155.     {
  156.         if (!b)
  157.         {
  158.             if (fgets(buf, GETSIZE(buf), stdin))
  159.                 b = TRUE;
  160.             else
  161.                 break;
  162.         }
  163.  
  164.         /* Empty line means "end of header" */
  165.  
  166.         if (buf[0] == '\n')
  167.         {
  168.             b = FALSE;    /* Don't put this line in the body. */
  169.             break;
  170.         }
  171.  
  172.         /*
  173.          * A line too long to fit in buf[] can't be a header line.
  174.          * At least, that's my opinion... :-)
  175.          */
  176.  
  177.         if (!strchr(buf, '\n'))
  178.             break;
  179.  
  180.         /*
  181.          * If line begins with whitespace, it's a continuation.
  182.          * Else if line begins with From_ or '>', prepend '>'.
  183.          * Else if line doesn't look like a header, this must
  184.          * be the beginning of the body.
  185.          */
  186.  
  187.         if (isspace(buf[0]))
  188.             ;               /* continuation */
  189.         else if (ISFROM(buf) || (buf[0] == '>'))
  190.             (void) fputc('>', dfp[T_HEADER]);
  191.         else
  192.         {
  193.             /* look for the colon on a header label */
  194.  
  195.             p = buf;
  196.             while (isalpha(*p) || *p == '-')
  197.                 ++p;
  198.             if ((p == buf) || (*p != ':'))
  199.                 break;  /* Not a header line! */
  200.         }
  201.  
  202.         /* Write the line to the header file. */
  203.  
  204.         (void) fputs(buf, dfp[T_HEADER]);
  205.     }
  206.  
  207.     /*
  208.      * End the header file with a blank line.
  209.      * This enables us to simply concatenate it with the body file
  210.      * to produce a valid message.
  211.      */
  212.  
  213.     (void) fputc('\n', dfp[T_HEADER]);
  214.  
  215.     /*
  216.      * Copy the body (if any).
  217.      */
  218.  
  219.     empty_line = FALSE;
  220.     for (; !feof(stdin); b = FALSE)
  221.     {
  222.         if (!b)
  223.         {
  224.             if (fgets(buf, GETSIZE(buf), stdin))
  225.                 b = TRUE;
  226.             else
  227.                 break;
  228.         }
  229.  
  230.         if (ISFROM(buf))
  231.             (void) fputc('>', dfp[T_BODY]);
  232.         (void) fputs(buf, dfp[T_BODY]);
  233.  
  234.         empty_line = (buf[0] == '\n');
  235.  
  236.         /*
  237.          * Output the rest of a very long line.
  238.          * We do this here, instead of going around the loop,
  239.          * in order to avoid misinterpreting From_ strings
  240.          * that may be found in long lines.
  241.          */
  242.  
  243.         while (!strchr(buf, '\n')
  244.             && !feof(stdin)
  245.             && fgets(buf, GETSIZE(buf), stdin))
  246.             (void) fputs(buf, dfp[T_BODY]);
  247.     }
  248.  
  249.     /* Ensure that the body ends with a blank line. */
  250.  
  251.     if (! empty_line)
  252.         (void) fputc('\n', dfp[T_BODY]);
  253.  
  254.     /*
  255.      * If we encountered any trouble writing to the temp files,
  256.      * let's not keep it secret.
  257.      */
  258.  
  259.     for (t = 0; t < T_MAX; ++t)
  260.     {
  261.         if (ferror(dfp[t]))
  262.         {
  263.             error("error writing to %s file %s\n",
  264.                 ttype[t], tfile[t]);
  265.             ret = -1;
  266.         }
  267.  
  268.         (void) fclose(dfp[t]);
  269.     }
  270.  
  271.     /* Return error/success. */
  272.  
  273.     return ret;
  274. }
  275.  
  276. /*----------------------------------------------------------------------
  277.  * Return a pointer to a temporary filename, or NULL if error.
  278.  */
  279.  
  280. static char *
  281. tempfile()
  282. {
  283.     static char template[] = "/tmp/dl.XXXXXX";
  284.     char    *f;
  285.  
  286.     f = zalloc(32);
  287.     (void) strcpy(f, template);
  288.     if (mktemp(f) == NULL)
  289.     {
  290.         error("can't create temporary file");
  291.         return NULL;
  292.     }
  293.     return f;
  294. }
  295.  
  296. /*----------------------------------------------------------------------
  297.  * Create a file, or complain if it doesn't work.
  298.  */
  299.  
  300. static int
  301. tcreate(name)
  302. char    *name;
  303. {
  304.     int     fd;
  305.  
  306.     if ((fd = open(name, O_RDWR|O_CREAT|O_EXCL, 0600)) == -1)
  307.     {
  308.         syserr("can't create %s", name);
  309.         return -1;
  310.     }
  311.  
  312.     return fd;
  313. }
  314.  
  315.