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