Article View: comp.mail.misc
Article #1808Re: ListServer software under Unix
From: Timothy Murphy
Date: Sat, 13 Oct 1990 20:33
Date: Sat, 13 Oct 1990 20:33
693 lines
17043 bytes
17043 bytes
In <90278.183340QQ11@LIVERPOOL.AC.UK> QQ11@LIVERPOOL.AC.UK writes:
>In article <1990Oct1.214010.4218@maths.tcd.ie>, tim@maths.tcd.ie (Timothy
>Murphy) says:
>>
>>I wonder if someone could point me to software
>>to run an archive or list server under Unix.
>There are UK sites which run info-servers which may do what you want.
>I found the following in the anonymous ftp site list:
>elroy.cs.iastate.edu 129.186.3.15 mail servers
>This may or may not be any use...
Thanks.
I did in fact try the mail-server at this address
(csdserv@cs.iostate.edu) as described by Dave Shaver
(shaver@elroy.cs.iostate.edu) but had no luck --
the user was unknown at the given address.
Maybe someone can point out the correct user/address.
Nelson Beebe (of TeX and Plot79 fame) kindly sent me
the following list-server software.
I'm posting it 'as-is',
since while I compiled it without problem on a Sun SparcStation,
it did not in fact do what I wanted,
which is perhaps better described as an archive-server --
that is, to reply to appropriate e-mail requests
by mailing back files.
I'm posting the list-server from Beebe
because I received many requests for it,
a couple of whom suggested I should post it.
Incidentally, I don't think Nelson Beebe uses it for his TeX archive --
that runs on an IBM, using the usual LISTSERV software, I believe.
I think this list-server could easily be modified to do
what I want.
If I don't get an appropriate program from Iowa (iostate, as above),
I'll try that.
But there are some 6 list-server programs available at iostate
so hopefully at least one of these will do the trick:
#! /bin/sh
# This is a shell archive. Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file". To overwrite existing
# files, type "sh file -c". You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g.. If this archive is complete, you
# will see the following message at the end:
# "End of shell archive."
# Contents: Makefile commands.c listserv.h main.c str.c subscribe.c
# Wrapped by tim@lanczos on Sat Oct 13 19:14:54 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Makefile' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(473 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
XRM = rm -f
X
XCFLAGS = -g
X
Xall: listserv
X
Xinstall: all
X install -c -m 2711 -g mail listserv /usr/mail
X
Xlistserv: main.o commands.o subscribe.o str.o
X cc -O -o listserv main.o commands.o subscribe.o str.o
X
Xmain.o: main.c listserv.h
X cc -c $(CFLAGS) main.c
X
Xcommands.o: commands.c listserv.h
X cc -c $(CFLAGS) commands.c
X
Xsubscribe.o: subscribe.c listserv.h
X cc -c $(CFLAGS) subscribe.c
X
Xstr.o: str.c
X cc -c $(CFLAGS) str.c
X
Xclean:
X $(RM) *.o
X
Xveryclean: clean
X $(RM) listserv
X
END_OF_FILE
if test 473 -ne `wc -c <'Makefile'`; then
echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'commands.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'commands.c'\"
else
echo shar: Extracting \"'commands.c'\" \(1638 characters\)
sed "s/^X//" >'commands.c' <<'END_OF_FILE'
X#include "listserv.h"
X
Xextern FILE *msg;
Xextern FILE *mailer;
X
Xsendhelp(from,request)
Xchar *from, *request;
X {
X printf("called sendhelp with %s %s\n", from, request);
X callmailer("", from, request);
X mailcat(HELPFILE,"");
X pclose(mailer);
X return;
X }
X
Xlisthelp(from,grp,request)
Xchar *from,*grp,*request;
X {
X char tmp[128];
X printf("called listhelp with %s %s %s\n", from,grp,request);
X
X sprintf(tmp,"%s/%s.info", SERVDIR, grp);
X if (access(tmp,R_OK) != 0)
X {
X callmailer("", from, request);
X fprintf(mailer,"The mailing list \"%s\" could not be found.\n",
X grp);
X fprintf(mailer,"You may use the INDEX command to get a listing\n");
X fprintf(mailer,"of available mailing lists.\n");
X fflush(mailer);
X pclose(mailer);
X return;
X }
X
X callmailer("", from, request);
X fprintf(mailer,"Mailing list \"%s\":\n", grp);
X mailcat(tmp,"\t");
X pclose(mailer);
X return;
X }
X
Xsendindex(from,request,l)
Xchar *from,*request;
Xint l;
X {
X FILE *ls;
X char tmp[128];
X char buf[128];
X int i;
X printf("called sendindex with %s %s %d\n", from,request,l);
X
X sprintf(tmp,"cd %s; ls *.info | sed -e 's/.info//", SERVDIR);
X ls = popen(tmp,"r");
X if (ls == NULL)
X {
X perror(tmp);
X exit(1);
X }
X callmailer("", from, request);
X fprintf(mailer,"Index of mailing lists\n");
X
X /* read the result of the ls */
X while (fgets(tmp, sizeof(tmp), ls))
X {
X while (tmp[(i=strlen(tmp)-1)] == '\n')
X tmp[i] = '\0';
X fprintf(mailer, "%s\n", tmp);
X
X /* if he wanted the long listing, cat the .info file */
X if (l)
X {
X sprintf(buf, "%s/%s.info", SERVDIR, tmp);
X mailcat(buf,"\t");
X fprintf(mailer, "\n");
X }
X }
X pclose(ls);
X pclose(mailer);
X return;
X }
X
END_OF_FILE
if test 1638 -ne `wc -c <'commands.c'`; then
echo shar: \"'commands.c'\" unpacked with wrong size!
fi
# end of 'commands.c'
fi
if test -f 'listserv.h' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'listserv.h'\"
else
echo shar: Extracting \"'listserv.h'\" \(236 characters\)
sed "s/^X//" >'listserv.h' <<'END_OF_FILE'
X#include <stdio.h>
X#include <strings.h>
X#include <ctype.h>
X#include <sys/file.h>
X
X#define MAILER "/usr/lib/sendmail"
X#define HELPFILE "/usr/mail/maillists/HELP"
X#define SERVDIR "/usr/mail/maillists"
X#define LOGFILE "/var/log/listserv"
X
END_OF_FILE
if test 236 -ne `wc -c <'listserv.h'`; then
echo shar: \"'listserv.h'\" unpacked with wrong size!
fi
# end of 'listserv.h'
fi
if test -f 'main.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'main.c'\"
else
echo shar: Extracting \"'main.c'\" \(4607 characters\)
sed "s/^X//" >'main.c' <<'END_OF_FILE'
X#include "listserv.h"
X
XFILE *mailer;
XFILE *logfile;
X
Xmain(argc,argv)
Xint argc;
Xchar **argv;
X {
X char from[256];
X char buf[BUFSIZ];
X char grp[64];
X char dat[64];
X char *p;
X int i;
X int gotcommand = 0;
X int inheader;
X
X /* gotta have some default if the From: line is missing */
X strcpy(from, "Postmaster");
X
X inheader = 1;
X while (fgets(buf,BUFSIZ,stdin) != NULL)
X {
X /* drop trailing newline */
X while (buf[(i=strlen(buf)-1)] == '\n')
X buf[i] = '\0';
X
X /* drop trailing blanks */
X p = buf + (strlen(buf) - 1);
X while (p && *p && p >= buf && isspace(*p))
X *p-- = '\0';
X
X /* deblank beginning of line */
X p = buf;
X while (p && *p && isspace(*p))
X p++;
X if (p != buf)
X strcpy(buf, p);
X
X if (strlen(buf) == 0) /* blank line ends header */
X {
X inheader = 0;
X continue;
X }
X
X /*
X get the From: line so we can return the answer
X
X Note that we DON'T check that we're in the header when
X picking up the From: line; that's so that we'll take the
X last from line we encounter which makes it handle
X forwarded messages correctly.
X */
X if (strncasecmp(buf,"From: ",6) == 0)
X {
X strcpy(from, &buf[6]);
X cleanup(from);
X continue;
X }
X
X /*
X don't look for commands in the header
X */
X if (inheader)
X continue;
X
X /* avoid mail loops - ignore requests from ourself! */
X if (!strncasecmp(from, "listserv", 8))
X {
X printf("I refuse to talk to myself.\n");
X exit(0);
X }
X
X /* force to lower case and scan for commands */
X p = buf;
X while (p && *p)
X {
X if (isupper(*p))
X *p = tolower(*p);
X p++;
X }
X
X /* log the request */
X logfile = fopen(LOGFILE,"a");
X if (logfile != NULL)
X {
X long clock = time(0);
X strcpy(dat,ctime(&clock));
X /* drop trailing newline */
X while (dat[(i=strlen(dat)-1)] == '\n')
X dat[i] = '\0';
X printf("logfile: %s|%s|%s\n", dat, from, buf);
X fprintf(logfile,"%s|%s|%s\n", dat, from, buf);
X fflush(logfile);
X fclose(logfile);
X }
X else
X perror(LOGFILE);
X
X if (!strncasecmp(buf,"add ", 4)
X || !strncasecmp(buf,"subscribe ", 10))
X {
X gotcommand++;
X subscription(from,buf,1);
X continue;
X }
X
X if (!strncasecmp(buf,"delete ", 7)
X || !strncasecmp(buf,"unsubscribe ", 12))
X {
X gotcommand++;
X subscription(from,buf,0);
X continue;
X }
X
X if (!strcasecmp(buf,"index")
X || !strcasecmp(buf,"longindex"))
X {
X gotcommand++;
X sendindex(from,buf,!strcasecmp(buf,"longindex"));
X continue;
X }
X
X if (!strcasecmp(buf,"help"))
X {
X gotcommand++;
X sendhelp(from,buf);
X continue;
X }
X
X if (!strncasecmp(buf,"help ",5))
X {
X gotcommand++;
X sscanf(buf,"%*s%s", grp);
X listhelp(from,grp,buf);
X continue;
X }
X }
X if (gotcommand == 0)
X sendhelp(from, "indecipherable");
X }
X
Xcallmailer(redirect, toaddr, request)
Xchar *redirect, *toaddr, *request;
X {
X char cbuf[BUFSIZ];
X
X printf("callmailer \"%s\",\"%s\",\"%s\"\n", redirect, toaddr, request);
X
X strcpy(cbuf, MAILER);
X strcat(cbuf, " -fPostmaster@ucsd.edu");
X strcat(cbuf, " -F\"Mailing List Processor\"");
X strcat(cbuf, " -t -oi");
X strcat(cbuf, " "); strcat(cbuf, redirect);
X mailer = popen(cbuf,"w");
X printf("mailer popen '%s'\n", cbuf);
X if (mailer == NULL)
X {
X perror(cbuf);
X exit(1);
X }
X fprintf(mailer,"From: postmaster@ucsd.edu (Mailing List Processor)\n");
X fprintf(mailer,"To: %s\n", toaddr);
X fprintf(mailer,"Subject: Re: your LISTSERVE request \"%s\"\n", request);
X fprintf(mailer,"\n");
X }
X
Xmailcat(mfname,prefix)
Xchar *mfname, *prefix;
X {
X FILE *mf;
X char buf[BUFSIZ];
X
X printf("mailcat \"%s\", \"%s\"\n", mfname, prefix);
X
X mf = fopen(mfname,"r");
X if (mf == NULL)
X {
X perror(mfname);
X fprintf(mailer,"This should have been the contents of\n");
X fprintf(mailer,"file '%s' but it's missing!\n",mfname);
X return;
X }
X
X /* copy the message file into the mailer */
X while (fgets(buf,BUFSIZ,mf) != NULL)
X {
X fputs(prefix,mailer);
X fputs(buf,mailer);
X }
X fclose(mf);
X return;
X }
X
Xcleanup(from)
Xchar *from;
X {
X char *p, *q;
X
X printf("cleanup \"%s\"\n", from);
X
X while (p = index(from,'~'))
X *p = 'X';
X
X while (p = index(from,'/'))
X *p = 'X';
X
X while (p = index(from,'|'))
X *p = 'X';
X
X /* elide stuff in parenthesis */
X if (p = index(from,'('))
X {
X if ( (q=index(from,')')) == NULL)
X {
X /* zap the from line; it's invalid */
X *p = '\0';
X return;
X }
X strcpy(p, q+1);
X }
X
X if (p = index(from,'<'))
X {
X if ( (q=index(from,'>')) == NULL)
X {
X /* zap the from line; it's invalid */
X *p = '\0';
X return;
X }
X *q = '\0';
X strcpy(from, p+1);
X }
X
X /* drop trailing blanks */
X p = from + (strlen(from) - 1);
X while (p && *p && p >= from && isspace(*p))
X *p-- = '\0';
X }
END_OF_FILE
if test 4607 -ne `wc -c <'main.c'`; then
echo shar: \"'main.c'\" unpacked with wrong size!
fi
# end of 'main.c'
fi
if test -f 'str.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'str.c'\"
else
echo shar: Extracting \"'str.c'\" \(487 characters\)
sed "s/^X//" >'str.c' <<'END_OF_FILE'
X#include <ctype.h>
X
Xstrcasecmp(a,b)
Xchar *a, *b;
X {
X char *p;
X p = a;
X while (p && *p)
X {
X if (isupper(*p))
X *p = tolower(*p);
X p++;
X }
X p = b;
X while (p && *p)
X {
X if (isupper(*p))
X *p = tolower(*p);
X p++;
X }
X return(strcmp(a,b));
X }
Xstrncasecmp(a,b,n)
Xchar *a, *b;
Xint n;
X {
X char *p;
X p = a;
X while (p && *p)
X {
X if (isupper(*p))
X *p = tolower(*p);
X p++;
X }
X p = b;
X while (p && *p)
X {
X if (isupper(*p))
X *p = tolower(*p);
X p++;
X }
X return(strncmp(a,b,n));
X }
END_OF_FILE
if test 487 -ne `wc -c <'str.c'`; then
echo shar: \"'str.c'\" unpacked with wrong size!
fi
# end of 'str.c'
fi
if test -f 'subscribe.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'subscribe.c'\"
else
echo shar: Extracting \"'subscribe.c'\" \(3479 characters\)
sed "s/^X//" >'subscribe.c' <<'END_OF_FILE'
X#include "listserv.h"
X
Xextern FILE *msg;
Xextern FILE *mailer;
X
Xsubscription(from,command,add)
Xchar *from,*command;
Xint add;
X {
X FILE *list;
X FILE *listtmp;
X char grp[256];
X char adr[256];
X char tmp[256];
X char buf[BUFSIZ];
X int del = 0;
X int i;
X
X printf("subscription %s %s %d\n", from, command, add);
X
X i = sscanf(command,"%s%s%s", tmp, adr, grp);
X if (i < 2 || i > 3)
X {
X callmailer("", from, command);
X fprintf(mailer,"Your command\n");
X fprintf(mailer,"\t%s\n", command);
X fprintf(mailer,"could not be understood. Correct syntax is\n");
X fprintf(mailer,"\tADD listname\n");
X fprintf(mailer,"\tADD mailbox listname\n");
X fprintf(mailer,"\tDELETE listname\n");
X fprintf(mailer,"\tDELETE mailbox listname\n");
X fflush(mailer);
X pclose(mailer);
X return(-1);
X }
X
X if (i == 2)
X {
X strcpy(grp, adr);
X strcpy(adr, from);
X }
X
X cleanup(grp);
X cleanup(adr);
X
X sprintf(tmp,"%s/%s.info", SERVDIR, grp);
X if (access(tmp,R_OK) != 0)
X {
X callmailer("", from, "");
X fprintf(mailer,"The mailing list \"%s\" could not be found.\n",
X grp);
X fprintf(mailer,"You may use the INDEX command to get a listing\n");
X fprintf(mailer,"of available mailing lists.\n");
X fflush(mailer);
X pclose(mailer);
X return(-1);
X }
X
X strcpy(tmp, SERVDIR);
X strcat(tmp, "/");
X strcat(tmp, grp);
X if (add)
X {
X list = fopen(tmp, "a");
X if (list == NULL)
X {
X callmailer("Postmaster", from, "");
X fprintf(mailer,"Error[1] processing request. Please try later.\n");
X fprintf(mailer,">%s\n", command);
X fflush(mailer);
X pclose(mailer);
X return(-1);
X }
X flock(fileno(list), LOCK_EX);
X fprintf(list, "%s\n", adr);
X fflush(list);
X flock(fileno(list), LOCK_UN);
X fclose(list);
X }
X else
X {
X del = 0;
X list = fopen(tmp, "r");
X if (list == NULL)
X {
X callmailer("Postmaster", from, "");
X fprintf(mailer,"Error[2] processing request. Please try later.\n");
X fprintf(mailer,">%s\n", command);
X fflush(mailer);
X pclose(mailer);
X return(-1);
X }
X flock(fileno(list), LOCK_EX);
X fprintf(list, "%s\n", adr);
X
X strcpy(tmp, SERVDIR);
X strcat(tmp, "/");
X strcat(tmp, grp);
X strcat(tmp, ".tmp");
X listtmp = fopen(tmp, "w");
X if (listtmp == NULL)
X {
X callmailer("Postmaster", from, "");
X fprintf(mailer,"Error[3] processing request. Please try later.\n");
X fprintf(mailer,">%s\n", command);
X fflush(mailer);
X pclose(mailer);
X return(-1);
X }
X /* copy the list, omitting the one address */
X while (fgets(buf, sizeof(buf), list))
X {
X buf[strlen(buf)-1] = '\0';
X if (strcasecmp(buf, adr))
X {
X fputs(buf, listtmp);
X fputs("\n", listtmp);
X }
X else
X del++;
X }
X fflush(listtmp);
X fclose(listtmp);
X
X /* replace the old list with the shortened one */
X strcpy(buf, SERVDIR);
X strcat(buf, "/");
X strcat(buf, grp);
X unlink(buf); /* delete original file */
X rename(tmp, buf); /* put updated one in place */
X flock(fileno(list), LOCK_UN); /* release lock */
X }
X
X if (strcmp(from, adr))
X {
X callmailer(adr, from, command);
X fprintf(mailer,"Per request by %s\n", from);
X }
X else
X {
X callmailer("", from, command);
X fprintf(mailer,"Per your request\n");
X }
X fprintf(mailer,"\t\"%s\"\n", command);
X if (add)
X fprintf(mailer,"'%s' was ADDED to the '%s' mailing list.\n",
X adr, grp);
X else
X if (del)
X fprintf(mailer,
X "'%s' was DELETED from the '%s' mailing list.\n",
X adr, grp);
X else
X fprintf(mailer,
X "'%s' was NOT FOUND on the '%s' mailing list.\n",
X adr, grp);
X fflush(mailer);
X pclose(mailer);
X }
END_OF_FILE
if test 3479 -ne `wc -c <'subscribe.c'`; then
echo shar: \"'subscribe.c'\" unpacked with wrong size!
fi
# end of 'subscribe.c'
fi
echo shar: End of shell archive.
exit 0
--
Timothy Murphy
e-mail: tim@maths.tcd.ie
Technical Details
Message-ID:
<1990Oct13.203358.7906@maths.tcd.ie>Path:
arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!sdd.hp.com!wuarchive!mit-eddie!bloom-beacon!eru!hagbard!sunic!mcsun!ukc!tcdcs!maths.tcd.ie!timReferences:
<1990Oct1.214010.4218@maths.tcd.ie> <90278.183340QQ11@LIVERPOOL.AC.UK>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!sdd.hp.com!wuarchive!mit-eddie!bloom-beacon!eru!hagbard!sunic!mcsun!ukc!tcdcs!maths.tcd.ie!tim From: tim@maths.tcd.ie (Timothy Murphy) Newsgroups: comp.mail.misc Subject: Re: ListServer software under Unix Message-ID: <1990Oct13.203358.7906@maths.tcd.ie> Date: 13 Oct 90 20:33:58 GMT References: <1990Oct1.214010.4218@maths.tcd.ie> <90278.183340QQ11@LIVERPOOL.AC.UK> Organization: Dept. of Maths, Trinity College, Dublin, Ireland. Lines: 693