home *** CD-ROM | disk | FTP | other *** search
- /*-------------------------------------------------------------------------
- * Listserv - Unix Mailing List manager (sub-set of FRECP's
- * Bitnet Listserv tool.
- *
- * Copyright (C) 1991,1992 Kimmo Suominen, Christophe Wolfhugel
- *
- * Please read the files COPYRIGHT and AUTHORS for the extended
- * copyrights refering to this file.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 1, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *----------------------------------------------------------------------*/
-
- static char rcsid[] = "@(#)$Id: l.c,v 1.34 93/03/02 22:13:17 wolf Exp $";
-
- #include <stdio.h>
- #include <string.h>
- #include <signal.h>
- #include <time.h>
- #include <unistd.h>
- #include <ctype.h>
- #include <sys/ioctl.h>
- #include <sys/param.h>
- #include <sys/times.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include "conf.h"
- #include "ext.h"
- #include "lp.h"
- #include "str.h"
- #include "popen.h"
- #include "ad.h"
- #include "lc.h"
- #include "messages.h"
- #ifdef FAKESYSLOG
- # include "fakesyslog.h"
- #else
- # include <syslog.h>
- #endif
-
- int Debug = 0;
-
- short subj;
-
- int msgHere = 0, done = 0;
- char listName[64];
- char From[MAXLINE], To[MAXLINE], ReplyTo[MAXLINE];
- char buf[MAXLINE], rcpt[MAXLINE];
- int d, h, m, s;
- long startTime, endTime, msgSize;
- struct tms t;
-
- static int ctr;
-
- void lTodhms(t)
- long t;
- {
- d = t / ( 24 * 3600L );
- h = ( t % ( 24 * 3600L )) / 3600;
- m = ( t % 3600 ) /60;
- s = t % 60;
- }
-
- char *instring(s1, s2)
- char *s1, *s2;
- {
- if ((int)strlen(s2) > (int)strlen(s1)) return(NULL);
- for (; *(s1 + strlen(s2) - 1); s1++)
- if (strncasecmp(s1, s2, strlen(s2)) == 0) return(s1);
- return(NULL);
- }
-
- char *strlwr(s)
- char *s;
- {
- char *p = s;
-
- if (s==NULL) return(NULL);
- for (; *s; s++) *s = tolower(*s);
- return(p);
- }
-
- char *strupr(s)
- char *s;
- {
- char *p = s;
-
- if (s == NULL) return(NULL);
- for (; *s; s++) *s = toupper(*s);
- return(p);
- }
-
- void mailMsg(to, subj)
- char *to, *subj;
- {
- FILE *f, *g;
- char buf[1024];
-
- sprintf(buf, "%s %s", SENDMAIL, to);
- if ((g = l_popen(buf, "w")) == NULL) {
- syslog(LOG_ERR, "mailMsg - popen failed: %m");
- exit(2);
- } /* endif */
- if ((f = fopen("msg","r")) == NULL) {
- syslog(LOG_ERR, "mailMsg - fopen failed: %m");
- exit(2);
- } /* endif */
- fprintf(g, "Subject: %s\n\n", subj);
- while (fgets(buf, sizeof(buf), f) != NULL)
- fputs(buf, g);
- l_pclose(g); fclose(f);
- }
-
- void sendMsg()
- {
- char cmd[MAXLINE + 256], *p;
- int c;
- FILE *f, *h;
-
- #ifdef ADD_REQUEST
- sprintf(cmd, "%s -f%s-request %s", SENDMAIL, listName, rcpt);
- #else
- sprintf(cmd, "%s %s", SENDMAIL, rcpt);
- #endif
- if ((h = l_popen(cmd,"w")) == NULL) {
- syslog(LOG_ERR, "sendMsg - popen: %m");
- exit(2);
- } /* endif */
- if ((f = fopen("msg", "r")) == NULL) {
- syslog(LOG_ERR, "sendMsg - popen: %m");
- exit(2);
- } /* endif */
- while (fgets(buf, sizeof(buf), f) != NULL && buf[0] != '\n') {
- /* if the line is too long, throw the rest away */
- if (index(buf, '\n') == NULL) {
- while ((c = getc(f)) != '\n' && c != EOF)
- continue;
- } /* endif */
- while ((c = getc(f)) == ' ' || c == '\t') {
- p = &buf[strlen(buf)];
- *p++ = ' ';
- if (fgets(p, sizeof(buf) - (p - buf), f) == NULL)
- break;
- } /* endwhile */
- if (!feof(f) && !ferror(f))
- ungetc(c, f);
-
- if (strncasecmp(buf, "Status: ", 8) == 0) continue;
- if (strncasecmp(buf, "X-Envelope-To: ", 15) == 0) continue;
- if (strncasecmp(buf, "X-Listserv-To: ", 15) == 0) continue;
- if (strncasecmp(buf, ">From ", 6) == 0) continue;
- if (strncasecmp(buf, "Return-receipt-to: ", 19) == 0) continue;
- #ifdef STRIP_RECEIVED
- if (strncasecmp(buf, "Received: ", 10) == 0) continue;
- #endif
- if (ReplyTo[0] != 0 && strncasecmp(buf, "Reply-To: ", 10) == 0)
- continue;
- if (*GetErrorsTo() != '\0' && strncasecmp(buf, "Errors-To: ", 11) == 0)
- continue;
- #ifdef ADD_SENDER
- if (strncasecmp(buf, "Sender: ", 8) == 0) continue;
- #endif
- fputs(buf, h);
- /* strcpy(cmd, listName); strupr(cmd);
- fprintf(h, "To: %s Distribution List <%s@%s>\n", cmd, listName, HOST);
- */
- } /* endwhile */
- #ifdef ADD_SENDER
- fputs(versSender, h);
- #endif
- if (*GetErrorsTo() != '\0') fprintf(h, "Errors-To: %s\n", GetErrorsTo());
- if (ReplyTo[0] != 0) fprintf(h, "Reply-To: %s\n", ReplyTo);
- if (subj == 0) fprintf(h, "Subject: <none>\n");
- if (ctr != 0) fprintf(h, "X-Sequence: %d\n", ctr);
- do {
- fputs(buf, h);
- } while (fgets(buf, sizeof(buf), f) != NULL);
- fclose(f); l_pclose(h);
- }
-
- void saveMsg()
- {
- FILE *f, *g;
- long ti;
- struct tm *t;
- int dir = 0, oldfile = 0;
- char cmd[64];
- struct stat st;
-
- time(&ti); t = localtime(&ti); f = fopen("msg","r");
- if (chdir(listName) == -1)
- return;
- else {
- dir = 1;
- sprintf(cmd, "log%02d%02d", t->tm_year, t->tm_mon + 1);
- oldfile = stat(cmd, &st) + 1;
- g = fopen(cmd, "a");
- } /* endif */
- if (!oldfile) {
- fprintf(g, "This digest for list %s has been created on %s\n\n",
- listName, asctime(t));
- fputs("------- THIS IS A RFC934 COMPLIANT DIGEST, YOU CAN BURST IT -------\n\n", g);
- }
- while (fgets(buf, sizeof(buf), f) != NULL && buf[0] != '\n') {
- if (strncmp(buf, "Subject:", 8) == 0 || strncmp(buf, "Date:", 5) == 0)
- fputs(buf, g);
- if (strncmp(buf, "From:", 5) == 0) {
- fprintf(g, "From: %s\n", From);
- if (subj == 0) fprintf(g, "Subject: <none>\n");
- } /* endif */
- strlwr(buf);
- } /* endwhile */
- if (ctr != 0) fprintf(g, "X-Sequence: %d\n", ctr);
- do {
- if (buf[0] == '-') { fprintf(g, "- "); }
- fputs(buf, g);
- } while (fgets(buf, 512, f) != NULL);
- fputs("------- CUT --- CUT --- CUT --- CUT --- CUT --- CUT --- CUT -------\n\n", g);
- fclose(f); fclose(g);
- if (dir == 1) chdir(TULPDIR);
- }
-
- void fwdMsg()
- {
- FILE *f, *g, *h;
- int i;
- char *p;
- char cmd[128];
-
- strcpy(listName, To);
- if (ReadUserList(listName) == -1) {
- syslog(LOG_INFO, "Sending error (list not found)");
- mailMsg("list-errors", "List-Errors");
- unlink("msg"); return;
- } /* endif */
- strcpy(buf, GetReplyTo());
- if (ReplyTo[0] == 0 || instring(buf, ",respect") == NULL) {
- if (strncasecmp(buf, "list", 4) == 0) {
- strcpy(cmd, listName);
- strupr(cmd);
- sprintf(ReplyTo, "%s Distribution List <%s@%s>", cmd, listName, HOST);
- } else if (strncasecmp(buf, "sender", 6) != 0)
- sprintf(ReplyTo, "%s", strtok(buf, ","));
- } /* endif */
- RewindUserList();
- if (strcasecmp(GetSend(), "private") == 0 && !IsUser(From)) {
- syslog(LOG_INFO,
- "Mail to list %s from %s - Refused, this user is not allowed",
- listName, From);
- sprintf(buf, "%s %s", SENDMAIL, strtok(From, " ")); /* NAK to sender */
- if ((g = l_popen(buf, "w")) == NULL) {
- syslog(LOG_ERR, "fwdMsg - popen failed: %m");
- unlink("msg");
- CloseUserList();
- return;
- } /* endif */
- if ((f = fopen("msg", "r")) == NULL) {
- syslog(LOG_ERR, "fwdMsg - fopen failed: %m");
- unlink("msg");
- CloseUserList();
- return;
- } /* endif */
- fprintf(g, TULP_HDRMAILNAK(From, listName));
- fprintf(g, TULP_MAILPRIVATE);
- while (fgets(buf, sizeof(buf), f) != NULL) /* unsent message */
- fputs(buf, g);
- l_pclose(g); fclose(f);
- mailMsg("list-errors", "attempt to send mail by a non subscriber");
- /* to inform list-errors */
- } else if (strcasecmp(GetSend(), "editor") == 0 && !IsEditor(From)) {
- syslog(LOG_INFO,"Mail to list %s from %s - Article to moderate",
- listName, From);
- RewindEditorList();
- if (GetEditor(buf) != NULL) {
- mailMsg(strtok(buf, " "), "Article to moderate");
- } /* endif */
- } else { /* Ok to send */
- strcpy(buf, listName); /* X-Sequence - update listName.n */
- strcat(buf, ".n");
- ctr = 0;
- h = fopen(buf, "r+");
- if (h != NULL) {
- fscanf(h, "%d", &ctr);
- rewind(h); fprintf(h, "%d\n", ++ctr); fclose(h);
- } /* endif */
- syslog(LOG_INFO,"List %s - Msg from %s accepted", listName, From);
- saveMsg(); /* save Msg in log file */
- i = 0; p = rcpt;
- while (GetUser(buf) != NULL) {
- strtok(buf, "\t\r\n ");
- if (((p - rcpt) + strlen(buf)+2) < sizeof(rcpt) && i++ < BATCHSIZE) {
- sprintf(p, "%s ", buf);
- p += strlen(p);
- } else {
- i = 0; p = rcpt;
- sendMsg();
- } /* endif */
- } /* endwhile */
- if (i != 0) sendMsg();
- } /* endif */
- unlink("msg");
- CloseUserList();
- }
-
- int copyMail()
- {
- FILE *h;
- char *p;
- int c;
- struct stat st;
-
- if (access("msg", 0) == -1) {
- winInc();
- if ((h = popen(MAILX, "w")) == NULL) return(-1);
- fprintf(h, "s 1 msg\n");
- fprintf(h, "q\n");
- pclose(h);
- } /* endif */
- if ((h = fopen("msg", "r")) == NULL) return(-1);
- To[0] = 0;
- fstat(fileno(h), &st); msgSize = st.st_size;
- subj = 0; To[0] = ReplyTo[0] = 0;
- while (fgets(buf, sizeof(buf), h) != NULL && buf[0] != '\n') {
- /* if the line is too long, throw the rest away */
- if (index(buf, '\n') == NULL) {
- while ((c = getc(h)) != '\n' && c != EOF)
- continue;
- } /* endif */
- while ((c = getc(h)) == ' ' || c == '\t') {
- p = &buf[strlen(buf) - 1];
- *p++ = ' ';
- if (fgets(p, sizeof(buf) - (p - buf), h) == NULL)
- break;
- } /* endif */
- if (!feof(h) && !ferror(h))
- ungetc(c, h);
- strtok(buf, "\n");
- if (Debug) {
- fprintf(stderr, "Collected line: %s\n", buf);
- } /* endif */
- if (strlen(buf) > MAXLINE) {
- syslog(LOG_ERR, "Header line too long: %s", strtok(buf, ":"));
- fclose(h);
- return(-2);
- } /* endif */
- if (strncmp(buf, "Reply-To: ", 10) == 0) {
- strcpy(ReplyTo, buf + 10);
- } /* endif */
- if (strncmp(buf, "Subject: ", 9) == 0) {
- /* We could save subject here, but we don't need it */
- subj = 1;
- continue;
- } /* endif */
- if (strncmp(buf, "From: ", 6) == 0) {
- /* Usually just one author */
- strcpy(From, buf + 6);
- continue;
- } /* endif */
- if (strncmp(buf, "X-Listserv-To: ", 15) == 0 ) {
- strcpy(To, buf + 15);
- continue;
- } /* endif */
- } /* endwhile */
- adChange(From);
- strlwr(To);
- fclose(h);
- if (To[0] == 0) {
- syslog(LOG_ERR, "Empry X-Listserv-To or not found");
- return(-2);
- } /* endif */
- }
-
- void sTe()
- {
- done = 1;
- }
-
- #ifndef NO_SIGUSR1
- void sPau()
- {
- msgHere = 1;
- }
- #endif
-
- void main(int argn, char **argv)
- {
- struct stat st;
- struct sigaction sa;
- FILE *f;
- int i;
- extern void reapchild();
-
- while ((i = getopt(argn, argv, "d")) != EOF) {
- switch (i) {
- case 'd':
- Debug = 1;
- break;
- default:
- fprintf(stderr,"usage: %s [-d]\n", *argv);
- exit(1);
- } /* endsw */
- } /* endif */
- versInit();
- if (chdir(TULPDIR) == -1) {
- perror("Can't chdir' to TULPDIR. Aborting.");
- exit(2);
- } /* endif */
- setbuf(stdout, NULL); printf("%s: daemon started for %s\n\r", vers, HOST);
- printf("Copyright (C) 1991,1992 Kimmo Suominen, Christophe Wolfhugel\n");
- printf("Listserv comes with ABSOLUTELY NO WARRANTY; for details see\n");
- printf("the GNU General Public License that is furnished with the\n");
- printf("sources of this package.\n");
- if (Debug == 0)
- if (fork()) exit (0); /* Dissociate us from tty */
- times(&t);
- time(&startTime);
- nice(NICENESS);
- if (Debug == 0) {
- freopen("/dev/null", "w", stdout);
- freopen("/dev/null", "w", stderr);
- close(fileno(stdin));
- setpgrp();
- } /* endif */
- sigemptyset(&sa.sa_mask);
- #ifdef SA_RESTART
- sa.sa_flags = SA_RESTART; /* Restart system calls? SA_RESTART */
- /* Children? SA_NOCLDWAIT, SA_NOCLDSTOP */
- #else
- sa.sa_flags = 0;
- #endif
- sa.sa_handler = sTe;
- sigaction(SIGTERM, &sa, NULL);
- #ifdef SIGURGENT
- sigaction(SIGURGENT, &sa, NULL);
- #endif
- sa.sa_handler = SIG_IGN;
- /* sa.sa_flags = SA_RESETHAND; /* Reset to SIG_DFL, not blocked */
- #ifndef NO_SIGUSR1
- sigaction(SIGUSR1, &sa, NULL);
- #endif
- sa.sa_handler = reapchild;
- sigaction(SIGCHLD, &sa, NULL);
- umask(022);
- openlog("listserv", LOG_PID, LOG_AUTH);
- syslog(LOG_INFO, "Listserv Started");
- f = fopen(PIDFILE, "w");
- if (f == NULL) {
- syslog(LOG_ERR, "Can't open PIDFILE for writing. Aborting.");
- exit(2);
- } /* endif */
- fprintf(f, "%d", getpid());
- fclose(f);
- umask(077);
- while (!done) {
- if (access("msg", 0) == -1 && (stat(MAILFILE, &st) == -1
- || st.st_size == 0)) {
- #ifdef NO_SIGUSR1
- sleep(NO_SIGUSR1);
- #else
- if (msgHere == 0) {
- sa.sa_handler = sPau;
- sigaction(SIGUSR1,&sa,NULL);
- pause();
- sa.sa_handler=SIG_IGN;
- sigaction(SIGUSR1,&sa,NULL);
- }
- #endif
- continue;
- } /* endif */
- msgHere = 0;
- if ((i = copyMail()) == -1) continue;
- if (i == -2) {
- mailMsg("list-errors", "Unknown error in saveMsg(), see the syslog");
- unlink("msg");
- continue;
- } /* endif */
- if (instring(From, "mailer") != NULL ||
- instring(From, "postmaster") != NULL ||
- instring(From, "listserv") != NULL ||
- instring(From, "root") != NULL ||
- instring(From, "system") != NULL ||
- instring(From, "-request") != NULL ||
- instring(From, "owner-") != NULL) {
- syslog(LOG_INFO,"Message from Mailer-Daemon");
- mailMsg("list-errors", "Trouble");
- unlink("msg");
- continue;
- } /* endif */
- if (strcmp(To, "listserv") == 0)
- { listservCmd(); } else { fwdMsg(); }
- } /* endwhile */
- syslog(LOG_INFO,"Listserv has been terminated");
- time(&endTime); lTodhms(endTime-startTime);
- times(&t);
- t.tms_utime+=t.tms_cutime;
- t.tms_stime+=t.tms_cstime;
- syslog(LOG_INFO,"Total elapsed time: +%dd %02d:%02d:%02d\n",d,h,m,s);
- lTodhms(t.tms_utime/HZ);
- syslog(LOG_INFO,"User CPU time: +%dd %02d:%02d:%02d\n",d,h,m,s);
- lTodhms(t.tms_stime/HZ);
- syslog(LOG_INFO,"System CPU time: +%dd %02d:%02d:%02d\n",d,h,m,s);
- lTodhms((t.tms_utime+=t.tms_stime)/HZ);
- syslog(LOG_INFO,"Total CPU time: +%dd %02d:%02d:%02d\n",d,h,m,s);
- syslog(LOG_INFO,"%% CPU used: %02.02f%%\n",
- (float)(t.tms_utime/HZ*100)/(float)(endTime-startTime+1));
- closelog();
- unlink(PIDFILE);
- exit(0);
- }
-