Subject: v09i002: ELM Mail System, Part02/19 Newsgroups: mod.sources Approved: rs@mirror.TMC.COM Submitted by: Dave Taylor Mod.sources: Volume 9, Issue 2 Archive-name: elm2/Part02 [ Yes, this is bigger than the News B2.11 distribution... --r$ ] #! /bin/sh # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # If this archive is complete, you will see the message: # "End of archive 2 (of 19)." # Contents: NOTICE doc/elm.1 doc/elmrc-info doc/fastmail.1 # doc/readmsg.1 filter/utils.c src/Makefile src/Makefile.mstr # src/args.c src/bounceback.c src/connect_to.c src/errno.c # src/fileio.c src/mkhdrs.c src/showmsg_cmd.c src/softkeys.c # utils/printmail.c PATH=/bin:/usr/bin:/usr/ucb ; export PATH echo shar: Extracting \"NOTICE\" \(2958 characters\) if test -f NOTICE ; then echo shar: Will not over-write existing file \"NOTICE\" else sed "s/^X//" >NOTICE <<'END_OF_NOTICE' X X The Elm(tm) Mail System General Public License X X X (C) Copyright 1986, Dave Taylor X X X COPYING POLICIES X X Permission is hereby granted for copying and distribution of copies of X the Elm source files, and that of any part thereof, subject to the following X license conditions: X X 1. You may without additional permission from the author, distribute X Elm or components of Elm, with or without additions developed by X you or by others at no charge. You may also distribute Elm along X with any other product for sale, provided that the cost of the X bundled package is the same regardless of whether Elm is included, X and provided that those interested only in Elm must be notified X that it is product freely available from the author. X X 2. Furthermore, if you distribute Elm software or parts of Elm, with X or without additions developed by you or others, then you must X either make available source of all portions of the Elm program X (exclusive of any additions made by you or by others) upon request, X or instead you may notify anyone requesting source that it is X freely available from the author. X X 3. In addition, you may not omit any of the copyright notices X on either the source files, the executable file, or the X documentation, and X X 4. Also, you may not omit transmission of this License agreement with X whatever portions of Elm that are distributed. X X 5. Lastly, any users of this software must be notified that it is any X without warrantee, or guarantee of any nature, express or implied, X nor is there any fitness for use represented. X XSoftware is a malleable thing - especially Unix - and the author can in no Xway guarantee that using this program will not cause grevious damage to your Xsystem. Of course this isn't anticipated, but if it does happen, the author Xcannot be held liable for any damages either directly or indirectly caused Xby this event. X XModification of the system is encouraged, providing that the portions of Xthe system that are from the original still carry the appropriate copyright Xnotices and that the changed sections are clearly delimited as such. The Xauthor requests copies of any changes made to ensure that the various versions Xstay reasonably in sync with each other. X XNOTE that it is not permitted to copy, sublicense distribute or transfer any Xof the Elm software except as expressly indicated herein. Any attempts to Xdo otherwise will be considered a violation of this license and your rights Xto the Elm software will be voided. X X XComments on the system and/or this licensing agreement is encouraged. Send Xelectronic mail to "taylor@hplabs.HP.COM". This license was written with Xhelp from Scott McGregor. Thanks Scott! X X X---- XElm is a trademark of Dave Taylor. END_OF_NOTICE if test 2958 -ne `wc -c doc/elm.1 <<'END_OF_doc/elm.1' X.TH ELM 1L X.ad b X.SH NAME Xelm - an interactive mail system X.SH SYNOPSIS X.B elm X[ X.B \-achkKmrwz X] [ X.B \-f X< X.B file X>] [ X.B \-d X< X.B level X>] X.br X.B elm X[ X.B \-s X< X.B subject X>] < X.B "list of aliases or addresses" X> X.PP X.SH HP-UX COMPATIBILITY X.TP 10 XLevel: XHP-UX/CONTRIBUTED X.TP XOrigin: XHewlett-Packard X.SH DESCRIPTION X.I Elm\^ Xis a new interactive mailer program that supercedes X.I mail Xand X.I mailx. X.PP XThere are three main ways to use the \fBelm\fR mailer; Xone way to use the mailer is to specify a list of addresses on the Xcommand line when the mailer is invoked. This will allow sending Xof a single message to the specified recipients with all the Xoptions usually available in the \fBelm\fR system itself. X.PP XThe second way, used most commonly when transmitting files and such, Xis to specify the subject of the message and the recipients using Xthe command line and redirect a file as standard input. For example, Xthe command X.nf X X elm -s testing joe < test.c X X.fi Xwould mail a copy of the Xfile test.c to alias joe, with the subject "testing" indicated. X.PP XOtherwise, the starting options are; X.TP 1.0i X.B "-a" XArrow - force the arrow cursor (instead of the inverse bar) X.TP X.B "-c" XCheckalias - expand the following aliases and return. X.TP X.B "-d " XDebug - set specified debug level - Output to "$HOME/Elm:debug.info" X.TP X.B "-f " XFile - read file (specified) rather than the incoming mailbox. X.TP X.B "-h" XHelp - give a list of starting options. X.TP X.B "?" XSynonymous with the "-h" option. X.TP X.B "-k" XKeypad - force knowledge of HP terminal keyboard, to allow Xthe use of the NEXT, PREV and HOME/SHIFT-HOME keys. X.TP X.B "-K" XKeypad + softkeys - enable use of softkeys on HP terminals only. X.TP X.B "-m" XMenu off - Use the extra lines for more message headers. X.TP X.B "-s" XSubject - specify subject for message to mail. X.TP X.B "-z" XZero - don't enter \fBElm\fR if no mail is pending. X.SH AUTHOR XDave Taylor, Hewlett-Packard Laboratories X.SH SEE ALSO X.I "Elm Users Guide", Xby Dave Taylor X.sp X.br X.I "Elm Reference Guide" Xby Dave Taylor X.sp X.br X.I "Elm Alias Users Guide" Xby Dave Taylor X.sp X.br Xnewalias(1L), checkalias(1L), mail(1), mailx(1), from(1L), printmail(1L) X.SH FILES X/usr/local/bin/elm-help.main help file X.br X/usr/mail/.alias_hash system alias hash table X.br X/usr/mail/.alias_data system alias data table X.br X$home/.alias_hash user alias hash table X.br X$home/.alias_data user alias data table X.br X/tmp/snd* outgoing mail edit buffer X.br X/tmp/mbox* temporary mailbox X.br X$HOME/ELM:debug.info Debug output if turned on X.SH DIAGNOSTICS XShould know about keyboards/softkey terminals other than HP. (If only Xtermcap were that powerful!) END_OF_doc/elm.1 if test 2799 -ne `wc -c doc/elmrc-info <<'END_OF_doc/elmrc-info' Xshell X# The shell to use for shell escapes X Xfullname X# The full user name for outbound mail X Xmaildir X# where to save my mail to, default directory X Xmailbox X# where to save messages to, default file X Xeditor X# what editor to use (none = simulate Berkeley Mail) X Xsavemail X# where to save mail if not specified somewhere else X Xcalendar X# where to save calendar entries X Xsortby X# and how to sort mailboxes, by default X Xprint X# how to print a message ('%s' is the filename) X Xprefix X# prefix sequence for including message text in other messages... X Xweedout X# what headers I DON'T want to see, ever. X Xbounceback X# threshold for bouncing copies of remote uucp messages... X# zero = disable function. X Xtimeout X# Set the main prompt timeout for resynching... X Xautocopy X# automatically copy message being replied to into buffer? X Xcopy X# save a copy of all outbound messages? X Xresolve X# emulate the mailx message increment mode (only increment after something X# has been 'done' to a message, either saved or deleted, as opposed to X# simply each time something is touched) X Xweed X# enable the weedout list to be read... X Xnoheader X# when messages are copied into the outbound buffer, don't include headers X Xtitles X# display message title when displaying pages of message X Xeditout X# edit the headers as the message leaves the machine (sort of) X Xsavename X# save messages, incoming and outbound, by login name of sender/recipient X Xmovepage X# when using the page commands (+ - ) change the current X# message pointer... X Xpointnew X# start up by pointing to the first new message received, if possible X Xsignature X# ".signature" files to append to outbound messages... X Xlocalsignature X# local ".signature" files to append to appropriate messages... X Xremotesignature X# remote ".signature" files to append to appropriate messages... X Xalwaysleave X# should we always leave messages as pending (change the default answer to yes) X Xalwaysdelete X# should we always delete messages we've marked for deletion (change the X# default answer to yes) X Xpager X# program to use for displaying messages ('builtin' is recommended) X Xkeypad X# we're running on an HP terminal and want HOME, PREV, NEXT, etc... X Xsoftkeys X# we're running on an HP terminal and want softkeys available too! X# (this implies "keypad=ON" too) X Xalternatives X# alternative addresses that I could receive mail from (usually a X# forwarding mailbox) and don't want to have listed... X Xforms X# we might mail out AT&T Mail Forms X Xwarnings X# tell us about addresses to machines we can't directly get to? X Xuserlevel X# are we good at it? 0=beginner, 1=intermediate, 2+ = expert! X Xnames X# let's just show the names, though, when expanding aliases... X Xarrow X# should we use the "->" rather than the inverse video bar? X Xmenu X# should we display the three-line menus? END_OF_doc/elmrc-info if test 2800 -ne `wc -c doc/fastmail.1 <<'END_OF_doc/fastmail.1' X.TH FASTMAIL 1L X.ad b X.SH NAME Xfastmail - quick batch mail interface to a single address X.SH SYNOPSIS X.B fastmail X[-b bcc-list] [-c cc-list] [-d] [-f fromname] [-r replyto] X[-s subject] filename address-list X.br X.SH HP-UX COMPATIBILITY X.TP 10 XLevel: XHP-UX/CONTRIBUTED X.TP XOrigin: XHewlett-Packard X.SH DESCRIPTION X.I Fastmail Xis a low-level interface to the mail system that allows batch Xprocessing of mail. It's intended for mailing to very large Xgroups of people in a staggered fashion. X.PP XThe starting options are; X.TP 1.0i X.B "-b bcc-list" XThis allows a list of people to receive blind-carbon copies, or BCCs, of Xthe message. This list should be full email addresses. X.TP X.B "-c cc-list" XThis allows a list of people to receive carbon copies, or CCs, of Xthe message. This list should be full email addresses. X.TP X.B "-d" XDebug. This is helpful for strange, unfriendly errors from Xthe program (etc). X.TP X.B "-f from" XThis overrides the users name in the From: line, so that if Xthe user was x@y, and their name was MrX then the default XFrom: line would be "From: x@y (MrX)". Using "-f Joe" when Xinvoking this, though, would change it to "From: x@y (Joe)" X.TP X.B "-r replyto" XOccasionally, you might send mail but want the replies to go Xto a different address (very common with mailing lists). XThere is a header for this purpose called "Reply-To:" which Xcan be utilized by using this starting option. For example, Xwe could send mail with a reply-to to list-request by Xusing "-r list-request". The header generated would then Xbe of the form "Reply-To: list-request". X.TP X.B "-s subject" XThe subject of the message is specified by using Xthis starting option. X.SH EXAMPLE XLet's say we're user "big" on machine "big-vax" and we have a Xshell script called 'batch-mail' that contains the following Xlines: X.nf X X # X # Batch Mail - batch mailing of a file to a LOT of users X # X # Usage: batch-mail "from" "subject" filename X X sender_copy = $LOGIN X replto = "The-Mr-Big-list" X X fastmail -b $sender_copy -r $replyto -f "$1" -s "$2" $3 person1 X sleep 10 X fastmail -r $replyto -f "$1" -s "$2" $3 person2 X sleep 10 X fastmail -r $replyto -f "$1" -s "$2" $3 person3 X sleep 10 X fastmail -r $replyto -f "$1" -s "$2" $3 person4 X X < etc > X Xwith the invocation: X X batch-mail "Mr. Big" "Warning to all" warning.text X X.fi Xwould mail a copy of the 'warning.text' file to person1, person2, Xperson3, etc. "$LOGIN" will also receive a copy of the first message Xin the mail, \fIsilently\fR. Each resultant message will include the headers: X.nf X X From: big-vax!big (Mr. Big) X Subject: Warning to all X Reply-To: The-Mr-Big-list X X.fi XThis program should turn out to be considerably Xfaster than the alternative methods of accomplishing this task. X.SH FILES X/usr/lib/sendmail sendmail transport if available X.br X/bin/rmail transport if no sendmail X.br X/tmp/fastmail.$$ temporary file X.SH AUTHOR XDave Taylor, Hewlett-Packard Laboratories X.SH SEE\ ALSO Xsendmail(1), rmail(1), elm(1L) END_OF_doc/fastmail.1 if test 3033 -ne `wc -c doc/readmsg.1 <<'END_OF_doc/readmsg.1' X.TH READMSG 1L X.ad b X.SH NAME Xreadmsg - read messages from incoming mail X.SH SYNOPSIS X.B readmsg X[\fB-p\fR] X[\fB-n\fR] X[\fB-f filename\fR] X[\fB-h\fR] X.br X.B readmsg X[\fB-p\fR] X[\fB-n\fR] X[\fB-f filename\fR] X[\fB-h\fR] Xnumber [number ...] X.br X.B readmsg X[\fB-p\fR] X[\fB-n\fR] X[\fB-f filename\fR] X[\fB-h\fR] Xpattern X.br X.SH HP-UX COMPATIBILITY X.TP 10 XLevel: XHP-UX/CONTRIBUTED X.TP XOrigin: XHewlett-Packard X.SH DESCRIPTION X.I Readmsg Xis a program that gives the \fBElm\fR user the functionality of Xthe mailx "~r" command from the editor of their choice. There Xare three different ways of using the program; X.P XFirst off, if you're actually creating a reply to a message Xfrom within the \fBElm\fR system then \fIreadmsg\fR without any Xarguments will include a summary of the headers and the body Xof the message being replied Xto. If you aren't currently editing a message the program will Xreturn an error. X.P XSecondly, if you want to include certain messages, you can Xspecify them by listing their ordinal locations in the Xmail file (that is, their "message numbers") Xup to 25 at a time. The \fImeta-\fRnumber '$' is understood to mean Xthe last message in the mailfile. Similarly, '*' is understood to Xrepresent every message in the file (that is, 1-$) X.P XFinally, you can also specify a pattern that occurs in one of Xthe messages as a way of including it. This pattern can be Xtyped in directly (no quotes) if the words are separated by a Xsingle space in the actual message. The pattern matching is case Xsensitive, so "Hello" and "hello" are NOT the same thing!! X.sp X.P XThe \fB-f\fR flag indicates that you'd rather use the file specified Xfor the operations specified rather than the default mailbox (see Xthe way \fBElm\fR implements printing multiple messages for more Xinformation on this...) X.P XThe \fB-h\fR flag instructs the program to include the entire header Xof the matched message or messages when displaying their Xtext. (default is to display the From: Date: and Subject: lines Xonly) X.P XThe \fB-n\fR flag instructs the program to exclude \fIall\fR Xheaders. This is used mostly for extracting files mailed and Xsuch. X.P XFinally, the \fB-p\fR flag indicates that the program should Xput form-feeds (control-L) between message headers. X.sp X.SH "EXAMPLES" XFirst off, to use this from within \fBvi\fR to include the text of the Xcurrent message at the end of the current message, you could Xuse the command; X.nf X X !!readmsg X X.fi X(as you hit the 'G' the editor will put you at the bottom of the screen Xwith the '!' prompt). X.sp 2 XLet's look at something more interesting, however; X.sp XSuppose you have the mailfile; X.nf X X From joe Jun 3 1986 4:45:30 MST X Subject: hello X X Hey Guy! Wanta go out and have a milk this evening? X X Joe X X From john Jun 3 1986 4:48:20 MST X Subject: Dinner at Eight X From: John Dinley X X Remember you should show up about eight, okay? X X - John D - X X From xxzyz!cron Jun 3 1986 5:02:43 MST X X Cannot connect to server: blob X Job 43243 deleted from queue. X X.fi XThe following commands will result in; X.nf X X $ readmsg 2 X [ display the second message, from John ] X X $ readmsg X [ an error, unless we're calling from \fBElm\fR ] X X $ readmsg BLOB X [ no match - case sensitive! ] X X $ readmsg -h connect to server X [ displays third message, including headers ] X X.fi X.SH FILES X/usr/mail/ The incoming mail X.br X$home/.readmsg The temp file from \fBElm\fR X.SH AUTHOR XDave Taylor, Hewlett-Packard Laboratories X.SH SEE\ ALSO Xnewmail(1L), Elm(1L) X.SH BUGS XThe '*' metacharacter doesn't always work as expected! X.br XPerhaps the pattern matching should be case insensitive? END_OF_doc/readmsg.1 if test 3666 -ne `wc -c filter/utils.c <<'END_OF_filter/utils.c' X/** utils.c **/ X X/** Utility routines for the filter program... X X (C) Copyright 1986, Dave Taylor X**/ X X#include X#include X#include X#include X X#include "defs.h" X#include "filter.h" X Xleave(reason) Xchar *reason; X{ X fprintf(stderr,"%sfilter (%s): LEAVE %s\n", BEEP, username, reason); X exit(1); X} X Xlog(what) Xint what; X{ X /** make an entry in the log files for the specified entry **/ X X FILE *fd; X char filename[SLEN]; X X if (! show_only) { X sprintf(filename, "%s/%s", home, filtersum); /* log action once! */ X if ((fd = fopen(filename, "a")) == NULL) { X fprintf(stderr,"%sfilter (%s): Couldn't open log file %s\n", X BEEP, filename); X fd = stdout; X } X fprintf(fd, "%d\n", rule_choosen); X fclose(fd); X } X X sprintf(filename, "%s/%s", home, filterlog); X X if (show_only) X fd = stdout; X else if ((fd = fopen(filename, "a")) == NULL) { X fprintf(stderr,"%sfilter (%s): Couldn't open log file %s\n", X BEEP, filename); X fd = stdout; X } X X setvbuf(fd, NULL, _IOFBF, BUFSIZ); X X if (strlen(from) + strlen(subject) > 60) X fprintf(fd, "\nMail from %s\n\tabout %s\n", from, subject); X else X fprintf(fd, "\nMail from %s about %s\n", from, subject); X X if (rule_choosen != -1) X if (rules[rule_choosen].condition->matchwhat == TO) X fprintf(fd, "\t(addressed to %s)\n", to); X X switch (what) { X case DELETE : fprintf(fd, "\tDELETED"); break; X case SAVE : fprintf(fd, "\tSAVED in file \"%s\"", X rules[rule_choosen].argument2); break; X case SAVECC : fprintf(fd,"\tSAVED in file \"%s\" AND PUT in mailbox", X rules[rule_choosen].argument2); break; X case FORWARD: fprintf(fd, "\tFORWARDED to \"%s\"", X rules[rule_choosen].argument2); break; X case EXEC : fprintf(fd, "\tEXECUTED \"%s\"", X rules[rule_choosen].argument2); break; X case LEAVE : fprintf(fd, "\tPUT in mailbox"); break; X } X X if (rule_choosen != -1) X fprintf(fd, " by rule #%d\n", rule_choosen+1); X else X fprintf(fd, ": the default action\n"); X X fflush(fd); X fclose(fd); X} X Xint Xcontains(string, pattern) Xchar *string, *pattern; X{ X /** Returns TRUE iff pattern occurs IN IT'S ENTIRETY in buffer. **/ X X register int i = 0, j = 0; X X while (string[i] != '\0') { X while (tolower(string[i++]) == tolower(pattern[j++])) X if (pattern[j] == '\0') X return(TRUE); X i = i - j + 1; X j = 0; X } X return(FALSE); X} X Xchar *itoa(i, two_digit) Xint i, two_digit; X{ X /** return 'i' as a null-terminated string. If two-digit use that X size field explicitly! **/ X X static char value[10]; X X if (two_digit) X sprintf(value, "%02d", i); X else X sprintf(value, "%d", i); X X return( (char *) value); X} X Xlowercase(string) Xchar *string; X{ X /** translate string into all lower case **/ X X register int i; X X for (i=0; i < strlen(string); i++) X if (isupper(string[i])) X string[i] = tolower(string[i]); X} END_OF_filter/utils.c if test 2862 -ne `wc -c src/Makefile <<'END_OF_src/Makefile' X# X# Makefile for the ELM mail program. X# X# (C) Copyright 1986, Dave Taylor X# X# Last modification: August 15th, 1986 X XSHELL=/bin/sh X XDEFINE= -DBSD XLIB2 = -lcurses X X# IF you're on an ACSnet system (Australia) then X# you'll want to uncomment the following; X X# DEFINE= ${DEFINE} -DACSNET X X############################## X XCFILES= addr_utils.c alias.c aliasdb.c aliaslib.c args.c bounceback.c \ X builtin.c calendar.c connect_to.c curses.c date.c delete.c \ X domains.c edit.c editmsg.c elm.c encode.c errno.c file.c \ X file_utils.c fileio.c forms.c getopt.c hdrconfg.c help.c \ X initialize.c input_utils.c leavembox.c limit.c mailmsg1.c \ X mailmsg2.c mailtime.c mkhdrs.c newmbox.c opt_utils.c options.c \ X output_utils.c pattern.c pmalloc.c quit.c read_rc.c remail.c \ X reply.c return_addr.c savecopy.c screen.c showmsg.c signals.c \ X softkeys.c sort.c string2.c strings.c syscall.c utils.c \ X save_opts.c validname.c X XHEADERS=../hdrs/curses.h ../hdrs/defs.h ../hdrs/headers.h ../hdrs/sysdefs.h X XOBJS = addr_utils.o alias.o aliasdb.o aliaslib.o args.o bounceback.o \ X builtin.o calendar.o connect_to.o curses.o date.o delete.o \ X domains.o edit.o editmsg.o elm.o encode.o errno.o file.o \ X file_utils.o fileio.o forms.o getopt.o hdrconfg.o help.o \ X initialize.o input_utils.o leavembox.o limit.o mailmsg1.o \ X mailmsg2.o mailtime.o mkhdrs.o newmbox.o opt_utils.o options.o \ X output_utils.o pattern.o pmalloc.o quit.o read_rc.o remail.o \ X reply.o return_addr.o savecopy.o screen.o showmsg.o signals.o \ X softkeys.o sort.o string2.o strings.o syscall.o utils.o \ X save_opts.o validname.o X XBIN= ../bin XLIBS= -ltermcap XCFLAGS= -O -I../hdrs XCC= /bin/cc XRM= /bin/rm -f X X../bin/elm: ${OBJS} ${EXTRA} ${HEADERS} ../hdrs/elm.h X ${CC} -o ${BIN}/elm -n ${OBJS} ${LIBS} ${LIB2} X X.c.o: ${HEADERS} X ${CC} -c ${CFLAGS} ${DEFINE} $*.c X Xcurses.o: curses.c ../hdrs/curses.h X ${CC} -c ${CFLAGS} -DRAWMODE ${DEFINE} curses.c X X# curses.c : curses.q X# @../bin/quickscreen curses.q X# X# curses.q : X# @cp curses.c curses.q X Xclean: X ${RM} ${OBJS} LINT.OUT ../bin/elm X Xlint: LINT.OUT X XLINT.OUT: ${CFILES} X lint -DRAWMODE -I../hdrs ${CFILES} -ltermcap > LINT.OUT X Xlisting: LISTING X XLISTING: Makefile INDEX ${HEADERS} ${CFILES} X @echo adding file 'Makefile'... X @/bin/echo \\f > LISTING X @cat Makefile >> LISTING X @echo adding file 'INDEX'... X @/bin/echo \\f >> LISTING X @cat INDEX >> LISTING X @../bin/makelisting ${HEADERS} ${CFILES} X @echo LISTING generated. X Xindex: INDEX X XINDEX: ${CFILES} ${HEADERS} X @echo Creating function definition index X @index *.c | sort > INDEX X @echo File INDEX generated END_OF_src/Makefile if test 2597 -ne `wc -c src/Makefile.mstr <<'END_OF_src/Makefile.mstr' X# X# Makefile for the ELM mail program. X# X# (C) Copyright 1986, Dave Taylor X# X# Last modification: August 15th, 1986 X XSHELL=/bin/sh X XDEFINE= >os-define< XLIB2 = >lib2< X X# IF you're on an ACSnet system (Australia) then X# you'll want to uncomment the following; X X# DEFINE= ${DEFINE} -DACSNET X X############################## X XCFILES= addr_utils.c alias.c aliasdb.c aliaslib.c args.c bounceback.c \ X builtin.c calendar.c connect_to.c curses.c date.c delete.c \ X domains.c edit.c editmsg.c elm.c encode.c errno.c file.c \ X file_utils.c fileio.c forms.c getopt.c hdrconfg.c help.c \ X initialize.c input_utils.c leavembox.c limit.c mailmsg1.c \ X mailmsg2.c mailtime.c mkhdrs.c newmbox.c opt_utils.c options.c \ X output_utils.c pattern.c pmalloc.c quit.c read_rc.c remail.c \ X reply.c return_addr.c savecopy.c screen.c showmsg.c signals.c \ X softkeys.c sort.c string2.c strings.c syscall.c utils.c \ X save_opts.c validname.c X XHEADERS=../hdrs/curses.h ../hdrs/defs.h ../hdrs/headers.h ../hdrs/sysdefs.h X XOBJS = addr_utils.o alias.o aliasdb.o aliaslib.o args.o bounceback.o \ X builtin.o calendar.o connect_to.o curses.o date.o delete.o \ X domains.o edit.o editmsg.o elm.o encode.o errno.o file.o \ X file_utils.o fileio.o forms.o getopt.o hdrconfg.o help.o \ X initialize.o input_utils.o leavembox.o limit.o mailmsg1.o \ X mailmsg2.o mailtime.o mkhdrs.o newmbox.o opt_utils.o options.o \ X output_utils.o pattern.o pmalloc.o quit.o read_rc.o remail.o \ X reply.o return_addr.o savecopy.o screen.o showmsg.o signals.o \ X softkeys.o sort.o string2.o strings.o syscall.o utils.o \ X save_opts.o validname.o X XBIN= ../bin XLIBS= >libs< XCFLAGS= -O -I../hdrs XCC= >cc< XRM= >rm< X X../bin/elm: ${OBJS} ${EXTRA} ${HEADERS} ../hdrs/elm.h X ${CC} -o ${BIN}/elm -n ${OBJS} ${LIBS} ${LIB2} X X.c.o: ${HEADERS} X ${CC} -c ${CFLAGS} ${DEFINE} $*.c X Xcurses.o: curses.c ../hdrs/curses.h X ${CC} -c ${CFLAGS} -DRAWMODE ${DEFINE} curses.c X X# curses.c : curses.q X# @../bin/quickscreen curses.q X# X# curses.q : X# @cp curses.c curses.q X Xclean: X ${RM} ${OBJS} LINT.OUT ../bin/elm X Xlint: LINT.OUT X XLINT.OUT: ${CFILES} X lint -DRAWMODE -I../hdrs ${CFILES} -ltermcap > LINT.OUT X Xlisting: LISTING X XLISTING: Makefile INDEX ${HEADERS} ${CFILES} X @echo adding file 'Makefile'... X @/bin/echo \\f > LISTING X @cat Makefile >> LISTING X @echo adding file 'INDEX'... X @/bin/echo \\f >> LISTING X @cat INDEX >> LISTING X @../bin/makelisting ${HEADERS} ${CFILES} X @echo LISTING generated. X Xindex: INDEX X XINDEX: ${CFILES} ${HEADERS} X @echo Creating function definition index X @index *.c | sort > INDEX X @echo File INDEX generated END_OF_src/Makefile.mstr if test 2589 -ne `wc -c src/args.c <<'END_OF_src/args.c' X/** args.c **/ X X/** starting argument parsing routines for ELM system... X X (C) Copyright 1986 Dave Taylor X**/ X X#include "headers.h" X X#define DONE 0 X#define ERROR -1 X Xextern char *optional_arg; /* optional argument as we go */ Xextern int opt_index; /* argnum + 1 when we leave */ X Xvoid exit(); /* just keeping lint happy.... */ X Xparse_arguments(argc, argv, to_whom) Xint argc; Xchar *argv[], *to_whom; X{ X /** Set flags according to what was given to program. If we are X fed a name or series of names, put them into the 'to_whom' buffer X and set "mail_only" to TRUE **/ X X register int c = 0, check_size = 0; X char *strcpy(); X X infile[0] = '\0'; X to_whom[0] = '\0'; X batch_subject[0] = '\0'; X X while ((c = get_options(argc, argv, "?acd:f:hkKms:wz")) > 0) { X switch (c) { X case 'a' : arrow_cursor++; break; X case 'c' : check_only++; break; X case 'd' : debug = atoi(optional_arg); break; X case 'f' : strcpy(infile, optional_arg); X mbox_specified = 2; break; X case '?' : X case 'h' : args_help(); X case 'k' : hp_terminal++; break; X case 'K' : hp_terminal++; hp_softkeys++; break; X case 'm' : mini_menu = 0; break; X case 's' : strcpy(batch_subject, optional_arg); break; X case 'w' : warnings = 0; break; X case 'z' : check_size++; break; X } X } X X if (c == ERROR) { X printf( X "Usage: %s [achkKmwz] [-d level] [-f file] [-s subject] \n\n", X argv[0]); X args_help(); X } X X if (opt_index < argc) { X while (opt_index < argc) { X sprintf(to_whom, "%s%s%s", to_whom, X to_whom[0] != '\0'? " " : "", argv[opt_index]); X mail_only++; X opt_index++; X } X check_size = 0; /* NEVER do this if we're mailing!! */ X } X X if (strlen(batch_subject) > 0 && ! mail_only) X exit(printf( X "\n\rDon't understand specifying a subject and no-one to send to!\n\r")); X X if (!isatty(fileno(stdin)) && strlen(batch_subject) == 0 && !check_only) X strcpy(batch_subject, DEFAULT_BATCH_SUBJECT); X X if (check_size) X check_mailfile_size(); X} X Xargs_help() X{ X /** print out possible starting arguments... **/ X X printf("\nPossible Starting Arguments for ELM program:\n\n"); X printf("\targ\t\t\tMeaning\n"); X printf("\t -a \t\tArrow - use the arrow pointer regardless\n"); X printf("\t -c \t\tCheckalias - check the given aliases only\n"); X printf("\t -dn\t\tDebug - set debug level to 'n'\n"); X printf("\t -fx\t\tFile - read file 'x' rather than mailbox\n"); X printf("\t -h \t\tHelp - give this list of options\n"); X printf("\t -k \t\tKeypad - enable HP 2622 terminal keyboard\n"); X printf("\t -K \t\tKeypad&softkeys - enable use of softkeys + \"-k\"\n"); X printf("\t -m \t\tMenu - Turn off menu, using more of the screen\n"); X printf("\t -sx\t\tSubject 'x' - for batchmailing\n"); X printf("\t -w \t\tSupress warning messages...\n"); X printf("\t -z \t\tZero - don't enter Elm if no mail is pending\n"); X printf("\n"); X printf("\n"); X exit(1); X} END_OF_src/args.c if test 2975 -ne `wc -c src/bounceback.c <<'END_OF_src/bounceback.c' X/** bounceback.c **/ X X/** This set of routines implement the bounceback feature of the mailer. X This feature allows mail greater than 'n' hops away (n specified by X the user) to have a 'cc' to the user through the remote machine. X X Due to the vagaries of the Internet addressing (uucp -> internet -> uucp) X this will NOT generate bounceback copies with mail to an internet host! X X (C) Copyright 1986 by Dave Taylor X**/ X X#include "headers.h" X Xchar *bounce_off_remote(), /* forward declaration */ X *strcat(), *strcpy(); X Xint Xuucp_hops(to) Xchar *to; X{ X /** Given the entire "To:" list, return the number of hops in the X first address (a hop = a '!') or ZERO iff the address is to a X non uucp address. X **/ X X register int hopcount = 0, index; X X for (index = 0; ! whitespace(to[index]) && to[index] != '\0'; index++) { X if (to[index] == '!') X hopcount++; X else if (to[index] == '@' || to[index] == '%' || to[index] == ':') X return(0); /* don't continue! */ X } X X return(hopcount); X} X Xchar *bounce_off_remote(to) Xchar *to; X{ X /** Return an address suitable for framing (no, that's not it...) X Er, suitable for including in a 'cc' line so that it ends up X with the bounceback address. The method is to take the first X address in the To: entry and break it into machines, then X build a message up from that. For example, consider the X following address: X a!b!c!d!e!joe X the bounceback address would be; X a!b!c!d!e!d!c!b!a!ourmachine!ourname X simple, eh? X **/ X X static char address[LONG_STRING]; /* BEEG address buffer! */ X X char host[MAX_HOPS][SHORT_SLEN]; /* for breaking up addr */ X register int hostcount = 0, hindex = 0, X index; X X for (index = 0; !whitespace(to[index]) && to[index] != '\0'; index++) { X if (to[index] == '!') { X host[hostcount][hindex] = '\0'; X hostcount++; X hindex = 0; X } X else X host[hostcount][hindex++] = to[index]; X } X X /* we have hostcount hosts... */ X X strcpy(address, host[0]); /* initialize it! */ X X for (index=1; index < hostcount; index++) { X strcat(address, "!"); X strcat(address, host[index]); X } X X /* and now the same thing backwards... */ X X for (index = hostcount -2; index > -1; index--) { X strcat(address, "!"); X strcat(address, host[index]); X } X X /* and finally, let's tack on our machine and login name */ X X strcat(address, "!"); X strcat(address, hostname); X strcat(address, "!"); X strcat(address, username); X X /* and we're done!! */ X X return( (char *) address ); X} END_OF_src/bounceback.c if test 2525 -ne `wc -c src/connect_to.c <<'END_OF_src/connect_to.c' X/** connect_to.c **/ X X/** This contains the routine(s) needed to have the Elm mailer figure X out what machines the current machine can talk to. This can be X done in one of two ways - either the program can read the L.sys X file, or (if it fails or "UUNAME" define is present) will invoke X uuname to a file, then read the file in! X X (C) Copyright Dave Taylor, 1986 X**/ X X#include "headers.h" X Xchar *strcpy(); X Xstruct lsys_rec *pmalloc(); X Xget_connections() X{ X X /** get the direct connections that this machine has, by hook X or by crook (so to speak) X **/ X X#ifndef USE_UUNAME X FILE *lsysfile; X char buffer[SLEN], sysname[NLEN]; X struct lsys_rec *system_record, *previous_record; X int loc_on_line; X X previous_record = NULL; X if ((lsysfile = fopen(Lsys,"r")) == NULL) { X dprint1(1, "Warning: Can't open L.sys file %s (read_lsys)\n", Lsys); X#endif X X if (read_uuname() == -1) { X error("Warning: couldn't figure out system connections..."); X talk_to_sys = NULL; X } X X#ifndef USE_UUNAME X /** ELSE: already read in uuname() output if we're here!! **/ X return; X } X X while (fgets(buffer, SLEN, lsysfile) != NULL) { X sscanf(buffer,"%s", sysname); X X if (previous_record == NULL) { X dprint1(2, "L.sys\tdirect connection to %s, ", sysname); X loc_on_line = 30 + strlen(sysname); X previous_record = pmalloc(sizeof *talk_to_sys); X X strcpy(previous_record->name, sysname); X previous_record->next = NULL; X talk_to_sys = previous_record; X } X else if (! talk_to(sysname) && sysname[0] != '#') { X if (loc_on_line + strlen(sysname) > 80) { X dprint0(2, "\n\t"); X loc_on_line = 8; X } X dprint1(2, "%s, ", sysname); X loc_on_line += (strlen(sysname) + 2); X system_record = pmalloc(sizeof *talk_to_sys); X X strcpy(system_record->name, sysname); X system_record->next = NULL; X previous_record->next = system_record; X previous_record = system_record; X } X } X X fclose(lsysfile); X X if (loc_on_line != 8) X dprint0(2, "\n"); X X dprint0(2, "\n"); /* for a nice format! Yeah! */ X#endif X} X Xint Xread_uuname() X{ X /** This routine trys to use the uuname routine to get the names of X all the machines that this machine connects to...it returns X -1 on failure. X **/ X X FILE *fd; X char buffer[SLEN], filename[SLEN]; X struct lsys_rec *system_record, *previous_record; X int loc_on_line; X X sprintf(filename, "%s%d", temp_uuname, getpid()); X sprintf(buffer,"%s > %s", uuname, filename); X X if (system_call(buffer, SH) != 0) { X dprint0(1, "Can't get uuname info - system call failed!\n"); X unlink(filename); /* insurance */ X return(-1); X } X X if ((fd = fopen(filename, "r")) == NULL) { X dprint1(1, "Can't get uuname info - can't open file %s for reading\n", X filename); X unlink(filename); /* insurance */ X return(-1); X } X X previous_record = NULL; X X while (fgets(buffer, SLEN, fd) != NULL) { X no_ret(buffer); X if (previous_record == NULL) { X dprint1(2, "uuname\tdirect connection to %s, ", buffer); X loc_on_line = 30 + strlen(buffer); X previous_record = pmalloc(sizeof *talk_to_sys); X X strcpy(previous_record->name, buffer); X previous_record->next = NULL; X talk_to_sys = previous_record; X } X else { /* don't have to check uniqueness - uuname does that! */ X if (loc_on_line + strlen(buffer) > 80) { X dprint0(2, "\n\t"); X loc_on_line = 8; X } X dprint1(2, "%s, ", buffer); X loc_on_line += (strlen(buffer) + 2); X system_record = pmalloc(sizeof *talk_to_sys); X X strcpy(system_record->name, buffer); X system_record->next = NULL; X previous_record->next = system_record; X previous_record = system_record; X } X } X X fclose(fd); X X (void) unlink(filename); /* kill da temp file!! */ X X dprint0(2, "\n"); /* for a nice format! Yeah! */ X X return(0); /* it all went okay... */ X} END_OF_src/connect_to.c if test 3860 -ne `wc -c src/errno.c <<'END_OF_src/errno.c' X/** errno.c **/ X X/** This routine maps error numbers to error names and error messages. X These are all directly ripped out of the include file errno.h, and X are HOPEFULLY standardized across the different breeds of Unix!! X X If (alas) yours are different, you should be able to use awk to X mangle your errno.h file quite simply... X X (C) Copyright 1986 Dave Taylor X**/ X X#include "headers.h" X Xchar *err_name[] = { X/* 0 */ "NOERROR", "No error status currently", X/* 1 */ "EPERM", "Not super-user", X/* 2 */ "ENOENT", "No such file or directory", X/* 3 */ "ESRCH", "No such process", X/* 4 */ "EINTR", "Interrupted system call", X/* 5 */ "EIO", "I/O error", X/* 6 */ "ENXIO", "No such device or address", X/* 7 */ "E2BIG", "Arg list too long", X/* 8 */ "ENOEXEC", "Exec format error", X/* 9 */ "EBADF", "Bad file number", X/* 10 */ "ECHILD", "No children", X/* 11 */ "EAGAIN", "No more processes", X/* 12 */ "ENOMEM", "Not enough core", X/* 13 */ "EACCES", "Permission denied", X/* 14 */ "EFAULT", "Bad address", X/* 15 */ "ENOTBLK", "Block device required", X/* 16 */ "EBUSY", "Mount device busy", X/* 17 */ "EEXIST", "File exists", X/* 18 */ "EXDEV", "Cross-device link", X/* 19 */ "ENODEV", "No such device", X/* 20 */ "ENOTDIR", "Not a directory", X/* 21 */ "EISDIR", "Is a directory", X/* 22 */ "EINVAL", "Invalid argument", X/* 23 */ "ENFILE", "File table overflow", X/* 24 */ "EMFILE", "Too many open files", X/* 25 */ "ENOTTY", "Not a typewriter", X/* 26 */ "ETXTBSY", "Text file busy", X/* 27 */ "EFBIG", "File too large", X/* 28 */ "ENOSPC", "No space left on device", X/* 29 */ "ESPIPE", "Illegal seek", X/* 30 */ "EROFS", "Read only file system", X/* 31 */ "EMLINK", "Too many links", X/* 32 */ "EPIPE", "Broken pipe", X/* 33 */ "EDOM", "Math arg out of domain of func", X/* 34 */ "ERANGE", "Math result not representable", X/* 35 */ "ENOMSG", "No message of desired type", X/* 36 */ "EIDRM", "Identifier removed" X }; X Xchar *strcpy(); X Xchar *error_name(errnumber) Xint errnumber; X{ X static char buffer[50]; X X if (errnumber < 0 || errnumber > 36) X sprintf(buffer,"ERR-UNKNOWN (%d)", errnumber); X else X strcpy(buffer, err_name[2*errnumber]); X X return( (char *) buffer); X} X Xchar *error_description(errnumber) Xint errnumber; X{ X static char buffer[50]; X X if (errnumber < 0 || errnumber > 36) X sprintf(buffer,"Unknown error - %d - No description", errnumber); X else X strcpy(buffer, err_name[2*errnumber + 1]); X X return ( (char *) buffer); X} END_OF_src/errno.c if test 2500 -ne `wc -c src/fileio.c <<'END_OF_src/fileio.c' X/** fileio.c **/ X X/** File I/O routines, including deletion from the mailbox! X X (C) Copyright 1986 Dave Taylor X**/ X X#include "headers.h" X#include X#include X X#ifdef BSD X#undef tolower X#endif X Xextern int errno; X Xchar *error_name(); X Xcopy_message(prefix, dest_file, remove_header, remote) Xchar *prefix; XFILE *dest_file; Xint remove_header, remote; X{ X /** Copy current message to destination file, with optional 'prefix' X as the prefix for each line. If remove_header is true, it will X skip lines in the message until it finds the end of header line... X then it will start copying into the file... If remote is true X then it will append "remote from " at the end of the X very first line of the file (for remailing) X **/ X X char buffer[LONG_SLEN]; X register int ok = 1, lines, in_header = 1, first_line = TRUE; X X /** get to the first line of the message desired **/ X X if (fseek(mailfile, header_table[current-1].offset, 0) == -1) { X dprint2(1,"ERROR: Attempt to seek %d bytes into file failed (%s)", X header_table[current-1].offset, "copy_message"); X error1("ELM [seek] failed trying to read %d bytes into file", X header_table[current-1].offset); X return; X } X X /* how many lines in message? */ X X lines = header_table[current-1].lines; X X /* now while not EOF & still in message... copy it! */ X X while (ok && lines--) { X ok = (int) (fgets(buffer, LONG_SLEN, mailfile) != NULL); X if (strlen(buffer) < 2) in_header = 0; X if (ok) X if (! (remove_header && in_header)) X if (first_line && remote) { X no_ret(buffer); X fprintf(dest_file, "%s%s remote from %s\n", X prefix, buffer, hostname); X first_line = FALSE; X } X else if (! in_header && first_word(buffer, "From ")) { X dprint0(1,"\n*** Internal Problem...Tried to add the following;\n"); X dprint1(1," '%s'\nto output file (copy_message) ***\n", buffer); X ok = 0; /* STOP NOW! */ X } X else X fprintf(dest_file, "%s%s", prefix, buffer); X } X if (strlen(buffer) + strlen(prefix) > 1) X fprintf(dest_file, "\n"); /* blank line to keep mailx happy *sigh* */ X} X X#ifdef SITE_HIDING X Xint Xis_a_hidden_user(specific_username) Xchar *specific_username; X{ X /** Returns true iff the username is present in the list of X 'hidden users' on the system. X **/ X X FILE *hidden_users; X char buffer[SLEN]; X X this is shit and should be flagged as bad news! X X if ((hidden_users = fopen (HIDDEN_SITE_USERS,"r")) == NULL) { X dprint2(1,"Couldn't open hidden site file %s [%s]\n", X HIDDEN_SITE_USERS, error_name(errno)); X return(FALSE); X } X X while (fscanf(hidden_users, "%s", buffer) != EOF) X if (strcmp(buffer, specific_username) == 0) { X dprint1(3,"** Found user '%s' in hidden site file!\n", X specific_username); X fclose(hidden_users); X return(TRUE); X } X X fclose(hidden_users); X dprint1(3,"** Couldn't find user '%s' in hidden site file!\n", X specific_username); X X return(FALSE); X} X X#endif END_OF_src/fileio.c if test 3020 -ne `wc -c src/mkhdrs.c <<'END_OF_src/mkhdrs.c' X/** mkhdrs.c **/ X X/** This contains all the header generating routines for the ELM X program. X X (C) Copyright 1985 Dave Taylor X X**/ X X#include X#include "headers.h" X Xextern char in_reply_to[SLEN]; X Xchar *strcpy(); Xunsigned long sleep(); X Xgenerate_reply_to(msg) Xint msg; X{ X /** Generate an 'in-reply-to' message... **/ X char buffer[SLEN]; X X X if (msg == -1) /* not a reply! */ X in_reply_to[0] = '\0'; X else { X if (chloc(header_table[msg].from, '!') != -1) X tail_of(header_table[msg].from, buffer, FALSE); X else X strcpy(buffer, header_table[msg].from); X sprintf(in_reply_to, "Message from \"%s\" of %s %s, %s at %s", X buffer, X header_table[msg].month, X header_table[msg].day, X header_table[msg].year, X header_table[msg].time); X } X} X Xadd_mailheaders(filedesc) XFILE *filedesc; X{ X /** Add the users .mailheaders file if available. Allow backquoting X in the file, too, for fortunes, etc...*shudder* X **/ X X FILE *fd; X char filename[SLEN], buffer[LONG_SLEN]; X X sprintf(filename, "%s/%s", home, mailheaders); X X if ((fd = fopen(filename, "r")) != NULL) { X while (fgets(buffer, LONG_SLEN, fd) != NULL) X if (strlen(buffer) < 2) { X dprint0(2, X "Strlen of line from .elmheaders is < 2 (write_header_info)"); X if (mail_only) X printf("Warning: blank line in %s ignored!\r\n", filename); X else { X error1("Warning: blank line in %s ignored!", filename); X sleep(2); X } X } X else if (occurances_of(BACKQUOTE, buffer) == 2) X expand_backquote(buffer, filedesc); X else X fprintf(filedesc, "%s", buffer); X X fclose(fd); X } X} X Xexpand_backquote(buffer, filedesc) Xchar *buffer; XFILE *filedesc; X{ X /** This routine is called with a line of the form: X Fieldname: `command` X and is expanded accordingly.. X **/ X X FILE *fd; X char command[SLEN], command_buffer[SLEN], fname[SLEN], X prefix[SLEN]; X register int i, j = 0; X X for (i=0; buffer[i] != BACKQUOTE; i++) X prefix[j++] = buffer[i]; X prefix[j] = '\0'; X X j = 0; X X for (i=chloc(buffer, BACKQUOTE)+1; buffer[i] != BACKQUOTE;i++) X command[j++] = buffer[i]; X command[j] = '\0'; X X sprintf(fname,"%s%d", temp_print, getpid()); X X sprintf(command_buffer, "%s > %s", command, fname); X X system_call(command_buffer, SH); X X if ((fd = fopen(fname, "r")) == NULL) { X if (mail_only) X printf("\nbackquoted command \"%s\" in .elmheaders failed\n", X command); X else X error1("backquoted command \"%s\" in .elmheaders failed", command); X return; X } X X /* If we get a line that is less than 80 - length of prefix then we X can toss it on the same line, otherwise, simply prepend each line X *starting with this line* with a leading tab and cruise along */ X X if (fgets(command_buffer, SLEN, fd) == NULL) X fprintf(filedesc, prefix); X else { X if (strlen(command_buffer) + strlen(prefix) < 80) X fprintf(filedesc, "%s%s", prefix, command_buffer); X else X fprintf(filedesc, "%s\n\t%s", prefix, command_buffer); X X while (fgets(command_buffer, SLEN, fd) != NULL) X fprintf(filedesc, "\t%s", command_buffer); X X fclose(fd); X } X X unlink(fname); /* don't leave the temp file laying around! */ X} END_OF_src/mkhdrs.c if test 3189 -ne `wc -c src/showmsg_cmd.c <<'END_OF_src/showmsg_cmd.c' X/** showmsg_cmd.c **/ X X/** This is an interface for the showmsg command line. The possible X functions that could be invoked from the showmsg command line are X almost as numerous as those from the main command line and include X the following; X X | = pipe this message to command... X ! = call Unix command X < = scan message for calendar info X b = bounce (remail) message X d = mark message for deletion X e = edit entire mailbox X f = forward message X g = group reply X j,n = move to body of next message X k = move to body of previous message X p = print this (all tagged) message X r = reply to this message X s = save this message to a maibox/folder X t = tag this message X x = Exit Elm NOW X X all commands not explicitly listed here are returned as unprocessed X to be dealt with at the main command level. X X This function returns 0 if it dealt with the command, or the command X otherwise. X**/ X X#include "headers.h" X Xprocess_showmsg_command(command) Xchar command; X{ X switch (command) { X case '|' : clear_bottom_of_screen(); X PutLine0(LINES-3,0,"Command: pipe"); X softkeys_off(); X (void) pipe(); /* do pipe regardless */ X softkeys_on(); X return(0); /* must have new screen */ X X case '!' : clear_bottom_of_screen(); X PutLine0(LINES-3,0,"Command: system call"); X softkeys_off(); X (void) subshell(); /* do shell regardless */ X softkeys_on(); X return(0); /* must have new screen */ X X case '<' : X#ifdef ENABLE_CALENDAR X scan_calendar(); X#else X error("can't scan for calendar entries!"); X#endif X break; X X case 'b' : clear_bottom_of_screen(); X PutLine0(LINES-3,0,"Command: bounce message"); X remail(); X return(0); /* must have new screen */ X X case 'd' : delete(TRUE); X break; X X case 'e' : edit_mailbox(); X return(0); /* must have new screen */ X X case 'f' : clear_bottom_of_screen(); X PutLine0(LINES-3,0,"Command: forward message"); X (void) forward(); X return(0); /* must have new screen */ X X case 'g' : clear_bottom_of_screen(); X PutLine0(LINES-3,0,"Command: group reply"); X (void) reply_to_everyone(); X return(0); /* must have new screen */ X X case 'j' : X case 'n' : if (current < message_count) X show_msg(++current); X return(0); X X case 'k' : if (current > 0) X show_msg(--current); X return(0); X X X case 'p' : printmsg(); X break; X X case 'r' : clear_bottom_of_screen(); X PutLine0(LINES-3,0,"Command: reply to message"); X (void) reply(); X return(0); /* must have new screen */ X X case 's' : clear_bottom_of_screen(); X PutLine0(LINES-3,0,"Command: save message"); X (void) save(); X break; X X case 't' : tag_message(); X break; X X case 'x' : leave(); X X case '\n': X case '\r': return(0); /* avoid looping */ X X default : return(command); /* couldn't deal with it! */ X } X X return(1); /* done with it! */ X} X Xclear_bottom_of_screen() X{ X /** clear the last 4 lines of the screen... **/ X X MoveCursor(LINES-4, 0); X CleartoEOS(); X} END_OF_src/showmsg_cmd.c if test 3188 -ne `wc -c src/softkeys.c <<'END_OF_src/softkeys.c' X/** softkeys.c **/ X X/** This file and associated routines: (C) Copyright 1986, Dave Taylor **/ X X#include X#include "headers.h" X Xdefine_softkeys(level) Xint level; X{ X if (! hp_softkeys) return; X X if (level == MAIN) { X X define_key(f1, " Show Msg", "\r"); X define_key(f2, " Mail Msg", "m"); X define_key(f3, " Reply to Msg", "r"); X X if (user_level == 0) { X define_key(f4, " Save Msg", "s"); X define_key(f5, " Delete Msg", "d"); X define_key(f6, "Undelete Msg", "u"); X } X else { X define_key(f4, " Change Mailbox", "c"); X define_key(f5, " Save Msg", "s"); X define_key(f6, " Delete/Undelete", "^"); X } X X define_key(f7, " Print Msg", "p"); X define_key(f8, " Quit Elm", "q"); X } X else if (level == ALIAS) { X define_key(f1, " Alias Current", "a"); X define_key(f2, " Check Person", "p"); X define_key(f3, " Check System", "s"); X define_key(f4, " Make Alias", "m"); X clear_key(f5); X clear_key(f6); X clear_key(f7); X define_key(f8, " Return to Elm", "r"); X } X else if (level == YESNO) { X define_key(f1, " Yes", "y"); X clear_key(f2); X clear_key(f3); X clear_key(f4); X clear_key(f5); X clear_key(f6); X clear_key(f7); X define_key(f8, " No", "n"); X } X else if (level == READ) { X define_key(f1, " Next Page ", " "); X clear_key(f2); X define_key(f3, " Skip Page ", "f"); X clear_key(f4); X clear_key(f5); X clear_key(f6); X clear_key(f7); X define_key(f8, " Return to Elm", "q"); X } X else if (level == CHANGE) { X define_key(f1, " Mail Directry", "=/"); X define_key(f2, " Home Directry", "~/"); X clear_key(f3); X define_key(f4, "Incoming Mailbox", "!\n"); X clear_key(f5); X clear_key(f6); X clear_key(f7); X define_key(f8, " Cancel", "\n"); X } X X softkeys_on(); X} X Xdefine_key(key, display, send) Xint key; Xchar *display, *send; X{ X X char buffer[30]; X X sprintf(buffer,"%s%s", display, send); X X fprintf(stderr, "%c&f%dk%dd%dL%s", ESCAPE, key, X strlen(display), strlen(send), buffer); X fflush(stdout); X} X Xsoftkeys_on() X{ X /* enable (esc&s1A) turn on softkeys (esc&jB) and turn on MENU X and USER/SYSTEM options. */ X X if (hp_softkeys) { X fprintf(stderr, "%c&s1A%c&jB%c&jR", ESCAPE, ESCAPE, ESCAPE); X fflush(stdout); X } X X} X Xsoftkeys_off() X{ X /* turn off softkeys (esc&j@) */ X X if (hp_softkeys) { X fprintf(stderr, "%c&s0A%c&j@", ESCAPE, ESCAPE); X fflush(stdout); X } X} X Xclear_key(key) X{ X /** set a key to nothing... **/ X X if (hp_softkeys) X define_key(key, " ", ""); X} END_OF_src/softkeys.c if test 2576 -ne `wc -c utils/printmail.c <<'END_OF_utils/printmail.c' X/** printmail.c **/ X X/** print mail, adding a formfeed between each message **/ X/** Modified to use stdin if being fed from a pipe. **/ X X/** (C) Copyright 1985, Dave Taylor **/ X X#include X#include "defs.h" X Xstatic char ident[] = { WHAT_STRING }; X X#define dashes \ X"\n\n------------------------------------------------------------------------------\n\n" X#define FF "\014" /* form feed! */ X XFILE *mailfile; Xchar separator[80]; X Xmain(argc, argv) Xint argc; Xchar *argv[]; X{ X char infile[80], username[40], c; X X strcpy(separator, FF); X X argv++; /* get past argv[0] */ X X if (argc > 1) X if (strcmp(*argv, "-d") == 0) { X strcpy(separator, dashes); X --argc; X argv++; X } X X if (argc > 1 && *argv[0] == '-') X exit(fprintf(stderr, "Usage: printmail {-d} {filename (s)}\n")); X X if (argc == 1) { X strcpy(username, getlogin()); X if (strlen(username) == 0) X cuserid(username); X if (isatty(fileno(stdin))) { /* normal invokation... */ X sprintf(infile,"%s/%s",mailhome, username); X if ((mailfile = fopen(infile,"r")) == NULL) { X fprintf(stderr, "No mail!\n"); X exit(0); X } X } X else X mailfile = stdin; /* read from stdin! */ X X if (read_headers() == 0) X fprintf(stderr, "No messages in mailbox!\n"); X } X X if (argc > 1) /* more than one file - delimit each */ X if (strcmp(separator, FF) != 0) X printf("\t\t\t%s\n%s", *argv, separator); X else X printf("\t\t\t%s\n\n", *argv); /* Don't put a formfeed! */ X X while (--argc) { X if ((mailfile = fopen(*argv,"r")) == NULL) { X fprintf(stderr, "Could not open file '%s'!", *argv); X break; X } X else X if (read_headers() == 0) X fprintf(stderr, "No messages in mailbox '%s'!\n", *argv); X argv++; X if (argc-1) { X if (strcmp(separator, FF) != 0) X printf("%s\t\t\t%s%s", separator, *argv, separator); X else X printf("%s\t\t\t%s\n\n", separator, *argv); X } X } X} X Xint Xread_headers() X{ X char buffer[100]; X register int count = 0; X X while (fgets(buffer, 100, mailfile) != NULL) X if (first_word(buffer,"From ")) { X if (real_from(buffer)) { X printf("%s%s", count ? separator : "", buffer); X count++; X } X } X else X printf("%s", buffer); X X return(count); X} X Xint Xreal_from(buffer) Xchar *buffer; X{ X /***** returns true iff 's' has the seven 'from' fields *****/ X X char junk[80]; X X junk[0] = '\0'; X sscanf(buffer, "%*s %*s %*s %*s %*s %*s %s", junk); X return(junk[0] != '\0'); X} END_OF_utils/printmail.c if test 2471 -ne `wc -c