]> diplodocus.org Git - nmh/commitdiff
Added several historical source archives from the early days of MH.
authorDavid Levine <levinedl@acm.org>
Sun, 12 May 2019 15:03:14 +0000 (11:03 -0400)
committerDavid Levine <levinedl@acm.org>
Sun, 12 May 2019 15:53:48 +0000 (11:53 -0400)
SRI-NOSC, 2.9BSD, mh-jun-1982, and mh-nov-1983 predate those under
RCS/CVS source code control.

Thanks to M. Levinson, David Malone, Chad, Noel Chiappa, and Ralph
for advising of their discoveries of the various archive locations.

Removed docs/historical/mh-6.8.5/miscellany/mem/a.out because SPARC
executables shouldn't be archived.

643 files changed:
docs/historical/2.9BSD/Makefile [new file with mode: 0644]
docs/historical/2.9BSD/README [new file with mode: 0644]
docs/historical/2.9BSD/cmds/Makefile [new file with mode: 0644]
docs/historical/2.9BSD/cmds/aliascheck.c [new file with mode: 0644]
docs/historical/2.9BSD/cmds/annotate.c [new file with mode: 0644]
docs/historical/2.9BSD/cmds/comp.c [new file with mode: 0644]
docs/historical/2.9BSD/cmds/deliver.c [new file with mode: 0644]
docs/historical/2.9BSD/cmds/dist.c [new file with mode: 0644]
docs/historical/2.9BSD/cmds/emitl.c [new file with mode: 0644]
docs/historical/2.9BSD/cmds/folder.c [new file with mode: 0644]
docs/historical/2.9BSD/cmds/forw.c [new file with mode: 0644]
docs/historical/2.9BSD/cmds/grep.c [new file with mode: 0644]
docs/historical/2.9BSD/cmds/inc.c [new file with mode: 0644]
docs/historical/2.9BSD/cmds/install-mh.c [new file with mode: 0644]
docs/historical/2.9BSD/cmds/mail.c [new file with mode: 0644]
docs/historical/2.9BSD/cmds/mh.h [new file with mode: 0644]
docs/historical/2.9BSD/cmds/news.c [new file with mode: 0644]
docs/historical/2.9BSD/cmds/next.c [new file with mode: 0644]
docs/historical/2.9BSD/cmds/nexthdr.c [new file with mode: 0644]
docs/historical/2.9BSD/cmds/pick.c [new file with mode: 0644]
docs/historical/2.9BSD/cmds/prevhdr.c [new file with mode: 0644]
docs/historical/2.9BSD/cmds/prompter.c [new file with mode: 0644]
docs/historical/2.9BSD/cmds/refile.c [new file with mode: 0644]
docs/historical/2.9BSD/cmds/replsubs.c [new file with mode: 0644]
docs/historical/2.9BSD/cmds/reply.c [new file with mode: 0644]
docs/historical/2.9BSD/cmds/rescue.c [new file with mode: 0644]
docs/historical/2.9BSD/cmds/rmf.c [new file with mode: 0644]
docs/historical/2.9BSD/cmds/rmm.c [new file with mode: 0644]
docs/historical/2.9BSD/cmds/scan.c [new file with mode: 0644]
docs/historical/2.9BSD/cmds/scansub.c [new file with mode: 0644]
docs/historical/2.9BSD/cmds/send.c [new file with mode: 0644]
docs/historical/2.9BSD/cmds/show.c [new file with mode: 0644]
docs/historical/2.9BSD/cmds/strings.h [new file with mode: 0644]
docs/historical/2.9BSD/cmds/unixtomh.c [new file with mode: 0644]
docs/historical/2.9BSD/cmds/vars.c [new file with mode: 0644]
docs/historical/2.9BSD/doc/Alias.Design [new file with mode: 0644]
docs/historical/2.9BSD/doc/MH_VGRIND [new file with mode: 0755]
docs/historical/2.9BSD/doc/MHgenerate [new file with mode: 0644]
docs/historical/2.9BSD/doc/MHnotes [new file with mode: 0644]
docs/historical/2.9BSD/doc/Makefile [new file with mode: 0644]
docs/historical/2.9BSD/doc/mh.me [new file with mode: 0644]
docs/historical/2.9BSD/doc/titlepage [new file with mode: 0644]
docs/historical/2.9BSD/man/Makefile [new file with mode: 0644]
docs/historical/2.9BSD/man/comp.1 [new file with mode: 0644]
docs/historical/2.9BSD/man/dist.1 [new file with mode: 0644]
docs/historical/2.9BSD/man/file.1 [new file with mode: 0644]
docs/historical/2.9BSD/man/folder.1 [new file with mode: 0644]
docs/historical/2.9BSD/man/forw.1 [new file with mode: 0644]
docs/historical/2.9BSD/man/inc.1 [new file with mode: 0644]
docs/historical/2.9BSD/man/next.1 [new file with mode: 0644]
docs/historical/2.9BSD/man/pick.1 [new file with mode: 0644]
docs/historical/2.9BSD/man/prev.1 [new file with mode: 0644]
docs/historical/2.9BSD/man/print [new file with mode: 0644]
docs/historical/2.9BSD/man/prompter.1 [new file with mode: 0644]
docs/historical/2.9BSD/man/repl.1 [new file with mode: 0644]
docs/historical/2.9BSD/man/rmf.1 [new file with mode: 0644]
docs/historical/2.9BSD/man/rmm.1 [new file with mode: 0644]
docs/historical/2.9BSD/man/scan.1 [new file with mode: 0644]
docs/historical/2.9BSD/man/send.1 [new file with mode: 0644]
docs/historical/2.9BSD/man/show.1 [new file with mode: 0644]
docs/historical/2.9BSD/strings/Mailprog.c [new file with mode: 0644]
docs/historical/2.9BSD/strings/Makefile [new file with mode: 0644]
docs/historical/2.9BSD/strings/anoyes.c [new file with mode: 0644]
docs/historical/2.9BSD/strings/components.c [new file with mode: 0644]
docs/historical/2.9BSD/strings/current.c [new file with mode: 0644]
docs/historical/2.9BSD/strings/defalt.c [new file with mode: 0644]
docs/historical/2.9BSD/strings/distcomps.c [new file with mode: 0644]
docs/historical/2.9BSD/strings/draft.c [new file with mode: 0644]
docs/historical/2.9BSD/strings/fileproc.c [new file with mode: 0644]
docs/historical/2.9BSD/strings/foldprot.c [new file with mode: 0644]
docs/historical/2.9BSD/strings/hostname.c [new file with mode: 0644]
docs/historical/2.9BSD/strings/installproc.c [new file with mode: 0644]
docs/historical/2.9BSD/strings/listname.c [new file with mode: 0644]
docs/historical/2.9BSD/strings/localname.c [new file with mode: 0644]
docs/historical/2.9BSD/strings/lockdir.c [new file with mode: 0644]
docs/historical/2.9BSD/strings/lsproc.c [new file with mode: 0644]
docs/historical/2.9BSD/strings/mailboxes.c [new file with mode: 0644]
docs/historical/2.9BSD/strings/mailproc.c [new file with mode: 0644]
docs/historical/2.9BSD/strings/mh_defs.c [new file with mode: 0644]
docs/historical/2.9BSD/strings/mh_deliver.c [new file with mode: 0644]
docs/historical/2.9BSD/strings/mh_prof.c [new file with mode: 0644]
docs/historical/2.9BSD/strings/mhnews.c [new file with mode: 0644]
docs/historical/2.9BSD/strings/msgprot.c [new file with mode: 0644]
docs/historical/2.9BSD/strings/pfolder.c [new file with mode: 0644]
docs/historical/2.9BSD/strings/prproc.c [new file with mode: 0644]
docs/historical/2.9BSD/strings/scanproc.c [new file with mode: 0644]
docs/historical/2.9BSD/strings/sendproc.c [new file with mode: 0644]
docs/historical/2.9BSD/strings/showproc.c [new file with mode: 0644]
docs/historical/2.9BSD/strings/stdcomps.c [new file with mode: 0644]
docs/historical/2.9BSD/strings/stddcomps.c [new file with mode: 0644]
docs/historical/2.9BSD/strings/strings.h [new file with mode: 0644]
docs/historical/2.9BSD/strings/sysed.c [new file with mode: 0644]
docs/historical/2.9BSD/strings/unixtomh.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/16158symdef [new file with mode: 0644]
docs/historical/2.9BSD/subs/16158symref [new file with mode: 0644]
docs/historical/2.9BSD/subs/Makefile [new file with mode: 0644]
docs/historical/2.9BSD/subs/add.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/ambigsw.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/atooi.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/brkstring.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/cdate.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/cndfree.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/concat.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/copy.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/copyip.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/cputc.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/crpbrkstring.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/done.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/fdcompare.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/gans.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/getans.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/getcpy.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/help.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/invo_name.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/locv.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/m_convert.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/m_delete.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/m_edit.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/m_find.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/m_getdefs.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/m_getfld.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/m_getfolder.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/m_gmprot.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/m_gmsg.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/m_maildir.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/m_name.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/m_replace.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/m_send.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/m_setcur.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/m_update.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/makedir.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/makename.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/peekc.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/pr_array.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/printsw.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/putdate.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/r1bindex.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/showfile.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/smatch.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/ssequal.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/trimcpy.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/type.c [new file with mode: 0644]
docs/historical/2.9BSD/subs/uleq.c [new file with mode: 0644]
docs/historical/2.9BSD/support/components [new file with mode: 0644]
docs/historical/2.9BSD/support/distcomps [new file with mode: 0644]
docs/historical/2.9BSD/support/l.c [new file with mode: 0644]
docs/historical/2.9BSD/support/news-1char [new file with mode: 0755]
docs/historical/2.9BSD/support/news-mh_receiv [new file with mode: 0755]
docs/historical/README
docs/historical/SRI-NOSC/annotate.c [new file with mode: 0644]
docs/historical/SRI-NOSC/delete.c [new file with mode: 0644]
docs/historical/SRI-NOSC/delete.run [new file with mode: 0644]
docs/historical/SRI-NOSC/errlst [new file with mode: 0644]
docs/historical/SRI-NOSC/errors.h [new file with mode: 0644]
docs/historical/SRI-NOSC/file.c [new file with mode: 0644]
docs/historical/SRI-NOSC/file.run [new file with mode: 0644]
docs/historical/SRI-NOSC/forward.c [new file with mode: 0644]
docs/historical/SRI-NOSC/forward.run [new file with mode: 0644]
docs/historical/SRI-NOSC/install-defs.c [new file with mode: 0644]
docs/historical/SRI-NOSC/install-defs.r [new file with mode: 0644]
docs/historical/SRI-NOSC/iobuf.h [new file with mode: 0644]
docs/historical/SRI-NOSC/mh.h [new file with mode: 0644]
docs/historical/SRI-NOSC/nosc.txt [new file with mode: 0644]
docs/historical/SRI-NOSC/nullproc.c [new file with mode: 0644]
docs/historical/SRI-NOSC/open.c [new file with mode: 0644]
docs/historical/SRI-NOSC/open.run [new file with mode: 0644]
docs/historical/SRI-NOSC/pickup.c [new file with mode: 0644]
docs/historical/SRI-NOSC/pickup.run [new file with mode: 0644]
docs/historical/SRI-NOSC/pr.c [new file with mode: 0644]
docs/historical/SRI-NOSC/pr.run [new file with mode: 0644]
docs/historical/SRI-NOSC/prompter.c [new file with mode: 0644]
docs/historical/SRI-NOSC/prompter.run [new file with mode: 0644]
docs/historical/SRI-NOSC/purge.c [new file with mode: 0644]
docs/historical/SRI-NOSC/purge.run [new file with mode: 0644]
docs/historical/SRI-NOSC/putc.s [new file with mode: 0644]
docs/historical/SRI-NOSC/reply.c [new file with mode: 0644]
docs/historical/SRI-NOSC/reply.run [new file with mode: 0644]
docs/historical/SRI-NOSC/rmf.c [new file with mode: 0644]
docs/historical/SRI-NOSC/rmf.run [new file with mode: 0644]
docs/historical/SRI-NOSC/scan.c [new file with mode: 0644]
docs/historical/SRI-NOSC/scan.run [new file with mode: 0644]
docs/historical/SRI-NOSC/scansub.c [new file with mode: 0644]
docs/historical/SRI-NOSC/send-ec.run [new file with mode: 0755]
docs/historical/SRI-NOSC/send.c [new file with mode: 0644]
docs/historical/SRI-NOSC/send.run [new file with mode: 0755]
docs/historical/SRI-NOSC/sgtty.h [new file with mode: 0644]
docs/historical/SRI-NOSC/show.c [new file with mode: 0644]
docs/historical/SRI-NOSC/show.run [new file with mode: 0644]
docs/historical/SRI-NOSC/signals.h [new file with mode: 0644]
docs/historical/SRI-NOSC/stat.h [new file with mode: 0644]
docs/historical/SRI-NOSC/strings-ec.c [new file with mode: 0644]
docs/historical/SRI-NOSC/strings.c [new file with mode: 0644]
docs/historical/SRI-NOSC/strings.run [new file with mode: 0644]
docs/historical/SRI-NOSC/subs.dir/ambigsw.c [new file with mode: 0644]
docs/historical/SRI-NOSC/subs.dir/atoi.c [new file with mode: 0644]
docs/historical/SRI-NOSC/subs.dir/atooi.c [new file with mode: 0644]
docs/historical/SRI-NOSC/subs.dir/cfree.c [new file with mode: 0644]
docs/historical/SRI-NOSC/subs.dir/concat.c [new file with mode: 0644]
docs/historical/SRI-NOSC/subs.dir/copyip.c [new file with mode: 0644]
docs/historical/SRI-NOSC/subs.dir/cputc.c [new file with mode: 0644]
docs/historical/SRI-NOSC/subs.dir/gans.c [new file with mode: 0644]
docs/historical/SRI-NOSC/subs.dir/getchar.c [new file with mode: 0644]
docs/historical/SRI-NOSC/subs.dir/getcpy.c [new file with mode: 0644]
docs/historical/SRI-NOSC/subs.dir/help.c [new file with mode: 0644]
docs/historical/SRI-NOSC/subs.dir/invo_name.c [new file with mode: 0644]
docs/historical/SRI-NOSC/subs.dir/m_convert.c [new file with mode: 0644]
docs/historical/SRI-NOSC/subs.dir/m_convert.c.te [new file with mode: 0644]
docs/historical/SRI-NOSC/subs.dir/m_convert.c.tm [new file with mode: 0644]
docs/historical/SRI-NOSC/subs.dir/m_convert.old [new file with mode: 0644]
docs/historical/SRI-NOSC/subs.dir/m_delete.c [new file with mode: 0644]
docs/historical/SRI-NOSC/subs.dir/m_find.c [new file with mode: 0644]
docs/historical/SRI-NOSC/subs.dir/m_getdefs.c [new file with mode: 0644]
docs/historical/SRI-NOSC/subs.dir/m_getfld.c [new file with mode: 0644]
docs/historical/SRI-NOSC/subs.dir/m_getfolder.c [new file with mode: 0644]
docs/historical/SRI-NOSC/subs.dir/m_gmprot.c [new file with mode: 0644]
docs/historical/SRI-NOSC/subs.dir/m_gmsg.c [new file with mode: 0644]
docs/historical/SRI-NOSC/subs.dir/m_maildir.c [new file with mode: 0644]
docs/historical/SRI-NOSC/subs.dir/m_name.c [new file with mode: 0644]
docs/historical/SRI-NOSC/subs.dir/m_news.cc [new file with mode: 0644]
docs/historical/SRI-NOSC/subs.dir/m_replace.c [new file with mode: 0644]
docs/historical/SRI-NOSC/subs.dir/m_setcur.c [new file with mode: 0644]
docs/historical/SRI-NOSC/subs.dir/m_update.c [new file with mode: 0644]
docs/historical/SRI-NOSC/subs.dir/makedir.c [new file with mode: 0644]
docs/historical/SRI-NOSC/subs.dir/peekc.c [new file with mode: 0644]
docs/historical/SRI-NOSC/subs.dir/pr_array.c [new file with mode: 0644]
docs/historical/SRI-NOSC/subs.dir/printsw.c [new file with mode: 0644]
docs/historical/SRI-NOSC/subs.dir/puts.c [new file with mode: 0644]
docs/historical/SRI-NOSC/subs.dir/showfile.c [new file with mode: 0644]
docs/historical/SRI-NOSC/subs.dir/smatch.c [new file with mode: 0644]
docs/historical/SRI-NOSC/subs.dir/ssequal.c [new file with mode: 0644]
docs/historical/SRI-NOSC/subs.dir/subs.run [new file with mode: 0755]
docs/historical/SRI-NOSC/subs.dir/trimcpy.c [new file with mode: 0644]
docs/historical/SRI-NOSC/subs.dir/uleq.c [new file with mode: 0644]
docs/historical/SRI-NOSC/undelete.c [new file with mode: 0644]
docs/historical/SRI-NOSC/undelete.run [new file with mode: 0644]
docs/historical/SRI-NOSC/wait.s [new file with mode: 0644]
docs/historical/SRI-NOSC/write.c [new file with mode: 0644]
docs/historical/SRI-NOSC/write.run [new file with mode: 0644]
docs/historical/mh-6.8.5/miscellany/mem/a.out [deleted file]
docs/historical/mh-jun-1982/4bsd.changes [new file with mode: 0644]
docs/historical/mh-jun-1982/ANOMALIES [new file with mode: 0644]
docs/historical/mh-jun-1982/Alias.Design [new file with mode: 0644]
docs/historical/mh-jun-1982/Bugs [new file with mode: 0644]
docs/historical/mh-jun-1982/DOC/README [new file with mode: 0644]
docs/historical/mh-jun-1982/DOC/brief [new file with mode: 0644]
docs/historical/mh-jun-1982/DOC/mh.me [new file with mode: 0644]
docs/historical/mh-jun-1982/DOC/mh.me.5 [new file with mode: 0644]
docs/historical/mh-jun-1982/DOC/mh1.nr [new file with mode: 0644]
docs/historical/mh-jun-1982/DOC/mhcov.t [new file with mode: 0644]
docs/historical/mh-jun-1982/DOC/rand.t [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/anno.bld [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/anno.cc [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/getenv.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/imp.h [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/lasthdr.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libg/getpw.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libg/getwho.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libg/gtfstn.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libg/gtldat.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libg/gtlogn.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libg/gtlstn.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libg/gtluid.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libg/gtmnem.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libg/gtpath.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libg/gtpriv.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libg/gtpswd.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libg/gtruid.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libg/gttype.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libg/gtubuf.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libg/gtunum.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libg/ttynam.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libg/ttynum.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libh/any.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libh/brkstg.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libh/cat.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libh/cdate.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libh/copy.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libh/date.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libh/echo.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libh/equal.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libh/error.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libh/errtyp.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libh/excsrh.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libh/execsh.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libh/fmt.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libh/fopen2.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libh/fseek.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libh/gdate.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libh/getcopy.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libh/getl.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libh/getline.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libh/glbmtc.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libh/gwd.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libh/inputf.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libh/length.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libh/makename.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libh/prndec.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libh/subshell.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libh/swmtch.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libh/t.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/libh/type.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/mailsys.h [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/resp.bld [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/resp.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/sndmsg.bld [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/sndmsg.c [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/strings.h [new file with mode: 0644]
docs/historical/mh-jun-1982/Extras/whoami.h [new file with mode: 0644]
docs/historical/mh-jun-1982/Log [new file with mode: 0644]
docs/historical/mh-jun-1982/MHL.Design [new file with mode: 0644]
docs/historical/mh-jun-1982/MHgenerate [new file with mode: 0644]
docs/historical/mh-jun-1982/MHnotes [new file with mode: 0644]
docs/historical/mh-jun-1982/Makefile [new file with mode: 0644]
docs/historical/mh-jun-1982/README [new file with mode: 0644]
docs/historical/mh-jun-1982/Wishlist [new file with mode: 0644]
docs/historical/mh-jun-1982/adrparse.h [new file with mode: 0644]
docs/historical/mh-jun-1982/dytest/Makefile [new file with mode: 0644]
docs/historical/mh-jun-1982/dytest/README [new file with mode: 0644]
docs/historical/mh-jun-1982/dytest/mhl.c [new file with mode: 0644]
docs/historical/mh-jun-1982/dytest/show.c [new file with mode: 0644]
docs/historical/mh-jun-1982/folder.h [new file with mode: 0644]
docs/historical/mh-jun-1982/man/Makefile [new file with mode: 0644]
docs/historical/mh-jun-1982/man/ali.1 [new file with mode: 0644]
docs/historical/mh-jun-1982/man/comp.1 [new file with mode: 0644]
docs/historical/mh-jun-1982/man/conflict.8 [new file with mode: 0644]
docs/historical/mh-jun-1982/man/deliver.8 [new file with mode: 0644]
docs/historical/mh-jun-1982/man/dist.1 [new file with mode: 0644]
docs/historical/mh-jun-1982/man/file.1 [new file with mode: 0644]
docs/historical/mh-jun-1982/man/folder.1 [new file with mode: 0644]
docs/historical/mh-jun-1982/man/folders.1 [new file with mode: 0644]
docs/historical/mh-jun-1982/man/forw.1 [new file with mode: 0644]
docs/historical/mh-jun-1982/man/inc.1 [new file with mode: 0644]
docs/historical/mh-jun-1982/man/mail.1 [new file with mode: 0644]
docs/historical/mh-jun-1982/man/mailer.8 [new file with mode: 0644]
docs/historical/mh-jun-1982/man/mh-alias.5 [new file with mode: 0644]
docs/historical/mh-jun-1982/man/mh-mail.5 [new file with mode: 0644]
docs/historical/mh-jun-1982/man/mh-profile.5 [new file with mode: 0644]
docs/historical/mh-jun-1982/man/mh.1 [new file with mode: 0644]
docs/historical/mh-jun-1982/man/mhl.1 [new file with mode: 0644]
docs/historical/mh-jun-1982/man/mhpath.1 [new file with mode: 0644]
docs/historical/mh-jun-1982/man/netmail.5 [new file with mode: 0644]
docs/historical/mh-jun-1982/man/news.1 [new file with mode: 0644]
docs/historical/mh-jun-1982/man/next.1 [new file with mode: 0644]
docs/historical/mh-jun-1982/man/pick.1 [new file with mode: 0644]
docs/historical/mh-jun-1982/man/prev.1 [new file with mode: 0644]
docs/historical/mh-jun-1982/man/prompter.1 [new file with mode: 0644]
docs/historical/mh-jun-1982/man/repl.1 [new file with mode: 0644]
docs/historical/mh-jun-1982/man/rmail.1 [new file with mode: 0644]
docs/historical/mh-jun-1982/man/rmf.1 [new file with mode: 0644]
docs/historical/mh-jun-1982/man/rmm.1 [new file with mode: 0644]
docs/historical/mh-jun-1982/man/scan.1 [new file with mode: 0644]
docs/historical/mh-jun-1982/man/send.1 [new file with mode: 0644]
docs/historical/mh-jun-1982/man/show.1 [new file with mode: 0644]
docs/historical/mh-jun-1982/mh.diff [new file with mode: 0644]
docs/historical/mh-jun-1982/mh.h [new file with mode: 0644]
docs/historical/mh-jun-1982/misc/depend.sh [new file with mode: 0755]
docs/historical/mh-jun-1982/progs/Makefile [new file with mode: 0644]
docs/historical/mh-jun-1982/progs/Makefile.bak [new file with mode: 0644]
docs/historical/mh-jun-1982/progs/UUCP.MEMO [new file with mode: 0644]
docs/historical/mh-jun-1982/progs/adrformat.c [new file with mode: 0644]
docs/historical/mh-jun-1982/progs/adrparse.c [new file with mode: 0644]
docs/historical/mh-jun-1982/progs/ali.c [new file with mode: 0644]
docs/historical/mh-jun-1982/progs/annotate.c [new file with mode: 0644]
docs/historical/mh-jun-1982/progs/comp.c [new file with mode: 0644]
docs/historical/mh-jun-1982/progs/conflict.c [new file with mode: 0644]
docs/historical/mh-jun-1982/progs/deliver.c [new file with mode: 0644]
docs/historical/mh-jun-1982/progs/dist.c [new file with mode: 0644]
docs/historical/mh-jun-1982/progs/file.c [new file with mode: 0644]
docs/historical/mh-jun-1982/progs/folder.c [new file with mode: 0644]
docs/historical/mh-jun-1982/progs/forw.c [new file with mode: 0644]
docs/historical/mh-jun-1982/progs/grep.c [new file with mode: 0644]
docs/historical/mh-jun-1982/progs/inc.c [new file with mode: 0644]
docs/historical/mh-jun-1982/progs/install-mh.c [new file with mode: 0644]
docs/historical/mh-jun-1982/progs/mail.c [new file with mode: 0644]
docs/historical/mh-jun-1982/progs/mhl.c [new file with mode: 0644]
docs/historical/mh-jun-1982/progs/mhpath.c [new file with mode: 0644]
docs/historical/mh-jun-1982/progs/news.c [new file with mode: 0644]
docs/historical/mh-jun-1982/progs/next.c [new file with mode: 0644]
docs/historical/mh-jun-1982/progs/nexthdr.c [new file with mode: 0644]
docs/historical/mh-jun-1982/progs/pick.c [new file with mode: 0644]
docs/historical/mh-jun-1982/progs/prevhdr.c [new file with mode: 0644]
docs/historical/mh-jun-1982/progs/prompter.c [new file with mode: 0644]
docs/historical/mh-jun-1982/progs/ptt.c [new file with mode: 0644]
docs/historical/mh-jun-1982/progs/repl.c [new file with mode: 0644]
docs/historical/mh-jun-1982/progs/replsubs.c [new file with mode: 0644]
docs/historical/mh-jun-1982/progs/rmail.c [new file with mode: 0644]
docs/historical/mh-jun-1982/progs/rmail.c.nodate [new file with mode: 0644]
docs/historical/mh-jun-1982/progs/rmf.c [new file with mode: 0644]
docs/historical/mh-jun-1982/progs/rmm.c [new file with mode: 0644]
docs/historical/mh-jun-1982/progs/scan.c [new file with mode: 0644]
docs/historical/mh-jun-1982/progs/scansub.c [new file with mode: 0644]
docs/historical/mh-jun-1982/progs/scansub.h [new file with mode: 0644]
docs/historical/mh-jun-1982/progs/send.c [new file with mode: 0644]
docs/historical/mh-jun-1982/progs/show.c [new file with mode: 0644]
docs/historical/mh-jun-1982/strings/Makefile [new file with mode: 0644]
docs/historical/mh-jun-1982/strings/anoyes.c [new file with mode: 0644]
docs/historical/mh-jun-1982/strings/components.c [new file with mode: 0644]
docs/historical/mh-jun-1982/strings/current.c [new file with mode: 0644]
docs/historical/mh-jun-1982/strings/defalt.c [new file with mode: 0644]
docs/historical/mh-jun-1982/strings/distcomps.c [new file with mode: 0644]
docs/historical/mh-jun-1982/strings/draft.c [new file with mode: 0644]
docs/historical/mh-jun-1982/strings/fileproc.c [new file with mode: 0644]
docs/historical/mh-jun-1982/strings/foldprot.c [new file with mode: 0644]
docs/historical/mh-jun-1982/strings/installproc.c [new file with mode: 0644]
docs/historical/mh-jun-1982/strings/listname.c [new file with mode: 0644]
docs/historical/mh-jun-1982/strings/lockdir.c [new file with mode: 0644]
docs/historical/mh-jun-1982/strings/lproc.c [new file with mode: 0644]
docs/historical/mh-jun-1982/strings/lsproc.c [new file with mode: 0644]
docs/historical/mh-jun-1982/strings/mailboxes.c [new file with mode: 0644]
docs/historical/mh-jun-1982/strings/mailproc.c [new file with mode: 0644]
docs/historical/mh-jun-1982/strings/mh_deliver.c [new file with mode: 0644]
docs/historical/mh-jun-1982/strings/mh_prof.c [new file with mode: 0644]
docs/historical/mh-jun-1982/strings/mhlformat.c [new file with mode: 0644]
docs/historical/mh-jun-1982/strings/mhlstdfmt.c [new file with mode: 0644]
docs/historical/mh-jun-1982/strings/mhnews.c [new file with mode: 0644]
docs/historical/mh-jun-1982/strings/msgprot.c [new file with mode: 0644]
docs/historical/mh-jun-1982/strings/pfolder.c [new file with mode: 0644]
docs/historical/mh-jun-1982/strings/prproc.c [new file with mode: 0644]
docs/historical/mh-jun-1982/strings/rhosts.c [new file with mode: 0644]
docs/historical/mh-jun-1982/strings/scanproc.c [new file with mode: 0644]
docs/historical/mh-jun-1982/strings/sendproc.c [new file with mode: 0644]
docs/historical/mh-jun-1982/strings/showproc.c [new file with mode: 0644]
docs/historical/mh-jun-1982/strings/stdcomps.c [new file with mode: 0644]
docs/historical/mh-jun-1982/strings/stddcomps.c [new file with mode: 0644]
docs/historical/mh-jun-1982/strings/sysed.c [new file with mode: 0644]
docs/historical/mh-jun-1982/strings/sysname.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/Makefile [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/Makefile.bak [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/add.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/ambigsw.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/atooi.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/brkstring.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/cdate.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/cndfree.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/concat.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/copy.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/copyip.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/cputc.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/depend.sh [new file with mode: 0755]
docs/historical/mh-jun-1982/subs/done.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/fdcompare.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/gans.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/getans.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/getcpy.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/help.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/invo_name.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/locv.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/m_convert.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/m_delete.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/m_edit.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/m_file.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/m_find.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/m_getcur.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/m_getdefs.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/m_getfld.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/m_getfolder.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/m_gmprot.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/m_gmsg.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/m_maildir.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/m_name.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/m_news.cc [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/m_replace.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/m_send.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/m_setcur.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/m_update.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/makedir.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/makename.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/mu_atoi.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/path.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/peekc.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/pr_array.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/printsw.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/putenv.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/pwd.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/r1bindex.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/showfile.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/smatch.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/ssequal.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/subs-lc [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/trimcpy.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/type.c [new file with mode: 0644]
docs/historical/mh-jun-1982/subs/uleq.c [new file with mode: 0644]
docs/historical/mh-jun-1982/support/MailAliases [new file with mode: 0644]
docs/historical/mh-jun-1982/support/Makefile [new file with mode: 0644]
docs/historical/mh-jun-1982/support/aliascheck.c [new file with mode: 0644]
docs/historical/mh-jun-1982/support/components [new file with mode: 0644]
docs/historical/mh-jun-1982/support/distcomps [new file with mode: 0644]
docs/historical/mh-jun-1982/support/l.c [new file with mode: 0644]
docs/historical/mh-jun-1982/support/mailsys.h [new file with mode: 0644]
docs/historical/mh-jun-1982/support/mhl.format [new file with mode: 0644]
docs/historical/mh-jun-1982/support/news/1char [new file with mode: 0644]
docs/historical/mh-jun-1982/support/news/Makefile [new file with mode: 0644]
docs/historical/mh-jun-1982/support/news/mh_profile [new file with mode: 0644]
docs/historical/mh-jun-1982/support/news/mh_receive [new file with mode: 0755]
docs/historical/mh-jun-1982/support/putenv.c [new file with mode: 0644]
docs/historical/mh-jun-1982/support/strings.h [new file with mode: 0644]
docs/historical/mh-nov-1983/Makefile [new file with mode: 0644]
docs/historical/mh-nov-1983/README [new file with mode: 0644]
docs/historical/mh-nov-1983/cmds/Makefile [new file with mode: 0644]
docs/historical/mh-nov-1983/cmds/aliascheck.c [new file with mode: 0644]
docs/historical/mh-nov-1983/cmds/annotate.c [new file with mode: 0644]
docs/historical/mh-nov-1983/cmds/comp.c [new file with mode: 0644]
docs/historical/mh-nov-1983/cmds/deliver.c [new file with mode: 0644]
docs/historical/mh-nov-1983/cmds/dist.c [new file with mode: 0644]
docs/historical/mh-nov-1983/cmds/emitl.c [new file with mode: 0644]
docs/historical/mh-nov-1983/cmds/folder.c [new file with mode: 0644]
docs/historical/mh-nov-1983/cmds/forw.c [new file with mode: 0644]
docs/historical/mh-nov-1983/cmds/grep.c [new file with mode: 0644]
docs/historical/mh-nov-1983/cmds/inc.c [new file with mode: 0644]
docs/historical/mh-nov-1983/cmds/install-mh.c [new file with mode: 0644]
docs/historical/mh-nov-1983/cmds/mail.c [new file with mode: 0644]
docs/historical/mh-nov-1983/cmds/mh.h [new file with mode: 0644]
docs/historical/mh-nov-1983/cmds/news.c [new file with mode: 0644]
docs/historical/mh-nov-1983/cmds/next.c [new file with mode: 0644]
docs/historical/mh-nov-1983/cmds/nexthdr.c [new file with mode: 0644]
docs/historical/mh-nov-1983/cmds/pick.c [new file with mode: 0644]
docs/historical/mh-nov-1983/cmds/prevhdr.c [new file with mode: 0644]
docs/historical/mh-nov-1983/cmds/prompter.c [new file with mode: 0644]
docs/historical/mh-nov-1983/cmds/refile.c [new file with mode: 0644]
docs/historical/mh-nov-1983/cmds/replsubs.c [new file with mode: 0644]
docs/historical/mh-nov-1983/cmds/reply.c [new file with mode: 0644]
docs/historical/mh-nov-1983/cmds/rescue.c [new file with mode: 0644]
docs/historical/mh-nov-1983/cmds/rmf.c [new file with mode: 0644]
docs/historical/mh-nov-1983/cmds/rmm.c [new file with mode: 0644]
docs/historical/mh-nov-1983/cmds/scan.c [new file with mode: 0644]
docs/historical/mh-nov-1983/cmds/scansub.c [new file with mode: 0644]
docs/historical/mh-nov-1983/cmds/send.c [new file with mode: 0644]
docs/historical/mh-nov-1983/cmds/show.c [new file with mode: 0644]
docs/historical/mh-nov-1983/cmds/strings.h [new file with mode: 0644]
docs/historical/mh-nov-1983/cmds/unixtomh.c [new file with mode: 0644]
docs/historical/mh-nov-1983/cmds/vars.c [new file with mode: 0644]
docs/historical/mh-nov-1983/doc/Alias.Design [new file with mode: 0644]
docs/historical/mh-nov-1983/doc/MH_VGRIND [new file with mode: 0644]
docs/historical/mh-nov-1983/doc/MHgenerate [new file with mode: 0644]
docs/historical/mh-nov-1983/doc/MHnotes [new file with mode: 0644]
docs/historical/mh-nov-1983/doc/Makefile [new file with mode: 0644]
docs/historical/mh-nov-1983/doc/mh.me [new file with mode: 0644]
docs/historical/mh-nov-1983/doc/titlepage [new file with mode: 0644]
docs/historical/mh-nov-1983/man/Makefile [new file with mode: 0644]
docs/historical/mh-nov-1983/man/comp.1 [new file with mode: 0644]
docs/historical/mh-nov-1983/man/dist.1 [new file with mode: 0644]
docs/historical/mh-nov-1983/man/file.1 [new file with mode: 0644]
docs/historical/mh-nov-1983/man/folder.1 [new file with mode: 0644]
docs/historical/mh-nov-1983/man/forw.1 [new file with mode: 0644]
docs/historical/mh-nov-1983/man/inc.1 [new file with mode: 0644]
docs/historical/mh-nov-1983/man/next.1 [new file with mode: 0644]
docs/historical/mh-nov-1983/man/pick.1 [new file with mode: 0644]
docs/historical/mh-nov-1983/man/prev.1 [new file with mode: 0644]
docs/historical/mh-nov-1983/man/print [new file with mode: 0644]
docs/historical/mh-nov-1983/man/prompter.1 [new file with mode: 0644]
docs/historical/mh-nov-1983/man/repl.1 [new file with mode: 0644]
docs/historical/mh-nov-1983/man/rmf.1 [new file with mode: 0644]
docs/historical/mh-nov-1983/man/rmm.1 [new file with mode: 0644]
docs/historical/mh-nov-1983/man/scan.1 [new file with mode: 0644]
docs/historical/mh-nov-1983/man/send.1 [new file with mode: 0644]
docs/historical/mh-nov-1983/man/show.1 [new file with mode: 0644]
docs/historical/mh-nov-1983/strings/Mailprog.c [new file with mode: 0644]
docs/historical/mh-nov-1983/strings/Makefile [new file with mode: 0644]
docs/historical/mh-nov-1983/strings/anoyes.c [new file with mode: 0644]
docs/historical/mh-nov-1983/strings/components.c [new file with mode: 0644]
docs/historical/mh-nov-1983/strings/current.c [new file with mode: 0644]
docs/historical/mh-nov-1983/strings/defalt.c [new file with mode: 0644]
docs/historical/mh-nov-1983/strings/distcomps.c [new file with mode: 0644]
docs/historical/mh-nov-1983/strings/draft.c [new file with mode: 0644]
docs/historical/mh-nov-1983/strings/fileproc.c [new file with mode: 0644]
docs/historical/mh-nov-1983/strings/foldprot.c [new file with mode: 0644]
docs/historical/mh-nov-1983/strings/hostname.c [new file with mode: 0644]
docs/historical/mh-nov-1983/strings/installproc.c [new file with mode: 0644]
docs/historical/mh-nov-1983/strings/listname.c [new file with mode: 0644]
docs/historical/mh-nov-1983/strings/localname.c [new file with mode: 0644]
docs/historical/mh-nov-1983/strings/lockdir.c [new file with mode: 0644]
docs/historical/mh-nov-1983/strings/lsproc.c [new file with mode: 0644]
docs/historical/mh-nov-1983/strings/mailboxes.c [new file with mode: 0644]
docs/historical/mh-nov-1983/strings/mailproc.c [new file with mode: 0644]
docs/historical/mh-nov-1983/strings/mh_defs.c [new file with mode: 0644]
docs/historical/mh-nov-1983/strings/mh_deliver.c [new file with mode: 0644]
docs/historical/mh-nov-1983/strings/mh_prof.c [new file with mode: 0644]
docs/historical/mh-nov-1983/strings/mhnews.c [new file with mode: 0644]
docs/historical/mh-nov-1983/strings/msgprot.c [new file with mode: 0644]
docs/historical/mh-nov-1983/strings/pfolder.c [new file with mode: 0644]
docs/historical/mh-nov-1983/strings/prproc.c [new file with mode: 0644]
docs/historical/mh-nov-1983/strings/scanproc.c [new file with mode: 0644]
docs/historical/mh-nov-1983/strings/sendproc.c [new file with mode: 0644]
docs/historical/mh-nov-1983/strings/showproc.c [new file with mode: 0644]
docs/historical/mh-nov-1983/strings/stdcomps.c [new file with mode: 0644]
docs/historical/mh-nov-1983/strings/stddcomps.c [new file with mode: 0644]
docs/historical/mh-nov-1983/strings/strings.h [new file with mode: 0644]
docs/historical/mh-nov-1983/strings/sysed.c [new file with mode: 0644]
docs/historical/mh-nov-1983/strings/unixtomh.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/Makefile [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/add.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/ambigsw.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/atooi.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/brkstring.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/cdate.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/cndfree.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/concat.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/copy.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/copyip.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/cputc.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/crpbrkstring.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/done.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/fdcompare.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/gans.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/getans.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/getcpy.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/help.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/invo_name.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/locv.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/m_convert.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/m_delete.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/m_edit.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/m_find.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/m_getdefs.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/m_getfld.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/m_getfolder.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/m_gmprot.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/m_gmsg.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/m_maildir.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/m_name.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/m_replace.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/m_send.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/m_setcur.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/m_update.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/makedir.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/makename.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/mh.h [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/peekc.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/pr_array.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/printsw.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/putdate.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/r1bindex.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/showfile.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/smatch.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/ssequal.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/trimcpy.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/type.c [new file with mode: 0644]
docs/historical/mh-nov-1983/subs/uleq.c [new file with mode: 0644]
docs/historical/mh-nov-1983/support/components [new file with mode: 0644]
docs/historical/mh-nov-1983/support/distcomps [new file with mode: 0644]
docs/historical/mh-nov-1983/support/l.c [new file with mode: 0644]
docs/historical/mh-nov-1983/support/news-1char [new file with mode: 0644]
docs/historical/mh-nov-1983/support/news-mh_receiv [new file with mode: 0644]

diff --git a/docs/historical/2.9BSD/Makefile b/docs/historical/2.9BSD/Makefile
new file mode 100644 (file)
index 0000000..4503c12
--- /dev/null
@@ -0,0 +1,13 @@
+#      %M%     %I%     %E%
+#
+DESTDIR=
+
+all:   
+       cd cmds; make ${MFLAGS}
+
+cp:    all
+       cd cmds; make DESTDIR=${DESTDIR} cp
+       cd man; make DESTDIR=${DESTDIR} cp
+
+clean:
+       cd cmds; make ${MFLAGS} clean
diff --git a/docs/historical/2.9BSD/README b/docs/historical/2.9BSD/README
new file mode 100644 (file)
index 0000000..9d034ee
--- /dev/null
@@ -0,0 +1,29 @@
+Title:         MH
+
+Authors:       Bruce Borden
+               Stockton Gaines
+               Norman Shapiro
+
+Help from:     Phyllis Kantar
+               Robert Anderson
+               David Crocker
+
+
+Description:
+
+The user command interface to MH is the UNIX ``shell'' (the standard
+UNIX command interpreter).  Each separable component of message handling,
+such as message composition or message display, is a separate command.
+Each program is driven from and updates a private user environment,
+which is stored as a file between program invocations.  This private
+environment also contains information to ``custom tailor'' MH to the
+individuals's tastes.  MH stores each message as a separate file under
+UNIX, and it utilizes the tree-structured UNIX file system to organize
+groups of files within separate directories or ``folders.''  All of
+the UNIX facilities for dealing with files and directories, such as
+renaming, copying, deleting, cataloging, off-line printing, etc., are
+applicable to messages and directories of messages (folders).  Thus,
+important capabilities needed in a message system are available in MH
+without the need (often seen in other message systems) for code that
+duplicates the facilities of the supporting operating system.  It also
+allows users familiar with the shell to use MH with minimal effort.
diff --git a/docs/historical/2.9BSD/cmds/Makefile b/docs/historical/2.9BSD/cmds/Makefile
new file mode 100644 (file)
index 0000000..eaf8203
--- /dev/null
@@ -0,0 +1,221 @@
+#      @(#)Makefile    4.9     (Berkeley)      83/07/07
+#
+# define UCB to get #files instead of ,files
+#
+LIBS=  subs.a strings.a /usr/src/ucb/libndir/libndir.a
+CFLAGS= -O -DUNIXCOMP -DUCB -I. -I/usr/src/ucb/libndir
+BINDIR= /usr/new/mh
+LIBDIR=        /usr/new/lib
+MHDIR=  ${LIBDIR}/mh
+SUBS = ../subs
+STRINGS = ../strings
+PROGS= comp deliver folder forw inc install-mh \
+       next news pick prev prompter refile repl rescue rmf rmm scan \
+       send show unixtomh
+DESTDIR=
+
+all:   ${PROGS}
+
+subs.a: mh.h
+       rm -f ${SUBS}/subs.a subs.a
+       cd ${SUBS}; make
+       ranlib ${SUBS}/subs.a
+       ln ${SUBS}/subs.a subs.a
+
+strings.a:
+       rm -f ${STRINGS}/strings.a strings.a
+       cd ${STRINGS}; make
+       ranlib ${STRINGS}/strings.a
+       ln ${STRINGS}/strings.a strings.a
+
+comp:   mh.h comp.o ${LIBS}
+       ${CC} -o comp comp.o ${LIBS}
+
+deliver:mh.h deliver.o ${LIBS}
+       ${CC} -o deliver deliver.o ${LIBS}
+
+refile:   mh.h refile.o ${LIBS}
+       ${CC} -o refile refile.o ${LIBS}
+
+folder: mh.h folder.o ${LIBS}
+       ${CC} -o folder folder.o ${LIBS}
+
+forw:   mh.h forw.o annotate.o ${LIBS}
+       ${CC} -o forw forw.o annotate.o ${LIBS}
+
+inc:    mh.h inc.o scansub.o ${LIBS}
+       ${CC} -o inc inc.o scansub.o ${LIBS}
+
+install-mh: mh.h install-mh.o ${LIBS}
+       ${CC} -o install-mh install-mh.o ${LIBS}
+
+news:   mh.h news.o ${LIBS}
+       ${CC} -o news news.o ${LIBS}
+
+next:   mh.h nexthdr.o next.o ${LIBS}
+       ${CC} -o next nexthdr.o next.o ${LIBS}
+
+pick:   mh.h pick.o grep.o ${LIBS}
+       ${CC} -o pick pick.o grep.o ${LIBS}
+
+prev:   mh.h prevhdr.o next.o ${LIBS}
+       ${CC} -o prev prevhdr.o next.o ${LIBS}
+
+prompter: mh.h prompter.o ${LIBS}
+       ${CC} -o prompter prompter.o ${LIBS}
+
+repl:   mh.h reply.o replsubs.o annotate.o ${LIBS}
+       ${CC} -o repl reply.o replsubs.o annotate.o ${LIBS}
+
+rescue:        rescue.o emitl.o
+       ${CC} -o rescue rescue.o
+
+rmf:    mh.h rmf.o ${LIBS}
+       ${CC} -o rmf rmf.o ${LIBS}
+
+rmm:    mh.h rmm.o ${LIBS}
+       ${CC} -o rmm rmm.o ${LIBS}
+
+scan:   mh.h scan.o scansub.o ${LIBS}
+       ${CC} -o scan scan.o scansub.o ${LIBS}
+
+send:   mh.h send.o ${LIBS}
+       ${CC} -o send send.o ${LIBS}
+
+show:   mh.h show.o ${LIBS}
+       ${CC} -o show show.o ${LIBS}
+
+unixtomh: unixtomh.o
+       ${CC} -o unixtomh unixtomh.o subs.a
+
+onceonly:
+       -@if [ ! -f ${DESTDIR}/usr/bin/filetype -a \
+              ! -f ${DESTDIR}/bin/filetype -a -f ${DESTDIR}/bin/file ] ; then \
+               mv ${DESTDIR}/bin/file ${DESTDIR}/bin/filetype; \
+               echo "${DESTDIR}/bin/file => ${DESTDIR}/bin/filetype" ; \
+        else true ; \
+        fi
+       -@if [ ! -f ${DESTDIR}/bin/filetype -a \
+              ! -f ${DESTDIR}/usr/bin/filetype -a \
+                -f ${DESTDIR}/usr/bin/file ] ; then \
+               mv ${DESTDIR}/usr/bin/file ${DESTDIR}/usr/bin/filetype; \
+               echo "${DESTDIR}/usr/bin/file => ${DESTDIR}/usr/bin/filetype"; \
+        else true ; \
+        fi
+       -@if [ ! -f ${DESTDIR}/bin/bellmail -a -f ${DESTDIR}/bin/mail ] ; then \
+               mv ${DESTDIR}/bin/mail ${DESTDIR}/bin/bellmail; \
+               echo "${DESTDIR}/bin/mail => ${DESTDIR}/bin/bellmail" ;\
+        else true ; \
+        fi
+       -@if [ -f ${DESTDIR}/${BINDIR}/comp ] ; then \
+               echo "Collision on ${DESTDIR}/${BINDIR}/comp" ; \
+        else true ; \
+        fi
+#       -@if [ -f ${DESTDIR}/${BINDIR}/dist ] ; then \
+               echo "Collision on ${DESTDIR}/${BINDIR}/dist" ; \
+        else true ; \
+        fi
+#       -@if [ -f ${DESTDIR}/${BINDIR}/file ] ; then \
+               echo "Collision on ${DESTDIR}/${BINDIR}/file" ; \
+        else true ; \
+        fi
+       -@if [ -f ${DESTDIR}/${BINDIR}/folder ] ; then \
+               echo "Collision on ${DESTDIR}/${BINDIR}/folder" ; \
+        else true ; \
+        fi
+       -@if [ -f ${DESTDIR}/${BINDIR}/forw ] ; then \
+               echo "Collision on ${DESTDIR}/${BINDIR}/forw" ; \
+        else true ; \
+        fi
+       -@if [ -f ${DESTDIR}/${BINDIR}/inc  ] ; then \
+               echo "Collision on ${DESTDIR}/${BINDIR}/inc"  ; \
+        else true ; \
+        fi
+#       -@if [ -f ${DESTDIR}/${BINDIR}/mail ] ; then \
+               echo "Collision on ${DESTDIR}/${BINDIR}/mail" ; \
+        else true ; \
+        fi
+       -@if [ -f ${DESTDIR}/${BINDIR}/news ] ; then \
+               echo "Collision on ${DESTDIR}/${BINDIR}/news" ; \
+        else true ; \
+        fi
+       -@if [ -f ${DESTDIR}/${BINDIR}/next ] ; then \
+               echo "Collision on ${DESTDIR}/${BINDIR}/next" ; \
+        else true ; \
+        fi
+       -@if [ -f ${DESTDIR}/${BINDIR}/pick ] ; then \
+               echo "Collision on ${DESTDIR}/${BINDIR}/pick" ; \
+        else true ; \
+        fi
+       -@if [ -f ${DESTDIR}/${BINDIR}/prev ] ; then \
+               echo "Collision on ${DESTDIR}/${BINDIR}/prev" ; \
+        else true ; \
+        fi
+       -@if [ -f ${DESTDIR}/${BINDIR}/prompter ] ; then \
+               echo "Collision on ${DESTDIR}/${BINDIR}/prompter" ; \
+        else true ; \
+        fi
+       -@if [ -f ${DESTDIR}/${BINDIR}/repl ] ; then \
+               echo "Collision on ${DESTDIR}/${BINDIR}/repl" ; \
+        else true ; \
+        fi
+       -@if [ -f ${DESTDIR}/${BINDIR}/rmf  ] ; then \
+               echo "Collision on ${DESTDIR}/${BINDIR}/rmf"  ; \
+        else true ; \
+        fi
+       -@if [ -f ${DESTDIR}/${BINDIR}/rmm  ] ; then \
+               echo "Collision on ${DESTDIR}/${BINDIR}/rmm"  ; \
+         else true ; \
+         fi
+       -@if [ -f ${DESTDIR}/${BINDIR}/scan ] ; then \
+               echo "Collision on ${DESTDIR}/${BINDIR}/scan" ; \
+        else true ; \
+        fi
+       -@if [ -f ${DESTDIR}/${BINDIR}/send ] ; then \
+               echo "Collision on ${DESTDIR}/${BINDIR}/send" ; \
+        else true ; \
+        fi
+       -@if [ -f ${DESTDIR}/${BINDIR}/show ] ; then \
+               echo "Collision on ${DESTDIR}/${BINDIR}/show" ; \
+        else true ; \
+        fi
+       -@if [ -f ${DESTDIR}/${MHDIR} -o -d ${DESTDIR}/${MHDIR} ] ; then \
+            echo "${DESTDIR}/${MHDIR} already exists!"; \
+        else true ; \
+        fi
+
+cp:    all
+       -mkdir ${DESTDIR}/${BINDIR}
+       -mkdir ${DESTDIR}/${LIBDIR}
+       -mkdir ${DESTDIR}/${MHDIR}
+       cp comp ${DESTDIR}/${BINDIR}; chmod 1755 ${DESTDIR}/${BINDIR}/comp ; strip ${DESTDIR}/${BINDIR}/comp
+       cp deliver ${DESTDIR}/${MHDIR}; strip ${DESTDIR}/${MHDIR}/deliver; chmod 4755 ${DESTDIR}/${MHDIR}/deliver
+       cp folder ${DESTDIR}/${BINDIR}; strip ${DESTDIR}/${BINDIR}/folder
+       cp forw ${DESTDIR}/${BINDIR}; strip ${DESTDIR}/${BINDIR}/forw
+       cp inc ${DESTDIR}/${BINDIR}; chmod 1755 ${DESTDIR}/${BINDIR}/inc ; strip ${DESTDIR}/${BINDIR}/inc
+       cp install-mh ${DESTDIR}/${MHDIR}; strip ${DESTDIR}/${MHDIR}/install-mh
+       cp next ${DESTDIR}/${BINDIR}; chmod 1755 ${DESTDIR}/${BINDIR}/next ; strip ${DESTDIR}/${BINDIR}/next
+       cp news ${DESTDIR}/${BINDIR}; strip ${DESTDIR}/${BINDIR}/news
+       cp pick ${DESTDIR}/${BINDIR}; strip ${DESTDIR}/${BINDIR}/pick
+       cp prev ${DESTDIR}/${BINDIR}; strip ${DESTDIR}/${BINDIR}/prev
+       cp prompter ${DESTDIR}/${BINDIR}; chmod 1755 ${DESTDIR}/${BINDIR}/prompter ; strip ${DESTDIR}/${BINDIR}/prompter
+       cp refile ${DESTDIR}/${BINDIR}; strip ${DESTDIR}/${BINDIR}/refile
+       cp repl ${DESTDIR}/${BINDIR}; strip ${DESTDIR}/${BINDIR}/repl
+       cp rmf ${DESTDIR}/${BINDIR}; strip ${DESTDIR}/${BINDIR}/rmf
+       cp rmm ${DESTDIR}/${BINDIR}; strip ${DESTDIR}/${BINDIR}/rmm
+       cp scan ${DESTDIR}/${BINDIR}; strip ${DESTDIR}/${BINDIR}/scan
+       cp send ${DESTDIR}/${BINDIR}; strip ${DESTDIR}/${BINDIR}/send
+       cp show ${DESTDIR}/${BINDIR}; chmod 1755 ${DESTDIR}/${BINDIR}/show ; strip ${DESTDIR}/${BINDIR}/show
+       cp unixtomh ${DESTDIR}/${MHDIR}; strip ${DESTDIR}/${MHDIR}/unixtomh
+       rm -f ${DESTDIR}/${BINDIR}/folders
+       ln ${DESTDIR}/${BINDIR}/folder ${DESTDIR}/${BINDIR}/folders
+       cp ../support/components ${DESTDIR}/${MHDIR}/components;
+       cp ../support/distcomps ${DESTDIR}/${MHDIR}/distcomps;
+
+cleanup:
+       rm -f ${PROGS}
+
+clean:
+       cd ${SUBS}; make ${MFLAG} clean
+       cd ${STRINGS}; make ${MFLAG} clean
+       rm -f ${PROGS} subs.a strings.a *.o
diff --git a/docs/historical/2.9BSD/cmds/aliascheck.c b/docs/historical/2.9BSD/cmds/aliascheck.c
new file mode 100644 (file)
index 0000000..03d94f6
--- /dev/null
@@ -0,0 +1,209 @@
+#include <stdio.h>
+#include <ctype.h>
+#include <grp.h>
+#include <sys/param.h>
+#include <dir.h>
+
+char    *AliasFile =    "/usr/local/lib/MailAliases";
+char    *Password  =    "/etc/passwd";
+char    *MailDir   =    "/usr/spool/mail";
+
+char *termptr;
+
+struct  mailname {
+       struct mailname *m_next;
+       char            *m_name;
+       int              m_seen;
+}  users, bad;
+
+
+char *parse(ptr, buf)
+register char *ptr;
+char *buf;
+{
+       register char *cp;
+
+       cp = buf;
+       while(isspace(*ptr) || *ptr == ',' || *ptr == ':')
+               ptr++;
+       while(isalnum(*ptr) || *ptr == '/' || *ptr == '-' || *ptr == '.')
+               *cp++ = *ptr++;
+       if(cp == buf) {
+               switch(*ptr) {
+               case '<':
+               case '*':
+               case '=':
+                       *cp++ = *ptr++;
+               }
+       }
+       *cp = 0;
+       if(cp == buf)
+               return 0;
+       termptr = ptr;
+       return buf;
+}
+
+
+char   *mail = 0;
+FILE   *out;
+int     donecd = 0;
+
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       register char *cp, *pp, **cpp;
+       register struct mailname *lp;
+       register struct group *gp;
+       struct direct *dir;
+       DIR *dirp;
+       char line[256], pbuf[64];
+       FILE *a;
+
+       if(argc == 3 && strcmp(argv[1], "-mail") == 0)
+               mail = argv[2];
+       if(!mail)
+               out = stdout;
+       if((a = fopen(Password, "r")) == NULL) {
+               om();
+               fprintf(out, "Can't open password file ");
+               perror(Password);
+               done(1);
+       }
+       while(fgets(line, sizeof line, a)) {
+               if(line[0] == '\n' || line[0] == ';')
+                       continue;
+               cp = parse(line, pbuf);
+               add(cp, &users);
+       }
+       fclose(a);
+       if((a = fopen(AliasFile, "r")) == NULL) {
+               om();
+               fprintf(out, "Can't open alias file: %s\n", AliasFile);
+               donecd = 1;
+       } else {
+               while(fgets(line, sizeof line, a)) {
+                       if(line[0] == '\n' || line[0] == ';')
+                               continue;
+                       cp = parse(line, pbuf);
+                       if(check(cp, 0)) {
+                               add(line, &bad);
+                               donecd = 1;
+                       }
+               }
+               fclose(a);
+               if(donecd < 1) {
+                       if(out)
+                               fprintf(out, "No Alias Inconsistencies.\n");
+               } else {
+                       om();
+                       fprintf(out, "%s :: %s Collisions:\n",
+                               Password, AliasFile);
+                       fprintf(out, "Colliding alias lines:\n");
+                       for(lp = bad.m_next; lp; lp = lp->m_next)
+                               fprintf(out, "%s", lp->m_name);
+                       donecd = 1;
+               }
+       }
+       while(gp = getgrent()) {
+               for(cpp = gp->gr_mem; *cpp; cpp++)
+                       if(!check(*cpp, 1)) {
+                               om();
+                               fprintf(out, "Group: %s--User: %s not in /etc/passwd\n",
+                                       gp->gr_name, *cpp);
+                               donecd = 2;
+                       }
+       }
+       if(donecd < 2 && out)
+               fprintf(out, "No extraneous group entries.\n");
+#ifdef RAND
+       for(lp = users.m_next; lp; lp = lp->m_next)
+               if(lp->m_seen == 0) {
+                       om();
+                       fprintf(out, "User: %s not in a group.\n", lp->m_name);
+                       donecd = 3;
+               }
+       if(donecd < 3 && out)
+               fprintf(out, "No Users not in any group.\n");
+#endif
+       if ((dirp = opendir(MailDir)) == 0) {
+               om();
+               fprintf(out, "Can't open mail directory: %s\n", MailDir);
+               donecd = 4;
+       } else {
+               (void) readdir(dirp);           /* skip . */
+               (void) readdir(dirp);           /* skip .. */
+               while (dir = readdir(dirp)) {
+                       if (!check(dir->d_name, 0)) {
+                               om();
+                               fprintf(out, "Mail drop: %s--Nonexistent user.\n",
+                                       dir->d_name);
+                               donecd = 4;
+                       }
+               }
+               closedir(dirp);
+       }
+       if(donecd < 4 && out)
+               fprintf(out, "No Extra mail drops.\n");
+
+       done(donecd);
+}
+
+
+add(name, list)
+char *name;
+struct mailname *list;
+{
+       register struct mailname *mp;
+       char *getcpy();
+
+       for(mp = list; mp->m_next; mp = mp->m_next)
+               ;
+       mp->m_next = (struct mailname *) malloc(sizeof *mp->m_next);
+       mp = mp->m_next;
+       mp->m_next = 0;
+       mp->m_name = getcpy(name);
+}
+
+check(name, mark)
+       char *name;
+       int mark;
+{
+       register struct mailname *mp;
+
+       for(mp = users.m_next; mp; mp = mp->m_next)
+               if(uleq(name, mp->m_name)) {
+                       if(mark)
+                               mp->m_seen = 1;
+                       return 1;
+               }
+       return 0;
+}
+
+
+om()
+{
+       int pipes[2], child;
+
+       if(out)
+               return;
+       if(mail) {
+               pipe(pipes);
+               out = fdopen(pipes[1], "w");
+               if((child = fork()) == -1) {
+                       fprintf(stderr, "Aliascheck: no forks!\n");
+                       done(1);
+               }
+               if(child == 0) {
+                       close(pipes[1]);
+                       close(0);
+                       dup(pipes[0]);
+                       close(pipes[0]);
+                       execl("/bin/mail", "mail", mail, 0);
+                       execl("/usr/bin/mail", "mail", mail, 0);
+                       perror("mail");
+                       done(1);
+               }
+               fprintf(out, "Aliascheck: ");
+       }
+}
diff --git a/docs/historical/2.9BSD/cmds/annotate.c b/docs/historical/2.9BSD/cmds/annotate.c
new file mode 100644 (file)
index 0000000..fce8b74
--- /dev/null
@@ -0,0 +1,110 @@
+#ifndef lint
+static char sccsid[] = "@(#)annotate.c 4.1 2/23/83";
+#endif
+
+#include "mh.h"
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+/* annotate file component data
+ *
+ * prepends   Component: data
+ *              date stamp
+ */
+
+annotate(file, comp, text, inplace)
+       char *file, *comp, *text;
+{
+       register int src;
+       register char *cp;
+       register FILE *tmp;
+       int cnt, fd;
+       char buf[BUFSIZ], *sp, tmpfil[128];
+       long now;
+       struct stat stbuf;
+       char *cdate();
+
+       if((src = open((cp = file), 2)) == -1) { /* this should be an X-open*/
+               fprintf(stderr, "Can't open ");
+               perror(cp);
+               return(1);
+       }
+       copy(cp, buf);
+       sp = r1bindex(buf);
+       if(sp != buf) {
+               *sp = 0;
+               cp = copy(buf, tmpfil);
+       } else
+               cp = tmpfil;
+       copy(makename("ano",".tmp"), cp);
+       fstat(src, &stbuf);
+       if((tmp = fopen(tmpfil, "w")) == NULL) {
+               fprintf(stderr, "Can't create ");
+               perror(tmpfil);
+               return(1);
+       }
+       chmod(tmpfil, stbuf.st_mode&0777);
+       cp = comp;
+       if(*cp >= 'a' && *cp <= 'z') *cp -= 040;
+       time(&now);
+       cp = cdate(&now);
+       cp[9] = ' ';  cp[15] = 0;
+       if(*cp == ' ') cp++;
+       fprintf(tmp, "%s: <<%s>>\n", comp, cp);
+       cp = text;
+       do {
+               if(*cp == ' ' || *cp == '\t') cp++;
+               sp = cp;
+               while(*cp && *cp++ != '\n') ;
+               if(cp - sp)
+                       fprintf(tmp, "%s: %*s", comp, cp-sp, sp);
+       } while(*cp);
+       if(cp[-1] != '\n' && cp != text) putc('\n', tmp);
+       do
+               if((cnt = read(src, buf, sizeof buf)) > 0)
+                       fwrite(buf, cnt, 1, tmp);
+       while(cnt == sizeof buf);
+       fclose(tmp);
+       if(inplace) {
+               fd = open(tmpfil, 0);          /* reopen for reading */
+               lseek(src, 0l, 0);
+               do
+                       if((cnt = read(fd, buf, sizeof buf)) > 0)
+                               write(src, buf, cnt);
+               while(cnt == sizeof buf);
+               close(fd);
+       } else {
+          /*   cp = copy(file, buf);           */
+          /*   *--cp =| 0200;                  */
+          /*   copy(".bak", copy(file, buf));  */
+               cp = copy(file, buf);
+               cp[1] = 0;
+               do
+                       *cp = cp[-1];
+               while(--cp >= buf && *cp != '/');
+               *++cp =
+#ifdef UCB
+                       '#';
+#else
+                       ',';
+#endif
+               unlink(buf);
+               if(link(file, buf) == -1) {
+                       fprintf(stderr, "Can't rename %s to bak file.\n", file);
+                       return(1);
+               }
+               if(unlink(file) == -1) {
+                       fprintf(stderr, "Can't unlink %s\n", file);
+                       return(1);
+               }
+               if(link(tmpfil, file) == -1) {
+                       fprintf(stderr, "Can't lnk temp file \"%s\" to %s\n",
+                         tmpfil, file);
+                       return(1);
+               }
+       }
+       close(src);
+       unlink(tmpfil);
+       return(0);
+}
diff --git a/docs/historical/2.9BSD/cmds/comp.c b/docs/historical/2.9BSD/cmds/comp.c
new file mode 100644 (file)
index 0000000..37a69aa
--- /dev/null
@@ -0,0 +1,163 @@
+#include "mh.h"
+#include <stdio.h>
+#include <strings.h>
+#include <signal.h>
+
+/* #define NEWS 1 */
+#define NONE 0
+
+/* #define TEST 1 */
+
+char *anyul[] = {
+       "no",   0,
+       "yes",  0,
+       "use",  0,
+       "list", 0,
+       0
+};
+
+char *aleqs[] = {
+       "list",              0,         /* 0 */
+       "edit [<editor>]",   0,         /* 1 */
+       "quit [delete]",     0,         /* 2 */
+       "send [verbose]",    0,         /* 3 */
+       0
+};
+
+
+struct swit switches[] = {
+       "editor editor",  0,      /* 0 */
+       "form formfile",  0,      /* 1 */
+       "use",            0,      /* 2 */
+       "nouse",          0,      /* 3 */
+       "help",           4,      /* 4 */
+       0,                0
+};
+
+main(argc, argv)
+char *argv[];
+{
+       register char *cp;
+       register int in, out;
+       int use, cnt, status, intr;
+       char buf[BUFSIZ], *ed, *file, *form;
+       static char path[128];
+       char **ap;
+       char *arguments[50], **argp;
+
+/***    setbuf(stdout, _sobuf); ***/
+#ifdef NEWS
+       m_news();
+#endif
+       form = 0; use = 0; file = 0; ed = 0;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-') {
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);  /* ambiguous */
+                               goto leave;
+                                                       /* unknown */
+                       case -1:fprintf(stderr, "comp: -%s unknown\n", cp);
+                               goto leave;
+                       case 0: if(!(ed = *argp++)) {   /* -editor */
+      missing:  fprintf(stderr, "comp: Missing argument for %s switch\n", argp[-2]);
+                                       goto leave;
+                               }
+                               continue;
+                       case 1: if(!(form = *argp++))   /* -form */
+                                       goto missing;
+                               continue;
+                       case 2: use = 1;  continue;     /* -use */
+                       case 3: use = 0;  continue;     /* -nouse */
+                       case 4: help("comp    [file]  [switches]",
+                                    switches);
+                               goto leave;
+                       }
+               }
+               file = cp;
+       }
+       if(form) {
+               if((in = open(m_maildir(form), 0)) < 0) {
+                       fprintf(stderr, "comp: Can't open form file: %s\n", form);
+                       goto leave;
+               }
+       } else if((in = open(m_maildir(components), 0)) < 0 &&
+                  (in = open(stdcomps, 0)) < 0) {
+                       fprintf(stderr, "comp: Can't open default components file!!\n");
+                       goto leave;
+       }
+       if(!file)
+               file = draft;
+       copy(m_maildir(file), path);
+       if((out = open(path, 0)) >= 0) {
+               cp = concat("\n\"", path, "\" exists; delete? ", 0);
+               if(use || fdcompare(in, out))
+                       goto editit;
+               while((status = gans(cp, anyul)) == 3)
+                               showfile(path);
+               if(status == 2) {
+                       use++;
+                       goto editit;
+               }
+               if(status == 0)
+                       goto leave;
+               close(out);
+       } else if(use) {
+               fprintf(stderr, "comp: \"%s\" doesn't exist!\n", path);
+               goto leave;
+       }
+       if((out = creat(path, m_gmprot())) < 0) {
+               fprintf(stderr, "comp: Can't create \"%s\"\n", path);
+               goto leave;
+       }
+       do
+               if(cnt = read(in, buf, sizeof buf))
+                       write(out, buf, cnt);
+       while(cnt == sizeof buf);
+       close(in);
+editit:
+       close(out);
+       if(m_edit(&ed, path, use, NONE) < 0)
+               goto leave;
+#ifdef TEST
+       fprintf(stderr, "!! Test Version of SEND Being Run !!\n");
+       fprintf(stderr, "   Send verbose !\n\n");
+#endif
+
+    for(;;) {
+       if(!(argp = getans("\nWhat now? ", aleqs)))
+               goto leave;
+       switch(smatch(*argp, aleqs)) {
+               case 0: showfile(path);                         /* list */
+                       break;
+               case 1: if(*++argp)                             /* edit */
+                               ed = *argp;
+                       if(m_edit(&ed, path, use, NONE) == -1)
+                               goto leave;
+                       break;
+               case 2: if(*++argp && *argp[0] == 'd')           /* quit */
+                               if(unlink(path) == -1)  {
+                                       fprintf(stderr, "Can't unlink %s ", path);
+                                       perror("");
+                               }
+                       goto leave;
+               case 3: if(*++argp) cp = *argp;  else cp = "";   /* send */
+                       if(! m_send(cp, path))
+                               goto leave;
+               default:fprintf(stderr, "comp: illegal option\n");       /*##*/
+                       break;
+       }
+    }
+
+leave:
+       m_update();
+       done(0);
+}
+
diff --git a/docs/historical/2.9BSD/cmds/deliver.c b/docs/historical/2.9BSD/cmds/deliver.c
new file mode 100644 (file)
index 0000000..4a4bc84
--- /dev/null
@@ -0,0 +1,883 @@
+#ifndef lint
+static char sccsid[] = "@(#)deliver.c  4.3 3/5/83";
+#endif
+
+#include "mh.h"
+#include <stdio.h>
+#include <ctype.h>
+#include <pwd.h>
+#include <sys/types.h>
+#include <sys/timeb.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <strings.h>
+
+/*#define      DELIVERMAIL     "/etc/delivermail"*/
+#define EVERYONE 10
+#define RECVPROG "/.mh_receive"
+#define FCCS    10      /* Max number of fcc's allowed */
+
+struct shome {          /* Internal name/uid/home database */
+       struct shome *h_next;
+       char *h_name;
+       int   h_uid;
+       int   h_gid;
+       char *h_home;
+} *homes, *home();
+
+struct swit switches[] = {
+       "debug",         -1,      /* 0 */
+       "format",         0,      /* 1 */
+       "noformat",       0,      /* 2 */
+       "msgid",          0,      /* 3 */
+       "nomsgid",        0,      /* 4 */
+       "verbose",        0,      /* 5 */
+       "noverbose",      0,      /* 6 */
+       "help",           4,      /* 7 */
+       0,                0
+};
+
+int     verbose, format, msgid, debug, myuid, addrp;
+int     lockwait;       /* Secs to wait for mail lock (From strings/lockdir.c) */
+#define LOCKWAIT (lockwait * 5) /* Ignore lock if older than this */
+int     donecd;
+long    now;
+char    tmpfil[32], fccfold[FCCS][128];
+char   tmp2fil[32];
+int     fccind;
+char   *rindex();
+
+struct  mailname {
+       struct mailname *m_next;
+       char            *m_name;
+}  addrlist;
+
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       register char *cp, *addrs, **argp;
+       register struct mailname *lp;
+       char buf[BUFSIZ], name[NAMESZ];
+       char *msg;
+       int state, compnum, fd;
+       FILE *in, *out;
+       char *getname();
+
+       msg = 0;
+       argp = argv + 1;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               done(1);
+                                                       /* unknown */
+                       case -1:fprintf(stderr, "sndmsg: -%s unknown switch.\n", cp);
+                               done(1);
+                       case 0: verbose++; debug++; continue; /* -debug */
+                       case 1: fprintf(stderr, "Deliver: -format not yet.\n");
+                               done(1);
+/***                    case 1: format = 1; continue;         /* -format */
+                       case 2: format = 0; continue;         /* -noformat */
+                       case 3: msgid = 1;  continue;         /* -msgid */
+                       case 4: msgid = 0;  continue;         /* -nomsgid */
+                       case 5: verbose = 1; continue;        /* -verbose */
+                       case 6: verbose = 0; continue;        /* -noverbose */
+                       case 7: help("deliver [switches] file",
+                                    switches);
+                               done(1);
+                       }
+               if(msg) {
+                       fprintf(stderr, "Deliver: Only one message at a time!\n");
+                       done(1);
+               } else
+                       msg = cp;
+       }
+       if(!msg) {
+               fprintf(stderr, "Deliver: No Message specified.\n");
+               fprintf(stderr, "Deliver: Usage: deliver [switches] file\n");
+               done(1);
+       }
+       if((in = fopen(msg, "r")) == NULL) {
+               fprintf(stderr, "Deliver: Can't open ");
+               perror(msg);
+               done(1);
+       }
+       copy(makename("locs", ".tmp"), copy("/tmp/", tmpfil));
+       if(!debug) {
+               if((out = fopen(tmpfil, "w")) == NULL) {
+                       fprintf(stderr, "Can't create %s\n", tmpfil);
+                       done(1);
+               }
+               chmod(tmpfil, 0744);
+       } else
+               out = stdout;
+
+       gethomes();
+       myuid = getuid();
+#ifndef UNIXCOMP
+       putdate(0, out);           /* Tack on the date */
+       putfrom(out);           /* Tack on the from */
+#endif
+       putmsgid(out);          /* and msg id if desired */
+       for(addrs = 0, compnum = 1, state = FLD;;) {
+               state = m_getfld(state, name, buf, sizeof buf, in);
+   swt:         switch(state) {
+
+               case FLD:
+               case FLDEOF:
+               case FLDPLUS:
+                       compnum++;
+                       if(uleq(name, "to") || uleq(name, "cc") ||
+                          uleq(name, "bcc"))
+                               addrs = add(buf, addrs);
+                       if(!uleq(name, "bcc")) {
+                               cp = buf;
+                               while(*cp == ' ' || *cp == '\t')
+                                       cp++;
+                               fprintf(out, "%s: %s", name, cp);
+                               if(uleq(name, "fcc")) {
+                                       if(fccind >= FCCS) {
+                                               fprintf(stderr, "Deliver: too many fcc's.\n");
+                                               done(1);
+                                       }
+                                       copy(cp, fccfold[fccind]);
+                                       if(cp = rindex(fccfold[fccind], '\n'))
+                                               *cp = 0;
+                                       fccind++;
+                               }
+                       }
+                       while(state == FLDPLUS || state == FLDEOF) {
+                               state = m_getfld(state, name, buf, sizeof buf, in);
+                               addrs = add(buf, addrs);
+                               fputs(buf, out);
+                       }
+                       if(state == FLDEOF)
+                               goto process;
+                       break;
+
+               case BODY:
+               case BODYEOF:
+                       fprintf(out, "\n%s", buf);
+                       while(state == BODY) {
+                               state=m_getfld(state,name,buf,sizeof buf,in);
+                               fputs(buf, out);
+                       }
+
+               case FILEEOF:
+                       goto process;
+
+               case LENERR:
+               case FMTERR:
+                       fprintf(stderr, "??Message Format Error ");
+                       fprintf(stderr, "in Component #%d.\n", compnum);
+                       done(1);
+
+               default:
+                       fprintf(stderr, "Getfld returned %d\n", state);
+                       done(1);
+               }
+       }
+process:
+       if(!debug)
+               fclose(out);
+       else
+               printf("-----\n");
+       fclose(in);
+       while(cp = getname(addrs))      /* Put addrs in chain */
+               insert(cp);
+       if(debug) {
+               printf("Before alias(): "); pl();
+       }
+
+       alias();                        /* Map names if needed */
+
+       for(lp = addrlist.m_next; lp; lp = lp->m_next) {
+#ifdef UNIXCOMP
+               if (netname(lp->m_name))
+                       continue;
+#endif
+#ifndef DELIVERMAIL
+               if(home(lp->m_name) == NULL) {
+                       fprintf(stderr, "Deliver: Unknown User: %s.\n", lp->m_name);
+                       fprintf(stderr, "Deliver: Message Not Delivered.\n");
+                       if(!debug)
+                               unlink(tmpfil);
+                       done(1);
+               }
+#endif DELIVERMAIL
+       }
+       if(debug) {
+               printf("Addrs: "); pl();
+       }
+
+       signal(SIGINT, SIG_IGN);
+       signal(SIGQUIT, SIG_IGN);
+       if(!debug) {                    /* Send the mail */
+               fd = open(tmpfil, 0);
+               for(lp = addrlist.m_next; lp; lp = lp->m_next)
+                       sendmail(lp->m_name, fd);
+#ifdef DELIVERMAIL
+               stflush(fd);
+#endif
+               close(fd);
+               if(fccind) {
+#ifdef UNIXCOMP
+                       strcpy(tmp2fil, "/tmp/mhFXXXXXX");
+                       mktemp(tmp2fil);
+                       out = fopen(tmp2fil, "w");
+                       putdate(0, out);           /* Tack on the date */
+                       putfrom(out);           /* Tack on the from */
+                       appendfile(tmpfil, out);
+                       fclose(out);
+                       for(state = 0; state < fccind; state++)
+                               fcc(tmp2fil, fccfold[state]);
+                       unlink(tmp2fil);
+#else
+                       for(state = 0; state < fccind; state++)
+                               fcc(tmp2fil, fccfold[state]);
+#endif
+               }
+               unlink(tmpfil);
+       }
+       done(donecd);
+}
+
+#ifdef UNIXCOMP
+
+appendfile(name, fout)
+       char name[];
+       register FILE *fout;
+{
+       register int c;
+       register FILE *fin;
+
+       if ((fin = fopen(name, "r")) == NULL) {
+               perror(name);
+               return;
+       }
+       while ((c = getc(fin)) != EOF)
+               putc(c, fout);
+       fclose(fin);
+}
+
+netname(name)
+       char name[];
+{
+       register char *cp;
+       char *index();
+
+       cp = name;
+       if (index(cp, ':') || index(cp, '!') ||
+           index(cp, '@') || index(cp, '^'))
+               return(1);
+       return(0);
+}
+#endif
+
+
+gethomes()
+{
+       register struct passwd *pw;
+       register struct shome *h, *ph;
+       struct passwd *getpwent();
+
+       ph = (struct shome *) &homes;
+       while((pw = getpwent()) != NULL) {
+               h = (struct shome *) malloc(sizeof *h);
+               h->h_next = NULL;
+               h->h_name = (char *) malloc(strlen(pw->pw_name)+1);
+               strcpy(h->h_name, pw->pw_name);
+               h->h_uid = pw->pw_uid;
+               h->h_gid = pw->pw_gid;
+               h->h_home = (char *) malloc(strlen(pw->pw_dir)+1);
+               strcpy(h->h_home, pw->pw_dir);
+               ph->h_next = h;
+               ph = h;
+       }
+}
+
+
+struct shome *
+home(name)
+       register char *name;
+{
+       register struct shome *h;
+
+       for(h = homes; h; h = h->h_next)
+               if(uleq(name, h->h_name))
+                       return(h);
+       return(NULL);
+}
+
+
+char *
+getname(addrs)
+       char *addrs;
+{
+       register char *tp;
+       static char name[32];
+       static char *getaddrs;
+
+       if(!getaddrs)
+               getaddrs = addrs;
+       tp = name;
+
+       while(*getaddrs && !isalpha(*getaddrs))
+               getaddrs++;
+       if(!*getaddrs) {
+               getaddrs = 0;
+               return NULL;
+       }
+#ifdef UNIXCOMP
+       while(!isspace(*getaddrs))
+               *tp++ = *getaddrs++;
+#else
+       while(isalnum(*getaddrs) || index(".:@/-", *getaddrs))
+               *tp++ = *getaddrs++;
+#endif
+       *tp = 0;
+       if(name[0] == 0)
+               return NULL;
+       return name;
+}
+
+char *bracket = "\1\1\1\1\n";
+
+sendmail(name, fd)              /* Runs with signals ignored! */
+       char *name;
+       register int fd;
+{
+       char buf[BUFSIZ], *myname;
+       register int i, m, c;
+       register char *mail, *receive, *lock = 0;
+       register struct shome *h;
+       int pid, status;
+       struct stat stbuf;
+
+       if(verbose) {
+               printf("%s: ", name);
+               fflush(stdout);
+       }
+       lseek(fd, 0l, 0);
+       h = home(name);
+
+       /*
+        * If no home for this user, as in network address
+        * being forced down this path, just assume normal
+        * delivery
+        */
+
+       if (h == NULL)
+               goto force;
+
+       mail = concat(mailboxes, h->h_name, 0);
+/***    mail = concat(h->h_home, mailbox, 0);           ***/
+       receive = concat(h->h_home, RECVPROG, 0);
+       if(access(receive, 1) == 0) {   /* User has a receive prog */
+
+               calluserprog(receive, mail, fd, h);
+
+       } else {
+
+force:
+
+#ifdef UNIXCOMP
+#ifdef DELIVERMAIL
+               nstash(name);
+               if (verbose)
+                       printf("Sent.\n");
+               return;
+#endif DELIVERMAIL
+#ifndef DELIVERMAIL
+               myname = getenv("USER");
+               if (myname == (char *) 0)
+                       myname = "nobody";
+               pid = fork();
+               switch (pid) {
+               case 0:
+                       /* fiddle with files, then . . . */
+                       lseek(fd, 0L, 0);
+                       close(0);
+                       dup(fd);
+                       close(fd);
+                       execl(Mailprog, "Mail", "-r", myname, name, 0);
+                       execl("/bin/mail", "mail", "-r", myname, name, 0);
+                       perror(Mailprog);
+                       _exit(1);
+               
+               case -1:
+                       perror("fork");
+                       return;
+
+               default:
+                       while (wait(&status) != pid)
+                               ;
+               }
+#endif DELIVERMAIL
+#endif UNIXCOMP
+#ifndef UNIXCOMP
+               if((m = open(mail, 2)) < 0) {
+                       if((m = creat(mail, 0600)) < 0) {
+                               fprintf(stderr, "Deliver: Can't write ");
+                               perror(mail);
+                               goto out;
+                       }
+                       chown(mail, h->h_uid, h->h_gid);
+                       if(verbose) {
+                               fprintf(stderr, "Creating %s ", mail);
+                               fflush(stdout);
+                       }
+               }
+               lock = concat(lockdir, h->h_name, 0);
+               for(i = 0; i < lockwait; i += 2) {
+                       if(link(mail, lock) >= 0)
+                               break;
+                       if(i == 0 && stat(mail, &stbuf) >= 0 &&
+                          stbuf.st_ctime + LOCKWAIT < time((long *) 0)) {
+                               i = lockwait;
+                               break;
+                       }
+                       if(verbose) {
+                               printf("Busy ");
+                               fflush(stdout);
+                       }
+                       sleep(2);
+               }
+               if(i >= lockwait) {
+                       unlink(lock);
+                       if(verbose) {
+                               printf("Removing lock. ");
+                               fflush(stdout);
+                       }
+                       if(link(mail, lock) < 0) {
+                               fprintf(stderr, "Can't lock %s to %s\n",
+                                       mail, lock);
+                               donecd = 1;
+                               goto out1;
+                       }
+               }
+               lseek(m, 0l, 2);
+               write(m, bracket, 5);
+               do
+                       if((c = read(fd, buf, sizeof buf)) > 0)
+                               if(write(m, buf, c) != c) {
+                                       fprintf(stderr, "Write error on ");
+                                       perror(mail);
+                                       donecd = 1;
+                                       goto out1;
+                               }
+               while(c == sizeof buf);
+               write(m, bracket, 5);
+out1:           close(m);
+out:            cndfree(mail);
+               if(lock) {
+                       unlink(lock);
+                       cndfree(lock);
+               }
+#endif UNIXCOMP
+       }
+       if(verbose && !donecd)
+               printf("Sent.\n");
+}
+
+#ifdef DELIVERMAIL
+
+/*
+ * Salt away a name to send to, ultimately.
+ */
+
+char   *stashname[100];
+char   **stashp;
+
+nstash(name)
+       char name[];
+{
+       register char *cp;
+
+       cp = (char *) calloc(1, strlen(name) + 1);
+       strcpy(cp, name);
+       if (stashp == 0) {
+               stashp = stashname;
+               *stashp++ = "delivermail";
+               *stashp++ = "-i";
+       }
+       *stashp++ = cp;
+}
+
+stflush(fd)
+{
+       int pid;
+
+       if (stashp == 0)
+               return;
+       while ((pid = fork()) == -1)
+               sleep(2);
+       if (pid == 0) {
+               signal(SIGHUP, SIG_IGN);
+               signal(SIGINT, SIG_IGN);
+               signal(SIGQUIT, SIG_IGN);
+               close(0);
+               dup(fd);
+               close(fd);
+               execv(DELIVERMAIL, stashname);
+               perror(DELIVERMAIL);
+               _exit(1);
+       }
+}
+#endif
+
+putfrom(out)
+       register FILE *out;
+{
+       register struct shome *h;
+
+       for(h = homes; h; h = h->h_next)
+               if(h->h_uid == myuid) {
+                       fprintf(out, "From: %s\n", h->h_name);
+                       return;
+               }
+       fprintf(stderr, "Deliver: WHO ARE YOU?\n");
+       done(1);
+}
+
+
+putmsgid(sp)
+       FILE *sp;
+{
+
+       if(!msgid)
+               return;
+       if(!now)
+               time(&now);
+       fprintf(sp, "Message-ID: <%u.%u.%ld.%s@%s>\n", getpid(), myuid,
+           now, localname, hostname);
+}
+
+/***/
+pl()
+{
+       register struct mailname *mp;
+
+       for(mp = addrlist.m_next; mp; mp=mp->m_next)
+               printf("%s%s", mp->m_name, mp->m_next?", ":"");
+       printf("\n");
+}
+/***/
+
+insert(name)
+       char *name;
+{
+       register struct mailname *mp;
+       char *getcpy();
+
+/***    printf("insert(%s)\n", name);   ***/
+
+       for(mp = &addrlist; mp->m_next; mp = mp->m_next)
+               if(uleq(name, mp->m_next->m_name))
+                       return;         /* Don't insert existing name! */
+       mp->m_next = (struct mailname *) malloc(sizeof *mp->m_next);
+       mp = mp->m_next;
+       mp->m_next = 0;
+       mp->m_name = getcpy(name);
+}
+
+
+/* alias implementation below...
+ */
+
+
+
+#define GROUP   "/etc/group"
+char    *AliasFile =    "/usr/local/lib/MailAliases";
+
+char *termptr;
+
+char *
+parse(ptr, buf)
+       register char *ptr;
+       char *buf;
+{
+       register char *cp;
+
+       cp = buf;
+       while(isspace(*ptr) || *ptr == ',' || *ptr == ':')
+               ptr++;
+       while(isalnum(*ptr) || *ptr == '/' || *ptr == '-' ||
+             *ptr == '.' || *ptr == '*')
+               *cp++ = *ptr++;
+       if(cp == buf) {
+               switch(*ptr) {
+               case '<':
+               case '=':
+                       *cp++ = *ptr++;
+               }
+       }
+       *cp = 0;
+       if(cp == buf)
+               return 0;
+       termptr = ptr;
+       return buf;
+}
+
+char *
+advance(ptr)
+       register char *ptr;
+{
+       return(termptr);
+}
+
+alias()
+{
+       register char *cp, *pp;
+       register struct mailname *lp;
+       char line[256], pbuf[64];
+       FILE *a;
+
+       if((a = fopen(AliasFile, "r")) == NULL)
+               return;
+       while(fgets(line, sizeof line, a)) {
+               if(line[0] == ';' || line[0] == '\n')   /* Comment Line */
+                       continue;
+               if((pp = parse(line, pbuf)) == NULL) {
+           oops:       fprintf(stderr, "Bad alias file %s\n", AliasFile);
+                       fprintf(stderr, "Line: %s", line);
+                       done(1);
+               }
+               for(lp = &addrlist; lp->m_next; lp = lp->m_next) {
+                       if(aleq(lp->m_next->m_name, pp)) {
+                               remove(lp);
+                               if(!(cp = advance(line)) ||
+                                  !(pp = parse(cp, pbuf)))
+                                       goto oops;
+                               switch(*pp) {
+                               case '<':       /* From file */
+                                       cp = advance(cp);
+                                       if((pp = parse(cp, pbuf)) == NULL)
+                                               goto oops;
+                                       addfile(pp);
+                                       break;
+                               case '=':       /* UNIX group */
+                                       cp = advance(cp);
+                                       if((pp = parse(cp, pbuf)) == NULL)
+                                               goto oops;
+                                       addgroup(pp);
+                                       break;
+                               case '*':       /* ALL Users */
+                                       addall();
+                                       break;
+                               default:        /* Simple list */
+                                       for(;;) {
+                                               insert(pp);
+                                               if(!(cp = advance(line)) ||
+                                                  !(pp = parse(cp, pbuf)))
+                                                       break;
+                                       }
+                               }
+                               break;
+                       }
+               }
+       }
+}
+
+
+addfile(file)
+       char *file;
+{
+       register char *cp, *pp;
+       char line[128], pbuf[64];
+       FILE *f;
+
+/***    printf("addfile(%s)\n", file);          ***/
+       if((f = fopen(file, "r")) == NULL) {
+               fprintf(stderr, "Can't open ");
+               perror(file);
+               done(1);
+       }
+       while(fgets(line, sizeof line, f)) {
+               cp = line;
+               while(pp = parse(cp, pbuf)) {
+                       insert(pp);
+                       cp = advance(cp);
+               }
+       }
+       fclose(f);
+}
+
+addgroup(group)
+       char *group;
+{
+       register char *cp, *pp;
+       int found = 0;
+       char line[128], pbuf[64], *rindex();
+       FILE *f;
+
+/***    printf("addgroup(%s)\n", group);        ***/
+       if((f = fopen(GROUP, "r")) == NULL) {
+               fprintf(stderr, "Can't open ");
+               perror(GROUP);
+               done(1);
+       }
+       while(fgets(line, sizeof line, f)) {
+               pp = parse(line, pbuf);
+               if(strcmp(pp, group) == 0) {
+                       cp = rindex(line, ':');
+                       while(pp = parse(cp, pbuf)) {
+                               insert(pp);
+                               cp = advance(cp);
+                       }
+                       found++;
+               }
+       }
+       if(!found) {
+               fprintf(stderr, "Group: %s non-existent\n", group);
+               done(1);
+       }
+       fclose(f);
+}
+
+addall()
+{
+       register struct shome *h;
+
+/***    printf("addall()\n");                   ***/
+       for(h = homes; h; h = h->h_next)
+               if(h->h_uid >= EVERYONE)
+                       insert(h->h_name);
+}
+
+remove(mp)              /* Remove NEXT from argument node! */
+       register struct mailname *mp;
+{
+       register struct mailname *rp;
+
+       rp = mp->m_next;
+       mp->m_next = rp->m_next;
+       cndfree(rp->m_name);
+       cndfree(rp);
+}
+
+int     alarmed;
+
+alarmclock()
+{
+       alarmed++;
+}
+
+extern  char **environ;
+char   envhome[60] = "HOME=";
+char   envname[60] = "NAME=";
+char   *envinit[] = {envhome, envname, (char *) 0};
+
+calluserprog(prog, mail, fd, h)
+       char *prog, *mail;
+       int fd;
+       register struct shome *h;
+{
+       register int pid, child, i;
+       int status;
+
+       if(verbose) {
+               printf("Invoking %s ", prog);
+               fflush(stdout);
+       }
+       i = 0;
+       while((child = fork()) == -1)
+               if(++i > 10) {
+                       fprintf(stderr, "Can't get a fork to invoke %s!\n",
+                               prog);
+                       donecd = 1;
+                       return;
+               } else
+                       sleep(2);
+       if(child == 0) {                /* In child... */
+               if(fd != 3)
+                       dup2(fd, 3);
+               for(i = 4; i < 15; i++)
+                       close(i);
+               strcat(envname, h->h_name);
+               strcat(envhome, h->h_home);
+               environ = envinit;
+               setgid(h->h_gid);
+               setuid(h->h_uid);
+               execlp(prog, prog, tmpfil, mail, h->h_home, 0);
+               perror(prog);
+               done(-1);
+       }
+       signal(SIGALRM, alarmclock);
+       alarmed = 0;
+       alarm(30);                      /* Give receive proc 30 secs */
+       status = 0;
+       while((pid = wait(&status)) != -1 && pid != child && !alarmed) ;
+       if(alarmed) {
+               kill(0, SIGINT);
+               signal(SIGALRM, alarmclock);
+               alarmed = 0;
+               alarm(30);
+               while((pid = wait(&status)) != -1 && pid != child && !alarmed) ;
+               if(alarmed) {
+                       kill(child, SIGKILL);
+                       signal(SIGALRM, alarmclock);
+                       alarmed = 0;
+                       alarm(30);
+                       while((pid = wait(&status)) != -1 && pid != child && !alarmed) ;
+               }
+               fprintf(stderr, "Deliver: Killed %s--Took more than 30 seconds!\n",
+                       prog);
+               donecd = 1;
+               status = 0;
+       } else
+               alarm(0);
+       if(status) {
+               printf("Deliver: %s error %d from %s on delivery to %s\n",
+                       status&0377? "System" : "User",
+                       status&0377? status&0377 : status>>8,
+                       prog, h->h_name);
+               donecd = 1;
+       }
+       if(pid == -1) {
+               fprintf(stderr, "Deliver: wait on receive process returned -1\n");
+               perror("");
+               donecd = 1;
+       }
+}
+
+aleq(string, aliasent)
+       register char *string, *aliasent;
+{
+       register int c;
+
+       while(c = *string++)
+               if(*aliasent == '*')
+                       return 1;
+               else if((c|040) != (*aliasent|040))
+                       return(0);
+               else
+                       aliasent++;
+       return(*aliasent == 0 | *aliasent == '*');
+}
+
+fcc(file, folder)
+       char *file, *folder;
+{
+       int child, pid, status;
+       char fold[128];
+
+       if(verbose) {
+               printf("Fcc: %s...", folder);
+               fflush(stdout);
+       }
+       while((child = fork()) == -1) sleep(5);
+       if(child == 0) {
+               if(*file != '+')
+                       strcpy(fold, "+");
+               strcat(fold, folder);
+               setuid(myuid);
+               execl(fileproc, "file", "-link", "-file", file, fold, 0);
+               exit(-1);
+       } else while((pid = wait(&status)) != -1 && pid != child) ;
+       if(status)
+               fprintf(stderr, "Deliver: Error on fcc to %s\n", folder);
+       else if(verbose)
+               putchar('\n');
+}
diff --git a/docs/historical/2.9BSD/cmds/dist.c b/docs/historical/2.9BSD/cmds/dist.c
new file mode 100644 (file)
index 0000000..76ea486
--- /dev/null
@@ -0,0 +1,295 @@
+#ifndef lint
+static char sccsid[] = "@(#)dist.c     4.1 2/23/83";
+#endif
+
+#include "mh.h"
+#include <stdio.h>
+#include <signal.h>
+#include <strings.h>
+
+#define NONE 0
+#define NOUSE 0
+
+/* #define TEST 1 */
+
+char    *anyl[] = {
+       "no",   0,
+       "yes",  0,
+       "list", 0,
+       0,
+};
+
+char    *anyv[] = {
+       "no",           0,
+       "yes",          0,
+       "verbose",      0,
+       0,
+};
+
+char    *aleqs[] = {
+       "list",              0,         /* 0 */
+       "edit [<editor>]",   0,         /* 1 */
+       "quit [delete]",     0,         /* 2 */
+       "send [verbose]",    0,         /* 3 */
+       0
+};
+
+struct msgs *mp;
+char drft[128];
+char *vec[MAXARGS];
+int inplace;            /* preserve links in anno */
+
+struct swit switches[] = {
+       "annotate",           0,      /* 0 */
+       "noannotate",         0,      /* 1 */
+       "editor editor",      0,      /* 2 */
+       "form formfile",      0,      /* 3 */
+       "inplace",            0,      /* 4 */
+       "noinplace",          0,      /* 5 */
+       "help",               4,      /* 6 */
+       0,                    0
+};
+
+main(argc, argv)
+char *argv[];
+{
+       char *folder, *maildir, *msgs[100], *ed, *form;
+       register int msgnum;
+       register char *cp, **ap;
+       int msgp, anot, curf;
+       int in, out, intr;
+       int pid, wpid, status;
+       char *arguments[50], **argp;
+
+#ifdef NEWS
+       m_news();
+#endif
+       anot = 0; folder = 0; curf = 0; msgp = 0; ed = 0; form = 0;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                            /* unknown */
+                       case -1:fprintf(stderr, "dist: -%s unknown\n", cp);
+                               goto leave;
+                       case 0: anot = 1;  continue;         /* -annotate */
+                       case 1: anot = 0;  continue;         /* -noannotate */
+                       case 2: if(!(ed = *argp++)) {        /* -editor */
+      missing:  fprintf(stderr, "dist: Missing argument for %s switch\n", argp[-2]);
+                                       goto leave;
+                               }
+                               continue;
+                       case 3: if(!(form = *argp++))        /* -form */
+                                       goto missing;
+                               continue;
+                       case 4: inplace = 1;  continue;      /* -inplace */
+                       case 5: inplace = 0;  continue;      /* -noinplace */
+                                                            /* -help */
+                       case 6: help("dist   [+folder] [msg] [switches]",
+                                    switches);
+                               goto leave;
+                       }
+               if(*cp == '+') {
+                       if(folder) {
+                               fprintf(stderr, "Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               folder = cp + 1;
+               } else
+                       msgs[msgp++] = cp;
+       }
+       if(!msgp)
+               msgs[msgp++] = "cur";
+       if(!folder)
+               folder = m_getfolder();
+       maildir = m_maildir(folder);
+       if(chdir(maildir) < 0) {
+               fprintf(stderr, "Can't chdir to: ");
+               perror(maildir);
+               goto leave;
+       }
+       if(!(mp = m_gmsg(folder))) {
+               fprintf(stderr, "Can't read folder!?\n");
+               goto leave;
+       }
+       if(mp->hghmsg == 0) {
+               fprintf(stderr, "No messages in \"%s\".\n", folder);
+               goto leave;
+       }
+       for(msgnum = 0; msgnum < msgp; msgnum++)
+               if(!m_convert((cp = msgs[msgnum])))
+                       goto leave;
+       if(mp->numsel == 0) {
+               fprintf(stderr, "dist: Tuna Melt\n");     /* never get here */
+               goto leave;
+       }
+       if(mp->numsel > 1) {
+               fprintf(stderr, "Only one message at a time.\n");
+               goto leave;
+       }
+       if(form) {
+               if((in = open(m_maildir(form), 0)) < 0) {
+                       fprintf(stderr, "dist: Can't open form file: %s\n", form);
+                       goto leave;
+               }
+       } else if(/***(in = open(m_maildir(distcomps), 0)) < 0 &&      ***/
+                  (in = open(stddcomps, 0)) < 0) {
+                       fprintf(stderr, "dist: Can't open default components file!!\n");
+                       goto leave;
+       }
+       copy(m_maildir(draft), drft);
+       if((out = open(drft, 0)) >= 0) {
+               if(!fdcompare(in, out)) {
+                       cp = concat("\"", drft, "\" exists; Delete? ", 0);
+                       while((msgnum = gans(cp, anyl)) == 2)
+                               showfile(drft);
+                       if(!msgnum)
+                               return;
+               }
+               close(out);
+       }
+       if((out = creat(drft, m_gmprot())) < 0) {
+               fprintf(stderr, "Can't create \"%s\"\n", drft);
+               goto leave;
+       }
+       cpydata(in, out);
+       close(in);
+       if((in = open(cp = m_name(mp->lowsel), 0)) < 0) {
+               fprintf(stderr, "Can't open message \"%s\"\n", cp);
+               unlink(drft);
+               goto leave;
+       }
+       cpydata(in, out);
+       close(in);
+       close(out);
+       m_replace(pfolder, folder);
+       if(mp->lowsel != mp->curmsg)
+               m_setcur(mp->lowsel);
+       if(m_edit(&ed, drft, NOUSE, NONE) < 0)
+               goto leave;
+#ifdef TEST
+       fprintf(stderr, "!! Test Version of SEND Being Run !!\n");
+       fprintf(stderr, "   Send verbose !\n\n");
+#endif
+
+    for(;;) {
+       if(!(argp = getans("\nWhat now? ", aleqs)))
+               goto leave;
+       switch(smatch(*argp, aleqs)) {
+               case 0: showfile(drft);                         /* list */
+                       break;
+               case 1: if(*++argp)                             /* edit */
+                               ed = *argp;
+                       if(m_edit(&ed, drft, NOUSE, NONE) == -1)
+                               goto leave;
+                       break;
+               case 2: if(*++argp && *argp[0] == 'd')          /* quit */
+                               if(unlink(drft) == -1)  {
+                                       fprintf(stderr, "Can't unlink %s ", drft);
+                                       perror("");
+                               }
+                       goto leave;
+               case 3: if(*++argp) cp = *argp;  else cp = "";  /* send */
+
+                       if(!mp->msgflags&READONLY) {    /* annotate first */
+                           if(anot > 0) {
+                               while((pid = fork()) == -1) sleep(5);
+                               if(pid) {
+                                       while(wpid=wait((int *)NULL)!= -1 && wpid!= pid);
+                                       doano();
+                                       goto leave;
+                               }
+                           }
+                       }
+                       if(!m_send(cp, drft))
+                               goto leave;
+               default:fprintf(stderr, "dist: illegal option\n");       /*##*/
+                       break;
+       }
+    }
+
+ leave:
+       m_update();
+       done(0);
+}
+
+
+cpydata(in, out)
+{
+       char buf[BUFSIZ];
+       register int i;
+
+       do
+               if((i = read(in, buf, sizeof buf)) > 0)
+                       write(out, buf, i);
+       while(i == sizeof buf);
+}
+
+
+doano()
+{
+       register FILE *in;
+       char name[NAMESZ], field[256];
+       register int ind, state;
+       register char *text;
+
+       if(stat(drft, field) != -1) {
+               fprintf(stderr, "%s not sent-- no annotations made.\n", drft);
+               return;
+       }
+       text = copy(drft, field);
+       text[1] = 0;
+       do
+               *text = text[-1];
+       while(--text >= field && *text != '/');
+       *++text =
+#ifdef UCB
+               '#';
+#else
+               ',';
+#endif
+       if((in = fopen(field, "r")) == NULL) {
+               fprintf(stderr, "Can't open %s\n", field);
+               return;
+       }
+       state = FLD;
+       text = 0;
+   for(;;) switch(state = m_getfld(state, name, field, sizeof field, in)) {
+
+       case FLD:
+       case FLDEOF:
+       case FLDPLUS:
+               if(uleq(name, "distribute-to") ||
+                  uleq(name, "distribute-cc") == 0) {
+                       if(state == FLD) {
+                               text = add(name, text);
+                               text = add(":", text);
+                       }
+                       text = add(field, text);
+               }
+               if(state == FLDEOF)
+                       goto out;
+               continue;
+       case BODY:
+       case BODYEOF:
+               goto out;
+       default:
+               fprintf(stderr, "Getfld returned %d\n", state);
+               return;
+       }
+
+out:
+       fclose(in);
+       annotate(m_name(mp->lowsel), "Distributed", text, inplace);
+
+
+}
diff --git a/docs/historical/2.9BSD/cmds/emitl.c b/docs/historical/2.9BSD/cmds/emitl.c
new file mode 100644 (file)
index 0000000..439b618
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Routine to convert a localtime(3) format date back into
+ * a system format date.
+ *
+ * Hats off to Bob Kridle for the insight that the way to do
+ * this is by binary search of the system date space.
+ */
+
+#include <sys/time.h>
+
+struct tm *localtime();
+
+long
+emitl(dp)
+       struct tm *dp;
+{
+       long conv;
+       register int i, bit;
+       struct tm dcopy;
+
+       dcopy = *dp;
+       dp = &dcopy;
+       conv = 0;
+       for (i = 31; i >= 0; i--) {
+               bit = 1 << i;
+               conv |= bit;
+               if (dcmp(localtime(&conv), dp) > 0)
+                       conv &= ~bit;
+       }
+       return(conv);
+}
+
+/*
+ * Compare two localtime dates, return result.
+ */
+
+#define DECIDE(a) \
+       if (dp->a > dp2->a) \
+               return(1); \
+       if (dp->a < dp2->a) \
+               return(-1)
+
+static
+dcmp(dp, dp2)
+       register struct tm *dp, *dp2;
+{
+
+       DECIDE(tm_year);
+       DECIDE(tm_mon);
+       DECIDE(tm_mday);
+       DECIDE(tm_hour);
+       DECIDE(tm_min);
+       DECIDE(tm_sec);
+       return(0);
+}
diff --git a/docs/historical/2.9BSD/cmds/folder.c b/docs/historical/2.9BSD/cmds/folder.c
new file mode 100644 (file)
index 0000000..8d63c71
--- /dev/null
@@ -0,0 +1,316 @@
+#include "mh.h"
+#include <stdio.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <dir.h>
+#include <strings.h>
+
+#define NFOLDERS 100
+
+int all, hdrflag, foldp;
+struct msgs *mp;
+char folder[128], *folds[NFOLDERS];
+int msgtot, foldtot, totonly, fshort;
+int fpack;
+struct swit switches[] = {
+       "all",          0,      /* 0 */
+       "down",         0,      /* 1 */
+       "fast",         0,      /* 2 */
+       "nofast",       0,      /* 3 */
+       "header",       0,      /* 4 */
+       "noheader",     0,      /* 5 */
+       "pack",         0,      /* 6 */
+       "nopack",       0,      /* 7 */
+       "short",       -1,      /* 8 */
+       "total",        0,      /* 9 */
+       "nototal",      0,      /*10 */
+       "up",           0,      /*11 */
+       "help",         4,      /*12 */
+       "debug",        5,      /*13 */
+       0,              0
+};
+
+int    debug;
+
+main(argc, argv)
+char *argv[];
+{
+       register char *cp, *curm;
+       register int i;
+       char *argfolder;
+       int up, down, j, def_short;
+       char *arguments[50], **argp, **ap;
+       struct stat stbf;
+       struct node *np;
+       extern char _sobuf[];
+       register struct direct *dir;
+       DIR *dirp;
+
+       setbuf(stdout, _sobuf);
+#ifdef NEWS
+       m_news();
+#endif
+       up = down = 0;
+       argfolder = NULL;
+       curm = 0;
+       if(argv[0][strlen(argv[0])-1] == 's')   /* Plural name?? */
+               all++;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);     /* ambiguous */
+                               goto leave;
+                                                          /* unknown */
+                       case -1:fprintf(stderr, "folder: -%s unknown\n", cp);
+                               goto leave;
+                       case 0: all++;  continue;          /* -all      */
+                       case 1: down++;  continue;         /* -down     */
+                       case 2:                            /* -fast     */
+                       case 3: fshort = 0; continue;      /* -nofast   */
+                       case 4: hdrflag = -1;  continue;   /* -header   */
+                       case 5: hdrflag = 0;  continue;    /* -noheader */
+                       case 6: fpack = 1; continue;       /* -pack     */
+                       case 7: fpack = 0; continue;       /* -nopack   */
+                       case 8: fshort = 1; continue;      /* -short    */
+                       case 9: all++; totonly = 1;        /* -total    */
+                               continue;
+                       case 10:if(totonly) all--;         /* -nototal  */
+                               totonly =0;  continue;
+                       case 11:up++;  continue;           /* -up       */
+                                                          /* -help     */
+                       case 12:help("folder [+folder]  [msg] [switches]",
+                                    switches);
+                               goto leave;
+                       case 13:debug++;                   /* -debug    */
+                               continue;
+                       }
+               if(*cp == '+') {
+                       if(argfolder) {
+                               fprintf(stderr, "Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               argfolder = cp + 1;
+               } else if(curm) {
+                       fprintf(stderr, "Only one current may be given.\n");
+                       goto leave;
+               } else
+                       curm = cp;
+       }
+       if(all) {
+               hdrflag = 0;
+               cp = m_maildir("");
+               m_getdefs();
+               for(np = m_defs; np; np = np->n_next) {
+                       if(!ssequal("cur-", np->n_name))
+                               continue;
+                       if(fshort) {
+                               def_short++;
+                               printf("%s\n", np->n_name+4);
+                       } else
+                               addfold(np->n_name+4);
+               }
+               if(def_short)
+                       putchar('\n');
+               if(fshort) {
+                       m_update();
+                       fflush(stdout);
+                       execl(lsproc, "mh-ls", "-x", cp, 0);
+                       fprintf(stderr, "Can't exec: ");
+                       perror(lsproc);
+                       goto leave;
+               }
+               if(chdir(cp) < 0) {
+                       fprintf(stderr, "Can't chdir to: ");
+                       perror(cp);
+                       goto leave;
+               }
+               if((cp = m_find(pfolder)) == NULL)
+                       *folder = 0;
+               else
+                       copy(cp, folder);
+               dirp = opendir(".");
+               (void) readdir(dirp);
+               (void) readdir(dirp);
+               while (dir = readdir(dirp)) {
+                       if (stat(dir->d_name, &stbf) < 0 ||
+                           (stbf.st_mode & S_IFMT) != S_IFDIR)
+                               continue;
+                       addfold(dir->d_name);
+               }
+               closedir(dirp);
+               for(i = 0; i < foldp; i++) {
+                       pfold(folds[i], 0); fflush(stdout);
+               }
+               if(!totonly)
+                       printf("\n\t\t     ");
+               printf("TOTAL= %3d message%c in %d Folder%s.\n",
+                       msgtot, msgtot!=1? 's':' ',
+                       foldtot, foldtot!=1? "s":"");
+       } else  {
+               hdrflag++;
+               if(argfolder)
+                       cp = copy(argfolder, folder);
+               else
+                       cp = copy(m_getfolder(), folder);
+               if(up) {
+                       while(cp > folder && *cp != '/') --cp;
+                       if(cp > folder)
+                               *cp = 0;
+                       argfolder = folder;
+               } else if(down) {
+                       copy(listname, copy("/", cp));
+                       argfolder = folder;
+               }
+               if(pfold(folder, curm) && argfolder)
+                       m_replace(pfolder, argfolder);
+       }
+
+ leave:
+       m_update();
+       done(0);
+}
+
+
+addfold(fold)
+char *fold;
+{
+       register int i,j;
+       register char *cp;
+
+       if(foldp >= NFOLDERS) {
+               fprintf(stderr, "More than %d folders!!\n", NFOLDERS);
+               return(1);
+       }
+       cp = getcpy(fold);
+       for(i = 0; i < foldp; i++)
+               if(compare(cp, folds[i]) < 0) {
+                       for(j = foldp - 1; j >= i; j--)
+                               folds[j+1] = folds[j];
+                       foldp++;
+                       folds[i] = cp;
+                       return(0);
+               }
+       folds[foldp++] = cp;
+       return(0);
+}
+
+
+pfold(fold, curm)
+char *fold;
+{
+       register char *mailfile;
+       register int msgnum, hole;
+       char newmsg[8], oldmsg[8];
+
+       mailfile = m_maildir(fold);
+       if(chdir(mailfile) < 0) {
+               fprintf(stderr, "Can't chdir to: ");
+               perror(mailfile);
+               return(0);
+       }
+       if(fshort) {
+               printf("%s\n", fold);
+               return(0);
+       }
+       mp = m_gmsg(fold);
+       foldtot++;
+       msgtot += mp->nummsg;
+       if (debug)
+               printf("pfold: %s message flags: 0%o\n", fold, mp->msgflags);
+       if(fpack && (mp->msgflags & READONLY) == 0) {
+           if (debug) {
+               printf("Would normally be packing folder %s\n", fold);
+               return;
+           }
+           for(msgnum = mp->lowmsg, hole = 1; msgnum <= mp->hghmsg; msgnum++) {
+               if(mp->msgstats[msgnum]&EXISTS) {
+                       if(msgnum != hole) {
+                               copy(m_name(hole), newmsg);
+                               copy(m_name(msgnum), oldmsg);
+                               if(link(oldmsg, newmsg) == -1 ||
+                                  unlink(oldmsg) == -1) {
+                                       fprintf(stderr, "Error moving %s to ", oldmsg);
+                                       perror(newmsg);
+                                       done(1);
+                               }
+                               mp->msgstats[hole] = mp->msgstats[msgnum];
+                               if(msgnum == mp->lowsel)
+                                       mp->lowsel = hole;
+                               if(msgnum == mp->hghsel)
+                                       mp->hghsel = hole;
+                       }
+                       hole++;
+               }
+           }
+           if(mp->nummsg > 0) {
+               mp->lowmsg = 1;
+               mp->hghmsg = hole - 1;
+           }
+       }
+       if(totonly)
+               goto out;
+       if(curm) {
+               if(!m_convert(curm))
+                       return(0);
+               if(mp->numsel > 1) {
+                       fprintf(stderr, "Can't set current msg to range: %s\n", curm);
+                       return(0);
+               }
+               m_setcur(mp->curmsg = mp->hghsel);
+       }
+       if(!hdrflag++)
+  printf("\t\tFolder   # of messages   ( range ); cur msg (other files)\n");
+       printf("%22s", fold);
+       if(strcmp(folder, fold) == 0)
+               printf("+ ");
+       else
+               printf("  ");
+       if(mp->hghmsg == 0)
+               printf("has  no messages");
+       else {
+               printf("has %3d message%s (%3d-%3d)",
+                       mp->nummsg, (mp->nummsg==1)?" ":"s",
+                       mp->lowmsg, mp->hghmsg);
+               if(mp->curmsg >= mp->lowmsg && mp->curmsg <= mp->hghmsg)
+                       printf("; cur=%3s", m_name(mp->curmsg));
+       }
+       if(mp->selist || mp->others) {
+               printf("; (");
+               if(mp->selist) {
+                       printf("%s", listname);
+                       if(mp->others)
+                               printf(", ");
+               }
+               if(mp->others)
+                       printf("others");
+               putchar(')');
+       }
+       putchar('.');
+       putchar('\n');
+out:
+       free(mp);
+       mp = 0;
+       return(1);
+}
+
+
+compare(s1, s2)
+char *s1, *s2;
+{
+       register char *c1, *c2;
+       register int i;
+
+       c1 = s1; c2 = s2;
+       while(*c1 || *c2)
+               if(i = *c1++ - *c2++)
+                       return(i);
+       return(0);
+}
diff --git a/docs/historical/2.9BSD/cmds/forw.c b/docs/historical/2.9BSD/cmds/forw.c
new file mode 100644 (file)
index 0000000..636efe0
--- /dev/null
@@ -0,0 +1,316 @@
+#ifndef lint
+static char sccsid[] = "@(#)forw.c     4.1 2/23/83";
+#endif
+
+#include "mh.h"
+#include <stdio.h>
+#include <signal.h>
+#include <strings.h>
+
+#define NONE 0
+#define NOUSE 0
+
+/* #define TEST 1 */
+
+int *vec[MAXARGS];
+struct msgs *mp;
+char drft[128];
+int inplace;            /* preserve links in anno */
+
+char    *anyl[] = {
+       "no",   0,
+       "yes",  0,
+       "list", 0,
+       0,
+};
+
+char    *anyv[] = {
+       "no",           0,
+       "yes",          0,
+       "verbose",      0,
+       0,
+};
+
+struct swit switches[] = {
+       "all",               -3,      /* 0 */
+       "annotate",           0,      /* 1 */
+       "noannotate",         0,      /* 2 */
+       "editor editor",      0,      /* 3 */
+       "form formfile",      0,      /* 4 */
+       "inplace",            0,      /* 5 */
+       "noinplace",          0,      /* 6 */
+       "help",               4,      /* 7 */
+       0,                    0
+};
+
+char *aleqs[] = {
+       "list",              0,         /* 0 */
+       "edit [<editor>]",   0,         /* 1 */
+       "quit [delete]",     0,         /* 2 */
+       "send [verbose]",    0,         /* 3 */
+       0
+};
+
+
+main(argc, argv)
+char *argv[];
+{
+       char *folder, *maildir, *msgs[100], *ed, *form;
+       register int msgnum;
+       register char *cp, **ap;
+       int msgp, status, anot;
+       int in, out, intr;
+       int pid, wpid, msgcnt;
+       char *arguments[50], **argp;
+       char numbuf[5];
+
+#ifdef NEWS
+       m_news();
+#endif
+       form = 0; anot = 0; folder = 0; msgp = 0; ed = 0;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                            /* unknown */
+                       case -1:fprintf(stderr, "forw: -%s unknown\n", cp);
+                               goto leave;
+                                                            /* -all */
+                       case 0: fprintf(stderr, "\"-all\" changed to \"all\"\n");
+                               goto leave;
+                       case 1: anot = 1;  continue;         /* -annotate */
+                       case 2: anot = 0;  continue;         /* -noannotate */
+                       case 3: if(!(ed = *argp++)) {        /* -editor */
+      missing:  fprintf(stderr, "forw: Missing argument for %s switch\n", argp[-2]);
+                                       goto leave;
+                               }
+                               continue;
+                       case 4: if(!(form = *argp++))        /* -form */
+                                       goto missing;
+                               continue;
+                       case 5: inplace = 1;  continue;      /* -inplace */
+                       case 6: inplace = 0;  continue;      /* -noinplace */
+                                                            /* -help */
+                       case 7: help("forw   [+folder] [msgs] [switches]",
+                                    switches);
+                               goto leave;
+                       }
+               if(*cp == '+') {
+                       if(folder) {
+                               fprintf(stderr, "Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               folder = cp + 1;
+               } else
+                       msgs[msgp++] = cp;
+       }
+       if(!msgp)
+               msgs[msgp++] = "cur";
+       if(!folder)
+               folder = m_getfolder();
+       maildir = m_maildir(folder);
+       if(chdir(maildir) < 0) {
+               fprintf(stderr, "Can't chdir to: ");
+               perror(maildir);
+               goto leave;
+       }
+       if(!(mp = m_gmsg(folder))) {
+               fprintf(stderr, "Can't read folder!?\n");
+               goto leave;
+       }
+       if(mp->hghmsg == 0) {
+               fprintf(stderr, "No messages in \"%s\".\n", folder);
+               goto leave;
+       }
+       for(msgnum = 0; msgnum < msgp; msgnum++)
+               if(!m_convert(msgs[msgnum]))
+                       goto leave;
+       if(mp->numsel == 0) {
+               fprintf(stderr, "forw: italian salami.\n");      /* never get here */
+               goto leave;
+       }
+       if(form) {
+               if((in = open(m_maildir(form), 0)) < 0) {
+                       fprintf(stderr, "forw: Can't open form file: %s\n", form);
+                       goto leave;
+               }
+       } else if((in = open(m_maildir(components), 0)) < 0 &&
+                  (in = open(stdcomps, 0)) < 0) {
+                       fprintf(stderr, "forw: Can't open default components file!!\n");
+                       goto leave;
+       }
+       copy(m_maildir(draft), drft);
+       if((out = open(drft, 0)) >= 0) {
+               if(!fdcompare(in, out)) {
+                       cp = concat("\"", drft, "\" exists; Delete? ", 0);
+                       while((msgnum = gans(cp, anyl)) == 2)
+                               showfile(drft);
+                       if(!msgnum)
+                               return;
+               }
+               close(out);
+       }
+       if((out = creat(drft, m_gmprot())) < 0) {
+               fprintf(stderr, "Can't create \"%s\"\n", drft);
+               goto leave;
+       }
+       cpydata(in, out);
+       close(in);
+       for(msgcnt = 1, msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
+               if(mp->msgstats[msgnum]&SELECTED)  {
+                       if((in = open(cp = m_name(msgnum), 0)) < 0) {
+                               fprintf(stderr, "Can't open message \"%s\"\n", cp);
+                               unlink(drft);
+                               goto leave;
+                       }
+                       type(out, "\n\n-------");
+                       if(msgnum == mp->lowsel) {
+                               type(out, " Forwarded Message");
+                               if(mp->numsel > 1)
+                                       type(out, "s");
+                       } else {
+                               type(out, " Message ");
+                               sprintf(numbuf, "%d", msgcnt);
+                               type(out, numbuf);
+                       }
+                       type(out, "\n\n");
+                       cpydata(in, out);
+                       close(in);
+                       msgcnt++;
+               }
+       type(out, "\n\n------- End of Forwarded Message");
+       if(mp->numsel > 1)
+               type(out, "s");
+       type(out, "\n");
+       close(out);
+       m_replace(pfolder, folder);
+       if(mp->lowsel != mp->curmsg)
+               m_setcur(mp->lowsel);
+       if(m_edit(&ed, drft, NOUSE, NONE) < 0)
+               goto leave;
+
+#ifdef TEST
+       fprintf(stderr, "!! Test Version of SEND Being Run !!\n");
+       fprintf(stderr, "   Send verbose !\n\n");
+#endif
+    for(;;) {
+       if(!(argp = getans("\nWhat now? ", aleqs)))
+               goto leave;
+       switch(smatch(*argp, aleqs)) {
+               case 0: showfile(drft);                         /* list */
+                       break;
+               case 1: if(*++argp)                             /* edit */
+                               ed = *argp;
+                       if(m_edit(&ed, drft, NOUSE, NONE) == -1)
+                               goto leave;
+                       break;
+               case 2: if(*++argp && *argp[0] == 'd')          /* quit */
+                               if(unlink(drft) == -1)  {
+                                       fprintf(stderr, "Can't unlink %s ", drft);
+                                       perror("");
+                               }
+                       goto leave;
+               case 3: if(*++argp) cp = *argp;  else cp = "";  /* send */
+
+                       if(!mp->msgflags&READONLY) {    /* annotate first */
+                           if(anot > 0) {
+                               while((pid = fork()) == -1) sleep(5);
+                               if(pid) {
+                                       while(wpid=wait((int *)NULL)!= -1 && wpid!= pid);
+                                       doano();
+                                       goto leave;
+                               }
+                           }
+                       }
+                       if(!m_send(cp, drft))
+                               goto leave;
+               default:fprintf(stderr, "forw: illegal option\n");       /*##*/
+                       break;
+       }
+    }
+
+ leave:
+       m_update();
+       done(0);
+}
+
+
+cpydata(in, out)
+{
+       char buf[BUFSIZ];
+       register int i;
+
+       do
+               if((i = read(in, buf, sizeof buf)) > 0)
+                       write(out, buf, i);
+       while(i == sizeof buf);
+}
+
+
+doano()
+{
+       FILE *in;
+       char name[NAMESZ], field[256];
+       register int ind, state;
+       register char *text;
+
+       if(stat(drft, field) != -1) {
+               fprintf(stderr, "%s not sent-- no annotations made.\n", drft);
+               return;
+       }
+       text = copy(drft, field);
+       text[1] = 0;
+       do
+               *text = text[-1];
+       while(--text >= field && *text != '/');
+       *++text =
+#ifdef UCB
+               '#';
+#else
+               ',';                  /* New backup convention */
+#endif
+       if((in = fopen(field, "r")) == NULL) {
+               fprintf(stderr, "Can't open "); perror(field);
+               return;
+       }
+       state = FLD;
+       text = 0;
+   for(;;) switch(state = m_getfld(state, name, field, sizeof field, in)) {
+
+       case FLD:
+       case FLDEOF:
+       case FLDPLUS:
+               if(uleq(name, "to") || uleq(name, "cc") == 0) {
+                       if(state == FLD) {
+                               text = add(name, text);
+                               text = add(":", text);
+                       }
+                       text = add(field, text);
+               }
+               if(state == FLDEOF)
+                       goto out;
+               continue;
+       case BODY:
+       case BODYEOF:
+               goto out;
+       default:
+               fprintf(stderr, "Getfld returned %d\n", state);
+               return;
+       }
+
+out:
+       fclose(in);
+
+       for(ind = mp->lowsel; ind <= mp->hghsel; ind++)
+               if(mp->msgstats[ind] & SELECTED)
+                       annotate(m_name(ind), "Forwarded", text, inplace);
+}
diff --git a/docs/historical/2.9BSD/cmds/grep.c b/docs/historical/2.9BSD/cmds/grep.c
new file mode 100644 (file)
index 0000000..314d357
--- /dev/null
@@ -0,0 +1,281 @@
+#include <stdio.h>
+#define        CCHR    2
+#define        CDOT    4
+#define        CCL     6
+#define        NCCL    8
+#define        CDOL    10
+#define        CEOF    11
+
+#define        STAR    01
+
+#define LBSIZE  1024
+#define        ESIZE   256
+
+char    ibuf[BUFSIZ];
+char   expbuf[ESIZE];
+char   linebuf[LBSIZE+1];
+int    circf;
+
+char cc[] = {
+       0000,0001,0002,0003,0004,0005,0006,0007,
+       0010,0011,0012,0013,0014,0015,0016,0017,
+       0020,0021,0022,0023,0024,0025,0026,0027,
+       0030,0031,0032,0033,0034,0035,0036,0037,
+       0040,0041,0042,0043,0044,0045,0046,0047,
+       0050,0051,0052,0053,0054,0055,0056,0057,
+       0060,0061,0062,0063,0064,0065,0066,0067,
+       0070,0071,0072,0073,0074,0075,0076,0077,
+       0100,0141,0142,0143,0144,0145,0146,0147,
+       0150,0151,0152,0153,0154,0155,0156,0157,
+       0160,0161,0162,0163,0164,0165,0166,0167,
+       0170,0171,0172,0133,0134,0135,0136,0137,
+       0140,0141,0142,0143,0144,0145,0146,0147,
+       0150,0151,0152,0153,0154,0155,0156,0157,
+       0160,0161,0162,0163,0164,0165,0166,0167,
+       0170,0171,0172,0173,0174,0175,0176,0177,
+};
+
+
+compile(astr)
+char *astr;
+{
+       register c;
+       register char *ep, *sp;
+       char *lastep;
+       int cclcnt;
+
+       ep = expbuf;
+       sp = astr;
+       if (*sp == '^') {
+               circf++;
+               sp++;
+       }
+       for (;;) {
+               if (ep >= &expbuf[ESIZE])
+                       goto cerror;
+               if ((c = *sp++) != '*')
+                       lastep = ep;
+               switch (c) {
+
+               case '\0':
+                       *ep++ = CEOF;
+                       return(1);
+
+               case '.':
+                       *ep++ = CDOT;
+                       continue;
+
+               case '*':
+                       if (lastep==0)
+                               goto defchar;
+                       *lastep |= STAR;
+                       continue;
+
+               case '$':
+                       if (*sp != '\0')
+                               goto defchar;
+                       *ep++ = CDOL;
+                       continue;
+
+               case '[':
+                       *ep++ = CCL;
+                       *ep++ = 0;
+                       cclcnt = 1;
+                       if ((c = *sp++) == '^') {
+                               c = *sp++;
+                               ep[-2] = NCCL;
+                       }
+                       do {
+                               *ep++ = c;
+                               cclcnt++;
+                               if (c=='\0' || ep >= &expbuf[ESIZE])
+                                       goto cerror;
+                       } while ((c = *sp++) != ']');
+                       lastep[1] = cclcnt;
+                       continue;
+
+               case '\\':
+                       if ((c = *sp++) == '\0')
+                               goto cerror;
+               defchar:
+               default:
+                       *ep++ = CCHR;
+                       *ep++ = c;
+               }
+       }
+    cerror:
+       return(0);
+}
+
+
+execute(file)
+char *file;
+{
+       register char *p1, *p2;
+       register c;
+       int f, body, lf;
+       char *ebp, *cbp;
+
+       if ((f = open(file, 0)) < 0) {
+               fprintf(stderr, "Grep: Can't open %s\n", file);
+               return(0);
+       }
+       body = 0;
+       ebp = ibuf;
+       cbp = ibuf;
+       for (;;) {
+               p1 = linebuf;
+               p2 = cbp;
+               lf = 0;
+               for (;;) {
+                       if (p2 >= ebp) {
+                               if ((c = read(f, ibuf, sizeof ibuf)) <= 0) {
+                                       close(f);
+                                       if(lf) break; /* bodyless comp! */
+                                       return(0);
+                               }
+                               p2 = ibuf;
+                               ebp = ibuf+c;
+                       }
+                       c = *p2++;
+                       if(lf) if(c != ' ' && c != '\t') {
+                               --p2;
+                               break;
+                       } else
+                               lf = 0;
+                       if (c == '\n')
+                               if(body)
+                                       break;
+                               else {
+                                       if(lf) {
+                                               body++;
+                                               break;
+                                       }
+                                       lf++;
+                                       c = ' ';
+                               }
+                       if(c && p1 < &linebuf[LBSIZE-1])
+                               *p1++ = c;
+               }
+               *p1++ = 0;
+               cbp = p2;
+               p1 = linebuf;
+               p2 = expbuf;
+               if (circf) {
+                       if (advance(p1, p2))
+                               goto found;
+                       continue;
+               }
+               /* fast check for first character */
+               if (*p2==CCHR) {
+                       c = p2[1];
+                       do {
+                               if(*p1==c || cc[*p1]==c)
+                                       if (advance(p1, p2))
+                                               goto found;
+                       } while (*p1++);
+                       continue;
+               }
+               /* regular algorithm */
+               do {
+                       if (advance(p1, p2))
+                               goto found;
+               } while (*p1++);
+               continue;
+       found:
+               close(f);
+               return(1);
+       }
+}
+
+
+advance(alp, aep)
+char *alp, *aep;
+{
+       register char *lp, *ep, *curlp;
+       char *nextep;
+
+       lp = alp;
+       ep = aep;
+       for (;;) switch (*ep++) {
+
+       case CCHR:
+               if (*ep++ == *lp++ || ep[-1] == cc[lp[-1]])
+                       continue;
+               return(0);
+
+       case CDOT:
+               if (*lp++)
+                       continue;
+               return(0);
+
+       case CDOL:
+               if (*lp==0)
+                       continue;
+               return(0);
+
+       case CEOF:
+               return(1);
+
+       case CCL:
+               if (cclass(ep, *lp++, 1)) {
+                       ep += *ep;
+                       continue;
+               }
+               return(0);
+
+       case NCCL:
+               if (cclass(ep, *lp++, 0)) {
+                       ep += *ep;
+                       continue;
+               }
+               return(0);
+
+       case CDOT|STAR:
+               curlp = lp;
+               while (*lp++);
+               goto star;
+
+       case CCHR|STAR:
+               curlp = lp;
+               while (*lp++ == *ep || cc[lp[-1]] == *ep) ;
+               ep++;
+               goto star;
+
+       case CCL|STAR:
+       case NCCL|STAR:
+               curlp = lp;
+               while (cclass(ep, *lp++, ep[-1]==(CCL|STAR)));
+               ep += *ep;
+               goto star;
+
+       star:
+               do {
+                       lp--;
+                       if (advance(lp, ep))
+                               return(1);
+               } while (lp > curlp);
+               return(0);
+
+       default:
+               printf("RE botch\n");
+               return(0);
+       }
+}
+
+
+cclass(aset, ac, af)
+char *aset;
+{
+       register char *set, c;
+       register n;
+
+       set = aset;
+       if ((c = ac) == 0)
+               return(0);
+       n = *set++;
+       while (--n)
+               if (*set++ == c)
+                       return(af);
+       return(!af);
+}
diff --git a/docs/historical/2.9BSD/cmds/inc.c b/docs/historical/2.9BSD/cmds/inc.c
new file mode 100644 (file)
index 0000000..5b08907
--- /dev/null
@@ -0,0 +1,331 @@
+#include "mh.h"
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <strings.h>
+#include <signal.h>
+
+char   *anoyes[];       /* Std no/yes gans array        */
+
+extern int errno;
+char    scanl[];
+struct  msgs *mp;
+FILE    *in, *aud;
+struct  stat stbuf;
+char    *locknode;
+int     lockwait;       /* Secs to wait for lock-Def in strings/lockdir.c */
+#define LOCKWAIT (lockwait*5) /* If lock is this old, simply ignore it! */
+
+struct  swit switches[] = {
+       "audit audit-file",     0,      /* 0 */
+       "ms ms-folder",         0,      /* 1 */
+       "help",                 4,      /* 2 */
+       "file mail-file",       0,      /* 3 */
+       0,                      0
+};
+
+#ifdef UNIXCOMP
+char   unixtmp[] = "/tmp/mhXXXXXX";
+#endif
+
+main(argc, argv)
+char *argv[];
+{
+
+       char *newmail, maildir[128], *folder, *from, *audfile, *srcfile;
+       char mailspace[128];
+       char *myname, *savemail;
+       register char *cp;
+       register int i, msgnum;
+       long now;
+       char **ap;
+       char *arguments[50], **argp;
+       int done();
+       long time();
+       int pid, status, fildes;
+       extern char _sobuf[];
+
+       setbuf(stdout, _sobuf);
+#ifdef NEWS
+       m_news();
+#endif
+
+       from = 0; folder = 0; audfile = 0; srcfile = 0;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                            /* unknown */
+                       case -1:fprintf(stderr, "inc: -%s unknown\n", cp);
+                               goto leave;
+                       case 0: if(!(audfile = *argp++)) {   /* -audit */
+      missing:  fprintf(stderr, "inc: Missing argument for %s switch\n", argp[-2]);
+                                       goto leave;
+                               }
+                               continue;
+                       case 1: if(!(from = *argp++))        /* -ms */
+                                       goto missing;
+                               continue;
+                       case 2:                              /* -help */
+                               help("inc [+folder]  [switches]", switches);
+                               goto leave;
+                       case 3:                              /* -file */
+                               if (!(srcfile = *argp++))
+                                       goto missing;
+                               continue;
+                       }
+               if(*cp == '+') {
+                       if(folder) {
+                               fprintf(stderr, "Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               folder = cp + 1;
+               } else {
+                       fprintf(stderr, "Bad arg: %s\n", argp[-1]);
+       fprintf(stderr, "Usage: inc [+folder] [-ms ms-folder] [-audit audit-file]\n");
+                       goto leave;
+               }
+       }
+       if (from && srcfile) {
+               fprintf(stderr, "Only one of \"-ms\" and \"-file\" allowed\n");
+               goto leave;
+       }
+       if(from)
+               newmail = from;
+       else {
+               if((myname = getenv("USER")) == 0) {
+                       fprintf(stderr,
+"Environment Variable \"USER\" Must be set to your login name!\n");
+                       done(1);
+               }
+               if (srcfile) {
+                       newmail = srcfile;
+                       goto statit;
+               }
+               newmail = concat(mailboxes, myname, 0);
+               if (stat(newmail, &stbuf) >= 0
+                   && (stbuf.st_mode & S_IFMT) == S_IFDIR) {
+                       strcpy(mailspace, newmail);
+                       newmail = mailspace;
+                       strcat(newmail, "/");
+                       strcat(newmail, myname);
+               }
+statit:
+               if(stat(newmail, &stbuf) < 0 ||
+                  stbuf.st_size == 0) {
+                       fprintf(stderr, "No Mail to incorporate.\n");
+                       goto leave;
+               }
+       }
+       fildes = -1;
+       if (srcfile)
+               if ((fildes = open(srcfile, 0)) < 0) {
+                       perror(srcfile);
+                       goto leave;
+               }
+       if(!folder) {
+               folder = defalt;
+               if(from && strcmp(from, "inbox") == 0) {
+                       cp = concat("Do you really want to convert from ",
+                               from, " into ", folder, "?? ", 0);
+                       if(!gans(cp, anoyes))
+                               goto leave;
+                       cndfree(cp);
+               }
+       }
+       copy(m_maildir(folder), maildir);
+       if(stat(maildir, &stbuf) < 0) {
+               if(errno != ENOENT) {
+                       fprintf(stderr, "Error on folder ");
+                       perror(maildir);
+                       goto leave;
+               }
+               cp = concat("Create folder \"", maildir, "\"? ", 0);
+               if(!gans(cp, anoyes))
+                       goto leave;
+               if(!makedir(maildir)) {
+                       fprintf(stderr, "Can't create folder \"%s\"\n", maildir);
+                       goto leave;
+               }
+       }
+       if(chdir(maildir) < 0) {
+               fprintf(stderr, "Can't chdir to: ");
+               perror(maildir);
+               goto leave;
+       }
+       if(!(mp = m_gmsg(folder))) {
+               fprintf(stderr, "Can't read folder!?\n");
+               goto leave;
+       }
+                                       /* Lock the mail file */
+       if(!from && !srcfile) {
+               signal(SIGINT, done);
+               cp = concat(lockdir, myname, 0);
+               for(i = 0; i < lockwait; i += 2) {
+                       if(link(newmail, cp) == -1) {
+                               fprintf(stderr, "Mailbox busy...\n");
+                               if(i == 0 && stat(newmail, &stbuf) >= 0)
+                                       if(stbuf.st_ctime + LOCKWAIT < time((long *)0)) {
+                                               unlink(cp);
+                                               fprintf(stderr, "Removing lock.\n");
+                                               continue;
+                                       }
+                               sleep(2);
+                       } else {
+                               locknode = cp;  /* We own the lock now! */
+                               break;
+                       }
+               }
+               if(i >= lockwait) {
+                       fprintf(stderr, "Try again.\n");
+                       done(1);
+               }
+       }
+
+#ifdef UNIXCOMP
+       /*
+        * If trying to be compatible with standard
+        * UNIX mailing scheme, call the program unixtomh
+        * to convert the mailbox to some temporary name.
+        */
+       
+       mktemp(unixtmp);
+       switch  (pid = fork()) {
+       case 0:
+               if (srcfile) {
+                       int nout;
+
+                       if ((nout = creat(unixtmp, 0600)) < 0) {
+                               perror(unixtmp);
+                               _exit(1);
+                       }
+                       close(0);
+                       dup(fildes);
+                       close(fildes);
+                       close(1);
+                       dup(nout);
+                       close(nout);
+                       execl(unixtomh, "unixtomh", 0);
+                       perror(unixtomh);
+                       _exit(1);
+               }
+               execl(unixtomh, "unixtomh", newmail, unixtmp, 0);
+               perror(unixtomh);
+               _exit(1);
+               break;
+
+       case -1:
+               perror("fork");
+               goto leave;
+
+       default:
+               while (wait(&status) != pid)
+                       ;
+               if (status != 0) {
+                       fprintf(stderr, "unixtomh failed!?\n");
+                       goto leave;
+               }
+       }
+       if (fildes >= 0)
+               close(fildes);
+       savemail = newmail;
+       newmail = unixtmp;
+       if((in = fopen(newmail, "r")) == NULL) {
+               fprintf(stderr, "Can't open "); perror(newmail);
+               goto leave;
+       }
+#else
+       if (srcfile)
+               in = fdopen(fildes, "r");
+       else
+               if((in = fopen(newmail, "r")) == NULL) {
+                       fprintf(stderr, "Can't open "); perror(newmail);
+                       goto leave;
+               }
+#endif
+
+       if(audfile) {
+               cp = m_maildir(audfile);
+               if((i = stat(cp, &stbuf)) < 0)
+                       fprintf(stderr, "Creating Receive-Audit: %s\n", cp);
+               if((aud = fopen(cp, "a")) == NULL) {
+                       fprintf(stderr, "Can't append to ");
+                       perror(cp);
+                       goto leave;
+               } else if(i < 0)
+                       chmod(cp, 0600);
+               time(&now);
+               fputs("<<inc>> ", aud);
+               cp = cdate(&now);
+               cp[9] = ' ';
+               fputs(cp, aud);
+               if(from) {
+                       fputs("  -ms ", aud);
+                       fputs(from, aud);
+               }
+               putc('\n', aud);
+       }
+       printf("Incorporating new mail into %s...\n\n", folder);
+       fflush(stdout);
+       msgnum = mp->hghmsg;
+
+       while((i = scan(in, msgnum+1, msgnum+1, msgnum == mp->hghmsg))) {
+               if(i == -1) {
+                       fprintf(stderr, "inc aborted!\n");
+                       if(aud)
+                               fputs("inc aborted!\n", aud);
+                       goto leave;
+               }
+               if(aud)
+                       fputs(scanl, aud);
+               fflush(stdout);
+               msgnum++;
+       }
+
+       fclose(in);
+       if(aud)
+               fclose(aud);
+
+#ifdef UNIXCOMP
+       unlink(newmail);
+       newmail = savemail;
+#endif
+
+       if(!from && !srcfile) {
+               if (unlink(newmail) < 0) {
+                       if((i = creat(newmail, 0600)) >= 0)
+                               close(i);
+                       else
+                               fprintf(stderr, "Error zeroing %s\n", newmail);
+               }
+       }
+
+       i = msgnum - mp->hghmsg;
+       if(!i)
+               fprintf(stderr, "[No messages incorporated.]\n");
+       else {
+               m_replace(pfolder, folder);
+               m_setcur(mp->hghmsg + 1);
+       }
+leave:
+       m_update();
+       done(0);
+}
+
+
+done(status)
+{
+       if(locknode);
+               unlink(locknode);
+       exit(status);
+}
diff --git a/docs/historical/2.9BSD/cmds/install-mh.c b/docs/historical/2.9BSD/cmds/install-mh.c
new file mode 100644 (file)
index 0000000..828eff7
--- /dev/null
@@ -0,0 +1,109 @@
+#include "mh.h"
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+char   *anoyes[];       /* Std no/yes gans array        */
+char   *mypath;
+char    defpath[128];
+
+main(argc, argv)
+char *argv[];
+{
+       register char *cp, *path;
+       register struct node *np;
+       int autof, exitstat;
+       struct stat stbuf;
+       char *geta();
+       extern char _sobuf[];
+
+       setbuf(stdout, _sobuf);
+       autof = (argc == 2 && strcmp(argv[1], "-auto") == 0);
+       exitstat = 1;                 /* Assume errors will occur */
+       mypath = getenv("HOME");
+/***    mypath = getpath(getruid());  /* to prevent recursion via m_getdefs */
+       copy(mh_prof, copy(mypath, defpath));
+       if(stat(defpath, &stbuf) != -1) {
+           if(autof)
+               printf("Install-defs invocation error!\n");
+           else
+               printf("You already have an MH profile... use an editor \
+to modify it.\n");
+           goto leave;
+
+       }
+       if(autof || gans("Do you want help? ", anoyes)) {
+printf("\nPrior to using MH, it is necessary to have a file in your login\n");
+printf("directory (%s) named %s which contains information\n",mypath,mh_prof+1);
+printf("to direct certain MH operations.  The only item which is required\n");
+printf("is the path to use for all MH folder operations. The suggested MH\n");
+printf("path for you is %s/Mail...\n\n", mypath);
+       }
+       cp = concat(mypath, "/", "Mail", 0);
+       if(stat(cp, &stbuf) != -1) {
+           if((stbuf.st_mode&S_IFMT) == S_IFDIR) {
+               cp = concat("You already have the standard MH directory \"",
+                       cp, "\".\nDo you want to use it for MH? ", 0);
+               if(gans(cp, anoyes))
+                   path = "Mail";
+               else
+                   goto xyz;
+           }
+       } else {
+           cp = concat("Do you want the standard MH path \"", mypath,
+                        "/", "Mail\"? ", 0);
+           if(gans(cp, anoyes))
+                   path = "Mail";
+           else {
+    xyz:        if(gans("Do you want a path below your login directory? ",
+                   anoyes)) {
+                   printf("What is the path ??  %s/", mypath);
+                   path = geta();
+               } else {
+                   printf("What is the whole path??  /");
+                   path = concat("/", geta(), 0);
+               }
+           }
+       }
+       chdir(mypath);
+       if(chdir(path) == -1) {
+               cp = concat("\"", path, "\" doesn't exist; Create it? ", 0);
+               if(gans(cp, anoyes))
+                       if(makedir(path) == 0) {
+                               printf("Can't create it!\n");
+                               goto leave;
+                       }
+       } else
+               printf("[Using existing directory]\n");
+
+       np = m_defs = (struct node *) malloc(sizeof *np);
+       np->n_name = "Path";
+       np->n_field = path;
+       np->n_next = 0;
+       m_replace(pfolder, defalt);
+       exitstat = 0;
+
+leave:
+       m_update();
+       done(exitstat);
+}
+
+
+char *geta()
+{
+       static char line[128];
+       register char *cp;
+       register int c;
+
+       fflush(stdout);
+       cp = line;
+       while((c = getchar()) != EOF) {
+               if(c == '\n') {
+                       *cp = 0;
+                       return(line);
+               }
+               if(cp < &line[128])
+                       *cp++ = c;
+       }
+       done(1);
+}
diff --git a/docs/historical/2.9BSD/cmds/mail.c b/docs/historical/2.9BSD/cmds/mail.c
new file mode 100644 (file)
index 0000000..227265f
--- /dev/null
@@ -0,0 +1,157 @@
+#include "mh.h"
+#include <stdio.h>
+#include <signal.h>
+
+#define NUMTOS  10              /* Number of to's & cc's accepted */
+
+char    tmpfil[32];
+int     exitstat = 1;
+char    *subject, *cc, *body;
+
+struct swit switches[] = {
+       "body",         0,      /* 0 */
+       "cc",           0,      /* 1 */
+       "subject",      0,      /* 2 */
+       "help",         4,      /* 3 */
+       0,              0
+};
+
+main(argc, argv)
+int argc;
+char *argv[];
+{
+       register FILE *out;
+       register int i, cnt;
+       register char *cp;
+       int pid, status, top, ccp, sig(), somebody = 0;
+       char buf[BUFSIZ], *tos[NUMTOS], *ccs[NUMTOS], **argp;
+
+       top = 0;
+       ccp = -1;               /* -1 -> collecting TOs */
+       if(argc == 1) {         /* Just call inc to read mail */
+               execl("/bin/inc", "inc", 0);
+               execl("/usr/bin/inc", "inc", 0);
+               perror("inc");
+               done(exitstat);
+       }
+       argp = argv + 1;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);  /* ambiguous */
+                               done(exitstat);
+                                                       /* unknown */
+                       case -1:fprintf(stderr, "send: -%s unknown\n", cp);
+                               done(exitstat);
+                                                       /* -body */
+                       case 0: if((body = *argp++) == 0) {
+                    missing:           fprintf(stderr, "Mail: Missing %s arg\n", cp);
+                                       done(exitstat);
+                               }
+                               continue;
+                                                       /* -cc */
+                       case 1: ccp = 0;                /* Now collecting ccs */
+                               continue;
+                                                       /* -subject */
+                       case 2: if((subject = *argp++) == 0)
+                                       goto missing;
+                               continue;
+                                                       /* -help */
+                       case 3: help("mail [switches] users ...",
+                                    switches);
+                               done(0);
+                       }
+               else {
+                       if(ccp >= 0) {                  /* If getting ccs..*/
+                               if(ccp < NUMTOS)
+                                       ccs[ccp++] = cp;
+                               else {
+                                       fprintf(stderr, "Mail: Too many ccs\n");
+                                       done(exitstat);
+                               }
+                       } else {                        /* Else, to */
+                               if(top < NUMTOS)
+                                       tos[top++] = cp;
+                               else {
+                                       fprintf(stderr, "Mail: Too many tos\n");
+                                       done(exitstat);
+                               }
+                       }
+               }
+       }
+                                       /* Create a mail temp file */
+       sprintf(tmpfil, "/tmp/%s", makename("mail", ".tmp"));
+       if((out = fopen(tmpfil, "w")) == NULL) {
+               perror(tmpfil);
+               done(exitstat);
+       }
+       signal(SIGINT, sig);            /* Clean up if user <del>s out */
+       fprintf(out, "To: ");           /* Create to list */
+       for(i = 0; i < top;) {
+               fprintf(out, "%s", tos[i]);
+               if(++i < top)
+                       fprintf(out, ", ");
+       }
+       fprintf(out, "\n");
+       if(ccp > 0) {
+               fprintf(out, "Cc: ");   /* Create cc list if needed */
+               for(i = 0; i < ccp;) {
+                       fprintf(out, "%s", ccs[i]);
+                       if(++i < ccp)
+                               fprintf(out, ", ");
+               }
+               fprintf(out, "\n");
+       }
+       if(subject)                     /* Create subject if needed */
+               fprintf(out, "Subject: %s\n", subject);
+
+       fprintf(out, "\n");
+
+       if(body) {                      /* Use body if I have it, */
+               somebody++;
+               fprintf(out, "%s\n", body);
+       } else {                        /* Otherwise, get a body */
+               while((cnt = read(0, buf, sizeof buf)) > 0) {
+                       somebody++;
+                       if(!fwrite(buf, cnt, 1, out)) {
+                               perror(tmpfil);
+                               sig();
+                       }
+               }
+       }
+
+       if(ferror(out)) {               /* Check that all wrote well */
+               fprintf(stderr, "Error writing tmp file\n");
+               sig();
+       }
+       fclose(out);
+       if(!somebody)                   /* If NO body, then don't send */
+               sig();                  /*  To be compatible with BELL mail */
+       while((i = fork()) == -1) {     /* Now, deliver the mail */
+               fprintf(stderr, "Waiting for a fork...\n");
+               sleep(2);
+       }
+       if(i == 0) {                    /* Call deliverer in child */
+               execl(mh_deliver, mh_deliver, tmpfil, 0);
+               perror(mh_deliver);
+               done(exitstat);
+       }
+       signal(SIGINT, SIG_IGN);
+       while((pid = wait(&status)) != -1 && pid != i) ;
+       if(status) {                    /* And save mail if delivery failed */
+               signal(SIGINT, SIG_DFL);
+               fprintf(stderr, "Letter saved in dead.letter\n");
+               execl("/bin/mv", "mv", tmpfil, "dead.letter", 0);
+               execl("/usr/bin/mv", "mv", tmpfil, "dead.letter", 0);
+               perror("/bin/mv");
+               done(exitstat);
+       }
+       exitstat = 0;
+       sig();
+}
+
+sig()
+{
+       unlink(tmpfil);
+       done(exitstat);
+}
diff --git a/docs/historical/2.9BSD/cmds/mh.h b/docs/historical/2.9BSD/cmds/mh.h
new file mode 100644 (file)
index 0000000..fba207f
--- /dev/null
@@ -0,0 +1,154 @@
+#define ALL ""
+
+#define MAXARGS 1000    /* Max messages to exec                 */
+
+#define EXISTS    01    /* Flag bits in msgstats-- Deleted is   */
+#define DELETED   02    /*      undefined currently             */
+#define SELECTED  04    /* Message selected by an arg           */
+
+#define READONLY  01    /* No write access to folder            */
+#define DEFMOD    01    /* In-core profile has been modified    */
+
+/*#define NEWS     1    /* Define for news inclusion            */
+
+struct  swit {
+       char *sw;
+       int minchars;
+};
+
+/*
+ * m_gmsg() returns this structure.  It contains the per folder
+ * information which is obtained from reading the folder directory.
+ */
+
+struct  msgs {
+       int     hghmsg;         /* Highest msg in directory     */
+       int     nummsg;         /* Actual Number of msgs        */
+       int     lowmsg;         /* Lowest msg number            */
+       int     curmsg;         /* Number of current msg if any */
+       int     lowsel;         /* Lowest selected msg number   */
+       int     hghsel;         /* Highest selected msg number  */
+       int     numsel;         /* Number of msgs selected      */
+       char   *foldpath;       /* Pathname of folder           */
+       char    selist,         /* Folder has a "select" file   */
+               msgflags,       /* Folder status bits           */
+               filler,
+               others;         /* Folder has other file(s)     */
+       char    msgstats[1];    /* Stat bytes for each msg      */
+};
+
+               /* m_getfld definitions and return values       */
+
+#define NAMESZ  64      /* Limit on component name size         */
+#define LENERR  -2      /* Name too long error from getfld      */
+#define FMTERR  -3      /* Message Format error                 */
+
+                       /* m_getfld return codes                */
+#define FLD      0      /* Field returned                       */
+#define FLDPLUS  1      /* Field " with more to come            */
+#define FLDEOF   2      /* Field " ending at eom                */
+#define BODY     3      /* Body  " with more to come            */
+#define BODYEOF  4      /* Body  " ending at eom                */
+#define FILEEOF  5      /* Reached end of input file            */
+
+/*
+ * These standard strings are defined in strings.a.  They are the
+ * only system-dependent parameters in MH, and thus by redefining
+ * their values and reloading the various modules, MH will run
+ * on any system.
+ */
+
+extern char
+       *components,    /* Name of user's component file (in mh dir) */
+       *current,       /* Name of current msg file in a folder */
+       *defalt,        /* Name of the std folder (inbox)       */
+       *distcomps,     /* Name of `dist' components file       */
+       *draft,         /* Name of the normal draft file        */
+       *fileproc,      /* Path of file program                 */
+       *foldprot,      /* Default folder protection            */
+       *hostname,      /* Local net host name                  */
+       *installproc,   /* Name of auto-install program path    */
+       *listname,      /* Default selection list folder name   */
+       *lockdir,       /* Dir for lock files (Same fs as mailboxes)*/
+       *lsproc,        /* Path of the Harvard ls program       */
+       *mailboxes,     /* Incoming mail directory              */
+       *mh_prof,       /* Name of users profile file           */
+       *mh_deliver,    /* Name of deliverer for mh             */
+       *mhnews,        /* Name of MH news file                 */
+       *msgprot,       /* Default message protection (s.a. 0664) */
+       *pfolder,       /* Name of current folder profile entry */
+       *prproc,        /* Path of the pr program               */
+       *scanproc,      /* Path of the scan program             */
+       *showproc,      /* Path of the type (l) program         */
+       *sendproc,      /* Path of the send message program     */
+       *stdcomps,      /* Std comp file if missing user's own  */
+       *stddcomps,     /* Std dist file if missing user's own  */
+       *sysed,         /* Path of the std (ned) editor         */
+/* Just about every program uses this also                      */
+       *mypath;        /* User's log-on path                   */
+
+#ifdef UNIXCOMP
+char *unixtomh;                /* Path of program to convert UNIX style
+                          mailboxes to MH style mailboxes */
+char *Mailprog;                /* Path of program to do actual mailing */
+char *localname;       /* Name of local machine on local net */
+#endif
+
+/*
+ * node structure used to hold a linked list of the users profile
+ * information taken from logpath/.mh_prof.
+ */
+
+struct node {
+       struct node *n_next;
+       char        *n_name,
+                   *n_field;
+} *m_defs;
+
+char  def_flags;
+
+
+/*
+ * The first char in the mhnews file indicates whether the program
+ * calling m_news() should continue running or halt.
+ */
+
+#define NEWSHALT        '!'     /* Halt after showing the news  */
+#define NEWSCONT        ' '     /* Continue  (ditto)            */
+#define NEWSPAUSE       '\001'  /* Pause during news output...  */
+
+
+/*
+ * Miscellaneous Defines to speed things up
+ */
+
+#define error(str) { fprintf(stderr, "%s\n", str); exit(-1); }
+
+/*
+ * Routine type declarations -- needed by version 7 compiler
+ */
+
+char **brkstring();
+char *m_maildir();
+char *m_find();
+char *m_name();
+char *concat();
+char *getcpy();
+char *trimcpy();
+char *add();
+char *invo_name();
+char **copyip();
+char *getcpy();
+char *m_getfolder();
+struct msgs *m_gmsg();
+char *copy();
+char **getans();
+char *cdate();
+char *makename();
+char *r1bindex();
+
+/*
+ * Routine type declarations -- SHOULD BE GLOBAL
+ */
+char *getenv();
+
diff --git a/docs/historical/2.9BSD/cmds/news.c b/docs/historical/2.9BSD/cmds/news.c
new file mode 100644 (file)
index 0000000..b3bbbd4
--- /dev/null
@@ -0,0 +1,301 @@
+#include "mh.h"
+#include <stdio.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <dir.h>
+#include <strings.h>
+#define max(a,b) (a > b ? a : b)
+
+#define NEWSP   "/usr/spool/newnews"
+#define MAXTOPICS       20      /* Enough for a while */
+
+char   *mypath;
+int     vecp, topicp;
+char    *topics[MAXTOPICS+1];
+char    *vec[MAXARGS];
+struct msgs *mp;
+int     fdisplay, fcheck, fupdate, fsend, freview, fbody;  /* flags */
+int     frevback;
+int     hit;
+
+struct nts {
+       char    *t_name;
+       int     t_num;
+} nts[MAXTOPICS+1], *check();
+
+struct swit switches[] = {
+       "add",          -1,     /* 0 */
+       "body",         -1,     /* 1 */
+       "check",        0,      /* 2 */
+       "display",      0,      /* 3 */
+       "review [#]",   0,      /* 4 */
+       "send topic ...",0,     /* 5 */
+       "topics",       0,      /* 6 */
+       "update",       0,      /* 7 */
+       "help",         4,      /* 8 */
+       0,              0,
+};
+
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       register int i;
+       register char *cp, **ap;
+       char *arguments[50], **argp;
+       extern char _sobuf[];
+
+       setbuf(stdout, _sobuf);
+#ifdef NEWS
+       m_news();
+#endif
+       vecp = 2;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               done(0);
+                                                            /* unknown */
+                       case -1:vec[vecp++] = --cp; continue;
+                       case 0:
+                       case 5: fsend++; continue;
+                       case 1: fbody++;
+                               vec[vecp++] = --cp; continue;
+                       case 2: fcheck++; continue;
+                       case 3: fdisplay++; continue;
+                       case 4: freview++;
+                               if(**argp >= '0' && **argp <= '9')
+                                       frevback = atoi(*argp++);
+                               continue;
+                       case 7: fupdate++; continue;
+
+                       case 8:
+  help("news [topic ...] [switches] [switches for \"c\" or \"mail\" ]",
+                                    switches);
+                               putchar('\n');
+                       case 6:
+                               printf("Topic    items\n\n"); fflush(stdout);
+                               getnts();
+                               for(i = 0; nts[i].t_name[0]; i++)
+                                       printf("%-9s%3d\n", nts[i].t_name,
+                                               nts[i].t_num);
+                               done(0);
+                       }
+               else
+                       if(vecp == 2)
+                               topics[topicp++] = cp;
+                       else
+                               vec[vecp++] = cp;
+       }
+       getnts();
+       if(fsend) {
+               if(topicp == 0) {
+                       fprintf(stderr, "Usage: news -send topic [mail switches]\n");
+                       done(1);
+               }
+               for(i = 0; i < topicp; i++)
+                       if(check(topics[i]))
+                               send(topics[i]);
+                       else
+                               printf("Unknown topic: %s\n", topics[i]);
+               done(0);
+       }
+       if(!topicp)
+               for(i = 0; nts[i].t_name[0]; i++)
+                       disp(nts[i].t_name, 0);
+       else
+               for(i = 0; i < topicp; i++)
+                       if(check(topics[i]) == NULL)
+                               printf("Topic: %s unknown.\n", topics[i]);
+                       else
+                               disp(topics[i], 1);
+       if(fcheck) {
+               if(hit)
+                       printf(".\n");
+       } else if(!hit && !topicp && !fupdate && !fdisplay)
+               nonews();
+       m_update();
+       done(0);
+}
+
+
+getnts()
+{
+       struct direct *dir;
+       struct stat st;
+       register struct nts *t;
+       register DIR *d;
+       char tbuf[16 + 16];
+
+       t = nts;
+       if((d = opendir(NEWSP)) == 00) {
+               fprintf(stderr, "Can't open ");
+               perror(NEWSP);
+               done(1);
+       }
+       while (dir = readdir(d))
+               if(dir->d_ino && dir->d_name[0] != '.') {
+                       t->t_name = (char *)malloc(dir->d_namlen + 1);
+                       if (t->t_name == 0)
+                               break;
+                       strcpy(t->t_name, dir->d_name);
+                       t++;
+               }
+       closedir(d);
+       for(t = nts; t->t_name[0]; t++) {
+               sprintf(tbuf, "%s/.%.14s", NEWSP, t->t_name);
+               if(stat(tbuf, &st) != -1)
+                       t->t_num = st.st_size;
+       }
+}
+
+struct nts *
+check(topic)
+       char *topic;
+{
+       register struct nts *t;
+
+       for(t = nts; t->t_name[0]; t++)
+               if(strcmp(topic, t->t_name) == 0)
+                       return t;
+       return 0;
+}
+
+
+disp(topic, argflg)
+       register char *topic;
+       int argflg;
+{
+       register struct nts *t;
+       register char *cp, *np;
+       register int msgnum;
+       int high;
+       char buf[128];
+
+       if((t = check(topic)) == 0)
+               fprintf(stderr, "HUH?\n");
+       if((cp = m_find(np = concat("news-", topic, 0))) == NULL)
+               cp = "0";
+       high = atoi(cp);
+       if(fcheck) {
+               if(t->t_num > high) {
+                       if(!hit++)
+                               printf("Unread news in");
+                       if(hit > 1)
+                               printf(",");
+                       printf(" %s", topic);
+               }
+               return;
+       }
+       if(fupdate) {
+               if(t->t_num > high) {
+                       m_replace(np, getcpy(m_name(t->t_num)));
+                       printf("Skipping %d items in %s.\n",
+                               t->t_num - high, topic);
+               }
+               return;
+       }
+       if(freview)
+               if(frevback)
+                       msgnum = max(high - frevback, 0);
+               else
+                       msgnum = 0;
+       else
+               msgnum = high;
+/***    msgnum = freview? frevback? high - frevback : 0 : high; */
+       if(msgnum >= t->t_num) {
+               if(argflg)
+                       printf("%s: no new news.\n", topic);
+               return;
+       }
+       sprintf(buf, "%s/%s", NEWSP, topic);
+       if(chdir(buf) == -1) {
+               perror(buf);
+               return;
+       }
+       vec[1] = showproc;
+       for( ; msgnum < t->t_num;) {
+               cp = m_name(++msgnum);
+               if(hit) {
+                       printf("\nPress <return> for %s:%s...", topic, cp);
+                       fflush(stdout);
+                       read(0, buf, sizeof buf);
+               } else
+                       printf("News item %s:%s\n", topic, cp);
+               if(msgnum > high) {
+                       m_replace(np, getcpy(cp));
+                       m_update();
+               }
+               vec[vecp] = cp;
+               putchar('\n');
+               call(vec + 1);
+               hit = 1;
+       }
+}
+
+
+call(vector)
+       char **vector;
+{
+       register int pid, child;
+       char path[32];
+       int status;
+
+       fflush(stdout);
+       while((child = fork()) == -1) {
+               printf("No forks...\n"); fflush(stdout);
+               sleep(2);
+       }
+       if(child == 0) {
+               execv(vector[0], vector);
+               perror(vector[0]);
+               done(1);
+       }
+       while((pid = wait(&status)) != -1 && pid != child) ;
+       if(pid == -1 || status) {
+               fprintf(stderr, "Abnormal termination from %s\n", vector[0]);
+               done(1);
+       }
+}
+
+char    *mailproc;
+
+send(topic)
+       register char *topic;
+{
+       vec[0] = mailproc;
+       vec[1] = concat("news.", topic, 0);
+       if(!fbody)
+               printf("Enter text for %s\n", topic);
+       call(vec);
+       free(vec[1]);
+}
+
+
+char    *nons[] = {
+       "No new news",
+       "No news to peruse",
+       "Only old news",
+       "News shortage",
+       "News reporters on strike",
+       "Report your own news",
+       "News presses broken"
+};
+#define NONS    (sizeof nons/ sizeof nons[0])
+
+nonews()
+{
+#include <sys/timeb.h>
+       struct timeb tb;
+
+       ftime(&tb);
+       printf("%s.\n", nons[tb.millitm % NONS]);
+}
diff --git a/docs/historical/2.9BSD/cmds/next.c b/docs/historical/2.9BSD/cmds/next.c
new file mode 100644 (file)
index 0000000..9fb3416
--- /dev/null
@@ -0,0 +1,97 @@
+#include "mh.h"
+#include <stdio.h>
+#include <strings.h>
+
+int     glbtype;
+struct msgs *mp;
+
+struct swit switches[] = {
+       "help",         4,      /* 0 */
+       0,              0
+};
+
+main(argc, argv)
+char *argv[];
+{
+       char *maildir, *vec[20], *folder, *nfolder;
+       register int msgnum;
+       register char *cp;
+       int next;
+       int vecp;
+       char **ap;
+       char *arguments[50], **argp;
+       extern char _sobuf[];
+
+       setbuf(stdout, _sobuf);
+#ifdef NEWS
+       m_news();
+#endif
+       next = glbtype;
+       folder = 0; vecp = 2;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                            /* unknown */
+                       case -1:vec[vecp++] = --cp;  continue;
+                       case 0: if(next > 0)                 /* -help  */
+       help("next [+folder]   [switches] [switches for \"type\" ]", switches);
+                               else
+       help("prev [+folder]   [switches] [switches for \"type\" ]", switches);
+                               goto leave;
+                       }
+               if(*cp == '+') {
+                       if(folder) {
+                               fprintf(stderr, "Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               folder = cp + 1;
+               } else {
+                       fprintf(stderr, "Bad arg: %s\n", cp);
+                       fprintf(stderr, "Usage: %s [+folder] [-l.switches]\n",
+                            next>0? "next" : "prev");
+                       goto leave;
+               }
+       }
+       vec[vecp] = 0;
+       if(!folder)
+               folder = m_getfolder();
+       maildir = m_maildir(folder);
+       if(chdir(maildir) < 0) {
+               fprintf(stderr, "Can't chdir to: ");
+               perror(maildir);
+               goto leave;
+       }
+       if(!(mp = m_gmsg(folder))) {
+               fprintf(stderr, "Can't read folder!?\n");
+               goto leave;
+       }
+       if(mp->hghmsg == 0) {
+               fprintf(stderr, "No messages in \"%s\".\n", folder);
+               goto leave;
+       }
+       if(!m_convert(next > 0 ? "next" : "prev"))
+               goto leave;
+       m_replace(pfolder, folder);
+       if(mp->lowsel != mp->curmsg)
+               m_setcur(mp->lowsel);
+       vec[1] = m_name(mp->lowsel);
+       printf("(Message %s:%s)\n", folder, vec[1]);
+       fflush(stdout);
+       vec[0] = "mh-type";
+       m_update();
+       execv(showproc, vec);
+       perror("Can't exec type");
+ leave:
+       m_update();
+       done(0);
+}
diff --git a/docs/historical/2.9BSD/cmds/nexthdr.c b/docs/historical/2.9BSD/cmds/nexthdr.c
new file mode 100644 (file)
index 0000000..f7def4b
--- /dev/null
@@ -0,0 +1 @@
+int     glbtype =  1;
diff --git a/docs/historical/2.9BSD/cmds/pick.c b/docs/historical/2.9BSD/cmds/pick.c
new file mode 100644 (file)
index 0000000..1384ac5
--- /dev/null
@@ -0,0 +1,490 @@
+#include "mh.h"
+#include <stdio.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <strings.h>
+
+#define NFOLD 20                /* Allow 20 folder specs */
+
+char *anoyes[];         /* Std no/yes gans array        */
+
+/*
+ * pick [-src folder] [msgs] search [-scan] [-show] [file-op]
+ *
+ *  search =  -from        \
+ *            -to           \
+ *            -cc            \
+ *            -subject        \  pattern
+ *            -sub            /
+ *            -date          /
+ *            -search       /
+ *            --component  /
+ *
+ * file-op =  -file [-preserve] [-link] +folder ...
+ *            -keep [-stay] [+folder ...]
+ */
+
+extern int errno;
+int nvecp, foldp;
+char **nvec;
+struct msgs *mp;
+char grep[256], *grepp, *folder, maildir[128];
+int showf, scanf, filef, keepf, linkf, noteold, prsrvf, stayf;
+int grep_lowsel  = 5000,
+    grep_hghsel  = 0;
+char *delprog;
+
+char   _sobuf[BUFSIZ];
+
+struct st_fold {
+       char        *f_name;
+       int          f_reused;
+       struct msgs *f_mp;
+} folders[NFOLD], *fptr;
+
+struct swit switches[] = {
+       "cc  pattern",                  0,      /*  0 */
+       "date  pattern",                0,      /*  1 */
+       "from  pattern",                0,      /*  2 */
+       "search  pattern",              0,      /*  3 */
+       "subject  pattern",             0,      /*  4 */
+       "to  pattern",                  0,      /*  5 */
+       "-othercomponent  pattern",    15,      /*  6 */
+       "all",                         -3,      /*  7 */
+       "file  +folder ...",            0,      /*  8 */
+       "nofile",                       0,      /*  9 */
+       "keep [+folder ...]",           0,      /* 10 */
+       "nokeep",                       0,      /* 11 */
+       "link",                         0,      /* 12 */
+       "nolink",                       0,      /* 13 */
+       "preserve",                     0,      /* 14 */
+       "nopreserve",                   0,      /* 15 */
+       "scan",                         0,      /* 16 */
+       "noscan",                       0,      /* 17 */
+       "show",                         0,      /* 18 */
+       "noshow",                       0,      /* 19 */
+       "src  +folder",                 0,      /* 20 */
+       "stay",                         0,      /* 21 */
+       "nostay",                       0,      /* 22 */
+       "help",                         4,      /* 23 */
+       0,                              0
+};
+
+main(argc, argv)
+char *argv[];
+{
+       char *msgs[128], buf[128];
+       register int msgnum;
+       register char *cp;
+       int msgp, i;
+       char **ap;
+       char *arguments[50], **argp, **arrp;
+
+       setbuf(stdout, _sobuf);
+
+#ifdef NEWS
+       m_news();
+#endif
+
+       nvecp = 1;
+       msgp = 0;
+       grepp = grep;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')  {
+                       if(*++cp == '-') {              /* --component */
+                   toomany:    if(grepp != grep) {
+                                   fprintf(stderr, "Only one search string.\n");
+                                   goto leave;
+                               }
+                               grepp = copy("^", grepp);
+                               grepp = copy(++cp, grepp);
+                               grepp = copy(":.*", grepp);
+                               goto pattern;
+                       }
+                       switch(i = smatch(cp, switches)) {
+                       case -2:ambigsw(cp, switches);  /* ambiguous */
+                               goto leave;
+                                                       /* unknown */
+                       case -1:fprintf(stderr, "pick: -%s unknown\n", cp);
+                               goto leave;
+                                                       /* -component */
+                       case 0:  case 1:  case 2:  case 4:  case 5:
+                               if(grepp != grep)
+                                       goto toomany;
+                               grepp = copy("^", grepp);
+                               arrp = brkstring(switches[i].sw, " ", 0);
+                               grepp = copy(*arrp, grepp);
+                               grepp = copy(":.*", grepp);
+                       case 3:                         /* -search */
+                      pattern: grepp = copy(*argp++, grepp);
+                               continue;
+                       case 6: fprintf(stderr, "pick:  can't get here\n");
+                               goto leave;
+                                                      /* -all */
+                       case 7: fprintf(stderr, "\"-all\" changed to \"all\"\n");
+                               goto leave;
+                       case 8: filef = 1;  continue;   /* -file */
+                       case 9: filef = 0;  continue;   /* -nofile */
+                       case 10:keepf = 1;  continue;   /* -keep */
+                       case 11:keepf = 0;  continue;   /* -nokeep */
+                       case 12:linkf = 1;  continue;   /* -link */
+                       case 13:linkf = 0;  continue;   /* -nolink */
+                       case 14:prsrvf = 1;  continue;  /* -preserve */
+                       case 15:prsrvf = 0;  continue;  /* -nopreserve */
+                       case 16:scanf = 1;  continue;   /* -scan */
+                       case 17:scanf = 0;  continue;   /* -noscan */
+                       case 18:showf = 1;  continue;   /* -show */
+                       case 19:showf = 0;  continue;   /* -noshow */
+                       case 21:stayf = 1;  continue;   /* -stay */
+                       case 22:stayf = 0;  continue;   /* -nostay */
+                       case 20:if(folder) {            /* -src */
+                                       fprintf(stderr, "Only one src folder.\n");
+                                       goto leave;
+                               }
+                               if(!(folder = *argp++) || *folder == '-') {
+               fprintf(stderr, "pick: Missing argument for %s switch\n", argp[-2]);
+                                        goto leave;
+                               }
+                               if(*folder == '+')
+                                       folder++;
+                               continue;
+                                                       /* -help */
+                       case 23:help("pick   [msgs] [switches]", switches);
+                               goto leave;
+                       }
+               } else if(*cp == '+') {
+                       if(foldp < NFOLD)
+                               folders[foldp++].f_name = cp + 1;
+                       else {
+                               fprintf(stderr, "Only %d folders allowed.\n", NFOLD);
+                               goto leave;
+                       }
+               } else
+                       msgs[msgp++] = cp;
+       }
+       if(grepp == grep) {
+               fprintf(stderr, "No search pattern specified.\n");
+               goto leave;
+       }
+       if(filef && keepf) {
+               fprintf(stderr, "-file and -keep don't go together.\n");
+               goto leave;
+       }
+       if(!scanf && !showf && !filef)
+               keepf++;                /* The default is -keep         */
+       if(keepf) {
+               prsrvf++;               /* -keep forces -preserve       */
+               linkf++;                /*   and -link                  */
+       }
+       if(!folder)
+               folder = m_getfolder(); /* use cur folder if no -src    */
+       copy(m_maildir(folder), maildir);
+       if(chdir(maildir) < 0) {
+               fprintf(stderr, "Can't chdir to: ");
+               perror(maildir);
+               goto leave;
+       }
+       if(!(mp = m_gmsg(folder))) {
+               fprintf(stderr, "Can't read folder!?\n");
+               goto leave;
+       }
+       if(mp->hghmsg == 0) {
+               fprintf(stderr, "No messages in \"%s\".\n", folder);
+               goto leave;
+       }
+       if(!foldp) {                    /* if no +folder given...       */
+               if(filef) {             /* -file requires one           */
+                       fprintf(stderr, "-file requires at least one folder arg.\n");
+                       goto leave;
+               }
+               if(keepf) {             /* use default selection-list name */
+                       copy(listname, copy("/", copy(folder, buf)));
+                       folders[foldp++].f_name = getcpy(buf);
+                       noteold++;      /* tell user if existing folder */
+               }
+       } else if(keepf) {              /* make folders sub-folders     */
+               for(msgnum = 0; msgnum < foldp; msgnum++)
+                       if(*(cp = folders[msgnum].f_name) != '.' &&
+                          *cp != '/') {
+                               copy(cp, copy("/", copy(folder, buf)));
+                               folders[msgnum].f_name = getcpy(buf);
+                       }
+               noteold++;
+       }
+       if(!msgp)
+               msgs[msgp++] = "first-last";
+       for(msgnum = 0; msgnum < msgp; msgnum++)
+               if(!m_convert(msgs[msgnum]))
+                       goto leave;
+       if(mp->numsel == 0) {
+               fprintf(stderr, "pick:  Peanut butter 'n jelly\n");/* never get here */
+               goto leave;
+       }
+       if(!compile(grep)) {
+               fprintf(stderr, "Pattern Error.\n");
+               goto leave;
+       }
+       for(msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
+               if(mp->msgstats[msgnum]&SELECTED)
+                       grepfn(msgnum);
+       if(mp->numsel == 0) {
+               fprintf(stderr, "No messages match specification.\n");
+               goto leave;
+       }
+       mp->lowsel = grep_lowsel;
+       mp->hghsel = grep_hghsel;
+                                                     /* all the exec's */
+       if((((delprog = m_find("delete-prog")) != NULL) &&
+           ((filef || keepf) && !linkf)) ||
+             scanf || showf) {
+               if(mp->numsel > MAXARGS-2) {
+                       fprintf(stderr, "pick: more than %d messages for %s exec\n",
+                               MAXARGS-2,
+                               scanf ? "scan" : showf ? "show" : delprog);
+                       goto leave;
+               }
+               nvec = (char **) malloc(MAXARGS * sizeof nvec[0]);
+               for(msgnum= mp->lowsel; msgnum<= mp->hghsel; msgnum++)
+                       if(mp->msgstats[msgnum]&SELECTED)
+                               nvec[nvecp++] = getcpy(m_name(msgnum));
+               nvec[nvecp] = 0;
+       }
+       if(keepf || filef)
+               if(opnfolds())
+                       goto leave;
+       if(!noteold || foldp > 1)
+               m_replace(pfolder, folder);
+       if(scanf)
+               scanfn(showf|filef|keepf);
+       else {
+               printf("%d hits.\n", mp->numsel); fflush(stdout);
+       }
+       if(showf)
+               showfn(filef|keepf);
+       if(!(filef|keepf))
+               goto leave;
+       for(msgnum= mp->lowsel; msgnum<= mp->hghsel; msgnum++)
+               if(mp->msgstats[msgnum]&SELECTED)
+                       if(process(cp = getcpy(m_name(msgnum))))
+                               goto leave;
+                       else
+                               free (cp);
+       if(!linkf)
+               remove();
+       if(noteold) {
+               if(!stayf && foldp == 1) {
+                       m_replace(pfolder, cp = folders[0].f_name);
+                       printf("[+%s now current]\n", cp); fflush(stdout);
+               }
+               for(fptr = folders; fptr < &folders[foldp]; fptr++)
+                       if(!fptr->f_reused) {
+                               chdir(m_maildir(fptr->f_name));
+                               m_setcur(fptr->f_mp->curmsg);
+                       }
+       }
+ leave:
+       m_update();
+}
+
+
+grepfn(msg)
+{
+       if(execute(m_name(msg))) {                  /* a match */
+               if(msg < grep_lowsel)
+                       grep_lowsel = msg;
+               if(msg > grep_hghsel)
+                       grep_hghsel = msg;
+       } else {
+               mp->msgstats[msg] &= ~SELECTED;     /* clear SELECTED bit */
+               mp->numsel--;
+       }
+}
+
+
+opnfolds()
+{
+       register int i;
+       register char *cp, *ap;
+       char nmaildir[128];
+       struct stat stbuf;
+
+       for(i = 0; i < foldp; i++) {
+               copy(m_maildir(cp = folders[i].f_name), nmaildir);
+               if(stat(nmaildir, &stbuf) < 0) {
+                       if(!noteold) {
+                               ap = concat("Create folder \"",
+                                       nmaildir, "\"? ", 0);
+                               if(!gans(ap, anoyes))
+                                       return(1);
+                       }
+                       if(!makedir(nmaildir)) {
+                               fprintf(stderr, "Can't create folder.\n");
+                               return(1);
+                       }
+               } else if(noteold) {
+                       printf("[Folder %s being re-used.]\n", cp);
+                       fflush(stdout);
+                       folders[i].f_reused++; /* Don't change cur in old fold */
+               }
+               if(chdir(nmaildir) < 0) {
+                       fprintf(stderr, "Can't chdir to: ");
+                       perror(nmaildir);
+                       return(1);
+               }
+               if(!(folders[i].f_mp = m_gmsg(folders[i].f_name))) {
+                       fprintf(stderr, "Can't read folder %s\n", folders[i].f_name);
+                       return(1);
+               }
+               folders[i].f_mp->curmsg = 0;
+       }
+       chdir(maildir);         /* return to src folder */
+       return(0);
+}
+
+
+scanfn(forkf)
+{
+       register int pid, i;
+
+       nvec[0] = "mh-scan";
+       if(forkf && (pid = fork())) {
+               if(pid == -1) {
+                       fprintf(stderr, "No forks!\n");
+                       done(1);
+               }
+               while(wait((int *)NULL) != pid) ;
+       } else {
+               m_update();
+               fflush(stdout);
+               execv(scanproc, nvec);
+               perror(scanproc);
+               done(1);
+       }
+}
+
+
+showfn(forkf)
+{
+       register int pid, i;
+       int sint, sqit;
+
+       nvec[0] = "c:mh-type";
+       if(forkf) {
+               sint = (int) signal(SIGINT, SIG_IGN);
+               sqit = (int) signal(SIGQUIT, SIG_IGN);
+       }
+       if(forkf && (pid = fork())) {
+               if(pid == -1) {
+                       fprintf(stderr, "No forks!\n");
+                       done(1);
+               }
+               while(wait((int *)NULL) != pid) ;
+               signal(SIGINT, sint);
+               signal(SIGQUIT, sqit);
+       } else {
+               m_update();
+               fflush(stdout);
+               execv(showproc, nvec);
+               perror(showproc);
+               done(1);
+       }
+}
+
+
+remove()
+{
+       register int i, j;
+       register char *cp;
+
+       if(delprog != NULL) {
+               nvec[0] = delprog;
+               m_update();
+               fflush(stdout);
+               execv(nvec[0], nvec);
+               fprintf(stderr, "Can't exec deletion-prog--");
+               perror(delprog);
+       } else {
+               for(i= mp->lowsel; i<= mp->hghsel; i++)
+                       if(mp->msgstats[i]&SELECTED)
+                               if(unlink(cp = m_name(i)) == -1) {
+                                       fprintf(stderr, "Can't unlink %s:",folder);
+                                       perror(cp);
+                               }
+       }
+}
+
+process(msg)
+char *msg;
+{
+       char newmsg[256], buf[BUFSIZ];
+       register int i;
+       register char *nmsg;
+       register struct st_fold *fp;
+       struct stat stbuf, stbf1;
+       int n, o, linkerr;
+
+    for(fp = folders; fp < &folders[foldp]; fp++) {
+       if(prsrvf)
+               nmsg = msg;
+       else
+               nmsg = m_name(fp->f_mp->hghmsg++ + 1);
+       copy(nmsg, copy("/", copy(m_maildir(fp->f_name), newmsg)));
+       if(link(msg, newmsg) < 0) {
+               linkerr = errno;
+               if(linkerr == EEXIST ||
+                 (linkerr == EXDEV && stat(newmsg, &stbuf) != -1)) {
+                       if(linkerr != EEXIST || stat(msg, &stbf1) < 0 ||
+                          stat(newmsg, &stbuf) < 0 ||
+                          stbf1.st_ino != stbuf.st_ino) {
+                               fprintf(stderr, "Message %s:%s already exists.\n",
+                                    fp->f_name, msg);
+                               return(1);
+                       }
+                       continue;
+               }
+               if(linkerr == EXDEV) {
+                       if((o = open(msg, 0)) == -1) {
+                               fprintf(stderr, "Can't open %s:%s.\n",
+                                       folder, msg);
+                               return(1);
+                       }
+                       fstat(o, &stbuf);
+                       if((n = creat(newmsg, stbuf.st_mode&0777)) == -1) {
+                               fprintf(stderr, "Can't create %s:%s.\n",
+                                       fp->f_name, nmsg);
+                               close(o);
+                               return(1);
+                       }
+                       do
+                               if((i=read(o, buf, sizeof buf)) < 0 ||
+                                 write(n, buf, i) == -1) {
+                                   fprintf(stderr, "Copy error on %s:%s to %s:%s!\n",
+                                           folder, msg, fp->f_name, nmsg);
+                                   close(o); close(n);
+                                   return(1);
+                               }
+                       while(i == sizeof buf);
+                       close(n); close(o);
+               } else {
+                       fprintf(stderr, "Error on link %s:%s to %s:",
+                           folder, msg, fp->f_name);
+                       perror(nmsg);
+                       return(1);
+               }
+       }
+       if((i = atoi(nmsg)) < fp->f_mp->curmsg || !fp->f_mp->curmsg)
+               fp->f_mp->curmsg = i;
+cont:   ;
+    }
+    return(0);
+}
diff --git a/docs/historical/2.9BSD/cmds/prevhdr.c b/docs/historical/2.9BSD/cmds/prevhdr.c
new file mode 100644 (file)
index 0000000..073abf2
--- /dev/null
@@ -0,0 +1 @@
+int     glbtype =   -1;
diff --git a/docs/historical/2.9BSD/cmds/prompter.c b/docs/historical/2.9BSD/cmds/prompter.c
new file mode 100644 (file)
index 0000000..00a2a86
--- /dev/null
@@ -0,0 +1,272 @@
+#include "mh.h"
+#include <stdio.h>
+#include <errno.h>
+#include <sgtty.h>
+#include <signal.h>
+#include <strings.h>
+
+char   *mypath;
+extern int errno;
+int     wtuser;         /* waiting for user input */
+int     sigint;         /* sensed an interrupt */
+FILE    *in, *out;
+struct  sgttyb sg;
+struct swit switches[] = {
+       "erase chr",      2,      /* 0 */ /* "2" can become "0",since no ed */
+       "kill chr",       0,      /* 1 */
+       "help",           4,      /* 2 */
+       0,                0
+};
+
+main(argc, argv)
+char *argv[];
+{
+       char tmpfil[32], *drft, name[NAMESZ], field[BUFSIZ];
+       int exitstat;
+       char skill, serase;
+       char *killp, *erasep;
+       register int i, state;
+       register char *cp;
+       char **ap;
+       char *arguments[50], **argp;
+       int sig();
+       int status, pid, wpid, intr;
+       extern char _sobuf[];
+
+       setbuf(stdout, _sobuf);
+       tmpfil[0] = 0;
+       skill = 0; exitstat = 0;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++)
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto badleave;
+                                                            /* unknown */
+                       case -1:fprintf(stderr, "prompter: -%s unknown\n", cp);
+                               goto badleave;
+                       case 0: if(!(erasep = *argp++)) {   /* -erase */
+     missing:  fprintf(stderr, "prompter: Missing argument for %s switch\n", argp[-2]);
+                                       goto badleave;
+                               }
+                               continue;
+                       case 1: if(!(killp= *argp++))       /* -kill */
+                                       goto missing;
+                               continue;
+                                                           /* -help */
+                       case 2: help("prompter    [switches]",
+                                    switches);
+                               goto badleave;
+                       }
+               else
+                       drft = cp;
+       if(!drft) {
+               fprintf(stderr, "prompter: missing skeleton\n");
+               goto badleave;
+       }
+       if((in = fopen(drft, "r")) == NULL) {
+               fprintf(stderr, "Can't open %s\n", drft);
+               goto badleave;
+       }
+       copy(makename("prmt", ".tmp"), copy("/tmp/", tmpfil));
+       if((out = fopen(tmpfil, "w")) == NULL) {
+               fprintf(stderr, "Can't create %s\n", tmpfil);
+               goto badleave;
+       }
+       chmod(tmpfil, 0700);
+       signal(SIGINT, sig);
+       gtty(0, &sg);
+       skill = sg.sg_kill;
+       serase = sg.sg_erase;
+       sg.sg_kill =    killp ?  chrcnv(killp) : skill;
+       sg.sg_erase =   erasep ? chrcnv(erasep) : serase;
+/***    stty(0, &sg);           ***/
+       ioctl(0, TIOCSETN, &sg);
+       if(killp || erasep) {
+               printf("Erase Char="); chrdisp(sg.sg_erase);
+               printf("; Kill Line="); chrdisp(sg.sg_kill);
+               printf(".\n"); fflush(stdout);
+       }
+       state = FLD;
+       for(;;) switch(state = m_getfld(state,name,field,sizeof field,in)) {
+
+       case FLD:
+       case FLDEOF:
+       case FLDPLUS:
+               if(field[0] != '\n' || field[1] != 0) {
+                       printf("%s:%s", name, field);
+                       fprintf(out, "%s:%s", name, field);
+                       while(state == FLDPLUS) {
+                               state=m_getfld(state,name,field,sizeof field,in);
+                               printf("%s", field);
+                               printf(out, "%s", field);
+                       }
+               } else {
+                       printf("%s: ", name);
+                       fflush(stdout);
+                       i = getln(field);
+                       if(i == -1)
+                               goto badleave;
+                       if(i == 0 && (field[0] == '\n' || !field[0]))
+                               continue;
+                       fprintf(out, "%s:", name);
+                       do {
+                               if(field[0] != ' ' && field[0] != '\t')
+                                       putc(' ', out);
+                               fputs(field, out);
+                       } while(i == 1 && (i = getln(field)) >= 0);
+                       if(i == -1)
+                               goto badleave;
+               }
+               field[0] = 0;
+               if(state == FLDEOF)
+                       goto body;
+               continue;
+
+       case BODY:
+       case BODYEOF:
+       case FILEEOF:
+  body:         fputs("--------\n", out);
+               printf("--------\n");
+               if(field[0]) {
+                       do {
+                               fputs(field, out);
+                               if(!sigint)
+                                       printf("%s", field);
+                       } while(state == BODY &&
+                               (state=m_getfld(state,name,field,sizeof field,in)));
+                       printf("\n--------Enter additional text\n\n");
+               }
+               fflush(stdout);
+               for(;;) {
+                       getln(field);
+                       if(field[0] == 0)
+                               break;
+                       fputs(field, out);
+               }
+               goto finish;
+
+       default:
+               fprintf(stderr, "Bad format file!\n");
+               goto badleave;
+       }
+
+
+finish:
+       printf("--------\n"); fflush(stdout);
+       fclose(out);
+       out = fopen(tmpfil, "r");
+       fclose(in);
+       in = fopen(drft, "w");          /* Truncate prior to copy back */
+       do
+               if((i = read(fileno(out), field, sizeof field)) > 0)
+                       write(fileno(in), field, i);
+       while(i == sizeof field);
+       goto leave;
+
+badleave:
+       exitstat = 1;
+
+leave:
+       if(in)
+               fclose(in);
+       if(out)
+               fclose(out);
+       if(tmpfil[0])
+               unlink(tmpfil);
+       m_update();
+       if(killp || erasep) {
+               sg.sg_kill = skill;
+               sg.sg_erase = serase;
+/***            stty(0, &sg);           ***/
+               ioctl(0, TIOCSETN, &sg);
+       }
+       done(exitstat);
+}
+
+
+getln(buf)
+char *buf;
+{
+       register char *cp;
+       register int c;
+       int stat;
+
+       cp = buf;
+       *cp = 0;
+       wtuser = 1;
+       for(;;) {
+               c = getchar();
+/***            fprintf(stderr,"getchar()=\\%o,errno=%d,EINTR=%d\n",c,errno,EINTR);/***/
+               if(c == EOF)
+                       if(errno == EINTR) {
+                               stat = -1;
+                               goto leave;
+                       } else {
+                               stat = 0;
+                               goto leave;
+                       }
+               if(c == '\n') {
+                       if(cp[-1] == '\\') {
+                               cp[-1] = c;
+                               stat = 1;
+                               goto leave;
+                       }
+                       *cp++ = c;
+                       *cp   = 0;
+                       stat = 0;
+                       goto leave;
+               }
+               if(cp < buf + 500)
+                       *cp++ = c;
+               *cp = 0;
+       }
+ leave: wtuser = 0;
+       return(stat);
+       }
+
+
+sig()
+{
+       signal(SIGINT, sig);
+       if(!wtuser)
+               sigint = 1;
+       return;
+}
+
+
+chrcnv(str)
+char *str;
+{
+       register char *cp;
+       register int c;
+
+       cp = str;
+       if((c = *cp++) != '\\')
+               return(c);
+       c = 0;
+       while(*cp && *cp != '\n') {
+               c *= 8;
+               c += *cp++ - '0';
+       }
+       return c;
+}
+
+
+chrdisp(chr)
+{
+       register int c;
+
+       c = chr;
+       if(c < ' ')
+               printf("<CTRL-%c>", c + '@');
+       else
+               printf("%c", c);
+}
diff --git a/docs/historical/2.9BSD/cmds/refile.c b/docs/historical/2.9BSD/cmds/refile.c
new file mode 100644 (file)
index 0000000..02c16b8
--- /dev/null
@@ -0,0 +1,364 @@
+#ifndef lint
+static char sccsid[] = "@(#)refile.c   1.1 5/26/83";
+#endif
+
+#include "mh.h"
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <strings.h>
+
+#define NFOLD 20                /* Allow 20 folder specs */
+
+/* file [-src folder] [msgs] +folder [+folder ...]
+ *
+ * moves messages from src folder (or current) to other one(s).
+ *
+ *  all = 1-999 for a message sequence
+ *  -preserve says preserve msg numbers
+ *  -link says don't delete old msg
+ */
+
+char *anoyes[];         /* Std no/yes gans array        */
+
+int vecp, foldp, prsrvf;
+char **vec, maildir[128], *folder, *file;
+struct msgs *mp;
+
+struct st_fold {
+       char *f_name;
+       struct msgs *f_mp;
+} folders[NFOLD];
+
+char   *files[NFOLD + 1];       /* Vec of files to process--starts at 1! */
+int     filec = 1;
+char   *bellfile = "/usr/bin/file";
+extern int errno;
+char   *rindex();
+
+struct swit switches[] = {
+       "all",           -3,      /* 0 */
+       "link",           0,      /* 1 */
+       "nolink",         0,      /* 2 */
+       "preserve",       0,      /* 3 */
+       "nopreserve",     0,      /* 4 */
+       "src +folder",    0,      /* 5 */
+       "file",           0,      /* 6 */
+       "help",           4,      /* 7 */
+       0,                0
+};
+main(argc, argv)
+char *argv[];
+{
+       register int i, msgnum;
+       register char *cp;
+       char *msgs[128];
+       int msgp, linkf;
+       int ismhfile = 0;
+       char **ap;
+       char *arguments[50], **argp;
+       char *pwd(), *pwds;
+
+       /*
+        * Rand has committed the sin of picking a name that already is
+        * used (file).  We fix this here since we can tell the difference
+        * between the two (mh file has -'s and +'s always, bell file never
+        * has them.)
+        */
+       for (i=1; i<argc; i++)
+               if (argv[i][0] == '-' || argv[i][0]=='+')
+                       ismhfile++;
+       if (!ismhfile) {
+               execv(bellfile, argv);
+               fprintf(stderr, "Cannot find %s\n", bellfile);
+               exit(1);
+       }
+
+#ifdef NEWS
+       m_news();
+#endif
+       folder = 0; msgp = 0; linkf = 0;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-') {
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                       /* unknown */
+                       case -1:fprintf(stderr, "file: -%s unknown\n", cp);
+                               goto leave;
+                                                      /* -all */
+                       case 0: fprintf(stderr, "\"-all\" changed to \"all\"\n");
+                               goto leave;
+                       case 1: linkf = 1;  continue;  /* -link */
+                       case 2: linkf = 0;  continue;  /* -nolink */
+                       case 3: prsrvf = 1;  continue; /* -preserve */
+                       case 4: prsrvf = 0;  continue; /* -nopreserve */
+                       case 5: if(folder) {           /* -src */
+                                       fprintf(stderr, "Only one src folder.\n");
+                                       goto leave;
+                               }
+                               if(!(folder = *argp++) || *folder == '-') {
+missing:        fprintf(stderr, "file: Missing argument for %s switch\n", argp[-2]);
+                                       goto leave;
+                               }
+                               if(*folder == '+')
+                                       folder++;
+                               continue;
+                                                       /* -help */
+                       case 6:
+                               if(filec >= NFOLD) {
+                                       fprintf(stderr, "Too many src files.\n");
+                                       goto leave;
+                               }
+                               if(!(files[filec++] = *argp) || **argp++ == '-')
+                                       goto missing;
+                               continue;
+
+                       case 7: help("file   [msgs] [switches]  +folder ...",
+                                    switches);
+                               goto leave;
+                       }
+               }
+               if(*cp == '+')  {
+                       if(foldp < NFOLD)
+                               folders[foldp++].f_name = cp + 1;
+                       else {
+                               fprintf(stderr, "Only %d folders allowed.\n", NFOLD);
+                               goto leave;
+                       }
+               } else
+                       msgs[msgp++] = cp;
+       }
+       if(!foldp) {
+               fprintf(stderr, "No folder specified.\n");
+fprintf(stderr, "Usage: file [-src folder] [msg ...] [switches] +folder [+folder]\n");
+               goto leave;
+       }
+       if(filec > 1) {
+               if(msgp) {
+                       fprintf(stderr, "File: Can't mix files and messages.\n");
+                       goto leave;
+               }
+               for(i = 1; i < filec; i++)
+                       if(*files[i] != '/') {
+                               if(!pwds)
+                                       pwds = pwd();
+                               files[i] = concat(pwds, "/", files[i], 0);
+                       }
+               if(opnfolds())
+                       goto leave;
+               for(i = 1; i < filec; i++) {
+                       if(process(files[i]))
+                               goto leave;
+               }
+               if(!linkf) {
+                       if((cp = m_find("delete-prog")) != NULL) {
+                               files[0] = cp;
+                               execvp(cp, files);
+                               fprintf(stderr, "Can't exec deletion-prog--");
+                               perror(cp);
+                       } else for(i = 1; i < filec; i++) {
+                               if(unlink(files[i]) == -1) {
+                                       fprintf(stderr, "Can't unlink ");
+                                       perror(files[i]);
+                               }
+                       }
+               }
+               goto leave;
+       }
+       if(!msgp)
+               msgs[msgp++] = "cur";
+       if(!folder)
+               folder = m_getfolder();
+       copy(m_maildir(folder), maildir);
+       if(chdir(maildir) < 0) {
+               fprintf(stderr, "Can't chdir to: ");
+               perror(maildir);
+               goto leave;
+       }
+       if(!(mp = m_gmsg(folder))) {
+               fprintf(stderr, "Can't read folder %s!?\n",folder);
+               goto leave;
+       }
+       if(mp->hghmsg == 0) {
+               fprintf(stderr, "No messages in \"%s\".\n", folder);
+               goto leave;
+       }
+       for(msgnum = 0; msgnum < msgp; msgnum++)
+               if(!m_convert((cp = msgs[msgnum])))
+                       goto leave;
+       if(mp->numsel == 0) {
+               fprintf(stderr, "file:  ham 'n cheese\n");       /* never get here */
+               goto leave;
+       }
+       m_replace(pfolder, folder);
+       if(mp->hghsel != mp->curmsg && ((mp->numsel != mp->nummsg) || linkf))
+               m_setcur(mp->hghsel);
+       if(opnfolds())
+               goto leave;
+       for(msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
+               if(mp->msgstats[msgnum] & SELECTED)
+                       if(process(cp = getcpy(m_name(msgnum))))
+                               goto leave;
+                       else
+                               cndfree(cp);
+       if(!linkf) {
+               if((cp = m_find("delete-prog")) != NULL) {
+                       if(mp->numsel > MAXARGS-2) {
+         fprintf(stderr, "file: more than %d messages for deletion-prog\n",MAXARGS-2);
+                               printf("[messages not unlinked]\n");
+                               goto leave;
+                       }
+                       vecp = 1;
+                       vec = (char **) calloc(MAXARGS + 2, sizeof *vec);
+                       for(msgnum= mp->lowsel; msgnum<= mp->hghsel; msgnum++)
+                               if(mp->msgstats[msgnum]&SELECTED)
+                                       vec[vecp++] = getcpy(m_name(msgnum));
+                       vec[vecp] = 0;
+                       m_update();
+                       fflush(stdout);
+                       vec[0] = cp;
+                       execv(vec[0], vec);
+                       fprintf(stderr, "Can't exec deletion-prog--");
+                       perror(cp);
+               } else {
+                       for(msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
+                               if(mp->msgstats[msgnum] & SELECTED)
+                                       if(unlink(cp = m_name(msgnum))== -1) {
+                                               fprintf(stderr, "Can't unlink %s:",folder);
+                                               perror(cp);
+                                       }
+               }
+       }
+leave:
+       m_update();
+       done(0);
+}
+
+
+opnfolds()
+{
+       register int i;
+       register char *cp;
+       char nmaildir[128];
+
+       for(i = 0; i < foldp; i++) {
+               copy(m_maildir(folders[i].f_name), nmaildir);
+               if(access(nmaildir, 5) < 0) {
+                       cp = concat("Create folder \"", nmaildir, "\"? ", 0);
+                       if(!gans(cp, anoyes))
+                               goto bad;
+                       free(cp);
+                       if(!makedir(nmaildir)) {
+                               fprintf(stderr, "Can't create folder.\n");
+                               goto bad;
+                       }
+               }
+               if(chdir(nmaildir) < 0) {
+                       fprintf(stderr, "Can't chdir to: ");
+                       perror(nmaildir);
+                       goto bad;
+               }
+               if(!(folders[i].f_mp = m_gmsg())) {
+                       fprintf(stderr, "Can't read folder %s\n", folders[i].f_name);
+                       goto bad;
+               }
+       }
+       chdir(maildir);         /* return to src folder */
+       return(0);
+bad:
+       return(1);
+}
+
+
+process(msg)
+char *msg;
+{
+       char newmsg[256], buf[BUFSIZ];
+       register int i;
+       register char *nmsg;
+       register struct st_fold *fp;
+       struct stat stbuf, stbf1;
+       int n, o, linkerr;
+
+    for(fp = folders; fp < &folders[foldp]; fp++) {
+       if(prsrvf)
+               nmsg = msg;
+       else
+               nmsg = m_name(fp->f_mp->hghmsg++ + 1);
+       copy(nmsg, copy("/", copy(m_maildir(fp->f_name), newmsg)));
+       if(link(msg, newmsg) < 0) {
+               linkerr = errno;
+               if(linkerr == EEXIST ||
+                 (linkerr == EXDEV && stat(newmsg, &stbuf) != -1)) {
+                       if(linkerr != EEXIST || stat(msg, &stbf1) < 0 ||
+                          stat(newmsg, &stbuf) < 0 ||
+                          stbf1.st_ino != stbuf.st_ino) {
+                               fprintf(stderr, "Message %s:%s already exists.\n",
+                                    fp->f_name, msg);
+                               return(1);
+                       }
+                       continue;
+               }
+               if(linkerr == EXDEV) {
+                       if((o = open(msg, 0)) == -1) {
+                               fprintf(stderr, "Can't open %s:%s.\n",
+                                       folder, msg);
+                               return(1);
+                       }
+                       fstat(o, &stbuf);
+                       if((n = creat(newmsg, stbuf.st_mode&0777)) == -1) {
+                               fprintf(stderr, "Can't create %s:%s.\n",
+                                       fp->f_name, nmsg);
+                               close(o);
+                               return(1);
+                       }
+                       do
+                               if((i=read(o, buf, sizeof buf)) < 0 ||
+                                 write(n, buf, i) == -1) {
+                                   fprintf(stderr, "Copy error on %s:%s to %s:%s!\n",
+                                           folder, msg, fp->f_name, nmsg);
+                                   close(o); close(n);
+                                   return(1);
+                               }
+                       while(i == sizeof buf);
+                       close(n); close(o);
+               } else {
+                       fprintf(stderr, "Error on link %s:%s to %s:",
+                           folder, msg, fp->f_name);
+                       perror(nmsg);
+                       return(1);
+               }
+       }
+cont:   ;
+    }
+    return(0);
+}
+
+
+char *
+pwd()
+{
+       register FILE *pp;
+       static char curpath[128];
+       register int i;
+       FILE *popen();
+
+       if((pp = popen("pwd", "r")) == NULL ||
+           fgets(curpath, sizeof curpath, pp) == NULL ||
+           pclose(pp) != 0) {
+               fprintf(stderr, "Can't find current directory!\n");
+               done(1);
+       }
+       *rindex(curpath, '\n') = 0;     /* Zap the lf */
+       return curpath;
+}
diff --git a/docs/historical/2.9BSD/cmds/replsubs.c b/docs/historical/2.9BSD/cmds/replsubs.c
new file mode 100644 (file)
index 0000000..77c5735
--- /dev/null
@@ -0,0 +1,232 @@
+#include "mh.h"
+
+char *ltrim(cp)
+char *cp;
+{
+       /* Return pointer to 1st non-blank char in string;
+        * If ptr ==> 0 or ptr ==> '\n'0, return NUL;
+        */
+
+       register char *cp1;
+
+       cp1 = cp;
+       while((*cp1 == ' ') || (*cp1 == '\t')) cp1++;
+       if((*cp1 == 0) || (*cp1 == '\n' && cp1[1] == 0))
+               cp1 = 0;
+       return(cp1);
+}
+
+char *rtrim(cp)
+char *cp;
+{
+       /* trim newline and blanks from the right */
+
+       register char *cp1;
+
+       cp1 = cp+strlen(cp)-1;
+       if(*cp1 == '\n') *cp1 = 0;
+       while(*--cp1 == ' ') ;
+       *++cp1 = 0;
+       return(cp);
+}
+
+char *niceadd(this, that)
+char *this, *that;
+{
+       register char *from, *to;
+
+       if(!(from = ltrim(this)))               /* nothing to add */
+               return(that);
+
+       if(to = that)
+               to = add(",\n    ", rtrim(to)); /* enuf blanks for "cc: " */
+       return(add(from, to));
+}
+
+#define ADDRLEN (needadr ? addrlen : 0)
+
+char *fix(field, address)
+char *field, *address;
+{
+       /* Appends address to each needy addressee in "field".
+        * Returns pointer to copy of new string. (HUH?)
+        * "field" should never be 0
+        */
+
+       register int len;
+       register char *newp;
+       int addrlen;
+       int needadr;
+       int fieldlen;
+       char *cp;
+
+       addrlen = strlen(address);
+       len = 0;
+       newp = "";
+
+       for(cp = field; ;cp += fieldlen + 1) {
+               needadr = needsaddr(&cp, &fieldlen); /* cp may be changed */
+               if(fieldlen == 0) {
+                       cndfree(field);
+                       newp = add("\n", newp);
+                       return(newp);
+               }
+               if((len + fieldlen + ADDRLEN) > 70) {
+                       newp = add(",\n    ", newp);
+                       len = 4;
+               } else if (*newp) {
+                       newp = add(", ", newp);
+                       len += 2;
+               }
+               *(cp + fieldlen) = 0;
+               newp = add(cp, newp);
+               if(needadr)
+                       newp = add(address, newp);
+               len += fieldlen + ADDRLEN;
+       }
+}
+
+anychar(fchars, field)
+char *fchars, *field;
+{
+       /* Returns 1 if any fancy char appears in "field"
+        * Returns 0 if either "field" is nul or contains no fancy chars
+        */
+
+       register char *fp;
+
+       if(!field)
+               return(0);
+       for(fp = fchars; *fp; fp++)
+               if(r_any(*fp, field))
+                       return(1);
+       return(0);
+}
+
+
+r_any(chr,stg)
+char chr, *stg;
+{
+       register char c, *s;
+
+       c = chr;
+       for (s = stg; (*s) && (*s != ',') && (*s != '\n');)
+               if (*s++ == c) return (1);
+       return (0);
+}
+
+char *addr(text)
+char *text;
+{
+       static char buf[128];
+       register char *cp, *bufp;
+       int textseen, blankseen;
+       char *copyaddr();
+
+       textseen = blankseen = 0;
+       bufp = buf;
+       if(!text)
+               return(0);
+       for(cp = text; (*cp == ' ' || *cp == '\t'); cp++);
+       for(;;cp++) {
+               switch(*cp) {
+               default:
+                       textseen++;
+                       break;
+               case ' ':  case '\t':
+                       blankseen++;
+                       break;
+               case 'a':
+                       if(!blankseen || !textseen || !ssequal("at ",cp)){
+                               textseen++;
+                               break;
+                       }
+                       bufp = copy(" at ", buf);
+                       copyaddr(cp+3, bufp);
+                       return(buf);
+               case '@':
+                       if(!textseen)
+                               return(0);
+                       bufp = copy(" @ ", buf);
+                       copyaddr(cp+1, bufp);
+                       return(buf);
+               case ',':  case '\n':  case 0:
+                       return(0);
+               }
+       }
+}
+
+#define ND1  (*fp) && (*fp != ' ') && (*fp != '\t')
+#define ND2  (*fp != '<') && (*fp != '(') && (*fp != '>') && (*fp != ')')
+#define ND3  (*fp != '\n') && (*fp!= ',') && (*fp != ':')
+#define NOTDELIM  ND1 &&  ND2 && ND3
+
+char *copyaddr(from, to)
+char *from, *to;
+{
+       /* Copies left-trimmed "from" to "to".
+        * Copy terminates on any delimiter.
+        * Returns pointer to NUL terminator in destination string
+        */
+
+       register char *fp, *tp;
+
+       for(fp = from; (*fp == ' ') && (*fp == '\t'); fp++) ;
+       for( ; NOTDELIM; *tp++ = *fp++);
+       *tp = 0;
+       return(tp);
+}
+#define NOTRELEVANT (*cp == ' ' || *cp == '\t' || *cp == '\n'|| *cp == ',')
+
+needsaddr(field, fieldlen)
+char **field;
+int *fieldlen;
+{
+       /* Returns 1 if this field needs an address
+        * Returns 0 if field contains any funny chars or has
+        * an address of the form "xxxx at " or "xxxx[<b>]@"
+        * "field": on input --  addr of pointer to start of field
+        *          on output -- val of ptr moved to 1st meaty char
+        * "fieldlen" returns the length of the new field
+        *  (it terminates on ',' or '\n' or 0)
+        */
+
+       register char *cp;
+       int textseen, blankseen;
+       int retval;
+                                  /* find 1st relevant char in field */
+       for(cp = *field; NOTRELEVANT ; cp++);
+
+       *field = cp;               /* return it to caller */
+       if(anychar("(<:", cp)) {
+               retval = 0;
+               goto leave;
+       }
+       for(;;cp++) {
+               switch(*cp) {
+               default:
+                       textseen++;
+                       break;
+               case ' ':  case '\t':
+                       blankseen++;
+                       break;
+               case 'a':
+                       if(!blankseen || !textseen || !ssequal("at ",cp)){
+                               textseen++;
+                               break;
+                       }
+               case '@':
+                       retval = 0;
+                       goto leave;
+               case ',':  case '\n':  case 0:
+                       retval = 1;
+                       goto leave;
+
+               }
+       }
+ leave:
+       for(; (*cp) && (*cp != ',') && (*cp != '\n'); cp++) ;
+       *fieldlen = cp- *field;
+       return(retval);
+}
+
diff --git a/docs/historical/2.9BSD/cmds/reply.c b/docs/historical/2.9BSD/cmds/reply.c
new file mode 100644 (file)
index 0000000..3d59a39
--- /dev/null
@@ -0,0 +1,321 @@
+#include "mh.h"
+#include <stdio.h>
+#include <signal.h>
+#include <strings.h>
+
+/*#define NEWS 1*/
+
+#define NOUSE 0
+
+/* #define TEST 1 */
+
+char    *anyl[] = {
+       "no",   0,
+       "yes",  0,
+       "list", 0,
+       0
+};
+
+char *aleqs[] = {
+       "list",              0,         /* 0 */
+       "edit [<editor>]",   0,         /* 1 */
+       "quit [delete]",     0,         /* 2 */
+       "send [verbose]",    0,         /* 3 */
+       0
+};
+
+int  *vec[MAXARGS], anot;
+int ccme = 1;
+struct msgs *mp;
+char *ed;
+int inplace;            /* preserve links in anno */
+
+struct swit switches[] = {
+       "annotate",           0,      /* 0 */
+       "noannotate",         0,      /* 1 */
+       "ccme",              -1,      /* 2 */
+       "noccme",            -1,      /* 3 */
+       "editor editor",      0,      /* 4 */
+       "inplace",            0,      /* 5 */
+       "noinplace",          0,      /* 6 */
+       "help",               4,      /* 7 */
+       0,                    0
+};
+
+char *ltrim();
+char *rtrim();
+char *niceadd();
+char *fix();
+char *addr();
+
+main(argc, argv)
+char *argv[];
+{
+       char *folder, *nfolder, *msg, *maildir;
+       register char *cp, **ap;
+       register int cur;
+       char *arguments[50], **argp;
+
+#ifdef NEWS
+       m_news();
+#endif
+       msg = 0; anot = 0; folder = 0;
+
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                            /* unknown */
+                       case -1:fprintf(stderr, "repl: -%s unknown\n", cp);
+                               goto leave;
+                       case 0: anot = 1;  continue;         /* -annotate */
+                       case 1: anot = 0;  continue;         /* -noannotate */
+                       case 2: ccme = 1;  continue;         /* -ccme */
+                       case 3: ccme = 0;  continue;         /* -noccme */
+                       case 4: if(!(ed = *argp++)) {        /* -editor */
+               fprintf(stderr, "repl: Missing argument for %s switch\n", argp[-2]);
+                                       goto leave;
+                               }
+                               continue;
+                       case 5: inplace = 1;  continue;      /* -inplace */
+                       case 6: inplace = 0;  continue;      /* -noinplace */
+                                                            /* -help */
+                       case 7: help("repl   [+folder] [msg] [switches]",
+                                    switches);
+                               goto leave;
+                       }
+               if(*cp == '+') {
+                       if(folder) {
+                               fprintf(stderr, "Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               folder = cp + 1;
+               } else if(msg) {
+                       fprintf(stderr, "Only one message per reply.\n");
+                       goto leave;
+               } else
+                       msg = cp;
+       }
+       if(!msg)
+               msg = "cur";
+       if(!folder)
+               folder = m_getfolder();
+       maildir = m_maildir(folder);
+       if(chdir(maildir) < 0) {
+               fprintf(stderr, "Can't chdir to: ");
+               perror(maildir);
+               goto leave;
+       }
+       if(!(mp = m_gmsg(folder))) {
+               fprintf(stderr, "Can't read folder!?\n");
+               goto leave;
+       }
+       if(mp->hghmsg == 0) {
+               fprintf(stderr, "No messages in \"%s\".\n", folder);
+               goto leave;
+       }
+       if(!m_convert(msg))
+               goto leave;
+       if(mp->numsel == 0) {
+               fprintf(stderr, "repl: pepperoni pizza\n");/* never get here */
+               goto leave;
+       }
+       if(mp->numsel > 1) {
+               fprintf(stderr, "Only one message at a time.\n");
+               goto leave;
+       }
+       m_replace(pfolder, folder);
+       if(mp->lowsel != mp->curmsg)
+               m_setcur(mp->lowsel);
+       repl(getcpy(m_name(mp->lowsel)));
+ leave:
+       m_update();
+       done(0);
+}
+
+
+repl(msg)
+{
+       register char *cp;
+       register int i,j;
+       register FILE *in;
+       char name[NAMESZ], field[BUFSIZ];
+       char *drft, *msgid, *replto, *from, *cc, *sub, *date, *to;
+       int state, out, status, intr;
+       int pid, wpid;
+       char **argp, *address;
+
+       if((in = fopen(msg, "r")) == NULL) {
+               fprintf(stderr, "Can't open "); perror(msg);
+               return;
+       }
+       drft = m_maildir(draft);
+       if((out = open(drft, 0)) >= 0) {
+               cp = concat("\"", drft, "\" exists; delete? ", 0);
+               while((i = gans(cp, anyl)) == 2)
+                       showfile(drft);
+               if(!i)
+                       return;
+               free(cp);
+               close(out);
+       }
+       if((out = creat(drft, m_gmprot())) < 0) {
+               fprintf(stderr, "Can't create \"%s\".\n", drft);
+               return;
+       }
+
+       state = FLD;
+       replto = msgid = to = from = cc = sub = date = 0;
+
+    for(;;) {
+
+       switch(state = m_getfld(state, name, field, sizeof field, in)) {
+
+       case FLD:
+       case FLDEOF:
+       case FLDPLUS:
+               if(uleq(name, "from"))
+                       from = niceadd(field, from);
+               if(uleq(name, "cc"))
+                       cc = niceadd(field, cc);
+               if(uleq(name, "subject"))
+                       sub = niceadd(field, sub);
+               if(uleq(name, "date"))
+                       date = niceadd(field, date);
+               if(uleq(name, "to"))
+                       to = niceadd(field, to);
+               if(uleq(name, "message-id"))
+                       msgid = niceadd(field, msgid);
+               if(uleq(name, "reply-to"))
+                       replto = niceadd(field, replto);
+       /*      if(uleq(name, "sender"))
+                       sender = niceadd(field, sender);        */
+               if(state == FLDEOF)
+                       goto done;
+               break;
+
+       case BODY:
+       case BODYEOF:
+       case FILEEOF:
+               goto done;
+
+       default:
+               fprintf(stderr, "getfld returned %d\n", state);
+               return;
+       }
+
+    }
+
+done:
+
+    /*  if(!(address = addr(sender)))
+               if(!(address = addr(from)))
+                       address = addr(replto);
+    */
+   /*   if(!(address = addr(replto)))
+               address = addr(from);
+    */
+       address = replto ? addr(replto) : addr(from);
+       if(!ccme)
+               to = 0;
+       if(!(from || replto)) {
+               fprintf(stderr, "No one to reply to!!!\n");
+               return;
+       }
+       fclose(in);
+       type(out, "To: ");                      /* To: */
+       type(out, replto ? replto : from);
+       if(cc || to )                           /* cc: */
+               type(out, "cc: ");
+       if(cc) {
+               if(address)
+                       cc = fix(cc, address);
+               if(to)
+                       rtrim(cc);
+               type(out, cc);
+       }
+       if(to) {
+               if(cc)
+                       type(out, ",\n    ");
+               if(address)
+                       to = fix(to, address);
+               type(out, to);
+       }
+       if(sub) {                               /* Subject: Re: */
+               type(out, "Subject: ");
+               if(*sub == ' ') sub++;
+               if((sub[0] != 'R' && sub[0] != 'r') ||
+                  (sub[1] != 'E' && sub[1] != 'e') ||
+                  sub[2] != ':')
+                       type(out, "Re: ");
+               type(out, sub);
+       }                                       /* In-reply-to: */
+       if(date) {
+               type(out, "In-reply-to: Your message of ");
+               date[strlen(date)-1] = '.';
+               if(*date == ' ') date++;
+               type(out, date);
+               type(out, "\n");
+               if(msgid) {
+                       type(out, "             ");
+                       if(*msgid == ' ') msgid++;
+                       type(out, msgid);
+               }
+       }
+       type(out, "----------\n");
+       close(out);
+       if(m_edit(&ed, drft, NOUSE, msg) < 0)
+               return;
+#ifdef TEST
+       fprintf(stderr, "!! Test Version of SEND Being Run !!\n");
+       fprintf(stderr, "   Send verbose !\n\n");
+#endif
+
+    for(;;) {
+       if(!(argp = getans("\nWhat now? ", aleqs))) {
+               unlink("@");
+               return;
+       }
+       switch(smatch(*argp, aleqs)) {
+               case 0: showfile(drft);                         /* list */
+                       break;
+               case 1: if(*++argp)                             /* edit */
+                               ed = *argp;
+                       if(m_edit(&ed, drft, NOUSE, msg) == -1)
+                               return;
+                       break;
+               case 2: if(*++argp && *argp[0] == 'd')          /* quit */
+                               if(unlink(drft) == -1)  {
+                                       fprintf(stderr, "Can't unlink %s ", drft);
+                                       perror("");
+                               }
+                       return;
+               case 3: if(*++argp) cp = *argp;  else cp = "";  /* send */
+
+                       if(!mp->msgflags&READONLY) {    /* annotate first */
+                           if(anot > 0) {
+                               while((pid = fork()) == -1) sleep(5);
+                               if(pid) {
+                                       while(wpid=wait((int *)NULL)!= -1 && wpid!= pid);
+                                       if(stat(drft, field) == -1)
+                                               annotate(msg, "Replied", "", inplace);
+                                       return;
+                               }
+                           }
+                       }
+                       if(!m_send(cp, drft))
+                               return;
+               default:fprintf(stderr, "repl: illegal option\n");       /*##*/
+                       break;
+       }
+    }
+}
diff --git a/docs/historical/2.9BSD/cmds/rescue.c b/docs/historical/2.9BSD/cmds/rescue.c
new file mode 100644 (file)
index 0000000..6c73714
--- /dev/null
@@ -0,0 +1,404 @@
+/*
+ * Read up the messages in the named files and rehabilitate them into
+ * UNIX+ style messages on standard output.
+ *
+ * +Unix is a trademark of Bell Laboratories.
+ * The optional -d flag tests the arpa net to unix date format
+ * transformer by reading lines from standard input, modifying them
+ * to unix format, and outputing them on standard output.
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/time.h>
+
+char   *index(), *rindex(), *reform();
+long   emitl();
+int    errs;
+int    dateerrs;
+int    dflag;
+int    lastblank;
+
+main(argc, argv)
+       char **argv;
+{
+       register char *cp, *fname;
+
+       if (argc < 2) {
+               fprintf(stderr, "Usage: rescue name ...\n");
+               _exit(1);
+       }
+       lastblank = 1;
+       while (--argc) {
+               fname = *++argv;
+               if (strcmp(fname, "-d") == 0) {
+                       dflag++;
+                       dtest();
+                       exit(0);
+               }
+               cp = rindex(fname, '/');
+               if (cp == 0)
+                       cp = fname;
+               else
+                       cp++;
+               if (strcmp(cp, "cur") == 0)
+                       continue;
+               if (strcmp(cp, "select") == 0)
+                       continue;
+               if (*cp == ',')
+                       continue;
+               while (*cp)
+                       if (!isdigit(*cp++)) {
+                               fprintf(stderr, "%s: not mh message file\n",
+                                   fname);
+                               goto blog;
+                       }
+               fix(fname);
+blog:          ;
+       }
+       if (dateerrs)
+               fprintf(stderr, "%d bad date(s) replaced by current date\n",
+                   dateerrs);
+       exit(errs);
+}
+
+/*
+ * Fix the named file by putting together a reasonable header
+ * and outputing the stuff onto standard output.
+ */
+fix(name)
+       char name[];
+{
+       register FILE *in;
+       char linebuf[BUFSIZ], from[BUFSIZ], date[BUFSIZ];
+       register int inhead;
+       register char *cp;
+
+       if ((in = fopen(name, "r")) == NULL) {
+               perror(name);
+               errs++;
+               return;
+       }
+       from[0] = date[0] = 0;
+       for (; from[0] == 0 || date[0] == 0;) {
+               if (fgets(linebuf, BUFSIZ, in) == NULL)
+                       goto noheader;
+               if (strlen(linebuf) == 1)
+                       goto noheader;
+               if (linebuf[0] == '-')
+                       goto noheader;
+               if (isfield(linebuf, "from")) {
+                       cp = index(linebuf, ':');
+                       if (cp == 0)
+                               goto noheader;
+                       cp++;
+                       while (*cp && isspace(*cp))
+                               cp++;
+                       strcpy(from, cp);
+                       continue;
+               }
+               if (isfield(linebuf, "date")) {
+                       cp = index(linebuf, ':');
+                       if (cp == 0)
+                               goto noheader;
+                       cp++;
+                       while (*cp && isspace(*cp))
+                               cp++;
+                       strcpy(date, cp);
+                       continue;
+               }
+       }
+       /*
+        * Ready to print the from line
+        */
+       zap(from);
+       zap(date);
+       if (!lastblank)
+               printf("\n");
+       printf("From %s %s\n", from, reform(date));
+       lastblank = 0;
+       rewind(in);
+       inhead = 1;
+       while (fgets(linebuf, BUFSIZ, in) != NULL) {
+               if (inhead &&
+                   (isfield(linebuf, "from") || isfield(linebuf, "date")))
+                       continue;
+               if (strlen(linebuf) == 1)
+                       inhead = 0;
+               fputs(linebuf, stdout);
+               lastblank = 0;
+               if (linebuf[0] == '\n' && linebuf[1] == 0)
+                       lastblank = 1;
+       }
+       fclose(in);
+       return;
+noheader:
+       fprintf(stderr, "%s:  Missing, bad, or incomplete header\n", name);
+       errs++;
+       fclose(in);
+}
+
+/*
+ * Determine if the passed line is a header of the given field name
+ */
+isfield(buf, field)
+       char buf[];
+       char field[];
+{
+       register char *cp, *cp2;
+
+       cp = buf;
+       cp2 = field;
+       while (lower(*cp++) == lower(*cp2++))
+               ;
+       if (*--cp == ':' && *--cp2 == 0)
+               return(1);
+       return(0);
+}
+
+/*
+ * Lower case the given character
+ */
+lower(c)
+       register int c;
+{
+
+       if (isupper(c))
+               return(tolower(c));
+       return(c);
+}
+
+/*
+ * Remove trailing newline from str, if present.
+ */
+zap(str)
+       char str[];
+{
+       register char *cp;
+
+       cp = index(str, '\n');
+       if (cp != 0)
+               *cp = 0;
+}
+
+/*
+ * Reformat the given Arpa net style date
+ * back into a unix ctime(3) date.
+ * Unfortunately, there appears to be NO standard arpa net
+ * date format.
+ */
+
+char *month = "janfebmaraprmayjunjulaugsepoctnovdec";
+
+char *
+reform(date)
+       char date[];
+{
+       static char retdate[35];
+       char dbuf[BUFSIZ];
+       register char *cp, *cp2, *mptr;
+       struct tm d;
+       long x, then;
+
+       cp = date;
+       cp2 = dbuf;
+       while (*cp) {
+               if (*cp == '(') {
+                       while (*cp != ')' && *cp)
+                               cp++;
+                       if (*cp)
+                               cp++;
+                       goto more;
+               }
+               if (*cp == '\t') {
+                       *cp2++ = ' ';
+                       cp++;
+                       continue;
+               }
+               if (*cp == '-') {
+                       *cp2++ = ' ';
+                       cp++;
+                       continue;
+               }
+               if (isupper(*cp)) {
+                       *cp2++ = tolower(*cp++);
+                       continue;
+               }
+               *cp2++ = *cp++;
+more:          ;
+       }
+       *cp2 = 0;
+       /*
+        * Okie dokie.  Now pick off the date part and store
+        * it away.  Only possible formats here are:
+        *      mm/dd/yy
+        * and
+        *      dd monthname year
+        */
+       if (index(dbuf, '/')) {
+               d.tm_mon = atoi(dbuf) - 1;
+               cp = index(dbuf, '/') + 1;
+               d.tm_mday = atoi(cp);
+               if ((cp = index(cp, '/')) == 0)
+                       goto baddate;
+               cp++;
+               d.tm_year = atoi(cp);
+               if (d.tm_year > 1900)
+                       d.tm_year -= 1900;
+               cp = index(cp, ' ');
+               if (cp == 0)
+                       goto baddate;
+       }
+       else {
+               d.tm_mday = atoi(dbuf);
+               cp = index(dbuf, ' ');
+               if (cp == 0)
+                       goto baddate;
+               while (*cp && isspace(*cp))
+                       cp++;
+               if (*cp == 0)
+                       goto baddate;
+               for (mptr = month; *mptr; mptr += 3)
+                       if (strncmp(mptr, cp, 3) == 0)
+                               break;
+               if (*mptr == 0)
+                       goto baddate;
+               d.tm_mon = (mptr - month)/3;
+               cp = index(cp, ' ');
+               if (cp == 0)
+                       goto baddate;
+               while (*cp && isspace(*cp))
+                       cp++;
+               if (*cp == 0)
+                       goto baddate;
+               d.tm_year = atoi(cp);
+               if (d.tm_year > 1900)
+                       d.tm_year -= 1900;
+               cp = index(cp, ' ');
+               if (cp == 0)
+                       goto baddate;
+       }
+       /*
+        * Got the month part, now fix up the time.
+        * Possibilities are:
+        *      hh:mm
+        *      hh:mm [am|pm]
+        *      hhmm edt
+        *      hh:mm:ss edt
+        * Basically, we lose by ignoring time zone.
+        */
+       for (;;) {
+               while (*cp && isspace(*cp))
+                       cp++;
+               if (*cp == 0)
+                       goto baddate;
+               if (strncmp(cp, "at ", 3) != 0)
+                       break;
+               cp += 3;
+       }
+       d.tm_sec = 0;
+       if (index(cp, ':')) {
+               d.tm_hour = atoi(cp);
+               cp = index(cp, ':') + 1;
+               d.tm_min = atoi(cp);
+               if (index(cp, ':')) {
+                       cp = index(cp, ':') + 1;
+                       d.tm_sec = atoi(cp);
+               }
+               while (*cp && !isspace(*cp))
+                       cp++;
+               while (*cp && isspace(*cp))
+                       cp++;
+               if (strncmp(cp, "pm", 2) == 0 && d.tm_hour < 12)
+                       d.tm_hour += 12;
+       }
+       else {
+               x = atoi(cp);
+               d.tm_hour = x / 100;
+               d.tm_min = x % 100;
+       }
+       then = emitl(&d);
+       strcpy(retdate, ctime(&then));
+       zap(retdate);
+       return(retdate);
+
+baddate:
+       dateerrs++;
+       if (dflag)
+               strcpy(retdate, "************************");
+       else {
+               then = time(0);
+               strcpy(retdate, ctime(&then));
+               zap(retdate);
+       }
+       return(retdate);
+}
+
+/*
+ * Test the arpa net to UNIX date modifier.
+ * Reads lines from standard input, converting them
+ * to unix format, and displaying both on stdout.
+ */
+dtest()
+{
+       char buf[BUFSIZ];
+       register char *cp;
+
+       while (gets(buf)) {
+               cp = reform(buf);
+               printf("\"%s\"  \"%s\"\n", buf, cp);
+       }
+}
+
+/*
+ * Routine to convert a localtime(3) format date back into
+ * a system format date.
+ *
+ * Hats off to Bob Kridle for the insight that the way to do
+ * this is by binary search of the system date space.
+ */
+
+struct tm *localtime();
+
+long
+emitl(dp)
+       struct tm *dp;
+{
+       long conv;
+       register int i, bit;
+       struct tm dcopy;
+
+       dcopy = *dp;
+       dp = &dcopy;
+       conv = 0;
+       for (i = 31; i >= 0; i--) {
+               bit = 1 << i;
+               conv |= bit;
+               if (dcmp(localtime(&conv), dp) > 0)
+                       conv &= ~bit;
+       }
+       return(conv);
+}
+
+/*
+ * Compare two localtime dates, return result.
+ */
+
+#define DECIDE(a) \
+       if (dp->a > dp2->a) \
+               return(1); \
+       if (dp->a < dp2->a) \
+               return(-1)
+
+dcmp(dp, dp2)
+       register struct tm *dp, *dp2;
+{
+
+       DECIDE(tm_year);
+       DECIDE(tm_mon);
+       DECIDE(tm_mday);
+       DECIDE(tm_hour);
+       DECIDE(tm_min);
+       DECIDE(tm_sec);
+       return(0);
+}
diff --git a/docs/historical/2.9BSD/cmds/rmf.c b/docs/historical/2.9BSD/cmds/rmf.c
new file mode 100644 (file)
index 0000000..126fb1d
--- /dev/null
@@ -0,0 +1,191 @@
+#ifndef lint
+static char sccsid[] = "@(#)rmf.c      1.4 7/7/83";
+#endif
+
+#include "mh.h"
+#include <stdio.h>
+#include <sys/types.h>
+#include <dir.h>
+#include "strings.h"
+
+char *anoyes[];         /* Std no/yes gans array        */
+
+int     subf;
+
+struct msgs *mp;
+
+struct swit switches[] = {
+       "help",         4,      /* 0 */
+       0,              0
+};
+
+main(argc, argv)
+char *argv[];
+{
+       register char *cp, **ap;
+       char *folder, buf[128];
+       int i, def_fold;
+       char *arguments[50], **argp;
+
+#ifdef NEWS
+       m_news();
+#endif
+       folder = 0;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                       /* unknown */
+                       case -1:fprintf(stderr, "rmf: -%s unknown\n", cp);
+                               goto leave;
+                                                       /* -help */
+                       case 0: help("rmf [+folder]  [switches]", switches);
+                               goto leave;
+                       }
+               if(*cp == '+')
+                       if(folder) {
+                               fprintf(stderr, "Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               folder = cp + 1;
+               else {
+                       fprintf(stderr, "Usage: rmf [+folder]\n");
+                       goto leave;
+               }
+       }
+       if(!folder) {
+               folder = m_getfolder();
+               def_fold++;
+       }
+       subf = !((!index(folder, '/')) | (*folder == '/') | (*folder == '.'));
+       if(def_fold && !subf) {
+               cp = concat("Remove folder \"", folder, "\" ?? ", 0);
+               if(!gans(cp, anoyes))
+                       goto leave;
+               free(cp);
+       }
+       if(rmfold(folder))
+               goto leave;
+       if(subf) {                      /* make parent "current" */
+               cp = copy(folder, buf);
+               while(cp > buf && *cp != '/') --cp;
+               if(cp > buf) {
+                       *cp = 0;
+                       if(strcmp(m_find(pfolder), buf) != 0) {
+                               printf("[+%s now current]\n", buf);
+                               m_replace(pfolder, buf);
+                       }
+               }
+       }
+ leave:
+       m_update();
+       done(0);
+}
+
+rmfold(fold)
+char *fold;
+{
+       register char *maildir;
+       struct direct *ent;
+       int i, leftover, cd;
+       register char *cp, *sp;
+       char nambuf[10];
+       register DIR *dirp;
+
+       leftover = 0;
+       if(!subf && strcmp(m_find(pfolder), fold) == 0) /* make default "current"*/
+               if(strcmp(m_find(pfolder), defalt) != 0) {
+                       printf("[+%s now current]\n", defalt);
+                       fflush(stdout);                          /*??*/
+                       m_replace(pfolder, defalt);
+               }
+       maildir = m_maildir(fold);
+       if((cd = chdir(maildir)) < 0)
+               goto funnyfold;
+       if(access(".", 2) == -1) {
+ funnyfold:     if(!m_delete(concat("cur-", fold, 0)))
+                       printf("[Folder %s de-referenced]\n", fold);
+               else
+                       fprintf(stderr, "You have no profile entry for the %s folder %s\n",
+                         cd < 0 ? "unreadable" : "read-only", fold);
+               return(1);
+       }
+       dirp = opendir(".");
+       ent = readdir(dirp);            /* move pointer past "." */
+       ent = readdir(dirp);            /* move pointer past ".." */
+       while(ent = readdir(dirp)) {
+               if (ent->d_ino==0) continue;
+               switch (ent->d_name[0]) {
+                       case '0':
+                       case '1':
+                       case '2':
+                       case '3':
+                       case '4':
+                       case '5':
+                       case '6':
+                       case '7':
+                       case '8':
+                       case '9':
+                       case '#':
+                       case ',':
+                               if(unlink(ent->d_name) == -1) {
+                                       fprintf(stderr, "Can't unlink %s:%s\n", fold,ent->d_name);
+                                       leftover++;
+                               }
+                               break;
+                       default:
+                               if (strcmp(ent->d_name, "cur") == 0 ||
+                                   strcmp(ent->d_name, "@") == 0) {
+                                       if(unlink(ent->d_name) == -1) {
+                                               fprintf(stderr, "Can't unlink %s:%s\n", fold,ent->d_name);
+                                               leftover++;
+                                       }
+                               } else {
+                                       fprintf(stderr, "File \"%s/%s\" not deleted!\n", fold, ent->d_name);
+                                       leftover++;
+                               }
+               }
+       }
+       closedir(dirp);
+       chdir("..");            /* Move out of dir to be deleted */
+       if(!leftover && removedir(maildir))
+               return(0);
+       else
+               fprintf(stderr, "Folder %s not removed!\n", fold);
+       return(1);
+}
+
+
+removedir(dir)
+{
+       register int pid, wpid;
+       int status;
+
+       if((pid = fork()) == 0) {
+               m_update();
+               fflush(stdout);
+               execl("/bin/rmdir", "rmdir", dir, 0);
+               execl("/usr/bin/rmdir", "rmdir", dir, 0);
+               fprintf(stderr, "Can't exec rmdir!!?\n");
+               return(0);
+       }
+       if(pid == -1) {
+               fprintf(stderr, "Can't fork\n");
+               return(0);
+       }
+       while((wpid = wait(&status)) != pid && wpid != -1) ;
+       if(status) {
+               fprintf(stderr, "Bad exit status (%o) from rmdir.\n", status);
+           /*  return(0);   */
+       }
+       return(1);
+}
diff --git a/docs/historical/2.9BSD/cmds/rmm.c b/docs/historical/2.9BSD/cmds/rmm.c
new file mode 100644 (file)
index 0000000..da34094
--- /dev/null
@@ -0,0 +1,131 @@
+#ifndef lint
+static char sccsid[] = "@(#)rmm.c      4.1 2/23/83";
+#endif
+
+#include "mh.h"
+#include <stdio.h>
+#include <strings.h>
+
+int     vecp;
+char    **vec;
+struct msgs *mp;
+
+struct swit switches[] = {
+       "all",         -3,      /* 0 */
+       "help",         4,      /* 1 */
+       0,              0
+};
+
+main(argc, argv)
+char *argv[];
+{
+       char *folder, *nfolder, *maildir, *msgs[100], buf[32];
+       register int msgnum;
+       register char *cp, *sp;
+       int msgp;
+       char **ap;
+       char *arguments[50], **argp;
+
+#ifdef NEWS
+       m_news();
+#endif
+       folder = 0; msgp = 0;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                       /* unknown */
+                       case -1:fprintf(stderr, "rmm: -%s unknown\n", cp);
+                               goto leave;
+                                                        /* -all */
+                       case 0: fprintf(stderr, "\"-all\" changed to \"all\"\n");
+                               goto leave;
+                                                       /* -help */
+                       case 1: help("rmm [+folder]  [msgs] [switches]",
+                                    switches);
+                               goto leave;
+                       }
+               if(*cp == '+')  {
+                       if(folder) {
+                               fprintf(stderr, "Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               folder = cp + 1;
+               } else
+                       msgs[msgp++] = cp;
+       }
+       if(!msgp)
+               msgs[msgp++] = "cur";
+       if(!folder)
+               folder = m_getfolder();
+       maildir = m_maildir(folder);
+       if(chdir(maildir) < 0) {
+               fprintf(stderr, "Can't chdir to: ");
+               perror(maildir);
+               goto leave;
+       }
+       if(!(mp = m_gmsg(folder))) {
+               fprintf(stderr, "Can't read folder!?\n");
+               goto leave;
+       }
+       if(mp->hghmsg == 0) {
+               fprintf(stderr, "No messages in \"%s\".\n", folder);
+               goto leave;
+       }
+       for(msgnum = 0; msgnum < msgp; msgnum++)
+               if(!m_convert(msgs[msgnum]))
+                       goto leave;
+       if(mp->numsel == 0) {
+               fprintf(stderr, "rmm: lasagne 'n sausage\n");     /* never get here */
+               goto leave;
+       }
+       m_replace(pfolder, folder);
+       if((cp = m_find("delete-prog")) == NULL) {
+               for(msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
+                       if(mp->msgstats[msgnum] & SELECTED) {
+                               sp = getcpy(m_name(msgnum));
+                               cp = copy(sp, buf);
+                               cp[1] = 0;
+                               do
+                                       *cp = cp[-1];
+                               while(--cp >= buf && *cp != '/');
+#ifdef UCB
+                               *++cp = '#';
+#else
+                               *++cp = ',';
+#endif
+                               unlink(buf);
+                               if(link(sp, buf) == -1 || unlink(sp) == -1)
+                                       fprintf(stderr, "Can't rename %s to %s.\n", sp, buf);
+                       }
+       } else {
+               if(mp->numsel > MAXARGS-2) {
+  fprintf(stderr, "rmm: more than %d messages for deletion-prog\n",MAXARGS-2);
+                       goto leave;
+               }
+               vec = (char **) calloc(MAXARGS +2, sizeof *vec);
+               vecp = 1;
+               for(msgnum= mp->lowsel; msgnum<= mp->hghsel; msgnum++)
+                       if(mp->msgstats[msgnum]&SELECTED)
+                               vec[vecp++] = getcpy(m_name(msgnum));
+               vec[vecp] = 0;
+               vec[0] = cp;
+               m_update();
+               fflush(stdout);
+               execv(vec[0], vec);
+               fprintf(stderr, "Can't exec deletion prog--");
+               perror(cp);
+       }
+leave:
+       m_update();
+       done(0);
+}
diff --git a/docs/historical/2.9BSD/cmds/scan.c b/docs/historical/2.9BSD/cmds/scan.c
new file mode 100644 (file)
index 0000000..72ef38c
--- /dev/null
@@ -0,0 +1,128 @@
+#include "mh.h"
+#include <stdio.h>
+#include <strings.h>
+
+int hdrflag = 1;
+int reverse = 0;
+struct msgs *mp;
+
+struct swit switches[] = {
+       "all",         -3,      /* 0 */
+       "ff",           0,      /* 1 */
+       "noff",         0,      /* 2 */
+       "header",       0,      /* 3 */
+       "noheader",     0,      /* 4 */
+       "reverse",      0,      /* 5 */
+       "help",         4,      /* 6 */
+       0,              0
+};
+
+main(argc, argv)
+char *argv[];
+{
+       char *folder, *maildir, *msgs[100];
+       register int msgnum;
+       register char *cp, **ap;
+       int msgp, ff;
+       FILE *in;
+       long now;
+       char *arguments[50], **argp;
+       extern char _sobuf[];
+
+       setbuf(stdout, _sobuf);
+#ifdef NEWS
+       m_news();
+#endif
+       ff = 0; msgp = 0; folder = 0;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                       /* unknown */
+                       case -1:fprintf(stderr, "scan: -%s unknown\n", cp);
+                               goto leave;
+                                                        /* -all */
+                       case 0: fprintf(stderr, "\"-all\" changed to \"all\"\n");
+                               goto leave;
+                       case 1: ff = 1;  continue;      /* -ff */
+                       case 2: ff = 0;  continue;      /* -noff */
+                       case 3: hdrflag = 0;  continue; /* -header */
+                       case 4: hdrflag = 1;  continue; /* -noheader */
+                       case 5: reverse = 1;  continue; /* -reverse */
+                       case 6: help("scan [+folder]  [msgs] [switches]",
+                                    switches);
+                               goto leave;
+                       }
+               if(*cp == '+') {
+                       if(folder) {
+                               fprintf(stderr, "Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               folder = cp + 1;
+               } else
+                       msgs[msgp++] = cp;
+       }
+       if(!folder)
+               folder = m_getfolder();
+       maildir = m_maildir(folder);
+       if(chdir(maildir) < 0) {
+               fprintf(stderr, "Can't chdir to: ");
+               perror(maildir);
+               goto leave;
+       }
+       if(!(mp = m_gmsg(folder))) {
+               fprintf(stderr, "Can't read folder!?\n");
+               goto leave;
+       }
+       if(mp->hghmsg == 0) {
+               fprintf(stderr, "No messages in \"%s\".\n", folder);
+               goto leave;
+       }
+       if(!msgp)
+               msgs[msgp++] = "first-last";
+       for(msgnum = 0; msgnum < msgp; msgnum++)
+               if(!m_convert(msgs[msgnum]))
+                       goto leave;
+       if(mp->numsel == 0) {
+               fprintf(stderr, "scan: matzo balls.\n");         /* never get here */
+               goto leave;
+       }
+       m_replace(pfolder,folder);
+       for( msgnum = (reverse ? mp->hghsel : mp->lowsel);
+            (reverse ? msgnum >= mp->lowsel : msgnum <= mp->hghsel); 
+            (reverse ? msgnum-- : msgnum++))  {
+               if(mp->msgstats[msgnum]&SELECTED) {
+                       if((in = fopen(cp = m_name(msgnum), "r")) == NULL)
+                               fprintf(stderr, "--Can't open %s\n", cp);
+                       else {
+                               if(!hdrflag++) {
+                                       time(&now);
+                                       cp = cdate(&now);
+                                       cp[9] = ' '; cp[15] = 0;
+printf("\
+                      Folder %-32s%s\n\n\
+  #   Date    From             Subject       [<<Body]\n\n", folder, cp);
+                               }
+                               scan(in, msgnum, 0, msgnum == mp->curmsg);
+                               fclose(in);
+                               if(stdout->_cnt < 80)
+                                       fflush(stdout);
+                       }
+               }
+       }
+       if(ff)
+               putchar('\014');
+leave:
+       m_update();
+       done(0);
+}
+
diff --git a/docs/historical/2.9BSD/cmds/scansub.c b/docs/historical/2.9BSD/cmds/scansub.c
new file mode 100644 (file)
index 0000000..dc3d1df
--- /dev/null
@@ -0,0 +1,407 @@
+#include "mh.h"
+#include <stdio.h>
+
+#define _FROM    1
+#define _NOTFROM 0
+
+
+#define FROM    13              /* Start of From field          */
+#define SFROM   16              /* Length of "        "         */
+#define DATE     5              /* Start of Date field          */
+#define SDATE    7              /* Length                       */
+#define SUBJ    31              /* Start of Subject field       */
+#define SSUBJ   (79-SUBJ)       /* Size of Subject field        */
+#define BSUBJ   20              /* Room needed in Sub field to  */
+                               /* add stuff from the body      */
+#define MSGN     0              /* Start of msg name field      */
+#define SMSGN    3              /* Length                       */
+#define FLGS     3              /* Start of flags field         */
+#define SFLGS    2              /* Width of flag field          */
+
+FILE  *scnout;
+char scanl[82];
+int local;
+int hostseen;
+char *frmtok();
+
+scan(inb, innum, outnum, curflg)
+struct iobuf *inb;
+int outnum;
+{
+
+       char buf[BUFSIZ], name[NAMESZ], tobuf[32], frombuf[32];
+       register char *cp, **tok1;
+       int state, subsz, first, compnum;
+       static char *myname;
+
+       local = 0; hostseen = 0;
+       if(!myname)
+               myname = getenv("USER");
+       tobuf[0] = 0; frombuf[0] = 0;
+       first = 0;
+       state = FLD;
+       compnum = 1;
+
+       for(;;) {
+
+               state = m_getfld(state, name, buf, sizeof buf, inb);
+               if(!first++ && state != FILEEOF) {      /*##*/
+                   if(outnum) {
+                       if((scnout = fopen(cp = m_name(outnum), "w")) == NULL) {
+                               fprintf(stderr, "Error creating msg ");
+                               perror(cp); done(-1);
+                       }
+                       chmod(cp, m_gmprot());
+                   }
+                   sfill(scanl, sizeof scanl);
+                   scanl[sizeof scanl - 1] = 0;
+                   subsz = 0;
+                   tobuf[0] = 0;
+               }
+
+               switch(state) {
+
+               case FLD:
+               case FLDEOF:
+               case FLDPLUS:
+                       compnum++;
+                       if(uleq(name, "from"))
+                               frombuf[
+                                  cpyfrm(buf,frombuf,sizeof frombuf,_FROM)]=0;
+                       else if(uleq(name, "date"))
+                               cpydat(buf, scanl+DATE, SDATE);
+                       else if(uleq(name, "subject") && scanl[SUBJ] == ' ')
+                               subsz = cpy(buf, scanl+SUBJ, SSUBJ);
+                       else if(uleq(name, "to") && !tobuf[0])
+                               tobuf[
+                                  cpyfrm(buf,tobuf,sizeof tobuf-1,_NOTFROM)]=0;
+                       else if(uleq(name, "replied"))
+                               cpy("-", scanl+FLGS+1, 1);
+                       put(name, buf, scnout);
+                       while(state == FLDPLUS) {
+                               state=m_getfld(state,name,buf,sizeof buf,inb);
+                               if(scnout)
+                                       fputs(buf, scnout);
+                       }
+                       if(state == FLDEOF)
+                               goto putscan;
+                       continue;
+
+               case BODY:
+               case BODYEOF:
+                       compnum = -1;
+                       if(buf[0] && subsz < SSUBJ - BSUBJ) {
+                               scanl[SUBJ+subsz+1] = '<';
+                               scanl[SUBJ+subsz+2] = '<';
+                               cpy(buf, scanl+SUBJ+subsz+3, SSUBJ-subsz-3);
+                               subsz = SSUBJ;
+                       }
+                       if(buf[0] && scnout) {
+                               putc('\n', scnout);
+                               fputs(buf, scnout);
+                               if(ferror(scnout)) {
+                                       fprintf(stderr, "Write error on ");
+                                       perror(m_name(outnum));done(-1);
+                               }
+                       }
+       body:           while(state == BODY) {
+                               state=m_getfld(state,name,buf,sizeof buf,inb);
+                               if(scnout)
+                                       fputs(buf, scnout);
+                       }
+                       if(state == BODYEOF) {
+                 putscan:      cpymsgn(m_name(innum), scanl+MSGN, SMSGN);
+                               tok1= brkstring(getcpy(frombuf), " ", "\n");
+                               if(!frombuf[0] || uleq(frombuf, myname) ||
+                                 (local && uleq(*tok1, myname))) {
+                                       cpy("To:", scanl+FROM, 3);
+                                       cpy(tobuf, scanl+FROM+3, SFROM-3);
+                               } else
+                                       cpy(frombuf, scanl+FROM, SFROM);
+                               if(curflg)
+                                       cpy("+", scanl+FLGS, SFLGS);
+                               trim(scanl);
+                               fputs(scanl, stdout);
+
+                               if(scnout) {
+                                       fflush(scnout);
+                                       if(ferror(scnout)) {
+                                               perror("Write error on ");
+                                               perror(m_name(outnum));
+                                               done(-1);
+                                       }
+                                       fclose(scnout);
+                                       scnout = NULL;
+                               }
+                               return(1);
+                       }
+                       break;
+
+               case LENERR:
+               case FMTERR:
+                       fprintf(stderr, "??Message Format Error ");
+                       fprintf(stderr, "(Message %d) ", outnum ? outnum :innum);/*##*/
+                       if(compnum < 0) fprintf(stderr, "in the Body.\n");
+                       else fprintf(stderr, "in Component #%d.\n", compnum);
+                       fprintf(stderr, "-----------------------------------------");
+                       fprintf(stderr, "-------------------------------------\n");
+                       goto badret;
+               default:
+                       fprintf(stderr, "Getfld returned %d\n", state);
+
+
+       badret:         if(outnum) {
+                               fputs("\n\nBAD MSG:\n", scnout);
+                               if(compnum < 0)
+                                       fputs(buf, scnout);
+                               else
+                                       fputs(name, scnout);
+                       /***    ungetc(inb);    ***/
+                               state = BODY;
+                               goto  body;
+
+                       }
+                       if(scnout)
+                               fflush(scnout);
+                       return(-1);
+               case FILEEOF:
+                       return(0);
+
+               }
+
+       }
+}
+
+
+trim(str)
+char *str;
+{
+       register char *cp;
+
+       cp = str;
+       while(*cp) cp++;
+       while(*--cp == ' ') ;
+       cp++;
+       *cp++ = '\n';
+       *cp++ = 0;
+}
+
+sfill(str, cnt)
+char *str;
+{
+       register char *cp;
+       register int i;
+
+       cp = str;  i = cnt;
+       do
+               *cp++ = ' ';
+       while(--i);
+}
+
+
+put(name, buf, ip)
+register FILE *ip;
+{
+       if(ip) {
+               fputs(name, ip);
+               putc(':', ip);
+               fputs(buf, ip);
+               if(ferror(ip)) { perror("Write error");done(-1);}
+       }
+}
+
+
+cpy(from, to, cnt)
+register char *from, *to;
+register int cnt;
+{
+       register int c;
+       char *sfrom;
+
+       sfrom = from;
+       while(*from == ' ' || *from == '\t' || *from == '\n')
+               from++;
+       while(cnt--)
+               if(c = *from) {
+                       if(c == '\t' || c == ' ' || c == '\n') {
+                               *to++ = ' ';
+                               do 
+                                       from++;
+                               while((c= *from)==' '||c=='\t'||c=='\n');
+                               continue;
+                       } else
+                               *to++ = c;
+                       from++;
+               } else
+                       break;
+       return(from - sfrom - 1);
+}
+
+int *localtime();
+char *findmonth();
+
+cpydat(sfrom, sto, cnt)
+char *sfrom, *sto;
+{
+       register char *from, *cp;
+       register int c;
+       static int *locvec;
+       long now;
+       char *to;
+
+       if(!locvec) {
+               time(&now);
+               locvec = localtime(&now);
+       }
+       to = sto;
+       for(from = sfrom; (c = *from) < '0' || c > '9'; from++)
+               if(!c)
+                       return;
+       c = cnt;
+       for(cp = from; (*cp >= '0' && *cp <= '9') || *cp == ' '; cp++);
+       if(cp = findmonth(cp)) {
+               if(!cp[1]) {
+                       *to++ = ' ';
+                       c--;
+               }
+               while(*cp && c--)
+                       *to++ = *cp++;
+               c--;  *to++ = '/';
+               if(from[1] == ' ') {
+                       *to++ = ' ';
+                       c--;
+               }
+               while(*from >= '0' && *from <= '9' && c--)
+                       *to++ = *from++;
+               if(c >= 2) {
+                       while(*from < '0' || *from > '9') from++;
+                       if(((c = atoi(from)) > 1970 && c-1900 < locvec[5])
+                           || c < locvec[5])  {
+                               *to++ = '/';
+                               *to++ = (c < 100) ? (c - 70 + '0')
+                                                 : (c - 1970 + '0');
+                       }
+               }
+               return;
+       }
+       if(from[1] == ' ') {
+               *to++ = ' ';
+               c--;
+       }
+       while(*from && c--)
+               *to++ = *from++;
+}
+
+
+char    *fromp, fromdlm, pfromdlm;
+
+cpyfrm(sfrom, sto, cnt, fromcall)
+char *sfrom, *sto;
+{
+       register char *to, *cp;
+       register int c;
+
+       fromdlm = ' ';
+       fromp = sfrom; to = sto;
+       cp = frmtok();
+       do
+               if(c = *cp++)
+                       *to++ = c;
+               else
+                       break;
+       while(--cnt);
+       for(;;) {
+               if(cnt < 3) break;
+               if(*(cp = frmtok()) == 0) break;
+               if(*cp == '@' || uleq(cp, "at")) {
+                       cp = frmtok();
+                       if(uleq(cp, "berkeley")) {
+                               /* if the first "From:" host is local */
+                               if(fromcall && !hostseen++)
+                                       local++;
+                       } else {
+                               *to++ = '@';
+                               cnt--;
+                               do
+                                       if(c = *cp++)
+                                               *to++ = c;
+                                       else
+                                               break;
+                               while(--cnt);
+                       }
+               } else if(cnt > 4) {
+                       cnt--; *to++ = pfromdlm;
+                       do
+                               if(c = *cp++)
+                                       *to++ = c;
+                               else
+                                       break;
+                       while(--cnt);
+               }
+       }
+       if(fromcall)
+               hostseen++;
+       return(to - sto);
+}
+
+
+char *frmtok()
+{
+       static char tokbuf[64];
+       register char *cp;
+       register int c;
+
+       pfromdlm = fromdlm;
+       cp = tokbuf; *cp = 0;
+       while(c = *fromp++) {
+               if(c == '\t')
+                       c = ' ';
+               if(c == ' ' && cp == tokbuf)
+                       continue;
+               if(c == ' ' || c == '\n' || c == ',')
+                       break;
+               *cp++ = c;
+               *cp = 0;
+               if(c == '@' || *fromp == '@' || cp == &tokbuf[63])
+                       break;
+       }
+       fromdlm = c;
+       return(tokbuf);
+}
+
+
+/*      num specific!         */
+
+cpymsgn(msgnam, addr, len)
+char *msgnam, *addr;
+{
+       register char *cp, *sp;
+
+       sp = msgnam;
+       cp = addr + (len - strlen(sp));
+       while(*sp)
+               *cp++ = *sp++;
+}
+
+char *monthtab[] = {
+       "jan", "feb", "mar", "apr", "may", "jun",
+       "jul", "aug", "sep", "oct", "nov", "dec",
+};
+
+char *findmonth(str)
+char *str;
+{
+       register char *cp, *sp;
+       register int i;
+       static char buf[4];
+       char *locv();
+
+       for(cp=str, sp=buf; (*sp++ = *cp++) && sp < &buf[3] && *cp != ' '; );
+       *sp = 0;
+       for(i = 0; i < 12; i++)
+               if(uleq(buf, monthtab[i])) {
+                       sprintf(buf, "%2d", i+1);
+                       return buf;
+               }
+       return(0);
+}
diff --git a/docs/historical/2.9BSD/cmds/send.c b/docs/historical/2.9BSD/cmds/send.c
new file mode 100644 (file)
index 0000000..95c3aec
--- /dev/null
@@ -0,0 +1,144 @@
+#ifndef lint
+static char sccsid[] = "@(#)send.c     4.2 2/23/83";
+#endif
+
+#include "mh.h"
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <strings.h>
+#include <signal.h>
+
+char   *anoyes[];       /* Std no/yes gans array        */
+
+char   *vec[20];
+int     vecp;
+
+struct swit switches[] = {
+       "debug",         -1,      /* 0 */
+       "draft",          0,      /* 1 */
+       "format",         0,      /* 2 */
+       "noformat",       0,      /* 3 */
+       "msgid",          0,      /* 4 */
+       "nomsgid",        0,      /* 5 */
+       "verbose",        0,      /* 6 */
+       "noverbose",      0,      /* 7 */
+       "help",           4,      /* 8 */
+       0,                0
+};
+
+int     debug;
+
+main(argc, argv)
+char *argv[];
+{
+       register char *drft, *cp;
+       register int i;
+       int status, pid;
+       struct stat stbuf;
+       char **ap;
+       char *arguments[50], **argp;
+
+#ifdef NEWS
+       m_news();
+#endif
+       drft = 0;
+       vec[vecp++] = "mh_deliver";
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                            /* unknown */
+                       case -1:fprintf(stderr, "send: -%s unknown\n", cp);
+                               goto leave;
+                                                            /* -draft */
+                       case 1: vec[vecp++] = drft = m_maildir(draft);
+                               continue;
+                       case 0: debug++;
+                       case 2: case 3: case 4:
+                       case 5: case 6: case 7:
+                               vec[vecp++] = --cp;
+                               continue;
+                       case 8: help("send [file]   [switches]",
+                                    switches);
+                               goto leave;
+                       }
+               if(drft) {
+                       fprintf(stderr, "Send: Only one message at a time.\n");
+                       done(1);
+               }
+               vec[vecp++] = drft = cp;
+       }
+       if(!drft) {
+               drft = m_maildir(draft);
+               if(stat(drft, &stbuf) == -1) {
+                       fprintf(stderr, "Draft file: %s doesn't exist.\n", drft);
+                       done(1);
+               }
+               cp = concat("Use \"", drft, "\"? ", 0);
+               if(!gans(cp, anoyes))
+                       done(0);
+               vec[vecp++] = drft;
+       } else {
+               if(stat(drft, &stbuf) == -1) {
+                       fprintf(stderr, "Draft file: %s doesn't exist.\n", drft);
+                       done(1);
+               }
+       }
+       m_update();
+       vec[vecp] = 0;
+
+       while((pid = fork()) == -1) {
+               fprintf("Waiting for a fork\n");
+               sleep(2);
+       }
+       if(pid == 0) {
+               execv(mh_deliver, vec);
+               perror(mh_deliver);
+               done(1);
+       }
+       signal(SIGINT, SIG_IGN);
+       signal(SIGQUIT, SIG_IGN);
+       while((i = wait(&status)) != -1 && i != pid) ;
+       if(status == 0 && !debug)
+               backup(drft);
+
+leave:  ;
+/***    m_update();     ***/
+}
+
+
+backup(file)
+char *file;
+{
+       char buf[128];
+       register char *cp;
+       extern char *rindex();
+
+       buf[0] = 0;
+       if(cp = rindex(file, '/'))
+               sprintf(buf, "%.*s", (++cp)-file, file);
+       else
+               cp = file;
+#ifdef UCB
+       strcat(buf, "#");
+#else
+       strcat(buf, ",");
+#endif
+       strcat(buf, cp);
+       unlink(buf);
+       if(link(file, buf) < 0 || unlink(file) < 0) {
+               fprintf(stderr, "Send: Backup rename failure ");
+               perror(buf);
+               done(1);
+       }
+}
diff --git a/docs/historical/2.9BSD/cmds/show.c b/docs/historical/2.9BSD/cmds/show.c
new file mode 100644 (file)
index 0000000..5c8bf96
--- /dev/null
@@ -0,0 +1,132 @@
+#include "mh.h"
+#include <stdio.h>
+#include <strings.h>
+
+int vecp;
+char *vec[MAXARGS];
+struct msgs *mp;
+struct swit switches[] = {
+       "all",         -3,      /* 0 */
+       "draft",        2,      /* 1 */
+       "pr",           2,      /* 2 */
+       "nopr",         2,      /* 3 */
+       "help",         4,      /* 4 */
+       0,              0
+};
+
+main(argc, argv)
+char *argv[];
+{
+       char *folder, *maildir, *msgs[100];
+       register int msgnum;
+       register char *cp, **ap;
+       int msgp, all, drft, pr;
+       char *arguments[50], **argp;
+       extern char _sobuf[];
+
+       setbuf(stdout, _sobuf);
+#ifdef NEWS
+       m_news();
+#endif
+       folder = (char *) 0;
+       pr = all = msgp = 0;
+       vecp = 1;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                            /* unknown */
+                       case -1:vec[vecp++] = --cp;  continue;
+                                                            /* -all   */
+                       case 0: fprintf(stderr, "\"-all\" changed to \"all\"\n");
+                               goto leave;
+                       case 1: drft = 1;  continue;         /* -draft */
+                       case 2: pr = 1;  continue;           /* -pr    */
+                       case 3: pr = 0;  vecp = 1;  continue;/* -nopr  */
+                       case 4:                              /* -help  */
+  help("show [+folder]  [msgs] [switches] [switches for \"type\" or \"pr\" ]",
+                                    switches);
+                               goto leave;
+                       }
+               if(*cp == '+') {
+                       if(folder) {
+                               fprintf(stderr, "Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               folder = cp + 1;
+               } else
+                       msgs[msgp++] = cp;
+       }
+       if(drft)
+               maildir = m_maildir("");
+       else {
+               if(!msgp)
+                       msgs[msgp++] = "cur";
+               if(!folder)
+                       folder = m_getfolder();
+               maildir = m_maildir(folder);
+       }
+       if(chdir(maildir) < 0) {
+               fprintf(stderr, "Can't chdir to: ");
+               perror(maildir);
+               goto leave;
+       }
+       if(drft) {
+               vec[vecp++] = draft;
+               goto doit;
+       }
+       if(!(mp = m_gmsg(folder))) {
+               fprintf(stderr, "Can't read folder!?\n");
+               goto leave;
+       }
+       if(mp->hghmsg == 0) {
+               fprintf(stderr, "No messages in \"%s\".\n", folder);
+               goto leave;
+       }
+       if(msgp)
+               for(msgnum = 0; msgnum < msgp; msgnum++)
+                       if(!m_convert(msgs[msgnum]))
+                               goto leave;
+       if(mp->numsel == 0) {
+               fprintf(stderr, "show: potato pancakes.\n");     /* never get here */
+               goto leave;
+       }
+       if(mp->numsel > MAXARGS-2) {
+  fprintf(stderr, "show: more than %d messages for show-exec\n", MAXARGS-2);
+               goto leave;
+       }
+       for(msgnum= mp->lowsel; msgnum<= mp->hghsel; msgnum++)
+               if(mp->msgstats[msgnum]&SELECTED)
+                       vec[vecp++] = getcpy(m_name(msgnum));
+       m_replace(pfolder, folder);
+       if(mp->hghsel != mp->curmsg)
+               m_setcur(mp->hghsel);
+       if(vecp == 2 ) {
+               printf("(Message %s:%s)\n", folder, vec[1]);
+       }
+doit:   m_update();
+       fflush(stdout);
+       vec[vecp] = 0;
+       if(!pr) {
+               vec[0] = "c:mh-type";
+               execv(showproc, vec);
+       } else {
+               vec[0] = "mh-pr";
+               execv(prproc, vec);
+       }
+       perror(pr ? prproc : showproc);
+ leave:
+       m_update();
+       done(0);
+}
+
+
diff --git a/docs/historical/2.9BSD/cmds/strings.h b/docs/historical/2.9BSD/cmds/strings.h
new file mode 100644 (file)
index 0000000..70c67e5
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * This file gives extern declarations to all the strings
+ * that we might ever reference.
+ *
+ * I don't know if this what strings.h is supposed to be,
+ * but this is as good a first guess as I can handle.
+ */
+
+extern char *anoyes[];
+extern char    *components;
+extern char    *current;
+extern char    *defalt;
+extern char    *distcomps;
+extern char    *draft;
+extern char    *fileproc;
+extern char    *foldprot;
+extern char    *hostname;
+extern char    *installproc;
+extern char    *listname;
+extern char    *lockdir;
+extern int     lockwait;
+extern char    *lsproc;
+extern char    *mailboxes;
+extern char    *mailproc;
+extern char    *mh_deliver;
+extern char    *mh_prof;
+extern char    *mhnews;
+extern char    *msgprot;
+extern char    *pfolder;
+extern char    *prproc;
+extern char    *scanproc;
+extern char    *sendproc;
+extern char    *showproc;
+extern char    *stdcomps;
+extern char    *stddcomps;
+extern char    *sysed;
+
+#ifdef UNIXCOMP
+extern char    *unixtomh;
+extern char    *Mailprog;
+extern char    *localname;
+#endif
diff --git a/docs/historical/2.9BSD/cmds/unixtomh.c b/docs/historical/2.9BSD/cmds/unixtomh.c
new file mode 100644 (file)
index 0000000..26a33de
--- /dev/null
@@ -0,0 +1,602 @@
+#
+
+/*
+ * This program copies the mail file in standard unix format
+ * given as $1 to the file $2 in Rand Message Handler format.
+ * The change made is to bracket each message with a line
+ * containing 4 control-A's and to split the From line into
+ * a From: field and a Date: field, with the date in Arpanet
+ * standard format.
+ *
+ * This program is designed to be called from the rand mh program
+ * ``inc''
+ *
+ * Set SENDMAIL if you are running sendmail -- this guarantees that
+ * From: and Date: lines will appear already, and will put the info
+ * in the UNIX-From line into a Received-From: field.
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/timeb.h>
+#include <ctype.h>
+
+
+struct headline {
+       char    *l_from;        /* The name of the sender */
+       char    *l_tty;         /* His tty string (if any) */
+       char    *l_date;        /* The entire date string */
+};
+
+char *savestr(), *copyin(), *copy(), *nextword(), *calloc();
+char *index();
+
+#define        NOSTR           ((char *) 0)
+#define        UUCP                    /* Undo strange uucp naming */
+
+main(argc, argv)
+       char **argv;
+{
+       char linebuf[BUFSIZ];
+       register int maybe;
+       register FILE *inf, *outf;
+       int inhdr, infld;
+
+       if (argc > 3) {
+               fprintf(stderr, "Usage: unixtomh name1 name2\n");
+               exit(1);
+       }
+       outf = inf = NULL;
+       if (argc < 3)
+               outf = stdout;
+       if (argc < 2)
+               inf = stdin;
+       if (inf == NULL && (inf = fopen(argv[1], "r")) == NULL) {
+               perror(argv[1]);
+               exit(1);
+       }
+       if (outf == NULL && (outf = fopen(argv[2], "w")) == NULL) {
+               perror(argv[2]);
+               exit(1);
+       }
+       maybe = 1;
+       inhdr = 0;
+       infld = 0;
+       while (nullgets(linebuf, BUFSIZ, inf) > 0) {
+               if (maybe && ishead(linebuf)) {
+                       fputs("\1\1\1\1\n", outf);
+                       inhdr++;
+                       dohead(linebuf, inf, outf);
+                       continue;
+               }
+               if (strlen(linebuf) == 0) {
+                       maybe = 1;
+                       inhdr = 0;
+                       infld = 0;
+                       putc('\n', outf);
+                       continue;
+               }
+               else
+                       maybe = 0;
+#ifndef SENDMAIL
+               if (inhdr && strncmp(linebuf, "Date: ", 6) == 0)
+                       continue;
+               if (inhdr && strncmp(linebuf, "From: ", 6) == 0)
+                       continue;
+#endif SENDMAIL
+               if (infld && isspace(linebuf[0])) {
+                       fputs(linebuf, outf);
+                       putc('\n', outf);
+                       continue;
+               }
+               if (inhdr && !isspace(linebuf[0])) {
+                       char *colp, *sp;
+
+                       colp = index(linebuf, ':');
+                       sp = index(linebuf, ' ');
+                       if (colp == NOSTR || sp == NOSTR || sp < colp) {
+                               putc('\n', outf);
+                               inhdr = 0;
+                       }
+                       else
+                               infld = 1;
+               }
+               fputs(linebuf, outf);
+               putc('\n', outf);
+       }
+       fputs("\1\1\1\1\n", outf);
+       fflush(outf);
+       if (ferror(outf)) {
+               fprintf(stderr, "unixtomh: write: ");
+               perror(argv[2]);
+               exit(1);
+       }
+       exit(0);
+}
+
+/*
+ * Get a line from the given file descriptor, don't return the
+ * terminating newline.
+ */
+
+nullgets(linebuf, sz, file)
+       char linebuf[];
+       register FILE *file;
+{
+       register char *cp;
+       register int c, cnt;
+
+       cp = linebuf;
+       cnt = sz;
+       do {
+               if (--cnt <= 0) {
+                       *cp = 0;
+                       return(1);
+               }
+               c = getc(file);
+               *cp++ = c;
+       } while (c != EOF && c != '\n');
+       if (c == EOF && cp == linebuf+1)
+               return(0);
+       *--cp = 0;
+       return(1);
+}
+
+/*
+ * Output the fields extracted from the From line --
+ * From: and Date:  Untangle UUCP stuff if appropriate.
+ */
+
+dohead(line, infile, outfile)
+       char line[];
+       register FILE *infile, *outfile;
+{
+       register char *cp;
+       struct headline hl;
+       char parbuf[BUFSIZ];
+#ifdef UUCP
+       char *word();
+       char namebuf[BUFSIZ];
+       char linebuf[BUFSIZ];
+       int first;
+       long curoff;
+#endif UUCP
+
+       parse(line, &hl, parbuf);
+#ifndef SENDMAIL
+       putdate(hl.l_date, outfile);
+#endif SENDMAIL
+#ifdef UUCP
+       if (strcmp(hl.l_from, "uucp") == 0) {
+               strcpy(namebuf, "");
+               first = 1;
+               for (;;) {
+                       curoff = ftell(infile);
+                       if (fgets(linebuf, BUFSIZ, infile) == NULL)
+                               break;
+                       if (strcmp(word(1, linebuf), ">From") != 0)
+                               break;
+                       if (strcmp(word(-3, linebuf), "remote") != 0)
+                               break;
+                       if (strcmp(word(-2, linebuf), "from") != 0)
+                               break;
+                       if (first) {
+                               strcpy(namebuf, word(-1, linebuf));
+                               strcat(namebuf, "!");
+                               strcat(namebuf, word(2, linebuf));
+                               first = 0;
+                       }
+                       else {
+                               strcpy(rindex(namebuf, '!')+1,
+                                   word(-1, linebuf));
+                               strcat(namebuf, "!");
+                               strcat(namebuf, word(2, linebuf));
+                       }
+               }
+               fseek(infile, curoff, 0);
+#ifdef SENDMAIL
+               if (!first)
+                       fprintf(outfile, "Return-Path: <%s>\n", namebuf);
+#else SENDMAIL
+               if (first)
+                       fprintf(outfile, "From: uucp\n");
+               else
+                       fprintf(outfile, "From: %s\n", namebuf);
+#endif SENDMAIL
+               return;
+       }
+#endif UUCP
+#ifdef SENDMAIL
+       if (hl.l_from[0] == '<')
+               fprintf(outfile, "Return-Path: %s\n", hl.l_from);
+       else
+               fprintf(outfile, "Return-Path: <%s>\n", hl.l_from);
+#else SENDMAIL
+       fprintf(outfile, "From: %s\n", hl.l_from);
+#endif SENDMAIL
+}
+
+#ifdef UUCP
+
+/*
+ * Return liberal word i from the given string.
+ * The words are numbered 1, 2, 3, . . .  from the left
+ * and -1, -2, . . . from the right.
+ */
+
+char *
+word(index, str)
+       char str[];
+{
+       register char *cp;
+       char *secbuf;
+       register int c;
+       static char retbuf[100];
+       char *gword();
+
+       cp = str;
+       if ((c = index) > 0) {
+               while (c-- > 0)
+                       cp = gword(cp, retbuf);
+               return(retbuf);
+       }
+       if (c == 0)
+               return("");
+       secbuf = (char *) malloc(strlen(str) + 1);
+       strcpy(secbuf, str);
+       rev(secbuf);
+       cp = word(-index, secbuf);
+       rev(cp);
+       return(cp);
+}
+
+/*
+ * Skip leading blanks in the string, return
+ * first liberal word collected.
+ */
+
+char *
+gword(cp, buf)
+       register char *cp;
+       char buf[];
+{
+       register char *cp2;
+
+       cp2 = buf;
+       while (*cp && any(*cp, " \t\n"))
+               cp++;
+       while (*cp && !any(*cp, " \t\n"))
+               *cp2++ = *cp++;
+       *cp2 = 0;
+       return(cp);
+}
+
+/*
+ * Reverse the characters in the string in place
+ */
+
+rev(str)
+       char str[];
+{
+       register char *cpl, *cpr;
+       register int s;
+
+       s = strlen(str);
+       cpl = str;
+       cpr = &str[s-1];
+       while (cpl < cpr) {
+               s = *cpl;
+               *cpl++ = *cpr;
+               *cpr-- = s;
+       }
+}
+#endif UUCP
+
+/*
+ * Save a string in dynamic space.
+ * This little goodie is needed for
+ * a headline detector in head.c
+ */
+
+char *
+savestr(str)
+       char str[];
+{
+       register char *top;
+
+       top = calloc(strlen(str) + 1, 1);
+       if (top == NOSTR) {
+               fprintf(stderr, "unixtomh:  Ran out of memory\n");
+               exit(1);
+       }
+       copy(str, top);
+       return(top);
+}
+
+/*
+ * See if the passed line buffer is a mail header.
+ * Return true if yes.  Note the extreme pains to
+ * accomodate all funny formats.
+ */
+
+ishead(linebuf)
+       char linebuf[];
+{
+       register char *cp;
+       struct headline hl;
+       char parbuf[BUFSIZ];
+
+       cp = linebuf;
+       if (!isname("From ", cp, 5))
+               return(0);
+       parse(cp, &hl, parbuf);
+       if (hl.l_from == NOSTR || hl.l_date == NOSTR) {
+               fail(linebuf, "No from or date field");
+               return(0);
+       }
+       if (!isdate(hl.l_date)) {
+               fail(linebuf, "Date field not legal date");
+               return(0);
+       }
+       
+       /*
+        * I guess we got it!
+        */
+
+       return(1);
+}
+
+fail(linebuf, reason)
+       char linebuf[], reason[];
+{
+       return;
+}
+
+/*
+ * Split a headline into its useful components.
+ * Copy the line into dynamic string space, then set
+ * pointers into the copied line in the passed headline
+ * structure.  Actually, it scans.
+ */
+
+parse(line, hl, pbuf)
+       char line[], pbuf[];
+       struct headline *hl;
+{
+       register char *cp, *dp;
+       char *sp;
+       char word[BUFSIZ];
+
+       hl->l_from = NOSTR;
+       hl->l_tty = NOSTR;
+       hl->l_date = NOSTR;
+       cp = line;
+       sp = pbuf;
+
+       /*
+        * Skip the first "word" of the line, which should be "From"
+        * anyway.
+        */
+
+       cp = nextword(cp, word);
+       dp = nextword(cp, word);
+       if (word[0] != 0)
+               hl->l_from = copyin(word, &sp);
+       if (isname(dp, "tty", 3)) {
+               cp = nextword(dp, word);
+               hl->l_tty = copyin(word, &sp);
+               if (cp != NOSTR)
+                       hl->l_date = copyin(cp, &sp);
+       }
+       else
+               if (dp != NOSTR)
+                       hl->l_date = copyin(dp, &sp);
+}
+
+/*
+ * Copy the string on the left into the string on the right
+ * and bump the right (reference) string pointer by the length.
+ * Thus, dynamically allocate space in the right string, copying
+ * the left string into it.
+ */
+
+char *
+copyin(src, space)
+       char src[];
+       char **space;
+{
+       register char *cp, *top;
+       register int s;
+
+       s = strlen(src);
+       cp = *space;
+       top = cp;
+       strcpy(cp, src);
+       cp += s + 1;
+       *space = cp;
+       return(top);
+}
+
+/*
+ * See if the two passed strings agree in the first n characters.
+ * Return true if they do, gnu.
+ */
+
+isname(as1, as2, acount)
+       char *as1, *as2;
+{
+       register char *s1, *s2;
+       register count;
+
+       s1 = as1;
+       s2 = as2;
+       count = acount;
+       if (count > 0)
+               do
+                       if (*s1++ != *s2++)
+                               return(0);
+               while (--count);
+       return(1);
+}
+
+/*
+ * Test to see if the passed string is a ctime(3) generated
+ * date string as documented in the manual.  The template
+ * below is used as the criterion of correctness.
+ * Also, we check for a possible trailing time zone using
+ * the auxtype template.
+ */
+
+#define        L       1               /* A lower case char */
+#define        S       2               /* A space */
+#define        D       3               /* A digit */
+#define        O       4               /* An optional digit or space */
+#define        C       5               /* A colon */
+#define        N       6               /* A new line */
+#define U      7               /* An upper case char */
+
+char ctypes[] = {U,L,L,S,U,L,L,S,O,D,S,D,D,C,D,D,C,D,D,S,D,D,D,D,0};
+char tmztypes[] = {U,L,L,S,U,L,L,S,O,D,S,D,D,C,D,D,C,D,D,S,U,U,U,S,D,D,D,D,0};
+
+isdate(date)
+       char date[];
+{
+       register char *cp;
+
+       cp = date;
+       if (cmatch(cp, ctypes))
+               return(1);
+       return(cmatch(cp, tmztypes));
+}
+
+/*
+ * Match the given string against the given template.
+ * Return 1 if they match, 0 if they don't
+ */
+
+cmatch(str, temp)
+       char str[], temp[];
+{
+       register char *cp, *tp;
+       register int c;
+
+       cp = str;
+       tp = temp;
+       while (*cp != '\0' && *tp != 0) {
+               c = *cp++;
+               switch (*tp++) {
+               case L:
+                       if (!islower(c))
+                               return(0);
+                       break;
+
+               case S:
+                       if (c != ' ')
+                               return(0);
+                       break;
+
+               case D:
+                       if (!isdigit(c))
+                               return(0);
+                       break;
+
+               case O:
+                       if (c != ' ' && !isdigit(c))
+                               return(0);
+                       break;
+
+               case C:
+                       if (c != ':')
+                               return(0);
+                       break;
+
+               case N:
+                       if (c != '\n')
+                               return(0);
+                       break;
+
+               case U:
+                       if (!isupper(c))
+                               return(0);
+                       break;
+               }
+       }
+       if (*cp != '\0' || *tp != 0)
+               return(0);
+       return(1);
+}
+
+/*
+ * Collect a liberal (space, tab delimited) word into the word buffer
+ * passed.  Also, return a pointer to the next word following that,
+ * or NOSTR if none follow.
+ */
+
+char *
+nextword(wp, wbuf)
+       char wp[], wbuf[];
+{
+       register char *cp, *cp2;
+
+       if ((cp = wp) == NOSTR) {
+               copy("", wbuf);
+               return(NOSTR);
+       }
+       cp2 = wbuf;
+       while (!any(*cp, " \t") && *cp != '\0')
+               *cp2++ = *cp++;
+       *cp2 = '\0';
+       while (any(*cp, " \t"))
+               cp++;
+       if (*cp == '\0')
+               return(NOSTR);
+       return(cp);
+}
+
+/*
+ * Copy str1 to str2, return pointer to null in str2.
+ */
+
+char *
+copy(str1, str2)
+       char *str1, *str2;
+{
+       register char *s1, *s2;
+
+       s1 = str1;
+       s2 = str2;
+       while (*s1)
+               *s2++ = *s1++;
+       *s2 = 0;
+       return(s2);
+}
+
+/*
+ * Is ch any of the characters in str?
+ */
+
+any(ch, str)
+       char *str;
+{
+       register char *f;
+       register c;
+
+       f = str;
+       c = ch;
+       while (*f)
+               if (c == *f++)
+                       return(1);
+       return(0);
+}
+
+/*
+ * Convert lower case letters to upper case.
+ */
+
+raise(c)
+       register int c;
+{
+       if (c >= 'a' && c <= 'z')
+               c += 'A' - 'a';
+       return(c);
+}
diff --git a/docs/historical/2.9BSD/cmds/vars.c b/docs/historical/2.9BSD/cmds/vars.c
new file mode 100644 (file)
index 0000000..cac97e0
--- /dev/null
@@ -0,0 +1,10 @@
+       register char *cp;
+       register int i,j;
+       register FILE *in;
+       char name[NAMESZ], field[BUFSIZ];
+       char *drft, *msgid, *replto, *from, *cc, *sub, *date, *to;
+       int state, out, status, intr;
+       int pid, wpid;
+       char **argp, *address;
+       char ackfile[10];
+       char buf[BUFSIZ];
diff --git a/docs/historical/2.9BSD/doc/Alias.Design b/docs/historical/2.9BSD/doc/Alias.Design
new file mode 100644 (file)
index 0000000..ed2490a
--- /dev/null
@@ -0,0 +1,67 @@
+The Alias file for mail delivery is the file
+
+       /etc/MailAliases
+
+Each line of the alias file has the format:
+
+match : alias
+
+Where:
+
+       alias       :=  simple-list
+                   |   "<" alias-file
+                   |   "=" UNIX-group
+                   |   "*"
+
+       simple-list :=  simple-name
+                   |   simple-list, simple-name
+
+Alias-file is a fully qualified UNIX file name.  UNIX-group is a
+group name from /etc/group.  A simple-name is a local user login
+name, including only alphanumerics, `.' and `-'.  Throughout this
+file case is ignored, except for alias-file.
+
+In match, a trailing * on a name will match anything. (See example
+below.)
+
+The procedure for mail aliasing is:
+
+1) Build a list of all addresses from the message to be
+   delivered, eliminating duplicates.
+
+2) For each line in the alias file, compare "match" against all
+   of the existing addresses.  If a match, remove the matched
+   name from the address list, and add each new alias name to the
+   address list if it is not already on the list.
+
+Since the alias file is read line by line, forward references
+work, but backward references are not recognized, thus, there is
+no recursion.
+
+E.g.:
+
+Borden: bruce
+Bruce: bsb
+Wharman: mike
+ASRL: bsb, mike, obrien, giarla
+UNIX-committee: < /usr/people/unix-committee
+System: = sys
+Everyone: *
+news.*: news
+   ...
+
+In the "unix-committee" example, the file "/usr/people/unix-
+committee" contains one simple-name, or a list of comma separated
+simple-names.  A new-line will be treated as a blank in this
+file, s.a.
+
+       foo, fie,
+       fum, fiddle
+
+In the "system" case, the names from the group "sys" will be used
+as the expanded name list.
+
+In the "news.*" case, all names of the form "news.<anything>" will
+be mapped to "news".  This is used for the MH news facility.
+
+Bruce Borden    October 1979
diff --git a/docs/historical/2.9BSD/doc/MH_VGRIND b/docs/historical/2.9BSD/doc/MH_VGRIND
new file mode 100755 (executable)
index 0000000..346e7f6
--- /dev/null
@@ -0,0 +1,27 @@
+vgrind aliascheck.c annotate.c comp.c deliver.c dist.c emitl.c\
+       errno.h file.c folder.c forw.c grep.c inc.c install-mh.c\
+       mail.c mh.h news.c next.c nexthdr.c pick.c prevhdr.c\
+       prompter.c replsubs.c reply.c rescue.c rmf.c rmm.c scan.c\
+       scansub.c send.c show.c strings.h strings/Mailprog.c strings/anoyes.c\
+       strings/components.c strings/current.c strings/defalt.c\
+       strings/distcomps.c strings/draft.c strings/fileproc.c\
+       strings/foldprot.c strings/hostname.c strings/installproc.c\
+       strings/listname.c strings/localname.c strings/lockdir.c\
+       strings/lsproc.c strings/mailboxes.c strings/mailproc.c\
+       strings/mh_defs.c strings/mh_deliver.c strings/mh_prof.c\
+       strings/mhnews.c strings/msgprot.c strings/pfolder.c\
+       strings/prproc.c strings/scanproc.c strings/sendproc.c\
+       strings/showproc.c strings/stdcomps.c strings/stddcomps.c\
+       strings/strings.h strings/sysed.c strings/unixtomh.c\
+       subs/add.c subs/ambigsw.c subs/atooi.c subs/brkstring.c\
+       subs/cdate.c subs/cndfree.c subs/concat.c subs/copy.c subs/copyip.c\
+       subs/cputc.c subs/crpbrkstring.c subs/done.c subs/fdcompare.c\
+       subs/gans.c subs/getans.c subs/getcpy.c subs/help.c subs/invo_name.c\
+       subs/locv.c subs/m_convert.c subs/m_delete.c subs/m_edit.c\
+       subs/m_find.c subs/m_getdefs.c subs/m_getfld.c subs/m_getfolder.c\
+       subs/m_gmprot.c subs/m_gmsg.c subs/m_maildir.c subs/m_name.c\
+       subs/m_replace.c subs/m_send.c subs/m_setcur.c subs/m_update.c\
+       subs/makedir.c subs/makename.c subs/mh.h subs/peekc.c\
+       subs/pr_array.c subs/printsw.c subs/putdate.c subs/r1bindex.c\
+       subs/showfile.c subs/smatch.c subs/ssequal.c subs/trimcpy.c\
+       subs/type.c subs/uleq.c support/l.c unixtomh.c vars.c
diff --git a/docs/historical/2.9BSD/doc/MHgenerate b/docs/historical/2.9BSD/doc/MHgenerate
new file mode 100644 (file)
index 0000000..2ef9669
--- /dev/null
@@ -0,0 +1,122 @@
+                      HOW TO GENERATE AN MH
+
+ASSUMPTIONS/RESTRICTIONS:
+
+        All of the code is written for Version 7 C, and assumes
+the existence of appropriate Version 7 /usr/include files.  It
+also uses the Version 7 stdio package, which is somewhat
+different than the Phototypesetter stdio!
+
+        There is moderate usage of Version 7 UNIX features,
+including:
+
+               ftime() system call
+               execlp() & execvp() environment exec calls
+               getenv() environment access
+
+also, login has to be changed to add the environment entry
+"USER=name".  This is used during scan listings to see if the
+message "From" should be replaced by "To:name".  This string is
+NOT used to determine the "From: name" stamp on outgoing mail.
+
+        All of these usages ARE replaceable by subroutines which
+do the same thing, only slower.  That is, a line of the form:
+
+               homedir = getenv("HOME");
+
+should be replaced by something like:
+
+               homedir = gethome();
+
+and the routine gethome() written to return the home directory by
+looking through /etc/passwd for the line matching the process'
+getuid().  This goes for the environment variable "USER" as well.
+
+The routines execlp() & execvp() are simply fancy exec's, which
+use the "PATH" environment variable to determine the search path
+by which to find the executable image.  They can be replaced by
+routines which use a default search list.  They also call a shell
+to execute the file in the same way the shell handles shell
+scripts.
+
+
+
+PROCEDURE:
+
+
+1) Read the MH directory tree onto a file system.
+
+2) Examine all of the files in directory strings.  These are the
+   names and paths of all of the programs MH calls upon.  Change
+   them to suit your installation.  Most of the files contain
+   short descriptions of what the strings are.
+
+3) In the top level directory, utter:
+
+       make strings.a subs.a all
+
+   This will make both of the libraries: strings.a and subs.a,
+   and ALL of the executable modules.
+
+4) AS SU:
+
+       make onceonly           This renames conflicting bell
+                               programs, and makes requisite
+                               directories.
+
+       make install            This puts all of the programs
+                               into appropriate directories.
+
+That's it.  Take a close look at the Makefile--it does LOTS of
+work.  If you don't want to install everything in standard
+places, run "make install" with the variables MHDIR=newdir and
+BINDIR=newdir pointing wherever you wish.  If you do this, you
+probably have to change some of the path names in the strings
+files.  For most of them, you can get away with adding profile
+entries to change where the default paths are sought.
+
+If you don't have `make':
+
+     You'll have to use the make file as a template for commands
+     to give by hand.  Basically each section of the make file
+     defines the sequence of shell commands needed to create the
+     object before the `:'.  The list immediately after the `:'
+     specifies the dependencies for the object--that is, those
+     objects which either must be made first, or those modules
+     that if they've changed, the object must be rebuilt.  The
+     following lines (up to the next object) are simply shell
+     commands to be executed.  Make knows how to create .o's from
+     .c's, and the "CFLAGS= -O" at the beginning tells it to
+     include optimization when it does a c compile.
+
+If you don't have stdio (i.e. some version 7 C compiler):
+
+     Punt.  I recently converted the whole package from the old
+     getc/putc/iobuf subroutines--including lots of upgrades/
+     improvements, it took me about a week.  Expect it to take a
+     couple of weeks for someone good to convert back.
+     Basically, convert the subroutines, then once you've
+     converted one module (start with show or comp), you'll find
+     all the rest VERY similar.  Some day I may split out all of
+     the system dependencies, but don't hold your breath.
+
+
+
+As a last resort:
+
+     Feel free to call me, but please don't expect me to spend
+hours helping.  Collect your questions/problems, and get in touch
+and I'll see what I can do.  I can be reached:
+
+       via ARPANET:    Borden at Rand-UNIX
+
+       Mail:           The Rand Corporation
+                       1700 Main Street
+                       Santa Monica, CA 90406
+
+       Phone:          (213) 399-0568 x 7463
+
+
+
+Bruce Borden
+October, 1979
diff --git a/docs/historical/2.9BSD/doc/MHnotes b/docs/historical/2.9BSD/doc/MHnotes
new file mode 100644 (file)
index 0000000..93167eb
--- /dev/null
@@ -0,0 +1,178 @@
+This file contains some notes on features/bugs/etc which are
+not documented in the "MH User's Manual", as well as some notes
+on future directions.  See MHgenerate for more info.  Some of
+these notes assume VAX/V7 UNIX--as noted by {V/V7}.
+
+0) Directories:
+       support contains files which get copied to /etc/mh, as
+               well as some miscellaneous Rand support programs
+       subs    contains support subroutines--built into subs.a
+       strings contains c files which define all of the default
+               names and paths used by the package->strings.a
+       Extras  old and un-supported code--much of it not
+                converted to V7.  Look at libg/libh for help in
+                getting around V7 features.
+       DOC     contains the MH User's Manual document in nroff/
+                troff form.  This requires the Phototypesetter or
+                V7 version of nroff/troff, AND the Berkeley -me
+                macros.
+
+1) Undocumented Feature:  The paths to the various programs which
+   MH exec's are kept in variables named something like "lsproc".
+   (See the strings directory.) While reading in the user's
+   profile, (m_getdefs()) a component matching one of these exec
+   path names, will cause the default string to be replaced by
+   the profile entry argument.  Thus, the profile entry "lsproc:
+   /usr/foo/bin/newls" will cause all MH programs using "lsproc"
+   to get a new ls.  At least for now, there is no way to specify
+   switches.  This mapping is arranged by the "procs" structure
+   in m_getdefs.c--keep it up to date if new exec procs are
+   added.
+
+2) Collision:  Take a close look at the "onceonly" entry of the
+   Makefile.  Bell already has a program named `file', which the
+   makefile will rename to `filetype', which is what it tries to
+   indicate.  If you really want to, you might rename the MH
+   command `file', but I have yet to hear of an even vaguely
+   reasonable alternative.
+
+3) Different Approach:  Using the Berkeley C shell (csh),
+   "multiple links to the same file with different profile
+   entries" is better served with aliases.
+
+4) Collision: {V/V7} BELL mail cannot co-exist with MH--IF THEY
+   SHARE THE SAME MAILBOXES, otherwise they co-exist fine!  If
+   you use the standard (VAX) mail directory /usr/spool/mail for
+   MH, you should also install the MH version of the mail
+   program.  It is much nicer, and integrates with MH cleanly.
+   The advantage of using /usr/spool/mail is that login will
+   notify of new mail.
+
+5) Feature: If you add a line like:
+
+       30 1 * * * /etc/mh/aliascheck -mail bsb
+
+   to crontab, then every morning at 1:30 AM, the alias file will
+   be checked against the /etc/passwd file to see that
+   inconsistencies haven't been introduced.  In particular, a
+   line in the alias file may be "tom: jones" (because Tom Jones
+   likes to be called Tom), but if tom is also a valid user name,
+   tom will no longer receive any mail!  This program also prints
+   any mail drops in /usr/spool/mail which don't belong to a
+   valid user (i.e. a deleted or renamed user id).
+
+   "Aliascheck -mail name" will check the consistency and mail
+   the specified user a short status message.
+
+   This program also checks to see if there are any users who do
+   not belong to any group, or any user in a group which is missing
+   from the passwd file.  This latter is an inconsistency on all
+   systems, whereas the former is not required except at Rand, and
+   won't be compiled without the "-DRAND" cc flag in the makefile.
+
+6) Hidden Feature:  At the request of some of the Rand staff,
+   there is the ability to invoke a user-specified deletion-
+   program to implement message deletion, rather than getting the
+   default comma renaming convention (see next item).  If a
+   user's profile contains the line: "Delete-prog: path", the
+   specified path will be called with a list of files needing
+   deletion.  All this code works...
+
+7) Feature:  When a message (draft or in a folder) is "removed",
+   it is really renamed with a leading comma.  E.g. foo -> ,foo.
+   At Rand we have a program called the midnight skulker which
+   goes through the whole system and removes all backup (starting
+   with comma), a.out, and core files.  This backup convention
+   gives users a chance to undo spurious removes, at least all
+   day.  You may want to replace these renames with a simple
+   unlink(), or each user may get this effect by specifying
+   "Delete-prog: /bin/rm" in his/her profile.
+
+8) Feature:  NEWS.  The news facility is undocumented in the MH
+   manual, because it is a very new addition to the package.  SO,
+   here it is...
+
+        The directory /usr/news should be created--it will
+        contain the folders for news topics, and various support
+        files.  The news items are strictly MH folders, and users
+        can utilize all of the MH commands on them.  The news
+        program is similar to "show", but it shows `unseen' news
+        as the default, keeping a separate entry in the users
+        profile for each news topic indicating the highest item
+       the user has seen.  These entries look like
+               "news-<topic>: highest-seen".
+
+        Rather than read through the news folders to determine
+        the number of entries, a file with name .<topic> (i.e.
+        period followed by the topic name) is kept with length
+        equal to highest message number.  Thus, to determine if a
+        user hasn't seen some news, the news directory
+        (/usr/news) is read, and for each non-period beginning
+        file (i.e. each folder), stat the associated period
+        beginning file, and compare its length with the users
+        profile news entry for the same name.  If the user has no
+        entry, or it is less than the length of the period-file,
+        then show him the remainder of the news in each such
+        topic.
+
+        The program `l' is used to display each message, and the
+        highest item profile entry is updated prior to each
+        individual message displayed, so <del> will leave the
+        user's profile in the proper state for the next news
+        request.
+
+        Add a user to the system called news, with home directory
+        /usr/news and add the line:
+
+               news.*: news
+
+        to /etc/MailAlias.  Thus, to add news to a topic, it is
+        only necessary to mail to news.topic, and it will happen.
+        To make the automatic filing into folders happen, copy
+        the file support/news-mh_receiv to /usr/news/.mh_receive.
+        This is a shell script which will get invoked whenever
+        mail is sent to the user news (see next "undocumented
+        feature").
+
+        Problems:  I have yet to write the program which packs
+        news folders.  Items can be readily removed (as long as
+        they are not the last item in the folder), but if the
+        folder is packed (after some months/years the item
+        numbers will reach the 999 limit), it is necessary to go
+        through everyones .mh_profile files and reset the
+        highest-seen numbers.  Not hard to write, I just haven't
+        done it yet.  Also, the receive shell script should be
+        recoded in C to speed it up considerably.
+
+9) Undocumented Feature:  If a user has an executable program or
+   shell script named ".mh_receive" in his home directory, then
+   it will be executed by the mail deliverer RATHER than
+   appending mail items to the user's mail file
+   (/usr/spool/mail/name).  This program will be called with:
+
+       execlp(prog, prog, tmpfil, mail, home, 0);
+
+   where prog is the receive program, tmpfil is a file in
+   /usr/tmp which is the mail to be received, mail is the path of
+   the user's mail drop (/usr/spool/mail/name), and home is the
+   $HOME directory of the user.  File descriptor 3 will have
+   tmpfil opened on it read only.  These are all the RECEIVER'S
+   parameters, not the sender's.  Also, the environment is set up
+   with appropriate values for HOME and USER.
+
+   Eventually, the goal is to have received mail LINKED into
+   user's inbox folders, rather than appended to their mailboxes.
+   This will facilitate the sending of mail to large distribution
+   lists (Rand is always tight on space!) Have a look at the news
+   .mh_receive file for an example of this facility.
+
+   Warning: appropriate interlocks are implemented in "deliver"
+   to prevent collisions when it appends to mailboxes, but it is
+   up to the users's .mh_receive program to provide its own
+   interlocks!
+
+
+
+
+Bruce Borden
+February 1980
diff --git a/docs/historical/2.9BSD/doc/Makefile b/docs/historical/2.9BSD/doc/Makefile
new file mode 100644 (file)
index 0000000..49f2d78
--- /dev/null
@@ -0,0 +1,2 @@
+manual:
+       itroff -me titlepage mh.me
diff --git a/docs/historical/2.9BSD/doc/mh.me b/docs/historical/2.9BSD/doc/mh.me
new file mode 100644 (file)
index 0000000..630fa1a
--- /dev/null
@@ -0,0 +1,2510 @@
+.de $c                          \" Major Heading printer
+.ce
+.b "\\s12\\n+(ch.\\ \\$1\\s0"   \" 12 Point Bold Header
+.(x
+
+\ \ \ \\n(ch.\\ \\ \\$1
+.)x
+.sp 45p         \" 45 point space or about 1/2 inch
+..
+\".nr xs .15v     \" Put index entries closer together
+.(x
+
+Section
+.)x _
+.de $0          \" Sub-Heading macro called AFTER printing the heading
+.(x
+.sp .3v
+.ti .5i
+\\$1
+.)x
+..
+.de $s          \" Macro to print footnote separator
+\"\l'2i'        \" No line drawn
+.if n \
+.       sp 1.3  \" But extra space to make up for it.
+..
+.fc ^ ~         \" The characters ^ and ~ CANNOT BE USED
+\"                 throughout this document except as field
+\"                 delimiter & pad indicator!
+.he ''-%-''
+.ll 32P         \" 32 Picas or about 5+1/3 inch Line Length
+.if n .ll 72m   \" Use 72 ems for nroff
+.nr ss 30p      \" 30 point space before section titles
+.nr fm 5v       \" Rand likes bigger than normal [3v] bottom margins
+.nr bm 7v       \"   ditto
+.ds . \\fB.\\fP\\h'-(1m/3)' \" Bold period to stand out.
+.ds << <\\h!-(\\w'<'/2)!<
+.ds >> >\\h!-(\\w'>'/2)!>
+.ds ** \v'-3p'\s+1*\s0\v'+3p'
+.++ C
+.+c INTRODUCTION
+.pp
+Although people can travel cross-country in hours and can
+reach others by telephone in seconds, communications still depend
+heavily upon paper, most of which is distributed through the mails.
+.pp
+There are several major reasons for this continued dependence on
+written documents.
+First, a written document may be proofread
+and corrected prior to its distribution, giving the author
+complete control over his words.
+Thus, a written document is
+better than a telephone conversation in this respect.
+Second,
+a carefully written document is far less likely to be
+misinterpreted or poorly translated than a phone conversation.
+Third, a signature offers reasonable verification of authorship,
+which cannot be provided with media such as telegrams.
+.pp
+However, the need for
+.u fast ,
+accurate, and reproducible document distribution is
+obvious.
+One solution in widespread use is the telefax.
+Another
+that is rapidly gaining popularity is electronic mail.
+Electronic mail is similar to telefax in that the data to be sent
+are digitized, transmitted via phone lines, and
+turned back into a document at the receiver.
+The advantage of
+electronic mail is in its compression factor.
+Whereas a telefax
+must scan a page in very fine lines and send all of the black and
+white information, electronic mail assigns characters fixed
+codes which can be transmitted as a few bits of information.
+Telefax presently has the advantage of being able to transmit an
+arbitrary page, including pictures, but electronic mail is
+beginning to deal with this problem.
+Electronic mail also integrates well
+with current directions in office automation, allowing documents
+prepared with sophisticated equipment at one site to be quickly
+transferred and printed at another site.
+.pp
+Currently, most electronic mail is intraorganizational,
+with mail transfer remaining within one computer.
+As computer
+networking becomes more common, however, it is becoming more feasible to
+communicate with anyone whose computer can be linked to your
+own via a network.
+.pp
+The pioneering efforts on general-purpose electronic mail
+were by organizations using the Defense Department's ARPANET.[1]
+The capability to send messages between computers existed before
+the ARPANET was developed, but it was used only in limited ways.
+With the advent of the
+ARPANET, tools began to be developed which made it convenient for
+individuals or organizations to distribute messages
+over broad geographic areas, using
+diverse computer facilities.
+The interest and activity in
+message systems has now reached such proportions that steps
+have been taken within the DoD to coordinate and
+unify the development of military message systems.
+The use of electronic mail is expected to increase
+dramatically in the next few years.
+The utility of such systems
+in the command and control and intelligence environments is
+clear, and applications in these areas will probably lead the
+way.
+As the costs for sending and handling electronic messags
+continue their rapid decrease, such uses can be
+expected to spread rapidly into other areas and, of course, will
+not be limited to the DoD.
+.pp
+A message system provides tools that help users (individuals
+or organizations) deal with messages in various ways.
+Messages
+must be composed, sent, received, stored, retrieved,
+forwarded, and replied to.
+Today's best interactive computer
+systems provide a variety of word-processing and information
+handling capabilities.
+The message handling facilities should be
+well integrated with the rest of the system, so as to be a
+graceful extension of overall system capability.
+.pp
+The message system described in this report, MH, provides most of the
+features that can be found in other message systems and also
+incorporates some new ones.
+It has been built on the UNIX time-sharing
+system,[2] a popular operating system for the DEC PDP-11
+and VAX classes of computers.
+A \*(lqsecure\*(rq operating
+system similar to UNIX is currently being developed,[3]
+and that system will also run MH.
+.pp
+This report provides a complete description of MH and
+thus may serve as a user's manual, although parts of the report
+will be of interest to non-users as well.
+Sections 2 and 3, the
+Overview and Tutorial, present the key
+ideas of MH and will give those not familiar with message systems
+an idea of what such systems are like.
+.pp
+MH consists of a set of commands which use some special
+files and conventions.
+Section 4 covers the information
+a user needs to know in addition to the
+commands.
+The final section, Sec. 5, describes each of
+the MH commands in detail.
+A summary of the commands is given in
+Appendix A, and Appendixes B and C describe the ARPANET
+conventions for messages (we expect that many users of MH
+will be using the ARPANET) and the formal syntax of such
+messages, respectively.
+Finally, Appendix D provides
+an illustration of how MH commands may be used in
+conjunction with other UNIX facilities.
+.pp
+A novel approach has been taken in the design of MH.
+The
+design concept will be reported in detail in a forthcoming Rand
+report, but it can be described briefly as follows.
+Instead of creating a large subsystem that appears as a single
+command to the user, (such as MS[4])
+MH is a collection of separate commands
+which are run as separate programs.
+The file and directory
+system of UNIX are used directly.
+Messages are stored as
+individual files (datasets), and collections of them are grouped
+into directories.
+In contrast, most other message systems store
+messages in a complicated data structure within a monolithic
+file.
+With the MH approach, UNIX commands can be
+interleaved with commands invoking the functions of the message
+handler.
+Conversely, existing UNIX commands
+can be used in connection with messages.
+For
+example, all the usual UNIX editing, text-formatting, and printing
+facilities can be applied directly to individual messages.
+MH,
+therefore, consists of a relatively small amount of new code; it
+makes extensive use of other UNIX software to provide the
+capabilities found in other message systems.
+.+c OVERVIEW
+.pp
+There are three main aspects of MH:  the  way  messages  are
+stored (the message database), the user's profile (which directs
+how certain actions of the message handler take place), and the
+commands for dealing with messages.
+.pp
+Under MH, each message is stored as a separate file.
+A user
+can take any action with a message that he could with an ordinary
+file in UNIX.
+A UNIX directory in which messages are stored is
+called a folder.
+Each folder contains some standard entries to support
+the message-handling functions.
+The messages in a folder have numerical
+names.
+These folders (directories)
+are entries in a particular directory path, described in
+the user profile, through which MH can find message folders.
+Using the UNIX \*(lqlink\*(rq facility, it is possible for one copy of a
+message to be \*(lqfiled\*(rq in more than one folder, providing a
+message index facility.
+Also, using the UNIX tree-structured
+file system, it is possible to have a folder within a folder.
+This two-level organization provides a \*(lqselection-list\*(rq
+facility, with the full power of the MH commands available on
+selected sublists of messages.
+.pp
+Each user of MH has a user profile, a file in his $HOME (initial
+login)
+directory called \*(lq\*.mh\(ruprofile\*(rq.
+This profile contains several
+pieces of information used by the MH commands:  a
+path name to the directory that contains the message folders,
+information concerning which folder the user last referenced (the
+\*(lqcurrent\*(rq folder), and parameters that tailor MH commands
+to the individual user's requirements.
+It also contains
+most of the necessary state information concerning how
+the user is dealing with his messages, enabling MH to be
+implemented as a set of individual UNIX commands, in contrast to the
+usual approach of a monolithic subsystem.
+.pp
+In MH, incoming mail is appended
+to the end of a file called \*.mail in a user's $HOME
+directory.
+The user adds the new messages to his collection of MH messages
+by invoking the command
+.i inc .
+.i Inc
+(incorporate) adds the new
+messages to a folder called \*(lqinbox\*(rq, assigning them names which
+are consecutive integers starting with the next highest integer
+available in inbox.
+.i Inc
+also produces a
+.i scan
+summary of
+the messages thus incorporated.
+.pp
+There are four commands for examining the messages in a
+folder:
+.i show ,
+.i prev ,
+.i next ,
+and
+.i scan .
+.i Show
+displays a
+message in a folder,
+.i prev
+displays the message preceding the
+current message, and
+.i next
+displays the message following the
+current message.
+.i Scan
+summarizes the messages in a folder,
+producing one line per message, showing who the message is from,
+the date, the subject, etc.
+.pp
+The user may move a message from one folder to another with
+the command
+.i file .
+Messages may be removed from a folder
+by means of the command
+.i rmm .
+In addition, a user may query
+what the current folder is and may specify that a new folder
+become the current folder, through the command
+.i folder .
+.pp
+A set of messages based on content may be selected by
+use of the command
+.i pick .
+This command searches through
+messages in a folder and selects those that match a given
+criterion.
+A subfolder is created within the original folder,
+containing links to all the messages that satisfy the selection
+criteria.
+.pp
+A message folder (or subfolder) may be removed by means of
+the command
+.i rmf .
+.pp
+There are five commands enabling the user to create new
+messages and send them:
+.i comp ,
+.i dist ,
+.i forw ,
+.i repl ,
+and
+.i send .
+.i Comp
+provides the facility for the user to compose a
+new message;
+.i dist
+redistributes mail to additional addressees;
+.i forw
+enables the user to forward messages; and
+.i repl
+facilitates the generation of a reply to an incoming message.
+If
+a message is not sent directly by one of these commands, it may
+be sent at a later time using the command
+.i send .
+.pp
+All of the elements summarized above
+are described in more detail in the following sections.
+Many of the
+normal facilities of UNIX provide additional capabilities for
+dealing with messages in various ways.
+For example, it is
+possible to print messages
+on the line-printer without requiring any additional code within
+MH.
+Using standard UNIX facilities, any terminal output can be
+redirected to a file for repeated or future viewing.
+In general,
+the flexibility and capabilities of the UNIX interface with the
+user are preserved as a result of the integration of MH into the UNIX
+structure.
+.+c TUTORIAL
+.pp
+This tutorial provides a brief introduction to the MH commands.
+It should be sufficient
+to allow the user to read his mail, do some simple manipulations of
+it, and create and send messages.
+.pp
+A message has two major pieces:  the
+header and the body.
+The body consists of the text of the message
+(whatever you care to type in).
+It follows the header and is separated from
+it by an empty line.
+(When you compose a message, the form that appears
+on your terminal shows a line of dashes after the header.
+This is for
+convenience and is replaced by an empty line when the message is
+sent.)  The header is composed of several components, including the
+subject of the message and the person to whom it is addressed.
+Each component starts with a name
+and a colon; components must not start with a blank.
+The text of the
+component may take more than one line, but each continuation line must
+start with a blank.
+Messages typically have \*(lqto:\*(rq, \*(lqcc:\*(rq, and
+\*(lqsubject:\*(rq components.
+When composing a message, you should include
+the \*(lqto:\*(rq and \*(lqsubject:\*(rq components; the \*(lqcc:\*(rq (for people
+you want to send copies to) is not necessary.
+.pp
+The basic MH commands are
+.i inc ,
+.i scan ,
+.i show ,
+.i next ,
+.i prev ,
+.i rmm ,
+.i comp ,
+and
+.i repl .
+These are described below.
+
+.i inc
+.pp
+When you get the message \*(lqYou have mail\*(rq, type the command
+.i inc .
+You will get a \*(lqscan listing\*(rq such as:
+
+.nf
+.if t .ta .4i 1.0i 2i
+.if n .ta .4i 1.2i 3i
+^7+~^^\07/13~^^Cas~^revival of measurement work
+^8~^^10/\09~^^Norm~^NBS people and publications
+^9~^^11/26~^^To:norm~^question \*(<<Are there any functions
+.re
+.fi
+.pp
+This shows the messages you received since the last time you
+executed this command (
+.i inc
+adds these new messages to
+your inbox folder).
+You can see this list again, plus a list of any
+other messages you have, by using the
+.i scan
+command.
+
+.i scan
+.pp
+The scan listing shows the message number, followed by the
+date and the sender.
+(If you are the sender, the addressee in the \*(lqto:\*(rq
+component is displayed.
+You may send yourself a message by including
+your name among the \*(lqto:\*(rq or \*(lqcc:\*(rq addressees.)
+It also shows the message's subject; if
+the subject is short, the first part of the body of the message is
+included after the characters \*(<<.
+
+.ne 5
+.i show
+.pp
+This command shows the current message, that is,
+the first one of the new messages after an
+.i inc .
+If the message is not
+specified by name (number), it is
+generally the last message referred to by an MH command.
+For example,
+
+.ta 1i
+.ti .5i
+^\fIshow\fP\05~^will show message 5.
+.pp
+You can use the show command to copy a message or print a
+message.
+
+.(b L
+.in .5i
+.if t .ta 1i
+.if n .ta 1.5i
+^\fIshow\fR\0>\0\fIx\fR~^will copy the message to file x.
+.br
+^\fIshow\fR\0|\0\fIprint\fR~^will print the message, using the \fIprint\fR command.
+.br
+^\fInext\fR~^will show the message that follows the current message.
+.br
+^\fIprev\fR~^will show the message previous to the current message.
+.br
+^\fIrmm\fR~^will remove the current message.
+.br
+^\fIrmm\03\fR~^will remove message 3.
+.)b
+
+.ne 5
+.i comp
+.pp
+The
+.i comp
+command puts you in the editor to write or edit a message.
+Fill in or
+delete the \*(lqto:\*(rq, \*(lqcc:\*(rq, and \*(lqsubject:\*(rq fields, as appropriate, and
+type the body of the message.
+Then
+exit normally from the editor.
+You will be asked
+\*(lqWhat now?\*(rq.
+Type a carriage return to see the options.
+Typing \fBsend\fR
+will cause the message to be sent; typing \fBquit\fR will cause an exit
+from
+.i comp ,
+with the message draft saved.
+.pp
+If you quit without sending the message, it will be saved in a file
+called /usr/<name>/Mail/draft (where /usr/<name> is your $HOME directory).
+You can edit this file and send the message later, using the
+.i send
+command.
+
+.ne 4
+.i "comp\0\-editor\0prompter"
+.pp
+This command uses a different editor and is useful for preparing
+\*(lqquick and dirty\*(rq messages.
+It prompts you for each component of the
+header.
+Type the information for that component, or type a carriage
+return to omit the component.
+After that, type the body of the
+message.
+Backspacing is the only form of editing allowed with this editor.
+When the body is complete, type a carriage return followed by <CTRL-D>
+(<OPEN> on Ann Arbor terminals).
+This completes the initial preparation of the message; from then on, use
+the same procedures as with
+.i comp
+(above).
+
+.ne 5
+.i repl
+.br
+.i "repl\0n"
+.pp
+This command makes up an initial message form with a header
+that is appropriate for
+replying to an existing message.
+The message being answered is the
+current message if no message number is mentioned, or n if a number
+is specified.
+After the header is completed, you can finish the message as in
+.i comp
+(above).
+.pp
+This is enough information to get you going using MH.
+There are more commands,
+and the commands described here have more features.
+Subsequent sections
+explain MH in complete detail.
+The system is quite powerful if you
+want to use its sophisticated features, but the foregoing commands
+suffice for sending and receiving messages.
+.pp
+There are numerous additional capabilities you may wish to explore.
+For example, the
+.i pick
+command will select a subset of messages
+based on specified criteria such as sender or subject.
+Groups of
+messages may be designated, as described in Sec. V, under \*(lqMessage
+Naming\*(rq.
+The file \*(lq\*.mh\(ruprofile\*(rq can be used to tailor your use of
+the message system to your needs and preferences, as described in Sec. V,
+under \*(lqThe User Profile\*(rq.
+In general, you may
+learn additional features of the system selectively, according to your
+requirements,
+by studying the relevant sections of this manual.
+There is no need to
+learn all the details of the system at once.
+.+c "DETAILED DESCRIPTION"
+.pp
+This section describes the MH system in detail, including the components
+of the user profile, the conventions for message naming, and some of
+the other MH conventions.
+Readers who are
+generally familiar with computer systems will be able to follow
+the principal ideas, although some details may be meaningful only to
+those familiar with UNIX.
+.uh "THE USER PROFILE"
+.pp
+The first time an MH command is issued by a new user, the system
+prompts for a \*(lqpath\*(rq and creates an MH \*(lqprofile\*(rq.
+.pp
+Each MH user has a profile which contains current
+state information for the MH package and, optionally, tailoring
+information for each individual program.
+When a folder becomes
+the current folder, it is recorded in the user's profile.
+Other profile entries control the MH path (where folders and
+special files are kept), folder and message protections, editor
+selection, and default arguments for each MH program.
+.pp
+The MH profile is stored in the file \*(lq\*.mh\(ruprofile\*(rq in the
+user's $HOME directory.
+It has the format of a message without
+any body.
+That is, each profile entry is on one line, with a
+keyword followed by a colon (:) followed by text particular to
+the keyword.
+.br
+\(rh\ \ \&
+.i "This file must not have blank lines."
+.br
+The keywords
+may have any combination of upper and lower case.
+(See Appendix
+B for a description of message formats.)
+.pp
+For the average MH user, the only profile entry of
+importance is \*(lqPath\*(rq.
+Path specifies a directory in which MH
+folders and certain files such as \*(lqdraft\*(rq are found.
+The
+argument to this keyword must be a legal UNIX path that names an
+existing directory.
+If this path is unrooted (i.e., does not
+begin with a \fB/\fR), it will be presumed to start from the
+user's $HOME directory.
+All folder and message references within
+MH will relate to this path unless full path names are used.
+.pp
+Message protection defaults to 664, and folder protection to
+751.
+These may be changed by profile entries \*(lqMsg-Protect\*(rq
+and \*(lqFolder-Protect\*(rq, respectively.
+The argument to these
+keywords is an octal number which is used as the UNIX file mode.\**
+.(f
+\**See
+.i chmod (I)
+in the
+.i "UNIX Programmer's Manual" .[5]
+.)f
+.pp
+When an MH program starts running, it looks through the
+user's profile for an entry with a keyword matching the program's
+name.
+For example, when
+.i comp
+is run, it looks for a \*(lqcomp\*(rq
+profile entry.
+If one is found, the text of the profile entry is
+used as the default switch setting until all defaults are overridden
+by explicit switches passed to the program as arguments.
+Thus the profile
+entry \*(lqcomp:\0\-form\0standard.list\*(rq would direct
+.i comp
+to use the
+file \*(lqstandard.list\*(rq as the message skeleton.
+If an explicit
+form switch is given to the
+.i comp
+command, it will override the
+switch obtained from the profile.
+.pp
+In UNIX, a program may exist under several names, either by
+linking or aliasing.
+The actual invocation name is used by an MH
+program when scanning for its profile defaults.
+Thus, each MH program
+may have several names by which it can be invoked, and each name
+may have a different set of default switches.
+For example, if
+.i comp
+is invoked by the name
+.i icomp ,
+the profile entry
+\*(lqicomp\*(rq will control the default switches for this invocation of
+the
+.i comp
+program.
+This provides a powerful
+definitional facility for commonly used switch settings.
+.pp
+The default editor
+for editing within
+.i comp ,
+.i repl ,
+.i forw ,
+and
+.i dist ,
+is \*(lq/bin/ned\*(rq.\**
+.(f
+\**See Ref. 6 for a description of
+the NED text editor.
+.)f
+A different editor may be used by specifying
+the profile entry
+\*(lqEditor: \*(rq.
+The argument to \*(lqEditor\*(rq is the name of an
+executable program or shell command file which can be found via
+the user's $PATH defined search path, excluding the current
+directory.
+The \*(lqEditor:\*(rq profile specification
+may in turn be overridden by a \*(lq\-editor\0<editor>\*(rq
+profile switch associated with
+.i comp ,
+.i repl ,
+.i forw ,
+or
+.i dist .
+Finally, an explicit editor switch specified with any
+of these four commands will have ultimate precedence.
+.pp
+During message composition, more than one editor may be
+used.
+For example, one editor (such as
+.i prompter )
+may be used
+initially, and a second editor may be invoked later to revise
+the message being composed
+(see the discussion of
+.i comp
+in Section 5 for details).
+A profile entry \*(lq<lasteditor>\-next:\0<editor>\*(rq specifies the name of
+the editor to be used after a particular editor.
+Thus \*(lqcomp:\0\-e\0prompter\*(rq
+causes the initial text to be collected by
+.i prompter ,
+and the profile entry \*(lqprompter\-next:\0ed\*(rq names ed as the
+editor to be invoked for the next round of editing.
+.pp
+Some of the MH commands, such as
+.i show ,
+can be used on
+message folders owned by others, if those folders are readable.
+However,
+you cannot write in someone else's folder.
+All the MH command
+actions not requiring write permission may be used with
+a \*(lqread-only\*(rq folder.
+In a writable folder, a file named
+\*(lqcur\*(rq is used to contain its current message name.
+For read-only folders, the current message name is
+stored in the user's profile.
+.pp
+Table 1 lists examples of the currently defined profile
+entries, typical arguments, and the programs that reference the
+entries.
+.in .9i
+.ll -.9i
+.ta 2.3i
+.sp 30p
+.ce
+Table 1
+.sp 8p
+.ce
+P\s-2ROFILE\s0 C\s-2OMPONENTS\s0
+.hl             \" ~12p preceding + 1v (12p) after
+.nf
+^^MH Programs that
+^Keyword and Argument~^\ Use Component\h'|\n(.lu-.9i'\v'4p'\l'|0'\v'-4p'  \" \l'..' does underlining
+.sp
+^Path:\0Mail~^All
+^Current-Folder:\0inbox~^Most
+^Editor:\0/bin/ed~^\fIcomp, dist, forw, repl\fR
+^Msg\-Protect:\0644~^\fIinc\fR
+^Folder\-Protect:\0711~^\fIfile, inc, pick\fR
+^<program>:\0default switches~^All
+^cur\-<read-onlyfolder>:\0172~^Most
+^prompter\-next:\0ed~^\fIcomp, dist, forw, repl\fR
+.hl
+.ll +.9i
+.in 0
+.fi
+.pp
+Path
+.u should
+be present.
+Folder is maintained
+automatically by many MH commands (see the \*(lqContext\*(rq sections of
+the individual commands in Sec. V).
+All other entries are optional,
+defaulting to the values described above.
+.uh "MESSAGE NAMING"
+.pp
+Messages may be referred to explicitly or implicitly when
+using MH commands.
+A formal syntax of message names is given in Appendix C, but the
+following description should be sufficient for most MH users.
+Some details of message naming that apply only to certain
+commands are included in the description of those
+commands.
+.pp
+Most of the MH commands accept arguments specifying one or
+more folders, and one or more messages to operate on.
+The use of
+the word \*(lqmsg\*(rq as an argument to a command means that exactly one
+message name may be specified.
+A message name may be a number,
+such as 1, 33, or 234, or it may be
+one of the \*(lqreserved\*(rq message names:
+first, last, prev, next, and cur.
+(As a shorthand, a
+period (\*.) is equivalent to cur.)
+The meanings of these names
+are straightforward:  \*(lqfirst\*(rq is the first message in the
+folder; \*(lqlast\*(rq is the last
+message in the folder; \*(lqprev\*(rq is the
+message numerically previous to the current message; \*(lqnext\*(rq
+is the message numerically following the current message; \*(lqcur\*(rq
+(or \*(lq\*.\*(rq) is the current message in the folder.
+.pp
+The default in commands that take a \*(lqmsg\*(rq argument is
+always \*(lqcur\*(rq.
+.pp
+The word \*(lqmsgs\*(rq indicates that several messages may be
+specified.
+Such a specification consists of several message
+designations separated by spaces.
+A message designation is
+either a message name or a message range.
+A message range is a
+specification of the form name1\-name2 or name1:n, where name1 and
+name2 are message names and n is an integer.
+The first form
+designates all the messages from name1 to name2 inclusive; this
+must be a non-empty range.
+The second form specifies up to n
+messages, starting with name1 if name1 is a number, or first,
+cur, or next, and ending with name1 if name1 is last or
+prev.
+This interpretation of n is overridden if n is preceded
+by a plus sign or a minus sign;
++n always means up to n messages starting with
+name1, and \-n always means up to n messages ending with name1.
+Repeated specifications of the same message have the same effect
+as a single specification of
+the message.
+Examples of
+specifications are:
+
+.(b
+1 5 7\-11 22
+first 6 8 next
+first\-10
+last:5
+.)b
+.pp
+The message name \*(lqall\*(rq is a shorthand for \*(lqfirst\-last\*(rq,
+indicating all of the messages in the folder.
+.pp
+The limit on the number of messages in an expanded message
+list is generally 999\*-the maximum number of messages in a
+folder.
+However, the
+.i show
+command and the
+commands `\fIpick\0\-scan\fR' and `\fIpick\0\-show\fR'
+are constrained to have argument lists
+that are no more than 512 characters long.
+(Under Version 7 UNIX this limit is 4096.)
+.pp
+In commands that accept \*(lqmsgs\*(rq arguments, the default is
+either cur or all, depending on which makes more sense.
+.pp
+In all of the MH commands, a plus sign preceding an argument
+indicates a folder name.
+Thus, \*(lq+inbox\*(rq is the name of the
+user's standard inbox.
+If an explicit folder argument is given
+to an MH command, it will become the current folder (that is,
+the \*(lqCurrent-Folder:\*(rq entry
+in \*(lq\*.mh\(ruprofile\*(rq will be changed to this
+folder).
+In the case of the
+.i file
+and
+.i pick
+commands, which
+can have multiple output folders, a new source folder (other than
+the default current folder) is specified by \*(lq\-src\0+folder\*(rq.
+.uh "OTHER MH CONVENTIONS"
+.pp
+One very powerful feature of MH is that the MH commands may
+be issued from any current directory, and the proper path to
+the appropriate folder(s) will be taken from the user's profile.
+If the MH path is not appropriate for a specific folder or file,
+the automatic prepending of the MH path can be avoided by
+beginning a folder or file name with \fB/\fR.
+Thus any specific full
+path may be specified.
+.pp
+Arguments to the various programs may be given in any order,
+with the exception of a few switches whose arguments must follow
+immediately, such as \*(lq\-src\0+folder\*(rq for \fIpick\fR and \fIfile\fR.
+.pp
+Whenever an MH command prompts the user, the valid options
+will be listed in response to a <RETURN>.
+(The first of the
+listed options is the default if end-of-file is encountered, such
+as from a command file.)  A valid response is any \fIunique\fR
+abbreviation of one of the listed options.
+.pp
+Standard UNIX documentation conventions are used in this report
+to describe MH command syntax.
+Arguments enclosed in brackets
+([ ]) are optional; exactly one of the arguments enclosed
+within braces ({ }) must be specified, and all other
+arguments are required.
+The use of ellipsis dots (...) indicates
+zero or more repetitions of the previous item.
+For example,
+\*(lq+folder ...\*(rq would indicate that one or more \*(lq+folder\*(rq arguments
+is required and \*(lq[+folder ...]\*(rq indicates that 0 or more
+\*(lq+folder\*(rq arguments may be given.
+.pp
+MH departs from UNIX standards by using switches that consist of
+more than one character, e.g. \*(lq\-header\*(rq.
+To minimize typing,
+only a unique abbreviation of a switch need be typed; thus, for
+\*(lq\-header\*(rq, \*(lq\-hea\*(rq is probably sufficient, depending on the
+other switches the command accepts.
+Each MH program
+accepts the switch \*(lq\-help\*(rq (which \fImust\fR be spelled out fully)
+and produces a syntax description and a list of switches.
+In the
+list of switches, parentheses indicate required characters.
+For example, all \*(lq\-help\*(rq switches will appear as \*(lq\-(help)\*(rq,
+indicating that no abbreviation is accepted.
+.pp
+Many MH switches have both on and off forms, such as
+\*(lq\-format\*(rq and \*(lq\-noformat\*(rq.
+In many of the descriptions in Sec. V,
+only one form is defined; the other form, often used to
+nullify profile switch settings, is assumed to be the opposite.
+.br
+.bp
+.uh "MH COMMANDS"
+.pp
+The MH package comprises 16 programs:
+
+.nf
+.in .5i
+.ta 1.5i
+^comp~^Compose a message
+^dist~^Redistribute a message
+^file~^Move messages between folders
+^folder~^Select/list status of folders
+^forw~^Forward a message
+^inc~^Incorporate new mail
+^next~^Show the next message
+^pick~^Select a set of messages by context
+^prev~^Show the previous message
+^prompter~^Prompting editor front end for composing messages
+^repl~^Reply to a message
+^rmf~^Remove a folder
+^rmm~^Remove messages
+^scan~^Produce a scan listing of selected messages
+^send~^Send a previously composed message
+^show~^Show messages
+.fi
+.re
+.pp
+These programs are described below.
+The form of the descriptions
+conforms to the standard
+form for the description of UNIX commands.
+.if t \{
+.ll 6.5i
+.lt 6.5i
+\}
+.fo '7th Edition'UNIX/32V(Rand)''
+.de SC
+.he '\\$1(1)'-%-'\\$1(1)'
+.bp
+.(x
+.ti .8i
+\\$1
+.)x
+..
+.de NA
+.b \\s-2NAME\\s0
+.ti .5i
+..
+.de SY
+.sp
+.b \\s-2SYNOPSIS\\s0
+.in 1i
+.ti .5i
+.na
+..
+.de DE
+.ad
+.sp
+.in 0
+.b  \\s-2DESCRIPTION\\s0
+.sp
+.fi
+.in .5i
+..
+.de Fi
+.(b L
+.ti 0
+.b \\s-2Files\\s0
+.ta 2i
+..
+.de Pr
+.)b
+.(b L F
+.in 2.5i
+.ti 0
+.b "\\s-2Profile Components\\s0"
+.ti .5i
+..
+.de Ps
+.ti .5i
+..
+.de De
+.)b
+.(b L
+.in .5i
+.ti 0
+.b \\s-2Defaults\\s0
+..
+.de Co
+.)b
+.(b L F
+.ti 0
+.b \\s-2Context\\s0
+.br
+..
+.de En
+.)b
+.in 0
+..
+.SC COMP
+.NA
+comp \- compose a message
+
+.SY
+comp \%[\-editor\ editor] \%[\-form\ formfile] \%[file] \%[\-use]
+\%[\-nouse] \%[\-help]
+
+.DE
+\fIComp\fP is used to create a new message to be mailed.
+If
+\fIfile\fP is not specified, the file named \*(lqdraft\*(rq in the user's MH
+directory will be used.
+\fIComp\fR copies a message form to
+the file being composed and then invokes an editor on the
+file.
+The default editor is /bin/ned, which may be overridden with
+the `\-editor' switch or with a profile entry \*(lqEditor:\*(rq.
+(See Ref. 5 for a
+description of the NED text editing system.)
+The default
+message form contains the following elements:
+
+     To:
+     cc:
+     Subject:
+     ----------
+
+If the file named \*(lqcomponents\*(rq exists in the user's MH directory,
+it will be used instead of this form.
+If `\-form
+formfile' is specified, the specified formfile (from the MH
+directory) will be used as the skeleton.
+The line of dashes
+or a blank line must be left between the header and the
+body of the message for the message to be identified properly when it is
+sent (see \fIsend;\fR).
+The switch `\-use' directs \fIcomp\fR to
+continue editing an already started message.
+That is, if a
+\fIcomp\fR (or \fIdist\fR, \fIrepl\fR, or \fIforw\fR) is terminated without
+sending the message, the message can be edited again via
+\*(lqcomp \-use\*(rq.
+
+If the specified file (or draft) already exists, \fIcomp\fR will ask
+if you want to delete it before continuing.
+A reply of \fBNo\fR will abort the
+\fIcomp\fR, \fByes\fR will replace the existing draft with a blank
+skeleton, \fBlist\fR will display the draft, and \fBuse\fR will use it
+for further composition.
+
+Upon exiting from the editor, \fIcomp\fR will ask \*(lqWhat now?\*(rq.
+The valid
+responses are \fBlist\fR, to list the draft on the terminal; \fBquit\fR, to
+terminate the session and preserve the draft; \fBquit delete\fR, to terminate,
+then delete the draft; \fBsend\fR, to send the message; \fBsend verbose\fR, to
+cause the delivery process to be monitored; \fBedit <editor>\fR, to invoke
+<editor> for further editing; and \fBedit\fR, to re-edit using the
+same editor that was used on the preceding round unless a profile
+entry \*(lq<lasteditor>\-next: <editor>\*(rq names an alternative editor.
+
+.Fi
+^/etc/mh/components~^The message skeleton
+^or <mh-dir>/components~^Rather than the standard skeleton
+^$HOME/\*.mh\(ruprofile~^The user profile
+^<mh-dir>/draft~^The default message file
+^/usr/bin/send~^To send the composed message
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Editor:~^To override the use of /bin/ned as the default editor
+.Ps
+^<lasteditor>\-next:~^To name an editor to be used after exit from <lasteditor>
+.De
+`file' defaults to draft
+`\-editor' defaults to /bin/ned
+`\-nouse'
+.Co
+\fIComp\fR does not affect either the current folder or the current message.
+.En
+.SC DIST
+.NA
+dist \- redistribute a message to additional addresses
+.SY
+dist \%[+folder] \%[msg] \%[\-form\ formfile] \%[\-editor\ editor]
+\%[\-annotate] \%[\-noannotate]
+\%[\-inplace] \%[\-noinplace]
+\%[\-help]
+.DE
+\fIDist\fR is similar to \fIforw\fR.
+It prepares the specified
+message for redistribution to addresses that (presumably) are
+not on the original address list.
+The file \*(lqdistcomps\*(rq in the
+user's MH directory, or a standard form, or the file specified by
+`\-form formfile' will be used as the blank components file to
+be prepended to the message being distributed.
+The standard form
+has the components \*(lqDistribute-to:\*(rq and \*(lqDistribute-cc:\*(rq.
+When
+the message is sent, \*(lqDistribution-Date:\0date\*(rq,
+\*(lqDistribution-From:\0name\*(rq, and
+\*(lqDistribution-Id:\0id\*(rq (if `\-msgid' is
+specified to \fIsend\fR;) will be prepended to the outgoing message.
+Only those addresses in \*(lqDistribute-To\*(rq, \*(lqDistribute-cc\*(rq, and
+\*(lqDistribute-Bcc\*(rq will be sent.
+Also, a \*(lqDistribute-Fcc:\0folder\*(rq
+will be honored (see \fIsend;\fR).
+
+\fISend\fR recognizes a message as a redistribution message by the
+existence of the field \*(lqDistribute-To:\*(rq, so don't try to
+redistribute a message with only a \*(lqDistribute-cc:\*(rq.
+
+If the `\-annotate' switch is given, each message being
+distributed will be annotated with the lines:
+
+     Distributed:\0\*(<<date\*(>>
+     Distributed:\0Distribute-to: names
+
+where each \*(lqto\*(rq list contains as many lines as required.
+This annotation
+will be done only if the message is sent directly from \fIdist\fR.
+If the
+message is not sent immediately from \fIdist\fR (i.e., if it is sent later
+via \fIsend;\fR),
+\*(lqcomp \-use\*(rq may be used to re-edit and send the constructed message, but
+the annotations won't take place.
+The '\-inplace' switch causes annotation to
+be done in place in order to preserve links to the annotated message.
+
+See \fIcomp\fR for a description of the `\-editor' switch and for options
+upon exiting from the editor.
+
+.Fi
+^/etc/mh/components~^The message skeleton
+^or <mh-dir>/components~^Rather than the standard skeleton
+^$HOME/\*.mh\(ruprofile~^The user profile
+^<mh-dir>/draft~^The default message file
+^/usr/bin/send~^To send the composed message
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Editor:~^To override the use of /bin/ned as the default editor
+.Ps
+^<lasteditor>\-next:~^To name an editor to be used after exit from <lasteditor>
+.De
+`+folder' defaults to the current folder
+`msg' defaults to cur
+`\-editor' defaults to /bin/ned
+`\-noannotate'
+`\-noinplace'
+.Co
+If a +folder is specified, it will become the current
+folder, and the current message will be set to the message
+being redistributed.
+.En
+.SC FILE
+.NA
+file \- file message(s) in (an)other folder(s)
+.SY
+file \%[\-src\ +folder] \%[msgs] \%[\-link] \%[\-preserve] \%+folder\ ...
+\%[\-nolink] \%[\-nopreserve]
+\%[\-file\ file] \%[\-nofile] \%[\-help]
+.DE
+\fIFile\fR moves (\fImv\fR(I)) or links (\fIln\fR(I)) messages from a
+source folder into one or more destination folders.
+If you think
+of a message as a sheet of paper, this operation is not
+unlike filing the sheet of paper (or copies) in file cabinet
+folders.
+When a message is filed, it is linked into the
+destination folder(s) if possible, and is copied otherwise.
+As long
+as the destination folders are all on the same file system, multiple filing
+causes little storage overhead.
+This facility provides a good way to cross-file or multiply-index
+messages.
+For example, if a message is received from Jones about
+the ARPA Map Project, the command
+
+     file\0cur\0+jones\0+Map
+
+would allow the message to be found in either of the two
+folders `jones' or `Map'.
+
+The option `\-file file' directs \fIfile\fR to use the specified
+file as the source message to be filed, rather than a message from
+a folder.
+
+If a destination folder doesn't exist, \fIfile\fR will ask if you
+want to create one.
+A negative response will abort the file
+operation.
+
+`\-link' preserves the source folder copy of the message
+(i.e., it does a \fIln\fR(I) rather than a \fImv\fR(I)), whereas,
+`\-nolink' deletes the \*(lqfiled\*(rq messages from the source
+folder.
+Normally, when a message is filed, it is assigned the
+next highest number available in each of the destination folders.
+Use of the `\-preserve' switch will override this message
+\*(lqrenaming\*(rq, but name conflicts may occur, so
+use this switch cautiously.
+(See \fIpick\fR for more details on
+message numbering.)
+
+If `\-link' is not specified (or `\-nolink' is specified),
+the filed messages will be removed (unlink(II)) from the
+source folder.
+
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Current-Folder:~^To find the default current folder
+.Ps
+^Folder\-Protect:~^To set mode when creating a new folder
+.De
+`\-src +folder' defaults to the current folder
+`msgs' defaults to cur
+`\-nolink'
+`\-nopreserve'
+`\-nofile'
+.Co
+If `\-src +folder' is given, it will become the
+current folder for future MH commands.
+If neither `\-link' nor
+`all' are specified, the current message in the source
+folder will be set to the last message specified; otherwise, the
+current message won't be changed.
+.En
+.SC FOLDER
+.NA
+folder \- set/list current folder/message
+.SY
+folder \%[+folder] \%[msg] \%[\-all] \%[\-fast] \%[\-nofast] \%[\-up] \%[\-down]
+\%[\-header] \%[\-noheader] \%[\-total] \%[\-nototal] \%[\-pack] \%[\-nopack]
+\%[\-help]
+
+.ti .5i
+folders  <equivalent to 'folder \-all'>
+.DE
+Since the MH environment is the shell, it is easy to lose
+track of the current folder from day to day.
+\fIFolder\fR will
+list the current folder, the number of messages in it, the
+range of the messages (low-high), and the current message within
+the folder, and will flag a selection list or extra files if they
+exist.
+An example of the output is:
+
+      inbox+ has 16 messages ( 3\- 22); cur= 5.
+
+If a `+folder' and/or `msg' are specified, they will
+become the current folder and/or message.
+An `\-all' switch
+will produce a line for each folder in the user's MH directory,
+sorted alphabetically.
+These folders are preceded by the read-only
+folders, which occur as \*.mh\(ruprofile \*(lqcur\-\*(rq entries.
+For example,
+
+.nf
+.ta 1.5i 2.1i 2.7i 3.5i
+^~Folder\ \ ^^~#\ of\ ^^messages~^^(~\ range\~ );\ ^cur msg (other files)
+^~/fsd/rs/m/tacc\ \ ^^has~35\ ^^messages~^^(~1\-\035);\ ^cur=\ 23.
+^~/rnd/phyl/Mail/EP\ \ ^^has~82\ ^^messages~^^(~1\-108);\ ^cur=\ 82.
+^~f\&f\ \ ^^has~4\ ^^messages~^^(~1\-\0\04);\ ^cur=\ \01.
+^~inbox+\ ^^has~16\ ^^messages~^^(~3\-\022);\ ^cur=\ \05.
+^~mh\ \ ^^has~76\ ^^messages~^^(~1\-\076);\ ^cur=\ 70.
+^~notes\ \ ^^has~2\ ^^messages~^^(~1\-\0\02);\ ^cur=\ \01.
+^~ucom\ \ ^^has~124\ ^^messages~^^(~1\-124);\ ^cur=\ \06; (select).
+
+^^^~TOTAL=\0339\ ^messages\0in\0\07\0Folders.
+.re
+.fi
+
+The \*(lq+\*(rq after inbox indicates that it is the current folder.
+The \*(lq(select)\*(rq indicates that the folder ucom has a selection
+list produced by \fIpick\fR.
+If \*(lqothers\*(rq had appeared in parentheses at
+the right of a line, it would indicate that there are files in
+the folder directory that don't belong under the MH file naming
+scheme.
+
+The header is output if either an `\-all' or a `\-header' switch
+is specified; it is suppressed by `\-noheader'.
+Also, if \fIfolder\fR
+is invoked by a name ending with \*(lqs\*(rq (e.g., \fIfolders\fR),
+`\-all' is assumed.
+A `\-total' switch will produce only the
+summary line.
+
+If `\-fast' is given, only the folder name (or names in the
+case of `\-all') will be listed.
+(This is faster because the
+folders need not be read.)
+
+The switches `\-up' and `\-down' change the folder to be the
+one above or below the current folder.
+That is, \*(lqfolder \-down\*(rq
+will set the folder to \*(lq<current\-folder>/select\*(rq, and if the
+current folder is a selection-list folder, \*(lqfolder \-up\*(rq will
+set the current folder to the parent of the selection-list.
+(See \fIpick\fR for details on selection-lists.)
+
+The `\-pack' switch will compress the message names in a folder, removing
+holes in message numbering.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+^/bin/ls~^To fast-list the folders
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+`+folder' defaults to the current folder
+`msg' defaults to none
+`\-nofast'
+`\-noheader'
+`\-nototal'
+`\-nopack'
+.Co
+If `+folder' and/or `msg' are given, they will become the
+current folder and/or message.
+.En
+.SC FORW
+.NA
+forw \- forward messages
+.SY
+forw \%[+folder] \%[msgs] \%[\-editor\ editor] \%[\-form\ formfile]
+\%[\-annotate] \%[\-noannotate]
+\%[\-inplace]  \%[\-noinplace]
+\%[\-help]
+.DE
+\fIForw\fR may be used to prepare a message containing other
+messages.
+It constructs the new message from the components file
+or `\-form formfile' (see \fIcomp\fR), with a body composed of the
+message(s) to be forwarded.
+An editor is invoked as in \fIcomp\fR,
+and after editing is complete, the user is prompted before the message
+is sent.
+
+If the `\-annotate' switch is given, each message being
+forwarded will be annotated with the lines
+
+     Forwarded: \*(<<date\*(>>
+     Forwarded: To: names
+     Forwarded: cc: names
+
+where each \*(lqTo:\*(rq and \*(lqcc:\*(rq list contains as many lines as required.
+This annotation will be done only if the message is sent directly
+from \fIforw\fR.
+If the message is not sent immediately from \fIforw\fR,
+\*(lqcomp \-use\*(rq may be used in a later session to re-edit and send
+the constructed message, but the annotations won't take place.
+The `\-inplace' switch permits annotating a message in place in
+order to preserve its links.
+
+See \fIcomp\fR for a description of the `\-editor' switch.
+.Fi
+^/etc/mh/components~^The message skeleton
+^or <mh-dir>/components~^Rather than the standard skeleton
+^$HOME/\*.mh\(ruprofile~^The user profile
+^<mh-dir>/draft~^The default message file
+^/usr/bin/send~^To send the composed message
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Editor:~^To override the use of /bin/ned as the default editor
+.Ps
+^Current-Folder:~^To find the default current folder
+.Ps
+^<lasteditor>\-next:~^To name an editor to be used after exit from <lasteditor>
+.De
+`+folder' defaults to the current folder
+`msgs' defaults to cur
+`\-editor' defaults to /bin/ned
+`\-noannotate'
+`\-noinplace'
+.Co
+If a +folder is specified, it will become
+the current folder, and the current message will be set to
+the first message being forwarded.
+.En
+.SC INC
+.NA
+inc \- incorporate new mail
+.SY
+inc \%[+folder] \%[\-audit\ audit-file] \%[\-help]
+.DE
+\fIInc\fR incorporates mail from the user's incoming mail drop
+(\*.mail) into an MH folder.
+If `+folder' isn't specified,
+the folder named \*(lqinbox\*(rq in the user's MH directory will be used.
+The
+new messages being incorporated are assigned numbers starting
+with the next highest number in the folder.
+If the specified (or
+default) folder doesn't exist, the user will be queried prior to
+its creation.
+As the messages are processed, a \fIscan\fR  listing
+of the new mail is produced.
+
+If the user's profile contains a \*(lqMsg\-Protect: nnn\*(rq entry, it
+will be used as the protection on the newly created messages,
+otherwise the MH default of 664 will be used.
+During all
+operations on messages, this initially assigned protection will
+be preserved for each message, so \fIchmod\fR(I) may be used to set a
+protection on an individual message, and its protection will be
+preserved thereafter.
+
+If the switch `\-audit audit-file' is specified (usually as a
+default switch in the profile), then \fIinc\fR will append a header
+line and a line per message to the end of the specified
+audit-file with the format:
+
+.nf
+.ti 1i
+\*(<<inc\*(>> date
+.ti 1.5i
+<scan line for first message>
+.ti 1.5i
+<scan line for second message>
+.ti 2.5i
+<etc.>
+.fi
+
+This is useful for keeping track of volume and source of incoming
+mail.
+Eventually, \fIrepl\fR, \fIforw\fR, \fIcomp\fR, and \fIdist\fR may also
+produce audits to this (or another) file, perhaps with
+\*(lqMessage-Id:\*(rq information to keep an exact correspondence history.
+\*(lqAudit-file\*(rq will be in the user's MH directory unless a full
+path is specified.
+
+\fIInc\fR will incorporate even illegally formatted messages into the
+user's MH folder, inserting a blank line prior to the offending
+component and printing a comment identifying the bad message.
+
+In all cases, the \*.mail file will be zeroed.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+^$HOME/\*.mail~^The user's mail drop
+^<mh-dir>/audit-file~^Audit trace file (optional)
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Folder\-Protect:~^For protection on new folders
+.Ps
+^Msg\-Protect:~^For protection on new messages
+.De
+`+folder' defaults to \*(lqinbox\*(rq
+.Co
+The folder into which the message is
+being incorporated will become the
+current folder, and the first message incorporated will be the
+current message.
+This leaves the context ready for a \fIshow\fR
+of the first new message.
+.En
+.SC NEXT
+.NA
+next \- show the next message
+.SY
+next \%[+folder] \%[\-switches\ for\ \fIl\fR] \%[\-help]
+.DE
+\fINext\fR performs a \fIshow\fR on the next message in the
+specified (or current) folder.
+Like \fIshow\fR, it passes any
+switches on to the program \fIl\fR, which is called to list the
+message.
+This command is exactly equivalent to \*(lqshow next\*(rq.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+.Co
+If a folder is specified, it will become the current folder, and the
+message that is shown (i.e., the next message in sequence)
+will become the current message.
+.En
+.SC PICK
+.NA
+pick \- select messages by content
+.SY
+.ta .4i 1.8i
+.nf
+.in .5i
+^pick~^^\0\-cc~^ \%[\-src\ +folder] \%[msgs] \%[\-help] \%[\-scan] \%[\-noscan]
+^^^\0\-date~^   \%[\-show] \%[\-noshow] \%[\-nofile] \%[\-nokeep]
+^^^\0\-from~^
+^^^\s+2\b'\(lt\(bv\(bv\(lk\(bv\(bv\(lb'\s0 \-search~\s+2\b'\(rt\(bv\(bv\(rk\(bv\(bv\(rb'\s0^ pattern
+^^^\0\-subject~^
+^^^\0\-to~^ \%[\-file \%[\-preserve] \%[\-link] \%+folder\ ... \%[\-nopreserve] \%[\-nolink] ]
+^^^\0\-\-component~^ \%[\-keep \%[\-stay] \%[\-nostay] \%[+folder\ ...]\ ]
+.fi
+
+.re
+.ti .5i
+typically:
+.in 1i
+pick\0\-from\0jones\0\-scan
+.br
+pick\0\-to\0holloway
+.br
+pick\0\-subject\0ned\0\-scan\0\-keep
+.DE
+\fIPick\fR searches messages within a folder for the specified
+contents, then performs several operations on the selected
+messages.
+
+A modified \fIgrep\fR(I) is used to perform the searching, so the
+full regular expression (see \fIed\fR(I)) facility is available
+within `pattern'.
+With `\-search', pattern is used directly,
+and with the others, the grep pattern constructed is:
+
+.ti +.5i
+\*(lq^component:\*.\*(**pattern\*(rq
+
+This means that the pattern specified for a `\-search' will be
+found everywhere in the message, including the header and the body,
+while the other search requests are limited to the single
+specified component.
+The expression `\-\-component pattern'
+is a shorthand for
+specifying `\-search \*(lqcomponent:\*.\*(**pattern\*(rq\ '; it is used to pick
+a component not in the set [cc date from subject to].
+An
+example is \*(lqpick \-\-reply\-to pooh \-show\*(rq.
+
+Searching is performed on a per-line basis.
+Within the header of
+the message, each component is treated as one long line, but in
+the body, each line is separate.
+Lower-case letters in the
+search pattern will match either lower or upper case in the
+message, while upper case will match only upper case.
+
+Once the search has been performed, the selected messages
+are scanned (see \fIscan\fR) if the `\-scan' switch is given, and
+then they are shown (see \fIshow\fR) if the `\-show' switch is
+given.
+After these two operations, the file operations (if
+requested) are performed.
+
+The `\-file' switch operates exactly like the \fIfile\fR command, with the
+same meaning for the `\-preserve' and `\-link' switches.
+
+The `\-keep' switch is similar to `\-file', but it produces a folder that
+is a subfolder of the folder being searched and defines it as
+the current folder (unless the `\-stay' flag is used).
+This
+subfolder contains the messages which matched the search
+criteria.
+All of the MH commands may be used with the sub-folder
+as the current folder.
+This gives the user considerable power
+in dealing with subsets of messages in a folder.
+
+The messages in a folder produced by `\-keep' will always have the
+same numbers as they have in the source folder (i.e., the
+`\-preserve' switch is automatic).
+This way, the message
+numbers are consistent with the folder from which the messages
+were selected.
+Messages are not removed from the source folder
+(i.e., the `\-link' switch is assumed).
+If a `+folder' is not
+specified, the standard name \*(lqselect\*(rq will be used.
+(This is the
+meaning of \*(lq(select)\*(rq when it appears in the output of the
+\fIfolder\fR command.) If `+folder' arguments are given to
+`\-keep', they will be used rather than \*(lqselect\*(rq for the names
+of the subfolders.
+This allows for several subfolders to be
+maintained concurrently.
+
+When a `\-keep' is performed, the subfolder becomes the current folder.
+This can be overridden by use
+of the `\-stay' switch.
+
+Here's an example:
+
+.nf
+\01  % folder +inbox
+\02           inbox+ has  16 messages (  3\- 22); cur=  3.
+\03  % pick \-from dcrocker
+\04  6 hits.
+\05  [+inbox/select now current]
+\06  % folder
+\07    inbox/select+ has  \06 messages (  3\- 16); cur=  3.
+\08  % scan
+.ds p \\h'\\w'+'u'
+\09   \03+  6/20   Dcrocker          Re: ned file update issue...
+10   \06\*p  6/23   Dcrocker          removal of files from /tm...
+11   \08\*p  6/27   Dcrocker          Problems with the new ned...
+12   13\*p  6/28   d\h'\w'D'u-\w'd'u'crocker          newest nned  \*(<<I would ap...
+13   15\*p  7/\05   Dcrocker          nned  \*(<<Last week I asked...
+14   16\*p  7/\05   d\h'\w'D'u-\w'd'u'crocker          message id format  \*(<<I re...
+15  % show all | print
+16     [produce a full listing of this set of messages on the line printer.]
+17  % folder \-up
+18            inbox+ has  16 messages (  3\- 22); cur=  3; (select).
+19  % folder \-down
+20   inbox/select+ has   6 messages (  3\- 16); cur=  3.
+21  % rmf
+22  [+inbox now current]
+23  % folder
+24            inbox+ has  16 messages (  3\- 22); cur=  3.
+.fi
+
+This is a rather lengthy example, but it shows the power of the
+MH package.
+In item 1, the current folder is set to inbox.
+In 3,
+all of the messages from dcrocker are found in inbox and linked
+into the folder \*(lqinbox/select\*(rq.
+(Since no action switch is
+specified, `\-keep' is assumed.)  Items 6 and 7 show that this
+subfolder is now the current folder.
+Items 8 through 14 are a
+\fIscan\fR of the selected messages (note that they are all from dcrocker
+and are all in upper and lower case).
+Item 15 lists all of the messages to
+the high-speed printer.
+Item 17 directs \fIfolder\fR to set the
+current folder to the parent of the selection-list folder, which
+is now current.
+Item 18 shows that this has been done.
+Item 19 resets
+the current folder to the selection list, and 21 removes the
+selection-list folder and resets the current folder to the
+parent folder, as shown in 22 and 23.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Folder\-Protect:~^For protection on new folders
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+`\-src +folder' defaults to current
+`msgs' defaults to all
+.fi
+`\-keep +select' is the default if no `\-scan', `\-show', or `\-file' is specified
+.Co
+If a `\-src +folder' is specified, it will
+become the current folder, unless a `\-keep' with 0 or 1
+folder arguments makes the selection-list subfolder the
+current folder.
+Each selection-list folder will have its
+current message set to the first of the messages linked into
+it unless the selection list already existed, in which case the
+current message won't be changed.
+.En
+.SC PREV
+.NA
+prev \- show the previous message
+.SY
+prev \%[+folder] \%[\-switches\ for\ \fIl\fR] \%[\-help]
+.DE
+\fIPrev\fR performs a \fIshow\fR on the previous message in the specified
+(or current) folder.
+Like \fIshow\fR, it passes any switches on to the
+program \fIl\fR, which is called to list the message.
+This command
+is exactly equivalent to \*(lqshow prev\*(rq.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+.Co
+If a folder is specified, it will become current, and the
+message that is shown (i.e., the previous message in sequence)
+will become the current message.
+.En
+.SC PROMPTER
+.NA
+prompter \- prompting editor front end
+.SY
+This program is not called directly but takes the place
+of an editor and acts as an editor front end.
+
+.ti .5i
+prompter \%[\-erase\ chr] \%[\-kill\ chr] \%[\-help]
+.DE
+\fIPrompter\fR is an editor which allows rapid composition of
+messages.
+It is particularly useful to network and low-speed
+(less than 2400 baud) users of MH.
+It is an MH program in that
+it can have its own profile entry with switches, but it can't
+be invoked directly as all other MH commands can; it is an editor
+in that it is invoked by an \*(lq\-editor prompter\*(rq switch or by the
+profile entry \*(lqEditor: prompter\*(rq, but functionally it is merely
+a text-collector and not a true editor.
+
+\fIPrompter\fR expects to be called from \fIcomp\fR, \fIrepl\fR, \fIdist\fR, or
+\fIforw\fR, with a draft file as an argument.
+For example, \*(lqcomp
+\-editor prompter\*(rq will call \fIprompter\fR with the file \*(lqdraft\*(rq already set
+up with blank components.
+For each blank component it finds in
+the draft, it prompts the user and accepts a response.
+A
+<RETURN> will cause the whole component to be left out.
+A \*(lq\\\*(rq
+preceding a <RETURN> will continue the response on the next line,
+allowing for multiline components.
+
+Any component that is non-blank will be copied and echoed to the
+terminal.
+
+The start of the message body is prompted by a line of
+dashes.
+If the body is non-blank, the prompt is
+\*(lq--------Enter additional text\*(rq.
+Message-body typing is terminated with
+a <CTRL-D> (or <OPEN>).
+Control is returned to the calling
+program, where the user is asked \*(lqWhat now?\*(rq.
+See \fIcomp\fR for
+the valid options.
+
+The line editing characters for kill and erase may be
+specified by the user via the arguments \*(lq\-kill chr\*(rq and \*(lq\-erase
+chr\*(rq, where chr may be a character; or \*(lq\\nnn\*(rq, where nnn is the
+octal value for the character.
+(Again, these may come from the
+default switches specified in the user's profile.)
+
+A <DEL> during message-body typing is equivalent to
+<CTRL-D> for compatibility with NED.
+A <DEL> during
+component typing will abort the command that invoked
+\fIprompter\fR.
+.Fi
+None
+.Pr
+^prompter-next:~^To name the editor to be used on exit from \fIprompter\fR
+.De
+.Co
+None
+.En
+.SC REPL
+.NA
+repl \- reply to a message
+.SY
+repl \%[+folder] \%[msg] \%[\-editor\ editor] \%[\-inplace] \%[\-annotate]
+\%[\-help] \%[\-noinplace]
+\%[\-noannotate]
+.DE
+\fIRepl\fR aids a user in producing a reply to an existing
+message.
+In its simplest form (with no arguments), it will set up
+a message-form skeleton in reply to the current message in the
+current folder, invoke the editor, and send the composed
+message if so directed.
+The composed message is constructed as
+follows:
+
+.nf
+.in 1i
+To: <Reply-To> or <From>
+cc: <cc>, <To>
+Subject: Re: <Subject>
+In-reply-to: Your message of <Date>
+.ti +\w'In-reply-to: 'u
+<Message-Id>
+.in .5i
+.fi
+
+where field names enclosed in angle brackets (< >) indicate the
+contents of the named field from the message to which the reply
+is being made.
+Once the skeleton is constructed, an editor is
+invoked (as in \fIcomp\fR, \fIdist\fR, and \fIforw\fR).
+While in the editor,
+the message being replied to is available through a link named
+\*(lq@\*(rq.
+In NED, this means the replied-to message may be \*(lqused\*(rq
+with \*(lquse @\*(rq, or put in a window by \*(lqwindow @\*(rq.
+
+As in \fIcomp\fR, \fIdist\fR, and \fIforw\fR, the user will be queried
+before the message is sent.
+If `\-annotate' is
+specified, the replied-to message will be annotated with the
+single line
+
+.ti +.5i
+Replied: \*(<<Date\*(>>.
+
+The command
+\*(lqcomp \-use\*(rq may be used to pick up interrupted editing, as in
+\fIdist\fR and \fIforw\fR; the `\-inplace' switch annotates the message in place,
+so that all folders with links to it will see the annotation.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+^<mh-dir>/draft~^The constructed message file
+^/usr/bin/send~^To send the composed message
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Editor:~^To override the use of /bin/ned as the default editor
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+`+folder' defaults to current
+`msgs' defaults to cur
+`\-editor' defaults to /bin/ned
+`\-noannotate'
+`\-noinplace'
+.Co
+If a `+folder' is specified, it will become the current
+folder, and the current message will be set to the replied-to
+message.
+.sp 2
+.En
+.SC RMF
+.NA
+rmf \- remove folder
+.SY
+rmf \%[+folder] \%[\-help]
+.DE
+\fIRmf\fR removes all of the files (messages) within the specified
+(or default) folder, and then removes the directory (folder).
+If
+there are any files within the folder which are not a part of MH,
+they will \fInot\fR be removed, and an error will be produced.
+If the
+folder is given explicitly or the current folder is a
+subfolder (i.e., a selection list from \fIpick\fR), it will be
+removed without confirmation.
+If no argument is specified and
+the current folder is not a selection-list folder, the
+user will be asked for confirmation.
+
+\fIRmf\fR irreversibly deletes messages that don't have other links,
+so use it with caution.
+
+If the folder being removed is a subfolder, the parent
+folder will become the new current folder, and \fIrmf\fR will
+produce a message telling the user this has happened.
+This
+provides an easy mechanism for selecting a set of messages,
+operating on the list, then removing the list and returning to
+the current folder from which the list was extracted.
+(See the
+example under \fIpick\fR.)
+
+The files that \fIrmf\fR will delete are cur, any file beginning
+with a comma, and files with purely numeric names.
+All others
+will produce error messages.
+
+\fIRmf\fR of a read-only folder will delete the \*(lqcur\-\*(rq entry from the
+profile without affecting the folder itself.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+`+folder' defaults to current, usually with confirmation
+.Co
+\fIRmf\fR will set the current folder to the parent folder if a
+subfolder is removed; or if the current folder is removed,
+it will make \*(lqinbox\*(rq current.
+Otherwise, it doesn't change the
+current folder or message.
+.En
+.SC RMM
+.NA
+rmm \- remove messages
+.SY
+rmm \%[+folder] \%[msgs] \%[\-help]
+.DE
+\fIRmm\fR removes the specified messages by renaming the message
+files with preceding commas.
+(This is the Rand-UNIX backup file
+convention.)
+
+The current message is not changed by \fIrmm\fR, so a \fInext\fR  will
+advance to the next message in the folder as expected.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+`+folder' defaults to current
+`msgs' defaults to cur
+.Co
+If a folder is given, it will become current.
+.En
+.SC SCAN
+.NA
+scan \- produce a one-line-per-message scan listing
+.SY
+scan \%[+folder] \%[msgs] \%[\-f\&f] \%[\-header] \%[\-help]
+\%[\-nof\&f] \%[\-noheader]
+.DE
+\fIScan\fR produces a one-line-per-message listing of the specified
+messages.
+Each \fIscan\fR line contains the message number (name),
+the date, the \*(lqFrom\*(rq field, the \*(lqSubject\*(rq field, and, if room
+allows, some of the body of the message.
+For example:
+
+.nf
+.ta .5i 1.2i 2.6i
+^ #~^^Date~^^  From~^Subject\ \ \ \ \[\*(<<Body]
+^15+~^^7/\05~^^Dcrocker~^nned  \*(<<Last week I asked some of
+^16\ \-~^^7/\05~^^dcrocker~^message id format  \*(<<I recommend
+^18~^^7/\06~^^Obrien~^Re: Exit status from mkdir
+^19~^^7/\07~^^Obrien~^"scan" listing format in MH
+.re
+.fi
+
+The `+' on message 15 indicates that it is the current message.
+The `\-' on message 16 indicates that it has been
+replied to, as indicated by a \*(lqReplied:\*(rq component produced by
+an `\-annotate' switch to the \fIrepl\fR command.
+
+If there is sufficient room left on the \fIscan\fR line after the
+subject, the line will be filled with text from the body,
+preceded by \*(<<.
+\fIScan\fR actually reads each of the specified
+messages and parses them to extract the desired fields.
+During parsing, appropriate error messages will be produced if
+there are format errors in any of the messages.
+
+The `\-header' switch produces a header line prior to the \fIscan\fR
+listing, and the `\-f\&f' switch will cause a form feed to be
+output at the end of the \fIscan\fR listing.
+See Appendix D.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+Defaults:
+`+folder' defaults to current
+`msgs' defaults to all
+`\-nof\&f'
+`\-noheader'
+.Co
+If a folder is given, it will become current.
+The current
+message is unaffected.
+.En
+.SC SEND
+.NA
+send \- send a message
+.SY
+send \%[file] \%[\-draft] \%[\-verbose] \%[\-format] \%[\-msgid]
+\%[\-help]  \%[\-noverbose] \%[\-noformat] \%[\-nomsgid]
+.DE
+\fISend\fR will cause the specified file (default <mh-dir>/draft) to
+be delivered to each of the addresses in the \*(lqTo:\*(rq, \*(lqcc:\*(rq, and \*(lqBcc:\*(rq
+fields of the message.
+If `\-verbose' is specified, \fIsend;\fR
+will monitor the delivery of local and net mail.
+\fISend\fR with no
+argument will query whether the draft is the intended file, whereas
+`\-draft' will suppress this question.
+Once the message has
+been mailed (or queued) successfully, the file will be renamed
+with a leading comma, which allows it to be retreived until the
+next draft message is sent.
+If there are errors in the
+formatting of the message, \fIsend;\fR will abort with a (hopefully)
+helpful error message.
+
+If a \*(lqBcc:\*(rq field is encountered, its addresses will be used for
+delivery, but the \*(lqBcc:\*(rq field itself will be deleted from all
+copies of the outgoing message.
+
+Prior to sending the message, the fields \*(lqFrom:  user\*(rq, and
+\*(lqDate: now\*(rq will be prepended to the message.
+If `\-msgid' is
+specified, then a \*(lqMessage-Id:\*(rq field will also be added to the
+message.
+If the message already contains a \*(lqFrom:\*(rq field, then a
+\*(lqSender: user\*(rq field will be added instead.
+(An already existing
+\*(lqSender:\*(rq field will be deleted from the message.)
+
+If the user doesn't specify `\-noformat', each of the entries in
+the \*(lqTo:\*(rq and \*(lqcc:\*(rq fields will be replaced with \*(lqstandard\*(rq format
+entries.
+This standard format is designed to be usable by all
+of the message handlers on the various systems around the
+ARPANET.
+
+If an \*(lqFcc: folder\*(rq is encountered, the message will be copied
+to the specified folder in the format in which it will appear to any
+receivers of the message.
+That is, it will have the prepended
+fields and field reformatting.
+
+If a \*(lqDistribute-To:\*(rq field is encountered, the message
+is handled as a redistribution message (see \fIdist\fR for
+details), with \*(lqDistribution-Date: now\*(rq and \*(lqDistribution-From: user\*(rq
+added.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+.Pr
+^Path:~^To determine the user's MH directory
+.De
+`file' defaults to draft
+`\-noverbose'
+`\-format'
+`\-nomsgid'
+.Co
+\fISend\fR has no effect on the current message or folder.
+.En
+.SC SHOW
+.NA
+show \- show (list) messages
+.SY
+show \%[+folder] \%[msgs] \%[\-pr] \%[\-nopr] \%[\-draft] \%[\-help]
+\%[\fIl\fR\ or\ \fIpr\fR\ switches]
+.DE
+\fIShow\fR lists each of the specified messages to the standard
+output (typically, the terminal).
+The messages are listed exactly
+as they are, with no reformatting.
+A program called \fIl\fR is
+invoked to do the listing, and any switches not recognized by
+\fIshow\fR are passed along to \fIl\fR.
+
+If no \*(lqmsgs\*(rq are specified, the current message is used.
+If
+more than one message is specified, \fIl\fR will prompt for a
+<return> prior to listing each message.
+
+\fIl\fR will list each message, a page at a time.
+When the end of
+page is reached, \fIl\fR will ring the bell and wait for a <RETURN>
+or <CTRL-D>.
+If a <return> is entered, \fIl\fR will clear the
+screen before listing the next page, whereas <CTRL-D> will not.
+The switches to \fIl\fR are
+`\-p#' to indicate the page length in lines, and `\-w#' to
+indicate the width of the page in characters.
+
+If the standard output is not a terminal, no queries are made,
+and each file is listed with a one-line header and two lines of
+separation.
+
+If `\-pr' is specified, then \fIpr\fR(I) will be invoked rather than
+\fIl\fR, and the switches (other than `\-draft') will be passed
+along.
+\*(lqShow \-draft\*(rq will list the file <mh-dir>/draft if it
+exists.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+^/bin/l~^Screen-at-a-time list program
+^/bin/pr~^\fIpr\fR(I)
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+`+folder' defaults to current
+`msgs' defaults to cur
+`\-nopr'
+.Co
+If a folder is given, it will become the current message.
+The last message
+listed will become the current message.
+.En
+\"
+\"              On to the Appendices
+\"
+.fo ''-%-''
+.he ''''
+.(x
+.sp
+Appendix
+.)x _
+.de $c                          \" Major Heading printer
+.ce
+Appendix \\n+(ch
+.sp 2p
+.ce
+.b "\\s12\\$1\\s0"              \" 12 Point Bold Header
+.(x
+\ \ \ \\n(ch.\\ \\ \\$2
+.)x
+.sp 45p                                \" 45 points or about 1/2 inch
+..
+.++ A
+.bp
+.$c "COMMAND SUMMARY\\**" "Command Summary"
+.(f
+\**All commands accept a \-help switch.
+.)f
+.in 1i
+.na
+.ti .5i
+comp \%[\-editor\ editor] \%[\-form\ formfile] \%[file] \%[\-use]
+\%[\-nouse] \%[\-help]
+
+.ti .5i
+dist \%[+folder] \%[msg] \%[\-form\ formfile] \%[\-editor\ editor]
+\%[\-annotate] \%[\-noannotate]
+\%[\-inplace] \%[\-noinplace]
+\%[\-help]
+
+.ti .5i
+file \%[\-src\ +folder] \%[msgs] \%[\-link] \%[\-preserve] \%+folder\ ...
+\%[\-nolink] \%[\-nopreserve]
+\%[\-file\ file] \%[\-nofile] \%[\-help]
+
+.ti .5i
+folder \%[+folder] \%[msg] \%[\-all] \%[\-fast] \%[\-nofast] \%[\-up] \%[\-down]
+\%[\-header] \%[\-noheader] \%[\-total] \%[\-nototal] \%[\-pack] \%[\-nopack]
+\%[\-help]
+
+.ti .5i
+forw \%[+folder] \%[msgs] \%[\-editor\ editor] \%[\-form\ formfile]
+\%[\-annotate] \%[\-noannotate]
+\%[\-inplace]  \%[\-noinplace]
+\%[\-help]
+
+.ti .5i
+inc \%[+folder] \%[\-audit\ audit-file] \%[\-help]
+
+.ti .5i
+next \%[+folder] \%[\-switches\ for\ \fIl\fR] \%[\-help]
+
+.ta .4i 1.8i
+.nf
+.in .5i
+^pick~^^\0\-cc~^ \%[\-src\ +folder] \%[msgs] \%[\-help] \%[\-scan] \%[\-noscan]
+^^^\0\-date~^   \%[\-show] \%[\-noshow] \%[\-nofile] \%[\-nokeep]
+^^^\0\-from~^
+^^^\s+2\b'\(lt\(bv\(bv\(lk\(bv\(bv\(lb'\s0 \-search~\s+2\b'\(rt\(bv\(bv\(rk\(bv\(bv\(rb'\s0^ pattern
+^^^\0\-subject~^
+^^^\0\-to~^ \%[\-file \%[\-preserve] \%[\-link] \%+folder\ ... \%[\-nopreserve] \%[\-nolink] ]
+^^^\0\-\-component~^ \%[\-keep \%[\-stay] \%[\-nostay] \%[+folder\ ...]\ ]
+.fi
+.re
+
+.ti .5i
+prev \%[+folder] \%[\-switches\ for\ \fIl\fR] \%[\-help]
+
+.ti .5i
+prompter \%[\-erase\ chr] \%[\-kill\ chr] \%[\-help]
+
+.ti .5i
+repl \%[+folder] \%[msg] \%[\-editor\ editor] \%[\-inplace] \%[\-annotate]
+\%[\-help] \%[\-noinplace]
+\%[\-noannotate]
+
+.ti .5i
+rmf \%[+folder] \%[\-help]
+
+.ti .5i
+rmm \%[+folder] \%[msgs] \%[\-help]
+
+.ti .5i
+scan \%[+folder] \%[msgs] \%[\-f\&f] \%[\-header] \%[\-help]
+\%[\-nof\&f] \%[\-noheader]
+
+.ti .5i
+send \%[file] \%[\-draft] \%[\-verbose] \%[\-format] \%[\-msgid]
+\%[\-help]  \%[\-noverbose] \%[\-noformat] \%[\-nomsgid]
+
+.ti .5i
+show \%[+folder] \%[msgs] \%[\-pr] \%[\-nopr] \%[\-draft] \%[\-help]
+\%[\fIl\fR\ or\ \fIpr\fR\ switches]
+.ad
+.in 0
+\".+c "MESSAGE FORMAT" "Message Format"
+.if t \{
+.ll 32P
+.lt 32P
+\}
+.bp
+.$c "MESSAGE FORMAT" "Message Format"
+.pp
+This section paraphrases the format of ARPANET text messages
+given in Ref. 6.
+
+.lp
+ASSUMPTIONS
+.np
+Messages
+are expected to consist of lines of text.
+Graphics and binary data are not handled.
+.np
+No data compression is accepted.
+All text is clear
+ASCII 7-bit data.
+
+.lp
+LAYOUT
+.lp
+A general \*(lqmemo\*(rq framework is used.
+A message consists of a
+block of information in a rigid format, followed by general
+text with no specified format.
+The rigidly formatted  first
+part of a message is  called the header, and the free-format
+portion is called the body.
+The header must always
+exist, but the body is optional.
+
+.lp
+THE HEADER
+.lp
+Each header item can be viewed as a single logical line of ASCII
+characters.
+If the text of a header item extends across several
+real lines, the continuation lines are indicated by leading
+spaces or tabs.
+.lp
+Each header item is called a component and is composed of a
+keyword or name, along with associated text.
+The keyword begins at the
+left margin, may contain spaces or tabs, may not exceed 63
+characters, and is terminated by a colon (:).
+Certain
+components (as identified by their keywords) must follow rigidly
+defined formats in their text portions.
+.lp
+The text for most formatted components (e.g., \*(lqDate:\*(rq and \*(lqMessage-Id:\*(rq)
+is produced automatically.
+The only ones entered by the
+user are address fields such as \*(lqTo:\*(rq, \*(lqcc:\*(rq, etc.
+ARPA addresses
+are assigned mailbox names and host computer specifications.
+The
+rough format is \*(lqmailbox at host\*(rq, such as \*(lqBorden at Rand-Unix\*(rq.
+Multiple addresses are separated by commas.
+A missing host is
+assumed to be the local host.
+
+.ne 10
+.lp
+THE BODY
+.lp
+A blank line signals that all following text up to the end of the file
+is the body.
+(A blank line is defined as a pair of
+<end-of-line> characters with \fIno\fR characters in between.)
+No formatting is expected or enforced within the body.
+.lp
+Within MH, a line consisting of dashes is accepted
+as the header delimiter.
+This is a cosmetic feature applying
+only to locally composed mail.
+.bp
+.$c "MESSAGE NAME BNF" "Message Name BNF"
+
+.ta 1.2i 1.8i 3.2i
+.nf
+.in 1i
+^msgs~^^:=~^^msgspec~^|
+^^^^msgs msgspec
+
+^msgspec~^^:=~^^msg~^|
+^^^^^msg-range~^|
+^^^^msg-sequence
+
+^msg~^^:=~^^msg-name~^|
+^^^^<number>^
+
+^msg-name~^^:=~^^\*(lqfirst\*(rq~^|
+^^^^^\*(lqlast\*(rq~^|
+^^^^^\*(lqcur\*(rq~^|
+^^^^^\*(lq\*.\*(rq~^|
+^^^^^\*(lqnext\*(rq~^|
+^^^^\*(lqprev\*(rq
+
+^msg-range~^^:=~^^msg\*(lq-\*(rqmsg~^|
+^^^^^\*(lqall\*(rq
+
+^msg-sequence~^^:=~^msg\*(lq:\*(rqsigned-number
+
+^signed-number~^^:=~^^\*(lq+\*(rq<number>~^|
+^^^^^\*(lq\--\*(rq<number>~^|
+^^^^<number>
+.re \" Reset Tabs
+.fi
+.sp
+.pp
+Where <number> is a decimal number in the range 1 to 999.
+.pp
+Msg-range specifies all of the messages in the given range
+and must not be empty.
+.pp
+Msg-sequence specifies up to <number> of messages, beginning
+with \*(lqmsg\*(rq (in the case of first, cur, next, or <number>),
+or ending with \*(lqmsg\*(rq (in the case of prev or last).
++<number> forces \*(lqstarting with msg\*(rq, and \-<number> forces
+\*(lqending with number\*(rq.
+In all cases, \*(lqmsg\*(rq must exist.
+.bp
+.$c "EXAMPLE OF SHELL COMMANDS"  "Example of Shell Commands"
+.pp
+UNIX commands may be mixed with MH commands to obtain additional
+functions.
+These may be prepared as files (known as
+shell command files or
+shell scripts).
+The following example is a useful function that
+illustrate the possibilities.
+Other functions, such as copying,
+deleting, renaming, etc., can be achieved in a similar fashion.
+
+HARDCOPY
+.pp
+The command:
+
+.ti +.5i
+(scan\0\-f\&f\0\-header;\0show\0all\0\-pr\0\-f)\0|\0print
+
+produces a scan listing of the current folder, followed by a
+form feed, followed by a formatted listing of all messages
+in the folder, one per page.
+Omitting \*(lq\-pr\0\-f\*(rq will cause the
+messages to be concatenated, separated by a one-line header
+and two blank lines.
+.pp
+You can create variations on this theme, using \fIpick\fR.
+.re
+.fi
+.in 0
+.bp
+.ce
+.b \\s12REFERENCES\\s0
+.(x
+.sp
+REFERENCES
+.)x
+.sp 3
+.in .4i
+.ti 0
+1.  Crocker, D. H., J. J. Vittal, K. T. Pogran, and D. A. Henderson, Jr.,
+\*(lqStandard for the Format of ARPA Network Test Messages,\*(rq \fIArpanet Request
+for Comments\fR, No. 733, Network Information Center 41952, Augmentation
+Research Center, Stanford Research Institute,
+November 1977.
+
+.ti 0
+2.  Thompson, K., and D. M. Ritchie, \*(lqThe UNIX Time-sharing System,\*(rq
+\fICommunications of the ACM\fR, Vol. 17, July 1974, pp. 365-375.
+
+.ti 0
+3.  McCauley, E. J., and P. J. Drongowski, \*(lqKSOS\-The Design of a Secure
+Operating System,\*(rq \fIAFIPS Conference Proceedings\fR,
+National Computer Conference,
+Vol. 48, 1979, pp. 345-353.
+
+.ti 0
+4.  Crocker, David H., \fIFramework and Functions of the \*(lqMS\*(rq Personal
+Message System\fR, The Rand Corporation, R-2134-ARPA, December 1977.
+
+.ti 0
+5.  Thompson, K., and D. M. Ritchie, \fIUNIX Programmer's Manual\fR, 6th ed.,
+Western Electric Company, May 1975 (available only to UNIX licensees).
+
+.ti 0
+6.  Bilofsky, Walter, \fIThe CRT Text Editor NED\-Introduction and
+Reference Manual\fR, The Rand Corporation, R-2176-ARPA, December 1977.
+.bp 3
+.de $c
+.ce
+.b "\\s12\\$1\\s0"   \" 12 Point Bold Header
+.(x y
+.sp
+\\$1
+.)x
+.sp 3
+..
+.pn 3
+.++ P
+.fo ''''
+.he ''-%-''
+.+c PREFACE
+.pp
+This report describes a system for dealing with messages transmitted on a
+computer.  Such messages might originate with other users of the same
+computer or might come from an outside source through a network to which the user's
+computer is connected.  Such computer-based message systems are
+becoming increasingly widely used, both within and outside the Department
+of Defense.
+.pp
+The message handling system MH was developed for two reasons.
+One was to investigate some
+research ideas concerning how a message system might take advantage of
+the architecture of the UNIX time-sharing operating system for
+Digital Equipment Corporation PDP-11 and VAX computers, and the special
+features of UNIX's command-level interface with the user (the
+\*(lqshell\*(rq).  The other reason was to provide a better and more
+adaptable base than that of conventional designs
+on which to build a command and control message system.
+The effort has succeeded in both
+regards, although this report mainly describes the message system itself
+and how it fits in with UNIX.  The main research results are being
+described and analyzed in a forthcoming Rand report.
+The system is currently being used as part
+of a tactical command and control \*(lqlaboratory,\*(rq which is also being described
+in a separate report.
+.pp
+The present report should be of interest to three groups of readers.  First,
+it is a complete reference manual for the users of MH (although
+users outside of Rand must take into
+account differences from the local Rand operating system).  Second, it should be
+of interest to those who have a general knowledge of computer-based
+message systems, both in civilian and military applications.  Finally,
+it should be of interest to those who build large subsystems that
+interface with users, since it illustrates a new approach to such
+interfaces.
+.pp
+The MH system was developed by the first
+author, using an approach suggested by the other two authors.
+Valuable assistance was provided by Phyllis Kantar in the later
+stages of the system's implementation.
+Several colleagues
+contributed to the ideas included in this system, particularly
+Robert Anderson and David Crocker.
+In addition, valuable experience
+in message systems, and a valuable source of ideas, was available
+to us in the form of a previous message system for UNIX called
+MS, designed at Rand by David Crocker.
+.pp
+This report was prepared as part of the Rand project entitled \*(lqData
+Automation Research\*(rq, sponsored by Project AIR FORCE.
+.pn 5
+.+c SUMMARY
+.pp
+Electronic communication of text messages is becoming
+commonplace.  Computer-based message systems\-software
+packages that provide tools for dealing with messages\-are used in many
+contexts.  In particular, message systems are becoming
+increasingly important in command and control and intelligence
+applications.
+.pp
+This report describes a message handling system called MH.
+This system provides the user
+with tools to compose, send, receive, store, retrieve, forward, and
+reply to messages.  MH has been built on the UNIX time-sharing system,
+a popular operating system developed for the DEC PDP-11 and VAX classes of
+computers.
+.pp
+A complete description of MH is given for users of
+the system.  For those who do not intend to use the system, this description
+gives a general idea of what a message system is like.  The system involves
+some new ideas about how large subsystems can be constructed.  These design
+concepts and a comparison of MH with other message systems
+will be published in a forthcoming Rand report.
+.pp
+The interesting and unusual features of MH include the
+following:  The user command interface to MH is the UNIX \*(lqshell\*(rq
+(the standard UNIX command interpreter).  Each separable
+component of message handling, such as message composition or
+message display, is a separate command.  Each program is driven from
+and updates a private user environment, which is stored as a file
+between program invocations.  This private environment also contains
+information to \*(lqcustom tailor\*(rq MH to the individual's tastes.  MH
+stores each message as a separate file under UNIX, and it utilizes the
+tree-structured UNIX file system to organize groups of files within
+separate directories or \*(lqfolders.\*(rq  All of the UNIX facilities
+for dealing with files and directories, such as
+renaming, copying, deleting, cataloging, off-line printing, etc., are
+applicable to messages and directories of messages (folders).  Thus,
+important capabilities needed in a message system are available in MH without
+the need (often seen in other message systems) for code that
+duplicates the facilities of the supporting operating system.
+It also allows users familiar with the shell to use MH with minimal
+effort.
+.he ''''
+.fo ''''
+.bp
+.ce
+.b \\s12CONTENTS\\s0
+.sp 3
+.xp y
+.xp x
+
+.bp     \" Spare numbers for cut and paste work!
+.ft B
+
+1       1       1       1       1       1       1       1
+
+1       1       1       1       1       1       1       1
+
+1       1       1       1       1       1       1       1
+
+1       1       1       1       1       1       1       1
+
+2       2       2       2       2       2       2       2
+
+2       2       2       2       2       2       2       2
+
+2       2       2       2       2       2       2       2
+
+3       3       3       3       3       3       3       3
+
+3       3       3       3       3       3       3       3
diff --git a/docs/historical/2.9BSD/doc/titlepage b/docs/historical/2.9BSD/doc/titlepage
new file mode 100644 (file)
index 0000000..427f156
--- /dev/null
@@ -0,0 +1,23 @@
+.(l C
+.sp 1i
+.sz +8
+.b
+MH
+.sp 0.4i
+.sz -4
+.r
+A Mail Handling System
+.sp 0.2i
+for \s-1UNIX\s+1
+.sz -4
+.sp 1i
+October, 1979
+
+Bruce Borden
+.sp 1i
+The Rand Corporation
+1700 Main Street
+Santa Monica, CA 90406
+
+(213) 399-0568 x 7463
+.)l
diff --git a/docs/historical/2.9BSD/man/Makefile b/docs/historical/2.9BSD/man/Makefile
new file mode 100644 (file)
index 0000000..237443e
--- /dev/null
@@ -0,0 +1,37 @@
+DEST         = $(DESTDIR)/usr/man/mann
+
+MAKEFILE      = Makefile
+
+PRINT        = vtroff
+
+SRCS         = comp.1 \
+               dist.1 \
+               file.1 \
+               folder.1 \
+               forw.1 \
+               inc.1 \
+               next.1 \
+               pick.1 \
+               prev.1 \
+               prompter.1 \
+               repl.1 \
+               rmf.1 \
+               rmm.1 \
+               scan.1 \
+               send.1 \
+               show.1
+
+all:;
+
+clean:;
+
+depend:;       @mkmf -f $(MAKEFILE)
+
+cp:;           @echo Installing $(SRCS) in $(DEST)
+               @for i in $(SRCS); do cp $$i $(DEST)/`basename $$i .1`.n; done
+
+print:         $(SRCS)
+               @$(PRINT) -man $?
+               @touch print
+
+update:;
diff --git a/docs/historical/2.9BSD/man/comp.1 b/docs/historical/2.9BSD/man/comp.1
new file mode 100644 (file)
index 0000000..87c392e
--- /dev/null
@@ -0,0 +1,82 @@
+.TH COMP 1 "3 August 1983"
+.UC 4
+.SH NAME
+comp \- compose a message
+.SH SYNOPSIS
+.B comp
+[ \-editor editor ] [ \-form formfile ] [ file ] [ \-use ]
+[ \-nouse ] [ \-help ]
+.SH DESCRIPTION
+\fIComp\fP is used to create a new message to be mailed.
+If
+\fIfile\fP is not specified, the file named \*(lqdraft\*(rq in the user's MH
+directory will be used.
+\fIComp\fR copies a message form to
+the file being composed and then invokes an editor on the
+file.
+The default editor is /bin/ned, which may be overridden with
+the `\-editor' switch or with a profile entry \*(lqEditor:\*(rq.
+The default message form contains the following elements:
+.nf
+
+     To:
+     cc:
+     Subject:
+     ----------
+
+.fi
+If the file named \*(lqcomponents\*(rq exists in the user's MH directory,
+it will be used instead of this form.
+If `\-form formfile' is specified, the specified formfile (from the MH
+directory) will be used as the skeleton.
+The line of dashes
+or a blank line must be left between the header and the
+body of the message for the message to be identified properly when it is
+sent (see
+.IR send (1)).
+The switch `\-use' directs \fIcomp\fR to
+continue editing an already started message.
+That is, if a
+\fIcomp\fR (or \fIdist\fR, \fIrepl\fR, or \fIforw\fR) is terminated without
+sending the message, the message can be edited again via
+\*(lqcomp \-use\*(rq.
+.PP
+If the specified file (or draft) already exists, \fIcomp\fR will ask
+if you want to delete it before continuing.
+A reply of \fBNo\fR will abort the
+\fIcomp\fR, \fByes\fR will replace the existing draft with a blank
+skeleton, \fBlist\fR will display the draft, and \fBuse\fR will use it
+for further composition.
+.PP
+Upon exiting from the editor, \fIcomp\fR will ask \*(lqWhat now?\*(rq.
+The valid
+responses are \fBlist\fR, to list the draft on the terminal; \fBquit\fR, to
+terminate the session and preserve the draft; \fBquit delete\fR, to terminate,
+then delete the draft; \fBsend\fR, to send the message; \fBsend verbose\fR, to
+cause the delivery process to be monitored; \fBedit <editor>\fR, to invoke
+<editor> for further editing; and \fBedit\fR, to re-edit using the
+same editor that was used on the preceding round unless a profile
+entry \*(lq<lasteditor>\-next: <editor>\*(rq names an alternative editor.
+.PP
+\fIComp\fR does not affect either the current folder or the current message.
+.SH FILES
+.nf
+.ta \w'or <mh-dir>/components    'u
+/etc/mh/components     The message skeleton
+or <mh-dir>/components Rather than the standard skeleton
+$HOME/\*.mh_profile    The user profile
+<mh-dir>/draft The default message file
+/usr/new/send  To send the composed message
+.fi
+.SH "PROFILE COMPONENTS"
+.nf
+.ta \w'<lasteditor>\-next:    'u
+Path:  To determine the user's MH directory
+Editor:        To override the use of /bin/ned as the default editor
+<lasteditor>\-next:    editor to be used after exit from <lasteditor>
+.SH DEFAULTS
+.nf
+`file' defaults to draft
+`\-editor' defaults to /bin/ned
+`\-nouse'
+.fi
diff --git a/docs/historical/2.9BSD/man/dist.1 b/docs/historical/2.9BSD/man/dist.1
new file mode 100644 (file)
index 0000000..2b0abf4
--- /dev/null
@@ -0,0 +1,83 @@
+.TH DIST 1 "3 August 1983"
+.UC 4
+.SH NAME
+dist \- redistribute a message to additional addresses
+.SH SYNOPSIS
+.B dist
+[ +folder ] [ msg ] [ \-form formfile ] [ \-editor editor ]
+[ \-annotate ] [ \-noannotate ]
+[ \-inplace ] [ \-noinplace ] [ \-help ]
+.SH DESCRIPTION
+\fIDist\fR is similar to \fIforw\fR.
+It prepares the specified
+message for redistribution to addresses that (presumably) are
+not on the original address list.
+The file \*(lqdistcomps\*(rq in the
+user's MH directory, or a standard form, or the file specified by
+`\-form formfile' will be used as the blank components file to
+be prepended to the message being distributed.
+The standard form
+has the components \*(lqDistribute-to:\*(rq and \*(lqDistribute-cc:\*(rq.
+When
+the message is sent, \*(lqDistribution-Date:\0date\*(rq,
+\*(lqDistribution-From:\0name\*(rq, and
+\*(lqDistribution-Id:\0id\*(rq (if `\-msgid' is
+specified to \fIsend\fR;) will be prepended to the outgoing message.
+Only those addresses in \*(lqDistribute-To\*(rq, \*(lqDistribute-cc\*(rq, and
+\*(lqDistribute-Bcc\*(rq will be sent.
+Also, a \*(lqDistribute-Fcc:\0folder\*(rq
+will be honored (see \fIsend;\fR).
+.PP
+\fISend\fR recognizes a message as a redistribution message by the
+existence of the field \*(lqDistribute-To:\*(rq, so don't try to
+redistribute a message with only a \*(lqDistribute-cc:\*(rq.
+.PP
+If the `\-annotate' switch is given, each message being
+distributed will be annotated with the lines:
+.nf
+
+     Distributed:\0\*(<<date\*(>>
+     Distributed:\0Distribute-to: names
+
+.fi
+where each \*(lqto\*(rq list contains as many lines as required.
+This annotation
+will be done only if the message is sent directly from \fIdist\fR.
+If the
+message is not sent immediately from \fIdist\fR (i.e., if it is sent later
+via \fIsend;\fR),
+\*(lqcomp \-use\*(rq may be used to re-edit and send the constructed message,
+but the annotations won't take place.
+The '\-inplace' switch causes annotation to
+be done in place in order to preserve links to the annotated message.
+.PP
+See \fIcomp\fR for a description of the `\-editor' switch and for options
+upon exiting from the editor.
+.PP
+If a +folder is specified, it will become the current
+folder, and the current message will be set to the message
+being redistributed.
+.SH FILES
+.nf
+.ta \w'or <mh-dir>/components    'u
+/etc/mh/components     The message skeleton
+or <mh-dir>/components Rather than the standard skeleton
+$HOME/\*.mh\(ruprofile The user profile
+<mh-dir>/draft The default message file
+/usr/bin/send  To send the composed message
+.fi
+.SH "PROFILE COMPONENTS"
+.nf
+.ta \w'<lasteditor>\-next:     'u
+Path:  To determine the user's MH directory
+Editor:        To override the use of /bin/ned as the default editor
+<lasteditor>\-next:    editor to be used after exit from <lasteditor>
+.fi
+.SH DEFAULTS
+.nf
+`+folder' defaults to the current folder
+`msg' defaults to cur
+`\-editor' defaults to /bin/ned
+`\-noannotate'
+`\-noinplace'
+.fi
diff --git a/docs/historical/2.9BSD/man/file.1 b/docs/historical/2.9BSD/man/file.1
new file mode 100644 (file)
index 0000000..74c7441
--- /dev/null
@@ -0,0 +1,91 @@
+.TH FILE 1 "3 August 1983"
+.UC 4
+.SH NAME
+file \- file message(s) in (an)other folder(s)
+.SH SYNOPSIS
+file [ \-src +folder ] [ msgs ] [ \-link ] [ \-preserve ] +folder ...
+[ \-nolink] [ \-nopreserve ]
+[ \-file file ] [ \-nofile ] [ \-help ]
+.SH DESCRIPTION
+\fIFile\fR moves (\fImv\fR(1)) or links (\fIln\fR(1)) messages from a
+source folder into one or more destination folders.
+If you think
+of a message as a sheet of paper, this operation is not
+unlike filing the sheet of paper (or copies) in file cabinet
+folders.
+When a message is filed, it is linked into the
+destination folder(s) if possible, and is copied otherwise.
+As long
+as the destination folders are all on the same file system, multiple filing
+causes little storage overhead.
+This facility provides a good way to cross-file or multiply-index
+messages.
+For example, if a message is received from Jones about
+the ARPA Map Project, the command
+.nf
+
+     file\0cur\0+jones\0+Map
+
+.fi
+would allow the message to be found in either of the two
+folders `jones' or `Map'.
+.PP
+The option `\-file file' directs \fIfile\fR to use the specified
+file as the source message to be filed, rather than a message from
+a folder.
+.PP
+If a destination folder doesn't exist, \fIfile\fR will ask if you
+want to create one.
+A negative response will abort the file
+operation.
+.PP
+`\-link' preserves the source folder copy of the message
+(i.e., it does a \fIln\fR(1) rather than a \fImv\fR(1)), whereas,
+`\-nolink' deletes the \*(lqfiled\*(rq messages from the source
+folder.
+Normally, when a message is filed, it is assigned the
+next highest number available in each of the destination folders.
+Use of the `\-preserve' switch will override this message
+\*(lqrenaming\*(rq, but name conflicts may occur, so
+use this switch cautiously.
+(See \fIpick\fR for more details on
+message numbering.)
+.PP
+If `\-link' is not specified (or `\-nolink' is specified),
+the filed messages will be removed (
+.IR unlink (2))
+from the source folder.
+.PP
+If `\-src +folder' is given, it will become the
+current folder for future MH commands.
+If neither `\-link' nor
+`all' are specified, the current message in the source
+folder will be set to the last message specified; otherwise, the
+current message won't be changed.
+.SH FILES
+.nf
+.ta \w'$HOME/\*.mh\(ruprofile    'u
+$HOME/\*.mh\(ruprofile The user profile
+.fi
+.SH "PROFILE COMPONENTS"
+.nf
+.ta \w'Folder\-Protect:    'u
+Path:  To determine the user's MH directory
+Current-Folder:        To find the default current folder
+Folder\-Protect:       To set mode when creating a new folder
+.fi
+.SH DEFAULTS
+.nf
+`\-src +folder' defaults to the current folder
+`msgs' defaults to cur
+`\-nolink'
+`\-nopreserve'
+`\-nofile'
+.fi
+.SH CONTEXT
+If `\-src +folder' is given, it will become the
+current folder for future MH commands.
+If neither `\-link' nor
+`all' are specified, the current message in the source
+folder will be set to the last message specified; otherwise, the
+current message won't be changed.
diff --git a/docs/historical/2.9BSD/man/folder.1 b/docs/historical/2.9BSD/man/folder.1
new file mode 100644 (file)
index 0000000..063faf9
--- /dev/null
@@ -0,0 +1,105 @@
+.TH FOLDER 1 "3 August 1983"
+.UC 4
+.SH NAME
+folder \- set/list current folder/message
+.SH SYNOPSIS
+.B folder
+[ +folder ] [ msg ] [ \-all ] [ \-fast ] [ \-nofast ] [ \-up ] [ \-down ]
+[ \-header ] [ \-noheader ] [ \-total ] [ \-nototal ] [ \-pack ] [ \-nopack ]
+[ \-help ]
+.PP
+folders  <equivalent to 'folder \-all'>
+.SH DESCRIPTION
+Since the MH environment is the shell, it is easy to lose
+track of the current folder from day to day.
+\fIFolder\fR will
+list the current folder, the number of messages in it, the
+range of the messages (low-high), and the current message within
+the folder, and will flag a selection list or extra files if they
+exist.
+An example of the output is:
+.nf
+
+      inbox+ has 16 messages ( 3\- 22); cur= 5.
+
+.fi
+If a `+folder' and/or `msg' are specified, they will
+become the current folder and/or message.
+An `\-all' switch
+will produce a line for each folder in the user's MH directory,
+sorted alphabetically.
+These folders are preceded by the read-only
+folders, which occur as \*.mh\(ruprofile \*(lqcur\-\*(rq entries.
+For example,
+.nf
+
+.fc ^ ~
+.ta 1.5i 2.1i 2.7i 3.5i
+^~Folder\ \ ^^~#\ of\ ^^messages~^^(~\ range\~ );\ ^cur msg (other files)
+^~/fsd/rs/m/tacc\ \ ^^has~35\ ^^messages~^^(~1\-\035);\ ^cur=\ 23.
+^~/rnd/phyl/Mail/EP\ \ ^^has~82\ ^^messages~^^(~1\-108);\ ^cur=\ 82.
+^~f\&f\ \ ^^has~4\ ^^messages~^^(~1\-\0\04);\ ^cur=\ \01.
+^~inbox+\ ^^has~16\ ^^messages~^^(~3\-\022);\ ^cur=\ \05.
+^~mh\ \ ^^has~76\ ^^messages~^^(~1\-\076);\ ^cur=\ 70.
+^~notes\ \ ^^has~2\ ^^messages~^^(~1\-\0\02);\ ^cur=\ \01.
+^~ucom\ \ ^^has~124\ ^^messages~^^(~1\-124);\ ^cur=\ \06; (select).
+
+^^^~TOTAL=\0339\ ^messages\0in\0\07\0Folders.
+.re
+.fi
+.PP
+The \*(lq+\*(rq after inbox indicates that it is the current folder.
+The \*(lq(select)\*(rq indicates that the folder ucom has a selection
+list produced by \fIpick\fR.
+If \*(lqothers\*(rq had appeared in parentheses at
+the right of a line, it would indicate that there are files in
+the folder directory that don't belong under the MH file naming
+scheme.
+.PP
+The header is output if either an `\-all' or a `\-header' switch
+is specified; it is suppressed by `\-noheader'.
+Also, if \fIfolder\fR
+is invoked by a name ending with \*(lqs\*(rq (e.g., \fIfolders\fR),
+`\-all' is assumed.
+A `\-total' switch will produce only the
+summary line.
+.PP
+If `\-fast' is given, only the folder name (or names in the
+case of `\-all') will be listed.
+(This is faster because the
+folders need not be read.)
+.PP
+The switches `\-up' and `\-down' change the folder to be the
+one above or below the current folder.
+That is, \*(lqfolder \-down\*(rq
+will set the folder to \*(lq<current\-folder>/select\*(rq, and if the
+current folder is a selection-list folder, \*(lqfolder \-up\*(rq will
+set the current folder to the parent of the selection-list.
+(See \fIpick\fR for details on selection-lists.)
+.PP
+The `\-pack' switch will compress the message names in a folder, removing
+holes in message numbering.
+.SH FILES
+.nf
+.ta \w'$HOME/\*.mh\(ruprofile    'u
+$HOME/\*.mh\(ruprofile The user profile
+/bin/ls        To fast-list the folders
+.fi
+.SH "PROFILE COMPONENTS"
+.nf
+.ta \w'Current-Folder:    'u
+Path:  To determine the user's MH directory
+Current-Folder:        To find the default current folder
+.fi
+.SH DEFAULTS
+.nf
+`+folder' defaults to the current folder
+`msg' defaults to none
+`\-nofast'
+`\-noheader'
+`\-nototal'
+`\-nopack'
+.fi
+.SH CONTEXT
+If `+folder' and/or `msg' are given, they will become the
+current folder and/or message.
diff --git a/docs/historical/2.9BSD/man/forw.1 b/docs/historical/2.9BSD/man/forw.1
new file mode 100644 (file)
index 0000000..ed87327
--- /dev/null
@@ -0,0 +1,68 @@
+.TH FORW 1 "3 August 1983"
+.UC 4
+.SH NAME
+forw \- forward messages
+.SH SYNOPSIS
+.B forw
+[ +folder ] [ msgs ] [ \-editor editor ] [ \-form formfile ]
+[ \-annotate ] [ \-noannotate ]
+[ \-inplace ]  [ \-noinplace ] [ \-help ]
+.SH DESCRIPTION
+\fIForw\fR may be used to prepare a message containing other
+messages.
+It constructs the new message from the components file
+or `\-form formfile' (see
+.IR comp (1)),
+with a body composed of the message(s) to be forwarded.
+An editor is invoked as in \fIcomp\fR,
+and after editing is complete, the user is prompted before the message
+is sent.
+.PP
+If the `\-annotate' switch is given, each message being
+forwarded will be annotated with the lines
+.nf
+
+     Forwarded: \*(<<date\*(>>
+     Forwarded: To: names
+     Forwarded: cc: names
+
+.fi
+where each \*(lqTo:\*(rq and \*(lqcc:\*(rq list contains as many lines as required.
+This annotation will be done only if the message is sent directly
+from \fIforw\fR.
+If the message is not sent immediately from \fIforw\fR,
+\*(lqcomp \-use\*(rq may be used in a later session to re-edit and send
+the constructed message, but the annotations won't take place.
+The `\-inplace' switch permits annotating a message in place in
+order to preserve its links.
+.PP
+See \fIcomp\fR for a description of the `\-editor' switch.
+.SH FILES
+.nf
+.ta \w'or <mh-dir>/components    'u
+/etc/mh/components     The message skeleton
+or <mh-dir>/components Rather than the standard skeleton
+$HOME/\*.mh\(ruprofile The user profile
+<mh-dir>/draft The default message file
+/usr/bin/send  To send the composed message
+.fi
+.SH "PROFILE COMPONENTS"
+.nf
+.ta \w'<lasteditor>\-next:    'u
+Path:  To determine the user's MH directory
+Editor:        To override the use of /bin/ned as the default editor
+Current-Folder:        To find the default current folder
+<lasteditor>\-next:    editor to be used after exit from <lasteditor>
+.fi
+.SH DEFAULTS
+.nf
+`+folder' defaults to the current folder
+`msgs' defaults to cur
+`\-editor' defaults to /bin/ned
+`\-noannotate'
+`\-noinplace'
+.fi
+.SH CONTEXT
+If a +folder is specified, it will become
+the current folder, and the current message will be set to
+the first message being forwarded.
diff --git a/docs/historical/2.9BSD/man/inc.1 b/docs/historical/2.9BSD/man/inc.1
new file mode 100644 (file)
index 0000000..48238b4
--- /dev/null
@@ -0,0 +1,84 @@
+.TH INC 1 "3 August 1983"
+.UC 4
+.SH NAME
+inc \- incorporate new mail
+.SH SYNOPSIS
+.B inc
+[ +folder ] [ \-audit audit-file ] [ \-help ]
+.SH DESCRIPTION
+\fIInc\fR incorporates mail from the user's incoming mail drop
+(\*.mail) into an MH folder.
+If `+folder' isn't specified,
+the folder named \*(lqinbox\*(rq in the user's MH directory will be used.
+The
+new messages being incorporated are assigned numbers starting
+with the next highest number in the folder.
+If the specified (or
+default) folder doesn't exist, the user will be queried prior to
+its creation.
+As the messages are processed, a \fIscan\fR  listing
+of the new mail is produced.
+.PP
+If the user's profile contains a \*(lqMsg\-Protect: nnn\*(rq entry, it
+will be used as the protection on the newly created messages,
+otherwise the MH default of 664 will be used.
+During all
+operations on messages, this initially assigned protection will
+be preserved for each message, so \fIchmod\fR(I) may be used to set a
+protection on an individual message, and its protection will be
+preserved thereafter.
+.PP
+If the switch `\-audit audit-file' is specified (usually as a
+default switch in the profile), then \fIinc\fR will append a header
+line and a line per message to the end of the specified
+audit-file with the format:
+.nf
+
+.ti 1i
+\*(<<inc\*(>> date
+.ti 1.5i
+<scan line for first message>
+.ti 1.5i
+<scan line for second message>
+.ti 2.5i
+<etc.>
+
+.fi
+This is useful for keeping track of volume and source of incoming
+mail.
+Eventually, \fIrepl\fR, \fIforw\fR, \fIcomp\fR, and \fIdist\fR may also
+produce audits to this (or another) file, perhaps with
+\*(lqMessage-Id:\*(rq information to keep an exact correspondence history.
+\*(lqAudit-file\*(rq will be in the user's MH directory unless a full
+path is specified.
+.PP
+\fIInc\fR will incorporate even illegally formatted messages into the
+user's MH folder, inserting a blank line prior to the offending
+component and printing a comment identifying the bad message.
+.PP
+In all cases, the \*.mail file will be zeroed.
+.SH FILES
+.nf
+.ta \w'<mh-dir>/audit-file    'u
+$HOME/\*.mh\(ruprofile The user profile
+$HOME/\*.mail  The user's mail drop
+<mh-dir>/audit-file    Audit trace file (optional)
+.fi
+.SH "PROFILE COMPONENTS"
+.nf
+.ta \w'Folder\-Protect:           'u
+Path:  To determine the user's MH directory
+Folder\-Protect:       For protection on new folders
+Msg\-Protect:  For protection on new messages
+.fi
+.SH DEFAULTS
+.nf
+`+folder' defaults to \*(lqinbox\*(rq
+.fi
+.SH CONTEXT
+The folder into which the message is
+being incorporated will become the
+current folder, and the first message incorporated will be the
+current message.
+This leaves the context ready for a \fIshow\fR
+of the first new message.
diff --git a/docs/historical/2.9BSD/man/next.1 b/docs/historical/2.9BSD/man/next.1
new file mode 100644 (file)
index 0000000..9531180
--- /dev/null
@@ -0,0 +1,29 @@
+.TH NEXT 1 "3 August 1983"
+.UC 4
+.SH NAME
+next \- show the next message
+.SH SYNOPSIS
+.B next
+[ +folder ] [ \-switches for \fIl\fR ] [ \-help ]
+.SH DESCRIPTION
+\fINext\fR performs a \fIshow\fR on the next message in the
+specified (or current) folder.
+Like \fIshow\fR, it passes any
+switches on to the program \fIl\fR, which is called to list the
+message.
+This command is exactly equivalent to \*(lqshow next\*(rq.
+.SH FILES
+.nf
+.ta \w'$HOME/\*.mh\(ruprofile   'u
+$HOME/\*.mh\(ruprofile The user profile
+.fi
+.SH "PROFILE COMPONENTS"
+.nf
+.ta \w'Current-Folder:   'u
+Path:  To determine the user's MH directory
+Current-Folder:        To find the default current folder
+.fi
+.SH CONTEXT
+If a folder is specified, it will become the current folder, and the
+message that is shown (i.e., the next message in sequence)
+will become the current message.
diff --git a/docs/historical/2.9BSD/man/pick.1 b/docs/historical/2.9BSD/man/pick.1
new file mode 100644 (file)
index 0000000..bdd15e1
--- /dev/null
@@ -0,0 +1,185 @@
+.TH PICK 1 "3 August 1983"
+.UC 4
+.SH NAME
+pick \- select messages by content
+.SH SYNOPSIS
+.fc ^ ~
+.ta .4i 1.8i
+.nf
+.in .5i
+^pick~^^\0\-cc~^ \%[\-src\ +folder] \%[msgs] \%[\-help] \%[\-scan] \%[\-noscan]
+^^^\0\-date~^   \%[\-show] \%[\-noshow] \%[\-nofile] \%[\-nokeep]
+^^^\0\-from~^
+^^^\s+2\b'\(lt\(bv\(bv\(lk\(bv\(bv\(lb'\s0 \-search~\s+2\b'\(rt\(bv\(bv\(rk\(bv\(bv\(rb'\s0^ pattern
+^^^\0\-subject~^
+^^^\0\-to~^ \%[\-file \%[\-preserve] \%[\-link] \%+folder\ ... \%[\-nopreserve] \%[\-nolink] ]
+^^^\0\-\-component~^ \%[\-keep \%[\-stay] \%[\-nostay] \%[+folder\ ...]\ ]
+.fi
+.fc
+
+.re
+.ti .5i
+typically:
+.in 1i
+pick\0\-from\0jones\0\-scan
+.br
+pick\0\-to\0holloway
+.br
+pick\0\-subject\0ned\0\-scan\0\-keep
+.SH DESCRIPTION
+\fIPick\fR searches messages within a folder for the specified
+contents, then performs several operations on the selected
+messages.
+.PP
+A modified \fIgrep\fR(I) is used to perform the searching, so the
+full regular expression (see \fIed\fR(I)) facility is available
+within `pattern'.
+With `\-search', pattern is used directly,
+and with the others, the grep pattern constructed is:
+.nf
+
+.ti +.5i
+\*(lq^component:\*.\*(**pattern\*(rq
+
+.fi
+This means that the pattern specified for a `\-search' will be
+found everywhere in the message, including the header and the body,
+while the other search requests are limited to the single
+specified component.
+The expression `\-\-component pattern'
+is a shorthand for
+specifying `\-search \*(lqcomponent:\*.\*(**pattern\*(rq\ '; it is used to pick
+a component not in the set [cc date from subject to].
+An
+example is \*(lqpick \-\-reply\-to pooh \-show\*(rq.
+.PP
+Searching is performed on a per-line basis.
+Within the header of
+the message, each component is treated as one long line, but in
+the body, each line is separate.
+Lower-case letters in the
+search pattern will match either lower or upper case in the
+message, while upper case will match only upper case.
+.PP
+Once the search has been performed, the selected messages
+are scanned (see \fIscan\fR) if the `\-scan' switch is given, and
+then they are shown (see \fIshow\fR) if the `\-show' switch is
+given.
+After these two operations, the file operations (if
+requested) are performed.
+.PP
+The `\-file' switch operates exactly like the \fIfile\fR command, with the
+same meaning for the `\-preserve' and `\-link' switches.
+.PP
+The `\-keep' switch is similar to `\-file', but it produces a folder that
+is a subfolder of the folder being searched and defines it as
+the current folder (unless the `\-stay' flag is used).
+This
+subfolder contains the messages which matched the search
+criteria.
+All of the MH commands may be used with the sub-folder
+as the current folder.
+This gives the user considerable power
+in dealing with subsets of messages in a folder.
+.PP
+The messages in a folder produced by `\-keep' will always have the
+same numbers as they have in the source folder (i.e., the
+`\-preserve' switch is automatic).
+This way, the message
+numbers are consistent with the folder from which the messages
+were selected.
+Messages are not removed from the source folder
+(i.e., the `\-link' switch is assumed).
+If a `+folder' is not
+specified, the standard name \*(lqselect\*(rq will be used.
+(This is the
+meaning of \*(lq(select)\*(rq when it appears in the output of the
+\fIfolder\fR command.) If `+folder' arguments are given to
+`\-keep', they will be used rather than \*(lqselect\*(rq for the names
+of the subfolders.
+This allows for several subfolders to be
+maintained concurrently.
+.PP
+When a `\-keep' is performed, the subfolder becomes the current folder.
+This can be overridden by use
+of the `\-stay' switch.
+.PP
+Here's an example:
+
+.nf
+\01  % folder +inbox
+\02           inbox+ has  16 messages (  3\- 22); cur=  3.
+\03  % pick \-from dcrocker
+\04  6 hits.
+\05  [+inbox/select now current]
+\06  % folder
+\07    inbox/select+ has  \06 messages (  3\- 16); cur=  3.
+\08  % scan
+.ds p \\h'\\w'+'u'
+\09   \03+  6/20   Dcrocker          Re: ned file update issue...
+10   \06\*p  6/23   Dcrocker          removal of files from /tm...
+11   \08\*p  6/27   Dcrocker          Problems with the new ned...
+12   13\*p  6/28   d\h'\w'D'u-\w'd'u'crocker          newest nned  \*(<<I would ap...
+13   15\*p  7/\05   Dcrocker          nned  \*(<<Last week I asked...
+14   16\*p  7/\05   d\h'\w'D'u-\w'd'u'crocker          message id format  \*(<<I re...
+15  % show all | print
+16     [produce a full listing of this set of messages on the line printer.]
+17  % folder \-up
+18            inbox+ has  16 messages (  3\- 22); cur=  3; (select).
+19  % folder \-down
+20   inbox/select+ has   6 messages (  3\- 16); cur=  3.
+21  % rmf
+22  [+inbox now current]
+23  % folder
+24            inbox+ has  16 messages (  3\- 22); cur=  3.
+.fi
+
+This is a rather lengthy example, but it shows the power of the
+MH package.
+In item 1, the current folder is set to inbox.
+In 3,
+all of the messages from dcrocker are found in inbox and linked
+into the folder \*(lqinbox/select\*(rq.
+(Since no action switch is
+specified, `\-keep' is assumed.)  Items 6 and 7 show that this
+subfolder is now the current folder.
+Items 8 through 14 are a
+\fIscan\fR of the selected messages (note that they are all from dcrocker
+and are all in upper and lower case).
+Item 15 lists all of the messages to
+the high-speed printer.
+Item 17 directs \fIfolder\fR to set the
+current folder to the parent of the selection-list folder, which
+is now current.
+Item 18 shows that this has been done.
+Item 19 resets
+the current folder to the selection list, and 21 removes the
+selection-list folder and resets the current folder to the
+parent folder, as shown in 22 and 23.
+.SH FILES
+.nf
+.ta \w'$HOME/\*.mh\(ruprofile    'u
+$HOME/\*.mh\(ruprofile The user profile
+.fi
+.SH "PROFILE COMPONENTS"
+.nf
+.ta \w'Current-Folder:    'u
+Path:  To determine the user's MH directory
+Folder\-Protect:       For protection on new folders
+Current-Folder:        To find the default current folder
+.fi
+.SH DEFAULTS
+.nf
+`\-src +folder' defaults to current
+`msgs' defaults to all
+`\-keep +select' is the default if no `\-scan', `\-show', or `\-file' is specified
+.fi
+.SH CONTEXT
+If a `\-src +folder' is specified, it will
+become the current folder, unless a `\-keep' with 0 or 1
+folder arguments makes the selection-list subfolder the
+current folder.
+Each selection-list folder will have its
+current message set to the first of the messages linked into
+it unless the selection list already existed, in which case the
+current message won't be changed.
diff --git a/docs/historical/2.9BSD/man/prev.1 b/docs/historical/2.9BSD/man/prev.1
new file mode 100644 (file)
index 0000000..f29df30
--- /dev/null
@@ -0,0 +1,29 @@
+.TH PREV 1 "3 August 1983"
+.UC 4
+.SH NAME
+prev \- show the previous message
+.SH SYNOPSIS
+.B prev
+[ +folder ] [ \-switches for \fIl\fR ] [ \-help ]
+.SH DESCRIPTION
+\fIPrev\fR performs a \fIshow\fR on the previous message in the specified
+(or current) folder.
+Like \fIshow\fR, it passes any switches on to the
+program \fIl\fR, which is called to list the message.
+This command
+is exactly equivalent to \*(lqshow prev\*(rq.
+.SH FILES
+.nf
+.ta \w'$HOME/\*.mh\(ruprofile    'u
+$HOME/\*.mh\(ruprofile The user profile
+.fi
+.SH "PROFILE COMPONENTS"
+.nf
+.ta \w'Current-Folder:    'u
+Path:  To determine the user's MH directory
+Current-Folder:        To find the default current folder
+.fi
+.SH CONTEXT
+If a folder is specified, it will become current, and the
+message that is shown (i.e., the previous message in sequence)
+will become the current message.
diff --git a/docs/historical/2.9BSD/man/print b/docs/historical/2.9BSD/man/print
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/docs/historical/2.9BSD/man/prompter.1 b/docs/historical/2.9BSD/man/prompter.1
new file mode 100644 (file)
index 0000000..16569d8
--- /dev/null
@@ -0,0 +1,64 @@
+.TH PROMPTER 1 "3 August 1983"
+.UC 4
+.SH NAME
+prompter \- prompting editor front end
+.SH SYNOPSIS
+.B prompter
+[ \-erase chr ] [ \-kill chr ] [ \-help ]
+.SH DESCRIPTION
+This program is not called directly but takes the place
+of an editor and acts as an editor front end.
+\fIPrompter\fR is an editor which allows rapid composition of
+messages.
+It is particularly useful to network and low-speed
+(less than 2400 baud) users of MH.
+It is an MH program in that
+it can have its own profile entry with switches, but it can't
+be invoked directly as all other MH commands can; it is an editor
+in that it is invoked by an \*(lq\-editor prompter\*(rq switch or by the
+profile entry \*(lqEditor: prompter\*(rq, but functionally it is merely
+a text-collector and not a true editor.
+.PP
+\fIPrompter\fR expects to be called from \fIcomp\fR, \fIrepl\fR, \fIdist\fR, or
+\fIforw\fR, with a draft file as an argument.
+For example, \*(lqcomp
+\-editor prompter\*(rq will call \fIprompter\fR with the file \*(lqdraft\*(rq already set
+up with blank components.
+For each blank component it finds in
+the draft, it prompts the user and accepts a response.
+A <RETURN> will cause the whole component to be left out.
+A \*(lq\\\*(rq
+preceding a <RETURN> will continue the response on the next line,
+allowing for multiline components.
+.PP
+Any component that is non-blank will be copied and echoed to the
+terminal.
+.PP
+The start of the message body is prompted by a line of
+dashes.
+If the body is non-blank, the prompt is
+\*(lq--------Enter additional text\*(rq.
+Message-body typing is terminated with
+a <CTRL-D> (or <OPEN>).
+Control is returned to the calling
+program, where the user is asked \*(lqWhat now?\*(rq.
+See \fIcomp\fR for
+the valid options.
+.PP
+The line editing characters for kill and erase may be
+specified by the user via the arguments \*(lq\-kill chr\*(rq and \*(lq\-erase
+chr\*(rq, where chr may be a character; or \*(lq\\nnn\*(rq, where nnn is the
+octal value for the character.
+(Again, these may come from the
+default switches specified in the user's profile.)
+.PP
+A <DEL> during message-body typing is equivalent to
+<CTRL-D> for compatibility with NED.
+A <DEL> during
+component typing will abort the command that invoked
+\fIprompter\fR.
+.SH "PROFILE COMPONENTS"
+.nf
+.ta \w'prompter-next:    'u
+prompter-next: editor to be used on exit from \fIprompter\fR
+.fi
diff --git a/docs/historical/2.9BSD/man/repl.1 b/docs/historical/2.9BSD/man/repl.1
new file mode 100644 (file)
index 0000000..50f98c3
--- /dev/null
@@ -0,0 +1,81 @@
+.TH REPL 1 "3 August 1983"
+.UC 4
+.SH NAME
+repl \- reply to a message
+.SH SYNOPSIS
+.B repl
+[ +folder ] [ msg ] [ \-editor editor ] [ \-inplace ] [ \-annotate ]
+[ \-help ] [ \-noinplace ] [ \-noannotate ]
+.SH DESCRIPTION
+\fIRepl\fR aids a user in producing a reply to an existing
+message.
+In its simplest form (with no arguments), it will set up
+a message-form skeleton in reply to the current message in the
+current folder, invoke the editor, and send the composed
+message if so directed.
+The composed message is constructed as
+follows:
+.nf
+
+.in 1i
+To: <Reply-To> or <From>
+cc: <cc>, <To>
+Subject: Re: <Subject>
+In-reply-to: Your message of <Date>
+.ti +\w'In-reply-to: 'u
+<Message-Id>
+.in .5i
+
+.fi
+where field names enclosed in angle brackets (< >) indicate the
+contents of the named field from the message to which the reply
+is being made.
+Once the skeleton is constructed, an editor is
+invoked (as in \fIcomp\fR, \fIdist\fR, and \fIforw\fR).
+While in the editor,
+the message being replied to is available through a link named
+\*(lq@\*(rq.
+In NED, this means the replied-to message may be \*(lqused\*(rq
+with \*(lquse @\*(rq, or put in a window by \*(lqwindow @\*(rq.
+.PP
+As in \fIcomp\fR, \fIdist\fR, and \fIforw\fR, the user will be queried
+before the message is sent.
+If `\-annotate' is
+specified, the replied-to message will be annotated with the
+single line
+.nf
+
+.ti +.5i
+Replied: \*(<<Date\*(>>.
+
+.fi
+The command
+\*(lqcomp \-use\*(rq may be used to pick up interrupted editing, as in
+\fIdist\fR and \fIforw\fR; the `\-inplace' switch annotates the message in
+place, so that all folders with links to it will see the annotation.
+.SH FILES
+.nf
+.ta \w'$HOME/\*.mh\(ruprofile    'u
+$HOME/\*.mh\(ruprofile The user profile
+<mh-dir>/draft The constructed message file
+/usr/bin/send  To send the composed message
+.fi
+.SH "PROFILE COMPONENTS"
+.nf
+.ta \w'Current-Folder:    'u
+Path:  To determine the user's MH directory
+Editor:        To override the use of /bin/ned as the default editor
+Current-Folder:        To find the default current folder
+.fi
+.SH DEFAULTS
+.nf
+`+folder' defaults to current
+`msgs' defaults to cur
+`\-editor' defaults to /bin/ned
+`\-noannotate'
+`\-noinplace'
+.fi
+.SH CONTEXT
+If a `+folder' is specified, it will become the current
+folder, and the current message will be set to the replied-to
+message.
diff --git a/docs/historical/2.9BSD/man/rmf.1 b/docs/historical/2.9BSD/man/rmf.1
new file mode 100644 (file)
index 0000000..9dfeecc
--- /dev/null
@@ -0,0 +1,62 @@
+.TH RMF 1 "3 August 1983"
+.UC 4
+.SH NAME
+rmf \- remove folder
+.SH SYNOPSIS
+.B rmf
+[ +folder ] [ \-help ]
+.SH DESCRIPTION
+\fIRmf\fR removes all of the files (messages) within the specified
+(or default) folder, and then removes the directory (folder).
+If
+there are any files within the folder which are not a part of MH,
+they will \fInot\fR be removed, and an error will be produced.
+If the
+folder is given explicitly or the current folder is a
+subfolder (i.e., a selection list from \fIpick\fR), it will be
+removed without confirmation.
+If no argument is specified and
+the current folder is not a selection-list folder, the
+user will be asked for confirmation.
+.PP
+\fIRmf\fR irreversibly deletes messages that don't have other links,
+so use it with caution.
+.PP
+If the folder being removed is a subfolder, the parent
+folder will become the new current folder, and \fIrmf\fR will
+produce a message telling the user this has happened.
+This
+provides an easy mechanism for selecting a set of messages,
+operating on the list, then removing the list and returning to
+the current folder from which the list was extracted.
+(See the
+example under \fIpick\fR.)
+.PP
+The files that \fIrmf\fR will delete are cur, any file beginning
+with a comma, and files with purely numeric names.
+All others
+will produce error messages.
+.PP
+\fIRmf\fR of a read-only folder will delete the \*(lqcur\-\*(rq entry from the
+profile without affecting the folder itself.
+.SH FILES
+.nf
+.ta \w'or <mh-dir>/components    'u
+.fi
+.SH "PROFILE COMPONENTS"
+.nf
+.ta \w'$HOME/\*.mh\(ruprofile    'u
+$HOME/\*.mh\(ruprofile The user profile
+Path:  To determine the user's MH directory
+Current-Folder:        To find the default current folder
+.fi
+.SH DEFAULTS
+.nf
+`+folder' defaults to current, usually with confirmation
+.fi
+.SH CONTEXT
+\fIRmf\fR will set the current folder to the parent folder if a
+subfolder is removed; or if the current folder is removed,
+it will make \*(lqinbox\*(rq current.
+Otherwise, it doesn't change the
+current folder or message.
diff --git a/docs/historical/2.9BSD/man/rmm.1 b/docs/historical/2.9BSD/man/rmm.1
new file mode 100644 (file)
index 0000000..35c07c1
--- /dev/null
@@ -0,0 +1,32 @@
+.TH RMM 1 "3 August 1983"
+.UC 4
+.SH NAME
+rmm \- remove messages
+.SH SYNOPSIS
+.B rmm
+[ +folder ] [ msgs ] [ \-help ]
+.SH DESCRIPTION
+\fIRmm\fR removes the specified messages by renaming the message
+files with preceding commas.
+(This is the Rand-UNIX backup file convention.)
+.PP
+The current message is not changed by \fIrmm\fR, so a \fInext\fR  will
+advance to the next message in the folder as expected.
+.SH FILES
+.nf
+.ta \w'$HOME/\*.mh\(ruprofile    'u
+$HOME/\*.mh\(ruprofile The user profile
+.fi
+.SH "PROFILE COMPONENTS"
+.nf
+.ta \w'Current-Folder:    'u
+Path:  To determine the user's MH directory
+Current-Folder:        To find the default current folder
+.fi
+.SH DEFAULTS
+.nf
+`+folder' defaults to current
+`msgs' defaults to cur
+.fi
+.SH CONTEXT
+If a folder is given, it will become current.
diff --git a/docs/historical/2.9BSD/man/scan.1 b/docs/historical/2.9BSD/man/scan.1
new file mode 100644 (file)
index 0000000..4216108
--- /dev/null
@@ -0,0 +1,64 @@
+.SC SCAN
+.TH SCAN 1 "3 August 1983"
+.UC 4
+.SH NAME
+scan \- produce a one-line-per-message scan listing
+.SH SYNOPSIS
+.B scan
+[ +folder ] [ msgs ] [ \-ff ] [ \-header ] [ \-help ]
+[ \-noff ] [ \-noheader ]
+.SH DESCRIPTION
+\fIScan\fR produces a one-line-per-message listing of the specified
+messages.
+Each \fIscan\fR line contains the message number (name),
+the date, the \*(lqFrom\*(rq field, the \*(lqSubject\*(rq field, and, if room
+allows, some of the body of the message.
+For example:
+.nf
+
+.ta .5i 1.2i 2.6i
+^ #~^^Date~^^  From~^Subject\ \ \ \ \[\*(<<Body]
+^15+~^^7/\05~^^Dcrocker~^nned  \*(<<Last week I asked some of
+^16\ \-~^^7/\05~^^dcrocker~^message id format  \*(<<I recommend
+^18~^^7/\06~^^Obrien~^Re: Exit status from mkdir
+^19~^^7/\07~^^Obrien~^"scan" listing format in MH
+.re
+
+.fi
+The `+' on message 15 indicates that it is the current message.
+The `\-' on message 16 indicates that it has been
+replied to, as indicated by a \*(lqReplied:\*(rq component produced by
+an `\-annotate' switch to the \fIrepl\fR command.
+.PP
+If there is sufficient room left on the \fIscan\fR line after the
+subject, the line will be filled with text from the body,
+preceded by \*(<<.
+\fIScan\fR actually reads each of the specified
+messages and parses them to extract the desired fields.
+During parsing, appropriate error messages will be produced if
+there are format errors in any of the messages.
+.PP
+The `\-header' switch produces a header line prior to the \fIscan\fR
+listing, and the `\-f\&f' switch will cause a form feed to be
+output at the end of the \fIscan\fR listing.
+.SH FILES
+.nf
+.ta \w'$HOME/\*.mh\(ruprofile    'u
+^$HOME/\*.mh\(ruprofile~^The user profile
+.fi
+.SH "PROFILE COMPONENTS"
+.nf
+.ta \w'Current-Folder:    'u
+Path:  To determine the user's MH directory
+Current-Folder:        To find the default current folder
+.fi
+.SH DEFAULTS
+.nf
+`+folder' defaults to current
+`msgs' defaults to all
+`\-nof\&f'
+`\-noheader'
+.fi
+.SH CONTEXT
+If a folder is given, it will become current.
+The current message is unaffected.
diff --git a/docs/historical/2.9BSD/man/send.1 b/docs/historical/2.9BSD/man/send.1
new file mode 100644 (file)
index 0000000..753413b
--- /dev/null
@@ -0,0 +1,76 @@
+.SC SEND
+.TH SEND 1 "3 August 1983"
+.UC 4
+.SH NAME
+send \- send a message
+.SH SYNOPSIS
+.B send
+[ file ] [ \-draft ] [ \-verbose ] [ \-format ] [ \-msgid ]
+[ \-help ]  [ \-noverbose ] [ \-noformat ] [ \-nomsgid ]
+.SH DESCRIPTION
+\fISend\fR will cause the specified file (default <mh-dir>/draft) to
+be delivered to each of the addresses in the \*(lqTo:\*(rq, \*(lqcc:\*(rq, and \*(lqBcc:\*(rq
+fields of the message.
+If `\-verbose' is specified, \fIsend;\fR
+will monitor the delivery of local and net mail.
+\fISend\fR with no
+argument will query whether the draft is the intended file, whereas
+`\-draft' will suppress this question.
+Once the message has
+been mailed (or queued) successfully, the file will be renamed
+with a leading comma, which allows it to be retreived until the
+next draft message is sent.
+If there are errors in the
+formatting of the message, \fIsend;\fR will abort with a (hopefully)
+helpful error message.
+.PP
+If a \*(lqBcc:\*(rq field is encountered, its addresses will be used for
+delivery, but the \*(lqBcc:\*(rq field itself will be deleted from all
+copies of the outgoing message.
+.PP
+Prior to sending the message, the fields \*(lqFrom:  user\*(rq, and
+\*(lqDate: now\*(rq will be prepended to the message.
+If `\-msgid' is
+specified, then a \*(lqMessage-Id:\*(rq field will also be added to the
+message.
+If the message already contains a \*(lqFrom:\*(rq field, then a
+\*(lqSender: user\*(rq field will be added instead.
+(An already existing
+\*(lqSender:\*(rq field will be deleted from the message.)
+.PP
+If the user doesn't specify `\-noformat', each of the entries in
+the \*(lqTo:\*(rq and \*(lqcc:\*(rq fields will be replaced with \*(lqstandard\*(rq format
+entries.
+This standard format is designed to be usable by all
+of the message handlers on the various systems around the
+ARPANET.
+.PP
+If an \*(lqFcc: folder\*(rq is encountered, the message will be copied
+to the specified folder in the format in which it will appear to any
+receivers of the message.
+That is, it will have the prepended
+fields and field reformatting.
+.PP
+If a \*(lqDistribute-To:\*(rq field is encountered, the message
+is handled as a redistribution message (see \fIdist\fR for
+details), with \*(lqDistribution-Date: now\*(rq and \*(lqDistribution-From: user\*(rq
+added.
+.SH FILES
+.nf
+.ta \w'$HOME/\*.mh\(ruprofile    'u
+$HOME/\*.mh\(ruprofile The user profile
+.fi
+.SH "PROFILE COMPONENTS"
+.nf
+.ta \w'Path:    'u
+Path:  To determine the user's MH directory
+.fi
+.SH DEFAULTS
+.nf
+`file' defaults to draft
+`\-noverbose'
+`\-format'
+`\-nomsgid'
+.fi
+.SH CONTEXT
+\fISend\fR has no effect on the current message or folder.
diff --git a/docs/historical/2.9BSD/man/show.1 b/docs/historical/2.9BSD/man/show.1
new file mode 100644 (file)
index 0000000..abbea1a
--- /dev/null
@@ -0,0 +1,64 @@
+.TH SHOW 1 "3 August 1983"
+.UC 4
+.SH NAME
+show \- show (list) messages
+.SH SYNOPSIS
+.B show
+[ +folder ] [ msgs ] [ \-pr ] [ \-nopr ] [ \-draft ] [ \-help ]
+[ \fIl\fR or \fIpr\fR switches ]
+.SH DESCRIPTION
+\fIShow\fR lists each of the specified messages to the standard
+output (typically, the terminal).
+The messages are listed exactly
+as they are, with no reformatting.
+A program called \fIl\fR is
+invoked to do the listing, and any switches not recognized by
+\fIshow\fR are passed along to \fIl\fR.
+.PP
+If no \*(lqmsgs\*(rq are specified, the current message is used.
+If
+more than one message is specified, \fIl\fR will prompt for a
+<return> prior to listing each message.
+.PP
+\fIl\fR will list each message, a page at a time.
+When the end of
+page is reached, \fIl\fR will ring the bell and wait for a <RETURN>
+or <CTRL-D>.
+If a <return> is entered, \fIl\fR will clear the
+screen before listing the next page, whereas <CTRL-D> will not.
+The switches to \fIl\fR are
+`\-p#' to indicate the page length in lines, and `\-w#' to
+indicate the width of the page in characters.
+.PP
+If the standard output is not a terminal, no queries are made,
+and each file is listed with a one-line header and two lines of
+separation.
+.PP
+If `\-pr' is specified, then \fIpr\fR(I) will be invoked rather than
+\fIl\fR, and the switches (other than `\-draft') will be passed
+along.
+\*(lqShow \-draft\*(rq will list the file <mh-dir>/draft if it
+exists.
+.SH FILES
+.nf
+.ta \w'$HOME/\*.mh\(ruprofile    'u
+$HOME/\*.mh\(ruprofile The user profile
+/bin/l Screen-at-a-time list program
+/bin/pr        \fIpr\fR(1)
+.fi
+.SH "PROFILE COMPONENTS"
+.nf
+.ta \w'Current-Folder:    'u
+Path:  To determine the user's MH directory
+Current-Folder:        To find the default current folder
+.fi
+.SH DEFAULTS
+.nf
+`+folder' defaults to current
+`msgs' defaults to cur
+`\-nopr'
+.fi
+.SH CONTEXT
+If a folder is given, it will become the current message.
+The last message
+listed will become the current message.
diff --git a/docs/historical/2.9BSD/strings/Mailprog.c b/docs/historical/2.9BSD/strings/Mailprog.c
new file mode 100644 (file)
index 0000000..fe8edb3
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ * This is the program called to deliver mail
+ * on systems where we try to maintain compatibility
+ * with the standard message format.
+ */
+
+char   *Mailprog = "/usr/ucb/Mail";
diff --git a/docs/historical/2.9BSD/strings/Makefile b/docs/historical/2.9BSD/strings/Makefile
new file mode 100644 (file)
index 0000000..eef5784
--- /dev/null
@@ -0,0 +1,38 @@
+CC = cc -I../cmds
+CFLAGS=-O
+
+strings.a: anoyes.o        \
+          components.o    \
+          current.o       \
+          defalt.o        \
+          distcomps.o     \
+          draft.o         \
+          fileproc.o      \
+          foldprot.o      \
+          hostname.o      \
+          installproc.o   \
+          listname.o      \
+          lockdir.o       \
+          lsproc.o        \
+          mailboxes.o     \
+          mailproc.o      \
+          mh_deliver.o    \
+          mh_prof.o       \
+          mhnews.o        \
+          msgprot.o       \
+          pfolder.o       \
+          prproc.o        \
+          scanproc.o      \
+          sendproc.o      \
+          showproc.o      \
+          stdcomps.o      \
+          stddcomps.o     \
+          sysed.o         \
+          Mailprog.o      \
+          unixtomh.o      \
+          localname.o
+
+       ar cr strings.a *.o
+
+clean:
+       rm -f *.o strings.a
diff --git a/docs/historical/2.9BSD/strings/anoyes.c b/docs/historical/2.9BSD/strings/anoyes.c
new file mode 100644 (file)
index 0000000..eb842c9
--- /dev/null
@@ -0,0 +1,5 @@
+char *anoyes[] = {
+       "no",   0,
+       "yes",  0,
+       0,
+};
diff --git a/docs/historical/2.9BSD/strings/components.c b/docs/historical/2.9BSD/strings/components.c
new file mode 100644 (file)
index 0000000..ffd97cb
--- /dev/null
@@ -0,0 +1 @@
+char    *components =   "components";
diff --git a/docs/historical/2.9BSD/strings/current.c b/docs/historical/2.9BSD/strings/current.c
new file mode 100644 (file)
index 0000000..86ea368
--- /dev/null
@@ -0,0 +1 @@
+char    *current =      "cur";
diff --git a/docs/historical/2.9BSD/strings/defalt.c b/docs/historical/2.9BSD/strings/defalt.c
new file mode 100644 (file)
index 0000000..ab3a012
--- /dev/null
@@ -0,0 +1 @@
+char    *defalt =       "inbox";
diff --git a/docs/historical/2.9BSD/strings/distcomps.c b/docs/historical/2.9BSD/strings/distcomps.c
new file mode 100644 (file)
index 0000000..acd7eb7
--- /dev/null
@@ -0,0 +1 @@
+char    *distcomps =    "distcomps";
diff --git a/docs/historical/2.9BSD/strings/draft.c b/docs/historical/2.9BSD/strings/draft.c
new file mode 100644 (file)
index 0000000..0e25051
--- /dev/null
@@ -0,0 +1 @@
+char    *draft =        "draft";
diff --git a/docs/historical/2.9BSD/strings/fileproc.c b/docs/historical/2.9BSD/strings/fileproc.c
new file mode 100644 (file)
index 0000000..56626c7
--- /dev/null
@@ -0,0 +1,6 @@
+/*
+ * This program is usually called directly by users, but it is
+ * also invoked by the deliver program to process an "fcc".
+ */
+
+char    *fileproc =     "/usr/new/mh/refile";
diff --git a/docs/historical/2.9BSD/strings/foldprot.c b/docs/historical/2.9BSD/strings/foldprot.c
new file mode 100644 (file)
index 0000000..8769a27
--- /dev/null
@@ -0,0 +1,5 @@
+/*
+ * Folders (directories) are created with this protection (mode)
+ */
+
+char    *foldprot =     "0751";
diff --git a/docs/historical/2.9BSD/strings/hostname.c b/docs/historical/2.9BSD/strings/hostname.c
new file mode 100644 (file)
index 0000000..64278d6
--- /dev/null
@@ -0,0 +1,6 @@
+/*
+ * For ARPANET mail, this is the local-site's Host name.
+ *   (currently not used.)
+ */
+
+char    *hostname =     "Berkeley";
diff --git a/docs/historical/2.9BSD/strings/installproc.c b/docs/historical/2.9BSD/strings/installproc.c
new file mode 100644 (file)
index 0000000..38814e7
--- /dev/null
@@ -0,0 +1,6 @@
+/*
+ * When a user runs an MH program for the first time, this program
+ * is called to create his MH profile, and mail directory.
+ */
+
+char    *installproc =  "/usr/new/lib/mh/install-mh";
diff --git a/docs/historical/2.9BSD/strings/listname.c b/docs/historical/2.9BSD/strings/listname.c
new file mode 100644 (file)
index 0000000..af8a882
--- /dev/null
@@ -0,0 +1 @@
+char    *listname =     "select";
diff --git a/docs/historical/2.9BSD/strings/localname.c b/docs/historical/2.9BSD/strings/localname.c
new file mode 100644 (file)
index 0000000..8d22edf
--- /dev/null
@@ -0,0 +1,5 @@
+/*
+ * Local network host name
+ */
+
+char *localname = "unknown";
diff --git a/docs/historical/2.9BSD/strings/lockdir.c b/docs/historical/2.9BSD/strings/lockdir.c
new file mode 100644 (file)
index 0000000..e349552
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * This is where the lock files are kept.  It MUST be on the same
+ * file system as the "mailboxes" directory.  It also must be read/
+ * write by the world.  When a mailbox needs locking (while being
+ * read and cleared by inc, or written by deliver), a link to the
+ * mailbox is made in this directory, under the same name (i.e., the
+ * users name).  Links are one of the few things even a privileged
+ * process (deliver) cannot over-ride.  The deliver process waits
+ * for lockwait seconds for the lock to clear, then it over-rides
+ * the lock.  This number should be set around 15-30 seconds in the
+ * case of a VERY loaded system.
+ */
+
+char    *lockdir =      "/usr/spool/locks/";
+int     lockwait =      15;                     /* Seconds */
diff --git a/docs/historical/2.9BSD/strings/lsproc.c b/docs/historical/2.9BSD/strings/lsproc.c
new file mode 100644 (file)
index 0000000..c926d79
--- /dev/null
@@ -0,0 +1,9 @@
+/*
+ * This is standard ls, but "folder -all -short" calls it with
+ * a -x switch meaning "list only directories".
+ *
+ * Also, its nice to have columnated output rather than a simple
+ * list... (personal prejudice).
+ */
+
+char    *lsproc =       "/bin/ls";
diff --git a/docs/historical/2.9BSD/strings/mailboxes.c b/docs/historical/2.9BSD/strings/mailboxes.c
new file mode 100644 (file)
index 0000000..b9c56b9
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ * This is where the user mailboxes are kept.  On our 11/70 they were
+ * kept in each users $HOME directory.  This is where the VAX login
+ * program is looking for them, as well as the old BELL mail.
+ */
+
+char    *mailboxes =      "/usr/spool/mail/";
diff --git a/docs/historical/2.9BSD/strings/mailproc.c b/docs/historical/2.9BSD/strings/mailproc.c
new file mode 100644 (file)
index 0000000..b702076
--- /dev/null
@@ -0,0 +1,6 @@
+/*
+ * This is the path for the Bell equivalent mail program... Used
+ *  by "news -send" to send news items to the news user.
+ */
+
+char    *mailproc =     "/bin/mail";
diff --git a/docs/historical/2.9BSD/strings/mh_defs.c b/docs/historical/2.9BSD/strings/mh_defs.c
new file mode 100644 (file)
index 0000000..fa86e65
--- /dev/null
@@ -0,0 +1,6 @@
+/*
+ * This is the name of the file used to store
+ * the user's MH profile
+ */
+
+char   *mh_defs = "/.mh_profile";
diff --git a/docs/historical/2.9BSD/strings/mh_deliver.c b/docs/historical/2.9BSD/strings/mh_deliver.c
new file mode 100644 (file)
index 0000000..601d614
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ * This is the delivery program called ONLY through send to
+ * actually deliver mail to users.  It is fairly small, and
+ * must run SUID ROOT, to create new mailboxes.
+ */
+
+char    *mh_deliver = "/usr/new/lib/mh/deliver";
diff --git a/docs/historical/2.9BSD/strings/mh_prof.c b/docs/historical/2.9BSD/strings/mh_prof.c
new file mode 100644 (file)
index 0000000..db3cc3a
--- /dev/null
@@ -0,0 +1 @@
+char    *mh_prof =      "/.mh_profile";
diff --git a/docs/historical/2.9BSD/strings/mhnews.c b/docs/historical/2.9BSD/strings/mhnews.c
new file mode 100644 (file)
index 0000000..098e8f4
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ * This program is called to print out MH news IF NEWS is defined
+ * when the MH programs are compiled.  This whole mechanism has not
+ * been tested under version 7!
+ */
+
+char    *mhnews =       "/usr/new/mh/news";
diff --git a/docs/historical/2.9BSD/strings/msgprot.c b/docs/historical/2.9BSD/strings/msgprot.c
new file mode 100644 (file)
index 0000000..65f1ff0
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ * Every NEW message will be created with this protection.  When a
+ * message is filed it retains its protection, so this only applies
+ * to messages coming in through inc.
+ */
+
+char    *msgprot =      "0664";
diff --git a/docs/historical/2.9BSD/strings/pfolder.c b/docs/historical/2.9BSD/strings/pfolder.c
new file mode 100644 (file)
index 0000000..209c7ee
--- /dev/null
@@ -0,0 +1 @@
+char    *pfolder =      "current-folder";
diff --git a/docs/historical/2.9BSD/strings/prproc.c b/docs/historical/2.9BSD/strings/prproc.c
new file mode 100644 (file)
index 0000000..4417a45
--- /dev/null
@@ -0,0 +1,6 @@
+/*
+ * This is the std BELL pr, which is invoked through show with the
+ * -pr switch.
+ */
+
+char    *prproc =       "/bin/pr";
diff --git a/docs/historical/2.9BSD/strings/scanproc.c b/docs/historical/2.9BSD/strings/scanproc.c
new file mode 100644 (file)
index 0000000..0bb22ea
--- /dev/null
@@ -0,0 +1,6 @@
+/*
+ * This program is usually called directly by users, but it is
+ * also invoked by "pick -scan".
+ */
+
+char    *scanproc =     "/usr/new/mh/scan";
diff --git a/docs/historical/2.9BSD/strings/sendproc.c b/docs/historical/2.9BSD/strings/sendproc.c
new file mode 100644 (file)
index 0000000..82baf79
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ * This program is usually called by one of the message composition
+ * programs: comp, repl, dist, and forw, but it may also be called
+ * directly to send a message previously composed.
+ */
+
+char    *sendproc =     "/usr/new/mh/send";
diff --git a/docs/historical/2.9BSD/strings/showproc.c b/docs/historical/2.9BSD/strings/showproc.c
new file mode 100644 (file)
index 0000000..4bd7c6d
--- /dev/null
@@ -0,0 +1,9 @@
+/*
+ * This program is called to list messages.  At Rand, the program
+ * c stops at the end of each page and waits for a <return> or
+ * <open> to continue.  Eventually, this path should invoke a
+ * special program which displays messages much more intelligently--
+ * such as layed out nicely on the screen.
+ */
+
+char    *showproc =     "/usr/ucb/more";                       /* 5/6/79 */
diff --git a/docs/historical/2.9BSD/strings/stdcomps.c b/docs/historical/2.9BSD/strings/stdcomps.c
new file mode 100644 (file)
index 0000000..5329fbe
--- /dev/null
@@ -0,0 +1,6 @@
+/*
+ * This is the standard skeleton for message composition with both
+ * comp and forw.
+ */
+
+char    *stdcomps =     "/usr/new/lib/mh/components";
diff --git a/docs/historical/2.9BSD/strings/stddcomps.c b/docs/historical/2.9BSD/strings/stddcomps.c
new file mode 100644 (file)
index 0000000..0e3fa76
--- /dev/null
@@ -0,0 +1,5 @@
+/*
+ * This is the standard skeleton for message composition with dist.
+ */
+
+char    *stddcomps =    "/usr/new/lib/mh/distcomps";
diff --git a/docs/historical/2.9BSD/strings/strings.h b/docs/historical/2.9BSD/strings/strings.h
new file mode 100644 (file)
index 0000000..3ab459c
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * This file gives extern declarations to all the strings
+ * that we might ever reference.
+ *
+ * I don't know if this what strings.h is supposed to be,
+ * but this is as good a first guess as I can handle.
+ */
+
+extern char    *anoyes[];
+extern char    *components;
+extern char    *current;
+extern char    *defalt;
+extern char    *distcomps;
+extern char    *draft;
+extern char    *fileproc;
+extern char    *foldprot;
+extern char    *hostname;
+extern char    *installproc;
+extern char    *listname;
+extern char    *lockdir;
+extern int     lockwait;
+extern char    *lsproc;
+extern char    *mailboxes;
+extern char    *mailproc;
+extern char    *mh_deliver;
+extern char    *mh_prof;
+extern char    *mhnews;
+extern char    *msgprot;
+extern char    *pfolder;
+extern char    *prproc;
+extern char    *scanproc;
+extern char    *sendproc;
+extern char    *showproc;
+extern char    *stdcomps;
+extern char    *stddcomps;
+extern char    *sysed;
diff --git a/docs/historical/2.9BSD/strings/sysed.c b/docs/historical/2.9BSD/strings/sysed.c
new file mode 100644 (file)
index 0000000..fe69d61
--- /dev/null
@@ -0,0 +1,9 @@
+/*
+ * This is the editor invoked by the various message composition
+ * programs.  It SHOULD be a 2-D scope editor, such as Rand's Ned
+ * or Berkeley's ex, but any editor will work.  If you don't have
+ * a scope editor, you might want to default to prompter, but it
+ * works very marginally with forw and dist.
+ */
+
+char    *sysed =        "/bin/ex";
diff --git a/docs/historical/2.9BSD/strings/unixtomh.c b/docs/historical/2.9BSD/strings/unixtomh.c
new file mode 100644 (file)
index 0000000..0d3ce08
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ * This program is called to convert UNIX style
+ * mailboxes to MH style mail boxes, if we are trying
+ * to stay UNIX mailbox compatible.
+ */
+
+char *unixtomh = "/usr/new/lib/mh/unixtomh";
diff --git a/docs/historical/2.9BSD/subs/16158symdef b/docs/historical/2.9BSD/subs/16158symdef
new file mode 100644 (file)
index 0000000..d3bd053
--- /dev/null
@@ -0,0 +1,51 @@
+_add add.o
+_ambigsw ambigsw.o
+_atooi atooi.o
+_brkany brkstring.o
+_brkstri brkstring.o
+_cdate cdate.o
+_cndfree cndfree.o
+_concat concat.o
+_copy copy.o
+_copyip copyip.o
+_cputc cputc.o
+_done done.o
+_fdcompa fdcompare.o
+_gans gans.o
+_g_sig getans.o
+_getans getans.o
+_getcpy getcpy.o
+_help help.o
+_invo_na invo_name.o
+_locv locv.o
+_m_conv m_convert.o
+_m_conve m_convert.o
+_m_delet m_delete.o
+_m_edit m_edit.o
+_m_find m_find.o
+_m_getde m_getdefs.o
+_procs m_getdefs.o
+_m_getfl m_getfld.o
+_m_getfo m_getfolder.o
+_m_gmpro m_gmprot.o
+_m_gmsg m_gmsg.o
+_mu_atoi m_gmsg.o
+_m_maild m_maildir.o
+_m_name m_name.o
+_m_repla m_replace.o
+_m_send m_send.o
+_m_setcu m_setcur.o
+_m_updat m_update.o
+_makedir makedir.o
+_makenam makename.o
+_peekc peekc.o
+_pr_arra pr_array.o
+_printsw printsw.o
+_putdate putdate.o
+_r1binde r1bindex.o
+_showfil showfile.o
+_smatch smatch.o
+_ssequal ssequal.o
+_trimcpy trimcpy.o
+_type type.o
+_uleq uleq.o
diff --git a/docs/historical/2.9BSD/subs/16158symref b/docs/historical/2.9BSD/subs/16158symref
new file mode 100644 (file)
index 0000000..c0c1d2d
--- /dev/null
@@ -0,0 +1,925 @@
+_cndfree add.o
+_malloc add.o
+_sprintf add.o
+_strlen add.o
+cret add.o
+csv add.o
+__iob ambigsw.o
+_fprintf ambigsw.o
+_invo_na ambigsw.o
+_printsw ambigsw.o
+cret ambigsw.o
+csv ambigsw.o
+cret atooi.o
+csv atooi.o
+cret brkstring.o
+csv brkstring.o
+_ctime cdate.o
+cret cdate.o
+csv cdate.o
+_end cndfree.o
+_free cndfree.o
+cret cndfree.o
+csv cndfree.o
+_compone concat.o
+_copy concat.o
+_current concat.o
+_def_fla concat.o
+_defalt concat.o
+_distcom concat.o
+_draft concat.o
+_filepro concat.o
+_foldpro concat.o
+_hostnam concat.o
+_install concat.o
+_listnam concat.o
+_lockdir concat.o
+_lsproc concat.o
+_m_defs concat.o
+_mailbox concat.o
+_malloc concat.o
+_mh_deli concat.o
+_mh_prof concat.o
+_mhnews concat.o
+_msgprot concat.o
+_mypath concat.o
+_pfolder concat.o
+_prproc concat.o
+_scanpro concat.o
+_sendpro concat.o
+_showpro concat.o
+_stdcomp concat.o
+_stddcom concat.o
+_strlen concat.o
+_sysed concat.o
+cret concat.o
+csv concat.o
+cret copy.o
+csv copy.o
+cret copyip.o
+csv copyip.o
+__flsbuf cputc.o
+_done cputc.o
+_perror cputc.o
+cret cputc.o
+csv cputc.o
+_exit done.o
+cret done.o
+csv done.o
+_lseek fdcompare.o
+_read fdcompare.o
+cret fdcompare.o
+csv fdcompare.o
+__filbuf gans.o
+__iob gans.o
+_compone gans.o
+_current gans.o
+_def_fla gans.o
+_defalt gans.o
+_distcom gans.o
+_draft gans.o
+_fflush gans.o
+_filepro gans.o
+_foldpro gans.o
+_hostnam gans.o
+_install gans.o
+_listnam gans.o
+_lockdir gans.o
+_lsproc gans.o
+_m_defs gans.o
+_mailbox gans.o
+_mh_deli gans.o
+_mh_prof gans.o
+_mhnews gans.o
+_msgprot gans.o
+_mypath gans.o
+_pfolder gans.o
+_printf gans.o
+_prproc gans.o
+_scanpro gans.o
+_sendpro gans.o
+_showpro gans.o
+_smatch gans.o
+_stdcomp gans.o
+_stddcom gans.o
+_sysed gans.o
+cret gans.o
+csv gans.o
+__filbuf getans.o
+__iob getans.o
+_ambigsw getans.o
+_brkstri getans.o
+_compone getans.o
+_current getans.o
+_def_fla getans.o
+_defalt getans.o
+_distcom getans.o
+_draft getans.o
+_fflush getans.o
+_filepro getans.o
+_foldpro getans.o
+_g_sigin getans.o
+_hostnam getans.o
+_install getans.o
+_listnam getans.o
+_lockdir getans.o
+_lsproc getans.o
+_m_defs getans.o
+_mailbox getans.o
+_mh_deli getans.o
+_mh_prof getans.o
+_mhnews getans.o
+_msgprot getans.o
+_mypath getans.o
+_pfolder getans.o
+_printf getans.o
+_printsw getans.o
+_prproc getans.o
+_scanpro getans.o
+_sendpro getans.o
+_showpro getans.o
+_signal getans.o
+_smatch getans.o
+_stdcomp getans.o
+_stddcom getans.o
+_sysed getans.o
+cret getans.o
+csv getans.o
+_malloc getcpy.o
+_strcpy getcpy.o
+_strlen getcpy.o
+cret getcpy.o
+csv getcpy.o
+_compone help.o
+_current help.o
+_def_fla help.o
+_defalt help.o
+_distcom help.o
+_draft help.o
+_filepro help.o
+_foldpro help.o
+_hostnam help.o
+_install help.o
+_listnam help.o
+_lockdir help.o
+_lsproc help.o
+_m_defs help.o
+_mailbox help.o
+_mh_deli help.o
+_mh_prof help.o
+_mhnews help.o
+_msgprot help.o
+_mypath help.o
+_pfolder help.o
+_printf help.o
+_printsw help.o
+_prproc help.o
+_scanpro help.o
+_sendpro help.o
+_showpro help.o
+_stdcomp help.o
+_stddcom help.o
+_sysed help.o
+cret help.o
+csv help.o
+cret invo_name.o
+csv invo_name.o
+_sprintf locv.o
+cret locv.o
+csv locv.o
+__iob m_convert.o
+_atoi m_convert.o
+_compone m_convert.o
+_convdir m_convert.o
+_current m_convert.o
+_def_fla m_convert.o
+_defalt m_convert.o
+_delimp m_convert.o
+_distcom m_convert.o
+_draft m_convert.o
+_filepro m_convert.o
+_foldpro m_convert.o
+_fprintf m_convert.o
+_hostnam m_convert.o
+_install m_convert.o
+_listnam m_convert.o
+_lockdir m_convert.o
+_lsproc m_convert.o
+_m_defs m_convert.o
+_mailbox m_convert.o
+_mh_deli m_convert.o
+_mh_prof m_convert.o
+_mhnews m_convert.o
+_mp m_convert.o
+_msgprot m_convert.o
+_mypath m_convert.o
+_pfolder m_convert.o
+_prproc m_convert.o
+_scanpro m_convert.o
+_sendpro m_convert.o
+_showpro m_convert.o
+_stdcomp m_convert.o
+_stddcom m_convert.o
+_strcmp m_convert.o
+_sysed m_convert.o
+cret m_convert.o
+csv m_convert.o
+_cndfree m_delete.o
+_compone m_delete.o
+_current m_delete.o
+_def_fla m_delete.o
+_defalt m_delete.o
+_distcom m_delete.o
+_draft m_delete.o
+_filepro m_delete.o
+_foldpro m_delete.o
+_free m_delete.o
+_hostnam m_delete.o
+_install m_delete.o
+_listnam m_delete.o
+_lockdir m_delete.o
+_lsproc m_delete.o
+_m_defs m_delete.o
+_m_getde m_delete.o
+_mailbox m_delete.o
+_mh_deli m_delete.o
+_mh_prof m_delete.o
+_mhnews m_delete.o
+_msgprot m_delete.o
+_mypath m_delete.o
+_pfolder m_delete.o
+_prproc m_delete.o
+_scanpro m_delete.o
+_sendpro m_delete.o
+_showpro m_delete.o
+_stdcomp m_delete.o
+_stddcom m_delete.o
+_sysed m_delete.o
+_uleq m_delete.o
+cret m_delete.o
+csv m_delete.o
+__iob m_edit.o
+_compone m_edit.o
+_concat m_edit.o
+_current m_edit.o
+_def_fla m_edit.o
+_defalt m_edit.o
+_distcom m_edit.o
+_done m_edit.o
+_draft m_edit.o
+_execlp m_edit.o
+_fflush m_edit.o
+_filepro m_edit.o
+_foldpro m_edit.o
+_fork m_edit.o
+_fprintf m_edit.o
+_getcpy m_edit.o
+_hostnam m_edit.o
+_install m_edit.o
+_invo_na m_edit.o
+_link m_edit.o
+_listnam m_edit.o
+_lockdir m_edit.o
+_lsproc m_edit.o
+_m_defs m_edit.o
+_m_find m_edit.o
+_m_updat m_edit.o
+_mailbox m_edit.o
+_mh_deli m_edit.o
+_mh_prof m_edit.o
+_mhnews m_edit.o
+_mp m_edit.o
+_msgprot m_edit.o
+_mypath m_edit.o
+_perror m_edit.o
+_pfolder m_edit.o
+_prproc m_edit.o
+_rindex m_edit.o
+_scanpro m_edit.o
+_sendpro m_edit.o
+_showpro m_edit.o
+_signal m_edit.o
+_stat m_edit.o
+_stdcomp m_edit.o
+_stddcom m_edit.o
+_sysed m_edit.o
+_unlink m_edit.o
+_wait m_edit.o
+cret m_edit.o
+csv m_edit.o
+_compone m_find.o
+_current m_find.o
+_def_fla m_find.o
+_defalt m_find.o
+_distcom m_find.o
+_draft m_find.o
+_filepro m_find.o
+_foldpro m_find.o
+_hostnam m_find.o
+_install m_find.o
+_listnam m_find.o
+_lockdir m_find.o
+_lsproc m_find.o
+_m_defs m_find.o
+_m_getde m_find.o
+_mailbox m_find.o
+_mh_deli m_find.o
+_mh_prof m_find.o
+_mhnews m_find.o
+_msgprot m_find.o
+_mypath m_find.o
+_pfolder m_find.o
+_prproc m_find.o
+_scanpro m_find.o
+_sendpro m_find.o
+_showpro m_find.o
+_stdcomp m_find.o
+_stddcom m_find.o
+_sysed m_find.o
+_uleq m_find.o
+cret m_find.o
+csv m_find.o
+__iob m_getdefs.o
+_compone m_getdefs.o
+_current m_getdefs.o
+_def_fla m_getdefs.o
+_defalt m_getdefs.o
+_defpath m_getdefs.o
+_distcom m_getdefs.o
+_done m_getdefs.o
+_draft m_getdefs.o
+_execl m_getdefs.o
+_fclose m_getdefs.o
+_filepro m_getdefs.o
+_foldpro m_getdefs.o
+_fopen m_getdefs.o
+_fork m_getdefs.o
+_fprintf m_getdefs.o
+_getcpy m_getdefs.o
+_getenv m_getdefs.o
+_hostnam m_getdefs.o
+_install m_getdefs.o
+_listnam m_getdefs.o
+_lockdir m_getdefs.o
+_lsproc m_getdefs.o
+_m_defs m_getdefs.o
+_m_getfl m_getdefs.o
+_mailbox m_getdefs.o
+_malloc m_getdefs.o
+_mh_deli m_getdefs.o
+_mh_prof m_getdefs.o
+_mhnews m_getdefs.o
+_msgprot m_getdefs.o
+_mypath m_getdefs.o
+_perror m_getdefs.o
+_pfolder m_getdefs.o
+_prproc m_getdefs.o
+_scanpro m_getdefs.o
+_sendpro m_getdefs.o
+_showpro m_getdefs.o
+_sprintf m_getdefs.o
+_stdcomp m_getdefs.o
+_stddcom m_getdefs.o
+_strcmp m_getdefs.o
+_sysed m_getdefs.o
+_trimcpy m_getdefs.o
+_wait m_getdefs.o
+cret m_getdefs.o
+csv m_getdefs.o
+__filbuf m_getfld.o
+__iob m_getfld.o
+_compone m_getfld.o
+_current m_getfld.o
+_def_fla m_getfld.o
+_defalt m_getfld.o
+_distcom m_getfld.o
+_draft m_getfld.o
+_filepro m_getfld.o
+_foldpro m_getfld.o
+_fprintf m_getfld.o
+_hostnam m_getfld.o
+_install m_getfld.o
+_listnam m_getfld.o
+_lockdir m_getfld.o
+_lsproc m_getfld.o
+_m_defs m_getfld.o
+_m_fldsz m_getfld.o
+_mailbox m_getfld.o
+_mh_deli m_getfld.o
+_mh_prof m_getfld.o
+_mhnews m_getfld.o
+_msgprot m_getfld.o
+_mypath m_getfld.o
+_peekc m_getfld.o
+_pfolder m_getfld.o
+_prproc m_getfld.o
+_scanpro m_getfld.o
+_sendpro m_getfld.o
+_showpro m_getfld.o
+_stdcomp m_getfld.o
+_stddcom m_getfld.o
+_sysed m_getfld.o
+cret m_getfld.o
+csv m_getfld.o
+_compone m_getfolder.o
+_current m_getfolder.o
+_def_fla m_getfolder.o
+_defalt m_getfolder.o
+_distcom m_getfolder.o
+_draft m_getfolder.o
+_filepro m_getfolder.o
+_foldpro m_getfolder.o
+_hostnam m_getfolder.o
+_install m_getfolder.o
+_listnam m_getfolder.o
+_lockdir m_getfolder.o
+_lsproc m_getfolder.o
+_m_defs m_getfolder.o
+_m_find m_getfolder.o
+_m_getde m_getfolder.o
+_mailbox m_getfolder.o
+_mh_deli m_getfolder.o
+_mh_prof m_getfolder.o
+_mhnews m_getfolder.o
+_msgprot m_getfolder.o
+_mypath m_getfolder.o
+_pfolder m_getfolder.o
+_prproc m_getfolder.o
+_scanpro m_getfolder.o
+_sendpro m_getfolder.o
+_showpro m_getfolder.o
+_stdcomp m_getfolder.o
+_stddcom m_getfolder.o
+_sysed m_getfolder.o
+cret m_getfolder.o
+csv m_getfolder.o
+_atooi m_gmprot.o
+_compone m_gmprot.o
+_current m_gmprot.o
+_def_fla m_gmprot.o
+_defalt m_gmprot.o
+_distcom m_gmprot.o
+_draft m_gmprot.o
+_filepro m_gmprot.o
+_foldpro m_gmprot.o
+_hostnam m_gmprot.o
+_install m_gmprot.o
+_listnam m_gmprot.o
+_lockdir m_gmprot.o
+_lsproc m_gmprot.o
+_m_defs m_gmprot.o
+_m_find m_gmprot.o
+_mailbox m_gmprot.o
+_mh_deli m_gmprot.o
+_mh_prof m_gmprot.o
+_mhnews m_gmprot.o
+_msgprot m_gmprot.o
+_mypath m_gmprot.o
+_pfolder m_gmprot.o
+_prproc m_gmprot.o
+_scanpro m_gmprot.o
+_sendpro m_gmprot.o
+_showpro m_gmprot.o
+_stdcomp m_gmprot.o
+_stddcom m_gmprot.o
+_sysed m_gmprot.o
+cret m_gmprot.o
+csv m_gmprot.o
+_access m_gmsg.o
+_close m_gmsg.o
+_closedi m_gmsg.o
+_compone m_gmsg.o
+_current m_gmsg.o
+_def_fla m_gmsg.o
+_defalt m_gmsg.o
+_distcom m_gmsg.o
+_draft m_gmsg.o
+_filepro m_gmsg.o
+_foldpro m_gmsg.o
+_hostnam m_gmsg.o
+_install m_gmsg.o
+_listnam m_gmsg.o
+_lockdir m_gmsg.o
+_lsproc m_gmsg.o
+_m_defs m_gmsg.o
+_m_find m_gmsg.o
+_mailbox m_gmsg.o
+_malloc m_gmsg.o
+_mh_deli m_gmsg.o
+_mh_prof m_gmsg.o
+_mhnews m_gmsg.o
+_mp m_gmsg.o
+_msgprot m_gmsg.o
+_mypath m_gmsg.o
+_open m_gmsg.o
+_opendir m_gmsg.o
+_pfolder m_gmsg.o
+_prproc m_gmsg.o
+_read m_gmsg.o
+_readdir m_gmsg.o
+_scanpro m_gmsg.o
+_sendpro m_gmsg.o
+_showpro m_gmsg.o
+_sprintf m_gmsg.o
+_stat m_gmsg.o
+_stdcomp m_gmsg.o
+_stddcom m_gmsg.o
+_strcmp m_gmsg.o
+_sysed m_gmsg.o
+cret m_gmsg.o
+csv m_gmsg.o
+_compone m_maildir.o
+_copy m_maildir.o
+_current m_maildir.o
+_def_fla m_maildir.o
+_defalt m_maildir.o
+_distcom m_maildir.o
+_draft m_maildir.o
+_filepro m_maildir.o
+_foldpro m_maildir.o
+_hostnam m_maildir.o
+_install m_maildir.o
+_listnam m_maildir.o
+_lockdir m_maildir.o
+_lsproc m_maildir.o
+_m_defs m_maildir.o
+_m_find m_maildir.o
+_m_getde m_maildir.o
+_m_getfo m_maildir.o
+_mailbox m_maildir.o
+_mh_deli m_maildir.o
+_mh_prof m_maildir.o
+_mhnews m_maildir.o
+_msgprot m_maildir.o
+_mypath m_maildir.o
+_pfolder m_maildir.o
+_prproc m_maildir.o
+_scanpro m_maildir.o
+_sendpro m_maildir.o
+_showpro m_maildir.o
+_sprintf m_maildir.o
+_stdcomp m_maildir.o
+_stddcom m_maildir.o
+_strcpy m_maildir.o
+_strlen m_maildir.o
+_sysed m_maildir.o
+cret m_maildir.o
+csv m_maildir.o
+cret m_name.o
+csv m_name.o
+_cndfree m_replace.o
+_compone m_replace.o
+_current m_replace.o
+_def_fla m_replace.o
+_defalt m_replace.o
+_distcom m_replace.o
+_draft m_replace.o
+_filepro m_replace.o
+_foldpro m_replace.o
+_getcpy m_replace.o
+_hostnam m_replace.o
+_install m_replace.o
+_listnam m_replace.o
+_lockdir m_replace.o
+_lsproc m_replace.o
+_m_defs m_replace.o
+_m_getde m_replace.o
+_mailbox m_replace.o
+_malloc m_replace.o
+_mh_deli m_replace.o
+_mh_prof m_replace.o
+_mhnews m_replace.o
+_msgprot m_replace.o
+_mypath m_replace.o
+_pfolder m_replace.o
+_prproc m_replace.o
+_scanpro m_replace.o
+_sendpro m_replace.o
+_showpro m_replace.o
+_stdcomp m_replace.o
+_stddcom m_replace.o
+_strcmp m_replace.o
+_sysed m_replace.o
+_uleq m_replace.o
+cret m_replace.o
+csv m_replace.o
+__iob m_send.o
+_compone m_send.o
+_current m_send.o
+_def_fla m_send.o
+_defalt m_send.o
+_distcom m_send.o
+_draft m_send.o
+_execv m_send.o
+_fflush m_send.o
+_filepro m_send.o
+_foldpro m_send.o
+_fprintf m_send.o
+_hostnam m_send.o
+_install m_send.o
+_listnam m_send.o
+_lockdir m_send.o
+_lsproc m_send.o
+_m_defs m_send.o
+_m_updat m_send.o
+_mailbox m_send.o
+_mh_deli m_send.o
+_mh_prof m_send.o
+_mhnews m_send.o
+_msgprot m_send.o
+_mypath m_send.o
+_pfolder m_send.o
+_prproc m_send.o
+_scanpro m_send.o
+_sendpro m_send.o
+_showpro m_send.o
+_stdcomp m_send.o
+_stddcom m_send.o
+_sysed m_send.o
+cret m_send.o
+csv m_send.o
+__iob m_setcur.o
+_close m_setcur.o
+_compone m_setcur.o
+_concat m_setcur.o
+_creat m_setcur.o
+_current m_setcur.o
+_def_fla m_setcur.o
+_defalt m_setcur.o
+_distcom m_setcur.o
+_draft m_setcur.o
+_exit m_setcur.o
+_filepro m_setcur.o
+_foldpro m_setcur.o
+_fprintf m_setcur.o
+_free m_setcur.o
+_hostnam m_setcur.o
+_install m_setcur.o
+_listnam m_setcur.o
+_lockdir m_setcur.o
+_lsproc m_setcur.o
+_m_defs m_setcur.o
+_m_name m_setcur.o
+_m_repla m_setcur.o
+_mailbox m_setcur.o
+_mh_deli m_setcur.o
+_mh_prof m_setcur.o
+_mhnews m_setcur.o
+_mp m_setcur.o
+_msgprot m_setcur.o
+_mypath m_setcur.o
+_pfolder m_setcur.o
+_prproc m_setcur.o
+_scanpro m_setcur.o
+_sendpro m_setcur.o
+_showpro m_setcur.o
+_stdcomp m_setcur.o
+_stddcom m_setcur.o
+_strcmp m_setcur.o
+_strcpy m_setcur.o
+_strlen m_setcur.o
+_sysed m_setcur.o
+_write m_setcur.o
+cret m_setcur.o
+csv m_setcur.o
+__iob m_update.o
+_compone m_update.o
+_current m_update.o
+_def_fla m_update.o
+_defalt m_update.o
+_defpath m_update.o
+_distcom m_update.o
+_done m_update.o
+_draft m_update.o
+_fclose m_update.o
+_filepro m_update.o
+_foldpro m_update.o
+_fopen m_update.o
+_fprintf m_update.o
+_hostnam m_update.o
+_install m_update.o
+_listnam m_update.o
+_lockdir m_update.o
+_lsproc m_update.o
+_m_defs m_update.o
+_mailbox m_update.o
+_mh_deli m_update.o
+_mh_prof m_update.o
+_mhnews m_update.o
+_msgprot m_update.o
+_mypath m_update.o
+_pfolder m_update.o
+_prproc m_update.o
+_scanpro m_update.o
+_sendpro m_update.o
+_showpro m_update.o
+_signal m_update.o
+_stdcomp m_update.o
+_stddcom m_update.o
+_sysed m_update.o
+cret m_update.o
+csv m_update.o
+__iob makedir.o
+_atooi makedir.o
+_chmod makedir.o
+_compone makedir.o
+_current makedir.o
+_def_fla makedir.o
+_defalt makedir.o
+_distcom makedir.o
+_draft makedir.o
+_execl makedir.o
+_filepro makedir.o
+_foldpro makedir.o
+_fork makedir.o
+_fprintf makedir.o
+_hostnam makedir.o
+_install makedir.o
+_listnam makedir.o
+_lockdir makedir.o
+_lsproc makedir.o
+_m_defs makedir.o
+_m_find makedir.o
+_mailbox makedir.o
+_mh_deli makedir.o
+_mh_prof makedir.o
+_mhnews makedir.o
+_msgprot makedir.o
+_mypath makedir.o
+_pfolder makedir.o
+_prproc makedir.o
+_scanpro makedir.o
+_sendpro makedir.o
+_showpro makedir.o
+_stdcomp makedir.o
+_stddcom makedir.o
+_sysed makedir.o
+_wait makedir.o
+cret makedir.o
+csv makedir.o
+__iob makename.o
+_compone makename.o
+_current makename.o
+_def_fla makename.o
+_defalt makename.o
+_distcom makename.o
+_draft makename.o
+_exit makename.o
+_filepro makename.o
+_foldpro makename.o
+_fprintf makename.o
+_getpid makename.o
+_hostnam makename.o
+_install makename.o
+_listnam makename.o
+_lockdir makename.o
+_lsproc makename.o
+_m_defs makename.o
+_mailbox makename.o
+_mh_deli makename.o
+_mh_prof makename.o
+_mhnews makename.o
+_msgprot makename.o
+_mypath makename.o
+_pfolder makename.o
+_prproc makename.o
+_scanpro makename.o
+_sendpro makename.o
+_showpro makename.o
+_stdcomp makename.o
+_stddcom makename.o
+_sysed makename.o
+cret makename.o
+csv makename.o
+__filbuf peekc.o
+_ungetc peekc.o
+cret peekc.o
+csv peekc.o
+_printf pr_array.o
+cret pr_array.o
+csv pr_array.o
+_compone printsw.o
+_current printsw.o
+_def_fla printsw.o
+_defalt printsw.o
+_distcom printsw.o
+_draft printsw.o
+_filepro printsw.o
+_foldpro printsw.o
+_hostnam printsw.o
+_install printsw.o
+_listnam printsw.o
+_lockdir printsw.o
+_lsproc printsw.o
+_m_defs printsw.o
+_mailbox printsw.o
+_mh_deli printsw.o
+_mh_prof printsw.o
+_mhnews printsw.o
+_msgprot printsw.o
+_mypath printsw.o
+_pfolder printsw.o
+_printf printsw.o
+_prproc printsw.o
+_scanpro printsw.o
+_sendpro printsw.o
+_showpro printsw.o
+_ssequal printsw.o
+_stdcomp printsw.o
+_stddcom printsw.o
+_strlen printsw.o
+_sysed printsw.o
+cret printsw.o
+csv printsw.o
+_asctime putdate.o
+_fprintf putdate.o
+_ftime putdate.o
+_localti putdate.o
+_strncmp putdate.o
+_time putdate.o
+_timezon putdate.o
+cret putdate.o
+csv putdate.o
+cret r1bindex.o
+csv r1bindex.o
+__iob showfile.o
+_compone showfile.o
+_current showfile.o
+_def_fla showfile.o
+_defalt showfile.o
+_distcom showfile.o
+_draft showfile.o
+_execv showfile.o
+_fflush showfile.o
+_filepro showfile.o
+_foldpro showfile.o
+_fork showfile.o
+_fprintf showfile.o
+_hostnam showfile.o
+_install showfile.o
+_listnam showfile.o
+_lockdir showfile.o
+_lsproc showfile.o
+_m_defs showfile.o
+_m_updat showfile.o
+_mailbox showfile.o
+_mh_deli showfile.o
+_mh_prof showfile.o
+_mhnews showfile.o
+_msgprot showfile.o
+_mypath showfile.o
+_perror showfile.o
+_pfolder showfile.o
+_prproc showfile.o
+_scanpro showfile.o
+_sendpro showfile.o
+_showpro showfile.o
+_signal showfile.o
+_stdcomp showfile.o
+_stddcom showfile.o
+_sysed showfile.o
+_wait showfile.o
+cret showfile.o
+csv showfile.o
+_compone smatch.o
+_current smatch.o
+_def_fla smatch.o
+_defalt smatch.o
+_distcom smatch.o
+_draft smatch.o
+_filepro smatch.o
+_foldpro smatch.o
+_hostnam smatch.o
+_install smatch.o
+_listnam smatch.o
+_lockdir smatch.o
+_lsproc smatch.o
+_m_defs smatch.o
+_mailbox smatch.o
+_mh_deli smatch.o
+_mh_prof smatch.o
+_mhnews smatch.o
+_msgprot smatch.o
+_mypath smatch.o
+_pfolder smatch.o
+_prproc smatch.o
+_scanpro smatch.o
+_sendpro smatch.o
+_showpro smatch.o
+_stdcomp smatch.o
+_stddcom smatch.o
+_strlen smatch.o
+_sysed smatch.o
+cret smatch.o
+csv smatch.o
+cret ssequal.o
+csv ssequal.o
+_malloc trimcpy.o
+_strcpy trimcpy.o
+cret trimcpy.o
+csv trimcpy.o
+_write type.o
+cret type.o
+csv type.o
+cret uleq.o
+csv uleq.o
diff --git a/docs/historical/2.9BSD/subs/Makefile b/docs/historical/2.9BSD/subs/Makefile
new file mode 100644 (file)
index 0000000..e6814ac
--- /dev/null
@@ -0,0 +1,56 @@
+subs.a: add.o           \
+       ambigsw.o       \
+       atooi.o         \
+       brkstring.o     \
+       cdate.o         \
+       cndfree.o       \
+       concat.o        \
+       copy.o          \
+       copyip.o        \
+       cputc.o         \
+       done.o          \
+       fdcompare.o     \
+       gans.o          \
+       getans.o        \
+       getcpy.o        \
+       help.o          \
+       invo_name.o     \
+       locv.o          \
+       m_convert.o     \
+       m_delete.o      \
+       m_edit.o        \
+       m_find.o        \
+       m_getdefs.o     \
+       m_getfld.o      \
+       m_getfolder.o   \
+       m_gmprot.o      \
+       m_gmsg.o        \
+       m_maildir.o     \
+       m_name.o        \
+       m_replace.o     \
+       m_send.o        \
+       m_setcur.o      \
+       m_update.o      \
+       makedir.o       \
+       makename.o      \
+       peekc.o         \
+       pr_array.o      \
+       printsw.o       \
+       putdate.o       \
+       r1bindex.o      \
+       showfile.o      \
+       smatch.o        \
+       ssequal.o       \
+       trimcpy.o       \
+       type.o          \
+       uleq.o
+
+       ar cr subs.a `lorder *.o | tsort`
+
+.c.o:
+       cc -I../cmds -I/usr/src/ucb/libndir -c -O $*.c
+       -@ld -x -r $@
+       @mv a.out $@
+
+clean:
+       rm -f *.o subs.a
diff --git a/docs/historical/2.9BSD/subs/add.c b/docs/historical/2.9BSD/subs/add.c
new file mode 100644 (file)
index 0000000..aad3815
--- /dev/null
@@ -0,0 +1,15 @@
+char *add(this, that)
+register char *this, *that;
+{
+       register char *r;
+
+       if(!this)
+               this = "";
+       if(!that)
+               that = "";
+       r = (char *) malloc(strlen(this)+strlen(that)+1);
+       sprintf(r, "%s%s", that, this);
+       if(*that)
+               cndfree(that);
+       return(r);
+}
diff --git a/docs/historical/2.9BSD/subs/ambigsw.c b/docs/historical/2.9BSD/subs/ambigsw.c
new file mode 100644 (file)
index 0000000..505b2d4
--- /dev/null
@@ -0,0 +1,10 @@
+#include <stdio.h>
+
+ambigsw(arg, swp)
+char *arg;
+{
+       fprintf(stderr, "%s: ", invo_name());
+       fprintf(stderr, "-%s ambiguous.  It matches \n", arg);
+       printsw(arg, swp, "-");
+}
+
diff --git a/docs/historical/2.9BSD/subs/atooi.c b/docs/historical/2.9BSD/subs/atooi.c
new file mode 100644 (file)
index 0000000..79991d3
--- /dev/null
@@ -0,0 +1,15 @@
+atooi(cp)
+register char *cp;
+{
+       register int i, base;
+
+/*      base = 10;      */
+       i = 0;
+/*      if(*cp == '0')  */
+               base = 8;
+       while(*cp >= '0' && *cp <= '9') {
+               i *= base;
+               i += *cp++ - '0';
+       }
+       return(i);
+}
diff --git a/docs/historical/2.9BSD/subs/brkstring.c b/docs/historical/2.9BSD/subs/brkstring.c
new file mode 100644 (file)
index 0000000..9933ff1
--- /dev/null
@@ -0,0 +1,38 @@
+#define NSTR 25
+char **brkstring(strg,brksep,brkterm)  /* returns pointer to static table of substring ptrs */
+char *strg;
+char *brksep, *brkterm;
+{
+
+       register char c, *bp, *sp;
+       static char *broken[NSTR+1];    /* static array of substring start addresses */
+       int bi;
+
+       sp = strg;      /* scan string, replacing separators with zeroes */
+
+       for (bi=0; bi<NSTR; bi++) {     /* and entering start addrs in "broken" */
+               while (brkany(c = *sp, brksep)) *sp++ = 0;
+               if (!c || brkany(c, brkterm)) {
+                       *sp=0;
+                       broken[bi] = 0;
+                       return(broken);         /* terminator found, finish up */
+               }
+
+               broken[bi] = sp;        /* set next start addr */
+
+               while ((c = *++sp) && !brkany(c,brksep) && !brkany(c,brkterm));
+
+       }
+       broken[NSTR] = 0;               /* reached limit of NSTR substrings */
+       return (broken);
+}
+
+brkany (chr,strg)      /* returns 1 if chr in strg, 0 otherwise */
+char chr,*strg;
+{
+       register char *sp;
+
+       for (sp=strg; *sp; sp++)
+               if (chr == *sp) return (1);
+       return (0);
+}
diff --git a/docs/historical/2.9BSD/subs/cdate.c b/docs/historical/2.9BSD/subs/cdate.c
new file mode 100644 (file)
index 0000000..a1fd866
--- /dev/null
@@ -0,0 +1,18 @@
+/* returns date in format dd-mon-yy@hh:mm:ss\0 */
+char *cdate(dataddr)
+long *dataddr;
+{
+       register char *cp;
+       char *ctime();
+
+       cp = ctime(dataddr);
+       cp[1] = cp[8];
+       cp[2] = cp[9];
+       cp[3] = '-';
+       cp[7] = '-';
+       cp[8] = cp[22];
+       cp[9] = cp[23];
+       cp[10] = '@';
+       cp[19] = 0;
+       return(cp+1);
+}
diff --git a/docs/historical/2.9BSD/subs/cndfree.c b/docs/historical/2.9BSD/subs/cndfree.c
new file mode 100644 (file)
index 0000000..c2f2bc4
--- /dev/null
@@ -0,0 +1,12 @@
+/* Conditional free -- perform a free call if the address passed
+ * is in free storage;  else NOP
+ */
+
+
+cndfree(addr)
+char *addr;
+{
+       extern char end;
+
+       if(addr >= &end) free(addr);
+}
diff --git a/docs/historical/2.9BSD/subs/concat.c b/docs/historical/2.9BSD/subs/concat.c
new file mode 100644 (file)
index 0000000..ba19272
--- /dev/null
@@ -0,0 +1,18 @@
+#include "mh.h"
+
+char *concat(args)
+char *args;
+{
+       register char **a;
+       register char *cp;
+       register int  len;
+       register char *ret;
+
+       len = 1;
+       for(a = &args; *a; )
+               len += strlen(*a++);
+       ret = cp = (char *) malloc(len);
+       for(a = &args; *a; )
+               cp = copy(*a++, cp);
+       return(ret);
+}
diff --git a/docs/historical/2.9BSD/subs/copy.c b/docs/historical/2.9BSD/subs/copy.c
new file mode 100644 (file)
index 0000000..3284c12
--- /dev/null
@@ -0,0 +1,6 @@
+char *copy(from,to)
+register char *from, *to;
+{
+       while(*to++ = *from++);
+       return to-1;
+};
diff --git a/docs/historical/2.9BSD/subs/copyip.c b/docs/historical/2.9BSD/subs/copyip.c
new file mode 100644 (file)
index 0000000..a145481
--- /dev/null
@@ -0,0 +1,9 @@
+int *copyip(ipf, ipt)
+register int *ipf, *ipt;
+{
+       while((*ipt = *ipf)  && *ipf++ != -1)
+               ipt++;
+       *ipt = 0;
+       return(ipt);
+}
+
diff --git a/docs/historical/2.9BSD/subs/cputc.c b/docs/historical/2.9BSD/subs/cputc.c
new file mode 100644 (file)
index 0000000..f3715fb
--- /dev/null
@@ -0,0 +1,13 @@
+#include <stdio.h>
+
+cputc(chr, ip)
+register FILE *ip;
+{
+       if(ip != NULL) {
+               putc(chr, ip);
+               if(ferror(ip)) {
+                       perror("Write error");
+                       done(-1);
+               }
+       }
+}
diff --git a/docs/historical/2.9BSD/subs/crpbrkstring.c b/docs/historical/2.9BSD/subs/crpbrkstring.c
new file mode 100644 (file)
index 0000000..bea7514
--- /dev/null
@@ -0,0 +1,50 @@
+#define NSTR 25
+
+/*
+ * Parse the given string into a number of sub strings separated
+ * by characters in brksep.  Terminate on brkterm or 0.
+ */
+
+char **
+brkstring(strg, brksep, brkterm)
+       char *strg;
+       char *brksep, *brkterm;
+{
+       register int c;
+       register char *cp, **ap;
+       static char *broken[NSTR+1];
+
+       cp = strg;
+       ap = broken;
+       for (;;) {
+               if (ap-broken > NSTR) {
+                       broken[NSTR] = 0;
+                       return(broken);
+               }
+               while (brkany(*cp, brksep))
+                       cp++;
+               if (*cp == 0 || *cp == brkterm) {
+done:
+                       *ap = 0;
+                       return(broken);
+               }
+               *ap++ = cp;
+               while (!brkany(*cp, brksep) && *cp && *cp != brkterm)
+                       cp++;
+               if (*cp == 0 || *cp == brkterm) {
+                       *cp = 0;
+                       goto done;
+               }
+               *cp++ = 0;
+       }
+}
+
+brkany (chr,strg)      /* returns 1 if chr in strg, 0 otherwise */
+char chr,*strg;
+{
+       register char *sp;
+
+       for (sp=strg; *sp; sp++)
+               if (chr == *sp) return (1);
+       return (0);
+}
diff --git a/docs/historical/2.9BSD/subs/done.c b/docs/historical/2.9BSD/subs/done.c
new file mode 100644 (file)
index 0000000..5808ba3
--- /dev/null
@@ -0,0 +1,8 @@
+/* This routine is replaced by some modules if they need to do
+ * cleanup.  All exits in the code call done rather than exit.
+ */
+
+done(status)
+{
+       exit(status);
+}
diff --git a/docs/historical/2.9BSD/subs/fdcompare.c b/docs/historical/2.9BSD/subs/fdcompare.c
new file mode 100644 (file)
index 0000000..94a54b2
--- /dev/null
@@ -0,0 +1,27 @@
+fdcompare(fd1, fd2)
+{
+       int n1, n2, resp;
+       register int i;
+       register char *c1, *c2;
+       char b1[512], b2[512];
+
+       resp = 1;
+       while((n1 = read(fd1, b1, 512)) >= 0 &&
+             (n2 = read(fd2, b2, 512)) >= 0 &&
+              n1 == n2) {
+
+               c1 = b1; c2 = b2;
+               for(i = n1 < 512? n1 : 512; i--; )
+                       if(*c1++ != *c2++) {
+                               resp = 0;
+                               goto leave;
+                       }
+               if(n1 < 512)
+                       goto leave;
+       }
+       resp = 0;
+leave:
+       lseek(fd1, 0l, 0);
+       lseek(fd2, 0l, 0);
+       return(resp);
+}
diff --git a/docs/historical/2.9BSD/subs/gans.c b/docs/historical/2.9BSD/subs/gans.c
new file mode 100644 (file)
index 0000000..c85c1e0
--- /dev/null
@@ -0,0 +1,38 @@
+#include "mh.h"
+#include <stdio.h>
+
+gans(prompt, ansp)
+struct swit *ansp;
+{
+       char ansbuf[32];
+       register char *cp;
+       register int i;
+       struct swit *ap;
+
+    for(;;) {
+       printf("%s", prompt);
+       fflush(stdout);
+       cp = ansbuf;
+       while((i = getchar()) != '\n') {
+               if(i == EOF)
+                       return(0);
+               if(cp < &ansbuf[31]) {
+                       if(i >= 'A' && i <= 'Z')
+                               i += 'a'-'A';
+                       *cp++ = i;
+               }
+       }
+       *cp = 0;
+       if(ansbuf[0] == '?' || cp == ansbuf) {
+               printf("Options are:\n");
+               for(ap = ansp; ap->sw; ap++)
+                       printf("  %s\n", ap->sw);
+               continue;
+       }
+       if((i = smatch(ansbuf, ansp)) < 0) {
+               printf("%s: %s.\n", ansbuf, i == -1? "unknown":"ambiguous");
+               continue;
+       }
+       return(i);
+    }
+}
diff --git a/docs/historical/2.9BSD/subs/getans.c b/docs/historical/2.9BSD/subs/getans.c
new file mode 100644 (file)
index 0000000..11abb45
--- /dev/null
@@ -0,0 +1,54 @@
+#include "mh.h"
+#include <signal.h>
+#include <stdio.h>
+
+int g_sigint;   /* sensed an interrupt */
+int g_sig();
+
+char **getans(prompt, ansp)
+struct swit *ansp;
+{
+       static char ansbuf[128];
+       register char *cp, **cpp;
+       register int i;
+       struct swit *ap;
+
+       signal(SIGINT, g_sig);
+       for(;;) {
+               printf("%s", prompt);
+               fflush(stdout);
+               cp = ansbuf;
+               while((i = getchar()) != '\n') {
+                       if(i == EOF || g_sigint)  {
+                               g_sigint = 0;
+                               return(0);
+                       }
+                       if(cp < &ansbuf[127])
+                               *cp++ = i;
+               }
+               *cp = 0;
+               if(ansbuf[0] == '?' || cp == ansbuf) {
+                       printf("Options are:\n");
+                       printsw(ALL, ansp, "");
+                       continue;
+               }
+               cpp = brkstring(ansbuf, " ", 0);
+               switch(smatch(*cpp, ansp)) {
+               case -2:ambigsw(*cpp, ansp);                   /* ambiguous */
+                       continue;
+               case -1:                                       /* unknown   */
+                       printf(" -%s unknown. Hit <CR> for help.\n", *cpp);
+                       continue;
+               default:
+                       return(cpp);            /* list, edit, quit, send */
+               }
+       }
+}
+
+
+g_sig()
+{
+       signal(SIGINT, g_sig);
+       g_sigint = 1;
+       return;
+}
diff --git a/docs/historical/2.9BSD/subs/getcpy.c b/docs/historical/2.9BSD/subs/getcpy.c
new file mode 100644 (file)
index 0000000..ab94cd1
--- /dev/null
@@ -0,0 +1,8 @@
+char *getcpy(str)
+{
+       register char *cp;
+
+       cp = (char *) malloc(strlen(str) + 1);
+       strcpy(cp, str);
+       return(cp);
+}
diff --git a/docs/historical/2.9BSD/subs/help.c b/docs/historical/2.9BSD/subs/help.c
new file mode 100644 (file)
index 0000000..9f6dc12
--- /dev/null
@@ -0,0 +1,9 @@
+#include "mh.h"
+
+help(str, swp)
+char *str;
+{
+       printf("syntax: %s\n", str);
+       printf("  switches are:\n");
+       printsw(ALL, swp, "-");
+}
diff --git a/docs/historical/2.9BSD/subs/invo_name.c b/docs/historical/2.9BSD/subs/invo_name.c
new file mode 100644 (file)
index 0000000..25b86a4
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * This routine returns the address on the stack of the text of the
+ *  first argument to the process.  It only works on the VAX, and only
+ *  if the process was not called with 4 empty args in a row.
+ */
+
+char *invo_name()
+{
+       register int *ip;
+
+       ip = (int *) 0x7ffffff8;        /* Highest stack address -4 */
+
+       while(*--ip != 0)               /* Look backwards for bumber */
+               ;
+       return (char *) &ip[1];         /* Next string is it. */
+}
diff --git a/docs/historical/2.9BSD/subs/locv.c b/docs/historical/2.9BSD/subs/locv.c
new file mode 100644 (file)
index 0000000..b530686
--- /dev/null
@@ -0,0 +1,8 @@
+char *locv(longint)
+long longint;
+{
+       static char locvbuf[12];
+
+       sprintf(locvbuf, "%ld", longint);
+       return locvbuf;
+}
diff --git a/docs/historical/2.9BSD/subs/m_convert.c b/docs/historical/2.9BSD/subs/m_convert.c
new file mode 100644 (file)
index 0000000..43220b4
--- /dev/null
@@ -0,0 +1,147 @@
+#include "mh.h"
+#include <stdio.h>
+
+int  convdir;
+struct msgs *mp;
+char *delimp;
+
+m_convert(name)
+char *name;
+{
+       register char *cp;
+       register int first, last;
+       int found, group, range, err;
+       char *bp;
+
+       found = group = 0;
+       if(strcmp((cp = name), "all") == 0)
+               cp = "first-last";
+       if((err = first = m_conv(cp)) <= 0)
+               goto badbad;
+       if(*(cp = delimp) && *cp != '-' && *cp != ':')  {
+       baddel: fprintf(stderr, "Illegal argument delimiter: \"%c\"\n", *delimp);
+               return(0);
+       }
+       if(*cp == '-') {
+               group++;  cp++;
+               if((err = last = m_conv(cp)) <= 0) {
+         badbad:       if(err == -1)
+                               fprintf(stderr, "No %s message\n", cp);
+                       else
+         badlist:              fprintf(stderr, "Bad message list \"%s\".\n", name);
+                       return(0);
+               }
+               if(last < first) goto badlist;
+               if(*delimp) goto baddel;
+               if(first > mp->hghmsg || last < mp->lowmsg) {
+       rangerr:        fprintf(stderr, "No messages in range \"%s\".\n", name);
+                       return(0);
+               }
+               if(last > mp->hghmsg)
+                       last = mp->hghmsg;
+               if(first < mp->lowmsg)
+                       first = mp->lowmsg;
+       } else if(*cp == ':') {
+               cp++;
+               if(*cp == '-') {
+                       convdir = -1;
+                       cp++;
+               } else if(*cp == '+') {
+                       convdir = 1;
+                       cp++;
+               }
+               if((range = atoi(bp = cp)) == 0)
+                       goto badlist;
+               while(*bp >= '0' && *bp <= '9') bp++;
+               if(*bp)
+                       goto baddel;
+               if((convdir > 0 && first > mp->hghmsg) ||
+                  (convdir < 0 && first < mp->lowmsg))
+                       goto rangerr;
+               if(first < mp->lowmsg)
+                       first = mp->lowmsg;
+               if(first > mp->hghmsg)
+                       first = mp->hghmsg;
+               for(last = first; last >= mp->lowmsg && last <= mp->hghmsg;
+                                               last += convdir)
+                       if(mp->msgstats[last]&EXISTS)
+                               if(--range <= 0)
+                                       break;
+               if(last < mp->lowmsg)
+                       last = mp->lowmsg;
+               if(last > mp->hghmsg)
+                       last = mp->hghmsg;
+               if(last < first) {
+                       range = last; last = first; first = range;
+               }
+       } else {
+               if(first > mp->hghmsg || first < mp->lowmsg ||
+                  !(mp->msgstats[first]&EXISTS)) {
+                       fprintf(stderr, "Message %d doesn't exist.\n", first);
+                       return(0);
+               }
+               last = first;
+       }
+       while(first <= last) {
+               if(mp->msgstats[first]&EXISTS) {
+                       if(!(mp->msgstats[first]&SELECTED)) {
+                               mp->numsel++;
+                               mp->msgstats[first] |= SELECTED;
+                               if(first < mp->lowsel)
+                                       mp->lowsel = first;
+                               if(first > mp->hghsel)
+                                       mp->hghsel = first;
+                       }
+                       found++;
+               }
+               first++;
+       }
+       if(!found)
+               goto rangerr;
+       return(1);
+}
+
+m_conv(str)
+char *str;
+{
+       register char *cp, *bp;
+       register int i;
+       char buf[16];
+
+       convdir = 1;
+       cp = bp = str;
+       if(*cp >= '0' && *cp <= '9')  {
+               while(*bp >= '0' && *bp <= '9') bp++;
+               delimp = bp;
+               return(atoi(cp));
+       }
+       bp = buf;
+       while((*cp >= 'a' && *cp <= 'z') || *cp == '.')
+               *bp++ = *cp++;
+       *bp++ = 0;
+       delimp = cp;
+       if(strcmp(buf, "first") == 0)
+               return(mp->lowmsg);
+       else if(strcmp(buf, "last") == 0) {
+               convdir = -1;
+               return(mp->hghmsg);
+       } else if(strcmp(buf, "cur") == 0 || strcmp(buf, ".") == 0)
+               return(mp->curmsg > 0 ? mp->curmsg : -1);
+       else if(strcmp(buf, "prev") == 0) {
+               convdir = -1;
+               for(i = (mp->curmsg<=mp->hghmsg)? mp->curmsg-1: mp->hghmsg;
+                   i >= mp->lowmsg; i--) {
+                       if(mp->msgstats[i]&EXISTS)
+                               return(i);
+               }
+               return(-1);                     /* non-existent message */
+       } else if(strcmp(buf, "next") == 0)  {
+               for(i = (mp->curmsg>=mp->lowmsg)? mp->curmsg+1: mp->lowmsg;
+                   i <= mp->hghmsg; i++) {
+                       if(mp->msgstats[i]&EXISTS)
+                               return(i);
+               }
+               return(-1);
+       } else
+               return(0);                     /* bad message list */
+}
diff --git a/docs/historical/2.9BSD/subs/m_delete.c b/docs/historical/2.9BSD/subs/m_delete.c
new file mode 100644 (file)
index 0000000..b1732bf
--- /dev/null
@@ -0,0 +1,22 @@
+#include "mh.h"
+
+m_delete(key)
+char *key;
+{
+       register struct node *np, *npprev;
+
+       m_getdefs();
+       for(np = (struct node *) &m_defs; npprev = np; )  {
+               if((np = np->n_next) == 0)
+                       break;
+               if(uleq(np->n_name, key)) {
+                       npprev->n_next = np->n_next;
+                       cndfree(np->n_name);
+                       cndfree(np->n_field);
+                       free(np);
+                       def_flags |= DEFMOD;
+                       return(0);
+               }
+       }
+       return(1);
+}
diff --git a/docs/historical/2.9BSD/subs/m_edit.c b/docs/historical/2.9BSD/subs/m_edit.c
new file mode 100644 (file)
index 0000000..13b470a
--- /dev/null
@@ -0,0 +1,94 @@
+#include "mh.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <stdio.h>
+#include "strings.h"
+
+struct msgs *mp;
+
+char *rindex();
+
+m_edit(ed, file, use, altmsg)
+char **ed, *file, *altmsg;
+int use;
+{
+       /* Exec editor.  Normal exit returns 0.
+        * To abort, returns -1.  To try again, returns -2
+        */
+
+       static char *edsave;
+       static int  reedit;
+       struct stat stbuf;
+       int retstat;
+       register char *cp;
+       int pid, wpid;
+       int intr;
+       union { int statint;
+               struct {char lobyte, hibyte;} statby;
+       } status;
+
+       if(!reedit) {                   /* set initial editor */
+               if(!*ed && (*ed = m_find("editor")) == NULL)
+                       *ed = sysed;
+       } else
+               if(!*ed) {              /* no explicit editor */
+                       *ed = edsave;
+                       cp = rindex(*ed, '/');
+                       if(cp == 0)
+                               cp = *ed;
+                       cp = concat(cp, "-next", 0);
+                       if((cp = m_find(cp)) != NULL)
+                               *ed = cp;
+               }
+       intr = (int) signal(SIGINT, SIG_IGN);
+       if((pid = fork()) == 0) {
+               if(altmsg) {
+                       unlink("@");
+                       link(altmsg, "@");    /* An easy handle on cur msg */
+               }
+               m_update();
+               fflush(stdout);
+               signal(SIGINT, (int (*)()) intr);
+               execlp(*ed, *ed, file, 0);
+               fprintf(stderr, "Can't exec the editor:  ");
+               perror(*ed);  done(-1);
+       } else if(pid == -1) {
+               fprintf(stderr, "No forks!\n");
+               retstat = -1;
+               goto leave;
+       } else
+               while((wpid = wait(&status)) != -1 && wpid != pid) ;
+       signal(SIGINT, (int (*)()) intr);
+       if(status.statint) {
+               if((status.statby.hibyte == -1) ||      /* Can't exec editor */
+                  (reedit && !status.statby.lobyte)) { /*2nd edit.Aborted by user*/
+                       retstat = -2;
+                       goto leave;
+               }
+               fprintf(stderr, "[%s aborted--%s ", invo_name(), file);
+               if(!use && status.statby.hibyte) {      /* edit aborted by user */
+                       unlink(file);
+                       fprintf(stderr, "deleted]\n");
+               } else                          /* 'use' or system abort */
+                       fprintf(stderr, "preserved]\n");
+               retstat = -2;
+               goto leave;
+       }
+       reedit++;
+       retstat = 0;
+       if(altmsg && !mp->msgflags&READONLY) {
+               stat("@", &stbuf);
+               if(stbuf.st_nlink == 1)  /*@'s been edited by Ned*/
+                       if(unlink(altmsg) == -1 || link("@", altmsg) == -1){
+                               fprintf(stderr, "Can't update %s from @ file!\n",altmsg);
+                               retstat = 0;
+                               goto leave;
+                       }
+       }
+ leave:
+       edsave = getcpy(*ed);
+       *ed = 0;
+       unlink("@");          /* Remove this extra link */
+       return(retstat);
+}
diff --git a/docs/historical/2.9BSD/subs/m_find.c b/docs/historical/2.9BSD/subs/m_find.c
new file mode 100644 (file)
index 0000000..26743a0
--- /dev/null
@@ -0,0 +1,13 @@
+#include "mh.h"
+#include <stdio.h>
+
+char *m_find(str)
+{
+       register struct node *n;
+
+       m_getdefs();
+       for(n = m_defs; n; n = n->n_next)
+               if(uleq(n->n_name, str))
+                       return(n->n_field);
+       return(NULL);
+}
diff --git a/docs/historical/2.9BSD/subs/m_getdefs.c b/docs/historical/2.9BSD/subs/m_getdefs.c
new file mode 100644 (file)
index 0000000..35eb085
--- /dev/null
@@ -0,0 +1,90 @@
+#include "mh.h"
+#include <stdio.h>
+
+char    defpath[128];
+
+struct procs {
+       char    *procname;
+       char    **procnaddr;
+} procs [] = {
+       { "lsproc",     &lsproc         },
+       { "mh_deliver", &mh_deliver     },
+       { "prproc",     &prproc         },
+       { "scanproc",   &scanproc       },
+       { "showproc",   &showproc       },
+       { "sendproc",   &sendproc       },
+       { "fileproc",   &fileproc       },
+       { 0,            0               },
+};
+
+m_getdefs()
+{
+       register struct node *np;
+       register int state, wpid, pid;
+       register struct procs *ps;
+       int status;
+       FILE *ib;
+       char name[NAMESZ], field[128];
+
+       if(defpath[0])
+               return;         /* We've already been called!   */
+       if(!mypath)
+               if((mypath = getenv("HOME")) == NULL) {
+                       fprintf(stderr, "HOME environment variable not set!\n");
+                       done(1);
+               }
+       sprintf(defpath, "%s%s", mypath, mh_prof);
+/***    copy(mh_prof, copy(mypath, defpath));           ***/
+
+       if((ib = fopen(defpath, "r")) == NULL) {
+               if((pid = fork()) == 0) {
+                       execl(installproc, "install-mh", "-auto", 0);
+                       fprintf(stderr, "Can't exec ");perror(installproc);
+                       done(1);
+               } else if(pid == -1) {
+                       fprintf(stderr, "No forks!\n");
+                       done(1);
+               } else
+                       while((wpid = wait(&status)) != -1 && wpid != pid)
+                               ;
+               if(status || (ib = fopen(defpath, "r")) == NULL) {
+                       fprintf(stderr, "[install-mh aborted]\n");
+                       done(1);
+               }
+       }
+
+#ifdef NEWS                     /* NOT CONVERTED TO V7!!! */
+       fstat(fildes(ib), field);
+       deftime = (&field)->i_atime;
+#endif
+
+       np = (struct node *) &m_defs;
+       state = FLD;
+    for(;;)
+       switch(state = m_getfld(state,name,field,sizeof field,ib)) {
+       case FLD:
+       case FLDEOF:
+               np->n_next = (struct node *) malloc(sizeof *np);
+               np = np->n_next;
+               np->n_name = getcpy(name);
+               np->n_field = trimcpy(field);
+               np->n_next = 0;
+               for(ps = procs; ps->procname; ps++)
+                       if(strcmp(np->n_name, ps->procname) == 0) {
+                               *ps->procnaddr = np->n_field;
+                               break;
+                       }
+               if(state == FLDEOF) {
+                       fclose(ib);
+                       return(0);
+               }
+               continue;
+       case BODY:
+       case BODYEOF:
+               fprintf(stderr, ".mh_profile must not contain a body--it can't \
+end with a blank line!\n");
+       default:
+               fprintf(stderr, "Bad format: .mh_profile!\n");
+               done(1);
+       }
+}
diff --git a/docs/historical/2.9BSD/subs/m_getfld.c b/docs/historical/2.9BSD/subs/m_getfld.c
new file mode 100644 (file)
index 0000000..27c3300
--- /dev/null
@@ -0,0 +1,87 @@
+#include "mh.h"
+#include <stdio.h>
+
+int     m_fldsz;
+
+m_getfld(state, name, buf, bufsz, iob)
+int state, bufsz;
+char *name, *buf;
+FILE *iob;
+{
+       register char *cp;
+       register c;
+
+ top:   while((c = getc(iob)) == '\001' && peekc(iob) == '\001')
+               while(getc(iob) != '\n');
+
+       if(c < 0)
+               return(FILEEOF);
+       m_fldsz = 0;
+
+       switch(state) {
+
+       case FLDEOF:
+       case BODYEOF:
+       case FLD:
+               if(c == '\n' || c == '-')
+                       goto body;
+               cp = name;
+               for(;;) {
+                       if(cp >= name+NAMESZ-1) {
+                               *cp = 0;
+fprintf(stderr, "??Component Name Exceeds %d Chars:\n    \"%s\"\n", NAMESZ-1, name);
+                               return(LENERR);
+                       }
+                       if(c == ':')
+                               break;
+                       if(c == '\n' || c < 0) {
+                               *cp = 0;
+fprintf(stderr, "??%s Encountered While Scanning for a colon:\n    \"%s\"\n",
+       (c < 0)? "<eof>":"<end of line>", name);
+                               return(FMTERR);
+                       }
+                       *cp++ = c;
+                       *cp   = 0;
+                       c = getc(iob);
+               }
+
+       case FLDPLUS:
+               cp = buf;
+               for(;;) {
+                       if((c = getc(iob)) < 0)
+                               return(FLDEOF);
+                       *cp++ = c;
+                       *cp   = 0;
+                       m_fldsz++;
+                       if(c == '\n')
+                               if((c = peekc(iob)) != ' ' && c != '\t')
+                                       if(c == '\001' || c < 0)
+                                               return(FLDEOF);
+                                       else
+                                               return(FLD);
+                       if(cp >= buf+bufsz-1)
+                               return(peekc(iob) < 0? FLDEOF:FLDPLUS);
+               }
+
+       body:   if(c == '-')
+                       while(getc(iob) != '\n') ;
+               buf[0] = 0;
+               if((c = getc(iob)) == '\001' && peekc(iob) == '\001')
+                       return(BODYEOF);
+
+       case BODY:
+               cp = buf;  *cp = 0;
+               for(;;) {
+                       if(c < 0 || (c == '\001' && peekc(iob) == '\001'))
+                               return(BODYEOF);
+                       *cp++ = c;
+                       *cp   = 0;
+                       m_fldsz++;
+                       if(cp >= buf+bufsz-1)
+                               return(((c=peekc(iob))<0||c=='\001')?
+                                       BODYEOF: BODY);
+                       c = getc(iob);
+               }
+
+       }
+}
diff --git a/docs/historical/2.9BSD/subs/m_getfolder.c b/docs/historical/2.9BSD/subs/m_getfolder.c
new file mode 100644 (file)
index 0000000..9f86bf6
--- /dev/null
@@ -0,0 +1,12 @@
+#include "mh.h"
+#include <stdio.h>
+
+char *m_getfolder()
+{
+       register char *folder;
+
+       m_getdefs();
+       if((folder = m_find(pfolder)) == NULL || *folder == 0)
+               folder = defalt;
+       return(folder);
+}
diff --git a/docs/historical/2.9BSD/subs/m_gmprot.c b/docs/historical/2.9BSD/subs/m_gmprot.c
new file mode 100644 (file)
index 0000000..3430259
--- /dev/null
@@ -0,0 +1,14 @@
+#include "mh.h"
+#include <stdio.h>
+
+m_gmprot()
+{
+       register char *cp;
+       register int prot;
+
+       if((cp = m_find("msg-protect")) != NULL)
+               prot = atooi(cp);
+       else
+               prot = atooi(msgprot);
+       return(prot);
+}
diff --git a/docs/historical/2.9BSD/subs/m_gmsg.c b/docs/historical/2.9BSD/subs/m_gmsg.c
new file mode 100644 (file)
index 0000000..7962a6b
--- /dev/null
@@ -0,0 +1,122 @@
+#include "mh.h"
+#include <stdio.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <dir.h>
+
+struct  msgs *mp;
+
+struct msgs *m_gmsg(name)
+char *name;
+{
+       register int i, j;
+       register char *cp;
+       register struct msgs *msgp;
+       register struct direct *dir;
+       DIR *dirp;
+       int  curfil;
+       struct stat statb;
+       char buf[132];
+
+       struct {
+               int xhghmsg,
+                   xnummsg,
+                   xlowmsg,
+                   xcurmsg;
+               char xselist,
+                    xflags,
+                    xfiller,
+                    xothers;
+               char xmsgs[1000];
+       } msgbuf;
+
+       if ((dirp = opendir(".")) == 0)
+               return (0);
+       for(j = 0; j < 1000; j++)
+               msgbuf.xmsgs[j] = 0;
+       msgbuf.xcurmsg = 0;
+       msgbuf.xnummsg = 0;
+       msgbuf.xselist = 0;
+       msgbuf.xothers = 0;
+       msgbuf.xlowmsg = 5000;
+       msgbuf.xhghmsg = 0;
+       msgbuf.xflags  = (access(".",2) == -1)? READONLY:0;
+
+       /*
+        * The following hack is that if the directory is writable
+        * and the cur file is not, we consider it to be read only
+        * folder.
+        */
+
+       if (stat("cur", &statb) >= 0 && access("cur", 2) < 0)
+               msgbuf.xflags |= READONLY;
+       curfil = 0;
+       while (dir = readdir(dirp)) {
+               cp = dir->d_name;
+               if (j = mu_atoi(cp)) {
+                       if (j > msgbuf.xhghmsg)
+                               msgbuf.xhghmsg = j;
+                       msgbuf.xnummsg++;
+                       if (j < msgbuf.xlowmsg)
+                               msgbuf.xlowmsg = j;
+                       msgbuf.xmsgs[j] = EXISTS;
+               } else if (*cp != ',' && *cp != '.' && *cp != '#')
+                       if (strcmp(cp, current) == 0)
+                               curfil++;
+                       else if (strcmp(cp, listname) == 0)
+                               msgbuf.xselist++;
+                       else
+                               msgbuf.xothers++;
+       }
+       if(!msgbuf.xhghmsg)
+               msgbuf.xlowmsg = 0;
+       closedir(dirp);
+       if(msgbuf.xflags&READONLY) {
+               sprintf(buf, "cur-%s", name);
+/***            copy(name, copy("cur-", buf));          ***/
+               if((cp = m_find(buf)) != NULL)
+                       if(j = mu_atoi(cp))
+                               msgbuf.xcurmsg = j;
+       } else if(curfil && (i = open(current, 0)) >= 0) {
+               if((j = read(i, buf, sizeof (buf))) >= 2) {
+                       buf[j-1] = '\0';    /* Zap <lf> */
+                       if (j = mu_atoi(buf))
+                               msgbuf.xcurmsg = j;
+               }
+               close(i);
+       }
+       if( (int) (msgp = (struct msgs *) malloc(sizeof *mp + msgbuf.xhghmsg + 2)) == -1)
+               return(0);
+       msgp->hghmsg   = msgbuf.xhghmsg;
+       msgp->nummsg   = msgbuf.xnummsg;
+       msgp->lowmsg   = msgbuf.xlowmsg;
+       msgp->curmsg   = msgbuf.xcurmsg;
+       msgp->selist   = msgbuf.xselist;
+       msgp->msgflags = msgbuf.xflags;
+       msgp->others   = msgbuf.xothers;
+       msgp->foldpath = name;
+       msgp->lowsel   = 5000;
+       msgp->hghsel   = 0;
+       msgp->numsel   = 0;
+       for(j = 0; j <= msgbuf.xhghmsg; j++)
+               msgp->msgstats[j] = msgbuf.xmsgs[j];
+       return(msgp);
+}
+
+
+mu_atoi(str)
+char *str;
+{
+       register char *cp;
+       register int i;
+
+       i = 0;
+       cp = str;
+       while(*cp) {
+               if(*cp < '0' || *cp > '9' || i > 99)
+                       return(0);
+               i *= 10;
+               i += *cp++ - '0';
+       }
+       return(i);
+}
diff --git a/docs/historical/2.9BSD/subs/m_maildir.c b/docs/historical/2.9BSD/subs/m_maildir.c
new file mode 100644 (file)
index 0000000..a64ef75
--- /dev/null
@@ -0,0 +1,29 @@
+#include "mh.h"
+#include <stdio.h>
+
+char *mypath;
+
+char *m_maildir(folder)
+char *folder;
+{
+       register char *fold, *path, *cp;
+       static char mailfold[128];
+
+       m_getdefs();
+       if(!(fold = folder))
+               fold = m_getfolder();
+       if(*fold == '/' || *fold == '.')
+               return(fold);
+       cp = mailfold;
+       if((path = m_find("path")) != NULL && *path) {
+               if(*path != '/') {
+                       sprintf(cp, "%s/", mypath);
+                       cp += strlen(cp);
+               }
+               cp = copy(path, cp);
+               if(cp[-1] != '/')
+                       *cp++ = '/';
+       }
+       strcpy(cp, fold);
+       return(mailfold);
+}
diff --git a/docs/historical/2.9BSD/subs/m_name.c b/docs/historical/2.9BSD/subs/m_name.c
new file mode 100644 (file)
index 0000000..c8880af
--- /dev/null
@@ -0,0 +1,21 @@
+char *m_name(num)
+{
+       static char name[4];
+       register char *cp;
+       register int i;
+
+       name[0] = 0;
+       name[1] = 0;
+       name[2] = 0;
+       name[3] = 0;
+       i = num;
+       cp = &name[3];
+       if(i > 0 && i < 1000)
+               do {
+                       *--cp = (i % 10) + '0';
+                       i /= 10;
+               } while(i);
+       else
+               *--cp = '?';
+       return(cp);
+}
diff --git a/docs/historical/2.9BSD/subs/m_replace.c b/docs/historical/2.9BSD/subs/m_replace.c
new file mode 100644 (file)
index 0000000..4d6496d
--- /dev/null
@@ -0,0 +1,29 @@
+#include "mh.h"
+
+
+m_replace(key,value)
+char *key, *value;
+
+{
+       register struct node *np;
+
+       m_getdefs();
+       for(np = m_defs; ; np = np->n_next) {
+               if(uleq(np->n_name, key)) {
+                       if(strcmp(value, np->n_field) != 0) {
+                               cndfree(np->n_field);
+                               np->n_field = value;
+                               def_flags |= DEFMOD;
+                       }
+                       return;
+               }
+               if(!np->n_next)
+                       break;
+       }
+       np->n_next = (struct node *) malloc(sizeof *np);
+       np = np->n_next;
+       np->n_name = getcpy(key);
+       np->n_next = 0;
+       np->n_field = value;
+       def_flags |= DEFMOD;
+}
diff --git a/docs/historical/2.9BSD/subs/m_send.c b/docs/historical/2.9BSD/subs/m_send.c
new file mode 100644 (file)
index 0000000..22ca0a7
--- /dev/null
@@ -0,0 +1,22 @@
+#include "mh.h"
+#include <stdio.h>
+
+m_send(arg, file)
+char *arg, *file;
+{
+       char *vec[10];
+       int ivec;
+
+       ivec = 0;
+       vec[ivec++] = "send";
+       vec[ivec++] = file;
+       if(*arg == 'v')
+               vec[ivec++] = "-verbose";
+       vec[ivec++] = 0;
+       m_update();
+       fflush(stdout);
+       execv(sendproc, vec);
+       fprintf(stderr, "Can't exec %s.\n", sendproc);
+       return(0);
+
+}
diff --git a/docs/historical/2.9BSD/subs/m_setcur.c b/docs/historical/2.9BSD/subs/m_setcur.c
new file mode 100644 (file)
index 0000000..e625149
--- /dev/null
@@ -0,0 +1,26 @@
+#include "mh.h"
+#include <stdio.h>
+
+struct  msgs *mp;
+
+m_setcur(num)
+{
+       char buf[6];
+       register int i;
+       register char *cp1;
+
+       if(mp->msgflags&READONLY) {
+               m_replace(cp1 = concat("cur-",mp->foldpath,0), m_name(num));
+               free(cp1);
+       } else {
+               strcpy(buf, m_name(num));
+               cp1 = buf + strlen(buf);
+               *cp1++ = '\n';
+               if(strcmp(current, "cur"))
+                       error("\"current\" got Clobbered!! Tell B. Borden");
+               if((i = creat(current, 0660)) >= 0) {
+                       write(i, buf, cp1-buf);
+                       close(i);
+               }
+       }
+}
diff --git a/docs/historical/2.9BSD/subs/m_update.c b/docs/historical/2.9BSD/subs/m_update.c
new file mode 100644 (file)
index 0000000..c2ea049
--- /dev/null
@@ -0,0 +1,25 @@
+#include "mh.h"
+#include <stdio.h>
+#include <signal.h>
+
+char    defpath[];
+
+m_update()
+{
+       FILE *out;
+       register struct node *np;
+       int save;
+
+       if(def_flags & DEFMOD) {
+               save = (int) signal(SIGINT, SIG_IGN);
+               if((out = fopen(defpath, "w")) == NULL) {
+                       fprintf(stderr, "Can't create %s!!\n", defpath);
+                       done(1);
+               }
+               for(np = m_defs; np; np = np->n_next)
+                       fprintf(out, "%s: %s\n", np->n_name, np->n_field);
+               fclose(out);
+               signal(SIGINT, (int (*)()) save);
+               def_flags &= ~DEFMOD;
+       }
+}
diff --git a/docs/historical/2.9BSD/subs/makedir.c b/docs/historical/2.9BSD/subs/makedir.c
new file mode 100644 (file)
index 0000000..7f9c927
--- /dev/null
@@ -0,0 +1,28 @@
+#include "mh.h"
+#include <stdio.h>
+
+makedir(dir)
+{
+       register int i, pid, wpid;
+       register char *c;
+       int status;
+
+       if((pid = fork()) == 0) {
+               execl("/bin/mkdir", "mkdir", dir, 0);
+               execl("/usr/bin/mkdir", "mkdir", dir, 0);
+               fprintf(stderr, "Can't exec mkdir!!?\n");
+               return(0);
+       }
+       if(pid == -1) {
+               fprintf(stderr, "Can't fork\n");
+               return(0);
+       }
+       while((wpid = wait(&status)) != pid && wpid != -1) ;
+       if(status) {
+               fprintf(stderr, "Bad exit status (%o) from mkdir.\n", status);
+               return(0);
+       }
+       chmod(dir, ((c = m_find("folder-protect")) != NULL)?
+                  atooi(c) : atooi(foldprot));
+       return(1);
+}
diff --git a/docs/historical/2.9BSD/subs/makename.c b/docs/historical/2.9BSD/subs/makename.c
new file mode 100644 (file)
index 0000000..027c4d8
--- /dev/null
@@ -0,0 +1,19 @@
+#include "mh.h"
+#include <stdio.h>
+
+char *makename(prefix,suffix)
+char *prefix, *suffix;
+{
+       static char tmpname[15];
+       register char *cp1, *cp2;
+       register int pid;
+
+       pid = getpid();
+       cp1 = tmpname;
+       for (cp2 = prefix; *cp1++ = *cp2++; );
+       cp1--;
+       do *cp1++ = pid%10 + '0'; while (pid /= 10);
+       for (cp2 = suffix; *cp1++ = *cp2++; );
+       if (cp1 >= &tmpname[15]) error("strs too long to makename");
+       return (tmpname);
+}
diff --git a/docs/historical/2.9BSD/subs/peekc.c b/docs/historical/2.9BSD/subs/peekc.c
new file mode 100644 (file)
index 0000000..0f5cea0
--- /dev/null
@@ -0,0 +1,11 @@
+#include <stdio.h>
+
+peekc(ib)
+FILE *ib;
+{
+       register c;
+
+       c = getc(ib);
+       ungetc(c,ib);
+       return(c);
+}
diff --git a/docs/historical/2.9BSD/subs/pr_array.c b/docs/historical/2.9BSD/subs/pr_array.c
new file mode 100644 (file)
index 0000000..00fddab
--- /dev/null
@@ -0,0 +1,9 @@
+pr_array(cp,ap)
+char *cp,  **ap;
+{
+       register  int  i;
+
+       for(i=0;  *ap;  ap++,i++)
+               printf("%s[%d]=> %s\n", cp,i,*ap);
+}
+
diff --git a/docs/historical/2.9BSD/subs/printsw.c b/docs/historical/2.9BSD/subs/printsw.c
new file mode 100644 (file)
index 0000000..0b516e8
--- /dev/null
@@ -0,0 +1,26 @@
+#include "mh.h"
+
+printsw(substr, swp, prefix)
+char *substr, *prefix;
+struct swit *swp;
+{
+       char buf[128];
+       register char *cp, *cp1;
+       register int i;
+       int len;
+
+       len = strlen(substr);
+       for(; swp->sw; swp++)
+               if(!*substr ||                  /* null matches all strings */
+                  (ssequal(substr, swp->sw) && len >= swp->minchars))
+                       if(swp->minchars > 0) {
+                               cp = buf;
+                               *cp++ = '(';
+                               for(cp1 = swp->sw, i = 0; i < swp->minchars; i++)
+                                       *cp++ = *cp1++;
+                               *cp++ = ')';
+                               while(*cp++ = *cp1++);
+                               printf("  %s%s\n", prefix, buf);
+                       } else if(swp->minchars == 0)
+                               printf("  %s%s\n", prefix, swp->sw);
+}
diff --git a/docs/historical/2.9BSD/subs/putdate.c b/docs/historical/2.9BSD/subs/putdate.c
new file mode 100644 (file)
index 0000000..ad0b855
--- /dev/null
@@ -0,0 +1,65 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/timeb.h>
+#include <sys/time.h>
+
+/*
+ * Output the date in right format gotten from
+ * the passed ctime(3) format date.
+ * If the passed date is NULL, output the current
+ * date and time.
+ */
+
+putdate(timestr, out)
+       char *timestr;
+       register FILE *out;
+{
+       register char *t, *p, *cp;
+       char *timezone();
+       struct tm *tmp;
+       struct tm *localtime();
+       struct timeb tb;
+       long now;
+       int isdst;
+       char *asctime();
+       static char *str = "SunMonTueWedThuFriSat";
+       static char *daytag[] = {
+               "Sunday",
+               "Monday",
+               "Tuesday",
+               "Wednesday",
+               "Thursday",
+               "Friday",
+               "Saturday"
+       };
+
+       now = time((long *) 0);
+       tmp = localtime(&now);
+       isdst = tmp->tm_isdst;
+       if (timestr == 0)
+               timestr = asctime(tmp);
+       cp = str;
+       t = timestr;
+       while (*cp) {
+               if (strncmp(cp, t, 3) == 0)
+                       break;
+               cp += 3;
+       }
+       if (*cp)
+               cp = daytag[(cp - str) / 3];
+       else
+               cp = 0;
+       ftime(&tb);
+       /*
+        * This call to timezone() may be wrong:
+        * really need the tm_isdst whoever generated timestr.
+        */
+       p = timezone(tb.timezone, isdst);
+
+       if (cp == 0)
+               fprintf(out, "Date: %.2s %.3s %.4s %.2s%.2s-%.3s\n",
+                            t+8, t+4, t+20, t+11, t+14, p);
+       else
+               fprintf(out, "Date: %.2s %.3s %.4s %.2s%.2s-%.3s (%s)\n",
+                            t+8, t+4, t+20, t+11, t+14, p, cp);
+}
diff --git a/docs/historical/2.9BSD/subs/r1bindex.c b/docs/historical/2.9BSD/subs/r1bindex.c
new file mode 100644 (file)
index 0000000..2aa5447
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * r1bindex(str, chr) stands for Right plus 1 or Beginning index of
+ *      chr in str.  I.e. return ptr 1 past LAST occurance of chr in
+ *      str, OR beginning of the string if str doesn't contain chr.
+ */
+
+char *
+r1bindex(str, chr)
+register char *str;
+register int chr;
+{
+       register char *cp;
+
+       for(cp = str; *cp; cp++) ;
+       --cp;
+       while(cp >= str && *cp != chr)
+               --cp;
+       return ++cp;
+}
diff --git a/docs/historical/2.9BSD/subs/showfile.c b/docs/historical/2.9BSD/subs/showfile.c
new file mode 100644 (file)
index 0000000..c75c138
--- /dev/null
@@ -0,0 +1,37 @@
+#include "mh.h"
+#include <signal.h>
+#include <stdio.h>
+
+showfile(file)
+char *file;
+{
+       int pid, wpid, intr, status;
+       char *vec[4];
+
+       intr = (int) signal(SIGINT, SIG_IGN);
+       m_update();
+       fflush(stdout);
+       if((pid = fork()) == 0) {
+               vec[0] = "mh-type";
+               vec[1] = file;
+               vec[2] = 0;
+               signal(SIGINT, (int (*)()) intr);
+               execv(showproc, vec);
+               perror("Can't exec showproc");
+               goto badleave;
+       } else if(pid == -1) {
+               fprintf(stderr, "No forks!\n");
+               goto badleave;
+       } else
+               while((wpid = wait(&status)) != -1 && wpid != pid) ;
+       signal(SIGINT, (int (*)()) intr);
+       if(status & 0377)
+               goto badleave;
+       return(0);
+
+ badleave:
+       fflush(stdout);
+       return(1);
+
+}
+
diff --git a/docs/historical/2.9BSD/subs/smatch.c b/docs/historical/2.9BSD/subs/smatch.c
new file mode 100644 (file)
index 0000000..aa4a2d3
--- /dev/null
@@ -0,0 +1,34 @@
+#include "mh.h"
+
+/* switch match, or any unambiguous abbreviation */
+/* exact match always wins, even if shares same root */
+/* returns subscript in zero-terminated tbl[] of strings */
+/* returns -1 if no match, -2 if ambiguous */
+
+#define abs(i) (i < 0 ? -i : i)
+
+smatch(string, swp)
+char *string;
+struct swit *swp;
+{
+       register char *sp, *tcp;
+       struct swit *tp;
+       int firstone, stringlen;
+
+       firstone = -1;
+
+       for (stringlen = strlen(string), tp = swp; tcp = tp->sw; tp++) {
+               if(stringlen < abs(tp->minchars)) continue;      /* no match */
+               for (sp = string; *sp == *tcp++; ) {
+                       if (*sp++ == 0) return(tp-swp); /* exact match */
+               }
+               if (*sp != 0) {
+                       if (*sp != ' ') continue; /* no match */
+                       if (*--tcp == 0) return(tp-swp); /* exact match */
+               }
+               if (firstone == -1) firstone = tp-swp; /* possible match */
+               else firstone = -2;     /* ambiguous */
+       }
+
+       return (firstone);
+}
diff --git a/docs/historical/2.9BSD/subs/ssequal.c b/docs/historical/2.9BSD/subs/ssequal.c
new file mode 100644 (file)
index 0000000..124581c
--- /dev/null
@@ -0,0 +1,8 @@
+ssequal(substr, str)
+char *substr, *str;
+{
+       while(*substr)
+               if(*substr++ != *str++)
+                       return(0);
+       return(1);
+}
diff --git a/docs/historical/2.9BSD/subs/trimcpy.c b/docs/historical/2.9BSD/subs/trimcpy.c
new file mode 100644 (file)
index 0000000..eb7d5fe
--- /dev/null
@@ -0,0 +1,16 @@
+char *trimcpy(cp)
+register char *cp;
+{
+       register char *sp;
+
+       while(*cp == ' ' || *cp == '\t')
+               cp++;
+       sp = cp;
+       while(*sp)
+               if(*sp++ == '\n')
+                       break;
+       *--sp = 0;
+       sp = (char *) malloc(sp - cp + 1);
+       strcpy(sp, cp);
+       return(sp);
+}
diff --git a/docs/historical/2.9BSD/subs/type.c b/docs/historical/2.9BSD/subs/type.c
new file mode 100644 (file)
index 0000000..31c800b
--- /dev/null
@@ -0,0 +1,10 @@
+type(ch, s)
+char *s;
+{
+       register char *p;
+
+       for (p = s; *p++; );
+       --p;
+       write(ch, s, p-s);
+       return(p-s);
+}
diff --git a/docs/historical/2.9BSD/subs/uleq.c b/docs/historical/2.9BSD/subs/uleq.c
new file mode 100644 (file)
index 0000000..663adcd
--- /dev/null
@@ -0,0 +1,12 @@
+uleq(c1, c2)
+register char *c1, *c2;
+{
+       register int c;
+
+       while(c = *c1++)
+               if((c|040) != (*c2|040))
+                       return(0);
+               else
+                       c2++;
+       return(*c2 == 0);
+}
diff --git a/docs/historical/2.9BSD/support/components b/docs/historical/2.9BSD/support/components
new file mode 100644 (file)
index 0000000..657e5dd
--- /dev/null
@@ -0,0 +1,4 @@
+To: 
+Cc: 
+Subject: 
+-------
diff --git a/docs/historical/2.9BSD/support/distcomps b/docs/historical/2.9BSD/support/distcomps
new file mode 100644 (file)
index 0000000..b3415f9
--- /dev/null
@@ -0,0 +1,2 @@
+Distribution-to:
+Distribution-cc:
diff --git a/docs/historical/2.9BSD/support/l.c b/docs/historical/2.9BSD/support/l.c
new file mode 100644 (file)
index 0000000..2f7b8d2
--- /dev/null
@@ -0,0 +1,259 @@
+/* Rewrite for VAX: BSB 9/9/79 */
+/* Compiled with V7 cc: BSB 6/2/79 */
+
+#include <stdio.h>
+#include <sgtty.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <sys/types.h>
+#include <stat.h>
+
+#define CLEARPAGE write(2,"\014\000",2);
+#define PAUSE  0
+#define NOTIFY 1
+#define CLEAR  2
+#define NOTICLEAR 3
+
+int spage = 37;
+int page;
+short int width = 79;
+short int noclr = 0;
+short int first = 0;
+short int numop = 0;
+short int flagctl = 1;
+short int ontty = 1;    /* assume we're outputting to a tty     */
+short int delflg;       /* a <DEL> was typed.                   */
+
+FILE *fin;
+jmp_buf envir;
+
+main(argc, argv)
+int argc;
+char *argv[];
+{
+       register int i,k,n;
+       register char *c1, *c2;
+       int j, clrflag;
+       int int2(), getout();
+       struct sgttyb sg;
+       struct stat st;
+       extern char _sibuf[], _sobuf[];
+
+       if(gtty(1, &sg) == -1) {
+               ontty = 0;
+               flagctl = 0;
+       }
+       c1 = c2 = argv[0];
+       do
+               if(*c1++ == '/')
+                       c2 = c1;
+       while(*c1);
+       if(*c2 == 'c')
+               noclr++;
+       k=0;
+       for( i=1; i<argc; i++ ) {/* look for - args */
+               if(argv[i][0] == '-' ) {
+                       switch( argv[i][1] ) {
+                               case 'c': noclr++; break;
+                               case 'f': first=num(&argv[i][2]); /* set first line */
+                                         break;
+                               case 'n': numop=1; /* set number option */
+                                         break;
+                               case 'l':
+                               case 'p': spage =num(&argv[i][2]); /* set page size */
+                                         break;
+                               case 'w': width =num(&argv[i][2]);
+                                         break;
+                               case 'x': flagctl = flagctl? 0 : 1;
+                                         break;
+                               default:  printf("Unknown switch: %s\n", argv[i]);
+                                         return;
+                       }
+               } else
+                       argv[k++] = argv[i];
+       }
+
+       if (spage<=0)
+               spage = 0x07fffffff;    /* largest positive number! */
+       setbuf(stdout, _sobuf);
+       if(ontty)
+               signal(SIGINT,int2);
+       signal(SIGQUIT,getout);
+       page = spage;
+       if(k == 0) {                    /* filter */
+               if(!setjmp(envir)) {
+                       fin = stdin;
+                       setbuf(fin, _sibuf);
+                       pfile(0);
+               }
+               getout();
+       }
+       j = 0;
+       setjmp(envir);
+       while((i=j++) < k) {
+               page = spage;
+               clrflag = 0;
+               if(fin != NULL) { fclose(fin); fin = NULL; }
+               if(stat(argv[i], &st) == 0 && (st.st_mode&S_IFMT) == S_IFDIR){
+                       printf("%s: Is a directory!\n", argv[i]);
+                       continue;
+               }
+               if((fin = fopen(argv[i],"r")) == NULL) {
+                       printf("Cannot open \"%s\" for reading!\n", argv[i]);
+                       continue;
+               }
+               if(st.st_size == 0) {
+                       printf("File \"%s\" is empty.\n", argv[i]);
+                       continue;
+               }
+               if(k>1) {
+                   if(i && delflg <= 0)
+                       printf("\n\n");
+                   delflg = 0;
+                   if(ontty) {
+                       printf("Press <RETURN> to list \"%s\"\n", argv[i]);
+                       clrflag = 1;
+                   } else
+                       printf(">>>>> File \"%s\"\n", argv[i]);
+               }
+
+               pfile(clrflag);
+       }
+       getout();
+}
+
+int  linpos, line, ct;
+
+pfile(flg)
+{
+       register int c;
+
+       if(flg) nextpage(NOTICLEAR);
+       else if(!noclr && ontty)
+               CLEARPAGE;
+       delflg = -1;
+       line = 1;
+       ct = page;
+       while (line < first)  /* Dcrocker: skip to first line */
+               if((c = getch()) == EOF)
+                       return;
+               else if(c == '\n')
+                       line++;
+       linpos = 0;
+
+       while ((c = getch()) != EOF)
+               putch(c);
+
+       fflush(stdout);
+}
+
+num(s)  /* computes the internal form of a number */
+register char *s;       /* bad chars are ignored */
+{
+       register int c, i, sign;
+
+       sign=1;  i=0;
+       while(c = *s++) {
+               if(c=='-' && sign==1) sign = -1;
+               c -= '0';
+               if(c>=0 && c<=9) i=i*10+c;
+       }
+       return(i*sign);
+}
+
+nextpage (clearpage)
+{       char c;
+
+       if(!ontty)
+               return;
+       if (clearpage & NOTIFY)
+               putchar('\007');
+       fflush(stdout);
+       c = 0;
+       while(read(2, &c, 1) && c != '\n') ;
+       if (clearpage & CLEAR && c) {
+               CLEARPAGE;
+               page = spage;
+       } else {
+               page = (spage>>1) + (spage>>3);
+/***            page = spage * .6;              ***/
+       }
+       return;
+}
+
+int2()
+{
+       signal(SIGINT,int2);
+       stdout->_cnt = BUFSIZ;
+       stdout->_ptr = stdout->_base;
+       if(delflg)
+               putchar('\n');
+       delflg++;
+       longjmp(envir, 1);
+}
+
+int     peekc = -2;
+
+peekch()
+{
+       return(peekc = getch());
+}
+
+getch()
+{
+       register int c;
+       static word;
+
+       if(peekc != -2) {
+               c = peekc;
+               peekc = -2;
+               return(c);
+       };
+       c = getc(fin);
+       if(c != EOF)
+               c &= 0177;
+       return(c);
+}
+
+putch(c)
+register int c;
+{
+               if(linpos == 0 && numop) {
+                       printf("%-5d | ");
+                       linpos += 8;
+               }
+               if(c < 040 || c == 0177) switch(c) {
+                       case '\n': line++;
+                                  linpos = -1;
+                                  break;
+                       case 014:  goto npage;
+                       case 011:  linpos += 8;
+                                  linpos &= ~07;
+                                  linpos--;
+                                  break;
+                       default:   if(flagctl) {
+                                       if(c == '\7')
+                                           putchar(c);
+                                       putch('^');
+                                       if(c != 0177)
+                                           c += '@';
+                                       else
+                                           c = 'd';
+                                  }
+               }
+               putchar(c);
+               linpos++;
+               if(width && linpos >= width && peekch() != '\n') {
+                       putchar('\n'); linpos = 0;
+               }
+               if(linpos == 0 && --ct <= 0) {
+          npage:       nextpage(NOTICLEAR);
+                       ct = page;
+               }
+}
+
+
+getout()
+{
+       exit(0);
+}
diff --git a/docs/historical/2.9BSD/support/news-1char b/docs/historical/2.9BSD/support/news-1char
new file mode 100755 (executable)
index 0000000..0519ecb
--- /dev/null
@@ -0,0 +1 @@
\ No newline at end of file
diff --git a/docs/historical/2.9BSD/support/news-mh_receiv b/docs/historical/2.9BSD/support/news-mh_receiv
new file mode 100755 (executable)
index 0000000..8f7d436
--- /dev/null
@@ -0,0 +1,8 @@
+F=`grep '[Tt][Oo]:' $1 | sed 's/[Tt][Oo]:.*news\.//p'`
+if [ -d /usr/mhnews/$F ] ; then
+       cat /usr/mhnews/.1char >> /usr/mhnews/.$F
+       /usr/new/mh/file -link -file $1 +$F
+else
+       echo Unknown News Category: $F
+       exit 1
+fi
index 6828e3173185381f84df44e1ff6493c10292cc0f..ba59a7325211382f8d2eb3c41419d36fba5db755 100644 (file)
@@ -1,3 +1,5 @@
+This directory
+--------------
 The most recent versions of the documents in this directory were
 downloaded from ftp://ftp.vim.org/pub/mail/mh/doc/
 
@@ -14,16 +16,52 @@ were downloaded from ftp://munnari.oz.au/pub/mh/doc/
 designOfMH.pdf was downloaded from
 http://www.dtic.mil/cgi-bin/GetTRDoc?AD=ADA257836
 
-mh-6.8.5/ contains the entire MH 6.8.5, include source code and
-RCS files, and was downloaded from
+
+Subdirectories
+--------------
+SRI-NOSC/ was downloaded from from Warren Toomey's minnie.tuhs.org using:
+  rsync -avz minnie.tuhs.org::UA_Distributions/Early_Networking/NOSC/ NOSC
+  tar xzBpf NOSC/nosc.tar.gz ./mh
+  cp -p NOSC/nosc.txt mh
+  chmod -R go+r mh
+  chmod go+x mh mh/subs.dir
+  find mh -name '*.[ao]' -execdir /bin/rm {} \;
+
+2.9BSD/ was downloaded from from Warren Toomey's minnie.tuhs.org using:
+  rsync -avz minnie.tuhs.org::UA_Distributions/UCB/2.9BSD/ 2.9BSD
+  tar xzBpf usr.tar.gz ./contrib/mh
+  chmod g-w contrib/mh/Makefile
+
+mh-jun-1982/ was downloaded from
+http://bitsavers.trailing-edge.com/bits/Rand/Rand_Software_Distribution_1.7_May82.zip
+
+mh-nov-1983/ was downloaded from
+http://www.tuhs.org/Archive/Distributions/UCB/4.2BSD/new.tar.gz
+
+Other versions of MH are, as of May 2019, available at these locations:
+mh-6.4              http://www.tuhs.org/Archive/Distributions/UCB/4.3BSD/new.tar.gz
+mh-6.5-4.3BSD-Tahoe http://www.tuhs.org/Archive/Distributions/UCB/4.3BSD-Tahoe/new.tar.gz
+mh-6.5-4.3BSD-Reno  http://www.tuhs.org/Archive/Distributions/UCB/4.3BSD-Reno/contrib.tar.gz
+mh-6.8              https://stuff.mit.edu/afs/athena/astaff/source/src-7.7/third/supported/mh.6.8/
+
+mh-6.8.5/ contains the entire MH 6.8.5 sources and RCS files, and was
+downloaded from
 http://iweb.dl.sourceforge.net/project/rand-mh/MH/6.8.5/mh-6.8.5.tgz
-Some obviously unnecessary files were removed.  mh.rf and mh.me
-were renamed to mh-intro.rf and mh-intro.me, respectively, to avoid
-name clashes with other files on case-insensitive file systems.
+Some obviously unnecessary files were removed.  mh.rf and mh.me were
+renamed to mh-intro.rf and mh-intro.me, respectively, to avoid name
+clashes with other files on case-insensitive file systems.
 
-MH source code, versions 6.3 through 6.8.5, is archived under
+
+Other repositories
+------------------
+MH source code, versions 5 through 6.8.5, is archived under
 http://sourceforge.net/projects/rand-mh/files/
+That repository contains other useful MH artifacts including
+the Jerry Peek's MH Book and mailing list archives.
+
 
+-------------------------------------------------------------------------------
+-------------------------------------------------------------------------------
 
 The README below is retained in its original form for posterity.  All
 of the txt (.doc and .tty) files have been renamed to .txt.  All of
@@ -31,8 +69,8 @@ the postscript (.ps) files have been converted to pdf using ps2pdf.
 
 D. Levine  28 Feb 2012
 
-------------------------------------------------------------------------
-------------------------------------------------------------------------
+-------------------------------------------------------------------------------
+-------------------------------------------------------------------------------
 
 mh/doc/README
 
@@ -52,7 +90,7 @@ Postscript versions are also available:
   changes.ps   - Changes from MH 6.6 to MH 6.8
   mh-gen.ps    - The "READ-ME" file - how to generate MH (aka mh-gen(8))
 
-------------------------------------------------------------------------
+-------------------------------------------------------------------------------
 
 These are postscript conversions of the MH papers which were written
 using the TeX typesetting language:
@@ -81,7 +119,7 @@ intosh, and printing them on a Laserwriter.  If you are able to generate
 copies of these papers which will print (identically to the originals or
 otherwise) on a Laserwriter, please contact "Bug-MH@ICS.UCI.EDU".
 
-------------------------------------------------------------------------
+-------------------------------------------------------------------------------
 
 These files are tty-readable conversions of the MH papers which were
 written using the TeX typesetting language:
diff --git a/docs/historical/SRI-NOSC/annotate.c b/docs/historical/SRI-NOSC/annotate.c
new file mode 100644 (file)
index 0000000..238068f
--- /dev/null
@@ -0,0 +1,107 @@
+#include "mh.h"
+#include "stat.h"
+
+/* annotate file component data
+ *
+ * prepends   Component: data
+ *              date stamp
+ */
+
+/*extern int inplace;*/            /* preserve links in anno */
+int inplace 1;                     /* preserve links in anno */
+
+annotate(file, comp, text)
+char *file, *comp, *text;
+{
+       register int src, tmp;
+       register char *cp;
+       int cnt;
+       char buf[512], *sp, tmpfil[128];
+       long now;
+       struct inode stbuf;
+
+       if((src = open((cp = file), 2)) == -1) { /* this should be an X-open*/
+               printf("Can't open "); flush();
+               perror(cp);
+               return(1);
+       }
+       copy(cp, buf);
+       sp = cp = buf;
+       while(*cp) if(*cp++ == '/') sp = cp;
+       if(sp != buf) {
+               *sp = 0;
+               cp = copy(buf, tmpfil);
+       } else
+               cp = tmpfil;
+       copy(makename("annot",".tmp"), cp);
+       fstat(src, &stbuf);
+       if((tmp = creat(tmpfil, stbuf.i_mode&0777)) == -1) {
+               printf("Can't create "); flush();
+               perror(tmpfil);
+               return(1);
+       }
+       cp = comp;
+       if(*cp >= 'a' && *cp <= 'z') *cp =- 040;
+       type(tmp, cp);
+       type(tmp, ": ");
+       time(&now);
+       cp = cdate(&now);
+       cp[9] = ' ';  cp[15] = 0;
+       if(*cp == ' ') cp++;
+       type(tmp, "<<");
+       type(tmp, cp);
+       type(tmp, ">>\n");
+       cp = text;
+       do {
+               if(*cp == ' ' || *cp == '\t') cp++;
+               sp = cp;
+               while(*cp && *cp++ != '\n') ;
+               if(cp - sp) {
+                       type(tmp, comp);
+                       type(tmp, ": ");
+                       write(tmp, sp, cp-sp);
+               }
+       } while(*cp);
+       if(cp[-1] != '\n' && cp != text) type(tmp, "\n");
+       do
+               if((cnt = read(src, buf, sizeof buf)) > 0)
+                       write(tmp, buf, cnt);
+       while(cnt == sizeof buf);
+       if(inplace) {
+               close(tmp);
+               tmp = open(tmpfil, 0);          /* reopen for reading */
+               seek(src, 0, 0);
+               do
+                       if((cnt = read(tmp, buf, sizeof buf)) > 0)
+                               write(src, buf, cnt);
+               while(cnt == sizeof buf);
+       } else {
+          /*   cp = copy(file, buf);           */
+          /*   *--cp =| 0200;                  */
+          /*   copy(".bak", copy(file, buf));  */
+               cp = copy(file, buf);
+               cp[1] = 0;
+               do
+                       *cp = cp[-1];
+               while(--cp >= buf && *cp != '/');
+               *++cp = ',';                    /* New backup convention */
+               unlink(buf);
+               if(link(file, buf) == -1) {
+                       printf("Can't rename %s to bak file.\n", file);
+                       return(1);
+               }
+               if(unlink(file) == -1) {
+                       printf("Can't unlink %s\n", file);
+                       return(1);
+               }
+               if(link(tmpfil, file) == -1) {
+                       printf("Can't lnk temp file \"%s\" to %s\n",
+                         tmpfil, file);
+                       return(1);
+               }
+       }
+       close(src);
+       close(tmp);
+       unlink(tmpfil);
+       return(0);
+}
diff --git a/docs/historical/SRI-NOSC/delete.c b/docs/historical/SRI-NOSC/delete.c
new file mode 100644 (file)
index 0000000..879ed93
--- /dev/null
@@ -0,0 +1,123 @@
+/* formerly rmm */
+#include "mh.h"
+
+int vecp, *vec[MAXARGS], fout;
+struct msgs *mp;
+struct swit switches[] {
+       "all",         -3,      /* 0 */
+       "help",         4,      /* 1 */
+       0,              0
+};
+
+main(argc, argv)
+char *argv[];
+{
+       char *folder, *nfolder, *maildir, *msgs[100], buf[32];
+       register int msgnum;
+       register char *cp, *sp;
+       int msgp;
+       char *ap, *inp;
+       char *arguments[50], **argp;
+
+       fout = dup(1);
+#ifdef NEWS
+       m_news();
+#endif
+       folder = msgp = 0;
+       vecp = 1;
+       inp = cp = argv[0];
+       while(*cp)
+               if(*cp++ == '/')
+                       inp = cp;
+       ap = inp;
+       if((cp = m_find(ap)) != -1) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                       /* unknown */
+                       case -1:printf("-%s unknown\n", cp);
+                               goto leave;
+                                                        /* -all */
+                       case 0: printf("\"-all\" changed to \"all\"\n");
+                               goto leave;
+                                                       /* -help */
+                       case 1: help(concat( inp, " [+folder] [msgs] [switches]", 0),
+                                    switches);
+                               goto leave;
+                       }
+               if(*cp == '+')  {
+                       if(folder) {
+                               printf("Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               folder = cp + 1;
+               } else
+                       msgs[msgp++] = cp;
+       }
+       if(!msgp)
+               msgs[msgp++] = "cur";
+       if(!folder)
+               folder = m_getfolder();
+       maildir = m_maildir(folder);
+       if(chdir(maildir) < 0) {
+               printf("Can't chdir to: "); flush();
+               perror(maildir);
+               goto leave;
+       }
+       if(!(mp = m_gmsg(folder))) {
+               printf("Can't read folder!?\n");
+               goto leave;
+       }
+       if(mp->hghmsg == 0) {
+               printf("No messages in \"%s\".\n", folder);
+               goto leave;
+       }
+       for(msgnum = 0; msgnum < msgp; msgnum++)
+               if(!m_convert(msgs[msgnum], UNDELETED, UNDELETED))
+                       goto leave;
+       if(mp->numsel == 0) {
+               goto leave;
+       }
+       m_replace("folder", folder);
+       if((cp = m_find("delete-prog")) == -1) {
+               for(msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
+                       if(mp->msgstats[msgnum] & SELECTED) {
+                               sp = getcpy(m_name(msgnum));
+                               cp = copy(sp, buf);
+                               cp[1] = 0;
+                               do
+                                       *cp = cp[-1];
+                               while(--cp >= buf && *cp != '/');
+                               *++cp = ',';            /* backup convention */
+                               unlink(buf);
+                               if(link(sp, buf) == -1 || unlink(sp) == -1)
+                                       printf("Can't rename %s to %s.\n", sp, buf);
+                       }
+       } else {
+               if(mp->numsel > MAXARGS-2) {
+  printf("More than %d messages for deletion-prog\n",MAXARGS-2);
+                       goto leave;
+               }
+               for(msgnum= mp->lowsel; msgnum<= mp->hghsel; msgnum++)
+                       if(mp->msgstats[msgnum]&SELECTED)
+                               vec[vecp++] = getcpy(m_name(msgnum));
+               vec[vecp] = 0;
+               vec[0] = cp;
+               m_update();
+               flush();
+               execvsrh(vec);
+               printf("Can't exec deletion prog--"); flush();
+               perror(cp);
+       }
+leave:
+       m_update();
+       flush();
+}
diff --git a/docs/historical/SRI-NOSC/delete.run b/docs/historical/SRI-NOSC/delete.run
new file mode 100644 (file)
index 0000000..1426cd7
--- /dev/null
@@ -0,0 +1,5 @@
+if -r delete rm delete
+load -n delete subs.a strings.a wait -O libg.a libh.a libg.a
+if -r a.out mv a.out delete
+:                                      fini
+
diff --git a/docs/historical/SRI-NOSC/errlst b/docs/historical/SRI-NOSC/errlst
new file mode 100644 (file)
index 0000000..fa8407c
--- /dev/null
@@ -0,0 +1 @@
+cc -n send.o subs.a strings-ec.a libg.a libh.a mailib.a mailib.a 
diff --git a/docs/historical/SRI-NOSC/errors.h b/docs/historical/SRI-NOSC/errors.h
new file mode 100644 (file)
index 0000000..68f6933
--- /dev/null
@@ -0,0 +1,41 @@
+#
+/* u_error codes */
+#define        EFAULT  106
+#define        EPERM   1
+#define        ENOENT  2
+#define        ESRCH   3
+#define        EINTR   4
+#define        EIO     5
+#define        ENXIO   6
+#define        E2BIG   7
+#define        ENOEXEC 8
+#define        EBADF   9
+#define        ECHILD  10
+#define        EAGAIN  11
+#define        ENOMEM  12
+#define        EACCES  13
+#define        ENOTBLK 15
+#define        EBUSY   16
+#define        EEXIST  17
+#define        EXDEV   18
+#define        ENODEV  19
+#define        ENOTDIR 20
+#define        EISDIR  21
+#define        EINVAL  22
+#define        ENFILE  23
+#define        EMFILE  24
+#define        ENOTTY  25
+#define        ETXTBSY 26
+#define        EFBIG   27
+#define        ENOSPC  28
+#define        ESPIPE  29
+#define        EROFS   30
+#define        EMLINK  31
+#define        EPIPE   32
+
+/* Harvard error codes */
+
+#define        EPLIM   99      /* process limit reached */
+#define        EPROTO  98      /* Protocol error */
+
+int errno;             /* where c saves the error code */
diff --git a/docs/historical/SRI-NOSC/file.c b/docs/historical/SRI-NOSC/file.c
new file mode 100644 (file)
index 0000000..f0429e3
--- /dev/null
@@ -0,0 +1,275 @@
+#include "mh.h"
+#include "stat.h"
+#include "errors.h"
+#define NFOLD 20                /* Allow 20 folder specs */
+
+/* file [-src folder] [msgs] +folder [+folder ...]
+ *
+ * moves messages from src folder (or current) to other one(s).
+ *
+ *  all = first-last for a message sequence
+ *  -preserve says preserve msg numbers
+ *  -link says don't delete old msg
+ */
+
+char *anoyes[];         /* Std no/yes gans array        */
+
+int fout, vecp, foldp, prsrvf;
+char *vec[MAXARGS], maildir[128], *folder;
+struct msgs *mp;
+
+struct st_fold {
+       char *f_name;
+       struct msgs *f_mp;
+} folders[NFOLD];
+
+struct swit switches[] {
+       "all",           -3,      /* 0 */
+       "link",           0,      /* 1 */
+       "nolink",         0,      /* 2 */
+       "preserve",       0,      /* 3 */
+       "nopreserve",     0,      /* 4 */
+       "src +folder",    0,      /* 5 */
+       "help",           4,      /* 6 */
+       0,                0
+};
+main(argc, argv)
+char *argv[];
+{
+       register int i, msgnum;
+       register char *cp;
+       char *msgs[128];
+       int msgp, linkf;
+       char *ap;
+       char *arguments[50], **argp;
+
+       fout = dup(1);
+       if(argc < 2) {
+ badarg:    printf("Usage: file [-src folder] [msg ...] +folder [+folder]\n");
+           goto leave;
+       }
+#ifdef NEWS
+       m_news();
+#endif
+       folder = msgp = linkf = 0;
+       vecp = 1;
+       ap = cp = argv[0];
+       while(*cp)
+               if(*cp++ == '/')
+                       ap = cp;
+       if((cp = m_find(ap)) != -1) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                       /* unknown */
+                       case -1:printf("file: -%s unknown\n", cp);
+                               goto leave;
+                                                      /* -all */
+                       case 0: printf("\"-all\" changed to \"all\"\n");
+                               goto leave;
+                       case 1: linkf = 1;  continue;  /* -link */
+                       case 2: linkf = 0;  continue;  /* -nolink */
+                       case 3: prsrvf = 1;  continue; /* -preserve */
+                       case 4: prsrvf = 0;  continue; /* -nopreserve */
+                       case 5: if(folder) {           /* -src */
+                                       printf("Only one src folder.\n");
+                                       goto leave;
+                               }
+                               if(!(folder = *argp++) || *folder == '-') {
+               printf("file: Missing argument for %s switch\n", argp[-2]);
+                                       goto leave;
+                               }
+                               if(*folder == '+')
+                                       folder++;
+                               continue;
+                                                       /* -help */
+                       case 6: help("file   [msgs] [switches]  +folder ...",
+                                    switches);
+                               goto leave;
+                       }
+               if(*cp == '+')  {
+                       if(foldp < NFOLD)
+                               folders[foldp++].f_name = cp + 1;
+                       else {
+                               printf("Only %d folders allowed.\n", NFOLD);
+                               goto leave;
+                       }
+               } else
+                       msgs[msgp++] = cp;
+       }
+       if(!foldp) {
+               printf("No folder specified.\n");
+               goto badarg;
+       }
+       if(!msgp)
+               msgs[msgp++] = "cur";
+       if(!folder)
+               folder = m_getfolder();
+       copy(m_maildir(folder), maildir);
+       if(chdir(maildir) < 0) {
+               printf("Can't chdir to: "); flush();
+               perror(maildir);
+               goto leave;
+       }
+       if(!(mp = m_gmsg(folder))) {
+               printf("Can't read folder %s!?\n",folder);
+               goto leave;
+       }
+       if(mp->hghmsg == 0) {
+               printf("No messages in \"%s\".\n", folder);
+               goto leave;
+       }
+       for(msgnum = 0; msgnum < msgp; msgnum++)
+               if(!m_convert((cp = msgs[msgnum]), UNDELETED, UNDELETED))
+                       goto leave;
+       if(mp->numsel == 0) {
+               printf("No undeleted messages specified\n");       
+               goto leave;
+       }
+       m_replace("folder", folder);
+       if(mp->hghsel != mp->curmsg && ((mp->numsel != mp->nummsg) || linkf))
+               m_setcur(mp->hghsel);
+       if(opnfolds())
+               goto leave;
+       for(msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
+               if(mp->msgstats[msgnum] & SELECTED)
+                       if(process(getcpy(m_name(msgnum))))
+                               goto leave;
+       if(!linkf) {
+               if((cp = m_find("delete-prog")) != -1) {
+                       if(mp->numsel > MAXARGS-2) {
+         printf("file: more than %d messages for deletion-prog\n",MAXARGS-2);
+                               printf("[messages not unlinked]\n");
+                               goto leave;
+                       }
+                       for(msgnum= mp->lowsel; msgnum<= mp->hghsel; msgnum++)
+                               if(mp->msgstats[msgnum]&SELECTED)
+                                       vec[vecp++] = getcpy(m_name(msgnum));
+                       vec[vecp] = 0;
+                       m_update();
+                       flush();
+                       vec[0] = cp;
+                       execvsrh(vec);
+                       printf("Can't exec deletion-prog--"); flush();
+                       perror(cp);
+               } else {
+                       for(msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
+                               if(mp->msgstats[msgnum] & SELECTED)
+                                       if(unlink(cp = getcpy(m_name(msgnum)))== -1) {
+                                               printf("Can't unlink %s:",folder);
+                                               flush(); perror(cp);
+                                       }
+               }
+       }
+leave:
+       m_update();
+       flush();
+}
+
+
+opnfolds()
+{
+       register int i;
+       register char *cp;
+       char nmaildir[128];
+       struct inode stbuf;
+
+       for(i = 0; i < foldp; i++) {
+               copy(m_maildir(folders[i].f_name), nmaildir);
+               if(stat(nmaildir, &stbuf) < 0) {
+                       cp = concat("Create folder \"", nmaildir, "\"? ", 0);
+                       if(!gans(cp, anoyes))
+                               goto bad;
+                       free(cp);
+                       if(!makedir(nmaildir)) {
+                               printf("Can't create folder.\n");
+                               goto bad;
+                       }
+               }
+               if(chdir(nmaildir) < 0) {
+                       printf("Can't chdir to: "); flush();
+                       perror(nmaildir);
+                       goto bad;
+               }
+               if(!(folders[i].f_mp = m_gmsg())) {
+                       printf("Can't read folder %s\n", folders[i].f_name);
+                       goto bad;
+               }
+       }
+       chdir(maildir);         /* return to src folder */
+       return(0);
+bad:
+       return(1);
+}
+
+
+process(msg)
+{
+       char newmsg[256], buf[512];
+       register int i;
+       register char *nmsg;
+       register struct st_fold *fp;
+       struct inode stbuf, stbf1;
+       int n, o;
+
+    for(fp = folders; fp < &folders[foldp]; fp++) {
+       if(prsrvf)
+               nmsg = msg;
+       else
+               nmsg = m_name(fp->f_mp->hghmsg++ + 1);
+       copy(nmsg, copy("/", copy(m_maildir(fp->f_name), newmsg)));
+       if(link(msg, newmsg) < 0) {
+               if(errno == EEXIST ||
+                 (errno == EXDEV && stat(newmsg, &stbuf) != -1)) {
+                       if(errno != EEXIST || stat(msg, &stbf1) < 0 ||
+                          stat(newmsg, &stbuf) < 0 ||
+                          stbf1.i_number != stbuf.i_number) {
+                               printf("Message %s:%s already exists.\n",
+                                    fp->f_name, msg);
+                               return(1);
+                       }
+                       continue;
+               }
+               if(errno == EXDEV) {
+                       if((o = open(msg, 0)) == -1) {
+                               printf("Can't open %s:%s.\n",
+                                       folder, msg);
+                               return(1);
+                       }
+                       fstat(o, &stbuf);
+                       if((n = creat(newmsg, stbuf.i_mode&0777)) == -1) {
+                               printf("Can't create %s:%s.\n",
+                                       fp->f_name, nmsg);
+                               close(o);
+                               return(1);
+                       }
+                       do
+                               if((i=read(o, buf, sizeof buf)) < 0 ||
+                                 write(n, buf, i) == -1) {
+                                   printf("Copy error on %s:%s to %s:%s!\n",
+                                           folder, msg, fp->f_name, nmsg);
+                                   close(o); close(n);
+                                   return(1);
+                               }
+                       while(i == sizeof buf);
+                       close(n); close(o);
+               } else {
+                       printf("Error on link %s:%s to %s:",
+                           folder, msg, fp->f_name);
+                       flush();
+                       perror(nmsg);
+                       return(1);
+               }
+       }
+cont:   ;
+    }
+    return(0);
+}
diff --git a/docs/historical/SRI-NOSC/file.run b/docs/historical/SRI-NOSC/file.run
new file mode 100644 (file)
index 0000000..f5c8734
--- /dev/null
@@ -0,0 +1,3 @@
+if -r file rm file
+load -n file subs.a strings.a wait -O libg.a libh.a
+if -r a.out mv a.out file
diff --git a/docs/historical/SRI-NOSC/forward.c b/docs/historical/SRI-NOSC/forward.c
new file mode 100644 (file)
index 0000000..b27a68b
--- /dev/null
@@ -0,0 +1,314 @@
+/* formerly forw */
+#include "mh.h"
+#include "iobuf.h"
+#include "signals.h"
+
+/*#define TEST 1*/
+
+char    draft[],
+       components[],
+       stdcomps[],
+       sysed[],
+#ifdef PROMPT
+       prmtproc[],
+#endif
+       sndproc[];
+
+int *vec[MAXARGS], fout;
+struct msgs *mp;
+char drft[128];
+
+char    *anysh[] {
+       "no",   0,
+       "yes",  0,
+       "show", 0,
+       0,
+};
+
+char    *anyv[] {
+       "no",           0,
+       "yes",          0,
+       "verbose",      0,
+       0,
+};
+struct swit switches[] {
+       "all",               -3,      /* 0 */
+       "annotate",           0,      /* 1 */
+       "noannotate",         0,      /* 2 */
+       "editor editor",      0,      /* 3 */
+       "form formfile",      0,      /* 4 */
+       "help",               4,      /* 5 */
+       0,                    0
+};
+
+main(argc, argv)
+char *argv[];
+{
+       char *folder, *maildir, *msgs[100], *ed, *form;
+       register int msgnum;
+       register char *cp, *ap;
+       char *inp;
+       int msgp, status, anot;
+       int in, out, intr;
+       char *arguments[50], **argp;
+
+       fout = dup(1);
+#ifdef NEWS
+       m_news();
+#endif
+       form = anot = folder = msgp = ed = 0;
+       ap = cp = argv[0];
+       while(*cp)
+               if(*cp++ == '/')
+                       ap = cp;
+       inp = ap;
+       if((cp = m_find(ap)) != -1) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                            /* unknown */
+                       case -1:printf("-%s unknown\n", cp);
+                               goto leave;
+                                                            /* -all */
+                       case 0: printf("\"-all\" changed to \"all\"\n");
+                               goto leave;
+                       case 1: anot = 1;  continue;         /* -annotate */
+                       case 2: anot = 0;  continue;         /* -noannotate */
+                       case 3: if(!(ed = *argp++)) {        /* -editor */
+      missing:  printf("Missing argument for %s switch\n", argp[-2]);
+                                       goto leave;
+                               }
+                               continue;
+                       case 4: if(!(form = *argp++))        /* -form */
+                                       goto missing;
+                               continue;
+                                                            /* -help */
+                       case 5: help(concat( inp, " [+folder] [msgs] [switches]", 0),
+                                    switches);
+                               goto leave;
+                       }
+               if(*cp == '+') {
+                       if(folder) {
+                               printf("Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               folder = cp + 1;
+               } else
+                       msgs[msgp++] = cp;
+       }
+       if(!msgp)
+               msgs[msgp++] = "cur";
+       if(!folder)
+               folder = m_getfolder();
+       maildir = m_maildir(folder);
+       if(chdir(maildir) < 0) {
+               printf("Can't chdir to: "); flush();
+               perror(maildir);
+               goto leave;
+       }
+       if(!(mp = m_gmsg(folder))) {
+               printf("Can't read folder!?\n");
+               goto leave;
+       }
+       if(mp->hghmsg == 0) {
+               printf("No messages in \"%s\".\n", folder);
+               goto leave;
+       }
+       for(msgnum = 0; msgnum < msgp; msgnum++)
+               if(!m_convert(msgs[msgnum], UNDELETED, UNDELETED))
+                       goto leave;
+       if(mp->numsel == 0) {
+               printf("No undeleted messages specified\n");
+               goto leave;
+       }
+       if(form) {
+               if((in = open(m_maildir(form), 0)) < 0) {
+                       printf("Can't open form file: %s\n", form);
+                       goto leave;
+               }
+       } else if((in = open(m_maildir(components), 0)) < 0 &&
+                  (in = open(stdcomps, 0)) < 0) {
+                       printf("Can't open default components file!!\n");
+                       goto leave;
+       }
+       copy(m_maildir(draft), drft);
+       if((out = open(drft, 0)) >= 0) {
+/*
+               if(!fdcompare(in, out)) {
+                       cp = concat("\"", drft, "\" exists; Delete? ", 0);
+                       while((msgnum = gans(cp, anysh)) == 2)
+                               showfile(drft);
+                       if(!msgnum)
+                               return;
+               }
+*/
+               close(out);
+       }
+       if((out = creat(drft, m_gmprot())) < 0) {
+               printf("Can't create \"%s\"\n", drft);
+               goto leave;
+       }
+       cpydata(in, out);
+       close(in);
+       printf("Forwarding message%s ", mp->numsel > 1 ? "s" : "");
+       for(msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
+               if(mp->msgstats[msgnum]&SELECTED)  {
+                       if((in = open(cp = m_name(msgnum), 0)) < 0) {
+                               printf("Can't open message \"%s\"\n", cp);
+                               unlink(drft);
+                               goto leave;
+                       }
+                       printf("%d ", msgnum);
+                       type(out, "-------");
+                       if(msgnum == mp->lowsel) {
+                               type(out, " Forwarded Message");
+                               if(mp->numsel > 1)
+                                       type(out, "s");
+                       }
+                       type(out, "\n");
+                       cpydata(in, out);
+                       close(in);
+               }
+       type(out, "------- End of Forwarded Message");
+       if(mp->numsel > 1)
+               type(out, "s");
+       type(out, "\n");
+       close(out);
+       printf("\n");
+       flush();
+       m_replace("folder", folder);
+       if(mp->lowsel != mp->curmsg)
+               m_setcur(mp->lowsel);
+       if(!ed && (ed = m_find("editor")) == -1)
+#ifdef PROMPT
+               ed = prmtproc;
+#else
+               ed = sysed;
+#endif
+       intr = signal(SIGINT, 1);
+       if((in = fork()) == 0) {
+               m_update();
+               flush();
+               execlsrh(ed, drft, 0);
+               printf("Can't exec the editor!!\n");
+               flush(); exit(1);
+       } else if(in == -1) {
+               printf("No forks!\n");
+               goto leave;
+       } else
+               while((out = waita(&status)) != -1 && out != in) ;
+       signal(SIGINT, intr);
+       if(status) {
+               if(status > 0377)
+                       unlink(drft);
+               printf("[command aborted--%s %s]\n", drft,
+                       status > 0377? "deleted" : "preserved");
+               goto leave;
+       }
+#ifdef TEST
+       printf("!! Test Version of SEND Being Run !!\n");
+       printf("   Send verbose !\n\n");
+#endif
+/*     cp = concat("Send \"", draft, "\"? ", 0); */
+       cp = "Send? ";
+       if((out = gans(cp, anyv)) > 0) {
+               if(anot) {
+                       while((in = fork()) == -1) sleep(5);
+                       if(in) {
+                               while(msgnum = wait() != -1 && msgnum != in);
+                               doano();
+                               goto leave;
+                       }
+               }
+               in = 0;
+               vec[in++] = "mh-sndproc";
+               vec[in++] = drft;
+               if(out == 2)
+                       vec[in++] = "-verbose";
+               vec[in++] = 0;
+               m_update();
+               flush();
+               execv(sndproc, vec);
+               printf("Can't exec send process.\n");
+               flush(); exit(1);
+       }
+
+ leave:
+       m_update();
+       flush();
+}
+
+
+cpydata(in, out)
+{
+       char buf[512];
+       register int i;
+
+       do
+               if((i = read(in, buf, sizeof buf)) > 0)
+                       write(out, buf, i);
+       while(i == sizeof buf);
+}
+
+
+doano()
+{
+       struct iobuf in;
+       char name[NAMESZ], field[256];
+       register int ind, state;
+       register char *text;
+
+       if(stat(drft, field) != -1) {
+               printf("%s not sent-- no annotations made.\n", drft);
+               return;
+       }
+       text = copy(drft, field);
+       text[1] = 0;
+       do
+               *text = text[-1];
+       while(--text >= field && *text != '/');
+       *++text = ',';                  /* New backup convention */
+       if(fopen(field, &in) < 0) {
+               printf("Can't open %s\n", field);
+               return;
+       }
+       state = FLD;
+       text = 0;
+   for(;;) switch(state = m_getfld(state, name, field, sizeof field, &in)) {
+
+       case FLD:
+       case FLDEOF:
+       case FLDPLUS:
+               if(uleq(name, "to") || equal(name, "cc")) {
+                       if(state == FLD) {
+                               text = add(name, text);
+                               text = add(":", text);
+                       }
+                       text = add(field, text);
+               }
+               if(state == FLDEOF)
+                       goto out;
+               continue;
+       case BODY:
+       case BODYEOF:
+               goto out;
+       default:
+               printf("Getfld returned %d\n", state);
+               return;
+       }
+
+out:
+       close(in.b_fildes);
+
+       for(ind = mp->lowsel; ind <= mp->hghsel; ind++)
+               if(mp->msgstats[ind] & SELECTED)
+                       annotate(m_name(ind), "Forwarded", text);
+}
diff --git a/docs/historical/SRI-NOSC/forward.run b/docs/historical/SRI-NOSC/forward.run
new file mode 100644 (file)
index 0000000..33b221f
--- /dev/null
@@ -0,0 +1,6 @@
+if -r forward rm forward
+load -n forward annotate subs.a strings.a wait \
+       -O libg.a libh.a libg.a
+if -r a.out mv a.out forward
+:                                      fini
+
diff --git a/docs/historical/SRI-NOSC/install-defs.c b/docs/historical/SRI-NOSC/install-defs.c
new file mode 100644 (file)
index 0000000..b01a12c
--- /dev/null
@@ -0,0 +1,110 @@
+#define TRUE 1
+#include "mh.h"
+#include "stat.h"
+
+char   *anoyes[],       /* Std no/yes gans array        */
+       mh_defs[],
+       defalt[];
+
+int     fout;
+char    *mypath, defpath[128];
+
+main(argc, argv)
+char *argv[];
+{
+       register char *cp, *path;
+       register struct node *np;
+       int autof, detached, exitstat;
+       struct inode stbuf;
+
+       fout = dup(1);
+       autof = (argc == 2 && equal(argv[1], "-auto"));
+       detached = (argc == 2 && equal(argv[1], "-detached"));
+       exitstat = 1;                 /* Assume errors will occur */
+       mypath = getpath(getruid());  /* to prevent recursion via m_getdefs */
+       copy(mh_defs, copy(mypath, defpath));
+       if(stat(defpath, &stbuf) != -1) {
+           if(autof)
+               printf("Install-defs invocation error!\n");
+           else if (!detached)
+               printf("You already have an MH profile... use an editor \
+to modify it.\n");
+           goto leave;
+
+       }
+       if(!detached && (autof || gans("Do you want help? ", anoyes))) {
+printf("\nPrior to using MH, it is necessary to have a file in your login\n");
+printf("directory (%s) named .mh_defs which contains information\n",mypath);
+printf("to direct certain MH operations.  The only item which is required\n");
+printf("is the path to use for all MH folder operations. The suggested MH\n");
+printf("path for you is %s/mail...\n\n", mypath);
+       }
+       cp = concat(mypath, "/", "mail", 0);
+       if(stat(cp, &stbuf) != -1) {
+           if((stbuf.i_mode&IFMT) == IFDIR) {
+               cp = concat("You already have the standard MH directory \"",
+                       cp, "\".\nDo you want to use it for MH? ", 0);
+               if( detached ? TRUE : gans(cp, anoyes))
+                   path = "mail";
+               else
+                   goto xyz;
+           }
+       } else {
+           cp = concat("Do you want the standard MH path \"", mypath,
+                        "/", "mail\"? ", 0);
+           if( detached ? TRUE : gans(cp, anoyes))
+                   path = "mail";
+           else {
+    xyz:        if(gans("Do you want a path below your login directory? ",
+                   anoyes)) {
+                   printf("What is the path ??  %s/", mypath);
+                   path = getans();
+               } else {
+                   printf("What is the whole path??  /");
+                   path = concat("/", getans(), 0);
+               }
+           }
+       }
+       chdir(mypath);
+       if(chdir(path) == -1) {
+               cp = concat("\"", path, "\" doesn't exist; Create it? ", 0);
+               if( detached ? TRUE : gans(cp, anoyes))
+                       if(makedir(path) == 0) {
+                               if (!detached) printf("Can't create it!\n");
+                               goto leave;
+                       }
+       } else
+               if (!detached) printf("[Using existing directory]\n");
+
+       np = m_defs = alloc(sizeof *np);
+       np->n_name = "Path";
+       np->n_field = path;
+       np->n_next = 0;
+       m_replace("folder", defalt);
+       exitstat = 0;
+
+leave:
+       m_update();
+       flush();
+       exit(exitstat);
+}
+
+
+getans()
+{
+       static char line[128];
+       register char *cp;
+       register int c;
+
+       flush();
+       cp = line;
+       while(c = getchar()) {
+               if(c == '\n') {
+                       *cp = 0;
+                       return(line);
+               }
+               if(cp < (&line) + 1)
+                       *cp++ = c;
+       }
+       exit(1);
+}
diff --git a/docs/historical/SRI-NOSC/install-defs.r b/docs/historical/SRI-NOSC/install-defs.r
new file mode 100644 (file)
index 0000000..5d81be1
--- /dev/null
@@ -0,0 +1,5 @@
+if -r install-defs rm install-defs
+load install-defs subs.a strings.a wait -O /m/mh/libg.a /m/mh/libh.a
+if -r a.out mv a.out install-defs
+:                                      fini
+
diff --git a/docs/historical/SRI-NOSC/iobuf.h b/docs/historical/SRI-NOSC/iobuf.h
new file mode 100644 (file)
index 0000000..553a763
--- /dev/null
@@ -0,0 +1,7 @@
+/* file used for getc/putc */
+struct iobuf {
+       int     b_fildes;
+       int     b_nleft;
+       char    *b_nextp;
+       char    b_buff[512];
+};
diff --git a/docs/historical/SRI-NOSC/mh.h b/docs/historical/SRI-NOSC/mh.h
new file mode 100644 (file)
index 0000000..4ae8451
--- /dev/null
@@ -0,0 +1,108 @@
+#define TRUE 1
+#define FALSE 0
+
+#define ALL ""
+
+#define MAXARGS 152     /* Max messages to exec                 */
+
+#define EXISTS    01      /*  existing msg msgstat bit - may be del or undel */
+#define DELETED   02      /* msg has been deleted */
+#define UNDELETED   04      /* msg is not deleted */
+#define SELECTED  010      /* Message selected by an arg           */
+
+#define READONLY  01      /* No write access to folder            */
+#define DEFMOD    01      /* In-core profile has been modified    */
+
+/*#define NEWS     1      /* Define for news inclusion            */
+#define PROMPT    1     /* Use prompter in compose, etc */
+
+struct  swit {
+       char *sw;
+       int minchars;
+};
+
+/*
+ * m_gmsg() returns this structure.  It contains the per folder
+ * information which is obtained from reading the folder directory.
+ */
+
+struct  msgs {
+       int     hghmsg;         /* Highest msg in directory     */
+       int     nummsg;         /* Actual Number of msgs        */
+       int     lowmsg;         /* Lowest msg number            */
+       int     curmsg;         /* Number of current msg if any */
+       int     lowsel;         /* Lowest selected msg number   */
+       int     hghsel;         /* Highest selected msg number  */
+       int     numsel;         /* Number of msgs selected      */
+       char   *foldpath;       /* Pathname of folder           */
+       char    selist,         /* Folder has a "select" file   */
+               msgflags,       /* Folder status bits           */
+               filler,
+               others;         /* Folder has other file(s)     */
+       char    msgstats[];     /* Stat bytes for each msg      */
+};
+
+               /* m_getfld definitions and return values       */
+
+#define NAMESZ  64      /* Limit on component name size         */
+#define LENERR  -2      /* Name too long error from getfld      */
+#define FMTERR  -3      /* Message Format error                 */
+
+                       /* m_getfld return codes                */
+#define FLD      0      /* Field returned                       */
+#define FLDPLUS  1      /* Field " with more to come            */
+#define FLDEOF   2      /* Field " ending at eom                */
+#define BODY     3      /* Body  " with more to come            */
+#define BODYEOF  4      /* Body  " ending at eom                */
+#define FILEEOF  5      /* Reached end of input file            */
+
+#ifdef COMMENT          /* Commented out to reduce space        */
+/*
+ * These standard strings are defined in strings.c.  They are the
+ * only system-dependent parameters in MH, and thus by redefining
+ * their values in strings.c and reloading the various modules, MH
+ * will run on any system.
+ */
+
+char    mailbox[],      /* Std incoming mail file (.mail)       */
+       draft[],        /* Name of the normal draft file        */
+       defalt[],       /* Name of the std folder (inbox)       */
+       components[],   /* Name of user's component file (in mh dir) */
+       stdcomps[],     /* Std comp file if missing user's own  */
+       sndproc[],      /* Path of the send message program     */
+       showproc[],     /* Path of the type (l) program         */
+       scanproc[],     /* Path of the scan program             */
+       prproc[],       /* Path of the pr program               */
+       lsproc[],       /* Path of the Harvard ls program       */
+       sbmitloc[],     /* Path of the submit program           */
+       sbmitnam[],     /* Name of submit program               */
+       mypath[],       /* User's log-on path                   */
+       sysed[],        /* Path of the std (ned) editor         */
+       msgprot[],      /* Default message protection (s.a. 0664) */
+       foldprot[],     /* Default folder protection      "     */
+       listname[],     /* Default selection list folder name   */
+       mhnews[];       /* Name of MH news file                 */
+#endif
+
+/*
+ * node structure used to hold a linked list of the users profile
+ * information taken from logpath/.mh_defs.
+ */
+
+struct node {
+       struct node *n_next;
+       char        *n_name,
+                   *n_field;
+} *m_defs;
+
+char  def_flags;
+
+
+/*
+ * The first char in the mhnews file indicates whether the program
+ * calling m_news() should continue running or halt.
+ */
+
+#define NEWSHALT        '!'     /* Halt after showing the news  */
+#define NEWSCONT        ' '     /* Continue  (ditto)            */
+#define NEWSPAUSE       '\001'  /* Pause during news output...  */
diff --git a/docs/historical/SRI-NOSC/nosc.txt b/docs/historical/SRI-NOSC/nosc.txt
new file mode 100644 (file)
index 0000000..3140997
--- /dev/null
@@ -0,0 +1,33 @@
+University of Illinois 'Network Unix'
+(from Noel Chiappa)
+
+  The first networked Unix system was one produced at the University of
+  Illinois in 1974-75 for use on the <a href="http://en.wikipedia.org/wiki/ARPANET">ARPANET</a>;
+  it used the <a href="http://en.wikipedia.org/wiki/Network_Control_Program">NCP</a> protocol.
+
+  The code is divided into three main groups: code for the kernel (further divided into
+  device drivers, and code common to all methods of interfacing to the ARPANET); a daemon
+  which ran as a process, which handled a lot of the protocol overhead (e.g. opening and
+  closing connections); and programs (also run as processes) to implement applications
+  such as FTP and TELNET.
+
+  The code was originally written mostly by Gary R. Grossman and Steve
+  F. Holmgren; many others later contributed fixes and improvements. The code
+  rapidly spread among computer science centers which were connected to the
+  ARPANET; this copy of the code came via NOSC (Naval Ocean Systems Center)
+  and SRI.
+
+  Also included are two important major application packages produced
+  elsewhere: the MH mail reader, done by Bruce S. Borden at RAND based on
+  suggestions by R. Stockton Gaines; and the MMDF mail agent, written by David
+  Crocker at the University of Delaware.
+
+  For more information about this system, see:
+  - Steve Holmgren; "The Network UNIX System"; Center for Advanced
+  Computation, University of Illinois at Urbana-Champaign; Urbana, Illinois;
+  1975
+  - Karl C Kelley, Richard Balocca, Jody Kravitz; "A Network Unix System for
+  the ARPANET: Volume 1 - The Network Control Program"; Center for Advanced
+  Computation and Computing Services Office, University of Illinois at
+  Urbana-Champaign; Urbana, Illinois; 1978
+
diff --git a/docs/historical/SRI-NOSC/nullproc.c b/docs/historical/SRI-NOSC/nullproc.c
new file mode 100644 (file)
index 0000000..a93dd9a
--- /dev/null
@@ -0,0 +1,3 @@
+main(argc,argv) char *argv[];
+{ int i;printf("NULL PROCESS\n");
+ for (i=0; i<argc; i++)printf("%s\n",argv[i]); return; }
diff --git a/docs/historical/SRI-NOSC/open.c b/docs/historical/SRI-NOSC/open.c
new file mode 100644 (file)
index 0000000..5209892
--- /dev/null
@@ -0,0 +1,273 @@
+/* formerly folder */
+#include "mh.h"
+#include "stat.h"
+#define NFOLDERS 100
+
+char    lsproc[],
+       listname[];
+
+int fout, all, hdrflag, foldp;
+struct msgs *mp;
+char folder[128], *folds[NFOLDERS];
+int msgtot, foldtot, totonly, shrt;
+struct swit switches[] {
+       "all",          0,      /* 0 */
+       "down",         0,      /* 1 */
+       "fast",         0,      /* 2 */
+       "nofast",       0,      /* 3 */
+       "header",       0,      /* 4 */
+       "noheader",     0,      /* 5 */
+       "short",        0,      /* 6 */
+       "total",        0,      /* 7 */
+       "nototal",      0,      /* 8 */
+       "up",           0,      /* 9 */
+       "help",         4,      /*10 */
+       0,              0
+};
+
+main(argc, argv)
+char *argv[];
+{
+       register char *cp, *curm;
+       register int i;
+       char *argfolder;
+       int up, down, j, def_short;
+       char *ap, *inp;
+       char *arguments[50], **argp;
+       struct inode stbf, *np;
+       struct { int    inum;
+                char   name[14];
+                int    pad;
+       } ent;
+
+       fout = dup(1);
+#ifdef NEWS
+       m_news();
+#endif
+       up = down = argfolder = 0;
+       curm = 0;
+       if(argv[0][length(argv[0])-1] == 's')   /* Plural name?? */
+               all++;
+       ap = cp = argv[0];
+       while(*cp)
+               if(*cp++ == '/')
+                       ap = cp;
+       inp = ap;
+       if(!uleq("folder", ap) && (cp = m_find(ap)) != -1) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);     /* ambiguous */
+                               goto leave;
+                                                          /* unknown */
+                       case -1:printf("-%s unknown\n", cp);
+                               goto leave;
+                       case 0: all++;  continue;          /* -all      */
+                       case 1: down++;  continue;         /* -down     */
+                       case 2:                            /* -fast     */
+                       case 6: shrt = 1;  continue;      /* -short    */
+                       case 3: shrt = 0;  continue;      /* -nofast   */
+                       case 4: hdrflag = -1;  continue;   /* -header   */
+                       case 5: hdrflag = 0;  continue;    /* -noheader */
+                       case 7: all++; totonly = 1;        /* -total    */
+                               continue;
+                       case 8: if(totonly) all--;         /* -nototal  */
+                               totonly =0;  continue;
+                       case 9: up++;  continue;           /* -up       */
+                                                          /* -help     */
+                       case 10:help(concat( inp, " [+folder]  [msg] [switches]",0),
+                                    switches);
+                               goto leave;
+                       }
+               if(*cp == '+') {
+                       if(argfolder) {
+                               printf("Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               argfolder = cp + 1;
+               } else if(curm) {
+                       printf("Only one current may be given.\n");
+                       goto leave;
+               } else
+                       curm = cp;
+       }
+       if(all) {
+               hdrflag = 0;
+               cp = m_maildir("");
+               m_getdefs();
+               for(np = m_defs; np; np = np->n_next) {
+                       if(!ssequal("cur-", np->n_name))
+                               continue;
+                       if(shrt) {
+                               def_short++;
+                               printf("%s\n", np->n_name+4);
+                       } else
+                               addfold(np->n_name+4);
+               }
+               if(def_short)
+                       putchar('\n');
+               if(shrt) {
+                       m_update();
+                       flush();
+                       execl(lsproc, "mh-ls", "-x", cp, 0);
+                       printf("Can't exec: "); flush();
+                       perror(lsproc);
+                       goto leave;
+               }
+               if(chdir(cp) < 0) {
+                       printf("Can't chdir to: "); flush();
+                       perror(cp);
+                       goto leave;
+               }
+               if((cp = m_find("folder")) == -1)
+                       *folder = 0;
+               else
+                       copy(cp, folder);
+               i = open(".", 0);
+               ent.pad = 0;
+               while(read(i, &ent.inum, sizeof ent.name + sizeof ent.inum))
+                       if(ent.inum && ent.name[0] != '.' &&
+                          stat(ent.name, &stbf) >= 0 &&
+                          (stbf.i_mode&IFMT) == IFDIR)
+                               addfold(ent.name);
+               close(i);
+               for(i = 0; i < foldp; i++) {
+                       pfold(folds[i], 0); flush();
+               }
+               if(!totonly)
+                       printf("\n\t\t     ");
+               printf("TOTAL= %3d message%c in %d Folder%s.\n",
+                       msgtot, msgtot!=1? 's':' ',
+                       foldtot, foldtot!=1? "s":"");
+       } else  {
+               hdrflag++;
+               if(argfolder)
+                       cp = copy(argfolder, folder);
+               else
+                       cp = copy(m_getfolder(), folder);
+               if(up) {
+                       while(cp > folder && *cp != '/') --cp;
+                       if(cp > folder)
+                               *cp = 0;
+                       argfolder = folder;
+               } else if(down) {
+                       copy(listname, copy("/", cp));
+                       argfolder = folder;
+               }
+               if(pfold(folder, curm) && argfolder)
+                       m_replace("folder",argfolder);
+       }
+
+ leave:
+       m_update();
+       flush();
+}
+
+
+addfold(fold)
+char *fold;
+{
+       register int i,j;
+       register char *cp;
+
+       if(foldp >= NFOLDERS) {
+               printf("More than %d folders!!\n", NFOLDERS);
+               return(1);
+       }
+       cp = getcpy(fold);
+       for(i = 0; i < foldp; i++)
+               if(compare(cp, folds[i]) < 0) {
+                       for(j = foldp - 1; j >= i; j--)
+                               folds[j+1] = folds[j];
+                       foldp++;
+                       folds[i] = cp;
+                       return(0);
+               }
+       folds[foldp++] = cp;
+       return(0);
+}
+
+
+pfold(fold, curm)
+char *fold;
+{
+       register char *mailfile;
+
+       mailfile = m_maildir(fold);
+       if(chdir(mailfile) < 0) {
+               printf("Can't chdir to: "); flush();
+               perror(mailfile);
+               return(0);
+       }
+       if(shrt) {
+               printf("%s\n", fold);
+               return(0);
+       }
+       mp = m_gmsg(fold);
+       foldtot++;
+       msgtot =+ mp->nummsg;
+       if(totonly)
+               goto out;
+       if(curm) {
+               if(!m_convert(curm))
+                       return(0);
+               if(mp->numsel > 1) {
+                       printf("Can't set current msg to %s\n", curm);
+                       return(0);
+               }
+               m_setcur(mp->curmsg = mp->hghsel);
+       }
+       if(!hdrflag++)
+  printf("\t\tFolder   # of messages   ( range ); cur msg (other files)\n");
+       printf("%22s", fold);
+       if(equal(folder, fold))
+               printf("+ ");
+       else
+               printf("  ");
+       if(mp->hghmsg == 0)
+               printf("has  no messages");
+       else {
+               printf("has %3d message%s (%3d-%3d)",
+                       mp->nummsg, (mp->nummsg==1)?" ":"s",
+                       mp->lowmsg, mp->hghmsg);
+               if(mp->curmsg >= mp->lowmsg && mp->curmsg <= mp->hghmsg)
+                       printf("; cur=%3s", m_name(mp->curmsg));
+       }
+       if(mp->selist || mp->others) {
+               printf("; (");
+               if(mp->selist) {
+                       printf("%s", listname);
+                       if(mp->others)
+                               printf(", ");
+               }
+               if(mp->others)
+                       printf("others");
+               putchar(')');
+       }
+       putchar('.');
+       putchar('\n');
+out:
+       free(mp);
+       mp = 0;
+       return(1);
+}
+
+
+compare(s1, s2)
+char *s1, *s2;
+{
+       register char *c1, *c2;
+       register int i;
+
+       c1 = s1; c2 = s2;
+       while(*c1 || *c2)
+               if(i = *c1++ - *c2++)
+                       return(i);
+       return(0);
+}
diff --git a/docs/historical/SRI-NOSC/open.run b/docs/historical/SRI-NOSC/open.run
new file mode 100644 (file)
index 0000000..deab5a2
--- /dev/null
@@ -0,0 +1,5 @@
+if -r open rm open
+load -n open subs.a strings.a wait -O libg.a libh.a
+if -r a.out mv a.out open
+:                                      fini
+
diff --git a/docs/historical/SRI-NOSC/pickup.c b/docs/historical/SRI-NOSC/pickup.c
new file mode 100644 (file)
index 0000000..37b6aee
--- /dev/null
@@ -0,0 +1,201 @@
+#include "mh.h"
+#include "iobuf.h"
+#include "stat.h"
+#include "errors.h"
+
+char   *anoyes[],       /* Std no/yes gans array        */
+       *mypath,
+       mailbox[],
+       defalt[];
+
+char    scanl[];
+struct  msgs *mp;
+struct  iobuf in, fout, *aud;
+struct  inode stbuf;
+
+struct  swit switches[] {
+       "audit audit-file",     0,      /* 0 */
+       "ms ms-folder",         0,      /* 1 */
+       "help",                 4,      /* 2 */
+       0,                      0
+};
+
+main(argc, argv)
+char *argv[];
+{
+
+       char newmail[128], maildir[128], *folder, *from, *audfile;
+       register char *cp;
+       register int i, msgnum;
+       long now;
+       char *ap, *inp;
+       char *arguments[50], **argp;
+
+       fout.b_fildes = dup(1);
+#ifdef NEWS
+       m_news();
+#endif
+       from = folder = audfile = 0;
+       ap = cp = argv[0];
+       while(*cp)
+               if(*cp++ == '/')
+                       ap = cp;
+       inp = ap;
+       if((cp = m_find(ap)) != -1) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                            /* unknown */
+                       case -1:printf("-%s unknown\n", cp);
+                               goto leave;
+                       case 0: if(!(audfile = *argp++)) {   /* -audit */
+      missing:  printf("Missing argument for %s switch\n", argp[-2]);
+                                       goto leave;
+                               }
+                               continue;
+                       case 1: if(!(from = *argp++))        /* -ms */
+                                       goto missing;
+                               continue;
+                       case 2:                              /* -help */
+                               help(concat( inp, " [+folder]  [switches]", 0), switches);
+                               goto leave;
+                       }
+               if(*cp == '+') {
+                       if(folder) {
+                               printf("Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               folder = cp + 1;
+               } else {
+                       printf("Bad arg: %s\n", argp[-1]);
+       printf(concat("Usage: ", inp, " [+folder] [-ms ms-folder] [-audit audit-file]\n", 0));
+                       goto leave;
+               }
+       }
+       if(from)
+               copy(from, newmail);
+       else {
+               mypath = getpath(getruid());
+               copy(mailbox, copy(mypath, newmail));
+               if(stat(newmail, &stbuf) < 0 ||
+                  !(stbuf.i_size0 | stbuf.i_size1)) {
+                       printf("No new mail.\n");
+                       goto leave;
+               }
+       }
+       if(fopen(newmail, &in) < 0) {
+               printf("Can't read \"%s\"??\n", newmail);
+               goto leave;
+       }
+       if(!folder) {
+               folder = defalt;
+               if(from && !equal(from, "inbox")) {
+                       cp = concat("Do you really want to convert from ",
+                               from, " into ", folder, "?? ", 0);
+                       if(!gans(cp, anoyes))
+                               goto leave;
+               }
+       }
+       copy(m_maildir(folder), maildir);
+       if(stat(maildir, &stbuf) < 0) {
+               if(errno != ENOENT) {
+                       printf("Error on folder "); flush();
+                       perror(maildir);
+                       goto leave;
+               }
+/*             cp = concat("Create folder \"", maildir, "\"? ", 0);
+               if(!gans(cp, anoyes))
+                       goto leave;     */
+               if(!makedir(maildir)) {
+                       printf("Can't create folder \"%s\"\n", maildir);
+                       goto leave;
+               }
+       }
+       if(chdir(maildir) < 0) {
+               printf("Can't chdir to: ");
+               perror(maildir);
+               goto leave;
+       }
+       if(!(mp = m_gmsg(folder))) {
+               printf("Can't read folder!?\n");
+               goto leave;
+       }
+       if(audfile) {
+               aud = alloc(sizeof *aud);
+               cp = m_maildir(audfile);
+               if(fopen2(cp, aud) == -1) {
+                       printf("Creating Receive-Audit: %s\n", cp);
+                       if(fcreat(cp, aud) == -1) {
+                               printf("Can't create "); flush();
+                               perror(cp);
+                               goto leave;
+                       }
+                       chmod(cp, 0600);
+                       putchar('\n');
+               } else
+                       seek(aud->b_fildes, 0, 2);
+               time(&now);
+               puts("<<inc>> ", aud);
+               cp = cdate(&now);
+               cp[9] = ' ';
+               puts(cp, aud);
+               if(from) {
+                       puts("  -ms ", aud);
+                       puts(from, aud);
+               }
+               putc('\n', aud);
+       }
+       printf("Incorporating new mail into %s...\n\n", folder);
+       flush();
+       msgnum = mp->hghmsg;
+
+       while((i = scan(&in, msgnum+1, msgnum+1, msgnum == mp->hghmsg))) {
+               if(i == -1) {
+                       printf("command aborted!\n");
+                       if(aud)
+                               puts("inc aborted!\n", aud);
+                       goto leave;
+               }
+               if(aud)
+                       puts(scanl, aud);
+               flush();
+               msgnum++;
+       }
+
+       close(in.b_fildes);
+       if(aud)
+               fflush(aud);
+
+       if(!from) {
+               if((i = creat(newmail, 0600)) >= 0)     /* Zap .mail file */
+                       close(i);
+               else
+                       printf("Error zeroing %s\n", newmail);
+       } else
+               printf("%s not zero'd\n", newmail);
+
+       i = msgnum - mp->hghmsg;
+   /*   printf("%d new message%s\n", i, i==1? "":"s");          */
+       if(!i)
+               printf("[No messages incorporated.]\n");
+       else {
+               if(!equal(m_getfolder(), folder))
+                       m_replace("folder", folder);
+               m_setcur(mp->hghmsg + 1);
+       }
+leave:
+       m_update();
+       flush();
+}
+
+
+
+
diff --git a/docs/historical/SRI-NOSC/pickup.run b/docs/historical/SRI-NOSC/pickup.run
new file mode 100644 (file)
index 0000000..321fdc3
--- /dev/null
@@ -0,0 +1,5 @@
+if -r pickup rm pickup
+load -n pickup scansub subs.a strings.a putc wait -O libg.a libh.a
+if -r a.out mv a.out pickup
+:                                      fini
+
diff --git a/docs/historical/SRI-NOSC/pr.c b/docs/historical/SRI-NOSC/pr.c
new file mode 100644 (file)
index 0000000..ddfac04
--- /dev/null
@@ -0,0 +1,1050 @@
+#
+/*
+ *   print file with headings
+ *   precl[2]+head+2+page[56]+endl[5]
+ */
+
+/*
+ *   NOTE:  Defaults are set in the routine dflts()
+ *          and not in these declares.
+ */
+
+int     errno;
+char   *sys_errlst[];
+
+int     ncol 1;                               /* number of columns            */
+char   *header;                               /* header text                  */
+int     col;
+int     icol;
+int     file;
+char   *bufp;
+#define        BUFS    5120
+char    buffer[BUFS];
+#define        FF      014
+int     line;                         /* current line on page         */
+int     linum;                        /* current text line            */
+int     ftext;                        /* first text line on page      */
+char   *colp[72];
+int     nofile;                               /* number of current file       */
+char    isclosed[10];
+int     peekc;
+int     swval;                        /* value for next switch        */
+int     fpage;                        /* first page to print          */
+int     page;                         /* current page number          */
+int     oheadr;                               /* use old header format        */
+int     colw;                         /* column width                 */
+int     nspace;
+int     width 65;                     /* line width                   */
+int     pwidth 65;                    /* width of physical line       */
+int     length 66;                    /* length of physical page      */
+int     plength 61;                   /* last print line              */
+int     margin 10;
+int     prone 1;                      /* print header on page one     */
+int     ntflg;                        /* no header or trailer         */
+int     nuflg;                        /* not header line              */
+int     mflg;
+int     tabc;                         /* print this as column separator */
+char   *tty;
+int     mode;
+int     precl 2;                      /* # blank lines preceding hdr  */
+int     endl 5;                               /* min # blank lines end of page */
+int     indent;                               /* spaces preceding each line   */
+int     ff;                           /* use ff, not blank lines      */
+int     wasff;                        /* page break caused by ff      */
+int     blankl;                               /* # blank lines between lines  */
+int     count;                        /* whether to count linums      */
+int     tab2sp;                               /* change tabs => spaces        */
+int     queeze;                               /* squeeze blank lines from top */
+                                      /*   of each page               */
+int     jnamflg;                      /* print just file and not path */
+int     rapflg;                               /* wrap-around line overflow    */
+int    spaftfil 0;                     /* space between files */
+
+
+struct inode
+{
+    int     dev;
+    int     inum;
+    int     flags;
+    char    nlink;
+    char    uid;
+    char    gid;
+    char    siz0;
+    int     size;
+    int     ptr[8];
+    int     atime[2];
+    int     mtime[2];
+};
+
+main (argc, argv)
+char  **argv;
+{
+    int     nfdone;
+    int     onintr ();
+    extern  fout;
+
+    tty = "/dev/ttyx";
+    fout = dup (1);
+    close (1);
+    if ((signal (2, 1) & 01) == 0)
+       signal (2, onintr);
+    fixtty ();
+    dflts (0);
+    for (nfdone = 0; argc > 1; argc--)
+    {
+       argv++;
+       if (**argv == '-')
+       {
+           swval = 1;                 /* default to on */
+    setsw: 
+           switch (*++*argv)
+           {
+               case 'b': 
+                   blankl = getn (++*argv);
+                   continue;
+
+               case 'c': 
+                   count = swval;
+                   continue;
+
+               case 'd': 
+                   dflts (*++*argv);
+                   continue;
+
+               case 'e': 
+                   endl = getn (++*argv);
+                   continue;
+
+               case 'f': 
+                   ff = swval;
+                   continue;
+
+               case 'h': 
+                   if (argc >= 2)
+                   {
+                       header = *++argv;
+                       argc--;
+                   }
+                   continue;
+
+               case 'i': 
+                   indent = getn (++*argv);
+                   continue;
+
+               case 'j': 
+                   jnamflg = swval;
+                   continue;
+
+               case 'l': 
+                   length = getn (++*argv);
+                   continue;
+
+               case 'm': 
+                   mflg = swval;
+                   continue;
+
+               case 'n': 
+                   prone = (swval ^ 1);
+                                      /* Yes => no */
+                   continue;
+
+               case 'o': 
+                   oheadr = swval;
+                   continue;
+
+               case 'p': 
+                   precl = getn (++*argv);
+                   continue;
+
+               case 'q': 
+                   queeze = swval;
+                   continue;
+
+               case 'r': 
+                   rapflg = swval;
+                   continue;
+
+               case 's': 
+                   spaftfil = getn( ++*argv);
+                   continue;
+
+               case 't': 
+                   ntflg = swval;
+                   continue;
+
+               case 'u': 
+                   nuflg = swval;
+                   continue;
+
+               case 'w': 
+                   width = getn (++*argv);
+                   continue;
+
+               case 'x': 
+                   tab2sp = swval;
+                   continue;
+
+               case '-': 
+                   swval = 0;
+                   goto setsw;
+
+               default: 
+                   ncol = getn (*argv);
+                   continue;
+           }
+       }
+       else
+           if (**argv == '+')
+           {
+               fpage = getn (++*argv);
+           }
+           else
+           {
+               col = 0;
+               icol = 0;
+               line = 0;
+               nspace = 0;
+               print (*argv, argv);
+               nfdone++;
+               if (mflg)
+                   break;
+           }
+    }
+    if (nfdone == 0)
+       print (0);
+    flush ();
+    onintr ();
+}
+
+onintr ()
+{
+
+    chmod (tty, mode);
+    exit (0);
+}
+
+fixtty ()
+{
+    struct inode    sbuf;
+    extern  fout;
+
+    tty[8] = ttyn (fout);
+    fstat (fout, &sbuf);
+    mode = sbuf.flags & 0777;
+    chmod (tty, 0600);
+}
+
+dflts (dfltpkg)
+{
+    switch (dfltpkg)
+    {
+       case 'd': 
+           ncol = 1;                  /* number of columns            */
+           width = 65;                /* line width                   */
+           length = 60;               /* length of physical page      */
+           plength = 61;              /* last print line              */
+           margin = 10;
+           precl = 1;                 /* # blank lines preceding hdr  */
+           endl = 5;                  /* min # blank lines end of page */
+           indent = 5;                /* spaces preceding each line   */
+           ff = 1;                    /* use ff, not blank lines      */
+           blankl = 0;                /* # blank lines between lines  */
+           count = 0;                 /* whether to count linums      */
+           prone = 0;                 /* print header on page one     */
+           tab2sp = 0;                /* change tabs into spaces      */
+           queeze = 1;                /* squeeze beginning of pages   */
+           jnamflg = 0;               /* print full pathname          */
+           rapflg = 1;                /* wrap around long lines       */
+           oheadr = 0;                /* nothin' but the best...      */
+           break;
+
+       case 'l': 
+           ncol = 1;                  /* number of columns            */
+           width = 77;                /* line width                   */
+           length = 60;               /* length of physical page      */
+           plength = 61;              /* last print line              */
+           margin = 10;
+           precl = 2;                 /* # blank lines preceding hdr  */
+           endl = 5;                  /* min # blank lines end of page */
+           indent = 5;                /* spaces preceding each line   */
+           ff = 1;                    /* use ff, not blank lines      */
+           blankl = 0;                /* # blank lines between lines  */
+           count = 0;                 /* whether to count linums      */
+           prone = 1;                 /* print header on page one     */
+           tab2sp = 0;                /* change tabs into spaces      */
+           queeze = 0;                /* preserve start of each page  */
+           jnamflg = 0;               /* print full pathname          */
+           rapflg = 1;                /* wrap around long lines       */
+           oheadr = 0;                /* nothin' but the best...      */
+           break;
+
+       case 'n': 
+           ncol = 1;                  /* number of columns            */
+           width = 80;                /* line width                   */
+           length = 60;               /* length of physical page      */
+           plength = 61;              /* last print line              */
+           margin = 10;
+           precl = 2;                 /* # blank lines preceding hdr  */
+           endl = 5;                  /* min # blank lines end of page */
+           indent = 5;                /* spaces preceding each line   */
+           ff = 1;                    /* use ff, not blank lines      */
+           blankl = 0;                /* # blank lines between lines  */
+           count = 1;                 /* whether to count linums      */
+           prone = 1;                 /* print header on page one     */
+           tab2sp = 0;                /* don't change tabs into spaces */
+           queeze = 0;                /* preserve start of each page  */
+           jnamflg = 0;               /* print full pathname          */
+           rapflg = 1;                /* wrap around long lines       */
+           oheadr = 0;                /* nothin' but the best...      */
+           break;
+
+       case 0: 
+       default: 
+           ncol = 0;                  /* number of columns            */
+           width = 72;                /* line width                   */
+           length = 66;               /* length of physical page      */
+           plength = 61;              /* last print line              */
+           margin = 10;
+           precl = 2;                 /* # blank lines preceding hdr  */
+           endl = 5;                  /* min # blank lines end of page */
+           indent = 0;                /* spaces preceding each line   */
+           ff = 0;                    /* use ff, not blank lines      */
+           blankl = 0;                /* # blank lines between lines  */
+           count = 0;                 /* whether to count linums      */
+           prone = 1;                 /* print header on page one     */
+           tab2sp = 0;                /* don't change tabs into spaces */
+           queeze = 0;                /* preserve start of each page  */
+           jnamflg = 1;               /* don't print full pathname    */
+           rapflg = 0;                /* don't wrap around long lines */
+           oheadr = 1;                /* nothin' but the worst...     */
+           break;
+    }
+}
+
+
+print (fp, argp)
+char   *fp;
+char  **argp;
+{
+    struct inode    sbuf;
+    int     tmp1;
+    register int    sncol,
+                    sheader;
+    register char  *cbuf;
+    extern  fout;
+
+    linum = 1;
+    if (ntflg)
+       margin = 0;
+    else
+       margin = precl + endl + (nuflg ? 0 : 3);
+    if (length <= margin)
+       length = 66;
+    if (width <= 0)
+       width = 65;
+    if (ncol > 72 || ncol > width)
+    {
+       write (2, "Very funny.\n", 12);
+       exit ();
+    }
+    if (mflg)
+    {
+       mopen (argp);
+       ncol = nofile;
+    }
+    if (ncol > 1)
+       rapflg = 0;
+    colw = width / ncol;
+    sncol = ncol;
+    sheader = header;
+    plength = length - endl;
+    pwidth = width + indent;
+    if (ntflg)
+       plength = length;
+    if (--ncol < 0)
+       ncol = 0;
+    if (mflg)
+       fp = 0;
+    if (fp)
+    {
+       file = open (fp, 0);
+       if (file < 0)
+       {
+           errrpt (fp, sys_errlst[errno]);
+           return;
+       }
+       fstat (file, &sbuf);
+    }
+    else
+    {
+       file = 0;
+       time (sbuf.mtime);
+    }
+    if ((header == 0) && (file != 0))
+       header = jnamflg ? fp
+           : getpath (fp);
+    cbuf = ctime (sbuf.mtime);
+    cbuf[16] = '\0';
+    cbuf[24] = '\0';
+    page = 1;
+    icol = 0;
+    colp[ncol] = bufp = buffer;
+    if (mflg == 0)
+       nexbuf ();
+    while (mflg && nofile || (!mflg) && tpgetc (ncol) > 0)
+    {
+       if (mflg == 0)
+       {
+           colp[ncol]--;
+           if (colp[ncol] < buffer)
+               colp[ncol] = &buffer[BUFS];
+       }
+       line = 0;
+       if (ntflg == 0)
+       {
+           for (tmp1 = precl; tmp1--;)
+               put ('\n');
+           if ((nuflg == 0) &&
+                   (prone || (page > 1)))
+           {
+               for (tmp1 = indent; tmp1--;)
+                   put (' ');
+               if (!oheadr && header)
+               {
+                   puts (header);
+                   puts ("   ");
+               }
+               puts (cbuf + 4);
+               put (' ');
+               puts (cbuf + 20);
+               if (oheadr)
+               {
+                   puts ("  ");
+                   if (header)
+                   {
+                       puts (header);
+                       put (' ');
+                   }
+               }
+               else
+                   do
+                       put (' ');
+                   while (col < (pwidth - 9));
+               puts ("Page ");
+               if (oheadr)
+                   putd (page);
+               else
+                   putrd (page);
+               puts ("\n\n\n");
+           }
+       }
+       ftext = line;                  /* # of first text line */
+       putpage ();
+
+       if (ff)
+           put ('\014');
+       else
+           if (ntflg == 0)
+               while (line < length)
+                   put ('\n');
+       page++;
+    }
+   if ( (ntflg != 0) && (spaftfil > 0))
+       for (tmp1 = spaftfil; tmp1--;)
+               put('\n');
+    if (file)
+       close (file);
+    ncol = sncol;
+    header = sheader;
+}
+
+mopen (ap)
+char  **ap;
+{
+    register char **p,
+                   *p1;
+
+    p = ap;
+    while ((p1 = *p++) && p1 != -1)
+    {
+       isclosed[nofile] = fopen (p1, &buffer[2 * 259 * nofile]);
+       if (++nofile >= 10)
+       {
+           write (2, "Too many args.\n", 15);
+           exit ();
+       }
+    }
+}
+
+putpage ()
+{
+    register int    lastcol,
+                    i,
+                    c;
+    int     j;
+
+    if (ncol == 0)
+    {
+       i = 1;                         /* always starting on new line */
+       while (c = pgetc (0))
+       {
+           if (i)                     /* new line */
+           {
+               if ((queeze) &&
+                       (c == '\n') &&
+                       (line == ftext) &&
+                       (!wasff) &&
+                       (page > 1)
+                   )
+               {
+                   linum++;
+                   continue;
+               }
+
+               for (i = indent; i--;)
+                   put (' ');
+               if (count)
+               {
+                   putrd (linum);
+                   puts ("  ");
+               };
+               i = 0;
+           };
+           switch (c)
+           {
+               case FF: 
+                   wasff = 1;
+                   return;
+               case '\n': 
+                   linum++;
+                   for ((i = (blankl + 1)); i--;)
+                   {
+                       put ('\n');
+                       if (line >= plength)
+                       {
+                           wasff = 0;
+                           return;
+                       }
+                   }
+                   i = 1;             /* signal new line */
+                   break;
+               default: 
+                   put (c);
+           }
+
+       }
+       return;
+    }
+    colp[0] = colp[ncol];
+    if (mflg == 0)
+       for (i = 1; i <= ncol; i++)
+       {
+           colp[i] = colp[i - 1];
+           for (j = margin; j < length; j++)
+               while ((c = tpgetc (i)) != '\n')
+                   if (c == 0)
+                       break;
+       }
+    while (line < plength)
+    {
+       for (i = indent; i--;)
+           put (' ');
+       lastcol = colw + indent;
+       for (i = 0; i < ncol; i++)
+       {
+           while ((c = pgetc (i)) && c != '\n')
+               if (col < lastcol || tabc != 0)
+                   put (c);
+           if (c == 0 && ntflg)
+               return;
+           if (tabc)
+               put (tabc);
+           else
+               while (col < lastcol)
+                   put (' ');
+           lastcol =+ colw;
+       }
+       while ((c = pgetc (ncol)) && c != '\n')
+           put (c);
+       put ('\n');
+    }
+}
+
+nexbuf ()
+{
+    register int    n;
+    register char  *rbufp;
+
+    rbufp = bufp;
+    n = &buffer[BUFS] - rbufp;
+    if (n > 512)
+       n = 512;
+    if ((n = read (file, rbufp, n)) <= 0)
+       *rbufp = 0376;
+    else
+    {
+       rbufp =+ n;
+       if (rbufp >= &buffer[BUFS])
+           rbufp = buffer;
+       *rbufp = 0375;
+    }
+    bufp = rbufp;
+}
+
+tpgetc (ai)
+{
+    register char **p;
+    register int    c,
+                    i;
+
+    i = ai;
+    if (mflg)
+    {
+       if ((c = getc (&buffer[2 * 259 * i])) < 0)
+       {
+           if (isclosed[i] == 0)
+           {
+               isclosed[i] = 1;
+               if (--nofile <= 0)
+                   return (0);
+           }
+           return ('\n');
+       }
+       if (c == FF && ncol > 0)
+           c = '\n';
+       return (c);
+    }
+loop: 
+    c = **(p = &colp[i]) & 0377;
+    if (c == 0375)
+    {
+       nexbuf ();
+       c = **p & 0377;
+    }
+    if (c == 0376)
+       return (0);
+    (*p)++;
+    if (*p >= &buffer[BUFS])
+       *p = buffer;
+    if (c == 0)
+       goto loop;
+    return (c);
+}
+
+pgetc (i)
+{
+    register int    c;
+
+    if (peekc)
+    {
+       c = peekc;
+       peekc = 0;
+    }
+    else
+       c = tpgetc (i);
+    if (tabc)
+       return (c);
+    switch (c)
+    {
+
+       case '\t': 
+           icol++;
+           if ((icol & 07) != 0)
+               peekc = '\t';
+           return (' ');
+
+       case '\n': 
+           icol = 0;
+           break;
+    }
+    if (c >= ' ')
+       icol++;
+    return (c);
+}
+
+puts (as)
+char   *as;
+{
+    register int    c;
+    register char  *s;
+
+    if ((s = as) == 0)
+       return;
+    while (c = *s++)
+       put (c);
+}
+
+putrd (an)
+{
+    register int    mag;
+
+    for (mag = 1000; ((mag > 1) && (mag > an)); mag =/ 10)
+       put (' ');
+    putd (an);
+}
+
+
+putd (an)
+{
+    register int    a,
+                    n;
+
+    n = an;
+    if (a = n / 10)
+       putd (a);
+    put (n % 10 + '0');
+}
+
+put (ac)
+{
+    register    c;
+    int     tspace;
+
+    c = ac;
+    if (tabc)
+    {
+       putcp (c);
+       if (c == '\n')
+           line++;
+       return;
+    }
+    switch (c)
+    {
+
+       case ' ': 
+           nspace++;
+           col++;
+           return;
+
+    /*     case '\t':                      */
+                                      /*             c = '~';                
+                                      */
+                                      /*             break;                  
+                                      */
+                                      /*               nspace =& 0177770;    
+                                      */
+                                      /*               nspace =+ 010;        
+                                      */
+                                      /*               col    =& 0177770;    
+                                      */
+                                      /*               col    =+ 010;        
+                                      */
+                                      /*               return;               
+                                      */
+
+       case '\n': 
+           nspace = 0;
+           line++;
+           col = 0;
+           break;
+
+       case 010: 
+       case 033: 
+           if (--col < 0)
+               col = 0;
+           if (--nspace < 0)
+               nspace = 0;
+
+    }
+
+    if (rapflg && (col >= 84))        /* overflow             */
+    {
+       putcp ('\n');
+       line++;
+       tspace = col - 84;
+       col = nspace = 62;             /* 84 - 22              */
+       sppr ();
+       putcp ('*');
+       putcp ('*');
+       col =+ (2 + (nspace = tspace));
+    };
+
+    sppr ();
+
+    if (c >= ' ')
+       col++;
+    putcp (c);
+}
+
+sppr ()
+{
+    register int    c,
+                    ns;
+
+    if ((c != '\n') && (c != FF))
+       while (nspace)
+       {
+           if (
+                   (!tab2sp) &&
+                   (nspace > 2) &&
+                   (col > (ns = ((col - nspace) | 07)))
+               )
+           {
+               nspace = col - ns - 1;
+               putcp ('\t');
+           }
+           else
+           {
+               nspace--;
+               putcp (' ');
+           }
+       }
+}
+
+getn (ap)
+char   *ap;
+{
+    register int    n,
+                    c;
+    register char  *p;
+
+    p = ap;
+    n = 0;
+    if ((*p < '0') || (*p > '9'))
+       errrpt (p, "in parameter is supposed to be a number");
+
+    while ((c = *p++) >= '0' && c <= '9')
+       n = n * 10 + c - '0';
+    return (n);
+}
+
+putcp (c)
+{
+    if (page >= fpage)
+       putchar (c);
+}
+
+int     fout;
+
+errrpt (str1, str2)
+char   *str1,
+       *str2;
+{
+    int     ofout;
+
+    flush ();
+    ofout = fout;
+    fout = 2;
+
+    printf ("pr: \"%s\" %s.\n", str1, str2);
+
+    flush ();
+    fout = ofout;
+};
+
+
+#define DOT     "."
+#define DOTDOT  ".."
+#define ROOT    "/"
+#define DEBUG
+
+getpath (filestr)
+char   *filestr;
+{
+    int     n;
+    int     gpfile;
+    char   *fulpath;
+    struct statb
+    {
+       int     devn,
+               inum,
+               i[18];
+    }               x;
+    struct entry
+    {
+       int     jnum;
+       char    name[16];
+    }               y;
+
+
+
+    if (*filestr == '/')
+    {
+       fulpath = filestr;             /* already a full name      */
+       return (fulpath);
+    }
+
+    fulpath = alloc (1);              /* got to start somewhere       */
+    *fulpath = 0;
+    setexit ();
+
+    if (*fulpath)                     /* been here before ?           */
+    {
+       chdir (fulpath);               /* get back to original dir     */
+       rplstr (&fulpath,
+               dircat ("", fulpath));
+       rplstr (&fulpath,
+               dircat (fulpath, filestr));
+       return (fulpath);
+    }
+
+    while (1)
+    {
+       stat (DOT, &x);
+       if ((gpfile = open (DOTDOT, 0)) < 0)
+           reset ();
+       do
+       {
+           if ((n = read (gpfile, &y, 16)) < 16)
+               reset ();
+                                      /* printf("y.name = %s\n",y.name); */
+       }
+       while (y.jnum != x.inum);
+       close (gpfile);
+                                      /* printf("y.jnum = %d\n",y.jnum); */
+       if (y.jnum == 1)
+           ckroot (y.name, &fulpath);
+
+       rplstr (&fulpath,
+               dircat (y.name, fulpath));
+                                      /* printf("fulpath = %s\n",fulpath); */
+       chdir (DOTDOT);
+    }
+}
+
+ckroot (name, fulpath)
+char   *name,
+      **fulpath;
+{
+    int     i,
+            n;
+    int     gpfile;
+    struct statb
+    {
+       int     devn,
+               inum,
+               i[18];
+    }               x;
+    struct entry
+    {
+       int     jnum;
+       char    name[16];
+    }               y;
+
+
+    if ((n = stat (name, &x)) < 0)
+       reset ();
+    i = x.devn;
+
+    if (((n = chdir (ROOT)) < 0) ||
+           ((gpfile = open (ROOT, 0)) < 0))
+       reset ();
+
+ /* printf("fulpath = %s\n",*fulpath); */
+    while (1)
+    {
+       if ((n = read (gpfile, &y, 16)) < 16)
+           reset ();
+       if (y.jnum == 0)
+           continue;
+       if ((n = stat (y.name, &x)) < 0)
+           reset ();
+       if (x.devn != i)
+           continue;
+       x.i[0] =& 060000;
+       if (x.i[0] != 040000)
+           continue;
+       if ((strequ (y.name, ".")) ||
+               (strequ (y.name, "..")))
+           break;
+                                      /* printf("y.name = %s\n",y.name); */
+       rplstr (fulpath,
+               dircat (y.name, *fulpath));
+                                      /* printf("fulpath = %s\n",*fulpath); */
+    }
+    reset ();
+}
+
+
+/*                                                              */
+/*      Return the length of the given string. This length      */
+/*  does not include the terminating null character.            */
+
+pstrlen (string)
+char   *string;
+{
+    register char  *rstring;
+    register int    rlength;          /* length of string     */
+
+    rstring = string;
+
+    for (rlength = 0; *rstring++ != 0; ++rlength);
+    return (rlength);
+}
+
+
+/*                                                              */
+/*      Copy the given string to the given location.            */
+/*                                                              */
+
+strcpy (from, to)
+char   *from,
+       *to;
+{
+    register char  *rfrom,
+                   *rto;
+
+    rfrom = from;
+    rto = to;
+
+    while (*rto++ = *rfrom++);
+}
+
+/*                                                                */
+/*      Concatenate the first given string the the second         */
+/*      given string.                                             */
+
+dircat (prefix, suffix)
+char   *prefix,
+       *suffix;
+{
+    register char  *rprefix,
+                   *rsuffix,
+                   *ptr;
+    char   *newstr;
+
+    if ((ptr = newstr =
+               alloc (pstrlen (rprefix = prefix) +
+                   pstrlen (rsuffix = suffix) + 2))
+           == -1)
+    {
+       write (1, "No more string storage!\n", 24);
+       exit ();
+    }
+    while (*ptr++ = *rprefix++);
+    ptr--;
+    if (ptr[-1] != '/')
+       *ptr++ = '/';
+    while (*ptr++ = *rsuffix++);
+    return (newstr);
+}
+
+/*                                                              */
+/*      Determine if the two given strings are equivalent.      */
+/*                                                              */
+
+strequ (str1, str2)
+char   *str1,
+       *str2;
+{
+    register char  *rstr1,
+                   *rstr2;
+
+    rstr1 = str1;
+    rstr2 = str2;
+
+    while (*rstr1 == *rstr2++)
+       if (*rstr1++ == 0)
+           return (1);
+    return (0);
+}
+
+rplstr (oldstr, newstr)
+char  **oldstr,
+       *newstr;
+{
+                                      /* printf("oldstr = %s\nnewstr =
+                                         %s\n",*oldstr,newstr); */
+    free (*oldstr);
+    *oldstr = newstr;
+}
diff --git a/docs/historical/SRI-NOSC/pr.run b/docs/historical/SRI-NOSC/pr.run
new file mode 100644 (file)
index 0000000..d2a5c60
--- /dev/null
@@ -0,0 +1,2 @@
+cc -n pr.c
+if -r a.out mv a.out pr
diff --git a/docs/historical/SRI-NOSC/prompter.c b/docs/historical/SRI-NOSC/prompter.c
new file mode 100644 (file)
index 0000000..4ac6681
--- /dev/null
@@ -0,0 +1,323 @@
+#include "mh.h"
+#include "iobuf.h"
+#include "errors.h"
+#include "sgtty.h"
+#include "signals.h"
+
+/*#define CEDIT 01 */  /* use following editing chars */
+#define CKILL   006     /* @ => <CLOSE>         */
+#define CERASE  001      /* # => <CTRL A>        */
+
+/*define EDIT   001*/  /* edit after filling in fields */
+char    sysed[];
+
+int     fout;
+struct  iobuf in, out;
+struct  sgtty sg;
+struct swit switches[] {
+       "editor editor",  0,      /* 0 */
+       "erase chr",      2,      /* 1 */
+       "kill chr",       0,      /* 2 */
+       "help",           4,      /* 3 */
+       0,                0
+};
+
+
+main(argc, argv)
+char *argv[];
+{
+       char tmpfil[32], *drft, name[NAMESZ], field[512], *ed;
+       int exitstat;
+       char skill, serase;
+       char *killp, *erasep;
+       register int i, state;
+       register char *cp;
+       char *ap;
+       char *arguments[50], **argp;
+       int sig();
+       int status, pid, wpid, intr;
+
+       fout = dup(1);
+       skill = exitstat = 0;
+       ap = cp = argv[0];
+       while(*cp)
+               if(*cp++ == '/')
+                       ap = cp;
+       if((cp = m_find(ap)) != -1) {
+               ap = brkstring(cp = getcpy(cp), " ", '\n');
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++)
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto badleave;
+                                                       /* unknown */
+                       case -1:printf("prompter: -%s unknown\n", cp);
+                               goto badleave;
+                       case 0: if(!(ed = *argp++)) {   /* -editor */
+      missing:  printf("prompter: Missing argument for %s switch\n", argp[-2]);
+                                       goto badleave;
+                               }
+                               continue;
+                       case 1: if(!(erasep = *argp++))     /* -erase */
+                                       goto missing;
+                               continue;
+                       case 2: if(!(killp= *argp++))      /* -kill */
+                                       goto missing;
+                               continue;
+                       case 3: help("prompter    [file]  [switches]",
+                                    switches);
+                               goto badleave;
+                       }
+               else
+                       drft = cp;
+       if(!drft) {
+               printf("prompter: missing skeleton\n");
+               goto badleave;
+       }
+       if(fopen(drft, &in) == -1) {
+               printf("Can't open %s\n", drft);
+               goto badleave;
+       }
+       copy(makename("prmt", ".tmp"), copy("/tmp/", tmpfil));
+       if(fcreat(tmpfil, &out) == -1) {
+               printf("Can't create %s\n", tmpfil);
+               goto badleave;
+       }
+       chmod(tmpfil, 0700);
+       signal(SIGINT, &sig);
+       gtty(0, &sg);
+       skill = sg.sg_kill;
+       serase = sg.sg_erase;
+#ifdef CEDIT
+       sg.sg_kill =    killp ?  chrcnv(killp) : CKILL;
+       sg.sg_erase =   erasep ? chrcnv(erasep) : CERASE;
+#else
+       sg.sg_kill =    killp ?  chrcnv(killp) : skill;
+       sg.sg_erase =   erasep ? chrcnv(erasep) : serase;
+#endif
+       stty(0, &sg);
+       if ( skill != sg.sg_kill || serase != sg.sg_erase ) {
+               printf("Erase Char="); chrdisp(sg.sg_erase);
+               printf("; Kill Line="); chrdisp(sg.sg_kill);
+               printf(".\n"); flush();
+       }
+
+       state = FLD;
+       for(;;) switch(state = m_getfld(state,name,field,sizeof field,&in)) {
+
+       case FLD:
+       case FLDEOF:
+       case FLDPLUS:
+               if(field[0] != '\n' || field[1] != 0) {
+                       printf("%s:%s", name, field);
+                       puts(name, &out);
+                       putc(':', &out);
+                       puts(field, &out);
+                       while(state == FLDPLUS) {
+                               state=m_getfld(state,name,field,sizeof field,&in);
+                               printf("%s", field);
+                               puts(field, &out);
+                       }
+               } else {
+                       printf("%s: ", name);
+                       flush();
+                       i = getln(&field);
+                       if(i == -1)
+                               goto badleave;
+                       if(i == 0 && (field[0] == '\n' || !field[0]))
+                               continue;
+                       puts(name, &out); putc(':', &out);
+                       do {
+                               if(field[0] != ' ' && field[0] != '\t')
+                                       putc(' ', &out);
+                               puts(field, &out);
+                       } while(i == 1 && (i = getln(&field)) >= 0);
+                       if(i == -1)
+                               goto badleave;
+               }
+               field[0] = 0;
+               if(state == FLDEOF)
+                       goto body;
+               continue;
+
+       case BODY:
+       case BODYEOF:
+       case FILEEOF:
+  body:         puts("--------\n", &out);
+               printf("--------\n");
+               if(field[0]) {
+                       do {
+                               puts(field, &out);
+                               /*printf("%s", field);*/
+                       } while(state == BODY &&
+                               (state=m_getfld(state,name,field,sizeof field,&in)));
+               }
+               flush();
+               for(;;) {
+                       i = getln(&field);
+                       if (i == -1) goto badleave; /**/
+                       if(field[0] == 0)
+                               break;
+                       puts(field, &out);
+               }
+               goto done;
+
+       default:
+               printf("Bad format file!\n");
+               goto badleave;
+       }
+
+
+done:
+       printf("--------\n"); flush();
+       fflush(&out);
+       close(out.b_fildes);
+       fopen(tmpfil, &out);
+       close(in.b_fildes);
+       fcreat(drft, &in);              /* Truncate prior to copy back */
+       do
+               if((i = read(out.b_fildes, field, sizeof field)) > 0)
+                       write(in.b_fildes, field, i);
+       while(i == sizeof field);
+       close(in.b_fildes);
+       close(out.b_fildes);
+       unlink(tmpfil);
+again:
+       if(skill) {
+               sg.sg_kill = skill;
+               sg.sg_erase = serase;
+               stty(0, &sg);
+               skill = 0;
+       }
+
+#ifdef EDIT
+       printf("Edit? ");
+       flush();
+       getln(&field);
+       if(field[0] == 0)
+               goto badleave;
+       field[length(field) - 1] = 0;   /* zap <lf> */
+       if(field[0] == 0) {
+               printf("Options are:\n  no\n  yes\n  show\n  <any editor>\n");
+               goto again;
+       }
+       if(ssequal(field, "no"))
+               goto leave;
+       if(ssequal(field, "show")) {
+               if(showfile(drft))
+                       goto badleave;
+               goto again;
+       }
+       if(ssequal(field, "yes")) {
+               if(!ed &&
+                  ((ed = m_find("editor")) == -1 ||  equal(invo_name(), ed)))
+                       ed = sysed;
+       } else
+               ed = field;
+       intr = signal(SIGINT, 1);
+       if((pid = fork()) == 0) {
+           /*  m_update();  */
+               flush();
+               execlsrh(ed, drft, 0);
+               exit(-1);               /* can't exec editor */
+       } else if(pid == -1) {
+               printf("prompter: no forks!\n");
+               goto leave;
+       } else
+               while((wpid = waita(&status)) != -1 && wpid != pid) ;
+       if((status & 0177400) == 0177400) goto again;   /* -1 */
+       signal(SIGINT, intr);
+#endif
+       goto leave;
+
+badleave:
+       exitstat = 1;
+leave:
+       m_update();
+       flush();
+       if(skill) {
+               sg.sg_kill = skill;
+               sg.sg_erase = serase;
+               stty(0, &sg);
+       }
+       exit(exitstat);
+}
+
+
+
+
+getln(buf)
+char *buf;
+{
+       register char *cp;
+       register int c;
+
+       cp = buf;
+       *cp = 0;
+       for(;;) {
+               c = getchar();
+               if(c == 0)
+                       if(errno == EINTR)
+                               return(-1);
+                       else
+                               return(0);
+               if(c == '\n') {
+                       if ( cp != buf ) /* if not first char in line */
+                               if(cp[-1] == '\\') {
+                                       cp[-1] = c;
+                                       return(1);
+                               }
+                               if((buf==&(cp[-1]))&&(cp[-1] == '.')) {
+                                       buf[0] = 0;
+                                       return(0);
+                               }
+                               *cp++ = c;
+                               *cp   = 0;
+                               return(0);
+               }
+               if(cp < buf + 500)
+                       *cp++ = c;
+               *cp = 0;
+       }
+}
+
+
+sig()
+{
+       signal(SIGINT, &sig);
+       return;
+}
+
+
+chrcnv(str)
+{
+       register char *cp;
+       register int c;
+
+       cp = str;
+       if((c = *cp++) != '\\')
+               return(c);
+       c = 0;
+       while(*cp && *cp != '\n') {
+               c =* 8;
+               c =+ *cp++ - '0';
+       }
+       return c;
+}
+
+
+chrdisp(chr)
+{
+       register int c;
+
+       c = chr;
+       if(c < ' ')
+               printf("<CTRL-%c>", c + '@');
+       else
+               printf("%c", c);
+}
diff --git a/docs/historical/SRI-NOSC/prompter.run b/docs/historical/SRI-NOSC/prompter.run
new file mode 100644 (file)
index 0000000..60c2311
--- /dev/null
@@ -0,0 +1,5 @@
+if -r prompter rm prompter
+load -n prompter subs.a strings.a wait.o -O libg.a libh.a libg.a
+if -r a.out mv a.out prompter
+:                                      fini
+
diff --git a/docs/historical/SRI-NOSC/purge.c b/docs/historical/SRI-NOSC/purge.c
new file mode 100644 (file)
index 0000000..5e4a66a
--- /dev/null
@@ -0,0 +1,144 @@
+#include "mh.h"
+#include "stat.h"
+
+char *anoyes[];         /* Std no/yes gans array        */
+char defalt[];
+
+int     fout;
+
+struct msgs *mp;
+struct dirent {
+        int    inum;
+        char   name[14];
+        int    pad;
+};
+struct swit switches[] {
+       "help",         4,      /* 0 */
+       0,              0
+};
+
+main(argc, argv)
+char *argv[];
+{
+       register char *cp, *ap;
+       char *folder, *inp, buf[128];
+       int i, def_fold;
+       struct inode stbf;
+       struct dirent ent;
+       char *arguments[50], **argp;
+
+       fout = dup(1);
+#ifdef NEWS
+       m_news();
+#endif
+       folder = 0;
+       ap = cp = argv[0];
+       while(*cp)
+               if(*cp++ == '/')
+                       ap = cp;
+       inp = ap;
+       if((cp = m_find(ap)) != -1) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                       /* unknown */
+                       case -1:printf("-%s unknown\n", cp);
+                               goto leave;
+                                                       /* -help */
+                       case 0: help(concat( inp, " [+folder] [switches]", 0), switches);
+                               goto leave;
+                       }
+               if(*cp == '+')
+                       if(folder) {
+                               printf("Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               folder = cp + 1;
+               else {
+                       printf(concat("Usage: ", inp, " [+folder]\n",0));
+                       goto leave;
+               }
+       }
+       if(!folder) {
+               folder = m_getfolder();
+               def_fold++;
+       }
+       expfold(folder);
+ leave:
+       m_update();
+       flush();
+}
+
+
+expfold(fold)
+char *fold;
+{
+       char *maildir;
+       int i, expcount, nxtmsg, compactok;
+       register int msgnum;
+       register char *cp, *sp;
+       char nambuf[10];
+       struct inode stbf;
+
+       expcount = 0;
+       maildir = m_maildir(fold);
+       if(chdir(maildir) < 0) {
+               printf("Can't chdir to: "); flush();
+               perror(maildir);
+               return(1);
+       }
+       if(access(".", 2) == -1) {
+               printf("You cannot manipulate %s\n", fold);
+               return(1);
+       }
+       if(!(mp = m_gmsg(fold))) {
+               printf("Can't read folder!\n");
+               return(1);
+       }
+       if(mp->hghmsg == 0) {
+               printf("No messages in \"%s\".\n", fold);
+               return(1);
+       }
+       nxtmsg = 0;
+       compactok = TRUE;
+       for(msgnum = 1; msgnum<=mp->hghmsg; msgnum++)
+               if(mp->msgstats[msgnum]&EXISTS) {
+                       cp = getcpy(m_name(msgnum));
+                       if (mp->msgstats[msgnum]&DELETED)
+                           if(unlink(cp) == -1)
+                               printf("Can't unlink %s: %s\n", fold,cp);
+                           else {
+                               mp->msgstats[msgnum] =& ~EXISTS & ~DELETED;
+                               if(msgnum==mp->curmsg)
+                                       m_setcur(0);
+                               expcount++;
+                               if (nxtmsg == 0) nxtmsg = msgnum;
+                          }
+                       else if ((nxtmsg > 0) && compactok) {
+                               if(link(cp,sp=m_name(nxtmsg)) == -1) {
+                                  compactok = FALSE;
+                                  printf("Can't rename %s to %s.\n", cp, sp);
+                               }
+                               else if(unlink(cp) == -1) {
+                                  compactok = FALSE;
+                                  printf("Can't rename %s to %s.\n", cp, sp);
+                               }
+                               else {
+                                  if(msgnum==mp->curmsg)
+                                       m_setcur(nxtmsg);
+                                  nxtmsg++;
+                               }
+                               }
+                       }
+               else if(nxtmsg==0) nxtmsg = msgnum;
+       printf("%d message%s gone\n", expcount, expcount==1 ? "":"s");
+       return(0);
+}
diff --git a/docs/historical/SRI-NOSC/purge.run b/docs/historical/SRI-NOSC/purge.run
new file mode 100644 (file)
index 0000000..b73af25
--- /dev/null
@@ -0,0 +1,5 @@
+if -r purge rm purge
+load -n purge subs.a strings.a wait -O libg.a libh.a
+if -r a.out mv a.out purge
+:                                      fini
+
diff --git a/docs/historical/SRI-NOSC/putc.s b/docs/historical/SRI-NOSC/putc.s
new file mode 100644 (file)
index 0000000..e6474dd
--- /dev/null
@@ -0,0 +1,93 @@
+/ putw/putc -- write words/characters on output file
+
+       .globl  _putc, _putw, _fflush, _fcreat
+       .globl cerror
+       .comm   _errno,2
+
+_fcreat:
+       mov     r5,-(sp)
+       mov     sp,r5
+       mov     4(r5),0f
+       mov     6(r5),r1
+       mov     pc,(r1)         / a putatively illegal file desc.
+       sys     0; 9f
+.data
+9:     sys     creat; 0:..; 666
+.text
+       bes     badret
+       mov     r0,(r1)+
+       clr     (r1)+
+       clr     (r1)+
+       br      goodret
+
+_putw:
+       mov     r5,-(sp)
+       mov     sp,r5
+       mov     6(r5),r1
+       dec     2(r1)
+       bge     1f
+       jsr     pc,fl
+       bes     badret
+       dec     2(r1)
+1:
+       movb    4(r5),*4(r1)
+       inc     4(r1)
+       dec     2(r1)
+       bge     1f
+       jsr     pc,fl
+       bes     badret
+       dec     2(r1)
+1:
+       movb    5(r5),*4(r1)
+       inc     4(r1)
+       mov     4(r5),r0
+       br      goodret
+
+_putc:
+       mov     r5,-(sp)
+       mov     sp,r5
+       mov     6(r5),r1
+       dec     2(r1)
+       bge     1f
+       jsr     pc,fl
+       bes     badret
+       dec     2(r1)
+1:
+       mov     4(r5),r0
+       movb    r0,*4(r1)
+       inc     4(r1)
+       br      goodret
+
+_fflush:
+       mov     r5,-(sp)
+       mov     sp,r5
+       mov     4(r5),r1
+       jsr     pc,fl
+       bes     badret
+       br      goodret
+
+fl:
+       mov     r1,r0
+       add     $6,r0
+       mov     r0,-(sp)
+       mov     r0,0f
+       mov     4(r1),0f+2
+       beq     1f
+       sub     r0,0f+2
+       mov     (r1),r0
+       sys     0; 9f
+.data
+9:     sys     write; 0:..; ..
+.text
+1:
+       mov     (sp)+,4(r1)
+       mov     $512.,2(r1)
+       rts     pc
+
+badret:
+       jmp     cerror
+
+goodret:
+       clr     _errno
+       mov     (sp)+,r5
+       rts     pc
diff --git a/docs/historical/SRI-NOSC/reply.c b/docs/historical/SRI-NOSC/reply.c
new file mode 100644 (file)
index 0000000..ac9f42f
--- /dev/null
@@ -0,0 +1,333 @@
+#include "mh.h"
+#include "iobuf.h"
+#include "stat.h"
+#include "signals.h"
+
+/*#define TEST 1*/
+
+char    draft[],
+       sysed[],
+#ifdef PROMPT
+       prmtproc[],
+#endif
+       sndproc[];
+
+char    *anysh[] {
+       "no",   0,
+       "yes",  0,
+       "show", 0,
+       0
+};
+char    *anyv[] {
+       "no",           0,
+       "yes",          0,
+       "verbose",      0,
+       0
+};
+
+int  *vec[MAXARGS], fout, anot;
+int ccme 1;
+struct msgs *mp;
+char *ed;
+
+struct swit switches[] {
+       "annotate",           0,      /* 0 */
+       "noannotate",         0,      /* 1 */
+       "ccme",               0,      /* 2 */
+       "noccme",             0,      /* 3 */
+       "editor editor",      0,      /* 4 */
+       "help",               4,      /* 5 */
+       0,                    0
+};
+
+main(argc, argv)
+char *argv[];
+{
+       char *inp, *folder, *nfolder, *msg, *maildir;
+       register char *cp, *ap;
+       register int cur;
+       char *arguments[50], **argp;
+
+       fout = dup(1);
+#ifdef NEWS
+       m_news();
+#endif
+       msg = anot = folder = 0;
+
+       ap = cp = argv[0];
+       while(*cp)
+               if(*cp++ == '/')
+                       ap = cp;
+       inp = ap;
+       if((cp = m_find(ap)) != -1) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                            /* unknown */
+                       case -1:printf("-%s unknown\n", cp);
+                               goto leave;
+                       case 0: anot = 1;  continue;         /* -annotate */
+                       case 1: anot = 0;  continue;         /* -noannotate */
+                       case 2: ccme = 1;  continue;         /* -ccme */
+                       case 3: ccme = 0;  continue;         /* -noccme */
+                       case 4: if(!(ed = *argp++)) {        /* -editor */
+               printf("Missing argument for %s switch\n", argp[-2]);
+                                       goto leave;
+                               }
+                               continue;
+                                                            /* -help */
+                       case 5: help(concat( inp, " [+folder] [msg] [switches]", 0),
+                                    switches);
+                               goto leave;
+                       }
+               if(*cp == '+') {
+                       if(folder) {
+                               printf("Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               folder = cp + 1;
+               } else if(msg) {
+                       printf("Only one message at a time.\n");
+                       goto leave;
+               } else
+                       msg = cp;
+       }
+       if(!msg)
+               msg = "cur";
+       if(!folder)
+               folder = m_getfolder();
+       maildir = m_maildir(folder);
+       if(chdir(maildir) < 0) {
+               printf("Can't chdir to: "); flush();
+               perror(maildir);
+               goto leave;
+       }
+       if(!(mp = m_gmsg(folder))) {
+               printf("Can't read folder!?\n");
+               goto leave;
+       }
+       if(mp->hghmsg == 0) {
+               printf("No messages in \"%s\".\n", folder);
+               goto leave;
+       }
+       if(!m_convert(msg, UNDELETED, UNDELETED))
+               goto leave;
+       if(mp->numsel == 0) {
+               printf("No undeleted message specified\n");
+               goto leave;
+       }
+       if(mp->numsel > 1) {
+                printf("Only one message at a time.\n");
+                goto leave;
+       }
+       m_replace("folder", folder);
+       if(mp->lowsel != mp->curmsg)
+               m_setcur(mp->lowsel);
+       repl(getcpy(m_name(mp->lowsel)));
+ leave:
+       m_update();
+       flush();
+}
+
+
+repl(msg)
+{
+       register char *cp;
+       register int i,j;
+       struct iobuf in;
+       char name[NAMESZ], field[512], *from, *cc, *sub, *date, *to;
+       char *drft, *msgid;
+       int state, out, status, intr;
+       struct inode stbuf;
+
+       if(fopen(msg, &in) < 0) {
+               printf("Can't open \"%s\"\n", msg);
+               return;
+       }
+       drft = m_maildir(draft);
+       if((out = open(drft, 0)) >= 0) {
+/*
+               cp = concat("\"", drft, "\" exists; delete? ", 0);
+               while((i = gans(cp, anysh)) == 2)
+                       showfile(drft);
+               if(!i)
+                       return;
+               free(cp);
+*/
+               close(out);
+       }
+       if((out = creat(drft, m_gmprot())) < 0) {
+               printf("Can't create \"%s\".\n", drft);
+               return;
+       }
+
+       state = FLD;
+       msgid = to = from = cc = sub = date = 0;
+
+    for(;;) {
+
+       switch(state = m_getfld(state, name, field, sizeof field, &in)) {
+
+       case FLD:
+       case FLDEOF:
+       case FLDPLUS:
+               if(uleq(name, "from"))
+                       from = add(field, from);
+               if(uleq(name, "cc"))
+                       cc = add(field, cc);
+               if(uleq(name, "subject"))
+                       sub = add(field, sub);
+               if(uleq(name, "date"))
+                       date = add(field, date);
+               if(uleq(name, "to"))
+                       to = add(field, to);
+               if(uleq(name, "message-id"))
+                       msgid = add(field, msgid);
+               if(state == FLDEOF)
+                       goto done;
+               break;
+
+       case BODY:
+       case BODYEOF:
+       case FILEEOF:
+               goto done;
+
+       default:
+               printf("getfld returned %d\n", state);
+               return;
+       }
+
+    }
+
+done:   if(!from) {
+               printf("No one to reply to!!!\n");
+               return;
+       }
+       close(in.b_fildes);
+       type(out, "To: ");
+       if(*from == ' ') from++;
+       type(out, from);
+       if(cc) {
+               while(*cc == ' ') cc++;
+               if(*cc == '\n' && cc[1] == 0) cc = 0;
+       }
+       if(to) {
+               while(*to == ' ') to++;
+               if(*to == 0) to = 0;
+       }
+       if(!ccme)
+               to = 0;
+       if(cc || to)
+               type(out, "cc: ");
+       if(cc) {
+               if(to) {
+                       cp = cc+length(cc)-1;
+                       if(*cp == '\n') *cp = 0;
+                       while(*--cp == ' ') ;
+                       *++cp = 0;
+               }
+               type(out, cc);
+       }
+       if(to) {
+               if(cc)
+                       type(out, ",\n    ");
+               type(out, to);
+       }
+       if(sub) {
+               type(out, "Subject: ");
+               if(*sub == ' ') sub++;
+               if((sub[0] != 'R' && sub[0] != 'r') ||
+                  (sub[1] != 'E' && sub[1] != 'e') ||
+                  sub[2] != ':')
+                       type(out, "Re: ");
+               type(out, sub);
+       }
+       if(date) {
+               type(out, "In-reply-to: Your message of ");
+               date[length(date)-1] = '.';
+               if(*date == ' ') date++;
+               type(out, date);
+               type(out, "\n");
+               if(msgid) {
+                       type(out, "             ");
+                       if(*msgid == ' ') msgid++;
+                       type(out, msgid);
+               }
+       }
+       type(out, "----------\n");
+       close(out);
+       if(!ed && (ed = m_find("editor")) == -1)
+#ifdef PROMPT
+               ed = prmtproc;
+#else
+               ed = sysed;
+#endif
+       intr = signal(SIGINT, 1);
+       if((out = fork()) == 0) {
+               unlink("@"); link(msg, "@");  /* An easy handle on cur msg */
+               m_update();
+               flush();
+       /***    printf("execlsh(%s, %s, 0)\n", ed, drft); flush();   ***/
+               execlsrh(ed, drft, 0);
+               printf("Can't exec the editor:  ");
+               flush(); perror(ed); exit(1);
+       } else if(out == -1) {
+               printf("No Forks\n");
+               return;
+       } else {
+               while((state = waita(&status)) != -1 && state != out) ;
+               signal(SIGINT, intr);
+               if(status) {
+                       if(status > 0377)
+                               unlink(drft);
+                       printf("[command aborted--%s %s]\n", drft,
+                               status > 0377? "deleted" : "preserved");
+                       unlink("@");
+                       return;
+               }
+       }
+#ifdef TEST
+       printf("!! Test Version of SEND Being Run !!\n");
+       printf("   Send verbose !\n\n");
+#endif
+/*     cp = concat("Send \"", draft, "\"? ", 0); */
+       cp = "Send? ";
+       if((j = gans(cp, anyv)) > 0) {
+               stat("@", &stbuf);
+               if(stbuf.i_nlink == 1)
+                       if(unlink(msg) == -1 || link("@", msg) == -1) {
+                               printf("Can't update %s from @ file!\n",msg);
+                               return(0);
+                       }
+               unlink("@");            /* Remove this extra link       */
+               if(anot > 0 || (!anot && m_find("reply-annotate") != -1)) {
+                       while((state = fork()) == -1) sleep(5);
+                       if(state) {
+                               while(out=wait()!= -1 && out != state);
+                               if(stat(drft, field) == -1)
+                                       annotate(msg, "Replied", "");
+                               return;
+                       }
+               }
+               i = 0;
+               vec[i++] = "mh-sndproc";
+               vec[i++] = drft;
+               if(j == 2)
+                       vec[i++] = "-verbose";
+               vec[i++] = 0;
+               m_update();
+               flush();
+               execv(sndproc, vec);
+               printf("Can't exec send!!\n");
+       } else
+               unlink("@");            /* Remove this extra link       */
+}
+
diff --git a/docs/historical/SRI-NOSC/reply.run b/docs/historical/SRI-NOSC/reply.run
new file mode 100644 (file)
index 0000000..f541fab
--- /dev/null
@@ -0,0 +1,5 @@
+if -r reply rm reply
+load -n reply annotate subs.a strings.a wait -O libg.a libh.a libg.a
+if -r a.out mv a.out reply
+:                                      fini
+
diff --git a/docs/historical/SRI-NOSC/rmf.c b/docs/historical/SRI-NOSC/rmf.c
new file mode 100644 (file)
index 0000000..0ef8815
--- /dev/null
@@ -0,0 +1,178 @@
+#include "mh.h"
+#include "stat.h"
+
+char *anoyes[];         /* Std no/yes gans array        */
+char defalt[];
+
+int     fout;
+int     subf;
+
+struct msgs *mp;
+struct dirent {
+        int    inum;
+        char   name[14];
+        int    pad;
+};
+struct swit switches[] {
+       "help",         4,      /* 0 */
+       0,              0
+};
+
+main(argc, argv)
+char *argv[];
+{
+       register char *cp, *ap;
+       char *folder, buf[128];
+       int i, def_fold;
+       struct inode stbf;
+       struct dirent ent;
+       char *arguments[50], **argp;
+
+       fout = dup(1);
+#ifdef NEWS
+       m_news();
+#endif
+       folder = 0;
+       ap = cp = argv[0];
+       while(*cp)
+               if(*cp++ == '/')
+                       ap = cp;
+       if((cp = m_find(ap)) != -1) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                       /* unknown */
+                       case -1:printf("rmf: -%s unknown\n", cp);
+                               goto leave;
+                                                       /* -help */
+                       case 0: help("rmf [+folder]  [switches]", switches);
+                               goto leave;
+                       }
+               if(*cp == '+')
+                       if(folder) {
+                               printf("Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               folder = cp + 1;
+               else {
+                       printf("Usage: rmf [+folder]\n");
+                       goto leave;
+               }
+       }
+       if(!folder) {
+               folder = m_getfolder();
+               def_fold++;
+       }
+       subf = !((!any('/', folder)) | (*folder == '/') | (*folder == '.'));
+       if(def_fold && !subf) {
+               cp = concat("Remove folder \"", folder, "\" ?? ", 0);
+               if(!gans(cp, anoyes))
+                       goto leave;
+               free(cp);
+       }
+       if(rmfold(folder))
+               goto leave;
+       if(subf) {
+               cp = copy(folder, buf);
+               while(cp > buf && *cp != '/') --cp;
+               if(cp > buf) {
+                       *cp = 0;
+                       printf("[+%s now current]\n", buf);
+                       m_replace("folder", buf);
+               }
+       }
+ leave:
+       m_update();
+       flush();
+}
+
+struct dirent ent;
+
+rmfold(fold)
+char *fold;
+{
+       register char *maildir;
+       int i, leftover;
+       register char *cp, *sp;
+       char nambuf[10];
+       struct inode stbf;
+
+       leftover = 0;
+       if(!subf && equal(m_find("folder"), fold)) {  /* don't re-do */
+               printf("[+%s now current]\n", defalt);
+               flush();                                 /*??*/
+               m_replace("folder", defalt);
+       }
+       maildir = m_maildir(fold);
+       if(chdir(maildir) < 0) {
+               printf("Can't chdir to: "); flush();
+               perror(maildir);
+               return(1);
+       }
+       if(access(".", 2) == -1) {
+               if(!m_delete(concat("cur-", fold, 0)))
+                       printf("[Folder %s de-referenced]\n", fold);
+               else
+ printf("You have no profile entry for the read-only folder %s\n", fold);
+               return(1);
+       }
+       i = open(".", 0);
+       ent.pad = 0;
+       while(read(i, &ent.inum, sizeof ent.name + sizeof ent.inum))
+               if(ent.inum)
+                   if((ent.name[0] >= '0' && ent.name[0] <= '9') ||
+                      ent.name[0] == ','     ||
+                      equal(ent.name, "cur") ||
+                      equal(ent.name, "@")) {
+                           if(unlink(ent.name) == -1) {
+                               printf("Can't unlink %s:%s\n", fold,ent.name);
+                               leftover++;
+                           }
+                   } else if(!equal(ent.name,".")&& !equal(ent.name,"..")) {
+                       printf("File \"%s/%s\" not deleted!\n",
+                               fold, ent.name);
+                       leftover++;
+                   }
+       close(i);
+       if(!leftover && removedir(maildir))
+               return(0);
+       else
+               printf("Folder %s not removed!\n", fold);
+       return(1);
+}
+
+
+removedir(dir)
+{
+       register int i, j;
+       int status;
+
+       if((i = fork()) == 0) {
+               m_update();
+               flush();
+               execl("/bin/rmdir", "rmdir", dir, 0);
+               printf("Can't exec rmdir!!?\n");
+               flush();
+               return(0);
+       }
+       if(i == -1) {
+               printf("Can't fork\n");
+               flush();
+               return(0);
+       }
+       while((j = waita(&status)) != i && j != -1) ;
+       if(status) {
+               printf("Bad exit status (%o) from rmdir.\n", status);
+               flush();
+           /*  return(0);   */
+       }
+       return(1);
+}
diff --git a/docs/historical/SRI-NOSC/rmf.run b/docs/historical/SRI-NOSC/rmf.run
new file mode 100644 (file)
index 0000000..3f8a79c
--- /dev/null
@@ -0,0 +1,5 @@
+if -r rmf rm rmf
+load rmf subs.a strings.a wait -O libg.a libh.a
+if -r a.out mv a.out rmf
+:                                      fini
+
diff --git a/docs/historical/SRI-NOSC/scan.c b/docs/historical/SRI-NOSC/scan.c
new file mode 100644 (file)
index 0000000..dc4333c
--- /dev/null
@@ -0,0 +1,126 @@
+#include "mh.h"
+#include "iobuf.h"
+
+int hdrflag 1;
+struct msgs *mp;
+struct iobuf fout;
+struct swit switches[] {
+       "all",         -3,      /* 0 */
+       "ff",           0,      /* 1 */
+       "noff",         0,      /* 2 */
+       "header",       0,      /* 3 */
+       "noheader",     0,      /* 4 */
+       "help",         4,      /* 5 */
+       0,              0
+};
+
+main(argc, argv)
+char *argv[];
+{
+       char *inp, *folder, *maildir, *msgs[100];
+       register int msgnum;
+       register char *cp, *ap;
+       int msgp, ff;
+       struct iobuf in;
+       long now;
+       char *arguments[50], **argp;
+
+       fout.b_fildes = dup(1);
+#ifdef NEWS
+       m_news();
+#endif
+       ff = msgp = folder = 0;
+       ap = cp = argv[0];
+       while(*cp)
+               if(*cp++ == '/')
+                       ap = cp;
+       inp = ap;
+       if((cp = m_find(ap)) != -1) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+         /*    printf("1:\n");    flush();                 ##*/
+         /*    pr_array("arguments", arguments); flush();  ##*/
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+  /*    printf("2:\n");  flush();                   ##*/
+  /*    pr_array("arguments", arguments); flush();  ##*/
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                       /* unknown */
+                       case -1:printf("-%s unknown\n", cp);
+                               goto leave;
+                                                        /* -all */
+                       case 0: printf("\"-all\" changed to \"all\"\n");
+                               goto leave;
+                       case 1: ff = 1;  continue;      /* -ff */
+                       case 2: ff = 0;  continue;      /* -noff */
+                       case 3: hdrflag = 0;  continue; /* -header */
+                       case 4: hdrflag = 1;  continue; /* -noheader */
+                       case 5: help(concat( inp, " [+folder] [msgs] [switches]", 0),
+                                    switches);
+                               goto leave;
+                       }
+               if(*cp == '+') {
+                       if(folder) {
+                               printf("Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               folder = cp + 1;
+               } else
+                       msgs[msgp++] = cp;
+       }
+       if(!folder)
+               folder = m_getfolder();
+       maildir = m_maildir(folder);
+       if(chdir(maildir) < 0) {
+               printf("Can't chdir to: "); flush();
+               perror(maildir);
+               goto leave;
+       }
+       if(!(mp = m_gmsg(folder))) {
+               printf("Can't read folder!?\n");
+               goto leave;
+       }
+       if(mp->hghmsg == 0) {
+               printf("No messages in \"%s\".\n", folder);
+               goto leave;
+       }
+       if(!msgp)
+               msgs[msgp++] = "first-last";
+       for(msgnum = 0; msgnum < msgp; msgnum++)
+               if(!m_convert(msgs[msgnum], EXISTS, EXISTS))
+                       goto leave;
+       m_replace("folder",folder);
+       for(msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)  {
+               if(mp->msgstats[msgnum]&SELECTED) {
+                       if(fopen(cp = m_name(msgnum), &in) < 0)
+                               printf("--Can't open %s\n", cp);
+                       else {
+                               if(!hdrflag++) {
+                                       time(&now);
+                                       cp = cdate(&now);
+                                       cp[9] = ' '; cp[15] = 0;
+printf("\
+                      Folder %-32s%s\n\n\
+  #   Date    From             Subject       [<<Body]\n\n", folder, cp);
+                               }
+                               scan(&in, msgnum, 0, msgnum == mp->curmsg);
+                               close(in.b_fildes);
+                               if(fout.b_nextp + 80 >= (&fout) + 1)
+                       /*      if(msgnum & 1)  */
+                                       flush();
+                       }
+               }
+       }
+       if(ff)
+               putchar('\014');
+leave:
+       m_update();
+       flush();
+}
+
diff --git a/docs/historical/SRI-NOSC/scan.run b/docs/historical/SRI-NOSC/scan.run
new file mode 100644 (file)
index 0000000..4ed0c93
--- /dev/null
@@ -0,0 +1,5 @@
+if -r scan rm scan
+load -n scan scansub subs.a strings.a wait -O libg.a libh.a
+if -r a.out mv a.out scan
+:                                      fini
+
diff --git a/docs/historical/SRI-NOSC/scansub.c b/docs/historical/SRI-NOSC/scansub.c
new file mode 100644 (file)
index 0000000..b8c1411
--- /dev/null
@@ -0,0 +1,361 @@
+#include "mh.h"
+#include "iobuf.h"
+
+#define FROM    13              /* Start of From field          */
+#define SFROM   16              /* Length of "        "         */
+#define DATE     5              /* Start of Date field          */
+#define SDATE    7              /* Length                       */
+#define SUBJ    31              /* Start of Subject field       */
+#define SSUBJ   (79-SUBJ)       /* Size of Subject field        */
+#define BSUBJ   20              /* Room needed in Sub field to  */
+                               /* add stuff from the body      */
+#define MSGN     0              /* Start of msg name field      */
+#define SMSGN    3              /* Length                       */
+#define FLGS     3              /* Start of flags field         */
+#define SFLGS    2              /* Width of flag field          */
+
+struct  iobuf scnout, fout;
+int errno;
+char scanl[82];
+
+scan(inb, innum, outnum, curflg)
+struct iobuf *inb;
+int outnum;
+{
+
+       char buf[512], name[NAMESZ], tobuf[32], frombuf[32];
+       register char *cp;
+       int state, subsz, first, compnum;
+       static char *myname;
+
+       if(!myname)
+               myname = getlogn(getruid());
+       tobuf[0] = frombuf[0] = 0;
+       errno = first = 0;
+       state = FLD;
+       compnum = 1;
+
+       for(;;) {
+
+               state = m_getfld(state, name, buf, sizeof buf, inb);
+               if(!first++ && state >= FLD && state != FILEEOF) {
+                   if(outnum) {
+                       if(fcreat((cp = m_name(outnum)),&scnout)<0) {
+                               printf("Error creating msg "); flush();
+                               perror(cp); exit(-1);
+                       }
+                       chmod(cp, m_gmprot());
+                   }
+                   sfill(scanl, sizeof scanl);
+                   scanl[sizeof scanl - 1] = 0;
+                   subsz = 0;
+                   tobuf[0] = 0;
+               }
+
+               switch(state) {
+
+               case FLD:
+               case FLDEOF:
+               case FLDPLUS:
+                       compnum++;
+                       if(uleq(name, "from"))
+                               frombuf[cpyfrm(buf, frombuf, sizeof frombuf)]=0;
+                       else if(uleq(name, "date"))
+                               cpydat(buf, scanl+DATE, SDATE);
+                       else if(uleq(name, "subject") && scanl[SUBJ] == ' ')
+                               subsz = cpy(buf, scanl+SUBJ, SSUBJ);
+                       else if(uleq(name, "to") && !tobuf[0])
+                               tobuf[cpyfrm(buf, tobuf, sizeof tobuf-1)] = 0;
+                       else if(uleq(name, "replied"))
+                               cpy("-", scanl+FLGS+1, 1);
+                       put(name, buf, &scnout);
+                       while(state == FLDPLUS) {
+                               state=m_getfld(state,name,buf,sizeof buf,inb);
+                               puts(buf, &scnout);
+                       }
+                       if(state == FLDEOF)
+                               goto putscan;
+                       continue;
+
+               case BODY:
+               case BODYEOF:
+                       compnum = -1;
+                       if(buf[0] && subsz < SSUBJ - BSUBJ) {
+                               scanl[SUBJ+subsz+1] = '<';
+                               scanl[SUBJ+subsz+2] = '<';
+                               cpy(buf, scanl+SUBJ+subsz+3, SSUBJ-subsz-3);
+                               subsz = SSUBJ;
+                       }
+                       if(buf[0] && scnout.b_fildes) {
+                               putc('\n', &scnout);
+                               if(errno) {
+                                       perror("Write error:");exit(-1);
+                               }
+                       }
+                       puts(buf, &scnout);
+                       while(state == BODY) {
+                               state=m_getfld(state,name,buf,sizeof buf,inb);
+                               puts(buf, &scnout);
+                       }
+                       if(state == BODYEOF) {
+                 putscan:      cpymsgn(m_name(innum), scanl+MSGN, SMSGN);
+                               if(!frombuf[0] || uleq(frombuf, myname)) {
+                                       cpy("To:", scanl+FROM, 3);
+                                       cpy(tobuf, scanl+FROM+3, SFROM-3);
+                               } else
+                                       cpy(frombuf, scanl+FROM, SFROM);
+                               if(curflg)
+                                       cpy("+", scanl+FLGS, SFLGS);
+                               trim(scanl);
+                               puts(scanl, &fout);
+
+                               if(scnout.b_fildes) {
+                                       fflush(&scnout);
+                                       if(errno) {
+                                               perror("Write error");
+                                               exit(-1);
+                                       }
+                                       close(scnout.b_fildes);
+                                       scnout.b_fildes = 0;
+                               }
+                               return(1);
+                       }
+                       break;
+
+               case LENERR:
+               case FMTERR:
+                       printf("??Message Format Error ");
+                       if(outnum) printf("(Message %d) ", outnum);
+                       if(compnum < 0) printf("in the Body.\n");
+                       else printf("in Component #%d.\n", compnum);
+                       goto badret;
+               default:
+                       printf("Getfld returned %d\n", state);
+       badret:         if(scnout.b_fildes)
+                               fflush(&scnout);
+                       return(-1);
+               case FILEEOF:
+                       return(0);
+
+               }
+
+       }
+}
+
+
+trim(str)
+{
+       register char *cp;
+
+       cp = str;
+       while(*cp) cp++;
+       while(*--cp == ' ') ;
+       cp++;
+       *cp++ = '\n';
+       *cp++ = 0;
+}
+
+sfill(str, cnt)
+{
+       register char *cp;
+       register int i;
+
+       cp = str;  i = cnt;
+       do
+               *cp++ = ' ';
+       while(--i);
+}
+
+
+put(name, buf, iob)
+{
+       register struct iobuf *ip;
+
+       ip = iob;
+       if(ip->b_fildes) {
+               puts(name, iob);
+               putc(':', iob);
+               if(errno) { perror("Write error");exit(-1);}
+               puts(buf, iob);
+       }
+}
+
+
+cpy(sfrom, sto, cnt)
+{
+       register char *from, *to;
+       register int c;
+       int i;
+
+       from = sfrom;  to = sto;
+       i = cnt;
+       while(*from == ' ' || *from == '\t' || *from == '\n')
+               from++;
+       while(i--)
+               if(c = *from) {
+                       if(c == '\t' || c == ' ' || c == '\n') {
+                               *to++ = ' ';
+                               do 
+                                       from++;
+                               while((c= *from)==' '||c=='\t'||c=='\n');
+                               continue;
+                       } else
+                               *to++ = c;
+                       from++;
+               } else
+                       break;
+       return(from - sfrom - 1);
+}
+
+
+cpydat(sfrom, sto, cnt)
+{
+       register char *from, *cp;
+       register int c;
+       static int *locvec;
+       long now;
+       char *to;
+
+       if(!locvec) {
+               time(&now);
+               locvec = localtime(&now);
+       }
+       to = sto;
+       for(from = sfrom; (c = *from) < '0' || c > '9'; from++)
+               if(!c)
+                       return;
+       c = cnt;
+       for(cp = from; (*cp >= '0' && *cp <= '9') || *cp == ' '; cp++);
+       if(cp = findmonth(cp)) {
+               if(!cp[1]) {
+                       *to++ = ' ';
+                       c--;
+               }
+               while(*cp && c--)
+                       *to++ = *cp++;
+               c--;  *to++ = '/';
+               if(from[1] == ' ') {
+                       *to++ = ' ';
+                       c--;
+               }
+               while(*from >= '0' && *from <= '9' && c--)
+                       *to++ = *from++;
+               if(c >= 2) {
+                       while(*from < '0' || *from > '9') from++;
+                       if((c = atoi(from)) > 1970 && c-1900 < locvec[5]) {
+                               *to++ = '/';
+                               *to++ = c - 1970 + '0';
+                       }
+               }
+               return;
+       }
+       if(from[1] == ' ') {
+               *to++ = ' ';
+               c--;
+       }
+       while(*from && c--)
+               *to++ = *from++;
+}
+
+
+char    *fromp, fromdlm, pfromdlm;
+
+cpyfrm(sfrom, sto, cnt)
+{
+       register char *to, *cp;
+       register int c;
+
+       fromdlm = ' ';
+       fromp = sfrom; to = sto;
+       cp = frmtok();
+       do
+               if(c = *cp++)
+                       *to++ = c;
+               else
+                       break;
+       while(--cnt);
+       for(;;) {
+               if(cnt < 3) break;
+               if(*(cp = frmtok()) == 0) break;
+               if(*cp == '@' || uleq(cp, "at")) {
+                       cp = frmtok();
+                       if(!uleq(cp, "rand-unix")) {
+                               *to++ = '@';
+                               cnt--;
+                               do
+                                       if(c = *cp++)
+                                               *to++ = c;
+                                       else
+                                               break;
+                               while(--cnt);
+                       }
+               } else if(cnt > 4) {
+                       cnt--; *to++ = pfromdlm;
+                       do
+                               if(c = *cp++)
+                                       *to++ = c;
+                               else
+                                       break;
+                       while(--cnt);
+               }
+       }
+       return(to - sto);
+}
+
+
+frmtok()
+{
+       static tokbuf[64];
+       register char *cp;
+       register int c;
+
+       pfromdlm = fromdlm;
+       cp = tokbuf; *cp = 0;
+       while(c = *fromp++) {
+               if(c == '\t')
+                       c = ' ';
+               if(c == ' ' && cp == tokbuf)
+                       continue;
+               if(c == ' ' || c == '\n' || c == ',')
+                       break;
+               *cp++ = c;
+               *cp = 0;
+               if(c == '@' || *fromp == '@' || cp == &tokbuf[63])
+                       break;
+       }
+       fromdlm = c;
+       return(tokbuf);
+}
+
+
+/*      num specific!         */
+
+cpymsgn(msgnam, addr, len)
+char *msgnam, *addr;
+{
+       register char *cp, *sp;
+
+       sp = msgnam;
+       cp = addr + (len - length(sp));
+       while(*sp)
+               *cp++ = *sp++;
+}
+
+char *monthtab[] {
+       "jan", "feb", "mar", "apr", "may", "jun",
+       "jul", "aug", "sep", "oct", "nov", "dec",
+};
+
+findmonth(str)
+{
+       register char *cp, *sp;
+       register int i;
+       char buf[4];
+
+       for(cp=str, sp=buf; (*sp++ = *cp++) && sp < &buf[3] && *cp != ' '; );
+       *sp = 0;
+       for(i = 0; i < 12; i++)
+               if(uleq(buf, monthtab[i]))
+                       return(locv(0, i+1));
+       return(0);
+}
diff --git a/docs/historical/SRI-NOSC/send-ec.run b/docs/historical/SRI-NOSC/send-ec.run
new file mode 100755 (executable)
index 0000000..16093cf
--- /dev/null
@@ -0,0 +1,7 @@
+if -r send-ec rm send-ec
+load -n send subs.a strings-ec.a \
+       libg.a libh.a \
+       mailib.a \
+       mailib.a \
+       | tee errlst
+if -r a.out mv a.out send-ec
diff --git a/docs/historical/SRI-NOSC/send.c b/docs/historical/SRI-NOSC/send.c
new file mode 100644 (file)
index 0000000..0a6250b
--- /dev/null
@@ -0,0 +1,933 @@
+#include "mh.h";
+#include "iobuf.h"
+#include "stat.h"
+
+#define DEBUG 1                          /* Comment out normally */
+#define TIMJUL  1
+#define TIMSECS 2
+#define TIMREG  3
+
+/* Include a -msgid switch to .mh_defs to cause a
+ * Message-Id component to be added to outgoing mail.
+ */
+
+char   *anoyes[],                /* Std no/yes gans array        */
+        draft[],
+       locname[],              /* local host name */
+       sbmitloc[],             /* location (pathname) of submit process */
+       sbmitnam[];             /* name of submit process */
+struct swit switches[]
+{
+    "debug", -1,                 /* 0 */
+    "draft", 0,                          /* 1 */
+    "format", 0,                 /* 2 */
+    "noformat", 0,               /* 3 */
+    "msgid", 0,                          /* 4 */
+    "nomsgid", 0,                /* 5 */
+    "verbose", 1,                /* 6 *//* DBG dhc */
+    "noverbose", 0,              /* 7 */
+    "help", 4,                   /* 8 */
+    0, 0
+};
+struct iobuf    in,
+                pin,
+                pout,
+                fout,
+                fccout;
+int     errno;
+int     format 0;                /* re-formatting is the default */
+int     sbmitfd[2];
+int     sbchild;
+
+char   *logn,
+       *parptr,
+       *nmsg,
+        fccfile[256],
+        sberrline[256];
+
+main (argc, argv)
+char   *argv[];
+{
+    int     debug;
+    register char  *cp;
+    register int    state;
+    char   *to,
+           *cc,
+           *bcc,
+           *dist_to,
+           *dist_cc,
+           *dist_bcc;
+    char   *tolist,
+           *cclist,
+           *adrlist,
+           *sender,
+       *fieldptr,
+           *fcc,
+           *dist_fcc;
+    char    msg[128];
+    char    name[NAMESZ],
+            field[512];
+    int     specfld,
+            dist,
+            fcconly;
+    int     from,
+            loc,
+            net,
+            verbose,
+            msgid;
+    char   *ap,
+       inp;
+    char   *arguments[50],
+          **argp;
+
+    fout.b_fildes = dup (1);
+    msgid = from = loc = net = to = cc = bcc = dist = fcc = dist_fcc =
+       dist_to = dist_cc = dist_bcc = fcconly = debug = 0;
+
+    loc = net = 1;  /* DBG during testing of new submit */
+
+    state = FLD;
+    msg[0] = 0;
+       ap = cp = argv[0];
+       while(*cp)
+               if(*cp++ == '/')
+                       ap = cp;
+       inp = ap;
+    copyip (argv + 1, arguments);
+    argp = arguments;
+    while (cp = *argp++)
+    {
+       if (*cp == '-')
+           switch (smatch (++cp, switches))
+           {
+               case -2: 
+                   ambigsw (cp, switches);
+                                 /* ambiguous */
+                   leave ("Illegal switch setting: \"%s\"", --cp);
+                                 /* unknown */
+               case -1: 
+                   leave ("-%s unknown", cp);
+               case 0: 
+                   verbose++;
+                   debug++;
+                   continue;     /* -debug */
+               case 1: 
+                   copy (m_maildir (draft), msg);
+                   continue;     /* -draft  */
+               case 2: 
+/* disabled for now format = 1;                         */
+                   continue;     /* -format */
+               case 3: 
+                   format = 0;
+                   continue;     /* -noformat */
+               case 4: 
+                   msgid = 1;
+                   continue;     /* -msgid */
+               case 5: 
+                   msgid = 0;
+                   continue;     /* -nomsgid */
+               case 6: 
+                   loc = 1;
+                   net = 1;
+                   continue;     /* -verbose */
+               case 7: 
+                   loc = 0;
+                   net = 0;
+                   continue;     /* -noverbose */
+               case 8: 
+                 help (concat( inp, " [file] [switches]", 0),
+                           switches);
+                   leave (0);
+           }
+       if (msg[0])
+           leave ("Only one message at a time!");
+       else
+           copy (cp, msg);
+    }
+    if (msg[0] == 0)
+    {
+       copy (m_maildir (draft), msg);
+       if (stat (msg, &field) == -1)
+       {
+           printf ("Draft file: %s doesn't exist.\n", msg);
+           flush ();
+           exit (1);
+       }
+       /* cp = concat ("Use \"", msg, "\"? ", 0);
+       if (!gans (cp, anoyes))
+           exit (0); */
+    }
+    if (fopen (msg, &in) < 0)
+       leave ("Can't open \"%s\" for reading.", msg);
+
+    state = FLD;
+
+    if (!loc && !net)
+        printf ("Message being processed...\n");
+    flush ();
+    for (;;)
+       switch (state = m_getfld (state, name, field, sizeof field, &in))
+       {
+
+           case FLD: 
+           case FLDEOF: 
+           case FLDPLUS: 
+               if (!dist && field[0] != 'n' &&  uleq (name, "to"))
+                   to = adrlist = add (field, adrlist);
+               else
+                   if (!dist && field[0] != 'n' && uleq (name, "cc"))
+                       cc = adrlist = add (field, adrlist);
+                   else
+                       if (!dist && uleq (name, "bcc"))
+                           adrlist = add (field, adrlist);
+                       else
+                           if (!dist && uleq (name, "fcc"))
+                               fcc = add (field, fcc);
+                           else
+                               if (field[0] != 'n' && uleq (name, "distribute-to"))
+                               {
+                                   dist++;
+                                 /* use presence of field as flag */
+                                   to = adrlist = add (field, adrlist);
+                               }
+                               else
+                                   if (field[0] != 'n' && uleq (name, "distribute-cc"))
+                                       cc = adrlist = add (field, adrlist);
+                                   else
+                                       if (field[0] != 'n' && uleq (name, "distribute-bcc"))
+                                           adrlist = add (field, adrlist);
+                                       else
+                                           if (uleq (name, "distribute-fcc"))
+                                               dist_fcc = add (field, dist_fcc);
+                                           else
+                                               if (uleq (name, "from"))
+                                                   from++;
+
+               if (state != FLDEOF)
+                   continue;
+           case BODY: 
+           case BODYEOF: 
+               goto done;
+
+           default: 
+               leave ("getfld returned %d", state);
+       }
+done: 
+    if (dist)
+    {
+/*      to = dist_to;                                                   */
+/*      cc = dist_cc;                                                   */
+/*      bcc = dist_bcc;                                                 */
+       fcc = dist_fcc;
+    }
+    if (!(to || cc))
+       if (!fcc)
+           leave ("Message %s has no addresses!!", msg);
+       else
+           fcconly++;
+     /****/ pin.b_fildes = dup (2);
+/**** pout.b_fildes = 3;*/
+
+/*  if ((to && parse (to, 'c')) ||                                      */
+/*      (cc && parse (cc, 'c')) ||                                      */
+/*      (bcc && parse (bcc, 'c'))                                       */
+/*          leavit ();                                                  */
+
+/*  parptr = adrlist;                                                   */
+/*  compress ();                                                        */
+/*  adrlist = parptr;                                                   */
+    parptr = 0;
+    if (verbose)
+    {
+       printf ("Address List:\n%s", adrlist);
+       flush ();
+    }
+
+/*  if (to && parse (to, 'r', dist ? "Distribute-To: " : "To: "))       */
+/*          leave (0);                                                  */
+/*  tolist = parptr;                                                    */
+/*  parptr = 0;                                                         */
+/*  if (cc && parse (cc, 'r', dist ? "Distribute-cc: " : "cc: "))       */
+/*          leave (0);                                                  */
+/*  cclist = parptr;                                                    */
+/*  parptr = 0;                                                         */
+/*                                                                      */
+/*  if (verbose)                                                        */
+/*  {                                                                   */
+/*      if (tolist)                                                     */
+/*          printf (tolist);                                            */
+/*      if (cclist)                                                     */
+/*          printf (cclist);                                            */
+/*      flush ();                                                       */
+/*  }                                                                   */
+    if (fcc)
+    {
+       if (*fcc == ' ')
+           fcc++;
+       for (cp = fcc; *cp && *cp != '\n'; cp++);
+       *cp = 0;
+       if (debug)
+           printf ("fcc: \"%s\"\n", fcc);
+       flush ();
+       if ((fccout.b_fildes = filemsg (fcc)) == -1)
+           leave ("Problem beginning fcc message transfer");
+    }
+
+/*  if (parse (field, 'r', dist ? "Distributed-By: "                    */
+/*               : (from ? "Sender: " : "From: ")))                     */
+/*      leave (0);                                                      */
+
+    sender = add ((dist) ? "Distributed-By: "
+           : (from) ? "Sender: "
+           : "From: ", sender);
+fieldptr = copy ((logn = getlogn (getruid ())), field);
+fieldptr = copy (" at ", fieldptr);
+fieldptr = copy ( locname, fieldptr);
+copy ( "\n", fieldptr);
+    sender = add (field, sender);
+/*    parptr = 0;                                                       */
+    seek (in.b_fildes, 0, 0);
+/* ***   INVOKE SUBMIT, AT LAST   ***  */
+    ap = arguments;
+    *ap++ = '-';                 /* indicate a switch sequence               
+                                 */
+    /* *ap++ = 'd';    /*DBG have submit output messages */
+    *ap++ = 'm';                 /* mail, not screen-notice, yet             
+                                 */
+/*  cputc ('s', &pout); */
+/* ******* During initial testing, mail always sent immediately, ****** */
+/*         so that users can verify delivery...                         */
+/*         Can't trust new software these days...                ****** */
+
+/*  if (loc)                    */
+       *ap++ = 'l';              /* send local mail now        */
+    if (net)
+       *ap++ = 'n';              /* send net mail now          */
+    if (net || loc)
+       *ap++ = 'w';              /* user will watch deliveries */
+
+/* *******  * * * * * * * * * * * * * * * * * * * * * * * * * *  ****** */
+
+    *ap++ = 'r';                 /* return messages go to sender             
+                                 */
+    *ap = '\0';
+
+    if (debug)
+       pout.b_fildes = 1;        /* Send msg to std output for debugging */
+    else
+       if (fcconly)
+           pout.b_fildes = 0;    /* Flush send output if only an fcc */
+       else
+       {
+           if ((sbchild = sbmitinit (arguments, sbmitfd)) == -1)
+               leave ("Unable to invoke submit");
+           pout.b_fildes = sbmitfd[1];
+       }
+
+    puts (adrlist, &pout);
+    puts ("!\n", &pout);         /* end the address list                 */
+    puts2 (sender, &pout);
+    puts2 (dist ? "Distribution-Date: " : "Date: ", &pout);
+    puts2 (cnvtdate (TIMREG), &pout);
+    puts2 ("\n", &pout);
+    if (msgid)
+    {
+       puts2 (dist ? "Distribution-ID: " : "Message-ID: ", &pout);
+       puts2 ("<", &pout);
+       puts2 (cnvtdate (TIMJUL), &pout);
+       puts2 (".", &pout);
+       puts2 (locv (0, getpid ()), &pout);
+       puts2 (" at ", &pout);
+       puts2 (locname, &pout);
+       puts2 ("\n", &pout);
+    }
+    seek (in.b_fildes, 0, 0);
+    in.b_nleft = in.b_nextp = 0;
+    state = FLD;
+    for (;;)
+       switch (state = m_getfld (state, name, field, sizeof field, &in))
+       {
+           case FLD: 
+           case FLDEOF: 
+           case FLDPLUS: 
+               specfld = 0;
+               if (format && uleq (name, dist ? "distribute-to" : "to"))
+               {
+                   specfld++;
+                   if (tolist)
+                       puts2 (tolist, &pout);
+               }
+               else
+                   if (format && uleq (name, dist ? "distribute-cc" : "cc"))
+                   {
+                       specfld++;
+                       if (cclist)
+                           puts2 (cclist, &pout);
+                   }
+                   else
+                       if (uleq (name, dist ? "distribute-bcc" : "bcc") ||
+                               uleq (name, dist ? "distributed-by" : "sender") ||
+                               uleq (name, dist ? "distribution-date" : "date") ||
+                               uleq (name, dist ? "distribution-id" : "message-id") ||
+                               uleq (name, dist ? "distribution-fcc" : "fcc"))
+                           specfld++;
+                                 /* Ignore these if present */
+                       else
+                       {
+                           puts2 (name, &pout);
+                           puts2 (":", &pout);
+                           puts2 (field, &pout);
+                       }
+               while (state == FLDPLUS)
+               {                 /* read rest of field */
+                   state = m_getfld (state, name, field, sizeof field, &in);
+                   if (specfld)
+                       continue;
+/*                  puts2(name, &pout); puts2(":", &pout);  */
+                   puts2 (field, &pout);
+               }
+               if (state == FLDEOF)
+                   goto endit;
+               continue;
+           case BODY: 
+           case BODYEOF: 
+               if (field[0])
+               {
+                   puts2 ("\n", &pout);
+                   puts2 (field, &pout);
+               }
+
+               while (state == BODY)
+               {
+                   state = m_getfld (state, name, field, sizeof field, &in);
+                   puts2 (field, &pout);
+               }
+               if (state == BODYEOF)
+                   goto endit;
+           default: 
+               leave ("Error from getfld=%d", state);
+       }
+
+endit: 
+    errno = 0;
+    if (pout.b_fildes)
+       if (fflush (&pout) <  0 || errno != 0)
+           leave ("Problem writing data to Submit.");
+    if (fccout.b_fildes)
+    {
+       fflush (&fccout);
+       close (fccout.b_fildes);
+    }
+    if (!debug && !fcconly)
+    {
+/*      if ((state = read (2, &field, sizeof field)) != 1 || field[0])  */
+       if (loc || net)
+       {
+           printf ("Delivery being attempted...\n");
+           flush ();
+       }
+       if (sbresp (&sbmitfd) != 0)
+           leave ("Mail submission program ended abnormally");
+    }
+    if (fccout.b_fildes)
+       printf ("Filed: %s:%s\n", fcc, nmsg);
+    if (!debug)
+    {
+       if (!fcconly)
+       {
+           printf ("Message processed.\n");
+/*         printf ("Message %s processed.\n", msg);*/
+           flush ();
+       }
+       cp = copy (msg, field);
+                                 /*  for(cp = field; *cp++; ) ;  */
+       cp[1] = 0;
+       do
+           *cp = cp[-1];
+       while (--cp >= field && *cp != '/');
+       *++cp = ',';              /* New backup convention */
+       unlink (field);
+       if (link (msg, field) == -1 || unlink (msg) == -1)
+           printf ("Can't rename %s to %s\n", msg, field);
+    }
+    m_update ();
+/*    childend ();  */
+    flush ();
+    exit (0);
+}
+
+leave (form, a1, a2, a3)
+char   *form,
+       *a1,
+       *a2,
+       *a3;
+{
+    if (form != 0)
+    {
+       printf (form, a1, a2, a3);
+        putchar ('\n');
+    }
+if (sbchild != 0)
+    kill (sbchild, 9);
+    printf ("[ Message NOT Delivered! ]\n");
+    if (fccout.b_fildes)
+       unlink (fccfile);
+    m_update ();
+    flush ();
+    exit (1);
+}
+
+parse (ptr, type, fldname)
+char   *fldname;
+{
+    register int    i;
+    register int    l;
+    char    line[128];
+
+    errno = 0;
+    putc (type, &pout);
+    puts ("\n", &pout);
+    puts (ptr, &pout);
+    if (fflush (&pout) < 0 || errno != 0)
+       leave ("Problem sending data to Submit.");
+    write (pout.b_fildes, "", 1);
+    l = 0;
+
+    while ((i = getl (&pin, line, (sizeof line) - 1)) > 0)
+    {
+       line[i] = 0;
+       if (line[0] == 0)
+       {
+           if (type == 'r')
+           {
+               if (l > 0)
+                   parptr = add ("\n", parptr);
+           }
+           return (0);
+       }
+       else
+           if (line[0] == '?')
+           {
+               printf ("Submit returned: %s", line);
+               return (1);
+           }
+       if (type == 'r')
+       {
+           line[--i] = 0;
+           if (l + i > 70)
+           {
+               parptr = add ("\n", parptr);
+               l = 0;
+           }
+           if (l == 0)
+           {
+               parptr = add (fldname, parptr);
+               l =+ length (fldname);
+           }
+           else
+           {
+               parptr = add (", ", parptr);
+               l =+ 2;
+           }
+           parptr = add (line + 1, parptr);
+           l =+ i;
+       }
+       else
+           parptr = add (line, parptr);
+    }
+    printf ("Error from Submit.\n");
+    return (1);
+}
+
+cnvtdate (flag)
+int     flag;                    /* date format option value     */
+{
+    static char datbuf[128];
+    extern int  daylight;
+    int     tvec[2];
+    long int    seconds;
+    register int
+                   *i;
+    register char
+                   *p,
+                   *t;
+
+    time (tvec);
+    i = localtime (tvec);
+    t = ctime (tvec);
+    p = datbuf;
+
+    switch (flag)
+    {
+       case TIMJUL:              /* Julian-oriented for msg-ids  */
+           for (itoa (i[5], p); *p; p++);
+           *p++ = '.';
+           for (itoa (i[7], p); *p; p++);
+           *p++ = '.';
+           seconds = i[2];
+           seconds = i[0] + (i[1] * 60) + (seconds * 3600);
+           litoa (seconds, p);   /* seconds since midnight     */
+           break;
+       case TIMREG:              /* RFC 733 standard time string */
+       default:                  /* "Sat, 21 Jan 76 14:30-PDT"   */
+           *p++ = t[0];
+           *p++ = t[1];
+           *p++ = t[2];
+           *p++ = ',';
+           *p++ = ' ';
+           *p++ = t[8];          /* day of month                 */
+           *p++ = t[9];
+           *p++ = ' ';
+           *p++ = t[4];          /* month abbreviation eg: "JAN" */
+           *p++ = t[5];
+           *p++ = t[6];
+           *p++ = ' ';
+           *p++ = t[22];         /* year eg: "76"              */
+           *p++ = t[23];
+           *p++ = ' ';
+           *p++ = t[11];         /* hours & minutes eg: "14:30" */
+           *p++ = t[12];
+           *p++ = ':';
+           *p++ = t[14];
+           *p++ = t[15];
+           *p++ = '-';
+           *p++ = 'P';           /* time zone eg: "PDT"          */
+           *p++ = (i[8]) ? 'D' : 'S';
+           *p++ = 'T';
+           *p++ = '\000';
+    }
+    free (i);
+    free (t);
+    return (datbuf);
+}
+
+getl (iob, buf, size)
+{
+    register char  *cp;
+    register int    cnt,
+                    c;
+
+    for (cp = buf, cnt = size; (c = getc (iob)) >= 0;)
+    {
+       *cp++ = c;
+       --cnt;
+       switch (c)
+       {
+           case '\0': 
+           case '\n': 
+               break;
+           default: 
+               continue;
+       }
+       break;
+    }
+    return (size - cnt);
+}
+
+compress ()
+{
+    register char  *f1,
+                   *f2,
+                   *f3;
+
+#ifdef DEBUG
+    printf ("compress:\n%s-----\n", parptr);
+#endif
+    for (f1 = parptr; *f1;)
+    {
+       for (f2 = f1; *f2++ != '\n';);
+       while (*f2)
+       {
+           if (eqqq (f1, f2))
+           {
+               for (f3 = f2; *f3++ != '\n';);
+               copy (f3, f2);
+           }
+           else
+               while (*f2++ != '\n');
+       }
+       while (*f1++ != '\n');
+    }
+}
+
+eqqq (s1, s2)
+{
+    register char  *c1,
+                   *c2;
+
+    c1 = s1;
+    c2 = s2;
+    while (*c1 != '\n' && *c2 != '\n')
+       if (*c1++ != *c2++)
+           return (0);
+    return (*c1 == *c2);
+}
+filemsg (folder)
+char   *folder;
+{
+    register int    i;
+    register char  *fp;
+    struct inode    stbuf;
+    struct msgs *mp;
+
+    fp = m_maildir (folder);
+    if (stat (fp, &stbuf) < 0)
+    {
+/*     nmsg = concat ("Create folder \"",
+               fp, "\"? ", 0);
+       if (!gans (nmsg, anoyes))
+           return (-1); */
+       if (!makedir (fp))
+       {
+           printf ("Can't create folder.\n");
+           return (-1);
+       }
+    }
+    if (chdir (fp) < 0)
+    {
+       perror (concat ("Can't chdir to ", fp, 0));
+       return (-1);
+    }
+    if (!(mp = m_gmsg ()))
+    {
+       printf ("Can't read folder %s\n", folder);
+       return (-1);
+    }
+    nmsg = m_name (mp -> hghmsg + 1);
+    copy (nmsg, copy ("/", copy (m_maildir (fp), fccfile)));
+    if ((i = creat (fccfile, m_gmprot ())) == -1)
+       printf ("Can't create %s\n", fccfile);
+    return (i);
+}
+
+puts2 (str, iob)
+{
+    puts (str, &fccout);
+     errno = 0;
+    puts (str, iob);
+    if (fflush (iob) < 0 || errno != 0)
+       leave ("Problem writing out data");
+}
+/* subroutines to interface to submit   */
+
+#define CLOSEFD -1               /* if equals fdarray[i], close (i);     */
+#define PUREXEC 0                /* simply exec over current process     */
+#define FRKEXEC 1                /* run it in lower process              */
+#define SPNEXEC 2                /* separate new process from old        */
+#define FRKWAIT 1                /* wait for FRKEXEC to complete         */
+#define FRKPIGO 2                /* Parent's signals off during FRKWAIT  */
+#define FRKCIGO 4                /* Childs signals off before execl      */
+/*#define EXECR   8               ** Use execr, instead of execv          */
+#define HIGHFD  16
+#define NUMTRY  30
+
+struct pstruct
+{
+    int     prd;
+    int     pwrt;
+};
+int     highfd
+{
+    HIGHFD
+};
+int     regfdary[]
+{
+    0, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+};
+
+sbmitinit (args, ioary)
+char   *args;
+int    *ioary;
+{
+
+    struct pstruct  sbpout;
+    int     sbmitid;
+    char    linebuf[256];
+    char   *p;
+
+    if (pipe (&sbpout) == -1)
+       return (-1);
+    regfdary[0] = sbpout.prd;
+    regfdary[1] = fout.b_fildes;
+
+    if ((sbmitid = newpgml (FRKEXEC, 0, regfdary,
+                   sbmitloc, sbmitnam, args, 0)) == -1)
+    {
+flush ();
+       close (sbpout.prd);
+       close (sbpout.pwrt);
+       return (-1);
+    }
+
+dbglog ("Ready to close");
+    close (sbpout.prd);
+    ioary[1] = sbpout.pwrt;
+    return (sbmitid);
+}
+
+#ifdef COMMNET
+sbmitadr (name, ioary)
+char   *name;
+int    *ioary;
+{
+    int     tmp;
+    char    linebuf[256];
+    char   *from,
+           *to;
+
+    for (from = name, to = linebuf; *to = *from++; to++);
+    for (from = "\n"; *to++ = *from++;);
+    tmp = to - &linebuf;
+
+    if (write (ioary[1], linebuf, tmp) == -1)
+       return (-1);
+
+    return (sbresp (ioary));
+}
+#endif
+
+sbresp (ioary)
+int    *ioary;
+{
+    return (childend ());
+}
+
+newpgml (proctyp, pgmflags, fdarray, pgm, pgmparm)
+int     proctyp,
+        pgmflags,
+        fdarray[];
+char   *pgm,
+       *pgmparm;
+{
+       int retval;
+       char *parmptr;
+                                 /* printf ("newpgml: calling newpgmv\n"); */
+    parmptr = &pgmparm;
+    retval = newpgmv (proctyp, pgmflags, fdarray, pgm, parmptr);
+    return (retval);
+}
+
+newpgmv (proctyp, pgmflags, fdarray, pgm, pgmparm)
+int     proctyp,
+        pgmflags,
+        fdarray[];
+char   *pgm,
+       *pgmparm[];
+{
+    register int    tmp;
+    int     tmp2;
+    int     childid;
+    int     tried;
+    int     osig[3];
+
+    if (proctyp != PUREXEC)
+    {
+                                 /* printf ("This is a forking call.\n"); */
+       for (tried = NUMTRY; (childid = fork ()) == -1 && tried--; sleep (1));
+       if (childid == -1)
+           return (-1);
+                                 /* printf ("Successful fork\n"); */
+       if (childid != 0)
+       {                         /* parent process               */
+           if (pgmflags & FRKPIGO)
+           {                     /* disable parent signals       */
+                                 /* printf ("Parent to be
+                                    non-interruptible\n"); */
+               osig[0] = signal (1, 1);
+               osig[1] = signal (2, 1);
+               osig[2] = signal (3, 1);
+           }
+           if ((proctyp == FRKEXEC) && (pgmflags & FRKWAIT))
+           {
+                                 /* printf ("Parent is to wait\n");      */
+               while ((tmp = wait (&tmp2)) != childid && tmp != -1);
+                                 /* printf ("Parent done waiting\n");    */
+               if (pgmflags & FRKPIGO)
+               {
+                   signal (1, osig[0]);
+                   signal (2, osig[1]);
+                   signal (3, osig[2]);
+               }
+               return (tmp2);
+           }
+           return (childid);
+       }
+       if (proctyp == SPNEXEC)
+       {                         /* want it to be a spawn        */
+                                 /* printf ("This is a spawn\n");    */
+           for (tried = NUMTRY; (tmp = fork ()) < 0 && tried--;
+                   sleep (1));
+           if (tmp != 0)         /* split the grandparent from the   */
+               exit (tmp < 0 ? -2 : 0);
+                                 /* grandchild: kill middle proc     */
+       }
+    }
+    if (fdarray)
+    {                            /* re-align fd array list           */
+       fout.b_fildes = fdarray[1];
+       for (tmp = 0; tmp < highfd; tmp++)
+       {                         /* first do the re-positions        */
+           if (fdarray[tmp] != CLOSEFD && fdarray[tmp] != tmp)
+           {
+                                  dbglog ("Closing %2d\n", tmp);     
+flush ();
+               close (tmp);
+               while ((tmp2 = dup (fdarray[tmp])) < tmp && tmp2 != -1);
+                  dbglog ("Last dup'd %d into %d\n", fdarray[tmp], tmp2);     
+flush ();
+                                 /* did we get right fd?     */
+           }
+       }
+       for (tmp = 0; tmp < highfd; tmp++)
+           if (fdarray[tmp] == CLOSEFD)
+           {
+                                  dbglog ("Closing %2d\n", tmp);     
+flush ();
+               close (tmp);      /* get rid of unwanted ones */
+           }
+    }
+fout.b_fildes = 1;
+
+    if (pgmflags & FRKCIGO)
+    {
+                                 /* printf ("Child's interrupts to be
+                                    disabled\n");      */
+       signal (1, 1);
+       signal (2, 1);
+       signal (3, 1);
+    }
+
+ /* printf ("Execing %s\n", pgm);    */
+/*  if (pgmflags & EXECR)       */
+/*      execr (pgm, pgmparm);   */
+/*  else                        */
+    execv (pgm, pgmparm);
+                                 /* printf ("Exec not successful\n"); */
+    if (proctyp == PUREXEC)
+       return (-1);
+    fout.b_fildes = 1;
+    printf ("Unable to exec \"%s\"\n", pgm);
+    flush ();
+    for (tmp = 0; tmp < 20 && pgmparm[tmp][0] != 0 ; tmp++)
+    {
+       printf ("Parm %d = \"%s\"\n", tmp, pgmparm[tmp]); flush ();
+    }
+    exit (-3);
+}
+
+childend ()
+{
+    int     tmp,
+            tmp2;
+
+    /* close (sbmitfd[0]); */
+    close (sbmitfd[1]);
+    while ((tmp = wait (&tmp2)) != sbchild && tmp != -1);
+    return (tmp2 >> 8);
+}
+dbglog (str)
+{
+return;
+printf(str);
+}
diff --git a/docs/historical/SRI-NOSC/send.run b/docs/historical/SRI-NOSC/send.run
new file mode 100755 (executable)
index 0000000..07ee0d8
--- /dev/null
@@ -0,0 +1,7 @@
+if -r send rm send
+load -n send subs.a strings.a \
+       libg.a libh.a \
+       mailib.a \
+       mailib.a \
+       | tee errlst
+if -r a.out mv a.out send
diff --git a/docs/historical/SRI-NOSC/sgtty.h b/docs/historical/SRI-NOSC/sgtty.h
new file mode 100644 (file)
index 0000000..c8c8aaf
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ *     struct for stty/gtty system call
+ *
+ *
+ *             sg_ispd = input speed
+ *             sg_ospd = output speed
+ *
+ *              sg_erase = character erase
+ *              sg_kill = line kill
+ *
+.*              sg_flag = flags
+ */
+
+struct sgtty   {
+       char    sg_ispd, sg_ospd;
+       char    sg_erase, sg_kill;
+       int     sg_flag;
+};
+
+#define        NODELAY 01
+#define        XTABS   02
+#define        LCASE   04
+#define        ECHO    010
+#define        CRMOD   020
+#define        RAW     040
+#define        ALTESC  0400
+#define        NTDELAY 010000
+#define        PPL     020000
+#define        TECO    040000
+#define        NOSLASH 0100000
+
+#define        CQUIT   002             /* control - b */
+#define        CINTR   003             /* control - c */
+#define        CEOT    004             /* control - d */
+#define        CKILL   025             /* control - u */
+#define        CERASE  0177            /* rubout */
+#define        CRETYPE 022             /* control - r */
+#define        CALTNEW 033             /* new style alt mode */
diff --git a/docs/historical/SRI-NOSC/show.c b/docs/historical/SRI-NOSC/show.c
new file mode 100644 (file)
index 0000000..b6ed3f8
--- /dev/null
@@ -0,0 +1,147 @@
+#include "mh.h"
+#include "signals.h"
+
+char    draft[],        /* Std strings  */
+       showproc[],
+       prproc[];
+
+int vecp, *vec[MAXARGS], fout;
+struct msgs *mp;
+struct swit switches[] {
+       "all",         -3,      /* 0 */
+       "draft",        2,      /* 1 */
+       "pr",           2,      /* 2 */
+       "nopr",         2,      /* 3 */
+       "help",         4,      /* 4 */
+       0,              0
+};
+
+main(argc, argv)
+char *argv[];
+{
+       char *inp, *folder, *maildir, *msgs[100], *proc;
+       register int msgnum;
+       register char *cp, *ap;
+       int msgp, all, drft, pr, infrk, status, frk;
+       char *arguments[50], **argp;
+
+       fout = dup(1);
+#ifdef NEWS
+       m_news();
+#endif
+       pr = all = msgp = folder = 0;
+       vecp = 1;
+       ap = cp = argv[0];
+       while(*cp)
+               if(*cp++ == '/')
+                       ap = cp;
+       inp = ap;
+       if((cp = m_find(ap)) != -1) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                            /* unknown */
+                       case -1:vec[vecp++] = --cp;  continue;
+                                                            /* -all   */
+                       case 0: printf("\"-all\" changed to \"all\"\n");
+                               goto leave;
+                       case 1: drft = 1;  continue;         /* -draft */
+                       case 2: pr = 1;  continue;           /* -pr    */
+                       case 3: pr = 0;  vecp = 1;  continue;/* -nopr  */
+                       case 4:                              /* -help  */
+  help(concat( inp, " [+folder] [msgs] [switches] [switches for l or pr (see /doc) ]", 0),
+                                    switches);
+                               goto leave;
+                       }
+               if(*cp == '+') {
+                       if(folder) {
+                               printf("Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               folder = cp + 1;
+               } else
+                       msgs[msgp++] = cp;
+       }
+       if (!pr)  {
+               vec[vecp++] = "-t"; /* no header */
+       }
+       if(drft)
+               maildir = m_maildir("");
+       else {
+               if(!msgp)
+                       msgs[msgp++] = "cur";
+               if(!folder)
+                       folder = m_getfolder();
+               maildir = m_maildir(folder);
+       }
+       if(chdir(maildir) < 0) {
+               printf("Can't chdir to: "); flush();
+               perror(maildir);
+               goto leave;
+       }
+       if(!pr) {
+               vec[0] = "mh-type";
+               proc = showproc;
+       } else {
+               vec[0] = "mh-pr";
+               proc = prproc;
+       }
+       if(drft) {
+               vec[vecp++] = draft;
+               vec[vecp] = 0;
+               m_update();
+               flush();
+               execv( proc, vec);
+               perror("Can't exec type");
+               goto leave;
+       }
+       if(!(mp = m_gmsg(folder))) {
+               printf("Can't read folder!?\n");
+               goto leave;
+       }
+       if(mp->hghmsg == 0) {
+               printf("No messages in \"%s\".\n", folder);
+               goto leave;
+       }
+       if(msgp)
+               for(msgnum = 0; msgnum < msgp; msgnum++)
+                       if(!m_convert(msgs[msgnum], UNDELETED, UNDELETED))
+                               goto leave;
+       if(mp->numsel == 0) {
+               printf("No undeleted messages specified.\n");     
+               goto leave;
+       }
+       vec[vecp+1]=0;
+       for(msgnum= mp->lowsel; msgnum<= mp->hghsel; msgnum++)
+               if(mp->msgstats[msgnum]&SELECTED) {
+                       vec[vecp] = getcpy(m_name(msgnum));
+                       printf("\nMessage %s\n", m_name(msgnum));
+                       flush();
+                       if((infrk = fork())==0) { /* inferior */
+                               execv( proc, vec);
+                               exit(1); /* execute didnt work */
+                       } else if(infrk== -1) {
+                               printf("No forks\n");
+                               break;
+                       } else
+                          while((frk=waita(&status)) != -1 && frk != infrk);
+                       if(status) {
+                               printf("[command aborted]\n");
+                               break;
+                       }
+               }
+       m_replace("folder", folder);
+       if(mp->hghsel != mp->curmsg)
+               m_setcur(mp->hghsel);
+ leave:
+       m_update();
+       flush();
+}
diff --git a/docs/historical/SRI-NOSC/show.run b/docs/historical/SRI-NOSC/show.run
new file mode 100644 (file)
index 0000000..00ea5d6
--- /dev/null
@@ -0,0 +1,5 @@
+if -r show rm show
+load -n show subs.a strings.a wait -O libg.a libh.a
+if -r a.out mv a.out show
+:                                      fini
+
diff --git a/docs/historical/SRI-NOSC/signals.h b/docs/historical/SRI-NOSC/signals.h
new file mode 100644 (file)
index 0000000..69e424f
--- /dev/null
@@ -0,0 +1,20 @@
+#define        NSIG    20      /* # of Bell signals */
+#define        NHSIG   1       /* # of Harvard signals */
+#define                SIGHUP  1       /* hangup */
+#define                SIGINT  2       /* interrupt (^C) */
+#define                SIGQIT  3       /* quit (^B) */
+#define                SIGINS  4       /* illegal instruction */
+#define                SIGTRC  5       /* trace or breakpoint */
+#define                SIGIOT  6       /* iot */
+#define                SIGEMT  7       /* emt */
+#define                SIGFPT  8       /* floating exception */
+#define                SIGKIL  9       /* kill */
+#define                SIGBUS  10      /* bus error */
+#define                SIGSEG  11      /* segmentation violation */
+#define                SIGSYS  12      /* sys */
+#define                SIGPIPE 13      /* end of pipe */
+#define                SIGALA 14       /* alarm clock */
+
+/* harvard signals */
+
+#define                SIGBRK (-1)     /* break (break) */
diff --git a/docs/historical/SRI-NOSC/stat.h b/docs/historical/SRI-NOSC/stat.h
new file mode 100644 (file)
index 0000000..0fa8dc5
--- /dev/null
@@ -0,0 +1,36 @@
+#
+/*
+ * Inode structure as returned by
+ * system call stat.
+ */
+struct inode
+{
+       int     i_dev;
+       int     i_number;
+       int     i_mode;
+       char    i_nlink;
+       char    i_uid;
+       char    i_gid;
+       char    i_size0;
+       char    *i_size1;
+       int     i_addr[8];
+       long    i_atime;
+       long    i_mtime;
+};
+/* advisable to use this define to generate owner as 16-bit num */
+#define IOWNER(i_n_buf) (((i_n_buf).i_uid<<8)|(i_n_buf).i_gid&0377)
+/* modes */
+#define        IALLOC  0100000
+#define        IFMT    060000
+#define                IFDIR   040000
+#define                IFCHR   020000
+#define                IFBLK   060000
+#define        ILARG   010000
+#define        ISUID   04000
+#define        ISGID   02000
+#define ISVTX  01000
+#define        IREAD   0400
+#define        IWRITE  0200
+#define        IEXEC   0100
+
+struct { char d_minor, d_major; };
diff --git a/docs/historical/SRI-NOSC/strings-ec.c b/docs/historical/SRI-NOSC/strings-ec.c
new file mode 100644 (file)
index 0000000..89bb65d
--- /dev/null
@@ -0,0 +1,42 @@
+char *anoyes[] {
+       "no",   0,
+       "yes",  0,
+       0,
+};
+char   components[]    "components";
+char   current[]       "cur";
+char   defalt[]        "inbox";
+char    distcomps[]     "distcomps";
+char   draft[]         "draft";
+char   foldprot[]      "0751";
+/*char    installproc[]   "/rnd/borden/bin/install-defs";*/
+/*char    installproc[]   "/rnd/phyl/bin/install-defs";*/
+char    installproc[]   "/m/mh/install-defs";
+char   listname[]      "select";
+/*char lsproc[]        "/bin/nls";*/
+char   lsproc[]        "bin/ls";
+char   mailbox[]       "/.mail";
+char   mh_defs[]       "/.mh_defs";
+char   mhnews[]        "/m/mh/news";
+char   msgprot[]       "0664";
+/*char prproc[]        "/rnd/borden/bin/ppr";*/
+char   prproc[]        "/bin/pr";
+/* char    scanproc[]      "/rnd/borden/bin/mh.2/scan"; */
+/* char    scanproc[]      "/fsd/phyl/mh/scan";         */
+/*char    scanproc[]      "/rnd/phyl/bin/mh/scan";*/
+char    scanproc[]      "/m/mh/nullproc";
+/*char showproc[]      "/rnd/borden/bin/type";*/
+char   showproc[]      "/m/mh/pr";
+char   prmtproc[]      "/m/mh/prompter";
+/* char    sndproc[]       "/rnd/borden/bin/mh.2/send"; */
+/* char sndproc[]          "/fsd/phyl/mh/send";         */
+/*char    sndproc[]      "/rnd/phyl/bin/mh/send";*/
+char    sndproc[]      "/m/mh/send";
+char   sbmitloc[]      "/m/mmdf/submit-ec";
+char   sbmitnam[]      "submit";
+/*char stdcomps[]      "/rnd/borden/etc/components";*/
+char   stdcomps[]      "/m/mh/components";
+/*char    stddcomps[]     "/rnd/borden/etc/distcomps";*/
+char    stddcomps[]     "/m/mh/distcomps";
+char   sysed[]         "/bin/ed";
+char   locname[]       "GC";   /* local host name */
diff --git a/docs/historical/SRI-NOSC/strings.c b/docs/historical/SRI-NOSC/strings.c
new file mode 100644 (file)
index 0000000..a4a6a72
--- /dev/null
@@ -0,0 +1,42 @@
+char *anoyes[] {
+       "no",   0,
+       "yes",  0,
+       0,
+};
+char   components[]    "components";
+char   current[]       "cur";
+char   defalt[]        "inbox";
+char    distcomps[]     "distcomps";
+char   draft[]         "draft";
+char   foldprot[]      "0751";
+/*char    installproc[]   "/rnd/borden/bin/install-defs";*/
+/*char    installproc[]   "/rnd/phyl/bin/install-defs";*/
+char    installproc[]   "/m/mh/install-defs";
+char   listname[]      "select";
+/*char lsproc[]        "/bin/nls";*/
+char   lsproc[]        "bin/ls";
+char   mailbox[]       "/.mail";
+char   mh_defs[]       "/.mh_defs";
+char   mhnews[]        "/m/mh/news";
+char   msgprot[]       "0664";
+/*char prproc[]        "/rnd/borden/bin/ppr";*/
+char   prproc[]        "/bin/pr";
+/* char    scanproc[]      "/rnd/borden/bin/mh.2/scan"; */
+/* char    scanproc[]      "/fsd/phyl/mh/scan";         */
+/*char    scanproc[]      "/rnd/phyl/bin/mh/scan";*/
+char    scanproc[]      "/m/mh/nullproc";
+/*char showproc[]      "/rnd/borden/bin/type";*/
+char   showproc[]      "/m/mh/pr";
+char   prmtproc[]      "/m/mh/prompter";
+/* char    sndproc[]       "/rnd/borden/bin/mh.2/send"; */
+/* char sndproc[]          "/fsd/phyl/mh/send";         */
+/*char    sndproc[]      "/rnd/phyl/bin/mh/send";*/
+char    sndproc[]      "/m/mh/send";
+char   sbmitloc[]      "/m/mmdf/submit";
+char   sbmitnam[]      "submit";
+/*char stdcomps[]      "/rnd/borden/etc/components";*/
+char   stdcomps[]      "/m/mh/components";
+/*char    stddcomps[]     "/rnd/borden/etc/distcomps";*/
+char    stddcomps[]     "/m/mh/distcomps";
+char   sysed[]         "/bin/ed";
+char   locname[]       "SRI-TSC";      /* local host name */
diff --git a/docs/historical/SRI-NOSC/strings.run b/docs/historical/SRI-NOSC/strings.run
new file mode 100644 (file)
index 0000000..7bd013c
--- /dev/null
@@ -0,0 +1,2 @@
+cc -c strings.c
+if -r strings.o mv strings.o strings.a
diff --git a/docs/historical/SRI-NOSC/subs.dir/ambigsw.c b/docs/historical/SRI-NOSC/subs.dir/ambigsw.c
new file mode 100644 (file)
index 0000000..2aa265c
--- /dev/null
@@ -0,0 +1,8 @@
+ambigsw(arg, swp)
+char *arg;
+{
+       printf("%s: ", invo_name());
+       printf("-%s ambiguous.  It matches \n", arg);
+       printsw(arg, swp);
+}
+
diff --git a/docs/historical/SRI-NOSC/subs.dir/atoi.c b/docs/historical/SRI-NOSC/subs.dir/atoi.c
new file mode 100644 (file)
index 0000000..d33254c
--- /dev/null
@@ -0,0 +1,13 @@
+atoi(str)
+{
+       register char *cp;
+       register int i;
+
+       i = 0;
+       cp = str;
+       while(*cp >= '0' && *cp <= '9') {
+               i =* 10;
+               i =+ *cp++ - '0';
+       }
+       return(i);
+}
diff --git a/docs/historical/SRI-NOSC/subs.dir/atooi.c b/docs/historical/SRI-NOSC/subs.dir/atooi.c
new file mode 100644 (file)
index 0000000..11fab04
--- /dev/null
@@ -0,0 +1,16 @@
+atooi(str)
+{
+       register char *cp;
+       register int i, base;
+
+       base = 10;
+       i = 0;
+       cp = str;
+       if(*cp == '0')
+               base = 8;
+       while(*cp >= '0' && *cp <= '9') {
+               i =* base;
+               i =+ *cp++ - '0';
+       }
+       return(i);
+}
diff --git a/docs/historical/SRI-NOSC/subs.dir/cfree.c b/docs/historical/SRI-NOSC/subs.dir/cfree.c
new file mode 100644 (file)
index 0000000..2b7abec
--- /dev/null
@@ -0,0 +1,12 @@
+/* Conditional free -- perform a free call if the address passed
+ * is in free storage;  else NOP
+ */
+
+
+cfree(addr)
+char *addr;
+{
+       extern end;
+
+       if(addr >= &end) free(addr);
+}
diff --git a/docs/historical/SRI-NOSC/subs.dir/concat.c b/docs/historical/SRI-NOSC/subs.dir/concat.c
new file mode 100644 (file)
index 0000000..a86cb2b
--- /dev/null
@@ -0,0 +1,15 @@
+concat(args)
+int args[];
+{
+       register char **a;
+       register char *cp;
+       register int len;
+
+       len = 1;
+       for(a = &args; *a; )
+               len =+ length(*a++);
+       len = cp = alloc(len);
+       for(a = &args; *a; )
+               cp = copy(*a++, cp);
+       return(len);
+}
diff --git a/docs/historical/SRI-NOSC/subs.dir/copyip.c b/docs/historical/SRI-NOSC/subs.dir/copyip.c
new file mode 100644 (file)
index 0000000..47c30b4
--- /dev/null
@@ -0,0 +1,12 @@
+copyip(ipfrom, ipto)
+int *ipfrom, *ipto;
+{
+       register int *ipf, *ipt;
+
+       ipf=ipfrom;  ipt=ipto;
+       while((*ipt = *ipf)  && *ipf++ != -1)
+               ipt++;
+       *ipt = 0;
+       return(ipt);
+}
+
diff --git a/docs/historical/SRI-NOSC/subs.dir/cputc.c b/docs/historical/SRI-NOSC/subs.dir/cputc.c
new file mode 100644 (file)
index 0000000..ba7c907
--- /dev/null
@@ -0,0 +1,15 @@
+#include "/rnd/borden/h/iobuf.h"
+
+cputc(chr, iob)
+{
+       register struct iobuf *ip;
+       extern int errno;
+
+       ip = iob;
+
+       errno = 0;
+       if(ip->b_fildes) {
+                       putc(chr, ip);
+                       if(errno) { perror("Write error"); exit(-1); }
+       }
+}
diff --git a/docs/historical/SRI-NOSC/subs.dir/gans.c b/docs/historical/SRI-NOSC/subs.dir/gans.c
new file mode 100644 (file)
index 0000000..52b0b26
--- /dev/null
@@ -0,0 +1,37 @@
+#include "mh.h"
+
+gans(prompt, ansp)
+struct swit *ansp;
+{
+       char ansbuf[32];
+       register char *cp;
+       register int i;
+       struct swit *ap;
+
+    for(;;) {
+       printf("%s", prompt);
+       flush();
+       cp = ansbuf;
+       while((i = getchar()) != '\n') {
+               if(i == 0)
+                       return(0);
+               if(cp < &ansbuf[31]) {
+                       if(i >= 'A' && i <= 'Z')
+                               i =+ 'a'-'A';
+                       *cp++ = i;
+               }
+       }
+       *cp = 0;
+       if(ansbuf[0] == '?' || cp == ansbuf) {
+               printf("Options are:\n");
+               for(ap = ansp; ap->sw; ap++)
+                       printf("  %s\n", ap->sw);
+               continue;
+       }
+       if((i = smatch(ansbuf, ansp)) < 0) {
+               printf("%s: %s.\n", ansbuf, i == -1? "unknown":"ambiguous");
+               continue;
+       }
+       return(i);
+    }
+}
diff --git a/docs/historical/SRI-NOSC/subs.dir/getchar.c b/docs/historical/SRI-NOSC/subs.dir/getchar.c
new file mode 100644 (file)
index 0000000..a2b8454
--- /dev/null
@@ -0,0 +1,9 @@
+getchar()
+{
+       int c;
+
+       c = 0;
+       if(read(0, &c, 1) != 1)
+               return(0);
+       return(c);
+}
diff --git a/docs/historical/SRI-NOSC/subs.dir/getcpy.c b/docs/historical/SRI-NOSC/subs.dir/getcpy.c
new file mode 100644 (file)
index 0000000..08a4733
--- /dev/null
@@ -0,0 +1,8 @@
+getcpy(str)
+{
+       register char *cp;
+
+       cp = alloc(length(str) + 1);
+       copy(str, cp);
+       return(cp);
+}
diff --git a/docs/historical/SRI-NOSC/subs.dir/help.c b/docs/historical/SRI-NOSC/subs.dir/help.c
new file mode 100644 (file)
index 0000000..d175828
--- /dev/null
@@ -0,0 +1,9 @@
+#include "mh.h"
+
+help(str, swp)
+char *str;
+{
+       printf("syntax: %s\n", str);
+       printf("  switches are:\n");
+       printsw(ALL, swp);
+}
diff --git a/docs/historical/SRI-NOSC/subs.dir/invo_name.c b/docs/historical/SRI-NOSC/subs.dir/invo_name.c
new file mode 100644 (file)
index 0000000..bf6a855
--- /dev/null
@@ -0,0 +1,12 @@
+invo_name()
+{
+       register int *ip;
+
+       ip = 0;
+
+       while(*--ip != -1)
+               ;
+       while(*--ip < 0)
+               ;
+       return(ip[2]);
+}
diff --git a/docs/historical/SRI-NOSC/subs.dir/m_convert.c b/docs/historical/SRI-NOSC/subs.dir/m_convert.c
new file mode 100644 (file)
index 0000000..84becba
--- /dev/null
@@ -0,0 +1,156 @@
+#include "/m/mh/mh.h"
+int  convdir;
+struct msgs *mp;
+char *delimp;
+
+m_convert(name, mask, match)
+{
+       register char *cp;
+       register int first, last;
+       int found, group, range, err;
+       char *bp;
+
+       found = group = 0;
+       mask =| EXISTS; /* dont fool with nonexistent msgs */
+       match =| EXISTS; /* ditto */
+       cp = name;
+       if(equal(cp, "all"))
+               cp = "first-last";
+       if(equal(cp, "del")) {
+               cp = "first-last";
+               mask =| DELETED;
+               match =| DELETED;
+       }
+       if(equal(cp, "undel")) {
+               cp = "first-last";
+               mask =| UNDELETED;
+               match =| UNDELETED;
+       }
+       if((err = first = m_conv(cp)) <= 0)
+               goto badbad;
+       if(*(cp = delimp) && *cp != '-' && *cp != ':')  {
+       baddel: printf("Illegal argument delimiter: \"%c\"\n", *delimp);
+               return(0);
+       }
+       if(*cp == '-') {
+               group++;  cp++;
+               if((err = last = m_conv(cp)) <= 0) {
+         badbad:       if(err == -1)
+                               printf("No %s message\n", cp);
+                       else
+         badlist:              printf("Bad message list \"%s\".\n", name);
+                       return(0);
+               }
+               if(last < first) goto badlist;
+               if(*delimp) goto baddel;
+               if(first > mp->hghmsg || last < mp->lowmsg) {
+       rangerr:        printf("No messages in range \"%s\".\n", name);
+                       return(0);
+               }
+               if(last > mp->hghmsg)
+                       last = mp->hghmsg;
+               if(first < mp->lowmsg)
+                       first = mp->lowmsg;
+       } else if(*cp == ':') {
+               cp++;
+               if(*cp == '-') {
+                       convdir = -1;
+                       cp++;
+               } else if(*cp == '+') {
+                       convdir = 1;
+                       cp++;
+               }
+               if((range = atoi(bp = cp)) == 0)
+                       goto badlist;
+               while(*bp >= '0' && *bp <= '9') bp++;
+               if(*bp)
+                       goto baddel;
+               if((convdir > 0 && first > mp->hghmsg) ||
+                  (convdir < 0 && first < mp->lowmsg))
+                       goto rangerr;
+               if(first < mp->lowmsg)
+                       first = mp->lowmsg;
+               if(first > mp->hghmsg)
+                       first = mp->hghmsg;
+               for(last = first; last >= mp->lowmsg && last <= mp->hghmsg;
+                                               last =+ convdir)
+                       if((mp->msgstats[last]&mask)==match)
+                               if(--range <= 0)
+                                       break;
+               if(last < mp->lowmsg)
+                       last = mp->lowmsg;
+               if(last > mp->hghmsg)
+                       last = mp->hghmsg;
+               if(last < first) {
+                       range = last; last = first; first = range;
+               }
+       } else {
+               if(first > mp->hghmsg || first < mp->lowmsg ||
+                  !(mp->msgstats[first]&EXISTS)) {
+                       printf("Message %d doesn't exist.\n", first);
+                       return(0);
+               }
+               last = first;
+       }
+       while(first <= last) {
+               if((mp->msgstats[first]&mask)==match) {
+                       if(!(mp->msgstats[first]&SELECTED)) {
+                               mp->numsel++;
+                               mp->msgstats[first] =| SELECTED;
+                               if(first < mp->lowsel)
+                                       mp->lowsel = first;
+                               if(first > mp->hghsel)
+                                       mp->hghsel = first;
+                       }
+                       found++;
+               }
+               first++;
+       }
+       /* if(!found)
+               goto rangerr; */
+       return(1);
+}
+
+m_conv(str)
+{
+       register char *cp, *bp;
+       register int i;
+       char buf[16];
+
+       convdir = 1;
+       cp = bp = str;
+       if(*cp >= '0' && *cp <= '9')  {
+               while(*bp >= '0' && *bp <= '9') bp++;
+               delimp = bp;
+               return(atoi(cp));
+       }
+       bp = buf;
+       while((*cp >= 'a' && *cp <= 'z') || *cp == '.')
+               *bp++ = *cp++;
+       *bp++ = 0;
+       delimp = cp;
+       if(equal(buf, "first"))
+               return(mp->lowmsg);
+       else if(equal(buf, "last")) {
+               convdir = -1;
+               return(mp->hghmsg);
+       } else if(equal(buf, "cur") || equal(buf, "."))
+               return(mp->curmsg);
+       else if(equal(buf, "prev")) {
+               convdir = -1;
+               for(i = (mp->curmsg<=mp->hghmsg)? mp->curmsg-1: mp->hghmsg;
+                   i >= mp->lowmsg; i--) {
+                       if(mp->msgstats[i]&EXISTS)
+                               return(i);
+               }
+               return(-1);                     /* non-existent message */
+       } else if(equal(buf, "next"))  {
+               for(i = (mp->curmsg>=mp->lowmsg)? mp->curmsg+1: mp->lowmsg;
+                   i <= mp->hghmsg; i++) {
+                       if(mp->msgstats[i]&EXISTS)
+                               return(i);
+               }
+               return(-1);
+       } else
+               return(0);                     /* bad message list */
+}
diff --git a/docs/historical/SRI-NOSC/subs.dir/m_convert.c.te b/docs/historical/SRI-NOSC/subs.dir/m_convert.c.te
new file mode 100644 (file)
index 0000000..7ddd015
--- /dev/null
@@ -0,0 +1,142 @@
+#include "mh.h"
+
+int  convdir;
+struct msgs *mp;
+char *delimp;
+
+m_convert(name)
+{
+       register char *cp;
+       register int first, last;
+       int found, group, range;
+       char *bp;
+
+       found = group = 0;
+       if(equal((cp = name), "all"))
+               cp = "first-last";
+       if((first = m_conv(cp)) == -1)
+               goto badbad;
+       printf("first=%s\n",first);     flush();          /*##*/
+       if(*(cp = delimp) && *cp != '-' && *cp != ':')  {
+       baddel: printf("Illegal argument delimiter: \"%c\"\n", *delimp);
+               return(0);
+       }
+       if(*cp == '-') {
+               group++;  cp++;
+               if((last = m_conv(cp)) == -1) {
+         badbad:       if(*cp > '9')
+                               printf("No %s message\n", cp);
+                       else
+         badlist:              printf("Bad message list \"%s\".\n", name);
+                       return(0);
+               }
+               if(last < first) goto badlist;
+               if(*delimp) goto baddel;
+               if(first > mp->hghmsg || last < mp->lowmsg) {
+       rangerr:        printf("No messages in range \"%s\".\n", name);
+                       return(0);
+               }
+               if(last > mp->hghmsg)
+                       last = mp->hghmsg;
+               if(first < mp->lowmsg)
+                       first = mp->lowmsg;
+       } else if(*cp == ':') {
+               cp++;
+               if(*cp == '-') {
+                       convdir = -1;
+                       cp++;
+               } else if(*cp == '+') {
+                       convdir = 1;
+                       cp++;
+               }
+               if((range = atoi(bp = cp)) == 0)
+                       goto badlist;
+               while(*bp >= '0' && *bp <= '9') bp++;
+               if(*bp)
+                       goto baddel;
+               if((convdir > 0 && first > mp->hghmsg) ||
+                  (convdir < 0 && first < mp->lowmsg))
+                       goto rangerr;
+               if(first < mp->lowmsg)
+                       first = mp->lowmsg;
+               if(first > mp->hghmsg)
+                       first = mp->hghmsg;
+               for(last = first; last >= mp->lowmsg && last <= mp->hghmsg;
+                                               last =+ convdir)
+                       if(mp->msgstats[last]&EXISTS)
+                               if(--range <= 0)
+                                       break;
+               if(last < mp->lowmsg)
+                       last = mp->lowmsg;
+               if(last > mp->hghmsg)
+                       last = mp->hghmsg;
+               if(last < first) {
+                       range = last; last = first; first = range;
+               }
+       } else {
+               if(first > mp->hghmsg || first < mp->lowmsg ||
+                  !(mp->msgstats[first]&EXISTS)) {
+                       printf("Message %d doesn't exist.\n", first);
+                       return(0);
+               }
+               last = first;
+       }
+       while(first <= last) {
+               if(mp->msgstats[first]&EXISTS) {
+                       if(!(mp->msgstats[first]&SELECTED)) {
+                               mp->numsel++;
+                               mp->msgstats[first] =| SELECTED;
+                               if(first < mp->lowsel)
+                                       mp->lowsel = first;
+                               if(first > mp->hghsel)
+                                       mp->hghsel = first;
+                       }
+                       found++;
+               }
+               first++;
+       }
+       if(!found)
+               goto rangerr;
+       return(1);
+}
+
+m_conv(str)
+{
+       register char *cp, *bp;
+       register int i;
+       char buf[16];
+
+       convdir = 1;
+       cp = bp = str;
+       if(*cp >= '0' && *cp <= '9')  {
+               while(*bp >= '0' && *bp <= '9') bp++;
+               delimp = bp;
+               return(atoi(cp));
+       }
+       bp = buf;
+       while((*cp >= 'a' && *cp <= 'z') || *cp == '.')
+               *bp++ = *cp++;
+       *bp++ = 0;
+       delimp = cp;
+       if(equal(buf, "first"))
+               return(mp->lowmsg);
+       else if(equal(buf, "last")) {
+               convdir = -1;
+               return(mp->hghmsg);
+       } else if(equal(buf, "cur") || equal(buf, "."))
+               return(mp->curmsg);
+       else if(equal(buf, "prev")) {
+               convdir = -1;
+               for(i = (mp->curmsg<=mp->hghmsg)? mp->curmsg-1: mp->hghmsg;
+                   i >= mp->lowmsg; i--) {
+                       if(mp->msgstats[i]&EXISTS)
+                               return(i);
+               }
+       } else if(equal(buf, "next"))
+               for(i = (mp->curmsg>=mp->lowmsg)? mp->curmsg+1: mp->lowmsg;
+                   i <= mp->hghmsg; i++) {
+                       if(mp->msgstats[i]&EXISTS)
+                               return(i);
+               }
+       return(-1);
+}
diff --git a/docs/historical/SRI-NOSC/subs.dir/m_convert.c.tm b/docs/historical/SRI-NOSC/subs.dir/m_convert.c.tm
new file mode 100644 (file)
index 0000000..60559b5
--- /dev/null
@@ -0,0 +1,139 @@
+#include "mh.h"
+
+int  convdir;
+struct msgs *mp;
+char *delimp;
+
+m_convert(name)
+{
+       register char *cp;
+       register int first, last;
+       int found, group, range;
+       char *bp;
+
+       found = group = 0;
+       if(equal((cp = name), "all"))
+               cp = "first-last";
+       if((first = m_conv(cp)) == -1)
+               goto badbad;
+       if(*(cp = delimp) && *cp != '-' && *cp != ':')  {
+       baddel: printf("Illegal argument delimiter: \"%c\"\n", *delimp);
+               return(0);
+       }
+       if(*cp == '-') {
+               group++;  cp++;
+               if((last = m_conv(cp)) == -1 || last < first ) {
+         badbad:       if(
+
+                       printf("Bad message list \"%s\".\n", name);
+                       return(0);
+               }
+               if(*delimp) goto baddel;
+               if(first > mp->hghmsg || last < mp->lowmsg) {
+       rangerr:        printf("No messages in range \"%s\".\n", name);
+                       return(0);
+               }
+               if(last > mp->hghmsg)
+                       last = mp->hghmsg;
+               if(first < mp->lowmsg)
+                       first = mp->lowmsg;
+       } else if(*cp == ':') {
+               cp++;
+               if(*cp == '-') {
+                       convdir = -1;
+                       cp++;
+               } else if(*cp == '+') {
+                       convdir = 1;
+                       cp++;
+               }
+               if((range = atoi(bp = cp)) == 0)
+                       goto badbad;
+               while(*bp >= '0' && *bp <= '9') bp++;
+               if(*bp)
+                       goto baddel;
+               if((convdir > 0 && first > mp->hghmsg) ||
+                  (convdir < 0 && first < mp->lowmsg))
+                       goto rangerr;
+               if(first < mp->lowmsg)
+                       first = mp->lowmsg;
+               if(first > mp->hghmsg)
+                       first = mp->hghmsg;
+               for(last = first; last >= mp->lowmsg && last <= mp->hghmsg;
+                                               last =+ convdir)
+                       if(mp->msgstats[last]&EXISTS)
+                               if(--range <= 0)
+                                       break;
+               if(last < mp->lowmsg)
+                       last = mp->lowmsg;
+               if(last > mp->hghmsg)
+                       last = mp->hghmsg;
+               if(last < first) {
+                       range = last; last = first; first = range;
+               }
+       } else {
+               if(first > mp->hghmsg || first < mp->lowmsg ||
+                  !(mp->msgstats[first]&EXISTS)) {
+                       printf("Message %d doesn't exist.\n", first);
+                       return(0);
+               }
+               last = first;
+       }
+       while(first <= last) {
+               if(mp->msgstats[first]&EXISTS) {
+                       if(!(mp->msgstats[first]&SELECTED)) {
+                               mp->numsel++;
+                               mp->msgstats[first] =| SELECTED;
+                               if(first < mp->lowsel)
+                                       mp->lowsel = first;
+                               if(first > mp->hghsel)
+                                       mp->hghsel = first;
+                       }
+                       found++;
+               }
+               first++;
+       }
+       if(!found)
+               goto rangerr;
+       return(1);
+}
+
+m_conv(str)
+{
+       register char *cp, *bp;
+       register int i;
+       char buf[16];
+
+       convdir = 1;
+       cp = bp = str;
+       if(*cp >= '0' && *cp <= '9')  {
+               while(*bp >= '0' && *bp <= '9') bp++;
+               delimp = bp;
+               return(atoi(cp));
+       }
+       bp = buf;
+       while((*cp >= 'a' && *cp <= 'z') || *cp == '.')
+               *bp++ = *cp++;
+       *bp++ = 0;
+       delimp = cp;
+       if(equal(buf, "first"))
+               return(mp->lowmsg);
+       else if(equal(buf, "last")) {
+               convdir = -1;
+               return(mp->hghmsg);
+       } else if(equal(buf, "cur") || equal(buf, "."))
+               return(mp->curmsg);
+       else if(equal(buf, "prev")) {
+               convdir = -1;
+               for(i = (mp->curmsg<=mp->hghmsg)? mp->curmsg-1: mp->hghmsg;
+                   i >= mp->lowmsg; i--) {
+                       if(mp->msgstats[i]&EXISTS)
+                               return(i);
+               }
+       } else if(equal(buf, "next"))
+               for(i = (mp->curmsg>=mp->lowmsg)? mp->curmsg+1: mp->lowmsg;
+                   i <= mp->hghmsg; i++) {
+                       if(mp->msgstats[i]&EXISTS)
+                               return(i);
+               }
+       return(-1);
+}
diff --git a/docs/historical/SRI-NOSC/subs.dir/m_convert.old b/docs/historical/SRI-NOSC/subs.dir/m_convert.old
new file mode 100644 (file)
index 0000000..494d97a
--- /dev/null
@@ -0,0 +1,165 @@
+#include "/m/mh/mh.h"
+
+#define ONLYDEL 1 /* use only deleted msgs */
+#define ONLYUNDEL 2 /* use only undelted msgs */
+#define DELORUNDEL 3 /* use either deleted msg or undeleted */
+int  convdir;
+struct msgs *mp;
+char *delimp;
+
+m_convert(name)
+{
+       register char *cp;
+       register int first, last;
+       int found, group, range, err, seltype, selected;
+       char *bp;
+
+       found = group = 0;
+       cp = name;
+       seltype = DELORUNDEL;
+       if(equal(cp, "all")) {
+               cp = "first-last";
+               }
+       else if(equal(cp, "undel")) {
+               cp = "first-last";
+               seltype = ONLYUNDEL;
+               }
+       else if(equal(cp, "del")) {
+               cp = "first-last";
+               seltype = ONLYDEL;
+               }
+       if((err = first = m_conv(cp)) <= 0)
+               goto badbad;
+       if(*(cp = delimp) && *cp != '-' && *cp != ':')  {
+       baddel: printf("Illegal argument delimiter: \"%c\"\n", *delimp);
+               return(0);
+       }
+       if(*cp == '-') {
+               group++;  cp++;
+               if((err = last = m_conv(cp)) <= 0) {
+         badbad:       if(err == -1)
+                               printf("No %s message\n", cp);
+                       else
+         badlist:              printf("Bad message list \"%s\".\n", name);
+                       return(0);
+               }
+               if(last < first) goto badlist;
+               if(*delimp) goto baddel;
+               if(first > mp->hghmsg || last < mp->lowmsg) {
+       rangerr:        printf("No messages in range \"%s\".\n", name);
+                       return(0);
+               }
+               if(last > mp->hghmsg)
+                       last = mp->hghmsg;
+               if(first < mp->lowmsg)
+                       first = mp->lowmsg;
+       } else if(*cp == ':') {
+               cp++;
+               if(*cp == '-') {
+                       convdir = -1;
+                       cp++;
+               } else if(*cp == '+') {
+                       convdir = 1;
+                       cp++;
+               }
+               if((range = atoi(bp = cp)) == 0)
+                       goto badlist;
+               while(*bp >= '0' && *bp <= '9') bp++;
+               if(*bp)
+                       goto baddel;
+               if((convdir > 0 && first > mp->hghmsg) ||
+                  (convdir < 0 && first < mp->lowmsg))
+                       goto rangerr;
+               if(first < mp->lowmsg)
+                       first = mp->lowmsg;
+               if(first > mp->hghmsg)
+                       first = mp->hghmsg;
+               for(last = first; last >= mp->lowmsg && last <= mp->hghmsg;
+                                               last =+ convdir)
+                       if(mp->msgstats[last]&EXISTS)
+                               if(--range <= 0)
+                                       break;
+               if(last < mp->lowmsg)
+                       last = mp->lowmsg;
+               if(last > mp->hghmsg)
+                       last = mp->hghmsg;
+               if(last < first) {
+                       range = last; last = first; first = range;
+               }
+       } else {
+               if(first > mp->hghmsg || first < mp->lowmsg ||
+                  !(mp->msgstats[first]&EXISTS)) {
+                       printf("Message %d doesn't exist.\n", first);
+                       return(0);
+               }
+               last = first;
+       }
+       while(first <= last) {
+               if(mp->msgstats[first]&EXISTS) {
+                       if(!(mp->msgstats[first]&SELECTED)) {
+                               if (seltype == ONLYDEL)
+                                       selected = mp->msgstats[first]&DELETED;
+                               else if (seltype == ONLYUNDEL)
+                                       selected = !(mp->msgstats[first]&DELETED);
+                               else selected = TRUE;
+                          if (selected) {
+                               mp->numsel++;
+                               mp->msgstats[first] =| SELECTED;
+                               if(first < mp->lowsel)
+                                       mp->lowsel = first;
+                               if(first > mp->hghsel)
+                                       mp->hghsel = first;
+                          }
+                       }
+                       found++;
+               }
+               first++;
+       }
+       if(!found)
+               goto rangerr;
+       return(1);
+}
+
+m_conv(str)
+{
+       register char *cp, *bp;
+       register int i;
+       char buf[16];
+
+       convdir = 1;
+       cp = bp = str;
+       if(*cp >= '0' && *cp <= '9')  {
+               while(*bp >= '0' && *bp <= '9') bp++;
+               delimp = bp;
+               return(atoi(cp));
+       }
+       bp = buf;
+       while((*cp >= 'a' && *cp <= 'z') || *cp == '.')
+               *bp++ = *cp++;
+       *bp++ = 0;
+       delimp = cp;
+       if(equal(buf, "first"))
+               return(mp->lowmsg);
+       else if(equal(buf, "last")) {
+               convdir = -1;
+               return(mp->hghmsg);
+       } else if(equal(buf, "cur") || equal(buf, "."))
+               return(mp->curmsg);
+       else if(equal(buf, "prev")) {
+               convdir = -1;
+               for(i = (mp->curmsg<=mp->hghmsg)? mp->curmsg-1: mp->hghmsg;
+                   i >= mp->lowmsg; i--) {
+                       if(mp->msgstats[i]&EXISTS)
+                               return(i);
+               }
+               return(-1);                     /* non-existent message */
+       } else if(equal(buf, "next"))  {
+               for(i = (mp->curmsg>=mp->lowmsg)? mp->curmsg+1: mp->lowmsg;
+                   i <= mp->hghmsg; i++) {
+                       if(mp->msgstats[i]&EXISTS)
+                               return(i);
+               }
+               return(-1);
+       } else
+               return(0);                     /* bad message list */
+}
diff --git a/docs/historical/SRI-NOSC/subs.dir/m_delete.c b/docs/historical/SRI-NOSC/subs.dir/m_delete.c
new file mode 100644 (file)
index 0000000..ab81a0e
--- /dev/null
@@ -0,0 +1,21 @@
+#include "mh.h"
+
+m_delete(key)
+char *key;
+{
+       register struct node *np, *npprev;
+
+       m_getdefs();
+       for(np = &m_defs; npprev = np; )  {
+               np = np->n_next;
+               if(uleq(np->n_name, key)) {
+                       npprev->n_next = np->n_next;
+                       cfree(np->n_name);
+                       cfree(np->n_field);
+                       free(np);
+                       def_flags =| DEFMOD;
+                       return(0);
+               }
+       }
+       return(1);
+}
diff --git a/docs/historical/SRI-NOSC/subs.dir/m_find.c b/docs/historical/SRI-NOSC/subs.dir/m_find.c
new file mode 100644 (file)
index 0000000..e8968c2
--- /dev/null
@@ -0,0 +1,12 @@
+#include "mh.h"
+
+m_find(str)
+{
+       register struct node *n;
+
+       m_getdefs();
+       for(n = m_defs; n; n = n->n_next)
+               if(uleq(n->n_name, str))
+                       return(n->n_field);
+       return(-1);
+}
diff --git a/docs/historical/SRI-NOSC/subs.dir/m_getdefs.c b/docs/historical/SRI-NOSC/subs.dir/m_getdefs.c
new file mode 100644 (file)
index 0000000..53f7bb4
--- /dev/null
@@ -0,0 +1,69 @@
+#include "/m/mh/mh.h"
+#include "/m/mh/iobuf.h"
+
+char    *mypath, defpath[128];
+char    mh_defs[];
+char    installproc[];
+
+m_getdefs()
+{
+       register struct node *np;
+       register int state, pid;
+       int status;
+       struct iobuf ib;
+       char name[NAMESZ], field[128];
+
+       if(defpath[0])
+               return;         /* We've already been called!   */
+       if(!mypath)
+               mypath = getpath(getruid());
+       copy(mh_defs, copy(mypath, defpath));
+
+       if(fopen(defpath, &ib) < 0) {
+               if((pid = fork()) == 0) {
+                       execl(installproc, "install-defs", "-detached", 0);
+                       printf("Can't install .mh_defs!!\n");
+                       flush();  exit(1);
+               } else if(pid == -1) {
+                       printf("No forks!\n");
+                       flush();  exit(1);
+               } else
+                       while((state = waita(&status)) != -1 && state != pid)
+                               ;
+               if(status || fopen(defpath, &ib) < 0) {
+                       printf("[install-defs aborted]\n");
+                       flush();  exit(1);
+               }
+       }
+
+#ifdef NEWS
+       fstat(ib.b_fildes, field);
+       deftime = (&field)->i_atime;
+#endif
+
+       np = &m_defs;
+       state = FLD;
+    for(;;)
+       switch(state = m_getfld(state,name,field,sizeof field,&ib)) {
+       case FLD:
+       case FLDEOF:
+               np->n_next = alloc(sizeof *np);
+               np = np->n_next;
+               np->n_name = getcpy(name);
+               np->n_field = trimcpy(field);
+               np->n_next = 0;
+               if(state == FLDEOF) {
+                       close(ib.b_fildes);
+                       return(0);
+               }
+               continue;
+       case BODY:
+       case BODYEOF:
+               printf(".mh_defs must not contain a body--it can't \
+end with a blank line!\n");
+       default:
+               printf("Bad format: .mh_defs!\n");
+               flush();
+               exit(1);
+       }
+}
diff --git a/docs/historical/SRI-NOSC/subs.dir/m_getfld.c b/docs/historical/SRI-NOSC/subs.dir/m_getfld.c
new file mode 100644 (file)
index 0000000..8add2c3
--- /dev/null
@@ -0,0 +1,86 @@
+#include "mh.h"
+
+int     m_fldsz;
+
+m_getfld(state, name, buf, bufsz, iob)
+int state, bufsz;
+char *name, *buf;
+struct iobuf *iob;
+{
+       register char *cp;
+       register c;
+
+ top:   while((c = getc(iob)) == '\001' && peekc(iob) == '\001')
+               while(getc(iob) != '\n');
+
+       if(c < 0)
+               return(FILEEOF);
+       m_fldsz = 0;
+
+       switch(state) {
+
+       case FLDEOF:
+       case BODYEOF:
+       case FLD:
+               if(c == '\n' || c == '-')
+                       goto body;
+               cp = name;
+               for(;;) {
+                       if(cp >= name+NAMESZ-1) {
+                               *cp = 0;
+printf("??Component Name Exceeds %d Chars:\n    \"%s\"\n", NAMESZ-1, name);
+                               return(LENERR);
+                       }
+                       if(c == ':')
+                               break;
+                       if(c == '\n' || c < 0) {
+                               *cp = 0;
+printf("??%s Encountered While Scanning for a colon:\n    \"%s\"\n",
+       (c < 0)? "<eof>":"<end of line>", name);
+                               return(FMTERR);
+                       }
+                       *cp++ = c;
+                       *cp   = 0;
+                       c = getc(iob);
+               }
+
+       case FLDPLUS:
+               cp = buf;
+               for(;;) {
+                       if((c = getc(iob)) < 0)
+                               return(FLDEOF);
+                       *cp++ = c;
+                       *cp   = 0;
+                       m_fldsz++;
+                       if(c == '\n')
+                               if((c = peekc(iob)) != ' ' && c != '\t')
+                                       if(c == '\001' || c < 0)
+                                               return(FLDEOF);
+                                       else
+                                               return(FLD);
+                       if(cp >= buf+bufsz-1)
+                               return(peekc(iob) < 0? FLDEOF:FLDPLUS);
+               }
+
+       body:   if(c == '-')
+                       while(getc(iob) != '\n') ;
+               buf[0] = 0;
+               if((c = getc(iob)) == '\001' && peekc(iob) == '\001')
+                       return(BODYEOF);
+
+       case BODY:
+               cp = buf;  *cp = 0;
+               for(;;) {
+                       if(c < 0 || (c == '\001' && peekc(iob) == '\001'))
+                               return(BODYEOF);
+                       *cp++ = c;
+                       *cp   = 0;
+                       m_fldsz++;
+                       if(cp >= buf+bufsz-1)
+                               return(((c=peekc(iob))<0||c=='\001')?
+                                       BODYEOF: BODY);
+                       c = getc(iob);
+               }
+
+       }
+}
diff --git a/docs/historical/SRI-NOSC/subs.dir/m_getfolder.c b/docs/historical/SRI-NOSC/subs.dir/m_getfolder.c
new file mode 100644 (file)
index 0000000..0a04b90
--- /dev/null
@@ -0,0 +1,11 @@
+char    defalt[];
+
+m_getfolder()
+{
+       register char *folder;
+
+       m_getdefs();
+       if((folder = m_find("folder")) == -1 || *folder == 0)
+               folder = defalt;
+       return(folder);
+}
diff --git a/docs/historical/SRI-NOSC/subs.dir/m_gmprot.c b/docs/historical/SRI-NOSC/subs.dir/m_gmprot.c
new file mode 100644 (file)
index 0000000..46b5435
--- /dev/null
@@ -0,0 +1,12 @@
+char msgprot[];
+
+m_gmprot()
+{
+       register int prot;
+
+       if((prot = m_find("msg-protect")) != -1)
+               prot = atooi(prot);
+       else
+               prot = atooi(msgprot);
+       return(prot);
+}
diff --git a/docs/historical/SRI-NOSC/subs.dir/m_gmsg.c b/docs/historical/SRI-NOSC/subs.dir/m_gmsg.c
new file mode 100644 (file)
index 0000000..d098946
--- /dev/null
@@ -0,0 +1,125 @@
+#include "/m/mh/mh.h"
+
+char    current[];
+char    listname[];
+struct  msgs *mp;
+
+m_gmsg(name)
+char *name;
+
+{
+       register int i, j;
+       register char *cp;
+       int  curfil;
+       char buf[132];
+
+       struct {
+               struct {
+                       int d_inum;
+                       char d_name[14];
+               } ent;
+               int terminator;
+       } dir;
+
+       struct {
+               int xhghmsg,
+                   xnummsg,
+                   xlowmsg,
+                   xcurmsg;
+               char xselist,
+                    xflags,
+                    xfiller,
+                    xothers;
+               char xmsgs[1000];
+       } msgbuf;
+
+       if((i = open(".", 0)) < 0)
+               return(0);
+       for(j = 0; j < 1000; j++)
+               msgbuf.xmsgs[j] = 0;
+       msgbuf.xcurmsg = 0;
+       msgbuf.xnummsg = 0;
+       msgbuf.xselist = 0;
+       msgbuf.xothers = 0;
+       msgbuf.xlowmsg = 5000;
+       msgbuf.xhghmsg = 0;
+       msgbuf.xflags  = (access(".",2) == -1)? READONLY:0;  /*RAND sys call*/
+       curfil = 0;
+       dir.terminator = 0;
+       cp = dir.ent.d_name;
+       for(;;) {
+               if(read(i, &dir, sizeof dir.ent) != sizeof dir.ent)
+                       break;
+               if(dir.ent.d_inum) {
+                       if(j = mu_atoi(cp)) {
+                               if(j > msgbuf.xhghmsg)
+                                       msgbuf.xhghmsg = j;
+                               msgbuf.xnummsg++;
+                               if(j < msgbuf.xlowmsg)
+                                       msgbuf.xlowmsg = j;
+                               msgbuf.xmsgs[j] = EXISTS;
+                               if(*cp == ',') msgbuf.xmsgs[j] =| DELETED;
+                               else msgbuf.xmsgs[j] =| UNDELETED;
+                       } else if(!equal(cp, ".")  &&
+                                 !equal(cp, "..") &&
+                                 *cp != ',')
+                                       if(equal(cp, current))
+                                               curfil++;
+                                       else if(equal(cp, listname))
+                                               msgbuf.xselist++;
+                                       else
+                                               msgbuf.xothers++;
+               }
+       }
+       if(!msgbuf.xhghmsg)
+               msgbuf.xlowmsg = 0;
+       close(i);
+       if(msgbuf.xflags&READONLY) {
+               copy(name, copy("cur-", buf));
+               if((cp = m_find(buf)) != -1)
+                       if(j = mu_atoi(cp))
+                               msgbuf.xcurmsg = j;
+       } else if(curfil && (i = open(current, 0)) >= 0) {
+               if((j = read(i, dir.ent.d_name, sizeof dir.ent.d_name)) >= 2){
+                       dir.ent.d_name[j-1] = 0;    /* Zap <lf> */
+                       if(j = mu_atoi(dir.ent.d_name))
+                               msgbuf.xcurmsg = j;
+               }
+               close(i);
+       }
+       if((i = alloc(sizeof *mp + msgbuf.xhghmsg + 2)) == -1)
+               return(0);
+       i->hghmsg   = msgbuf.xhghmsg;
+       i->nummsg   = msgbuf.xnummsg;
+       i->lowmsg   = msgbuf.xlowmsg;
+       i->curmsg   = msgbuf.xcurmsg;
+       i->selist   = msgbuf.xselist;
+       i->msgflags = msgbuf.xflags;
+       i->others   = msgbuf.xothers;
+       i->foldpath = name;
+       i->lowsel   = 5000;
+       i->hghsel   = 0;
+       i->numsel   = 0;
+       for(j = 0; j <= msgbuf.xhghmsg; j++)
+               i->msgstats[j] = msgbuf.xmsgs[j];
+       return(i);
+}
+
+
+mu_atoi(str)
+char *str;
+{
+       register char *cp;
+       register int i;
+
+       i = 0;
+       cp = str;
+       if(*cp==',') cp++;
+       while(*cp) {
+               if(*cp < '0' || *cp > '9' || i > 99)
+                       return(0);
+               i =* 10;
+               i =+ *cp++ - '0';
+       }
+       return(i);
+}
diff --git a/docs/historical/SRI-NOSC/subs.dir/m_maildir.c b/docs/historical/SRI-NOSC/subs.dir/m_maildir.c
new file mode 100644 (file)
index 0000000..b8c8867
--- /dev/null
@@ -0,0 +1,23 @@
+char *mypath;
+
+m_maildir(folder)
+{
+       register char *fold, *path, *cp;
+       static char mailfold[128];
+
+       m_getdefs();
+       if(!(fold = folder))
+               fold = m_getfolder();
+       if(*fold == '/' || *fold == '.')
+               return(fold);
+       cp = mailfold;
+       if((path = m_find("path")) != -1 && *path) {
+               if(*path != '/')
+                       cp = copy("/", copy(mypath, cp));
+               cp = copy(path, cp);
+               if(cp[-1] != '/')
+                       *cp++ = '/';
+       }
+       copy(fold, cp);
+       return(mailfold);
+}
diff --git a/docs/historical/SRI-NOSC/subs.dir/m_name.c b/docs/historical/SRI-NOSC/subs.dir/m_name.c
new file mode 100644 (file)
index 0000000..d1db6c2
--- /dev/null
@@ -0,0 +1,25 @@
+#include "/m/mh/mh.h"
+struct msgs *mp;
+m_name(num)
+{
+       static char name[4];
+       register char *cp;
+       register int i;
+
+       name[0] = 0;
+       name[1] = 0;
+       name[2] = 0;
+       name[3] = 0;
+       i = num;
+       cp = &name[3];
+       if(i > 0 && i < 1000) {
+               do {
+                       *--cp = (i % 10) + '0';
+                       i =/ 10;
+               } while(i);
+               if(( mp->msgstats[num]&EXISTS) && ( mp->msgstats[num]&DELETED))
+                       *--cp = ',';
+       } else
+               *--cp = '?';
+       return(cp);
+}
diff --git a/docs/historical/SRI-NOSC/subs.dir/m_news.cc b/docs/historical/SRI-NOSC/subs.dir/m_news.cc
new file mode 100644 (file)
index 0000000..24e8f66
--- /dev/null
@@ -0,0 +1,25 @@
+#include "mh.h"
+
+m_news()
+{
+       struct inode stbf;
+       struct iobuf in;
+       register flag, c;
+
+       m_getdefs();
+       if(stat(mhnews, &stbf) != -1 &&
+          stbf.i_mtime > deftime) {
+               fopen(mhnews, &in);
+               flag = getc(&in);
+               while((c = getc(&in)) != -1)
+                       if(c == NEWSPAUSE) {
+                               if(!gans("More? ", anoyes))
+                                       break;
+                       } else
+                               putchar(c);
+               flush();
+               if(flag == NEWSHALT)
+                       exit(0);
+               close(in.b_fildes);
+       }
+}
diff --git a/docs/historical/SRI-NOSC/subs.dir/m_replace.c b/docs/historical/SRI-NOSC/subs.dir/m_replace.c
new file mode 100644 (file)
index 0000000..96a96f5
--- /dev/null
@@ -0,0 +1,29 @@
+#include "mh.h"
+
+
+m_replace(key,value)
+char *key, *value;
+
+{
+       register struct node *np;
+
+       m_getdefs();
+       for(np = m_defs; ; np = np->n_next) {
+               if(uleq(np->n_name, key)) {
+                       if(!equal(value, np->n_field)) {
+                               cfree(np->n_field);
+                               np->n_field = value;
+                               def_flags =| DEFMOD;
+                       }
+                       return;
+               }
+               if(!np->n_next)
+                       break;
+       }
+       np->n_next = alloc(sizeof *np);
+       np = np->n_next;
+       np->n_name = key;
+       np->n_next = 0;
+       np->n_field = value;
+       def_flags =| DEFMOD;
+}
diff --git a/docs/historical/SRI-NOSC/subs.dir/m_setcur.c b/docs/historical/SRI-NOSC/subs.dir/m_setcur.c
new file mode 100644 (file)
index 0000000..e35edb0
--- /dev/null
@@ -0,0 +1,27 @@
+#include "mh.h"
+
+char    current[];
+struct msgs *mp;
+
+m_setcur(num)
+
+{
+       char buf[6];
+       register int i;
+       register char *cp1;
+
+       if(mp->msgflags&READONLY) {
+               m_replace(cp1 = concat("cur-",mp->foldpath,0), m_name(num));
+               free(cp1);
+       }
+       else {
+               cp1 = copy(m_name(num), buf);
+               *cp1++ = '\n';
+               if(!equal(current, "cur"))
+                       error("\"current\" got Clobbered!! Tell B. Borden");
+               if((i = creat(current, 0660)) >= 0) {
+                       write(i, buf, cp1-buf);
+                       close(i);
+               }
+       }
+}
diff --git a/docs/historical/SRI-NOSC/subs.dir/m_update.c b/docs/historical/SRI-NOSC/subs.dir/m_update.c
new file mode 100644 (file)
index 0000000..24a6619
--- /dev/null
@@ -0,0 +1,30 @@
+#include "mh.h"
+#include "/rnd/borden/h/iobuf.h"
+#include "/rnd/borden/h/signals.h"
+
+char    defpath[];
+
+m_update()
+{
+       struct iobuf out;
+       register struct node *np;
+       int save;
+
+       if(def_flags & DEFMOD) {
+               save = signal(SIGINT, 1);
+               if(fcreat(defpath, &out) < 0) {
+                       printf("Can't create %s!!\n", defpath);
+                       flush();  exit(1);
+               }
+               for(np = m_defs; np; np = np->n_next) {
+                       puts(np->n_name, &out);
+                       puts(": ", &out);
+                       puts(np->n_field, &out);
+                       putc('\n', &out);
+               }
+               fflush(&out);
+               signal(SIGINT, save);
+               close(out.b_fildes);
+               def_flags =& ~DEFMOD;
+       }
+}
diff --git a/docs/historical/SRI-NOSC/subs.dir/makedir.c b/docs/historical/SRI-NOSC/subs.dir/makedir.c
new file mode 100644 (file)
index 0000000..28c3a71
--- /dev/null
@@ -0,0 +1,28 @@
+char   foldprot[];
+
+makedir(dir)
+{
+       register int i, j;
+       int status;
+
+       if((i = fork()) == 0) {
+               execl("/bin/mkdir", "mkdir", dir, 0);
+               printf("Can't exec mkdir!!?\n");
+               flush();
+               return(0);
+       }
+       if(i == -1) {
+               printf("Can't fork\n");
+               flush();
+               return(0);
+       }
+       while((j = waita(&status)) != i && j != -1) ;
+       if(status) {
+               printf("Bad exit status (%o) from mkdir.\n", status);
+               flush();
+               return(0);
+       }
+       chmod(dir, ((i = m_find("folder-protect")) != -1)?
+                  atooi(i) : atooi(foldprot));
+       return(1);
+}
diff --git a/docs/historical/SRI-NOSC/subs.dir/peekc.c b/docs/historical/SRI-NOSC/subs.dir/peekc.c
new file mode 100644 (file)
index 0000000..34a14f7
--- /dev/null
@@ -0,0 +1,15 @@
+#include "/rnd/borden/h/iobuf.h"
+
+peekc(iob)
+struct iobuf *iob;
+{
+       register c;
+       register struct iobuf *p;
+
+       p = iob;
+       if((c = getc(p)) >= 0) {
+               p->b_nleft++;
+               p->b_nextp--;
+       }
+       return(c);
+}
diff --git a/docs/historical/SRI-NOSC/subs.dir/pr_array.c b/docs/historical/SRI-NOSC/subs.dir/pr_array.c
new file mode 100644 (file)
index 0000000..00fddab
--- /dev/null
@@ -0,0 +1,9 @@
+pr_array(cp,ap)
+char *cp,  **ap;
+{
+       register  int  i;
+
+       for(i=0;  *ap;  ap++,i++)
+               printf("%s[%d]=> %s\n", cp,i,*ap);
+}
+
diff --git a/docs/historical/SRI-NOSC/subs.dir/printsw.c b/docs/historical/SRI-NOSC/subs.dir/printsw.c
new file mode 100644 (file)
index 0000000..a69f1e1
--- /dev/null
@@ -0,0 +1,26 @@
+#include "mh.h"
+
+printsw(substr, swp)
+char *substr;
+struct swit *swp;
+{
+       char buf[128];
+       register char *cp, *cp1;
+       register int i;
+       int len;
+
+       len = length(substr);
+       for(; swp->sw; swp++)
+               if(!*substr ||                  /* null matches all strings */
+                  (ssequal(substr, swp->sw) && len >= swp->minchars))
+                       if(swp->minchars > 0) {
+                               cp = buf;
+                               *cp++ = '(';
+                               for(cp1 = swp->sw, i = 0; i < swp->minchars; i++)
+                                       *cp++ = *cp1++;
+                               *cp++ = ')';
+                               while(*cp++ = *cp1++);
+                               printf("  -%s\n", buf);
+                       } else if(swp->minchars == 0)
+                               printf("  -%s\n", swp->sw);
+}
diff --git a/docs/historical/SRI-NOSC/subs.dir/puts.c b/docs/historical/SRI-NOSC/subs.dir/puts.c
new file mode 100644 (file)
index 0000000..b4d1616
--- /dev/null
@@ -0,0 +1,18 @@
+#include "/rnd/borden/h/iobuf.h"
+
+puts(buf, iob)
+{
+       register char *cp;
+       register struct iobuf *ip;
+       extern int errno;
+
+       cp = buf;
+       ip = iob;
+
+       errno = 0;
+       if(ip->b_fildes)
+               while(*cp) {
+                       putc(*cp++, ip);
+                       if(errno) { perror("Write error"); exit(-1); }
+               }
+}
diff --git a/docs/historical/SRI-NOSC/subs.dir/showfile.c b/docs/historical/SRI-NOSC/subs.dir/showfile.c
new file mode 100644 (file)
index 0000000..b6ce76a
--- /dev/null
@@ -0,0 +1,18 @@
+showfile(file)
+{
+       register int i, cnt;
+       char buf[512];
+
+       type(1, "\n");
+       if((i = open(file, 0)) == -1) {
+               printf("Can't open %s\n", file);
+               return 1;
+       }
+       do
+               if((cnt = read(i, buf, sizeof buf)) > 0)
+                       write(1, buf, cnt);
+       while(cnt == sizeof buf);
+       close(i);
+       type(1, "\n");
+       return 0;
+}
diff --git a/docs/historical/SRI-NOSC/subs.dir/smatch.c b/docs/historical/SRI-NOSC/subs.dir/smatch.c
new file mode 100644 (file)
index 0000000..0da9c7e
--- /dev/null
@@ -0,0 +1,37 @@
+#include "mh.h"
+
+/* switch match, or any unambiguous abbreviation */
+/* exact match always wins, even if shares same root */
+/* returns subscript in zero-terminated tbl[] of strings */
+/* returns -1 if no match, -2 if ambiguous */
+
+smatch(string, swp)
+char *string;
+struct swit *swp;
+{
+       register char *sp, *tcp;
+       struct swit *tp;
+       int firstone, strlen;
+
+       firstone = -1;
+
+       for (strlen = length(string), tp = swp; tcp = tp->sw; tp++) {
+               if(strlen < abs(tp->minchars)) continue;      /* no match */
+               for (sp = string; *sp == *tcp++; ) {
+                       if (*sp++ == 0) return(tp-swp); /* exact match */
+               }
+               if (*sp != 0) {
+                       if (*sp != ' ') continue; /* no match */
+                       if (*--tcp == 0) return(tp-swp); /* exact match */
+               }
+               if (firstone == -1) firstone = tp-swp; /* possible match */
+               else firstone = -2;     /* ambiguous */
+       }
+
+       return (firstone);
+}
+
+abs(i)
+{
+       return(i < 0 ? -i : i);
+}
diff --git a/docs/historical/SRI-NOSC/subs.dir/ssequal.c b/docs/historical/SRI-NOSC/subs.dir/ssequal.c
new file mode 100644 (file)
index 0000000..124581c
--- /dev/null
@@ -0,0 +1,8 @@
+ssequal(substr, str)
+char *substr, *str;
+{
+       while(*substr)
+               if(*substr++ != *str++)
+                       return(0);
+       return(1);
+}
diff --git a/docs/historical/SRI-NOSC/subs.dir/subs.run b/docs/historical/SRI-NOSC/subs.dir/subs.run
new file mode 100755 (executable)
index 0000000..d5542d4
--- /dev/null
@@ -0,0 +1,20 @@
+ar rv /m/mh/subs.a     m_maildir.o     \
+               m_setcur.o      \
+               makedir.o       \
+               m_gmprot.o      \
+               m_getfolder.o   \
+               m_convert.o     \
+               m_find.o        \
+               m_replace.o     \
+               m_update.o      \
+               m_getdefs.o     \
+               m_getfld.o      \
+               m_gmsg.o        \
+               m_name.o        \
+               add.o atoi.o atooi.o concat.o \
+               gans.o getchar.o \
+               getcpy.o peekc.o puts.o cputc.o trimcpy.o uleq.o \
+               showfile.o      \
+               fdcompare.o cfree.o copyip.o    \
+               locv.o m_delete.o ambigsw.o help.o \
+               invo_name.o printsw.o ssequal.o smatch.o pr_array.o
diff --git a/docs/historical/SRI-NOSC/subs.dir/trimcpy.c b/docs/historical/SRI-NOSC/subs.dir/trimcpy.c
new file mode 100644 (file)
index 0000000..d14ab6c
--- /dev/null
@@ -0,0 +1,16 @@
+trimcpy(str)
+{
+       register char *cp, *sp;
+
+       cp = str;
+       while(*cp == ' ' || *cp == '\t')
+               cp++;
+       sp = cp;
+       while(*sp)
+               if(*sp++ == '\n')
+                       break;
+       *--sp = 0;
+       sp = alloc(sp - cp + 1);
+       copy(cp, sp);
+       return(sp);
+}
diff --git a/docs/historical/SRI-NOSC/subs.dir/uleq.c b/docs/historical/SRI-NOSC/subs.dir/uleq.c
new file mode 100644 (file)
index 0000000..da58a0c
--- /dev/null
@@ -0,0 +1,13 @@
+uleq(s1, s2)
+{
+       register char *c1, *c2;
+       register int c;
+
+       c1 = s1; c2 = s2;
+       while(c = *c1++)
+               if(c != *c2 && (c =| 040) != *c2)
+                       return(0);
+               else
+                       c2++;
+       return(*c2 == 0);
+}
diff --git a/docs/historical/SRI-NOSC/undelete.c b/docs/historical/SRI-NOSC/undelete.c
new file mode 100644 (file)
index 0000000..2cfead6
--- /dev/null
@@ -0,0 +1,103 @@
+#include "mh.h"
+
+int vecp, *vec[MAXARGS], fout;
+struct msgs *mp;
+struct swit switches[] {
+       "all",         -3,      /* 0 */
+       "help",         4,      /* 1 */
+       0,              0
+};
+
+main(argc, argv)
+char *argv[];
+{
+       char *folder, *nfolder, *maildir, *msgs[100], buf[32];
+       register int msgnum;
+       register char *cp, *sp;
+       int msgp;
+       char *ap, *inp;
+       char *arguments[50], **argp;
+
+       fout = dup(1);
+#ifdef NEWS
+       m_news();
+#endif
+       folder = msgp = 0;
+       vecp = 1;
+       inp = cp = argv[0];
+       while(*cp)
+               if(*cp++ == '/')
+                       inp = cp;
+       ap = inp;
+       if((cp = m_find(ap)) != -1) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                       /* unknown */
+                       case -1:printf("-%s unknown\n", cp);
+                               goto leave;
+                                                        /* -all */
+                       case 0: printf("\"-all\" changed to \"all\"\n");
+                               goto leave;
+                                                       /* -help */
+                       case 1: help(concat( inp, " [+folder] [msgs] [switches]", 0),
+                                    switches);
+                               goto leave;
+                       }
+               if(*cp == '+')  {
+                       if(folder) {
+                               printf("Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               folder = cp + 1;
+               } else
+                       msgs[msgp++] = cp;
+       }
+       if(!msgp)
+               msgs[msgp++] = "cur";
+       if(!folder)
+               folder = m_getfolder();
+       maildir = m_maildir(folder);
+       if(chdir(maildir) < 0) {
+               printf("Can't chdir to: "); flush();
+               perror(maildir);
+               goto leave;
+       }
+       if(!(mp = m_gmsg(folder))) {
+               printf("Can't read folder!?\n");
+               goto leave;
+       }
+       if(mp->hghmsg == 0) {
+               printf("No messages in \"%s\".\n", folder);
+               goto leave;
+       }
+       for(msgnum = 0; msgnum < msgp; msgnum++)
+               if(!m_convert(msgs[msgnum], DELETED, DELETED))
+                       goto leave;
+       if(mp->numsel == 0) {
+               goto leave;
+       }
+       m_replace("folder", folder);
+       for(msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
+               if(mp->msgstats[msgnum] & SELECTED) {
+                       sp = getcpy(m_name(msgnum));
+                       cp = copy(sp, buf);
+                       while(--cp >= buf && *cp != '/');
+                       do *++cp = cp[1];
+                       while(*cp);
+                       unlink(buf);
+                       if(link(sp, buf) == -1 || unlink(sp) == -1)
+                               printf("Can't rename %s to %s.\n", sp, buf);
+               }
+leave:
+       m_update();
+       flush();
+}
diff --git a/docs/historical/SRI-NOSC/undelete.run b/docs/historical/SRI-NOSC/undelete.run
new file mode 100644 (file)
index 0000000..a877161
--- /dev/null
@@ -0,0 +1,5 @@
+if -r undelete rm undelete
+load -n undelete subs.a strings.a wait -O libg.a libh.a libg.a
+if -r a.out mv a.out undelete
+:                                      fini
+
diff --git a/docs/historical/SRI-NOSC/wait.s b/docs/historical/SRI-NOSC/wait.s
new file mode 100644 (file)
index 0000000..76599b8
--- /dev/null
@@ -0,0 +1,21 @@
+/ C library -- wait     /* modified - does not call nargs */
+
+/ pid = wait(&status);
+/
+/ pid == -1 if error
+/ status indicates fate of process, if given
+
+.globl  _wait, _waita, cerror
+
+_waita:
+_wait:
+       mov     r5,-(sp)
+       mov     sp,r5
+       sys     wait
+       bec     1f
+       tst     (sp)+
+       jmp     cerror
+1:
+       mov     r1,*4(r5)       / status return
+       mov     (sp)+,r5
+       rts     pc
diff --git a/docs/historical/SRI-NOSC/write.c b/docs/historical/SRI-NOSC/write.c
new file mode 100644 (file)
index 0000000..eb6fb10
--- /dev/null
@@ -0,0 +1,190 @@
+#include "mh.h"
+#include "signals.h"
+
+
+char    draft[],
+       components[],
+       stdcomps[],
+       sysed[],
+#ifdef PROMPT
+       prmtproc[],
+#endif
+       sndproc[];
+
+int    fout;
+
+char    *anyus[] {
+       "no",   0,
+       "yes",  0,
+       "use",  0,
+       "show", 0,
+       0,
+};
+
+char    *anyv[] {
+       "no",           0,
+       "yes",          0,
+       "verbose",      0,
+       0,
+};
+
+struct swit switches[] {
+       "editor editor",  0,      /* 0 */
+       "form formfile",  0,      /* 1 */
+       "use",            0,      /* 2 */
+       "nouse",          0,      /* 3 */
+       "help",           4,      /* 4 */
+       0,                0
+};
+
+main(argc, argv)
+char *argv[];
+{
+       register char *cp;
+       register int in, out;
+       int use, cnt, status, intr;
+       char buf[512], path[128], *ed, *file, *vec[10], *form;
+       char *inp, *ap;
+       char *arguments[50], **argp;
+
+       fout = dup(1);
+#ifdef NEWS
+       m_news();
+#endif
+       form = use = file = ed = 0;
+       ap = cp = argv[0];
+       while(*cp)
+               if(*cp++ == '/')
+                       ap = cp;
+       inp = ap;
+       if((cp = m_find(ap)) != -1) {
+               ap = brkstring(cp = getcpy(cp), " ", '\n');
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-') {
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                       /* unknown */
+                       case -1:printf("-%s unknown\n", cp);
+                               goto leave;
+                       case 0: if(!(ed = *argp++)) {   /* -editor */
+      missing:  printf("Missing argument for %s switch\n", argp[-2]);
+                                       goto leave;
+                               }
+                               continue;
+                       case 1: if(!(form = *argp++))   /* -form */
+                                       goto missing;
+                               continue;
+                       case 2: use = 1;  continue;     /* -use */
+                       case 3: use = 0;  continue;     /* -nouse */
+                       case 4: help(concat( inp, " [file] [switches]", 0),
+                                    switches);
+                               goto leave;
+                       }
+               }
+               file = cp;
+       }
+       if(form) {
+               if((in = open(m_maildir(form), 0)) < 0) {
+                       printf("Can't open form file: %s\n", form);
+                       goto leave;
+               }
+       } else if((in = open(m_maildir(components), 0)) < 0 &&
+                  (in = open(stdcomps, 0)) < 0) {
+                       printf("Can't open default components file!!\n");
+                       goto leave;
+       }
+       if(!file)
+               file = draft;
+       copy(m_maildir(file), path);
+       if((out = open(path, 0)) >= 0) {
+               if(use || fdcompare(in, out))
+                       goto editit;
+/*
+               cp = concat("\"", path, "\" exists; delete? ", 0);
+               while((status = gans(cp, anyus)) == 3)
+                               showfile(path);
+               if(status == 2) {
+                       use++;
+                       goto editit;
+               }
+               if(status == 0)
+                       goto leave;
+*/
+               close(out);
+       } else if(use) {
+               printf("\"%s\" doesn't exist!\n", path);
+               goto leave;
+       }
+       if((out = creat(path, m_gmprot())) < 0) {
+               printf("Can't create \"%s\"\n", path);
+               goto leave;
+       }
+       do
+               if(cnt = read(in, buf, sizeof buf))
+                       write(out, buf, cnt);
+       while(cnt == sizeof buf);
+       close(in);
+editit:
+       close(out);
+       if(!ed && (ed = m_find("editor")) == -1)
+#ifdef PROMPT
+               ed = prmtproc;
+#else
+               ed = sysed;
+#endif
+       intr = signal(SIGINT, 1);
+       if((in = fork()) == 0) {
+               m_update();
+               flush();
+               execlsrh(ed, path, 0);
+               printf("Can't exec editor!!\n");
+               flush();  exit(1);
+       } else if(in == -1) {
+               printf("No forks!\n");
+               goto leave;
+       } else
+               while((out = waita(&status)) != -1 && out != in) ;
+       if(status) {
+               printf("[command aborted--%s ", file);
+               if(!use && status > 0377) {
+                       unlink(path);
+                       printf("deleted]\n");
+               } else
+                       printf("preserved]\n");
+               goto leave;
+       }
+       signal(SIGINT, intr);
+#ifdef TEST
+       printf("!! Test Version of SEND Being Run !!\n");
+       printf("   Send verbose !\n\n");
+#endif
+/*     in = concat("Send \"", file, "\"? ", 0); */
+       in = "Send? ";
+/***    printf("Send \"%s\"? ", file);  ***/
+       if((out = gans(in, anyv)) > 0) {
+               in = 0;
+               vec[in++] = "mh-sndproc";
+               vec[in++] = path;
+               if(out == 2)
+                       vec[in++] = "-verbose";
+               vec[in++] = 0;
+               m_update();
+               flush();
+               execv(sndproc, vec);
+               printf("Can't exec send process.\n");
+       }
+leave:
+       m_update();
+       flush();
+}
+
+
+
+
+
diff --git a/docs/historical/SRI-NOSC/write.run b/docs/historical/SRI-NOSC/write.run
new file mode 100644 (file)
index 0000000..19c7532
--- /dev/null
@@ -0,0 +1,5 @@
+if -r write rm write
+load -n write subs.a strings.a wait.o -O libg.a libh.a libg.a
+if -r a.out mv a.out write
+:                                      fini
+
diff --git a/docs/historical/mh-6.8.5/miscellany/mem/a.out b/docs/historical/mh-6.8.5/miscellany/mem/a.out
deleted file mode 100755 (executable)
index 90eeea6..0000000
Binary files a/docs/historical/mh-6.8.5/miscellany/mem/a.out and /dev/null differ
diff --git a/docs/historical/mh-jun-1982/4bsd.changes b/docs/historical/mh-jun-1982/4bsd.changes
new file mode 100644 (file)
index 0000000..d437462
--- /dev/null
@@ -0,0 +1,7 @@
+
+
+11/15/80
+
+       _sobuf is defined.  Previously it was in stdio.h
+
+       errno is defined.  Previously it was in errno.h
diff --git a/docs/historical/mh-jun-1982/ANOMALIES b/docs/historical/mh-jun-1982/ANOMALIES
new file mode 100644 (file)
index 0000000..7198dc9
--- /dev/null
@@ -0,0 +1,12 @@
+"Extras" contains several weird C sources.  They should be checked.
+Still gotta fix Mail
+Gotta make sure the Make onceonly installs /etc/MailAliases and /usr/spool/locks
+Should make a whole subsection for installing the News stuff.  It should
+all be in a subdirectory with its own makefile, in fact, since it basically
+is an entirely separate module from the other stuff.
+
+Berkeley seems to have their own program called "l" in /usr/ucb.  
+
+Some systems purge /usr/tmp in their /etc/rc file, thus destroying the
+/usr/tmp/mh directory.  MH programs which need that directory should attempt
+to make it if it is not there.
diff --git a/docs/historical/mh-jun-1982/Alias.Design b/docs/historical/mh-jun-1982/Alias.Design
new file mode 100644 (file)
index 0000000..ed2490a
--- /dev/null
@@ -0,0 +1,67 @@
+The Alias file for mail delivery is the file
+
+       /etc/MailAliases
+
+Each line of the alias file has the format:
+
+match : alias
+
+Where:
+
+       alias       :=  simple-list
+                   |   "<" alias-file
+                   |   "=" UNIX-group
+                   |   "*"
+
+       simple-list :=  simple-name
+                   |   simple-list, simple-name
+
+Alias-file is a fully qualified UNIX file name.  UNIX-group is a
+group name from /etc/group.  A simple-name is a local user login
+name, including only alphanumerics, `.' and `-'.  Throughout this
+file case is ignored, except for alias-file.
+
+In match, a trailing * on a name will match anything. (See example
+below.)
+
+The procedure for mail aliasing is:
+
+1) Build a list of all addresses from the message to be
+   delivered, eliminating duplicates.
+
+2) For each line in the alias file, compare "match" against all
+   of the existing addresses.  If a match, remove the matched
+   name from the address list, and add each new alias name to the
+   address list if it is not already on the list.
+
+Since the alias file is read line by line, forward references
+work, but backward references are not recognized, thus, there is
+no recursion.
+
+E.g.:
+
+Borden: bruce
+Bruce: bsb
+Wharman: mike
+ASRL: bsb, mike, obrien, giarla
+UNIX-committee: < /usr/people/unix-committee
+System: = sys
+Everyone: *
+news.*: news
+   ...
+
+In the "unix-committee" example, the file "/usr/people/unix-
+committee" contains one simple-name, or a list of comma separated
+simple-names.  A new-line will be treated as a blank in this
+file, s.a.
+
+       foo, fie,
+       fum, fiddle
+
+In the "system" case, the names from the group "sys" will be used
+as the expanded name list.
+
+In the "news.*" case, all names of the form "news.<anything>" will
+be mapped to "news".  This is used for the MH news facility.
+
+Bruce Borden    October 1979
diff --git a/docs/historical/mh-jun-1982/Bugs b/docs/historical/mh-jun-1982/Bugs
new file mode 100644 (file)
index 0000000..320ebf7
--- /dev/null
@@ -0,0 +1,213 @@
+11/14/79
+       If .mh_profile contains an entry like "show: -pr -a -b -c" and you
+       call "show" with the explicit switch -nopr, then you have those
+       dangling -a -b -c switches that were intended for pr.
+       (Bound the switch list for pr, etc., with a semi-colon?)
+
+2/1/80
+       "file +junk" makes junk a folder, while "file +.junk" makes ".junk"
+       a subfolder. "file" should test for pathname beginning with "./"
+       instead of just '.'
+
+9/15/80
+       When repl gets an adrparse error, it should return to
+       "What now?" instead of aborting. (But see objections in
+       /r/phyl/Mail/MH/16)
+
+       The same goes for comp, dist, forw
+
+9/29/80
+       When send is invoked with no args, and the draft already
+        exists, options to "use draft?" should include "list" along with
+       yes/no
+
+10/21/80
+       Tabs in address lists aren't recognized.
+
+12/23/80
+       Fix and install "dist"
+
+1/14/81
+       inc -nochangecur displays that the first-inc'ed message is the current
+       message, and it's not.  It should also do a scan from cur, I think.
+       (I fixed the 1st bug, but not the scan from cur.   /phyl 7/9/81)
+
+5/28/81
+       'news' will break when there are multiple news folders in the 'To:'
+       field(s)!
+
+
+7/7/81 phyl
+        Re:Log:"3/23/81 jdg/day: changed deliver.c to check for effective
+        uid and gid while it is preventing forgery of mail.  Needed for
+        uucp, when uucico is invoked by a real person instead of uucp
+        itself."
+
+        The real fix should be to check for real uid==0 (srvrftp) or real
+        gid==daemon (any uu program) or effective gid==daemon (human
+        running uucico, and uucico should be SGID daemon).
+
+2/16/81
+       /usr/tmp/mh files are readable by the world.
+       So are /usr/spool/uucp files.
+
+2/21/81
+       A message should not have to exist for you to be able to use
+       its number in a range, as in 'scan cur-last' when cur does
+       not exist.
+
+2/28/81
+       "This RAND-UNIX stuff (adding and removing them from message
+       headers on the vax) is a crock.  Reply strips 'RAND-UNIX' off of
+       addresses, but not 'rand-unix'.  If I type it up myself, deliver
+       rejects either of them."  --guyton
+
+
+4/4/81
+       "The delivery program should not leave headers that the mailer doesn't
+       understand.  Replying to the following header was painful: " --jim
+
+       (Message inbox:1)
+       From: graphics!root
+       Date:  4 Apr 1981 at 2138-PST
+       To: Vax!mh-discussion at RAND-UNIX
+       Cc: greep at SU-ISL
+       Subject: Mail to terminals
+       From: greep at SU-ISL
+
+
+       ...AND LOTS OF OTHER MESSAGE HEADER OBJECTIONS
+
+4/7/81
+       scan and inc should check ALIASES and recognize UUCP localhost!me
+       when deciding whether or not the message is from me.
+
+4/16/81
+       Deliver should run one uux per site instead of one per addressee.
+
+6/2/81
+       "rmf" should automatically remove .e* files from the named folder.
+
+7/81
+       deliver fails to recognize "at" when it is preceded by
+            more than one blank.
+
+       repl tries to parse a Sender [or From] field, and a To
+            field, without first testing for their existence.
+
+       file protections on rmail/uucico are inconsistent with
+            deliver's internal user/group tests.
+
+       deliver fails to recognize that localhost!user is indeed user.
+            (Should it?)
+
+       temporary mail files stay around when the "no such local user"
+            error occurs--because of a spurious flag test.
+
+       deliver should parenthesize (user at host) as well as (host!user)
+            when constructing the uux command.
+
+       rmail should direct stderr to a file before invoking deliver.
+
+       rmail should check for unknown local user and send return mail to the
+            originator. (Can't fix unless no intervening Arpanet addresses.)
+
+       rmail should add a Date: component if there is none.
+
+       mail headers should be reordered.
+
+7/23/81
+       "mail" should be in /bin, not in /usr/randbin. (?)
+
+8/17/81
+       "rmf" should verify that the requested folder is not the current
+       directory.
+
+8/20/81
+       /usr/tmp/mh and /usr/MailAliases should be defined in strings.a
+
+9/1/81
+       repl should remove leading blanks from date and subject fields
+       before putting them in the new in-reply-to and subject fields.
+       (Greep)
+
+9/9/81
+       Adrparse should recognize the full RFC733 syntax; viz, colon
+       as part of the address list.
+
+10/2/81
+       Subject: news bug
+       From: phyl at RAND-UNIX
+
+       The table of news topics overflowed.
+
+        news.c counts all non-dot files in the directory /usr/news to
+        determine the number of news topics.  But mail sent to an UNKNOWN
+        news topic remains in the top level news directory, erroneously
+        getting counted into the total.  Either .mh-receive should stow
+        undeliverable news into another directory, or news.c should count
+        only directory entries.
+
+10/6/81
+       mhl should know about termcap
+
+10/14/81
+       Subject: Mail to "everyone"
+       From: obrien at RAND-UNIX
+
+                An insoluble problem: sending mail to "everyone" (a risky
+        business at best) generates mail to every line in /etc/passwd,
+        including those like "uucp", "unix32v", and such which aren't real
+        people.  An exception list is no help because it gets out of date.
+        Only cure I know of is to go through /usr/spool/mail every now and
+        again and get rid of phony files.
+
+11/10/81
+       Subject: HOSTNUM not necessary
+       From: greep at SU-DSN
+
+        Mh deliver should really not need HOSTNUM (this is in
+         /usr/include/whoami.h) - it can get the number by searching for
+         HOSTNAME in the host table.
+
+11/18/81
+       SUBJECT: folder with a -fast flag doesn't change current folder
+       From: norm at RAND-UNIX
+
+11/81
+       Message lists should not be reordered.  (Norm, Phyl)
+
+12/17/81
+       The alias function doesn't work when a single message contains
+       multiple instances of the address form "foo.*"--ergo, a message
+       cannot be sent to more than one news group.
+
+       Note that /usr/news/.mh_receive won't recognize multiple news
+       groups in a single message either!
+
+12/19/81
+       If a message is addressed to more than one local alias-group,
+       people who are in more than one of the groups receive multiple
+       copies of the message. (I think! --phyl--)
+
+1/5/82
+       If you send a message to a bad uucp host name, it a) gives you
+       an error message, b) queues the mail anyway, and c) deletes the
+       draft because the mail was "correctly sent".  Ha!
+       It should a) give you an error message and b) punt.
+                       --Michael W.--
+
+1/19/82
+
+       MH argument parsing should be upgraded to allow
+       folder arguments to have a space between the +
+       and the folder name so you can use shell matching
+       syntax.  Example:
+
+          % folder + /usr/news/net-g*
+          % cd !$
+
+       --dave
+
+3/11/82
+       deliver should clean up before exiting. 
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/DOC/README b/docs/historical/mh-jun-1982/DOC/README
new file mode 100644 (file)
index 0000000..2d2dc74
--- /dev/null
@@ -0,0 +1 @@
+More recent information is to be found in the man pages in ../man
diff --git a/docs/historical/mh-jun-1982/DOC/brief b/docs/historical/mh-jun-1982/DOC/brief
new file mode 100644 (file)
index 0000000..b09d666
--- /dev/null
@@ -0,0 +1,41 @@
+
+
+
+
+       R-2367-AF, The MH Message Handling System: Users Manual,
+       B. S. Borden, R. S. Gaines, N. Z. Shapiro, November 1979.
+
+
+
+PURPOSE: To describe an electronic message handling system.  The report
+outlines the implementation and provides complete user level documentation
+for efficient utilization of a new computer utility.
+
+RELATED TO: Project AIR FORCE work on command and control, ...
+
+
+DISCUSSION:  The MH message handling system was designed and implemented
+to  provide  comprehensive electronic message facilities.  It implements
+no new facilities which are not available in other message systems,  but
+its  close  integration  with  the system's command interpreter lends it
+more power and flexibility than is otherwise available.  Rather  than  a
+standard  implementation  in  which  all  of  the  functions  of message
+handling are implemented in one monolithic program, MH is  a  collection
+of  loosly  coupled  programs,  each  of  which implement one particular
+aspect of message handling.
+     This implementation strategy has been found to be very flexible and
+easy  to  use.  Rather  than  having  to learn a new set of commands and
+conventions for interacting with  the  message  system,  users  use  the
+standard  system  command facility which they are already familiar with.
+Also, each module is relatively small, easy to debug and modify, and new
+modules  are  easy  to  add in a completely transparent manner.  Another
+important design feature of MH is its use of the operating  system  file
+facilities  directly.  That  is,  there  are  no monolithic message data
+bases,  rather  messages  are  stored   as   individual   files   within
+directories, which act as message folders.  Thus, all standard utilities
+are available on the messages without  having  to  code  them  into  the
+message system itself.
+     Finally, each user of MH has a personal profile which allows for
+tailoring of each command.  With these facilities, users are able to
+start using the package immediately, and to enhance their interface as
+they gain knowledge of their own usage patterns.
diff --git a/docs/historical/mh-jun-1982/DOC/mh.me b/docs/historical/mh-jun-1982/DOC/mh.me
new file mode 100644 (file)
index 0000000..f46b2fa
--- /dev/null
@@ -0,0 +1,2508 @@
+.de $c                          \" Major Heading printer
+.ce
+.b "\\s12\\n+(ch.\\ \\$1\\s0"   \" 12 Point Bold Header
+.(x
+
+\ \ \ \\n(ch.\\ \\ \\$1
+.)x
+.sp 45p         \" 45 point space or about 1/2 inch
+..
+\".nr xs .15v     \" Put index entries closer together
+.(x
+
+Section
+.)x _
+.de $0          \" Sub-Heading macro called AFTER printing the heading
+.(x
+.sp .3v
+.ti .5i
+\\$1
+.)x
+..
+.de $s          \" Macro to print footnote separator
+\"\l'2i'        \" No line drawn
+.if n \
+.       sp 1.3  \" But extra space to make up for it.
+..
+.fc ^ ~         \" The characters ^ and ~ CANNOT BE USED
+\"                 throughout this document except as field
+\"                 delimiter & pad indicator!
+.he ''-%-''
+.ll 32P         \" 32 Picas or about 5+1/3 inch Line Length
+.if n .ll 72m   \" Use 72 ems for nroff
+.nr ss 30p      \" 30 point space before section titles
+.nr fm 5v       \" Rand likes bigger than normal [3v] bottom margins
+.nr bm 7v       \"   ditto
+.ds . \\fB.\\fP\\h'-(1m/3)' \" Bold period to stand out.
+.ds << <\\h!-(\\w'<'/2)!<
+.ds >> >\\h!-(\\w'>'/2)!>
+.ds ** \v'-3p'\s+1*\s0\v'+3p'
+.++ C
+.+c INTRODUCTION
+.pp
+Although people can travel cross-country in hours and can
+reach others by telephone in seconds, communications still depend
+heavily upon paper, most of which is distributed through the mails.
+.pp
+There are several major reasons for this continued dependence on
+written documents.
+First, a written document may be proofread
+and corrected prior to its distribution, giving the author
+complete control over his words.
+Thus, a written document is
+better than a telephone conversation in this respect.
+Second,
+a carefully written document is far less likely to be
+misinterpreted or poorly translated than a phone conversation.
+Third, a signature offers reasonable verification of authorship,
+which cannot be provided with media such as telegrams.
+.pp
+However, the need for
+.u fast ,
+accurate, and reproducible document distribution is
+obvious.
+One solution in widespread use is the telefax.
+Another
+that is rapidly gaining popularity is electronic mail.
+Electronic mail is similar to telefax in that the data to be sent
+are digitized, transmitted via phone lines, and
+turned back into a document at the receiver.
+The advantage of
+electronic mail is in its compression factor.
+Whereas a telefax
+must scan a page in very fine lines and send all of the black and
+white information, electronic mail assigns characters fixed
+codes which can be transmitted as a few bits of information.
+Telefax presently has the advantage of being able to transmit an
+arbitrary page, including pictures, but electronic mail is
+beginning to deal with this problem.
+Electronic mail also integrates well
+with current directions in office automation, allowing documents
+prepared with sophisticated equipment at one site to be quickly
+transferred and printed at another site.
+.pp
+Currently, most electronic mail is intraorganizational,
+with mail transfer remaining within one computer.
+As computer
+networking becomes more common, however, it is becoming more feasible to
+communicate with anyone whose computer can be linked to your
+own via a network.
+.pp
+The pioneering efforts on general-purpose electronic mail
+were by organizations using the Defense Department's ARPANET.[1]
+The capability to send messages between computers existed before
+the ARPANET was developed, but it was used only in limited ways.
+With the advent of the
+ARPANET, tools began to be developed which made it convenient for
+individuals or organizations to distribute messages
+over broad geographic areas, using
+diverse computer facilities.
+The interest and activity in
+message systems has now reached such proportions that steps
+have been taken within the DoD to coordinate and
+unify the development of military message systems.
+The use of electronic mail is expected to increase
+dramatically in the next few years.
+The utility of such systems
+in the command and control and intelligence environments is
+clear, and applications in these areas will probably lead the
+way.
+As the costs for sending and handling electronic messags
+continue their rapid decrease, such uses can be
+expected to spread rapidly into other areas and, of course, will
+not be limited to the DoD.
+.pp
+A message system provides tools that help users (individuals
+or organizations) deal with messages in various ways.
+Messages
+must be composed, sent, received, stored, retrieved,
+forwarded, and replied to.
+Today's best interactive computer
+systems provide a variety of word-processing and information
+handling capabilities.
+The message handling facilities should be
+well integrated with the rest of the system, so as to be a
+graceful extension of overall system capability.
+.pp
+The message system described in this report, MH, provides most of the
+features that can be found in other message systems and also
+incorporates some new ones.
+It has been built on the UNIX time-sharing
+system,[2] a popular operating system for the DEC PDP-11
+and VAX classes of computers.
+A \*(lqsecure\*(rq operating
+system similar to UNIX is currently being developed,[3]
+and that system will also run MH.
+.pp
+This report provides a complete description of MH and
+thus may serve as a user's manual, although parts of the report
+will be of interest to non-users as well.
+Sections 2 and 3, the
+Overview and Tutorial, present the key
+ideas of MH and will give those not familiar with message systems
+an idea of what such systems are like.
+.pp
+MH consists of a set of commands which use some special
+files and conventions.
+Section 4 covers the information
+a user needs to know in addition to the
+commands.
+The final section, Sec. 5, describes each of
+the MH commands in detail.
+A summary of the commands is given in
+Appendix A, and Appendixes B and C describe the ARPANET
+conventions for messages (we expect that many users of MH
+will be using the ARPANET) and the formal syntax of such
+messages, respectively.
+Finally, Appendix D provides
+an illustration of how MH commands may be used in
+conjunction with other UNIX facilities.
+.pp
+A novel approach has been taken in the design of MH.
+The
+design concept will be reported in detail in a forthcoming Rand
+report, but it can be described briefly as follows.
+Instead of creating a large subsystem that appears as a single
+command to the user, (such as MS[4])
+MH is a collection of separate commands
+which are run as separate programs.
+The file and directory
+system of UNIX are used directly.
+Messages are stored as
+individual files (datasets), and collections of them are grouped
+into directories.
+In contrast, most other message systems store
+messages in a complicated data structure within a monolithic
+file.
+With the MH approach, UNIX commands can be
+interleaved with commands invoking the functions of the message
+handler.
+Conversely, existing UNIX commands
+can be used in connection with messages.
+For
+example, all the usual UNIX editing, text-formatting, and printing
+facilities can be applied directly to individual messages.
+MH,
+therefore, consists of a relatively small amount of new code; it
+makes extensive use of other UNIX software to provide the
+capabilities found in other message systems.
+.+c OVERVIEW
+.pp
+There are three main aspects of MH:  the  way  messages  are
+stored (the message database), the user's profile (which directs
+how certain actions of the message handler take place), and the
+commands for dealing with messages.
+.pp
+Under MH, each message is stored as a separate file.
+A user
+can take any action with a message that he could with an ordinary
+file in UNIX.
+A UNIX directory in which messages are stored is
+called a folder.
+Each folder contains some standard entries to support
+the message-handling functions.
+The messages in a folder have numerical
+names.
+These folders (directories)
+are entries in a particular directory path, described in
+the user profile, through which MH can find message folders.
+Using the UNIX \*(lqlink\*(rq facility, it is possible for one copy of a
+message to be \*(lqfiled\*(rq in more than one folder, providing a
+message index facility.
+Also, using the UNIX tree-structured
+file system, it is possible to have a folder within a folder.
+This two-level organization provides a \*(lqselection-list\*(rq
+facility, with the full power of the MH commands available on
+selected sublists of messages.
+.pp
+Each user of MH has a user profile, a file in his $HOME (initial
+login)
+directory called \*(lq\*.mh\(ruprofile\*(rq.
+This profile contains several
+pieces of information used by the MH commands:  a
+path name to the directory that contains the message folders,
+information concerning which folder the user last referenced (the
+\*(lqcurrent\*(rq folder), and parameters that tailor MH commands
+to the individual user's requirements.
+It also contains
+most of the necessary state information concerning how
+the user is dealing with his messages, enabling MH to be
+implemented as a set of individual UNIX commands, in contrast to the
+usual approach of a monolithic subsystem.
+.pp
+In MH, incoming mail is appended
+to the end of a file called \*.mail in a user's $HOME
+directory.
+The user adds the new messages to his collection of MH messages
+by invoking the command
+.i inc .
+.i Inc
+(incorporate) adds the new
+messages to a folder called \*(lqinbox\*(rq, assigning them names which
+are consecutive integers starting with the next highest integer
+available in inbox.
+.i Inc
+also produces a
+.i scan
+summary of
+the messages thus incorporated.
+.pp
+There are four commands for examining the messages in a
+folder:
+.i show ,
+.i prev ,
+.i next ,
+and
+.i scan .
+.i Show
+displays a
+message in a folder,
+.i prev
+displays the message preceding the
+current message, and
+.i next
+displays the message following the
+current message.
+.i Scan
+summarizes the messages in a folder,
+producing one line per message, showing who the message is from,
+the date, the subject, etc.
+.pp
+The user may move a message from one folder to another with
+the command
+.i file .
+Messages may be removed from a folder
+by means of the command
+.i rmm .
+In addition, a user may query
+what the current folder is and may specify that a new folder
+become the current folder, through the command
+.i folder .
+.pp
+A set of messages based on content may be selected by
+use of the command
+.i pick .
+This command searches through
+messages in a folder and selects those that match a given
+criterion.
+A subfolder is created within the original folder,
+containing links to all the messages that satisfy the selection
+criteria.
+.pp
+A message folder (or subfolder) may be removed by means of
+the command
+.i rmf .
+.pp
+There are five commands enabling the user to create new
+messages and send them:
+.i comp ,
+.i dist ,
+.i forw ,
+.i repl ,
+and
+.i send .
+.i Comp
+provides the facility for the user to compose a
+new message;
+.i dist
+redistributes mail to additional addressees;
+.i forw
+enables the user to forward messages; and
+.i repl
+facilitates the generation of a reply to an incoming message.
+If
+a message is not sent directly by one of these commands, it may
+be sent at a later time using the command
+.i send .
+.pp
+All of the elements summarized above
+are described in more detail in the following sections.
+Many of the
+normal facilities of UNIX provide additional capabilities for
+dealing with messages in various ways.
+For example, it is
+possible to print messages
+on the line-printer without requiring any additional code within
+MH.
+Using standard UNIX facilities, any terminal output can be
+redirected to a file for repeated or future viewing.
+In general,
+the flexibility and capabilities of the UNIX interface with the
+user are preserved as a result of the integration of MH into the UNIX
+structure.
+.+c TUTORIAL
+.pp
+This tutorial provides a brief introduction to the MH commands.
+It should be sufficient
+to allow the user to read his mail, do some simple manipulations of
+it, and create and send messages.
+.pp
+A message has two major pieces:  the
+header and the body.
+The body consists of the text of the message
+(whatever you care to type in).
+It follows the header and is separated from
+it by an empty line.
+(When you compose a message, the form that appears
+on your terminal shows a line of dashes after the header.
+This is for
+convenience and is replaced by an empty line when the message is
+sent.)  The header is composed of several components, including the
+subject of the message and the person to whom it is addressed.
+Each component starts with a name
+and a colon; components must not start with a blank.
+The text of the
+component may take more than one line, but each continuation line must
+start with a blank.
+Messages typically have \*(lqto:\*(rq, \*(lqcc:\*(rq, and
+\*(lqsubject:\*(rq components.
+When composing a message, you should include
+the \*(lqto:\*(rq and \*(lqsubject:\*(rq components; the \*(lqcc:\*(rq (for people
+you want to send copies to) is not necessary.
+.pp
+The basic MH commands are
+.i inc ,
+.i scan ,
+.i show ,
+.i next ,
+.i prev ,
+.i rmm ,
+.i comp ,
+and
+.i repl .
+These are described below.
+
+.i inc
+.pp
+When you get the message \*(lqYou have mail\*(rq, type the command
+.i inc .
+You will get a \*(lqscan listing\*(rq such as:
+
+.nf
+.if t .ta .4i 1.0i 2i
+.if n .ta .4i 1.2i 3i
+^7+~^^\07/13~^^Cas~^revival of measurement work
+^8~^^10/\09~^^Norm~^NBS people and publications
+^9~^^11/26~^^To:norm~^question \*(<<Are there any functions
+.re
+.fi
+.pp
+This shows the messages you received since the last time you
+executed this command (
+.i inc
+adds these new messages to
+your inbox folder).
+You can see this list again, plus a list of any
+other messages you have, by using the
+.i scan
+command.
+
+.i scan
+.pp
+The scan listing shows the message number, followed by the
+date and the sender.
+(If you are the sender, the addressee in the \*(lqto:\*(rq
+component is displayed.
+You may send yourself a message by including
+your name among the \*(lqto:\*(rq or \*(lqcc:\*(rq addressees.)
+It also shows the message's subject; if
+the subject is short, the first part of the body of the message is
+included after the characters \*(<<.
+
+.ne 5
+.i show
+.pp
+This command shows the current message, that is,
+the first one of the new messages after an
+.i inc .
+If the message is not
+specified by name (number), it is
+generally the last message referred to by an MH command.
+For example,
+
+.ta 1i
+.ti .5i
+^\fIshow\fP\05~^will show message 5.
+.pp
+You can use the show command to copy a message or print a
+message.
+
+.(b L
+.in .5i
+.if t .ta 1i
+.if n .ta 1.5i
+^\fIshow\fR\0>\0\fIx\fR~^will copy the message to file x.
+.br
+^\fIshow\fR\0|\0\fIprint\fR~^will print the message, using the \fIprint\fR command.
+.br
+^\fInext\fR~^will show the message that follows the current message.
+.br
+^\fIprev\fR~^will show the message previous to the current message.
+.br
+^\fIrmm\fR~^will remove the current message.
+.br
+^\fIrmm\03\fR~^will remove message 3.
+.)b
+
+.ne 5
+.i comp
+.pp
+The
+.i comp
+command puts you in the editor to write or edit a message.
+Fill in or
+delete the \*(lqto:\*(rq, \*(lqcc:\*(rq, and \*(lqsubject:\*(rq fields, as appropriate, and
+type the body of the message.
+Then
+exit normally from the editor.
+You will be asked
+\*(lqWhat now?\*(rq.
+Type a carriage return to see the options.
+Typing \fBsend\fR
+will cause the message to be sent; typing \fBquit\fR will cause an exit
+from
+.i comp ,
+with the message draft saved.
+.pp
+If you quit without sending the message, it will be saved in a file
+called /usr/<name>/Mail/draft (where /usr/<name> is your $HOME directory).
+You can edit this file and send the message later, using the
+.i send
+command.
+
+.ne 4
+.i "comp\0\-editor\0prompter"
+.pp
+This command uses a different editor and is useful for preparing
+\*(lqquick and dirty\*(rq messages.
+It prompts you for each component of the
+header.
+Type the information for that component, or type a carriage
+return to omit the component.
+After that, type the body of the
+message.
+Backspacing is the only form of editing allowed with this editor.
+When the body is complete, type a carriage return followed by <CTRL-D>
+(<OPEN> on Ann Arbor terminals).
+This completes the initial preparation of the message; from then on, use
+the same procedures as with
+.i comp
+(above).
+
+.ne 5
+.i repl
+.br
+.i "repl\0n"
+.pp
+This command makes up an initial message form with a header
+that is appropriate for
+replying to an existing message.
+The message being answered is the
+current message if no message number is mentioned, or n if a number
+is specified.
+After the header is completed, you can finish the message as in
+.i comp
+(above).
+.pp
+This is enough information to get you going using MH.
+There are more commands,
+and the commands described here have more features.
+Subsequent sections
+explain MH in complete detail.
+The system is quite powerful if you
+want to use its sophisticated features, but the foregoing commands
+suffice for sending and receiving messages.
+.pp
+There are numerous additional capabilities you may wish to explore.
+For example, the
+.i pick
+command will select a subset of messages
+based on specified criteria such as sender or subject.
+Groups of
+messages may be designated, as described in Sec. V, under \*(lqMessage
+Naming\*(rq.
+The file \*(lq\*.mh\(ruprofile\*(rq can be used to tailor your use of
+the message system to your needs and preferences, as described in Sec. V,
+under \*(lqThe User Profile\*(rq.
+In general, you may
+learn additional features of the system selectively, according to your
+requirements,
+by studying the relevant sections of this manual.
+There is no need to
+learn all the details of the system at once.
+.+c "DETAILED DESCRIPTION"
+.pp
+This section describes the MH system in detail, including the components
+of the user profile, the conventions for message naming, and some of
+the other MH conventions.
+Readers who are
+generally familiar with computer systems will be able to follow
+the principal ideas, although some details may be meaningful only to
+those familiar with UNIX.
+.uh "THE USER PROFILE"
+.pp
+The first time an MH command is issued by a new user, the system
+prompts for a \*(lqpath\*(rq and creates an MH \*(lqprofile\*(rq.
+.pp
+Each MH user has a profile which contains current
+state information for the MH package and, optionally, tailoring
+information for each individual program.
+When a folder becomes
+the current folder, it is recorded in the user's profile.
+Other profile entries control the MH path (where folders and
+special files are kept), folder and message protections, editor
+selection, and default arguments for each MH program.
+.pp
+The MH profile is stored in the file \*(lq\*.mh\(ruprofile\*(rq in the
+user's $HOME directory.
+It has the format of a message without
+any body.
+That is, each profile entry is on one line, with a
+keyword followed by a colon (:) followed by text particular to
+the keyword.
+.br
+\(rh\ \ \&
+.i "This file must not have blank lines."
+.br
+The keywords
+may have any combination of upper and lower case.
+(See Appendix
+B for a description of message formats.)
+.pp
+For the average MH user, the only profile entry of
+importance is \*(lqPath\*(rq.
+Path specifies a directory in which MH
+folders and certain files such as \*(lqdraft\*(rq are found.
+The
+argument to this keyword must be a legal UNIX path that names an
+existing directory.
+If this path is unrooted (i.e., does not
+begin with a \fB/\fR), it will be presumed to start from the
+user's $HOME directory.
+All folder and message references within
+MH will relate to this path unless full path names are used.
+.pp
+Message protection defaults to 664, and folder protection to
+751.
+These may be changed by profile entries \*(lqMsg-Protect\*(rq
+and \*(lqFolder-Protect\*(rq, respectively.
+The argument to these
+keywords is an octal number which is used as the UNIX file mode.\**
+.(f
+\**See
+.i chmod (I)
+in the
+.i "UNIX Programmer's Manual" .[5]
+.)f
+.pp
+When an MH program starts running, it looks through the
+user's profile for an entry with a keyword matching the program's
+name.
+For example, when
+.i comp
+is run, it looks for a \*(lqcomp\*(rq
+profile entry.
+If one is found, the text of the profile entry is
+used as the default switch setting until all defaults are overridden
+by explicit switches passed to the program as arguments.
+Thus the profile
+entry \*(lqcomp:\0\-form\0standard.list\*(rq would direct
+.i comp
+to use the
+file \*(lqstandard.list\*(rq as the message skeleton.
+If an explicit
+form switch is given to the
+.i comp
+command, it will override the
+switch obtained from the profile.
+.pp
+In UNIX, a program may exist under several names, either by
+linking or aliasing.
+The actual invocation name is used by an MH
+program when scanning for its profile defaults.
+Thus, each MH program
+may have several names by which it can be invoked, and each name
+may have a different set of default switches.
+For example, if
+.i comp
+is invoked by the name
+.i icomp ,
+the profile entry
+\*(lqicomp\*(rq will control the default switches for this invocation of
+the
+.i comp
+program.
+This provides a powerful
+definitional facility for commonly used switch settings.
+.pp
+The default editor
+for editing within
+.i comp ,
+.i repl ,
+.i forw ,
+and
+.i dist ,
+is \*(lq/bin/ned\*(rq.\**
+.(f
+\**See Ref. 6 for a description of
+the NED text editor.
+.)f
+A different editor may be used by specifying
+the profile entry
+\*(lqEditor: \*(rq.
+The argument to \*(lqEditor\*(rq is the name of an
+executable program or shell command file which can be found via
+the user's $PATH defined search path, excluding the current
+directory.
+The \*(lqEditor:\*(rq profile specification
+may in turn be overridden by a \*(lq\-editor\0<editor>\*(rq
+profile switch associated with
+.i comp ,
+.i repl ,
+.i forw ,
+or
+.i dist .
+Finally, an explicit editor switch specified with any
+of these four commands will have ultimate precedence.
+.pp
+During message composition, more than one editor may be
+used.
+For example, one editor (such as
+.i prompter )
+may be used
+initially, and a second editor may be invoked later to revise
+the message being composed
+(see the discussion of
+.i comp
+in Section 5 for details).
+A profile entry \*(lq<lasteditor>\-next:\0<editor>\*(rq specifies the name of
+the editor to be used after a particular editor.
+Thus \*(lqcomp:\0\-e\0prompter\*(rq
+causes the initial text to be collected by
+.i prompter ,
+and the profile entry \*(lqprompter\-next:\0ed\*(rq names ed as the
+editor to be invoked for the next round of editing.
+.pp
+Some of the MH commands, such as
+.i show ,
+can be used on
+message folders owned by others, if those folders are readable.
+However,
+you cannot write in someone else's folder.
+All the MH command
+actions not requiring write permission may be used with
+a \*(lqread-only\*(rq folder.
+In a writable folder, a file named
+\*(lqcur\*(rq is used to contain its current message name.
+For read-only folders, the current message name is
+stored in the user's profile.
+.pp
+Table 1 lists examples of the currently defined profile
+entries, typical arguments, and the programs that reference the
+entries.
+.in .9i
+.ll -.9i
+.ta 2.3i
+.sp 30p
+.ce
+Table 1
+.sp 8p
+.ce
+P\s-2ROFILE\s0 C\s-2OMPONENTS\s0
+.hl             \" ~12p preceding + 1v (12p) after
+.nf
+^^MH Programs that
+^Keyword and Argument~^\ Use Component\h'|\n(.lu-.9i'\v'4p'\l'|0'\v'-4p'  \" \l'..' does underlining
+.sp
+^Path:\0Mail~^All
+^Current-Folder:\0inbox~^Most
+^Editor:\0/bin/ed~^\fIcomp, dist, forw, repl\fR
+^Msg\-Protect:\0644~^\fIinc\fR
+^Folder\-Protect:\0711~^\fIfile, inc, pick\fR
+^<program>:\0default switches~^All
+^cur\-<read-onlyfolder>:\0172~^Most
+^prompter\-next:\0ed~^\fIcomp, dist, forw, repl\fR
+.hl
+.ll +.9i
+.in 0
+.fi
+.pp
+Path
+.u should
+be present.
+Folder is maintained
+automatically by many MH commands (see the \*(lqContext\*(rq sections of
+the individual commands in Sec. V).
+All other entries are optional,
+defaulting to the values described above.
+.uh "MESSAGE NAMING"
+.pp
+Messages may be referred to explicitly or implicitly when
+using MH commands.
+A formal syntax of message names is given in Appendix C, but the
+following description should be sufficient for most MH users.
+Some details of message naming that apply only to certain
+commands are included in the description of those
+commands.
+.pp
+Most of the MH commands accept arguments specifying one or
+more folders, and one or more messages to operate on.
+The use of
+the word \*(lqmsg\*(rq as an argument to a command means that exactly one
+message name may be specified.
+A message name may be a number,
+such as 1, 33, or 234, or it may be
+one of the \*(lqreserved\*(rq message names:
+first, last, prev, next, and cur.
+(As a shorthand, a
+period (\*.) is equivalent to cur.)
+The meanings of these names
+are straightforward:  \*(lqfirst\*(rq is the first message in the
+folder; \*(lqlast\*(rq is the last
+message in the folder; \*(lqprev\*(rq is the
+message numerically previous to the current message; \*(lqnext\*(rq
+is the message numerically following the current message; \*(lqcur\*(rq
+(or \*(lq\*.\*(rq) is the current message in the folder.
+.pp
+The default in commands that take a \*(lqmsg\*(rq argument is
+always \*(lqcur\*(rq.
+.pp
+The word \*(lqmsgs\*(rq indicates that several messages may be
+specified.
+Such a specification consists of several message
+designations separated by spaces.
+A message designation is
+either a message name or a message range.
+A message range is a
+specification of the form name1\-name2 or name1:n, where name1 and
+name2 are message names and n is an integer.
+The first form
+designates all the messages from name1 to name2 inclusive; this
+must be a non-empty range.
+The second form specifies up to n
+messages, starting with name1 if name1 is a number, or first,
+cur, or next, and ending with name1 if name1 is last or
+prev.
+This interpretation of n is overridden if n is preceded
+by a plus sign or a minus sign;
++n always means up to n messages starting with
+name1, and \-n always means up to n messages ending with name1.
+Repeated specifications of the same message have the same effect
+as a single specification of
+the message.
+Examples of
+specifications are:
+
+.(b
+1 5 7\-11 22
+first 6 8 next
+first\-10
+last:5
+.)b
+.pp
+The message name \*(lqall\*(rq is a shorthand for \*(lqfirst\-last\*(rq,
+indicating all of the messages in the folder.
+.pp
+The limit on the number of messages in an expanded message
+list is generally 999\*-the maximum number of messages in a
+folder.
+However, the
+.i show
+command and the
+commands `\fIpick\0\-scan\fR' and `\fIpick\0\-show\fR'
+are constrained to have argument lists
+that are no more than 512 characters long.
+(Under Version 7 UNIX this limit is 4096.)
+.pp
+In commands that accept \*(lqmsgs\*(rq arguments, the default is
+either cur or all, depending on which makes more sense.
+.pp
+In all of the MH commands, a plus sign preceding an argument
+indicates a folder name.
+Thus, \*(lq+inbox\*(rq is the name of the
+user's standard inbox.
+If an explicit folder argument is given
+to an MH command, it will become the current folder (that is,
+the \*(lqCurrent-Folder:\*(rq entry
+in \*(lq\*.mh\(ruprofile\*(rq will be changed to this
+folder).
+In the case of the
+.i file
+and
+.i pick
+commands, which
+can have multiple output folders, a new source folder (other than
+the default current folder) is specified by \*(lq\-src\0+folder\*(rq.
+.uh "OTHER MH CONVENTIONS"
+.pp
+One very powerful feature of MH is that the MH commands may
+be issued from any current directory, and the proper path to
+the appropriate folder(s) will be taken from the user's profile.
+If the MH path is not appropriate for a specific folder or file,
+the automatic prepending of the MH path can be avoided by
+beginning a folder or file name with \fB/\fR.
+Thus any specific full
+path may be specified.
+.pp
+Arguments to the various programs may be given in any order,
+with the exception of a few switches whose arguments must follow
+immediately, such as \*(lq\-src\0+folder\*(rq for \fIpick\fR and \fIfile\fR.
+.pp
+Whenever an MH command prompts the user, the valid options
+will be listed in response to a <RETURN>.
+(The first of the
+listed options is the default if end-of-file is encountered, such
+as from a command file.)  A valid response is any \fIunique\fR
+abbreviation of one of the listed options.
+.pp
+Standard UNIX documentation conventions are used in this report
+to describe MH command syntax.
+Arguments enclosed in brackets
+([ ]) are optional; exactly one of the arguments enclosed
+within braces ({ }) must be specified, and all other
+arguments are required.
+The use of ellipsis dots (...) indicates
+zero or more repetitions of the previous item.
+For example,
+\*(lq+folder ...\*(rq would indicate that one or more \*(lq+folder\*(rq arguments
+is required and \*(lq[+folder ...]\*(rq indicates that 0 or more
+\*(lq+folder\*(rq arguments may be given.
+.pp
+MH departs from UNIX standards by using switches that consist of
+more than one character, e.g. \*(lq\-header\*(rq.
+To minimize typing,
+only a unique abbreviation of a switch need be typed; thus, for
+\*(lq\-header\*(rq, \*(lq\-hea\*(rq is probably sufficient, depending on the
+other switches the command accepts.
+Each MH program
+accepts the switch \*(lq\-help\*(rq (which \fImust\fR be spelled out fully)
+and produces a syntax description and a list of switches.
+In the
+list of switches, parentheses indicate required characters.
+For example, all \*(lq\-help\*(rq switches will appear as \*(lq\-(help)\*(rq,
+indicating that no abbreviation is accepted.
+.pp
+Many MH switches have both on and off forms, such as
+\*(lq\-format\*(rq and \*(lq\-noformat\*(rq.
+In many of the descriptions in Sec. V,
+only one form is defined; the other form, often used to
+nullify profile switch settings, is assumed to be the opposite.
+.br
+.bp
+.uh "MH COMMANDS"
+.pp
+The MH package comprises 16 programs:
+
+.nf
+.in .5i
+.ta 1.5i
+^comp~^Compose a message
+^dist~^Redistribute a message
+^file~^Move messages between folders
+^folder~^Select/list status of folders
+^forw~^Forward a message
+^inc~^Incorporate new mail
+^next~^Show the next message
+^pick~^Select a set of messages by context
+^prev~^Show the previous message
+^prompter~^Prompting editor front end for composing messages
+^repl~^Reply to a message
+^rmf~^Remove a folder
+^rmm~^Remove messages
+^scan~^Produce a scan listing of selected messages
+^send~^Send a previously composed message
+^show~^Show messages
+.fi
+.re
+.pp
+These programs are described below.
+The form of the descriptions
+conforms to the standard
+form for the description of UNIX commands.
+.if t \{
+.ll 6.5i
+.lt 6.5i
+\}
+.fo '7th Edition'UNIX/32V(Rand)''
+.de SC
+.he '\\$1(1)'-%-'\\$1(1)'
+.bp
+.(x
+.ti .8i
+\\$1
+.)x
+..
+.de NA
+.b \\s-2NAME\\s0
+.ti .5i
+..
+.de SY
+.sp
+.b \\s-2SYNOPSIS\\s0
+.in 1i
+.ti .5i
+.na
+..
+.de DE
+.ad
+.sp
+.in 0
+.b  \\s-2DESCRIPTION\\s0
+.sp
+.fi
+.in .5i
+..
+.de Fi
+.(b L
+.ti 0
+.b \\s-2Files\\s0
+.ta 2i
+..
+.de Pr
+.)b
+.(b L F
+.in 2.5i
+.ti 0
+.b "\\s-2Profile Components\\s0"
+.ti .5i
+..
+.de Ps
+.ti .5i
+..
+.de De
+.)b
+.(b L
+.in .5i
+.ti 0
+.b \\s-2Defaults\\s0
+..
+.de Co
+.)b
+.(b L F
+.ti 0
+.b \\s-2Context\\s0
+.br
+..
+.de En
+.)b
+.in 0
+..
+.SC COMP
+.NA
+comp \- compose a message
+
+.SY
+comp \%[\-editor\ editor] \%[\-form\ formfile] \%[file] \%[\-use]
+\%[\-nouse] \%[\-help]
+
+.DE
+\fIComp\fP is used to create a new message to be mailed.
+If
+\fIfile\fP is not specified, the file named \*(lqdraft\*(rq in the user's MH
+directory will be used.
+\fIComp\fR copies a message form to
+the file being composed and then invokes an editor on the
+file.
+The default editor is /bin/ned, which may be overridden with
+the `\-editor' switch or with a profile entry \*(lqEditor:\*(rq.
+(See Ref. 5 for a
+description of the NED text editing system.)
+The default
+message form contains the following elements:
+
+     To:
+     cc:
+     Subject:
+     ----------
+
+If the file named \*(lqcomponents\*(rq exists in the user's MH directory,
+it will be used instead of this form.
+If `\-form
+formfile' is specified, the specified formfile (from the MH
+directory) will be used as the skeleton.
+The line of dashes
+or a blank line must be left between the header and the
+body of the message for the message to be identified properly when it is
+sent (see \fIsend;\fR).
+The switch `\-use' directs \fIcomp\fR to
+continue editing an already started message.
+That is, if a
+\fIcomp\fR (or \fIdist\fR, \fIrepl\fR, or \fIforw\fR) is terminated without
+sending the message, the message can be edited again via
+\*(lqcomp \-use\*(rq.
+
+If the specified file (or draft) already exists, \fIcomp\fR will ask
+if you want to delete it before continuing.
+A reply of \fBNo\fR will abort the
+\fIcomp\fR, \fByes\fR will replace the existing draft with a blank
+skeleton, \fBlist\fR will display the draft, and \fBuse\fR will use it
+for further composition.
+
+Upon exiting from the editor, \fIcomp\fR will ask \*(lqWhat now?\*(rq.
+The valid
+responses are \fBlist\fR, to list the draft on the terminal; \fBquit\fR, to
+terminate the session and preserve the draft; \fBquit delete\fR, to terminate,
+then delete the draft; \fBsend\fR, to send the message; \fBsend verbose\fR, to
+cause the delivery process to be monitored; \fBedit <editor>\fR, to invoke
+<editor> for further editing; and \fBedit\fR, to re-edit using the
+same editor that was used on the preceding round unless a profile
+entry \*(lq<lasteditor>\-next: <editor>\*(rq names an alternative editor.
+
+.Fi
+^/etc/mh/components~^The message skeleton
+^or <mh-dir>/components~^Rather than the standard skeleton
+^$HOME/\*.mh\(ruprofile~^The user profile
+^<mh-dir>/draft~^The default message file
+^/usr/bin/send~^To send the composed message
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Editor:~^To override the use of /bin/ned as the default editor
+.Ps
+^<lasteditor>\-next:~^To name an editor to be used after exit from <lasteditor>
+.De
+`file' defaults to draft
+`\-editor' defaults to /bin/ned
+`\-nouse'
+.Co
+\fIComp\fR does not affect either the current folder or the current message.
+.En
+.SC DIST
+.NA
+dist \- redistribute a message to additional addresses
+.SY
+dist \%[+folder] \%[msg] \%[\-form\ formfile] \%[\-editor\ editor]
+\%[\-annotate] \%[\-noannotate]
+\%[\-inplace] \%[\-noinplace]
+\%[\-help]
+.DE
+\fIDist\fR is similar to \fIforw\fR.
+It prepares the specified
+message for redistribution to addresses that (presumably) are
+not on the original address list.
+The file \*(lqdistcomps\*(rq in the
+user's MH directory, or a standard form, or the file specified by
+`\-form formfile' will be used as the blank components file to
+be prepended to the message being distributed.
+The standard form
+has the components \*(lqDistribute-to:\*(rq and \*(lqDistribute-cc:\*(rq.
+When
+the message is sent, \*(lqDistribution-Date:\0date\*(rq,
+\*(lqDistribution-From:\0name\*(rq, and
+\*(lqDistribution-Id:\0id\*(rq (if `\-msgid' is
+specified to \fIsend\fR;) will be prepended to the outgoing message.
+Only those addresses in \*(lqDistribute-To\*(rq, \*(lqDistribute-cc\*(rq, and
+\*(lqDistribute-Bcc\*(rq will be sent.
+Also, a \*(lqDistribute-Fcc:\0folder\*(rq
+will be honored (see \fIsend;\fR).
+
+\fISend\fR recognizes a message as a redistribution message by the
+existence of the field \*(lqDistribute-To:\*(rq, so don't try to
+redistribute a message with only a \*(lqDistribute-cc:\*(rq.
+
+If the `\-annotate' switch is given, each message being
+distributed will be annotated with the lines:
+
+     Distributed:\0\*(<<date\*(>>
+     Distributed:\0Distribute-to: names
+
+where each \*(lqto\*(rq list contains as many lines as required.
+This annotation
+will be done only if the message is sent directly from \fIdist\fR.
+If the
+message is not sent immediately from \fIdist\fR (i.e., if it is sent later
+via \fIsend;\fR),
+\*(lqcomp \-use\*(rq may be used to re-edit and send the constructed message, but
+the annotations won't take place.
+The '\-inplace' switch causes annotation to
+be done in place in order to preserve links to the annotated message.
+
+See \fIcomp\fR for a description of the `\-editor' switch and for options
+upon exiting from the editor.
+
+.Fi
+^/etc/mh/components~^The message skeleton
+^or <mh-dir>/components~^Rather than the standard skeleton
+^$HOME/\*.mh\(ruprofile~^The user profile
+^<mh-dir>/draft~^The default message file
+^/usr/bin/send~^To send the composed message
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Editor:~^To override the use of /bin/ned as the default editor
+.Ps
+^<lasteditor>\-next:~^To name an editor to be used after exit from <lasteditor>
+.De
+`+folder' defaults to the current folder
+`msg' defaults to cur
+`\-editor' defaults to /bin/ned
+`\-noannotate'
+`\-noinplace'
+.Co
+If a +folder is specified, it will become the current
+folder, and the current message will be set to the message
+being redistributed.
+.En
+.SC FILE
+.NA
+file \- file message(s) in (an)other folder(s)
+.SY
+file \%[\-src\ +folder] \%[msgs] \%[\-link] \%[\-preserve] \%+folder\ ...
+\%[\-nolink] \%[\-nopreserve]
+\%[\-file\ file] \%[\-nofile] \%[\-help]
+.DE
+\fIFile\fR moves (\fImv\fR(I)) or links (\fIln\fR(I)) messages from a
+source folder into one or more destination folders.
+If you think
+of a message as a sheet of paper, this operation is not
+unlike filing the sheet of paper (or copies) in file cabinet
+folders.
+When a message is filed, it is linked into the
+destination folder(s) if possible, and is copied otherwise.
+As long
+as the destination folders are all on the same file system, multiple filing
+causes little storage overhead.
+This facility provides a good way to cross-file or multiply-index
+messages.
+For example, if a message is received from Jones about
+the ARPA Map Project, the command
+
+     file\0cur\0+jones\0+Map
+
+would allow the message to be found in either of the two
+folders `jones' or `Map'.
+
+The option `\-file file' directs \fIfile\fR to use the specified
+file as the source message to be filed, rather than a message from
+a folder.
+
+If a destination folder doesn't exist, \fIfile\fR will ask if you
+want to create one.
+A negative response will abort the file
+operation.
+
+`\-link' preserves the source folder copy of the message
+(i.e., it does a \fIln\fR(I) rather than a \fImv\fR(I)), whereas,
+`\-nolink' deletes the \*(lqfiled\*(rq messages from the source
+folder.
+Normally, when a message is filed, it is assigned the
+next highest number available in each of the destination folders.
+Use of the `\-preserve' switch will override this message
+\*(lqrenaming\*(rq, but name conflicts may occur, so
+use this switch cautiously.
+(See \fIpick\fR for more details on
+message numbering.)
+
+If `\-link' is not specified (or `\-nolink' is specified),
+the filed messages will be removed (unlink(II)) from the
+source folder.
+
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Current-Folder:~^To find the default current folder
+.Ps
+^Folder\-Protect:~^To set mode when creating a new folder
+.De
+`\-src +folder' defaults to the current folder
+`msgs' defaults to cur
+`\-nolink'
+`\-nopreserve'
+`\-nofile'
+.Co
+If `\-src +folder' is given, it will become the
+current folder for future MH commands.
+If neither `\-link' nor
+`all' are specified, the current message in the source
+folder will be set to the last message specified; otherwise, the
+current message won't be changed.
+.En
+.SC FOLDER
+.NA
+folder \- set/list current folder/message
+.SY
+folder \%[+folder] \%[msg] \%[\-all] \%[\-fast] \%[\-nofast] \%[\-up] \%[\-down]
+\%[\-header] \%[\-noheader] \%[\-total] \%[\-nototal] \%[\-pack] \%[\-nopack]
+\%[\-help]
+
+.ti .5i
+folders  <equivalent to 'folder \-all'>
+.DE
+Since the MH environment is the shell, it is easy to lose
+track of the current folder from day to day.
+\fIFolder\fR will
+list the current folder, the number of messages in it, the
+range of the messages (low-high), and the current message within
+the folder, and will flag a selection list or extra files if they
+exist.
+An example of the output is:
+
+      inbox+ has 16 messages ( 3\- 22); cur= 5.
+
+If a `+folder' and/or `msg' are specified, they will
+become the current folder and/or message.
+An `\-all' switch
+will produce a line for each folder in the user's MH directory,
+sorted alphabetically.
+These folders are preceded by the read-only
+folders, which occur as \*.mh\(ruprofile \*(lqcur\-\*(rq entries.
+For example,
+
+.nf
+.ta 1.5i 2.1i 2.7i 3.5i
+^~Folder\ \ ^^~#\ of\ ^^messages~^^(~\ range\~ );\ ^cur msg (other files)
+^~/fsd/rs/m/tacc\ \ ^^has~35\ ^^messages~^^(~1\-\035);\ ^cur=\ 23.
+^~/rnd/phyl/Mail/EP\ \ ^^has~82\ ^^messages~^^(~1\-108);\ ^cur=\ 82.
+^~f\&f\ \ ^^has~4\ ^^messages~^^(~1\-\0\04);\ ^cur=\ \01.
+^~inbox+\ ^^has~16\ ^^messages~^^(~3\-\022);\ ^cur=\ \05.
+^~mh\ \ ^^has~76\ ^^messages~^^(~1\-\076);\ ^cur=\ 70.
+^~notes\ \ ^^has~2\ ^^messages~^^(~1\-\0\02);\ ^cur=\ \01.
+^~ucom\ \ ^^has~124\ ^^messages~^^(~1\-124);\ ^cur=\ \06; (select).
+
+^^^~TOTAL=\0339\ ^messages\0in\0\07\0Folders.
+.re
+.fi
+
+The \*(lq+\*(rq after inbox indicates that it is the current folder.
+The \*(lq(select)\*(rq indicates that the folder ucom has a selection
+list produced by \fIpick\fR.
+If \*(lqothers\*(rq had appeared in parentheses at
+the right of a line, it would indicate that there are files in
+the folder directory that don't belong under the MH file naming
+scheme.
+
+The header is output if either an `\-all' or a `\-header' switch
+is specified; it is suppressed by `\-noheader'.
+Also, if \fIfolder\fR
+is invoked by a name ending with \*(lqs\*(rq (e.g., \fIfolders\fR),
+`\-all' is assumed.
+A `\-total' switch will produce only the
+summary line.
+
+If `\-fast' is given, only the folder name (or names in the
+case of `\-all') will be listed.
+(This is faster because the
+folders need not be read.)
+
+The switches `\-up' and `\-down' change the folder to be the
+one above or below the current folder.
+That is, \*(lqfolder \-down\*(rq
+will set the folder to \*(lq<current\-folder>/select\*(rq, and if the
+current folder is a selection-list folder, \*(lqfolder \-up\*(rq will
+set the current folder to the parent of the selection-list.
+(See \fIpick\fR for details on selection-lists.)
+
+The `\-pack' switch will compress the message names in a folder, removing
+holes in message numbering.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+^/bin/ls~^To fast-list the folders
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+`+folder' defaults to the current folder
+`msg' defaults to none
+`\-nofast'
+`\-noheader'
+`\-nototal'
+`\-nopack'
+.Co
+If `+folder' and/or `msg' are given, they will become the
+current folder and/or message.
+.En
+.SC FORW
+.NA
+forw \- forward messages
+.SY
+forw \%[+folder] \%[msgs] \%[\-editor\ editor] \%[\-form\ formfile]
+\%[\-annotate] \%[\-noannotate]
+\%[\-inplace]  \%[\-noinplace]
+\%[\-help]
+.DE
+\fIForw\fR may be used to prepare a message containing other
+messages.
+It constructs the new message from the components file
+or `\-form formfile' (see \fIcomp\fR), with a body composed of the
+message(s) to be forwarded.
+An editor is invoked as in \fIcomp\fR,
+and after editing is complete, the user is prompted before the message
+is sent.
+
+If the `\-annotate' switch is given, each message being
+forwarded will be annotated with the lines
+
+     Forwarded: \*(<<date\*(>>
+     Forwarded: To: names
+     Forwarded: cc: names
+
+where each \*(lqTo:\*(rq and \*(lqcc:\*(rq list contains as many lines as required.
+This annotation will be done only if the message is sent directly
+from \fIforw\fR.
+If the message is not sent immediately from \fIforw\fR,
+\*(lqcomp \-use\*(rq may be used in a later session to re-edit and send
+the constructed message, but the annotations won't take place.
+The `\-inplace' switch permits annotating a message in place in
+order to preserve its links.
+
+See \fIcomp\fR for a description of the `\-editor' switch.
+.Fi
+^/etc/mh/components~^The message skeleton
+^or <mh-dir>/components~^Rather than the standard skeleton
+^$HOME/\*.mh\(ruprofile~^The user profile
+^<mh-dir>/draft~^The default message file
+^/usr/bin/send~^To send the composed message
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Editor:~^To override the use of /bin/ned as the default editor
+.Ps
+^Current-Folder:~^To find the default current folder
+.Ps
+^<lasteditor>\-next:~^To name an editor to be used after exit from <lasteditor>
+.De
+`+folder' defaults to the current folder
+`msgs' defaults to cur
+`\-editor' defaults to /bin/ned
+`\-noannotate'
+`\-noinplace'
+.Co
+If a +folder is specified, it will become
+the current folder, and the current message will be set to
+the first message being forwarded.
+.En
+.SC INC
+.NA
+inc \- incorporate new mail
+.SY
+inc \%[+folder] \%[\-audit\ audit-file] \%[\-help]
+.DE
+\fIInc\fR incorporates mail from the user's incoming mail drop
+(\*.mail) into an MH folder.
+If `+folder' isn't specified,
+the folder named \*(lqinbox\*(rq in the user's MH directory will be used.
+The
+new messages being incorporated are assigned numbers starting
+with the next highest number in the folder.
+If the specified (or
+default) folder doesn't exist, the user will be queried prior to
+its creation.
+As the messages are processed, a \fIscan\fR  listing
+of the new mail is produced.
+
+If the user's profile contains a \*(lqMsg\-Protect: nnn\*(rq entry, it
+will be used as the protection on the newly created messages,
+otherwise the MH default of 664 will be used.
+During all
+operations on messages, this initially assigned protection will
+be preserved for each message, so \fIchmod\fR(I) may be used to set a
+protection on an individual message, and its protection will be
+preserved thereafter.
+
+If the switch `\-audit audit-file' is specified (usually as a
+default switch in the profile), then \fIinc\fR will append a header
+line and a line per message to the end of the specified
+audit-file with the format:
+
+.nf
+.ti 1i
+\*(<<inc\*(>> date
+.ti 1.5i
+<scan line for first message>
+.ti 1.5i
+<scan line for second message>
+.ti 2.5i
+<etc.>
+.fi
+
+This is useful for keeping track of volume and source of incoming
+mail.
+Eventually, \fIrepl\fR, \fIforw\fR, \fIcomp\fR, and \fIdist\fR may also
+produce audits to this (or another) file, perhaps with
+\*(lqMessage-Id:\*(rq information to keep an exact correspondence history.
+\*(lqAudit-file\*(rq will be in the user's MH directory unless a full
+path is specified.
+
+\fIInc\fR will incorporate even illegally formatted messages into the
+user's MH folder, inserting a blank line prior to the offending
+component and printing a comment identifying the bad message.
+
+In all cases, the \*.mail file will be zeroed.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+^$HOME/\*.mail~^The user's mail drop
+^<mh-dir>/audit-file~^Audit trace file (optional)
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Folder\-Protect:~^For protection on new folders
+.Ps
+^Msg\-Protect:~^For protection on new messages
+.De
+`+folder' defaults to \*(lqinbox\*(rq
+.Co
+The folder into which the message is
+being incorporated will become the
+current folder, and the first message incorporated will be the
+current message.
+This leaves the context ready for a \fIshow\fR
+of the first new message.
+.En
+.SC NEXT
+.NA
+next \- show the next message
+.SY
+next \%[+folder] \%[\-switches\ for\ \fIl\fR] \%[\-help]
+.DE
+\fINext\fR performs a \fIshow\fR on the next message in the
+specified (or current) folder.
+Like \fIshow\fR, it passes any
+switches on to the program \fIl\fR, which is called to list the
+message.
+This command is exactly equivalent to \*(lqshow next\*(rq.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+.Co
+If a folder is specified, it will become the current folder, and the
+message that is shown (i.e., the next message in sequence)
+will become the current message.
+.En
+.SC PICK
+.NA
+pick \- select messages by content
+.SY
+.ta .4i 1.8i
+.nf
+.in .5i
+^pick~^^\0\-cc~^ \%[\-src\ +folder] \%[msgs] \%[\-help] \%[\-scan] \%[\-noscan]
+^^^\0\-date~^   \%[\-show] \%[\-noshow] \%[\-nofile] \%[\-nokeep]
+^^^\0\-from~^
+^^^\s+2\b'\(lt\(bv\(bv\(lk\(bv\(bv\(lb'\s0 \-search~\s+2\b'\(rt\(bv\(bv\(rk\(bv\(bv\(rb'\s0^ pattern
+^^^\0\-subject~^
+^^^\0\-to~^ \%[\-file \%[\-preserve] \%[\-link] \%+folder\ ... \%[\-nopreserve] \%[\-nolink] ]
+^^^\0\-\-component~^ \%[\-keep \%[\-stay] \%[\-nostay] \%[+folder\ ...]\ ]
+.fi
+
+.re
+.ti .5i
+typically:
+.in 1i
+pick\0\-from\0jones\0\-scan
+.br
+pick\0\-to\0holloway
+.br
+pick\0\-subject\0ned\0\-scan\0\-keep
+.DE
+\fIPick\fR searches messages within a folder for the specified
+contents, then performs several operations on the selected
+messages.
+
+A modified \fIgrep\fR(I) is used to perform the searching, so the
+full regular expression (see \fIed\fR(I)) facility is available
+within `pattern'.
+With `\-search', pattern is used directly,
+and with the others, the grep pattern constructed is:
+
+.ti +.5i
+\*(lq^component:\*.\*(**pattern\*(rq
+
+This means that the pattern specified for a `\-search' will be
+found everywhere in the message, including the header and the body,
+while the other search requests are limited to the single
+specified component.
+The expression `\-\-component pattern'
+is a shorthand for
+specifying `\-search \*(lqcomponent:\*.\*(**pattern\*(rq\ '; it is used to pick
+a component not in the set [cc date from subject to].
+An
+example is \*(lqpick \-\-reply\-to pooh \-show\*(rq.
+
+Searching is performed on a per-line basis.
+Within the header of
+the message, each component is treated as one long line, but in
+the body, each line is separate.
+Lower-case letters in the
+search pattern will match either lower or upper case in the
+message, while upper case will match only upper case.
+
+Once the search has been performed, the selected messages
+are scanned (see \fIscan\fR) if the `\-scan' switch is given, and
+then they are shown (see \fIshow\fR) if the `\-show' switch is
+given.
+After these two operations, the file operations (if
+requested) are performed.
+
+The `\-file' switch operates exactly like the \fIfile\fR command, with the
+same meaning for the `\-preserve' and `\-link' switches.
+
+The `\-keep' switch is similar to `\-file', but it produces a folder that
+is a subfolder of the folder being searched and defines it as
+the current folder (unless the `\-stay' flag is used).
+This
+subfolder contains the messages which matched the search
+criteria.
+All of the MH commands may be used with the sub-folder
+as the current folder.
+This gives the user considerable power
+in dealing with subsets of messages in a folder.
+
+The messages in a folder produced by `\-keep' will always have the
+same numbers as they have in the source folder (i.e., the
+`\-preserve' switch is automatic).
+This way, the message
+numbers are consistent with the folder from which the messages
+were selected.
+Messages are not removed from the source folder
+(i.e., the `\-link' switch is assumed).
+If a `+folder' is not
+specified, the standard name \*(lqselect\*(rq will be used.
+(This is the
+meaning of \*(lq(select)\*(rq when it appears in the output of the
+\fIfolder\fR command.) If `+folder' arguments are given to
+`\-keep', they will be used rather than \*(lqselect\*(rq for the names
+of the subfolders.
+This allows for several subfolders to be
+maintained concurrently.
+
+When a `\-keep' is performed, the subfolder becomes the current folder.
+This can be overridden by use
+of the `\-stay' switch.
+
+Here's an example:
+
+.nf
+\01  % folder +inbox
+\02           inbox+ has  16 messages (  3\- 22); cur=  3.
+\03  % pick \-from dcrocker
+\04  6 hits.
+\05  [+inbox/select now current]
+\06  % folder
+\07    inbox/select+ has  \06 messages (  3\- 16); cur=  3.
+\08  % scan
+.ds p \\h'\\w'+'u'
+\09   \03+  6/20   Dcrocker          Re: ned file update issue...
+10   \06\*p  6/23   Dcrocker          removal of files from /tm...
+11   \08\*p  6/27   Dcrocker          Problems with the new ned...
+12   13\*p  6/28   d\h'\w'D'u-\w'd'u'crocker          newest nned  \*(<<I would ap...
+13   15\*p  7/\05   Dcrocker          nned  \*(<<Last week I asked...
+14   16\*p  7/\05   d\h'\w'D'u-\w'd'u'crocker          message id format  \*(<<I re...
+15  % show all | print
+16     [produce a full listing of this set of messages on the line printer.]
+17  % folder \-up
+18            inbox+ has  16 messages (  3\- 22); cur=  3; (select).
+19  % folder \-down
+20   inbox/select+ has   6 messages (  3\- 16); cur=  3.
+21  % rmf
+22  [+inbox now current]
+23  % folder
+24            inbox+ has  16 messages (  3\- 22); cur=  3.
+.fi
+
+This is a rather lengthy example, but it shows the power of the
+MH package.
+In item 1, the current folder is set to inbox.
+In 3,
+all of the messages from dcrocker are found in inbox and linked
+into the folder \*(lqinbox/select\*(rq.
+(Since no action switch is
+specified, `\-keep' is assumed.)  Items 6 and 7 show that this
+subfolder is now the current folder.
+Items 8 through 14 are a
+\fIscan\fR of the selected messages (note that they are all from dcrocker
+and are all in upper and lower case).
+Item 15 lists all of the messages to
+the high-speed printer.
+Item 17 directs \fIfolder\fR to set the
+current folder to the parent of the selection-list folder, which
+is now current.
+Item 18 shows that this has been done.
+Item 19 resets
+the current folder to the selection list, and 21 removes the
+selection-list folder and resets the current folder to the
+parent folder, as shown in 22 and 23.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Folder\-Protect:~^For protection on new folders
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+`\-src +folder' defaults to current
+`msgs' defaults to all
+.fi
+`\-keep +select' is the default if no `\-scan', `\-show', or `\-file' is specified
+.Co
+If a `\-src +folder' is specified, it will
+become the current folder, unless a `\-keep' with 0 or 1
+folder arguments makes the selection-list subfolder the
+current folder.
+Each selection-list folder will have its
+current message set to the first of the messages linked into
+it unless the selection list already existed, in which case the
+current message won't be changed.
+.En
+.SC PREV
+.NA
+prev \- show the previous message
+.SY
+prev \%[+folder] \%[\-switches\ for\ \fIl\fR] \%[\-help]
+.DE
+\fIPrev\fR performs a \fIshow\fR on the previous message in the specified
+(or current) folder.
+Like \fIshow\fR, it passes any switches on to the
+program \fIl\fR, which is called to list the message.
+This command
+is exactly equivalent to \*(lqshow prev\*(rq.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+.Co
+If a folder is specified, it will become current, and the
+message that is shown (i.e., the previous message in sequence)
+will become the current message.
+.En
+.SC PROMPTER
+.NA
+prompter \- prompting editor front end
+.SY
+This program is not called directly but takes the place
+of an editor and acts as an editor front end.
+
+.ti .5i
+prompter \%[\-erase\ chr] \%[\-kill\ chr] \%[\-help]
+.DE
+\fIPrompter\fR is an editor which allows rapid composition of
+messages.
+It is particularly useful to network and low-speed
+(less than 2400 baud) users of MH.
+It is an MH program in that
+it can have its own profile entry with switches, but it can't
+be invoked directly as all other MH commands can; it is an editor
+in that it is invoked by an \*(lq\-editor prompter\*(rq switch or by the
+profile entry \*(lqEditor: prompter\*(rq, but functionally it is merely
+a text-collector and not a true editor.
+
+\fIPrompter\fR expects to be called from \fIcomp\fR, \fIrepl\fR, \fIdist\fR, or
+\fIforw\fR, with a draft file as an argument.
+For example, \*(lqcomp
+\-editor prompter\*(rq will call \fIprompter\fR with the file \*(lqdraft\*(rq already set
+up with blank components.
+For each blank component it finds in
+the draft, it prompts the user and accepts a response.
+A
+<RETURN> will cause the whole component to be left out.
+A \*(lq\\\*(rq
+preceding a <RETURN> will continue the response on the next line,
+allowing for multiline components.
+
+Any component that is non-blank will be copied and echoed to the
+terminal.
+
+The start of the message body is prompted by a line of
+dashes.
+If the body is non-blank, the prompt is
+\*(lq--------Enter additional text\*(rq.
+Message-body typing is terminated with
+a <CTRL-D> (or <OPEN>).
+Control is returned to the calling
+program, where the user is asked \*(lqWhat now?\*(rq.
+See \fIcomp\fR for
+the valid options.
+
+The line editing characters for kill and erase may be
+specified by the user via the arguments \*(lq\-kill chr\*(rq and \*(lq\-erase
+chr\*(rq, where chr may be a character; or \*(lq\\nnn\*(rq, where nnn is the
+octal value for the character.
+(Again, these may come from the
+default switches specified in the user's profile.)
+
+A <DEL> during message-body typing is equivalent to
+<CTRL-D> for compatibility with NED.
+A <DEL> during
+component typing will abort the command that invoked
+\fIprompter\fR.
+.Fi
+None
+.Pr
+^prompter-next:~^To name the editor to be used on exit from \fIprompter\fR
+.De
+.Co
+None
+.En
+.SC REPL
+.NA
+repl \- reply to a message
+.SY
+repl \%[+folder] \%[msg] \%[\-editor\ editor] \%[\-inplace] \%[\-annotate]
+\%[\-help] \%[\-noinplace]
+\%[\-noannotate]
+.DE
+\fIRepl\fR aids a user in producing a reply to an existing
+message.
+In its simplest form (with no arguments), it will set up
+a message-form skeleton in reply to the current message in the
+current folder, invoke the editor, and send the composed
+message if so directed.
+The composed message is constructed as
+follows:
+
+.nf
+.in 1i
+To: <Reply-To> or <From>
+cc: <cc>, <To>
+Subject: Re: <Subject>
+In-reply-to: Your message of <Date>
+.ti +\w'In-reply-to: 'u
+<Message-Id>
+.in .5i
+.fi
+
+where field names enclosed in angle brackets (< >) indicate the
+contents of the named field from the message to which the reply
+is being made.
+Once the skeleton is constructed, an editor is
+invoked (as in \fIcomp\fR, \fIdist\fR, and \fIforw\fR).
+While in the editor,
+the message being replied to is available through a link named
+\*(lq@\*(rq.
+In NED, this means the replied-to message may be \*(lqused\*(rq
+with \*(lquse @\*(rq, or put in a window by \*(lqwindow @\*(rq.
+
+As in \fIcomp\fR, \fIdist\fR, and \fIforw\fR, the user will be queried
+before the message is sent.
+If `\-annotate' is
+specified, the replied-to message will be annotated with the
+single line
+
+.ti +.5i
+Replied: \*(<<Date\*(>>.
+
+The command
+\*(lqcomp \-use\*(rq may be used to pick up interrupted editing, as in
+\fIdist\fR and \fIforw\fR; the `\-inplace' switch annotates the message in place,
+so that all folders with links to it will see the annotation.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+^<mh-dir>/draft~^The constructed message file
+^/usr/bin/send~^To send the composed message
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Editor:~^To override the use of /bin/ned as the default editor
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+`+folder' defaults to current
+`msgs' defaults to cur
+`\-editor' defaults to /bin/ned
+`\-noannotate'
+`\-noinplace'
+.Co
+If a `+folder' is specified, it will become the current
+folder, and the current message will be set to the replied-to
+message.
+.sp 2
+.En
+.SC RMF
+.NA
+rmf \- remove folder
+.SY
+rmf \%[+folder] \%[\-help]
+.DE
+\fIRmf\fR removes all of the files (messages) within the specified
+(or default) folder, and then removes the directory (folder).
+If
+there are any files within the folder which are not a part of MH,
+they will \fInot\fR be removed, and an error will be produced.
+If the
+folder is given explicitly or the current folder is a
+subfolder (i.e., a selection list from \fIpick\fR), it will be
+removed without confirmation.
+If no argument is specified and
+the current folder is not a selection-list folder, the
+user will be asked for confirmation.
+
+\fIRmf\fR irreversibly deletes messages that don't have other links,
+so use it with caution.
+
+If the folder being removed is a subfolder, the parent
+folder will become the new current folder, and \fIrmf\fR will
+produce a message telling the user this has happened.
+This
+provides an easy mechanism for selecting a set of messages,
+operating on the list, then removing the list and returning to
+the current folder from which the list was extracted.
+(See the
+example under \fIpick\fR.)
+
+The files that \fIrmf\fR will delete are cur, any file beginning
+with a comma, and files with purely numeric names.
+All others
+will produce error messages.
+
+\fIRmf\fR of a read-only folder will delete the \*(lqcur\-\*(rq entry from the
+profile without affecting the folder itself.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+`+folder' defaults to current, usually with confirmation
+.Co
+\fIRmf\fR will set the current folder to the parent folder if a
+subfolder is removed; or if the current folder is removed,
+it will make \*(lqinbox\*(rq current.
+Otherwise, it doesn't change the
+current folder or message.
+.En
+.SC RMM
+.NA
+rmm \- remove messages
+.SY
+rmm \%[+folder] \%[msgs] \%[\-help]
+.DE
+\fIRmm\fR removes the specified messages by renaming the message
+files with preceding commas.
+(This is the Rand-UNIX backup file
+convention.)
+
+The current message is not changed by \fIrmm\fR, so a \fInext\fR  will
+advance to the next message in the folder as expected.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+`+folder' defaults to current
+`msgs' defaults to cur
+.Co
+If a folder is given, it will become current.
+.En
+.SC SCAN
+.NA
+scan \- produce a one-line-per-message scan listing
+.SY
+scan \%[+folder] \%[msgs] \%[\-f\&f] \%[\-header] \%[\-help]
+\%[\-nof\&f] \%[\-noheader]
+.DE
+\fIScan\fR produces a one-line-per-message listing of the specified
+messages.
+Each \fIscan\fR line contains the message number (name),
+the date, the \*(lqFrom\*(rq field, the \*(lqSubject\*(rq field, and, if room
+allows, some of the body of the message.
+For example:
+
+.nf
+.ta .5i 1.2i 2.6i
+^ #~^^Date~^^  From~^Subject\ \ \ \ \[\*(<<Body]
+^15+~^^7/\05~^^Dcrocker~^nned  \*(<<Last week I asked some of
+^16\ \-~^^7/\05~^^dcrocker~^message id format  \*(<<I recommend
+^18~^^7/\06~^^Obrien~^Re: Exit status from mkdir
+^19~^^7/\07~^^Obrien~^"scan" listing format in MH
+.re
+.fi
+
+The `+' on message 15 indicates that it is the current message.
+The `\-' on message 16 indicates that it has been
+replied to, as indicated by a \*(lqReplied:\*(rq component produced by
+an `\-annotate' switch to the \fIrepl\fR command.
+
+If there is sufficient room left on the \fIscan\fR line after the
+subject, the line will be filled with text from the body,
+preceded by \*(<<.
+\fIScan\fR actually reads each of the specified
+messages and parses them to extract the desired fields.
+During parsing, appropriate error messages will be produced if
+there are format errors in any of the messages.
+
+The `\-header' switch produces a header line prior to the \fIscan\fR
+listing, and the `\-f\&f' switch will cause a form feed to be
+output at the end of the \fIscan\fR listing.
+See Appendix D.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+Defaults:
+`+folder' defaults to current
+`msgs' defaults to all
+`\-nof\&f'
+`\-noheader'
+.Co
+If a folder is given, it will become current.
+The current
+message is unaffected.
+.En
+.SC SEND
+.NA
+send \- send a message
+.SY
+send \%[file] \%[\-draft] \%[\-verbose] \%[\-format] \%[\-msgid]
+\%[\-help]  \%[\-noverbose] \%[\-noformat] \%[\-nomsgid]
+.DE
+\fISend\fR will cause the specified file (default <mh-dir>/draft) to
+be delivered to each of the addresses in the \*(lqTo:\*(rq, \*(lqcc:\*(rq, and \*(lqBcc:\*(rq
+fields of the message.
+If `\-verbose' is specified, \fIsend;\fR
+will monitor the delivery of local and net mail.
+\fISend\fR with no
+argument will query whether the draft is the intended file, whereas
+`\-draft' will suppress this question.
+Once the message has
+been mailed (or queued) successfully, the file will be renamed
+with a leading comma, which allows it to be retreived until the
+next draft message is sent.
+If there are errors in the
+formatting of the message, \fIsend;\fR will abort with a (hopefully)
+helpful error message.
+
+If a \*(lqBcc:\*(rq field is encountered, its addresses will be used for
+delivery, but the \*(lqBcc:\*(rq field itself will be deleted from all
+copies of the outgoing message.
+
+Prior to sending the message, the fields \*(lqFrom:  user\*(rq, and
+\*(lqDate: now\*(rq will be prepended to the message.
+If `\-msgid' is
+specified, then a \*(lqMessage-Id:\*(rq field will also be added to the
+message.
+If the message already contains a \*(lqFrom:\*(rq field, then a
+\*(lqSender: user\*(rq field will be added instead.
+(An already existing
+\*(lqSender:\*(rq field will be deleted from the message.)
+
+If the user doesn't specify `\-noformat', each of the entries in
+the \*(lqTo:\*(rq and \*(lqcc:\*(rq fields will be replaced with \*(lqstandard\*(rq format
+entries.
+This standard format is designed to be usable by all
+of the message handlers on the various systems around the
+ARPANET.
+
+If an \*(lqFcc: folder\*(rq is encountered, the message will be copied
+to the specified folder in the format in which it will appear to any
+receivers of the message.
+That is, it will have the prepended
+fields and field reformatting.
+
+If a \*(lqDistribute-To:\*(rq field is encountered, the message
+is handled as a redistribution message (see \fIdist\fR for
+details), with \*(lqDistribution-Date: now\*(rq and \*(lqDistribution-From: user\*(rq
+added.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+.Pr
+^Path:~^To determine the user's MH directory
+.De
+`file' defaults to draft
+`\-noverbose'
+`\-format'
+`\-nomsgid'
+.Co
+\fISend\fR has no effect on the current message or folder.
+.En
+.SC SHOW
+.NA
+show \- show (list) messages
+.SY
+show \%[+folder] \%[msgs] \%[\-pr] \%[\-nopr] \%[\-draft] \%[\-help]
+\%[\fIl\fR\ or\ \fIpr\fR\ switches]
+.DE
+\fIShow\fR lists each of the specified messages to the standard
+output (typically, the terminal).
+The messages are listed exactly
+as they are, with no reformatting.
+A program called \fIl\fR is
+invoked to do the listing, and any switches not recognized by
+\fIshow\fR are passed along to \fIl\fR.
+
+If no \*(lqmsgs\*(rq are specified, the current message is used.
+If
+more than one message is specified, \fIl\fR will prompt for a
+<return> prior to listing each message.
+
+\fIl\fR will list each message, a page at a time.
+When the end of
+page is reached, \fIl\fR will ring the bell and wait for a <RETURN>
+or <CTRL-D>.
+If a <return> is entered, \fIl\fR will clear the
+screen before listing the next page, whereas <CTRL-D> will not.
+The switches to \fIl\fR are
+`\-p#' to indicate the page length in lines, and `\-w#' to
+indicate the width of the page in characters.
+
+If the standard output is not a terminal, no queries are made,
+and each file is listed with a one-line header and two lines of
+separation.
+
+If `\-pr' is specified, then \fIpr\fR(I) will be invoked rather than
+\fIl\fR, and the switches (other than `\-draft') will be passed
+along.
+\*(lqShow \-draft\*(rq will list the file <mh-dir>/draft if it
+exists.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+^/bin/l~^Screen-at-a-time list program
+^/bin/pr~^\fIpr\fR(I)
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+`+folder' defaults to current
+`msgs' defaults to cur
+`\-nopr'
+.Co
+If a folder is given, it will become the current message.
+The last message
+listed will become the current message.
+.En
+\"
+\"              On to the Appendices
+\"
+.fo ''-%-''
+.he ''''
+.(x
+.sp
+Appendix
+.)x _
+.de $c                          \" Major Heading printer
+.ce
+Appendix \\n+(ch
+.sp 2p
+.ce
+.b "\\s12\\$1\\s0"              \" 12 Point Bold Header
+.(x
+\ \ \ \\n(ch.\\ \\ \\$2
+.)x
+.sp 45p                                \" 45 points or about 1/2 inch
+..
+.++ A
+.bp
+.$c "COMMAND SUMMARY\\**" "Command Summary"
+.(f
+\**All commands accept a \-help switch.
+.)f
+.in 1i
+.na
+.ti .5i
+comp \%[\-editor\ editor] \%[\-form\ formfile] \%[file] \%[\-use]
+\%[\-nouse] \%[\-help]
+
+.ti .5i
+dist \%[+folder] \%[msg] \%[\-form\ formfile] \%[\-editor\ editor]
+\%[\-annotate] \%[\-noannotate]
+\%[\-inplace] \%[\-noinplace]
+\%[\-help]
+
+.ti .5i
+file \%[\-src\ +folder] \%[msgs] \%[\-link] \%[\-preserve] \%+folder\ ...
+\%[\-nolink] \%[\-nopreserve]
+\%[\-file\ file] \%[\-nofile] \%[\-help]
+
+.ti .5i
+folder \%[+folder] \%[msg] \%[\-all] \%[\-fast] \%[\-nofast] \%[\-up] \%[\-down]
+\%[\-header] \%[\-noheader] \%[\-total] \%[\-nototal] \%[\-pack] \%[\-nopack]
+\%[\-help]
+
+.ti .5i
+forw \%[+folder] \%[msgs] \%[\-editor\ editor] \%[\-form\ formfile]
+\%[\-annotate] \%[\-noannotate]
+\%[\-inplace]  \%[\-noinplace]
+\%[\-help]
+
+.ti .5i
+inc \%[+folder] \%[\-audit\ audit-file] \%[\-help]
+
+.ti .5i
+next \%[+folder] \%[\-switches\ for\ \fIl\fR] \%[\-help]
+
+.ta .4i 1.8i
+.nf
+.in .5i
+^pick~^^\0\-cc~^ \%[\-src\ +folder] \%[msgs] \%[\-help] \%[\-scan] \%[\-noscan]
+^^^\0\-date~^   \%[\-show] \%[\-noshow] \%[\-nofile] \%[\-nokeep]
+^^^\0\-from~^
+^^^\s+2\b'\(lt\(bv\(bv\(lk\(bv\(bv\(lb'\s0 \-search~\s+2\b'\(rt\(bv\(bv\(rk\(bv\(bv\(rb'\s0^ pattern
+^^^\0\-subject~^
+^^^\0\-to~^ \%[\-file \%[\-preserve] \%[\-link] \%+folder\ ... \%[\-nopreserve] \%[\-nolink] ]
+^^^\0\-\-component~^ \%[\-keep \%[\-stay] \%[\-nostay] \%[+folder\ ...]\ ]
+.fi
+.re
+
+.ti .5i
+prev \%[+folder] \%[\-switches\ for\ \fIl\fR] \%[\-help]
+
+.ti .5i
+prompter \%[\-erase\ chr] \%[\-kill\ chr] \%[\-help]
+
+.ti .5i
+repl \%[+folder] \%[msg] \%[\-editor\ editor] \%[\-inplace] \%[\-annotate]
+\%[\-help] \%[\-noinplace]
+\%[\-noannotate]
+
+.ti .5i
+rmf \%[+folder] \%[\-help]
+
+.ti .5i
+rmm \%[+folder] \%[msgs] \%[\-help]
+
+.ti .5i
+scan \%[+folder] \%[msgs] \%[\-f\&f] \%[\-header] \%[\-help]
+\%[\-nof\&f] \%[\-noheader]
+
+.ti .5i
+send \%[file] \%[\-draft] \%[\-verbose] \%[\-format] \%[\-msgid]
+\%[\-help]  \%[\-noverbose] \%[\-noformat] \%[\-nomsgid]
+
+.ti .5i
+show \%[+folder] \%[msgs] \%[\-pr] \%[\-nopr] \%[\-draft] \%[\-help]
+\%[\fIl\fR\ or\ \fIpr\fR\ switches]
+.ad
+.in 0
+\".+c "MESSAGE FORMAT" "Message Format"
+.if t \{
+.ll 32P
+.lt 32P
+\}
+.bp
+.$c "MESSAGE FORMAT" "Message Format"
+.pp
+This section paraphrases the format of ARPANET text messages
+given in Ref. 6.
+
+.lp
+ASSUMPTIONS
+.np
+Messages
+are expected to consist of lines of text.
+Graphics and binary data are not handled.
+.np
+No data compression is accepted.
+All text is clear
+ASCII 7-bit data.
+
+.lp
+LAYOUT
+.lp
+A general \*(lqmemo\*(rq framework is used.
+A message consists of a
+block of information in a rigid format, followed by general
+text with no specified format.
+The rigidly formatted  first
+part of a message is  called the header, and the free-format
+portion is called the body.
+The header must always
+exist, but the body is optional.
+
+.lp
+THE HEADER
+.lp
+Each header item can be viewed as a single logical line of ASCII
+characters.
+If the text of a header item extends across several
+real lines, the continuation lines are indicated by leading
+spaces or tabs.
+.lp
+Each header item is called a component and is composed of a
+keyword or name, along with associated text.
+The keyword begins at the
+left margin, may contain spaces or tabs, may not exceed 63
+characters, and is terminated by a colon (:).
+Certain
+components (as identified by their keywords) must follow rigidly
+defined formats in their text portions.
+.lp
+The text for most formatted components (e.g., \*(lqDate:\*(rq and \*(lqMessage-Id:\*(rq)
+is produced automatically.
+The only ones entered by the
+user are address fields such as \*(lqTo:\*(rq, \*(lqcc:\*(rq, etc.
+ARPA addresses
+are assigned mailbox names and host computer specifications.
+The
+rough format is \*(lqmailbox at host\*(rq, such as \*(lqBorden at Rand-Unix\*(rq.
+Multiple addresses are separated by commas.
+A missing host is
+assumed to be the local host.
+
+.ne 10
+.lp
+THE BODY
+.lp
+A blank line signals that all following text up to the end of the file
+is the body.
+(A blank line is defined as a pair of
+<end-of-line> characters with \fIno\fR characters in between.)
+No formatting is expected or enforced within the body.
+.lp
+Within MH, a line consisting of dashes is accepted
+as the header delimiter.
+This is a cosmetic feature applying
+only to locally composed mail.
+.bp
+.$c "MESSAGE NAME BNF" "Message Name BNF"
+
+.ta 1.2i 1.8i 3.2i
+.nf
+.in 1i
+^msgs~^^:=~^^msgspec~^|
+^^^^msgs msgspec
+
+^msgspec~^^:=~^^msg~^|
+^^^^^msg-range~^|
+^^^^msg-sequence
+
+^msg~^^:=~^^msg-name~^|
+^^^^<number>^
+
+^msg-name~^^:=~^^\*(lqfirst\*(rq~^|
+^^^^^\*(lqlast\*(rq~^|
+^^^^^\*(lqcur\*(rq~^|
+^^^^^\*(lq\*.\*(rq~^|
+^^^^^\*(lqnext\*(rq~^|
+^^^^\*(lqprev\*(rq
+
+^msg-range~^^:=~^^msg\*(lq-\*(rqmsg~^|
+^^^^^\*(lqall\*(rq
+
+^msg-sequence~^^:=~^msg\*(lq:\*(rqsigned-number
+
+^signed-number~^^:=~^^\*(lq+\*(rq<number>~^|
+^^^^^\*(lq\--\*(rq<number>~^|
+^^^^<number>
+.re \" Reset Tabs
+.fi
+.sp
+.pp
+Where <number> is a decimal number in the range 1 to 999.
+.pp
+Msg-range specifies all of the messages in the given range
+and must not be empty.
+.pp
+Msg-sequence specifies up to <number> of messages, beginning
+with \*(lqmsg\*(rq (in the case of first, cur, next, or <number>),
+or ending with \*(lqmsg\*(rq (in the case of prev or last).
++<number> forces \*(lqstarting with msg\*(rq, and \-<number> forces
+\*(lqending with number\*(rq.
+In all cases, \*(lqmsg\*(rq must exist.
+.bp
+.$c "EXAMPLE OF SHELL COMMANDS"  "Example of Shell Commands"
+.pp
+UNIX commands may be mixed with MH commands to obtain additional
+functions.
+These may be prepared as files (known as
+shell command files or
+shell scripts).
+The following example is a useful function that
+illustrate the possibilities.
+Other functions, such as copying,
+deleting, renaming, etc., can be achieved in a similar fashion.
+
+HARDCOPY
+.pp
+The command:
+
+.ti +.5i
+(scan\0\-f\&f\0\-header;\0show\0all\0\-pr\0\-f)\0|\0print
+
+produces a scan listing of the current folder, followed by a
+form feed, followed by a formatted listing of all messages
+in the folder, one per page.
+Omitting \*(lq\-pr\0\-f\*(rq will cause the
+messages to be concatenated, separated by a one-line header
+and two blank lines.
+.pp
+You can create variations on this theme, using \fIpick\fR.
+.re
+.fi
+.in 0
+.bp
+.ce
+.b \\s12REFERENCES\\s0
+.(x
+.sp
+REFERENCES
+.)x
+.sp 3
+.in .4i
+.ti 0
+1.  Crocker, D. H., J. J. Vittal, K. T. Pogran, and D. A. Henderson, Jr.,
+\*(lqStandard for the Format of ARPA Network Test Messages,\*(rq \fIArpanet Request
+for Comments\fR, No. 733, Network Information Center 41952, Augmentation
+Research Center, Stanford Research Institute,
+November 1977.
+
+.ti 0
+2.  Thompson, K., and D. M. Ritchie, \*(lqThe UNIX Time-sharing System,\*(rq
+\fICommunications of the ACM\fR, Vol. 17, July 1974, pp. 365-375.
+
+.ti 0
+3.  McCauley, E. J., and P. J. Drongowski, \*(lqKSOS\-The Design of a Secure
+Operating System,\*(rq \fIAFIPS Conference Proceedings\fR,
+National Computer Conference,
+Vol. 48, 1979, pp. 345-353.
+
+.ti 0
+4.  Crocker, David H., \fIFramework and Functions of the \*(lqMS\*(rq Personal
+Message System\fR, The Rand Corporation, R-2134-ARPA, December 1977.
+
+.ti 0
+5.  Thompson, K., and D. M. Ritchie, \fIUNIX Programmer's Manual\fR, 6th ed.,
+Western Electric Company, May 1975 (available only to UNIX licensees).
+
+.ti 0
+6.  Bilofsky, Walter, \fIThe CRT Text Editor NED\-Introduction and
+Reference Manual\fR, The Rand Corporation, R-2176-ARPA, December 1977.
+.bp 3
+.de $c
+.ce
+.b "\\s12\\$1\\s0"   \" 12 Point Bold Header
+.(x y
+.sp
+\\$1
+.)x
+.sp 3
+..
+.pn 3
+.++ P
+.fo ''''
+.he ''-%-''
+.+c PREFACE
+.pp
+This report describes a system for dealing with messages transmitted on a
+computer.  Such messages might originate with other users of the same
+computer or might come from an outside source through a network to which the user's
+computer is connected.  Such computer-based message systems are
+becoming increasingly widely used, both within and outside the Department
+of Defense.
+.pp
+The message handling system MH was developed for two reasons.
+One was to investigate some
+research ideas concerning how a message system might take advantage of
+the architecture of the UNIX time-sharing operating system for
+Digital Equipment Corporation PDP-11 and VAX computers, and the special
+features of UNIX's command-level interface with the user (the
+\*(lqshell\*(rq).  The other reason was to provide a better and more
+adaptable base than that of conventional designs
+on which to build a command and control message system.
+The effort has succeeded in both
+regards, although this report mainly describes the message system itself
+and how it fits in with UNIX.  The main research results are being
+described and analyzed in a forthcoming Rand report.
+The system is currently being used as part
+of a tactical command and control \*(lqlaboratory,\*(rq which is also being described
+in a separate report.
+.pp
+The present report should be of interest to three groups of readers.  First,
+it is a complete reference manual for the users of MH (although
+users outside of Rand must take into
+account differences from the local Rand operating system).  Second, it should be
+of interest to those who have a general knowledge of computer-based
+message systems, both in civilian and military applications.  Finally,
+it should be of interest to those who build large subsystems that
+interface with users, since it illustrates a new approach to such
+interfaces.
+.pp
+The MH system was developed by the first
+author, using an approach suggested by the other two authors.
+Valuable assistance was provided by Phyllis Kantar in the later
+stages of the system's implementation.
+Several colleagues
+contributed to the ideas included in this system, particularly
+Robert Anderson and David Crocker.
+In addition, valuable experience
+in message systems, and a valuable source of ideas, was available
+to us in the form of a previous message system for UNIX called
+MS, designed at Rand by David Crocker.
+.pp
+This report was prepared as part of the Rand project entitled \*(lqData
+Automation Research\*(rq, sponsored by Project AIR FORCE.
+.pn 5
+.+c SUMMARY
+.pp
+Electronic communication of text messages is becoming
+commonplace.  Computer-based message systems\-software
+packages that provide tools for dealing with messages\-are used in many
+contexts.  In particular, message systems are becoming
+increasingly important in command and control and intelligence
+applications.
+.pp
+This report describes a message handling system called MH.
+This system provides the user
+with tools to compose, send, receive, store, retrieve, forward, and
+reply to messages.  MH has been built on the UNIX time-sharing system,
+a popular operating system developed for the DEC PDP-11 and VAX classes of
+computers.
+.pp
+A complete description of MH is given for users of
+the system.  For those who do not intend to use the system, this description
+gives a general idea of what a message system is like.  The system involves
+some new ideas about how large subsystems can be constructed.  These design
+concepts and a comparison of MH with other message systems
+will be published in a forthcoming Rand report.
+.pp
+The interesting and unusual features of MH include the
+following:  The user command interface to MH is the UNIX \*(lqshell\*(rq
+(the standard UNIX command interpreter).  Each separable
+component of message handling, such as message composition or
+message display, is a separate command.  Each program is driven from
+and updates a private user environment, which is stored as a file
+between program invocations.  This private environment also contains
+information to \*(lqcustom tailor\*(rq MH to the individual's tastes.  MH
+stores each message as a separate file under UNIX, and it utilizes the
+tree-structured UNIX file system to organize groups of files within
+separate directories or \*(lqfolders.\*(rq  All of the UNIX facilities
+for dealing with files and directories, such as
+renaming, copying, deleting, cataloging, off-line printing, etc., are
+applicable to messages and directories of messages (folders).  Thus,
+important capabilities needed in a message system are available in MH without
+the need (often seen in other message systems) for code that
+duplicates the facilities of the supporting operating system.
+It also allows users familiar with the shell to use MH with minimal
+effort.
+.he ''''
+.fo ''''
+.bp
+.ce
+.b \\s12CONTENTS\\s0
+.sp 3
+.xp y
+.xp x
+
+.bp     \" Spare numbers for cut and paste work!
+.ft B
+
+1       1       1       1       1       1       1       1
+
+1       1       1       1       1       1       1       1
+
+1       1       1       1       1       1       1       1
+
+1       1       1       1       1       1       1       1
+
+2       2       2       2       2       2       2       2
+
+2       2       2       2       2       2       2       2
+
+2       2       2       2       2       2       2       2
+
+3       3       3       3       3       3       3    
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/DOC/mh.me.5 b/docs/historical/mh-jun-1982/DOC/mh.me.5
new file mode 100644 (file)
index 0000000..de016ee
--- /dev/null
@@ -0,0 +1,2507 @@
+.de $c                          \" Major Heading printer
+.ce
+.b "\\s12\\n+(ch.\\ \\$1\\s0"   \" 12 Point Bold Header
+.(x
+
+\ \ \ \\n(ch.\\ \\ \\$1
+.)x
+.sp 45p         \" 45 point space or about 1/2 inch
+..
+\".nr xs .15v     \" Put index entries closer together
+.(x
+
+Section
+.)x _
+.de $0          \" Sub-Heading macro called AFTER printing the heading
+.(x
+.sp .3v
+.ti .5i
+\\$1
+.)x
+..
+.de $s          \" Macro to print footnote separator
+\"\l'2i'        \" No line drawn
+.if n \
+.       sp 1.3  \" But extra space to make up for it.
+..
+.fc ^ ~         \" The characters ^ and ~ CANNOT BE USED
+\"                 throughout this document except as field
+\"                 delimiter & pad indicator!
+.he ''-%-''
+.ll 32P         \" 32 Picas or about 5+1/3 inch Line Length
+.if n .ll 72m   \" Use 72 ems for nroff
+.nr ss 30p      \" 30 point space before section titles
+.nr fm 5v       \" Rand likes bigger than normal [3v] bottom margins
+.nr bm 7v       \"   ditto
+.ds . \\fB.\\fP\\h'-(1m/4)' \" Bold period to stand out.
+.ds << <\\h!-(\\w'<'/2)!<
+.ds >> >\\h!-(\\w'>'/2)!>
+.ds ** \v'-3p'\s+1*\s0\v'+3p'
+.++ C
+.+c INTRODUCTION
+.pp
+Although people can travel cross-country in hours and can
+reach others by telephone in seconds, communications still depend
+heavily upon paper, most of which is distributed through the mails.
+.pp
+There are several major reasons for this continued dependence on
+written documents.
+First, a written document may be proofread
+and corrected prior to its distribution, giving the author
+complete control over his words.
+Thus, a written document is
+better than a telephone conversation in this respect.
+Second,
+a carefully written document is far less likely to be
+misinterpreted or poorly translated than a phone conversation.
+Third, a signature offers reasonable verification of authorship,
+which cannot be provided with media such as telegrams.
+.pp
+However, the need for
+.u fast ,
+accurate, and reproducible document distribution is
+obvious.
+One solution in widespread use is the telefax.
+Another
+that is rapidly gaining popularity is electronic mail.
+Electronic mail is similar to telefax in that the data to be sent
+are digitized, transmitted via phone lines, and
+turned back into a document at the receiver.
+The advantage of
+electronic mail is in its compression factor.
+Whereas a telefax
+must scan a page in very fine lines and send all of the black and
+white information, electronic mail assigns characters fixed
+codes which can be transmitted as a few bits of information.
+Telefax presently has the advantage of being able to transmit an
+arbitrary page, including pictures, but electronic mail is
+beginning to deal with this problem.
+Electronic mail also integrates well
+with current directions in office automation, allowing documents
+prepared with sophisticated equipment at one site to be quickly
+transferred and printed at another site.
+.pp
+Currently, most electronic mail is intraorganizational,
+with mail transfer remaining within one computer.
+As computer
+networking becomes more common, however, it is becoming more feasible to
+communicate with anyone whose computer can be linked to your
+own via a network.
+.pp
+The pioneering efforts on general-purpose electronic mail
+were by organizations using the Defense Department's ARPANET.[1]
+The capability to send messages between computers existed before
+the ARPANET was developed, but it was used only in limited ways.
+With the advent of the
+ARPANET, tools began to be developed which made it convenient for
+individuals or organizations to distribute messages
+over broad geographic areas, using
+diverse computer facilities.
+The interest and activity in
+message systems has now reached such proportions that steps
+have been taken within the DoD to coordinate and
+unify the development of military message systems.
+The use of electronic mail is expected to increase
+dramatically in the next few years.
+The utility of such systems
+in the command and control and intelligence environments is
+clear, and applications in these areas will probably lead the
+way.
+As the costs for sending and handling electronic messags
+continue their rapid decrease, such uses can be
+expected to spread rapidly into other areas and, of course, will
+not be limited to the DoD.
+.pp
+A message system provides tools that help users (individuals
+or organizations) deal with messages in various ways.
+Messages
+must be composed, sent, received, stored, retrieved,
+forwarded, and replied to.
+Today's best interactive computer
+systems provide a variety of word-processing and information
+handling capabilities.
+The message handling facilities should be
+well integrated with the rest of the system, so as to be a
+graceful extension of overall system capability.
+.pp
+The message system described in this report, MH, provides most of the
+features that can be found in other message systems and also
+incorporates some new ones.
+It has been built on the UNIX time-sharing
+system,[2] a popular operating system for the DEC PDP-11
+and VAX classes of computers.
+A \*(lqsecure\*(rq operating
+system similar to UNIX is currently being developed,[3]
+and that system will also run MH.
+.pp
+This report provides a complete description of MH and
+thus may serve as a user's manual, although parts of the report
+will be of interest to non-users as well.
+Sections 2 and 3, the
+Overview and Tutorial, present the key
+ideas of MH and will give those not familiar with message systems
+an idea of what such systems are like.
+.pp
+MH consists of a set of commands which use some special
+files and conventions.
+Section 4 covers the information
+a user needs to know in addition to the
+commands.
+The final section, Sec. 5, describes each of
+the MH commands in detail.
+A summary of the commands is given in
+Appendix A, and Appendixes B and C describe the ARPANET
+conventions for messages (we expect that many users of MH
+will be using the ARPANET) and the formal syntax of such
+messages, respectively.
+Finally, Appendix D provides
+an illustration of how MH commands may be used in
+conjunction with other UNIX facilities.
+.pp
+A novel approach has been taken in the design of MH.
+The
+design concept will be reported in detail in a forthcoming Rand
+report, but it can be described briefly as follows.
+Instead of creating a large subsystem that appears as a single
+command to the user, MH is a collection of separate commands
+which are run as separate programs.
+The file and directory
+system of UNIX are used directly.
+Messages are stored as
+individual files (datasets), and collections of them are grouped
+into directories.
+In contrast, most other message systems store
+messages in a complicated data structure within a monolithic
+file.
+With the MH approach, UNIX commands can be
+interleaved with commands invoking the functions of the message
+handler.
+Conversely, existing UNIX commands
+can be used in connection with messages.
+For
+example, all the usual UNIX editing, text-formatting, and printing
+facilities can be applied directly to individual messages.
+MH,
+therefore, consists of a relatively small amount of new code; it
+makes extensive use of other UNIX software to provide the
+capabilities found in other message systems.
+.pp
+The MH system was developed by the first
+author, using an approach suggested by the other two authors.
+Valuable assistance was provided by Phyllis Kantar in the later
+stages of the system's implementation.
+Several colleagues
+contributed to the ideas included in this system, particularly
+Robert Anderson and David Crocker.
+In addition, valuable experience
+in message systems, and a valuable source of ideas, was available
+to us in the form of a previous message system for UNIX called
+MS,[4] designed at Rand by David Crocker.
+.+c OVERVIEW
+.pp
+There are three main aspects of MH:  the  way  messages  are
+stored (the message database), the user's profile (which directs
+how certain actions of the message handler take place), and the
+commands for dealing with messages.
+.pp
+Under MH, each message is stored as a separate file.
+A user
+can take any action with a message that he could with an ordinary
+file in UNIX.
+A UNIX directory in which messages are stored is
+called a folder.
+Each folder contains some standard entries to support
+the message-handling functions.
+The messages in a folder have numerical
+names.
+These folders (directories)
+are entries in a particular directory path, described in
+the user profile, through which MH can find message folders.
+Using the UNIX \*(lqlink\*(rq facility, it is possible for one copy of a
+message to be \*(lqfiled\*(rq in more than one folder, providing a
+message index facility.
+Also, using the UNIX tree-structured
+file system, it is possible to have a folder within a folder.
+This two-level organization provides a \*(lqselection-list\*(rq
+facility, with the full power of the MH commands available on
+selected sublists of messages.
+.pp
+Each user of MH has a user profile, a file in his $HOME (initial
+login)
+directory called \*(lq\*.mh\(ruprofile\*(rq.
+This profile contains several
+pieces of information used by the MH commands:  a
+path name to the directory that contains the message folders,
+information concerning which folder the user last referenced (the
+\*(lqcurrent\*(rq folder), and parameters that tailor MH commands
+to the individual user's requirements.
+It also contains
+most of the necessary state information concerning how
+the user is dealing with his messages, enabling MH to be
+implemented as a set of individual UNIX commands, in contrast to the
+usual approach of a monolithic subsystem.
+.pp
+In MH, incoming mail is appended
+to the end of a file called \*.mail in a user's $HOME
+directory.
+The user adds the new messages to his collection of MH messages
+by invoking the command
+.i inc .
+.i Inc
+(incorporate) adds the new
+messages to a folder called \*(lqinbox\*(rq, assigning them names which
+are consecutive integers starting with the next highest integer
+available in inbox.
+.i Inc
+also produces a
+.i scan
+summary of
+the messages thus incorporated.
+.pp
+There are four commands for examining the messages in a
+folder:
+.i show ,
+.i prev ,
+.i next ,
+and
+.i scan .
+.i Show
+displays a
+message in a folder,
+.i prev
+displays the message preceding the
+current message, and
+.i next
+displays the message following the
+current message.
+.i Scan
+summarizes the messages in a folder,
+producing one line per message, showing who the message is from,
+the date, the subject, etc.
+.pp
+The user may move a message from one folder to another with
+the command
+.i file .
+Messages may be removed from a folder
+by means of the command
+.i rmm .
+In addition, a user may query
+what the current folder is and may specify that a new folder
+become the current folder, through the command
+.i folder .
+.pp
+A set of messages based on content may be selected by
+use of the command
+.i pick .
+This command searches through
+messages in a folder and selects those that match a given
+criterion.
+A subfolder is created within the original folder,
+containing links to all the messages that satisfy the selection
+criteria.
+.pp
+A message folder (or subfolder) may be removed by means of
+the command
+.i rmf .
+.pp
+There are five commands enabling the user to create new
+messages and send them:
+.i comp ,
+.i dist ,
+.i forw ,
+.i repl ,
+and
+.i send .
+.i Comp
+provides the facility for the user to compose a
+new message;
+.i dist
+redistributes mail to additional addressees;
+.i forw
+enables the user to forward messages; and
+.i repl
+facilitates the generation of a reply to an incoming message.
+If
+a message is not sent directly by one of these commands, it may
+be sent at a later time using the command
+.i send .
+.pp
+All of the elements summarized above
+are described in more detail in the following sections.
+Many of the
+normal facilities of UNIX provide additional capabilities for
+dealing with messages in various ways.
+For example, it is
+possible to print messages
+on the line-printer without requiring any additional code within
+MH.
+Using standard UNIX facilities, any terminal output can be
+redirected to a file for repeated or future viewing.
+In general,
+the flexibility and capabilities of the UNIX interface with the
+user are preserved as a result of the integration of MH into the UNIX
+structure.
+.+c TUTORIAL
+.pp
+This tutorial provides a brief introduction to the MH commands.
+It should be sufficient
+to allow the user to read his mail, do some simple manipulations of
+it, and create and send messages.
+.pp
+A message has two major pieces:  the
+header and the body.
+The body consists of the text of the message
+(whatever you care to type in).
+It follows the header and is separated from
+it by an empty line.
+(When you compose a message, the form that appears
+on your terminal shows a line of dashes after the header.
+This is for
+convenience and is replaced by an empty line when the message is
+sent.)  The header is composed of several components, including the
+subject of the message and the person to whom it is addressed.
+Each component starts with a name
+and a colon; components must not start with a blank.
+The text of the
+component may take more than one line, but each continuation line must
+start with a blank.
+Messages typically have \*(lqto:\*(rq, \*(lqcc:\*(rq, and
+\*(lqsubject:\*(rq components.
+When composing a message, you should include
+the \*(lqto:\*(rq and \*(lqsubject:\*(rq components; the \*(lqcc:\*(rq (for people
+you want to send copies to) is not necessary.
+.pp
+The basic MH commands are
+.i inc ,
+.i scan ,
+.i show ,
+.i next ,
+.i prev ,
+.i rmm ,
+.i comp ,
+and
+.i repl .
+These are described below.
+
+.i inc
+.pp
+When you get the message \*(lqYou have mail\*(rq, type the command
+.i inc .
+You will get a \*(lqscan listing\*(rq such as:
+
+.nf
+.if t .ta .4i 1.0i 2i
+.if n .ta .4i 1.2i 3i
+^7+~^^\07/13~^^Cas~^revival of measurement work
+^8~^^10/\09~^^Norm~^NBS people and publications
+^9~^^11/26~^^To:norm~^question \*(<<Are there any functions
+.re
+.fi
+.pp
+This shows the messages you received since the last time you
+executed this command (
+.i inc
+adds these new messages to
+your inbox folder).
+You can see this list again, plus a list of any
+other messages you have, by using the
+.i scan
+command.
+
+.i scan
+.pp
+The scan listing shows the message number, followed by the
+date and the sender.
+(If you are the sender, the addressee in the \*(lqto:\*(rq
+component is displayed.
+You may send yourself a message by including
+your name among the \*(lqto:\*(rq or \*(lqcc:\*(rq addressees.)
+It also shows the message's subject; if
+the subject is short, the first part of the body of the message is
+included after the characters \*(<<.
+
+.ne 5
+.i show
+.pp
+This command shows the current message, that is,
+the first one of the new messages after an
+.i inc .
+If the message is not
+specified by name (number), it is
+generally the last message referred to by an MH command.
+For example,
+
+.ta 1i
+.ti .5i
+^\fIshow\fP\05~^will show message 5.
+.pp
+You can use the show command to copy a message or print a
+message.
+
+.(b L
+.in .5i
+.if t .ta 1i
+.if n .ta 1.5i
+^\fIshow\fR\0>\0\fIx\fR~^will copy the message to file x.
+.br
+^\fIshow\fR\0|\0\fIprint\fR~^will print the message, using the \fIprint\fR command.
+.br
+^\fInext\fR~^will show the message that follows the current message.
+.br
+^\fIprev\fR~^will show the message previous to the current message.
+.br
+^\fIrmm\fR~^will remove the current message.
+.br
+^\fIrmm\03\fR~^will remove message 3.
+.)b
+
+.ne 5
+.i comp
+.pp
+The
+.i comp
+command puts you in the editor to write or edit a message.
+Fill in or
+delete the \*(lqto:\*(rq, \*(lqcc:\*(rq, and \*(lqsubject:\*(rq fields, as appropriate, and
+type the body of the message.
+Then
+exit normally from the editor.
+You will be asked
+\*(lqWhat now?\*(rq.
+Type a carriage return to see the options.
+Typing \fBsend\fR
+will cause the message to be sent; typing \fBquit\fR will cause an exit
+from
+.i comp ,
+with the message draft saved.
+.pp
+If you quit without sending the message, it will be saved in a file
+called /usr/<name>/Mail/draft (where /usr/<name> is your $HOME directory).
+You can edit this file and send the message later, using the
+.i send
+command.
+
+.ne 4
+.i "comp\0\-editor\0prompter"
+.pp
+This command uses a different editor and is useful for preparing
+\*(lqquick and dirty\*(rq messages.
+It prompts you for each component of the
+header.
+Type the information for that component, or type a carriage
+return to omit the component.
+After that, type the body of the
+message.
+Backspacing is the only form of editing allowed with this editor.
+When the body is complete, type a carriage return followed by <CTRL-D>
+(<OPEN> on Ann Arbor terminals).
+This completes the initial preparation of the message; from then on, use
+the same procedures as with
+.i comp
+(above).
+
+.ne 5
+.i repl
+.br
+.i "repl\0n"
+.pp
+This command makes up an initial message form with a header
+that is appropriate for
+replying to an existing message.
+The message being answered is the
+current message if no message number is mentioned, or n if a number
+is specified.
+After the header is completed, you can finish the message as in
+.i comp
+(above).
+.pp
+This is enough information to get you going using MH.
+There are more commands,
+and the commands described here have more features.
+Subsequent sections
+explain MH in complete detail.
+The system is quite powerful if you
+want to use its sophisticated features, but the foregoing commands
+suffice for sending and receiving messages.
+.pp
+There are numerous additional capabilities you may wish to explore.
+For example, the
+.i pick
+command will select a subset of messages
+based on specified criteria such as sender or subject.
+Groups of
+messages may be designated, as described in Sec. V, under \*(lqMessage
+Naming\*(rq.
+The file \*(lq\*.mh\(ruprofile\*(rq can be used to tailor your use of
+the message system to your needs and preferences, as described in Sec. V,
+under \*(lqThe User Profile\*(rq.
+In general, you may
+learn additional features of the system selectively, according to your
+requirements,
+by studying the relevant sections of this manual.
+There is no need to
+learn all the details of the system at once.
+.+c "DETAILED DESCRIPTION"
+.pp
+This section describes the MH system in detail, including the components
+of the user profile, the conventions for message naming, and some of
+the other MH conventions.
+Readers who are
+generally familiar with computer systems will be able to follow
+the principal ideas, although some details may be meaningful only to
+those familiar with UNIX.
+.uh "THE USER PROFILE"
+.pp
+The first time an MH command is issued by a new user, the system
+prompts for a \*(lqpath\*(rq and creates an MH \*(lqprofile\*(rq.
+.pp
+Each MH user has a profile which contains current
+state information for the MH package and, optionally, tailoring
+information for each individual program.
+When a folder becomes
+the current folder, it is recorded in the user's profile.
+Other profile entries control the MH path (where folders and
+special files are kept), folder and message protections, editor
+selection, and default arguments for each MH program.
+.pp
+The MH profile is stored in the file \*(lq\*.mh\(ruprofile\*(rq in the
+user's $HOME directory.
+It has the format of a message without
+any body.
+That is, each profile entry is on one line, with a
+keyword followed by a colon (:) followed by text particular to
+the keyword.
+.br
+\(rh\ \ \&
+.i "This file must not have blank lines."
+.br
+The keywords
+may have any combination of upper and lower case.
+(See Appendix
+B for a description of message formats.)
+.pp
+For the average MH user, the only profile entry of
+importance is \*(lqPath\*(rq.
+Path specifies a directory in which MH
+folders and certain files such as \*(lqdraft\*(rq are found.
+The
+argument to this keyword must be a legal UNIX path that names an
+existing directory.
+If this path is unrooted (i.e., does not
+begin with a \fB/\fR), it will be presumed to start from the
+user's $HOME directory.
+All folder and message references within
+MH will relate to this path unless full path names are used.
+.pp
+Message protection defaults to 664, and folder protection to
+751.
+These may be changed by profile entries \*(lqMsg-Protect\*(rq
+and \*(lqFolder-Protect\*(rq, respectively.
+The argument to these
+keywords is an octal number which is used as the UNIX file mode.\**
+.(f
+\**See
+.i chmod (I)
+in the
+.i "UNIX Programmer's Manual" .[5]
+.)f
+.pp
+When an MH program starts running, it looks through the
+user's profile for an entry with a keyword matching the program's
+name.
+For example, when
+.i comp
+is run, it looks for a \*(lqcomp\*(rq
+profile entry.
+If one is found, the text of the profile entry is
+used as the default switch setting until all defaults are overridden
+by explicit switches passed to the program as arguments.
+Thus the profile
+entry \*(lqcomp:\0\-form\0standard.list\*(rq would direct
+.i comp
+to use the
+file \*(lqstandard.list\*(rq as the message skeleton.
+If an explicit
+form switch is given to the
+.i comp
+command, it will override the
+switch obtained from the profile.
+.pp
+In UNIX, a program may exist under several names, either by
+linking or aliasing.
+The actual invocation name is used by an MH
+program when scanning for its profile defaults.
+Thus, each MH program
+may have several names by which it can be invoked, and each name
+may have a different set of default switches.
+For example, if
+.i comp
+is invoked by the name
+.i icomp ,
+the profile entry
+\*(lqicomp\*(rq will control the default switches for this invocation of
+the
+.i comp
+program.
+This provides a powerful
+definitional facility for commonly used switch settings.
+.pp
+The default editor
+for editing within
+.i comp ,
+.i repl ,
+.i forw ,
+and
+.i dist ,
+is \*(lq/bin/ned\*(rq.\**
+.(f
+\**See Ref. 6 for a description of
+the NED text editor.
+.)f
+A different editor may be used by specifying
+the profile entry
+\*(lqEditor: \*(rq.
+The argument to \*(lqEditor\*(rq is the name of an
+executable program or shell command file which can be found via
+the user's $PATH defined search path, excluding the current
+directory.
+The \*(lqEditor:\*(rq profile specification
+may in turn be overridden by a \*(lq\-editor\0<editor>\*(rq
+profile switch associated with
+.i comp ,
+.i repl ,
+.i forw ,
+or
+.i dist .
+Finally, an explicit editor switch specified with any
+of these four commands will have ultimate precedence.
+.pp
+During message composition, more than one editor may be
+used.
+For example, one editor (such as
+.i prompter )
+may be used
+initially, and a second editor may be invoked later to revise
+the message being composed
+(see the discussion of
+.i comp
+in Section 5 for details).
+A profile entry \*(lq<lasteditor>\-next:\0<editor>\*(rq specifies the name of
+the editor to be used after a particular editor.
+Thus \*(lqcomp:\0\-e\0prompter\*(rq
+causes the initial text to be collected by
+.i prompter ,
+and the profile entry \*(lqprompter\-next:\0ed\*(rq names ed as the
+editor to be invoked for the next round of editing.
+.pp
+Some of the MH commands, such as
+.i show ,
+can be used on
+message folders owned by others, if those folders are readable.
+However,
+you cannot write in someone else's folder.
+All the MH command
+actions not requiring write permission may be used with
+a \*(lqread-only\*(rq folder.
+In a writable folder, a file named
+\*(lqcur\*(rq is used to contain its current message name.
+For read-only folders, the current message name is
+stored in the user's profile.
+.pp
+Table 1 lists examples of the currently defined profile
+entries, typical arguments, and the programs that reference the
+entries.
+.in .9i
+.ll -.9i
+.ta 2.3i
+.sp 30p
+.ce
+Table 1
+.sp 8p
+.ce
+P\s-2ROFILE\s0 C\s-2OMPONENTS\s0
+.hl             \" ~12p preceding + 1v (12p) after
+.nf
+^^MH Programs that
+^Keyword and Argument~^\ Use Component\h'|\n(.lu-.9i'\v'2p'\l'|0'\v'-2'  \" \l'..' does underlining
+.sp
+^Path:\0Mail~^All
+^Current-Folder:\0inbox~^Most
+^Editor:\0/bin/ed~^\fIcomp, dist, forw, repl\fR
+^Msg\-Protect:\0644~^\fIinc\fR
+^Folder\-Protect:\0711~^\fIfile, inc, pick\fR
+^<program>:\0default switches~^All
+^cur\-<read-onlyfolder>:\0172~^Most
+^prompter\-next:\0ed~^\fIcomp, dist, forw, repl\fR
+.hl
+.ll +.9i
+.in 0
+.fi
+.pp
+Path
+.u should
+be present.
+Folder is maintained
+automatically by many MH commands (see the \*(lqContext\*(rq sections of
+the individual commands in Sec. V).
+All other entries are optional,
+defaulting to the values described above.
+.uh "MESSAGE NAMING"
+.pp
+Messages may be referred to explicitly or implicitly when
+using MH commands.
+A formal syntax of message names is given in Appendix C, but the
+following description should be sufficient for most MH users.
+Some details of message naming that apply only to certain
+commands are included in the description of those
+commands.
+.pp
+Most of the MH commands accept arguments specifying one or
+more folders, and one or more messages to operate on.
+The use of
+the word \*(lqmsg\*(rq as an argument to a command means that exactly one
+message name may be specified.
+A message name may be a number,
+such as 1, 33, or 234, or it may be
+one of the \*(lqreserved\*(rq message names:
+first, last, prev, next, and cur.
+(As a shorthand, a
+period (\*.) is equivalent to cur.)
+The meanings of these names
+are straightforward:  \*(lqfirst\*(rq is the first message in the
+folder; \*(lqlast\*(rq is the last
+message in the folder; \*(lqprev\*(rq is the
+message numerically previous to the current message; \*(lqnext\*(rq
+is the message numerically following the current message; \*(lqcur\*(rq
+(or \*(lq\*.\*(rq) is the current message in the folder.
+.pp
+The default in commands that take a \*(lqmsg\*(rq argument is
+always \*(lqcur\*(rq.
+.pp
+The word \*(lqmsgs\*(rq indicates that several messages may be
+specified.
+Such a specification consists of several message
+designations separated by spaces.
+A message designation is
+either a message name or a message range.
+A message range is a
+specification of the form name1\-name2 or name1:n, where name1 and
+name2 are message names and n is an integer.
+The first form
+designates all the messages from name1 to name2 inclusive; this
+must be a non-empty range.
+The second form specifies up to n
+messages, starting with name1 if name1 is a number, or first,
+cur, or next, and ending with name1 if name1 is last or
+prev.
+This interpretation of n is overridden if n is preceded
+by a plus sign or a minus sign;
++n always means up to n messages starting with
+name1, and \-n always means up to n messages ending with name1.
+Repeated specifications of the same message have the same effect
+as a single specification of
+the message.
+Examples of
+specifications are:
+
+.(b
+1 5 7\-11 22
+first 6 8 next
+first\-10
+last:5
+.)b
+.pp
+The message name \*(lqall\*(rq is a shorthand for \*(lqfirst\-last\*(rq,
+indicating all of the messages in the folder.
+.pp
+The limit on the number of messages in an expanded message
+list is generally 999\*-the maximum number of messages in a
+folder.
+However, the
+.i show
+command and the
+commands `\fIpick\0\-scan\fR' and `\fIpick\0\-show\fR'
+are constrained to have argument lists
+that are no more than 512 characters long.
+(Under Version 7 UNIX this limit is 4096.)
+.pp
+In commands that accept \*(lqmsgs\*(rq arguments, the default is
+either cur or all, depending on which makes more sense.
+.pp
+In all of the MH commands, a plus sign preceding an argument
+indicates a folder name.
+Thus, \*(lq+inbox\*(rq is the name of the
+user's standard inbox.
+If an explicit folder argument is given
+to an MH command, it will become the current folder (that is,
+the \*(lqCurrent-Folder:\*(rq entry
+in \*(lq\*.mh\(ruprofile\*(rq will be changed to this
+folder).
+In the case of the
+.i file
+and
+.i pick
+commands, which
+can have multiple output folders, a new source folder (other than
+the default current folder) is specified by \*(lq\-src\0+folder\*(rq.
+.uh "OTHER MH CONVENTIONS"
+.pp
+One very powerful feature of MH is that the MH commands may
+be issued from any current directory, and the proper path to
+the appropriate folder(s) will be taken from the user's profile.
+If the MH path is not appropriate for a specific folder or file,
+the automatic prepending of the MH path can be avoided by
+beginning a folder or file name with \fB/\fR.
+Thus any specific full
+path may be specified.
+.pp
+Arguments to the various programs may be given in any order,
+with the exception of a few switches whose arguments must follow
+immediately, such as \*(lq\-src\0+folder\*(rq for \fIpick\fR and \fIfile\fR.
+.pp
+Whenever an MH command prompts the user, the valid options
+will be listed in response to a <RETURN>.
+(The first of the
+listed options is the default if end-of-file is encountered, such
+as from a command file.)  A valid response is any \fIunique\fR
+abbreviation of one of the listed options.
+.pp
+Standard UNIX documentation conventions are used in this report
+to describe MH command syntax.
+Arguments enclosed in brackets
+([ ]) are optional; exactly one of the arguments enclosed
+within braces ({ }) must be specified, and all other
+arguments are required.
+The use of ellipsis dots (...) indicates
+zero or more repetitions of the previous item.
+For example,
+\*(lq+folder ...\*(rq would indicate that one or more \*(lq+folder\*(rq arguments
+is required and \*(lq[+folder ...]\*(rq indicates that 0 or more
+\*(lq+folder\*(rq arguments may be given.
+.pp
+MH departs from UNIX standards by using switches that consist of
+more than one character, e.g. \*(lq\-header\*(rq.
+To minimize typing,
+only a unique abbreviation of a switch need be typed; thus, for
+\*(lq\-header\*(rq, \*(lq\-hea\*(rq is probably sufficient, depending on the
+other switches the command accepts.
+Each MH program
+accepts the switch \*(lq\-help\*(rq (which \fImust\fR be spelled out fully)
+and produces a syntax description and a list of switches.
+In the
+list of switches, parentheses indicate required characters.
+For example, all \*(lq\-help\*(rq switches will appear as \*(lq\-(help)\*(rq,
+indicating that no abbreviation is accepted.
+.pp
+Many MH switches have both on and off forms, such as
+\*(lq\-format\*(rq and \*(lq\-noformat\*(rq.
+In many of the descriptions in Sec. V,
+only one form is defined; the other form, often used to
+nullify profile switch settings, is assumed to be the opposite.
+.br
+.bp
+.uh "MH COMMANDS"
+.pp
+The MH package comprises 16 programs:
+
+.nf
+.in .5i
+.ta 1.5i
+^comp~^Compose a message
+^dist~^Redistribute a message
+^file~^Move messages between folders
+^folder~^Select/list status of folders
+^forw~^Forward a message
+^inc~^Incorporate new mail
+^next~^Show the next message
+^pick~^Select a set of messages by context
+^prev~^Show the previous message
+^prompter~^Prompting editor front end for composing messages
+^repl~^Reply to a message
+^rmf~^Remove a folder
+^rmm~^Remove messages
+^scan~^Produce a scan listing of selected messages
+^send~^Send a previously composed message
+^show~^Show messages
+.fi
+.re
+.pp
+These programs are described below.
+The form of the descriptions
+conforms to the standard
+form for the description of UNIX commands.
+.if t \{
+.ll 6.5i
+.lt 6.5i
+\}
+.fo '7th Edition'UNIX/32V(Rand)''
+.de SC
+.he '\\$1(1)'-%-'\\$1(1)'
+.bp
+.(x
+.ti .8i
+\\$1
+.)x
+..
+.de NA
+.b \\s-2NAME\\s0
+.ti .5i
+..
+.de SY
+.sp
+.b \\s-2SYNOPSIS\\s0
+.in 1i
+.ti .5i
+.na
+..
+.de DE
+.ad
+.sp
+.in 0
+.b  \\s-2DESCRIPTION\\s0
+.sp
+.fi
+.in .5i
+..
+.de Fi
+.(b L
+.ti 0
+.b \\s-2Files\\s0
+.ta 2i
+..
+.de Pr
+.)b
+.(b L F
+.in 2.5i
+.ti 0
+.b "\\s-2Profile Components\\s0"
+.ti .5i
+..
+.de Ps
+.ti .5i
+..
+.de De
+.)b
+.(b L
+.in .5i
+.ti 0
+.b \\s-2Defaults\\s0
+..
+.de Co
+.)b
+.(b L F
+.ti 0
+.b \\s-2Context\\s0
+.br
+..
+.de En
+.)b
+.in 0
+..
+.SC COMP
+.NA
+comp \- compose a message
+
+.SY
+comp \%[\-editor\ editor] \%[\-form\ formfile] \%[file] \%[\-use]
+\%[\-nouse] \%[\-help]
+
+.DE
+\fIComp\fP is used to create a new message to be mailed.
+If
+\fIfile\fP is not specified, the file named \*(lqdraft\*(rq in the user's MH
+directory will be used.
+\fIComp\fR copies a message form to
+the file being composed and then invokes an editor on the
+file.
+The default editor is /bin/ned, which may be overridden with
+the `\-editor' switch or with a profile entry \*(lqEditor:\*(rq.
+(See Ref. 5 for a
+description of the NED text editing system.)
+The default
+message form contains the following elements:
+
+     To:
+     cc:
+     Subject:
+     ----------
+
+If the file named \*(lqcomponents\*(rq exists in the user's MH directory,
+it will be used instead of this form.
+If `\-form
+formfile' is specified, the specified formfile (from the MH
+directory) will be used as the skeleton.
+The line of dashes
+or a blank line must be left between the header and the
+body of the message for the message to be identified properly when it is
+sent (see \fIsend;\fR).
+The switch `\-use' directs \fIcomp\fR to
+continue editing an already started message.
+That is, if a
+\fIcomp\fR (or \fIdist\fR, \fIrepl\fR, or \fIforw\fR) is terminated without
+sending the message, the message can be edited again via
+\*(lqcomp \-use\*(rq.
+
+If the specified file (or draft) already exists, \fIcomp\fR will ask
+if you want to delete it before continuing.
+A reply of \fBNo\fR will abort the
+\fIcomp\fR, \fByes\fR will replace the existing draft with a blank
+skeleton, \fBlist\fR will display the draft, and \fBuse\fR will use it
+for further composition.
+
+Upon exiting from the editor, \fIcomp\fR will ask \*(lqWhat now?\*(rq.
+The valid
+responses are \fBlist\fR, to list the draft on the terminal; \fBquit\fR, to
+terminate the session and preserve the draft; \fBquit delete\fR, to terminate,
+then delete the draft; \fBsend\fR, to send the message; \fBsend verbose\fR, to
+cause the delivery process to be monitored; \fBedit <editor>\fR, to invoke
+<editor> for further editing; and \fBedit\fR, to re-edit using the
+same editor that was used on the preceding round unless a profile
+entry \*(lq<lasteditor>\-next: <editor>\*(rq names an alternative editor.
+
+.Fi
+^/etc/mh/components~^The message skeleton
+^or <mh-dir>/components~^Rather than the standard skeleton
+^$HOME/\*.mh\(ruprofile~^The user profile
+^<mh-dir>/draft~^The default message file
+^/usr/bin/send~^To send the composed message
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Editor:~^To override the use of /bin/ned as the default editor
+.Ps
+^<lasteditor>\-next:~^To name an editor to be used after exit from <lasteditor>
+.De
+`file' defaults to draft
+`\-editor' defaults to /bin/ned
+`\-nouse'
+.Co
+\fIComp\fR does not affect either the current folder or the current message.
+.En
+.SC DIST
+.NA
+dist \- redistribute a message to additional addresses
+.SY
+dist \%[+folder] \%[msg] \%[\-form\ formfile] \%[\-editor\ editor]
+\%[\-annotate] \%[\-noannotate]
+\%[\-inplace] \%[\-noinplace]
+\%[\-help]
+.DE
+\fIDist\fR is similar to \fIforw\fR.
+It prepares the specified
+message for redistribution to addresses that (presumably) are
+not on the original address list.
+The file \*(lqdistcomps\*(rq in the
+user's MH directory, or a standard form, or the file specified by
+`\-form formfile' will be used as the blank components file to
+be prepended to the message being distributed.
+The standard form
+has the components \*(lqDistribute-to:\*(rq and \*(lqDistribute-cc:\*(rq.
+When
+the message is sent, \*(lqDistribution-Date:\0date\*(rq,
+\*(lqDistribution-From:\0name\*(rq, and
+\*(lqDistribution-Id:\0id\*(rq (if `\-msgid' is
+specified to \fIsend\fR;) will be prepended to the outgoing message.
+Only those addresses in \*(lqDistribute-To\*(rq, \*(lqDistribute-cc\*(rq, and
+\*(lqDistribute-Bcc\*(rq will be sent.
+Also, a \*(lqDistribute-Fcc:\0folder\*(rq
+will be honored (see \fIsend;\fR).
+
+\fISend\fR recognizes a message as a redistribution message by the
+existence of the field \*(lqDistribute-To:\*(rq, so don't try to
+redistribute a message with only a \*(lqDistribute-cc:\*(rq.
+
+If the `\-annotate' switch is given, each message being
+distributed will be annotated with the lines:
+
+     Distributed:\0\*(<<date\*(>>
+     Distributed:\0Distribute-to: names
+
+where each \*(lqto\*(rq list contains as many lines as required.
+This annotation
+will be done only if the message is sent directly from \fIdist\fR.
+If the
+message is not sent immediately from \fIdist\fR (i.e., if it is sent later
+via \fIsend;\fR),
+\*(lqcomp \-use\*(rq may be used to re-edit and send the constructed message, but
+the annotations won't take place.
+The '\-inplace' switch causes annotation to
+be done in place in order to preserve links to the annotated message.
+
+See \fIcomp\fR for a description of the `\-editor' switch and for options
+upon exiting from the editor.
+
+.Fi
+^/etc/mh/components~^The message skeleton
+^or <mh-dir>/components~^Rather than the standard skeleton
+^$HOME/\*.mh\(ruprofile~^The user profile
+^<mh-dir>/draft~^The default message file
+^/usr/bin/send~^To send the composed message
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Editor:~^To override the use of /bin/ned as the default editor
+.Ps
+^<lasteditor>\-next:~^To name an editor to be used after exit from <lasteditor>
+.De
+`+folder' defaults to the current folder
+`msg' defaults to cur
+`\-editor' defaults to /bin/ned
+`\-noannotate'
+`\-noinplace'
+.Co
+If a +folder is specified, it will become the current
+folder, and the current message will be set to the message
+being redistributed.
+.En
+.SC FILE
+.NA
+file \- file message(s) in (an)other folder(s)
+.SY
+file \%[\-src\ +folder] \%[msgs] \%[\-link] \%[\-preserve] \%+folder\ ...
+\%[\-nolink] \%[\-nopreserve]
+\%[\-file\ file] \%[\-nofile] \%[\-help]
+.DE
+\fIFile\fR moves (\fImv\fR(I)) or links (\fIln\fR(I)) messages from a
+source folder into one or more destination folders.
+If you think
+of a message as a sheet of paper, this operation is not
+unlike filing the sheet of paper (or copies) in file cabinet
+folders.
+When a message is filed, it is linked into the
+destination folder(s) if possible, and is copied otherwise.
+As long
+as the destination folders are all on the same file system, multiple filing
+causes little storage overhead.
+This facility provides a good way to cross-file or multiply-index
+messages.
+For example, if a message is received from Jones about
+the ARPA Map Project, the command
+
+     file\0cur\0+jones\0+Map
+
+would allow the message to be found in either of the two
+folders `jones' or `Map'.
+
+The option `\-file file' directs \fIfile\fR to use the specified
+file as the source message to be filed, rather than a message from
+a folder.
+
+If a destination folder doesn't exist, \fIfile\fR will ask if you
+want to create one.
+A negative response will abort the file
+operation.
+
+`\-link' preserves the source folder copy of the message
+(i.e., it does a \fIln\fR(I) rather than a \fImv\fR(I)), whereas,
+`\-nolink' deletes the \*(lqfiled\*(rq messages from the source
+folder.
+Normally, when a message is filed, it is assigned the
+next highest number available in each of the destination folders.
+Use of the `\-preserve' switch will override this message
+\*(lqrenaming\*(rq, but name conflicts may occur, so
+use this switch cautiously.
+(See \fIpick\fR for more details on
+message numbering.)
+
+If `\-link' is not specified (or `\-nolink' is specified),
+the filed messages will be removed (unlink(II)) from the
+source folder.
+
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Current-Folder:~^To find the default current folder
+.Ps
+^Folder\-Protect:~^To set mode when creating a new folder
+.De
+`\-src +folder' defaults to the current folder
+`msgs' defaults to cur
+`\-nolink'
+`\-nopreserve'
+`\-nofile'
+.Co
+If `\-src +folder' is given, it will become the
+current folder for future MH commands.
+If neither `\-link' nor
+`all' are specified, the current message in the source
+folder will be set to the last message specified; otherwise, the
+current message won't be changed.
+.En
+.SC FOLDER
+.NA
+folder \- set/list current folder/message
+.SY
+folder \%[+folder] \%[msg] \%[\-all] \%[\-fast] \%[\-nofast] \%[\-up] \%[\-down]
+\%[\-header] \%[\-noheader] \%[\-total] \%[\-nototal] \%[\-pack] \%[\-nopack]
+\%[\-help]
+
+.ti .5i
+folders  <equivalent to 'folder \-all'>
+.DE
+Since the MH environment is the shell, it is easy to lose
+track of the current folder from day to day.
+\fIFolder\fR will
+list the current folder, the number of messages in it, the
+range of the messages (low-high), and the current message within
+the folder, and will flag a selection list or extra files if they
+exist.
+An example of the output is:
+
+      inbox+ has 16 messages ( 3\- 22); cur= 5.
+
+If a `+folder' and/or `msg' are specified, they will
+become the current folder and/or message.
+An `\-all' switch
+will produce a line for each folder in the user's MH directory,
+sorted alphabetically.
+These folders are preceded by the read-only
+folders, which occur as \*.mh\(ruprofile \*(lqcur\-\*(rq entries.
+For example,
+
+.nf
+.ta 1.5i 2.1i 2.7i 3.5i
+^~Folder\ \ ^^~#\ of\ ^^messages~^^(~\ range\~ );\ ^cur msg (other files)
+^~/fsd/rs/m/tacc\ \ ^^has~35\ ^^messages~^^(~1\-\035);\ ^cur=\ 23.
+^~/rnd/phyl/Mail/EP\ \ ^^has~82\ ^^messages~^^(~1\-108);\ ^cur=\ 82.
+^~f\&f\ \ ^^has~4\ ^^messages~^^(~1\-\0\04);\ ^cur=\ \01.
+^~inbox+\ ^^has~16\ ^^messages~^^(~3\-\022);\ ^cur=\ \05.
+^~mh\ \ ^^has~76\ ^^messages~^^(~1\-\076);\ ^cur=\ 70.
+^~notes\ \ ^^has~2\ ^^messages~^^(~1\-\0\02);\ ^cur=\ \01.
+^~ucom\ \ ^^has~124\ ^^messages~^^(~1\-124);\ ^cur=\ \06; (select).
+
+^^^~TOTAL=\0339\ ^messages\0in\0\07\0Folders.
+.re
+.fi
+
+The \*(lq+\*(rq after inbox indicates that it is the current folder.
+The \*(lq(select)\*(rq indicates that the folder ucom has a selection
+list produced by \fIpick\fR.
+If \*(lqothers\*(rq had appeared in parentheses at
+the right of a line, it would indicate that there are files in
+the folder directory that don't belong under the MH file naming
+scheme.
+
+The header is output if either an `\-all' or a `\-header' switch
+is specified; it is suppressed by `\-noheader'.
+Also, if \fIfolder\fR
+is invoked by a name ending with \*(lqs\*(rq (e.g., \fIfolders\fR),
+`\-all' is assumed.
+A `\-total' switch will produce only the
+summary line.
+
+If `\-fast' is given, only the folder name (or names in the
+case of `\-all') will be listed.
+(This is faster because the
+folders need not be read.)
+
+The switches `\-up' and `\-down' change the folder to be the
+one above or below the current folder.
+That is, \*(lqfolder \-down\*(rq
+will set the folder to \*(lq<current\-folder>/select\*(rq, and if the
+current folder is a selection-list folder, \*(lqfolder \-up\*(rq will
+set the current folder to the parent of the selection-list.
+(See \fIpick\fR for details on selection-lists.)
+
+The `\-pack' switch will compress the message names in a folder, removing
+holes in message numbering.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+^/bin/ls~^To fast-list the folders
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+`+folder' defaults to the current folder
+`msg' defaults to none
+`\-nofast'
+`\-noheader'
+`\-nototal'
+`\-nopack'
+.Co
+If `+folder' and/or `msg' are given, they will become the
+current folder and/or message.
+.En
+.SC FORW
+.NA
+forw \- forward messages
+.SY
+forw \%[+folder] \%[msgs] \%[\-editor\ editor] \%[\-form\ formfile]
+\%[\-annotate] \%[\-noannotate]
+\%[\-inplace]  \%[\-noinplace]
+\%[\-help]
+.DE
+\fIForw\fR may be used to prepare a message containing other
+messages.
+It constructs the new message from the components file
+or `\-form formfile' (see \fIcomp\fR), with a body composed of the
+message(s) to be forwarded.
+An editor is invoked as in \fIcomp\fR,
+and after editing is complete, the user is prompted before the message
+is sent.
+
+If the `\-annotate' switch is given, each message being
+forwarded will be annotated with the lines
+
+     Forwarded: \*(<<date\*(>>
+     Forwarded: To: names
+     Forwarded: cc: names
+
+where each \*(lqTo:\*(rq and \*(lqcc:\*(rq list contains as many lines as required.
+This annotation will be done only if the message is sent directly
+from \fIforw\fR.
+If the message is not sent immediately from \fIforw\fR,
+\*(lqcomp \-use\*(rq may be used in a later session to re-edit and send
+the constructed message, but the annotations won't take place.
+The `\-inplace' switch permits annotating a message in place in
+order to preserve its links.
+
+See \fIcomp\fR for a description of the `\-editor' switch.
+.Fi
+^/etc/mh/components~^The message skeleton
+^or <mh-dir>/components~^Rather than the standard skeleton
+^$HOME/\*.mh\(ruprofile~^The user profile
+^<mh-dir>/draft~^The default message file
+^/usr/bin/send~^To send the composed message
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Editor:~^To override the use of /bin/ned as the default editor
+.Ps
+^Current-Folder:~^To find the default current folder
+.Ps
+^<lasteditor>\-next:~^To name an editor to be used after exit from <lasteditor>
+.De
+`+folder' defaults to the current folder
+`msgs' defaults to cur
+`\-editor' defaults to /bin/ned
+`\-noannotate'
+`\-noinplace'
+.Co
+If a +folder is specified, it will become
+the current folder, and the current message will be set to
+the first message being forwarded.
+.En
+.SC INC
+.NA
+inc \- incorporate new mail
+.SY
+inc \%[+folder] \%[\-audit\ audit-file] \%[\-help]
+.DE
+\fIInc\fR incorporates mail from the user's incoming mail drop
+(\*.mail) into an MH folder.
+If `+folder' isn't specified,
+the folder named \*(lqinbox\*(rq in the user's MH directory will be used.
+The
+new messages being incorporated are assigned numbers starting
+with the next highest number in the folder.
+If the specified (or
+default) folder doesn't exist, the user will be queried prior to
+its creation.
+As the messages are processed, a \fIscan\fR  listing
+of the new mail is produced.
+
+If the user's profile contains a \*(lqMsg\-Protect: nnn\*(rq entry, it
+will be used as the protection on the newly created messages,
+otherwise the MH default of 664 will be used.
+During all
+operations on messages, this initially assigned protection will
+be preserved for each message, so \fIchmod\fR(I) may be used to set a
+protection on an individual message, and its protection will be
+preserved thereafter.
+
+If the switch `\-audit audit-file' is specified (usually as a
+default switch in the profile), then \fIinc\fR will append a header
+line and a line per message to the end of the specified
+audit-file with the format:
+
+.nf
+.ti 1i
+\*(<<inc\*(>> date
+.ti 1.5i
+<scan line for first message>
+.ti 1.5i
+<scan line for second message>
+.ti 2.5i
+<etc.>
+.fi
+
+This is useful for keeping track of volume and source of incoming
+mail.
+Eventually, \fIrepl\fR, \fIforw\fR, \fIcomp\fR, and \fIdist\fR may also
+produce audits to this (or another) file, perhaps with
+\*(lqMessage-Id:\*(rq information to keep an exact correspondence history.
+\*(lqAudit-file\*(rq will be in the user's MH directory unless a full
+path is specified.
+
+\fIInc\fR will incorporate even illegally formatted messages into the
+user's MH folder, inserting a blank line prior to the offending
+component and printing a comment identifying the bad message.
+
+In all cases, the \*.mail file will be zeroed.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+^$HOME/\*.mail~^The user's mail drop
+^<mh-dir>/audit-file~^Audit trace file (optional)
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Folder\-Protect:~^For protection on new folders
+.Ps
+^Msg\-Protect:~^For protection on new messages
+.De
+`+folder' defaults to \*(lqinbox\*(rq
+.Co
+The folder into which the message is
+being incorporated will become the
+current folder, and the first message incorporated will be the
+current message.
+This leaves the context ready for a \fIshow\fR
+of the first new message.
+.En
+.SC NEXT
+.NA
+next \- show the next message
+.SY
+next \%[+folder] \%[\-switches\ for\ \fIl\fR] \%[\-help]
+.DE
+\fINext\fR performs a \fIshow\fR on the next message in the
+specified (or current) folder.
+Like \fIshow\fR, it passes any
+switches on to the program \fIl\fR, which is called to list the
+message.
+This command is exactly equivalent to \*(lqshow next\*(rq.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+.Co
+If a folder is specified, it will become the current folder, and the
+message that is shown (i.e., the next message in sequence)
+will become the current message.
+.En
+.SC PICK
+.NA
+pick \- select messages by content
+.SY
+.ta .4i 1.8i
+.nf
+.in .5i
+^pick~^^\0\-cc~^ \%[\-src\ +folder] \%[msgs] \%[\-help] \%[\-scan] \%[\-noscan]
+^^^\0\-date~^   \%[\-show] \%[\-noshow] \%[\-nofile] \%[\-nokeep]
+^^^\0\-from~^
+^^^\s+2\b'\(lt\(bv\(bv\(lk\(bv\(bv\(lb'\s0 \-search~\s+2\b'\(rt\(bv\(bv\(rk\(bv\(bv\(rb'\s0^ pattern
+^^^\0\-subject~^
+^^^\0\-to~^ \%[\-file \%[\-preserve] \%[\-link] \%+folder\ ... \%[\-nopreserve] \%[\-nolink] ]
+^^^\0\-\-component~^ \%[\-keep \%[\-stay] \%[\-nostay] \%[+folder\ ...]\ ]
+.fi
+
+.re
+.ti .5i
+typically:
+.in 1i
+pick\0\-from\0jones\0\-scan
+.br
+pick\0\-to\0holloway
+.br
+pick\0\-subject\0ned\0\-scan\0\-keep
+.DE
+\fIPick\fR searches messages within a folder for the specified
+contents, then performs several operations on the selected
+messages.
+
+A modified \fIgrep\fR(I) is used to perform the searching, so the
+full regular expression (see \fIed\fR(I)) facility is available
+within `pattern'.
+With `\-search', pattern is used directly,
+and with the others, the grep pattern constructed is:
+
+.ti +.5i
+\*(lq^component:\*.\*(**pattern\*(rq
+
+This means that the pattern specified for a `\-search' will be
+found everywhere in the message, including the header and the body,
+while the other search requests are limited to the single
+specified component.
+The expression `\-\-component pattern'
+is a shorthand for
+specifying `\-search \*(lqcomponent:\*.\*(**pattern\*(rq\ '; it is used to pick
+a component not in the set [cc date from subject to].
+An
+example is \*(lqpick \-\-reply\-to pooh \-show\*(rq.
+
+Searching is performed on a per-line basis.
+Within the header of
+the message, each component is treated as one long line, but in
+the body, each line is separate.
+Lower-case letters in the
+search pattern will match either lower or upper case in the
+message, while upper case will match only upper case.
+
+Once the search has been performed, the selected messages
+are scanned (see \fIscan\fR) if the `\-scan' switch is given, and
+then they are shown (see \fIshow\fR) if the `\-show' switch is
+given.
+After these two operations, the file operations (if
+requested) are performed.
+
+The `\-file' switch operates exactly like the \fIfile\fR command, with the
+same meaning for the `\-preserve' and `\-link' switches.
+
+The `\-keep' switch is similar to `\-file', but it produces a folder that
+is a subfolder of the folder being searched and defines it as
+the current folder (unless the `\-stay' flag is used).
+This
+subfolder contains the messages which matched the search
+criteria.
+All of the MH commands may be used with the sub-folder
+as the current folder.
+This gives the user considerable power
+in dealing with subsets of messages in a folder.
+
+The messages in a folder produced by `\-keep' will always have the
+same numbers as they have in the source folder (i.e., the
+`\-preserve' switch is automatic).
+This way, the message
+numbers are consistent with the folder from which the messages
+were selected.
+Messages are not removed from the source folder
+(i.e., the `\-link' switch is assumed).
+If a `+folder' is not
+specified, the standard name \*(lqselect\*(rq will be used.
+(This is the
+meaning of \*(lq(select)\*(rq when it appears in the output of the
+\fIfolder\fR command.) If `+folder' arguments are given to
+`\-keep', they will be used rather than \*(lqselect\*(rq for the names
+of the subfolders.
+This allows for several subfolders to be
+maintained concurrently.
+
+When a `\-keep' is performed, the subfolder becomes the current folder.
+This can be overridden by use
+of the `\-stay' switch.
+
+Here's an example:
+
+.nf
+\01  % folder +inbox
+\02           inbox+ has  16 messages (  3\- 22); cur=  3.
+\03  % pick \-from dcrocker
+\04  6 hits.
+\05  [+inbox/select now current]
+\06  % folder
+\07    inbox/select+ has  \06 messages (  3\- 16); cur=  3.
+\08  % scan
+.ds p \\h'\\w'+'u'
+\09   \03+  6/20   Dcrocker          Re: ned file update issue...
+10   \06\*p  6/23   Dcrocker          removal of files from /tm...
+11   \08\*p  6/27   Dcrocker          Problems with the new ned...
+12   13\*p  6/28   d\h'\w'D'u-\w'd'u'crocker          newest nned  \*(<<I would ap...
+13   15\*p  7/\05   Dcrocker          nned  \*(<<Last week I asked...
+14   16\*p  7/\05   d\h'\w'D'u-\w'd'u'crocker          message id format  \*(<<I re...
+15  % show all | print
+16     [produce a full listing of this set of messages on the line printer.]
+17  % folder \-up
+18            inbox+ has  16 messages (  3\- 22); cur=  3; (select).
+19  % folder \-down
+20   inbox/select+ has   6 messages (  3\- 16); cur=  3.
+21  % rmf
+22  [+inbox now current]
+23  % folder
+24            inbox+ has  16 messages (  3\- 22); cur=  3.
+.fi
+
+This is a rather lengthy example, but it shows the power of the
+MH package.
+In item 1, the current folder is set to inbox.
+In 3,
+all of the messages from dcrocker are found in inbox and linked
+into the folder \*(lqinbox/select\*(rq.
+(Since no action switch is
+specified, `\-keep' is assumed.)  Items 6 and 7 show that this
+subfolder is now the current folder.
+Items 8 through 14 are a
+\fIscan\fR of the selected messages (note that they are all from dcrocker
+and are all in upper and lower case).
+Item 15 lists all of the messages to
+the high-speed printer.
+Item 17 directs \fIfolder\fR to set the
+current folder to the parent of the selection-list folder, which
+is now current.
+Item 18 shows that this has been done.
+Item 19 resets
+the current folder to the selection list, and 21 removes the
+selection-list folder and resets the current folder to the
+parent folder, as shown in 22 and 23.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Folder\-Protect:~^For protection on new folders
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+`\-src +folder' defaults to current
+`msgs' defaults to all
+.fi
+`\-keep +select' is the default if no `\-scan', `\-show', or `\-file' is specified
+.Co
+If a `\-src +folder' is specified, it will
+become the current folder, unless a `\-keep' with 0 or 1
+folder arguments makes the selection-list subfolder the
+current folder.
+Each selection-list folder will have its
+current message set to the first of the messages linked into
+it unless the selection list already existed, in which case the
+current message won't be changed.
+.En
+.SC PREV
+.NA
+prev \- show the previous message
+.SY
+prev \%[+folder] \%[\-switches\ for\ \fIl\fR] \%[\-help]
+.DE
+\fIPrev\fR performs a \fIshow\fR on the previous message in the specified
+(or current) folder.
+Like \fIshow\fR, it passes any switches on to the
+program \fIl\fR, which is called to list the message.
+This command
+is exactly equivalent to \*(lqshow prev\*(rq.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+.Co
+If a folder is specified, it will become current, and the
+message that is shown (i.e., the previous message in sequence)
+will become the current message.
+.En
+.SC PROMPTER
+.NA
+prompter \- prompting editor front end
+.SY
+This program is not called directly but takes the place
+of an editor and acts as an editor front end.
+
+.ti .5i
+prompter \%[\-erase\ chr] \%[\-kill\ chr] \%[\-help]
+.DE
+\fIPrompter\fR is an editor which allows rapid composition of
+messages.
+It is particularly useful to network and low-speed
+(less than 2400 baud) users of MH.
+It is an MH program in that
+it can have its own profile entry with switches, but it can't
+be invoked directly as all other MH commands can; it is an editor
+in that it is invoked by an \*(lq\-editor prompter\*(rq switch or by the
+profile entry \*(lqEditor: prompter\*(rq, but functionally it is merely
+a text-collector and not a true editor.
+
+\fIPrompter\fR expects to be called from \fIcomp\fR, \fIrepl\fR, \fIdist\fR, or
+\fIforw\fR, with a draft file as an argument.
+For example, \*(lqcomp
+\-editor prompter\*(rq will call \fIprompter\fR with the file \*(lqdraft\*(rq already set
+up with blank components.
+For each blank component it finds in
+the draft, it prompts the user and accepts a response.
+A
+<RETURN> will cause the whole component to be left out.
+A \*(lq\\\*(rq
+preceding a <RETURN> will continue the response on the next line,
+allowing for multiline components.
+
+Any component that is non-blank will be copied and echoed to the
+terminal.
+
+The start of the message body is prompted by a line of
+dashes.
+If the body is non-blank, the prompt is
+\*(lq--------Enter additional text\*(rq.
+Message-body typing is terminated with
+a <CTRL-D> (or <OPEN>).
+Control is returned to the calling
+program, where the user is asked \*(lqWhat now?\*(rq.
+See \fIcomp\fR for
+the valid options.
+
+The line editing characters for kill and erase may be
+specified by the user via the arguments \*(lq\-kill chr\*(rq and \*(lq\-erase
+chr\*(rq, where chr may be a character; or \*(lq\\nnn\*(rq, where nnn is the
+octal value for the character.
+(Again, these may come from the
+default switches specified in the user's profile.)
+
+A <DEL> during message-body typing is equivalent to
+<CTRL-D> for compatibility with NED.
+A <DEL> during
+component typing will abort the command that invoked
+\fIprompter\fR.
+.Fi
+None
+.Pr
+^prompter-next:~^To name the editor to be used on exit from \fIprompter\fR
+.De
+.Co
+None
+.En
+.SC REPL
+.NA
+repl \- reply to a message
+.SY
+repl \%[+folder] \%[msg] \%[\-editor\ editor] \%[\-inplace] \%[\-annotate]
+\%[\-help] \%[\-noinplace]
+\%[\-noannotate]
+.DE
+\fIRepl\fR aids a user in producing a reply to an existing
+message.
+In its simplest form (with no arguments), it will set up
+a message-form skeleton in reply to the current message in the
+current folder, invoke the editor, and send the composed
+message if so directed.
+The composed message is constructed as
+follows:
+
+.nf
+.in 1i
+To: <Reply-To> or <From>
+cc: <cc>, <To>
+Subject: Re: <Subject>
+In-reply-to: Your message of <Date>
+.ti +\w'In-reply-to: 'u
+<Message-Id>
+.in .5i
+.fi
+
+where field names enclosed in angle brackets (< >) indicate the
+contents of the named field from the message to which the reply
+is being made.
+Once the skeleton is constructed, an editor is
+invoked (as in \fIcomp\fR, \fIdist\fR, and \fIforw\fR).
+While in the editor,
+the message being replied to is available through a link named
+\*(lq@\*(rq.
+In NED, this means the replied-to message may be \*(lqused\*(rq
+with \*(lquse @\*(rq, or put in a window by \*(lqwindow @\*(rq.
+
+As in \fIcomp\fR, \fIdist\fR, and \fIforw\fR, the user will be queried
+before the message is sent.
+If `\-annotate' is
+specified, the replied-to message will be annotated with the
+single line
+
+.ti +.5i
+Replied: \*(<<Date\*(>>.
+
+The command
+\*(lqcomp \-use\*(rq may be used to pick up interrupted editing, as in
+\fIdist\fR and \fIforw\fR; the `\-inplace' switch annotates the message in place,
+so that all folders with links to it will see the annotation.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+^<mh-dir>/draft~^The constructed message file
+^/usr/bin/send~^To send the composed message
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Editor:~^To override the use of /bin/ned as the default editor
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+`+folder' defaults to current
+`msgs' defaults to cur
+`\-editor' defaults to /bin/ned
+`\-noannotate'
+`\-noinplace'
+.Co
+If a `+folder' is specified, it will become the current
+folder, and the current message will be set to the replied-to
+message.
+.sp 2
+.En
+.SC RMF
+.NA
+rmf \- remove folder
+.SY
+rmf \%[+folder] \%[\-help]
+.DE
+\fIRmf\fR removes all of the files (messages) within the specified
+(or default) folder, and then removes the directory (folder).
+If
+there are any files within the folder which are not a part of MH,
+they will \fInot\fR be removed, and an error will be produced.
+If the
+folder is given explicitly or the current folder is a
+subfolder (i.e., a selection list from \fIpick\fR), it will be
+removed without confirmation.
+If no argument is specified and
+the current folder is not a selection-list folder, the
+user will be asked for confirmation.
+
+\fIRmf\fR irreversibly deletes messages that don't have other links,
+so use it with caution.
+
+If the folder being removed is a subfolder, the parent
+folder will become the new current folder, and \fIrmf\fR will
+produce a message telling the user this has happened.
+This
+provides an easy mechanism for selecting a set of messages,
+operating on the list, then removing the list and returning to
+the current folder from which the list was extracted.
+(See the
+example under \fIpick\fR.)
+
+The files that \fIrmf\fR will delete are cur, any file beginning
+with a comma, and files with purely numeric names.
+All others
+will produce error messages.
+
+\fIRmf\fR of a read-only folder will delete the \*(lqcur\-\*(rq entry from the
+profile without affecting the folder itself.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+`+folder' defaults to current, usually with confirmation
+.Co
+\fIRmf\fR will set the current folder to the parent folder if a
+subfolder is removed; or if the current folder is removed,
+it will make \*(lqinbox\*(rq current.
+Otherwise, it doesn't change the
+current folder or message.
+.En
+.SC RMM
+.NA
+rmm \- remove messages
+.SY
+rmm \%[+folder] \%[msgs] \%[\-help]
+.DE
+\fIRmm\fR removes the specified messages by renaming the message
+files with preceding commas.
+(This is the Rand-UNIX backup file
+convention.)
+
+The current message is not changed by \fIrmm\fR, so a \fInext\fR  will
+advance to the next message in the folder as expected.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+`+folder' defaults to current
+`msgs' defaults to cur
+.Co
+If a folder is given, it will become current.
+.En
+.SC SCAN
+.NA
+scan \- produce a one-line-per-message scan listing
+.SY
+scan \%[+folder] \%[msgs] \%[\-f\&f] \%[\-header] \%[\-help]
+\%[\-nof\&f] \%[\-noheader]
+.DE
+\fIScan\fR produces a one-line-per-message listing of the specified
+messages.
+Each \fIscan\fR line contains the message number (name),
+the date, the \*(lqFrom\*(rq field, the \*(lqSubject\*(rq field, and, if room
+allows, some of the body of the message.
+For example:
+
+.nf
+.ta .5i 1.2i 2.6i
+^ #~^^Date~^^  From~^Subject\ \ \ \ \[\*(<<Body]
+^15+~^^7/\05~^^Dcrocker~^nned  \*(<<Last week I asked some of
+^16\ \-~^^7/\05~^^dcrocker~^message id format  \*(<<I recommend
+^18~^^7/\06~^^Obrien~^Re: Exit status from mkdir
+^19~^^7/\07~^^Obrien~^"scan" listing format in MH
+.re
+.fi
+
+The `+' on message 15 indicates that it is the current message.
+The `\-' on message 16 indicates that it has been
+replied to, as indicated by a \*(lqReplied:\*(rq component produced by
+an `\-annotate' switch to the \fIrepl\fR command.
+
+If there is sufficient room left on the \fIscan\fR line after the
+subject, the line will be filled with text from the body,
+preceded by \*(<<.
+\fIScan\fR actually reads each of the specified
+messages and parses them to extract the desired fields.
+During parsing, appropriate error messages will be produced if
+there are format errors in any of the messages.
+
+The `\-header' switch produces a header line prior to the \fIscan\fR
+listing, and the `\-f\&f' switch will cause a form feed to be
+output at the end of the \fIscan\fR listing.
+See Appendix D.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+Defaults:
+`+folder' defaults to current
+`msgs' defaults to all
+`\-nof\&f'
+`\-noheader'
+.Co
+If a folder is given, it will become current.
+The current
+message is unaffected.
+.En
+.SC SEND
+.NA
+send \- send a message
+.SY
+send \%[file] \%[\-draft] \%[\-verbose] \%[\-format] \%[\-msgid]
+\%[\-help]  \%[\-noverbose] \%[\-noformat] \%[\-nomsgid]
+.DE
+\fISend\fR will cause the specified file (default <mh-dir>/draft) to
+be delivered to each of the addresses in the \*(lqTo:\*(rq, \*(lqcc:\*(rq, and \*(lqBcc:\*(rq
+fields of the message.
+If `\-verbose' is specified, \fIsend;\fR
+will monitor the delivery of local and net mail.
+\fISend\fR with no
+argument will query whether the draft is the intended file, whereas
+`\-draft' will suppress this question.
+Once the message has
+been mailed (or queued) successfully, the file will be renamed
+with a leading comma, which allows it to be retreived until the
+next draft message is sent.
+If there are errors in the
+formatting of the message, \fIsend;\fR will abort with a (hopefully)
+helpful error message.
+
+If a \*(lqBcc:\*(rq field is encountered, its addresses will be used for
+delivery, but the \*(lqBcc:\*(rq field itself will be deleted from all
+copies of the outgoing message.
+
+Prior to sending the message, the fields \*(lqFrom:  user\*(rq, and
+\*(lqDate: now\*(rq will be prepended to the message.
+If `\-msgid' is
+specified, then a \*(lqMessage-Id:\*(rq field will also be added to the
+message.
+If the message already contains a \*(lqFrom:\*(rq field, then a
+\*(lqSender: user\*(rq field will be added instead.
+(An already existing
+\*(lqSender:\*(rq field will be deleted from the message.)
+
+If the user doesn't specify `\-noformat', each of the entries in
+the \*(lqTo:\*(rq and \*(lqcc:\*(rq fields will be replaced with \*(lqstandard\*(rq format
+entries.
+This standard format is designed to be usable by all
+of the message handlers on the various systems around the
+ARPANET.
+
+If an \*(lqFcc: folder\*(rq is encountered, the message will be copied
+to the specified folder in the format in which it will appear to any
+receivers of the message.
+That is, it will have the prepended
+fields and field reformatting.
+
+If a \*(lqDistribute-To:\*(rq field is encountered, the message
+is handled as a redistribution message (see \fIdist\fR for
+details), with \*(lqDistribution-Date: now\*(rq and \*(lqDistribution-From: user\*(rq
+added.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+.Pr
+^Path:~^To determine the user's MH directory
+.De
+`file' defaults to draft
+`\-noverbose'
+`\-format'
+`\-nomsgid'
+.Co
+\fISend\fR has no effect on the current message or folder.
+.En
+.SC SHOW
+.NA
+show \- show (list) messages
+.SY
+show \%[+folder] \%[msgs] \%[\-pr] \%[\-nopr] \%[\-draft] \%[\-help]
+\%[\fIl\fR\ or\ \fIpr\fR\ switches]
+.DE
+\fIShow\fR lists each of the specified messages to the standard
+output (typically, the terminal).
+The messages are listed exactly
+as they are, with no reformatting.
+A program called \fIl\fR is
+invoked to do the listing, and any switches not recognized by
+\fIshow\fR are passed along to \fIl\fR.
+
+If no \*(lqmsgs\*(rq are specified, the current message is used.
+If
+more than one message is specified, \fIl\fR will prompt for a
+<return> prior to listing each message.
+
+\fIl\fR will list each message, a page at a time.
+When the end of
+page is reached, \fIl\fR will ring the bell and wait for a <RETURN>
+or <CTRL-D>.
+If a <return> is entered, \fIl\fR will clear the
+screen before listing the next page, whereas <CTRL-D> will not.
+The switches to \fIl\fR are
+`\-p#' to indicate the page length in lines, and `\-w#' to
+indicate the width of the page in characters.
+
+If the standard output is not a terminal, no queries are made,
+and each file is listed with a one-line header and two lines of
+separation.
+
+If `\-pr' is specified, then \fIpr\fR(I) will be invoked rather than
+\fIl\fR, and the switches (other than `\-draft') will be passed
+along.
+\*(lqShow \-draft\*(rq will list the file <mh-dir>/draft if it
+exists.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+^/bin/l~^Screen-at-a-time list program
+^/bin/pr~^\fIpr\fR(I)
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+`+folder' defaults to current
+`msgs' defaults to cur
+`\-nopr'
+.Co
+If a folder is given, it will become the current message.
+The last message
+listed will become the current message.
+.En
+\"
+\"              On to the Appendices
+\"
+.fo ''-%-''
+.he ''''
+.(x
+.sp
+Appendix
+.)x _
+.de $c                          \" Major Heading printer
+.ce
+Appendix \\n+(ch
+.sp 2p
+.ce
+.b "\\s12\\$1\\s0"              \" 12 Point Bold Header
+.(x
+\ \ \ \\n(ch.\\ \\ \\$2
+.)x
+.sp 45p                                \" 45 points or about 1/2 inch
+..
+.++ A
+.bp
+.$c "COMMAND SUMMARY\\**" "Command Summary"
+.(f
+\**All commands accept a \-help switch.
+.)f
+.in 1i
+.na
+.ti .5i
+comp \%[\-editor\ editor] \%[\-form\ formfile] \%[file] \%[\-use]
+\%[\-nouse] \%[\-help]
+
+.ti .5i
+dist \%[+folder] \%[msg] \%[\-form\ formfile] \%[\-editor\ editor]
+\%[\-annotate] \%[\-noannotate]
+\%[\-inplace] \%[\-noinplace]
+\%[\-help]
+
+.ti .5i
+file \%[\-src\ +folder] \%[msgs] \%[\-link] \%[\-preserve] \%+folder\ ...
+\%[\-nolink] \%[\-nopreserve]
+\%[\-file\ file] \%[\-nofile] \%[\-help]
+
+.ti .5i
+folder \%[+folder] \%[msg] \%[\-all] \%[\-fast] \%[\-nofast] \%[\-up] \%[\-down]
+\%[\-header] \%[\-noheader] \%[\-total] \%[\-nototal] \%[\-pack] \%[\-nopack]
+\%[\-help]
+
+.ti .5i
+forw \%[+folder] \%[msgs] \%[\-editor\ editor] \%[\-form\ formfile]
+\%[\-annotate] \%[\-noannotate]
+\%[\-inplace]  \%[\-noinplace]
+\%[\-help]
+
+.ti .5i
+inc \%[+folder] \%[\-audit\ audit-file] \%[\-help]
+
+.ti .5i
+next \%[+folder] \%[\-switches\ for\ \fIl\fR] \%[\-help]
+
+.ta .4i 1.8i
+.nf
+.in .5i
+^pick~^^\0\-cc~^ \%[\-src\ +folder] \%[msgs] \%[\-help] \%[\-scan] \%[\-noscan]
+^^^\0\-date~^   \%[\-show] \%[\-noshow] \%[\-nofile] \%[\-nokeep]
+^^^\0\-from~^
+^^^\s+2\b'\(lt\(bv\(bv\(lk\(bv\(bv\(lb'\s0 \-search~\s+2\b'\(rt\(bv\(bv\(rk\(bv\(bv\(rb'\s0^ pattern
+^^^\0\-subject~^
+^^^\0\-to~^ \%[\-file \%[\-preserve] \%[\-link] \%+folder\ ... \%[\-nopreserve] \%[\-nolink] ]
+^^^\0\-\-component~^ \%[\-keep \%[\-stay] \%[\-nostay] \%[+folder\ ...]\ ]
+.fi
+.re
+
+.ti .5i
+prev \%[+folder] \%[\-switches\ for\ \fIl\fR] \%[\-help]
+
+.ti .5i
+prompter \%[\-erase\ chr] \%[\-kill\ chr] \%[\-help]
+
+.ti .5i
+repl \%[+folder] \%[msg] \%[\-editor\ editor] \%[\-inplace] \%[\-annotate]
+\%[\-help] \%[\-noinplace]
+\%[\-noannotate]
+
+.ti .5i
+rmf \%[+folder] \%[\-help]
+
+.ti .5i
+rmm \%[+folder] \%[msgs] \%[\-help]
+
+.ti .5i
+scan \%[+folder] \%[msgs] \%[\-f\&f] \%[\-header] \%[\-help]
+\%[\-nof\&f] \%[\-noheader]
+
+.ti .5i
+send \%[file] \%[\-draft] \%[\-verbose] \%[\-format] \%[\-msgid]
+\%[\-help]  \%[\-noverbose] \%[\-noformat] \%[\-nomsgid]
+
+.ti .5i
+show \%[+folder] \%[msgs] \%[\-pr] \%[\-nopr] \%[\-draft] \%[\-help]
+\%[\fIl\fR\ or\ \fIpr\fR\ switches]
+.ad
+.in 0
+\".+c "MESSAGE FORMAT" "Message Format"
+.if t \{
+.ll 32P
+.lt 32P
+\}
+.bp
+.$c "MESSAGE FORMAT" "Message Format"
+.pp
+This section paraphrases the format of ARPANET text messages
+given in Ref. 6.
+
+.lp
+ASSUMPTIONS
+.np
+Messages
+are expected to consist of lines of text.
+Graphics and binary data are not handled.
+.np
+No data compression is accepted.
+All text is clear
+ASCII 7-bit data.
+
+.lp
+LAYOUT
+.lp
+A general \*(lqmemo\*(rq framework is used.
+A message consists of a
+block of information in a rigid format, followed by general
+text with no specified format.
+The rigidly formatted  first
+part of a message is  called the header, and the free-format
+portion is called the body.
+The header must always
+exist, but the body is optional.
+
+.lp
+THE HEADER
+.lp
+Each header item can be viewed as a single logical line of ASCII
+characters.
+If the text of a header item extends across several
+real lines, the continuation lines are indicated by leading
+spaces or tabs.
+.lp
+Each header item is called a component and is composed of a
+keyword or name, along with associated text.
+The keyword begins at the
+left margin, may contain spaces or tabs, may not exceed 63
+characters, and is terminated by a colon (:).
+Certain
+components (as identified by their keywords) must follow rigidly
+defined formats in their text portions.
+.lp
+The text for most formatted components (e.g., \*(lqDate:\*(rq and \*(lqMessage-Id:\*(rq)
+is produced automatically.
+The only ones entered by the
+user are address fields such as \*(lqTo:\*(rq, \*(lqcc:\*(rq, etc.
+ARPA addresses
+are assigned mailbox names and host computer specifications.
+The
+rough format is \*(lqmailbox at host\*(rq, such as \*(lqBorden at Rand-Unix\*(rq.
+Multiple addresses are separated by commas.
+A missing host is
+assumed to be the local host.
+
+.ne 10
+.lp
+THE BODY
+.lp
+A blank line signals that all following text up to the end of the file
+is the body.
+(A blank line is defined as a pair of
+<end-of-line> characters with \fIno\fR characters in between.)
+No formatting is expected or enforced within the body.
+.lp
+Within MH, a line consisting of dashes is accepted
+as the header delimiter.
+This is a cosmetic feature applying
+only to locally composed mail.
+.bp
+.$c "MESSAGE NAME BNF" "Message Name BNF"
+
+.ta 1.2i 1.8i 3.2i
+.nf
+.in 1i
+^msgs~^^:=~^^msgspec~^|
+^^^^msgs msgspec
+
+^msgspec~^^:=~^^msg~^|
+^^^^^msg-range~^|
+^^^^msg-sequence
+
+^msg~^^:=~^^msg-name~^|
+^^^^<number>^
+
+^msg-name~^^:=~^^\*(lqfirst\*(rq~^|
+^^^^^\*(lqlast\*(rq~^|
+^^^^^\*(lqcur\*(rq~^|
+^^^^^\*(lq\*.\*(rq~^|
+^^^^^\*(lqnext\*(rq~^|
+^^^^\*(lqprev\*(rq
+
+^msg-range~^^:=~^^msg\*(lq-\*(rqmsg~^|
+^^^^^\*(lqall\*(rq
+
+^msg-sequence~^^:=~^msg\*(lq:\*(rqsigned-number
+
+^signed-number~^^:=~^^\*(lq+\*(rq<number>~^|
+^^^^^\*(lq\--\*(rq<number>~^|
+^^^^<number>
+.re \" Reset Tabs
+.fi
+.sp
+.pp
+Where <number> is a decimal number in the range 1 to 999.
+.pp
+Msg-range specifies all of the messages in the given range
+and must not be empty.
+.pp
+Msg-sequence specifies up to <number> of messages, beginning
+with \*(lqmsg\*(rq (in the case of first, cur, next, or <number>),
+or ending with \*(lqmsg\*(rq (in the case of prev or last).
++<number> forces \*(lqstarting with msg\*(rq, and \-<number> forces
+\*(lqending with number\*(rq.
+In all cases, \*(lqmsg\*(rq must exist.
+.bp
+.$c "EXAMPLE OF SHELL COMMANDS"  "Example of Shell Commands"
+.pp
+UNIX commands may be mixed with MH commands to obtain additional
+functions.
+These may be prepared as files (known as
+shell command files or
+shell scripts).
+The following example is a useful function that
+illustrate the possibilities.
+Other functions, such as copying,
+deleting, renaming, etc., can be achieved in a similar fashion.
+
+HARDCOPY
+.pp
+The command:
+
+.ti +.5i
+(scan\0\-f\&f\0\-header;\0show\0all\0\-pr\0\-f)\0|\0print
+
+produces a scan listing of the current folder, followed by a
+form feed, followed by a formatted listing of all messages
+in the folder, one per page.
+Omitting \*(lq\-pr\0\-f\*(rq will cause the
+messages to be concatenated, separated by a one-line header
+and two blank lines.
+.pp
+You can create variations on this theme, using \fIpick\fR.
+.re
+.fi
+.in 0
+.bp
+.ce
+.b \\s12REFERENCES\\s0
+.(x
+.sp
+REFERENCES
+.)x
+.sp 3
+.in .4i
+.ti 0
+1.  Crocker, D. H., J. J. Vittal, K. T. Pogran, and D. A. Henderson, Jr.,
+\*(lqStandard for the Format of ARPA Network Test Messages,\*(rq \fIArpanet Request
+for Comments\fR, No. 733, Network Information Center 41952, Augmentation
+Research Center, Stanford Research Institute,
+November 1977.
+
+.ti 0
+2.  Thompson, K., and D. M. Ritchie, \*(lqThe UNIX Time-sharing System,\*(rq
+\fICommunications of the ACM\fR, Vol. 17, July 1974, pp. 365-375.
+
+.ti 0
+3.  McCauley, E. J., and P. J. Drongowski, \*(lqKSOS\-The Design of a Secure
+Operating System,\*(rq \fIAFIPS Conference Proceedings\fR,
+National Computer Conference,
+Vol. 48, 1979, pp. 345-353.
+
+.ti 0
+4.  Crocker, David H., \fIFramework and Functions of the \*(lqMS\*(rq Personal
+Message System\fR, The Rand Corporation, R-2134-ARPA, December 1977.
+
+.ti 0
+5.  Thompson, K., and D. M. Ritchie, \fIUNIX Programmer's Manual\fR, 6th ed.,
+Western Electric Company, May 1975 (available only to UNIX licensees).
+
+.ti 0
+6.  Bilofsky, Walter, \fIThe CRT Text Editor NED\-Introduction and
+Reference Manual\fR, The Rand Corporation, R-2176-ARPA, December 1977.
+.bp 3
+.de $c
+.ce
+.b "\\s12\\$1\\s0"   \" 12 Point Bold Header
+.(x y
+.sp
+\\$1
+.)x
+.sp 3
+..
+.pn 3
+.++ P
+.fo ''''
+.he ''-%-''
+.+c PREFACE
+.pp
+This report describes a system for dealing with messages transmitted on a
+computer.  Such messages might originate with other users of the same
+computer or might come from an outside source through a network to which the user's
+computer is connected.  Such computer-based message systems are
+becoming increasingly widely used, both within and outside the Department
+of Defense.
+.pp
+The message handling system MH was developed for two reasons.
+One was to investigate some
+research ideas concerning how a message system might take advantage of
+the architecture of the UNIX time-sharing operating system for
+Digital Equipment Corporation PDP-11 and VAX computers, and the special
+features of UNIX's command-level interface with the user (the
+\*(lqshell\*(rq).  The other reason was to provide a better and more
+adaptable base than that of conventional designs
+on which to build a command and control message system.
+The effort has succeeded in both
+regards, although this report mainly describes the message system itself
+and how it fits in with UNIX.  The main research results are being
+described and analyzed in a forthcoming Rand report.
+The system is currently being used as part
+of a tactical command and control \*(lqlaboratory,\*(rq which is also being described
+in a separate report.
+.pp
+The present report should be of interest to three groups of readers.  First,
+it is a complete reference manual for the users of MH (although
+users outside of Rand must take into
+account differences from the local Rand environment).  Second, it should be
+of interest to those who have a general knowledge of computer-based
+message systems, both in civilian and military environments.  Finally,
+it should be of interest to those who build large subsystems that
+interface with users, since it illustrates a new approach to such
+interfaces.
+.pp
+This report was prepared as part of the Rand project entitled \*(lqData
+Automation Research\*(rq, sponsored by Project AIR FORCE.
+.pn 5
+.+c SUMMARY
+.pp
+Electronic communication of text messages is becoming
+commonplace.  Computer-based message systems\-software
+packages that provide tools for dealing with messages\-are used in many
+contexts.  In particular, message systems are becoming
+increasingly important in command and control and intelligence
+applications.
+.pp
+This report describes a message handling system called MH.
+This system provides the user
+with tools to compose, send, receive, store, retrieve, forward, and
+reply to messages.  MH has been built on the UNIX time-sharing system,
+a popular operating system developed for the DEC PDP-11 and VAX classes of
+computers.
+.pp
+A complete description of MH is given for users of
+the system.  For those who do not intend to use the system, this description
+gives a general idea of what a message system is like.  The system involves
+some new ideas about how large subsystems can be constructed.  These design
+concepts and a comparison of MH with other message systems
+will be published in a forthcoming Rand report.
+.pp
+The interesting and unusual features of MH include the
+following:  The user command interface to MH is the UNIX \*(lqshell\*(rq
+(the standard UNIX command interpreter).  Each separable
+component of message handling, such as message composition or
+message display, is a separate command.  Each program is driven from
+and updates a private user environment, which is stored as a file
+between program invocations.  This private environment also contains
+information to \*(lqcustom tailor\*(rq MH to the individual's tastes.  MH
+stores each message as a separate file under UNIX, and it utilizes the
+tree-structured UNIX file system to organize groups of files within
+separate directories or \*(lqfolders.\*(rq  All of the UNIX facilities
+for dealing with files and directories, such as
+renaming, copying, deleting, cataloging, off-line printing, etc., are
+applicable to messages and directories of messages (folders).  Thus,
+important capabilities needed in a message system are available in MH without
+the need (often seen in other message systems) for code that
+duplicates the facilities of the supporting operating system.
+It also allows users familiar with the shell to use MH with minimal
+effort.
+.he ''''
+.fo ''''
+.bp
+.ce
+.b \\s12CONTENTS\\s0
+.sp 3
+.xp y
+.xp x
+
+.bp     \" Spare numbers for cut and paste work!
+.ft B
+
+1       1       1       1       1       1       1       1
+
+1       1       1       1       1       1       1       1
+
+1       1       1       1       1       1       1       1
+
+1       1       1       1       1       1       1       1
+
+2       2       2       2       2       2       2       2
+
+2       2       2       2       2       2       2       2
+
+2       2       2       2       2       2       2       2
+
+3       3       3       3       3       3       3    
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/DOC/mh1.nr b/docs/historical/mh-jun-1982/DOC/mh1.nr
new file mode 100644 (file)
index 0000000..a613981
--- /dev/null
@@ -0,0 +1,2482 @@
+.de $c                          \" Major Heading printer
+.ce
+.b "\\s12\\n+(ch.\\ \\$1\\s0"   \" 12 Point Bold Header
+.(x
+
+\\n(ch.\\ \\$1
+.)x
+.sp 45p         \" 45 point space or about 1/2 inch
+..
+.de $0          \" Sub-Heading macro called AFTER printing the heading
+.(x
+
+.ti .5i
+\\$1
+.)x
+..
+.de $s          \" Macro to print footnote separator
+\"\l'2i'        \" No line drawn
+.if n \
+.       sp 1.3  \" But extra space to make up for it.
+..
+.fc ^ ~         \" The characters ^ and ~ CANNOT BE USED
+\"                 throughout this document except as field
+\"                 delimiter & pad indicator!
+.he \*(rq-%-\*(rq
+.ll 32P         \" 32 Picas or about 5+1/3 inch Line Length
+.nr ss 30p      \" 30 point space before section titles
+.ds . \\fB.\\fP\\h'-(1m/4)' \" Bold period to stand out.
+.ds << <\\h!-(\\w'<'/2)!<
+.ds >> >\\h!-(\\w'>'/2)!>
+.ds ** \v'-3p'\s+1*\s0\v'+3p'
+.++ C
+.+c INTRODUCTION
+.pp
+Although people can travel cross-country in hours and can
+reach others by telephone in seconds, communications still depend
+heavily upon paper, most of which is distributed through the mails.
+.pp
+There are several major reasons for this continued dependence on
+written documents.
+First, a written document may be proofread
+and corrected prior to its distribution, giving the author
+complete control over his words.
+Thus, a written document is
+better than a telephone conversation in this respect.
+Second,
+a carefully written document is far less likely to be
+misinterpreted or poorly translated than a phone conversation.
+Third, a signature offers reasonable verification of authorship,
+which cannot be provided with media such as telegrams.
+.pp
+However, the need for
+.u fast ,
+accurate, and reproducible document distribution is
+obvious.
+One solution in widespread use is the telefax.
+Another
+that is rapidly gaining popularity is electronic mail.
+Electronic mail is similar to telefax in that the data to be sent
+are digitized, transmitted via phone lines, and
+turned back into a document at the receiver.
+The advantage of
+electronic mail is in its compression factor.
+Whereas a telefax
+must scan a page in very fine lines and send all of the black and
+white information, electronic mail assigns characters fixed
+codes which can be transmitted as a few bits of information.
+Telefax presently has the advantage of being able to transmit an
+arbitrary page, including pictures, but electronic mail is
+beginning to deal with this problem.
+Electronic mail also integrates well
+with current directions in office automation, allowing documents
+prepared with sophisticated equipment at one site to be quickly
+transferred and printed at another site.
+.pp
+Currently, most electronic mail is intraorganizational,
+with mail transfer remaining within one computer.
+As computer
+networking becomes more common, however, it is becoming more feasible to
+communicate with anyone whose computer can be linked to your
+own via a network.
+.pp
+The pioneering efforts on general-purpose electronic mail
+were by organizations using the Defense Department's ARPANET.[1]
+The capability to send messages between computers existed before
+the ARPANET was developed, but it was used only in limited ways.
+With the advent of the
+ARPANET, tools began to be developed which made it convenient for
+individuals or organizations to distribute messages
+over broad geographic areas, using
+diverse computer facilities.
+The interest and activity in
+message systems has now reached such proportions that steps
+have been taken within the DoD to coordinate and
+unify the development of military message systems.
+The use of electronic mail is expected to increase
+dramatically in the next few years.
+The utility of such systems
+in the command and control and intelligence environments is
+clear, and applications in these areas will probably lead the
+way.
+As the costs for sending and handling electronic messags
+continue their rapid decrease, such uses can be
+expected to spread rapidly into other areas and, of course, will
+not be limited to the DoD.
+.pp
+A message system provides tools that help users (individuals
+or organizations) deal with messages in various ways.
+Messages
+must be composed, sent, received, stored, retrieved,
+forwarded, and replied to.
+Today's best interactive computer
+systems provide a variety of word-processing and information
+handling capabilities.
+The message handling facilities should be
+well integrated with the rest of the system, so as to be a
+graceful extension of overall system capability.
+.pp
+The message system described in this report, MH, provides most of the
+features that can be found in other message systems and also
+incorporates some new ones.
+It has been built on the UNIX time-sharing
+system,[2] a popular operating system for the DEC PDP-11
+and VAX classes of computers.
+A \*(lqsecure\*(rq operating
+system similar to UNIX is currently being developed,[3]
+and that system will also run MH.
+.pp
+This report provides a complete description of MH and
+thus may serve as a user's manual, although parts of the report
+will be of interest to non-users as well.
+Sections 2 and 3, the
+Overview and Tutorial, present the key
+ideas of MH and will give those not familiar with message systems
+an idea of what such systems are like.
+.pp
+MH consists of a set of commands which use some special
+files and conventions.
+Section 4 covers the information
+a user needs to know in addition to the
+commands.
+The final section, Sec. 5, describes each of
+the MH commands in detail.
+A summary of the commands is given in
+Appendix A, and Appendixes B and C describe the ARPANET
+conventions for messages (we expect that many users of MH
+will be using the ARPANET) and the formal syntax of such
+messages, respectively.
+Finally, Appendix D provides
+some illustrations of how MH commands may be used in
+conjunction with other UNIX facilities.
+.pp
+A novel approach has been taken in the design of MH.
+The
+design concept will be reported in detail in a forthcoming Rand
+report, but it can be described briefly as follows.
+Instead of creating a large subsystem that appears as a single
+command to the user, MH is a collection of separate commands
+which are run as separate programs.
+The file and directory
+system of UNIX are used directly.
+Messages are stored as
+individual files (datasets), and collections of them are grouped
+into directories.
+In contrast, most other message systems store
+messages in a complicated data structure within a monolithic
+file.
+With the MH approach, UNIX commands can be
+interleaved with commands invoking the functions of the message
+handler.
+Conversely, existing UNIX commands
+can be used in connection with messages.
+For
+example, all the usual UNIX editing, text-formatting, and printing
+facilities can be applied directly to individual messages.
+MH,
+therefore, consists of a relatively small amount of new code; it
+makes extensive use of other UNIX software to provide the
+capabilities found in other message systems.
+.pp
+The MH system was developed by the first
+author, using an approach suggested by the other two authors.
+Valuable assistance was provided by Phyllis Kantar in the later
+stages of the system's implementation.
+Several colleagues
+contributed to the ideas included in this system, particularly
+Robert Anderson and David Crocker.
+In addition, valuable experience
+in message systems, and a valuable source of ideas, was available
+to us in the form of a previous message system for UNIX called
+MS,[4] designed at Rand by David Crocker.
+.+c OVERVIEW
+.pp
+There are three main aspects of MH:  the  way  messages  are
+stored (the message database), the user's profile (which directs
+how certain actions of the message handler take place), and the
+commands for dealing with messages.
+.pp
+Under MH, each message is stored as a separate file.
+A user
+can take any action with a message that he could with an ordinary
+file in UNIX.
+A UNIX directory in which messages are stored is
+called a folder.
+Each folder contains some standard entries to support
+the message-handling functions.
+The messages in a folder have numerical
+names.
+These folders (directories)
+are entries in a particular directory path, described in
+the user profile, through which MH can find message folders.
+Using the UNIX \*(lqlink\*(rq facility, it is possible for one copy of a
+message to be \*(lqfiled\*(rq in more than one folder, providing a
+message index facility.
+Also, using the UNIX tree-structured
+file system, it is possible to have a folder within a folder.
+This two-level organization provides a \*(lqselection-list\*(rq
+facility, with the full power of the MH commands available on
+selected sublists of messages.
+.pp
+Each user of MH has a user profile, a file in his $HOME (initial
+login)
+directory called \*(lq\*.mh\(ruprofile\*(rq.
+This profile contains several
+pieces of information used by the MH commands:  a
+path name to the directory that contains the message folders,
+information concerning which folder the user last referenced (the
+\*(lqcurrent\*(rq folder), and parameters that tailor MH commands
+to the individual user's requirements.
+It also contains
+most of the necessary state information concerning how
+the user is dealing with his messages, enabling MH to be
+implemented as a set of individual UNIX commands, in contrast to the
+usual approach of a monolithic subsystem.
+.pp
+In MH, incoming mail is appended
+to the end of a file called \*.mail in a user's $HOME
+directory.
+The user adds the new messages to his collection of MH messages
+by invoking the command
+.i inc .
+.i Inc
+(incorporate) adds the new
+messages to a folder called \*(lqinbox\*(rq, assigning them names which
+are consecutive integers starting with the next highest integer
+available in inbox.
+.i Inc
+also produces a
+.i scan
+summary of
+the messages thus incorporated.
+.pp
+There are four commands for examining the messages in a
+folder:
+.i show ,
+.i prev ,
+.i next ,
+and
+.i scan .
+.i Show
+displays a
+message in a folder,
+.i prev
+displays the message preceding the
+current message, and
+.i next
+displays the message following the
+current message.
+.i Scan
+summarizes the messages in a folder,
+producing one line per message, showing who the message is from,
+the date, the subject, etc.
+.pp
+The user may move a message from one folder to another with
+the command
+.i file .
+Messages may be removed from a folder
+by means of the command
+.i rmm .
+In addition, a user may query
+what the current folder is and may specify that a new folder
+become the current folder, through the command
+.i folder .
+.pp
+A set of messages based on content may be selected by
+use of the command
+.i pick .
+This command searches through
+messages in a folder and selects those that match a given
+criterion.
+A subfolder is created within the original folder,
+containing links to all the messages that satisfy the selection
+criteria.
+.pp
+A message folder (or subfolder) may be removed by means of
+the command
+.i rmf .
+.pp
+There are five commands enabling the user to create new
+messages and send them:
+.i comp ,
+.i dist ,
+.i forw ,
+.i repl ,
+and
+.i send .
+.i Comp
+provides the facility for the user to compose a
+new message;
+.i dist
+redistributes mail to additional addressees;
+.i forw
+enables the user to forward messages; and
+.i repl
+facilitates the generation of a reply to an incoming message.
+If
+a message is not sent directly by one of these commands, it may
+be sent at a later time using the command
+.i send .
+.pp
+All of the elements summarized above
+are described in more detail in the following sections.
+Many of the
+normal facilities of UNIX provide additional capabilities for
+dealing with messages in various ways.
+For example, it is
+possible to print messages
+on the line-printer without requiring any additional code within
+MH.
+Using standard UNIX facilities, any terminal output can be
+redirected to a file for repeated or future viewing.
+In general,
+the flexibility and capabilities of the UNIX interface with the
+user are preserved as a result of the integration of MH into the UNIX
+structure.
+.+c TUTORIAL
+.pp
+This tutorial provides a brief introduction to the MH commands.
+It should be sufficient
+to allow the user to read his mail, do some simple manipulations of
+it, and create and send messages.
+.pp
+A message has two major pieces:  the
+header and the body.
+The body consists of the text of the message
+(whatever you care to type in).
+It follows the header and is separated from
+it by an empty line.
+(When you compose a message, the form that appears
+on your terminal shows a line of dashes after the header.
+This is for
+convenience and is replaced by an empty line when the message is
+sent.)  The header is composed of several components, including the
+subject of the message and the person to whom it is addressed.
+Each component starts with a name
+and a colon; components must not start with a blank.
+The text of the
+component may take more than one line, but each continuation line must
+start with a blank.
+Messages typically have \*(lqto:\*(rq, \*(lqcc:\*(rq, and
+\*(lqsubject:\*(rq components.
+When composing a message, you should include
+the \*(lqto:\*(rq and \*(lqsubject:\*(rq components; the \*(lqcc:\*(rq (for people
+you want to send copies to) is not necessary.
+.pp
+The basic MH commands are
+.i inc ,
+.i scan ,
+.i show ,
+.i next ,
+.i prev ,
+.i rmm ,
+.i comp ,
+and
+.i repl .
+These are described below.
+
+.i inc
+.pp
+When you get the message \*(lqYou have mail\*(rq, type the command
+.i inc .
+You will get a \*(lqscan listing\*(rq such as:
+
+.nf
+.ta .4i 1.2i 3i
+^7+~^^\07/13~^^Cas~^revival of measurement work
+^8~^^10/\09~^^Norm~^NBS people and publications
+^9~^^11/26~^^To:norm~^question \*(<<Are there any functions
+.re
+.fi
+.pp
+This shows the messages you received since the last time you
+executed this command (
+.i inc
+adds these new messages to
+your inbox folder).
+You can see this list again, plus a list of any
+other messages you have, by using the
+.i scan
+command.
+
+.i scan
+.pp
+The scan listing shows the message number, followed by the
+date and the sender.
+(If you are the sender, the addressee in the \*(lqto:\*(rq
+component is displayed.
+You may send yourself a message by including
+your name among the \*(lqto:\*(rq or \*(lqcc:\*(rq addressees.)
+It also shows the message's subject; if
+the subject is short, the first part of the body of the message is
+included after the characters \*(<<.
+
+.i show
+.pp
+This command shows the current message, that is,
+the first one of the new messages after an
+.i inc .
+If the message is not
+specified by name (number), it is
+generally the last message referred to by an MH command.
+For example,
+
+.ta 1i
+.ti .5i
+^\fIshow\fP\05~^will show message 5.
+.pp
+You can use the show command to copy a message or print a
+message.
+
+.(b L
+.in .5i
+.ta 1i
+^\fIshow\fR\0>\0\fIx\fR~^will copy the message to file x.
+.br
+^\fIshow\fR\0|\0\fIprint\fR~^will print the message, using the \fIprint\fR command.
+.br
+^\fInext\fR~^will show the message that follows the current message.
+.br
+^\fIprev\fR~^will show the message previous to the current message.
+.br
+^\fIrmm\fR~^will remove the current message.
+.br
+^\fIrmm\03\fR~^will remove message 3.
+.)b
+
+.i comp
+.pp
+The
+.i comp
+command puts you in the editor to write or edit a message.
+Fill in or
+delete the \*(lqto:\*(rq, \*(lqcc:\*(rq, and \*(lqsubject:\*(rq fields, as appropriate, and
+type the body of the message.
+Then
+exit normally from the editor.
+You will be asked
+\*(lqWhat now?\*(rq.
+Type a carriage return to see the options.
+Typing \fBsend\fR
+will cause the message to be sent; typing \fBquit\fR will cause an exit
+from
+.i comp ,
+with the message draft saved.
+.pp
+If you quit without sending the message, it will be saved in a file
+called /usr/<name>/Mail/draft (where /usr/<name> is your $HOME directory).
+You can edit this file and send the message later, using the
+.i send
+command.
+
+.ne 4
+.i "comp\0\-editor\0prompter"
+.pp
+This command uses a different editor and is useful for preparing
+\*(lqquick and dirty\*(rq messages.
+It prompts you for each component of the
+header.
+Type the information for that component, or type a carriage
+return to omit the component.
+After that, type the body of the
+message.
+Backspacing is the only form of editing allowed with this editor.
+When the body is complete, type a carriage return followed by <CTRL-D>
+(<OPEN> on Ann Arbor terminals).
+This completes the initial preparation of the message; from then on, use
+the same procedures as with
+.i comp
+(above).
+
+.ne 5
+.i repl
+.br
+.i "repl\0n"
+.pp
+This command makes up an initial message form with a header
+that is appropriate for
+replying to an existing message.
+The message being answered is the
+current message if no message number is mentioned, or n if a number
+is specified.
+After the header is completed, you can finish the message as in
+.i comp
+(above).
+.pp
+This is enough information to get you going using MH.
+There are more commands,
+and the commands described here have more features.
+Subsequent sections
+explain MH in complete detail.
+The system is quite powerful if you
+want to use its sophisticated features, but the foregoing commands
+suffice for sending and receiving messages.
+.pp
+There are numerous additional capabilities you may wish to explore.
+For example, the
+.i pick
+command will select a subset of messages
+based on specified criteria such as sender or subject.
+Groups of
+messages may be designated, as described in Sec. V, under \*(lqMessage
+Naming\*(rq.
+The file \*(lq\*.mh\(ruprofile\*(rq can be used to tailor your use of
+the message system to your needs and preferences, as described in Sec. V,
+under \*(lqThe User Profile\*(rq.
+In general, you may
+learn additional features of the system selectively, according to your
+requirements,
+by studying the relevant sections of this manual.
+There is no need to
+learn all the details of the system at once.
+.+c "DETAILED DESCRIPTION"
+.pp
+This section describes the MH system in detail, including the components
+of the user profile, the conventions for message naming, and some of
+the other MH conventions.
+Readers who are
+generally familiar with computer systems will be able to follow
+the principal ideas, although some details may be meaningful only to
+those familiar with UNIX.
+.uh "THE USER PROFILE"
+.pp
+The first time an MH command is issued by a new user, the system
+prompts for a \*(lqpath\*(rq and creates an MH \*(lqprofile\*(rq.
+.pp
+Each MH user has a profile which contains current
+state information for the MH package and, optionally, tailoring
+information for each individual program.
+When a folder becomes
+the current folder, it is recorded in the user's profile.
+Other profile entries control the MH path (where folders and
+special files are kept), folder and message protections, editor
+selection, and default arguments for each MH program.
+.pp
+The MH profile is stored in the file \*(lq\*.mh\(ruprofile\*(rq in the
+user's $HOME directory.
+It has the format of a message without
+any body.
+That is, each profile entry is on one line, with a
+keyword followed by a colon (:) followed by text particular to
+the keyword.
+.br
+\(rh\ \ \&
+.i "This file must not have blank lines."
+.br
+The keywords
+may have any combination of upper and lower case.
+(See Appendix
+B for a description of message formats.)
+.pp
+For the average MH user, the only profile entry of
+importance is \*(lqPath\*(rq.
+Path specifies a directory in which MH
+folders and certain files such as \*(lqdraft\*(rq are found.
+The
+argument to this keyword must be a legal UNIX path that names an
+existing directory.
+If this path is unrooted (i.e., does not
+begin with a \fB/\fR), it will be presumed to start from the
+user's $HOME directory.
+All folder and message references within
+MH will relate to this path unless full path names are used.
+.pp
+Message protection defaults to 664, and folder protection to
+751.
+These may be changed by profile entries \*(lqMsg-Protect\*(rq
+and \*(lqFolder-Protect\*(rq, respectively.
+The argument to these
+keywords is an octal number which is used as the UNIX file mode.\**
+.(f
+\**See
+.i chmod (I)
+in the
+.i "UNIX Programmer's Manual" .[5]
+.)f
+.pp
+When an MH program starts running, it looks through the
+user's profile for an entry with a keyword matching the program's
+name.
+For example, when
+.i comp
+is run, it looks for a \*(lqcomp\*(rq
+profile entry.
+If one is found, the text of the profile entry is
+used as the default switch setting until all defaults are overridden
+by explicit switches passed to the program as arguments.
+Thus the profile
+entry \*(lqcomp:\0\-form\0standard.list\*(rq would direct
+.i comp
+to use the
+file \*(lqstandard.list\*(rq as the message skeleton.
+If an explicit
+form switch is given to the
+.i comp
+command, it will override the
+switch obtained from the profile.
+.pp
+In UNIX, a program may exist under several names, either by
+linking or aliasing.
+The actual invocation name is used by an MH
+program when scanning for its profile defaults.
+Thus, each MH program
+may have several names by which it can be invoked, and each name
+may have a different set of default switches.
+For example, if
+.i comp
+is invoked by the name
+.i icomp ,
+the profile entry
+\*(lqicomp\*(rq will control the default switches for this invocation of
+the
+.i comp
+program.
+This provides a powerful
+definitional facility for commonly used switch settings.
+.pp
+The default editor
+for editing within
+.i comp ,
+.i repl ,
+.i forw ,
+and
+.i dist ,
+is \*(lq/bin/ned\*(rq.\**
+.(f
+\**See Ref. 6 for a description of
+the NED text editor.
+.)f
+A different editor may be used by specifying
+the profile entry
+\*(lqEditor: \*(rq.
+The argument to \*(lqEditor\*(rq is the name of an
+executable program or shell command file which can be found via
+the user's $PATH defined search path, excluding the current
+directory.
+The \*(lqEditor:\*(rq profile specification
+may in turn be overridden by a \*(lq\-editor\0<editor>\*(rq
+profile switch associated with
+.i comp ,
+.i repl ,
+.i forw ,
+or
+.i dist .
+Finally, an explicit editor switch specified with any
+of these four commands will have ultimate precedence.
+.pp
+During message composition, more than one editor may be
+used.
+For example, one editor (such as
+.i prompter )
+may be used
+initially, and a second editor may be invoked later to revise
+the message being composed
+(see the discussion of
+.i comp
+in Section 5 for details).
+A profile entry \*(lq<lasteditor>\-next:\0<editor>\*(rq specifies the name of
+the editor to be used after a particular editor.
+Thus \*(lqcomp:\0\-e\0prompter\*(rq
+causes the initial text to be collected by
+.i prompter ,
+and the profile entry \*(lqprompter\-next:\0ed\*(rq names ed as the
+editor to be invoked for the next round of editing.
+.pp
+Some of the MH commands, such as
+.i show ,
+can be used on
+message folders owned by others, if those folders are readable.
+However,
+you cannot write in someone else's folder.
+All the MH command
+actions not requiring write permission may be used with
+a \*(lqread-only\*(rq folder.
+In a writable folder, a file named
+\*(lqcur\*(rq is used to contain its current message name.
+For read-only folders, the current message name is
+stored in the user's profile.
+.pp
+Table 1 lists examples of the currently defined profile
+entries, typical arguments, and the programs that reference the
+entries.
+.in .9i
+.ll -.9i
+.ta 2.3i
+.sp 30p
+.ce
+Table 1
+.sp 8p
+.ce
+P\s-2ROFILE\s0 C\s-2OMPONENTS\s0
+.hl             \" ~12p preceding + 1v (12p) after
+.nf
+^^MH Programs that
+^Keyword and Argument~^\ Use Component\h'|\n(.lu-.9i'\l'|0'  \" \l'..' does underlining
+.sp
+^Path:\0Mail~^All
+^Current-Folder:\0inbox~^Most
+^Editor:\0/bin/ed~^\fIcomp, dist, forw, repl\fR
+^Msg\-Protect:\0644~^\fIinc\fR
+^Folder\-Protect:\0711~^\fIfile, inc, pick\fR
+^<program>:\0default switches~^All
+^cur\-<read-onlyfolder>:\0172~^Most
+^prompter\-next:\0ed~^\fIcomp, dist, forw, repl\fR
+.hl
+.ll +1i
+.in 0
+.fi
+.pp
+Path
+.u should
+be present.
+Folder is maintained
+automatically by many MH commands (see the \*(lqContext\*(rq sections of
+the individual commands in Sec. V).
+All other entries are optional,
+defaulting to the values described above.
+.uh "MESSAGE NAMING"
+.pp
+Messages may be referred to explicitly or implicitly when
+using MH commands.
+A formal syntax of message names is given in Appendix C, but the
+following description should be sufficient for most MH users.
+Some details of message naming that apply only to certain
+commands are included in the description of those
+commands.
+.pp
+Most of the MH commands accept arguments specifying one or
+more folders, and one or more messages to operate on.
+The use of
+the word \*(lqmsg\*(rq as an argument to a command means that exactly one
+message name may be specified.
+A message name may be a number,
+such as 1, 33, or 234, or it may be
+one of the \*(lqreserved\*(rq message names:
+first, last, prev, next, and cur.
+(As a shorthand, a
+period (\*.) is equivalent to cur.)
+The meanings of these names
+are straightforward:  \*(lqfirst\*(rq is the first message in the
+folder; \*(lqlast\*(rq is the last
+message in the folder; \*(lqprev\*(rq is the
+message numerically previous to the current message; \*(lqnext\*(rq
+is the message numerically following the current message; \*(lqcur\*(rq
+(or \*(lq\*.\*(rq) is the current message in the folder.
+.pp
+The default in commands that take a \*(lqmsg\*(rq argument is
+always \*(lqcur\*(rq.
+.pp
+The word \*(lqmsgs\*(rq indicates that several messages may be
+specified.
+Such a specification consists of several message
+designations separated by spaces.
+A message designation is
+either a message name or a message range.
+A message range is a
+specification of the form name1\-name2 or name1:n, where name1 and
+name2 are message names and n is an integer.
+The first form
+designates all the messages from name1 to name2 inclusive; this
+must be a non-empty range.
+The second form specifies up to n
+messages, starting with name1 if name1 is a number, or first,
+cur, or next, and ending with name1 if name1 is last or
+prev.
+This interpretation of n is overridden if n is preceded
+by a plus sign or a minus sign;
++n always means up to n messages starting with
+name1, and \-n always means up to n messages ending with name1.
+Repeated specifications of the same message have the same effect
+as a single specification of
+the message.
+Examples of
+specifications are:
+
+.(b
+1 5 7\-11 22
+first 6 8 next
+first\-10
+last:5
+.)b
+.pp
+The message name \*(lqall\*(rq is a shorthand for \*(lqfirst\-last\*(rq,
+indicating all of the messages in the folder.
+.pp
+The limit on the number of messages in an expanded message
+list is generally 999\*-the maximum number of messages in a
+folder.
+However, the
+.i show
+command and the
+commands `\fIpick\0\-scan\fR' and `\fIpick\0\-show\fR'
+are constrained to have argument lists
+that are no more than 512 characters long.
+(Under Version 7 UNIX this limit is 4096.)
+.pp
+In commands that accept \*(lqmsgs\*(rq arguments, the default is
+either cur or all, depending on which makes more sense.
+.pp
+In all of the MH commands, a plus sign preceding an argument
+indicates a folder name.
+Thus, \*(lq+inbox\*(rq is the name of the
+user's standard inbox.
+If an explicit folder argument is given
+to an MH command, it will become the current folder (that is,
+the \*(lqCurrent-Folder:\*(rq entry
+in \*(lq\*.mh\(ruprofile\*(rq will be changed to this
+folder).
+In the case of the
+.i file
+and
+.i pick
+commands, which
+can have multiple output folders, a new source folder (other than
+the default current folder) is specified by \*(lq\-src\0+folder\*(rq.
+.uh "OTHER MH CONVENTIONS"
+.pp
+One very powerful feature of MH is that the MH commands may
+be issued from any current directory, and the proper path to
+the appropriate folder(s) will be taken from the user's profile.
+If the MH path is not appropriate for a specific folder or file,
+the automatic prepending of the MH path can be avoided by
+beginning a folder or file name with \fB/\fR.
+Thus any specific full
+path may be specified.
+.pp
+Arguments to the various programs may be given in any order,
+with the exception of a few switches whose arguments must follow
+immediately, such as \*(lq\-src\0+folder\*(rq for \fIpick\fR and \fIfile\fR.
+.pp
+Whenever an MH command prompts the user, the valid options
+will be listed in response to a <RETURN>.
+(The first of the
+listed options is the default if end-of-file is encountered, such
+as from a command file.)  A valid response is any \fIunique\fR
+abbreviation of one of the listed options.
+.pp
+Standard UNIX documentation conventions are used in this report
+to describe MH command syntax.
+Arguments enclosed in brackets
+([ ]) are optional; exactly one of the arguments enclosed
+within braces ({ }) must be specified, and all other
+arguments are required.
+The use of ellipsis dots (...) indicates
+zero or more repetitions of the previous item.
+For example,
+\*(lq+folder ...\*(rq would indicate that one or more \*(lq+folder\*(rq arguments
+is required and \*(lq[+folder ...]\*(rq indicates that 0 or more
+\*(lq+folder\*(rq arguments may be given.
+.pp
+MH departs from UNIX standards by using switches that consist of
+more than one character, e.g. \*(lq\-header\*(rq.
+To minimize typing,
+only a unique abbreviation of a switch need be typed; thus, for
+\*(lq\-header\*(rq, \*(lq\-hea\*(rq is probably sufficient, depending on the
+other switches the command accepts.
+Each MH program
+accepts the switch \*(lq\-help\*(rq (which \fImust\fR be spelled out fully)
+and produces a syntax description and a list of switches.
+In the
+list of switches, parentheses indicate required characters.
+For example, all \*(lq\-help\*(rq switches will appear as \*(lq\-(help)\*(rq,
+indicating that no abbreviation is accepted.
+.pp
+Many MH switches have both on and off forms, such as
+\*(lq\-format\*(rq and \*(lq\-noformat\*(rq.
+In many of the descriptions in Sec. V,
+only one form is defined; the other form, often used to
+nullify profile switch settings, is assumed to be the opposite.
+.(b L
+.uh "MH COMMANDS"
+.pp
+The MH package comprises 16 programs:
+
+.nf
+.in .5i
+.ta 1.5i
+^comp~^Compose a message
+^dist~^Redistribute a message
+^file~^Move messages between folders
+^folder~^Select/list status of folders
+^forw~^Forward a message
+^inc~^Incorporate new mail
+^next~^Show the next message
+^pick~^Select a set of messages by context
+^prev~^Show the previous message
+^prompter~^Prompting editor front end for composing messages
+^repl~^Reply to a message
+^rmf~^Remove a folder
+^rmm~^Remove messages
+^scan~^Produce a scan listing of selected messages
+^send~^Send a previously composed message
+^show~^Show messages
+.fi
+.re
+.)b
+.pp
+These programs are described below.
+The form of the descriptions
+conforms to the standard
+form for the description of UNIX commands.
+.ll 6.5i
+.lt 6.5i
+.nr Us 0 1
+.fo '7th Edition'UNIX/32V(Rand)'\\\\\\\\n+(Us'
+.de SC
+.he '\\$1(1)'-%-'\\$1(1)'
+.nr Us 0 1
+.bp
+.(x
+.ti .8i
+\\$1
+.)x
+..
+.de NA
+.b \\s-2NAME\\s0
+.ti .5i
+..
+.de SY
+.sp
+.b \\s-2SYNOPSIS\\s0
+.in 1i
+.ti .5i
+.na
+..
+.de DE
+.ad
+.sp
+.in 0
+.b  \\s-2DESCRIPTION\\s0
+.sp
+.fi
+.in .5i
+..
+.de Fi
+.(b L
+.ti 0
+.b \\s-2Files\\s0
+.ta 2i
+..
+.de Pr
+.)b
+.(b L F
+.in 2.5i
+.ti 0
+.b "\\s-2Profile Components\\s0"
+.ti .5i
+..
+.de Ps
+.ti .5i
+..
+.de De
+.)b
+.(b L
+.in .5i
+.ti 0
+.b \\s-2Defaults\\s0
+..
+.de Co
+.)b
+.(b L F
+.ti 0
+.b \\s-2Context\\s0
+.br
+..
+.de En
+.)b
+.in 0
+..
+.SC COMP
+.NA
+comp \- compose a message
+
+.SY
+comp [\-editor editor] [\-form formfile] [file] [\-use] [\-nouse] [\-help]
+
+.DE
+\fIComp\fP is used to create a new message to be mailed.
+If
+\fIfile\fP is not specified, the file named \*(lqdraft\*(rq in the user's MH
+directory will be used.
+\fIComp\fR copies a message form to
+the file being composed and then invokes an editor on the
+file.
+The default editor is /bin/ned, which may be overridden with
+the `\-editor' switch or with a profile entry \*(lqEditor:\*(rq.
+(See Ref. 5 for a
+description of the NED text editing system.)
+The default
+message form contains the following elements:
+
+     To:
+     cc:
+     Subject:
+     ----------
+
+If the file named \*(lqcomponents\*(rq exists in the user's MH directory,
+it will be used instead of this form.
+If `\-form
+formfile' is specified, the specified formfile (from the MH
+directory) will be used as the skeleton.
+The line of dashes
+or a blank line must be left between the header and the
+body of the message for the message to be identified properly when it is
+sent (see \fIsend;\fR).
+The switch `\-use' directs \fIcomp\fR to
+continue editing an already started message.
+That is, if a
+\fIcomp\fR (or \fIdist\fR, \fIrepl\fR, or \fIforw\fR) is terminated without
+sending the message, the message can be edited again via
+\*(lqcomp \-use\*(rq.
+
+If the specified file (or draft) already exists, \fIcomp\fR will ask
+if you want to delete it before continuing.
+A reply of \fBNo\fR will abort the
+\fIcomp\fR, \fByes\fR will replace the existing draft with a blank
+skeleton, \fBlist\fR will display the draft, and \fBuse\fR will use it
+for further composition.
+
+Upon exiting from the editor, \fIcomp\fR will ask \*(lqWhat now?\*(rq.
+The valid
+responses are \fBlist\fR, to list the draft on the terminal; \fBquit\fR, to
+terminate the session and preserve the draft; \fBquit delete\fR, to terminate,
+then delete the draft; \fBsend\fR, to send the message; \fBsend verbose\fR, to
+cause the delivery process to be monitored; \fBedit <editor>\fR, to invoke
+<editor> for further editing; and \fBedit\fR, to re-edit using the
+same editor that was used on the preceding round unless a profile
+entry \*(lq<lasteditor>\-next: <editor>\*(rq names an alternative editor.
+
+.Fi
+^/etc/mh/components~^The message skeleton
+^or <mh-dir>/components~^Rather than the standard skeleton
+^$HOME/\*.mh\(ruprofile~^The user profile
+^<mh-dir>/draft~^The default message file
+^/usr/bin/send~^To send the composed message
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Editor:~^To override the use of /bin/ned as the default editor
+.Ps
+^<lasteditor>\-next:~^To name an editor to be used after exit from <lasteditor>
+.De
+`file' defaults to draft
+`\-editor' defaults to /bin/ned
+`\-nouse'
+.Co
+\fIComp\fR does not affect either the current folder or the current message.
+.En
+.SC DIST
+.NA
+dist \- redistribute a message to additional addresses
+.SY
+dist [+folder] [msg] [\-form formfile] [\-editor editor]
+[\-annotate] [\-noannotate]
+[\-inplace] [\-noinplace]
+[\-help]
+.DE
+\fIDist\fR is similar to \fIforw\fR.
+It prepares the specified
+message for redistribution to addresses that (presumably) are
+not on the original address list.
+The file \*(lqdistcomps\*(rq in the
+user's MH directory, or a standard form, or the file specified by
+`\-form formfile' will be used as the blank components file to
+be prepended to the message being distributed.
+The standard form
+has the components \*(lqDistribute-to:\*(rq and \*(lqDistribute-cc:\*(rq.
+When
+the message is sent, \*(lqDistribution-Date:\0date\*(rq,
+\*(lqDistribution-From:\0name\*(rq, and
+\*(lqDistribution-Id:\0id\*(rq (if `\-msgid' is
+specified to \fIsend\fR;) will be prepended to the outgoing message.
+Only those addresses in \*(lqDistribute-To\*(rq, \*(lqDistribute-cc\*(rq, and
+\*(lqDistribute-Bcc\*(rq will be sent.
+Also, a \*(lqDistribute-Fcc:\0folder\*(rq
+will be honored (see \fIsend;\fR).
+
+\fISend\fR recognizes a message as a redistribution message by the
+existence of the field \*(lqDistribute-To:\*(rq, so don't try to
+redistribute a message with only a \*(lqDistribute-cc:\*(rq.
+
+If the `\-annotate' switch is given, each message being
+distributed will be annotated with the lines:
+
+     Distributed:\0\*(<<date\*(>>
+     Distributed:\0Distribute-to: names
+
+where each \*(lqto\*(rq list contains as many lines as required.
+This annotation
+will be done only if the message is sent directly from \fIdist\fR.
+If the
+message is not sent immediately from \fIdist\fR (i.e., if it is sent later
+via \fIsend;\fR),
+\*(lqcomp \-use\*(rq may be used to re-edit and send the constructed message, but
+the annotations won't take place.
+The '\-inplace' switch causes annotation to
+be done in place in order to preserve links to the annotated message.
+
+See \fIcomp\fR for a description of the `\-editor' switch and for options
+upon exiting from the editor.
+
+.Fi
+^/etc/mh/components~^The message skeleton
+^or <mh-dir>/components~^Rather than the standard skeleton
+^$HOME/\*.mh\(ruprofile~^The user profile
+^<mh-dir>/draft~^The default message file
+^/usr/bin/send~^To send the composed message
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Editor:~^To override the use of /bin/ned as the default editor
+.Ps
+^<lasteditor>\-next:~^To name an editor to be used after exit from <lasteditor>
+.De
+`+folder' defaults to the current folder
+`msg' defaults to cur
+`\-editor' defaults to /bin/ned
+`\-noannotate'
+`\-noinplace'
+.Co
+If a +folder is specified, it will become the current
+folder, and the current message will be set to the message
+being redistributed.
+.En
+.SC FILE
+.NA
+file \- file message(s) in (an)other folder(s)
+.SY
+file [\-src +folder] [msgs] [\-link] [\-preserve] +folder\ ...
+[\-nolink] [\-nopreserve] [\-help]
+.DE
+\fIFile\fR moves (\fImv\fR(I)) or links (\fIln\fR(I)) messages from a
+source folder into one or more destination folders.
+If you think
+of a message as a sheet of paper, this operation is not
+unlike filing the sheet of paper (or copies) in file cabinet
+folders.
+When a message is filed, it is linked into the
+destination folder(s) if possible, and is copied otherwise.
+As long
+as the destination folders are all on the same file system, multiple filing
+causes little storage overhead.
+This facility provides a good way to cross-file or multiply-index
+messages.
+For example, if a message is received from Jones about
+the ARPA Map Project, the instruction
+
+     file\0cur\0+jones\0+Map
+
+would allow the message to be found in either of the two
+folders `jones' or `Map'.
+
+If a destination folder doesn't exist, \fIfile\fR will ask if you
+want to create one.
+A negative response will abort the file
+operation.
+
+`\-link' preserves the source folder copy of the message
+(i.e., it does a \fIln\fR(I) rather than a \fImv\fR(I)), whereas,
+`\-nolink' deletes the \*(lqfiled\*(rq messages from the source
+folder.
+Normally, when a message is filed, it is assigned the
+next highest number available in each of the destination folders.
+Use of the `\-preserve' switch will override this message
+\*(lqrenaming\*(rq, but name conflicts may occur, so
+use this switch cautiously.
+(See \fIpick\fR for more details on
+message numbering.)
+
+If `\-link' is not specified (or `\-nolink' is specified),
+the filed messages will be removed (unlink(II)) from the
+source folder.
+
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Current-Folder:~^To find the default current folder
+.Ps
+^Folder\-Protect:~^To set mode when creating a new folder
+.De
+`\-src +folder' defaults to the current folder
+`msgs' defaults to cur
+`\-nolink'
+`\-nopreserve'
+.Co
+If `\-src +folder' is given, it will become the
+current folder for future MH commands.
+If neither `\-link' nor
+`all' are specified, the current message in the source
+folder will be set to the last message specified; otherwise, the
+current message won't be changed.
+.En
+.SC FOLDER
+.NA
+folder \- set/list current folder/message
+.SY
+folder [+folder] [msg] [\-all] [\-fast] [\-nofast] [\-up] [\-down]
+[\-header] [\-noheader] [\-total] [\-nototal] [\-help]
+
+.ti .5i
+folders  <equivalent to 'folder \-all'>
+.DE
+Since the MH environment is the shell, it is easy to lose
+track of the current folder from day to day.
+\fIFolder\fR will
+list the current folder, the number of messages in it, the
+range of the messages (low-high), and the current message within
+the folder, and will flag a selection list or extra files if they
+exist.
+An example of the output is:
+
+      inbox+ has 16 messages ( 3\- 22); cur= 5.
+
+But it is well to note here that \\n(Us is \n(Us.
+
+If a `+folder' and/or `msg' are specified, they will
+become the current folder and/or message.
+An `\-all' switch
+will produce a line for each folder in the user's MH directory,
+sorted alphabetically.
+These folders are preceded by the read-only
+folders, which occur as \*.mh\(ruprofile \*(lqcur\-\*(rq entries.
+For example,
+
+.nf
+.ta 1.5i 2.1i 2.7i 3.5i
+^~Folder\ \ ^^~#\ of\ ^^messages~^^(~\ range\~ );\ ^cur msg (other files)
+^~/fsd/rs/m/tacc\ \ ^^has~35\ ^^messages~^^(~1\-\035);\ ^cur=\ 23.
+^~/rnd/phyl/Mail/EP\ \ ^^has~82\ ^^messages~^^(~1\-108);\ ^cur=\ 82.
+^~ff\ \ ^^has~4\ ^^messages~^^(~1\-\0\04);\ ^cur=\ \01.
+^~inbox+\ ^^has~16\ ^^messages~^^(~3\-\022);\ ^cur=\ \05.
+^~mh\ \ ^^has~76\ ^^messages~^^(~1\-\076);\ ^cur=\ 70.
+^~notes\ \ ^^has~2\ ^^messages~^^(~1\-\0\02);\ ^cur=\ \01.
+^~ucom\ \ ^^has~124\ ^^messages~^^(~1\-124);\ ^cur=\ \06; (select).
+
+^^^~TOTAL=\0339\ ^messages\0in\0\07\0Folders.
+.re
+.fi
+
+The \*(lq+\*(rq after inbox indicates that it is the current folder.
+The \*(lq(select)\*(rq indicates that the folder ucom has a selection
+list produced by \fIpick\fR.
+If \*(lqothers\*(rq had appeared in parentheses at
+the right of a line, it would indicate that there are files in
+the folder directory that don't belong under the MH file naming
+scheme.
+
+The header is output if either an `\-all' or a `\-header' switch
+is specified; it is suppressed by `\-noheader'.
+Also, if \fIfolder\fR
+is invoked by a name ending with \*(lqs\*(rq (e.g., \fIfolders\fR),
+`\-all' is assumed.
+A `\-total' switch will produce only the
+summary line.
+
+If `\-fast' is given, only the folder name (or names in the
+case of `\-all') will be listed.
+(This is faster because the
+folders need not be read.)
+
+The switches `\-up' and `\-down' change the folder to be the
+one above or below the current folder.
+That is, \*(lqfolder \-down\*(rq
+will set the folder to \*(lq<current\-folder>/select\*(rq, and if the
+current folder is a selection-list folder, \*(lqfolder \-up\*(rq will
+set the current folder to the parent of the selection-list.
+(See \fIpick\fR for details on selection-lists.)
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+^/bin/ls~^To fast-list the folders
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+`+folder' defaults to the current folder
+`msg' defaults to none
+`\-nofast'
+`\-noheader'
+`\-nototal'
+.Co
+If `+folder' and/or `msg' are given, they will become the
+current folder and/or message.
+.En
+.SC FORW
+.NA
+forw \- forward messages
+.SY
+forw [+folder] [msgs] [\-editor editor] [\-form formfile]
+[\-annotate] [\-noannotate]
+[\-inplace]  [\-noinplace]
+[\-help]
+.DE
+\fIForw\fR may be used to prepare a message containing other
+messages.
+It constructs the new message from the components file
+or `\-form formfile' (see \fIcomp\fR), with a body composed of the
+message(s) to be forwarded.
+An editor is invoked as in \fIcomp\fR,
+and after editing is complete, the user is prompted before the message
+is sent.
+
+If the `\-annotate' switch is given, each message being
+forwarded will be annotated with the lines
+
+     Forwarded: \*(<<date\*(>>
+     Forwarded: To: names
+     Forwarded: cc: names
+
+where each \*(lqTo:\*(rq and \*(lqcc:\*(rq list contains as many lines as required.
+This annotation will be done only if the message is sent directly
+from \fIforw\fR.
+If the message is not sent immediately from \fIforw\fR,
+\*(lqcomp \-use\*(rq may be used in a later session to re-edit and send
+the constructed message, but the annotations won't take place.
+The `\-inplace' switch permits annotating a message in place in
+order to preserve its links.
+
+See \fIcomp\fR for a description of the `\-editor' switch.
+.Fi
+^/etc/mh/components~^The message skeleton
+^or <mh-dir>/components~^Rather than the standard skeleton
+^$HOME/\*.mh\(ruprofile~^The user profile
+^<mh-dir>/draft~^The default message file
+^/usr/bin/send~^To send the composed message
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Editor:~^To override the use of /bin/ned as the default editor
+.Ps
+^Current-Folder:~^To find the default current folder
+.Ps
+^<lasteditor>\-next:~^To name an editor to be used after exit from <lasteditor>
+.De
+`+folder' defaults to the current folder
+`msgs' defaults to cur
+`\-editor' defaults to /bin/ned
+`\-noannotate'
+`\-noinplace'
+.Co
+If a +folder is specified, it will become
+the current folder, and the current message will be set to
+the first message being forwarded.
+.En
+.SC INC
+.NA
+inc \- incorporate new mail
+.SY
+inc [+folder] [\-audit audit-file] [\-help]
+.DE
+\fIInc\fR incorporates mail from the user's incoming mail drop
+(\*.mail) into an MH folder.
+If `+folder' isn't specified,
+the folder named \*(lqinbox\*(rq in the user's MH directory will be used.
+The
+new messages being incorporated are assigned numbers starting
+with the next highest number in the folder.
+If the specified (or
+default) folder doesn't exist, the user will be queried prior to
+its creation.
+As the messages are processed, a \fIscan\fR  listing
+of the new mail is produced.
+
+If the user's profile contains a \*(lqMsg\-Protect: nnn\*(rq entry, it
+will be used as the protection on the newly created messages,
+otherwise the MH default of 664 will be used.
+During all
+operations on messages, this initially assigned protection will
+be preserved for each message, so \fIchmod\fR(I) may be used to set a
+protection on an individual message, and its protection will be
+preserved thereafter.
+
+If the switch `\-audit audit-file' is specified (usually as a
+default switch in the profile), then \fIinc\fR will append a header
+line and a line per message to the end of the specified
+audit-file with the format:
+
+.nf
+.ti 1i
+\*(<<inc\*(>> date
+.ti 1.5i
+<scan line for first message>
+.ti 1.5i
+<scan line for second message>
+.ti 2.5i
+<etc.>
+.fi
+
+This is useful for keeping track of volume and source of incoming
+mail.
+Eventually, \fIrepl\fR, \fIforw\fR, \fIcomp\fR, and \fIdist\fR may also
+produce audits to this (or another) file, perhaps with
+\*(lqMessage-Id:\*(rq information to keep an exact correspondence history.
+\*(lqAudit-file\*(rq will be in the user's MH directory unless a full
+path is specified.
+
+\fIInc\fR will incorporate even illegally formatted messages into the
+user's MH folder, inserting a blank line prior to the offending
+component and printing a comment identifying the bad message.
+
+In all cases, the \*.mail file will be zeroed.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+^$HOME/\*.mail~^The user's mail drop
+^<mh-dir>/audit-file~^Audit trace file (optional)
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Folder\-Protect:~^For protection on new folders
+.Ps
+^Msg\-Protect:~^For protection on new messages
+.De
+`+folder' defaults to \*(lqinbox\*(rq
+.Co
+The folder into which the message is
+being incorporated will become the
+current folder, and the first message incorporated will be the
+current message.
+This leaves the context ready for a \fIshow\fR
+of the first new message.
+.En
+.SC NEXT
+.NA
+next \- show the next message
+.SY
+next [+folder] [\-switches for \fIl\fR] [\-help]
+.DE
+\fINext\fR performs a \fIshow\fR on the next message in the
+specified (or current) folder.
+Like \fIshow\fR, it passes any
+switches on to the program \fIl\fR, which is called to list the
+message.
+This command is exactly equivalent to \*(lqshow next\*(rq.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+.Co
+If a folder is specified, it will become the current folder, and the
+message that is shown (i.e., the next message in sequence)
+will become the current message.
+.En
+.SC PICK
+.NA
+pick \- select messages by content
+.SY
+.ta .4i 1.8i
+.nf
+.in .5i
+^pick~^^\0\-cc~^ [\-src +folder] [msgs] [\-help] [\-scan] [\-noscan]
+^^^\0\-date~^   [\-show] [\-noshow] [\-nofile] [\-nokeep]
+^^^\0\-from~^
+^^^\s+2\b'\(lt\(bv\(bv\(lk\(bv\(bv\(lb'\s0 \-search~\s+2\b'\(rt\(bv\(bv\(rk\(bv\(bv\(rb'\s0^ pattern
+^^^\0\-subject~^
+^^^\0\-to~^ [\-file [\-preserve] [\-link] +folder ... [\-nopreserve] [\-nolink] ]
+^^^\0\-\-component~^ [\-keep [\-stay] [\-nostay] [+folder ...] ]
+.fi
+
+.re
+.ti .5i
+typically:
+.in 1i
+pick\0\-from\0jones\0\-scan
+.br
+pick\0\-to\0holloway
+.br
+pick\0\-subject\0ned\0\-scan\0\-keep
+.DE
+\fIPick\fR searches messages within a folder for the specified
+contents, then performs several operations on the selected
+messages.
+
+A modified \fIgrep\fR(I) is used to perform the searching, so the
+full regular expression (see \fIed\fR(I)) facility is available
+within `pattern'.
+With `\-search', pattern is used directly,
+and with the others, the grep pattern constructed is:
+
+.ti +.5i
+\*(lq^component:\*.\*(**pattern\*(rq
+
+This means that the pattern specified for a `\-search' will be
+found everywhere in the message, including the header and the body,
+while the other search requests are limited to the single
+specified component.
+The expression `\-\-component pattern'
+is a shorthand for
+specifying `\-search \*(lqcomponent:\*.\*(**pattern\*(rq\ '; it is used to pick
+a component not in the set [cc date from subject to].
+An
+example is \*(lqpick \-\-reply\-to pooh \-show\*(rq.
+
+Searching is performed on a per-line basis.
+Within the header of
+the message, each component is treated as one long line, but in
+the body, each line is separate.
+Lower-case letters in the
+search pattern will match either lower or upper case in the
+message, while upper case will match only upper case.
+
+Once the search has been performed, the selected messages
+are scanned (see \fIscan\fR) if the `\-scan' switch is given, and
+then they are shown (see \fIshow\fR) if the `\-show' switch is
+given.
+After these two operations, the file operations (if
+requested) are performed.
+
+The `\-file' switch operates exactly like the \fIfile\fR command, with the
+same meaning for the `\-preserve' and `\-link' switches.
+
+The `\-keep' switch is similar to `\-file', but it produces a folder that
+is a subfolder of the folder being searched and defines it as
+the current folder (unless the `\-stay' flag is used).
+This
+subfolder contains the messages which matched the search
+criteria.
+All of the MH commands may be used with the sub-folder
+as the current folder.
+This gives the user considerable power
+in dealing with subsets of messages in a folder.
+
+The messages in a folder produced by `\-keep' will always have the
+same numbers as they have in the source folder (i.e., the
+`\-preserve' switch is automatic).
+This way, the message
+numbers are consistent with the folder from which the messages
+were selected.
+Messages are not removed from the source folder
+(i.e., the `\-link' switch is assumed).
+If a `+folder' is not
+specified, the standard name \*(lqselect\*(rq will be used.
+(This is the
+meaning of \*(lq(select)\*(rq when it appears in the output of the
+\fIfolder\fR command.) If `+folder' arguments are given to
+`\-keep', they will be used rather than \*(lqselect\*(rq for the names
+of the subfolders.
+This allows for several subfolders to be
+maintained concurrently.
+
+When a `\-keep' is performed, the subfolder becomes the current folder.
+This can be overridden by use
+of the `\-stay' switch.
+
+Here's an example:
+
+.nf
+\01  % folder +inbox
+\02           inbox+ has  16 messages (  3\- 22); cur=  3.
+\03  % pick \-from dcrocker
+\04  6 hits.
+\05  [+inbox/select now current]
+\06  % folder
+\07    inbox/select+ has  \06 messages (  3\- 16); cur=  3.
+\08  % scan
+.ds + \\h'\\w!+!'
+\09   \03+  6/20   Dcrocker          Re: ned file update issue...
+10   \06\*+  6/23   Dcrocker          removal of files from /tm...
+11   \08\*+  6/27   Dcrocker          Problems with the new ned...
+12   13\*+  6/28   dcrocker          newest nned  \*(<<I would ap...
+13   15\*+  7/\05   Dcrocker          nned  \*(<<Last week I asked...
+14   16\*+  7/\05   dcrocker          message id format  \*(<<I re...
+15  % show all | print
+16     [produce a full listing of this set of messages on the line printer.]
+17  % folder \-up
+18           inbox+ has  16 messages (  3\- 22); cur=  3; (select).
+19  % folder \-down
+20   inbox/select+ has   6 messages (  3\- 16); cur=  3.
+21  % rmf
+22  [+inbox now current]
+23  % folder
+24           inbox+ has  16 messages (  3\- 22); cur=  3.
+.fi
+
+This is a rather lengthy example, but it shows the power of the
+MH package.
+In item 1, the current folder is set to inbox.
+In 3,
+all of the messages from dcrocker are found in inbox and linked
+into the folder \*(lqinbox/select\*(rq.
+(Since no action switch is
+specified, `\-keep' is assumed.)  Items 6 and 7 show that this
+subfolder is now the current folder.
+Items 8 through 14 are a
+\fIscan\fR of the selected messages (note that they are all from dcrocker
+and are all in upper and lower case).
+Item 15 lists all of the messages to
+the high-speed printer.
+Item 17 directs \fIfolder\fR to set the
+current folder to the parent of the selection-list folder, which
+is now current.
+Item 18 shows that this has been done.
+Item 19 resets
+the current folder to the selection list, and 21 removes the
+selection-list folder and resets the current folder to the
+parent folder, as shown in 22 and 23.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Folder\-Protect:~^For protection on new folders
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+`\-src +folder' defaults to current
+`msgs' defaults to all
+.fi
+`\-keep +select' is the default if no `\-scan', `\-show', or `\-file' is specified
+.Co
+If a `\-src +folder' is specified, it will
+become the current folder, unless a `\-keep' with 0 or 1
+folder arguments makes the selection-list subfolder the
+current folder.
+Each selection-list folder will have its
+current message set to the first of the messages linked into
+it unless the selection list already existed, in which case the
+current message won't be changed.
+.En
+.SC PREV
+.NA
+prev \- show the previous message
+.SY
+prev [+folder] [\-switches for \fIl\fR] [\-help]
+.DE
+\fIPrev\fR performs a \fIshow\fR on the previous message in the specified
+(or current) folder.
+Like \fIshow\fR, it passes any switches on to the
+program \fIl\fR, which is called to list the message.
+This command
+is exactly equivalent to \*(lqshow prev\*(rq.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+.Co
+If a folder is specified, it will become current, and the
+message that is shown (i.e., the previous message in sequence)
+will become the current message.
+.En
+.SC PROMPTER
+.NA
+prompter \- prompts the editor front end
+.SY
+This program is not called directly but takes the place
+of an editor and acts as an editor front end.
+
+.ti .5i
+prompter [\-erase chr] [\-kill chr] [\-help]
+.DE
+\fIPrompter\fR is an editor which allows rapid composition of
+messages.
+It is particularly useful to network and low-speed
+(less than 2400 baud) users of MH.
+It is an MH program in that
+it can have its own profile entry with switches, but it can't
+be invoked directly as all other MH commands can; it is an editor
+in that it is invoked by an \*(lq\-editor prompter\*(rq switch or by the
+profile entry \*(lqEditor: prompter\*(rq, but functionally it is merely
+a text-collector and not a true editor.
+
+\fIPrompter\fR expects to be called from \fIcomp\fR, \fIrepl\fR, \fIdist\fR, or
+\fIforw\fR, with a draft file as an argument.
+For example, \*(lqcomp
+\-editor prompter\*(rq will call \fIprompter\fR with the file \*(lqdraft\*(rq already set
+up with blank components.
+For each blank component it finds in
+the draft, it prompts the user and accepts a response.
+A
+<RETURN> will cause the whole component to be left out.
+A \*(lq\\\*(rq
+preceding a <RETURN> will continue the response on the next line,
+allowing for multiline components.
+
+Any component that is non-blank will be copied and echoed to the
+terminal.
+
+The start of the message body is prompted by a line of
+dashes.
+If the body is non-blank, the prompt is
+\*(lq--------Enter additional text\*(rq.
+Message-body typing is terminated with
+a <CTRL-D> (or <CLOSE>).
+Control is returned to the calling
+program, where the user is asked \*(lqWhat now?\*(rq.
+See \fIcomp\fR for
+the valid options.
+
+During \fIprompter\fR execution, the line-deletion character is
+redefined to be <CTRL-F> (<OPEN> on a NED Ann Arbor terminal)
+rather than @, to facilitate the typing of ARPANET addresses such as
+\*(lqKierr @ PARC\*(rq.
+The standard UNIX character-deletion code is
+changed from # to <CTRL-A>, but the destructive backspace key
+will continue to work normally.
+These two characters may be
+specified by the user via the arguments \*(lq\-kill chr\*(rq and \*(lq\-erase
+chr\*(rq, where chr may be a character; or \*(lq\\nnn\*(rq, where nnn is the
+octal value for the character.
+(Again, these may come from the
+default switches specified in the user's profile.)
+
+A <DEL> during message-body typing is equivalent to
+<CTRL-D> for compatibility with NED.
+A <DEL> during
+component typing will abort the command that invoked
+\fIprompter\fR.
+.Fi
+None
+.Pr
+^prompter-next:~^To name the editor to be used on exit from \fIprompter\fR
+.De
+`\-editor' defaults to /bin/ned
+`\-kill \\006'
+`\-erase \\001'
+.Co
+None
+.En
+.SC REPL
+.NA
+repl \- reply to a message
+.SY
+repl [+folder] [msg] [\-editor editor] [\-inplace] [\-annotate]
+[\-help] [\-noinplace] [\-noannotate]
+.DE
+\fIRepl\fR aids a user in producing a reply to an existing
+message.
+In its simplest form (with no arguments), it will set up
+a message-form skeleton in reply to the current message in the
+current folder, invoke the editor, and send the composed
+message if so directed.
+The composed message is constructed as
+follows:
+
+.nf
+.in 1i
+To: <Reply-To> or <From>
+cc: <cc>, <To>
+Subject: Re: <Subject>
+In-reply-to: Your message of <Date>
+.ti +\w'In-reply-to: 'u
+<Message-Id>
+.in .5i
+.fi
+
+where field names enclosed in angle brackets (< >) indicate the
+contents of the named field from the message to which the reply
+is being made.
+Once the skeleton is constructed, an editor is
+invoked (as in \fIcomp\fR, \fIdist\fR, and \fIforw\fR).
+While in the editor,
+the message being replied to is available through a link named
+\*(lq@\*(rq.
+In NED, this means the replied-to message may be \*(lqused\*(rq
+with \*(lquse @\*(rq, or put in a window by \*(lqwindow @\*(rq.
+
+As in \fIcomp\fR, \fIdist\fR, and \fIforw\fR, the user will be queried
+before the message is sent.
+If the `\-annotate' switch is
+specified, the replied-to message will be annotated with the
+single line
+
+.ti +.5i
+Replied: \*(<<Date\*(>>
+
+only if the message is sent directly.
+The command
+\*(lqcomp \-use\*(rq may be used to pick up interrupted editing, as in
+\fIdist\fR and \fIforw\fR; the `\-inplace' switch annotates the message in place,
+so that all folders with links to it will see the annotation.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+^<mh-dir>/draft~^The constructed message file
+^/usr/bin/send~^To send the composed message
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Editor:~^To override the use of /bin/ned as the default editor
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+`+folder' defaults to current
+`msgs' defaults to cur
+`\-editor' defaults to /bin/ned
+`\-noannotate'
+`\-noinplace'
+.Co
+If a `+folder' is specified, it will become the current
+folder, and the current message will be set to the replied-to
+message.
+.En
+.SC RMF
+.NA
+rmf \- remove folder
+.SY
+rmf [+folder] [\-help]
+.DE
+\fIRmf\fR removes all of the files (messages) within the specified
+(or default) folder, and then removes the directory (folder).
+If
+there are any files within the folder which are not a part of MH,
+they will \fInot\fR be removed, and an error will be produced.
+If the
+folder is given explicitly or the current folder is a
+subfolder (i.e., a selection list from \fIpick\fR), it will be
+removed without confirmation.
+If no argument is specified and
+the current folder is not a selection-list folder, the
+user will be asked for confirmation.
+
+\fIRmf\fR irreversibly deletes messages that don't have other links,
+so use it with caution.
+
+If the folder being removed is a subfolder, the parent
+folder will become the new current folder, and \fIrmf\fR will
+produce a message telling the user this has happened.
+This
+provides an easy mechanism for selecting a set of messages,
+operating on the list, then removing the list and returning to
+the current folder from which the list was extracted.
+(See the
+example under \fIpick\fR.)
+
+The files that \fIrmf\fR will delete are cur, any file beginning
+with a comma, and files with purely numeric names.
+All others
+will produce error messages.
+
+\fIRmf\fR of a read-only folder will delete the \*(lqcur\-\*(rq entry from the
+profile without affecting the folder itself.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+`+folder' defaults to current, usually with confirmation
+.Co
+\fIRmf\fR will set the current folder to the parent folder if a
+subfolder is removed; or if the current folder is removed,
+it will make \*(lqinbox\*(rq current.
+Otherwise, it doesn't change the
+current folder or message.
+.En
+.SC RMM
+.NA
+rmm \- remove messages
+.SY
+rmm [+folder] [msgs] [\-help]
+.DE
+\fIRmm\fR removes the specified messages by renaming the message
+files with preceding commas.
+(This is the Rand-UNIX backup file
+convention.)
+
+The current message is not changed by \fIrmm\fR, so a \fInext\fR  will
+advance to the next message in the folder as expected.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+`+folder' defaults to current
+`msgs' defaults to cur
+.Co
+If a folder is given, it will become current.
+.En
+.SC SCAN
+.NA
+scan \- produce a one-line-per-message scan listing
+.SY
+scan [+folder] [msgs] [\-ff] [\-header] [\-help]
+[\-noff] [\-noheader]
+.DE
+\fIScan\fR produces a one-line-per-message listing of the specified
+messages.
+Each \fIscan\fR line contains the message number (name),
+the date, the \*(lqFrom\*(rq field, the \*(lqSubject\*(rq field, and, if room
+allows, some of the body of the message.
+For example:
+
+.nf
+.ta .5i 1.2i 2.6i
+^ #~^^Date~^^  From~^Subject\ \ \ \ \[\*(<<Body]
+^15+~^^7/\05~^^Dcrocker~^nned  \*(<<Last week I asked some of
+^16\ \-~^^7/\05~^^dcrocker~^message id format  \*(<<I recommend
+^18~^^7/\06~^^Obrien~^Re: Exit status from mkdir
+^19~^^7/\07~^^Obrien~^"scan" listing format in MH
+.re
+.fi
+
+The `+' on message 15 indicates that it is the current message.
+The `\-' on message 16 indicates that it has been
+replied to, as indicated by a \*(lqReplied:\*(rq component produced by
+an `\-annotate' switch to the \fIrepl\fR command.
+
+If there is sufficient room left on the \fIscan\fR line after the
+subject, the line will be filled with text from the body,
+preceded by \*(<<.
+\fIScan\fR actually reads each of the specified
+messages and parses them to extract the desired fields.
+During parsing, appropriate error messages will be produced if
+there are format errors in any of the messages.
+
+The `\-header' switch produces a header line prior to the \fIscan\fR
+listing, and the `\-ff' switch will cause a form feed to be
+output at the end of the \fIscan\fR listing.
+See Appendix D.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+Defaults:
+`+folder' defaults to current
+`msgs' defaults to all
+`\-noff'
+`\-noheader'
+.Co
+If a folder is given, it will become current.
+The current
+message is unaffected.
+.En
+.SC SEND
+.NA
+send \- send a message
+.SY
+send [file] [\-draft] [\-verbose] [\-format] [\-msgid]
+[\-help]  [\-noverbose] [\-noformat] [\-nomsgid]
+.DE
+\fISend\fR will cause the specified file (default <mh-dir>/draft) to
+be delivered to each of the addresses in the \*(lqTo:\*(rq, \*(lqcc:\*(rq, and \*(lqBcc:\*(rq
+fields of the message.
+If `\-verbose' is specified, \fIsend;\fR
+will monitor the delivery of local and net mail.
+\fISend\fR with no
+argument will query whether the draft is the intended file, whereas
+`\-draft' will suppress this question.
+Once the message has
+been mailed (or queued) successfully, the file will be renamed
+with a leading comma, which allows it to be retreived until the
+next draft message is sent.
+If there are errors in the
+formatting of the message, \fIsend;\fR will abort with a (hopefully)
+helpful error message.
+
+If a \*(lqBcc:\*(rq field is encountered, its addresses will be used for
+delivery, but the \*(lqBcc:\*(rq field itself will be deleted from all
+copies of the outgoing message.
+
+Prior to sending the message, the fields \*(lqFrom:  user\*(rq, and
+\*(lqDate: now\*(rq will be prepended to the message.
+If `\-msgid' is
+specified, then a \*(lqMessage-Id:\*(rq field will also be added to the
+message.
+If the message already contains a \*(lqFrom:\*(rq field, then a
+\*(lqSender: user\*(rq field will be added instead.
+(An already existing
+\*(lqSender:\*(rq field will be deleted from the message.)
+
+If the user doesn't specify `\-noformat', each of the entries in
+the \*(lqTo:\*(rq and \*(lqcc:\*(rq fields will be replaced with \*(lqstandard\*(rq format
+entries.
+This standard format is designed to be usable by all
+of the message handlers on the various systems around the
+ARPANET.
+
+If an \*(lqFcc: folder\*(rq is encountered, the message will be copied
+to the specified folder in the format in which it will appear to any
+receivers of the message.
+That is, it will have the prepended
+fields and field reformatting.
+
+If a \*(lqDistribute-To:\*(rq field is encountered, the message
+is handled as a redistribution message (see \fIdist\fR for
+details), with \*(lqDistribution-Date: now\*(rq and \*(lqDistribution-From: user\*(rq
+added.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+.Pr
+^Path:~^To determine the user's MH directory
+.De
+`file' defaults to draft
+`\-noverbose'
+`\-format'
+`\-nomsgid'
+.Co
+\fISend\fR has no effect on the current message or folder.
+.En
+.SC SHOW
+.NA
+show \- show (list) messages
+.SY
+show [+folder] [msgs] [\-pr] [\-nopr] [\-draft] [\-help]
+[\fIl\fR or \fIpr\fR switches]
+.DE
+\fIShow\fR lists each of the specified messages to the standard
+output (typically, the terminal).
+The messages are listed exactly
+as they are, with no reformatting.
+A program called \fIl\fR is
+invoked to do the listing, and any switches not recognized by
+\fIshow\fR are passed along to \fIl\fR.
+
+If no \*(lqmsgs\*(rq are specified, the current message is used.
+If
+more than one message is specified, \fIl\fR will prompt for a
+<return> prior to listing each message.
+
+\fIl\fR will list each message, a page at a time.
+When the end of
+page is reached, \fIl\fR will ring the bell and wait for a <RETURN>
+or <CTRL-D>.
+If a <return> is entered, \fIl\fR will clear the
+screen before listing the next page, whereas <CTRL-D> will not.
+The switches to \fIl\fR are
+`\-p#' to indicate the page length in lines, and `\-w#' to
+indicate the width of the page in characters.
+
+If the standard output is not a terminal, no queries are made,
+and each file is listed with a one-line header and two lines of
+separation.
+
+If `\-pr' is specified, then \fIpr\fR(I) will be invoked rather than
+\fIl\fR, and the switches (other than `\-draft') will be passed
+along.
+\*(lqShow \-draft\*(rq will list the file <mh-dir>/draft if it
+exists.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+^/bin/l~^Screen-at-a-time list program
+^/bin/pr~^\fIpr\fR(I)
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+`+folder' defaults to current
+`msgs' defaults to cur
+`\-nopr'
+.Co
+If a folder is given, it will become the current message.
+The last message
+listed will become the current message.
+.En
+.fo ''-%-''
+.he ''''
+\".AH COMMAND SUMMARY*
+.(x
+
+
+APPENDICES
+.)x _
+.++ A
+\".+c "COMMAND SUMMARY\**"
+.bp
+.ll 32P
+.lt 32P
+.ce
+COMMAND SUMMARY\**
+.(f
+\**All commands accept a \-help switch.
+.)f
+.(x
+
+A.\ COMMAND\ SUMMARY
+.)x
+.sp 3
+.nr ch +1
+.nf
+comp    [file]      [\-editor editor] [\-form formfile]
+                             [\-use] [\-nouse]
+
+dist    [+folder]   [msg] [\-form formfile] [\-editor editor]
+                         [\-annotate] [\-noannotate]
+                         [\-inplace] [\-noinplace]
+
+file    [\-src +folder][msgs] [\-link]   [\-preserve] +folder ...
+                            [\-nolink] [\-nopreserve]
+
+folder  [+folder]   [msg] [\-all] [\-fast] [\-nofast] [\-up] [\-down]
+                         [\-header] [\-noheader] [\-total] [\-nototal]
+
+forw    [+folder]   [msgs] [\-editor editor] [\-form formfile]
+                          [\-annotate] [\-noannotate]
+                          [\-inplace] [\-noinplace]
+
+inc     [+folder]   [\-audit audit-file]
+
+next    [+folder]   [\-switches for \fIl\fR]
+
+pick {\-cc        }  [\-src +folder] [msgs]
+     {\-date      }  [\-scan] [\-noscan] [\-show] [\-noshow]
+     {\-from      }
+     {\-search    } pattern   [\-nofile] [\-nokeep]
+     {\-subject   }
+     {\-to        }  [\-file [\-preserve] [\-nopreserve] [\-link]
+     {\-\-component}         [\-nolink] +folder ... ]
+                   [\-keep [\-stay] [+folder ...] [\-nostay] ]
+
+prev    [+folder]   [\-switches for \fIl\fR]
+
+prompter  [\-erase chr] [\-kill chr]
+
+repl    [+folder]   [msg] [\-editor editor] [\-annotate] [\-noannotate]
+                         [\-inplace] [\-noinplace]
+
+rmf     [+folder]
+
+rmm     [+folder]   [msgs]
+
+scan    [+folder]   [msgs] [\-ff]   [\-header]
+                          [\-noff] [\-noheader]
+
+send    [file]      [\-draft] [\-verbose]   [\-format]   [\-msgid]
+                            [\-noverbose] [\-noformat] [\-nomsgid]
+
+show    [+folder]   [msgs] [\-pr] [\-nopr] [\-draft]
+                       [\fIl\fR or \fIpr\fR switches]
+.fi
+.he ''-%-''
+.fo ''''
+.+c "MESSAGE FORMAT"
+.pp
+This section paraphrases the format of ARPANET text messages
+given in Ref. 6.
+.lp
+ASSUMPTIONS
+.np
+Messages
+are expected to consist of lines of text.
+Graphics and binary data are not handled.
+.np
+No data compression is accepted.
+All text is clear
+ASCII 7-bit data.
+.lp
+LAYOUT
+.lp
+A general \*(lqmemo\*(rq framework is used.
+A message consists of a
+block of information in a rigid format, followed by general
+text with no specified format.
+The rigidly formatted  first
+part of a message is  called the header, and the free-format
+portion is called the body.
+The header must always
+exist, but the body is optional.
+.lp
+THE HEADER
+.lp
+Each header item can be viewed as a single logical line of ASCII
+characters.
+If the text of a header item extends across several
+real lines, the continuation lines are indicated by leading
+spaces or tabs.
+.lp
+Each header item is called a component and is composed of a
+keyword or name, along with associated text.
+The keyword begins at the
+left margin, may contain spaces or tabs, may not exceed 63
+characters, and is terminated by a colon (:).
+Certain
+components (as identified by their keywords) must follow rigidly
+defined formats in their text portions.
+.lp
+The text for most formatted components (e.g., \*(lqDate:\*(rq and \*(lqMessage-Id:\*(rq)
+is produced automatically.
+The only ones entered by the
+user are address fields such as \*(lqTo:\*(rq, \*(lqcc:\*(rq, etc.
+ARPA addresses
+are assigned mailbox names and host computer specifications.
+The
+rough format is \*(lqmailbox at host\*(rq, such as \*(lqBorden at Rand-Unix\*(rq.
+Multiple addresses are separated by commas.
+A missing host is
+assumed to be the local host.
+.ne 10
+.lp
+THE BODY
+.lp
+A blank line signals that all following text up to the end of the file
+is the body.
+(A blank line is defined as a pair of
+<end-of-line> characters with \fIno\fR characters in between.)
+No formatting is expected or enforced within the body.
+.lp
+Within MH, a line consisting of dashes is accepted
+as the header delimiter.
+This is a cosmetic feature applying
+only to locally composed mail.
+.+c "MESSAGE NAME BNF"
+
+.ta 1.2i 1.8i 3.2i
+.nf
+.in 1i
+^msgs~^^:=~^^msgspec~^|
+^^^^msgs msgspec
+
+^msgspec~^^:=~^^msg~^|
+^^^^^msg-range~^|
+^^^^msg-sequence
+
+^msg~^^:=~^^msg-name~^|
+^^^^<number>^
+
+^msg-name~^^:=~^^\*(lqfirst\*(rq~^|
+^^^^^\*(lqlast\*(rq~^|
+^^^^^\*(lqcur\*(rq~^|
+^^^^^\*(lq\*.\*(rq~^|
+^^^^^\*(lqnext\*(rq~^|
+^^^^\*(lqprev\*(rq
+
+^msg-range~^^:=~^^msg\*(lq-\*(rqmsg~^|
+^^^^^\*(lqall\*(rq
+
+^msg-sequence~^^:=~^msg\*(lq:\*(rqsigned-number
+
+^signed-number~^^:=~^^\*(lq+\*(rq<number>~^|
+^^^^^\*(lq\--\*(rq<number>~^|
+^^^^<number>
+.re \" Reset Tabs
+.fi
+.sp
+.pp
+Where <number> is a decimal number in the range 1 to 999.
+.pp
+Msg-range specifies all of the messages in the given range
+and must not be empty.
+.pp
+Msg-sequence specifies up to <number> of messages, beginning
+with \*(lqmsg\*(rq (in the case of first, cur, next, or <number>),
+or ending with \*(lqmsg\*(rq (in the case of prev or last).
++<number> forces \*(lqstarting with msg\*(rq, and \-<number> forces
+\*(lqending with number\*(rq.
+In all cases, \*(lqmsg\*(rq must exist.
+
+.+c "EXAMPLES OF SHELL COMMANDS"
+.pp
+UNIX commands may be mixed with MH commands to obtain additional
+functions.
+These may be prepared as files (known as
+shell command files or
+shell scripts).
+The following two examples are useful functions that
+illustrate the possibilities.
+Other functions, such as copying,
+deleting, renaming, etc., can be achieved in a similar fashion.
+
+HARDCOPY
+.pp
+The command:
+
+.ti +.5i
+(scan\0\-ff\0\-header;\0show\0all\0\-pr\0\-f)\0|\0print
+
+produces a scan listing of the current folder, followed by a
+form feed, followed by a formatted listing of all messages
+in the folder, one per page.
+Omitting \*(lq\-pr\0\-f\*(rq will cause the
+messages to be concatenated, separated by a one-line header
+and two blank lines.
+.pp
+You can create variations on this theme, using \fIpick\fR.
+
+
+RENUMBERING
+.pp
+To compact the message numbers within the folder called inbox,
+use the commands:
+
+.in 5
+.nf
+.ta 3i
+^file\0\-src\0+inbox\0all\0+temp~^/* file and renumber */
+^file\0all\0\-src\0+temp\0+inbox~^/* move 'em back */
+^rmf\0+temp~^/* remove \*(lqtemp\*(rq */
+^folder\0+inbox~^/* reset \*(lqcurrent\*(rq folder */
+.re
+.fi
+.in 0
+.+c REFERENCES
+.in .4i
+.ti 0
+1.  Crocker, D. H., J. J. Vittal, K. T. Pogran, and D. A. Henderson, Jr.,
+\*(lqStandard for the Format of ARPA Network Test Messages,\*(rq \fIArpanet Request
+for Comments\fR, No. 733, Network Information Center 41952, Augmentation
+Research Center, Stanford Research Institute,
+November 1977.
+
+.ti 0
+2.  Thompson, K., and D. M. Ritchie, \*(lqThe UNIX Time-sharing System,\*(rq
+\fICommunications of the ACM\fR, Vol. 17, July 1974, pp. 365-375.
+
+.ti 0
+3.  McCauley, E. J., and P. J. Drongowski, \*(lqKSOS\-The Design of a Secure
+Operating System,\*(rq \fIAFIPS Conference Proceedings\fR,
+National Computer Conference,
+Vol. 48, 1979, pp. 345-353.
+
+.ti 0
+4.  Crocker, David H., \fIFramework and Functions of the \*(lqMS\*(rq Personal
+Message System\fR, The Rand Corporation, R-2134-ARPA, December 1977.
+
+.ti 0
+5.  Thompson, K., and D. M. Ritchie, \fIUNIX Programmer's Manual\fR, 6th ed.,
+Western Electric Company, May 1975 (available only to UNIX licensees).
+
+.ti 0
+6.  Bilofsky, Walter, \fIThe CRT Text Editor NED\-Introduction and
+Reference Manual\fR, The Rand Corporation, R-2176-ARPA, December 1977.
+.de $c
+.ce
+.b "\\s12\\$1\\s0"   \" 12 Point Bold Header
+.(x y
+
+\\$1
+.)x
+.sp 3
+..
+.hx
+.tp
+.nf
+.sp 15
+.ps 18
+.vs 24
+.ft B
+.ce 2
+THE MH MESSAGE HANDLING SYSTEM:
+USER'S MANUAL
+.ps
+.vs
+.ft
+.sp .75i
+.ps 12
+.ft B
+.ce
+PREPARED FOR THE AIR FORCE
+.ps
+.ft
+.sp 1i
+.ps 14
+.vs 17
+.ft B
+.ce 3
+BRUCE S. BORDEN
+R. STOCKTON GAINES
+NORMAN Z. SHAPIRO
+.ps
+.ft
+.vs
+.sp |-3.5i
+.ps 16
+.vs 20
+.ft B
+.ce 2
+R-2367-PAF
+OCTOBER 1979
+.ps
+.ft
+.vs
+.pn 3
+.af % i
+.+c PREFACE
+.pp
+This report describes a system for dealing with messages transmitted on a
+computer.  Such messages might originate with other users of the same
+computer or might come from an outside source through a network to which the user's
+computer is connected.  Such computer-based message systems are
+becoming increasingly widely used, both within and outside the Department
+of Defense.
+.pp
+The message handling system MH was developed for two reasons.
+One was to investigate some
+research ideas concerning how a message system might take advantage of
+the architecture of the UNIX time-sharing operating system for
+Digital Equipment Corporation PDP-11 and VAX computers, and the special
+features of UNIX's command-level interface with the user (the
+\*(lqshell\*(rq).  The other reason was to provide a better and more
+adaptable base than that of conventional designs
+on which to build a command and control message system.
+The effort has succeeded in both
+regards, although this report mainly describes the message system itself
+and how it fits in with UNIX.  The main research results are being
+described and analyzed in a forthcoming Rand report.
+The system is currently being used as part
+of a tactical command and control \*(lqlaboratory,\*(rq which is also being described
+in a separate report.
+.pp
+The present report should be of interest to three groups of readers.  First,
+it is a complete reference manual for the users of MH (although
+users outside of Rand must take into
+account differences from the local Rand environment).  Second, it should be
+of interest to those who have a general knowledge of computer-based
+message systems, both in civilian and military environments.  Finally,
+it should be of interest to those who build large subsystems that
+interface with users, since it illustrates a new approach to such
+interfaces.
+.pp
+This report was prepared as part of the Rand project entitled \*(lqData
+Automation Research\*(rq, sponsored by Project AIR FORCE.
+.+c SUMMARY
+.pp
+Electronic communication of text messages is becoming
+commonplace.  Computer-based message systems\-software
+packages that provide tools for dealing with messages\-are used in many
+contexts.  In particular, message systems are becoming
+increasingly important in command and control and intelligence
+applications.
+.pp
+This report describes a message handling system called MH.
+This system provides the user
+with tools to compose, send, receive, store, retrieve, forward, and
+reply to messages.  MH has been built on the UNIX time-sharing system,
+a popular operating system developed for the DEC PDP-11 and VAX classes of
+computers.
+.pp
+A complete description of MH is given for users of
+the system.  For those who do not intend to use the system, this description
+gives a general idea of what a message system is like.  The system involves
+some new ideas about how large subsystems can be constructed.  These design
+concepts and a comparison of MH with other message systems
+will be published in a forthcoming Rand report.
+.pp
+The interesting and unusual features of MH include the
+following:  The user command interface to MH is the UNIX \*(lqshell\*(rq
+(the standard UNIX command interpreter).  Each separable
+component of message handling, such as message composition or
+message display, is a separate command.  Each program is driven from
+and updates a private user environment, which is stored as a file
+between program invocations.  This private environment also contains
+information to \*(lqcustom tailor\*(rq MH to the individual's tastes.  MH
+stores each message as a separate file under UNIX, and it utilizes the
+tree-structured UNIX file system to organize groups of files within
+separate directories or \*(lqfolders.\*(rq  All of the UNIX facilities
+for dealing with files and directories, such as
+renaming, copying, deleting, cataloging, off-line printing, etc., are
+applicable to messages and directories of messages (folders).  Thus,
+important capabilities needed in a message system are available in MH without
+the need (often seen in other message systems) for code that
+duplicates the facilities of the supporting operating system.
+It also allows users familiar with the shell to use MH with minimal
+effort.
+.de $c
+.ce
+.b "\\s12\\$1\\s0"   \" 12 Point Bold Header
+.sp 3
+..
+.pn 1
+.af % i
+.
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/DOC/mhcov.t b/docs/historical/mh-jun-1982/DOC/mhcov.t
new file mode 100644 (file)
index 0000000..38aaee7
--- /dev/null
@@ -0,0 +1,29 @@
+.ll 32P
+.nf
+.sp |2.5i
+.ps 18
+.vs 24
+.ft B
+.ce 2
+THE MH MESSAGE HANDLING SYSTEM:
+USER'S MANUAL
+.vs
+.sp .75i
+.ps 12
+.ce
+PREPARED FOR THE AIR FORCE
+.sp 1i
+.ps 14
+.vs 17
+.ce 3
+BRUCE S. BORDEN
+R. STOCKTON GAINES
+NORMAN Z. SHAPIRO
+.vs
+.sp 3.5i
+.ps 16
+.vs 20
+.ft B
+.ce 2
+R-2367-PAF
+OCTOBER 1979
diff --git a/docs/historical/mh-jun-1982/DOC/rand.t b/docs/historical/mh-jun-1982/DOC/rand.t
new file mode 100644 (file)
index 0000000..e28549b
--- /dev/null
@@ -0,0 +1,10 @@
+.de RA
+.mk v
+\kh\c
+.ft B
+.ps \\$1
+.vs \\$1+2
+RAND\kH
+.br
+.ps \\$1/4
+SANTA MONICA, CA. 90406
diff --git a/docs/historical/mh-jun-1982/Extras/anno.bld b/docs/historical/mh-jun-1982/Extras/anno.bld
new file mode 100644 (file)
index 0000000..56e135e
--- /dev/null
@@ -0,0 +1,5 @@
+if -r anno rm anno
+load -s anno annotate subs.a strings.a -O /rnd/borden/libg.a /rnd/borden/libh.a
+if -r anno.out  mv anno.out anno
+:                                      fini
+
diff --git a/docs/historical/mh-jun-1982/Extras/anno.cc b/docs/historical/mh-jun-1982/Extras/anno.cc
new file mode 100644 (file)
index 0000000..397bfa0
--- /dev/null
@@ -0,0 +1,162 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "mh.h"
+
+/* anno  [+folder] [msgs] [switches] -component component [-text [text]]
+ *
+ * prepends   Component: <<date stamp>>
+ *                       text
+ */
+
+int fout;
+struct msgs *mp;
+int inplace;            /* preserve links in anno */
+
+struct swit switches[] {
+       "all",               -3,      /* 0 */
+       "component",          0,      /* 1 */
+       "inplace",            0,      /* 2 */
+       "noinplace",          0,      /* 3 */
+       "text",               0,      /* 4 */
+       "help",               4,      /* 5 */
+       0,                    0
+};
+
+main(argc, argv)
+char *argv[];
+{
+       register int i, msgnum;
+       register char *cp, *ap;
+       char *folder, *maildir, *msgs[128], *component, *text;
+       char *arguments[50], **argp;
+       int msgp;
+
+       fout = dup(1);
+#ifdef NEWS
+       m_news();
+#endif
+       folder = msgp = component = text = 0;
+       ap = cp = argv[0];
+       while(*cp)
+               if(*cp++ == '/')
+                       ap = cp;
+       if((cp = m_find(ap)) != -1) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                            /* unknown */
+                       case -1:printf("anno: -%s unknown\n", cp);
+                               goto leave;
+                                                            /* -all */
+                       case 0: printf("\"-all\" changed to \"all\"\n");
+                               goto leave;
+                                                            /* -component */
+                       case 1: if(component) {
+                                       printf("Only one component.\n");
+                                       goto leave;
+                               }
+                               if(!(component = *argp++)) {
+               printf("anno: Missing argument for %s switch\n", argp[-2]);
+                                        goto leave;
+                               }
+                               continue;
+                       case 2: inplace = 1;  continue;      /* -inplace */
+                       case 3: inplace = 0;  continue;      /* -noinplace */
+                       case 4: if(text) {                   /* -text */
+                                       printf("Only one text switch.\n");
+                                       goto leave;
+                               }
+                               text = *argp++;  continue;
+                       case 5:                              /* -help */
+help("anno   [+folder] [msgs] [switches] -component component [-text [text]]", switches);
+                               goto leave;
+                       }
+               if(*cp == '+')
+                       if(folder) {
+                               printf("Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               folder = cp + 1;
+               else
+                       msgs[msgp++] = cp;
+       }
+       if(!component) {
+ usage:
+  printf("usage: anno  [+folder] [msgs] [switches] -component component [-text [text]] \n");
+               goto leave;
+       }
+       if(!msgp)
+               msgs[msgp++] = "cur";
+       if(!folder)
+               folder = m_getfolder();
+       maildir = m_maildir(folder);
+       if(chdir(maildir) < 0) {
+               printf("Can't chdir to: "); flush();
+               perror(maildir);
+               goto leave;
+       }
+       if(!(mp = m_gmsg(folder))) {
+               printf("Can't read folder!?\n");
+               goto leave;
+       }
+       if(mp->hghmsg == 0) {
+               printf("No messages in \"%s\".\n", folder);
+               goto leave;
+       }
+       for(msgnum = 0; msgnum < msgp; msgnum++)
+               if(!m_convert(msgs[msgnum]))
+                       goto leave;
+       if(mp->numsel == 0) {
+               printf("anno: feta cheese and garlic\n"); /* never get here */
+               goto leave;
+       }
+       m_replace("folder", folder);
+       if(mp->lowsel != mp->curmsg)
+               m_setcur(mp->lowsel);
+       for(i = mp->lowsel; i <= mp->hghsel; i++)
+               if(mp->msgstats[i] & SELECTED)
+                       annotate(m_name(i), component, text ? text : "");
+ leave:
+       m_update();
+       flush();
+}
+
+
+/*
+ *              if(*cp == '\"' )
+ *                       if(astrp > 1)
+ *                               goto usage;
+ *                       else
+ *                               if(!(ap = rmquote(cp + 1)))
+ *                                       goto usage;
+ *                               astrings[astrp++] = ap;
+*rmquote(cp)
+*char *cp;
+*{
+ *       int i;
+ *
+ *       if(cp[i = length(cp) -1] != '\"') {
+ *               printf("rmquote: string doesn't end with \"\n");
+ *               return(0);
+ *       }
+ *       cp[i] = 0;
+ *       return(cp);
+*}
+               if(*cp == '=' )  {
+                       if(astrp > 1)
+                               goto usage;
+                       else
+                               astrings[astrp++] = cp + 1;
diff --git a/docs/historical/mh-jun-1982/Extras/getenv.c b/docs/historical/mh-jun-1982/Extras/getenv.c
new file mode 100644 (file)
index 0000000..eeaa939
--- /dev/null
@@ -0,0 +1,25 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include <stdio.h>
+#include <pwd.h>
+
+char *
+getenv(key)
+       char *key;
+{
+       register char *r;
+       register struct passwd *p;
+
+       if(strcmp(key, "USER") == 0 || strcmp(key, "HOME") == 0)
+               if((p = getpwuid(getruid())) == NULL)
+                       return NULL;
+               else
+                       return strcmp(key, "USER") == 0 ?
+                              p->pw_name : p->pw_dir;
+       return NULL;
+}
diff --git a/docs/historical/mh-jun-1982/Extras/imp.h b/docs/historical/mh-jun-1982/Extras/imp.h
new file mode 100644 (file)
index 0000000..de51d37
--- /dev/null
@@ -0,0 +1,83 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+
+#ifdef  OLDNCP
+struct netopen  /* Format of open request */
+{
+       long no_lskt;   /* Local socket */
+       long no_fskt;   /* Foreign socket */
+       short no_flags; /* Flag bits */
+       short no_rel;   /* Local socket relative to this file */
+       short no_imp;   /* Imp number */
+       char no_host;   /* Host within Imp */
+       char no_net;    /* Network number (!) */
+       char no_bsize;  /* Byte size */
+};
+#else
+struct netopen  /* Format of open request */
+{
+       long no_lskt;   /* Local socket */
+       long no_fskt;   /* Foreign socket */
+       short no_flags; /* Flag bits */
+       short no_rel;   /* Local socket relative to this file */
+       short no_imp;   /* Imp number */
+       char no_host;   /* Host within Imp */
+       char no_net;    /* Network number (!) */
+       char no_bsize;  /* Byte size */
+};
+#endif
+
+#define NO_ABS 01       /* Absolute local socket number for a connect */
+#define NO_REL 02       /* Relative to another file */
+
+#define NIMPS   20      /* number of imp devices */
+#define MAX_IMPS  10    /* number of imp devices, starting from imp1 */
+
+#define HOSTTBL "/etc/nethosts"
+
+/* Op codes */
+#define NET_CNCT 0
+#define NET_RD   1
+#define NET_WRT  2
+#define NET_CLS  3
+#define NET_LSN  4
+#define NET_SICP 5
+#define NET_UICP 6
+#define NET_RST  7
+#define NET_STRT 8
+#define NET_LOG  9
+#define NET_RSTAT 10
+#define NET_WSTAT 11
+#define NET_SRVR  12
+#define NET_DUMP  13
+#define NET_FLOW 255
+
+/* ioctl commands for imp device*/
+#define IMPCONCT        (('I'<<8)|NET_CNCT)    /* Connect */
+#define IMPLISTN        (('I'<<8)|NET_LSN )    /* Listen */
+#define IMPSICP         (('I'<<8)|NET_SICP)    /* Server ICP */
+#define IMPUICP         (('I'<<8)|NET_UICP)    /* User ICP */
+#define IMPRST          (('I'<<8)|NET_RST )    /* Reset */
+#define IMPSTRT         (('I'<<8)|NET_STRT)    /* Start NCP */
+#define IMPLOG          (('I'<<8)|NET_LOG )    /* Set log flags */
+#define IMPRSTAT        (('I'<<8)|NET_RSTAT)   /* Read socket status */
+#define IMPWSTAT        (('I'<<8)|NET_WSTAT)   /* Write socket status */
+#define IMPRDST         (('I'<<8)|100     )  /* Get read status */
+#define IMPWRTST        (('I'<<8)|101     )  /* Get write status */
+
+/* Structure for IMPSTAT ioctl */
+struct sockstat {
+       long sck_lskt;
+       long sck_fskt;
+       short sck_imp;
+       char sck_host;
+       char sck_net;
+};
+
+long hostnum();
+char *hos
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/Extras/lasthdr.c b/docs/historical/mh-jun-1982/Extras/lasthdr.c
new file mode 100644 (file)
index 0000000..d6bf0ae
--- /dev/null
@@ -0,0 +1,8 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+int     glbtype     0;
diff --git a/docs/historical/mh-jun-1982/Extras/libg/getpw.c b/docs/historical/mh-jun-1982/Extras/libg/getpw.c
new file mode 100644 (file)
index 0000000..fa8a40f
--- /dev/null
@@ -0,0 +1,68 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+
+struct buf {
+
+       int     fildes;
+       int     nleft;
+       char    *nextp;
+       char    buff[512];
+
+};
+
+int pich;
+
+
+getpw(uid, buf)
+char *buf;
+{
+       auto pbuf[259];
+       register n, c;
+       register char *bp;
+
+       if (pich == 0) pich = open("/etc/passwd",0);
+       if (pich <  0) return(1);
+       seek(pich,0,0);
+       pbuf->fildes = pich;
+       pbuf->nleft = 0;
+       uid =& 0377;            /* not for harv unix */
+
+       for(;;) {
+               bp = buf;
+               while((c=pwgetc(&pbuf)) != '\n') {
+                       if (c <= 0) return(1);
+                       *bp++ = c;
+               }
+               *bp++ = '\0';
+               bp = buf;
+               n = 3;
+               while(--n)
+                       while((c = *bp++) != ':')
+                               if (c == '\n') return(1);
+               while((c = *bp++) != ':') {
+                       if (c < '0' || c > '9') continue;
+                       n = n * 10 + c - '0';
+               }
+               if (n == uid) return(0);
+       }
+       return(1);
+}
+
+pwgetc(buf)
+struct buf *buf;
+{
+       register struct buf *bp;
+
+       bp = buf;
+       if (--bp->nleft < 0) {
+               bp->nleft = read(bp->fildes,bp->buff,512)-1;
+               if (bp->nleft < 0) return(-1);
+               bp->nextp = bp->buff;
+       }
+       return(*bp->nextp++);
+}
diff --git a/docs/historical/mh-jun-1982/Extras/libg/getwho.c b/docs/historical/mh-jun-1982/Extras/libg/getwho.c
new file mode 100644 (file)
index 0000000..2430c2e
--- /dev/null
@@ -0,0 +1,19 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "libg.h"
+#include "../h/stat.h"
+getwho(i)
+{
+       register char *st;
+       struct inode i_buf;
+
+       st = ttyname(i);
+       if (st == NULSTR) return(-1);
+       stat(cat("/dev/",st),&i_buf);
+       return(i_buf.i_uid&0377);
+}
diff --git a/docs/historical/mh-jun-1982/Extras/libg/gtfstn.c b/docs/historical/mh-jun-1982/Extras/libg/gtfstn.c
new file mode 100644 (file)
index 0000000..f8ba9ca
--- /dev/null
@@ -0,0 +1,12 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+
+getfstn(uid)
+{
+       return("first name");
+}
diff --git a/docs/historical/mh-jun-1982/Extras/libg/gtldat.c b/docs/historical/mh-jun-1982/Extras/libg/gtldat.c
new file mode 100644 (file)
index 0000000..5dea14b
--- /dev/null
@@ -0,0 +1,14 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+
+getldate(uid)
+{
+       static int logout_date[2];
+
+       return(logout_date);
+}
diff --git a/docs/historical/mh-jun-1982/Extras/libg/gtlogn.c b/docs/historical/mh-jun-1982/Extras/libg/gtlogn.c
new file mode 100644 (file)
index 0000000..205cdea
--- /dev/null
@@ -0,0 +1,21 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "libg.h"
+
+char *getlogn(uid)
+{
+       static char name[20];
+       register char *np, *bp;
+
+       if (getubuf(uid)<=0) return(NULSTR);
+
+       np = name; bp = u_buf;
+       while( (*np++ = *bp++) != ':');
+       *--np = '\0';
+       return(name);
+}
diff --git a/docs/historical/mh-jun-1982/Extras/libg/gtlstn.c b/docs/historical/mh-jun-1982/Extras/libg/gtlstn.c
new file mode 100644 (file)
index 0000000..6896bcb
--- /dev/null
@@ -0,0 +1,12 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+
+getlstn(uid)
+{
+       return("last name");
+}
diff --git a/docs/historical/mh-jun-1982/Extras/libg/gtluid.c b/docs/historical/mh-jun-1982/Extras/libg/gtluid.c
new file mode 100644 (file)
index 0000000..88daa1a
--- /dev/null
@@ -0,0 +1,23 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../h/stat.h"
+/* this subr returns owner of tty attached to file handle # 2 */
+/* on harv/unix, this may not be the real uid, because */
+/* we have the command "alias" which spawns a sub-shell with */
+/* a new real uid.  luid (login uid) is used by the harvard shell */
+/* to find the "save.txt" file (via getpath(getluid())) for $a - $z */
+/* shell macros, and elsewhere by certain accounting routines. */
+
+getluid()
+{
+       struct inode ibuf;
+       if (fstat(2,&ibuf) < 0 &&
+           fstat(1,&ibuf) < 0) return(getruid());
+       if ((ibuf.i_mode & IFMT) != IFCHR) return(getruid());
+       return(ibuf.i_uid&0377);
+}
diff --git a/docs/historical/mh-jun-1982/Extras/libg/gtmnem.c b/docs/historical/mh-jun-1982/Extras/libg/gtmnem.c
new file mode 100644 (file)
index 0000000..ecd3aca
--- /dev/null
@@ -0,0 +1,12 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+
+getmnem(uid)
+{
+       return("mnemonic");
+}
diff --git a/docs/historical/mh-jun-1982/Extras/libg/gtpath.c b/docs/historical/mh-jun-1982/Extras/libg/gtpath.c
new file mode 100644 (file)
index 0000000..12ad8fb
--- /dev/null
@@ -0,0 +1,21 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "libg.h"
+
+getpath(uid)
+{
+       static char path[50];
+       register char *pp, *bp;
+       register int n;
+
+       if (getubuf(uid) <= 0) return(NULSTR);
+       pp = path; bp = u_buf;
+       for(n=0; n<5; n++) while(*bp++ != ':');
+       while((*pp++ = *bp++) != ':');
+       *--pp = '\0';
+       return(p
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/Extras/libg/gtpriv.c b/docs/historical/mh-jun-1982/Extras/libg/gtpriv.c
new file mode 100644 (file)
index 0000000..6fb2735
--- /dev/null
@@ -0,0 +1,12 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+
+getpriv(uid)
+{
+       return(0);
+}
diff --git a/docs/historical/mh-jun-1982/Extras/libg/gtpswd.c b/docs/historical/mh-jun-1982/Extras/libg/gtpswd.c
new file mode 100644 (file)
index 0000000..d2286e8
--- /dev/null
@@ -0,0 +1,23 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "libg.h"
+
+char *getpswd(uid)
+{
+       static char pswd[9];
+       register char *bp, *np;
+
+       bp = u_buf; np = pswd;
+
+       if (getubuf(uid) <= 0) return(NULSTR);
+       while(*bp++ != ':');
+       --bp;
+       while((*np++ = *bp++) != ':');
+       *--np = '\0';
+       return(pswd);
+}
diff --git a/docs/historical/mh-jun-1982/Extras/libg/gtruid.c b/docs/historical/mh-jun-1982/Extras/libg/gtruid.c
new file mode 100644 (file)
index 0000000..2d0afd1
--- /dev/null
@@ -0,0 +1,26 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+/* break up uid into effective and real */
+/* more compatible with 16-bit uid's */
+/* getuid and setuid are std. bell routines */
+geteuid()
+{
+       return((getuid()>>8)&0377);
+}
+getruid()
+{
+       return(getuid()&0377);
+}
+seteuid(euid)
+{
+       return(setuid(euid<<8|getuid()&0377));
+}
+setruid(ruid)
+{
+       return(setuid(ruid&0377|getuid()&0177600));
+}
diff --git a/docs/historical/mh-jun-1982/Extras/libg/gttype.c b/docs/historical/mh-jun-1982/Extras/libg/gttype.c
new file mode 100644 (file)
index 0000000..624efa3
--- /dev/null
@@ -0,0 +1,13 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+
+gettype(uid)
+{
+       /* return account type */
+       return(0);
+}
diff --git a/docs/historical/mh-jun-1982/Extras/libg/gtubuf.c b/docs/historical/mh-jun-1982/Extras/libg/gtubuf.c
new file mode 100644 (file)
index 0000000..6193944
--- /dev/null
@@ -0,0 +1,16 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "libg.h"
+
+getubuf(uid)
+{
+       if (uid != last_uid || uid == 0)
+               if (getpw(uid,u_buf)) return(0);
+       last_uid = uid;
+       return(1);
+}
diff --git a/docs/historical/mh-jun-1982/Extras/libg/gtunum.c b/docs/historical/mh-jun-1982/Extras/libg/gtunum.c
new file mode 100644 (file)
index 0000000..38d1eff
--- /dev/null
@@ -0,0 +1,51 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "libg.h"
+
+getunum(name)
+char *name;
+{
+       register char *bp, *np;
+       register c;
+       int inptr[259];
+       int uid;
+
+       if (pich <= 0)
+               pich = open("/etc/passwd",0);
+       if (pich < 0) return(-1);
+       seek(pich,0,0);
+       inptr[0] = pich;
+       inptr[1] = inptr[2] = 0;
+       uid = 0;
+       if (u_buf[0] != 0) goto test;  /* first test what is presently in
+                                        the buffer */
+
+       for(;;) {
+
+               bp = u_buf;
+               while((c=getc(inptr)) != '\n') {
+                       if (c <= 0) return(-1);
+                       *bp++ = c;
+               }
+               *bp++ = '\0';
+
+       test:   bp = u_buf;
+               np = name;
+               while(*bp++ == *np++);
+               --bp; --np;
+               if (*bp++ == ':' &&
+                   *np++ == '\0') {
+                       while(*bp++ != ':');
+                       while(*bp != ':')
+                               uid = uid * 10 + *bp++ - '0';
+                       last_uid = uid;
+                       return(uid);
+               }
+       }
+       return(-1);
+}
diff --git a/docs/historical/mh-jun-1982/Extras/libg/ttynam.c b/docs/historical/mh-jun-1982/Extras/libg/ttynam.c
new file mode 100644 (file)
index 0000000..b4e8dcb
--- /dev/null
@@ -0,0 +1,34 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "libg.h"
+
+/* this routine returns the file name within "/dev" */
+/* corresponding to the internal tty #, which */
+/* is in turn used by ttynum and getwho */
+/* this routine is obviously very system dependent. */
+
+/* ttyname is set up so that, in conjunction */
+/* with getwho, the following simple "who" program will work: */
+/* for (i = 0; ttnam = ttyname(i); i++)    */
+/*     if (luid = getwho(i)) printf("%s %s\n",ttnam,getlogn(luid)); */
+
+/* also, ttynum(ttyname(n)) should equal n if 0 <= n <= 31 */
+
+char *ttyname(num)
+{
+       register char *tty;
+       tty = "ttyx";
+       if (num < 0 || num > 31) return(NULSTR);
+       if (num == 0) return("tty8");
+       if (num < 9) {
+               tty[3] = num + ('0' - 1);
+               return(tty);
+       }
+       tty[3] = num - ('a' - 9);
+       return(tty);
+}
diff --git a/docs/historical/mh-jun-1982/Extras/libg/ttynum.c b/docs/historical/mh-jun-1982/Extras/libg/ttynum.c
new file mode 100644 (file)
index 0000000..dbf646f
--- /dev/null
@@ -0,0 +1,40 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../h/stat.h"
+
+ttynum(name)
+char *name;
+{
+       /* this routine returns the internal number */
+       /* of the given tty name (string) */
+       /* if the name="tty" or "", the number is that */
+       /* of the user's tty. */
+       /* this is obviously very system dependent */
+       register int major, minor, flags;
+       struct inode ibuf;
+       struct { char low, high; };
+
+       if (*name == '\0' || equal(name,"tty")) {
+               if (fstat(2,&ibuf) < 0 &&
+                   fstat(1,&ibuf) < 0) return(-1);
+       }
+       else
+       if (stat(cat("/dev/",name),&ibuf) < 0 &&
+           stat(cat("/dev/tty",name),&ibuf) < 0) return(-1);
+       flags = ibuf.i_mode;
+       if ((flags & IFMT) != IFCHR) return(-1);
+       minor = ibuf.i_addr[0].low;
+       major = ibuf.i_addr[0].high;
+       if (major == 0)
+               return(minor);
+       else
+       if (major == 1)
+               return(minor+1);
+       else
+       return (-1);
+}
diff --git a/docs/historical/mh-jun-1982/Extras/libh/any.c b/docs/historical/mh-jun-1982/Extras/libh/any.c
new file mode 100644 (file)
index 0000000..d7bdf87
--- /dev/null
@@ -0,0 +1,17 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+any(chr,stg)
+char chr, *stg;
+{
+       register char c, *s;
+
+       c = chr;
+       for (s = stg; *s;)
+               if (*s++ == c) return (1);
+       return (0);
+}
diff --git a/docs/historical/mh-jun-1982/Extras/libh/brkstg.c b/docs/historical/mh-jun-1982/Extras/libh/brkstg.c
new file mode 100644 (file)
index 0000000..e28f519
--- /dev/null
@@ -0,0 +1,45 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#define NSTR 25
+char **brkstring(strg,brksep,brkterm)  /* returns pointer to static table of substring ptrs */
+char *strg;
+char *brksep, *brkterm;
+{
+
+       register char c, *bp, *sp;
+       static char *broken[NSTR+1];    /* static array of substring start addresses */
+       int bi;
+
+       sp = strg;      /* scan string, replacing separators with zeroes */
+
+       for (bi=0; bi<NSTR; bi++) {     /* and entering start addrs in "broken" */
+               while (brkany(c = *sp, brksep)) *sp++ = 0;
+               if (!c || brkany(c, brkterm)) {
+                       *sp=0;
+                       broken[bi] = 0;
+                       return(broken);         /* terminator found, finish up */
+               }
+
+               broken[bi] = sp;        /* set next start addr */
+
+               while ((c = *++sp) && !brkany(c,brksep) && !brkany(c,brkterm));
+
+       }
+       broken[NSTR] = 0;               /* reached limit of NSTR substrings */
+       return (broken);
+}
+
+brkany (chr,strg)      /* returns 1 if chr in strg, 0 otherwise */
+char chr,*strg;
+{
+       register char *sp;
+
+       for (sp=strg; *sp; sp++)
+               if (chr == *sp) return (1);
+       return (0);
+}
diff --git a/docs/historical/mh-jun-1982/Extras/libh/cat.c b/docs/historical/mh-jun-1982/Extras/libh/cat.c
new file mode 100644 (file)
index 0000000..510ed6d
--- /dev/null
@@ -0,0 +1,21 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+char cat_buf[80];
+
+
+char *cat(s1,s2)
+char *s1, *s2;
+{
+       register char *r1, *r2, *bp;
+       r1 = s1; r2 = s2;
+       bp = cat_buf;
+       while(*bp++ = *r1++);
+       bp--;
+       while(*bp++ = *r2++);
+       return(cat_buf);
+}
diff --git a/docs/historical/mh-jun-1982/Extras/libh/cdate.c b/docs/historical/mh-jun-1982/Extras/libh/cdate.c
new file mode 100644 (file)
index 0000000..917da16
--- /dev/null
@@ -0,0 +1,24 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+/* returns date in format dd-mon-yy@hh:mm:ss\0 */
+cdate(dataddr)
+long *dataddr;
+{
+       register char *cp;
+
+       cp = ctime(dataddr);
+       cp[1] = cp[8];
+       cp[2] = cp[9];
+       cp[3] = '-';
+       cp[7] = '-';
+       cp[8] = cp[22];
+       cp[9] = cp[23];
+       cp[10] = '@';
+       cp[19] = 0;
+       return(cp+1);
+}
diff --git a/docs/historical/mh-jun-1982/Extras/libh/copy.c b/docs/historical/mh-jun-1982/Extras/libh/copy.c
new file mode 100644 (file)
index 0000000..8469579
--- /dev/null
@@ -0,0 +1,17 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+copy(from,to)
+char *from, *to;
+{
+       register char *rfrom, *rto;
+
+       rfrom = from;
+       rto = to;
+       while(*rto++ = *rfrom++);
+       return(rto-1);
+};
diff --git a/docs/historical/mh-jun-1982/Extras/libh/date.c b/docs/historical/mh-jun-1982/Extras/libh/date.c
new file mode 100644 (file)
index 0000000..8514b1a
--- /dev/null
@@ -0,0 +1,130 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+/** Version of date.c in s1 modified to be a subroutine
+*  it is called with a string and returns a pointer to ints.
+*  ie,         ip = date(string);
+*  returns 0 if it fails.
+*  only error message is bad conversion if string is illegal.
+*  The only legal format is ########[ps]
+*  where the int field is fixed input and 'p' forces PM by adding 12 hours
+*  and 's' would force standard savings time
+*/
+int    timbuf[2];
+char   *cbp;
+int *cpx;
+int    dmsize[];
+date(string)
+char *string;
+{
+       extern int timezone, *localtime();
+
+       cbp = string;
+       if(gtime()) {
+               write(2, "bad conversion\n", 15);
+               return(0);
+       }
+       if (*cbp != 's') {
+       /* convert to Greenwich time, on assumption of Standard time. */
+               dpadd(timbuf, timezone);
+       /* Now fix up to local daylight time. */
+               if ((cpx = localtime(timbuf))[8])
+                       dpadd(timbuf, -1*60*60);
+       }
+       return(timbuf);
+}
+
+gtime()
+{
+       register int i;
+       register int y, t;
+       int d, h, m;
+       extern int *localtime();
+       int nt[2];
+
+       t = gpair();
+       if(t<1 || t>12)
+               goto bad;
+       d = gpair();
+       if(d<1 || d>31)
+               goto bad;
+       h = gpair();
+       if(h == 24) {
+               h = 0;
+               d++;
+       }
+       m = gpair();
+       if(m<0 || m>59)
+               goto bad;
+       y = gpair();
+       if (y<0) {
+               time(nt);
+               y = localtime(nt)[5];
+       }
+       if (*cbp == 'p')
+               h =+ 12;
+       if (h<0 || h>23)
+               goto bad;
+       timbuf[0] = 0;
+       timbuf[1] = 0;
+       y =+ 1900;
+       for(i=1970; i<y; i++)
+               gdadd(dysize(i));
+       /* Leap year */
+       if (dysize(y)==366 && t >= 3)
+               gdadd(1);
+       while(--t)
+               gdadd(dmsize[t-1]);
+       gdadd(d-1);
+       gmdadd(24, h);
+       gmdadd(60, m);
+       gmdadd(60, 0);
+       return(0);
+
+bad:
+       return(1);
+}
+
+gdadd(n)
+{
+       register char *t;
+
+       t = timbuf[1]+n;
+       if(t < timbuf[1])
+               timbuf[0]++;
+       timbuf[1] = t;
+}
+
+gmdadd(m, n)
+{
+       register int t1;
+
+       timbuf[0] =* m;
+       t1 = timbuf[1];
+       while(--m)
+               gdadd(t1);
+       gdadd(n);
+}
+
+gpair()
+{
+       register int c, d;
+       register char *cp;
+
+       cp = cbp;
+       if(*cp == 0)
+               return(-1);
+       c = (*cp++ - '0') * 10;
+       if (c<0 || c>100)
+               return(-1);
+       if(*cp == 0)
+               return(-1);
+       if ((d = *cp++ - '0') < 0 || d > 9)
+               return(-1);
+       cbp = cp;
+       return (c+d);
+}
diff --git a/docs/historical/mh-jun-1982/Extras/libh/echo.c b/docs/historical/mh-jun-1982/Extras/libh/echo.c
new file mode 100644 (file)
index 0000000..9e499f1
--- /dev/null
@@ -0,0 +1,23 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#define ECHO 010
+/* set, clear echo on file handle # 2 */
+
+int tt_mode[3];
+noecho()
+{
+       gtty(2,tt_mode);
+       tt_mode[2] =& ~ECHO;
+       return(stty(2,tt_mode));
+}
+
+doecho()
+{
+       gtty(2,tt_mode);
+       tt_mode[2] =| ECHO;
+       return(stty(2,tt_mo
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/Extras/libh/equal.c b/docs/historical/mh-jun-1982/Extras/libh/equal.c
new file mode 100644 (file)
index 0000000..6170dcc
--- /dev/null
@@ -0,0 +1,16 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+equal(s1,s2)
+char *s1, *s2;
+{
+       register char *r1, *r2;
+       r1 = s1; r2 = s2;
+       while (*r1++ == *r2)
+               if (*r2++ == 0) return (1);
+       return(0);
+}
diff --git a/docs/historical/mh-jun-1982/Extras/libh/error.c b/docs/historical/mh-jun-1982/Extras/libh/error.c
new file mode 100644 (file)
index 0000000..c968656
--- /dev/null
@@ -0,0 +1,20 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+error(s)
+char *s;
+{
+       register char *p;
+
+       flush();
+       write(2, "?", 1);
+       for (p = s; *p++; );
+       --p;
+       write(2, s, p-s);
+       write(2, "?\n", 2);
+       exit(-1);
+}
diff --git a/docs/historical/mh-jun-1982/Extras/libh/errtyp.c b/docs/historical/mh-jun-1982/Extras/libh/errtyp.c
new file mode 100644 (file)
index 0000000..77c2312
--- /dev/null
@@ -0,0 +1,24 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+errtype(file, errmsg)
+char *file, *errmsg;
+{
+       register char *r1, *r2;
+       char errlin[80];
+       register char *r3;
+
+       r3 = errlin;
+       r1 = r3;
+       r2 = file;
+       while (*r1++ = *r2++);
+       r1[-1] = ':';
+       r2 = errmsg;
+       while (*r1++ = *r2++);
+       r1[-1] = '\n';
+       write(2, r3, r1-r3);
+}
diff --git a/docs/historical/mh-jun-1982/Extras/libh/excsrh.c b/docs/historical/mh-jun-1982/Extras/libh/excsrh.c
new file mode 100644 (file)
index 0000000..95b4580
--- /dev/null
@@ -0,0 +1,61 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#
+#include "../h/errors.h"
+
+char *SRHLIST[] {      /* upper case!! */
+       "",
+       "%",
+       "/bin/",
+       "/usr/bin/",
+       0
+};
+
+char **srhlist SRHLIST;
+
+execvsrh(argv)
+char **argv;
+{
+       return(excvsrh(argv[0], argv));
+}
+
+excvsrh(prog, argv)
+char *prog, **argv;
+{
+       extern errno;
+       register char **r1, *r2, *r3;
+       static char command[50];
+
+       for (r1 = srhlist; r2 = *r1++; ) {
+               r3 = command;
+               if(*r2 == '%') {
+                       r2 = getpath(getruid()&0377);
+                       while(*r3++ = *r2++);
+                       --r3;
+                       r2 = "/bin/";
+               }
+               while (*r3++ = *r2++);
+               --r3;
+               r2 = prog;
+               while (*r3++ = *r2++);
+               if (execvsh(command, argv) != 0) break;
+       }
+       errtype(prog, errno==E2BIG?"arg list too long":"not found");
+       return(-1);
+}
+execlsrh(arg1,arg2,arg3)
+char *arg1,*arg2,*arg3;
+{
+       return(excvsrh(arg1, &arg1));
+}
+
+exclsrh(prog, arg1, arg2)
+char *prog, *arg1, *arg2;
+{
+       return(excvsrh(prog, &arg1));
+}
diff --git a/docs/historical/mh-jun-1982/Extras/libh/execsh.c b/docs/historical/mh-jun-1982/Extras/libh/execsh.c
new file mode 100644 (file)
index 0000000..d584d70
--- /dev/null
@@ -0,0 +1,45 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#
+#include "../h/errors.h"
+#define NSHARGS 25     /* limit on number of args to shell command file  */
+execvsh(name,args)
+char *name, **args;
+{
+       extern errno;
+       register char **v1, **v2;
+       char *shvec[NSHARGS];
+
+       v2 = args;
+       for (v1 = v2; *v1; )
+               if (*v1++ == -1) *--v1 = 0;
+       execv(name, v2);
+       /* return 0 if not found, -1 if not executable */
+       if (errno == ENOENT || errno == EACCES)
+               return (0);
+       else if (errno != ENOEXEC)
+               return(-1);
+       v1 = shvec;
+       *v1++ = "sh";
+       *v1++ = name;
+       *v2++ = "/bin/sh";
+       while (*v1++ = *v2++) {
+               if (v1 >= &shvec[NSHARGS]) {
+                       errno = E2BIG;
+                       return(-1);
+               }
+       }
+       execv(args[0], shvec);
+       return(-1);
+}
+
+execlsh(name,arg0,arg1,arg2)
+char *name, *arg0, *arg1, *arg2;
+{
+       return(execvsh(name,&arg0));
+}
diff --git a/docs/historical/mh-jun-1982/Extras/libh/fmt.c b/docs/historical/mh-jun-1982/Extras/libh/fmt.c
new file mode 100644 (file)
index 0000000..4d9b571
--- /dev/null
@@ -0,0 +1,38 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../h/iobuf.h"
+#define NBUFFED        256     /* limit on fmt buffer */
+
+extern struct iobuf fout;
+int fmtlen;
+
+fmt(fmtstrng, arg1, arg2, arg3)
+char *fmtstrng;
+{
+       int svfildes, svnleft, svnextp;
+
+       flush();
+       svfildes = fout.b_fildes;
+       svnleft = fout.b_nleft;
+       svnextp = fout.b_nextp;
+
+       /* a very illegal file handle */
+       fout.b_fildes = 99;
+       /* use last half of fout buffer */
+       fout.b_nleft = NBUFFED;
+       fout.b_nextp = &fout.b_buff[512-NBUFFED];
+       printf("%r", &fmtstrng);        /* and pass the buck ... */
+       fmtlen = fout.b_nextp - &fout.b_buff[512-NBUFFED];
+       putchar(0);
+
+       fout.b_fildes = svfildes;
+       fout.b_nleft = svnleft;
+       fout.b_nextp = svnextp;
+
+       return(&fout.b_buff[512-NBUFFED]);
+}
diff --git a/docs/historical/mh-jun-1982/Extras/libh/fopen2.c b/docs/historical/mh-jun-1982/Extras/libh/fopen2.c
new file mode 100644 (file)
index 0000000..5c40bb3
--- /dev/null
@@ -0,0 +1,26 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../h/iobuf.h"
+
+/* this is the counterpart to fopen which leaves
+ * the file opened for both read and write
+ * fseek may then be used to position at the end of the
+ * file (or wherever) before reading/writing
+ */
+fopen2(filename, abufp)
+char *filename;
+struct iobuf *abufp;
+{
+       register struct iobuf *bufp;
+
+       bufp = abufp;
+       bufp->b_nleft = 0;
+       bufp->b_nextp = 0;
+       if ((bufp->b_fildes = open(filename, 2)) < 0) return(-1);
+       return(0);
+}
diff --git a/docs/historical/mh-jun-1982/Extras/libh/fseek.c b/docs/historical/mh-jun-1982/Extras/libh/fseek.c
new file mode 100644 (file)
index 0000000..356864e
--- /dev/null
@@ -0,0 +1,89 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "/h/stat.h"
+#include "/h/iobuf.h"
+/* used for input using getc/getw */
+/* does equivalent to requested seek */
+/* by doing seek by blocks if necessary, */
+/* and then adjusting nleft/nextp in iobuf */
+/* first arg is iobuf pointer, others are identical to seek or lseek */
+struct { int hiword, loword; };
+struct { char lobyte, hibyte; };
+
+fseek(bp, offs, dir)
+struct iobuf *bp;
+{
+        long loff;
+
+        loff = offs;
+        if (dir%3 == 0) loff.hiword = 0;
+        return(lfseek(bp, loff, dir));
+}
+
+lfseek(abp, aloff, adir)
+struct iobuf *abp;
+long aloff;
+{
+        register byteoff, blockoff;
+        long loff;
+        register struct iobuf *bp;
+        int dir;
+        struct inode statb;
+        long lsize;
+
+        bp = abp;
+        dir = adir;
+        loff = aloff;
+
+        if (dir >= 3) {
+                loff =<< 9;
+                dir =- 3;
+        }
+        switch(dir) {
+        case 1:
+                /* relative seek */
+                if (bp->b_nleft >= 0) {
+                        if (bp->b_nextp) {
+                                byteoff = bp->b_nextp-bp->b_buff;
+                                loff =+ byteoff;
+                                bp->b_nleft =+ byteoff;
+                        }
+                        break;
+                }
+                /* negative nleft means must be at e.o.f */
+                /* drop into rel.-to-end seek */
+        case 2:
+                if (fstat(bp->b_fildes, &statb) < 0)
+                        return(-1);
+                lsize.hiword.hibyte = 0;
+                lsize.hiword.lobyte = statb.i_size0;
+                lsize.loword = statb.i_size1;
+                /* adjust loff by size of file */
+                loff =+ lsize;
+                dir = 0;        /* now have offset rel.-to-beg. */
+        case 0:
+                /* rel.-to-beginning of file seek */
+                bp->b_nleft = 0;
+                break;
+        default:
+                return(-1);
+        }
+
+        bp->b_nextp = bp->b_buff;
+        blockoff = loff>>9;
+        byteoff = loff;
+        byteoff =& 0777;
+        if (dir != 1 || blockoff != 0) {
+                /* must do the seek */
+                if (seek(bp->b_fildes, blockoff, dir+3) < 0)
+                        return(-1);
+                bp->b_nleft = read(bp->b_fildes, &bp->b_buff, 512);
+        }
+        bp->b_nleft =- byteoff;
+        bp->b_nextp =+ byteoff;
+        retur
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/Extras/libh/gdate.c b/docs/historical/mh-jun-1982/Extras/libh/gdate.c
new file mode 100644 (file)
index 0000000..fedface
--- /dev/null
@@ -0,0 +1,144 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+char *tim_ptr;
+int dmsize[];
+int timezone;
+int no_add;
+
+char *gd_months[] {
+       "january",      "february",     "march",        "april",
+       "may",          "june",         "july",         "august",
+       "september",    "october",      "november",     "december",
+       0,
+};
+
+
+long gdate(str)
+{
+       long tim, now, ghours(), secs;
+       int day, month, year, *nowp;
+       register int i;
+       register char *monp;
+
+       time(&now);
+       nowp = localtime(&now);
+       tim_ptr = str;
+       if(*tim_ptr == '+') {
+               tim_ptr++;
+               return(now + ghours());
+       }
+       day = gd_gdec();
+       if(*tim_ptr == '-') {
+               tim_ptr++;
+               if(*tim_ptr >= 'A' && *tim_ptr <= 'z') {
+                       monp = gd_head();
+                       if((month = swmtch(monp, &gd_months)) < 0) {
+                               printf("Month \"%s\" Nonexistant.\n", monp);
+                               return(0l);
+                       }
+                       if(*tim_ptr == '-') {
+                               tim_ptr++;
+                               year = gd_gdec();
+                       } else
+                               year = nowp[5];
+               } else {
+                       month = nowp[4];
+                       year = nowp[5];
+               }
+               if(*tim_ptr == ' ' || *tim_ptr == '@') {
+                       tim_ptr++;
+                       secs = ghours();
+               } else
+                       secs = nowp[0]+ nowp[1]*60l + nowp[2]*3600l;
+               tim = 0l;
+               if(year<1900) year =+ 1900;
+               for(i = 1970; i < year; i++)
+                       tim =+ dysize(i);
+               if(dysize(year) == 366 && month >= 3)
+                       tim++;
+               while(month--)
+                       tim =+ dmsize[month];
+               tim =+ day - 1;
+               tim =* 24l*60l*60l;
+               tim =+ secs;
+               tim =+ timezone;
+               nowp = localtime(&tim);
+               if(nowp[8])
+                       tim =- 1*60l*60l;
+               return(tim);
+       }
+       tim_ptr = str;
+       secs = ghours();
+       secs =- nowp[0] + nowp[1]*60l + nowp[2]*3600l;
+       if(secs < 0 && no_add == 0)
+               secs =+ 24 * 60l * 60l;
+       return(now + secs);
+}
+
+
+long ghours()
+{
+       register char *cp;
+       register int h, m;
+       int s;
+
+       cp = tim_ptr;
+       s = m = 0;
+       h = gd_gdec();
+       if(tim_ptr - cp == 4 && *tim_ptr != ':') {
+               m = h % 100;
+               h = h / 100;
+       } else {
+               if(*tim_ptr == ':') {
+                       tim_ptr++;
+                       m = gd_gdec();
+                       if(*tim_ptr == ':') {
+                               tim_ptr++;
+                               s = gd_gdec();
+                       }
+               }
+       }
+       if(*tim_ptr == 'p') {
+               tim_ptr++;
+               h =+ 12;
+       }
+       return(h*3600l + m*60l + s);
+}
+
+
+gd_gdec()
+{
+       register int c, i;
+
+       i = 0;
+       c = *tim_ptr;
+       while(c >= '0' && c <= '9') {
+               i = i*10 + c - '0';
+               c = *++tim_ptr;
+       }
+       return(i);
+}
+
+
+gd_head()
+{
+       static char buf[20];
+       register char *c2, c;
+
+       c2 = buf;
+       while(((c = *tim_ptr) >= 'a' && c <= 'z') ||
+                       (c >= 'A' && c <= 'Z')) {
+               if(c <= 'Z')
+                       c =+ 'a' - 'A';
+               if(c2 < &buf[18])
+                       *c2++ = c;
+               tim_ptr++;
+       }
+       *c2 = 0;
+       return(buf);
+}
diff --git a/docs/historical/mh-jun-1982/Extras/libh/getcopy.c b/docs/historical/mh-jun-1982/Extras/libh/getcopy.c
new file mode 100644 (file)
index 0000000..bd6db76
--- /dev/null
@@ -0,0 +1,34 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+char copy_space[128];
+int copy_size; /* if this is non-zero, assume represents */
+               /* actual size of copy_space */
+char *copy_ptr;
+char *
+getcopy(str)
+char *str;
+{
+       static char *cpend;
+       register char *r1, *r2;
+
+       if (cpend == 0) {
+               /* first time through */
+               cpend = copy_space+ (copy_size? copy_size: sizeof copy_space);
+               copy_ptr = copy_space;
+       }
+       r2 = str;
+       for (r1 = copy_ptr; r1 < cpend; ) {
+               if ((*r1++ = *r2++) == 0) {
+                       r2 = copy_ptr;
+                       copy_ptr = r1;
+                       return(r2);
+               }
+       }
+       write(2, "getcopy out of space\n", 21);
+       exit(-1);
+}
diff --git a/docs/historical/mh-jun-1982/Extras/libh/getl.c b/docs/historical/mh-jun-1982/Extras/libh/getl.c
new file mode 100644 (file)
index 0000000..cfacb31
--- /dev/null
@@ -0,0 +1,28 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../h/iobuf.h"
+/* return one line using getc, caller must supply iobuf pointer, */
+/* line buffer, and max. count */
+/* returns actual char count */
+
+getl(bufp,line,cnt)
+struct iobuf *bufp;
+char line[];
+int cnt;
+{
+       register char *lp;
+       register c, cc;
+
+       lp = line;
+       cc = cnt;
+       while ((c = getc(bufp)) >= 0) {
+               *lp++ = c;
+               if (--cc <= 0 || c == '\n') break;
+       }
+       return(cnt-cc);
+}
diff --git a/docs/historical/mh-jun-1982/Extras/libh/getline.c b/docs/historical/mh-jun-1982/Extras/libh/getline.c
new file mode 100644 (file)
index 0000000..bfe014b
--- /dev/null
@@ -0,0 +1,25 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+/* return one line using getchar, caller must supply line buf and max. cnt */
+/* return actual char cnt */
+
+getline(line,cnt)
+char line[];
+int cnt;
+{
+       register char *lp;
+       register c, cc;
+
+       lp = line;
+       cc = cnt;
+       while ((c = getchar()) > 0) {
+               *lp++ = c;
+               if (--cc <= 0 || c == '\n') break;
+       }
+       return(cnt-cc);
+}
diff --git a/docs/historical/mh-jun-1982/Extras/libh/glbmtc.c b/docs/historical/mh-jun-1982/Extras/libh/glbmtc.c
new file mode 100644 (file)
index 0000000..d85beae
--- /dev/null
@@ -0,0 +1,58 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#
+/* glob match subroutine --
+
+   "*" in params matches r.e ".*"
+   "?" in params matches r.e. "."
+   "[...]" in params matches character class
+   "[...a-z...]" in params matches a through z.
+*/
+
+glbmtch(as, ap)
+char *as, *ap;
+{
+       register char *s, *p;
+       register scc;
+       int c, cc, ok, lc;
+
+       s = as;
+       p = ap;
+       if ((scc = *s++) && (scc =& 0177) == 0) scc = 0200;
+       switch (c = *p++) {
+       case '[':
+               ok = 0;
+               lc = 077777;
+               while (cc = *p++) {
+                       if (cc==']') {
+                               if (ok) return(glbmtch(s, p));
+                               else return(0);
+                       } else if (cc=='-') {
+                               if (lc<=scc && scc<=(c = *p++)) ok++;
+                       } else if (scc == (lc=cc)) ok++;
+               }
+               return(0);
+       default:
+               if (c!=scc) return(0);
+       case '?':
+               if (scc) return(glbmtch(s, p));
+               return(0);
+       case '*':
+               return(umatch(--s, p));
+       case '\0':
+               return(!scc);
+       }
+}
+
+umatch(s, p)
+char *s, *p;
+{
+       if(*p==0) return(1);
+       while(*s) if (glbmtch(s++,p)) return(1);
+       return(0);
+}
diff --git a/docs/historical/mh-jun-1982/Extras/libh/gwd.c b/docs/historical/mh-jun-1982/Extras/libh/gwd.c
new file mode 100644 (file)
index 0000000..d8a8319
--- /dev/null
@@ -0,0 +1,123 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../h/stat.h"
+#include "../h/dirent.h"
+
+struct dirinfo {
+       struct dirent dir;
+       char null;
+       int dotino;
+       int dotdotino;
+};
+
+char *rootlist[] {
+       "/",
+       "/rnd/",
+       "/mnt/",
+       "/sys/",
+       "/bak/",
+       "/fsd/",
+       0
+};
+gwd()
+{
+       return(fullpath(0));
+}
+
+fullpath(str)
+char *str;
+{
+       static char wdbuf[128];
+       struct dirinfo d;
+       register char *wp, *cp, **cpp;
+       int fino;
+       char *savewp, *markwp;
+       int dotdev;
+       struct inode statb;
+
+       wp = &wdbuf + 1;
+       *--wp = 0;
+       markwp = 0;
+       if (str) {
+               wp = prepend(str, wp);
+               if (*wp == '/') return(wp);
+               *--wp = 0;
+               markwp = wp;
+       }
+       fino = 0;
+
+       for (;;) {
+               wp = scandir(&d, fino, wp);
+               if (d.dotino != d.dotdotino) {
+                       fino = d.dotino;
+                       chdir("..");
+                       continue;
+               }
+               savewp = wp;
+               if (d.dotino != ROOTINO) break; /* error */
+               stat(".", &statb);
+               dotdev = statb.i_dev;
+               for (cpp = rootlist; cp = *cpp++; ) {
+                       if (stat(cp, &statb) < 0) continue;
+                       if (statb.i_dev == dotdev) {
+                               wp = prepend(cp, wp);
+                               break;
+                       }
+               }
+               break;
+       }
+       chdir(savewp);
+       if (markwp) *markwp = '/';
+       return(wp);
+}
+
+scandir(dp, fileino, endwhere)
+struct dirinfo *dp;
+char *endwhere;
+{
+       register struct dirinfo *d;
+       register char *cp, *wp;
+       int fh;
+
+       d = dp;
+       d->dotino = 0;
+       d->dotdotino = 0;
+       if (fileino == 0) wp = endwhere;
+       else wp = 0;
+       fh = open(".", 0);
+       if (fh < 0) return(wp);
+       while ((!d->dotino || !d->dotdotino || !wp) &&
+           read(fh, &d->dir, sizeof d->dir) == sizeof d->dir) {
+               if (d->dir.d_ino == NULLINO) continue;
+               if (!d->dotino && equal(d->dir.d_name, "."))
+                       d->dotino = d->dir.d_ino;
+               else if (!d->dotdotino && equal(d->dir.d_name, ".."))
+                       d->dotdotino = d->dir.d_ino;
+               else if (!wp && d->dir.d_ino == fileino) {
+                       /* ensure name is null term'd */
+                       d->null = 0;
+                       wp = endwhere;
+                       /* separate with '/' */
+                       if (*wp) *--wp = '/';
+                       wp = prepend(d->dir.d_name, wp);
+               }
+       }
+       close(fh);
+       return(wp);
+}
+
+prepend(prefix, endwhere)
+char *prefix, *endwhere;
+{
+       register char *cp, *wp;
+
+       for (cp = prefix; *cp++; );
+       --cp;
+       for (wp = endwhere; cp > prefix; *--wp = *--cp);
+       return(wp);
+}
diff --git a/docs/historical/mh-jun-1982/Extras/libh/inputf.c b/docs/historical/mh-jun-1982/Extras/libh/inputf.c
new file mode 100644 (file)
index 0000000..78ba0ea
--- /dev/null
@@ -0,0 +1,184 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#
+/* inputf is roughly complementary to printf,
+except input comes from getchar (may be
+user supplied, must return 0 at eof). in addition
+all args must be pointers (addresses). the first arg
+is the format string.  '%' is used as the escape char as in 
+printf.  the general format is %w.dc where w and d are decimal
+character counts, and c is one of (d, o, i, f, e, s, c, x).
+the args are all assumed to be pointers to the appropriate
+typed args -- note all floating point is assumed to be float
+unless the %e format is used (extended float). if w is omitted
+the field ends with the first field delimeter (typically, space, comma,
+and newline -- these can be specified by following the specification
+by a list of chars before the next '%'). d represents the default
+number of decimal places for 'f' and 'e' if no explicit
+decimal point.  for 's' w is the width of the field, and d is
+the maximum number of chars after stripping off delimeters
+on either end.  s and c are approximately identical, except
+that s returns a pointer into a static buffer, and c returns char
+by char into the program itself, which means a 'd' specification
+for c is essential, and in fact 1 is assumed as a default (as opposed
+to infinity for s). if a w field is specified, the input data
+is assumed to be in a fixed format, with exactly w columns
+devoted to the designated field.  this means that data in this format
+does not have to be separated by blanks, etc.  chars in the format
+string before the first '%' are output before any requests
+to the subroutine for chars.  e.g.:
+       inputf("-> %i%e%s\n",&integ, &dbl, &charptr);
+would read an integer into integ, a double into dbl, and a string
+terminated only by a <nl> into a static buffer, returning its start
+addr in charptr, after prompting with "-> ". */
+#define DFTSEP ",; \t\n\r"     /* default field separators */
+#define NEXTCHR getchar()      /* character input routine */
+#define SCBLEN 100             /* max. no. of chars in static char buff */
+struct { float *fltp; };
+struct { double *dblp; };
+inputf(format,arg1,arg2,arg3)
+char *format;
+{
+       register char *fp, *cp, cc;
+       int **ap;
+       int fld, val, wv, dv, radix;
+       char formc, negflg, negexp, *fsp, *scp;
+       static char scbuf[SCBLEN], fldsep[10];
+       double dval;
+
+       ap = &arg1;
+       fp = format;
+       scp = scbuf;    /* init static string pointer */
+
+       while ((cc = *fp++) && cc != '%') putchar(cc);
+       flush();
+
+       fld = 0;        /* used as return value when error found */
+       while (cc) {
+               fld--;
+               wv = 0; dv = 0; /* init w.d fields */
+               while (numeric(cc = *fp++)) wv = wv*10 + cc - '0';
+               if (cc == '.')
+                       while (numeric(cc = *fp++)) dv = dv*10 + cc - '0';
+               if (!wv) wv--; if (!dv) dv--;   /* zero --> minus one */
+               formc = cc;     /* save format character */
+               fsp = cp = fldsep;  /* collect terminators */
+               while (*cp++ = *fp)
+                       if (*fp++ == '%') {
+                               fp--;
+                               *--cp = 0;
+                               break;
+                       }
+               if (!*fsp) fsp = DFTSEP;
+               switch (formc) {
+               case 'o':
+                       radix = 8;
+                       goto ido;
+               case 'd':
+               case 'i':
+                       radix = 10;
+               ido:
+                       val = 0;
+                       negflg = 0;
+                       while ((cc = NEXTCHR) && (cc == ' ' || cc == '-') && --wv)
+                               if (cc == '-') negflg++;
+                       if (!cc) return (fld);  /* return error if eof found */
+                       if (formc == 'i' && cc == '0') radix = 8;
+                       if (wv) do {
+                               if (numeric (cc)) {
+                                       val = val*radix + cc - '0';
+                               } else if (any(cc,fsp))
+                                       break;
+                       } while (--wv && (cc = NEXTCHR));
+                       if (negflg) val = -val;
+                       **ap++ = val;
+                       break;
+               case 'c':
+                       if (dv < 0)
+                               if (wv < 0) dv = 1;
+                               else dv = wv;
+                       cp = *ap++;
+                       goto casecs;
+               case 's':
+                       cp = scp;
+                       val = scbuf + SCBLEN - 1 - cp;  /* calc max. limit on input */
+                       if (dv<0 || dv>val)
+                               if ((dv = val) <= 0) return (fld);
+               casecs:
+                       while ((cc = NEXTCHR) && cc == ' ' && --wv);
+                       if (!cc) return (fld);  /* return error if eof found */
+                       if (wv) do {
+                               if (any(cc,fsp)) break;
+                               if (!dv--) return (fld); /* too big */
+                               *cp++ = cc;
+                       } while (--wv && (cc = NEXTCHR));
+                       if (dv || formc == 's') *cp++ = 0;
+                       if (formc == 'c') break;
+                       **ap++ = scp;
+                       scp = cp;
+                       break;
+               case 'x':
+                       while ((cc = NEXTCHR) && cc == ' ' && --wv);
+                       if (wv)
+                               while (!any(cc,fsp) && --wv && (cc = NEXTCHR));
+                       break;
+               case 'f':
+               case 'e':
+                       dval = 0.;
+                       negflg = 0;
+                       val = 0;        /* used for explicit exponent */
+                       radix = 0100000; /* used for decimal place count */
+                       while ((cc = NEXTCHR) && (cc == ' ' || cc == '-') && --wv)
+                               if (cc == '-') negflg++;
+                       if (!cc) return (fld);  /* return error if eof found */
+                       if (wv) do {
+                               if (numeric(cc)) {
+                                       dval = dval*10. + (cc-'0');
+                                       radix++;
+                               } else if (cc == '.') {
+                                       radix = 0;
+                                       dv = -1;
+                               } else if (any(cc,fsp)) break;
+                               else if (cc == 'e') {
+                                       negexp = 0;
+                                       while ((cc = NEXTCHR) && !numeric(cc) && --wv)
+                                               if (cc == '-') negexp++;
+                                       if (!cc) return (fld);  /* return error if eof found */
+                                       if (wv) do {
+                                               if (numeric(cc))
+                                                       val = val*10 + cc-'0';
+                                               else if (any(cc,fsp)) break;
+                                       } while (--wv && (cc = NEXTCHR));
+                                       if (negexp) val = -val;
+                                       break;
+                               }
+                       } while (--wv && (cc = NEXTCHR));
+                       if (dv > 0) radix = dv;
+                       if (radix > 0) val =- radix;
+                       if (val >= 0)
+                               while (--val >= 0) dval = dval*10.;
+                       else
+                               while (++val <= 0) dval = dval/10.;
+                       if (negflg) dval = -dval;
+                       if (formc == 'f')
+                               *ap->fltp = dval;
+                       else
+                               *ap->dblp = dval;
+                       ap++;
+                       break;
+               default:
+                       write(2,"bad format specification",20);
+                       exit(fld);
+               }
+               cc = *fp++;
+       }
+       return (0);
+}
+numeric(chr)
+{
+       return (chr >= '0' && chr <= 
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/Extras/libh/length.c b/docs/historical/mh-jun-1982/Extras/libh/length.c
new file mode 100644 (file)
index 0000000..2b65072
--- /dev/null
@@ -0,0 +1,16 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+/* return length of a string, not counting the null terminator */
+length(str)
+char *str;
+{
+       register char *cp;
+
+       for (cp = str; *cp++; );
+       return(cp-str-1);
+}
diff --git a/docs/historical/mh-jun-1982/Extras/libh/makename.c b/docs/historical/mh-jun-1982/Extras/libh/makename.c
new file mode 100644 (file)
index 0000000..0e0fcc0
--- /dev/null
@@ -0,0 +1,23 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+makename(prefix,suffix)
+char *prefix, *suffix;
+{
+       static char tmpname[15];
+       register char *cp1, *cp2;
+       register int pid;
+
+       pid = getpid();
+       cp1 = tmpname;
+       for (cp2 = prefix; *cp1++ = *cp2++; );
+       cp1--;
+       do *cp1++ = pid%10 + '0'; while (pid =/ 10);
+       for (cp2 = suffix; *cp1++ = *cp2++; );
+       if (cp1 > &tmpname + 1) error("strs too long to makename");
+       return (tmpname);
+}
diff --git a/docs/historical/mh-jun-1982/Extras/libh/prndec.c b/docs/historical/mh-jun-1982/Extras/libh/prndec.c
new file mode 100644 (file)
index 0000000..a510080
--- /dev/null
@@ -0,0 +1,33 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+prndec(ch, d)
+{
+       char buf[8];
+       register char *cp;
+       register int i, j;
+
+       i = d;
+       cp = &buf[8];
+       *--cp = 0;
+       j = 0;
+       if(i < 0) {
+               i =- i;
+               j =+ 10;
+       }
+       do {
+               *--cp = (i % 10) + '0';
+               i =/ 10;
+               j++;
+       } while(i);
+       if(j > 10) {
+               j =- 9;
+               *--cp = '-';
+       }
+       write(ch, cp, j);
+       return(j);
+}
diff --git a/docs/historical/mh-jun-1982/Extras/libh/subshell.c b/docs/historical/mh-jun-1982/Extras/libh/subshell.c
new file mode 100644 (file)
index 0000000..eb8a88e
--- /dev/null
@@ -0,0 +1,44 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../h/errors.h"
+
+subshell(str)
+char *str;
+{
+       register s2, s3;
+       char *a2, *a3;
+       register pid;
+       char st[2];
+       /* if str is non null, exec it as a command to the shell */
+       /* and return immediately */
+       /* if str is the null string, simply spawn a sub-shell */
+
+       if (str == 0 || *str == 0) {
+               a2 = 0;
+               a3 = 0;
+       } else {
+               a2 = "-c";
+               a3 = str;
+       }
+       pid = fork();
+       if (pid == 0) {
+               execl("/bin/sh", "-", a2, a3, 0);
+               error("no shell!");
+       }
+       if (pid == -1) {
+               type(2, errno == EAGAIN? "system": "your");
+               type(2, " process limit reached\n");
+               return(-1);
+       }
+       s2 = signal(2,1);
+       s3 = signal(3,1);
+       while(pid != wait(&st));
+       signal(2,s2);
+       signal(3,s3);
+       return(st[1]);
+}
diff --git a/docs/historical/mh-jun-1982/Extras/libh/swmtch.c b/docs/historical/mh-jun-1982/Extras/libh/swmtch.c
new file mode 100644 (file)
index 0000000..1f9e490
--- /dev/null
@@ -0,0 +1,35 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+/* switch match, or any unambiguous abbreviation */
+/* exact match always wins, even if shares same root */
+/* returns subscript in zero-terminated tbl[] of strings */
+/* returns -1 if no match, -2 if ambiguous */
+
+swmtch(string,tbl)
+char *tbl[],*string;
+{
+       register char *sp, *tcp, c;
+       char **tp;
+       int firstone;
+
+       firstone = -1;
+
+       for (tp=tbl; tcp = *tp; tp++) {
+               for (sp = string; *sp == *tcp++; ) {
+                       if (*sp++ == 0) return(tp-tbl); /* exact match */
+               }
+               if (*sp != 0) {
+                       if (*sp != ' ') continue; /* no match */
+                       if (*--tcp == 0) return(tp-tbl); /* exact match */
+               }
+               if (firstone == -1) firstone = tp-tbl; /* possible match */
+               else firstone = -2;     /* ambiguous */
+       }
+
+       return (firstone);
+}
diff --git a/docs/historical/mh-jun-1982/Extras/libh/t.c b/docs/historical/mh-jun-1982/Extras/libh/t.c
new file mode 100644 (file)
index 0000000..c911f5c
--- /dev/null
@@ -0,0 +1,15 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+
+extern errno;
+
+main()
+{
+       execl("foo", "foo", 0);
+       printf("errno=%d\n", errno);
+}
diff --git a/docs/historical/mh-jun-1982/Extras/libh/type.c b/docs/historical/mh-jun-1982/Extras/libh/type.c
new file mode 100644 (file)
index 0000000..1b3efcc
--- /dev/null
@@ -0,0 +1,17 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+type(ch, s)
+char *s;
+{
+       register char *p;
+
+       for (p = s; *p++; );
+       --p;
+       write(ch, s, p-s);
+       return(p-s);
+}
diff --git a/docs/historical/mh-jun-1982/Extras/mailsys.h b/docs/historical/mh-jun-1982/Extras/mailsys.h
new file mode 100644 (file)
index 0000000..3b56dc1
--- /dev/null
@@ -0,0 +1,19 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#define MSGRETTIME      (5*24*60*60)    /* How long to keep trying */
+#define MAILQDIR        "/usr/spool/netmail/"
+#define MAILDROP        "/usr/spool/mail/"
+#define TMAILQDIR       "/usr/spool/mailt/"
+#define MAILLOCKDIR     "/usr/spool/locks/"
+#define MAILALIASES     "/etc/MailAliases"
+
+/* Exit codes from net mailer */
+#define NM_OK        0  /* Delivered */
+#define NM_BAD       1  /* Not delivered to some addresses (perm failure) */
+#define NM_MORE      2  /* Some addresses not yet processed (temp failure) */
+#define NM_BADMORE   3  /* Both of above */
diff --git a/docs/historical/mh-jun-1982/Extras/resp.bld b/docs/historical/mh-jun-1982/Extras/resp.bld
new file mode 100644 (file)
index 0000000..a770af0
--- /dev/null
@@ -0,0 +1,5 @@
+if -r resp rm resp
+load -s resp replsubs annotate subs.a strings.a -O /rnd/borden/libg.a /rnd/borden/libh.a /rnd/borden/libg.a
+if -r resp.out mv resp.out resp
+:                                      fini
+
diff --git a/docs/historical/mh-jun-1982/Extras/resp.c b/docs/historical/mh-jun-1982/Extras/resp.c
new file mode 100644 (file)
index 0000000..ec7bd53
--- /dev/null
@@ -0,0 +1,329 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "mh.h"
+#include "/rnd/borden/h/iobuf.h"
+#include "/rnd/borden/h/signals.h"
+#define NOUSE 0
+
+/* #define TEST 1 */
+
+char    draft[],
+       sysed[],
+
+char    *anyl[] {
+       "no",   0,
+       "yes",  0,
+       "list", 0,
+       0
+};
+char *aleqs[] {
+       "list",              0,         /* 0 */
+       "edit [<editor>]",   0,         /* 1 */
+       "quit [delete]",     0,         /* 2 */
+       "send [verbose]",    0,         /* 3 */
+       0
+};
+
+int  *vec[MAXARGS], fout, anot;
+int ccme 1;
+char *maildir;
+struct msgs *mp;
+char *ed;
+int inplace;            /* preserve links in anno */
+
+struct swit switches[] {
+       "annotate",           0,      /* 0 */
+       "noannotate",         0,      /* 1 */
+       "ccme",              -1,      /* 2 */
+       "noccme",            -1,      /* 3 */
+       "editor editor",      0,      /* 4 */
+       "inplace",            0,      /* 5 */
+       "noinplace",          0,      /* 6 */
+       "help",               4,      /* 7 */
+       0,                    0
+};
+
+main(argc, argv)
+char *argv[];
+{
+       char *folder, *nfolder, *msg;
+       register char *cp, *ap;
+       register int cur;
+       char *arguments[50], **argp;
+
+       fout = dup(1);
+#ifdef NEWS
+       m_news();
+#endif
+       msg = anot = folder = 0;
+
+       ap = cp = argv[0];
+       while(*cp)
+               if(*cp++ == '/')
+                       ap = cp;
+       if((cp = m_find(ap)) != -1) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                            /* unknown */
+                       case -1:printf("resp: -%s unknown\n", cp);
+                               goto leave;
+                       case 0: anot = 1;  continue;         /* -annotate */
+                       case 1: anot = 0;  continue;         /* -noannotate */
+                       case 2: ccme = 1;  continue;         /* -ccme */
+                       case 3: ccme = 0;  continue;         /* -noccme */
+                       case 4: if(!(ed = *argp++)) {        /* -editor */
+               printf("resp: Missing argument for %s switch\n", argp[-2]);
+                                       goto leave;
+                               }
+                               continue;
+                       case 5: inplace = 1;  continue;      /* -inplace */
+                       case 6: inplace = 0;  continue;      /* -noinplace */
+                                                            /* -help */
+                       case 7: help("resp   [+folder] [msg] [switches]",
+                                    switches);
+                               goto leave;
+                       }
+               if(*cp == '+') {
+                       if(folder) {
+                               printf("Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               folder = cp + 1;
+               } else if(msg) {
+                       printf("Only one message per response.\n");
+                       goto leave;
+               } else
+                       msg = cp;
+       }
+       if(!msg)
+               msg = "cur";
+       if(!folder)
+               folder = m_getfolder();
+       maildir = getcpy(m_maildir(folder));
+       if(chdir(maildir) < 0) {
+               printf("Can't chdir to: "); flush();
+               perror(maildir);
+               goto leave;
+       }
+       if(!(mp = m_gmsg(folder))) {
+               printf("Can't read folder!?\n");
+               goto leave;
+       }
+       if(mp->hghmsg == 0) {
+               printf("No messages in \"%s\".\n", folder);
+               goto leave;
+       }
+       if(!m_convert(msg))
+               goto leave;
+       if(mp->numsel == 0) {
+               printf("resp: shark's fin soup\n");      /* never get here */
+               goto leave;
+       }
+       if(mp->numsel > 1) {
+                printf("Only one message at a time.\n");
+                goto leave;
+       }
+       m_replace(pfolder, folder);
+       if(mp->lowsel != mp->curmsg)
+               m_setcur(mp->lowsel);
+       repl(getcpy(m_name(mp->lowsel)));
+ leave:
+       m_update();
+       flush();
+}
+
+
+repl(msg)
+{
+       register char *cp;
+       register int i,j;
+       struct iobuf in;
+       char name[NAMESZ], field[512], *replto, *from, *cc, *sub, *date, *to;
+       char *drft, *msgid;
+       int state, out, status, intr;
+       int pid, wpid;
+       char **argp, *address;
+
+       if(fopen(msg, &in) < 0) {
+               printf("Can't open \"%s\"\n", msg);
+               return;
+       }
+       drft = m_maildir(draft);
+       if((out = open(drft, 0)) >= 0) {
+               cp = concat("\"", drft, "\" exists; delete? ", 0);
+               while((i = gans(cp, anyl)) == 2)
+                       showfile(drft);
+               if(!i)
+                       return;
+               free(cp);
+               close(out);
+       }
+       if((out = creat(drft, m_gmprot())) < 0) {
+               printf("Can't create \"%s\".\n", drft);
+               return;
+       }
+
+       state = FLD;
+       replto = msgid = to = from = cc = sub = date = 0;
+
+    for(;;) {
+
+       switch(state = m_getfld(state, name, field, sizeof field, &in)) {
+
+       case FLD:
+       case FLDEOF:
+       case FLDPLUS:
+               if(uleq(name, "from"))
+                       from = niceadd(field, from);
+               if(uleq(name, "cc"))
+                       cc = niceadd(field, cc);
+               if(uleq(name, "subject"))
+                       sub = niceadd(field, sub);
+               if(uleq(name, "date"))
+                       date = niceadd(field, date);
+               if(uleq(name, "to"))
+                       to = niceadd(field, to);
+               if(uleq(name, "message-id"))
+                       msgid = niceadd(field, msgid);
+               if(uleq(name, "reply-to"))
+                       replto = niceadd(field, replto);
+       /*      if(uleq(name, "sender"))
+                       sender = niceadd(field, sender);        */
+               if(state == FLDEOF)
+                       goto done;
+               break;
+
+       case BODY:
+       case BODYEOF:
+       case FILEEOF:
+               goto done;
+
+       default:
+               printf("getfld returned %d\n", state);
+               return;
+       }
+
+    }
+
+done:
+
+    /*  if(!(address = addr(sender)))
+               if(!(address = addr(from)))
+                       address = addr(replto);
+      */
+       address = (replto ? addr(replto) : addr(from));
+       if(!ccme)
+               to = 0;
+       if(!(from || replto || to)) {
+               printf("No one to respond to!!!\n");
+               return;
+       }
+       close(in.b_fildes);
+       if(replto)
+               rtrim(replto);
+       if(from)
+               rtrim(from);
+       type(out, "To: ");                      /* To: */
+       if(cp = (replto ? replto : from))
+               type(out, cp);
+       if(to) {
+               if(cp)
+                       type(out, ",\n    ");
+               if(address)
+                       to = fix(to, address);
+               type(out, to);
+       }
+       if(cc) {                                /* cc */
+               type(out, "cc: ");
+               if(address)
+                       cc = fix(cc, address);
+               type(out, cc);
+       }
+       if(sub) {                               /* Subject: Re: */
+               type(out, "Subject: ");
+               if(*sub == ' ') sub++;
+               if((sub[0] != 'R' && sub[0] != 'r') ||
+                  (sub[1] != 'E' && sub[1] != 'e') ||
+                  sub[2] != ':')
+                       type(out, "Re: ");
+               type(out, sub);
+       }                                       /* In-response-to: */
+       type(out, "In-response-to: Message from ");
+       type(out, from);
+       if(date) {
+               date[length(date)-1] = '.';
+               if(*date == ' ') date++;
+               type(out, ", ");
+               type(out, date);
+       }
+       type(out, "\n");
+       if(msgid) {
+               type(out, "                ");
+               if(*msgid == ' ') msgid++;
+               type(out, msgid);
+       }
+       type(out, "\t\t");
+       type(out, maildir);
+       type(out, "/");
+       type(out, msg);
+       type(out, "\n----------\n");
+       close(out);
+
+       if(m_edit(&ed, drft, NOUSE, msg) < 0)
+               return;
+#ifdef TEST
+       printf("!! Test Version of SEND Being Run !!\n");
+       printf("   Send verbose !\n\n");
+#endif
+
+    for(;;) {
+       if(!(argp = getans("\nWhat now? ", aleqs))) {
+               unlink("@");
+               return;
+       }
+       switch(smatch(*argp, aleqs)) {
+               case 0: showfile(drft);                         /* list */
+                       break;
+               case 1: if(*++argp)                             /* edit */
+                               ed = *argp;
+                       if(m_edit(&ed, drft, NOUSE, msg) == -1)
+                               return;
+                       break;
+               case 2: if(*++argp && *argp[0] == 'd')          /* quit */
+                               if(unlink(drft) == -1)  {
+                                       printf("Can't unlink %s ", drft);
+                                       perror("");
+                               }
+                       return;
+               case 3: if(*++argp) cp = *argp;  else cp = "";  /* send */
+
+                       if(!mp->msgflags&READONLY) {    /* annotate first */
+                           if(anot > 0) {
+                               while((pid = fork()) == -1) sleep(5);
+                               if(pid) {
+                                       while(wpid=wait()!= -1 && wpid!= pid);
+                                       if(stat(drft, field) == -1)
+                                               annotate(msg, "Responded", "");
+                                       return;
+                               }
+                           }
+                       }
+                       if(!m_send(cp, drft))
+                               return;
+               default:printf("resp: illegal option\n");       /*##*/
+                       break;
+       }
diff --git a/docs/historical/mh-jun-1982/Extras/sndmsg.bld b/docs/historical/mh-jun-1982/Extras/sndmsg.bld
new file mode 100644 (file)
index 0000000..83286c2
--- /dev/null
@@ -0,0 +1,10 @@
+if -r sndmsg.out rm sndmsg.out
+load sndmsg subs.a strings.a -O /rnd/borden/libg.a /rnd/borden/libh.a
+if ! -r sndmsg.out /rnd/borden/bin/skip {
+: strip sndmsg.out
+if $1x = x /rnd/borden/bin/skip {
+cp sndmsg.out /etc/ms.2.78/xsnd
+rm sndmsg.out
+: }
+:                                      fini
+
diff --git a/docs/historical/mh-jun-1982/Extras/sndmsg.c b/docs/historical/mh-jun-1982/Extras/sndmsg.c
new file mode 100644 (file)
index 0000000..481f438
--- /dev/null
@@ -0,0 +1,550 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "mh.h";
+#include "/rnd/borden/h/iobuf.h"
+#include "/rnd/borden/h/stat.h"
+
+/*#define DEBUG 1         /* Comment out normally */
+
+/* Include a -msgid switch to .mh_profile to cause a
+ * Message-Id component to be added to outgoing mail.
+ */
+
+char *anoyes[];         /* Std no/yes gans array        */
+struct swit switches[] {
+       "debug",         -1,      /* 0 */
+       "format",         0,      /* 1 */
+       "noformat",       0,      /* 2 */
+       "msgid",          0,      /* 3 */
+       "nomsgid",        0,      /* 4 */
+       "verbose",        0,      /* 5 */
+       "noverbose",      0,      /* 6 */
+       "help",           4,      /* 7 */
+       0,                0
+};
+struct iobuf in, pin, pout, fout, fccout;
+int     format  1;              /* re-formatting is the default */
+
+char    *logn, *parptr, *nmsg, fccfile[256];
+
+main(argc, argv)
+char *argv[];
+{
+       int debug;
+       register char *cp, *msg;
+       register int state;
+       char *to, *cc, *bcc, *dist_to, *dist_cc, *dist_bcc;
+       char *tolist, *cclist, *adrlist, *sender, *fcc, *dist_fcc;
+       char name[NAMESZ], field[512];
+       int specfld, dist, fcconly;
+       int from, loc, net, verbose, msgid;
+       int toseen, ccseen;
+       char *ap;
+       char *arguments[50], **argp;
+
+       fout.b_fildes = dup(1);
+       msgid = from = loc = net = to = cc = bcc = dist = fcc = dist_fcc =
+               dist_to = dist_cc = dist_bcc = fcconly = debug =
+               toseen = ccseen = 0;
+       state = FLD;
+       msg = 0;
+       copyip(argv+1, arguments);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                       /* unknown */
+                       case -1:printf("sndmsg: -%s unknown\n", cp);
+                               goto leave;
+                       case 0: verbose++; debug++; continue; /* -debug */
+                       case 1: format = 1; continue;         /* -format */
+                       case 2: format = 0; continue;         /* -noformat */
+                       case 3: msgid = 1;  continue;         /* -msgid */
+                       case 4: msgid = 0;  continue;         /* -nomsgid */
+                       case 5: loc = 1; net = 1; continue;   /* -verbose */
+                       case 6: loc = 0; net = 0; continue;   /* -noverbose */
+                       case 7: help("sndmsg [file]   [switches]",
+                                    switches);
+                               goto leave;
+                       }
+               if(msg) {
+                       printf("Only one message at a time!\n");
+                       goto leave;
+               } else
+                       msg = cp;
+       }
+       if(!msg) {
+               printf("No Message specified.\n");
+               goto leave;
+       }
+       if(fopen(msg, &in) < 0) {
+               printf("Can't open \"%s\" for reading.\n", msg);
+               goto leave;
+       }
+
+       state = FLD;
+
+    for(;;)
+       switch(state = m_getfld(state, name, field, sizeof field, &in)) {
+
+       case FLD:
+       case FLDEOF:
+       case FLDPLUS:
+               if(!dist && uleq(name, "to"))
+                       to = add(field, to);
+               else if(!dist && uleq(name, "cc"))
+                       cc = add(field, cc);
+               else if(!dist && uleq(name, "bcc"))
+                       bcc = add(field, bcc);
+               else if(!dist && uleq(name, "fcc"))
+                       fcc = add(field, fcc);
+               else if(uleq(name, "distribute-to"))
+               {       dist++;         /* use presence of field as flag */
+                       dist_to = add(field, dist_to);
+               }
+               else if(uleq(name, "distribute-cc"))
+                       dist_cc = add(field, dist_cc);
+               else if(uleq(name, "distribute-bcc"))
+                       dist_bcc = add(field, dist_bcc);
+               else if(uleq(name, "distribute-fcc"))
+                       dist_fcc = add(field, dist_fcc);
+               else if(uleq(name, "from"))
+                       from++;
+
+               if(state == FLDEOF)
+                       goto done;
+               continue;
+
+       case BODY:
+       case BODYEOF:
+               goto done;
+
+       default:
+               printf("getfld returned %d\n", state);
+               goto leave;
+       }
+
+done:
+       if (dist)
+       {       to = dist_to;
+               cc = dist_cc;
+               bcc = dist_bcc;
+               fcc = dist_fcc;
+       }
+       if (!(to || cc))
+               if(!fcc) {
+                       printf("Message %s has no addresses!!\n", msg);
+                       goto leave;
+               } else
+                       fcconly++;
+       pin.b_fildes = dup(2);
+       pout.b_fildes = 3;
+
+       if(to)
+               if(parse(to, 'c'))
+                       goto leave;
+       if(cc)
+               if(parse(cc, 'c'))
+                       goto leave;
+       if(bcc)
+               if(parse(bcc, 'c'))
+                       goto leave;
+
+       compress();
+       adrlist = parptr; parptr = 0;
+       if(verbose) {
+               printf("Address List:\n%s", adrlist);
+               flush();
+       }
+
+       if(to)
+               if(parse(to, 'r', dist ? "Distribute-To: " : "To: "))
+                       goto leave;
+       tolist = parptr; parptr = 0;
+       if(cc)
+               if(parse(cc, 'r', dist ? "Distribute-cc: " : "cc: "))
+                       goto leave;
+       cclist = parptr; parptr = 0;
+
+       if(verbose) {
+               if (tolist) printf(tolist);
+               if (cclist) printf(cclist);
+               flush();
+       }
+       if(fcc) {
+               if(*fcc == ' ')
+                       fcc++;
+               for(cp = fcc; *cp && *cp != '\n'; cp++) ;
+               *cp = 0;
+               if(debug)
+                       printf("fcc: \"%s\"\n", fcc); flush();
+               if((fccout.b_fildes = filemsg(fcc)) == -1)
+                       goto leave;
+       }
+       copy("\n", copy((logn = getlogn(getruid())), field));
+       if(parse(field, 'r', dist ? "Distributed-By: " :
+              (from ? "Sender: ":"From: ")))
+               goto leave;
+       sender = parptr; parptr = 0;
+       seek(in.b_fildes, 0, 0);
+       if(debug)
+               pout.b_fildes = 1;  /* Send msg to std output for debugging */
+       else if(fcconly)
+               pout.b_fildes = 0;  /* Flush send output if only an fcc */
+       cputc('s', &pout);
+       if(loc)
+               cputc('l', &pout);
+       if(net)
+               cputc('n', &pout);
+       cputc('\n', &pout);
+       puts(logn, &pout);
+       cputc('\n', &pout);
+       puts(adrlist, &pout);
+       puts("!\n", &pout);
+       puts2(sender, &pout);
+       puts2(dist ? "Distribution-Date: " : "Date: ", &pout);
+       puts2(gd(), &pout);
+       if(msgid) {
+               puts2(dist ? "Distribution-ID: " : "Message-ID: ", &pout);
+               puts2(gmid(), &pout);
+       }
+       seek(in.b_fildes, 0, 0);
+       in.b_nleft = in.b_nextp = 0;
+
+       state = FLD;
+
+    for(;;)
+       switch(state = m_getfld(state, name, field, sizeof field, &in)) {
+
+       case FLD:
+       case FLDEOF:
+       case FLDPLUS:
+               specfld = 0;
+               if(format && uleq(name,dist ? "distribute-to":"to")) {
+                       if(!toseen) {
+                               toseen++;
+                               specfld++;
+                               if (tolist)
+                                       puts2(tolist,&pout);
+                       }
+               } else if (format && uleq(name,dist ?"distribute-cc":"cc")) {
+                       if(!ccseen) {
+                               ccseen++;
+                               specfld++;
+                               if (cclist)
+                                       puts2(cclist,&pout);
+                       }
+               } else if (uleq(name,dist ? "distribute-bcc" : "bcc") ||
+                    uleq(name,dist ? "distributed-by" : "sender") ||
+                    uleq(name,dist ? "distribution-date" : "date") ||
+                    uleq(name,dist ? "distribution-id" : "message-id") ||
+                    uleq(name,dist ? "distribution-fcc" : "fcc")) {
+                       specfld++;      /* Ignore these if present */
+               } else {
+                       puts2(name, &pout);
+                       puts2(":", &pout);
+                       puts2(field, &pout);
+               }
+               while(state == FLDPLUS) {       /* read rest of field */
+                       state=m_getfld(state, name, field, sizeof field, &in);
+                       if (specfld) continue;
+                  /*   puts2(name, &pout);
+                       puts2(":", &pout);  */
+                       puts2(field, &pout);
+               }
+               if(state == FLDEOF)
+                       goto endit;
+               continue;
+       case BODY:
+       case BODYEOF:
+               if(field[0]) {
+                       puts2("\n", &pout);
+                       puts2(field, &pout);
+               }
+
+               while(state == BODY) {
+                       state=m_getfld(state, name, field, sizeof field, &in);
+                       puts2(field, &pout);
+               }
+               if(state == BODYEOF)
+                       goto endit;
+       default:
+               printf("Error from getfld=%d\n", state);
+               goto leave;
+       }
+endit:
+       if(pout.b_fildes)
+               fflush(&pout);
+       if(fccout.b_fildes) {
+               fflush(&fccout);
+               close(fccout.b_fildes);
+       }
+       if(!debug && !fcconly) {
+               write(3, "", 1);
+               if((state = read(2, &field, sizeof field)) != 1 || field[0]) {
+                       printf("Error from adrparse.\n");
+                       goto leave;
+               }
+       }
+       if(fccout.b_fildes)
+               printf("Filed: %s:%s\n", fcc, nmsg);
+       if(!debug) {
+               if(!fcconly) {
+                       printf("Message %s sent.\n", msg);
+                       flush();
+               }
+               cp = copy(msg, field);
+           /*  for(cp = field; *cp++; ) ;  */
+               cp[1] = 0;
+               do
+                       *cp = cp[-1];
+               while(--cp >= field && *cp != '/');
+               *++cp = ',';                    /* New backup convention */
+               unlink(field);
+               if(link(msg, field) == -1 || unlink(msg) == -1)
+                       printf("Can't rename %s to %s\n", msg, field);
+       }
+       m_update();
+       flush();
+       done(0);
+leave:
+       printf("[Message NOT Delivered!]\n");
+       if(fccout.b_fildes)
+               unlink(fccfile);
+       m_update();
+       flush();
+       done(1);
+}
+
+
+parse(ptr, type, fldname)
+char *fldname;
+{
+       register int i;
+       register int l;
+       char line[128];
+
+       putc(type, &pout);
+       puts("\n", &pout);
+       puts(ptr, &pout);
+       fflush(&pout);
+       write(3, "", 1);
+       l = 0;
+
+       while((i = getl(&pin, line, (sizeof line) - 1)) > 0) {
+               line[i] = 0;
+               if(line[0] == 0)
+               {       if (type == 'r')
+                       {       if (l > 0)
+                                       parptr = add("\n",parptr);
+                       }
+                       return(0);
+               }
+               else if(line[0] == '?') {
+                       printf("Adrparse: %s", line);
+                       return(1);
+               }
+               if (type == 'r')
+               {       line[--i] = 0;
+                       if (l+i > 70)
+                       {       parptr = add("\n",parptr);
+                               l = 0;
+                       }
+                       if (l == 0)
+                       {       parptr = add(fldname,parptr);
+                               l =+ length(fldname);
+                       }
+                       else
+                       {       parptr = add(", ",parptr);
+                               l =+ 2;
+                       }
+                       parptr = add(line+1, parptr);
+                       l =+ i;
+               }
+               else
+                       parptr = add(line, parptr);
+       }
+       printf("Error from adrparse.\n");
+       return(1);
+}
+
+gmid()
+{
+       static char bufmid[128];
+       long now;
+       register char *cp, *c2;
+       register int *ip;
+
+       cp = bufmid;
+       *cp++ = '<';
+       cp = copy(locv(0, getruid()), cp);
+       *cp++ = '.';
+       time(&now);
+       cp = copy(locv(now), cp);
+       cp = copy("@Rand-Unix>\n", cp);
+       *cp = 0;
+       return(bufmid);
+}
+
+#ifdef COMMENT
+gmid()
+{
+       static char bufmid[128];
+       long now;
+       register char *cp, *c2;
+
+       cp = bufmid;
+       cp = copy("<[Rand-Unix]", cp);
+       time(&now);
+       c2 = cdate(&now);
+       c2[9] = ' ';
+       c2[18] = 0;
+       cp = copy(c2, cp);
+       *cp++ = '.';
+       cp = copy(logn, cp);
+       *cp++ = '>';
+       *cp++ = '\n';
+       *cp = 0;
+       return(bufmid);
+}
+#endif
+
+gd()
+{
+       register char *t, *p;
+       register int *i;
+       static bufgd[32];
+       extern char *tzname[];
+       long now;
+
+       time(&now);
+       t = ctime(&now);
+       p = bufgd;
+
+       *p++ = t[8];
+       *p++ = t[9];
+       *p++ = ' ';
+       *p++ = t[4];
+       *p++ = t[5];
+       *p++ = t[6];
+       *p++ = ' ';
+       *p++ = t[20];
+       *p++ = t[21];
+       *p++ = t[22];
+       *p++ = t[23];
+       *p++ = ' ';
+       *p++ = 'a';
+       *p++ = 't';
+       *p++ = ' ';
+       *p++ = t[11];
+       *p++ = t[12];
+       *p++ = t[14];
+       *p++ = t[15];
+       *p++ = '-';
+       i = localtime(&now);
+       t = tzname[i[8]];
+       *p++ = *t++;
+       *p++ = *t++;
+       *p++ = *t++;
+       *p++ = '\n';
+       *p++ = 0;
+       return(bufgd);
+}
+
+
+getl(iob, buf, size)
+{
+       register char *cp;
+       register int cnt, c;
+
+       cp = buf; cnt = size;
+
+       while((c = getc(iob)) >= 0) {
+               *cp++ = c;
+               --cnt;
+               if(c == 0 || c == '\n' || cnt == 0)
+                       break;
+       }
+       return(size - cnt);
+}
+
+
+compress()
+{
+       register char *f1, *f2, *f3;
+
+#ifdef DEBUG
+       printf("compress:\n%s-----\n", parptr);
+#endif
+       for(f1 = parptr; *f1; ) {
+               for(f2 = f1; *f2++ != '\n'; ) ;
+               while(*f2) {
+                       if(eqqq(f1, f2)) {
+                               for(f3 = f2; *f3++ != '\n'; ) ;
+                               copy(f3, f2);
+                       } else
+                               while(*f2++ != '\n') ;
+               }
+               while(*f1++ != '\n') ;
+       }
+}
+
+
+eqqq(s1, s2)
+{
+       register char *c1, *c2;
+
+       c1 = s1; c2 = s2;
+       while(*c1 != '\n' && *c2 != '\n')
+               if((*c1++|040) != (*c2++|040))
+                       return(0);
+       return((*c1|040) == (*c2|040));
+}
+
+
+filemsg(folder)
+char *folder;
+{
+       register int i;
+       register char *fp;
+       struct inode stbuf;
+       struct msgs *mp;
+
+       fp = m_maildir(folder);
+       if(stat(fp, &stbuf) < 0) {
+               nmsg = concat("Create folder \"",
+                       fp, "\"? ", 0);
+               if(!gans(nmsg, anoyes))
+                       return(-1);
+               if(!makedir(fp)) {
+                       printf("Can't create folder.\n");
+                       return(-1);
+               }
+       }
+       if(chdir(fp) < 0) {
+               perror(concat("Can't chdir to ", fp, 0));
+               return(-1);
+       }
+       if(!(mp = m_gmsg())) {
+               printf("Can't read folder %s\n", folder);
+               return(-1);
+       }
+       nmsg = m_name(mp->hghmsg + 1);
+       copy(nmsg, copy("/", copy(m_maildir(fp), fccfile)));
+       if((i = creat(fccfile, m_gmprot())) == -1)
+               printf("Can't create %s\n", fccfile);
+       return(i);
+}
+
+
+puts2(str, iob)
+{
+       puts(str, &fccout);
+       puts(str, i
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/Extras/strings.h b/docs/historical/mh-jun-1982/Extras/strings.h
new file mode 100644 (file)
index 0000000..4676960
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * Type definitions for the strings(3) subroutines.
+ */
+
+char   *strcat();
+char    *strncat();
+char   *strcpy();
+char    *strncpy();
+int     strcmp();
+int     strncmp();
+char   *index();
+char   *rindex();
diff --git a/docs/historical/mh-jun-1982/Extras/whoami.h b/docs/historical/mh-jun-1982/Extras/whoami.h
new file mode 100644 (file)
index 0000000..fdd5c3b
--- /dev/null
@@ -0,0 +1,13 @@
+/* USE THIS FILE AS AN EXAMPLE ONLY */
+/* You must fill in your own stuff in your whoami.h, which you already have */
+
+#define sysname "youruucpname"
+
+/* Omit these if not on the ARPANET */
+#define HOSTNAME "ARPA-NAME"    /* Arpa STANDARD host name for us */
+#define HOSTNUM  nnn            /* Short style host number */
+#define HOSTHOST nnn            /* For long style host/imp numbers */
+#define HOSTIMP  nnn            /*  ditto */
+
+/* HOSTNUM = (HOSTHOST<<6)|HOSTIMP  which only works if host is 0-3 */
+/*   since result must fit in a byte.   */
diff --git a/docs/historical/mh-jun-1982/Log b/docs/historical/mh-jun-1982/Log
new file mode 100644 (file)
index 0000000..ce63193
--- /dev/null
@@ -0,0 +1,300 @@
+2/16/81 progs Dave Yost:
+       Fixed folder so that it checks value from m_gmsg and complains
+       if the folder is unreadable.  All other commands that call it
+       do this, so it was simply an error of omission.
+
+2/16/81 subs Dave Yost:
+       m_gmsg.c was testing return value of malloc against -1.
+       Tsk.
+
+2/16/81 subs Phyllis Kantar
+       trimcpy.c was scanning profile fields from the left and
+       truncating ('\0') at the first newline.  It now zaps
+       the trailing newline and replaces embedded NL's with blanks.
+
+2/23/81 progs phyl:
+       Fixed annotation so that it annotates only "To:" and "cc:"
+           In forw.c  doano():
+                   Changed
+                           if(uleq(name, "to") || uleq(name, "cc") == 0) {
+                   to:
+                           if(uleq(name, "to") || uleq(name, "cc") ) {
+
+       Similarly for dist.c
+       Changed /etc/mh/distcomps to read "Distribute*"
+               instead of "Distribution*"
+
+       Also, fixed bug in annotate.c:
+               fprintf(tmp, "%s: %*s", comp, cp-sp, sp);
+                       should be
+               fprintf(tmp, "%s: %*.*s", comp, cp-sp, cp-sp, sp);
+
+       Note: none of these fixes affects repl
+
+
+
+3/23/81 progs jdg/day:  changed deliver.c to check for effective uid and gid
+       while it is preventing forgery of mail.  Needed for uucp, when
+       uucico is invoked by a real person instead of uucp itself.
+
+4/7/81  progs Dave-Yost
+       Fixed scansub.c to check for HOSTNAME instead of "rand-unix".
+       A little portability, please.
+
+4/13/81 progs  Dave-Yost
+       Changed deliver to put out a date format like
+         Monday, 13 Apr 1981 20:46-PST
+       instead of
+         13 Apr 1981 at 2046-PST
+
+4/13/81 subs Dave Yost
+       modified m_edit.c to exec the editor with altmsg as an extra
+       argument, in case the editor can use it as an alt file.
+
+5/7/81  progs Dave-Yost
+       Changed conflict.c and conflict.8 to ignore /usr/spool/mail
+       files starting with '.'.
+
+5/7/81  progs Dave-Yost
+       conflict isn't smart about the fact that there can be
+       more than one login name on the same uid.  This should
+       be fixed.
+
+5/29/81 progs Phyl
+       Changed /usr/news/.mh_receive to grep for
+
+               '^[Tt][Oo]:.*news\.'
+
+       instead of
+
+               '[Tt][Oo]:'
+
+       However, 'news' will still break when there are multiple news folders
+        in the 'To:' field(s)!
+
+7/2/81  progs Phyl:
+       Changed inc.c and scansub.c so that mail is not lost when
+               the message number exceeds 999.
+
+7/2/81  progs day:
+       mh.h has #define MAXFOLDER 999 and hopefully all occurrences
+       of that magic number have been changed to MAXFOLDER.
+
+7/2/81  progs day:
+        Fixed pick and file so they won't go beyond 999 (MAXFOLDER)
+       into a folder.  file.c and pick.c had virtually identical
+        copies of the same routine to file a message.  Took it out and
+       put it into subs as m_file(), and changed it to have
+        several arguments so there are no connections via globals.
+        Also created ../folder.h which is included by pick.c, file.c,
+        and ../subs/m_file.c.
+
+7/2/81  progs day:
+       Changed the message-name parser (../subs/m_convert.c) to
+       limit message number arguments to 999 (MAXFOLDER).  Thus if you
+       say 'scan 800-10000', this will be interpreted as 'scan 800-999'
+
+7/2/81  progs day:
+       Some very minor changes to satisfy lint.
+
+7/6/81  progs day:
+       Did a make install of all the stuff changed in the last
+       few days.
+
+7/9/81  progs phyl:
+       fixed inc so that "inc -nochangecur" doesn't display a spurious '+'
+       on the 1st incorporated msg.
+
+7/24/81 progs  phyl:
+
+        Fixed rmail to match graphics.  On the Vax, it failed to construct
+        a From: field when the next hop is Arpanet if there was a remote
+       uucp hop remaining.
+
+8/10/81 progs phyl:
+
+       Fixed rmail to block uucp-to-arpanet mail when the originating
+       host is not a Rand sysname.  It also returns mail to the sender
+       when this condition occurs.
+
+       rmail now recognizes "at" as well as "@".
+
+       rmail no longer compares headers against a list of legal headers;
+       rather it tests for proper form "<63-chars-or-less>:"
+
+       m_getfld.c now tests for ':' BEFORE it tests for header length
+       exceeded.
+
+8/10/81 progs strings day:
+
+       remove hostname.c from mh/strings.a.  It was used only by
+       deliver.c for constructing a msgid;  now it uses
+       HOSTNAME (from <whoami.h>)
+
+8/10/81 Dave Yost
+       Put rhosts[] decl in mh.h and added rhosts.c to strings.a
+       rmail is only thing that references it just now.
+
+8/11/81 Dave Yost
+       Added rand proprietary notice to all .c, .h, and Makefiles.
+       Ownership and date on all files left unchanged.
+
+8/11/81 Dave Yost
+       Combined */Log into this file
+
+8/13/81 Phyl
+       Added uucp addresses to deliver's debug printout.
+       (Didn't install).
+
+8/18/81 Phyl
+       Fixed adrparse so that it accepts multiple "at"s in an address:
+       a!b!c at d at e at f  ==> (a!b!c at d at e) at f
+
+       Changed deliver to set a new process group when it is called
+        with the -deliver switch--so that if it sends an interrupt to pid
+        0, it's parent (e.g., srvrftp) won't get blown away.
+       Note that deliver now must be loaded with the jobs library (-ljobs),
+       to access setpgrp().  I added "#define VMUNIX" to mh.h,
+       and #ifdef'd the call to setpgrp.
+
+       Fixed deliver to allow 120 secs (instead of only 30)
+       for a user's .mh_receive to complete.
+
+8/26/81 Mike
+       Fixed "folder" so you can now have up to 300 folders.
+
+9/24/81 phyl
+       fixed scansub.c to incorporate illegal messages correctly:
+               Bug: If the bad message has the bobo in its last line,
+                       then inc says [No mail incorporated]
+               FIX: if (state == BODYEOF || state == FILEEOF)
+                                         -------------------
+               Bug: spurious chars printed in the body of the bad msg.
+               FIX:    a) \n after the bad component
+                       b) if(scnout && state != FILEEOF)
+                                    -------------------
+
+10/1/81 phyl
+       fixed mhl bug;  it no longer bombs on "mhl: -option " profile
+       arguments:
+               procargs(ap);           /* Old */
+               procargs(profargs);     /* New */
+
+10/13/81 obrien
+       changed scansub to replace '\f' with blank
+
+11/4/81 day
+       Fixed pick to say '1 hit' instead of `1 hits'.
+
+11/18/81  phyl
+        Accidently did a "make" in /usr/src/cmd/mh on Nov 18.  Most
+        programs reloaded because the new "#define VMUNIX" in mh.h caused
+        strings.a to be remade.  Did not install any of it. err file moved
+        to err.Nov18
+
+1/6/82    phyl
+       o Added scansub dependencies to Makefile
+       o Added rmail.c and scansub.c to CFILES in Makefile
+       o Alphabetized  dependency list in Makefile
+       o ??Are all the Nov 18 binaries suspect?  The Aug 18 .o files?
+       o I ask because--
+          Nov 18 prompter had strange behavior (didn't respond to <DEL>,
+          didn't display error messages) which disappeared when
+           recompiled.
+
+1/7/82  phyl
+       o Added cs-rand to rhosts.c.
+       o Re-make all of MH (save old .o files in DOT.o.01072;
+                            save old executables in SAVE.01072)
+
+1/20/82  phyl
+       Fixed scansub.c to terminate a short message body with ">>"
+       on the scan line.
+
+1/25/82  phyl
+       Changed deliver.c, repl.c, send.c to require all 5 characters
+       for -debug switch.
+
+       (didn't "make")
+
+2/19/82  phyl
+       mh.h: added SELECT_EMPTY flag
+
+2/22/82 day
+       mh.h change char to extern char for strings in strings/strings.a
+       progs: install my new inc, scan, and scansub with -time and -numdate
+       progs: change show.c so it includes mhl.c and calls it if
+       showproc is mhl, rather than execing it.
+
+3/10/82  phyl
+       Changed adrparse to return 0 in case of error, instead of exiting.
+       Changed repl to test for adrparse's return value and do the
+                right thing.  It constructs a reply skeleton, omitting the
+                offending addresses from the header.  Instead, unparsable
+                addresses are listed in the skeleton body.  Note, repl
+               normally takes the sender:'s (or from:'s) host as the default
+               to append to hostless addressees.  In the new version,
+               if the sender (or from) field was unparsable, the default
+               host is "?????".
+       Changed deliver to test for adrparse's 0 return value, and exit.
+
+4/22/82  phyl
+       Changed the functions msg_convert() and msg_conv() to convert()
+       and conv(), respectively, to maintain 8-char uniqueness.
+       Linked new source into /usr/dist/1.7
+
+4/23/82 phyl
+       scansub.c: renamed the structure tag 'zone' to 'tzone'
+       for compatibility with lesser C compilers (?). (Anyway,
+       it wouldn't load on the 11/45 under 2.8bsd without that change.)
+       Delete unused reference to locv().
+       Linked new source into /usr/dist/1.7
+
+5/8/82 phyl, guyton
+       scansub.c: no longer reads the full message when called
+       by scan.
+       Linked new source into /usr/dist/1.7
+
+5/8/82 phyl
+       rmail: now tacks on Arpa-style date to dateless uucp mail.
+       Takes date from oldest uucp-From line.  Assumes uudate is
+       in ctime() format.
+
+5/10/82 phyl
+        Fixed bug in deliver that caused mail addresses uuhost1!joe,
+        uuhost2!joe to look like duplicates.  Fix: if uuaddress, compare
+        host names instead of host numbers.
+
+5/12/82
+       Fixed news.
+
+           Until now it couldn't handle "cc: news.topic", or "To: news.topicA,
+           news.topicB", or news topics that aren't explicitly in the message
+           header, or ...).
+
+           Deliver: fixed it so that aliasing keeps a handle on the
+           1st (local) alias.  Now deliver can pass this string to
+           /usr/news/.mh_receive as an argument, rather than have .mh_receive
+           grep through the message for the news topic.
+           Deliver: changed aliasing so that, once it finds a match to an
+           alias whose form is <string>*, it *continues* comparing addresses.
+
+       Deliver: changed it to fflush(stdout) after every printf() sans '\n'.
+
+6/3/82 phyl
+       All references to anoyes were changed from char *
+       to extern struct swit.
+
+       mh.h: delete hostname, layout;  add mailproc; change mypath
+       from extern char * to char *.
+
+       progs/Makefile:  move "chmod 777 MHTMP" down to installroot.
+
+       Deliver: a bug that caused the temp files in /usr/tmp/mh
+       to hang around whenever there was a local delivery error
+       was fixed.
+
+               if(!debug && rmflg > 1)  ==>  if(!debug && rmflg > 0)
+
+       m_gmsg.c:  WAS FIXED TO USE FREAD INSTEAD OF READ on the mail
+       dir
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/MHL.Design b/docs/historical/mh-jun-1982/MHL.Design
new file mode 100644 (file)
index 0000000..0546b96
--- /dev/null
@@ -0,0 +1,148 @@
+                               MHL Design
+
+Mhl is a formatted  message  listing  program.  It  can  be  used  as  a
+replacement  for  "c"  (the default message lister).  As with c, each of
+the messages specified as arguments (or stdin) will be output.  If  more
+than  one  message file is specified, the user will be prompted prior to
+each one, and a <return> or <eot> will begin the output,  with  <return>
+clearing  the  screen (if appropriate), and <eot> suppressing the screen
+clear.  An <interrupt> will abort the current message  ouput,  prompting
+for  the next message (if there is one), and a <quit> will terminate the
+program (without core dump).
+
+NOTE: This is a preliminary document and the design is VERY young.
+
+Syntax: mhl [switches] [files]
+
+As in all MH programs, mhl looks for a line "mhl: args"  in  the  user's
+profile, and thus allows tailored defaults.  The switches are:
+
+       -clear          /* Clear screen each page       */
+       -noclear        /* Don't clear screen each page */
+       -folder folder  /* Use this "folder" name       */
+       -form formfile  /* Name of the format file      */
+       -length         /* Screen length                */
+       -width          /* Screen width                 */
+       -help           /* Standard help message        */
+
+All of the functions these switches perform are affected  or  controlled
+by information elsewhere.  That is, the format file can specify "clear",
+in which case, the  command  line  switches  will  override.  Also,  the
+length  and  width  can  be  specified in the format file, or default to
+40x80.  The folder is used in constructing a message name  (see  special
+component  "MessageName" below).  If it is not specified in a switch, it
+is taken from the environment variable  "mhfolder",  which  show,  next,
+prev, and pick initialize appropriately.
+
+If  the  form  file  is  not  specified,  it  is  taken  from  the  file
+"mhl.format" in the user's MH directory, and if that file doesn't exist,
+it is taken from "/etc/mh/mhl.format". (Same evaluation hierarchy as the
+compose form file.)
+
+Mhl operates in two phases: 1) read and parse the format  file,  and  2)
+process each message (file).  During phase 1, an internal description of
+the format is produced as a structured list.  In phase 2, this  list  is
+walked  for each message, outputing message information under the format
+constraints from the format file.
+
+The "mhl.format" file contains information controlling screen  clearing,
+screen  size,  wraparound control, transparent text, component ordering,
+and component formatting.  Also, a list of components to ignore  may  be
+specified, and a couple of "special" components are defined  to  provide
+added  functionality.  Message  output will be in the order specified by
+the order in the format file.
+
+
+Each line of mhl.format has one of the formats:
+
+       ;comment
+       :cleartext
+       variable[,variable...]
+       component:[variable,...]
+
+A line beginning with a ";"  is  a  comment,  and  is  ignored.  A  line
+beginning with a ":" is clear text, and is output exactly as is. (A line
+containing only a ":" produces a blank  line  in  the  output.)  A  line
+beginning  with  "component:"  defines  the  format  for  the  specified
+component, and finally, remaining lines define the global environment.
+
+For example, the line:
+
+width=80,length=40,clearscreen,overflowtext=***,overflowoffset=5
+
+defines the screen size to be 80 columns by 40 rows, specifies that  the
+screen  should  be  cleared  prior  to  each  page,  that  the  overflow
+indentation is 5, and that overflow text should be flagged with "***".
+
+Following are all of the current  variables  and  their  argmuments.  If
+they  follow  a component, they apply only to that component, otherwise,
+their affect is global.  Since the whole format  is  parsed  before  any
+output processing, the last global switch setting for a variable applies
+to the whole message.
+
+width=#         Screen width, component width
+length=#        Screen length, component line limit
+offset=#        Positions to indent text
+overflowtext=t  Text to use at the beginning of an overflow line
+overflowoffset=# Positions to indent overflow lines
+compwidth=#     Positions to indent component text after first line
+nocomponent     Don't output "component: " for this component
+uppercase       Output text of this component in all upper case
+center          Center component on line (works for one-line components
+               only)
+clearscreen     Clear the screen (form feed) prior to each page
+leftadjust      Strip off leading spaces & tabs on each line of text
+compress        Change newlines in text to spaces
+
+Where "=#" indicates a number must be specified, and "=t" indicates that
+arbitrary  text  up  to  end  of line or "," is required.  The variables
+without arguments are ON indicators, with the default in all cases  OFF.
+The  variables  "nocomponent",  center,  leftadjust and compress have no
+affect globally, and clearscreen only affects the global environment.
+
+A line of the form:
+
+ignores=component,...
+
+specifies a list of components which are never output.
+
+The component "MessageName" (case is unimportant) will output the actual
+message  name  (file  name) preceded by "folder:" if one is specified or
+found in the environment.
+
+The component "Extras" will output all of the components of the  message
+which were not matched by explicit components, or included in the ignore
+list.  If this component is not specified, an ignore list is not  needed
+since all non-specified components will be ignored.
+
+If "nocomponent" is NOT specified, then the component name will be output
+as it appears in the format file.
+
+The current default format is:
+
+width=80,length=40,overflowtext=***,overflowoffset=5
+ignores=msgid,message-id
+Date:leftadjust,offset=40
+To:leftadjust
+Cc:leftadjust
+:
+From:leftadjust
+Subject:leftadjust
+:
+extras:leftadjust,nocomponent
+:
+body:nocomponent
+
+
+Future work:(?)
+
+ o Fancier address formatting (to, cc, from)
+ o Tests for "am i in this address list?" and what to do if yes/no
+ o Currently only one component per line--should be generalized
+ o Clear text and components intermixed on a line
+ o Intelligent fill/justify per component?
+
+
+
+May 1980
+Bruce
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/MHgenerate b/docs/historical/mh-jun-1982/MHgenerate
new file mode 100644 (file)
index 0000000..3570300
--- /dev/null
@@ -0,0 +1,178 @@
+                      HOW TO GENERATE AN MH
+
+ASSUMPTIONS/RESTRICTIONS:
+
+        All of the code is written for Version  7  C,  and  assumes  the
+existence of appropriate Version 7 /usr/include files.  It also uses the
+Version  7  stdio  package,  which  is  somewhat  different   from   the
+Phototypesetter stdio!
+
+        There is moderate usage of Version 7 UNIX features, including:
+
+               ftime() system call
+               execlp() & execvp() environment exec calls
+               getenv() environment access
+
+also, login has to be changed to add the environment entry  "USER=name".
+This is used during scan listings to see if the message "From" should be
+replaced by "To:name".  This string is NOT used to determine the  "From:
+name" stamp on outgoing mail.
+
+        All of these usages ARE replaceable by subroutines which do  the
+same thing, only slower.  That is, a line of the form:
+
+               homedir = getenv("HOME");
+
+should be replaced by something like:
+
+               homedir = gethome();
+
+and the routine gethome()  written  to  return  the  home  directory  by
+looking through /etc/passwd for the line matching the process' getuid().
+This goes for the environment variable "USER" as well.
+
+The routines execlp() & execvp() are simply fancy exec's, which use  the
+"PATH"  environment  variable  to  determine the search path by which to
+find the executable image.  They can be replaced by routines which use a
+default  search list.  They also call a shell to execute the file in the
+same way the shell handles shell scripts.
+
+
+
+PROCEDURE:
+
+
+1) Read the MH directory tree onto a file system.
+   On our system it lives in the directory "/usr/src/cmd/mh".
+
+2) Edit mh.h, and define ARPANET if you are on the ARPANET.
+   If not, don't define it.  If ARPANET is not defined and if you want to
+   assign your host a name for address formatting, change HOSTNAME in
+   adrparse.h.  If you are on VMUNIX, define that in mh.h and set up the
+   JOBSLIB define in progs/Makefile.
+
+3) Examine the C header files in the "Extras" directory.  Copy  them  to
+   /usr/include or support/ and modify them for your installation.
+   If you are going to use mh over uucp and/or ARPANET links, you must edit
+   your /usr/include/whoami.h to be sure the defines for sysname (uucp) and
+   HOSTNAME & HOSTNUM (ARPANET) are correct.  If you are not on the
+   ARPANET, delete HOSTNAME and HOSTNUM from whoami.h.
+
+4) Examine all of the files in the "strings" directory.  These contain
+   site-dependent strings, such as pathnames for programs used by MH.  Most
+   of the files contain short descriptions of what the strings are.
+   'showproc.c' refers to a program which is found as support/l.c and which
+   is installed as 'c' linked to 'l'.  You may want to use Berkeley's
+   'more' or some other program here.  The BINDIR and MHDIR entries in
+   Makefile and */Makefile must agree with the contents of strings/*.c.
+   Also, the 'file' command in support/news/mh_receive should have the same
+   path as is in strings/fileproc.c.  Make sure BINDIR (/usr/local as
+   distributed) is put into everyone's PATH by login or by shell startup
+   files.
+   Note:  if you are installing mh `unofficially', and you don't have
+   permissions to make directories in /usr/spool/ and /etc/, then make
+   sure the paths in the strings/*.c files and in support/mailsys.h
+   are directories you have permission to make if they don't exist already.
+   In particular, /usr/spool/locks/ must be on the same file system as
+   /usr/spool/mail so that links can be made.  Try /usr/tmp/locks if
+   you can't mkdir /usr/spool/locks/.
+
+5) Install support/putenv.c into your system libc.a,  or  if  you  don't
+   want  it as part of your standard C library, move it into subs. (Both
+   options work equally well for MH!)
+
+6) Copy the file "support/MailAliases" to /etc.  Then you should look at
+   it and see if you want to add any mail aliases.
+
+7) In the top level directory, utter:
+
+       make all
+
+   This will make both of the libraries: strings.a and subs.a,  and  all
+   of the executable modules.
+   (Ignore the possible error message "nm: sysname.o--no name list")
+
+
+8) For the 'news' facility of mh to work, you must:
+       Create a user called 'news' who belongs to the group 'mail',
+         with password '--none--' in /etc/passwd and /etc/group.
+       Creat a home directory for news: "/usr/news".
+       cd /usr/news
+       /etc/chown news * .??*
+
+9)
+       make onceonly           This renames conflicting bell
+                               programs, and makes requisite
+                               directories.
+
+       make install            This puts all of the programs,
+                               misc files, and man pages
+                               into appropriate directories.
+
+10) As SU:
+       cd progs; make installroot
+
+    - If /etc/chown isn't found, try linking /bin/chown to /etc/chown
+
+    - If [ isn't found, try linking /bin/test to /bin/[
+
+    - If "true" isn't found, create the executable NULL file /bin/true.
+
+That's it.  Take a close look at the Makefile--it does LOTS of work.
+Especially note that it renames the V7 `file' program to `filetype'
+because for historical and other reasons, mh has its own `file' command.
+Also, MH has its own versions of `mail' and `rmail'.  If you don't want
+to install everything in standard places, run "make install" with the
+variables MHDIR=newdir and BINDIR=newdir pointing wherever you wish.  If
+you do this, you probably have to change some of the path names in the
+strings files.  For most of them, you can get away with adding profile
+entries to change where the default paths are sought.
+
+If you don't have `make':
+
+     You'll have to use the make file as a template for commands to give
+     by  hand.  Basically  each  section  of  the  make file defines the
+     sequence of shell commands needed to create the object  before  the
+     `:'.  The list immediately after the `:' specifies the dependencies
+     for the object--that is, those objects which either  must  be  made
+     first, or those modules that if they've changed, the object must be
+     rebuilt.  The following lines (up to the next  object)  are  simply
+     shell  commands to be executed.  Make knows how to create .o's from
+     .c's, and the "CFLAGS= -O" at the beginning  tells  it  to  include
+     optimization when it does a c compile.
+
+If you don't have stdio (i.e. some version 7 C compiler):
+
+     Punt.   I  recently  converted  the  whole  package  from  the  old
+     getc/putc/iobuf    subroutines--including    lots    of   upgrades/
+     improvements, it took me about a week.  Expect it to take a  couple
+     of  weeks for someone good to convert back.  Basically, convert the
+     subroutines, then once you've converted one module (start with show
+     or  comp),  you'll  find all the rest VERY similar.  Some day I may
+     split out all of the  system  dependencies,  but  don't  hold  your
+     breath.
+
+
+
+As a last resort:
+
+     Feel free to send mail to me, but please don't expect me  to  spend
+hours  helping.  Collect  your  questions/problems, and get in touch and
+I'll see what I can do.  I can be reached:
+
+       via ARPANET:    Borden at Rand-UNIX
+
+       Mail:           The Rand Corporation
+                       1700 Main Street
+                       Santa Monica, CA 90406
+
+Bruce Borden
+April, 1980
+
+
+    If you are accessible via the  arpanet  or  via  uucp  mail,  please
+contact the secretary to the Director of the Information Systems Lab at
+Rand, and get on our mh-bugs electronic mailing list.  213/393-0411
+
+Dave Yost
+Februar
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/MHnotes b/docs/historical/mh-jun-1982/MHnotes
new file mode 100644 (file)
index 0000000..a62da1f
--- /dev/null
@@ -0,0 +1,186 @@
+This file contains some notes on features/bugs/etc which are
+not documented in the "MH User's Manual", as well as some notes
+on future directions.  See MHgenerate for more info.  Some of
+these notes assume VAX/V7 UNIX--as noted by {V/V7}.
+
+0) Directories:
+       support contains files which get copied to /etc/mh, as
+               well as some miscellaneous Rand support programs
+       subs    contains support subroutines--built into subs.a
+       strings contains c files which define all of the default
+               names and paths used by the package->strings.a
+       Extras  old and un-supported code--much of it not
+                converted to V7.  Look at libg/libh for help in
+                getting around V7 features.
+       DOC     contains the MH User's Manual document in nroff/
+                troff form.  This requires the Phototypesetter or
+                V7 version of nroff/troff, AND the Berkeley -me
+                macros.
+
+1) Undocumented Feature:  The paths to the various programs which
+   MH exec's are kept in variables named something like "lsproc".
+   (See the strings directory.) While reading in the user's
+   profile, (m_getdefs()) a component matching one of these exec
+   path names, will cause the default string to be replaced by
+   the profile entry argument.  Thus, the profile entry "lsproc:
+   /usr/foo/bin/newls" will cause all MH programs using "lsproc"
+   to get a new ls.  At least for now, there is no way to specify
+   switches.  This mapping is arranged by the "procs" structure
+   in m_getdefs.c--keep it up to date if new exec procs are
+   added.
+
+2) Collision:  Take a close look at the "onceonly" entry of the
+   Makefile.  Bell already has a program named `file', which the
+   makefile will rename to `filetype', which is what it tries to
+   indicate.  If you really want to, you might rename the MH
+   command `file', but I have yet to hear of an even vaguely
+   reasonable alternative.
+
+3) Different Approach:  Using the Berkeley C shell (csh),
+   "multiple links to the same file with different profile
+   entries" is better served with aliases.
+
+4) Collision: {V/V7} BELL mail cannot co-exist with MH--IF THEY
+   SHARE THE SAME MAILBOXES, otherwise they co-exist fine!  If
+   you use the standard (VAX) mail directory /usr/spool/mail for
+   MH, you should also install the MH version of the mail
+   program.  It is much nicer, and integrates with MH cleanly.
+   The advantage of using /usr/spool/mail is that login will
+   notify of new mail.
+
+5) Feature: If you add a line like:
+
+       30 1 * * * /etc/mh/conflict -mail admin
+
+   to crontab, then every morning at 1:30 AM, the alias file will
+   be checked against the /etc/passwd file to see that
+   inconsistencies haven't been introduced.  In particular, a
+   line in the alias file may be "tom: jones" (because Tom Jones
+   likes to be called Tom), but if tom is also a valid user name,
+   tom will no longer receive any mail!  This program also prints
+   any mail drops in /usr/spool/mail which don't belong to a
+   valid user (i.e. a deleted or renamed user id).
+
+   "convlict -mail name" will check the consistency and mail
+   the specified user a short status message.
+
+   This program also checks to see if there are any users who do
+   not belong to any group, or any user in a group which is missing
+   from the passwd file.  This latter is an inconsistency on all
+   systems, whereas the former is not required except at Rand, and
+   won't be compiled without the "-DRAND" cc flag in the makefile.
+
+6) Hidden Feature:  At the request of some of the Rand staff,
+   there is the ability to invoke a user-specified deletion-
+   program to implement message deletion, rather than getting the
+   default comma renaming convention (see next item).  If a
+   user's profile contains the line: "Delete-prog: path", the
+   specified path will be called with a list of files needing
+   deletion.  All this code works...
+
+7) Feature:  When a message (draft or in a folder) is "removed",
+   it is really renamed with a leading comma.  E.g. foo -> ,foo.
+   At Rand we have a program called the midnight skulker which
+   goes through the whole system and removes all backup (starting
+   with comma), a.out, and core files.  This backup convention
+   gives users a chance to undo spurious removes, at least all
+   day.  You may want to replace these renames with a simple
+   unlink(), or each user may get this effect by specifying
+   "Delete-prog: /bin/rm" in his/her profile.
+
+8) Feature:  NEWS.  The news facility is undocumented in the MH
+   manual, because it is a very new addition to the package.  SO,
+   here it is...
+
+        The directory /usr/news should be created--it will
+        contain the folders for news topics, and various support
+        files.  The news items are strictly MH folders, and users
+        can utilize all of the MH commands on them.  The news
+        program is similar to "show", but it shows `unseen' news
+        as the default, keeping a separate entry in the users
+        profile for each news topic indicating the highest item
+       the user has seen.  These entries look like
+               "news-<topic>: highest-seen".
+
+        Rather than read through the news folders to determine
+        the number of entries, a file with name .<topic> (i.e.
+        period followed by the topic name) is kept with length
+        equal to highest message number.  Thus, to determine if a
+        user hasn't seen some news, the news directory
+        (/usr/news) is read, and for each non-period beginning
+        file (i.e. each folder), stat the associated period
+        beginning file, and compare its length with the users
+        profile news entry for the same name.  If the user has no
+        entry, or it is less than the length of the period-file,
+        then show him the remainder of the news in each such
+        topic.
+
+        The program `l' is used to display each message, and the
+        highest item profile entry is updated prior to each
+        individual message displayed, so <del> will leave the
+        user's profile in the proper state for the next news
+        request.
+
+        Add a user to the system called news, with home directory
+        /usr/news and add the line:
+
+               news.*: news
+
+        to /etc/MailAlias.  Thus, to add news to a topic, it is
+        only necessary to mail to news.topic, and it will happen.
+        To make the automatic filing into folders happen, copy
+        the file support/news-mh_receiv to /usr/news/.mh_receive.
+        This is a shell script which will get invoked whenever
+        mail is sent to the user news (see next "undocumented
+        feature").
+
+        Problems:  I have yet to write the program which packs
+        news folders.  Items can be readily removed (as long as
+        they are not the last item in the folder), but if the
+        folder is packed (after some months/years the item
+        numbers will reach the 999 limit), it is necessary to go
+        through everyones .mh_profile files and reset the
+        highest-seen numbers.  Not hard to write, I just haven't
+        done it yet.  Also, the receive shell script should be
+        recoded in C to speed it up considerably.
+
+9) Undocumented Feature:  If a user has an executable program or
+   shell script named ".mh_receive" in his home directory, then
+   it will be executed by the mail deliverer RATHER than
+   appending mail items to the user's mail file
+   (/usr/spool/mail/name).  This program will be called with:
+
+       execlp(prog, prog, tmpfil, mail, home, 0);
+
+   where prog is the receive program, tmpfil is a file in
+   /usr/tmp which is the mail to be received, mail is the path of
+   the user's mail drop (/usr/spool/mail/name), and home is the
+   $HOME directory of the user.  File descriptor 3 will have
+   tmpfil opened on it read only.  These are all the RECEIVER'S
+   parameters, not the sender's.  Also, the environment is set up
+   with appropriate values for HOME and USER.
+
+   Eventually, the goal is to have received mail LINKED into
+   user's inbox folders, rather than appended to their mailboxes.
+   This will facilitate the sending of mail to large distribution
+   lists (Rand is always tight on space!) Have a look at the news
+   .mh_receive file for an example of this facility.
+
+   Warning: appropriate interlocks are implemented in "deliver"
+   to prevent collisions when it appends to mailboxes, but it is
+   up to the users's .mh_receive program to provide its own
+   interlocks!
+
+10) New Program: "mhl" is a custom MH list program which displays
+   messages according to a format specification.  See MHL.Design
+   for further details.  See Extras/mhl.bsb for an added example.
+
+11) New Program: "ali" is a mail alias checker.  It takes a list
+   of names, and produces the alias list for the names.  It also
+   indicates any names which are not valid local names or aliases.
+
+
+
+
+Bruce Borden
+Mar
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/Makefile b/docs/historical/mh-jun-1982/Makefile
new file mode 100644 (file)
index 0000000..dc27821
--- /dev/null
@@ -0,0 +1,100 @@
+#
+#       Proprietary Rand Corporation, 1981.
+#       Further distribution of this software
+#       subject to the terms of the Rand
+#       license agreement.
+#
+
+#
+
+# The following two must match entries in */Makefile
+BINDIR  = /usr/local
+MHDIR   = /etc/mh
+
+all:
+       cd subs; make
+       cd strings; make
+       cd progs; make progs
+
+uninstall:
+       cd progs; make uninstall
+       cd support; make uninstall
+       cd man; make uninstall
+       -rm -rf $(MHDIR)
+       -mv /usr/man/man1/bellmail.1 /usr/man/man1/mail.1
+       -mv /bin/bellmail /bin/mail
+       rm -f /bin/rmail
+       ln /bin/mail /bin/rmail
+       -mv /usr/man/man1/filetype.1 /usr/man/man1/file.1
+       -mv /usr/bin/filetype /usr/bin/file
+       -mv /bin/filetype /bin/file
+
+onceonly:
+       -@if [ ! -f /usr/bin/filetype -a ! -f /bin/filetype -a -f /bin/file ] ; then \
+         mv /bin/file /bin/filetype;echo "/bin/file => /bin/filetype" ; else true ; fi
+       -@if [ ! -f /bin/filetype -a ! -f /usr/bin/filetype -a -f /usr/bin/file ] ; then \
+         mv /usr/bin/file /usr/bin/filetype;echo "/usr/bin/file => /usr/bin/filetype" ; else true ; fi
+       -@if [ ! -f /usr/man/man1/filetype.1 -a -f /usr/man/man1/file.1 ] ; then \
+         mv /usr/man/man1/file.1 /usr/man/man1/filetype.1;echo "/usr/man/man1/file.1 => /usr/man/man1/filetype.1" ; else true ; fi
+       -@if [ ! -f /bin/bellmail -a -f /bin/mail ] ; then \
+         mv /bin/mail /bin/bellmail;echo "/bin/mail => /bin/bellmail" ; else true ; fi
+       -@if [ ! -f /usr/man/man1/bellmail.1 -a -f /usr/man/man1/mail.1 ] ; then \
+         mv /usr/man/man1/mail.1 /usr/man/man1/bellmail.1;echo "/usr/man/man1/mail.1 => /usr/man/man1/bellmail.1" ; else true ; fi
+       -@if [ -f $(BINDIR)/comp ] ; then \
+               echo "Collision on $(BINDIR)/comp" ; else true ; fi
+#       -@if [ -f $(BINDIR)/dist ] ; then \
+               echo "Collision on $(BINDIR)/dist" ; else true ; fi
+#       -@if [ -f $(BINDIR)/file ] ; then \
+               echo "Collision on $(BINDIR)/file" ; else true ; fi
+       -@if [ -f $(BINDIR)/folder ] ; then \
+               echo "Collision on $(BINDIR)/folder" ; else true ; fi
+       -@if [ -f $(BINDIR)/forw ] ; then \
+               echo "Collision on $(BINDIR)/forw" ; else true ; fi
+       -@if [ -f $(BINDIR)/inc  ] ; then \
+               echo "Collision on $(BINDIR)/inc"  ; else true ; fi
+#       -@if [ -f $(BINDIR)/mail ] ; then \
+               echo "Collision on $(BINDIR)/mail" ; else true ; fi
+       -@if [ -f $(BINDIR)/news ] ; then \
+               echo "Collision on $(BINDIR)/news" ; else true ; fi
+       -@if [ -f $(BINDIR)/next ] ; then \
+               echo "Collision on $(BINDIR)/next" ; else true ; fi
+       -@if [ -f $(BINDIR)/pick ] ; then \
+               echo "Collision on $(BINDIR)/pick" ; else true ; fi
+       -@if [ -f $(BINDIR)/prev ] ; then \
+               echo "Collision on $(BINDIR)/prev" ; else true ; fi
+       -@if [ -f $(BINDIR)/prompter ] ; then \
+               echo "Collision on $(BINDIR)/prompter" ; else true ; fi
+       -@if [ -f $(BINDIR)/repl ] ; then \
+               echo "Collision on $(BINDIR)/repl" ; else true ; fi
+       -@if [ -f $(BINDIR)/rmf  ] ; then \
+               echo "Collision on $(BINDIR)/rmf"  ; else true ; fi
+       -@if [ -f $(BINDIR)/rmm  ] ; then \
+               echo "Collision on $(BINDIR)/rmm"  ; else true ; fi
+       -@if [ -f $(BINDIR)/scan ] ; then \
+               echo "Collision on $(BINDIR)/scan" ; else true ; fi
+       -@if [ -f $(BINDIR)/send ] ; then \
+               echo "Collision on $(BINDIR)/send" ; else true ; fi
+       -@if [ -f $(BINDIR)/show ] ; then \
+               echo "Collision on $(BINDIR)/show" ; else true ; fi
+       -@if [ -f $(MHDIR) -o -d $(MHDIR) ] ; then \
+            echo "$(MHDIR) already exists!"; else true ; fi
+
+install:
+       cd progs; make install
+       cd support; make install
+       cd man; make install
+
+pinstall:
+       cd progs; make pinstall
+
+distribution:
+       cd support; make distribution
+       cd subs; make distribution
+       cd strings; make distribution
+       cd progs; make distribution
+
+clean:
+       cd support; make clean
+       cd subs; make clean
+       cd strings; make clean
+       cd progs; make clean
diff --git a/docs/historical/mh-jun-1982/README b/docs/historical/mh-jun-1982/README
new file mode 100644 (file)
index 0000000..3ba4b78
--- /dev/null
@@ -0,0 +1,7 @@
+To install mh, read the file 'MHgenerate'
+
+The documentation is somewhat in transition.
+In the DOC directory you will find the original Rand
+report on mh, but since then we have generated man pages
+which will be found in the 'man' directory and are
+more current.
diff --git a/docs/historical/mh-jun-1982/Wishlist b/docs/historical/mh-jun-1982/Wishlist
new file mode 100644 (file)
index 0000000..4f4cd1f
--- /dev/null
@@ -0,0 +1,509 @@
+11/14/79
+       Allow complex boolean expressions in "pick"
+
+11/14/79
+       Add profile switches that will "answer" prompts,
+       sa "Draft exists, delete?"
+
+11/14/79
+       Have the stand-alone "anno" prompt for component and text.
+
+3/19/80
+       More elaborate "<command> -help".  (But see objections in
+       /r/phyl/Mail/MH/2)
+
+10/6/80
+       MH should be able to pass the terminal type to the editor.
+
+10/23/80
+       Mail sent to mailing list aliases should also be sent to "news"
+       (Complex problem--but see BSB's msg /r/phyl/Mail/MH/134)
+
+11/21/80
+       Allow a "delete-after: <date>" component to MH;  have a
+       daemon go thru everyone's MH folders and delete stale
+       messages.  (see /r/phyl/Mail/MH/45...)
+
+11/21/81
+       Add a -noformat option to mhl--to get rid of " at RAND-UNIX"
+       when the message is listed.
+
+1/13/81
+       Have a file "/etc/Newsgroups" with lists of people
+       who should see certain news, so that systems personnel
+       can decide who should see certain topics and not have to
+       alter .mh_profiles.
+
+1/15/81
+       "ali -user" to give the reverse info from "ali aliasname";
+       viz, given a user, what aliases will send mail to him.
+
+1/20/81
+       "repl -form formfile"
+
+            or
+
+       There could .mh_profile entries that specify the
+       defaults for the various components for messages,
+       and all programs like comp & forw could look to
+       those instead of looking to a 'compform' or the like.
+
+       Examples:
+       From-Component: dave-yost
+       Fcc-Component: inbox
+
+1/26/81
+       Link messages instead of copying them
+
+1/29/81
+       Have "news -folder" change your current folder to the 1st unread
+       news folder, thus allowing you to use all the usual MH commands on it.
+
+2/3/81
+       "news -inc"
+
+2/9/81
+       "All plain files that now reside in 'Mail' should live in a
+        subdirectory like 'Mail/M'.  Now I can unprotect the 'Mail'
+        directory, so that I can selectively grant snoop permission on any
+        folder without fear of making my other miscellaneous files like
+       'draft' vulnerable.  All I have to do is protect 'Mail/M'."  --Dave
+
+2/16/81  FROM BERKELEY
+
+
+    Date: 3 Feb 1981 15:57:05-PST
+    From: CSVAX.kas at Berkeley
+    Message-ID: <601.350091987@CSVAX.Berkeley>
+    To: Day@Rand-Unix, Urban@Rand-Unix
+    Subject: Re: Updated MH to run in 4bsd environment
+    In-reply-to: Your message of 27 Jan 1981 2011-PST (Tuesday).
+    Fcc: mh
+
+    I have finished making the new version of MH run in our 4bsd
+    environment.  That is, our version of MH runs compatibly with
+    the standard v7 mail program, the Berkeley Mail, UNIX sndmsg, msg,
+    and others.  Some of the things I encountered may be of use to
+    you in making your distribution of MH easier to install in 4bsd systems.
+
+    So here they are:
+
+    ali.c           Changed to use a #define for the MailAlias file.
+                   Should really have created a new strings file for it.
+
+    annotate.c      Now uses the character defined by CBACKUP instead of ,
+                   for the backup convention.  We have a line of the form:
+
+                   40 4 * * * find / -name '#*' -atime +3 -exec rm -f {} \;
+
+                   in /usr/lib/crontab and it seemed easier to make MH
+                   obey that than to convince users to use ,
+
+    conflict.c      Used to reference ``struct dir'' which in our system at
+                   least is defined in /usr/include/sys/dir.h as
+                   ``struct direct''
+
+    dist.c          Changed to use CBACKUP, instead of comma
+
+    folder.c        Removed fflush(stdout) after each line of output.  This makes
+                    the program appear to run faster.
+
+    forw.c          Changed to use CBACKUP, not comma
+
+    inc.c           Changed to call a program unixtomh (described later) which
+                   reads mail in standard unix format and converts it to MH
+                   format.  Now has -file filename flag to read messages
+                   from a file (many users already have mbox files full of
+                    unix format mail. they can do inc -file mbox +mbox to
+                    convert this to an MH folder).  Also has -keep to
+                    prefer close(creat(mailboxname, 0600)) to unlink to
+                    help users preserve a non-publically readable mode on
+                    their mail drop.
+
+    mail.c          Renamed mhmail.c to avoid confusion
+
+    mhl.c           Changed to use termlib to clear terminal screen correctly.
+                   Fixed its argument processing so it won't try to open flag
+                   arguments as files.
+
+    news.c          s/struct dir/struct direct/
+
+    rmf.c           Uses CBACKUP instead of comma
+
+    rmm.c           Uses CBACKUP instead of comma
+
+    scan.c          Has -reverse flag to look at headers newest first.  A user
+                   with a HUGE inbox demanded this.
+
+    send.c          Uses CBACKUP instead of comma
+
+    unixtomh.c      Created program to read unix format mail and put it in MH
+                   format.  This is invoked by inc.
+
+    mh.h            Although this is the wrong place to do it, added CBACKUP
+                   #define to give backup character.  Should really be in
+                   strings.
+
+    mailsys.h       Changed path names to end with / to satisfy the assumption
+                   in inc.c that they look that way.
+
+    deliver.c       Now makes temporary file in /tmp, not /usr/tmp/mh,
+                   doesn't check validity of network addressees,
+                   Only outputs From: and Date: in fcc copy of message,
+                   invokes /etc/delivermail on all recipients to actually
+                   deliver the mail, removed putdate() routine in favor
+                   of shared (with unixtomh) version in subs, and now
+                   uses #define MAILALIASES.
+
+    Also, a couple of minor notes:  we do not have a strings.h file in
+    /usr/include, which I assume gave the return types of routines like
+    rindex() and friends.  A number of files include system files as, eg:
+
+    #include <types.h>
+    #include <stat.h>
+
+    this requires that you give the preprocessor flag -I/usr/include/sys
+    for it to be found.  This creates problems for the make depend stuff
+    since include files are not necessarily in /usr/include.  I got around
+    this by simply editing out the header file dependencies from the
+    Makefiles.
+
+    Finally, to get around the conflict between /usr/bin/file and the MH file
+    command, I made a program fakefile which examines its arguments.  If any
+    begin with +, it invokes MH file, else /usr/bin/file.  This seems to
+    work fine.
+
+    I have everything sccs'd so I can send you sccs source, diffs, new source
+    or whatever if you like.
+
+           Kurt Shoens
+
+
+2/17/81
+       Sort folders by time-received.
+
+2/17/81
+       Whenever a news topic is created, a suitable message to news.everyone
+       should announce that fact and try to sell users on the new topic.
+
+2/18/81
+       "... I've been hacking up an MH to
+       put the attributes in the file names, format n-aaa, where n is
+       the message number, and the a's are the attribute characters,
+       initially, only 's' for 'seen' being implemented.  This is VERY
+       efficient, and only runs into the original problems Norm pointed
+       out...the name is difficult to guess from an environment which
+       does not allow wild-cards, such as inside the editor.
+
+       "Personally, I think the advantage gained is well worth the
+       messiness.  I would like to be able to say "scan unseen",
+       or "file seen +handled", etc.  This can't be done in ANY
+       other fashion under UNIX without losing lots of other important
+       features, such as preservation on copy."
+
+       /Bruce
+
+2/18/81
+       Allow personal alias files.
+
+       Except---
+       "No personal aliases because there ain't no way to reply!
+       The 733 syntax is totally botched on "file inclusion".
+       There should be a meta-syntax for using a file as an
+       address, which deliver programs ALL AROUND THE NET could
+       use for replies."
+       /B
+
+       But---
+       "You could have personal aliases if they were expanded into the
+       message."
+       --dave
+
+2/19/81
+       "Screw -time and -numdate.  How about a -display <string> option,
+       where <string> is a printf-like format that dictates exactly the
+       way you want the scan to look. Something like:
+
+       scan -display '%3(num) %2(mo)/%2(day)/%2(yr) \
+       %2(hour):%2(min)-(timezone) \
+       %10(from) %40(subject)%(incl)(body)'
+
+       "It has been suggested that the 'ls' command should have an option
+       like this, too."
+
+       --dave
+
+2/19/81
+       Scan and inc should display control characters in readable form.
+       (Except, for example, ^G, ^I)
+
+2/23/81
+       encrypted mail
+
+2/23/81
+       Integrate MH file naming conventions with Unix naming conventions.
+       So, for example, when in the editor, you could reference
+       "last" or "+junk/14"
+
+2/24/81
+       "Replied-to" Subject fields should somehow keep track of
+       the "generation" of the replied-to message.
+
+2/26/81 Dave Clemans, SDC
+
+        Because the ISC system is a UNIX V6 variant, and MH is set up for
+        V7, there are a few differences:
+
+       Because of name conflicts between MH programs and ISC programs,
+               mail
+               news
+               file
+        are in the directory /misc/bin.  The version of file in /misc/bin
+        is a preprocessor; if its argument list has an argument with a '+'
+        as its first character, it calls /usr/bin/file.msg, otherwise it
+        calls /bin/file.
+
+        MH wants to look at a few environment variables, which don't exist
+        on UNIX V6.  They are simulated using the global shell variables of
+        the SDC-extended "Harvard" shell.  For people who use the "Harvard"
+        shell (hsh), this procedure is handled automatically.  For people
+        who use the Berkeley C shell (csh) or people who use the ISC shell,
+        a special command has to be run at least once, and possible every
+        time that you log in, depending on how often you change things.
+        What follows is a short description of that command:
+
+            /misc/bin/mhsetup <login  name>  <home  directory>  <search path>
+
+                                                         Environment Variable
+               <login name> is your actual login name          USER
+               <home directory> is your login directory        HOME
+               <search path> is the PWB/UNIX style path        PATH
+
+        There also has been a few extensions made to MH at SDC.  A short
+        list of these are:
+
+        a.  Registered mail: send has a -register and a -noregister switch.
+           A receipt is sent back to the sending user when the receiving
+           user types "inc" and a registered message is received. (Done by
+           adding a "Registered" component to the message)
+
+        b.  Fcc:  Multiple folder names are accepted in this component and
+           handled correctly.
+
+        c.  Personal mailing lists:  In addition to the mailing lists
+           accepted by the /etc/MailAliases file, users can maintain
+           private mailing lists.  These are referenced by addresses of the
+           form "<path", where path is the name of the mailing list.  It is
+           looked for first in the current directory, and then in the users
+           Mail directory.  It should have the same format as a list of
+           addresses typed in by hand.
+
+        d.  Automatic forwarding:  If a user has accounts on multiple
+           machines, but only uses one of them on a regular basis, it is
+           possible to have all messages from those other machines
+           automatically forwarded to the machine that is used regularly.
+           The same database hook used by this is also used to provide full
+           names in addresses:
+               (i.e., Full Name <user at host>)
+          (Done by having a file with one line for each user, of the format:
+               <user>  <flag>  <address>       :<Full Name>
+          <user> is the local user name
+          <flag> says whether or not to forward
+          <address> is the forwarding address
+          <Full Name> is the users full name)
+
+        e.  Msg/Sndmsg:  There are msg/sndmsg programs in /misc/bin that
+           look very similar to normal ARPAnet msg/sndmsg programs, but
+           which interface to MH.
+
+        f.  Repl: repl has "-fccme" and "-nofccme" switches for making file
+           copies of replies to messages.
+
+        g.  Next/Prev: next and prev have "-pr" and "-nopr" switches.  They
+           have the same effect as the "-pr" and "-nopr" switches in show.
+
+       The "onstruct is recognized and handled correctly.  The only
+       transport mechanism available currently is the Berkeley network (from
+       2BSD).
+       (Hooks do exist to add others, specifically UUCP).  Currently defined
+       host names are:
+               sdc-70          the R&D 11/70 system
+               sdc-net         the 11/45 network support machine
+
+       Two other host names exist for sending mail into the ISC mail system.
+       These are "sdc-70x" and "local".
+
+       For any problems, or for more information, send a message to dgc
+       dgc
+
+       Dave Clemans
+       -----
+
+3/2/81
+       repl -use
+
+3/17/81
+       Delayed mail delivery:  add a "Deliver-date:" header containing
+       the delivery date...
+
+3/18/81
+       "send" in the background
+
+4/5/81
+       Mail to terminals
+
+       "... the sender would decide which of the four possible
+       options to select:
+       1. mail only
+       2. send to terminal only
+       3. send to terminal and also mail
+       4. send to terminal if possible, otherwise mail
+
+       "Furthermore, messages added to your mailbox would indicate whether
+        they were sent as mail or tty messages, so you could discard
+       messages which were intended to be displayed on the the terminal."
+
+       --greep
+
+4/17/81
+       Automatic mail agents, per Dave Farber
+
+4/23/81
+       <command> -nochangedir
+
+5/7/81
+       bcc recipients should SEE the bcc header in their copy of
+       the message
+
+
+5/14/81
+       Repl should have an option that includes
+       the replied-to message in the body of the
+       new message, indented one tabstop, so you
+       can intersperse answers with original text.
+       (But see objections in mail subsequent to the
+       suggestion)
+
+5/26/81
+       scan -name;  folder -name
+       to return full path names of message files
+
+6/1/81
+       You should be able to anti-alias a login id,
+       making the user unknown for mail delivery purposes.
+               username:<NUL>
+
+7/30/81
+       Scansub should insert ">>" if msg body all fits on the scan line.
+
+7/30/81
+       Speed MH up by having 2 interfaces: a monolithic environment
+       for speed in commonly used commands, and the current MH
+       environment for generality.
+
+8/4/81
+       Move all the scattered mail alias files to /usr/MailLists.
+       Also move /etc/MailAliases and /etc/mh to /usr.
+
+8/17/81
+       add a -noreorder switch to request that MH process the msg
+       list in the GIVEN order, not in sorted order.
+
+8/20/81
+       There should be a common LOGFILE to be written by srvrftp,
+       rmail, and deliver.
+
+8/20/81
+       An environment variable should be set so that MH can choose
+       an editor based on your terminal type.
+
+
+
+
+MAIL ROUTING
+
+       Modularize the delivery process so that new networks can
+       be easily incorporated (e.g., SU-DSN is on the arpanet as well as
+       the ethernet)
+
+       Host table lookup:  "joe at destination"
+
+       Etc...
+
+9/12/81
+       From: wales at UCLA-Security (Rich Wales)
+       Subject: mail security and mailing to files/pipes
+
+9/16/81
+       From: greep at SU-DSN
+
+       How about an option in comp (along with "list", "edit", "quit", and
+       "send") to get a new shell? Sometimes I'm in the middle of composing
+       a message and realize there's some program I want to run.
+
+11/3/81
+       From: Dave-Yost at RAND-UNIX
+       Subject: 'message does not exist'
+
+        If I do something with cur and the message pointed to doesn't
+        exist, I think mh should automatically look for the next message.
+        Or at least it should be something I can opt for with an entry in
+        .mh_profile.
+
+       This I don't need:
+         % show      # look at the current message
+         % rmm       # decide to junk it
+         % ...       # do some other work
+         % show      # show current message if not deleted, else next
+         Message 18 doesn't exist.
+
+       --dave
+
+11/4/81
+       From: Dave-Yost at RAND-UNIX
+       Subject: mh vs mail or msg or ms or Berkmail or ...
+
+       I'll tell ya, I'm a fan of mh and everything, but
+       mh has GOT to be optionally available as a
+       monolithic program within which you give mh
+       commands.
+
+       (See /r/phyl/Mail/MH for discussion)
+
+11/24/81
+       SUBJECT: An mh argument to specify the profile file
+       From: norm at RAND-UNIX
+
+        What the world needs is for every mh command to have an optional
+        flag, say "-profile", which introduces an alternative file to be
+        used, for all purposes, instead of .mh_profile.
+
+        This capability has a number of obvious and less obvious
+        consequences that would make mh a much more powerful system and
+        seems to have little adverse impact when not used.
+
+
+1/24/82
+       Subject: mail aliases and automatic forwarding
+
+       MH should provide facilities for a user to
+       forward/unforward his mail somewhere easily.
+       This does NOT mean telling him that all he has
+       to do is write a shell procedure and install it
+       in his .mh_receive file.  The MH command I am
+       proposing would do that for you, and do the
+       appropriate locking against race conditions.
+       You need to be able to divert your incoming mail,
+       and to set up other aliases to your login name--
+       in this case, the command should send a message
+       to a system administrator requresting the alias.
+
+       Bell mail allows a user to write, for example,
+               Forward to harpo!ber
+       in the beginning of your mail spool file to
+       forward mail.  (Brian also points out that that is
+       also the ONLY aliasing that they provide.)
+       I don't think this is such a good idea, since
+       it requires knowledge of where the mail spool file is,
+       and is susceptible to a race condition if incoming mail
+       comes in while you are messing with the spool 
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/adrparse.h b/docs/historical/mh-jun-1982/adrparse.h
new file mode 100644 (file)
index 0000000..6d49ae4
--- /dev/null
@@ -0,0 +1,35 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+struct  mailname {
+       struct mailname *m_next;
+       char            *m_text,
+                       *m_headali,    /***/
+                       *m_mbox,
+                       *m_at,
+                       *m_host,
+                       *m_hs, *m_he;
+       long            m_hnum;
+       char            m_nohost;
+}  *getm();
+
+char *adrformat(), *getname(), *stdhost();
+
+struct  hosts {
+       struct hosts *nh_next;
+       char *nh_name;
+       long nh_num;
+} hosts;
+
+#ifdef ARPANET
+long gethnum();
+#else
+#define HOSTNAME "(local)"
+#define HOSTNUM  0
+#endif
+/* If on the ARPANET, whoami.h should have these defined. */
+/* If not on the ARPANET, delete HOSTNAME, HOSTNUM from whoami.h */
diff --git a/docs/historical/mh-jun-1982/dytest/Makefile b/docs/historical/mh-jun-1982/dytest/Makefile
new file mode 100644 (file)
index 0000000..d2dfb29
--- /dev/null
@@ -0,0 +1,414 @@
+#
+#       Proprietary Rand Corporation, 1981.
+#       Further distribution of this software
+#       subject to the terms of the Rand
+#       license agreement.
+#
+
+#                       Remove the -DRAND elsewhere!
+# In ../mh.h: define ARPANET if you are on the arpanet.
+# In ../mh.h: define VMUNIX if you are running a berkeley system
+LIBJOBS=#-ljobs
+
+CFLAGS  = -O $(A) # -m -DRAND
+# The following two must match entry in ../Makefile
+BINDIR  = /usr/local
+MHDIR   = /etc/mh
+MHTMP   = /usr/tmp/mh
+LOCKDIR = /usr/spool/locks
+NETDIR  = /usr/spool/netmail
+
+SUBS    = ../subs/subs.a
+STRINGS = ../strings/strings.a
+
+LINT    = lint
+
+# The 'dist' program is not ready yet, and so is not listed in the CMDS
+# See also ../man/Makefile
+CMDS    = \
+ali \
+comp \
+file \
+folder \
+forw \
+inc \
+mail \
+mhpath \
+next \
+news \
+pick \
+prev \
+prompter \
+repl \
+rmf \
+rmm \
+scan \
+send \
+show
+
+MISC    = \
+conflict \
+deliver \
+install-mh \
+mhl
+
+PROGS = $(CMDS) $(MISC) rmail
+
+CFILES  = \
+adrformat.c \
+adrparse.c \
+ali.c \
+comp.c \
+conflict.c \
+deliver.c \
+dist.c \
+file.c \
+folder.c \
+forw.c \
+inc.c \
+install-mh.c \
+mail.c \
+mhl.c \
+mhpath.c \
+news.c \
+next.c \
+pick.c \
+prompter.c \
+repl.c \
+rmail.c \
+rmf.c \
+rmm.c \
+scan.c \
+scansub.c \
+send.c \
+show.c
+
+progs:  $(PROGS)
+
+ali:    ali.o $(SUBS)
+       $(CC) -o ali ali.o $(SUBS)
+
+comp:   comp.o $(SUBS) $(STRINGS)
+       $(CC) -o comp comp.o $(SUBS) $(STRINGS)
+
+conflict: conflict.o $(SUBS)
+       $(CC) -o conflict conflict.o $(SUBS)
+
+deliver: deliver.o adrparse.o adrformat.o $(SUBS) $(STRINGS)
+       $(CC) -o deliver deliver.o adrparse.o adrformat.o $(SUBS) $(STRINGS)\
+       $(JOBSLIB)
+
+dist:   dist.o annotate.o $(SUBS) $(STRINGS)
+       $(CC) -o dist dist.o annotate.o $(SUBS) $(STRINGS)
+
+file:   file.o $(SUBS) $(STRINGS)
+       $(CC) -o file file.o $(SUBS) $(STRINGS)
+
+folder: folder.o $(SUBS) $(STRINGS)
+       $(CC) -o folder folder.o $(SUBS) $(STRINGS)
+
+forw:   forw.o annotate.o $(SUBS) $(STRINGS)
+       $(CC) -o forw forw.o annotate.o $(SUBS) $(STRINGS)
+
+inc:    inc.o scansub.o $(SUBS) $(STRINGS)
+       $(CC) -o inc inc.o scansub.o $(SUBS) $(STRINGS)
+
+install-mh: install-mh.o $(SUBS) $(STRINGS)
+       $(CC) -o install-mh install-mh.o $(SUBS) $(STRINGS)
+
+mail:   mail.o $(SUBS) $(STRINGS)
+       $(CC) -o mail mail.o $(SUBS) $(STRINGS)
+
+mhpath: mhpath.o $(SUBS) $(STRINGS)
+       $(CC) -o mhpath mhpath.o $(SUBS) $(STRINGS)
+
+mhl:    mhl.o $(SUBS) $(STRINGS)
+       $(CC) -o mhl mhl.o $(SUBS) $(STRINGS)
+
+news:   news.o $(SUBS) $(STRINGS)
+       $(CC) -o news news.o $(SUBS) $(STRINGS)
+
+next:   nexthdr.o next.o $(SUBS) $(STRINGS)
+       $(CC) -o next nexthdr.o next.o $(SUBS) $(STRINGS)
+
+pick:   pick.o grep.o $(SUBS) $(STRINGS)
+       $(CC) -o pick pick.o grep.o $(SUBS) $(STRINGS)
+
+prev:   prevhdr.o next.o $(SUBS) $(STRINGS)
+       $(CC) -o prev prevhdr.o next.o $(SUBS) $(STRINGS)
+
+prompter: prompter.o $(SUBS) $(STRINGS)
+       $(CC) -o prompter prompter.o $(SUBS) $(STRINGS)
+
+repl:   repl.o annotate.o adrparse.o adrformat.o $(SUBS) $(STRINGS)
+       $(CC) -o repl repl.o annotate.o adrparse.o adrformat.o $(SUBS) $(STRINGS)
+
+rmail:  rmail.o  $(SUBS) $(STRINGS)
+       $(CC) -o rmail rmail.o  $(SUBS) $(STRINGS)
+
+rmf:    rmf.o $(SUBS) $(STRINGS)
+       $(CC) -o rmf rmf.o $(SUBS) $(STRINGS)
+
+rmm:    rmm.o $(SUBS) $(STRINGS)
+       $(CC) -o rmm rmm.o $(SUBS) $(STRINGS)
+
+scan:   scan.o scansub.o $(SUBS) $(STRINGS)
+       $(CC) -o scan scan.o scansub.o $(SUBS) $(STRINGS)
+
+send:   send.o $(SUBS) $(STRINGS)
+       $(CC) -o send send.o $(SUBS) $(STRINGS)
+
+show:   show.o $(SUBS) $(STRINGS)
+       $(CC) -o show show.o $(SUBS) $(STRINGS)
+
+lint:
+       -$(LINT) ali.c -v ../subs/subs-lc | tee ali.lint
+       -$(LINT) comp.c -v ../subs/subs-lc | tee comp.lint
+       -$(LINT) conflict.c -v ../subs/subs-lc | tee conflict.lint
+       -$(LINT) deliver.c adrparse.c adrformat.c -v ../subs/subs-lc | tee deliver.lint
+       -$(LINT) dist.c -v ../subs/subs-lc | tee dist.lint
+       -$(LINT) file.c -v ../subs/subs-lc | tee file.lint
+       -$(LINT) folder.c -v ../subs/subs-lc | tee folder.lint
+       -$(LINT) forw.c annotate.c -v ../subs/subs-lc | tee forw.lint
+       -$(LINT) inc.c scansub.c -v ../subs/subs-lc | tee inc.lint
+       -$(LINT) install-mh.c -v ../subs/subs-lc | tee install.lint
+       -$(LINT) mail.c -v ../subs/subs-lc | tee mail.lint
+       -$(LINT) mhl.c -v ../subs/subs-lc | tee mhl.lint
+       -$(LINT) mhpath.c -v ../subs/subs-lc | tee mhpath.lint
+       -$(LINT) news.c -v ../subs/subs-lc | tee news.lint
+       -$(LINT) pick.c -v ../subs/subs-lc | tee pick.lint
+       -$(LINT) prevhdr.c next.c -v ../subs/subs-lc | tee prev.lint
+       -$(LINT) prompter.c -v ../subs/subs-lc | tee prompter.lint
+       -$(LINT) repl.c replsubs.c -v ../subs/subs-lc | tee repl.lint
+       -$(LINT) rmf.c -v ../subs/subs-lc | tee rmf.lint
+       -$(LINT) rmm.c -v ../subs/subs-lc | tee rmm.lint
+       -$(LINT) scan.c scansub.c -v ../subs/subs-lc | tee scan.lint
+       -$(LINT) show.c -v ../subs/subs-lc | tee show.lint
+
+install: strip installprogs
+       -mkdir $(MHTMP)
+       chmod 777 $(MHTMP)
+       -mkdir $(MHDIR)
+       -mkdir $(LOCKDIR)
+       -mkdir $(NETDIR)
+       -chmod a+x $(MISC)
+       -cd $(MHDIR); rm -f $(MISC)
+       -cp $(MISC) $(MHDIR)
+       echo Now become root and \'make installroot\'
+
+installprogs:
+       -chmod a+x $(PROGS)
+       -cd $(BINDIR); rm -f $(CMDS) folders
+       -cp $(CMDS) $(BINDIR)
+       -cd $(BINDIR); ln folder folders
+
+installroot:
+       -cd $(BINDIR); chmod a+x $(CMDS)
+       -cd $(MHDIR); chmod a+x $(MISC)
+       /etc/chown root $(NETDIR)
+       chmod 755  $(NETDIR)
+       -rm -f /bin/rmail
+       /etc/chown root $(LOCKDIR)
+       chmod 777  $(LOCKDIR)
+       -cp rmail /bin
+#           Setuid and Setgid:
+       -chmod 6755 /bin/rmail
+#           Sticky Bit & Setgid:   (?Setuid? PK)
+       -/etc/chown root $(MHDIR)/deliver;chmod 5755 $(MHDIR)/deliver
+#           Sticky Bit:
+       -chmod 1755 $(BINDIR)/comp
+       -chmod 1755 $(BINDIR)/inc
+       -chmod 1755 $(BINDIR)/next
+       -chmod 1755 $(BINDIR)/prompter
+       -chmod 1755 $(BINDIR)/show
+
+uninstall:
+       -rmdir $(MHTMP)
+       -cd $(MHDIR); rm -f $(MISC)
+       -cd $(BINDIR); rm -f $(CMDS) folders
+
+strip:
+       -strip $(PROGS)
+
+chmod:
+       chmod a+x $(PROGS)
+
+pinstall:
+       -install -s comp $(BINDIR)/comp
+       -install -s file $(BINDIR)/file
+       -install -s folder $(BINDIR)/folder
+       -install -s forw $(BINDIR)/forw
+       -install -s inc $(BINDIR)/inc
+       -install -s mhl $(MHDIR)/mhl
+       -install -s mhpath $(BINDIR)/mhpath
+       -install -s next $(BINDIR)/next
+       -install -s pick $(BINDIR)/pick
+       -install -s prev $(BINDIR)/prev
+       -install -s prompter $(BINDIR)/prompter
+       -install -s repl $(BINDIR)/repl
+       -install -s rmf $(BINDIR)/rmf
+       -install -s rmm $(BINDIR)/rmm
+       -install -s scan $(BINDIR)/scan
+       -install -s send $(BINDIR)/send
+       -install -s show $(BINDIR)/show
+
+distribution:   clean rmprogs
+
+rmprogs:
+       -rm -f $(PROGS)
+
+clean:
+       -rm -f *.o *.lint
+
+depend:
+       ../misc/depend.sh $(CFILES)
+
+
+###DEPENDENCIES Follow.  Do not delete this line
+adrformat.o:    /usr/include/stdio.h
+adrformat.o:    ../mh.h
+adrformat.o:    ../adrparse.h
+adrformat.o:    /usr/include/ctype.h
+adrparse.o:     /usr/include/stdio.h
+adrparse.o:     /usr/include/whoami.h
+adrparse.o:     ../mh.h
+adrparse.o:     ../adrparse.h
+adrparse.o:     /usr/include/imp.h
+adrparse.o:     /usr/include/ctype.h
+ali.o:  ../mh.h
+ali.o:  /usr/include/stdio.h
+ali.o:  /usr/include/ctype.h
+ali.o:  /usr/include/pwd.h
+ali.o:  /usr/include/sys/types.h
+comp.o:         ../mh.h
+comp.o:         /usr/include/stdio.h
+comp.o:         /usr/include/strings.h
+comp.o:         /usr/include/signal.h
+conflict.o:     /usr/include/stdio.h
+conflict.o:     /usr/include/ctype.h
+conflict.o:     /usr/include/pwd.h
+conflict.o:     /usr/include/grp.h
+conflict.o:     /usr/include/sys/types.h
+conflict.o:     /usr/include/sys/dir.h
+conflict.o:     ../mh.h
+conflict.o:     /usr/include/mailsys.h
+deliver.o:      /usr/include/whoami.h
+deliver.o:      ../mh.h
+deliver.o:      ../adrparse.h
+deliver.o:      /usr/include/stdio.h
+deliver.o:      /usr/include/ctype.h
+deliver.o:      /usr/include/pwd.h
+deliver.o:      /usr/include/sys/types.h
+deliver.o:      /usr/include/sys/timeb.h
+deliver.o:      /usr/include/sys/stat.h
+deliver.o:      /usr/include/signal.h
+deliver.o:      /usr/include/strings.h
+deliver.o:      /usr/include/mailsys.h
+deliver.o:      /usr/include/time.h
+dist.o:         ../mh.h
+dist.o:         /usr/include/stdio.h
+dist.o:         /usr/include/signal.h
+dist.o:         /usr/include/strings.h
+dist.o:         /usr/include/sys/types.h
+dist.o:         /usr/include/sys/stat.h
+file.o:         ../mh.h
+file.o:         ../folder.h
+file.o:         /usr/include/stdio.h
+folder.o:       ../mh.h
+folder.o:       /usr/include/stdio.h
+folder.o:       /usr/include/sys/types.h
+folder.o:       /usr/include/sys/stat.h
+folder.o:       /usr/include/strings.h
+forw.o:         ../mh.h
+forw.o:         /usr/include/stdio.h
+forw.o:         /usr/include/signal.h
+forw.o:         /usr/include/strings.h
+forw.o:         /usr/include/sys/types.h
+forw.o:         /usr/include/sys/stat.h
+inc.o:  ../mh.h
+inc.o:  /usr/include/stdio.h
+inc.o:  /usr/include/sys/types.h
+inc.o:  /usr/include/sys/stat.h
+inc.o:  /usr/include/errno.h
+inc.o:  /usr/include/strings.h
+inc.o:  /usr/include/signal.h
+inc.o:  scansub.h
+install-mh.o:   ../mh.h
+install-mh.o:   /usr/include/stdio.h
+install-mh.o:   /usr/include/sys/types.h
+install-mh.o:   /usr/include/sys/stat.h
+mail.o:         ../mh.h
+mail.o:         /usr/include/stdio.h
+mail.o:         /usr/include/signal.h
+mhl.o:  /usr/include/ctype.h
+mhl.o:  /usr/include/signal.h
+mhl.o:  /usr/include/setjmp.h
+mhl.o:  /usr/include/sgtty.h
+mhl.o:  /usr/include/stdio.h
+mhl.o:  ../mh.h
+mhpath.o:       ../mh.h
+mhpath.o:       /usr/include/stdio.h
+mhpath.o:       /usr/include/strings.h
+mhpath.o:       /usr/include/ctype.h
+news.o:         ../mh.h
+news.o:         /usr/include/stdio.h
+news.o:         /usr/include/sys/types.h
+news.o:         /usr/include/sys/stat.h
+news.o:         /usr/include/sys/dir.h
+news.o:         /usr/include/strings.h
+news.o:         /usr/include/sys/timeb.h
+next.o:         ../mh.h
+next.o:         /usr/include/stdio.h
+next.o:         /usr/include/strings.h
+pick.o:         ../mh.h
+pick.o:         ../folder.h
+pick.o:         /usr/include/stdio.h
+pick.o:         /usr/include/signal.h
+pick.o:         /usr/include/sys/types.h
+pick.o:         /usr/include/sys/stat.h
+prompter.o:     ../mh.h
+prompter.o:     /usr/include/stdio.h
+prompter.o:     /usr/include/errno.h
+prompter.o:     /usr/include/sgtty.h
+prompter.o:     /usr/include/signal.h
+prompter.o:     /usr/include/strings.h
+repl.o:         /usr/include/whoami.h
+repl.o:         ../mh.h
+repl.o:         /usr/include/stdio.h
+repl.o:         /usr/include/signal.h
+repl.o:         /usr/include/strings.h
+repl.o:         /usr/include/sys/types.h
+repl.o:         /usr/include/sys/stat.h
+repl.o:         ../adrparse.h
+rmail.o:        ../mh.h
+rmail.o:        /usr/include/whoami.h
+rmail.o:        /usr/include/stdio.h
+rmail.o:        /usr/include/sys/types.h
+rmail.o:        /usr/include/sys/timeb.h
+rmail.o:        /usr/include/time.h
+rmf.o:  ../mh.h
+rmf.o:  /usr/include/stdio.h
+rmf.o:  /usr/include/strings.h
+rmm.o:  ../mh.h
+rmm.o:  /usr/include/stdio.h
+rmm.o:  /usr/include/strings.h
+scan.o:         ../mh.h
+scan.o:         /usr/include/stdio.h
+scan.o:         /usr/include/strings.h
+scan.o:         scansub.h
+scansub.o:      ../mh.h
+scansub.o:      /usr/include/whoami.h
+scansub.o:      /usr/include/stdio.h
+scansub.o:      /usr/include/ctype.h
+scansub.o:      /usr/include/time.h
+scansub.o:      ../adrparse.h
+scansub.o:      scansub.h
+send.o:         ../mh.h
+send.o:         /usr/include/stdio.h
+send.o:         /usr/include/sys/types.h
+send.o:         /usr/include/stat.h
+send.o:         /usr/include/strings.h
+send.o:         /usr/include/signal.h
+show.o:         ../mh.h
+show.o:         /usr/include/stdio.h
+show.o:         /usr/include/st
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/dytest/README b/docs/historical/mh-jun-1982/dytest/README
new file mode 100644 (file)
index 0000000..10d9c01
--- /dev/null
@@ -0,0 +1,2 @@
+This directory contains Dave Yost's test versions
+of some mh commands.
diff --git a/docs/historical/mh-jun-1982/dytest/mhl.c b/docs/historical/mh-jun-1982/dytest/mhl.c
new file mode 100644 (file)
index 0000000..1441e3c
--- /dev/null
@@ -0,0 +1,762 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+/*  THIS command is included wholesale by show.c, which calls
+ *  its `main' rather than execing it when showproc is "mhl"
+ */
+
+#include <ctype.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <sgtty.h>
+#ifndef  INCLUDED_BY_SHOW
+#include <stdio.h>
+#include "../mh.h"
+#endif   INCLUDED_BY_SHOW
+char *calloc();
+extern char *index();
+extern char *sprintf();
+
+char    *ignores[25];
+char    **igp = ignores;        /* List of ignored components           */
+char    *parptr, *parse();
+char    *fmtfile;               /* User specified format file           */
+char    *folder;                /* Name of folder messages are in       */
+char    *profargs[32];          /* Args extracted from profile          */
+int     ofilec;                 /* Count of real output file args       */
+int     ofilen;                 /* Number of output file                */
+int     ontty;                  /* Output to char device                */
+int     clearflg;               /* Overrides format screen clear        */
+int     row, column;            /* For character output routine         */
+int     alength, awidth;        /* -length and -width args              */
+char    *oneline();
+int     sigcatch();
+int     exitstat;
+jmp_buf env;
+
+extern  char _sobuf[];          /* MLW  standard out buffer */
+char    *strcpy();
+
+/* Defines for c_flags (see below)                                      */
+#define NOCOMPONENT     01      /* Don't show component name            */
+#define UPPERCASE       02      /* Display in all upper case            */
+#define CENTER          04      /* Center line within width             */
+#define CLEARTEXT      010      /* Clear text line--simply copy to output */
+#define PROCESSED      020      /* This item processed already          */
+#define EXTRA          040      /* This message comp is an "extra"      */
+#define HDROUTPUT     0100      /* This comp's hdr has been output      */
+#define CLEARSCR      0200      /* Clear screen before each file        */
+#define LEFTADJUST    0400      /* Left adjust mult lines of component  */
+#define COMPRESS     01000      /* Compress text--ignore <lf's>         */
+
+struct  comp  {
+       struct comp  *c_next;   /* Chain to next                        */
+       char         *c_name,   /* Component name                       */
+                    *c_text,   /* Text associated with component       */
+                    *c_ovtxt;  /* Line overflow indicator text         */
+       int           c_offset, /* Left margin indent                   */
+                     c_ovoff,  /* Line overflow indent                 */
+                     c_width,  /* Width of field                       */
+                     c_cwidth, /* Component width (default strlen(comp)) */
+                     c_length; /* Length in lines                      */
+       short         c_flags;  /* Special flags (see above)            */
+
+} *msghd, *msgtl, *fmthd, *fmttl,
+                               /* Global contains global len/wid info  */
+  global = { NULL, NULL, NULL,   "", 0, 0, 80,  0, 40, 0 },
+  holder = { NULL, NULL, NULL, NULL, 0, 0,  0,  0,  0, NOCOMPONENT };
+
+/* Defines for putcomp subrutine mode arg                               */
+#define ONECOMP         0       /* Display only control comp name       */
+#define BOTHCOMP        1       /* Display both comp names (conditionally) */
+
+/*ARGSUSED*/
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       register struct comp *comp;
+       register char *cp, **ap;
+       FILE *fp;
+       char line[256], name[64];
+       int out();
+
+       invo_name = argv[0];
+       setbuf(stdout, _sobuf);
+       VOID signal(SIGQUIT, out);
+       ontty = gtty(1, (struct sgttyb *)name) != -1;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(getcpy(cp), " ", "\n");
+               VOID copyip(ap, profargs);
+/*              procargs(ap);*/
+               procargs(profargs);
+       }
+       procargs(argv + 1);
+       if(!folder)
+               folder = getenv("mhfolder");
+       if(fmtfile) {
+               if((fp = fopen(m_maildir(fmtfile), "r")) == NULL) {
+                       fprintf(stderr, "mhl: Can't open format file: %s\n",
+                               fmtfile);
+                       done(1);
+               }
+       } else if((fp = fopen(m_maildir(mhlformat), "r")) == NULL &&
+                 (fp = fopen(mhlstdfmt, "r")) == NULL) {
+                       fprintf(stderr, "mhl: Can't open default format file.\n");
+                       done(1);
+       }
+       while(fgets(line, sizeof line, fp)) {
+               if(line[0] == ';')              /* Comment line */
+                       continue;
+
+               line[strlen(line)-1] = 0;       /* Zap the <lf> */
+
+               if(line[0] == ':') {            /* Clear text line */
+                       comp = (struct comp *) calloc(1, sizeof (struct comp));
+                       comp->c_text = getcpy(line+1);
+                       comp->c_flags = CLEARTEXT;
+                       comp->c_ovoff = -1;
+                       comp->c_cwidth = -1;
+                       goto fmtqueue;
+               }
+
+               parptr = line;
+               strcpy(name, parse());
+/***  printf("%s %c %s\n", name, *parptr, parptr+1);    */
+               switch(*parptr) {
+
+               case '\0':
+               case ',':
+               case '=':
+                       if(uleq(name, "ignores")) {
+                               igp = copyip(brkstring(getcpy(++parptr), ",", NULLCP), igp);
+                               continue;
+                       }
+                       parptr = line;
+                       while(*parptr) {
+                               if(evalvar(&global)) {
+       fmterr:                         fprintf(stderr, "mhl: format file syntax error: %s\n",
+                                               line);
+                                       done(1);
+                               }
+                               if(*parptr)
+                                       parptr++;
+                       }
+                       continue;
+
+               case ':':
+                       comp = (struct comp *) calloc(1, sizeof (struct comp));
+                       comp->c_name = getcpy(name);
+                       comp->c_cwidth = -1;
+                       comp->c_ovoff = -1;
+                       while(*parptr == ':' || *parptr == ',') {
+                               parptr++;
+                               if(evalvar(comp))
+                                       goto fmterr;
+                       }
+       fmtqueue:       if(!fmthd)
+                               fmthd = fmttl = comp;
+                       else {
+                               fmttl->c_next = comp;
+                               fmttl = comp;
+                       }
+                       continue;
+
+               default:
+                       goto fmterr;
+
+               }
+       }
+       if(clearflg == 1)
+               global.c_flags |= CLEARSCR;
+       else if(clearflg == -1)
+               global.c_flags &= ~CLEARSCR;
+       if(awidth) global.c_width = awidth;
+       if(alength) global.c_length = alength;
+       if(global.c_width  < 5) global.c_width  = 10000;
+       if(global.c_length < 5) global.c_length = 10000;
+       VOID fclose(fp);
+       if(!ofilec)
+               process(NULLCP);
+       else {
+               for(ap = profargs; *ap; ap++)
+                       if(**ap)
+                               process(*ap);
+               for(ap = argv+1; *ap; ap++)
+                       if(**ap)
+                               process(*ap);
+       }
+       done(exitstat);
+}
+
+
+evalvar(sp)
+       register struct comp *sp;
+{
+       register char *cp;
+       int c;
+       char name[32];
+
+       if(!*parptr)
+               return 0;
+       strcpy(name, parse());
+/***printf("evalvar: %s %c %s\n", name, *parptr, parptr+1);     */
+       if(uleq(name, "width")) {
+               if(!*parptr++ == '=' || !*(cp = parse())) {
+missing:                fprintf(stderr, "mhl: missing arg to variable %s\n",
+                               name);
+                       return 1;
+               }
+               sp->c_width = atoi(cp);
+               return 0;
+       }
+       if(uleq(name, "compwidth")) {
+               if(!*parptr++ == '=' || !*(cp = parse())) goto missing;
+               sp->c_cwidth = atoi(cp);
+               return 0;
+       }
+       if(uleq(name, "length")) {
+               if(!*parptr++ == '=' || !*(cp = parse())) goto missing;
+               sp->c_length = atoi(cp);
+               return 0;
+       }
+       if(uleq(name, "overflowtext")) {
+               if(!*parptr++ == '=') goto missing;
+               cp = parptr;
+               while(*parptr && *parptr != ':' && *parptr != ',') parptr++;
+               c = *parptr;
+               *parptr = 0;
+               sp->c_ovtxt = getcpy(cp);
+               *parptr = c;
+               return 0;
+       }
+       if(uleq(name, "offset")) {
+               if(!*parptr++ == '=' || !*(cp = parse())) goto missing;
+               sp->c_offset = atoi(cp);
+               return 0;
+       }
+       if(uleq(name, "overflowoffset")) {
+               if(!*parptr++ == '=' || !*(cp = parse())) goto missing;
+               sp->c_ovoff = atoi(cp);
+               return 0;
+       }
+       if(uleq(name, "nocomponent")) {
+               sp->c_flags |= NOCOMPONENT;
+               return 0;
+       }
+       if(uleq(name, "uppercase")) {
+               sp->c_flags |= UPPERCASE;
+               return 0;
+       }
+       if(uleq(name, "center")) {
+               sp->c_flags |= CENTER;
+               return 0;
+       }
+       if(uleq(name, "clearscreen")) {
+               sp->c_flags |= CLEARSCR;
+               return 0;
+       }
+       if(uleq(name, "leftadjust")) {
+               sp->c_flags |= LEFTADJUST;
+               return 0;
+       }
+       if(uleq(name, "compress")) {
+               sp->c_flags |= COMPRESS;
+               return 0;
+       }
+       return 1;
+}
+
+
+char *
+parse()
+{
+       static char result[64];
+       register char *cp;
+       register int c;
+
+       cp = result;
+       while(c = *parptr)
+               if(isalnum(c) || c == '.' || c == '-' || c == '_') {
+                       *cp++ = c;
+                       parptr++;
+               } else
+                       break;
+       *cp = 0;
+       return result;
+}
+
+struct swit switches[] = {
+       "clear",                0,      /* 0 */
+       "noclear",              0,      /* 1 */
+       "folder folder",        0,      /* 2 */
+       "form formfile",        0,      /* 3 */
+       "length of page",       0,      /* 4 */
+       "width of line",        0,      /* 5 */
+       "help",                 4,      /* 6 */
+       0,                      0
+};
+
+procargs(ap)
+       register char **ap;
+{
+       register char *cp;
+
+       while(cp = *ap++)
+               if(*cp == '-') switch(smatch(++cp, switches)) {
+               case -2:ambigsw(cp, switches);  /* ambiguous */
+                       done(1);
+                                               /* unknown */
+               case -1:fprintf(stderr, "mhl: -%s unknown\n", cp);
+                       done(1);
+                                               /* -form format */
+               case 0: clearflg = 1;           /* -clear       */
+                       ap[-1] = "";
+                       break;
+
+               case 1: clearflg = -1;          /* -noclear     */
+                       ap[-1] = "";
+                       break;
+
+               case 2: if(!(folder = *ap++) || *folder == '-') {
+       missing: fprintf(stderr, "mhl: Missing arg for %s\n", ap[-2]);
+                               done(1);
+                       }
+                       ap[-2] = ""; ap[-1] = "";
+                       break;
+
+               case 3: if(!(fmtfile = *ap++) || *fmtfile == '-')
+                               goto missing;
+                       ap[-2] = ""; ap[-1] = "";
+                       break;
+                                               /* length */
+               case 4: if(!(cp = *ap++) || *cp == '-')
+                               goto missing;
+                       alength = atoi(cp);
+                       ap[-2] = ""; ap[-1] = "";
+                       break;
+                                               /* width */
+               case 5: if(!(cp = *ap++) || *cp == '-')
+                               goto missing;
+                       awidth = atoi(cp);
+                       ap[-2] = ""; ap[-1] = "";
+                       break;
+                                               /* -help        */
+               case 6: help("mhl [switches] [files]", switches);
+                       done(0);
+
+               } else
+                       ofilec++;
+}
+
+FILE *fp;
+
+process(fname)
+       char *fname;
+{
+       register int state;
+       register struct comp *comp, *c2, *c3;
+       char *cp, **ip, name[NAMESZ], buf[BUFSIZ];
+
+       if(setjmp(env)) {
+               discard(stdout);
+               putchar('\n');
+               goto out;
+       }
+       VOID signal(SIGINT, sigcatch);
+       if(fname) {
+               if((fp = fopen(fname, "r")) == NULL) {
+                       fprintf(stderr, "mhl: Can't open ");
+                       perror(fname);
+                       exitstat++;
+                       VOID signal(SIGINT, SIG_IGN);
+                       return;
+               }
+       } else
+               fp = stdin;
+       if(ontty) {
+               strcpy(buf, "\n");
+               if(ofilec > 1) {
+                       if(ofilen)
+                               printf("\n\n\n");
+                       printf("Press <return> to list \"");
+                       if(folder) printf("%s:", folder);
+                       printf("%s\"...", fname);
+                       VOID fflush(stdout);
+                       strcpy(buf, "");
+                       VOID read(1, buf, sizeof buf);
+               }
+               if(index(buf, '\n')) {
+                       if(global.c_flags & CLEARSCR)
+                               printf("\014\200");
+               } else
+                       printf("\n");
+       } else if(ofilec > 1) {
+                       if(ofilen)
+                               printf("\n\n\n");
+                       printf(">>> ");
+                       if(folder) printf("%s: ", folder);
+                       printf("%s\n\n", fname);
+       }
+
+       ofilen++;
+       row = column = 0;
+       msghd = 0;
+       for(state = FLD ; ;) {
+               state = m_getfld(state, name, buf, sizeof buf, fp);
+               switch(state) {
+
+               case FLD:
+               case FLDEOF:
+               case FLDPLUS:
+                       for(ip = ignores; *ip; ip++)
+                           if(uleq(name, *ip)) {
+                               while(state == FLDPLUS)
+                                   state = m_getfld(state, name, buf, sizeof buf, fp);
+                               goto next;
+                           }
+                       for(c3 = msghd; c3; c3 = c3->c_next)
+                           if(uleq(name, c3->c_name))
+                               break;
+                       if(c3) {
+                           comp = c3;
+                           comp->c_text = add(buf, comp->c_text);
+                       } else {
+                           comp = (struct comp *) calloc(1, sizeof (struct comp));
+                           comp->c_name = getcpy(name);
+                           comp->c_text = getcpy(buf);
+                           comp->c_cwidth = -1;
+                           comp->c_ovoff = -1;
+                       }
+                       while(state == FLDPLUS) {
+                           state = m_getfld(state, name, buf, sizeof buf, fp);
+                           comp->c_text = add(buf, comp->c_text);
+                       }
+                       for(c2 = fmthd; c2; c2 = c2->c_next)
+                               if(uleq(c2->c_name, comp->c_name))
+                                       goto goodun;
+                       comp->c_flags |= EXTRA;
+          goodun:      if(!c3) {
+                           if(!msghd)
+                                   msghd = msgtl = comp;
+                           else {
+                                   msgtl->c_next = comp;
+                                   msgtl = comp;
+                           }
+                       }
+                       if(state == FLDEOF)
+                           goto doit;
+                       continue;
+
+               default:
+               case LENERR:
+               case FMTERR:
+                       fprintf(stderr, "Message format error!\n");
+                       exitstat++;
+                       return;
+
+               case BODY:
+               case BODYEOF:
+               case FILEEOF:
+       doit:
+                       for(comp = fmthd; comp; comp = comp->c_next) {
+                           if(comp->c_flags & CLEARTEXT) {
+                               putcomp(comp, comp, ONECOMP);
+                               continue;
+                           }
+                           if(uleq(comp->c_name, "messagename")) {
+                               cp = concat(fname, "\n", NULLCP);
+                               if(folder) {
+                                   holder.c_text = concat(folder, ":", cp, NULLCP);
+                                   free(cp);
+                               } else
+                                   holder.c_text = cp;
+                               putcomp(comp, &holder, ONECOMP);
+                               free(holder.c_text);
+                               holder.c_text = 0;
+                           }
+                           if(uleq(comp->c_name, "extras")) {
+                               for(c2 = msghd; c2; c2 = c2->c_next)
+                                   if(c2->c_flags & EXTRA)
+                                       putcomp(comp, c2, BOTHCOMP);
+                               continue;
+                           }
+                           if(uleq(comp->c_name, "body")) {
+                               holder.c_text = buf;
+                               putcomp(comp, &holder, ONECOMP);
+                               holder.c_text = 0;
+                               while(state == BODY) {
+                                   state = m_getfld(state, name, buf, sizeof buf, fp);
+                                   holder.c_text = buf;
+                                   putcomp(comp, &holder, ONECOMP);
+                                   holder.c_text = 0;
+                               }
+                               continue;
+                           }
+                           for(c2 = msghd; c2; c2 = c2->c_next)
+                               if(uleq(c2->c_name, comp->c_name)) {
+                                   putcomp(comp, c2, ONECOMP);
+                                   break;
+                               }
+                       }
+               out:
+                       if(fp)
+                               VOID fclose(fp);
+                       fp = NULL;
+                       if(holder.c_text) cndfree(holder.c_text);
+                       holder.c_text = 0;
+                       for(c2 = msghd; c2; c2 = comp) {
+                               comp = c2->c_next;
+                               cndfree(c2->c_name);
+                               cndfree(c2->c_text);
+                               free( (char *)c2);
+                       }
+                       msghd = msgtl = NULL;
+                       for(c2 = fmthd; c2; c2 = c2->c_next)
+                               c2->c_flags &= ~HDROUTPUT;
+                       VOID signal(SIGINT, SIG_IGN);
+                       return;
+               }
+next:   ;
+       }
+}
+
+int     lm;             /* Left Margin for putstr               */
+int     llim;           /* line limit for this component        */
+int     wid;            /* width limit for this comp            */
+int     ovoff;          /* overflow offset for this comp        */
+char    *ovtxt;         /* overflow text for this comp          */
+int     term;           /* term from last oneline()             */
+char    *onelp;         /* oneline() text pointer               */
+
+putcomp(cc, c2, flag)
+       register struct comp *cc, *c2;
+       int flag;
+{
+       register char *cp;
+       int count, cchdr = 0;
+
+#ifdef DEBUGCOMP
+           printf("%s(%o):%s:%s", cc->c_name, cc->c_flags, c2->c_name,
+               c2->c_text);
+#endif
+       onelp = NULL;
+       lm = 0;
+       llim = cc->c_length? cc->c_length : -1;
+       wid   = cc->c_width? cc->c_width : global.c_width;
+       ovoff = cc->c_ovoff >= 0 ? cc->c_ovoff : global.c_ovoff;
+       ovoff += cc->c_offset;
+       ovtxt = cc->c_ovtxt ? cc->c_ovtxt : global.c_ovtxt;
+       if(!ovtxt) ovtxt = "";
+       if(wid < ovoff + strlen(ovtxt) + 5) {
+               fprintf(stderr, "mhl: component: %s width too small for overflow.\n",
+                       cc->c_name);
+               done(1);
+       }
+       if(cc->c_flags & CLEARTEXT) {
+               putstr(cc->c_text);
+               putstr("\n");
+               return;
+       }
+       if(cc->c_flags & CENTER) {
+               count = global.c_width;
+               if(cc->c_width) count = cc->c_width;
+               count -= cc->c_offset;
+               count -= strlen(c2->c_text);
+               if(!(cc->c_flags&HDROUTPUT) && !(cc->c_flags&NOCOMPONENT))
+                       count -= strlen(cc->c_name) + 2;
+               lm = cc->c_offset+(count/2);
+       } else if(cc->c_offset)
+               lm = cc->c_offset;
+       if(!(cc->c_flags & HDROUTPUT) && !(cc->c_flags & NOCOMPONENT)) {
+               putstr(cc->c_name); putstr(": ");
+               cc->c_flags |= HDROUTPUT;
+               cchdr++;
+               if((count = cc->c_cwidth - strlen(cc->c_name) - 2) > 0)
+                       while(count--) putstr(" ");
+       }
+       if(flag == BOTHCOMP && !(c2->c_flags & HDROUTPUT) &&
+                              !(c2->c_flags & NOCOMPONENT)) {
+               putstr(c2->c_name); putstr(": ");
+               c2->c_flags |= HDROUTPUT;
+       }
+       if(cc->c_flags & UPPERCASE)
+               for(cp = c2->c_text; *cp; cp++)
+                       if(islower(*cp))
+                               *cp -= 'a' - 'A';
+       count = 0;
+       if(cchdr)
+               count = (cc->c_cwidth>=0) ? cc->c_cwidth : strlen(cc->c_name)+2;
+       count += cc->c_offset;
+       putstr(oneline(c2->c_text, cc->c_flags));
+/***   if(cc->c_flags & COMPRESS) printf("-1-");        /***/
+       if(term == '\n')
+               putstr("\n");
+       while(cp = oneline(c2->c_text, cc->c_flags)) {
+/***   if(cc->c_flags & COMPRESS) printf("-2-");        /***/
+               if(*cp) {
+                       lm = count;
+                       putstr(cp);
+                       if(term == '\n')
+                               putstr("\n");
+               } else
+                       if(term == '\n')
+                               putstr("\n");
+       }
+       c2->c_flags |= PROCESSED;
+}
+
+putstr(string)
+       register char *string;
+{
+       if(!column && lm > 0)
+               while(lm > 0)
+                       if(lm >= 8) {
+                               putch('\t');
+                               lm -= 8;
+                       } else {
+                               putch(' ');
+                               lm--;
+                       }
+       lm = 0;
+       while(*string)
+               putch(*string++);
+}
+
+putch(ch)
+{
+       char buf[32];
+
+       if(llim == 0)
+               return;
+       switch(ch) {
+       case '\n':
+               if(llim > 0) llim--;
+               column = 0;
+               row++;
+               if(ontty && row == global.c_length) {
+                       putchar('\007');
+                       VOID fflush(stdout);
+                       buf[0] = 0;
+                       VOID read(1, buf, sizeof buf);
+                       if(index(buf, '\n')) {
+                               if(global.c_flags & CLEARSCR) {
+                                       putchar('\014');
+                                       putchar('\200');
+                               }
+                               row = 0;
+                       } else {
+                               putchar('\n');
+                               row = global.c_length / 3;
+                       }
+                       return;
+               }
+               break;
+       case '\t':
+               column |= 07;
+               column++;
+               break;
+
+       case '\010':
+               column--;
+               break;
+
+       case '\r':
+               column = 0;
+               break;
+
+       default:
+               if(ch >= ' ')
+                       column++;
+       }
+       if(column >= wid) {
+               putch('\n');
+               if(ovoff > 0)
+                       lm = ovoff;
+               if(ovtxt)
+                       putstr(ovtxt);
+               else
+                       putstr("");
+               putch(ch);
+               return;
+       }
+       putchar(ch);
+}
+
+
+char *
+oneline(stuff, flgs)
+       char *stuff;
+{
+       register char *ret;
+       register char *cp;
+       int spc;
+
+       if(!onelp)
+               onelp = stuff;
+       if(!*onelp) {
+               onelp = 0;
+               return NULL;
+       }
+       ret = onelp;
+       term = 0;
+       if(flgs & COMPRESS) {
+               cp = ret;
+               spc = 0;
+               while(*onelp) {
+                       if(*onelp == '\n' || *onelp == '\t' || *onelp == ' '){
+                               if(*onelp == '\n' && !onelp[1]) {
+                                       term = '\n';
+                                       break;
+                               } else if(!spc) {
+                                       *cp++ = ' ';
+                                       spc++;
+                               }
+                       } else {
+                               *cp++ = *onelp;
+                               spc = 0;
+                       }
+                       onelp++;
+               }
+               *onelp = 0;
+               *cp = 0;
+       } else {
+               while(*onelp && *onelp != '\n') onelp++;
+               if(*onelp == '\n') {
+                       term = '\n';
+                       *onelp++ = 0;
+               }
+               if(flgs&LEFTADJUST)
+                       while(*ret == ' ' || *ret == '\t') ret++;
+       }
+       return ret;
+}
+
+
+sigcatch()
+{
+       longjmp(env, 1);
+}
+
+
+out()
+{
+       putchar('\n');
+       VOID fflush(stdout);
+       exit(-1);
+}
+
+discard(io)
+register FILE *io;
+{
+       struct sgttyb sg;
+
+       if (ioctl(fileno (io), TIOCGETP, &sg) >= 0)
+               ioctl(fileno (io), TIOCSETP, &sg);
+       io->_cnt = BUFSIZ;
+       io->_ptr
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/dytest/show.c b/docs/historical/mh-jun-1982/dytest/show.c
new file mode 100644 (file)
index 0000000..83dede2
--- /dev/null
@@ -0,0 +1,177 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+#include <stdio.h>
+#include <strings.h>
+
+int vecp;
+int     header = 1;
+char *vec[MAXARGS];
+struct msgs *mp;
+/*  The minimum match numbers below are all at least 2 as
+/*  a kludge to avoid conflict between switches intended for
+/*  "show" and those that it passes on to pr, mhl, c, ...
+/**/
+struct swit switches[] = {
+       "all",         -3,      /* 0 */
+       "draft",        2,      /* 1 */
+       "header",       2,      /* 2 */
+       "noheader",     3,      /* 3 */
+       "format",       2,      /* 4 */
+       "noformat",     3,      /* 5 */
+       "pr",           2,      /* 6 */
+       "nopr",         3,      /* 7 */
+       "help",         4,      /* 8 */
+       0,              0
+};
+
+extern  char _sobuf[];          /* MLW  standard out buffer */
+
+/*ARGSUSED*/
+main(argc, argv)
+char *argv[];
+{
+       char *folder, *maildir, *msgs[100];
+       register int msgnum;
+       register char *cp, **ap;
+       int msgp, drft, pr, format;
+       char *arguments[50], **argp;
+
+       invo_name = argv[0];
+       setbuf(stdout, _sobuf);
+#ifdef NEWS
+       m_news();
+#endif
+       folder = (char *) 0;
+       pr = msgp = 0;
+       format = 1;
+       vecp = 1;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       VOID copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                            /* unknown */
+                       case -1:vec[vecp++] = --cp;  continue;
+                                                            /* -all   */
+                       case 0: fprintf(stderr, "\"-all\" changed to \"all\"\n");
+                               goto leave;
+                       case 1: drft = 1;  continue;         /* -draft */
+                       case 2: header = 1; continue;        /* -header */
+                       case 3: header = 0; continue;        /* -noheader */
+                       case 4: format = 1;  continue;       /* -format */
+                       case 5: format = 0;  continue;       /* -noformat */
+                       case 6: pr = 1;  continue;           /* -pr    */
+                       case 7: pr = 0;  vecp = 1;  continue;/* -nopr  */
+                       case 8:                              /* -help  */
+  help("show [+folder]  [msgs] [switches] [switches for \"type\" or \"pr\" ]",
+                                    switches);
+                               goto leave;
+                       }
+               if(*cp == '+') {
+                       if(folder) {
+                               fprintf(stderr, "Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               folder = path(cp+1, TFOLDER);
+               } else
+                       msgs[msgp++] = cp;
+       }
+       if(!m_find("path")) free(path("./", TFOLDER));
+       if(drft)
+               maildir = m_maildir("");
+       else {
+               if(!msgp)
+                       msgs[msgp++] = "cur";
+               if(!folder)
+                       folder = m_getfolder();
+               maildir = m_maildir(folder);
+       }
+       if(chdir(maildir) < 0) {
+               fprintf(stderr, "Can't chdir to: ");
+               perror(maildir);
+               goto leave;
+       }
+       if(drft) {
+               vec[vecp++] = draft;
+               goto doit;
+       }
+       if(!(mp = m_gmsg(folder))) {
+               fprintf(stderr, "Can't read folder!?\n");
+               goto leave;
+       }
+       if(mp->hghmsg == 0) {
+               fprintf(stderr, "No messages in \"%s\".\n", folder);
+               goto leave;
+       }
+       if(msgp)
+               for(msgnum = 0; msgnum < msgp; msgnum++)
+                       if(!m_convert(msgs[msgnum]))
+                               goto leave;
+       if(mp->numsel == 0) {
+               fprintf(stderr, "show: potato pancakes.\n");     /* never get here */
+               goto leave;
+       }
+       if(mp->numsel > MAXARGS-2) {
+  fprintf(stderr, "show: more than %d messages for show-exec\n", MAXARGS-2);
+               goto leave;
+       }
+       for(msgnum= mp->lowsel; msgnum<= mp->hghsel; msgnum++)
+               if(mp->msgstats[msgnum]&SELECTED)
+                       vec[vecp++] = getcpy(m_name(msgnum));
+       m_replace(pfolder, folder);
+       if(mp->hghsel != mp->curmsg)
+               m_setcur(mp->hghsel);
+       if(vecp == 2 && header) {
+               printf("(Message %s:%s)\n", folder, vec[1]);
+       }
+doit:
+       VOID fflush(stdout);
+       vec[vecp] = 0;
+       {
+               register char *proc;
+               if(pr)
+                       proc = prproc;
+               else if(format) {
+                       putenv("mhfolder", folder);
+                       if (!showproc) {
+                               mhl(vecp, vec);
+                               m_update();
+                               done(0);
+                       }
+                       proc = showproc;
+               } else {
+                       proc = "/bin/cat";
+                       /* THIS IS INEFFICIENT */
+                       /* what we really should do in this case is
+                       /* copy it out ourself to save the extra exec */
+               }
+               m_update();
+               vec[0] = r1bindex(proc, '/');
+               execv(proc, vec);
+               perror(proc);
+       }
+       done(0);
+ leave:
+       m_update();
+       done(0);
+}
+
+#define switches mhlswitches
+#define INCLUDED_BY_SHOW
+#define main(a,b) mhl(a,b)
+
+#include "mhl.c"
diff --git a/docs/historical/mh-jun-1982/folder.h b/docs/historical/mh-jun-1982/folder.h
new file mode 100644 (file)
index 0000000..2818cfa
--- /dev/null
@@ -0,0 +1,13 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+
+struct st_fold {
+       char        *f_name;
+       int          f_reused;
+       struct msgs *f_mp;
+};
diff --git a/docs/historical/mh-jun-1982/man/Makefile b/docs/historical/mh-jun-1982/man/Makefile
new file mode 100644 (file)
index 0000000..989fd9e
--- /dev/null
@@ -0,0 +1,54 @@
+#
+#       Proprietary Rand Corporation, 1981.
+#       Further distribution of this software
+#       subject to the terms of the Rand
+#       license agreement.
+#
+
+DESTMAN = /usr/man
+
+# 'dist.1' is not ready yet.
+MAN1    = \
+ali.1 \
+comp.1 \
+file.1 \
+folder.1 \
+forw.1 \
+inc.1 \
+mail.1 \
+mh.1 \
+mhl.1 \
+mhpath.1 \
+news.1 \
+next.1 \
+pick.1 \
+prev.1 \
+prompter.1 \
+repl.1 \
+rmail.1 \
+rmf.1 \
+rmm.1 \
+scan.1 \
+send.1 \
+show.1
+
+MAN5    = \
+mh-alias.5 \
+mh-mail.5 \
+netmail.5 \
+mh-profile.5
+
+MAN8    = \
+conflict.8 \
+deliver.8 \
+mailer.8
+
+install: uninstall
+       -cp $(MAN1) $(DESTMAN)/man1
+       -cp $(MAN5) $(DESTMAN)/man5
+       -cp $(MAN8) $(DESTMAN)/man8
+
+uninstall:
+       -cd $(DESTMAN)/man1; rm -f $(MAN1)
+       -cd $(DESTMAN)/man5; rm -f $(MAN5)
+       -cd $(DESTMAN)/man8; rm -f $(MAN8)
diff --git a/docs/historical/mh-jun-1982/man/ali.1 b/docs/historical/mh-jun-1982/man/ali.1
new file mode 100644 (file)
index 0000000..2721bb3
--- /dev/null
@@ -0,0 +1,35 @@
+.TH ALI 1 RAND
+.SH NAME
+ali \- list mail aliases
+.SH SYNOPSIS
+.B ali
+[
+.B \-l
+] name ...
+.SH DESCRIPTION
+.I Ali 
+searches the mail alias file for each of the given
+\fIname\fRs.
+It creates a list of users for whom those
+\fIname\fRs
+are aliases, and writes that list on standard output.
+If the
+.B \-l
+option is specified, each username appears on a separate line;
+otherwise, the names are separated by commas and printed on
+as few lines as possible.  Usernames are not repeated on the
+output list.
+.PP
+Each
+.I name
+is processed as described in mh-alias(5).  After
+processing, any resulting names that do not appear
+in the password file are printed with an error message.
+.SH FILES
+/etc/passwd
+.br
+/etc/MailAliases
+.br
+/etc/group
+.SH SEE ALSO
+deliver(8),mh-alias(5)
diff --git a/docs/historical/mh-jun-1982/man/comp.1 b/docs/historical/mh-jun-1982/man/comp.1
new file mode 100644 (file)
index 0000000..1be70dd
--- /dev/null
@@ -0,0 +1,99 @@
+.TH COMP 1 RAND
+.SH NAME
+comp \- compose a message
+
+.SH SYNOPSIS
+.B comp 
+\%[
+.B \-editor\ \fReditor] \%[
+.B \-form\ \fRformfile] \%[file] \%[
+.B \-use
+] \%[
+.B \-nouse
+] \%[
+.B \-help
+]
+
+.SH DESCRIPTION
+\fIComp\fP is used to create a new message to be mailed.
+If
+\fIfile\fP is not specified, the file named ``draft'' in the user's MH
+directory will be used.
+\fIComp\fR copies a message form to
+the file being composed and then invokes an editor on the
+file.
+The default editor is /bin/e, which may be overridden with
+the `\-editor' switch or with a profile entry ``Editor:''.
+
+The default
+message form contains the following elements:
+
+     To:
+     cc:
+     Subject:
+     ----------
+
+If the file named ``components'' exists in the user's MH directory,
+it will be used instead of this form.
+If `\-form
+formfile' is specified, the specified formfile (from the MH
+directory) will be used as the skeleton.
+The line of dashes
+or a blank line must be left between the header and the
+body of the message for the message to be identified properly when it is
+sent (see \fIsend(1)\fR).
+The switch `\-use' directs \fIcomp\fR to
+continue editing an already started message.
+That is, if a
+\fIcomp\fR (or \fIdist\fR, \fIrepl\fR, or \fIforw\fR) is terminated without
+sending the message, the message can be edited again via
+``comp \-use''.
+
+If the specified file (or draft) already exists, \fIcomp\fR will ask
+if you want to delete it before continuing.
+A reply of \fBNo\fR will abort the
+\fIcomp\fR, \fByes\fR will replace the existing draft with a blank
+skeleton, \fBlist\fR will display the draft, and \fBuse\fR will use it
+for further composition.
+
+Upon exiting from the editor, \fIcomp\fR will ask ``What now?''.
+The valid
+responses are \fBlist\fR, to list the draft on the terminal; \fBquit\fR, to
+terminate the session and preserve the draft; \fBquit delete\fR, to terminate,
+then delete the draft; \fBsend\fR, to send the message; \fBsend verbose\fR, to
+cause the delivery process to be monitored; \fBedit <editor>\fR, to invoke
+<editor> for further editing; and \fBedit\fR, to re-edit using the
+same editor that was used on the preceding round unless a profile
+entry ``<lasteditor>\-next: <editor>'' names an alternative editor.
+
+See \fImh-profile(5)\fR for further information
+about the how editors are used by MH.
+.SH FILES
+.ta 2.4i
+/etc/mh/components             The message skeleton
+.br
+or <mh-dir>/components         Rather than the standard 
+.br
+$HOME/\*.mh\(ruprofile         The user profile
+.br
+<mh-dir>/draft                 The default message file
+.br
+/usr/bin/send                  To send the composed message
+.SH PROFILE\ ELEMENTS
+Path:                  To determine the user's MH directory
+.br
+Editor:                        To override the default editor
+.br
+<lasteditor>\-next:    To name an editor to be used 
+                       after exit from <lasteditor>
+sendproc:      Program to use to send the message
+.SH SEE ALSO
+send(1), dist(1), repl(1)
+.SH DEFAULTS
+`file' defaults to draft
+.br
+`\-editor' defaults to /bin/e
+.br
+`\-nouse'
+.SH CONTEXT
+\fIComp\fR does not affect either the current folder or the current messa
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/man/conflict.8 b/docs/historical/mh-jun-1982/man/conflict.8
new file mode 100644 (file)
index 0000000..0de7418
--- /dev/null
@@ -0,0 +1,52 @@
+.TH CONFLICT 8 RAND
+.SH NAME
+conflict \- Search for alias/password conflicts
+.SH SYNOPSIS
+.B /etc/mh/conflict
+[\fB\-mail\fR\ name]
+.SH DESCRIPTION
+.I Conflict
+is a program which checks to see that inconsistencies between
+the Rand MH alias file (
+.I mh-alias(5)
+) and the
+.I password(5)
+file have not been introduced.  In particular, a line in the
+alias file may be "tom: jones" (because the user "jones" likes to be
+called Tom), but if "tom" is also a valid user name for someone else, then 
+that user will no longer receive any mail; his mail will be received
+by "jones" instead!
+.PP
+.I Conflict
+also checks for mailboxes in /usr/spool/mail which do not belong
+to a valid user.
+It assumes that no user name will start with `.',
+and thus ignores files in /usr/spool/mail which
+begin with `.'.
+It also checks for entries in the
+.I group(5)
+file which do not belong to a valid user, and for users who do
+not belong to any group in the group file.  This last test is
+local to Rand, and will not be performed unless the \-DRAND flag
+was set at compile time.
+.PP
+If the
+.I \-mail
+flag is set, then the results will be sent to the specified
+.I name.
+Otherwise, the results are sent to the standard output.
+.PP
+.I Conflict 
+should be run under 
+.I Cron(1),
+or whenever system accounting takes place.
+.SH FILES
+/etc/MailAliases
+.br
+/etc/passwd
+.br
+/etc/group
+.br
+/usr/spool/mail/*
+.SH SEE ALSO
+mh-alias(5), passwd(5), group(5), ali(1)
diff --git a/docs/historical/mh-jun-1982/man/deliver.8 b/docs/historical/mh-jun-1982/man/deliver.8
new file mode 100644 (file)
index 0000000..875963f
--- /dev/null
@@ -0,0 +1,161 @@
+.TH DELIVER 8 RAND
+.SH NAME
+deliver \- deliver a message
+.SH SYNOPSIS
+.B /etc/mh/deliver 
+[\fB\-deliver\fR user]
+[\fB\-verbose\fR] [\fB\-format\fR] [\fB\-msgid\fR]
+[\fB\-help\fR]  [\fB\-noverbose\fR] [\fB\-noformat\fR] [\fB\-nomsgid\fR] file
+.SH DESCRIPTION
+.I Deliver 
+is the program called by 
+.I send(1)
+to deliver the message in
+.I file
+to a local or remote user.  In fact,
+all of the functions attributed to 
+.I send
+on its manual page are peformed by 
+.I deliver,
+with
+.I send
+acting as a relatively simple preprocessor.  Thus, it is
+.I deliver
+which parses the various header fields, appends From: and 
+Date: lines, and maintains the correct locking on maildrop
+files.  
+.I Deliver
+will not normally be called directly by the user.
+.PP
+.I Deliver
+searches the ``To:'', ``Bcc:'', and ``Fcc:'' header lines of
+the specified message for destination addresses, checks these
+addresses for validity, and formats them so as to conform to 
+Arpanet Mail protocol, unless the 
+.I \-noformat
+flag is set.  This will normally cause ``AT local-site'' to
+be appended to each local destination address, as well
+as any local return addresses..  Destinations are
+of three types:
+.PP
+LOCAL MAIL (e.g. ``To: root''): The message is appended to the 
+appropriate mailbox.  The specified name may be mapped
+into a different user name if it matches an entry in the
+file /etc/MailAlias.  See mh-alias(5) for additional details on the
+aliasing system..
+If the recipient user's home directory contains an 
+executable or shell file named .mh\(rureceive, that program will be
+called via
+
+       execlp (prog, prog, tmpfil, mail, home, alias, 0)
+
+where prog is the receive program, tmpfil is a file in
+/usr/tmp which is the mail to be received, mail is the path of
+the user's mail drop (/usr/spool/mail/name), home is the
+$HOME directory of the user, and alias is the string that matched
+the first in a sequence of local aliases.  File descriptor 3 will have
+tmpfil opened on it read only.  These are all the RECEIVER'S
+parameters, not the sender's.  Also, the environment is set up
+with appropriate values for HOME and USER.
+.PP
+ARPANET MAIL (e.g. ``To: root@bbn-unix''): A copy of the message is 
+left as a uniquely-named file 
+in the Arpanet mail queue directory (/usr/spool/netmail/), 
+with the text prepended
+by a list of the network addresses of the recipients.  The
+format of this queue file is given in 
+.I netmail(5).
+The file is picked up by an Arpanet mailer daemon (
+.I mailer(8)
+)
+for later processing.
+.PP
+UUCP MAIL (e.g. ``To: ucbvax!root''): Uux(1) is forked with the 
+.I file 
+as
+its standard input, so as to execute mail(1) at the remote site.
+Thus, a message with a field such as given in the example would
+be given as standard input with a command line of
+
+       uux \- ucbvax!rmail root
+
+Rmail is assumed to be linked to mail(1) (or an equivalent program
+such as the UC Berkeley or Bell mail programs)
+so as to correctly deliver the
+message at the remote site.
+.PP
+It is possible to have all three types of destinations in the various
+destination fields of the message; each destination is processed
+separately.  It is also possible to mix destinations from the
+two delivery networks.  For example, one might specify a destination
+of ``csvax!root@Berkeley''.  However, there is an ambiguity here as
+to whether 
+.I deliver
+should attempt to use the Arpanet to send the message to Berkeley
+with ``csvax!root'' as the recipient, or whether it should use uux
+to tell csvax to deliver mail to ``root@Berkeley''.  The choice
+is determined by a compile-time constant which tells whether
+or not the local machine is on the Arpanet.  If it is, the message
+is sent via the Arpanet to the remote host, which presumably
+forwards the message via uux.  Otherwise the at-sign is given
+no special treatment,
+and the message is sent via uux.
+.PP
+If the 
+.B \-deliver
+flag is set, 
+.I deliver
+will attempt to send the message to the appropriate user
+with no formatting or header processing.  As this is primarily
+for the use of the 
+.I rmail(1)
+command, use of this flag is restricted to the super-user.
+.ta 2.4i
+.SH FILES
+/usr/spool/mail/*      Recipient mail drop
+.br
+/usr/spool/locks/*     Lockout for the mail drop
+.br
+/usr/spool/netmail/*   Arpanet mail queue
+.br
+/usr/spool/mailt/*      Arpanet temp mail queue
+.br
+/usr/tmp/mh/locsXXXX.tmpTemporary local output file
+.br
+/usr/tmp/mh/uulcXXXX.tmpTemporary uucp output file
+.br
+/etc/MailAliases       Alias list
+.SH PROFILE COMPONENTS
+fileproc:      Used for Fcc: processing
+.SH SEE ALSO
+\fIThe MH Message Handling System: User's Manual\fR
+by B. Borden, R. Gaines, and N. Shapiro
+.br
+\fIStandard for the Format of ARPA Network Test Messages\fR
+by D. Crocker, J. Vittal, K. Pogran, and D. Henderson, Jr.
+.br
+send(1)
+.br
+mail(1)
+.br
+rmail(1)
+.br
+uux(1)
+.br
+netmail(5)
+.br
+mh-mail(5)
+.br
+mh-alias(5)
+.SH DEFAULTS
+.br
+`\-noverbose'
+.br
+`\-format'
+.br
+`\-nomsgid'
+.SH BUGS
+If the message is going through a series of hops (say, via UUCP links),
+the "From" field will not be adequate for a reply.  Deliver should,
+but currently does not, formulate a "Reply-to:" field for such
+compicated cases.
diff --git a/docs/historical/mh-jun-1982/man/dist.1 b/docs/historical/mh-jun-1982/man/dist.1
new file mode 100644 (file)
index 0000000..8f75984
--- /dev/null
@@ -0,0 +1,96 @@
+.TH DIST 1 RAND
+.SH NAME
+dist \- redistribute a message to additional addresses
+.SH SYNOPSIS
+\fBdist\ \fR
+\%[\fB+folder\fR] 
+\%[msg] 
+\%[\fB\-form\fR\ formfile] 
+\%[\fB\-editor\fR\ editor]
+\%[\fB\-annotate\fR]
+\%[\fB\-noannotate\fR] 
+\%[\fB\-inplace\fR] 
+\%[\fB\-noinplace\fR] 
+\%[\fB\-help\fR]
+.SH DESCRIPTION
+\fIDist\fR is similar to \fIforw\fR.
+It prepares the specified
+message for redistribution to addresses that (presumably) are
+not on the original address list.
+The file ``distcomps'' in the
+user's MH directory, or a standard form, or the file specified by
+`\-form formfile' will be used as the blank components file to
+be prepended to the message being distributed.
+The standard form
+has the components ``Distribute-to:'' and ``Distribute-cc:''.
+When
+the message is sent, ``Distribution-Date:\ date'',
+``Distribution-From:\ name'', and
+``Distribution-Id:\ id'' (if `\-msgid' is
+specified to \fIsend(1)\fR;) will be prepended to the outgoing message.
+Only those addresses in ``Distribute-To'', ``Distribute-cc'', and
+``Distribute-Bcc'' will be sent.
+Also, a ``Distribute-Fcc:\ folder''
+will be honored (see \fIsend(1)\fR).
+
+\fISend\fR recognizes a message as a redistribution message by the
+existence of the field ``Distribute-To:'', so don't try to
+redistribute a message with only a ``Distribute-cc:''.
+
+If the `\-annotate' switch is given, each message being
+distributed will be annotated with the lines:
+
+     Distributed:\ <<date>>
+     Distributed:\ Distribute-to: names
+
+where each ``to'' list contains as many lines as required.
+This annotation
+will be done only if the message is sent directly from \fIdist\fR.
+If the
+message is not sent immediately from \fIdist\fR (i.e., if it is sent later
+via \fIsend\fR),
+``comp \-use'' may be used to re-edit and send the constructed message, but
+the annotations won't take place.
+The '\-inplace' switch causes annotation to
+be done in place in order to preserve links to the annotated message.
+
+See \fIcomp(1)\fR for a description of the `\-editor' switch and for options
+upon exiting from the editor.
+See \fImh-profile(5)\fR for further information
+about the how editors are used by MH.
+.SH FILES
+.ta 2.4i
+/etc/mh/components     The message skeleton
+.br
+or <mh-dir>/components Rather than the standard skeleton
+.br
+$HOME/.mh\(ruprofile   The user profile
+.br
+<mh-dir>/draft The default message file
+.br
+/usr/ucb/send  To send the composed message
+.SH PROFILE COMPONENTS
+Path:  To determine the user's MH directory
+.br
+Editor:        To override the use of /bin/ned as the default editor
+.br
+<lasteditor>\-next:    To name an editor to be used 
+                       after exit from <lasteditor>
+.br
+sendproc:              Program to use for Send
+.SH SEE ALSO
+comp(1), deliver(8)
+.SH DEFAULTS
+`+folder' defaults to the current folder
+.br
+`msg' defaults to cur
+.br
+`\-editor' defaults to /bin/ned
+.br
+`\-noannotate'
+.br
+`\-noinplace'
+.SH CONTEXT
+If a +folder is specified, it will become the current
+folder, and the current message will be set to the message
+being redistr
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/man/file.1 b/docs/historical/mh-jun-1982/man/file.1
new file mode 100644 (file)
index 0000000..048eca9
--- /dev/null
@@ -0,0 +1,87 @@
+.TH FILE 1 RAND
+.SH NAME
+file \- file message(s) in (an)other folder(s)
+.SH SYNOPSIS
+\fBfile \%[\fB\-\fRsrc\ +folder] \%[msgs] \%[\fB\-link\fR] \%[\fB\-preserve\fR] \%+folder\ ...
+\%[\fB\-nolink\fR] \%[\fB\-nopreserve\fR]
+\%[\fB\-file\fR\ file] \%[\fB\-nofile\fR] \%[\fB\-help\fR]
+.SH DESCRIPTION
+\fIFile\fR moves (\fImv\fR(1)) or links (\fIln\fR(1)) messages from a
+source folder into one or more destination folders.
+If you think
+of a message as a sheet of paper, this operation is not
+unlike filing the sheet of paper (or copies) in file cabinet
+folders.
+When a message is filed, it is linked into the
+destination folder(s) if possible, and is copied otherwise.
+As long
+as the destination folders are all on the same file system, multiple filing
+causes little storage overhead.
+This facility provides a good way to cross-file or multiply-index
+messages.
+For example, if a message is received from Jones about
+the ARPA Map Project, the command
+
+     file\0cur\0+jones\0+Map
+
+would allow the message to be found in either of the two
+folders `jones' or `Map'.
+
+The option `\-file file' directs \fIfile\fR to use the specified
+file as the source message to be filed, rather than a message from
+a folder.
+
+If a destination folder doesn't exist, \fIfile\fR will ask if you
+want to create one.
+A negative response will abort the file
+operation.
+
+`\-link' preserves the source folder copy of the message
+(i.e., it does a \fIln\fR(1) rather than a \fImv\fR(1)), whereas,
+`\-nolink' deletes the ``filed'' messages from the source
+folder.
+Normally, when a message is filed, it is assigned the
+next highest number available in each of the destination folders.
+Use of the `\-preserve' switch will override this message
+``renaming'', but name conflicts may occur, so
+use this switch cautiously.
+(See \fIpick\fR for more details on
+message numbering.)
+
+If `\-link' is not specified (or `\-nolink' is specified),
+the filed messages will be removed (unlink(2)) from the
+source folder.
+.SH IMPORTANT NOTE
+"File" already exists in many Unix systems as a program to check
+the type of a file.  If the Rand MH system has been installed,
+that program will have been renamed to
+.I filetype(1).
+.SH FILES
+.ta 2.4i
+$HOME/\*.mh\(ruprofile The user profile
+.SH PROFILE COMPONENTS
+.br
+Path:  To determine the user's MH directory
+.br
+Current-Folder:        To find the default current folder
+.br
+Folder\-Protect:       To set mode when creating a new folder
+.SH SEE ALSO
+show(1), folder(1)
+.SH DEFAULTS
+`\-src +folder' defaults to the current folder
+.br
+`msgs' defaults to cur
+.br
+`\-nolink'
+.br
+`\-nopreserve'
+.br
+`\-nofile'
+.SH CONTEXT
+If `\-src +folder' is given, it will become the
+current folder for future MH commands.
+If neither `\-link' nor
+`all' are specified, the current message in the source
+folder will be set to the last message specified; otherwise, the
+current message won't be changed.
diff --git a/docs/historical/mh-jun-1982/man/folder.1 b/docs/historical/mh-jun-1982/man/folder.1
new file mode 100644 (file)
index 0000000..12d0f52
--- /dev/null
@@ -0,0 +1,104 @@
+.TH FOLDER 1 RAND
+.SH NAME
+folder, folders \- set/list current folder/message
+.SH SYNOPSIS
+\fBfolder\fR \%[+folder] \%[msg] \%[\fB\-all\fR]
+\%[\fB\-fast\fR] \%[\fB\-nofast\fR] \%[\fB\-up\fR] \%[\fB\-down\fR]
+\%[\fB\-header\fR] \%[\fB\-noheader\fR] \%[\fB\-total\fR]
+\%[\fB\-nototal\fR] \%[\fB\-pack\fR] \%[\fB\-nopack\fR]
+\%[\fB\-help\fR]
+.br
+\fBfolders\fR
+.SH DESCRIPTION
+Since the MH environment is the shell, it is easy to lose
+track of the current folder from day to day.
+\fIFolder\fR will
+list the current folder, the number of messages in it, the
+range of the messages (low-high), and the current message within
+the folder, and will flag a selection list or extra files if they
+exist.
+An example of the output is:
+
+      inbox+ has 16 messages ( 3\- 22); cur= 5.
+
+If a `+folder' and/or `msg' are specified, they will
+become the current folder and/or message.
+An `\-all' switch
+will produce a line for each folder in the user's MH directory,
+sorted alphabetically.
+These folders are preceded by the read-only
+folders, which occur as \*.mh\(ruprofile ``cur\-'' entries.
+For example,
+
+.nf
+.ta .5i 2.5i 3.6i 
+           Folder\ \   #\ of\ messages (\ range\ );\ cur msg (other files)
+   /fsd/rs/m/tacc\ \ has       35\ messages    (1\-\035);\ cur=\ 23.
+/rnd/phyl/Mail/EP\ \ has       82\ messages    (       1\-108);\ cur=\ 82.
+               ff\ \ has       4\ messages     (1\-\0\04);\ cur=\ \01.
+            inbox+\ has        16\ messages    (3\-\022);\ cur=\ \05.
+               mh\ \ has       76\ messages    (1\-\076);\ cur=\ 70.
+            notes\ \ has       2\ messages     (1\-\0\02);\ cur=\ \01.
+             ucom\ \ has       124\ messages   (1\-124);\ cur=\ \06; (select).
+
+       TOTAL=\0339\ messages\0in\0\07\0Folders.
+.re
+.fi
+
+The ``+'' after inbox indicates that it is the current folder.
+The ``(select)'' indicates that the folder ucom has a selection
+list produced by \fIpick\fR.
+If ``others'' had appeared in parentheses at
+the right of a line, it would indicate that there are files in
+the folder directory that don't belong under the MH file naming
+scheme.
+
+The header is output if either an `\-all' or a `\-header' switch
+is specified; it is suppressed by `\-noheader'.
+Also, if \fIfolder\fR
+is invoked by a name ending with ``s'' (e.g., \fIfolders\fR),
+`\-all' is assumed.
+A `\-total' switch will produce only the
+summary line.
+
+If `\-fast' is given, only the folder name (or names in the
+case of `\-all') will be listed.
+(This is faster because the
+folders need not be read.)
+
+The switches `\-up' and `\-down' change the folder to be the
+one above or below the current folder.
+That is, ``folder \-down''
+will set the folder to ``<current\-folder>/select'', and if the
+current folder is a selection-list folder, ``folder \-up'' will
+set the current folder to the parent of the selection-list.
+(See \fIpick(1)\fR for details on selection-lists.)
+
+The `\-pack' switch will compress the message names in a folder, removing
+holes in message numbering.
+.SH FILES
+.ta 2.4i
+$HOME/\*.mh\(ruprofile The user profile
+.br
+/bin/ls        To fast-list the folders
+.SH PROFILE COMPONENTS
+Path:  To determine the user's MH directory
+.br
+Current-Folder:        To find the default current folder
+.SH SEE ALSO
+pick(1)
+.SH DEFAULTS
+`+folder' defaults to the current folder
+.br
+`msg' defaults to none
+.br
+`\-nofast'
+.br
+`\-noheader'
+.br
+`\-nototal'
+.br
+`\-nopack'
+.SH CONTEXT
+If `+folder' and/or `msg' are given, they will become the
+current folder and/or message.
diff --git a/docs/historical/mh-jun-1982/man/folders.1 b/docs/historical/mh-jun-1982/man/folders.1
new file mode 100644 (file)
index 0000000..4c13cc9
--- /dev/null
@@ -0,0 +1 @@
+.so /usr/man/man1/folder.1
diff --git a/docs/historical/mh-jun-1982/man/forw.1 b/docs/historical/mh-jun-1982/man/forw.1
new file mode 100644 (file)
index 0000000..c228fc0
--- /dev/null
@@ -0,0 +1,77 @@
+.TH FORW 1 RAND
+.SH NAME
+forw \- forward messages
+.SH SYNOPSIS
+forw \%[+folder] \%[msgs] \%[\-editor\ editor] \%[\-form\ formfile]
+\%[\-annotate] \%[\-noannotate]
+\%[\-inplace]  \%[\-noinplace]
+\%[\-help]
+.SH DESCRIPTION
+\fIForw\fR may be used to prepare a message containing other
+messages.
+It constructs the new message from the components file
+or `\-form formfile' (see \fIcomp\fR), with a body composed of the
+message(s) to be forwarded.
+An editor is invoked as in \fIcomp\fR,
+and after editing is complete, the user is prompted before the message
+is sent.
+
+If the `\-annotate' switch is given, each message being
+forwarded will be annotated with the lines
+
+     Forwarded: \*(<<date\*(>>
+     Forwarded: To: names
+     Forwarded: cc: names
+
+where each \*(lqTo:\*(rq and \*(lqcc:\*(rq list contains as many lines as required.
+This annotation will be done only if the message is sent directly
+from \fIforw\fR.
+If the message is not sent immediately from \fIforw\fR,
+\*(lqcomp \-use\*(rq may be used in a later session to re-edit and send
+the constructed message, but the annotations won't take place.
+The `\-inplace' switch permits annotating a message in place in
+order to preserve its links.
+
+See \fIcomp(1)\fR for a description of the `\-editor' switch and for options
+upon exiting from the editor.
+See \fImh-profile(5)\fR for further information
+about the how editors are used by MH.
+.SH FILES
+.ta 2.4i
+/etc/mh/components     The message skeleton
+.br
+or <mh-dir>/components Rather than the standard skeleton
+.br
+$HOME/\*.mh\(ruprofile The user profile
+.br
+<mh-dir>/draft The default message file
+.br
+/usr/bin/send  To send the composed message
+.SH PROFILE COMPONENTS
+Path:  To determine the user's MH directory
+.Ps
+.br
+Editor:        To override the default editor
+.Ps
+.br
+Current-Folder:        To find the default current folder
+.Ps
+.br
+<lasteditor>\-next:    To name an editor to be used 
+                       after exit from <lasteditor>
+.SH SEE ALSO
+dist(1), send(1)
+.SH DEFAULTS
+`+folder' defaults to the current folder
+.br
+`msgs' defaults to cur
+.br
+`\-editor' defaults to /bin/ned
+.br
+`\-noannotate'
+.br
+`\-noinplace'
+.SH CONTEXT
+If a +folder is specified, it will become
+the current folder, and the current message will be set to
+the first message being forward
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/man/inc.1 b/docs/historical/mh-jun-1982/man/inc.1
new file mode 100644 (file)
index 0000000..435a627
--- /dev/null
@@ -0,0 +1,100 @@
+.TH INC 1 RAND
+.SH NAME
+inc \- incorporate new mail
+.SH SYNOPSIS
+\fBinc\fR \%[+folder] \%[\fB\-audit\ \fRaudit-file] \%[\fB\-help\fR]
+\%[\fB\-changecur\fR] \%[\fB\-nochangecur\fR]
+ \%[\-time] \%[\-notime] \%[\-numdate] \%[\-nonumdate]
+.SH DESCRIPTION
+\fIInc\fR incorporates mail from the user's incoming mail drop
+into an MH folder.
+If `+folder' isn't specified,
+the folder named ``inbox'' in the user's MH directory will be used.
+The
+new messages being incorporated are assigned numbers starting
+with the next highest number in the folder.
+If the specified (or
+default) folder doesn't exist, the user will be queried prior to
+its creation.
+As the messages are processed, a \fIscan\fR  listing
+of the new mail is produced.
+
+If the user's profile contains a ``Msg\-Protect: nnn'' entry, it
+will be used as the protection on the newly created messages,
+otherwise the MH default of 664 will be used.
+During all
+operations on messages, this initially assigned protection will
+be preserved for each message, so \fIchmod\fR(I) may be used to set a
+protection on an individual message, and its protection will be
+preserved thereafter.
+
+If the switch `\-audit audit-file' is specified (usually as a
+default switch in the profile), then \fIinc\fR will append a header
+line and a line per message to the end of the specified
+audit-file with the format:
+
+.nf
+.ti 1i
+\*(<<inc\*(>> date
+.ti 1.5i
+<scan line for first message>
+.ti 1.5i
+<scan line for second message>
+.ti 2.5i
+<etc.>
+.fi
+
+This is useful for keeping track of volume and source of incoming
+mail.
+Eventually, \fIrepl\fR, \fIforw\fR, \fIcomp\fR, and \fIdist\fR may also
+produce audits to this (or another) file, perhaps with
+``Message-Id:'' information to keep an exact correspondence history.
+``Audit-file'' will be in the user's MH directory unless a full
+path is specified.
+
+\fIInc\fR will incorporate even illegally formatted messages into the
+user's MH folder, inserting a blank line prior to the offending
+component and printing a comment identifying the bad message.
+
+In all cases, the \*.mail file will be zeroed.
+
+If the `\-time' switch is selected, the time of the message is shown
+after the date in the scan lines.
+If the `\-numdate' switch is selected,
+the date (and time if `\-time' is selected) of the message
+is shown in the scan lines as one long number
+made up of year, month, day, hour, minute.
+.SH FILES
+.ta 2.4i
+$HOME/\*.mh\(ruprofile The user profile
+.br
+/usr/spool/mail/*      The user's mail drop
+.br
+<mh-dir>/audit-file    Audit trace file (optional)
+.SH PROFILE COMPONENTS
+Path:  To determine the user's MH directory
+.br
+Folder\-Protect:       For protection on new folders
+.br
+Msg\-Protect:  For protection on new messages
+.SH SEE ALSO
+deliver(8), mh-mail(5), scan(1), mail(1)
+.SH DEFAULTS
+`+folder' defaults to ``inbox''
+.br
+`-changecur'
+.br
+`\-notime'
+.br
+`\-nonumdate'
+.SH CONTEXT
+The folder into which the message is
+being incorporated will become the
+current folder, and the first message incorporated will be the
+current message unless the
+.B \-nochangecur
+option is specified.
+This leaves the context ready for a \fIshow\fR
+of the first new message.
+.SH BUGS
+The `\-numdate' option ignores tim
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/man/mail.1 b/docs/historical/mh-jun-1982/man/mail.1
new file mode 100644 (file)
index 0000000..cb224aa
--- /dev/null
@@ -0,0 +1,48 @@
+
+.TH MAIL 1 RAND
+.SH NAME
+mail \- send or read mail
+.SH SYNOPSIS
+.B mail
+[[\fB\-subject\fR\ subject] [\fB\-cc\ \fRname ...] [\fB\-help\fR] user ...]
+.SH DESCRIPTION
+.I Mail
+is intended as a replacement for the standard Bell mail program
+(\fIbellmail(1)\fR), compatible with the Rand message-handling
+system, mh.  When invoked without arguments, it simply 
+execs 
+.I inc(1) 
+to incorporate new messages from the user's maildrop.
+When one or more users is specified, a message is read from
+the standard input and spooled to a temporary file.
+.I Mail
+then invokes
+.I deliver(8) 
+with the name of the temporary file as
+its argument to deliver the message to the specified user.
+.PP
+The
+.B subject
+and
+.B cc
+switches can be used to insert the corresponding header components into
+the message to be delivered.
+.PP
+This program is intended for the use of programs 
+such as
+.I at(1),
+which expect
+to automatically send mail to various users.
+Normally, real people will prefer to use 
+.I comp(1) 
+and
+.I send(1) 
+to send messages.
+.SH FILES
+/etc/mh/deliver
+.br
+/tmp/mail*.tmp
+.br
+/usr/tmp/mh/lst*.tmp
+.SH SEE ALSO
+bellmail(1), rmail(1), send(1), inc(1), deliver(8)
diff --git a/docs/historical/mh-jun-1982/man/mailer.8 b/docs/historical/mh-jun-1982/man/mailer.8
new file mode 100644 (file)
index 0000000..f06d617
--- /dev/null
@@ -0,0 +1,69 @@
+.TH MAILER 8 RAND
+.SH NAME
+mailer \- Send Arpanet mail
+.SH SYNOPSIS
+.B /etc/mailer 
+[
+.B \-l
+] [
+.B \-v
+] [file ...]
+.SH DESCRIPTION
+.I Mailer
+is a program to send messages to remote Arpanet sites.  If one or more
+.I file\fRs
+are specified, 
+.I mailer 
+will process 
+those files as its only task.  If no
+.I file
+is specified, 
+.I mailer 
+will attempt to process all files in the queue directory,
+/usr/spool/netmail.
+.PP
+The
+.B \-l
+flag causes output to be placed on standard output suitable
+for a log.
+.PP
+The
+.B \-v
+flag causes output to be placed on the standard output suitable
+for a user (as in the \-v option of
+.I deliver(8).
+The two flags should not be used together.
+.PP
+The format of message files is described in
+.I netmail(5).
+It should be noted that control lines for all of the recipients
+of a single message are maintained at the beginning of the file.
+Due to transient Arpanet failures, it is possible for some or
+all of the recipient lines to be marked as 
+being in an as-yet-undelivered state.  
+When all of the recipients have either accepted or rejected
+the message, it is removed.
+If a message has still not been disposed of after five days,
+it is considered undeliverable.
+.PP
+Messages may also become undeliverable for a number of other reasons,
+such as a "no such user" message from the foreign site.  In any case,
+if a message is undeliverable, it is returned to the sender
+via 
+.I mail(1)
+with a note prepended to explain the problem.  Clearly, more than
+one such returned message may result from a single message file
+with multiple recipients.
+.PP
+.I Mailer
+should be invoked periodically by 
+.I cron(8).
+Ten-minute intervals are not unreasonable.
+.SH FILES
+/usr/spool/netmail
+.br
+/dev/imp*
+.br
+/etc/hosttable
+.SH SEE ALSO
+deliver(8),netmail(5),mail(1),imp(4)
diff --git a/docs/historical/mh-jun-1982/man/mh-alias.5 b/docs/historical/mh-jun-1982/man/mh-alias.5
new file mode 100644 (file)
index 0000000..d1e257b
--- /dev/null
@@ -0,0 +1,89 @@
+.TH MH-ALIAS 5 RAND
+.SH NAME
+mh-alias \- alias file for mh message system
+.SH DESCRIPTION
+The Alias file for mail delivery is the file
+
+       /etc/MailAliases
+
+Each line of the alias file has the format:
+
+match : alias
+
+Where:
+
+       alias       :=  simple-list
+.br
+                   |   "<" alias-file
+.br
+                   |   "=" UNIX-group
+.br
+                   |   "*"
+
+.br
+       simple-list :=  simple-name
+.br
+                   |   simple-list, simple-name
+
+.PP
+Alias-file is a fully qualified UNIX file name.  UNIX-group is a
+group name from /etc/group.  A simple-name is a local user login
+name, including only alphanumerics, `.' and `\-'.  Throughout this
+file, case is ignored, except for alias-file names.
+.PP
+In match, a trailing * on a name will match anything. (See example
+below.)
+.PP
+The procedure for mail aliasing is:
+.br
+.HP 3
+1) Build a list of all addresses from the message to be
+delivered, eliminating duplicates.
+.br
+.HP 3
+2) For each line in the alias file, compare "match" against all
+of the existing addresses.  If a match, remove the matched
+name from the address list, and add each new alias name to the
+address list if it is not already on the list.
+.PP
+Since the alias file is read line by line, forward references
+work, but backward references are not recognized, thus, there is
+no recursion.
+.PP
+\fBExample:\fR
+.br
+       Borden: bruce
+.br
+       Bruce: bsb
+.br
+       Wahrman: mike
+.br
+       ASRL: bsb, mike, obrien, giarla
+.br
+       UNIX-committee: < /usr/people/unix-committee
+.br
+       System: = sys
+.br
+       Everyone: *
+.br
+       news.*: news
+          ...
+.PP
+In the "unix-committee" example, the file "/usr/people/unix-
+committee" contains one simple-name, or a list of comma separated
+simple-names.  A new-line will be treated as a blank in this
+file, s.a.
+.br
+       foo, fie,
+.br
+       fum, fiddle
+.PP
+In the "system" case, the names from the group "sys" will be used
+as the expanded name list.
+.PP
+In the "news.*" case, all names of the form "news.<anything>" will
+be mapped to "news".  This is used for the MH news facility.
+.SH FILES
+/etc/MailAliases
+.SH SEE ALSO
+deliver(8),group(5),ali(1),
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/man/mh-mail.5 b/docs/historical/mh-jun-1982/man/mh-mail.5
new file mode 100644 (file)
index 0000000..a3ec070
--- /dev/null
@@ -0,0 +1,193 @@
+.TH MH-MAIL 5 RAND
+.SH NAME
+mh-mail \- Message format for MH
+.SH DESCRIPTION
+.I MH,
+the Rand message-handling system, processes messages in
+a particular format.  It should be noted that neither
+the Berkeley mailer nor the Bell mail program produces
+message files in precisely the correct format for 
+.I mh.
+.PP
+Each user possesses a mail drop box which initially receives
+all messages processed by
+.I deliver(8).
+.I Inc(1)
+will read from that drop box and incorporate the new messages
+found there into the user's own mail folders.   The mail drop
+box consists of one or more messages.  To facilitate the
+separation of messages, each message begins and ends with
+a line consisting of nothing but four Control-A (octal 001)
+characters.
+.PP
+Each message consists of two parts: a header, consisting of
+one or more header lines, and a body, containing the actual
+text of the message.  These parts are separated by an empty
+line, i.e. two consecutive Newline characters.
+Within MH, the header and body may be separated by a line
+consisting of dashes.
+.PP
+Each header item can be viewed as a single logical line of ASCII
+characters.
+If the text of a header item extends across several
+real lines, the continuation lines are indicated by leading
+spaces or tabs.
+.PP
+Each header item is called a component and is composed of a
+keyword or name, along with associated text.
+The keyword begins at the
+left margin, may contain spaces or tabs, may not exceed 63
+characters, and is terminated by a colon (:).
+Certain
+components (as identified by their keywords) must follow rigidly
+defined formats in their text portions.
+.PP
+The text for most formatted components (e.g., ``Date:'' and ``Message-Id:'')
+is produced automatically.
+The only ones entered by the
+user are address fields such as ``To:'', ``cc:'', etc.
+ARPA addresses
+are assigned mailbox names and host computer specifications.
+The
+rough format is ``mailbox at host'', such as ``Borden at Rand-Unix''.
+Multiple addresses are separated by commas.
+A missing host is
+assumed to be the local host.
+.PP 
+Following is a list of header components that are considered
+meaningful to various MH programs.
+.TP 15
+.I Component
+.I Usage
+.br
+.TP
+Date:
+Added by
+.I deliver(8),
+contains date and time of delivery.
+.br
+.ns
+.TP
+From:
+Added by
+.I deliver(8),
+contains the userid of the sender.  But see "Sender:"
+.br
+.ns
+.TP
+Sender:
+Added by
+.I deliver(8)
+in the event that the user has supplied a "From:" line,
+contains the userid of the sender.
+.br
+.ns
+.TP
+To:
+Contains address of recipient of message.
+.br
+.ns
+.TP
+cc:
+Contains addresses of additional recipients.
+.br
+.ns
+.TP
+Bcc:
+Still more recipients.  However, the Bcc line is not
+copied onto the message as delivered, so these recipients
+are not listed.
+.br
+.ns
+.TP
+fcc:
+Causes
+.I deliver(8)
+to copy the message into the specified folder.
+.br
+.ns
+.TP
+Subject:
+Sender's commentary.  It is displayed by
+.I scan(1).
+.br
+.ns
+.TP
+Message-ID:
+A unique message identifier glued on by 
+.I deliver
+if the
+.B \-msgid
+flag is set.
+.br
+.ns
+.TP
+In-Reply-To:
+A commentary line added by 
+.I repl(1)
+when replying to a message.
+.br
+.ns
+.TP
+Replied:
+Reply date added by
+.I repl(1)
+under the "annotate" option.
+.br
+.ns
+.TP
+Forwarded:
+Forwarding date added by
+.I forw(1)
+under the "annotate" option.
+.br
+.ns
+.TP
+Distribute-to:
+New recipients for a redistributed message processed
+by
+.I dist(1).
+.br
+.ns
+.TP
+Distribute-cc:
+Still more recipients.  See "cc:".
+.br
+.ns
+.TP
+Distribute-bcc:
+Even more recipients.  See "bcc:.
+.br
+.ns
+.TP
+Distribute-fcc:
+Copy distributed message into a folder.  See "fcc:".
+.br
+.ns
+.TP
+Distribute-from:
+Added when redistributing a message.
+.br
+.ns
+.TP
+Distribution-date:
+Is to distribute-from as Date: is to From:.
+.br
+.ns
+.TP
+Distribution-id:
+Added if msgid option is in effect.
+.br
+.ns
+.TP
+Distributed:
+Annotation for
+.I dist(1)
+.SH FILES
+/usr/spool/mail/*
+.SH SEE ALSO
+\fIThe MH Message Handling System: User's Manual\fR
+by B. Borden, R. Gaines, and N. Shapiro
+.br
+\fIStandard for the Format of ARPA Network Test Messages\fR
+by D. Crocker, J. Vittal, K. Pogran, and D. Henderson, Jr.
diff --git a/docs/historical/mh-jun-1982/man/mh-profile.5 b/docs/historical/mh-jun-1982/man/mh-profile.5
new file mode 100644 (file)
index 0000000..49a7b54
--- /dev/null
@@ -0,0 +1,113 @@
+.TH MH\(ruPROFILE 5 RAND
+.SH NAME
+mh\(ruprofile \- User parameters for MH message handler
+.SH DESCRIPTION
+Each user of
+.I mh
+is expected to have a file named
+.B .mh\(ruprofile
+in his or her home directory.  This file contains a set of
+user parameters used by some or all of the
+.I mh
+family of programs.  Each line of the file is of the format
+.TP 15
+\fIprofile-component\fR: \fIvalue\fR
+The currently defined profile components are exemplified below:
+.TP
+Path: Mail
+Locates mh transactions in directory "Mail".
+.TP
+Current-Folder: inbox
+Keeps track of currently open folder.
+.TP
+Editor: /bin/e
+Defines editor to be used by 
+.I comp(1),
+.I repl(1),
+.I forw(1),
+and
+.I dist(1).
+.br
+.B NOTE:
+.I repl(1)
+invokes the editor with two file arguments.
+The second is intended
+to be used as an `alternate' file.
+If the editor used doesn't have this feature, it must
+ignore the extra file argument and edit the first
+file argument.
+.TP
+Msg\-Protect: 644
+Defines octal protection bits for message files.  See 
+.I chmod(1)
+for an explanation of the octal number.
+.TP
+Folder\-Protect: 711
+Defines protection bits for folder directories.
+.TP
+\fIprogram\fR: default switches
+Sets default switches to be used whenever the mh program
+.I program
+is invoked.  For example, one could override the 
+       .I Editor:
+profile component when replying to messages by adding a
+component such as:
+.br
+       repl: -editor /bin/ed
+.TP
+cur\-\fIread-onlyfolder\fR: 172
+Keeps track of the last message seen in the specified read-only
+folder.  In folders to which write access is permitted, the
+current-message value is kept in a file called "cur" within
+that folder.
+.TP
+news\-\fInews-topic\fR: 12
+Keeps track of the last message seen in the specified news topic.
+.TP
+News\-Topics: news topics
+Sets the news topics to be selected by default for the news program.
+.TP
+prompter\-next: ed
+Names the editor to be used on exit from
+.I prompter(1)
+.PP
+The following profile elements are used whenever an mh program
+invokes some other program such as
+.I file(1)
+or
+.I ls(1).
+The mh profile can be used to select alternate versions of these
+programs if the user wishes.  The default values are given in
+the examples.
+.br
+       fileproc: /usr/ucb/file
+.br
+       installproc: /etc/mh/install-mh
+.br
+       lproc: /usr/ucb/c
+.br
+       lsproc: /usr/ucb/ls
+.br
+       mailproc: /usr/ucb/mail
+.br
+       prproc: /bin/pr
+.br
+       scanproc: /usr/ucb/scan
+.br
+       sendproc: /usr/ucb/send
+.br
+       showproc: /usr/ucb/c
+.TP
+       delete-prog: /bin/rm
+Normally, 
+.I rmm(1),
+rather than removing a message in file X will rename the
+file to ,X.  At Rand, a program known as the Midnight Skulker
+comes around once a day and eliminates files whose names begin
+with a comma.  If a user provides a 
+.I delete-prog
+profile entry, however, the specified program will be used
+instead to remove the file.
+.SH FILES
+$HOME/.mh\(ruprofile
+.SH SEE ALS
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/man/mh.1 b/docs/historical/mh-jun-1982/man/mh.1
new file mode 100644 (file)
index 0000000..24fcfa4
--- /dev/null
@@ -0,0 +1,54 @@
+.TH MH 1 RAND
+.SH NAME
+mh \- Rand Message Handler
+.SH DESCRIPTION
+.I MH
+is the name of the Rand Message Handling system.
+Rather then being a single comprehensive program,
+.I MH
+consists of a collection of fairly simple 
+single-purpose programs to send, receive, save, 
+and retrieve messages.  The user should refer
+to the MH User's Manual and the pages for the
+.I MH
+programs in the Unix Programmers Manual.
+.SH SEE ALSO
+\fIThe MH Message Handling System: User's Manual\fR
+by B. Borden, R. Gaines, and N. Shapiro.
+Note: the online man pages supercede those in the
+current version of the MH User's Manual just cited.
+.br
+.nf
+.ta 1.5i
+ali (1)        - list mail aliases
+comp (1)       - compose a message 
+dist (1)       - redistribute a message to additional addresses
+file (1)       - file message(s)       in (an)other folder(s)
+folder (1)     - set/list current folder/message
+folders (1)    - list all folders
+forw (1)       - forward messages
+inc (1)        - incorporate new mail
+mail (1)       - send and receive mail
+mhl (1)        - produce formatted listings of MH messages
+mhpath (1)     - print full pathnames of MH messages and folders
+news (1)       - show news
+next (1)       - show the next message
+pick (1)       - select messages by content
+prev (1)       - show the previous message
+prompter (1)   - prompting editor front end
+repl (1)       - reply to a message
+rmail (1)      - send mail from a remote site
+rmf (1)        - remove folder
+rmm (1)        - remove messages
+scan (1)       - produce a one-line-per-message scan listing
+send (1)       - send a message
+show (1)       - show (list)   messages
+.br
+mh-alias (5)   - alias file for mh message system
+mh-mail (5)    - Message format for MH
+mh-profile (5) - User parameters for MH message handler
+netmail (5)    - Arpanet mail queue
+.br
+conflict (8)   - Search for alias/password conflicts
+deliver (8)    - deliver a message
+mailer (8)     - Send Arpanet mail
diff --git a/docs/historical/mh-jun-1982/man/mhl.1 b/docs/historical/mh-jun-1982/man/mhl.1
new file mode 100644 (file)
index 0000000..0da2459
--- /dev/null
@@ -0,0 +1,184 @@
+.TH MHL 1 RAND(DRAFT)
+.SH NAME
+mhl \- Produce formatted listings of MH messages
+.SH SYNOPSIS
+\fBmhl 
+[
+\fB\-clear\fR]
+[\fB\-noclear\fR]
+[\fB\-folder\fR\ folder]
+[\fB\-form\fR\ formfile]
+[\fB\-length\fR\ length] 
+[\fB\-width\fR\ width] 
+[\fB\-help\fR] 
+[file ...]
+.SH DESCRIPTION
+.I Mhl 
+is a formatted message listing program. It can be used as a
+replacement for "c" (the default message lister). As with c, each of
+the messages specified as arguments (or stdin) will be output.  If more
+than one message file is specified, the user will be prompted prior to
+each one, and a <return> or <eot> will begin the output, with <return>
+clearing the screen (if appropriate), and <eot> suppressing the screen
+clear.  An <interrupt> will abort the current message ouput, prompting
+for the next message (if there is one), and a <quit> will terminate the
+program (without core dump).
+.PP
+As in all MH programs, mhl looks for a line "mhl: args" in the user's
+profile, and thus allows tailored defaults.  The switches are:
+.PP
+.ta 1.5i
+.br
+\-clear        Clear screen each page
+.br
+\-noclear      Don't clear screen each page
+.br
+\-folder folder        Use this "folder" name
+.br
+\-form formfile        Name of the format file
+.br
+\-length length        Screen length
+.br
+\-width width  Screen width
+.br
+\-help Standard help message
+.PP
+All of the functions these switches perform are affected or controlled
+by information elsewhere.  That is, the format file can specify "clear",
+in which case, the command line switches will override.  Also, the
+length and width can be specified in the format file, or default to
+40x80.  The folder is used in constructing a message name (see special
+component "MessageName" below).  If it is not specified in a switch, it
+is taken from the environment variable "mhfolder", which show, next,
+prev, and pick initialize appropriately.
+.PP
+If the form file is not specified, it is taken from the file
+"mhl.format" in the user's MH directory, and if that file doesn't exist,
+it is taken from "/etc/mh/mhl.format". (Same evaluation hierarchy as the
+compose form file.)
+.PP
+Mhl operates in two phases: 1) read and parse the format file, and 2)
+process each message (file).  During phase 1, an internal description of
+the format is produced as a structured list.  In phase 2, this list is
+walked for each message, outputing message information under the format
+constraints from the format file.
+.PP
+The "mhl.format" file contains information controlling screen clearing,
+screen size, wraparound control, transparent text, component ordering,
+and component formatting.  Also, a list of components to ignore may be
+specified, and a couple of "special" components are defined  to  provide
+added  functionality.  Message  output will be in the order specified by
+the order in the format file.
+.PP
+Each line of mhl.format has one of the formats:
+.PP
+       ;comment
+.br
+       :cleartext
+.br
+       variable[,variable...]
+.br
+       component:[variable,...]
+.PP
+A line beginning with a ";"  is  a  comment,  and  is  ignored.  A  line
+beginning with a ":" is clear text, and is output exactly as is. (A line
+containing only a ":" produces a blank  line  in  the  output.)  A  line
+beginning  with  "component:"  defines  the  format  for  the  specified
+component, and finally, remaining lines define the global environment.
+.PP
+For example, the line:
+.PP
+width=80,length=40,clearscreen,overflowtext=***,overflowoffset=5
+.PP
+defines the screen size to be 80 columns by 40 rows, specifies that  the
+screen  should  be  cleared  prior  to  each  page,  that  the  overflow
+indentation is 5, and that overflow text should be flagged with "***".
+.PP
+Following are all of the current  variables  and  their  argmuments.  If
+they  follow  a component, they apply only to that component, otherwise,
+their affect is global.  Since the whole format  is  parsed  before  any
+output processing, the last global switch setting for a variable applies
+to the whole message.
+.TP 15
+width=#         
+Screen width, component width
+.TP
+overflowtext=t  
+Text to use at the beginning of an overflow line
+.TP
+overflowoffset=# 
+Positions to indent overflow lines
+.TP
+compwidth=#     
+Positions to indent component text after first line
+.TP
+nocomponent     
+Don't output "component: " for this component
+.TP
+uppercase       
+Output text of this component in all upper case
+.TP
+center          
+Center component on line (works for one-line components only)
+.TP
+clearscreen     
+Clear the screen (form feed) prior to each page
+.TP
+leftadjust      
+Strip off leading spaces & tabs on each line of text
+.TP
+compress        
+Change newlines in text to spaces
+.PP
+Where "=#" indicates a number must be specified, and "=t" indicates that
+arbitrary  text  up  to  end  of line or "," is required.  The variables
+without arguments are ON indicators, with the default in all cases  OFF.
+The  variables  "nocomponent",  center,  leftadjust and compress have no
+affect globally, and clearscreen only affects the global environment.
+.PP
+A line of the form:
+.PP
+ignores=component,...
+.PP
+specifies a list of components which are never output.
+.PP
+The component "MessageName" (case is unimportant) will output the actual
+message  name  (file  name) preceded by "folder:" if one is specified or
+found in the environment.
+.PP
+The component "Extras" will output all of the components of the  message
+which were not matched by explicit components, or included in the ignore
+list.  If this component is not specified, an ignore list is not  needed
+since all non-specified components will be ignored.
+.PP
+If "nocomponent" is NOT specified, then the component name will be output
+as it appears in the format file.
+.PP
+The current default format is:
+.PP
+width=80,length=40,overflowtext=***,overflowoffset=5
+.br
+ignores=msgid,message-id
+.br
+Date:leftadjust,offset=40
+.br
+To:leftadjust
+.br
+Cc:leftadjust
+.br
+:
+.br
+From:leftadjust
+.br
+Subject:leftadjust
+.br
+:
+.br
+extras:leftadjust,nocomponent
+.br
+:
+.br
+body:nocomponent
+.SH FILES
+.SH SEE ALSO
+c(1),
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/man/mhpath.1 b/docs/historical/mh-jun-1982/man/mhpath.1
new file mode 100644 (file)
index 0000000..741c396
--- /dev/null
@@ -0,0 +1,116 @@
+.TH MHPATH 1 RAND
+.SH NAME
+mhpath \- print full pathnames of MH messages and folders
+.SH SYNOPSIS
+mhpath \%[+folder] \%[msgs] \%[\-help]
+.SH DESCRIPTION
+\fIMhpath\fR expands and sorts the message list \%[msgs] and writes
+the full pathnames of the messages to the standard output
+separated by newlines.
+
+If no ``msgs'' are specified, \fImhpath\fR outputs the folder (directory)
+pathname (current folder default).
+
+Contrasted with other MH commands, a message argument to \fImhpath\fR
+may often be intended for \fIwriting\fR.
+Because of this: 1) the name
+"new" has been added to \fImhpath\fR's list of reserved message names
+(the others are first, last, prev, next, cur, all).
+New is last + 1 (where last is 0 in a messageless folder).
+New may not be used as part of a message range.
+2) Within a message list,
+the following designations may refer to messages that do not exist:
+a single numeric message name,
+the single message name cur, and (obviously) the single message name new.
+All other message designations must refer to at least one existing message.
+3) An empty folder is not in itself an error.
+
+Message numbers greater than 999 as part of a range designation
+are replaced with 999.  Explicit single message numbers greater
+than 999, or message number 0 in any context, are errors.
+
+Examples: The current folder foo contains messages 3 5 6.
+Cur is 4.
+.nf
+\    % mhpath
+\    /r/phyl/Mail/foo
+
+\    % mhpath all
+\    /r/phyl/Mail/foo/3
+\    /r/phyl/Mail/foo/5
+\    /r/phyl/Mail/foo/6
+
+\    % mhpath 1000
+\    Message 1000 out of range 1-999
+
+\    % mhpath 1-1001
+\    /r/phyl/Mail/foo/3
+\    /r/phyl/Mail/foo/5
+\    /r/phyl/Mail/foo/6
+
+\    % mhpath new
+\    /r/phyl/Mail/foo/7
+
+\    % mhpath last new
+\    /r/phyl/Mail/foo/6
+\    /r/phyl/Mail/foo/7
+
+\    % mhpath last-new
+\    Bad message list "last-new".
+
+\    % mhpath cur
+\    /r/phyl/Mail/foo/4
+
+\    % mhpath 1-2
+\    No messages in range "1-2".
+
+\    % mhpath first:2
+\    /r/phyl/Mail/foo/3
+\    /r/phyl/Mail/foo/5
+
+\    % mhpath 1 2
+\    /r/phyl/Mail/foo/1
+\    /r/phyl/Mail/foo/2
+
+\    % mhpath 0
+\    Bad message list "0".
+
+\    % mhpath 0-last
+\    Bad message list "0-last".
+
+\    --Backquoted Operations--
+
+\    % cd `mhpath +inbox`
+
+     From "e":
+\    <CMD> run cat `mhpath cur`
+
+.fi
+.SH FILES
+.ta 2.4i
+$HOME/\*.mh\(ruprofile The user profile
+.SH PROFILE COMPONENTS
+Path:  To determine the user's MH directory
+.br
+Current-Folder:        To find the default current folder
+.SH DEFAULTS
+`+folder' defaults to current
+.br
+`msgs' defaults to NULL
+.SH CONTEXT
+The folder and the current message are unaffected.
+.SH BUGS
+Like all MH commands, \fImhpath\fR expands and sorts \%[msgs].
+So don't expect
+.br
+\        mv `mhpath 501 500`
+.br
+to move 501 to 500.
+Quite the reverse.  But
+.br
+\        mv `mhpath 501` `mhpath 500`
+.br
+will do the trick.
+
+Out of range message 0 is treated far more severely than large out of
+range message numbers.
diff --git a/docs/historical/mh-jun-1982/man/netmail.5 b/docs/historical/mh-jun-1982/man/netmail.5
new file mode 100644 (file)
index 0000000..96d4f41
--- /dev/null
@@ -0,0 +1,39 @@
+.TH NETMAIL 5 RAND
+.SH NAME
+netmail \- Arpanet mail queue
+.SH DESCRIPTION
+Each file in /usr/spool/netmail contains a message to be sent to
+one or more sites on the Arpanet.  They are processed by the
+.I mailer(8)
+daemon.
+The format of a message file is as follows:
+The first line has the sender's name, a space, and the date the
+message was sent (in the form returned by 
+.I cdate(3)
+).  Following lines
+represent addresses and have a code character, a host name, a space,
+and a mailbox name.  The code is '/' if this address has not already
+been handled, '|' if it has.  The addresses end with a blank line.
+The remainder of the file is the text of the message.
+.PP
+.B Example:
+.br
+   jones 10-Jul-80@13:13:13
+.br
+   /usc-isif op-nobody
+.br
+   |rand-ai smith
+.br
+
+.br
+   From: Jones at Rand-Unix
+.br
+   To: op-nobody at Usc-Isif, smith at Rand-Ai
+.br
+
+.br
+   This is a test message.
+.SH FILES
+/usr/spool/netmail/*
+.SH SEE ALSO
+mailer(8),deliver(8)
diff --git a/docs/historical/mh-jun-1982/man/news.1 b/docs/historical/mh-jun-1982/man/news.1
new file mode 100644 (file)
index 0000000..5195176
--- /dev/null
@@ -0,0 +1,101 @@
+.TH NEWS 1 RAND
+.SH NAME
+news \- show news
+.SH SYNOPSIS
+\fBnews\fR \%[topic\ ...]
+\%[\fB\-check\fR]
+\%[\fB\-display\fR]
+\%[\fB\-update\fR]
+\%[\fB\-review\fR\ [topic]]
+\%[\fB\-send\ \fRtopic]
+\%[\fB\-topics\fR]
+\%[\fB\-help\fR]
+.SH DESCRIPTION
+.I News
+is an MH program which checks, displays, reviews, or sends news.
+A pseudo-user called `news' acts as an automated
+custodian for news items on various topics.
+These topics are managed as MH folders in the home directory of news.
+Mail sent to `news.everyone', for instance, will get
+filed in the `everyone' news folder.
+.PP
+You can explicitly select the group of news topics you want
+to check or display by specifying them as arguments to the
+.I news
+command.
+If you don't explicitly select topics in this way,
+the topic `everyone' is selected by default.
+Additional default topics can be selected by listing them on a
+\&``News\-Topics:'' line in your MH profile.
+The MH profile line
+must contain a blank-separated list of topics.
+As a special case, the profile line:
+.br
+    \&``News\-Topics:\ *''
+.br
+means you want to keep track of all news.
+.PP
+\&``\fINews \fB\-topics\fR''
+will show you what topics exist and
+the number of messages in each.
+Topics selected are marked with asterisks.
+\&``\fINews \fB\-help\fR''
+is like
+\&``\fInews \fB\-topics\fR''
+except that it also displays the syntax of the
+.I news
+command.
+.PP
+\&``\fINews \fB\-check\fR''
+will report the existence of unread news in the selected topics.
+.I News
+without any option arguments
+will display all unread news items from
+all selected topics.
+\&``\fINews \fB\-display\fR''
+is identical to
+.I news
+without an argument, but it suppresses the
+no news message (useful in login scripts).
+\&``\fINews \fB\-review\fR [#] [topic]''
+will redisplay the last # (default all) items
+in the selected topics.
+.PP
+News stores in your MH profile the message number of the most recent news
+item it has shown you in each topic.
+\&``\fINews \fB\-update\fR''
+will update your MH profile to indicate no
+outstanding news items to be read.
+.PP
+\&``\fINews \fB\-send\fR topic''
+is identical to
+\&``mail news.topic''.
+The mail sent to news.topic is
+automatically filed in a folder with
+name topic.
+.PP
+Any unrecognized switches to
+.I news
+are sent along to
+.IR l (1)
+for displaying items, or to
+.IR mail (1)
+for sending a news item.
+.SH FILES
+.ta 2.4i
+$HOME/.mh\(ruprofile   The user profile
+.br
+~news/<topics> The news folders
+.br
+~news/.<topics>        The number of items in <topics>
+.SH PROFILE COMPONENTS
+News-topics:            Topics the user is interested in.
+.br
+News-<topic>:           Current message in news topics
+.SH SEE ALSO
+mh-mail(5), mh(1)
+.SH DEFAULTS
+The topic `everyone' is the default topic.
+.SH CONTEXT
+The current message in each news folder is maintained in the
+user's mh\(ruprofile.
diff --git a/docs/historical/mh-jun-1982/man/next.1 b/docs/historical/mh-jun-1982/man/next.1
new file mode 100644 (file)
index 0000000..24a91d0
--- /dev/null
@@ -0,0 +1,29 @@
+.TH NEXT 1 RAND
+.SH NAME
+next \- show the next message
+.SH SYNOPSIS
+.B next 
+\%[+folder] \%[\-switches\ for\ \fIshowproc\fR] \%[\-help]
+.SH DESCRIPTION
+\fINext\fR performs a \fIshow\fR on the next message in the
+specified (or current) folder.
+Like \fIshow\fR, it passes any
+switches on to the program \fIshowproc\fR, which is called to list the
+message.
+This command is exactly equivalent to ``show next''.
+.SH FILES
+.ta 2.4i
+$HOME/\*.mh\(ruprofile The user profile
+.SH PROFILE COMPONENTS
+Path:  To determine the user's MH directory
+showproc:      Program called to list the message
+.br
+Current-Folder:        To find the default current folder
+.SH DEFAULTS
+showproc:      /usr/ucb/c
+.SH SEE ALSO
+show(1),prev(1)
+.SH CONTEXT
+If a folder is specified, it will become the current folder, and the
+message that is shown (i.e., the next message in sequence)
+will become the current message.
diff --git a/docs/historical/mh-jun-1982/man/pick.1 b/docs/historical/mh-jun-1982/man/pick.1
new file mode 100644 (file)
index 0000000..5417d32
--- /dev/null
@@ -0,0 +1,188 @@
+.TH PICK 1 RAND
+.SH NAME
+pick \- select messages by content
+.SH SYNOPSIS
+.B pick
+\-hdr-component pattern
+\%[\fB\-src\fR\ +folder] \%[msgs] \%[\fB\-help\fR] 
+\%[\fB\-scan\fR] \%[\fB\-noscan\fR]
+\%[\fB\-show\fR] \%[\fB\-noshow\fR] \%[\fB\-nofile\fR] \%[\fB\-nokeep\fR]
+\%[\fB\-fil\fRe \%[\fB\-preserve\fR] \%[\fB\-link\fR] 
+\%+folder\ ... \%[\fB\-nopreserve\fR] \%[\fB\-nolink\fR] ]
+\%[\fB\-keep\fR \%[\fB\-stay\fR] \%[\fB\-nostay\fR] \%[+folder\ ...]\ ]
+.br
+
+Where 
+.I hdr-component 
+is a member of 
+.br
+       [\fBcc date from to subject search\fR],
+.br
+or
+is of the form \-text
+.PP
+Typically:
+.in 1i
+pick\0\-from\0jones\0\-scan
+.br
+pick\0\-search\0documentation
+.br
+pick\0\-subject\0ned\0\-scan\0\-keep
+.br
+pick\0\--expires\01-jan-85\0-scan
+.SH DESCRIPTION
+\fIPick\fR searches messages within a folder for the specified
+contents, then performs several operations on the selected
+messages.
+
+A modified \fIgrep\fR(1) is used to perform the searching, so the
+full regular expression (see \fIed\fR(1)) facility is available
+within `pattern'.
+With `\-search', 
+.I pattern
+is used directly,
+and with the others, the grep pattern constructed is:
+
+.ti +.5i
+``hdr-component:\*.\*(**pattern''
+
+This means that the pattern specified for a `\-search' will be
+found everywhere in the message, including the header and the body,
+while the other search requests are limited to the single
+specified component.
+The expression `\-\-component pattern'
+is a shorthand for
+specifying `\-search ``component:\*.\*(**pattern''\ '; it is used to pick
+a component not in the set [cc date from subject to].
+An
+example is ``pick \-\-reply\-to pooh \-show''.
+
+Searching is performed on a per-line basis.
+Within the header of
+the message, each component is treated as one long line, but in
+the body, each line is separate.
+Lower-case letters in the
+search pattern will match either lower or upper case in the
+message, while upper case will match only upper case.
+
+Once the search has been performed, the selected messages
+are scanned (see \fIscan(1)\fR) if the `\-scan' switch is given, and
+then they are shown (see \fIshow(1)\fR) if the `\-show' switch is
+given.
+After these two operations, the file operations (if
+requested) are performed.
+
+The `\-file' switch operates exactly like the \fIfile\fR command, with the
+same meaning for the `\-preserve' and `\-link' switches.
+
+The `\-keep' switch is similar to `\-file', but it produces a folder that
+is a subfolder of the folder being searched and defines it as
+the current folder (unless the `\-stay' flag is used).
+This
+subfolder contains the messages which matched the search
+criteria.
+All of the MH commands may be used with the sub-folder
+as the current folder.
+This gives the user considerable power
+in dealing with subsets of messages in a folder.
+
+The messages in a folder produced by `\-keep' will always have the
+same numbers as they have in the source folder (i.e., the
+`\-preserve' switch is automatic).
+This way, the message
+numbers are consistent with the folder from which the messages
+were selected.
+Messages are not removed from the source folder
+(i.e., the `\-link' switch is assumed).
+If a `+folder' is not
+specified, the standard name ``select'' will be used.
+(This is the
+meaning of ``(select)'' when it appears in the output of the
+\fIfolder\fR command.) If `+folder' arguments are given to
+`\-keep', they will be used rather than ``select'' for the names
+of the subfolders.
+This allows for several subfolders to be
+maintained concurrently.
+
+When a `\-keep' is performed, the subfolder becomes the current folder.
+This can be overridden by use
+of the `\-stay' switch.
+
+Here's an example:
+
+.nf
+\01  % folder +inbox
+\02           inbox+ has  16 messages (  3\- 22); cur=  3.
+\03  % pick \-from dcrocker
+\04  6 hits.
+\05  [+inbox/select now current]
+\06  % folder
+\07    inbox/select+ has  \06 messages (  3\- 16); cur=  3.
+\08  % scan
+.ds p \\h'\\w'+'u'
+\09   \03+  6/20   Dcrocker          Re: ned file update issue...
+10   \06\*p  6/23   Dcrocker          removal of files from /tm...
+11   \08\*p  6/27   Dcrocker          Problems with the new ned...
+12   13\*p  6/28   d\h'\w'D'u-\w'd'u'crocker          newest nned  \*(<<I would ap...
+13   15\*p  7/\05   Dcrocker          nned  \*(<<Last week I asked...
+14   16\*p  7/\05   d\h'\w'D'u-\w'd'u'crocker          message id format  \*(<<I re...
+15  % show all | print
+16     [produce a full listing of this set of messages on the line printer.]
+17  % folder \-up
+18            inbox+ has  16 messages (  3\- 22); cur=  3; (select).
+19  % folder \-down
+20   inbox/select+ has   6 messages (  3\- 16); cur=  3.
+21  % rmf
+22  [+inbox now current]
+23  % folder
+24            inbox+ has  16 messages (  3\- 22); cur=  3.
+.fi
+
+This is a rather lengthy example, but it shows the power of the
+MH package.
+In item 1, the current folder is set to inbox.
+In 3,
+all of the messages from dcrocker are found in inbox and linked
+into the folder ``inbox/select''.
+(Since no action switch is
+specified, `\-keep' is assumed.)  Items 6 and 7 show that this
+subfolder is now the current folder.
+Items 8 through 14 are a
+\fIscan\fR of the selected messages (note that they are all from dcrocker
+and are all in upper and lower case).
+Item 15 lists all of the messages to
+the high-speed printer.
+Item 17 directs \fIfolder\fR to set the
+current folder to the parent of the selection-list folder, which
+is now current.
+Item 18 shows that this has been done.
+Item 19 resets
+the current folder to the selection list, and 21 removes the
+selection-list folder and resets the current folder to the
+parent folder, as shown in 22 and 23.
+.SH FILES
+.ta 2.4i
+$HOME/\*.mh\(ruprofile The user profile
+.SH PROFILE COMPONENTS
+Path:  To determine the user's MH directory
+.br
+Folder\-Protect:       For protection on new folders
+.br
+Current-Folder:        To find the default current folder
+.SH SEE ALSO
+scan(1), show(1), folder(1)
+.SH DEFAULTS
+`\-src +folder' defaults to current
+.br
+`msgs' defaults to all
+.br
+`\-keep +select' is the default if no `\-scan', `\-show', or `\-file' is specified
+.SH CONTEXT
+If a `\-src +folder' is specified, it will
+become the current folder, unless a `\-keep' with 0 or 1
+folder arguments makes the selection-list subfolder the
+current folder.
+Each selection-list folder will have its
+current message set to the first of the messages linked into
+it unless the selection list already existed, in which case the
+current message won't be c
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/man/prev.1 b/docs/historical/mh-jun-1982/man/prev.1
new file mode 100644 (file)
index 0000000..f9b1611
--- /dev/null
@@ -0,0 +1,30 @@
+.TH PREV 1 RAND
+.SH NAME
+prev \- show the previous message
+.SH SYNOPSIS
+.B prev 
+\%[+folder] \%[\-switches\ for\ \fIshowproc\fR] \%[\fB\-help\fR]
+.SH DESCRIPTION
+\fIPrev\fR performs a \fIshow\fR on the previous message in the specified
+(or current) folder.
+Like \fIshow\fR, it passes any switches on to the
+program named by \fIshowproc\fR, which is called to list the message.
+This command
+is exactly equivalent to ``show prev''.
+.SH FILES
+.ta 2.4i
+$HOME/\*.mh\(ruprofile The user profile
+.SH PROFILE COMPONENTS
+Showproc:      Program to list the message.
+.br
+Path:  To determine the user's MH directory
+.Ps
+Current-Folder:        To find the default current folder
+.SH SEE ALSO
+next(1), show(1)
+.SH DEFAULTS
+showproc:      /usr/ucb/c
+.SH CONTEXT
+If a folder is specified, it will become current, and the
+message that is shown (i.e., the previous message in sequence)
+will become the current message.
diff --git a/docs/historical/mh-jun-1982/man/prompter.1 b/docs/historical/mh-jun-1982/man/prompter.1
new file mode 100644 (file)
index 0000000..c58b573
--- /dev/null
@@ -0,0 +1,73 @@
+.TH PROMPTER 1 RAND
+.SH NAME
+prompter \- prompting editor front end
+.SH SYNOPSIS
+This program is not called directly but takes the place
+of an editor and acts as an editor front end.
+.br
+\fBprompter\fR \%[\fB\-erase\fR\ chr] \%[\fB\-kill\fR\ chr] \%[\fB\-help\fR]
+.SH DESCRIPTION
+\fIPrompter\fR is an editor which allows rapid composition of
+messages.
+It is particularly useful to network and low-speed
+(less than 2400 baud) users of MH.
+It is an MH program in that
+it can have its own profile entry with switches, but it can't
+be invoked directly as all other MH commands can; it is an editor
+in that it is invoked by an ``\-editor prompter'' switch or by the
+profile entry ``Editor: prompter'', but functionally it is merely
+a text-collector and not a true editor.
+
+\fIPrompter\fR expects to be called from \fIcomp\fR, \fIrepl\fR, \fIdist\fR, or
+\fIforw\fR, with a draft file as an argument.
+For example, ``comp
+\-editor prompter'' will call \fIprompter\fR with the file ``draft'' already set
+up with blank components.
+For each blank component it finds in
+the draft, it prompts the user and accepts a response.
+A
+<RETURN> will cause the whole component to be left out.
+A ``\\''
+preceding a <RETURN> will continue the response on the next line,
+allowing for multiline components.
+
+Any component that is non-blank will be copied and echoed to the
+terminal.
+
+The start of the message body is prompted by a line of
+dashes.
+If the body is non-blank, the prompt is
+.br
+``--------Enter additional text''.
+Message-body typing is terminated with
+a <CTRL-D> (or <OPEN>).
+Control is returned to the calling
+program, where the user is asked ``What now?''.
+See \fIcomp\fR for
+the valid options.
+
+The line editing characters for kill and erase may be
+specified by the user via the arguments ``\-kill chr'' and ``\-erase
+chr'', where chr may be a character; or ``\\nnn'', where nnn is the
+octal value for the character.
+(Again, these may come from the
+default switches specified in the user's profile.)
+
+A <DEL> during message-body typing is equivalent to
+<CTRL-D> for compatibility with NED.
+A <DEL> during
+component typing will abort the command that invoked
+\fIprompter\fR.
+.PP
+The first non-flag argument to
+.I comp
+is taken as the name of the draft file, and
+subsequent non-flag arguments are ignored.
+(`Repl' invokes editors with two file arguments:
+the draft file name and the replied-to message file name.)
+.SH FILES
+None
+.SH PROFILE COMPONENTS
+.ta 2.4i
+prompter-next: To name the editor to be 
+       used on exit from \fIprom
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/man/repl.1 b/docs/historical/mh-jun-1982/man/repl.1
new file mode 100644 (file)
index 0000000..a383580
--- /dev/null
@@ -0,0 +1,94 @@
+.TH REPL 1 RAND
+.SH NAME
+repl \- reply to a message
+.SH SYNOPSIS
+\fBrepl\fR \%[+folder] \%[msg] \%[\fB\-editor\fR\ editor]
+\%[\fB\-inplace\fR] \%[\fB\-annotate\fR]
+\%[\fB\-help\fR] \%[\fB\-noinplace\fR]
+\%[\fB\-noannotate\fR]
+.SH DESCRIPTION
+\fIRepl\fR aids a user in producing a reply to an existing
+message.
+In its simplest form (with no arguments), it will set up
+a message-form skeleton in reply to the current message in the
+current folder, invoke the editor, and send the composed
+message if so directed.
+The composed message is constructed as
+follows:
+
+.nf
+.in 1i
+To: <Reply-To> or <From>
+cc: <cc>, <To>
+Subject: Re: <Subject>
+In-reply-to: Your message of <Date>
+.ti +\w'In-reply-to: 'u
+<Message-Id>
+.in .5i
+.fi
+
+where field names enclosed in angle brackets (< >) indicate the
+contents of the named field from the message to which the reply
+is being made.
+Once the skeleton is constructed, an editor is
+invoked (as in \fIcomp\fR, \fIdist\fR, and \fIforw\fR).
+While in the editor,
+the message being replied to is available through a link named
+``@''.
+
+.B NOTE:
+.I repl
+invokes the editor with two file arguments.
+The second is the filename of the message being
+replied to, and is intended
+to be used as an `alternate' file within the editor.
+If the editor used doesn't have this feature, it must
+ignore the extra file argument and edit the first
+file argument.
+
+As in \fIcomp\fR, \fIdist\fR, and \fIforw\fR, the user will be queried
+before the message is sent.
+If `\-annotate' is
+specified, the replied-to message will be annotated with the
+single line
+
+.ti +.5i
+Replied: \*(<<Date\*(>>.
+
+The command
+``comp \-use'' may be used to pick up interrupted editing, as in
+\fIdist\fR and \fIforw\fR; the `\-inplace' switch annotates the message in place,
+so that all folders with links to it will see the annotation.
+
+See \fIcomp(1)\fR for a description of the `\-editor' switch and for options
+upon exiting from the editor.
+.SH FILES
+.ta 2.4i
+$HOME/\*.mh\(ruprofile The user profile
+.br
+<mh-dir>/draft The constructed message file
+.br
+/usr/bin/send  To send the composed message
+.SH PROFILE COMPONENTS
+Path:  To determine the user's MH directory
+.br
+Editor:        To override the default editor
+.br
+Current-Folder:        To find the default current folder
+.SH DEFAULTS
+`+folder' defaults to current
+.br
+`msgs' defaults to cur
+.br
+`\-editor' defaults to /bin/ned
+.br
+`\-noannotate'
+.br
+`\-noinplace'
+.SH SEE ALSO
+comp(1),dist(1), forw(1)
+.SH CONTEXT
+If a `+folder' is specified, it will become the current
+folder, and the current message will be set to the replied-to
+message.
+.sp 2
diff --git a/docs/historical/mh-jun-1982/man/rmail.1 b/docs/historical/mh-jun-1982/man/rmail.1
new file mode 100644 (file)
index 0000000..f2ae09f
--- /dev/null
@@ -0,0 +1,44 @@
+
+.TH RMAIL 1 RAND
+.SH NAME
+rmail \- send mail from a remote site
+.SH SYNOPSIS
+.B mail
+user 
+.SH DESCRIPTION
+.I Rmail
+is intended as an interface between mail sent from foreign
+sites via
+.I uucp(1)
+and the Rand message handling system,
+.I mh(1).
+It reads a message from the standard input and, after creating
+mh-format lines for the sender and recipient user, writes
+it into a temporary file.  It then invokes
+.I deliver(8)
+to complete the mail delivery.
+.PP
+.I Rmail
+is able to understand a series of lines of the form:
+.br
+       From \fIuser\fB ... remote from \fIsite\fR
+.br
+and turn them into the correct "From: \fIsite\fR!\fIuser\fR" form,
+thus allowing effective use of the 
+.I reply(1)
+command.
+.PP
+If the destination 
+.I user
+is in fact a foreign uucp site, no formatting or reprocessing is
+done; 
+.I deliver
+will simply forward the message to the foreign site with the
+appropriate uucp-style header on it.
+.SH FILES
+/etc/mh/deliver
+.br
+/tmp/mail*.tmp
+.br
+.SH SEE ALSO
+bellmail(1),  deliver(8), mail(1), uucp(1)
diff --git a/docs/historical/mh-jun-1982/man/rmf.1 b/docs/historical/mh-jun-1982/man/rmf.1
new file mode 100644 (file)
index 0000000..3c7e7d8
--- /dev/null
@@ -0,0 +1,59 @@
+.TH RMF 1 RAND
+.SH NAME
+rmf \- remove folder
+.SH SYNOPSIS
+.B rmf 
+\%[+folder] \%[
+.B \-help
+]
+.SH DESCRIPTION
+\fIRmf\fR removes all of the files (messages) within the specified
+(or default) folder, and then removes the directory (folder).
+If
+there are any files within the folder which are not a part of MH,
+they will \fInot\fR be removed, and an error will be produced.
+If the
+folder is given explicitly or the current folder is a
+subfolder (i.e., a selection list from \fIpick\fR), it will be
+removed without confirmation.
+If no argument is specified and
+the current folder is not a selection-list folder, the
+user will be asked for confirmation.
+
+\fIRmf\fR irreversibly deletes messages that don't have other links,
+so use it with caution.
+
+If the folder being removed is a subfolder, the parent
+folder will become the new current folder, and \fIrmf\fR will
+produce a message telling the user this has happened.
+This
+provides an easy mechanism for selecting a set of messages,
+operating on the list, then removing the list and returning to
+the current folder from which the list was extracted.
+(See the
+example under \fIpick\fR.)
+
+The files that \fIrmf\fR will delete are cur, any file beginning
+with a comma, and files with purely numeric names.
+All others
+will produce error messages.
+
+\fIRmf\fR of a read-only folder will delete the ``cur\-'' entry from the
+profile without affecting the folder itself.
+.SH FILES
+.ta 2.4i
+$HOME/\*.mh\(ruprofile The user profile
+.SH PROFILE COMPONENTS
+Path:  To determine the user's MH directory
+.br
+Current-Folder:        To find the default current folder
+.SH SEE ALSO
+rmm(1)
+.SH DEFAULTS
+`+folder' defaults to current, usually with confirmation
+.SH CONTEXT
+\fIRmf\fR will set the current folder to the parent folder if a
+subfolder is removed; or if the current folder is removed,
+it will make ``inbox'' current.
+Otherwise, it doesn't change the
+current folder or message.
diff --git a/docs/historical/mh-jun-1982/man/rmm.1 b/docs/historical/mh-jun-1982/man/rmm.1
new file mode 100644 (file)
index 0000000..88b5ac9
--- /dev/null
@@ -0,0 +1,52 @@
+.TH RMM 1 RAND
+.SH NAME
+rmm \- remove messages
+.SH SYNOPSIS
+.B rmm
+\%[+folder] \%[msgs] \%[
+.B \-help
+]
+.SH DESCRIPTION
+\fIRmm\fR removes the specified messages by renaming the message
+files with preceding commas.
+(This is the Rand-UNIX backup file
+convention.)
+.PP
+If the user has a profile component such as
+.br
+       delete-prog:    /bin/rm
+.br
+then instead of simply renaming the message file,
+.I rmm
+will call the named program to delete the file.
+.PP
+Some users of csh prefer the following:
+.br
+       alias rmm file +d
+.br
+where folder +d is a folder for deleted messages, and
+.br
+       alias mexp 'rm `mhpath +d all`'
+.br
+is used to `exponge' deleted messages.
+.PP
+The current message is not changed by \fIrmm\fR, so a \fInext\fR  will
+advance to the next message in the folder as expected.
+.SH FILES
+.ta 2.4i
+$HOME/\*.mh\(ruprofile The user profile
+.SH PROFILE COMPONENTS
+Path:  To determine the user's MH directory
+.br
+Current-Folder:        To find the default current folder
+.br
+Delete-prog:   Optional program to delete the message
+.SH SEE ALSO
+rmf(1)
+.SH DEFAULTS
+.br
+`+folder' defaults to current
+.br
+`msgs' defaults to cur
+.SH CONTEXT
+If a folder is given, it will become current.
diff --git a/docs/historical/mh-jun-1982/man/scan.1 b/docs/historical/mh-jun-1982/man/scan.1
new file mode 100644 (file)
index 0000000..49a4b21
--- /dev/null
@@ -0,0 +1,90 @@
+.TH SCAN 1 RAND
+.SH NAME
+scan \- produce a one-line-per-message scan listing
+.SH SYNOPSIS
+scan \%[+folder] \%[msgs] \%[\-f\&f] \%[\-header] \%[\-help]
+\%[\-nof\&f] \%[\-noheader] \%[\-time] \%[\-notime] \%[\-numdate] \%[\-nonumdate]
+.SH DESCRIPTION
+\fIScan\fR produces a one-line-per-message listing of the specified
+messages.
+Each \fIscan\fR line contains the message number (name),
+the date, the ``From'' field, the \*(lqSubject'' field, and, if room
+allows, some of the body of the message.
+For example:
+
+.nf
+.ta .5i 1.2i 2.6i
+ #     Date      From  Subject\ \ \ \ \[\*(<<Body]
+15+    7/\05   dcrocker        nned  <<Last week I asked some of
+16\ \- 7/\05   dcrocker        message id format  <<I recommend
+18     7/\06   Obrien  Re: Exit status from mkdir
+19     7/\07   Obrien  "scan" listing format in MH
+20   7/\07   phyl \    \   \  Short  <<message >>
+.re
+.fi
+
+The `+' on message 15 indicates that it is the current message.
+The `\-' on message 16 indicates that it has been
+replied to, as indicated by a ``Replied:'' component produced by
+an `\-annotate' switch to the \fIrepl\fR command.
+
+If there is sufficient room left on the \fIscan\fR line after the
+subject, the line will be filled with text from the body,
+preceded by <<, and terminated by >> if the body is sufficiently short.
+\fIScan\fR actually reads each of the specified
+messages and parses them to extract the desired fields.
+During parsing, appropriate error messages will be produced if
+there are format errors in any of the messages.
+
+The `\-header' switch produces a header line prior to the \fIscan\fR
+listing, and the `\-f\&f' switch will cause a form feed to be
+output at the end of the \fIscan\fR listing.
+.PP
+Example:
+
+The command:  (scan -ff -header; show all -pr -f) | print
+
+produces a scan listing of the current folder, followed by a form feed,
+followed by a formatted listing of all messages in the folder, one per
+page.  Omitting "-pr -f" will cause the messages to be concatenated,
+separated by a one-line header and two blank lines.
+
+If the `\-time' switch is selected, the time of the message is shown
+after the date.
+If the `\-numdate' switch is selected,
+the date (and time if `\-time' is selected) of the message
+is shown as one long number made up of year, month, day, hour, minute.
+This is useful for sorting messages in a folder.
+.PP
+Example:
+
+162+ 8202192032 Dave-Yost         mh distrib  <<is almost done.
+
+.SH FILES
+.ta 2.4i
+$HOME/\*.mh\(ruprofile The user profile
+.SH PROFILE COMPONENTS
+Path:  To determine the user's MH directory
+.br
+Current-Folder:        To find the default current folder
+.SH SEE ALSO
+inc(1), show(1)
+.SH DEFAULTS
+.br
+`+folder' defaults to current
+.br
+`msgs' defaults to all
+.br
+`\-nof\&f'
+.br
+`\-noheader'
+.br
+`\-notime'
+.br
+`\-nonumdate'
+.SH CONTEXT
+If a folder is given, it will become current.
+The current
+message is unaffected.
+.SH BUGS
+The `\-numdate' option ignores timezones.
diff --git a/docs/historical/mh-jun-1982/man/send.1 b/docs/historical/mh-jun-1982/man/send.1
new file mode 100644 (file)
index 0000000..070200c
--- /dev/null
@@ -0,0 +1,74 @@
+.TH SEND 1 RAND
+.SH NAME
+send \- send a message
+.SH SYNOPSIS
+send \%[file] \%[\-draft] \%[\-verbose] \%[\-format] \%[\-msgid]
+\%[\-help]  \%[\-noverbose] \%[\-noformat] \%[\-nomsgid]
+.SH DESCRIPTION
+\fISend\fR will cause the specified file (default <mh-dir>/draft) to
+be delivered 
+(via 
+.I deliver(8)
+) to each of the addresses in the ``To:'', ``cc:'', and ``Bcc:''
+fields of the message.
+If `\-verbose' is specified, \fIsend;\fR
+will monitor the delivery of local and net mail.
+\fISend\fR with no
+argument will query whether the draft is the intended file, whereas
+`\-draft' will suppress this question.
+Once the message has
+been mailed (or queued) successfully, the file will be renamed
+with a leading comma, which allows it to be retreived until the
+next draft message is sent.
+If there are errors in the
+formatting of the message, \fIsend;\fR will abort with a (hopefully)
+helpful error message.
+
+If a ``Bcc:'' field is encountered, its addresses will be used for
+delivery, but the ``Bcc:'' field itself will be deleted from all
+copies of the outgoing message.
+
+Prior to sending the message, the fields ``From:  user'', and
+``Date: now'' will be prepended to the message.
+If `\-msgid' is
+specified, then a ``Message-Id:'' field will also be added to the
+message.
+If the message already contains a ``From:'' field, then a
+``Sender: user'' field will be added instead.
+(An already existing
+``Sender:'' field will be deleted from the message.)
+
+If the user doesn't specify `\-noformat', each of the entries in
+the ``To:'' and ``cc:'' fields will be replaced with ``standard'' format
+entries.
+This standard format is designed to be usable by all
+of the message handlers on the various systems around the
+ARPANET.
+
+If an ``Fcc: folder'' is encountered, the message will be copied
+to the specified folder in the format in which it will appear to any
+receivers of the message.
+That is, it will have the prepended
+fields and field reformatting.
+
+If a ``Distribute-To:'' field is encountered, the message
+is handled as a redistribution message (see \fIdist(1)\fR for
+details), with ``Distribution-Date: now'' and ``Distribution-From: user''
+added.
+.SH FILES
+.ta 2.4i
+$HOME/\*.mh\(ruprofile The user profile
+.SH PROFILE COMPONENTS
+Path:  To determine the user's MH directory
+.SH SEE ALSO
+deliver(8),dist(1),forw(1)
+.SH DEFAULTS
+`file' defaults to draft
+.br
+`\-noverbose'
+.br
+`\-format'
+.br
+`\-nomsgid'
+.SH CONTEXT
+\fISend\fR has no effect on the current message or 
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/man/show.1 b/docs/historical/mh-jun-1982/man/show.1
new file mode 100644 (file)
index 0000000..8c369cb
--- /dev/null
@@ -0,0 +1,74 @@
+.TH SHOW 1 RAND
+.SH NAME
+show \- show (list) messages
+.SH SYNOPSIS
+show \%[+folder] \%[msgs] \%[\-format] \%[\-noformat] \%[\-pr] \%[\-nopr] \%[\-draft] \%[\-help]
+\%[\fIc\fR\ or\ \fIpr\fR\ switches]
+.SH DESCRIPTION
+\fIShow\fR lists each of the specified messages to the standard
+output (typically, the terminal).
+The messages are listed exactly
+as they are, with no reformatting.
+A program named by the \fBshowproc\fR profile component is
+invoked to do the listing, and any switches not recognized by
+\fIshow\fR are passed along to that program.  The default
+program is known as \fIc\fR (also known as \fIl\fR).
+The mh command \fBmhl\fR can be used as a \fBshowproc\fR
+to show messages in a more uniform format.  See mhl(1).
+If the `-noformat' option is specified, `/bin/cat' is used
+instead of \fBshowproc\fR.
+The opposite of this is `-format', which is the default.
+
+If no ``msgs'' are specified, the current message is used.
+If
+more than one message is specified, \fIc\fR will prompt for a
+<return> prior to listing each message.
+
+\fIc\fR will list each message, a page at a time.
+When the end of
+page is reached, \fIc\fR will ring the bell and wait for a <RETURN>
+or <CTRL-D>.
+If a <return> is entered, \fIc\fR will clear the
+screen before listing the next page, whereas <CTRL-D> will not.
+The switches to \fIc\fR are
+`\-p#' to indicate the page length in lines, and `\-w#' to
+indicate the width of the page in characters.
+
+If the standard output is not a terminal, no queries are made,
+and each file is listed with a one-line header and two lines of
+separation.
+
+If `\-pr' is specified, then \fIpr\fR(I) will be invoked rather than
+\fIc\fR, and the switches (other than `\-draft') will be passed
+along.
+``Show \-draft'' will list the file <mh-dir>/draft if it
+exists.
+.SH FILES
+.ta 2.4i
+$HOME/\*.mh\(ruprofile The user profile
+.br
+/usr/ucb/c     Screen-at-a-time list program
+.br
+/bin/pr        \fIpr\fR(I)
+.SH PROFILE COMPONENTS
+Path:  To determine the user's MH directory
+.br
+Current-Folder:        To find the default current folder
+.br
+showproc:      Program to show message
+.br
+prproc:                Program to use for ``pr''
+.SH SEE ALSO
+next(1), prev(1), c(1), mhl(1)
+.SH DEFAULTS
+`+folder' defaults to current
+.br
+`msgs' defaults to cur
+.br
+`\-format'
+.br
+`\-nopr'
+.SH CONTEXT
+If a folder is given, it will become the current message.
+The last message
+listed will become the current message.
diff --git a/docs/historical/mh-jun-1982/mh.diff b/docs/historical/mh-jun-1982/mh.diff
new file mode 100644 (file)
index 0000000..746d921
--- /dev/null
@@ -0,0 +1,693 @@
+Only in /usr/src/cmd/mh: Adrparse
+
+
+diff -rb /usr/src/cmd/mh/Bugs mh/Bugs
+215,231d214
+< 5/25/82 phyl
+<      news bugs:
+<      1) .mh_receive should have a locking mechanism to guard
+<      against simultaneous incoming messages.
+<      2) news/.mh_receive requires its mail directory to be
+<      its top level directory.  Instead, .mh_receive should
+<      be a C program that looks at .mh_profile for the proper
+<      mail path.
+<      3) The alias string that is passed off to news/.mh_receive
+<      should be the string that matched news.* rather than the
+<      1st alias match.  Example:
+<              /etc/MailAliases
+<                 fum: news.pktest
+<                 news.*: news
+<              To: fum
+<      execs news/.mh_receive(,,,fum) instead of
+<      news/.mh_receive(,,,news.pktest)
+Common subdirectories: /usr/src/cmd/mh/DOC and mh/DOC
+Common subdirectories: /usr/src/cmd/mh/Extras and mh/Extras
+
+
+diff -rb /usr/src/cmd/mh/MHgenerate mh/MHgenerate
+49c49
+<    If not, don't define it.  If ARPANET is not defined, and if you want to
+---
+>    If not, don't define it.  If ARPANET is not defined and if you want to
+51,52c51,52
+<    adrparse.h.  If you are on VMUNIX, define that in mh.h and set up
+<    the JOBSLIB define in progs/Makefile.
+---
+>    adrparse.h.  If you are on VMUNIX, define that in mh.h and set up the
+>    JOBSLIB define in progs/Makefile.
+55,58c55,58
+<    /usr/include and modify them for your installation.
+<    If you are going to use mh over uucp and/or ARPANET links, you must
+<    edit your /usr/include/whoami.h to be sure the defines for sysname (uucp)
+<    and HOSTNAME & HOSTNUM (ARPANET) are correct.  If you are not on the
+---
+>    /usr/include or support/ and modify them for your installation.
+>    If you are going to use mh over uucp and/or ARPANET links, you must edit
+>    your /usr/include/whoami.h to be sure the defines for sysname (uucp) and
+>    HOSTNAME & HOSTNUM (ARPANET) are correct.  If you are not on the
+92a93,94
+>    (Ignore the possible error message "nm: sysname.o--no name list")
+> 
+Only in /usr/src/cmd/mh: Makeback
+
+
+diff -rb /usr/src/cmd/mh/Makefile mh/Makefile
+11c11
+< BINDIR  = /usr/randbin
+---
+> BINDIR  = /usr/local
+
+
+diff -rb /usr/src/cmd/mh/Wishlist mh/Wishlist
+484a485
+> 
+512,518d512
+< 5/12/82
+<      Send to an alias list, less the following exceptions.
+< 
+<              To: group<except, except...>
+< 
+<              Cc: csd-mgrs<terry>
+<                                      Terry West
+Only in /usr/src/cmd/mh: adrparse.h.sav
+Only in /usr/src/cmd/mh: di.man1
+Only in /usr/src/cmd/mh: diff.05112
+Only in /usr/src/cmd/mh: diff.05132
+Common subdirectories: /usr/src/cmd/mh/dytest and mh/dytest
+Only in /usr/src/cmd/mh: err
+Only in /usr/src/cmd/mh: greep
+Common subdirectories: /usr/src/cmd/mh/man and mh/man
+Only in /usr/src/cmd/mh: mh.h.sav
+Common subdirectories: /usr/src/cmd/mh/misc and mh/misc
+Only in /usr/src/cmd/mh: pktest
+Only in /usr/src/cmd/mh: printmh
+Common subdirectories: /usr/src/cmd/mh/progs and mh/progs
+Only in /usr/src/cmd/mh: randnet
+Common subdirectories: /usr/src/cmd/mh/strings and mh/strings
+Common subdirectories: /usr/src/cmd/mh/subs and mh/subs
+Common subdirectories: /usr/src/cmd/mh/support and mh/support
+Common subdirectories: /usr/src/cmd/mh/Extras/libg and mh/Extras/libg
+Common subdirectories: /usr/src/cmd/mh/Extras/libh and mh/Extras/libh
+Only in /usr/src/cmd/mh/Extras: mhl.bsb
+
+
+diff -rb /usr/src/cmd/mh/dytest/Makefile mh/dytest/Makefile
+11c11
+< JOBSLIB= -ljobs
+---
+> LIBJOBS=#-ljobs
+15c15
+< BINDIR  = /usr/randbin
+---
+> BINDIR  = /usr/local
+60d59
+< ack.c \
+89,91d87
+< ack:    ack.o $(SUBS)
+<      $(CC) -o ack ack.o $(SUBS)
+< 
+419d414
+< show.o:       mhl.c
+Only in /usr/src/cmd/mh/dytest: Olson
+Only in /usr/src/cmd/mh/dytest: ack
+Only in /usr/src/cmd/mh/dytest: ack.c
+Only in /usr/src/cmd/mh/dytest: ack.o
+Only in /usr/src/cmd/mh/dytest: err
+Only in /usr/src/cmd/mh/dytest: gimme.c
+Only in /usr/src/cmd/mh/dytest: key.c
+Only in /usr/src/cmd/mh/dytest: key.o
+Only in mh/dytest: mhl.c
+Only in mh/dytest: show.c
+Only in /usr/src/cmd/mh/dytest: test
+Only in /usr/src/cmd/mh/man: test
+Only in /usr/src/cmd/mh/progs: Makeback
+
+
+diff -rb /usr/src/cmd/mh/progs/Makefile mh/progs/Makefile
+11c11
+< JOBSLIB= -ljobs
+---
+> JOBSLIB=#-ljobs
+13c13,16
+< CFLAGS  = -O $(A) # -m -DRAND
+---
+> CFLAGS  = -O $(A) -I/usr/include -I../support # -m -DRAND
+> # On a PDP/11, if the sticky bit is to be set, text must be shareable
+> CCSHARE = -n
+> 
+15c18
+< BINDIR  = /usr/randbin
+---
+> BINDIR  = /usr/local
+92c95
+<      $(CC) -o comp comp.o $(SUBS) $(STRINGS)
+---
+>      $(CC) $(CCSHARE) -o comp comp.o $(SUBS) $(STRINGS)
+98,99c101,102
+<      $(CC) -o deliver deliver.o adrparse.o adrformat.o $(SUBS) $(STRINGS)\
+<      $(JOBSLIB)
+---
+>      $(CC) $(CCSHARE) -o deliver deliver.o adrparse.o adrformat.o $(SUBS) \
+>      $(STRINGS) $(JOBSLIB)
+114c117
+<      $(CC) -o inc inc.o scansub.o $(SUBS) $(STRINGS)
+---
+>      $(CC) $(CCSHARE) -o inc inc.o scansub.o $(SUBS) $(STRINGS)
+132c135
+<      $(CC) -o next nexthdr.o next.o $(SUBS) $(STRINGS)
+---
+>      $(CC) $(CCSHARE) -o next nexthdr.o next.o $(SUBS) $(STRINGS)
+141c144
+<      $(CC) -o prompter prompter.o $(SUBS) $(STRINGS)
+---
+>      $(CC) $(CCSHARE) -o prompter prompter.o $(SUBS) $(STRINGS)
+162c165
+<      $(CC) -o show show.o $(SUBS) $(STRINGS)
+---
+>      $(CC) $(CCSHARE) -o show show.o $(SUBS) $(STRINGS)
+207,208c210,211
+<      -/etc/chown root $(NETDIR)
+<      -chmod 755  $(NETDIR)
+---
+>      /etc/chown root $(NETDIR)
+>      chmod 755  $(NETDIR)
+210,211c213,214
+<      -/etc/chown root $(LOCKDIR)
+<      -chmod 777  $(LOCKDIR)
+---
+>      /etc/chown root $(LOCKDIR)
+>      chmod 777  $(LOCKDIR)
+233c236
+<      -chmod a+x $(PROGS)
+---
+>      chmod a+x $(PROGS)
+272c275
+< adrparse.o:   /usr/include/whoami.h
+---
+> #adrparse.o:      /usr/include/whoami.h
+275c278
+< adrparse.o:   /usr/include/imp.h
+---
+> #adrparse.o:      /usr/include/imp.h
+284c287
+< comp.o:       /usr/include/strings.h
+---
+> #comp.o:  /usr/include/strings.h
+293,294c296,297
+< conflict.o:   /usr/include/mailsys.h
+< deliver.o:    /usr/include/whoami.h
+---
+> #conflict.o:      /usr/include/mailsys.h
+> #deliver.o:       /usr/include/whoami.h
+304,305c307,308
+< deliver.o:    /usr/include/strings.h
+< deliver.o:    /usr/include/mailsys.h
+---
+> #deliver.o:       /usr/include/strings.h
+> #deliver.o:       /usr/include/mailsys.h
+310c313
+< dist.o:       /usr/include/strings.h
+---
+> #dist.o:  /usr/include/strings.h
+320c323
+< folder.o:     /usr/include/strings.h
+---
+> #folder.o:        /usr/include/strings.h
+324c327
+< forw.o:       /usr/include/strings.h
+---
+> #forw.o:  /usr/include/strings.h
+332c335
+< inc.o:        /usr/include/strings.h
+---
+> #inc.o:   /usr/include/strings.h
+350c353
+< mhpath.o:     /usr/include/strings.h
+---
+> #mhpath.o:        /usr/include/strings.h
+357c360
+< news.o:       /usr/include/strings.h
+---
+> #news.o:  /usr/include/strings.h
+361c364
+< next.o:       /usr/include/strings.h
+---
+> #next.o:  /usr/include/strings.h
+373,374c376,377
+< prompter.o:   /usr/include/strings.h
+< repl.o:       /usr/include/whoami.h
+---
+> #prompter.o:      /usr/include/strings.h
+> #repl.o:  /usr/include/whoami.h
+378c381
+< repl.o:       /usr/include/strings.h
+---
+> #repl.o:  /usr/include/strings.h
+383c386
+< rmail.o:      /usr/include/whoami.h
+---
+> #rmail.o:         /usr/include/whoami.h
+390c393
+< rmf.o:        /usr/include/strings.h
+---
+> #rmf.o:   /usr/include/strings.h
+393c396
+< rmm.o:        /usr/include/strings.h
+---
+> #rmm.o:   /usr/include/strings.h
+396c399
+< scan.o:       /usr/include/strings.h
+---
+> #scan.o:  /usr/include/strings.h
+399c402
+< scansub.o:    /usr/include/whoami.h
+---
+> #scansub.o:       /usr/include/whoami.h
+409c412
+< send.o:       /usr/include/strings.h
+---
+> #send.o:  /usr/include/strings.h
+413c416
+< show.o:       /usr/include/strings.h
+---
+> #show.o:  /usr/include/strings.h
+Only in mh/progs: Makefile.bak
+Only in /usr/src/cmd/mh/progs: adrformat.o
+Only in /usr/src/cmd/mh/progs: adrpars.c.3102
+Only in /usr/src/cmd/mh/progs: adrparse.c.sav
+Only in /usr/src/cmd/mh/progs: adrparse.o
+Only in /usr/src/cmd/mh/progs: ali
+Only in /usr/src/cmd/mh/progs: ali.lint
+Only in /usr/src/cmd/mh/progs: ali.o
+Only in /usr/src/cmd/mh/progs: annotate.o
+Only in /usr/src/cmd/mh/progs: comp
+Only in /usr/src/cmd/mh/progs: comp.lint
+Only in /usr/src/cmd/mh/progs: comp.o
+Only in /usr/src/cmd/mh/progs: conflict
+Only in /usr/src/cmd/mh/progs: conflict.lint
+Only in /usr/src/cmd/mh/progs: conflict.o
+Only in /usr/src/cmd/mh/progs: deliver
+Only in /usr/src/cmd/mh/progs: deliver.c.3-1
+Only in /usr/src/cmd/mh/progs: deliver.c.3102
+Only in /usr/src/cmd/mh/progs: deliver.c.sav
+Only in /usr/src/cmd/mh/progs: deliver.lint
+Only in /usr/src/cmd/mh/progs: deliver.o
+
+
+diff -rb /usr/src/cmd/mh/progs/dist.c mh/progs/dist.c
+26c26
+< extern struct swit aleqs[] = {
+---
+> struct swit aleqs[] = {
+Only in /usr/src/cmd/mh/progs: dist.lint
+Only in /usr/src/cmd/mh/progs: err
+Only in /usr/src/cmd/mh/progs: file
+Only in /usr/src/cmd/mh/progs: file.lint
+Only in /usr/src/cmd/mh/progs: file.o
+Only in /usr/src/cmd/mh/progs: folder
+Only in /usr/src/cmd/mh/progs: folder.lint
+Only in /usr/src/cmd/mh/progs: folder.o
+Only in /usr/src/cmd/mh/progs: forw
+Only in /usr/src/cmd/mh/progs: forw.lint
+Only in /usr/src/cmd/mh/progs: forw.o
+Only in /usr/src/cmd/mh/progs: grep.o
+Only in /usr/src/cmd/mh/progs: inc
+Only in /usr/src/cmd/mh/progs: inc.o
+Only in /usr/src/cmd/mh/progs: install-mh
+Only in /usr/src/cmd/mh/progs: install-mh.o
+Only in /usr/src/cmd/mh/progs: install.lint
+Only in /usr/src/cmd/mh/progs: m_send.c
+Only in /usr/src/cmd/mh/progs: mail
+Only in /usr/src/cmd/mh/progs: mail.lint
+Only in /usr/src/cmd/mh/progs: mail.o
+Only in /usr/src/cmd/mh/progs: mhl
+Only in /usr/src/cmd/mh/progs: mhl.lint
+Only in /usr/src/cmd/mh/progs: mhl.o
+Only in /usr/src/cmd/mh/progs: mhpath
+Only in /usr/src/cmd/mh/progs: mhpath.o
+Only in /usr/src/cmd/mh/progs: news
+Only in /usr/src/cmd/mh/progs: news.lint
+Only in /usr/src/cmd/mh/progs: news.o
+Only in /usr/src/cmd/mh/progs: next
+Only in /usr/src/cmd/mh/progs: next.o
+Only in /usr/src/cmd/mh/progs: nexthdr.o
+Only in /usr/src/cmd/mh/progs: pick
+Only in /usr/src/cmd/mh/progs: pick.lint
+Only in /usr/src/cmd/mh/progs: pick.o
+Only in /usr/src/cmd/mh/progs: prev
+Only in /usr/src/cmd/mh/progs: prev.lint
+Only in /usr/src/cmd/mh/progs: prevhdr.o
+Only in /usr/src/cmd/mh/progs: prompter
+Only in /usr/src/cmd/mh/progs: prompter.lint
+Only in /usr/src/cmd/mh/progs: prompter.nutty
+Only in /usr/src/cmd/mh/progs: prompter.o
+Only in /usr/src/cmd/mh/progs: repl
+Only in /usr/src/cmd/mh/progs: repl.c.03122
+Only in /usr/src/cmd/mh/progs: repl.c.ok
+Only in /usr/src/cmd/mh/progs: repl.lint
+Only in /usr/src/cmd/mh/progs: repl.o
+
+
+diff -rb /usr/src/cmd/mh/progs/replsubs.c mh/progs/replsubs.c
+1,5d0
+< /*  This mess pre-dates adrparse.  It's function is to
+<  *  attach the Reply-to or From host to hostless addresses
+<  *  on a reply.
+<  */
+< 
+Only in /usr/src/cmd/mh/progs: rmail
+
+
+diff -rb /usr/src/cmd/mh/progs/rmail.c mh/progs/rmail.c
+31,32d30
+<  *
+<  * 5/8/82: Tack on uu-Date: if msg has no date.  PK.
+35d32
+< /*#define DEBUG 1*/
+42,43d38
+< #define PARSE   1
+< #define NOPARSE 0
+45d39
+< 
+55,56d48
+< char d1[10], d2[10], d3[10], d4[10], d5[10];   /*** ctime() fields ***/
+< 
+68d59
+<      int badhdr;   /***/
+91,93c82,83
+< /***/           sscanf(lbuf, "%s %s %s %s %s %s %s remote from %s",
+<               junk, ufrom, d1, d2, d3, d4, d5, sys);
+< /*              sscanf(lbuf, "%s %s", junk, ufrom);  */
+---
+>              /* sscanf(lbuf, "%s %s %s %s %s %s %s remote from %s", junk, ufrom, junk, junk, junk, junk, junk, sys); */
+>              sscanf(lbuf, "%s %s", junk, ufrom);
+136c126
+<              putmsg(NOPARSE);
+---
+>              putmsg();
+145c135
+<      if( !((cp = index(lbuf, ':')) &&  (cp - lbuf <  NAMESZ ))) {
+---
+>      if( !((cp = index(lbuf, ':')) &&  (cp - lbuf <  NAMESZ )))
+147,149c137,138
+<              badhdr++;
+<      }
+<      putmsg(badhdr?NOPARSE:PARSE);
+---
+> 
+>      putmsg();
+223a213
+> 
+242c232
+<      putmsg(NOPARSE);
+---
+>      putmsg();
+296,297c286
+< putmsg(parse)
+< int parse;
+---
+> putmsg()
+299,305d287
+<      int dateseen = 0;
+< 
+<      if(!parse)
+<              putall();
+<      else {
+<              if (uleqn(lbuf, "date:", 5) == 0)
+<                      dateseen++;
+307,324d288
+<              while (fgets(lbuf, sizeof lbuf, stdin)) {
+<                      if(lbuf[0] == '\n' ) { /* end of hdrs */
+<                              if(!dateseen)
+<                                      uudate();
+<                              putall();
+<                      } else {
+<                              if (uleqn(lbuf, "date:", 5) == 0)
+<                                      dateseen++;
+<                              fputs(lbuf, out);
+<                      }
+<              }
+<      }
+< }
+< 
+< 
+< putall()
+< {
+<      fputs(lbuf, out);
+342,391d305
+< /*
+<  * Compare strings (at most n bytes) without regard to case.
+<  *   Returns:   s1>s2: >0,  s1==s2: 0,  s1<s2: <0.
+<  */
+< 
+< uleqn(s1, s2, n)
+< register char *s1, *s2;
+< register n;
+< {
+< 
+<      while (--n >= 0 && (*s1|040) == (*s2|040)) {
+<              s2++;
+<              if (*s1++ == '\0')
+<                      return(0);
+<      }
+<      return(n<0 ? 0 : (*s1|040) - (*s2|040));
+< }
+< 
+< 
+< uudate()
+< {
+<      char *prefix();
+< 
+<      /*                  day    13   Apr  1981 20  :38   -PST */
+<      fprintf(out, "Date: %sday, %.2s %.3s %.4s %.2s:%.2s-%.3s\n",
+<                   prefix(d1), d3, d2, d5, d4, d4+3, "???");
+< }
+< 
+< char *
+< prefix(str)
+< char *str;
+< {
+<      static char *wday[] = {
+<              "Sun",
+<              "Mon",
+<              "Tues",
+<              "Wednes",
+<              "Thurs",
+<              "Fri",
+<              "Satur",
+<              0
+<      };
+< 
+<      register char **wp;
+< 
+<      for(wp=wday; wp; wp++)
+<              if(uleqn(str, *wp, 3) == 0)
+<                      return(*wp);
+<      return("???");
+< }
+Only in /usr/src/cmd/mh/progs: rmail.c.sav
+Only in /usr/src/cmd/mh/progs: rmail.lint
+Only in /usr/src/cmd/mh/progs: rmail.o
+Only in /usr/src/cmd/mh/progs: rmail.sav
+Only in /usr/src/cmd/mh/progs: rmf
+Only in /usr/src/cmd/mh/progs: rmf.lint
+Only in /usr/src/cmd/mh/progs: rmf.o
+Only in /usr/src/cmd/mh/progs: rmm
+Only in /usr/src/cmd/mh/progs: rmm.lint
+Only in /usr/src/cmd/mh/progs: rmm.o
+Only in /usr/src/cmd/mh/progs: scan
+Only in /usr/src/cmd/mh/progs: scan.o
+Only in /usr/src/cmd/mh/progs: scansub.c.sav
+Only in /usr/src/cmd/mh/progs: scansub.o
+Only in /usr/src/cmd/mh/progs: send
+Only in /usr/src/cmd/mh/progs: send.o
+Only in /usr/src/cmd/mh/progs: show
+Only in /usr/src/cmd/mh/progs: show.o
+Only in /usr/src/cmd/mh/strings: Makeback
+
+
+diff -rb /usr/src/cmd/mh/strings/Makefile mh/strings/Makefile
+39c39,40
+<      sysed.o
+---
+>      sysed.o \
+>      sysname.o
+70c71,72
+<         sysed.c
+---
+>         sysed.c \
+>         sysname.c
+89,90c91,92
+< lockdir.o:    /usr/include/mailsys.h
+< mailboxes.o:  /usr/include/mailsys.h
+---
+> #lockdir.o:       /usr/include/mailsys.h
+> #mailboxes.o:     /usr/include/mailsys.h
+91a94
+> #sysname.o:      /usr/include/whoami.h
+Only in /usr/src/cmd/mh/strings: anoyes.o
+Only in /usr/src/cmd/mh/strings: components.o
+Only in /usr/src/cmd/mh/strings: current.o
+Only in /usr/src/cmd/mh/strings: defalt.o
+Only in /usr/src/cmd/mh/strings: distcomps.o
+Only in /usr/src/cmd/mh/strings: draft.o
+Only in /usr/src/cmd/mh/strings: err
+
+
+diff -rb /usr/src/cmd/mh/strings/fileproc.c mh/strings/fileproc.c
+13c13
+< char    *fileproc =     "/usr/randbin/file";
+---
+> char    *fileproc =     "/usr/local/file";
+Only in /usr/src/cmd/mh/strings: fileproc.o
+Only in /usr/src/cmd/mh/strings: foldprot.o
+Only in /usr/src/cmd/mh/strings: installproc.o
+Only in /usr/src/cmd/mh/strings: list
+Only in /usr/src/cmd/mh/strings: listname.o
+Only in /usr/src/cmd/mh/strings: lockdir.o
+
+
+diff -rb /usr/src/cmd/mh/strings/lproc.c mh/strings/lproc.c
+14c14
+< char    *lproc =        "/usr/randbin/c";
+---
+> char    *lproc =        "/usr/ucb/more";
+Only in /usr/src/cmd/mh/strings: lproc.o
+Only in /usr/src/cmd/mh/strings: lsproc.o
+Only in /usr/src/cmd/mh/strings: mailboxes.o
+Only in /usr/src/cmd/mh/strings: mailproc.o
+Only in /usr/src/cmd/mh/strings: mh_deliver.o
+Only in /usr/src/cmd/mh/strings: mh_prof.o
+Only in /usr/src/cmd/mh/strings: mhlformat.o
+Only in /usr/src/cmd/mh/strings: mhlstdfmt.o
+Only in /usr/src/cmd/mh/strings: mhnews.o
+Only in /usr/src/cmd/mh/strings: msgprot.o
+Only in /usr/src/cmd/mh/strings: pfolder.o
+Only in /usr/src/cmd/mh/strings: prproc.o
+
+
+diff -rb /usr/src/cmd/mh/strings/rhosts.c mh/strings/rhosts.c
+19,23d18
+<      "randvax",
+<      "vax",
+<      "graphics",
+<      "gr",
+<      "cs-rand",
+Only in /usr/src/cmd/mh/strings: rhosts.o
+
+
+diff -rb /usr/src/cmd/mh/strings/scanproc.c mh/strings/scanproc.c
+13c13
+< char    *scanproc =     "/usr/randbin/scan";
+---
+> char    *scanproc =     "/usr/local/scan";
+Only in /usr/src/cmd/mh/strings: scanproc.o
+
+
+diff -rb /usr/src/cmd/mh/strings/sendproc.c mh/strings/sendproc.c
+14c14
+< char    *sendproc =     "/usr/randbin/send";
+---
+> char    *sendproc =     "/usr/local/send";
+Only in /usr/src/cmd/mh/strings: sendproc.o
+
+
+diff -rb /usr/src/cmd/mh/strings/showproc.c mh/strings/showproc.c
+16c16
+< char    *showproc =     "/usr/randbin/c";                       /* 5/6/79 */
+---
+> char    *showproc =     "/usr/ucb/more";                       /* 5/6/79 */
+Only in /usr/src/cmd/mh/strings: showproc.o
+Only in /usr/src/cmd/mh/strings: stdcomps.o
+Only in /usr/src/cmd/mh/strings: stddcomps.o
+Only in /usr/src/cmd/mh/strings: strings.a
+Only in /usr/src/cmd/mh/strings: sysed.o
+Only in mh/strings: sysname.c
+
+
+diff -rb /usr/src/cmd/mh/subs/Makefile mh/subs/Makefile
+8c8
+< CFLAGS = # -m
+---
+> CFLAGS = -O -I/usr/include -I../support # -m
+161c161
+< m_edit.o:     /usr/include/strings.h
+---
+> #m_edit.o:        /usr/include/strings.h
+204c204
+< pwd.o:        /usr/include/strings.h
+---
+> #pwd.o:   /usr/include/strings.h
+Only in mh/subs: Makefile.bak
+Only in /usr/src/cmd/mh/subs: add.o
+Only in /usr/src/cmd/mh/subs: ambigsw.o
+Only in /usr/src/cmd/mh/subs: atooi.o
+Only in /usr/src/cmd/mh/subs: brkstring.o
+Only in /usr/src/cmd/mh/subs: cdate.o
+Only in /usr/src/cmd/mh/subs: cndfree.o
+Only in /usr/src/cmd/mh/subs: concat.o
+Only in /usr/src/cmd/mh/subs: copy.o
+Only in /usr/src/cmd/mh/subs: copyip.o
+Only in /usr/src/cmd/mh/subs: cputc.o
+Only in /usr/src/cmd/mh/subs: done.o
+Only in /usr/src/cmd/mh/subs: err
+Only in /usr/src/cmd/mh/subs: fdcompare.o
+Only in /usr/src/cmd/mh/subs: gans.o
+Only in /usr/src/cmd/mh/subs: getans.o
+Only in /usr/src/cmd/mh/subs: getcpy.o
+Only in /usr/src/cmd/mh/subs: help.o
+Only in /usr/src/cmd/mh/subs: locv.o
+Only in /usr/src/cmd/mh/subs: m_convert.o
+Only in /usr/src/cmd/mh/subs: m_delete.o
+Only in /usr/src/cmd/mh/subs: m_edit.o
+Only in /usr/src/cmd/mh/subs: m_file.o
+Only in /usr/src/cmd/mh/subs: m_find.o
+Only in /usr/src/cmd/mh/subs: m_getcur.o
+Only in /usr/src/cmd/mh/subs: m_getdefs.c1
+Only in /usr/src/cmd/mh/subs: m_getdefs.o
+Only in /usr/src/cmd/mh/subs: m_getfld.o
+Only in /usr/src/cmd/mh/subs: m_getfolder.o
+Only in /usr/src/cmd/mh/subs: m_gmprot.o
+Only in /usr/src/cmd/mh/subs: m_gmsg.o
+Only in /usr/src/cmd/mh/subs: m_maildir.o
+Only in /usr/src/cmd/mh/subs: m_name.o
+Only in /usr/src/cmd/mh/subs: m_replace.o
+Only in /usr/src/cmd/mh/subs: m_send.o
+Only in /usr/src/cmd/mh/subs: m_setcur.o
+Only in /usr/src/cmd/mh/subs: m_update.o
+Only in /usr/src/cmd/mh/subs: makedir.o
+Only in /usr/src/cmd/mh/subs: makename.o
+Only in /usr/src/cmd/mh/subs: mu_atoi.o
+Only in /usr/src/cmd/mh/subs: path.o
+Only in /usr/src/cmd/mh/subs: peekc.o
+Only in /usr/src/cmd/mh/subs: pr_array.o
+Only in /usr/src/cmd/mh/subs: printsw.o
+Only in /usr/src/cmd/mh/subs: putenv.o
+Only in /usr/src/cmd/mh/subs: pwd.o
+Only in /usr/src/cmd/mh/subs: r1bindex.o
+Only in /usr/src/cmd/mh/subs: showfile.o
+Only in /usr/src/cmd/mh/subs: smatch.o
+Only in /usr/src/cmd/mh/subs: ssequal.o
+Only in /usr/src/cmd/mh/subs: subs.a
+Only in /usr/src/cmd/mh/subs: trimcpy.o
+Only in /usr/src/cmd/mh/subs: type.o
+Only in /usr/src/cmd/mh/subs: uleq.o
+Only in /usr/src/cmd/mh/support: err
+Only in mh/support: mailsys.h
+Common subdirectories: /usr/src/cmd/mh/support/news and mh/support/news
+Only in mh/support: strings.h
+
+
+diff -rb /usr/src/cmd/mh/support/news/mh_receive mh/support/news/mh_receive
+6c6
+<      /usr/randbin/file -link -file $1 +/usr/news/$F
+---
+>      /usr/local/file -link -file $1 +/usr/news/$F
+8c8
+<      /usr/randbin/file -link -file $1 +/usr/news/Lost+Found
+---
+>      /usr/local/file -link -file $1 +/usr/news/Lost+Found
+11c11
+<      /usr/randbin/file -link -file $1 +/usr/news/Lost+Found
+---
+>      /usr/local/file -link -file $1 +/usr/
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/mh.h b/docs/historical/mh-jun-1982/mh.h
new file mode 100644 (file)
index 0000000..792f71c
--- /dev/null
@@ -0,0 +1,202 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+/* mh.h - main header file for all of mh */
+
+/*  VOID is used to indicate explicitly that the value of a function
+/*  is to be ignored.
+/*  If you have a newer C compiler, it is better to simply say:
+       #define VOID (void)
+/*  instead of what follows
+/**/
+# define void int
+# ifdef  lint
+# define VOID _VOID_ = (int)
+  int     _VOID_;
+# else
+# define VOID
+# endif
+
+/* #define ARPANET         /* if you are on the ARPANET */
+
+/* #define VMUNIX          /* if you are running a Berkeley system */
+/* if you define VMUNIX, then define JOBSLIB=-ljobs in progs/Makefile */
+
+#ifdef ARPANET
+#define NOGATEWAY
+#ifdef  NOGATEWAY
+  extern char *rhosts[];
+#endif  NOGATEWAY
+#endif ARPANET
+
+#define ALL ""
+#define NULLCP (char *)0
+
+#define MAXFOLDER 999   /* Max number of messages in a folder */
+#define DMAXFOLDER 3    /* Number of digits in MAXFOLDER */
+
+#define MAXARGS 1000    /* Max messages to exec                 */
+
+                       /* Flag bits in msgstats                        */
+#define EXISTS    01    /* Message exists                               */
+#define DELETED   02    /* Deleted undefined currently                  */
+#define SELECTED  04    /* Message selected by an arg                   */
+#define SELECT_EMPTY 010/* Single empty msg selected by an mhpath arg   */
+
+#define READONLY  01    /* No write access to folder                    */
+#define DEFMOD    01    /* In-core profile has been modified            */
+
+/*#define NEWS     1    /* Define for news inclusion                    */
+
+struct  swit {
+       char *sw;
+       int minchars;
+};
+
+/*
+ * m_gmsg() returns this structure.  It contains the per folder
+ * information which is obtained from reading the folder directory.
+ */
+
+struct  msgs {
+       int     hghmsg;         /* Highest msg in directory     */
+       int     nummsg;         /* Actual Number of msgs        */
+       int     lowmsg;         /* Lowest msg number            */
+       int     curmsg;         /* Number of current msg if any */
+       int     lowsel;         /* Lowest selected msg number   */
+       int     hghsel;         /* Highest selected msg number  */
+       int     numsel;         /* Number of msgs selected      */
+       char   *foldpath;       /* Pathname of folder           */
+       char    selist,         /* Folder has a "select" file   */
+               msgflags,       /* Folder status bits           */
+               filler,
+               others;         /* Folder has other file(s)     */
+       char    msgstats[1];    /* Stat bytes for each msg      */
+};
+
+               /* m_getfld definitions and return values       */
+
+#define NAMESZ  64      /* Limit on component name size         */
+#define LENERR  -2      /* Name too long error from getfld      */
+#define FMTERR  -3      /* Message Format error                 */
+
+                       /* m_getfld return codes                */
+#define FLD      0      /* Field returned                       */
+#define FLDPLUS  1      /* Field " with more to come            */
+#define FLDEOF   2      /* Field " ending at eom                */
+#define BODY     3      /* Body  " with more to come            */
+#define BODYEOF  4      /* Body  " ending at eom                */
+#define FILEEOF  5      /* Reached end of input file            */
+
+/*
+ * These standard strings are defined in strings.a.  They are the
+ * only system-dependent parameters in MH, and thus by redefining
+ * their values and reloading the various modules, MH will run
+ * on any system.
+ */
+
+extern char
+       *components,    /* Name of user's component file (in mh dir) */
+       *current,       /* Name of current msg file in a folder */
+       *defalt,        /* Name of the std folder (inbox)       */
+       *distcomps,     /* Name of `dist' components file       */
+       *draft,         /* Name of the normal draft file        */
+       *fileproc,      /* Path of file program                 */
+       *foldprot,      /* Default folder protection            */
+/*      *hostname,      /* Local net host name                  */
+       *installproc,   /* Name of auto-install program path    */
+/*      *layout,        /* Name of mhl layout file              */
+       *listname,      /* Default selection list folder name   */
+       *lockdir,       /* Dir for lock files (Same fs as mailboxes)*/
+       *lproc,         /* Path of "list" prog for "What now?"  */
+       *lsproc,        /* Path of the block style ls program   */
+       *mailboxes,     /* Incoming mail directory              */
+       *mailproc,      /* Path of Bell equivalent mail pgm, used by news -send */
+       *mh_prof,       /* Name of users profile file           */
+       *mh_deliver,    /* Name of deliverer for mh             */
+       *mhlformat,     /* Name of mhl format file in MH dir    */
+       *mhlstdfmt,     /* Name of standard mhl format file     */
+       *mhnews,        /* Name of MH news file                 */
+       *msgprot,       /* Default message protection (s.a. 0664) */
+       *pfolder,       /* Name of current folder profile entry */
+       *prproc,        /* Path of the pr program               */
+       *scanproc,      /* Path of the scan program             */
+       *showproc,      /* Path of the type (l) program         */
+       *sendproc,      /* Path of the send message program     */
+       *stdcomps,      /* Std comp file if missing user's own  */
+       *stddcomps,     /* Std dist file if missing user's own  */
+       *sysed;         /* Path of the std (e) editor           */
+
+/* Just about every program uses this also via m_getdefs        */
+char    *mypath;        /* User's log-on path                   */
+
+/*
+ * node structure used to hold a linked list of the users profile
+ * information taken from logpath/.mh_prof.
+ */
+
+struct node {
+       struct node *n_next;
+       char        *n_name,
+                   *n_field;
+} *m_defs;
+
+char  def_flags;
+
+
+/*
+ * The first char in the mhnews file indicates whether the program
+ * calling m_news() should continue running or halt.
+ */
+
+#define NEWSHALT        '!'     /* Halt after showing the news  */
+#define NEWSCONT        ' '     /* Continue  (ditto)            */
+#define NEWSPAUSE       '\001'  /* Pause during news output...  */
+
+
+/*
+ * Miscellaneous Defines to speed things up
+ */
+
+#define error(str) { fprintf(stderr, "%s\n", str); exit(-1); }
+
+/*
+ * Routine type declarations -- needed by version 7 compiler
+ */
+
+char *invo_name;
+char **brkstring();
+char *m_maildir();
+char *m_find();
+char *m_name();
+char *concat();
+char *getcpy();
+char *trimcpy();
+char *add();
+char **copyip();
+char *getcpy();
+char *m_getfolder();
+struct msgs *m_gmsg();
+char *copy();
+char **getans();
+char *cdate();
+char *makename();
+char *r1bindex();
+char *pwd();
+char *path();
+
+/*
+ * Routine type declarations -- SHOULD BE GLOBAL
+ */
+char *getenv();
+
+/*
+ * Defines for path evaluation type--routine path second arg:
+ */
+
+#define TFOLDER 0
+#define TF
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/misc/depend.sh b/docs/historical/mh-jun-1982/misc/depend.sh
new file mode 100755 (executable)
index 0000000..8abadf1
--- /dev/null
@@ -0,0 +1,10 @@
+sed "/DEPENDENCIES/,\$d" < Makefile > Maketemp
+echo "###DEPENDENCIES Follow.  Do not delete this line" >> Maketemp
+grep \^#include $@ | sed '
+       s/\.c/\.o/
+       s/:#include/:   /
+       s/"\(.*\)"/\1/
+       s/<\(.*\)>/\/usr\/include\/\1/
+' >> Maketemp
+mv Makefile Makeback
+mv Maketemp Makefile
diff --git a/docs/historical/mh-jun-1982/progs/Makefile b/docs/historical/mh-jun-1982/progs/Makefile
new file mode 100644 (file)
index 0000000..daa147a
--- /dev/null
@@ -0,0 +1,416 @@
+#
+#       Proprietary Rand Corporation, 1981.
+#       Further distribution of this software
+#       subject to the terms of the Rand
+#       license agreement.
+#
+
+#                       Remove the -DRAND elsewhere!
+# In ../mh.h: define ARPANET if you are on the arpanet.
+# In ../mh.h: define VMUNIX if you are running a berkeley system
+JOBSLIB=#-ljobs
+
+CFLAGS  = -O $(A) -I/usr/include -I../support # -m -DRAND
+# On a PDP/11, if the sticky bit is to be set, text must be shareable
+CCSHARE = -n
+
+# The following two must match entry in ../Makefile
+BINDIR  = /usr/local
+MHDIR   = /etc/mh
+MHTMP   = /usr/tmp/mh
+LOCKDIR = /usr/spool/locks
+NETDIR  = /usr/spool/netmail
+
+SUBS    = ../subs/subs.a
+STRINGS = ../strings/strings.a
+
+LINT    = lint
+
+# The 'dist' program is not ready yet, and so is not listed in the CMDS
+# See also ../man/Makefile
+CMDS    = \
+ali \
+comp \
+file \
+folder \
+forw \
+inc \
+mail \
+mhpath \
+next \
+news \
+pick \
+prev \
+prompter \
+repl \
+rmf \
+rmm \
+scan \
+send \
+show
+
+MISC    = \
+conflict \
+deliver \
+install-mh \
+mhl
+
+PROGS = $(CMDS) $(MISC) rmail
+
+CFILES  = \
+adrformat.c \
+adrparse.c \
+ali.c \
+comp.c \
+conflict.c \
+deliver.c \
+dist.c \
+file.c \
+folder.c \
+forw.c \
+inc.c \
+install-mh.c \
+mail.c \
+mhl.c \
+mhpath.c \
+news.c \
+next.c \
+pick.c \
+prompter.c \
+repl.c \
+rmail.c \
+rmf.c \
+rmm.c \
+scan.c \
+scansub.c \
+send.c \
+show.c
+
+progs:  $(PROGS)
+
+ali:    ali.o $(SUBS)
+       $(CC) -o ali ali.o $(SUBS)
+
+comp:   comp.o $(SUBS) $(STRINGS)
+       $(CC) $(CCSHARE) -o comp comp.o $(SUBS) $(STRINGS)
+
+conflict: conflict.o $(SUBS)
+       $(CC) -o conflict conflict.o $(SUBS)
+
+deliver: deliver.o adrparse.o adrformat.o $(SUBS) $(STRINGS)
+       $(CC) $(CCSHARE) -o deliver deliver.o adrparse.o adrformat.o $(SUBS) \
+       $(STRINGS) $(JOBSLIB)
+
+dist:   dist.o annotate.o $(SUBS) $(STRINGS)
+       $(CC) -o dist dist.o annotate.o $(SUBS) $(STRINGS)
+
+file:   file.o $(SUBS) $(STRINGS)
+       $(CC) -o file file.o $(SUBS) $(STRINGS)
+
+folder: folder.o $(SUBS) $(STRINGS)
+       $(CC) -o folder folder.o $(SUBS) $(STRINGS)
+
+forw:   forw.o annotate.o $(SUBS) $(STRINGS)
+       $(CC) -o forw forw.o annotate.o $(SUBS) $(STRINGS)
+
+inc:    inc.o scansub.o $(SUBS) $(STRINGS)
+       $(CC) $(CCSHARE) -o inc inc.o scansub.o $(SUBS) $(STRINGS)
+
+install-mh: install-mh.o $(SUBS) $(STRINGS)
+       $(CC) -o install-mh install-mh.o $(SUBS) $(STRINGS)
+
+mail:   mail.o $(SUBS) $(STRINGS)
+       $(CC) -o mail mail.o $(SUBS) $(STRINGS)
+
+mhpath: mhpath.o $(SUBS) $(STRINGS)
+       $(CC) -o mhpath mhpath.o $(SUBS) $(STRINGS)
+
+mhl:    mhl.o $(SUBS) $(STRINGS)
+       $(CC) -o mhl mhl.o $(SUBS) $(STRINGS)
+
+news:   news.o $(SUBS) $(STRINGS)
+       $(CC) -o news news.o $(SUBS) $(STRINGS)
+
+next:   nexthdr.o next.o $(SUBS) $(STRINGS)
+       $(CC) $(CCSHARE) -o next nexthdr.o next.o $(SUBS) $(STRINGS)
+
+pick:   pick.o grep.o $(SUBS) $(STRINGS)
+       $(CC) -o pick pick.o grep.o $(SUBS) $(STRINGS)
+
+prev:   prevhdr.o next.o $(SUBS) $(STRINGS)
+       $(CC) -o prev prevhdr.o next.o $(SUBS) $(STRINGS)
+
+prompter: prompter.o $(SUBS) $(STRINGS)
+       $(CC) $(CCSHARE) -o prompter prompter.o $(SUBS) $(STRINGS)
+
+repl:   repl.o annotate.o adrparse.o adrformat.o $(SUBS) $(STRINGS)
+       $(CC) -o repl repl.o annotate.o adrparse.o adrformat.o $(SUBS) $(STRINGS)
+
+rmail:  rmail.o  $(SUBS) $(STRINGS)
+       $(CC) -o rmail rmail.o  $(SUBS) $(STRINGS)
+
+rmf:    rmf.o $(SUBS) $(STRINGS)
+       $(CC) -o rmf rmf.o $(SUBS) $(STRINGS)
+
+rmm:    rmm.o $(SUBS) $(STRINGS)
+       $(CC) -o rmm rmm.o $(SUBS) $(STRINGS)
+
+scan:   scan.o scansub.o $(SUBS) $(STRINGS)
+       $(CC) -o scan scan.o scansub.o $(SUBS) $(STRINGS)
+
+send:   send.o $(SUBS) $(STRINGS)
+       $(CC) -o send send.o $(SUBS) $(STRINGS)
+
+show:   show.o $(SUBS) $(STRINGS)
+       $(CC) $(CCSHARE) -o show show.o $(SUBS) $(STRINGS)
+
+lint:
+       -$(LINT) ali.c -v ../subs/subs-lc | tee ali.lint
+       -$(LINT) comp.c -v ../subs/subs-lc | tee comp.lint
+       -$(LINT) conflict.c -v ../subs/subs-lc | tee conflict.lint
+       -$(LINT) deliver.c adrparse.c adrformat.c -v ../subs/subs-lc | tee deliver.lint
+       -$(LINT) dist.c -v ../subs/subs-lc | tee dist.lint
+       -$(LINT) file.c -v ../subs/subs-lc | tee file.lint
+       -$(LINT) folder.c -v ../subs/subs-lc | tee folder.lint
+       -$(LINT) forw.c annotate.c -v ../subs/subs-lc | tee forw.lint
+       -$(LINT) inc.c scansub.c -v ../subs/subs-lc | tee inc.lint
+       -$(LINT) install-mh.c -v ../subs/subs-lc | tee install.lint
+       -$(LINT) mail.c -v ../subs/subs-lc | tee mail.lint
+       -$(LINT) mhl.c -v ../subs/subs-lc | tee mhl.lint
+       -$(LINT) mhpath.c -v ../subs/subs-lc | tee mhpath.lint
+       -$(LINT) news.c -v ../subs/subs-lc | tee news.lint
+       -$(LINT) pick.c -v ../subs/subs-lc | tee pick.lint
+       -$(LINT) prevhdr.c next.c -v ../subs/subs-lc | tee prev.lint
+       -$(LINT) prompter.c -v ../subs/subs-lc | tee prompter.lint
+       -$(LINT) repl.c replsubs.c -v ../subs/subs-lc | tee repl.lint
+       -$(LINT) rmf.c -v ../subs/subs-lc | tee rmf.lint
+       -$(LINT) rmm.c -v ../subs/subs-lc | tee rmm.lint
+       -$(LINT) scan.c scansub.c -v ../subs/subs-lc | tee scan.lint
+       -$(LINT) show.c -v ../subs/subs-lc | tee show.lint
+
+install: strip installprogs
+       -mkdir $(MHTMP)
+       -mkdir $(MHDIR)
+       -mkdir $(LOCKDIR)
+       -mkdir $(NETDIR)
+       -chmod a+x $(MISC)
+       -cd $(MHDIR); rm -f $(MISC)
+       -cp $(MISC) $(MHDIR)
+       echo Now become root and \'make installroot\'
+
+installprogs: chmod
+       -cd $(BINDIR); rm -f $(CMDS) folders
+       -cp $(CMDS) $(BINDIR)
+       -cd $(BINDIR); ln folder folders
+
+installroot:
+       -chmod 777 $(MHTMP)
+       -cd $(BINDIR); chmod a+x $(CMDS)
+       -cd $(MHDIR); chmod a+x $(MISC)
+       /etc/chown root $(NETDIR)
+       chmod 755  $(NETDIR)
+       -rm -f /bin/rmail
+       /etc/chown root $(LOCKDIR)
+       chmod 777  $(LOCKDIR)
+       -cp rmail /bin
+#           Setuid and Setgid:
+       -chmod 6755 /bin/rmail
+#           Sticky Bit & Setuid:
+       -/etc/chown root $(MHDIR)/deliver;chmod 5755 $(MHDIR)/deliver
+#           Sticky Bit:
+       -chmod 1755 $(BINDIR)/comp
+       -chmod 1755 $(BINDIR)/inc
+       -chmod 1755 $(BINDIR)/next
+       -chmod 1755 $(BINDIR)/prompter
+       -chmod 1755 $(BINDIR)/show
+
+uninstall:
+       -rmdir $(MHTMP)
+       -cd $(MHDIR); rm -f $(MISC)
+       -cd $(BINDIR); rm -f $(CMDS) folders
+
+strip:
+       -strip $(PROGS)
+
+chmod:
+       chmod a+x $(PROGS)
+
+pinstall:
+       -install -s comp $(BINDIR)/comp
+       -install -s file $(BINDIR)/file
+       -install -s folder $(BINDIR)/folder
+       -install -s forw $(BINDIR)/forw
+       -install -s inc $(BINDIR)/inc
+       -install -s mhl $(MHDIR)/mhl
+       -install -s mhpath $(BINDIR)/mhpath
+       -install -s next $(BINDIR)/next
+       -install -s pick $(BINDIR)/pick
+       -install -s prev $(BINDIR)/prev
+       -install -s prompter $(BINDIR)/prompter
+       -install -s repl $(BINDIR)/repl
+       -install -s rmf $(BINDIR)/rmf
+       -install -s rmm $(BINDIR)/rmm
+       -install -s scan $(BINDIR)/scan
+       -install -s send $(BINDIR)/send
+       -install -s show $(BINDIR)/show
+
+distribution:   clean rmprogs
+
+rmprogs:
+       -rm -f $(PROGS)
+
+clean:
+       -rm -f *.o *.lint
+
+depend:
+       ../misc/depend.sh $(CFILES)
+
+
+###DEPENDENCIES Follow.  Do not delete this line
+adrformat.o:     /usr/include/stdio.h
+adrformat.o:     ../mh.h
+adrformat.o:     ../adrparse.h
+adrformat.o:     /usr/include/ctype.h
+adrparse.o:      /usr/include/stdio.h
+#adrparse.o:      /usr/include/whoami.h
+adrparse.o:      ../mh.h
+adrparse.o:      ../adrparse.h
+#adrparse.o:      /usr/include/imp.h
+adrparse.o:      /usr/include/ctype.h
+ali.o:   ../mh.h
+ali.o:   /usr/include/stdio.h
+ali.o:   /usr/include/ctype.h
+ali.o:   /usr/include/pwd.h
+ali.o:   /usr/include/sys/types.h
+comp.o:  ../mh.h
+comp.o:  /usr/include/stdio.h
+#comp.o:  /usr/include/strings.h
+comp.o:  /usr/include/signal.h
+conflict.o:      /usr/include/stdio.h
+conflict.o:      /usr/include/ctype.h
+conflict.o:      /usr/include/pwd.h
+conflict.o:      /usr/include/grp.h
+conflict.o:      /usr/include/sys/types.h
+conflict.o:      /usr/include/sys/dir.h
+conflict.o:      ../mh.h
+#conflict.o:      /usr/include/mailsys.h
+#deliver.o:       /usr/include/whoami.h
+deliver.o:       ../mh.h
+deliver.o:       ../adrparse.h
+deliver.o:       /usr/include/stdio.h
+deliver.o:       /usr/include/ctype.h
+deliver.o:       /usr/include/pwd.h
+deliver.o:       /usr/include/sys/types.h
+deliver.o:       /usr/include/sys/timeb.h
+deliver.o:       /usr/include/sys/stat.h
+deliver.o:       /usr/include/signal.h
+#deliver.o:       /usr/include/strings.h
+#deliver.o:       /usr/include/mailsys.h
+deliver.o:       /usr/include/time.h
+dist.o:  ../mh.h
+dist.o:  /usr/include/stdio.h
+dist.o:  /usr/include/signal.h
+#dist.o:  /usr/include/strings.h
+dist.o:  /usr/include/sys/types.h
+dist.o:  /usr/include/sys/stat.h
+file.o:  ../mh.h
+file.o:  ../folder.h
+file.o:  /usr/include/stdio.h
+folder.o:        ../mh.h
+folder.o:        /usr/include/stdio.h
+folder.o:        /usr/include/sys/types.h
+folder.o:        /usr/include/sys/stat.h
+#folder.o:        /usr/include/strings.h
+forw.o:  ../mh.h
+forw.o:  /usr/include/stdio.h
+forw.o:  /usr/include/signal.h
+#forw.o:  /usr/include/strings.h
+forw.o:  /usr/include/sys/types.h
+forw.o:  /usr/include/sys/stat.h
+inc.o:   ../mh.h
+inc.o:   /usr/include/stdio.h
+inc.o:   /usr/include/sys/types.h
+inc.o:   /usr/include/sys/stat.h
+inc.o:   /usr/include/errno.h
+#inc.o:   /usr/include/strings.h
+inc.o:   /usr/include/signal.h
+inc.o:   scansub.h
+install-mh.o:    ../mh.h
+install-mh.o:    /usr/include/stdio.h
+install-mh.o:    /usr/include/sys/types.h
+install-mh.o:    /usr/include/sys/stat.h
+mail.o:  ../mh.h
+mail.o:  /usr/include/stdio.h
+mail.o:  /usr/include/signal.h
+mhl.o:   /usr/include/ctype.h
+mhl.o:   /usr/include/signal.h
+mhl.o:   /usr/include/setjmp.h
+mhl.o:   /usr/include/sgtty.h
+mhl.o:   /usr/include/stdio.h
+mhl.o:   ../mh.h
+mhpath.o:        ../mh.h
+mhpath.o:        /usr/include/stdio.h
+#mhpath.o:        /usr/include/strings.h
+mhpath.o:        /usr/include/ctype.h
+news.o:  ../mh.h
+news.o:  /usr/include/stdio.h
+news.o:  /usr/include/sys/types.h
+news.o:  /usr/include/sys/stat.h
+news.o:  /usr/include/sys/dir.h
+#news.o:  /usr/include/strings.h
+news.o:  /usr/include/sys/timeb.h
+next.o:  ../mh.h
+next.o:  /usr/include/stdio.h
+#next.o:  /usr/include/strings.h
+pick.o:  ../mh.h
+pick.o:  ../folder.h
+pick.o:  /usr/include/stdio.h
+pick.o:  /usr/include/signal.h
+pick.o:  /usr/include/sys/types.h
+pick.o:  /usr/include/sys/stat.h
+prompter.o:      ../mh.h
+prompter.o:      /usr/include/stdio.h
+prompter.o:      /usr/include/errno.h
+prompter.o:      /usr/include/sgtty.h
+prompter.o:      /usr/include/signal.h
+#prompter.o:      /usr/include/strings.h
+#repl.o:  /usr/include/whoami.h
+repl.o:  ../mh.h
+repl.o:  /usr/include/stdio.h
+repl.o:  /usr/include/signal.h
+#repl.o:  /usr/include/strings.h
+repl.o:  /usr/include/sys/types.h
+repl.o:  /usr/include/sys/stat.h
+repl.o:  ../adrparse.h
+rmail.o:         ../mh.h
+#rmail.o:         /usr/include/whoami.h
+rmail.o:         /usr/include/stdio.h
+rmail.o:         /usr/include/sys/types.h
+rmail.o:         /usr/include/sys/timeb.h
+rmail.o:         /usr/include/time.h
+rmf.o:   ../mh.h
+rmf.o:   /usr/include/stdio.h
+#rmf.o:   /usr/include/strings.h
+rmm.o:   ../mh.h
+rmm.o:   /usr/include/stdio.h
+#rmm.o:   /usr/include/strings.h
+scan.o:  ../mh.h
+scan.o:  /usr/include/stdio.h
+#scan.o:  /usr/include/strings.h
+scan.o:  scansub.h
+scansub.o:       ../mh.h
+#scansub.o:       /usr/include/whoami.h
+scansub.o:       /usr/include/stdio.h
+scansub.o:       /usr/include/ctype.h
+scansub.o:       /usr/include/time.h
+scansub.o:       ../adrparse.h
+scansub.o:       scansub.h
+send.o:  ../mh.h
+send.o:  /usr/include/stdio.h
+send.o:  /usr/include/sys/types.h
+send.o:  /usr/include/stat.h
+#send.o:  /usr/include/strings.h
+send.o:  /usr/include/signal.h
+show.o:  ../mh.h
+show.o:  /usr/include/stdio.h
+#show.o:  /usr/include/strings.h
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/progs/Makefile.bak b/docs/historical/mh-jun-1982/progs/Makefile.bak
new file mode 100644 (file)
index 0000000..99d5da7
--- /dev/null
@@ -0,0 +1,415 @@
+#
+#       Proprietary Rand Corporation, 1981.
+#       Further distribution of this software
+#       subject to the terms of the Rand
+#       license agreement.
+#
+
+#                       Remove the -DRAND elsewhere!
+# In ../mh.h: define ARPANET if you are on the arpanet.
+# In ../mh.h: define VMUNIX if you are running a berkeley system
+JOBSLIB=#-ljobs
+
+CFLAGS  = -O $(A)  # -m -DRAND
+# The following two must match entry in ../Makefile
+BINDIR  = /usr/local
+MHDIR   = /etc/mh
+MHTMP   = /usr/tmp/mh
+LOCKDIR = /usr/spool/locks
+NETDIR  = /usr/spool/netmail
+
+SUBS    = ../subs/subs.a
+STRINGS = ../strings/strings.a
+
+LINT    = lint
+
+# The 'dist' program is not ready yet, and so is not listed in the CMDS
+# See also ../man/Makefile
+CMDS    = \
+ali \
+comp \
+file \
+folder \
+forw \
+inc \
+mail \
+mhpath \
+next \
+news \
+pick \
+prev \
+prompter \
+repl \
+rmf \
+rmm \
+scan \
+send \
+show
+
+MISC    = \
+conflict \
+deliver \
+install-mh \
+mhl
+
+PROGS = $(CMDS) $(MISC) rmail
+
+CFILES  = \
+adrformat.c \
+adrparse.c \
+ali.c \
+comp.c \
+conflict.c \
+deliver.c \
+dist.c \
+file.c \
+folder.c \
+forw.c \
+inc.c \
+install-mh.c \
+mail.c \
+mhl.c \
+mhpath.c \
+news.c \
+next.c \
+pick.c \
+prompter.c \
+repl.c \
+rmail.c \
+rmf.c \
+rmm.c \
+scan.c \
+scansub.c \
+send.c \
+show.c
+
+progs:  $(PROGS)
+
+ali:    ali.o $(SUBS)
+       $(CC) -o ali ali.o $(SUBS)
+
+comp:   comp.o $(SUBS) $(STRINGS)
+       $(CC) -o comp comp.o $(SUBS) $(STRINGS)
+
+conflict: conflict.o $(SUBS)
+       $(CC) -o conflict conflict.o $(SUBS)
+
+deliver: deliver.o adrparse.o adrformat.o $(SUBS) $(STRINGS)
+       $(CC) -o deliver deliver.o adrparse.o adrformat.o $(SUBS) $(STRINGS)\
+       $(JOBSLIB)
+
+dist:   dist.o annotate.o $(SUBS) $(STRINGS)
+       $(CC) -o dist dist.o annotate.o $(SUBS) $(STRINGS)
+
+file:   file.o $(SUBS) $(STRINGS)
+       $(CC) -o file file.o $(SUBS) $(STRINGS)
+
+folder: folder.o $(SUBS) $(STRINGS)
+       $(CC) -o folder folder.o $(SUBS) $(STRINGS)
+
+forw:   forw.o annotate.o $(SUBS) $(STRINGS)
+       $(CC) -o forw forw.o annotate.o $(SUBS) $(STRINGS)
+
+inc:    inc.o scansub.o $(SUBS) $(STRINGS)
+       $(CC) -o inc inc.o scansub.o $(SUBS) $(STRINGS)
+
+install-mh: install-mh.o $(SUBS) $(STRINGS)
+       $(CC) -o install-mh install-mh.o $(SUBS) $(STRINGS)
+
+mail:   mail.o $(SUBS) $(STRINGS)
+       $(CC) -o mail mail.o $(SUBS) $(STRINGS)
+
+mhpath: mhpath.o $(SUBS) $(STRINGS)
+       $(CC) -o mhpath mhpath.o $(SUBS) $(STRINGS)
+
+mhl:    mhl.o $(SUBS) $(STRINGS)
+       $(CC) -o mhl mhl.o $(SUBS) $(STRINGS)
+
+news:   news.o $(SUBS) $(STRINGS)
+       $(CC) -o news news.o $(SUBS) $(STRINGS)
+
+next:   nexthdr.o next.o $(SUBS) $(STRINGS)
+       $(CC) -o next nexthdr.o next.o $(SUBS) $(STRINGS)
+
+pick:   pick.o grep.o $(SUBS) $(STRINGS)
+       $(CC) -o pick pick.o grep.o $(SUBS) $(STRINGS)
+
+prev:   prevhdr.o next.o $(SUBS) $(STRINGS)
+       $(CC) -o prev prevhdr.o next.o $(SUBS) $(STRINGS)
+
+prompter: prompter.o $(SUBS) $(STRINGS)
+       $(CC) -o prompter prompter.o $(SUBS) $(STRINGS)
+
+repl:   repl.o annotate.o adrparse.o adrformat.o $(SUBS) $(STRINGS)
+       $(CC) -o repl repl.o annotate.o adrparse.o adrformat.o $(SUBS) $(STRINGS)
+
+rmail:  rmail.o  $(SUBS) $(STRINGS)
+       $(CC) -o rmail rmail.o  $(SUBS) $(STRINGS)
+
+rmf:    rmf.o $(SUBS) $(STRINGS)
+       $(CC) -o rmf rmf.o $(SUBS) $(STRINGS)
+
+rmm:    rmm.o $(SUBS) $(STRINGS)
+       $(CC) -o rmm rmm.o $(SUBS) $(STRINGS)
+
+scan:   scan.o scansub.o $(SUBS) $(STRINGS)
+       $(CC) -o scan scan.o scansub.o $(SUBS) $(STRINGS)
+
+send:   send.o $(SUBS) $(STRINGS)
+       $(CC) -o send send.o $(SUBS) $(STRINGS)
+
+show:   show.o $(SUBS) $(STRINGS)
+       $(CC) -o show show.o $(SUBS) $(STRINGS)
+
+lint:
+       -$(LINT) ali.c -v ../subs/subs-lc | tee ali.lint
+       -$(LINT) comp.c -v ../subs/subs-lc | tee comp.lint
+       -$(LINT) conflict.c -v ../subs/subs-lc | tee conflict.lint
+       -$(LINT) deliver.c adrparse.c adrformat.c -v ../subs/subs-lc | tee deliver.lint
+       -$(LINT) dist.c -v ../subs/subs-lc | tee dist.lint
+       -$(LINT) file.c -v ../subs/subs-lc | tee file.lint
+       -$(LINT) folder.c -v ../subs/subs-lc | tee folder.lint
+       -$(LINT) forw.c annotate.c -v ../subs/subs-lc | tee forw.lint
+       -$(LINT) inc.c scansub.c -v ../subs/subs-lc | tee inc.lint
+       -$(LINT) install-mh.c -v ../subs/subs-lc | tee install.lint
+       -$(LINT) mail.c -v ../subs/subs-lc | tee mail.lint
+       -$(LINT) mhl.c -v ../subs/subs-lc | tee mhl.lint
+       -$(LINT) mhpath.c -v ../subs/subs-lc | tee mhpath.lint
+       -$(LINT) news.c -v ../subs/subs-lc | tee news.lint
+       -$(LINT) pick.c -v ../subs/subs-lc | tee pick.lint
+       -$(LINT) prevhdr.c next.c -v ../subs/subs-lc | tee prev.lint
+       -$(LINT) prompter.c -v ../subs/subs-lc | tee prompter.lint
+       -$(LINT) repl.c replsubs.c -v ../subs/subs-lc | tee repl.lint
+       -$(LINT) rmf.c -v ../subs/subs-lc | tee rmf.lint
+       -$(LINT) rmm.c -v ../subs/subs-lc | tee rmm.lint
+       -$(LINT) scan.c scansub.c -v ../subs/subs-lc | tee scan.lint
+       -$(LINT) show.c -v ../subs/subs-lc | tee show.lint
+
+install: strip installprogs
+       -mkdir $(MHTMP)
+       chmod 777 $(MHTMP)
+       -mkdir $(MHDIR)
+       -mkdir $(LOCKDIR)
+       -mkdir $(NETDIR)
+       -chmod a+x $(MISC)
+       -cd $(MHDIR); rm -f $(MISC)
+       -cp $(MISC) $(MHDIR)
+       echo Now become root and \'make installroot\'
+
+installprogs:
+       -chmod a+x $(PROGS)
+       -cd $(BINDIR); rm -f $(CMDS) folders
+       -cp $(CMDS) $(BINDIR)
+       -cd $(BINDIR); ln folder folders
+
+installroot:
+       -cd $(BINDIR); chmod a+x $(CMDS)
+       -cd $(MHDIR); chmod a+x $(MISC)
+       /etc/chown root $(NETDIR)
+       chmod 755  $(NETDIR)
+       -rm -f /bin/rmail
+       /etc/chown root $(LOCKDIR)
+       chmod 777  $(LOCKDIR)
+       -cp rmail /bin
+#           Setuid and Setgid:
+       -chmod 6755 /bin/rmail
+#           Sticky Bit & Setgid:   (?Setuid? PK)
+       -/etc/chown root $(MHDIR)/deliver;chmod 5755 $(MHDIR)/deliver
+#           Sticky Bit:
+       -chmod 1755 $(BINDIR)/comp
+       -chmod 1755 $(BINDIR)/inc
+       -chmod 1755 $(BINDIR)/next
+       -chmod 1755 $(BINDIR)/prompter
+       -chmod 1755 $(BINDIR)/show
+
+uninstall:
+       -rmdir $(MHTMP)
+       -cd $(MHDIR); rm -f $(MISC)
+       -cd $(BINDIR); rm -f $(CMDS) folders
+
+strip:
+       -strip $(PROGS)
+
+chmod:
+       chmod a+x $(PROGS)
+
+pinstall:
+       -install -s comp $(BINDIR)/comp
+       -install -s file $(BINDIR)/file
+       -install -s folder $(BINDIR)/folder
+       -install -s forw $(BINDIR)/forw
+       -install -s inc $(BINDIR)/inc
+       -install -s mhl $(MHDIR)/mhl
+       -install -s mhpath $(BINDIR)/mhpath
+       -install -s next $(BINDIR)/next
+       -install -s pick $(BINDIR)/pick
+       -install -s prev $(BINDIR)/prev
+       -install -s prompter $(BINDIR)/prompter
+       -install -s repl $(BINDIR)/repl
+       -install -s rmf $(BINDIR)/rmf
+       -install -s rmm $(BINDIR)/rmm
+       -install -s scan $(BINDIR)/scan
+       -install -s send $(BINDIR)/send
+       -install -s show $(BINDIR)/show
+
+distribution:   clean rmprogs
+
+rmprogs:
+       -rm -f $(PROGS)
+
+clean:
+       -rm -f *.o *.lint
+
+depend:
+       ../misc/depend.sh $(CFILES)
+
+
+###DEPENDENCIES Follow.  Do not delete this line
+adrformat.o:    /usr/include/stdio.h
+adrformat.o:    ../mh.h
+adrformat.o:    ../adrparse.h
+adrformat.o:    /usr/include/ctype.h
+adrparse.o:     /usr/include/stdio.h
+adrparse.o:     /usr/include/whoami.h
+adrparse.o:     ../mh.h
+adrparse.o:     ../adrparse.h
+adrparse.o:     /usr/include/imp.h
+adrparse.o:     /usr/include/ctype.h
+ali.o:  ../mh.h
+ali.o:  /usr/include/stdio.h
+ali.o:  /usr/include/ctype.h
+ali.o:  /usr/include/pwd.h
+ali.o:  /usr/include/sys/types.h
+comp.o:         ../mh.h
+comp.o:         /usr/include/stdio.h
+comp.o:  /usr/include/strings.h
+comp.o:         /usr/include/signal.h
+conflict.o:     /usr/include/stdio.h
+conflict.o:     /usr/include/ctype.h
+conflict.o:     /usr/include/pwd.h
+conflict.o:     /usr/include/grp.h
+conflict.o:     /usr/include/sys/types.h
+conflict.o:     /usr/include/sys/dir.h
+conflict.o:     ../mh.h
+conflict.o:     /usr/include/mailsys.h
+deliver.o:      /usr/include/whoami.h
+deliver.o:      ../mh.h
+deliver.o:      ../adrparse.h
+deliver.o:      /usr/include/stdio.h
+deliver.o:      /usr/include/ctype.h
+deliver.o:      /usr/include/pwd.h
+deliver.o:      /usr/include/sys/types.h
+deliver.o:      /usr/include/sys/timeb.h
+deliver.o:      /usr/include/sys/stat.h
+deliver.o:      /usr/include/signal.h
+deliver.o:       /usr/include/strings.h
+deliver.o:      /usr/include/mailsys.h
+deliver.o:      /usr/include/time.h
+dist.o:         ../mh.h
+dist.o:         /usr/include/stdio.h
+dist.o:         /usr/include/signal.h
+dist.o:  /usr/include/strings.h
+dist.o:         /usr/include/sys/types.h
+dist.o:         /usr/include/sys/stat.h
+file.o:         ../mh.h
+file.o:         ../folder.h
+file.o:         /usr/include/stdio.h
+folder.o:       ../mh.h
+folder.o:       /usr/include/stdio.h
+folder.o:       /usr/include/sys/types.h
+folder.o:       /usr/include/sys/stat.h
+folder.o:        /usr/include/strings.h
+forw.o:         ../mh.h
+forw.o:         /usr/include/stdio.h
+forw.o:         /usr/include/signal.h
+forw.o:  /usr/include/strings.h
+forw.o:         /usr/include/sys/types.h
+forw.o:         /usr/include/sys/stat.h
+inc.o:  ../mh.h
+inc.o:  /usr/include/stdio.h
+inc.o:  /usr/include/sys/types.h
+inc.o:  /usr/include/sys/stat.h
+inc.o:  /usr/include/errno.h
+inc.o:   /usr/include/strings.h
+inc.o:  /usr/include/signal.h
+inc.o:  scansub.h
+install-mh.o:   ../mh.h
+install-mh.o:   /usr/include/stdio.h
+install-mh.o:   /usr/include/sys/types.h
+install-mh.o:   /usr/include/sys/stat.h
+mail.o:         ../mh.h
+mail.o:         /usr/include/stdio.h
+mail.o:         /usr/include/signal.h
+mhl.o:  /usr/include/ctype.h
+mhl.o:  /usr/include/signal.h
+mhl.o:  /usr/include/setjmp.h
+mhl.o:  /usr/include/sgtty.h
+mhl.o:  /usr/include/stdio.h
+mhl.o:  ../mh.h
+mhpath.o:       ../mh.h
+mhpath.o:       /usr/include/stdio.h
+mhpath.o:        /usr/include/strings.h
+mhpath.o:       /usr/include/ctype.h
+news.o:         ../mh.h
+news.o:         /usr/include/stdio.h
+news.o:         /usr/include/sys/types.h
+news.o:         /usr/include/sys/stat.h
+news.o:         /usr/include/sys/dir.h
+news.o:  /usr/include/strings.h
+news.o:         /usr/include/sys/timeb.h
+next.o:         ../mh.h
+next.o:         /usr/include/stdio.h
+next.o:  /usr/include/strings.h
+pick.o:         ../mh.h
+pick.o:         ../folder.h
+pick.o:         /usr/include/stdio.h
+pick.o:         /usr/include/signal.h
+pick.o:         /usr/include/sys/types.h
+pick.o:         /usr/include/sys/stat.h
+prompter.o:     ../mh.h
+prompter.o:     /usr/include/stdio.h
+prompter.o:     /usr/include/errno.h
+prompter.o:     /usr/include/sgtty.h
+prompter.o:     /usr/include/signal.h
+prompter.o:      /usr/include/strings.h
+repl.o:         /usr/include/whoami.h
+repl.o:         ../mh.h
+repl.o:         /usr/include/stdio.h
+repl.o:         /usr/include/signal.h
+repl.o:  /usr/include/strings.h
+repl.o:         /usr/include/sys/types.h
+repl.o:         /usr/include/sys/stat.h
+repl.o:         ../adrparse.h
+rmail.o:        ../mh.h
+rmail.o:        /usr/include/whoami.h
+rmail.o:        /usr/include/stdio.h
+rmail.o:        /usr/include/sys/types.h
+rmail.o:        /usr/include/sys/timeb.h
+rmail.o:        /usr/include/time.h
+rmf.o:  ../mh.h
+rmf.o:  /usr/include/stdio.h
+rmf.o:   /usr/include/strings.h
+rmm.o:  ../mh.h
+rmm.o:  /usr/include/stdio.h
+rmm.o:   /usr/include/strings.h
+scan.o:         ../mh.h
+scan.o:         /usr/include/stdio.h
+scan.o:  /usr/include/strings.h
+scan.o:         scansub.h
+scansub.o:      ../mh.h
+scansub.o:      /usr/include/whoami.h
+scansub.o:      /usr/include/stdio.h
+scansub.o:      /usr/include/ctype.h
+scansub.o:      /usr/include/time.h
+scansub.o:      ../adrparse.h
+scansub.o:      scansub.h
+send.o:         ../mh.h
+send.o:         /usr/include/stdio.h
+send.o:         /usr/include/sys/types.h
+send.o:         /usr/include/stat.h
+send.o:  /usr/include/strings.h
+send.o:         /usr/include/signal.h
+show.o:         ../mh.h
+show.o:         /usr/include/stdio.h
+show.o:  /usr/include/strings.h
+show.o:
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/progs/UUCP.MEMO b/docs/historical/mh-jun-1982/progs/UUCP.MEMO
new file mode 100644 (file)
index 0000000..94518cb
--- /dev/null
@@ -0,0 +1,133 @@
+      Several changes have been made recently, primarily to
+adrparse.c, adrformat.c, deliver.c, rmail.c,  and repl.c.  
+These changes permit MH messages to flow between the host
+machine, the Arpanet, and the UUCP system.  A description
+of how all this works is included here.
+
+A. SENDING MAIL
+
+1) Arpanet mail.  When a message is destined for the Arpanet,
+   a single copy of that message is placed in /usr/spool/netmail,
+   headed by a list of remote recipients.  A mailer daemon
+   picks these up and delivers them via the FTP "MAIL" command.
+   If the local site is NOT an Arpanet site, the Arpanet address
+   is simply considered as a local address.  One could, conceivably,
+   have a local user named "a@ucla-s", after all.
+
+2) UUCP mail.  As DELIVER is processing the message, it is producing
+   a SECOND copy of the message in /usr/tmp/mh/uu*.  This copy
+   differs from the normally-delivered copy in that no "format"
+   operation is ever done, and in that no "From: " line is
+   added to the header (the user may still have one if he
+   thinks he knows what he's doing).  For each message destined
+   for a UUCP site, say "site!person", a header is prepended
+   of the form "From <local-user> <date> remote from <local-site>".
+   This message is then given as standard input to a command
+   like "uux - site!rmail person".  Note that "person" may not
+   contain blanks.  If it contains additional uucp routing,
+   the form is "uux - site!rmail (more!person)".  Evidently,
+   without the parens, Uux considers "more!person" to be
+   the name of a remote file.
+
+B. RECEIVING MAIL
+
+1) Arpanet Mail.  Mail from the Arpanet is received by the
+   FTP Server daemon via the MAIL (or MLFL) command.  At
+   present, this server invokes the "rmail" program, which
+   purports to be the name of the standard Unix remote mail
+   program.  Supposedly, this would even work on a system
+   not running MH or anything special.  Right.  Anyhow,
+   the Rmail associated with MH copies its input into a
+   file and gives that file to Deliver, with the special
+   option, "-deliverto <recipient>".  This option is
+   reserved to the super-user and members of Uucp's
+   group (constant DAEMON_GROUP in deliver.c .  It varies
+   between the /45 and the Vax, unfortunately).  If
+   it were not so restricted, anybody could send mail
+   with forged signatures ("From: " lines).  When
+   Deliver is given that option, it does nothing but
+   deliver the file as it sees it to the specified
+   recipient, be it local or remote.  No formatting
+   or additional "From:" or "Date" processing is 
+   performed, although Uucp "From" lines ARE added if needed.
+
+2) UUCP mail.  As noted, Uucp mail happens when some
+   remote site executes Rmail via Uux.  Out there
+   in the real world, the only thing you can expect
+   a message to have is one of those "From <user> <date>"
+   lines at the beginning.  Perhaps several, if 
+   it's been through this process before.  Rmail is
+   able to take these lines and turn them into
+   a sensible line like "From: site1!site2!site3!person".
+   If a reasonable Arpa header follows (and it's pretty
+   crude about "reasonable"), Rmail just prepends that
+   From: line and copies the input into a file and
+   gives it to Deliver as in the Arpanet case.  If not,
+   it adds an extra blank line, thus leaving you
+   with a header consisting of just the From: line.
+   Deliver then sends the formatted-as-best-we-could
+   message to the specified recipient.  
+   In the special case in which the destination is
+   another Uucp site (rmail sitex!person), NO processing
+   is done before invoking Deliver; Deliver will 
+   add the obligatory extra "From" line at the beginning
+   of the Uucp output.
+
+KNOWN problems.  
+
+   When mail is going to somewhere like "graphics!person",
+   and there are "cc:" lines, these "cc:" lines are not
+   formatted in such a way as to allow automatic replies.
+   Note that they would have to be different for local
+   users than they would be for the remote user.
+
+   Similarly, when a message gets sent to someone like
+   "graphics!mike@ucla-s", the "To: " line is going to
+   contain that "graphics!" when it gets to the remote
+   Arpanet site.  This will be wrong, there.  Note again
+   that local users getting a carbon copy will want
+   that information to appear.
+
+   When a message comes from the Arpanet and gets forwarded
+   to Uucp, it arrives at the destination site with
+   a Uucp-style "From xxx remote from yyy" line at the
+   beginning, and an ARPA-style "From: " line which was
+   generated at the original site.  Rmail will cause
+   you to end up with two Arpa-style From lines,
+   "From: yyy!xxx" and the original one.  Repl will be
+   able to start up OK, and will try to reply to both.
+   Unfortunately, NEITHER will be right.  This is rather
+   difficult to fix without modifying the original Arpa
+   header.  Impossible, in fact.
+
+   You can send messages to graphics!person@host.  However
+   if you try to send it to "graphics!person at host", you
+   will indeed execute "graphics!rmail person at host".  
+   This will cause Rmail to choke (too many args).  You never
+   get to hear about it when Uux chokes.
+
+   In general, Rmail should make a better effort to see if
+   things went OK, and send a return message if they didn't.
+   Similarly, the FTP server should make sure Rmail died 
+   happy, and reply with a failure code (412 or something,
+   isn't it?)  when things don't run smoothly.  The
+   Arpanet Mailer, by the way, is pretty good about reporting
+   its failures.  
+
+   Replying to messages from various sources works pretty well.
+   However, people who try to invoke the "-format" option 
+   when no Arpanet is present currently get a screwy result
+   like "at (local)" getting glued to the end of addresses.
+   Frankly, the "format" option should be completely disabled
+   at non-Arpa sites, as near as I can tell.  This applies
+   both to "repl" as well as "send" (deliver).  
+
+   While "Ali" has been changed to understand that Uucp and
+   Arpanet addresses should not be checked for validity,
+   there are common subroutines in Ali and Deliver which
+   are Very Similar, though their calling sequences and
+   usages vary somewhat.  It would be Aesthetically Preferable
+   to break these routines out and put them in "subs".
+
+       Mike Urban
+       3/81
diff --git a/docs/historical/mh-jun-1982/progs/adrformat.c b/docs/historical/mh-jun-1982/progs/adrformat.c
new file mode 100644 (file)
index 0000000..f474027
--- /dev/null
@@ -0,0 +1,68 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include <stdio.h>
+#include "../mh.h"
+#include "../adrparse.h"
+#include <ctype.h>
+
+extern char *sprintf();
+
+char *
+adrformat(mp,hostname)
+       register struct mailname *mp;
+       register char *hostname;
+{
+       static char buf[512];
+       register char *tp, *cp, *sp;
+
+       for(tp = buf, cp = mp->m_text;*cp ;cp++ ) {
+               if(cp == mp->m_at) {
+                       if(*cp == '@') {
+                               if(cp[-1] != ' ')
+                                       *tp++ = ' ';
+                               *tp++ = 'a';
+                               *tp++ = 't';
+                               if(cp[1] != ' ')
+                                       *tp++ = ' ';
+                               continue;
+                       }
+               }
+               if((cp == mp->m_hs) && (*mp->m_at != '!')){
+                       if(sp = stdhost(mp->m_hnum)) {
+                               while(*sp)
+                                       *tp++ = islower(*sp) ?
+                                               toupper(*sp++) : *sp++;
+                               cp = mp->m_he;
+                               continue;
+                       } else {
+                               fprintf(stderr, "adrformat: bad host!?\n");
+                               return NULL;
+                       }
+               }
+               *tp++ = *cp;
+       }
+       if(mp->m_nohost)
+               VOID sprintf(tp, " at %s", !mp->m_at? mp->m_host: hostname);
+               /* This probably only needs "hostname" unconditionally */
+       else
+               *tp = 0;
+       return buf;
+}
+
+
+char *
+stdhost(num)
+       long num;
+{
+       register struct hosts *hp;
+
+       for(hp = hosts.nh_next; hp; hp = hp->nh_next)
+               if(num == hp->nh_num)
+                       return hp->nh_name;
+       return 0;
+}
diff --git a/docs/historical/mh-jun-1982/progs/adrparse.c b/docs/historical/mh-jun-1982/progs/adrparse.c
new file mode 100644 (file)
index 0000000..e64284e
--- /dev/null
@@ -0,0 +1,291 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include <stdio.h>
+#include <whoami.h>
+#include "../mh.h"
+#include "../adrparse.h"
+
+extern char *strcpy(), *strncpy();
+
+#ifndef ARPANET
+#define HOSTTBL "/dev/null"
+#else
+#include <imp.h>
+#endif
+#include <ctype.h>
+
+char *malloc(), *calloc(), *getncpy();
+
+
+char *
+getname(addrs)
+       char *addrs;
+{
+       register char *tp;
+       static char name[256];
+       static char *getaddrs;
+
+       if(!getaddrs)
+               getaddrs = addrs;
+       tp = name;
+
+       while(*getaddrs && isspace(*getaddrs))
+               getaddrs++;
+       if(!*getaddrs) {
+               getaddrs = 0;
+               return NULL;
+       }
+       while(*getaddrs && *getaddrs != ',') {
+               if(isspace(*getaddrs))
+                       *tp++ = ' ';
+               else
+                       *tp++ = *getaddrs;
+               getaddrs++;
+       }
+       if(*getaddrs) getaddrs++;
+       *tp = 0;
+       while(isspace(tp[-1]) && tp > name)
+               *--tp = 0;
+       tp = name;
+       while(*tp == ' ' || *tp == '\t')
+               tp++;
+       if(*tp == 0)
+               return NULL;
+       return tp;
+}
+
+
+struct mailname *
+getm(str, defaulthost)         /* WHY isn't it just taken from HOSTNAME?*/
+                               /* Answer: REPLY uses foreign site */
+       char *str;
+       char *defaulthost;
+{
+       register char *cp;
+       register char *mbp = 0, *mbe = 0;
+       register char *hp = 0, *he = 0;
+       register struct mailname *mp;
+       int lbrkt = 0;
+
+       if(!hosts.nh_next)
+               gethosts();
+       mp = (struct mailname *) calloc(1, sizeof *mp);
+       mp->m_headali = "";
+       mp->m_text = cp = getcpy(str);
+       while(*cp) {
+           switch(*cp) {
+#ifdef FOO
+               case '"':
+                       if(!mbp) mbp = cp;
+                       do {
+                               cp++;
+                       } while(*cp && *cp != '"');
+                       break;
+#endif
+               case '<':
+                       mbp = mbe = hp = he = mp->m_at = 0;
+                       lbrkt++;
+                       break;
+               case '>':
+                       if(!lbrkt) {
+                               fprintf(stderr, "adrparse: extraneous '>'\n");
+                               goto line;
+                       }
+                       if(mbp && !mbe) {
+                               fprintf(stderr, "adrparse: Missing host within <> spec.\n");
+                               goto line;
+                       } else if(hp && !he)
+                               he = cp - 1;
+                       goto gotaddr;
+               case ' ': if(!HOSTNUM) break;
+                       if(strncmp(cp, " at ", 4) == 0 ||
+                          strncmp(cp, " At ", 4) == 0 ||
+                          strncmp(cp, " AT ", 4) == 0) {
+                               cp++;
+                  at:          if (!HOSTNUM)break;     /* Host 0 means no arpanet */
+                               if(!mbp) {
+                                       fprintf(stderr, "adrparse: at without mbox\n");
+                                       goto line;
+                               }
+                               if(!mbe)
+                                       mbe = cp - 1;
+                               if(mp->m_at) {
+                                   if (*mp->m_at == '!')
+                                       mbp = hp;     /* uusite!person@site */
+                                   else
+                                       mbe = cp - 1;   /* [x!]y@q@z */
+                               }
+                               mp->m_at = cp;
+                               if(*cp != '@')
+                                       cp += 2;
+                               hp = he = 0;
+                       }
+                       break;
+               case '@':
+                       goto at;
+               case '!':                               /* uusite!otherstuff */
+                       if (!mbp && !hp) break; /* Ignore leading '!'s */
+                       if(mbp && !hp) {        /* No other '!'s so far...*/
+                               hp=mbp;                 /* Host name */
+                               he=cp-1;
+
+                               mbp = 0;
+                               mp->m_at = cp;
+                       }
+                       break;
+               case '(':
+                       if(mbp && !mbe)
+                               mbe = cp - 1;
+                       else if(hp && !he)
+                               he = cp - 1;
+                       while(*cp && *cp != ')') cp++;
+                       break;
+               default:
+                       if(isalnum(*cp) || *cp == '-' || *cp == '.' ||
+                           *cp == '_') {
+                               if(!mbp)
+                                       mbp = cp;
+                               else if(mp->m_at && !hp)
+                                       hp = cp;
+                       } else {
+                               fprintf(stderr, "adrparse: address err: %s\n", cp);
+                               goto line;
+                       }
+                       break;
+           }
+           cp++;
+       }
+gotaddr:
+       if(mbp && !mbe)
+               mbe = cp - 1;
+       else if(hp && !he)
+               he = cp - 1;
+       if(!mp->m_at) {
+               if(hp) {
+                       fprintf(stderr, "adrparse: HUH? host wo @\n");
+                       return(0);
+               }
+               mp->m_nohost++;
+               if(defaulthost == 0) {
+                       fprintf(stderr, "adrparse: Missing host\n");
+                       return(0);
+               }
+               mp->m_host = getcpy(defaulthost);
+       } else {
+               while(*he == ' ') --he;
+               mp->m_host = getncpy(hp, he-hp+1);
+               mp->m_hs = hp;
+               mp->m_he = he;
+               if (*mp->m_at == '!')   /* It's a uucp addr, not arpa */
+                       mp->m_nohost++; /* So formatter will glue on local name*/
+       }
+       if(!mbp) {
+               fprintf(stderr, "adrparse: No mailbox: %s\n", str);
+               return(0);
+       }
+       while(*mbe == ' ') --mbe;
+       mp->m_mbox = getncpy(mbp, mbe-mbp+1);
+       if (*mp->m_at == '!')           /* Going out over UUCP */
+       {
+               mp->m_hnum = -1;        /* UUCP addresses are basically local*/
+               return mp;
+       }
+#ifndef ARPANET
+       mp->m_hnum = 0;
+       return mp;
+#else
+       if((mp->m_hnum = gethnum(mp->m_host)) == -1) {
+               fprintf(stderr, "adrparse: Unknown host: %s\n", mp->m_host);
+#endif
+      line:     fprintf(stderr, "adrparse: In address: %s\n", str);
+               return(0);
+#ifdef ARPANET
+       }
+       if(mp->m_at && (mp->m_hnum == HOSTNUM))
+               /* Local!  Try to reparse in case of UUCP address */
+       {
+               char localname[32];
+
+               strcpy(localname, mp->m_mbox);  /* not same struct */
+               mnfree(mp);
+               if((mp = getm(localname,HOSTNAME)) == 0)  /* Really local */
+                       return(0);
+       }
+       return mp;
+#endif
+}
+
+
+char *
+getncpy(str, len)
+       char *str;
+       int len;
+{
+       register char *cp;
+
+       cp = calloc(1, (unsigned)len + 1);
+       strncpy(cp, str, len);
+       return cp;
+}
+
+
+gethosts()
+{
+       register FILE *ht;
+       register struct hosts *hp = &hosts;
+       char buf[32], hostname[16];
+       int hn;
+
+       if((ht = fopen(HOSTTBL, "r")) == NULL) {
+hte:            perror(HOSTTBL);
+               exit(1);
+       }
+       while(fgets(buf, sizeof buf, ht)) {
+               if(sscanf(buf, "%o %s", &hn, hostname) != 2)
+                       goto hte;
+               hp->nh_next = (struct hosts *) calloc(1, sizeof *hp);
+               hp = hp->nh_next;
+               hp->nh_name = getcpy(hostname);
+               hp->nh_num = hn;
+       }
+       VOID fclose(ht);
+}
+
+long
+gethnum(host)
+       char *host;
+{
+       register struct hosts *hp;
+
+       for (hp = hosts.nh_next; hp; hp = hp->nh_next)
+               if(uleq(host, hp->nh_name))
+                       return hp->nh_num;
+       return -1;
+}
+
+
+mnfree(mn)
+       register struct mailname *mn;
+{
+       free(mn->m_mbox);
+       free(mn->m_host);
+       free(mn->m_text);
+       cndfree(mn->m_headali);
+       free((char *)mn);
+}
+
+#ifdef COMMENT
+/* Eventually we should do something more like this (from tn.c) */
+       if ((hnum>>24) == 0) {          /* Old format */
+               netparm.no_imp = hnum&077;
+               netparm.no_host = hnum>>6;
+       }
+       else {                          /* New format */
+               netparm.no_imp = hnum&0177777;
+               netparm.no_host = hnum>>16;
+       }
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/progs/ali.c b/docs/historical/mh-jun-1982/progs/ali.c
new file mode 100644 (file)
index 0000000..3c26c1c
--- /dev/null
@@ -0,0 +1,323 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+#include <stdio.h>
+#include <ctype.h>
+#include <pwd.h>
+#include <sys/types.h>
+
+extern char *index();
+
+#define EVERYONE 10
+
+struct shome {          /* Internal name/uid/home database */
+       struct shome *h_next;
+       char *h_name;
+       int   h_uid;
+       int   h_gid;
+       char *h_home;
+} *homes, *home();
+
+struct  mailname {
+       struct mailname *m_next;
+       char            *m_name;
+}  addrlist;
+
+char *malloc();
+
+extern  char _sobuf[];          /* MLW  standard out buffer */
+
+main(argc, argv)
+       char **argv;
+{
+       register int i, list = 0;
+       register struct mailname *lp;
+
+       invo_name = argv[0];
+       if(argc < 2) {
+               printf("Usage: ali [-l] name ...\n");
+               exit(1);
+       }
+       if(argc > 1 && strcmp(argv[1], "-l") == 0) {
+               list++;
+               argc--; argv++;
+       }
+       setbuf(stdout, _sobuf);
+       gethomes();
+       for(i = 1; i < argc; i++)
+               insert(argv[i]);
+       alias();                        /* Map names if needed */
+       for(lp = addrlist.m_next; lp; lp = lp->m_next) {
+               if(home(lp->m_name)) {
+                       if(list)
+                               printf("%s\n", lp->m_name);
+                       else {
+                               printf("%s%s", lp->m_name, lp->m_next?", ":"");
+                               if(stdout->_cnt < BUFSIZ - 65) {
+                                       printf("\n"); VOID fflush(stdout);
+                               }
+                       }
+               }
+       }
+       if(!list && stdout->_cnt && stdout->_cnt < BUFSIZ) {
+               printf("\n"); VOID fflush(stdout);
+       }
+       for(lp = addrlist.m_next; lp; lp = lp->m_next)
+               if(home(lp->m_name) == NULL)
+                       fprintf(stderr, "Ali: Unknown User: %s.\n", lp->m_name);
+
+}
+
+insert(name)
+       char *name;
+{
+       register struct mailname *mp;
+       char *getcpy();
+
+/***    printf("insert(%s)\n", name);   ***/
+
+       for(mp = &addrlist; mp->m_next; mp = mp->m_next)
+               if(uleq(name, mp->m_next->m_name))
+                       return;         /* Don't insert existing name! */
+       mp->m_next = (struct mailname *) malloc(sizeof *mp->m_next);
+       mp = mp->m_next;
+       mp->m_next = 0;
+       mp->m_name = getcpy(name);
+}
+
+gethomes()
+{
+       register struct passwd *pw;
+       register struct shome *h, *ph;
+       struct   passwd *getpwent();
+       char     *strcpy();
+
+       ph = (struct shome *) &homes;
+       while((pw = getpwent()) != NULL) {
+               h = (struct shome *) malloc(sizeof *h);
+               h->h_next = NULL;
+               h->h_name = malloc((unsigned)strlen(pw->pw_name)+1);
+               strcpy(h->h_name, pw->pw_name);
+               h->h_uid = pw->pw_uid;
+               h->h_gid = pw->pw_gid;
+               h->h_home = malloc((unsigned)strlen(pw->pw_dir)+1);
+               strcpy(h->h_home, pw->pw_dir);
+               ph->h_next = h;
+               ph = h;
+       }
+}
+
+struct shome *
+home(name)
+       register char *name;
+{
+       register struct shome *h;
+
+       if (index(name, '@') || 
+           index(name, ' ') ||
+           index(name, '!')) 
+               return (homes); /* WARNING! Depends on return value */
+                               /*              being indifferent!  */
+
+       for(h = homes; h; h = h->h_next)
+               if(uleq(name, h->h_name))
+                       return(h);
+       return(NULL);
+}
+
+aleq(string, aliasent)
+       register char *string, *aliasent;
+{
+       register int c;
+
+       while(c = *string++)
+               if(*aliasent == '*')
+                       return 1;
+               else if((c|040) != (*aliasent|040))
+                       return(0);
+               else
+                       aliasent++;
+       return(*aliasent == 0 | *aliasent == '*');
+}
+
+
+/* alias implementation below...
+ */
+
+
+
+#define GROUP   "/etc/group"
+char    *AliasFile =    "/etc/MailAliases";
+
+char *termptr;
+
+char *
+parse(ptr, buf)
+       register char *ptr;
+       char *buf;
+{
+       register char *cp;
+
+       cp = buf;
+       while(isspace(*ptr) || *ptr == ',' || *ptr == ':')
+               ptr++;
+       while(isalnum(*ptr) || *ptr == '/' || *ptr == '-' ||
+           *ptr == '!' || *ptr == '@' || *ptr == ' ' ||
+           *ptr == '.' || *ptr == '*')
+               *cp++ = *ptr++;
+       if(cp == buf) {
+               switch(*ptr) {
+               case '<':
+               case '=':
+                       *cp++ = *ptr++;
+               }
+       }
+       *cp = 0;
+       if(cp == buf)
+               return 0;
+       termptr = ptr;
+       return buf;
+}
+
+char *
+advance()
+{
+       return(termptr);
+}
+
+alias()
+{
+       register char *cp, *pp;
+       register struct mailname *lp;
+       char line[256], pbuf[64];
+       FILE *a;
+
+       if((a = fopen(AliasFile, "r")) == NULL) {
+               fprintf(stderr, "Can't open alias file ");
+               perror(AliasFile);
+               done(1);
+       }
+       while(fgets(line, sizeof line, a)) {
+               if(line[0] == ';' || line[0] == '\n')   /* Comment Line */
+                       continue;
+               if((pp = parse(line, pbuf)) == NULL) {
+           oops:       fprintf(stderr, "Bad alias file %s\n", AliasFile);
+                       fprintf(stderr, "Line: %s", line);
+                       done(1);
+               }
+               for(lp = &addrlist; lp->m_next; lp = lp->m_next) {
+                       if(aleq(lp->m_next->m_name, pp)) {
+                               remove(lp);
+                               if(!(cp = advance()) ||
+                                  !(pp = parse(cp, pbuf)))
+                                       goto oops;
+                               switch(*pp) {
+                               case '<':       /* From file */
+                                       cp = advance();
+                                       if((pp = parse(cp, pbuf)) == NULL)
+                                               goto oops;
+                                       addfile(pp);
+                                       break;
+                               case '=':       /* UNIX group */
+                                       cp = advance();
+                                       if((pp = parse(cp, pbuf)) == NULL)
+                                               goto oops;
+                                       addgroup(pp);
+                                       break;
+                               case '*':       /* ALL Users */
+                                       addall();
+                                       break;
+                               default:        /* Simple list */
+                                       for(;;) {
+                                               insert(pp);
+                                               if(!(cp = advance()) ||
+                                                  !(pp = parse(cp, pbuf)))
+                                                       break;
+                                       }
+                               }
+                               break;
+                       }
+               }
+       }
+}
+
+
+addfile(file)
+       char *file;
+{
+       register char *cp, *pp;
+       char line[128], pbuf[64];
+       FILE *f;
+
+/***    printf("addfile(%s)\n", file);          ***/
+       if((f = fopen(file, "r")) == NULL) {
+               fprintf(stderr, "Can't open ");
+               perror(file);
+               done(1);
+       }
+       while(fgets(line, sizeof line, f)) {
+               cp = line;
+               while(pp = parse(cp, pbuf)) {
+                       insert(pp);
+                       cp = advance();
+               }
+       }
+       VOID fclose(f);
+}
+
+addgroup(group)
+       char *group;
+{
+       register char *cp, *pp;
+       int found = 0;
+       char line[128], pbuf[64], *rindex();
+       FILE *f;
+
+/***    printf("addgroup(%s)\n", group);        ***/
+       if((f = fopen(GROUP, "r")) == NULL) {
+               fprintf(stderr, "Can't open ");
+               perror(GROUP);
+               done(1);
+       }
+       while(fgets(line, sizeof line, f)) {
+               pp = parse(line, pbuf);
+               if(strcmp(pp, group) == 0) {
+                       cp = rindex(line, ':');
+                       while(pp = parse(cp, pbuf)) {
+                               insert(pp);
+                               cp = advance();
+                       }
+                       found++;
+               }
+       }
+       if(!found) {
+               fprintf(stderr, "Group: %s non-existent\n", group);
+               done(1);
+       }
+       VOID fclose(f);
+}
+
+addall()
+{
+       register struct shome *h;
+
+/***    printf("addall()\n");                   ***/
+       for(h = homes; h; h = h->h_next)
+               if(h->h_uid >= EVERYONE)
+                       insert(h->h_name);
+}
+
+remove(mp)              /* Remove NEXT from argument node! */
+       register struct mailname *mp;
+{
+       register struct mailname *rp;
+
+       rp = mp->m_next;
+       mp->m_next = rp->m_next;
+       cndfree((char *)rp->m_name);
+       cndfree((char *
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/progs/annotate.c b/docs/historical/mh-jun-1982/progs/annotate.c
new file mode 100644 (file)
index 0000000..7983597
--- /dev/null
@@ -0,0 +1,117 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+time_t time();
+long lseek();
+
+/* annotate file component data
+ *
+ * prepends   Component: data
+ *              date stamp
+ */
+
+annotate(file, comp, text, inplace)
+       char *file, *comp, *text;
+{
+       register int src;
+       register char *cp;
+       register FILE *tmp;
+       int cnt, fd;
+       char buf[BUFSIZ], *sp, tmpfil[128];
+       long now;
+       struct stat stbuf;
+       char *cdate();
+
+       if((src = open((cp = file), 2)) == -1) { /* this should be an X-open*/
+               fprintf(stderr, "Can't open ");
+               perror(cp);
+               return(1);
+       }
+       VOID copy(cp, buf);
+       sp = r1bindex(buf, '/');
+       if(sp != buf) {
+               *sp = 0;
+               cp = copy(buf, tmpfil);
+       } else
+               cp = tmpfil;
+       VOID copy(makename("ano",".tmp"), cp);
+       VOID fstat(src, &stbuf);
+       if((tmp = fopen(tmpfil, "w")) == NULL) {
+               fprintf(stderr, "Can't create ");
+               perror(tmpfil);
+               return(1);
+       }
+       VOID chmod(tmpfil, (int)stbuf.st_mode&0777);
+       cp = comp;
+       if(*cp >= 'a' && *cp <= 'z') *cp -= 040;
+       now = time((long *)0);
+       cp = cdate(&now);
+       cp[9] = ' ';  cp[15] = 0;
+       if(*cp == ' ') cp++;
+       fprintf(tmp, "%s: <<%s>>\n", comp, cp);
+       cp = text;
+       do {
+               if(*cp == ' ' || *cp == '\t') cp++;
+               sp = cp;
+               while(*cp && *cp++ != '\n') ;
+               if(cp - sp)
+                       fprintf(tmp, "%s: %*.*s", comp, cp-sp, cp-sp, sp);
+       } while(*cp);
+       if(cp[-1] != '\n' && cp != text) putc('\n', tmp);
+       do
+               if((cnt = read(src, buf, sizeof buf)) > 0)
+                       if(fwrite(buf, cnt, 1, tmp) != 1) {
+                               fprintf(stderr, "anno: Error writing to ");
+                               perror(tmpfil);
+                               done(1);
+                       }
+       while(cnt == sizeof buf);
+       VOID fclose(tmp);
+       if(inplace) {
+               fd = open(tmpfil, 0);          /* reopen for reading */
+               VOID lseek(src, 0l, 0);
+               do
+                       if((cnt = read(fd, buf, sizeof buf)) > 0)
+                               if(write(src, buf, cnt) != cnt) {
+                                       fprintf(stderr, "anno: Error rewriting ");
+                                       perror(file);
+                                       done(1);
+                               }
+               while(cnt == sizeof buf);
+               VOID close(fd);
+       } else {
+          /*   cp = copy(file, buf);           */
+          /*   *--cp =| 0200;                  */
+          /*   VOID copy(".bak", copy(file, buf));  */
+               cp = copy(file, buf);
+               cp[1] = 0;
+               do
+                       *cp = cp[-1];
+               while(--cp >= buf && *cp != '/');
+               *++cp = ',';                    /* New backup convention */
+               VOID unlink(buf);
+               if(link(file, buf) == -1) {
+                       fprintf(stderr, "Can't rename %s to bak file.\n", file);
+                       return(1);
+               }
+               if(unlink(file) == -1) {
+                       fprintf(stderr, "Can't unlink %s\n", file);
+                       return(1);
+               }
+               if(link(tmpfil, file) == -1) {
+                       fprintf(stderr, "Can't lnk temp file \"%s\" to %s\n",
+                         tmpfil, file);
+                       return(1);
+               }
+       }
+       VOID close(src);
+       VOID unlink(tmpfil);
+       retur
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/progs/comp.c b/docs/historical/mh-jun-1982/progs/comp.c
new file mode 100644 (file)
index 0000000..9989e2c
--- /dev/null
@@ -0,0 +1,178 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+#include <stdio.h>
+#include <strings.h>
+#include <signal.h>
+
+/* #define NEWS 1 */
+/* #define TEST 1 */
+
+struct swit anyul[] = {
+       "no",   0,
+       "yes",  0,
+       "use",  0,
+       "list", 0,
+       0
+};
+
+struct swit aleqs[] = {
+       "list",                 0,      /* 0 */
+       "edit [<editor>]",      0,      /* 1 */
+       "quit [delete]",        0,      /* 2 */
+       "send [switches]",      0,      /* 3 */
+       0
+};
+
+
+struct swit switches[] = {
+       "editor editor",        0,      /* 0 */
+       "form formfile",        0,      /* 1 */
+       "use",                  0,      /* 2 */
+       "nouse",                0,      /* 3 */
+       "help",                 4,      /* 4 */
+       0,                      0
+};
+
+/*ARGSUSED*/
+main(argc, argv)
+char *argv[];
+{
+       register char *cp;
+       register int in, out;
+       int use, cnt, status;
+       char buf[BUFSIZ], *ed, *file, *form;
+       static char path[128];
+       char **ap;
+       char *arguments[50], **argp;
+
+       invo_name = argv[0];
+/***    setbuf(stdout, _sobuf); ***/
+#ifdef NEWS
+       m_news();
+#endif
+       form = 0; use = 0; file = 0; ed = 0;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       VOID copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-') {
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);  /* ambiguous */
+                               goto leave;
+                                                       /* unknown */
+                       case -1:fprintf(stderr, "comp: -%s unknown\n", cp);
+                               goto leave;
+                       case 0: if(!(ed = *argp++)) {   /* -editor */
+      missing:  fprintf(stderr, "comp: Missing argument for %s switch\n", argp[-2]);
+                                       goto leave;
+                               }
+                               continue;
+                       case 1: if(!(form = *argp++))   /* -form */
+                                       goto missing;
+                               continue;
+                       case 2: use = 1;  continue;     /* -use */
+                       case 3: use = 0;  continue;     /* -nouse */
+                       case 4: help("comp    [file]  [switches]",
+                                    switches);
+                               goto leave;
+                       }
+               }
+               file = cp;
+       }
+       if(form) {
+               if((in = open(m_maildir(form), 0)) < 0) {
+                       fprintf(stderr, "comp: Can't open form file: %s\n", form);
+                       goto leave;
+               }
+       } else if((in = open(m_maildir(components), 0)) < 0 &&
+                  (in = open(stdcomps, 0)) < 0) {
+                       fprintf(stderr, "comp: Can't open default components file!!\n");
+                       goto leave;
+       }
+       if(!file)
+               file = draft;
+       VOID copy(m_maildir(file), path);
+       if((out = open(path, 0)) >= 0) {
+               cp = concat("\n\"", path, "\" exists; delete? ", 0);
+               if(use || fdcompare(in, out))
+                       goto editit;
+               while((status = gans(cp, anyul)) == 3)
+                               VOID showfile(path);
+               if(status == 2) {
+                       use++;
+                       goto editit;
+               }
+               if(status == 0)
+                       goto leave;
+               VOID close(out);
+       } else if(use) {
+               fprintf(stderr, "comp: \"%s\" doesn't exist!\n", path);
+               goto leave;
+       }
+       if((out = creat(path, m_gmprot())) < 0) {
+               fprintf(stderr, "comp: Can't create \"%s\"\n", path);
+               goto leave;
+       }
+       do
+               if(cnt = read(in, buf, sizeof buf))
+                       if(write(out, buf, cnt) != cnt) {
+                               fprintf(stderr, "comp: error writing ");
+                               perror(path);
+                               goto leave;
+                       }
+       while(cnt == sizeof buf);
+       VOID close(in);
+editit:
+       VOID close(out);
+       if(m_edit(&ed, path, use, NULLCP) < 0)
+               goto leave;
+#ifdef TEST
+       fprintf(stderr, "!! Test Version of SEND Being Run !!\n");
+       fprintf(stderr, "   Send verbose !\n\n");
+#endif
+
+    for(;;) {
+       if(!(argp = getans("\nWhat now? ", aleqs)))
+               goto leave;
+       switch(smatch(*argp, aleqs)) {
+               case 0: VOID showfile(path);                    /* list */
+                       break;
+
+               case 1: if(*++argp)                             /* edit */
+                               ed = *argp;
+                       if(m_edit(&ed, path, use, NULLCP) == -1)
+                               goto leave;
+                       break;
+                                                               /* quit */
+               case 2: if(*++argp && (*argp[0] == 'd' ||
+                                      (*argp[0]=='-' && *argp[1]=='d')))
+                               if(unlink(path) == -1)  {
+                                       fprintf(stderr, "Can't unlink %s ", path);
+                                       perror("");
+                               }
+                       goto leave;
+
+               case 3: VOID m_send(++argp, path);              /* send */
+                       goto leave;
+
+               default:fprintf(stderr, "comp: illegal option\n");      /*##*/
+                       break;
+       }
+    }
+
+leave:
+       m_update();
+       done(0);
+}
+
diff --git a/docs/historical/mh-jun-1982/progs/conflict.c b/docs/historical/mh-jun-1982/progs/conflict.c
new file mode 100644 (file)
index 0000000..1937efc
--- /dev/null
@@ -0,0 +1,221 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+#include <pwd.h>
+#include <grp.h>
+#include <sys/types.h>
+#include <sys/dir.h>
+#include "../mh.h"
+#include <mailsys.h>
+
+char    *AliasFile =    MAILALIASES;
+char    *Password  =    "/etc/passwd";
+char    *MailDir   =    MAILDROP;
+
+char *termptr;
+char *malloc();
+
+struct  mailname {
+       struct mailname *m_next;
+       char            *m_name;
+       int              m_seen;
+}  users, bad;
+
+
+char *parse(ptr, buf)
+register char *ptr;
+char *buf;
+{
+       register char *cp;
+
+       cp = buf;
+       while(isspace(*ptr) || *ptr == ',' || *ptr == ':')
+               ptr++;
+       while(isalnum(*ptr) || *ptr == '/' || *ptr == '-' || *ptr == '.')
+               *cp++ = *ptr++;
+       if(cp == buf) {
+               switch(*ptr) {
+               case '<':
+               case '*':
+               case '=':
+                       *cp++ = *ptr++;
+               }
+       }
+       *cp = 0;
+       if(cp == buf)
+               return 0;
+       termptr = ptr;
+       return buf;
+}
+
+
+char   *mail = 0;
+FILE   *out;
+int     donecd = 0;
+
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       register char *cp, **cpp;
+       register struct mailname *lp;
+       register struct group *gp;
+       struct direct dir;
+       char line[256], pbuf[64];
+       FILE *a;
+       struct group *getgrent();
+
+       invo_name = argv[0];
+       if(argc == 3 && strcmp(argv[1], "-mail") == 0)
+               mail = argv[2];
+       if(!mail)
+               out = stdout;
+       if((a = fopen(Password, "r")) == NULL) {
+               om();
+               fprintf(out, "Can't open password file ");
+               perror(Password);
+               done(1);
+       }
+       while(fgets(line, sizeof line, a)) {
+               if(line[0] == '\n' || line[0] == ';')
+                       continue;
+               cp = parse(line, pbuf);
+               addu(cp, &users);
+       }
+       VOID fclose(a);
+       if((a = fopen(AliasFile, "r")) == NULL) {
+               om();
+               fprintf(out, "Can't open alias file: %s\n", AliasFile);
+               donecd = 1;
+       } else {
+               while(fgets(line, sizeof line, a)) {
+                       if(line[0] == '\n' || line[0] == ';')
+                               continue;
+                       cp = parse(line, pbuf);
+                       if(check(cp, 0)) {
+                               addu(line, &bad);
+                               donecd = 1;
+                       }
+               }
+               VOID fclose(a);
+               if(donecd < 1) {
+                       if(out)
+                               fprintf(out, "No Alias Inconsistencies.\n");
+               } else {
+                       om();
+                       fprintf(out, "%s :: %s Collisions:\n",
+                               Password, AliasFile);
+                       fprintf(out, "Colliding alias lines:\n");
+                       for(lp = bad.m_next; lp; lp = lp->m_next)
+                               fprintf(out, "%s", lp->m_name);
+                       donecd = 1;
+               }
+       }
+       while(gp = getgrent()) {
+               for(cpp = gp->gr_mem; *cpp; cpp++)
+                       if(!check(*cpp, 1)) {
+                               om();
+                               fprintf(out, "Group: %s--User: %s not in /etc/passwd\n",
+                                       gp->gr_name, *cpp);
+                               donecd = 2;
+                       }
+       }
+       if(donecd < 2 && out)
+               fprintf(out, "No extraneous group entries.\n");
+#ifdef RAND
+       for(lp = users.m_next; lp; lp = lp->m_next)
+               if(lp->m_seen == 0) {
+                       om();
+                       fprintf(out, "User: %s not in a group.\n", lp->m_name);
+                       donecd = 3;
+               }
+       if(donecd < 3 && out)
+               fprintf(out, "No Users not in any group.\n");
+#endif
+       if((a = fopen(MailDir, "r")) == NULL) {
+               om();
+               fprintf(out, "Can't open mail directory: %s\n", MailDir);
+               donecd = 4;
+       } else {
+               while(fread((char *)&dir, sizeof dir, 1, a)) {
+                       if(   dir.d_ino == 0
+                          || dir.d_name[0] == '.'
+                         )
+                               continue;
+                       if(!check(dir.d_name, 0)) {
+                               om();
+                               fprintf(out, "Mail drop: %s--Nonexistent user.\n",
+                                       dir.d_name);
+                               donecd = 4;
+                       }
+               }
+               VOID fclose(a);
+       }
+       if(donecd < 4 && out)
+               fprintf(out, "No Extra mail drops.\n");
+
+       done(donecd);
+}
+
+
+addu(name, list)
+       char *name;
+       struct mailname *list;
+{
+       register struct mailname *mp;
+       char *getcpy();
+
+       for(mp = list; mp->m_next; mp = mp->m_next)
+               ;
+       mp->m_next = (struct mailname *) malloc(sizeof *mp->m_next);
+       mp = mp->m_next;
+       mp->m_next = 0;
+       mp->m_name = getcpy(name);
+}
+
+check(name, mark)
+       char *name;
+       int mark;
+{
+       register struct mailname *mp;
+
+       for(mp = users.m_next; mp; mp = mp->m_next)
+               if(uleq(name, mp->m_name)) {
+                       if(mark)
+                               mp->m_seen = 1;
+                       return 1;
+               }
+       return 0;
+}
+
+
+om()
+{
+       int pipes[2], child;
+
+       if(out)
+               return;
+       if(mail) {
+               VOID pipe(pipes);
+               out = fdopen(pipes[1], "w");
+               if((child = fork()) == -1) {
+                       fprintf(stderr, "Conflict: no forks!\n");
+                       done(1);
+               }
+               if(child == 0) {
+                       VOID close(pipes[1]);
+                       VOID close(0);
+                       VOID dup(pipes[0]);
+                       VOID close(pipes[0]);
+                       execl("/bin/mail", "mail", mail, 0);
+                       execl("/usr/bin/mail", "mail", mail, 0);
+                       perror("mail");
+                       done(1);
+               }
+               fprintf(out, "Conflict: "
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/progs/deliver.c b/docs/historical/mh-jun-1982/progs/deliver.c
new file mode 100644 (file)
index 0000000..47e7359
--- /dev/null
@@ -0,0 +1,1154 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include <whoami.h>
+#include "../mh.h"
+#include "../adrparse.h"
+#include <stdio.h>
+#include <ctype.h>
+#include <pwd.h>
+#include <sys/types.h>
+#include <sys/timeb.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <strings.h>
+#include <mailsys.h>
+#include <time.h>
+
+
+time_t time();
+char *malloc(), *calloc(), *getncpy(), *sprintf(), *strcpy(), *strncop();
+char *ctime();
+long lseek();
+
+#define OUTPUTLINELEN 72
+#define EVERYONE 10
+#define RECVPROG "/.mh_receive"
+#define DAEMON_GRP 2
+#define FCCS    10      /* Max number of fcc's allowed */
+
+/* Alias */
+#define STAR 2
+int alitype;    /*** 0 = nomatch, 2 = *match, 1 = stringmatch ***/
+
+struct shome {          /* Internal name/uid/home database */
+       struct shome *h_next;
+       char *h_name;
+       int   h_uid;
+       int   h_gid;
+       char *h_home;
+} *homes, *home();
+
+struct swit switches[] = {
+       "debug",         -5,      /* 0 */
+       "deliver",       -1,      /* 1 */
+       "format",         0,      /* 2 */
+       "noformat",       0,      /* 3 */
+       "msgid",          0,      /* 4 */
+       "nomsgid",        0,      /* 5 */
+       "remove",         0,      /* 6 */
+       "noremove",       0,      /* 7 */
+       "verbose",        0,      /* 8 */
+       "noverbose",      0,      /* 9 */
+       "width",          0,      /*10 */
+       "help",           4,      /*11 */
+       0,                0
+};
+
+int     verbose, format=1, msgid, debug, myuid, rmflg;
+short   lockwait;       /* Secs to wait for mail lock (From strings/lockdir.c) */
+#define LOCKWAIT (lockwait * 5) /* Ignore lock if older than this */
+short   donecd;
+short   outputlinelen = OUTPUTLINELEN;
+long    now;
+char    tmpfil[32], uutmpfil[32], fccfold[FCCS][128];
+short   fccind;
+char   *deliverto;
+char   *head_alias = "";   /* 1st match in a local mailbox's alias chain */
+                          /* (If a:b, b:c, c:d then head_alias == "a") */
+
+struct mailname localaddrs, netaddrs, uuaddrs;
+struct mailname *mn_from;
+char *hdrptr;
+
+/*ARGSUSED*/
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       register char *cp, **argp;
+       register struct mailname *lp;
+       char buf[BUFSIZ], name[NAMESZ];
+       char *msg;
+       int state, compnum, fd;
+       FILE *in, *out, *uuout;
+
+       invo_name = argv[0];
+#ifndef ARPANET
+       format=0;               /* default to noformat if no Arpanet */
+#endif
+       msg = 0;
+       argp = argv + 1;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               done(1);
+                                                       /* unknown */
+                       case -1:fprintf(stderr, "deliver: -%s unknown switch.\n", cp);
+                               done(1);
+                       case 0: verbose++; debug++; continue; /* -debug */
+                       case 1: if(!(deliverto = *argp++) || *deliverto == '-'){
+                 missing:          fprintf(stderr, "deliver: missing arg to %s\n",
+                                            argp[-2]);
+                                   done(1);
+                               }
+                               continue;
+                       case 2: format = 1; continue;         /* -format */
+                       case 3: format = 0; continue;         /* -noformat */
+                       case 4: msgid = 1;  continue;         /* -msgid */
+                       case 5: msgid = 0;  continue;         /* -nomsgid */
+                       case 6: rmflg = 1;  continue;         /* -remove */
+                       case 7: rmflg = -1; continue;         /* -noremove */
+                       case 8: verbose = 1; continue;        /* -verbose */
+                       case 9: verbose = 0; continue;        /* -noverbose */
+                       case 10: if(!(cp = *argp++) || *cp == '-')
+                                       goto missing;
+                               outputlinelen = atoi(cp);
+                               continue;
+                       case 11: help("deliver [switches] file",
+                                    switches);
+                               done(1);
+                       }
+               if(msg) {
+                       fprintf(stderr, "Deliver: Only one message at a time!\n");
+                       done(1);
+               } else
+                       msg = cp;
+       }
+       if(!msg) {
+               fprintf(stderr, "Deliver: No Message specified.\n");
+               fprintf(stderr, "Deliver: Usage: deliver [switches] file\n");
+               done(1);
+       }
+       if(outputlinelen < 10) {
+               fprintf(stderr, "deliver: Impossible width: %d\n",
+                               outputlinelen);
+               done(1);
+       }
+       gethomes();
+       myuid = getuid();
+       if(deliverto) {
+               int uid;
+               if((uid = geteuid()) && uid != 1 && getegid() != DAEMON_GRP) {
+/*              if(myuid != 0 && getgid() != DAEMON_GRP) {  */
+                       fprintf(stderr, "Deliver: -deliver switch su only.\n");
+                       done(1);
+               }
+#ifdef VMUNIX
+               setpgrp(0, getpid());   /* So we don't blow away our parent */
+#endif
+               strcpy(tmpfil, msg);
+               strcpy(uutmpfil, msg);
+               if(access(tmpfil, 4) == -1) {
+                       fprintf(stderr, "Deliver: Can't access ");
+                       perror(tmpfil);
+                       done(1);
+               }
+               if(!rmflg) rmflg = -1;
+               goto del1;
+       }
+       if(!rmflg) rmflg = 1;
+       if((in = fopen(msg, "r")) == NULL) {
+               fprintf(stderr, "Deliver: Can't open ");
+               perror(msg);
+               done(1);
+       }
+       VOID copy(makename("locs", ".tmp"), copy("/usr/tmp/mh/", tmpfil));
+       if(!debug) {
+               if((out = fopen(tmpfil, "w")) == NULL) {
+                       fprintf(stderr, "Can't create %s\n", tmpfil);
+                       done(1);
+               }
+               VOID chmod(tmpfil, 0744);
+       } else
+               out = stdout;
+
+       VOID copy(makename("uulc", ".tmp"), copy("/usr/tmp/mh/", uutmpfil));
+       if(!debug) {
+               if((uuout = fopen(uutmpfil, "w")) == NULL) {
+                       fprintf(stderr, "Can't create %s\n", uutmpfil);
+                       done(1);
+               }
+               VOID chmod(uutmpfil, 0600);
+       } else
+               uuout = fopen("/dev/null","w");;
+
+       putdate(out);           /* Tack on the date */
+       putdate(uuout);           /* Tack on the date */
+       for(compnum = 1, state = FLD;;) {
+               state = m_getfld(state, name, buf, sizeof buf, in);
+               switch(state) {
+
+               case FLD:
+               case FLDEOF:
+               case FLDPLUS:
+                       hdrptr = 0;
+                       compnum++;
+                       if(uleq(name, "fcc")) {
+                               cp = buf;
+                               while(*cp == ' ' || *cp == '\t')
+                                       cp++;
+                               if(fccind >= FCCS) {
+                                       fprintf(stderr, "Deliver: too many fcc's.\n");
+                                       done(1);
+                               }
+                               VOID copy(cp, fccfold[fccind]);
+                               if(cp = rindex(fccfold[fccind], '\n'))
+                                       *cp = 0;
+                               fccind++;
+                               break;
+                       }
+                       hdrptr = add(buf, hdrptr);
+                       while(state == FLDPLUS) {
+                               state = m_getfld(state, name, buf, sizeof buf, in);
+                               hdrptr = add(buf, hdrptr);
+                       }
+                       putfmt(name, hdrptr, out);
+                       {       /* Do not format uucp mail */
+                               int tmpformat;
+                               tmpformat = format; format = 0;
+                               putfmt (name, hdrptr, uuout);
+                               format = tmpformat;
+                       }
+                       if(state == FLDEOF)
+                               goto process;
+                       break;
+
+               case BODY:
+               case BODYEOF:
+                       putfrom(out);           /* Tack on the from */
+                                               /* But NOT on the UUCP mail */
+                       putmsgid(out);          /* and msg id if desired */
+                       putmsgid(uuout);        /* (why not?) */
+
+                       fprintf(out, "\n%s", buf);
+                       fprintf(uuout, "\n%s", buf);
+                       while(state == BODY) {
+                               state=m_getfld(state,name,buf,sizeof buf,in);
+                               fputs(buf, out);
+                               fputs(buf, uuout);
+                       }
+
+               case FILEEOF:
+                       goto process;
+
+               case LENERR:
+               case FMTERR:
+                       fprintf(stderr, "??Message Format Error ");
+                       fprintf(stderr, "in Component #%d.\n", compnum);
+                       done(1);
+
+               default:
+                       fprintf(stderr, "Getfld returned %d\n", state);
+                       done(1);
+               }
+       }
+process:
+       if(!debug) {
+               VOID fclose(out);
+               VOID fclose(uuout);
+       }
+       else
+               printf("-----\n");
+       VOID fclose(in);
+del1:   if(deliverto)   {
+               cinsert(deliverto);
+       }
+       if(debug) {
+               printf("Before alias():\n"); pl();
+       }
+
+       if(localaddrs.m_next)
+               alias();                        /* Map names if needed */
+
+       for(lp = localaddrs.m_next; lp; lp = lp->m_next)
+               if(home(lp->m_mbox) == NULL) {
+                       fprintf(stderr, "Deliver: Unknown local user: %s.\n", lp->m_mbox);
+                       fprintf(stderr, "Deliver: Message not delivered.\n");
+                       if(!debug)
+                               unlinktmp();
+                       done(1);
+               }
+       if(debug) {
+               printf("Addrs:\n"); pl();
+       }
+
+       VOID signal(SIGINT, SIG_IGN);
+       VOID signal(SIGQUIT, SIG_IGN);
+       if(!debug) {                    /* Send the mail */
+               if(localaddrs.m_next) {
+                       fd = open(tmpfil, 0);
+                       for(lp = localaddrs.m_next; lp; lp = lp->m_next)
+                               sendmail(lp->m_mbox, fd, lp->m_headali);
+                       VOID close(fd);
+               }
+               if(fccind)
+                       for(state = 0; state < fccind; state++)
+                               fcc(tmpfil, fccfold[state]);
+               if(uuaddrs.m_next)
+                       uumail();
+               if(netaddrs.m_next)
+                       netmail();
+               unlinktmp();
+       }
+       done(donecd);
+}
+
+
+unlinktmp()
+{
+       if (!deliverto) /* "Deliverto" makes it same as tmpfil */
+               VOID unlink (uutmpfil);         /* Even if rmflg < 0? */
+       if(rmflg > 0)
+               VOID unlink(tmpfil);
+}
+
+
+
+putfmt(name, str, out)
+       char *name, *str;
+       FILE *out;
+{
+       register char *cp;
+       register struct mailname *mp;
+       int nameoutput = 0;
+       int linepos = 0;
+       int len;
+
+       while(*str == ' ' || *str == '\t') str++;
+       if(uleq(name, "to") ||
+          uleq(name, "cc") ||
+          uleq(name, "bcc") ||
+          uleq(name, "reply-to") ||
+          uleq(name, "from")) {
+           while(cp = getname(str)) {
+               if(!(mp = getm(cp, HOSTNAME)))
+                       done(1);
+               if(uleq(name, "from") || uleq(name, "reply-to") ||
+                  insert(mp, 
+                       mp->m_hnum == HOSTNUM ?
+                                            &localaddrs : 
+                       (*mp->m_at == '!') ? &uuaddrs :
+                                            &netaddrs)) {
+                   if(!uleq(name, "bcc") && format) {
+                       if(!nameoutput) {
+                           fprintf(out, "%s: ", name);
+                           linepos += (nameoutput = strlen(name)+2);
+                       }
+                       cp = adrformat(mp,HOSTNAME);    
+                               /* Needs default name in uumail case */
+                       len = strlen(cp);
+                       if(linepos != nameoutput)
+                           if(len + linepos + 2 > outputlinelen) {
+                               fprintf(out, ",\n%*s", nameoutput, "");
+                               linepos = nameoutput;
+                           } else {
+                               fputs(", ", out);
+                               linepos += 2;
+                           }
+                       fputs(cp, out);
+                       linepos += len;
+                   }
+                   if(uleq(name, "from"))
+                       mn_from = mp;
+               } else
+                   mnfree(mp);
+           }
+           if(linepos) putc('\n', out);
+           if(!format && !uleq(name, "bcc"))
+               goto nofmt;
+       } else {
+nofmt:
+           fprintf(out, "%s: %s", name, str);
+       }
+}
+
+gethomes()
+{
+       register struct passwd *pw;
+       register struct shome *h, *ph;
+       struct passwd *getpwent();
+
+       ph = (struct shome *) &homes;
+       while((pw = getpwent()) != NULL) {
+               h = (struct shome *) malloc(sizeof *h);
+               h->h_next = NULL;
+               h->h_name = (char *) malloc((unsigned)strlen(pw->pw_name)+1);
+               strcpy(h->h_name, pw->pw_name);
+               h->h_uid = pw->pw_uid;
+               h->h_gid = pw->pw_gid;
+               h->h_home = (char *) malloc((unsigned)strlen(pw->pw_dir)+1);
+               strcpy(h->h_home, pw->pw_dir);
+               ph->h_next = h;
+               ph = h;
+       }
+}
+
+
+struct shome *
+home(name)
+       register char *name;
+{
+       register struct shome *h;
+
+       for(h = homes; h; h = h->h_next)
+               if(uleq(name, h->h_name))
+                       return(h);
+       return(NULL);
+}
+
+char *bracket = "\1\1\1\1\n";
+
+sendmail(name, fd, head_alias)              /* Runs with signals ignored! */
+       char *name;
+       register int fd;
+       char *head_alias;
+{
+       char buf[BUFSIZ];
+       register int i, m, c;
+       register char *mail, *receive, *lock = 0;
+       register struct shome *h;
+       struct stat stbuf;
+
+       if(verbose)  {
+               printf("%s: ", name);   fflush(stdout);
+       }
+       VOID lseek(fd, 0l, 0);
+       h = home(name);
+
+       mail = concat(mailboxes, "/", h->h_name, NULLCP);
+/***    mail = concat(h->h_home, mailbox, NULLCP);           ***/
+       receive = concat(h->h_home, RECVPROG, NULLCP);
+       if(access(receive, 1) == 0) {   /* User has a receive prog */
+
+               calluserprog(receive, mail, fd, h, head_alias);
+
+       } else {
+
+               if((m = open(mail, 2)) < 0) {
+                       if((m = creat(mail, 0600)) < 0) {
+                               fprintf(stderr, "Deliver: Can't write ");
+                               perror(mail);
+                               donecd = 1; goto out;
+                       }
+                       VOID chown(mail, h->h_uid, h->h_gid);
+                       if(verbose) {
+                               printf("Creating %s ", mail); fflush(stdout);
+                       }
+               }
+               lock = concat(lockdir, "/", h->h_name, NULLCP);
+               for(i = 0; i < lockwait; i += 2) {
+                       if(link(mail, lock) >= 0)
+                               break;
+                       if(i == 0 && stat(mail, &stbuf) >= 0 &&
+                          stbuf.st_ctime + LOCKWAIT < time((long *) 0)) {
+                               i = lockwait;
+                               break;
+                       }
+                       if(verbose) {
+                               printf("Busy ");  fflush(stdout);
+                       }
+                       sleep(2);
+               }
+               if(i >= lockwait) {
+                       VOID unlink(lock);
+                       if(verbose) {
+                               printf("Removing lock. ");  fflush(stdout);
+                       }
+                       if(link(mail, lock) < 0) {
+                               fprintf(stderr, "Can't lock %s to %s\n",
+                                       mail, lock);
+                               donecd = 1;
+                               goto out1;
+                       }
+               }
+               VOID lseek(m, 0l, 2);
+               if(write(m, bracket, 5) != 5)
+                       goto wrerr;
+               do
+                       if((c = read(fd, buf, sizeof buf)) > 0)
+                               if(write(m, buf, c) != c) {
+                           wrerr:      fprintf(stderr, "Write error on ");
+                                       perror(mail);
+                                       donecd = 1;
+                                       goto out1;
+                               }
+               while(c == sizeof buf);
+               if(write(m, bracket, 5) != 5)
+                       goto wrerr;
+out1:           VOID close(m);
+out:            cndfree(mail);
+               if(lock) {
+                       VOID unlink(lock);
+                       cndfree(lock);
+               }
+       }
+       if(verbose && !donecd)
+               printf("Sent.\n");
+}
+
+netmail()
+{
+       register struct mailname *mp;
+       register struct shome *h;
+       register struct hosts *hp;
+       register FILE *md;
+       int fd, count;
+       char namebuf[15], tmpname[40], queuename[40];
+       char buf[BUFSIZ];
+
+       crname(namebuf);
+       VOID sprintf(tmpname,   "%s/%s", TMAILQDIR, namebuf);
+       VOID sprintf(queuename, "%s/%s",  MAILQDIR, namebuf);
+       if((md = fopen(tmpname, "w")) == NULL) {
+               fprintf(stderr, "Deliver: Can't create netmail tmp: ");
+               perror(tmpname);
+               done(1);
+       }
+       for(h = homes; ; h = h->h_next) {
+               if(!h) {
+                       fprintf(stderr, "Deliver: Who are you?\n");
+                       done(1);
+               }
+               if(h->h_uid == myuid)
+                       break;
+       }
+       if(!now)
+               now = time((long *)0);
+       fprintf(md, "%s %s\n", h->h_name, cdate(&now));
+       if(debug) {
+               printf("Netmail...");   fflush(stdout);
+       }
+       for(mp = netaddrs.m_next; mp; mp = mp->m_next) {
+               if(debug) printf("%s at %s\n",mp->m_mbox, mp->m_host);
+               for(hp = hosts.nh_next; hp; hp = hp->nh_next)
+                       if(mp->m_hnum == hp->nh_num)
+                               break;
+               if(!hp) {
+                       fprintf(stderr, "Deliver: hnum->name botch.\n");
+                       done(1);
+               }
+               fprintf(md, "/%s %s\n", hp->nh_name, mp->m_mbox);
+               if(verbose)
+                       printf("%s at %s: queued\n", mp->m_mbox, mp->m_host);
+       }
+       putc('\n', md);
+       if(fflush(md) == EOF) goto wrerr;
+       if((fd = open(tmpfil, 0)) == -1) {
+               fprintf(stderr, "Deliver: HuH? Can't reopen ");
+               perror(tmpfil);
+               done(1);
+       }
+       do {
+               if((count = read(fd, buf, sizeof buf)) > 0) {
+                       if(write(fileno(md), buf, count) != count) {
+                  wrerr:       fprintf(stderr, "Deliver: write error on ");
+                               perror(tmpname);
+                               VOID unlink(tmpname);
+                               done(1);
+                       }
+               } else if(count < 0) {
+                       fprintf(stderr, "deliver: Read error on ");
+                       perror(tmpfil);
+                       VOID unlink(tmpname);
+                       done(1);
+               }
+       } while(count == sizeof buf);
+       if(close(fd) == -1 || fclose(md) == EOF) goto wrerr;
+       if(link(tmpname, queuename) == -1 ||
+          unlink(tmpname) == -1) {
+               fprintf(stderr, "Deliver: Trouble linking tmpfile into queue ");
+               perror(queuename);
+       }
+       VOID chmod (queuename, 0600);
+}
+
+uumail()
+{
+       register struct mailname *mp;
+       register struct shome *h;
+       register FILE *rmf;
+       FILE *popen();
+       int fd, count;
+       char cmd[64];
+       char buf[BUFSIZ];
+
+       for(h = homes; h; h = h->h_next)
+               if(h->h_uid == myuid)
+                       break;
+       if(!h) {
+               fprintf(stderr, "Deliver: Who are you?\n");
+               done(1);
+       }
+       if(!now)
+               now = time((long *)0);
+       for(mp = uuaddrs.m_next; mp; mp = mp->m_next) {
+               VOID sprintf(cmd, index(mp->m_mbox, '!') ?
+                               "uux - %s!rmail \\(%s\\)" :
+                               "uux - %s!rmail %s",
+                               mp->m_host, mp->m_mbox);
+               if ((rmf=popen (cmd, "w")) == NULL) {
+                       fprintf(stderr, "Deliver: Could not open uux pipe.\n");
+                       done(1);
+               }
+       
+               if((fd = open(uutmpfil, 0)) == -1) {
+                       fprintf(stderr, "Deliver: HuH? Can't reopen ");
+                       perror(uutmpfil);
+                       done(1);
+               }
+       /* UUCP mail insists on beginning with a "From" line.  */
+       /*   No other concessions (">" before From) will be provided now */
+               fprintf(rmf, "From %s %.24s remote from %s\n", h->h_name,
+                               ctime(&now),
+                               sysname);
+               VOID fflush(rmf);    /* Lest the "write"s get in ahead */
+
+               do {
+                       if((count = read(fd, buf, sizeof buf)) > 0) {
+                               if(write(fileno(rmf), buf, count) != count) {
+                  wrerr:               fprintf(stderr, "Deliver: write error on pipe\n");
+                                       done(1);
+                               }
+                       } else if(count < 0) {
+                               fprintf(stderr, "deliver: Read error on ");
+                               perror(uutmpfil);
+                               done(1);
+                       }
+               } while(count == sizeof buf);
+               if(close(fd) == -1 ) goto wrerr;
+               pclose(rmf);
+               if(verbose)
+                       printf("%s At %s (via uux): queued.\n",
+                               mp->m_mbox, mp->m_host);
+
+       }
+}
+
+char hex[] = "0123456789ABCDEF";  /* Hexadecimal */
+
+crname(ptr)     /* Create unique file name in /usr/tmp */
+       char *ptr;
+{
+       int i;
+       short tvec[4];
+       static int filecnt;
+       register char *p, *q;
+
+       q = ptr;
+       p = (char *)&tvec[0];
+       tvec[2] = getpid();
+       tvec[3] = filecnt++;
+       if (filecnt==256) {
+               filecnt = 0;
+               sleep(1);
+       }
+       VOID time((time_t *)tvec);
+       for (i=7; i; --i) {
+               *q++ = hex[(*p>>4)&017];
+               *q++ = hex[ *p++  &017];
+       }
+       *q = '\0';
+}
+
+
+putfrom(out)
+       register FILE *out;
+{
+       register struct shome *h;
+       register struct mailname *mp;
+       register char *cp;
+
+       for(h = homes; h; h = h->h_next)
+               if(h->h_uid == myuid) {
+                       if(format) {
+                               if(!(mp = getm(h->h_name, HOSTNAME)))
+                                       done(1);
+                               cp = adrformat(mp,HOSTNAME);
+                               mnfree(mp);
+                       } else
+                               cp = h->h_name;
+                       if(mn_from) {
+                               if(mn_from->m_hnum != HOSTNUM ||
+                                  !uleq(mn_from->m_mbox, h->h_name))
+                                       fprintf(out, "Sender: %s\n", cp);
+                       } else
+                               fprintf(out, "From: %s\n", cp);
+                       return;
+               }
+       fprintf(stderr, "Deliver: WHO ARE YOU?\n");
+       done(1);
+}
+
+
+putdate(out)
+       register FILE *out;
+{
+       register char *t, *p;
+       char *timezone();
+       struct timeb tb;
+       struct tm *tmp, *localtime();
+       static char *wday[] = {
+               "Sun",
+               "Mon",
+               "Tues",
+               "Wednes",
+               "Thurs",
+               "Fri",
+               "Satur"
+       };
+
+       if(!now)
+               now = time((long *)0);
+       t = ctime(&now);
+       ftime(&tb);
+       tmp = localtime(&now);
+       p = timezone(tb.timezone, tmp->tm_isdst);
+
+       /*                  day    13   Apr  1981 20  :38   -PST */
+       fprintf(out, "Date: %sday, %.2s %.3s %.4s %.2s:%.2s-%.3s\n",
+                    wday[tmp->tm_wday], t+8, t+4, t+20, t+11, t+14, p);
+}
+
+
+putmsgid(sp)
+       FILE *sp;
+{
+       if(!msgid)
+               return;
+       if(!now)
+               now = time((long *)0);
+       fprintf(sp, "Message-ID: <%u.%ld@%s>\n", myuid, now, HOSTNAME);
+}
+
+
+/***/
+pl()
+{
+       register struct mailname *mp;
+
+       printf("local: ");
+       for(mp = localaddrs.m_next; mp; mp=mp->m_next)
+               printf("%s (%s)%s",
+               mp->m_mbox, mp->m_headali, mp->m_next?", ":"");
+       printf("\n");
+       printf("net: ");
+       for(mp = netaddrs.m_next; mp; mp=mp->m_next)
+               printf("%s@%s (%s)%s",
+                mp->m_mbox, mp->m_host, mp->m_headali, mp->m_next?", ":"");
+       printf("\n");
+       printf("uucp: ");
+       for(mp = uuaddrs.m_next; mp; mp=mp->m_next)
+               printf("%s!%s (%s)%s",
+               mp->m_host, mp->m_mbox, mp->m_headali, mp->m_next?", ":"");
+       printf("\n");
+}
+/***/
+
+insert(np, queue)
+       register struct mailname *np, *queue;
+{
+       register struct mailname *mp;
+
+       /*** printf("insert(%s@%d)=>", np->m_mbox, np->m_hnum);   /***/
+       for(mp = queue; mp->m_next; mp = mp->m_next)
+               if(duplicate(np, mp)) { /* Don't insert existing name! */
+                       /*** printf("0\n");     /***/
+                       return 0;
+               }
+       mp->m_next = np;
+/*** printf("1\n");     /***/
+       return 1;
+}
+
+duplicate(np, mp)
+struct mailname *np, *mp;
+{
+       if (*np->m_at == '!')
+               /* If uucp, compare host names */
+               if(uleq(np->m_host, mp->m_next->m_host) &&
+                  uleq(np->m_mbox, mp->m_next->m_mbox))
+                       return(1);
+               else
+                       return(0);
+
+       /* Otherwise, compare host numbers */
+       if(np->m_hnum == mp->m_next->m_hnum &&
+       uleq(np->m_mbox, mp->m_next->m_mbox))
+               /* Special consideration, eg:  news.topic1 != news.topic2 */
+               return( uleq(np->m_headali, mp->m_next->m_headali) ? 1
+               : alitype == STAR ?  0 : 1);
+       else
+               return(0);
+}
+
+
+
+cinsert(str)
+       char *str;
+{
+       register struct mailname *mp;
+
+       if(!(mp = getm(str, HOSTNAME)))
+               done(1);
+       mp->m_headali =  getcpy(head_alias);
+       if(!insert(mp, mp->m_hnum == HOSTNUM ?
+                                       &localaddrs : 
+                       (*mp->m_at == '!')?  &uuaddrs :
+                                       &netaddrs)) {
+               mnfree(mp);
+       }
+}
+
+
+/* alias implementation below...
+ */
+
+#define SAVE   0
+#define RESET  1
+#define NEXT   2
+#define GROUP   "/etc/group"
+char    *AliasFile =    "/etc/MailAliases";
+
+char *termptr, *listsave;
+
+char *
+parse(ptr, buf)
+       register char *ptr;
+       char *buf;
+{
+       register char *cp;
+
+       cp = buf;
+       while(isspace(*ptr) || *ptr == ',' || *ptr == ':')
+               ptr++;
+       while(isalnum(*ptr) || *ptr == '/' || *ptr == '-' ||
+           *ptr == '!' || *ptr == '@' || *ptr == ' ' ||
+           *ptr == '.' || *ptr == '*')
+               *cp++ = *ptr++;
+       if(cp == buf) {
+               switch(*ptr) {
+               case '<':
+               case '=':
+                       *cp++ = *ptr++;
+               }
+       }
+       *cp = 0;
+       if(cp == buf)
+               return 0;
+       termptr = ptr;
+       return buf;
+}
+
+char *
+setptr(type)
+int type;
+{
+       switch(type) {
+
+       case SAVE:
+               listsave = termptr;
+               break;
+       case RESET:             /* Reread the current alias replacement-list */
+               termptr = listsave;
+               break;
+       case NEXT:
+               break;
+       }
+       return(termptr);
+}
+
+alias()
+{
+       register char *cp, *pp;
+       char *parsep = 0;
+       struct mailname ptrsave;
+       register struct mailname *lp;
+       char line[256], pbuf[64];
+       FILE *a;
+
+       if((a = fopen(AliasFile, "r")) == NULL) {
+               fprintf(stderr, "Can't open alias file ");
+               perror(AliasFile);
+               done(1);
+       }
+       while(fgets(line, sizeof line, a)) {
+               if(line[0] == ';' || line[0] == '\n')   /* Comment Line */
+                       continue;
+               cndfree(parsep);
+               if((parsep = getcpy(parse(line, pbuf))) == NULL) {
+           oops:       fprintf(stderr, "Bad alias file %s\n", AliasFile);
+                       fprintf(stderr, "Line: %s", line);
+                       done(1);
+               }
+               VOID setptr(SAVE);
+               for(lp = &localaddrs; lp->m_next; lp = lp->m_next) {
+                       if(alitype = aleq(lp->m_next->m_mbox, parsep)) {
+                               setali(lp->m_next);
+
+                               ptrsave.m_next = lp;   /* Maintain ptr */
+                               remove(lp);            /* continuity after */
+                               lp = &ptrsave;         /* lp->next is removed. */
+
+                               if(!(cp = setptr(NEXT)) ||
+                                  !(pp = parse(cp, pbuf)))
+                                       goto oops;
+                               switch(*pp) {
+                               case '<':       /* From file */
+                                       cp = setptr(NEXT);
+                                       if((pp = parse(cp, pbuf)) == NULL)
+                                               goto oops;
+                                       addfile(pp);
+                                       break;
+                               case '=':       /* UNIX group */
+                                       cp = setptr(NEXT);
+                                       if((pp = parse(cp, pbuf)) == NULL)
+                                               goto oops;
+                                       addgroup(pp);
+                                       break;
+                               case '*':       /* ALL Users */
+                                       addall();
+                                       break;
+                               default:        /* Simple list */
+                                       for(;;) {
+                                               cinsert(pp);
+                                               if(!(cp = setptr(NEXT)) ||
+                                                  !(pp = parse(cp, pbuf)))
+                                                       break;
+                                       }
+                                       VOID setptr(RESET);
+                               }
+                               /* May be more news.*<topics> in hdr */
+                               if(alitype == STAR) continue;
+                               else                 break;
+                       }
+               }
+       }
+       alitype = 0;
+}
+
+setali(mp)
+struct mailname *mp;
+{
+       /* propogate original alias match */
+
+       cndfree(head_alias);
+       head_alias = (*mp->m_headali ? getcpy(mp->m_headali) :
+                                      getcpy(mp->m_mbox));
+}
+
+
+addfile(file)
+       char *file;
+{
+       register char *cp, *pp;
+       char line[128], pbuf[64];
+       FILE *f;
+
+/***    printf("addfile(%s)\n", file);          ***/
+       if((f = fopen(file, "r")) == NULL) {
+               fprintf(stderr, "Can't open ");
+               perror(file);
+               done(1);
+       }
+       while(fgets(line, sizeof line, f)) {
+               cp = line;
+               while(pp = parse(cp, pbuf)) {
+                       cinsert(pp);
+                       cp = setptr(NEXT);
+               }
+       }
+       VOID fclose(f);
+}
+
+addgroup(group)
+       char *group;
+{
+       register char *cp, *pp;
+       int found = 0;
+       char line[128], pbuf[64], *rindex();
+       FILE *f;
+
+/***    printf("addgroup(%s)\n", group);        ***/
+       if((f = fopen(GROUP, "r")) == NULL) {
+               fprintf(stderr, "Can't open ");
+               perror(GROUP);
+               done(1);
+       }
+       while(fgets(line, sizeof line, f)) {
+               pp = parse(line, pbuf);
+               if(strcmp(pp, group) == 0) {
+                       cp = rindex(line, ':');
+                       while(pp = parse(cp, pbuf)) {
+                               cinsert(pp);
+                               cp = setptr(NEXT);
+                       }
+                       found++;
+               }
+       }
+       if(!found) {
+               fprintf(stderr, "Group: %s non-existent\n", group);
+               done(1);
+       }
+       VOID fclose(f);
+}
+
+addall()
+{
+       register struct shome *h;
+
+/***    printf("addall()\n");                   ***/
+       for(h = homes; h; h = h->h_next)
+               if(h->h_uid >= EVERYONE)
+                       cinsert(h->h_name);
+}
+
+remove(mp)              /* Remove NEXT from argument node! */
+       register struct mailname *mp;
+{
+       register struct mailname *rp;
+
+       rp = mp->m_next;
+       mp->m_next = rp->m_next;
+       cndfree(rp->m_mbox);
+       cndfree(rp->m_host);
+       cndfree(rp->m_text);
+       cndfree(rp->m_headali);
+       cndfree( (char *)rp);
+}
+
+int     alarmed;
+
+alarmclock()
+{
+       alarmed++;
+}
+
+char    **environ;
+char    *empty[] = {0};
+
+calluserprog(prog, mail, fd, h, head_alias)
+       char *prog, *mail, *head_alias;
+       int fd;
+       register struct shome *h;
+{
+       register int pid, child, i;
+       int status;
+
+       if(verbose) {
+               printf("Invoking %s ", prog);  fflush(stdout);
+       }
+       i = 0;
+       while((child = fork()) == -1)
+               if(++i > 10) {
+                       fprintf(stderr, "Can't get a fork to invoke %s!\n",
+                               prog);
+                       donecd = 1;
+                       return;
+               } else
+                       sleep(2);
+       if(child == 0) {                /* In child... */
+               if(fd != 3)
+                       dup2(fd, 3);
+               for(i = 4; i < 15; i++)
+                       VOID close(i);
+               environ = empty;
+               putenv("USER", h->h_name);
+               putenv("HOME", h->h_home);
+               VOID setgid(h->h_gid);
+               VOID setuid(h->h_uid);
+               execlp(prog, prog, tmpfil, mail, h->h_home, head_alias, 0);
+               perror(prog);
+               done(-1);
+       }
+       VOID signal(SIGALRM, alarmclock);
+       alarmed = 0;
+       VOID alarm(120);                 /* Give receive proc 120 secs */
+       status = 0;
+       while((pid = wait(&status)) != -1 && pid != child && !alarmed) ;
+       if(alarmed) {
+               VOID kill(0, SIGINT);
+               VOID signal(SIGALRM, alarmclock);
+               alarmed = 0;
+               VOID alarm(120);
+               while((pid = wait(&status)) != -1 && pid != child && !alarmed) ;
+               if(alarmed) {
+                       VOID kill(child, SIGKILL);
+                       VOID signal(SIGALRM, alarmclock);
+                       alarmed = 0;
+                       VOID alarm(120);
+                       while((pid = wait(&status)) != -1 && pid != child && !alarmed) ;
+               }
+               fprintf(stderr, "Deliver: Killed %s--Took more than 120 seconds!\n",
+                       prog);
+               donecd = 1;
+               status = 0;
+       } else
+               VOID alarm(0);
+       if(status) {
+               printf("Deliver: %s error %d from %s on delivery to %s\n",
+                       status&0377? "System" : "User",
+                       status&0377? status&0377 : status>>8,
+                       prog, h->h_name);
+               donecd = 1;
+       }
+       if(pid == -1) {
+               fprintf(stderr, "Deliver: wait on receive process returned -1\n");
+               perror("");
+               donecd = 1;
+       }
+}
+
+aleq(string, aliasent)
+       register char *string, *aliasent;
+{
+       register int c;
+
+       while(c = *string++)
+               if(*aliasent == '*')
+                       return(STAR);
+               else if((c|040) != (*aliasent|040))
+                       return(0);
+               else
+                       aliasent++;
+/***    return(*aliasent == 0 | *aliasent == '*');   ***/
+       return(*aliasent == '*' ? STAR : *aliasent == 0 ? 1 : 0);
+}
+
+fcc(file, folder)
+       char *file, *folder;
+{
+       int child, pid, status;
+       char fold[128];
+
+       if(verbose) {
+               printf("Fcc: %s...", folder);   fflush(stdout);
+       }
+       while((child = fork()) == -1) sleep(5);
+       if(child == 0) {
+               if(*file != '+')
+                       strcpy(fold, "+");
+               strcat(fold, folder);
+               VOID setuid(myuid);
+               execl(fileproc, "file", "-link", "-file", file, fold, 0);
+               exit(-1);
+       } else while((pid = wait(&status)) != -1 && pid != child) ;
+       if(status)
+               fprintf(stderr, "Deliver: Error on fcc to %s\n", folder);
+       else if(verbose)
+               p
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/progs/dist.c b/docs/historical/mh-jun-1982/progs/dist.c
new file mode 100644 (file)
index 0000000..67a0c11
--- /dev/null
@@ -0,0 +1,295 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+#include <stdio.h>
+#include <signal.h>
+#include <strings.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#define NOUSE 0
+
+/* #define TEST 1 */
+
+struct swit anyl[] = {
+       "no",   0,
+       "yes",  0,
+       "list", 0,
+       0,
+};
+
+struct swit aleqs[] = {
+       "list",                 0,      /* 0 */
+       "edit [<editor>]",      0,      /* 1 */
+       "quit [delete]",        0,      /* 2 */
+       "send [switches]",      0,      /* 3 */
+       0
+};
+
+struct msgs *mp;
+char drft[128];
+int inplace;            /* preserve links in anno */
+
+struct swit switches[] = {
+       "annotate",           0,      /* 0 */
+       "noannotate",         0,      /* 1 */
+       "editor editor",      0,      /* 2 */
+       "form formfile",      0,      /* 3 */
+       "inplace",            0,      /* 4 */
+       "noinplace",          0,      /* 5 */
+       "help",               4,      /* 6 */
+       0,                    0
+};
+
+/*ARGSUSED*/
+main(argc, argv)
+char *argv[];
+{
+       char *folder, *maildir, *msgs[100], *ed, *form;
+       register int msgnum;
+       register char *cp, **ap;
+       int msgp, anot;
+       int in, out;
+       int pid, wpid;
+       char *arguments[50], **argp;
+
+       invo_name = argv[0];
+#ifdef NEWS
+       m_news();
+#endif
+       anot = 0; folder = 0; msgp = 0; ed = 0; form = 0;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       VOID copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                            /* unknown */
+                       case -1:fprintf(stderr, "dist: -%s unknown\n", cp);
+                               goto leave;
+                       case 0: anot = 1;  continue;         /* -annotate */
+                       case 1: anot = 0;  continue;         /* -noannotate */
+                       case 2: if(!(ed = *argp++)) {        /* -editor */
+      missing:  fprintf(stderr, "dist: Missing argument for %s switch\n", argp[-2]);
+                                       goto leave;
+                               }
+                               continue;
+                       case 3: if(!(form = *argp++))        /* -form */
+                                       goto missing;
+                               continue;
+                       case 4: inplace = 1;  continue;      /* -inplace */
+                       case 5: inplace = 0;  continue;      /* -noinplace */
+                                                            /* -help */
+                       case 6: help("dist   [+folder] [msg] [switches]",
+                                    switches);
+                               goto leave;
+                       }
+               if(*cp == '+') {
+                       if(folder) {
+                               fprintf(stderr, "Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               folder = path(cp+1, TFOLDER);
+               } else
+                       msgs[msgp++] = cp;
+       }
+       if(!m_find("path")) free(path("./", TFOLDER));
+       if(!msgp)
+               msgs[msgp++] = "cur";
+       if(!folder)
+               folder = m_getfolder();
+       maildir = m_maildir(folder);
+       if(chdir(maildir) < 0) {
+               fprintf(stderr, "Can't chdir to: ");
+               perror(maildir);
+               goto leave;
+       }
+       if(!(mp = m_gmsg(folder))) {
+               fprintf(stderr, "Can't read folder!?\n");
+               goto leave;
+       }
+       if(mp->hghmsg == 0) {
+               fprintf(stderr, "No messages in \"%s\".\n", folder);
+               goto leave;
+       }
+       for(msgnum = 0; msgnum < msgp; msgnum++)
+               if(!m_convert((cp = msgs[msgnum])))
+                       goto leave;
+       if(mp->numsel == 0) {
+               fprintf(stderr, "dist: Tuna Melt\n");     /* never get here */
+               goto leave;
+       }
+       if(mp->numsel > 1) {
+               fprintf(stderr, "Only one message at a time.\n");
+               goto leave;
+       }
+       if(form) {
+               if((in = open(m_maildir(form), 0)) < 0) {
+                       fprintf(stderr, "dist: Can't open form file: %s\n", form);
+                       goto leave;
+               }
+       } else if(/***(in = open(m_maildir(distcomps), 0)) < 0 &&      ***/
+                  (in = open(stddcomps, 0)) < 0) {
+                       fprintf(stderr, "dist: Can't open default components file!!\n");
+                       goto leave;
+       }
+       VOID copy(m_maildir(draft), drft);
+       if((out = open(drft, 0)) >= 0) {
+               if(!fdcompare(in, out)) {
+                       cp = concat("\"", drft, "\" exists; Delete? ", 0);
+                       while((msgnum = gans(cp, anyl)) == 2)
+                               VOID showfile(drft);
+                       if(!msgnum)
+                               return;
+               }
+               VOID close(out);
+       }
+       if((out = creat(drft, m_gmprot())) < 0) {
+               fprintf(stderr, "Can't create \"%s\"\n", drft);
+               goto leave;
+       }
+       cpydata(in, out);
+       VOID close(in);
+       if((in = open(cp = m_name(mp->lowsel), 0)) < 0) {
+               fprintf(stderr, "Can't open message \"%s\"\n", cp);
+               VOID unlink(drft);
+               goto leave;
+       }
+       cpydata(in, out);
+       VOID close(in);
+       VOID close(out);
+       m_replace(pfolder, folder);
+       if(mp->lowsel != mp->curmsg)
+               m_setcur(mp->lowsel);
+       if(m_edit(&ed, drft, NOUSE, NULLCP) < 0)
+               goto leave;
+#ifdef TEST
+       fprintf(stderr, "!! Test Version of SEND Being Run !!\n");
+       fprintf(stderr, "   Send verbose !\n\n");
+#endif
+
+    for(;;) {
+       if(!(argp = getans("\nWhat now? ", aleqs)))
+               goto leave;
+       switch(smatch(*argp, aleqs)) {
+               case 0: VOID showfile(drft);                    /* list */
+                       break;
+
+               case 1: if(*++argp)                             /* edit */
+                               ed = *argp;
+                       if(m_edit(&ed, drft, NOUSE, NULLCP) == -1)
+                               goto leave;
+                       break;
+
+               case 2: if(*++argp && (*argp[0] == 'd' ||       /* quit */
+                                      (*argp[0]=='-' && *argp[1]=='d')))
+                               if(unlink(drft) == -1)  {
+                                       fprintf(stderr, "Can't unlink %s ", drft);
+                                       perror("");
+                               }
+                       goto leave;
+               case 3:                                         /* send */
+                       if(!mp->msgflags&READONLY) {    /* annotate first */
+                           if(anot > 0) {
+                               while((pid = fork()) == -1) sleep(5);
+                               if(pid) {
+                                       while((wpid=wait((int *)NULL))!= -1
+                                             && wpid != pid);
+                                       doano();
+                                       goto leave;
+                               }
+                           }
+                       }
+                       VOID m_send(++argp, drft);
+                       goto leave;
+
+               default:fprintf(stderr, "dist: illegal option\n");       /*##*/
+                       break;
+       }
+    }
+
+ leave:
+       m_update();
+       done(0);
+}
+
+
+cpydata(in, out)
+{
+       char buf[BUFSIZ];
+       register int i;
+
+       do
+               if((i = read(in, buf, sizeof buf)) > 0)
+                       if(write(out, buf, i) != i) {
+                               fprintf(stderr, "dist: error on ");
+                               perror("write");
+                               done(1);
+                       }
+       while(i == sizeof buf);
+}
+
+
+doano()
+{
+       register FILE *in;
+       char name[NAMESZ], field[256];
+       register int state;
+       register char *text;
+
+       if(stat(drft, (struct stat *)field) != -1) {
+               fprintf(stderr, "%s not sent-- no annotations made.\n", drft);
+               return;
+       }
+       text = copy(drft, field);
+       text[1] = 0;
+       do
+               *text = text[-1];
+       while(--text >= field && *text != '/');
+       *++text = ',';                  /* New backup convention */
+       if((in = fopen(field, "r")) == NULL) {
+               fprintf(stderr, "Can't open %s\n", field);
+               return;
+       }
+       state = FLD;
+       text = 0;
+   for(;;) switch(state = m_getfld(state, name, field, sizeof field, in)) {
+
+       case FLD:
+       case FLDEOF:
+       case FLDPLUS:
+               if(uleq(name, "distribute-to") ||
+                  uleq(name, "distribute-cc") ) {
+                       if(state == FLD) {
+                               text = add(name, text);
+                               text = add(":", text);
+                       }
+                       text = add(field, text);
+               }
+               if(state == FLDEOF)
+                       goto out;
+               continue;
+       case BODY:
+       case BODYEOF:
+               goto out;
+       default:
+               fprintf(stderr, "Getfld returned %d\n", state);
+               return;
+       }
+
+out:
+       VOID fclose(in);
+       annotate(m_name(mp->lowsel), "Distributed", text, inplace);
+}
diff --git a/docs/historical/mh-jun-1982/progs/file.c b/docs/historical/mh-jun-1982/progs/file.c
new file mode 100644 (file)
index 0000000..3421ef8
--- /dev/null
@@ -0,0 +1,257 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+#include "../folder.h"
+#include <stdio.h>
+
+#define NFOLD 20                /* Allow 20 folder specs */
+char *calloc();
+
+/* file [-src folder] [msgs] +folder [+folder ...]
+ *
+ * moves messages from src folder (or current) to other one(s).
+ *
+ *  all = 1-999 (MAXFOLDER) for a message sequence
+ *  -preserve says preserve msg numbers
+ *  -link says don't delete old msg
+ */
+
+extern struct swit anoyes[];    /* Std no/yes gans array */
+
+int vecp, foldp, prsrvf;
+char **vec, maildir[128], *folder;
+struct msgs *mp;
+
+struct st_fold folders[NFOLD];
+
+char   *files[NFOLD + 1];       /* Vec of files to process--starts at 1! */
+int     filec = 1;
+
+struct swit switches[] = {
+       "all",           -3,      /* 0 */
+       "link",           0,      /* 1 */
+       "nolink",         0,      /* 2 */
+       "preserve",       0,      /* 3 */
+       "nopreserve",     0,      /* 4 */
+       "src +folder",    0,      /* 5 */
+       "file",           0,      /* 6 */
+       "help",           4,      /* 7 */
+       0,                0
+};
+
+/*ARGSUSED*/
+main(argc, argv)
+char *argv[];
+{
+       register int i, msgnum;
+       register char *cp;
+       char *msgs[128];
+       int msgp, linkf;
+       char **ap;
+       char *arguments[50], **argp;
+
+       invo_name = argv[0];
+#ifdef NEWS
+       m_news();
+#endif
+       folder = 0; msgp = 0; linkf = 0;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       VOID copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                       /* unknown */
+                       case -1:fprintf(stderr, "file: -%s unknown\n", cp);
+                               goto leave;
+                                                      /* -all */
+                       case 0: fprintf(stderr, "\"-all\" changed to \"all\"\n");
+                               goto leave;
+                       case 1: linkf = 1;  continue;  /* -link */
+                       case 2: linkf = 0;  continue;  /* -nolink */
+                       case 3: prsrvf = 1;  continue; /* -preserve */
+                       case 4: prsrvf = 0;  continue; /* -nopreserve */
+                       case 5: if(folder) {           /* -src */
+                                       fprintf(stderr, "Only one src folder.\n");
+                                       goto leave;
+                               }
+                               if(!(folder = *argp++) || *folder == '-') {
+missing:        fprintf(stderr, "file: Missing argument for %s switch\n", argp[-2]);
+                                       goto leave;
+                               }
+                               if(*folder == '+')
+                                       folder++;
+                               folder = path(folder, TFOLDER);
+                               continue;
+                       case 6:
+                               if(filec >= NFOLD) {
+                                       fprintf(stderr, "Too many src files.\n");
+                                       goto leave;
+                               }
+                               if(!(cp = *argp++) || *cp == '-')
+                                       goto missing;
+                               files[filec++] = path(cp, TFILE);
+                               continue;
+
+                                                       /* -help */
+                       case 7: help("file   [msgs] [switches]  +folder ...",
+                                    switches);
+                               goto leave;
+                       }
+               if(*cp == '+')  {
+                       if(foldp < NFOLD)
+                               folders[foldp++].f_name = path(++cp, TFOLDER);
+                       else {
+                               fprintf(stderr, "Only %d folders allowed.\n", NFOLD);
+                               goto leave;
+                       }
+               } else
+                       msgs[msgp++] = cp;
+       }
+       if(!m_find("path")) free(path("./", TFOLDER));
+       if(!foldp) {
+               fprintf(stderr, "No folder specified.\n");
+fprintf(stderr, "Usage: file [-src folder] [msg ...] [switches] +folder [+folder]\n");
+               goto leave;
+       }
+       if(filec > 1) {
+               if(msgp) {
+                       fprintf(stderr, "File: Can't mix files and messages.\n");
+                       goto leave;
+               }
+               if(opnfolds())
+                       goto leave;
+               for(i = 1; i < filec; i++) {
+                       if(m_file(folder, files[i], folders, foldp, prsrvf, 0))
+                               goto leave;
+               }
+               if(!linkf) {
+                       if((cp = m_find("delete-prog")) != NULL) {
+                               files[0] = r1bindex(cp, '/');
+                               execvp(cp, files);
+                               fprintf(stderr, "Can't exec deletion-prog--");
+                               perror(cp);
+                       } else for(i = 1; i < filec; i++) {
+                               if(unlink(files[i]) == -1) {
+                                       fprintf(stderr, "Can't unlink ");
+                                       perror(files[i]);
+                               }
+                       }
+               }
+               goto leave;
+       }
+       if(!msgp)
+               msgs[msgp++] = "cur";
+       if(!folder)
+               folder = m_getfolder();
+       VOID copy(m_maildir(folder), maildir);
+       if(chdir(maildir) < 0) {
+               fprintf(stderr, "Can't chdir to: ");
+               perror(maildir);
+               goto leave;
+       }
+       if(!(mp = m_gmsg(folder))) {
+               fprintf(stderr, "Can't read folder %s!?\n",folder);
+               goto leave;
+       }
+       if(mp->hghmsg == 0) {
+               fprintf(stderr, "No messages in \"%s\".\n", folder);
+               goto leave;
+       }
+       for(msgnum = 0; msgnum < msgp; msgnum++)
+               if(!m_convert((cp = msgs[msgnum])))
+                       goto leave;
+       if(mp->numsel == 0) {
+               fprintf(stderr, "file:  ham 'n cheese\n");       /* never get here */
+               goto leave;
+       }
+       m_replace(pfolder, folder);
+       if(mp->hghsel != mp->curmsg && ((mp->numsel != mp->nummsg) || linkf))
+               m_setcur(mp->hghsel);
+       if(opnfolds())
+               goto leave;
+       for(msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
+               if(mp->msgstats[msgnum] & SELECTED)
+                       if(m_file(folder, cp = getcpy(m_name(msgnum)),
+                                 folders, foldp, prsrvf, 0))
+                               goto leave;
+                       else
+                               cndfree(cp);
+       if(!linkf) {
+               if((cp = m_find("delete-prog")) != NULL) {
+                       if(mp->numsel > MAXARGS-2) {
+         fprintf(stderr, "file: more than %d messages for deletion-prog\n",MAXARGS-2);
+                               printf("[messages not unlinked]\n");
+                               goto leave;
+                       }
+                       vecp = 1;
+                       vec = (char **) calloc(MAXARGS + 2, sizeof *vec);
+                       for(msgnum= mp->lowsel; msgnum<= mp->hghsel; msgnum++)
+                               if(mp->msgstats[msgnum]&SELECTED)
+                                       vec[vecp++] = getcpy(m_name(msgnum));
+                       vec[vecp] = 0;
+                       m_update();
+                       VOID fflush(stdout);
+                       vec[0] = r1bindex(cp, '/');
+                       execv(vec[0], vec);
+                       fprintf(stderr, "Can't exec deletion-prog--");
+                       perror(cp);
+               } else {
+                       for(msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
+                               if(mp->msgstats[msgnum] & SELECTED)
+                                       if(unlink(cp = m_name(msgnum))== -1) {
+                                               fprintf(stderr, "Can't unlink %s:",folder);
+                                               perror(cp);
+                                       }
+               }
+       }
+leave:
+       m_update();
+       done(0);
+}
+
+
+opnfolds()
+{
+       register int i;
+       register char *cp;
+       char nmaildir[128];
+
+       for(i = 0; i < foldp; i++) {
+               VOID copy(m_maildir(folders[i].f_name), nmaildir);
+               if(access(nmaildir, 5) < 0) {
+                       cp = concat("Create folder \"", nmaildir, "\"? ", 0);
+                       if(!gans(cp, anoyes))
+                               goto bad;
+                       free(cp);
+                       if(!makedir(nmaildir)) {
+                               fprintf(stderr, "Can't create folder.\n");
+                               goto bad;
+                       }
+               }
+               if(chdir(nmaildir) < 0) {
+                       fprintf(stderr, "Can't chdir to: ");
+                       perror(nmaildir);
+                       goto bad;
+               }
+               if(!(folders[i].f_mp = m_gmsg(folders[i].f_name))) {
+                       fprintf(stderr, "Can't read folder %s\n", folders[i].f_name);
+                       goto bad;
+               }
+       }
+       VOID chdir(maildir);    /* return to src folder */
+       return(0);
+bad:
+       retur
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/progs/folder.c b/docs/historical/mh-jun-1982/progs/folder.c
new file mode 100644 (file)
index 0000000..2a046b7
--- /dev/null
@@ -0,0 +1,322 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <strings.h>
+
+#define NFOLDERS 300
+
+int all, hdrflag, foldp;
+struct msgs *mp;
+char folder[128], *folds[NFOLDERS];
+int msgtot, foldtot, totonly, fshort;
+int fpack;
+struct swit switches[] = {
+       "all",          0,      /* 0 */
+       "down",         0,      /* 1 */
+       "fast",         0,      /* 2 */
+       "nofast",       0,      /* 3 */
+       "header",       0,      /* 4 */
+       "noheader",     0,      /* 5 */
+       "pack",         0,      /* 6 */
+       "nopack",       0,      /* 7 */
+       "short",       -1,      /* 8 */
+       "total",        0,      /* 9 */
+       "nototal",      0,      /*10 */
+       "up",           0,      /*11 */
+       "help",         4,      /*12 */
+       0,              0
+};
+
+extern  char _sobuf[];          /* MLW  standard out buffer */
+
+/*ARGSUSED*/
+main(argc, argv)
+char *argv[];
+{
+       register char *cp, *curm;
+       register int i;
+       char *argfolder;
+       int up, down, def_short = 0;
+       char *arguments[50], **argp, **ap;
+       struct stat stbf;
+       struct node *np;
+       struct { short  inum;
+                char   name[14];
+                int    pad;
+       } ent;
+
+       invo_name = argv[0];
+       setbuf(stdout, _sobuf);
+#ifdef NEWS
+       m_news();
+#endif
+       up = down = 0;
+       argfolder = NULL;
+       curm = 0;
+       /* set -all if program name ends in 's' -- "folders" */
+       if(argv[0][strlen(argv[0])-1] == 's')   /* Plural name?? */
+               all++;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       VOID copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);     /* ambiguous */
+                               goto leave;
+                                                          /* unknown */
+                       case -1:fprintf(stderr, "folder: -%s unknown\n", cp);
+                               goto leave;
+                       case 0: all++;  continue;          /* -all      */
+                       case 1: down++;  continue;         /* -down     */
+                       case 2:                            /* -fast     */
+                       case 8: fshort = 1; continue;      /* -short    */
+                       case 3: fshort = 0; continue;      /* -nofast   */
+                       case 4: hdrflag = -1;  continue;   /* -header   */
+                       case 5: hdrflag = 0;  continue;    /* -noheader */
+                       case 6: fpack = 1; continue;       /* -pack     */
+                       case 7: fpack = 0; continue;       /* -nopack   */
+                       case 9: all++; totonly = 1;        /* -total    */
+                               continue;
+                       case 10:if(totonly) all--;         /* -nototal  */
+                               totonly =0;  continue;
+                       case 11:up++;  continue;           /* -up       */
+                                                          /* -help     */
+                       case 12:help("folder [+folder]  [msg] [switches]",
+                                    switches);
+                               goto leave;
+                       }
+               if(*cp == '+') {
+                       if(argfolder) {
+                               fprintf(stderr, "Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               argfolder = path(cp+1, TFOLDER);
+               } else if(curm) {
+                       fprintf(stderr, "Only one current may be given.\n");
+                       goto leave;
+               } else
+                       curm = cp;
+       }
+                               /* free() has side affects!!! */
+       if(!m_find("path")) free(path("./", TFOLDER));
+       if(all) {
+               hdrflag = 0;
+               cp = m_maildir("");
+               m_getdefs();
+               for(np = m_defs; np; np = np->n_next) {
+                       if(!ssequal("cur-", np->n_name))
+                               continue;
+                       if(fshort) {
+                               def_short++;
+                               printf("%s\n", np->n_name+4);
+                       } else
+                               addfold(np->n_name+4);
+               }
+               if(def_short)
+                       putchar('\n');
+               if(fshort) {
+                       m_update();
+                       VOID fflush(stdout);
+                       execl(lsproc, r1bindex(lsproc, '/'), "-x", cp, 0);
+                       fprintf(stderr, "Can't exec: ");
+                       perror(lsproc);
+                       goto leave;
+               }
+               if(chdir(cp) < 0) {
+                       fprintf(stderr, "Can't chdir to: ");
+                       perror(cp);
+                       goto leave;
+               }
+               if((cp = m_find(pfolder)) == NULL)
+                       *folder = 0;
+               else
+                       VOID copy(cp, folder);
+               i = open(".", 0);
+               ent.pad = 0;
+               while(read(i, (char *)&ent.inum,
+                          sizeof ent.name + sizeof ent.inum))
+                       if(ent.inum && ent.name[0] != '.' &&
+                          stat(ent.name, &stbf) >= 0 &&
+                          (stbf.st_mode&S_IFMT) == S_IFDIR)
+                               addfold(ent.name);
+               VOID close(i);
+               for(i = 0; i < foldp; i++) {
+                       VOID pfold(folds[i], NULLCP); VOID fflush(stdout);
+               }
+               if(!totonly)
+                       printf("\n\t\t     ");
+               printf("TOTAL= %3d message%c in %d Folder%s.\n",
+                       msgtot, msgtot!=1? 's':' ',
+                       foldtot, foldtot!=1? "s":"");
+       } else  {
+               hdrflag++;
+               if(argfolder)
+                       cp = copy(argfolder, folder);
+               else
+                       cp = copy(m_getfolder(), folder);
+               if(up) {
+                       while(cp > folder && *cp != '/') --cp;
+                       if(cp > folder)
+                               *cp = 0;
+                       argfolder = folder;
+               } else if(down) {
+                       VOID copy(listname, copy("/", cp));
+                       argfolder = folder;
+               }
+               if(pfold(folder, curm) && argfolder)
+                       m_replace(pfolder, argfolder);
+       }
+
+ leave:
+       m_update();
+       done(0);
+}
+
+
+addfold(fold)
+char *fold;
+{
+       register int i,j;
+       register char *cp;
+
+       if(foldp >= NFOLDERS) {
+               fprintf(stderr, "More than %d folders!!\n", NFOLDERS);
+               done(1);
+       }
+       cp = getcpy(fold);
+       for(i = 0; i < foldp; i++)
+               if(compare(cp, folds[i]) < 0) {
+                       for(j = foldp - 1; j >= i; j--)
+                               folds[j+1] = folds[j];
+                       foldp++;
+                       folds[i] = cp;
+                       return;
+               }
+       folds[foldp++] = cp;
+       return;
+}
+
+
+pfold(fold, curm)
+       char *fold, *curm;
+{
+       register char *mailfile;
+       register int msgnum, hole;
+       char newmsg[8], oldmsg[8];
+
+       mailfile = m_maildir(fold);
+       if(chdir(mailfile) < 0) {
+               fprintf(stderr, "Can't chdir to: ");
+               perror(mailfile);
+               return(0);
+       }
+       if(fshort) {
+               printf("%s\n", fold);
+               return(0);
+       }
+       if(!(mp = m_gmsg(folder))) {
+               fprintf(stderr, "Can't read folder %s!?\n",folder);
+               return(0);
+       }
+       foldtot++;
+       msgtot += mp->nummsg;
+       if(fpack) {
+           for(msgnum = mp->lowmsg, hole = 1; msgnum <= mp->hghmsg; msgnum++) {
+               if(mp->msgstats[msgnum]&EXISTS) {
+                       if(msgnum != hole) {
+                               VOID copy(m_name(hole), newmsg);
+                               VOID copy(m_name(msgnum), oldmsg);
+                               if(link(oldmsg, newmsg) == -1 ||
+                                  unlink(oldmsg) == -1) {
+                                       fprintf(stderr, "Error moving %s to ", oldmsg);
+                                       perror(newmsg);
+                                       done(1);
+                               }
+                               if (msgnum == mp->curmsg)
+                                       m_setcur(mp->curmsg = hole);
+                               mp->msgstats[hole] = mp->msgstats[msgnum];
+                               if(msgnum == mp->lowsel)
+                                       mp->lowsel = hole;
+                               if(msgnum == mp->hghsel)
+                                       mp->hghsel = hole;
+                       }
+                       hole++;
+               }
+           }
+           if(mp->nummsg > 0) {
+               mp->lowmsg = 1;
+               mp->hghmsg = hole - 1;
+           }
+       }
+       if(totonly)
+               goto out;
+       if(curm) {
+               if(!m_convert(curm))
+                       return(0);
+               if(mp->numsel > 1) {
+                       fprintf(stderr, "Can't set current msg to range: %s\n", curm);
+                       return(0);
+               }
+               m_setcur(mp->curmsg = mp->hghsel);
+       }
+       if(!hdrflag++)
+  printf("\t\tFolder   # of messages   ( range ); cur msg (other files)\n");
+       printf("%22s", fold);
+       if(strcmp(folder, fold) == 0)
+               printf("+ ");
+       else
+               printf("  ");
+       if(mp->hghmsg == 0)
+               printf("has  no messages");
+       else {
+               printf("has %3d message%s (%3d-%3d)",
+                       mp->nummsg, (mp->nummsg==1)?" ":"s",
+                       mp->lowmsg, mp->hghmsg);
+               if(mp->curmsg >= mp->lowmsg && mp->curmsg <= mp->hghmsg)
+                       printf("; cur=%3s", m_name(mp->curmsg));
+       }
+       if(mp->selist || mp->others) {
+               printf("; (");
+               if(mp->selist) {
+                       printf("%s", listname);
+                       if(mp->others)
+                               printf(", ");
+               }
+               if(mp->others)
+                       printf("others");
+               putchar(')');
+       }
+       putchar('.');
+       putchar('\n');
+out:
+       free( (char *)mp);
+       mp = 0;
+       return(1);
+}
+
+
+compare(s1, s2)
+char *s1, *s2;
+{
+       register char *c1, *c2;
+       register int i;
+
+       c1 = s1; c2 = s2;
+       while(*c1 || *c2)
+               if(i = *c1++ - *c2++)
+                       return(i);
+       retur
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/progs/forw.c b/docs/historical/mh-jun-1982/progs/forw.c
new file mode 100644 (file)
index 0000000..3096126
--- /dev/null
@@ -0,0 +1,318 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+#include <stdio.h>
+#include <signal.h>
+#include <strings.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+extern char *sprintf();
+
+#define NOUSE 0
+
+/* #define TEST 1 */
+
+struct msgs *mp;
+char drft[128];
+int inplace;            /* preserve links in anno */
+
+struct swit anyl[] = {
+       "no",   0,
+       "yes",  0,
+       "list", 0,
+       0,
+};
+
+struct swit switches[] = {
+       "all",                 -3,      /* 0 */
+       "annotate",             0,      /* 1 */
+       "noannotate",           0,      /* 2 */
+       "editor editor",        0,      /* 3 */
+       "form formfile",        0,      /* 4 */
+       "inplace",              0,      /* 5 */
+       "noinplace",            0,      /* 6 */
+       "help",                 4,      /* 7 */
+       0,                      0
+};
+
+struct swit aleqs[] = {
+       "list",                 0,      /* 0 */
+       "edit [<editor>]",      0,      /* 1 */
+       "quit [delete]",        0,      /* 2 */
+       "send [switches]",      0,      /* 3 */
+       0
+};
+
+/*ARGSUSED*/
+main(argc, argv)
+char *argv[];
+{
+       char *folder, *maildir, *msgs[100], *ed, *form;
+       register int msgnum;
+       register char *cp, **ap;
+       int msgp, anot;
+       int in, out;
+       int pid, wpid, msgcnt;
+       char *arguments[50], **argp;
+       char numbuf[5];
+
+       invo_name = argv[0];
+#ifdef NEWS
+       m_news();
+#endif
+       form = 0; anot = 0; folder = 0; msgp = 0; ed = 0;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       VOID copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                            /* unknown */
+                       case -1:fprintf(stderr, "forw: -%s unknown\n", cp);
+                               goto leave;
+                                                            /* -all */
+                       case 0: fprintf(stderr, "\"-all\" changed to \"all\"\n");
+                               goto leave;
+                       case 1: anot = 1;  continue;         /* -annotate */
+                       case 2: anot = 0;  continue;         /* -noannotate */
+                       case 3: if(!(ed = *argp++)) {        /* -editor */
+      missing:  fprintf(stderr, "forw: Missing argument for %s switch\n", argp[-2]);
+                                       goto leave;
+                               }
+                               continue;
+                       case 4: if(!(form = *argp++))        /* -form */
+                                       goto missing;
+                               continue;
+                       case 5: inplace = 1;  continue;      /* -inplace */
+                       case 6: inplace = 0;  continue;      /* -noinplace */
+                                                            /* -help */
+                       case 7: help("forw   [+folder] [msgs] [switches]",
+                                    switches);
+                               goto leave;
+                       }
+               if(*cp == '+') {
+                       if(folder) {
+                               fprintf(stderr, "Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               folder = path(cp+1, TFOLDER);
+               } else
+                       msgs[msgp++] = cp;
+       }
+       if(!m_find("path")) free(path("./", TFOLDER));
+       if(!msgp)
+               msgs[msgp++] = "cur";
+       if(!folder)
+               folder = m_getfolder();
+       maildir = m_maildir(folder);
+       if(chdir(maildir) < 0) {
+               fprintf(stderr, "Can't chdir to: ");
+               perror(maildir);
+               goto leave;
+       }
+       if(!(mp = m_gmsg(folder))) {
+               fprintf(stderr, "Can't read folder!?\n");
+               goto leave;
+       }
+       if(mp->hghmsg == 0) {
+               fprintf(stderr, "No messages in \"%s\".\n", folder);
+               goto leave;
+       }
+       for(msgnum = 0; msgnum < msgp; msgnum++)
+               if(!m_convert(msgs[msgnum]))
+                       goto leave;
+       if(mp->numsel == 0) {
+               fprintf(stderr, "forw: italian salami.\n");      /* never get here */
+               goto leave;
+       }
+       if(form) {
+               if((in = open(m_maildir(form), 0)) < 0) {
+                       fprintf(stderr, "forw: Can't open form file: %s\n", form);
+                       goto leave;
+               }
+       } else if((in = open(m_maildir(components), 0)) < 0 &&
+                  (in = open(stdcomps, 0)) < 0) {
+                       fprintf(stderr, "forw: Can't open default components file!!\n");
+                       goto leave;
+       }
+       VOID copy(m_maildir(draft), drft);
+       if((out = open(drft, 0)) >= 0) {
+               if(!fdcompare(in, out)) {
+                       cp = concat("\"", drft, "\" exists; Delete? ", 0);
+                       while((msgnum = gans(cp, anyl)) == 2)
+                               VOID showfile(drft);
+                       if(!msgnum)
+                               return;
+               }
+               VOID close(out);
+       }
+       if((out = creat(drft, m_gmprot())) < 0) {
+               fprintf(stderr, "Can't create \"%s\"\n", drft);
+               goto leave;
+       }
+       cpydata(in, out);
+       VOID close(in);
+       for(msgcnt = 1, msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
+               if(mp->msgstats[msgnum]&SELECTED)  {
+                       if((in = open(cp = m_name(msgnum), 0)) < 0) {
+                               fprintf(stderr, "Can't open message \"%s\"\n", cp);
+                               VOID unlink(drft);
+                               goto leave;
+                       }
+                       VOID type(out, "\n\n-------");
+                       if(msgnum == mp->lowsel) {
+                               VOID type(out, " Forwarded Message");
+                               if(mp->numsel > 1)
+                                       VOID type(out, "s");
+                       } else {
+                               VOID type(out, " Message ");
+                               VOID sprintf(numbuf, "%d", msgcnt);
+                               VOID type(out, numbuf);
+                       }
+                       VOID type(out, "\n\n");
+                       cpydata(in, out);
+                       VOID close(in);
+                       msgcnt++;
+               }
+       VOID type(out, "\n\n------- End of Forwarded Message");
+       if(mp->numsel > 1)
+               VOID type(out, "s");
+       VOID type(out, "\n");
+       VOID close(out);
+       m_replace(pfolder, folder);
+       if(mp->lowsel != mp->curmsg)
+               m_setcur(mp->lowsel);
+       if(m_edit(&ed, drft, NOUSE, NULLCP) < 0)
+               goto leave;
+
+#ifdef TEST
+       fprintf(stderr, "!! Test Version of SEND Being Run !!\n");
+       fprintf(stderr, "   Send verbose !\n\n");
+#endif
+    for(;;) {
+       if(!(argp = getans("\nWhat now? ", aleqs)))
+               goto leave;
+       switch(smatch(*argp, aleqs)) {
+               case 0: VOID showfile(drft);                         /* list */
+                       break;
+
+               case 1: if(*++argp)                             /* edit */
+                               ed = *argp;
+                       if(m_edit(&ed, drft, NOUSE, NULLCP) == -1)
+                               goto leave;
+                       break;
+               case 2: if(*++argp && (*argp[0] == 'd' ||       /* quit */
+                                      (*argp[0]=='-' && *argp[1]=='d')))
+                               if(unlink(drft) == -1)  {
+                                       fprintf(stderr, "Can't unlink %s ", drft);
+                                       perror("");
+                               }
+                       goto leave;
+
+               case 3:                                         /* send */
+                       if(!mp->msgflags&READONLY) {    /* annotate first */
+                           if(anot > 0) {
+                               while((pid = fork()) == -1) sleep(5);
+                               if(pid) {
+                                       while((wpid=wait((int *)NULL))!= -1
+                                             && wpid!= pid);
+                                       doano();
+                                       goto leave;
+                               }
+                           }
+                       }
+                       VOID m_send(++argp, drft);
+                       goto leave;
+
+               default:fprintf(stderr, "forw: illegal option\n");       /*##*/
+                       break;
+       }
+    }
+
+ leave:
+       m_update();
+       done(0);
+}
+
+
+cpydata(in, out)
+{
+       char buf[BUFSIZ];
+       register int i;
+
+       do
+               if((i = read(in, buf, sizeof buf)) > 0)
+                       if(write(out, buf, i) != i) {
+                               fprintf(stderr, "forw: write ");
+                               perror("error");
+                               done(1);
+                       }
+       while(i == sizeof buf);
+}
+
+
+doano()
+{
+       FILE *in;
+       char name[NAMESZ], field[256];
+       register int ind, state;
+       register char *text;
+
+       if(stat(drft, (struct stat *)field) != -1) {
+               fprintf(stderr, "%s not sent-- no annotations made.\n", drft);
+               return;
+       }
+       text = copy(drft, field);
+       text[1] = 0;
+       do
+               *text = text[-1];
+       while(--text >= field && *text != '/');
+       *++text = ',';                  /* New backup convention */
+       if((in = fopen(field, "r")) == NULL) {
+               fprintf(stderr, "Can't open "); perror(field);
+               return;
+       }
+       state = FLD;
+       text = 0;
+   for(;;) switch(state = m_getfld(state, name, field, sizeof field, in)) {
+
+       case FLD:
+       case FLDEOF:
+       case FLDPLUS:
+               if(uleq(name, "to") || uleq(name, "cc") ) {
+                       if(state == FLD) {
+                               text = add(name, text);
+                               text = add(":", text);
+                       }
+                       text = add(field, text);
+               }
+               if(state == FLDEOF)
+                       goto out;
+               continue;
+       case BODY:
+       case BODYEOF:
+               goto out;
+       default:
+               fprintf(stderr, "Getfld returned %d\n", state);
+               return;
+       }
+
+out:
+       VOID fclose(in);
+
+       for(ind = mp->lowsel; ind <= mp->hghsel; ind++)
+               if(mp->msgstats[ind] & SELECTED)
+                       VOID annotate(m_name(ind), "Forwarded", text, inpl
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/progs/grep.c b/docs/historical/mh-jun-1982/progs/grep.c
new file mode 100644 (file)
index 0000000..df270c6
--- /dev/null
@@ -0,0 +1,287 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include <stdio.h>
+#define        CCHR    2
+#define        CDOT    4
+#define        CCL     6
+#define        NCCL    8
+#define        CDOL    10
+#define        CEOF    11
+
+#define        STAR    01
+
+#define LBSIZE  1024
+#define        ESIZE   256
+
+char    ibuf[BUFSIZ];
+char   expbuf[ESIZE];
+char   linebuf[LBSIZE+1];
+int    circf;
+
+char cc[] = {
+       0000,0001,0002,0003,0004,0005,0006,0007,
+       0010,0011,0012,0013,0014,0015,0016,0017,
+       0020,0021,0022,0023,0024,0025,0026,0027,
+       0030,0031,0032,0033,0034,0035,0036,0037,
+       0040,0041,0042,0043,0044,0045,0046,0047,
+       0050,0051,0052,0053,0054,0055,0056,0057,
+       0060,0061,0062,0063,0064,0065,0066,0067,
+       0070,0071,0072,0073,0074,0075,0076,0077,
+       0100,0141,0142,0143,0144,0145,0146,0147,
+       0150,0151,0152,0153,0154,0155,0156,0157,
+       0160,0161,0162,0163,0164,0165,0166,0167,
+       0170,0171,0172,0133,0134,0135,0136,0137,
+       0140,0141,0142,0143,0144,0145,0146,0147,
+       0150,0151,0152,0153,0154,0155,0156,0157,
+       0160,0161,0162,0163,0164,0165,0166,0167,
+       0170,0171,0172,0173,0174,0175,0176,0177,
+};
+
+
+compile(astr)
+char *astr;
+{
+       register c;
+       register char *ep, *sp;
+       char *lastep;
+       int cclcnt;
+
+       ep = expbuf;
+       sp = astr;
+       if (*sp == '^') {
+               circf++;
+               sp++;
+       }
+       for (;;) {
+               if (ep >= &expbuf[ESIZE])
+                       goto cerror;
+               if ((c = *sp++) != '*')
+                       lastep = ep;
+               switch (c) {
+
+               case '\0':
+                       *ep++ = CEOF;
+                       return(1);
+
+               case '.':
+                       *ep++ = CDOT;
+                       continue;
+
+               case '*':
+                       if (lastep==0)
+                               goto defchar;
+                       *lastep |= STAR;
+                       continue;
+
+               case '$':
+                       if (*sp != '\0')
+                               goto defchar;
+                       *ep++ = CDOL;
+                       continue;
+
+               case '[':
+                       *ep++ = CCL;
+                       *ep++ = 0;
+                       cclcnt = 1;
+                       if ((c = *sp++) == '^') {
+                               c = *sp++;
+                               ep[-2] = NCCL;
+                       }
+                       do {
+                               *ep++ = c;
+                               cclcnt++;
+                               if (c=='\0' || ep >= &expbuf[ESIZE])
+                                       goto cerror;
+                       } while ((c = *sp++) != ']');
+                       lastep[1] = cclcnt;
+                       continue;
+
+               case '\\':
+                       if ((c = *sp++) == '\0')
+                               goto cerror;
+               defchar:
+               default:
+                       *ep++ = CCHR;
+                       *ep++ = c;
+               }
+       }
+    cerror:
+       return(0);
+}
+
+
+execute(file)
+char *file;
+{
+       register char *p1, *p2;
+       register c;
+       int f, body, lf;
+       char *ebp, *cbp;
+
+       if ((f = open(file, 0)) < 0) {
+               fprintf(stderr, "Grep: Can't open %s\n", file);
+               return(0);
+       }
+       body = 0;
+       ebp = ibuf;
+       cbp = ibuf;
+       for (;;) {
+               p1 = linebuf;
+               p2 = cbp;
+               lf = 0;
+               for (;;) {
+                       if (p2 >= ebp) {
+                               if ((c = read(f, ibuf, sizeof ibuf)) <= 0) {
+                                       close(f);
+                                       if(lf) break; /* bodyless comp! */
+                                       return(0);
+                               }
+                               p2 = ibuf;
+                               ebp = ibuf+c;
+                       }
+                       c = *p2++;
+                       if(lf) if(c != ' ' && c != '\t') {
+                               --p2;
+                               break;
+                       } else
+                               lf = 0;
+                       if (c == '\n')
+                               if(body)
+                                       break;
+                               else {
+                                       if(lf) {
+                                               body++;
+                                               break;
+                                       }
+                                       lf++;
+                                       c = ' ';
+                               }
+                       if(c && p1 < &linebuf[LBSIZE-1])
+                               *p1++ = c;
+               }
+               *p1++ = 0;
+               cbp = p2;
+               p1 = linebuf;
+               p2 = expbuf;
+               if (circf) {
+                       if (advance(p1, p2))
+                               goto found;
+                       continue;
+               }
+               /* fast check for first character */
+               if (*p2==CCHR) {
+                       c = p2[1];
+                       do {
+                               if(*p1==c || cc[*p1]==c)
+                                       if (advance(p1, p2))
+                                               goto found;
+                       } while (*p1++);
+                       continue;
+               }
+               /* regular algorithm */
+               do {
+                       if (advance(p1, p2))
+                               goto found;
+               } while (*p1++);
+               continue;
+       found:
+               close(f);
+               return(1);
+       }
+}
+
+
+advance(alp, aep)
+char *alp, *aep;
+{
+       register char *lp, *ep, *curlp;
+
+       lp = alp;
+       ep = aep;
+       for (;;) switch (*ep++) {
+
+       case CCHR:
+               if (*ep++ == *lp++ || ep[-1] == cc[lp[-1]])
+                       continue;
+               return(0);
+
+       case CDOT:
+               if (*lp++)
+                       continue;
+               return(0);
+
+       case CDOL:
+               if (*lp==0)
+                       continue;
+               return(0);
+
+       case CEOF:
+               return(1);
+
+       case CCL:
+               if (cclass(ep, *lp++, 1)) {
+                       ep += *ep;
+                       continue;
+               }
+               return(0);
+
+       case NCCL:
+               if (cclass(ep, *lp++, 0)) {
+                       ep += *ep;
+                       continue;
+               }
+               return(0);
+
+       case CDOT|STAR:
+               curlp = lp;
+               while (*lp++);
+               goto star;
+
+       case CCHR|STAR:
+               curlp = lp;
+               while (*lp++ == *ep || cc[lp[-1]] == *ep) ;
+               ep++;
+               goto star;
+
+       case CCL|STAR:
+       case NCCL|STAR:
+               curlp = lp;
+               while (cclass(ep, *lp++, ep[-1]==(CCL|STAR)));
+               ep += *ep;
+               goto star;
+
+       star:
+               do {
+                       lp--;
+                       if (advance(lp, ep))
+                               return(1);
+               } while (lp > curlp);
+               return(0);
+
+       default:
+               printf("RE botch\n");
+               return(0);
+       }
+}
+
+
+cclass(aset, ac, af)
+char *aset;
+{
+       register char *set, c;
+       register n;
+
+       set = aset;
+       if ((c = ac) == 0)
+               return(0);
+       n = *set++;
+       while (--n)
+               if (*set++ == c)
+                       return(af);
+       return(!af);
+}
diff --git a/docs/historical/mh-jun-1982/progs/inc.c b/docs/historical/mh-jun-1982/progs/inc.c
new file mode 100644 (file)
index 0000000..cbfe8d8
--- /dev/null
@@ -0,0 +1,279 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <strings.h>
+#include <signal.h>
+#include "scansub.h"
+
+extern char *sprintf();
+
+extern struct swit anoyes[];    /* Std no/yes gans array */
+
+char    scanl[];
+struct  msgs *mp;
+FILE    *in, *aud;
+struct  stat stbuf;
+char    *locknode;
+int     lockwait;       /* Secs to wait for lock-Def in strings/lockdir.c */
+#define LOCKWAIT (lockwait*5) /* If lock is this old, simply ignore it! */
+
+int timeflag;
+int numflag;
+
+extern  int errno;      /* MLW  4bsd does not have errno defined in errno.h */
+extern  char _sobuf[];  /* MLW  standard out buffer */
+
+struct  swit switches[] = {
+       "audit audit-file",     0,      /* 0 */
+       "ms ms-folder",         0,      /* 1 */
+       "help",                 4,      /* 2 */
+       "changecur",            0,      /* 3 */
+       "nochangecur",          0,      /* 4 */
+       "time",                 0,      /* 5 */
+       "notime",               0,      /* 6 */
+       "numdate",              0,      /* 7 */
+       "nonumdate",            0,      /* 8 */
+       0,                      0
+};
+
+/*ARGSUSED*/
+main(argc, argv)
+char *argv[];
+{
+
+       char *newmail, maildir[128], *folder, *from, *audfile;
+       char *myname;
+       int change_cur;
+       register char *cp;
+       register int i, msgnum;
+       long now;
+       char **ap;
+       char *arguments[50], **argp;
+       int done();
+       long time();
+
+       invo_name = argv[0];
+       setbuf(stdout, _sobuf);
+#ifdef NEWS
+       m_news();
+#endif
+
+       change_cur = 1;                         /* Default */
+       from = 0; folder = 0; audfile = 0;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       VOID copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                            /* unknown */
+                       case -1:fprintf(stderr, "inc: -%s unknown\n", cp);
+                               goto leave;
+                       case 0: if(!(audfile = *argp++)) {   /* -audit */
+      missing:  fprintf(stderr, "inc: Missing argument for %s switch\n", argp[-2]);
+                                       goto leave;
+                               }
+                               continue;
+                       case 1: if(!(from = *argp++))        /* -ms */
+                                       goto missing;
+                               continue;
+                       case 2:                              /* -help */
+                               help("inc [+folder]  [switches]", switches);
+                               goto leave;
+                       case 3:
+                               change_cur = 1;
+                               continue;
+                       case 4:
+                               change_cur = 0;
+                               continue;
+                       case 5: timeflag = 1;  continue; /* -time */
+                       case 6: timeflag = 0;  continue; /* -notime */
+                       case 7: numflag = 1;  continue; /* -numdate */
+                       case 8: numflag = 0;  continue; /* -nonumdate */
+                       }
+               if(*cp == '+') {
+                       if(folder) {
+                               fprintf(stderr, "Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               folder = path(cp+1, TFOLDER);
+               } else {
+                       fprintf(stderr, "Bad arg: %s\n", argp[-1]);
+       fprintf(stderr, "Usage: inc [+folder] [-ms ms-folder] [-audit audit-file]\n");
+                       goto leave;
+               }
+       }
+       if(!m_find("path")) free(path("./", TFOLDER));
+       if(from)
+               newmail = from;
+       else {
+               if((myname = getenv("USER")) == 0) {
+                       fprintf(stderr,
+"Environment Variable \"USER\" Must be set to your login name!\n");
+                       done(1);
+               }
+               newmail = concat(mailboxes, "/", myname, NULLCP);
+/***            VOID copy(mailbox, copy(mypath, newmail));           ***/
+               if(stat(newmail, &stbuf) < 0 ||
+                  stbuf.st_size == 0) {
+                       fprintf(stderr, "No Mail to incorporate.\n");
+                       goto leave;
+               }
+       }
+       if(!folder) {
+               folder = defalt;
+               if(from && strcmp(from, "inbox") == 0) {
+                       cp = concat("Do you really want to convert from ",
+                               from, " into ", folder, "?? ", NULLCP);
+                       if(!gans(cp, anoyes))
+                               goto leave;
+                       cndfree(cp);
+               }
+       }
+       VOID copy(m_maildir(folder), maildir);
+       if(stat(maildir, &stbuf) < 0) {
+               if(errno != ENOENT) {
+                       fprintf(stderr, "Error on folder ");
+                       perror(maildir);
+                       goto leave;
+               }
+               cp = concat("Create folder \"", maildir, "\"? ", NULLCP);
+               if(!gans(cp, anoyes))
+                       goto leave;
+               if(!makedir(maildir)) {
+                       fprintf(stderr, "Can't create folder \"%s\"\n", maildir);
+                       goto leave;
+               }
+       }
+       if(chdir(maildir) < 0) {
+               fprintf(stderr, "Can't chdir to: ");
+               perror(maildir);
+               goto leave;
+       }
+       if(!(mp = m_gmsg(folder))) {
+               fprintf(stderr, "Can't read folder!?\n");
+               goto leave;
+       }
+                                       /* Lock the mail file */
+       if(!from) {
+               VOID signal(SIGINT, done);
+               cp = concat(lockdir, "/", myname, NULLCP);
+               for(i = 0; i < lockwait; i += 2) {
+                       if(link(newmail, cp) == -1) {
+                               fprintf(stderr, "Mailbox busy...\n");
+                               if(i == 0 && stat(newmail, &stbuf) >= 0)
+                                       if(stbuf.st_ctime + LOCKWAIT < time((long *)0)) {
+                                               VOID unlink(cp);
+                                               fprintf(stderr, "Removing lock.\n");
+                                               continue;
+                                       }
+                               sleep(2);
+                       } else {
+                               locknode = cp;  /* We own the lock now! */
+                               break;
+                       }
+               }
+               if(i >= lockwait) {
+                       fprintf(stderr, "Try again.\n");
+                       done(1);
+               }
+       }
+       if((in = fopen(newmail, "r")) == NULL) {
+               fprintf(stderr, "Can't open "); perror(newmail);
+               goto leave;
+       }
+       if(audfile) {
+               cp = m_maildir(audfile);
+               if((i = stat(cp, &stbuf)) < 0)
+                       fprintf(stderr, "Creating Receive-Audit: %s\n", cp);
+               if((aud = fopen(cp, "a")) == NULL) {
+                       fprintf(stderr, "Can't append to ");
+                       perror(cp);
+                       goto leave;
+               } else if(i < 0)
+                       VOID chmod(cp, 0600);
+               now = time((long *)0);
+               fputs("<<inc>> ", aud);
+               cp = cdate(&now);
+               cp[9] = ' ';
+               fputs(cp, aud);
+               if(from) {
+                       fputs("  -ms ", aud);
+                       fputs(from, aud);
+               }
+               putc('\n', aud);
+       }
+       printf("Incorporating new mail into %s...\n\n", folder);
+       VOID fflush(stdout);
+       msgnum = mp->hghmsg;
+
+       while((i = scan(in, msgnum+1, msgnum+1, msgnum == mp->hghmsg,
+                                         (timeflag ? DOTIME : 0)
+                                         | (numflag ? NUMDATE : 0), 0))) {
+               if(i == -1) {
+                       fprintf(stderr, "inc aborted!\n");
+                       if(aud)
+                               fputs("inc aborted!\n", aud);
+                       goto leave;
+               }
+               if(i == -2) {
+                       fprintf(stderr,
+                               "More than %d messages. Inc aborted!\n",
+                               MAXFOLDER);
+                       fprintf(stderr,"%s not zero'd\n", newmail);
+                       goto leave;
+               }
+               if(aud)
+                       fputs(scanl, aud);
+               VOID fflush(stdout);
+               msgnum++;
+       }
+
+       VOID fclose(in);
+       if(aud)
+               VOID fclose(aud);
+
+       if(!from) {
+               if((i = creat(newmail, 0600)) >= 0)     /* Zap .mail file */
+                       VOID close(i);
+               else
+                       fprintf(stderr, "Error zeroing %s\n", newmail);
+       } else
+               printf("%s not zero'd\n", newmail);
+
+       i = msgnum - mp->hghmsg;
+   /*   printf("%d new message%s\n", i, i==1? "":"s");          */
+       if(!i)
+               fprintf(stderr, "[No messages incorporated.]\n");
+       else {
+               m_replace(pfolder, folder);
+               if (change_cur)
+                       m_setcur(mp->hghmsg + 1);
+       }
+leave:
+       m_update();
+       done(0);
+}
+
+
+done(status)
+{
+       if(locknode);
+               VOID unlink(locknode);
+       exit(sta
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/progs/install-mh.c b/docs/historical/mh-jun-1982/progs/install-mh.c
new file mode 100644 (file)
index 0000000..21d2ffd
--- /dev/null
@@ -0,0 +1,120 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+extern struct swit anoyes[];    /* Std no/yes gans array */
+char   *malloc();
+
+char defpath[128];
+
+extern  char _sobuf[];          /* MLW  standard out buffer */
+
+main(argc, argv)
+char *argv[];
+{
+       register char *cp, *path;
+       register struct node *np;
+       int autof, exitstat;
+       struct stat stbuf;
+       char *geta();
+
+       invo_name = argv[0];
+       setbuf(stdout, _sobuf);
+       autof = (argc == 2 && strcmp(argv[1], "-auto") == 0);
+       exitstat = 1;                 /* Assume errors will occur */
+       mypath = getenv("HOME");
+/***    mypath = getpath(getruid());  /* to prevent recursion via m_getdefs */
+       VOID copy(mh_prof, copy(mypath, defpath));
+       if(stat(defpath, &stbuf) != -1) {
+           if(autof)
+               printf("Install-defs invocation error!\n");
+           else
+               printf("You already have an MH profile... use an editor \
+to modify it.\n");
+           goto leave;
+
+       }
+       if(autof || gans("Do you want help? ", anoyes)) {
+printf("\nPrior to using MH, it is necessary to have a file in your login\n");
+printf("directory (%s) named %s which contains information\n",mypath,mh_prof+1);
+printf("to direct certain MH operations.  The only item which is required\n");
+printf("is the path to use for all MH folder operations. The suggested MH\n");
+printf("path for you is %s/Mail...\n\n", mypath);
+       }
+       cp = concat(mypath, "/", "Mail", NULLCP);
+       if(stat(cp, &stbuf) != -1) {
+           if((stbuf.st_mode&S_IFMT) == S_IFDIR) {
+               cp = concat("You already have the standard MH directory \"",
+                       cp, "\".\nDo you want to use it for MH? ", NULLCP);
+               if(gans(cp, anoyes))
+                   path = "Mail";
+               else
+                   goto xyz;
+           }
+       } else {
+           cp = concat("Do you want the standard MH path \"", mypath,
+                        "/", "Mail\"? ", NULLCP);
+           if(gans(cp, anoyes))
+                   path = "Mail";
+           else {
+    xyz:        if(gans("Do you want a path below your login directory? ",
+                   anoyes)) {
+                   printf("What is the path ??  %s/", mypath);
+                   path = geta();
+               } else {
+                   printf("What is the whole path??  /");
+                   path = concat("/", geta(), NULLCP);
+               }
+           }
+       }
+       VOID chdir(mypath);
+       if(chdir(path) == -1) {
+               cp = concat("\"", path, "\" doesn't exist; Create it? ", NULLCP);
+               if(gans(cp, anoyes))
+                       if(makedir(path) == 0) {
+                               printf("Can't create it!\n");
+                               goto leave;
+                       }
+       } else
+               printf("[Using existing directory]\n");
+
+       np = m_defs = (struct node *) malloc(sizeof *np);
+       np->n_name = "Path";
+       np->n_field = path;
+       np->n_next = 0;
+       m_replace(pfolder, defalt);
+       exitstat = 0;
+
+leave:
+       m_update();
+       done(exitstat);
+}
+
+
+char *geta()
+{
+       static char line[128];
+       register char *cp;
+       register int c;
+
+       VOID fflush(stdout);
+       cp = line;
+       while((c = getchar()) != EOF) {
+               if(c == '\n') {
+                       *cp = 0;
+                       return(line);
+               }
+               if(cp < &line[128])
+                       *cp++ = c;
+       }
+       done(1);
+       /*NOTREACHED*/
+}
diff --git a/docs/historical/mh-jun-1982/progs/mail.c b/docs/historical/mh-jun-1982/progs/mail.c
new file mode 100644 (file)
index 0000000..9b61f18
--- /dev/null
@@ -0,0 +1,166 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+#include <stdio.h>
+#include <signal.h>
+
+extern char *sprintf();
+
+#define NUMTOS  10              /* Number of to's & cc's accepted */
+
+char    tmpfil[32];
+int     exitstat = 1;
+char    *subject, *body;
+
+struct swit switches[] = {
+       "body",         0,      /* 0 */
+       "cc",           0,      /* 1 */
+       "subject",      0,      /* 2 */
+       "help",         4,      /* 3 */
+       0,              0
+};
+
+main(argc, argv)
+int argc;
+char *argv[];
+{
+       register FILE *out;
+       register int i, cnt;
+       register char *cp;
+       int pid, status, top, ccp, sig(), somebody = 0;
+       char buf[BUFSIZ], *tos[NUMTOS], *ccs[NUMTOS], **argp;
+
+       invo_name = argv[0];
+       top = 0;
+       ccp = -1;               /* -1 -> collecting TOs */
+       if(argc == 1) {         /* Just call inc to read mail */
+               execlp("inc", "inc", 0);
+               perror("Mail: inc");
+               done(exitstat);
+       }
+       argp = argv + 1;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);  /* ambiguous */
+                               done(exitstat);
+                                                       /* unknown */
+                       case -1:fprintf(stderr, "send: -%s unknown\n", cp);
+                               done(exitstat);
+                                                       /* -body */
+                       case 0: if((body = *argp++) == 0) {
+                    missing:           fprintf(stderr, "Mail: Missing %s arg\n", cp);
+                                       done(exitstat);
+                               }
+                               continue;
+                                                       /* -cc */
+                       case 1: ccp = 0;                /* Now collecting ccs */
+                               continue;
+                                                       /* -subject */
+                       case 2: if((subject = *argp++) == 0)
+                                       goto missing;
+                               continue;
+                                                       /* -help */
+                       case 3: help("mail [switches] users ...",
+                                    switches);
+                               done(0);
+                       }
+               else {
+                       if(ccp >= 0) {                  /* If getting ccs..*/
+                               if(ccp < NUMTOS)
+                                       ccs[ccp++] = cp;
+                               else {
+                                       fprintf(stderr, "Mail: Too many ccs\n");
+                                       done(exitstat);
+                               }
+                       } else {                        /* Else, to */
+                               if(top < NUMTOS)
+                                       tos[top++] = cp;
+                               else {
+                                       fprintf(stderr, "Mail: Too many tos\n");
+                                       done(exitstat);
+                               }
+                       }
+               }
+       }
+                                       /* Create a mail temp file */
+       VOID sprintf(tmpfil, "/tmp/%s", makename("mail", ".tmp"));
+       if((out = fopen(tmpfil, "w")) == NULL) {
+               perror(tmpfil);
+               done(exitstat);
+       }
+       VOID signal(SIGINT, sig);       /* Clean up if user <del>s out */
+       fprintf(out, "To: ");           /* Create to list */
+       for(i = 0; i < top;) {
+               fprintf(out, "%s", tos[i]);
+               if(++i < top)
+                       fprintf(out, ", ");
+       }
+       fprintf(out, "\n");
+       if(ccp > 0) {
+               fprintf(out, "Cc: ");   /* Create cc list if needed */
+               for(i = 0; i < ccp;) {
+                       fprintf(out, "%s", ccs[i]);
+                       if(++i < ccp)
+                               fprintf(out, ", ");
+               }
+               fprintf(out, "\n");
+       }
+       if(subject)                     /* Create subject if needed */
+               fprintf(out, "Subject: %s\n", subject);
+
+       fprintf(out, "\n");
+
+       if(body) {                      /* Use body if I have it, */
+               somebody++;
+               fprintf(out, "%s\n", body);
+       } else {                        /* Otherwise, get a body */
+               while((cnt = read(0, buf, sizeof buf)) > 0) {
+                       somebody++;
+                       if(!fwrite(buf, cnt, 1, out)) {
+                               perror(tmpfil);
+                               sig();
+                       }
+               }
+       }
+
+       if(ferror(out)) {               /* Check that all wrote well */
+               fprintf(stderr, "Error writing tmp file\n");
+               sig();
+       }
+       VOID fclose(out);
+       if(!somebody)                   /* If NO body, then don't send */
+               sig();                  /*  To be compatible with BELL mail */
+       while((i = fork()) == -1) {     /* Now, deliver the mail */
+               fprintf(stderr, "Waiting for a fork...\n");
+               sleep(2);
+       }
+       if(i == 0) {                    /* Call deliverer in child */
+               execl(mh_deliver, r1bindex(mh_deliver, '/'), tmpfil, 0);
+               perror(mh_deliver);
+               done(exitstat);
+       }
+       VOID signal(SIGINT, SIG_IGN);
+       while((pid = wait(&status)) != -1 && pid != i) ;
+       if(status) {                    /* And save mail if delivery failed */
+               VOID signal(SIGINT, SIG_DFL);
+               fprintf(stderr, "Letter saved in dead.letter\n");
+               execl("/bin/mv", "mv", tmpfil, "dead.letter", 0);
+               execl("/usr/bin/mv", "mv", tmpfil, "dead.letter", 0);
+               perror("/bin/mv");
+               done(exitstat);
+       }
+       exitstat = 0;
+       sig();
+}
+
+sig()
+{
+       VOID unlink(tmpfil);
+       done(exitstat);
+}
diff --git a/docs/historical/mh-jun-1982/progs/mhl.c b/docs/historical/mh-jun-1982/progs/mhl.c
new file mode 100644 (file)
index 0000000..1441e3c
--- /dev/null
@@ -0,0 +1,762 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+/*  THIS command is included wholesale by show.c, which calls
+ *  its `main' rather than execing it when showproc is "mhl"
+ */
+
+#include <ctype.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <sgtty.h>
+#ifndef  INCLUDED_BY_SHOW
+#include <stdio.h>
+#include "../mh.h"
+#endif   INCLUDED_BY_SHOW
+char *calloc();
+extern char *index();
+extern char *sprintf();
+
+char    *ignores[25];
+char    **igp = ignores;        /* List of ignored components           */
+char    *parptr, *parse();
+char    *fmtfile;               /* User specified format file           */
+char    *folder;                /* Name of folder messages are in       */
+char    *profargs[32];          /* Args extracted from profile          */
+int     ofilec;                 /* Count of real output file args       */
+int     ofilen;                 /* Number of output file                */
+int     ontty;                  /* Output to char device                */
+int     clearflg;               /* Overrides format screen clear        */
+int     row, column;            /* For character output routine         */
+int     alength, awidth;        /* -length and -width args              */
+char    *oneline();
+int     sigcatch();
+int     exitstat;
+jmp_buf env;
+
+extern  char _sobuf[];          /* MLW  standard out buffer */
+char    *strcpy();
+
+/* Defines for c_flags (see below)                                      */
+#define NOCOMPONENT     01      /* Don't show component name            */
+#define UPPERCASE       02      /* Display in all upper case            */
+#define CENTER          04      /* Center line within width             */
+#define CLEARTEXT      010      /* Clear text line--simply copy to output */
+#define PROCESSED      020      /* This item processed already          */
+#define EXTRA          040      /* This message comp is an "extra"      */
+#define HDROUTPUT     0100      /* This comp's hdr has been output      */
+#define CLEARSCR      0200      /* Clear screen before each file        */
+#define LEFTADJUST    0400      /* Left adjust mult lines of component  */
+#define COMPRESS     01000      /* Compress text--ignore <lf's>         */
+
+struct  comp  {
+       struct comp  *c_next;   /* Chain to next                        */
+       char         *c_name,   /* Component name                       */
+                    *c_text,   /* Text associated with component       */
+                    *c_ovtxt;  /* Line overflow indicator text         */
+       int           c_offset, /* Left margin indent                   */
+                     c_ovoff,  /* Line overflow indent                 */
+                     c_width,  /* Width of field                       */
+                     c_cwidth, /* Component width (default strlen(comp)) */
+                     c_length; /* Length in lines                      */
+       short         c_flags;  /* Special flags (see above)            */
+
+} *msghd, *msgtl, *fmthd, *fmttl,
+                               /* Global contains global len/wid info  */
+  global = { NULL, NULL, NULL,   "", 0, 0, 80,  0, 40, 0 },
+  holder = { NULL, NULL, NULL, NULL, 0, 0,  0,  0,  0, NOCOMPONENT };
+
+/* Defines for putcomp subrutine mode arg                               */
+#define ONECOMP         0       /* Display only control comp name       */
+#define BOTHCOMP        1       /* Display both comp names (conditionally) */
+
+/*ARGSUSED*/
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       register struct comp *comp;
+       register char *cp, **ap;
+       FILE *fp;
+       char line[256], name[64];
+       int out();
+
+       invo_name = argv[0];
+       setbuf(stdout, _sobuf);
+       VOID signal(SIGQUIT, out);
+       ontty = gtty(1, (struct sgttyb *)name) != -1;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(getcpy(cp), " ", "\n");
+               VOID copyip(ap, profargs);
+/*              procargs(ap);*/
+               procargs(profargs);
+       }
+       procargs(argv + 1);
+       if(!folder)
+               folder = getenv("mhfolder");
+       if(fmtfile) {
+               if((fp = fopen(m_maildir(fmtfile), "r")) == NULL) {
+                       fprintf(stderr, "mhl: Can't open format file: %s\n",
+                               fmtfile);
+                       done(1);
+               }
+       } else if((fp = fopen(m_maildir(mhlformat), "r")) == NULL &&
+                 (fp = fopen(mhlstdfmt, "r")) == NULL) {
+                       fprintf(stderr, "mhl: Can't open default format file.\n");
+                       done(1);
+       }
+       while(fgets(line, sizeof line, fp)) {
+               if(line[0] == ';')              /* Comment line */
+                       continue;
+
+               line[strlen(line)-1] = 0;       /* Zap the <lf> */
+
+               if(line[0] == ':') {            /* Clear text line */
+                       comp = (struct comp *) calloc(1, sizeof (struct comp));
+                       comp->c_text = getcpy(line+1);
+                       comp->c_flags = CLEARTEXT;
+                       comp->c_ovoff = -1;
+                       comp->c_cwidth = -1;
+                       goto fmtqueue;
+               }
+
+               parptr = line;
+               strcpy(name, parse());
+/***  printf("%s %c %s\n", name, *parptr, parptr+1);    */
+               switch(*parptr) {
+
+               case '\0':
+               case ',':
+               case '=':
+                       if(uleq(name, "ignores")) {
+                               igp = copyip(brkstring(getcpy(++parptr), ",", NULLCP), igp);
+                               continue;
+                       }
+                       parptr = line;
+                       while(*parptr) {
+                               if(evalvar(&global)) {
+       fmterr:                         fprintf(stderr, "mhl: format file syntax error: %s\n",
+                                               line);
+                                       done(1);
+                               }
+                               if(*parptr)
+                                       parptr++;
+                       }
+                       continue;
+
+               case ':':
+                       comp = (struct comp *) calloc(1, sizeof (struct comp));
+                       comp->c_name = getcpy(name);
+                       comp->c_cwidth = -1;
+                       comp->c_ovoff = -1;
+                       while(*parptr == ':' || *parptr == ',') {
+                               parptr++;
+                               if(evalvar(comp))
+                                       goto fmterr;
+                       }
+       fmtqueue:       if(!fmthd)
+                               fmthd = fmttl = comp;
+                       else {
+                               fmttl->c_next = comp;
+                               fmttl = comp;
+                       }
+                       continue;
+
+               default:
+                       goto fmterr;
+
+               }
+       }
+       if(clearflg == 1)
+               global.c_flags |= CLEARSCR;
+       else if(clearflg == -1)
+               global.c_flags &= ~CLEARSCR;
+       if(awidth) global.c_width = awidth;
+       if(alength) global.c_length = alength;
+       if(global.c_width  < 5) global.c_width  = 10000;
+       if(global.c_length < 5) global.c_length = 10000;
+       VOID fclose(fp);
+       if(!ofilec)
+               process(NULLCP);
+       else {
+               for(ap = profargs; *ap; ap++)
+                       if(**ap)
+                               process(*ap);
+               for(ap = argv+1; *ap; ap++)
+                       if(**ap)
+                               process(*ap);
+       }
+       done(exitstat);
+}
+
+
+evalvar(sp)
+       register struct comp *sp;
+{
+       register char *cp;
+       int c;
+       char name[32];
+
+       if(!*parptr)
+               return 0;
+       strcpy(name, parse());
+/***printf("evalvar: %s %c %s\n", name, *parptr, parptr+1);     */
+       if(uleq(name, "width")) {
+               if(!*parptr++ == '=' || !*(cp = parse())) {
+missing:                fprintf(stderr, "mhl: missing arg to variable %s\n",
+                               name);
+                       return 1;
+               }
+               sp->c_width = atoi(cp);
+               return 0;
+       }
+       if(uleq(name, "compwidth")) {
+               if(!*parptr++ == '=' || !*(cp = parse())) goto missing;
+               sp->c_cwidth = atoi(cp);
+               return 0;
+       }
+       if(uleq(name, "length")) {
+               if(!*parptr++ == '=' || !*(cp = parse())) goto missing;
+               sp->c_length = atoi(cp);
+               return 0;
+       }
+       if(uleq(name, "overflowtext")) {
+               if(!*parptr++ == '=') goto missing;
+               cp = parptr;
+               while(*parptr && *parptr != ':' && *parptr != ',') parptr++;
+               c = *parptr;
+               *parptr = 0;
+               sp->c_ovtxt = getcpy(cp);
+               *parptr = c;
+               return 0;
+       }
+       if(uleq(name, "offset")) {
+               if(!*parptr++ == '=' || !*(cp = parse())) goto missing;
+               sp->c_offset = atoi(cp);
+               return 0;
+       }
+       if(uleq(name, "overflowoffset")) {
+               if(!*parptr++ == '=' || !*(cp = parse())) goto missing;
+               sp->c_ovoff = atoi(cp);
+               return 0;
+       }
+       if(uleq(name, "nocomponent")) {
+               sp->c_flags |= NOCOMPONENT;
+               return 0;
+       }
+       if(uleq(name, "uppercase")) {
+               sp->c_flags |= UPPERCASE;
+               return 0;
+       }
+       if(uleq(name, "center")) {
+               sp->c_flags |= CENTER;
+               return 0;
+       }
+       if(uleq(name, "clearscreen")) {
+               sp->c_flags |= CLEARSCR;
+               return 0;
+       }
+       if(uleq(name, "leftadjust")) {
+               sp->c_flags |= LEFTADJUST;
+               return 0;
+       }
+       if(uleq(name, "compress")) {
+               sp->c_flags |= COMPRESS;
+               return 0;
+       }
+       return 1;
+}
+
+
+char *
+parse()
+{
+       static char result[64];
+       register char *cp;
+       register int c;
+
+       cp = result;
+       while(c = *parptr)
+               if(isalnum(c) || c == '.' || c == '-' || c == '_') {
+                       *cp++ = c;
+                       parptr++;
+               } else
+                       break;
+       *cp = 0;
+       return result;
+}
+
+struct swit switches[] = {
+       "clear",                0,      /* 0 */
+       "noclear",              0,      /* 1 */
+       "folder folder",        0,      /* 2 */
+       "form formfile",        0,      /* 3 */
+       "length of page",       0,      /* 4 */
+       "width of line",        0,      /* 5 */
+       "help",                 4,      /* 6 */
+       0,                      0
+};
+
+procargs(ap)
+       register char **ap;
+{
+       register char *cp;
+
+       while(cp = *ap++)
+               if(*cp == '-') switch(smatch(++cp, switches)) {
+               case -2:ambigsw(cp, switches);  /* ambiguous */
+                       done(1);
+                                               /* unknown */
+               case -1:fprintf(stderr, "mhl: -%s unknown\n", cp);
+                       done(1);
+                                               /* -form format */
+               case 0: clearflg = 1;           /* -clear       */
+                       ap[-1] = "";
+                       break;
+
+               case 1: clearflg = -1;          /* -noclear     */
+                       ap[-1] = "";
+                       break;
+
+               case 2: if(!(folder = *ap++) || *folder == '-') {
+       missing: fprintf(stderr, "mhl: Missing arg for %s\n", ap[-2]);
+                               done(1);
+                       }
+                       ap[-2] = ""; ap[-1] = "";
+                       break;
+
+               case 3: if(!(fmtfile = *ap++) || *fmtfile == '-')
+                               goto missing;
+                       ap[-2] = ""; ap[-1] = "";
+                       break;
+                                               /* length */
+               case 4: if(!(cp = *ap++) || *cp == '-')
+                               goto missing;
+                       alength = atoi(cp);
+                       ap[-2] = ""; ap[-1] = "";
+                       break;
+                                               /* width */
+               case 5: if(!(cp = *ap++) || *cp == '-')
+                               goto missing;
+                       awidth = atoi(cp);
+                       ap[-2] = ""; ap[-1] = "";
+                       break;
+                                               /* -help        */
+               case 6: help("mhl [switches] [files]", switches);
+                       done(0);
+
+               } else
+                       ofilec++;
+}
+
+FILE *fp;
+
+process(fname)
+       char *fname;
+{
+       register int state;
+       register struct comp *comp, *c2, *c3;
+       char *cp, **ip, name[NAMESZ], buf[BUFSIZ];
+
+       if(setjmp(env)) {
+               discard(stdout);
+               putchar('\n');
+               goto out;
+       }
+       VOID signal(SIGINT, sigcatch);
+       if(fname) {
+               if((fp = fopen(fname, "r")) == NULL) {
+                       fprintf(stderr, "mhl: Can't open ");
+                       perror(fname);
+                       exitstat++;
+                       VOID signal(SIGINT, SIG_IGN);
+                       return;
+               }
+       } else
+               fp = stdin;
+       if(ontty) {
+               strcpy(buf, "\n");
+               if(ofilec > 1) {
+                       if(ofilen)
+                               printf("\n\n\n");
+                       printf("Press <return> to list \"");
+                       if(folder) printf("%s:", folder);
+                       printf("%s\"...", fname);
+                       VOID fflush(stdout);
+                       strcpy(buf, "");
+                       VOID read(1, buf, sizeof buf);
+               }
+               if(index(buf, '\n')) {
+                       if(global.c_flags & CLEARSCR)
+                               printf("\014\200");
+               } else
+                       printf("\n");
+       } else if(ofilec > 1) {
+                       if(ofilen)
+                               printf("\n\n\n");
+                       printf(">>> ");
+                       if(folder) printf("%s: ", folder);
+                       printf("%s\n\n", fname);
+       }
+
+       ofilen++;
+       row = column = 0;
+       msghd = 0;
+       for(state = FLD ; ;) {
+               state = m_getfld(state, name, buf, sizeof buf, fp);
+               switch(state) {
+
+               case FLD:
+               case FLDEOF:
+               case FLDPLUS:
+                       for(ip = ignores; *ip; ip++)
+                           if(uleq(name, *ip)) {
+                               while(state == FLDPLUS)
+                                   state = m_getfld(state, name, buf, sizeof buf, fp);
+                               goto next;
+                           }
+                       for(c3 = msghd; c3; c3 = c3->c_next)
+                           if(uleq(name, c3->c_name))
+                               break;
+                       if(c3) {
+                           comp = c3;
+                           comp->c_text = add(buf, comp->c_text);
+                       } else {
+                           comp = (struct comp *) calloc(1, sizeof (struct comp));
+                           comp->c_name = getcpy(name);
+                           comp->c_text = getcpy(buf);
+                           comp->c_cwidth = -1;
+                           comp->c_ovoff = -1;
+                       }
+                       while(state == FLDPLUS) {
+                           state = m_getfld(state, name, buf, sizeof buf, fp);
+                           comp->c_text = add(buf, comp->c_text);
+                       }
+                       for(c2 = fmthd; c2; c2 = c2->c_next)
+                               if(uleq(c2->c_name, comp->c_name))
+                                       goto goodun;
+                       comp->c_flags |= EXTRA;
+          goodun:      if(!c3) {
+                           if(!msghd)
+                                   msghd = msgtl = comp;
+                           else {
+                                   msgtl->c_next = comp;
+                                   msgtl = comp;
+                           }
+                       }
+                       if(state == FLDEOF)
+                           goto doit;
+                       continue;
+
+               default:
+               case LENERR:
+               case FMTERR:
+                       fprintf(stderr, "Message format error!\n");
+                       exitstat++;
+                       return;
+
+               case BODY:
+               case BODYEOF:
+               case FILEEOF:
+       doit:
+                       for(comp = fmthd; comp; comp = comp->c_next) {
+                           if(comp->c_flags & CLEARTEXT) {
+                               putcomp(comp, comp, ONECOMP);
+                               continue;
+                           }
+                           if(uleq(comp->c_name, "messagename")) {
+                               cp = concat(fname, "\n", NULLCP);
+                               if(folder) {
+                                   holder.c_text = concat(folder, ":", cp, NULLCP);
+                                   free(cp);
+                               } else
+                                   holder.c_text = cp;
+                               putcomp(comp, &holder, ONECOMP);
+                               free(holder.c_text);
+                               holder.c_text = 0;
+                           }
+                           if(uleq(comp->c_name, "extras")) {
+                               for(c2 = msghd; c2; c2 = c2->c_next)
+                                   if(c2->c_flags & EXTRA)
+                                       putcomp(comp, c2, BOTHCOMP);
+                               continue;
+                           }
+                           if(uleq(comp->c_name, "body")) {
+                               holder.c_text = buf;
+                               putcomp(comp, &holder, ONECOMP);
+                               holder.c_text = 0;
+                               while(state == BODY) {
+                                   state = m_getfld(state, name, buf, sizeof buf, fp);
+                                   holder.c_text = buf;
+                                   putcomp(comp, &holder, ONECOMP);
+                                   holder.c_text = 0;
+                               }
+                               continue;
+                           }
+                           for(c2 = msghd; c2; c2 = c2->c_next)
+                               if(uleq(c2->c_name, comp->c_name)) {
+                                   putcomp(comp, c2, ONECOMP);
+                                   break;
+                               }
+                       }
+               out:
+                       if(fp)
+                               VOID fclose(fp);
+                       fp = NULL;
+                       if(holder.c_text) cndfree(holder.c_text);
+                       holder.c_text = 0;
+                       for(c2 = msghd; c2; c2 = comp) {
+                               comp = c2->c_next;
+                               cndfree(c2->c_name);
+                               cndfree(c2->c_text);
+                               free( (char *)c2);
+                       }
+                       msghd = msgtl = NULL;
+                       for(c2 = fmthd; c2; c2 = c2->c_next)
+                               c2->c_flags &= ~HDROUTPUT;
+                       VOID signal(SIGINT, SIG_IGN);
+                       return;
+               }
+next:   ;
+       }
+}
+
+int     lm;             /* Left Margin for putstr               */
+int     llim;           /* line limit for this component        */
+int     wid;            /* width limit for this comp            */
+int     ovoff;          /* overflow offset for this comp        */
+char    *ovtxt;         /* overflow text for this comp          */
+int     term;           /* term from last oneline()             */
+char    *onelp;         /* oneline() text pointer               */
+
+putcomp(cc, c2, flag)
+       register struct comp *cc, *c2;
+       int flag;
+{
+       register char *cp;
+       int count, cchdr = 0;
+
+#ifdef DEBUGCOMP
+           printf("%s(%o):%s:%s", cc->c_name, cc->c_flags, c2->c_name,
+               c2->c_text);
+#endif
+       onelp = NULL;
+       lm = 0;
+       llim = cc->c_length? cc->c_length : -1;
+       wid   = cc->c_width? cc->c_width : global.c_width;
+       ovoff = cc->c_ovoff >= 0 ? cc->c_ovoff : global.c_ovoff;
+       ovoff += cc->c_offset;
+       ovtxt = cc->c_ovtxt ? cc->c_ovtxt : global.c_ovtxt;
+       if(!ovtxt) ovtxt = "";
+       if(wid < ovoff + strlen(ovtxt) + 5) {
+               fprintf(stderr, "mhl: component: %s width too small for overflow.\n",
+                       cc->c_name);
+               done(1);
+       }
+       if(cc->c_flags & CLEARTEXT) {
+               putstr(cc->c_text);
+               putstr("\n");
+               return;
+       }
+       if(cc->c_flags & CENTER) {
+               count = global.c_width;
+               if(cc->c_width) count = cc->c_width;
+               count -= cc->c_offset;
+               count -= strlen(c2->c_text);
+               if(!(cc->c_flags&HDROUTPUT) && !(cc->c_flags&NOCOMPONENT))
+                       count -= strlen(cc->c_name) + 2;
+               lm = cc->c_offset+(count/2);
+       } else if(cc->c_offset)
+               lm = cc->c_offset;
+       if(!(cc->c_flags & HDROUTPUT) && !(cc->c_flags & NOCOMPONENT)) {
+               putstr(cc->c_name); putstr(": ");
+               cc->c_flags |= HDROUTPUT;
+               cchdr++;
+               if((count = cc->c_cwidth - strlen(cc->c_name) - 2) > 0)
+                       while(count--) putstr(" ");
+       }
+       if(flag == BOTHCOMP && !(c2->c_flags & HDROUTPUT) &&
+                              !(c2->c_flags & NOCOMPONENT)) {
+               putstr(c2->c_name); putstr(": ");
+               c2->c_flags |= HDROUTPUT;
+       }
+       if(cc->c_flags & UPPERCASE)
+               for(cp = c2->c_text; *cp; cp++)
+                       if(islower(*cp))
+                               *cp -= 'a' - 'A';
+       count = 0;
+       if(cchdr)
+               count = (cc->c_cwidth>=0) ? cc->c_cwidth : strlen(cc->c_name)+2;
+       count += cc->c_offset;
+       putstr(oneline(c2->c_text, cc->c_flags));
+/***   if(cc->c_flags & COMPRESS) printf("-1-");        /***/
+       if(term == '\n')
+               putstr("\n");
+       while(cp = oneline(c2->c_text, cc->c_flags)) {
+/***   if(cc->c_flags & COMPRESS) printf("-2-");        /***/
+               if(*cp) {
+                       lm = count;
+                       putstr(cp);
+                       if(term == '\n')
+                               putstr("\n");
+               } else
+                       if(term == '\n')
+                               putstr("\n");
+       }
+       c2->c_flags |= PROCESSED;
+}
+
+putstr(string)
+       register char *string;
+{
+       if(!column && lm > 0)
+               while(lm > 0)
+                       if(lm >= 8) {
+                               putch('\t');
+                               lm -= 8;
+                       } else {
+                               putch(' ');
+                               lm--;
+                       }
+       lm = 0;
+       while(*string)
+               putch(*string++);
+}
+
+putch(ch)
+{
+       char buf[32];
+
+       if(llim == 0)
+               return;
+       switch(ch) {
+       case '\n':
+               if(llim > 0) llim--;
+               column = 0;
+               row++;
+               if(ontty && row == global.c_length) {
+                       putchar('\007');
+                       VOID fflush(stdout);
+                       buf[0] = 0;
+                       VOID read(1, buf, sizeof buf);
+                       if(index(buf, '\n')) {
+                               if(global.c_flags & CLEARSCR) {
+                                       putchar('\014');
+                                       putchar('\200');
+                               }
+                               row = 0;
+                       } else {
+                               putchar('\n');
+                               row = global.c_length / 3;
+                       }
+                       return;
+               }
+               break;
+       case '\t':
+               column |= 07;
+               column++;
+               break;
+
+       case '\010':
+               column--;
+               break;
+
+       case '\r':
+               column = 0;
+               break;
+
+       default:
+               if(ch >= ' ')
+                       column++;
+       }
+       if(column >= wid) {
+               putch('\n');
+               if(ovoff > 0)
+                       lm = ovoff;
+               if(ovtxt)
+                       putstr(ovtxt);
+               else
+                       putstr("");
+               putch(ch);
+               return;
+       }
+       putchar(ch);
+}
+
+
+char *
+oneline(stuff, flgs)
+       char *stuff;
+{
+       register char *ret;
+       register char *cp;
+       int spc;
+
+       if(!onelp)
+               onelp = stuff;
+       if(!*onelp) {
+               onelp = 0;
+               return NULL;
+       }
+       ret = onelp;
+       term = 0;
+       if(flgs & COMPRESS) {
+               cp = ret;
+               spc = 0;
+               while(*onelp) {
+                       if(*onelp == '\n' || *onelp == '\t' || *onelp == ' '){
+                               if(*onelp == '\n' && !onelp[1]) {
+                                       term = '\n';
+                                       break;
+                               } else if(!spc) {
+                                       *cp++ = ' ';
+                                       spc++;
+                               }
+                       } else {
+                               *cp++ = *onelp;
+                               spc = 0;
+                       }
+                       onelp++;
+               }
+               *onelp = 0;
+               *cp = 0;
+       } else {
+               while(*onelp && *onelp != '\n') onelp++;
+               if(*onelp == '\n') {
+                       term = '\n';
+                       *onelp++ = 0;
+               }
+               if(flgs&LEFTADJUST)
+                       while(*ret == ' ' || *ret == '\t') ret++;
+       }
+       return ret;
+}
+
+
+sigcatch()
+{
+       longjmp(env, 1);
+}
+
+
+out()
+{
+       putchar('\n');
+       VOID fflush(stdout);
+       exit(-1);
+}
+
+discard(io)
+register FILE *io;
+{
+       struct sgttyb sg;
+
+       if (ioctl(fileno (io), TIOCGETP, &sg) >= 0)
+               ioctl(fileno (io), TIOCSETP, &sg);
+       io->_cnt = BUFSIZ;
+       io->_ptr
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/progs/mhpath.c b/docs/historical/mh-jun-1982/progs/mhpath.c
new file mode 100644 (file)
index 0000000..64829ab
--- /dev/null
@@ -0,0 +1,323 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+#include <stdio.h>
+#include <strings.h>
+
+
+struct msgs *mp;
+extern  char _sobuf[];
+
+struct swit switches[] = {
+       "all",         -3,      /* 0 */
+       "help",         4,      /* 1 */
+       0,              0
+};
+
+/*ARGSUSED*/
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       char *cp;
+       char *mhnam();
+
+       if(!(cp = mhnam(&argv[1])))
+               done(1);
+       printf("%s\n", cp);     /* Expanded message list */
+       done(0);
+}
+
+char *
+mhnam(args)
+       char **args;
+{
+       int j;
+       static char *string;
+       char buf[100];
+       char *folder, *maildir, *msgs[100];
+       register int msgnum;
+       register char *cp;
+       int msgp;
+       char *arguments[50], **argp;
+
+       setbuf(stdout, _sobuf);
+
+       folder = (char *) 0;
+       msgp = 0;
+       VOID copyip(args, arguments);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               return(0);
+                                                       /* unknown */
+                       case -1:fprintf(stderr, "mhnam: -%s unknown\n", cp);
+                               return(0);
+                                                        /* -all */
+                       case 0: fprintf(stderr, "\"-all\" changed to \"all\"\n");
+                               return(0);
+                       case 1: help("mhnam [+folder]  [msgs] [switches]", switches);
+                               return(0);
+                       }
+               if(*cp == '+') {
+                       if(folder) {
+                               fprintf(stderr, "Only one folder at a time.\n");
+                               return(0);
+                       } else
+                               folder = path(cp+1, TFOLDER);
+               } else
+                       msgs[msgp++] = cp;
+       }
+       if(!m_find("path")) free(path("./", TFOLDER));
+
+       /* Mhpath defaults to the folder name     */
+       /***    if(!msgp)
+        ***            msgs[msgp++] = "cur";
+        ***/
+
+       if(!folder)
+               folder = m_getfolder();
+       maildir = m_maildir(folder);
+
+
+       if(!msgp)
+               return(maildir);
+
+
+       if(chdir(maildir) < 0) {
+               fprintf(stderr, "Can't chdir to: ");
+               perror(maildir);
+               return(0);
+       }
+
+       if(!(mp = m_gmsg(folder))) {
+               fprintf(stderr, "Can't read folder!?\n");
+               return(0);
+       }
+       /* Need to accomodate MAXFOLDER messages instead of mp->hghmsg */
+       if( (char *) (mp = (struct msgs *)
+            realloc((char *) mp, (unsigned)(sizeof *mp + MAXFOLDER + 1 + 2)))
+          == (char *) 0)
+               return(0);
+
+       /* Clear the newly allocated space */
+       for(j = mp->hghmsg + 1; j <= MAXFOLDER; j++)
+               mp->msgstats[j] = 0;
+
+       /* Mhpath permits empty folders */
+       /***    if(mp->hghmsg == 0) {
+        ***            fprintf(stderr, "No messages in \"%s\".\n", folder);
+        ***            return(0);
+        ***    }
+        ***/
+
+       if(msgp)
+               for(msgnum = 0; msgnum < msgp; msgnum++)
+                       if(!convert(msgs[msgnum]))
+                               return(0);
+       if(mp->numsel == 0) {
+               fprintf(stderr, "mhnam: Never get here. \n");
+               return(0);
+       }
+       if(mp->numsel > MAXARGS-2) {
+               fprintf(stderr, "mhnam: more than %d messages \n", MAXARGS-2);
+               return(0);
+       }
+
+       for(msgnum= mp->lowsel; msgnum<= mp->hghsel; msgnum++)
+               if(mp->msgstats[msgnum]&SELECTED)
+               {
+                       VOID sprintf(buf,"%s%c%s", maildir,'/', m_name(msgnum));
+
+                       if(string)
+                               string = add("\n", string);
+                       string = add(buf, string);
+               /***    printf("buf %s  string %s\n",buf,string); ***/
+               }
+       return(string);
+}
+
+
+#include <ctype.h>
+
+int  convdir;
+char *delimp;
+
+#define FIRST 1                                         /***/
+#define LAST  2                                         /***/
+
+convert(name)       /*** Slightly hacked version of ../subs/m_convert.c */
+char *name;
+{
+       register char *cp;
+       register int first, last;
+       int found, range, err;
+       char *bp;
+
+       found = 0;
+
+
+       if(strcmp((cp = name), "new") == 0)             /***/
+       {
+               if((err = first = getnew(cp)) <= 0)
+                       goto badbad;
+               goto single;
+       }
+       if(strcmp((cp = name), "all") == 0)
+               cp = "first-last";
+       if((err = first = conv(cp, FIRST)) <= 0)   /***/
+               goto badbad;
+       if(*(cp = delimp) && *cp != '-' && *cp != ':')  {
+       baddel: fprintf(stderr, "Illegal argument delimiter: \"%c\"\n", *delimp);
+               return(0);
+       }
+       if(*cp == '-') {
+               cp++;
+               if((err = last = conv(cp, LAST)) <= 0) {    /***/
+         badbad:       if(err == -1)
+                               fprintf(stderr, "No %s message\n", cp);
+                       else if (err == -2)                     /***/
+                               fprintf(stderr,
+                                "Message %s out of range 1-%d\n",
+                                 cp,MAXFOLDER);
+                       else
+         badlist:              fprintf(stderr, "Bad message list \"%s\".\n",
+                                       name);
+                       return(0);
+               }
+               if(last < first) goto badlist;
+               if(*delimp) goto baddel;
+               if(first > mp->hghmsg || last < mp->lowmsg) {
+       rangerr:        fprintf(stderr,"No messages in range \"%s\".\n",name);
+                       return(0);
+               }
+               if(last > mp->hghmsg)
+                       last = mp->hghmsg;
+               if(first < mp->lowmsg)
+                       first = mp->lowmsg;
+       } else if(*cp == ':') {
+               cp++;
+               if(*cp == '-') {
+                       convdir = -1;
+                       cp++;
+               } else if(*cp == '+') {
+                       convdir = 1;
+                       cp++;
+               }
+               if((range = atoi(bp = cp)) == 0)
+                       goto badlist;
+               while(isdigit(*bp)) bp++;
+               if(*bp)
+                       goto baddel;
+               if((convdir > 0 && first > mp->hghmsg) ||
+                  (convdir < 0 && first < mp->lowmsg))
+                       goto rangerr;
+               if(first < mp->lowmsg)
+                       first = mp->lowmsg;
+               if(first > mp->hghmsg)
+                       first = mp->hghmsg;
+               for(last = first; last >= mp->lowmsg && last <= mp->hghmsg;
+                                               last += convdir)
+                       if(mp->msgstats[last]&EXISTS)
+                               if(--range <= 0)
+                                       break;
+               if(last < mp->lowmsg)
+                       last = mp->lowmsg;
+               if(last > mp->hghmsg)
+                       last = mp->hghmsg;
+               if(last < first) {
+                       range = last; last = first; first = range;
+               }
+       } else  {
+             /*** Here's the hack: cur message, single numeric message,
+              *** or new message are permitted to be non-existent
+              ***/
+single:         last = first;
+               mp->msgstats[first] |= SELECT_EMPTY;
+       }
+       while(first <= last) {
+               if(mp->msgstats[first]&(EXISTS|SELECT_EMPTY)) { /***/
+                       if(!(mp->msgstats[first]&SELECTED)) {
+                               mp->numsel++;
+                               mp->msgstats[first] |= SELECTED;
+                               if(first < mp->lowsel)
+                                       mp->lowsel = first;
+                               if(first > mp->hghsel)
+                                       mp->hghsel = first;
+                       }
+                       found++;
+               }
+               first++;
+       }
+       if(!found)
+               goto rangerr;
+       return(1);
+}
+
+conv(str, callno)   /*** Slightly hacked version of ../subs/m_conv.c */
+char *str;
+int callno;             /***/
+{
+       register char *cp, *bp;
+       register int i;
+       char buf[16];
+
+       convdir = 1;
+       cp = bp = str;
+       if(isdigit(*cp))  {
+               while(isdigit(*bp)) bp++;
+               delimp = bp;
+/***            return (i = atoi(cp)) > MAXFOLDER ? MAXFOLDER : i;   ***/
+               /* If msg # <= MAXFOLDER, return it;
+                * if > MAXFOLDER but part of a range, return MAXFOLDER;
+                * if single explicit msg #, return error.
+                */
+               return (i = atoi(cp)) <= MAXFOLDER ? i :
+                 *delimp || callno == LAST ? MAXFOLDER : -2;
+       }
+       bp = buf;
+       while((*cp >= 'a' && *cp <= 'z') || *cp == '.')
+               *bp++ = *cp++;
+       *bp++ = 0;
+       delimp = cp;
+       if(strcmp(buf, "first") == 0)
+               return(mp->hghmsg? mp->lowmsg : -1);    /* Folder empty? */
+/***            return(mp->lowmsg);     ***/
+       else if(strcmp(buf, "last") == 0) {
+               convdir = -1;
+               return(mp->hghmsg? mp->hghmsg : -1);
+/***            return(mp->hghmsg);     ***/
+       } else if(strcmp(buf, "cur") == 0 || strcmp(buf, ".") == 0)
+               return(mp->curmsg > 0 ? mp->curmsg : -1);
+       else if(strcmp(buf, "prev") == 0) {
+               convdir = -1;
+               for(i = (mp->curmsg<=mp->hghmsg)? mp->curmsg-1: mp->hghmsg;
+                   i >= mp->lowmsg; i--) {
+                       if(mp->msgstats[i]&EXISTS)
+                               return(i);
+               }
+               return(-1);                     /* non-existent message */
+       } else if(strcmp(buf, "next") == 0)  {
+               for(i = (mp->curmsg>=mp->lowmsg)? mp->curmsg+1: mp->lowmsg;
+                   i <= mp->hghmsg; i++) {
+                       if(mp->msgstats[i]&EXISTS)
+                               return(i);
+               }
+               return(-1);
+       } else
+               return(0);                     /* bad message list */
+}
+
+getnew(str)
+char *str;
+{
+       register char *cp;
+
+       return(mp->hghmsg<MAXFOLDER? mp->hghmsg+ 1 : 
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/progs/news.c b/docs/historical/mh-jun-1982/progs/news.c
new file mode 100644 (file)
index 0000000..2a96f99
--- /dev/null
@@ -0,0 +1,404 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/dir.h>
+#include <strings.h>
+
+extern char *sprintf();
+
+#define max(a,b) (a > b ? a : b)
+#define YES 1
+#define NO  0
+
+#define NEWSP   "/usr/news"     /* MUST be same as login News's login dir */
+#define MAXTOPICS       50      /* Enough for a while */
+
+int     vecp, topicp;
+int     topicspec;      /* topic argument(s) given */
+char    *topics[MAXTOPICS+1];
+char    *vec[MAXARGS];
+int     fdisplay, fcheck, fupdate, fsend, freview, fbody;  /* flags */
+int     frevback, fverbose, fhelp, ftopics; /* flags */
+int     hit;
+
+struct nts {
+       char    t_name[16];
+       int     t_num;
+} nts[MAXTOPICS+1], *check();
+struct nts *ntps[MAXTOPICS];
+int nnts;       /* number of actual topics */
+
+struct swit switches[] = {
+       "add",          -1,     /* 0 */
+       "body",         -1,     /* 1 */
+       "check",        0,      /* 2 */
+       "display",      0,      /* 3 */
+       "review [#]",   0,      /* 4 */
+       "send topic ...",0,     /* 5 */
+       "topics",       0,      /* 6 */
+       "update",       0,      /* 7 */
+       "help",         4,      /* 8 */
+       0,              0,
+};
+
+extern  char _sobuf[];          /* MLW  standard out buffer */
+
+/*ARGSUSED*/
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       register int i;
+       register char *cp, **ap;
+       char *arguments[50], **argp;
+
+       invo_name = argv[0];
+       setbuf(stdout, _sobuf);
+#ifdef NEWS
+       m_news();
+#endif
+       if (chdir (NEWSP) < 0) {        /* <-- N.B. */
+               fprintf(stderr, "Can't change directory to ");
+               perror(NEWSP);
+               done(1);
+       }
+       vecp = 2;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       VOID copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               done(0);
+                                                            /* unknown */
+                       case -1:vec[vecp++] = --cp; continue;
+                       case 0:
+                       case 5: fsend = YES; continue;
+                       case 1: fbody = YES;
+                               vec[vecp++] = --cp; continue;
+                       case 2: fcheck = YES; continue;
+                       case 3: fdisplay = YES; continue;
+                       case 4: freview = YES;
+                               if(**argp >= '0' && **argp <= '9')
+                                       frevback = atoi(*argp++);
+                               continue;
+                       case 7: fupdate = YES; continue;
+
+                       case 8:
+                               fhelp = YES;
+                       case 6:
+                               ftopics = YES;
+                               continue;
+                       }
+               else
+                       if(vecp == 2) {
+                               VOID addtopic (cp, YES);
+                               topicspec = YES;
+                       }
+                       else
+                               vec[vecp++] = cp;
+       }
+       if (!topicspec)
+               /* user didn't specify topics so give him his defaults */
+               gettopics();
+       getnts();
+       if (fhelp) {
+               help(
+"news [topic ...] [switches] [switches for \"c\" or \"mail\" ]", switches);
+               putchar('\n');
+       }
+       if (ftopics) {
+               showtopics();
+               done(0);
+       }
+       if(fsend) {
+               if(!topicspec) {
+                       fprintf(stderr, "Usage: news -send topic [mail switches]\n");
+                       done(1);
+               }
+               for(i = 0; i < topicp; i++)
+                       if(check(topics[i]))
+                               send(topics[i]);
+                       else
+                               printf("Unknown topic: %s\n", topics[i]);
+               done(0);
+       }
+       for(i = 0; i < topicp; i++)
+               if(check(topics[i]) == NULL)
+                       printf("Topic: %s unknown.\n", topics[i]);
+               else
+                       disp(topics[i], fverbose || topicspec);
+       if(fcheck) {
+               if(hit)
+                       printf(".\n");
+       } else if(!hit && !topicspec && !fupdate && !fdisplay)
+               nonews();
+       m_update();
+       done(0);
+}
+
+
+struct nts *
+check(topic)
+       char *topic;
+{
+       register struct nts *t;
+
+       for(t = nts; t->t_name[0]; t++)
+               if(strncmp(topic, t->t_name, DIRSIZ) == 0)
+                       return t;
+       return 0;
+}
+
+
+disp(topic, argflg)
+       register char *topic;
+       int argflg;
+{
+       register struct nts *t;
+       register char *cp, *np;
+       register int msgnum;
+       int high;
+       char buf[128];
+
+       if((t = check(topic)) == 0)
+               fprintf(stderr, "HUH?\n");
+       if((cp = m_find(np = concat("news-", topic, NULLCP))) == NULL)
+               cp = "0";
+       high = atoi(cp);
+       if(fcheck) {
+               if(t->t_num > high) {
+                       if(!hit++)
+                               printf("Unread news in");
+                       if(hit > 1)
+                               printf(",");
+                       printf(" '%s'", topic);
+               }
+               return;
+       }
+       if(fupdate) {
+               if(t->t_num > high) {
+                       m_replace(np, getcpy(m_name(t->t_num)));
+                       printf("Skipping %d items in %s.\n",
+                               t->t_num - high, topic);
+               }
+               return;
+       }
+       if(freview)
+               if(frevback)
+                       msgnum = max(high - frevback, 0);
+               else
+                       msgnum = 0;
+       else
+               msgnum = high;
+/***    msgnum = freview? frevback? high - frevback : 0 : high; */
+       if(msgnum >= t->t_num) {
+               if(argflg)
+                       printf("%s: no new news.\n", topic);
+               return;
+       }
+       VOID sprintf(buf, "%s/%s", NEWSP, topic);
+       if(chdir(buf) == -1) {
+               perror(buf);
+               return;
+       }
+       vec[1] = showproc;
+       for( ; msgnum < t->t_num;) {
+               cp = m_name(++msgnum);
+               if(hit) {
+                       printf("\nPress <return> for %s:%s...", topic, cp);
+                       VOID fflush(stdout);
+                       VOID read(0, buf, sizeof buf);
+               } else
+                       printf("News item %s:%s\n", topic, cp);
+               if(msgnum > high) {
+                       m_replace(np, getcpy(cp));
+                       m_update();
+               }
+               putenv("mhfolder", topic);
+               vec[vecp] = cp;
+               putchar('\n');
+               call(vec + 1);
+               hit = 1;
+       }
+}
+
+
+call(vector)
+       char **vector;
+{
+       register int pid, child;
+       int status;
+
+       VOID fflush(stdout);
+       while((child = fork()) == -1) {
+               printf("No forks...\n"); VOID fflush(stdout);
+               sleep(2);
+       }
+       if(child == 0) {
+               execv(vector[0], vector);
+               perror(vector[0]);
+               done(1);
+       }
+       while((pid = wait(&status)) != -1 && pid != child) ;
+       if(pid == -1 || status) {
+               fprintf(stderr, "Abnormal termination from %s\n", vector[0]);
+               done(1);
+       }
+}
+
+
+send(topic)
+       register char *topic;
+{
+       vec[0] = mailproc;
+       vec[1] = concat("news.", topic, NULLCP);
+       if(!fbody)
+               printf("Enter text for %s\n", topic);
+       call(vec);
+       free(vec[1]);
+}
+
+
+#ifdef CUTE
+char    *nons[] = {
+       "No new news",
+       "No news to peruse",
+       "Only old news",
+       "News shortage",
+       "News reporters on strike",
+       "Report your own news",
+       "News presses broken"
+};
+#define NONS    (sizeof nons/ sizeof nons[0])
+#endif
+
+nonews()
+{
+#ifdef CUTE
+#include <sys/timeb.h>
+       struct timeb tb;
+
+       ftime(&tb);
+       printf("%s.\n", nons[tb.millitm % NONS]);
+#else
+       printf("No new news.\n");
+#endif
+}
+
+showtopics()
+{
+       register int i;
+
+       sortnts();
+       printf("Chk Items Topics\n");
+       printf("--- ----- ------\n");
+       for(i = 0; i < nnts; i++)
+               printf(" %s  %4d  %s\n",
+                      addtopic (ntps[i]->t_name, NO) ? "*" : " ",
+                      ntps[i]->t_num, ntps[i]->t_name);
+       return;
+}
+
+gettopics ()
+{
+       register char **ap;
+       register char *cp;
+
+       VOID addtopic ("everyone", YES);
+       if((cp = m_find("news-topics")) != NULL) {
+               for (ap = brkstring (cp = getcpy(cp), " ", "\n")
+                   ; *ap; ap++)
+                       VOID addtopic (*ap, YES);
+       }
+       return;
+}
+
+addtopic (cp, real)
+char *cp;
+int real;
+{
+       register char **cpp;
+
+       for (cpp = topics; *cpp; cpp++)
+               if (!strcmp (*cpp, cp))
+                       return YES; /* We have it already */
+       if (real) {
+               if (!strcmp ("*", cp)) {
+                       register int i;
+                       getnts ();
+                       for(i = 0; i < nnts; i++)
+                               VOID addtopic (nts[i].t_name, YES);
+               }
+               else if (topicp < MAXTOPICS - 1)
+                       topics[topicp++] = cp;
+       }
+       return NO;     /* We don't have it already */
+}
+
+getnts()
+{
+       /* shouldn't ALWAYS look up all news folders.
+        * Should only do that for a -topics or -help.
+        */
+       struct direct dir;
+       struct stat st;
+       register struct nts *t;
+       register FILE *d;
+       char tbuf[DIRSIZ + 2];
+
+       if (nnts > 0)
+               /* we've done it already */
+               return;
+       t = nts;
+       if((d = fopen(".", "r")) == NULL) {
+               fprintf(stderr, "Can't open ");
+               perror(NEWSP);
+               done(1);
+       }
+       tbuf[0] = '.';
+       while(fread((char *)&dir, sizeof dir, 1, d)) {
+               if(dir.d_ino && dir.d_name[0] != '.') {
+                       strncpy(t->t_name, dir.d_name, DIRSIZ);
+                       strcpy(&tbuf[1], t->t_name);
+                       if(stat(tbuf, &st) != -1)
+                               t->t_num = st.st_size;
+                       nnts++;
+                       t++;
+               }
+       }
+       VOID fclose(d);
+       return;
+}
+
+sortnts()
+{
+       register int i;
+       extern int ntcmp();
+
+       for (i = 0; i < nnts; i++)
+               ntps[i] = &nts[i];
+       qsort ((char *) ntps, nnts, sizeof ntps[0], ntcmp);
+       return;
+}
+
+ntcmp (n1, n2)
+struct nts **n1;
+struct nts **n2;
+{
+       return strcmp ((*n1)->t_name, (*n2)->t_name);
+}
diff --git a/docs/historical/mh-jun-1982/progs/next.c b/docs/historical/mh-jun-1982/progs/next.c
new file mode 100644 (file)
index 0000000..2469fda
--- /dev/null
@@ -0,0 +1,114 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+#include <stdio.h>
+#include <strings.h>
+
+int     glbtype;
+int     header = 1;
+struct msgs *mp;
+
+struct swit switches[] = {
+       "header",       0,      /* 0 */
+       "noheader",     0,      /* 1 */
+       "help",         4,      /* 2 */
+       0,              0
+};
+
+
+/*ARGSUSED*/
+main(argc, argv)
+char *argv[];
+{
+       char *maildir, *vec[20], *folder;
+       register char *cp;
+       int next;
+       int vecp;
+       char **ap;
+       char *arguments[50], **argp;
+       extern char _sobuf[];
+
+       invo_name = argv[0];
+       setbuf(stdout, _sobuf);
+#ifdef NEWS
+       m_news();
+#endif
+       next = glbtype;
+       folder = 0; vecp = 2;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       VOID copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                            /* unknown */
+                       case -1:vec[vecp++] = --cp;  continue;
+                       case 0: header = 1; continue;        /* -header */
+                       case 1: header = 0; continue;        /* -noheader */
+                       case 2: if(next > 0)                 /* -help  */
+       help("next [+folder]   [switches] [switches for \"type\" ]", switches);
+                               else
+       help("prev [+folder]   [switches] [switches for \"type\" ]", switches);
+                               goto leave;
+                       }
+               if(*cp == '+') {
+                       if(folder) {
+                               fprintf(stderr, "Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               folder = path(cp+1, TFOLDER);
+               } else {
+                       fprintf(stderr, "Bad arg: %s\n", cp);
+                       fprintf(stderr, "Usage: %s [+folder] [-l.switches]\n",
+                            next>0? "next" : "prev");
+                       goto leave;
+               }
+       }
+       vec[vecp] = 0;
+       if(!m_find("path")) free(path("./", TFOLDER));
+       if(!folder)
+               folder = m_getfolder();
+       maildir = m_maildir(folder);
+       if(chdir(maildir) < 0) {
+               fprintf(stderr, "Can't chdir to: ");
+               perror(maildir);
+               goto leave;
+       }
+       if(!(mp = m_gmsg(folder))) {
+               fprintf(stderr, "Can't read folder!?\n");
+               goto leave;
+       }
+       if(mp->hghmsg == 0) {
+               fprintf(stderr, "No messages in \"%s\".\n", folder);
+               goto leave;
+       }
+       if(!m_convert(next > 0 ? "next" : "prev"))
+               goto leave;
+       m_replace(pfolder, folder);
+       if(mp->lowsel != mp->curmsg)
+               m_setcur(mp->lowsel);
+       vec[1] = m_name(mp->lowsel);
+       if(header)
+               printf("(Message %s:%s)\n", folder, vec[1]);
+       VOID fflush(stdout);
+       vec[0] = r1bindex(showproc, '/');
+       m_update();
+       putenv("mhfolder", folder);
+       execv(showproc, vec);
+       perror("Can't exec type");
+ leave:
+       m_update();
+       done(0);
+}
diff --git a/docs/historical/mh-jun-1982/progs/nexthdr.c b/docs/historical/mh-jun-1982/progs/nexthdr.c
new file mode 100644 (file)
index 0000000..863656b
--- /dev/null
@@ -0,0 +1,8 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+int     glbtype =  1;
diff --git a/docs/historical/mh-jun-1982/progs/pick.c b/docs/historical/mh-jun-1982/progs/pick.c
new file mode 100644 (file)
index 0000000..0cda291
--- /dev/null
@@ -0,0 +1,427 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+#include "../folder.h"
+#include <stdio.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+char *malloc();
+
+#define NFOLD 20                /* Allow 20 folder specs */
+
+extern struct swit anoyes[];    /* Std no/yes gans array */
+
+/*
+ * pick [-src folder] [msgs] search [-scan] [-show] [file-op]
+ *
+ *  search =  -from        \
+ *            -to           \
+ *            -cc            \
+ *            -subject        \  pattern
+ *            -sub            /
+ *            -date          /
+ *            -search       /
+ *            --component  /
+ *
+ * file-op =  -file [-preserve] [-link] +folder ...
+ *            -keep [-stay] [+folder ...]
+ */
+
+int nvecp, foldp;
+char **nvec;
+struct msgs *mp;
+char grep[256], *grepp, *folder, maildir[128];
+int showf, scanfl, filef, keepf, linkf, noteold, prsrvf, stayf;
+int grep_lowsel  = 5000,
+    grep_hghsel  = 0;
+char *delprog;
+
+struct st_fold folders[NFOLD];
+
+struct swit switches[] = {
+       "cc  pattern",                  0,      /*  0 */
+       "date  pattern",                0,      /*  1 */
+       "from  pattern",                0,      /*  2 */
+       "search  pattern",              0,      /*  3 */
+       "subject  pattern",             0,      /*  4 */
+       "to  pattern",                  0,      /*  5 */
+       "-othercomponent  pattern",    15,      /*  6 */
+       "all",                         -3,      /*  7 */
+       "file  +folder ...",            0,      /*  8 */
+       "nofile",                       0,      /*  9 */
+       "keep [+folder ...]",           0,      /* 10 */
+       "nokeep",                       0,      /* 11 */
+       "link",                         0,      /* 12 */
+       "nolink",                       0,      /* 13 */
+       "preserve",                     0,      /* 14 */
+       "nopreserve",                   0,      /* 15 */
+       "scan",                         0,      /* 16 */
+       "noscan",                       0,      /* 17 */
+       "show",                         0,      /* 18 */
+       "noshow",                       0,      /* 19 */
+       "src  +folder",                 0,      /* 20 */
+       "stay",                         0,      /* 21 */
+       "nostay",                       0,      /* 22 */
+       "help",                         4,      /* 23 */
+       0,                              0
+};
+
+/*ARGSUSED*/
+main(argc, argv)
+char *argv[];
+{
+       char *msgs[128], buf[128];
+       register int msgnum;
+       register char *cp;
+       int msgp, i;
+       char **ap;
+       char *arguments[50], **argp, **arrp;
+
+       invo_name = argv[0];
+#ifdef NEWS
+       m_news();
+#endif
+       nvecp = 1;
+       msgp = 0;
+       grepp = grep;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       VOID copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')  {
+                       if(*++cp == '-') {              /* --component */
+                   toomany:    if(grepp != grep) {
+                                   fprintf(stderr, "Only one search string.\n");
+                                   goto leave;
+                               }
+                               grepp = copy("^", grepp);
+                               grepp = copy(++cp, grepp);
+                               grepp = copy(":.*", grepp);
+                               goto pattern;
+                       }
+                       switch(i = smatch(cp, switches)) {
+                       case -2:ambigsw(cp, switches);  /* ambiguous */
+                               goto leave;
+                                                       /* unknown */
+                       case -1:fprintf(stderr, "pick: -%s unknown\n", cp);
+                               goto leave;
+                                                       /* -component */
+                       case 0:  case 1:  case 2:  case 4:  case 5:
+                               if(grepp != grep)
+                                       goto toomany;
+                               grepp = copy("^", grepp);
+                               arrp = brkstring(switches[i].sw, " ", NULLCP);
+                               grepp = copy(*arrp, grepp);
+                               grepp = copy(":.*", grepp);
+                       case 3:                         /* -search */
+                      pattern: grepp = copy(*argp++, grepp);
+                               continue;
+                       case 6: fprintf(stderr, "pick:  can't get here\n");
+                               goto leave;
+                                                      /* -all */
+                       case 7: fprintf(stderr, "\"-all\" changed to \"all\"\n");
+                               goto leave;
+                       case 8: filef = 1;  continue;   /* -file */
+                       case 9: filef = 0;  continue;   /* -nofile */
+                       case 10:keepf = 1;  continue;   /* -keep */
+                       case 11:keepf = 0;  continue;   /* -nokeep */
+                       case 12:linkf = 1;  continue;   /* -link */
+                       case 13:linkf = 0;  continue;   /* -nolink */
+                       case 14:prsrvf = 1;  continue;  /* -preserve */
+                       case 15:prsrvf = 0;  continue;  /* -nopreserve */
+                       case 16:scanfl = 1;  continue;   /* -scan */
+                       case 17:scanfl = 0;  continue;   /* -noscan */
+                       case 18:showf = 1;  continue;   /* -show */
+                       case 19:showf = 0;  continue;   /* -noshow */
+                       case 21:stayf = 1;  continue;   /* -stay */
+                       case 22:stayf = 0;  continue;   /* -nostay */
+                       case 20:if(folder) {            /* -src */
+                                       fprintf(stderr, "Only one src folder.\n");
+                                       goto leave;
+                               }
+                               if(!(folder = *argp++) || *folder == '-') {
+               fprintf(stderr, "pick: Missing argument for %s switch\n", argp[-2]);
+                                        goto leave;
+                               }
+                               if(*folder == '+')
+                                       folder++;
+                               folder = path(folder, TFOLDER);
+                               continue;
+                                                       /* -help */
+                       case 23:help("pick   [msgs] [switches]", switches);
+                               goto leave;
+                       }
+               } else if(*cp == '+') {
+                       if(foldp < NFOLD)
+                               folders[foldp++].f_name = path(cp+1, TFOLDER);
+                       else {
+                               fprintf(stderr, "Only %d folders allowed.\n", NFOLD);
+                               goto leave;
+                       }
+               } else
+                       msgs[msgp++] = cp;
+       }
+       if(!m_find("path")) free(path("./", TFOLDER));
+       if(grepp == grep) {
+               fprintf(stderr, "No search pattern specified.\n");
+               goto leave;
+       }
+       if(filef && keepf) {
+               fprintf(stderr, "-file and -keep don't go together.\n");
+               goto leave;
+       }
+       if(!scanfl && !showf && !filef)
+               keepf++;                /* The default is -keep         */
+       if(keepf) {
+               prsrvf++;               /* -keep forces -preserve       */
+               linkf++;                /*   and -link                  */
+       }
+       if(!folder)
+               folder = m_getfolder(); /* use cur folder if no -src    */
+       VOID copy(m_maildir(folder), maildir);
+       if(chdir(maildir) < 0) {
+               fprintf(stderr, "Can't chdir to: ");
+               perror(maildir);
+               goto leave;
+       }
+       if(!(mp = m_gmsg(folder))) {
+               fprintf(stderr, "Can't read folder!?\n");
+               goto leave;
+       }
+       if(mp->hghmsg == 0) {
+               fprintf(stderr, "No messages in \"%s\".\n", folder);
+               goto leave;
+       }
+       if(!foldp) {                    /* if no +folder given...       */
+               if(filef) {             /* -file requires one           */
+                       fprintf(stderr, "-file requires at least one folder arg.\n");
+                       goto leave;
+               }
+               if(keepf) {             /* use default selection-list name */
+                       VOID copy(listname, copy("/", copy(folder, buf)));
+                       folders[foldp++].f_name = getcpy(buf);
+                       noteold++;      /* tell user if existing folder */
+               }
+       } else if(keepf) {              /* make folders sub-folders     */
+               for(msgnum = 0; msgnum < foldp; msgnum++)
+                       if(*(cp = folders[msgnum].f_name) != '.' &&
+                          *cp != '/') {
+                               VOID copy(cp, copy("/", copy(folder, buf)));
+                               folders[msgnum].f_name = getcpy(buf);
+                       }
+               noteold++;
+       }
+       if(!msgp)
+               msgs[msgp++] = "first-last";
+       for(msgnum = 0; msgnum < msgp; msgnum++)
+               if(!m_convert(msgs[msgnum]))
+                       goto leave;
+       if(mp->numsel == 0) {
+               fprintf(stderr, "pick:  Peanut butter 'n jelly\n");/* never get here */
+               goto leave;
+       }
+       if(!compile(grep)) {
+               fprintf(stderr, "Pattern Error.\n");
+               goto leave;
+       }
+       for(msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
+               if(mp->msgstats[msgnum]&SELECTED)
+                       grepfn(msgnum);
+       if(mp->numsel == 0) {
+               fprintf(stderr, "No messages match specification.\n");
+               goto leave;
+       }
+       mp->lowsel = grep_lowsel;
+       mp->hghsel = grep_hghsel;
+                                                     /* all the exec's */
+       if((((delprog = m_find("delete-prog")) != NULL) &&
+           ((filef || keepf) && !linkf)) ||
+             scanfl || showf) {
+               if(mp->numsel > MAXARGS-2) {
+                       fprintf(stderr, "pick: more than %d messages for %s exec\n",
+                               MAXARGS-2,
+                               scanfl ? "scan" : showf ? "show" : delprog);
+                       goto leave;
+               }
+               nvec = (char **) malloc(MAXARGS * sizeof nvec[0]);
+               for(msgnum= mp->lowsel; msgnum<= mp->hghsel; msgnum++)
+                       if(mp->msgstats[msgnum]&SELECTED)
+                               nvec[nvecp++] = getcpy(m_name(msgnum));
+               nvec[nvecp] = 0;
+       }
+       if(keepf || filef)
+               if(opnfolds())
+                       goto leave;
+       if(!noteold || foldp > 1)
+               m_replace(pfolder, folder);
+       if(scanfl)
+               scanfn(showf|filef|keepf);
+       else {
+               printf("%d hit%s.\n", mp->numsel, mp->numsel == 1 ? "" : "s");
+               VOID fflush(stdout);
+       }
+       if(showf)
+               showfn(filef|keepf);
+       if(!(filef|keepf))
+               goto leave;
+       for(msgnum= mp->lowsel; msgnum<= mp->hghsel; msgnum++)
+               if(mp->msgstats[msgnum]&SELECTED)
+                       if(m_file(folder, cp = getcpy(m_name(msgnum)),
+                                 folders, foldp, prsrvf, 1))
+                               goto leave;
+                       else
+                               free (cp);
+       if(!linkf)
+               remove();
+       if(noteold) {
+               struct st_fold *fptr;
+               if(!stayf && foldp == 1) {
+                       m_replace(pfolder, cp = folders[0].f_name);
+                       printf("[+%s now current]\n", cp); VOID fflush(stdout);
+               }
+               for(fptr = folders; fptr < &folders[foldp]; fptr++)
+                       if(!fptr->f_reused) {
+                               VOID chdir(m_maildir(fptr->f_name));
+                               m_setcur(fptr->f_mp->curmsg);
+                       }
+       }
+ leave:
+       m_update();
+}
+
+
+grepfn(msg)
+{
+       if(execute(m_name(msg))) {                  /* a match */
+               if(msg < grep_lowsel)
+                       grep_lowsel = msg;
+               if(msg > grep_hghsel)
+                       grep_hghsel = msg;
+       } else {
+               mp->msgstats[msg] &= ~SELECTED;     /* clear SELECTED bit */
+               mp->numsel--;
+       }
+}
+
+
+opnfolds()
+{
+       register int i;
+       register char *cp, *ap;
+       char nmaildir[128];
+       struct stat stbuf;
+
+       for(i = 0; i < foldp; i++) {
+               VOID copy(m_maildir(cp = folders[i].f_name), nmaildir);
+               if(stat(nmaildir, &stbuf) < 0) {
+                       if(!noteold) {
+                               ap = concat("Create folder \"",
+                                       nmaildir, "\"? ", 0);
+                               if(!gans(ap, anoyes))
+                                       return(1);
+                       }
+                       if(!makedir(nmaildir)) {
+                               fprintf(stderr, "Can't create folder.\n");
+                               return(1);
+                       }
+               } else if(noteold) {
+                       printf("[Folder %s being re-used.]\n", cp);
+                       VOID fflush(stdout);
+                       folders[i].f_reused++; /* Don't change cur in old fold */
+               }
+               if(chdir(nmaildir) < 0) {
+                       fprintf(stderr, "Can't chdir to: ");
+                       perror(nmaildir);
+                       return(1);
+               }
+               if(!(folders[i].f_mp = m_gmsg(folders[i].f_name))) {
+                       fprintf(stderr, "Can't read folder %s\n", folders[i].f_name);
+                       return(1);
+               }
+               folders[i].f_mp->curmsg = 0;
+       }
+       VOID chdir(maildir);    /* return to src folder */
+       return(0);
+}
+
+
+scanfn(forkf)
+{
+       register int pid;
+
+       nvec[0] = r1bindex(scanproc, '/');
+       if(forkf && (pid = fork())) {
+               if(pid == -1) {
+                       fprintf(stderr, "No forks!\n");
+                       done(1);
+               }
+               while(wait((int *)NULL) != pid) ;
+       } else {
+               m_update();
+               VOID fflush(stdout);
+               execv(scanproc, nvec);
+               perror(scanproc);
+               done(1);
+       }
+}
+
+
+showfn(forkf)
+{
+       register int pid;
+       int (*sint)(), (*sqit)();
+
+       nvec[0] = r1bindex(showproc, '/');
+       if(forkf) {
+               sint = signal(SIGINT, SIG_IGN);
+               sqit = signal(SIGQUIT, SIG_IGN);
+       }
+       if(forkf && (pid = fork())) {
+               if(pid == -1) {
+                       fprintf(stderr, "No forks!\n");
+                       done(1);
+               }
+               while(wait((int *)NULL) != pid) ;
+               VOID signal(SIGINT, sint);
+               VOID signal(SIGQUIT, sqit);
+       } else {
+               m_update();
+               VOID fflush(stdout);
+               putenv("mhfolder", folder);
+               execv(showproc, nvec);
+               perror(showproc);
+               done(1);
+       }
+}
+
+
+remove()
+{
+       register int i;
+       register char *cp;
+
+       if(delprog != NULL) {
+               nvec[0] = r1bindex(delprog, '/');
+               m_update();
+               VOID fflush(stdout);
+               execv(delprog, nvec);
+               fprintf(stderr, "Can't exec deletion-prog--");
+               perror(delprog);
+       } else {
+               for(i= mp->lowsel; i<= mp->hghsel; i++)
+                       if(mp->msgstats[i]&SELECTED)
+                               if(unlink(cp = m_name(i)) == -1) {
+                                       fprintf(stderr, "Can't unlink %s:",folder);
+                                       perror(cp);
+                       
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/progs/prevhdr.c b/docs/historical/mh-jun-1982/progs/prevhdr.c
new file mode 100644 (file)
index 0000000..d9d0ee4
--- /dev/null
@@ -0,0 +1,8 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+int     glbtype =   -1;
diff --git a/docs/historical/mh-jun-1982/progs/prompter.c b/docs/historical/mh-jun-1982/progs/prompter.c
new file mode 100644 (file)
index 0000000..0de368a
--- /dev/null
@@ -0,0 +1,287 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+#include <stdio.h>
+#include <errno.h>
+#include <sgtty.h>
+#include <signal.h>
+#include <strings.h>
+
+#define CKILL   006     /* @ => <CLOSE>         */
+#define CERASE  001     /* # => <CTRL A>        */
+
+int     wtuser;         /* waiting for user input */
+int     sigint;         /* sensed an interrupt */
+FILE    *in, *out;
+struct  sgttyb sg;
+struct swit switches[] = {
+       "erase chr",      2,      /* 0 */ /* "2" can become "0",since no ed */
+       "kill chr",       0,      /* 1 */
+       "help",           4,      /* 2 */
+       0,                0
+};
+
+extern  int errno;      /* MLW  4bsd does not have errno defined in errno.h */
+extern  char _sobuf[];          /* MLW  standard out buffer */
+
+/*ARGSUSED*/
+main(argc, argv)
+char *argv[];
+{
+       char tmpfil[32], *drft, name[NAMESZ], field[BUFSIZ];
+       int exitstat;
+       char skill, serase;
+       char *killp, *erasep;
+       register int i, state;
+       register char *cp;
+       char **ap;
+       char *arguments[50], **argp;
+       int sig();
+
+       invo_name = argv[0];
+       setbuf(stdout, _sobuf);
+       tmpfil[0] = 0;
+       skill = 0; exitstat = 0;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       VOID copyip(argv+1, ap);
+       argp = arguments;
+       drft = NULLCP;
+       while(cp = *argp++)
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto badleave;
+                                                            /* unknown */
+                       case -1:fprintf(stderr, "prompter: -%s unknown\n", cp);
+                               goto badleave;
+                       case 0: if(!(erasep = *argp++)) {   /* -erase */
+     missing:  fprintf(stderr, "prompter: Missing argument for %s switch\n", argp[-2]);
+                                       goto badleave;
+                               }
+                               continue;
+                       case 1: if(!(killp= *argp++))       /* -kill */
+                                       goto missing;
+                               continue;
+                                                           /* -help */
+                       case 2: help("prompter    [switches]",
+                                    switches);
+                               goto badleave;
+                       }
+               else if (!drft)
+                       drft = cp;
+       if(!drft) {
+               fprintf(stderr, "prompter: missing skeleton\n");
+               goto badleave;
+       }
+       if((in = fopen(drft, "r")) == NULL) {
+               fprintf(stderr, "Can't open %s\n", drft);
+               goto badleave;
+       }
+       VOID copy(makename("prmt", ".tmp"), copy("/tmp/", tmpfil));
+       if((out = fopen(tmpfil, "w")) == NULL) {
+               fprintf(stderr, "Can't create %s\n", tmpfil);
+               goto badleave;
+       }
+       VOID chmod(tmpfil, 0700);
+       VOID signal(SIGINT, sig);
+       VOID gtty(0, &sg);
+       skill = sg.sg_kill;
+       serase = sg.sg_erase;
+       sg.sg_kill =    killp ?  chrcnv(killp) : skill;
+       sg.sg_erase =   erasep ? chrcnv(erasep) : serase;
+/***    stty(0, &sg);           ***/
+       ioctl(0, TIOCSETN, &sg);
+       if(killp || erasep) {
+               printf("Erase Char="); chrdisp(sg.sg_erase);
+               printf("; Kill Line="); chrdisp(sg.sg_kill);
+               printf(".\n"); VOID fflush(stdout);
+       }
+       state = FLD;
+       for(;;) switch(state = m_getfld(state,name,field,sizeof field,in)) {
+
+       case FLD:
+       case FLDEOF:
+       case FLDPLUS:
+               if(field[0] != '\n' || field[1] != 0) {
+                       printf("%s:%s", name, field);
+                       fprintf(out, "%s:%s", name, field);
+                       while(state == FLDPLUS) {
+                               state=m_getfld(state,name,field,sizeof field,in);
+                               printf("%s", field);
+                               fprintf(out, "%s", field);
+                       }
+               } else {
+                       printf("%s: ", name);
+                       VOID fflush(stdout);
+                       i = getln(field);
+                       if(i == -1)
+                               goto badleave;
+                       if(i == 0 && (field[0] == '\n' || !field[0]))
+                               continue;
+                       fprintf(out, "%s:", name);
+                       do {
+                               if(field[0] != ' ' && field[0] != '\t')
+                                       putc(' ', out);
+                               fputs(field, out);
+                       } while(i == 1 && (i = getln(field)) >= 0);
+                       if(i == -1)
+                               goto badleave;
+               }
+               field[0] = 0;
+               if(state == FLDEOF)
+                       goto body;
+               continue;
+
+       case BODY:
+       case BODYEOF:
+       case FILEEOF:
+  body:         fputs("--------\n", out);
+               printf("--------\n");
+               if(field[0]) {
+                       do {
+                               fputs(field, out);
+                               if(!sigint)
+                                       printf("%s", field);
+                       } while(state == BODY &&
+                               (state=m_getfld(state,name,field,sizeof field,in)));
+                       printf("\n--------Enter additional text\n\n");
+               }
+               VOID fflush(stdout);
+               for(;;) {
+                       VOID getln(field);
+                       if(field[0] == 0)
+                               break;
+                       fputs(field, out);
+               }
+               goto finish;
+
+       default:
+               fprintf(stderr, "Bad format file!\n");
+               goto badleave;
+       }
+
+
+finish:
+       printf("--------\n"); VOID fflush(stdout);
+       VOID fclose(out);
+       out = fopen(tmpfil, "r");
+       VOID fclose(in);
+       in = fopen(drft, "w");          /* Truncate prior to copy back */
+       do
+               if((i = read(fileno(out), field, sizeof field)) > 0)
+                       if(write(fileno(in), field, i) != i) {
+                               fprintf(stderr, "Write error to ");
+                               perror(drft);
+                               done(1);
+                       }
+       while(i == sizeof field);
+       goto leave;
+
+badleave:
+       exitstat = 1;
+
+leave:
+       if(in)
+               VOID fclose(in);
+       if(out)
+               VOID fclose(out);
+       if(tmpfil[0])
+               VOID unlink(tmpfil);
+       m_update();
+       if(killp || erasep) {
+               sg.sg_kill = skill;
+               sg.sg_erase = serase;
+/***            stty(0, &sg);           ***/
+               ioctl(0, TIOCSETN, &sg);
+       }
+       done(exitstat);
+}
+
+
+getln(buf)
+       char *buf;
+{
+       register char *cp;
+       register int c;
+       int stat;
+
+       cp = buf;
+       *cp = 0;
+       wtuser = 1;
+       for(;;) {
+               c = getchar();
+/***            fprintf(stderr,"getchar()=\\%o,errno=%d,EINTR=%d\n",c,errno,EINTR);/***/
+               if(c == EOF)
+                       if(errno == EINTR) {
+                               stat = -1;
+                               goto leave;
+                       } else {
+                               stat = 0;
+                               goto leave;
+                       }
+               if(c == '\n') {
+                       if(cp[-1] == '\\') {
+                               cp[-1] = c;
+                               stat = 1;
+                               goto leave;
+                       }
+                       *cp++ = c;
+                       *cp   = 0;
+                       stat = 0;
+                       goto leave;
+               }
+               if(cp < buf + 500)
+                       *cp++ = c;
+               *cp = 0;
+       }
+ leave: wtuser = 0;
+       return(stat);
+       }
+
+
+sig()
+{
+       VOID signal(SIGINT, sig);
+       if(!wtuser)
+               sigint = 1;
+       return;
+}
+
+
+chrcnv(str)
+char *str;
+{
+       register char *cp;
+       register int c;
+
+       cp = str;
+       if((c = *cp++) != '\\')
+               return(c);
+       c = 0;
+       while(*cp && *cp != '\n') {
+               c *= 8;
+               c += *cp++ - '0';
+       }
+       return c;
+}
+
+
+chrdisp(chr)
+{
+       register int c;
+
+       c = chr;
+       if(c < ' ')
+               printf("<CTRL-%c>", c + '@');
+       else
+               printf("%c"
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/progs/ptt.c b/docs/historical/mh-jun-1982/progs/ptt.c
new file mode 100644 (file)
index 0000000..1057c8b
--- /dev/null
@@ -0,0 +1,42 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../adrparse.h"
+
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       register struct mailname *mp;
+       register char *cp;
+
+       if(!(mp = getm(argv[1],"RAND-UNIX"))) {
+               printf("adrparse returned 0\n");
+               exit(0);
+       }
+       printf("%s\n", mp->m_text);
+       printf("mbox: %s\n", mp->m_mbox);
+       if(!mp->m_nohost) {
+               printf("at: ");
+               cp = mp->m_at;
+               if(*cp == '@') putchar('@');
+               else while(*cp != ' ') putchar(*cp++);
+               printf("\n");
+       }
+       printf("host: %s ", mp->m_host);
+       if(mp->m_nohost)
+               printf("[default] ");
+       else {
+               putchar('"');
+               for(cp = mp->m_hs; cp <= mp->m_he; )
+                       putchar(*cp++);
+               putchar('"');
+       }
+       printf("\n");
+       printf("hnum: %d\n", mp->m_hnum);
+       printf("Proper: %s\n", adrformat(mp,"RAND-UNIX"));
+}
diff --git a/docs/historical/mh-jun-1982/progs/repl.c b/docs/historical/mh-jun-1982/progs/repl.c
new file mode 100644 (file)
index 0000000..c99d1df
--- /dev/null
@@ -0,0 +1,494 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include <whoami.h>
+#include "../mh.h"
+#include <stdio.h>
+#include <signal.h>
+#include <strings.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "../adrparse.h"
+
+#define ERRHOST "?????"
+/*#define NEWS 1*/
+
+#define NOUSE 0
+
+/* #define TEST 1 */
+
+struct swit anyl[] = {
+       "no",   0,
+       "yes",  0,
+       "list", 0,
+       0
+};
+
+struct swit aleqs[] = {
+       "list",                 0,      /* 0 */
+       "edit [<editor>]",      0,      /* 1 */
+       "quit [delete]",        0,      /* 2 */
+       "send [switches]",      0,      /* 3 */
+       0
+};
+
+short   anot;
+#define OUTPUTLINELEN 72
+short   outputlinelen = OUTPUTLINELEN;
+short   ccme = 1;
+struct msgs *mp;
+char    *ed;
+short   format = -1;            /* Default to re-format optionally*/
+short   inplace;                /* preserve links in anno */
+short   debug;
+char    *badaddrs;
+
+struct swit switches[] = {
+       "annotate",           0,      /* 0 */
+       "noannotate",         0,      /* 1 */
+       "ccme",              -1,      /* 2 */
+       "noccme",            -1,      /* 3 */
+       "editor editor",      0,      /* 4 */
+       "format",             0,      /* 5 */
+       "noformat",           0,      /* 6 */
+       "inplace",            0,      /* 7 */
+       "noinplace",          0,      /* 8 */
+       "width",              0,      /* 9 */
+       "help",               4,      /*10 */
+       "debug",              -5,     /*11 */
+       0,                    0
+};
+
+char *ltrim();
+char *rtrim();
+char *niceadd();
+char *fix();
+char *addr();
+
+
+/*ARGSUSED*/
+main(argc, argv)
+char *argv[];
+{
+       char *folder, *msg, *maildir;
+       register char *cp, **ap, **argp;
+       char *arguments[50];
+
+       invo_name = argv[0];
+#ifdef NEWS
+       m_news();
+#endif
+       msg = 0; anot = 0; folder = 0;
+
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       VOID copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                            /* unknown */
+                       case -1:fprintf(stderr, "repl: -%s unknown\n", cp);
+                               goto leave;
+                       case 0: anot = 1;  continue;         /* -annotate */
+                       case 1: anot = 0;  continue;         /* -noannotate */
+                       case 2: ccme = 1;  continue;         /* -ccme */
+                       case 3: ccme = 0;  continue;         /* -noccme */
+                       case 4: if(!(ed = *argp++)) {        /* -editor */
+missing:        fprintf(stderr, "repl: Missing argument for %s switch\n", argp[-2]);
+                                       goto leave;
+                               }
+                               continue;
+                       case 5: format = 1; continue;        /* -format */
+                       case 6: format = 0; continue;        /* -noformat */
+                       case 7: inplace = 1;  continue;      /* -inplace */
+                       case 8: inplace = 0;  continue;      /* -noinplace */
+                       case 9: if(!(cp = *argp++) || *cp == '-')
+                                       goto missing;
+                               outputlinelen = atoi(cp); continue;
+                                                            /* -help */
+                       case 10:help("repl   [+folder] [msg] [switches]",
+                                    switches);
+                               goto leave;
+                       case 11:debug++; continue;           /* -debug */
+
+                       }
+               if(*cp == '+') {
+                       if(folder) {
+                               fprintf(stderr, "Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               folder = path(cp+1, TFOLDER);
+               } else if(msg) {
+                       fprintf(stderr, "Only one message per reply.\n");
+                       goto leave;
+               } else
+                       msg = cp;
+       }
+       if(!m_find("path")) free(path("./", TFOLDER));
+       if(!msg)
+               msg = "cur";
+       if(!folder)
+               folder = m_getfolder();
+       maildir = m_maildir(folder);
+       if(chdir(maildir) < 0) {
+               fprintf(stderr, "Can't chdir to: ");
+               perror(maildir);
+               goto leave;
+       }
+       if(!(mp = m_gmsg(folder))) {
+               fprintf(stderr, "Can't read folder!?\n");
+               goto leave;
+       }
+       if(mp->hghmsg == 0) {
+               fprintf(stderr, "No messages in \"%s\".\n", folder);
+               goto leave;
+       }
+       if(!m_convert(msg))
+               goto leave;
+       if(mp->numsel == 0) {
+               fprintf(stderr, "repl: pepperoni pizza\n");/* never get here */
+               goto leave;
+       }
+       if(mp->numsel > 1) {
+               fprintf(stderr, "Only one message at a time.\n");
+               goto leave;
+       }
+       m_replace(pfolder, folder);
+       if(mp->lowsel != mp->curmsg)
+               m_setcur(mp->lowsel);
+       repl(getcpy(m_name(mp->lowsel)));
+ leave:
+       m_update();
+       done(0);
+}
+
+char   *mn_rep;
+
+repl(msg)
+       char *msg;
+{
+       register char *cp;
+       register int i;
+       FILE *in, *out;
+       char name[NAMESZ], field[BUFSIZ];
+       char *drft, *msgid, *replto, *from, *sub, *date, *sender, *to, *cc;
+       int state;
+       int pid, wpid;
+       char **argp;
+       struct mailname *mnp = 0;
+       struct stat stbuf;
+
+/***/if(debug) printf("repl(%s)\n", msg);
+       if((in = fopen(msg, "r")) == NULL) {
+               fprintf(stderr, "Can't open "); perror(msg);
+               return;
+       }
+       drft = m_maildir(draft);
+/***/if(debug) printf("drft=%s\n", drft);
+       if(stat(drft, &stbuf) != -1) {
+               cp = concat("\"", drft, "\" exists; delete? ", 0);
+               while((i = gans(cp, anyl)) == 2)
+                       VOID showfile(drft);
+               if(!i)
+                       return;
+               free(cp);
+       }
+       if((out = fopen(drft, "w")) == NULL) {
+               fprintf(stderr, "Can't create \"%s\".\n", drft);
+               return;
+       }
+       VOID chmod(drft, m_gmprot());
+
+       state = FLD;
+       to = cc = sender = replto = msgid = from = sub = date = 0;
+
+    for(;;) {
+
+       switch(state = m_getfld(state, name, field, sizeof field, in)) {
+
+       case FLD:
+       case FLDEOF:
+       case FLDPLUS:
+               if(uleq(name, "from")) {
+                       if(state == FLD && from) from = add(",",from);
+                       from = add(field, from);
+                       }
+               if(uleq(name, "cc")) {
+                       if(state == FLD && cc) cc = add(",",cc);
+                       cc = add(field, cc);
+                       }
+               if(uleq(name, "subject"))
+                       sub = add(field, sub);
+               if(uleq(name, "date"))
+                       date = add(field, date);
+               if(uleq(name, "to")) {
+                       if(state == FLD && to) to = add(",",to);
+                       to = add(field, to);
+                       }
+               if(uleq(name, "message-id"))
+                       msgid = add(field, msgid);
+               if(uleq(name, "reply-to")) {
+                       if(state == FLD && replto) replto = add(",",replto);
+                       replto = add(field, replto);
+                       }
+               if(uleq(name, "sender")) {
+                       if(state == FLD && sender) sender = add(",",sender);
+                       sender = add(field, sender);
+                       }
+               if(state == FLDEOF)
+                       goto done;
+               break;
+
+       case BODY:
+       case BODYEOF:
+       case FILEEOF:
+               goto done;
+
+       default:
+               fprintf(stderr, "getfld returned %d\n", state);
+               return;
+       }
+
+    }
+
+done:
+       VOID fclose(in);
+
+       if(!(sender || from)) {
+               fprintf(stderr, "repl: No Sender or From!?\n");
+               return;
+       }
+
+       /* Pick up replacement host from "sender", else "from" */
+#ifdef ARPANET
+       if((cp = getname(sender ? sender : from)) == 0)
+               return;
+       if((mnp = getm(cp, HOSTNAME)) == 0)
+               mn_rep = ERRHOST;
+       else {
+               if((mnp -> m_at) && ((*mnp -> m_at) == '!')) {  /* UUCP address */
+                       cp = stdhost((long)HOSTNUM);
+               }
+               else
+                       cp = stdhost(mnp->m_hnum);
+               if(!cp) {
+                       fprintf(stderr, "repl: Unknown host: %s\n", mnp->m_host);
+                       return;
+               }
+               mn_rep = getcpy(cp);
+               mnfree(mnp);
+       }
+#else
+       mn_rep = getcpy (HOSTNAME);
+#endif
+       while(getname("")) ;    /* In case multi-name from/sender */
+
+      /***/if(debug) printf("before testformats\n");
+       /* Set format flag to 0 or 1 based on actual addresses, */
+       /*  provided it hasn't been explicitly set */
+
+       if(format == -1 && *mn_rep == '?') /* Oops, error in sender/from.*/
+               format = 1;        /* Format! Use replacement host ERRHOST */
+       if(format == -1) testformat(sender);
+       if(format == -1) testformat(from);
+       if(format == -1) testformat(replto);
+       if(format == -1) testformat(to);
+       if(format == -1) testformat(cc);
+       if(format == -1) format = 0;    /* All LOCAL--don't format! */
+
+/***/if(debug) printf("after testformats\n");
+       if(!(from || replto)) {
+               fprintf(stderr, "No one to reply to!!!\n");
+               return;
+       }
+       outfmt(out, replto ? replto : from, "To", 0);
+
+       if(to && cc)            /* Combine to & cc data */
+               to = add(" ,", to);
+       if(cc)
+               to = add(cc, to);
+       outfmt(out, to, "Cc", 1);
+
+       if(sub) {                               /* Subject: Re: */
+               fprintf(out, "Subject: ");
+               if(*sub == ' ') sub++;
+               if((sub[0] != 'R' && sub[0] != 'r') ||
+                  (sub[1] != 'E' && sub[1] != 'e') ||
+                  sub[2] != ':')
+                       fprintf(out, "Re: ");
+               fprintf(out, sub);
+       }
+       if(date) {                              /* In-reply-to: */
+               date[strlen(date)-1] = '.';
+               if(*date == ' ') date++;
+               fprintf(out, "In-reply-to: Your message of %s\n", date);
+               if(msgid) {
+                       if(*msgid == ' ') msgid++;
+                       fprintf(out, "             %s", msgid);
+               }
+       }
+       fprintf(out, "----------\n");
+       if(badaddrs)
+               fprintf(out, "\nREPL: CANT CONSTRUCT:\n%s\n", badaddrs);
+       if(fclose(out) == EOF) {
+               fprintf(stderr, "reply: Write error on ");
+               perror(drft);
+               return;
+       }
+       if(!debug)
+               if(m_edit(&ed, drft, NOUSE, msg) < 0)
+                       return;
+#ifdef TEST
+       fprintf(stderr, "!! Test Version of SEND Being Run !!\n");
+       fprintf(stderr, "   Send verbose !\n\n");
+#endif
+
+    for(;;) {
+       if(!(argp = getans("\nWhat now? ", aleqs))) {
+               VOID unlink("@");
+               return;
+       }
+       switch(smatch(*argp, aleqs)) {
+               case 0: VOID showfile(drft);                    /* list */
+                       break;
+
+               case 1: if(*++argp)                             /* edit */
+                               ed = *argp;
+                       if(m_edit(&ed, drft, NOUSE, msg) == -1)
+                               return;
+                       break;
+
+               case 2: if(*++argp && (*argp[0] == 'd' ||       /* quit */
+                                      (*argp[0]=='-' && *argp[1]=='d')))
+                               if(unlink(drft) == -1)  {
+                                       fprintf(stderr, "Can't unlink %s ", drft);
+                                       perror("");
+                               }
+                       return;
+
+               case 3:                                         /* send */
+                       if(!mp->msgflags&READONLY) {    /* annotate first */
+                           if(anot > 0) {
+                               while((pid = fork()) == -1) sleep(5);
+                               if(pid) {
+                                       while((wpid=wait((int *)NULL))!= -1
+                                             && wpid!= pid);
+                                       if(stat(drft, &stbuf) == -1)
+                                               annotate(msg, "Replied", "", inplace);
+                                       return;
+                               }
+                           }
+                       }
+                       VOID m_send(++argp, drft);
+                       return;
+
+               default:fprintf(stderr, "repl: illegal option\n");       /*##*/
+                       break;
+       }
+    }
+}
+
+
+outfmt(out, str, fn, chk)
+       FILE *out;
+       char *str, *fn;
+       int chk;
+{
+       register char *cp;
+       register struct mailname *mnp = 0;
+       short ccoutput = 0, linepos = 0, len;
+
+/***/if(debug)printf("outfmt mn_rep=%s\n", mn_rep);
+       while(cp = getname(str)) {
+               if(mnp) mnfree(mnp);
+/***/if(debug)printf("Parse '%s'\n",cp);
+
+               /* If couldn't find foreign default host due to sender/from */
+               /* parse error, hand adrparse HOSTNAME for the time. */
+
+               if((mnp = getm(cp, *mn_rep == '?' ? HOSTNAME : mn_rep)) == 0){
+                       char buf[512];
+                       /* Can't parse.  Add to badlist. */
+                       VOID sprintf(buf, " %s: %s\n", fn, cp);
+                       badaddrs = add(buf,  badaddrs);
+                       continue;
+               } else if(*mn_rep == '?') {
+                       /*
+                        * Now must distinguish between explicit-local and
+                        * hostless-foreign, which parse identically
+                        * because of the borrowed HOSTNAME.
+                        * Kludge: If same string gives parse error when
+                        * default host is ERRHOST, then original string was
+                        * hostless (foreign).  Otherwise original string had
+                        * HOSTNAME explicitly and is local.
+                        */
+                       struct mailname *tmpmnp;
+
+                       if(tmpmnp = getm(cp, ERRHOST))
+                               mnfree(tmpmnp);
+                       else
+                               mnp->m_host = getcpy(ERRHOST);
+
+               }
+/***/if(debug) printf ("Host %D\n",mnp->m_hnum);
+               if(chk && !ccme && uleq(mnp->m_mbox, getenv("USER")) &&
+                  mnp->m_hnum == HOSTNUM)
+                       continue;
+               if(!ccoutput) {
+                       fprintf(out, "%s: ", fn);
+                       linepos += (ccoutput = strlen(fn) + 2);
+               }
+               if((format && *mn_rep != '?')|| ((mnp->m_at && *mnp->m_at != '!') &&
+                             (mnp->m_hnum != HOSTNUM)) ) {
+
+/***/if(debug) printf ("That's not %d, so format it (name %s)\n",
+                       HOSTNUM, HOSTNAME);
+                       cp = adrformat(mnp,HOSTNAME);
+/***/if(debug) printf ("Formatting produces '%s'\n",cp);
+               }
+               else if (format && *mn_rep == '?') {
+                       cp = adrformat(mnp, mn_rep);
+               }
+               else
+                       cp = mnp->m_text;
+               len = strlen(cp);
+               if(linepos != ccoutput)
+                       if(len + linepos + 2 > outputlinelen) {
+                               fprintf(out, ",\n%*s", ccoutput, "");
+                               linepos = ccoutput;
+                       } else {
+                               fputs(", ", out);
+                               linepos += 2;
+                       }
+               fputs(cp, out);
+               linepos += len;
+       }
+       if(mnp) mnfree(mnp);
+       if(linepos) putc('\n', out);
+}
+
+
+testformat(str)
+       char *str;
+{
+       register struct mailname *mnp;
+       register char *cp;
+
+       if(str)
+               while(cp = getname(str)) {
+                       if(mnp = getm(cp, mn_rep)) {
+                               if((mnp->m_hnum != HOSTNUM) &&
+                                  (mnp->m_at) && (*mnp->m_at != '!'))
+                                       format = 1;
+                               mnfree(m
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/progs/replsubs.c b/docs/historical/mh-jun-1982/progs/replsubs.c
new file mode 100644 (file)
index 0000000..5e6e772
--- /dev/null
@@ -0,0 +1,236 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+
+char *ltrim(cp)
+char *cp;
+{
+       /* Return pointer to 1st non-blank char in string;
+        * If ptr ==> 0 or ptr ==> '\n'0, return NUL;
+        */
+
+       register char *cp1;
+
+       cp1 = cp;
+       while((*cp1 == ' ') || (*cp1 == '\t')) cp1++;
+       if((*cp1 == 0) || (*cp1 == '\n' && cp1[1] == 0))
+               cp1 = 0;
+       return(cp1);
+}
+
+char *rtrim(cp)
+       char *cp;
+{
+       /* trim newline and blanks from the right */
+
+       register char *cp1;
+
+       cp1 = cp+strlen(cp)-1;
+       if(*cp1 == '\n') *cp1 = 0;
+       while(*--cp1 == ' ') ;
+       *++cp1 = 0;
+       return(cp);
+}
+
+char *niceadd(this, that)
+char *this, *that;
+{
+       register char *from, *to;
+
+       if(!(from = ltrim(this)))               /* nothing to add */
+               return(that);
+
+       if(to = that)
+               to = add(",\n    ", rtrim(to)); /* enuf blanks for "cc: " */
+       return(add(from, to));
+}
+
+#define ADDRLEN (needadr ? addrlen : 0)
+
+char *fix(field, address)
+char *field, *address;
+{
+       /* Appends address to each needy addressee in "field".
+        * Returns pointer to copy of new string. (HUH?)
+        * "field" should never be 0
+        */
+
+       register int len;
+       register char *newp;
+       int addrlen;
+       int needadr;
+       int fieldlen;
+       char *cp;
+
+       addrlen = strlen(address);
+       len = 0;
+       newp = "";
+
+       for(cp = field; ;cp += fieldlen + 1) {
+               needadr = needsaddr(&cp, &fieldlen); /* cp may be changed */
+               if(fieldlen == 0) {
+                       cndfree(field);
+                       newp = add("\n", newp);
+                       return(newp);
+               }
+               if((len + fieldlen + ADDRLEN) > 70) {
+                       newp = add(",\n    ", newp);
+                       len = 4;
+               } else if (*newp) {
+                       newp = add(", ", newp);
+                       len += 2;
+               }
+               *(cp + fieldlen) = 0;
+               newp = add(cp, newp);
+               if(needadr)
+                       newp = add(address, newp);
+               len += fieldlen + ADDRLEN;
+       }
+}
+
+anychar(fchars, field)
+char *fchars, *field;
+{
+       /* Returns 1 if any fancy char appears in "field"
+        * Returns 0 if either "field" is nul or contains no fancy chars
+        */
+
+       register char *fp;
+
+       if(!field)
+               return(0);
+       for(fp = fchars; *fp; fp++)
+               if(r_any(*fp, field))
+                       return(1);
+       return(0);
+}
+
+
+r_any(chr,stg)
+char chr, *stg;
+{
+       register char c, *s;
+
+       c = chr;
+       for (s = stg; (*s) && (*s != ',') && (*s != '\n');)
+               if (*s++ == c) return (1);
+       return (0);
+}
+
+char *
+addr(text)
+char *text;
+{
+       static char buf[128];
+       register char *cp, *bufp;
+       int textseen, blankseen;
+       char *copyaddr();
+
+       textseen = blankseen = 0;
+       bufp = buf;
+       if(!text)
+               return(0);
+       for(cp = text; (*cp == ' ' || *cp == '\t'); cp++);
+       for(;;cp++) {
+               switch(*cp) {
+               default:
+                       textseen++;
+                       break;
+               case ' ':  case '\t':
+                       blankseen++;
+                       break;
+               case 'a':
+                       if(!blankseen || !textseen || !ssequal("at ",cp)){
+                               textseen++;
+                               break;
+                       }
+                       bufp = copy(" at ", buf);
+                       VOID copyaddr(cp+3, bufp);
+                       return(buf);
+               case '@':
+                       if(!textseen)
+                               return(0);
+                       bufp = copy(" @ ", buf);
+                       VOID copyaddr(cp+1, bufp);
+                       return(buf);
+               case ',':  case '\n':  case 0:
+                       return(0);
+               }
+       }
+}
+
+#define ND1  (*fp) && (*fp != ' ') && (*fp != '\t')
+#define ND2  (*fp != '<') && (*fp != '(') && (*fp != '>') && (*fp != ')')
+#define ND3  (*fp != '\n') && (*fp!= ',') && (*fp != ':')
+#define NOTDELIM  ND1 && ND2 && ND3
+
+char *copyaddr(fp, tp)
+       register char *fp, *tp;
+{
+       /* Copies left-trimmed "from" to "to".
+        * Copy terminates on any delimiter.
+        * Returns pointer to NUL terminator in destination string
+        */
+
+       for( ; *fp == ' ' || *fp == '\t'; fp++) ;
+       for( ; NOTDELIM; *tp++ = *fp++);
+       *tp = 0;
+       return(tp);
+}
+#define NOTRELEVANT (*cp == ' ' || *cp == '\t' || *cp == '\n'|| *cp == ',')
+
+needsaddr(field, fieldlen)
+char **field;
+int *fieldlen;
+{
+       /* Returns 1 if this field needs an address
+        * Returns 0 if field contains any funny chars or has
+        * an address of the form "xxxx at " or "xxxx[<b>]@"
+        * "field": on input --  addr of pointer to start of field
+        *          on output -- val of ptr moved to 1st meaty char
+        * "fieldlen" returns the length of the new field
+        *  (it terminates on ',' or '\n' or 0)
+        */
+
+       register char *cp;
+       int textseen = 0, blankseen = 0;
+       int retval;
+                                  /* find 1st relevant char in field */
+       for(cp = *field; NOTRELEVANT ; cp++);
+
+       *field = cp;               /* return it to caller */
+       if(anychar("(<:", cp)) {
+               retval = 0;
+               goto leave;
+       }
+       for(;;cp++) {
+               switch(*cp) {
+               default:
+                       textseen++;
+                       break;
+               case ' ':  case '\t':
+                       blankseen++;
+                       break;
+               case 'a':
+                       if(!blankseen || !textseen || !ssequal("at ",cp)){
+                               textseen++;
+                               break;
+                       }
+               case '@':
+                       retval = 0;
+                       goto leave;
+               case ',':  case '\n':  case 0:
+                       retval = 1;
+                       goto leave;
+
+               }
+       }
+ leave:
+       for(; (*cp) && (*cp != ',') && (*cp != '\n'); cp++) ;
+       *fieldlen = cp- *field;
+       return(retv
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/progs/rmail.c b/docs/historical/mh-jun-1982/progs/rmail.c
new file mode 100644 (file)
index 0000000..d18bbd6
--- /dev/null
@@ -0,0 +1,391 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+static char *sccsid = "@(#)from rmail.c      4.1 (Berkeley) 10/1/80";
+/*
+ * rmail: front end for mail to stack up those stupid >From ... remote from ...
+ * lines and make a correct return address.  This works with the -f option
+ * to /etc/delivermail so it won't work on systems without delivermail.
+ * However, it ought to be easy to modify a standard /bin/mail to do the
+ * same thing.
+ *
+ * NOTE: Rmail is SPECIFICALLY INTENDED for ERNIE COVAX because of its
+ * physical position as a gateway between the uucp net and the arpanet.
+ * By default, other sites will probably want /bin/rmail to be a link
+ * to /bin/mail, as it was intended by BTL.  However, other than the
+ * (somewhat annoying) loss of information about when the mail was
+ * originally sent, rmail should work OK on other systems running uucp.
+ * If you don't run uucp you don't even need any rmail.
+ *
+ * This version revised around New Year's Day 1981 to interface with
+ * Rand's MH system.  The nature of the revision is to (1) do nothing
+ * if the destination is uucp-remote (note the assumption of single
+ * destination) and (2) to call "/etc/mh/deliver" to do the deed.
+ *
+ * Revised Aug 1981 to add NOGATEWAY screen.  Also fixed a few bugs.
+ * PK.
+ *
+ * 5/8/82: Tack on uu-Date: if msg has no date.  PK.
+ */
+
+/*#define DEBUG 1*/
+
+#include "../mh.h"
+#include <whoami.h>
+#include <stdio.h>
+
+#define MATCH   0
+#define PARSE   1
+#define NOPARSE 0
+
+
+char *index();
+
+FILE *out;              /* output to delivermail */
+char *tmpfil;           /* file name of same */
+char tmpfila[24];       /* array for tmpfil */
+char *to;               /* argv[1] */
+char from[512];         /* accumulated path of sender */
+char lbuf[512];         /* one line of the message */
+
+char d1[10], d2[10], d3[10], d4[10], d5[10];   /*** ctime() fields ***/
+
+#ifdef ARPANET
+int netaddr;            /* set if "to" contains an arpanet address */
+#endif
+
+main(argc, argv)
+char **argv;
+{
+       char ufrom[64]; /* user on remote system */
+       char sys[64];   /* a system in path */
+       char junk[512]; /* scratchpad */
+       char *cp;
+       int badhdr;   /***/
+
+       to = argv[1];
+       if (argc != 2) {
+               fprintf(stderr, "Usage: rmail user\n");
+               exit(1);
+       }
+#ifdef DEBUG
+       out=stdout;
+       tmpfil = "/dev/tty";
+#else
+       tmpfil = tmpfila;
+       sprintf (tmpfil, "/tmp/%s", makename ("mail",".tmp"));
+       if ((out=fopen(tmpfil, "w")) == NULL) {
+               fprintf(stderr, "Can't create %s\n", tmpfil);
+               exit(1);
+       }
+#endif
+       for (;;) {
+               fgets(lbuf, sizeof lbuf, stdin);
+               if (strncmp(lbuf, "From ", 5) && strncmp(lbuf, ">From ", 6))
+                       break;
+               fputs(lbuf, out); /* Save--in case we are just forwarding */
+/***/           sscanf(lbuf, "%s %s %s %s %s %s %s remote from %s",
+                junk, ufrom, d1, d2, d3, d4, d5, sys);
+/*              sscanf(lbuf, "%s %s", junk, ufrom);  */
+               cp = lbuf;
+               for (;;) {
+                       cp = index(cp+1, 'r');
+                       if (cp == NULL)
+                               cp = "remote from somewhere";
+#ifdef DEBUG
+                       printf("cp='%s'\n", cp);
+#endif
+                       if (strncmp(cp, "remote from ", 12) == MATCH)
+                               break;
+               }
+               sscanf(cp, "remote from %s", sys);
+               strcat(from, sys);
+               strcat(from, "!");
+#ifdef DEBUG
+               printf("ufrom='%s', sys='%s', from now '%s'\n", ufrom, sys, from);
+#endif
+       }
+       strcat(from, ufrom);
+
+#ifdef DEBUG
+       printf("from now '%s'\n",  from);
+#endif
+
+
+#ifdef ARPANET
+       netaddr = isarpa(to);           /* Arpanet destination?  */
+
+#ifdef NOGATEWAY
+       if(netaddr && !okhost(sys))
+       {
+               truncate();
+               returnmail("Sorry, not an Arpanet gateway!");
+               exit(0);
+       }
+#endif
+
+       if (index (to, '!') && !netaddr)  {
+#else
+       if (index (to, '!')) {
+#endif
+               /* Just forwarding! */
+               putmsg(NOPARSE);
+               deliver(to);
+               exit(0);
+       }
+
+       truncate();
+       /* fprintf(out, "To: %s\n",to); */
+       putfrom();
+
+       if( !((cp = index(lbuf, ':')) &&  (cp - lbuf <  NAMESZ ))) {
+               fputs("\n",out);/* Doesn't look good; terminate hdr */
+               badhdr++;
+       }
+       putmsg(badhdr?NOPARSE:PARSE);
+       deliver(to);
+
+}
+
+
+deliver(to)
+       char *to;
+{
+       int sts,pid,waitid;
+
+#ifdef DEBUG
+       printf("%s would get called here; Delivery to: %s \n", mh_deliver,to);
+       exit(0);
+#endif
+       fclose(out);
+
+       if ((pid=fork()) == -1) {
+               fprintf(stderr, "Cannot fork Deliver!\n");
+
+#ifndef DEBUG   /* Extra precaution */
+               unlink(tmpfil);
+#endif
+               exit(1);
+       }
+       if(pid) {
+               while(((waitid = wait(&sts)) != pid) && (waitid != -1));
+
+#ifndef DEBUG   /* Extra precaution */
+               unlink(tmpfil);
+#endif
+               exit(0);
+       }
+       execl(mh_deliver, "deliver", "-deliver", to, tmpfil, 0);
+
+       perror( "Cannot exec Deliver ");
+
+       exit(1);
+
+}
+
+#ifdef ARPANET
+
+isarpa(str)                             /* Gateway to Arpanet? */
+       char *str;
+{
+       char *cp;
+
+       if (index (str, '@'))
+               return(1);
+
+       for (cp = str; ;) {
+               if((cp = index(cp, ' ')) == NULL)
+                       return(0);
+               while(*cp == ' ')
+                       cp++;
+               if ((strncmp(cp, "at ", 3) == MATCH) ||
+                   (strncmp(cp, "AT ", 3) == MATCH) ||
+                   (strncmp(cp, "At ", 3) == MATCH))
+
+                       return(1);
+       }
+}
+
+
+okhost(str)             /* Host permitted to use us as an arpanet gateway? */
+       char *str;
+{
+       register short i;
+
+       for (i=0; rhosts[i]; i++)
+               if (strcmp (str, rhosts[i]) == MATCH)
+                       return(1);
+       return(0);
+}
+#endif
+
+returnmail(message)
+       char  *message;
+{
+
+#ifdef DEBUG
+       printf("returnmail()\n");
+#endif
+       if(!from)  return;
+
+       putdate();
+       fprintf(out, "To: %s\n", from);
+       fputs("\n",out);
+       fputs (message, out);
+       fputs("\n\n\n*--------------RETURNED MESSAGE---------------*\n\n",
+         out);
+
+       putmsg(NOPARSE);
+       deliver(from);
+
+}
+
+
+#include <sys/types.h>
+#include <sys/timeb.h>
+#include <time.h>
+
+putdate()
+{
+       long  now;
+       register char *t, *p;
+       char *timezone();
+       struct timeb tb;
+       struct tm *tmp;
+       static char *wday[] = {
+               "Sun",
+               "Mon",
+               "Tues",
+               "Wednes",
+               "Thurs",
+               "Fri",
+               "Satur"
+       };
+
+       now = time((long *)0);
+       t = ctime(&now);
+       ftime(&tb);
+       tmp = localtime(&now);
+       p = timezone(tb.timezone, tmp->tm_isdst);
+
+       /*                  day    13   Apr  1981 20  :38   -PST */
+       fprintf(out, "Date: %sday, %.2s %.3s %.4s %.2s:%.2s-%.3s\n",
+                    wday[tmp->tm_wday], t+8, t+4, t+20, t+11, t+14, p);
+}
+
+
+putfrom()
+{
+       if (strlen(from)) 
+#ifdef ARPANET
+               if (netaddr)
+                       fprintf(out, "From: %s at %s\n",from, HOSTNAME);
+               else
+                       fprintf(out, "From: %s\n", from);
+#else
+               fprintf(out, "From: %s\n",from);
+#endif
+
+}
+
+
+putmsg(parse)
+int parse;
+{
+       int dateseen = 0;
+
+       if(!parse)
+               putall();
+       else {
+               if (uleqn(lbuf, "date:", 5) == 0)
+                       dateseen++;
+               fputs(lbuf, out);
+               while (fgets(lbuf, sizeof lbuf, stdin)) {
+                       if(lbuf[0] == '\n' ) { /* end of hdrs */
+                               if(!dateseen)
+                                       uudate();
+                               putall();
+                       } else {
+                               if (uleqn(lbuf, "date:", 5) == 0)
+                                       dateseen++;
+                               fputs(lbuf, out);
+                       }
+               }
+       }
+}
+
+
+putall()
+{
+       fputs(lbuf, out);
+       while (fgets(lbuf, sizeof lbuf, stdin))
+               fputs(lbuf, out);
+}
+
+
+truncate()
+{
+       /* Truncate those "...remote from..." header lines. */
+       /* They're kept only if the message is to be uucp-forwarded */
+
+#ifndef DEBUG
+       fclose (out);   out=fopen(tmpfil, "w");
+#endif
+
+}
+
+
+/*
+ * Compare strings (at most n bytes) without regard to case.
+ *   Returns:   s1>s2: >0,  s1==s2: 0,  s1<s2: <0.
+ */
+
+uleqn(s1, s2, n)
+register char *s1, *s2;
+register n;
+{
+
+       while (--n >= 0 && (*s1|040) == (*s2|040)) {
+               s2++;
+               if (*s1++ == '\0')
+                       return(0);
+       }
+       return(n<0 ? 0 : (*s1|040) - (*s2|040));
+}
+
+
+uudate()
+{
+       char *prefix();
+
+       /*                  day    13   Apr  1981 20  :38   -PST */
+       fprintf(out, "Date: %sday, %.2s %.3s %.4s %.2s:%.2s-%.3s\n",
+                    prefix(d1), d3, d2, d5, d4, d4+3, "???");
+}
+
+char *
+prefix(str)
+char *str;
+{
+       static char *wday[] = {
+               "Sun",
+               "Mon",
+               "Tues",
+               "Wednes",
+               "Thurs",
+               "Fri",
+               "Satur",
+               0
+       };
+
+       register char **wp;
+
+       for(wp=wday; wp; wp++)
+               if(uleqn(str, *wp, 3) == 0)
+                       return(*wp);
+       return("???");
+}
diff --git a/docs/historical/mh-jun-1982/progs/rmail.c.nodate b/docs/historical/mh-jun-1982/progs/rmail.c.nodate
new file mode 100644 (file)
index 0000000..fab61c4
--- /dev/null
@@ -0,0 +1,301 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+static char *sccsid = "@(#)from rmail.c      4.1 (Berkeley) 10/1/80";
+/*
+ * rmail: front end for mail to stack up those stupid >From ... remote from ...
+ * lines and make a correct return address.  This works with the -f option
+ * to /etc/delivermail so it won't work on systems without delivermail.
+ * However, it ought to be easy to modify a standard /bin/mail to do the
+ * same thing.
+ *
+ * NOTE: Rmail is SPECIFICALLY INTENDED for ERNIE COVAX because of its
+ * physical position as a gateway between the uucp net and the arpanet.
+ * By default, other sites will probably want /bin/rmail to be a link
+ * to /bin/mail, as it was intended by BTL.  However, other than the
+ * (somewhat annoying) loss of information about when the mail was
+ * originally sent, rmail should work OK on other systems running uucp.
+ * If you don't run uucp you don't even need any rmail.
+ *
+ * This version revised around New Year's Day 1981 to interface with
+ * Rand's MH system.  The nature of the revision is to (1) do nothing
+ * if the destination is uucp-remote (note the assumption of single
+ * destination) and (2) to call "/etc/mh/deliver" to do the deed.
+ *
+ * Revised Aug 1981 to add NOGATEWAY screen.  Also fixed a few bugs.
+ * PK.
+ */
+
+
+#include "../mh.h"
+#include <whoami.h>
+#include <stdio.h>
+
+#define MATCH 0
+
+char *index();
+
+FILE *out;              /* output to delivermail */
+char *tmpfil;           /* file name of same */
+char tmpfila[24];       /* array for tmpfil */
+char *to;               /* argv[1] */
+char from[512];         /* accumulated path of sender */
+char lbuf[512];         /* one line of the message */
+
+#ifdef ARPANET
+int netaddr;            /* set if "to" contains an arpanet address */
+#endif
+
+main(argc, argv)
+char **argv;
+{
+       char ufrom[64]; /* user on remote system */
+       char sys[64];   /* a system in path */
+       char junk[512]; /* scratchpad */
+       char *cp;
+
+       to = argv[1];
+       if (argc != 2) {
+               fprintf(stderr, "Usage: rmail user\n");
+               exit(1);
+       }
+#ifdef DEBUG
+       out=stdout;
+       tmpfil = "/dev/tty";
+#else
+       tmpfil = tmpfila;
+       sprintf (tmpfil, "/tmp/%s", makename ("mail",".tmp"));
+       if ((out=fopen(tmpfil, "w")) == NULL) {
+               fprintf(stderr, "Can't create %s\n", tmpfil);
+               exit(1);
+       }
+#endif
+       for (;;) {
+               fgets(lbuf, sizeof lbuf, stdin);
+               if (strncmp(lbuf, "From ", 5) && strncmp(lbuf, ">From ", 6))
+                       break;
+               fputs(lbuf, out); /* Save--in case we are just forwarding */
+               /* sscanf(lbuf, "%s %s %s %s %s %s %s remote from %s", junk, ufrom, junk, junk, junk, junk, junk, sys); */
+               sscanf(lbuf, "%s %s", junk, ufrom);
+               cp = lbuf;
+               for (;;) {
+                       cp = index(cp+1, 'r');
+                       if (cp == NULL)
+                               cp = "remote from somewhere";
+#ifdef DEBUG
+                       printf("cp='%s'\n", cp);
+#endif
+                       if (strncmp(cp, "remote from ", 12) == MATCH)
+                               break;
+               }
+               sscanf(cp, "remote from %s", sys);
+               strcat(from, sys);
+               strcat(from, "!");
+#ifdef DEBUG
+               printf("ufrom='%s', sys='%s', from now '%s'\n", ufrom, sys, from);
+#endif
+       }
+       strcat(from, ufrom);
+
+#ifdef DEBUG
+       printf("from now '%s'\n",  from);
+#endif
+
+
+#ifdef ARPANET
+       netaddr = isarpa(to);           /* Arpanet destination?  */
+
+#ifdef NOGATEWAY
+       if(netaddr && !okhost(sys))
+       {
+               truncate();
+               returnmail("Sorry, not an Arpanet gateway!");
+               exit(0);
+       }
+#endif
+
+       if (index (to, '!') && !netaddr)  {
+#else
+       if (index (to, '!')) {
+#endif
+               /* Just forwarding! */
+               putmsg();
+               deliver(to);
+               exit(0);
+       }
+
+       truncate();
+       /* fprintf(out, "To: %s\n",to); */
+       putfrom();
+
+       if( !((cp = index(lbuf, ':')) &&  (cp - lbuf <  NAMESZ )))
+               fputs("\n",out);/* Doesn't look good; terminate hdr */
+
+       putmsg();
+       deliver(to);
+
+}
+
+
+deliver(to)
+       char *to;
+{
+       int sts,pid,waitid;
+
+#ifdef DEBUG
+       printf("%s would get called here; Delivery to: %s \n", mh_deliver,to);
+       exit(0);
+#endif
+       fclose(out);
+
+       if ((pid=fork()) == -1) {
+               fprintf(stderr, "Cannot fork Deliver!\n");
+
+#ifndef DEBUG   /* Extra precaution */
+               unlink(tmpfil);
+#endif
+               exit(1);
+       }
+       if(pid) {
+               while(((waitid = wait(&sts)) != pid) && (waitid != -1));
+
+#ifndef DEBUG   /* Extra precaution */
+               unlink(tmpfil);
+#endif
+               exit(0);
+       }
+       execl(mh_deliver, "deliver", "-deliver", to, tmpfil, 0);
+
+       perror( "Cannot exec Deliver ");
+
+       exit(1);
+
+}
+
+#ifdef ARPANET
+
+isarpa(str)                             /* Gateway to Arpanet? */
+       char *str;
+{
+       char *cp;
+
+       if (index (str, '@'))
+               return(1);
+
+       for (cp = str; ;) {
+               if((cp = index(cp, ' ')) == NULL)
+                       return(0);
+               while(*cp == ' ')
+                       cp++;
+               if ((strncmp(cp, "at ", 3) == MATCH) ||
+                   (strncmp(cp, "AT ", 3) == MATCH) ||
+                   (strncmp(cp, "At ", 3) == MATCH))
+
+                       return(1);
+       }
+}
+
+
+okhost(str)             /* Host permitted to use us as an arpanet gateway? */
+       char *str;
+{
+       register short i;
+
+       for (i=0; rhosts[i]; i++)
+               if (strcmp (str, rhosts[i]) == MATCH)
+                       return(1);
+       return(0);
+}
+
+#endif
+
+returnmail(message)
+       char  *message;
+{
+
+#ifdef DEBUG
+       printf("returnmail()\n");
+#endif
+       if(!from)  return;
+
+       putdate();
+       fprintf(out, "To: %s\n", from);
+       fputs("\n",out);
+       fputs (message, out);
+       fputs("\n\n\n*--------------RETURNED MESSAGE---------------*\n\n",
+         out);
+
+       putmsg();
+       deliver(from);
+
+}
+
+
+#include <sys/types.h>
+#include <sys/timeb.h>
+#include <time.h>
+
+putdate()
+{
+       long  now;
+       register char *t, *p;
+       char *timezone();
+       struct timeb tb;
+       struct tm *tmp;
+       static char *wday[] = {
+               "Sun",
+               "Mon",
+               "Tues",
+               "Wednes",
+               "Thurs",
+               "Fri",
+               "Satur"
+       };
+
+       now = time((long *)0);
+       t = ctime(&now);
+       ftime(&tb);
+       tmp = localtime(&now);
+       p = timezone(tb.timezone, tmp->tm_isdst);
+
+       /*                  day    13   Apr  1981 20  :38   -PST */
+       fprintf(out, "Date: %sday, %.2s %.3s %.4s %.2s:%.2s-%.3s\n",
+                    wday[tmp->tm_wday], t+8, t+4, t+20, t+11, t+14, p);
+}
+
+
+putfrom()
+{
+       if (strlen(from)) 
+#ifdef ARPANET
+               if (netaddr)
+                       fprintf(out, "From: %s at %s\n",from, HOSTNAME);
+               else
+                       fprintf(out, "From: %s\n", from);
+#else
+               fprintf(out, "From: %s\n",from);
+#endif
+
+}
+
+
+putmsg()
+{
+       fputs(lbuf, out);
+       while (fgets(lbuf, sizeof lbuf, stdin))
+               fputs(lbuf, out);
+}
+
+
+truncate()
+{
+       /* Truncate those "...remote from..." header lines. */
+       /* They're kept only if the message is to be uucp-forwarded */
+
+#ifndef DEBUG
+       fclose (out);   out=fopen(tmpfil, "w");
+#end
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/progs/rmf.c b/docs/historical/mh-jun-1982/progs/rmf.c
new file mode 100644 (file)
index 0000000..1b1d233
--- /dev/null
@@ -0,0 +1,181 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+#include <stdio.h>
+#include <strings.h>
+
+extern struct swit anoyes[];    /* Std no/yes gans array */
+
+int     subf;
+
+struct dirent {
+       short   inum;
+       char    name[14];
+       int     pad;
+};
+
+struct swit switches[] = {
+       "help",         4,      /* 0 */
+       0,              0
+};
+
+
+/*ARGSUSED*/
+main(argc, argv)
+char *argv[];
+{
+       register char *cp, **ap;
+       char *folder, buf[128];
+       int def_fold = 0;
+       char *arguments[50], **argp;
+
+       invo_name = argv[0];
+#ifdef NEWS
+       m_news();
+#endif
+       folder = 0;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       VOID copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                       /* unknown */
+                       case -1:fprintf(stderr, "rmf: -%s unknown\n", cp);
+                               goto leave;
+                                                       /* -help */
+                       case 0: help("rmf [+folder]  [switches]", switches);
+                               goto leave;
+                       }
+               if(*cp == '+')
+                       if(folder) {
+                               fprintf(stderr, "Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               folder = path(cp+1, TFOLDER);
+               else {
+                       fprintf(stderr, "Usage: rmf [+folder]\n");
+                       goto leave;
+               }
+       }
+       if(!m_find("path")) free(path("./", TFOLDER));
+       if(!folder) {
+               folder = m_getfolder();
+               def_fold++;
+       }
+       subf = !((!index(folder, '/')) | (*folder == '/') | (*folder == '.'));
+       if(def_fold && !subf) {
+               cp = concat("Remove folder \"", folder, "\" ?? ", NULLCP);
+               if(!gans(cp, anoyes))
+                       goto leave;
+               free(cp);
+       }
+       if(rmfold(folder))
+               goto leave;
+       if(subf) {                      /* make parent "current" */
+               cp = copy(folder, buf);
+               while(cp > buf && *cp != '/') --cp;
+               if(cp > buf) {
+                       *cp = 0;
+                       if(strcmp(m_find(pfolder), buf) != 0) {
+                               printf("[+%s now current]\n", buf);
+                               m_replace(pfolder, buf);
+                       }
+               }
+       }
+ leave:
+       m_update();
+       done(0);
+}
+
+struct dirent ent;
+
+rmfold(fold)
+char *fold;
+{
+       register char *maildir;
+       int i, leftover, cd;
+
+       leftover = 0;
+       if(!subf && strcmp(m_find(pfolder), fold) == 0) /* make default "current"*/
+               if(strcmp(m_find(pfolder), defalt) != 0) {
+                       printf("[+%s now current]\n", defalt);
+                       VOID fflush(stdout);                    /*??*/
+                       m_replace(pfolder, defalt);
+               }
+       maildir = m_maildir(fold);
+       if((cd = chdir(maildir)) < 0)
+               goto funnyfold;
+       if(access(".", 2) == -1) {
+ funnyfold:     if(!m_delete(concat("cur-", fold, NULLCP)))
+                       printf("[Folder %s de-referenced]\n", fold);
+               else
+                       fprintf(stderr, "You have no profile entry for the %s folder %s\n",
+                         cd < 0 ? "unreadable" : "read-only", fold);
+               return(1);
+       }
+       i = open(".", 0);
+       ent.pad = 0;
+       while(read(i, (char *)&ent.inum, sizeof ent.name + sizeof ent.inum))
+               if(ent.inum)
+                   if((ent.name[0] >= '0' && ent.name[0] <= '9') ||
+                       ent.name[0] == ',' ||
+                       (ent.name[0] == '.' && ent.name[1] && ent.name[1] != '.') ||
+                       strcmp(ent.name, "cur") == 0 ||
+                       strcmp(ent.name, "@") == 0) {
+                           if(unlink(ent.name) == -1) {
+                               fprintf(stderr, "Can't unlink %s:%s\n", fold,ent.name);
+                               leftover++;
+                           }
+                   } else if(strcmp(ent.name,".") != 0 &&
+                             strcmp(ent.name,"..") != 0) {
+                       fprintf(stderr, "File \"%s/%s\" not deleted!\n",
+                               fold, ent.name);
+                       leftover++;
+                   }
+       VOID close(i);
+       VOID chdir("..");       /* Move out of dir to be deleted */
+       if(!leftover && removedir(maildir))
+               return(0);
+       else
+               fprintf(stderr, "Folder %s not removed!\n", fold);
+       return(1);
+}
+
+
+removedir(dir)
+       char *dir;
+{
+       register int pid, wpid;
+       int status;
+
+       if((pid = fork()) == 0) {
+               m_update();
+               VOID fflush(stdout);
+               execl("/bin/rmdir", "rmdir", dir, 0);
+               execl("/usr/bin/rmdir", "rmdir", dir, 0);
+               fprintf(stderr, "Can't exec rmdir!!?\n");
+               return(0);
+       }
+       if(pid == -1) {
+               fprintf(stderr, "Can't fork\n");
+               return(0);
+       }
+       while((wpid = wait(&status)) != pid && wpid != -1) ;
+       if(status) {
+               fprintf(stderr, "Bad exit status (%o) from rmdir.\n", status);
+           /*  return(0);   */
+       }
+       retur
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/progs/rmm.c b/docs/historical/mh-jun-1982/progs/rmm.c
new file mode 100644 (file)
index 0000000..5deac2f
--- /dev/null
@@ -0,0 +1,155 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+#include <stdio.h>
+#include <strings.h>
+char *calloc();
+
+int     vecp;
+char    **vec;
+struct msgs *mp;
+
+struct swit switches[] = {
+       "all",         -3,      /* 0 */
+       "help",         4,      /* 1 */
+       0,              0
+};
+
+
+/*ARGSUSED*/
+main(argc, argv)
+char *argv[];
+{
+       char *folder, *maildir, *msgs[100], buf[32];
+       register int msgnum;
+       register char *cp, *sp;
+       int msgp;
+       char **ap;
+       char *arguments[50], **argp;
+
+       invo_name = argv[0];
+#ifdef NEWS
+       m_news();
+#endif
+       folder = 0; msgp = 0;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       VOID copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                       /* unknown */
+                       case -1:fprintf(stderr, "rmm: -%s unknown\n", cp);
+                               goto leave;
+                                                        /* -all */
+                       case 0: fprintf(stderr, "\"-all\" changed to \"all\"\n");
+                               goto leave;
+                                                       /* -help */
+                       case 1: help("rmm [+folder]  [msgs] [switches]",
+                                    switches);
+                               goto leave;
+                       }
+               if(*cp == '+')  {
+                       if(folder) {
+                               fprintf(stderr, "Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               folder = path(cp+1, TFOLDER);
+               } else
+                       msgs[msgp++] = cp;
+       }
+       if(!m_find("path")) free(path("./", TFOLDER));
+#ifdef COMMENT
+       if(!msgp)
+               msgs[msgp++] = "cur";
+#endif
+       if(!folder)
+               folder = m_getfolder();
+       maildir = m_maildir(folder);
+       if(chdir(maildir) < 0) {
+               fprintf(stderr, "Can't chdir to: ");
+               perror(maildir);
+               goto leave;
+       }
+       if(!msgp) {
+               if((msgnum = m_getcur(folder)) == 0) {
+                       fprintf(stderr, "%s: No current message.\n", folder);
+                       goto leave;
+               }
+               goto doit;
+       }
+       if(!(mp = m_gmsg(folder))) {
+               fprintf(stderr, "Can't read folder!?\n");
+               goto leave;
+       }
+       if(mp->hghmsg == 0) {
+               fprintf(stderr, "No messages in \"%s\".\n", folder);
+               goto leave;
+       }
+       for(msgnum = 0; msgnum < msgp; msgnum++)
+               if(!m_convert(msgs[msgnum]))
+                       goto leave;
+       if(mp->numsel == 0) {
+               fprintf(stderr, "rmm: lasagne 'n sausage\n");     /* never get here */
+               goto leave;
+       }
+doit:
+       m_replace(pfolder, folder);
+       if((cp = m_find("delete-prog")) == NULL) {
+               if(!msgp)
+                       goto lp1;
+               for(msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
+                       if(mp->msgstats[msgnum] & SELECTED) {
+                    lp1:       sp = getcpy(m_name(msgnum));
+                               cp = copy(sp, buf);
+                               cp[1] = 0;
+                               do
+                                       *cp = cp[-1];
+                               while(--cp >= buf && *cp != '/');
+                               *++cp = ',';            /* New backup convention */
+                               VOID unlink(buf);
+                               if(link(sp, buf) == -1 || unlink(sp) == -1)
+                                       fprintf(stderr, "Can't rename %s to %s.\n", sp, buf);
+                               if(!msgp)
+                                       goto leave;
+                       }
+       } else {
+               if(!msgp) {
+                       vec = (char **) calloc(3, sizeof *vec);
+                       vecp = 1;
+                       vec[vecp++] = getcpy(m_name(msgnum));
+                       goto lp2;
+               }
+               if(mp->numsel > MAXARGS-2) {
+  fprintf(stderr, "rmm: more than %d messages for deletion-prog\n",MAXARGS-2);
+                       goto leave;
+               }
+               vec = (char **) calloc(MAXARGS +2, sizeof *vec);
+               vecp = 1;
+               for(msgnum= mp->lowsel; msgnum<= mp->hghsel; msgnum++)
+                       if(mp->msgstats[msgnum]&SELECTED)
+                               vec[vecp++] = getcpy(m_name(msgnum));
+       lp2:    vec[vecp] = 0;
+               vec[0] = r1bindex(cp, '/');
+               m_update();
+               VOID fflush(stdout);
+               execv(cp, vec);
+               fprintf(stderr, "Can't exec deletion prog--");
+               perror(cp);
+       }
+leave:
+       m_update();
+       done(0);
+}
diff --git a/docs/historical/mh-jun-1982/progs/scan.c b/docs/historical/mh-jun-1982/progs/scan.c
new file mode 100644 (file)
index 0000000..6d4c70b
--- /dev/null
@@ -0,0 +1,150 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+#include <stdio.h>
+#include <strings.h>
+#include "scansub.h"
+
+long time();
+
+int hdrflag;
+int timeflag;
+int numflag;
+struct msgs *mp;
+
+struct swit switches[] = {
+       "all",         -3,      /* 0 */
+       "ff",           0,      /* 1 */
+       "noff",         0,      /* 2 */
+       "header",       0,      /* 3 */
+       "noheader",     0,      /* 4 */
+       "help",         4,      /* 5 */
+       "time",         0,      /* 6 */
+       "notime",       0,      /* 7 */
+       "numdate",      0,      /* 8 */
+       "nonumdate",    0,      /* 9 */
+       0,              0
+};
+
+extern  char _sobuf[];          /* MLW  standard out buffer */
+
+/*ARGSUSED*/
+main(argc, argv)
+char *argv[];
+{
+       char *folder, *maildir, *msgs[100];
+       register int msgnum;
+       register char *cp, **ap;
+       int msgp, ff;
+       FILE *in;
+       long now;
+       char *arguments[50], **argp;
+
+       invo_name = argv[0];
+#ifndef _IOLBF
+       setbuf(stdout, _sobuf);
+#endif  _IOLBF
+#ifdef NEWS
+       m_news();
+#endif
+       ff = 0; msgp = 0; folder = 0;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       VOID copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                       /* unknown */
+                       case -1:fprintf(stderr, "scan: -%s unknown\n", cp);
+                               goto leave;
+                                                        /* -all */
+                       case 0: fprintf(stderr, "\"-all\" changed to \"all\"\n");
+                               goto leave;
+                       case 1: ff = 1;  continue;      /* -ff */
+                       case 2: ff = 0;  continue;      /* -noff */
+                       case 3: hdrflag = 1;  continue; /* -header */
+                       case 4: hdrflag = 0;  continue; /* -noheader */
+                       case 6: timeflag = 1;  continue; /* -time */
+                       case 7: timeflag = 0;  continue; /* -notime */
+                       case 8: numflag = 1;  continue; /* -numdate */
+                       case 9: numflag = 0;  continue; /* -nonumdate */
+                       case 5: help("scan [+folder]  [msgs] [switches]",
+                                    switches);
+                               goto leave;
+                       }
+               if(*cp == '+') {
+                       if(folder) {
+                               fprintf(stderr, "Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               folder = path(cp+1, TFOLDER);
+               } else
+                       msgs[msgp++] = cp;
+       }
+       if(!m_find("path")) free(path("./", TFOLDER));
+       if(!folder)
+               folder = m_getfolder();
+       maildir = m_maildir(folder);
+       if(chdir(maildir) < 0) {
+               fprintf(stderr, "Can't chdir to: ");
+               perror(maildir);
+               goto leave;
+       }
+       if(!(mp = m_gmsg(folder))) {
+               fprintf(stderr, "Can't read folder!?\n");
+               goto leave;
+       }
+       if(mp->hghmsg == 0) {
+               fprintf(stderr, "No messages in \"%s\".\n", folder);
+               goto leave;
+       }
+       if(!msgp)
+               msgs[msgp++] = "first-last";
+       for(msgnum = 0; msgnum < msgp; msgnum++)
+               if(!m_convert(msgs[msgnum]))
+                       goto leave;
+       if(mp->numsel == 0) {
+               fprintf(stderr, "scan: matzo balls.\n");         /* never get here */
+               goto leave;
+       }
+       m_replace(pfolder,folder);
+       for(msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)  {
+               if(mp->msgstats[msgnum]&SELECTED) {
+                       if((in = fopen(cp = m_name(msgnum), "r")) == NULL)
+                               fprintf(stderr, "--Can't open %s\n", cp);
+                       else {
+                               if(hdrflag) {
+                                       now = time((long *)0);
+                                       cp = cdate(&now);
+                                       cp[9] = ' '; cp[15] = 0;
+printf("\
+                      Folder %-32s%s\n\n", folder, cp);
+                               }
+                               VOID scan(in, msgnum, 0,
+                                         msgnum == mp->curmsg,
+                                         (timeflag ? DOTIME : 0)
+                                         | (numflag ? NUMDATE : 0), hdrflag);
+                               hdrflag = 0;
+                               VOID fclose(in);
+                               if(stdout->_cnt < 80)
+                                       VOID fflush(stdout);
+                       }
+               }
+       }
+       if(ff)
+               putchar('\014');
+leave:
+       m_update();
+       done
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/progs/scansub.c b/docs/historical/mh-jun-1982/progs/scansub.c
new file mode 100644 (file)
index 0000000..5cb419b
--- /dev/null
@@ -0,0 +1,673 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+/* the only thing wrong with this version is that
+   the numeric date format needs to be adjusted for
+   the timezone.  See adjtime() at the end of the file.
+   -- dave yost, june, 1981
+ */
+#include "../mh.h"
+#include <whoami.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <time.h>
+#include "../adrparse.h"
+#include "scansub.h"
+
+#define Block
+
+#define _FROM    1
+#define _NOTFROM 0
+
+#define MSGN     0              /* Start of msg name field      */
+#define SMSGN    DMAXFOLDER     /* Length                       */
+#define SFLGS    2              /* Width of flag field          */
+#define SDATE    7              /* Length of Date field         */
+#define STIME    8              /* Length of time field         */
+#define SNDATE   6              /* Length of numeric date       */
+#define SNTIME   4              /* Length of numeric time       */
+#define SFROM   16              /* Length of "        "         */
+#define SLINE   79              /* size of line                 */
+#define BSUBJ   20              /* Room needed in Sub field to  */
+                               /* add stuff from the body      */
+
+FILE  *scnout;
+char scanl[512];
+int local;
+int hostseen;
+char *frmtok();
+
+scan(inb, innum, outnum, curflg, howdate, header)
+       FILE *inb;
+       int outnum;
+{
+
+       char buf[BUFSIZ], name[NAMESZ], tobuf[32], frombuf[32];
+       register char *cp, **tok1;
+       int state, subsz, first, compnum;
+       static char *myname;
+       int f_msgn;     /* Start of msg name field      */
+       int f_smsgn;    /* Length                       */
+       int f_flgs;     /* Start of flags field         */
+       int f_sflgs;    /* Width of flag field          */
+       int f_date;     /* Start of Date field          */
+       int f_sdate;    /* Length                       */
+       int f_from;     /* Start of From field          */
+       int f_sfrom;    /* Length of "        "         */
+       int f_subj;     /* Start of Subject field       */
+       int f_ssubj;    /* Size of Subject field        */
+       int f_bsubj;    /* Room needed in Sub field to  */
+                       /* add stuff from the body      */
+
+       f_msgn  = MSGN;
+       f_smsgn = SMSGN;
+       f_flgs  = f_msgn + f_smsgn;
+       f_sflgs = SFLGS;
+       f_date  = f_flgs + f_sflgs;
+
+       switch (howdate) {
+       default:
+               f_sdate = SDATE;
+               break;
+
+       case DOTIME:
+               f_sdate = SDATE + 1 + STIME;
+               break;
+
+       case NUMDATE:
+               f_sdate = SNDATE;
+               break;
+
+       case DOTIME | NUMDATE:
+               f_sdate = SNDATE + SNTIME;
+               break;
+       }
+       f_from  = f_date + f_sdate + 1;
+       f_sfrom = SFROM;
+       f_subj  = f_from + f_sfrom + 2;
+       f_ssubj = SLINE - f_subj;
+       f_bsubj = BSUBJ;
+
+       local = 0; hostseen = 0;
+       if(!myname)
+               myname = getenv("USER");
+       tobuf[0] = 0; frombuf[0] = 0;
+       first = 0;
+       state = FLD;
+       compnum = 1;
+
+       if (header)
+               printf ("  #   %-*sFrom              Subject        [<<Body]\n\n",
+                       f_from - f_date - 1,
+                       howdate == DOTIME ? "Date     Time" : "Date");
+       for(;;) {
+
+               state = m_getfld(state, name, buf, sizeof buf, inb);
+               if(!first++ && state != FILEEOF) {      /*##*/
+                   if(outnum) {
+                       cp = m_name(outnum);
+                       if(*cp == '?')       /* msg num out of range */
+                               return(-2);
+                       if((scnout = fopen(cp, "w")) == NULL) {
+                               fprintf(stderr, "Error creating msg ");
+                               perror(cp); done(-1);
+                       }
+                       VOID chmod(cp, m_gmprot());
+                   }
+                   sfill(scanl, sizeof scanl);
+                   scanl[sizeof scanl - 1] = 0;
+                   subsz = 0;
+                   tobuf[0] = 0;
+               }
+
+               switch(state) {
+
+               case FLD:
+               case FLDEOF:
+               case FLDPLUS:
+                       compnum++;
+                       if(uleq(name, "from"))
+                           frombuf[cpyfrm(buf,frombuf,sizeof frombuf,_FROM)]
+                               = 0;
+                       else if(uleq(name, "date"))
+                               cpydat(buf, &scanl[f_date], f_sdate, howdate);
+                       else if(uleq(name, "subject") && scanl[f_subj] == ' ')
+                               subsz = cpy(buf, &scanl[f_subj], f_ssubj);
+                       else if(uleq(name, "to") && !tobuf[0])
+                               tobuf[
+                                  cpyfrm(buf,tobuf,sizeof tobuf-1,_NOTFROM)]=0;
+                       else if(uleq(name, "replied"))
+                               VOID cpy("-", &scanl[f_flgs+1], 1);
+                       put(name, buf, scnout);
+                       while(state == FLDPLUS) {
+                               state=m_getfld(state,name,buf,sizeof buf,inb);
+                               if(scnout)
+                                       fputs(buf, scnout);
+                       }
+                       if(state == FLDEOF)
+                               goto putscan;
+                       continue;
+
+               case BODY:
+               case BODYEOF:
+                       compnum = -1;
+                       if(buf[0] && subsz < f_ssubj - f_bsubj) {
+                               int bodsz;
+                               scanl[f_subj+subsz+1] = '<';
+                               scanl[f_subj+subsz+2] = '<';
+                               bodsz= cpy(buf, scanl+f_subj+subsz+3,
+                                 f_ssubj-subsz-3);
+                               if(bodsz < f_ssubj - subsz - 3)
+                                       scanl[f_subj+subsz+3 + bodsz] = '>';
+                               if(bodsz < f_ssubj - subsz - 4)
+                                       scanl[f_subj+subsz+4 + bodsz] = '>';
+                               subsz = f_ssubj;
+                       }
+                       if(buf[0] && scnout) {
+                               putc('\n', scnout);
+                               fputs(buf, scnout);
+                               if(ferror(scnout)) {
+                                       fprintf(stderr, "Write error on ");
+                                       perror(m_name(outnum));done(-1);
+                               }
+                       }
+       body:
+                       if (!scnout)
+                               state = FILEEOF; /* stop now if scan cmd */
+                       else while(state == BODY) { /*else inc, so copy body*/
+                               state=m_getfld(state,name,buf,sizeof buf,inb);
+                               if(state != FILEEOF)
+                                       fputs(buf, scnout);
+                       }
+                       if(state == BODYEOF || state == FILEEOF) {
+                 putscan:      cpymsgn(m_name(innum), &scanl[f_msgn], f_smsgn);
+                               tok1= brkstring(getcpy(frombuf), " ", "\n");
+                               if(!frombuf[0] || uleq(frombuf, myname) ||
+                                 (local && uleq(*tok1, myname))) {
+                                       VOID cpy("To:", &scanl[f_from], 3);
+                                       VOID cpy(tobuf, &scanl[f_from+3], f_sfrom-3);
+                               } else
+                                       VOID cpy(frombuf, &scanl[f_from], f_sfrom);
+                               if(curflg)
+                                       VOID cpy("+", &scanl[f_flgs], f_sflgs);
+                               trim(scanl);
+                               fputs(scanl, stdout);
+
+                               if(scnout) {
+                                       VOID fflush(scnout);
+                                       if(ferror(scnout)) {
+                                               perror("Write error on ");
+                                               perror(m_name(outnum));
+                                               done(-1);
+                                       }
+                                       VOID fclose(scnout);
+                                       scnout = NULL;
+                               }
+                               return(1);
+                       }
+                       break;
+
+               case LENERR:
+               case FMTERR:
+                       fprintf(stderr, "??Message Format Error ");
+                       fprintf(stderr, "(Message %d) ", outnum ? outnum :innum);/*##*/
+                       if(compnum < 0) fprintf(stderr, "in the Body.\n");
+                       else fprintf(stderr, "in Component #%d.\n", compnum);
+                       fprintf(stderr, "-----------------------------------------");
+                       fprintf(stderr, "-------------------------------------\n");
+                       goto badret;
+               default:
+                       fprintf(stderr, "Getfld returned %d\n", state);
+
+
+       badret:         if(outnum) {
+                               fputs("\n\nBAD MSG:\n", scnout);
+                               if(compnum < 0)
+                                       fputs(buf, scnout);
+                               else {
+                                       fputs(name, scnout);
+                                       putc('\n', scnout);
+                               }
+                       /***    ungetc(inb);    ***/
+                               state = BODY;
+                               goto  body;
+
+                       }
+                       if(scnout)
+                               VOID fflush(scnout);
+                       return(-1);
+               case FILEEOF:
+                       return(0);
+
+               }
+
+       }
+}
+
+
+trim(str)
+char *str;
+{
+       register char *cp;
+
+       cp = str;
+       while(*cp) cp++;
+       while(*--cp == ' ') ;
+       cp++;
+       *cp++ = '\n';
+       *cp++ = 0;
+}
+
+sfill(str, cnt)
+char *str;
+{
+       register char *cp;
+       register int i;
+
+       cp = str;  i = cnt;
+       do
+               *cp++ = ' ';
+       while(--i);
+}
+
+
+put(name, buf, ip)
+       char *name, *buf;
+       register FILE *ip;
+{
+       if(ip) {
+               fputs(name, ip);
+               putc(':', ip);
+               fputs(buf, ip);
+               if(ferror(ip)) { perror("Write error");done(-1);}
+       }
+}
+
+
+cpy(from, to, cnt)
+       register char *from, *to;
+       register int cnt;
+{
+       register int c;
+       char *savto;
+
+       savto = to;
+       while(*from == ' ' || *from == '\t' || *from == '\n' || *from == '\f')
+               from++;
+       while(cnt--)
+               if(c = *from) {
+                       if(c == '\t' || c == ' ' || c == '\n' || c == '\f') {
+                               *to++ = ' ';
+                               do 
+                                       from++;
+                               while((c= *from)==' '||c=='\t'||c=='\n'||c=='\f');
+                               continue;
+                       } else {
+                               *to++ = c;
+                               from++;
+                       }
+               } else
+                       break;
+       return(to - savto);   /*Includes 1 char trailing white space, if any*/
+}
+
+struct tm *localtime();
+long time();
+char *findmonth();
+
+struct date {
+       char *day;
+       char *month;
+       char *year;
+       char *timestr;
+       char *zone;
+       char zoneadd;
+ };
+
+cpydat(sfrom, sto, cnt, how)
+       char *sfrom, *sto;
+{
+       register char *cp;
+       register char *to;
+       static struct tm *locvec;
+       char frombuf[100];
+       char buf[30];           /* should be char buf[cnt + 1] */
+       long now;
+       struct date dt;
+
+       strncpy(frombuf, sfrom, sizeof frombuf);
+       frombuf[sizeof frombuf -1] = '\0';
+       if(!locvec) {
+               now = time((long *)0);
+               locvec = localtime(&now);
+       }
+
+       /* Collect the various fields of the date */
+       for(cp = frombuf; *cp < '0' || *cp > '9'; cp++)
+               if(!*cp)
+                       return;
+
+       /* get the day */
+       dt.day = cp;
+       while (isdigit(*cp))
+               cp++;
+       if (*cp)
+               *cp++ = '\0';
+
+       /* get the month */
+       while (*cp && !isalpha(*cp))
+               cp++;
+       dt.month = cp;
+       while (isalpha (*cp))
+               cp++;
+       if (*cp)
+               *cp++ = '\0';
+
+       /* get the year */
+       while (*cp && !isdigit(*cp))
+               cp++;
+       dt.year = cp;
+       while (isdigit(*cp))
+               cp++;
+       if (*cp)
+               *cp++ = '\0';
+
+       /* Point timestr at the time, and remove colons, if present */
+       while (*cp && !isdigit(*cp))
+               cp++;
+       dt.timestr = to = cp;
+       for (; isdigit(*cp) || *cp == ':'; cp++)
+               if (*cp != ':')
+                       *to++ = *cp;
+       if (*cp)
+               cp++;
+       *to = '\0';
+
+       /* get the time zone. */
+       /* Can be alphas as in PST */
+       /* If plus/minus digits, then set zoneadd to the + or - */
+       /* point zone at the string of digits or alphas */
+       dt.zoneadd = '\0';
+       while (*cp && !isalpha(*cp) && !isdigit(*cp)) {
+               if (*cp == '+' || *cp == '-')
+                       dt.zoneadd = *cp;
+               cp++;
+       }
+       dt.zone = cp;
+       if (isdigit(*cp))
+               while (isdigit (*cp))
+                       cp++;
+       else {
+               dt.zoneadd = '\0';
+               while (isalpha (*cp))
+                       cp++;
+       }
+       if (*cp)
+               *cp++ = '\0';
+
+ /*     printf ("Yr='%s' Mo='%s' Day='%s' Time='%s' Zone='%s'\n",
+               dt.year, dt.month, dt.day, dt.timestr, dt.zone);
+       if(cp = findmonth(dt.month))
+               printf ("month='%s'\n", cp);
+       return;
+ /**/
+       to = buf;
+       if(cp = findmonth(dt.month)) {
+               if (how & NUMDATE) {
+                       adjtime(&dt);
+                       if(strlen(dt.year) >= 2) {
+                               cp = &dt.year[strlen(dt.year) - 2];
+                               *to++ = *cp++;
+                               *to++ = *cp++;
+                       }
+                       else {
+                               *to++ = ' ';
+                               *to++ = ' ';
+                       }
+                       if ((cp = findmonth(dt.month))[1])
+                               *to++ = *cp++;
+                       else
+                               *to++ = '0';
+                       *to++ = *cp++;
+                       if (*(cp = dt.day)) {
+                               if (cp[1])
+                                       *to++ = *cp++;
+                               else
+                                       *to++ = '0';
+                               *to++ = *cp++;
+                       }
+                       else {
+                               *to++ = ' ';
+                               *to++ = ' ';
+                       }
+                       *to = '\0';
+                       if (how & DOTIME) {
+                               /* kludge for now */
+                               dt.timestr[4] = '\0';
+                               strcpy (to, dt.timestr);
+                       }
+               }
+               else {
+                       if(!cp[1])
+                               *to++ = ' ';
+                       while(*cp)
+                               *to++ = *cp++;
+                       *to++ = '/';
+
+                       cp = dt.day;
+                       if(!cp[1])
+                               *to++ = ' ';
+                       while(*cp >= '0' && *cp <= '9')
+                               *to++ = *cp++;
+                       Block {
+                               register int yr;
+                               if(   (   (yr = atoi(dt.year)) > 1970
+                                      && yr - 1900 < locvec->tm_year
+                                     )
+                                  || yr < locvec->tm_year
+                                 )  {
+                                       *to++ = '/';
+                                       *to++ = (yr - (yr < 100 ? 70 : 1970))
+                                               % 10 + '0';
+                               }
+                               else {
+                                       *to++ = ' ';
+                                       *to++ = ' ';
+                               }
+                       }
+                       *to = '\0';
+                       if (how & DOTIME) {
+                               *to++ = ' ';
+                               sprintf (to, "%4.4s", dt.timestr);
+                               to += 4;
+                               if (*dt.zone) {
+                                       *to++ = '-';
+                                       strncpy(to, dt.zone, 3);
+                               }
+                       }
+               }
+       }
+       else {
+               cp = dt.day;
+               if(!cp[1])
+                       *to++ = ' ';
+               while(*cp)
+                       *to++ = *cp++;
+       }
+       Block {
+               register int tmp;
+               if (cnt < (tmp = strlen(buf)))
+                       tmp = cnt;
+               strncpy(sto, buf, tmp);
+       }
+       return;
+}
+
+
+char    *fromp, fromdlm, pfromdlm;
+
+cpyfrm(sfrom, sto, cnt, fromcall)
+char *sfrom, *sto;
+{
+       register char *to, *cp;
+       register int c;
+
+       fromdlm = ' ';
+       fromp = sfrom; to = sto;
+       cp = frmtok();
+       do
+               if(c = *cp++)
+                       *to++ = c;
+               else
+                       break;
+       while(--cnt);
+       for(;;) {
+               if(cnt < 3) break;
+               if(*(cp = frmtok()) == 0) break;
+               if(*cp == '@' || uleq(cp, "at")) {
+                       cp = frmtok();
+                       if(uleq(cp, HOSTNAME)) {
+                               /* if the first "From:" host is local */
+                               if(fromcall != _NOTFROM && !hostseen++)
+                                       local++;
+                       } else {
+                               *to++ = '@';
+                               cnt--;
+                               do
+                                       if(c = *cp++)
+                                               *to++ = c;
+                                       else
+                                               break;
+                               while(--cnt);
+                       }
+               } else if(cnt > 4) {
+                       cnt--; *to++ = pfromdlm;
+                       do
+                               if(c = *cp++)
+                                       *to++ = c;
+                               else
+                                       break;
+                       while(--cnt);
+               }
+       }
+       if(fromcall != _NOTFROM)
+               hostseen++;
+       return(to - sto);
+}
+
+
+char *frmtok()
+{
+       static char tokbuf[64];
+       register char *cp;
+       register int c;
+
+       pfromdlm = fromdlm;
+       cp = tokbuf; *cp = 0;
+       while(c = *fromp++) {
+               if(c == '\t')
+                       c = ' ';
+               if(c == ' ' && cp == tokbuf)
+                       continue;
+               if(c == ' ' || c == '\n' || c == ',')
+                       break;
+               *cp++ = c;
+               *cp = 0;
+               if(c == '@' || *fromp == '@' || cp == &tokbuf[63])
+                       break;
+       }
+       fromdlm = c;
+       return(tokbuf);
+}
+
+
+/*      num specific!         */
+
+/* copy msgnam to addr, right justified */
+cpymsgn(msgnam, addr, len)
+char *msgnam, *addr;
+{
+       register char *cp, *sp;
+
+       sp = msgnam;
+       cp = &addr[len - strlen(sp)];
+       if (cp < addr)
+               cp = addr;
+       while(*sp)
+               *cp++ = *sp++;
+}
+
+char *monthtab[] = {
+       "jan", "feb", "mar", "apr", "may", "jun",
+       "jul", "aug", "sep", "oct", "nov", "dec",
+};
+
+char *findmonth(str)
+char *str;
+{
+       register char *cp, *sp;
+       register int i;
+       static char buf[4];
+
+       for(cp=str, sp=buf; (*sp++ = *cp++) && sp < &buf[3] && *cp != ' '; )
+               continue;
+       *sp = 0;
+       for(i = 0; i < 12; i++)
+               if(uleq(buf, monthtab[i])) {
+                       VOID sprintf(buf, "%d", i+1);
+                       return buf;
+               }
+       return(0);
+}
+
+struct tzone {
+       char *z_nam;
+       int z_hour;
+       int z_min;
+};
+struct tzone zonetab[] = {
+     {  "GMT",   0,       0,    },
+     {  "NST",  -3,     -30,    },
+     {  "AST",  -4,       0,    },
+     {  "ADT",  -3,       0,    },
+     {  "EST",  -5,       0,    },
+     {  "EDT",  -4,       0,    },
+     {  "CST",  -6,       0,    },
+     {  "CDT",  -5,       0,    },
+     {  "MST",  -7,       0,    },
+     {  "MDT",  -6,       0,    },
+     {  "PST",  -8,       0,    },
+     {  "PDT",  -7,       0,    },
+     {  "YST",  -9,       0,    },
+     {  "YDT",  -8,       0,    },
+     {  "HST", -10,       0,    },
+     {  "HDT",  -9,       0,    },
+     {  "BST", -11,       0,    },
+     {  "BDT", -10,       0,    },
+     {  "Z",     0,       0,    },
+     {  "A",    -1,       0,    },
+     {  "M",   -12,       0,    },
+     {  "N",     1,       0,    },
+     {  "Y",    12,       0,    },
+     {  0                       }
+ };
+
+/* adjust for timezone */
+adjtime(dt)
+       register struct date *dt;
+{
+       /* what we should do here is adjust all other timezones to our own */
+       return;
+
+ /*     if (isdigit (dt->zone[0])) {
+               atoi ...
+               if (dt->zoneadd == '+')
+                       ;
+       }
+       else {
+       }
+       return;
diff --git a/docs/historical/mh-jun-1982/progs/scansub.h b/docs/historical/mh-jun-1982/progs/scansub.h
new file mode 100644 (file)
index 0000000..0703ef5
--- /dev/null
@@ -0,0 +1,5 @@
+
+#define DOTIME  1       /* show the time with the date */
+#define NUMDATE 2       /* do entire date like yymmdd */
+                       /* or yymmddhhmm if DOTIME set */
+                       /* not implemented yet */
diff --git a/docs/historical/mh-jun-1982/progs/send.c b/docs/historical/mh-jun-1982/progs/send.c
new file mode 100644 (file)
index 0000000..015c715
--- /dev/null
@@ -0,0 +1,145 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+#include <stdio.h>
+#include <sys/types.h>
+#include <stat.h>
+#include <strings.h>
+#include <signal.h>
+
+extern struct swit anoyes[];    /* Std no/yes gans array */
+
+char   *vec[20];
+int     vecp = 1;
+
+struct swit switches[] = {
+       "debug",         -5,      /* 0 */
+       "draft",          0,      /* 1 */
+       "format",         0,      /* 2 */
+       "noformat",       0,      /* 3 */
+       "msgid",          0,      /* 4 */
+       "nomsgid",        0,      /* 5 */
+       "verbose",        0,      /* 6 */
+       "noverbose",      0,      /* 7 */
+       "help",           4,      /* 8 */
+       0,                0
+};
+
+int     debug;
+
+
+/*ARGSUSED*/
+main(argc, argv)
+char *argv[];
+{
+       register char *drft, *cp;
+       register int i;
+       int status, pid;
+       struct stat stbuf;
+       char **ap;
+       char *arguments[50], **argp;
+
+       invo_name = argv[0];
+#ifdef NEWS
+       m_news();
+#endif
+       drft = 0;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                            /* unknown */
+                       case -1:fprintf(stderr, "send: -%s unknown\n", cp);
+                               goto leave;
+                                                            /* -draft */
+                       case 1: vec[vecp++] = drft = m_maildir(draft);
+                               continue;
+                       case 0: debug++;
+                       case 2: case 3: case 4:
+                       case 5: case 6: case 7:
+                               vec[vecp++] = --cp;
+                               continue;
+                       case 8: help("send [file]   [switches]",
+                                    switches);
+                               goto leave;
+                       }
+               if(drft) {
+                       fprintf(stderr, "Send: Only one message at a time.\n");
+                       done(1);
+               }
+               vec[vecp++] = drft = cp;
+       }
+       if(!drft) {
+               drft = m_maildir(draft);
+               if(stat(drft, &stbuf) == -1) {
+                       fprintf(stderr, "Draft file: %s doesn't exist.\n", drft);
+                       done(1);
+               }
+               cp = concat("Use \"", drft, "\"? ", 0);
+               if(!gans(cp, anoyes))
+                       done(0);
+               vec[vecp++] = drft;
+       } else {
+               if(stat(drft, &stbuf) == -1) {
+                       fprintf(stderr, "Draft file: %s doesn't exist.\n", drft);
+                       done(1);
+               }
+       }
+       m_update();
+       vec[vecp] = 0;
+       vec[0] = r1bindex(mh_deliver, '/');
+
+       while((pid = fork()) == -1) {
+               fprintf(stderr, "Waiting for a fork\n");
+               sleep(2);
+       }
+       if(pid == 0) {
+               execv(mh_deliver, vec);
+               perror(mh_deliver);
+               done(1);
+       }
+       signal(SIGINT, SIG_IGN);
+       signal(SIGQUIT, SIG_IGN);
+       while((i = wait(&status)) != -1 && i != pid) ;
+       if(status == 0 && !debug)
+               backup(drft);
+
+leave:  ;
+/***    m_update();     ***/
+}
+
+
+backup(file)
+char *file;
+{
+       char buf[128];
+       register char *cp;
+
+       buf[0] = 0;
+       if(cp = rindex(file, '/'))
+               sprintf(buf, "%.*s", (++cp)-file, file);
+       else
+               cp = file;
+       strcat(buf, ",");
+       strcat(buf, cp);
+       unlink(buf);
+       if(link(file, buf) < 0 || unlink(file) < 0) {
+               fprintf(stderr, "Send: Backup rename failure ");
+               perror(buf);
+               done(1);
+       }
+}
diff --git a/docs/historical/mh-jun-1982/progs/show.c b/docs/historical/mh-jun-1982/progs/show.c
new file mode 100644 (file)
index 0000000..1caa14b
--- /dev/null
@@ -0,0 +1,178 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+#include <stdio.h>
+#include <strings.h>
+
+int vecp;
+int     header = 1;
+char *vec[MAXARGS];
+struct msgs *mp;
+/*  The minimum match numbers below are all at least 2 as
+/*  a kludge to avoid conflict between switches intended for
+/*  "show" and those that it passes on to pr, mhl, c, ...
+/**/
+struct swit switches[] = {
+       "all",         -3,      /* 0 */
+       "draft",        2,      /* 1 */
+       "header",       2,      /* 2 */
+       "noheader",     2,      /* 3 */
+       "format",       2,      /* 4 */
+       "noformat",     2,      /* 5 */
+       "pr",           2,      /* 6 */
+       "nopr",         2,      /* 7 */
+       "help",         4,      /* 8 */
+       0,              0
+};
+
+extern  char _sobuf[];          /* MLW  standard out buffer */
+
+/*ARGSUSED*/
+main(argc, argv)
+char *argv[];
+{
+       char *folder, *maildir, *msgs[100];
+       register int msgnum;
+       register char *cp, **ap;
+       int msgp, drft, pr, format;
+       char *arguments[50], **argp;
+
+       invo_name = argv[0];
+       setbuf(stdout, _sobuf);
+#ifdef NEWS
+       m_news();
+#endif
+       folder = (char *) 0;
+       pr = msgp = 0;
+       format = 1;
+       vecp = 1;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       VOID copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                            /* unknown */
+                       case -1:vec[vecp++] = --cp;  continue;
+                                                            /* -all   */
+                       case 0: fprintf(stderr, "\"-all\" changed to \"all\"\n");
+                               goto leave;
+                       case 1: drft = 1;  continue;         /* -draft */
+                       case 2: header = 1; continue;        /* -header */
+                       case 3: header = 0; continue;        /* -noheader */
+                       case 4: format = 1;  continue;       /* -format */
+                       case 5: format = 0;  continue;       /* -noformat */
+                       case 6: pr = 1;  continue;           /* -pr    */
+                       case 7: pr = 0;  vecp = 1;  continue;/* -nopr  */
+                       case 8:                              /* -help  */
+  help("show [+folder]  [msgs] [switches] [switches for \"type\" or \"pr\" ]",
+                                    switches);
+                               goto leave;
+                       }
+               if(*cp == '+') {
+                       if(folder) {
+                               fprintf(stderr, "Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               folder = path(cp+1, TFOLDER);
+               } else
+                       msgs[msgp++] = cp;
+       }
+       if(!m_find("path")) free(path("./", TFOLDER));
+       if(drft)
+               maildir = m_maildir("");
+       else {
+               if(!msgp)
+                       msgs[msgp++] = "cur";
+               if(!folder)
+                       folder = m_getfolder();
+               maildir = m_maildir(folder);
+       }
+       if(chdir(maildir) < 0) {
+               fprintf(stderr, "Can't chdir to: ");
+               perror(maildir);
+               goto leave;
+       }
+       if(drft) {
+               vec[vecp++] = draft;
+               goto doit;
+       }
+       if(!(mp = m_gmsg(folder))) {
+               fprintf(stderr, "Can't read folder!?\n");
+               goto leave;
+       }
+       if(mp->hghmsg == 0) {
+               fprintf(stderr, "No messages in \"%s\".\n", folder);
+               goto leave;
+       }
+       if(msgp)
+               for(msgnum = 0; msgnum < msgp; msgnum++)
+                       if(!m_convert(msgs[msgnum]))
+                               goto leave;
+       if(mp->numsel == 0) {
+               fprintf(stderr, "show: potato pancakes.\n");     /* never get here */
+               goto leave;
+       }
+       if(mp->numsel > MAXARGS-2) {
+  fprintf(stderr, "show: more than %d messages for show-exec\n", MAXARGS-2);
+               goto leave;
+       }
+       for(msgnum= mp->lowsel; msgnum<= mp->hghsel; msgnum++)
+               if(mp->msgstats[msgnum]&SELECTED)
+                       vec[vecp++] = getcpy(m_name(msgnum));
+       m_replace(pfolder, folder);
+       if(mp->hghsel != mp->curmsg)
+               m_setcur(mp->hghsel);
+       if(vecp == 2 && header) {
+               printf("(Message %s:%s)\n", folder, vec[1]);
+       }
+doit:
+       VOID fflush(stdout);
+       vec[vecp] = 0;
+       {
+               register char *proc;
+               if(pr)
+                       proc = prproc;
+               else if(format) {
+                       extern char *r1bindex();
+                       putenv("mhfolder", folder);
+                       if (!strcmp (r1bindex(showproc, '/'), "mhl")) {
+                               mhl(vecp, vec);
+                               m_update();
+                               done(0);
+                       }
+                       proc = showproc;
+               } else {
+                       proc = "/bin/cat";
+                       /* THIS IS INEFFICIENT */
+                       /* what we really should do in this case is
+                       /* copy it out ourself to save the extra exec */
+               }
+               m_update();
+               vec[0] = r1bindex(proc, '/');
+               execv(proc, vec);
+               perror(proc);
+       }
+       done(0);
+ leave:
+       m_update();
+       done(0);
+}
+
+#define switches mhlswitches
+#define INCLUDED_BY_SHOW
+#define main(a,b) mhl(a,b)
+
+#include 
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/strings/Makefile b/docs/historical/mh-jun-1982/strings/Makefile
new file mode 100644 (file)
index 0000000..2c119e2
--- /dev/null
@@ -0,0 +1,94 @@
+#
+#       Proprietary Rand Corporation, 1981.
+#       Further distribution of this software
+#       subject to the terms of the Rand
+#       license agreement.
+#
+
+LIB = strings.a
+OFILES =\
+       anoyes.o \
+       components.o \
+       current.o \
+       defalt.o \
+       distcomps.o \
+       draft.o \
+       fileproc.o \
+       foldprot.o \
+       installproc.o \
+       listname.o \
+       lockdir.o \
+       lproc.o \
+       lsproc.o \
+       mailboxes.o \
+       mailproc.o \
+       mh_deliver.o \
+       mh_prof.o \
+       mhlformat.o \
+       mhlstdfmt.o \
+       mhnews.o \
+       msgprot.o \
+       pfolder.o \
+       prproc.o \
+       rhosts.o \
+       scanproc.o \
+       sendproc.o \
+       showproc.o \
+       stdcomps.o \
+       stddcomps.o \
+       sysed.o \
+       sysname.o
+
+CFILES =   anoyes.c \
+          components.c \
+          current.c \
+          defalt.c \
+          distcomps.c \
+          draft.c \
+          fileproc.c \
+          foldprot.c \
+          installproc.c \
+          listname.c \
+          lockdir.c \
+          lproc.c \
+          lsproc.c \
+          mailboxes.c \
+          mailproc.c \
+          mh_deliver.c \
+          mh_prof.c \
+          mhlformat.c \
+          mhlstdfmt.c \
+          mhnews.c \
+          msgprot.c \
+          pfolder.c \
+          prproc.c \
+          rhosts.c \
+          scanproc.c \
+          sendproc.c \
+          showproc.c \
+          stdcomps.c \
+          stddcomps.c \
+          sysed.c \
+          sysname.c
+
+$(LIB): $(OFILES)
+       -rm -f $(LIB)
+       ar cr $(LIB) $(OFILES)
+       ranlib $(LIB)
+
+distribution:   clean
+       -rm -f $(LIB)
+
+clean:
+       -rm -f $(OFILES)
+
+depend:
+       ../misc/depend.sh $(CFILES)
+
+
+###DEPENDENCIES Follow.  Do not delete this line
+anoyes.o:       ../mh.h
+#lockdir.o:       /usr/include/mailsys.h
+#mailboxes.o:     /usr/include/mailsys.h
+rhosts.o:       ../mh.h
+#sysname.o:      /usr/include/whoami.h
diff --git a/docs/historical/mh-jun-1982/strings/anoyes.c b/docs/historical/mh-jun-1982/strings/anoyes.c
new file mode 100644 (file)
index 0000000..fdcf6a4
--- /dev/null
@@ -0,0 +1,14 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+
+struct swit anoyes[] = {
+       "no",   0,
+       "yes",  0,
+       0,
+};
diff --git a/docs/historical/mh-jun-1982/strings/components.c b/docs/historical/mh-jun-1982/strings/components.c
new file mode 100644 (file)
index 0000000..019790a
--- /dev/null
@@ -0,0 +1,8 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+char    *components =   "components";
diff --git a/docs/historical/mh-jun-1982/strings/current.c b/docs/historical/mh-jun-1982/strings/current.c
new file mode 100644 (file)
index 0000000..6c45f32
--- /dev/null
@@ -0,0 +1,8 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+char    *current =      "cur";
diff --git a/docs/historical/mh-jun-1982/strings/defalt.c b/docs/historical/mh-jun-1982/strings/defalt.c
new file mode 100644 (file)
index 0000000..48d26a1
--- /dev/null
@@ -0,0 +1,8 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+char    *defalt =       "inbox";
diff --git a/docs/historical/mh-jun-1982/strings/distcomps.c b/docs/historical/mh-jun-1982/strings/distcomps.c
new file mode 100644 (file)
index 0000000..381bcd2
--- /dev/null
@@ -0,0 +1,8 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+char    *distcomps =    "distcomps";
diff --git a/docs/historical/mh-jun-1982/strings/draft.c b/docs/historical/mh-jun-1982/strings/draft.c
new file mode 100644 (file)
index 0000000..a947bbc
--- /dev/null
@@ -0,0 +1,8 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+char    *draft =        "draft";
diff --git a/docs/historical/mh-jun-1982/strings/fileproc.c b/docs/historical/mh-jun-1982/strings/fileproc.c
new file mode 100644 (file)
index 0000000..1570f97
--- /dev/null
@@ -0,0 +1,13 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+/*
+ * This program is usually called directly by users, but it is
+ * also invoked by the deliver program to process an "fcc".
+ */
+
+char    *fileproc =     "/usr/local/file";
diff --git a/docs/historical/mh-jun-1982/strings/foldprot.c b/docs/historical/mh-jun-1982/strings/foldprot.c
new file mode 100644 (file)
index 0000000..99b6c0f
--- /dev/null
@@ -0,0 +1,12 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+/*
+ * Folders (directories) are created with this protection (mode)
+ */
+
+char    *foldprot =     "0751";
diff --git a/docs/historical/mh-jun-1982/strings/installproc.c b/docs/historical/mh-jun-1982/strings/installproc.c
new file mode 100644 (file)
index 0000000..1af8f3f
--- /dev/null
@@ -0,0 +1,13 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+/*
+ * When a user runs an MH program for the first time, this program
+ * is called to create his MH profile, and mail directory.
+ */
+
+char    *installproc =  "/etc/mh/install-mh";
diff --git a/docs/historical/mh-jun-1982/strings/listname.c b/docs/historical/mh-jun-1982/strings/listname.c
new file mode 100644 (file)
index 0000000..066e3e3
--- /dev/null
@@ -0,0 +1,8 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+char    *listname =     "select";
diff --git a/docs/historical/mh-jun-1982/strings/lockdir.c b/docs/historical/mh-jun-1982/strings/lockdir.c
new file mode 100644 (file)
index 0000000..9242dff
--- /dev/null
@@ -0,0 +1,24 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+/*
+ * This is where the lock files are kept.  It MUST be on the same
+ * file system as the "mailboxes" directory.  It also must be read/
+ * write by the world.  When a mailbox needs locking (while being
+ * read and cleared by inc, or written by deliver), a link to the
+ * mailbox is made in this directory, under the same name (i.e., the
+ * users name).  Links are one of the few things even a privileged
+ * process (deliver) cannot over-ride.  The deliver process waits
+ * for lockwait seconds for the lock to clear, then it over-rides
+ * the lock.  This number should be set around 15-30 seconds in the
+ * case of a VERY loaded system.
+ */
+
+#include <mailsys.h>
+
+char    *lockdir =      MAILLOCKDIR;
+short   lockwait =      15;                     /* Sec
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/strings/lproc.c b/docs/historical/mh-jun-1982/strings/lproc.c
new file mode 100644 (file)
index 0000000..1b05f91
--- /dev/null
@@ -0,0 +1,14 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+/*
+ * This is the program invoked by a "list" response to "What now?"
+ *  whereas, showproc is the program invoked by show, next, prev,
+ *  "pick -show".
+ */
+
+char    *lproc =        "/usr/ucb/more";
diff --git a/docs/historical/mh-jun-1982/strings/lsproc.c b/docs/historical/mh-jun-1982/strings/lsproc.c
new file mode 100644 (file)
index 0000000..44e9d40
--- /dev/null
@@ -0,0 +1,16 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+/*
+ * This is standard ls, but "folder -all -short" calls it with
+ * a -x switch meaning "list only directories".
+ *
+ * Also, its nice to have columnated output rather than a simple
+ * list... (personal prejudice).
+ */
+
+char    *lsproc =       "/usr/ucb/ls";
diff --git a/docs/historical/mh-jun-1982/strings/mailboxes.c b/docs/historical/mh-jun-1982/strings/mailboxes.c
new file mode 100644 (file)
index 0000000..cecec66
--- /dev/null
@@ -0,0 +1,16 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+/*
+ * This is where the user mailboxes are kept.  On our 11/70 they were
+ * kept in each users $HOME directory.  This is where the VAX login
+ * program is looking for them, as well as the old BELL mail.
+ */
+
+#include <mailsys.h>
+
+char    *mailboxes =      MAILDROP;
diff --git a/docs/historical/mh-jun-1982/strings/mailproc.c b/docs/historical/mh-jun-1982/strings/mailproc.c
new file mode 100644 (file)
index 0000000..ede94cb
--- /dev/null
@@ -0,0 +1,13 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+/*
+ * This is the path for the Bell equivalent mail program... Used
+ *  by "news -send" to send news items to the news user.
+ */
+
+char    *mailproc =     "/usr/ucb/mail";
diff --git a/docs/historical/mh-jun-1982/strings/mh_deliver.c b/docs/historical/mh-jun-1982/strings/mh_deliver.c
new file mode 100644 (file)
index 0000000..1328aed
--- /dev/null
@@ -0,0 +1,14 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+/*
+ * This is the delivery program called ONLY through send to
+ * actually deliver mail to users.  It is fairly small, and
+ * must run SUID ROOT, to create new mailboxes.
+ */
+
+char    *mh_deliver = "/etc/mh/deliver";
diff --git a/docs/historical/mh-jun-1982/strings/mh_prof.c b/docs/historical/mh-jun-1982/strings/mh_prof.c
new file mode 100644 (file)
index 0000000..959d5db
--- /dev/null
@@ -0,0 +1,8 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+char    *mh_prof =      "/.mh_profile";
diff --git a/docs/historical/mh-jun-1982/strings/mhlformat.c b/docs/historical/mh-jun-1982/strings/mhlformat.c
new file mode 100644 (file)
index 0000000..23238ca
--- /dev/null
@@ -0,0 +1,8 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+char    *mhlformat  =   "mhl.format";
diff --git a/docs/historical/mh-jun-1982/strings/mhlstdfmt.c b/docs/historical/mh-jun-1982/strings/mhlstdfmt.c
new file mode 100644 (file)
index 0000000..da501be
--- /dev/null
@@ -0,0 +1,8 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+char    *mhlstdfmt  =   "/etc/mh/mhl.format";
diff --git a/docs/historical/mh-jun-1982/strings/mhnews.c b/docs/historical/mh-jun-1982/strings/mhnews.c
new file mode 100644 (file)
index 0000000..ba78917
--- /dev/null
@@ -0,0 +1,14 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+/*
+ * This program is called to print out MH news IF NEWS is defined
+ * when the MH programs are compiled.  This whole mechanism has not
+ * been tested under version 7!
+ */
+
+char    *mhnews =       "/etc/mh/news";
diff --git a/docs/historical/mh-jun-1982/strings/msgprot.c b/docs/historical/mh-jun-1982/strings/msgprot.c
new file mode 100644 (file)
index 0000000..44cc697
--- /dev/null
@@ -0,0 +1,14 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+/*
+ * Every NEW message will be created with this protection.  When a
+ * message is filed it retains its protection, so this only applies
+ * to messages coming in through inc.
+ */
+
+char    *msgprot =      "0664";
diff --git a/docs/historical/mh-jun-1982/strings/pfolder.c b/docs/historical/mh-jun-1982/strings/pfolder.c
new file mode 100644 (file)
index 0000000..b273f23
--- /dev/null
@@ -0,0 +1,8 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+char    *pfolder =      "current-folder";
diff --git a/docs/historical/mh-jun-1982/strings/prproc.c b/docs/historical/mh-jun-1982/strings/prproc.c
new file mode 100644 (file)
index 0000000..2e0a75e
--- /dev/null
@@ -0,0 +1,13 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+/*
+ * This is the std BELL pr, which is invoked through show with the
+ * -pr switch.
+ */
+
+char    *prproc =       "/bin/pr";
diff --git a/docs/historical/mh-jun-1982/strings/rhosts.c b/docs/historical/mh-jun-1982/strings/rhosts.c
new file mode 100644 (file)
index 0000000..666c3eb
--- /dev/null
@@ -0,0 +1,25 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+
+#ifdef ARPANET
+
+#ifdef NOGATEWAY
+
+/*  rhosts is a list of legal uucp hosts who are allowed to
+/*  send stuff out over the arpanet.
+/**/
+
+char *rhosts[] = {
+       0
+       };
+
+#endif
+
+#endif
+
diff --git a/docs/historical/mh-jun-1982/strings/scanproc.c b/docs/historical/mh-jun-1982/strings/scanproc.c
new file mode 100644 (file)
index 0000000..c80cd98
--- /dev/null
@@ -0,0 +1,13 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+/*
+ * This program is usually called directly by users, but it is
+ * also invoked by "pick -scan".
+ */
+
+char    *scanproc =     "/usr/local/scan";
diff --git a/docs/historical/mh-jun-1982/strings/sendproc.c b/docs/historical/mh-jun-1982/strings/sendproc.c
new file mode 100644 (file)
index 0000000..b071d02
--- /dev/null
@@ -0,0 +1,14 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+/*
+ * This program is usually called by one of the message composition
+ * programs: comp, repl, dist, and forw, but it may also be called
+ * directly to send a message previously composed.
+ */
+
+char    *sendproc =     "/usr/local/send";
diff --git a/docs/historical/mh-jun-1982/strings/showproc.c b/docs/historical/mh-jun-1982/strings/showproc.c
new file mode 100644 (file)
index 0000000..fd8f773
--- /dev/null
@@ -0,0 +1,16 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+/*
+ * This program is called to list messages.  At Rand, the program
+ * `c' stops at the end of each page and waits for a <return> or
+ * <open> to continue.  Eventually, this path should invoke a
+ * special program which displays messages much more intelligently--
+ * such as layed out nicely on the screen.
+ */
+
+char    *showproc =     "/usr/ucb/more";                       /* 5/6/79 */
diff --git a/docs/historical/mh-jun-1982/strings/stdcomps.c b/docs/historical/mh-jun-1982/strings/stdcomps.c
new file mode 100644 (file)
index 0000000..d9e2991
--- /dev/null
@@ -0,0 +1,13 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+/*
+ * This is the standard skeleton for message composition with both
+ * comp and forw.
+ */
+
+char    *stdcomps =     "/etc/mh/components";
diff --git a/docs/historical/mh-jun-1982/strings/stddcomps.c b/docs/historical/mh-jun-1982/strings/stddcomps.c
new file mode 100644 (file)
index 0000000..ce10837
--- /dev/null
@@ -0,0 +1,12 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+/*
+ * This is the standard skeleton for message composition with dist.
+ */
+
+char    *stddcomps =    "/etc/mh/distcomps";
diff --git a/docs/historical/mh-jun-1982/strings/sysed.c b/docs/historical/mh-jun-1982/strings/sysed.c
new file mode 100644 (file)
index 0000000..f034e20
--- /dev/null
@@ -0,0 +1,16 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+/*
+ * This is the editor invoked by the various message composition
+ * programs.  It SHOULD be a 2-D scope editor, such as Rand's Ned
+ * or Berkeley's ex, but any editor will work.  If you don't have
+ * a scope editor, you might want to default to prompter, but it
+ * works very marginally with forw and dist.
+ */
+
+char    *sysed =        "/bin/e";
diff --git a/docs/historical/mh-jun-1982/strings/sysname.c b/docs/historical/mh-jun-1982/strings/sysname.c
new file mode 100644 (file)
index 0000000..7761e88
--- /dev/null
@@ -0,0 +1,5 @@
+#include <whoami.h>
+
+#ifndef sysname
+char sysname[] = SYSNAME;
+#endif
diff --git a/docs/historical/mh-jun-1982/subs/Makefile b/docs/historical/mh-jun-1982/subs/Makefile
new file mode 100644 (file)
index 0000000..ca75fb9
--- /dev/null
@@ -0,0 +1,209 @@
+#
+#       Proprietary Rand Corporation, 1981.
+#       Further distribution of this software
+#       subject to the terms of the Rand
+#       license agreement.
+#
+
+CFLAGS = -O -I/usr/include -I../support # -m
+LIB = subs.a
+OFILES =\
+       add.o \
+       ambigsw.o \
+       atooi.o \
+       brkstring.o \
+       cdate.o \
+       cndfree.o \
+       concat.o \
+       copy.o \
+       copyip.o \
+       cputc.o \
+       done.o \
+       fdcompare.o \
+       gans.o \
+       getans.o \
+       getcpy.o \
+       help.o \
+       locv.o \
+       m_convert.o \
+       m_delete.o \
+       m_edit.o \
+       m_file.o \
+       m_find.o \
+       m_getcur.o \
+       m_getdefs.o \
+       m_getfld.o \
+       m_getfolder.o \
+       m_gmprot.o \
+       m_gmsg.o \
+       m_maildir.o \
+       m_name.o \
+       m_replace.o \
+       m_send.o \
+       m_setcur.o \
+       m_update.o \
+       makedir.o \
+       makename.o \
+       mu_atoi.o \
+       path.o \
+       peekc.o \
+       pr_array.o \
+       printsw.o \
+       putenv.o \
+       pwd.o \
+       r1bindex.o \
+       showfile.o \
+       smatch.o \
+       ssequal.o \
+       trimcpy.o \
+       type.o \
+       uleq.o
+
+CFILES =\
+       add.c \
+       ambigsw.c \
+       atooi.c \
+       brkstring.c \
+       cdate.c \
+       cndfree.c \
+       concat.c \
+       copy.c \
+       copyip.c \
+       cputc.c \
+       done.c \
+       fdcompare.c \
+       gans.c \
+       getans.c \
+       getcpy.c \
+       help.c \
+       locv.c \
+       m_convert.c \
+       m_delete.c \
+       m_edit.c \
+       m_file.c \
+       m_find.c \
+       m_getcur.c \
+       m_getdefs.c \
+       m_getfld.c \
+       m_getfolder.c \
+       m_gmprot.c \
+       m_gmsg.c \
+       m_maildir.c \
+       m_name.c \
+       m_replace.c \
+       m_send.c \
+       m_setcur.c \
+       m_update.c \
+       makedir.c \
+       makename.c \
+       mu_atoi.c \
+       path.c \
+       peekc.c \
+       pr_array.c \
+       printsw.c \
+       putenv.c \
+       pwd.c \
+       r1bindex.c \
+       showfile.c \
+       smatch.c \
+       ssequal.c \
+       trimcpy.c \
+       type.c \
+       uleq.c
+
+$(LIB): $(OFILES)
+       -rm -f $(LIB)
+       ar cr $(LIB) `lorder $(OFILES) | tsort`
+       ranlib $(LIB)
+
+.c.o:
+       $(CC) $(CFLAGS) -c -O $*.c
+       -@ld -x -r $@
+       @mv a.out $@
+
+lint:
+       -lint $(CFILES) subs-lc
+
+distribution:   clean
+       -rm -f $(LIB)
+
+clean:
+       -rm -f $(OFILES)
+
+depend:
+       ../misc/depend.sh $(CFILES)
+
+###DEPENDENCIES Follow.  Do not delete this line
+add.o:  /usr/include/stdio.h
+add.o:  ../mh.h
+ambigsw.o:      /usr/include/stdio.h
+ambigsw.o:      ../mh.h
+concat.o:       ../mh.h
+cputc.o:        /usr/include/stdio.h
+fdcompare.o:    ../mh.h
+gans.o:         ../mh.h
+gans.o:         /usr/include/stdio.h
+getans.o:       ../mh.h
+getans.o:       /usr/include/signal.h
+getans.o:       /usr/include/stdio.h
+getcpy.o:       ../mh.h
+help.o:         ../mh.h
+locv.o:         /usr/include/stdio.h
+m_convert.o:    ../mh.h
+m_convert.o:    /usr/include/stdio.h
+m_convert.o:    /usr/include/ctype.h
+m_delete.o:     ../mh.h
+m_edit.o:       ../mh.h
+m_edit.o:       /usr/include/sys/types.h
+m_edit.o:       /usr/include/sys/stat.h
+m_edit.o:       /usr/include/signal.h
+m_edit.o:       /usr/include/stdio.h
+#m_edit.o:        /usr/include/strings.h
+m_file.o:       ../mh.h
+m_file.o:       ../folder.h
+m_file.o:       /usr/include/stdio.h
+m_file.o:       /usr/include/sys/types.h
+m_file.o:       /usr/include/sys/stat.h
+m_file.o:       /usr/include/errno.h
+m_find.o:       ../mh.h
+m_find.o:       /usr/include/stdio.h
+m_getcur.o:     /usr/include/stdio.h
+m_getcur.o:     ../mh.h
+m_getdefs.o:    ../mh.h
+m_getdefs.o:    /usr/include/stdio.h
+m_getfld.o:     ../mh.h
+m_getfld.o:     /usr/include/stdio.h
+m_getfolder.o:  ../mh.h
+m_getfolder.o:  /usr/include/stdio.h
+m_gmprot.o:     ../mh.h
+m_gmprot.o:     /usr/include/stdio.h
+m_gmsg.o:       ../mh.h
+m_gmsg.o:       /usr/include/stdio.h
+m_maildir.o:    ../mh.h
+m_maildir.o:    /usr/include/stdio.h
+m_name.o:       ../mh.h
+m_replace.o:    ../mh.h
+m_send.o:       ../mh.h
+m_send.o:       /usr/include/stdio.h
+m_setcur.o:     ../mh.h
+m_setcur.o:     /usr/include/stdio.h
+m_update.o:     ../mh.h
+m_update.o:     /usr/include/stdio.h
+m_update.o:     /usr/include/signal.h
+makedir.o:      ../mh.h
+makedir.o:      /usr/include/stdio.h
+makename.o:     ../mh.h
+makename.o:     /usr/include/stdio.h
+mu_atoi.o:      ../mh.h
+path.o:         ../mh.h
+peekc.o:        /usr/include/stdio.h
+peekc.o:        ../mh.h
+printsw.o:      ../mh.h
+putenv.o:       /usr/include/stdio.h
+pwd.o:  /usr/include/stdio.h
+#pwd.o:   /usr/include/strings.h
+showfile.o:     ../mh.h
+showfile.o:     /usr/include/signal.h
+showfile.o:     /usr/include/stdio.h
+smatch.o:       ../mh.h
+type.o:         /usr/include/stdio.h
diff --git a/docs/historical/mh-jun-1982/subs/Makefile.bak b/docs/historical/mh-jun-1982/subs/Makefile.bak
new file mode 100644 (file)
index 0000000..34bd5ed
--- /dev/null
@@ -0,0 +1,209 @@
+#
+#       Proprietary Rand Corporation, 1981.
+#       Further distribution of this software
+#       subject to the terms of the Rand
+#       license agreement.
+#
+
+CFLAGS = # -m
+LIB = subs.a
+OFILES =\
+       add.o \
+       ambigsw.o \
+       atooi.o \
+       brkstring.o \
+       cdate.o \
+       cndfree.o \
+       concat.o \
+       copy.o \
+       copyip.o \
+       cputc.o \
+       done.o \
+       fdcompare.o \
+       gans.o \
+       getans.o \
+       getcpy.o \
+       help.o \
+       locv.o \
+       m_convert.o \
+       m_delete.o \
+       m_edit.o \
+       m_file.o \
+       m_find.o \
+       m_getcur.o \
+       m_getdefs.o \
+       m_getfld.o \
+       m_getfolder.o \
+       m_gmprot.o \
+       m_gmsg.o \
+       m_maildir.o \
+       m_name.o \
+       m_replace.o \
+       m_send.o \
+       m_setcur.o \
+       m_update.o \
+       makedir.o \
+       makename.o \
+       mu_atoi.o \
+       path.o \
+       peekc.o \
+       pr_array.o \
+       printsw.o \
+       putenv.o \
+       pwd.o \
+       r1bindex.o \
+       showfile.o \
+       smatch.o \
+       ssequal.o \
+       trimcpy.o \
+       type.o \
+       uleq.o
+
+CFILES =\
+       add.c \
+       ambigsw.c \
+       atooi.c \
+       brkstring.c \
+       cdate.c \
+       cndfree.c \
+       concat.c \
+       copy.c \
+       copyip.c \
+       cputc.c \
+       done.c \
+       fdcompare.c \
+       gans.c \
+       getans.c \
+       getcpy.c \
+       help.c \
+       locv.c \
+       m_convert.c \
+       m_delete.c \
+       m_edit.c \
+       m_file.c \
+       m_find.c \
+       m_getcur.c \
+       m_getdefs.c \
+       m_getfld.c \
+       m_getfolder.c \
+       m_gmprot.c \
+       m_gmsg.c \
+       m_maildir.c \
+       m_name.c \
+       m_replace.c \
+       m_send.c \
+       m_setcur.c \
+       m_update.c \
+       makedir.c \
+       makename.c \
+       mu_atoi.c \
+       path.c \
+       peekc.c \
+       pr_array.c \
+       printsw.c \
+       putenv.c \
+       pwd.c \
+       r1bindex.c \
+       showfile.c \
+       smatch.c \
+       ssequal.c \
+       trimcpy.c \
+       type.c \
+       uleq.c
+
+$(LIB): $(OFILES)
+       -rm -f $(LIB)
+       ar cr $(LIB) `lorder $(OFILES) | tsort`
+       ranlib $(LIB)
+
+.c.o:
+       $(CC) $(CFLAGS) -c -O $*.c
+       -@ld -x -r $@
+       @mv a.out $@
+
+lint:
+       -lint $(CFILES) subs-lc
+
+distribution:   clean
+       -rm -f $(LIB)
+
+clean:
+       -rm -f $(OFILES)
+
+depend:
+       ../misc/depend.sh $(CFILES)
+
+###DEPENDENCIES Follow.  Do not delete this line
+add.o:  /usr/include/stdio.h
+add.o:  ../mh.h
+ambigsw.o:      /usr/include/stdio.h
+ambigsw.o:      ../mh.h
+concat.o:       ../mh.h
+cputc.o:        /usr/include/stdio.h
+fdcompare.o:    ../mh.h
+gans.o:         ../mh.h
+gans.o:         /usr/include/stdio.h
+getans.o:       ../mh.h
+getans.o:       /usr/include/signal.h
+getans.o:       /usr/include/stdio.h
+getcpy.o:       ../mh.h
+help.o:         ../mh.h
+locv.o:         /usr/include/stdio.h
+m_convert.o:    ../mh.h
+m_convert.o:    /usr/include/stdio.h
+m_convert.o:    /usr/include/ctype.h
+m_delete.o:     ../mh.h
+m_edit.o:       ../mh.h
+m_edit.o:       /usr/include/sys/types.h
+m_edit.o:       /usr/include/sys/stat.h
+m_edit.o:       /usr/include/signal.h
+m_edit.o:       /usr/include/stdio.h
+m_edit.o:       /usr/include/strings.h
+m_file.o:       ../mh.h
+m_file.o:       ../folder.h
+m_file.o:       /usr/include/stdio.h
+m_file.o:       /usr/include/sys/types.h
+m_file.o:       /usr/include/sys/stat.h
+m_file.o:       /usr/include/errno.h
+m_find.o:       ../mh.h
+m_find.o:       /usr/include/stdio.h
+m_getcur.o:     /usr/include/stdio.h
+m_getcur.o:     ../mh.h
+m_getdefs.o:    ../mh.h
+m_getdefs.o:    /usr/include/stdio.h
+m_getfld.o:     ../mh.h
+m_getfld.o:     /usr/include/stdio.h
+m_getfolder.o:  ../mh.h
+m_getfolder.o:  /usr/include/stdio.h
+m_gmprot.o:     ../mh.h
+m_gmprot.o:     /usr/include/stdio.h
+m_gmsg.o:       ../mh.h
+m_gmsg.o:       /usr/include/stdio.h
+m_maildir.o:    ../mh.h
+m_maildir.o:    /usr/include/stdio.h
+m_name.o:       ../mh.h
+m_replace.o:    ../mh.h
+m_send.o:       ../mh.h
+m_send.o:       /usr/include/stdio.h
+m_setcur.o:     ../mh.h
+m_setcur.o:     /usr/include/stdio.h
+m_update.o:     ../mh.h
+m_update.o:     /usr/include/stdio.h
+m_update.o:     /usr/include/signal.h
+makedir.o:      ../mh.h
+makedir.o:      /usr/include/stdio.h
+makename.o:     ../mh.h
+makename.o:     /usr/include/stdio.h
+mu_atoi.o:      ../mh.h
+path.o:         ../mh.h
+peekc.o:        /usr/include/stdio.h
+peekc.o:        ../mh.h
+printsw.o:      ../mh.h
+putenv.o:       /usr/include/stdio.h
+pwd.o:  /usr/include/stdio.h
+pwd.o:  /usr/include/strings.h
+showfile.o:     ../mh.h
+showfile.o:     /usr/include/signal.h
+showfile.o:     /usr/include/stdio.h
+smatch.o:       ../mh.h
+type.o:         /usr/include/
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/subs/add.c b/docs/historical/mh-jun-1982/subs/add.c
new file mode 100644 (file)
index 0000000..7126135
--- /dev/null
@@ -0,0 +1,28 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include <stdio.h>
+#include "../mh.h"
+
+char *sprintf();
+char *malloc();
+
+char *add(this, that)
+       register char *this, *that;
+{
+       register char *r;
+
+       if(!this)
+               this = "";
+       if(!that)
+               that = "";
+       r = malloc((unsigned) (strlen(this)+strlen(that)+1));
+       VOID sprintf(r, "%s%s", that, this);
+       if(*that)
+               cndfree(that);
+       return(r);
+}
diff --git a/docs/historical/mh-jun-1982/subs/ambigsw.c b/docs/historical/mh-jun-1982/subs/ambigsw.c
new file mode 100644 (file)
index 0000000..0afcd7b
--- /dev/null
@@ -0,0 +1,19 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include <stdio.h>
+#include "../mh.h"
+
+ambigsw(arg, swp)
+       char *arg;
+       struct swit *swp;
+{
+       fprintf(stderr, "%s: ", invo_name);
+       fprintf(stderr, "-%s ambiguous.  It matches \n", arg);
+       printsw(arg, swp, "-");
+}
+
diff --git a/docs/historical/mh-jun-1982/subs/atooi.c b/docs/historical/mh-jun-1982/subs/atooi.c
new file mode 100644 (file)
index 0000000..a72af55
--- /dev/null
@@ -0,0 +1,22 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+
+/* octal version of atoi */
+atooi(cp)
+register char *cp;
+{
+       register int i, base;
+
+       i = 0;
+       base = 8;
+       while(*cp >= '0' && *cp <= '7') {
+               i *= base;
+               i += *cp++ - '0';
+       }
+       return(i);
+}
diff --git a/docs/historical/mh-jun-1982/subs/brkstring.c b/docs/historical/mh-jun-1982/subs/brkstring.c
new file mode 100644 (file)
index 0000000..b61ff2e
--- /dev/null
@@ -0,0 +1,49 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+/* returns pointer to static table of substring ptrs */
+
+#define NSTR 25
+
+char **
+brkstring(strg,brksep,brkterm)
+       char *strg;
+       char *brksep, *brkterm;
+{
+
+       register char c, *sp;
+       static char *broken[NSTR+1];    /* static array of substring start addresses */
+       int bi;
+
+       sp = strg;      /* scan string, replacing separators with zeroes */
+
+       for (bi=0; bi<NSTR; bi++) {     /* and entering start addrs in "broken" */
+               while (brkany(c = *sp, brksep)) *sp++ = 0;
+               if (!c || brkany(c, brkterm)) {
+                       *sp=0;
+                       broken[bi] = 0;
+                       return(broken);         /* terminator found, finish up */
+               }
+
+               broken[bi] = sp;        /* set next start addr */
+
+               while ((c = *++sp) && !brkany(c,brksep) && !brkany(c,brkterm));
+
+       }
+       broken[NSTR] = 0;               /* reached limit of NSTR substrings */
+       return (broken);
+}
+
+brkany (chr,strg)      /* returns 1 if chr in strg, 0 otherwise */
+char chr,*strg;
+{
+       register char *sp;
+
+       for (sp=strg; *sp; sp++)
+               if (chr == *sp) return (1);
+       return (0);
+}
diff --git a/docs/historical/mh-jun-1982/subs/cdate.c b/docs/historical/mh-jun-1982/subs/cdate.c
new file mode 100644 (file)
index 0000000..558103a
--- /dev/null
@@ -0,0 +1,25 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+/* returns date in format dd-mon-yy@hh:mm:ss\0 */
+char *cdate(dataddr)
+long *dataddr;
+{
+       register char *cp;
+       char *ctime();
+
+       cp = ctime(dataddr);
+       cp[1] = cp[8];
+       cp[2] = cp[9];
+       cp[3] = '-';
+       cp[7] = '-';
+       cp[8] = cp[22];
+       cp[9] = cp[23];
+       cp[10] = '@';
+       cp[19] = 0;
+       return(cp+1);
+}
diff --git a/docs/historical/mh-jun-1982/subs/cndfree.c b/docs/historical/mh-jun-1982/subs/cndfree.c
new file mode 100644 (file)
index 0000000..5f765e3
--- /dev/null
@@ -0,0 +1,19 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+/* Conditional free -- perform a free call if the address passed
+ * is in free storage;  else NOP
+ */
+
+
+cndfree(addr)
+char *addr;
+{
+       extern char end;
+
+       if(addr >= &end) free(addr);
+}
diff --git a/docs/historical/mh-jun-1982/subs/concat.c b/docs/historical/mh-jun-1982/subs/concat.c
new file mode 100644 (file)
index 0000000..73c1134
--- /dev/null
@@ -0,0 +1,27 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+char *malloc();
+
+/*VARARGS*/
+char *concat(args)
+       char *args;
+{
+       register char **a;
+       register char *cp;
+       register unsigned len;
+       register char *ret;
+
+       len = 1;
+       for(a = &args; *a; )
+               len += strlen(*a++);
+       ret = cp = malloc(len);
+       for(a = &args; *a; )
+               cp = copy(*a++, cp);
+       return(ret);
+}
diff --git a/docs/historical/mh-jun-1982/subs/copy.c b/docs/historical/mh-jun-1982/subs/copy.c
new file mode 100644 (file)
index 0000000..950752a
--- /dev/null
@@ -0,0 +1,13 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+char *copy(from,to)
+register char *from, *to;
+{
+       while(*to++ = *from++);
+       return to-1;
+};
diff --git a/docs/historical/mh-jun-1982/subs/copyip.c b/docs/historical/mh-jun-1982/subs/copyip.c
new file mode 100644 (file)
index 0000000..150db91
--- /dev/null
@@ -0,0 +1,22 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+char **
+copyip(cpf, cpt)
+char **cpf, **cpt;
+{
+       register int *ipf, *ipt;
+
+       ipf = (int *) cpf;
+       ipt = (int *) cpt;
+
+       while((*ipt = *ipf) && *ipf++ != -1)
+               ipt++;
+       *ipt = 0;
+       return (char **) ipt;
+}
+
diff --git a/docs/historical/mh-jun-1982/subs/cputc.c b/docs/historical/mh-jun-1982/subs/cputc.c
new file mode 100644 (file)
index 0000000..531e082
--- /dev/null
@@ -0,0 +1,20 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include <stdio.h>
+
+cputc(chr, ip)
+register FILE *ip;
+{
+       if(ip != NULL) {
+               putc(chr, ip);
+               if(ferror(ip)) {
+                       perror("Write error");
+                       done(-1);
+               }
+       }
+}
diff --git a/docs/historical/mh-jun-1982/subs/depend.sh b/docs/historical/mh-jun-1982/subs/depend.sh
new file mode 100755 (executable)
index 0000000..8abadf1
--- /dev/null
@@ -0,0 +1,10 @@
+sed "/DEPENDENCIES/,\$d" < Makefile > Maketemp
+echo "###DEPENDENCIES Follow.  Do not delete this line" >> Maketemp
+grep \^#include $@ | sed '
+       s/\.c/\.o/
+       s/:#include/:   /
+       s/"\(.*\)"/\1/
+       s/<\(.*\)>/\/usr\/include\/\1/
+' >> Maketemp
+mv Makefile Makeback
+mv Maketemp Makefile
diff --git a/docs/historical/mh-jun-1982/subs/done.c b/docs/historical/mh-jun-1982/subs/done.c
new file mode 100644 (file)
index 0000000..1a29912
--- /dev/null
@@ -0,0 +1,15 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+/* This routine is replaced by some modules if they need to do
+ * cleanup.  All exits in the code call done rather than exit.
+ */
+
+done(status)
+{
+       exit(status);
+}
diff --git a/docs/historical/mh-jun-1982/subs/fdcompare.c b/docs/historical/mh-jun-1982/subs/fdcompare.c
new file mode 100644 (file)
index 0000000..6645126
--- /dev/null
@@ -0,0 +1,37 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+long lseek();
+
+fdcompare(fd1, fd2)
+{
+       int n1, n2, resp;
+       register int i;
+       register char *c1, *c2;
+       char b1[512], b2[512];
+
+       resp = 1;
+       while((n1 = read(fd1, b1, 512)) >= 0 &&
+             (n2 = read(fd2, b2, 512)) >= 0 &&
+              n1 == n2) {
+
+               c1 = b1; c2 = b2;
+               for(i = n1 < 512? n1 : 512; i--; )
+                       if(*c1++ != *c2++) {
+                               resp = 0;
+                               goto leave;
+                       }
+               if(n1 < 512)
+                       goto leave;
+       }
+       resp = 0;
+leave:
+       VOID lseek(fd1, 0l, 0);
+       VOID lseek(fd2, 0l, 0);
+       return(resp);
+}
diff --git a/docs/historical/mh-jun-1982/subs/gans.c b/docs/historical/mh-jun-1982/subs/gans.c
new file mode 100644 (file)
index 0000000..a8f1e68
--- /dev/null
@@ -0,0 +1,46 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+#include <stdio.h>
+
+gans(prompt, ansp)
+char *prompt;
+struct swit *ansp;
+{
+       char ansbuf[32];
+       register char *cp;
+       register int i;
+       struct swit *ap;
+
+    for(;;) {
+       printf("%s", prompt);
+       VOID fflush(stdout);
+       cp = ansbuf;
+       while((i = getchar()) != '\n') {
+               if(i == EOF)
+                       return(0);
+               if(cp < &ansbuf[31]) {
+                       if(i >= 'A' && i <= 'Z')
+                               i += 'a'-'A';
+                       *cp++ = i;
+               }
+       }
+       *cp = 0;
+       if(ansbuf[0] == '?' || cp == ansbuf) {
+               printf("Options are:\n");
+               for(ap = ansp; ap->sw; ap++)
+                       printf("  %s\n", ap->sw);
+               continue;
+       }
+       if((i = smatch(ansbuf, ansp)) < 0) {
+               printf("%s: %s.\n", ansbuf, i == -1? "unknown":"ambiguous");
+               continue;
+       }
+       return(i);
+    }
+}
diff --git a/docs/historical/mh-jun-1982/subs/getans.c b/docs/historical/mh-jun-1982/subs/getans.c
new file mode 100644 (file)
index 0000000..2c40e9f
--- /dev/null
@@ -0,0 +1,62 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+#include <signal.h>
+#include <stdio.h>
+
+int g_sigint;   /* sensed an interrupt */
+int g_sig();
+
+char **
+getans(prompt, ansp)
+       char *prompt;
+       struct swit *ansp;
+{
+       static char ansbuf[128];
+       register char *cp, **cpp;
+       register int i;
+
+       VOID signal(SIGINT, g_sig);
+       for(;;) {
+               printf("%s", prompt);
+               VOID fflush(stdout);
+               cp = ansbuf;
+               while((i = getchar()) != '\n') {
+                       if(i == EOF || g_sigint)  {
+                               g_sigint = 0;
+                               return(0);
+                       }
+                       if(cp < &ansbuf[127])
+                               *cp++ = i;
+               }
+               *cp = 0;
+               if(ansbuf[0] == '?' || cp == ansbuf) {
+                       printf("Options are:\n");
+                       printsw(ALL, ansp, "");
+                       continue;
+               }
+               cpp = brkstring(ansbuf, " ", NULLCP);
+               switch(smatch(*cpp, ansp)) {
+               case -2:ambigsw(*cpp, ansp);                   /* ambiguous */
+                       continue;
+               case -1:                                       /* unknown   */
+                       printf(" -%s unknown. Hit <CR> for help.\n", *cpp);
+                       continue;
+               default:
+                       return(cpp);            /* list, edit, quit, send */
+               }
+       }
+}
+
+
+g_sig()
+{
+       VOID signal(SIGINT, g_sig);
+       g_sigint = 1;
+       return;
+}
diff --git a/docs/historical/mh-jun-1982/subs/getcpy.c b/docs/historical/mh-jun-1982/subs/getcpy.c
new file mode 100644 (file)
index 0000000..b81d8d3
--- /dev/null
@@ -0,0 +1,22 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+
+char *malloc();
+char *strcpy();
+
+char *
+getcpy(str)
+       char *str;
+{
+       register char *cp;
+
+       cp = malloc((unsigned)strlen(str) + 1);
+       VOID strcpy(cp, str);
+       return(cp);
+}
diff --git a/docs/historical/mh-jun-1982/subs/help.c b/docs/historical/mh-jun-1982/subs/help.c
new file mode 100644 (file)
index 0000000..130a481
--- /dev/null
@@ -0,0 +1,17 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+
+help(str, swp)
+       char *str;
+       struct swit *swp;
+{
+       printf("syntax: %s\n", str);
+       printf("  switches are:\n");
+       printsw(ALL, swp, "-");
+}
diff --git a/docs/historical/mh-jun-1982/subs/invo_name.c b/docs/historical/mh-jun-1982/subs/invo_name.c
new file mode 100644 (file)
index 0000000..b684288
--- /dev/null
@@ -0,0 +1,26 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+/*
+ * This routine returns the address on the stack of the text of the
+ *  first argument to the process.  It only works on the VAX, and only
+ *  if the process was not called with 4 empty args in a row.
+ *
+ *   This is a crock, and it doesn't work on 4bsd.
+ *   invo_name is now an external char * pointer
+ *   2/1/81 - dave yost.
+ */
+
+char *invo_name()
+{
+       register int *ip;
+
+       ip = (int *) 0x7ffffff8;        /* Highest stack address -4 */
+
+       while(*--ip != 0)               /* Look backwards for bumber */
+               continue;
+       return (char *) &ip[1];         /* Next string is i
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/subs/locv.c b/docs/historical/mh-jun-1982/subs/locv.c
new file mode 100644 (file)
index 0000000..5e58529
--- /dev/null
@@ -0,0 +1,19 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include <stdio.h>
+
+extern char *sprintf ();
+
+char *
+locv(longint)
+       long longint;
+{
+       static char locvbuf[12];
+
+       return sprintf(locvbuf, "%ld", longint);
+}
diff --git a/docs/historical/mh-jun-1982/subs/m_convert.c b/docs/historical/mh-jun-1982/subs/m_convert.c
new file mode 100644 (file)
index 0000000..3f56b52
--- /dev/null
@@ -0,0 +1,156 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+#include <stdio.h>
+#include <ctype.h>
+
+int  convdir;
+struct msgs *mp;
+char *delimp;
+
+m_convert(name)
+char *name;
+{
+       register char *cp;
+       register int first, last;
+       int found, range, err;
+       char *bp;
+
+       found = 0;
+       if(strcmp((cp = name), "all") == 0)
+               cp = "first-last";
+       if((err = first = m_conv(cp)) <= 0)
+               goto badbad;
+       if(*(cp = delimp) && *cp != '-' && *cp != ':')  {
+       baddel: fprintf(stderr, "Illegal argument delimiter: \"%c\"\n", *delimp);
+               return(0);
+       }
+       if(*cp == '-') {
+               cp++;
+               if((err = last = m_conv(cp)) <= 0) {
+         badbad:       if(err == -1)
+                               fprintf(stderr, "No %s message\n", cp);
+                       else
+         badlist:              fprintf(stderr, "Bad message list \"%s\".\n",
+                                       name);
+                       return(0);
+               }
+               if(last < first) goto badlist;
+               if(*delimp) goto baddel;
+               if(first > mp->hghmsg || last < mp->lowmsg) {
+       rangerr:        fprintf(stderr, "No messages in range \"%s\".\n", name);
+                       return(0);
+               }
+               if(last > mp->hghmsg)
+                       last = mp->hghmsg;
+               if(first < mp->lowmsg)
+                       first = mp->lowmsg;
+       } else if(*cp == ':') {
+               cp++;
+               if(*cp == '-') {
+                       convdir = -1;
+                       cp++;
+               } else if(*cp == '+') {
+                       convdir = 1;
+                       cp++;
+               }
+               if((range = atoi(bp = cp)) == 0)
+                       goto badlist;
+               while(isdigit(*bp)) bp++;
+               if(*bp)
+                       goto baddel;
+               if((convdir > 0 && first > mp->hghmsg) ||
+                  (convdir < 0 && first < mp->lowmsg))
+                       goto rangerr;
+               if(first < mp->lowmsg)
+                       first = mp->lowmsg;
+               if(first > mp->hghmsg)
+                       first = mp->hghmsg;
+               for(last = first; last >= mp->lowmsg && last <= mp->hghmsg;
+                                               last += convdir)
+                       if(mp->msgstats[last]&EXISTS)
+                               if(--range <= 0)
+                                       break;
+               if(last < mp->lowmsg)
+                       last = mp->lowmsg;
+               if(last > mp->hghmsg)
+                       last = mp->hghmsg;
+               if(last < first) {
+                       range = last; last = first; first = range;
+               }
+       } else {
+               if(first > mp->hghmsg || first < mp->lowmsg ||
+                  !(mp->msgstats[first]&EXISTS)) {
+                       fprintf(stderr, "Message %d doesn't exist.\n", first);
+                       return(0);
+               }
+               last = first;
+       }
+       while(first <= last) {
+               if(mp->msgstats[first]&EXISTS) {
+                       if(!(mp->msgstats[first]&SELECTED)) {
+                               mp->numsel++;
+                               mp->msgstats[first] |= SELECTED;
+                               if(first < mp->lowsel)
+                                       mp->lowsel = first;
+                               if(first > mp->hghsel)
+                                       mp->hghsel = first;
+                       }
+                       found++;
+               }
+               first++;
+       }
+       if(!found)
+               goto rangerr;
+       return(1);
+}
+
+m_conv(str)
+char *str;
+{
+       register char *cp, *bp;
+       register int i;
+       char buf[16];
+
+       convdir = 1;
+       cp = bp = str;
+       if(isdigit(*cp))  {
+               while(isdigit(*bp)) bp++;
+               delimp = bp;
+               return (i = atoi(cp)) > MAXFOLDER ? MAXFOLDER : i;
+       }
+       bp = buf;
+       while((*cp >= 'a' && *cp <= 'z') || *cp == '.')
+               *bp++ = *cp++;
+       *bp++ = 0;
+       delimp = cp;
+       if(strcmp(buf, "first") == 0)
+               return(mp->lowmsg);
+       else if(strcmp(buf, "last") == 0) {
+               convdir = -1;
+               return(mp->hghmsg);
+       } else if(strcmp(buf, "cur") == 0 || strcmp(buf, ".") == 0)
+               return(mp->curmsg > 0 ? mp->curmsg : -1);
+       else if(strcmp(buf, "prev") == 0) {
+               convdir = -1;
+               for(i = (mp->curmsg<=mp->hghmsg)? mp->curmsg-1: mp->hghmsg;
+                   i >= mp->lowmsg; i--) {
+                       if(mp->msgstats[i]&EXISTS)
+                               return(i);
+               }
+               return(-1);                     /* non-existent message */
+       } else if(strcmp(buf, "next") == 0)  {
+               for(i = (mp->curmsg>=mp->lowmsg)? mp->curmsg+1: mp->lowmsg;
+                   i <= mp->hghmsg; i++) {
+                       if(mp->msgstats[i]&EXISTS)
+                               return(i);
+               }
+               return(-1);
+       } else
+               return(0);                     /* bad message list */
+}
diff --git a/docs/historical/mh-jun-1982/subs/m_delete.c b/docs/historical/mh-jun-1982/subs/m_delete.c
new file mode 100644 (file)
index 0000000..f2dedf7
--- /dev/null
@@ -0,0 +1,29 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+
+m_delete(key)
+char *key;
+{
+       register struct node *np, *npprev;
+
+       m_getdefs();
+       for(np = (struct node *) &m_defs; npprev = np; )  {
+               if((np = np->n_next) == 0)
+                       break;
+               if(uleq(np->n_name, key)) {
+                       npprev->n_next = np->n_next;
+                       cndfree(np->n_name);
+                       cndfree(np->n_field);
+                       free((char *)np);
+                       def_flags |= DEFMOD;
+                       return(0);
+               }
+       }
+       return(1);
+}
diff --git a/docs/historical/mh-jun-1982/subs/m_edit.c b/docs/historical/mh-jun-1982/subs/m_edit.c
new file mode 100644 (file)
index 0000000..b87381a
--- /dev/null
@@ -0,0 +1,98 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <stdio.h>
+#include <strings.h>
+
+struct msgs *mp;
+
+m_edit(ed, file, use, altmsg)
+char **ed, *file, *altmsg;
+int use;
+{
+       /* Exec editor.  Normal exit returns 0.
+        * To abort, returns -1.  To try again, returns -2
+        */
+
+       static char *edsave;
+       static int  reedit;
+       struct stat stbuf;
+       int retstat;
+       register char *cp;
+       int pid, wpid;
+       int (*intr)();
+       int status;
+
+       if(!reedit) {                   /* set initial editor */
+               if(!*ed && (*ed = m_find("editor")) == NULL)
+                       *ed = sysed;
+       } else
+               if(!*ed) {              /* no explicit editor */
+                       *ed = edsave;
+                       cp = rindex(*ed, '/');
+                       if(cp == 0)
+                               cp = *ed;
+                       cp = concat(cp, "-next", 0);
+                       if((cp = m_find(cp)) != NULL)
+                               *ed = cp;
+               }
+       intr = signal(SIGINT, SIG_IGN);
+       if((pid = fork()) == 0) {
+               if(altmsg) {
+                       VOID unlink("@");
+                       VOID link(altmsg, "@"); /* An easy handle on cur msg */
+                       putenv("editalt", altmsg);
+               }
+               m_update();
+               VOID fflush(stdout);
+               VOID signal(SIGINT, intr);
+               execlp(*ed, r1bindex(*ed, '/'), file, 0);
+               fprintf(stderr, "Can't exec the editor:  ");
+               perror(*ed);  done(-1);
+       } else if(pid == -1) {
+               fprintf(stderr, "No forks!\n");
+               retstat = -1;
+               goto leave;
+       } else
+               while((wpid = wait(&status)) != -1 && wpid != pid) ;
+       VOID signal(SIGINT, intr);
+       if(status) {
+               if((status&0177400 == 0177400) ||       /* Can't exec editor */
+                  (reedit && (status&0377) == 0)) {    /*2nd edit.Aborted by user*/
+                       retstat = -2;
+                       goto leave;
+               }
+               fprintf(stderr, "[%s aborted--%s ", invo_name, file);
+               if(!use && (status&017740)) {   /* edit aborted by user */
+                       VOID unlink(file);
+                       fprintf(stderr, "deleted]\n");
+               } else                          /* 'use' or system abort */
+                       fprintf(stderr, "preserved]\n");
+               retstat = -2;
+               goto leave;
+       }
+       reedit++;
+       retstat = 0;
+       if(altmsg && !mp->msgflags&READONLY) {
+               VOID stat("@", &stbuf);
+               if(stbuf.st_nlink == 1)  /*@'s been edited by Ned*/
+                       if(unlink(altmsg) == -1 || link("@", altmsg) == -1){
+                               fprintf(stderr, "Can't update %s from @ file!\n",altmsg);
+                               retstat = 0;
+                               goto leave;
+                       }
+       }
+ leave:
+       edsave = getcpy(*ed);
+       *ed = 0;
+       VOID unlink("@");       /* Remove this extra link */
+       return(retstat);
+}
diff --git a/docs/historical/mh-jun-1982/subs/m_file.c b/docs/historical/mh-jun-1982/subs/m_file.c
new file mode 100644 (file)
index 0000000..550d7d4
--- /dev/null
@@ -0,0 +1,95 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+#include "../folder.h"
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+extern  int errno;
+
+m_file(folder, msg, folders, nfolders, prsrvf, setcur)
+char *folder;
+char *msg;
+struct st_fold folders[];
+int nfolders;
+int prsrvf;
+int setcur;
+{
+       char newmsg[256], buf[BUFSIZ];
+       register int i;
+       register char *nmsg;
+       register struct st_fold *fp;
+       struct stat stbuf, stbf1;
+       int n, o, linkerr;
+
+    for(fp = folders; fp < &folders[nfolders]; fp++) {
+       if(prsrvf)
+               nmsg = msg;
+       else {
+               if (fp->f_mp->hghmsg >= MAXFOLDER) {
+                       fprintf(stderr,
+                               "Can't file msg %s -- folder %s is full.\n",
+                               msg, fp->f_name);
+                       return(1);
+               }
+               nmsg = m_name(fp->f_mp->hghmsg++ + 1);
+       }
+       VOID copy(nmsg, copy("/", copy(m_maildir(fp->f_name), newmsg)));
+       if(link(msg, newmsg) < 0) {
+               linkerr = errno;
+               if(linkerr == EEXIST ||
+                 (linkerr == EXDEV && stat(newmsg, &stbuf) != -1)) {
+                       if(linkerr != EEXIST || stat(msg, &stbf1) < 0 ||
+                          stat(newmsg, &stbuf) < 0 ||
+                          stbf1.st_ino != stbuf.st_ino) {
+                               fprintf(stderr, "Message %s:%s already exists.\n",
+                                    fp->f_name, msg);
+                               return(1);
+                       }
+                       continue;
+               }
+               if(linkerr == EXDEV) {
+                       if((o = open(msg, 0)) == -1) {
+                               fprintf(stderr, "Can't open %s:%s.\n",
+                                       folder, msg);
+                               return(1);
+                       }
+                       VOID fstat(o, &stbuf);
+                       if((n = creat(newmsg, (int)stbuf.st_mode&0777)) == -1) {
+                               fprintf(stderr, "Can't create %s:%s.\n",
+                                       fp->f_name, nmsg);
+                               VOID close(o);
+                               return(1);
+                       }
+                       do
+                               if((i=read(o, buf, sizeof buf)) < 0 ||
+                                 write(n, buf, i) == -1) {
+                                   fprintf(stderr, "Copy error on %s:%s to %s:%s!\n",
+                                           folder, msg, fp->f_name, nmsg);
+                                   VOID close(o); VOID close(n);
+                                   return(1);
+                               }
+                       while(i == sizeof buf);
+                       VOID close(n); VOID close(o);
+               } else {
+                       fprintf(stderr, "Error on link %s:%s to %s:",
+                           folder, msg, fp->f_name);
+                       perror(nmsg);
+                       return(1);
+               }
+       }
+       if(   setcur
+          && (   (i = atoi(nmsg)) < fp->f_mp->curmsg
+              || !fp->f_mp->curmsg
+             )
+         )
+               fp->f_mp->curmsg = i;
+    }
+    retur
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/subs/m_find.c b/docs/historical/mh-jun-1982/subs/m_find.c
new file mode 100644 (file)
index 0000000..71576a3
--- /dev/null
@@ -0,0 +1,21 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+#include <stdio.h>
+
+char *m_find(str)
+       char *str;
+{
+       register struct node *n;
+
+       m_getdefs();
+       for(n = m_defs; n; n = n->n_next)
+               if(uleq(n->n_name, str))
+                       return(n->n_field);
+       return(NULL);
+}
diff --git a/docs/historical/mh-jun-1982/subs/m_getcur.c b/docs/historical/mh-jun-1982/subs/m_getcur.c
new file mode 100644 (file)
index 0000000..57d244d
--- /dev/null
@@ -0,0 +1,34 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include <stdio.h>
+#include "../mh.h"
+
+extern char *sprintf();
+
+m_getcur(name)
+       char *name;
+{
+       register char *cp;
+       register int i, j;
+       short readonly, curfil = 0;
+       char buf[132];
+
+       readonly = (access(".",2) == -1);
+       if(readonly) {
+               VOID sprintf(buf, "cur-%s", name);
+               if(cp = m_find(buf))
+                       curfil = mu_atoi(cp);
+       } else if(i = open(current, 0)) {
+               if((j = read(i, buf, sizeof buf)) >= 2){
+                       buf[j-1] = 0;                   /* Zap <lf> */
+                       curfil = mu_atoi(buf);
+               }
+               VOID close(i);
+       }
+       return curfil;
+}
diff --git a/docs/historical/mh-jun-1982/subs/m_getdefs.c b/docs/historical/mh-jun-1982/subs/m_getdefs.c
new file mode 100644 (file)
index 0000000..a707060
--- /dev/null
@@ -0,0 +1,99 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+#include <stdio.h>
+
+char *malloc();
+extern char *sprintf();
+
+char    defpath[128];
+
+struct procs {
+       char    *procname;
+       char    **procnaddr;
+} procs [] = {
+       { "lproc",      &lproc          },
+       { "lsproc",     &lsproc         },
+       { "mh_deliver", &mh_deliver     },
+       { "prproc",     &prproc         },
+       { "scanproc",   &scanproc       },
+       { "showproc",   &showproc       },
+       { "sendproc",   &sendproc       },
+       { "fileproc",   &fileproc       },
+       { 0,            0               },
+};
+
+m_getdefs()
+{
+       register struct node *np;
+       register int state, wpid, pid;
+       register struct procs *ps;
+       int status;
+       FILE *ib;
+       char name[NAMESZ], field[1024];
+
+       if(defpath[0])
+               return;         /* We've already been called!   */
+       if(!mypath)
+               if((mypath = getenv("HOME")) == NULL) {
+                       fprintf(stderr, "HOME environment variable not set!\n");
+                       done(1);
+               }
+       VOID sprintf(defpath, "%s%s", mypath, mh_prof);
+/***    copy(mh_prof, copy(mypath, defpath));           ***/
+
+       if((ib = fopen(defpath, "r")) == NULL) {
+               if((pid = fork()) == 0) {
+                       execl(installproc, "install-mh", "-auto", 0);
+                       fprintf(stderr, "Can't exec ");perror(installproc);
+                       done(1);
+               } else if(pid == -1) {
+                       fprintf(stderr, "No forks!\n");
+                       done(1);
+               } else
+                       while((wpid = wait(&status)) != -1 && wpid != pid)
+                               ;
+               if(status || (ib = fopen(defpath, "r")) == NULL) {
+                       fprintf(stderr, "[install-mh aborted]\n");
+                       done(1);
+               }
+       }
+
+#ifdef NEWS                     /* NOT CONVERTED TO V7!!! */
+       VOID fstat(fildes(ib), field);
+       deftime = (&field)->i_atime;
+#endif
+
+       np = (struct node *) &m_defs;
+       state = FLD;
+    for(;;)
+       switch(state = m_getfld(state,name,field,sizeof field,ib)) {
+       case FLD:
+       case FLDEOF:
+               np->n_next = (struct node *) malloc(sizeof *np);
+               np = np->n_next;
+               np->n_name = getcpy(name);
+               np->n_field = trimcpy(field);
+               np->n_next = 0;
+               for(ps = procs; ps->procname; ps++)
+                       if(strcmp(np->n_name, ps->procname) == 0) {
+                               *ps->procnaddr = np->n_field;
+                               break;
+                       }
+               if(state == FLDEOF) {
+                       VOID fclose(ib);
+                       return;
+               }
+               continue;
+       case BODY:
+       case BODYEOF:
+               fprintf(stderr, ".mh_profile must not contain a body--it can't \
+end with a blank line!\n");
+       default:
+               fprintf(stderr, "Bad format: .mh_profile!\n");
+               done(1
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/subs/m_getfld.c b/docs/historical/mh-jun-1982/subs/m_getfld.c
new file mode 100644 (file)
index 0000000..4b66a69
--- /dev/null
@@ -0,0 +1,95 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+#include <stdio.h>
+
+int     m_fldsz;
+
+m_getfld(state, name, buf, bufsz, iob)
+int state, bufsz;
+char *name, *buf;
+FILE *iob;
+{
+       register char *cp;
+       register c;
+
+       while((c = getc(iob)) == '\001' && peekc(iob) == '\001')
+               while(getc(iob) != '\n');
+
+       if(c < 0)
+               return(FILEEOF);
+       m_fldsz = 0;
+
+       switch(state) {
+
+       case FLDEOF:
+       case BODYEOF:
+       case FLD:
+               if(c == '\n' || c == '-')
+                       goto body;
+               cp = name;
+               for(;;) {
+                       if(c == ':')
+                               break;
+                       if(cp >= &name[NAMESZ-1]) {
+                               *cp = 0;
+fprintf(stderr, "??Component Name Exceeds %d Chars:\n    \"%s\"\n", NAMESZ-1, name);
+                               return(LENERR);
+                       }
+                       if(c == '\n' || c < 0) {
+                               *cp = 0;
+fprintf(stderr, "??%s Encountered While Scanning for a colon:\n    \"%s\"\n",
+       (c < 0)? "<eof>":"<end of line>", name);
+                               return(FMTERR);
+                       }
+                       *cp++ = c;
+                       *cp   = 0;
+                       c = getc(iob);
+               }
+
+       case FLDPLUS:
+               cp = buf;
+               for(;;) {
+                       if((c = getc(iob)) < 0)
+                               return(FLDEOF);
+                       *cp++ = c;
+                       *cp   = 0;
+                       m_fldsz++;
+                       if(c == '\n')
+                               if((c = peekc(iob)) != ' ' && c != '\t')
+                                       if(c == '\001' || c < 0)
+                                               return(FLDEOF);
+                                       else
+                                               return(FLD);
+                       if(cp >= &buf[bufsz-1])
+                               return(peekc(iob) < 0? FLDEOF:FLDPLUS);
+               }
+
+       body:   if(c == '-')
+                       while(getc(iob) != '\n') ;
+               buf[0] = 0;
+               if((c = getc(iob)) == '\001' && peekc(iob) == '\001')
+                       return(BODYEOF);
+
+       case BODY:
+               cp = buf;  *cp = 0;
+               for(;;) {
+                       if(c < 0 || (c == '\001' && peekc(iob) == '\001'))
+                               return(BODYEOF);
+                       *cp++ = c;
+                       *cp   = 0;
+                       m_fldsz++;
+                       if(cp >= &buf[bufsz-1])
+                               return(((c=peekc(iob))<0||c=='\001')?
+                                       BODYEOF: BODY);
+                       c = getc(iob);
+               }
+
+       }
+/*NOTREACHED*/
+}
diff --git a/docs/historical/mh-jun-1982/subs/m_getfolder.c b/docs/historical/mh-jun-1982/subs/m_getfolder.c
new file mode 100644 (file)
index 0000000..d8e0048
--- /dev/null
@@ -0,0 +1,19 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+#include <stdio.h>
+
+char *m_getfolder()
+{
+       register char *folder;
+
+       m_getdefs();
+       if((folder = m_find(pfolder)) == NULL || *folder == 0)
+               folder = defalt;
+       return(folder);
+}
diff --git a/docs/historical/mh-jun-1982/subs/m_gmprot.c b/docs/historical/mh-jun-1982/subs/m_gmprot.c
new file mode 100644 (file)
index 0000000..b920342
--- /dev/null
@@ -0,0 +1,21 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+#include <stdio.h>
+
+m_gmprot()
+{
+       register char *cp;
+       register int prot;
+
+       if((cp = m_find("msg-protect")) != NULL)
+               prot = atooi(cp);
+       else
+               prot = atooi(msgprot);
+       return(prot);
+}
diff --git a/docs/historical/mh-jun-1982/subs/m_gmsg.c b/docs/historical/mh-jun-1982/subs/m_gmsg.c
new file mode 100644 (file)
index 0000000..65eace0
--- /dev/null
@@ -0,0 +1,124 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+#include <stdio.h>
+
+extern char *malloc();
+extern char *sprintf();
+
+#define Block
+
+struct  msgs *mp;
+
+/*  Look through a folder.
+/*  Alloc a 'struct msgs' structure and fill it in
+/*  with such things as what the low, high, and current messages are.
+/*  Return a pointer to this structure or a null pointer if trouble.
+/**/
+struct msgs *
+m_gmsg(name)
+char *name;
+{
+       FILE *ifp;      /***/
+       register int i, j;
+       register char *cp;
+       int  curfil;
+
+       struct {
+               struct {
+                       short d_inum;
+                       char d_name[14];
+               } ent;
+               int terminator;
+       } dir;
+
+       struct {
+               int xhghmsg,
+                   xnummsg,
+                   xlowmsg,
+                   xcurmsg;
+               char xselist,
+                    xflags,
+                    xfiller,
+                    xothers;
+               char xmsgs[MAXFOLDER + 1];
+       } msgbuf;
+
+       if((ifp = fopen(".", "r")) == 0)
+               return(0);
+       for(j = 0; j <= MAXFOLDER; j++)
+               msgbuf.xmsgs[j] = 0;
+       msgbuf.xcurmsg = 0;
+       msgbuf.xnummsg = 0;
+       msgbuf.xselist = 0;
+       msgbuf.xothers = 0;
+       msgbuf.xlowmsg = 5000;
+       msgbuf.xhghmsg = 0;
+       msgbuf.xflags  = (access(".",2) == -1)? READONLY:0;  /*RAND sys call*/
+       curfil = 0;
+       dir.terminator = 0;
+       cp = dir.ent.d_name;
+       for(;;) {
+               if(fread(&dir, sizeof dir.ent, 1, ifp) != 1)
+                       break;
+               if(dir.ent.d_inum)
+                       if(j = mu_atoi(cp)) {
+                               if(j > msgbuf.xhghmsg)
+                                       msgbuf.xhghmsg = j;
+                               msgbuf.xnummsg++;
+                               if(j < msgbuf.xlowmsg)
+                                       msgbuf.xlowmsg = j;
+                               msgbuf.xmsgs[j] = EXISTS;
+                       } else if(*cp != ',' && *cp != '.')
+                                       if(strcmp(cp, current) == 0)
+                                               curfil++;
+                                       else if(strcmp(cp, listname) == 0)
+                                               msgbuf.xselist++;
+                                       else
+                                               msgbuf.xothers++;
+       }
+       if(!msgbuf.xhghmsg)
+               msgbuf.xlowmsg = 0;
+       VOID fclose(ifp);
+       if(msgbuf.xflags&READONLY) Block {
+               char buf[132];
+               VOID sprintf(buf, "cur-%s", name);
+/***            copy(name, copy("cur-", buf));          ***/
+               if((cp = m_find(buf)) != NULL)
+                       if(j = mu_atoi(cp))
+                               msgbuf.xcurmsg = j;
+       } else if(curfil && (i = open(current, 0)) >= 0) {
+               if((j = read(i, dir.ent.d_name, sizeof dir.ent.d_name)) >= 2){
+                       dir.ent.d_name[j-1] = 0;    /* Zap <lf> */
+                       if(j = mu_atoi(dir.ent.d_name))
+                               msgbuf.xcurmsg = j;
+               }
+               VOID close(i);
+       }
+       Block {
+               register struct msgs *msgp;
+               if( (char *) (msgp = (struct msgs *)
+                    malloc((unsigned) (sizeof *mp + msgbuf.xhghmsg + 2)))
+                  == (char *) 0)
+                       return(0);
+               msgp->hghmsg   = msgbuf.xhghmsg;
+               msgp->nummsg   = msgbuf.xnummsg;
+               msgp->lowmsg   = msgbuf.xlowmsg;
+               msgp->curmsg   = msgbuf.xcurmsg;
+               msgp->selist   = msgbuf.xselist;
+               msgp->msgflags = msgbuf.xflags;
+               msgp->others   = msgbuf.xothers;
+               msgp->foldpath = name;
+               msgp->lowsel   = 5000;
+               msgp->hghsel   = 0;
+               msgp->numsel   = 0;
+               for(j = 0; j <= msgbuf.xhghmsg; j++)
+                       msgp->msgstats[j] = msgbuf.xmsgs[j];
+               return(msgp);
+       }
+}
diff --git a/docs/historical/mh-jun-1982/subs/m_maildir.c b/docs/historical/mh-jun-1982/subs/m_maildir.c
new file mode 100644 (file)
index 0000000..694f19c
--- /dev/null
@@ -0,0 +1,39 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+#include <stdio.h>
+
+extern char *sprintf();
+extern char *strcpy();
+
+char *mypath;
+
+char *m_maildir(folder)
+char *folder;
+{
+       register char *fold, *pth, *cp;
+       static char mailfold[128];
+
+       m_getdefs();
+       if(!(fold = folder))
+               fold = m_getfolder();
+       if(*fold == '/' || *fold == '.')
+               return(fold);
+       cp = mailfold;
+       if((pth = m_find("path")) != NULL && *pth) {
+               if(*pth != '/') {
+                       VOID sprintf(cp, "%s/", mypath);
+                       cp += strlen(cp);
+               }
+               cp = copy(pth, cp);
+               if(cp[-1] != '/')
+                       *cp++ = '/';
+       } else
+               cp = copy(path("./", TFOLDER), cp);
+       strcpy(cp, fold);
+       return(mailf
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/subs/m_name.c b/docs/historical/mh-jun-1982/subs/m_name.c
new file mode 100644 (file)
index 0000000..042268e
--- /dev/null
@@ -0,0 +1,30 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+
+char *m_name(num)
+{
+       static char name[4];
+       register char *cp;
+       register int i;
+
+       name[0] = 0;
+       name[1] = 0;
+       name[2] = 0;
+       name[3] = 0;
+       i = num;
+       cp = &name[3];
+       if(i > 0 && i <= MAXFOLDER)
+               do {
+                       *--cp = (i % 10) + '0';
+                       i /= 10;
+               } while(i);
+       else
+               *--cp = '?';
+       return(cp);
+}
diff --git a/docs/historical/mh-jun-1982/subs/m_news.cc b/docs/historical/mh-jun-1982/subs/m_news.cc
new file mode 100644 (file)
index 0000000..50ef9b4
--- /dev/null
@@ -0,0 +1,53 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "mh.h"
+#include "/rnd/borden/h/stat.h"
+#include "/rnd/borden/h/iobuf.h"
+
+char    mhnews[];
+char    anoyes[];
+
+m_news()
+{
+       struct inode stbf;
+       struct iobuf in;
+       register flag, c;
+       long  readdate, gdate();
+       char *cp, *ap;
+
+       if(stat(mhnews, &stbf) == -1)
+               return;
+       m_getdefs();
+       if((ap = m_find("newsdate")) != -1 ) {          /* seen news? */
+               readdate = gdate(ap);
+               if(stbf.i_mtime < readdate)             /* recently? */
+                        return;
+       }
+       time(&readdate);                                /* current time */
+       m_replace("newsdate", cdate(&readdate));        /* update profile */
+       m_update();
+
+       fopen(mhnews, &in);                             /* show news */
+       flag = getc(&in);
+
+       /**************************************************
+       while((c = getc(&in)) != -1)
+        *      if(c == NEWSPAUSE) {
+        *              if(!gans("More? ", anoyes))
+        *                      break;
+        *      } else
+        *              putchar(c);
+        ***************************************************
+        */
+       flush();
+       showfile(mhnews);
+       if(flag == NEWSHALT)
+               exit(0);
+       close(in.b_fildes);
+}
+
diff --git a/docs/historical/mh-jun-1982/subs/m_replace.c b/docs/historical/mh-jun-1982/subs/m_replace.c
new file mode 100644 (file)
index 0000000..45b6548
--- /dev/null
@@ -0,0 +1,36 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+char *malloc();
+
+m_replace(key,value)
+char *key, *value;
+
+{
+       register struct node *np;
+
+       m_getdefs();
+       for(np = m_defs; ; np = np->n_next) {
+               if(uleq(np->n_name, key)) {
+                       if(strcmp(value, np->n_field) != 0) {
+                               cndfree(np->n_field);
+                               np->n_field = value;
+                               def_flags |= DEFMOD;
+                       }
+                       return;
+               }
+               if(!np->n_next)
+                       break;
+       }
+       np->n_next = (struct node *) malloc(sizeof *np);
+       np = np->n_next;
+       np->n_name = getcpy(key);
+       np->n_next = 0;
+       np->n_field = value;
+       def_flags |= DEFMOD;
+}
diff --git a/docs/historical/mh-jun-1982/subs/m_send.c b/docs/historical/mh-jun-1982/subs/m_send.c
new file mode 100644 (file)
index 0000000..8b640ae
--- /dev/null
@@ -0,0 +1,34 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+#include <stdio.h>
+
+m_send(arg, file)
+char **arg, *file;
+{
+       char *vec[15];
+       int ivec;
+
+       ivec = 0;
+       vec[ivec++] = "send";
+       vec[ivec++] = file;
+       if(**arg == 'v')
+               vec[ivec++] = "-verbose";
+       else if(*arg) {
+               do
+                       vec[ivec++] = *arg++;
+               while(*arg);
+       }
+       vec[ivec++] = 0;
+       m_update();
+       VOID fflush(stdout);
+       execv(sendproc, vec);
+       fprintf(stderr, "Can't exec %s.\n", sendproc);
+       return(0);
+
+}
diff --git a/docs/historical/mh-jun-1982/subs/m_setcur.c b/docs/historical/mh-jun-1982/subs/m_setcur.c
new file mode 100644 (file)
index 0000000..5c71513
--- /dev/null
@@ -0,0 +1,39 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+#include <stdio.h>
+
+extern char *strcpy();
+
+struct  msgs *mp;
+
+m_setcur(num)
+{
+       char buf[6];
+       register int i;
+       register char *cp1;
+
+       if(mp->msgflags&READONLY) {
+               m_replace(cp1 = concat("cur-",mp->foldpath,0), m_name(num));
+               free(cp1);
+       } else {
+               strcpy(buf, m_name(num));
+               cp1 = buf + strlen(buf);
+               *cp1++ = '\n';
+               if(strcmp(current, "cur"))
+                       error("\"current\" got Clobbered!! Bug!");
+               if((i = creat(current, 0660)) >= 0) {
+                       if(write(i, buf, cp1-buf) != cp1-buf) {
+                               fprintf(stderr, "m_setcur: write error on ");
+                               perror(current);
+                               done(1);
+                       }
+                       VOID close(i);
+               }
+       }
+}
diff --git a/docs/historical/mh-jun-1982/subs/m_update.c b/docs/historical/mh-jun-1982/subs/m_update.c
new file mode 100644 (file)
index 0000000..3fef773
--- /dev/null
@@ -0,0 +1,32 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+#include <stdio.h>
+#include <signal.h>
+
+char    defpath[];
+
+m_update()
+{
+       FILE *out;
+       register struct node *np;
+       int (*save)();
+
+       if(def_flags & DEFMOD) {
+               save = signal(SIGINT, SIG_IGN);
+               if((out = fopen(defpath, "w")) == NULL) {
+                       fprintf(stderr, "Can't create %s!!\n", defpath);
+                       done(1);
+               }
+               for(np = m_defs; np; np = np->n_next)
+                       fprintf(out, "%s: %s\n", np->n_name, np->n_field);
+               VOID fclose(out);
+               VOID signal(SIGINT, save);
+               def_flags &= ~DEFMOD;
+       }
+}
diff --git a/docs/historical/mh-jun-1982/subs/makedir.c b/docs/historical/mh-jun-1982/subs/makedir.c
new file mode 100644 (file)
index 0000000..2a912b3
--- /dev/null
@@ -0,0 +1,37 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+#include <stdio.h>
+
+makedir(dir)
+       char *dir;
+{
+       register int pid, wpid;
+       register char *c;
+       int status;
+
+       if((pid = fork()) == 0) {
+               execl("/bin/mkdir", "mkdir", dir, 0);
+               execl("/usr/bin/mkdir", "mkdir", dir, 0);
+               fprintf(stderr, "Can't exec mkdir!!?\n");
+               return(0);
+       }
+       if(pid == -1) {
+               fprintf(stderr, "Can't fork\n");
+               return(0);
+       }
+       while((wpid = wait(&status)) != pid && wpid != -1) ;
+       if(status) {
+               fprintf(stderr, "Bad exit status (%o) from mkdir.\n", status);
+               return(0);
+       }
+       if((c = m_find("folder-protect")) == NULL)
+               c = foldprot;
+       VOID chmod(dir, atooi(c));
+       return(1);
+}
diff --git a/docs/historical/mh-jun-1982/subs/makename.c b/docs/historical/mh-jun-1982/subs/makename.c
new file mode 100644 (file)
index 0000000..2ce9c5d
--- /dev/null
@@ -0,0 +1,25 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+#include <stdio.h>
+
+char *makename(prefix,suffix)
+char *prefix, *suffix;
+{
+       static char tmpname[15];
+       register char *cp1, *cp2;
+       register int pid;
+
+       pid = getpid();
+       cp1 = tmpname;
+       for (cp2 = prefix; *cp1++ = *cp2++; );
+       cp1--;
+       do *cp1++ = pid%10 + '0'; while (pid /= 10);
+       for (cp2 = suffix; *cp1++ = *cp2++; );
+       if (cp1 >= &tmpname[15]) error("strs too long to makename");
+       return (tmpn
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/subs/mu_atoi.c b/docs/historical/mh-jun-1982/subs/mu_atoi.c
new file mode 100644 (file)
index 0000000..978f5b8
--- /dev/null
@@ -0,0 +1,27 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+
+mu_atoi(str)
+       char *str;
+{
+       register char *cp;
+       register int i;
+
+       i = 0;
+       cp = str;
+       while(*cp) {
+               if(*cp < '0' || *cp > '9')
+                       return 0;
+               i *= 10;
+               i += *cp++ - '0';
+       }
+       if (i > MAXFOLDER)
+               return 0;
+       return i;
+}
diff --git a/docs/historical/mh-jun-1982/subs/path.c b/docs/historical/mh-jun-1982/subs/path.c
new file mode 100644 (file)
index 0000000..e5bcc70
--- /dev/null
@@ -0,0 +1,23 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+
+char *path(name, type)
+       register char *name;
+{
+       static char *pwds;
+
+       if(*name == '/' ||
+          (type == TFOLDER && *name != '.'))
+               return name;
+       if(!pwds)
+               pwds = pwd();
+       if(*name == '.' && name[1] == '/')
+               name += 2;
+       return concat(pwds, "/", name, 0);
+}
diff --git a/docs/historical/mh-jun-1982/subs/peekc.c b/docs/historical/mh-jun-1982/subs/peekc.c
new file mode 100644 (file)
index 0000000..ac4889a
--- /dev/null
@@ -0,0 +1,19 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include <stdio.h>
+#include "../mh.h"
+
+peekc(ib)
+FILE *ib;
+{
+       register c;
+
+       c = getc(ib);
+       VOID ungetc(c,ib);
+       return(c);
+}
diff --git a/docs/historical/mh-jun-1982/subs/pr_array.c b/docs/historical/mh-jun-1982/subs/pr_array.c
new file mode 100644 (file)
index 0000000..f7da785
--- /dev/null
@@ -0,0 +1,16 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+pr_array(cp,ap)
+char *cp,  **ap;
+{
+       register  int  i;
+
+       for(i=0;  *ap;  ap++,i++)
+               printf("%s[%d]=> %s\n", cp,i,*ap);
+}
+
diff --git a/docs/historical/mh-jun-1982/subs/printsw.c b/docs/historical/mh-jun-1982/subs/printsw.c
new file mode 100644 (file)
index 0000000..b1bf63d
--- /dev/null
@@ -0,0 +1,33 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+
+printsw(substr, swp, prefix)
+       char *substr, *prefix;
+       struct swit *swp;
+{
+       char buf[128];
+       register char *cp, *cp1;
+       register int i;
+       int len;
+
+       len = strlen(substr);
+       for(; swp->sw; swp++)
+               if(!*substr ||                  /* null matches all strings */
+                  (ssequal(substr, swp->sw) && len >= swp->minchars))
+                       if(swp->minchars > 0) {
+                               cp = buf;
+                               *cp++ = '(';
+                               for(cp1 = swp->sw, i = 0; i < swp->minchars; i++)
+                                       *cp++ = *cp1++;
+                               *cp++ = ')';
+                               while(*cp++ = *cp1++);
+                               printf("  %s%s\n", prefix, buf);
+                       } else if(swp->minchars == 0)
+                               printf("  %s%s\n", prefix, swp->sw);
+}
diff --git a/docs/historical/mh-jun-1982/subs/putenv.c b/docs/historical/mh-jun-1982/subs/putenv.c
new file mode 100644 (file)
index 0000000..1f3e64e
--- /dev/null
@@ -0,0 +1,66 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+/*
+ *      putenv(name, arg)
+ *      replaces or adds the `name' entry with "name=arg";
+ *
+ *      Uses malloc() for space for new vector and new entry;
+ *
+ *      Bruce Borden            January 1980
+ *      The Rand Corporation
+ */
+
+#include <stdio.h>
+
+extern  char **environ;
+
+putenv(name, arg)
+char *name, *arg;
+{
+       register int i;
+       register char **ep, **nep, *cp;
+
+       if((cp = (char *) malloc(strlen(name) + strlen(arg) + 2)) == NULL)
+               return(1);
+       strcpy(cp, name);
+       strcat(cp, "=");
+       strcat(cp, arg);
+       for(ep = environ, i = 0; *ep; ep++, i++)
+               if(nvmatch(name, *ep)) {
+                       *ep = cp;
+                       return(0);
+               }
+       if((nep = (char **) malloc((i+2) * sizeof *nep)) == NULL)
+               return(1);
+       for(ep = environ, i = 0; *ep; )
+               nep[i++] = *ep++;
+       nep[i++] = cp;
+       nep[i] = 0;
+       environ = nep;
+       return(0);
+}
+
+/*
+ *     s1 is either name, or name=value
+ *     s2 is name=value
+ *     if names match, return value of s2, else NULL
+ *     used for environment searching: see getenv
+ */
+
+static
+nvmatch(s1, s2)
+register char *s1, *s2;
+{
+
+       while (*s1 == *s2++)
+               if (*s1++ == '=')
+                       return(1);
+       if (*s1 == '\0' && *(s2-1) == '=')
+               return(1);
+       return(0);
+}
diff --git a/docs/historical/mh-jun-1982/subs/pwd.c b/docs/historical/mh-jun-1982/subs/pwd.c
new file mode 100644 (file)
index 0000000..4a1c0bc
--- /dev/null
@@ -0,0 +1,27 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include <stdio.h>
+#include <strings.h>
+
+extern FILE *popen ();
+
+char *
+pwd()
+{
+       register FILE *pp;
+       static char curpath[128];
+
+       if((pp = popen("pwd", "r")) == NULL ||
+           fgets(curpath, sizeof curpath, pp) == NULL ||
+           pclose(pp) != 0) {
+               fprintf(stderr, "Can't find current directory!\n");
+               done(1);
+       }
+       *rindex(curpath, '\n') = 0;     /* Zap the lf */
+       return curpath;
+}
diff --git a/docs/historical/mh-jun-1982/subs/r1bindex.c b/docs/historical/mh-jun-1982/subs/r1bindex.c
new file mode 100644 (file)
index 0000000..b567feb
--- /dev/null
@@ -0,0 +1,27 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+/*
+ * r1bindex(str, chr) stands for Right plus 1 or Beginning index of
+ *      chr in str.  I.e. return ptr 1 past LAST occurrence of chr in
+ *      str, OR beginning of the string if str doesn't contain chr.
+ */
+
+char *
+r1bindex(str, chr)
+register char *str;
+register int chr;
+{
+       register char *cp;
+
+       for(cp = str; *cp; cp++)
+               continue;
+       --cp;
+       while(cp >= str && *cp != chr)
+               --cp;
+       return ++cp;
+}
diff --git a/docs/historical/mh-jun-1982/subs/showfile.c b/docs/historical/mh-jun-1982/subs/showfile.c
new file mode 100644 (file)
index 0000000..552abe3
--- /dev/null
@@ -0,0 +1,45 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+#include <signal.h>
+#include <stdio.h>
+
+showfile(file)
+char *file;
+{
+       int pid, wpid, (*intr)(), status;
+       char *vec[4];
+
+       intr = signal(SIGINT, SIG_IGN);
+       m_update();
+       VOID fflush(stdout);
+       if((pid = fork()) == 0) {
+               vec[0] = r1bindex(lproc, '/');
+               vec[1] = file;
+               vec[2] = 0;
+               VOID signal(SIGINT, intr);
+               execv(lproc, vec);
+               fprintf(stderr, "Can't exec ");
+               perror(lproc);
+               goto badleave;
+       } else if(pid == -1) {
+               fprintf(stderr, "No forks!\n");
+               goto badleave;
+       } else
+               while((wpid = wait(&status)) != -1 && wpid != pid) ;
+       VOID signal(SIGINT, intr);
+       if(status & 0377)
+               goto badleave;
+       return(0);
+
+ badleave:
+       VOID fflush(stdout);
+       return(1);
+
+}
+
diff --git a/docs/historical/mh-jun-1982/subs/smatch.c b/docs/historical/mh-jun-1982/subs/smatch.c
new file mode 100644 (file)
index 0000000..786f398
--- /dev/null
@@ -0,0 +1,40 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include "../mh.h"
+
+/* switch match, or any unambiguous abbreviation */
+/* exact match always wins, even if shares same root */
+/* returns subscript in zero-terminated tbl[] of strings */
+/* returns -1 if no match, -2 if ambiguous */
+
+#define abs(i) (i < 0 ? -i : i)
+
+smatch(string, swp)
+char *string;
+struct swit *swp;
+{
+       register char *sp, *tcp;
+       struct swit *tp;
+       int firstone, stringlen;
+
+       firstone = -1;
+
+       for (stringlen = strlen(string), tp = swp; tcp = tp->sw; tp++) {
+               if(stringlen < abs(tp->minchars)) continue;      /* no match */
+               for (sp = string; *sp == *tcp++; ) {
+                       if (*sp++ == 0) return(tp-swp); /* exact match */
+               }
+               if (*sp != 0) {
+                       if (*sp != ' ') continue; /* no match */
+                       if (*--tcp == 0) return(tp-swp); /* exact match */
+               }
+               if (firstone == -1) firstone = tp-swp; /* possible match */
+               else firstone = -2;     /* ambiguous */
+       }
+
+       return (first
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/subs/ssequal.c b/docs/historical/mh-jun-1982/subs/ssequal.c
new file mode 100644 (file)
index 0000000..27958c2
--- /dev/null
@@ -0,0 +1,15 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+ssequal(substr, str)
+char *substr, *str;
+{
+       while(*substr)
+               if(*substr++ != *str++)
+                       return(0);
+       return(1);
+}
diff --git a/docs/historical/mh-jun-1982/subs/subs-lc b/docs/historical/mh-jun-1982/subs/subs-lc
new file mode 100644 (file)
index 0000000..99cd49c
--- /dev/null
@@ -0,0 +1,63 @@
+/*LINTLIBRARY*/
+#include "../mh.h"
+#include "../folder.h"
+#include <stdio.h>
+char    *invo_name;
+
+char    *add(a, b) char *a, *b; { return a; }
+int     ambigsw(a, s) char *a; struct swit *s; { ; }
+int     atooi(s) char *s; { return 1; }
+char    **brkstring(s,b,t) char *s,*b,*t; { return &s; }
+char    *cdate(d) long *d; { return cdate(d); }
+       cndfree(a) char *a; { ; }
+       /*VARARGS3*/
+char    *concat(s1,s2,s3) char *s1,*s2,*s3; { return s1; }
+char    *copy(f,t) char *f,*t; { return f; }
+char    **copyip(f,t) char **f,**t; { return t; }
+       cputc(c,f) FILE *f; { ; }
+/*
+ * done should not be defined here because it is designed to be
+ *  redefined by the parent routines if they need special exit
+ *  processing.  Definition here causes multiply defined messages
+ *  from lint.
+ *
+ *      done(s) { ; }
+ */
+int     fdcompare(f1,f2) { return f1; }
+int     gans(p,s) char *p; struct swit *s; { return 1; }
+char    **getans(p,s) char *p; struct swit *s; { return &p; }
+char    *getcpy(s) char *s; { return s; }
+       help(s,sw) char *s; struct swit *sw; { ; }
+char    *locv(l) long l; { return locv(l); }
+int     m_convert(s) char *s; { return 0; }
+int     m_delete(s) char *s; { return 1; }
+int     m_edit(e,f,u,a) char **e,*f,*a; { return 0; }
+int     m_file(folder, msg, folders, nfolders, prsrvf, setcur)
+       char *folder, *msg; struct st_fold folders[];
+       int nfolders, prsrvf, setcur;
+       { return 0; }
+char    *m_find(s) char *s; { return s; }
+int     m_getcur(s) char *s; { return 0; }
+       m_getdefs() { ; }
+int     m_getfld(s,n,b,bs,i) char *n,*b; FILE *i; { return 0; }
+char    *m_getfolder() { return m_getfolder(); }
+int     m_gmprot() { return 0; }
+struct msgs *m_gmsg(s) char *s; { return m_gmsg(s); }
+char    *m_mailder(s) char *s; { return s; }
+char    *m_name(i) { return m_name(0); }
+       m_replace(k,v) char *k,*v; { ; }
+int     m_send(a,f) char **a,*f; { return 0; }
+       m_setcur(i) { ; }
+       m_update() { ; }
+int     m_makedir(s) char *s; { return 1; }
+char    *makename(p,s) char *p,*s; { return p; }
+char    *path(n,t) char *n; { return n; }
+int     peekc(i) FILE *i; { return 1; }
+       printsw(s,sw,p) char *s,*p; struct swit *sw; { ; }
+char    *pwd() { return pwd(); }
+char    *r1bindex(s,c) char *s; { return s; }
+int     showfile(f) char *f; { return 1; }
+int     smatch(s,sw) char *s; struct swit *sw; { return 1; }
+char    *trimcpy(s) char *s; { return s; }
+int     type(fd,s) char *s; { return 1; }
+int     uleq(s1,s2) char *s1,*s2; { return 1; }
diff --git a/docs/historical/mh-jun-1982/subs/trimcpy.c b/docs/historical/mh-jun-1982/subs/trimcpy.c
new file mode 100644 (file)
index 0000000..078bea8
--- /dev/null
@@ -0,0 +1,30 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+char *malloc();
+extern char *strcpy();
+
+
+char *trimcpy(cp)
+register char *cp;
+{
+       register char *sp;
+
+       while(*cp == ' ' || *cp == '\t')
+               cp++;
+
+       /* Zap trailing NL */
+       cp[strlen(cp) - 1] = '\0';
+
+       /* Replace embedded NL's with blanks */
+       for(sp = cp; *sp; sp++)
+               if(*sp == '\n')
+                       *sp = ' ';
+       sp = malloc((unsigned)(sp - cp + 1));
+       strcpy(sp, cp);
+       return(sp);
+}
diff --git a/docs/historical/mh-jun-1982/subs/type.c b/docs/historical/mh-jun-1982/subs/type.c
new file mode 100644 (file)
index 0000000..008fe8b
--- /dev/null
@@ -0,0 +1,23 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#include <stdio.h>
+
+type(ch, s)
+char *s;
+{
+       register char *p;
+
+       for (p = s; *p++; );
+       --p;
+       if(write(ch, s, p-s) != p-s) {
+               fprintf(stderr, "type: write error!");
+               perror("");
+               return 0;
+       }
+       return(p-s);
+}
diff --git a/docs/historical/mh-jun-1982/subs/uleq.c b/docs/historical/mh-jun-1982/subs/uleq.c
new file mode 100644 (file)
index 0000000..016a090
--- /dev/null
@@ -0,0 +1,19 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+uleq(c1, c2)
+       register char *c1, *c2;
+{
+       register int c;
+
+       while(c = *c1++)
+               if((c|040) != (*c2|040))
+                       return(0);
+               else
+                       c2++;
+       return(*c2 == 0);
+}
diff --git a/docs/historical/mh-jun-1982/support/MailAliases b/docs/historical/mh-jun-1982/support/MailAliases
new file mode 100644 (file)
index 0000000..df56c53
--- /dev/null
@@ -0,0 +1,13 @@
+; See comments at end of this file
+Everyone: *
+news.*: news
+
+; Blank lines & lines beginning with a ; are ignored.
+; foo: fum      -> simple replacement
+; foo: fum, fie -> list replacement
+; foo: < file   -> list replacement from file
+; foo: = group  -> list replacement from UNIX group
+; foo: *        -> list replacement by ALL users in /etc/passwd
+;                     with uid >= 10
+; foo*: fum     -> matches foo<anything> (incl null)
+
diff --git a/docs/historical/mh-jun-1982/support/Makefile b/docs/historical/mh-jun-1982/support/Makefile
new file mode 100644 (file)
index 0000000..22b0ab0
--- /dev/null
@@ -0,0 +1,38 @@
+#
+#       Proprietary Rand Corporation, 1981.
+#       Further distribution of this software
+#       subject to the terms of the Rand
+#       license agreement.
+#
+
+
+# The following must match entry in ../Makefile
+MHDIR   = /etc/mh
+PROGS   = l c
+
+all:    $(PROGS)
+
+#define TERMCAP in l.c if you have TERMCAP
+#otherwise, you'll have to look at l.c and figure out what you want to do
+#about the things that will be ifdeffed out
+l:      l.c
+       -rm -f l
+       $(CC) -o l $(CFLAGS) -DTERMCAP l.c -ltermcap
+
+c:      l
+       ln l c
+
+install:
+       cd news; make install
+       -install -c ../support/components $(MHDIR)/components
+       -install -c ../support/distcomps $(MHDIR)/distcomps
+       -install -c ../support/mhl.format $(MHDIR)/mhl.format
+
+uninstall:
+       cd news; make uninstall
+       -cd $(MHDIR); rm -f components distcomps mhl.format
+
+distribution: clean
+
+clean:
+       -rm $(PROGS)
diff --git a/docs/historical/mh-jun-1982/support/aliascheck.c b/docs/historical/mh-jun-1982/support/aliascheck.c
new file mode 100644 (file)
index 0000000..d1bd280
--- /dev/null
@@ -0,0 +1,77 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+/*
+ * aliascheck(name) will return an indication of whether name is
+ *  a valid alias from AliasFile.  The return values are:
+ *
+ *      1 -> yes
+ *      0 -> no
+ *     -1 -> an error in the alias file
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+char    *AliasFile =    "/etc/MailAliases";
+
+char *
+parse(ptr, buf)
+       register char *ptr;
+       char *buf;
+{
+       register char *cp = buf;
+
+       while(isalnum(*ptr) || *ptr == '/' || *ptr == '-' ||
+             *ptr == '.' || *ptr == '*')
+               *cp++ = *ptr++;
+       *cp = 0;
+       if(cp == buf)
+               return 0;
+       return buf;
+}
+
+
+aliascheck(name)
+       char *name;
+{
+       register char *pp;
+       char line[256], pbuf[64];
+       register FILE *a;
+
+       if((a = fopen(AliasFile, "r")) == NULL)
+               return -1;
+       while(fgets(line, sizeof line, a)) {
+               if(line[0] == ';' || line[0] == '\n')   /* Comment Line */
+                       continue;
+               if((pp = parse(line, pbuf)) == NULL) {
+                       fclose(a);
+                       return -1;
+               }
+               if(aleq(name, pp)) {
+                       fclose(a);
+                       return 1;
+               }
+       }
+       fclose(a);
+       return 0;
+}
+
+
+aleq(string, aliasent)
+       register char *string, *aliasent;
+{
+       register int c;
+
+       while(c = *string++)
+               if(*aliasent == '*')
+                       return 1;
+               else if((c|040) != (*aliasent|040))
+                       return(0);
+               else
+                       aliasent++;
+       return *aliasent == 0 || *aliasent == '*';
+}
diff --git a/docs/historical/mh-jun-1982/support/components b/docs/historical/mh-jun-1982/support/components
new file mode 100644 (file)
index 0000000..6d4da32
--- /dev/null
@@ -0,0 +1,4 @@
+To:
+Cc:
+Subject:
+-------
diff --git a/docs/historical/mh-jun-1982/support/distcomps b/docs/historical/mh-jun-1982/support/distcomps
new file mode 100644 (file)
index 0000000..b3415f9
--- /dev/null
@@ -0,0 +1,2 @@
+Distribution-to:
+Distribution-cc:
diff --git a/docs/historical/mh-jun-1982/support/l.c b/docs/historical/mh-jun-1982/support/l.c
new file mode 100644 (file)
index 0000000..c156e54
--- /dev/null
@@ -0,0 +1,323 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+/* Added termcap (termlib): BSB:3Com 9/17/80 */
+/* Rewrite for VAX: BSB 9/9/79 */
+/* Compiled with V7 cc: BSB 6/2/79 */
+
+#include <stdio.h>
+#include <sgtty.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#define YES 1
+#define NO  0
+
+#ifdef TERMCAP
+# define CLEARPAGE       { tputs(cl, 1, toutc); putchar('\000'); }
+#else
+# define CLEARPAGE       putchar('\014');
+#endif
+#define discard(io) { io->_cnt = BUFSIZ; io->_ptr = io->_base; }
+
+#define PAUSE  0
+#define NOTIFY 1
+#define CLEAR  2
+#define NOTICLEAR 3
+
+int spage;
+int page;
+short width;
+short noclr = 0;
+short first = 0;
+short numop = 0;
+short wrap = 0;
+short flagctl = 1;
+short ontty = 1;       /* assume we're outputting to a tty     */
+short delflg;          /* a <DEL> was typed.                   */
+char bp[1024];
+char   cl[40];         /* Clear Screen string */
+char   *clp = cl;
+int    toutc();
+
+FILE *fin;
+jmp_buf envir;
+
+main(argc, argv)
+int argc;
+char *argv[];
+{
+       register int i,k;
+       register char *c1, *c2;
+       int j, clrflag;
+       int int2(), getout();
+       struct sgttyb sg;
+       struct stat st;
+       extern char _sibuf[], _sobuf[];
+       extern char *getenv();
+
+#ifdef TERMCAP
+       if((c1 = getenv("TERM")) == NULL)
+               c1 = "aa";                      /* RAND */
+       if(tgetent(bp, c1) != 1) {
+               fprintf(stderr, "l: TERM env not in termcap\n");
+               exit(1);
+       }
+       if((width = tgetnum("co")) == -1 ||
+          (spage = tgetnum("li")) == -1) {
+               fprintf(stderr, "l: Can't find term width/length\n");
+               exit(1);
+       }
+       tgetstr("cl", &clp);
+#else
+       width = 80;
+       spage = 24;
+#endif
+       width--;
+       spage -= 2;
+       if(gtty(1, &sg) == -1) {
+               ontty = 0;
+               flagctl = 0;
+       }
+       c1 = c2 = argv[0];
+       do
+               if(*c1++ == '/')
+                       c2 = c1;
+       while(*c1);
+       if(*c2 == 'c')
+               noclr++;
+       k=0;
+       for( i=1; i<argc; i++ ) {/* look for - args */
+               if(argv[i][0] == '-' ) {
+                       switch( argv[i][1] ) {
+                               case 'c': noclr++; break;
+                               case 'f': first=num(&argv[i][2]); /* set first line */
+                                         break;
+                               case 'n': numop=1; /* set number option */
+                                         break;
+                               case 'l':
+                               case 'p': spage =num(&argv[i][2]); /* set page size */
+                                         break;
+                               case 'w': width =num(&argv[i][2]);
+                                         break;
+                               case 'x': flagctl = !flagctl;
+                                         break;
+                               default:  printf("Unknown switch: %s\n", argv[i]);
+                                         return;
+                       }
+               } else
+                       argv[k++] = argv[i];
+       }
+
+       if (spage<=0)
+               spage = 0x07fffffff;    /* largest positive number! */
+       setbuf(stdout, _sobuf);
+       if(ontty)
+               signal(SIGINT,int2);
+       signal(SIGQUIT,getout);
+       page = spage;
+       if(k == 0) {                    /* filter */
+               if(!setjmp(envir)) {
+                       fin = stdin;
+                       setbuf(fin, _sibuf);
+                       pfile(0);
+               }
+               getout();
+       }
+       j = 0;
+       setjmp(envir);
+       while((i=j++) < k) {
+               page = spage;
+               clrflag = 0;
+               if(fin != NULL) { fclose(fin); fin = NULL; }
+               if(stat(argv[i], &st) == 0 && (st.st_mode&S_IFMT) == S_IFDIR){
+                       printf("%s: Is a directory!\n", argv[i]);
+                       continue;
+               }
+               if((fin = fopen(argv[i],"r")) == NULL) {
+                       printf("Cannot open \"%s\" for reading!\n", argv[i]);
+                       continue;
+               }
+               if(st.st_size == 0) {
+                       printf("File \"%s\" is empty.\n", argv[i]);
+                       continue;
+               }
+               if(k>1) {
+                   if(i && delflg <= 0)
+                       printf("\n\n");
+                   delflg = 0;
+                   if(ontty) {
+                       printf("Press <RETURN> to list \"%s\"\n", argv[i]);
+                       clrflag = 1;
+                   } else
+                       printf(">>>>> File \"%s\"\n", argv[i]);
+               }
+
+               pfile(clrflag);
+       }
+       getout();
+}
+
+int  linpos, line, ct;
+
+pfile(flg)
+{
+       register int c;
+
+       if(flg)
+               nextpage(NOTICLEAR);
+       delflg = -1;
+       line = 1;
+       ct = page;
+       while (line < first)  /* Dcrocker: skip to first line */
+               if((c = getch()) == EOF)
+                       return;
+               else if(c == '\n')
+                       line++;
+       linpos = 0;
+
+       if ((c = getch()) != EOF) {
+               if(!flg && !noclr && ontty)
+                       CLEARPAGE;
+               do
+                       putch(c);
+               while ((c = getch()) != EOF);
+       }
+       fflush(stdout);
+}
+
+num(s)  /* computes the internal form of a number */
+register char *s;       /* bad chars are ignored */
+{
+       register int c, i, sign;
+
+       sign=1;  i=0;
+       while(c = *s++) {
+               if(c=='-' && sign==1) sign = -1;
+               c -= '0';
+               if(c>=0 && c<=9) i=i*10+c;
+       }
+       return(i*sign);
+}
+
+nextpage (clearpage)
+{       char c;
+
+       if(!ontty)
+               return;
+       if (clearpage & NOTIFY)
+               putchar('\007');
+       fflush(stdout);
+       c = 0;
+       while(read(2, &c, 1) && c != '\n') ;
+       if (clearpage & CLEAR && c) {
+               CLEARPAGE;
+               page = spage;
+       } else {
+               page = (spage>>1) + (spage>>3);
+/***            page = spage * .6;              ***/
+       }
+       return;
+}
+
+int2()
+{
+       signal(SIGINT,int2);
+       discard(stdout);
+       if(delflg)
+               putchar('\n');
+       delflg++;
+       longjmp(envir, 1);
+}
+
+int     peekc = -2;
+
+peekch()
+{
+       return(peekc = getch());
+}
+
+getch()
+{
+       register int c;
+
+       if(peekc != -2) {
+               c = peekc;
+               peekc = -2;
+               return(c);
+       };
+       c = getc(fin);
+       if(c != EOF)
+               c &= 0177;
+       return(c);
+}
+
+putch(c)
+register int c;
+{
+               if(linpos == 0 && numop) {
+                       if(!wrap)
+                               printf("%5d\t", line);
+                       else
+                               printf("\t");
+                       linpos += 8;
+               }
+               if(c < 040 || c == 0177) {
+                       switch(c) {
+                       case '\n':
+                               line++;
+                               linpos = 0;
+                               wrap = 0;
+                               putchar(c);
+                               break;
+                       case '\f':
+                               goto npage;
+                       case '\t':
+                               linpos += 8;
+                               linpos &= ~07;
+                               putchar(c);
+                               break;
+                       case '\b': /* ignore backspaces */
+                               break;
+                       default:
+                               if(flagctl) {
+                                       if(c == '\7')
+                                               putchar(c);
+                                       putch('^');
+                                       if(c != 0177)
+                                               c += '@';
+                                       else
+                                               c = 'd';
+                               }
+                               putchar(c);
+                               break;
+                       }
+               }
+               else {
+                       putchar(c);
+                       linpos++;
+               }
+               if(width && linpos >= width && peekch() != '\n') {
+                       putchar('\n'); linpos = 0;
+               }
+               if(linpos == 0 && --ct <= 0) {
+          npage:       nextpage(NOTICLEAR);
+                       ct = page;
+               }
+}
+
+
+getout()
+{
+       exit(0);
+}
+
+toutc(ch)
+{
+       putchar
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/support/mailsys.h b/docs/historical/mh-jun-1982/support/mailsys.h
new file mode 100644 (file)
index 0000000..3b56dc1
--- /dev/null
@@ -0,0 +1,19 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+#define MSGRETTIME      (5*24*60*60)    /* How long to keep trying */
+#define MAILQDIR        "/usr/spool/netmail/"
+#define MAILDROP        "/usr/spool/mail/"
+#define TMAILQDIR       "/usr/spool/mailt/"
+#define MAILLOCKDIR     "/usr/spool/locks/"
+#define MAILALIASES     "/etc/MailAliases"
+
+/* Exit codes from net mailer */
+#define NM_OK        0  /* Delivered */
+#define NM_BAD       1  /* Not delivered to some addresses (perm failure) */
+#define NM_MORE      2  /* Some addresses not yet processed (temp failure) */
+#define NM_BADMORE   3  /* Both of above */
diff --git a/docs/historical/mh-jun-1982/support/mhl.format b/docs/historical/mh-jun-1982/support/mhl.format
new file mode 100644 (file)
index 0000000..ceb4fc7
--- /dev/null
@@ -0,0 +1,29 @@
+ignores=Message-id
+;for pagination, use length=30 or whatever
+width=134,length=0,overflowtext=***>,overflowoffset=0
+ignores=.
+MessageName:nocomponent
+:
+Date:nocomponent,leftadjust
+:
+From:leftadjust,compwidth=6
+To:leftadjust,compwidth=6
+cc:leftadjust,compress,width=80,compwidth=5
+bcc:leftadjust,compress,width=80,compwidth=6
+:
+Subject:leftadjust,width=80,compwidth=9
+Re:leftadjust,width=80,compwidth=4
+In-reply-to:leftadjust,width=80,compwidth=13
+:
+body:nocomponent,width=134,length=0,overflowtext=***>,overflowoffset=0
+:
+width=80,length=0,overflowtext=,overflowoffset=11
+extras:leftadjust,compwidth=11
+:
+reply-to:leftadjust,compwidth=11
+sender:leftadjust,compwidth=11
+received:leftadjust,compwidth=11
+via:leftadjust,compwidth=11
+timestamp:leftadjust,compwidth=11
+mail-from:leftadjust,compwidth=11
+MessageName:noco
\ No newline at end of file
diff --git a/docs/historical/mh-jun-1982/support/news/1char b/docs/historical/mh-jun-1982/support/news/1char
new file mode 100644 (file)
index 0000000..8b13789
--- /dev/null
@@ -0,0 +1 @@
+
diff --git a/docs/historical/mh-jun-1982/support/news/Makefile b/docs/historical/mh-jun-1982/support/news/Makefile
new file mode 100644 (file)
index 0000000..18d4d95
--- /dev/null
@@ -0,0 +1,17 @@
+#
+#       Proprietary Rand Corporation, 1981.
+#       Further distribution of this software
+#       subject to the terms of the Rand
+#       license agreement.
+#
+
+
+NEWSDIR = /usr/news
+
+install:
+       cp 1char           $(NEWSDIR)/.1char
+       cp mh_profile      $(NEWSDIR)/.mh_profile
+       cp mh_receive      $(NEWSDIR)/.mh_receive
+
+uninstall:
+       cd $(NEWSDIR); rm -f .1char .mh_profile .mh_receive
diff --git a/docs/historical/mh-jun-1982/support/news/mh_profile b/docs/historical/mh-jun-1982/support/news/mh_profile
new file mode 100644 (file)
index 0000000..01ecf19
--- /dev/null
@@ -0,0 +1 @@
+Path: /usr/news
diff --git a/docs/historical/mh-jun-1982/support/news/mh_receive b/docs/historical/mh-jun-1982/support/news/mh_receive
new file mode 100755 (executable)
index 0000000..8987b7b
--- /dev/null
@@ -0,0 +1,17 @@
+F=`echo  $4 | sed '
+s/news\.//
+'`
+if [ -d /usr/news/$F ] ; then
+       cat /usr/news/.1char >> /usr/news/.$F
+       /usr/local/file -link -file $1 +/usr/news/$F
+elif [ -d /usr/news/Lost+Found ] ; then
+       /usr/local/file -link -file $1 +/usr/news/Lost+Found
+else
+       mkdir /usr/news/Lost+Found
+       /usr/local/file -link -file $1 +/usr/news/Lost+Found
+fi
+
+
+: BUGS: mail directory must be in /usr/news.
+:       .mh_receive should be a C program that
+:       searches news's .mh_profile for the mail path.
diff --git a/docs/historical/mh-jun-1982/support/putenv.c b/docs/historical/mh-jun-1982/support/putenv.c
new file mode 100644 (file)
index 0000000..1f3e64e
--- /dev/null
@@ -0,0 +1,66 @@
+#ifdef COMMENT
+       Proprietary Rand Corporation, 1981.
+       Further distribution of this software
+       subject to the terms of the Rand
+       license agreement.
+#endif
+
+/*
+ *      putenv(name, arg)
+ *      replaces or adds the `name' entry with "name=arg";
+ *
+ *      Uses malloc() for space for new vector and new entry;
+ *
+ *      Bruce Borden            January 1980
+ *      The Rand Corporation
+ */
+
+#include <stdio.h>
+
+extern  char **environ;
+
+putenv(name, arg)
+char *name, *arg;
+{
+       register int i;
+       register char **ep, **nep, *cp;
+
+       if((cp = (char *) malloc(strlen(name) + strlen(arg) + 2)) == NULL)
+               return(1);
+       strcpy(cp, name);
+       strcat(cp, "=");
+       strcat(cp, arg);
+       for(ep = environ, i = 0; *ep; ep++, i++)
+               if(nvmatch(name, *ep)) {
+                       *ep = cp;
+                       return(0);
+               }
+       if((nep = (char **) malloc((i+2) * sizeof *nep)) == NULL)
+               return(1);
+       for(ep = environ, i = 0; *ep; )
+               nep[i++] = *ep++;
+       nep[i++] = cp;
+       nep[i] = 0;
+       environ = nep;
+       return(0);
+}
+
+/*
+ *     s1 is either name, or name=value
+ *     s2 is name=value
+ *     if names match, return value of s2, else NULL
+ *     used for environment searching: see getenv
+ */
+
+static
+nvmatch(s1, s2)
+register char *s1, *s2;
+{
+
+       while (*s1 == *s2++)
+               if (*s1++ == '=')
+                       return(1);
+       if (*s1 == '\0' && *(s2-1) == '=')
+               return(1);
+       return(0);
+}
diff --git a/docs/historical/mh-jun-1982/support/strings.h b/docs/historical/mh-jun-1982/support/strings.h
new file mode 100644 (file)
index 0000000..4676960
--- /dev/null
@@ -0,0 +1,12 @@
+/*
+ * Type definitions for the strings(3) subroutines.
+ */
+
+char   *strcat();
+char    *strncat();
+char   *strcpy();
+char    *strncpy();
+int     strcmp();
+int     strncmp();
+char   *index();
+char   *rindex();
diff --git a/docs/historical/mh-nov-1983/Makefile b/docs/historical/mh-nov-1983/Makefile
new file mode 100644 (file)
index 0000000..7855432
--- /dev/null
@@ -0,0 +1,13 @@
+#      %M%     %I%     %E%
+#
+DESTDIR=
+
+all:   
+       cd cmds; make ${MFLAGS}
+
+install: all
+       cd cmds; make DESTDIR=${DESTDIR} install
+       cd man; make DESTDIR=${DESTDIR} install
+
+clean:
+       cd cmds; make ${MFLAGS} clean
diff --git a/docs/historical/mh-nov-1983/README b/docs/historical/mh-nov-1983/README
new file mode 100644 (file)
index 0000000..9d034ee
--- /dev/null
@@ -0,0 +1,29 @@
+Title:         MH
+
+Authors:       Bruce Borden
+               Stockton Gaines
+               Norman Shapiro
+
+Help from:     Phyllis Kantar
+               Robert Anderson
+               David Crocker
+
+
+Description:
+
+The user command interface to MH is the UNIX ``shell'' (the standard
+UNIX command interpreter).  Each separable component of message handling,
+such as message composition or message display, is a separate command.
+Each program is driven from and updates a private user environment,
+which is stored as a file between program invocations.  This private
+environment also contains information to ``custom tailor'' MH to the
+individuals's tastes.  MH stores each message as a separate file under
+UNIX, and it utilizes the tree-structured UNIX file system to organize
+groups of files within separate directories or ``folders.''  All of
+the UNIX facilities for dealing with files and directories, such as
+renaming, copying, deleting, cataloging, off-line printing, etc., are
+applicable to messages and directories of messages (folders).  Thus,
+important capabilities needed in a message system are available in MH
+without the need (often seen in other message systems) for code that
+duplicates the facilities of the supporting operating system.  It also
+allows users familiar with the shell to use MH with minimal effort.
diff --git a/docs/historical/mh-nov-1983/cmds/Makefile b/docs/historical/mh-nov-1983/cmds/Makefile
new file mode 100644 (file)
index 0000000..7dbbb51
--- /dev/null
@@ -0,0 +1,214 @@
+#      @(#)Makefile    4.9     (Berkeley)      83/07/07
+#
+# define UCB to get #files instead of ,files
+#
+CFLAGS= -O -DUNIXCOMP -DUCB -I.
+BINDIR= /usr/new/mh
+MHDIR=  /usr/new/lib/mh
+SUBS = ../subs
+STRINGS = ../strings
+PROGS= comp refile folder forw inc install-mh \
+       next news pick prev prompter repl rescue rmf rmm scan \
+       send show unixtomh
+DESTDIR=
+
+all:   ${PROGS}
+
+subs.a: mh.h
+       rm -f ${SUBS}/subs.a subs.a
+       cd ${SUBS}; make
+       ranlib ${SUBS}/subs.a
+       ln -s ${SUBS}/subs.a subs.a
+
+strings.a:
+       rm -f ${STRINGS}/strings.a strings.a
+       cd ${STRINGS}; make
+       ranlib ${STRINGS}/strings.a
+       ln -s ${STRINGS}/strings.a strings.a
+
+comp:   mh.h comp.o subs.a strings.a
+       ${CC} -o comp comp.o subs.a strings.a
+
+refile:   mh.h refile.o subs.a strings.a
+       ${CC} -o refile refile.o subs.a strings.a
+
+folder: mh.h folder.o subs.a strings.a
+       ${CC} -o folder folder.o subs.a strings.a
+
+forw:   mh.h forw.o annotate.o subs.a strings.a
+       ${CC} -o forw forw.o annotate.o subs.a strings.a
+
+inc:    mh.h inc.o scansub.o subs.a strings.a
+       ${CC} -o inc inc.o scansub.o subs.a strings.a
+
+install-mh: mh.h install-mh.o subs.a strings.a
+       ${CC} -o install-mh install-mh.o subs.a strings.a
+
+news:   mh.h news.o subs.a strings.a
+       ${CC} -o news news.o subs.a strings.a
+
+next:   mh.h nexthdr.o next.o subs.a strings.a
+       ${CC} -o next nexthdr.o next.o subs.a strings.a
+
+pick:   mh.h pick.o grep.o subs.a strings.a
+       ${CC} -o pick pick.o grep.o subs.a strings.a
+
+prev:   mh.h prevhdr.o next.o subs.a strings.a
+       ${CC} -o prev prevhdr.o next.o subs.a strings.a
+
+prompter: mh.h prompter.o subs.a strings.a
+       ${CC} -o prompter prompter.o subs.a strings.a
+
+repl:   mh.h reply.o replsubs.o annotate.o subs.a strings.a
+       ${CC} -o repl reply.o replsubs.o annotate.o subs.a strings.a
+
+rescue:        rescue.o emitl.o
+       ${CC} -o rescue rescue.o
+
+rmf:    mh.h rmf.o subs.a strings.a
+       ${CC} -o rmf rmf.o subs.a strings.a
+
+rmm:    mh.h rmm.o subs.a strings.a
+       ${CC} -o rmm rmm.o subs.a strings.a
+
+scan:   mh.h scan.o scansub.o subs.a strings.a
+       ${CC} -o scan scan.o scansub.o subs.a strings.a
+
+send:   mh.h send.o subs.a strings.a
+       ${CC} -o send send.o subs.a strings.a
+
+show:   mh.h show.o subs.a strings.a
+       ${CC} -o show show.o subs.a strings.a
+
+unixtomh: unixtomh.o
+       ${CC} -o unixtomh unixtomh.o subs.a
+
+onceonly:
+       -@if [ ! -f ${DESTDIR}/usr/bin/filetype -a \
+              ! -f ${DESTDIR}/bin/filetype -a -f ${DESTDIR}/bin/file ] ; then \
+               mv ${DESTDIR}/bin/file ${DESTDIR}/bin/filetype; \
+               echo "${DESTDIR}/bin/file => ${DESTDIR}/bin/filetype" ; \
+        else true ; \
+        fi
+       -@if [ ! -f ${DESTDIR}/bin/filetype -a \
+              ! -f ${DESTDIR}/usr/bin/filetype -a \
+                -f ${DESTDIR}/usr/bin/file ] ; then \
+               mv ${DESTDIR}/usr/bin/file ${DESTDIR}/usr/bin/filetype; \
+               echo "${DESTDIR}/usr/bin/file => ${DESTDIR}/usr/bin/filetype"; \
+        else true ; \
+        fi
+       -@if [ ! -f ${DESTDIR}/bin/bellmail -a -f ${DESTDIR}/bin/mail ] ; then \
+               mv ${DESTDIR}/bin/mail ${DESTDIR}/bin/bellmail; \
+               echo "${DESTDIR}/bin/mail => ${DESTDIR}/bin/bellmail" ;\
+        else true ; \
+        fi
+       -@if [ -f ${DESTDIR}/${BINDIR}/comp ] ; then \
+               echo "Collision on ${DESTDIR}/${BINDIR}/comp" ; \
+        else true ; \
+        fi
+#       -@if [ -f ${DESTDIR}/${BINDIR}/dist ] ; then \
+               echo "Collision on ${DESTDIR}/${BINDIR}/dist" ; \
+        else true ; \
+        fi
+#       -@if [ -f ${DESTDIR}/${BINDIR}/file ] ; then \
+               echo "Collision on ${DESTDIR}/${BINDIR}/file" ; \
+        else true ; \
+        fi
+       -@if [ -f ${DESTDIR}/${BINDIR}/folder ] ; then \
+               echo "Collision on ${DESTDIR}/${BINDIR}/folder" ; \
+        else true ; \
+        fi
+       -@if [ -f ${DESTDIR}/${BINDIR}/forw ] ; then \
+               echo "Collision on ${DESTDIR}/${BINDIR}/forw" ; \
+        else true ; \
+        fi
+       -@if [ -f ${DESTDIR}/${BINDIR}/inc  ] ; then \
+               echo "Collision on ${DESTDIR}/${BINDIR}/inc"  ; \
+        else true ; \
+        fi
+#       -@if [ -f ${DESTDIR}/${BINDIR}/mail ] ; then \
+               echo "Collision on ${DESTDIR}/${BINDIR}/mail" ; \
+        else true ; \
+        fi
+       -@if [ -f ${DESTDIR}/${BINDIR}/news ] ; then \
+               echo "Collision on ${DESTDIR}/${BINDIR}/news" ; \
+        else true ; \
+        fi
+       -@if [ -f ${DESTDIR}/${BINDIR}/next ] ; then \
+               echo "Collision on ${DESTDIR}/${BINDIR}/next" ; \
+        else true ; \
+        fi
+       -@if [ -f ${DESTDIR}/${BINDIR}/pick ] ; then \
+               echo "Collision on ${DESTDIR}/${BINDIR}/pick" ; \
+        else true ; \
+        fi
+       -@if [ -f ${DESTDIR}/${BINDIR}/prev ] ; then \
+               echo "Collision on ${DESTDIR}/${BINDIR}/prev" ; \
+        else true ; \
+        fi
+       -@if [ -f ${DESTDIR}/${BINDIR}/prompter ] ; then \
+               echo "Collision on ${DESTDIR}/${BINDIR}/prompter" ; \
+        else true ; \
+        fi
+       -@if [ -f ${DESTDIR}/${BINDIR}/repl ] ; then \
+               echo "Collision on ${DESTDIR}/${BINDIR}/repl" ; \
+        else true ; \
+        fi
+       -@if [ -f ${DESTDIR}/${BINDIR}/rmf  ] ; then \
+               echo "Collision on ${DESTDIR}/${BINDIR}/rmf"  ; \
+        else true ; \
+        fi
+       -@if [ -f ${DESTDIR}/${BINDIR}/rmm  ] ; then \
+               echo "Collision on ${DESTDIR}/${BINDIR}/rmm"  ; \
+         else true ; \
+         fi
+       -@if [ -f ${DESTDIR}/${BINDIR}/scan ] ; then \
+               echo "Collision on ${DESTDIR}/${BINDIR}/scan" ; \
+        else true ; \
+        fi
+       -@if [ -f ${DESTDIR}/${BINDIR}/send ] ; then \
+               echo "Collision on ${DESTDIR}/${BINDIR}/send" ; \
+        else true ; \
+        fi
+       -@if [ -f ${DESTDIR}/${BINDIR}/show ] ; then \
+               echo "Collision on ${DESTDIR}/${BINDIR}/show" ; \
+        else true ; \
+        fi
+       -@if [ -f ${DESTDIR}/${MHDIR} -o -d ${DESTDIR}/${MHDIR} ] ; then \
+            echo "${DESTDIR}/${MHDIR} already exists!"; \
+        else true ; \
+        fi
+
+install:
+       -mkdir ${DESTDIR}/${BINDIR}
+       -mkdir ${DESTDIR}/${MHDIR}
+       install -s -m 1755 comp ${DESTDIR}/${BINDIR}/comp;
+       install -s refile ${DESTDIR}/${BINDIR}/refile;
+       install -s folder ${DESTDIR}/${BINDIR}/folder;
+       install -s forw ${DESTDIR}/${BINDIR}/forw;
+       install -s -m 1755 inc ${DESTDIR}/${BINDIR}/inc;
+       install -s install-mh ${DESTDIR}/${MHDIR}/install-mh;
+       install -s -m 1755 next ${DESTDIR}/${BINDIR}/next;
+       install -s news ${DESTDIR}/${BINDIR}/news;
+       install -s pick ${DESTDIR}/${BINDIR}/pick;
+       install -s prev ${DESTDIR}/${BINDIR}/prev;
+       install -s -m 1755 prompter ${DESTDIR}/${BINDIR}/prompter;
+       install -s repl ${DESTDIR}/${BINDIR}/repl;
+       install -s rmf ${DESTDIR}/${BINDIR}/rmf;
+       install -s rmm ${DESTDIR}/${BINDIR}/rmm;
+       install -s scan ${DESTDIR}/${BINDIR}/scan;
+       install -s send ${DESTDIR}/${BINDIR}/send;
+       install -s -m 1755 show ${DESTDIR}/${BINDIR}/show;
+       install -s unixtomh ${DESTDIR}/${MHDIR}/unixtomh;
+       rm -f ${DESTDIR}/${BINDIR}/folders
+       ln ${DESTDIR}/${BINDIR}/folder ${DESTDIR}/${BINDIR}/folders
+       install -c ../support/components ${DESTDIR}/${MHDIR}/components;
+       install -c ../support/distcomps ${DESTDIR}/${MHDIR}/distcomps;
+
+cleanup:
+       rm -f ${PROGS}
+
+clean:
+       cd ${SUBS}; make ${MFLAG} clean
+       cd ${STRINGS}; make ${MFLAG} clean
+       rm -f ${PROGS} subs.a strings.a *.o
diff --git a/docs/historical/mh-nov-1983/cmds/aliascheck.c b/docs/historical/mh-nov-1983/cmds/aliascheck.c
new file mode 100644 (file)
index 0000000..03d94f6
--- /dev/null
@@ -0,0 +1,209 @@
+#include <stdio.h>
+#include <ctype.h>
+#include <grp.h>
+#include <sys/param.h>
+#include <dir.h>
+
+char    *AliasFile =    "/usr/local/lib/MailAliases";
+char    *Password  =    "/etc/passwd";
+char    *MailDir   =    "/usr/spool/mail";
+
+char *termptr;
+
+struct  mailname {
+       struct mailname *m_next;
+       char            *m_name;
+       int              m_seen;
+}  users, bad;
+
+
+char *parse(ptr, buf)
+register char *ptr;
+char *buf;
+{
+       register char *cp;
+
+       cp = buf;
+       while(isspace(*ptr) || *ptr == ',' || *ptr == ':')
+               ptr++;
+       while(isalnum(*ptr) || *ptr == '/' || *ptr == '-' || *ptr == '.')
+               *cp++ = *ptr++;
+       if(cp == buf) {
+               switch(*ptr) {
+               case '<':
+               case '*':
+               case '=':
+                       *cp++ = *ptr++;
+               }
+       }
+       *cp = 0;
+       if(cp == buf)
+               return 0;
+       termptr = ptr;
+       return buf;
+}
+
+
+char   *mail = 0;
+FILE   *out;
+int     donecd = 0;
+
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       register char *cp, *pp, **cpp;
+       register struct mailname *lp;
+       register struct group *gp;
+       struct direct *dir;
+       DIR *dirp;
+       char line[256], pbuf[64];
+       FILE *a;
+
+       if(argc == 3 && strcmp(argv[1], "-mail") == 0)
+               mail = argv[2];
+       if(!mail)
+               out = stdout;
+       if((a = fopen(Password, "r")) == NULL) {
+               om();
+               fprintf(out, "Can't open password file ");
+               perror(Password);
+               done(1);
+       }
+       while(fgets(line, sizeof line, a)) {
+               if(line[0] == '\n' || line[0] == ';')
+                       continue;
+               cp = parse(line, pbuf);
+               add(cp, &users);
+       }
+       fclose(a);
+       if((a = fopen(AliasFile, "r")) == NULL) {
+               om();
+               fprintf(out, "Can't open alias file: %s\n", AliasFile);
+               donecd = 1;
+       } else {
+               while(fgets(line, sizeof line, a)) {
+                       if(line[0] == '\n' || line[0] == ';')
+                               continue;
+                       cp = parse(line, pbuf);
+                       if(check(cp, 0)) {
+                               add(line, &bad);
+                               donecd = 1;
+                       }
+               }
+               fclose(a);
+               if(donecd < 1) {
+                       if(out)
+                               fprintf(out, "No Alias Inconsistencies.\n");
+               } else {
+                       om();
+                       fprintf(out, "%s :: %s Collisions:\n",
+                               Password, AliasFile);
+                       fprintf(out, "Colliding alias lines:\n");
+                       for(lp = bad.m_next; lp; lp = lp->m_next)
+                               fprintf(out, "%s", lp->m_name);
+                       donecd = 1;
+               }
+       }
+       while(gp = getgrent()) {
+               for(cpp = gp->gr_mem; *cpp; cpp++)
+                       if(!check(*cpp, 1)) {
+                               om();
+                               fprintf(out, "Group: %s--User: %s not in /etc/passwd\n",
+                                       gp->gr_name, *cpp);
+                               donecd = 2;
+                       }
+       }
+       if(donecd < 2 && out)
+               fprintf(out, "No extraneous group entries.\n");
+#ifdef RAND
+       for(lp = users.m_next; lp; lp = lp->m_next)
+               if(lp->m_seen == 0) {
+                       om();
+                       fprintf(out, "User: %s not in a group.\n", lp->m_name);
+                       donecd = 3;
+               }
+       if(donecd < 3 && out)
+               fprintf(out, "No Users not in any group.\n");
+#endif
+       if ((dirp = opendir(MailDir)) == 0) {
+               om();
+               fprintf(out, "Can't open mail directory: %s\n", MailDir);
+               donecd = 4;
+       } else {
+               (void) readdir(dirp);           /* skip . */
+               (void) readdir(dirp);           /* skip .. */
+               while (dir = readdir(dirp)) {
+                       if (!check(dir->d_name, 0)) {
+                               om();
+                               fprintf(out, "Mail drop: %s--Nonexistent user.\n",
+                                       dir->d_name);
+                               donecd = 4;
+                       }
+               }
+               closedir(dirp);
+       }
+       if(donecd < 4 && out)
+               fprintf(out, "No Extra mail drops.\n");
+
+       done(donecd);
+}
+
+
+add(name, list)
+char *name;
+struct mailname *list;
+{
+       register struct mailname *mp;
+       char *getcpy();
+
+       for(mp = list; mp->m_next; mp = mp->m_next)
+               ;
+       mp->m_next = (struct mailname *) malloc(sizeof *mp->m_next);
+       mp = mp->m_next;
+       mp->m_next = 0;
+       mp->m_name = getcpy(name);
+}
+
+check(name, mark)
+       char *name;
+       int mark;
+{
+       register struct mailname *mp;
+
+       for(mp = users.m_next; mp; mp = mp->m_next)
+               if(uleq(name, mp->m_name)) {
+                       if(mark)
+                               mp->m_seen = 1;
+                       return 1;
+               }
+       return 0;
+}
+
+
+om()
+{
+       int pipes[2], child;
+
+       if(out)
+               return;
+       if(mail) {
+               pipe(pipes);
+               out = fdopen(pipes[1], "w");
+               if((child = fork()) == -1) {
+                       fprintf(stderr, "Aliascheck: no forks!\n");
+                       done(1);
+               }
+               if(child == 0) {
+                       close(pipes[1]);
+                       close(0);
+                       dup(pipes[0]);
+                       close(pipes[0]);
+                       execl("/bin/mail", "mail", mail, 0);
+                       execl("/usr/bin/mail", "mail", mail, 0);
+                       perror("mail");
+                       done(1);
+               }
+               fprintf(out, "Aliascheck: ");
+       }
+}
diff --git a/docs/historical/mh-nov-1983/cmds/annotate.c b/docs/historical/mh-nov-1983/cmds/annotate.c
new file mode 100644 (file)
index 0000000..fce8b74
--- /dev/null
@@ -0,0 +1,110 @@
+#ifndef lint
+static char sccsid[] = "@(#)annotate.c 4.1 2/23/83";
+#endif
+
+#include "mh.h"
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+/* annotate file component data
+ *
+ * prepends   Component: data
+ *              date stamp
+ */
+
+annotate(file, comp, text, inplace)
+       char *file, *comp, *text;
+{
+       register int src;
+       register char *cp;
+       register FILE *tmp;
+       int cnt, fd;
+       char buf[BUFSIZ], *sp, tmpfil[128];
+       long now;
+       struct stat stbuf;
+       char *cdate();
+
+       if((src = open((cp = file), 2)) == -1) { /* this should be an X-open*/
+               fprintf(stderr, "Can't open ");
+               perror(cp);
+               return(1);
+       }
+       copy(cp, buf);
+       sp = r1bindex(buf);
+       if(sp != buf) {
+               *sp = 0;
+               cp = copy(buf, tmpfil);
+       } else
+               cp = tmpfil;
+       copy(makename("ano",".tmp"), cp);
+       fstat(src, &stbuf);
+       if((tmp = fopen(tmpfil, "w")) == NULL) {
+               fprintf(stderr, "Can't create ");
+               perror(tmpfil);
+               return(1);
+       }
+       chmod(tmpfil, stbuf.st_mode&0777);
+       cp = comp;
+       if(*cp >= 'a' && *cp <= 'z') *cp -= 040;
+       time(&now);
+       cp = cdate(&now);
+       cp[9] = ' ';  cp[15] = 0;
+       if(*cp == ' ') cp++;
+       fprintf(tmp, "%s: <<%s>>\n", comp, cp);
+       cp = text;
+       do {
+               if(*cp == ' ' || *cp == '\t') cp++;
+               sp = cp;
+               while(*cp && *cp++ != '\n') ;
+               if(cp - sp)
+                       fprintf(tmp, "%s: %*s", comp, cp-sp, sp);
+       } while(*cp);
+       if(cp[-1] != '\n' && cp != text) putc('\n', tmp);
+       do
+               if((cnt = read(src, buf, sizeof buf)) > 0)
+                       fwrite(buf, cnt, 1, tmp);
+       while(cnt == sizeof buf);
+       fclose(tmp);
+       if(inplace) {
+               fd = open(tmpfil, 0);          /* reopen for reading */
+               lseek(src, 0l, 0);
+               do
+                       if((cnt = read(fd, buf, sizeof buf)) > 0)
+                               write(src, buf, cnt);
+               while(cnt == sizeof buf);
+               close(fd);
+       } else {
+          /*   cp = copy(file, buf);           */
+          /*   *--cp =| 0200;                  */
+          /*   copy(".bak", copy(file, buf));  */
+               cp = copy(file, buf);
+               cp[1] = 0;
+               do
+                       *cp = cp[-1];
+               while(--cp >= buf && *cp != '/');
+               *++cp =
+#ifdef UCB
+                       '#';
+#else
+                       ',';
+#endif
+               unlink(buf);
+               if(link(file, buf) == -1) {
+                       fprintf(stderr, "Can't rename %s to bak file.\n", file);
+                       return(1);
+               }
+               if(unlink(file) == -1) {
+                       fprintf(stderr, "Can't unlink %s\n", file);
+                       return(1);
+               }
+               if(link(tmpfil, file) == -1) {
+                       fprintf(stderr, "Can't lnk temp file \"%s\" to %s\n",
+                         tmpfil, file);
+                       return(1);
+               }
+       }
+       close(src);
+       unlink(tmpfil);
+       return(0);
+}
diff --git a/docs/historical/mh-nov-1983/cmds/comp.c b/docs/historical/mh-nov-1983/cmds/comp.c
new file mode 100644 (file)
index 0000000..37a69aa
--- /dev/null
@@ -0,0 +1,163 @@
+#include "mh.h"
+#include <stdio.h>
+#include <strings.h>
+#include <signal.h>
+
+/* #define NEWS 1 */
+#define NONE 0
+
+/* #define TEST 1 */
+
+char *anyul[] = {
+       "no",   0,
+       "yes",  0,
+       "use",  0,
+       "list", 0,
+       0
+};
+
+char *aleqs[] = {
+       "list",              0,         /* 0 */
+       "edit [<editor>]",   0,         /* 1 */
+       "quit [delete]",     0,         /* 2 */
+       "send [verbose]",    0,         /* 3 */
+       0
+};
+
+
+struct swit switches[] = {
+       "editor editor",  0,      /* 0 */
+       "form formfile",  0,      /* 1 */
+       "use",            0,      /* 2 */
+       "nouse",          0,      /* 3 */
+       "help",           4,      /* 4 */
+       0,                0
+};
+
+main(argc, argv)
+char *argv[];
+{
+       register char *cp;
+       register int in, out;
+       int use, cnt, status, intr;
+       char buf[BUFSIZ], *ed, *file, *form;
+       static char path[128];
+       char **ap;
+       char *arguments[50], **argp;
+
+/***    setbuf(stdout, _sobuf); ***/
+#ifdef NEWS
+       m_news();
+#endif
+       form = 0; use = 0; file = 0; ed = 0;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-') {
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);  /* ambiguous */
+                               goto leave;
+                                                       /* unknown */
+                       case -1:fprintf(stderr, "comp: -%s unknown\n", cp);
+                               goto leave;
+                       case 0: if(!(ed = *argp++)) {   /* -editor */
+      missing:  fprintf(stderr, "comp: Missing argument for %s switch\n", argp[-2]);
+                                       goto leave;
+                               }
+                               continue;
+                       case 1: if(!(form = *argp++))   /* -form */
+                                       goto missing;
+                               continue;
+                       case 2: use = 1;  continue;     /* -use */
+                       case 3: use = 0;  continue;     /* -nouse */
+                       case 4: help("comp    [file]  [switches]",
+                                    switches);
+                               goto leave;
+                       }
+               }
+               file = cp;
+       }
+       if(form) {
+               if((in = open(m_maildir(form), 0)) < 0) {
+                       fprintf(stderr, "comp: Can't open form file: %s\n", form);
+                       goto leave;
+               }
+       } else if((in = open(m_maildir(components), 0)) < 0 &&
+                  (in = open(stdcomps, 0)) < 0) {
+                       fprintf(stderr, "comp: Can't open default components file!!\n");
+                       goto leave;
+       }
+       if(!file)
+               file = draft;
+       copy(m_maildir(file), path);
+       if((out = open(path, 0)) >= 0) {
+               cp = concat("\n\"", path, "\" exists; delete? ", 0);
+               if(use || fdcompare(in, out))
+                       goto editit;
+               while((status = gans(cp, anyul)) == 3)
+                               showfile(path);
+               if(status == 2) {
+                       use++;
+                       goto editit;
+               }
+               if(status == 0)
+                       goto leave;
+               close(out);
+       } else if(use) {
+               fprintf(stderr, "comp: \"%s\" doesn't exist!\n", path);
+               goto leave;
+       }
+       if((out = creat(path, m_gmprot())) < 0) {
+               fprintf(stderr, "comp: Can't create \"%s\"\n", path);
+               goto leave;
+       }
+       do
+               if(cnt = read(in, buf, sizeof buf))
+                       write(out, buf, cnt);
+       while(cnt == sizeof buf);
+       close(in);
+editit:
+       close(out);
+       if(m_edit(&ed, path, use, NONE) < 0)
+               goto leave;
+#ifdef TEST
+       fprintf(stderr, "!! Test Version of SEND Being Run !!\n");
+       fprintf(stderr, "   Send verbose !\n\n");
+#endif
+
+    for(;;) {
+       if(!(argp = getans("\nWhat now? ", aleqs)))
+               goto leave;
+       switch(smatch(*argp, aleqs)) {
+               case 0: showfile(path);                         /* list */
+                       break;
+               case 1: if(*++argp)                             /* edit */
+                               ed = *argp;
+                       if(m_edit(&ed, path, use, NONE) == -1)
+                               goto leave;
+                       break;
+               case 2: if(*++argp && *argp[0] == 'd')           /* quit */
+                               if(unlink(path) == -1)  {
+                                       fprintf(stderr, "Can't unlink %s ", path);
+                                       perror("");
+                               }
+                       goto leave;
+               case 3: if(*++argp) cp = *argp;  else cp = "";   /* send */
+                       if(! m_send(cp, path))
+                               goto leave;
+               default:fprintf(stderr, "comp: illegal option\n");       /*##*/
+                       break;
+       }
+    }
+
+leave:
+       m_update();
+       done(0);
+}
+
diff --git a/docs/historical/mh-nov-1983/cmds/deliver.c b/docs/historical/mh-nov-1983/cmds/deliver.c
new file mode 100644 (file)
index 0000000..87d58b4
--- /dev/null
@@ -0,0 +1,883 @@
+#ifndef lint
+static char sccsid[] = "@(#)deliver.c  4.4 9/25/83";
+#endif
+
+#include "mh.h"
+#include <stdio.h>
+#include <ctype.h>
+#include <pwd.h>
+#include <sys/types.h>
+#include <sys/timeb.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <strings.h>
+
+#define        DELIVERMAIL     "/usr/lib/sendmail"
+#define EVERYONE 10
+#define RECVPROG "/.mh_receive"
+#define FCCS    10      /* Max number of fcc's allowed */
+
+struct shome {          /* Internal name/uid/home database */
+       struct shome *h_next;
+       char *h_name;
+       int   h_uid;
+       int   h_gid;
+       char *h_home;
+} *homes, *home();
+
+struct swit switches[] = {
+       "debug",         -1,      /* 0 */
+       "format",         0,      /* 1 */
+       "noformat",       0,      /* 2 */
+       "msgid",          0,      /* 3 */
+       "nomsgid",        0,      /* 4 */
+       "verbose",        0,      /* 5 */
+       "noverbose",      0,      /* 6 */
+       "help",           4,      /* 7 */
+       0,                0
+};
+
+int     verbose, format, msgid, debug, myuid, addrp;
+int     lockwait;       /* Secs to wait for mail lock (From strings/lockdir.c) */
+#define LOCKWAIT (lockwait * 5) /* Ignore lock if older than this */
+int     donecd;
+long    now;
+char    tmpfil[32], fccfold[FCCS][128];
+char   tmp2fil[32];
+int     fccind;
+char   *rindex();
+
+struct  mailname {
+       struct mailname *m_next;
+       char            *m_name;
+}  addrlist;
+
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       register char *cp, *addrs, **argp;
+       register struct mailname *lp;
+       char buf[BUFSIZ], name[NAMESZ];
+       char *msg;
+       int state, compnum, fd;
+       FILE *in, *out;
+       char *getname();
+
+       msg = 0;
+       argp = argv + 1;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               done(1);
+                                                       /* unknown */
+                       case -1:fprintf(stderr, "sndmsg: -%s unknown switch.\n", cp);
+                               done(1);
+                       case 0: verbose++; debug++; continue; /* -debug */
+                       case 1: fprintf(stderr, "Deliver: -format not yet.\n");
+                               done(1);
+/***                    case 1: format = 1; continue;         /* -format */
+                       case 2: format = 0; continue;         /* -noformat */
+                       case 3: msgid = 1;  continue;         /* -msgid */
+                       case 4: msgid = 0;  continue;         /* -nomsgid */
+                       case 5: verbose = 1; continue;        /* -verbose */
+                       case 6: verbose = 0; continue;        /* -noverbose */
+                       case 7: help("deliver [switches] file",
+                                    switches);
+                               done(1);
+                       }
+               if(msg) {
+                       fprintf(stderr, "Deliver: Only one message at a time!\n");
+                       done(1);
+               } else
+                       msg = cp;
+       }
+       if(!msg) {
+               fprintf(stderr, "Deliver: No Message specified.\n");
+               fprintf(stderr, "Deliver: Usage: deliver [switches] file\n");
+               done(1);
+       }
+       if((in = fopen(msg, "r")) == NULL) {
+               fprintf(stderr, "Deliver: Can't open ");
+               perror(msg);
+               done(1);
+       }
+       copy(makename("locs", ".tmp"), copy("/tmp/", tmpfil));
+       if(!debug) {
+               if((out = fopen(tmpfil, "w")) == NULL) {
+                       fprintf(stderr, "Can't create %s\n", tmpfil);
+                       done(1);
+               }
+               chmod(tmpfil, 0744);
+       } else
+               out = stdout;
+
+       gethomes();
+       myuid = getuid();
+#ifndef UNIXCOMP
+       putdate(0, out);           /* Tack on the date */
+       putfrom(out);           /* Tack on the from */
+#endif
+       putmsgid(out);          /* and msg id if desired */
+       for(addrs = 0, compnum = 1, state = FLD;;) {
+               state = m_getfld(state, name, buf, sizeof buf, in);
+   swt:         switch(state) {
+
+               case FLD:
+               case FLDEOF:
+               case FLDPLUS:
+                       compnum++;
+                       if(uleq(name, "to") || uleq(name, "cc") ||
+                          uleq(name, "bcc"))
+                               addrs = add(buf, addrs);
+                       if(!uleq(name, "bcc")) {
+                               cp = buf;
+                               while(*cp == ' ' || *cp == '\t')
+                                       cp++;
+                               fprintf(out, "%s: %s", name, cp);
+                               if(uleq(name, "fcc")) {
+                                       if(fccind >= FCCS) {
+                                               fprintf(stderr, "Deliver: too many fcc's.\n");
+                                               done(1);
+                                       }
+                                       copy(cp, fccfold[fccind]);
+                                       if(cp = rindex(fccfold[fccind], '\n'))
+                                               *cp = 0;
+                                       fccind++;
+                               }
+                       }
+                       while(state == FLDPLUS || state == FLDEOF) {
+                               state = m_getfld(state, name, buf, sizeof buf, in);
+                               addrs = add(buf, addrs);
+                               fputs(buf, out);
+                       }
+                       if(state == FLDEOF)
+                               goto process;
+                       break;
+
+               case BODY:
+               case BODYEOF:
+                       fprintf(out, "\n%s", buf);
+                       while(state == BODY) {
+                               state=m_getfld(state,name,buf,sizeof buf,in);
+                               fputs(buf, out);
+                       }
+
+               case FILEEOF:
+                       goto process;
+
+               case LENERR:
+               case FMTERR:
+                       fprintf(stderr, "??Message Format Error ");
+                       fprintf(stderr, "in Component #%d.\n", compnum);
+                       done(1);
+
+               default:
+                       fprintf(stderr, "Getfld returned %d\n", state);
+                       done(1);
+               }
+       }
+process:
+       if(!debug)
+               fclose(out);
+       else
+               printf("-----\n");
+       fclose(in);
+       while(cp = getname(addrs))      /* Put addrs in chain */
+               insert(cp);
+       if(debug) {
+               printf("Before alias(): "); pl();
+       }
+
+       alias();                        /* Map names if needed */
+
+       for(lp = addrlist.m_next; lp; lp = lp->m_next) {
+#ifdef UNIXCOMP
+               if (netname(lp->m_name))
+                       continue;
+#endif
+#ifndef DELIVERMAIL
+               if(home(lp->m_name) == NULL) {
+                       fprintf(stderr, "Deliver: Unknown User: %s.\n", lp->m_name);
+                       fprintf(stderr, "Deliver: Message Not Delivered.\n");
+                       if(!debug)
+                               unlink(tmpfil);
+                       done(1);
+               }
+#endif DELIVERMAIL
+       }
+       if(debug) {
+               printf("Addrs: "); pl();
+       }
+
+       signal(SIGINT, SIG_IGN);
+       signal(SIGQUIT, SIG_IGN);
+       if(!debug) {                    /* Send the mail */
+               fd = open(tmpfil, 0);
+               for(lp = addrlist.m_next; lp; lp = lp->m_next)
+                       sendmail(lp->m_name, fd);
+               stflush(fd);
+               close(fd);
+               if(fccind) {
+#ifdef UNIXCOMP
+                       strcpy(tmp2fil, "/tmp/mhFXXXXXX");
+                       mktemp(tmp2fil);
+                       out = fopen(tmp2fil, "w");
+                       putdate(0, out);           /* Tack on the date */
+                       putfrom(out);           /* Tack on the from */
+                       appendfile(tmpfil, out);
+                       fclose(out);
+                       for(state = 0; state < fccind; state++)
+                               fcc(tmp2fil, fccfold[state]);
+                       unlink(tmp2fil);
+#else
+                       for(state = 0; state < fccind; state++)
+                               fcc(tmp2fil, fccfold[state]);
+#endif
+               }
+               unlink(tmpfil);
+       }
+       done(donecd);
+}
+
+#ifdef UNIXCOMP
+
+appendfile(name, fout)
+       char name[];
+       register FILE *fout;
+{
+       register int c;
+       register FILE *fin;
+
+       if ((fin = fopen(name, "r")) == NULL) {
+               perror(name);
+               return;
+       }
+       while ((c = getc(fin)) != EOF)
+               putc(c, fout);
+       fclose(fin);
+}
+
+netname(name)
+       char name[];
+{
+       register char *cp;
+       char *index();
+
+       cp = name;
+       if (index(cp, ':') || index(cp, '!') ||
+           index(cp, '@') || index(cp, '^'))
+               return(1);
+       return(0);
+}
+#endif
+
+
+gethomes()
+{
+       register struct passwd *pw;
+       register struct shome *h, *ph;
+       struct passwd *getpwent();
+
+       ph = (struct shome *) &homes;
+       while((pw = getpwent()) != NULL) {
+               h = (struct shome *) malloc(sizeof *h);
+               h->h_next = NULL;
+               h->h_name = (char *) malloc(strlen(pw->pw_name)+1);
+               strcpy(h->h_name, pw->pw_name);
+               h->h_uid = pw->pw_uid;
+               h->h_gid = pw->pw_gid;
+               h->h_home = (char *) malloc(strlen(pw->pw_dir)+1);
+               strcpy(h->h_home, pw->pw_dir);
+               ph->h_next = h;
+               ph = h;
+       }
+}
+
+
+struct shome *
+home(name)
+       register char *name;
+{
+       register struct shome *h;
+
+       for(h = homes; h; h = h->h_next)
+               if(uleq(name, h->h_name))
+                       return(h);
+       return(NULL);
+}
+
+
+char *
+getname(addrs)
+       char *addrs;
+{
+       register char *tp;
+       static char name[32];
+       static char *getaddrs;
+
+       if(!getaddrs)
+               getaddrs = addrs;
+       tp = name;
+
+       while(*getaddrs && !isalpha(*getaddrs))
+               getaddrs++;
+       if(!*getaddrs) {
+               getaddrs = 0;
+               return NULL;
+       }
+#ifdef UNIXCOMP
+       while(!isspace(*getaddrs))
+               *tp++ = *getaddrs++;
+#else
+       while(isalnum(*getaddrs) || index(".:@/-", *getaddrs))
+               *tp++ = *getaddrs++;
+#endif
+       *tp = 0;
+       if(name[0] == 0)
+               return NULL;
+       return name;
+}
+
+char *bracket = "\1\1\1\1\n";
+
+sendmail(name, fd)              /* Runs with signals ignored! */
+       char *name;
+       register int fd;
+{
+       char buf[BUFSIZ], *myname;
+       register int i, m, c;
+       register char *mail, *receive, *lock = 0;
+       register struct shome *h;
+       int pid, status;
+       struct stat stbuf;
+
+       if(verbose) {
+               printf("%s: ", name);
+               fflush(stdout);
+       }
+       lseek(fd, 0l, 0);
+       h = home(name);
+
+       /*
+        * If no home for this user, as in network address
+        * being forced down this path, just assume normal
+        * delivery
+        */
+
+       if (h == NULL)
+               goto force;
+
+       mail = concat(mailboxes, h->h_name, 0);
+/***    mail = concat(h->h_home, mailbox, 0);           ***/
+       receive = concat(h->h_home, RECVPROG, 0);
+       if(access(receive, 1) == 0) {   /* User has a receive prog */
+
+               calluserprog(receive, mail, fd, h);
+
+       } else {
+
+force:
+
+#ifdef UNIXCOMP
+#ifdef DELIVERMAIL
+               nstash(name);
+               if (verbose)
+                       printf("Sent.\n");
+               return;
+#endif DELIVERMAIL
+#ifndef DELIVERMAIL
+               myname = getenv("USER");
+               if (myname == (char *) 0)
+                       myname = "nobody";
+               pid = fork();
+               switch (pid) {
+               case 0:
+                       /* fiddle with files, then . . . */
+                       lseek(fd, 0L, 0);
+                       close(0);
+                       dup(fd);
+                       close(fd);
+                       execl(Mailprog, "Mail", "-r", myname, name, 0);
+                       execl("/bin/mail", "mail", "-r", myname, name, 0);
+                       perror(Mailprog);
+                       _exit(1);
+               
+               case -1:
+                       perror("fork");
+                       return;
+
+               default:
+                       while (wait(&status) != pid)
+                               ;
+               }
+#endif DELIVERMAIL
+#endif UNIXCOMP
+#ifndef UNIXCOMP
+               if((m = open(mail, 2)) < 0) {
+                       if((m = creat(mail, 0600)) < 0) {
+                               fprintf(stderr, "Deliver: Can't write ");
+                               perror(mail);
+                               goto out;
+                       }
+                       chown(mail, h->h_uid, h->h_gid);
+                       if(verbose) {
+                               fprintf(stderr, "Creating %s ", mail);
+                               fflush(stdout);
+                       }
+               }
+               lock = concat(lockdir, h->h_name, ".lock", 0);
+               for(i = 0; i < lockwait; i += 2) {
+                       if(link(mail, lock) >= 0)
+                               break;
+                       if(i == 0 && stat(mail, &stbuf) >= 0 &&
+                          stbuf.st_ctime + LOCKWAIT < time((long *) 0)) {
+                               i = lockwait;
+                               break;
+                       }
+                       if(verbose) {
+                               printf("Busy ");
+                               fflush(stdout);
+                       }
+                       sleep(2);
+               }
+               if(i >= lockwait) {
+                       unlink(lock);
+                       if(verbose) {
+                               printf("Removing lock. ");
+                               fflush(stdout);
+                       }
+                       if(link(mail, lock) < 0) {
+                               fprintf(stderr, "Can't lock %s to %s\n",
+                                       mail, lock);
+                               donecd = 1;
+                               goto out1;
+                       }
+               }
+               lseek(m, 0l, 2);
+               write(m, bracket, 5);
+               do
+                       if((c = read(fd, buf, sizeof buf)) > 0)
+                               if(write(m, buf, c) != c) {
+                                       fprintf(stderr, "Write error on ");
+                                       perror(mail);
+                                       donecd = 1;
+                                       goto out1;
+                               }
+               while(c == sizeof buf);
+               write(m, bracket, 5);
+out1:           close(m);
+out:            cndfree(mail);
+               if(lock) {
+                       unlink(lock);
+                       cndfree(lock);
+               }
+#endif UNIXCOMP
+       }
+       if(verbose && !donecd)
+               printf("Sent.\n");
+}
+
+#ifdef DELIVERMAIL
+
+/*
+ * Salt away a name to send to, ultimately.
+ */
+
+char   *stashname[100];
+char   **stashp;
+
+nstash(name)
+       char name[];
+{
+       register char *cp;
+
+       cp = (char *) calloc(1, strlen(name) + 1);
+       strcpy(cp, name);
+       if (stashp == 0) {
+               stashp = stashname;
+               *stashp++ = "sendmail";
+               *stashp++ = "-i";
+               if (verbose)
+                       *stashp++ = "-v";
+       }
+       *stashp++ = cp;
+}
+
+stflush(fd)
+{
+       int pid;
+
+       if (stashp == 0)
+               return;
+       while ((pid = fork()) == -1)
+               sleep(2);
+       if (pid == 0) {
+               signal(SIGHUP, SIG_IGN);
+               signal(SIGINT, SIG_IGN);
+               signal(SIGQUIT, SIG_IGN);
+               close(0);
+               dup(fd);
+               close(fd);
+               execv(DELIVERMAIL, stashname);
+               perror(DELIVERMAIL);
+               _exit(1);
+       }
+}
+#endif
+
+putfrom(out)
+       register FILE *out;
+{
+       register struct shome *h;
+
+       for(h = homes; h; h = h->h_next)
+               if(h->h_uid == myuid) {
+                       fprintf(out, "From: %s\n", h->h_name);
+                       return;
+               }
+       fprintf(stderr, "Deliver: WHO ARE YOU?\n");
+       done(1);
+}
+
+
+putmsgid(sp)
+       FILE *sp;
+{
+
+       if(!msgid)
+               return;
+       if(!now)
+               time(&now);
+       fprintf(sp, "Message-ID: <%u.%u.%ld.%s@%s>\n", getpid(), myuid,
+           now, localname, hostname);
+}
+
+/***/
+pl()
+{
+       register struct mailname *mp;
+
+       for(mp = addrlist.m_next; mp; mp=mp->m_next)
+               printf("%s%s", mp->m_name, mp->m_next?", ":"");
+       printf("\n");
+}
+/***/
+
+insert(name)
+       char *name;
+{
+       register struct mailname *mp;
+       char *getcpy();
+
+/***    printf("insert(%s)\n", name);   ***/
+
+       for(mp = &addrlist; mp->m_next; mp = mp->m_next)
+               if(uleq(name, mp->m_next->m_name))
+                       return;         /* Don't insert existing name! */
+       mp->m_next = (struct mailname *) malloc(sizeof *mp->m_next);
+       mp = mp->m_next;
+       mp->m_next = 0;
+       mp->m_name = getcpy(name);
+}
+
+
+/* alias implementation below...
+ */
+
+
+
+#define GROUP   "/etc/group"
+char    *AliasFile =    "/usr/local/lib/MailAliases";
+
+char *termptr;
+
+char *
+parse(ptr, buf)
+       register char *ptr;
+       char *buf;
+{
+       register char *cp;
+
+       cp = buf;
+       while(isspace(*ptr) || *ptr == ',' || *ptr == ':')
+               ptr++;
+       while(isalnum(*ptr) || *ptr == '/' || *ptr == '-' ||
+             *ptr == '.' || *ptr == '*')
+               *cp++ = *ptr++;
+       if(cp == buf) {
+               switch(*ptr) {
+               case '<':
+               case '=':
+                       *cp++ = *ptr++;
+               }
+       }
+       *cp = 0;
+       if(cp == buf)
+               return 0;
+       termptr = ptr;
+       return buf;
+}
+
+char *
+advance(ptr)
+       register char *ptr;
+{
+       return(termptr);
+}
+
+alias()
+{
+       register char *cp, *pp;
+       register struct mailname *lp;
+       char line[256], pbuf[64];
+       FILE *a;
+
+       if((a = fopen(AliasFile, "r")) == NULL)
+               return;
+       while(fgets(line, sizeof line, a)) {
+               if(line[0] == ';' || line[0] == '\n')   /* Comment Line */
+                       continue;
+               if((pp = parse(line, pbuf)) == NULL) {
+           oops:       fprintf(stderr, "Bad alias file %s\n", AliasFile);
+                       fprintf(stderr, "Line: %s", line);
+                       done(1);
+               }
+               for(lp = &addrlist; lp->m_next; lp = lp->m_next) {
+                       if(aleq(lp->m_next->m_name, pp)) {
+                               remove(lp);
+                               if(!(cp = advance(line)) ||
+                                  !(pp = parse(cp, pbuf)))
+                                       goto oops;
+                               switch(*pp) {
+                               case '<':       /* From file */
+                                       cp = advance(cp);
+                                       if((pp = parse(cp, pbuf)) == NULL)
+                                               goto oops;
+                                       addfile(pp);
+                                       break;
+                               case '=':       /* UNIX group */
+                                       cp = advance(cp);
+                                       if((pp = parse(cp, pbuf)) == NULL)
+                                               goto oops;
+                                       addgroup(pp);
+                                       break;
+                               case '*':       /* ALL Users */
+                                       addall();
+                                       break;
+                               default:        /* Simple list */
+                                       for(;;) {
+                                               insert(pp);
+                                               if(!(cp = advance(line)) ||
+                                                  !(pp = parse(cp, pbuf)))
+                                                       break;
+                                       }
+                               }
+                               break;
+                       }
+               }
+       }
+}
+
+
+addfile(file)
+       char *file;
+{
+       register char *cp, *pp;
+       char line[128], pbuf[64];
+       FILE *f;
+
+/***    printf("addfile(%s)\n", file);          ***/
+       if((f = fopen(file, "r")) == NULL) {
+               fprintf(stderr, "Can't open ");
+               perror(file);
+               done(1);
+       }
+       while(fgets(line, sizeof line, f)) {
+               cp = line;
+               while(pp = parse(cp, pbuf)) {
+                       insert(pp);
+                       cp = advance(cp);
+               }
+       }
+       fclose(f);
+}
+
+addgroup(group)
+       char *group;
+{
+       register char *cp, *pp;
+       int found = 0;
+       char line[128], pbuf[64], *rindex();
+       FILE *f;
+
+/***    printf("addgroup(%s)\n", group);        ***/
+       if((f = fopen(GROUP, "r")) == NULL) {
+               fprintf(stderr, "Can't open ");
+               perror(GROUP);
+               done(1);
+       }
+       while(fgets(line, sizeof line, f)) {
+               pp = parse(line, pbuf);
+               if(strcmp(pp, group) == 0) {
+                       cp = rindex(line, ':');
+                       while(pp = parse(cp, pbuf)) {
+                               insert(pp);
+                               cp = advance(cp);
+                       }
+                       found++;
+               }
+       }
+       if(!found) {
+               fprintf(stderr, "Group: %s non-existent\n", group);
+               done(1);
+       }
+       fclose(f);
+}
+
+addall()
+{
+       register struct shome *h;
+
+/***    printf("addall()\n");                   ***/
+       for(h = homes; h; h = h->h_next)
+               if(h->h_uid >= EVERYONE)
+                       insert(h->h_name);
+}
+
+remove(mp)              /* Remove NEXT from argument node! */
+       register struct mailname *mp;
+{
+       register struct mailname *rp;
+
+       rp = mp->m_next;
+       mp->m_next = rp->m_next;
+       cndfree(rp->m_name);
+       cndfree(rp);
+}
+
+int     alarmed;
+
+alarmclock()
+{
+       alarmed++;
+}
+
+extern  char **environ;
+char   envhome[60] = "HOME=";
+char   envname[60] = "NAME=";
+char   *envinit[] = {envhome, envname, (char *) 0};
+
+calluserprog(prog, mail, fd, h)
+       char *prog, *mail;
+       int fd;
+       register struct shome *h;
+{
+       register int pid, child, i;
+       int status;
+
+       if(verbose) {
+               printf("Invoking %s ", prog);
+               fflush(stdout);
+       }
+       i = 0;
+       while((child = fork()) == -1)
+               if(++i > 10) {
+                       fprintf(stderr, "Can't get a fork to invoke %s!\n",
+                               prog);
+                       donecd = 1;
+                       return;
+               } else
+                       sleep(2);
+       if(child == 0) {                /* In child... */
+               if(fd != 3)
+                       dup2(fd, 3);
+               for(i = 4; i < 15; i++)
+                       close(i);
+               strcat(envname, h->h_name);
+               strcat(envhome, h->h_home);
+               environ = envinit;
+               setgid(h->h_gid);
+               setuid(h->h_uid);
+               execlp(prog, prog, tmpfil, mail, h->h_home, 0);
+               perror(prog);
+               done(-1);
+       }
+       signal(SIGALRM, alarmclock);
+       alarmed = 0;
+       alarm(30);                      /* Give receive proc 30 secs */
+       status = 0;
+       while((pid = wait(&status)) != -1 && pid != child && !alarmed) ;
+       if(alarmed) {
+               kill(0, SIGINT);
+               signal(SIGALRM, alarmclock);
+               alarmed = 0;
+               alarm(30);
+               while((pid = wait(&status)) != -1 && pid != child && !alarmed) ;
+               if(alarmed) {
+                       kill(child, SIGKILL);
+                       signal(SIGALRM, alarmclock);
+                       alarmed = 0;
+                       alarm(30);
+                       while((pid = wait(&status)) != -1 && pid != child && !alarmed) ;
+               }
+               fprintf(stderr, "Deliver: Killed %s--Took more than 30 seconds!\n",
+                       prog);
+               donecd = 1;
+               status = 0;
+       } else
+               alarm(0);
+       if(status) {
+               printf("Deliver: %s error %d from %s on delivery to %s\n",
+                       status&0377? "System" : "User",
+                       status&0377? status&0377 : status>>8,
+                       prog, h->h_name);
+               donecd = 1;
+       }
+       if(pid == -1) {
+               fprintf(stderr, "Deliver: wait on receive process returned -1\n");
+               perror("");
+               donecd = 1;
+       }
+}
+
+aleq(string, aliasent)
+       register char *string, *aliasent;
+{
+       register int c;
+
+       while(c = *string++)
+               if(*aliasent == '*')
+                       return 1;
+               else if((c|040) != (*aliasent|040))
+                       return(0);
+               else
+                       aliasent++;
+       return(*aliasent == 0 | *aliasent == '*');
+}
+
+fcc(file, folder)
+       char *file, *folder;
+{
+       int child, pid, status;
+       char fold[128];
+
+       if(verbose) {
+               printf("Fcc: %s...", folder);
+               fflush(stdout);
+       }
+       while((child = fork()) == -1) sleep(5);
+       if(child == 0) {
+               if(*file != '+')
+                       strcpy(fold, "+");
+               strcat(fold, folder);
+               setuid(myuid);
+               execl(fileproc, "file", "-link", "-file", file, fold, 0);
+               exit(-1);
+       } else while((pid = wait(&status)) != -1 && pid != child) ;
+       if(status)
+               fprintf(stderr, "Deliver: Error on fcc to %s\n", folder);
+       else if(verbose)
+               putchar('\n');
+}
diff --git a/docs/historical/mh-nov-1983/cmds/dist.c b/docs/historical/mh-nov-1983/cmds/dist.c
new file mode 100644 (file)
index 0000000..76ea486
--- /dev/null
@@ -0,0 +1,295 @@
+#ifndef lint
+static char sccsid[] = "@(#)dist.c     4.1 2/23/83";
+#endif
+
+#include "mh.h"
+#include <stdio.h>
+#include <signal.h>
+#include <strings.h>
+
+#define NONE 0
+#define NOUSE 0
+
+/* #define TEST 1 */
+
+char    *anyl[] = {
+       "no",   0,
+       "yes",  0,
+       "list", 0,
+       0,
+};
+
+char    *anyv[] = {
+       "no",           0,
+       "yes",          0,
+       "verbose",      0,
+       0,
+};
+
+char    *aleqs[] = {
+       "list",              0,         /* 0 */
+       "edit [<editor>]",   0,         /* 1 */
+       "quit [delete]",     0,         /* 2 */
+       "send [verbose]",    0,         /* 3 */
+       0
+};
+
+struct msgs *mp;
+char drft[128];
+char *vec[MAXARGS];
+int inplace;            /* preserve links in anno */
+
+struct swit switches[] = {
+       "annotate",           0,      /* 0 */
+       "noannotate",         0,      /* 1 */
+       "editor editor",      0,      /* 2 */
+       "form formfile",      0,      /* 3 */
+       "inplace",            0,      /* 4 */
+       "noinplace",          0,      /* 5 */
+       "help",               4,      /* 6 */
+       0,                    0
+};
+
+main(argc, argv)
+char *argv[];
+{
+       char *folder, *maildir, *msgs[100], *ed, *form;
+       register int msgnum;
+       register char *cp, **ap;
+       int msgp, anot, curf;
+       int in, out, intr;
+       int pid, wpid, status;
+       char *arguments[50], **argp;
+
+#ifdef NEWS
+       m_news();
+#endif
+       anot = 0; folder = 0; curf = 0; msgp = 0; ed = 0; form = 0;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                            /* unknown */
+                       case -1:fprintf(stderr, "dist: -%s unknown\n", cp);
+                               goto leave;
+                       case 0: anot = 1;  continue;         /* -annotate */
+                       case 1: anot = 0;  continue;         /* -noannotate */
+                       case 2: if(!(ed = *argp++)) {        /* -editor */
+      missing:  fprintf(stderr, "dist: Missing argument for %s switch\n", argp[-2]);
+                                       goto leave;
+                               }
+                               continue;
+                       case 3: if(!(form = *argp++))        /* -form */
+                                       goto missing;
+                               continue;
+                       case 4: inplace = 1;  continue;      /* -inplace */
+                       case 5: inplace = 0;  continue;      /* -noinplace */
+                                                            /* -help */
+                       case 6: help("dist   [+folder] [msg] [switches]",
+                                    switches);
+                               goto leave;
+                       }
+               if(*cp == '+') {
+                       if(folder) {
+                               fprintf(stderr, "Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               folder = cp + 1;
+               } else
+                       msgs[msgp++] = cp;
+       }
+       if(!msgp)
+               msgs[msgp++] = "cur";
+       if(!folder)
+               folder = m_getfolder();
+       maildir = m_maildir(folder);
+       if(chdir(maildir) < 0) {
+               fprintf(stderr, "Can't chdir to: ");
+               perror(maildir);
+               goto leave;
+       }
+       if(!(mp = m_gmsg(folder))) {
+               fprintf(stderr, "Can't read folder!?\n");
+               goto leave;
+       }
+       if(mp->hghmsg == 0) {
+               fprintf(stderr, "No messages in \"%s\".\n", folder);
+               goto leave;
+       }
+       for(msgnum = 0; msgnum < msgp; msgnum++)
+               if(!m_convert((cp = msgs[msgnum])))
+                       goto leave;
+       if(mp->numsel == 0) {
+               fprintf(stderr, "dist: Tuna Melt\n");     /* never get here */
+               goto leave;
+       }
+       if(mp->numsel > 1) {
+               fprintf(stderr, "Only one message at a time.\n");
+               goto leave;
+       }
+       if(form) {
+               if((in = open(m_maildir(form), 0)) < 0) {
+                       fprintf(stderr, "dist: Can't open form file: %s\n", form);
+                       goto leave;
+               }
+       } else if(/***(in = open(m_maildir(distcomps), 0)) < 0 &&      ***/
+                  (in = open(stddcomps, 0)) < 0) {
+                       fprintf(stderr, "dist: Can't open default components file!!\n");
+                       goto leave;
+       }
+       copy(m_maildir(draft), drft);
+       if((out = open(drft, 0)) >= 0) {
+               if(!fdcompare(in, out)) {
+                       cp = concat("\"", drft, "\" exists; Delete? ", 0);
+                       while((msgnum = gans(cp, anyl)) == 2)
+                               showfile(drft);
+                       if(!msgnum)
+                               return;
+               }
+               close(out);
+       }
+       if((out = creat(drft, m_gmprot())) < 0) {
+               fprintf(stderr, "Can't create \"%s\"\n", drft);
+               goto leave;
+       }
+       cpydata(in, out);
+       close(in);
+       if((in = open(cp = m_name(mp->lowsel), 0)) < 0) {
+               fprintf(stderr, "Can't open message \"%s\"\n", cp);
+               unlink(drft);
+               goto leave;
+       }
+       cpydata(in, out);
+       close(in);
+       close(out);
+       m_replace(pfolder, folder);
+       if(mp->lowsel != mp->curmsg)
+               m_setcur(mp->lowsel);
+       if(m_edit(&ed, drft, NOUSE, NONE) < 0)
+               goto leave;
+#ifdef TEST
+       fprintf(stderr, "!! Test Version of SEND Being Run !!\n");
+       fprintf(stderr, "   Send verbose !\n\n");
+#endif
+
+    for(;;) {
+       if(!(argp = getans("\nWhat now? ", aleqs)))
+               goto leave;
+       switch(smatch(*argp, aleqs)) {
+               case 0: showfile(drft);                         /* list */
+                       break;
+               case 1: if(*++argp)                             /* edit */
+                               ed = *argp;
+                       if(m_edit(&ed, drft, NOUSE, NONE) == -1)
+                               goto leave;
+                       break;
+               case 2: if(*++argp && *argp[0] == 'd')          /* quit */
+                               if(unlink(drft) == -1)  {
+                                       fprintf(stderr, "Can't unlink %s ", drft);
+                                       perror("");
+                               }
+                       goto leave;
+               case 3: if(*++argp) cp = *argp;  else cp = "";  /* send */
+
+                       if(!mp->msgflags&READONLY) {    /* annotate first */
+                           if(anot > 0) {
+                               while((pid = fork()) == -1) sleep(5);
+                               if(pid) {
+                                       while(wpid=wait((int *)NULL)!= -1 && wpid!= pid);
+                                       doano();
+                                       goto leave;
+                               }
+                           }
+                       }
+                       if(!m_send(cp, drft))
+                               goto leave;
+               default:fprintf(stderr, "dist: illegal option\n");       /*##*/
+                       break;
+       }
+    }
+
+ leave:
+       m_update();
+       done(0);
+}
+
+
+cpydata(in, out)
+{
+       char buf[BUFSIZ];
+       register int i;
+
+       do
+               if((i = read(in, buf, sizeof buf)) > 0)
+                       write(out, buf, i);
+       while(i == sizeof buf);
+}
+
+
+doano()
+{
+       register FILE *in;
+       char name[NAMESZ], field[256];
+       register int ind, state;
+       register char *text;
+
+       if(stat(drft, field) != -1) {
+               fprintf(stderr, "%s not sent-- no annotations made.\n", drft);
+               return;
+       }
+       text = copy(drft, field);
+       text[1] = 0;
+       do
+               *text = text[-1];
+       while(--text >= field && *text != '/');
+       *++text =
+#ifdef UCB
+               '#';
+#else
+               ',';
+#endif
+       if((in = fopen(field, "r")) == NULL) {
+               fprintf(stderr, "Can't open %s\n", field);
+               return;
+       }
+       state = FLD;
+       text = 0;
+   for(;;) switch(state = m_getfld(state, name, field, sizeof field, in)) {
+
+       case FLD:
+       case FLDEOF:
+       case FLDPLUS:
+               if(uleq(name, "distribute-to") ||
+                  uleq(name, "distribute-cc") == 0) {
+                       if(state == FLD) {
+                               text = add(name, text);
+                               text = add(":", text);
+                       }
+                       text = add(field, text);
+               }
+               if(state == FLDEOF)
+                       goto out;
+               continue;
+       case BODY:
+       case BODYEOF:
+               goto out;
+       default:
+               fprintf(stderr, "Getfld returned %d\n", state);
+               return;
+       }
+
+out:
+       fclose(in);
+       annotate(m_name(mp->lowsel), "Distributed", text, inplace);
+
+
+}
diff --git a/docs/historical/mh-nov-1983/cmds/emitl.c b/docs/historical/mh-nov-1983/cmds/emitl.c
new file mode 100644 (file)
index 0000000..439b618
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Routine to convert a localtime(3) format date back into
+ * a system format date.
+ *
+ * Hats off to Bob Kridle for the insight that the way to do
+ * this is by binary search of the system date space.
+ */
+
+#include <sys/time.h>
+
+struct tm *localtime();
+
+long
+emitl(dp)
+       struct tm *dp;
+{
+       long conv;
+       register int i, bit;
+       struct tm dcopy;
+
+       dcopy = *dp;
+       dp = &dcopy;
+       conv = 0;
+       for (i = 31; i >= 0; i--) {
+               bit = 1 << i;
+               conv |= bit;
+               if (dcmp(localtime(&conv), dp) > 0)
+                       conv &= ~bit;
+       }
+       return(conv);
+}
+
+/*
+ * Compare two localtime dates, return result.
+ */
+
+#define DECIDE(a) \
+       if (dp->a > dp2->a) \
+               return(1); \
+       if (dp->a < dp2->a) \
+               return(-1)
+
+static
+dcmp(dp, dp2)
+       register struct tm *dp, *dp2;
+{
+
+       DECIDE(tm_year);
+       DECIDE(tm_mon);
+       DECIDE(tm_mday);
+       DECIDE(tm_hour);
+       DECIDE(tm_min);
+       DECIDE(tm_sec);
+       return(0);
+}
diff --git a/docs/historical/mh-nov-1983/cmds/folder.c b/docs/historical/mh-nov-1983/cmds/folder.c
new file mode 100644 (file)
index 0000000..a5b9e46
--- /dev/null
@@ -0,0 +1,316 @@
+#include "mh.h"
+#include <stdio.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/dir.h>
+#include <strings.h>
+
+#define NFOLDERS 100
+
+int all, hdrflag, foldp;
+struct msgs *mp;
+char folder[128], *folds[NFOLDERS];
+int msgtot, foldtot, totonly, fshort;
+int fpack;
+struct swit switches[] = {
+       "all",          0,      /* 0 */
+       "down",         0,      /* 1 */
+       "fast",         0,      /* 2 */
+       "nofast",       0,      /* 3 */
+       "header",       0,      /* 4 */
+       "noheader",     0,      /* 5 */
+       "pack",         0,      /* 6 */
+       "nopack",       0,      /* 7 */
+       "short",       -1,      /* 8 */
+       "total",        0,      /* 9 */
+       "nototal",      0,      /*10 */
+       "up",           0,      /*11 */
+       "help",         4,      /*12 */
+       "debug",        5,      /*13 */
+       0,              0
+};
+
+int    debug;
+
+main(argc, argv)
+char *argv[];
+{
+       register char *cp, *curm;
+       register int i;
+       char *argfolder;
+       int up, down, j, def_short;
+       char *arguments[50], **argp, **ap;
+       struct stat stbf;
+       struct node *np;
+       extern char _sobuf[];
+       register struct direct *dir;
+       DIR *dirp;
+
+       setbuf(stdout, _sobuf);
+#ifdef NEWS
+       m_news();
+#endif
+       up = down = 0;
+       argfolder = NULL;
+       curm = 0;
+       if(argv[0][strlen(argv[0])-1] == 's')   /* Plural name?? */
+               all++;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);     /* ambiguous */
+                               goto leave;
+                                                          /* unknown */
+                       case -1:fprintf(stderr, "folder: -%s unknown\n", cp);
+                               goto leave;
+                       case 0: all++;  continue;          /* -all      */
+                       case 1: down++;  continue;         /* -down     */
+                       case 2:                            /* -fast     */
+                       case 3: fshort = 0; continue;      /* -nofast   */
+                       case 4: hdrflag = -1;  continue;   /* -header   */
+                       case 5: hdrflag = 0;  continue;    /* -noheader */
+                       case 6: fpack = 1; continue;       /* -pack     */
+                       case 7: fpack = 0; continue;       /* -nopack   */
+                       case 8: fshort = 1; continue;      /* -short    */
+                       case 9: all++; totonly = 1;        /* -total    */
+                               continue;
+                       case 10:if(totonly) all--;         /* -nototal  */
+                               totonly =0;  continue;
+                       case 11:up++;  continue;           /* -up       */
+                                                          /* -help     */
+                       case 12:help("folder [+folder]  [msg] [switches]",
+                                    switches);
+                               goto leave;
+                       case 13:debug++;                   /* -debug    */
+                               continue;
+                       }
+               if(*cp == '+') {
+                       if(argfolder) {
+                               fprintf(stderr, "Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               argfolder = cp + 1;
+               } else if(curm) {
+                       fprintf(stderr, "Only one current may be given.\n");
+                       goto leave;
+               } else
+                       curm = cp;
+       }
+       if(all) {
+               hdrflag = 0;
+               cp = m_maildir("");
+               m_getdefs();
+               for(np = m_defs; np; np = np->n_next) {
+                       if(!ssequal("cur-", np->n_name))
+                               continue;
+                       if(fshort) {
+                               def_short++;
+                               printf("%s\n", np->n_name+4);
+                       } else
+                               addfold(np->n_name+4);
+               }
+               if(def_short)
+                       putchar('\n');
+               if(fshort) {
+                       m_update();
+                       fflush(stdout);
+                       execl(lsproc, "mh-ls", "-x", cp, 0);
+                       fprintf(stderr, "Can't exec: ");
+                       perror(lsproc);
+                       goto leave;
+               }
+               if(chdir(cp) < 0) {
+                       fprintf(stderr, "Can't chdir to: ");
+                       perror(cp);
+                       goto leave;
+               }
+               if((cp = m_find(pfolder)) == NULL)
+                       *folder = 0;
+               else
+                       copy(cp, folder);
+               dirp = opendir(".");
+               (void) readdir(dirp);
+               (void) readdir(dirp);
+               while (dir = readdir(dirp)) {
+                       if (stat(dir->d_name, &stbf) < 0 ||
+                           (stbf.st_mode & S_IFMT) != S_IFDIR)
+                               continue;
+                       addfold(dir->d_name);
+               }
+               closedir(dirp);
+               for(i = 0; i < foldp; i++) {
+                       pfold(folds[i], 0); fflush(stdout);
+               }
+               if(!totonly)
+                       printf("\n\t\t     ");
+               printf("TOTAL= %3d message%c in %d Folder%s.\n",
+                       msgtot, msgtot!=1? 's':' ',
+                       foldtot, foldtot!=1? "s":"");
+       } else  {
+               hdrflag++;
+               if(argfolder)
+                       cp = copy(argfolder, folder);
+               else
+                       cp = copy(m_getfolder(), folder);
+               if(up) {
+                       while(cp > folder && *cp != '/') --cp;
+                       if(cp > folder)
+                               *cp = 0;
+                       argfolder = folder;
+               } else if(down) {
+                       copy(listname, copy("/", cp));
+                       argfolder = folder;
+               }
+               if(pfold(folder, curm) && argfolder)
+                       m_replace(pfolder, argfolder);
+       }
+
+ leave:
+       m_update();
+       done(0);
+}
+
+
+addfold(fold)
+char *fold;
+{
+       register int i,j;
+       register char *cp;
+
+       if(foldp >= NFOLDERS) {
+               fprintf(stderr, "More than %d folders!!\n", NFOLDERS);
+               return(1);
+       }
+       cp = getcpy(fold);
+       for(i = 0; i < foldp; i++)
+               if(compare(cp, folds[i]) < 0) {
+                       for(j = foldp - 1; j >= i; j--)
+                               folds[j+1] = folds[j];
+                       foldp++;
+                       folds[i] = cp;
+                       return(0);
+               }
+       folds[foldp++] = cp;
+       return(0);
+}
+
+
+pfold(fold, curm)
+char *fold;
+{
+       register char *mailfile;
+       register int msgnum, hole;
+       char newmsg[8], oldmsg[8];
+
+       mailfile = m_maildir(fold);
+       if(chdir(mailfile) < 0) {
+               fprintf(stderr, "Can't chdir to: ");
+               perror(mailfile);
+               return(0);
+       }
+       if(fshort) {
+               printf("%s\n", fold);
+               return(0);
+       }
+       mp = m_gmsg(fold);
+       foldtot++;
+       msgtot += mp->nummsg;
+       if (debug)
+               printf("pfold: %s message flags: 0%o\n", fold, mp->msgflags);
+       if(fpack && (mp->msgflags & READONLY) == 0) {
+           if (debug) {
+               printf("Would normally be packing folder %s\n", fold);
+               return;
+           }
+           for(msgnum = mp->lowmsg, hole = 1; msgnum <= mp->hghmsg; msgnum++) {
+               if(mp->msgstats[msgnum]&EXISTS) {
+                       if(msgnum != hole) {
+                               copy(m_name(hole), newmsg);
+                               copy(m_name(msgnum), oldmsg);
+                               if(link(oldmsg, newmsg) == -1 ||
+                                  unlink(oldmsg) == -1) {
+                                       fprintf(stderr, "Error moving %s to ", oldmsg);
+                                       perror(newmsg);
+                                       done(1);
+                               }
+                               mp->msgstats[hole] = mp->msgstats[msgnum];
+                               if(msgnum == mp->lowsel)
+                                       mp->lowsel = hole;
+                               if(msgnum == mp->hghsel)
+                                       mp->hghsel = hole;
+                       }
+                       hole++;
+               }
+           }
+           if(mp->nummsg > 0) {
+               mp->lowmsg = 1;
+               mp->hghmsg = hole - 1;
+           }
+       }
+       if(totonly)
+               goto out;
+       if(curm) {
+               if(!m_convert(curm))
+                       return(0);
+               if(mp->numsel > 1) {
+                       fprintf(stderr, "Can't set current msg to range: %s\n", curm);
+                       return(0);
+               }
+               m_setcur(mp->curmsg = mp->hghsel);
+       }
+       if(!hdrflag++)
+  printf("\t\tFolder   # of messages   ( range ); cur msg (other files)\n");
+       printf("%22s", fold);
+       if(strcmp(folder, fold) == 0)
+               printf("+ ");
+       else
+               printf("  ");
+       if(mp->hghmsg == 0)
+               printf("has  no messages");
+       else {
+               printf("has %3d message%s (%3d-%3d)",
+                       mp->nummsg, (mp->nummsg==1)?" ":"s",
+                       mp->lowmsg, mp->hghmsg);
+               if(mp->curmsg >= mp->lowmsg && mp->curmsg <= mp->hghmsg)
+                       printf("; cur=%3s", m_name(mp->curmsg));
+       }
+       if(mp->selist || mp->others) {
+               printf("; (");
+               if(mp->selist) {
+                       printf("%s", listname);
+                       if(mp->others)
+                               printf(", ");
+               }
+               if(mp->others)
+                       printf("others");
+               putchar(')');
+       }
+       putchar('.');
+       putchar('\n');
+out:
+       free(mp);
+       mp = 0;
+       return(1);
+}
+
+
+compare(s1, s2)
+char *s1, *s2;
+{
+       register char *c1, *c2;
+       register int i;
+
+       c1 = s1; c2 = s2;
+       while(*c1 || *c2)
+               if(i = *c1++ - *c2++)
+                       return(i);
+       return(0);
+}
diff --git a/docs/historical/mh-nov-1983/cmds/forw.c b/docs/historical/mh-nov-1983/cmds/forw.c
new file mode 100644 (file)
index 0000000..636efe0
--- /dev/null
@@ -0,0 +1,316 @@
+#ifndef lint
+static char sccsid[] = "@(#)forw.c     4.1 2/23/83";
+#endif
+
+#include "mh.h"
+#include <stdio.h>
+#include <signal.h>
+#include <strings.h>
+
+#define NONE 0
+#define NOUSE 0
+
+/* #define TEST 1 */
+
+int *vec[MAXARGS];
+struct msgs *mp;
+char drft[128];
+int inplace;            /* preserve links in anno */
+
+char    *anyl[] = {
+       "no",   0,
+       "yes",  0,
+       "list", 0,
+       0,
+};
+
+char    *anyv[] = {
+       "no",           0,
+       "yes",          0,
+       "verbose",      0,
+       0,
+};
+
+struct swit switches[] = {
+       "all",               -3,      /* 0 */
+       "annotate",           0,      /* 1 */
+       "noannotate",         0,      /* 2 */
+       "editor editor",      0,      /* 3 */
+       "form formfile",      0,      /* 4 */
+       "inplace",            0,      /* 5 */
+       "noinplace",          0,      /* 6 */
+       "help",               4,      /* 7 */
+       0,                    0
+};
+
+char *aleqs[] = {
+       "list",              0,         /* 0 */
+       "edit [<editor>]",   0,         /* 1 */
+       "quit [delete]",     0,         /* 2 */
+       "send [verbose]",    0,         /* 3 */
+       0
+};
+
+
+main(argc, argv)
+char *argv[];
+{
+       char *folder, *maildir, *msgs[100], *ed, *form;
+       register int msgnum;
+       register char *cp, **ap;
+       int msgp, status, anot;
+       int in, out, intr;
+       int pid, wpid, msgcnt;
+       char *arguments[50], **argp;
+       char numbuf[5];
+
+#ifdef NEWS
+       m_news();
+#endif
+       form = 0; anot = 0; folder = 0; msgp = 0; ed = 0;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                            /* unknown */
+                       case -1:fprintf(stderr, "forw: -%s unknown\n", cp);
+                               goto leave;
+                                                            /* -all */
+                       case 0: fprintf(stderr, "\"-all\" changed to \"all\"\n");
+                               goto leave;
+                       case 1: anot = 1;  continue;         /* -annotate */
+                       case 2: anot = 0;  continue;         /* -noannotate */
+                       case 3: if(!(ed = *argp++)) {        /* -editor */
+      missing:  fprintf(stderr, "forw: Missing argument for %s switch\n", argp[-2]);
+                                       goto leave;
+                               }
+                               continue;
+                       case 4: if(!(form = *argp++))        /* -form */
+                                       goto missing;
+                               continue;
+                       case 5: inplace = 1;  continue;      /* -inplace */
+                       case 6: inplace = 0;  continue;      /* -noinplace */
+                                                            /* -help */
+                       case 7: help("forw   [+folder] [msgs] [switches]",
+                                    switches);
+                               goto leave;
+                       }
+               if(*cp == '+') {
+                       if(folder) {
+                               fprintf(stderr, "Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               folder = cp + 1;
+               } else
+                       msgs[msgp++] = cp;
+       }
+       if(!msgp)
+               msgs[msgp++] = "cur";
+       if(!folder)
+               folder = m_getfolder();
+       maildir = m_maildir(folder);
+       if(chdir(maildir) < 0) {
+               fprintf(stderr, "Can't chdir to: ");
+               perror(maildir);
+               goto leave;
+       }
+       if(!(mp = m_gmsg(folder))) {
+               fprintf(stderr, "Can't read folder!?\n");
+               goto leave;
+       }
+       if(mp->hghmsg == 0) {
+               fprintf(stderr, "No messages in \"%s\".\n", folder);
+               goto leave;
+       }
+       for(msgnum = 0; msgnum < msgp; msgnum++)
+               if(!m_convert(msgs[msgnum]))
+                       goto leave;
+       if(mp->numsel == 0) {
+               fprintf(stderr, "forw: italian salami.\n");      /* never get here */
+               goto leave;
+       }
+       if(form) {
+               if((in = open(m_maildir(form), 0)) < 0) {
+                       fprintf(stderr, "forw: Can't open form file: %s\n", form);
+                       goto leave;
+               }
+       } else if((in = open(m_maildir(components), 0)) < 0 &&
+                  (in = open(stdcomps, 0)) < 0) {
+                       fprintf(stderr, "forw: Can't open default components file!!\n");
+                       goto leave;
+       }
+       copy(m_maildir(draft), drft);
+       if((out = open(drft, 0)) >= 0) {
+               if(!fdcompare(in, out)) {
+                       cp = concat("\"", drft, "\" exists; Delete? ", 0);
+                       while((msgnum = gans(cp, anyl)) == 2)
+                               showfile(drft);
+                       if(!msgnum)
+                               return;
+               }
+               close(out);
+       }
+       if((out = creat(drft, m_gmprot())) < 0) {
+               fprintf(stderr, "Can't create \"%s\"\n", drft);
+               goto leave;
+       }
+       cpydata(in, out);
+       close(in);
+       for(msgcnt = 1, msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
+               if(mp->msgstats[msgnum]&SELECTED)  {
+                       if((in = open(cp = m_name(msgnum), 0)) < 0) {
+                               fprintf(stderr, "Can't open message \"%s\"\n", cp);
+                               unlink(drft);
+                               goto leave;
+                       }
+                       type(out, "\n\n-------");
+                       if(msgnum == mp->lowsel) {
+                               type(out, " Forwarded Message");
+                               if(mp->numsel > 1)
+                                       type(out, "s");
+                       } else {
+                               type(out, " Message ");
+                               sprintf(numbuf, "%d", msgcnt);
+                               type(out, numbuf);
+                       }
+                       type(out, "\n\n");
+                       cpydata(in, out);
+                       close(in);
+                       msgcnt++;
+               }
+       type(out, "\n\n------- End of Forwarded Message");
+       if(mp->numsel > 1)
+               type(out, "s");
+       type(out, "\n");
+       close(out);
+       m_replace(pfolder, folder);
+       if(mp->lowsel != mp->curmsg)
+               m_setcur(mp->lowsel);
+       if(m_edit(&ed, drft, NOUSE, NONE) < 0)
+               goto leave;
+
+#ifdef TEST
+       fprintf(stderr, "!! Test Version of SEND Being Run !!\n");
+       fprintf(stderr, "   Send verbose !\n\n");
+#endif
+    for(;;) {
+       if(!(argp = getans("\nWhat now? ", aleqs)))
+               goto leave;
+       switch(smatch(*argp, aleqs)) {
+               case 0: showfile(drft);                         /* list */
+                       break;
+               case 1: if(*++argp)                             /* edit */
+                               ed = *argp;
+                       if(m_edit(&ed, drft, NOUSE, NONE) == -1)
+                               goto leave;
+                       break;
+               case 2: if(*++argp && *argp[0] == 'd')          /* quit */
+                               if(unlink(drft) == -1)  {
+                                       fprintf(stderr, "Can't unlink %s ", drft);
+                                       perror("");
+                               }
+                       goto leave;
+               case 3: if(*++argp) cp = *argp;  else cp = "";  /* send */
+
+                       if(!mp->msgflags&READONLY) {    /* annotate first */
+                           if(anot > 0) {
+                               while((pid = fork()) == -1) sleep(5);
+                               if(pid) {
+                                       while(wpid=wait((int *)NULL)!= -1 && wpid!= pid);
+                                       doano();
+                                       goto leave;
+                               }
+                           }
+                       }
+                       if(!m_send(cp, drft))
+                               goto leave;
+               default:fprintf(stderr, "forw: illegal option\n");       /*##*/
+                       break;
+       }
+    }
+
+ leave:
+       m_update();
+       done(0);
+}
+
+
+cpydata(in, out)
+{
+       char buf[BUFSIZ];
+       register int i;
+
+       do
+               if((i = read(in, buf, sizeof buf)) > 0)
+                       write(out, buf, i);
+       while(i == sizeof buf);
+}
+
+
+doano()
+{
+       FILE *in;
+       char name[NAMESZ], field[256];
+       register int ind, state;
+       register char *text;
+
+       if(stat(drft, field) != -1) {
+               fprintf(stderr, "%s not sent-- no annotations made.\n", drft);
+               return;
+       }
+       text = copy(drft, field);
+       text[1] = 0;
+       do
+               *text = text[-1];
+       while(--text >= field && *text != '/');
+       *++text =
+#ifdef UCB
+               '#';
+#else
+               ',';                  /* New backup convention */
+#endif
+       if((in = fopen(field, "r")) == NULL) {
+               fprintf(stderr, "Can't open "); perror(field);
+               return;
+       }
+       state = FLD;
+       text = 0;
+   for(;;) switch(state = m_getfld(state, name, field, sizeof field, in)) {
+
+       case FLD:
+       case FLDEOF:
+       case FLDPLUS:
+               if(uleq(name, "to") || uleq(name, "cc") == 0) {
+                       if(state == FLD) {
+                               text = add(name, text);
+                               text = add(":", text);
+                       }
+                       text = add(field, text);
+               }
+               if(state == FLDEOF)
+                       goto out;
+               continue;
+       case BODY:
+       case BODYEOF:
+               goto out;
+       default:
+               fprintf(stderr, "Getfld returned %d\n", state);
+               return;
+       }
+
+out:
+       fclose(in);
+
+       for(ind = mp->lowsel; ind <= mp->hghsel; ind++)
+               if(mp->msgstats[ind] & SELECTED)
+                       annotate(m_name(ind), "Forwarded", text, inplace);
+}
diff --git a/docs/historical/mh-nov-1983/cmds/grep.c b/docs/historical/mh-nov-1983/cmds/grep.c
new file mode 100644 (file)
index 0000000..314d357
--- /dev/null
@@ -0,0 +1,281 @@
+#include <stdio.h>
+#define        CCHR    2
+#define        CDOT    4
+#define        CCL     6
+#define        NCCL    8
+#define        CDOL    10
+#define        CEOF    11
+
+#define        STAR    01
+
+#define LBSIZE  1024
+#define        ESIZE   256
+
+char    ibuf[BUFSIZ];
+char   expbuf[ESIZE];
+char   linebuf[LBSIZE+1];
+int    circf;
+
+char cc[] = {
+       0000,0001,0002,0003,0004,0005,0006,0007,
+       0010,0011,0012,0013,0014,0015,0016,0017,
+       0020,0021,0022,0023,0024,0025,0026,0027,
+       0030,0031,0032,0033,0034,0035,0036,0037,
+       0040,0041,0042,0043,0044,0045,0046,0047,
+       0050,0051,0052,0053,0054,0055,0056,0057,
+       0060,0061,0062,0063,0064,0065,0066,0067,
+       0070,0071,0072,0073,0074,0075,0076,0077,
+       0100,0141,0142,0143,0144,0145,0146,0147,
+       0150,0151,0152,0153,0154,0155,0156,0157,
+       0160,0161,0162,0163,0164,0165,0166,0167,
+       0170,0171,0172,0133,0134,0135,0136,0137,
+       0140,0141,0142,0143,0144,0145,0146,0147,
+       0150,0151,0152,0153,0154,0155,0156,0157,
+       0160,0161,0162,0163,0164,0165,0166,0167,
+       0170,0171,0172,0173,0174,0175,0176,0177,
+};
+
+
+compile(astr)
+char *astr;
+{
+       register c;
+       register char *ep, *sp;
+       char *lastep;
+       int cclcnt;
+
+       ep = expbuf;
+       sp = astr;
+       if (*sp == '^') {
+               circf++;
+               sp++;
+       }
+       for (;;) {
+               if (ep >= &expbuf[ESIZE])
+                       goto cerror;
+               if ((c = *sp++) != '*')
+                       lastep = ep;
+               switch (c) {
+
+               case '\0':
+                       *ep++ = CEOF;
+                       return(1);
+
+               case '.':
+                       *ep++ = CDOT;
+                       continue;
+
+               case '*':
+                       if (lastep==0)
+                               goto defchar;
+                       *lastep |= STAR;
+                       continue;
+
+               case '$':
+                       if (*sp != '\0')
+                               goto defchar;
+                       *ep++ = CDOL;
+                       continue;
+
+               case '[':
+                       *ep++ = CCL;
+                       *ep++ = 0;
+                       cclcnt = 1;
+                       if ((c = *sp++) == '^') {
+                               c = *sp++;
+                               ep[-2] = NCCL;
+                       }
+                       do {
+                               *ep++ = c;
+                               cclcnt++;
+                               if (c=='\0' || ep >= &expbuf[ESIZE])
+                                       goto cerror;
+                       } while ((c = *sp++) != ']');
+                       lastep[1] = cclcnt;
+                       continue;
+
+               case '\\':
+                       if ((c = *sp++) == '\0')
+                               goto cerror;
+               defchar:
+               default:
+                       *ep++ = CCHR;
+                       *ep++ = c;
+               }
+       }
+    cerror:
+       return(0);
+}
+
+
+execute(file)
+char *file;
+{
+       register char *p1, *p2;
+       register c;
+       int f, body, lf;
+       char *ebp, *cbp;
+
+       if ((f = open(file, 0)) < 0) {
+               fprintf(stderr, "Grep: Can't open %s\n", file);
+               return(0);
+       }
+       body = 0;
+       ebp = ibuf;
+       cbp = ibuf;
+       for (;;) {
+               p1 = linebuf;
+               p2 = cbp;
+               lf = 0;
+               for (;;) {
+                       if (p2 >= ebp) {
+                               if ((c = read(f, ibuf, sizeof ibuf)) <= 0) {
+                                       close(f);
+                                       if(lf) break; /* bodyless comp! */
+                                       return(0);
+                               }
+                               p2 = ibuf;
+                               ebp = ibuf+c;
+                       }
+                       c = *p2++;
+                       if(lf) if(c != ' ' && c != '\t') {
+                               --p2;
+                               break;
+                       } else
+                               lf = 0;
+                       if (c == '\n')
+                               if(body)
+                                       break;
+                               else {
+                                       if(lf) {
+                                               body++;
+                                               break;
+                                       }
+                                       lf++;
+                                       c = ' ';
+                               }
+                       if(c && p1 < &linebuf[LBSIZE-1])
+                               *p1++ = c;
+               }
+               *p1++ = 0;
+               cbp = p2;
+               p1 = linebuf;
+               p2 = expbuf;
+               if (circf) {
+                       if (advance(p1, p2))
+                               goto found;
+                       continue;
+               }
+               /* fast check for first character */
+               if (*p2==CCHR) {
+                       c = p2[1];
+                       do {
+                               if(*p1==c || cc[*p1]==c)
+                                       if (advance(p1, p2))
+                                               goto found;
+                       } while (*p1++);
+                       continue;
+               }
+               /* regular algorithm */
+               do {
+                       if (advance(p1, p2))
+                               goto found;
+               } while (*p1++);
+               continue;
+       found:
+               close(f);
+               return(1);
+       }
+}
+
+
+advance(alp, aep)
+char *alp, *aep;
+{
+       register char *lp, *ep, *curlp;
+       char *nextep;
+
+       lp = alp;
+       ep = aep;
+       for (;;) switch (*ep++) {
+
+       case CCHR:
+               if (*ep++ == *lp++ || ep[-1] == cc[lp[-1]])
+                       continue;
+               return(0);
+
+       case CDOT:
+               if (*lp++)
+                       continue;
+               return(0);
+
+       case CDOL:
+               if (*lp==0)
+                       continue;
+               return(0);
+
+       case CEOF:
+               return(1);
+
+       case CCL:
+               if (cclass(ep, *lp++, 1)) {
+                       ep += *ep;
+                       continue;
+               }
+               return(0);
+
+       case NCCL:
+               if (cclass(ep, *lp++, 0)) {
+                       ep += *ep;
+                       continue;
+               }
+               return(0);
+
+       case CDOT|STAR:
+               curlp = lp;
+               while (*lp++);
+               goto star;
+
+       case CCHR|STAR:
+               curlp = lp;
+               while (*lp++ == *ep || cc[lp[-1]] == *ep) ;
+               ep++;
+               goto star;
+
+       case CCL|STAR:
+       case NCCL|STAR:
+               curlp = lp;
+               while (cclass(ep, *lp++, ep[-1]==(CCL|STAR)));
+               ep += *ep;
+               goto star;
+
+       star:
+               do {
+                       lp--;
+                       if (advance(lp, ep))
+                               return(1);
+               } while (lp > curlp);
+               return(0);
+
+       default:
+               printf("RE botch\n");
+               return(0);
+       }
+}
+
+
+cclass(aset, ac, af)
+char *aset;
+{
+       register char *set, c;
+       register n;
+
+       set = aset;
+       if ((c = ac) == 0)
+               return(0);
+       n = *set++;
+       while (--n)
+               if (*set++ == c)
+                       return(af);
+       return(!af);
+}
diff --git a/docs/historical/mh-nov-1983/cmds/inc.c b/docs/historical/mh-nov-1983/cmds/inc.c
new file mode 100644 (file)
index 0000000..3b433b6
--- /dev/null
@@ -0,0 +1,335 @@
+#ifndef lint
+static char sccsid[] = "@(#)inc.c      1.2 9/25/83";
+#endif
+
+#include "mh.h"
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <strings.h>
+#include <signal.h>
+
+char   *anoyes[];       /* Std no/yes gans array        */
+
+extern int errno;
+char    scanl[];
+struct  msgs *mp;
+FILE    *in, *aud;
+struct  stat stbuf;
+char    *locknode;
+int     lockwait;       /* Secs to wait for lock-Def in strings/lockdir.c */
+#define LOCKWAIT (lockwait*5) /* If lock is this old, simply ignore it! */
+
+struct  swit switches[] = {
+       "audit audit-file",     0,      /* 0 */
+       "ms ms-folder",         0,      /* 1 */
+       "help",                 4,      /* 2 */
+       "file mail-file",       0,      /* 3 */
+       0,                      0
+};
+
+#ifdef UNIXCOMP
+char   unixtmp[] = "/tmp/mhXXXXXX";
+#endif
+
+main(argc, argv)
+char *argv[];
+{
+
+       char *newmail, maildir[128], *folder, *from, *audfile, *srcfile;
+       char mailspace[128];
+       char *myname, *savemail;
+       register char *cp;
+       register int i, msgnum;
+       long now;
+       char **ap;
+       char *arguments[50], **argp;
+       int done();
+       long time();
+       int pid, status, fildes;
+       extern char _sobuf[];
+
+       setbuf(stdout, _sobuf);
+#ifdef NEWS
+       m_news();
+#endif
+
+       from = 0; folder = 0; audfile = 0; srcfile = 0;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                            /* unknown */
+                       case -1:fprintf(stderr, "inc: -%s unknown\n", cp);
+                               goto leave;
+                       case 0: if(!(audfile = *argp++)) {   /* -audit */
+      missing:  fprintf(stderr, "inc: Missing argument for %s switch\n", argp[-2]);
+                                       goto leave;
+                               }
+                               continue;
+                       case 1: if(!(from = *argp++))        /* -ms */
+                                       goto missing;
+                               continue;
+                       case 2:                              /* -help */
+                               help("inc [+folder]  [switches]", switches);
+                               goto leave;
+                       case 3:                              /* -file */
+                               if (!(srcfile = *argp++))
+                                       goto missing;
+                               continue;
+                       }
+               if(*cp == '+') {
+                       if(folder) {
+                               fprintf(stderr, "Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               folder = cp + 1;
+               } else {
+                       fprintf(stderr, "Bad arg: %s\n", argp[-1]);
+       fprintf(stderr, "Usage: inc [+folder] [-ms ms-folder] [-audit audit-file]\n");
+                       goto leave;
+               }
+       }
+       if (from && srcfile) {
+               fprintf(stderr, "Only one of \"-ms\" and \"-file\" allowed\n");
+               goto leave;
+       }
+       if(from)
+               newmail = from;
+       else {
+               if((myname = getenv("USER")) == 0) {
+                       fprintf(stderr,
+"Environment Variable \"USER\" Must be set to your login name!\n");
+                       done(1);
+               }
+               if (srcfile) {
+                       newmail = srcfile;
+                       goto statit;
+               }
+               newmail = concat(mailboxes, myname, 0);
+               if (stat(newmail, &stbuf) >= 0
+                   && (stbuf.st_mode & S_IFMT) == S_IFDIR) {
+                       strcpy(mailspace, newmail);
+                       newmail = mailspace;
+                       strcat(newmail, "/");
+                       strcat(newmail, myname);
+               }
+statit:
+               if(stat(newmail, &stbuf) < 0 ||
+                  stbuf.st_size == 0) {
+                       fprintf(stderr, "No Mail to incorporate.\n");
+                       goto leave;
+               }
+       }
+       fildes = -1;
+       if (srcfile)
+               if ((fildes = open(srcfile, 0)) < 0) {
+                       perror(srcfile);
+                       goto leave;
+               }
+       if(!folder) {
+               folder = defalt;
+               if(from && strcmp(from, "inbox") == 0) {
+                       cp = concat("Do you really want to convert from ",
+                               from, " into ", folder, "?? ", 0);
+                       if(!gans(cp, anoyes))
+                               goto leave;
+                       cndfree(cp);
+               }
+       }
+       copy(m_maildir(folder), maildir);
+       if(stat(maildir, &stbuf) < 0) {
+               if(errno != ENOENT) {
+                       fprintf(stderr, "Error on folder ");
+                       perror(maildir);
+                       goto leave;
+               }
+               cp = concat("Create folder \"", maildir, "\"? ", 0);
+               if(!gans(cp, anoyes))
+                       goto leave;
+               if(!makedir(maildir)) {
+                       fprintf(stderr, "Can't create folder \"%s\"\n", maildir);
+                       goto leave;
+               }
+       }
+       if(chdir(maildir) < 0) {
+               fprintf(stderr, "Can't chdir to: ");
+               perror(maildir);
+               goto leave;
+       }
+       if(!(mp = m_gmsg(folder))) {
+               fprintf(stderr, "Can't read folder!?\n");
+               goto leave;
+       }
+                                       /* Lock the mail file */
+       if(!from && !srcfile) {
+               signal(SIGINT, done);
+               cp = concat(lockdir, myname, ".lock", 0);
+               for(i = 0; i < lockwait; i += 2) {
+                       if(link(newmail, cp) == -1) {
+                               fprintf(stderr, "Mailbox busy...\n");
+                               if(i == 0 && stat(newmail, &stbuf) >= 0)
+                                       if(stbuf.st_ctime + LOCKWAIT < time((long *)0)) {
+                                               unlink(cp);
+                                               fprintf(stderr, "Removing lock.\n");
+                                               continue;
+                                       }
+                               sleep(2);
+                       } else {
+                               locknode = cp;  /* We own the lock now! */
+                               break;
+                       }
+               }
+               if(i >= lockwait) {
+                       fprintf(stderr, "Try again.\n");
+                       done(1);
+               }
+       }
+
+#ifdef UNIXCOMP
+       /*
+        * If trying to be compatible with standard
+        * UNIX mailing scheme, call the program unixtomh
+        * to convert the mailbox to some temporary name.
+        */
+       
+       mktemp(unixtmp);
+       switch  (pid = fork()) {
+       case 0:
+               if (srcfile) {
+                       int nout;
+
+                       if ((nout = creat(unixtmp, 0600)) < 0) {
+                               perror(unixtmp);
+                               _exit(1);
+                       }
+                       close(0);
+                       dup(fildes);
+                       close(fildes);
+                       close(1);
+                       dup(nout);
+                       close(nout);
+                       execl(unixtomh, "unixtomh", 0);
+                       perror(unixtomh);
+                       _exit(1);
+               }
+               execl(unixtomh, "unixtomh", newmail, unixtmp, 0);
+               perror(unixtomh);
+               _exit(1);
+               break;
+
+       case -1:
+               perror("fork");
+               goto leave;
+
+       default:
+               while (wait(&status) != pid)
+                       ;
+               if (status != 0) {
+                       fprintf(stderr, "unixtomh failed!?\n");
+                       goto leave;
+               }
+       }
+       if (fildes >= 0)
+               close(fildes);
+       savemail = newmail;
+       newmail = unixtmp;
+       if((in = fopen(newmail, "r")) == NULL) {
+               fprintf(stderr, "Can't open "); perror(newmail);
+               goto leave;
+       }
+#else
+       if (srcfile)
+               in = fdopen(fildes, "r");
+       else
+               if((in = fopen(newmail, "r")) == NULL) {
+                       fprintf(stderr, "Can't open "); perror(newmail);
+                       goto leave;
+               }
+#endif
+
+       if(audfile) {
+               cp = m_maildir(audfile);
+               if((i = stat(cp, &stbuf)) < 0)
+                       fprintf(stderr, "Creating Receive-Audit: %s\n", cp);
+               if((aud = fopen(cp, "a")) == NULL) {
+                       fprintf(stderr, "Can't append to ");
+                       perror(cp);
+                       goto leave;
+               } else if(i < 0)
+                       chmod(cp, 0600);
+               time(&now);
+               fputs("<<inc>> ", aud);
+               cp = cdate(&now);
+               cp[9] = ' ';
+               fputs(cp, aud);
+               if(from) {
+                       fputs("  -ms ", aud);
+                       fputs(from, aud);
+               }
+               putc('\n', aud);
+       }
+       printf("Incorporating new mail into %s...\n\n", folder);
+       fflush(stdout);
+       msgnum = mp->hghmsg;
+
+       while((i = scan(in, msgnum+1, msgnum+1, msgnum == mp->hghmsg))) {
+               if(i == -1) {
+                       fprintf(stderr, "inc aborted!\n");
+                       if(aud)
+                               fputs("inc aborted!\n", aud);
+                       goto leave;
+               }
+               if(aud)
+                       fputs(scanl, aud);
+               fflush(stdout);
+               msgnum++;
+       }
+
+       fclose(in);
+       if(aud)
+               fclose(aud);
+
+#ifdef UNIXCOMP
+       unlink(newmail);
+       newmail = savemail;
+#endif
+
+       if(!from && !srcfile) {
+               if (unlink(newmail) < 0) {
+                       if((i = creat(newmail, 0600)) >= 0)
+                               close(i);
+                       else
+                               fprintf(stderr, "Error zeroing %s\n", newmail);
+               }
+       }
+
+       i = msgnum - mp->hghmsg;
+       if(!i)
+               fprintf(stderr, "[No messages incorporated.]\n");
+       else {
+               m_replace(pfolder, folder);
+               m_setcur(mp->hghmsg + 1);
+       }
+leave:
+       m_update();
+       done(0);
+}
+
+
+done(status)
+{
+       if(locknode);
+               unlink(locknode);
+       exit(status);
+}
diff --git a/docs/historical/mh-nov-1983/cmds/install-mh.c b/docs/historical/mh-nov-1983/cmds/install-mh.c
new file mode 100644 (file)
index 0000000..0e536e6
--- /dev/null
@@ -0,0 +1,109 @@
+#include "mh.h"
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+char   *anoyes[];       /* Std no/yes gans array        */
+
+char    defpath[128];
+
+main(argc, argv)
+char *argv[];
+{
+       register char *cp, *path;
+       register struct node *np;
+       int autof, exitstat;
+       struct stat stbuf;
+       char *geta();
+       extern char _sobuf[];
+
+       setbuf(stdout, _sobuf);
+       autof = (argc == 2 && strcmp(argv[1], "-auto") == 0);
+       exitstat = 1;                 /* Assume errors will occur */
+       mypath = getenv("HOME");
+/***    mypath = getpath(getruid());  /* to prevent recursion via m_getdefs */
+       copy(mh_prof, copy(mypath, defpath));
+       if(stat(defpath, &stbuf) != -1) {
+           if(autof)
+               printf("Install-defs invocation error!\n");
+           else
+               printf("You already have an MH profile... use an editor \
+to modify it.\n");
+           goto leave;
+
+       }
+       if(autof || gans("Do you want help? ", anoyes)) {
+printf("\nPrior to using MH, it is necessary to have a file in your login\n");
+printf("directory (%s) named %s which contains information\n",mypath,mh_prof+1);
+printf("to direct certain MH operations.  The only item which is required\n");
+printf("is the path to use for all MH folder operations. The suggested MH\n");
+printf("path for you is %s/Mail...\n\n", mypath);
+       }
+       cp = concat(mypath, "/", "Mail", 0);
+       if(stat(cp, &stbuf) != -1) {
+           if((stbuf.st_mode&S_IFMT) == S_IFDIR) {
+               cp = concat("You already have the standard MH directory \"",
+                       cp, "\".\nDo you want to use it for MH? ", 0);
+               if(gans(cp, anoyes))
+                   path = "Mail";
+               else
+                   goto xyz;
+           }
+       } else {
+           cp = concat("Do you want the standard MH path \"", mypath,
+                        "/", "Mail\"? ", 0);
+           if(gans(cp, anoyes))
+                   path = "Mail";
+           else {
+    xyz:        if(gans("Do you want a path below your login directory? ",
+                   anoyes)) {
+                   printf("What is the path ??  %s/", mypath);
+                   path = geta();
+               } else {
+                   printf("What is the whole path??  /");
+                   path = concat("/", geta(), 0);
+               }
+           }
+       }
+       chdir(mypath);
+       if(chdir(path) == -1) {
+               cp = concat("\"", path, "\" doesn't exist; Create it? ", 0);
+               if(gans(cp, anoyes))
+                       if(makedir(path) == 0) {
+                               printf("Can't create it!\n");
+                               goto leave;
+                       }
+       } else
+               printf("[Using existing directory]\n");
+
+       np = m_defs = (struct node *) malloc(sizeof *np);
+       np->n_name = "Path";
+       np->n_field = path;
+       np->n_next = 0;
+       m_replace(pfolder, defalt);
+       exitstat = 0;
+
+leave:
+       m_update();
+       done(exitstat);
+}
+
+
+char *geta()
+{
+       static char line[128];
+       register char *cp;
+       register int c;
+
+       fflush(stdout);
+       cp = line;
+       while((c = getchar()) != EOF) {
+               if(c == '\n') {
+                       *cp = 0;
+                       return(line);
+               }
+               if(cp < &line[128])
+                       *cp++ = c;
+       }
+       done(1);
+}
diff --git a/docs/historical/mh-nov-1983/cmds/mail.c b/docs/historical/mh-nov-1983/cmds/mail.c
new file mode 100644 (file)
index 0000000..227265f
--- /dev/null
@@ -0,0 +1,157 @@
+#include "mh.h"
+#include <stdio.h>
+#include <signal.h>
+
+#define NUMTOS  10              /* Number of to's & cc's accepted */
+
+char    tmpfil[32];
+int     exitstat = 1;
+char    *subject, *cc, *body;
+
+struct swit switches[] = {
+       "body",         0,      /* 0 */
+       "cc",           0,      /* 1 */
+       "subject",      0,      /* 2 */
+       "help",         4,      /* 3 */
+       0,              0
+};
+
+main(argc, argv)
+int argc;
+char *argv[];
+{
+       register FILE *out;
+       register int i, cnt;
+       register char *cp;
+       int pid, status, top, ccp, sig(), somebody = 0;
+       char buf[BUFSIZ], *tos[NUMTOS], *ccs[NUMTOS], **argp;
+
+       top = 0;
+       ccp = -1;               /* -1 -> collecting TOs */
+       if(argc == 1) {         /* Just call inc to read mail */
+               execl("/bin/inc", "inc", 0);
+               execl("/usr/bin/inc", "inc", 0);
+               perror("inc");
+               done(exitstat);
+       }
+       argp = argv + 1;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);  /* ambiguous */
+                               done(exitstat);
+                                                       /* unknown */
+                       case -1:fprintf(stderr, "send: -%s unknown\n", cp);
+                               done(exitstat);
+                                                       /* -body */
+                       case 0: if((body = *argp++) == 0) {
+                    missing:           fprintf(stderr, "Mail: Missing %s arg\n", cp);
+                                       done(exitstat);
+                               }
+                               continue;
+                                                       /* -cc */
+                       case 1: ccp = 0;                /* Now collecting ccs */
+                               continue;
+                                                       /* -subject */
+                       case 2: if((subject = *argp++) == 0)
+                                       goto missing;
+                               continue;
+                                                       /* -help */
+                       case 3: help("mail [switches] users ...",
+                                    switches);
+                               done(0);
+                       }
+               else {
+                       if(ccp >= 0) {                  /* If getting ccs..*/
+                               if(ccp < NUMTOS)
+                                       ccs[ccp++] = cp;
+                               else {
+                                       fprintf(stderr, "Mail: Too many ccs\n");
+                                       done(exitstat);
+                               }
+                       } else {                        /* Else, to */
+                               if(top < NUMTOS)
+                                       tos[top++] = cp;
+                               else {
+                                       fprintf(stderr, "Mail: Too many tos\n");
+                                       done(exitstat);
+                               }
+                       }
+               }
+       }
+                                       /* Create a mail temp file */
+       sprintf(tmpfil, "/tmp/%s", makename("mail", ".tmp"));
+       if((out = fopen(tmpfil, "w")) == NULL) {
+               perror(tmpfil);
+               done(exitstat);
+       }
+       signal(SIGINT, sig);            /* Clean up if user <del>s out */
+       fprintf(out, "To: ");           /* Create to list */
+       for(i = 0; i < top;) {
+               fprintf(out, "%s", tos[i]);
+               if(++i < top)
+                       fprintf(out, ", ");
+       }
+       fprintf(out, "\n");
+       if(ccp > 0) {
+               fprintf(out, "Cc: ");   /* Create cc list if needed */
+               for(i = 0; i < ccp;) {
+                       fprintf(out, "%s", ccs[i]);
+                       if(++i < ccp)
+                               fprintf(out, ", ");
+               }
+               fprintf(out, "\n");
+       }
+       if(subject)                     /* Create subject if needed */
+               fprintf(out, "Subject: %s\n", subject);
+
+       fprintf(out, "\n");
+
+       if(body) {                      /* Use body if I have it, */
+               somebody++;
+               fprintf(out, "%s\n", body);
+       } else {                        /* Otherwise, get a body */
+               while((cnt = read(0, buf, sizeof buf)) > 0) {
+                       somebody++;
+                       if(!fwrite(buf, cnt, 1, out)) {
+                               perror(tmpfil);
+                               sig();
+                       }
+               }
+       }
+
+       if(ferror(out)) {               /* Check that all wrote well */
+               fprintf(stderr, "Error writing tmp file\n");
+               sig();
+       }
+       fclose(out);
+       if(!somebody)                   /* If NO body, then don't send */
+               sig();                  /*  To be compatible with BELL mail */
+       while((i = fork()) == -1) {     /* Now, deliver the mail */
+               fprintf(stderr, "Waiting for a fork...\n");
+               sleep(2);
+       }
+       if(i == 0) {                    /* Call deliverer in child */
+               execl(mh_deliver, mh_deliver, tmpfil, 0);
+               perror(mh_deliver);
+               done(exitstat);
+       }
+       signal(SIGINT, SIG_IGN);
+       while((pid = wait(&status)) != -1 && pid != i) ;
+       if(status) {                    /* And save mail if delivery failed */
+               signal(SIGINT, SIG_DFL);
+               fprintf(stderr, "Letter saved in dead.letter\n");
+               execl("/bin/mv", "mv", tmpfil, "dead.letter", 0);
+               execl("/usr/bin/mv", "mv", tmpfil, "dead.letter", 0);
+               perror("/bin/mv");
+               done(exitstat);
+       }
+       exitstat = 0;
+       sig();
+}
+
+sig()
+{
+       unlink(tmpfil);
+       done(exitstat);
+}
diff --git a/docs/historical/mh-nov-1983/cmds/mh.h b/docs/historical/mh-nov-1983/cmds/mh.h
new file mode 100644 (file)
index 0000000..9ba122a
--- /dev/null
@@ -0,0 +1,154 @@
+#define ALL ""
+
+#define MAXARGS 1000    /* Max messages to exec                 */
+
+#define EXISTS    01    /* Flag bits in msgstats-- Deleted is   */
+#define DELETED   02    /*      undefined currently             */
+#define SELECTED  04    /* Message selected by an arg           */
+
+#define READONLY  01    /* No write access to folder            */
+#define DEFMOD    01    /* In-core profile has been modified    */
+
+/*#define NEWS     1    /* Define for news inclusion            */
+
+struct  swit {
+       char *sw;
+       int minchars;
+};
+
+/*
+ * m_gmsg() returns this structure.  It contains the per folder
+ * information which is obtained from reading the folder directory.
+ */
+
+struct  msgs {
+       int     hghmsg;         /* Highest msg in directory     */
+       int     nummsg;         /* Actual Number of msgs        */
+       int     lowmsg;         /* Lowest msg number            */
+       int     curmsg;         /* Number of current msg if any */
+       int     lowsel;         /* Lowest selected msg number   */
+       int     hghsel;         /* Highest selected msg number  */
+       int     numsel;         /* Number of msgs selected      */
+       char   *foldpath;       /* Pathname of folder           */
+       char    selist,         /* Folder has a "select" file   */
+               msgflags,       /* Folder status bits           */
+               filler,
+               others;         /* Folder has other file(s)     */
+       char    msgstats[1];    /* Stat bytes for each msg      */
+};
+
+               /* m_getfld definitions and return values       */
+
+#define NAMESZ  64      /* Limit on component name size         */
+#define LENERR  -2      /* Name too long error from getfld      */
+#define FMTERR  -3      /* Message Format error                 */
+
+                       /* m_getfld return codes                */
+#define FLD      0      /* Field returned                       */
+#define FLDPLUS  1      /* Field " with more to come            */
+#define FLDEOF   2      /* Field " ending at eom                */
+#define BODY     3      /* Body  " with more to come            */
+#define BODYEOF  4      /* Body  " ending at eom                */
+#define FILEEOF  5      /* Reached end of input file            */
+
+/*
+ * These standard strings are defined in strings.a.  They are the
+ * only system-dependent parameters in MH, and thus by redefining
+ * their values and reloading the various modules, MH will run
+ * on any system.
+ */
+
+char
+       *components,    /* Name of user's component file (in mh dir) */
+       *current,       /* Name of current msg file in a folder */
+       *defalt,        /* Name of the std folder (inbox)       */
+       *distcomps,     /* Name of `dist' components file       */
+       *draft,         /* Name of the normal draft file        */
+       *fileproc,      /* Path of file program                 */
+       *foldprot,      /* Default folder protection            */
+       *hostname,      /* Local net host name                  */
+       *installproc,   /* Name of auto-install program path    */
+       *listname,      /* Default selection list folder name   */
+       *lockdir,       /* Dir for lock files (Same fs as mailboxes)*/
+       *lsproc,        /* Path of the Harvard ls program       */
+       *mailboxes,     /* Incoming mail directory              */
+       *mh_prof,       /* Name of users profile file           */
+       *mh_deliver,    /* Name of deliverer for mh             */
+       *mhnews,        /* Name of MH news file                 */
+       *msgprot,       /* Default message protection (s.a. 0664) */
+       *pfolder,       /* Name of current folder profile entry */
+       *prproc,        /* Path of the pr program               */
+       *scanproc,      /* Path of the scan program             */
+       *showproc,      /* Path of the type (l) program         */
+       *sendproc,      /* Path of the send message program     */
+       *stdcomps,      /* Std comp file if missing user's own  */
+       *stddcomps,     /* Std dist file if missing user's own  */
+       *sysed,         /* Path of the std (ned) editor         */
+/* Just about every program uses this also                      */
+       *mypath;        /* User's log-on path                   */
+
+#ifdef UNIXCOMP
+char *unixtomh;                /* Path of program to convert UNIX style
+                          mailboxes to MH style mailboxes */
+char *Mailprog;                /* Path of program to do actual mailing */
+char *localname;       /* Name of local machine on local net */
+#endif
+
+/*
+ * node structure used to hold a linked list of the users profile
+ * information taken from logpath/.mh_prof.
+ */
+
+struct node {
+       struct node *n_next;
+       char        *n_name,
+                   *n_field;
+} *m_defs;
+
+char  def_flags;
+
+
+/*
+ * The first char in the mhnews file indicates whether the program
+ * calling m_news() should continue running or halt.
+ */
+
+#define NEWSHALT        '!'     /* Halt after showing the news  */
+#define NEWSCONT        ' '     /* Continue  (ditto)            */
+#define NEWSPAUSE       '\001'  /* Pause during news output...  */
+
+
+/*
+ * Miscellaneous Defines to speed things up
+ */
+
+#define error(str) { fprintf(stderr, "%s\n", str); exit(-1); }
+
+/*
+ * Routine type declarations -- needed by version 7 compiler
+ */
+
+char **brkstring();
+char *m_maildir();
+char *m_find();
+char *m_name();
+char *concat();
+char *getcpy();
+char *trimcpy();
+char *add();
+char *invo_name();
+char **copyip();
+char *getcpy();
+char *m_getfolder();
+struct msgs *m_gmsg();
+char *copy();
+char **getans();
+char *cdate();
+char *makename();
+char *r1bindex();
+
+/*
+ * Routine type declarations -- SHOULD BE GLOBAL
+ */
+char *getenv();
+
diff --git a/docs/historical/mh-nov-1983/cmds/news.c b/docs/historical/mh-nov-1983/cmds/news.c
new file mode 100644 (file)
index 0000000..42f0ed4
--- /dev/null
@@ -0,0 +1,300 @@
+#include "mh.h"
+#include <stdio.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/dir.h>
+#include <strings.h>
+#define max(a,b) (a > b ? a : b)
+
+#define NEWSP   "/usr/spool/newnews"
+#define MAXTOPICS       20      /* Enough for a while */
+
+int     vecp, topicp;
+char    *topics[MAXTOPICS+1];
+char    *vec[MAXARGS];
+struct msgs *mp;
+int     fdisplay, fcheck, fupdate, fsend, freview, fbody;  /* flags */
+int     frevback;
+int     hit;
+
+struct nts {
+       char    *t_name;
+       int     t_num;
+} nts[MAXTOPICS+1], *check();
+
+struct swit switches[] = {
+       "add",          -1,     /* 0 */
+       "body",         -1,     /* 1 */
+       "check",        0,      /* 2 */
+       "display",      0,      /* 3 */
+       "review [#]",   0,      /* 4 */
+       "send topic ...",0,     /* 5 */
+       "topics",       0,      /* 6 */
+       "update",       0,      /* 7 */
+       "help",         4,      /* 8 */
+       0,              0,
+};
+
+main(argc, argv)
+       int argc;
+       char *argv[];
+{
+       register int i;
+       register char *cp, **ap;
+       char *arguments[50], **argp;
+       extern char _sobuf[];
+
+       setbuf(stdout, _sobuf);
+#ifdef NEWS
+       m_news();
+#endif
+       vecp = 2;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               done(0);
+                                                            /* unknown */
+                       case -1:vec[vecp++] = --cp; continue;
+                       case 0:
+                       case 5: fsend++; continue;
+                       case 1: fbody++;
+                               vec[vecp++] = --cp; continue;
+                       case 2: fcheck++; continue;
+                       case 3: fdisplay++; continue;
+                       case 4: freview++;
+                               if(**argp >= '0' && **argp <= '9')
+                                       frevback = atoi(*argp++);
+                               continue;
+                       case 7: fupdate++; continue;
+
+                       case 8:
+  help("news [topic ...] [switches] [switches for \"c\" or \"mail\" ]",
+                                    switches);
+                               putchar('\n');
+                       case 6:
+                               printf("Topic    items\n\n"); fflush(stdout);
+                               getnts();
+                               for(i = 0; nts[i].t_name[0]; i++)
+                                       printf("%-9s%3d\n", nts[i].t_name,
+                                               nts[i].t_num);
+                               done(0);
+                       }
+               else
+                       if(vecp == 2)
+                               topics[topicp++] = cp;
+                       else
+                               vec[vecp++] = cp;
+       }
+       getnts();
+       if(fsend) {
+               if(topicp == 0) {
+                       fprintf(stderr, "Usage: news -send topic [mail switches]\n");
+                       done(1);
+               }
+               for(i = 0; i < topicp; i++)
+                       if(check(topics[i]))
+                               send(topics[i]);
+                       else
+                               printf("Unknown topic: %s\n", topics[i]);
+               done(0);
+       }
+       if(!topicp)
+               for(i = 0; nts[i].t_name[0]; i++)
+                       disp(nts[i].t_name, 0);
+       else
+               for(i = 0; i < topicp; i++)
+                       if(check(topics[i]) == NULL)
+                               printf("Topic: %s unknown.\n", topics[i]);
+                       else
+                               disp(topics[i], 1);
+       if(fcheck) {
+               if(hit)
+                       printf(".\n");
+       } else if(!hit && !topicp && !fupdate && !fdisplay)
+               nonews();
+       m_update();
+       done(0);
+}
+
+
+getnts()
+{
+       struct direct *dir;
+       struct stat st;
+       register struct nts *t;
+       register DIR *d;
+       char tbuf[16 + 16];
+
+       t = nts;
+       if((d = opendir(NEWSP)) == 00) {
+               fprintf(stderr, "Can't open ");
+               perror(NEWSP);
+               done(1);
+       }
+       while (dir = readdir(d))
+               if(dir->d_ino && dir->d_name[0] != '.') {
+                       t->t_name = (char *)malloc(dir->d_namlen + 1);
+                       if (t->t_name == 0)
+                               break;
+                       strcpy(t->t_name, dir->d_name);
+                       t++;
+               }
+       closedir(d);
+       for(t = nts; t->t_name[0]; t++) {
+               sprintf(tbuf, "%s/.%.14s", NEWSP, t->t_name);
+               if(stat(tbuf, &st) != -1)
+                       t->t_num = st.st_size;
+       }
+}
+
+struct nts *
+check(topic)
+       char *topic;
+{
+       register struct nts *t;
+
+       for(t = nts; t->t_name[0]; t++)
+               if(strcmp(topic, t->t_name) == 0)
+                       return t;
+       return 0;
+}
+
+
+disp(topic, argflg)
+       register char *topic;
+       int argflg;
+{
+       register struct nts *t;
+       register char *cp, *np;
+       register int msgnum;
+       int high;
+       char buf[128];
+
+       if((t = check(topic)) == 0)
+               fprintf(stderr, "HUH?\n");
+       if((cp = m_find(np = concat("news-", topic, 0))) == NULL)
+               cp = "0";
+       high = atoi(cp);
+       if(fcheck) {
+               if(t->t_num > high) {
+                       if(!hit++)
+                               printf("Unread news in");
+                       if(hit > 1)
+                               printf(",");
+                       printf(" %s", topic);
+               }
+               return;
+       }
+       if(fupdate) {
+               if(t->t_num > high) {
+                       m_replace(np, getcpy(m_name(t->t_num)));
+                       printf("Skipping %d items in %s.\n",
+                               t->t_num - high, topic);
+               }
+               return;
+       }
+       if(freview)
+               if(frevback)
+                       msgnum = max(high - frevback, 0);
+               else
+                       msgnum = 0;
+       else
+               msgnum = high;
+/***    msgnum = freview? frevback? high - frevback : 0 : high; */
+       if(msgnum >= t->t_num) {
+               if(argflg)
+                       printf("%s: no new news.\n", topic);
+               return;
+       }
+       sprintf(buf, "%s/%s", NEWSP, topic);
+       if(chdir(buf) == -1) {
+               perror(buf);
+               return;
+       }
+       vec[1] = showproc;
+       for( ; msgnum < t->t_num;) {
+               cp = m_name(++msgnum);
+               if(hit) {
+                       printf("\nPress <return> for %s:%s...", topic, cp);
+                       fflush(stdout);
+                       read(0, buf, sizeof buf);
+               } else
+                       printf("News item %s:%s\n", topic, cp);
+               if(msgnum > high) {
+                       m_replace(np, getcpy(cp));
+                       m_update();
+               }
+               vec[vecp] = cp;
+               putchar('\n');
+               call(vec + 1);
+               hit = 1;
+       }
+}
+
+
+call(vector)
+       char **vector;
+{
+       register int pid, child;
+       char path[32];
+       int status;
+
+       fflush(stdout);
+       while((child = fork()) == -1) {
+               printf("No forks...\n"); fflush(stdout);
+               sleep(2);
+       }
+       if(child == 0) {
+               execv(vector[0], vector);
+               perror(vector[0]);
+               done(1);
+       }
+       while((pid = wait(&status)) != -1 && pid != child) ;
+       if(pid == -1 || status) {
+               fprintf(stderr, "Abnormal termination from %s\n", vector[0]);
+               done(1);
+       }
+}
+
+char    *mailproc;
+
+send(topic)
+       register char *topic;
+{
+       vec[0] = mailproc;
+       vec[1] = concat("news.", topic, 0);
+       if(!fbody)
+               printf("Enter text for %s\n", topic);
+       call(vec);
+       free(vec[1]);
+}
+
+
+char    *nons[] = {
+       "No new news",
+       "No news to peruse",
+       "Only old news",
+       "News shortage",
+       "News reporters on strike",
+       "Report your own news",
+       "News presses broken"
+};
+#define NONS    (sizeof nons/ sizeof nons[0])
+
+nonews()
+{
+#include <sys/timeb.h>
+       struct timeb tb;
+
+       ftime(&tb);
+       printf("%s.\n", nons[tb.millitm % NONS]);
+}
diff --git a/docs/historical/mh-nov-1983/cmds/next.c b/docs/historical/mh-nov-1983/cmds/next.c
new file mode 100644 (file)
index 0000000..9fb3416
--- /dev/null
@@ -0,0 +1,97 @@
+#include "mh.h"
+#include <stdio.h>
+#include <strings.h>
+
+int     glbtype;
+struct msgs *mp;
+
+struct swit switches[] = {
+       "help",         4,      /* 0 */
+       0,              0
+};
+
+main(argc, argv)
+char *argv[];
+{
+       char *maildir, *vec[20], *folder, *nfolder;
+       register int msgnum;
+       register char *cp;
+       int next;
+       int vecp;
+       char **ap;
+       char *arguments[50], **argp;
+       extern char _sobuf[];
+
+       setbuf(stdout, _sobuf);
+#ifdef NEWS
+       m_news();
+#endif
+       next = glbtype;
+       folder = 0; vecp = 2;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                            /* unknown */
+                       case -1:vec[vecp++] = --cp;  continue;
+                       case 0: if(next > 0)                 /* -help  */
+       help("next [+folder]   [switches] [switches for \"type\" ]", switches);
+                               else
+       help("prev [+folder]   [switches] [switches for \"type\" ]", switches);
+                               goto leave;
+                       }
+               if(*cp == '+') {
+                       if(folder) {
+                               fprintf(stderr, "Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               folder = cp + 1;
+               } else {
+                       fprintf(stderr, "Bad arg: %s\n", cp);
+                       fprintf(stderr, "Usage: %s [+folder] [-l.switches]\n",
+                            next>0? "next" : "prev");
+                       goto leave;
+               }
+       }
+       vec[vecp] = 0;
+       if(!folder)
+               folder = m_getfolder();
+       maildir = m_maildir(folder);
+       if(chdir(maildir) < 0) {
+               fprintf(stderr, "Can't chdir to: ");
+               perror(maildir);
+               goto leave;
+       }
+       if(!(mp = m_gmsg(folder))) {
+               fprintf(stderr, "Can't read folder!?\n");
+               goto leave;
+       }
+       if(mp->hghmsg == 0) {
+               fprintf(stderr, "No messages in \"%s\".\n", folder);
+               goto leave;
+       }
+       if(!m_convert(next > 0 ? "next" : "prev"))
+               goto leave;
+       m_replace(pfolder, folder);
+       if(mp->lowsel != mp->curmsg)
+               m_setcur(mp->lowsel);
+       vec[1] = m_name(mp->lowsel);
+       printf("(Message %s:%s)\n", folder, vec[1]);
+       fflush(stdout);
+       vec[0] = "mh-type";
+       m_update();
+       execv(showproc, vec);
+       perror("Can't exec type");
+ leave:
+       m_update();
+       done(0);
+}
diff --git a/docs/historical/mh-nov-1983/cmds/nexthdr.c b/docs/historical/mh-nov-1983/cmds/nexthdr.c
new file mode 100644 (file)
index 0000000..f7def4b
--- /dev/null
@@ -0,0 +1 @@
+int     glbtype =  1;
diff --git a/docs/historical/mh-nov-1983/cmds/pick.c b/docs/historical/mh-nov-1983/cmds/pick.c
new file mode 100644 (file)
index 0000000..1384ac5
--- /dev/null
@@ -0,0 +1,490 @@
+#include "mh.h"
+#include <stdio.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <strings.h>
+
+#define NFOLD 20                /* Allow 20 folder specs */
+
+char *anoyes[];         /* Std no/yes gans array        */
+
+/*
+ * pick [-src folder] [msgs] search [-scan] [-show] [file-op]
+ *
+ *  search =  -from        \
+ *            -to           \
+ *            -cc            \
+ *            -subject        \  pattern
+ *            -sub            /
+ *            -date          /
+ *            -search       /
+ *            --component  /
+ *
+ * file-op =  -file [-preserve] [-link] +folder ...
+ *            -keep [-stay] [+folder ...]
+ */
+
+extern int errno;
+int nvecp, foldp;
+char **nvec;
+struct msgs *mp;
+char grep[256], *grepp, *folder, maildir[128];
+int showf, scanf, filef, keepf, linkf, noteold, prsrvf, stayf;
+int grep_lowsel  = 5000,
+    grep_hghsel  = 0;
+char *delprog;
+
+char   _sobuf[BUFSIZ];
+
+struct st_fold {
+       char        *f_name;
+       int          f_reused;
+       struct msgs *f_mp;
+} folders[NFOLD], *fptr;
+
+struct swit switches[] = {
+       "cc  pattern",                  0,      /*  0 */
+       "date  pattern",                0,      /*  1 */
+       "from  pattern",                0,      /*  2 */
+       "search  pattern",              0,      /*  3 */
+       "subject  pattern",             0,      /*  4 */
+       "to  pattern",                  0,      /*  5 */
+       "-othercomponent  pattern",    15,      /*  6 */
+       "all",                         -3,      /*  7 */
+       "file  +folder ...",            0,      /*  8 */
+       "nofile",                       0,      /*  9 */
+       "keep [+folder ...]",           0,      /* 10 */
+       "nokeep",                       0,      /* 11 */
+       "link",                         0,      /* 12 */
+       "nolink",                       0,      /* 13 */
+       "preserve",                     0,      /* 14 */
+       "nopreserve",                   0,      /* 15 */
+       "scan",                         0,      /* 16 */
+       "noscan",                       0,      /* 17 */
+       "show",                         0,      /* 18 */
+       "noshow",                       0,      /* 19 */
+       "src  +folder",                 0,      /* 20 */
+       "stay",                         0,      /* 21 */
+       "nostay",                       0,      /* 22 */
+       "help",                         4,      /* 23 */
+       0,                              0
+};
+
+main(argc, argv)
+char *argv[];
+{
+       char *msgs[128], buf[128];
+       register int msgnum;
+       register char *cp;
+       int msgp, i;
+       char **ap;
+       char *arguments[50], **argp, **arrp;
+
+       setbuf(stdout, _sobuf);
+
+#ifdef NEWS
+       m_news();
+#endif
+
+       nvecp = 1;
+       msgp = 0;
+       grepp = grep;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')  {
+                       if(*++cp == '-') {              /* --component */
+                   toomany:    if(grepp != grep) {
+                                   fprintf(stderr, "Only one search string.\n");
+                                   goto leave;
+                               }
+                               grepp = copy("^", grepp);
+                               grepp = copy(++cp, grepp);
+                               grepp = copy(":.*", grepp);
+                               goto pattern;
+                       }
+                       switch(i = smatch(cp, switches)) {
+                       case -2:ambigsw(cp, switches);  /* ambiguous */
+                               goto leave;
+                                                       /* unknown */
+                       case -1:fprintf(stderr, "pick: -%s unknown\n", cp);
+                               goto leave;
+                                                       /* -component */
+                       case 0:  case 1:  case 2:  case 4:  case 5:
+                               if(grepp != grep)
+                                       goto toomany;
+                               grepp = copy("^", grepp);
+                               arrp = brkstring(switches[i].sw, " ", 0);
+                               grepp = copy(*arrp, grepp);
+                               grepp = copy(":.*", grepp);
+                       case 3:                         /* -search */
+                      pattern: grepp = copy(*argp++, grepp);
+                               continue;
+                       case 6: fprintf(stderr, "pick:  can't get here\n");
+                               goto leave;
+                                                      /* -all */
+                       case 7: fprintf(stderr, "\"-all\" changed to \"all\"\n");
+                               goto leave;
+                       case 8: filef = 1;  continue;   /* -file */
+                       case 9: filef = 0;  continue;   /* -nofile */
+                       case 10:keepf = 1;  continue;   /* -keep */
+                       case 11:keepf = 0;  continue;   /* -nokeep */
+                       case 12:linkf = 1;  continue;   /* -link */
+                       case 13:linkf = 0;  continue;   /* -nolink */
+                       case 14:prsrvf = 1;  continue;  /* -preserve */
+                       case 15:prsrvf = 0;  continue;  /* -nopreserve */
+                       case 16:scanf = 1;  continue;   /* -scan */
+                       case 17:scanf = 0;  continue;   /* -noscan */
+                       case 18:showf = 1;  continue;   /* -show */
+                       case 19:showf = 0;  continue;   /* -noshow */
+                       case 21:stayf = 1;  continue;   /* -stay */
+                       case 22:stayf = 0;  continue;   /* -nostay */
+                       case 20:if(folder) {            /* -src */
+                                       fprintf(stderr, "Only one src folder.\n");
+                                       goto leave;
+                               }
+                               if(!(folder = *argp++) || *folder == '-') {
+               fprintf(stderr, "pick: Missing argument for %s switch\n", argp[-2]);
+                                        goto leave;
+                               }
+                               if(*folder == '+')
+                                       folder++;
+                               continue;
+                                                       /* -help */
+                       case 23:help("pick   [msgs] [switches]", switches);
+                               goto leave;
+                       }
+               } else if(*cp == '+') {
+                       if(foldp < NFOLD)
+                               folders[foldp++].f_name = cp + 1;
+                       else {
+                               fprintf(stderr, "Only %d folders allowed.\n", NFOLD);
+                               goto leave;
+                       }
+               } else
+                       msgs[msgp++] = cp;
+       }
+       if(grepp == grep) {
+               fprintf(stderr, "No search pattern specified.\n");
+               goto leave;
+       }
+       if(filef && keepf) {
+               fprintf(stderr, "-file and -keep don't go together.\n");
+               goto leave;
+       }
+       if(!scanf && !showf && !filef)
+               keepf++;                /* The default is -keep         */
+       if(keepf) {
+               prsrvf++;               /* -keep forces -preserve       */
+               linkf++;                /*   and -link                  */
+       }
+       if(!folder)
+               folder = m_getfolder(); /* use cur folder if no -src    */
+       copy(m_maildir(folder), maildir);
+       if(chdir(maildir) < 0) {
+               fprintf(stderr, "Can't chdir to: ");
+               perror(maildir);
+               goto leave;
+       }
+       if(!(mp = m_gmsg(folder))) {
+               fprintf(stderr, "Can't read folder!?\n");
+               goto leave;
+       }
+       if(mp->hghmsg == 0) {
+               fprintf(stderr, "No messages in \"%s\".\n", folder);
+               goto leave;
+       }
+       if(!foldp) {                    /* if no +folder given...       */
+               if(filef) {             /* -file requires one           */
+                       fprintf(stderr, "-file requires at least one folder arg.\n");
+                       goto leave;
+               }
+               if(keepf) {             /* use default selection-list name */
+                       copy(listname, copy("/", copy(folder, buf)));
+                       folders[foldp++].f_name = getcpy(buf);
+                       noteold++;      /* tell user if existing folder */
+               }
+       } else if(keepf) {              /* make folders sub-folders     */
+               for(msgnum = 0; msgnum < foldp; msgnum++)
+                       if(*(cp = folders[msgnum].f_name) != '.' &&
+                          *cp != '/') {
+                               copy(cp, copy("/", copy(folder, buf)));
+                               folders[msgnum].f_name = getcpy(buf);
+                       }
+               noteold++;
+       }
+       if(!msgp)
+               msgs[msgp++] = "first-last";
+       for(msgnum = 0; msgnum < msgp; msgnum++)
+               if(!m_convert(msgs[msgnum]))
+                       goto leave;
+       if(mp->numsel == 0) {
+               fprintf(stderr, "pick:  Peanut butter 'n jelly\n");/* never get here */
+               goto leave;
+       }
+       if(!compile(grep)) {
+               fprintf(stderr, "Pattern Error.\n");
+               goto leave;
+       }
+       for(msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
+               if(mp->msgstats[msgnum]&SELECTED)
+                       grepfn(msgnum);
+       if(mp->numsel == 0) {
+               fprintf(stderr, "No messages match specification.\n");
+               goto leave;
+       }
+       mp->lowsel = grep_lowsel;
+       mp->hghsel = grep_hghsel;
+                                                     /* all the exec's */
+       if((((delprog = m_find("delete-prog")) != NULL) &&
+           ((filef || keepf) && !linkf)) ||
+             scanf || showf) {
+               if(mp->numsel > MAXARGS-2) {
+                       fprintf(stderr, "pick: more than %d messages for %s exec\n",
+                               MAXARGS-2,
+                               scanf ? "scan" : showf ? "show" : delprog);
+                       goto leave;
+               }
+               nvec = (char **) malloc(MAXARGS * sizeof nvec[0]);
+               for(msgnum= mp->lowsel; msgnum<= mp->hghsel; msgnum++)
+                       if(mp->msgstats[msgnum]&SELECTED)
+                               nvec[nvecp++] = getcpy(m_name(msgnum));
+               nvec[nvecp] = 0;
+       }
+       if(keepf || filef)
+               if(opnfolds())
+                       goto leave;
+       if(!noteold || foldp > 1)
+               m_replace(pfolder, folder);
+       if(scanf)
+               scanfn(showf|filef|keepf);
+       else {
+               printf("%d hits.\n", mp->numsel); fflush(stdout);
+       }
+       if(showf)
+               showfn(filef|keepf);
+       if(!(filef|keepf))
+               goto leave;
+       for(msgnum= mp->lowsel; msgnum<= mp->hghsel; msgnum++)
+               if(mp->msgstats[msgnum]&SELECTED)
+                       if(process(cp = getcpy(m_name(msgnum))))
+                               goto leave;
+                       else
+                               free (cp);
+       if(!linkf)
+               remove();
+       if(noteold) {
+               if(!stayf && foldp == 1) {
+                       m_replace(pfolder, cp = folders[0].f_name);
+                       printf("[+%s now current]\n", cp); fflush(stdout);
+               }
+               for(fptr = folders; fptr < &folders[foldp]; fptr++)
+                       if(!fptr->f_reused) {
+                               chdir(m_maildir(fptr->f_name));
+                               m_setcur(fptr->f_mp->curmsg);
+                       }
+       }
+ leave:
+       m_update();
+}
+
+
+grepfn(msg)
+{
+       if(execute(m_name(msg))) {                  /* a match */
+               if(msg < grep_lowsel)
+                       grep_lowsel = msg;
+               if(msg > grep_hghsel)
+                       grep_hghsel = msg;
+       } else {
+               mp->msgstats[msg] &= ~SELECTED;     /* clear SELECTED bit */
+               mp->numsel--;
+       }
+}
+
+
+opnfolds()
+{
+       register int i;
+       register char *cp, *ap;
+       char nmaildir[128];
+       struct stat stbuf;
+
+       for(i = 0; i < foldp; i++) {
+               copy(m_maildir(cp = folders[i].f_name), nmaildir);
+               if(stat(nmaildir, &stbuf) < 0) {
+                       if(!noteold) {
+                               ap = concat("Create folder \"",
+                                       nmaildir, "\"? ", 0);
+                               if(!gans(ap, anoyes))
+                                       return(1);
+                       }
+                       if(!makedir(nmaildir)) {
+                               fprintf(stderr, "Can't create folder.\n");
+                               return(1);
+                       }
+               } else if(noteold) {
+                       printf("[Folder %s being re-used.]\n", cp);
+                       fflush(stdout);
+                       folders[i].f_reused++; /* Don't change cur in old fold */
+               }
+               if(chdir(nmaildir) < 0) {
+                       fprintf(stderr, "Can't chdir to: ");
+                       perror(nmaildir);
+                       return(1);
+               }
+               if(!(folders[i].f_mp = m_gmsg(folders[i].f_name))) {
+                       fprintf(stderr, "Can't read folder %s\n", folders[i].f_name);
+                       return(1);
+               }
+               folders[i].f_mp->curmsg = 0;
+       }
+       chdir(maildir);         /* return to src folder */
+       return(0);
+}
+
+
+scanfn(forkf)
+{
+       register int pid, i;
+
+       nvec[0] = "mh-scan";
+       if(forkf && (pid = fork())) {
+               if(pid == -1) {
+                       fprintf(stderr, "No forks!\n");
+                       done(1);
+               }
+               while(wait((int *)NULL) != pid) ;
+       } else {
+               m_update();
+               fflush(stdout);
+               execv(scanproc, nvec);
+               perror(scanproc);
+               done(1);
+       }
+}
+
+
+showfn(forkf)
+{
+       register int pid, i;
+       int sint, sqit;
+
+       nvec[0] = "c:mh-type";
+       if(forkf) {
+               sint = (int) signal(SIGINT, SIG_IGN);
+               sqit = (int) signal(SIGQUIT, SIG_IGN);
+       }
+       if(forkf && (pid = fork())) {
+               if(pid == -1) {
+                       fprintf(stderr, "No forks!\n");
+                       done(1);
+               }
+               while(wait((int *)NULL) != pid) ;
+               signal(SIGINT, sint);
+               signal(SIGQUIT, sqit);
+       } else {
+               m_update();
+               fflush(stdout);
+               execv(showproc, nvec);
+               perror(showproc);
+               done(1);
+       }
+}
+
+
+remove()
+{
+       register int i, j;
+       register char *cp;
+
+       if(delprog != NULL) {
+               nvec[0] = delprog;
+               m_update();
+               fflush(stdout);
+               execv(nvec[0], nvec);
+               fprintf(stderr, "Can't exec deletion-prog--");
+               perror(delprog);
+       } else {
+               for(i= mp->lowsel; i<= mp->hghsel; i++)
+                       if(mp->msgstats[i]&SELECTED)
+                               if(unlink(cp = m_name(i)) == -1) {
+                                       fprintf(stderr, "Can't unlink %s:",folder);
+                                       perror(cp);
+                               }
+       }
+}
+
+process(msg)
+char *msg;
+{
+       char newmsg[256], buf[BUFSIZ];
+       register int i;
+       register char *nmsg;
+       register struct st_fold *fp;
+       struct stat stbuf, stbf1;
+       int n, o, linkerr;
+
+    for(fp = folders; fp < &folders[foldp]; fp++) {
+       if(prsrvf)
+               nmsg = msg;
+       else
+               nmsg = m_name(fp->f_mp->hghmsg++ + 1);
+       copy(nmsg, copy("/", copy(m_maildir(fp->f_name), newmsg)));
+       if(link(msg, newmsg) < 0) {
+               linkerr = errno;
+               if(linkerr == EEXIST ||
+                 (linkerr == EXDEV && stat(newmsg, &stbuf) != -1)) {
+                       if(linkerr != EEXIST || stat(msg, &stbf1) < 0 ||
+                          stat(newmsg, &stbuf) < 0 ||
+                          stbf1.st_ino != stbuf.st_ino) {
+                               fprintf(stderr, "Message %s:%s already exists.\n",
+                                    fp->f_name, msg);
+                               return(1);
+                       }
+                       continue;
+               }
+               if(linkerr == EXDEV) {
+                       if((o = open(msg, 0)) == -1) {
+                               fprintf(stderr, "Can't open %s:%s.\n",
+                                       folder, msg);
+                               return(1);
+                       }
+                       fstat(o, &stbuf);
+                       if((n = creat(newmsg, stbuf.st_mode&0777)) == -1) {
+                               fprintf(stderr, "Can't create %s:%s.\n",
+                                       fp->f_name, nmsg);
+                               close(o);
+                               return(1);
+                       }
+                       do
+                               if((i=read(o, buf, sizeof buf)) < 0 ||
+                                 write(n, buf, i) == -1) {
+                                   fprintf(stderr, "Copy error on %s:%s to %s:%s!\n",
+                                           folder, msg, fp->f_name, nmsg);
+                                   close(o); close(n);
+                                   return(1);
+                               }
+                       while(i == sizeof buf);
+                       close(n); close(o);
+               } else {
+                       fprintf(stderr, "Error on link %s:%s to %s:",
+                           folder, msg, fp->f_name);
+                       perror(nmsg);
+                       return(1);
+               }
+       }
+       if((i = atoi(nmsg)) < fp->f_mp->curmsg || !fp->f_mp->curmsg)
+               fp->f_mp->curmsg = i;
+cont:   ;
+    }
+    return(0);
+}
diff --git a/docs/historical/mh-nov-1983/cmds/prevhdr.c b/docs/historical/mh-nov-1983/cmds/prevhdr.c
new file mode 100644 (file)
index 0000000..073abf2
--- /dev/null
@@ -0,0 +1 @@
+int     glbtype =   -1;
diff --git a/docs/historical/mh-nov-1983/cmds/prompter.c b/docs/historical/mh-nov-1983/cmds/prompter.c
new file mode 100644 (file)
index 0000000..1a9a0bb
--- /dev/null
@@ -0,0 +1,271 @@
+#include "mh.h"
+#include <stdio.h>
+#include <errno.h>
+#include <sgtty.h>
+#include <signal.h>
+#include <strings.h>
+
+extern int errno;
+int     wtuser;         /* waiting for user input */
+int     sigint;         /* sensed an interrupt */
+FILE    *in, *out;
+struct  sgttyb sg;
+struct swit switches[] = {
+       "erase chr",      2,      /* 0 */ /* "2" can become "0",since no ed */
+       "kill chr",       0,      /* 1 */
+       "help",           4,      /* 2 */
+       0,                0
+};
+
+main(argc, argv)
+char *argv[];
+{
+       char tmpfil[32], *drft, name[NAMESZ], field[BUFSIZ];
+       int exitstat;
+       char skill, serase;
+       char *killp, *erasep;
+       register int i, state;
+       register char *cp;
+       char **ap;
+       char *arguments[50], **argp;
+       int sig();
+       int status, pid, wpid, intr;
+       extern char _sobuf[];
+
+       setbuf(stdout, _sobuf);
+       tmpfil[0] = 0;
+       skill = 0; exitstat = 0;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++)
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto badleave;
+                                                            /* unknown */
+                       case -1:fprintf(stderr, "prompter: -%s unknown\n", cp);
+                               goto badleave;
+                       case 0: if(!(erasep = *argp++)) {   /* -erase */
+     missing:  fprintf(stderr, "prompter: Missing argument for %s switch\n", argp[-2]);
+                                       goto badleave;
+                               }
+                               continue;
+                       case 1: if(!(killp= *argp++))       /* -kill */
+                                       goto missing;
+                               continue;
+                                                           /* -help */
+                       case 2: help("prompter    [switches]",
+                                    switches);
+                               goto badleave;
+                       }
+               else
+                       drft = cp;
+       if(!drft) {
+               fprintf(stderr, "prompter: missing skeleton\n");
+               goto badleave;
+       }
+       if((in = fopen(drft, "r")) == NULL) {
+               fprintf(stderr, "Can't open %s\n", drft);
+               goto badleave;
+       }
+       copy(makename("prmt", ".tmp"), copy("/tmp/", tmpfil));
+       if((out = fopen(tmpfil, "w")) == NULL) {
+               fprintf(stderr, "Can't create %s\n", tmpfil);
+               goto badleave;
+       }
+       chmod(tmpfil, 0700);
+       signal(SIGINT, sig);
+       gtty(0, &sg);
+       skill = sg.sg_kill;
+       serase = sg.sg_erase;
+       sg.sg_kill =    killp ?  chrcnv(killp) : skill;
+       sg.sg_erase =   erasep ? chrcnv(erasep) : serase;
+/***    stty(0, &sg);           ***/
+       ioctl(0, TIOCSETN, &sg);
+       if(killp || erasep) {
+               printf("Erase Char="); chrdisp(sg.sg_erase);
+               printf("; Kill Line="); chrdisp(sg.sg_kill);
+               printf(".\n"); fflush(stdout);
+       }
+       state = FLD;
+       for(;;) switch(state = m_getfld(state,name,field,sizeof field,in)) {
+
+       case FLD:
+       case FLDEOF:
+       case FLDPLUS:
+               if(field[0] != '\n' || field[1] != 0) {
+                       printf("%s:%s", name, field);
+                       fprintf(out, "%s:%s", name, field);
+                       while(state == FLDPLUS) {
+                               state=m_getfld(state,name,field,sizeof field,in);
+                               printf("%s", field);
+                               printf(out, "%s", field);
+                       }
+               } else {
+                       printf("%s: ", name);
+                       fflush(stdout);
+                       i = getln(field);
+                       if(i == -1)
+                               goto badleave;
+                       if(i == 0 && (field[0] == '\n' || !field[0]))
+                               continue;
+                       fprintf(out, "%s:", name);
+                       do {
+                               if(field[0] != ' ' && field[0] != '\t')
+                                       putc(' ', out);
+                               fputs(field, out);
+                       } while(i == 1 && (i = getln(field)) >= 0);
+                       if(i == -1)
+                               goto badleave;
+               }
+               field[0] = 0;
+               if(state == FLDEOF)
+                       goto body;
+               continue;
+
+       case BODY:
+       case BODYEOF:
+       case FILEEOF:
+  body:         fputs("--------\n", out);
+               printf("--------\n");
+               if(field[0]) {
+                       do {
+                               fputs(field, out);
+                               if(!sigint)
+                                       printf("%s", field);
+                       } while(state == BODY &&
+                               (state=m_getfld(state,name,field,sizeof field,in)));
+                       printf("\n--------Enter additional text\n\n");
+               }
+               fflush(stdout);
+               for(;;) {
+                       getln(field);
+                       if(field[0] == 0)
+                               break;
+                       fputs(field, out);
+               }
+               goto finish;
+
+       default:
+               fprintf(stderr, "Bad format file!\n");
+               goto badleave;
+       }
+
+
+finish:
+       printf("--------\n"); fflush(stdout);
+       fclose(out);
+       out = fopen(tmpfil, "r");
+       fclose(in);
+       in = fopen(drft, "w");          /* Truncate prior to copy back */
+       do
+               if((i = read(fileno(out), field, sizeof field)) > 0)
+                       write(fileno(in), field, i);
+       while(i == sizeof field);
+       goto leave;
+
+badleave:
+       exitstat = 1;
+
+leave:
+       if(in)
+               fclose(in);
+       if(out)
+               fclose(out);
+       if(tmpfil[0])
+               unlink(tmpfil);
+       m_update();
+       if(killp || erasep) {
+               sg.sg_kill = skill;
+               sg.sg_erase = serase;
+/***            stty(0, &sg);           ***/
+               ioctl(0, TIOCSETN, &sg);
+       }
+       done(exitstat);
+}
+
+
+getln(buf)
+char *buf;
+{
+       register char *cp;
+       register int c;
+       int stat;
+
+       cp = buf;
+       *cp = 0;
+       wtuser = 1;
+       for(;;) {
+               c = getchar();
+/***            fprintf(stderr,"getchar()=\\%o,errno=%d,EINTR=%d\n",c,errno,EINTR);/***/
+               if(c == EOF)
+                       if(errno == EINTR) {
+                               stat = -1;
+                               goto leave;
+                       } else {
+                               stat = 0;
+                               goto leave;
+                       }
+               if(c == '\n') {
+                       if(cp[-1] == '\\') {
+                               cp[-1] = c;
+                               stat = 1;
+                               goto leave;
+                       }
+                       *cp++ = c;
+                       *cp   = 0;
+                       stat = 0;
+                       goto leave;
+               }
+               if(cp < buf + 500)
+                       *cp++ = c;
+               *cp = 0;
+       }
+ leave: wtuser = 0;
+       return(stat);
+       }
+
+
+sig()
+{
+       signal(SIGINT, sig);
+       if(!wtuser)
+               sigint = 1;
+       return;
+}
+
+
+chrcnv(str)
+char *str;
+{
+       register char *cp;
+       register int c;
+
+       cp = str;
+       if((c = *cp++) != '\\')
+               return(c);
+       c = 0;
+       while(*cp && *cp != '\n') {
+               c *= 8;
+               c += *cp++ - '0';
+       }
+       return c;
+}
+
+
+chrdisp(chr)
+{
+       register int c;
+
+       c = chr;
+       if(c < ' ')
+               printf("<CTRL-%c>", c + '@');
+       else
+               printf("%c", c);
+}
diff --git a/docs/historical/mh-nov-1983/cmds/refile.c b/docs/historical/mh-nov-1983/cmds/refile.c
new file mode 100644 (file)
index 0000000..02c16b8
--- /dev/null
@@ -0,0 +1,364 @@
+#ifndef lint
+static char sccsid[] = "@(#)refile.c   1.1 5/26/83";
+#endif
+
+#include "mh.h"
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <strings.h>
+
+#define NFOLD 20                /* Allow 20 folder specs */
+
+/* file [-src folder] [msgs] +folder [+folder ...]
+ *
+ * moves messages from src folder (or current) to other one(s).
+ *
+ *  all = 1-999 for a message sequence
+ *  -preserve says preserve msg numbers
+ *  -link says don't delete old msg
+ */
+
+char *anoyes[];         /* Std no/yes gans array        */
+
+int vecp, foldp, prsrvf;
+char **vec, maildir[128], *folder, *file;
+struct msgs *mp;
+
+struct st_fold {
+       char *f_name;
+       struct msgs *f_mp;
+} folders[NFOLD];
+
+char   *files[NFOLD + 1];       /* Vec of files to process--starts at 1! */
+int     filec = 1;
+char   *bellfile = "/usr/bin/file";
+extern int errno;
+char   *rindex();
+
+struct swit switches[] = {
+       "all",           -3,      /* 0 */
+       "link",           0,      /* 1 */
+       "nolink",         0,      /* 2 */
+       "preserve",       0,      /* 3 */
+       "nopreserve",     0,      /* 4 */
+       "src +folder",    0,      /* 5 */
+       "file",           0,      /* 6 */
+       "help",           4,      /* 7 */
+       0,                0
+};
+main(argc, argv)
+char *argv[];
+{
+       register int i, msgnum;
+       register char *cp;
+       char *msgs[128];
+       int msgp, linkf;
+       int ismhfile = 0;
+       char **ap;
+       char *arguments[50], **argp;
+       char *pwd(), *pwds;
+
+       /*
+        * Rand has committed the sin of picking a name that already is
+        * used (file).  We fix this here since we can tell the difference
+        * between the two (mh file has -'s and +'s always, bell file never
+        * has them.)
+        */
+       for (i=1; i<argc; i++)
+               if (argv[i][0] == '-' || argv[i][0]=='+')
+                       ismhfile++;
+       if (!ismhfile) {
+               execv(bellfile, argv);
+               fprintf(stderr, "Cannot find %s\n", bellfile);
+               exit(1);
+       }
+
+#ifdef NEWS
+       m_news();
+#endif
+       folder = 0; msgp = 0; linkf = 0;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-') {
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                       /* unknown */
+                       case -1:fprintf(stderr, "file: -%s unknown\n", cp);
+                               goto leave;
+                                                      /* -all */
+                       case 0: fprintf(stderr, "\"-all\" changed to \"all\"\n");
+                               goto leave;
+                       case 1: linkf = 1;  continue;  /* -link */
+                       case 2: linkf = 0;  continue;  /* -nolink */
+                       case 3: prsrvf = 1;  continue; /* -preserve */
+                       case 4: prsrvf = 0;  continue; /* -nopreserve */
+                       case 5: if(folder) {           /* -src */
+                                       fprintf(stderr, "Only one src folder.\n");
+                                       goto leave;
+                               }
+                               if(!(folder = *argp++) || *folder == '-') {
+missing:        fprintf(stderr, "file: Missing argument for %s switch\n", argp[-2]);
+                                       goto leave;
+                               }
+                               if(*folder == '+')
+                                       folder++;
+                               continue;
+                                                       /* -help */
+                       case 6:
+                               if(filec >= NFOLD) {
+                                       fprintf(stderr, "Too many src files.\n");
+                                       goto leave;
+                               }
+                               if(!(files[filec++] = *argp) || **argp++ == '-')
+                                       goto missing;
+                               continue;
+
+                       case 7: help("file   [msgs] [switches]  +folder ...",
+                                    switches);
+                               goto leave;
+                       }
+               }
+               if(*cp == '+')  {
+                       if(foldp < NFOLD)
+                               folders[foldp++].f_name = cp + 1;
+                       else {
+                               fprintf(stderr, "Only %d folders allowed.\n", NFOLD);
+                               goto leave;
+                       }
+               } else
+                       msgs[msgp++] = cp;
+       }
+       if(!foldp) {
+               fprintf(stderr, "No folder specified.\n");
+fprintf(stderr, "Usage: file [-src folder] [msg ...] [switches] +folder [+folder]\n");
+               goto leave;
+       }
+       if(filec > 1) {
+               if(msgp) {
+                       fprintf(stderr, "File: Can't mix files and messages.\n");
+                       goto leave;
+               }
+               for(i = 1; i < filec; i++)
+                       if(*files[i] != '/') {
+                               if(!pwds)
+                                       pwds = pwd();
+                               files[i] = concat(pwds, "/", files[i], 0);
+                       }
+               if(opnfolds())
+                       goto leave;
+               for(i = 1; i < filec; i++) {
+                       if(process(files[i]))
+                               goto leave;
+               }
+               if(!linkf) {
+                       if((cp = m_find("delete-prog")) != NULL) {
+                               files[0] = cp;
+                               execvp(cp, files);
+                               fprintf(stderr, "Can't exec deletion-prog--");
+                               perror(cp);
+                       } else for(i = 1; i < filec; i++) {
+                               if(unlink(files[i]) == -1) {
+                                       fprintf(stderr, "Can't unlink ");
+                                       perror(files[i]);
+                               }
+                       }
+               }
+               goto leave;
+       }
+       if(!msgp)
+               msgs[msgp++] = "cur";
+       if(!folder)
+               folder = m_getfolder();
+       copy(m_maildir(folder), maildir);
+       if(chdir(maildir) < 0) {
+               fprintf(stderr, "Can't chdir to: ");
+               perror(maildir);
+               goto leave;
+       }
+       if(!(mp = m_gmsg(folder))) {
+               fprintf(stderr, "Can't read folder %s!?\n",folder);
+               goto leave;
+       }
+       if(mp->hghmsg == 0) {
+               fprintf(stderr, "No messages in \"%s\".\n", folder);
+               goto leave;
+       }
+       for(msgnum = 0; msgnum < msgp; msgnum++)
+               if(!m_convert((cp = msgs[msgnum])))
+                       goto leave;
+       if(mp->numsel == 0) {
+               fprintf(stderr, "file:  ham 'n cheese\n");       /* never get here */
+               goto leave;
+       }
+       m_replace(pfolder, folder);
+       if(mp->hghsel != mp->curmsg && ((mp->numsel != mp->nummsg) || linkf))
+               m_setcur(mp->hghsel);
+       if(opnfolds())
+               goto leave;
+       for(msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
+               if(mp->msgstats[msgnum] & SELECTED)
+                       if(process(cp = getcpy(m_name(msgnum))))
+                               goto leave;
+                       else
+                               cndfree(cp);
+       if(!linkf) {
+               if((cp = m_find("delete-prog")) != NULL) {
+                       if(mp->numsel > MAXARGS-2) {
+         fprintf(stderr, "file: more than %d messages for deletion-prog\n",MAXARGS-2);
+                               printf("[messages not unlinked]\n");
+                               goto leave;
+                       }
+                       vecp = 1;
+                       vec = (char **) calloc(MAXARGS + 2, sizeof *vec);
+                       for(msgnum= mp->lowsel; msgnum<= mp->hghsel; msgnum++)
+                               if(mp->msgstats[msgnum]&SELECTED)
+                                       vec[vecp++] = getcpy(m_name(msgnum));
+                       vec[vecp] = 0;
+                       m_update();
+                       fflush(stdout);
+                       vec[0] = cp;
+                       execv(vec[0], vec);
+                       fprintf(stderr, "Can't exec deletion-prog--");
+                       perror(cp);
+               } else {
+                       for(msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
+                               if(mp->msgstats[msgnum] & SELECTED)
+                                       if(unlink(cp = m_name(msgnum))== -1) {
+                                               fprintf(stderr, "Can't unlink %s:",folder);
+                                               perror(cp);
+                                       }
+               }
+       }
+leave:
+       m_update();
+       done(0);
+}
+
+
+opnfolds()
+{
+       register int i;
+       register char *cp;
+       char nmaildir[128];
+
+       for(i = 0; i < foldp; i++) {
+               copy(m_maildir(folders[i].f_name), nmaildir);
+               if(access(nmaildir, 5) < 0) {
+                       cp = concat("Create folder \"", nmaildir, "\"? ", 0);
+                       if(!gans(cp, anoyes))
+                               goto bad;
+                       free(cp);
+                       if(!makedir(nmaildir)) {
+                               fprintf(stderr, "Can't create folder.\n");
+                               goto bad;
+                       }
+               }
+               if(chdir(nmaildir) < 0) {
+                       fprintf(stderr, "Can't chdir to: ");
+                       perror(nmaildir);
+                       goto bad;
+               }
+               if(!(folders[i].f_mp = m_gmsg())) {
+                       fprintf(stderr, "Can't read folder %s\n", folders[i].f_name);
+                       goto bad;
+               }
+       }
+       chdir(maildir);         /* return to src folder */
+       return(0);
+bad:
+       return(1);
+}
+
+
+process(msg)
+char *msg;
+{
+       char newmsg[256], buf[BUFSIZ];
+       register int i;
+       register char *nmsg;
+       register struct st_fold *fp;
+       struct stat stbuf, stbf1;
+       int n, o, linkerr;
+
+    for(fp = folders; fp < &folders[foldp]; fp++) {
+       if(prsrvf)
+               nmsg = msg;
+       else
+               nmsg = m_name(fp->f_mp->hghmsg++ + 1);
+       copy(nmsg, copy("/", copy(m_maildir(fp->f_name), newmsg)));
+       if(link(msg, newmsg) < 0) {
+               linkerr = errno;
+               if(linkerr == EEXIST ||
+                 (linkerr == EXDEV && stat(newmsg, &stbuf) != -1)) {
+                       if(linkerr != EEXIST || stat(msg, &stbf1) < 0 ||
+                          stat(newmsg, &stbuf) < 0 ||
+                          stbf1.st_ino != stbuf.st_ino) {
+                               fprintf(stderr, "Message %s:%s already exists.\n",
+                                    fp->f_name, msg);
+                               return(1);
+                       }
+                       continue;
+               }
+               if(linkerr == EXDEV) {
+                       if((o = open(msg, 0)) == -1) {
+                               fprintf(stderr, "Can't open %s:%s.\n",
+                                       folder, msg);
+                               return(1);
+                       }
+                       fstat(o, &stbuf);
+                       if((n = creat(newmsg, stbuf.st_mode&0777)) == -1) {
+                               fprintf(stderr, "Can't create %s:%s.\n",
+                                       fp->f_name, nmsg);
+                               close(o);
+                               return(1);
+                       }
+                       do
+                               if((i=read(o, buf, sizeof buf)) < 0 ||
+                                 write(n, buf, i) == -1) {
+                                   fprintf(stderr, "Copy error on %s:%s to %s:%s!\n",
+                                           folder, msg, fp->f_name, nmsg);
+                                   close(o); close(n);
+                                   return(1);
+                               }
+                       while(i == sizeof buf);
+                       close(n); close(o);
+               } else {
+                       fprintf(stderr, "Error on link %s:%s to %s:",
+                           folder, msg, fp->f_name);
+                       perror(nmsg);
+                       return(1);
+               }
+       }
+cont:   ;
+    }
+    return(0);
+}
+
+
+char *
+pwd()
+{
+       register FILE *pp;
+       static char curpath[128];
+       register int i;
+       FILE *popen();
+
+       if((pp = popen("pwd", "r")) == NULL ||
+           fgets(curpath, sizeof curpath, pp) == NULL ||
+           pclose(pp) != 0) {
+               fprintf(stderr, "Can't find current directory!\n");
+               done(1);
+       }
+       *rindex(curpath, '\n') = 0;     /* Zap the lf */
+       return curpath;
+}
diff --git a/docs/historical/mh-nov-1983/cmds/replsubs.c b/docs/historical/mh-nov-1983/cmds/replsubs.c
new file mode 100644 (file)
index 0000000..77c5735
--- /dev/null
@@ -0,0 +1,232 @@
+#include "mh.h"
+
+char *ltrim(cp)
+char *cp;
+{
+       /* Return pointer to 1st non-blank char in string;
+        * If ptr ==> 0 or ptr ==> '\n'0, return NUL;
+        */
+
+       register char *cp1;
+
+       cp1 = cp;
+       while((*cp1 == ' ') || (*cp1 == '\t')) cp1++;
+       if((*cp1 == 0) || (*cp1 == '\n' && cp1[1] == 0))
+               cp1 = 0;
+       return(cp1);
+}
+
+char *rtrim(cp)
+char *cp;
+{
+       /* trim newline and blanks from the right */
+
+       register char *cp1;
+
+       cp1 = cp+strlen(cp)-1;
+       if(*cp1 == '\n') *cp1 = 0;
+       while(*--cp1 == ' ') ;
+       *++cp1 = 0;
+       return(cp);
+}
+
+char *niceadd(this, that)
+char *this, *that;
+{
+       register char *from, *to;
+
+       if(!(from = ltrim(this)))               /* nothing to add */
+               return(that);
+
+       if(to = that)
+               to = add(",\n    ", rtrim(to)); /* enuf blanks for "cc: " */
+       return(add(from, to));
+}
+
+#define ADDRLEN (needadr ? addrlen : 0)
+
+char *fix(field, address)
+char *field, *address;
+{
+       /* Appends address to each needy addressee in "field".
+        * Returns pointer to copy of new string. (HUH?)
+        * "field" should never be 0
+        */
+
+       register int len;
+       register char *newp;
+       int addrlen;
+       int needadr;
+       int fieldlen;
+       char *cp;
+
+       addrlen = strlen(address);
+       len = 0;
+       newp = "";
+
+       for(cp = field; ;cp += fieldlen + 1) {
+               needadr = needsaddr(&cp, &fieldlen); /* cp may be changed */
+               if(fieldlen == 0) {
+                       cndfree(field);
+                       newp = add("\n", newp);
+                       return(newp);
+               }
+               if((len + fieldlen + ADDRLEN) > 70) {
+                       newp = add(",\n    ", newp);
+                       len = 4;
+               } else if (*newp) {
+                       newp = add(", ", newp);
+                       len += 2;
+               }
+               *(cp + fieldlen) = 0;
+               newp = add(cp, newp);
+               if(needadr)
+                       newp = add(address, newp);
+               len += fieldlen + ADDRLEN;
+       }
+}
+
+anychar(fchars, field)
+char *fchars, *field;
+{
+       /* Returns 1 if any fancy char appears in "field"
+        * Returns 0 if either "field" is nul or contains no fancy chars
+        */
+
+       register char *fp;
+
+       if(!field)
+               return(0);
+       for(fp = fchars; *fp; fp++)
+               if(r_any(*fp, field))
+                       return(1);
+       return(0);
+}
+
+
+r_any(chr,stg)
+char chr, *stg;
+{
+       register char c, *s;
+
+       c = chr;
+       for (s = stg; (*s) && (*s != ',') && (*s != '\n');)
+               if (*s++ == c) return (1);
+       return (0);
+}
+
+char *addr(text)
+char *text;
+{
+       static char buf[128];
+       register char *cp, *bufp;
+       int textseen, blankseen;
+       char *copyaddr();
+
+       textseen = blankseen = 0;
+       bufp = buf;
+       if(!text)
+               return(0);
+       for(cp = text; (*cp == ' ' || *cp == '\t'); cp++);
+       for(;;cp++) {
+               switch(*cp) {
+               default:
+                       textseen++;
+                       break;
+               case ' ':  case '\t':
+                       blankseen++;
+                       break;
+               case 'a':
+                       if(!blankseen || !textseen || !ssequal("at ",cp)){
+                               textseen++;
+                               break;
+                       }
+                       bufp = copy(" at ", buf);
+                       copyaddr(cp+3, bufp);
+                       return(buf);
+               case '@':
+                       if(!textseen)
+                               return(0);
+                       bufp = copy(" @ ", buf);
+                       copyaddr(cp+1, bufp);
+                       return(buf);
+               case ',':  case '\n':  case 0:
+                       return(0);
+               }
+       }
+}
+
+#define ND1  (*fp) && (*fp != ' ') && (*fp != '\t')
+#define ND2  (*fp != '<') && (*fp != '(') && (*fp != '>') && (*fp != ')')
+#define ND3  (*fp != '\n') && (*fp!= ',') && (*fp != ':')
+#define NOTDELIM  ND1 &&  ND2 && ND3
+
+char *copyaddr(from, to)
+char *from, *to;
+{
+       /* Copies left-trimmed "from" to "to".
+        * Copy terminates on any delimiter.
+        * Returns pointer to NUL terminator in destination string
+        */
+
+       register char *fp, *tp;
+
+       for(fp = from; (*fp == ' ') && (*fp == '\t'); fp++) ;
+       for( ; NOTDELIM; *tp++ = *fp++);
+       *tp = 0;
+       return(tp);
+}
+#define NOTRELEVANT (*cp == ' ' || *cp == '\t' || *cp == '\n'|| *cp == ',')
+
+needsaddr(field, fieldlen)
+char **field;
+int *fieldlen;
+{
+       /* Returns 1 if this field needs an address
+        * Returns 0 if field contains any funny chars or has
+        * an address of the form "xxxx at " or "xxxx[<b>]@"
+        * "field": on input --  addr of pointer to start of field
+        *          on output -- val of ptr moved to 1st meaty char
+        * "fieldlen" returns the length of the new field
+        *  (it terminates on ',' or '\n' or 0)
+        */
+
+       register char *cp;
+       int textseen, blankseen;
+       int retval;
+                                  /* find 1st relevant char in field */
+       for(cp = *field; NOTRELEVANT ; cp++);
+
+       *field = cp;               /* return it to caller */
+       if(anychar("(<:", cp)) {
+               retval = 0;
+               goto leave;
+       }
+       for(;;cp++) {
+               switch(*cp) {
+               default:
+                       textseen++;
+                       break;
+               case ' ':  case '\t':
+                       blankseen++;
+                       break;
+               case 'a':
+                       if(!blankseen || !textseen || !ssequal("at ",cp)){
+                               textseen++;
+                               break;
+                       }
+               case '@':
+                       retval = 0;
+                       goto leave;
+               case ',':  case '\n':  case 0:
+                       retval = 1;
+                       goto leave;
+
+               }
+       }
+ leave:
+       for(; (*cp) && (*cp != ',') && (*cp != '\n'); cp++) ;
+       *fieldlen = cp- *field;
+       return(retval);
+}
+
diff --git a/docs/historical/mh-nov-1983/cmds/reply.c b/docs/historical/mh-nov-1983/cmds/reply.c
new file mode 100644 (file)
index 0000000..3d59a39
--- /dev/null
@@ -0,0 +1,321 @@
+#include "mh.h"
+#include <stdio.h>
+#include <signal.h>
+#include <strings.h>
+
+/*#define NEWS 1*/
+
+#define NOUSE 0
+
+/* #define TEST 1 */
+
+char    *anyl[] = {
+       "no",   0,
+       "yes",  0,
+       "list", 0,
+       0
+};
+
+char *aleqs[] = {
+       "list",              0,         /* 0 */
+       "edit [<editor>]",   0,         /* 1 */
+       "quit [delete]",     0,         /* 2 */
+       "send [verbose]",    0,         /* 3 */
+       0
+};
+
+int  *vec[MAXARGS], anot;
+int ccme = 1;
+struct msgs *mp;
+char *ed;
+int inplace;            /* preserve links in anno */
+
+struct swit switches[] = {
+       "annotate",           0,      /* 0 */
+       "noannotate",         0,      /* 1 */
+       "ccme",              -1,      /* 2 */
+       "noccme",            -1,      /* 3 */
+       "editor editor",      0,      /* 4 */
+       "inplace",            0,      /* 5 */
+       "noinplace",          0,      /* 6 */
+       "help",               4,      /* 7 */
+       0,                    0
+};
+
+char *ltrim();
+char *rtrim();
+char *niceadd();
+char *fix();
+char *addr();
+
+main(argc, argv)
+char *argv[];
+{
+       char *folder, *nfolder, *msg, *maildir;
+       register char *cp, **ap;
+       register int cur;
+       char *arguments[50], **argp;
+
+#ifdef NEWS
+       m_news();
+#endif
+       msg = 0; anot = 0; folder = 0;
+
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                            /* unknown */
+                       case -1:fprintf(stderr, "repl: -%s unknown\n", cp);
+                               goto leave;
+                       case 0: anot = 1;  continue;         /* -annotate */
+                       case 1: anot = 0;  continue;         /* -noannotate */
+                       case 2: ccme = 1;  continue;         /* -ccme */
+                       case 3: ccme = 0;  continue;         /* -noccme */
+                       case 4: if(!(ed = *argp++)) {        /* -editor */
+               fprintf(stderr, "repl: Missing argument for %s switch\n", argp[-2]);
+                                       goto leave;
+                               }
+                               continue;
+                       case 5: inplace = 1;  continue;      /* -inplace */
+                       case 6: inplace = 0;  continue;      /* -noinplace */
+                                                            /* -help */
+                       case 7: help("repl   [+folder] [msg] [switches]",
+                                    switches);
+                               goto leave;
+                       }
+               if(*cp == '+') {
+                       if(folder) {
+                               fprintf(stderr, "Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               folder = cp + 1;
+               } else if(msg) {
+                       fprintf(stderr, "Only one message per reply.\n");
+                       goto leave;
+               } else
+                       msg = cp;
+       }
+       if(!msg)
+               msg = "cur";
+       if(!folder)
+               folder = m_getfolder();
+       maildir = m_maildir(folder);
+       if(chdir(maildir) < 0) {
+               fprintf(stderr, "Can't chdir to: ");
+               perror(maildir);
+               goto leave;
+       }
+       if(!(mp = m_gmsg(folder))) {
+               fprintf(stderr, "Can't read folder!?\n");
+               goto leave;
+       }
+       if(mp->hghmsg == 0) {
+               fprintf(stderr, "No messages in \"%s\".\n", folder);
+               goto leave;
+       }
+       if(!m_convert(msg))
+               goto leave;
+       if(mp->numsel == 0) {
+               fprintf(stderr, "repl: pepperoni pizza\n");/* never get here */
+               goto leave;
+       }
+       if(mp->numsel > 1) {
+               fprintf(stderr, "Only one message at a time.\n");
+               goto leave;
+       }
+       m_replace(pfolder, folder);
+       if(mp->lowsel != mp->curmsg)
+               m_setcur(mp->lowsel);
+       repl(getcpy(m_name(mp->lowsel)));
+ leave:
+       m_update();
+       done(0);
+}
+
+
+repl(msg)
+{
+       register char *cp;
+       register int i,j;
+       register FILE *in;
+       char name[NAMESZ], field[BUFSIZ];
+       char *drft, *msgid, *replto, *from, *cc, *sub, *date, *to;
+       int state, out, status, intr;
+       int pid, wpid;
+       char **argp, *address;
+
+       if((in = fopen(msg, "r")) == NULL) {
+               fprintf(stderr, "Can't open "); perror(msg);
+               return;
+       }
+       drft = m_maildir(draft);
+       if((out = open(drft, 0)) >= 0) {
+               cp = concat("\"", drft, "\" exists; delete? ", 0);
+               while((i = gans(cp, anyl)) == 2)
+                       showfile(drft);
+               if(!i)
+                       return;
+               free(cp);
+               close(out);
+       }
+       if((out = creat(drft, m_gmprot())) < 0) {
+               fprintf(stderr, "Can't create \"%s\".\n", drft);
+               return;
+       }
+
+       state = FLD;
+       replto = msgid = to = from = cc = sub = date = 0;
+
+    for(;;) {
+
+       switch(state = m_getfld(state, name, field, sizeof field, in)) {
+
+       case FLD:
+       case FLDEOF:
+       case FLDPLUS:
+               if(uleq(name, "from"))
+                       from = niceadd(field, from);
+               if(uleq(name, "cc"))
+                       cc = niceadd(field, cc);
+               if(uleq(name, "subject"))
+                       sub = niceadd(field, sub);
+               if(uleq(name, "date"))
+                       date = niceadd(field, date);
+               if(uleq(name, "to"))
+                       to = niceadd(field, to);
+               if(uleq(name, "message-id"))
+                       msgid = niceadd(field, msgid);
+               if(uleq(name, "reply-to"))
+                       replto = niceadd(field, replto);
+       /*      if(uleq(name, "sender"))
+                       sender = niceadd(field, sender);        */
+               if(state == FLDEOF)
+                       goto done;
+               break;
+
+       case BODY:
+       case BODYEOF:
+       case FILEEOF:
+               goto done;
+
+       default:
+               fprintf(stderr, "getfld returned %d\n", state);
+               return;
+       }
+
+    }
+
+done:
+
+    /*  if(!(address = addr(sender)))
+               if(!(address = addr(from)))
+                       address = addr(replto);
+    */
+   /*   if(!(address = addr(replto)))
+               address = addr(from);
+    */
+       address = replto ? addr(replto) : addr(from);
+       if(!ccme)
+               to = 0;
+       if(!(from || replto)) {
+               fprintf(stderr, "No one to reply to!!!\n");
+               return;
+       }
+       fclose(in);
+       type(out, "To: ");                      /* To: */
+       type(out, replto ? replto : from);
+       if(cc || to )                           /* cc: */
+               type(out, "cc: ");
+       if(cc) {
+               if(address)
+                       cc = fix(cc, address);
+               if(to)
+                       rtrim(cc);
+               type(out, cc);
+       }
+       if(to) {
+               if(cc)
+                       type(out, ",\n    ");
+               if(address)
+                       to = fix(to, address);
+               type(out, to);
+       }
+       if(sub) {                               /* Subject: Re: */
+               type(out, "Subject: ");
+               if(*sub == ' ') sub++;
+               if((sub[0] != 'R' && sub[0] != 'r') ||
+                  (sub[1] != 'E' && sub[1] != 'e') ||
+                  sub[2] != ':')
+                       type(out, "Re: ");
+               type(out, sub);
+       }                                       /* In-reply-to: */
+       if(date) {
+               type(out, "In-reply-to: Your message of ");
+               date[strlen(date)-1] = '.';
+               if(*date == ' ') date++;
+               type(out, date);
+               type(out, "\n");
+               if(msgid) {
+                       type(out, "             ");
+                       if(*msgid == ' ') msgid++;
+                       type(out, msgid);
+               }
+       }
+       type(out, "----------\n");
+       close(out);
+       if(m_edit(&ed, drft, NOUSE, msg) < 0)
+               return;
+#ifdef TEST
+       fprintf(stderr, "!! Test Version of SEND Being Run !!\n");
+       fprintf(stderr, "   Send verbose !\n\n");
+#endif
+
+    for(;;) {
+       if(!(argp = getans("\nWhat now? ", aleqs))) {
+               unlink("@");
+               return;
+       }
+       switch(smatch(*argp, aleqs)) {
+               case 0: showfile(drft);                         /* list */
+                       break;
+               case 1: if(*++argp)                             /* edit */
+                               ed = *argp;
+                       if(m_edit(&ed, drft, NOUSE, msg) == -1)
+                               return;
+                       break;
+               case 2: if(*++argp && *argp[0] == 'd')          /* quit */
+                               if(unlink(drft) == -1)  {
+                                       fprintf(stderr, "Can't unlink %s ", drft);
+                                       perror("");
+                               }
+                       return;
+               case 3: if(*++argp) cp = *argp;  else cp = "";  /* send */
+
+                       if(!mp->msgflags&READONLY) {    /* annotate first */
+                           if(anot > 0) {
+                               while((pid = fork()) == -1) sleep(5);
+                               if(pid) {
+                                       while(wpid=wait((int *)NULL)!= -1 && wpid!= pid);
+                                       if(stat(drft, field) == -1)
+                                               annotate(msg, "Replied", "", inplace);
+                                       return;
+                               }
+                           }
+                       }
+                       if(!m_send(cp, drft))
+                               return;
+               default:fprintf(stderr, "repl: illegal option\n");       /*##*/
+                       break;
+       }
+    }
+}
diff --git a/docs/historical/mh-nov-1983/cmds/rescue.c b/docs/historical/mh-nov-1983/cmds/rescue.c
new file mode 100644 (file)
index 0000000..57b8b1f
--- /dev/null
@@ -0,0 +1,415 @@
+/*
+ * Read up the messages in the named files and rehabilitate them into
+ * UNIX+ style messages on standard output.
+ *
+ * +Unix is a trademark of Bell Laboratories.
+ * The optional -d flag tests the arpa net to unix date format
+ * transformer by reading lines from standard input, modifying them
+ * to unix format, and outputing them on standard output.
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/time.h>
+
+char   *index(), *rindex(), *reform();
+long   emitl();
+int    errs;
+int    dateerrs;
+int    dflag;
+int    lastblank;
+
+main(argc, argv)
+       char **argv;
+{
+       register char *cp, *fname;
+
+       if (argc < 2) {
+               fprintf(stderr, "Usage: rescue name ...\n");
+               _exit(1);
+       }
+       lastblank = 1;
+       while (--argc) {
+               fname = *++argv;
+               if (strcmp(fname, "-d") == 0) {
+                       dflag++;
+                       dtest();
+                       exit(0);
+               }
+               cp = rindex(fname, '/');
+               if (cp == 0)
+                       cp = fname;
+               else
+                       cp++;
+               if (strcmp(cp, "cur") == 0)
+                       continue;
+               if (strcmp(cp, "select") == 0)
+                       continue;
+               if (*cp == '#')
+                       continue;
+               while (*cp)
+                       if (!isdigit(*cp++)) {
+                               fprintf(stderr, "%s: not mh message file\n",
+                                   fname);
+                               goto blog;
+                       }
+               fix(fname);
+blog:          ;
+       }
+       if (dateerrs)
+               fprintf(stderr, "%d bad date(s) replaced by current date\n",
+                   dateerrs);
+       exit(errs);
+}
+
+/*
+ * Fix the named file by putting together a reasonable header
+ * and outputing the stuff onto standard output.
+ */
+fix(name)
+       char name[];
+{
+       register FILE *in;
+       char linebuf[BUFSIZ], from[BUFSIZ], date[BUFSIZ];
+       register int inhead;
+       register char *cp;
+       int i;
+
+       if ((in = fopen(name, "r")) == NULL) {
+               perror(name);
+               errs++;
+               return;
+       }
+       from[0] = date[0] = 0;
+       for (; from[0] == 0 || date[0] == 0;) {
+               if (fgets(linebuf, BUFSIZ, in) == NULL)
+                       goto noheader;
+               if (strlen(linebuf) == 1)
+                       goto noheader;
+               if (linebuf[0] == '-')
+                       goto noheader;
+               if (isfield(linebuf, "from")) {
+                       cp = index(linebuf, ':');
+                       if (cp == 0)
+                               goto noheader;
+                       cp++;
+                       while (*cp && isspace(*cp))
+                               cp++;
+                       /*
+                       ** the below was: strcpy(from, cp);
+                       ** but this will not work, since
+                       ** headers can be like this:
+                       ** From: foo (foo bar)
+                       ** which /usr/ucb/Mail gags on... -layer
+                       */
+                       i = 0;
+                       while(*cp && !isspace(*cp))
+                               from[i++] = *cp++;
+                       from[i] = '\0';
+                       continue;
+               }
+               if (isfield(linebuf, "date")) {
+                       cp = index(linebuf, ':');
+                       if (cp == 0)
+                               goto noheader;
+                       cp++;
+                       while (*cp && isspace(*cp))
+                               cp++;
+                       strcpy(date, cp);
+                       continue;
+               }
+       }
+       /*
+        * Ready to print the from line
+        */
+       zap(from);
+       zap(date);
+       if (!lastblank)
+               printf("\n");
+       printf("From %s %s\n", from, reform(date));
+       lastblank = 0;
+       rewind(in);
+       inhead = 1;
+       while (fgets(linebuf, BUFSIZ, in) != NULL) {
+               if (inhead &&
+                   (isfield(linebuf, "from") || isfield(linebuf, "date")))
+                       continue;
+               if (strlen(linebuf) == 1)
+                       inhead = 0;
+               fputs(linebuf, stdout);
+               lastblank = 0;
+               if (linebuf[0] == '\n' && linebuf[1] == 0)
+                       lastblank = 1;
+       }
+       fclose(in);
+       return;
+noheader:
+       fprintf(stderr, "%s:  Missing, bad, or incomplete header\n", name);
+       errs++;
+       fclose(in);
+}
+
+/*
+ * Determine if the passed line is a header of the given field name
+ */
+isfield(buf, field)
+       char buf[];
+       char field[];
+{
+       register char *cp, *cp2;
+
+       cp = buf;
+       cp2 = field;
+       while (lower(*cp++) == lower(*cp2++))
+               ;
+       if (*--cp == ':' && *--cp2 == 0)
+               return(1);
+       return(0);
+}
+
+/*
+ * Lower case the given character
+ */
+lower(c)
+       register int c;
+{
+
+       if (isupper(c))
+               return(tolower(c));
+       return(c);
+}
+
+/*
+ * Remove trailing newline from str, if present.
+ */
+zap(str)
+       char str[];
+{
+       register char *cp;
+
+       cp = index(str, '\n');
+       if (cp != 0)
+               *cp = 0;
+}
+
+/*
+ * Reformat the given Arpa net style date
+ * back into a unix ctime(3) date.
+ * Unfortunately, there appears to be NO standard arpa net
+ * date format.
+ */
+
+char *month = "janfebmaraprmayjunjulaugsepoctnovdec";
+
+char *
+reform(date)
+       char date[];
+{
+       static char retdate[35];
+       char dbuf[BUFSIZ];
+       register char *cp, *cp2, *mptr;
+       struct tm d;
+       long x, then;
+
+       cp = date;
+       cp2 = dbuf;
+       while (*cp) {
+               if (*cp == '(') {
+                       while (*cp != ')' && *cp)
+                               cp++;
+                       if (*cp)
+                               cp++;
+                       goto more;
+               }
+               if (*cp == '\t') {
+                       *cp2++ = ' ';
+                       cp++;
+                       continue;
+               }
+               if (*cp == '-') {
+                       *cp2++ = ' ';
+                       cp++;
+                       continue;
+               }
+               if (isupper(*cp)) {
+                       *cp2++ = tolower(*cp++);
+                       continue;
+               }
+               *cp2++ = *cp++;
+more:          ;
+       }
+       *cp2 = 0;
+       /*
+        * Okie dokie.  Now pick off the date part and store
+        * it away.  Only possible formats here are:
+        *      mm/dd/yy
+        * and
+        *      dd monthname year
+        */
+       if (index(dbuf, '/')) {
+               d.tm_mon = atoi(dbuf) - 1;
+               cp = index(dbuf, '/') + 1;
+               d.tm_mday = atoi(cp);
+               if ((cp = index(cp, '/')) == 0)
+                       goto baddate;
+               cp++;
+               d.tm_year = atoi(cp);
+               if (d.tm_year > 1900)
+                       d.tm_year -= 1900;
+               cp = index(cp, ' ');
+               if (cp == 0)
+                       goto baddate;
+       }
+       else {
+               d.tm_mday = atoi(dbuf);
+               cp = index(dbuf, ' ');
+               if (cp == 0)
+                       goto baddate;
+               while (*cp && isspace(*cp))
+                       cp++;
+               if (*cp == 0)
+                       goto baddate;
+               for (mptr = month; *mptr; mptr += 3)
+                       if (strcmpn(mptr, cp, 3) == 0)
+                               break;
+               if (*mptr == 0)
+                       goto baddate;
+               d.tm_mon = (mptr - month)/3;
+               cp = index(cp, ' ');
+               if (cp == 0)
+                       goto baddate;
+               while (*cp && isspace(*cp))
+                       cp++;
+               if (*cp == 0)
+                       goto baddate;
+               d.tm_year = atoi(cp);
+               if (d.tm_year > 1900)
+                       d.tm_year -= 1900;
+               cp = index(cp, ' ');
+               if (cp == 0)
+                       goto baddate;
+       }
+       /*
+        * Got the month part, now fix up the time.
+        * Possibilities are:
+        *      hh:mm
+        *      hh:mm [am|pm]
+        *      hhmm edt
+        *      hh:mm:ss edt
+        * Basically, we lose by ignoring time zone.
+        */
+       for (;;) {
+               while (*cp && isspace(*cp))
+                       cp++;
+               if (*cp == 0)
+                       goto baddate;
+               if (strcmpn(cp, "at ", 3) != 0)
+                       break;
+               cp += 3;
+       }
+       d.tm_sec = 0;
+       if (index(cp, ':')) {
+               d.tm_hour = atoi(cp);
+               cp = index(cp, ':') + 1;
+               d.tm_min = atoi(cp);
+               if (index(cp, ':')) {
+                       cp = index(cp, ':') + 1;
+                       d.tm_sec = atoi(cp);
+               }
+               while (*cp && !isspace(*cp))
+                       cp++;
+               while (*cp && isspace(*cp))
+                       cp++;
+               if (strcmpn(cp, "pm", 2) == 0 && d.tm_hour < 12)
+                       d.tm_hour += 12;
+       }
+       else {
+               x = atoi(cp);
+               d.tm_hour = x / 100;
+               d.tm_min = x % 100;
+       }
+       then = emitl(&d);
+       strcpy(retdate, ctime(&then));
+       zap(retdate);
+       return(retdate);
+
+baddate:
+       dateerrs++;
+       if (dflag)
+               strcpy(retdate, "************************");
+       else {
+               then = time(0);
+               strcpy(retdate, ctime(&then));
+               zap(retdate);
+       }
+       return(retdate);
+}
+
+/*
+ * Test the arpa net to UNIX date modifier.
+ * Reads lines from standard input, converting them
+ * to unix format, and displaying both on stdout.
+ */
+dtest()
+{
+       char buf[BUFSIZ];
+       register char *cp;
+
+       while (gets(buf)) {
+               cp = reform(buf);
+               printf("\"%s\"  \"%s\"\n", buf, cp);
+       }
+}
+
+/*
+ * Routine to convert a localtime(3) format date back into
+ * a system format date.
+ *
+ * Hats off to Bob Kridle for the insight that the way to do
+ * this is by binary search of the system date space.
+ */
+
+struct tm *localtime();
+
+long
+emitl(dp)
+       struct tm *dp;
+{
+       long conv;
+       register int i, bit;
+       struct tm dcopy;
+
+       dcopy = *dp;
+       dp = &dcopy;
+       conv = 0;
+       for (i = 31; i >= 0; i--) {
+               bit = 1 << i;
+               conv |= bit;
+               if (dcmp(localtime(&conv), dp) > 0)
+                       conv &= ~bit;
+       }
+       return(conv);
+}
+
+/*
+ * Compare two localtime dates, return result.
+ */
+
+#define DECIDE(a) \
+       if (dp->a > dp2->a) \
+               return(1); \
+       if (dp->a < dp2->a) \
+               return(-1)
+
+dcmp(dp, dp2)
+       register struct tm *dp, *dp2;
+{
+
+       DECIDE(tm_year);
+       DECIDE(tm_mon);
+       DECIDE(tm_mday);
+       DECIDE(tm_hour);
+       DECIDE(tm_min);
+       DECIDE(tm_sec);
+       return(0);
+}
diff --git a/docs/historical/mh-nov-1983/cmds/rmf.c b/docs/historical/mh-nov-1983/cmds/rmf.c
new file mode 100644 (file)
index 0000000..3522bce
--- /dev/null
@@ -0,0 +1,166 @@
+#ifndef lint
+static char sccsid[] = "@(#)rmf.c      1.4 7/7/83";
+#endif
+
+#include "mh.h"
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/dir.h>
+#include "strings.h"
+
+char *anoyes[];         /* Std no/yes gans array        */
+
+int     subf;
+
+struct msgs *mp;
+
+struct swit switches[] = {
+       "help",         4,      /* 0 */
+       0,              0
+};
+
+main(argc, argv)
+char *argv[];
+{
+       register char *cp, **ap;
+       char *folder, buf[128];
+       int i, def_fold;
+       char *arguments[50], **argp;
+
+#ifdef NEWS
+       m_news();
+#endif
+       folder = 0;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                       /* unknown */
+                       case -1:fprintf(stderr, "rmf: -%s unknown\n", cp);
+                               goto leave;
+                                                       /* -help */
+                       case 0: help("rmf [+folder]  [switches]", switches);
+                               goto leave;
+                       }
+               if(*cp == '+')
+                       if(folder) {
+                               fprintf(stderr, "Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               folder = cp + 1;
+               else {
+                       fprintf(stderr, "Usage: rmf [+folder]\n");
+                       goto leave;
+               }
+       }
+       if(!folder) {
+               folder = m_getfolder();
+               def_fold++;
+       }
+       subf = !((!index(folder, '/')) | (*folder == '/') | (*folder == '.'));
+       if(def_fold && !subf) {
+               cp = concat("Remove folder \"", folder, "\" ?? ", 0);
+               if(!gans(cp, anoyes))
+                       goto leave;
+               free(cp);
+       }
+       if(rmfold(folder))
+               goto leave;
+       if(subf) {                      /* make parent "current" */
+               cp = copy(folder, buf);
+               while(cp > buf && *cp != '/') --cp;
+               if(cp > buf) {
+                       *cp = 0;
+                       if(strcmp(m_find(pfolder), buf) != 0) {
+                               printf("[+%s now current]\n", buf);
+                               m_replace(pfolder, buf);
+                       }
+               }
+       }
+ leave:
+       m_update();
+       done(0);
+}
+
+rmfold(fold)
+char *fold;
+{
+       register char *maildir;
+       struct direct *ent;
+       int i, leftover, cd;
+       register char *cp, *sp;
+       char nambuf[10];
+       register DIR *dirp;
+
+       leftover = 0;
+       if(!subf && strcmp(m_find(pfolder), fold) == 0) /* make default "current"*/
+               if(strcmp(m_find(pfolder), defalt) != 0) {
+                       printf("[+%s now current]\n", defalt);
+                       fflush(stdout);                          /*??*/
+                       m_replace(pfolder, defalt);
+               }
+       maildir = m_maildir(fold);
+       if((cd = chdir(maildir)) < 0)
+               goto funnyfold;
+       if(access(".", 2) == -1) {
+ funnyfold:     if(!m_delete(concat("cur-", fold, 0)))
+                       printf("[Folder %s de-referenced]\n", fold);
+               else
+                       fprintf(stderr, "You have no profile entry for the %s folder %s\n",
+                         cd < 0 ? "unreadable" : "read-only", fold);
+               return(1);
+       }
+       dirp = opendir(".");
+       ent = readdir(dirp);            /* move pointer past "." */
+       ent = readdir(dirp);            /* move pointer past ".." */
+       while(ent = readdir(dirp)) {
+               if (ent->d_ino==0) continue;
+               switch (ent->d_name[0]) {
+                       case '0':
+                       case '1':
+                       case '2':
+                       case '3':
+                       case '4':
+                       case '5':
+                       case '6':
+                       case '7':
+                       case '8':
+                       case '9':
+                       case '#':
+                       case ',':
+                               if(unlink(ent->d_name) == -1) {
+                                       fprintf(stderr, "Can't unlink %s:%s\n", fold,ent->d_name);
+                                       leftover++;
+                               }
+                               break;
+                       default:
+                               if (strcmp(ent->d_name, "cur") == 0 ||
+                                   strcmp(ent->d_name, "@") == 0) {
+                                       if(unlink(ent->d_name) == -1) {
+                                               fprintf(stderr, "Can't unlink %s:%s\n", fold,ent->d_name);
+                                               leftover++;
+                                       }
+                               } else {
+                                       fprintf(stderr, "File \"%s/%s\" not deleted!\n", fold, ent->d_name);
+                                       leftover++;
+                               }
+               }
+       }
+       closedir(dirp);
+       chdir("..");            /* Move out of dir to be deleted */
+       if (leftover) {
+               fprintf(stderr, "Folder %s not removed!\n", fold);
+               return(1);
+       }
+       if(rmdir(maildir))
+               fprintf(stderr, "rmdir failed!\n");
+}
diff --git a/docs/historical/mh-nov-1983/cmds/rmm.c b/docs/historical/mh-nov-1983/cmds/rmm.c
new file mode 100644 (file)
index 0000000..da34094
--- /dev/null
@@ -0,0 +1,131 @@
+#ifndef lint
+static char sccsid[] = "@(#)rmm.c      4.1 2/23/83";
+#endif
+
+#include "mh.h"
+#include <stdio.h>
+#include <strings.h>
+
+int     vecp;
+char    **vec;
+struct msgs *mp;
+
+struct swit switches[] = {
+       "all",         -3,      /* 0 */
+       "help",         4,      /* 1 */
+       0,              0
+};
+
+main(argc, argv)
+char *argv[];
+{
+       char *folder, *nfolder, *maildir, *msgs[100], buf[32];
+       register int msgnum;
+       register char *cp, *sp;
+       int msgp;
+       char **ap;
+       char *arguments[50], **argp;
+
+#ifdef NEWS
+       m_news();
+#endif
+       folder = 0; msgp = 0;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                       /* unknown */
+                       case -1:fprintf(stderr, "rmm: -%s unknown\n", cp);
+                               goto leave;
+                                                        /* -all */
+                       case 0: fprintf(stderr, "\"-all\" changed to \"all\"\n");
+                               goto leave;
+                                                       /* -help */
+                       case 1: help("rmm [+folder]  [msgs] [switches]",
+                                    switches);
+                               goto leave;
+                       }
+               if(*cp == '+')  {
+                       if(folder) {
+                               fprintf(stderr, "Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               folder = cp + 1;
+               } else
+                       msgs[msgp++] = cp;
+       }
+       if(!msgp)
+               msgs[msgp++] = "cur";
+       if(!folder)
+               folder = m_getfolder();
+       maildir = m_maildir(folder);
+       if(chdir(maildir) < 0) {
+               fprintf(stderr, "Can't chdir to: ");
+               perror(maildir);
+               goto leave;
+       }
+       if(!(mp = m_gmsg(folder))) {
+               fprintf(stderr, "Can't read folder!?\n");
+               goto leave;
+       }
+       if(mp->hghmsg == 0) {
+               fprintf(stderr, "No messages in \"%s\".\n", folder);
+               goto leave;
+       }
+       for(msgnum = 0; msgnum < msgp; msgnum++)
+               if(!m_convert(msgs[msgnum]))
+                       goto leave;
+       if(mp->numsel == 0) {
+               fprintf(stderr, "rmm: lasagne 'n sausage\n");     /* never get here */
+               goto leave;
+       }
+       m_replace(pfolder, folder);
+       if((cp = m_find("delete-prog")) == NULL) {
+               for(msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
+                       if(mp->msgstats[msgnum] & SELECTED) {
+                               sp = getcpy(m_name(msgnum));
+                               cp = copy(sp, buf);
+                               cp[1] = 0;
+                               do
+                                       *cp = cp[-1];
+                               while(--cp >= buf && *cp != '/');
+#ifdef UCB
+                               *++cp = '#';
+#else
+                               *++cp = ',';
+#endif
+                               unlink(buf);
+                               if(link(sp, buf) == -1 || unlink(sp) == -1)
+                                       fprintf(stderr, "Can't rename %s to %s.\n", sp, buf);
+                       }
+       } else {
+               if(mp->numsel > MAXARGS-2) {
+  fprintf(stderr, "rmm: more than %d messages for deletion-prog\n",MAXARGS-2);
+                       goto leave;
+               }
+               vec = (char **) calloc(MAXARGS +2, sizeof *vec);
+               vecp = 1;
+               for(msgnum= mp->lowsel; msgnum<= mp->hghsel; msgnum++)
+                       if(mp->msgstats[msgnum]&SELECTED)
+                               vec[vecp++] = getcpy(m_name(msgnum));
+               vec[vecp] = 0;
+               vec[0] = cp;
+               m_update();
+               fflush(stdout);
+               execv(vec[0], vec);
+               fprintf(stderr, "Can't exec deletion prog--");
+               perror(cp);
+       }
+leave:
+       m_update();
+       done(0);
+}
diff --git a/docs/historical/mh-nov-1983/cmds/scan.c b/docs/historical/mh-nov-1983/cmds/scan.c
new file mode 100644 (file)
index 0000000..72ef38c
--- /dev/null
@@ -0,0 +1,128 @@
+#include "mh.h"
+#include <stdio.h>
+#include <strings.h>
+
+int hdrflag = 1;
+int reverse = 0;
+struct msgs *mp;
+
+struct swit switches[] = {
+       "all",         -3,      /* 0 */
+       "ff",           0,      /* 1 */
+       "noff",         0,      /* 2 */
+       "header",       0,      /* 3 */
+       "noheader",     0,      /* 4 */
+       "reverse",      0,      /* 5 */
+       "help",         4,      /* 6 */
+       0,              0
+};
+
+main(argc, argv)
+char *argv[];
+{
+       char *folder, *maildir, *msgs[100];
+       register int msgnum;
+       register char *cp, **ap;
+       int msgp, ff;
+       FILE *in;
+       long now;
+       char *arguments[50], **argp;
+       extern char _sobuf[];
+
+       setbuf(stdout, _sobuf);
+#ifdef NEWS
+       m_news();
+#endif
+       ff = 0; msgp = 0; folder = 0;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                       /* unknown */
+                       case -1:fprintf(stderr, "scan: -%s unknown\n", cp);
+                               goto leave;
+                                                        /* -all */
+                       case 0: fprintf(stderr, "\"-all\" changed to \"all\"\n");
+                               goto leave;
+                       case 1: ff = 1;  continue;      /* -ff */
+                       case 2: ff = 0;  continue;      /* -noff */
+                       case 3: hdrflag = 0;  continue; /* -header */
+                       case 4: hdrflag = 1;  continue; /* -noheader */
+                       case 5: reverse = 1;  continue; /* -reverse */
+                       case 6: help("scan [+folder]  [msgs] [switches]",
+                                    switches);
+                               goto leave;
+                       }
+               if(*cp == '+') {
+                       if(folder) {
+                               fprintf(stderr, "Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               folder = cp + 1;
+               } else
+                       msgs[msgp++] = cp;
+       }
+       if(!folder)
+               folder = m_getfolder();
+       maildir = m_maildir(folder);
+       if(chdir(maildir) < 0) {
+               fprintf(stderr, "Can't chdir to: ");
+               perror(maildir);
+               goto leave;
+       }
+       if(!(mp = m_gmsg(folder))) {
+               fprintf(stderr, "Can't read folder!?\n");
+               goto leave;
+       }
+       if(mp->hghmsg == 0) {
+               fprintf(stderr, "No messages in \"%s\".\n", folder);
+               goto leave;
+       }
+       if(!msgp)
+               msgs[msgp++] = "first-last";
+       for(msgnum = 0; msgnum < msgp; msgnum++)
+               if(!m_convert(msgs[msgnum]))
+                       goto leave;
+       if(mp->numsel == 0) {
+               fprintf(stderr, "scan: matzo balls.\n");         /* never get here */
+               goto leave;
+       }
+       m_replace(pfolder,folder);
+       for( msgnum = (reverse ? mp->hghsel : mp->lowsel);
+            (reverse ? msgnum >= mp->lowsel : msgnum <= mp->hghsel); 
+            (reverse ? msgnum-- : msgnum++))  {
+               if(mp->msgstats[msgnum]&SELECTED) {
+                       if((in = fopen(cp = m_name(msgnum), "r")) == NULL)
+                               fprintf(stderr, "--Can't open %s\n", cp);
+                       else {
+                               if(!hdrflag++) {
+                                       time(&now);
+                                       cp = cdate(&now);
+                                       cp[9] = ' '; cp[15] = 0;
+printf("\
+                      Folder %-32s%s\n\n\
+  #   Date    From             Subject       [<<Body]\n\n", folder, cp);
+                               }
+                               scan(in, msgnum, 0, msgnum == mp->curmsg);
+                               fclose(in);
+                               if(stdout->_cnt < 80)
+                                       fflush(stdout);
+                       }
+               }
+       }
+       if(ff)
+               putchar('\014');
+leave:
+       m_update();
+       done(0);
+}
+
diff --git a/docs/historical/mh-nov-1983/cmds/scansub.c b/docs/historical/mh-nov-1983/cmds/scansub.c
new file mode 100644 (file)
index 0000000..dc3d1df
--- /dev/null
@@ -0,0 +1,407 @@
+#include "mh.h"
+#include <stdio.h>
+
+#define _FROM    1
+#define _NOTFROM 0
+
+
+#define FROM    13              /* Start of From field          */
+#define SFROM   16              /* Length of "        "         */
+#define DATE     5              /* Start of Date field          */
+#define SDATE    7              /* Length                       */
+#define SUBJ    31              /* Start of Subject field       */
+#define SSUBJ   (79-SUBJ)       /* Size of Subject field        */
+#define BSUBJ   20              /* Room needed in Sub field to  */
+                               /* add stuff from the body      */
+#define MSGN     0              /* Start of msg name field      */
+#define SMSGN    3              /* Length                       */
+#define FLGS     3              /* Start of flags field         */
+#define SFLGS    2              /* Width of flag field          */
+
+FILE  *scnout;
+char scanl[82];
+int local;
+int hostseen;
+char *frmtok();
+
+scan(inb, innum, outnum, curflg)
+struct iobuf *inb;
+int outnum;
+{
+
+       char buf[BUFSIZ], name[NAMESZ], tobuf[32], frombuf[32];
+       register char *cp, **tok1;
+       int state, subsz, first, compnum;
+       static char *myname;
+
+       local = 0; hostseen = 0;
+       if(!myname)
+               myname = getenv("USER");
+       tobuf[0] = 0; frombuf[0] = 0;
+       first = 0;
+       state = FLD;
+       compnum = 1;
+
+       for(;;) {
+
+               state = m_getfld(state, name, buf, sizeof buf, inb);
+               if(!first++ && state != FILEEOF) {      /*##*/
+                   if(outnum) {
+                       if((scnout = fopen(cp = m_name(outnum), "w")) == NULL) {
+                               fprintf(stderr, "Error creating msg ");
+                               perror(cp); done(-1);
+                       }
+                       chmod(cp, m_gmprot());
+                   }
+                   sfill(scanl, sizeof scanl);
+                   scanl[sizeof scanl - 1] = 0;
+                   subsz = 0;
+                   tobuf[0] = 0;
+               }
+
+               switch(state) {
+
+               case FLD:
+               case FLDEOF:
+               case FLDPLUS:
+                       compnum++;
+                       if(uleq(name, "from"))
+                               frombuf[
+                                  cpyfrm(buf,frombuf,sizeof frombuf,_FROM)]=0;
+                       else if(uleq(name, "date"))
+                               cpydat(buf, scanl+DATE, SDATE);
+                       else if(uleq(name, "subject") && scanl[SUBJ] == ' ')
+                               subsz = cpy(buf, scanl+SUBJ, SSUBJ);
+                       else if(uleq(name, "to") && !tobuf[0])
+                               tobuf[
+                                  cpyfrm(buf,tobuf,sizeof tobuf-1,_NOTFROM)]=0;
+                       else if(uleq(name, "replied"))
+                               cpy("-", scanl+FLGS+1, 1);
+                       put(name, buf, scnout);
+                       while(state == FLDPLUS) {
+                               state=m_getfld(state,name,buf,sizeof buf,inb);
+                               if(scnout)
+                                       fputs(buf, scnout);
+                       }
+                       if(state == FLDEOF)
+                               goto putscan;
+                       continue;
+
+               case BODY:
+               case BODYEOF:
+                       compnum = -1;
+                       if(buf[0] && subsz < SSUBJ - BSUBJ) {
+                               scanl[SUBJ+subsz+1] = '<';
+                               scanl[SUBJ+subsz+2] = '<';
+                               cpy(buf, scanl+SUBJ+subsz+3, SSUBJ-subsz-3);
+                               subsz = SSUBJ;
+                       }
+                       if(buf[0] && scnout) {
+                               putc('\n', scnout);
+                               fputs(buf, scnout);
+                               if(ferror(scnout)) {
+                                       fprintf(stderr, "Write error on ");
+                                       perror(m_name(outnum));done(-1);
+                               }
+                       }
+       body:           while(state == BODY) {
+                               state=m_getfld(state,name,buf,sizeof buf,inb);
+                               if(scnout)
+                                       fputs(buf, scnout);
+                       }
+                       if(state == BODYEOF) {
+                 putscan:      cpymsgn(m_name(innum), scanl+MSGN, SMSGN);
+                               tok1= brkstring(getcpy(frombuf), " ", "\n");
+                               if(!frombuf[0] || uleq(frombuf, myname) ||
+                                 (local && uleq(*tok1, myname))) {
+                                       cpy("To:", scanl+FROM, 3);
+                                       cpy(tobuf, scanl+FROM+3, SFROM-3);
+                               } else
+                                       cpy(frombuf, scanl+FROM, SFROM);
+                               if(curflg)
+                                       cpy("+", scanl+FLGS, SFLGS);
+                               trim(scanl);
+                               fputs(scanl, stdout);
+
+                               if(scnout) {
+                                       fflush(scnout);
+                                       if(ferror(scnout)) {
+                                               perror("Write error on ");
+                                               perror(m_name(outnum));
+                                               done(-1);
+                                       }
+                                       fclose(scnout);
+                                       scnout = NULL;
+                               }
+                               return(1);
+                       }
+                       break;
+
+               case LENERR:
+               case FMTERR:
+                       fprintf(stderr, "??Message Format Error ");
+                       fprintf(stderr, "(Message %d) ", outnum ? outnum :innum);/*##*/
+                       if(compnum < 0) fprintf(stderr, "in the Body.\n");
+                       else fprintf(stderr, "in Component #%d.\n", compnum);
+                       fprintf(stderr, "-----------------------------------------");
+                       fprintf(stderr, "-------------------------------------\n");
+                       goto badret;
+               default:
+                       fprintf(stderr, "Getfld returned %d\n", state);
+
+
+       badret:         if(outnum) {
+                               fputs("\n\nBAD MSG:\n", scnout);
+                               if(compnum < 0)
+                                       fputs(buf, scnout);
+                               else
+                                       fputs(name, scnout);
+                       /***    ungetc(inb);    ***/
+                               state = BODY;
+                               goto  body;
+
+                       }
+                       if(scnout)
+                               fflush(scnout);
+                       return(-1);
+               case FILEEOF:
+                       return(0);
+
+               }
+
+       }
+}
+
+
+trim(str)
+char *str;
+{
+       register char *cp;
+
+       cp = str;
+       while(*cp) cp++;
+       while(*--cp == ' ') ;
+       cp++;
+       *cp++ = '\n';
+       *cp++ = 0;
+}
+
+sfill(str, cnt)
+char *str;
+{
+       register char *cp;
+       register int i;
+
+       cp = str;  i = cnt;
+       do
+               *cp++ = ' ';
+       while(--i);
+}
+
+
+put(name, buf, ip)
+register FILE *ip;
+{
+       if(ip) {
+               fputs(name, ip);
+               putc(':', ip);
+               fputs(buf, ip);
+               if(ferror(ip)) { perror("Write error");done(-1);}
+       }
+}
+
+
+cpy(from, to, cnt)
+register char *from, *to;
+register int cnt;
+{
+       register int c;
+       char *sfrom;
+
+       sfrom = from;
+       while(*from == ' ' || *from == '\t' || *from == '\n')
+               from++;
+       while(cnt--)
+               if(c = *from) {
+                       if(c == '\t' || c == ' ' || c == '\n') {
+                               *to++ = ' ';
+                               do 
+                                       from++;
+                               while((c= *from)==' '||c=='\t'||c=='\n');
+                               continue;
+                       } else
+                               *to++ = c;
+                       from++;
+               } else
+                       break;
+       return(from - sfrom - 1);
+}
+
+int *localtime();
+char *findmonth();
+
+cpydat(sfrom, sto, cnt)
+char *sfrom, *sto;
+{
+       register char *from, *cp;
+       register int c;
+       static int *locvec;
+       long now;
+       char *to;
+
+       if(!locvec) {
+               time(&now);
+               locvec = localtime(&now);
+       }
+       to = sto;
+       for(from = sfrom; (c = *from) < '0' || c > '9'; from++)
+               if(!c)
+                       return;
+       c = cnt;
+       for(cp = from; (*cp >= '0' && *cp <= '9') || *cp == ' '; cp++);
+       if(cp = findmonth(cp)) {
+               if(!cp[1]) {
+                       *to++ = ' ';
+                       c--;
+               }
+               while(*cp && c--)
+                       *to++ = *cp++;
+               c--;  *to++ = '/';
+               if(from[1] == ' ') {
+                       *to++ = ' ';
+                       c--;
+               }
+               while(*from >= '0' && *from <= '9' && c--)
+                       *to++ = *from++;
+               if(c >= 2) {
+                       while(*from < '0' || *from > '9') from++;
+                       if(((c = atoi(from)) > 1970 && c-1900 < locvec[5])
+                           || c < locvec[5])  {
+                               *to++ = '/';
+                               *to++ = (c < 100) ? (c - 70 + '0')
+                                                 : (c - 1970 + '0');
+                       }
+               }
+               return;
+       }
+       if(from[1] == ' ') {
+               *to++ = ' ';
+               c--;
+       }
+       while(*from && c--)
+               *to++ = *from++;
+}
+
+
+char    *fromp, fromdlm, pfromdlm;
+
+cpyfrm(sfrom, sto, cnt, fromcall)
+char *sfrom, *sto;
+{
+       register char *to, *cp;
+       register int c;
+
+       fromdlm = ' ';
+       fromp = sfrom; to = sto;
+       cp = frmtok();
+       do
+               if(c = *cp++)
+                       *to++ = c;
+               else
+                       break;
+       while(--cnt);
+       for(;;) {
+               if(cnt < 3) break;
+               if(*(cp = frmtok()) == 0) break;
+               if(*cp == '@' || uleq(cp, "at")) {
+                       cp = frmtok();
+                       if(uleq(cp, "berkeley")) {
+                               /* if the first "From:" host is local */
+                               if(fromcall && !hostseen++)
+                                       local++;
+                       } else {
+                               *to++ = '@';
+                               cnt--;
+                               do
+                                       if(c = *cp++)
+                                               *to++ = c;
+                                       else
+                                               break;
+                               while(--cnt);
+                       }
+               } else if(cnt > 4) {
+                       cnt--; *to++ = pfromdlm;
+                       do
+                               if(c = *cp++)
+                                       *to++ = c;
+                               else
+                                       break;
+                       while(--cnt);
+               }
+       }
+       if(fromcall)
+               hostseen++;
+       return(to - sto);
+}
+
+
+char *frmtok()
+{
+       static char tokbuf[64];
+       register char *cp;
+       register int c;
+
+       pfromdlm = fromdlm;
+       cp = tokbuf; *cp = 0;
+       while(c = *fromp++) {
+               if(c == '\t')
+                       c = ' ';
+               if(c == ' ' && cp == tokbuf)
+                       continue;
+               if(c == ' ' || c == '\n' || c == ',')
+                       break;
+               *cp++ = c;
+               *cp = 0;
+               if(c == '@' || *fromp == '@' || cp == &tokbuf[63])
+                       break;
+       }
+       fromdlm = c;
+       return(tokbuf);
+}
+
+
+/*      num specific!         */
+
+cpymsgn(msgnam, addr, len)
+char *msgnam, *addr;
+{
+       register char *cp, *sp;
+
+       sp = msgnam;
+       cp = addr + (len - strlen(sp));
+       while(*sp)
+               *cp++ = *sp++;
+}
+
+char *monthtab[] = {
+       "jan", "feb", "mar", "apr", "may", "jun",
+       "jul", "aug", "sep", "oct", "nov", "dec",
+};
+
+char *findmonth(str)
+char *str;
+{
+       register char *cp, *sp;
+       register int i;
+       static char buf[4];
+       char *locv();
+
+       for(cp=str, sp=buf; (*sp++ = *cp++) && sp < &buf[3] && *cp != ' '; );
+       *sp = 0;
+       for(i = 0; i < 12; i++)
+               if(uleq(buf, monthtab[i])) {
+                       sprintf(buf, "%2d", i+1);
+                       return buf;
+               }
+       return(0);
+}
diff --git a/docs/historical/mh-nov-1983/cmds/send.c b/docs/historical/mh-nov-1983/cmds/send.c
new file mode 100644 (file)
index 0000000..6660f13
--- /dev/null
@@ -0,0 +1,325 @@
+#ifndef lint
+static char sccsid[] = "@(#)send.c     4.6 7/7/83";
+#endif
+
+#include "mh.h"
+#include <sys/wait.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <pwd.h>
+#include <sys/types.h>
+#include <sys/timeb.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <strings.h>
+
+#define        SENDMAIL        "/usr/lib/sendmail"
+#define FCCS           10                  /* Max number of fcc's allowed */
+
+struct swit switches[] = {
+       "debug",         -1,      /* 0 */
+       "draft",          0,      /* 1 */
+       "format",         0,      /* 2 */
+       "noformat",       0,      /* 3 */
+       "msgid",          0,      /* 4 */
+       "nomsgid",        0,      /* 5 */
+       "verbose",        0,      /* 6 */
+       "noverbose",      0,      /* 7 */
+       "help",           4,      /* 8 */
+       "wait",           0,      /* 9 */
+       "nowait",         0,      /* 10 */
+       0,                0
+};
+
+int     verbose, format, msgid, debug, myuid;
+int    waitfor = 1;
+char    *anoyes[];                     /* Std no/yes gans array */
+int     donecd;
+long    now;
+char    tmpfil[32], fccfold[FCCS][128];
+int     fccind;
+char   *rindex();
+
+main(argc, argv)
+char *argv[];
+{
+       register char *drft, *cp, *addrs;
+       register int i;
+       int pid;
+       struct stat stbuf;
+       char **ap, *msg;
+       char *arguments[50], **argp;
+       char buf[BUFSIZ], name[NAMESZ];
+       int state, compnum, fd;
+       FILE *in, *out;
+       char *getname();
+
+#ifdef NEWS
+       m_news();
+#endif
+       drft = 0;
+       cp = r1bindex(argv[0], '/');
+       if ((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               done(1);
+                                                       /* unknown */
+                       case -1:fprintf(stderr, "send: -%s unknown\n", cp);
+                               done(1);
+                       case 0: verbose++; debug++; continue; /* -debug */
+                       case 1: drft = m_maildir(draft);      /* -draft */
+                               continue;
+                       case 2: fprintf(stderr, "Send: -format not yet.\n");
+                               done(1);
+                       case 3: format = 0; continue;         /* -noformat */
+                       case 4: msgid = 1;  continue;         /* -msgid */
+                       case 5: msgid = 0;  continue;         /* -nomsgid */
+                       case 6: verbose = 1; continue;        /* -verbose */
+                       case 7: verbose = 0; continue;        /* -noverbose */
+                       case 8: help("send [file] [switches]", switches);
+                               done(1);
+                       case 9: waitfor = 1;  continue;         /* -wait */
+                       case 10:waitfor = 0;  continue;         /* -nowait */
+                       }
+               if(drft) {
+                       fprintf(stderr, "send: Only 1 message at a time!\n");
+                       done(1);
+               } else
+                       drft = cp;
+       }
+       if(!drft) {
+               drft = m_maildir(draft);
+               if(stat(drft, &stbuf) == -1) {
+                       fprintf(stderr,
+                               "Draft file: %s doesn't exist.\n", drft);
+                       done(1);
+               }
+               cp = concat("Use \"", drft, "\"? ", 0);
+               if(!gans(cp, anoyes))
+                       done(0);
+       } else {
+               if(stat(drft, &stbuf) == -1) {
+                       fprintf(stderr,
+                               "Draft file: %s doesn't exist.\n", drft);
+                       done(1);
+               }
+       }
+       m_update();
+
+       /* open files... */
+       if((in = fopen(drft, "r")) == NULL) {
+               fprintf(stderr, "Send: Can't open ");
+               perror(drft);
+               done(1);
+       }
+       copy(makename("locs", ".tmp"), copy("/tmp/", tmpfil));
+       if(!debug) {
+               if((out = fopen(tmpfil, "w")) == NULL) {
+                       fprintf(stderr, "Can't create %s\n", tmpfil);
+                       done(1);
+               }
+               chmod(tmpfil, 0744);
+       } else
+               out = stdout;
+
+       myuid = getuid();
+       putdate(0, out);           /* Tack on the date */
+       /* putfrom(out);*/         /* let sendmail do this */
+       putmsgid(out);             /* and message id if desired */
+
+       /*
+       ** Delivery phase
+       */
+       for(compnum = 1, state = FLD;;) {
+               state = m_getfld(state, name, buf, sizeof buf, in);
+               switch (state)
+               {
+               case FLD:
+               case FLDEOF:
+               case FLDPLUS:
+                       compnum++;
+                       cp = buf;
+                       while(*cp == ' ' || *cp == '\t')
+                               cp++;
+                       fprintf(out, "%s: %s", name, cp);
+                       if(uleq(name, "fcc")) {
+                               if(fccind >= FCCS) {
+                                       fprintf(stderr, "Send: too many fcc's.\n");
+                                       done(1);
+                               }
+                               copy(cp, fccfold[fccind]);
+                               if(cp = rindex(fccfold[fccind], '\n'))
+                                       *cp = 0;
+                               fccind++;
+                       }
+                       while(state == FLDPLUS || state == FLDEOF) {
+                               state = m_getfld(state, name, buf, sizeof buf, in);
+                               fputs(buf, out);
+                       }
+                       if(state == FLDEOF)
+                               goto process;
+                       break;
+
+               case BODY:
+               case BODYEOF:
+                       fprintf(out, "\n%s", buf);
+                       while(state == BODY) {
+                               state=m_getfld(state,name,buf,sizeof buf,in);
+                               fputs(buf, out);
+                       }
+
+               case FILEEOF:
+                       goto process;
+
+               case LENERR:
+               case FMTERR:
+                       fprintf(stderr, "??Message Format Error ");
+                       fprintf(stderr, "in Component #%d.\n", compnum);
+                       done(1);
+
+               default:
+                       fprintf(stderr, "Getfld returned %d\n", state);
+                       done(1);
+               }
+       }
+process:
+       if(!debug)
+               fclose(out);
+       else
+               printf("-----\n");
+       fclose(in);
+
+       signal(SIGINT, SIG_IGN);
+       signal(SIGQUIT, SIG_IGN);
+       if(!debug) {                    /* Send the mail */
+               fd = open(tmpfil, 0);
+               sendmail(fd);
+               close(fd);
+               if(fccind) {
+                       for(state = 0; state < fccind; state++)
+                               fcc(tmpfil, fccfold[state]);
+               }
+               unlink(tmpfil);
+       }
+       if (!debug)
+               backup(drft);
+       done(donecd);
+}
+
+sendmail(fd)
+{
+       int pid;
+       char *stashname[10];
+       char **stashp;
+
+       stashp = stashname;
+       *stashp++ = "sendmail";
+       *stashp++ = "-i";
+       *stashp++ = "-t";
+       if (verbose)
+               *stashp++ = "-v";
+       *stashp = 0;
+
+       while ((pid = fork()) == -1)
+               sleep(2);
+       if (pid == 0) {
+               close(0);
+               dup(fd);
+               close(fd);
+               execv(SENDMAIL, stashname);
+               perror(SENDMAIL);
+               _exit(1);
+       }
+       else if (waitfor)
+               (void) wait(0);
+}
+
+putfrom(out)
+       register FILE *out;
+{
+       register struct passwd *pw;
+
+       pw = getpwuid(myuid);
+       if (pw == NULL)
+       {
+               fprintf(stderr, "Send: WHO ARE YOU?\n");
+               done(1);
+       }
+       fprintf(out, "From: %s\n", pw->pw_name);
+}
+
+putmsgid(sp)
+       FILE *sp;
+{
+       char hostname[32];
+       auto int i = sizeof hostname;
+
+       if(!msgid)
+               return;
+       if(!now)
+               time(&now);
+       gethostname(hostname, &i);
+       fprintf(sp,
+               "Message-Id: <%u.%u.%ld@%s>\n", getpid(), myuid, now, hostname);
+}
+
+fcc(file, folder)
+       char *file, *folder;
+{
+       int child, pid;
+       union wait status;
+       char fold[128];
+
+       if(verbose) {
+               printf("Fcc: %s...", folder);
+               fflush(stdout);
+       }
+       while ((child = fork()) == -1)
+               sleep(5);
+       if(child == 0) {
+               if(*file != '+')
+                       strcpy(fold, "+");
+               strcat(fold, folder);
+               execl(fileproc, "file", "-link", "-file", file, fold, 0);
+               exit(-1);
+       } else
+               while((pid = wait(&status)) != -1 && pid != child);
+       if (status.w_status)
+               fprintf(stderr, "Send: Error on fcc to %s\n", folder);
+       else if(verbose)
+               putchar('\n');
+}
+
+backup(file)
+char *file;
+{
+       char buf[128];
+       register char *cp;
+
+       buf[0] = 0;
+       if(cp = rindex(file, '/'))
+               sprintf(buf, "%.*s", (++cp)-file, file);
+       else
+               cp = file;
+#ifdef UCB
+       strcat(buf, "#");
+#else
+       strcat(buf, ",");
+#endif
+       strcat(buf, cp);
+       unlink(buf);
+       if(link(file, buf) < 0 || unlink(file) < 0) {
+               fprintf(stderr, "Send: Backup rename failure ");
+               perror(buf);
+               done(1);
+       }
+}
diff --git a/docs/historical/mh-nov-1983/cmds/show.c b/docs/historical/mh-nov-1983/cmds/show.c
new file mode 100644 (file)
index 0000000..5c8bf96
--- /dev/null
@@ -0,0 +1,132 @@
+#include "mh.h"
+#include <stdio.h>
+#include <strings.h>
+
+int vecp;
+char *vec[MAXARGS];
+struct msgs *mp;
+struct swit switches[] = {
+       "all",         -3,      /* 0 */
+       "draft",        2,      /* 1 */
+       "pr",           2,      /* 2 */
+       "nopr",         2,      /* 3 */
+       "help",         4,      /* 4 */
+       0,              0
+};
+
+main(argc, argv)
+char *argv[];
+{
+       char *folder, *maildir, *msgs[100];
+       register int msgnum;
+       register char *cp, **ap;
+       int msgp, all, drft, pr;
+       char *arguments[50], **argp;
+       extern char _sobuf[];
+
+       setbuf(stdout, _sobuf);
+#ifdef NEWS
+       m_news();
+#endif
+       folder = (char *) 0;
+       pr = all = msgp = 0;
+       vecp = 1;
+       cp = r1bindex(argv[0], '/');
+       if((cp = m_find(cp)) != NULL) {
+               ap = brkstring(cp = getcpy(cp), " ", "\n");
+               ap = copyip(ap, arguments);
+       } else
+               ap = arguments;
+       copyip(argv+1, ap);
+       argp = arguments;
+       while(cp = *argp++) {
+               if(*cp == '-')
+                       switch(smatch(++cp, switches)) {
+                       case -2:ambigsw(cp, switches);       /* ambiguous */
+                               goto leave;
+                                                            /* unknown */
+                       case -1:vec[vecp++] = --cp;  continue;
+                                                            /* -all   */
+                       case 0: fprintf(stderr, "\"-all\" changed to \"all\"\n");
+                               goto leave;
+                       case 1: drft = 1;  continue;         /* -draft */
+                       case 2: pr = 1;  continue;           /* -pr    */
+                       case 3: pr = 0;  vecp = 1;  continue;/* -nopr  */
+                       case 4:                              /* -help  */
+  help("show [+folder]  [msgs] [switches] [switches for \"type\" or \"pr\" ]",
+                                    switches);
+                               goto leave;
+                       }
+               if(*cp == '+') {
+                       if(folder) {
+                               fprintf(stderr, "Only one folder at a time.\n");
+                               goto leave;
+                       } else
+                               folder = cp + 1;
+               } else
+                       msgs[msgp++] = cp;
+       }
+       if(drft)
+               maildir = m_maildir("");
+       else {
+               if(!msgp)
+                       msgs[msgp++] = "cur";
+               if(!folder)
+                       folder = m_getfolder();
+               maildir = m_maildir(folder);
+       }
+       if(chdir(maildir) < 0) {
+               fprintf(stderr, "Can't chdir to: ");
+               perror(maildir);
+               goto leave;
+       }
+       if(drft) {
+               vec[vecp++] = draft;
+               goto doit;
+       }
+       if(!(mp = m_gmsg(folder))) {
+               fprintf(stderr, "Can't read folder!?\n");
+               goto leave;
+       }
+       if(mp->hghmsg == 0) {
+               fprintf(stderr, "No messages in \"%s\".\n", folder);
+               goto leave;
+       }
+       if(msgp)
+               for(msgnum = 0; msgnum < msgp; msgnum++)
+                       if(!m_convert(msgs[msgnum]))
+                               goto leave;
+       if(mp->numsel == 0) {
+               fprintf(stderr, "show: potato pancakes.\n");     /* never get here */
+               goto leave;
+       }
+       if(mp->numsel > MAXARGS-2) {
+  fprintf(stderr, "show: more than %d messages for show-exec\n", MAXARGS-2);
+               goto leave;
+       }
+       for(msgnum= mp->lowsel; msgnum<= mp->hghsel; msgnum++)
+               if(mp->msgstats[msgnum]&SELECTED)
+                       vec[vecp++] = getcpy(m_name(msgnum));
+       m_replace(pfolder, folder);
+       if(mp->hghsel != mp->curmsg)
+               m_setcur(mp->hghsel);
+       if(vecp == 2 ) {
+               printf("(Message %s:%s)\n", folder, vec[1]);
+       }
+doit:   m_update();
+       fflush(stdout);
+       vec[vecp] = 0;
+       if(!pr) {
+               vec[0] = "c:mh-type";
+               execv(showproc, vec);
+       } else {
+               vec[0] = "mh-pr";
+               execv(prproc, vec);
+       }
+       perror(pr ? prproc : showproc);
+ leave:
+       m_update();
+       done(0);
+}
+
+
diff --git a/docs/historical/mh-nov-1983/cmds/strings.h b/docs/historical/mh-nov-1983/cmds/strings.h
new file mode 100644 (file)
index 0000000..70c67e5
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * This file gives extern declarations to all the strings
+ * that we might ever reference.
+ *
+ * I don't know if this what strings.h is supposed to be,
+ * but this is as good a first guess as I can handle.
+ */
+
+extern char *anoyes[];
+extern char    *components;
+extern char    *current;
+extern char    *defalt;
+extern char    *distcomps;
+extern char    *draft;
+extern char    *fileproc;
+extern char    *foldprot;
+extern char    *hostname;
+extern char    *installproc;
+extern char    *listname;
+extern char    *lockdir;
+extern int     lockwait;
+extern char    *lsproc;
+extern char    *mailboxes;
+extern char    *mailproc;
+extern char    *mh_deliver;
+extern char    *mh_prof;
+extern char    *mhnews;
+extern char    *msgprot;
+extern char    *pfolder;
+extern char    *prproc;
+extern char    *scanproc;
+extern char    *sendproc;
+extern char    *showproc;
+extern char    *stdcomps;
+extern char    *stddcomps;
+extern char    *sysed;
+
+#ifdef UNIXCOMP
+extern char    *unixtomh;
+extern char    *Mailprog;
+extern char    *localname;
+#endif
diff --git a/docs/historical/mh-nov-1983/cmds/unixtomh.c b/docs/historical/mh-nov-1983/cmds/unixtomh.c
new file mode 100644 (file)
index 0000000..2190c62
--- /dev/null
@@ -0,0 +1,603 @@
+#
+
+/*
+ * This program copies the mail file in standard unix format
+ * given as $1 to the file $2 in Rand Message Handler format.
+ * The change made is to bracket each message with a line
+ * containing 4 control-A's and to split the From line into
+ * a From: field and a Date: field, with the date in Arpanet
+ * standard format.
+ *
+ * This program is designed to be called from the rand mh program
+ * ``inc''
+ *
+ * Set SENDMAIL if you are running sendmail -- this guarantees that
+ * From: and Date: lines will appear already, and will put the info
+ * in the UNIX-From line into a Received-From: field.
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/timeb.h>
+#include <ctype.h>
+
+#define SENDMAIL
+
+struct headline {
+       char    *l_from;        /* The name of the sender */
+       char    *l_tty;         /* His tty string (if any) */
+       char    *l_date;        /* The entire date string */
+};
+
+char *savestr(), *copyin(), *copy(), *nextword(), *calloc();
+char *index();
+
+#define        NOSTR           ((char *) 0)
+#define        UUCP                    /* Undo strange uucp naming */
+
+main(argc, argv)
+       char **argv;
+{
+       char linebuf[BUFSIZ];
+       register int maybe;
+       register FILE *inf, *outf;
+       int inhdr, infld;
+
+       if (argc > 3) {
+               fprintf(stderr, "Usage: unixtomh name1 name2\n");
+               exit(1);
+       }
+       outf = inf = NULL;
+       if (argc < 3)
+               outf = stdout;
+       if (argc < 2)
+               inf = stdin;
+       if (inf == NULL && (inf = fopen(argv[1], "r")) == NULL) {
+               perror(argv[1]);
+               exit(1);
+       }
+       if (outf == NULL && (outf = fopen(argv[2], "w")) == NULL) {
+               perror(argv[2]);
+               exit(1);
+       }
+       maybe = 1;
+       inhdr = 0;
+       infld = 0;
+       while (nullgets(linebuf, BUFSIZ, inf) > 0) {
+               if (maybe && ishead(linebuf)) {
+                       fputs("\1\1\1\1\n", outf);
+                       inhdr++;
+                       dohead(linebuf, inf, outf);
+                       continue;
+               }
+               if (strlen(linebuf) == 0) {
+                       maybe = 1;
+                       inhdr = 0;
+                       infld = 0;
+                       putc('\n', outf);
+                       continue;
+               }
+               else
+                       maybe = 0;
+#ifndef SENDMAIL
+               if (inhdr && strcmpn(linebuf, "Date: ", 6) == 0)
+                       continue;
+               if (inhdr && strcmpn(linebuf, "From: ", 6) == 0)
+                       continue;
+#endif SENDMAIL
+               if (infld && isspace(linebuf[0])) {
+                       fputs(linebuf, outf);
+                       putc('\n', outf);
+                       continue;
+               }
+               if (inhdr && !isspace(linebuf[0])) {
+                       char *colp, *sp;
+
+                       colp = index(linebuf, ':');
+                       sp = index(linebuf, ' ');
+                       if (colp == NOSTR || sp == NOSTR || sp < colp) {
+                               putc('\n', outf);
+                               inhdr = 0;
+                       }
+                       else
+                               infld = 1;
+               }
+               fputs(linebuf, outf);
+               putc('\n', outf);
+       }
+       fputs("\1\1\1\1\n", outf);
+       fflush(outf);
+       if (ferror(outf)) {
+               fprintf(stderr, "unixtomh: write: ");
+               perror(argv[2]);
+               exit(1);
+       }
+       exit(0);
+}
+
+/*
+ * Get a line from the given file descriptor, don't return the
+ * terminating newline.
+ */
+
+nullgets(linebuf, sz, file)
+       char linebuf[];
+       register FILE *file;
+{
+       register char *cp;
+       register int c, cnt;
+
+       cp = linebuf;
+       cnt = sz;
+       do {
+               if (--cnt <= 0) {
+                       *cp = 0;
+                       return(1);
+               }
+               c = getc(file);
+               *cp++ = c;
+       } while (c != EOF && c != '\n');
+       if (c == EOF && cp == linebuf+1)
+               return(0);
+       *--cp = 0;
+       return(1);
+}
+
+/*
+ * Output the fields extracted from the From line --
+ * From: and Date:  Untangle UUCP stuff if appropriate.
+ */
+
+dohead(line, infile, outfile)
+       char line[];
+       register FILE *infile, *outfile;
+{
+       register char *cp;
+       struct headline hl;
+       char parbuf[BUFSIZ];
+#ifdef UUCP
+       char *word();
+       char namebuf[BUFSIZ];
+       char linebuf[BUFSIZ];
+       int first;
+       long curoff;
+#endif UUCP
+
+       parse(line, &hl, parbuf);
+#ifndef SENDMAIL
+       putdate(hl.l_date, outfile);
+#endif SENDMAIL
+#ifdef UUCP
+       if (strcmp(hl.l_from, "uucp") == 0) {
+               strcpy(namebuf, "");
+               first = 1;
+               for (;;) {
+                       curoff = ftell(infile);
+                       if (fgets(linebuf, BUFSIZ, infile) == NULL)
+                               break;
+                       if (strcmp(word(1, linebuf), ">From") != 0)
+                               break;
+                       if (strcmp(word(-3, linebuf), "remote") != 0)
+                               break;
+                       if (strcmp(word(-2, linebuf), "from") != 0)
+                               break;
+                       if (first) {
+                               strcpy(namebuf, word(-1, linebuf));
+                               strcat(namebuf, "!");
+                               strcat(namebuf, word(2, linebuf));
+                               first = 0;
+                       }
+                       else {
+                               strcpy(rindex(namebuf, '!')+1,
+                                   word(-1, linebuf));
+                               strcat(namebuf, "!");
+                               strcat(namebuf, word(2, linebuf));
+                       }
+               }
+               fseek(infile, curoff, 0);
+#ifdef SENDMAIL
+               if (!first)
+                       fprintf(outfile, "Return-Path: <%s>\n", namebuf);
+#else SENDMAIL
+               if (first)
+                       fprintf(outfile, "From: uucp\n");
+               else
+                       fprintf(outfile, "From: %s\n", namebuf);
+#endif SENDMAIL
+               return;
+       }
+#endif UUCP
+#ifdef SENDMAIL
+       if (hl.l_from[0] == '<')
+               fprintf(outfile, "Return-Path: %s\n", hl.l_from);
+       else
+               fprintf(outfile, "Return-Path: <%s>\n", hl.l_from);
+#else SENDMAIL
+       fprintf(outfile, "From: %s\n", hl.l_from);
+#endif SENDMAIL
+}
+
+#ifdef UUCP
+
+/*
+ * Return liberal word i from the given string.
+ * The words are numbered 1, 2, 3, . . .  from the left
+ * and -1, -2, . . . from the right.
+ */
+
+char *
+word(index, str)
+       char str[];
+{
+       register char *cp;
+       char *secbuf;
+       register int c;
+       static char retbuf[100];
+       char *gword();
+
+       cp = str;
+       if ((c = index) > 0) {
+               while (c-- > 0)
+                       cp = gword(cp, retbuf);
+               return(retbuf);
+       }
+       if (c == 0)
+               return("");
+       secbuf = (char *) alloca(strlen(str) + 1);
+       strcpy(secbuf, str);
+       rev(secbuf);
+       cp = word(-index, secbuf);
+       rev(cp);
+       return(cp);
+}
+
+/*
+ * Skip leading blanks in the string, return
+ * first liberal word collected.
+ */
+
+char *
+gword(cp, buf)
+       register char *cp;
+       char buf[];
+{
+       register char *cp2;
+
+       cp2 = buf;
+       while (*cp && any(*cp, " \t\n"))
+               cp++;
+       while (*cp && !any(*cp, " \t\n"))
+               *cp2++ = *cp++;
+       *cp2 = 0;
+       return(cp);
+}
+
+/*
+ * Reverse the characters in the string in place
+ */
+
+rev(str)
+       char str[];
+{
+       register char *cpl, *cpr;
+       register int s;
+
+       s = strlen(str);
+       cpl = str;
+       cpr = &str[s-1];
+       while (cpl < cpr) {
+               s = *cpl;
+               *cpl++ = *cpr;
+               *cpr-- = s;
+       }
+}
+#endif UUCP
+
+/*
+ * Save a string in dynamic space.
+ * This little goodie is needed for
+ * a headline detector in head.c
+ */
+
+char *
+savestr(str)
+       char str[];
+{
+       register char *top;
+
+       top = calloc(strlen(str) + 1, 1);
+       if (top == NOSTR) {
+               fprintf(stderr, "unixtomh:  Ran out of memory\n");
+               exit(1);
+       }
+       copy(str, top);
+       return(top);
+}
+
+/*
+ * See if the passed line buffer is a mail header.
+ * Return true if yes.  Note the extreme pains to
+ * accomodate all funny formats.
+ */
+
+ishead(linebuf)
+       char linebuf[];
+{
+       register char *cp;
+       struct headline hl;
+       char parbuf[BUFSIZ];
+
+       cp = linebuf;
+       if (!isname("From ", cp, 5))
+               return(0);
+       parse(cp, &hl, parbuf);
+       if (hl.l_from == NOSTR || hl.l_date == NOSTR) {
+               fail(linebuf, "No from or date field");
+               return(0);
+       }
+       if (!isdate(hl.l_date)) {
+               fail(linebuf, "Date field not legal date");
+               return(0);
+       }
+       
+       /*
+        * I guess we got it!
+        */
+
+       return(1);
+}
+
+fail(linebuf, reason)
+       char linebuf[], reason[];
+{
+       return;
+}
+
+/*
+ * Split a headline into its useful components.
+ * Copy the line into dynamic string space, then set
+ * pointers into the copied line in the passed headline
+ * structure.  Actually, it scans.
+ */
+
+parse(line, hl, pbuf)
+       char line[], pbuf[];
+       struct headline *hl;
+{
+       register char *cp, *dp;
+       char *sp;
+       char word[BUFSIZ];
+
+       hl->l_from = NOSTR;
+       hl->l_tty = NOSTR;
+       hl->l_date = NOSTR;
+       cp = line;
+       sp = pbuf;
+
+       /*
+        * Skip the first "word" of the line, which should be "From"
+        * anyway.
+        */
+
+       cp = nextword(cp, word);
+       dp = nextword(cp, word);
+       if (word[0] != 0)
+               hl->l_from = copyin(word, &sp);
+       if (isname(dp, "tty", 3)) {
+               cp = nextword(dp, word);
+               hl->l_tty = copyin(word, &sp);
+               if (cp != NOSTR)
+                       hl->l_date = copyin(cp, &sp);
+       }
+       else
+               if (dp != NOSTR)
+                       hl->l_date = copyin(dp, &sp);
+}
+
+/*
+ * Copy the string on the left into the string on the right
+ * and bump the right (reference) string pointer by the length.
+ * Thus, dynamically allocate space in the right string, copying
+ * the left string into it.
+ */
+
+char *
+copyin(src, space)
+       char src[];
+       char **space;
+{
+       register char *cp, *top;
+       register int s;
+
+       s = strlen(src);
+       cp = *space;
+       top = cp;
+       strcpy(cp, src);
+       cp += s + 1;
+       *space = cp;
+       return(top);
+}
+
+/*
+ * See if the two passed strings agree in the first n characters.
+ * Return true if they do, gnu.
+ */
+
+isname(as1, as2, acount)
+       char *as1, *as2;
+{
+       register char *s1, *s2;
+       register count;
+
+       s1 = as1;
+       s2 = as2;
+       count = acount;
+       if (count > 0)
+               do
+                       if (*s1++ != *s2++)
+                               return(0);
+               while (--count);
+       return(1);
+}
+
+/*
+ * Test to see if the passed string is a ctime(3) generated
+ * date string as documented in the manual.  The template
+ * below is used as the criterion of correctness.
+ * Also, we check for a possible trailing time zone using
+ * the auxtype template.
+ */
+
+#define        L       1               /* A lower case char */
+#define        S       2               /* A space */
+#define        D       3               /* A digit */
+#define        O       4               /* An optional digit or space */
+#define        C       5               /* A colon */
+#define        N       6               /* A new line */
+#define U      7               /* An upper case char */
+
+char ctypes[] = {U,L,L,S,U,L,L,S,O,D,S,D,D,C,D,D,C,D,D,S,D,D,D,D,0};
+char tmztypes[] = {U,L,L,S,U,L,L,S,O,D,S,D,D,C,D,D,C,D,D,S,U,U,U,S,D,D,D,D,0};
+
+isdate(date)
+       char date[];
+{
+       register char *cp;
+
+       cp = date;
+       if (cmatch(cp, ctypes))
+               return(1);
+       return(cmatch(cp, tmztypes));
+}
+
+/*
+ * Match the given string against the given template.
+ * Return 1 if they match, 0 if they don't
+ */
+
+cmatch(str, temp)
+       char str[], temp[];
+{
+       register char *cp, *tp;
+       register int c;
+
+       cp = str;
+       tp = temp;
+       while (*cp != '\0' && *tp != 0) {
+               c = *cp++;
+               switch (*tp++) {
+               case L:
+                       if (!islower(c))
+                               return(0);
+                       break;
+
+               case S:
+                       if (c != ' ')
+                               return(0);
+                       break;
+
+               case D:
+                       if (!isdigit(c))
+                               return(0);
+                       break;
+
+               case O:
+                       if (c != ' ' && !isdigit(c))
+                               return(0);
+                       break;
+
+               case C:
+                       if (c != ':')
+                               return(0);
+                       break;
+
+               case N:
+                       if (c != '\n')
+                               return(0);
+                       break;
+
+               case U:
+                       if (!isupper(c))
+                               return(0);
+                       break;
+               }
+       }
+       if (*cp != '\0' || *tp != 0)
+               return(0);
+       return(1);
+}
+
+/*
+ * Collect a liberal (space, tab delimited) word into the word buffer
+ * passed.  Also, return a pointer to the next word following that,
+ * or NOSTR if none follow.
+ */
+
+char *
+nextword(wp, wbuf)
+       char wp[], wbuf[];
+{
+       register char *cp, *cp2;
+
+       if ((cp = wp) == NOSTR) {
+               copy("", wbuf);
+               return(NOSTR);
+       }
+       cp2 = wbuf;
+       while (!any(*cp, " \t") && *cp != '\0')
+               *cp2++ = *cp++;
+       *cp2 = '\0';
+       while (any(*cp, " \t"))
+               cp++;
+       if (*cp == '\0')
+               return(NOSTR);
+       return(cp);
+}
+
+/*
+ * Copy str1 to str2, return pointer to null in str2.
+ */
+
+char *
+copy(str1, str2)
+       char *str1, *str2;
+{
+       register char *s1, *s2;
+
+       s1 = str1;
+       s2 = str2;
+       while (*s1)
+               *s2++ = *s1++;
+       *s2 = 0;
+       return(s2);
+}
+
+/*
+ * Is ch any of the characters in str?
+ */
+
+any(ch, str)
+       char *str;
+{
+       register char *f;
+       register c;
+
+       f = str;
+       c = ch;
+       while (*f)
+               if (c == *f++)
+                       return(1);
+       return(0);
+}
+
+/*
+ * Convert lower case letters to upper case.
+ */
+
+raise(c)
+       register int c;
+{
+       if (c >= 'a' && c <= 'z')
+               c += 'A' - 'a';
+       return(c);
+}
diff --git a/docs/historical/mh-nov-1983/cmds/vars.c b/docs/historical/mh-nov-1983/cmds/vars.c
new file mode 100644 (file)
index 0000000..cac97e0
--- /dev/null
@@ -0,0 +1,10 @@
+       register char *cp;
+       register int i,j;
+       register FILE *in;
+       char name[NAMESZ], field[BUFSIZ];
+       char *drft, *msgid, *replto, *from, *cc, *sub, *date, *to;
+       int state, out, status, intr;
+       int pid, wpid;
+       char **argp, *address;
+       char ackfile[10];
+       char buf[BUFSIZ];
diff --git a/docs/historical/mh-nov-1983/doc/Alias.Design b/docs/historical/mh-nov-1983/doc/Alias.Design
new file mode 100644 (file)
index 0000000..ed2490a
--- /dev/null
@@ -0,0 +1,67 @@
+The Alias file for mail delivery is the file
+
+       /etc/MailAliases
+
+Each line of the alias file has the format:
+
+match : alias
+
+Where:
+
+       alias       :=  simple-list
+                   |   "<" alias-file
+                   |   "=" UNIX-group
+                   |   "*"
+
+       simple-list :=  simple-name
+                   |   simple-list, simple-name
+
+Alias-file is a fully qualified UNIX file name.  UNIX-group is a
+group name from /etc/group.  A simple-name is a local user login
+name, including only alphanumerics, `.' and `-'.  Throughout this
+file case is ignored, except for alias-file.
+
+In match, a trailing * on a name will match anything. (See example
+below.)
+
+The procedure for mail aliasing is:
+
+1) Build a list of all addresses from the message to be
+   delivered, eliminating duplicates.
+
+2) For each line in the alias file, compare "match" against all
+   of the existing addresses.  If a match, remove the matched
+   name from the address list, and add each new alias name to the
+   address list if it is not already on the list.
+
+Since the alias file is read line by line, forward references
+work, but backward references are not recognized, thus, there is
+no recursion.
+
+E.g.:
+
+Borden: bruce
+Bruce: bsb
+Wharman: mike
+ASRL: bsb, mike, obrien, giarla
+UNIX-committee: < /usr/people/unix-committee
+System: = sys
+Everyone: *
+news.*: news
+   ...
+
+In the "unix-committee" example, the file "/usr/people/unix-
+committee" contains one simple-name, or a list of comma separated
+simple-names.  A new-line will be treated as a blank in this
+file, s.a.
+
+       foo, fie,
+       fum, fiddle
+
+In the "system" case, the names from the group "sys" will be used
+as the expanded name list.
+
+In the "news.*" case, all names of the form "news.<anything>" will
+be mapped to "news".  This is used for the MH news facility.
+
+Bruce Borden    October 1979
diff --git a/docs/historical/mh-nov-1983/doc/MH_VGRIND b/docs/historical/mh-nov-1983/doc/MH_VGRIND
new file mode 100644 (file)
index 0000000..346e7f6
--- /dev/null
@@ -0,0 +1,27 @@
+vgrind aliascheck.c annotate.c comp.c deliver.c dist.c emitl.c\
+       errno.h file.c folder.c forw.c grep.c inc.c install-mh.c\
+       mail.c mh.h news.c next.c nexthdr.c pick.c prevhdr.c\
+       prompter.c replsubs.c reply.c rescue.c rmf.c rmm.c scan.c\
+       scansub.c send.c show.c strings.h strings/Mailprog.c strings/anoyes.c\
+       strings/components.c strings/current.c strings/defalt.c\
+       strings/distcomps.c strings/draft.c strings/fileproc.c\
+       strings/foldprot.c strings/hostname.c strings/installproc.c\
+       strings/listname.c strings/localname.c strings/lockdir.c\
+       strings/lsproc.c strings/mailboxes.c strings/mailproc.c\
+       strings/mh_defs.c strings/mh_deliver.c strings/mh_prof.c\
+       strings/mhnews.c strings/msgprot.c strings/pfolder.c\
+       strings/prproc.c strings/scanproc.c strings/sendproc.c\
+       strings/showproc.c strings/stdcomps.c strings/stddcomps.c\
+       strings/strings.h strings/sysed.c strings/unixtomh.c\
+       subs/add.c subs/ambigsw.c subs/atooi.c subs/brkstring.c\
+       subs/cdate.c subs/cndfree.c subs/concat.c subs/copy.c subs/copyip.c\
+       subs/cputc.c subs/crpbrkstring.c subs/done.c subs/fdcompare.c\
+       subs/gans.c subs/getans.c subs/getcpy.c subs/help.c subs/invo_name.c\
+       subs/locv.c subs/m_convert.c subs/m_delete.c subs/m_edit.c\
+       subs/m_find.c subs/m_getdefs.c subs/m_getfld.c subs/m_getfolder.c\
+       subs/m_gmprot.c subs/m_gmsg.c subs/m_maildir.c subs/m_name.c\
+       subs/m_replace.c subs/m_send.c subs/m_setcur.c subs/m_update.c\
+       subs/makedir.c subs/makename.c subs/mh.h subs/peekc.c\
+       subs/pr_array.c subs/printsw.c subs/putdate.c subs/r1bindex.c\
+       subs/showfile.c subs/smatch.c subs/ssequal.c subs/trimcpy.c\
+       subs/type.c subs/uleq.c support/l.c unixtomh.c vars.c
diff --git a/docs/historical/mh-nov-1983/doc/MHgenerate b/docs/historical/mh-nov-1983/doc/MHgenerate
new file mode 100644 (file)
index 0000000..2ef9669
--- /dev/null
@@ -0,0 +1,122 @@
+                      HOW TO GENERATE AN MH
+
+ASSUMPTIONS/RESTRICTIONS:
+
+        All of the code is written for Version 7 C, and assumes
+the existence of appropriate Version 7 /usr/include files.  It
+also uses the Version 7 stdio package, which is somewhat
+different than the Phototypesetter stdio!
+
+        There is moderate usage of Version 7 UNIX features,
+including:
+
+               ftime() system call
+               execlp() & execvp() environment exec calls
+               getenv() environment access
+
+also, login has to be changed to add the environment entry
+"USER=name".  This is used during scan listings to see if the
+message "From" should be replaced by "To:name".  This string is
+NOT used to determine the "From: name" stamp on outgoing mail.
+
+        All of these usages ARE replaceable by subroutines which
+do the same thing, only slower.  That is, a line of the form:
+
+               homedir = getenv("HOME");
+
+should be replaced by something like:
+
+               homedir = gethome();
+
+and the routine gethome() written to return the home directory by
+looking through /etc/passwd for the line matching the process'
+getuid().  This goes for the environment variable "USER" as well.
+
+The routines execlp() & execvp() are simply fancy exec's, which
+use the "PATH" environment variable to determine the search path
+by which to find the executable image.  They can be replaced by
+routines which use a default search list.  They also call a shell
+to execute the file in the same way the shell handles shell
+scripts.
+
+
+
+PROCEDURE:
+
+
+1) Read the MH directory tree onto a file system.
+
+2) Examine all of the files in directory strings.  These are the
+   names and paths of all of the programs MH calls upon.  Change
+   them to suit your installation.  Most of the files contain
+   short descriptions of what the strings are.
+
+3) In the top level directory, utter:
+
+       make strings.a subs.a all
+
+   This will make both of the libraries: strings.a and subs.a,
+   and ALL of the executable modules.
+
+4) AS SU:
+
+       make onceonly           This renames conflicting bell
+                               programs, and makes requisite
+                               directories.
+
+       make install            This puts all of the programs
+                               into appropriate directories.
+
+That's it.  Take a close look at the Makefile--it does LOTS of
+work.  If you don't want to install everything in standard
+places, run "make install" with the variables MHDIR=newdir and
+BINDIR=newdir pointing wherever you wish.  If you do this, you
+probably have to change some of the path names in the strings
+files.  For most of them, you can get away with adding profile
+entries to change where the default paths are sought.
+
+If you don't have `make':
+
+     You'll have to use the make file as a template for commands
+     to give by hand.  Basically each section of the make file
+     defines the sequence of shell commands needed to create the
+     object before the `:'.  The list immediately after the `:'
+     specifies the dependencies for the object--that is, those
+     objects which either must be made first, or those modules
+     that if they've changed, the object must be rebuilt.  The
+     following lines (up to the next object) are simply shell
+     commands to be executed.  Make knows how to create .o's from
+     .c's, and the "CFLAGS= -O" at the beginning tells it to
+     include optimization when it does a c compile.
+
+If you don't have stdio (i.e. some version 7 C compiler):
+
+     Punt.  I recently converted the whole package from the old
+     getc/putc/iobuf subroutines--including lots of upgrades/
+     improvements, it took me about a week.  Expect it to take a
+     couple of weeks for someone good to convert back.
+     Basically, convert the subroutines, then once you've
+     converted one module (start with show or comp), you'll find
+     all the rest VERY similar.  Some day I may split out all of
+     the system dependencies, but don't hold your breath.
+
+
+
+As a last resort:
+
+     Feel free to call me, but please don't expect me to spend
+hours helping.  Collect your questions/problems, and get in touch
+and I'll see what I can do.  I can be reached:
+
+       via ARPANET:    Borden at Rand-UNIX
+
+       Mail:           The Rand Corporation
+                       1700 Main Street
+                       Santa Monica, CA 90406
+
+       Phone:          (213) 399-0568 x 7463
+
+
+
+Bruce Borden
+October, 1979
diff --git a/docs/historical/mh-nov-1983/doc/MHnotes b/docs/historical/mh-nov-1983/doc/MHnotes
new file mode 100644 (file)
index 0000000..93167eb
--- /dev/null
@@ -0,0 +1,178 @@
+This file contains some notes on features/bugs/etc which are
+not documented in the "MH User's Manual", as well as some notes
+on future directions.  See MHgenerate for more info.  Some of
+these notes assume VAX/V7 UNIX--as noted by {V/V7}.
+
+0) Directories:
+       support contains files which get copied to /etc/mh, as
+               well as some miscellaneous Rand support programs
+       subs    contains support subroutines--built into subs.a
+       strings contains c files which define all of the default
+               names and paths used by the package->strings.a
+       Extras  old and un-supported code--much of it not
+                converted to V7.  Look at libg/libh for help in
+                getting around V7 features.
+       DOC     contains the MH User's Manual document in nroff/
+                troff form.  This requires the Phototypesetter or
+                V7 version of nroff/troff, AND the Berkeley -me
+                macros.
+
+1) Undocumented Feature:  The paths to the various programs which
+   MH exec's are kept in variables named something like "lsproc".
+   (See the strings directory.) While reading in the user's
+   profile, (m_getdefs()) a component matching one of these exec
+   path names, will cause the default string to be replaced by
+   the profile entry argument.  Thus, the profile entry "lsproc:
+   /usr/foo/bin/newls" will cause all MH programs using "lsproc"
+   to get a new ls.  At least for now, there is no way to specify
+   switches.  This mapping is arranged by the "procs" structure
+   in m_getdefs.c--keep it up to date if new exec procs are
+   added.
+
+2) Collision:  Take a close look at the "onceonly" entry of the
+   Makefile.  Bell already has a program named `file', which the
+   makefile will rename to `filetype', which is what it tries to
+   indicate.  If you really want to, you might rename the MH
+   command `file', but I have yet to hear of an even vaguely
+   reasonable alternative.
+
+3) Different Approach:  Using the Berkeley C shell (csh),
+   "multiple links to the same file with different profile
+   entries" is better served with aliases.
+
+4) Collision: {V/V7} BELL mail cannot co-exist with MH--IF THEY
+   SHARE THE SAME MAILBOXES, otherwise they co-exist fine!  If
+   you use the standard (VAX) mail directory /usr/spool/mail for
+   MH, you should also install the MH version of the mail
+   program.  It is much nicer, and integrates with MH cleanly.
+   The advantage of using /usr/spool/mail is that login will
+   notify of new mail.
+
+5) Feature: If you add a line like:
+
+       30 1 * * * /etc/mh/aliascheck -mail bsb
+
+   to crontab, then every morning at 1:30 AM, the alias file will
+   be checked against the /etc/passwd file to see that
+   inconsistencies haven't been introduced.  In particular, a
+   line in the alias file may be "tom: jones" (because Tom Jones
+   likes to be called Tom), but if tom is also a valid user name,
+   tom will no longer receive any mail!  This program also prints
+   any mail drops in /usr/spool/mail which don't belong to a
+   valid user (i.e. a deleted or renamed user id).
+
+   "Aliascheck -mail name" will check the consistency and mail
+   the specified user a short status message.
+
+   This program also checks to see if there are any users who do
+   not belong to any group, or any user in a group which is missing
+   from the passwd file.  This latter is an inconsistency on all
+   systems, whereas the former is not required except at Rand, and
+   won't be compiled without the "-DRAND" cc flag in the makefile.
+
+6) Hidden Feature:  At the request of some of the Rand staff,
+   there is the ability to invoke a user-specified deletion-
+   program to implement message deletion, rather than getting the
+   default comma renaming convention (see next item).  If a
+   user's profile contains the line: "Delete-prog: path", the
+   specified path will be called with a list of files needing
+   deletion.  All this code works...
+
+7) Feature:  When a message (draft or in a folder) is "removed",
+   it is really renamed with a leading comma.  E.g. foo -> ,foo.
+   At Rand we have a program called the midnight skulker which
+   goes through the whole system and removes all backup (starting
+   with comma), a.out, and core files.  This backup convention
+   gives users a chance to undo spurious removes, at least all
+   day.  You may want to replace these renames with a simple
+   unlink(), or each user may get this effect by specifying
+   "Delete-prog: /bin/rm" in his/her profile.
+
+8) Feature:  NEWS.  The news facility is undocumented in the MH
+   manual, because it is a very new addition to the package.  SO,
+   here it is...
+
+        The directory /usr/news should be created--it will
+        contain the folders for news topics, and various support
+        files.  The news items are strictly MH folders, and users
+        can utilize all of the MH commands on them.  The news
+        program is similar to "show", but it shows `unseen' news
+        as the default, keeping a separate entry in the users
+        profile for each news topic indicating the highest item
+       the user has seen.  These entries look like
+               "news-<topic>: highest-seen".
+
+        Rather than read through the news folders to determine
+        the number of entries, a file with name .<topic> (i.e.
+        period followed by the topic name) is kept with length
+        equal to highest message number.  Thus, to determine if a
+        user hasn't seen some news, the news directory
+        (/usr/news) is read, and for each non-period beginning
+        file (i.e. each folder), stat the associated period
+        beginning file, and compare its length with the users
+        profile news entry for the same name.  If the user has no
+        entry, or it is less than the length of the period-file,
+        then show him the remainder of the news in each such
+        topic.
+
+        The program `l' is used to display each message, and the
+        highest item profile entry is updated prior to each
+        individual message displayed, so <del> will leave the
+        user's profile in the proper state for the next news
+        request.
+
+        Add a user to the system called news, with home directory
+        /usr/news and add the line:
+
+               news.*: news
+
+        to /etc/MailAlias.  Thus, to add news to a topic, it is
+        only necessary to mail to news.topic, and it will happen.
+        To make the automatic filing into folders happen, copy
+        the file support/news-mh_receiv to /usr/news/.mh_receive.
+        This is a shell script which will get invoked whenever
+        mail is sent to the user news (see next "undocumented
+        feature").
+
+        Problems:  I have yet to write the program which packs
+        news folders.  Items can be readily removed (as long as
+        they are not the last item in the folder), but if the
+        folder is packed (after some months/years the item
+        numbers will reach the 999 limit), it is necessary to go
+        through everyones .mh_profile files and reset the
+        highest-seen numbers.  Not hard to write, I just haven't
+        done it yet.  Also, the receive shell script should be
+        recoded in C to speed it up considerably.
+
+9) Undocumented Feature:  If a user has an executable program or
+   shell script named ".mh_receive" in his home directory, then
+   it will be executed by the mail deliverer RATHER than
+   appending mail items to the user's mail file
+   (/usr/spool/mail/name).  This program will be called with:
+
+       execlp(prog, prog, tmpfil, mail, home, 0);
+
+   where prog is the receive program, tmpfil is a file in
+   /usr/tmp which is the mail to be received, mail is the path of
+   the user's mail drop (/usr/spool/mail/name), and home is the
+   $HOME directory of the user.  File descriptor 3 will have
+   tmpfil opened on it read only.  These are all the RECEIVER'S
+   parameters, not the sender's.  Also, the environment is set up
+   with appropriate values for HOME and USER.
+
+   Eventually, the goal is to have received mail LINKED into
+   user's inbox folders, rather than appended to their mailboxes.
+   This will facilitate the sending of mail to large distribution
+   lists (Rand is always tight on space!) Have a look at the news
+   .mh_receive file for an example of this facility.
+
+   Warning: appropriate interlocks are implemented in "deliver"
+   to prevent collisions when it appends to mailboxes, but it is
+   up to the users's .mh_receive program to provide its own
+   interlocks!
+
+
+
+
+Bruce Borden
+February 1980
diff --git a/docs/historical/mh-nov-1983/doc/Makefile b/docs/historical/mh-nov-1983/doc/Makefile
new file mode 100644 (file)
index 0000000..49f2d78
--- /dev/null
@@ -0,0 +1,2 @@
+manual:
+       itroff -me titlepage mh.me
diff --git a/docs/historical/mh-nov-1983/doc/mh.me b/docs/historical/mh-nov-1983/doc/mh.me
new file mode 100644 (file)
index 0000000..630fa1a
--- /dev/null
@@ -0,0 +1,2510 @@
+.de $c                          \" Major Heading printer
+.ce
+.b "\\s12\\n+(ch.\\ \\$1\\s0"   \" 12 Point Bold Header
+.(x
+
+\ \ \ \\n(ch.\\ \\ \\$1
+.)x
+.sp 45p         \" 45 point space or about 1/2 inch
+..
+\".nr xs .15v     \" Put index entries closer together
+.(x
+
+Section
+.)x _
+.de $0          \" Sub-Heading macro called AFTER printing the heading
+.(x
+.sp .3v
+.ti .5i
+\\$1
+.)x
+..
+.de $s          \" Macro to print footnote separator
+\"\l'2i'        \" No line drawn
+.if n \
+.       sp 1.3  \" But extra space to make up for it.
+..
+.fc ^ ~         \" The characters ^ and ~ CANNOT BE USED
+\"                 throughout this document except as field
+\"                 delimiter & pad indicator!
+.he ''-%-''
+.ll 32P         \" 32 Picas or about 5+1/3 inch Line Length
+.if n .ll 72m   \" Use 72 ems for nroff
+.nr ss 30p      \" 30 point space before section titles
+.nr fm 5v       \" Rand likes bigger than normal [3v] bottom margins
+.nr bm 7v       \"   ditto
+.ds . \\fB.\\fP\\h'-(1m/3)' \" Bold period to stand out.
+.ds << <\\h!-(\\w'<'/2)!<
+.ds >> >\\h!-(\\w'>'/2)!>
+.ds ** \v'-3p'\s+1*\s0\v'+3p'
+.++ C
+.+c INTRODUCTION
+.pp
+Although people can travel cross-country in hours and can
+reach others by telephone in seconds, communications still depend
+heavily upon paper, most of which is distributed through the mails.
+.pp
+There are several major reasons for this continued dependence on
+written documents.
+First, a written document may be proofread
+and corrected prior to its distribution, giving the author
+complete control over his words.
+Thus, a written document is
+better than a telephone conversation in this respect.
+Second,
+a carefully written document is far less likely to be
+misinterpreted or poorly translated than a phone conversation.
+Third, a signature offers reasonable verification of authorship,
+which cannot be provided with media such as telegrams.
+.pp
+However, the need for
+.u fast ,
+accurate, and reproducible document distribution is
+obvious.
+One solution in widespread use is the telefax.
+Another
+that is rapidly gaining popularity is electronic mail.
+Electronic mail is similar to telefax in that the data to be sent
+are digitized, transmitted via phone lines, and
+turned back into a document at the receiver.
+The advantage of
+electronic mail is in its compression factor.
+Whereas a telefax
+must scan a page in very fine lines and send all of the black and
+white information, electronic mail assigns characters fixed
+codes which can be transmitted as a few bits of information.
+Telefax presently has the advantage of being able to transmit an
+arbitrary page, including pictures, but electronic mail is
+beginning to deal with this problem.
+Electronic mail also integrates well
+with current directions in office automation, allowing documents
+prepared with sophisticated equipment at one site to be quickly
+transferred and printed at another site.
+.pp
+Currently, most electronic mail is intraorganizational,
+with mail transfer remaining within one computer.
+As computer
+networking becomes more common, however, it is becoming more feasible to
+communicate with anyone whose computer can be linked to your
+own via a network.
+.pp
+The pioneering efforts on general-purpose electronic mail
+were by organizations using the Defense Department's ARPANET.[1]
+The capability to send messages between computers existed before
+the ARPANET was developed, but it was used only in limited ways.
+With the advent of the
+ARPANET, tools began to be developed which made it convenient for
+individuals or organizations to distribute messages
+over broad geographic areas, using
+diverse computer facilities.
+The interest and activity in
+message systems has now reached such proportions that steps
+have been taken within the DoD to coordinate and
+unify the development of military message systems.
+The use of electronic mail is expected to increase
+dramatically in the next few years.
+The utility of such systems
+in the command and control and intelligence environments is
+clear, and applications in these areas will probably lead the
+way.
+As the costs for sending and handling electronic messags
+continue their rapid decrease, such uses can be
+expected to spread rapidly into other areas and, of course, will
+not be limited to the DoD.
+.pp
+A message system provides tools that help users (individuals
+or organizations) deal with messages in various ways.
+Messages
+must be composed, sent, received, stored, retrieved,
+forwarded, and replied to.
+Today's best interactive computer
+systems provide a variety of word-processing and information
+handling capabilities.
+The message handling facilities should be
+well integrated with the rest of the system, so as to be a
+graceful extension of overall system capability.
+.pp
+The message system described in this report, MH, provides most of the
+features that can be found in other message systems and also
+incorporates some new ones.
+It has been built on the UNIX time-sharing
+system,[2] a popular operating system for the DEC PDP-11
+and VAX classes of computers.
+A \*(lqsecure\*(rq operating
+system similar to UNIX is currently being developed,[3]
+and that system will also run MH.
+.pp
+This report provides a complete description of MH and
+thus may serve as a user's manual, although parts of the report
+will be of interest to non-users as well.
+Sections 2 and 3, the
+Overview and Tutorial, present the key
+ideas of MH and will give those not familiar with message systems
+an idea of what such systems are like.
+.pp
+MH consists of a set of commands which use some special
+files and conventions.
+Section 4 covers the information
+a user needs to know in addition to the
+commands.
+The final section, Sec. 5, describes each of
+the MH commands in detail.
+A summary of the commands is given in
+Appendix A, and Appendixes B and C describe the ARPANET
+conventions for messages (we expect that many users of MH
+will be using the ARPANET) and the formal syntax of such
+messages, respectively.
+Finally, Appendix D provides
+an illustration of how MH commands may be used in
+conjunction with other UNIX facilities.
+.pp
+A novel approach has been taken in the design of MH.
+The
+design concept will be reported in detail in a forthcoming Rand
+report, but it can be described briefly as follows.
+Instead of creating a large subsystem that appears as a single
+command to the user, (such as MS[4])
+MH is a collection of separate commands
+which are run as separate programs.
+The file and directory
+system of UNIX are used directly.
+Messages are stored as
+individual files (datasets), and collections of them are grouped
+into directories.
+In contrast, most other message systems store
+messages in a complicated data structure within a monolithic
+file.
+With the MH approach, UNIX commands can be
+interleaved with commands invoking the functions of the message
+handler.
+Conversely, existing UNIX commands
+can be used in connection with messages.
+For
+example, all the usual UNIX editing, text-formatting, and printing
+facilities can be applied directly to individual messages.
+MH,
+therefore, consists of a relatively small amount of new code; it
+makes extensive use of other UNIX software to provide the
+capabilities found in other message systems.
+.+c OVERVIEW
+.pp
+There are three main aspects of MH:  the  way  messages  are
+stored (the message database), the user's profile (which directs
+how certain actions of the message handler take place), and the
+commands for dealing with messages.
+.pp
+Under MH, each message is stored as a separate file.
+A user
+can take any action with a message that he could with an ordinary
+file in UNIX.
+A UNIX directory in which messages are stored is
+called a folder.
+Each folder contains some standard entries to support
+the message-handling functions.
+The messages in a folder have numerical
+names.
+These folders (directories)
+are entries in a particular directory path, described in
+the user profile, through which MH can find message folders.
+Using the UNIX \*(lqlink\*(rq facility, it is possible for one copy of a
+message to be \*(lqfiled\*(rq in more than one folder, providing a
+message index facility.
+Also, using the UNIX tree-structured
+file system, it is possible to have a folder within a folder.
+This two-level organization provides a \*(lqselection-list\*(rq
+facility, with the full power of the MH commands available on
+selected sublists of messages.
+.pp
+Each user of MH has a user profile, a file in his $HOME (initial
+login)
+directory called \*(lq\*.mh\(ruprofile\*(rq.
+This profile contains several
+pieces of information used by the MH commands:  a
+path name to the directory that contains the message folders,
+information concerning which folder the user last referenced (the
+\*(lqcurrent\*(rq folder), and parameters that tailor MH commands
+to the individual user's requirements.
+It also contains
+most of the necessary state information concerning how
+the user is dealing with his messages, enabling MH to be
+implemented as a set of individual UNIX commands, in contrast to the
+usual approach of a monolithic subsystem.
+.pp
+In MH, incoming mail is appended
+to the end of a file called \*.mail in a user's $HOME
+directory.
+The user adds the new messages to his collection of MH messages
+by invoking the command
+.i inc .
+.i Inc
+(incorporate) adds the new
+messages to a folder called \*(lqinbox\*(rq, assigning them names which
+are consecutive integers starting with the next highest integer
+available in inbox.
+.i Inc
+also produces a
+.i scan
+summary of
+the messages thus incorporated.
+.pp
+There are four commands for examining the messages in a
+folder:
+.i show ,
+.i prev ,
+.i next ,
+and
+.i scan .
+.i Show
+displays a
+message in a folder,
+.i prev
+displays the message preceding the
+current message, and
+.i next
+displays the message following the
+current message.
+.i Scan
+summarizes the messages in a folder,
+producing one line per message, showing who the message is from,
+the date, the subject, etc.
+.pp
+The user may move a message from one folder to another with
+the command
+.i file .
+Messages may be removed from a folder
+by means of the command
+.i rmm .
+In addition, a user may query
+what the current folder is and may specify that a new folder
+become the current folder, through the command
+.i folder .
+.pp
+A set of messages based on content may be selected by
+use of the command
+.i pick .
+This command searches through
+messages in a folder and selects those that match a given
+criterion.
+A subfolder is created within the original folder,
+containing links to all the messages that satisfy the selection
+criteria.
+.pp
+A message folder (or subfolder) may be removed by means of
+the command
+.i rmf .
+.pp
+There are five commands enabling the user to create new
+messages and send them:
+.i comp ,
+.i dist ,
+.i forw ,
+.i repl ,
+and
+.i send .
+.i Comp
+provides the facility for the user to compose a
+new message;
+.i dist
+redistributes mail to additional addressees;
+.i forw
+enables the user to forward messages; and
+.i repl
+facilitates the generation of a reply to an incoming message.
+If
+a message is not sent directly by one of these commands, it may
+be sent at a later time using the command
+.i send .
+.pp
+All of the elements summarized above
+are described in more detail in the following sections.
+Many of the
+normal facilities of UNIX provide additional capabilities for
+dealing with messages in various ways.
+For example, it is
+possible to print messages
+on the line-printer without requiring any additional code within
+MH.
+Using standard UNIX facilities, any terminal output can be
+redirected to a file for repeated or future viewing.
+In general,
+the flexibility and capabilities of the UNIX interface with the
+user are preserved as a result of the integration of MH into the UNIX
+structure.
+.+c TUTORIAL
+.pp
+This tutorial provides a brief introduction to the MH commands.
+It should be sufficient
+to allow the user to read his mail, do some simple manipulations of
+it, and create and send messages.
+.pp
+A message has two major pieces:  the
+header and the body.
+The body consists of the text of the message
+(whatever you care to type in).
+It follows the header and is separated from
+it by an empty line.
+(When you compose a message, the form that appears
+on your terminal shows a line of dashes after the header.
+This is for
+convenience and is replaced by an empty line when the message is
+sent.)  The header is composed of several components, including the
+subject of the message and the person to whom it is addressed.
+Each component starts with a name
+and a colon; components must not start with a blank.
+The text of the
+component may take more than one line, but each continuation line must
+start with a blank.
+Messages typically have \*(lqto:\*(rq, \*(lqcc:\*(rq, and
+\*(lqsubject:\*(rq components.
+When composing a message, you should include
+the \*(lqto:\*(rq and \*(lqsubject:\*(rq components; the \*(lqcc:\*(rq (for people
+you want to send copies to) is not necessary.
+.pp
+The basic MH commands are
+.i inc ,
+.i scan ,
+.i show ,
+.i next ,
+.i prev ,
+.i rmm ,
+.i comp ,
+and
+.i repl .
+These are described below.
+
+.i inc
+.pp
+When you get the message \*(lqYou have mail\*(rq, type the command
+.i inc .
+You will get a \*(lqscan listing\*(rq such as:
+
+.nf
+.if t .ta .4i 1.0i 2i
+.if n .ta .4i 1.2i 3i
+^7+~^^\07/13~^^Cas~^revival of measurement work
+^8~^^10/\09~^^Norm~^NBS people and publications
+^9~^^11/26~^^To:norm~^question \*(<<Are there any functions
+.re
+.fi
+.pp
+This shows the messages you received since the last time you
+executed this command (
+.i inc
+adds these new messages to
+your inbox folder).
+You can see this list again, plus a list of any
+other messages you have, by using the
+.i scan
+command.
+
+.i scan
+.pp
+The scan listing shows the message number, followed by the
+date and the sender.
+(If you are the sender, the addressee in the \*(lqto:\*(rq
+component is displayed.
+You may send yourself a message by including
+your name among the \*(lqto:\*(rq or \*(lqcc:\*(rq addressees.)
+It also shows the message's subject; if
+the subject is short, the first part of the body of the message is
+included after the characters \*(<<.
+
+.ne 5
+.i show
+.pp
+This command shows the current message, that is,
+the first one of the new messages after an
+.i inc .
+If the message is not
+specified by name (number), it is
+generally the last message referred to by an MH command.
+For example,
+
+.ta 1i
+.ti .5i
+^\fIshow\fP\05~^will show message 5.
+.pp
+You can use the show command to copy a message or print a
+message.
+
+.(b L
+.in .5i
+.if t .ta 1i
+.if n .ta 1.5i
+^\fIshow\fR\0>\0\fIx\fR~^will copy the message to file x.
+.br
+^\fIshow\fR\0|\0\fIprint\fR~^will print the message, using the \fIprint\fR command.
+.br
+^\fInext\fR~^will show the message that follows the current message.
+.br
+^\fIprev\fR~^will show the message previous to the current message.
+.br
+^\fIrmm\fR~^will remove the current message.
+.br
+^\fIrmm\03\fR~^will remove message 3.
+.)b
+
+.ne 5
+.i comp
+.pp
+The
+.i comp
+command puts you in the editor to write or edit a message.
+Fill in or
+delete the \*(lqto:\*(rq, \*(lqcc:\*(rq, and \*(lqsubject:\*(rq fields, as appropriate, and
+type the body of the message.
+Then
+exit normally from the editor.
+You will be asked
+\*(lqWhat now?\*(rq.
+Type a carriage return to see the options.
+Typing \fBsend\fR
+will cause the message to be sent; typing \fBquit\fR will cause an exit
+from
+.i comp ,
+with the message draft saved.
+.pp
+If you quit without sending the message, it will be saved in a file
+called /usr/<name>/Mail/draft (where /usr/<name> is your $HOME directory).
+You can edit this file and send the message later, using the
+.i send
+command.
+
+.ne 4
+.i "comp\0\-editor\0prompter"
+.pp
+This command uses a different editor and is useful for preparing
+\*(lqquick and dirty\*(rq messages.
+It prompts you for each component of the
+header.
+Type the information for that component, or type a carriage
+return to omit the component.
+After that, type the body of the
+message.
+Backspacing is the only form of editing allowed with this editor.
+When the body is complete, type a carriage return followed by <CTRL-D>
+(<OPEN> on Ann Arbor terminals).
+This completes the initial preparation of the message; from then on, use
+the same procedures as with
+.i comp
+(above).
+
+.ne 5
+.i repl
+.br
+.i "repl\0n"
+.pp
+This command makes up an initial message form with a header
+that is appropriate for
+replying to an existing message.
+The message being answered is the
+current message if no message number is mentioned, or n if a number
+is specified.
+After the header is completed, you can finish the message as in
+.i comp
+(above).
+.pp
+This is enough information to get you going using MH.
+There are more commands,
+and the commands described here have more features.
+Subsequent sections
+explain MH in complete detail.
+The system is quite powerful if you
+want to use its sophisticated features, but the foregoing commands
+suffice for sending and receiving messages.
+.pp
+There are numerous additional capabilities you may wish to explore.
+For example, the
+.i pick
+command will select a subset of messages
+based on specified criteria such as sender or subject.
+Groups of
+messages may be designated, as described in Sec. V, under \*(lqMessage
+Naming\*(rq.
+The file \*(lq\*.mh\(ruprofile\*(rq can be used to tailor your use of
+the message system to your needs and preferences, as described in Sec. V,
+under \*(lqThe User Profile\*(rq.
+In general, you may
+learn additional features of the system selectively, according to your
+requirements,
+by studying the relevant sections of this manual.
+There is no need to
+learn all the details of the system at once.
+.+c "DETAILED DESCRIPTION"
+.pp
+This section describes the MH system in detail, including the components
+of the user profile, the conventions for message naming, and some of
+the other MH conventions.
+Readers who are
+generally familiar with computer systems will be able to follow
+the principal ideas, although some details may be meaningful only to
+those familiar with UNIX.
+.uh "THE USER PROFILE"
+.pp
+The first time an MH command is issued by a new user, the system
+prompts for a \*(lqpath\*(rq and creates an MH \*(lqprofile\*(rq.
+.pp
+Each MH user has a profile which contains current
+state information for the MH package and, optionally, tailoring
+information for each individual program.
+When a folder becomes
+the current folder, it is recorded in the user's profile.
+Other profile entries control the MH path (where folders and
+special files are kept), folder and message protections, editor
+selection, and default arguments for each MH program.
+.pp
+The MH profile is stored in the file \*(lq\*.mh\(ruprofile\*(rq in the
+user's $HOME directory.
+It has the format of a message without
+any body.
+That is, each profile entry is on one line, with a
+keyword followed by a colon (:) followed by text particular to
+the keyword.
+.br
+\(rh\ \ \&
+.i "This file must not have blank lines."
+.br
+The keywords
+may have any combination of upper and lower case.
+(See Appendix
+B for a description of message formats.)
+.pp
+For the average MH user, the only profile entry of
+importance is \*(lqPath\*(rq.
+Path specifies a directory in which MH
+folders and certain files such as \*(lqdraft\*(rq are found.
+The
+argument to this keyword must be a legal UNIX path that names an
+existing directory.
+If this path is unrooted (i.e., does not
+begin with a \fB/\fR), it will be presumed to start from the
+user's $HOME directory.
+All folder and message references within
+MH will relate to this path unless full path names are used.
+.pp
+Message protection defaults to 664, and folder protection to
+751.
+These may be changed by profile entries \*(lqMsg-Protect\*(rq
+and \*(lqFolder-Protect\*(rq, respectively.
+The argument to these
+keywords is an octal number which is used as the UNIX file mode.\**
+.(f
+\**See
+.i chmod (I)
+in the
+.i "UNIX Programmer's Manual" .[5]
+.)f
+.pp
+When an MH program starts running, it looks through the
+user's profile for an entry with a keyword matching the program's
+name.
+For example, when
+.i comp
+is run, it looks for a \*(lqcomp\*(rq
+profile entry.
+If one is found, the text of the profile entry is
+used as the default switch setting until all defaults are overridden
+by explicit switches passed to the program as arguments.
+Thus the profile
+entry \*(lqcomp:\0\-form\0standard.list\*(rq would direct
+.i comp
+to use the
+file \*(lqstandard.list\*(rq as the message skeleton.
+If an explicit
+form switch is given to the
+.i comp
+command, it will override the
+switch obtained from the profile.
+.pp
+In UNIX, a program may exist under several names, either by
+linking or aliasing.
+The actual invocation name is used by an MH
+program when scanning for its profile defaults.
+Thus, each MH program
+may have several names by which it can be invoked, and each name
+may have a different set of default switches.
+For example, if
+.i comp
+is invoked by the name
+.i icomp ,
+the profile entry
+\*(lqicomp\*(rq will control the default switches for this invocation of
+the
+.i comp
+program.
+This provides a powerful
+definitional facility for commonly used switch settings.
+.pp
+The default editor
+for editing within
+.i comp ,
+.i repl ,
+.i forw ,
+and
+.i dist ,
+is \*(lq/bin/ned\*(rq.\**
+.(f
+\**See Ref. 6 for a description of
+the NED text editor.
+.)f
+A different editor may be used by specifying
+the profile entry
+\*(lqEditor: \*(rq.
+The argument to \*(lqEditor\*(rq is the name of an
+executable program or shell command file which can be found via
+the user's $PATH defined search path, excluding the current
+directory.
+The \*(lqEditor:\*(rq profile specification
+may in turn be overridden by a \*(lq\-editor\0<editor>\*(rq
+profile switch associated with
+.i comp ,
+.i repl ,
+.i forw ,
+or
+.i dist .
+Finally, an explicit editor switch specified with any
+of these four commands will have ultimate precedence.
+.pp
+During message composition, more than one editor may be
+used.
+For example, one editor (such as
+.i prompter )
+may be used
+initially, and a second editor may be invoked later to revise
+the message being composed
+(see the discussion of
+.i comp
+in Section 5 for details).
+A profile entry \*(lq<lasteditor>\-next:\0<editor>\*(rq specifies the name of
+the editor to be used after a particular editor.
+Thus \*(lqcomp:\0\-e\0prompter\*(rq
+causes the initial text to be collected by
+.i prompter ,
+and the profile entry \*(lqprompter\-next:\0ed\*(rq names ed as the
+editor to be invoked for the next round of editing.
+.pp
+Some of the MH commands, such as
+.i show ,
+can be used on
+message folders owned by others, if those folders are readable.
+However,
+you cannot write in someone else's folder.
+All the MH command
+actions not requiring write permission may be used with
+a \*(lqread-only\*(rq folder.
+In a writable folder, a file named
+\*(lqcur\*(rq is used to contain its current message name.
+For read-only folders, the current message name is
+stored in the user's profile.
+.pp
+Table 1 lists examples of the currently defined profile
+entries, typical arguments, and the programs that reference the
+entries.
+.in .9i
+.ll -.9i
+.ta 2.3i
+.sp 30p
+.ce
+Table 1
+.sp 8p
+.ce
+P\s-2ROFILE\s0 C\s-2OMPONENTS\s0
+.hl             \" ~12p preceding + 1v (12p) after
+.nf
+^^MH Programs that
+^Keyword and Argument~^\ Use Component\h'|\n(.lu-.9i'\v'4p'\l'|0'\v'-4p'  \" \l'..' does underlining
+.sp
+^Path:\0Mail~^All
+^Current-Folder:\0inbox~^Most
+^Editor:\0/bin/ed~^\fIcomp, dist, forw, repl\fR
+^Msg\-Protect:\0644~^\fIinc\fR
+^Folder\-Protect:\0711~^\fIfile, inc, pick\fR
+^<program>:\0default switches~^All
+^cur\-<read-onlyfolder>:\0172~^Most
+^prompter\-next:\0ed~^\fIcomp, dist, forw, repl\fR
+.hl
+.ll +.9i
+.in 0
+.fi
+.pp
+Path
+.u should
+be present.
+Folder is maintained
+automatically by many MH commands (see the \*(lqContext\*(rq sections of
+the individual commands in Sec. V).
+All other entries are optional,
+defaulting to the values described above.
+.uh "MESSAGE NAMING"
+.pp
+Messages may be referred to explicitly or implicitly when
+using MH commands.
+A formal syntax of message names is given in Appendix C, but the
+following description should be sufficient for most MH users.
+Some details of message naming that apply only to certain
+commands are included in the description of those
+commands.
+.pp
+Most of the MH commands accept arguments specifying one or
+more folders, and one or more messages to operate on.
+The use of
+the word \*(lqmsg\*(rq as an argument to a command means that exactly one
+message name may be specified.
+A message name may be a number,
+such as 1, 33, or 234, or it may be
+one of the \*(lqreserved\*(rq message names:
+first, last, prev, next, and cur.
+(As a shorthand, a
+period (\*.) is equivalent to cur.)
+The meanings of these names
+are straightforward:  \*(lqfirst\*(rq is the first message in the
+folder; \*(lqlast\*(rq is the last
+message in the folder; \*(lqprev\*(rq is the
+message numerically previous to the current message; \*(lqnext\*(rq
+is the message numerically following the current message; \*(lqcur\*(rq
+(or \*(lq\*.\*(rq) is the current message in the folder.
+.pp
+The default in commands that take a \*(lqmsg\*(rq argument is
+always \*(lqcur\*(rq.
+.pp
+The word \*(lqmsgs\*(rq indicates that several messages may be
+specified.
+Such a specification consists of several message
+designations separated by spaces.
+A message designation is
+either a message name or a message range.
+A message range is a
+specification of the form name1\-name2 or name1:n, where name1 and
+name2 are message names and n is an integer.
+The first form
+designates all the messages from name1 to name2 inclusive; this
+must be a non-empty range.
+The second form specifies up to n
+messages, starting with name1 if name1 is a number, or first,
+cur, or next, and ending with name1 if name1 is last or
+prev.
+This interpretation of n is overridden if n is preceded
+by a plus sign or a minus sign;
++n always means up to n messages starting with
+name1, and \-n always means up to n messages ending with name1.
+Repeated specifications of the same message have the same effect
+as a single specification of
+the message.
+Examples of
+specifications are:
+
+.(b
+1 5 7\-11 22
+first 6 8 next
+first\-10
+last:5
+.)b
+.pp
+The message name \*(lqall\*(rq is a shorthand for \*(lqfirst\-last\*(rq,
+indicating all of the messages in the folder.
+.pp
+The limit on the number of messages in an expanded message
+list is generally 999\*-the maximum number of messages in a
+folder.
+However, the
+.i show
+command and the
+commands `\fIpick\0\-scan\fR' and `\fIpick\0\-show\fR'
+are constrained to have argument lists
+that are no more than 512 characters long.
+(Under Version 7 UNIX this limit is 4096.)
+.pp
+In commands that accept \*(lqmsgs\*(rq arguments, the default is
+either cur or all, depending on which makes more sense.
+.pp
+In all of the MH commands, a plus sign preceding an argument
+indicates a folder name.
+Thus, \*(lq+inbox\*(rq is the name of the
+user's standard inbox.
+If an explicit folder argument is given
+to an MH command, it will become the current folder (that is,
+the \*(lqCurrent-Folder:\*(rq entry
+in \*(lq\*.mh\(ruprofile\*(rq will be changed to this
+folder).
+In the case of the
+.i file
+and
+.i pick
+commands, which
+can have multiple output folders, a new source folder (other than
+the default current folder) is specified by \*(lq\-src\0+folder\*(rq.
+.uh "OTHER MH CONVENTIONS"
+.pp
+One very powerful feature of MH is that the MH commands may
+be issued from any current directory, and the proper path to
+the appropriate folder(s) will be taken from the user's profile.
+If the MH path is not appropriate for a specific folder or file,
+the automatic prepending of the MH path can be avoided by
+beginning a folder or file name with \fB/\fR.
+Thus any specific full
+path may be specified.
+.pp
+Arguments to the various programs may be given in any order,
+with the exception of a few switches whose arguments must follow
+immediately, such as \*(lq\-src\0+folder\*(rq for \fIpick\fR and \fIfile\fR.
+.pp
+Whenever an MH command prompts the user, the valid options
+will be listed in response to a <RETURN>.
+(The first of the
+listed options is the default if end-of-file is encountered, such
+as from a command file.)  A valid response is any \fIunique\fR
+abbreviation of one of the listed options.
+.pp
+Standard UNIX documentation conventions are used in this report
+to describe MH command syntax.
+Arguments enclosed in brackets
+([ ]) are optional; exactly one of the arguments enclosed
+within braces ({ }) must be specified, and all other
+arguments are required.
+The use of ellipsis dots (...) indicates
+zero or more repetitions of the previous item.
+For example,
+\*(lq+folder ...\*(rq would indicate that one or more \*(lq+folder\*(rq arguments
+is required and \*(lq[+folder ...]\*(rq indicates that 0 or more
+\*(lq+folder\*(rq arguments may be given.
+.pp
+MH departs from UNIX standards by using switches that consist of
+more than one character, e.g. \*(lq\-header\*(rq.
+To minimize typing,
+only a unique abbreviation of a switch need be typed; thus, for
+\*(lq\-header\*(rq, \*(lq\-hea\*(rq is probably sufficient, depending on the
+other switches the command accepts.
+Each MH program
+accepts the switch \*(lq\-help\*(rq (which \fImust\fR be spelled out fully)
+and produces a syntax description and a list of switches.
+In the
+list of switches, parentheses indicate required characters.
+For example, all \*(lq\-help\*(rq switches will appear as \*(lq\-(help)\*(rq,
+indicating that no abbreviation is accepted.
+.pp
+Many MH switches have both on and off forms, such as
+\*(lq\-format\*(rq and \*(lq\-noformat\*(rq.
+In many of the descriptions in Sec. V,
+only one form is defined; the other form, often used to
+nullify profile switch settings, is assumed to be the opposite.
+.br
+.bp
+.uh "MH COMMANDS"
+.pp
+The MH package comprises 16 programs:
+
+.nf
+.in .5i
+.ta 1.5i
+^comp~^Compose a message
+^dist~^Redistribute a message
+^file~^Move messages between folders
+^folder~^Select/list status of folders
+^forw~^Forward a message
+^inc~^Incorporate new mail
+^next~^Show the next message
+^pick~^Select a set of messages by context
+^prev~^Show the previous message
+^prompter~^Prompting editor front end for composing messages
+^repl~^Reply to a message
+^rmf~^Remove a folder
+^rmm~^Remove messages
+^scan~^Produce a scan listing of selected messages
+^send~^Send a previously composed message
+^show~^Show messages
+.fi
+.re
+.pp
+These programs are described below.
+The form of the descriptions
+conforms to the standard
+form for the description of UNIX commands.
+.if t \{
+.ll 6.5i
+.lt 6.5i
+\}
+.fo '7th Edition'UNIX/32V(Rand)''
+.de SC
+.he '\\$1(1)'-%-'\\$1(1)'
+.bp
+.(x
+.ti .8i
+\\$1
+.)x
+..
+.de NA
+.b \\s-2NAME\\s0
+.ti .5i
+..
+.de SY
+.sp
+.b \\s-2SYNOPSIS\\s0
+.in 1i
+.ti .5i
+.na
+..
+.de DE
+.ad
+.sp
+.in 0
+.b  \\s-2DESCRIPTION\\s0
+.sp
+.fi
+.in .5i
+..
+.de Fi
+.(b L
+.ti 0
+.b \\s-2Files\\s0
+.ta 2i
+..
+.de Pr
+.)b
+.(b L F
+.in 2.5i
+.ti 0
+.b "\\s-2Profile Components\\s0"
+.ti .5i
+..
+.de Ps
+.ti .5i
+..
+.de De
+.)b
+.(b L
+.in .5i
+.ti 0
+.b \\s-2Defaults\\s0
+..
+.de Co
+.)b
+.(b L F
+.ti 0
+.b \\s-2Context\\s0
+.br
+..
+.de En
+.)b
+.in 0
+..
+.SC COMP
+.NA
+comp \- compose a message
+
+.SY
+comp \%[\-editor\ editor] \%[\-form\ formfile] \%[file] \%[\-use]
+\%[\-nouse] \%[\-help]
+
+.DE
+\fIComp\fP is used to create a new message to be mailed.
+If
+\fIfile\fP is not specified, the file named \*(lqdraft\*(rq in the user's MH
+directory will be used.
+\fIComp\fR copies a message form to
+the file being composed and then invokes an editor on the
+file.
+The default editor is /bin/ned, which may be overridden with
+the `\-editor' switch or with a profile entry \*(lqEditor:\*(rq.
+(See Ref. 5 for a
+description of the NED text editing system.)
+The default
+message form contains the following elements:
+
+     To:
+     cc:
+     Subject:
+     ----------
+
+If the file named \*(lqcomponents\*(rq exists in the user's MH directory,
+it will be used instead of this form.
+If `\-form
+formfile' is specified, the specified formfile (from the MH
+directory) will be used as the skeleton.
+The line of dashes
+or a blank line must be left between the header and the
+body of the message for the message to be identified properly when it is
+sent (see \fIsend;\fR).
+The switch `\-use' directs \fIcomp\fR to
+continue editing an already started message.
+That is, if a
+\fIcomp\fR (or \fIdist\fR, \fIrepl\fR, or \fIforw\fR) is terminated without
+sending the message, the message can be edited again via
+\*(lqcomp \-use\*(rq.
+
+If the specified file (or draft) already exists, \fIcomp\fR will ask
+if you want to delete it before continuing.
+A reply of \fBNo\fR will abort the
+\fIcomp\fR, \fByes\fR will replace the existing draft with a blank
+skeleton, \fBlist\fR will display the draft, and \fBuse\fR will use it
+for further composition.
+
+Upon exiting from the editor, \fIcomp\fR will ask \*(lqWhat now?\*(rq.
+The valid
+responses are \fBlist\fR, to list the draft on the terminal; \fBquit\fR, to
+terminate the session and preserve the draft; \fBquit delete\fR, to terminate,
+then delete the draft; \fBsend\fR, to send the message; \fBsend verbose\fR, to
+cause the delivery process to be monitored; \fBedit <editor>\fR, to invoke
+<editor> for further editing; and \fBedit\fR, to re-edit using the
+same editor that was used on the preceding round unless a profile
+entry \*(lq<lasteditor>\-next: <editor>\*(rq names an alternative editor.
+
+.Fi
+^/etc/mh/components~^The message skeleton
+^or <mh-dir>/components~^Rather than the standard skeleton
+^$HOME/\*.mh\(ruprofile~^The user profile
+^<mh-dir>/draft~^The default message file
+^/usr/bin/send~^To send the composed message
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Editor:~^To override the use of /bin/ned as the default editor
+.Ps
+^<lasteditor>\-next:~^To name an editor to be used after exit from <lasteditor>
+.De
+`file' defaults to draft
+`\-editor' defaults to /bin/ned
+`\-nouse'
+.Co
+\fIComp\fR does not affect either the current folder or the current message.
+.En
+.SC DIST
+.NA
+dist \- redistribute a message to additional addresses
+.SY
+dist \%[+folder] \%[msg] \%[\-form\ formfile] \%[\-editor\ editor]
+\%[\-annotate] \%[\-noannotate]
+\%[\-inplace] \%[\-noinplace]
+\%[\-help]
+.DE
+\fIDist\fR is similar to \fIforw\fR.
+It prepares the specified
+message for redistribution to addresses that (presumably) are
+not on the original address list.
+The file \*(lqdistcomps\*(rq in the
+user's MH directory, or a standard form, or the file specified by
+`\-form formfile' will be used as the blank components file to
+be prepended to the message being distributed.
+The standard form
+has the components \*(lqDistribute-to:\*(rq and \*(lqDistribute-cc:\*(rq.
+When
+the message is sent, \*(lqDistribution-Date:\0date\*(rq,
+\*(lqDistribution-From:\0name\*(rq, and
+\*(lqDistribution-Id:\0id\*(rq (if `\-msgid' is
+specified to \fIsend\fR;) will be prepended to the outgoing message.
+Only those addresses in \*(lqDistribute-To\*(rq, \*(lqDistribute-cc\*(rq, and
+\*(lqDistribute-Bcc\*(rq will be sent.
+Also, a \*(lqDistribute-Fcc:\0folder\*(rq
+will be honored (see \fIsend;\fR).
+
+\fISend\fR recognizes a message as a redistribution message by the
+existence of the field \*(lqDistribute-To:\*(rq, so don't try to
+redistribute a message with only a \*(lqDistribute-cc:\*(rq.
+
+If the `\-annotate' switch is given, each message being
+distributed will be annotated with the lines:
+
+     Distributed:\0\*(<<date\*(>>
+     Distributed:\0Distribute-to: names
+
+where each \*(lqto\*(rq list contains as many lines as required.
+This annotation
+will be done only if the message is sent directly from \fIdist\fR.
+If the
+message is not sent immediately from \fIdist\fR (i.e., if it is sent later
+via \fIsend;\fR),
+\*(lqcomp \-use\*(rq may be used to re-edit and send the constructed message, but
+the annotations won't take place.
+The '\-inplace' switch causes annotation to
+be done in place in order to preserve links to the annotated message.
+
+See \fIcomp\fR for a description of the `\-editor' switch and for options
+upon exiting from the editor.
+
+.Fi
+^/etc/mh/components~^The message skeleton
+^or <mh-dir>/components~^Rather than the standard skeleton
+^$HOME/\*.mh\(ruprofile~^The user profile
+^<mh-dir>/draft~^The default message file
+^/usr/bin/send~^To send the composed message
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Editor:~^To override the use of /bin/ned as the default editor
+.Ps
+^<lasteditor>\-next:~^To name an editor to be used after exit from <lasteditor>
+.De
+`+folder' defaults to the current folder
+`msg' defaults to cur
+`\-editor' defaults to /bin/ned
+`\-noannotate'
+`\-noinplace'
+.Co
+If a +folder is specified, it will become the current
+folder, and the current message will be set to the message
+being redistributed.
+.En
+.SC FILE
+.NA
+file \- file message(s) in (an)other folder(s)
+.SY
+file \%[\-src\ +folder] \%[msgs] \%[\-link] \%[\-preserve] \%+folder\ ...
+\%[\-nolink] \%[\-nopreserve]
+\%[\-file\ file] \%[\-nofile] \%[\-help]
+.DE
+\fIFile\fR moves (\fImv\fR(I)) or links (\fIln\fR(I)) messages from a
+source folder into one or more destination folders.
+If you think
+of a message as a sheet of paper, this operation is not
+unlike filing the sheet of paper (or copies) in file cabinet
+folders.
+When a message is filed, it is linked into the
+destination folder(s) if possible, and is copied otherwise.
+As long
+as the destination folders are all on the same file system, multiple filing
+causes little storage overhead.
+This facility provides a good way to cross-file or multiply-index
+messages.
+For example, if a message is received from Jones about
+the ARPA Map Project, the command
+
+     file\0cur\0+jones\0+Map
+
+would allow the message to be found in either of the two
+folders `jones' or `Map'.
+
+The option `\-file file' directs \fIfile\fR to use the specified
+file as the source message to be filed, rather than a message from
+a folder.
+
+If a destination folder doesn't exist, \fIfile\fR will ask if you
+want to create one.
+A negative response will abort the file
+operation.
+
+`\-link' preserves the source folder copy of the message
+(i.e., it does a \fIln\fR(I) rather than a \fImv\fR(I)), whereas,
+`\-nolink' deletes the \*(lqfiled\*(rq messages from the source
+folder.
+Normally, when a message is filed, it is assigned the
+next highest number available in each of the destination folders.
+Use of the `\-preserve' switch will override this message
+\*(lqrenaming\*(rq, but name conflicts may occur, so
+use this switch cautiously.
+(See \fIpick\fR for more details on
+message numbering.)
+
+If `\-link' is not specified (or `\-nolink' is specified),
+the filed messages will be removed (unlink(II)) from the
+source folder.
+
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Current-Folder:~^To find the default current folder
+.Ps
+^Folder\-Protect:~^To set mode when creating a new folder
+.De
+`\-src +folder' defaults to the current folder
+`msgs' defaults to cur
+`\-nolink'
+`\-nopreserve'
+`\-nofile'
+.Co
+If `\-src +folder' is given, it will become the
+current folder for future MH commands.
+If neither `\-link' nor
+`all' are specified, the current message in the source
+folder will be set to the last message specified; otherwise, the
+current message won't be changed.
+.En
+.SC FOLDER
+.NA
+folder \- set/list current folder/message
+.SY
+folder \%[+folder] \%[msg] \%[\-all] \%[\-fast] \%[\-nofast] \%[\-up] \%[\-down]
+\%[\-header] \%[\-noheader] \%[\-total] \%[\-nototal] \%[\-pack] \%[\-nopack]
+\%[\-help]
+
+.ti .5i
+folders  <equivalent to 'folder \-all'>
+.DE
+Since the MH environment is the shell, it is easy to lose
+track of the current folder from day to day.
+\fIFolder\fR will
+list the current folder, the number of messages in it, the
+range of the messages (low-high), and the current message within
+the folder, and will flag a selection list or extra files if they
+exist.
+An example of the output is:
+
+      inbox+ has 16 messages ( 3\- 22); cur= 5.
+
+If a `+folder' and/or `msg' are specified, they will
+become the current folder and/or message.
+An `\-all' switch
+will produce a line for each folder in the user's MH directory,
+sorted alphabetically.
+These folders are preceded by the read-only
+folders, which occur as \*.mh\(ruprofile \*(lqcur\-\*(rq entries.
+For example,
+
+.nf
+.ta 1.5i 2.1i 2.7i 3.5i
+^~Folder\ \ ^^~#\ of\ ^^messages~^^(~\ range\~ );\ ^cur msg (other files)
+^~/fsd/rs/m/tacc\ \ ^^has~35\ ^^messages~^^(~1\-\035);\ ^cur=\ 23.
+^~/rnd/phyl/Mail/EP\ \ ^^has~82\ ^^messages~^^(~1\-108);\ ^cur=\ 82.
+^~f\&f\ \ ^^has~4\ ^^messages~^^(~1\-\0\04);\ ^cur=\ \01.
+^~inbox+\ ^^has~16\ ^^messages~^^(~3\-\022);\ ^cur=\ \05.
+^~mh\ \ ^^has~76\ ^^messages~^^(~1\-\076);\ ^cur=\ 70.
+^~notes\ \ ^^has~2\ ^^messages~^^(~1\-\0\02);\ ^cur=\ \01.
+^~ucom\ \ ^^has~124\ ^^messages~^^(~1\-124);\ ^cur=\ \06; (select).
+
+^^^~TOTAL=\0339\ ^messages\0in\0\07\0Folders.
+.re
+.fi
+
+The \*(lq+\*(rq after inbox indicates that it is the current folder.
+The \*(lq(select)\*(rq indicates that the folder ucom has a selection
+list produced by \fIpick\fR.
+If \*(lqothers\*(rq had appeared in parentheses at
+the right of a line, it would indicate that there are files in
+the folder directory that don't belong under the MH file naming
+scheme.
+
+The header is output if either an `\-all' or a `\-header' switch
+is specified; it is suppressed by `\-noheader'.
+Also, if \fIfolder\fR
+is invoked by a name ending with \*(lqs\*(rq (e.g., \fIfolders\fR),
+`\-all' is assumed.
+A `\-total' switch will produce only the
+summary line.
+
+If `\-fast' is given, only the folder name (or names in the
+case of `\-all') will be listed.
+(This is faster because the
+folders need not be read.)
+
+The switches `\-up' and `\-down' change the folder to be the
+one above or below the current folder.
+That is, \*(lqfolder \-down\*(rq
+will set the folder to \*(lq<current\-folder>/select\*(rq, and if the
+current folder is a selection-list folder, \*(lqfolder \-up\*(rq will
+set the current folder to the parent of the selection-list.
+(See \fIpick\fR for details on selection-lists.)
+
+The `\-pack' switch will compress the message names in a folder, removing
+holes in message numbering.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+^/bin/ls~^To fast-list the folders
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+`+folder' defaults to the current folder
+`msg' defaults to none
+`\-nofast'
+`\-noheader'
+`\-nototal'
+`\-nopack'
+.Co
+If `+folder' and/or `msg' are given, they will become the
+current folder and/or message.
+.En
+.SC FORW
+.NA
+forw \- forward messages
+.SY
+forw \%[+folder] \%[msgs] \%[\-editor\ editor] \%[\-form\ formfile]
+\%[\-annotate] \%[\-noannotate]
+\%[\-inplace]  \%[\-noinplace]
+\%[\-help]
+.DE
+\fIForw\fR may be used to prepare a message containing other
+messages.
+It constructs the new message from the components file
+or `\-form formfile' (see \fIcomp\fR), with a body composed of the
+message(s) to be forwarded.
+An editor is invoked as in \fIcomp\fR,
+and after editing is complete, the user is prompted before the message
+is sent.
+
+If the `\-annotate' switch is given, each message being
+forwarded will be annotated with the lines
+
+     Forwarded: \*(<<date\*(>>
+     Forwarded: To: names
+     Forwarded: cc: names
+
+where each \*(lqTo:\*(rq and \*(lqcc:\*(rq list contains as many lines as required.
+This annotation will be done only if the message is sent directly
+from \fIforw\fR.
+If the message is not sent immediately from \fIforw\fR,
+\*(lqcomp \-use\*(rq may be used in a later session to re-edit and send
+the constructed message, but the annotations won't take place.
+The `\-inplace' switch permits annotating a message in place in
+order to preserve its links.
+
+See \fIcomp\fR for a description of the `\-editor' switch.
+.Fi
+^/etc/mh/components~^The message skeleton
+^or <mh-dir>/components~^Rather than the standard skeleton
+^$HOME/\*.mh\(ruprofile~^The user profile
+^<mh-dir>/draft~^The default message file
+^/usr/bin/send~^To send the composed message
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Editor:~^To override the use of /bin/ned as the default editor
+.Ps
+^Current-Folder:~^To find the default current folder
+.Ps
+^<lasteditor>\-next:~^To name an editor to be used after exit from <lasteditor>
+.De
+`+folder' defaults to the current folder
+`msgs' defaults to cur
+`\-editor' defaults to /bin/ned
+`\-noannotate'
+`\-noinplace'
+.Co
+If a +folder is specified, it will become
+the current folder, and the current message will be set to
+the first message being forwarded.
+.En
+.SC INC
+.NA
+inc \- incorporate new mail
+.SY
+inc \%[+folder] \%[\-audit\ audit-file] \%[\-help]
+.DE
+\fIInc\fR incorporates mail from the user's incoming mail drop
+(\*.mail) into an MH folder.
+If `+folder' isn't specified,
+the folder named \*(lqinbox\*(rq in the user's MH directory will be used.
+The
+new messages being incorporated are assigned numbers starting
+with the next highest number in the folder.
+If the specified (or
+default) folder doesn't exist, the user will be queried prior to
+its creation.
+As the messages are processed, a \fIscan\fR  listing
+of the new mail is produced.
+
+If the user's profile contains a \*(lqMsg\-Protect: nnn\*(rq entry, it
+will be used as the protection on the newly created messages,
+otherwise the MH default of 664 will be used.
+During all
+operations on messages, this initially assigned protection will
+be preserved for each message, so \fIchmod\fR(I) may be used to set a
+protection on an individual message, and its protection will be
+preserved thereafter.
+
+If the switch `\-audit audit-file' is specified (usually as a
+default switch in the profile), then \fIinc\fR will append a header
+line and a line per message to the end of the specified
+audit-file with the format:
+
+.nf
+.ti 1i
+\*(<<inc\*(>> date
+.ti 1.5i
+<scan line for first message>
+.ti 1.5i
+<scan line for second message>
+.ti 2.5i
+<etc.>
+.fi
+
+This is useful for keeping track of volume and source of incoming
+mail.
+Eventually, \fIrepl\fR, \fIforw\fR, \fIcomp\fR, and \fIdist\fR may also
+produce audits to this (or another) file, perhaps with
+\*(lqMessage-Id:\*(rq information to keep an exact correspondence history.
+\*(lqAudit-file\*(rq will be in the user's MH directory unless a full
+path is specified.
+
+\fIInc\fR will incorporate even illegally formatted messages into the
+user's MH folder, inserting a blank line prior to the offending
+component and printing a comment identifying the bad message.
+
+In all cases, the \*.mail file will be zeroed.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+^$HOME/\*.mail~^The user's mail drop
+^<mh-dir>/audit-file~^Audit trace file (optional)
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Folder\-Protect:~^For protection on new folders
+.Ps
+^Msg\-Protect:~^For protection on new messages
+.De
+`+folder' defaults to \*(lqinbox\*(rq
+.Co
+The folder into which the message is
+being incorporated will become the
+current folder, and the first message incorporated will be the
+current message.
+This leaves the context ready for a \fIshow\fR
+of the first new message.
+.En
+.SC NEXT
+.NA
+next \- show the next message
+.SY
+next \%[+folder] \%[\-switches\ for\ \fIl\fR] \%[\-help]
+.DE
+\fINext\fR performs a \fIshow\fR on the next message in the
+specified (or current) folder.
+Like \fIshow\fR, it passes any
+switches on to the program \fIl\fR, which is called to list the
+message.
+This command is exactly equivalent to \*(lqshow next\*(rq.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+.Co
+If a folder is specified, it will become the current folder, and the
+message that is shown (i.e., the next message in sequence)
+will become the current message.
+.En
+.SC PICK
+.NA
+pick \- select messages by content
+.SY
+.ta .4i 1.8i
+.nf
+.in .5i
+^pick~^^\0\-cc~^ \%[\-src\ +folder] \%[msgs] \%[\-help] \%[\-scan] \%[\-noscan]
+^^^\0\-date~^   \%[\-show] \%[\-noshow] \%[\-nofile] \%[\-nokeep]
+^^^\0\-from~^
+^^^\s+2\b'\(lt\(bv\(bv\(lk\(bv\(bv\(lb'\s0 \-search~\s+2\b'\(rt\(bv\(bv\(rk\(bv\(bv\(rb'\s0^ pattern
+^^^\0\-subject~^
+^^^\0\-to~^ \%[\-file \%[\-preserve] \%[\-link] \%+folder\ ... \%[\-nopreserve] \%[\-nolink] ]
+^^^\0\-\-component~^ \%[\-keep \%[\-stay] \%[\-nostay] \%[+folder\ ...]\ ]
+.fi
+
+.re
+.ti .5i
+typically:
+.in 1i
+pick\0\-from\0jones\0\-scan
+.br
+pick\0\-to\0holloway
+.br
+pick\0\-subject\0ned\0\-scan\0\-keep
+.DE
+\fIPick\fR searches messages within a folder for the specified
+contents, then performs several operations on the selected
+messages.
+
+A modified \fIgrep\fR(I) is used to perform the searching, so the
+full regular expression (see \fIed\fR(I)) facility is available
+within `pattern'.
+With `\-search', pattern is used directly,
+and with the others, the grep pattern constructed is:
+
+.ti +.5i
+\*(lq^component:\*.\*(**pattern\*(rq
+
+This means that the pattern specified for a `\-search' will be
+found everywhere in the message, including the header and the body,
+while the other search requests are limited to the single
+specified component.
+The expression `\-\-component pattern'
+is a shorthand for
+specifying `\-search \*(lqcomponent:\*.\*(**pattern\*(rq\ '; it is used to pick
+a component not in the set [cc date from subject to].
+An
+example is \*(lqpick \-\-reply\-to pooh \-show\*(rq.
+
+Searching is performed on a per-line basis.
+Within the header of
+the message, each component is treated as one long line, but in
+the body, each line is separate.
+Lower-case letters in the
+search pattern will match either lower or upper case in the
+message, while upper case will match only upper case.
+
+Once the search has been performed, the selected messages
+are scanned (see \fIscan\fR) if the `\-scan' switch is given, and
+then they are shown (see \fIshow\fR) if the `\-show' switch is
+given.
+After these two operations, the file operations (if
+requested) are performed.
+
+The `\-file' switch operates exactly like the \fIfile\fR command, with the
+same meaning for the `\-preserve' and `\-link' switches.
+
+The `\-keep' switch is similar to `\-file', but it produces a folder that
+is a subfolder of the folder being searched and defines it as
+the current folder (unless the `\-stay' flag is used).
+This
+subfolder contains the messages which matched the search
+criteria.
+All of the MH commands may be used with the sub-folder
+as the current folder.
+This gives the user considerable power
+in dealing with subsets of messages in a folder.
+
+The messages in a folder produced by `\-keep' will always have the
+same numbers as they have in the source folder (i.e., the
+`\-preserve' switch is automatic).
+This way, the message
+numbers are consistent with the folder from which the messages
+were selected.
+Messages are not removed from the source folder
+(i.e., the `\-link' switch is assumed).
+If a `+folder' is not
+specified, the standard name \*(lqselect\*(rq will be used.
+(This is the
+meaning of \*(lq(select)\*(rq when it appears in the output of the
+\fIfolder\fR command.) If `+folder' arguments are given to
+`\-keep', they will be used rather than \*(lqselect\*(rq for the names
+of the subfolders.
+This allows for several subfolders to be
+maintained concurrently.
+
+When a `\-keep' is performed, the subfolder becomes the current folder.
+This can be overridden by use
+of the `\-stay' switch.
+
+Here's an example:
+
+.nf
+\01  % folder +inbox
+\02           inbox+ has  16 messages (  3\- 22); cur=  3.
+\03  % pick \-from dcrocker
+\04  6 hits.
+\05  [+inbox/select now current]
+\06  % folder
+\07    inbox/select+ has  \06 messages (  3\- 16); cur=  3.
+\08  % scan
+.ds p \\h'\\w'+'u'
+\09   \03+  6/20   Dcrocker          Re: ned file update issue...
+10   \06\*p  6/23   Dcrocker          removal of files from /tm...
+11   \08\*p  6/27   Dcrocker          Problems with the new ned...
+12   13\*p  6/28   d\h'\w'D'u-\w'd'u'crocker          newest nned  \*(<<I would ap...
+13   15\*p  7/\05   Dcrocker          nned  \*(<<Last week I asked...
+14   16\*p  7/\05   d\h'\w'D'u-\w'd'u'crocker          message id format  \*(<<I re...
+15  % show all | print
+16     [produce a full listing of this set of messages on the line printer.]
+17  % folder \-up
+18            inbox+ has  16 messages (  3\- 22); cur=  3; (select).
+19  % folder \-down
+20   inbox/select+ has   6 messages (  3\- 16); cur=  3.
+21  % rmf
+22  [+inbox now current]
+23  % folder
+24            inbox+ has  16 messages (  3\- 22); cur=  3.
+.fi
+
+This is a rather lengthy example, but it shows the power of the
+MH package.
+In item 1, the current folder is set to inbox.
+In 3,
+all of the messages from dcrocker are found in inbox and linked
+into the folder \*(lqinbox/select\*(rq.
+(Since no action switch is
+specified, `\-keep' is assumed.)  Items 6 and 7 show that this
+subfolder is now the current folder.
+Items 8 through 14 are a
+\fIscan\fR of the selected messages (note that they are all from dcrocker
+and are all in upper and lower case).
+Item 15 lists all of the messages to
+the high-speed printer.
+Item 17 directs \fIfolder\fR to set the
+current folder to the parent of the selection-list folder, which
+is now current.
+Item 18 shows that this has been done.
+Item 19 resets
+the current folder to the selection list, and 21 removes the
+selection-list folder and resets the current folder to the
+parent folder, as shown in 22 and 23.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Folder\-Protect:~^For protection on new folders
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+`\-src +folder' defaults to current
+`msgs' defaults to all
+.fi
+`\-keep +select' is the default if no `\-scan', `\-show', or `\-file' is specified
+.Co
+If a `\-src +folder' is specified, it will
+become the current folder, unless a `\-keep' with 0 or 1
+folder arguments makes the selection-list subfolder the
+current folder.
+Each selection-list folder will have its
+current message set to the first of the messages linked into
+it unless the selection list already existed, in which case the
+current message won't be changed.
+.En
+.SC PREV
+.NA
+prev \- show the previous message
+.SY
+prev \%[+folder] \%[\-switches\ for\ \fIl\fR] \%[\-help]
+.DE
+\fIPrev\fR performs a \fIshow\fR on the previous message in the specified
+(or current) folder.
+Like \fIshow\fR, it passes any switches on to the
+program \fIl\fR, which is called to list the message.
+This command
+is exactly equivalent to \*(lqshow prev\*(rq.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+.Co
+If a folder is specified, it will become current, and the
+message that is shown (i.e., the previous message in sequence)
+will become the current message.
+.En
+.SC PROMPTER
+.NA
+prompter \- prompting editor front end
+.SY
+This program is not called directly but takes the place
+of an editor and acts as an editor front end.
+
+.ti .5i
+prompter \%[\-erase\ chr] \%[\-kill\ chr] \%[\-help]
+.DE
+\fIPrompter\fR is an editor which allows rapid composition of
+messages.
+It is particularly useful to network and low-speed
+(less than 2400 baud) users of MH.
+It is an MH program in that
+it can have its own profile entry with switches, but it can't
+be invoked directly as all other MH commands can; it is an editor
+in that it is invoked by an \*(lq\-editor prompter\*(rq switch or by the
+profile entry \*(lqEditor: prompter\*(rq, but functionally it is merely
+a text-collector and not a true editor.
+
+\fIPrompter\fR expects to be called from \fIcomp\fR, \fIrepl\fR, \fIdist\fR, or
+\fIforw\fR, with a draft file as an argument.
+For example, \*(lqcomp
+\-editor prompter\*(rq will call \fIprompter\fR with the file \*(lqdraft\*(rq already set
+up with blank components.
+For each blank component it finds in
+the draft, it prompts the user and accepts a response.
+A
+<RETURN> will cause the whole component to be left out.
+A \*(lq\\\*(rq
+preceding a <RETURN> will continue the response on the next line,
+allowing for multiline components.
+
+Any component that is non-blank will be copied and echoed to the
+terminal.
+
+The start of the message body is prompted by a line of
+dashes.
+If the body is non-blank, the prompt is
+\*(lq--------Enter additional text\*(rq.
+Message-body typing is terminated with
+a <CTRL-D> (or <OPEN>).
+Control is returned to the calling
+program, where the user is asked \*(lqWhat now?\*(rq.
+See \fIcomp\fR for
+the valid options.
+
+The line editing characters for kill and erase may be
+specified by the user via the arguments \*(lq\-kill chr\*(rq and \*(lq\-erase
+chr\*(rq, where chr may be a character; or \*(lq\\nnn\*(rq, where nnn is the
+octal value for the character.
+(Again, these may come from the
+default switches specified in the user's profile.)
+
+A <DEL> during message-body typing is equivalent to
+<CTRL-D> for compatibility with NED.
+A <DEL> during
+component typing will abort the command that invoked
+\fIprompter\fR.
+.Fi
+None
+.Pr
+^prompter-next:~^To name the editor to be used on exit from \fIprompter\fR
+.De
+.Co
+None
+.En
+.SC REPL
+.NA
+repl \- reply to a message
+.SY
+repl \%[+folder] \%[msg] \%[\-editor\ editor] \%[\-inplace] \%[\-annotate]
+\%[\-help] \%[\-noinplace]
+\%[\-noannotate]
+.DE
+\fIRepl\fR aids a user in producing a reply to an existing
+message.
+In its simplest form (with no arguments), it will set up
+a message-form skeleton in reply to the current message in the
+current folder, invoke the editor, and send the composed
+message if so directed.
+The composed message is constructed as
+follows:
+
+.nf
+.in 1i
+To: <Reply-To> or <From>
+cc: <cc>, <To>
+Subject: Re: <Subject>
+In-reply-to: Your message of <Date>
+.ti +\w'In-reply-to: 'u
+<Message-Id>
+.in .5i
+.fi
+
+where field names enclosed in angle brackets (< >) indicate the
+contents of the named field from the message to which the reply
+is being made.
+Once the skeleton is constructed, an editor is
+invoked (as in \fIcomp\fR, \fIdist\fR, and \fIforw\fR).
+While in the editor,
+the message being replied to is available through a link named
+\*(lq@\*(rq.
+In NED, this means the replied-to message may be \*(lqused\*(rq
+with \*(lquse @\*(rq, or put in a window by \*(lqwindow @\*(rq.
+
+As in \fIcomp\fR, \fIdist\fR, and \fIforw\fR, the user will be queried
+before the message is sent.
+If `\-annotate' is
+specified, the replied-to message will be annotated with the
+single line
+
+.ti +.5i
+Replied: \*(<<Date\*(>>.
+
+The command
+\*(lqcomp \-use\*(rq may be used to pick up interrupted editing, as in
+\fIdist\fR and \fIforw\fR; the `\-inplace' switch annotates the message in place,
+so that all folders with links to it will see the annotation.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+^<mh-dir>/draft~^The constructed message file
+^/usr/bin/send~^To send the composed message
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Editor:~^To override the use of /bin/ned as the default editor
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+`+folder' defaults to current
+`msgs' defaults to cur
+`\-editor' defaults to /bin/ned
+`\-noannotate'
+`\-noinplace'
+.Co
+If a `+folder' is specified, it will become the current
+folder, and the current message will be set to the replied-to
+message.
+.sp 2
+.En
+.SC RMF
+.NA
+rmf \- remove folder
+.SY
+rmf \%[+folder] \%[\-help]
+.DE
+\fIRmf\fR removes all of the files (messages) within the specified
+(or default) folder, and then removes the directory (folder).
+If
+there are any files within the folder which are not a part of MH,
+they will \fInot\fR be removed, and an error will be produced.
+If the
+folder is given explicitly or the current folder is a
+subfolder (i.e., a selection list from \fIpick\fR), it will be
+removed without confirmation.
+If no argument is specified and
+the current folder is not a selection-list folder, the
+user will be asked for confirmation.
+
+\fIRmf\fR irreversibly deletes messages that don't have other links,
+so use it with caution.
+
+If the folder being removed is a subfolder, the parent
+folder will become the new current folder, and \fIrmf\fR will
+produce a message telling the user this has happened.
+This
+provides an easy mechanism for selecting a set of messages,
+operating on the list, then removing the list and returning to
+the current folder from which the list was extracted.
+(See the
+example under \fIpick\fR.)
+
+The files that \fIrmf\fR will delete are cur, any file beginning
+with a comma, and files with purely numeric names.
+All others
+will produce error messages.
+
+\fIRmf\fR of a read-only folder will delete the \*(lqcur\-\*(rq entry from the
+profile without affecting the folder itself.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+`+folder' defaults to current, usually with confirmation
+.Co
+\fIRmf\fR will set the current folder to the parent folder if a
+subfolder is removed; or if the current folder is removed,
+it will make \*(lqinbox\*(rq current.
+Otherwise, it doesn't change the
+current folder or message.
+.En
+.SC RMM
+.NA
+rmm \- remove messages
+.SY
+rmm \%[+folder] \%[msgs] \%[\-help]
+.DE
+\fIRmm\fR removes the specified messages by renaming the message
+files with preceding commas.
+(This is the Rand-UNIX backup file
+convention.)
+
+The current message is not changed by \fIrmm\fR, so a \fInext\fR  will
+advance to the next message in the folder as expected.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+`+folder' defaults to current
+`msgs' defaults to cur
+.Co
+If a folder is given, it will become current.
+.En
+.SC SCAN
+.NA
+scan \- produce a one-line-per-message scan listing
+.SY
+scan \%[+folder] \%[msgs] \%[\-f\&f] \%[\-header] \%[\-help]
+\%[\-nof\&f] \%[\-noheader]
+.DE
+\fIScan\fR produces a one-line-per-message listing of the specified
+messages.
+Each \fIscan\fR line contains the message number (name),
+the date, the \*(lqFrom\*(rq field, the \*(lqSubject\*(rq field, and, if room
+allows, some of the body of the message.
+For example:
+
+.nf
+.ta .5i 1.2i 2.6i
+^ #~^^Date~^^  From~^Subject\ \ \ \ \[\*(<<Body]
+^15+~^^7/\05~^^Dcrocker~^nned  \*(<<Last week I asked some of
+^16\ \-~^^7/\05~^^dcrocker~^message id format  \*(<<I recommend
+^18~^^7/\06~^^Obrien~^Re: Exit status from mkdir
+^19~^^7/\07~^^Obrien~^"scan" listing format in MH
+.re
+.fi
+
+The `+' on message 15 indicates that it is the current message.
+The `\-' on message 16 indicates that it has been
+replied to, as indicated by a \*(lqReplied:\*(rq component produced by
+an `\-annotate' switch to the \fIrepl\fR command.
+
+If there is sufficient room left on the \fIscan\fR line after the
+subject, the line will be filled with text from the body,
+preceded by \*(<<.
+\fIScan\fR actually reads each of the specified
+messages and parses them to extract the desired fields.
+During parsing, appropriate error messages will be produced if
+there are format errors in any of the messages.
+
+The `\-header' switch produces a header line prior to the \fIscan\fR
+listing, and the `\-f\&f' switch will cause a form feed to be
+output at the end of the \fIscan\fR listing.
+See Appendix D.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+Defaults:
+`+folder' defaults to current
+`msgs' defaults to all
+`\-nof\&f'
+`\-noheader'
+.Co
+If a folder is given, it will become current.
+The current
+message is unaffected.
+.En
+.SC SEND
+.NA
+send \- send a message
+.SY
+send \%[file] \%[\-draft] \%[\-verbose] \%[\-format] \%[\-msgid]
+\%[\-help]  \%[\-noverbose] \%[\-noformat] \%[\-nomsgid]
+.DE
+\fISend\fR will cause the specified file (default <mh-dir>/draft) to
+be delivered to each of the addresses in the \*(lqTo:\*(rq, \*(lqcc:\*(rq, and \*(lqBcc:\*(rq
+fields of the message.
+If `\-verbose' is specified, \fIsend;\fR
+will monitor the delivery of local and net mail.
+\fISend\fR with no
+argument will query whether the draft is the intended file, whereas
+`\-draft' will suppress this question.
+Once the message has
+been mailed (or queued) successfully, the file will be renamed
+with a leading comma, which allows it to be retreived until the
+next draft message is sent.
+If there are errors in the
+formatting of the message, \fIsend;\fR will abort with a (hopefully)
+helpful error message.
+
+If a \*(lqBcc:\*(rq field is encountered, its addresses will be used for
+delivery, but the \*(lqBcc:\*(rq field itself will be deleted from all
+copies of the outgoing message.
+
+Prior to sending the message, the fields \*(lqFrom:  user\*(rq, and
+\*(lqDate: now\*(rq will be prepended to the message.
+If `\-msgid' is
+specified, then a \*(lqMessage-Id:\*(rq field will also be added to the
+message.
+If the message already contains a \*(lqFrom:\*(rq field, then a
+\*(lqSender: user\*(rq field will be added instead.
+(An already existing
+\*(lqSender:\*(rq field will be deleted from the message.)
+
+If the user doesn't specify `\-noformat', each of the entries in
+the \*(lqTo:\*(rq and \*(lqcc:\*(rq fields will be replaced with \*(lqstandard\*(rq format
+entries.
+This standard format is designed to be usable by all
+of the message handlers on the various systems around the
+ARPANET.
+
+If an \*(lqFcc: folder\*(rq is encountered, the message will be copied
+to the specified folder in the format in which it will appear to any
+receivers of the message.
+That is, it will have the prepended
+fields and field reformatting.
+
+If a \*(lqDistribute-To:\*(rq field is encountered, the message
+is handled as a redistribution message (see \fIdist\fR for
+details), with \*(lqDistribution-Date: now\*(rq and \*(lqDistribution-From: user\*(rq
+added.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+.Pr
+^Path:~^To determine the user's MH directory
+.De
+`file' defaults to draft
+`\-noverbose'
+`\-format'
+`\-nomsgid'
+.Co
+\fISend\fR has no effect on the current message or folder.
+.En
+.SC SHOW
+.NA
+show \- show (list) messages
+.SY
+show \%[+folder] \%[msgs] \%[\-pr] \%[\-nopr] \%[\-draft] \%[\-help]
+\%[\fIl\fR\ or\ \fIpr\fR\ switches]
+.DE
+\fIShow\fR lists each of the specified messages to the standard
+output (typically, the terminal).
+The messages are listed exactly
+as they are, with no reformatting.
+A program called \fIl\fR is
+invoked to do the listing, and any switches not recognized by
+\fIshow\fR are passed along to \fIl\fR.
+
+If no \*(lqmsgs\*(rq are specified, the current message is used.
+If
+more than one message is specified, \fIl\fR will prompt for a
+<return> prior to listing each message.
+
+\fIl\fR will list each message, a page at a time.
+When the end of
+page is reached, \fIl\fR will ring the bell and wait for a <RETURN>
+or <CTRL-D>.
+If a <return> is entered, \fIl\fR will clear the
+screen before listing the next page, whereas <CTRL-D> will not.
+The switches to \fIl\fR are
+`\-p#' to indicate the page length in lines, and `\-w#' to
+indicate the width of the page in characters.
+
+If the standard output is not a terminal, no queries are made,
+and each file is listed with a one-line header and two lines of
+separation.
+
+If `\-pr' is specified, then \fIpr\fR(I) will be invoked rather than
+\fIl\fR, and the switches (other than `\-draft') will be passed
+along.
+\*(lqShow \-draft\*(rq will list the file <mh-dir>/draft if it
+exists.
+.Fi
+^$HOME/\*.mh\(ruprofile~^The user profile
+^/bin/l~^Screen-at-a-time list program
+^/bin/pr~^\fIpr\fR(I)
+.Pr
+^Path:~^To determine the user's MH directory
+.Ps
+^Current-Folder:~^To find the default current folder
+.De
+`+folder' defaults to current
+`msgs' defaults to cur
+`\-nopr'
+.Co
+If a folder is given, it will become the current message.
+The last message
+listed will become the current message.
+.En
+\"
+\"              On to the Appendices
+\"
+.fo ''-%-''
+.he ''''
+.(x
+.sp
+Appendix
+.)x _
+.de $c                          \" Major Heading printer
+.ce
+Appendix \\n+(ch
+.sp 2p
+.ce
+.b "\\s12\\$1\\s0"              \" 12 Point Bold Header
+.(x
+\ \ \ \\n(ch.\\ \\ \\$2
+.)x
+.sp 45p                                \" 45 points or about 1/2 inch
+..
+.++ A
+.bp
+.$c "COMMAND SUMMARY\\**" "Command Summary"
+.(f
+\**All commands accept a \-help switch.
+.)f
+.in 1i
+.na
+.ti .5i
+comp \%[\-editor\ editor] \%[\-form\ formfile] \%[file] \%[\-use]
+\%[\-nouse] \%[\-help]
+
+.ti .5i
+dist \%[+folder] \%[msg] \%[\-form\ formfile] \%[\-editor\ editor]
+\%[\-annotate] \%[\-noannotate]
+\%[\-inplace] \%[\-noinplace]
+\%[\-help]
+
+.ti .5i
+file \%[\-src\ +folder] \%[msgs] \%[\-link] \%[\-preserve] \%+folder\ ...
+\%[\-nolink] \%[\-nopreserve]
+\%[\-file\ file] \%[\-nofile] \%[\-help]
+
+.ti .5i
+folder \%[+folder] \%[msg] \%[\-all] \%[\-fast] \%[\-nofast] \%[\-up] \%[\-down]
+\%[\-header] \%[\-noheader] \%[\-total] \%[\-nototal] \%[\-pack] \%[\-nopack]
+\%[\-help]
+
+.ti .5i
+forw \%[+folder] \%[msgs] \%[\-editor\ editor] \%[\-form\ formfile]
+\%[\-annotate] \%[\-noannotate]
+\%[\-inplace]  \%[\-noinplace]
+\%[\-help]
+
+.ti .5i
+inc \%[+folder] \%[\-audit\ audit-file] \%[\-help]
+
+.ti .5i
+next \%[+folder] \%[\-switches\ for\ \fIl\fR] \%[\-help]
+
+.ta .4i 1.8i
+.nf
+.in .5i
+^pick~^^\0\-cc~^ \%[\-src\ +folder] \%[msgs] \%[\-help] \%[\-scan] \%[\-noscan]
+^^^\0\-date~^   \%[\-show] \%[\-noshow] \%[\-nofile] \%[\-nokeep]
+^^^\0\-from~^
+^^^\s+2\b'\(lt\(bv\(bv\(lk\(bv\(bv\(lb'\s0 \-search~\s+2\b'\(rt\(bv\(bv\(rk\(bv\(bv\(rb'\s0^ pattern
+^^^\0\-subject~^
+^^^\0\-to~^ \%[\-file \%[\-preserve] \%[\-link] \%+folder\ ... \%[\-nopreserve] \%[\-nolink] ]
+^^^\0\-\-component~^ \%[\-keep \%[\-stay] \%[\-nostay] \%[+folder\ ...]\ ]
+.fi
+.re
+
+.ti .5i
+prev \%[+folder] \%[\-switches\ for\ \fIl\fR] \%[\-help]
+
+.ti .5i
+prompter \%[\-erase\ chr] \%[\-kill\ chr] \%[\-help]
+
+.ti .5i
+repl \%[+folder] \%[msg] \%[\-editor\ editor] \%[\-inplace] \%[\-annotate]
+\%[\-help] \%[\-noinplace]
+\%[\-noannotate]
+
+.ti .5i
+rmf \%[+folder] \%[\-help]
+
+.ti .5i
+rmm \%[+folder] \%[msgs] \%[\-help]
+
+.ti .5i
+scan \%[+folder] \%[msgs] \%[\-f\&f] \%[\-header] \%[\-help]
+\%[\-nof\&f] \%[\-noheader]
+
+.ti .5i
+send \%[file] \%[\-draft] \%[\-verbose] \%[\-format] \%[\-msgid]
+\%[\-help]  \%[\-noverbose] \%[\-noformat] \%[\-nomsgid]
+
+.ti .5i
+show \%[+folder] \%[msgs] \%[\-pr] \%[\-nopr] \%[\-draft] \%[\-help]
+\%[\fIl\fR\ or\ \fIpr\fR\ switches]
+.ad
+.in 0
+\".+c "MESSAGE FORMAT" "Message Format"
+.if t \{
+.ll 32P
+.lt 32P
+\}
+.bp
+.$c "MESSAGE FORMAT" "Message Format"
+.pp
+This section paraphrases the format of ARPANET text messages
+given in Ref. 6.
+
+.lp
+ASSUMPTIONS
+.np
+Messages
+are expected to consist of lines of text.
+Graphics and binary data are not handled.
+.np
+No data compression is accepted.
+All text is clear
+ASCII 7-bit data.
+
+.lp
+LAYOUT
+.lp
+A general \*(lqmemo\*(rq framework is used.
+A message consists of a
+block of information in a rigid format, followed by general
+text with no specified format.
+The rigidly formatted  first
+part of a message is  called the header, and the free-format
+portion is called the body.
+The header must always
+exist, but the body is optional.
+
+.lp
+THE HEADER
+.lp
+Each header item can be viewed as a single logical line of ASCII
+characters.
+If the text of a header item extends across several
+real lines, the continuation lines are indicated by leading
+spaces or tabs.
+.lp
+Each header item is called a component and is composed of a
+keyword or name, along with associated text.
+The keyword begins at the
+left margin, may contain spaces or tabs, may not exceed 63
+characters, and is terminated by a colon (:).
+Certain
+components (as identified by their keywords) must follow rigidly
+defined formats in their text portions.
+.lp
+The text for most formatted components (e.g., \*(lqDate:\*(rq and \*(lqMessage-Id:\*(rq)
+is produced automatically.
+The only ones entered by the
+user are address fields such as \*(lqTo:\*(rq, \*(lqcc:\*(rq, etc.
+ARPA addresses
+are assigned mailbox names and host computer specifications.
+The
+rough format is \*(lqmailbox at host\*(rq, such as \*(lqBorden at Rand-Unix\*(rq.
+Multiple addresses are separated by commas.
+A missing host is
+assumed to be the local host.
+
+.ne 10
+.lp
+THE BODY
+.lp
+A blank line signals that all following text up to the end of the file
+is the body.
+(A blank line is defined as a pair of
+<end-of-line> characters with \fIno\fR characters in between.)
+No formatting is expected or enforced within the body.
+.lp
+Within MH, a line consisting of dashes is accepted
+as the header delimiter.
+This is a cosmetic feature applying
+only to locally composed mail.
+.bp
+.$c "MESSAGE NAME BNF" "Message Name BNF"
+
+.ta 1.2i 1.8i 3.2i
+.nf
+.in 1i
+^msgs~^^:=~^^msgspec~^|
+^^^^msgs msgspec
+
+^msgspec~^^:=~^^msg~^|
+^^^^^msg-range~^|
+^^^^msg-sequence
+
+^msg~^^:=~^^msg-name~^|
+^^^^<number>^
+
+^msg-name~^^:=~^^\*(lqfirst\*(rq~^|
+^^^^^\*(lqlast\*(rq~^|
+^^^^^\*(lqcur\*(rq~^|
+^^^^^\*(lq\*.\*(rq~^|
+^^^^^\*(lqnext\*(rq~^|
+^^^^\*(lqprev\*(rq
+
+^msg-range~^^:=~^^msg\*(lq-\*(rqmsg~^|
+^^^^^\*(lqall\*(rq
+
+^msg-sequence~^^:=~^msg\*(lq:\*(rqsigned-number
+
+^signed-number~^^:=~^^\*(lq+\*(rq<number>~^|
+^^^^^\*(lq\--\*(rq<number>~^|
+^^^^<number>
+.re \" Reset Tabs
+.fi
+.sp
+.pp
+Where <number> is a decimal number in the range 1 to 999.
+.pp
+Msg-range specifies all of the messages in the given range
+and must not be empty.
+.pp
+Msg-sequence specifies up to <number> of messages, beginning
+with \*(lqmsg\*(rq (in the case of first, cur, next, or <number>),
+or ending with \*(lqmsg\*(rq (in the case of prev or last).
++<number> forces \*(lqstarting with msg\*(rq, and \-<number> forces
+\*(lqending with number\*(rq.
+In all cases, \*(lqmsg\*(rq must exist.
+.bp
+.$c "EXAMPLE OF SHELL COMMANDS"  "Example of Shell Commands"
+.pp
+UNIX commands may be mixed with MH commands to obtain additional
+functions.
+These may be prepared as files (known as
+shell command files or
+shell scripts).
+The following example is a useful function that
+illustrate the possibilities.
+Other functions, such as copying,
+deleting, renaming, etc., can be achieved in a similar fashion.
+
+HARDCOPY
+.pp
+The command:
+
+.ti +.5i
+(scan\0\-f\&f\0\-header;\0show\0all\0\-pr\0\-f)\0|\0print
+
+produces a scan listing of the current folder, followed by a
+form feed, followed by a formatted listing of all messages
+in the folder, one per page.
+Omitting \*(lq\-pr\0\-f\*(rq will cause the
+messages to be concatenated, separated by a one-line header
+and two blank lines.
+.pp
+You can create variations on this theme, using \fIpick\fR.
+.re
+.fi
+.in 0
+.bp
+.ce
+.b \\s12REFERENCES\\s0
+.(x
+.sp
+REFERENCES
+.)x
+.sp 3
+.in .4i
+.ti 0
+1.  Crocker, D. H., J. J. Vittal, K. T. Pogran, and D. A. Henderson, Jr.,
+\*(lqStandard for the Format of ARPA Network Test Messages,\*(rq \fIArpanet Request
+for Comments\fR, No. 733, Network Information Center 41952, Augmentation
+Research Center, Stanford Research Institute,
+November 1977.
+
+.ti 0
+2.  Thompson, K., and D. M. Ritchie, \*(lqThe UNIX Time-sharing System,\*(rq
+\fICommunications of the ACM\fR, Vol. 17, July 1974, pp. 365-375.
+
+.ti 0
+3.  McCauley, E. J., and P. J. Drongowski, \*(lqKSOS\-The Design of a Secure
+Operating System,\*(rq \fIAFIPS Conference Proceedings\fR,
+National Computer Conference,
+Vol. 48, 1979, pp. 345-353.
+
+.ti 0
+4.  Crocker, David H., \fIFramework and Functions of the \*(lqMS\*(rq Personal
+Message System\fR, The Rand Corporation, R-2134-ARPA, December 1977.
+
+.ti 0
+5.  Thompson, K., and D. M. Ritchie, \fIUNIX Programmer's Manual\fR, 6th ed.,
+Western Electric Company, May 1975 (available only to UNIX licensees).
+
+.ti 0
+6.  Bilofsky, Walter, \fIThe CRT Text Editor NED\-Introduction and
+Reference Manual\fR, The Rand Corporation, R-2176-ARPA, December 1977.
+.bp 3
+.de $c
+.ce
+.b "\\s12\\$1\\s0"   \" 12 Point Bold Header
+.(x y
+.sp
+\\$1
+.)x
+.sp 3
+..
+.pn 3
+.++ P
+.fo ''''
+.he ''-%-''
+.+c PREFACE
+.pp
+This report describes a system for dealing with messages transmitted on a
+computer.  Such messages might originate with other users of the same
+computer or might come from an outside source through a network to which the user's
+computer is connected.  Such computer-based message systems are
+becoming increasingly widely used, both within and outside the Department
+of Defense.
+.pp
+The message handling system MH was developed for two reasons.
+One was to investigate some
+research ideas concerning how a message system might take advantage of
+the architecture of the UNIX time-sharing operating system for
+Digital Equipment Corporation PDP-11 and VAX computers, and the special
+features of UNIX's command-level interface with the user (the
+\*(lqshell\*(rq).  The other reason was to provide a better and more
+adaptable base than that of conventional designs
+on which to build a command and control message system.
+The effort has succeeded in both
+regards, although this report mainly describes the message system itself
+and how it fits in with UNIX.  The main research results are being
+described and analyzed in a forthcoming Rand report.
+The system is currently being used as part
+of a tactical command and control \*(lqlaboratory,\*(rq which is also being described
+in a separate report.
+.pp
+The present report should be of interest to three groups of readers.  First,
+it is a complete reference manual for the users of MH (although
+users outside of Rand must take into
+account differences from the local Rand operating system).  Second, it should be
+of interest to those who have a general knowledge of computer-based
+message systems, both in civilian and military applications.  Finally,
+it should be of interest to those who build large subsystems that
+interface with users, since it illustrates a new approach to such
+interfaces.
+.pp
+The MH system was developed by the first
+author, using an approach suggested by the other two authors.
+Valuable assistance was provided by Phyllis Kantar in the later
+stages of the system's implementation.
+Several colleagues
+contributed to the ideas included in this system, particularly
+Robert Anderson and David Crocker.
+In addition, valuable experience
+in message systems, and a valuable source of ideas, was available
+to us in the form of a previous message system for UNIX called
+MS, designed at Rand by David Crocker.
+.pp
+This report was prepared as part of the Rand project entitled \*(lqData
+Automation Research\*(rq, sponsored by Project AIR FORCE.
+.pn 5
+.+c SUMMARY
+.pp
+Electronic communication of text messages is becoming
+commonplace.  Computer-based message systems\-software
+packages that provide tools for dealing with messages\-are used in many
+contexts.  In particular, message systems are becoming
+increasingly important in command and control and intelligence
+applications.
+.pp
+This report describes a message handling system called MH.
+This system provides the user
+with tools to compose, send, receive, store, retrieve, forward, and
+reply to messages.  MH has been built on the UNIX time-sharing system,
+a popular operating system developed for the DEC PDP-11 and VAX classes of
+computers.
+.pp
+A complete description of MH is given for users of
+the system.  For those who do not intend to use the system, this description
+gives a general idea of what a message system is like.  The system involves
+some new ideas about how large subsystems can be constructed.  These design
+concepts and a comparison of MH with other message systems
+will be published in a forthcoming Rand report.
+.pp
+The interesting and unusual features of MH include the
+following:  The user command interface to MH is the UNIX \*(lqshell\*(rq
+(the standard UNIX command interpreter).  Each separable
+component of message handling, such as message composition or
+message display, is a separate command.  Each program is driven from
+and updates a private user environment, which is stored as a file
+between program invocations.  This private environment also contains
+information to \*(lqcustom tailor\*(rq MH to the individual's tastes.  MH
+stores each message as a separate file under UNIX, and it utilizes the
+tree-structured UNIX file system to organize groups of files within
+separate directories or \*(lqfolders.\*(rq  All of the UNIX facilities
+for dealing with files and directories, such as
+renaming, copying, deleting, cataloging, off-line printing, etc., are
+applicable to messages and directories of messages (folders).  Thus,
+important capabilities needed in a message system are available in MH without
+the need (often seen in other message systems) for code that
+duplicates the facilities of the supporting operating system.
+It also allows users familiar with the shell to use MH with minimal
+effort.
+.he ''''
+.fo ''''
+.bp
+.ce
+.b \\s12CONTENTS\\s0
+.sp 3
+.xp y
+.xp x
+
+.bp     \" Spare numbers for cut and paste work!
+.ft B
+
+1       1       1       1       1       1       1       1
+
+1       1       1       1       1       1       1       1
+
+1       1       1       1       1       1       1       1
+
+1       1       1       1       1       1       1       1
+
+2       2       2       2       2       2       2       2
+
+2       2       2       2       2       2       2       2
+
+2       2       2       2       2       2       2       2
+
+3       3       3       3       3       3       3       3
+
+3       3       3       3       3       3       3       3
diff --git a/docs/historical/mh-nov-1983/doc/titlepage b/docs/historical/mh-nov-1983/doc/titlepage
new file mode 100644 (file)
index 0000000..427f156
--- /dev/null
@@ -0,0 +1,23 @@
+.(l C
+.sp 1i
+.sz +8
+.b
+MH
+.sp 0.4i
+.sz -4
+.r
+A Mail Handling System
+.sp 0.2i
+for \s-1UNIX\s+1
+.sz -4
+.sp 1i
+October, 1979
+
+Bruce Borden
+.sp 1i
+The Rand Corporation
+1700 Main Street
+Santa Monica, CA 90406
+
+(213) 399-0568 x 7463
+.)l
diff --git a/docs/historical/mh-nov-1983/man/Makefile b/docs/historical/mh-nov-1983/man/Makefile
new file mode 100644 (file)
index 0000000..b95bc89
--- /dev/null
@@ -0,0 +1,39 @@
+DEST         = $(DESTDIR)/usr/man/mann
+
+MAKEFILE      = Makefile
+
+PRINT        = vtroff
+
+SRCS         = comp.1 \
+               dist.1 \
+               file.1 \
+               folder.1 \
+               forw.1 \
+               inc.1 \
+               next.1 \
+               pick.1 \
+               prev.1 \
+               prompter.1 \
+               repl.1 \
+               rmf.1 \
+               rmm.1 \
+               scan.1 \
+               send.1 \
+               show.1
+
+SUFFIX       = .1:s
+
+all:;
+
+clean:;
+
+depend:;       @mkmf -f $(MAKEFILE)
+
+install:;      @echo Installing $(SRCS) in $(DEST)
+               @for i in $(SRCS); do cp $$i $(DEST)/`basename $$i .1`.n; done
+
+print:         $(SRCS)
+               @$(PRINT) -man $?
+               @touch print
+
+update:;
diff --git a/docs/historical/mh-nov-1983/man/comp.1 b/docs/historical/mh-nov-1983/man/comp.1
new file mode 100644 (file)
index 0000000..87c392e
--- /dev/null
@@ -0,0 +1,82 @@
+.TH COMP 1 "3 August 1983"
+.UC 4
+.SH NAME
+comp \- compose a message
+.SH SYNOPSIS
+.B comp
+[ \-editor editor ] [ \-form formfile ] [ file ] [ \-use ]
+[ \-nouse ] [ \-help ]
+.SH DESCRIPTION
+\fIComp\fP is used to create a new message to be mailed.
+If
+\fIfile\fP is not specified, the file named \*(lqdraft\*(rq in the user's MH
+directory will be used.
+\fIComp\fR copies a message form to
+the file being composed and then invokes an editor on the
+file.
+The default editor is /bin/ned, which may be overridden with
+the `\-editor' switch or with a profile entry \*(lqEditor:\*(rq.
+The default message form contains the following elements:
+.nf
+
+     To:
+     cc:
+     Subject:
+     ----------
+
+.fi
+If the file named \*(lqcomponents\*(rq exists in the user's MH directory,
+it will be used instead of this form.
+If `\-form formfile' is specified, the specified formfile (from the MH
+directory) will be used as the skeleton.
+The line of dashes
+or a blank line must be left between the header and the
+body of the message for the message to be identified properly when it is
+sent (see
+.IR send (1)).
+The switch `\-use' directs \fIcomp\fR to
+continue editing an already started message.
+That is, if a
+\fIcomp\fR (or \fIdist\fR, \fIrepl\fR, or \fIforw\fR) is terminated without
+sending the message, the message can be edited again via
+\*(lqcomp \-use\*(rq.
+.PP
+If the specified file (or draft) already exists, \fIcomp\fR will ask
+if you want to delete it before continuing.
+A reply of \fBNo\fR will abort the
+\fIcomp\fR, \fByes\fR will replace the existing draft with a blank
+skeleton, \fBlist\fR will display the draft, and \fBuse\fR will use it
+for further composition.
+.PP
+Upon exiting from the editor, \fIcomp\fR will ask \*(lqWhat now?\*(rq.
+The valid
+responses are \fBlist\fR, to list the draft on the terminal; \fBquit\fR, to
+terminate the session and preserve the draft; \fBquit delete\fR, to terminate,
+then delete the draft; \fBsend\fR, to send the message; \fBsend verbose\fR, to
+cause the delivery process to be monitored; \fBedit <editor>\fR, to invoke
+<editor> for further editing; and \fBedit\fR, to re-edit using the
+same editor that was used on the preceding round unless a profile
+entry \*(lq<lasteditor>\-next: <editor>\*(rq names an alternative editor.
+.PP
+\fIComp\fR does not affect either the current folder or the current message.
+.SH FILES
+.nf
+.ta \w'or <mh-dir>/components    'u
+/etc/mh/components     The message skeleton
+or <mh-dir>/components Rather than the standard skeleton
+$HOME/\*.mh_profile    The user profile
+<mh-dir>/draft The default message file
+/usr/new/send  To send the composed message
+.fi
+.SH "PROFILE COMPONENTS"
+.nf
+.ta \w'<lasteditor>\-next:    'u
+Path:  To determine the user's MH directory
+Editor:        To override the use of /bin/ned as the default editor
+<lasteditor>\-next:    editor to be used after exit from <lasteditor>
+.SH DEFAULTS
+.nf
+`file' defaults to draft
+`\-editor' defaults to /bin/ned
+`\-nouse'
+.fi
diff --git a/docs/historical/mh-nov-1983/man/dist.1 b/docs/historical/mh-nov-1983/man/dist.1
new file mode 100644 (file)
index 0000000..2b0abf4
--- /dev/null
@@ -0,0 +1,83 @@
+.TH DIST 1 "3 August 1983"
+.UC 4
+.SH NAME
+dist \- redistribute a message to additional addresses
+.SH SYNOPSIS
+.B dist
+[ +folder ] [ msg ] [ \-form formfile ] [ \-editor editor ]
+[ \-annotate ] [ \-noannotate ]
+[ \-inplace ] [ \-noinplace ] [ \-help ]
+.SH DESCRIPTION
+\fIDist\fR is similar to \fIforw\fR.
+It prepares the specified
+message for redistribution to addresses that (presumably) are
+not on the original address list.
+The file \*(lqdistcomps\*(rq in the
+user's MH directory, or a standard form, or the file specified by
+`\-form formfile' will be used as the blank components file to
+be prepended to the message being distributed.
+The standard form
+has the components \*(lqDistribute-to:\*(rq and \*(lqDistribute-cc:\*(rq.
+When
+the message is sent, \*(lqDistribution-Date:\0date\*(rq,
+\*(lqDistribution-From:\0name\*(rq, and
+\*(lqDistribution-Id:\0id\*(rq (if `\-msgid' is
+specified to \fIsend\fR;) will be prepended to the outgoing message.
+Only those addresses in \*(lqDistribute-To\*(rq, \*(lqDistribute-cc\*(rq, and
+\*(lqDistribute-Bcc\*(rq will be sent.
+Also, a \*(lqDistribute-Fcc:\0folder\*(rq
+will be honored (see \fIsend;\fR).
+.PP
+\fISend\fR recognizes a message as a redistribution message by the
+existence of the field \*(lqDistribute-To:\*(rq, so don't try to
+redistribute a message with only a \*(lqDistribute-cc:\*(rq.
+.PP
+If the `\-annotate' switch is given, each message being
+distributed will be annotated with the lines:
+.nf
+
+     Distributed:\0\*(<<date\*(>>
+     Distributed:\0Distribute-to: names
+
+.fi
+where each \*(lqto\*(rq list contains as many lines as required.
+This annotation
+will be done only if the message is sent directly from \fIdist\fR.
+If the
+message is not sent immediately from \fIdist\fR (i.e., if it is sent later
+via \fIsend;\fR),
+\*(lqcomp \-use\*(rq may be used to re-edit and send the constructed message,
+but the annotations won't take place.
+The '\-inplace' switch causes annotation to
+be done in place in order to preserve links to the annotated message.
+.PP
+See \fIcomp\fR for a description of the `\-editor' switch and for options
+upon exiting from the editor.
+.PP
+If a +folder is specified, it will become the current
+folder, and the current message will be set to the message
+being redistributed.
+.SH FILES
+.nf
+.ta \w'or <mh-dir>/components    'u
+/etc/mh/components     The message skeleton
+or <mh-dir>/components Rather than the standard skeleton
+$HOME/\*.mh\(ruprofile The user profile
+<mh-dir>/draft The default message file
+/usr/bin/send  To send the composed message
+.fi
+.SH "PROFILE COMPONENTS"
+.nf
+.ta \w'<lasteditor>\-next:     'u
+Path:  To determine the user's MH directory
+Editor:        To override the use of /bin/ned as the default editor
+<lasteditor>\-next:    editor to be used after exit from <lasteditor>
+.fi
+.SH DEFAULTS
+.nf
+`+folder' defaults to the current folder
+`msg' defaults to cur
+`\-editor' defaults to /bin/ned
+`\-noannotate'
+`\-noinplace'
+.fi
diff --git a/docs/historical/mh-nov-1983/man/file.1 b/docs/historical/mh-nov-1983/man/file.1
new file mode 100644 (file)
index 0000000..74c7441
--- /dev/null
@@ -0,0 +1,91 @@
+.TH FILE 1 "3 August 1983"
+.UC 4
+.SH NAME
+file \- file message(s) in (an)other folder(s)
+.SH SYNOPSIS
+file [ \-src +folder ] [ msgs ] [ \-link ] [ \-preserve ] +folder ...
+[ \-nolink] [ \-nopreserve ]
+[ \-file file ] [ \-nofile ] [ \-help ]
+.SH DESCRIPTION
+\fIFile\fR moves (\fImv\fR(1)) or links (\fIln\fR(1)) messages from a
+source folder into one or more destination folders.
+If you think
+of a message as a sheet of paper, this operation is not
+unlike filing the sheet of paper (or copies) in file cabinet
+folders.
+When a message is filed, it is linked into the
+destination folder(s) if possible, and is copied otherwise.
+As long
+as the destination folders are all on the same file system, multiple filing
+causes little storage overhead.
+This facility provides a good way to cross-file or multiply-index
+messages.
+For example, if a message is received from Jones about
+the ARPA Map Project, the command
+.nf
+
+     file\0cur\0+jones\0+Map
+
+.fi
+would allow the message to be found in either of the two
+folders `jones' or `Map'.
+.PP
+The option `\-file file' directs \fIfile\fR to use the specified
+file as the source message to be filed, rather than a message from
+a folder.
+.PP
+If a destination folder doesn't exist, \fIfile\fR will ask if you
+want to create one.
+A negative response will abort the file
+operation.
+.PP
+`\-link' preserves the source folder copy of the message
+(i.e., it does a \fIln\fR(1) rather than a \fImv\fR(1)), whereas,
+`\-nolink' deletes the \*(lqfiled\*(rq messages from the source
+folder.
+Normally, when a message is filed, it is assigned the
+next highest number available in each of the destination folders.
+Use of the `\-preserve' switch will override this message
+\*(lqrenaming\*(rq, but name conflicts may occur, so
+use this switch cautiously.
+(See \fIpick\fR for more details on
+message numbering.)
+.PP
+If `\-link' is not specified (or `\-nolink' is specified),
+the filed messages will be removed (
+.IR unlink (2))
+from the source folder.
+.PP
+If `\-src +folder' is given, it will become the
+current folder for future MH commands.
+If neither `\-link' nor
+`all' are specified, the current message in the source
+folder will be set to the last message specified; otherwise, the
+current message won't be changed.
+.SH FILES
+.nf
+.ta \w'$HOME/\*.mh\(ruprofile    'u
+$HOME/\*.mh\(ruprofile The user profile
+.fi
+.SH "PROFILE COMPONENTS"
+.nf
+.ta \w'Folder\-Protect:    'u
+Path:  To determine the user's MH directory
+Current-Folder:        To find the default current folder
+Folder\-Protect:       To set mode when creating a new folder
+.fi
+.SH DEFAULTS
+.nf
+`\-src +folder' defaults to the current folder
+`msgs' defaults to cur
+`\-nolink'
+`\-nopreserve'
+`\-nofile'
+.fi
+.SH CONTEXT
+If `\-src +folder' is given, it will become the
+current folder for future MH commands.
+If neither `\-link' nor
+`all' are specified, the current message in the source
+folder will be set to the last message specified; otherwise, the
+current message won't be changed.
diff --git a/docs/historical/mh-nov-1983/man/folder.1 b/docs/historical/mh-nov-1983/man/folder.1
new file mode 100644 (file)
index 0000000..063faf9
--- /dev/null
@@ -0,0 +1,105 @@
+.TH FOLDER 1 "3 August 1983"
+.UC 4
+.SH NAME
+folder \- set/list current folder/message
+.SH SYNOPSIS
+.B folder
+[ +folder ] [ msg ] [ \-all ] [ \-fast ] [ \-nofast ] [ \-up ] [ \-down ]
+[ \-header ] [ \-noheader ] [ \-total ] [ \-nototal ] [ \-pack ] [ \-nopack ]
+[ \-help ]
+.PP
+folders  <equivalent to 'folder \-all'>
+.SH DESCRIPTION
+Since the MH environment is the shell, it is easy to lose
+track of the current folder from day to day.
+\fIFolder\fR will
+list the current folder, the number of messages in it, the
+range of the messages (low-high), and the current message within
+the folder, and will flag a selection list or extra files if they
+exist.
+An example of the output is:
+.nf
+
+      inbox+ has 16 messages ( 3\- 22); cur= 5.
+
+.fi
+If a `+folder' and/or `msg' are specified, they will
+become the current folder and/or message.
+An `\-all' switch
+will produce a line for each folder in the user's MH directory,
+sorted alphabetically.
+These folders are preceded by the read-only
+folders, which occur as \*.mh\(ruprofile \*(lqcur\-\*(rq entries.
+For example,
+.nf
+
+.fc ^ ~
+.ta 1.5i 2.1i 2.7i 3.5i
+^~Folder\ \ ^^~#\ of\ ^^messages~^^(~\ range\~ );\ ^cur msg (other files)
+^~/fsd/rs/m/tacc\ \ ^^has~35\ ^^messages~^^(~1\-\035);\ ^cur=\ 23.
+^~/rnd/phyl/Mail/EP\ \ ^^has~82\ ^^messages~^^(~1\-108);\ ^cur=\ 82.
+^~f\&f\ \ ^^has~4\ ^^messages~^^(~1\-\0\04);\ ^cur=\ \01.
+^~inbox+\ ^^has~16\ ^^messages~^^(~3\-\022);\ ^cur=\ \05.
+^~mh\ \ ^^has~76\ ^^messages~^^(~1\-\076);\ ^cur=\ 70.
+^~notes\ \ ^^has~2\ ^^messages~^^(~1\-\0\02);\ ^cur=\ \01.
+^~ucom\ \ ^^has~124\ ^^messages~^^(~1\-124);\ ^cur=\ \06; (select).
+
+^^^~TOTAL=\0339\ ^messages\0in\0\07\0Folders.
+.re
+.fi
+.PP
+The \*(lq+\*(rq after inbox indicates that it is the current folder.
+The \*(lq(select)\*(rq indicates that the folder ucom has a selection
+list produced by \fIpick\fR.
+If \*(lqothers\*(rq had appeared in parentheses at
+the right of a line, it would indicate that there are files in
+the folder directory that don't belong under the MH file naming
+scheme.
+.PP
+The header is output if either an `\-all' or a `\-header' switch
+is specified; it is suppressed by `\-noheader'.
+Also, if \fIfolder\fR
+is invoked by a name ending with \*(lqs\*(rq (e.g., \fIfolders\fR),
+`\-all' is assumed.
+A `\-total' switch will produce only the
+summary line.
+.PP
+If `\-fast' is given, only the folder name (or names in the
+case of `\-all') will be listed.
+(This is faster because the
+folders need not be read.)
+.PP
+The switches `\-up' and `\-down' change the folder to be the
+one above or below the current folder.
+That is, \*(lqfolder \-down\*(rq
+will set the folder to \*(lq<current\-folder>/select\*(rq, and if the
+current folder is a selection-list folder, \*(lqfolder \-up\*(rq will
+set the current folder to the parent of the selection-list.
+(See \fIpick\fR for details on selection-lists.)
+.PP
+The `\-pack' switch will compress the message names in a folder, removing
+holes in message numbering.
+.SH FILES
+.nf
+.ta \w'$HOME/\*.mh\(ruprofile    'u
+$HOME/\*.mh\(ruprofile The user profile
+/bin/ls        To fast-list the folders
+.fi
+.SH "PROFILE COMPONENTS"
+.nf
+.ta \w'Current-Folder:    'u
+Path:  To determine the user's MH directory
+Current-Folder:        To find the default current folder
+.fi
+.SH DEFAULTS
+.nf
+`+folder' defaults to the current folder
+`msg' defaults to none
+`\-nofast'
+`\-noheader'
+`\-nototal'
+`\-nopack'
+.fi
+.SH CONTEXT
+If `+folder' and/or `msg' are given, they will become the
+current folder and/or message.
diff --git a/docs/historical/mh-nov-1983/man/forw.1 b/docs/historical/mh-nov-1983/man/forw.1
new file mode 100644 (file)
index 0000000..ed87327
--- /dev/null
@@ -0,0 +1,68 @@
+.TH FORW 1 "3 August 1983"
+.UC 4
+.SH NAME
+forw \- forward messages
+.SH SYNOPSIS
+.B forw
+[ +folder ] [ msgs ] [ \-editor editor ] [ \-form formfile ]
+[ \-annotate ] [ \-noannotate ]
+[ \-inplace ]  [ \-noinplace ] [ \-help ]
+.SH DESCRIPTION
+\fIForw\fR may be used to prepare a message containing other
+messages.
+It constructs the new message from the components file
+or `\-form formfile' (see
+.IR comp (1)),
+with a body composed of the message(s) to be forwarded.
+An editor is invoked as in \fIcomp\fR,
+and after editing is complete, the user is prompted before the message
+is sent.
+.PP
+If the `\-annotate' switch is given, each message being
+forwarded will be annotated with the lines
+.nf
+
+     Forwarded: \*(<<date\*(>>
+     Forwarded: To: names
+     Forwarded: cc: names
+
+.fi
+where each \*(lqTo:\*(rq and \*(lqcc:\*(rq list contains as many lines as required.
+This annotation will be done only if the message is sent directly
+from \fIforw\fR.
+If the message is not sent immediately from \fIforw\fR,
+\*(lqcomp \-use\*(rq may be used in a later session to re-edit and send
+the constructed message, but the annotations won't take place.
+The `\-inplace' switch permits annotating a message in place in
+order to preserve its links.
+.PP
+See \fIcomp\fR for a description of the `\-editor' switch.
+.SH FILES
+.nf
+.ta \w'or <mh-dir>/components    'u
+/etc/mh/components     The message skeleton
+or <mh-dir>/components Rather than the standard skeleton
+$HOME/\*.mh\(ruprofile The user profile
+<mh-dir>/draft The default message file
+/usr/bin/send  To send the composed message
+.fi
+.SH "PROFILE COMPONENTS"
+.nf
+.ta \w'<lasteditor>\-next:    'u
+Path:  To determine the user's MH directory
+Editor:        To override the use of /bin/ned as the default editor
+Current-Folder:        To find the default current folder
+<lasteditor>\-next:    editor to be used after exit from <lasteditor>
+.fi
+.SH DEFAULTS
+.nf
+`+folder' defaults to the current folder
+`msgs' defaults to cur
+`\-editor' defaults to /bin/ned
+`\-noannotate'
+`\-noinplace'
+.fi
+.SH CONTEXT
+If a +folder is specified, it will become
+the current folder, and the current message will be set to
+the first message being forwarded.
diff --git a/docs/historical/mh-nov-1983/man/inc.1 b/docs/historical/mh-nov-1983/man/inc.1
new file mode 100644 (file)
index 0000000..48238b4
--- /dev/null
@@ -0,0 +1,84 @@
+.TH INC 1 "3 August 1983"
+.UC 4
+.SH NAME
+inc \- incorporate new mail
+.SH SYNOPSIS
+.B inc
+[ +folder ] [ \-audit audit-file ] [ \-help ]
+.SH DESCRIPTION
+\fIInc\fR incorporates mail from the user's incoming mail drop
+(\*.mail) into an MH folder.
+If `+folder' isn't specified,
+the folder named \*(lqinbox\*(rq in the user's MH directory will be used.
+The
+new messages being incorporated are assigned numbers starting
+with the next highest number in the folder.
+If the specified (or
+default) folder doesn't exist, the user will be queried prior to
+its creation.
+As the messages are processed, a \fIscan\fR  listing
+of the new mail is produced.
+.PP
+If the user's profile contains a \*(lqMsg\-Protect: nnn\*(rq entry, it
+will be used as the protection on the newly created messages,
+otherwise the MH default of 664 will be used.
+During all
+operations on messages, this initially assigned protection will
+be preserved for each message, so \fIchmod\fR(I) may be used to set a
+protection on an individual message, and its protection will be
+preserved thereafter.
+.PP
+If the switch `\-audit audit-file' is specified (usually as a
+default switch in the profile), then \fIinc\fR will append a header
+line and a line per message to the end of the specified
+audit-file with the format:
+.nf
+
+.ti 1i
+\*(<<inc\*(>> date
+.ti 1.5i
+<scan line for first message>
+.ti 1.5i
+<scan line for second message>
+.ti 2.5i
+<etc.>
+
+.fi
+This is useful for keeping track of volume and source of incoming
+mail.
+Eventually, \fIrepl\fR, \fIforw\fR, \fIcomp\fR, and \fIdist\fR may also
+produce audits to this (or another) file, perhaps with
+\*(lqMessage-Id:\*(rq information to keep an exact correspondence history.
+\*(lqAudit-file\*(rq will be in the user's MH directory unless a full
+path is specified.
+.PP
+\fIInc\fR will incorporate even illegally formatted messages into the
+user's MH folder, inserting a blank line prior to the offending
+component and printing a comment identifying the bad message.
+.PP
+In all cases, the \*.mail file will be zeroed.
+.SH FILES
+.nf
+.ta \w'<mh-dir>/audit-file    'u
+$HOME/\*.mh\(ruprofile The user profile
+$HOME/\*.mail  The user's mail drop
+<mh-dir>/audit-file    Audit trace file (optional)
+.fi
+.SH "PROFILE COMPONENTS"
+.nf
+.ta \w'Folder\-Protect:           'u
+Path:  To determine the user's MH directory
+Folder\-Protect:       For protection on new folders
+Msg\-Protect:  For protection on new messages
+.fi
+.SH DEFAULTS
+.nf
+`+folder' defaults to \*(lqinbox\*(rq
+.fi
+.SH CONTEXT
+The folder into which the message is
+being incorporated will become the
+current folder, and the first message incorporated will be the
+current message.
+This leaves the context ready for a \fIshow\fR
+of the first new message.
diff --git a/docs/historical/mh-nov-1983/man/next.1 b/docs/historical/mh-nov-1983/man/next.1
new file mode 100644 (file)
index 0000000..9531180
--- /dev/null
@@ -0,0 +1,29 @@
+.TH NEXT 1 "3 August 1983"
+.UC 4
+.SH NAME
+next \- show the next message
+.SH SYNOPSIS
+.B next
+[ +folder ] [ \-switches for \fIl\fR ] [ \-help ]
+.SH DESCRIPTION
+\fINext\fR performs a \fIshow\fR on the next message in the
+specified (or current) folder.
+Like \fIshow\fR, it passes any
+switches on to the program \fIl\fR, which is called to list the
+message.
+This command is exactly equivalent to \*(lqshow next\*(rq.
+.SH FILES
+.nf
+.ta \w'$HOME/\*.mh\(ruprofile   'u
+$HOME/\*.mh\(ruprofile The user profile
+.fi
+.SH "PROFILE COMPONENTS"
+.nf
+.ta \w'Current-Folder:   'u
+Path:  To determine the user's MH directory
+Current-Folder:        To find the default current folder
+.fi
+.SH CONTEXT
+If a folder is specified, it will become the current folder, and the
+message that is shown (i.e., the next message in sequence)
+will become the current message.
diff --git a/docs/historical/mh-nov-1983/man/pick.1 b/docs/historical/mh-nov-1983/man/pick.1
new file mode 100644 (file)
index 0000000..bdd15e1
--- /dev/null
@@ -0,0 +1,185 @@
+.TH PICK 1 "3 August 1983"
+.UC 4
+.SH NAME
+pick \- select messages by content
+.SH SYNOPSIS
+.fc ^ ~
+.ta .4i 1.8i
+.nf
+.in .5i
+^pick~^^\0\-cc~^ \%[\-src\ +folder] \%[msgs] \%[\-help] \%[\-scan] \%[\-noscan]
+^^^\0\-date~^   \%[\-show] \%[\-noshow] \%[\-nofile] \%[\-nokeep]
+^^^\0\-from~^
+^^^\s+2\b'\(lt\(bv\(bv\(lk\(bv\(bv\(lb'\s0 \-search~\s+2\b'\(rt\(bv\(bv\(rk\(bv\(bv\(rb'\s0^ pattern
+^^^\0\-subject~^
+^^^\0\-to~^ \%[\-file \%[\-preserve] \%[\-link] \%+folder\ ... \%[\-nopreserve] \%[\-nolink] ]
+^^^\0\-\-component~^ \%[\-keep \%[\-stay] \%[\-nostay] \%[+folder\ ...]\ ]
+.fi
+.fc
+
+.re
+.ti .5i
+typically:
+.in 1i
+pick\0\-from\0jones\0\-scan
+.br
+pick\0\-to\0holloway
+.br
+pick\0\-subject\0ned\0\-scan\0\-keep
+.SH DESCRIPTION
+\fIPick\fR searches messages within a folder for the specified
+contents, then performs several operations on the selected
+messages.
+.PP
+A modified \fIgrep\fR(I) is used to perform the searching, so the
+full regular expression (see \fIed\fR(I)) facility is available
+within `pattern'.
+With `\-search', pattern is used directly,
+and with the others, the grep pattern constructed is:
+.nf
+
+.ti +.5i
+\*(lq^component:\*.\*(**pattern\*(rq
+
+.fi
+This means that the pattern specified for a `\-search' will be
+found everywhere in the message, including the header and the body,
+while the other search requests are limited to the single
+specified component.
+The expression `\-\-component pattern'
+is a shorthand for
+specifying `\-search \*(lqcomponent:\*.\*(**pattern\*(rq\ '; it is used to pick
+a component not in the set [cc date from subject to].
+An
+example is \*(lqpick \-\-reply\-to pooh \-show\*(rq.
+.PP
+Searching is performed on a per-line basis.
+Within the header of
+the message, each component is treated as one long line, but in
+the body, each line is separate.
+Lower-case letters in the
+search pattern will match either lower or upper case in the
+message, while upper case will match only upper case.
+.PP
+Once the search has been performed, the selected messages
+are scanned (see \fIscan\fR) if the `\-scan' switch is given, and
+then they are shown (see \fIshow\fR) if the `\-show' switch is
+given.
+After these two operations, the file operations (if
+requested) are performed.
+.PP
+The `\-file' switch operates exactly like the \fIfile\fR command, with the
+same meaning for the `\-preserve' and `\-link' switches.
+.PP
+The `\-keep' switch is similar to `\-file', but it produces a folder that
+is a subfolder of the folder being searched and defines it as
+the current folder (unless the `\-stay' flag is used).
+This
+subfolder contains the messages which matched the search
+criteria.
+All of the MH commands may be used with the sub-folder
+as the current folder.
+This gives the user considerable power
+in dealing with subsets of messages in a folder.
+.PP
+The messages in a folder produced by `\-keep' will always have the
+same numbers as they have in the source folder (i.e., the
+`\-preserve' switch is automatic).
+This way, the message
+numbers are consistent with the folder from which the messages
+were selected.
+Messages are not removed from the source folder
+(i.e., the `\-link' switch is assumed).
+If a `+folder' is not
+specified, the standard name \*(lqselect\*(rq will be used.
+(This is the
+meaning of \*(lq(select)\*(rq when it appears in the output of the
+\fIfolder\fR command.) If `+folder' arguments are given to
+`\-keep', they will be used rather than \*(lqselect\*(rq for the names
+of the subfolders.
+This allows for several subfolders to be
+maintained concurrently.
+.PP
+When a `\-keep' is performed, the subfolder becomes the current folder.
+This can be overridden by use
+of the `\-stay' switch.
+.PP
+Here's an example:
+
+.nf
+\01  % folder +inbox
+\02           inbox+ has  16 messages (  3\- 22); cur=  3.
+\03  % pick \-from dcrocker
+\04  6 hits.
+\05  [+inbox/select now current]
+\06  % folder
+\07    inbox/select+ has  \06 messages (  3\- 16); cur=  3.
+\08  % scan
+.ds p \\h'\\w'+'u'
+\09   \03+  6/20   Dcrocker          Re: ned file update issue...
+10   \06\*p  6/23   Dcrocker          removal of files from /tm...
+11   \08\*p  6/27   Dcrocker          Problems with the new ned...
+12   13\*p  6/28   d\h'\w'D'u-\w'd'u'crocker          newest nned  \*(<<I would ap...
+13   15\*p  7/\05   Dcrocker          nned  \*(<<Last week I asked...
+14   16\*p  7/\05   d\h'\w'D'u-\w'd'u'crocker          message id format  \*(<<I re...
+15  % show all | print
+16     [produce a full listing of this set of messages on the line printer.]
+17  % folder \-up
+18            inbox+ has  16 messages (  3\- 22); cur=  3; (select).
+19  % folder \-down
+20   inbox/select+ has   6 messages (  3\- 16); cur=  3.
+21  % rmf
+22  [+inbox now current]
+23  % folder
+24            inbox+ has  16 messages (  3\- 22); cur=  3.
+.fi
+
+This is a rather lengthy example, but it shows the power of the
+MH package.
+In item 1, the current folder is set to inbox.
+In 3,
+all of the messages from dcrocker are found in inbox and linked
+into the folder \*(lqinbox/select\*(rq.
+(Since no action switch is
+specified, `\-keep' is assumed.)  Items 6 and 7 show that this
+subfolder is now the current folder.
+Items 8 through 14 are a
+\fIscan\fR of the selected messages (note that they are all from dcrocker
+and are all in upper and lower case).
+Item 15 lists all of the messages to
+the high-speed printer.
+Item 17 directs \fIfolder\fR to set the
+current folder to the parent of the selection-list folder, which
+is now current.
+Item 18 shows that this has been done.
+Item 19 resets
+the current folder to the selection list, and 21 removes the
+selection-list folder and resets the current folder to the
+parent folder, as shown in 22 and 23.
+.SH FILES
+.nf
+.ta \w'$HOME/\*.mh\(ruprofile    'u
+$HOME/\*.mh\(ruprofile The user profile
+.fi
+.SH "PROFILE COMPONENTS"
+.nf
+.ta \w'Current-Folder:    'u
+Path:  To determine the user's MH directory
+Folder\-Protect:       For protection on new folders
+Current-Folder:        To find the default current folder
+.fi
+.SH DEFAULTS
+.nf
+`\-src +folder' defaults to current
+`msgs' defaults to all
+`\-keep +select' is the default if no `\-scan', `\-show', or `\-file' is specified
+.fi
+.SH CONTEXT
+If a `\-src +folder' is specified, it will
+become the current folder, unless a `\-keep' with 0 or 1
+folder arguments makes the selection-list subfolder the
+current folder.
+Each selection-list folder will have its
+current message set to the first of the messages linked into
+it unless the selection list already existed, in which case the
+current message won't be changed.
diff --git a/docs/historical/mh-nov-1983/man/prev.1 b/docs/historical/mh-nov-1983/man/prev.1
new file mode 100644 (file)
index 0000000..f29df30
--- /dev/null
@@ -0,0 +1,29 @@
+.TH PREV 1 "3 August 1983"
+.UC 4
+.SH NAME
+prev \- show the previous message
+.SH SYNOPSIS
+.B prev
+[ +folder ] [ \-switches for \fIl\fR ] [ \-help ]
+.SH DESCRIPTION
+\fIPrev\fR performs a \fIshow\fR on the previous message in the specified
+(or current) folder.
+Like \fIshow\fR, it passes any switches on to the
+program \fIl\fR, which is called to list the message.
+This command
+is exactly equivalent to \*(lqshow prev\*(rq.
+.SH FILES
+.nf
+.ta \w'$HOME/\*.mh\(ruprofile    'u
+$HOME/\*.mh\(ruprofile The user profile
+.fi
+.SH "PROFILE COMPONENTS"
+.nf
+.ta \w'Current-Folder:    'u
+Path:  To determine the user's MH directory
+Current-Folder:        To find the default current folder
+.fi
+.SH CONTEXT
+If a folder is specified, it will become current, and the
+message that is shown (i.e., the previous message in sequence)
+will become the current message.
diff --git a/docs/historical/mh-nov-1983/man/print b/docs/historical/mh-nov-1983/man/print
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/docs/historical/mh-nov-1983/man/prompter.1 b/docs/historical/mh-nov-1983/man/prompter.1
new file mode 100644 (file)
index 0000000..16569d8
--- /dev/null
@@ -0,0 +1,64 @@
+.TH PROMPTER 1 "3 August 1983"
+.UC 4
+.SH NAME
+prompter \- prompting editor front end
+.SH SYNOPSIS
+.B prompter
+[ \-erase chr ] [ \-kill chr ] [ \-help ]
+.SH DESCRIPTION
+This program is not called directly but takes the place
+of an editor and acts as an editor front end.
+\fIPrompter\fR is an editor which allows rapid composition of
+messages.
+It is particularly useful to network and low-speed
+(less than 2400 baud) users of MH.
+It is an MH program in that
+it can have its own profile entry with switches, but it can't
+be invoked directly as all other MH commands can; it is an editor
+in that it is invoked by an \*(lq\-editor prompter\*(rq switch or by the
+profile entry \*(lqEditor: prompter\*(rq, but functionally it is merely
+a text-collector and not a true editor.
+.PP
+\fIPrompter\fR expects to be called from \fIcomp\fR, \fIrepl\fR, \fIdist\fR, or
+\fIforw\fR, with a draft file as an argument.
+For example, \*(lqcomp
+\-editor prompter\*(rq will call \fIprompter\fR with the file \*(lqdraft\*(rq already set
+up with blank components.
+For each blank component it finds in
+the draft, it prompts the user and accepts a response.
+A <RETURN> will cause the whole component to be left out.
+A \*(lq\\\*(rq
+preceding a <RETURN> will continue the response on the next line,
+allowing for multiline components.
+.PP
+Any component that is non-blank will be copied and echoed to the
+terminal.
+.PP
+The start of the message body is prompted by a line of
+dashes.
+If the body is non-blank, the prompt is
+\*(lq--------Enter additional text\*(rq.
+Message-body typing is terminated with
+a <CTRL-D> (or <OPEN>).
+Control is returned to the calling
+program, where the user is asked \*(lqWhat now?\*(rq.
+See \fIcomp\fR for
+the valid options.
+.PP
+The line editing characters for kill and erase may be
+specified by the user via the arguments \*(lq\-kill chr\*(rq and \*(lq\-erase
+chr\*(rq, where chr may be a character; or \*(lq\\nnn\*(rq, where nnn is the
+octal value for the character.
+(Again, these may come from the
+default switches specified in the user's profile.)
+.PP
+A <DEL> during message-body typing is equivalent to
+<CTRL-D> for compatibility with NED.
+A <DEL> during
+component typing will abort the command that invoked
+\fIprompter\fR.
+.SH "PROFILE COMPONENTS"
+.nf
+.ta \w'prompter-next:    'u
+prompter-next: editor to be used on exit from \fIprompter\fR
+.fi
diff --git a/docs/historical/mh-nov-1983/man/repl.1 b/docs/historical/mh-nov-1983/man/repl.1
new file mode 100644 (file)
index 0000000..50f98c3
--- /dev/null
@@ -0,0 +1,81 @@
+.TH REPL 1 "3 August 1983"
+.UC 4
+.SH NAME
+repl \- reply to a message
+.SH SYNOPSIS
+.B repl
+[ +folder ] [ msg ] [ \-editor editor ] [ \-inplace ] [ \-annotate ]
+[ \-help ] [ \-noinplace ] [ \-noannotate ]
+.SH DESCRIPTION
+\fIRepl\fR aids a user in producing a reply to an existing
+message.
+In its simplest form (with no arguments), it will set up
+a message-form skeleton in reply to the current message in the
+current folder, invoke the editor, and send the composed
+message if so directed.
+The composed message is constructed as
+follows:
+.nf
+
+.in 1i
+To: <Reply-To> or <From>
+cc: <cc>, <To>
+Subject: Re: <Subject>
+In-reply-to: Your message of <Date>
+.ti +\w'In-reply-to: 'u
+<Message-Id>
+.in .5i
+
+.fi
+where field names enclosed in angle brackets (< >) indicate the
+contents of the named field from the message to which the reply
+is being made.
+Once the skeleton is constructed, an editor is
+invoked (as in \fIcomp\fR, \fIdist\fR, and \fIforw\fR).
+While in the editor,
+the message being replied to is available through a link named
+\*(lq@\*(rq.
+In NED, this means the replied-to message may be \*(lqused\*(rq
+with \*(lquse @\*(rq, or put in a window by \*(lqwindow @\*(rq.
+.PP
+As in \fIcomp\fR, \fIdist\fR, and \fIforw\fR, the user will be queried
+before the message is sent.
+If `\-annotate' is
+specified, the replied-to message will be annotated with the
+single line
+.nf
+
+.ti +.5i
+Replied: \*(<<Date\*(>>.
+
+.fi
+The command
+\*(lqcomp \-use\*(rq may be used to pick up interrupted editing, as in
+\fIdist\fR and \fIforw\fR; the `\-inplace' switch annotates the message in
+place, so that all folders with links to it will see the annotation.
+.SH FILES
+.nf
+.ta \w'$HOME/\*.mh\(ruprofile    'u
+$HOME/\*.mh\(ruprofile The user profile
+<mh-dir>/draft The constructed message file
+/usr/bin/send  To send the composed message
+.fi
+.SH "PROFILE COMPONENTS"
+.nf
+.ta \w'Current-Folder:    'u
+Path:  To determine the user's MH directory
+Editor:        To override the use of /bin/ned as the default editor
+Current-Folder:        To find the default current folder
+.fi
+.SH DEFAULTS
+.nf
+`+folder' defaults to current
+`msgs' defaults to cur
+`\-editor' defaults to /bin/ned
+`\-noannotate'
+`\-noinplace'
+.fi
+.SH CONTEXT
+If a `+folder' is specified, it will become the current
+folder, and the current message will be set to the replied-to
+message.
diff --git a/docs/historical/mh-nov-1983/man/rmf.1 b/docs/historical/mh-nov-1983/man/rmf.1
new file mode 100644 (file)
index 0000000..9dfeecc
--- /dev/null
@@ -0,0 +1,62 @@
+.TH RMF 1 "3 August 1983"
+.UC 4
+.SH NAME
+rmf \- remove folder
+.SH SYNOPSIS
+.B rmf
+[ +folder ] [ \-help ]
+.SH DESCRIPTION
+\fIRmf\fR removes all of the files (messages) within the specified
+(or default) folder, and then removes the directory (folder).
+If
+there are any files within the folder which are not a part of MH,
+they will \fInot\fR be removed, and an error will be produced.
+If the
+folder is given explicitly or the current folder is a
+subfolder (i.e., a selection list from \fIpick\fR), it will be
+removed without confirmation.
+If no argument is specified and
+the current folder is not a selection-list folder, the
+user will be asked for confirmation.
+.PP
+\fIRmf\fR irreversibly deletes messages that don't have other links,
+so use it with caution.
+.PP
+If the folder being removed is a subfolder, the parent
+folder will become the new current folder, and \fIrmf\fR will
+produce a message telling the user this has happened.
+This
+provides an easy mechanism for selecting a set of messages,
+operating on the list, then removing the list and returning to
+the current folder from which the list was extracted.
+(See the
+example under \fIpick\fR.)
+.PP
+The files that \fIrmf\fR will delete are cur, any file beginning
+with a comma, and files with purely numeric names.
+All others
+will produce error messages.
+.PP
+\fIRmf\fR of a read-only folder will delete the \*(lqcur\-\*(rq entry from the
+profile without affecting the folder itself.
+.SH FILES
+.nf
+.ta \w'or <mh-dir>/components    'u
+.fi
+.SH "PROFILE COMPONENTS"
+.nf
+.ta \w'$HOME/\*.mh\(ruprofile    'u
+$HOME/\*.mh\(ruprofile The user profile
+Path:  To determine the user's MH directory
+Current-Folder:        To find the default current folder
+.fi
+.SH DEFAULTS
+.nf
+`+folder' defaults to current, usually with confirmation
+.fi
+.SH CONTEXT
+\fIRmf\fR will set the current folder to the parent folder if a
+subfolder is removed; or if the current folder is removed,
+it will make \*(lqinbox\*(rq current.
+Otherwise, it doesn't change the
+current folder or message.
diff --git a/docs/historical/mh-nov-1983/man/rmm.1 b/docs/historical/mh-nov-1983/man/rmm.1
new file mode 100644 (file)
index 0000000..35c07c1
--- /dev/null
@@ -0,0 +1,32 @@
+.TH RMM 1 "3 August 1983"
+.UC 4
+.SH NAME
+rmm \- remove messages
+.SH SYNOPSIS
+.B rmm
+[ +folder ] [ msgs ] [ \-help ]
+.SH DESCRIPTION
+\fIRmm\fR removes the specified messages by renaming the message
+files with preceding commas.
+(This is the Rand-UNIX backup file convention.)
+.PP
+The current message is not changed by \fIrmm\fR, so a \fInext\fR  will
+advance to the next message in the folder as expected.
+.SH FILES
+.nf
+.ta \w'$HOME/\*.mh\(ruprofile    'u
+$HOME/\*.mh\(ruprofile The user profile
+.fi
+.SH "PROFILE COMPONENTS"
+.nf
+.ta \w'Current-Folder:    'u
+Path:  To determine the user's MH directory
+Current-Folder:        To find the default current folder
+.fi
+.SH DEFAULTS
+.nf
+`+folder' defaults to current
+`msgs' defaults to cur
+.fi
+.SH CONTEXT
+If a folder is given, it will become current.
diff --git a/docs/historical/mh-nov-1983/man/scan.1 b/docs/historical/mh-nov-1983/man/scan.1
new file mode 100644 (file)
index 0000000..4216108
--- /dev/null
@@ -0,0 +1,64 @@
+.SC SCAN
+.TH SCAN 1 "3 August 1983"
+.UC 4
+.SH NAME
+scan \- produce a one-line-per-message scan listing
+.SH SYNOPSIS
+.B scan
+[ +folder ] [ msgs ] [ \-ff ] [ \-header ] [ \-help ]
+[ \-noff ] [ \-noheader ]
+.SH DESCRIPTION
+\fIScan\fR produces a one-line-per-message listing of the specified
+messages.
+Each \fIscan\fR line contains the message number (name),
+the date, the \*(lqFrom\*(rq field, the \*(lqSubject\*(rq field, and, if room
+allows, some of the body of the message.
+For example:
+.nf
+
+.ta .5i 1.2i 2.6i
+^ #~^^Date~^^  From~^Subject\ \ \ \ \[\*(<<Body]
+^15+~^^7/\05~^^Dcrocker~^nned  \*(<<Last week I asked some of
+^16\ \-~^^7/\05~^^dcrocker~^message id format  \*(<<I recommend
+^18~^^7/\06~^^Obrien~^Re: Exit status from mkdir
+^19~^^7/\07~^^Obrien~^"scan" listing format in MH
+.re
+
+.fi
+The `+' on message 15 indicates that it is the current message.
+The `\-' on message 16 indicates that it has been
+replied to, as indicated by a \*(lqReplied:\*(rq component produced by
+an `\-annotate' switch to the \fIrepl\fR command.
+.PP
+If there is sufficient room left on the \fIscan\fR line after the
+subject, the line will be filled with text from the body,
+preceded by \*(<<.
+\fIScan\fR actually reads each of the specified
+messages and parses them to extract the desired fields.
+During parsing, appropriate error messages will be produced if
+there are format errors in any of the messages.
+.PP
+The `\-header' switch produces a header line prior to the \fIscan\fR
+listing, and the `\-f\&f' switch will cause a form feed to be
+output at the end of the \fIscan\fR listing.
+.SH FILES
+.nf
+.ta \w'$HOME/\*.mh\(ruprofile    'u
+^$HOME/\*.mh\(ruprofile~^The user profile
+.fi
+.SH "PROFILE COMPONENTS"
+.nf
+.ta \w'Current-Folder:    'u
+Path:  To determine the user's MH directory
+Current-Folder:        To find the default current folder
+.fi
+.SH DEFAULTS
+.nf
+`+folder' defaults to current
+`msgs' defaults to all
+`\-nof\&f'
+`\-noheader'
+.fi
+.SH CONTEXT
+If a folder is given, it will become current.
+The current message is unaffected.
diff --git a/docs/historical/mh-nov-1983/man/send.1 b/docs/historical/mh-nov-1983/man/send.1
new file mode 100644 (file)
index 0000000..753413b
--- /dev/null
@@ -0,0 +1,76 @@
+.SC SEND
+.TH SEND 1 "3 August 1983"
+.UC 4
+.SH NAME
+send \- send a message
+.SH SYNOPSIS
+.B send
+[ file ] [ \-draft ] [ \-verbose ] [ \-format ] [ \-msgid ]
+[ \-help ]  [ \-noverbose ] [ \-noformat ] [ \-nomsgid ]
+.SH DESCRIPTION
+\fISend\fR will cause the specified file (default <mh-dir>/draft) to
+be delivered to each of the addresses in the \*(lqTo:\*(rq, \*(lqcc:\*(rq, and \*(lqBcc:\*(rq
+fields of the message.
+If `\-verbose' is specified, \fIsend;\fR
+will monitor the delivery of local and net mail.
+\fISend\fR with no
+argument will query whether the draft is the intended file, whereas
+`\-draft' will suppress this question.
+Once the message has
+been mailed (or queued) successfully, the file will be renamed
+with a leading comma, which allows it to be retreived until the
+next draft message is sent.
+If there are errors in the
+formatting of the message, \fIsend;\fR will abort with a (hopefully)
+helpful error message.
+.PP
+If a \*(lqBcc:\*(rq field is encountered, its addresses will be used for
+delivery, but the \*(lqBcc:\*(rq field itself will be deleted from all
+copies of the outgoing message.
+.PP
+Prior to sending the message, the fields \*(lqFrom:  user\*(rq, and
+\*(lqDate: now\*(rq will be prepended to the message.
+If `\-msgid' is
+specified, then a \*(lqMessage-Id:\*(rq field will also be added to the
+message.
+If the message already contains a \*(lqFrom:\*(rq field, then a
+\*(lqSender: user\*(rq field will be added instead.
+(An already existing
+\*(lqSender:\*(rq field will be deleted from the message.)
+.PP
+If the user doesn't specify `\-noformat', each of the entries in
+the \*(lqTo:\*(rq and \*(lqcc:\*(rq fields will be replaced with \*(lqstandard\*(rq format
+entries.
+This standard format is designed to be usable by all
+of the message handlers on the various systems around the
+ARPANET.
+.PP
+If an \*(lqFcc: folder\*(rq is encountered, the message will be copied
+to the specified folder in the format in which it will appear to any
+receivers of the message.
+That is, it will have the prepended
+fields and field reformatting.
+.PP
+If a \*(lqDistribute-To:\*(rq field is encountered, the message
+is handled as a redistribution message (see \fIdist\fR for
+details), with \*(lqDistribution-Date: now\*(rq and \*(lqDistribution-From: user\*(rq
+added.
+.SH FILES
+.nf
+.ta \w'$HOME/\*.mh\(ruprofile    'u
+$HOME/\*.mh\(ruprofile The user profile
+.fi
+.SH "PROFILE COMPONENTS"
+.nf
+.ta \w'Path:    'u
+Path:  To determine the user's MH directory
+.fi
+.SH DEFAULTS
+.nf
+`file' defaults to draft
+`\-noverbose'
+`\-format'
+`\-nomsgid'
+.fi
+.SH CONTEXT
+\fISend\fR has no effect on the current message or folder.
diff --git a/docs/historical/mh-nov-1983/man/show.1 b/docs/historical/mh-nov-1983/man/show.1
new file mode 100644 (file)
index 0000000..abbea1a
--- /dev/null
@@ -0,0 +1,64 @@
+.TH SHOW 1 "3 August 1983"
+.UC 4
+.SH NAME
+show \- show (list) messages
+.SH SYNOPSIS
+.B show
+[ +folder ] [ msgs ] [ \-pr ] [ \-nopr ] [ \-draft ] [ \-help ]
+[ \fIl\fR or \fIpr\fR switches ]
+.SH DESCRIPTION
+\fIShow\fR lists each of the specified messages to the standard
+output (typically, the terminal).
+The messages are listed exactly
+as they are, with no reformatting.
+A program called \fIl\fR is
+invoked to do the listing, and any switches not recognized by
+\fIshow\fR are passed along to \fIl\fR.
+.PP
+If no \*(lqmsgs\*(rq are specified, the current message is used.
+If
+more than one message is specified, \fIl\fR will prompt for a
+<return> prior to listing each message.
+.PP
+\fIl\fR will list each message, a page at a time.
+When the end of
+page is reached, \fIl\fR will ring the bell and wait for a <RETURN>
+or <CTRL-D>.
+If a <return> is entered, \fIl\fR will clear the
+screen before listing the next page, whereas <CTRL-D> will not.
+The switches to \fIl\fR are
+`\-p#' to indicate the page length in lines, and `\-w#' to
+indicate the width of the page in characters.
+.PP
+If the standard output is not a terminal, no queries are made,
+and each file is listed with a one-line header and two lines of
+separation.
+.PP
+If `\-pr' is specified, then \fIpr\fR(I) will be invoked rather than
+\fIl\fR, and the switches (other than `\-draft') will be passed
+along.
+\*(lqShow \-draft\*(rq will list the file <mh-dir>/draft if it
+exists.
+.SH FILES
+.nf
+.ta \w'$HOME/\*.mh\(ruprofile    'u
+$HOME/\*.mh\(ruprofile The user profile
+/bin/l Screen-at-a-time list program
+/bin/pr        \fIpr\fR(1)
+.fi
+.SH "PROFILE COMPONENTS"
+.nf
+.ta \w'Current-Folder:    'u
+Path:  To determine the user's MH directory
+Current-Folder:        To find the default current folder
+.fi
+.SH DEFAULTS
+.nf
+`+folder' defaults to current
+`msgs' defaults to cur
+`\-nopr'
+.fi
+.SH CONTEXT
+If a folder is given, it will become the current message.
+The last message
+listed will become the current message.
diff --git a/docs/historical/mh-nov-1983/strings/Mailprog.c b/docs/historical/mh-nov-1983/strings/Mailprog.c
new file mode 100644 (file)
index 0000000..fe8edb3
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ * This is the program called to deliver mail
+ * on systems where we try to maintain compatibility
+ * with the standard message format.
+ */
+
+char   *Mailprog = "/usr/ucb/Mail";
diff --git a/docs/historical/mh-nov-1983/strings/Makefile b/docs/historical/mh-nov-1983/strings/Makefile
new file mode 100644 (file)
index 0000000..966fc43
--- /dev/null
@@ -0,0 +1,37 @@
+CC = cc -I../cmds
+CFLAGS=-O
+
+strings.a: anoyes.o        \
+          components.o    \
+          current.o       \
+          defalt.o        \
+          distcomps.o     \
+          draft.o         \
+          fileproc.o      \
+          foldprot.o      \
+          hostname.o      \
+          installproc.o   \
+          listname.o      \
+          lockdir.o       \
+          lsproc.o        \
+          mailboxes.o     \
+          mailproc.o      \
+          mh_prof.o       \
+          mhnews.o        \
+          msgprot.o       \
+          pfolder.o       \
+          prproc.o        \
+          scanproc.o      \
+          sendproc.o      \
+          showproc.o      \
+          stdcomps.o      \
+          stddcomps.o     \
+          sysed.o         \
+          Mailprog.o      \
+          unixtomh.o      \
+          localname.o
+
+       ar cr strings.a *.o
+
+clean:
+       rm -f *.o strings.a
diff --git a/docs/historical/mh-nov-1983/strings/anoyes.c b/docs/historical/mh-nov-1983/strings/anoyes.c
new file mode 100644 (file)
index 0000000..eb842c9
--- /dev/null
@@ -0,0 +1,5 @@
+char *anoyes[] = {
+       "no",   0,
+       "yes",  0,
+       0,
+};
diff --git a/docs/historical/mh-nov-1983/strings/components.c b/docs/historical/mh-nov-1983/strings/components.c
new file mode 100644 (file)
index 0000000..ffd97cb
--- /dev/null
@@ -0,0 +1 @@
+char    *components =   "components";
diff --git a/docs/historical/mh-nov-1983/strings/current.c b/docs/historical/mh-nov-1983/strings/current.c
new file mode 100644 (file)
index 0000000..86ea368
--- /dev/null
@@ -0,0 +1 @@
+char    *current =      "cur";
diff --git a/docs/historical/mh-nov-1983/strings/defalt.c b/docs/historical/mh-nov-1983/strings/defalt.c
new file mode 100644 (file)
index 0000000..ab3a012
--- /dev/null
@@ -0,0 +1 @@
+char    *defalt =       "inbox";
diff --git a/docs/historical/mh-nov-1983/strings/distcomps.c b/docs/historical/mh-nov-1983/strings/distcomps.c
new file mode 100644 (file)
index 0000000..acd7eb7
--- /dev/null
@@ -0,0 +1 @@
+char    *distcomps =    "distcomps";
diff --git a/docs/historical/mh-nov-1983/strings/draft.c b/docs/historical/mh-nov-1983/strings/draft.c
new file mode 100644 (file)
index 0000000..0e25051
--- /dev/null
@@ -0,0 +1 @@
+char    *draft =        "draft";
diff --git a/docs/historical/mh-nov-1983/strings/fileproc.c b/docs/historical/mh-nov-1983/strings/fileproc.c
new file mode 100644 (file)
index 0000000..56626c7
--- /dev/null
@@ -0,0 +1,6 @@
+/*
+ * This program is usually called directly by users, but it is
+ * also invoked by the deliver program to process an "fcc".
+ */
+
+char    *fileproc =     "/usr/new/mh/refile";
diff --git a/docs/historical/mh-nov-1983/strings/foldprot.c b/docs/historical/mh-nov-1983/strings/foldprot.c
new file mode 100644 (file)
index 0000000..8769a27
--- /dev/null
@@ -0,0 +1,5 @@
+/*
+ * Folders (directories) are created with this protection (mode)
+ */
+
+char    *foldprot =     "0751";
diff --git a/docs/historical/mh-nov-1983/strings/hostname.c b/docs/historical/mh-nov-1983/strings/hostname.c
new file mode 100644 (file)
index 0000000..64278d6
--- /dev/null
@@ -0,0 +1,6 @@
+/*
+ * For ARPANET mail, this is the local-site's Host name.
+ *   (currently not used.)
+ */
+
+char    *hostname =     "Berkeley";
diff --git a/docs/historical/mh-nov-1983/strings/installproc.c b/docs/historical/mh-nov-1983/strings/installproc.c
new file mode 100644 (file)
index 0000000..38814e7
--- /dev/null
@@ -0,0 +1,6 @@
+/*
+ * When a user runs an MH program for the first time, this program
+ * is called to create his MH profile, and mail directory.
+ */
+
+char    *installproc =  "/usr/new/lib/mh/install-mh";
diff --git a/docs/historical/mh-nov-1983/strings/listname.c b/docs/historical/mh-nov-1983/strings/listname.c
new file mode 100644 (file)
index 0000000..af8a882
--- /dev/null
@@ -0,0 +1 @@
+char    *listname =     "select";
diff --git a/docs/historical/mh-nov-1983/strings/localname.c b/docs/historical/mh-nov-1983/strings/localname.c
new file mode 100644 (file)
index 0000000..b11b7da
--- /dev/null
@@ -0,0 +1,5 @@
+/*
+ * Local network host name
+ */
+
+char *localname = "CSVAX";
diff --git a/docs/historical/mh-nov-1983/strings/lockdir.c b/docs/historical/mh-nov-1983/strings/lockdir.c
new file mode 100644 (file)
index 0000000..1496570
--- /dev/null
@@ -0,0 +1,15 @@
+/*
+ * This is where the lock files are kept.  It MUST be on the same
+ * file system as the "mailboxes" directory.  It also must be read/
+ * write by the world.  When a mailbox needs locking (while being
+ * read and cleared by inc, or written by deliver), a link to the
+ * mailbox is made in this directory, under the same name (i.e., the
+ * users name).  Links are one of the few things even a privileged
+ * process (deliver) cannot over-ride.  The deliver process waits
+ * for lockwait seconds for the lock to clear, then it over-rides
+ * the lock.  This number should be set around 15-30 seconds in the
+ * case of a VERY loaded system.
+ */
+
+char    *lockdir =      "/usr/spool/mail/";
+int     lockwait =      15;                     /* Seconds */
diff --git a/docs/historical/mh-nov-1983/strings/lsproc.c b/docs/historical/mh-nov-1983/strings/lsproc.c
new file mode 100644 (file)
index 0000000..50ca14c
--- /dev/null
@@ -0,0 +1,9 @@
+/*
+ * This is standard ls, but "folder -all -short" calls it with
+ * a -x switch meaning "list only directories".
+ *
+ * Also, its nice to have columnated output rather than a simple
+ * list... (personal prejudice).
+ */
+
+char    *lsproc =       "/usr/ucb/ls";
diff --git a/docs/historical/mh-nov-1983/strings/mailboxes.c b/docs/historical/mh-nov-1983/strings/mailboxes.c
new file mode 100644 (file)
index 0000000..b9c56b9
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ * This is where the user mailboxes are kept.  On our 11/70 they were
+ * kept in each users $HOME directory.  This is where the VAX login
+ * program is looking for them, as well as the old BELL mail.
+ */
+
+char    *mailboxes =      "/usr/spool/mail/";
diff --git a/docs/historical/mh-nov-1983/strings/mailproc.c b/docs/historical/mh-nov-1983/strings/mailproc.c
new file mode 100644 (file)
index 0000000..b702076
--- /dev/null
@@ -0,0 +1,6 @@
+/*
+ * This is the path for the Bell equivalent mail program... Used
+ *  by "news -send" to send news items to the news user.
+ */
+
+char    *mailproc =     "/bin/mail";
diff --git a/docs/historical/mh-nov-1983/strings/mh_defs.c b/docs/historical/mh-nov-1983/strings/mh_defs.c
new file mode 100644 (file)
index 0000000..fa86e65
--- /dev/null
@@ -0,0 +1,6 @@
+/*
+ * This is the name of the file used to store
+ * the user's MH profile
+ */
+
+char   *mh_defs = "/.mh_profile";
diff --git a/docs/historical/mh-nov-1983/strings/mh_deliver.c b/docs/historical/mh-nov-1983/strings/mh_deliver.c
new file mode 100644 (file)
index 0000000..62f4928
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ * This is the delivery program called ONLY through send to
+ * actually deliver mail to users.  It is fairly small, and
+ * must run SUID ROOT, to create new mailboxes.
+ */
+
+/* char    *mh_deliver = "/usr/new/lib/mh/deliver"; */
diff --git a/docs/historical/mh-nov-1983/strings/mh_prof.c b/docs/historical/mh-nov-1983/strings/mh_prof.c
new file mode 100644 (file)
index 0000000..db3cc3a
--- /dev/null
@@ -0,0 +1 @@
+char    *mh_prof =      "/.mh_profile";
diff --git a/docs/historical/mh-nov-1983/strings/mhnews.c b/docs/historical/mh-nov-1983/strings/mhnews.c
new file mode 100644 (file)
index 0000000..098e8f4
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ * This program is called to print out MH news IF NEWS is defined
+ * when the MH programs are compiled.  This whole mechanism has not
+ * been tested under version 7!
+ */
+
+char    *mhnews =       "/usr/new/mh/news";
diff --git a/docs/historical/mh-nov-1983/strings/msgprot.c b/docs/historical/mh-nov-1983/strings/msgprot.c
new file mode 100644 (file)
index 0000000..65f1ff0
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ * Every NEW message will be created with this protection.  When a
+ * message is filed it retains its protection, so this only applies
+ * to messages coming in through inc.
+ */
+
+char    *msgprot =      "0664";
diff --git a/docs/historical/mh-nov-1983/strings/pfolder.c b/docs/historical/mh-nov-1983/strings/pfolder.c
new file mode 100644 (file)
index 0000000..209c7ee
--- /dev/null
@@ -0,0 +1 @@
+char    *pfolder =      "current-folder";
diff --git a/docs/historical/mh-nov-1983/strings/prproc.c b/docs/historical/mh-nov-1983/strings/prproc.c
new file mode 100644 (file)
index 0000000..4417a45
--- /dev/null
@@ -0,0 +1,6 @@
+/*
+ * This is the std BELL pr, which is invoked through show with the
+ * -pr switch.
+ */
+
+char    *prproc =       "/bin/pr";
diff --git a/docs/historical/mh-nov-1983/strings/scanproc.c b/docs/historical/mh-nov-1983/strings/scanproc.c
new file mode 100644 (file)
index 0000000..0bb22ea
--- /dev/null
@@ -0,0 +1,6 @@
+/*
+ * This program is usually called directly by users, but it is
+ * also invoked by "pick -scan".
+ */
+
+char    *scanproc =     "/usr/new/mh/scan";
diff --git a/docs/historical/mh-nov-1983/strings/sendproc.c b/docs/historical/mh-nov-1983/strings/sendproc.c
new file mode 100644 (file)
index 0000000..82baf79
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ * This program is usually called by one of the message composition
+ * programs: comp, repl, dist, and forw, but it may also be called
+ * directly to send a message previously composed.
+ */
+
+char    *sendproc =     "/usr/new/mh/send";
diff --git a/docs/historical/mh-nov-1983/strings/showproc.c b/docs/historical/mh-nov-1983/strings/showproc.c
new file mode 100644 (file)
index 0000000..4bd7c6d
--- /dev/null
@@ -0,0 +1,9 @@
+/*
+ * This program is called to list messages.  At Rand, the program
+ * c stops at the end of each page and waits for a <return> or
+ * <open> to continue.  Eventually, this path should invoke a
+ * special program which displays messages much more intelligently--
+ * such as layed out nicely on the screen.
+ */
+
+char    *showproc =     "/usr/ucb/more";                       /* 5/6/79 */
diff --git a/docs/historical/mh-nov-1983/strings/stdcomps.c b/docs/historical/mh-nov-1983/strings/stdcomps.c
new file mode 100644 (file)
index 0000000..5329fbe
--- /dev/null
@@ -0,0 +1,6 @@
+/*
+ * This is the standard skeleton for message composition with both
+ * comp and forw.
+ */
+
+char    *stdcomps =     "/usr/new/lib/mh/components";
diff --git a/docs/historical/mh-nov-1983/strings/stddcomps.c b/docs/historical/mh-nov-1983/strings/stddcomps.c
new file mode 100644 (file)
index 0000000..0e3fa76
--- /dev/null
@@ -0,0 +1,5 @@
+/*
+ * This is the standard skeleton for message composition with dist.
+ */
+
+char    *stddcomps =    "/usr/new/lib/mh/distcomps";
diff --git a/docs/historical/mh-nov-1983/strings/strings.h b/docs/historical/mh-nov-1983/strings/strings.h
new file mode 100644 (file)
index 0000000..e9af6d0
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * This file gives extern declarations to all the strings
+ * that we might ever reference.
+ *
+ * I don't know if this what strings.h is supposed to be,
+ * but this is as good a first guess as I can handle.
+ */
+
+extern char *anoyes[];
+extern char    *components;
+extern char    *current;
+extern char    *defalt;
+extern char    *distcomps;
+extern char    *draft;
+extern char    *fileproc;
+extern char    *foldprot;
+extern char    *hostname;
+extern char    *installproc;
+extern char    *listname;
+extern char    *lockdir;
+extern int     lockwait;
+extern char    *lsproc;
+extern char    *mailboxes;
+extern char    *mailproc;
+extern char    *mh_deliver;
+extern char    *mh_prof;
+extern char    *mhnews;
+extern char    *msgprot;
+extern char    *pfolder;
+extern char    *prproc;
+extern char    *scanproc;
+extern char    *sendproc;
+extern char    *showproc;
+extern char    *stdcomps;
+extern char    *stddcomps;
+extern char    *sysed;
diff --git a/docs/historical/mh-nov-1983/strings/sysed.c b/docs/historical/mh-nov-1983/strings/sysed.c
new file mode 100644 (file)
index 0000000..25bb0e5
--- /dev/null
@@ -0,0 +1,9 @@
+/*
+ * This is the editor invoked by the various message composition
+ * programs.  It SHOULD be a 2-D scope editor, such as Rand's Ned
+ * or Berkeley's ex, but any editor will work.  If you don't have
+ * a scope editor, you might want to default to prompter, but it
+ * works very marginally with forw and dist.
+ */
+
+char    *sysed =        "/bin/e";
diff --git a/docs/historical/mh-nov-1983/strings/unixtomh.c b/docs/historical/mh-nov-1983/strings/unixtomh.c
new file mode 100644 (file)
index 0000000..0d3ce08
--- /dev/null
@@ -0,0 +1,7 @@
+/*
+ * This program is called to convert UNIX style
+ * mailboxes to MH style mail boxes, if we are trying
+ * to stay UNIX mailbox compatible.
+ */
+
+char *unixtomh = "/usr/new/lib/mh/unixtomh";
diff --git a/docs/historical/mh-nov-1983/subs/Makefile b/docs/historical/mh-nov-1983/subs/Makefile
new file mode 100644 (file)
index 0000000..62c7449
--- /dev/null
@@ -0,0 +1,56 @@
+subs.a: add.o           \
+       ambigsw.o       \
+       atooi.o         \
+       brkstring.o     \
+       cdate.o         \
+       cndfree.o       \
+       concat.o        \
+       copy.o          \
+       copyip.o        \
+       cputc.o         \
+       done.o          \
+       fdcompare.o     \
+       gans.o          \
+       getans.o        \
+       getcpy.o        \
+       help.o          \
+       invo_name.o     \
+       locv.o          \
+       m_convert.o     \
+       m_delete.o      \
+       m_edit.o        \
+       m_find.o        \
+       m_getdefs.o     \
+       m_getfld.o      \
+       m_getfolder.o   \
+       m_gmprot.o      \
+       m_gmsg.o        \
+       m_maildir.o     \
+       m_name.o        \
+       m_replace.o     \
+       m_send.o        \
+       m_setcur.o      \
+       m_update.o      \
+       makedir.o       \
+       makename.o      \
+       peekc.o         \
+       pr_array.o      \
+       printsw.o       \
+       putdate.o       \
+       r1bindex.o      \
+       showfile.o      \
+       smatch.o        \
+       ssequal.o       \
+       trimcpy.o       \
+       type.o          \
+       uleq.o
+
+       ar cr subs.a `lorder *.o | tsort`
+
+.c.o:
+       cc -I../cmds -c -O $*.c
+       -@ld -x -r $@
+       @mv a.out $@
+
+clean:
+       rm -f *.o subs.a
diff --git a/docs/historical/mh-nov-1983/subs/add.c b/docs/historical/mh-nov-1983/subs/add.c
new file mode 100644 (file)
index 0000000..aad3815
--- /dev/null
@@ -0,0 +1,15 @@
+char *add(this, that)
+register char *this, *that;
+{
+       register char *r;
+
+       if(!this)
+               this = "";
+       if(!that)
+               that = "";
+       r = (char *) malloc(strlen(this)+strlen(that)+1);
+       sprintf(r, "%s%s", that, this);
+       if(*that)
+               cndfree(that);
+       return(r);
+}
diff --git a/docs/historical/mh-nov-1983/subs/ambigsw.c b/docs/historical/mh-nov-1983/subs/ambigsw.c
new file mode 100644 (file)
index 0000000..505b2d4
--- /dev/null
@@ -0,0 +1,10 @@
+#include <stdio.h>
+
+ambigsw(arg, swp)
+char *arg;
+{
+       fprintf(stderr, "%s: ", invo_name());
+       fprintf(stderr, "-%s ambiguous.  It matches \n", arg);
+       printsw(arg, swp, "-");
+}
+
diff --git a/docs/historical/mh-nov-1983/subs/atooi.c b/docs/historical/mh-nov-1983/subs/atooi.c
new file mode 100644 (file)
index 0000000..79991d3
--- /dev/null
@@ -0,0 +1,15 @@
+atooi(cp)
+register char *cp;
+{
+       register int i, base;
+
+/*      base = 10;      */
+       i = 0;
+/*      if(*cp == '0')  */
+               base = 8;
+       while(*cp >= '0' && *cp <= '9') {
+               i *= base;
+               i += *cp++ - '0';
+       }
+       return(i);
+}
diff --git a/docs/historical/mh-nov-1983/subs/brkstring.c b/docs/historical/mh-nov-1983/subs/brkstring.c
new file mode 100644 (file)
index 0000000..9933ff1
--- /dev/null
@@ -0,0 +1,38 @@
+#define NSTR 25
+char **brkstring(strg,brksep,brkterm)  /* returns pointer to static table of substring ptrs */
+char *strg;
+char *brksep, *brkterm;
+{
+
+       register char c, *bp, *sp;
+       static char *broken[NSTR+1];    /* static array of substring start addresses */
+       int bi;
+
+       sp = strg;      /* scan string, replacing separators with zeroes */
+
+       for (bi=0; bi<NSTR; bi++) {     /* and entering start addrs in "broken" */
+               while (brkany(c = *sp, brksep)) *sp++ = 0;
+               if (!c || brkany(c, brkterm)) {
+                       *sp=0;
+                       broken[bi] = 0;
+                       return(broken);         /* terminator found, finish up */
+               }
+
+               broken[bi] = sp;        /* set next start addr */
+
+               while ((c = *++sp) && !brkany(c,brksep) && !brkany(c,brkterm));
+
+       }
+       broken[NSTR] = 0;               /* reached limit of NSTR substrings */
+       return (broken);
+}
+
+brkany (chr,strg)      /* returns 1 if chr in strg, 0 otherwise */
+char chr,*strg;
+{
+       register char *sp;
+
+       for (sp=strg; *sp; sp++)
+               if (chr == *sp) return (1);
+       return (0);
+}
diff --git a/docs/historical/mh-nov-1983/subs/cdate.c b/docs/historical/mh-nov-1983/subs/cdate.c
new file mode 100644 (file)
index 0000000..a1fd866
--- /dev/null
@@ -0,0 +1,18 @@
+/* returns date in format dd-mon-yy@hh:mm:ss\0 */
+char *cdate(dataddr)
+long *dataddr;
+{
+       register char *cp;
+       char *ctime();
+
+       cp = ctime(dataddr);
+       cp[1] = cp[8];
+       cp[2] = cp[9];
+       cp[3] = '-';
+       cp[7] = '-';
+       cp[8] = cp[22];
+       cp[9] = cp[23];
+       cp[10] = '@';
+       cp[19] = 0;
+       return(cp+1);
+}
diff --git a/docs/historical/mh-nov-1983/subs/cndfree.c b/docs/historical/mh-nov-1983/subs/cndfree.c
new file mode 100644 (file)
index 0000000..c2f2bc4
--- /dev/null
@@ -0,0 +1,12 @@
+/* Conditional free -- perform a free call if the address passed
+ * is in free storage;  else NOP
+ */
+
+
+cndfree(addr)
+char *addr;
+{
+       extern char end;
+
+       if(addr >= &end) free(addr);
+}
diff --git a/docs/historical/mh-nov-1983/subs/concat.c b/docs/historical/mh-nov-1983/subs/concat.c
new file mode 100644 (file)
index 0000000..ba19272
--- /dev/null
@@ -0,0 +1,18 @@
+#include "mh.h"
+
+char *concat(args)
+char *args;
+{
+       register char **a;
+       register char *cp;
+       register int  len;
+       register char *ret;
+
+       len = 1;
+       for(a = &args; *a; )
+               len += strlen(*a++);
+       ret = cp = (char *) malloc(len);
+       for(a = &args; *a; )
+               cp = copy(*a++, cp);
+       return(ret);
+}
diff --git a/docs/historical/mh-nov-1983/subs/copy.c b/docs/historical/mh-nov-1983/subs/copy.c
new file mode 100644 (file)
index 0000000..3284c12
--- /dev/null
@@ -0,0 +1,6 @@
+char *copy(from,to)
+register char *from, *to;
+{
+       while(*to++ = *from++);
+       return to-1;
+};
diff --git a/docs/historical/mh-nov-1983/subs/copyip.c b/docs/historical/mh-nov-1983/subs/copyip.c
new file mode 100644 (file)
index 0000000..a145481
--- /dev/null
@@ -0,0 +1,9 @@
+int *copyip(ipf, ipt)
+register int *ipf, *ipt;
+{
+       while((*ipt = *ipf)  && *ipf++ != -1)
+               ipt++;
+       *ipt = 0;
+       return(ipt);
+}
+
diff --git a/docs/historical/mh-nov-1983/subs/cputc.c b/docs/historical/mh-nov-1983/subs/cputc.c
new file mode 100644 (file)
index 0000000..f3715fb
--- /dev/null
@@ -0,0 +1,13 @@
+#include <stdio.h>
+
+cputc(chr, ip)
+register FILE *ip;
+{
+       if(ip != NULL) {
+               putc(chr, ip);
+               if(ferror(ip)) {
+                       perror("Write error");
+                       done(-1);
+               }
+       }
+}
diff --git a/docs/historical/mh-nov-1983/subs/crpbrkstring.c b/docs/historical/mh-nov-1983/subs/crpbrkstring.c
new file mode 100644 (file)
index 0000000..bea7514
--- /dev/null
@@ -0,0 +1,50 @@
+#define NSTR 25
+
+/*
+ * Parse the given string into a number of sub strings separated
+ * by characters in brksep.  Terminate on brkterm or 0.
+ */
+
+char **
+brkstring(strg, brksep, brkterm)
+       char *strg;
+       char *brksep, *brkterm;
+{
+       register int c;
+       register char *cp, **ap;
+       static char *broken[NSTR+1];
+
+       cp = strg;
+       ap = broken;
+       for (;;) {
+               if (ap-broken > NSTR) {
+                       broken[NSTR] = 0;
+                       return(broken);
+               }
+               while (brkany(*cp, brksep))
+                       cp++;
+               if (*cp == 0 || *cp == brkterm) {
+done:
+                       *ap = 0;
+                       return(broken);
+               }
+               *ap++ = cp;
+               while (!brkany(*cp, brksep) && *cp && *cp != brkterm)
+                       cp++;
+               if (*cp == 0 || *cp == brkterm) {
+                       *cp = 0;
+                       goto done;
+               }
+               *cp++ = 0;
+       }
+}
+
+brkany (chr,strg)      /* returns 1 if chr in strg, 0 otherwise */
+char chr,*strg;
+{
+       register char *sp;
+
+       for (sp=strg; *sp; sp++)
+               if (chr == *sp) return (1);
+       return (0);
+}
diff --git a/docs/historical/mh-nov-1983/subs/done.c b/docs/historical/mh-nov-1983/subs/done.c
new file mode 100644 (file)
index 0000000..5808ba3
--- /dev/null
@@ -0,0 +1,8 @@
+/* This routine is replaced by some modules if they need to do
+ * cleanup.  All exits in the code call done rather than exit.
+ */
+
+done(status)
+{
+       exit(status);
+}
diff --git a/docs/historical/mh-nov-1983/subs/fdcompare.c b/docs/historical/mh-nov-1983/subs/fdcompare.c
new file mode 100644 (file)
index 0000000..94a54b2
--- /dev/null
@@ -0,0 +1,27 @@
+fdcompare(fd1, fd2)
+{
+       int n1, n2, resp;
+       register int i;
+       register char *c1, *c2;
+       char b1[512], b2[512];
+
+       resp = 1;
+       while((n1 = read(fd1, b1, 512)) >= 0 &&
+             (n2 = read(fd2, b2, 512)) >= 0 &&
+              n1 == n2) {
+
+               c1 = b1; c2 = b2;
+               for(i = n1 < 512? n1 : 512; i--; )
+                       if(*c1++ != *c2++) {
+                               resp = 0;
+                               goto leave;
+                       }
+               if(n1 < 512)
+                       goto leave;
+       }
+       resp = 0;
+leave:
+       lseek(fd1, 0l, 0);
+       lseek(fd2, 0l, 0);
+       return(resp);
+}
diff --git a/docs/historical/mh-nov-1983/subs/gans.c b/docs/historical/mh-nov-1983/subs/gans.c
new file mode 100644 (file)
index 0000000..c85c1e0
--- /dev/null
@@ -0,0 +1,38 @@
+#include "mh.h"
+#include <stdio.h>
+
+gans(prompt, ansp)
+struct swit *ansp;
+{
+       char ansbuf[32];
+       register char *cp;
+       register int i;
+       struct swit *ap;
+
+    for(;;) {
+       printf("%s", prompt);
+       fflush(stdout);
+       cp = ansbuf;
+       while((i = getchar()) != '\n') {
+               if(i == EOF)
+                       return(0);
+               if(cp < &ansbuf[31]) {
+                       if(i >= 'A' && i <= 'Z')
+                               i += 'a'-'A';
+                       *cp++ = i;
+               }
+       }
+       *cp = 0;
+       if(ansbuf[0] == '?' || cp == ansbuf) {
+               printf("Options are:\n");
+               for(ap = ansp; ap->sw; ap++)
+                       printf("  %s\n", ap->sw);
+               continue;
+       }
+       if((i = smatch(ansbuf, ansp)) < 0) {
+               printf("%s: %s.\n", ansbuf, i == -1? "unknown":"ambiguous");
+               continue;
+       }
+       return(i);
+    }
+}
diff --git a/docs/historical/mh-nov-1983/subs/getans.c b/docs/historical/mh-nov-1983/subs/getans.c
new file mode 100644 (file)
index 0000000..11abb45
--- /dev/null
@@ -0,0 +1,54 @@
+#include "mh.h"
+#include <signal.h>
+#include <stdio.h>
+
+int g_sigint;   /* sensed an interrupt */
+int g_sig();
+
+char **getans(prompt, ansp)
+struct swit *ansp;
+{
+       static char ansbuf[128];
+       register char *cp, **cpp;
+       register int i;
+       struct swit *ap;
+
+       signal(SIGINT, g_sig);
+       for(;;) {
+               printf("%s", prompt);
+               fflush(stdout);
+               cp = ansbuf;
+               while((i = getchar()) != '\n') {
+                       if(i == EOF || g_sigint)  {
+                               g_sigint = 0;
+                               return(0);
+                       }
+                       if(cp < &ansbuf[127])
+                               *cp++ = i;
+               }
+               *cp = 0;
+               if(ansbuf[0] == '?' || cp == ansbuf) {
+                       printf("Options are:\n");
+                       printsw(ALL, ansp, "");
+                       continue;
+               }
+               cpp = brkstring(ansbuf, " ", 0);
+               switch(smatch(*cpp, ansp)) {
+               case -2:ambigsw(*cpp, ansp);                   /* ambiguous */
+                       continue;
+               case -1:                                       /* unknown   */
+                       printf(" -%s unknown. Hit <CR> for help.\n", *cpp);
+                       continue;
+               default:
+                       return(cpp);            /* list, edit, quit, send */
+               }
+       }
+}
+
+
+g_sig()
+{
+       signal(SIGINT, g_sig);
+       g_sigint = 1;
+       return;
+}
diff --git a/docs/historical/mh-nov-1983/subs/getcpy.c b/docs/historical/mh-nov-1983/subs/getcpy.c
new file mode 100644 (file)
index 0000000..ab94cd1
--- /dev/null
@@ -0,0 +1,8 @@
+char *getcpy(str)
+{
+       register char *cp;
+
+       cp = (char *) malloc(strlen(str) + 1);
+       strcpy(cp, str);
+       return(cp);
+}
diff --git a/docs/historical/mh-nov-1983/subs/help.c b/docs/historical/mh-nov-1983/subs/help.c
new file mode 100644 (file)
index 0000000..9f6dc12
--- /dev/null
@@ -0,0 +1,9 @@
+#include "mh.h"
+
+help(str, swp)
+char *str;
+{
+       printf("syntax: %s\n", str);
+       printf("  switches are:\n");
+       printsw(ALL, swp, "-");
+}
diff --git a/docs/historical/mh-nov-1983/subs/invo_name.c b/docs/historical/mh-nov-1983/subs/invo_name.c
new file mode 100644 (file)
index 0000000..25b86a4
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * This routine returns the address on the stack of the text of the
+ *  first argument to the process.  It only works on the VAX, and only
+ *  if the process was not called with 4 empty args in a row.
+ */
+
+char *invo_name()
+{
+       register int *ip;
+
+       ip = (int *) 0x7ffffff8;        /* Highest stack address -4 */
+
+       while(*--ip != 0)               /* Look backwards for bumber */
+               ;
+       return (char *) &ip[1];         /* Next string is it. */
+}
diff --git a/docs/historical/mh-nov-1983/subs/locv.c b/docs/historical/mh-nov-1983/subs/locv.c
new file mode 100644 (file)
index 0000000..b530686
--- /dev/null
@@ -0,0 +1,8 @@
+char *locv(longint)
+long longint;
+{
+       static char locvbuf[12];
+
+       sprintf(locvbuf, "%ld", longint);
+       return locvbuf;
+}
diff --git a/docs/historical/mh-nov-1983/subs/m_convert.c b/docs/historical/mh-nov-1983/subs/m_convert.c
new file mode 100644 (file)
index 0000000..43220b4
--- /dev/null
@@ -0,0 +1,147 @@
+#include "mh.h"
+#include <stdio.h>
+
+int  convdir;
+struct msgs *mp;
+char *delimp;
+
+m_convert(name)
+char *name;
+{
+       register char *cp;
+       register int first, last;
+       int found, group, range, err;
+       char *bp;
+
+       found = group = 0;
+       if(strcmp((cp = name), "all") == 0)
+               cp = "first-last";
+       if((err = first = m_conv(cp)) <= 0)
+               goto badbad;
+       if(*(cp = delimp) && *cp != '-' && *cp != ':')  {
+       baddel: fprintf(stderr, "Illegal argument delimiter: \"%c\"\n", *delimp);
+               return(0);
+       }
+       if(*cp == '-') {
+               group++;  cp++;
+               if((err = last = m_conv(cp)) <= 0) {
+         badbad:       if(err == -1)
+                               fprintf(stderr, "No %s message\n", cp);
+                       else
+         badlist:              fprintf(stderr, "Bad message list \"%s\".\n", name);
+                       return(0);
+               }
+               if(last < first) goto badlist;
+               if(*delimp) goto baddel;
+               if(first > mp->hghmsg || last < mp->lowmsg) {
+       rangerr:        fprintf(stderr, "No messages in range \"%s\".\n", name);
+                       return(0);
+               }
+               if(last > mp->hghmsg)
+                       last = mp->hghmsg;
+               if(first < mp->lowmsg)
+                       first = mp->lowmsg;
+       } else if(*cp == ':') {
+               cp++;
+               if(*cp == '-') {
+                       convdir = -1;
+                       cp++;
+               } else if(*cp == '+') {
+                       convdir = 1;
+                       cp++;
+               }
+               if((range = atoi(bp = cp)) == 0)
+                       goto badlist;
+               while(*bp >= '0' && *bp <= '9') bp++;
+               if(*bp)
+                       goto baddel;
+               if((convdir > 0 && first > mp->hghmsg) ||
+                  (convdir < 0 && first < mp->lowmsg))
+                       goto rangerr;
+               if(first < mp->lowmsg)
+                       first = mp->lowmsg;
+               if(first > mp->hghmsg)
+                       first = mp->hghmsg;
+               for(last = first; last >= mp->lowmsg && last <= mp->hghmsg;
+                                               last += convdir)
+                       if(mp->msgstats[last]&EXISTS)
+                               if(--range <= 0)
+                                       break;
+               if(last < mp->lowmsg)
+                       last = mp->lowmsg;
+               if(last > mp->hghmsg)
+                       last = mp->hghmsg;
+               if(last < first) {
+                       range = last; last = first; first = range;
+               }
+       } else {
+               if(first > mp->hghmsg || first < mp->lowmsg ||
+                  !(mp->msgstats[first]&EXISTS)) {
+                       fprintf(stderr, "Message %d doesn't exist.\n", first);
+                       return(0);
+               }
+               last = first;
+       }
+       while(first <= last) {
+               if(mp->msgstats[first]&EXISTS) {
+                       if(!(mp->msgstats[first]&SELECTED)) {
+                               mp->numsel++;
+                               mp->msgstats[first] |= SELECTED;
+                               if(first < mp->lowsel)
+                                       mp->lowsel = first;
+                               if(first > mp->hghsel)
+                                       mp->hghsel = first;
+                       }
+                       found++;
+               }
+               first++;
+       }
+       if(!found)
+               goto rangerr;
+       return(1);
+}
+
+m_conv(str)
+char *str;
+{
+       register char *cp, *bp;
+       register int i;
+       char buf[16];
+
+       convdir = 1;
+       cp = bp = str;
+       if(*cp >= '0' && *cp <= '9')  {
+               while(*bp >= '0' && *bp <= '9') bp++;
+               delimp = bp;
+               return(atoi(cp));
+       }
+       bp = buf;
+       while((*cp >= 'a' && *cp <= 'z') || *cp == '.')
+               *bp++ = *cp++;
+       *bp++ = 0;
+       delimp = cp;
+       if(strcmp(buf, "first") == 0)
+               return(mp->lowmsg);
+       else if(strcmp(buf, "last") == 0) {
+               convdir = -1;
+               return(mp->hghmsg);
+       } else if(strcmp(buf, "cur") == 0 || strcmp(buf, ".") == 0)
+               return(mp->curmsg > 0 ? mp->curmsg : -1);
+       else if(strcmp(buf, "prev") == 0) {
+               convdir = -1;
+               for(i = (mp->curmsg<=mp->hghmsg)? mp->curmsg-1: mp->hghmsg;
+                   i >= mp->lowmsg; i--) {
+                       if(mp->msgstats[i]&EXISTS)
+                               return(i);
+               }
+               return(-1);                     /* non-existent message */
+       } else if(strcmp(buf, "next") == 0)  {
+               for(i = (mp->curmsg>=mp->lowmsg)? mp->curmsg+1: mp->lowmsg;
+                   i <= mp->hghmsg; i++) {
+                       if(mp->msgstats[i]&EXISTS)
+                               return(i);
+               }
+               return(-1);
+       } else
+               return(0);                     /* bad message list */
+}
diff --git a/docs/historical/mh-nov-1983/subs/m_delete.c b/docs/historical/mh-nov-1983/subs/m_delete.c
new file mode 100644 (file)
index 0000000..b1732bf
--- /dev/null
@@ -0,0 +1,22 @@
+#include "mh.h"
+
+m_delete(key)
+char *key;
+{
+       register struct node *np, *npprev;
+
+       m_getdefs();
+       for(np = (struct node *) &m_defs; npprev = np; )  {
+               if((np = np->n_next) == 0)
+                       break;
+               if(uleq(np->n_name, key)) {
+                       npprev->n_next = np->n_next;
+                       cndfree(np->n_name);
+                       cndfree(np->n_field);
+                       free(np);
+                       def_flags |= DEFMOD;
+                       return(0);
+               }
+       }
+       return(1);
+}
diff --git a/docs/historical/mh-nov-1983/subs/m_edit.c b/docs/historical/mh-nov-1983/subs/m_edit.c
new file mode 100644 (file)
index 0000000..13b470a
--- /dev/null
@@ -0,0 +1,94 @@
+#include "mh.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <signal.h>
+#include <stdio.h>
+#include "strings.h"
+
+struct msgs *mp;
+
+char *rindex();
+
+m_edit(ed, file, use, altmsg)
+char **ed, *file, *altmsg;
+int use;
+{
+       /* Exec editor.  Normal exit returns 0.
+        * To abort, returns -1.  To try again, returns -2
+        */
+
+       static char *edsave;
+       static int  reedit;
+       struct stat stbuf;
+       int retstat;
+       register char *cp;
+       int pid, wpid;
+       int intr;
+       union { int statint;
+               struct {char lobyte, hibyte;} statby;
+       } status;
+
+       if(!reedit) {                   /* set initial editor */
+               if(!*ed && (*ed = m_find("editor")) == NULL)
+                       *ed = sysed;
+       } else
+               if(!*ed) {              /* no explicit editor */
+                       *ed = edsave;
+                       cp = rindex(*ed, '/');
+                       if(cp == 0)
+                               cp = *ed;
+                       cp = concat(cp, "-next", 0);
+                       if((cp = m_find(cp)) != NULL)
+                               *ed = cp;
+               }
+       intr = (int) signal(SIGINT, SIG_IGN);
+       if((pid = fork()) == 0) {
+               if(altmsg) {
+                       unlink("@");
+                       link(altmsg, "@");    /* An easy handle on cur msg */
+               }
+               m_update();
+               fflush(stdout);
+               signal(SIGINT, (int (*)()) intr);
+               execlp(*ed, *ed, file, 0);
+               fprintf(stderr, "Can't exec the editor:  ");
+               perror(*ed);  done(-1);
+       } else if(pid == -1) {
+               fprintf(stderr, "No forks!\n");
+               retstat = -1;
+               goto leave;
+       } else
+               while((wpid = wait(&status)) != -1 && wpid != pid) ;
+       signal(SIGINT, (int (*)()) intr);
+       if(status.statint) {
+               if((status.statby.hibyte == -1) ||      /* Can't exec editor */
+                  (reedit && !status.statby.lobyte)) { /*2nd edit.Aborted by user*/
+                       retstat = -2;
+                       goto leave;
+               }
+               fprintf(stderr, "[%s aborted--%s ", invo_name(), file);
+               if(!use && status.statby.hibyte) {      /* edit aborted by user */
+                       unlink(file);
+                       fprintf(stderr, "deleted]\n");
+               } else                          /* 'use' or system abort */
+                       fprintf(stderr, "preserved]\n");
+               retstat = -2;
+               goto leave;
+       }
+       reedit++;
+       retstat = 0;
+       if(altmsg && !mp->msgflags&READONLY) {
+               stat("@", &stbuf);
+               if(stbuf.st_nlink == 1)  /*@'s been edited by Ned*/
+                       if(unlink(altmsg) == -1 || link("@", altmsg) == -1){
+                               fprintf(stderr, "Can't update %s from @ file!\n",altmsg);
+                               retstat = 0;
+                               goto leave;
+                       }
+       }
+ leave:
+       edsave = getcpy(*ed);
+       *ed = 0;
+       unlink("@");          /* Remove this extra link */
+       return(retstat);
+}
diff --git a/docs/historical/mh-nov-1983/subs/m_find.c b/docs/historical/mh-nov-1983/subs/m_find.c
new file mode 100644 (file)
index 0000000..26743a0
--- /dev/null
@@ -0,0 +1,13 @@
+#include "mh.h"
+#include <stdio.h>
+
+char *m_find(str)
+{
+       register struct node *n;
+
+       m_getdefs();
+       for(n = m_defs; n; n = n->n_next)
+               if(uleq(n->n_name, str))
+                       return(n->n_field);
+       return(NULL);
+}
diff --git a/docs/historical/mh-nov-1983/subs/m_getdefs.c b/docs/historical/mh-nov-1983/subs/m_getdefs.c
new file mode 100644 (file)
index 0000000..35eb085
--- /dev/null
@@ -0,0 +1,90 @@
+#include "mh.h"
+#include <stdio.h>
+
+char    defpath[128];
+
+struct procs {
+       char    *procname;
+       char    **procnaddr;
+} procs [] = {
+       { "lsproc",     &lsproc         },
+       { "mh_deliver", &mh_deliver     },
+       { "prproc",     &prproc         },
+       { "scanproc",   &scanproc       },
+       { "showproc",   &showproc       },
+       { "sendproc",   &sendproc       },
+       { "fileproc",   &fileproc       },
+       { 0,            0               },
+};
+
+m_getdefs()
+{
+       register struct node *np;
+       register int state, wpid, pid;
+       register struct procs *ps;
+       int status;
+       FILE *ib;
+       char name[NAMESZ], field[128];
+
+       if(defpath[0])
+               return;         /* We've already been called!   */
+       if(!mypath)
+               if((mypath = getenv("HOME")) == NULL) {
+                       fprintf(stderr, "HOME environment variable not set!\n");
+                       done(1);
+               }
+       sprintf(defpath, "%s%s", mypath, mh_prof);
+/***    copy(mh_prof, copy(mypath, defpath));           ***/
+
+       if((ib = fopen(defpath, "r")) == NULL) {
+               if((pid = fork()) == 0) {
+                       execl(installproc, "install-mh", "-auto", 0);
+                       fprintf(stderr, "Can't exec ");perror(installproc);
+                       done(1);
+               } else if(pid == -1) {
+                       fprintf(stderr, "No forks!\n");
+                       done(1);
+               } else
+                       while((wpid = wait(&status)) != -1 && wpid != pid)
+                               ;
+               if(status || (ib = fopen(defpath, "r")) == NULL) {
+                       fprintf(stderr, "[install-mh aborted]\n");
+                       done(1);
+               }
+       }
+
+#ifdef NEWS                     /* NOT CONVERTED TO V7!!! */
+       fstat(fildes(ib), field);
+       deftime = (&field)->i_atime;
+#endif
+
+       np = (struct node *) &m_defs;
+       state = FLD;
+    for(;;)
+       switch(state = m_getfld(state,name,field,sizeof field,ib)) {
+       case FLD:
+       case FLDEOF:
+               np->n_next = (struct node *) malloc(sizeof *np);
+               np = np->n_next;
+               np->n_name = getcpy(name);
+               np->n_field = trimcpy(field);
+               np->n_next = 0;
+               for(ps = procs; ps->procname; ps++)
+                       if(strcmp(np->n_name, ps->procname) == 0) {
+                               *ps->procnaddr = np->n_field;
+                               break;
+                       }
+               if(state == FLDEOF) {
+                       fclose(ib);
+                       return(0);
+               }
+               continue;
+       case BODY:
+       case BODYEOF:
+               fprintf(stderr, ".mh_profile must not contain a body--it can't \
+end with a blank line!\n");
+       default:
+               fprintf(stderr, "Bad format: .mh_profile!\n");
+               done(1);
+       }
+}
diff --git a/docs/historical/mh-nov-1983/subs/m_getfld.c b/docs/historical/mh-nov-1983/subs/m_getfld.c
new file mode 100644 (file)
index 0000000..27c3300
--- /dev/null
@@ -0,0 +1,87 @@
+#include "mh.h"
+#include <stdio.h>
+
+int     m_fldsz;
+
+m_getfld(state, name, buf, bufsz, iob)
+int state, bufsz;
+char *name, *buf;
+FILE *iob;
+{
+       register char *cp;
+       register c;
+
+ top:   while((c = getc(iob)) == '\001' && peekc(iob) == '\001')
+               while(getc(iob) != '\n');
+
+       if(c < 0)
+               return(FILEEOF);
+       m_fldsz = 0;
+
+       switch(state) {
+
+       case FLDEOF:
+       case BODYEOF:
+       case FLD:
+               if(c == '\n' || c == '-')
+                       goto body;
+               cp = name;
+               for(;;) {
+                       if(cp >= name+NAMESZ-1) {
+                               *cp = 0;
+fprintf(stderr, "??Component Name Exceeds %d Chars:\n    \"%s\"\n", NAMESZ-1, name);
+                               return(LENERR);
+                       }
+                       if(c == ':')
+                               break;
+                       if(c == '\n' || c < 0) {
+                               *cp = 0;
+fprintf(stderr, "??%s Encountered While Scanning for a colon:\n    \"%s\"\n",
+       (c < 0)? "<eof>":"<end of line>", name);
+                               return(FMTERR);
+                       }
+                       *cp++ = c;
+                       *cp   = 0;
+                       c = getc(iob);
+               }
+
+       case FLDPLUS:
+               cp = buf;
+               for(;;) {
+                       if((c = getc(iob)) < 0)
+                               return(FLDEOF);
+                       *cp++ = c;
+                       *cp   = 0;
+                       m_fldsz++;
+                       if(c == '\n')
+                               if((c = peekc(iob)) != ' ' && c != '\t')
+                                       if(c == '\001' || c < 0)
+                                               return(FLDEOF);
+                                       else
+                                               return(FLD);
+                       if(cp >= buf+bufsz-1)
+                               return(peekc(iob) < 0? FLDEOF:FLDPLUS);
+               }
+
+       body:   if(c == '-')
+                       while(getc(iob) != '\n') ;
+               buf[0] = 0;
+               if((c = getc(iob)) == '\001' && peekc(iob) == '\001')
+                       return(BODYEOF);
+
+       case BODY:
+               cp = buf;  *cp = 0;
+               for(;;) {
+                       if(c < 0 || (c == '\001' && peekc(iob) == '\001'))
+                               return(BODYEOF);
+                       *cp++ = c;
+                       *cp   = 0;
+                       m_fldsz++;
+                       if(cp >= buf+bufsz-1)
+                               return(((c=peekc(iob))<0||c=='\001')?
+                                       BODYEOF: BODY);
+                       c = getc(iob);
+               }
+
+       }
+}
diff --git a/docs/historical/mh-nov-1983/subs/m_getfolder.c b/docs/historical/mh-nov-1983/subs/m_getfolder.c
new file mode 100644 (file)
index 0000000..9f86bf6
--- /dev/null
@@ -0,0 +1,12 @@
+#include "mh.h"
+#include <stdio.h>
+
+char *m_getfolder()
+{
+       register char *folder;
+
+       m_getdefs();
+       if((folder = m_find(pfolder)) == NULL || *folder == 0)
+               folder = defalt;
+       return(folder);
+}
diff --git a/docs/historical/mh-nov-1983/subs/m_gmprot.c b/docs/historical/mh-nov-1983/subs/m_gmprot.c
new file mode 100644 (file)
index 0000000..3430259
--- /dev/null
@@ -0,0 +1,14 @@
+#include "mh.h"
+#include <stdio.h>
+
+m_gmprot()
+{
+       register char *cp;
+       register int prot;
+
+       if((cp = m_find("msg-protect")) != NULL)
+               prot = atooi(cp);
+       else
+               prot = atooi(msgprot);
+       return(prot);
+}
diff --git a/docs/historical/mh-nov-1983/subs/m_gmsg.c b/docs/historical/mh-nov-1983/subs/m_gmsg.c
new file mode 100644 (file)
index 0000000..20f220a
--- /dev/null
@@ -0,0 +1,122 @@
+#include "mh.h"
+#include <stdio.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/dir.h>
+
+struct  msgs *mp;
+
+struct msgs *m_gmsg(name)
+char *name;
+{
+       register int i, j;
+       register char *cp;
+       register struct msgs *msgp;
+       register struct direct *dir;
+       DIR *dirp;
+       int  curfil;
+       struct stat statb;
+       char buf[132];
+
+       struct {
+               int xhghmsg,
+                   xnummsg,
+                   xlowmsg,
+                   xcurmsg;
+               char xselist,
+                    xflags,
+                    xfiller,
+                    xothers;
+               char xmsgs[1000];
+       } msgbuf;
+
+       if ((dirp = opendir(".")) == 0)
+               return (0);
+       for(j = 0; j < 1000; j++)
+               msgbuf.xmsgs[j] = 0;
+       msgbuf.xcurmsg = 0;
+       msgbuf.xnummsg = 0;
+       msgbuf.xselist = 0;
+       msgbuf.xothers = 0;
+       msgbuf.xlowmsg = 5000;
+       msgbuf.xhghmsg = 0;
+       msgbuf.xflags  = (access(".",2) == -1)? READONLY:0;
+
+       /*
+        * The following hack is that if the directory is writable
+        * and the cur file is not, we consider it to be read only
+        * folder.
+        */
+
+       if (stat("cur", &statb) >= 0 && access("cur", 2) < 0)
+               msgbuf.xflags |= READONLY;
+       curfil = 0;
+       while (dir = readdir(dirp)) {
+               cp = dir->d_name;
+               if (j = mu_atoi(cp)) {
+                       if (j > msgbuf.xhghmsg)
+                               msgbuf.xhghmsg = j;
+                       msgbuf.xnummsg++;
+                       if (j < msgbuf.xlowmsg)
+                               msgbuf.xlowmsg = j;
+                       msgbuf.xmsgs[j] = EXISTS;
+               } else if (*cp != ',' && *cp != '.' && *cp != '#')
+                       if (strcmp(cp, current) == 0)
+                               curfil++;
+                       else if (strcmp(cp, listname) == 0)
+                               msgbuf.xselist++;
+                       else
+                               msgbuf.xothers++;
+       }
+       if(!msgbuf.xhghmsg)
+               msgbuf.xlowmsg = 0;
+       closedir(dirp);
+       if(msgbuf.xflags&READONLY) {
+               sprintf(buf, "cur-%s", name);
+/***            copy(name, copy("cur-", buf));          ***/
+               if((cp = m_find(buf)) != NULL)
+                       if(j = mu_atoi(cp))
+                               msgbuf.xcurmsg = j;
+       } else if(curfil && (i = open(current, 0)) >= 0) {
+               if((j = read(i, buf, sizeof (buf))) >= 2) {
+                       buf[j-1] = '\0';    /* Zap <lf> */
+                       if (j = mu_atoi(buf))
+                               msgbuf.xcurmsg = j;
+               }
+               close(i);
+       }
+       if( (int) (msgp = (struct msgs *) malloc(sizeof *mp + msgbuf.xhghmsg + 2)) == -1)
+               return(0);
+       msgp->hghmsg   = msgbuf.xhghmsg;
+       msgp->nummsg   = msgbuf.xnummsg;
+       msgp->lowmsg   = msgbuf.xlowmsg;
+       msgp->curmsg   = msgbuf.xcurmsg;
+       msgp->selist   = msgbuf.xselist;
+       msgp->msgflags = msgbuf.xflags;
+       msgp->others   = msgbuf.xothers;
+       msgp->foldpath = name;
+       msgp->lowsel   = 5000;
+       msgp->hghsel   = 0;
+       msgp->numsel   = 0;
+       for(j = 0; j <= msgbuf.xhghmsg; j++)
+               msgp->msgstats[j] = msgbuf.xmsgs[j];
+       return(msgp);
+}
+
+
+mu_atoi(str)
+char *str;
+{
+       register char *cp;
+       register int i;
+
+       i = 0;
+       cp = str;
+       while(*cp) {
+               if(*cp < '0' || *cp > '9' || i > 99)
+                       return(0);
+               i *= 10;
+               i += *cp++ - '0';
+       }
+       return(i);
+}
diff --git a/docs/historical/mh-nov-1983/subs/m_maildir.c b/docs/historical/mh-nov-1983/subs/m_maildir.c
new file mode 100644 (file)
index 0000000..a64ef75
--- /dev/null
@@ -0,0 +1,29 @@
+#include "mh.h"
+#include <stdio.h>
+
+char *mypath;
+
+char *m_maildir(folder)
+char *folder;
+{
+       register char *fold, *path, *cp;
+       static char mailfold[128];
+
+       m_getdefs();
+       if(!(fold = folder))
+               fold = m_getfolder();
+       if(*fold == '/' || *fold == '.')
+               return(fold);
+       cp = mailfold;
+       if((path = m_find("path")) != NULL && *path) {
+               if(*path != '/') {
+                       sprintf(cp, "%s/", mypath);
+                       cp += strlen(cp);
+               }
+               cp = copy(path, cp);
+               if(cp[-1] != '/')
+                       *cp++ = '/';
+       }
+       strcpy(cp, fold);
+       return(mailfold);
+}
diff --git a/docs/historical/mh-nov-1983/subs/m_name.c b/docs/historical/mh-nov-1983/subs/m_name.c
new file mode 100644 (file)
index 0000000..c8880af
--- /dev/null
@@ -0,0 +1,21 @@
+char *m_name(num)
+{
+       static char name[4];
+       register char *cp;
+       register int i;
+
+       name[0] = 0;
+       name[1] = 0;
+       name[2] = 0;
+       name[3] = 0;
+       i = num;
+       cp = &name[3];
+       if(i > 0 && i < 1000)
+               do {
+                       *--cp = (i % 10) + '0';
+                       i /= 10;
+               } while(i);
+       else
+               *--cp = '?';
+       return(cp);
+}
diff --git a/docs/historical/mh-nov-1983/subs/m_replace.c b/docs/historical/mh-nov-1983/subs/m_replace.c
new file mode 100644 (file)
index 0000000..4d6496d
--- /dev/null
@@ -0,0 +1,29 @@
+#include "mh.h"
+
+
+m_replace(key,value)
+char *key, *value;
+
+{
+       register struct node *np;
+
+       m_getdefs();
+       for(np = m_defs; ; np = np->n_next) {
+               if(uleq(np->n_name, key)) {
+                       if(strcmp(value, np->n_field) != 0) {
+                               cndfree(np->n_field);
+                               np->n_field = value;
+                               def_flags |= DEFMOD;
+                       }
+                       return;
+               }
+               if(!np->n_next)
+                       break;
+       }
+       np->n_next = (struct node *) malloc(sizeof *np);
+       np = np->n_next;
+       np->n_name = getcpy(key);
+       np->n_next = 0;
+       np->n_field = value;
+       def_flags |= DEFMOD;
+}
diff --git a/docs/historical/mh-nov-1983/subs/m_send.c b/docs/historical/mh-nov-1983/subs/m_send.c
new file mode 100644 (file)
index 0000000..22ca0a7
--- /dev/null
@@ -0,0 +1,22 @@
+#include "mh.h"
+#include <stdio.h>
+
+m_send(arg, file)
+char *arg, *file;
+{
+       char *vec[10];
+       int ivec;
+
+       ivec = 0;
+       vec[ivec++] = "send";
+       vec[ivec++] = file;
+       if(*arg == 'v')
+               vec[ivec++] = "-verbose";
+       vec[ivec++] = 0;
+       m_update();
+       fflush(stdout);
+       execv(sendproc, vec);
+       fprintf(stderr, "Can't exec %s.\n", sendproc);
+       return(0);
+
+}
diff --git a/docs/historical/mh-nov-1983/subs/m_setcur.c b/docs/historical/mh-nov-1983/subs/m_setcur.c
new file mode 100644 (file)
index 0000000..e625149
--- /dev/null
@@ -0,0 +1,26 @@
+#include "mh.h"
+#include <stdio.h>
+
+struct  msgs *mp;
+
+m_setcur(num)
+{
+       char buf[6];
+       register int i;
+       register char *cp1;
+
+       if(mp->msgflags&READONLY) {
+               m_replace(cp1 = concat("cur-",mp->foldpath,0), m_name(num));
+               free(cp1);
+       } else {
+               strcpy(buf, m_name(num));
+               cp1 = buf + strlen(buf);
+               *cp1++ = '\n';
+               if(strcmp(current, "cur"))
+                       error("\"current\" got Clobbered!! Tell B. Borden");
+               if((i = creat(current, 0660)) >= 0) {
+                       write(i, buf, cp1-buf);
+                       close(i);
+               }
+       }
+}
diff --git a/docs/historical/mh-nov-1983/subs/m_update.c b/docs/historical/mh-nov-1983/subs/m_update.c
new file mode 100644 (file)
index 0000000..c2ea049
--- /dev/null
@@ -0,0 +1,25 @@
+#include "mh.h"
+#include <stdio.h>
+#include <signal.h>
+
+char    defpath[];
+
+m_update()
+{
+       FILE *out;
+       register struct node *np;
+       int save;
+
+       if(def_flags & DEFMOD) {
+               save = (int) signal(SIGINT, SIG_IGN);
+               if((out = fopen(defpath, "w")) == NULL) {
+                       fprintf(stderr, "Can't create %s!!\n", defpath);
+                       done(1);
+               }
+               for(np = m_defs; np; np = np->n_next)
+                       fprintf(out, "%s: %s\n", np->n_name, np->n_field);
+               fclose(out);
+               signal(SIGINT, (int (*)()) save);
+               def_flags &= ~DEFMOD;
+       }
+}
diff --git a/docs/historical/mh-nov-1983/subs/makedir.c b/docs/historical/mh-nov-1983/subs/makedir.c
new file mode 100644 (file)
index 0000000..7f9c927
--- /dev/null
@@ -0,0 +1,28 @@
+#include "mh.h"
+#include <stdio.h>
+
+makedir(dir)
+{
+       register int i, pid, wpid;
+       register char *c;
+       int status;
+
+       if((pid = fork()) == 0) {
+               execl("/bin/mkdir", "mkdir", dir, 0);
+               execl("/usr/bin/mkdir", "mkdir", dir, 0);
+               fprintf(stderr, "Can't exec mkdir!!?\n");
+               return(0);
+       }
+       if(pid == -1) {
+               fprintf(stderr, "Can't fork\n");
+               return(0);
+       }
+       while((wpid = wait(&status)) != pid && wpid != -1) ;
+       if(status) {
+               fprintf(stderr, "Bad exit status (%o) from mkdir.\n", status);
+               return(0);
+       }
+       chmod(dir, ((c = m_find("folder-protect")) != NULL)?
+                  atooi(c) : atooi(foldprot));
+       return(1);
+}
diff --git a/docs/historical/mh-nov-1983/subs/makename.c b/docs/historical/mh-nov-1983/subs/makename.c
new file mode 100644 (file)
index 0000000..027c4d8
--- /dev/null
@@ -0,0 +1,19 @@
+#include "mh.h"
+#include <stdio.h>
+
+char *makename(prefix,suffix)
+char *prefix, *suffix;
+{
+       static char tmpname[15];
+       register char *cp1, *cp2;
+       register int pid;
+
+       pid = getpid();
+       cp1 = tmpname;
+       for (cp2 = prefix; *cp1++ = *cp2++; );
+       cp1--;
+       do *cp1++ = pid%10 + '0'; while (pid /= 10);
+       for (cp2 = suffix; *cp1++ = *cp2++; );
+       if (cp1 >= &tmpname[15]) error("strs too long to makename");
+       return (tmpname);
+}
diff --git a/docs/historical/mh-nov-1983/subs/mh.h b/docs/historical/mh-nov-1983/subs/mh.h
new file mode 100644 (file)
index 0000000..9ba122a
--- /dev/null
@@ -0,0 +1,154 @@
+#define ALL ""
+
+#define MAXARGS 1000    /* Max messages to exec                 */
+
+#define EXISTS    01    /* Flag bits in msgstats-- Deleted is   */
+#define DELETED   02    /*      undefined currently             */
+#define SELECTED  04    /* Message selected by an arg           */
+
+#define READONLY  01    /* No write access to folder            */
+#define DEFMOD    01    /* In-core profile has been modified    */
+
+/*#define NEWS     1    /* Define for news inclusion            */
+
+struct  swit {
+       char *sw;
+       int minchars;
+};
+
+/*
+ * m_gmsg() returns this structure.  It contains the per folder
+ * information which is obtained from reading the folder directory.
+ */
+
+struct  msgs {
+       int     hghmsg;         /* Highest msg in directory     */
+       int     nummsg;         /* Actual Number of msgs        */
+       int     lowmsg;         /* Lowest msg number            */
+       int     curmsg;         /* Number of current msg if any */
+       int     lowsel;         /* Lowest selected msg number   */
+       int     hghsel;         /* Highest selected msg number  */
+       int     numsel;         /* Number of msgs selected      */
+       char   *foldpath;       /* Pathname of folder           */
+       char    selist,         /* Folder has a "select" file   */
+               msgflags,       /* Folder status bits           */
+               filler,
+               others;         /* Folder has other file(s)     */
+       char    msgstats[1];    /* Stat bytes for each msg      */
+};
+
+               /* m_getfld definitions and return values       */
+
+#define NAMESZ  64      /* Limit on component name size         */
+#define LENERR  -2      /* Name too long error from getfld      */
+#define FMTERR  -3      /* Message Format error                 */
+
+                       /* m_getfld return codes                */
+#define FLD      0      /* Field returned                       */
+#define FLDPLUS  1      /* Field " with more to come            */
+#define FLDEOF   2      /* Field " ending at eom                */
+#define BODY     3      /* Body  " with more to come            */
+#define BODYEOF  4      /* Body  " ending at eom                */
+#define FILEEOF  5      /* Reached end of input file            */
+
+/*
+ * These standard strings are defined in strings.a.  They are the
+ * only system-dependent parameters in MH, and thus by redefining
+ * their values and reloading the various modules, MH will run
+ * on any system.
+ */
+
+char
+       *components,    /* Name of user's component file (in mh dir) */
+       *current,       /* Name of current msg file in a folder */
+       *defalt,        /* Name of the std folder (inbox)       */
+       *distcomps,     /* Name of `dist' components file       */
+       *draft,         /* Name of the normal draft file        */
+       *fileproc,      /* Path of file program                 */
+       *foldprot,      /* Default folder protection            */
+       *hostname,      /* Local net host name                  */
+       *installproc,   /* Name of auto-install program path    */
+       *listname,      /* Default selection list folder name   */
+       *lockdir,       /* Dir for lock files (Same fs as mailboxes)*/
+       *lsproc,        /* Path of the Harvard ls program       */
+       *mailboxes,     /* Incoming mail directory              */
+       *mh_prof,       /* Name of users profile file           */
+       *mh_deliver,    /* Name of deliverer for mh             */
+       *mhnews,        /* Name of MH news file                 */
+       *msgprot,       /* Default message protection (s.a. 0664) */
+       *pfolder,       /* Name of current folder profile entry */
+       *prproc,        /* Path of the pr program               */
+       *scanproc,      /* Path of the scan program             */
+       *showproc,      /* Path of the type (l) program         */
+       *sendproc,      /* Path of the send message program     */
+       *stdcomps,      /* Std comp file if missing user's own  */
+       *stddcomps,     /* Std dist file if missing user's own  */
+       *sysed,         /* Path of the std (ned) editor         */
+/* Just about every program uses this also                      */
+       *mypath;        /* User's log-on path                   */
+
+#ifdef UNIXCOMP
+char *unixtomh;                /* Path of program to convert UNIX style
+                          mailboxes to MH style mailboxes */
+char *Mailprog;                /* Path of program to do actual mailing */
+char *localname;       /* Name of local machine on local net */
+#endif
+
+/*
+ * node structure used to hold a linked list of the users profile
+ * information taken from logpath/.mh_prof.
+ */
+
+struct node {
+       struct node *n_next;
+       char        *n_name,
+                   *n_field;
+} *m_defs;
+
+char  def_flags;
+
+
+/*
+ * The first char in the mhnews file indicates whether the program
+ * calling m_news() should continue running or halt.
+ */
+
+#define NEWSHALT        '!'     /* Halt after showing the news  */
+#define NEWSCONT        ' '     /* Continue  (ditto)            */
+#define NEWSPAUSE       '\001'  /* Pause during news output...  */
+
+
+/*
+ * Miscellaneous Defines to speed things up
+ */
+
+#define error(str) { fprintf(stderr, "%s\n", str); exit(-1); }
+
+/*
+ * Routine type declarations -- needed by version 7 compiler
+ */
+
+char **brkstring();
+char *m_maildir();
+char *m_find();
+char *m_name();
+char *concat();
+char *getcpy();
+char *trimcpy();
+char *add();
+char *invo_name();
+char **copyip();
+char *getcpy();
+char *m_getfolder();
+struct msgs *m_gmsg();
+char *copy();
+char **getans();
+char *cdate();
+char *makename();
+char *r1bindex();
+
+/*
+ * Routine type declarations -- SHOULD BE GLOBAL
+ */
+char *getenv();
+
diff --git a/docs/historical/mh-nov-1983/subs/peekc.c b/docs/historical/mh-nov-1983/subs/peekc.c
new file mode 100644 (file)
index 0000000..0f5cea0
--- /dev/null
@@ -0,0 +1,11 @@
+#include <stdio.h>
+
+peekc(ib)
+FILE *ib;
+{
+       register c;
+
+       c = getc(ib);
+       ungetc(c,ib);
+       return(c);
+}
diff --git a/docs/historical/mh-nov-1983/subs/pr_array.c b/docs/historical/mh-nov-1983/subs/pr_array.c
new file mode 100644 (file)
index 0000000..00fddab
--- /dev/null
@@ -0,0 +1,9 @@
+pr_array(cp,ap)
+char *cp,  **ap;
+{
+       register  int  i;
+
+       for(i=0;  *ap;  ap++,i++)
+               printf("%s[%d]=> %s\n", cp,i,*ap);
+}
+
diff --git a/docs/historical/mh-nov-1983/subs/printsw.c b/docs/historical/mh-nov-1983/subs/printsw.c
new file mode 100644 (file)
index 0000000..0b516e8
--- /dev/null
@@ -0,0 +1,26 @@
+#include "mh.h"
+
+printsw(substr, swp, prefix)
+char *substr, *prefix;
+struct swit *swp;
+{
+       char buf[128];
+       register char *cp, *cp1;
+       register int i;
+       int len;
+
+       len = strlen(substr);
+       for(; swp->sw; swp++)
+               if(!*substr ||                  /* null matches all strings */
+                  (ssequal(substr, swp->sw) && len >= swp->minchars))
+                       if(swp->minchars > 0) {
+                               cp = buf;
+                               *cp++ = '(';
+                               for(cp1 = swp->sw, i = 0; i < swp->minchars; i++)
+                                       *cp++ = *cp1++;
+                               *cp++ = ')';
+                               while(*cp++ = *cp1++);
+                               printf("  %s%s\n", prefix, buf);
+                       } else if(swp->minchars == 0)
+                               printf("  %s%s\n", prefix, swp->sw);
+}
diff --git a/docs/historical/mh-nov-1983/subs/putdate.c b/docs/historical/mh-nov-1983/subs/putdate.c
new file mode 100644 (file)
index 0000000..7a8fb3d
--- /dev/null
@@ -0,0 +1,65 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/timeb.h>
+#include <sys/time.h>
+
+/*
+ * Output the date in right format gotten from
+ * the passed ctime(3) format date.
+ * If the passed date is NULL, output the current
+ * date and time.
+ */
+
+putdate(timestr, out)
+       char *timestr;
+       register FILE *out;
+{
+       register char *t, *p, *cp;
+       char *timezone();
+       struct tm *tmp;
+       struct tm *localtime();
+       struct timeb tb;
+       long now;
+       int isdst;
+       char *asctime();
+       static char *str = "SunMonTueWedThuFriSat";
+       static char *daytag[] = {
+               "Sunday",
+               "Monday",
+               "Tuesday",
+               "Wednesday",
+               "Thursday",
+               "Friday",
+               "Saturday"
+       };
+
+       now = time((long *) 0);
+       tmp = localtime(&now);
+       isdst = tmp->tm_isdst;
+       if (timestr == 0)
+               timestr = asctime(tmp);
+       cp = str;
+       t = timestr;
+       while (*cp) {
+               if (strcmpn(cp, t, 3) == 0)
+                       break;
+               cp += 3;
+       }
+       if (*cp)
+               cp = daytag[(cp - str) / 3];
+       else
+               cp = 0;
+       ftime(&tb);
+       /*
+        * This call to timezone() may be wrong:
+        * really need the tm_isdst whoever generated timestr.
+        */
+       p = timezone(tb.timezone, isdst);
+
+       if (cp == 0)
+               fprintf(out, "Date: %.2s %.3s %.4s %.2s%.2s-%.3s\n",
+                            t+8, t+4, t+20, t+11, t+14, p);
+       else
+               fprintf(out, "Date: %.2s %.3s %.4s %.2s%.2s-%.3s (%s)\n",
+                            t+8, t+4, t+20, t+11, t+14, p, cp);
+}
diff --git a/docs/historical/mh-nov-1983/subs/r1bindex.c b/docs/historical/mh-nov-1983/subs/r1bindex.c
new file mode 100644 (file)
index 0000000..2aa5447
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+ * r1bindex(str, chr) stands for Right plus 1 or Beginning index of
+ *      chr in str.  I.e. return ptr 1 past LAST occurance of chr in
+ *      str, OR beginning of the string if str doesn't contain chr.
+ */
+
+char *
+r1bindex(str, chr)
+register char *str;
+register int chr;
+{
+       register char *cp;
+
+       for(cp = str; *cp; cp++) ;
+       --cp;
+       while(cp >= str && *cp != chr)
+               --cp;
+       return ++cp;
+}
diff --git a/docs/historical/mh-nov-1983/subs/showfile.c b/docs/historical/mh-nov-1983/subs/showfile.c
new file mode 100644 (file)
index 0000000..c75c138
--- /dev/null
@@ -0,0 +1,37 @@
+#include "mh.h"
+#include <signal.h>
+#include <stdio.h>
+
+showfile(file)
+char *file;
+{
+       int pid, wpid, intr, status;
+       char *vec[4];
+
+       intr = (int) signal(SIGINT, SIG_IGN);
+       m_update();
+       fflush(stdout);
+       if((pid = fork()) == 0) {
+               vec[0] = "mh-type";
+               vec[1] = file;
+               vec[2] = 0;
+               signal(SIGINT, (int (*)()) intr);
+               execv(showproc, vec);
+               perror("Can't exec showproc");
+               goto badleave;
+       } else if(pid == -1) {
+               fprintf(stderr, "No forks!\n");
+               goto badleave;
+       } else
+               while((wpid = wait(&status)) != -1 && wpid != pid) ;
+       signal(SIGINT, (int (*)()) intr);
+       if(status & 0377)
+               goto badleave;
+       return(0);
+
+ badleave:
+       fflush(stdout);
+       return(1);
+
+}
+
diff --git a/docs/historical/mh-nov-1983/subs/smatch.c b/docs/historical/mh-nov-1983/subs/smatch.c
new file mode 100644 (file)
index 0000000..aa4a2d3
--- /dev/null
@@ -0,0 +1,34 @@
+#include "mh.h"
+
+/* switch match, or any unambiguous abbreviation */
+/* exact match always wins, even if shares same root */
+/* returns subscript in zero-terminated tbl[] of strings */
+/* returns -1 if no match, -2 if ambiguous */
+
+#define abs(i) (i < 0 ? -i : i)
+
+smatch(string, swp)
+char *string;
+struct swit *swp;
+{
+       register char *sp, *tcp;
+       struct swit *tp;
+       int firstone, stringlen;
+
+       firstone = -1;
+
+       for (stringlen = strlen(string), tp = swp; tcp = tp->sw; tp++) {
+               if(stringlen < abs(tp->minchars)) continue;      /* no match */
+               for (sp = string; *sp == *tcp++; ) {
+                       if (*sp++ == 0) return(tp-swp); /* exact match */
+               }
+               if (*sp != 0) {
+                       if (*sp != ' ') continue; /* no match */
+                       if (*--tcp == 0) return(tp-swp); /* exact match */
+               }
+               if (firstone == -1) firstone = tp-swp; /* possible match */
+               else firstone = -2;     /* ambiguous */
+       }
+
+       return (firstone);
+}
diff --git a/docs/historical/mh-nov-1983/subs/ssequal.c b/docs/historical/mh-nov-1983/subs/ssequal.c
new file mode 100644 (file)
index 0000000..124581c
--- /dev/null
@@ -0,0 +1,8 @@
+ssequal(substr, str)
+char *substr, *str;
+{
+       while(*substr)
+               if(*substr++ != *str++)
+                       return(0);
+       return(1);
+}
diff --git a/docs/historical/mh-nov-1983/subs/trimcpy.c b/docs/historical/mh-nov-1983/subs/trimcpy.c
new file mode 100644 (file)
index 0000000..eb7d5fe
--- /dev/null
@@ -0,0 +1,16 @@
+char *trimcpy(cp)
+register char *cp;
+{
+       register char *sp;
+
+       while(*cp == ' ' || *cp == '\t')
+               cp++;
+       sp = cp;
+       while(*sp)
+               if(*sp++ == '\n')
+                       break;
+       *--sp = 0;
+       sp = (char *) malloc(sp - cp + 1);
+       strcpy(sp, cp);
+       return(sp);
+}
diff --git a/docs/historical/mh-nov-1983/subs/type.c b/docs/historical/mh-nov-1983/subs/type.c
new file mode 100644 (file)
index 0000000..31c800b
--- /dev/null
@@ -0,0 +1,10 @@
+type(ch, s)
+char *s;
+{
+       register char *p;
+
+       for (p = s; *p++; );
+       --p;
+       write(ch, s, p-s);
+       return(p-s);
+}
diff --git a/docs/historical/mh-nov-1983/subs/uleq.c b/docs/historical/mh-nov-1983/subs/uleq.c
new file mode 100644 (file)
index 0000000..663adcd
--- /dev/null
@@ -0,0 +1,12 @@
+uleq(c1, c2)
+register char *c1, *c2;
+{
+       register int c;
+
+       while(c = *c1++)
+               if((c|040) != (*c2|040))
+                       return(0);
+               else
+                       c2++;
+       return(*c2 == 0);
+}
diff --git a/docs/historical/mh-nov-1983/support/components b/docs/historical/mh-nov-1983/support/components
new file mode 100644 (file)
index 0000000..657e5dd
--- /dev/null
@@ -0,0 +1,4 @@
+To: 
+Cc: 
+Subject: 
+-------
diff --git a/docs/historical/mh-nov-1983/support/distcomps b/docs/historical/mh-nov-1983/support/distcomps
new file mode 100644 (file)
index 0000000..b3415f9
--- /dev/null
@@ -0,0 +1,2 @@
+Distribution-to:
+Distribution-cc:
diff --git a/docs/historical/mh-nov-1983/support/l.c b/docs/historical/mh-nov-1983/support/l.c
new file mode 100644 (file)
index 0000000..2f7b8d2
--- /dev/null
@@ -0,0 +1,259 @@
+/* Rewrite for VAX: BSB 9/9/79 */
+/* Compiled with V7 cc: BSB 6/2/79 */
+
+#include <stdio.h>
+#include <sgtty.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <sys/types.h>
+#include <stat.h>
+
+#define CLEARPAGE write(2,"\014\000",2);
+#define PAUSE  0
+#define NOTIFY 1
+#define CLEAR  2
+#define NOTICLEAR 3
+
+int spage = 37;
+int page;
+short int width = 79;
+short int noclr = 0;
+short int first = 0;
+short int numop = 0;
+short int flagctl = 1;
+short int ontty = 1;    /* assume we're outputting to a tty     */
+short int delflg;       /* a <DEL> was typed.                   */
+
+FILE *fin;
+jmp_buf envir;
+
+main(argc, argv)
+int argc;
+char *argv[];
+{
+       register int i,k,n;
+       register char *c1, *c2;
+       int j, clrflag;
+       int int2(), getout();
+       struct sgttyb sg;
+       struct stat st;
+       extern char _sibuf[], _sobuf[];
+
+       if(gtty(1, &sg) == -1) {
+               ontty = 0;
+               flagctl = 0;
+       }
+       c1 = c2 = argv[0];
+       do
+               if(*c1++ == '/')
+                       c2 = c1;
+       while(*c1);
+       if(*c2 == 'c')
+               noclr++;
+       k=0;
+       for( i=1; i<argc; i++ ) {/* look for - args */
+               if(argv[i][0] == '-' ) {
+                       switch( argv[i][1] ) {
+                               case 'c': noclr++; break;
+                               case 'f': first=num(&argv[i][2]); /* set first line */
+                                         break;
+                               case 'n': numop=1; /* set number option */
+                                         break;
+                               case 'l':
+                               case 'p': spage =num(&argv[i][2]); /* set page size */
+                                         break;
+                               case 'w': width =num(&argv[i][2]);
+                                         break;
+                               case 'x': flagctl = flagctl? 0 : 1;
+                                         break;
+                               default:  printf("Unknown switch: %s\n", argv[i]);
+                                         return;
+                       }
+               } else
+                       argv[k++] = argv[i];
+       }
+
+       if (spage<=0)
+               spage = 0x07fffffff;    /* largest positive number! */
+       setbuf(stdout, _sobuf);
+       if(ontty)
+               signal(SIGINT,int2);
+       signal(SIGQUIT,getout);
+       page = spage;
+       if(k == 0) {                    /* filter */
+               if(!setjmp(envir)) {
+                       fin = stdin;
+                       setbuf(fin, _sibuf);
+                       pfile(0);
+               }
+               getout();
+       }
+       j = 0;
+       setjmp(envir);
+       while((i=j++) < k) {
+               page = spage;
+               clrflag = 0;
+               if(fin != NULL) { fclose(fin); fin = NULL; }
+               if(stat(argv[i], &st) == 0 && (st.st_mode&S_IFMT) == S_IFDIR){
+                       printf("%s: Is a directory!\n", argv[i]);
+                       continue;
+               }
+               if((fin = fopen(argv[i],"r")) == NULL) {
+                       printf("Cannot open \"%s\" for reading!\n", argv[i]);
+                       continue;
+               }
+               if(st.st_size == 0) {
+                       printf("File \"%s\" is empty.\n", argv[i]);
+                       continue;
+               }
+               if(k>1) {
+                   if(i && delflg <= 0)
+                       printf("\n\n");
+                   delflg = 0;
+                   if(ontty) {
+                       printf("Press <RETURN> to list \"%s\"\n", argv[i]);
+                       clrflag = 1;
+                   } else
+                       printf(">>>>> File \"%s\"\n", argv[i]);
+               }
+
+               pfile(clrflag);
+       }
+       getout();
+}
+
+int  linpos, line, ct;
+
+pfile(flg)
+{
+       register int c;
+
+       if(flg) nextpage(NOTICLEAR);
+       else if(!noclr && ontty)
+               CLEARPAGE;
+       delflg = -1;
+       line = 1;
+       ct = page;
+       while (line < first)  /* Dcrocker: skip to first line */
+               if((c = getch()) == EOF)
+                       return;
+               else if(c == '\n')
+                       line++;
+       linpos = 0;
+
+       while ((c = getch()) != EOF)
+               putch(c);
+
+       fflush(stdout);
+}
+
+num(s)  /* computes the internal form of a number */
+register char *s;       /* bad chars are ignored */
+{
+       register int c, i, sign;
+
+       sign=1;  i=0;
+       while(c = *s++) {
+               if(c=='-' && sign==1) sign = -1;
+               c -= '0';
+               if(c>=0 && c<=9) i=i*10+c;
+       }
+       return(i*sign);
+}
+
+nextpage (clearpage)
+{       char c;
+
+       if(!ontty)
+               return;
+       if (clearpage & NOTIFY)
+               putchar('\007');
+       fflush(stdout);
+       c = 0;
+       while(read(2, &c, 1) && c != '\n') ;
+       if (clearpage & CLEAR && c) {
+               CLEARPAGE;
+               page = spage;
+       } else {
+               page = (spage>>1) + (spage>>3);
+/***            page = spage * .6;              ***/
+       }
+       return;
+}
+
+int2()
+{
+       signal(SIGINT,int2);
+       stdout->_cnt = BUFSIZ;
+       stdout->_ptr = stdout->_base;
+       if(delflg)
+               putchar('\n');
+       delflg++;
+       longjmp(envir, 1);
+}
+
+int     peekc = -2;
+
+peekch()
+{
+       return(peekc = getch());
+}
+
+getch()
+{
+       register int c;
+       static word;
+
+       if(peekc != -2) {
+               c = peekc;
+               peekc = -2;
+               return(c);
+       };
+       c = getc(fin);
+       if(c != EOF)
+               c &= 0177;
+       return(c);
+}
+
+putch(c)
+register int c;
+{
+               if(linpos == 0 && numop) {
+                       printf("%-5d | ");
+                       linpos += 8;
+               }
+               if(c < 040 || c == 0177) switch(c) {
+                       case '\n': line++;
+                                  linpos = -1;
+                                  break;
+                       case 014:  goto npage;
+                       case 011:  linpos += 8;
+                                  linpos &= ~07;
+                                  linpos--;
+                                  break;
+                       default:   if(flagctl) {
+                                       if(c == '\7')
+                                           putchar(c);
+                                       putch('^');
+                                       if(c != 0177)
+                                           c += '@';
+                                       else
+                                           c = 'd';
+                                  }
+               }
+               putchar(c);
+               linpos++;
+               if(width && linpos >= width && peekch() != '\n') {
+                       putchar('\n'); linpos = 0;
+               }
+               if(linpos == 0 && --ct <= 0) {
+          npage:       nextpage(NOTICLEAR);
+                       ct = page;
+               }
+}
+
+
+getout()
+{
+       exit(0);
+}
diff --git a/docs/historical/mh-nov-1983/support/news-1char b/docs/historical/mh-nov-1983/support/news-1char
new file mode 100644 (file)
index 0000000..0519ecb
--- /dev/null
@@ -0,0 +1 @@
\ No newline at end of file
diff --git a/docs/historical/mh-nov-1983/support/news-mh_receiv b/docs/historical/mh-nov-1983/support/news-mh_receiv
new file mode 100644 (file)
index 0000000..8f7d436
--- /dev/null
@@ -0,0 +1,8 @@
+F=`grep '[Tt][Oo]:' $1 | sed 's/[Tt][Oo]:.*news\.//p'`
+if [ -d /usr/mhnews/$F ] ; then
+       cat /usr/mhnews/.1char >> /usr/mhnews/.$F
+       /usr/new/mh/file -link -file $1 +$F
+else
+       echo Unknown News Category: $F
+       exit 1
+fi