home *** CD-ROM | disk | FTP | other *** search
- 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.
-
-
-