home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume1
/
digest
< prev
next >
Wrap
Internet Message Format
|
1986-11-30
|
35KB
From: cbosgd!plus5!hokey (Hokey)
Date: 10 Mar 85 16:15:47 CST (Sun)
To: moderators@cbosgd.ATT.UUCP
Subject: shar of digest software
# This is a shell archive. Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by hokey on Sun Mar 10 16:07:28 CST 1985
# Contents: OLD/ Digest/ Digest/README Digest/digest.c aliases request inbox
# hdr.mail hdr.news submit digest.info
echo mkdir - OLD
mkdir OLD
chmod u=rwx,g=rwx,o=rx OLD
echo mkdir - Digest
mkdir Digest
chmod u=rwx,g=rwx,o=rx Digest
echo x - Digest/README
sed 's/^@//' > "Digest/README" <<'@//E*O*F Digest/README//'
This program is used to build ARPA-style digests from a file full of
UNIX mail messages. The messages must have the standard UNIX "From"
line (the one with no colon after the "From"). Features of the program
are:
+ Automatic issue number maintenance
+ All letters with same subject grouped together in digest
+ Any letter with "Administrivia" as the subject will
always be first in the digest (these are usually messages
from the moderator).
Basically, here's what you do to set up a mailing list and everything
from scratch. This assumes that you have 4.2BSD and sendmail. The
strategy here is to make everything controllable by an average user,
who does not have super-user privileges. This method will let the user
maintain the list of people to send the digest to. The system aliases
file DOES NOT have to be rebuilt whenever the mailing list changes.
1. Create a directory in which you will keep all the digest materials.
This directory should be searchable by everyone; you can make sure of
this by using the command "chmod a+x directory-name". For the purposes
of discussion, we will call this directory "/mydir/digest".
2. Change into your digest directory. Create a file to receive incoming
mail in. This file should be world-writeable, so "chmod a+w filename".
For the purposes of this discussion, we will call the file
"/mydir/digest/inbox".
3. Create another file, and put the list of all people you will be
sending the digest to in it. The names should be separated by commas,
continuation lines should start with a tab. An example is shown below.
Personally, I find it easiest if you make each letter of the alphabet
start on a new line; this makes it easy to keep the aliases in
alphabetical order. For the purpose of this discussion, we will call
this file "mydir/digest/aliases".
4. Now have the system administrator place the following lines in
the system aliases file (/usr/lib/aliases):
Digest-Name-Request:your_login_name
Digest-Name:/mydir/digest/inbox
Digest-Name-People: :include:/mydir/digest/aliases
5. Now, create another file in your digest directory. This file must be
called "digest.info". Into this file, you should put the following
lines:
Name-of-the-digest # omit the word "Digest"
Your-Host-Name # Where the digest lives
Your-Login-Name # Who sends the digest
Digest-Name-People # Who the digest is sent to
Volume N : Issue M # Maintained automatically
Day, dd Mon yy hh:mm:ss tzn # Maintained automatically
----------------
EXAMPLE
----------------
I run a digest called "Purdue-Networking-Digest". Our local network
here is called "ECN", and my mailing address is "davy@ECN". To submit to
the digest, people send to "Purdue-Networking@ECN". To send mail to me,
they send to "Purdue-Networking-Request@ECN". I mail the digest out to
"Network-People@ECN". Our system aliases file contains (my login is "davy"):
Purdue-Networking-Request:davy
Purdue-Networking:/e/davy/digest/inbox
Network-People: :include:/e/davy/digest/aliases
The file "/e/davy/digest/aliases" contains:
aak@CS-Mordred,aaz@Pucc-I,abe@Pucc-J,abv@Pucc-H,ac4@Pucc-H,ace@ECN,
acu@Pucc-J,ad0@Pucc-I,ad3@Pucc-H,aeh@Pucc-H,aeq@Pucc-H,aex@Pucc-I,
afc@Pucc-I,ag5@Pucc-K,agc@Pucc-I,agd@Pucc-I,agj@Pucc-I,
beachy@ECN,buhrt@ECN,bv@ECN,
cak@CS-Mordred,cca@Physics,crl@Physics,cvu@Pucc-K,
d4a@Pucc-H,davy@ECN,devi@Physics,droms@CS-Merlin,dwm@ECN,
gjo@Pucc-H,gml@Pucc-H,
hal@Physics,hammonds@ECN,hisao@Physics,hzn@Pucc-E,
jad@CS-Mordred,jamesl@ECN,jtk@CS-Mordred,jump@ECN,
k31@Pucc-H,kcs@CS-Mordred,kg9s@ECN,kurmas@ECN,
lewie@ECN,lq4@ECN,
mahler@ECN,mckay@ECN,mhs@Physics,miller@ECN,mj@ECN,
pam@CS-Mordred,
rgn@Pucc-D,rhs@ECN,rjs@ECN,rl0@Pucc-E,rsk@ECN,ruan@CS-Arthur,
simmons@ECN,steve@ECN,stirling@ECN,
tth@ECN,
wb9vxy@ECN,wd9get@ECN,westerm@ECN,wn9nbt@ECN
Finally, my "digest.info" file contains:
Purdue-Networking
ECN
Dave Curry (The Moderator) <davy@ECN>
Network-People@ECN
Volume 1 : Issue 1
Mon, 3 Dec 84 07:31:41 EST
The digest program will automatically maintain the Issue Number (you
must change the Volume Number by hand) and the date. The date is always
the date of the most recent digest created.
----------------
END OF EXAMPLE
----------------
6. Now, compile the digest program. This can be done with the command
"cc -O -s -o digest digest.c".
7. When people send mail to "Digest-Name@Host", it will be placed into
the "/mydir/digest/inbox" file. When you think there are enough letters
to make a digest, type the following commands:
cp inbox digest.input
cp /dev/null inbox
digest
/usr/lib/sendmail -t < digest.output
cp digest.output archivedir/issuenumber
Obviously, the last step is optional, and should only be performed if
you want to maintain an archive of the digests (a nice thing to do).
@//E*O*F Digest/README//
chmod u=rw,g=rw,o=r Digest/README
echo x - Digest/digest.c
sed 's/^@//' > "Digest/digest.c" <<'@//E*O*F Digest/digest.c//'
/*
* digest - create digests of mail messages
*
* This program uses the file "digest.info" to figure out what issue
* of the digest it is making. The format of this file is:
*
* Name of the List # leave out the word "digest"
* Host # the host where the digest lives
* From # who sends the digest out
#ifdef OLD
* To # who the list is sent to
#endif OLD
* Volume # Volume XX : Issue XXX
* Date # Day, dd Mon yy hh:mm:ss timezone
*
* The file "digest.input" should contain a set of mail messages. These
* will be read into memory and a list of "Today's Topics" generated
* from the subject lines. The messages will then be sorted so that
* all the messages on the same topic come out together. Any message
* whose first word in the subject line is "Administrivia" will be
* guaranteed to come out at the top of the list. The digest will be
* left in the file "<Volume>.<Issue>".
*
* PROBLEM: sorting the messages to get all the same topic seems to
* work fairly well. After getting them together, we sort each
* topic back into original arrival order. The problem arises
* when someone changes the subject line on you. If it is
* alphabetically before the original subject line, then these
* messages will come before the originals. This shouldn't
* occur too often though.
*
* Special thanks to Jon Solomon who sent me his TELECOM digest generating
* program. I swiped a lot of ideas from it in writing this one.
*
* David A. Curry
* decvax!pur-ee!davy
* ecn.davy@purdue
*
* March, 1985: {ihnp4,cbosgd,seismo}plus5!hokey (Hokey)
*
* I'll take credit for any bugs.
*
* Conversational output and "progress reports" now goes to stderr.
*
* Digest output is now saved to a file named "<Volume>.<Issue>". This
* name is echoed to stdout. Makes it easier to archive files and send
* the digest to news and mail.
*
* The To: line has been removed, to facilitate sending the output to news
* and mail, by prepending the appropriate header info to the file.
*
* If OLD is defined, it behaves as it used to.
*
* I removed the code to munge (I like a final "e") local names to fully
* qualified names because it should be done by the mailer. So There.
*
* If BSD42 is not defined, the program will compile on a USG version of Unix.
*/
#include <sys/types.h>
#ifdef BSD42
#include <sys/timeb.h>
#else ~BSD42
#define index=strchr
#endif BSD42
#include <sys/time.h>
#include <ctype.h>
#include <stdio.h>
#define HEAD1 27 /* Field width of first third */
#define HEAD2 20 /* Field width of second third */
#define HEAD3 21 /* Field width of last third */
#define DATELEN 14 /* Amount of date to put in hdr */
#define LINELEN 70 /* Length of an average line */
#define MAXMSGS 32 /* Maximum number of msgs/digest*/
#define LINESIZE 128 /* Maximum line size */
#define LISTINFO "digest.info" /* Information file name */
#define LISTINPUT "digest.input" /* Input file name */
char ListOutput[32]; /* Output file name */
/*
* Message structure. We read through the input file and fill one of
* these in for each message. The To, Cc, From, Date, and Subject
* point to the fields of the same names from the message. The
* "sortstring" is a copy of the subject string with all whitespace
* deleted and all letters in lower case. The messageaddr is the
* seek position in the file where the message body starts, and
* messagelength is how long the message is.
*/
struct message {
char *To;
char *Cc;
char *From;
char *Date;
char *Subject;
char *sortstring;
long messageaddr;
long messagelength;
} messages[MAXMSGS];
/*
* List structure. Contains the information from the LISTINFO file.
*/
struct listinfo {
char *Title;
char *Host;
char *From;
#ifdef OLD
char *To;
#endif OLD
char *Volline;
char *Dateline;
} listinfo;
FILE *input;
FILE *output;
int volume_number; /* The volume number */
int issue_number; /* The issue number */
int nmessages = 0; /* Number of messages */
int digestsize = 0; /* Size of digest in bytes */
char *index(), *malloc(), *safter(), *nospace(), *getline();
main()
{
/*
* Read the list information file and update the
* issue number and date strings.
*/
get_list_info();
inc_volume_and_date();
fprintf(stderr, "Assembling %s Digest %s (%.*s)\n", listinfo.Title, listinfo.Volline, DATELEN, listinfo.Dateline);
fprintf(stderr, "Scanning and sorting messages for topic lines.\n");
/*
* Scan the message file for subject strings and
* sort the messages to get all the messages for
* each topic next to each other.
*/
scan_messages();
sort_messages();
sprintf(ListOutput, "%d.%d", volume_number, issue_number);
fprintf(stderr, "Writing %s Digest to \"%s\"\n", listinfo.Title, ListOutput);
/*
* Print the digest header, put the messages
* in the digest.
*/
do_digest_header();
read_messages();
fprintf(stderr, "The digest is %d characters long in %d messages.\n", digestsize, nmessages);
/*
* Put out the new list information.
*/
put_list_info();
fprintf(stdout, "%s", ListOutput);
exit(0);
}
/*
* get_list_info - reads in the LISTINFO file.
*/
get_list_info()
{
FILE *fp;
int incomplete;
if ((fp = fopen(LISTINFO, "r")) == NULL) {
fprintf(stderr, "digest: cannot open \"%s\" for reading.\n", LISTINFO);
exit(1);
}
incomplete = 0;
if ((listinfo.Title = getline(fp)) == NULL)
incomplete++;
if ((listinfo.Host = getline(fp)) == NULL)
incomplete++;
if ((listinfo.From = getline(fp)) == NULL)
incomplete++;
#ifdef OLD
if ((listinfo.To = getline(fp)) == NULL)
incomplete++;
#endif OLD
if ((listinfo.Volline = getline(fp)) == NULL)
incomplete++;
if ((listinfo.Dateline = getline(fp)) == NULL)
incomplete++;
fclose(fp);
/*
* Error-check. Not too sophisicated, but then you're
* supposed to know what you're doing anyway.
*/
if (incomplete) {
fprintf(stderr, "digest: incomplete or badly formatted \"%s\" file.\n", LISTINFO);
fprintf(stderr, "Proper format:\n");
fprintf(stderr, "\tTitle\n\tHost\n\tFrom\n");
#ifdef OLD
fprintf(stderr, "\tTo\n");
#endif OLD
fprintf(stderr, "\tVolline\n\tDateline\n");
exit(1);
}
}
/*
* inc_volume_and_date - update the volume/issue string and get a new date.
*/
inc_volume_and_date()
{
char *msgdate();
register char *volline, *colon;
if ((volline = malloc(strlen(listinfo.Volline)+1)) == NULL) {
fprintf(stderr, "digest: out of memory.\n");
exit(1);
}
/*
* Volume numbers get changed by hand.
*/
volume_number = atoi(safter(listinfo.Volline, "Volume "));
issue_number = atoi(safter(listinfo.Volline, " Issue ")) + 1;
if ((colon = index(listinfo.Volline, ':')) != NULL)
*colon = NULL;
sprintf(volline, "%s: Issue %3d", listinfo.Volline, issue_number);
strcpy(listinfo.Volline, volline);
/*
* Get a new date.
*/
listinfo.Dateline = msgdate();
free(volline);
}
/*
* msgdate - produce a new date string. Format is
*
* Day, dd Mon yy hh:mm:ss tzn
*/
char *msgdate()
{
#ifdef BSD42
char *timezone();
struct timeb tbuf;
#else ~BSD42
long curtime;
#endif BSD42
register struct tm *t;
struct tm *localtime();
static char datebuf[64];
char *days = "SunMonTueWedThuFriSat";
char *months = "JanFebMarAprMayJunJulAugSepNovDec";
#ifdef BSD42
ftime(&tbuf);
t = localtime(&(tbuf.time));
#else ~BSD42
curtime = time((long *)0);
t = localtime(&curtime);
#endif BSD42
t->tm_mon--;
sprintf(datebuf, "%3.3s, %2d %3.3s %02d %02d:%02d:%02d %3.3s",
&days[3 * t->tm_wday], t->tm_mday,
&months[3 * t->tm_mon], t->tm_year, t->tm_hour,
t->tm_min, t->tm_sec,
#ifdef BSD42
timezone(tbuf.timezone, t->tm_isdst)
#else ~BSD42
tzname[daylight != 0]
#endif BSD42
);
return(datebuf);
}
/*
* getline - read a line into a dynamically allocated buffer.
*/
char *getline(fp)
FILE *fp;
{
register int c;
register char *str, *str_begin;
if ((str = malloc(LINESIZE)) == NULL) {
fprintf(stderr, "digest: out of memory.\n");
exit(1);
}
str_begin = str;
while (((c = getc(fp)) != '\n') && (c != EOF))
*str++ = c;
*str++ = NULL;
if (c == EOF)
return(NULL);
return(str_begin);
}
/*
* scan_messages - scans through LISTINPUT reading in header fields
* and marking the beginning and ending of messages.
*
* NOTE: some of the code here depends on the UNIX mail header format.
* This format simply guarantees that the first line of a message's
* header will be "From blah-blah-blah". Note there is no colon
* (`:') on the "From", the real "From:" line is farther down in
* the headers.
*/
scan_messages()
{
register long n;
register char *s;
if ((input = fopen(LISTINPUT, "r")) == NULL) {
fprintf(stderr, "digest: cannot open \"%s\" for reading.\n", LISTINPUT);
exit(1);
}
/*
* We break out of this from inside.
*/
for (;;) {
if (nmessages >= MAXMSGS) {
fprintf(stderr, "digest: too many messages.\n");
exit(1);
}
/*
* Find the start of the next message.
*/
do {
/*
* If we hit EOF, mark the length of the
* previous message and go back.
*/
if ((s = getline(input)) == NULL) {
n = ftell(input);
n = n - messages[nmessages - 1].messageaddr;
messages[nmessages - 1].messagelength = n;
return;
}
} while (strncmp(s, "From ", 5) != 0);
/*
* If we have found another message, mark the
* length of the previous message.
*/
if (nmessages) {
n = ftell(input);
n = n - (strlen(s) + 1);
n = n - messages[nmessages - 1].messageaddr;
messages[nmessages - 1].messagelength = n;
}
/*
* Read in the headers.
*/
for (;;) {
/*
* We shouldn't hit EOF here, we should
* at least finish the headers first.
*/
if ((s = getline(input)) == NULL) {
fprintf(stderr, "digest: \"%s\": unexpected EOF.\n", LISTINPUT);
exit(1);
}
/*
* Blank line terminates headers.
*/
if (*s == NULL)
break;
/*
* Save certain headers. We strip the
* header name and leading whitespace.
*/
if (strncmp(s, "To:", 3) == 0) {
messages[nmessages].To = nospace(safter(s, "To:"));
}
else if (strncmp(s, "Cc:", 3) == 0) {
messages[nmessages].Cc = nospace(safter(s, "Cc:"));
}
else if (strncmp(s, "From:", 5) == 0) {
messages[nmessages].From = nospace(safter(s, "From:"));
}
else if (strncmp(s, "Date:", 5) == 0) {
messages[nmessages].Date = nospace(safter(s, "Date:"));
}
else if (strncmp(s, "Subject:", 8) == 0) {
s = nospace(safter(s, "Subject:"));
/*
* We don't need the "Re:" stuff.
*/
if ((strncmp(s, "re:", 3) == 0) || (strncmp(s, "Re:", 3) == 0) ||
(strncmp(s, "RE:", 3) == 0) || (strncmp(s, "rE:", 3) == 0))
s += 3;
messages[nmessages].Subject = nospace(s);
}
else {
/*
* If we aren't saving this line,
* give the memory back.
*/
free(s);
}
}
/*
* The message starts after the header.
*/
messages[nmessages].messageaddr = ftell(input);
nmessages++;
}
}
/*
* sort_messages - convert each message's subject line to a string
* all in lower case with no whitespace. Then sort
* the messages on this string. This will group
* all the messages on the same subject together.
*/
sort_messages()
{
register int i;
extern int comp();
register char *s, *t;
for (i=0; i < nmessages; i++) {
/*
* Skip messages with no subject.
*/
if (messages[i].Subject == NULL)
continue;
s = messages[i].Subject;
if ((t = malloc(strlen(s)+1)) == NULL) {
fprintf(stderr, "digest: out of memory.\n");
exit(1);
}
messages[i].sortstring = t;
/*
* Zap leading whitespace.
*/
s = nospace(s);
/*
* Copy the subject string into sortstring
* converting upper case to lower case and
* ignoring whitespace.
*/
while (*s) {
if ((*s == ' ') || (*s == '\t')) {
s++;
continue;
}
if (isupper(*s))
*t++ = tolower(*s);
else
*t++ = *s;
s++;
}
*t = NULL;
}
/*
* Sort 'em.
*/
qsort(messages, nmessages, sizeof(struct message), comp);
}
/*
* comp - comparison routine for qsort. Messages with no subject go
* at the end of the digest, messages with "administrivia" as
* the subject go to the top of the digest.
*/
comp(m1, m2)
register struct message *m1, *m2;
{
int admin1, admin2;
if (m1->sortstring == NULL) {
if (m2->sortstring == NULL)
return(0);
return(1); /* no subject messages to end */
}
if (m2->sortstring == NULL)
return(-1); /* no subject messages to end */
admin1 = strncmp(m1->sortstring, "administrivia", 13);
admin2 = strncmp(m2->sortstring, "administrivia", 13);
if (admin1 == 0) {
if (admin2 == 0)
return(0);
return(-1); /* administrivia to beginning */
}
if (admin2 == 0)
return(1); /* administrivia to beginning */
return(strcmp(m1->sortstring, m2->sortstring));
}
/*
* do_digest_header - prints the digest header and mailer headers.
*/
do_digest_header()
{
char *laststr;
char buf[BUFSIZ];
char tmp[LINESIZE];
extern int comp2();
register int i, j, length;
if ((output = fopen(ListOutput, "w")) == NULL) {
fprintf(stderr, "digest: cannot create \"%s\"\n", ListOutput);
exit(1);
}
digestsize = 0;
/*
* Mailer headers.
*/
sprintf(buf, "Date: %s\n", listinfo.Dateline);
digestsize += strlen(buf);
fputs(buf, output);
sprintf(buf, "From: %s\n", listinfo.From);
digestsize += strlen(buf);
fputs(buf, output);
sprintf(buf, "Reply-To: %s@%s\n", listinfo.Title, listinfo.Host);
digestsize += strlen(buf);
fputs(buf, output);
sprintf(buf, "Subject: %s Digest V1 #%d\n", listinfo.Title, issue_number);
digestsize += strlen(buf);
fputs(buf, output);
#ifdef OLD
sprintf(buf, "To: %s\n", listinfo.To);
digestsize += strlen(buf);
fputs(buf, output);
#endif OLD
/*
* The digest header.
*/
sprintf(tmp, "%s Digest", listinfo.Title);
sprintf(buf, "\n\n%-*.*s %-*.*s %-*.*s\n\n",
HEAD1, HEAD1, tmp,
HEAD2, DATELEN, listinfo.Dateline,
HEAD3, HEAD3, listinfo.Volline);
digestsize += strlen(buf);
fputs(buf, output);
sprintf(buf, "Today's Topics:\n");
digestsize += strlen(buf);
fputs(buf, output);
/*
* Do today's topics lines.
*/
laststr = "";
for (i=0; i < nmessages; i++) {
/*
* No topic.
*/
if (messages[i].Subject == NULL)
continue;
laststr = messages[i].sortstring;
/*
* Count the number of messages with this topic.
*/
j = 1;
while (((i + j) < nmessages) && (strcmp(laststr, messages[i+j].sortstring) == 0))
j++;
/*
* Print the topic centered on the line.
*/
if (j > 1) {
sprintf(tmp, "%s (%d msgs)", messages[i].Subject, j);
length = (LINELEN / 2) + (strlen(tmp) / 2);
sprintf(buf, "%*s\n", length, tmp);
/*
* Sort messages with same topic into their
* original arrival order.
*/
qsort(&messages[i], j, sizeof(struct message), comp2);
i += (j - 1);
}
else {
length = (LINELEN / 2) + (strlen(messages[i].Subject) / 2);
sprintf(buf, "%*s\n", length, messages[i].Subject);
}
digestsize += strlen(buf);
fputs(buf, output);
}
/*
* Print a line of dashes.
*/
for (i=0; i < LINELEN; i++) {
putc('-', output);
digestsize++;
}
fputs("\n\n", output);
digestsize += 2;
}
/*
* comp2 - comparison routine for second qsort. This one simply compares
* messages addresses in the input file, so that we can sort the
* messages with the same topic back into the order they arrived.
*/
comp2(m1, m2)
register struct message *m1, *m2;
{
return(m1->messageaddr - m2->messageaddr);
}
/*
* read_messages - reads in the message texts and puts them in the
* digest with their headers.
*/
read_messages()
{
char buf[BUFSIZ];
register char *s, *t;
register int i, length;
for (i=0; i < nmessages; i++) {
/*
* Just in case.
*/
clearerr(input);
/*
* Put the message's headers back in.
*/
sprintf(buf, "Date: %s\n", messages[i].Date);
digestsize += strlen(buf);
fputs(buf, output);
sprintf(buf, "From: %s\n", messages[i].From);
digestsize += strlen(buf);
fputs(buf, output);
if (messages[i].Subject != NULL) {
sprintf(buf, "Subject: %s\n", messages[i].Subject);
digestsize += strlen(buf);
fputs(buf, output);
}
sprintf(buf, "To: %s\n\n", messages[i].To);
digestsize += strlen(buf);
fputs(buf, output);
/*
* Read the message into memory. This is
* so we can zap extra blank lines.
*/
fseek(input, messages[i].messageaddr, 0);
length = messages[i].messagelength;
if ((s = malloc(length+1)) == NULL) {
fprintf(stderr, "digest: out of memory.\n");
exit(1);
}
fread(s, 1, length, input);
/*
* Zap trailing newlines.
*/
t = s + length;
while (*--t == '\n')
length--;
*++t = NULL;
/*
* Zap leading newlines.
*/
t = s;
while (*t++ == '\n')
length--;
t--;
/*
* Write the message.
*/
digestsize += length;
fwrite(t, 1, length, output);
sprintf(buf, "\n\n------------------------------\n\n");
digestsize += strlen(buf);
fputs(buf, output);
free(s);
}
/*
* All done.
*/
sprintf(buf, "End of %s Digest\n******************************\n", listinfo.Title);
digestsize += strlen(buf);
fputs(buf, output);
fclose(output);
fclose(input);
}
/*
* put_list_info - rewrite the LISTINFO file with the new data.
*/
put_list_info()
{
FILE *fp;
char tmp[LINESIZE];
sprintf(tmp, "%s.old", LISTINFO);
#ifdef BSD42
if (rename(LISTINFO, tmp) < 0) {
fprintf(stderr, "digest: cannot move old \"%s\" file, today's data lost.\n", LISTINFO);
return;
}
#else ~BSD42
if (link(LISTINFO, tmp) < 0) {
fprintf(stderr, "digest: cannot move link \"%s\" file to \"%s\", today's data lost.\n", LISTINFO, tmp);
return;
}
if (unlink(LISTINFO) < 0) {
fprintf(stderr, "digest: cannot remove \"%s\" file, today's data lost.\n", LISTINFO);
return;
}
#endif BSD42
if ((fp = fopen(LISTINFO, "w")) == NULL) {
fprintf(stderr, "digest: cannot create \"%s\", today's data lost.\n", LISTINFO);
return;
}
fprintf(fp, "%s\n", listinfo.Title);
fprintf(fp, "%s\n", listinfo.Host);
fprintf(fp, "%s\n", listinfo.From);
#ifdef OLD
fprintf(fp, "%s\n", listinfo.To);
#endif OLD
fprintf(fp, "%s\n", listinfo.Volline);
fprintf(fp, "%s\n", listinfo.Dateline);
fclose(fp);
unlink(tmp);
}
/*
* safter - return a pointer to the position in str which follows pat.
*/
char *safter(str, pat)
register char *str, *pat;
{
register int len;
len = strlen(pat);
while (*str) {
if (strncmp(str, pat, len) == 0) {
str += len;
return(str);
}
str++;
}
return(NULL);
}
/*
* nospace - advance s over leading whitespace, return new value.
*/
char *nospace(s)
register char *s;
{
while ((*s != NULL) && ((*s == ' ') || (*s == '\t')))
s++;
return(s);
}
@//E*O*F Digest/digest.c//
chmod u=rw,g=rw,o=r Digest/digest.c
echo x - aliases
sed 's/^@//' > "aliases" <<'@//E*O*F aliases//'
bowie@nimbus.dec
ihnp4!sask!regina!mumps
okane@tennessee.csnet
ihnp4!ucbvax!ucdavis!clover:mumps
@//E*O*F aliases//
chmod u=rw,g=rw,o=r aliases
echo x - request
sed 's/^@//' > "request" <<'@//E*O*F request//'
@//E*O*F request//
chmod u=rw,g=rw,o=r request
echo x - inbox
sed 's/^@//' > "inbox" <<'@//E*O*F inbox//'
@//E*O*F inbox//
chmod u=rw,g=rw,o=rw inbox
echo x - hdr.mail
sed 's/^@//' > "hdr.mail" <<'@//E*O*F hdr.mail//'
To: std-mumps-People
@//E*O*F hdr.mail//
chmod u=rw,g=rw,o=r hdr.mail
echo x - hdr.news
sed 's/^@//' > "hdr.news" <<'@//E*O*F hdr.news//'
Newsgroups: mod.std.mumps
Approved: hokey@plus5.uucp
@//E*O*F hdr.news//
chmod u=rw,g=rw,o=r hdr.news
echo x - submit
sed 's/^@//' > "submit" <<'@//E*O*F submit//'
:
Requests=requests
: 'Check to see if any new requests have come in'
if [ -s $Requests ]
then
echo "There are mailing list requests which must be handled"
exit 1
fi
: 'Check to see if any submissions have arrived'
if [ ! -s inbox ]
then
echo "No new submissions"
exit 1
fi
mv inbox digest.input
touch inbox
chmod 666 inbox
: 'protect against disaster'
cp digest.input inbox-
cp digest.info digest.info-
: 'This is a good place to "pre-edit" input'
Digest=`Digest/digest`
if [ -z "$Digest" ]
then
echo "No digest created."
exit 1
fi
: 'This is a good place to make sure we did OK'
cat hdr.mail $Digest | /usr/lib/sendmail -t
cat hdr.news $Digest | /usr/lib/news/inews -h
mv $Digest OLD
exit 0
@//E*O*F submit//
chmod u=rwx,g=rwx,o=rx submit
echo x - digest.info
sed 's/^@//' > "digest.info" <<'@//E*O*F digest.info//'
std-mumps
plus5.uucp
Hokey (The Moderator) <hokey@plus5.uucp>
Volume 1 : Issue 10
Sat, 9 Feb 85 19:20:44 CDT
@//E*O*F digest.info//
chmod u=rw,g=rw,o=r digest.info
exit 0
From cbosgd!ihnp4!wnuxb!netnews Wed Mar 13 03:32:44 1985
Received: by genrad.UUCP (4.12/4.7)
id AA03315; Wed, 13 Mar 85 03:32:39 est
From: ihnp4!wnuxb!netnews
Message-Id: <8503130753.AA10972@cbosgd.ATT.UUCP>
Received: by cbosgd.ATT.UUCP (4.12/3.7boo)
id AA10972; Wed, 13 Mar 85 02:53:59 est
Date: 12 Mar 85 22:42:29 CST (Tue)
Received: by ihnp4.ATT.UUCP; id AA20654; 12 Mar 85 22:42:29 CST (Tue)
To: ihnp4!cbosgd!moderators
Subject: Re: shar of digest software
Status: R
The stuff hokey posted worked out really well for me. I was using
just the "lame" shell scripts, now the C stuff makes things MUCH
easier. Of course, I couldn't leave well enough alone, so I made
a few changes. On my SysV, time is not in /usr/include/sys, just
/usr/include. Also, I didn't see any reason to include the "To:"
lines in each of the digestified messages, so that is now surrounded
by #ifdef INTO. (Although I may have missed something so that it
may break if INTO actually gets defined.) I was getting memory
faults on some long lines, so I bumped the max line size to 256.
And, I like GMT. (Berkleyites should check this part. I just do
SysV. :->) Another thing was that I wanted the "Name" of the
digest to be different from the "address" to which submissions should
be sent, so I added a line to the digest.info file. Here are context
diffs of digest.c. (Hope you all have patch!) After that, is an
example of the new digest.info file (virtually identical). Ron.
-------------------
*** digest.old Sun Mar 10 21:59:05 1985
--- digest.c Mon Mar 11 22:45:27 1985
***************
*** 62,68
#else ~BSD42
#define index=strchr
#endif BSD42
! #include <sys/time.h>
#include <ctype.h>
#include <stdio.h>
--- 62,68 -----
#else ~BSD42
#define index=strchr
#endif BSD42
! #include <time.h>
#include <ctype.h>
#include <stdio.h>
***************
*** 72,78
#define DATELEN 14 /* Amount of date to put in hdr */
#define LINELEN 70 /* Length of an average line */
#define MAXMSGS 32 /* Maximum number of msgs/digest*/
! #define LINESIZE 128 /* Maximum line size */
#define LISTINFO "digest.info" /* Information file name */
#define LISTINPUT "digest.input" /* Input file name */
char ListOutput[32]; /* Output file name */
--- 72,78 -----
#define DATELEN 14 /* Amount of date to put in hdr */
#define LINELEN 70 /* Length of an average line */
#define MAXMSGS 32 /* Maximum number of msgs/digest*/
! #define LINESIZE 256 /* Maximum line size */
#define LISTINFO "digest.info" /* Information file name */
#define LISTINPUT "digest.input" /* Input file name */
char ListOutput[32]; /* Output file name */
***************
*** 102,107
*/
struct listinfo {
char *Title;
char *Host;
char *From;
#ifdef OLD
--- 102,108 -----
*/
struct listinfo {
char *Title;
+ char *Address;
char *Host;
char *From;
#ifdef OLD
***************
*** 178,183
if ((listinfo.Title = getline(fp)) == NULL)
incomplete++;
if ((listinfo.Host = getline(fp)) == NULL)
incomplete++;
if ((listinfo.From = getline(fp)) == NULL)
--- 179,186 -----
if ((listinfo.Title = getline(fp)) == NULL)
incomplete++;
+ if ((listinfo.Address = getline(fp)) == NULL)
+ incomplete++;
if ((listinfo.Host = getline(fp)) == NULL)
incomplete++;
if ((listinfo.From = getline(fp)) == NULL)
***************
*** 257,263
long curtime;
#endif BSD42
register struct tm *t;
! struct tm *localtime();
static char datebuf[64];
char *days = "SunMonTueWedThuFriSat";
char *months = "JanFebMarAprMayJunJulAugSepNovDec";
--- 260,266 -----
long curtime;
#endif BSD42
register struct tm *t;
! struct tm *gmtime();
static char datebuf[64];
char *days = "SunMonTueWedThuFriSat";
char *months = "JanFebMarAprMayJunJulAugSepNovDec";
***************
*** 264,270
#ifdef BSD42
ftime(&tbuf);
! t = localtime(&(tbuf.time));
#else ~BSD42
curtime = time((long *)0);
t = localtime(&curtime);
--- 267,273 -----
#ifdef BSD42
ftime(&tbuf);
! t = gmtime(&(tbuf.time));
#else ~BSD42
curtime = time((long *)0);
t = gmtime(&curtime);
***************
*** 267,273
t = localtime(&(tbuf.time));
#else ~BSD42
curtime = time((long *)0);
! t = localtime(&curtime);
#endif BSD42
t->tm_mon--;
--- 270,276 -----
t = gmtime(&(tbuf.time));
#else ~BSD42
curtime = time((long *)0);
! t = gmtime(&curtime);
#endif BSD42
t->tm_mon--;
***************
*** 276,282
&months[3 * t->tm_mon], t->tm_year, t->tm_hour,
t->tm_min, t->tm_sec,
#ifdef BSD42
! timezone(tbuf.timezone, t->tm_isdst)
#else ~BSD42
tzname[daylight != 0]
#endif BSD42
--- 279,285 -----
&months[3 * t->tm_mon], t->tm_year, t->tm_hour,
t->tm_min, t->tm_sec,
#ifdef BSD42
! "GMT"
#else ~BSD42
"GMT"
#endif BSD42
***************
*** 278,284
#ifdef BSD42
timezone(tbuf.timezone, t->tm_isdst)
#else ~BSD42
! tzname[daylight != 0]
#endif BSD42
);
--- 281,287 -----
#ifdef BSD42
"GMT"
#else ~BSD42
! "GMT"
#endif BSD42
);
***************
*** 555,561
digestsize += strlen(buf);
fputs(buf, output);
! sprintf(buf, "Reply-To: %s@%s\n", listinfo.Title, listinfo.Host);
digestsize += strlen(buf);
fputs(buf, output);
--- 558,564 -----
digestsize += strlen(buf);
fputs(buf, output);
! sprintf(buf, "Reply-To: %s@%s\n", listinfo.Address, listinfo.Host);
digestsize += strlen(buf);
fputs(buf, output);
***************
*** 679,685
fputs(buf, output);
if (messages[i].Subject != NULL) {
! sprintf(buf, "Subject: %s\n", messages[i].Subject);
digestsize += strlen(buf);
fputs(buf, output);
}
--- 682,689 -----
fputs(buf, output);
if (messages[i].Subject != NULL) {
! sprintf(buf, "Subject: %s\n\n", messages[i].Subject);
! } else sprintf(buf, "\n");
digestsize += strlen(buf);
fputs(buf, output);
***************
*** 682,688
sprintf(buf, "Subject: %s\n", messages[i].Subject);
digestsize += strlen(buf);
fputs(buf, output);
- }
sprintf(buf, "To: %s\n\n", messages[i].To);
digestsize += strlen(buf);
--- 686,691 -----
} else sprintf(buf, "\n");
digestsize += strlen(buf);
fputs(buf, output);
#ifdef INTO
sprintf(buf, "To: %s\n\n", messages[i].To);
***************
*** 684,689
fputs(buf, output);
}
sprintf(buf, "To: %s\n\n", messages[i].To);
digestsize += strlen(buf);
fputs(buf, output);
--- 687,693 -----
digestsize += strlen(buf);
fputs(buf, output);
+ #ifdef INTO
sprintf(buf, "To: %s\n\n", messages[i].To);
digestsize += strlen(buf);
fputs(buf, output);
***************
*** 687,692
sprintf(buf, "To: %s\n\n", messages[i].To);
digestsize += strlen(buf);
fputs(buf, output);
/*
* Read the message into memory. This is
--- 691,697 -----
sprintf(buf, "To: %s\n\n", messages[i].To);
digestsize += strlen(buf);
fputs(buf, output);
+ #endif INTO
/*
* Read the message into memory. This is
***************
*** 772,777
}
fprintf(fp, "%s\n", listinfo.Title);
fprintf(fp, "%s\n", listinfo.Host);
fprintf(fp, "%s\n", listinfo.From);
#ifdef OLD
--- 777,783 -----
}
fprintf(fp, "%s\n", listinfo.Title);
+ fprintf(fp, "%s\n", listinfo.Address);
fprintf(fp, "%s\n", listinfo.Host);
fprintf(fp, "%s\n", listinfo.From);
#ifdef OLD
-------------------------------
Unix Technical
unix
cbosgd.UUCP
Ron Heiby (The Moderator) <unix-request@cbosgd.UUCP>
Volume 1 : Issue 14
Wed, 13 Feb 85 04:13:30 GMT
From cbosgd!ihnp4!wnuxb!netnews Thu Mar 14 00:41:42 1985
Received: by genrad.UUCP (4.12/4.7)
id AA17962; Thu, 14 Mar 85 00:41:40 est
From: ihnp4!wnuxb!netnews
Message-Id: <8503140334.AA21213@cbosgd.ATT.UUCP>
Received: by cbosgd.ATT.UUCP (4.12/3.73boo)
id AA21213; Wed, 13 Mar 85 22:34:23 est
Date: 13 Mar 85 21:32:22 CST (Wed)
Received: by ihnp4.ATT.UUCP; id AA15294; 13 Mar 85 21:32:22 CST (Wed)
To: ihnp4!cbosgd!moderators
Subject: Re: New digest software
Status: R
There seems to be a bug in digest.c in the date area. Just after we
find out what the current time is and fill in the tm struct, there is
a line that says, "t->tm_mon--;". This puts the message one month
into the past on my System V machine. I have removed the line. Ron.