home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume26 / tulp-3.0.3 / part02 / l.c next >
C/C++ Source or Header  |  1993-04-15  |  15KB  |  521 lines

  1. /*-------------------------------------------------------------------------
  2.  *  Listserv - Unix Mailing List manager (sub-set of FRECP's
  3.  *             Bitnet Listserv tool.
  4.  *
  5.  *  Copyright (C) 1991,1992  Kimmo Suominen, Christophe Wolfhugel
  6.  *
  7.  *  Please read the files COPYRIGHT and AUTHORS for the extended
  8.  *  copyrights refering to this file.
  9.  *
  10.  *  This program is free software; you can redistribute it and/or modify
  11.  *  it under the terms of the GNU General Public License as published by
  12.  *  the Free Software Foundation; either version 1, or (at your option)
  13.  *  any later version.
  14.  *
  15.  *  This program is distributed in the hope that it will be useful,
  16.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  *  GNU General Public License for more details.
  19.  *
  20.  *  You should have received a copy of the GNU General Public License
  21.  *  along with this program; if not, write to the Free Software
  22.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  23.  *----------------------------------------------------------------------*/
  24.  
  25. static char rcsid[] = "@(#)$Id: l.c,v 1.34 93/03/02 22:13:17 wolf Exp $";
  26.  
  27. #include <stdio.h>
  28. #include <string.h>
  29. #include <signal.h>
  30. #include <time.h>
  31. #include <unistd.h>
  32. #include <ctype.h>
  33. #include <sys/ioctl.h>
  34. #include <sys/param.h>
  35. #include <sys/times.h>
  36. #include <sys/types.h>
  37. #include <sys/stat.h>
  38. #include "conf.h"
  39. #include "ext.h"
  40. #include "lp.h"
  41. #include "str.h"
  42. #include "popen.h"
  43. #include "ad.h"
  44. #include "lc.h"
  45. #include "messages.h"
  46. #ifdef FAKESYSLOG
  47. # include "fakesyslog.h"
  48. #else
  49. # include <syslog.h>
  50. #endif
  51.  
  52. int     Debug = 0;
  53.  
  54. short    subj;
  55.  
  56. int    msgHere = 0, done = 0;
  57. char    listName[64];
  58. char    From[MAXLINE], To[MAXLINE], ReplyTo[MAXLINE];
  59. char    buf[MAXLINE], rcpt[MAXLINE];
  60. int    d, h, m, s;
  61. long    startTime, endTime, msgSize;
  62. struct     tms t;
  63.  
  64. static    int ctr;
  65.  
  66. void lTodhms(t)
  67. long t;
  68. {
  69.    d = t / ( 24 * 3600L );
  70.    h = ( t % ( 24 * 3600L )) / 3600;
  71.    m = ( t % 3600 ) /60;
  72.    s = t % 60;
  73. }
  74.  
  75. char *instring(s1, s2)
  76. char *s1, *s2;
  77. {
  78.    if ((int)strlen(s2) > (int)strlen(s1)) return(NULL);
  79.    for (; *(s1 + strlen(s2) - 1); s1++)
  80.       if (strncasecmp(s1, s2, strlen(s2)) == 0) return(s1);
  81.    return(NULL);
  82. }
  83.  
  84. char *strlwr(s)
  85. char *s;
  86. {
  87.    char *p = s;
  88.  
  89.    if (s==NULL) return(NULL);
  90.    for (; *s; s++) *s = tolower(*s);
  91.    return(p);
  92. }
  93.  
  94. char *strupr(s)
  95. char *s;
  96. {
  97.    char *p = s;
  98.  
  99.    if (s == NULL) return(NULL);
  100.    for (; *s; s++) *s = toupper(*s);
  101.    return(p);
  102. }
  103.  
  104. void mailMsg(to, subj)
  105. char *to, *subj;
  106. {
  107.    FILE *f, *g;
  108.    char buf[1024];
  109.  
  110.    sprintf(buf, "%s %s", SENDMAIL, to);
  111.    if ((g = l_popen(buf, "w")) == NULL) {
  112.       syslog(LOG_ERR, "mailMsg - popen failed: %m");
  113.       exit(2);
  114.    } /* endif */
  115.    if ((f = fopen("msg","r")) == NULL) {
  116.       syslog(LOG_ERR, "mailMsg - fopen failed: %m");
  117.       exit(2);
  118.    } /* endif */
  119.    fprintf(g, "Subject: %s\n\n", subj);
  120.    while (fgets(buf, sizeof(buf), f) != NULL)
  121.       fputs(buf, g);
  122.    l_pclose(g); fclose(f);
  123. }
  124.  
  125. void sendMsg()
  126. {
  127.    char cmd[MAXLINE + 256], *p;
  128.    int c;
  129.    FILE *f, *h;
  130.  
  131. #ifdef ADD_REQUEST
  132.    sprintf(cmd, "%s -f%s-request %s", SENDMAIL, listName, rcpt);
  133. #else
  134.    sprintf(cmd, "%s %s", SENDMAIL, rcpt);
  135. #endif
  136.    if ((h = l_popen(cmd,"w")) == NULL) {
  137.       syslog(LOG_ERR, "sendMsg - popen: %m");
  138.       exit(2);
  139.    } /* endif */
  140.    if ((f = fopen("msg", "r")) == NULL) {
  141.       syslog(LOG_ERR, "sendMsg - popen: %m");
  142.       exit(2);
  143.    } /* endif */
  144.    while (fgets(buf, sizeof(buf), f) != NULL && buf[0] != '\n') {
  145.       /* if the line is too long, throw the rest away */
  146.       if (index(buf, '\n') == NULL) {
  147.          while ((c = getc(f)) != '\n' && c != EOF)
  148.             continue;
  149.       } /* endif */
  150.       while ((c = getc(f)) == ' ' || c == '\t') {
  151.      p = &buf[strlen(buf)];
  152.      *p++ = ' ';
  153.      if (fgets(p, sizeof(buf) - (p - buf), f) == NULL)
  154.             break;
  155.       } /* endwhile */
  156.       if (!feof(f) && !ferror(f))
  157.      ungetc(c, f);
  158.  
  159.       if (strncasecmp(buf, "Status: ", 8) == 0) continue;
  160.       if (strncasecmp(buf, "X-Envelope-To: ", 15) == 0) continue;
  161.       if (strncasecmp(buf, "X-Listserv-To: ", 15) == 0) continue;
  162.       if (strncasecmp(buf, ">From ", 6) == 0) continue;
  163.       if (strncasecmp(buf, "Return-receipt-to: ", 19) == 0) continue;
  164. #ifdef STRIP_RECEIVED
  165.       if (strncasecmp(buf, "Received: ", 10) == 0) continue;
  166. #endif
  167.       if (ReplyTo[0] != 0 && strncasecmp(buf, "Reply-To: ", 10) == 0)
  168.      continue;
  169.       if (*GetErrorsTo() != '\0' && strncasecmp(buf, "Errors-To: ", 11) == 0)
  170.      continue;
  171. #ifdef ADD_SENDER
  172.       if (strncasecmp(buf, "Sender: ", 8) == 0) continue;
  173. #endif
  174.       fputs(buf, h);
  175.          /* strcpy(cmd, listName); strupr(cmd);
  176.      fprintf(h, "To: %s Distribution List <%s@%s>\n", cmd, listName, HOST);
  177.      */
  178.    } /* endwhile */
  179. #ifdef ADD_SENDER
  180.    fputs(versSender, h);
  181. #endif
  182.    if (*GetErrorsTo() != '\0') fprintf(h, "Errors-To: %s\n", GetErrorsTo());
  183.    if (ReplyTo[0] != 0) fprintf(h, "Reply-To: %s\n", ReplyTo);
  184.    if (subj == 0) fprintf(h, "Subject: <none>\n");
  185.    if (ctr != 0) fprintf(h, "X-Sequence: %d\n", ctr);
  186.    do {
  187.       fputs(buf, h);
  188.    } while (fgets(buf, sizeof(buf), f) != NULL);
  189.    fclose(f); l_pclose(h);
  190. }
  191.  
  192. void saveMsg()
  193. {
  194.   FILE *f, *g;
  195.   long ti;
  196.   struct tm *t;
  197.   int dir = 0, oldfile = 0;
  198.   char cmd[64];
  199.   struct stat st;
  200.  
  201.   time(&ti); t = localtime(&ti); f = fopen("msg","r");
  202.   if (chdir(listName) == -1)
  203.     return;
  204.   else {
  205.     dir = 1;
  206.     sprintf(cmd, "log%02d%02d", t->tm_year, t->tm_mon + 1);
  207.     oldfile = stat(cmd, &st) + 1;
  208.     g = fopen(cmd, "a");
  209.   } /* endif */
  210.   if (!oldfile) {
  211.     fprintf(g, "This digest for list %s has been created on %s\n\n",
  212.         listName, asctime(t));
  213.     fputs("------- THIS IS A RFC934 COMPLIANT DIGEST, YOU CAN BURST IT -------\n\n", g);
  214.   }
  215.   while (fgets(buf, sizeof(buf), f) != NULL && buf[0] != '\n') {
  216.     if (strncmp(buf, "Subject:", 8) == 0 || strncmp(buf, "Date:", 5) == 0)
  217.       fputs(buf, g);
  218.     if (strncmp(buf, "From:", 5) == 0) {
  219.       fprintf(g, "From: %s\n", From);
  220.       if (subj == 0) fprintf(g, "Subject: <none>\n");
  221.     } /* endif */
  222.     strlwr(buf);
  223.   } /* endwhile */
  224.   if (ctr != 0) fprintf(g, "X-Sequence: %d\n", ctr);
  225.   do {
  226.     if (buf[0] == '-') { fprintf(g, "- "); }
  227.     fputs(buf, g);
  228.   } while (fgets(buf, 512, f) != NULL);
  229.   fputs("------- CUT --- CUT --- CUT --- CUT --- CUT --- CUT --- CUT -------\n\n", g);
  230.   fclose(f); fclose(g);
  231.   if (dir == 1) chdir(TULPDIR);
  232. }
  233.  
  234. void fwdMsg()
  235. {
  236.    FILE *f, *g, *h;
  237.    int i;
  238.    char *p;
  239.    char cmd[128];
  240.  
  241.    strcpy(listName, To);
  242.    if (ReadUserList(listName) == -1) { 
  243.       syslog(LOG_INFO, "Sending error (list not found)");
  244.       mailMsg("list-errors", "List-Errors");
  245.       unlink("msg"); return; 
  246.    } /* endif */
  247.    strcpy(buf, GetReplyTo());
  248.    if (ReplyTo[0] == 0 || instring(buf, ",respect") == NULL) {
  249.       if (strncasecmp(buf, "list", 4) == 0) {
  250.          strcpy(cmd, listName);
  251.          strupr(cmd);
  252.          sprintf(ReplyTo, "%s Distribution List <%s@%s>", cmd, listName, HOST);
  253.       } else if (strncasecmp(buf, "sender", 6) != 0)
  254.          sprintf(ReplyTo, "%s", strtok(buf, ","));
  255.    } /* endif */
  256.    RewindUserList();
  257.    if (strcasecmp(GetSend(), "private") == 0 && !IsUser(From)) {
  258.       syslog(LOG_INFO,
  259.          "Mail to list %s from %s - Refused, this user is not allowed",
  260.          listName, From);
  261.       sprintf(buf, "%s %s", SENDMAIL, strtok(From, " ")); /* NAK to sender */
  262.       if ((g = l_popen(buf, "w")) == NULL) {
  263.      syslog(LOG_ERR, "fwdMsg - popen failed: %m");
  264.      unlink("msg"); 
  265.          CloseUserList();
  266.          return;
  267.       } /* endif */
  268.       if ((f = fopen("msg", "r")) == NULL) {
  269.          syslog(LOG_ERR, "fwdMsg - fopen failed: %m");
  270.          unlink("msg"); 
  271.          CloseUserList();
  272.          return;
  273.       } /* endif */
  274.       fprintf(g, TULP_HDRMAILNAK(From, listName));
  275.       fprintf(g, TULP_MAILPRIVATE);
  276.       while (fgets(buf, sizeof(buf), f) != NULL)   /* unsent message */
  277.          fputs(buf, g);
  278.       l_pclose(g); fclose(f);
  279.       mailMsg("list-errors", "attempt to send mail by a non subscriber");
  280.                                             /* to inform list-errors */
  281.    } else if (strcasecmp(GetSend(), "editor") == 0 && !IsEditor(From)) {
  282.       syslog(LOG_INFO,"Mail to list %s from %s - Article to moderate",
  283.                       listName, From);
  284.       RewindEditorList();
  285.       if (GetEditor(buf) != NULL) {
  286.      mailMsg(strtok(buf, " "), "Article to moderate");
  287.       } /* endif */
  288.    } else {            /* Ok to send */
  289.       strcpy(buf, listName);    /* X-Sequence - update listName.n */
  290.       strcat(buf, ".n");
  291.       ctr = 0;
  292.       h = fopen(buf, "r+"); 
  293.       if (h != NULL) {
  294.          fscanf(h, "%d", &ctr);
  295.          rewind(h); fprintf(h, "%d\n", ++ctr); fclose(h);
  296.       } /* endif */
  297.       syslog(LOG_INFO,"List %s - Msg from %s accepted", listName, From);
  298.       saveMsg();        /* save Msg in log file */
  299.       i = 0; p = rcpt;
  300.       while (GetUser(buf) != NULL) {
  301.      strtok(buf, "\t\r\n ");
  302.      if (((p - rcpt) + strlen(buf)+2) < sizeof(rcpt) && i++ < BATCHSIZE) {
  303.         sprintf(p, "%s ", buf);
  304.         p += strlen(p);
  305.      } else {
  306.             i = 0; p = rcpt;
  307.         sendMsg();
  308.      } /* endif */
  309.       } /* endwhile */
  310.       if (i != 0) sendMsg();
  311.    } /* endif */
  312.    unlink("msg");
  313.    CloseUserList();
  314. }
  315.  
  316. int  copyMail()
  317. {
  318.    FILE *h;
  319.    char *p;
  320.    int c;
  321.    struct stat st;
  322.  
  323.    if (access("msg", 0) == -1) {
  324.       winInc(); 
  325.       if ((h = popen(MAILX, "w")) == NULL) return(-1);
  326.       fprintf(h, "s 1 msg\n");
  327.       fprintf(h, "q\n");
  328.       pclose(h);
  329.    } /* endif */
  330.    if ((h = fopen("msg", "r")) == NULL) return(-1); 
  331.    To[0] = 0;
  332.    fstat(fileno(h), &st); msgSize = st.st_size;
  333.    subj = 0; To[0] = ReplyTo[0] = 0;
  334.    while (fgets(buf, sizeof(buf), h) != NULL && buf[0] != '\n') {
  335.       /* if the line is too long, throw the rest away */
  336.       if (index(buf, '\n') == NULL) {
  337.      while ((c = getc(h)) != '\n' && c != EOF)
  338.         continue;
  339.       } /* endif */
  340.       while ((c = getc(h)) == ' ' || c == '\t') {
  341.      p = &buf[strlen(buf) - 1];
  342.      *p++ = ' ';
  343.      if (fgets(p, sizeof(buf) - (p - buf), h) == NULL)
  344.         break;
  345.       } /* endif */
  346.       if (!feof(h) && !ferror(h))
  347.      ungetc(c, h);
  348.       strtok(buf, "\n");
  349.       if (Debug) {
  350.      fprintf(stderr, "Collected line: %s\n", buf);
  351.       } /* endif */
  352.       if (strlen(buf) > MAXLINE) {
  353.      syslog(LOG_ERR, "Header line too long: %s", strtok(buf, ":"));
  354.      fclose(h);
  355.      return(-2);
  356.       } /* endif */
  357.       if (strncmp(buf, "Reply-To: ", 10) == 0) {
  358.          strcpy(ReplyTo, buf + 10);
  359.       } /* endif */
  360.       if (strncmp(buf, "Subject: ", 9) == 0) { 
  361.          /* We could save subject here, but we don't need it */
  362.          subj = 1; 
  363.          continue; 
  364.       } /* endif */
  365.       if (strncmp(buf, "From: ", 6) == 0) {
  366.          /* Usually just one author */
  367.          strcpy(From, buf + 6);
  368.          continue;
  369.       } /* endif */
  370.       if (strncmp(buf, "X-Listserv-To: ", 15) == 0 ) {
  371.          strcpy(To, buf + 15);
  372.          continue;
  373.       } /* endif */
  374.    } /* endwhile */
  375.    adChange(From);
  376.    strlwr(To);
  377.    fclose(h);
  378.    if (To[0] == 0) {
  379.       syslog(LOG_ERR, "Empry X-Listserv-To or not found");
  380.       return(-2);
  381.    } /* endif */
  382. }
  383.  
  384. void sTe()
  385. {
  386.    done = 1;
  387. }
  388.  
  389. #ifndef NO_SIGUSR1
  390. void sPau()
  391. {
  392.    msgHere = 1;
  393. }
  394. #endif
  395.  
  396. void main(int argn, char **argv)
  397. {
  398.    struct stat st;
  399.    struct sigaction sa;
  400.    FILE *f;
  401.    int i;
  402.    extern void reapchild();
  403.  
  404.    while ((i = getopt(argn, argv, "d")) != EOF) {
  405.       switch (i) {
  406.      case 'd':
  407.         Debug = 1;
  408.         break;
  409.      default:
  410.         fprintf(stderr,"usage: %s [-d]\n", *argv);
  411.         exit(1);
  412.       } /* endsw */
  413.    } /* endif */
  414.    versInit();
  415.    if (chdir(TULPDIR) == -1) {
  416.       perror("Can't chdir' to TULPDIR. Aborting.");
  417.       exit(2);
  418.    } /* endif */
  419.    setbuf(stdout, NULL); printf("%s: daemon started for %s\n\r", vers, HOST);
  420.    printf("Copyright (C) 1991,1992  Kimmo Suominen, Christophe Wolfhugel\n");
  421.    printf("Listserv comes with ABSOLUTELY NO WARRANTY; for details see\n");
  422.    printf("the GNU General Public License that is furnished with the\n");
  423.    printf("sources of this package.\n");
  424.    if (Debug == 0)
  425.       if (fork()) exit (0);   /* Dissociate us from tty */
  426.    times(&t);
  427.    time(&startTime);
  428.    nice(NICENESS);
  429.    if (Debug == 0) {
  430.       freopen("/dev/null", "w", stdout);
  431.       freopen("/dev/null", "w", stderr);
  432.       close(fileno(stdin));
  433.       setpgrp();
  434.    } /* endif */
  435.    sigemptyset(&sa.sa_mask);
  436. #ifdef SA_RESTART
  437.    sa.sa_flags = SA_RESTART;    /* Restart system calls?  SA_RESTART */
  438.                 /* Children?  SA_NOCLDWAIT, SA_NOCLDSTOP */
  439. #else
  440.    sa.sa_flags = 0;
  441. #endif
  442.    sa.sa_handler = sTe;
  443.    sigaction(SIGTERM, &sa, NULL);
  444. #ifdef SIGURGENT
  445.    sigaction(SIGURGENT, &sa, NULL);
  446. #endif
  447.    sa.sa_handler = SIG_IGN;
  448.    /* sa.sa_flags = SA_RESETHAND;    /* Reset to SIG_DFL, not blocked */
  449. #ifndef NO_SIGUSR1
  450.    sigaction(SIGUSR1, &sa, NULL);
  451. #endif
  452.    sa.sa_handler = reapchild;
  453.    sigaction(SIGCHLD, &sa, NULL);
  454.    umask(022);
  455.    openlog("listserv", LOG_PID, LOG_AUTH);
  456.    syslog(LOG_INFO, "Listserv Started");
  457.    f = fopen(PIDFILE, "w");
  458.    if (f == NULL) {
  459.       syslog(LOG_ERR, "Can't open PIDFILE for writing. Aborting.");
  460.       exit(2);
  461.    } /* endif */
  462.    fprintf(f, "%d", getpid());
  463.    fclose(f);
  464.    umask(077);
  465.    while (!done) {
  466.       if (access("msg", 0) == -1 && (stat(MAILFILE, &st) == -1 
  467.       || st.st_size == 0)) {
  468. #ifdef NO_SIGUSR1
  469.          sleep(NO_SIGUSR1);
  470. #else
  471.          if (msgHere == 0) {
  472.        sa.sa_handler = sPau;
  473.        sigaction(SIGUSR1,&sa,NULL);
  474.        pause();
  475.        sa.sa_handler=SIG_IGN;
  476.        sigaction(SIGUSR1,&sa,NULL);
  477.      }
  478. #endif
  479.          continue;
  480.       } /* endif */
  481.       msgHere = 0;
  482.       if ((i = copyMail()) == -1) continue;
  483.       if (i == -2) {
  484.      mailMsg("list-errors", "Unknown error in saveMsg(), see the syslog");
  485.      unlink("msg");
  486.      continue;
  487.       } /* endif */
  488.       if (instring(From, "mailer") != NULL || 
  489.       instring(From, "postmaster") != NULL ||
  490.       instring(From, "listserv") != NULL ||
  491.       instring(From, "root") != NULL ||
  492.       instring(From, "system") != NULL ||
  493.       instring(From, "-request") != NULL ||
  494.       instring(From, "owner-") != NULL) {
  495.          syslog(LOG_INFO,"Message from Mailer-Daemon");
  496.      mailMsg("list-errors", "Trouble");
  497.          unlink("msg");
  498.          continue;
  499.       } /* endif */
  500.       if (strcmp(To, "listserv") == 0)
  501.          { listservCmd(); } else { fwdMsg(); }
  502.    } /* endwhile */
  503.    syslog(LOG_INFO,"Listserv has been terminated");
  504.    time(&endTime); lTodhms(endTime-startTime);
  505.    times(&t);
  506.    t.tms_utime+=t.tms_cutime;
  507.    t.tms_stime+=t.tms_cstime;
  508.    syslog(LOG_INFO,"Total elapsed time: +%dd %02d:%02d:%02d\n",d,h,m,s);
  509.    lTodhms(t.tms_utime/HZ);
  510.    syslog(LOG_INFO,"User CPU time:      +%dd %02d:%02d:%02d\n",d,h,m,s);
  511.    lTodhms(t.tms_stime/HZ);
  512.    syslog(LOG_INFO,"System CPU time:    +%dd %02d:%02d:%02d\n",d,h,m,s);
  513.    lTodhms((t.tms_utime+=t.tms_stime)/HZ);
  514.    syslog(LOG_INFO,"Total CPU time:     +%dd %02d:%02d:%02d\n",d,h,m,s);
  515.    syslog(LOG_INFO,"%% CPU used:  %02.02f%%\n",
  516.              (float)(t.tms_utime/HZ*100)/(float)(endTime-startTime+1));
  517.    closelog();
  518.    unlink(PIDFILE);
  519.    exit(0);
  520. }
  521.