home *** CD-ROM | disk | FTP | other *** search
/ back2roots/padua / padua.7z / padua / uucp / uucp_mods.lha.30.12.93 / uucp_mods / sendmail / sendmail.c
Encoding:
C/C++ Source or Header  |  1993-12-02  |  32.3 KB  |  1,433 lines

  1.  
  2. /*
  3.  *  SENDMAIL / RMAIL
  4.  *
  5.  *  (C) Copyright 1989-1990 by Matthew Dillon,  All Rights Reserved.
  6.  *  Domain-Path Enhancement by Henning Schmiedehausen. This is PD.
  7.  *
  8.  *  SENDMAIL <file -f from -t to -s subject -c cc -b bcc -r
  9.  *  RMAIL user
  10.  *
  11.  *  Example:    Sendmail <datafile -froot
  12.  *
  13.  *  From: line is automatically added but can be overriden by a From:
  14.  *  header in the file.  stdin is made up of a list of headers, a blank
  15.  *  line, and then data until EOF.
  16.  *
  17.  *  the -r option tells sendmail that this is incomming mail.
  18.  *  If av[0] begins with an 'r' for RMail instead of an 's' for
  19.  *  Sendmail, then the rmail argument format is used (rmail user),
  20.  *  as well as forcing -r.
  21.  *
  22.  *  Hierarchical Spool Conversion 1 Dec 93,
  23.  *                      Mike J. Bruins bruins@hal9000.apana.org.au
  24.  */
  25.  
  26. #include "defs.h"
  27.  
  28. #include <fcntl.h>
  29. #include <log.h>
  30. #include <time.h>
  31. #include <pwd.h>
  32. #include <config.h>
  33. #include <version.h>
  34. #include <owndevunit.h>
  35.  
  36. IDENT(".19");
  37.  
  38. Prototype char *DefaultNode;
  39. Prototype char *NodeName;
  40. Prototype char *DomainPath;
  41. Prototype char ROpt;
  42. Prototype char BounceOpt;
  43.  
  44. Local    void Usage(void);
  45. Local    int brk(void);
  46. Local    void myexit(void);
  47. Local    NODE *MakeNode(LIST *, char *);
  48. Local    void MakeToFixNode(LIST *, char *, char *);
  49. Local    void fixCallBack(char *, LIST *, int);
  50. Local    void IntegrateHeader(char *, short);
  51. Local    void FromFixup(LIST *);
  52. Local    void ToFixup(LIST *);
  53. Local    void MakeToAddrNode(LIST *, char *);
  54. Local    FILE *TermMailToUUCP(FILE *);
  55. Local    FILE *SendMailTo(LIST *, FILE *);
  56. Local    FILE *OneMailTo(char *, FILE *, short);
  57. Local    FILE *OneMailToPipe(char *, FILE *);
  58. Local    FILE *OneMailToUser(char *, FILE *);
  59. Local    FILE *OneMailToFile(char *, FILE *);
  60. Local    FILE *OneMailToUUCP(char *, char *, FILE *);
  61. Local    void DumpHeaderInfo(FILE *, int, int, int, char *);
  62. Local    void DumpHeader(FILE *, char *, LIST *, char *);
  63. Local    char *FindHeader(char *);
  64. Local    void DumpCombineHeader(FILE *, char *, LIST *, char *);
  65. Local    char *atime(time_t *);
  66. Local    int GetHourOffset(char *);
  67. Local    void PostPend(char *, int);
  68. Local    int EmptyList(LIST *);
  69.  
  70.  
  71. #define RCVR_UUCP    1
  72. #define RCVR_SENDMAIL    2
  73.  
  74. char    *UserName;
  75. char    *RealName;
  76. char    *NodeName;
  77. char    *DomainPath = "";
  78. char    CutNodeName[8];
  79. char    *DomainName;
  80. char    *TimeZoneName;    /*  All caps, ex: PST             */
  81. char    *DefaultNode;    /*  for addr formats we don't understand */
  82. LIST    RecvList;    /*  Received:        */
  83. LIST    FromList;    /*  last one rules  */
  84. LIST    ToList;     /*  To:         */
  85. LIST    CcList;     /*  Cc:         */
  86. LIST    BccList;    /*  Bcc:        */
  87. LIST    XccList;    /*  list of actual mail to be sent  */
  88. LIST    SubjList;    /*  Subject:        */
  89. LIST    HdrList;    /*  other headers not specifically parsed   */
  90. LIST    UUHostList;    /*  tracking mail sent to a given UUCP host */
  91.  
  92. char    DiagnosticMessage[128];
  93. char    ScrBuf[1024];
  94. char    ScrBuf2[1024];
  95. char    TempFileBuf[256];
  96. int    Seq;        /*  UUCP sequence no    */
  97. int    TopSeq;     /*  Top sequence no for Message-Id: */
  98. char    Notify;
  99. char    ROpt;        /*  RMAIL flag        */
  100. char    BounceOpt;
  101. char    ForceNoBounce;
  102. char    NoHdrOpt;    /*  ignore headers opt    */
  103. static char OrigFromLine[512];
  104. static char FromLine[512];  /*    'From ' line, if ROpt   */
  105.  
  106. int _bufsiz = 4096;    /*  for stdio        */
  107. time_t T;        /*  current time    */
  108. struct Library *OwnDevUnitBase;
  109.  
  110. main(ac, av)
  111. char *av[];
  112. {
  113.     short isRMail = 0;
  114.     short isSendMail = 1;
  115.     FILE *fi;
  116.  
  117.     onbreak(brk);
  118.  
  119.     NewList(&RecvList);
  120.     NewList(&FromList);
  121.     NewList(&ToList);
  122.     NewList(&CcList);
  123.     NewList(&BccList);
  124.     NewList(&XccList);
  125.     NewList(&SubjList);
  126.     NewList(&HdrList);
  127.     NewList(&UUHostList);
  128.  
  129.     atexit(myexit);
  130.     if ((OwnDevUnitBase = OpenLibrary(ODU_NAME, 0)) == NULL) {
  131.     printf("Unable to open %s\n", ODU_NAME);
  132.     exit(20);
  133.     }
  134.  
  135.     UserName = GetUserName();
  136.     RealName = GetRealName();
  137.  
  138.     T = time(NULL);
  139.     TopSeq = GetSequence(1);
  140.  
  141.     if (UserName == NULL) {
  142.     puts("Sendmail: UserName config entry not found!");
  143.     ulog(0, "UserName config missing");
  144.     exit(1);
  145.     }
  146.     if (RealName == NULL) {
  147.     puts("Sendmail: RealName config entry not found!");
  148.     ulog(0, "RealName config missing");
  149.     exit(1);
  150.     }
  151.  
  152.     NodeName = FindConfig("NodeName");
  153.     {
  154.     char *ptr = GetConfig(MAILBOUNCE, "0");
  155.     if (*ptr == '1' || *ptr == 'y' || *ptr == 'Y')
  156.         BounceOpt = 1;
  157.     }
  158.     strncpy(CutNodeName, NodeName, 7);
  159.     if (NodeName == NULL) {
  160.     puts("Sendmail: NodeName config entry not found!");
  161.     ulog(0, "NodeName config missing");
  162.     exit(1);
  163.     }
  164.     DomainName = FindConfig("DomainName");
  165.     if (DomainName == NULL) {
  166.     puts("Sendmail: DomainName config entry not found! using .UUCP");
  167.     DomainName = ".uucp";
  168.     }
  169.     {
  170.     char *str = GetConfig(DOMAINPATH, "N");
  171.     if (str[0] == 'y' || str[0] == 'Y' || str[0] == '1')
  172.         DomainPath = DomainName;
  173.     }
  174.     DefaultNode = FindConfig(DEFAULTNODE);
  175.     TimeZoneName = FindConfig("TimeZone");
  176.  
  177.     LoadAliases();
  178.  
  179.     {
  180.     char *ptr = av[0] + strlen(av[0]);
  181.  
  182.     /*
  183.      *  Skip path
  184.      */
  185.  
  186.     while (ptr >= av[0] && *ptr != ':' && *ptr != '/')
  187.         --ptr;
  188.     ++ptr;
  189.  
  190.     if (*ptr == 'r' || *ptr == 'R') {
  191.         isRMail = 1;
  192.         isSendMail = 0;
  193.     }
  194.     }
  195.  
  196.     if (isRMail) {
  197.     if (ac <= 1) {
  198.         MakeNode(&BccList, "Mailer-Daemon");
  199.     } else {
  200.         short i;
  201.         for(i = 1; i < ac; ++i)
  202.         MakeNode(&BccList, av[i]);
  203.     }
  204.     UserName = "postmaster";    /*  XXX  */
  205.     RealName = "Mr.Amiga";      /*  XXX  */
  206.     ROpt = 1;            /*    no header processing */
  207.     }
  208.  
  209.     if (isSendMail) {
  210.     short i;
  211.     char *arg;
  212.     for (i = 1; i < ac; ++i) {
  213.         arg = av[i];
  214.         if (*arg != '-')
  215.         Usage();
  216.         arg += 2;
  217.         switch(arg[-1]) {
  218.         case 'f':
  219.         UserName = av[i+1];
  220.         sprintf(ScrBuf, "%s@%s%s", UserName, NodeName, DomainName);
  221.         MakeNode(&FromList, ScrBuf);
  222.         ++i;
  223.         break;
  224.         case 'R':
  225.         RealName = av[++i];
  226.         break;
  227.         case 't':
  228.         MakeNode(&ToList, av[++i]);
  229.         break;
  230.         case 'c':
  231.         MakeNode(&CcList, av[++i]);
  232.         break;
  233.         case 'b':
  234.         MakeNode(&BccList, av[++i]);
  235.         break;
  236.         case 's':
  237.         MakeNode(&SubjList, av[++i]);
  238.         break;
  239.         case 'r':
  240.         if (strcmp(arg, "aw") == 0)
  241.             NoHdrOpt = 1;
  242.         else
  243.             ++ROpt;
  244.         break;
  245.         default:
  246.         Usage();
  247.         }
  248.     }
  249.     }
  250.  
  251.     /*
  252.      *    Read headers from input file.  Headers are not necessarily
  253.      *    contained on a single line.  Maximum 4096 chars per header.
  254.      */
  255.  
  256.     if (ROpt) {
  257.     fgets(ScrBuf, sizeof(ScrBuf), stdin);
  258.     strcpy(OrigFromLine, ScrBuf);
  259.     if (strncmp(ScrBuf, "From ", 5) != 0) {
  260.         ulog(-1, "Receive mail, expected 'From ', got %s", ScrBuf);
  261.     }
  262.     strcpy(FromLine, "From ");
  263.     PostPend(ScrBuf + 5, 1);
  264.  
  265.     while (fgets(ScrBuf, sizeof(ScrBuf), stdin) && strncmp(ScrBuf, ">From ", 6) == 0) {
  266.         strcpy(OrigFromLine, ScrBuf + 1);
  267.         PostPend(ScrBuf + 6, 1);
  268.     }
  269.     strcpy(ScrBuf2, OrigFromLine + 5);
  270.     PostPend(ScrBuf2, 0);
  271.     } else {
  272.     ScrBuf[0] = '\n';
  273.     if (NoHdrOpt == 0)
  274.         fgets(ScrBuf, sizeof(ScrBuf), stdin);
  275.     }
  276.     if (NoHdrOpt == 0) {
  277.     static char Hdr[4096];
  278.     short i = 0;        /*  index into Hdr  */
  279.  
  280.     while (ScrBuf[0] != '\n') {
  281.         char *ptr = ScrBuf;
  282.         while (*ptr && *ptr != ' ' && *ptr != '\t' && *ptr != ':')
  283.         ++ptr;
  284.         if (*ptr == ':') {  /*  found new header */
  285.         if (i)          /*  Dump old header  */
  286.             IntegrateHeader(Hdr, i);
  287.         strcpy(Hdr, ScrBuf);
  288.         i = strlen(Hdr);
  289.         } else {        /*  append to existing header    */
  290.         if (i == 0)
  291.             puts("Expected a Header!");
  292.         strcpy(Hdr + i, ScrBuf);
  293.         i = i + strlen(Hdr + i);
  294.         }
  295.  
  296.         if (fgets(ScrBuf, sizeof(ScrBuf), stdin) == NULL)
  297.         ScrBuf[0] = '\n';
  298.     }
  299.     if (i)
  300.         IntegrateHeader(Hdr, i);
  301.  
  302.     if (ScrBuf[0] != '\n') {
  303.         puts("sendmail: no mail");
  304.         ulog(0, "No Mail");
  305.         exit(1);
  306.     }
  307.     }
  308.  
  309.     /*
  310.      *    Parse & fixup each To:, Cc:, and Bcc: field.
  311.      *
  312.      *    From:    we add the personal info arg from the password file
  313.      *    To:    we expand any aliases
  314.      *
  315.      *    OpenLog() : log optimization
  316.      */
  317.  
  318.     OpenLog();
  319.     if (ROpt == 0)
  320.     FromFixup(&FromList);
  321.     if (ROpt) {
  322.     ToFixup(&BccList);
  323.     } else {
  324.     ToFixup(&ToList);
  325.     ToFixup(&CcList);
  326.     ToFixup(&BccList);
  327.     }
  328.     CloseLog();
  329.  
  330.     /*
  331.      *    If no Subject: field add a dummy one
  332.      */
  333.  
  334.     if (EmptyList(&SubjList))
  335.     MakeNode(&SubjList, "");
  336.  
  337.     if (EmptyList(&FromList)) {
  338.     sprintf(ScrBuf, "%s@%s%s", UserName, NodeName, DomainName);
  339.     MakeNode(&FromList, ScrBuf);
  340.     }
  341.  
  342.     fi = SendMailTo(&XccList, stdin);
  343.     if (fi && fi != stdin)
  344.     fclose(fi);
  345.     if (TempFileBuf[0])
  346.     remove(TempFileBuf);
  347.     UnLockFiles();
  348.  
  349.     /*
  350.      *    Notify if T:MailRdy does not exist (created by us, deleted by
  351.      *    notify when notify exits).  Prevents running multiple notifies.
  352.      */
  353.  
  354.     if (Notify) {
  355.     int fd = open("T:MailRdy", O_RDONLY);
  356.     if (fd < 0) {
  357.         char *cmd;
  358.  
  359.  
  360.         if (cmd = FindConfig(MAILREADYCMD)) {
  361.         fd = open("T:MailRdy", O_CREAT|O_TRUNC, 0666);
  362.         if (fd >= 0)
  363.             close(fd);
  364.         sprintf(ScrBuf, "Run %s -x T:MailRdy", cmd);
  365.         Execute(ScrBuf, NULL, NULL);
  366.         }
  367.     } else {
  368.         close(fd);
  369.     }
  370.  
  371.     /*
  372.      *  signal for update for any utilities that support it.
  373.      */
  374.     {
  375.         MsgPort *port;
  376.         Forbid();
  377.         if ((port = FindPort("T:MailRdy")) && port->mp_SigTask)
  378.         Signal(port->mp_SigTask, 1 << port->mp_SigBit);
  379.         Permit();
  380.     }
  381.     }
  382.     return(0);
  383. }
  384.  
  385. void
  386. myexit()
  387. {
  388.     UnLockFiles();
  389.  
  390.     if (OwnDevUnitBase) {
  391.     CloseLibrary(OwnDevUnitBase);
  392.     OwnDevUnitBase = NULL;
  393.     }
  394. }
  395.  
  396. void
  397. Usage()
  398. {
  399.     printf(
  400.     "Sendmail -f user [-t address -c address -b address -s subject -r]\n"
  401.     "RMail user\n"
  402.     );
  403. }
  404.  
  405. int
  406. brk()
  407. {
  408.     UnLockFiles();
  409.     return(0);
  410. }
  411.  
  412. /*
  413.  *  Strips string and creates named node which is appended to the
  414.  *  given list.
  415.  */
  416.  
  417. NODE *
  418. MakeNode(list, str)
  419. LIST *list;
  420. char *str;
  421. {
  422.     NODE *node;
  423.     char *ptr;
  424.  
  425.     while (*str == ' ' || *str == '\t')
  426.     ++str;
  427.     for (ptr = str + strlen(str) - 1; ptr >= str && (*ptr == ' ' || *ptr == '\t'); --ptr);
  428.     ++ptr;
  429.     *ptr = 0;
  430.     node = malloc(sizeof(NODE) + strlen(str) + 1);
  431.     node->ln_Pri = 0;
  432.     node->ln_Name = (char *)(node + 1);
  433.     strcpy(node->ln_Name, str);
  434.     AddTail(list, node);
  435.     return(node);
  436. }
  437.  
  438. /*
  439.  *  Ultimate to field , handles basic user security and expands aliases.
  440.  */
  441.  
  442. void
  443. MakeToFixNode(list, str, send)
  444. LIST *list;
  445. char *str;
  446. char *send;
  447. {
  448.     char *ptr;
  449.     short len;
  450.     short c;
  451.  
  452.     while (str < send && (*str == ' ' || *str == '\t'))
  453.     ++str;
  454.     for (ptr = send - 1; ptr >= str && (*ptr == ' ' || *ptr == '\t'); --ptr);
  455.     ++ptr;
  456.  
  457.     len = ptr - str;
  458.     if (len < 0)
  459.     return;
  460.  
  461.     /*
  462.      *    str[0..len-1]
  463.      */
  464.  
  465.     c = str[len];
  466.     str[len] = 0;
  467.  
  468.     if (ROpt) {     /*  disallow remote asking for special options */
  469.     ulog(-1, "Received mail for %s", str);
  470.     if (str[0] == '>' || str[0] == '<' || str[0] == '|' || strchr(str, '/') || strchr(str, ':')) {
  471.         ulog(-1, "SendMail, bad user %s", str);
  472.         return;
  473.     }
  474.     }
  475.  
  476.     /*
  477.      *    expand aliases.  If the str exists as an alias and the special
  478.      *    :: (do not expand alias in To: field) is used, then the name of
  479.      *    the alias is placed in the To: field.
  480.      */
  481.  
  482.     if (AliasExists(str))
  483.     ForceNoBounce = 1;
  484.     if (UserAliasList(str, fixCallBack, (long)list, 1)) {
  485.     NODE *node;
  486.  
  487.     sprintf(ScrBuf, "%s@%s%s", str, NodeName, DomainName);
  488.  
  489.     node = malloc(sizeof(NODE) + strlen(ScrBuf) + 1);
  490.     node->ln_Pri = 0;
  491.     node->ln_Name = (char *)(node + 1);
  492.     strcpy(node->ln_Name, ScrBuf);
  493.     AddTail(list, node);
  494.     }
  495.     ForceNoBounce = 0;
  496.     str[len] = c;
  497. }
  498.  
  499. void
  500. fixCallBack(user, list, showto)
  501. char *user;
  502. LIST *list;
  503. int showto;
  504. {
  505.     NODE    *node;
  506.  
  507.     if (user[0] == '<') {
  508.     FILE *fi = fopen(user + 1, "r");
  509.     char *buf = malloc(256);
  510.  
  511.     if (fi == NULL) {
  512.         ulog(-1, "Unable to open < file %s", user + 1);
  513.         return;
  514.     }
  515.     while (fgets(buf, 256, fi)) {
  516.         short i = 0;
  517.         short j;
  518.         while (buf[i] == ' ' || buf[i] == '\t')
  519.         ++i;
  520.         if (buf[i] == 0 || buf[i] == '\n')
  521.         continue;
  522.         for (j = i; buf[j] && buf[j] != '\n' && buf[j] != ' ' && buf[j] != '\t'; ++j);
  523.         buf[j] = 0;
  524.         UserAliasList(buf, fixCallBack, (long)list, showto);
  525.     }
  526.     fclose(fi);
  527.     free(buf);
  528.     return;
  529.     }
  530.  
  531.     if (showto)
  532.     ulog(-1, "Sendmail, Sending mail to %s", user);
  533.  
  534.     if (user[0] == '\\')
  535.     ++user;
  536.  
  537.     /*
  538.      *    add to Xcc (actual send list).  If showto < 0 then the alias was
  539.      *    given to us for display (To: field display) purposes only and
  540.      *    should NOT be added to the Xcc list
  541.      */
  542.  
  543.     if (showto >= 0) {
  544.     node = malloc(sizeof(NODE) + strlen(user) + 1);
  545.     node->ln_Name = (char *)(node + 1);
  546.     node->ln_Pri = ForceNoBounce;
  547.     strcpy(node->ln_Name, user);
  548.     AddTail(&XccList, node);
  549.     }
  550.  
  551.     /*
  552.      *    If an alias element is to be shown in the To: field of the
  553.      *    message, do so.  If it is a local user with no qualifications,
  554.      *    then append our full domain name.
  555.      *
  556.      *    do not show any > or | redirections
  557.      */
  558.  
  559.     if (showto && *user != '|' && *user != '>') {
  560.     short localFix = 1;
  561.     {
  562.         char *ptr;
  563.         for (ptr = user; *ptr; ++ptr) {
  564.         if (*ptr == '!' || *ptr == '@' || *ptr == '%' || *ptr == ':') {
  565.             localFix = 0;
  566.             break;
  567.         }
  568.         }
  569.     }
  570.     if (localFix)
  571.         sprintf(ScrBuf, "%s@%s%s", user, NodeName, DomainName);
  572.     else
  573.         strcpy(ScrBuf, user);
  574.  
  575.     node = malloc(sizeof(NODE) + strlen(ScrBuf) + 1);
  576.     node->ln_Pri = 0;
  577.     node->ln_Name = (char *)(node + 1);
  578.     strcpy(node->ln_Name, ScrBuf);
  579.     AddTail(list, node);
  580.     }
  581. }
  582.  
  583. /*
  584.  *  Integrates a header
  585.  */
  586.  
  587. void
  588. IntegrateHeader(hdr, len)
  589. char *hdr;
  590. short len;
  591. {
  592.     if (hdr[len-1] == '\n')     /*  strip trailing newline  */
  593.     hdr[len-1] = 0;
  594.  
  595.     if (strncmp(hdr, "From:", 5) == 0) {
  596.     MakeNode(&FromList, hdr + 5);
  597.     return;
  598.     }
  599.     if (strncmp(hdr, "To:", 3) == 0) {
  600.     MakeNode(&ToList, hdr + 3);
  601.     return;
  602.     }
  603.     if (strncmp(hdr, "Cc:", 3) == 0) {
  604.     MakeNode(&CcList, hdr + 3);
  605.     return;
  606.     }
  607.     if (strncmp(hdr, "Bcc:", 4) == 0) {
  608.     MakeNode(&BccList, hdr + 4);
  609.     return;
  610.     }
  611.     if (strncmp(hdr, "Subject:", 8) == 0) {
  612.     MakeNode(&SubjList, hdr + 8);
  613.     return;
  614.     }
  615.     if (strncmp(hdr, "Received:", 9) == 0) {
  616.     MakeNode(&RecvList, hdr + 9);
  617.     return;
  618.     }
  619.     MakeNode(&HdrList, hdr);
  620. }
  621.  
  622. /*
  623.  *  Adds (personal info) to FromList based on passwd entry or, if
  624.  *  that is not available, from the Config entry 'RealName' or
  625.  *  ENV:REALNAME (env:REALNAME takes precedence)
  626.  */
  627.  
  628. void
  629. FromFixup(list)
  630. LIST *list;
  631. {
  632.     NODE *node;
  633.     NODE *nn;
  634.     LIST tmpList;
  635.  
  636.     NewList(&tmpList);
  637.  
  638.     while (node = RemHead(list)) {
  639.     /*
  640.      *  FIXME.  Fix getpwnam() and use pw_gecos entry.
  641.      */
  642.     nn = malloc(sizeof(NODE) + strlen(node->ln_Name) + strlen(RealName) + 16);
  643.     nn->ln_Name = (char *)(nn + 1);
  644.     sprintf(nn->ln_Name, "%s (%s)", node->ln_Name, RealName);
  645.     free(node);
  646.     AddTail(&tmpList, nn);
  647.     }
  648.     while (node = RemHead(&tmpList))
  649.     AddTail(list, node);
  650. }
  651.  
  652. /*
  653.  *  Converts an unparsed list of names into a list of single address
  654.  *  fields, removing any personal idents from the entries.  These will
  655.  *  be recombined after processing when the data file is written out.
  656.  *
  657.  *  Also expands sendmail aliases (UULIB:Aliases) (HACK)
  658.  */
  659.  
  660. void
  661. ToFixup(list)
  662. LIST *list;
  663. {
  664.     NODE *node;
  665.     LIST tmpList;
  666.  
  667.     NewList(&tmpList);
  668.  
  669.     while (node = RemHead(list)) {
  670.     char *str = node->ln_Name;
  671.     char *ptr;
  672.  
  673.     while (*str) {      /*  breakup fields by newline or comma */
  674.         for (ptr = str; *ptr && *ptr != '\n' && *ptr != ','; ++ptr);
  675.         MakeToAddrNode(&tmpList, str);
  676.         str = ptr;
  677.         while (*str == '\n' || *str == ',' || *str == ' ' || *str == '\t')
  678.         ++str;
  679.     }
  680.     free(node);
  681.     }
  682.     while (node = RemHead(&tmpList))
  683.     AddTail(list, node);
  684. }
  685.  
  686. /*
  687.  *  Extracts a single name / address (comma or newline delimited)
  688.  *  field and creates a new node.
  689.  */
  690.  
  691. void
  692. MakeToAddrNode(list, str)
  693. LIST *list;
  694. char *str;
  695. {
  696.     char *p1, *p2;
  697.     short ns = 0;    /*  non-whitespace encountered */
  698.  
  699.     for (p1 = str; *p1 && *p1 != ',' && *p1 != '\n'; ++p1) {
  700.     if (*p1 == '(') {   /*  addr (name) OR (name) addr */
  701.         if (ns) {       /*  addr (name) */
  702.         MakeToFixNode(list, str, p1);
  703.         } else {
  704.         while (*p1 && *p1 != ',' && *p1 != '\n' && *p1 != ')')
  705.             ++p1;
  706.         if (*p1 == ')') {
  707.             for (p2 = p1 + 1; *p2 && *p2 != ',' && *p2 != '\n'; ++p2);
  708.             MakeToFixNode(list, p1 + 1, p2);
  709.         }
  710.         }
  711.         return;
  712.     }
  713.  
  714.     if (*p1 == '<') {   /*  <addr>  */
  715.         for (p2 = p1 + 1; *p2 && *p2 != ',' && *p2 != '\n' && *p2 != '>'; ++p2);
  716.         if (*p2 == '>')
  717.         MakeToFixNode(list, p1 + 1, p2);
  718.         return;
  719.     }
  720.     if (*p1 != ' ' && *p1 != '\t')
  721.         ns = 1;
  722.     }
  723.     MakeToFixNode(list, str, p1);
  724. }
  725.  
  726.  
  727. /*
  728.  *  Send mail to <recipiants>
  729.  *
  730.  *    -Local mail
  731.  *    -Machine path (UUCP)
  732.  *
  733.  *  NOTE:   now groups mail
  734.  */
  735.  
  736. FILE *
  737. SendMailTo(list, fi)
  738. LIST *list;
  739. FILE *fi;
  740. {
  741.     NODE *node;
  742.  
  743.     for (node = list->lh_Head; node != (NODE *)&list->lh_Tail; node = node->ln_Succ)
  744.     fi = OneMailTo(node->ln_Name, fi, node->ln_Pri);
  745.     fi = TermMailToUUCP(fi);
  746.     return(fi);
  747. }
  748.  
  749. FILE *
  750. OneMailTo(toaddr, rfi, nobounce)
  751. char *toaddr;
  752. FILE *rfi;
  753. short nobounce;
  754. {
  755.     short i;
  756.     char c;
  757.     static char ToAddr[512];
  758.     static char Buf[512];
  759.     static char typeBuf[16];
  760.     static char classBuf[16];
  761.     static char addrBuf[128];
  762.  
  763.     if (toaddr[0] == '|')       /*  pipe through command    */
  764.     return(OneMailToPipe(toaddr + 1, rfi));
  765.     if (toaddr[0] == '>')       /*  copy to file            */
  766.     return(OneMailToFile(toaddr + 1, rfi));
  767.  
  768.     strncpy(ToAddr, toaddr, sizeof(ToAddr));
  769.     ToAddr[sizeof(ToAddr) - 1] = 0;
  770.  
  771. loop:
  772.     for (i = 0; c = ToAddr[i]; ++i) {
  773.     if (c == '!' || c == '%' || c == '@' || c == ':')
  774.         break;
  775.     }
  776.     if (c == 0)                 /*  local name  */
  777.     return(OneMailToUser(ToAddr, rfi));
  778.  
  779.     /*
  780.      *    Non-Local mail
  781.      */
  782.  
  783.     i = ParseAddress(ToAddr, Buf, strlen(ToAddr));
  784.     if (DomainLookup(Buf, strlen(Buf), typeBuf, classBuf, addrBuf, nobounce)) {
  785.     printf("type %s class %s addr %s ROUTE %s\n", typeBuf, classBuf, addrBuf, Buf);
  786.  
  787.     /*
  788.      *  Note distinction between mail destination and mail forwarder.
  789.      *  mail destination removes the first machine from the rmail line
  790.      *  mail forwarder does NOT
  791.      */
  792.  
  793.     if (strcmpi(classBuf, "UU") == 0) {
  794.         if (strcmpi(typeBuf, "MD") == 0)
  795.         return(OneMailToUUCP(addrBuf, Buf + i + 1, rfi));
  796.         else
  797.         return(OneMailToUUCP(addrBuf, Buf, rfi));
  798.     } else if (strcmpi(classBuf, "LL") == 0) {  /*  local mail, loop */
  799.         for (i = 0; Buf[i] && Buf[i] != '!'; ++i);
  800.         if (Buf[i] == 0) {
  801.         strcpy(Buf + i, "postmaster");
  802.         --i;
  803.         }
  804.         strcpy(ToAddr, Buf + i + 1);
  805.         goto loop;
  806.     } else {
  807.         ulog(-1, "Unsupported domain class: %s", classBuf);
  808.         printf("Unsupported domain class: %s\n", classBuf);
  809.     }
  810.     return(rfi);
  811.     } else {
  812.     char *from;
  813.  
  814.     /*
  815.      *  handle bounced mail here.  We only reach this point if BounceMode
  816.      *  was enabled (only way the DomainLookup() could return 0
  817.      *
  818.      *  Include the headers and first few lines of the message in the
  819.      *  bounced mail.  Do not bounce mail from mailer-daemon
  820.      */
  821.  
  822.     if (from = FindHeader("From:")) {
  823.         if (strstr(from, "mailer-daemon") || strstr(from, "MAILER-DAEMON")) {
  824.         ulog(-1, "Received mailer-daemon bounce: %s", from);
  825.         } else {
  826.         if ((from = FindHeader("Sender:")) || (from = FindHeader("From:"))) {
  827.             FILE *fo;
  828.             long pos = ftell(rfi);
  829.             short maxlines = 10;
  830.  
  831.             /*
  832.              *    return mail to sender
  833.              */
  834.  
  835.             strcpy(ScrBuf2, TmpFileName("t:bounce"));
  836.             if (fo = fopen(ScrBuf2, "w")) {
  837.             fprintf(fo, "From: MAILER-DAEMON@%s%s (mailer-daemon)\n", NodeName, DomainName);
  838.             fprintf(fo, "To: %s\n", from);
  839.             fprintf(fo, "Subject: Returned mail: host unknown\n");
  840.             fprintf(fo, "Precedence: junk\n");
  841.             fprintf(fo, "Sender: postmaster@%s%s (Mr-Amiga)\n", NodeName, DomainName);
  842.             fprintf(fo, "\n");
  843.             fprintf(fo, "%s%s is unable to resolve: %s\n", NodeName, DomainName, Buf);
  844.             fprintf(fo, "message returned to sender:\n\n");
  845.  
  846.             DumpHeaderInfo(fo, RCVR_SENDMAIL, 0, 0, ":");
  847.  
  848.             fprintf(fo, "a few lines of the Bounced Message follows:\n");
  849.             while (maxlines && fgets(ScrBuf, sizeof(ScrBuf), rfi)) {
  850.                 fputs(ScrBuf, fo);
  851.                 --maxlines;
  852.             }
  853.             if (maxlines)
  854.                 fprintf(fo, "...\n\n");
  855.             fclose(fo);
  856.             sprintf(ScrBuf, "sendmail <%s", ScrBuf2);
  857.             system(ScrBuf);
  858.             }
  859.             fseek(rfi, pos, 0);
  860.             remove(ScrBuf2);
  861.         }
  862.         }
  863.     } else {
  864.         ulog(-1, "Could not find domain for %s, no mail sent", Buf);
  865.         printf("Unable to send mail to %s\n", Buf);
  866.     }
  867.     return(rfi);
  868.     }
  869. }
  870.  
  871.  
  872. FILE *
  873. OneMailToPipe(toaddr, rfi)
  874. char *toaddr;
  875. FILE *rfi;
  876. {
  877.     FILE *fi;
  878.     char *ptr;
  879.     static long pos;
  880.  
  881.     if (TempFileBuf[0] == 0) {
  882.     strcpy(TempFileBuf, TmpFileName("T:pipe"));
  883.     fi = fopen(TempFileBuf, "w");
  884.     if (fi == NULL) {
  885.         ulog(-1, "Unable to open temp file %s for command: %s", TempFileBuf, toaddr);
  886.         return(rfi);
  887.     }
  888.     DumpHeaderInfo(fi, RCVR_SENDMAIL, 0, 1, "");
  889.     pos = ftell(fi);
  890. #ifdef NOTDEF    /*  removed    */
  891.     if (ROpt) {
  892.         if (fgets(ScrBuf, sizeof(ScrBuf), rfi))
  893.         fputs(ScrBuf, fo);
  894.     }
  895. #endif
  896.     while (fgets(ScrBuf, sizeof(ScrBuf), rfi)) {
  897.         if (ScrBuf[0] == 'F' && strncmp(ScrBuf, "From ", 5) == 0)
  898.         strins(ScrBuf, " ");
  899.         fputs(ScrBuf, fi);
  900.     }
  901.     fclose(fi);
  902.     }
  903.     strcpy(ScrBuf, toaddr);
  904.  
  905.     ptr = toaddr;
  906.     if (strncmpi(toaddr, "run", 3) == 0) {
  907.     ptr += 3;
  908.     while (*ptr == ' ' || *ptr == '\t')
  909.         ++ptr;
  910.     }
  911.     while (*ptr && *ptr != ' ' && *ptr != '\t')
  912.     ++ptr;
  913.  
  914.     if (*ptr == 0)
  915.     strcat(ScrBuf, " ");
  916.     sprintf(ScrBuf + (ptr - toaddr + 1), "<%s %s", TempFileBuf, ptr);
  917.     if (Execute(ScrBuf, NULL, NULL) == 0)
  918.     ulog(-1, "Couldn't execute %s", ScrBuf);
  919.  
  920.     fi = fopen(TempFileBuf, "r");
  921.     if (fi) {
  922.     if (rfi != stdin)
  923.         fclose(rfi);
  924.     rfi = fi;
  925.     fseek(rfi, pos, 0);
  926.     } else {
  927.     ulog(-1, "Couldn't reopen temp '%s', mail failed!", TempFileBuf);
  928.     rfi = stdin;
  929.     }
  930.     return(rfi);
  931. }
  932.  
  933. FILE *
  934. OneMailToUser(toaddr, rfi)
  935. char *toaddr;
  936. FILE *rfi;
  937. {
  938.     ++Notify;
  939.     strcpy(ScrBuf, MakeConfigPath(UUMAIL, toaddr));
  940.     return(OneMailToFile(ScrBuf, rfi));
  941. }
  942.  
  943. FILE *
  944. OneMailToFile(tofile, rfi)
  945. char *tofile;
  946. FILE *rfi;
  947. {
  948.     FILE *fo;
  949.     static char DataFile[128];
  950.     long pos;
  951.  
  952.     strcpy(DataFile, tofile);
  953.  
  954.     LockFile(DataFile);
  955.     fo = fopen(DataFile, "a");
  956.     if (fo == NULL) {
  957.     strcpy(DataFile, "T:MailOverflow");
  958.     fo = fopen(DataFile, "a");
  959.     if (fo)
  960.         ulog(-1, "Could not append to %s, appending to %s", tofile, DataFile);
  961.     else
  962.         ulog(-1, "Can't append to anywhere! (%s)", tofile);
  963.     }
  964.     if (fo) {
  965.     DumpHeaderInfo(fo, RCVR_SENDMAIL, 0, 1, "");
  966.     pos = ftell(fo);
  967. #ifdef NOTDEF
  968.     if (ROpt) {
  969.         if (fgets(ScrBuf, sizeof(ScrBuf), rfi))
  970.         fputs(ScrBuf, fo);
  971.     }
  972. #endif
  973.     while (fgets(ScrBuf, sizeof(ScrBuf), rfi)) {
  974.         if (ScrBuf[0] == 'F' && strncmp(ScrBuf, "From ", 5) == 0)
  975.         strins(ScrBuf, " ");
  976.         fputs(ScrBuf, fo);
  977.     }
  978.     if (ScrBuf[0] != '\n')
  979.         fputs("\n", fo);
  980.     fclose(fo);
  981.     if (rfi != stdin)
  982.         fclose(rfi);
  983.     rfi = fopen(DataFile, "r");
  984.     fseek(rfi, pos, 0);
  985.     }
  986.     UnLockFile(DataFile);
  987.     return(rfi);
  988. }
  989.  
  990. /*
  991.  *  UUCP MAILER.  Generate a control node for each destination.  When the
  992.  *  mail is terminated, a batch file will be created for each destination
  993.  *  host.
  994.  */
  995.  
  996. FILE *
  997. OneMailToUUCP(toaddr, skipaddr, rfi)
  998. char *toaddr;
  999. char *skipaddr;
  1000. FILE *rfi;
  1001. {
  1002.     UUHostNode *uh;
  1003.     struct Node *node;
  1004.     short i;
  1005.     int hostLen;
  1006.     int maxRMailLen = atoi(GetConfig(MAXRMAILLEN, "0"));
  1007.  
  1008.     /*
  1009.      *    find host, first element of 'toaddr'
  1010.      */
  1011.  
  1012. loop:
  1013.     for (i = 0; toaddr[i] && toaddr[i] != '!' && toaddr[i] != '.' && i != 7; ++i);
  1014.  
  1015.     /*
  1016.      *    search for UUHostNode in UUHostList, append to node list for
  1017.      *    rmail line.
  1018.      */
  1019.  
  1020.     for (uh = GetHead(&UUHostList); uh; uh = GetSucc(&uh->uh_Node)) {
  1021.     if (strlen(uh->uh_Node.ln_Name) == i && strnicmp(uh->uh_Node.ln_Name, toaddr, i) == 0)
  1022.         break;
  1023.     }
  1024.     if (uh == NULL) {
  1025.     uh = malloc(sizeof(UUHostNode) + i + 1);
  1026.     uh->uh_Node.ln_Name = (char *)(uh + 1);
  1027.     uh->uh_Len = 10;    /*    'C rmail'   */
  1028.     uh->uh_NAddr = 0;
  1029.     strncpy(uh->uh_Node.ln_Name, toaddr, i);
  1030.     uh->uh_Node.ln_Name[i] = 0;
  1031.     AddTail(&UUHostList, &uh->uh_Node);
  1032.     NewList(&uh->uh_List);
  1033.     }
  1034.  
  1035.     while (toaddr[i] && toaddr[i] != '!')
  1036.     ++i;
  1037.     if (toaddr[i] == '!')
  1038.     ++i;
  1039.  
  1040.     hostLen = strlen(toaddr + i) + strlen(skipaddr) + 3;
  1041.  
  1042.     if (uh->uh_NAddr > 0 && uh->uh_Len + hostLen > maxRMailLen) {
  1043.     rfi = TermMailToUUCP(rfi);
  1044.     goto loop;
  1045.     }
  1046.  
  1047.  
  1048.     node = malloc(sizeof(struct Node) + hostLen + 1);
  1049.     node->ln_Pri = 0;
  1050.     node->ln_Name = (char *)(node + 1);
  1051.     AddTail(&uh->uh_List, node);
  1052.  
  1053.     if (toaddr[i]) {
  1054.     sprintf(node->ln_Name, "%s!%s", toaddr + i, skipaddr);
  1055.     } else {
  1056.     sprintf(node->ln_Name, "%s", skipaddr);
  1057.     }
  1058.     ++uh->uh_NAddr;
  1059.     uh->uh_Len += strlen(node->ln_Name) + 1;    /*  inc space */
  1060.     return(rfi);
  1061. }
  1062.  
  1063.  
  1064. FILE *
  1065. TermMailToUUCP(rfi)
  1066. FILE *rfi;
  1067. {
  1068.     static char ExecFile[128];
  1069.     static char RemoteExecFile[128];
  1070.     static char CommandFile[128];
  1071.     static char DataFile[128];
  1072.     static char RemoteDataFile[128];
  1073.     UUHostNode *uh;
  1074.     char spoolDir[256];
  1075.     short foff;
  1076.     short failure = 0;
  1077.  
  1078.     while (uh = RemHead(&UUHostList)) {
  1079.     int seq;
  1080.     long pos;
  1081.     FILE *fi;
  1082.  
  1083.     Seq = seq = GetSequence(4);
  1084.                                               /* hierarch - bruins */
  1085.     strcpy(spoolDir,MakeConfigPath(UUSPOOL, uh->uh_Node.ln_Name));
  1086.     if(spoolDir==NULL || *spoolDir=='\0'){
  1087.        ulog(-1,"Can't create spool for \"%s\".", uh->uh_Node.ln_Name);
  1088.        return(-1);
  1089.     }
  1090.     if(chdir(spoolDir)){
  1091.        ulog(-1,"Can't change to spool: \"%s\".",spoolDir);
  1092.        if(mkdir(spoolDir)){
  1093.         ulog(-1,"Can't find spool \"%s\", creating.",spoolDir);
  1094.         return(-1);
  1095.        }
  1096.        chdir(spoolDir);
  1097.         }
  1098.  
  1099.     foff = strlen(spoolDir)+1;  /* hierarch - bruins */
  1100.  
  1101.     sprintf(CommandFile,    "%s/C.%sA%s", spoolDir, uh->uh_Node.ln_Name, SeqToName(seq));
  1102.     sprintf(DataFile,       "%s/D.%sB%s", spoolDir, uh->uh_Node.ln_Name, SeqToName(seq));
  1103.     sprintf(ExecFile,       "%s/D.%sX%s", spoolDir, uh->uh_Node.ln_Name, SeqToName(seq));
  1104.     ++seq;
  1105.     sprintf(RemoteExecFile, "%s/X.%sX%s", spoolDir, CutNodeName, SeqToName(seq));
  1106.     ++seq;
  1107.     sprintf(RemoteDataFile, "%s/D.%sB%s", spoolDir, CutNodeName, SeqToName(seq));
  1108.  
  1109.     LockFile(CommandFile);
  1110.     LockFile(DataFile);
  1111.  
  1112.     /*
  1113.      *  Note, cannot run uuxqt from sendmail as uuxqt may call
  1114.      *  sendmail itself!
  1115.      */
  1116.  
  1117.     if (strncmp(uh->uh_Node.ln_Name, NodeName, 7) == 0) {
  1118.         strcpy(ExecFile, RemoteExecFile);
  1119.         strcpy(RemoteDataFile, DataFile);
  1120.     }
  1121.  
  1122.     fi = fopen(ExecFile, "w");
  1123.  
  1124.     if (fi == NULL) {
  1125.         UnLockFile(CommandFile);
  1126.         UnLockFile(DataFile);
  1127.         failure = 1;
  1128.         break;
  1129.     }
  1130.  
  1131.     fprintf(fi, "U %s %s\n", UserName, NodeName);
  1132.     fprintf(fi, "F %s\n", RemoteDataFile + foff);
  1133.     fprintf(fi, "I %s\n", RemoteDataFile + foff);
  1134.     fprintf(fi, "C rmail");
  1135.  
  1136.     {
  1137.         struct Node *node;
  1138.  
  1139.         while (node = RemHead(&uh->uh_List)) {
  1140.         fprintf(fi, " %s", node->ln_Name);
  1141.         free(node);
  1142.         }
  1143.         fputc('\n', fi);
  1144.     }
  1145.     fclose(fi);
  1146.  
  1147.     if (strnicmp(uh->uh_Node.ln_Name, NodeName, 7) != 0) {
  1148.         fi = fopen(CommandFile, "w");
  1149.         if (fi == NULL) {
  1150.         UnLockFile(CommandFile);
  1151.         UnLockFile(DataFile);
  1152.         failure = 1;
  1153.         break;
  1154.         }
  1155.  
  1156.         fprintf(fi, "S %s %s %s - %s 0666\n", DataFile + foff, RemoteDataFile + foff, UserName, DataFile + foff);
  1157.         fprintf(fi, "S %s %s %s - %s 0666\n", ExecFile + foff, RemoteExecFile + foff, UserName, ExecFile + foff);
  1158.         fclose(fi);
  1159.     }
  1160.  
  1161.     fi = fopen(DataFile, "w");
  1162.     if (fi == NULL) {
  1163.         UnLockFile(CommandFile);
  1164.         UnLockFile(DataFile);
  1165.         remove(CommandFile);
  1166.         failure = 1;
  1167.         break;
  1168.     }
  1169.  
  1170.     DumpHeaderInfo(fi, RCVR_UUCP, 1, 0, "");
  1171.     pos = ftell(fi);
  1172.  
  1173. #ifdef NOTDEF
  1174.     if (ROpt) {
  1175.         if (fgets(ScrBuf, sizeof(ScrBuf), rfi))
  1176.         fputs(ScrBuf, fi);
  1177.     }
  1178. #endif
  1179.     while (fgets(ScrBuf, sizeof(ScrBuf), rfi)) {
  1180.         if (ScrBuf[0] == 'F' && strncmp(ScrBuf, "From ", 5) == 0)
  1181.         strins(ScrBuf, " ");
  1182.         fputs(ScrBuf, fi);
  1183.     }
  1184.     fclose(fi);
  1185.     if (rfi != stdin)
  1186.         fclose(rfi);
  1187.     fi = fopen(DataFile, "r");
  1188.     fseek(fi, pos, 0);
  1189.     rfi = fi;
  1190.  
  1191.     UnLockFile(CommandFile);
  1192.     UnLockFile(DataFile);
  1193.     free(uh);
  1194.     }
  1195.     if (failure) {
  1196.     puts("Fail");
  1197.     ulog(-1, "Output failed %s", CommandFile);
  1198.     }
  1199.     return(rfi);
  1200. }
  1201.  
  1202. void
  1203. DumpHeaderInfo(fi, rcvr, resend, local, prestr)
  1204. FILE *fi;
  1205. int rcvr, resend, local;
  1206. char *prestr;
  1207. {
  1208.     char *source;
  1209.  
  1210.     /*
  1211.      *    Write header info
  1212.      */
  1213.  
  1214. #ifdef NOTDEF
  1215.     if (rcvr == RCVR_UUCP)
  1216.     source = "AmigaUUCP";
  1217.     else
  1218.     source = "Sendmail";
  1219. #endif
  1220.  
  1221.     if (ROpt) {
  1222.     if (resend)
  1223.         fprintf(fi, "%s%s %s remote from %s%s\n", prestr, FromLine, atime(&T), NodeName, DomainPath);
  1224.     else
  1225.         fprintf(fi, "%s%s %s\n", prestr, FromLine, atime(&T));
  1226.     } else {
  1227.     if (local)
  1228.         fprintf(fi, "%sFrom %s %s\n", prestr, UserName, atime(&T));
  1229.     else
  1230.         fprintf(fi, "%sFrom %s %s remote from %s%s\n", prestr, UserName, atime(&T), NodeName, DomainPath);
  1231.     }
  1232.     fprintf(fi, "%sReceived: by %s%s (" VERSION "/Amiga)\n\tid AA0%s; %s\n",
  1233.     prestr, NodeName, DomainName, SeqToName(Seq), atime(&T)
  1234.     );
  1235.     DumpHeader(fi, "Received:", &RecvList, prestr);
  1236.     if (ROpt == 0) {
  1237.     time_t t2 = T + 3600 * GetHourOffset(TimeZoneName);
  1238.     struct tm *ut;
  1239.  
  1240.     if (FindHeader("Date:") == NULL)
  1241.         fprintf(fi, "%sDate: %s\n", prestr, atime(&T));
  1242.     ut = localtime(&t2);
  1243.     fprintf(fi, "%sMessage-Id: <%02d%02d%02d%02d%02d.AA0%s@%s%s>\n",
  1244.         prestr,
  1245.         ut->tm_year % 100, ut->tm_mon + 1, ut->tm_mday, ut->tm_hour, ut->tm_min,
  1246.         SeqToName(TopSeq), NodeName, DomainName
  1247.     );
  1248.     }
  1249.  
  1250.     /*
  1251.      *    From:, To:, Cc:, Subject: (Bcc: never written to header),
  1252.      *    and any other header fields
  1253.      */
  1254.  
  1255.     DumpHeader(fi, NULL, &HdrList, prestr);
  1256.     DumpHeader(fi, "From:", &FromList, prestr);
  1257.     DumpCombineHeader(fi, "To:", &ToList, prestr);
  1258.     if (!EmptyList(&CcList))
  1259.     DumpCombineHeader(fi, "Cc:", &CcList, prestr);
  1260.     DumpHeader(fi, "Subject:", &SubjList, prestr);
  1261.  
  1262.     fprintf(fi, "\n");
  1263. }
  1264.  
  1265. void
  1266. DumpHeader(fi, field, list, prestr)
  1267. FILE *fi;
  1268. char *field;
  1269. LIST *list;
  1270. char *prestr;
  1271. {
  1272.     NODE *node;
  1273.  
  1274.     for (node = list->lh_Head; node != (NODE *)&list->lh_Tail; node = node->ln_Succ) {
  1275.     if (field)
  1276.         fprintf(fi, "%s%s %s\n", prestr, field, node->ln_Name);
  1277.     else
  1278.         fprintf(fi, "%s%s\n", prestr, node->ln_Name);
  1279.     }
  1280. }
  1281.  
  1282. char *
  1283. FindHeader(field)
  1284. char *field;
  1285. {
  1286.     NODE *node;
  1287.     char *ptr = NULL;
  1288.     short len = strlen(field);
  1289.  
  1290.     for (node = HdrList.lh_Head; node != (NODE *)&HdrList.lh_Tail; node = node->ln_Succ) {
  1291.     if (strncmp(node->ln_Name, field, len) == 0) {
  1292.         ptr = node->ln_Name;
  1293.         break;
  1294.     }
  1295.     }
  1296.     if (ptr == NULL) {
  1297.     if ((node = (void *)GetTail(&FromList)) && strncmp("From:", field, len) == 0)
  1298.         ptr = node->ln_Name - len;
  1299.     }
  1300.     if (ptr == NULL) {
  1301.     if ((node = (void *)GetTail(&SubjList)) && strncmp("Subject:", field, len) == 0)
  1302.         ptr = node->ln_Name - len;
  1303.     }
  1304.     if (ptr) {
  1305.     ptr += len;
  1306.     while (*ptr == ' ' || *ptr == '\t')
  1307.         ++ptr;
  1308.     }
  1309.     return(ptr);
  1310. }
  1311.  
  1312. void
  1313. DumpCombineHeader(fi, field, list, prestr)
  1314. FILE *fi;
  1315. char *field;
  1316. LIST *list;
  1317. char *prestr;
  1318. {
  1319.     NODE *node;
  1320.     short ci = 0;
  1321.  
  1322.     fprintf(fi, "%s%s ", prestr, field);
  1323.     for (node = list->lh_Head; node != (NODE *)&list->lh_Tail; node = node->ln_Succ) {
  1324.     if (ci && ci + strlen(node->ln_Name) > 70) {
  1325.         fprintf(fi, ",\n%s\t", prestr);
  1326.         ci = 0;
  1327.     }
  1328.     if (ci)
  1329.         fprintf(fi, ", ");
  1330.     fprintf(fi, "%s", node->ln_Name);
  1331.     ci += strlen(node->ln_Name) + 2;
  1332.     }
  1333.     fprintf(fi, "\n");
  1334. }
  1335.  
  1336. #ifdef NOTDEF    /*  now in uucp:src/lib */
  1337. char *
  1338. atime(pt)
  1339. time_t *pt;
  1340. {
  1341.     static char buf[40];
  1342.     static char *mo[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  1343.                 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  1344.             };
  1345.     static char *dow[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
  1346.     struct tm *ut = localtime(pt);
  1347.  
  1348.     sprintf(buf, "%s, %d %s %02d %02d:%02d:%02d %s",
  1349.     dow[ut->tm_wday], ut->tm_mday, mo[ut->tm_mon],
  1350.     ut->tm_year % 100, ut->tm_hour, ut->tm_min, ut->tm_sec,
  1351.     TimeZoneName
  1352.     );
  1353.     return(buf);
  1354. }
  1355. #endif
  1356.  
  1357. int
  1358. GetHourOffset(tz)
  1359. char *tz;
  1360. {
  1361.     short i;
  1362.  
  1363.     static struct {
  1364.     char *Name;
  1365.     short Hours;
  1366.     } TZAry[] = {
  1367.     "GMT",  0,
  1368.     "UT",   0,
  1369.     "UTC",  0,
  1370.     "PST",  8,
  1371.     "MST",  7,
  1372.     "CST",  6,
  1373.     "EST",  5,
  1374.     "AST",  4,
  1375.     "PDT",  7,
  1376.     "MDT",  6,
  1377.     "CDT",  5,
  1378.     "EDT",  4,
  1379.     "ADT",  3,
  1380.     "CET",  -1,
  1381.     "MET",  -1,     /*  alternate, please use CET   */
  1382.     "MEZ",  -1,     /*  alternate, please use CET   */
  1383.     "CED",  -2,     /*  central european daylight saving time   */
  1384.     "CEDT", -2,     /*  alternate                   */
  1385.     "MED",  -2,     /*  alternate, please use CED   */
  1386.     "CEST", -2,     /*  alternate, please use CED   */
  1387.     "MESZ", -2,     /*  alternate, please use CED   */
  1388.     "EET",  -2,     /*  ??                          */
  1389.     "JST",  -9,
  1390.     "HST",  -10,    /*  Hawaiian Sandard Time       */
  1391.     NULL, 0
  1392.     };
  1393.     for (i = 0; TZAry[i].Name; ++i) {
  1394.     if (strncmp(tz, TZAry[i].Name, 3) == 0)
  1395.         return((int)TZAry[i].Hours);
  1396.     }
  1397.     ulog(-1, "Unknown Timezone: %s", tz);
  1398. /*    printf("Unknown Timezone: %s\n", tz);  - bruins */
  1399.     return(6);
  1400. }
  1401.  
  1402. void
  1403. PostPend(str, frend)
  1404. char *str;
  1405. int frend;
  1406. {
  1407.     char *ptr;
  1408.     if (frend) {
  1409.     ptr = str + strlen(str);
  1410.     while (ptr > str && *ptr != ' ' && *ptr != '\t') {
  1411.         if (*ptr == '\n')
  1412.         *ptr = 0;
  1413.         --ptr;
  1414.     }
  1415.     str = ptr + 1;
  1416.     }
  1417.     for (ptr = str; *ptr && *ptr != ' ' && *ptr != '\t' && *ptr != '\n'; ++ptr);
  1418.     if (frend)
  1419.     *ptr++ = '!';
  1420.     *ptr = 0;
  1421.     for (ptr = FromLine + 5; *ptr && *ptr != ' ' && *ptr != '\t'; ++ptr);
  1422.     strins(ptr, str);
  1423. }
  1424.  
  1425. EmptyList(list)
  1426. LIST *list;
  1427. {
  1428.     if (list->lh_Head == (NODE *)&list->lh_Tail)
  1429.     return(1);
  1430.     return(0);
  1431. }
  1432.  
  1433.