jerry@ora.com (Jerry Peek) (02/02/91)
Submitted-by: jerry@ora.com (Jerry Peek) Posting-number: Volume 16, Issue 89 Archive-name: mh-scripts/part01 These files are Bourne shell scripts that use MH electronic mail commands. The scripts come from the Nutshell Handbook called "MH & xmh: Email for Users and Programmers" published by O'Reilly & Associates, Inc. Whether you have the book or not, these scripts should be useful if you use MH. (If you don't use MH, look at the kinds of things you could do.) --Jerry Peek, jerry@ora.com # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # # NOTE: Tabstops in these files are set at 4-column intervals. # # Wrapped by ora!jerry on Sat Jan 12 18:30:42 EST 1991 # Contents: README append babyl2mh distprompter fixsubj fols incs mhprofile # recomp replf resend.fixmsg rmmer scandrafts showpr vmsmail2mh xmhprint echo extracting - README sed 's/^X//' > "README" <<'X//E*O*F README//' XINTRODUCTION: These files are Bourne shell scripts that use MH electronic Xmail commands. The scripts come from the Nutshell Handbook called "MH & xmh: XEmail for Users and Programmers" published by O'Reilly & Associates, Inc. XThe book will be available this month (January, 1991). X XWhether you have the book or not, these scripts should be useful if you Xuse MH. (If you don't use MH, look at the kinds of things you could do. XBecause MH isn't a "one-mail-program-does-all" system and its programs are Xall run by the UNIX shell, shell programming with MH is easy.) XEach file has a comment block that explains the program; individual Xparts of the scripts are commented, too. Although the book has complete Xexplanations, people who have some experience with shell programming and XMH should be able to use these without the book. X X XDO THEY WORK?: I developed these scripts under BSD UNIX and SunOS; I've Xused most of them myself for months or years. The book's reviewers tested Xthem on other flavors of UNIX. Still, there could be some portability or Xother problems. If you don't have MH 6.7 installed, you could run into a Xfew problems there. There are also some compatibility problems, like X"echo -n" vs. "echo \c", that I haven't tried to code around; remember Xthat these are intended more as examples than as portable bulletproof code. X XIf you find problems, though, please send me mail. Of course, some Xsystem-dependent stuff like variables that hold the pathnames of files and Xprograms will have to be edited to work on your computer. Also, some Xobscure problems and system dependencies are explained in the book. XBut I'd be GLAD to get your mail (and answer it as soon as I can). X XBecause these scripts come directly from the book, I'm not sure what to Xdo about patches and patchlevel.h files for the comp.sources.misc Xarchives. The book versions won't be patched; they'll just be updated. XThe latest versions should always be available on the uunet.uu.net Xcomputer for anonymous ftp and uucp; get the tar file named MHxmh.tar.Z Xfrom the nutshell/MHxmh directory. X X XDESCRIPTIONS: Here are one-line descriptions of the script files. XEven if you don't need the capabilities that a particular program gives, Xyou might want to look at the scripts anyway for examples of MH programming. X Xappend Append file(s) to an MH mail message at "What now?" prompt Xdistprompter Replaces "prompter" editor for MH "dist" command Xfixsubj Fix (add or change) "Subject:" on a mail message Xfols Show list of folders in columns, current folder marked Xmhprofile Grab matching line(s) from MH profile file Xrecomp Re-compose a draft mesage in MH draft folder Xreplf Refile current message into folder, reply to it Xresend.fixmsg Editor for fixing up returned mail (use with "resend") Xrmmer Move mail to DELETE (sub-)folder for "find" to delete later Xscandrafts Scan MH draft folder; return to original folder or stay Xshowpr Show MH message(s) with pr(1), custom heading Xxmhprint Print command for xmh X X XAUTHORSHIP, COPYING, ETC.: These programs are in the public domain. XOf course, you use them at your own risk. I wrote most of them myself. XI adapted two of them, "append" and "replf", from scripts that come Xwith the MH distribution; Marshall Rose, John Romine and Bob Desinger Xwere authors of those scripts, I believe. If you make changes or fix Xbugs, I'd really appreciate getting a mail message about that and/or Xa copy of your fixed script. If I use the changes, I'll give you Xcredit... and people who use the scripts will appreciate your help! X X--Jerry Peek, jerry@ora.com, +1 617 354-5800 X//E*O*F README// chmod u=rw,g=r,o=r README echo extracting - append sed 's/^X//' > "append" <<'X//E*O*F append//' X#! /bin/sh X# $Header: /u3/acs/jdpeek/.bin/RCS/append,v 1.10 90/10/13 09:48:04 jdpeek book $ X### append - append file(s) to an MH mail message X### Usage: What now? e append file [files...] X## X## THIS SCRIPT LETS YOU APPEND ONE OR MORE FILES TO A DRAFT MH MAIL X## MESSAGE; IT ALSO ALLOWS WILDCARDS AND ENVARIABLES. X## YOU CALL IT AS AN EDITOR, AT THE What now? PROMPT. X## FOR EXAMPLE, TO APPEND A COPY OF YOUR FILE report TO YOUR DRAFT: X## What now? e append report X## X## AFTER IT APPENDS THE FILE(S), YOU GET ANOTHER What now? PROMPT. X## IF YOU WANT TO SEPARATE THE FILES WITH BLANK LINES, ROWS OF DASHES, X## OR WHATEVER, AN EASY WAY IS TO MAKE A LITTLE FILE NAMED SOMETHING X## LIKE SEP WITH THAT SEPARATOR IN IT. THIS NEXT EXAMPLE SHOWS HOW TO X## APPEND ALL THE FILES FROM THE $HOME/proj DIRECTORY WHOSE NAMES END X## WITH .out, THEN YOUR SEPARATOR FILE, THEN THE FILE .signature: X## What now? e append $HOME/proj/*.out sep .signature X# X# Original, apparently by John Romine, from the paper X# "MH.5: How to process 200 messages a day and still get some X# real work done," in the Summer 1985 USENIX Proceedings. X# Hacked more by Jerry Peek, with hints from John Romine. X Xcase $# in X0) echo 1>&2 "`basename $0`: shouldn't get here!"; exit 1;; X1) echo 1>&2 "Usage: e[dit] `basename $0` file [files...]"; exit 1 ;; X*) while : X do X case $# in X 1) msg=$1; break ;; X *) files="$files $1"; shift ;; X esac X done X ;; Xesac X X# eval EXPANDS ENVIRONMENT VARIABLES IN $files; BUT PROTECT >> FROM eval: Xeval cat $files '>>' $msg X//E*O*F append// chmod u=rwx,g=rx,o=rx append echo extracting - babyl2mh sed 's/^X//' > "babyl2mh" <<'X//E*O*F babyl2mh//' X#! /bin/sh X# $Header: /u3/acs/jdpeek/.bin/RCS.Z/babyl2mh,v 1.1 90/03/22 03:57:05 jdpeek Exp $ X### babyl2mh - slow way to convert Emacs Rmail files to MH X### Usage: babyl2mh +mh-folder [RMAIL-FILE] X X# NOTE: PROGRAM HASN'T BEEN TESTED THOROUGHLY. X# CHECK THE MESSAGES! X# Placed in the public domain. Use at your own risk. X# --Jerry Peek, 22 March 1990 X Xdfltprot=600 # DEFAULT MESSAGE PROTECTION (IF NONE IN MH PROFILE) Xfolopts="-fast -nolist -nototal -nopack -norecurse" Xmh=/usr/local/mh Xmhprofile=/u3/acs/jdpeek/.bin/mhprofile # READS MH PROFILE Xscanopts="-noclear -noheader -noreverse" X Xcase "$1" in X[@+]?*) X # IF $1 DOESN'T EXIST, folder WILL CREATE IT (SIGH). X # THAT'S BECAUSE stdout IS REDIRECTED AWAY FROM TERMINAL. X if $mh/folder $folopts "$1" >/dev/null X then X # GET PATHNAME OF FOLDER, LAST MESSAGE NUMBER: X folpath="`$mh/mhpath`" || exit X firstmsg="`$mh/scan -format '%(msg)' last`" || exit X else X echo "`basename $0`: no folder. quitting." 1>&2 X exit 1 X fi X ;; X*) echo "Usage: `basename $0` +folder|@folder [file] X ('$1' doesn't start with + or @.)" 1>&2 X exit 1 X ;; Xesac X Xif [ -n "$2" -a \( ! -r "$2" \) ] Xthen X echo "`basename $0`: quitting: can't read Rmail file '$2'." 1>&2 X exit 1 Xfi X X# GET PROTECTION MODE FROM MH PROFILE (IF NONE, USE $dfltprot): Xmsgprot="`$mhprofile -b msg-protect`" || msgprot=$dfltprot X X# MAKE SHELL ARCHIVE FILE ON awk'S STANDARD OUTPUT. X# PIPE IT INTO sh TO CREATE THE MESSAGE FILES... Xawk "BEGIN { X folpath=\"$folpath\" # STORE AS STRING, WITH QUOTES X msgprot=$msgprot # STORE AS NUMBER (NO QUOTES) X msgnum=$firstmsg"' # CHANGE FROM DOUBLE- TO SINGLE-QUOTES X gotflags=0 X gotgoodhdr=0 X gotbadhdr=0 X} X# SKIP BABYL HEADER: XNR==1, /\037\014/ { X next X} X# PROCESS MESSAGES. USE gotflags, ETC. TO "REMEMBER" X# WHEN WE HAVE PASSED EACH PART OF EACH MESSAGE. X{ X # MESSAGE ENDS WITH CTRL-UNDERSCORE AT START OF A LINE. X # PRINT SHELL COMMANDS AND RESET FLAGS: X if ($0 ~ /^\037/) { X printf "END-OF-%s/%d\n\n", folpath, msgnum X # SET PROTECTION (INEFFICIENT; SHOULD DO ALL MSGS. AT ONCE) X printf "chmod %d %s/%d\n", msgprot, folpath, msgnum X gotflags = 0 X gotgoodhdr = 0 X gotbadhdr = 0 X next X } X # INSTEAD OF FLAGS LINE (LIKE "1,,"), PRINT START OF ARCHIVE: X if (gotflags == 0) { X gotflags = 1 X msgnum += 1 X printf "/bin/cat > %s/%d << \\END-OF-%s/%d\n", \ X folpath, msgnum, folpath, msgnum X next X } X # PRINT THE FULL HEADER (UP TO FIRST BLANK LINE): X if (gotgoodhdr == 0) { X if ($0 !~ /^$/) { X print X next X } X else { X gotgoodhdr = 1 X next X } X } X # SKIP THE SHORT HEADER (UP TO NEXT BLANK LINE): X if (gotbadhdr == 0 && $0 !~ /^$/) X next X gotbadhdr = 1 X # PRINT THE MESSAGE (UP TO ^_): X print X next X}' $2 | X/bin/sh -e # EXIT ON ANY ERROR X Xexit # RETURN STATUS FROM PIPE ABOVE X//E*O*F babyl2mh// chmod u=rwx,g=rx,o=rx babyl2mh echo extracting - distprompter sed 's/^X//' > "distprompter" <<'X//E*O*F distprompter//' X#! /bin/sh X# $Header: /u3/acs/jdpeek/.bin/RCS/distprompter,v 1.4 90/10/12 09:03:48 jdpeek book $ X### distprompter - replaces "prompter" for MH "dist" command X### Usage (in .mh_profile): dist: -editor distprompter X## X## BY DEFAULT, THE MH dist COMMAND USES prompter TO EDIT THE DRAFT X## MESSAGE. FOR dist, THAT'S NOT A GREAT CHOICE BECAUSE: X## - IF YOU ACCIDENTALLY TYPE A BODY, THE MESSAGE CAN'T BE SENT X## - YOU ALWAYS HAVE TO PRESS CONTROL-D TO SKIP THE BODY X## X## distprompter IS AN EDITOR DESIGNED FOR dist. IT READS THE X## EMPTY HEADER THAT dist GIVES IT, LINE BY LINE. IF A COMPONENT X## IS EMPTY, IT PROMPTS YOU. IF A COMPONENT IS FINISHED, IT DOESN'T X## PROMPT. IF A COMPONENT IS ILLEGAL (NOT Resent-xxx:), IT COMPLAINS. X## WHEN IT'S READ THE HEADER, IT EXITS; YOU DON'T NEED CONTROL-D. X Xmyname="`basename $0`" Xerr=/tmp/DISTPRe$$ header=/tmp/DISTPRd$$ X> $header Xchmod 600 $header X Xstat=1 # DEFAULT EXIT STATUS; RESET TO 0 FOR NORMAL EXITS Xtrap 'rm -f $header $err; exit $stat' 0 Xtrap 'echo "$myname: Interrupt! Cleaning up..." 1>&2; exit' 1 2 15 X Xif [ ! -w "$1" -o -z "$1" ] Xthen X echo 1>&2 "$myname: quitting: missing or unwritable draft X '$1'" X exit Xfi X X# READ DRAFT (A COPY OF distcomps FILE) LINE-BY-LINE. X# ACT LIKE prompter, BUT EXIT AFTER WE'VE READ DRAFT FILE X# (WHEN YOU USE dist, THE DRAFT FILE IS ONLY A HEADER). Xwhile read label line Xdo X case "$label" in X [Rr]esent-?*:) X case "$line" in X ?*) # SHOW LINE ON SCREEN AND PUT INTO HEADER FILE: X echo "$label $line" X echo "$label $line" 1>&3 X ;; X *) # FILL IT IN OURSELVES: X echo -n "$label " X # stdin IS FROM DRAFT, SO READ DIRECTLY FROM tty: X ans="`/usr/ucb/head -1 </dev/tty`" X case "$ans" in X "") ;; # EMPTY; DO NOTHING X *) echo "$label $ans" 1>&3 ;; X esac X ;; X esac X ;; X ""|---*) # END OF HEADER X echo "-------" 1>&3 X break # PROBABLY NOT NEEDED... X ;; X *) echo "$myname: illegal header component X '$label $line'" 1>&2 X break X ;; X esac Xdone <$1 2>$err 3>$header X X# IF THE ERROR FILE HAD SOMETHING IN IT, SHOW IT AND QUIT: Xif [ -s $err ] Xthen X /bin/cat $err 1>&2 X echo "$myname: quitting." 1>&2 Xelse X if /bin/cp $header $1 X then stat=0 X else echo "$myname: can't replace draft '$1'?" X fi Xfi Xexit X//E*O*F distprompter// chmod u=rwx,g=rx,o=rx distprompter echo extracting - fixsubj sed 's/^X//' > "fixsubj" <<'X//E*O*F fixsubj//' X#! /bin/sh X# $Header: /u3/acs/jdpeek/.bin/RCS/fixsubj,v 1.9 90/10/13 10:01:45 jdpeek book $ X# X### fixsubj - fix (add or change) "Subject:" on a mail message X### Usage: fixsubj [+folder] [msgnum [msgnums]] -s 'new subj' X## X## SOME PEOPLE DON'T BOTHER TO PUT A Subject: LINE ON THEIR MAIL X## MESSAGES. THAT MAKES IT HARD, LATER, WHEN YOU scan YOUR MAIL. X## fixsubj LETS YOU ADD YOUR OWN Subject: LINE TO MESSAGE(S). X## YOU CAN USE THE SAME SUBJECT ON MANY MESSAGES BY GIVING ALL NUMBERS. X## X## IF A MESSAGE ALREADY HAS A SUBJECT, fixsubj WILL TELL YOU X## AND ASK YOU IF YOU WANT TO EDIT IT BY HAND, USE THE DEFAULT X## FROM -s), OR SKIP IT. X## X## TO USE IT, TYPE: X## % fixsubj -s 'this is the subject' (FOR THE CURRENT MESSAGE) X## OR SOMETHING LIKE X## % fixsubj +foo last -s 'a subject' (last MESSAGE IN foo FOLDER) X## % fixsubj -s 'my day' 23-25 42 (MESSAGES 23, 24, 25, AND 42) X## ...AND SO ON. THE SUBJECT, AFTER THE -s, SHOULD BE "ONE WORD" TO X## THE SHELL... YOU'LL USUALLY NEED TO QUOTE IT. YOU CAN PUT THE X## OPTIONAL FOLDER NAME (STARTS WITH A +) AND MESSAGE NUMBERS (NUMBERS, X## WORDS LIKE last, first:20, first-33, etc.) IN ANY ORDER. X Xeditor=${VISUAL-${EDITOR-/usr/ucb/vi}} # TEXT EDITOR Xline="/usr/ucb/head -1" # READS ONE LINE Xmh=/usr/local/mh # WHERE MH COMMANDS LIVE Xmyname="`basename $0`" # BASENAME OF THIS PROGRAM Xscanopts="-noclear -noheader -noreverse" # BYPASS MH PROFILE Xstat=1 # DEFAULT EXIT STATUS; SET TO 0 BEFORE NORMAL EXIT Xtemp=/tmp/FIXSUBJ$$ Xtemperr=/tmp/FIXSUBJe$$ # HOLDS ERRORS FROM while LOOP Xusage="Usage: $myname [+folder] [msgnum] -s 'subject'" X Xtrap 'rm -f $temp $temperr; exit $stat' 0 1 2 15 X> $temp X> $temperr Xchmod 600 $temp $temperr X X# PARSE COMMAND LINE: Xwhile : Xdo X case "$1" in X "") break ;; # NO MORE ARGUMENTS X -help) echo "$usage" 1>&2; stat=0; exit ;; X [@+]*) folder="$1"; shift ;; X -s*) X case "$2" in X "") echo "$usage X (Missing subject.)" 1>&2 X exit X ;; X *) newsubj="$2" X shift; shift X ;; X esac X ;; X *) msgs="$msgs $1"; shift ;; X esac Xdone X Xcase "$newsubj" in X"") echo "$usage X (Missing subject.)" 1>&2 X exit X ;; Xesac X X# FOLDER PATH; IF NO $folder GIVEN, DEFAULTS TO CURRENT: Xfolpath="`$mh/mhpath $folder`" || exit X X# MAKE LIST OF MESSAGE NUMBERS AND SUBJECTS, ONE PER LINE. X# IF NO Subject: IN MESSAGE, $subjnow WILL BE EMPTY. X# FEED INTO LOOP. IF NO msgs ON COMMAND LINE, SET TO cur. X# X# sh WILL RUN THIS IN A SUB-SHELL, SO exit WILL ONLY END X# THE LOOP, NOT THE WHOLE SCRIPT. WORK-AROUND: PUT INTERNAL X# ERRORS ON FILE DESCRIPTOR 3 AND COLLECT AT END OF LOOP: X$mh/scan $scanopts -width 200 -format "%(msg) %{subject}" ${msgs=cur} | Xwhile read msg subjnow Xdo X msgpath=$folpath/$msg X X # IF MESSAGE IS UNREADABLE, scan (MH6.6 AND BEFORE) X # WILL PRINT A LINE (TO STANDARD OUTPUT!) LIKE THIS, X # WITH LEADING BLANKS UNLESS msgnum > 999: X # <msgnum> unreadable X # IF THERE ARE LEADING BLANKS, SOME BOURNE SHELLS WILL X # COPY BOTH THE MESSAGE NUMBER AND THE unreadable INTO X # subjnow, AND LEAVE $msg EMPTY. TRY TO FIX BOTH CASES: X case "$msg" in X "") echo "$myname: quitting, message $msg $subjnow" 1>&3; break ;; X esac X case "$subjnow" in X unreadable) X echo "$myname: quitting: can't read message '$msg'." 1>&3 X break X ;; X "") # GLUE Subject AND X-Original-Subject TO TOP. X # IF YOUR SHELL DOESN'T UNDERSTAND "<<-", REPLACE IT X # WITH "<<" AND SHIFT LINES TO LEFT-HAND EDGE: X cat - $msgpath > $temp <<- ENDOFHDR X Subject: $newsubj X X-Original-Subject: (none) X ENDOFHDR X cp $temp $msgpath || { X echo "$myname: quitting: can't replace ${msgpath}?" 1>&3 X break X } X ;; X *) # MESSAGE HAS A SUBJECT ALREADY; ASK USER: X # LOOP UNTIL GET ANSWER: X while : X do X # SAME NOTE AS ABOVE ABOUT REPLACING "<<-"... X cat <<- ENDOFMSG X X Message $msg already has a subject: X ... $subjnow X Type c to change subject to '$newsubj' X Type e to edit the message yourself with $editor X Type s to skip this message and go on to the next (if any) X Type q to quit and not change any more messages. X ENDOFMSG X echo -n "And the answer is? " 1>&2 X ans="`$line </dev/tty`" X case "$ans" in X s*) break ;; # CONTINUE OUTER (MESSAGE) LOOP X q*) break 2 ;; X e*) $editor $msgpath </dev/tty >/dev/tty 2>/dev/tty X break X ;; X c*) # NOTE: FIX "<<-" AND LINES IF SHELL NEEDS: X ed - $msgpath <<- !ENDOFEDIT! >$temp 2>&1 X /^Subject: /s/^/X-Original-/ X i X Subject: $newsubj X . X w X q X !ENDOFEDIT! X if [ ! -s $temp ] X then break X else X echo "$myname: error editing '$msg':" 1>&2 X cat "$temp" 1>&2 X echo "Should you edit it by hand? Try again: X " 1>&2 X fi X ;; X *) echo "Please try again..." 1>&2 ;; X esac # END OF case "$ans" X done # END OF while : X ;; X esac # END OF case "$subjnow" Xdone 3> $temperr # END OF while read msg subjnow X Xif test -s $temperr Xthen cat $temperr 1>&2 Xelse stat=0 Xfi Xexit X//E*O*F fixsubj// chmod u=rwx,g=rx,o=rx fixsubj echo extracting - fols sed 's/^X//' > "fols" <<'X//E*O*F fols//' X#! /bin/sh X# $Header: /u3/acs/jdpeek/.bin/RCS/fols,v 1.7 90/10/13 08:45:31 jdpeek book $ X### fols - Show list of folders, in columns, current folder marked X### Usage: fols [ -recurse ] << (just -r is enough...) X## X## THE folder -fast PROGRAM GIVES A LIST OF YOUR TOP-LEVEL FOLDERS X## IN ONE COLUMN. IF YOU HAVE A LOT OF FOLDERS, THIS CAN BE A PAIN X## BECAUSE THE LIST CAN SCROLL OFF YOUR SCREEN. fols REFORMATS THE X## folder -fast OUTPUT INTO FOUR COLUMNS. IT MARKS THE CURRENT FOLDER X## WITH A +. IF ANY FOLDER NAMES ARE TOO LONG FOR A COLUMN, IT X## CUTS OUT THE MIDDLE OF THE NAME AND REPLACES IT WITH AN "=". X## X## BY DEFAULT, fols ONLY SHOWS THE TOP-LEVEL FOLDERS. THE -r SWITCH X## MAKES IT RECURSIVE, LIKE folder -recurse -fast. X## X## HERE'S AN EXAMPLE. THE EXAMPLE WITH -r SHOWS A SET OF SUB-FOLDERS X## NINE LEVELS DEEP, STARTING WITH A SUB-FOLDER NAMED test/l1: X## X## % fols X## drafts haha inbox+ scans X## scantest test test2 test3 X## % fols -r X## drafts haha haha/sub inbox+ X## scans scantest test test/MaIlSoRt9818 X## test/haha test/l1 test/l1/l2 test/l1/l2/l3 X## test/l1/l2/l3/l4 test/l1/=/l3/l4/l5 test/l1/=/l4/l5/l6 test/l1/=/l5/l6/l7 X## test/l1/=/l6/l7/l8 test/l1/=/l7/l8/l9 test2 test3 X Xfolopts="-fast -nolist -nototal -nopack" # OVERRIDE MH PROFILE Xmh=/usr/local/mh # WHERE MH COMMMANDS ARE Xrec= X Xcase "$#$1" in X0"") ;; X1-r*) rec=-recurse ;; X*) echo "Usage: `basename $0` [ -recurse ] (just -r is enough)" 1>&2 X exit 1 X ;; Xesac X X# USE BACKQUOTES TO "PASTE" THE CURRENT FOLDER NAME X# INTO THE sed EXPRESSION THAT ADDS A + TO END. X# THEN, IN ANY LINE WHICH HAS AT LEAST 19 CHARACTERS, X# SAVE FIRST 8 AND LAST 9 CHARACTERS AND REPLACE X# MIDDLE CHARACTER(S) WITH AN = SIGN. FINALLY, GIVE X# TO pr WITH LINE LENGTH OF 1 TO MAKE INTO 4 COLUMNS: X$mh/folders $rec $folopts | X/bin/sed -e "s@^`$mh/folder $folopts`\$@&+@" \ X -e 's/^\(........\)...*\(.........\)$/\1=\2/' | X/bin/pr -l1 -4 -w78 -t X//E*O*F fols// chmod u=rwx,g=rx,o=rx fols echo extracting - incs sed 's/^X//' > "incs" <<'X//E*O*F incs//' X#! /bin/sh X# $Header: /u1/acs/jdpeek/.bin/RCS/incs,v 1.9 90/07/03 07:18:22 jdpeek Exp $ X# X### incs - incorporate messages, then show them X### Usage: incs [+folder] [-inc options] X## X## incs DOES AN inc, THEN A show OF ALL MESSAGES inc'D. IF YOU SET THE X## ENVIRONMENT VARIABLE $INCSHOW TO THE NAME OF A PROGRAM (LIKE X## mail.review), THEN incs WILL USE IT INSTEAD OF show. X## X## IF YOU GIVE IT A FOLDER NAME, LIKE THIS: X## % incs +newmail X## IT'LL INCORPORATE THE MAIL INTO THE FOLDER YOU NAME (HERE, newmail). X Xumask 077 # MAKE TEMP FILE PRIVATE Xtemp=/tmp/INCS$$ Xinc=/usr/local/mh/inc Xstat=1 # DEFAULT EXIT STATUS; RESET TO 0 ON NORMAL EXIT Xtrap 'rm -f $temp; exit $stat' 0 1 2 15 X X# ONLY SHOW MESSAGE IF inc ACTUALLY INCORPORATED ONE. X# BE SURE inc CHANGES CURRENT MESSAGE (OVERRIDE .mh_profile): Xif $inc -changecur $* > $temp Xthen X cat $temp X ${INCSHOW-show} cur-last X stat=0 Xfi X//E*O*F incs// chmod u=rwx,g=rx,o=rx incs echo extracting - mhprofile sed 's/^X//' > "mhprofile" <<'X//E*O*F mhprofile//' X#! /bin/sh X# $Header: /u3/acs/jdpeek/.bin/RCS/mhprofile,v 1.4 90/10/13 08:41:27 jdpeek book $ X# X### mhprofile - show matching line(s) from MH profile file X### Usage: mhprofile [-b] component-name X## X## USE mhprofile TO READ A LINE FROM THE .mh_profile FILE. X## FOR EXAMPLE, IF YOU WANT TO READ THE "DRAFT-FOLDER" LINE, TYPE: X## $ mhprofile draft-folder X## Draft-Folder: drafts X## THE -b OPTION STRIPS OFF THE COMPONENT NAME. EXAMPLE: X## $ mhprofile -b draft-folder X## drafts X## X## RETURNS 0 IF MATCH FOUND, 1 IF NO MATCHES, 2 ON ERRORS X Xgrep=/bin/grep # HAS -i OPTION, HANDLES REGULAR EXPRESSIONS Xsed=/bin/sed Xprofile=${MH-${HOME?}/.mh_profile} # COMPLAIN AND EXIT IF $HOME NOT SET X X# GET -b OPTION, IF ANY, AND shift IT AWAY: Xcase "$1" in X-b) stripname=y; shift;; X-*) echo "Usage: `basename $0` [-b] component-name X (I don't understand '$1')." 1>&2 X exit 2 X ;; Xesac X X# ONLY REMAINING ARGUMENT SHOULD BE A COMPONENT NAME: Xcase $# in X1) ;; X*) echo "Usage: `basename $0` [-b] component-name X (wrong number of arguments)." 1>&2 X exit 2 X ;; Xesac X X# IF grep FAILS, RETURN ITS STATUS (1=NO MATCH, 2=ERROR): Xlines="`$grep -i \"^${1}:\" $profile`" || exit X X# IF -b SET, USE sed TO SEARCH AND STRIP OFF LABEL+BLANKS. X# ASSUME NO BLANKS IN NAME, ":" AND MAYBE BLANKS AFTER NAME: Xcase "$stripname" in Xy) echo "$lines" | $sed -n 's/^[^:]*: *//p' ;; X*) echo "$lines" ;; Xesac Xexit 0 # A LITTLE PRESUMPTUOUS? X//E*O*F mhprofile// chmod u=rwx,g=rx,o=rx mhprofile echo extracting - recomp sed 's/^X//' > "recomp" <<'X//E*O*F recomp//' X#! /bin/sh X# $Header: /u3/acs/jdpeek/.bin/RCS/recomp,v 1.6 90/10/13 08:25:07 jdpeek book $ X### recomp - re-compose a draft mesage in MH draft folder X### Usage: recomp [msgnum] X# X## WHEN YOU TYPE q AT A What now? PROMPT, IT LEAVES THE DRAFT MESSAGE X## WITHOUT SENDING IT. IF YOU HAVE A DRAFT FOLDER, THE COMMAND LINE X## YOU'D TYPE TO RE-COMPOSE THE DRAFT IS LONG, LIKE: X## comp -use -draftm 3 -draftf +drafts -editor vi. X## ALSO, IT CAN BE HARD TO REMEMBER THE DRAFT NUMBER--SO YOU HAVE TO X## scan THE DRAFT FOLDER, THEN REMEMBER TO CHANGE YOUR FOLDER BACK. X## X## THIS SCRIPT HELPS WITH THAT. IF YOU GIVE IT A MESSAGE NUMBER IN THE X## DRAFT FOLDER, IT STARTS comp -use ON THAT MESSAGE WITH YOUR FAVORITE X## EDITOR PROGRAM. WITHOUT A MESSAGE NUMBER, recomp scanS THE DRAFT X## FOLDER, THEN LETS YOU ENTER THE NUMBER OF THE MESSAGE YOU WANT TO X## RE-COMPOSE AND STARTS comp -use. X## X## WHEN YOU EXIT YOUR EDITOR, YOU GET THE USUAL What now? PROMPT. X Xdraftf=+drafts # NAME OF DRAFT FOLDER Xfolopts="-fast -norecurse -nolist -nototal -nopack" Xmh=/usr/local/mh # WHERE MH PROGRAMS LIVE X X# THIS CAN LEAVE US IN THE $draftf FOLDER. SO, PUSH X# CURRENT FOLDER ON STACK AND COME BACK AFTER EDITING: X$mh/folder -push $folopts $draftf >/dev/null || { X echo "`basename $0`: quitting: problem with draft folder '$draftf'." 1>&2 X exit 1 X} Xstat=1 # DEFAULT EXIT STATUS; RESET TO 0 FOR NORMAL EXITS Xtrap '$mh/folder -pop $folopts >/dev/null; exit $stat' 0 Xtrap 'echo "`basename $0`: Interrupt! Cleaning up..." 1>&2' 1 2 15 X Xcase $# in X0) # THEY DIDN'T GIVE MESSAGE NUMBER; SHOW THEM FOLDER: X if $mh/scan X then X echo -n "Which draft message number do you want to re-edit? " X read msgnum X else X echo "`basename $0`: quitting: no messages in your $draftf folder?" 1>&2 X exit X fi X ;; X1) msgnum="$1" ;; X*) echo "I don't understand '$*'. X I need the draft message number, if you know it... otherwise, nothing. X Usage: `basename $0` [msgnum]" 1>&2 X exit X ;; Xesac X X$mh/comp -use -e ${VISUAL-${EDITOR-${EDIT-vi}}} -draftm $msgnum -draftf $draftf Xstat=$? # SAVE comp'S STATUS (IT'S USUALLY 0) FOR OUR exit X//E*O*F recomp// chmod u=rwx,g=rx,o=rx recomp echo extracting - replf sed 's/^X//' > "replf" <<'X//E*O*F replf//' X#! /bin/sh X# $Header: /u3/acs/jdpeek/.bin/RCS/replf,v 1.3 90/10/13 08:31:54 jdpeek book $ X### replf - refile current message into folder, then reply to it X### Usage: replf +folder [switches for repl] X## X## DO YOU USE MH FOLDERS A LOT? YOU PROBABLY inc MAIL INTO YOUR inbox, X## THEN YOU replY TO SOME MESSAGES AND refile THE ORIGINALS INTO SOME X## OTHER FOLDER. THE PROBLEM IS THAT IF YOU USE AN Fcc: LINE TO PUT X## A COPY OF THE REPLY IN THE DESTINATION FOLDER, IT IS STORED BEFORE X## THE ORIGINAL MESSAGE. ALSO, IT'S A PAIN TO refile THE ORIGINAL, X## THEN TYPE THE SAME NAME ON THE Fcc LINE. SO, IT'D BE CONVENIENT X## TO DO ALL THAT IN ONE STEP. replf LETS YOU DO THAT. X## X## replf USES refile TO MOVE THE *CURRENT* MESSAGE INTO THE FOLDER YOU X## NAME. (IT ONLY WORKS FOR THE CURRENT MESSAGE!) THEN, IT STARTS X## repl WITH THE -fcc +folder SWITCH, SO THAT AN Fcc: OF YOUR MESSAGE X## WILL GO INTO THAT FOLDER, TOO. X## X## WATCH OUT: THIS VERSION OF replf HAS ONE PROBLEM: YOU CAN'T USE X## What now? push X## TO SEND THE DRAFT. THAT'S BECAUSE THE TEMPORARY FILES replf MAKES X## ARE REMOVED BEFORE THE MESSAGE IS SENT. USE send INSTEAD. X# X# Original from Marshall T. Rose and John L. Romine in X# MH6.6 distribution. Revised by Jerry Peek, 2/25/90. X Xcontext=/tmp/ctx$$ # COPY OF MH context FILE Xmh=/usr/local/mh # WHERE MH COMMANDS LIVE Xprofile=/tmp/prf$$ # COPY OF .mh_profile FILE Xstat=1 # DEFAULT EXIT STATUS; RESET TO 0 BEFORE NORMAL exit X X/bin/rm -f $profile $context Xtrap '/bin/rm -f $profile $context; exit $stat' 0 1 2 15 X X# PARSE COMMAND LINE: Xfolder= switches= Xfor arg Xdo X case "$arg" in X +*|@*) # IT'S A FOLDER X case "$folder" in X "") folder="$arg" ;; X *) echo "`basename $0`: '$arg'? Only one folder at a time." 1>&2 X exit X ;; X esac X ;; X *) switches="$switches $arg" ;; X esac Xdone X Xcase "$folder" in X"") echo "usage: `basename $0` +folder [switches for repl]" 1>&2 X exit X ;; Xesac X X# MAKE TEMPORARY context AND .mh_profile FILES. X# THEN, RESET $MH AND $MHCONTEXT UNTIL END OF THIS SCRIPT: X/bin/cp ${MHCONTEXT-`$mh/mhpath +`/context} $context || exit X# READ NEXT TWO LINES, PLUS A COPY OF USER'S STANDARD X# .mh_profile, INTO NEW $profile: X/bin/cat - ${MH-$HOME/.mh_profile} << \END > $profile || exit XMH-Sequences: XPrevious-Sequence: pseq XEND X XMH=$profile MHCONTEXT=$context Xexport MH MHCONTEXT X X# REFILE MESSAGE INTO $folder. X# NEW MESSAGE NUMBER IS IN THE pseq OF $folder. X$mh/refile $folder || exit X$mh/repl $folder pseq -fcc $folder $switches Xstat=$? # EXIT WITH STATUS OF repl Xexit X//E*O*F replf// chmod u=rwx,g=rx,o=rx replf echo extracting - resend.fixmsg sed 's/^X//' > "resend.fixmsg" <<'X//E*O*F resend.fixmsg//' X#! /bin/sh X# $Header: /u3/acs/jdpeek/.bin/RCS/resend.fixmsg,v 1.5 90/10/13 09:39:23 jdpeek book $ X### resend.fixmsg - editor for fixing up returned mail X### Usage in .mh_profile: resend: -editor resend.fixmsg -nodashmunging X## X## TO USE THIS, FIRST MAKE A VERSION OF forw NAMED resend X## (MAKE SYMBOLIC LINK TO forw, ETC.). THEN, ADD THE ENTRY X## SHOWN ABOVE TO YOUR .mh_profile. X## X## WHEN YOU START resend, IT BUILDS A DRAFT AND CALLS X## resend.fixmsg TO EDIT IT. resend.fixmsg MAKES THE MESSAGE X## LOOK ALMOST EXACTLY AS IT DID THE FIRST TIME YOU COMPOSED X## IT, THEN POPS YOU INTO AN EDITOR (DEFAULT: vi) TO FIX THE X## ADDRESS. X X# $1 IS PATH TO DRAFT MESSAGE (forw SETS THIS). X# X# HERE'S WHAT ed SCRIPT DOES TO THE DRAFT THAT forw BUILT: X# DELETE LINES THROUGH FIRST "To: (you)". X# DELETE LINES TO BUT NOT INCLUDING NEXT "To: (original)". X# ZAP Date:/From:/Sender: LINES THAT MAILER PUT IN MESSAGE. X# ZAP FROM BLANK LINE BEFORE "---- End of Forwarded Message" X# THROUGH THE END OF THE FILE. X/bin/ed - $1 << "END" X1,/^To: /d X1,/^To: /-1d X1,/^$/g/^Date: /d X1,/^$/g/^From: /d X1,/^$/g/^Sender: /d X$ X?^------- End of Forwarded Message?-1,$d Xw Xq XEND X X# EDIT WITH $EDITOR (DEFAULT: vi). exec TO SAVE A PROCESS: Xexec ${EDITOR-vi} $1 X//E*O*F resend.fixmsg// chmod u=rwx,g=rx,o=rx resend.fixmsg echo extracting - rmmer sed 's/^X//' > "rmmer" <<'X//E*O*F rmmer//' X#! /bin/sh X# $Header: /u3/acs/jdpeek/.bin/RCS/rmmer,v 3.4 90/11/21 06:52:02 jdpeek Exp $ X### rmmer - move mail to @DELETE for "find" to clean up X### Usage in .mh_profile: rmmproc: rmmer X### rmmer.one_fdr - move mail to +DELETE for "find" to clean up X### Usage in .mh_profile: rmmproc: rmmer.one_fdr X## X## rmmer IS DESIGNED TO BE USED WITH THE MH MAIL rmm COMMAND. X## INSTEAD OF JUST ADDING A COMMA (,) TO THE MESSAGE NAME, LIKE X## STANDARD rmm DOES, rmmer MOVES THE MESSAGE INTO A SUB-FOLDER X## NAMED "DELETE". A SYSTEM PROGRAM SHOULD CLEAN OUT THAT FOLDER X## EVERY SO OFTEN (YOU MAY HAVE TO SET THAT UP, TOO). ANYHOW, X## THE IDEA IS THAT MESSAGES IN A "DELETE" SUB-FOLDER ARE EASY TO X## RECOVER IF YOU REMOVED ONE BY ACCIDENT. X## X## FOR EXAMPLE, LET'S SAY YOU JUST DELETED A MESSAGE BY ACCIDENT. X## TO GET IT BACK, YOU GO TO THE SUB-FOLDER. YOUR MESSAGE WILL X## BE THE LAST ONE IN THE SUB-FOLDER BECAUSE YOU JUST REMOVED IT. X## TO RECOVER THE DELETED MESSAGE, MOVE IT BACK TO THE PARENT FOLDER X## (WHERE IT WAS BEFORE) WITH refile. AFTER YOU RECOVER IT, IT'LL X## BE THE LAST MESSAGE IN THE FOLDER. HERE GOES: X## % rmm X## % show last @DELETE X## (Message inbox/DELETE:25) X## (message appears -- this is the one you "deleted") X## % refile @.. X## % show last @.. X## (Message inbox:54) X## (same message appears -- now it's back in the parent folder) X## X## IF YOU DON'T WANT rmmer TO USE A SUB-FOLDER--AND, INSTEAD, PUT X## ALL THE MESSAGES IN A CENTRAL "DELETE" FOLDER--YOU CAN CALL THE X## PROGRAM WITH THE NAME rmmer.one_fdr AND THAT'LL DO IT. X X# TABSTOPS ARE SET AT 4 IN THIS CODE X Xtempchr=',' # CHARACTER rmm ADDS TO "REMOVE" MESSAGE Xmh=/usr/local/mh # MH COMMANDS ARE IN THIS DIRECTORY Xmoveto=DELETE # NAME OF FOLDER FOR DELETED MESSAGES Xmvdir=/bin # DIRECTORY WHERE mv COMMAND LIVES X Xawk=/bin/awk mkdir=/bin/mkdir touch=/bin/touch tr=/bin/tr X X# USE PROGRAM NAME TO SET PATH TO DESTINATION FOLDER: Xcase "$0" in X*rmmer) destfol="@$moveto" ;; X*rmmer.one_fdr) destfol="+$moveto" ;; X*) echo "$0 aborting: can't find my name." 1>&2; exit 1 ;; Xesac X Xstat=1 # DEFAULT EXIT STATUS; RESET TO 0 BEFORE NORMAL EXIT Xtrap 'rm -f $MH; exit $stat' 0 Xtrap 'echo "$0: Interrupt! $* may not be removed." 1>&2; exit' 1 2 15 X X# TO AVOID ENDLESS LOOPS WHERE THE rmm IN rmmer RUNS rmmproc, X# MAKE TEMPORARY .mh_profile TO BYPASS USER'S rmmproc: rmmer. X# MAKE WHILE MH IS SHELL VARIABLE, THEN export TO USE IT: XMH=/tmp/RMMER$$ Xecho "Path: `$mh/mhpath +`" > $MH || exit Xexport MH X X# rmm SETS CURRENT DIRECTORY TO FOLDER, SO IT'S EASY TO MAKE X# NEW SUB-FOLDER. (LET USER MAKE THEIR OWN "+DELETE" ONCE.) Xif [ "$destfol" = "@$moveto" -a ! -d "$moveto" ] Xthen $mkdir $moveto || exit Xfi X X# rmm PUTS SINGLE MESSAGE NUMBERS INTO $* (LIKE 12 13 14). X# UPDATE LAST-MOD TIME SO find -mtime WON'T DELETE TOO SOON: X$touch $* >/dev/null 2>&1 X X$mh/rmm $* || exit # ADDS $tempchr TO MESSAGE NUMBERS X X# IF <= 7 MESSAGES, REFILE EACH WITH mv AND mhpath new. X# OTHERWISE, SAVE TIME BY GETTING FIRST UNUSED MESSAGE NUMBER X# IN $destfol AND USING PLAIN mv COMMANDS IN A LOOP: Xcase $# in X[1-7]) X for m X do $mvdir/mv ${tempchr}$m `$mh/mhpath new $destfol` || exit X done X ;; X*) newpath="`$mh/mhpath new $destfol`" || exit # FIRST MSG. X PATH=${mvdir}:$PATH; export PATH # GET THE RIGHT mv X # GIVE awk NUMBERS LIKE 23 24, SPLIT ONTO SEPARATE LINES X # BY TURNING SPACES INTO NEWLINES. OUTPUT mv COMMANDS X # THAT THE SHELL READS (BY eval) AND RUNS, LIKE THIS: X # mv ,23 /xxx/Mail/inbox/DELETE/99; X # mv ,24 /xxx/Mail/inbox/DELETE/100; X # **HUGE** MESSAGE LISTS MAY CAUSE LONG-LINE PROBLEMS. X eval ` X echo $* | $tr ' ' '\012' | $awk ' X BEGIN { X # SPLIT PATH OF FIRST UNUSED MESSAGE INTO part ARRAY: X np = split("'$newpath'", part, "/") X # BUILD ALL BUT THE LAST PIECE INTO DIRECTORY NAME: X for (i = 2; i < np; i++) X dir = dir "/" part[i] X # LAST part IS FIRST NEW MESSAGE NUMBER; PUT IN new. X # MAKE SURE awk TREATS AS INTEGER BY ADDING ZERO: X new = part[np] + 0 X } X { X # READ MESSAGE NUMBERS, OUTPUT COMMANDS: X printf "mv ,%d %s/%d;", $1, dir, new++ X }'` X ;; Xesac X Xstat=0 Xexit X//E*O*F rmmer// chmod u=rwx,g=rx,o=rx rmmer echo extracting - scandrafts sed 's/^X//' > "scandrafts" <<'X//E*O*F scandrafts//' X#! /bin/sh X# $Header: /u3/acs/jdpeek/.bin/RCS/scandrafts,v 1.5 90/10/13 09:08:29 jdpeek book $ X### scandrafts - scan MH draft folder; return to original folder if no -stay X### Usage: scandrafts [-stay] [scan arguments] X## X## THIS SCRIPT IS NICE WHEN YOU'RE WONDERING WHAT'S IN YOUR DRAFT X## FOLDER, OR YOU NEED TO WORK IN IT. X## X## BY DEFAULT, scandrafts SHOWS A LIST OF THE MESSAGES YOU'VE ALREADY X## SENT (THESE MESSAGES ARE IN FILES WITH A COMMA OR POUND SIGN BEFORE X## THEIR NAMES). THEN, IT scanS YOUR DRAFT FOLDER, AND POPS YOU BACK X## TO YOUR CURRENT FOLDER. X## X## IF YOU USE THE -stay OPTION, scandrafts WILL START A SHELL WITH X## BOTH THE CURRENT DIRECTORY AND CURRENT FOLDER IN THE DRAFT FOLDER. X## THAT WAY, YOU CAN RESTORE ONE OF THE ALREADY-SENT MESSAGES AND/OR X## refile IT TO ANOTHER FOLDER (IN CASE YOU FORGOT TO GIVE YOURSELF A X## COPY WHEN YOU SENT IT). OR, YOU CAN DO EXTENSIVE WORK ON THE X## DRAFTS, MORE DIRECTLY THAN A SCRIPT LIKE recomp WILL LET YOU. X## X## HERE'S A DEMONSTRATION: X## X## $ scandrafts -stay X## Draft message(s) you've already sent: X## X## ,1:Subject: Re: SC or GA islands X## ,5:Subject: Re: our previous message about banners dialups etc X## ,6:Subject: Re: Can you help? X## ,7:Subject: Out this morning X## X## To get them back, use 'mv'. X## =================================================================== X## Draft message(s) you haven't sent: X## X## 1 03/07*To:alison@mvus.cs Project status<<Alison, the project X## 2 empty X## 3+ 03/07*To:kx9cq@cornell. Scientific Visualization Demo<<I re X## X## You'll be in a /usr/local/bin/ksh shell in the +drafts folder. X## To quit, type control-d. X## scandrafts> rmm 2 X## scandrafts> mv ,6 6 X## scandrafts> scan X## 1 03/07*To:alison@mvus.cs Project status<<Alison, the project X## 3+ 03/07*To:kx9cq@cornell. Scientific Visualization Demo<<I re X## 6 03/04*To:warren Re: Can you help?<<Warren, you aske X## scandrafts> refile 6 +outbox X## scandrafts> ^D X## [folder +inbox now current] X## $ X Xargs= # RESET IN CASE THERE'S AN args ENVIRONMENT VARIABLE Xfolopts="-fast -nolist -nototal -nopack" Xmh=/usr/local/mh Xmhprf=/XXXXXXXXXXXXXXXXXX/mhprofile # READS MH PROFILE Xpageprog=${PAGER-/usr/ucb/more} # DISPLAYS SCREEN-BY-SCREEN Xstat=1 # DEFAULT EXIT STATUS; RESET TO 0 FOR NORMAL EXITS Xtemp=/tmp/SCANDRFTS$$ X>$temp Xchmod 600 $temp Xtrap 'rm -f $temp; exit $stat' 0 1 2 15 X X# IF -stay SWITCH IS SET, SET $stay TO y: Xfor arg Xdo X case "$arg" in X -stay) stay=y ;; X *) args="$args $arg" ;; X esac Xdone X X# GET DRAFT FOLDER NAME: Xdraftfold="`$mhprf -b draft-folder`" || { X echo "`basename $0`: quitting: can't find your 'Draft-Folder'." 1>&2 X exit X} X X$mh/folder $folopts -push +$draftfold >/dev/null || exit Xfolpath=`$mh/mhpath +$draftfold` || exit Xcd $folpath || exit X X# IF ANY UN-SENT DRAFTS, SHOW THEM; THEN, scan FOLDER. X# PIPE ALL OF IT TO PAGER SO NONE OF IT SCROLLS OFF SCREEN: Xgrep "^Subject: " [,#]*[1-9]* >$temp 2>/dev/null X(if test -s $temp Xthen X echo "Draft message(s) you've already sent: X " X cat $temp X echo X case "$stay" in X y) echo "To get them back, use 'mv'." ;; X *) echo "To get them back, use 'cd $folpath' and 'mv'." ;; X esac X echo "=============================================================" X echo "Draft message(s) you haven't sent: X " Xfi X$mh/scan $args 2>&1) | $pageprog X X# USE THEIR $SHELL, IF DEFINED... OTHERWISE, USE sh: Xcase "$stay" in Xy) echo " X You'll be in a ${SHELL-Bourne} shell in the +$draftfold folder. X To quit, type control-d." X PS1="scandrafts> " ${SHELL-sh} X ;; Xesac X X# POP FOLDER BACK; PUT NEWLINE BEFORE MESSAGE: Xecho " X[folder +`$mh/folder $folopts -pop` now current]" Xstat=0 X//E*O*F scandrafts// chmod u=rwx,g=rx,o=rx scandrafts echo extracting - showpr sed 's/^X//' > "showpr" <<'X//E*O*F showpr//' X#! /bin/sh X# $Header: /u3/acs/jdpeek/.bin/RCS/showpr,v 2.2 90/10/13 10:30:57 jdpeek book $ X### showpr - show MH message(s) with pr(1), custom heading, maybe mhl(1) X### Usage: showpr [fdr] [msgs] [-mhl] [-format 'mh-format-str'] [-pr 'pr-opts'] X## X## THE EASY WAY TO PRINT MESSAGES IN MH ISN'T ESPECIALLY GREAT. YOU CAN X## PRINT YOUR MAIL MESSAGES LIKE THIS (ASSUMING YOUR PRINTER PROGRAM IS X## NAMED lpr), BUT ALL THE MESSAGES WILL BE RUN TOGETHER: X## % show 23 24 29 | lpr X## OR, YOU CAN USE pr(1) TO MAKE SIMPLE HEADERS (WITH THE FOLDER AND X## MESSAGE NUMBER), PAGE NUMBERS, AND START EACH MESSAGE ON A NEW PAGE: X## % show -showproc pr 23 24 29 | lpr X## X## THE showpr PROGRAM LETS YOU DO MORE. IT CAN USE mhl, IF YOU WANT, TO X## CLEAN UP THE MESSAGE BEFORE PRINTING. YOU CAN CUSTOMIZE THE PAGE HEADING X## -- INCLUDING THE MESSAGE SUBJECT, FOR INSTANCE. AND YOU CAN PASS OPTIONS TO X## pr, TO TELL IT HOW TO FORMAT YOUR MESSAGE. FINALLY, YOU CAN STORE DEFAULT X## showpr OPTIONS IN YOUR .mh_profile FILE, BECAUSE showpr CALLS THE mhprofile X## SCRIPT TO GET THEM. X## X## THE COMMAND LINE USES mh-format STRINGS LIKE THE ONES YOU'D GIVE TO X## THE scan COMMAND. HERE ARE SOME EXAMPLES. SOME OF THESE MIGHT LOOK X## COMPLICATED, BUT REMEMBER THAT YOU CAN STORE ANY SET OF OPTIONS AS X## DEFAULTS IN YOUR .mh_profile FILE: X## X## TO PRINT THE CURRENT MESSAGE, WITH THE MESSAGE SUBJECT IN EACH PAGE X## HEADING (IF YOU HAVEN'T PUT ANY showpr OPTIONS IN YOUR .mh_profile): X## % showpr | lpr X## TO PRINT THE LAST 3 MESSAGES, WITH THE MESSAGE SUBJECT IN EACH PAGE X## HEADING; FORMAT THE MESSAGES WITH mhl; AND TELL pr TO USE X## ITS OPTIONS -f (SEPARATE PAGES WITH FORMFEEDS) AND -l50 X## (MAKE PAGE LENGTH 50 LINES): X## % showpr -mhl -pr '-f -l50' last:3 X## (YOU CAN SHORTEN THOSE OPTIONS TO -m AND -p, IF YOU WANT.) X## X## HERE'S MORE. TO PRINT THE LAST 3 MESSAGES WITH mhl FORMATTING, WITH X## THE "From" ADDRESS AND MESSAGE DATE IN THE HEADING, LIKE THIS: X## Mar 11 08:49 1990 From: al@phlabs.ph.com Date: 11/23/89 Page 2 X## USE A COMMAND LINE LIKE THIS (SPLIT ONTO TWO LINES FOR READABILITY): X## showpr -m -f 'from: %(friendly{from}) \ X## date: %(mon{date})/%(mday{date})/%(year{date})' last:3 | lpr X## TO MAKE THAT EASIER, YOU COULD PUT THE FOLLOWING LINE IN X## YOUR .mh_profile FILE (NOTE: ALTHOUGH IT'S SPLIT ONTO TWO LINES X## HERE, YOU SHOULD PUT IT ALL ON *ONE* LINE IN YOUR .mh_profile FILE): X## showpr: -m -f 'from: %(friendly{from}) \ X## date: %(mon{date})/%(mday{date})/%(year{date})' X## THEN GET THAT FORMATTING AND PRINT YOUR MESSAGES WITH: X## % showpr last:3 | lpr X## X## FINALLY, ABOUT mhl. YOU CAN MAKE AN mhl FORM FILE NAMED mhl.showpr X## AND PUT IT IN YOUR MH DIRECTORY (LIKE /xxx/yyy/Mail/mhl.showpr). X## IF YOU DO, AND IF YOU USE THE -mhl OPTION, THEN showpr WILL X## FORMAT YOUR MESSAGES WITH mhl -form mhl.showpr. X## OTHERWISE, THE -mhl OPTION USES THE STANDARD mhl.format FILE. X X# NOTE: TABSTOPS ARE SET AT 4 IN THIS CODE. X Xfolopts="-nolist -nototal -nopack" Xmh=/usr/local/mh # WHERE MOST MH PROGRAMS LIVE Xmhl=/usr/local/lib/mh/mhl # WHERE mhl LIVES Xmhprofile=/XXXXXXXXXXXXXXXXXX/mhprofile # READS MH PROFILE Xmyname="`basename $0`" Xpr=/bin/pr Xprwidth=55 # MAX WIDTH OF -h FIELD IN $pr + 5 FOR MSG NUM Xscanopts="-noclear -noheader -noreverse" Xstat=1 # DEFAULT EXIT STATUS, RESET TO 0 BEFORE NORMAL EXIT Xusage="usage: $myname [fdr] [msgs] [-mhl] [-format 'mh-format-str'] [-pr 'pr-opts']" X X# RESET "COMMAND LINE" PARAMETERS. FIRST, AN x, WHICH WE X# shift AWAY, IN CASE THERE ARE NO OTHER PARAMETERS. X# THEN, MH PROFILE OPTIONS (IGNORE mhprofile RETURN STATUS). X# LAST, ORIGINAL COMMAND LINE ARGS (WITH SHELL BUG PATCH): Xeval set x `$mhprofile -b $myname` '${1+"$@"}' Xshift X X# PARSE set ARGS. IF OPTIONS REPEATED, LAST ONES PREVAIL: Xwhile : Xdo X case "$1" in X "") break ;; # NO MORE ARGUMENTS X [+@]*) newfdr="$1" ;; X -h*) # HELP: X echo "$usage X \$Revision: 2.2 $ \$Date: 90/10/13 10:30:57 $" X exit X ;; X -m*) # SET mhlopts AS FLAG TO USE mhl. X mhlopts="-nobell -noclear -nofaceproc -nomoreproc" X # USE mhl.showpr FILE, IF ANY: X if test -r `$mh/mhpath +`/mhl.showpr X then mhlopts="$mhlopts -form mhl.showpr" X fi X ;; X -f*) X case "$2" in X "") echo "$usage X (Missing string after '-format')." 1>&2 X exit X ;; X *) format="$2"; shift ;; X esac X ;; X -p*) X case "$2" in X "") echo "$usage X (Missing string after '-pr')." 1>&2 X exit X ;; X +*|-*) propts="$2"; shift ;; X *) echo "$usage X (Bad options after '-pr')." 1>&2 X exit X ;; X esac X ;; X *) msgs="$msgs $1" ;; X esac X X shift Xdone X X# SET FORMAT OF pr HEADER. IF NO -format OPTION, AND IF NO X# "showpr:" LINE IN MH PROFILE, DEFAULT TO MESSAGE SUBJECT: X: ${format='%{subject}'} X X# CHANGE FOLDER (IF USER GAVE ONE), GET NAME. Xfolder="`$mh/folder $folopts -fast $newfdr`" Xcd `$mh/mhpath +` || exit # cd TO MH DIRECTORY X X# scan ALL MESSAGES; FEED TO LOOP. IF NONE, DEFAULT TO cur: Xscan -width $prwidth $scanopts -format "%(msg) $format" ${msgs-cur} | Xwhile read msgnum heading Xdo X # IF MESSAGE UNREADABLE, MH 6.6 scan PRINTS (TO stdout!) X # LIKE THIS, WITH LEADING BLANKS UNLESS msgnum > 999: X # <msgnum> unreadable X # IF THERE ARE LEADING BLANKS, SOME sh'S WILL COPY BOTH X # MESSAGE NUMBER AND unreadable INTO $heading, AND LEAVE X # $msgnum EMPTY. TRY TO CATCH BOTH CASES: X case "$msgnum" in X "") echo "$myname: skipping, message $msgnum $heading" 1>&2; continue ;; X esac X case "$heading" in X unreadable) echo "$myname: skipping unreadable message '$msgnum'." 1>&2; continue ;; X esac X X msgpath=$folder/$msgnum X case "$mhlopts" in X "") $pr $propts -h "$heading" $msgpath || break ;; X *) $mhl $mhlopts $msgpath | $pr $propts -h "$heading" || break ;; X esac Xdone X Xstat=0 Xexit X//E*O*F showpr// chmod u=rwx,g=rx,o=rx showpr echo extracting - vmsmail2mh sed 's/^X//' > "vmsmail2mh" <<'X//E*O*F vmsmail2mh//' X#! /bin/sh X# $Header: /u3/acs/jdpeek/.bin/RCS.Z/vmsmail2mh,v 1.2 90/03/22 06:53:59 jdpeek Exp $ X### vmsmail2mh - split VMS mail messages from EXTRACT/ALL into MH folder X### Usage: vmsmail2mh [+folder] [...vmsmsg-files] X## X## AN EASY WAY TO TRANSFER VMS MAIL MESSAGES TO UNIX IS BY EXTRACTING X## ALL THE MESSAGES FROM A VMS MAIL FOLDER INTO A FILE... USE: X## MAIL> EXTRACT/ALL X## _file: FILENAME X## THEN, YOU CAN ftp THEM TO THE SYSTEM RUNNING MH. X## X## WHEN YOU GET THEM TO THE MH SYSTEM, vmsmail2mh WILL READ THROUGH X## THE FILE (OR STANDARD INPUT, IF YOU DON'T GIVE A FILENAME): X## - THE MESSAGES ARE SEPARATED BY FORMFEEDS (CONTROL-L). X## vmsmail2mh WILL CUT THEM INTO SEPARATE MH MESSAGES X## IN THE CURRENT FOLDER (OR +folder IF YOU GIVE ONE). X## - THE FORMAT OF THE VMS MAIL MESSAGE IS DIFFERENT. X## * Subj: LINES ARE CONVERTED TO Subject: LINES. X## * From: LINES ARE SPLIT INTO From: AND Date: LINES. X## ONLY THE FIRST Subj: AND From: IN EACH MESSAGE IS CONVERTED. X## X## BUG: VMS ADDRESSES LIKE: X## SMTP%"user@host" X## HOST::USER X## AREN'T CONVERTED. IN FACT, *NO* ADDRESSES ARE CONVERTED. X X# NOTE: PROGRAM HASN'T BEEN TESTED THOROUGHLY. X# CHECK THE MESSAGES! X# Placed in the public domain. Use at your own risk. X# --Jerry Peek, 22 March 1990 X Xdfltprot=600 # DEFAULT MESSAGE PROTECTION (IF NONE IN MH PROFILE) Xfolopts="-fast -nolist -nototal -nopack -norecurse" Xmh=/usr/local/mh Xmhprofile=/u3/acs/jdpeek/.bin/mhprofile # READS MH PROFILE Xscanopts="-noclear -noheader -noreverse" X Xcase "$1" in X[@+]?*) X # IF $1 DOESN'T EXIST, folder WILL CREATE IT (SIGH). X # THAT'S BECAUSE stdout IS REDIRECTED AWAY FROM TERMINAL. X if $mh/folder $folopts "$1" >/dev/null X then X # GET PATHNAME OF FOLDER, LAST MESSAGE NUMBER: X folpath="`$mh/mhpath`" || exit X firstmsg="`$mh/scan -format '%(msg)' last`" || exit X else X echo "`basename $0`: no folder. quitting." 1>&2 X exit 1 X fi X ;; X*) echo "Usage: `basename $0` +folder|@folder [file] X ('$1' doesn't start with + or @.)" 1>&2 X exit 1 X ;; Xesac X Xif [ -n "$2" -a \( ! -r "$2" \) ] Xthen X echo "`basename $0`: quitting: can't read VMS file '$2'." 1>&2 X exit 1 Xfi X X# GET PROTECTION MODE FROM MH PROFILE (IF NONE, USE $dfltprot): Xmsgprot="`$mhprofile -b msg-protect`" || msgprot=$dfltprot X X# MAKE SHELL ARCHIVE FILE ON awk'S STANDARD OUTPUT. X# PIPE IT INTO sh TO CREATE THE MESSAGE FILES... Xawk "BEGIN { X folpath=\"$folpath\" # STORE AS STRING, WITH QUOTES X msgprot=$msgprot # STORE AS NUMBER (NO QUOTES) X msgnum=$firstmsg"' # CHANGE FROM DOUBLE- TO SINGLE-QUOTES X inmsg = 0 X} X# PROCESS MESSAGES. EACH MESSAGE STARTS WITH CONTROL-L. X# HOPE THERE ARE NO LINES WITH JUST A CONTROL-L IN MESSAGES! X{ X # MESSAGE STARTS WITH CTRL-L ON A LINE BY ITSELF. X # PRINT SHELL COMMANDS AND RESET FLAGS: X if ($0 ~ /^\014$/ && inmsg == 1) { X printf "END-OF-%s/%d\n", folpath, msgnum X # SET PROTECTION (INEFFICIENT; SHOULD DO ALL MSGS. AT ONCE) X printf "chmod %d %s/%d\n\n", msgprot, folpath, msgnum X inmsg = 0 X } X # AT START OF MESSAGE, PRINT START OF ARCHIVE AND SET FLAGS: X if (inmsg == 0) { X inmsg = 1 X msgnum += 1 X printf "/bin/cat > %s/%d << \\END-OF-%s/%d\n", \ X folpath, msgnum, folpath, msgnum X didsubj = 0 X didfrom = 0 X next X } X # TURN Subj: INTO Subject: AND SET FLAG TO MAKE SURE WE DO NOT X # TRASH ANY OTHER Subj: LINES (LIKE IN FORWARDED MESSAGES). X # STRIP DATE (14-MAR-1990 15:31:12.02) OFF END OF THE From: LINE X # AND MOVE IT TO LINE OF ITS OWN, THEN SET FLAG LIKE ABOVE: X if ($1 ~ /^Subj:/ && didsubj == 0) { X $1 = "Subject:" X didsubj = 1 X print X } X else if ($1 ~ /^From:/ && didfrom == 0) { X for (i = 1; i <= NF - 3; i++) X printf "%s ", $i X printf "%s\n", $(NF - 2) X printf "Date: %s %s\n", $(NF - 1), $NF X didfrom = 1 X } X else X print X}' $2 | # IF NO $2, WILL READ STANDARD INPUT... X/bin/sh -e # EXIT ON ANY ERROR X Xexit # RETURN STATUS FROM PIPE ABOVE X//E*O*F vmsmail2mh// chmod u=rwx,g=rx,o=rx vmsmail2mh echo extracting - xmhprint sed 's/^X//' > "xmhprint" <<'X//E*O*F xmhprint//' X#! /bin/sh X# $Header: /u3/acs/jdpeek/.bin/RCS/xmhprint,v 1.3 90/10/14 10:43:03 jdpeek book $ X### xmhprint - print command for xmh X### Usage (in .Xdefaults): xmh*PrintCommand: xmhprint [-cmd_num] X## X## THE PRINTER SUPPORT WITH xmh (X11r3 AND x11r4) ISN'T VERY GOOD. X## IT HANDS ALL YOUR MESSAGE FILES TO A PRINTER COMMAND AT ONCE. X## IT DOESN'T FILTER THEM TO REMOVE UNINTERESTING HEADER LINES. X## YOU CAN'T USE A PIPE AS PART OF THE PRINTER COMMAND BECAUSE xmh X## PUTS THE MESSAGE FILENAMES AT THE END OF THE PRINTER COMMAND LINE. X## X## THIS PROGRAM, xmhprint, TAKES MESSAGE FILENAMES(S) FROM THE X## COMMAND LINE, AS WELL AS (MAYBE) ONE OPTION. X## THE SHELL SCRIPT GETS THE MESSAGE FILENAMES FROM xmh, AND IT CAN X## PROCESS THEM ANY WAY YOU WANT IT TO. X## THE OPTIONS LET YOU CHANGE YOUR PRINT SETUP EASILY--INSTEAD OF X## STORING A COMPLICATED xmh*PrintCommand IN THE RESOURCE MANAGER, X## JUST CHANGE THE OPTION ON THE xmhprint COMMAND LINE IN .Xdefaults: X## xmh*PrintCommand: xmhprint -2 X## X## YOU CAN CUSTOMIZE THIS SCRIPT TO FIT YOUR NEEDS. X## ADD mhl(1) TO CLEAN UP THE MESSAGE HEADERS, USE OTHER PRINTERS, X## USE A POSTSCRIPT FILTER... GO WILD! X## X## STORE ANY lpr OPTIONS IN THE $PRINTER ENVIRONMENT VARIABLE. X X# TABSTOPS IN THIS CODE ARE SET AT 4 X Xerrsubj="xmh*PrintCommand print ERROR" # FOR MAILED ERRORS X X# APPEND ALL ERRORS TO FILE (NEEDS CLEANING PERIODICALLY) Xerrfile=$HOME/.xmh_printerrs Xexec >> $errfile 2>&1 X X# GET OPTION (xmh ALWAYS PUTS FILENAMES LAST): Xcase "$1" in X-1) # JUST pr; PUTS PATHNAME IN HEADER. NOTHING FANCY: X shift X pr "$@" | lpr X exit X ;; X-2) # SHOW SUBJECT IN pr HEADER OF EACH MESSAGE: X shift X for f X do X pr -h "`sed -n '/^[sS]ubject: / { X s///p X q X }' $f`" $f X done | lpr X exit X ;; X"") echo "No filenames or command line arguments!?!" | X mail -s "$errsubj" $USER X exit 1 X ;; X*) # DEFAULT: SEND ALL OPTIONS AND FILENAMES TO lpr: X lpr "$@" X exit X ;; Xesac X//E*O*F xmhprint// chmod u=rwx,g=rx,o=rx xmhprint echo Inspecting for damage in transit... temp=/tmp/shar$$; dtemp=/tmp/.shar$$ trap "rm -f $temp $dtemp; exit" 0 1 2 3 15 cat > $temp <<\!!! 65 597 3654 README 39 277 1521 append 103 441 2745 babyl2mh 78 375 2209 distprompter 163 812 4848 fixsubj 50 324 2100 fols 28 152 884 incs 48 232 1400 mhprofile 55 355 2091 recomp 76 432 2518 replf 37 211 1235 resend.fixmsg 111 722 4068 rmmer 113 569 3638 scandrafts 155 940 5697 showpr 117 655 3844 vmsmail2mh 61 326 1900 xmhprint 1299 7420 44352 total !!! wc README append babyl2mh distprompter fixsubj fols incs mhprofile recomp replf resend.fixmsg rmmer scandrafts showpr vmsmail2mh xmhprint | sed 's/^X//' | diff -b $temp - >$dtemp if [ -s $dtemp ] then echo "Ouch [diff of wc output]:" ; cat $dtemp else echo "No problems found." fi exit 0 exit 0 # Just in case... -- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM Sterling Software, IMD UUCP: uunet!sparky!kent Phone: (402) 291-8300 FAX: (402) 291-4362 Please send comp.sources.misc-related mail to kent@uunet.uu.net.