sources-request@mirror.UUCP (06/18/86)
Submitted: taylor@hplabs Mod.sources: Volume 6, Issue 6 Archive-name: maildigest [ The mail.digest.m program refers to mailx; change this to Mail if you have it. If you have neither, you'll have to do something else to get the subject lines in there. Change the "SEE ALSO" in digest.1 also, which has to be the chattiest manpage in Unix(tm) history. --r$] --------------------------------cut here-------------------- # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # Contents: Makefile center.1 center.c digest.1 digest.all digest.awk # issue.master mail.digest.m mail.issue.m mydate.1 mydate.c readword.c echo x - Makefile sed 's/^XX//' > "Makefile" <<'@//E*O*F Makefile//' XX# Makefile for the Digest system... XX# XX# This entire Digest system is; XX# (C) Copyright 1986, Dave Taylor, Hewlett-Packard XX# XX# To use, merely type "make all" XXSHELL=/bin/csh XXCFILES= readword.c center.c mydate.c XXSCRIPTS= digest.all digest.awk digest.tail issue mail.digest mail_issue \ XX volume_number XXCC=/bin/cc XXCFLAGS=-O XXall: readword .DIGESTNAME .DIGESTADDR .MODERATOR .MOD_ADDR \ XX center mydate ${SCRIPTS} XX @chmod a+rx digest.all issue mail.digest mail_issue XX @echo digest system ready to go... XXreadword : readword.c XX @echo Creating readword program for interactive section of Makefile XX @echo " " XX ${CC} ${CFLAGS} readword.c -o readword XXcenter : center.c XX ${CC} ${CFLAGS} center.c -o center XX XXmydate: mydate.c XX ${CC} ${CFLAGS} mydate.c -o mydate XX.DIGESTNAME: XX @echo " " XX @echo -n "Please enter the name of the digest: " XX @readword .DIGESTNAME XX.DIGESTADDR: XX @echo -n "Please enter the alias you'll use for sending the digest: " XX @readword .DIGESTADDR XX.MODERATOR: XX @echo -n "Please enter the full name of the moderator: " XX @readword .MODERATOR XX.MOD_ADDR: XX @echo -n "Please enter the mailing address for mail to the moderator: " XX @readword .MOD_ADDR XX @echo " " XXdigest.tail: XX @echo 'Creating digest.tail...' XX @echo " " > digest.tail XX @echo "-------------------------------------" >> digest.tail XX @echo " " >> digest.tail XX @echo \ XX "To join this group or have your thoughts in the next issue, please" \ XX >> digest.tail XX @echo \ XX "send electronic mail to `cat .MODERATOR` at the following address;" \ XX >> digest.tail XX @echo " " >> digest.tail XX @echo " `cat .MOD_ADDR`" >> digest.tail XX @echo " " >> digest.tail XX @echo "The views expressed in `cat .DIGESTNAME`" >> digest.tail XX @echo "are those of the individual authors only.">> digest.tail XX @echo " " >> digest.tail XX @echo "*********************" >> digest.tail XX @echo "End of `cat .DIGESTNAME`" >> digest.tail XX @echo "*********************" >> digest.tail XXissue: issue.master XX @echo "Creating issue script..." XX @echo " " > issue XX @echo " digest_name='`cat .DIGESTNAME`'" >> issue XX @cat issue.master >> issue XXmail.digest: mail.digest.m XX @echo "Creating mail.digest..." XX @echo " " > mail.digest XX @echo " digest_name='`cat .DIGESTNAME`'" >> mail.digest XX @cat mail.digest.m >> mail.digest XXmail_issue: mail.issue.m XX @echo "Creating mail_issue..." XX @echo " " > mail_issue XX @echo " digest_name='`cat .DIGESTNAME`'" >> mail_issue XX @echo " to='`cat .DIGESTADDR`'" >> mail_issue XX @cat mail.issue.m >> mail_issue XXvolume_number: XX @echo 'Creating volume_number file...' XX @echo 1 > volume_number XXclean: XX /bin/rm -f .DIGESTNAME .DIGESTADDR .MODERATOR \ XX .MOD_ADDR digest.tail issue digest.title \ XX mail.digest mail_issue volume_number center mydate readword @//E*O*F Makefile// chmod u=rw,g=rw,o=rw Makefile echo x - center.1 sed 's/^XX//' > "center.1" <<'@//E*O*F center.1//' XX.TH CENTER 1L XX.ad b XX.SH NAME XXcenter \- read stdin, output each line centered in 80 cols XX.SH SYNOPSIS XX.B center XX< text > centered-text XX.SH HP-UX COMPATIBILITY XX.TP 10 XXLevel: XXHP-UX/USER CONTRIBUTED XX.TP XXOrigin: XXHewlett-Packard Laboratories XX.SH DESCRIPTION XX.I Center XXis a simple program that is useful within shell scripts. There XXare no doubt millions of `better' ways to accomplish what XXthis program does, but it does work! XX.SH EXAMPLE XX.P XXLet's assume we're in "sh"; XX.nf XX $ name="John Doe" XX $ echo $name XX John Doe XX $ name1=`echo $name | center` XX $ echo $name1 XX John Doe XX $ XX.fi XX.SH AUTHOR XXDave Taylor, Hewlett-Packard Laboratories XX.SH "SEE ALSO" XXdigest(1) @//E*O*F center.1// chmod u=rw,g=r,o=r center.1 echo x - center.c sed 's/^XX//' > "center.c" <<'@//E*O*F center.c//' XX/** center.c **/ XX/** Simple program that filters stdin to stdout centering each line XX it reads. For batch/shell script processing, mostly. **/ XX#include <stdio.h> XXmain() XX{ XX char buffer[100]; XX register int i; XX while (gets(buffer, 100) != NULL) { XX for (i = 0; i < (80-strlen(buffer))/2; i++) XX putchar(' '); XX printf("%s\n", buffer); XX } XX} @//E*O*F center.c// chmod u=rw,g=r,o=r center.c echo x - digest.1 sed 's/^XX//' > "digest.1" <<'@//E*O*F digest.1//' XX.TH DIGEST 1L XX.ad b XX.SH NAME XXdigest \- tools to help maintain a mailing list/digest XX.SH HP-UX COMPATIBILITY XX.TP 10 XXLevel: XXHP-UX/USER CONTRIBUTED XX.TP XXOrigin: XXHewlett-Packard Laboratories XX.SH DESCRIPTION XXThe XX.I digest XXsystem is composed of a number of programs and scripts; XX.nf XX Makefile - to customize all the scripts, etc XX center.c - to center lines for formatting XX center.1 - manual entry for \fIcenter\fR XX digest.all - script to create an individual digest XX digest.awk - awk script to `massage' mailboxes XX issue.master - master copy of issue script XX mail.digest.master - master copy of mail.digest script XX mail_issue.master - master copy of mail_issue script XX mydate.c - program for `nice' date strings XX mydate.1 - manual entry for \fImydate\fR XX readword.c - dumb program for reading line from stdin XX.fi XXWhen the \fImake\fR is done, a number of other files will appear XXand will comprise the full \fIdigest\fR script and mailing system; XX.nf XX DIGEST_ALIAS_ADDRESS - the address you use to send mail to everyone XX DIGEST_NAME - the full name of the digest XX MODERATOR - the full name of the moderator XX MODERATOR_ADDRESS - the email addres of MODERATOR XX center - executable version of center.c XX digest.tail - localized copy of digest.tail XX issue - localized copy of issue XX mail.digest - localized copy of mail.digest XX mail_issue - localized copy of mail_issue XX mydate - executable version of mydate.c XX readword - executable version of readword.c XX volume_number - file used to autoincrement issues XX.fi XXThe easiest way to see how they all interact is by example... XX.SH EXAMPLE XXLet's say that we want to create a new mailing list called XXcalled "Snail-Fans Digest", and we've already created the XXaliases "snail-fans-request" and "snail-fans" as the mail XXaddresses for requests to join the list/submit articles and XXto send mail to everyone in the group, respectively. XX.P XXWe could then type...[user input in \fBbold face\fR, comments in XXsquare brackets like this]; XX.nf XX $ \fBmake all\fR XX /bin/cc -O readword.c -o readword [for interactive makefile] XX The name of the digest: \fBSnail-Fans Digest\fR XX The alias you'll use for sending it out: \fBsnail-fans\fR XX The full name of the moderator: \fBJohn Q. Public\fR XX The mailing address of the moderator: \fBsnail-fans-request\fR XX /bin/cc -O center.c -o center XX /bin/cc -O mydate.c -o mydate XX Creating digest.tail... XX Creating issue script... XX Creating mail.digest... XX Creating mail_issue... XX Creating volume_number file... XX digest system ready to go... XX $ \fBmore digest.tail\fR XX ------------------------------------- XX XX To join this group or have your thoughts in the next issue, please XX send electronic mail to John Q. Public at the following address; XX XX snail-fans-request XX XX ********************* XX End of Snail-Fans Digest XX ********************* XX $ \fBhead issue\fR XX XX digest_name='Snail-Fans Digest' XX # ISSUE - Shell script creates a new issue of a mailing-list Digest. XX # To do this it creates a new title file then calls the digest.all XX # program to summarize the mailings. It then drops you into the XX # editor to modify the subject headers, if desired. Upon leaving XX # it then starts up the batchmail program in the background and XX # exits. XX # XX $ \fBhead mail.digest\fR XX XX digest_name='Snail-Fans Digest' XX XX # mail_issue - This shell script mails out the previously created digest... XX # XX XX digest="outbound.digest" XX archive="Digest." XX volume="volume_number" XX XX $ \fBhead mail_issue\fR XX XX digest_name='Snail-Fans Digest' XX to='snail-fans' XX XX # mail_issue - This shell script mails out the previously created digest... XX # XX XX digest="outbound.digest" XX archive="Digest." XX volume="volume_number" XX $ \fBmore volume_number\fR XX 1 XX.fi XXThat's an idea of the files it creates. Now let's actually send out XXan issue of the digest! XX.P XXFirst off, a few administration details - the \fIdigest\fR system XXassumes that you use \fIoutbound\fR as the name of the mailbox that XXall outbound mail is queued in (note that no processing whatsoever XXneed be done beforehand on the mailbox) and that you won't mind XXsaving back issues as Digest.\fIn\fR where \fIn\fR is the number of XXthe digest...the most recently mailed digest mailbox is also saved XX(until the next mailing) as \fIoutbound.last\fR. XX.P XX.nf XX $ \fBcat outbound\fR XX From jqpublic Mon Jun 2 17:40:31 1986 XX To: jqpublic XX Date: Mon Jun 2 17:40:31 1986 PST XX Subject: Welcome to the Snail Fans Digest! XX Just a short hello to welcome everyone to the list and XX to try out the digest software. XX Please let me know if you have any problems! XX -- JQ XX [ now we can actually send it out... ] XX $ \fBissue\fR XX Creating Snail-Fans Digest, Number 1 XX XX Extracting all the 'subject' lines... XX XX ...feeding the file to awk... XX XX [your favorite editor is then invoked with the ready-to-be-sent XX digest, for a final pass through (recommended)] XX Are you sure you want to send this issue out now? (y/n) \fBno\fR XX just type "mail_issue" when you're ready to mail it out! XX [since we cancelled the actual mailing, let's look at the digest XX it created...] XX $ \fBcat outbound.digest\fR XX XX Snail-Fans Digest, Number 1 XX XX Monday, June 2nd 1986 XX XX Today's Topics: XX XX Welcome to the Snail Fans Digest! XX ---------------------------------------------------------------------- XX XX Date: Mon Jun 2 17:40:31 1986 PST XX Subject: Welcome to the Snail Fans Digest! XX From: jqpublic XX Just a short hello to welcome everyone to the list and XX to try out the digest software. XX Please let me know if you have any problems! XX -- JQ XX XX ------------------------------------- XX XX To join this group or have your thoughts in the next issue, please XX send electronic mail to John Q. Public at the following address; XX XX snail-fans-request XX XX ********************* XX End of Snail-Fans Digest XX ********************* XX XX $ \fBmail_issue\fR XX Mailing Snail-Fans Digest, Number 1 XX XX $ XX.fi XXPretty slick, eh? In practice, maintaining a mailing list is XXmostly maintaining the actual addresses themselves. The overhead XXof creating a digest (etc) is all avoided. XX.SH AUTHOR XXDave Taylor, Hewlett-Packard Laboratories XX.SH "SEE ALSO" XXawk(1), center(1), mydate(1), mailx(1), sendmail(1). @//E*O*F digest.1// chmod u=rw,g=r,o=r digest.1 echo x - digest.all sed 's/^XX//' > "digest.all" <<'@//E*O*F digest.all//' XX# DIGEST-ALL XX# XX# This shell script is to help create a 'digest' suitable for mailing out XX# of all messages in a given mailbox... XX# XX# Dave Taylor, Hewlett-Packard Laboratories XX awk_script="digest.awk" XXif [ $# -ne 4 ] XXthen XX echo "Usage: $0 <header> <mailbox-name> <digest-name> <tail>" XX exit 1 XXfi XXif [ ! -r $1 -o ! -r $4 ] XXthen XX echo "$0: Can't find the header and/or tail files!" XX exit 2 XXfi XXif [ ! -r $awk_script ] XXthen XX echo "$0: Can't find the AWK script I need." XX exit 2 XXfi XXif [ ! -r $2 ] XXthen XX echo "$0: Can't find specified mailbox - $2" XX exit 3 XXfi XXif [ -z $2 ] XXthen XX echo "$0: Mailbox $2 is EMPTY!" XX exit 4 XXfi XXif [ -r $3 ] XXthen XX if [ "`echo -n hi | grep n`" = "" ] # can echo use "-n" ?? XX then XX echo -n "$0: File $3 exists! Overwrite it? (y/n) " # yes! XX else XX echo "$0: File $3 exists! Overwrite it? (y/n) \\c" # no! XX fi XX read answer junk XX if [ "$answer" = "y" -o "$answer" = "yes" ] XX then XX echo "$0: removing current copy of file $3..." XX rm -f $3 XX else XX echo "$0: Digest processing cancelled!" XX exit 5 XX fi XXfi XX# Now let's try to do something! XXcat $1 > $3 XX# first collect all the 'subject' lines at the top of the file... XXecho ' ' XXecho "Extracting all the 'subject' lines..." XXegrep -e "^Subject:" $2 | sed 's/Subject://' | center >> $3 XXecho ' ' XX# now digest the file... XXecho "...feeding the file to awk..." XXcat $2 | awk -f $awk_script - >> $3 XXcat $4 >> $3 XX XXecho ' ' XXexit 0 @//E*O*F digest.all// chmod u=rwx,g=rx,o=rx digest.all echo x - digest.awk sed 's/^XX//' > "digest.awk" <<'@//E*O*F digest.awk//' XX# XX# Awk Script called by 'digest'. See DIGEST(1) XX# XX# Version two - sucks in the '>From' lines too... XX# (guarantees a "valid" return address!) XXBEGIN { XX message = 0; XX last = "this should never be matched" XX in_header = 1; XX have_from = 0; XX } XX$1 ~ /^From$/ { if (message == 0) { XX print "----------------------------------------------------------------------" XX print " " XX } XX else { XX print "------------------------------" XX print " " XX } XX message++; XX in_header = 1; XX from = $2; XX parse_count = 0; XX have_from = 0; XX last = "we should have a hard time matching this, too" XX } XX$1 ~ /^From:/ { if (in_header) print $0; XX have_from = 1 } XX$1 ~ /^>From/ { parse_count++; XX address = $2 XX if (parse_count > 1) XX from = from"!"$10 XX else XX from = $10 XX } XX$1 ~ /^Subject:/ { if (in_header) print $0 } XX$1 ~ /^Date:/ { if (in_header) print $0 } XXlength($0) < 2 { XX if (in_header == 1) XX if (have_from == 0) XX print "From: "from"!"address XX if ($0 != last) XX print $0 XX in_header = 0 XX last = $0 XX } XXin_header == 0 { if ($0 != last) XX print $0 XX last = $0 XX } @//E*O*F digest.awk// chmod u=rw,g=r,o=r digest.awk echo x - issue.master sed 's/^XX//' > "issue.master" <<'@//E*O*F issue.master//' XX# ISSUE - Shell script creates a new issue of a mailing-list Digest. XX# To do this it creates a new title file then calls the digest.all XX# program to summarize the mailings. It then drops you into the XX# editor to modify the subject headers, if desired. Upon leaving XX# it then starts up the batchmail program in the background and XX# exits. XX# XX# (C) 1985, Dave Taylor, Hewlett-Packard Laboratories XX# XX titles=digest.title XX vol=volume_number XX tail=digest.tail XXif [ ! -r outbound ] XXthen XX echo Nothing queued to go out. XX exit 0 XXfi XXecho " " XXecho "Creating $digest_name, Number `cat $vol`" XXrm -f $titles XXecho ' ' > $titles XXecho "$digest_name, Number `cat $vol`" | center >> $titles XXecho " " >> $titles XXmydate notime | center >> $titles XXecho ' ' >> $titles XXecho "Today's Topics:" >> $titles XXecho ' ' >> $titles XXdigest.all $titles outbound outbound.digest $tail XXmv outbound outbound.last XXif [ "$EDITOR" = "" ] XXthen XX /bin/vi outbound.digest XXelse XX $EDITOR outbound.digest XXfi XXecho ' ' XXecho ' ' XXif [ "`echo -n hi | grep n`" = "" ] # can echo deal with -n ? XXthen XX echo -n "Are you sure you want to send this issue out now? (y/n) " XXelse XX echo "Are you sure you want to send this issue out now? (y/n) \\c" XXfi XXread answer junk XXif [ "$answer" = "yes" -o "$answer" = "y" ] XXthen XX echo " " XX rm -f $issue_log XX echo "starting up mail daemon..." XX mail_issue XX echo " " XXelse XX echo "just type \"mail_issue\" when you're ready to mail it out!" XXfi XXexit 0 @//E*O*F issue.master// chmod u=rw,g=r,o=r issue.master echo x - mail.digest.m sed 's/^XX//' > "mail.digest.m" <<'@//E*O*F mail.digest.m//' XX# mail_issue - This shell script mails out the previously created digest... XX# XX digest="outbound.digest" XX archive="Digest." XX volume="volume_number" XX# does the file exist??? XXif [ -r $digest ] XXthen XX volnum=`cat $volume` XX (mailx -s "$digest_name, #$volnum" $to < $digest XX mv $digest $archive$volnum; XX rm -f $digest; XX rm -f $volume; XX echo Incrementing volume number.. XX echo `expr $volnum + 1` > $volume) > $log 2>&1 & XX XXfi XXexit 0 @//E*O*F mail.digest.m// chmod u=rw,g=r,o=r mail.digest.m echo x - mail.issue.m sed 's/^XX//' > "mail.issue.m" <<'@//E*O*F mail.issue.m//' XX# Front end for mailing out the digest... XX vol=volume_number XXecho "Mailing \"$digest_name, Volume `cat $vol`\"" XXexec nohup mail.digest @//E*O*F mail.issue.m// chmod u=rw,g=r,o=r mail.issue.m echo x - mydate.1 sed 's/^XX//' > "mydate.1" <<'@//E*O*F mydate.1//' XX.TH MYDATE 1L XX.ad b XX.SH NAME XXmydate \- readable date format XX.SH SYNOPSIS XX.B mydate XX.br XX.B "mydate notime" XX.SH HP-UX COMPATIBILITY XX.TP 10 XXLevel: XXHP-UX/USER CONTRIBUTED XX.TP XXOrigin: XXHewlett-Packard Laboratories XX.SH DESCRIPTION XX.I Mydate XXis a simple program that displays the local date in a much more XXreadable format than possible by the \fIdate\fR(1) program. XXThere are two ways to use it, both exemplified below. XX.P XXThis is most useful for use within scripts. XX.SN EXAMPLE XX.nf XX % date XX Mon Jun 2 18:35:24 PDT 1986 XX % mydate XX Monday, June 2nd 1986 at 6:35 pm XX % mydate notime XX Monday, June 2nd 1986 XX XX.fi XX.SH AUTHOR XXDave Taylor, Hewlett-Packard Laboratories XX.SH "SEE ALSO" XXdate(1), digest(1) @//E*O*F mydate.1// chmod u=rw,g=r,o=r mydate.1 echo x - mydate.c sed 's/^XX//' > "mydate.c" <<'@//E*O*F mydate.c//' XX/** mydate.c **/ XX/** This program outputs the date in the format: XX DAY, MONTH DATE YEAR at HH:MM am|pm XX ("Monday, January 17th, 1985 at 4:17 pm" for example) XX or, with ANY parameters at all; XX DAY, MONTH DATE YEAR XX without any 'time' string... XX Dave Taylor, Colorado Networks Operation XX**/ XX#include <time.h> XX#include <stdio.h> XX#define ampm(n) (n > 12? n - 12 : n) XX#define am_or_pm(n) (n > 12? "pm" : "am") XXchar *dayname[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", XX "Friday", "Saturday", "" }; XXchar *monname[] = { "January", "February", "March", "April", "May", "June", XX "July", "August", "September", "October", "November", XX "December", ""}; XXmain(argc, argv) XXint argc; XXchar *argv[]; XX{ XX struct tm *the_time; /* Time structure, see CTIME(3C) */ XX char *suffix(); /* digit suffix for date */ XX long junk; /* time in seconds.... */ XX junk = time(0); /* this must be here for it to work! */ XX the_time = (struct tm * ) localtime(&junk); XX XX if (argc == 1) /* normal format... */ XX printf("%s, %s %d%s %d at %d:%02d %s\n", XX dayname[the_time->tm_wday], /* weekday */ XX monname[the_time->tm_mon], /* month */ XX the_time->tm_mday, /* day */ XX suffix(the_time->tm_mday), /* suffix */ XX the_time->tm_year + 1900, /* year */ XX ampm(the_time->tm_hour), /* hour */ XX the_time->tm_min, /* minute */ XX am_or_pm(the_time->tm_hour)); /* am | pm */ XX else /* sccs (retch) format */ XX printf("%s, %s %d%s %d\n", XX dayname[the_time->tm_wday], /* weekday */ XX monname[the_time->tm_mon], /* month */ XX the_time->tm_mday, /* day */ XX suffix(the_time->tm_mday), /* suffix */ XX the_time->tm_year + 1900); /* year */ XX} XXchar *suffix(day) XXint day; XX{ XX /** this routine returns the suffix appropriate for the XX specified number to make it an ordinal number. ie, XX if given '1' it would return 'st', and '2' => 'nd' XX **/ XX static char buffer[10]; XX register int digit; XX digit = day % 10; XX if (digit == 0 || digit > 3 || (day > 10 && day < 14)) XX strcpy(buffer,"th"); XX else if (digit == 1) XX strcpy(buffer,"st"); XX else if (digit == 2) XX strcpy(buffer, "nd"); XX else XX strcpy(buffer, "rd"); XX return( (char *) buffer); XX} @//E*O*F mydate.c// chmod u=rw,g=r,o=r mydate.c echo x - readword.c sed 's/^XX//' > "readword.c" <<'@//E*O*F readword.c//' XX/** readword.c **/ XX/* Stupid little program to read a line from stdin and write it to the XX specified filename. This SHOULD be equivalent to XX read var ; echo $var > filename XX but that doesn't work from within Makefiles *sigh* XX*/ XX#include <stdio.h> XXmain(argc, argv) XXint argc; XXchar *argv[]; XX{ XX FILE *file_device; /* file descriptor... */ XX char buffer[100]; /* and input buffer */ XX /** first lets check the starting arguments... **/ XX if (argc != 2) { XX fprintf(stderr,"Usage: readword <filename>\n"); XX exit(1); XX } XX /** can we open the file for writing??? **/ XX if ((file_device = fopen(argv[1], "w")) == NULL) { XX fprintf(stderr,"Cannot open file %s for writing!\n", argv[1]); XX exit(2); XX } XX /** okay...read and write the input **/ XX gets(buffer); XX fputs(buffer, file_device); XX /** close the file... **/ XX fclose(file_device); XX /** and we're done! **/ XX exit(0); XX} @//E*O*F readword.c// chmod u=rw,g=rw,o=rw readword.c exit 0