home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-05-05 | 54.2 KB | 1,466 lines |
- Newsgroups: comp.sources.misc
- subject: v12i040: Mail User's Shell, Part12/19
- from: argv@Eng.Sun.COM (Dan Heller)
- Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
-
- Posting-number: Volume 12, Issue 40
- Submitted-by: argv@Eng.Sun.COM (Dan Heller)
- Archive-name: mush/part12
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # The tool that generated this appeared in the comp.sources.unix newsgroup;
- # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
- # If this archive is complete, you will see the following message at the end:
- # "End of archive 12 (of 19)."
- # Contents: mush/README mush/mail.c.b
- # Wrapped by argv@turnpike on Wed May 2 13:59:38 1990
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'mush/README' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'mush/README'\"
- else
- echo shar: Extracting \"'mush/README'\" \(25704 characters\)
- sed "s/^X//" >'mush/README' <<'END_OF_FILE'
- X/* @(#)README (c) copyright 9/15/89 (Dan Heller) */
- X
- XAuthor:
- X Dan Heller
- X
- XNetwork addresses:
- X argv@sun.com argv@monet.berkeley.edu.
- X argv@garp.mit.edu dheller@ucbcory.berkeley.edu
- X
- XWhen sending mail, mail to the addresses in the order given.
- X
- XContained is the source for "Mail User's Shell" (MUSH), a "Mail User
- XAgent" (MUA) that is designed to manage electronic mail on most UNIX
- Xsystems. That is, mush is used by users to read mail, sort it, edit
- Xit, delete it, or use it to act as an interface to send mail to others.
- XA Mail Transport Agent (MTA) is the program which mush communicates with
- Xthat actually -delivers- mail.
- X
- XThe Mush sources are copyright (c) 1986, 1987, 1988, 1989 by Dan Heller.
- XRedistribution of the unmodified source code is permitted as long as all
- Xcopyright notices remain intact and all other identifying notices remain
- Xin the code and in the binary. This includes message headers on outgoing
- Xmail and the startup message. Future releases may extract the release
- Xversion from the message headers of mush-originated messages to aid in
- Ximplementing features and providing backwards compatibility with previous
- Xversions. Modification of the source for personal use is permitted.
- XModifications sent to the authors are humbly accepted and it is their
- Xperogative to make the mods official. Only the "official" sources may be
- Xredistributed and no sale of the code or any part thereof is permitted
- Xwithout written consent from the authors. Further, no part of the code
- Xmay be used in any other product, free or otherwise, without consent from
- Xthe authors.
- X
- XWith that out of the way...
- X
- XMush runs on various flavors of unix. To build mush, you should identify
- Xwhich unix you are running:
- X
- X Sun (all versions from 2.0 and higher).
- X BSD (versions 4.2 and up)
- X System-V / Version 7 / System III (Bell Labs)
- X Xenix (this might be tricky)
- X
- XYou will need to copy "config.h-dist" to config.h and edit it to reflect
- Xthe system dependencies described there. These consist of "compile-time
- Xdefinitions and macros."
- X
- XWhen it comes to "compile-time definitions", you may use one of two methods:
- X
- X #define DEFINITION /* in the config.h file */
- X -DDEFINITION /* in your makefile */
- X
- XIf the definition is of the form MACRO="string", then use:
- X
- X #define MACRO string
- X -DMACRO=string
- X
- XNote that if you use definitions in the makefile, you should remove the
- Xcorresponding definitions from config.h -- if you do not, the config.h
- Xdefinitions will override the -D definitions. The compiler will usually
- Xprint a warning message if this happens, but the result will still be wrong.
- X
- X---------------
- XWhich makefile to use:
- X
- XIf you are on a Sun Workstation:
- X
- X makefile.sun applies only to suns and creates a binary called "mush."
- X If the binary ends in "tool", then the graphics (suntools) mode will be
- X used by default on invocation. Otherwise, you must specify -t for
- X toolmode on sun workstations. The SUNTOOL define is used in the
- X makefile.sun in order to compile the suntools version. You DO need
- X to be running SunView; old SunWindows (2.0+) no longer works. Be sure
- X to follow the notes in the makefile.sun for SunOS-4.0 machines.
- X
- X If you know that you're not going to use the suntools mode then you
- X should use makefile.bsd so that SUNTOOL won't be defined and unnecessary
- X files will not be compiled so the binary will be smaller.
- X
- X Whether or not you define SUNTOOL, you should define one of SUN_3_5,
- X SUN_4_0, or SUN_4_1 depending on your SunOS version. If SUNTOOL is
- X the only thing defined, SUN_4_0 will be used.
- X
- XIf you are on a BSD UNIX machine:
- X
- X You should use the makefile.bsd makefile.
- X
- XIf you are using XENIX:
- X
- X There is one makefile for xenix: makefile.xenix. However, SCO-xenix
- X runs on either 80286 or 80386 architectures. This makefiles has been
- X tuned for SCO's version of xenix. This does not mean that it won't
- X work under other xenix versions -- however, some changes may have to
- X be made by hand. If your xenix release is sco-xenix 2.2 or higher
- X then you must define USG. The libraries to use may be -ltinfo instead
- X of -lcurses -ltermlib. This is because the curses package may use
- X termio instead of the sgtty data structure. If you want to use termio
- X anyway, even if you're on an older xenix system (that supports termio),
- X then you may define USG anyway.
- X
- X Follow the hints in the makefile.xenix for compiling for 286 systems
- X or 386 systems. It is *very likely* that the CFLAGS will have to be
- X modified -- specifically, the model size and the stack size options.
- X You should be very familiar with your xenix to know how to tune this
- X properly.
- X
- XIf you are on a System-V Bell labs machine:
- X
- X makefile.sys.v is for unix machines that are not running any flavor of
- X BSD and probably running a system-v flavor of unix -- this defines USG
- X so that termio will be used.
- X
- X SCO UNIX V.3.2 users will need to change the declaration of ttytype[]
- X in curses.c to be "extern unsigned char" when using terminfo-based
- X curses. This may also be necessary with termcap-based curses.
- X
- X MicroPort sys-v users should probably remove the -O compiler option
- X from the makefile, and may have trouble with the msg_bit() macro
- X defined in mush.h. It should be fairly trivial to generate an
- X equivalent function.
- X
- X Silicon Graphics Iris workstations should add -DDIRECTORY to the CFLAGS
- X in the makefile. This prevents the portable directory routines from
- X being compiled in.
- X
- XIf you are using Ultrix:
- X
- X Start with makefile.bsd.
- X
- X For Ultrix 2.2, change LIBES in makefile.bsd from
- X LIBES= -lcurses -ltermlib
- X to
- X LIBES= -lcurses -ltermcap
- X
- X For Ultrix V3.0, use the standard makefile.bsd LIBES, but add
- X -DSIGRET=void
- X to the CFLAGS, or add
- X #define SIGRET void
- X to config.h (see discussion below).
- X
- XIf you are using HP-UX:
- X
- X Use makefile.hpux.
- X
- X Versions 6.5 and 7.0 of HP-UX (not to be confused with the same
- X version numbers of Mush) have the Berkeley-style directory access
- X libraries. Those using older versions should omit -DDIRECTORY
- X from the CFLAGS. This will cause the portable directory access
- X routines in that file to be compiled.
- X
- XWhen you decide on an appropriate makefile, _copy_ it to a new file called
- XMakefile _before_ making any of local changes. Please read the following
- Xsections for addtional configuration information. In addition to changing
- Xcompilation options as appropriate, you should examine the rules for the
- X"install:" target. Running "make" will NOT use this target by default;
- Xit is provided for your convenience only.
- X---------------
- X
- XYour Mail Transport Agent:
- XSendmail:
- X Mush was originally designed to use sendmail as the Mail Transport Agent.
- X However, other MTA's will work. The MTA you use should be defined in
- X config.h under the MAIL_DELIVERY macro define. By default,
- X /usr/lib/sendmail -i
- X is used -- the option, -i, tells sendmail not to accept "." on a line
- X by itself as an end-of-file marker. This has been obsleted by "-oi",
- X but "-i" still works and is backwards compatible with older sendmails.
- X
- XDelivermail:
- X Some mailers such as delivermail and MMDF use special strings to separate
- X messages stored in a folder. Older delivermail versions would use "^C".
- X Whatever your system uses, if it is NOT "From " (just the first 5 chars
- X on a line matching "From "), then this string should be defined in
- X config.h with the MSG_SEPARATOR macro.
- X
- XMMDF:
- X NOTE: MMDF sites can define MMDF and not worry about MSG_SEPARATOR. See
- X config.h-dist if you run MMDF.
- X
- X Since MMDF can deliver users' mail in their home directories, there is
- X a define to specify this option: -DHOMEMAIL
- X
- X Since MMDF uses its own libraries to do file locking, you should add the
- X appropriate library to the LIBS list in your makefile.
- X
- X MMDF sites should probably NOT define PICKY_MAILER (see below).
- X
- XAll others:
- X Chances are, your MTA uses the "From " format to separate messges in
- X a folder. This includes, /bin/mail, rmail, smail, execmail, and so on.
- X Unless you *know* otherwise, assume this to be the case with your MTA.
- X
- X If no MSG_SEPARATOR is specified, what mush looks for is a pattern of
- X From <string> <date format>
- X The "string" is usually the return address of the sender and the date
- X format is supposed to be in ctime(3) format. Even still, some MTAs
- X don't conform completely to this standard and vary slightly in
- X implementation. The function load_folder() (which reads in messages)
- X contains a scanf which looks for this format to verify that this is
- X indeed a new message being scanned. If you install mush and find that
- X you are entering a shell, but mush indicates there are no messages in
- X the folder, it could be that you have a weird "From " line format and
- X the scanf() call needs to be either modified or removed.
- X
- X Machines that use mail transfer agents that *do not* use a colon-less
- X "From " line as a message separator should #define in config.h the string
- X MSG_SEPARATOR. Since this string is usually control characters, you
- X need to specify actual ascii values for those characters. Users of MMDF,
- X for example, may use "\001\001\001\001" since some mmdf versions use four
- X control-A's to separate messages. This message separator assumes that
- X there is a carriage return at the end of the string. Systems that use
- X sendmail need not concern themselves with this define. MSG_SEPARATOR
- X should not contain a newline, except for MMDF. The MSG_SEPARATOR must
- X match a complete line; a prefix will not work.
- X
- X#defines specifically for your MTA:
- X
- XMSG_SEPARATOR
- X See the discussion above.
- X
- XUUCP
- X This should be defined if your MTA does not automatically create a
- X From: header *and* your machine talks to other computers via uucp.
- X If defined, the From: line created specifies the user's address in
- X UUCP format (host!user). Otherwise, arpa format is used (user@host).
- X Also, return addresses generated from RFC822 route specs will be put
- X in UUCP format with a complete path.
- X
- XMTA_EXIT
- X The exit code of a successful delivery of a message by your MTA.
- X This is typically 0, but MMDF sites should define 9 (see config.h-dist).
- X
- XNO_COMMAS
- X If your mailer does *NOT* like commas between addresses (smail sites,
- X xenix and sys-v machines), then you should define NO_COMMAS. Otherwise,
- X you will get mailer-daemon [type] messages back when trying to send mail
- X to multiple users. Sendmail should not define this.
- X
- XVERBOSE_ARG
- X If your mailer does NOT have a verbose option, then you should not have
- X VERBOSE_ARG defined. Otherwise, define it to be whatever the verbose
- X argument is for your mailer. The default is -v.
- X
- XMETOO
- X Sendmail uses the -m argument to say, "metoo" -- when sending to sendmail
- X aliases (e.g. mailing lists), sendmail will expand the alias, but if your
- X address appears in the expansion, you are excluded from getting your own
- X mail. However, if you have the variable metoo set with your variables,
- X then the METOO argument is passed to sendmail to say, "I know I'm on this
- X mailing list, but send me a copy of my message even tho I sent it." For
- X sendmail, this is -m. If your mailer uses something else, then define
- X METOO_ARG in the config.h file. If you don't have it (sys-v), then this
- X should not be defined.
- X
- XPICKY_MAILER
- X Most RFC822 compliant mailers (sendmail) will add the headers From:
- X and Date: on outgoing mail. If the user or UA sends these headers,
- X most MTAs will not append them automatically. However, there are
- X certain MTAs which will not allow this -- these "picky mailers" will
- X precede such headers with a '>' and make the headers very ugly and
- X somewhat redundant or contradictory. It's hard to determine whether
- X or not your MTA will do this without actually sending mail to yourself.
- X However, it is advised to set this *unless* your mailer is not RFC822-
- X compliant (used to be defined by OLD_MAILER in previous mush releases).
- X
- X PICKY_MAILER should NOT normally be defined when MMDF is defined.
- X
- XDOT_LOCK
- X Different systems use different locking mechanisms. By default,
- X mush uses one of flock(), locking(), or lockf() (depending on your
- X system). Some systems use a file called the same name as the file
- X you're locking with an appended ".lock" at the end (some Xenix's use
- X /tmp/$USER.mlk). If you define DOT_LOCK, mush will first check for the
- X .lock file. If it exists, mush loops until it goes away and then mush
- X creates it mode 600. Regardless of whether you use dot-locking, mush
- X will continue to try to use flock(), or whatever.
- X
- X Dot-locking requires mush to have write access to the directory where
- X your mailbox exists. Normally, this directory isn't writable by the
- X average user, so to do this you may have to sgid mush to the group id
- X of the owner of that directory. Mush will get the effective gid at the
- X beginning of the program and immediately reset it to your real gid until
- X the time it needs to lock the file occurs. It changes back to the sgid,
- X locks, then returns to normal. There shouldn't be a security problem.
- X
- X If you don't know what any of this means, ignore DOT_LOCK.
- X
- X Another warning is that some MTA's don't even follow their own protocol.
- X System V, it has been reported, creates the .lock file without checking
- X to see if it exists (therefore ruining someone else's lock).
- X
- X---------------
- XSignals:
- X
- XSIGRET
- X When signals occur in unix, the program can identify a function to be
- X called whenever a specific signal interrupts the process. That function
- X returns one of two types in unix: int and void. Because the return value
- X of this function is always ignored, many unix systems are converting
- X their definition of this function from int to void. Mush has a define:
- X SIGRET which defines what the function should return.
- X
- X By default, SIGRET is defined to be "int", except for SunOS4.0, where
- X it is defined to be "void".
- X
- X Some System-V, some Ultrix and some Xenix machines should also define
- X SIGRET to be void. If you don't know, leave it alone. If you guess
- X wrong, you will get compiler "warnings" on lines that read:
- X on_intr();
- X off_intr();
- X---------------
- XMemory allocation:
- X
- XINTERNAL_MALLOC
- X Mush depends on the xfree() function to detect invalid pointers, so
- X that they will not be incorrectly passed to free(). Some system
- X organizations make this very difficult, if not impossible. 80286-based
- X machines in certain memory models, AT&T 3b2s and 3b15s, and others have
- X these difficulties; VAX, Sun, Sequent, Apollo, and most 680x0 and many
- X 80386-based machines do not. Changes have been made to xfree() to
- X handle the AT&T machines, but if you aren't sure about your machine,
- X or if you get unexpected segmentation faults, define INTERNAL_MALLOC.
- X SysV users may want to define this anyway, because the internal malloc
- X may be faster than the default malloc(3).
- X
- X By default, INTERNAL_MALLOC is undefined.
- X
- X---------------
- XMiscellaneous defines:
- X
- XTIMEZONE
- X If this is defined, the string it is defined to is used as your timezone
- X regardless of what the system thinks your timezone is. This is intended
- X for systems which have no functions for determining the timezone. On
- X newer Gould BSD 4.3 systems, it is safe to use
- X #define TIMEZONE T->tm_zone
- X On other systems, it is better to define TIMEZONE as a string, e.g.
- X #define TIMEZONE "PST" /* Or "-0800" for MH style */
- X
- XDAYLITETZ
- X This should be defined to your Daylight Savings Time timezone string if
- X and only if you also define TIMEZONE (above). Do not define this if you
- X use the Gould tm_zone.
- X
- XVPRINTF
- X This should be defined if your system has the vprintf functions. You
- X *have* these functions if you are running:
- X o system V
- X o xenix
- X o Sun release 3.0 or higher.
- X If you are still not sure, try the following command from your shell:
- X
- X % ar t /lib/libc.a | grep vprintf
- X
- X If you have it, you'll probably get something like
- X vprintf.o
- X vsprintf.o
- X as output. If you don't have it, you won't have any output. If your
- X main C-libraries are not in /lib/libc.a, then find where they are and
- X try the same command using that file. BSD machines before 4.3-tahoe
- X do not have vprintf().
- X
- X---------------
- XThe sprintf() function:
- X If you *know* your system's sprintf returns a char *, you can remove the
- X #define sprintf Sprintf
- X in strings.h. Careful, not all BSD4.3 machines are alike! If you don't
- X know for sure, don't change this define.
- X
- X---------------
- XRegular expression defines:
- X Some systems have regcmp/regex as their regular expression matching
- X routines while others have re_comp/re_exec -- If you have regcmp,
- X you should define REGCMP so that you will use the routines regcmp()
- X and regex() as the regular expression composer/parser. REGCMP should
- X normally be defined for xenix and System-V Unix. If you don't have
- X REGCMP defined, then the routines re_comp() and re_exec() are used
- X (this is the default for mush).
- X
- X Note that some systems do not have either set of routines in the default
- X libraries. You must find the library to use and add it to the list of
- X libraries to use. If this is the case, your link will fail with the
- X errors that regex and re_comp are undefined functions. Read your man
- X page for regex(3) to find where to locate those libraries.
- X
- X---------------
- XThe Berkeley directory(3) routines:
- X If your system has directory access routines compatible with BSD Unix
- X (opendir, readdir, closedir) you should define DIRECTORY in either the
- X makefile or config.h. This is already reflected in the makefile.hpux.
- X See the notes above for other Sys-V-ish systems that may require this.
- X If DIRECTORY is not defined, replacement routines in glob.c are used.
- X
- X---------------
- XThe select() function call:
- X Mush uses select() to implement macros, mappings and bindings. If your
- X system is a BSD system, then this is defined for you. However, with the
- X advent of hybrid bsd/sys-v systems, you may not be able to set BSD, but
- X you know you still have select() --for such systems, define SELECT in
- X your makefile or in config.h.
- X
- X Newer xenix machines have this as so some system-v machines. If you don't
- X define one of BSD or SELECT, mush will use another function although not
- X as optimal as select().
- X
- X---------------
- XThe default Mushrc startup file:
- X A default mushrc should be installed, containing local configuration
- X information (aliases or variable settings). This can also provide
- X first-time users with a more friendly interface. UCB mail's default
- X Mail.rc works, but no default file works also. The location of the
- X default file should be defined in config.h. To have no default Mushrc,
- X set the default to /dev/null.
- X
- X The Mushrc file supplied with the mush distribution is heavily commented
- X and uses several of mush's features in setting up the interface. THIS
- X FILE IS NOT INTENDED TO BE USED WITHOUT LOCAL MODIFICATIONS! If you
- X use this file, you should modify it so settings of the variables MAILRC,
- X ALTERNATE_RC, and ALT_DEF_RC correspond to the definitions in your
- X config.h file. You should also examine and possibly delete the help
- X section for new users (creates the .mushuser/.mushexpert files), which is
- X included mainly as an example. The Mushrc is designed to source the
- X ALT_DEF_RC, which is usually equivalent to the UCB mail Mail.rc. This
- X eases the transition to mush for UCB sites, and allows aliases and
- X settings that should apply to both mush and mail to reside in a single
- X file. UUCP sites may also want to uncomment the line which sets the
- X auto_route and known_hosts variables; be sure to modify known_hosts to be
- X an accurate list of your UUCP mail neighbors.
- X
- X Important Note to sys-v'ers who can't get their hostname from utsname(2)
- X (xenix, more?), the hostname should probably be set in the default Mailrc
- X defined in config.h. set hostname=whatever
- X
- X If your system has a LAN or UUCP name returned by gethostname(3) and
- X an additional network mail (domain) name, you probably want to add the
- X domain name to the value of hostname. set hostname="domain $hostname"
- X (where "domain" is your local domain name). Sometimes, the domain name
- X is listed among the alternate names for the machine, which mush is able
- X to look up, but will not be the first name mush finds. Since mush uses
- X the first name listed in $hostname when constructing From: lines and
- X the like, you may need to use a "set" in Mushrc to rearrange the list.
- X
- X For sun systems, the sun Mail Mailrc (/usr/lib/Mailrc) does not work
- X very well because sun's Mail is not standard /usr/ucb/Mail. For this
- X reason, sun has not changed the default Mail.rc which still resides
- X in /usr/lib/Mail.rc (note this has the "." whereas the other file
- X does not). The default config.h-dist reflects this.
- X
- X There is a supplied Mailrc file with mush, but this is only intended to
- X be used as an example of how to make mush look like ucbMail. This is a
- X _reduction_ in functionality and its usage is not encouraged. It is
- X provided for those who wish to "invisibly" replace UCB mail with mush.
- X
- X There is a Gnurc file, also supplied as an example, which can aid in
- X making mush's curses mode appear similar to gnu-emacs (NOT Rmail).
- X
- X The files sample.mushrc and advanced.mushrc are intended as samples of
- X individual users' ~/.mushrc files. There is some overlap from Mushrc
- X in sample.mushrc; in particular, if you use Mushrc as the default file,
- X the sample.mushrc need not source ~/.mailrc.
- X
- X---------------
- XHelp files:
- X The help files should be placed somewhere which is readable and accessible
- X by all. Failing to do so removes virtually the entire help facility's
- X ability to help anyone. There is a help file (cmd_help) for command help
- X (e.g. "command -?"), and the file tool_help is for the graphics mode (Sun
- X workstations only). You should define where you want these files in
- X config.h so at runtime, they can be accessed without error. If for some
- X reason you can't define a location at run-time, you can change Mushrc
- X to set the variables $cmd_help and $tool_help to the correct locations.
- X
- X---------------
- X
- XYou should now be able to run make. You may wish to use the target "install"
- Xto put the mush binary and the help and init files in their proper places; be
- Xsure to correct the destination directories in the Makefile you have selected,
- Xand to doublecheck file path names in the init files.
- X
- X---------------
- XMaintenance:
- X
- XIf you want to use dbx or any other debugger, or to use your default tty
- Xdriver, -e should be used as command line argument when you run the program.
- XWhat this flag does is prevents your echo from being turned off and leaving
- Xcbreak off, thus, keeping your tty in a sane state. This prevents the use
- Xof mappings and macros (map and map!). However, curses mode will automatic-
- Xally disable that mode. The -e flag is highly discouraged.
- X
- XIf you have memory allocation checking and validation (sun 3.0+ ?) then
- Xdefine M_DEBUG in the makefile (main.c) and add the library
- X/usr/lib/debug/malloc.o to the library list. Do this only if you
- Xfind bugs in the program and suspect memory allocation errors. main.c
- Xhas the code which sets the debugging level according to the value of
- Xan environment variable. Because malloc-debugging is so cpu intensive,
- Xthe tool mode program may get a SIGXCPU (cpu time limit exceeded)
- Xbecause of the large amount of opening and closing large pixrects and
- Xdevices. For this reason, SIGXPCPU is is caught in main.c.
- X
- XThe "warning" variable may be set (at runtime in your .mushrc or as
- Xa command: "set warning") to aid in finding runtime errors that aren't
- Xfatal. You can also use the "debug" command:
- X debug 1 -- general trace messages
- X debug 3 -- verbose messages, MTA disabled
- X debug 4 -- really verbose messages
- X debug 5 -- free() disabled
- X
- XIf you ever get "Message N has bad date: <date string>" then note
- Xthe FORMAT of that date and edit dates.c. There are a number of
- X"sscanf"s which you can see match known date formats. Use them as
- Xexamples and insert the new date format you have.
- X
- XIf Mush ever coredumps and you are suspicious about whether or not
- Xyour folder (or spool directory) was removed, or if you were editing
- Xa letter, you should check for the files .mushXXXXXX and .edXXXXXXX.
- XUnless something incredibly awful has happened, Mush won't die without
- Xasking if you want to save the .mushXXXXX file and if you actually want
- Xit to dump core. Note that if you run mush from .suntools and there is
- Xa core dump, it probably wants to do some IO with the console and may
- Xhang (not exit) because it doesn't know it can't talk to you. If mush
- Xis killed by SIGHUP, it won't remove the .mushXXXXXX file, but it won't
- Xtell you about it either (unfortunately).
- X
- XBare-bones line-mode mush (no CURSES) and tool mode (SUNTOOL) pass lint
- Xwith a small number of errors, mostly about long assignments losing accuracy.
- XThe SysV code has not been linted as thoroughly as the rest. Curses doesn't
- Xlint very well, but even when you lint mush with CURSES defined, it mainly
- Xcomplains about the unused curses globals in curses.h.
- END_OF_FILE
- if test 25704 -ne `wc -c <'mush/README'`; then
- echo shar: \"'mush/README'\" unpacked with wrong size!
- fi
- # end of 'mush/README'
- fi
- if test -f 'mush/mail.c.b' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'mush/mail.c.b'\"
- else
- echo shar: Extracting \"'mush/mail.c.b'\" \(26265 characters\)
- sed "s/^X//" >'mush/mail.c.b' <<'END_OF_FILE'
- X }
- X if (c == 'd') {
- X rm_edfile(-2);
- X return 0;
- X } else if (c == 'c') {
- X wprint("(continue editing letter)\n");
- X return -1;
- X } else if (c == 's')
- X break;
- X }
- X }
- X }
- X
- X if (send_it() == -1) {
- X if (isoff(flags, SEND_NOW))
- X wprint("(continue)\n");
- X return -1;
- X }
- X return 0;
- X}
- X
- X/*
- X * actually send the letter.
- X * 1. reset all the signals because of fork.
- X * 2. determine recipients (users, address, files, programs)
- X * 3. determine mailer, fork and return (if not verbose).
- X * 4. popen mailer, $record, and other files specified in step 1.
- X * 5. make the headers; this includes To: line, and user set headers, etc...
- X * 6. copy the letter right into the array of file pointers (step 1).
- X * 7. close the mailer and other files (step 1) and remove the edit-file.
- X * return -1 if mail wasn't sent. could be user error, could be the system.
- X * allow user to try again or to save message to file and abort message.
- X * return 0 if successful.
- X */
- Xstatic int
- Xsend_it()
- X{
- X register char *p, *b, *addr_list;
- X#ifdef MAXFILES
- X register int size = MAXFILES - 1;
- X FILE *files[MAXFILES];
- X char *names[MAXFILES];
- X#else
- X register int size = getdtablesize() - 1;
- X FILE *files[30]; /* 30 should be sufficiently large enough */
- X char *names[30];
- X#endif /* MAXFILES */
- X#if defined(VERBOSE_ARG) && !defined(SUNTOOL)
- X SIGRET (*oldchld)();
- X#endif /* VERBOSE_ARG && !SUNTOOL */
- X int next_file = 1; /* reserve files[0] for the mail delivery program */
- X int log_file = -1; /* the index into the files array for mail logging */
- X char buf[3*HDRSIZ];
- X char *orig_to, *orig_cc, *orig_bcc; /* save originals to restore on error */
- X char expand = !do_set(set_options, "no_expand");
- X int fork_err = 0;
- X
- X names[0] = names[1] = NULL; /* for free_vec() */
- X /* If edit_hdrs, make sure the correct headers exist and are intact
- X * before bothering to continue.
- X */
- X if (ison(flags, EDIT_HDRS)) {
- X /* fool header_field into thinking that the file is the folder */
- X FILE *save_tmpf = tmpf;
- X long old_offset = msg[msg_cnt].m_offset;
- X
- X if (!ed_fp) {
- X wprint("No file for headers!\n");
- X return -1;
- X }
- X Debug("Getting headers from file ... ");
- X
- X tmpf = ed_fp;
- X msg[msg_cnt].m_offset = 0L;
- X if (p = header_field(msg_cnt, "to")) {
- X (void) strcpy(To, p);
- X Cc[0] = Bcc[0] = 0;
- X if (p = header_field(msg_cnt, "cc"))
- X (void) strcpy(Cc, p);
- X if (p = header_field(msg_cnt, "bcc"))
- X (void) strcpy(Bcc, p);
- X if (p = header_field(msg_cnt, "fcc"))
- X next_file += find_files(p, names+next_file, size-next_file, 1);
- X } else
- X *To = 0; /* Error caught below */
- X msg[msg_cnt].m_offset = old_offset;
- X tmpf = save_tmpf;
- X Debug("\n");
- X }
- X if (!*To) {
- X wprint("You must have a To: recipient to send mail.\n");
- X if (!istool) {
- X (void) signal(SIGINT, oldint);
- X (void) signal(SIGQUIT, oldquit);
- X (void) signal(SIGTERM, oldterm);
- X }
- X free_vec(&names[1]);
- X return -1;
- X }
- X
- X if (!(p = do_set(set_options, "sendmail")))
- X p = MAIL_DELIVERY;
- X
- X#ifdef VERBOSE_ARG
- X if (ison(flags, VERBOSE) || do_set(set_options, "verbose")) {
- X turnon(flags, VERBOSE); /* prevent fork when "verbose" has changed */
- X#ifndef SUNTOOL
- X oldchld = signal(SIGCHLD, SIG_DFL); /* let pclose() do the wait() */
- X#endif /* SUNTOOL */
- X#ifdef MMDF
- X b = &buf[strlen(sprintf(buf, "%s%s", p, VERBOSE_ARG))];
- X#else /* MMDF */
- X b = &buf[strlen(sprintf(buf, "%s %s", p, VERBOSE_ARG))];
- X#endif /* MMDF */
- X } else
- X#endif /* VERBOSE_ARG */
- X b = buf + Strcpy(buf, p);
- X#ifdef METOO_ARG
- X if (!strcmp(p, MAIL_DELIVERY) && do_set(set_options, "metoo"))
- X b += strlen(sprintf(b, " %s", METOO_ARG));
- X#endif /* METOO_ARG */
- X *b++ = ' ', *b = 0; /* strcat(b, " "); */
- X addr_list = b; /* save this position to check for addresses later */
- X
- X /* save original list. If alias expansion fails, replace address lists
- X * with what was originally typed so user can fix it. This isn't necessary
- X * if the lists are already in the file the user is editing (edit_hdrs).
- X */
- X if (isoff(flags, EDIT_HDRS))
- X orig_to = savestr(To);
- X /*
- X * Build the address lines to give to the mail transfer system. This
- X * address line cannot contain comment fields! First, expand aliases
- X * since they may contain comment fields within addresses. Copy this
- X * result back into the Buffer since this will go into the header ...
- X * Next, remove all comments so the buffer contains ONLY valid addresses.
- X * Next, strip off any filenames/programs which might occur in the list.
- X * Finally, add this information to the command line buffer (buf).
- X * Remove commas if necessary (see ifdefs). In the event of errors,
- X * force a dead letter by rm_edfile(-1).
- X */
- X if (!(p = alias_to_address(To))) {
- X print("address expansion failed for To: list.\n");
- X free_vec(&names[1]);
- X if (isoff(flags, EDIT_HDRS))
- X strcpy(To, orig_to), xfree(orig_to);
- X return -1;
- X } else {
- X next_file += find_files(p, names+next_file, size-next_file, 0);
- X if (expand)
- X (void) strcpy(To, p);
- X rm_cmts_in_addr(p);
- X skipspaces(0);
- X b += Strcpy(b, p);
- X }
- X if (isoff(flags, EDIT_HDRS))
- X orig_cc = savestr(Cc);
- X if (*Cc) {
- X if (!(p = alias_to_address(Cc))) {
- X wprint("address expansion failed for Cc: list.\n");
- X free_vec(&names[1]);
- X if (isoff(flags, EDIT_HDRS)) {
- X strcpy(To, orig_to), xfree(orig_to);
- X strcpy(Cc, orig_cc), xfree(orig_cc);
- X }
- X return -1;
- X } else {
- X next_file += find_files(p, names+next_file, size-next_file, 0);
- X if (expand)
- X (void) strcpy(Cc, p);
- X rm_cmts_in_addr(p);
- X skipspaces(0);
- X if (*p) {
- X *b++ = ',', *b++ = ' ';
- X b += Strcpy(b, p);
- X }
- X }
- X }
- X
- X /* expand Bcc addrs, but don't add to list yet. sign letter first */
- X if (isoff(flags, EDIT_HDRS))
- X orig_bcc = savestr(Bcc);
- X if (*Bcc) {
- X if (p = alias_to_address(Bcc))
- X p = strcpy(Bcc, p);
- X else {
- X wprint("address expansion failed for Bcc: list.\n");
- X free_vec(&names[1]);
- X /* rm_edfile(-1); */
- X if (isoff(flags, EDIT_HDRS)) {
- X strcpy(To, orig_to), xfree(orig_to);
- X strcpy(Cc, orig_cc), xfree(orig_cc);
- X strcpy(Bcc, orig_bcc), xfree(orig_bcc);
- X }
- X return -1;
- X }
- X } else
- X p = NULL;
- X
- X /* Sign the letter before adding the Bcc list since they aren't
- X * considered when adding a signature.
- X */
- X if (*addr_list && ison(flags, SIGN|DO_FORTUNE) &&
- X isoff(glob_flags, REDIRECT) && isoff(flags, FORWARD))
- X sign_letter(addr_list, flags, ed_fp);
- X
- X if (p) { /* p still points to expanded Bcc list */
- X next_file += find_files(p, names+next_file, size-next_file, 0);
- X rm_cmts_in_addr(p);
- X skipspaces(0);
- X if (*p) {
- X *b++ = ',', *b++ = ' ';
- X b += Strcpy(b, p);
- X }
- X }
- X if (!*addr_list && next_file == 1) {
- X wprint("There must be at least 1 legal recipient.\n");
- X if (isoff(flags, EDIT_HDRS)) {
- X strcpy(To, orig_to), xfree(orig_to);
- X strcpy(Cc, orig_cc), xfree(orig_cc);
- X strcpy(Bcc, orig_bcc), xfree(orig_bcc);
- X }
- X return -1;
- X }
- X
- X#ifdef NO_COMMAS
- X for (p = buf; p = index(p, ','); p++)
- X *p = ' ';
- X#endif /* NO_COMMAS */
- X
- X Debug("mail command: %s\n", buf);
- X
- X if (isoff(flags, VERBOSE) && debug < 3)
- X switch (fork()) {
- X case 0: /* the child will send the letter. ignore signals */
- X#ifdef SYSV
- X if (setpgrp() == -1)
- X#else /* SYSV */
- X if (setpgrp(0, getpid()) == -1)
- X#endif /* SYSV */
- X error("setpgrp");
- X#ifndef SUNTOOL
- X (void) signal(SIGCHLD, SIG_DFL);
- X (void) signal(SIGTERM, SIG_IGN);
- X#endif /* SUNTOOL */
- X (void) signal(SIGINT, SIG_IGN);
- X (void) signal(SIGHUP, SIG_IGN);
- X (void) signal(SIGQUIT, SIG_IGN);
- X#ifdef SIGTTIN
- X (void) signal(SIGTTOU, SIG_IGN);
- X (void) signal(SIGTTIN, SIG_IGN);
- X#endif /* SIGTTIN */
- X#ifdef SIGCONT
- X (void) signal(SIGCONT, SIG_IGN);
- X (void) signal(SIGTSTP, SIG_IGN);
- X#endif /* SIGCONT */
- X turnon(glob_flags, IGN_SIGS);
- X when -1:
- X error("fork failed trying to send mail");
- X fork_err++;
- X if (isoff(flags, EDIT_HDRS)) {
- X strcpy(To, orig_to);
- X strcpy(Cc, orig_cc);
- X strcpy(Bcc, orig_bcc);
- X }
- X /* fall thru */
- X default:
- X /* istool doesn't need ed_fp, so don't keep it around */
- X if (istool || !fork_err && isoff(glob_flags, REDIRECT))
- X (void) fclose(ed_fp), ed_fp = NULL_FILE;
- X free_vec(&names[1]);
- X if (isoff(flags, EDIT_HDRS))
- X xfree(orig_to), xfree(orig_cc), xfree(orig_bcc);
- X if (!istool) {
- X (void) signal(SIGINT, oldint);
- X (void) signal(SIGQUIT, oldquit);
- X (void) signal(SIGTERM, oldterm);
- X }
- X return 0 - fork_err;
- X }
- X
- X
- X#ifdef MMDF
- X *(addr_list-1) = '\0';
- X#endif /* MMDF */
- X if (debug > 2) {
- X files[0] = stdout;
- X if (!*addr_list)
- X addr_list = "[no recipients]";
- X } else if (*addr_list) {
- X if (!(files[0] = open_file(buf, TRUE, FALSE))) {
- X rm_edfile(-1); /* force saving of undeliverable mail */
- X if (isoff(flags, VERBOSE) && debug < 3)
- X exit(-1);
- X else
- X return 0;
- X }
- X } else
- X files[0] = NULL_FILE;
- X
- X if (ison(flags, VERBOSE))
- X wprint("Sending letter ... "), (void) fflush(stdout);
- X#ifdef MMDF
- X /* give address list to submit */
- X for (p = addr_list; *p && (p = any(p, ",<")); p++)
- X if (*p == ',')
- X *p = '\n';
- X else
- X p = index(p, '>');
- X if (*addr_list)
- X (void) fprintf(files[0], "%s\n\n", addr_list);
- X#endif /* MMDF */
- X
- X /* see if log is set. This is just to add message headers. No msg body. */
- X if (p = do_set(set_options, "logfile")) {
- X if (!*p)
- X p = "~/mail.log";
- X if (!index("~|/+", *p))
- X (void) sprintf(buf, "%s/%s", do_set(set_options, "cwd"), p);
- X else
- X (void) strcpy(buf, p);
- X log_file = next_file;
- X next_file += find_files(buf, names+next_file, size-next_file, 0);
- X if (log_file == next_file)
- X log_file = -1;
- X }
- X
- X /* see if record is set. If so, open that file for appending and add
- X * the letter in a format such that mail can be read from it
- X */
- X if (p = do_set(set_options, "record")) {
- X if (!*p)
- X p = "~/record";
- X if (!index("~|/+", *p))
- X (void) sprintf(buf, "%s/%s", do_set(set_options, "cwd"), p);
- X else
- X (void) strcpy(buf, p);
- X next_file += find_files(buf, names+next_file, size-next_file, 0);
- X }
- X
- X /* Don't need to open names[0] as files[0], so skip those */
- X next_file = 1 + open_list(names + 1, files + 1, next_file - 1);
- X
- X /* First, put the message separator in... */
- X for (size = 1; size < next_file; size++)
- X#ifndef MSG_SEPARATOR
- X {
- X time_t t;
- X (void) time(&t);
- X (void) fprintf(files[size], "From %s %s", login, ctime(&t));
- X }
- X#else /* MSG_SEPARATOR */
- X#ifdef MMDF
- X (void) fputs(MSG_SEPARATOR, files[size]);
- X#else /* MMDF */
- X (void) fprintf(files[size], "%s\n", MSG_SEPARATOR);
- X#endif /* MMDF */
- X#endif /* MSG_SEPARATOR */
- X
- X /* if redirection, ed_fp = stdin, else rewind the file just made */
- X if (isoff(glob_flags, REDIRECT))
- X rewind(ed_fp);
- X else
- X ed_fp = stdin;
- X
- X#ifndef MSG_SEPARATOR
- X /* If forwarding or reading a draft, skip the leading From_ line.
- X * This is done for drafts so that messages saved by dead_letter()
- X * can be read back in as a draft; in other cases, this isn't done
- X * for edit_hdrs because FORWARD wouldn't be set.
- X */
- X if (ison(flags, FORWARD|SEND_NOW) && fgets(buf, sizeof buf, ed_fp) &&
- X strncmp(buf, "From ", 5) != 0)
- X rewind(ed_fp); /* No From_ line (should never happen) */
- X#endif /* MSG_SEPARATOR */
- X {
- X long offset = add_headers(ed_fp, files, next_file, flags);
- X if (offset == -1)
- X offset = 0L;
- X (void) fseek(ed_fp, offset, L_SET);
- X }
- X
- X /* Read from stdin or the edfile till EOF and send it all to the mailer
- X * and other open files/folders/programs. Check for "From " at the
- X * beginnings of these lines to prevent creating new messages in folders.
- X */
- X while (fgets(buf, sizeof buf, ed_fp))
- X for (size = 0; size < next_file; size++) {
- X if (!files[size]) /* files[0] will be NULL if not calling MTA */
- X continue;
- X if (size == log_file)
- X continue;
- X#ifndef MSG_SEPARATOR
- X if (!strncmp(buf, "From ", 5))
- X (void) fputc('>', files[size]);
- X#endif /* MSG_SEPARATOR */
- X if (fputs(buf, files[size]) == EOF) {
- X if (size == 0) {
- X error("Lost connection to MTA");
- X dead_letter(-1);
- X break;
- X } else {
- X /* Drop this file, but continue writing others */
- X if (names[size]) {
- X error("Write failed: %s", names[size]);
- X (void) close_lock(names[size], files[size]);
- X xfree(names[size]);
- X } else
- X error("Write failed");
- X if (size < --next_file) {
- X names[size] = names[next_file];
- X files[size--] = files[next_file];
- X }
- X files[next_file] = NULL_FILE;
- X names[next_file] = NULL;
- X }
- X }
- X }
- X
- X /* loop thru the open files (except for the first: the mail delivery agent)
- X * and append a blank line so that ucb-mail can read these folders.
- X * Then close the files.
- X */
- X for (size = 1; size < next_file; size++) {
- X#ifdef END_MSG_SEP
- X (void) fputs(END_MSG_SEP, files[size]);
- X#endif /* END_MSG_SEP */
- X if (names[size]) {
- X#ifndef END_MSG_SEP
- X (void) fputc('\n', files[size]);
- X#endif /* !END_MSG_SEP */
- X if (close_lock(names[size], files[size]) == EOF) {
- X error("Warning: Close failed: %s", names[size]);
- X }
- X xfree(names[size]);
- X } else {
- X if (debug < 3)
- X (void) fclose(files[size]); /* Don't mess with pclose() */
- X else
- X (void) pclose(files[size]); /* unless we never forked */
- X }
- X }
- X
- X if (debug < 3) {
- X int reply_code = files[0]? pclose(files[0]) : (MTA_EXIT << 8);
- X Debug("pclose reply_code = %d\n", reply_code);
- X rm_edfile((reply_code == (MTA_EXIT << 8))? 0 : -1);
- X } else
- X rm_edfile(0);
- X
- X#ifndef SUNTOOL
- X#ifdef VERBOSE_ARG
- X if (ison(flags, VERBOSE))
- X (void) signal(SIGCHLD, oldchld);
- X#endif /* VERBOSE_ARG */
- X#endif /* SUNTOOL */
- X
- X if (ison(flags, VERBOSE) || debug > 2) {
- X if (isoff(glob_flags, REDIRECT))
- X wprint("sent.\n");
- X if (!istool) {
- X (void) signal(SIGINT, oldint);
- X (void) signal(SIGQUIT, oldquit);
- X (void) signal(SIGTERM, oldterm);
- X }
- X } else
- X exit(0); /* not a user exit -- a child exit */
- X return 0;
- X}
- X
- X/*
- X * Add the necessary headers to make a file a legitimate mail message.
- X * This could be for a file which the user will edit (via edit_hdrs) or
- X * for delivery to an MTA.
- X * Make folders conform to RFC-822 by adding From: and Date: headers.
- X * Prefix certain header with the "Resent-" prefix when forwarding.
- X * Return offset of fp if we're parsing it for headers (for delivery to MTA).
- X */
- Xstatic long
- Xadd_headers(fp, files, size, flags)
- XFILE *fp, *files[];
- Xint size;
- Xu_long flags;
- X{
- X char buf[BUFSIZ], From_buf[256], *pF = From_buf, date_str[64];
- X char *host = NULL, *p, *subj = NULL, *own_from = NULL; /* See WARNING */
- X int i, for_editor = (fp == NULL_FILE);
- X int got_date = for_editor, got_from = for_editor;
- X struct options *opts;
- X
- X if (for_editor && hfile) {
- X i = file_to_fp(hfile, files[0], "r");
- X xfree(hfile), hfile = NULL;
- X return (i < 0 ? -1 : TRUE);
- X }
- X
- X buf[0] = 0;
- X if (ourname)
- X host = ourname[0];
- X if (for_editor)
- X turnoff(flags,FORWARD); /* forwarded messages must not be edited */
- X
- X /* [Re]create a From: header -- check first to see if the user has
- X * created a From: header with the my_hdr command (the own_hdrs list).
- X * If his is not legitimate, warn user and use the other header.
- X */
- X if ((for_editor || isoff(glob_flags, EDIT_HDRS)) &&
- X own_hdrs && !do_set(set_options, "no_hdrs")) {
- X for (opts = own_hdrs; opts; opts = opts->next)
- X if (!strcmp(opts->option, "From:")) {
- X p = opts->value;
- X skipspaces(0);
- X sprintf(buf, "%sFrom: %s\n",
- X ison(flags, FORWARD)? "Resent-" : "", p);
- X own_from = buf;
- X /* WARNING: the above depends on the following facts:
- X * 1. If for_editor, own_from will be output immediately,
- X * so buf will not be overwritten;
- X * 2. If !for_editor but EDIT_HDRS, the "real" from line
- X * will be read from the file so own_from isn't needed;
- X * 3. If neither, From: is the first line output, so
- X * buf will not be overwritten.
- X * Any change in the above means a new buffer for own_from
- X * may be needed. Check carefully.
- X */
- X }
- X }
- X if (ison(flags, FORWARD))
- X pF += Strcpy(From_buf, "Resent-");
- X pF += Strcpy(pF, "From: ");
- X#ifdef UUCP
- X if (host && *host)
- X pF += strlen(sprintf(pF, "%s!", host));
- X#endif /* UUCP */
- X pF += Strcpy(pF, login);
- X#ifndef UUCP
- X if (host && *host)
- X pF += strlen(sprintf(pF, "@%s", host));
- X#endif /* UUCP */
- X if ((p = do_set(set_options, "realname")) ||
- X (p = do_set(set_options, "name")))
- X pF += strlen(sprintf(pF, " (%s)", p));
- X *pF++ = '\n', *pF++ = 0;
- X
- X /* First print From, Date, In-Reply-To */
- X for (i = 0; i < size; i++) {
- X if (!files[i])
- X continue;
- X if (for_editor)
- X if (own_from)
- X (void) fputs(own_from, files[i]), *own_from = 0;
- X else
- X (void) fputs(From_buf, files[i]);
- X else if (isoff(flags, EDIT_HDRS)) {
- X#ifdef PICKY_MAILER
- X if (i > 0)
- X#endif /* PICKY_MAILER */
- X if (own_from)
- X (void) fputs(own_from, files[i]), *own_from = 0;
- X else
- X (void) fputs(From_buf, files[i]);
- X got_from = TRUE;
- X }
- X if (for_editor || isoff(flags, EDIT_HDRS)) {
- X#ifdef PICKY_MAILER
- X if (i > 0 && !for_editor)
- X#endif /* PICKY_MAILER */
- X (void) fprintf(files[i], "%sDate: %s\n",
- X ison(flags, FORWARD) ? "Resent-" : "", rfc_date(date_str));
- X got_date = TRUE;
- X if (*in_reply_to)
- X fprintf(files[i], "In-Reply-To: %s\n", in_reply_to);
- X }
- X }
- X /* next print user's own message headers */
- X if (for_editor || isoff(flags, EDIT_HDRS))
- X if (own_hdrs && !do_set(set_options, "no_hdrs")) {
- X for (opts = own_hdrs; opts; opts = opts->next) {
- X if (!strcmp(opts->option, "From:"))
- X continue;
- X for (i = 0; i < size; i++) {
- X if (!files[i])
- X continue;
- X p = opts->value;
- X skipspaces(0);
- X fprintf(files[i], "%s %s\n", opts->option, p);
- X }
- X }
- X }
- X
- X /*
- X * Now either prepare to put the rest of the headers into the file
- X * or (when sending edited headers) copy them back out of the file
- X */
- X if (for_editor) {
- X char *orig = NULL;
- X /* for edit_hdrs, print the headers followed by a blank line */
- X if (To[0]) {
- X orig = savestr(To);
- X if (!(p = alias_to_address(To))) {
- X wprint("To: list unmodified.\n");
- X p = orig;
- X }
- X (void) strcpy(To, p);
- X }
- X if (Cc[0]) {
- X strdup(orig, Cc);
- X if (!(p = alias_to_address(Cc))) {
- X wprint("Cc: list unmodified.\n");
- X p = orig;
- X }
- X (void) strcpy(Cc, p);
- X }
- X if (Bcc[0]) {
- X strdup(orig, Bcc);
- X if (!(p = alias_to_address(Bcc))) {
- X wprint("Bcc: list unmodified.\n");
- X p = orig;
- X }
- X (void) strcpy(Bcc, p);
- X }
- X xfree(orig);
- X } else if (ison(flags, EDIT_HDRS)) {
- X /* copy the headers of the message removing special headers */
- X int print_hdr = FALSE;
- X if (isoff(flags, SEND_NOW))
- X rewind(fp); /* Drafts may have had fp positioned */
- X while (fgets(buf, sizeof(buf), fp)) {
- X (void) no_newln(buf);
- X if (!buf[0])
- X break;
- X /* if the first char is NOT a space, it MUST be a new header.
- X * Otherwise, it is considered part of the message body.
- X */
- X if (!isspace(buf[0])) {
- X print_hdr = TRUE;
- X if (!(p = any(buf, " \t:")) || isspace(*p))
- X break; /* this is not a legitimate header */
- X skipspaces(1);
- X if (!*p)
- X print_hdr = FALSE; /* blank headers are not allowed */
- X p = buf;
- X if (!lcase_strncmp(buf, "resent-", 7)) {
- X if (ison(flags, EDIT_HDRS))
- X wprint("You can't use \"Resent-\" headers in edited messages.\n");
- X p += 7;
- X }
- X if (!lcase_strncmp(p, "to:", 3) ||
- X !lcase_strncmp(p, "cc:", 3) ||
- X !lcase_strncmp(p, "bcc:", 4) ||
- X !lcase_strncmp(p, "fcc:", 4) ||
- X !lcase_strncmp(p, "x-mailer:", 9) ||
- X !lcase_strncmp(p, "status:", 7))
- X print_hdr = FALSE;
- X else if (!lcase_strncmp(p, "date:", 5))
- X if (got_date)
- X wprint("You can't change or add date headers.\n");
- X else {
- X got_date = TRUE;
- X (void) sprintf(buf, "Date: %s", rfc_date(date_str));
- X p = buf;
- X }
- X else if (!lcase_strncmp(p, "subject:", 8))
- X (print_hdr = FALSE), strdup(subj, p);
- X else if (!lcase_strncmp(p, "from:", 5)) {
- X char not_me[BUFSIZ];
- X (void) strcpy(not_me, buf + 5);
- X take_me_off(not_me);
- X if (*not_me) {
- X /* Ignore bogus From: if we have a good one */
- X if (got_from)
- X print_hdr = FALSE;
- X /* otherwise, output a good one */
- X else {
- X (void) strcpy(buf, From_buf);
- X (void) no_newln(buf);
- X }
- X }
- X got_from = TRUE;
- X#ifdef PICKY_MAILER
- X /* don't send From: to mta -- fool "for loop" below
- X * by initializing the loop at files[1], not files[0]
- X */
- X if (!for_editor)
- X print_hdr = 2;
- X#endif /* PICKY_MAILER */
- X }
- X }
- X if (print_hdr)
- X /* print_hdr may be 2 for From: header */
- X for (i = print_hdr-1; i < size; i++)
- X if (files[i]) {
- X (void) fputs(buf, files[i]);
- X (void) fputc('\n', files[i]);
- X }
- X }
- X }
- X /* Finally, do the required (or changed) headers (Date, To, Cc) */
- X (void) wrap_addrs(To, 80);
- X (void) wrap_addrs(Cc, 80);
- X (void) wrap_addrs(Bcc, 80);
- X for (i = 0; i < size; i++) {
- X if (!files[i])
- X continue;
- X#ifdef PICKY_MAILER
- X if (i > 0) {
- X#endif /* PICKY_MAILER */
- X if (!got_from)
- X if (own_from)
- X (void) fputs(own_from, files[i]);
- X else
- X (void) fputs(From_buf, files[i]);
- X if (!got_date)
- X (void) fprintf(files[i], "%sDate: %s\n",
- X ison(flags, FORWARD) ? "Resent-" : "", rfc_date(date_str));
- X#ifdef PICKY_MAILER
- X }
- X#endif /* PICKY_MAILER */
- X (void) fprintf(files[i], "X-Mailer: %s\n", check_internal("version"));
- X (void) fprintf(files[i], "%sTo: %s\n",
- X ison(flags, FORWARD) ? "Resent-" : "", To);
- X if (for_editor || isoff(flags, EDIT_HDRS)) {
- X if (isoff(flags, FORWARD) &&
- X (*Subject || for_editor && (do_set(set_options, "ask") ||
- X do_set(set_options, "asksub"))))
- X (void) fprintf(files[i], "Subject: %s\n", Subject);
- X } else if (subj && *subj && strlen(subj) > 9)
- X (void) (fputs(subj, files[i]), fputc('\n', files[i]));
- X if (*Cc || for_editor && do_set(set_options, "askcc"))
- X (void) fprintf(files[i], "%sCc: %s\n",
- X ison(flags, FORWARD) ? "Resent-" : "", Cc);
- X if (i > 0 || for_editor)
- X /* Do not send these to mail transfer agent */
- X if (*Bcc)
- X (void) fprintf(files[i], "%sBcc: %s\n",
- X ison(flags, FORWARD) ? "Resent-" : "", Bcc);
- X if (i > 0)
- X (void) fprintf(files[i], "Status: OR\n");
- X }
- X for (i = 0; i < size; i++)
- X if (files[i])
- X (void) fflush(files[i]);
- X if (buf[0]) /* last attempted header read was a line of msg text */
- X for (i = 0; i < size; i++) {
- X if (files[i]) {
- X (void) fputs(buf, files[i]);
- X (void) fputc('\n', files[i]);
- X (void) fflush(files[i]);
- X }
- X }
- X else
- X if (isoff(flags, FORWARD))
- X for (i = 0; i < size; i++)
- X if (files[i]) {
- X (void) fputc('\n', files[i]);
- X (void) fflush(files[i]);
- X }
- X return fp? ftell(fp) : (long)TRUE;
- X}
- X
- X/* ARGSUSED */
- XSIGRET
- Xrm_edfile(sig)
- X{
- X if (sig > 0) {
- X char *fix;
- X if (ison(glob_flags, IGN_SIGS))
- X return;
- X /* wrapcolumn may have been trashed -- restore it */
- X if ((fix = do_set(set_options, "wrapcolumn")) && *fix)
- X wrapcolumn = atoi(fix);
- X mac_flush(); /* abort pending macros */
- X }
- X /* now check whether we should abort the letter */
- X if (sig > 0 && !killme && ison(glob_flags, IS_GETTING)) {
- X if (!istool)
- X (void) signal(sig, rm_edfile);
- X killme = 1;
- X print("\n** interrupt -- one more to kill letter **\n");
- X longjmp(cntrl_c_buf, 1);
- X }
- X killme = 0;
- X /* if sig == -1, force a save into dead.letter.
- X * else, check for nosave not being set and save anyway if it's not set
- X * sig == 0 indicates normal exit (or ~x), so don't save a dead letter.
- X */
- X if (sig == -1 || sig != 0 && !do_set(set_options, "nosave"))
- X dead_letter(sig);
- X if (isoff(glob_flags, REDIRECT) && ed_fp) /* ed_fp may be null in toolmode*/
- X (void) fclose(ed_fp), ed_fp = NULL_FILE;
- X (void) unlink(edfile);
- X
- X turnoff(glob_flags, IS_GETTING);
- X if (sig == -1)
- X return;
- X
- X if (sig == SIGHUP)
- X cleanup(0);
- X if (!istool) {
- X (void) signal(SIGINT, oldint);
- X (void) signal(SIGQUIT, oldquit);
- X (void) signal(SIGTERM, oldterm);
- X }
- X
- X if (sig == 0 || sig == -2 || istool) /* make sure sigchld is reset first */
- X return;
- X
- X if (isoff(glob_flags, DO_SHELL)) { /* If we're not in a shell, exit */
- X puts("exiting");
- X echo_on();
- X exit(1);
- X }
- X longjmp(jmpbuf, 1);
- X}
- X
- X/* save letter into dead letter */
- Xdead_letter(sig)
- Xint sig; /* signal passed to rm_edfile() or 0 */
- X{
- X char *p, buf[BUFSIZ];
- X long t;
- X FILE *dead;
- X
- X if (ison(glob_flags, REDIRECT)) {
- X print("input redirected -- can't save dead letter.\n");
- X return;
- X }
- X /* If the file doesn't exist, get outta here. File may not exist if
- X * user generated a ^C from a promptable header and catch sent us here.
- X */
- X if (!ed_fp && Access(edfile, R_OK) != 0)
- X return;
- X /* User may have killed mush via a signal while he was in an editor.
- X * ed_fp will be NULL in this case. Since the file does exist (above),
- X * open it so we can copy it to dead letter.
- X */
- X if (!ed_fp && !(ed_fp = fopen(edfile, "r"))) {
- X error("can't save dead letter from %s", edfile);
- X return;
- X }
- X /* don't save a dead letter if there's nothing to save. */
- X if (fseek(ed_fp, 0L, 2) || ftell(ed_fp) <= 1L)
- X return;
- X if (!(p = do_set(set_options, "dead")))
- X p = "~/dead.letter";
- X if (!(dead = open_file(p + (*p == '|'), (*p == '|'), TRUE)))
- X return;
- X (void) time (&t);
- X (void) fflush(ed_fp);
- X rewind(ed_fp);
- X#ifdef MSG_SEPARATOR
- X (void) fputs(MSG_SEPARATOR, dead);
- X#ifndef MMDF
- X (void) fputc('\n', dead);
- X#endif /* MMDF */
- X#else /* MSG_SEPARATOR */
- X (void) fprintf(dead, "From %s %s", login, ctime(&t));
- X#endif /* MSG_SEPARATOR */
- X (void) fprintf(dead, "From: %s\nTo: %s\nSubject: %s\n", login, To, Subject);
- X (void) fprintf(dead, "Date: %s\n", rfc_date(buf));
- X if (*Cc)
- X (void) fprintf(dead, "Cc: %s\n", Cc);
- X if (*Bcc)
- X (void) fprintf(dead, "Bcc: %s\n", Bcc);
- X (void) fputc('\n', dead);
- X while (fgets(buf, sizeof(buf), ed_fp))
- X (void) fputs(buf, dead);
- X (void) fputc('\n', dead);
- X#ifdef END_MSG_SEP
- X (void) fputs(END_MSG_SEP, dead);
- X#endif /* END_MSG_SEP */
- X if (*p != '|')
- X (void) close_lock(p, dead);
- X else
- X (void) pclose(dead);
- X wprint("Saved%s letter in %s.\n", sig > 0? " unfinished" : "", p);
- X}
- END_OF_FILE
- if test 26265 -ne `wc -c <'mush/mail.c.b'`; then
- echo shar: \"'mush/mail.c.b'\" unpacked with wrong size!
- fi
- # end of 'mush/mail.c.b'
- fi
- echo shar: End of archive 12 \(of 19\).
- cp /dev/null ark12isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 19 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-
-