#! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # CHANGES # INSTALLATION # USAGE # filter-rules # fold.c # path_undig # procmailrc # test_undig # undig # undig_pm # bmw_def # itacar_def # na_def # skunk_def # undig_def # This archive created: Thu Aug 1 17:29:29 1996 export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'CHANGES'" '(9043 characters)' if test -f 'CHANGES' then echo shar: "will not over-write existing file 'CHANGES'" else cat << \SHAR_EOF > 'CHANGES' v1.0 2 Apr 1995 John Firestone, jfiresto@awi.bremerhaven.de ---------------- Program written. v2.0 8 Apr 1995 ibid. ---------------- Messages are filtered to a mail box file rather than re-mailed to the user. A kill list now discards mail from specified contributors. v2.1 9 May 1995 ibid. ---------------- An optional input mail box may be given to work with the "elm filter" program. The daemon option now looks like a "-daemon" option. v2.2 25 May 1995 ibid. ---------------- The daemon keeps track of the digests it has received and discards those it has already seen. At specified hours, the daemon queries the majordomo for an index of the digests it has on line. Using this index, the daemon finds and requests any missing, backlogged digests, up to a specified limit. The rest it marks as stale and ignores. Eliminated multiple checks for competing daemons: the added checks were overly-cautious. The program saves messages that look like but aren't quite digests. Added test to see if Mail actually deletes its messages. Eliminated the need to manage the program with an alias. Moved specification of mail boxes from the command line into the program. Added code to let the user peruse the output mail box and the index, and (manually) request files from the majordomo. Made perusing the output mail box the default behavoir. Added -undigest switch to (re)start the undigestifier. v3.0 16 Jul 1995 ibid. ---------------- The undigestifier now uses a mail filtering program to capture digest- related mail, for example, "elm filter", or better yet, "procmail". This has led to the program being split into three pieces: a requester daemon and user interface program, undig; a mail processing program, undig_pm; and a file of common definitions, undig_def. The program no longer needs to use "mail" to read or manage the system mail box, however, it still uses "mail" to send messages. Error messages now show the time of the error. The program no longer uses a "dot" file in the home directory. Instead, it creates a work directory with the same name as the output mail box with the extension ".d". By default, the program saves mail in "$HOME/bmw-mbox", and creates and uses the work directory, "$HOME/bmw-mbox.d". The "-undigest" option is now called the "-start" option. A new option "-START" restarts the daemon even if another daemon is running; any sleeping daemons will exit quietly when they wake up. Both options are easy to type on a QWERTY keyboard. A new option "-e" allows the user to edit a list of the files the majordomo has on line and to request them. The list also shows which digests have been received, turned stale, etc. A companion option, "-l", simply outputs the list. The undigestifier daemon may now be set to run for a single cycle, rather than continuously, yet still detect and request missing digests. Because of portability problems, the undigestifier no longer uses "ps" and "who" to determine if another daemon is already running. Instead, it looks at the last time a daemon touched the daemon i.d. file. If no daemon has touched the file in 3-4 hours, the "-start" option assumes no daemon is running and starts another. Thus the option may require up to 4 hours before it will start a new daemon. In the meantime, the user can force start a new daemon, with the "-START" option. The undigestifier was changed in a number of other ways to make it portable to a wider range of machines. The requester daemon tries to check for errors whenever and wherever it can. It also checks its error log periodically to catch errors it missed the first time around. In principle, any error that outputs an error message will eventually be caught. When started from scratch (with a blank history), the daemon no longer requests the ten most recent digest available from the majordomo; rather, it requests just the most recent one. The requester daemon checks if its history file has grown beyond a specified number of lines; it discards the earliest (oldest) lines if it has. The daemon checks if the mail system has stopped working: it quits if it has not received a bmw-digest index in more than five days. The daemon cleanly quits if it receives a signal -- once it has woken up, that is. The requester daemon tries to remove its i.d. file when it quits because of an error or a signal. This allows another daemon to start up immediately, rather than wait several hours for the i.d. file to age. The undigestifier process-mail program adds two more kills lists to the original list of senders to ignore. They are: subjects to ignore and one-line messages to ignore. The undigestifer also discards redundant digest contributions. It also discards duplicate contributions as well as short messages that look like junk. Long digest lines are folded to limit the number of fields per line to what "awk" can handle. Following the standard convention, the "awk" undigestifier escapes false mail message "From ..." lines in the digest body so that they read: ">From ...". You can now make a digest contribution's submission date, its receive date so that mail readers that do not distinguish between the two (for example, "mailx" and Sun's "mailtool") will display the submission date rather than its (local) receive date. v3.0a 20 Jul 1995 ibid. ----------------- The requester-daemon, undig, diverts unwanted "grep" output to /dev/null rather than try to suppress it with "grep -s". (The "-s" option outputs matching lines under System V.) v3.1 01 May 1996 ibid. ---------------- The 'path_undig' program now lists directories required by the user interface / requester daemon program, undig. The UPDATE interval parameter has been deleted. The from, subject and oneline message kill lists, FROM_KILL_LIST, SUBJECT_KILL_LIST and ONELINE_KILL_LIST have been changed to 'awk' regular expressions The parameter LONGEST_MLINE has been renamed to LONGEST_DLINE. By default, the daemon requests a new digest index every 22-24 hours rather than every 12 hours. (cf. REQD_INTERVAL and REQD_HOURS.) The requester-daemon, undig, and process mail program, undig_pm, now require a supplementary definition file specified on the command line with the option: "-d file". This allows the programs to process multiple majordomo mailing lists, simultaneously. The definitions specific to each mailing list have been moved out of the general definition file, undig_def, and into specific definition files such as: bmw_def [bmw mailing list], itacar_def [Italian cars mailing list] and skunk_def [Lockhead skunk works mailing list]. To undigest one of these groups, you must include "-d bmw_def" or "-d itacar_def", and so forth, on the command line. The following parameters have been added to the common undigestifier definitions file, undig_def: LOG_DIGESTS which controls whether requested and received digests are logged LOG_KILLS which controls whether killed messages are logged MAX_QLINE which sets the maximum allowed number of quoted lines The following parameters are included in each digest definition file, e.g. bmw_def: SUBJECT_PREFIX which adds the given prefix to the digest contribution subject lines, SUB_COM which defines the command to subscribe to the digest, UNSUB_COM which defines the command to unsubscribe from the digest. The requester-daemon will subscribe and unsubscribe to a digest when given the options "-subscribe" and "-unsubscribe". The requester-daemon, undig, sleeps until the start of the next hour rather than wake up periodically (by default every, 600 seconds). Patterns specific to the BMW mailing list have been removed from the process mail program, undig_pm. The process mail undigestifier awk program has been made simpler and faster, and now uses regular expressions in the subject, sender and oneline message kill lists, SUBJECT_KILL_LIST, FROM_KILL_LIST and LINE1_KILL_LIST. It is also more aggressive in killing junk messages and it truncates quoted passages that are longer than MAX_QLINE (40 lines by default). If the variable LOG_KILLS is non-null, the undigestifier will create a short mail message that summaries the messages it has killed showing the sender, sender date, subject and first body line. The original, global message kill lists have been renamed to SUBJECT_KILL_LIST0, FROM_KILL_LIST0, and LINE1_KILL_LIST0. You may now add specific sender and subject kill lists for a particular mailing list, by defining the awk/egrep regular expressions FROM_KILL_LIST and SUBJECT_KILL_LIST in its definition file. The undigestifier interface program, undig, only checks if the daemon has died when an i.d. file exists. It the file has not been touched for a least a day, undig warns the user that the daemon has died and then deletes the i.d. file to make that its one and only warning. To save disk space, the user interface program, undig, deletes the new majordomo index supplied by the undigestifier program, undig_pm, once, it has created a listing from it. SHAR_EOF fi echo shar: "extracting 'INSTALLATION'" '(15199 characters)' if test -f 'INSTALLATION' then echo shar: "will not over-write existing file 'INSTALLATION'" else cat << \SHAR_EOF > 'INSTALLATION' PREREQUISITES: In order to run this undigestifier, you need to use a mail filtering program, such as "elm filter" or "procmail", to collect mail from the the mailing list and 'pipe' it into the program. Of the two, "procmail" is much preferred because of its speed, robustness and file locking; "elm filter" will no longer be supported with the next release of "elm". This file gives instructions for both filter programs. You can "ftp" the current version of "procmail" from two locations: The European source site directory: ftp.informatik.rwth-aachen.de/pub/packages/procmail/ A North American mirror directory: ftp.psg.com/pub/unix/procmail/ The latest version is in the files procmail.tar.gz (gzip format) procmail.tar.Z (compress format) INSTALLATION: 1. If you have run a very old version of the undigestifier (version 2), remove any lines in your ".cshrc" and ".login" files that refer to "bmw", "undigest_bmw" or "bmw -undigest". Then remove any remaining temporary files in your home directory with the commands: rm $HOME/.undigest_bmw* rm -r $HOME/.bmw This will kill off any old copies of the undigestifier that may still be running. 2. Copy the definition files for the digests you wish to read, for example, bmw_def itacar_def skunk_def to a a directory in your command search path. By default, these files will direct messages from the corresponding digests to: ~/Mail/bmw-mbox ~/Mail/itacar-mbox ~/Mail/skunk-mbox If you would like to put the majordomo and digest messages in a some other mail box file or files, edit the corresponding definition files and change the digest's pathname: OUT_BOX. A companion data directory and lockfile will be created with the names, $OUT_BOX.d and $OUT_BOX.lock. 3. Edit the first three assignment lines in "undig_def", and, for the moment, no more! - Normally, when you run these programs, you will use the '-d' option to choose one of your definition files and define the mailing list you wish to read. If you do not specify a list with the '-d' option, the program will choose a mailing list for you. By default this is the BMW digest: bmw_def The instructions that follow assume and test this default list. If you do not want to read this list or would like to first try another, change the variable DEFAULT_LIST to the definition file name of the list you would like to read, for example: DEFAULT_LIST=itacar_def Make sure that you copied the corresponding definition file in step 2! - If you do not care for the default editor, EDITOR, or you have not defined this shell variable (try giving the command "echo $EDITOR"), change the third line to the editor you like to use, for example: EDITOR=vi or EDITOR=emacs - If you have a favorite program you like to use to read your mail, edit the next assignment line, READ_DIGEST_COMMAND, so that the program opens and reads the OUT_BOX. - Normally, a digest contribution's receive-date is set to the date its digest was exploded rather than the date the contribution was submitted to the mailing list. The date the contribution was submitted is set in the usual send-date line. This makes available both a contribution's receive- and send-dates. Some mail readers such as "mailx" or Sun's "mailtool" do not look at a mail message's send-date (i.e. they ignore the "Date:" line). Instead, they use its receive date in their summary of what is in the mail box. Consequently, what you will see is a contribution's explosion date. If you use such a mailers and would rather see the date a contribution was submitted, set the variable in the fourth line, DUP_SEND_DATE to: DUP_SEND_DATE=T This will duplicate the message's send date as its receive date. If, on the other hand, you use a mail reader that *can* distinguish between a message's receive- and send-dates, for example, 'elm', leave the line unchanged: DUP_SEND_DATE= 4. Copy the files undig undig_def undig_pm to the same directory you copied your mailing list definition files in step 2. 5. Give the command which fold to see if your system has the "fold" program. If it does, skip to step 8. 6. If it doesn't, compile the 'fold' source supplied with the undigestifier using the command: cc -o fold fold.c 7. Copy the resulting "fold" program to a directory in your command search path. 8. If you are running the C-shell, give the command rehash so that the shell finds the programs. 9. Run the undigestifier test script: test_undig The script will save a sample bmw-digest index and explode and save a sample digest. You should see the message: undig_pm: Created work directory '/...'. 10. Give the command: undig This should start your favorite mail reader and list the following three messages: 1 joe@machine.com Thu Jul 6 17:55 10/317 request-new 740IL fo... 2 wayne@aprf.arl.mil Thu Jul 6 17:55 14/603 Re: bmw-digest V1... 3 halsteds@atlanta.com Thu Jul 6 17:55 18/531 Spoiler and Gro... Verify that the messages are complete, delete them and then exit your mail program. After you exit you may see the message: Warning: The daemon is not running. This is normal. 11. Run the undigestifier path location program: path_undig It will locate the various programs the undigestifier uses. Write down the directories the program says should be included in the process-mail PATH. 12. If you are running the "procmail" program: A. Edit the sample 'procmail' startup up file, 'procmailrc'. Change the command path string, PATH, to include those directories. If you changed the mail OUT_BOX in step 2, be sure to update it here as well. Then, uncomment the lines for the mailing list you wish to read. Save your work and exit your editor. B. Copy or append the file to ~/.procmailrc If "procmail" is not installed as the default mail delivery agent on your system, create a "~/.forward" file as described in the NOTES section on the "procmail" man page. 13. If you are running the "elm filter" program, edit and append the sample "filter-rules" file to ~/.elm/filter-rules Don't forget to update the output mail box if you changed it in step 2. 14. Now give the command: undig -e This should start your favorite editor, open the file "status+request" and display a dummy bmw-digest index similar to the following (only the date should differ): index bmw-digest Thu Jul 6 17:59:29 MET DST 1995 Nov 22 16:52 README Nov 23 15:05 FAQ.0 Jan 1 22:10 v01.n999 + Jan 1 10:10 v01.n998 M Jump to the very beginning of the file and insert a single space in front of the first line. Save the file and exit your editor. Continue to ignore the "Daemon is not running" message. 15. You should see the message: Requesting new index from majordomo@lists.balltown.cma.com or the site that handles the list you wish to try. You have requested a copy of the digest index. Wait for that mail to arrive. An easy way to check if it has, is to list the index periodically with the command: undig -l 16. If your "procmail" or "elm filter" program has been configured correctly, it will feed the digest index to the undigestifier process-mail program, undig_pm. That program, in turn, will clean the message and replace the dummy digest index with a real one showing the files the majordomo has online. Give the command undig -e to see if that has happened. 17. Request the *second-most* recent digest that is listed by inserting a single space at the start of its line. Save the "status+request" file and exit your editor. Again you should see: Requesting 1 file from majordomo@lists.balltown.cma.com or something similar. Wait for that mail to arrive. An easy way to check if it has, is to periodically try the command: undig If there is no mail, it will return more or less immediately. 18. If your mail filter program is working correctly, it will feed the digest to "undig_pm". In turn, that program will explode the digest and save the individual contributions in the output mail box, OUT_BOX. Give the command: undig This should open the output mail box using your favorite mail reader. Verify that the digest exploded correctly. Do not be surprised if any bounced digests, subscription requests, repeated messages or the like have disappeared. The undigestifier is designed to do that. (Though unless you have set the log kills flag, LOG_KILLS, as described in the USAGE file, how will you know? :) 19. Again, edit the file "undig_def". If you plan to never run the daemon, leave the variable REQD_INTERVAL unchanged: REQD_INTERVAL=23 If you want to briefly run the daemon as you log in, set the variable REQD_INTERVAL to REQD_INTERVAL=22 or however often you want to pester the majordomo for another copy of the bmw-digest index and missing digests. (In this instance, at least 22 hours since you last did this.) If you want to run the daemon continuously, set REQD_INTERVAL to the null string: REQD_INTERVAL= If you like, check the rest of the lines in "undig_def" to see if they suit your tastes. They all should be pretty reasonable. If you really want to make my day, check the "sed" patterns as well. :) Save any changes you make and update the copy of "undig_def" you saved in your command search path. 20. If you wish to run the daemon, change to your home directory and add to your personal ".login" file a line for each mailing list you wish to keep track of. For example: undig -d bmw_def -start if you wish to follow the BMW digest or undig -d itacar_def -start if you are following the Italian Cars digest. Depending on how you have set REQD_INTERVAL, this will cause the undigestifier to do one of two helpful things each time you log in. If you have set the daemon to run continuously, the undigestifier will check if the requester daemon has died; if it has, it will start another. If you have set the daemon to run only once and you have not logged in recently (within one REQD_INTERVAL), the undigestifier will run the daemon for one quick cycle during which it will request a fresh copy of the digest's index and any missing digests. 21. For convenience, add the undigestifier's output mail box to the list of files the shell should check for mail. For example, if you are reading the bmw digest, running the C-shell and are directing mail to the default bmw output mail box, you could add the following line to your ".cshrc" file set mail = (/usr/spool/mail/$USER $HOME/Mail/bmw-mbox) or if you wish to check your mail every 300 seconds set mail = (300 /usr/spool/mail/$USER $HOME/Mail/bmw-mbox) While you are editing ".cshrc", you might also add an agreeable alias of 'undig' for each list you would like to read. For example: alias undig -d bmw_def bmw alias undig -d itacar_def itacar will allow you to access the BMW and Italian Car digests with the commands 'bmw' and 'itacar'. If you are using the Bourne shell, you can write an equivalent shell script, for example: : undig -d bmw_def $* Please note that when the 'undig' program outputs a usage summary, it assumes the alias you have chosen is the first half of the mail list's definition file name, for example: definition_file_name assumed_alias -------------------- ------------- bmw_def bmw itacar_def itacar If you want to specify a list with a different alias, you should change its definition file name accordingly, for example: beemer_def beemer 22. If you are not yet subscribed to the digest you wish to try, give the command: undig -subscribe If you ever wish to unsubscribe, you may with the command: undig -unsubscribe 23. While you are still in your home directory, start or run the requester daemon with the commands: rehash [if you are running the csh] source .login You should see the message undig:bmw-mbox: Daemon started. or undig:bmw-mbox: Daemon cycled. or something similar, depending on the mailing list you are trying and how you are running the daemon. If you have renamed the OUT_BOX, its name will appear instead of "bmw-mbox". The "daemon cycled" message is only printed this once. Note that the daemon will not run if you have unsubscribed from the list as discussed in the previous step. 24. If you are running the daemon only once, the program should request another copy of the digest index as well as a copy of the most recent bmw-digest. Skip to step 26. 25. If you are running the daemon continuously, verify that it is running by scanning all your processes with something like: ps -e | grep 'undi[g]' or ps x | grep 'undi[g]' You should see a line like: 4022 p1 IWN 0:00 sh /usr1/jfiresto/Bin/undig -daemon Within 24 hours, the daemon should request a new copy of the digest index. Within 27 hours, it should request a copy of the latest digest that appeared in the digest index at step 16, as well as any new digests that have appeared since. 26. Wait for the new index and the digest(s) to arrive. 27. Using the command undig read and verify the latest digest(s). 28. Using the command undig -e verify that undigestifier has updated the history. The most recent digests you requested and read should have capital M's after their names showing that they were originally missing. The other, older digests should have capital S's, showing that they are stale. For example: index bmw-digest Thu Jul 6 18:30:09 MET DST 1995 Nov 23 1994 FAQ.0 Nov 22 1994 FAQ.1 . . . Nov 22 1994 FAQ.12 Jul 6 06:10 v03.n457 M Jul 5 21:10 v03.n456 M Jul 5 06:10 v03.n455 S Jul 4 21:10 v03.n454 S Jul 4 06:10 v03.n453 S . . . You may see other letters or symbols as well. These are explained in the USAGE file in the section: "Examining the digests received and files available". 29. This completes the installation. Happy undigestifying and be sure to report any bugs you find! ---- John Firestone 1 May 1996 jfiresto@awi-bremerhaven.de SHAR_EOF fi echo shar: "extracting 'USAGE'" '(12265 characters)' if test -f 'USAGE' then echo shar: "will not over-write existing file 'USAGE'" else cat << \SHAR_EOF > 'USAGE' ======== OVERVIEW ======== Some months ago, Richard Welty had to change the bmw mailing list to its present digest format. Since then, we have discovered the advantages and disadvantages of receiving bmw digests. While we no longer see days when a blizzard of messages threatened to fill our mailboxes faster than you can say "ABS", unfortunately, we now suffer two new problems the digests have created. Everything, both the wheat and the chaff, is now globbed together, making it a great nuisance sometimes finding the articles we want to read and reply to. Entire digests are delayed for days, or sometimes they don't come at all, making it hard to maintain a dialogue. This BMW undigestifier was written to solve both these problems, and if I make no mistake, it makes the bmw-digests work even better than the old bmw mailing list. The program explodes the bmw digests into their individual contributions and fills a mailbox with the messages. The result looks very much like the old mailing list, only better. The undigestifier searches for and discards repeated and bounced messages as well as subscription and file requests. The program also automatically detects and requests missing digests. The number of junk messages you see should drop to 1/4th of what it used to be. Provided the e-mail system is running and your machine does not crash, you should never fall more than a day behind. PROGRAM ORGANIZATION -------------------- The undigestifier is split into four parts: - a mail undigestifier, - a requester daemon and user program, - and two sets of definitions. To use the program, you must be running a mail filtering system such as "procmail" or "elm filter". You use the filtering system to feed bmw-digests and majorodomo messages to the mail undigestifier. The undigestifier process-mail program, undig_pm, cleans and saves bmw-digest indexes, logs the bmw-digests and explodes the digests you haven't seen into their individual messages; it throws away the junk messages it finds, and it saves the remaining messages in an output mail box, OUT_BOX. The requester daemon and user program, undig, periodically requests a bmw-digest index from the majordomo; from that, it finds and requests any digests that have been delayed or have disappeared. The program also points your favorite mail reader at the exploded digests so that you may easily read them. It also lists the digests you have received and the files the majordomo has online, and lets you request any and all using your favorite text editor and a few key strokes. A common definitions file, undig_def, controls the behavior of both programs. A specific definitions file, for example bmw_def, tailors the programs to the particular mailing list you wish to read. ================== USING THE PROGRAMS ================== THE UNDIGESTIFIER PROCESS-MAIL PROGRAM, undig_pm ------------------------------------------------ Once you have plugged the mail undigestifier, undig_pm, into your mail filter system as explained in the INSTALLATION instructions, there is really not much you need to do with it. In the definitions file, undig_def, there are three kill lists that over time you might add to. They specify the senders, subjects and one-line messages that the undigestifier discards. I have set them to discard many bounced digests, as well as most subscription and file requests that should have gone to the majordomo. There are also second subject and sender kill lists in each mailing list definition file, if you wish to be a more selective article assasin. To help debug your kill lists, you can have the undigestifier send you a post-mortem on yours kills - and mine as well - by setting the variable LOG_KILLS in the definitions file, undig_def: LOG_KILLS=T I wish you good hunting. THE REQUESTER DAEMON, undig --------------------------- Similarly, there is not much you need to do with the requester half of "undig", the requester daemon and user interface program. Mostly, you need to decide whether you want to run the daemon all the time, or once when you log in, or not run it at all. The INSTALLATION instructions explain how. THE USER INTERFACE PROGRAM, undig --------------------------------- With the "undig" user interface program, you can read any new digests or majordomo files that have arrived, examine the digests you have received, and query the files the majordomo has on line. To use the program, you need to specify which mailing list you want to access by giving the "-d" option followed by the name of the list's definition file. If you are running the c-shell, you will find it most convenient to define an alias for each mailing list. For example, for the 'bmw' mailing list you would define: alias bmw undig -d bmw_def If you are running the bourne shell, you might write a short shell script to do the same thing, for example: : undig -d bmw_def $@ Then instead of typing undig -d bmw_def -e to examine the bmw digest log, you can type bmw -e As these examples suggest, the alias you choose to read a mailing list should be the first half of the name of its definition file. This is the name the user interface program, undig, assumes when you ask it for help. If you use the same name, when you ask for help: bmw -help it will show the correct alias: Usage: bmw Read the new messages. bmw -e Examine the files online and request them. bmw -kill_daemon Kill the daemon. bmw -l List the files online. bmw -START Force start the daemon even if it died recently. bmw -subscribe Subscribe to the digest. bmw -unsubsribe Unsubscribe from the digest. These rest of these instructions will assume you have defined such a definition for each of your mailing lists. If you want to access a mailing list under a different alias name than what I have given, change the name of its definition file accordingly. Now, suppose you wish to read the bmw mailing list. Subscribing and unsubscribing to a digest ----------------------------------------- To subscribe to the bmw digest, give the command: bmw -subscribe To unsubscribe, give the command: bmw -unsubscribe If you have been running a requester daemon to read the list and have put a line in your .login file to restart the daemon, you may wish to remove it, though you do not have to. Until you ask to "-subscribe" again, the daemon will not restart unless you force it to with the "-START" command described below in the "Housekeeping" section. Reading the new digests and files --------------------------------- To read the new digests and files, give the command: bmw If any have arrived, the undigestifier program, undig_pm, will have put them in the output mail box specified during INSTALLATION; the "undig" program will now open the messages using your favorite mail reader. You may read, reply to and delete them. After you quit your mail reader, the program will report any mail processing errors. If you have set the requester daemon to run continuously, it will also do a quick and dirty check to see if it is running. Examining the digests received and files available -------------------------------------------------- To catalog the digests you have received and see the files the majordomo has online, give the command: bmw -e This will open a copy of the latest bmw-digest index you have received, (if any). The top line gives the time you received the index. The next block of lines list the non-digest files the majordomo has online. The final block list the bmw-digests it has online, starting with the most recent. You may see the following status characters following the digests' names: A: Indicates: -- ----------- + The digest was received normally D The digest was received after some delay M The digest was missing and had to be requested from the majordomo R The digest was repeated S The digest has become so old it is now stale . The digest has been requested but has not yet been received Requesting a file the majordomo has on line ------------------------------------------- After you give the command bmw -e you may request any file that is shown or a new copy of the index by editing and saving the listing. To request a file, insert a space at the start of its line (indent its line one space). If the file is a digest followed by one of the above status characters, you can also request it by changing the status character to a "<", the less-than symbol. This is a very fast way to request a number of digests if your editor can do a global search and replace. To request a new copy of the bmw-digest index, insert a space in front of the first line. ==================== GENERAL HOUSEKEEPING ==================== Cleaning the history file ------------------------- Assuming you have not changed the file names in the common definitions files, undig_def, or the mailing list definition file, bmw_def, both the undigestifier program and requester daemon save BMW-related messages in the mail box: ~/Mail/bmw-mbox The two programs create a directory that holds various status and log files. By default it is: ~/Mail/bmw-mbox.d Within that directory the two programs keep a history of the digests that have been received and requested, by default: ~/Mail/bmw-mbox.d/history If you remove the history, the requester daemon and undigestifier program will have no past; both will start over from scratch and request copies of the bmw-digest index and the latest bmw-digest. If you are running the requester daemon continuously or once when you log in, you should not need to touch the history file. The daemon watches the history as it grows and automatically discards its earliest (oldest) entries when it become too large (by default, more than 4400 lines). If you never run the undigestifier daemon, you may have to do this by hand once in a while. The first time, however, might be sometime after you retire your computer. Restarting the requester daemon ------------------------------- If you are running the requester daemon continuously and have added the line undig -d bmw_def -start in your ".login" file as per the INSTALLATION instructions, should the daemon die, it will be restarted automatically if you log in again at least four hours later. If you wish to restart the daemon before the four hours have elapsed, give the command: bmw -START Before you do this, make sure that the old daemon is dead or at least sound asleep (see the next item). Killing the requester daemon ---------------------------- The easiest way to kill the requester daemon, if you are running it continuously, is with the command: bmw -kill_daemon Another way is to unsubscribe from its digest. Both ways may take up to an hour. This is because the daemon does not actually run continuously. When it has nothing to do, the daemon goes to sleep until the start of the next hour, whereupon it checks if it has anything to do, or if it should die. Since its work requires only a few seconds once in a while, the daemon spends most of its time sleeping. Another, very quick and clean way to kill the daemon is to kill its sleep process. If you list all your processes including those detached from any terminal, perhaps with ps x you should see a detached sleep process when the daemon is inactive. It will have a three- or four-digit period with the last three digits all the same, for example: sleep 3666 Kill this sleeper before it wakes up. ================ ACKNOWLEDGEMENTS ================ I would like to thank Al Cote for his heroic alpha-testing of this undigestifier, during which I believe I trashed his mailbox, though only once. :) He set aside his own undigestifier to look at mine, found a couple of subtle bugs which we are now fortunate not to experience and made a number of suggestions that led to substantial improvements in the program. ---- John Firestone 01 May 1996 jfiresto@awi-bremerhaven.de SHAR_EOF fi echo shar: "extracting 'filter-rules'" '(366 characters)' if test -f 'filter-rules' then echo shar: "will not over-write existing file 'filter-rules'" else cat << \SHAR_EOF > 'filter-rules' # # Sample "elm filter" rule file for the BMW undigestifier # # Make a copy of this file, edit it appropriately, and then append it # to '~/.elm/filter-rules'. # if (from matches /bmw-digest.*mailgate\.wizvax\.net/) then execute "undig_pm >> $HOME/Mail/bmw-mbox" if (from matches /majordomo.*mailgate\.wizvax\.net/) then execute "undig_pm >> $HOME/Mail/bmw-mbox" SHAR_EOF fi echo shar: "extracting 'fold.c'" '(3402 characters)' if test -f 'fold.c' then echo shar: "will not over-write existing file 'fold.c'" else cat << \SHAR_EOF > 'fold.c' #include #include #define DEFAULT_WIDTH 80 /* The default output width */ char *program; /* This program's name */ /* * fold - Fold long lines for display on a output device of a given width. * * Usage: fold [-width] [files] * * Fold the contents of the specified files, or the standard input if no * files are given. Break the lines so that they are no more than * the maximum width, by default 80. * * BUGS: A file name can not start with a dash, '-'. * Underlining and non-standard tabs may spoil the folding. The * latter should first be changed to spaces using 'expand'. * The Berkeley version of 'fold' outputs a spurious leading newline * when the width is less than eight and a tab is the first character * on a line. This program doesn't. Berkeley 'fold' also outputs * non-blank lines when the width is zero. With this program, if * you ask for output that fits on a zero-width device, you get it: * one empty line for each character on a line and each blank line. */ static char *sccsid = "@(#)RELEASE v1.1 11 Jul 1995 John Firestone"; main(argc, argv) int argc; char **argv; { int c; int col; /* The current column */ int col0; /* The previous column */ char *cp; char *file; /* The current file */ int width; /* The output width */ sccsid += 0; /* Lint pacifier */ /* * Get the program's name and the output width. */ program = *argv++; width = DEFAULT_WIDTH; if (--argc > 0 && *(cp = *argv) == '-') { do { /* Verify the width is a valid integer. */ cp++; } while (isdigit(*cp)); if (*cp != '\0' || sscanf(*argv+1, "%d", &width) != 1) { (void) fprintf(stderr, "Usage: %s [-width] [files]\n", program, *argv); exit(1); } argc--; argv++; } do { /* * Open the next file. If no files were specified, use standard in. */ file = ""; if (argc > 0) { file = *argv++; if (freopen(file, "r", stdin) == NULL) { (void) fprintf(stderr, "%s: Can not open '%s'.\n", program, file); exit(1); } } /* * Output the file, character-by-character, folding long lines. */ col = 0; while ((c = getchar()) != EOF) { /* * Determine the column position after the character is output. */ col0 = col; if (c == '\t') col += 8-(col%8); else if (c == '\n') col = 0; else col++; /* * If we are outputting to a zero-width device, output a * newline for each blank line and each character on a line. * If we are not, break the line if it would grow too long. */ if (width == 0) { if (c == '\n' && col != col0) continue; else c = '\n'; } else if (col0 > 0 && col > width) { if (putchar('\n') == EOF) { (void) fprintf(stderr, "%s: Write error while folding '%s'.\n", program, file); exit(1); } col = (c == '\t') ? 8 : 1; } /* * Output the character. */ if (putchar(c) == EOF) { (void) fprintf(stderr, "%s: Write error while folding '%s'.\n", program, file); exit(1); } } /* * Check for read errors. */ if (ferror(stdin)) { (void) fprintf(stderr, "%s: Error reading '%s'.\n", program, file); exit(1); } } while (--argc > 0); exit(0); /*NOTREACHED*/ } SHAR_EOF fi echo shar: "extracting 'path_undig'" '(1801 characters)' if test -f 'path_undig' then echo shar: "will not over-write existing file 'path_undig'" else cat << \SHAR_EOF > 'path_undig' : # @(#) undigestifier find-command-paths program v3.1 01 May 1996 # John Firestone, jfiresto@awi-bremerhaven.de # # Find the directories needed in the 'procmail' PATH and also check # if a system has all the programs needed to run the undigestifier. # # # The programs used by the undigestifier process mail program and the # additional programs by the requester daemon. # PROGS_undig_pm='awk basename cat date echo fold mkdir mv rm sed sh test undig undig_def undig_pm' PROGS_undig='cmp find grep ls nice sleep tail touch tr undig' # # Change to the '/dev' directory, which most likely contains none of the # above programs, and try to find the programs' directories. Collect the # directory names we find as well as the names of the programs we can # not locate. First do this for the programs used in the process mail # program then for the programs used in the requester daemon program. # ORG_DIR=`pwd` cd /dev FOUND="" NOT_FOUND="" echo 1>&2 "Locating programs...." for PROG in `echo $PROGS_undig_pm $PROGS_undig` do echo 1>&2 " $PROG" DIR=`which $PROG | sed 's/\/[^\/]*$//'` echo "$DIR" | grep 2>/dev/null ' ' && DIR="" if test $DIR then FOUND="$FOUND $DIR" else NOT_FOUND="$NOT_FOUND $PROG" fi done # # Output the programs we could not locate. # if test "$NOT_FOUND" then echo 1>&2 "Could not located the following programs:" echo $NOT_FOUND | tr ' ' '\012' | sed 's/^/ /' fi # # Sort the directory names, eliminate duplicates and output the # required directories. Output a path from the home directory, where # that is convenient. # HOME2=`echo $HOME | sed 's/\//\\\&/g'` echo 'The process-mail PATH should include the following directories:' echo $FOUND | tr ' ' '\012' | sort | uniq | sed "s/^/ /" \ | sed "s|$HOME|\$HOME|" SHAR_EOF chmod +x 'path_undig' fi echo shar: "extracting 'procmailrc'" '(2065 characters)' if test -f 'procmailrc' then echo shar: "will not over-write existing file 'procmailrc'" else cat << \SHAR_EOF > 'procmailrc' # @(#) Sample ".procmailrc" file for the undigestifier v3.1a 01 Aug 1996 # John Firestone, jfiresto@awi-bremerhaven.de # Sample ".procmailrc" file for the undigestifier # # Make a copy of this file and uncomment the double-commented lines of # the lists you wish to receive, e.g.: # # ## :0 wi : # ## * ^From .*skunk-works-digest # ## | undig_pm -d skunk_def >> $HOME/Mail/skunk-mbox ; exit 0 # # Then move the copy to "~/.procmailrc". # # My copies of "undig," "undig_pm," etc. are in "$HOME/Bin" and our # "tail" program is in /usr/ucb. Thus, I need to include both # directories in the PATH. (The 'path_undig' program should tell you # what you need to include.) # PATH=/bin:/usr/ucb:$HOME/Bin MAILDIR=$HOME/Mail LOGFILE=$MAILDIR/log # # Undigestify mail from the bmw-digest mailing list and its majordomo. # Wait for that to complete and use a lockfile to avoid competing # updates. Also ignore errors: we can always ask for a digest again - # there is no neet to bounce it back to the mailing list or the majordomo. ## :0 wi : ## * ^From .*bmw-digest.*mailgate\.wizvax\.net ## | undig_pm -d bmw_def >> $HOME/Mail/bmw-mbox ; exit 0 ## :0 BEHwi : ## * ^From .*majordomo.*mailgate\.wizvax\.net ## * ^(Subject:|>>>> index|>>>> get).*bmw-digest ## | undig_pm -d bmw_def >> $HOME/Mail/bmw-mbox ; exit 0 # # Undigestify mail from the italian-cars-digest mailing list and its. # majordomo. # ## :0 wi : ## * ^From .*italian-cars-digest.*mailgate\.wizvax\.net ## | undig_pm -d itacar_def >> $HOME/Mail/itacar-mbox ; exit 0 ## :0 BEHwi : ## * ^From .*majordomo.*mailgate\.wizvax\.net ## * ^(Subject:|>>>> index|>>>> get).*italian-cars-digest ## | undig_pm -d itacar_def >> $HOME/Mail/itacar-mbox ; exit 0 # # Undigestify mail from the skunk-works mailing list. # ## :0 wi : ## * ^From .*skunk-works-digest ## | undig_pm -d skunk_def >> $HOME/Mail/skunk-mbox ; exit 0 # # Undigestify mail from the Numerical Analysis mailing list. # ## :0 wi : ## * ^From .*na.digest ## | undig_pm -d na_def >> $HOME/Mail/na-mbox ; exit 0 SHAR_EOF fi echo shar: "extracting 'test_undig'" '(6769 characters)' if test -f 'test_undig' then echo shar: "will not over-write existing file 'test_undig'" else cat << \SHAR_EOF > 'test_undig' : # @(#) BMW undigestifier test program v3.1 01 May 1996 # John Firestone jfiresto@awi-bremerhaven.de # . undig_def PM_PROG=undig_pm # Undigestifier process mail program if [ -s $OUT_BOX ] then echo 1>&2 You have mail in the mail box "'$OUT_BOX'". echo 1>&2 Delete or save this mail and then rerun this program. exit 1 fi echo Test 1 - Ignore a simple message acknowledgement. sed 's/^ *//' < $OUT_BOX From majordomo-owner@lists.balltown.cma.com Tue Jan 2 00:00:01 1900 Return-Path: Date: Tue, 2 Jan 1900 00:00:01 -0400 From: majordomo@lists.balltown.cma.com Subject: Majordomo results Reply-To: majordomo@lists.balltown.cma.com -- >>>> get bmw-digest v01.n998 List 'bmw-digest' file 'v01.n998' is being sent as a separate message. END echo Test 2 - Save a digest received from the majordomo. sed 's/^ *//' <> $OUT_BOX From majordomo-owner@lists.balltown.cma.com Tue Jan 2 00:00:02 1900 Return-Path: Date: Tue, 2 Jan 1900 00:00:02 -0400 From: majordomo@lists.balltown.cma.com Subject: Majordomo file: list 'bmw-digest' file 'v01.n998' Reply-To: majordomo@lists.balltown.cma.com -- From: owner-bmw-digest To: bmw-digest@lists.balltown.cma.com Subject: bmw-digest V1 #998 Reply-To: bmw-digest Errors-To: owner-bmw-digest Precedence: bulk bmw-digest Tuesday, 2 January 1900 Volume 01 : Number 998 Forum for Discussion of BMW Automobiles, etc. Richard Welty Digest Coordinator Contents: request-new 740IL for sale SUBSCRIBE Re: bmw-digest V1 #997 - bolts Send administrative requests to bmw-digest-request@lists.balltown.cma.com To unsubscribe, include the word unsubscribe by itself in the body of the message, unless you are sending the request from a different address than the one that appears on the list. Include the word help in a message to bmw-digest-request to get a list of other majordomo commands. ---------------------------------------------------------------------- From: joe@machine.com Date: Mon, 1 Jan 00 14:41:38 PDT Subject: request-new 740IL for sale I am attempting to help my sister who ordered a 95 740il and now went on disability and can't afford. The cost will be below retail. Thanks for the forth coming information. Joe > > Oops. I accidently quoted the rest of the digest. > > blah blah blah > blah blah blah > blah blah blah > blah blah blah > blah blah blah > blah blah blah > blah blah blah > blah blah blah > blah blah blah > blah blah blah > blah blah blah > blah blah blah > blah blah blah > blah blah blah > blah blah blah > blah blah blah > blah blah blah > blah blah blah > blah blah blah > blah blah blah > blah blah blah > blah blah blah > blah blah blah > blah blah blah > blah blah blah > blah blah blah > blah blah blah > blah blah blah > blah blah blah > blah blah blah > blah blah blah > blah blah blah > blah blah blah > blah blah blah > blah blah blah > blah blah blah > blah blah blah > blah blah blah > blah blah blah > blah blah blah > blah blah blah > blah blah blah > blah blah blah > blah blah blah > blah blah blah > The undigestifier should not print this line! ------------------------------ From: newbie@gateway.com (Newt Newbie) Date: Mon, 1 Jan 00 15:01:24 PDT Subject: SUBSCRIBE SUBSCRIBE ------------------------------ From: wayne@aprf.arl.mil Date: Mon, 1 Jan 1900 22:31:00 +0000 (GMT) Subject: Re: bmw-digest V1 #997 - bolts A couple other possibilities are as torque multiplier for your socket (see the Snap-On catalogue) or a larger impact (your local Rent-All place might have a 1" drive, or maybe the local Caterpillar dealer will rent one) - -- Wayne Flowers Voice: 505-678-8303 Senior Scientist Fax: 505-678-6049 Science & Technology Corp. E-mail: wayne@aprf.arl.mil White Sands, New Mexico URL: http://aprf.arl.mil/ ------------------------------ End of bmw-digest V1 #998 ************************* END echo Test 3 - Save a digest received from the mailing list. sed 's/^ *//' <> $OUT_BOX From owner-bmw-digest@lists.balltown.cma.com Tue Jan 2 00:00:03 1900 To: bmw-digest@homer.balltown.cma.com Subject: bmw-digest V1 #999 Reply-To: bmw-digest@lists.balltown.cma.com bmw-digest Thursday, 2 January 1900 Volume 01 : Number 999 Forum for Discussion of BMW Automobiles, etc. Richard Welty Digest Coordinator Contents: Spoiler and Ground effects kit bmw-digest V1 #997 -Reply Send administrative requests to bmw-digest-request@lists.balltown.cma.com To unsubscribe, include the word unsubscribe by itself in the body of the message, unless you are sending the request from a different address than the one that appears on the list. Include the word help in a message to bmw-digest-request to get a list of other majordomo commands. ---------------------------------------------------------------------- From: halsteds@atlanta.com Date: Mon, 1 Jan 00 09:55:57 PDT Subject: Spoiler and Ground effects kit - -------------------------------- Name: Derek Halstead E-Mail: halsteds@atlanta.com Date: 01/01/00 Time: 10:00pm - -------------------------------- I am the owner of a 1994 BMW 325IS. I recently began looking for a spoiler and ground effects kit. I did find what I was looking for at the dealer, however, I think the parts are far to expensive. Do you have any suggestions? ------------------------------ From: Harold Holiday Date: Mon, 1 Jan 1900 14:11:18 +0200 Subject: bmw-digest V1 #997 -Reply I'm on leave until the 22.01.1900 Please contact x1234 if urgent. Thank you. Harry. ------------------------------ End of bmw-digest V1 #999 ************************* END echo Test 4 - Save a dummy bmw-digest index. sed 's/^ *//' <> $OUT_BOX From majordomo-owner@homer.balltown.cma.com Tue Jan 2 00:00:00 1900 Date: Tue, 2 Jan 1900 00:00:04 -0400 From: majordomo@lists.balltown.cma.com Subject: Majordomo results Reply-To: majordomo@lists.balltown.cma.com -- >>>> index bmw-digest total 42 -rw-r--r-- 1 majordom 278 Nov 22 16:52 README -rw-r--r-- 1 majordom 4737 Nov 23 15:05 FAQ.0 -rw-rw---- 1 majordom 18050 Jan 1 10:10 v01.n998 -rw-rw---- 1 majordom 20365 Jan 1 22:10 v01.n999 END SHAR_EOF chmod +x 'test_undig' fi echo shar: "extracting 'undig'" '(20906 characters)' if test -f 'undig' then echo shar: "will not over-write existing file 'undig'" else cat << \SHAR_EOF > 'undig' : # @(#) BMW undigestifier interface/daemon v3.1 01 May 1996 John Firestone # jfiresto@awi-bremerhaven.de # # With this program, the user may view new mail and program errors, # start or force start the requester daemon and list the files the # majordomo has online and request them. The daemon periodically # requests a list of the files the majordomo has online (the majordomo # index). It compares the list after a healthy transmission delay to # the digests that have been received (as listed in a history) and # automatically requests the digests that are missing. # BUGS: The sequence "undig -l | head" ends with the message: "Can # not list the majordomo files." The sequence "undig -l | tail" # does not. # The help message outputs this program's unaliased name. # # Get the program's name. Get and execute the definition files. # PROG_NAME=`basename $0` DEF_FILE="" if test "+$1" = "+-d" then test "+$2" = "+" && echo 1>&2 "Usage: $PROG_NAME [-d def_file]" && exit 1 DEF_FILE="$1 $2" . $2 . undig_def . $2 shift ; shift else . undig_def fi # # Define the command string to report an error. Later we will append " -rmid" # so that we remove the daemon i.d. file on errors. To report an error within # the program, use the code: $CANT "do something" This will be printed as: # "program: Can not do something." # If given the error option, print an error message and exit. # CANT="exec $PROG_NAME $DEF_FILE -err" if test "+$1" = "+-err" then test "+$2" = "+-rmid" && shift && rm -f $ID_FILE BOX_NAME=`basename $OUT_BOX` DATE=`date 2>/dev/null` echo 1>&2 "$PROG_NAME:$BOX_NAME: Can not $2. $DATE" exit 1 fi # # Create the work directory if it does not already exist. # if test ! -d $WORK_DIR then mkdir $WORK_DIR || $CANT "create the work directory" echo 1>&2 "$PROG_NAME: Created work directory '$WORK_DIR'." fi # # Set/reset the run-daemon-once flag. Parse the command line. # RUN_ONCE="" ; test "$REQD_HOURS" || RUN_ONCE=T case "+$1" in # # Check if the user has any interesting mail and let him read it. # +) test -s $OUT_BOX && $READ_DIGEST_COMMAND # # Report any old errors and clear them. Quickly check if the daemon # has died by checking if it has touched its i.d. file over the last day # Issue a warning, only once, if it is not running and it should be. # test ! -s $D_ERR_FILE \ || (cat 1>&2 $D_ERR_FILE && cp /dev/null $D_ERR_FILE) \ || $CANT "report/clear error messages" test ! -s $M_ERR_FILE \ || (cat 1>&2 $M_ERR_FILE && cp /dev/null $M_ERR_FILE) \ || $CANT "report/clear error messages" test $RUN_ONCE || test ! -f $ID_FILE \ || grep unsubscribed $ID_FILE 2>/dev/null >/dev/null \ || test "`find $ID_FILE -mtime 0 -print 2>/dev/null`" \ || (echo 1>&2 "Warning:`basename $OUT_BOX`: The daemon is not running." \ ; rm $ID_FILE) exit 0 ;; # # Run the daemon. # +-daemon) A_DAEMON=T # Flag that we are a daemon. ;; # # Show the files the majordomo has on line, show their status and let # the user request what files he wants. # +-e) # # Create the edit directory if it doesn't already exist. # if test ! -d $EDIT_DIR then mkdir $EDIT_DIR || $CANT "create the edit directory" echo 1>&2 "$PROG_NAME: Created edit directory '$EDIT_DIR'." fi # # Make a copy of the index listing; bail out if there is nothing to # list. Let the user edit the copy. # $PROG_NAME $DEF_FILE -l > $EDIT_FILE \ || $CANT "create status-and-request file" if test -s $EDIT_FILE then : else test "$REQI_COM" || exit 0 echo $REQI_COM > $EDIT_FILE fi test $EDITOR || EDITOR=vi (cd $EDIT_DIR ; $EDITOR $EDIT_FILE) || $CANT "edit status-and-request file" # # If the user has selected the header line, request a new file index. # if test "$REQI_COM" && grep "^ $REQI_COM" $EDIT_FILE 2>/dev/null >/dev/null then echo "$REQI_COM" | mail $DOMO_RADDR || $CANT "request new file index" echo 1>&2 "Requesting index from $DOMO_RADDR" fi # # Find and output in reverse order the files the user has selected: lines # marked with a "<"; lines with a trailing status character, indented # one space; and lines without one, indented one space. Count the files. # awk 'NR>1 && NF>1 && $NF=="<" { file[++i]=$(NF-1) ; next } NR>1 && NF>1 && /^ / && length($NF)<=1 { file[++i]=$(NF-1) ; next } NR>1 && NF>1 && /^ / && length($NF)>1 { file[++i]=$NF ; next } END { while (i>0) print file[i--] } ' $EDIT_FILE 2>/dev/null > $EDIT_FILE.tmp CNT=`grep -c . $EDIT_FILE.tmp 2>/dev/null` # # Log the digests being requested so that the process-mail program # does not discard them when they arrive. Update the file index # listing by requesting a copy and then discarding it. Request the # files from the majordomo. Announce what we have done. # if test 0$CNT -gt 0 then if test $LOG_DIGESTS then sed -n "s/$DIGEST_VNPAT2/\2.\4 U/p" $EDIT_FILE.tmp \ >> $HIST_FILE || $CANT "log digest requests" $PROG_NAME $DEF_FILE -l 2>/dev/null > /dev/null & fi test "$REQD_COM" || $CANT "request digest(s) - do not know how" sed "s/^/$REQD_COM /" $EDIT_FILE.tmp | mail $DOMO_RADDR \ || $CANT "request files" S="s" ; test 0$CNT -gt 1 || S="" echo 1>&2 "Requesting $CNT file$S from $DOMO_RADDR" fi # # Clean the edit directory, report any old errors and clear them. # Quickly check if the daemon has died, by checking if it has # touched its i.d. file over the last day. Issue a warning, only # once, if it is not running and it should be. # rm -f $EDIT_DIR/* test "`ls $EDIT_DIR`" && $CANT "clean the edit directory, '$EDIT_DIR'" test ! -s $D_ERR_FILE \ || (cat 1>&2 $D_ERR_FILE && cp /dev/null $D_ERR_FILE) \ || $CANT "report/clear error messages" test ! -s $M_ERR_FILE \ || (cat 1>&2 $M_ERR_FILE && cp /dev/null $M_ERR_FILE) \ || $CANT "report/clear error messages" test $RUN_ONCE || test ! -f $ID_FILE \ || grep unsubscribed $ID_FILE 2>/dev/null >/dev/null \ || test "`find $ID_FILE -mtime 0 -print 2>/dev/null`" \ || (echo 1>&2 "Warning:`basename $OUT_BOX`: The daemon is not running." \ ; rm $ID_FILE) exit 0 ;; # # List the files the majordomo has on line and show their status. # +-l) # # If there is a new index file, overwrite the old index file # listing and flag that the digest entries should be reversed. # if test -s $INDEX_FILE then mv $INDEX_FILE $INDEX_FILE.ls \ || $CANT "save the majordomo file listing" REVERSE=reverse else # # Quit if neither a new file index or an old file index listing # exists. Output the index listing if it is newer than the history. # If the history is newer, update the index file listing leaving # the digest order unchanged. # test $INDEX_FILE.ls || exit 0 if test "`find $HIST_FILE -newer $INDEX_FILE.ls \ -print 2>/dev/null`" = "" then cat $INDEX_FILE.ls || $CANT "list the majordomo files" exit 0 fi REVERSE="" fi # # Touch the index file listing to fend off competing updates. # List the majordomo's non-digest files. Insert a blank line # after the header line (the first line). # touch $INDEX_FILE.ls || $CANT "touch the majordomo file listing" sed -n "/^$/d /.*$DIGEST_VNPAT2.*/!p 1s/.*//p" $INDEX_FILE.ls > $INDEX_FILE.ls.tmp \ || $CANT "list the majordomo's non-digest files" # # List the digest files and their status in reverse order. The # echo line passes the reverse flag to the 'reverse' clause. The # 'cat' line feeds the history file, to the NF==2 clause. The # first 'sed' line feeds to the NF==5/6 clauses, the new file index # or the old index listing, prefixed line-by-line with the digests' # packed history names. The final 'sed' line removes those packed names. # WARNING: Do not put ANY single-quote marks in the awk program comments. # (echo $REVERSE ; test -f $HIST_FILE && cat $HIST_FILE ; \ sed -n "s/\(.* \)$DIGEST_VNPAT2/\3.\5 \1\2\3\4\5/p" $INDEX_FILE.ls) \ | awk ' BEGIN { cnt = 0 # Reset the digest count. reverse = 0 # Clear the reverse digest order flag. } /^reverse$/ { reverse = 1 } # List digests in reverse order. # # Using the previous digest status + its current status --> change # the digest status using the following state transition list: # any + S -> S # D/L + L -> R, M + L -> D, nil/S + L -> L # nil/S + M -> M # Flag work-in-progress each time a digest is requested (Q/U) # and clear w-i-p as soon as the digest is received (L/M). # NF==2 { if ($2 == "Q" || $2 == "U") hist_wip[$1] = 1 else if ($2 == "S") hist_stat[$1] = "S" else { # current status==L/M hist_wip[$1] = 0 pstat = hist_stat[$1] if ($2 == "L") { if (pstat == "D" || pstat == "L") hist_stat[$1] = "R" else if (pstat == "M") hist_stat[$1] = "D" else if (pstat != "R") # Previous status == nil/S? hist_stat[$1] = "L" } else if (pstat == "" || pstat == "S") # current status==M hist_stat[$1] = "M" } } # # Save the status and complete text of a digest listed in the # index, or print it, if we are recycling an old index. # Check if the digest is recorded in the history, and # use its latest status if it is. If the digest has been # requested, show the work-in-progress with a displaced dot. If # it was received from the list normally, show that with a plus sign. # NF==5 || NF==6 { if (hist_wip[$1]) stat = " ." else { stat = hist_stat[$1] if (stat == "L") stat = "+" } if (reverse) { out_stat[cnt] = stat out_text[cnt++] = $0 } else { # # If we are outputting a recycled digest listing in unreversed # order, output a blank line before the first listing, strip # off the terminal status letter (if any) and its # preceding space or spaces, then print the entry. # if (cnt == 0) { cnt = -1 print "" } i = length($0) if (NF == 5) print substr($0, 1, i-1), stat else if (substr($0, i, i) != ".") print substr($0, 1, i-2), stat else print substr($0, 1, i-3), stat } } # # If we have a new digest index, output the index in reverse order. # END { if (cnt > 0) print "" while (--cnt >= 0) print out_text[cnt], out_stat[cnt] } ' | sed 's/[^ ]* //' >> $INDEX_FILE.ls.tmp \ || $CANT "list the majordomo's digests and their status" # # Update and output the majordomo index listing. # mv -f $INDEX_FILE.ls.tmp $INDEX_FILE.ls \ || $CANT "update majordomo file listing" cat $INDEX_FILE.ls || $CANT "list majordomo files" exit 0 ;; # # Kill the current daemon by removing its i.d. file. Leave it # untouched if it shows we are unsubscribed. # +-kill_daemon) grep unsubscribed $ID_FILE 2>/dev/null >/dev/null && exit 0 rm -f $ID_FILE ; test -f $ID_FILE && $CANT "remove daemon i.d. file" exit 0 ;; # # Force old daemons to die and start up a new requester daemon. # +-START) rm -f $ID_FILE ; test -f $ID_FILE && $CANT "remove old daemon i.d. file" A_DAEMON="" # Flag that we are not a daemon. ;; # # Start up the requester daemon. # +-start) A_DAEMON="" # Flag that we are not a daemon. ;; # # Subscribe to a digest. # +-subscribe) test "$SUB_COM" || $CANT "subscribe - don't know how" echo $SUB_COM | mail $DOMO_RADDR || $CANT "subscribe" echo 1>&2 "Subscription request sent to $DOMO_RADDR" grep unsubscribed $ID_FILE 2>/dev/null >/dev/null && rm $ID_FILE exit 0 ;; # # Unsubscribe from a digest. # +-unsubscribe) test "$SUB_COM" || $CANT "unsubscribe - don't know how" echo $UNSUB_COM | mail $DOMO_RADDR || $CANT "unsubscribe" echo 1>&2 "Subscription termination request sent to $DOMO_RADDR" echo unsubscribed >$ID_FILE exit 0 ;; # # Output a usage message. # *) NAME=`echo $DEF_FILE | sed -n 's/.* \(.*\)_def$/\1/p'` test .$NAME != . || NAME=$PROG_NAME sed -n 's/[ ]*\.//p' <<-END 1>&2 .Usage: $NAME Read the new messages. . $NAME -e Examine the files online and request them. . $NAME -kill_daemon Kill the daemon. . $NAME -l List the files online. . $NAME -START Force start the daemon even if it died recently. . $NAME -subscribe Subscribe to the digest. . $NAME -unsubsribe Unsubscribe from the digest. END exit 1 ;; esac test "$REQI_COM" || $CANT "run daemon - don't know how to request digest index" test "$REQD_COM" || $CANT "run daemon - don't know how to request digest" test $REQD_INTERVAL || test "$REQD_HOURS" \ || $CANT "run daemon - do not know when to request digests" # # If we are not a daemon, decide if we should (re)start one. # if test ! "$A_DAEMON" then # # Don't restart the daemon if we have unsubscribed. # grep unsubscribed $ID_FILE 2>/dev/null >/dev/null && exit 0 # # Find the last daemon i.d. record. If it is less than a day old # and less than a few hours old, assume a daemon is already running. # TIMEOUT=$DAEMON_EXPIRATION ; test $RUN_ONCE && TIMEOUT=$REQD_INTERVAL if test 0$TIMEOUT -gt 0 \ && test "`find $ID_FILE -mtime 0 -print 2>/dev/null`" then # # Compute the record's age from the day of the month and the hour. # DAEMON_AGE=`(date ; ls -l $ID_FILE) \ | sed -n 's/.* \([0-9]*\) *\([0-2][0-9]\):.*/\1 \2/p' \ | awk 'NF == 2 && NR == 1 { day=$1; hour=$2 } NF == 2 && NR == 2 { if (day!=$1) hour+=24; print hour-$2 }'` test $DAEMON_AGE || $CANT "determine the age of the latest daemon" test $DAEMON_AGE -gt $TIMEOUT || exit 0 fi # # Determine if we are starting, restarting or cycling the daemon. # Report any old errors and clear them. # if test $RUN_ONCE then ACT="cycled" ; test -f $D_ERR_FILE -o -f $ID_FILE && ACT="" else ACT="started" ; test -f $D_ERR_FILE -o -f $ID_FILE && ACT="restarted" fi test ! -s $D_ERR_FILE \ || (cat 1>&2 $D_ERR_FILE && cp /dev/null $D_ERR_FILE) \ || $CANT "report/clear error messages" test ! -s $M_ERR_FILE \ || (cat 1>&2 $M_ERR_FILE && cp /dev/null $M_ERR_FILE) \ || $CANT "report/clear error messages" # # Start up a requester daemon and then quit. # (nice $NICE_VAL $PROG_NAME $DEF_FILE -daemon 1>&2) 2>> $D_ERR_FILE & test $ACT && echo 1>&2 "$PROG_NAME:`basename $OUT_BOX`: Daemon $ACT." exit 0 fi # # -------- The requester daemon starts here. -------- # # Add a switch to the error string to remove the i.d. file on errors. # Set a trap to catch and log signals. Announce that we are the # latest daemon by saving our pid and the current time: echo through # a cat so that we may catch file write errors. Touch the index file # so that we wait a few days before concluding the mail system has died. # DATE=`date` || $CANT "get today's date" OUR_DAEMON="$$ $DATE" CANT="$CANT -rmid" trap 'echo 1>&2 "$PROG_NAME: Received a signal."' 1 2 3 15 echo "$OUR_DAEMON" | cat > $ID_FILE || $CANT "write daemon i.d." touch $INDEX_FILE.ls || $CANT "touch index file listing" # # If we are running the daemon only once, set the last known hour, the # current hour and the request hours to immediately request the index and # any missing digests. If we are running the daemon continuously, add leading # zeros to the hours at which we should requests missing digests, if the # zeros are missing; advance the hours at which we should request the # majordomo file index by the maximum expected mail delay. # if test $RUN_ONCE then THE_HOUR=now REQD_HOURS=now REQI_HOURS=now else REQD_HOURS=`echo $REQD_HOURS | tr -s " " "\012" \ | awk '{printf "%02d ", $1}'` REQI_HOURS=`echo $REQD_HOURS | tr -s " " "\012" \ | awk '{printf "%02d ", (24-'$MAX_MAIL_DELAY'+$1)%24}'` fi # # At scheduled hours, query the majordomo for file indexes and missing digests. # while : do if test ! "$RUN_ONCE" then # # Compute the number of seconds to the start of the next hour, rounded # up so that the last three digits are the same. Sleep until then, # then get the new hour. # SLEEP_TIME=`date | sed -n 's/.*:\([0-5][0-9]\):.*/\1/p' \ | awk '{print int((60-$1)*0.6+1)}' | sed 's/.$/&&&/'` sleep $SLEEP_TIME || $CANT "sleep" THE_HOUR=`date | sed -n 's/.* \([0-2][0-9]\):.*/\1/p'` # # Check if any errors have appeared in the error log. # Exit quietly if a newer daemon has appeared. Touch our i.d. # record to show we are still alive. # test -s $D_ERR_FILE && $CANT "pinpoint error" echo "$OUR_DAEMON" | cmp -s - $ID_FILE 2>/dev/null || exit 1 touch -c $ID_FILE 2>/dev/null || exit 1 fi # # If it is time to request the file index, ask the majordomo for a # new copy. # echo $REQI_HOURS | grep $THE_HOUR > /dev/null && echo "$REQI_COM" \ | mail $DOMO_RADDR # # If it is time to request any missing digests, consult # the file index and settle which are missing. # if test -s $INDEX_FILE.ls && echo $REQD_HOURS | grep $THE_HOUR > /dev/null then # # Compare the digest history against the index and extract the # digests we have not received or requested. The 'cat' line # feeds the history file to the NF==2 clause. The 'sed' line # feeds the majordomo file index to the NF==3 clause. # WARNING: As before, do not put single-quotes in the awk code. # (Note that "print >> /pathname" will not work in the awk program.) # (test -f $HIST_FILE && cat $HIST_FILE ; \ sed -n "s/.* $DIGEST_VNPAT2.*/\2.\4 \1\2\3\4 ./p" $INDEX_FILE.ls) \ | awk ' # # Reset the number of missing digests and the first historical # missing digest (the first that falls within the current history.) # BEGIN { n = 0 first_hist = -1 } NF==2 { known[$1] = 1 # Mark a digest as known history. } NF==3 { # # If the digest is not in the history, save its index # value and its name. If the previous digest was the # first in the history, record the current digest as # the first historical missing digest. # if (!known[$1]) { md_index[++n] = $1 md_name[n] = $2 if (first_hist == 0) first_hist = n } else if (first_hist < 0) first_hist = 0 } END { # # If there are no missing digests, life is easy. If there # are none that fall within the history, make the last # missing digest the first historical missing digest. # if (!n) exit if (first_hist <= 0) first_hist = n # # Determine the first fresh missing digest, either the # first historical missing digest or the first missing # digest within the backlog limit, whichever is later. # first_fresh = n - '$MAX_BACKLOG' + 1 if (first_fresh < first_hist) first_fresh = first_hist # # Log the digests before the first fresh digest as stale. # Log the fresh digests as "requested" and repeat their names. # for (i = 1; i < first_fresh; i++) print md_index[i], "S" for (; i <= n; i++) { print md_index[i], "Q" print md_name[i] } } ' > $REQ_FILE.tmp || $CANT "extract missing digests" # # Log the missing digests and ask the majordomo to send the fresh ones. # CNT=`grep -cv " " $REQ_FILE.tmp` test $CNT || $CANT "count missing digests" if test $CNT -gt 0 then sed "/ /!d" $REQ_FILE.tmp >> $HIST_FILE \ || $CANT "log missing digests" sed -n "/ /!s/^/$REQD_COM /p" $REQ_FILE.tmp | mail $DOMO_RADDR \ || $CANT "request missing digests" fi rm $REQ_FILE.tmp || $CANT "remove request file" fi # # Check if the digest history has overflowed. If it has, discard the # oldest history. We should probably use file locking here, however, the # history is not truncated very often nor for very long. At 1 sec per # week, the chances for grief should be about 1 in 1000 over 30 years. # CNT=0 ; test -s $HIST_FILE && CNT=`grep -c . $HIST_FILE` test $CNT || $CANT "size the digest history, '$HIST_FILE'" if test $CNT -gt $HIST_HIGHLIM then tail -$HIST_LOWLIM $HIST_FILE > $HIST_FILE.tmp \ || $CANT "discard the oldest digest history" mv -f $HIST_FILE.tmp $HIST_FILE || $CANT "rename the digest history" fi # # See if mail processing has died by checking if the index file has # changed. Exit if we are running the daemon only once, # test "`find $INDEX_FILE.ls -mtime -$MAIL_EXPIRATION -print 2>/dev/null`" \ || $CANT "get a new majordomo index after $MAIL_EXPIRATION days" test $RUN_ONCE && exit 0 done SHAR_EOF chmod +x 'undig' fi echo shar: "extracting 'undig_pm'" '(11058 characters)' if test -f 'undig_pm' then echo shar: "will not over-write existing file 'undig_pm'" else cat << \SHAR_EOF > 'undig_pm' : # @(#) Undigestifier mail processor v3.1 01 May 1996 # John Firestone, jfiresto@awi-bremerhaven.de # # Save message and explode digests coming from a mailing list # and its majordomo. # Usage: undig_pm [definition file] < mail_message >> output_mailbox # # # Get the program's name. Get and execute the definition files. # PROG_NAME=`basename $0` DEF_FILE="" if test "+$1" = "+-d" then test "+$2" = "+" && echo 1>&2 "Usage: $PROG_NAME [-d def_file]" && exit 1 DEF_FILE="$1 $2" . $2 . undig_def . $2 shift ; shift else . undig_def fi # # Define the command string to report an error. To report an error # within the program, use the code: $CANT "do something" This will be # printed as: "program: Can not do something." # If given the error option and an error message, print the message and quit. # CANT="exec $PROG_NAME $DEF_FILE -err" if test "+$1" = "+-err" then BOX_NAME=`basename $OUT_BOX` DATE=`date 2>/dev/null` echo 1>&2 "$PROG_NAME:$BOX_NAME: Can not $2. $DATE" exit 1 fi # # Create the work directory if it does not already exist. # if test ! -d $WORK_DIR then mkdir $WORK_DIR || $CANT "create the work directory" echo 1>&2 "$PROG_NAME: Created work directory '$WORK_DIR'." fi # # Redirect errors to the error file. Save the message and check if it # comes from the majordomo as either a file or as results. # exec 2>> $M_ERR_FILE cat > $MSG_FILE || $CANT "save mail message" DOMO_MSG=`sed -n "s/^Subject:.*Majordomo results.*/results/p s/^Subject:.*Majordomo file.*/file/p /^Subject:/q" $MSG_FILE` test $? -eq 0 || $CANT "determine mail message's source" # # Determine the message's type. If it results from the majordomo, check # if it is an index of files online or a simple acknowledgement. If it # none of the above, try to get a digest volume and number from one of the # "Subject:" lines. If we succeed, consider the message a digest. # MSG_TYPE="" if test "$DOMO_MSG" = results then MSG_TYPE=`sed -n "s/^>>>> *$REQI_COM.*/index/p s/^is being sent as a separate message..*/ack/p" $MSG_FILE\ | sed 1q` test $? -eq 0 || $CANT "determine mail message's type" else REF=`sed -n "s/$DIGEST_SUBJECT/v\1\2.n\3\4 \2 \4/p" $MSG_FILE | sed 1q` test $? -eq 0 || $CANT "determine mail message's type" set . $REF ; DIGEST_REF=$2 ; DIGEST_VOL=$3 ; DIGEST_NUM=$4 test "$DIGEST_VOL" -a "$DIGEST_NUM" && MSG_TYPE=digest fi # # Process the message, clean up and quit. # case $MSG_TYPE in # # Let a simple acknowledgement disappear. # ack) ;; # # Explode a digest and output its individual mail messages. # digest) # # Check if the digest has already been received and is not being # rerequested. If it has and is not, discard the digest. # DISCARD="" if test "$LOG_DIGESTS" != "" -a -f $HIST_FILE then DISCARD=`sed -n "/$DIGEST_VOL\.$DIGEST_NUM /p" $HIST_FILE \ | sed -n '$s/.*[LM].*/T/p'` test $? -eq 0 || $CANT "determine digest's status" fi # # If we are not discarding the digest, create a mail message header with # the digest's volume and number. Get the current date and call # that the receive-date. (The two are pretty darn close.) # if test ! "$DISCARD" then MSG_HDR="From digest.$DIGEST_REF" RCV_DATE=`date | sed 's/[A-Z][A-Z]* //g'` test "$RCV_DATE" || $CANT "get the current date" fi # # Disable the mailing list's kill lists if they have not been given. # test "$FROM_KILL_LIST" || FROM_KILL_LIST="^" test "$SUBJECT_KILL_LIST" || SUBJECT_KILL_LIST="^" # # If we are not discarding the digest, explode it and output its articles. # WARNING: Do not put ANY single-quote marks in the awk program comments. # DFILE=$MSG_FILE ; test $DISCARD && DFILE=/dev/null fold -$LONGEST_DLINE $DFILE | awk ' # # Kill but do not log the introductory message. # Prepare to get the message header. # BEGIN { kill_msg = 1 nlog = -1 nline = -1 } # # If we reach the end of a message, try to print it. # /^------------------------------/ { # # Kill the message if: # 1. it does not have at least one body line and a body # that is different than that of the previous message, # 2. it is on the first-line kill list and it has one body # line or the first body line is less than four words long, # 3. all its lines have fewer than four fields and the # first line does not end with a punctuation mark. # if (!kill_msg) { if (nline < 1 || !diffbody) kill_msg = 1 else if (kill_line1) { if (nline == 1 || nf_line1 < 4) kill_msg = 1 } else if (nfsize < 4) { i = length(lf_line1) if (!index("?!.", substr(lf_line1, i, i))) kill_msg = 1 } } # # Ignore the message if it is incomplete. If requested to, log # the message if it is not the introductory message and we should # kill it. Output the message if we should not kill it. # if (nline <= 0) nline = -1 else if (kill_msg) { if ("'"$LOG_KILLS"'" != "") { if (nlog < 0) nlog = 0 else { # # Log the sender, date, subject and first four lines. # klog[++nlog] = from klog[++nlog] = send_date if (diffbody) klog[++nlog] = subject else klog[++nlog] = subject " [repeat]" for (i = 1; i <= 4; i++) { if (i <= nline) klog[++nlog] = line[i] else klog[++nlog] = " " # Flag missing line. } } } } else { # # Set the message from-line-date to either the receive-date # or the send-date. Output the message header, including # the receive-date if it differs from the from-line-date. # from_date = rcv_date = "'"$RCV_DATE"'" if ("'"$DUP_SEND_DATE"'" != "") from_date = send_date printf "'"$MSG_HDR"' %s\nFrom: %s\n", from_date, from printf "Date: %s\nSubject: '"$SUBJECT_PREFIX"'%s\n", \ send_date, subject if (rcv_date != from_date) printf "Receive-date: %s\n", rcv_date print "" # # Print the message body. # qc = " " qcnt = '$MAX_QLINE' for (i = 1; i <= nline; i++) { # # Prefix bastard "^From " lines. # cline = line[i] if (substr(cline, 1, 5) == "From ") cline = ">" cline # # Watch for and truncate long quoted passages. # c = lineqc[i] if (c == qc) { qcnt-- if (qcnt >= 0) print cline continue } if (qcnt < 0) printf " ------ Deleted %d quoted line(s) ------\n\n",\ -qcnt print cline qc = c qcnt = '$MAX_QLINE' } if (qcnt < 0) printf " ------ Deleted %d quoted line(s) ------\n", -qcnt print "" } # # Start a new message by clearing the sender, date and # subject fields, the kill-message flags, and the number # of body lines in the current message. # from = send_date = subject = "" kill_msg = kill_line1 = 0 nline = -1 next } # # If we are killing the current message, get its first four lines # and then skip to its end. # kill_msg == 1 && nline >= 4 { next } # # If we are about to save the first body line, check if it is # on the first-line kill list. If we have a complete message # header, collect its body lines. # nline == 0 && NF > 0 && /'"$LINE1_KILL_LIST0"'/ { kill_line1 = 1 } nline >= 0 { # # Start collecting at the first non-blank line. At the first # line: clear the body-is-different flag, initialize the line # index and the size of the number of fields per line, and save # the last field of the first line and its number of fields. # if (nline || NF) { if (!nline) { diffbody = iline = nfsize = 0 lf_line1 = $NF nf_line1 = NF } # # If the line is not blank, advance the line count, check # if the body now differs from the body of the previous # message, and update the size of the number of fields per # line, as measured in the n-infinity norm, i.e. find the # line with the greatest number of fields. Make the # first non-blank character the new quoting character. # iline++ if (NF) { nline = iline if (!diffbody && line[iline] != $0) diffbody = 1 if (NF > nfsize) nfsize = NF qc = substr($1,1,1) } line[iline] = $0 # Save the line and its first character lineqc[iline] = qc # which may flag a quoted line. } next # Treat header fields as message body. } # # If we reach the first "From:" or "Subject:" line, check if either is # on the kill lists. If we reach a "Date:", "From:" or "Subject:" # line, save the the message send-date, sender or subject. Start # collecting body lines as soon as we have a complete message header. # from == "" && /^From: .*'"$FROM_KILL_LIST0"'/ { kill_msg = 1 } from == "" && /^From: .*'"$FROM_KILL_LIST"'/ { kill_msg = 1 } subject == "" && /^Subject: .*'"$SUBJECT_KILL_LIST0"'/{ kill_msg = 1 } subject == "" && /^Subject: .*'"$SUBJECT_KILL_LIST1"'/{ kill_msg = 1 } subject == "" && /^Subject: .*'"$SUBJECT_KILL_LIST"'/ { kill_msg = 1 } send_date == "" && /^Date: / { send_date = substr($0,7) } from == "" && /^From: / { from = substr($0,7) } subject == "" && /^Subject: / { subject = substr($0,10) } from != "" && send_date != "" && subject != "" { nline = 0 } # # If we logged any killed messages, list them in a mail message. # END { if (nlog > 0) { rcv_date = "'"$RCV_DATE"'" printf "'"$MSG_HDR"' %s\nFrom: undigestifier\n", rcv_date printf "Date: %s\nSubject: '"$SUBJECT_PREFIX"'%s", \ rcv_date, "-- Killed Messages --" for (i = 1; i < nlog; ) { printf "\n\nFrom: %s\nDate: %s\nSubject: %s\n\n", \ klog[i], klog[i+1], klog[i+2] i += 3 for (j = 0; j < 4; j++) { cline = klog[i++] if (cline != " ") # Ignore missing lines. print " ", cline } } print "" } } ' || $CANT "explode digest" # # Log the digest, indicating its source. Echo through cat in order # to catch file write errors. Update the file index listing by # requesting a copy and then discarding it. # if test "$LOG_DIGESTS" != "" -a "$REQI_COM" != "" then DIGEST_SRC=L ; test "$DOMO_MSG" && DIGEST_SRC=M echo "$DIGEST_VOL.$DIGEST_NUM $DIGEST_SRC" | cat >> $HIST_FILE \ || $CANT "log digest" undig $DEF_FILE -l 2>/dev/null > /dev/null fi ;; # # Clean and save an index of the files on the majordomo. # index) sed -n "1s/.*/$REQI_COM `date 2>/dev/null`/p s/^-.* \($MONTH_PAT [ 1-3][0-9] .*\)/\1/p" $MSG_FILE \ >> $INDEX_FILE.tmp || $CANT "save majordomo file index" mv -f $INDEX_FILE.tmp $INDEX_FILE || $CANT "update majordomo file index" undig $DEF_FILE -l 2>/dev/null > /dev/null ;; # # Output all other types of messages, as is. # *) cat $MSG_FILE || $CANT "add message to the output mail box" ;; esac rm $MSG_FILE || $CANT "remove mail message" exit 0 SHAR_EOF chmod +x 'undig_pm' fi echo shar: "extracting 'bmw_def'" '(1232 characters)' if test -f 'bmw_def' then echo shar: "will not over-write existing file 'bmw_def'" else cat << \SHAR_EOF > 'bmw_def' : # @(#) BMW-list undigestifier definitions v3.1a 01 Aug 1996 # John Firestone, jfiresto@awi-bremerhaven.de # # Where to find messages and exploded digests OUT_BOX=$HOME/Mail/bmw-mbox # Add this prefix to the digest contribution subject lines, e.g.: "[bmw] " SUBJECT_PREFIX= # The majordomo's return (request) address, followed by majordomo commands # to request a digest and the majordomo file index and to subscribe # and unsubscribe. DOMO_RADDR=majordomo@mailgate.wizvax.net REQD_COM="get bmw-digest" REQI_COM="index bmw-digest" SUB_COM="subscribe bmw-digest" UNSUB_COM="unsubscribe bmw-digest" # Two sed patterns to match the digest volume and issue numbers. Both # assign n-item fields to the volume number header including leading zeros, # the volume, the number header including leading zeros, and the number. DIGEST_VNPAT1='V\(0*\)\([1-9][0-9]*\) #\(0*\)\([1-9][0-9]*\)' DIGEST_VNPAT2='\(v0*\)\([1-9][0-9]*\)\(.n0*\)\([1-9][0-9]*\)' # The subject line introducing a digest. It should assign n-item fields to # the volume and number using one of the volume/number patterns. DIGEST_SUBJECT="^Subject: *bmw-digest $DIGEST_VNPAT1" # # User defined kill lists. # FROM_KILL_LIST= SUBJECT_KILL_LIST= SHAR_EOF chmod +x 'bmw_def' fi echo shar: "extracting 'itacar_def'" '(1288 characters)' if test -f 'itacar_def' then echo shar: "will not over-write existing file 'itacar_def'" else cat << \SHAR_EOF > 'itacar_def' : # @(#) Italian car list undigestifier definitions v3.1a 01 Aug 1996 # John Firestone, jfiresto@awi-bremerhaven.de # # Where to find messages and exploded digests OUT_BOX=$HOME/Mail/itacar-mbox # Add this prefix to the digest contribution subject lines, e.g.: "[ita] " SUBJECT_PREFIX= # The majordomo's return (request) address, followed by majordomo commands # to request a digest and the majordomo file index and to subscribe # and unsubscribe. DOMO_RADDR=majordomo@mailgate.wizvax.net REQD_COM="get italian-cars-digest" REQI_COM="index italian-cars-digest" SUB_COM="subscribe italian-cars-digest" UNSUB_COM="unsubscribe italian-cars-digest" # Two sed patterns to match the digest volume and issue numbers. Both # assign n-item fields to the volume number header including leading zeros, # the volume, the number header including leading zeros, and the number. DIGEST_VNPAT1='V\(0*\)\([1-9][0-9]*\) #\(0*\)\([1-9][0-9]*\)' DIGEST_VNPAT2='\(v0*\)\([1-9][0-9]*\)\(.n0*\)\([1-9][0-9]*\)' # The subject line introducing a digest. It should assign n-item fields to # the volume and number using one of the volume/number patterns. DIGEST_SUBJECT="^Subject: *italian-cars-digest $DIGEST_VNPAT1" # # User defined kill lists. # FROM_KILL_LIST= SUBJECT_KILL_LIST= SHAR_EOF chmod +x 'itacar_def' fi echo shar: "extracting 'na_def'" '(1343 characters)' if test -f 'na_def' then echo shar: "will not over-write existing file 'na_def'" else cat << \SHAR_EOF > 'na_def' : # @(#) Numerical Analysis List undigestifier definitions v3.1 01 May 1996 # John Firestone, jfiresto@awi-bremerhaven.de # # NOTE: this list does not archive old digests in a way that makes them # easy to catalog and read. Don't bother running a requester # daemon for this list. # # Where to find messages and exploded digests OUT_BOX=$HOME/Mail/na-mbox # Add this prefix to the digest contribution subject lines, e.g.: "[na] " SUBJECT_PREFIX= # The majordomo's return (request) address, followed by majordomo commands # to request a digest and the majordomo file index and to subscribe # and unsubscribe. DOMO_RADDR=na.help@na-net.ornl.gov REQD_COM= REQI_COM= SUB_COM=help UNSUB_COM=help # Two sed patterns to match the digest volume and issue numbers. Both # assign n-item fields to the volume number header including leading zeros, # the volume, the number header including leading zeros, and the number. DIGEST_VNPAT1='V\. *\(0*\)\([1-9][0-9]*\), # *\(0*\)\([1-9][0-9]*\)' DIGEST_VNPAT2='\(v0*\)\([1-9][0-9]*\)\(.n0*\)\([1-9][0-9]*\)' # The subject line introducing a digest. It should assign n-item fields to # the volume and number using one of the volume/number patterns. DIGEST_SUBJECT="^Subject: NA Digest, $DIGEST_VNPAT1" # # User defined kill lists. # FROM_KILL_LIST= SUBJECT_KILL_LIST= SHAR_EOF chmod +x 'na_def' fi echo shar: "extracting 'skunk_def'" '(1401 characters)' if test -f 'skunk_def' then echo shar: "will not over-write existing file 'skunk_def'" else cat << \SHAR_EOF > 'skunk_def' : # @(#) Skunk works list undigestifier definitions v3.1 01 May 1996 # John Firestone, jfiresto@awi-bremerhaven.de # # NOTE: this list does not archive old digests in a way that makes them # easy to catalog and read. Don't bother running a requester # daemon for this list. # # Where to find messages and exploded digests OUT_BOX=$HOME/Mail/skunk-mbox # Add this prefix to the digest contribution subject lines, e.g.: "[bmw] " SUBJECT_PREFIX= # The majordomo's return (request) address, followed by majordomo commands # to request a digest and the majordomo file index and to subscribe # and unsubscribe. DOMO_RADDR=majordomo@gaia.ucs.orst.edu REQD_COM= REQI_COM= SUB_COM="subscribe skunk-works-digest" UNSUB_COM="unsubscribe skunk-works-digest" # Two sed patterns to match the digest volume and issue numbers. Both # assign n-item fields to the volume number header including leading zeros, # the volume, the number header including leading zeros, and the number. DIGEST_VNPAT1='V\(0*\)\([1-9][0-9]*\) #\(0*\)\([1-9][0-9]*\)' DIGEST_VNPAT2='\(v0*\)\([1-9][0-9]*\)\(.n0*\)\([1-9][0-9]*\)' # The subject line introducing a digest. It should assign n-item fields to # the volume and number using one of the volume/number patterns. DIGEST_SUBJECT="^Subject: *Skunk Works Digest $DIGEST_VNPAT1" # # User defined kill lists. # FROM_KILL_LIST= SUBJECT_KILL_LIST= SHAR_EOF chmod +x 'skunk_def' fi echo shar: "extracting 'undig_def'" '(4097 characters)' if test -f 'undig_def' then echo shar: "will not over-write existing file 'undig_def'" else cat << \SHAR_EOF > 'undig_def' : # @(#) General undigestifier definitions v3.1 01 May 1996 # John Firestone, jfiresto@awi-bremerhaven.de # DEFAULT_LIST=bmw_def test $OUT_BOX || . $DEFAULT_LIST # The editor for viewing and requesting majordomo files EDITOR=$EDITOR # The command line to actually read the messages and undigestfied digests READ_DIGEST_COMMAND="Mail -f $OUT_BOX" # Duplicate a contribution's raw send date. Set this variable if # you wish to make that date rather than its explosion date, its # mail message receive date. Some mailer readers, e.g. 'elm', will # choke on raw send dates. DUP_SEND_DATE= # How often to run the daemon and request missing digests (in hours<24). Set # this variable to the null string if the daemon should run continuously. REQD_INTERVAL=23 # The hours at which the daemon should request missing digests, if # the daemon is running continuously. The interval between requests # should be greater than the maximum expected mail delay. REQD_HOURS="07" # Log digests. Set this variable to the null string to disable # digest logging. LOG_DIGESTS=T # Log killed messages. Set this variable to to the null string to disable # kill logging. Set it a single letter to get a summary of killed messages. LOG_KILLS= # The maximum expected delay in getting mail from the digest # server to this host machine (in hours<24) MAX_MAIL_DELAY=3 # The maximum digest backlog MAX_BACKLOG=20 # The number of days to wait before assuming mail processing has died MAIL_EXPIRATION=5 # The number of hours to wait (<24) before assuming a daemon has died DAEMON_EXPIRATION=3 # The nice value to give the daemon or background jobs NICE_VAL= # This program keeps a history of the files it has requested and received. # These two values set its approximate low and high line-count limits. HIST_LOWLIM=4000 HIST_HIGHLIM=4400 # The following three kill lists should be awk/egrep patterns. # First, the digest contributors to ignore... FROM_KILL_LIST0='(Administrator_at|DAEMON|[Dd]aemon|majordomo\ |Post_Office|POSTMAST|[Pp]ostmast|SMTP@|smtp@|uucp@)' # Second, the digest subjects to ignore... SUBJECT_KILL_LIST0='(digest.*[0-9] -Reply$|Auto-*[Rr]eply|SUBSCRIBE[ .!]\ |SUBSCRIBE$|[Ss]ubscribe[ .!]|[Ss]ubscribe$|[Dd]elivery [Ff]ail\ |Returned [Mm]ail|Undeliverable [Mm]ail|Undeliverable [Mm]ess\ |Message Delivery Report)' SUBJECT_KILL_LIST1='(Server down|Automatic [Rr]eply)' # Third, the line one phrases to ignore... LINE1_KILL_LIST0='(^ *get|^ *help|SUBSCRIBE[. ]|SUBSCRIBE$|[Ss]ubscribe[ .!]\ |[Ss]ubscribe$|^ *which|^ *who)' # A sed pattern that matches the month MONTH_PAT="[A-Z][a-z][a-z]" # # The longest allowed digest line. Longer lines will be folded. # LONGEST_DLINE=320 # # The longest allowed quoted passage (in lines) before truncation begins. # MAX_QLINE=40 # # File definitions. # # Majordomo index file: # e.g.: Nov 23 15:05 FAQ.0 # Jan 17 10:10 v01.n001 # Jan 17 22:10 v01.n002 # Jan 18 10:10 v01.n003 # Digest history file: . # e.g.: 1.1 S # 1.2 L # 1.3 U # The status letters are: D=delayed*, L=received from the mailing # list, M=received from the majordomo/originally missing, # Q=requested by the daemon, R=repeated*, S=stale, U=requested by # the user. The starred (*) status letters only appear when the # history is listed. They are not recorded in the history. # WORK_DIR=$OUT_BOX.d # The working directory D_ERR_FILE=$WORK_DIR/errors.daemon # The daemon error log EDIT_DIR=$WORK_DIR/edit # The edit directory EDIT_FILE=$EDIT_DIR/status+request # The status/request edit file HIST_FILE=$WORK_DIR/history # The received/requested digest history ID_FILE=$WORK_DIR/id # The file holding our daemon i.d. INDEX_FILE=$WORK_DIR/index # Index of the majordomo files M_ERR_FILE=$WORK_DIR/errors.mail # The process-mail error log MSG_FILE=$WORK_DIR/message # The current mail message REQ_FILE=$WORK_DIR/request # The missing digests request file SHAR_EOF chmod +x 'undig_def' fi exit 0 # End of shell archive