
This is patch Elm 2.4 PL25 -> Elm 2.4ME+ PL25 (25)
Warning: Elm 2.4ME+ is UNOFFICIAL!

					- K E H <hurtta+elm@ozone.FMI.FI>
-------------------------------------------------------------------------------
Index: WORK/hdrs/patchlevel.h
*** elm2.4.25/hdrs/patchlevel.h	Mon Dec  4 17:50:56 1995
--- WORK/hdrs/patchlevel.h	Tue Aug 13 15:08:59 1996
***************
*** 1 ****
! #define PATCHLEVEL "25"
--- 1 ----
! #define PATCHLEVEL "25 (25)"
Index: WORK/README.ME+
*** /tmp/null.14101	Tue Aug 20 22:05:34 1996
--- WORK/README.ME+	Tue Aug 13 15:18:50 1996
***************
*** 0 ****
--- 1,1092 ----
+ 
+ Version Elm2.4ME+ PL0 (25) is based to version Elm2.4 PL24 ME8b+.
+ Version Elm2.4 PL24 ME8b+ is based to version Elm2.4 PL24 ME8b.
+ 
+ Version Elm2.4 PL24 ME8b is done by Michael Elkins <elkins.aero.org>.
+ For details, look file ANNOUNCE.ME
+ 
+ [ Equivalent of MIME code in Elm2.4 PL24 ME8b is posted to
+   Elm Development Cordinator ]
+    
+ Version Elm2.4 PL24 ME8b is based to version Elm2.4 PL24.
+ Version Elm2.4ME+ PLx (25) includes patch of version Elm2.4 PL25.
+ 
+ Changes of Elm2.4ME+ PL25 (25) compared to Elm2.4ME+ PL24 (25)
+ --------------------------------------------------------------
+ 
+ 	- Problem with screen size (elm_LINES and elm_COLUMNS
+ 	  are inconsistent).
+           [ I was commented out line what was comment
+ 	              /* kludge for HP Window system? ... */
+             in PL23. VERY misleading........................
+ 
+ 	    I HATE this.         - K E H <hurtta@ozone.FMI.FI>
+           ]
+           
+ 
+ 	- Fix release month
+ 
+ Changes of Elm2.4ME+ PL24 (25) compared to Elm2.4ME+ PL23 (25)
+ --------------------------------------------------------------
+ 
+ 	- ks/ke capabilities are optional. They are not present
+ 	  in ANSI -terminal.
+ 	  From: "Andrey A. Chernov" <ache@nagual.ru>
+ 
+ 	- X-ELM-OSV was not correctly parsed
+ 
+ Changes of Elm2.4ME+ PL23 (25) compared to Elm2.4ME+ PL22 (25)
+ --------------------------------------------------------------
+ 
+         - Add a new config variable, called askpgpsig. 
+           When set to ON, Elm will ask for a username to 
+           sign pgp messages with. 
+           From: Guido van Rooij <guido@gvr.win.tue.nl>
+ 
+         - menu2.c: ch must be int, or comparations with -1 (EOF) 
+           and 257 (REDRAW_MARK) produce wrong results.
+           From: Andrey A. Chernov <ache@nagual.ru>
+           From: Guy Harris <guy@netapp.com>
+ 
+         - In "do_pipe()", "redraw" was both a variable and a label.
+           From: Guy Harris <guy@netapp.com>
+ 
+         - If you've set characters such as the word-erase or 
+           reprint character to non-standard values, use your values, 
+           not the standard ones.
+           From: Guy Harris <guy@netapp.com>
+           [ Added also !escaped test, because now these characters can 
+             be printable. ]
+ 
+         - Moved processing of cursor keys to ReadCh
+           (old cursor key handling was buggy).
+         > HP's shoftkeys are not supported:
+            No options: -k -K
+            No elmrc variables: softkeys keypad
+         > Recognized keys are:
+                 Key             tercap name     terminfo name
+                 -----           -----------     -------------
+                 UP arrow        ku              kcuu1
+                 DOWN arrow      kd              kcud1
+                 LEFT arrow      kl              kcub1
+                 RIGHT arrow     kr              kcuf1
+                 PAGE UP         kP              kpp
+                 PAGE DOWN       kN              knp
+                 HOME            kh              khome
+                 HELP            %1              khlp
+                 FIND            @0              kfnd
+         > To get keys to use, your $TERM variable must point 
+           termcap/terminfo defination what includes these keys.
+           Notice that 'vt100' does not include other than cursor
+           keys. You must perhaps make new defination, for example
+           terminal type 'vt100-plus' :-) For terminfo use 'tic' and
+           'infocmp' -commands.
+ 
+         - state operations are moved outside of #ifdef MIME ... #endif
+         - Added new routines state_write_headers, state_read_headers,
+           delete_headers, locate_header and find_header to
+           parse_util.c. read_header_line is now implemented with routine
+           state_read_hdr_line. file_read_headers is implemented with routine
+           state_read_headers.
+         > Now included RFC 822 parts have printed text
+           -- Start of included mail From: xxxxx
+           instead of
+           -- Start of included mail.
+         - Rewritten read_mime_header to use file_read_headers, mainly by 
+ 	  dividing it to new routine parse_mime_headers
+ 	> Rewritten rfc822_parse. Now non-mime messages inside of
+ 	  message/rfc822 should be handled more correctly.
+ 	- Setting elmrc variable 
+ 	  require-mime-version-for-body-encoding to FALSE causes
+ 	  that almost all messages are treated as MIME -messages and
+ 	  MIME-Version is not required for these (in top level
+ 	  or inside of message/rfc822).
+ 
+         - Add  flag CM_REMOVE_ENVELOPE for copy_message
+         > make message/RFC822 attachment when forwarding with copy_message
+ 
+         - Make wait() in matapager restart in case of EINTR error
+ 
+         - Do MIME Part 2 (RFC 1522) decoding even when not MIME
+           even when not Mime-Version -header is present 
+           (If you want olf behauviour, set elmrc variable
+            require-mime-version-for-hdr-encoding to TRUE).
+           Header decoding is not done if sending elm was 
+           disabled to do MIME Part 2 (RFC 1522) encoding
+           (as set in elmrc variable nohdrencoding). That 
+           information is carried in header X-ELM-OSV:
+           (Our standard violations).
+ 
+         - quoted-printable-decode was not decoding zero length part
+           correctly.
+         > Indicate with length == -1 as not set instead of length == 0
+ 
+         - Added symbolics values RHL_MARK_FOLDING and RHL_CHECK_HEADER
+           for flags of read_header_line. Now read_header_line check
+           header for carefully. Side effect: If there is spaces before
+           ':' in header, them are deleted (assuming RHL_CHECK_HEADER).
+ 
+         - Add to mime_types[] following non-standard main content types:
+           x-world, model
+ 
+ Changes of Elm2.4ME+ PL22 (25) compared to Elm2.4ME+ PL21 (25)
+ --------------------------------------------------------------
+ 
+ 	[ Warning: There is quite much changes in
+           user interface, so perhaps there is bugs. ]
+ 
+ 	> Changes in Makefile.SH -- remember to run
+ 	  'Configure' or 'Configure -d' or 'Configure -S'
+ 
+         - 'ch' need to be 'int' in alias()
+         - 'cmd' need to be 'int' in MenuLoop()
+         - 'ch' need to be 'int' in generic_menu()
+           Problem noted by: Claus Assmann <ca@informatik.uni-kiel.de>
+ 
+         - There was unwanted trigraph in run_decoder()
+           Problem noted by: Claus Assmann <ca@informatik.uni-kiel.de>
+ 
+         - There was missing 'default:' in state_put()
+           Problem noted by: Claus Assmann <ca@informatik.uni-kiel.de>
+           Problem noted by: Guy Harris <guy@netapp.com>
+ 
+         - rename 'timeout' to 'elm_timeout' to get rid out linker warning
+         - rename 'filter' to 'elm_filter' to get rid out linker warning
+         - rename 'LINES' to 'elm_LINES' to get rid out linker warning
+           (These are defined also in libtermlib.so)
+ 
+         - rename 'COLUMNS' to 'elm_COLUMNS' to match 'elm_LINES'
+ 
+         - If there is Raw(ON) in parent in metapager(), then
+           also Raw(OFF) must be in parent
+           Noted by (?): Jurgen Fluk <louis@dachau.marco.de>
+ 
+         - Replace some getchar()s with ReadCh(REDRAW_MARK)
+           in syscall.c
+ 
+         - Replace some getchar()s with ReadCh(REDRAW_MARK)
+           in read_rc.c
+ 
+         - Replace some getchar()s with ReadCh(REDRAW_MARK)
+           in alias.c
+ 
+         - Replace some getchar() with ReadCh(REDRAW_MARK)
+           in utils.c
+ 
+         - Use type application/X-ELM-encode with
+           [enclode] ... [clear] if message is multipart
+           (Elm 2.4ME+ PL6 should know this type, but there
+            was error is some versions of ME+ in mime_notplain).
+ 
+         - mime_notplain was returning TRUE (should be FALSE) 
+           for application/X-ELM-encode.
+ 
+         - The builtin++ pager clears the screen before displaying the 
+           first screen of the message; however, the metapager wasn't 
+           clearing the screen before running the external pager, which 
+           left some junk on the screen.
+           From: Guy Harris <guy@netapp.com>
+ 
+         - Convert optionally_enter to use flag bits and
+           now it returns REDRAW_MARK in most places when redraw
+           is needed
+ 
+ 	- LOCK_DIR removed from Configure / config.h.SH
+ 
+ 	- Rememmber if last Configure run there was answer
+ 	  'none' for additional librariers
+ 
+ 	- Some new checks in Makefile (or actually in Makefile.SH), 
+ 	  Configure is run lately (that confih.sh or Makefile or
+ 	  config.h are not stale)
+ 	  
+ 
+ Changes of Elm2.4ME+ PL21 (25) compared to Elm2.4ME+ PL20 (25)
+ --------------------------------------------------------------
+ 
+         - More Configure fixes for IRIX 6.2
+ 
+         - PGP signed messages (with type text/plain) was not handled
+           correctly.
+           Noted by: Volker Paulsen <Volker.Paulsen@gmd.de>
+ 
+         - Just a short one-liner to fix the display:  
+           When you leave the key selection menu in 
+           pgp_mail_public_key() with `q' (i.e., don't mail a key), 
+           this routine currently returns 0.  This means that the main list
+           won't be redrawn and seems to be a bug.
+           From: Thomas Roessler <roessler@sobolev.rhein.de>
+ 
+         - read_number should create buffer of size SLEN, not NLEN
+           since it uses optionally_enter() which assumes that the 
+           buffer has length SLEN
+           From: Thomas Roessler <roessler@sobolev.rhein.de>
+ 
+         - Additionally, one might want to have the pgp functions 
+           in the help menu.
+           From: Thomas Roessler <roessler@sobolev.rhein.de>
+           
+ Changes of Elm2.4ME+ PL20 (25) compared to Elm2.4ME+ PL19 (25)
+ --------------------------------------------------------------
+ 
+         [ There is changes of error handling of leave_mbox --
+           so report, if you lost mail... ]
+ 
+         - Look also termlib.so and curses.so in Configure
+ 
+         - Remove PGP test from need_meta in showmsg.c
+           (It was causing that metamail was not called for 
+            multipart/signed what isn't supported.)
+ 
+         - Move metamail flags before PGP flags in show_message
+           in screen.c 
+ 
+         - lib/safeopen.c need to be added to MANIFEST
+           Noted by: Keith Manley <kmanley@bits.fc.hp.com>
+ 
+         - Elm as acting quite oddly if ending boundary of multipart
+           structure was missing.
+           Detected from report of: Rolf Larsson <rln@ludd.luth.se>
+ 
+         - Add sleep_message() to out_utils.c
+ 
+         - Detect if there is read error in newmbox!
+ 
+         - Check read errors also in some other places....
+ 
+         - Changes in leave_mbox -- now it returns with value -2 if
+            it fails to leave folder
+ 
+         - SIGUSR1 and SIGUSR2 is anly handled when in prompt
+           (because otherwise we can be in wrong state --
+            for example in middle in resync.)
+ 
+         - Check in ReadCh if it was called from GetPrompt
+           (GetPrompt want to see EINTR error!)
+ 
+         - ReadCh takes now redraw flag: Either 0 or REDRAW_MARK.
+           Now elm is able in many places automatically redraw screen
+           when elm resumes after suspending.
+ 
+         - skip_envelope() to parse_util.c
+ 
+         - Use skip_envelope() in get_and_expand_everybody() and
+           handle_reply_to() -- now elm should not be confused
+           with MMDF envelope of mail
+           Reported by: { Unknown -- mail lost }
+ 
+ Changes of Elm2.4ME+ PL19 (25) compared to Elm2.4ME+ PL18 (25)
+ --------------------------------------------------------------
+ 
+         - Fix SIGSEGV (with application/pgp; format=mime)
+ 
+         - With application/pgp; format=mime in included mime type
+           nested structures was not parsed (actually that was causing
+           SIGSEGV)
+ 
+         - recognize application/pgp; x-action=signclear
+ 
+         - Add "-- Start of included mail." and "-- End of included mail."
+           texts.
+ 
+ Changes of Elm2.4ME+ PL18 (25) compared to Elm2.4ME+ PL17 (25)
+ --------------------------------------------------------------
+ 
+         [ This patch includes very many changes, so perhaps there
+           are bugs ... ]
+ 
+         - Clean up some of the questions in the "Configure" script.
+           From: Guy Harris <guy@netapp.com>
+ 
+         - Added a '-S' option to the Configure script to just redo the
+           "variable substitutions on .SH files" that the script performs
+           at the end.  "I found this extremely useful, as I often made
+           changes to the config.sh (for instance, the 'optimize' flags),
+           and I wanted to re-create the Makefiles without running the
+           entire Configure script all over again."
+         - Also added '-h' option to report usage and available options to
+           Configure script.
+           From: Will Day <willday@rom.oit.gatech.edu>
+ 
+         - Add support for a "mailpermissions" variable in your "elmrc" file 
+           that can be set to specify the permissions to be used when creating 
+           a new mail folder.  The syntax to use when specifying the permissions
+           is *not* numeric, it's an "ls"-style string such as "rw-rw----", and
+           the default is "rw-------".
+           From: Guy Harris <guy@netapp.com>
+ 
+         - (Elm)HelpViewAttach was missing from s_elm.m
+ 
+         - Have the NLS stuff make "s_elmalias.h" from "s_elmalias.m".
+           From: Guy Harris <guy@netapp.com>
+ 
+         - Fix up "gencat" to compile on systems that don't do ANSI C 
+           (e.g., SunOS 4.1[.x] when using the bundled C compiler).
+           From: Guy Harris <guy@netapp.com>
+ 
+         - Some additions to help text of Elm
+ 
+         - Reconstruct mime_send_t.  There was wrong type when multipart
+           message was sent and pgp was used.
+           Noted by: J. Porter Clark <jpc@hammer.msfc.nasa.gov>
+ 
+         - Added elmrc option: "quoteforward", which will let the user 
+           restore the behavior of original elm when forwarding messages 
+           - that is, to quote them like replies.  
+           "I wanted this available, because usually when I forward a 
+            message, I will comment various lines, and if it's not quoted 
+            like a reply, my comments can be confused with the forwarded 
+            message (and I didn't want to have to manually comment the 
+            message every time)."
+           From: Will Day <willday@rom.oit.gatech.edu>
+ 
+         - convert mail() and send_msg() to use binary flags. 
+           Get rid of global variable "forwarding".
+ 
+         - Added safeopen_rdwr() call yet some places.
+           "While browsing through elm me+ xyz kh's source code, 
+            I stumbled across an invocation of tempnam() in a 
+            somewhat insecure environment:  In mailmsg2.c, it's 
+            output is used as argument to fopen(...,"w+").  This is
+            dangerous, since it may allow other users to access those 
+            temporary files."
+           From: Thomas Roessler <roessler@sobolev.rhein.de>
+         > Also use open_end_update() call, then code is cleaner
+           [ In suplied patch there was possibility that elm destroyes
+             =sent folder... ]
+ 
+         - Modification for Configure: On a Linux system which uses 
+           ELF-format shared libaries, the library symbols do not have 
+           an underscore prepended to them.
+           "I simply removed the [._] part from the sed expression.  This
+            makes everything compile and run happily on my machine, 
+            but if you want to correct this problem in your distribution, 
+            you would probably want to keep the old rule as well, to keep 
+            it from breaking elsewhere."
+           Noted by: Matthew Hunt <hunt@mph124.rh.psu.edu>
+ 
+         - "The second patch (re-)enables the use of the `T' key in the menu 
+            at the end of a message (tag + next).  This used to work in 
+            earlier releases of elm."
+           From: J Wunsch <j@uriah.heep.sax.de>
+ 
+         - "I think there is a small bug in metapager.c which has the 
+            consequence that the pager menu is sometimes displayed on the 
+            wrong screen page. The patch below fixes this behaviour."
+          From: Thomas Roessler <roessler@sobolev.rhein.de>
+ 
+          [ This patch little questionable -- 'ti' is "string to begin
+            brograms that use cup" (cursor addressing) and 'te' is
+            "string to end programs rhat use cup" -- problem is
+            that xterm uses ti/te to swap screen page... ]
+ 
+         - "Additionally, there is still an ugly timezone bug in elm-me+; 
+            the old patch for elm 2.4 applies cleanly to the current me+ 
+            version."
+           Noted by: Thomas Roessler <roessler@sobolev.rhein.de>
+         > Fix timezone:
+           "OK...here is the fix for the wierd timezone shifting.  
+            Besides the botched month parameter, the year also was wrong.
+ 
+            This patch better documents the input parameters to the 
+            lib/date_util.c procedures, and fixes get_tz_mins() to avoid 
+            a wierd offset shifting problem.  Thanks to Thomas Roessler 
+            <roessler@sobolev.rhein.de> for chasing down the cause of the 
+            problem."
+          From: Chip Rosenthal <chip@unicom.com>
+ 
+         - Fix dangling pointer bug in attach_viewer!
+ 
+         - Recognize text/x-pgp.
+           From: Guido van Rooij <guido@gvr.win.tue.nl>
+           [ + #ifdef USE_PGP added ]
+         > If type was text/x-pgp, don't consider case 
+           that PGP file is binary
+ 
+         - Don't convert application/x-pgp* to application/pgp
+           in newmbox.c -- instead recognize it in mime_decode.
+ 
+         - Don't reset type_opts when converting text/plain to
+           application/pgp.
+           [ That change was buggy -- fixed in PL21 ]
+ 
+         - Move "Decrypting message..." and "Checking signature..."
+           messages to another place.
+ 
+ Changes of Elm2.4ME+ PL17 (25) compared to Elm2.4ME+ PL16 (25)
+ --------------------------------------------------------------
+ 
+         -  Some systems use OXTABS bit instead of TABDLY
+           [ Various paches for *BSD ]
+           From: Ollivier Robert <roberto@keltia.freenix.fr>
+           From: Jeff Thieleke <thieleke@lust.isca.uiowa.edu>
+           From: Andrey A. Chernov <ache@astral.msk.su>
+ 
+         - Undone HP-UX change for ANSI_C
+           "This is mostly incorrect.  We figured out that 
+            the problem was the -traditional flag that was included 
+            by default when compiling with gcc."
+           Noted by: Jeff Thieleke <thieleke@lust.isca.uiowa.edu>
+ 
+         - Removed -traditional from gcc flags in Configure
+           "The real fix would be to remove the default CFLAGS when 
+            compiling with gcc, since they probably aren't needed any more."
+           Suggested by: Jeff Thieleke <thieleke@lust.isca.uiowa.edu>
+ 
+         - Don't allow change a filename of forwarded mail in attachment
+           menu.
+ 
+         - If content-transfer-encoding is unknown when saving attachment,
+           treate it as binary.
+ 
+         - Don't allow change filename in attachment menu to non-existent
+ 
+ Changes of Elm2.4ME+ PL16 (25) compared to Elm2.4ME+ PL15 (25)
+ --------------------------------------------------------------
+ 
+         [ Warning: state routines are rewritten -- so look below
+           what to do if you get STATE PANIC message ... ]
+ 
+         - Add #include "headers.h" to safeopen.c to get rid
+           out one stupid compiler warning
+           Urged by: Andrew J. Piziali <andy@daldd.sc.ti.com>
+ 
+         - struct state is divided to two structs: struct in_state
+           and struct out_state. Large modifications to state
+           routines (state.c). 
+ 
+           If you get message STATE PANIC: Bad magic number
+           compile elm with debugging -g and -DDEBUG
+           and run elm with -d11 and try get it repeated.
+           Now STATE PANIC should cause producing of core file.
+           
+           Look with debugger where that STACE PANIC accured (ask
+           stack trace from debugger) and look also file ~/ELM:debug.info
+ 
+         - If terminal driver is expanding tabs, do not print
+           them -- instead jump to correct location
+ 
+         - "HP-UX apparently doesn't declare __STDC__ (like AIX), 
+            so compiling with cc or gcc fails in src/init.c at the getgid(), 
+            getuid() prototypes."
+           From: Jeff Thieleke <thieleke@icaen.uiowa.edu>
+           [ Undone in ME+ PL17 ]
+ 
+         - If you sign 8-bit mail, it will be later encoded with
+           quoted-printable or base64 (by elm or by sendmail).
+           Thus 'invalidating' because pgp_decode does not undo contet-
+           transfer encoding before calling PGP.
+           Noted by: Zoltan Hidvegi <hzoli@cs.elte.hu>
+           Noted by: Hans-Christoph Wirth <hansi@dianoia.mayn.de>
+         * Now content-transfer-encoding is decoded before bodypart
+           is passed to pgp (it also now work, when *.pgp file
+           is encoded with base64).
+         > That decoding is done via temporary file -- perhaps I
+           some time stack state routines so temporary file is not needed
+           and decoding of content-ttransfer-encodings are done during
+           reading.
+         > If I some day get implemented MIME/PGP then 8-bit mail is always
+           encoded with quoted printable and then passed to PGP for signing.
+ 
+         - Display text before PGP armor if elmrc variable showpgppreamble
+           is set (default). Binary PGP files are detected by looking first
+           byte (after decoding content-transfer-encoding).
+ 
+         - Fix to PL15 fix: "Elm fail in resyncing if mailfile is created 
+           after initial entering to mailbox." -- previous fix can cuase
+           elm exiting with message 
+           "What's this?  The temp folder already exists??" and then
+           "Ahhhh... I give up."
+           Perhaps noted by: Andrew J. Piziali <andy@daldd.sc.ti.com>
+ 
+         - SECURITY: Elm was running PGP as setgid mail (by using popen)
+           when searching matching keys -- converting to use 
+                 pipe - fork - setgid (groupid) - execl
+ 
+         - Need pass +language=en to PGP when searching matching keys
+           Noted by: Boris Staeblow <balu@reido.in-berlin.de>
+ 
+         - Initialize last (extra) element also to NULL in DynamicArray
+           so that DestroyDynamicArray works (lib/dynarray.c)
+           -- was causing SIGSEGV in GetPGPKey
+ 
+         [ Undo Elm2.4ME+ PL15s patch before installing this patch. ]
+ 
+ Changes of Elm2.4ME+ PL15s (25) compared to Elm2.4ME+ PL15 (25)
+ ---------------------------------------------------------------
+ 
+         - SECURITY: Elm was running PGP as setgid mail (by using popen)
+           when searching matching keys -- converting to use 
+                 pipe - fork - setgid (groupid) - execl
+ 
+ Changes of Elm2.4ME+ PL15 (25) compared to Elm2.4ME+ PL14 (25)
+ --------------------------------------------------------------
+ 
+         [ Warning: This is perhaps more buggy than PL14. ]
+ 
+         - Some changes in Makefiles, Configure
+         - Change of temporary mbox name, put temporary mbox to
+           back to temp directory (from home directory)
+         - lib/safeopen.c
+         - can_open(filename,"sw") checks if creating of _new_ file
+            is possible (O_EXCL) -- and use that in leavembox.c
+            Side-effect: New file is created
+         - use isprint((unsigned char)ch) in src/curses.c
+         - "I removed all fopen(file, "w") where file was a filename in /tmp 
+            and replaced these with a safeopen(file) call.  These changes 
+            should be also applied to the vanilla elm source."
+         - "Also there are some minor bugfixes for PL11.  
+            Elm did not asked my PGP password when I wanted to 
+            read a PGP encrypted mail since it wrongly thought
+            that the mail is only signed but not encrypted.  
+            That's the most serious bug."
+         - "I add a ClearScreen() before the fork in pgp_decrypt_init() 
+            to make the screen look clearer."
+            From: Zoltan Hidvegi <hzoli@cs.elte.hu>
+ 
+         - Routine safeopen_rdwr added to safeopen.c 
+ 
+         - Test agaist special modes was WRONG in leavembox.c
+                 (it was 0x7000 and it should be 07000)
+         - Treate files with special modes as SPOOL files (newmbox.c)
+         - Handle 'intelligent' way also SPOOL files what haven't in mailhome
+         - Restore also special modes of file if file is not executable
+         - Don't chown file if owner is already correct -- it resets
+           special modes
+         * With these changes it is possible to redirect sendmail aliases
+           to files (mode 04600) and cause that elm does not reset setgid
+           bit (what is required to be set, before sendmail accepts forwarding
+           to no world writable files).
+ 
+         - Multiple To: -headers was cauisng of trashing of memory
+           and SIGSEGV
+           Noted by: Richard Allen <ra@rhi.hi.is>
+ 
+         - Elm fail in resyncing if mailfile is created after initial
+           entering to mailbox.
+           Noted by: Miroslav Ruda <ruda@ics.muni.cz>
+           { I didn't used suplied patch. }
+ 
+         - Elm fails to create received -folder
+           Noted by: Jussi Kaurola <kaurola@dionysos.FMI.FI>
+         - Added function open_end_update to file_util.c
+ 
+         - Replace iscntrl((unsigned char)*pending) with
+           !isprint((unsigned char)*pending) in builtin++.c
+           because Configure asks that is isprint 
+           working with 8-bit values, but it does not ask about iscntrl
+ 
+         * Notice: Seems that someones does not agreed with interpretation
+           of ASCII_CTYPE defination. My interpretation is:
+ 
+                 ASCII_CTYPE defined:    isprint works only with arguments
+                                         0-127
+ 
+                 Conclusion:             We can't test that is characters in
+                                         range 128-255 printable or not, so
+                                         don't print them
+ 
+           ASCII_CTYPE is defined when you answer "no" to following question:
+           "Should Elm assume that isprint() won't break on 
+             non-ASCII characters?"
+ 
+           To get 8-bit characters to work you need:
+                 1) 8-bit clean ctype functions and macros
+                 2) ASCII_CTYPE is not defined
+                 3) setlocale exists (Configure have found locale.h;
+                    that is: I_LOCALE is defined)
+                 4) Correct locale defination (environment variable
+                         $LANG or $LC_CTYPE usually)
+                    Look manual page of setlocale
+                 - If you are not using builtin(++) pager in Elm, thinks
+                   can go more complicated -- all pagers does not use
+                   locale definations
+ 
+         - Use kill(getpid(), SIGSTOP) instead of  kill(0, SIGSTOP)
+           so that delivering of mail does not stop when user suspends
+           Elm.
+           Reported by: Richard J. Auletta <rauletta@erebor.cudenver.edu>
+ 
+ Changes of Elm2.4ME+ PL14 (25) compared to Elm2.4ME+ PL13 (25)
+ --------------------------------------------------------------
+ 
+         - PGP signed (or encrypted) MIME mail was not quoted when 
+           replying. Quick fix for pgp_decode in pgp.c. It still 
+           perhaps have broken...
+ 
+ Changes of Elm2.4ME+ PL13 (25) compared to Elm2.4ME+ PL12 (25)
+ --------------------------------------------------------------
+ 
+         - Compiler was giving warning that 'char *' and
+           'unsigned char *' are not assignment-compatible
+           (for code in mime_encode.c)
+           Noted by: Arkady Altman <aya@cae.cig.mot.com>
+ 
+         - Include headers of forwarded message to editor
+           buffer even when you have noheader = ON
+           (that is in situation mimeforward = OFF).
+           That is now controlled with elmrc variable "noheaderfwd"
+           (default: OFF)
+ 
+         - Elm was getting SIGSEGV in remailer_parse_opts in remailer.c
+           Noted by: V Menayang <victor@slip-50-11.ots.utexas.edu>
+           [ Notice that this REMAILER code is still broken! ]
+ 
+         - remailer.c was calling finger without resetting egid!
+ 
+         - FreeBSD changes to utils/newmail.c also pertain to NetBSD
+           From: Jeff Thieleke <thieleke@icaen.uiowa.edu>
+ 
+ Changes of Elm2.4ME+ PL12 (25) compared to Elm2.4ME+ PL11 (25)
+ --------------------------------------------------------------
+ 
+         Warning: This version is probably much more buggy
+                  than PL11 !!
+ 
+         - The blank line between two messages in a folder 
+           was missing.
+           Noted by: Juergen Obermann <Juergen.Obermann@hrz.uni-giessen.de>
+ 
+         - If nohdrencoding = TRUE and there is 8bit  characters in subject,
+           treat as there was 8bit characters in body.
+           From: Andrey A. Chernov <ache@astral.msk.su>
+           [ This does not work very well... ie. It works only when
+             Content-Type is Text/plain. ]
+           " Before RFC 1522 issued, too many users (f.e. Russian users) use
+             8bit chars in Subject: header field. There is a lots of 8bit 
+             capable MUA & MTA exists now, much more then RFC1522 compatible 
+             ones. In existent variant when you enter 8bit subject with ASCII 
+             body result content charset stays as ASCII, it makes impossible to
+             recognize Subject: charset. I UNDERSTAND that my method violates 
+             MIME slightly (no 8bit characters must be in header field) but it 
+             is adoptation of real life practic."
+ 
+         - Add /usr/sbin to default path, there is sendmail on FreeBSD
+         - Disable national extensions of 'date'
+         - Add FreeBSD lock directory
+         - Add KOI8-R charset to user prompt, it is officially registered, 
+           RFC1700
+         - Fix utime_buffer declaration for FreeBSD
+         - Allow mailbox editing for Expert user level only. Total disabling
+           of this option makes life harder for experienced users and total
+           enabling cause accidental 'e' hitting damage novice users mailboxes.
+           It seems that enabling it for Expert user leve is the best solution.
+           From: Andrey A. Chernov <ache@astral.msk.su>
+ 
+         - "I also discovered another small 'bug'... Michael Elkins changed 
+            someday in pgp.c a get_address_from() call to a simple strcpy() 
+            which caused my pgp not to find my secret key because of a 
+            leading blank:
+            " Volker Paulsen <paulsen@gmd.de>"
+             ^
+            After I changed it back to get_address_from() the leading blank
+            becomes removed and pgp matches the key correctly against its key
+            ring ."
+           From: Volker Paulsen <Volker.Paulsen@gmd.de>
+ 
+         - Add binary -flag for header_rec. No longer hack for remail.c.
+ 
+         - Make more clear what part of message was PGP signed or encrypted.
+           (Why pgp returns exit status 0 even when signature doesn not
+            match???)
+ 
+         - Some massive rewriting of copy_message. Now should decoding of
+           RFC 1522 encoding work correctly when replying (and forwarding).
+           Side effects:
+                 - Headers which have longer than 32 KB after unfolding
+                   are truncated
+                 - Exact folding is not preserved
+ 
+ Changes of Elm2.4ME+ PL11 (25) compared to Elm2.4ME+ PL10 (25)
+ --------------------------------------------------------------
+ 
+         - Elm wrote incorrect Content-Length: -header when 
+           updating Status: -header
+           Noted by: Juergen Obermann <Juergen.Obermann@hrz.uni-giessen.de>
+           [ That content-length is lightly too big and is not fixed
+             if it is last mail in folder (it is not big enough that
+             newmbox.c notices) also incorrent Content-Length: -header
+             causes in other situations that it is ignored. This causes
+             problems when "From ":s are not escaped. ]
+ 
+ Changes of Elm2.4ME+ PL10 (25) compared to Elm2.4ME+ PL9 (25)
+ -------------------------------------------------------------
+ 
+         - CM_DISPLAYING was wrong value in hdrs/defs.h
+ 
+         - Elm was corrupting folder by adding number to end of mail...
+           And therefore causes that next mail does not start
+           with "From " in folder.
+           Noted by: Volker Paulsen <Volker.Paulsen@gmd.de>
+ 
+         - REMAILER code does not compile.
+           From: Andrey A. Chernov <ache@astral.msk.su>
+           From: Arkady Altman <aya@cae.cig.mot.com> 
+ 
+ Changes of Elm2.4ME+ PL9 (25) compared to Elm2.4ME+ PL8 (25)
+ ------------------------------------------------------------
+ 
+         - Attach viewer does not completely fill header_rec 
+           so "lines" was uninitiazed, which may cause
+           "metapager()" to choose randomly whether to use the 
+           built-in pager or not, if you haven't set "pager" to 
+           "builtin" or "internal". Now structure is pre-initialized
+           completely. "lines" is set to number of bytes / 60
+           (not saticfactory, but actually metapager should use 
+            number of lines in decoded message -- 
+           not in original anyway.)
+           Prompted by: Guy Harris <guy@netapp.com>
+ 
+ Changes of Elm2.4ME+ PL8 (25) compared to Elm2.4ME+ PL7 (25)
+ ------------------------------------------------------------
+ 
+         - In syscall.c, around line 180, the space for p 
+           was allocated but the actual string was never built.
+           From: Mark Johnson <Mark.Johnson@ustc.vlsi.COM>
+         
+         - At the end of a message with the buildin pager I 
+           sometimes get the prompt "MORE (you've seen 101%):"
+           and I can not read the next message with 
+           pressing the space bar.
+           From: Juergen Obermann <Juergen.Obermann@hrz.uni-giessen.de>
+ 
+         - "rfc822_reap_comments()" wasn't properly handling 
+           Content-Type: headers like
+ 
+           Content-Type: Multipart/Mixed;
+                 boundary="--Next_Part(Wed_Feb_14_09:54:49_1996)--"
+ 
+           because it didn't realize that the ")" in the boundary 
+           was inside a quote, and therefore should be copied rather 
+           than being stripped out.
+           From: Guy Harris <guy@netapp.com>
+ 
+         - It wasn't RFC 1522-decoding the name in the "From:" header 
+           when it put in the "Forwarded message from" and 
+           "End of forwarded message from" lines.
+           From: Guy Harris <guy@netapp.com>
+ 
+         - Put defualt disposition for attachment to be 'attachment'
+           when sending.
+ 
+         - Check that attachment is not deleted before mail is sent.
+ 
+         - Because copy_message is now called from metapager, it
+           needs two more arguments (mailfile and current_header).
+           I hope that this change breaks nothing! 
+           Detected from report of: Mark Johnson <Mark.Johnson@ustc.vlsi.COM>
+ 
+ Changes of Elm2.4ME+ PL7 (25) compared to Elm2.4ME+ PL6 (25)
+ ------------------------------------------------------------
+ 
+         - Incorrect subject
+ 
+ Changes of Elm2.4ME+ PL6 (25) compared to Elm2.4ME+ PL5 (25)
+ ------------------------------------------------------------
+ 
+         - Sometimes extra newline was added when message or
+           body of it was copied.
+ 
+               > copy_message in fileio.c was gone too hairy.
+                 Tried to reorganize it. I hope that nothing
+                 breaks.
+ 
+               > Semantic of flag CM_DECODE is now changed.
+ 
+               > Now message is decoded before replying and forwarding
+                 (excpet when mime_forward is true -- forwarded message
+                 as attachment is not decoded).
+ 
+               > Well, now [encode] [clear] does not work when metamail
+                 is called.
+ 
+               > [encode] ... [clear] is now internally handled as
+                 application/X-ELM-encode (in MIME -message)
+ 
+         - Do RFC 1522 decoding only in MIME messages.
+ 
+         - builtin++ code in metapager was broken [encode] ... [clear] 
+ 
+               > I simplified metapager. I hope that nothing
+                 breaks.
+ 
+         > Notice that [encode] ... [clear] is broken when sending
+           multipart messages.
+ 
+         - Now also headers of message/rfc822 are prefixed when replying
+ 
+         - Nicer printing of folded headers (in metapager and rfc822_decode)
+ 
+         - Letter 'e' (= uses Elm's [encode] ... [clear]) added to status
+           letter of mailbox menu.
+ 
+ Changes of Elm2.4ME+ PL5 (25) compared to Elm2.4ME+ PL4 (25)
+ ------------------------------------------------------------
+ 
+         - "nohdrencoding" was in wrong place in list
+ 
+         - To instead of From in headers was always displayed:
+           From: Petr Lampa <lampa@fee.vutbr.cz>
+ 
+         - There was some confusion in (char *) versus (unsigned char *)
+           in rfc1522_encode_text.
+           Pointed by: Petr Lampa <lampa@fee.vutbr.cz>
+ 
+         - Replaced check of R_OK with ECCESS_EXISTS in can_save 
+           in attach_menu.c
+ 
+         - Reordering of attach_viewer so metamail is not called 
+           when it isn't needed (new defination of 'pagemultipart'
+           was broken it.)
+ 
+         - Message "Parsing MIME structure..." is printed
+ 
+         - Added to some unlink and elm_chown calls to attach_menu.c
+ 
+         - Now prints "Executing metamail..." if metamail is called for
+           display message.
+ 
+         - Tried fix MIME decoding of headers in copy_message
+           (well, it still can't work correctly.)
+ 
+         - MIME (RFC 1522) encoding of In-Reply-To -header
+ 
+                 > Address headers and headers from .elm/elmheaders are still
+                   not encoded.
+ 
+         - Don't try print To: address in menu if it does not exists.
+ 
+ Changes of Elm2.4ME+ PL4 (25) compared to Elm2.4ME+ PL3 (25)
+ ------------------------------------------------------------
+ 
+         [ Warning: This is perhaps more buggy than PL 3 (25). ]
+ 
+         * Sending of simple Text/Plain messages with quoted-printable encoding
+           was broken when remailer -code was added.
+           Noted by: Petr Lampa <lampa@fee.vutbr.cz>
+ 
+         - In the index screen Tag all, Delete all and Undelete all 
+           didn't show the new status of the messages.
+           From: Juergen Obermann <Juergen.Obermann@hrz.uni-giessen.de>
+ 
+         - In readmsg the Cc-header line is always shown.
+           From: Juergen Obermann <Juergen.Obermann@hrz.uni-giessen.de>
+           [ This should be also posted to Elm Development Cordinator ]
+ 
+         - Add a "Status: RO" line to all outgoing messages (when the "copy" 
+           option is turned on), so that they do not show up as "New" when you 
+           look at a folder.
+           From: Pete Wenzel <pete@stc.com> 
+ 
+         - The macro X_OK is undefined in some systems. 
+           Use EXECUTE_ACCESS instead.
+           From: Gunnar Ekolin <ekolin@carlstedt.se>
+ 
+         > Failing to include <unistd.h>. 
+           Test agaist I_UNISTD instead of ANSI_C.
+           Noted by: Petr Lampa <lampa@fee.vutbr.cz>
+ 
+         > Now EXECUTE_ACCESS, WRITE_ACCESS, READ_ACCESS, ACCESS_EXISTS,
+           EDIT_ACCESS is defined in terms of X_OK, W_OK, R_OK, F_OK
+           from unistd.h (if available)
+ 
+         - Fix defination in hdrs/mcprt.h to match with lib/mcprt.c
+           From: Claus Assmann <ca@informatik.uni-kiel.de>
+ 
+         - DisplayAddress not work (well, I really not used that patch).
+           That needs still reconsideration.
+           From: Claus Assmann <ca@informatik.uni-kiel.de>
+ 
+         - Mime (RFC 1522) encoding of following headers:
+                 - From  (fullname)
+                 - Subject
+                 - Content-Description
+ 
+                 Encoding of In-Reply-To, To, CC or headers in 
+                 .elm/elmheaders is NOT done.
+ 
+         - New elmrc variable "nohdrencoding". If this variable is TRUE,
+           then MIME encoding of headers isn't done.
+ 
+         - Wrong tests with allow_no_encoding in src/mailmsg2.c.
+           Noted by: Petr Lampa <lampa@fee.vutbr.cz>
+ 
+         - Use strincmp for lib/strincmp.c instead of strcasecmp.
+           Noted by: Petr Lampa <lampa@fee.vutbr.cz>
+ 
+         - Added check for write errors in mime_encode.c
+         
+ Changes of Elm2.4ME+ PL3 (25) compared to Elm2.4ME+ PL2 (25)
+ ------------------------------------------------------------
+ 
+         - Fix to builtin++.c SIGSEGV fix
+ 
+ Changes of Elm2.4ME+ PL2 (25) compared to Elm2.4ME+ PL1 (25)
+ ------------------------------------------------------------
+ 
+         - Really fix In-Reply-To -header
+           [ This is also posted to Elm Development Cordinator ]
+ 
+ Changes of Elm2.4ME+ PL1 (25) compared to Elm2.4ME+ PL0 (25)
+ ------------------------------------------------------------
+ 
+         - SIGSEGV in builtin++.c when looking full headers of mail
+           and Ctrl-L was hit.
+ 
+         - Typo in remailer.c (causes that it don't link)
+           From: Ollivier Robert <roberto@keltia.freenix.fr>
+ 
+         - Ultrix patch from comp.mail.elm
+           From: John Simonson <gort@wildcat.ceas.rochester.edu>,
+                 Sydney Weinstein <syd@myxa.com>, 
+                 Bill Gianopoulos <wag@swl.msd.ray.com>
+ 
+         - Now Elm's Configure search for metamail -program
+ 
+         - DisplayAddress: Don't munge sender with get_real_name
+ 
+         - Elm was generating syntactically incorrect In-Reply-To -headers
+ 
+         - Because some peoples seems have trashed src/state.c that patch
+           includes file src/state.c.PL1. 
+           If src/state.c.PL1 and src/state.c don't have identical,
+           use command: mv src/state.c.PL1 src/state.c
+           otherwise:   rm src/state.c.PL1
+ 
+         - SIGSEGV when hitting 'G' in builtin++.c
+ 
+ 
+ Changes of Elm2.4ME+ PL0 (25) compared to version Elm2.4 PL24 ME8b+
+ -------------------------------------------------------------------
+ 
+         - Added (security) patch PL24 -> PL25 and 
+           added same kind (security) fixes for MIME code
+ 
+         - Version number is now formed with new style :-)
+ 
+         - elmrc -variable 'displaycharset' is propgated to
+           environment variable $MM_CHARSET when calling metamail.
+           Environment variable $MM_CHARSET overwrides default value
+           of 'displaycharset'.
+ 
+         - New elmrc -variable 'metamail'. So now you not need define
+           environment variable $NOMETAMAIL, if you want compile Elm
+           with MIME support, and you don't have metamail. Special values:
+                 none            Don't call metamail
+                 metamail        Call metamail, if environment variable
+                                 $NOMETAMAIL is not defined
+                 /path           Call tiss, if this is executable
+ 
+         - Meaning of elmrc -variable 'pagemultipart' is changed. If
+           this is FALSE (default), then call metamail if elm can't
+           handle all subpart of multipart -type or if type is other
+           than multipart/mixed, multipart/digest or multipart/report.
+           If 'pagemultipart' is TRUE, then always handle multipart type
+           without metamail (and treate unknown subtypes as multipart/mixed).
+ 
+           Decision can Elm handle that type, is done when message is 
+           displayed. So there is now 'M' -letter (= metamail needed) in
+           multipart mails until message is displayed even when Elm can
+           show it (that is because that defination is recursive and
+           requires parsing of structure of message.)
+ 
+         - Multipart/digest now works correctly when viewing attachment
+           what we have sending and we have put type for it to be 
+           Multipart/mixed.
+ 
+         - Configure now tries test if sendmail supports -B8BITMIME and
+           -BBINARYMIME (unlikely).
+ 
+         - Makefile now don't compile or install 'filter' because security
+           problems in it.
+ 
+ Changes of Elm2.4 PL24 ME8b+ compared to version Elm2.4 PL24 ME8b
+ -----------------------------------------------------------------
+ 
+         - New version of my Reply-To patch included
+           [ Old version of that patch is posted to Elm Development Cordinator ]
+ 
+         - Made MIME part 2 (RFC 1522) decoding more accoriding of RFC.
+ 
+         - Some bugfixes
+ 
+ Elm mailbox menu's status letters
+ ---------------------------------
+         - First letter:         D       Deleted
+                                 E       Expired
+                                 N       New
+                                 O       Unread
+                                 r       replied
+ 
+         - Second letter:        C       Confidental
+                                 U       Urgent
+                                 P       Private         (or ...)
+                                 A       Action
+                                 F       Form letter
+                                 e       Uses Elm's [encode] ... [clear]
+                                 P       PGP message     (or ...)
+                                 S       PGP signed message
+                                 K       PGP public key
+                                 ?       MIME message with unknown
+                                                 MIME version
+                                 M       MIME message wich requires metamail
+                                                 or isn't yet parsed
+                                 m       Pre-MIME message wich requires metamail
+ 
+ New elmrc variables for Elm 2.4ME+
+ ----------------------------------
+ 
+         askpgpsig                               PGP
+         keeppassfor                             PGP
+         metamail                                MIME
+         mimeforward                             MIME
+         noencoding                              MIME
+         nohdrencoding                           MIME
+         noheaderfwd                             -
+         pagemultipart                           MIME
+ 	quoteforward				-
+         require-mime-version-for-body-encoding  MIME
+         require-mime-version-for-hdr-encoding   MIME
+         showpgppreamble                         PGP
+         usepgppass                              PGP
+ 
+ Obsolete elmrc variables
+ -------------------------
+         hpkeypad                                (alias to keypad)
+         hpsoftkeys                              (alias to softkeys)
+         keypad                                  -
+         softkeys                                -
+         textencoding                            MIME
+ 
+ Warnings
+ -------- 
+ 
+         - Not compiled with MMDF or REMAILER support defined, so
+           probably they don't work (or even compile).
+ 
+         - As far I know REMAILER code have newer worked. 
+           Specially: remailers are incompatible with MIME
+ 
+         - This is not tested very much so there can be bad bugs. Bug
+           Reports to: Kari E. Hurtta <hurtta+elm@dionysos.FMI.FI>
+ 
+         - There still don't be support for multipart/alternative, but
+           now metamail will be called for it because new semantic of 
+           'pagemultipart' (assuming that 'pagemultipart' have default
+           value.)
+ 
+         - Decoding of MIME is not done when searching content of mail
+ 
+         - RFC 1522: Mime part 2 support is incomplete
+ 
+         - There is not support for multipart/signed and multipart/encrypted
+           (specially: no support for PGP/MIME)
+ 
+ 	> But anyway, Elm will newer be MIME Conformant
+ 
+ 	- HP's shoftkeys are no longer supported
+ 
+ Collector of these patches
+ --------------------------
+ 
+         Kari E. Hurtta <hurtta+elm@ozone.FMI.FI>
Index: WORK/ANNOUNCE.ME
*** /tmp/null.14101	Tue Aug 20 22:05:34 1996
--- WORK/ANNOUNCE.ME	Mon Jun  3 20:15:16 1996
***************
*** 0 ****
--- 1,280 ----
+ ELM 2.4 PL24 ME8
+ 
+ This is an announcement for Patchlevel ME8 for Elm 2.4pl24.
+ 
+ The most current version of this document is available via the web:
+ http://www.cs.hmc.edu/~me/elm/announce.html. You can also visit the "ME" home
+ page at http://www.cs.hmc.edu/~me/elm/me.html.
+ NOTE THAT THIS ADDRESS HAS CHANGED FROM THE PREVIOUS ANNOUNCEMENT!
+ 
+ What's new:
+ 
+    * Anonymous remailer support (plus chaining, PGP encryption & MIME support)
+    * mime.types file when guessing the content-type of an attachment.
+    * Forwarded messages can be attached as MESSAGE/RFC822 data
+    * Supports extraction of PGP public keys directly
+    * Support for application/pgp type inside multipart/mixed and message/rfc822
+      messages
+ 
+ Changes from ME7a:
+ 
+    * Replying to MULTIPART messages now works correctly.
+    * MESSAGE/RFC822 is now properly supported.
+    * BINARY encoding is better supported.
+    * Fixed bugs with BASE64 and QUOTED-PRINTABLE encodings.
+    * Enhanced attachment menu
+    * Improved interface for PGP encrypting messages
+ 
+ Where to get it:
+ 
+    * ftp://cs.hmc.edu/pub/me/elm-2.4pl24me8.tar.Z
+    * ftp://cs.hmc.edu/pub/me/elm-2.4pl24me8.tar.gz
+    * ftp://cs.hmc.edu/pub/me/elm-2.4pl24me8.diffs.Z
+    * ftp://cs.hmc.edu/pub/me/elm-2.4pl24me7a-8.diffs.Z
+ 
+ -OR-
+ 
+    * ftp://uiarchive.cso.uiuc.edu/pub/packages/mail/elm/me/elm-2.4pl24me8.tar.Z
+    * ftp://uiarchive.cso.uiuc.edu/pub/packages/mail/elm/me/elm-2.4pl24me8.tar.gz
+    * ftp://uiarchive.cso.uiuc.edu/pub/packages/mail/elm/me/elm-2.4pl24me8.diffs.Z
+    * ftp://uiarchive.cso.uiuc.edu/pub/packages/mail/elm/me/elm-2.4pl24me7a-8.diffs.Z
+ 
+ -------------------------------------------------------------------------------
+ 
+ STATUS
+ 
+ These patches are not an official release of Elm, and are not supported by the
+ Elm Development Group. Features included in this patch may or may not be
+ included in the next official release of Elm. I can say for certain that the
+ PGP portion will not. I am hoping that my MIME patches will be included in the
+ 2.5 release, but that is still an open question. Should the 2.5 release appear
+ without these patches, I plan on "porting" them and using 2.5 as the base.
+ -------------------------------------------------------------------------------
+ And now on to the interesting stuff...
+ 
+ PGP SUPPORT
+ 
+ [This work was inspired by pgpelm which was started by Mic the Missing and
+ furthur developed by Ken Cox (kenc@viewlogic.com). This version is a complete
+ rewrite of that system but looks very similar.]
+ 
+ Features include: mark on folder menu showing PGP encrypted messages and public
+ key blocks, encryption/signing of outgoing messages, decrypting/signature
+ check, mailing public key blocks, and extracting public key blocks from
+ messages. Special feature allows you to have ELM keep track of your PGP
+ passphrase so you only need to enter it a minimal number of times.
+ 
+ I have written a primer for using PGP with this version of ELM which can be
+ found at http://www.cs.hmc.edu/~me/elm/pgp.html. It contains everything you
+ need to know about how to use PGP with ELM.
+ 
+ MIME SUPPORT
+ 
+ With this version of Elm, the need for metamail is much less since it can now
+ handle the MIME encodings and multipart/* messages internally. The only case in
+ which metamail is called is when there is a content-type which Elm does not
+ understand (eg. image/*, audio/*). In most cases you will probably only receive
+ this as attachments anyway, so you might still not require metamail.
+ 
+    * Incoming Attachments
+ 
+      Access to individual portions of a MIME mulitpart message can be accessed
+      via the "Attachments" menu (type 'v' in the index menu). This brings up a
+      menu listing the attachments for the current message. You then have the
+      option of viewing or saving the attachment.
+ 
+    * Outgoing Attachments
+ 
+      In addition to using the "[include ..." construct when editing your
+      message, there is now an "Attachments" menu accesible from the "Send" menu
+      (it is abbreviated to "a)tt" because of space problems). Simply type "a"
+      to get into the Attachments menu. You may then add/delete/edit/modify
+      attachments. When possible, Elm will attempt to guess the correct
+      Content-Type (based on file extension, see the "mime.types" section below)
+      and Content-Transfer-Encoding.
+ 
+    * Automatic encoding for outgoing messages.
+ 
+      If Elm finds 8bit or control characters in text files to be attached, it
+      will automatically encode them QUOTED-PRINTABLE if Elm has been compiled
+      without the 8BITMIME option (meaning that your MTA isn't 8bit clean). This
+      behavior can be overriden with the "noencoding" elmrc option (see below)
+      in cases where your sendmail is 8bit clean, but doesn't support the
+      -B8BITMIME option.
+ 
+    * mime.types file
+ 
+      Elm now mime.types file which maps filename extensions to Content-Type
+      field when sending attachments via the new attachment menu. The format of
+      these files is as follows:
+ 
+      <extension> <content-type>
+ 
+      A hash character ('#') may be used as a comment, but it must be in the
+      first column of a line.
+ 
+      Here is an example of mime.types file:
+ 
+      # This is a commented line
+      html    text/html
+      tgz     application/octet-stream; type=tar; conversions="x-gzip"
+ 
+      Note that the content-type field is not limited to just the type/subtype
+      part; in can also include suplementary information.
+ 
+      Elm first looks to see if the user has a ~/.elm/mime.types file. If there
+      is no match, Elm will then try to read the system types file (typically
+      /usr/local/lib/elm.mimetypes). Failing that, Elm has a few builtin types
+      that it understands.
+ 
+      You might want to pick up a copy of my mime.types file as a starting point
+      for either your personal or system file at
+      http://www.cs.hmc.edu/~me/elm/mime.types.
+ 
+ REMAILER SUPPORT
+ 
+ This version of Elm has the ability to prepare messages for use with anonymous
+ remailers (if you don't know what that is, read alt.privacy.anon-server for
+ more information).
+ 
+ Elm gets its information about anonymous servers by either fingering
+ "remailer-list@kiwi.cs.berkeley.edu" or by reading ~/.elm/remailers (if this
+ file exists, it overrides the "finger" so you can still use this feature even
+ if you are not directly net connected.)
+ 
+ To send an anonymous message, first compose your message as you normally would,
+ entering the name of the person who should ultimately receive the message as
+ the To: address. Then, at the "send" menu, you can type "r" to get into the
+ "remailer" menu.
+ 
+ There are several options in this menu: remail, chain, path and encrypt.
+ The "remail" option indicates whether or not the current message will be
+ remailed.
+ 
+ "chain" indicates how many servers this message should be sent through (the
+ higher chain is, the more secure, but the tradeoff is how long until the
+ receiver gets the message).
+ 
+ "path" is where you can specify which servers you would like this message to go
+ through (this overrides "chain"). You can specify a semi-colon (";") separated
+ list of server "nicknames" here.
+ 
+ "encrypt" means that Elm should encrypt your messages with the PGP public key
+ of server you are remailing through (note that if chain > 1 or there is more
+ that one server in "path", Elm will do the "right" thing and call PGP multiple
+ times for each hop).
+ 
+ Once the desired options are set, you can quit the menu and send the message.
+ What you see next will vary... If you are a PGP user and set encrypt=TRUE in
+ the remailer menu, you will see the call(s) to pgp flash across your screen.
+ Otherwise you will most likely just see the "Mail sent." message.
+ 
+ If you have MIME defined, it should be possible for you to include attachments
+ in your anonymous mail in the normal manner. Most servers these days support
+ the "hash" option which Elm makes use of to pass the proper MIME headers.
+ 
+ NEW ELMRC OPTIONS
+ 
+    * usepgppass = [ ON | OFF ]
+      Default: usepgppass = OFF
+         o OFF: Elm does not keep your passphrase in memory. You must enter it
+           each time you want to decrypt a pgp mail.
+         o ON: Elm keep your passphrase in memory for "keeppassfor" seconds.
+    * keeppassfor = <number>
+      Default: keeppassfor = 0
+         o keeppassfor>=0: Elm will keep your passphrase in memory for seconds
+           after entering the passphrase.
+         o keeppassfor<0: Elm will keep your passphrase in memory without
+           clearing it from memory.
+    * noencoding = <level>
+      Default: noencoding = 0
+ 
+      This control makes it possible to send raw 8bit or binary data when the
+      MTA doesn't support 8BITMIME and the -B8BITMIME option or BINARYMIME and
+      the -BBINARYMIME option.
+ 
+      Possible values:
+         o  0 : Always convert 8BIT and BINARY data to QUOTED-PRINTABLE if the
+           MTA doesn't support the -B8BITMIME and -BBINARYMIME options.
+         o  1 : Allow 8bit without -B8BITMIME, but binary data is encoded
+         o  2+: Allow binary without -BBINARYMIME and and 8bit without
+           -B8BITMIME
+      It is STRONGLY recommended that it be left set to 0 unless you know what
+      you are doing!!
+    * showto = [ ON | OFF ]
+      Default: showto = OFF
+         o ON: Elm should show you who the message is addressed to rather than
+           who it is from if the message is not addressed to you.
+         o OFF: normal behavior
+    * pagemultipart = [ ON | OFF ]
+      Default: pagemultipart = ON
+         o ON: Use the internal MIME support to display MULTIPART messages
+           rather than calling metamail
+         o OFF: display MULTIPART messages with metamail
+    * mimeforward = [ ON | OFF ]
+      Default: mimeforward = OFF
+         o ON: When forwarding a message, Elm will attach as a MIME body part of
+           type MESSAGE/RFC822.
+         o OFF: Elm will include the forwarded message in your message, just
+           like it always has.
+ 
+ BUILTIN++ PAGER
+ 
+ This pager looks a lot like more, but has some of the movement features of
+ less, most notably, paging backwards through your messages. Press '?' inside of
+ the pager for a list of valid keystroke commands.
+ 
+ TAGS
+ 
+ Use the keyword "tagged" in the "Delete messages with pattern" (invoked by ^D
+ in the index menu) to delete all tagged messages.
+ 
+ You can now use the keyword "all" to tag all visible messages.
+ 
+ LIMIT FUNCTIONALITY
+ 
+    * Simple compound statements can be made using '|' (OR) and '&' (AND).
+    * The "Cc:" field is now availible for search.
+    * New keyword "tagged" for narrowing to only the currently tagged messages.
+ 
+ MISCELLANEOUS
+ 
+ '*' may be used as a wildcard in the "alternatives" list in the elmrc file. For
+ instance, "me@*.hmc.edu" would me to match the user "me" in all hosts from the
+ "hmc.edu" domain.
+ 
+ Elm will keep track of the messages which you have replied to with an 'r' mark
+ in the index menu.
+ 
+ Forwarded messages are encapsulated instead of quoted like replies:
+ 
+         ----- Forwarded message from Joe User  -----
+         [...]
+         ----- End of forwarded message from Joe User  -----
+ 
+ You can effect an automatic Bcc: line by setting the address(es) in the "BCC"
+ environment variable. Note that this is non-standard, but provided as a means
+ of accomplishing the task.
+ 
+ BUGS
+ 
+ A list of known bugs can be found at
+ http://www.cs.hmc.edu/~elkins/elm/bugs.html.
+ 
+ AUTHOR
+ 
+ Michael Elkins <elkins@aero.org>
+ Home Page: http://www.cs.hmc.edu/~me/index.html
+ 
+ If you are interested in knowing what my future plans are, you can browse my
+ "TO DO" list at http://www.cs.hmc.edu/~me/elm/todo.html
+ 
+ THANKS
+ 
+ Kari Hurrta <Kari.Hurtta@fmi.fi> has contributed a great deal to the MIME
+ support (and fixed lots of my stupid bugs ;-)
+ 
+ I would also like to thank everyone who took the time to report bugs or suggest
+ improvements!
+ -------------------------------------------------------------------------------
+ Last updated Sept 21, 1995.
Index: WORK/ChangeLog.ME
*** /tmp/null.14101	Tue Aug 20 22:05:34 1996
--- WORK/ChangeLog.ME	Mon Jun  3 20:15:19 1996
***************
*** 0 ****
--- 1,805 ----
+ -----------------
+ Changes from ME8a
+ -----------------
+ When checking to see if the subject line should be centered when displaying
+ a mail message, the weedlist check should be for "subject:", not "subject".
+ This case is more general.
+ 
+ control-F in the main menu now causes Elm to forget your passphrase.  Useful
+ for when you screw up so you don't have to exit Elm before using PGP
+ again.
+ 
+ Added a "metoo" argument in pgp_encrypt to decide whether or not the
+ +encrypttoself=on flag should be passed to pgp.  This was needed so that
+ the value of auto_cc can be overidden when remailing.
+ 
+ Added support for decoding of RFC1522 style encoded headers.  This should
+ work in the index menu, the pager, and when replying (the "attribution").
+ 
+ metapager will now recover if pgp fails by displaying the message "as is"
+ in the case where the message is only signed.
+ 
+ Simplified "pager" check in metapager since there are two pagers now.
+ 
+ Fixed problem in copy_message where the rfc822 newline at the end of the
+ headers was missing.
+ 
+ Fixed bug in menu2.c:generic_menu (used by the remailer) which caused
+ Elm to segfault when not compiled with gcc.
+ From: Andrey A. Chernov <ache@astral.msk.su>
+ 
+ Fixed problem where trailing MMDF separator was still being printed.
+ 
+ The default filename for the Content-Disposition header was not getting
+ set if the included file did not have an extension.
+ 
+ text/plain => application/pgp conversion is now NOT done for public key
+ blocks.
+ 
+ Configure now figures out where "finger" is instead of hardcoding a path
+ in remailer.c
+ 
+ Hopefully fixed definition for sleep() in defs.h.
+ 
+ Fixed bug where elm would segfault when typing ^E when there are no messages
+ in the mailbox.
+ 
+ Fixed bug where a leading space could be inserted before the real name when
+ looking up a PGP public key from the return address.
+ 
+ Fixed some of the movement commands in builtin++ so that they work now.
+ 
+ Convert application/x-pgp-* => application/pgp to decode messages generated
+ by pgpelm.
+ 
+ Fixed problem where if the signature was added after editing the message,
+ it would be written over the message right after the content length.  Fixed
+ by seeking to the end of the file after writing the content length field.
+ 
+ ----------------
+ Changes from ME8
+ ----------------
+ Fixed bug in conversion of text/plain => application/pgp in newmbox.c which
+ was causing Elm to segfault. (Thanks to Kari.Hurtta@fmi.fi)
+ 
+ Fixed bug where builtin++ segfaults when viewing zero length messages.
+ 
+ -----------------------
+ Changes from ME8alpha19
+ -----------------------
+ Fixed bug where external pager did not work with non-MIME messages when
+ USE_PGP is defined.
+ 
+ Cleaned up mime_pgp_decode so that it does not need to look at the
+ header_rec for the current message any longer.
+ 
+ Do text/plain => application/pgp conversion in newmbox.c if PGP type data
+ is discovered in the message.  This supports those who are sending PGP
+ messages but are not compliant with what Elm expects.
+ 
+ Added the control-E (extract public key) command to showmsg_c.c.
+ 
+ Security fix from Olaf Kirch <okir@monad.swb.de> which forces Elm to write
+ the temp spool mailbox in the user's home directory instead of /tmp.  This
+ prevents exploitation of symlinks to create a .rhosts in the user's 
+ directory.
+ 
+ Fixed bug in show_status where flags from the previous message were not
+ being properly cleared with USE_PGP was defined and MIME was not.
+ 
+ -----------------------
+ Changes from ME8alpha18
+ -----------------------
+ added application_decode for support of APPLICATION/* types.  Calls
+ null_decode if the subtype is unknown.
+ 
+ rfc822_decode now matches the headers against the weedlist when printing
+ out.  You can view all the headers for a message by pressing 'h' while
+ viewing a message just as you normally would.
+ 
+ added mime_pgp_decode for inline decoding of application/pgp parts.
+ application/pgp at the top level is still handled by metapager since some
+ people will be configured without MIME.  I might eventually require that
+ to use PGP, you must also define MIME, but not yet!
+ 
+ Status header was printed in the wrong place with BINARY encoding.
+ From: Kari.Hurtta@fmi.fi
+ 
+ Added the DONT_ADD_FROM and NEEDS_LONE_PERIOD_ESCAPE checks to write_encoded,
+ and other MIME text parts.
+ From: Kari.Hurtta@fmi.fi
+ 
+ Added a "type_opts" field in mime_send_t.
+ 
+ mime_write_header now just writes the MIME headers.  The code to add the
+ boundary for multipart messages and the charset for text/plain was moved into
+ mailmsg2.c.
+ 
+ Changed pgp code to set MIME fields to use add_parameter and type_opts instead
+ of directly writing to subtype.
+ 
+ Made some changes in the Content-Type for PGP messages to be more compliant
+ with the unofficial standard.
+ 
+ -----------------------
+ Changes from ME8alpha17
+ -----------------------
+ MIME header code in write_header_info() was moved to 
+ mime_write_header in mime_encode.c.  This was done to greatly simplify the
+ code, and to make it possible for me to send MIME messages with the
+ remailer code.  This will also make it possible for me to have PGP
+ encrypted MIME messages in the future.
+ 
+ Content-Length headers are generated regardless of whether or not MIME
+ is defined.
+ 
+ Lots of changes to the remailer code to make it work with MIME.
+ 
+ -----------------------
+ Changes from ME8alpha16
+ -----------------------
+ Removed Content-Length header from attachments included by the "[include ...]"
+ statement.
+ 
+ Made the existing global variables that set the toplevel Content-Length header
+ a part of mime_send_t.  This has the side effect that if MIME is not
+ defined, no Content-Length header will be added on outgoing messages.
+ 
+ Commented out the code which reads the content-length header from attachments
+ in mime_parse.c.  It should now ignore that header and figure out the length
+ in multipart_parse().
+ 
+ -----------------------
+ Changes from ME8alpha15
+ -----------------------
+ New option "mimeforward" controls whether or not forwarded messages are
+ sent as MESSAGE/RFC822 MIME messages, or are sent in the old non-MIME
+ way.
+ 
+ - Fixes for my mistakes in alpha15.
+ - text_unsupported_decode() added for printing warning message about
+ unsupported text subtypes.
+ From: Kari.Hurtta@fmi.fi
+ 
+ Changed disposition handing such that a message saying that the user should
+ type 'v' to view an attachment which is declared something other than
+ "inline".
+ 
+ -----------------------
+ Changes from ME8alpha14
+ -----------------------
+ Make sure that arguments to fseek(), etc., are type long.
+ From: Kari.Hurtta@fmi.fi
+ 
+ Added some general access commands for attachments in the attach_menu.c
+ routines.
+ From: Kari.Hurtta@fmi.fi
+ 
+ The disposition is now displayed in the little mini-header.  This looks nicer
+ than the previous message about "[Content-Disposition: attachment, skipping]".
+ 
+ select_CT_decoder now returns text_decode for all TEXT types.  My reasoning
+ here is that since the MIME spec says that all unknown subtypes of TEXT
+ should be treated as TEXT/PLAIN so long as the charset is understood, then
+ all TEXT can be treated in this manner.
+ 
+ Made sure that the pgp field of header_rec gets set to zero when initializing
+ in attach_viewer and also in newmbox.c.
+ 
+ Removed lots of unused variables.
+ 
+ Added some parentheses in places to make "gcc -Wparentheses" happy.
+ 
+ -----------------------
+ Changes from ME8alpha13
+ -----------------------
+ Forgot to initialize usepass=FALSE in pgp_decrypt_init.  This caused elm
+ to hang when trying to decode a signed message while pgp was waiting for
+ the passphrase...
+ 
+ The attachment menu should now work properly for viewing message/rfc822
+ messages with the builtin pager.
+ 
+ When attaching a message/rfc822 with the "forward" command, you should
+ now be able to perform all the actions in attach_menu() as for a "normal"
+ attachment.
+ 
+ -----------------------
+ Changes from ME8alpha12
+ -----------------------
+ Tried to fix MIME_NOTPLAIN code again.  This time MESSAGE/RFC822 will not
+ have it set, which MULTIPART will if pagemultipart=OFF.
+ 
+ Fixed attach_menu so that Elm does not segfault when you try to do an
+ operation on an attachment when there are no attachments defined.
+ 
+ Removed the MIME_NOTPLAIN flag and made it a one-bit flag in mime_t instead.
+ Removed PGP flags from defs.h and use a 3-bit field in header_rec instead.
+ These two now ensure that the "status" field of header_rec is always less
+ than 65536 so that 16bit integer machines will not have troubles.
+ 
+ Elm now pays attention to what the MIME-Version header says and passes any
+ messages with an unknown MIME-Version header value to metamail, or displays
+ an error if $NOMETAMAIL is set.
+ From: Kari.Hurtta@fmi.fi
+ 
+ -----------------------
+ Changes from ME8alpha11
+ -----------------------
+ pgp_call() now uses the expanded_* address lists so that aliases are 
+ expanded before trying to look up the ids with PGP.
+ 
+ Fixed calls in mailmsg2.c with wrong number of arguments (botched job
+ including Kari Hurtta's patch).
+ From: Kari.Hurtta@fmi.fi
+ 
+ Reordered the preMIME code in newmbox.c to make it a little more efficient.
+ 
+ Fixed bug in write_header_info() where a spurious newline was being printed
+ after the Content-Type header for TEXT.  This was causing the remaining 
+ fields not to be a part of the message header.
+ 
+ Removed check for old-style RFCXXX Mime-Version header.  I don't believe
+ anybody uses that anymore since RFC1341 has been out so long.
+ 
+ pgp_status needed to be reset when the user aborts sending a message,
+ otherwise you can't encrypt another message until you successfully send
+ another message.
+ 
+ MIME_NOTPLAIN is not set for multipart messages if "pagemultipart" is TRUE.
+ 
+ Cleaned up code for deciding if metamail mail should be called to display
+ a message in showmsg.c.  Created a need routine, need_meta(), for this
+ purpose.
+ 
+ -----------------------
+ Changes from ME8alpha10
+ -----------------------
+ Fixes to remove some global MIME variables used for composing.
+ From: Kari.Hurtta@fmi.fi
+ 
+ Added a redraw command to the attachment menu.
+ 
+ Fixed the code in newmbox.c where MIME_NOTPLAIN was not set for non-TEXT
+ content-types.  Also, check for "plain" should be "text" for old-style
+ pre-MIME content-type headers.
+ 
+ Added a print command to the attachment menu.
+ 
+ Made the remailer support a Configure option.
+ 
+ ----------------------
+ Changes from ME8alpha9
+ ----------------------
+ Use Elm's error routines in the attachment menu. 
+ Protected iscntrl() more calling isascii() before it in builtin++.
+ From: Kari Hurtta <Kari.Hurtta@fmi.fi>
+ 
+ Added bit of code lost from old showmsg.c which centers the subject line 
+ after the title line in the case where "subject" is in the weedlist.
+ 
+ Viewing attachments with metamail while in send mode now works.  It required
+ different arguments to be passed to metamail.
+ 
+ -----------------------
+ Changes from ME8alpha8a
+ -----------------------
+ mime_t_clear() now sets the defaults of TEXT/PLAIN, ENCODING_7BIT, DISP_INLINE,
+ when called.
+ 
+ More fixes from Kari Hurtta <kari.hurtta@fmi.fi>
+ 
+ Removed padding bitfield from struct mimeinfo since it isn't needed.
+ 
+ Added +clearsig=ON when adding a PGP signature to a message.
+ 
+ Added prototypes for the functions defined in pgp.c.
+ 
+ Elm will now allow you to edit the list of usernames to encrypt to when
+ using PGP.  This fixes the problem where sometimes the return address
+ doesn't match the address on the key.  However, it still requires that
+ the user know this.
+ 
+ Implemented Kari Hurtta's suggestion of using a "state" variable for the
+ MIME output when decoding messages.  This will make it easier to add new
+ extensions for output.  The state information is defined in hdrs/state.h
+ 
+ The user interface for the attachment menu now is more consistent with
+ the mailbox menu.  (Kari.Hurtta@fmi.fi)
+ 
+ User is now asked for confirmation upon deleting an attachment from the
+ attachment menu if "ask=ON" in the elmrc.
+ 
+ Fixed replying to messages with PGP signatures.  They were getting sucked
+ into the new MIME code and getting skipped as an unknown type.
+ 
+ Added new procedure to allow for extraction of PGP public keys directly
+ instead of relying on metamail.
+ 
+ If Elm can't find a PGP key that it is looking for, it now tells the user
+ which key instead of just that there was an error.
+ 
+ The user is now allowed to re-edit the filename in attach_modify() if the
+ file was not found.  This also allows a user to change the file associated
+ with an attachment.
+ 
+ Fixed very old bug of MMDF separators being printed when displaying a
+ message.
+ 
+ ----------------------
+ Changes from ME8alpha8
+ ----------------------
+ Fixed problem where you couldn't edit the default filename in attach_save().
+ 
+ ----------------------
+ Changes from ME8alpha7
+ ----------------------
+ Use safe_malloc() and safe_realloc() instead. (Kari Hurtta)
+ 
+ Fixed bug where no EOLN token was printed after the Content-Type header
+ when type_opts was NULL in attach_generate_message().
+ 
+ Reorganized struct mimeinfo so that bitfields are next to each other and
+ added padding to make them 1 byte long total.
+ 
+ -----------------------
+ Changes from ME8alpha6+
+ -----------------------
+ Reduced memory usage in "struct mimeinfo" by using bitfields or pointers
+ instead of predefined strings when possible.  Also removed the "comments"
+ fields.
+ 
+ New routine lib/strmcpy.c for doing malloc/realloc and strcpy in one shot.
+ Helps out with the above objective.
+ 
+ The attachment menu now defaults to disposition "inline" when sending
+ mail.
+ 
+ Reorganized the screen in the attachment "configuration" menu.
+ 
+ Removed code for adding "name=" field to APPLICATION/OCTET-STREAM types.
+ Uses Kari's code for Content-Disposition "filename" instead.  attach_menu()
+ still supports both for getting default filename when saving an
+ attachment.
+ 
+ Removed MIME_MULTIPART flag.  Use MIME_TYPE_MULTIPART with "type" instead.
+ 
+ Removed "encoding" field from "header_rec".  Use "encoding" in "mimeinfo"
+ instead (this was already mostly true, but there were a few cases left
+ over from the early support for encoding...)
+ 
+ ----------------------
+ Changes from ME8alpha6
+ ----------------------
+ Incorporated changes from Kari Hurtta <Kari.Hurtta@FMI.FI>.
+ Big changes are the use of Content-Disposition and routines to better parse
+ rfc822 headers.  Also fixed multi-line MIME header problem in newmbox.c
+ 
+ ----------------------
+ Changes from ME8alpha5
+ ----------------------
+ Fixed places where "/tmp" was hardcoded for temporary files instead of using
+ "temp_dir" in the ME extensions.
+ 
+ Fixed more isspace() problems with "signed char".
+ 
+ Made some formatting improvements in multipart_decode().
+ 
+ Fixed bug where multi-line Content-Type headers were not properly parsed in
+ newmbox.c.
+ 
+ Added builtin++2.c which contains a tempfile based pager which may become
+ part of the "official" distribution.  For right now it is "experimental".
+ 
+ ----------------------
+ Changes from ME8alpha4
+ ----------------------
+ Fixed attach_modify() to use ->type and ->subtype like the rest of the
+ attachment routines.
+ 
+ Viewing an attachment while sending didn't work because it read from
+ mailfile...  Now it can view external files as well.
+ 
+ Fixed problem with signed char and iscntrl() in AddLineToCache().
+ This fixes the problem with umlaut characters in some sets.
+ From: guy@netapp.com.
+ 
+ Modified mime_generate_boundary() to use mime_count as a counter so that
+ subsequent calls will generate different values.
+ 
+ Elm will now read ~/.elm/mime.types and $libdir/elm.mimetypes (system
+ mime.types file), if they exist, to map filename extensions to
+ Content-Type values when sending attachments.  The format of this file
+ is:
+ 	<suffix> <content-type>
+ There must be no line breaks in the Content-Type field.
+ Example:
+ 	tar	application/octet-stream; type=tar
+ for .tar files.
+ NOTE: data which is declared "application/octet-stream" will automatically
+       get the option "name=<default_filename>" added to it, so there is no
+       need to put it in the definition.
+ 
+ Modified attach_info() so that it uses BASE64 encoding for "application"
+ types that have 8bit or control chars in them.
+ Also, "image" automatically defaults to BASE64 without reading the file.
+ 
+ attach_save() now uses the "name=<default_filename>" field of "application"
+ types as the default filename.
+ 
+ Added '+' as a synonym for NEXT_PAGE in builtin++ per popular request.
+ 
+ attach_generate_msg() no longer puts Content-Length headers on parts that
+ it generates.
+ 
+ ----------------------
+ Changes from ME8alpha3
+ ----------------------
+ Added support for multi-line Content-Type: headers in read_headers() and
+ mime_read_headers().
+ 
+ me.h now contains prototypes for functions defined by this set of patches.
+ 
+ Fixed some problems with using PGP and remailers.
+ 
+ Fixed parsing of options in the Content-Type header so that semicolons
+ inside quotes are protected.
+ 
+ If MIME is defined, forwarded messages will be an attachment of type
+ MESSAGE/RFC822.
+ 
+ Fixed problem with viewing MULTIPART or MESSAGE/RFC822 attachments from
+ the attachment menu.
+ 
+ Replaced MIME_BOUNDARY with a function (mime_generate_boundary()) that
+ sets the global variable "mime_boundary" to generate unique multipart
+ boundaries.  This is important now that Elm will be sending out
+ MESSAGE/RFC822 data which Elm might have originally generated...
+ 
+ ----------------------
+ Changes from ME8alpha2
+ ----------------------
+ Added a second line for menu items in verify_transmission() since adding
+ the "r)emailer" option didn't fit on the first line.
+ 
+ Modified the PGP code a little for more flexibility.  You can now specify
+ a string of "ids" to encrypt with in pgp_call().
+ 
+ ---------------------
+ Changes from ME8alpha
+ ---------------------
+ The menus from attach.c and attach_send.c were combined into a single
+ menu in attach_menu.c which servers both purposes.  The difference is
+ whether or not the user is allowed to modify the given attachments.
+ 
+ The rest of attach_send.c was renamed as mime_encode.c.
+ 
+ -----------------
+ Changes from ME7a
+ -----------------
+ 
+ Added a check in quoted_printable_decode() to make sure that the index
+ into outbuf[] does not run off the end and cause problems.
+ 
+ attach_edit() didn't return TRUE after editing in one spot, which causes
+ problems on some platforms, namely Solaris.
+ From: Martin Walter <mawa@ruf.uni-freiburg.de>
+ 
+ base64_decode() was broken because it would fread() a data chunk, and 
+ wasn't always a multiple of 4 bytes, causing the decoding to break.
+ 
+ Changed char => unsigned char in most places in *_encode() to fix problems
+ with ISO characters >127.
+ 
+ Added message about PGP support for the 'elm -v' command in args.c.
+ 
+ Support for anonymous remailers. [ALPHA]
+ 
+ Major rewrite of the MIME handling code.  MULTIPART and MESSAGE/RFC822
+ messages are parsed the first time they are accessed (eg. viewed/replied)
+ and then are ready to use without parsing after that.  See mime_parse.c
+ and mime_decode.c for details.
+ 
+ From: Kari Hurtta <Kari.Hurtta@fmi.fi>
+   Put a loop around verify_transmission() so that Elm will no longer just
+   be lame when an error occurs in [include ...] statements.  (Way cool! -Ed)
+ 
+   Don't allow user read or writes files as attachmentds which he don't heve 
+   access. Notice that elm is (usually) setgid mail.
+ 
+   Consider if MTA supports 8BITMIME also when encoding attachments.
+ 
+   Now mail is encoded with quoted-printable if it includes control characters.
+   8BITMIME doesn't help in this case.
+ 
+   Attachments are checked for 8bit characters, then content-transfer-encoding
+   7bit is not allowed.
+ 
+   If any of subpart (also attachments) have content-tarnsfer-encoding 8bit
+   or binary it propagates to content-transfer-encoding of top multipart -type.
+ 
+   Now taken note of MIME's canonical encoding model:
+   - End of line in text -subtypes when they have encoded with BASE64
+     must be encoded as CR LF.
+   - Also CR and LF must be encoded in quoted-printable-encoding if
+     type have binary data (ie. not line oriented).
+   - Done mapping CR LF -> LF when decoding text -subtypes.
+ 
+   These content-transfer-encoding checks for attachments are also done
+   for [include ...] keywords when sending.
+ 
+   Now [include ...] also don't need metamail's help (they use same routines
+   than attachments menu).
+ 
+   Added configuration file option 'noencoding' (see elmrc-info for details
+   on what this does).
+ 
+ ----------------
+ Changes from ME7
+ ----------------
+ 
+ Forgot to kill the newline from the PGP output before putting it in to the
+ builtin++ pager.  This resulted in messages being displayed double-spaced.
+ Ick!
+ 
+ ----------------
+ Changes from ME6
+ ----------------
+ 
+ attach_send.c needs <sys/stat.h> on some machines.
+ 
+ Fixed initialization of arrays in attach_send.c because CC isn't quite
+ ANSI compliant.  You can only initialize static arrays.
+ From: Guy Harris <guy@netapp.com>
+ 
+ Added support for sendmail 8.7 which has support for 8BIT content 
+ encoding.  Uses the -B8BITMIME option.
+ From: Kari Hurtta <hurtta@dionysos.fmi.fi>
+ 
+ Fixed problem where QUOTED-PRINTABLE messages were not decoded when
+ replying if USE_PGP was not defined.
+ From: Kari Hurtta <hurtta@dionysos.fmi.fi>
+ 
+ [keyword ...] constructs are no longer broken when using MIME and the
+ message is to be encoded QUOTED-PRINTABLE.
+ From: Kari Hurtta <hurtta@dionysos.fmi.fi>
+ 
+ Made the QUOTED-PRINTABLE encoding routine more compliant with the
+ standard.
+ From: Kari Hurtta <hurtta@dionysos.fmi.fi>
+ 
+ Added patch to mark messages NEW in all folders (not just the SPOOL)
+ if there is no status: line.
+ NOTE: This will probably go away when 2.5 is released.  Instead, they
+ will use some sort of "magic" flag to accomplish the same thing.
+ 
+ Added check to make sure that we don't run off the end of outbuf[] in
+ base64_decode() in mime.c.
+ From: Kurt.Jaeger@rus.uni-stuttgart.de
+ 
+ Fixed type casting problem with BSD 4.4 derivatives in mime.c.
+ From: Andrey A. Chernov <ache@astral.msk.su>
+ 
+ KOI8-R added as a valid compat charset.
+ From: Andrey A. Chernov <ache@astral.msk.su>
+ 
+ builtin++ now wraps the line at the number of columns on the screen, not
+ one character before.  NewLine() apparently "does the right thing" and
+ doesn't print an extra line if the last character is in the last column.
+ From: Kari Hurtta <Kari.Hurtta@fmi.fi>
+ 
+ The arrow keys now do what they did before instead of controlling the
+ bultin++ pager.
+ 
+ builtin++ always clears the screen before displaying the next (or
+ previous) page.
+ 
+ The length of a line in the cache for builtin++ is increased to 150
+ chars because the old value of 128 didn't work with hpterms with a 
+ width of 134 chars.
+ 
+ Fixed problem where Elm would SIGBUS if you tried to use the
+ attachments menu in an empty folder.
+ From: Kari Hurtta <Kari.Hurtta@fmi.fi>
+ 
+ buf[STRING] was too short in AttachmentMenu() and caused certain Elm to
+ bomb out on certain messages which had header lines which were too
+ long.
+ 
+ AddLineToCache() can now handle multiline input.  This meant that
+ calls to it from metapager had to remove the trailing newlines.
+ 
+ Changed the MIME mini-header format in metapager().
+ 
+ attach_edit() looks more like header_edit() now.  Makes the interface
+ more consistent.
+ 
+ lib/getrealname.c needed <ctype.h> on older BSD systems.
+ 
+ Fixed nasty bug where the blank line in between the headers and the body
+ of a NEW message would get deleted when resync'ing in the spool folder.
+ 
+ Fixed infinite loop in Configure when run with the -d option.
+ 
+ ----------------
+ Changes from ME5
+ ----------------
+ 
+ Added the DoAll() call so that the keyword "all" can be used when tagging
+ or deleting.
+ 
+ Decoupled PGP and MIME support such that you don't need MIME to use PGP.
+ 
+ Added lots of error checking code in metapager.c.
+ From: guy@netapp.com (Guy Harris).
+ 
+ Fixed bug in quoted_printable_decode() where I did not convert read
+ characters to base16.
+ 
+ Added hex() function to protect index_hex from bad values.
+ 
+ metapager() prompts for a command if necessary after running the external
+ pager, just as Elm used to do.
+ 
+ Fixed the From: line in write_header_info() where I broke it before.
+ 
+ Fixed bug where the MIME multipart boundary would be written after the
+ MMDF separator when copy=ON and the message was being copied to the user's
+ desired folder.
+ 
+ Added an "Attachments" menu in verify_transmission() for including 
+ attachments.  This works in addition to the current method of using
+ "[include ..."
+ 
+ Elm now directly supports writing of BASE64 and QUOTED-PRINTABLE
+ encodings.
+ 
+ Changed the return value of match_address() to be zero, since it
+ returns an int, and NULL is not always an int.
+ From: Michael Shields <shields@tembel.org>
+ 
+ AttachViewer() now uses notplain() to determine whether or not
+ metamail is needed to view the message.
+ From: Guy Harris <guy@netapp.com>
+ 
+ needs_mmdecode() now takes the integer version of the encoding rather
+ than a string.  This avoids parsing the string twice.
+ From: Guy Harris <guy@netapp.com>
+ 
+ Elm now checks outgoing messages to see if there are any non-printable
+ characters, and if so encodes the message QUOTED-PRINTABLE.
+ 
+ Cleaned up PGP code by moving more code to pgp.c so that other files
+ require less modification (ie. the diffs will be simpler).
+ 
+ Fixed showmsg.c so that it passes anything that doesn't require metamail
+ to the metapager.  This fixed the problem where messages with no
+ Mime-Version header but had a Content-Type header wouldn't get displayed.
+ From: Guy Harris <guy@netapp.com>
+ 
+ Fixed bug in dispaddr.c so that if a message is from the user, it will
+ always use the TO address to display.
+ 
+ Moved get_real_name() to its own file in lib so it can be used by
+ dispaddr.c.
+ 
+ Modified get_real_name() so that if it sees an address like
+ "<elkins@aero.org>" it will return "elkins@aero.org" instead of a zero
+ length string.
+ 
+ ----------------
+ Changes from ME4
+ ----------------
+ 
+ Introduced the "metapager".  It replaces most of the code in showmsg.c.
+ It also takes care of all the MIME and PGP functions the bultin++ pager
+ used to perform, so that the user doesn't have to use builtin++ in those
+ cases.
+ 
+ PGP decrypting function was rewritten using pipes so no temp files are
+ required!
+ 
+ The attachment handling code was modified to handle multiline content-type
+ headers generate by such mailers as zmailer.  It also looks through each
+ modifier in the line intead of just assuming that the boundary field will
+ be the first.
+ From: guy@netapp.com (Guy Harris)
+ 
+ The "command" status line in the builtin++ pager now floats around instead
+ of always being on the bottom.  This was done to facilitate the ^L in
+ the pager so it didn't look stupid.
+ 
+ Moved the MIME QUOTED-PRINTABLE and BASE64 decoding code to mime.c so it
+ can be shared.
+ 
+ Fixed copy_message() so that it will automatically decode MIME B64 and QP
+ encodings.  This means that replies to these types of messages do what the
+ user will expect.
+ 
+ ----------------
+ Changes from ME3
+ ----------------
+ 
+ Fixed problems in builtin++.c and pgp.c where I used the return value
+ from sprintf() as a char* when in SYSV systems it returns an int. 
+ This caused Elm to seg fault while decrypting messages.
+ 
+ Configure now asks about PGP support and automatically sets up
+ config.h.  Thanks to Ken Cox (kenc@viewlogic.com) for additional help.
+ 
+ PGP messages are now automatically decrypted when replying if
+ usepgppass = ON.
+ 
+ Back to using the application/pgp format content-type.  Use
+ format=keys-only for send a public key block.
+ 
+ PGPCall() now uses the pgp option +encrypttoself=on instead of tacking
+ the username on the end of the TO list.
+ 
+ Fixed problem where any messages after sending a PGP public key had
+ the key text included before the included message text.
+ 
+ Use rename() if availible instead of copying the file in PGPCall(). 
+ Otherwise use link(), unlink().  This should be a little more
+ efficient.
+ 
+ pgp is now called with the -w (wipe) option when encrypting.
+ 
+ builtin++ can now handle text which is QUOTED-PRINTABLE or BASE64
+ encoded.
+ 
+ Fixed bug where the last line of messages was not being printed.
+ 
+ Elm will no longer seg fault if you hit return without entering your
+ PGP passphrase.
+ 
+ Discovered the +batchmode option for pgp.  This makes dealing with
+ incorrect passphrases much easier!
+ 
+ Fixed bug in builtin++ where the last line of pgp messages would be
+ printed more than once while at the end of the message under certain
+ circumstances.
+ 
+ Changed notplain() in mime.c to support message/* content-type.
+ 
+ Cleaned up the multipart handling by removing the boundary string from
+ header_rec to conserve memory.  This is now handled by builtin++ and
+ AttachMenu().
+ 
+ builtin++ can now handle multipart/digest correctly.
+ 
+ SaveAttach() no longer needs to call metamail to decode QUOTED-PRINTABLE
+ or BASE64 encodings.
+ 
+ -----------------
+ Changes from ME2a
+ -----------------
+ 
+ Elm will now keep track of your PGP passphrase for your RSA secret key.
+ To use this feature, add the line "usepgppass = ON" to your .elmrc.
+ There is also a timeout feature which will cause Elm to "forget" your
+ passphrase after so many seconds if you don't use it.  The default is
+ 300 seconds, but this can be changes by setting the variable
+ "keeppassfor" in your .elmrc.
+ 
+ The builtin++ pager was completely rewritten (again) so that it can now
+ handle normal messages, MIME multipart messages, automatic decryption
+ and automatic signature checking for PGP messages.  It also seems to be
+ lacking some of the memory allocation bugs that the previous pager had.
+ 
+ Fixed a bug in DynamicArray() which causes DestroyDynamicArray() to
+ seg fault if exactly max+n elements were allocated. (weo@recco.de)
+ 
+ ----------------
+ Changes from ME2
+ ----------------
+ 
+ It is now possible to delete all "tagged" messages by entering "tagged"
+ as the pattern to match after typing <control>-d (^D).
+ 
+ fixed a bug in the limit command where you could not "un"limit the
+ display of headers.  Thanks to guy@netapp.com (Guy Harris) for
+ pointing it out!
+ 
+ fixed a bug in is_multipart() where the "boundary" token match was
+ case-sensitive.
Index: WORK/Configure
*** elm2.4.25/Configure	Mon May 30 19:55:55 1994
--- WORK/Configure	Sun Jun 16 22:05:35 1996
***************
*** 15,21 ****
  # working with this copy of Configure, you may wish to get metaconfig.)
  
  : sanity checks
! PATH=".:/bin:/usr/bin:/usr/local/bin:/usr/ucb:/usr/local:/usr/lbin:/etc:/usr/new:/usr/new/bin:/usr/nbin:$PATH"
  export PATH || (echo "OOPS, this isn't sh.  Desperation time.  I will feed myself to sh."; sh $0; kill $$)
  
  if test ! -t 0; then
--- 15,21 ----
  # working with this copy of Configure, you may wish to get metaconfig.)
  
  : sanity checks
! PATH=".:/bin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/ucb:/usr/local:/usr/lbin:/etc:/usr/new:/usr/new/bin:/usr/nbin:$PATH"
  export PATH || (echo "OOPS, this isn't sh.  Desperation time.  I will feed myself to sh."; sh $0; kill $$)
  
  if test ! -t 0; then
***************
*** 34,43 ****
      cd UU
  fi
  
! case "$1" in
! -d) shift; fastread='yes';;
  esac
  
  Log=''
  Header=''
  bin=''
--- 34,126 ----
      cd UU
  fi
  
! fastread=''
! extractsh=''
! 
! while test $# -gt 0; do
! 	case "$1" in
! 		-d) shift; fastread='yes';;
! 		-S) shift; extractsh=true;;
! 		-h) shift; error=true;;
! 		-*) echo "Configure: unknown option $1" >&2; shift; error=true;;
! 		*) break;;
! 	esac
! done
! 
! case "$error" in
! true)
!     cat >&2 << EOM
! Usage: Configure [-dS]
!   -d : use defaults for all answers.
!   -h : print this help message and exit (with an error status).
!   -S : perform variable substitutions on all .SH files
! EOM
!     exit 1
!     ;;
! esac
! 
! case "$extractsh" in
! true)
!     cd ..
!     . ./config.sh
!     echo " "
!     echo "Doing variable substitutions on .SH files..."
!     set x `awk '{print $1}' <MANIFEST | $grep '\.SH'`
!     shift
!     case $# in
!     0) set x *.SH; shift;;
!     esac
!     if test ! -f $1; then
! 	shift
!     fi
!     for file in $*; do
! 	case "$file" in
! 	*/*)
! 	    dir=`$expr X$file : 'X\(.*\)/'`
! 	    file=`$expr X$file : 'X.*/\(.*\)'`
! 	    (cd $dir && . $file)
! 	    ;;
!     	*)
! 	    . $file
! 	    ;;
!     	esac
!     done
!     if test -f config.h.SH; then
!     	if test ! -f config.h; then
! 	    : oops, they left it out of MANIFEST, probably, so do it anyway.
! 	    . config.h.SH
!     	fi
!     fi
! 
!     if $contains '^depend:' Makefile >/dev/null 2>&1; then
!     	dflt=n
!     	$cat <<EOM
! 
! Now you need to generate make dependencies by running "make depend".
! You might prefer to run it in background: "make depend > makedepend.out &"
! It can take a while, so you might not want to run it right now.
! 
! EOM
!     	rp="Run make depend now? [$dflt]"
!     	$echo $n "$rp $c"
!     	. UU/myread
!     	case "$ans" in
!     	y*) make depend && echo "Now you must run a make."
! 	    ;;
!     	*)  echo "You must run 'make depend' then 'make'."
! 	    ;;
!     	esac
!     elif test -f Makefile; then
!     	echo " "
!     	echo "Now you must run a make."
!     else
!     	echo "Done."
!     fi
!     exit 0
!     ;;
  esac
  
+ 
  Log=''
  Header=''
  bin=''
***************
*** 50,55 ****
--- 133,139 ----
  d_rename=''
  d_symlink=''
  d_whoami=''
+ d_poll=''
  n=''
  c=''
  orderlib=''
***************
*** 138,144 ****
  d_flock=''
  d_dotlock=''
  d_fcntlock=''
- lock_dir=''
  has_flock=''
  has_fcntl=''
  d_ftruncate=''
--- 222,227 ----
***************
*** 160,166 ****
  d_mallocvoid=''
  d_mboxedit=''
  d_mime=''
! defencoding=''
  defcharset=''
  defdispcharset=''
  d_mmdf=''
--- 243,253 ----
  d_mallocvoid=''
  d_mboxedit=''
  d_mime=''
! metamail_path=''
! metamail=''
! # defencoding=''
! d_8bitmime=''
! d_binarymime=''
  defcharset=''
  defdispcharset=''
  d_mmdf=''
***************
*** 248,253 ****
--- 335,341 ----
  ldflags=''
  cc=''
  libs=''
+ noaddlib=''
  nametype=''
  d_passnames=''
  d_berknames=''
***************
*** 267,272 ****
--- 355,366 ----
  xenlf=''
  d_xenix=''
  d_bsd=''
+ d_pgp=''
+ pgp=''
+ pgp_path=''
+ d_remailer=''
+ finger=''
+ finger_path=''
  CONFIG=''
  : set package name
  package=elm2
***************
*** 591,596 ****
--- 685,691 ----
  date
  emacs
  execmail
+ finger
  ispell
  line
  lint
***************
*** 597,607 ****
--- 692,704 ----
  lp
  lpr
  mailx
+ metamail
  mips
  more
  nroff
  pack
  pg
+ pgp
  pmake
  pr
  rmail
***************
*** 705,711 ****
  
  : see if date exists, if so, init c_date
  if $test ! "x$date" = "x" ; then
!     c_date=`LANGUAGE= $date`
  else
      c_date='date was unavailable at configuration'
  fi
--- 802,808 ----
  
  : see if date exists, if so, init c_date
  if $test ! "x$date" = "x" ; then
!     c_date=`LANG= LC_TIME= $date`
  else
      c_date='date was unavailable at configuration'
  fi
***************
*** 814,819 ****
--- 911,922 ----
  	echo exit 1 >bsd
  	echo exit 0 >usg
  	echo exit 1 >v7
+     elif $test "$uname_os" = "IRIX" ; then
+     : test `echo abc | tr a-z A-Z` = Abc does not work in IRIX 6.2
+ 	echo "Looks like an IRIX system, but we'll see.."
+ 	echo exit 1 >bsd
+ 	echo exit 0 >usg
+ 	echo exit 1 >v7
      else
  	echo "Looks kind of like a BSD system, but we'll see..."
  	echo exit 0 >bsd
***************
*** 881,886 ****
--- 984,991 ----
  	dflt=y
      elif xenix; then
  	dflt=y
+     elif $test "$uname_os" = "IRIX"; then
+         dflt=y
      else
  	dflt=n
      fi
***************
*** 1646,1652 ****
  
  case "$ccflags" in
  '') case "$cc" in
!     *gcc*) dflt='-fpcc-struct-return -traditional';;
      *) dflt='';;
      esac
      ;;
--- 1751,1757 ----
  
  case "$ccflags" in
  '') case "$cc" in
!     *gcc*) dflt='-fpcc-struct-return';;
      *) dflt='';;
      esac
      ;;
***************
*** 1754,1795 ****
  case "$libswanted" in
  '') libswanted='c_s';;
  esac
! for thislib in $libswanted; do
!     case "$thislib" in
!     dbm) thatlib=ndbm;;
!     *_s) thatlib=NONE;;
!     *) thatlib="${thislib}_s";;
!     *) thatlib=NONE;;
!     esac
!     xxx=`loc lib$thislib.a X /usr/lib /usr/ccs/lib /usr/local/lib /lib`
!     if test -f $xxx; then
! 	echo "Found -l$thislib."
! 	case "$dflt" in
! 	*-l$thislib*|*-l$thatlib*);;
! 	*) dflt="$dflt -l$thislib";;
  	esac
!     else
! 	xxx=`loc lib$thislib.a X $libpth`
  	if test -f $xxx; then
! 	    echo "Found $xxx."
  	    case "$dflt" in
! 	    *$xxx*);;
! 	    *) dflt="$dflt $xxx";;
  	    esac
  	else
! 	    xxx=`loc Slib$thislib.a X $xlibpth`
  	    if test -f $xxx; then
! 		echo "Found -l$thislib."
  		case "$dflt" in
! 		*-l$thislib*|*-l$thatlib*);;
! 		*) dflt="$dflt -l$thislib";;
  		esac
  	    else
! 		echo "No -l$thislib."
  	    fi
  	fi
!     fi
! done
  set X $dflt
  shift
  dflt="$*"
--- 1859,1904 ----
  case "$libswanted" in
  '') libswanted='c_s';;
  esac
! if [ "$noaddlib" != yes ]; then
!     for thislib in $libswanted; do
! 	case "$thislib" in
! 	dbm) thatlib=ndbm;;
! 	*_s) thatlib=NONE;;
! 	*) thatlib="${thislib}_s";;
! 	*) thatlib=NONE;;
  	esac
! 	xxx=`loc lib$thislib.a X /usr/lib /usr/ccs/lib /usr/local/lib /lib`
  	if test -f $xxx; then
! 	    echo "Found -l$thislib."
  	    case "$dflt" in
! 	    *-l$thislib*|*-l$thatlib*);;
! 	    *) dflt="$dflt -l$thislib";;
  	    esac
  	else
! 	    xxx=`loc lib$thislib.a X $libpth`
  	    if test -f $xxx; then
! 		echo "Found $xxx."
  		case "$dflt" in
! 		*$xxx*);;
! 		*) dflt="$dflt $xxx";;
  		esac
  	    else
! 		xxx=`loc Slib$thislib.a X $xlibpth`
! 		if test -f $xxx; then
! 		    echo "Found -l$thislib."
! 		    case "$dflt" in
! 		    *-l$thislib*|*-l$thatlib*);;
! 		    *) dflt="$dflt -l$thislib";;
! 		    esac
! 		else
! 		    echo "No -l$thislib."
! 		fi
  	    fi
  	fi
!     done
! else
!     echo "You told last time that additional libraries are not needed!"
! fi
  set X $dflt
  shift
  dflt="$*"
***************
*** 1816,1822 ****
  $echo $n "$rp $c"
  . myread
  case "$ans" in
! none) ans='';
  esac
  libs="$ans"
  
--- 1925,1936 ----
  $echo $n "$rp $c"
  . myread
  case "$ans" in
! none|'') ans='';
!     noaddlib='yes';
!     ;;
! *)
!     noaddlib='no'
!     ;;
  esac
  libs="$ans"
  
***************
*** 1941,1947 ****
  set `echo $libc $libnames | tr ' ' '\012' | sort | uniq`
  $echo $n "Extracting names from $* for later perusal...$c"
  nm $nm_opts $* 2>/dev/null >libc.tmp
! $sed -n -e 's/^.* [ATDS]  *[_.]*//p' -e 's/^.* [ATDS] //p' <libc.tmp >libc.list
  if $contains '^printf$' libc.list >/dev/null 2>&1; then
      echo done
  elif $sed -n -e 's/^__*//' -e 's/^\([a-zA-Z_0-9$]*\).*xtern.*/\1/p' \
--- 2055,2061 ----
  set `echo $libc $libnames | tr ' ' '\012' | sort | uniq`
  $echo $n "Extracting names from $* for later perusal...$c"
  nm $nm_opts $* 2>/dev/null >libc.tmp
! $sed -n -e 's/^.* [ATDSUW]  *[_.]*//p' -e 's/^.* [ATDSUW] //p' <libc.tmp >libc.list
  if $contains '^printf$' libc.list >/dev/null 2>&1; then
      echo done
  elif $sed -n -e 's/^__*//' -e 's/^\([a-zA-Z_0-9$]*\).*xtern.*/\1/p' \
***************
*** 1966,1971 ****
--- 2080,2089 ----
  	   <libc.tmp >libc.list; \
    $contains '^printf$' libc.list >/dev/null 2>&1; then
      echo done
+ elif $sed -n -e 's/^.* [ATDSUW]  *//p' -e 's/^.* [ATDSUW] //p' \
+ 	<libc.tmp >libc.list; \
+   $contains '^printf$' libc.list >/dev/null 2>&1; then
+     echo done
  else
      nm -p $* 2>/dev/null >libc.tmp
      $sed -n -e 's/^.* [AT]  *_[_.]*//p' -e 's/^.* [AT] //p' <libc.tmp >libc.list
***************
*** 2459,2479 ****
      echo 'Dot lock style locking will be used'
  fi
  
- if $test -d /usr/spool/locks ; then
-     lock_dir=/usr/spool/locks
- elif $test -d /usr/spool/uucp ; then
-     lock_dir=/usr/spool/uucp
- elif $test -d /var/spool/locks ; then
-     lock_dir=/var/spool/locks
- elif $test -d /var/spool/uucp ; then
-     lock_dir=/var/spool/uucp
- else
-     lock_dir=/tmp
- fi
- echo " "
- echo "Non-mailbox locks will use the $lock_dir directory"
- echo " "
- 
  : now get the host name
  if $test "$autohostname" != "$undef" -o "$hostname" = "" ; then
      autohostname="$define"
--- 2577,2582 ----
***************
*** 2642,2647 ****
--- 2745,2760 ----
      d_whoami="$undef"
  fi
  
+ 
+ : see if there is a poll file
+ echo " "
+ if $test -r /usr/include/poll.h ; then
+     d_poll="$define"
+     echo "poll.h found."
+ else
+     d_poll="$undef"
+ fi
+ 
  : see how we will look up host name
  echo " "
  d_douname="$undef"
***************
*** 3207,3224 ****
  case "$d_mime" in
  "$define") dflt=y;;
  "$undef")  dflt=n;;
! *)	   if $test -f "$metamail"; then
! 		$cat <<EOM
! 
! I've found the metamail program out there, I assume you want support for
! MIME (Multipurpose Internet Mail Extension, RFC 1341).
! 
! EOM
! 		dflt=y
! 	   else
! 		dflt=n
! 	   fi;;
! 
  esac
  $cat <<EOM
  
--- 3320,3326 ----
  case "$d_mime" in
  "$define") dflt=y;;
  "$undef")  dflt=n;;
! *)         dflt=y;;
  esac
  $cat <<EOM
  
***************
*** 3228,3247 ****
  doesn't necessarily need graphics capabilities on your display, but its
  useful.
  
- If you have installed Nathaniel Borenstein's metamail package for
- displaying MIME messages, elm can make use of it.  If you didn't
- have metamail installed you might want to obtain a copy of it.  The
- most recent version is on thumper.bellcore.com [128.96.41.1], or ask
- the archie servers for the nearest site.
- 
  Compiling elm even with MIME support enabled would not depend on the
! metamail package, but you would not be able to use nearly all of the
! MIME features as long as you don't have metamail installed.  Metamail
! with its companion programs (mmencode) must be installed somewhere in
! the search path, usually /usr/local/bin.
!   
! 
  
  EOM
  
  rp="Should support for MIME be compiled in? [$dflt]"
--- 3330,3342 ----
  doesn't necessarily need graphics capabilities on your display, but its
  useful.
  
  Compiling elm even with MIME support enabled would not depend on the
! Nathaniel Borenstein's metamail package, but you would not be able to 
! use nearly all of the MIME features as long as you don't have metamail 
! installed.  
  
+ You can also compile Elm with MIME support and tell that metamail should
+ not be used. This is configuration option.
  EOM
  
  rp="Should support for MIME be compiled in? [$dflt]"
***************
*** 3252,3258 ****
  *)  d_mime="$undef";;
  esac
  
- 
  case "$defcharset" in
  '') defcharset="US-ASCII";;
  *) defcharset="$defcharset";;
--- 3347,3352 ----
***************
*** 3263,3278 ****
  *) defdispcharset="$defdispcharset";;
  esac
  
! case "$defencoding" in
! '') if $test "$defcharset" = "US-ASCII"; then
! 		defencoding="7bit"
! 	else
! 		defencoding="8bit"
! 	fi;;
! *) defencoding="$defencoding";;
! esac
  
  if $test "$d_mime" = "$define"; then
  	dflt="$defcharset"
  cat <<EOM
  
--- 3357,3443 ----
  *) defdispcharset="$defdispcharset";;
  esac
  
! # case "$defencoding" in
! # '') if $test "$defcharset" = "US-ASCII"; then
! # 		defencoding="7bit"
! # 	else
! # 		defencoding="8bit"
! # 	fi;;
! # *) defencoding="$defencoding";;
! # esac
  
  if $test "$d_mime" = "$define"; then
+ 
+ case "$metamail_path" in
+ '') if test -f "$metamail" ; then
+ 	dflt="$metamail"
+ 	echo
+         echo "Metamail program found from $metamail"
+     else
+         dflt='none'
+     fi
+    ;;
+ *) dflt="$metamail_path"
+    ;;
+ esac
+ 
+ 
+ cat <<EOM
+ 
+ If you have installed Nathaniel Borenstein's metamail package for
+ displaying MIME messages, elm can make use of it.  If you didn't
+ have metamail installed you might want to obtain a copy of it.  The
+ most recent version is on thumper.bellcore.com [128.96.41.1], or ask
+ the archie servers for the nearest site.
+ 
+ This version (Elm 2.4ME+) does not use Metamail's companion programs 
+ (such as mmencode) directly, but metamail package supposes that
+ companion programs are installed to search path.
+   
+ What is the compile time default path for metamail?
+ Possible values include:
+ 	none		Don't call metamail
+ 	metamail	Call metamail if environment variable \$NOMETAMAIL
+ 			is not set.
+ 	/path		Call metamail via that path, if it is executable
+   
+ EOM
+ cont=true
+ while $test "$cont" ; do
+ 	rp="Default path for metamail? [$dflt]"
+ 	$echo $n "$rp $c"
+ 	. myread
+ 	case "$ans" in
+ 		none|metamail)
+ 			metamail_path="$ans"
+ 	    		cont=''
+ 		;;
+ 		/*)
+ 			if $test -f "$ans"; then
+ 		                metamail_path="$ans"	
+ 	    			cont=''
+ 			else
+ 	    			if $test "$fastread" = yes; then
+ 					dflt=y
+ 	    			else
+ 					dflt=n
+ 	    			fi
+ 	    			rp="File $ans doesn't exist.  Use that name anyway? [$dflt]"
+ 	    			$echo $n "$rp $c"
+ 	    			. myread
+ 	    			case "$ans" in
+ 	    				y*) 
+ 					metamail_path="$ans"
+ 					cont='';;
+ 	    			esac
+ 			fi
+ 		;;
+ 		*)
+ 			metamail_path="$ans"
+ 		;;
+ 	esac
+ done
+ 
  	dflt="$defcharset"
  cat <<EOM
  
***************
*** 3289,3299 ****
  	$cat <<EOM
  
  The Character Set which your terminals support. You could set this
! to one of the ISO-8859 charsets, even if you set the default for
! the Text Messages to US-ASCII, as the ISO-8859 charsets could display
! US-ASCII as well. For a X-Windows environment, ISO-8859-1 would be 
! a convenient value.
  
  EOM
  	rp="Default Character Set which could be displayed [$dflt]"
  	$echo $n "$rp $c"
--- 3454,3467 ----
  	$cat <<EOM
  
  The Character Set which your terminals support. You could set this
! to one of the ISO-8859 charsets or KOI8-R charset, even if you set
! the default for the Text Messages to US-ASCII, as the ISO-8859 and
! KOI8-R charsets could display US-ASCII as well. For a X-Windows
! environment, ISO-8859-1 would be a convenient value.
  
+ Default Display Character Set is overriden by environment variable
+ \$MM_CHARSET if it is set (and \$NOMETAMAIL is not set.)
+ 
  EOM
  	rp="Default Character Set which could be displayed [$dflt]"
  	$echo $n "$rp $c"
***************
*** 3300,3320 ****
  	. myread
  	defdispcharset="$ans"
  
! 	dflt="$defencoding"
! 	$cat <<EOM
! Default Content-Transfer-Encoding for MIME Content-type text.
! If you are using the default US-ASCII charset, you should use
! 7bit encoding. But if you are using some other national character
! set, 8bit is recommended, unless you are using a 7bit character set.
! For 8bit encoding your transport paths should be 8bit clean, which
! is not true all over the world. base64 or quoted-printable aren't
! yet supported for the default Content-Transfer-Encoding.
  
  EOM
! 	rp="Default Content-Transfer-Encoding for MIME Content-type text? [$dflt]"
! 	$echo $n "$rp $c"
! 	. myread
! 	defencoding="$ans"
  fi
  
  : see if mkdir exists
--- 3468,3673 ----
  	. myread
  	defdispcharset="$ans"
  
! # 	dflt="$defencoding"
! # 	$cat <<EOM
! # Default Content-Transfer-Encoding for MIME Content-type text.
! # If you are using the default US-ASCII charset, you should use
! # 7bit encoding. But if you are using some other national character
! # set, 8bit is recommended, unless you are using a 7bit character set.
! # For 8bit encoding your transport paths should be 8bit clean, which
! # is not true all over the world. base64 or quoted-printable aren't
! # yet supported for the default Content-Transfer-Encoding.
! # 
! # EOM
! # 	rp="Default Content-Transfer-Encoding for MIME Content-type text? [$dflt]"
! # 	$echo $n "$rp $c"
! # 	. myread
! # 	defencoding="$ans"
! 
! case "$d_8bitmime" in
! "$define") dflt=y;;
! "$undef") dflt=n;;
! *)  
! if $test "$mailer" = "$sendmail" ; then
! 	echo "Testing if your mailer supports -B8BITMIME ..."
! 	if $mailer -B8BITMIME -bv root >/dev/null < /dev/null; then
! 		echo "Yup. Option -B8BITMIME perhaps works."
! 		echo "(Sendmail 8.6 will accept but ignore that option.)"
! 		dflt=y
! 	else
! 		echo "Seems that option -B8BITMIME does not work."
! 		dflt=n
! 	fi
! else
! 	echo "Can't figure how to test if your mailer supports -B8BITMIME ..."
! 	dflt=n
! fi
! ;;
! esac
! 
! cat <<EOM
! 
! If your MTA (Mail transport Agent) supports 8BITMIME ESMTP -extension
! and accepts also option -B8BITMIME (that is BODYTYPE=8BITMIME), Elm
! can left doing encoding from 8bit to quoted_printable to MTA. Otherwise
! Elm does encoding of 8bit data itself. Sendmail version 8.7 supports
! 8BITMIME -extension.
  
  EOM
! rp="MTA supports -B8BITMIME -option? [$dflt]"
! $echo $n "$rp $c"
! . myread
! case "$ans" in
! y*) d_8bitmime="$define";;
! *)  d_8bitmime="$undef";;
! esac
! 
! # If mailer don't support 8BITMIME it also don't support BINARYMIME
! case "$d_8bitmime" in
! "$define")
! 
! case "$d_binarymime" in
! "$define") dflt=y;;
! "$undef") dflt=n;;
! *)  
! if $test "$mailer" = "$sendmail" ; then
! 	echo " "
! 	echo "Testing if your mailer supports -BBINARYMIME ..."
! 	if $mailer -BBINARYMIME -bv root >/dev/null </dev/null; then
! 		echo "Yup. Option -BBINARYMIME perhaps works."
! 		echo "(Is there really MTA what supports BINARYMIME?)"
! 		dflt=y
! 	else
! 		echo "Seems that option -BBINARYMIME does not work."
! 		dflt=n
! 	fi
! else
! 	echo "Can't figure how to test if your mailer supports -BBINARYMIME ..."
! 	dflt=n
! fi
! ;;
! esac
! 
! cat <<EOM
! 
! If your MTA (Mail transport Agent) supports BINARYMIME ESMTP -extension
! and accepts also option -BBINARYMIME (that is BODYTYPE=BINARYMIME), Elm
! can left doing encoding from BINARY to base64 or quoted-printabe to MTA. 
! Otherwise Elm does encoding of binary data itself. Passing of binary data
! requires that all text data lines are terminated with CRLF -- Unix's
! LF is NOT sufficient. Currently ELM don't use CRLF as line terminator
! in every places when using -BBINARYMIME option (so that option is only
! partially implemented by Elm). Notice also that isn't known any MTA (mailer)
! what implements BINARYMIME or accepts -BBINARYMIME option. Notice also
! that BINARYMIME is Experimental Protocol (as stated in RFC1830).
! 
! EOM
! rp="MTA supports -BBINARYMIME -option? [$dflt]"
! $echo $n "$rp $c"
! . myread
! case "$ans" in
! y*) d_binarymime="$define";;
! *)  d_binarymime="$undef";;
! esac
! 
! ;;
! *) d_binarymime="$undef";;
! esac
! 
! else
! 
! metamail_path="none"
! d_8bitmime="$undef"
! d_binarymime="$undef"
! 
! fi
! 
! : ask about PGP support
! if $test "$d_pgp" = "$define"; then
! 	dflt=y
! 	pgp=$pgp_path
! else
! 	dflt=n
! fi
! echo ''
! rp="Should PGP (Pretty Good Privacy) support be compiled in? [$dflt]"
! echo $n "$rp $c"
! . myread
! if test "$ans" = "y"; then
! 	d_pgp="$define"
! 	cont=true
! 	dflt="$pgp"
! 	while $test "$cont"; do
!                 rp="Where is the pgp binary located? [$dflt]"
! 		echo $n "$rp $c"
! 		. myread
! 		pgp_path="$ans"
! 		case "$ans" in
! 		/*)
! 			if $test -f $ans; then
! 				cont=''
! 			else
! 				if $test "$fastread" = yes; then
! 					dflt=y
! 				else
! 					dflt=n
! 				fi
! 				rp="File $ans doesn't exist.  Use that name anyway? [$dflt]"
! 				echo $n "$rp $c"
! 				. myread
! 				case "$ans" in
! 				y*) cont='';;
! 				esac
! 			fi
! 			;;
! 		*)
! 			echo "Please give the full pathname."
! 			;;
! 		esac
! 	done
! else
! 	d_pgp="$undef"
! fi
! 
! : ask about remailer support
! if $test "$d_remailer" = "$define"; then
! 	dflt='y'
! else
! 	dflt='n'
! fi
! echo ''
! echo 'Warning: REMAILER code does not work.'
! echo ''
! rp="Should support for anonymous remailers be included? [$dflt]"
! echo $n "$rp $c"
! . myread
! if $test "$ans" = "y"; then
! 	d_remailer="$define"
! 	dflt=$finger
! 	cont=true
! 	while $test "$cont"; do
! 		rp="Where is the finger binary located? [$dflt]"
! 		echo $n "$rp $c"	
! 		. myread
! 		finger_path=$ans
! 		if $test -f $ans; then
! 			cont=''
! 		else
! 			if $test "$fastread" = yes; then
! 				dflt=y
! 			else
! 				dflt=n
! 			fi
! 			rp="File $ans doesn't exist.  Use that name anyway? [$dflt]"
! 			echo $n "$rp $c"
! 			. myread
! 			case "$ans" in
! 			y*) cont='';;
! 			esac;
! 		fi
! 	done
! else
! 	d_remailer="$undef"
  fi
  
  : see if mkdir exists
***************
*** 4348,4354 ****
  
  : ask the preferred pager for this system.
  case "$pager" in
! '') dflt="builtin+";;
  *)  dflt="$pager";;
  esac
  
--- 4701,4707 ----
  
  : ask the preferred pager for this system.
  case "$pager" in
! '') dflt="builtin++";;
  *)  dflt="$pager";;
  esac
  
***************
*** 4367,4372 ****
--- 4720,4728 ----
      builtin+)
          cont=''
  	;;
+     builtin++)
+         cont=''
+         ;;
      /*)
  	if $test -f "$ans"; then
  	    cont=''
***************
*** 4476,4481 ****
--- 4832,4840 ----
      if $test "$ans" = x; then
          ans=`loc Slibtermlib.a x $libpth`
      fi
+     if $test "$ans" = x; then
+         ans=`loc libtermlib.so x $libpth`
+     fi
      case "$ans" in
      /usr/lib*|/usr/ccs/lib*|/lib*)
  	termlib='-ltermlib'
***************
*** 4492,4497 ****
--- 4851,4859 ----
  	if $test "$ans" = x; then
  	    ans=`loc Slibcurses.a x $libpth`
  	fi
+ 	if $test "$ans" = x; then
+ 	    ans=`loc libcurses.so x $libpth`
+ 	fi
  	case "$ans" in
  	/*)
  	    ar t $ans >grimble
***************
*** 4718,4723 ****
--- 5080,5086 ----
  d_rename='$d_rename'
  d_symlink='$d_symlink'
  d_whoami='$d_whoami'
+ d_poll='$d_poll'
  n='$n'
  c='$c'
  orderlib='$orderlib'
***************
*** 4789,4794 ****
--- 5152,5158 ----
  compress='$compress'
  execmail='$execmail'
  libswanted='$libswanted'
+ noaddlib='$noaddlib'
  c_date='$c_date'
  d_ascii='$d_ascii'
  d_broke_ctype='$d_broke_ctype'
***************
*** 4806,4812 ****
  d_flock='$d_flock'
  d_dotlock='$d_dotlock'
  d_fcntlock='$d_fcntlock'
- lock_dir='$lock_dir'
  has_flock='$has_flock'
  has_fcntl='$has_fcntl'
  d_ftruncate='$d_ftruncate'
--- 5170,5175 ----
***************
*** 4828,4834 ****
--- 5191,5200 ----
  d_mallocvoid='$d_mallocvoid'
  d_mboxedit='$d_mboxedit'
  d_mime='$d_mime'
+ metamail_path='$metamail_path'
  defencoding='$defencoding'
+ d_8bitmime='$d_8bitmime'
+ d_binarymime='$d_binarymime'
  defcharset='$defcharset'
  defdispcharset='$defdispcharset'
  d_mmdf='$d_mmdf'
***************
*** 4935,4940 ****
--- 5301,5312 ----
  xenlf='$xenlf'
  d_xenix='$d_xenix'
  d_bsd='$d_bsd'
+ d_pgp='$d_pgp'
+ pgp='$pgp'
+ pgp_path='$pgp_path'
+ d_remailer='$d_remailer'
+ finger='$finger'
+ finger_path='$finger_path'
  CONFIG=true
  EOT
  
Index: WORK/MANIFEST
*** elm2.4.25/MANIFEST	Thu Mar 10 19:14:46 1994
--- WORK/MANIFEST	Tue Jun  4 22:24:26 1996
***************
*** 1,3 ****
--- 1,6 ----
+ README.ME+
+ ANNOUNCE.ME
+ ChangeLog.ME
  Changes
  Configure
  Instruct
***************
*** 31,36 ****
--- 34,40 ----
  doc/frm.1
  doc/listalias.1
  doc/messages.1
+ doc/mime.types
  doc/newalias.1
  doc/newmail.1
  doc/printmail.1
***************
*** 55,60 ****
--- 59,67 ----
  hdrs/headers.h
  hdrs/mcprt.h
  hdrs/mcprtlib.h
+ hdrs/me.h
+ hdrs/menu.h
+ hdrs/menu2.h
  hdrs/mime.h
  hdrs/msgcat.h
  hdrs/ndbz.h
***************
*** 84,89 ****
--- 91,98 ----
  lib/can_open.c
  lib/chloc.c
  lib/date_util.c
+ lib/dispaddr.c
+ lib/dynarray.c
  lib/errno.c
  lib/expand.c
  lib/figadrssee.c
***************
*** 92,97 ****
--- 101,107 ----
  lib/getaddrfrm.c
  lib/getarpdate.c
  lib/getfullnam.c
+ lib/getrealname.c
  lib/getword.c
  lib/header_cmp.c
  lib/in_list.c
***************
*** 124,133 ****
--- 134,145 ----
  lib/strftime.c
  lib/strincmp.c
  lib/striparens.c
+ lib/strmcpy.c
  lib/strstr.c
  lib/strtokq.c
  lib/tail_of.c
  lib/validname.c
+ lib/safeopen.c
  nls/C/C/C/s_aliases.m
  nls/C/C/C/s_answer.m
  nls/C/C/C/s_elm.m
***************
*** 159,166 ****
  src/alias.c
  src/aliaslib.c
  src/args.c
  src/bouncebk.c
! src/builtin.c
  src/calendar.c
  src/curses.c
  src/date.c
--- 171,179 ----
  src/alias.c
  src/aliaslib.c
  src/args.c
+ src/attach_menu.c
  src/bouncebk.c
! src/builtin++.c
  src/calendar.c
  src/curses.c
  src/date.c
***************
*** 185,200 ****
--- 198,222 ----
  src/lock.c
  src/mailmsg1.c
  src/mailmsg2.c
+ src/menu.c
+ src/menu2.c
+ src/metapager.c
  src/mime.c
+ src/mime_decode.c
+ src/mime_encode.c
+ src/mime_parse.c
+ src/parse_util.c
  src/mkhdrs.c
  src/newmbox.c
  src/options.c
  src/out_utils.c
  src/pattern.c
+ src/pgp.c
  src/pmalloc.c
  src/quit.c
  src/read_rc.c
  src/remail.c
+ src/remailer.c
  src/reply.c
  src/returnadd.c
  src/save_opts.c
***************
*** 205,210 ****
--- 227,233 ----
  src/signals.c
  src/softkeys.c
  src/sort.c
+ src/state.c
  src/string2.c
  src/strings.c
  src/syscall.c
Index: WORK/Makefile.SH
*** elm2.4.25/Makefile.SH	Wed Apr 21 04:53:22 1993
--- WORK/Makefile.SH	Sun Jun 16 21:39:52 1996
***************
*** 65,77 ****
  default_target:	all
  
  #	Targets that are simply executed in each subordinate makefile as is
! all install uninstall lint clean:
  		cd lib; $(MAKE) $(MJ) -$(MAKEFLAGS) $@
  		cd src; $(MAKE) $(MJ) -$(MAKEFLAGS) $@
  		cd utils; $(MAKE) $(MJ) -$(MAKEFLAGS) $@
! 		cd filter; $(MAKE) $(MJ) -$(MAKEFLAGS) $@
  		cd doc; $(MAKE) $(MJ) -$(MAKEFLAGS) $@
  
  #	Targets that apply to all elm at once
  listing:
  		@$(ECHO) "Making source listing in file LISTING."
--- 65,91 ----
  default_target:	all
  
  #	Targets that are simply executed in each subordinate makefile as is
! all install uninstall lint clean: config.h config.sh Makefile
  		cd lib; $(MAKE) $(MJ) -$(MAKEFLAGS) $@
  		cd src; $(MAKE) $(MJ) -$(MAKEFLAGS) $@
  		cd utils; $(MAKE) $(MJ) -$(MAKEFLAGS) $@
! 		# cd filter; $(MAKE) $(MJ) -$(MAKEFLAGS) $@
  		cd doc; $(MAKE) $(MJ) -$(MAKEFLAGS) $@
  
+ # Check that config.h is up of date
+ config.h: config.h.SH config.sh
+ 	@echo "You must run 'sh Configure -S' or 'sh Configure'"
+ 	exit 1
+ 
+ # Check that config.sh is up of data
+ config.sh: Configure	
+ 	@echo "You must run 'sh Configure'"
+ 	exit 1
+ 
+ Makefile: Makefile.SH config.sh
+ 	@echo "You must run 'sh Configure -S' or 'sh Configure'"
+ 	exit 1
+ 
  #	Targets that apply to all elm at once
  listing:
  		@$(ECHO) "Making source listing in file LISTING."
***************
*** 86,92 ****
  		  $(SLEEP) 10;)
  		cd lib; $(MAKE) $(MJ) -$(MAKEFLAGS) REMOTE=$(REMOTE) $@
  		cd src; $(MAKE) $(MJ) -$(MAKEFLAGS) REMOTE=$(REMOTE) $@
! 		cd filter; $(MAKE) $(MJ) -$(MAKEFLAGS) REMOTE=$(REMOTE) $@
  		cd utils; $(MAKE) $(MJ) -$(MAKEFLAGS) REMOTE=$(REMOTE) $@
  		cd doc; $(MAKE) $(MJ) -$(MAKEFLAGS) REMOTE=$(REMOTE) $@
  
--- 100,106 ----
  		  $(SLEEP) 10;)
  		cd lib; $(MAKE) $(MJ) -$(MAKEFLAGS) REMOTE=$(REMOTE) $@
  		cd src; $(MAKE) $(MJ) -$(MAKEFLAGS) REMOTE=$(REMOTE) $@
! 		# cd filter; $(MAKE) $(MJ) -$(MAKEFLAGS) REMOTE=$(REMOTE) $@
  		cd utils; $(MAKE) $(MJ) -$(MAKEFLAGS) REMOTE=$(REMOTE) $@
  		cd doc; $(MAKE) $(MJ) -$(MAKEFLAGS) REMOTE=$(REMOTE) $@
  
***************
*** 120,126 ****
  filter: _filter
  
  _filter:
! 	cd filter; $(MAKE) $(MJ) -$(MAKEFLAGS) all
  
  #	The dummy dependency here prevents make from thinking the target is the
  #	utils directory that sits in the current directory, rather than
--- 134,140 ----
  filter: _filter
  
  _filter:
! 	# cd filter; $(MAKE) $(MJ) -$(MAKEFLAGS) all
  
  #	The dummy dependency here prevents make from thinking the target is the
  #	utils directory that sits in the current directory, rather than
Index: WORK/config.h.SH
*** elm2.4.25/config.h.SH	Mon May 30 19:55:57 1994
--- WORK/config.h.SH	Sun Jun 16 21:29:43 1996
***************
*** 82,87 ****
--- 82,93 ----
   */
  #$d_whoami	WHOAMI		/**/
  
+ /* POLL:
+  *	This symbol, if defined, indicates that the program may include
+  *	poll.h.
+  */
+ #$d_poll	POLL		/**/
+ 
  /* PREFSHELL:
   *	This symbol contains the full name of the preferred user shell on this
   *	system.  Usual values are /bin/csh, /bin/ksh, /bin/sh.
***************
*** 185,194 ****
  /* USE_FCNTL_LOCKING
   *	This symbol, if defined, indicates that SYSV style fcntl file locking should be used.
   */
- /* LOCK_DIR
-  *	This symbol is the name of the lock directory for access (not mailbox) locks.
-  *	It will be /usr/spool/locks or /usr/spool/uucp
-  */
  #$d_flock	USE_FLOCK_LOCKING		/**/
  
  #$d_dotlock	USE_DOTLOCK_LOCKING		/**/
--- 191,196 ----
***************
*** 195,202 ****
  
  #$d_fcntlock	USE_FCNTL_LOCKING	/**/
  
- #define		LOCK_DIR	"$lock_dir"	/**/
- 
  /* FTRUNCATE:
   *	This symbol, if defined, indicates that the ftruncate() routine exists.
   */
--- 197,202 ----
***************
*** 292,297 ****
--- 292,333 ----
   */
  #$d_mime	MIME	/**/
  
+ /* MIME:
+  *	This symbol defines default path to metamail.
+  *          Special values:    none         Don't call metamail
+  *                             metamail     Call metamail if environment
+  *                                          variable NOMETAMAIL is not defined
+  */                     
+ #define METAMAIL_PATH    "$metamail_path"
+ 
+ /* USE_8BITMIME
+  *     Mailer accepts -B8BITMIME option
+  *     -B == BODYTYPE
+  */
+ #$d_8bitmime     USE_8BITMIME      /**/
+ 
+ /* USE_BINARYMIME
+  *     Mailer accepts -BBINARYMIME option
+  *     -B == BODYTYPE
+  *
+  * Elm don't yet fully support BINARYMIME: it requires that lines are
+  * terminated with \r\n, Unix's \n isn't sufficient!
+  * That is only partially implemented in this version of Elm.
+  *
+  * Quote from RFC 1830 (Experimental Protocol): 
+  *  SMTP Service Extensions for Transmission of Large and Binary MIME Messages
+  *
+  *      It is important to note that when using BINARYMIME, it is
+  *      especially important to ensure that the MIME message itself is
+  *      properly formed.  In particular, it is essential that text be
+  *      canonically encoded with each line properly terminated with <CR>
+  *      <LF>.  Any transformation of text into non-canonical MIME to
+  *      observe local storage conventions must be reversed before sending
+  *      as BINARYMIME.  The usual line-oriented shortcuts will break if
+  *      used with BINARYMIME.
+  */
+ #$d_binarymime     USE_BINARYMIME      /**/
+ 
  /* MMDF:
   *	This symbol, if defined, indicates that mailboxes are in
   *	the MMDF format.
***************
*** 602,605 ****
--- 638,663 ----
  #$d_xenix	XENIX	/**/
  #$d_bsd	BSD	/**/
  
+ /* USE_PGP:
+  *	This symbol, if defined, means that PGP support should be compiled in.
+  */
+ /* PGP_PATH:
+  *	The path to the PGP binary.
+  */
+ #$d_pgp USE_PGP /**/
+ #ifdef USE_PGP
+ #define PGP_PATH "$pgp_path"
+ #endif
+ 
+ /* USE_REMAILER:
+  *	If defined, includes support for anonymous remailing, chaining, and
+  *      if USE_PGP is defined, encryption.
+  *
+  * FINGER_PATH:
+  *      Path to the finger binary.
+  */
+ #$d_remailer USE_REMAILER /**/
+ #ifdef USE_REMAILER
+ #define FINGER_PATH "$finger_path"
+ #endif
  !GROK!THIS!
Index: WORK/doc/Makefile.SH
*** elm2.4.25/doc/Makefile.SH	Thu Mar 10 19:20:29 1994
--- WORK/doc/Makefile.SH	Mon Jun  3 20:15:47 1996
***************
*** 114,120 ****
  			$(MAN)/elm$(MANEXT)		\
  			$(MAN)/elmalias$(MANEXT)	\
  			$(MAN)/fastmail$(MANEXT)	\
- 			$(MAN)/filter$(MANEXT)		\
  			$(MAN)/frm$(MANEXT)		\
  			$(MAN)/listalias$(MANEXT)	\
  			$(MAN)/messages$(MANEXT)	\
--- 114,119 ----
***************
*** 123,128 ****
--- 122,129 ----
  			$(MAN)/printmail$(MANEXT)	\
  			$(MAN)/readmsg$(MANEXT)
  
+ #			$(MAN)/filter$(MANEXT)		
+ 
  # List of installed catman pages (except for wnemail.1 - handled differently)
  CATMAN_LIST	=	$(CATMAN)/answer$(CATMANEXT)$(SUFFIX)	\
  			$(CATMAN)/checkalias$(CATMANEXT)$(SUFFIX)\
***************
*** 129,135 ****
  			$(CATMAN)/elm$(CATMANEXT)$(SUFFIX)	\
  			$(CATMAN)/elmalias$(CATMANEXT)$(SUFFIX)\
  			$(CATMAN)/fastmail$(CATMANEXT)$(SUFFIX)	\
- 			$(CATMAN)/filter$(CATMANEXT)$(SUFFIX)	\
  			$(CATMAN)/frm$(CATMANEXT)$(SUFFIX)	\
  			$(CATMAN)/listalias$(CATMANEXT)$(SUFFIX)	\
  			$(CATMAN)/messages$(CATMANEXT)$(SUFFIX)	\
--- 130,135 ----
***************
*** 138,143 ****
--- 138,145 ----
  			$(CATMAN)/printmail$(CATMANEXT)$(SUFFIX)	\
  			$(CATMAN)/readmsg$(CATMANEXT)$(SUFFIX)
  
+ #			$(CATMAN)/filter$(CATMANEXT)$(SUFFIX)
+ 
  # List of formatted pages for catman
  FORMATTED_PAGES_LIST =	catman/answer$(CATMANEXT)$(SUFFIX)	\
  			catman/checkalias$(CATMANEXT)$(SUFFIX)\
***************
*** 144,150 ****
  			catman/elm$(CATMANEXT)$(SUFFIX)	\
  			catman/elmalias$(CATMANEXT)$(SUFFIX)\
  			catman/fastmail$(CATMANEXT)$(SUFFIX)	\
- 			catman/filter$(CATMANEXT)$(SUFFIX)	\
  			catman/frm$(CATMANEXT)$(SUFFIX)	\
  			catman/listalias$(CATMANEXT)$(SUFFIX)	\
  			catman/messages$(CATMANEXT)$(SUFFIX)	\
--- 146,151 ----
***************
*** 153,158 ****
--- 154,161 ----
  			catman/printmail$(CATMANEXT)$(SUFFIX)	\
  			catman/readmsg$(CATMANEXT)$(SUFFIX)
  
+ #			catman/filter$(CATMANEXT)$(SUFFIX)	
+ 
  # List of remotely installed man pages (except for wnemail.1 - handled
  # differently)
  REMOTE_MAN_LIST	=	$(REMOTE)$(MAN)/answer$(MANEXT)	\
***************
*** 160,166 ****
  			$(REMOTE)$(MAN)/elm$(MANEXT)		\
  			$(REMOTE)$(MAN)/elmalias$(MANEXT)	\
  			$(REMOTE)$(MAN)/fastmail$(MANEXT)	\
- 			$(REMOTE)$(MAN)/filter$(MANEXT)	\
  			$(REMOTE)$(MAN)/frm$(MANEXT)		\
  			$(REMOTE)$(MAN)/listalias$(MANEXT)	\
  			$(REMOTE)$(MAN)/messages$(MANEXT)	\
--- 163,168 ----
***************
*** 169,174 ****
--- 171,178 ----
  			$(REMOTE)$(MAN)/printmail$(MANEXT)	\
  			$(REMOTE)$(MAN)/readmsg$(MANEXT)
  
+ #			$(REMOTE)$(MAN)/filter$(MANEXT)	
+ 
  # List of files installed in LIB directory
  LIB_LIST	=	$(LIB)/elm-help.0	\
  			$(LIB)/elm-help.1	\
***************
*** 187,196 ****
  FORMATTED_LIST	=	Alias.fmtd	\
  			Config.fmtd 	\
  			Cover.fmtd	\
- 			Filter.fmtd	\
  			Form.fmtd	\
  			Ref.fmtd	\
  			Users.fmtd
  
  # Targets
  all: 
--- 191,201 ----
  FORMATTED_LIST	=	Alias.fmtd	\
  			Config.fmtd 	\
  			Cover.fmtd	\
  			Form.fmtd	\
  			Ref.fmtd	\
  			Users.fmtd
+ 
+ #			Filter.fmtd	
  
  # Targets
  all: 
Index: WORK/doc/elm-help.0
*** elm2.4.25/doc/elm-help.0	Mon Apr 12 06:13:09 1993
--- WORK/doc/elm-help.0	Tue Jun 11 11:57:51 1996
***************
*** 1,5 ****
  
!         Command                      Elm 2.4 Action
  
            <RETURN>,<SPACE>      Display current message
             |                    Pipe current message or tagged messages to
--- 1,5 ----
  
!         Command                      Elm 2.4ME+ Action
  
            <RETURN>,<SPACE>      Display current message
             |                    Pipe current message or tagged messages to
***************
*** 24,35 ****
--- 24,38 ----
             c                    Change to another folder
             d                    Delete current message
            ^D                    Delete messages with a specified pattern
+           ^E                    Extract PGP public keys from current message
             e                    Edit current folder
             f                    Forward current message
+           ^F                    Forget PGP passphrase
             g                    Group (all recipients) reply to current message
             h                    Headers displayed with message
             J                    Increment current message by one
             j, <DOWN>            Advance to next undeleted message
+           ^K                    Mail PGP public key(s)
             K                    Decrement current message by one
             k, <UP>              Advance to previous undeleted message
             l                    Limit messages by specified criteria
***************
*** 50,55 ****
--- 53,59 ----
            ^T                    Tag messages with a specified pattern
             u                    Undelete current message
            ^U                    Undelete messages with a specified pattern
+            v                    View attachments in current message.
             x, ^Q                Exit leaving folder untouched, ask permission
                                          if folder changed
             X                    Exit leaving folder untouched, unconditionally
Index: WORK/doc/elm-help.3
*** elm2.4.25/doc/elm-help.3	Mon Apr 12 06:13:10 1993
--- WORK/doc/elm-help.3	Mon Jun  3 20:16:05 1996
***************
*** 1,5 ****
  
!         Command                      Elm 2.4 Action
  
  
            <RETURN>              Display the current message,
--- 1,5 ----
  
!         Command                      Elm 2.4ME+ Action
  
  
            <RETURN>              Display the current message,
***************
*** 38,43 ****
--- 38,44 ----
             t                    Tag current message for further operations
             T                    Tag current message and go to next message
             u                    Undelete current message
+ 	   v			View attachments in current message.
             x                    Exit leaving folder untouched, ask permission
                                          if folder changed
             X                    Exit leaving folder untouched, unconditionally
Index: WORK/doc/elm.1
*** elm2.4.25/doc/elm.1	Fri Dec 25 01:46:52 1992
--- WORK/doc/elm.1	Sat Aug 10 20:58:26 1996
***************
*** 93,102 ****
--- 93,106 ----
  Synonymous with the "-h" option.
  .TP
  .B "  -k"
+ Ignored.
+ 
  Keypad - force knowledge of HP terminal keyboard, to allow
  the use of the NEXT, PREV and HOME/SHIFT-HOME keys.
  .TP
  .B "  -K"
+ Ignored.
+ 
  Keypad + softkeys - enable use of softkeys on HP terminals only.
  .TP
  .B "  -m"
Index: WORK/doc/elmrc-info
*** elm2.4.25/doc/elmrc-info	Fri Mar 11 23:19:26 1994
--- WORK/doc/elmrc-info	Sat Aug 10 22:59:53 1996
***************
*** 22,27 ****
--- 22,30 ----
  maildir
  # where to save my mail to, default directory is "Mail"
  
+ mailpermissions
+ # permissions to be given to newly-created saved mail files, default rw-------
+   
  tmpdir
  # where to place temporary files, default directory is "/tmp"
  
***************
*** 88,95 ****
--- 91,152 ----
  weed
  # enable the weedout list to be read?
  
+ metamail
+ # This tells path of metamail program
+ #
+ # That version (Elm 2.4ME+) does not use Metamail's companion programs 
+ # (suchs as mmencode) directly, but metamail package supposes that
+ # companion programs are installed to search path.
+ #
+ # Special values:   none		Don't call metamail
+ #		    metamail		Don't call metamail if environment
+ #						variable $NOMETAMAIL is defined
+ 
+ noencoding
+ # This control makes it possible to send raw 8bit or binary data when the MTA
+ # doesn't support 8BITMIME and the -B8BITMIME option or
+ # BINARYMIME and the -BBINARYMIME option
+ #
+ # Possible values:
+ #    0 : Always convert 8BIT and BINARY data to QUOTED-PRINTABLE if the MTA
+ #        doesn't support the -B8BITMIME and -BBINARYMIME options.
+ #    1 : Allow 8bit without -B8BITMIME, but binary data is encoded
+ #    2+: Allow binary without -BBINARYMIME and and 8bit without -B8BITMIME
+ #
+ # It is STRONGLY recommended that it be left set to 0 unless you know what
+ # you are doing!!
+ #
+ # Elm doesn't yet fully support BINARYMIME: it requires that text lines are
+ # terminated with \r\n, Unix's \n isn't sufficient!
+ # That is only partially implemented in this version of Elm.
+ #
+ # Quote from RFC 1830 (Experimental Protocol): 
+ #  SMTP Service Extensions for Transmission of Large and Binary MIME Messages
+ #
+ #      It is important to note that when using BINARYMIME, it is
+ #      especially important to ensure that the MIME message itself is
+ #      properly formed.  In particular, it is essential that text be
+ #      canonically encoded with each line properly terminated with <CR>
+ #      <LF>.  Any transformation of text into non-canonical MIME to
+ #      observe local storage conventions must be reversed before sending
+ #      as BINARYMIME.  The usual line-oriented shortcuts will break if
+ #      used with BINARYMIME.
+ 
+ nohdrencoding
+ # Don't do MIME part 2 (RFC 1522) encoding for 8-bit headers?
+ # Because 8-bit data is not allowed in headers, 
+ # it is STRONGLY recommended that this is left set to OFF
+ 
  noheader
  # when messages are copied into the outbound buffer, don't include headers?
+ # when replying
+ 
+ noheaderfwd
+ # when messages are copied into the outbound buffer, don't include headers?
+ # when forwarding 	
+ # (Notice that messages are not copiend to outbound buffer when
+ #  mimeworward = ON)
+ 
  
  titles
  # display message title when displaying pages of message?
***************
*** 197,203 ****
  
  displaycharset
  # name of Character Set which the display supports. This is independent
! # of the above "charset".
  
  compatcharsets
  # list of Character Sets, which are more or less a superset of US-ASCII
--- 254,261 ----
  
  displaycharset
  # name of Character Set which the display supports. This is independent
! # of the above "charset". This is also copied to environment variable 
! # MM_CHARSET when metamail is called.
  
  compatcharsets
  # list of Character Sets, which are more or less a superset of US-ASCII
***************
*** 247,250 ****
  textencoding
  # Type of encoding to be put into the MIME Content-Transfer-Encoding header.
  # Usual values are 7bit or 8bit.
! # NOTE: Elm will not encode your message based on this variable.
--- 305,355 ----
  textencoding
  # Type of encoding to be put into the MIME Content-Transfer-Encoding header.
  # Usual values are 7bit or 8bit.
! #
! # -- NOT Used in this version of elm (2.4 PL24 ME7) or ELM 2.4ME+ PLxx (25)
! # Now elm analyzes mail when sending and does that encoding of quoted-printable
! # when necessary.
! 
! showpgppreamble
! # if this variable is ON, display text before PGP armor.
! 
! showto
! # if this variable is ON, Elm will show who the message is to rather than
! # who it is from in the headers display.
! 
! usepgppass
! # If ON, Elm will prompt you for your PGP passphrase and use it whenever
! # necessary to make it more convenient to hand PGP messages.
! 
! keeppassfor
! # The number of seconds Elm should remember your passphrase.  -1 means never
! # expire it.
! 
! askpgpsig
! # If ON, Elm will prompt you for a username with which to sign the pgp
! # message
! 
! pagemultipart
! # Should Elm use "pager" to display MIME multipart messages
! # with unknown subparts or with unknown subtype?
! 
! mimeforward
! # This option controls how Elm will forward messages when MIME is defined.
! #	ON: Causes Elm to send the message as a MIME attachment of type
! #		MESSAGE/RFC822.  Highly recommended when forwarding MIME
! #		messages so that the receiver can correctly view the message!
! #	OFF: Elm will include the forwarded message in your editor instead
! #		of making it an attachment.
! 
! quoteforward
! # Forwarded messages are quoted like replies, rather than included
! # with "Forwarded message" and "End of forwarded message" banners 
! # above and below. This don't have effect if "mimeforward" is TRUE.
! 
! require-mime-version-for-hdr-encoding
! # If set MIME Part 2 (RFC 1522) decoding is only done when MIME-version
! # header is present. Default: False
! 
! require-mime-version-for-body-encoding
! # If set MIME Part 1 (RFC 1521) decoding is only done when MIME-version
! # header is present. Default: True
Index: WORK/doc/mime.types
*** /tmp/null.14101	Tue Aug 20 22:05:34 1996
--- WORK/doc/mime.types	Mon Jun  3 20:16:07 1996
***************
*** 0 ****
--- 1,27 ----
+ # mime.types for Elm 2.4PL24 ME8 (or greater)
+ #
+ # Format of this file:
+ # <suffix> <content-type>
+ #
+ # Elm already has the following "builtin" definitions:
+ # ps	application/postscript
+ # gif	image/gif
+ # tiff	image/tiff
+ # jpeg	image/jpeg
+ #
+ # NOTE: data which is declared "application/octet-stream" will automatically
+ # have the "name=<default_filename>" option added to it, so you should not
+ # put it in your definitions.
+ 
+ gz	application/octet-stream
+ pbm	image/pbm
+ pgm	image/pgm
+ ppm	image/ppm
+ taz	application/octet-stream; type=tar; conversions=x-compress
+ tgz	application/octet-stream; type=tar; conversions=x-gzip
+ tar	application/octet-stream; type=tar
+ Z	application/octet-stream
+ zip	application/octet-stream; type=zip
+ 
+ # PGP users might want the following
+ pgp	application/pgp
Index: WORK/filter/Makefile.SH
*** elm2.4.25/filter/Makefile.SH	Sun Jun  6 20:35:08 1993
--- WORK/filter/Makefile.SH	Mon Jun  3 20:16:09 1996
***************
*** 86,92 ****
  #	Other variables
  BIN		=	../bin
  INCLDIR		=	../hdrs
! CFLAGS		=	$(CCFLAGS) $(OPTIMIZE) -I$(INCLDIR) $(DEBUG) $(DACSNET) 
  LINTFLAGS	=	-I$(INCLDIR)
  SHELL		=	/bin/sh
  
--- 86,92 ----
  #	Other variables
  BIN		=	../bin
  INCLDIR		=	../hdrs
! CFLAGS		=	-I$(INCLDIR) $(CCFLAGS) $(OPTIMIZE) $(DEBUG) $(DACSNET) 
  LINTFLAGS	=	-I$(INCLDIR)
  SHELL		=	/bin/sh
  
Index: WORK/filter/filter.c
*** elm2.4.25/filter/filter.c	Mon May 30 19:31:55 1994
--- WORK/filter/filter.c	Mon Jun  3 20:16:10 1996
***************
*** 232,238 ****
  
  	sprintf(filename, "%s.%d", filter_temp, getpid());
  
! 	if ((fd = fopen(filename,"w")) == NULL)
  	  {
  		sprintf(buffer,
  			catgets(elm_msg_cat,FilterSet,
--- 232,238 ----
  
  	sprintf(filename, "%s.%d", filter_temp, getpid());
  
! 	if ((fd = safeopen(filename)) == NULL)
  	  {
  		sprintf(buffer,
  			catgets(elm_msg_cat,FilterSet,
Index: WORK/hdrs/defs.h
*** elm2.4.25/hdrs/defs.h	Mon Dec  4 17:50:56 1995
--- WORK/hdrs/defs.h	Tue Aug 13 15:14:19 1996
***************
*** 194,203 ****
  #include "sysdefs.h"	/* system/configurable defines */
  
  
! # define VERSION	"2.4"				/* Version number... */
! # define VERS_DATE	"November 11, 1995"		/* for elm -v option */
  # define WHAT_STRING	\
! 	"@(#) Version 2.4, USENET supported version, released November 11, 1995"
  
  #if defined(__STDC__) || defined(_AIX)
  # define ANSI_C 1
--- 194,203 ----
  #include "sysdefs.h"	/* system/configurable defines */
  
  
! # define VERSION	"2.4ME+"		/* Version number... */
! # define VERS_DATE	"Aug, 1996"	/* for elm -v option */
  # define WHAT_STRING	\
! 	"@(#) Version 2.4(ME+), USENET supported version, released Aug, 1996"
  
  #if defined(__STDC__) || defined(_AIX)
  # define ANSI_C 1
***************
*** 231,238 ****
--- 231,254 ----
  #define TILDE_ESCAPE	'~'		/* escape character~    */
  #define ESCAPE		'\033'		/* the escape		*/
  
+ 
  #define NO_OP_COMMAND	'\0'		/* no-op for timeouts   */
  
+ #define READCH_MASK      0x0FFF         /* Mask flags off        */
+ #define READCH_CURSOR    0x1000         /* Return cursor keys    */      
+ #define READCH_NOCURSOR  0x2000         /* Disable cursor keys   */      
+ 
+ #define REDRAW_MARK    257              /* Artificial "char" for  redrawing */
+ #define UP_MARK        258              /* Artificial UP key    */
+ #define LEFT_MARK      259              /* Artificial LEFT key  */
+ #define RIGHT_MARK     260              /* Artificial RIGHT key */
+ #define DOWN_MARK      261              /* Artificial DOWN key  */
+ #define PAGEUP_MARK    262              /* Artificial PAGE UP key */
+ #define PAGEDOWN_MARK  263              /* Artificial PAGE DOWN key */
+ #define HELP_MARK      264              /* Artificial HELP key      */
+ #define HOME_MARK      265              /* Artificial HOME key      */
+ #define FIND_MARK      266              /* Artificial FIND key      */
+ 
  #define STANDARD_INPUT  0		/* file number of stdin */
  
  #ifndef TRUE
***************
*** 263,268 ****
--- 279,285 ----
  #define SY_ENAB_SIGHUP	(1<<2)		/* pgm to exec can handle signals    */
  #define SY_ENAB_SIGINT	(1<<3)		/*  ...and it can handle SIGINT too  */
  #define SY_DUMPSTATE	(1<<4)		/* create folder state dump file     */
+ #define SY_ENV_METAMAIL	(1<<5)		/* put MM_CHARSET to environ         */
  
  /* options to the copy_message() procedure */
  #define CM_REMOVE_HEADER	(1<<0)	/* skip header of message */
***************
*** 270,282 ****
  #define CM_UPDATE_STATUS	(1<<2)	/* Update Status: Header  */
  #define CM_MMDF_HEAD		(1<<3)	/* strip mmdf message seperator */
  #define CM_REMAIL		(1<<4)	/* Add Sender: and Orig-To: headers */
! #define CM_DECODE		(1<<5)	/* prompt for key if message is encrypted */
  
! #define EXECUTE_ACCESS	1		/* These five are 	   */
! #define WRITE_ACCESS	2		/*    for the calls	   */
! #define READ_ACCESS	4		/*       to access()       */
! #define ACCESS_EXISTS	0		/*           <etc>         */
! #define EDIT_ACCESS	6		/*  (this is r+w access)   */
  
  #define BIG_NUM		999999		/* big number!             */
  #define BIGGER_NUM	9999999 	/* bigger number!          */
--- 287,310 ----
  #define CM_UPDATE_STATUS	(1<<2)	/* Update Status: Header  */
  #define CM_MMDF_HEAD		(1<<3)	/* strip mmdf message seperator */
  #define CM_REMAIL		(1<<4)	/* Add Sender: and Orig-To: headers */
! #define CM_DECODE		(1<<5)	/* Decode MIME, PGP and elm */
! #define CM_FILT_HDR		(1<<6)  /* Filter headers (for forwarding) */
! #define CM_DISPLAYING		(1<<7)  /* Pass to MIME code */
! #define CM_REMOVE_ENVELOPE	(1<<8)	/* Remove envelope */
! 
! /* Options for mail() procedure */
! #define MAIL_COPY_MSG          (1<<0)
! #define MAIL_EDIT_MSG          (1<<1)
! #define MAIL_ISFORM            (1<<2)
! #define MAIL_REPLYING          (1<<3)
! #define MAIL_FORWARDING        (1<<4)
! 
! /* options to the optionally_enter() function */
! #define OE_APPEND_CURRENT      (1<<0) 
! #define OE_PASSWD              (1<<1)
! #define OE_REDRAW_MARK         (1<<2)
  
! /* xxx_ACCESS moved to down after including of unistd.h */
  
  #define BIG_NUM		999999		/* big number!             */
  #define BIGGER_NUM	9999999 	/* bigger number!          */
***************
*** 309,330 ****
  
  /** some defines for the "status" field of the header and alias record **/
  
! #define ACTION		1		/* bit masks, of course */
! #define CONFIDENTIAL	2
! #define DELETED		4
! #define EXPIRED		8
! #define FORM_LETTER	16
! #define NEW		32
! #define PRIVATE		64
! #define TAGGED		128
! #define URGENT		256
! #define VISIBLE		512
! #define UNREAD		1024
! #define STATUS_CHANGED	2048
! #define MIME_MESSAGE	4096	/* indicates existence of MIME Header */
! #define MIME_NEEDDECOD	8192	/* indicates that we need to call mmdecode */
! #define	MIME_NOTPLAIN	16384	/* indicates that we have a content-type,
! 				   for which we need metamail anyway. */
  
  /** some defines for the "type" field of the alias record **/
  
--- 337,365 ----
  
  /** some defines for the "status" field of the header and alias record **/
  
! #define ACTION               1          /* bit masks, of course */
! #define CONFIDENTIAL         2
! #define DELETED              4
! #define EXPIRED              8
! #define FORM_LETTER         16
! #define NEW                 32
! #define PRIVATE             64
! #define TAGGED             128
! #define URGENT             256
! #define VISIBLE            512
! #define UNREAD            1024
! #define REPLIED           2048
! #define MIME_MESSAGE      4096  /* indicates existence of MIME Header */
! #define PRE_MIME_CONTENT  8192
! #define MIME_UNSUPPORTED 16384
! #define NOHDRENCODING    32768
! /* Don't add values bigger than 2^15 == 32768 */
! 
! #ifdef USE_PGP
! #define PGP_MESSAGE		1
! #define PGP_SIGNED_MESSAGE	2
! #define PGP_PUBLIC_KEY		4
! #endif
  
  /** some defines for the "type" field of the alias record **/
  
***************
*** 420,431 ****
  #define prev_tab(a)	(((((a-1)/tabspacing))*tabspacing)+1)
  #define next_tab(a)	(((((a-1)/tabspacing)+1)*tabspacing)+1)
  
- #define movement_command(c)	(c == 'j' || c == 'k' || c == ' ' || 	      \
- 				 c == BACKSPACE || c == ESCAPE || c == '*' || \
- 				 c == '-' || c == '+' || c == '=' ||          \
- 				 c == '#' || c == '@' || c == 'x' || 	      \
- 				 c == 'a' || c == 'q')
- 
  #define no_ret(s)	{ register int xyz; /* varname is for lint */	      \
  		          for (xyz=strlen(s)-1; xyz >= 0 && 		      \
  				(s[xyz] == '\r' || s[xyz] == '\n'); )	      \
--- 455,460 ----
***************
*** 506,511 ****
--- 535,546 ----
  #define PMALLOC_THRESHOLD	256	/* if greater, then just use malloc */
  #define PMALLOC_BUFFER_SIZE    2048	/* internal [memory] buffer size... */
  
+ /* Flags for  classify_header in parse_util.c */
+ 
+ #define HDR_TEXT       1
+ #define HDR_STRUCTURED 2
+ #define HDR_PHRASE     4
+ 
  /** the following macro is as suggested by Larry McVoy.  Thanks! **/
  
  # ifdef DEBUG
***************
*** 521,526 ****
--- 556,591 ----
  
  /* some random structs... */
  
+ #ifdef MIME
+ typedef struct mimeinfo {
+   unsigned int type : 3;        /* see mime.h for MIME_TYPE_* */
+   unsigned int disposition : 1; /* DISP_INLINE or DISP_ATTACH */
+   unsigned int unlink : 1;      /* used to mark that the file should be
+                                  * unlinked after sending the attachment */
+   unsigned int notplain : 1;
+ 
+   char subtype[WLEN];
+   char *type_opts;
+   char *disposition_opts;
+   char *description;
+ 
+   int encoding;      /* Notice: ENCODING_ILLEGAL == -1, ENCODING_* in mime.h */
+   long length;
+   long begin_offset; /* the beginning of the attachment (includes headers) */
+   long offset;       /* where the real data starts */
+   int flags;
+ 
+   struct mimeinfo *parts; /* If this is a multipart message, pointer
+                            * to the list of parts contained inside it */
+   
+   struct mimeinfo *next; /* pointer to the next attachment in the list */
+   
+   /* These next fields are only used when sending multipart messages. */
+   char *pathname;
+   struct mimeinfo *prev;
+ } mime_t;
+ #endif
+ 
  struct header_rec {
  	int  lines;		/** # of lines in the message	**/
  	int  status;		/** Urgent, Deleted, Expired?	**/
***************
*** 532,538 ****
  	long offset;		/** offset in bytes of message	**/
  	time_t received_time;	/** when elm received here	**/
  	char from[STRING];	/** who sent the message?	**/
! 	char to[STRING];	/** who it was sent to		**/
  	char messageid[STRING];	/** the Message-ID: value	**/
  	char time_zone[12];	/**                incl. tz	**/
  	time_t time_sent;	/** gmt when sent for sorting	**/
--- 597,604 ----
  	long offset;		/** offset in bytes of message	**/
  	time_t received_time;	/** when elm received here	**/
  	char from[STRING];	/** who sent the message?	**/
! 	char to[LONG_STRING];	/** who it was sent to		**/
!         char cc[LONG_STRING];
  	char messageid[STRING];	/** the Message-ID: value	**/
  	char time_zone[12];	/**                incl. tz	**/
  	time_t time_sent;	/** gmt when sent for sorting	**/
***************
*** 540,545 ****
--- 606,620 ----
  	time_t tz_offset;	/** offset to gmt of time sent	**/
  	char subject[STRING];   /** The subject of the mail	**/
  	char mailx_status[WLEN];/** mailx status flags (RO...)	**/
+ #ifdef MIME
+ 	mime_t mime_rec;        /** MIME information for this message **/
+ #endif
+ #ifdef USE_PGP
+ 	unsigned int pgp : 3;
+ #endif
+ 	unsigned int binary :1;  /* Binary message -- headers are terminated
+ 				  * with \r\n 
+ 				  */
         };
  
  #ifdef __alpha
***************
*** 621,645 ****
  #  endif
  #endif
  
! #ifndef ANSI_C   /* ANSI puts these in string.h */
  char *index(), *rindex(); /* names will be traslated by define in config.h */
  char *strtok(), *strcpy(), *strcat(), *strncpy(); /* more in string.h in ANSI */
  long lseek();
  int fseek();
- #if defined(__convexc__)
- unsigned sleep();
- #else
- unsigned long sleep();
  #endif
  #else
! #  ifdef I_UNISTD /* unistd.h available */
! #    include <unistd.h> /* ansi C puts sleep, lseek and fseek in unistd.h */
! #  else /* I_UNISTD */
! long lseek();
! int fseek();
! unsigned long sleep();
! #  endif /* I_UNISTD */
  #endif
  char *strtokq(); /* our own quote minding strtok */
  
  #ifndef STRSTR
--- 696,726 ----
  #  endif
  #endif
  
! #ifdef I_UNISTD
! #include <unistd.h>
! #else
! unsigned sleep();
  char *index(), *rindex(); /* names will be traslated by define in config.h */
  char *strtok(), *strcpy(), *strcat(), *strncpy(); /* more in string.h in ANSI */
  long lseek();
  int fseek();
  #endif
+ 
+ /* Defined in unistd.h ... */
+ #ifdef F_OK
+ #define EXECUTE_ACCESS  X_OK
+ #define WRITE_ACCESS    W_OK
+ #define READ_ACCESS     R_OK
+ #define ACCESS_EXISTS   F_OK
+ #define EDIT_ACCESS     (W_OK|R_OK)
  #else
! #define EXECUTE_ACCESS	1		/* These five are 	   */
! #define WRITE_ACCESS	2		/*    for the calls	   */
! #define READ_ACCESS	4		/*       to access()       */
! #define ACCESS_EXISTS	0		/*           <etc>         */
! #define EDIT_ACCESS	6		/*  (this is r+w access)   */
  #endif
+ 
  char *strtokq(); /* our own quote minding strtok */
  
  #ifndef STRSTR
***************
*** 666,672 ****
  
  #ifdef POSIX_SIGNALS
  #define signal posix_signal
! #if ANSI_C
  extern SIGHAND_TYPE (*posix_signal(int, SIGHAND_TYPE (*)(int)))(int);
  #else	/* ANSI_C */
  extern SIGHAND_TYPE (*posix_signal())();
--- 747,753 ----
  
  #ifdef POSIX_SIGNALS
  #define signal posix_signal
! #ifdef ANSI_C
  extern SIGHAND_TYPE (*posix_signal(int, SIGHAND_TYPE (*)(int)))(int);
  #else	/* ANSI_C */
  extern SIGHAND_TYPE (*posix_signal())();
***************
*** 746,751 ****
--- 827,836 ----
  char *pmalloc();
  char *header_cmp();
  char *safe_strdup();
+ 
+ FILE *safeopen();
+ FILE *safeopen_rdwr();
+ FILE *open_end_update();
  
  malloc_t safe_malloc();
  malloc_t safe_realloc();
Index: WORK/hdrs/elm.h
*** elm2.4.25/hdrs/elm.h	Thu Sep  1 22:42:40 1994
--- WORK/hdrs/elm.h	Tue Aug 13 15:15:25 1996
***************
*** 89,96 ****
  #include <errno.h>
  #include <signal.h>
  
! #include "../hdrs/curses.h"
! #include "../hdrs/defs.h"
  #include <setjmp.h>
  
  /******** static character string containing the version number  *******/
--- 89,96 ----
  #include <errno.h>
  #include <signal.h>
  
! #include "curses.h"
! #include "defs.h"
  #include <setjmp.h>
  
  /******** static character string containing the version number  *******/
***************
*** 122,130 ****
  #ifdef MIME
  char charset[SLEN] = {0};		/* name of character set */
  char display_charset[SLEN] = {0};	/* the charset, the display supports */
  char charset_compatlist[SLEN] = {0};	/* list of charsets which are a
  					   superset of us-ascii */
! char text_encoding[SLEN] = {0};	/* default encoding for text/plain */
  #endif
  char cur_folder[SLEN] = {0};	/* name of current folder */
  char cur_tempfolder[SLEN] = {0};/* name of temp folder open for a mailbox */
--- 122,140 ----
  #ifdef MIME
  char charset[SLEN] = {0};		/* name of character set */
  char display_charset[SLEN] = {0};	/* the charset, the display supports */
+ char raw_display_charset[SLEN] = "$MM_CHARSET";	
+                                         /* the charset, the display supports */
  char charset_compatlist[SLEN] = {0};	/* list of charsets which are a
  					   superset of us-ascii */
! char text_encoding[SLEN] = {0};	/* default encoding for text/plain -- NOT USED */
! int allow_no_encoding = 0;      /* 1: Allow 8bit without -B8BITMIME
!                                  * 2: Allow binary without -BBINARYMIME and
!                                  *    and 8bit without -B8BITMIME */
! int allow_no_hdrencoding = 0;    /* TRUE, if header encoding is 
! 				  * not required */
! 
! char raw_metamail_path[SLEN] = METAMAIL_PATH;
! char metamail_path[SLEN]     = "metamail"; /* Metamail path or "none" if no metamail */
  #endif
  char cur_folder[SLEN] = {0};	/* name of current folder */
  char cur_tempfolder[SLEN] = {0};/* name of temp folder open for a mailbox */
***************
*** 191,203 ****
  
  char backspace,			/* the current backspace char */
       escape_char = TILDE_ESCAPE,/* '~' or something else..    */
!      kill_line;			/* the current kill-line char */
! 
! char up[SHORT] = {0},		/* cursor control seq's    */
!      down[SHORT] = {0},
!      left[SHORT] = {0},
!      right[SHORT] = {0};
! int  cursor_control = FALSE;	/* cursor control avail?   */
  
  int  has_highlighting = FALSE;	/* highlighting available? */
  
--- 201,211 ----
  
  char backspace,			/* the current backspace char */
       escape_char = TILDE_ESCAPE,/* '~' or something else..    */
!      kill_line,			/* the current kill-line char */
!      word_erase,		/* the current word-erase char */
!      interrupt_char,		/* the current interrupt char */
!      reprint_char,		/* the current reprint-line char */
!      eof_char;			/* the current end-of-file char */
  
  int  has_highlighting = FALSE;	/* highlighting available? */
  
***************
*** 210,223 ****
  int prompt_after_pager = 1;	/* flag: prompt after pager exits   */
  int folder_type = 0;		/* flag: type of folder		    */
  int auto_copy = 0;		/* flag: automatically copy source? */
! int filter = 1;			/* flag: weed out header lines?	    */
  int resolve_mode = 1;		/* flag: delete saved mail?	    */
  int auto_cc = 0;		/* flag: mail copy to user?	    */
  int noheader = 1;		/* flag: copy + header to file?     */
  int title_messages = 1;		/* flag: title message display?     */
! int forwarding = 0;		/* flag: are we forwarding the msg? */
! int hp_terminal = 0;		/* flag: are we on HP term?	    */
! int hp_softkeys = 0;		/* flag: are there softkeys?        */
  int save_by_name = 1;		/* flag: save mail by login name?   */
  int force_name = 0;		/* flag: save by name forced?	    */
  int mail_only = 0;		/* flag: send mail then leave?      */
--- 218,231 ----
  int prompt_after_pager = 1;	/* flag: prompt after pager exits   */
  int folder_type = 0;		/* flag: type of folder		    */
  int auto_copy = 0;		/* flag: automatically copy source? */
! int elm_filter = 1;		/* flag: weed out header lines?	    */
  int resolve_mode = 1;		/* flag: delete saved mail?	    */
  int auto_cc = 0;		/* flag: mail copy to user?	    */
  int noheader = 1;		/* flag: copy + header to file?     */
+ int noheaderfwd = 0;		/* flag: copy + header to file(fwd)? */
  int title_messages = 1;		/* flag: title message display?     */
! /* int hp_terminal = 0;	*/	/* flag: are we on HP term?	    */
! /* int hp_softkeys = 0;	*/	/* flag: are there softkeys?        */
  int save_by_name = 1;		/* flag: save mail by login name?   */
  int force_name = 0;		/* flag: save by name forced?	    */
  int mail_only = 0;		/* flag: send mail then leave?      */
***************
*** 248,266 ****
  int confirm_create = 0;		/* flag: confirm create new folder? */
  int confirm_files = 0;		/* flag: confirm files for append?  */
  int confirm_folders = 0;	/* flag: confirm folders for create?*/
  
  int sortby = REVERSE SENT_DATE;	/* how to sort incoming mail...     */
  int alias_sortby = NAME_SORT;	/* how to sort aliases...           */
  
! long timeout = 600L;		/* timeout (secs) on main prompt    */
  
  /** set up some default values for a 'typical' terminal *snicker* **/
  
! int LINES=23;			/** lines per screen      **/
! int COLUMNS=80;			/** columns per page      **/
  #ifdef SIGWINCH
  int resize_screen = 0;		/** SIGWINCH occured?	  **/
  #endif
  
  long size_of_pathfd;		/** size of pathfile, 0 if none **/
  
--- 256,277 ----
  int confirm_create = 0;		/* flag: confirm create new folder? */
  int confirm_files = 0;		/* flag: confirm files for append?  */
  int confirm_folders = 0;	/* flag: confirm folders for create?*/
+ int mail_permissions = 0600;	/* int: permissions for mailbox files   */
+ int quote_forward = 0;		/* flag: fwd'd msgs quoted like replies */
  
  int sortby = REVERSE SENT_DATE;	/* how to sort incoming mail...     */
  int alias_sortby = NAME_SORT;	/* how to sort aliases...           */
  
! long elm_timeout = 600L;	/* timeout (secs) on main prompt    */
  
  /** set up some default values for a 'typical' terminal *snicker* **/
  
! int elm_LINES=23;		/** lines per screen      **/
! int elm_COLUMNS=80;		/** columns per page      **/
  #ifdef SIGWINCH
  int resize_screen = 0;		/** SIGWINCH occured?	  **/
  #endif
+ int redraw_screen = 0;          /* Elm suspended?          */
  
  long size_of_pathfd;		/** size of pathfile, 0 if none **/
  
***************
*** 292,294 ****
--- 303,326 ----
  
  JMP_BUF GetPromptBuf;		/* setjmp buffer */
  int InGetPrompt;		/* set if in GetPrompt() in read() */
+ #ifdef USE_PGP
+ int pgp_askpgpsig=0; /* Should pgp ask userid to sign messages with? */
+ int pgp_status=0;    /* var to keep track of pgp internals */
+ int pgp_keeppass=0;  /* should Elm keep the passphrase in memory? */
+ int pgp_noarmor=1;   /* Should Elm display text before PGP armor */
+ #endif
+ int me_retcode;
+ int showto;
+ #ifdef MIME
+ int req_mime_hdrencoding = 0;
+ int req_mime_bodyencoding = 1;
+ int pagemultipart=0;  /* Page unknown mime subparts? */
+ short mime_count = 0; /* A counter used so that each call to
+                        * mime_generate_boundary() returns a unique value.
+                        */
+ mime_t *attachments = NULL;
+ int mimeforward = FALSE;
+ #endif
+ #ifdef USE_REMAILER
+ int remailing;
+ #endif
Index: WORK/hdrs/headers.h
*** elm2.4.25/hdrs/headers.h	Thu Sep  1 22:42:40 1994
--- WORK/hdrs/headers.h	Tue Aug 13 15:14:38 1996
***************
*** 116,125 ****
--- 116,133 ----
  	   sleepmsg;		/* time to sleep for messages being overwritten on screen */
  #ifdef MIME
  extern char charset[SLEN];	/* name of character set */
+ extern char raw_display_charset[SLEN];
  extern char display_charset[SLEN];	/* name of character set */
  extern char charset_compatlist[SLEN];	/* list of charsets which are a
  					   superset of us-ascii */
  extern char text_encoding[SLEN];	/* default encoding for text/plain */
+ extern int allow_no_encoding;       /* 1: Allow 8bit without -B8BITMIME
+                                      * 2: Allow binary without -BBINARYMIME
+                                      *    and 8bit without -B8BITMIME */
+ extern int allow_no_hdrencoding;    /* TRUE, if header encoding is 
+ 				     * not required */
+ extern char raw_metamail_path[SLEN];
+ extern char metamail_path[SLEN];  /* Metamail path or "none" if no metamail */
  #endif
  extern char cur_folder[SLEN];	/* name of current folder */
  extern char cur_tempfolder[SLEN]; /* name of temp folder open for a mailbox */
***************
*** 185,198 ****
  
  extern char backspace,		/* the current backspace char  */
  	    escape_char,	/* '~' or something else...    */
! 	    kill_line;		/* the current kill_line char  */
  
- extern char up[SHORT], 
- 	    down[SHORT],
- 	    left[SHORT],
- 	    right[SHORT];	/* cursor control seq's    */
- extern int  cursor_control;	/* cursor control avail?   */
- 
  extern int  has_highlighting;	/* highlighting available? */
  
  /** the following two are for arbitrary weedout lists.. **/
--- 193,204 ----
  
  extern char backspace,		/* the current backspace char  */
  	    escape_char,	/* '~' or something else...    */
! 	    kill_line,		/* the current kill_line char  */
!   	    word_erase,		/* the current word-erase char */
!   	    interrupt_char,	/* the current interrupt char */
!   	    reprint_char,	/* the current reprint-line char */
!   	    eof_char;		/* the current end-of-file char */
  
  extern int  has_highlighting;	/* highlighting available? */
  
  /** the following two are for arbitrary weedout lists.. **/
***************
*** 206,219 ****
  extern int  metoo;		/* flag: copy me on mail to alias?    */
  extern int  folder_type;	/* flag: type of folder		      */
  extern int  auto_copy;		/* flag: auto copy source into reply? */
! extern int  filter;		/* flag: weed out header lines?	      */
  extern int  resolve_mode;	/* flag: resolve before moving mode?  */
  extern int  auto_cc;		/* flag: mail copy to yourself?       */
  extern int  noheader;		/* flag: copy + header to file?       */
  extern int  title_messages;	/* flag: title message display?       */
! extern int  forwarding;		/* flag: are we forwarding the msg?   */
! extern int  hp_terminal;	/* flag: are we on an hp terminal?    */
! extern int  hp_softkeys;	/* flag: are there softkeys?          */
  extern int  save_by_name;  	/* flag: save mail by login name?     */
  extern int  force_name;		/* flag: save by name forced?	      */
  extern int  mail_only;		/* flag: send mail then leave?        */
--- 212,225 ----
  extern int  metoo;		/* flag: copy me on mail to alias?    */
  extern int  folder_type;	/* flag: type of folder		      */
  extern int  auto_copy;		/* flag: auto copy source into reply? */
! extern int  elm_filter;		/* flag: weed out header lines?	      */
  extern int  resolve_mode;	/* flag: resolve before moving mode?  */
  extern int  auto_cc;		/* flag: mail copy to yourself?       */
  extern int  noheader;		/* flag: copy + header to file?       */
+ extern int  noheaderfwd;	/* flag: copy + header to file?(fwd)  */
  extern int  title_messages;	/* flag: title message display?       */
! /* extern int  hp_terminal; */	/* flag: are we on an hp terminal?    */
! /* extern int  hp_softkeys; */	/* flag: are there softkeys?          */
  extern int  save_by_name;  	/* flag: save mail by login name?     */
  extern int  force_name;		/* flag: save by name forced?	      */
  extern int  mail_only;		/* flag: send mail then leave?        */
***************
*** 241,257 ****
  extern int  confirm_create;	/* flag: confirm create new folder?   */
  extern int  confirm_files;	/* flag: confirm files for append?    */
  extern int  confirm_folders;	/* flag: confirm folders for create?  */
  
  extern int  sortby;		/* how to sort folders	      */
  extern int  alias_sortby;	/* how to sort aliases        */
  
! extern long timeout;		/* seconds for main level timeout     */
  
! extern int LINES;		/** lines per screen    **/
! extern int COLUMNS;		/** columns per line    **/
  #ifdef SIGWINCH
  extern int resize_screen;	/** SIGWINCH occured?   **/
  #endif
  
  extern long size_of_pathfd;	/** size of pathfile, 0 if none **/
  
--- 247,266 ----
  extern int  confirm_create;	/* flag: confirm create new folder?   */
  extern int  confirm_files;	/* flag: confirm files for append?    */
  extern int  confirm_folders;	/* flag: confirm folders for create?  */
+ extern int  mail_permissions;	/* int: permissions for mailbox files   */
+ extern int  quote_forward;	/* flag: fwd'd msgs quoted like replies */
  
  extern int  sortby;		/* how to sort folders	      */
  extern int  alias_sortby;	/* how to sort aliases        */
  
! extern long elm_timeout;        /* seconds for main level timeout     */
  
! extern int elm_LINES;		/** lines per screen    **/
! extern int elm_COLUMNS;		/** columns per line    **/
  #ifdef SIGWINCH
  extern int resize_screen;	/** SIGWINCH occured?   **/
  #endif
+ extern int redraw_screen;	/** Elm suspended?   **/
  
  extern long size_of_pathfd;	/** size of pathfile, 0 if none **/
  
***************
*** 283,285 ****
--- 292,311 ----
  
  extern JMP_BUF GetPromptBuf;	/* setjmp buffer */
  extern int InGetPrompt;		/* set if in GetPrompt() in read() */
+ #ifdef USE_PGP
+ extern int pgp_askpgpsig;   /* Should pgp ask userid to sign messages with? */
+ extern int pgp_status;
+ extern int pgp_keeppass;    /* should Elm keep the passphrase? */
+ extern int pgp_keeppassfor; /* how long to keep it before expiring */
+ extern int pgp_noarmor;     /* Should Elm display text before PGP armor */
+ #endif
+ extern int  showto;
+ extern int me_retcode;
+ #ifdef MIME
+ extern int pagemultipart;
+ extern int req_mime_hdrencoding;
+ extern int req_mime_bodyencoding;
+ extern char *mime_encode_names[]; /* defined in mime.c */
+ extern char *mime_types[];
+ extern int mimeforward;
+ #endif
Index: WORK/hdrs/mcprt.h
*** elm2.4.25/hdrs/mcprt.h	Thu Jun 30 19:42:29 1994
--- WORK/hdrs/mcprt.h	Mon Jun  3 20:16:26 1996
***************
*** 48,54 ****
  #include <stdio.h>
  
  #ifdef USENLS
! #  ifdef ANSI_C
  extern int     	MCprintf(char *fmt, ...);
  extern int     	MCfprintf(FILE *fptr, char *fmt, ...);
  extern int     	MCsprintf(char *cptr, char *fmt, ...);
--- 48,54 ----
  #include <stdio.h>
  
  #ifdef USENLS
! #  if ANSI_C & defined(I_STDARG)
  extern int     	MCprintf(char *fmt, ...);
  extern int     	MCfprintf(FILE *fptr, char *fmt, ...);
  extern int     	MCsprintf(char *cptr, char *fmt, ...);
Index: WORK/hdrs/mcprtlib.h
*** elm2.4.25/hdrs/mcprtlib.h	Mon Aug 23 05:48:18 1993
--- WORK/hdrs/mcprtlib.h	Mon Jun  3 20:16:26 1996
***************
*** 49,55 ****
  /* taken from Xm/lib/VaSimple.h
     currently no one defines MISSING_STDARG_H */
   
! #ifdef	I_STDARG
  # include <stdarg.h>
  # define Va_start(a,b) va_start(a,b)
  #else
--- 49,55 ----
  /* taken from Xm/lib/VaSimple.h
     currently no one defines MISSING_STDARG_H */
   
! #if	ANSI_C & defined(I_STDARG)
  # include <stdarg.h>
  # define Va_start(a,b) va_start(a,b)
  #else
Index: WORK/hdrs/me.h
*** /tmp/null.14101	Tue Aug 20 22:05:34 1996
--- WORK/hdrs/me.h	Sat Aug 10 16:15:21 1996
***************
*** 0 ****
--- 1,367 ----
+ #define PUBLIC 
+ 
+ #undef P_
+ #ifdef __STDC__
+ #define P_(x) x
+ #else
+ #define P_(x) ()
+ #endif
+ 
+ /** Definitions for state operations **/
+ 
+ struct in_state;
+ struct out_state;
+ 
+ /* can't be 'char' as argumnet because problems of default
+  * promotion rules of arguments -- therefore 'int' is used
+  * in functios: state_filter, state_putc
+  *
+  * Notice also that we assumen here that char agument (as int)
+  * is 'unsigned char'
+  *
+  *  - K E H
+  */
+ 
+ typedef int state_filter P_((int, struct out_state *));
+ 
+ /* state magics */
+ #define   STATE_in_file      0xFA01
+ #define   STATE_in_string    0xFA02
+ 
+ #define   STATE_out_file     0xFB01
+ #define   STATE_out_string   0xFB02
+ 
+ typedef struct {
+   FILE *fpin;
+ } in_state_file;
+ 
+ typedef struct {
+   char *inbuf;
+   char *inreadp;
+ } in_state_string;
+ 
+ typedef struct in_state {
+   unsigned short magic;
+ 
+   union {
+     in_state_file    file;
+     in_state_string  string;
+   } u;
+ } in_state_t;
+ 
+ typedef struct {
+   FILE *fpout;
+ } out_state_file;
+ 
+ typedef struct {
+   char *outbuf;
+   char *outwritep;
+   int outbufsize;
+ } out_state_string;
+ 
+ 
+ typedef struct out_state {
+   unsigned short magic;
+ 
+   unsigned int displaying : 1;
+   char *prefix;
+ 
+   state_filter * filter;
+ 
+   union {
+     out_state_file    file;
+     out_state_string  string;
+   } u;
+ } out_state_t;
+ 
+ #define state_add_prefix(x) if((x)->prefix)state_puts((x)->prefix,x)
+ 
+ extern void in_state_clear   P_((in_state_t *, int));
+ extern void in_state_destroy P_((in_state_t *));
+ 
+ extern void set_in_state_buffer P_((char *,in_state_t *));   /* STATE_in_string */
+ extern void set_in_state_file   P_((FILE *,in_state_t *));   /* STATE_in_file */
+ 
+ extern int  in_state_seekable P_((in_state_t *)); 
+ extern int  in_state_fseek P_((in_state_t *, long)); /* STATE_in_file */
+ extern long in_state_ftell P_((in_state_t *));       /* STATE_in_file */
+ extern FILE * in_state_FILE P_((in_state_t *)); /* STATE_in_file */
+ 
+ extern char *state_gets P_((char *, int, in_state_t *));
+ extern int   state_getl P_((char *, int, in_state_t *));
+ extern int   state_getc P_((in_state_t *s));
+ extern int   state_ungetc P_((int,in_state_t *));
+ 
+ extern void out_state_clear   P_((out_state_t *, int));
+ extern void out_state_destroy P_((out_state_t *));
+ 
+ /* STATE_out_string */
+ extern void set_out_state_buffer P_((char *,int,out_state_t *));
+ extern void set_out_state_file   P_((FILE *,out_state_t *));  /* STATE_out_file */
+ 
+ extern int state_put  P_((char *, int, out_state_t *));
+ extern int state_puts P_((char *, out_state_t *));
+ extern int state_putc P_((int,  out_state_t *));
+ 
+ /* STATE_out_string */
+ extern void out_state_ref_buffer P_((out_state_t *, char **, int*));
+ 
+ extern int NULL_filter P_((int, struct out_state *));
+ 
+ /* curses.c */
+ 
+ extern int ReadCh P_((int));
+ 
+ /* elm.c */
+ extern void motion P_((int));
+ 
+ /* in_utils.c */
+ 
+ extern int optionally_enter P_((char *, int, int, int));
+ 
+ /* out_utils.c */
+ 
+ extern void sleep_message P_((void));
+ 
+ /* Alias.c */
+ 
+ extern void alias P_((void));
+ 
+ /* fileutil.c */
+ 
+ extern FILE *open_end_update P_((char *));
+ 
+ /* lib/strmcpy.c */
+ 
+ extern char *strmcpy P_((char *, char *));
+ 
+ /* lib/safeopen.c */
+ 
+ extern FILE *safeopen P_((char *));
+ extern FILE *safeopen_rdwr P_((char *));
+ 
+ /* lib/dispaddr.c */
+ 
+ int DisplayAddress  P_((struct header_rec *,char *,int));
+ void get_real_name P_((char *, char *, int));
+ 
+ /* lib/qstring.c */
+ char *qstrpbrk P_((char *, char *));
+ 
+ /* lib/strincmp.c */
+ 
+ int strincmp P_((char *, char *, int));
+ 
+ /* lib/istrcmp.c */
+ 
+ int istrcmp P_((char *, char *));
+ 
+ /* src/remailer.c */
+ 
+ #ifdef USE_REMAILER
+ #ifdef MIME
+ extern int remailer_copy_message_across P_((FILE *, FILE *, int, mime_send_t *));
+ #else
+ extern int remailer_copy_message_across P_((FILE *, FILE *, int));
+ #endif
+ extern int remailer_proc P_((void));
+ #endif
+ 
+ #ifdef USE_PGP
+ extern int pgp_decrypt_init		P_((FILE **, FILE **, int));
+ extern int pgp_encrypt			P_((char *, char *, char *, int, int));
+ extern int pgp_menu			P_((char *));
+ extern int pgp_extract_public_key	P_((void));
+ #ifdef MIME
+ extern void pgp_decode  		P_((mime_t *, 
+ 					    in_state_t *, out_state_t *));
+ #endif
+ #endif
+ 
+ extern int metapager		P_((FILE *, struct header_rec *, int));
+ extern int builtinplusplus	P_((FILE *, long, int, char **, int));
+ 
+ /* mime.c */
+ 
+ extern int have_metamail        P_((void));
+ 
+ /* parse_util.c */
+ 
+ typedef struct header_info {
+   char * header;
+   int flag;
+ } * header_ptr;
+ 
+ #define HEADER_magic        0xFC00
+ 
+ typedef struct header_list {
+   unsigned short magic;
+   header_ptr header_name;
+   struct header_list * next_this_header;
+   struct header_list * next_header;
+   struct header_list * next_other_header;
+   char * body;
+ } * header_list_ptr;
+ 
+ #define   RHL_MARK_FOLDING      1
+ #define   RHL_CHECK_HEADER      2
+ 
+ extern void rfc822_reap_comments        P_((char *, char *, int));
+ extern int read_header_line             P_((FILE *,char *,int,int));
+ extern int state_read_hdr_line          P_((in_state_t *,char *, int, int));
+ 
+ typedef int header_filter    P_((header_list_ptr, int));
+ typedef void header_converter P_((header_list_ptr, int, char *, int));
+ 
+ extern int NULL_header_filter    P_((header_list_ptr, int));
+ extern void NULL_header_converter P_((header_list_ptr, int, char *, int));
+ 
+ extern void state_write_headers P_((out_state_t *,header_list_ptr,
+ 				    header_filter *, header_converter *,
+ 				    int));
+ 
+ extern header_list_ptr state_read_headers P_((in_state_t *, int));
+ extern header_list_ptr file_read_headers  P_((FILE *, int));
+ extern void delete_headers                P_((header_list_ptr));
+ extern header_list_ptr locate_header      P_((header_list_ptr,header_ptr));
+ 
+ extern header_ptr find_header           P_((char *,int));
+ extern int classify_header              P_((char *));
+ 
+ #define locate_header_by_name(h,n)      locate_header(h,find_header(n,0))
+ 
+ extern long skip_envelope P_((struct header_rec *hdr, FILE *fp));
+ 
+ /* fileio.h */
+ extern void copy_message P_((FILE *, struct header_rec *,
+ 			     char *, FILE *, int));
+ 
+ extern void copy_plain P_((char *,FILE *,int, struct header_rec *, FILE *));
+ #ifdef MIME
+ extern void copy_mime P_((char *,FILE *,int, struct header_rec *, FILE *));
+ #endif
+ 
+ typedef void copy_decoder P_((char *,FILE *,int, struct header_rec *, FILE *));
+ typedef copy_decoder *copy_decoder_t;
+ extern copy_decoder_t select_copy_decoder P_((struct header_rec *));
+ 
+ /* newmbox.c */
+ 
+ extern void header_zero P_((struct header_rec *));
+ 
+ #ifdef MIME
+ extern int is_pre_mime_content_type P_((mime_t *,char *));
+ #endif /* MIME */
+ 
+ /* mailmsg1.c */
+ 
+ int send_msg            P_((char *, char *, char *, int, int));
+ int copy_the_msg        P_((int *,int));
+ 
+ /* mailmsg2.c */
+ 
+ int mail P_((struct header_rec *, int, int));
+ int mail_form P_((struct header_rec *, char *, char *));
+ 
+ /* syscall.c */
+ #define FDVEC_TO_PRG       1
+ #define FDVEC_DEFINE       2
+ #define FDVEC_STDIN        4
+ #define FDVEC_STDOUT       8
+ #define FDVEC_STDERR      16
+ #define FDVEC_FILE        32
+ #define FDVEC_END         -1
+ 
+ struct fdvec {
+   int fd;
+   char * name;
+   int flag;
+ 
+   /* used only internally: */
+   int fd2;
+ };
+ 
+ extern int system_call    P_((char *, int));
+ #ifdef MAYBE_IN_NEXT_RELEASE
+ extern int start_pipes    P_((char *,struct fdvec [], char * [], int,int));
+ extern int end_pipes      P_((int,char *,struct fdvec [],int, char *));
+ extern void close_pipes   P_((struct fdvec []));
+ #endif
+ 
+ /* lib/errno.c */
+ 
+ extern char *error_description P_((int));
+ 
+ #ifdef MIME
+ extern int save_copy		P_((char *, char *, char *, char *, 
+ 				       char *, int, mime_send_t *));
+ extern int append_copy_to_file	P_((char *, char *, char *, char *, 
+ 				       char *, int, mime_send_t *));
+ extern FILE *write_header_info	P_((char *, char *, char *, char *, 
+ 				       int, int, mime_send_t *));
+ extern int copy_message_across	P_((FILE *, FILE *, int, mime_send_t *));
+ extern int check_for_multipart	P_((FILE *, mime_send_t *));
+ extern int Include_Part		P_((FILE *, char *, int, mime_send_t *, int));
+ 
+ /* mime_decode.c */
+ 
+ extern void base64_decode	P_((in_state_t *, out_state_t *, int, int));
+ extern void quoted_printable_decode  P_((in_state_t *, out_state_t *,
+ 					 int, int));
+ extern void null_decode		P_((mime_t *, in_state_t *, out_state_t *));
+ extern void mime_decode		P_((mime_t *, in_state_t *, out_state_t *));
+ extern void rfc1522_decode P_((char *, int));
+ extern void rfc1522_decode_structured   P_((int, char *, int));
+ extern int is_rfc1522 P_((char *));
+ 
+ extern int set_filter	P_((mime_t *, out_state_t *)); 
+ extern FILE *arrange_decoded P_((mime_t *,in_state_t  *,
+ 			      out_state_t *,in_state_t *));
+ 
+ typedef void CT_decoder	        P_((mime_t *, in_state_t *, out_state_t *));
+ typedef CT_decoder *CT_decoder_t;
+ extern CT_decoder_t select_CT_decoder	P_((mime_t *));
+ 
+ /* mime_encode.c */
+ 
+ extern void attach_generate_message P_((mime_t *, FILE *, int, mime_send_t *));
+ extern void base64_encode	    P_((FILE *, FILE *, int, mime_send_t *));
+ extern void line_quoted_printable_encode P_((char *, FILE *, int, int,
+ 					       int, mime_send_t *));
+ extern void quoted_printable_encode	P_((FILE *, FILE *, int, int,
+ 						mime_send_t *));
+ extern int is_text_type			P_((char *, char *, int));
+ extern char *mime_generate_boundary	P_((char *));
+ extern void add_parameter		P_((char *,char *,char *,int, int));
+ extern void print_EOLN			P_((FILE *,int));
+ extern int update_encoding		P_((int *,int));
+ extern void write_encoded   P_((FILE *, FILE *, int, int, int, mime_send_t *));
+ extern void mime_write_header		P_((FILE *, mime_send_t *, int));
+ extern void rfc1522_encode_text         P_((char *,int,char *,int));
+ 
+ /* mime_parse.c */
+ 
+ extern mime_t *mime_t_alloc             P_((void));
+ extern void mime_t_copy                 P_((mime_t *, mime_t *));
+ extern void mime_t_zero                 P_((mime_t *));
+ extern void mime_destroy		P_((mime_t *));
+ extern void mime_get_disposition        P_((char *, mime_t *));
+ extern void mime_get_content		P_((char *, mime_t *));
+ extern int class_charset                P_((char *));
+ extern int mime_get_charset             P_((char *, char *, int));
+ extern char * mime_parse_content_opts	P_((char *));
+ extern int mime_get_param               P_((char *,char *,char *,int));
+ extern void mime_warnings		P_((struct header_rec *));
+ extern mime_t *rfc822_parse		P_((FILE *, int));
+ extern mime_t * multipart_parse         P_((FILE *, int, char *, int));
+ extern void mime_get_boundary           P_((char *, char *, int));
+ 
+ extern void attach_parse		P_((struct header_rec *,FILE *));
+ extern mime_t *mime_read_header         P_((FILE *, int));
+ extern mime_t *parse_mime_headers       P_((header_list_ptr,long,long,int));
+ 
+ /* attach_menu.c */
+ 
+ extern mime_t *attach_menu		P_((mime_t *, int));
+ 
+ #endif
Index: WORK/hdrs/menu.h
*** /tmp/null.14101	Tue Aug 20 22:05:34 1996
--- WORK/hdrs/menu.h	Mon Jun  3 20:16:29 1996
***************
*** 0 ****
--- 1,24 ----
+ /* $Id: $
+  *
+  * $Log: $
+  */
+ 
+ /* returns the number of the current selection from the menu */
+ #define MenuCurrent(X) X.current
+ 
+ /* this will make MenuLoop() update the screen on the next call */
+ #define MenuUpdate(X) (X.update = 1)
+ 
+ struct menu_object {
+   char **data;
+   char *title;
+   char *prompt;
+   char *help;
+   int prompt_length;
+   int len;
+   int max;
+   int current;
+   int pagetop; /* the index of the first entry on this page */
+   unsigned int update : 1;
+ };
+ typedef struct menu_object menu_t;
Index: WORK/hdrs/menu2.h
*** /tmp/null.14101	Tue Aug 20 22:05:34 1996
--- WORK/hdrs/menu2.h	Mon Jun  3 20:16:29 1996
***************
*** 0 ****
--- 1,10 ----
+ struct menu_item {
+   char *option;
+   char key;
+   char offset;
+   char type;
+   union ptrs { 
+     char *c;
+     int *i; /* used by BOL and INT */
+   } d;
+ };
Index: WORK/hdrs/mime.h
*** elm2.4.25/hdrs/mime.h	Sat Nov  7 22:50:23 1992
--- WORK/hdrs/mime.h	Mon Jun  3 20:16:30 1996
***************
*** 30,42 ****
  #define	MIME_HEADER	"MIME-Version: 1.0"
  #define	MIME_HEADER_NAME	"MIME-Version"
  #define	MIME_HEADER_VERSION	"1.0"
- #define	MIME_OLDVERSION	"MIME-Version: RFCXXXX"
- #define	MIME_HEADER_OLDVERSION	"RFCXXXX"
  #define	MIME_INCLUDE	"[include"
- #define MIME_BOUNDARY	"%#%record%#%"	/* default boundary */
  #define	MIME_CONTENTTYPE	"Content-Type:"
  #define	MIME_HEADER_CONTENTTYPE	"Content-Type"
  #define	MIME_CONTENTENCOD	"Content-Transfer-Encoding:"
  #define	MIME_HEADER_CONTENTENCOD	"Content-Transfer-Encoding"
  
  /* Encoding types */
--- 30,41 ----
  #define	MIME_HEADER	"MIME-Version: 1.0"
  #define	MIME_HEADER_NAME	"MIME-Version"
  #define	MIME_HEADER_VERSION	"1.0"
  #define	MIME_INCLUDE	"[include"
  #define	MIME_CONTENTTYPE	"Content-Type:"
+ #define	MIME_CONTENTTYPE_LEN	13
  #define	MIME_HEADER_CONTENTTYPE	"Content-Type"
  #define	MIME_CONTENTENCOD	"Content-Transfer-Encoding:"
+ #define	MIME_CONTENTENCOD_LEN	26
  #define	MIME_HEADER_CONTENTENCOD	"Content-Transfer-Encoding"
  
  /* Encoding types */
***************
*** 56,62 ****
  #define	ENC_NAME_QUOTED "quoted-printable"
  #define	ENC_NAME_BASE64	"base64"
  
! /* default charsets, which are a superset of US-ASCII, so we did not
     have to go out to metamail for us-ascii */
  
! #define COMPAT_CHARSETS "ISO-8859-1 ISO-8859-2 ISO-8859-3 ISO-8859-4 ISO-8859-5 ISO-8859-7 ISO-8859-8 ISO-8859-9"
--- 55,126 ----
  #define	ENC_NAME_QUOTED "quoted-printable"
  #define	ENC_NAME_BASE64	"base64"
  
! /* Default charsets, which are a superset of US-ASCII, so we do not
     have to go out to metamail for us-ascii */
  
! #define COMPAT_CHARSETS "ISO-8859-1 ISO-8859-2 ISO-8859-3 ISO-8859-4 ISO-8859-5 ISO-8859-7 ISO-8859-8 ISO-8859-9 KOI8-R"
! 
! /* These are for figuring out what the encoding on outgoing messages should
!  * be.
!  */
! #define HAVE_8BIT 1
! #define HAVE_CTRL 4
! #define HAVE_BINARY 8
! 
! /* Possible major types in Content-Type field. */
! #define MIME_TYPE_UNKNOWN	0
! #define MIME_TYPE_APPLICATION	1
! #define MIME_TYPE_AUDIO		2
! #define MIME_TYPE_IMAGE		3
! #define MIME_TYPE_MESSAGE	4
! #define MIME_TYPE_MULTIPART	5
! #define MIME_TYPE_TEXT		6
! #define MIME_TYPE_VIDEO		7
! 
! /* Values for the "flag" field in "mimeinfo" */
! #define MIME_RFC822 1
! #define MIME_MIXED 2
! #define MIME_DIGEST 4
! 
! /* Content-Disposition */
! #define DISP_INLINE	0
! #define DISP_ATTACH	1
! 
! #define DISPOSITION(x) (x == DISP_INLINE ? "inline" : "attachment")
! #define TYPE(x) (mime_types[(x)])
! #define NONULL(x) (x ? x : "")
! #define ENCODING(x) (x >= 0 ? mime_encode_names[x] : "<ILLEGAL>")
! 
! typedef struct mime_send {    /* Mime parameters for this mail */
! 
!   /* Information for multipart  */
!   int encoding_top; /* Encoding for top multipart type.
!                      * ENCODING_8BIT:   add content_transfer_encoding: 8bit
!                      *                  pass -B8BITMIME to mailer
!                      * ENCODING_BINARY: add content_transfer_encoding: binary
! 		     *                  pass -BBINARYMIME to mailer
!                      */
!   char mime_boundary[STRING];
!   char type_opts_top[STRING];
! 
!   /* Information for text parts */
!   int encoding_text;/* Encoding of text parts (nt attachments)
! 		     * ENCODING_QUOTED: 
! 		     *         add content_transfer_encoding: quoted-printable
! 		     * ENCODING_8BIT:
! 		     *         add content_transfer_encoding: 8bit
! 		     */
!   int need_enc;     /* Bitmask: HAVE_8BIT:   have 8-bit data
! 		     *          HAVE_BINARY: have 'binary' data
! 		     *          HAVE_CTRL:   have control characters
! 		     */
!   char * Charset;   /* Charset of text */
!   unsigned int type_text : 3;
!   char         subtype_text[STRING];
!   char         type_opts_text[STRING];
! 
!   int msg_is_multipart;
!   char encoded_subject[LONG_STRING];
!   char encoded_fullname[STRING];
!   char encoded_in_reply_to[LONG_STRING];
! } mime_send_t;
Index: WORK/hdrs/s_aliases.h
*** elm2.4.25/hdrs/s_aliases.h	Mon Apr 12 07:14:23 1993
--- WORK/hdrs/s_aliases.h	Mon Jun  3 20:16:32 1996
***************
*** 1,4 ****
- /* s_aliases.h created from s_aliases.us by gencat on Mon Apr 12 00:14:23 EDT 1993 */
  
  #define AliasesSet	0x5
  #define AliasesDelete	0x1
--- 1,3 ----
Index: WORK/hdrs/s_answer.h
*** elm2.4.25/hdrs/s_answer.h	Sun Oct  4 00:35:11 1992
--- WORK/hdrs/s_answer.h	Mon Jun  3 20:16:32 1996
***************
*** 1,4 ****
- /* s_answer.h created from s_answer.us by gencat on Sat Oct  3 18:33:40 EDT 1992 */
  
  #define AnswerSet	0xb
  #define AnswerQuitWord	0x1
--- 1,3 ----
Index: WORK/hdrs/s_elm.h
*** elm2.4.25/hdrs/s_elm.h	Tue Aug  3 21:58:35 1993
--- WORK/hdrs/s_elm.h	Mon Jun  3 20:16:32 1996
***************
*** 1,4 ****
- /* s_elm.h created from s_elm.us by gencat on Tue Aug  3 14:58:35 EDT 1993 */
  
  #define ElmSet	0x3
  #define ElmYes	0x1
--- 1,3 ----
***************
*** 759,761 ****
--- 758,762 ----
  #define ElmVfyMenuSndFgt	0x34e
  #define ElmVfyMessageKept	0x34f
  #define ElmVfyNoFieldsInForm	0x350
+ #define ElmHelpViewAttach	0x351
+ #define ElmBadModeInElmrc	0x352
Index: WORK/hdrs/s_elmalias.h
*** elm2.4.25/hdrs/s_elmalias.h	Mon Apr 12 05:10:16 1993
--- WORK/hdrs/s_elmalias.h	Mon Jun  3 20:16:31 1996
***************
*** 1,4 ****
- /* s_elmalias.h created from s_elmalias.us by gencat on Sun Apr 11 22:03:05 EDT 1993 */
  
  #define ElmaliasSet	0x4
  #define ElmaliasUsage	0x1
--- 1,3 ----
Index: WORK/hdrs/s_elmrc.h
*** elm2.4.25/hdrs/s_elmrc.h	Fri Mar 11 23:18:49 1994
--- WORK/hdrs/s_elmrc.h	Mon Jun  3 20:16:33 1996
***************
*** 1,4 ****
- /* s_elmrc.h created from s_elmrc.us by gencat on Fri Mar 11 16:18:48 EST 1994 */
  
  #define ElmrcSet	0x1
  #define ElmrcExpandHome	0x1
--- 1,3 ----
Index: WORK/hdrs/s_error.h
*** elm2.4.25/hdrs/s_error.h	Sun Oct  4 00:35:12 1992
--- WORK/hdrs/s_error.h	Mon Jun  3 20:16:34 1996
***************
*** 1,4 ****
- /* s_error.h created from s_error.us by gencat on Sat Oct  3 18:34:12 EDT 1992 */
  
  #define ErrorSet	0x2
  #define ErrorGetoptReq	0x1
--- 1,3 ----
Index: WORK/hdrs/s_fastmail.h
*** elm2.4.25/hdrs/s_fastmail.h	Sun Oct  4 00:35:13 1992
--- WORK/hdrs/s_fastmail.h	Mon Jun  3 20:16:34 1996
***************
*** 1,4 ****
- /* s_fastmail.h created from s_fastmail.us by gencat on Sat Oct  3 18:34:11 EDT 1992 */
  
  #define FastmailSet	0x12
  #define FastmailCantFindFile	0x1
--- 1,3 ----
Index: WORK/hdrs/s_filter.h
*** elm2.4.25/hdrs/s_filter.h	Sun Nov 15 04:02:01 1992
--- WORK/hdrs/s_filter.h	Mon Jun  3 20:16:34 1996
***************
*** 1,4 ****
- /* s_filter.h created from s_filter.us by gencat on Sat Nov 14 21:02:00 EST 1992 */
  
  #define FilterSet	0x10
  #define FilterCantGetPasswdEntry	0x1
--- 1,3 ----
Index: WORK/hdrs/s_from.h
*** elm2.4.25/hdrs/s_from.h	Mon May 31 22:36:00 1993
--- WORK/hdrs/s_from.h	Mon Jun  3 20:16:34 1996
***************
*** 1,4 ****
- /* s_from.h created from s_from.us by gencat on Mon May 31 15:36:00 EDT 1993 */
  
  #define FromSet	0x11
  #define FromForMoreInfo	0x1
--- 1,3 ----
Index: WORK/hdrs/s_newalias.h
*** elm2.4.25/hdrs/s_newalias.h	Fri Dec 11 05:04:45 1992
--- WORK/hdrs/s_newalias.h	Mon Jun  3 20:16:34 1996
***************
*** 1,4 ****
- /* s_newalias.h created from s_newalias.us by gencat on Thu Dec 10 22:04:44 EST 1992 */
  
  #define NewaliasSet	0xc
  #define NewaliasUsage	0x1
--- 1,3 ----
Index: WORK/hdrs/s_newmail.h
*** elm2.4.25/hdrs/s_newmail.h	Tue Nov 17 21:24:10 1992
--- WORK/hdrs/s_newmail.h	Mon Jun  3 20:16:34 1996
***************
*** 1,4 ****
- /* s_newmail.h created from s_newmail.us by gencat on Sat Oct  3 18:34:18 EDT 1992 */
  
  #define NewmailSet	0xd
  #define NewmailNoSubject	0x1
--- 1,3 ----
Index: WORK/hdrs/s_readmsg.h
*** elm2.4.25/hdrs/s_readmsg.h	Sun Oct  4 00:35:16 1992
--- WORK/hdrs/s_readmsg.h	Mon Jun  3 20:16:34 1996
***************
*** 1,4 ****
- /* s_readmsg.h created from s_readmsg.us by gencat on Sat Oct  3 18:34:19 EDT 1992 */
  
  #define ReadmsgSet	0x13
  #define ReadmsgUsage	0x1
--- 1,3 ----
Index: WORK/hdrs/save_opts.h
*** elm2.4.25/hdrs/save_opts.h	Tue Aug 10 21:49:32 1993
--- WORK/hdrs/save_opts.h	Sat Aug 10 23:12:30 1996
***************
*** 95,100 ****
--- 95,101 ----
  #define DT_SRT 7 /* sort-by code */
  #define DT_MLT 8 /* multiple destinations for data */
  #define DT_ASR 9 /* sort-by code */
+ #define DT_PRM 10 /* file permissions */
  #define DT_MASK 037 /* mask for data type */
  #define FL_LOCAL 0040          /* flag if changed */
  #define FL_NOSPC 0100          /* flag if preserve blanks as "_" */
***************
*** 159,164 ****
--- 160,168 ----
  {"arrow",		-1L,DT_BOL|FL_OR,(char *)&arrow_cursor},
  {"ask",			-1L,DT_BOL,(char *)&question_me},
  {"askcc",		-1L,DT_BOL,(char *)&prompt_for_cc},
+ #ifdef USE_PGP
+ {"askpgpsig",		-1L,DT_BOL,(char *)&pgp_askpgpsig},
+ #endif
  {"attribution",		-1L,DT_STR,attribution},
  {"auto_cc",		-1L,DT_SYN,"copy"},
  {"autocopy",		-1L,DT_BOL,(char *)&auto_copy},
***************
*** 179,185 ****
  {"copy",		-1L,DT_BOL,(char *)&auto_cc},
  {"delete",		-1L,DT_SYN,"alwaysdelete"},
  #ifdef MIME
! {"displaycharset",	-1L,DT_STR,display_charset},
  #endif
  {"easyeditor",		-1L,DT_STR,e_editor},
  {"editor",		-1L,DT_STR,raw_editor},
--- 183,189 ----
  {"copy",		-1L,DT_BOL,(char *)&auto_cc},
  {"delete",		-1L,DT_SYN,"alwaysdelete"},
  #ifdef MIME
! {"displaycharset",	-1L,DT_STR,raw_display_charset},
  #endif
  {"easyeditor",		-1L,DT_STR,e_editor},
  {"editor",		-1L,DT_STR,raw_editor},
***************
*** 192,215 ****
  {"hostdomain",		-1L,DT_STR|FL_SYS,hostdomain},
  {"hostfullname",	-1L,DT_STR|FL_SYS,hostfullname},
  {"hostname",		-1L,DT_STR|FL_SYS,hostname},
! {"hpkeypad",		-1L,DT_SYN,"keypad"},
! {"hpsoftkeys",		-1L,DT_SYN,"softkeys"},
  {"keep",		-1L,DT_SYN,"keepempty"},
  {"keepempty",		-1L,DT_BOL,(char *)&keep_empty_files},
! {"keypad",		-1L,DT_BOL|FL_OR,(char *)&hp_terminal},
  {"localsignature",	-1L,DT_STR,raw_local_signature},
  {"mailbox",		-1L,DT_SYN,"receivedmail"},
  {"maildir",		-1L,DT_STR,raw_folders},
  {"mailedit",		-1L,DT_SYN,"editor"},
  {"menu",		-1L,DT_BOL|FL_AND,(char *)&mini_menu},
  {"menus",		-1L,DT_SYN,"menu"},
  {"metoo",		-1L,DT_BOL,(char *)&metoo},
  {"movepage",		-1L,DT_BOL,(char *)&move_when_paged},
  {"movewhenpaged",	-1L,DT_SYN,"movepage"},
  {"name",		-1L,DT_SYN,"fullname"},
  {"names",		-1L,DT_BOL,(char *)&names_only},
  {"noheader",		-1L,DT_BOL,(char *)&noheader},
  {"page",		-1L,DT_SYN,"pager"},
  {"pager",		-1L,DT_STR,raw_pager},
  {"pointnew",		-1L,DT_BOL,(char *)&point_to_new},
  {"pointtonew",		-1L,DT_SYN,"pointnew"},
--- 196,240 ----
  {"hostdomain",		-1L,DT_STR|FL_SYS,hostdomain},
  {"hostfullname",	-1L,DT_STR|FL_SYS,hostfullname},
  {"hostname",		-1L,DT_STR|FL_SYS,hostname},
!   /* {"hpkeypad",		-1L,DT_SYN,"keypad"}, */
!   /* {"hpsoftkeys",		-1L,DT_SYN,"softkeys"}, */
  {"keep",		-1L,DT_SYN,"keepempty"},
  {"keepempty",		-1L,DT_BOL,(char *)&keep_empty_files},
! #ifdef USE_PGP
! {"keeppassfor", -1L,DT_NUM,(char *)&pgp_keeppassfor},
! #endif
!   /* {"keypad",		-1L,DT_BOL|FL_OR,(char *)&hp_terminal}, */
  {"localsignature",	-1L,DT_STR,raw_local_signature},
  {"mailbox",		-1L,DT_SYN,"receivedmail"},
  {"maildir",		-1L,DT_STR,raw_folders},
  {"mailedit",		-1L,DT_SYN,"editor"},
+ {"mailpermissions",	-1L,DT_PRM,(char *)&mail_permissions},
  {"menu",		-1L,DT_BOL|FL_AND,(char *)&mini_menu},
  {"menus",		-1L,DT_SYN,"menu"},
+ #ifdef MIME
+ {"metamail",		-1L,DT_STR,raw_metamail_path},
+ #endif
  {"metoo",		-1L,DT_BOL,(char *)&metoo},
+ #ifdef MIME
+ {"mimeforward",		-1L,DT_BOL,(char *)&mimeforward},
+ #endif
  {"movepage",		-1L,DT_BOL,(char *)&move_when_paged},
  {"movewhenpaged",	-1L,DT_SYN,"movepage"},
  {"name",		-1L,DT_SYN,"fullname"},
  {"names",		-1L,DT_BOL,(char *)&names_only},
+ #ifdef MIME
+ {"noencoding",-1L,DT_NUM,(char *)&allow_no_encoding},
+                                  /* 1: Allow 8bit without -B8BITMIME
+                                   * 2: Allow binary without -BBINARYMIME and
+                                   *    and 8bit without -B8BITMIME */
+ {"nohdrencoding",       -1L,DT_BOL,(char *)&allow_no_hdrencoding},
+ #endif /* MIME **/
  {"noheader",		-1L,DT_BOL,(char *)&noheader},
+ {"noheaderfwd",		-1L,DT_BOL,(char *)&noheaderfwd},
  {"page",		-1L,DT_SYN,"pager"},
+ #ifdef MIME
+ {"pagemultipart",	-1L,DT_BOL,(char *)&pagemultipart},
+ #endif /* MIME */
  {"pager",		-1L,DT_STR,raw_pager},
  {"pointnew",		-1L,DT_BOL,(char *)&point_to_new},
  {"pointtonew",		-1L,DT_SYN,"pointnew"},
***************
*** 219,227 ****
--- 244,259 ----
  {"printmail",		-1L,DT_SYN,"print"},
  {"promptafter",		-1L,DT_BOL,(char *)&prompt_after_pager},
  {"question",		-1L,DT_SYN,"ask"},
+ {"quoteforward",	-1L,DT_BOL,(char *)&quote_forward},
  {"readmsginc",		-1L,DT_NUM,(char *)&readmsginc},
  {"receivedmail",	-1L,DT_STR,raw_recvdmail},
  {"remotesignature",	-1L,DT_STR,raw_remote_signature},
+ #ifdef MIME
+ {"require-mime-version-for-body-encoding",
+    -1L,DT_BOL,(char *)&req_mime_bodyencoding},
+ {"require-mime-version-for-hdr-encoding",
+    -1L,DT_BOL,(char *)&req_mime_hdrencoding},
+ #endif
  {"resolve",		-1L,DT_BOL,(char *)&resolve_mode},
  {"savebyname",		-1L,DT_SYN,"savename"},
  {"savemail",		-1L,DT_SYN,"sentmail"},
***************
*** 229,238 ****
  {"saveto",		-1L,DT_SYN,"sentmail"},
  {"sentmail",		-1L,DT_STR,raw_sentmail},
  {"shell",		-1L,DT_STR,raw_shell},
  {"sigdashes",		-1L,DT_BOL,(char *)&sig_dashes},
  {"signature",		-1L,DT_MLT,(char *)SIGS},
  {"sleepmsg",		-1L,DT_NUM,(char *)&sleepmsg},
! {"softkeys",		-1L,DT_BOL|FL_OR,(char *)&hp_softkeys},
  {"sort",		-1L,DT_SYN,"sortby"},
  {"sortby",		-1L,DT_SRT,(char *)&sortby},
  {"store",		-1L,DT_SYN,"alwaysstore"},
--- 261,274 ----
  {"saveto",		-1L,DT_SYN,"sentmail"},
  {"sentmail",		-1L,DT_STR,raw_sentmail},
  {"shell",		-1L,DT_STR,raw_shell},
+ #ifdef USE_PGP
+ {"showpgppreamble",	-1L,DT_BOL,(char *)&pgp_noarmor},
+ #endif
+ {"showto",		-1L,DT_BOL,(char *)&showto},
  {"sigdashes",		-1L,DT_BOL,(char *)&sig_dashes},
  {"signature",		-1L,DT_MLT,(char *)SIGS},
  {"sleepmsg",		-1L,DT_NUM,(char *)&sleepmsg},
!   /* {"softkeys",		-1L,DT_BOL|FL_OR,(char *)&hp_softkeys}, */
  {"sort",		-1L,DT_SYN,"sortby"},
  {"sortby",		-1L,DT_SRT,(char *)&sortby},
  {"store",		-1L,DT_SYN,"alwaysstore"},
***************
*** 239,252 ****
  #ifdef MIME
  {"textencoding", -1L,DT_STR,text_encoding},
  #endif
! {"timeout",		-1L,DT_NUM,(char *)&timeout},
  {"titles",		-1L,DT_BOL,(char *)&title_messages},
  {"tmpdir",		-1L,DT_STR,raw_temp_dir},
  {"userlevel",		-1L,DT_NUM,(char *)&user_level},
  {"username",		-1L,DT_SYN,"fullname"},
  {"usetite",		-1L,DT_BOL|FL_AND,(char *)&use_tite},
  {"visualeditor",	-1L,DT_STR,v_editor},
! {"weed",		-1L,DT_BOL,(char *)&filter},
  {"weedout",		-1L,DT_WEE,(char *)weedlist},
  };
  int NUMBER_OF_SAVEABLE_OPTIONS=(sizeof(save_info_data)/sizeof(save_info_recs_init));
--- 275,291 ----
  #ifdef MIME
  {"textencoding", -1L,DT_STR,text_encoding},
  #endif
! {"timeout",		-1L,DT_NUM,(char *)&elm_timeout},
  {"titles",		-1L,DT_BOL,(char *)&title_messages},
  {"tmpdir",		-1L,DT_STR,raw_temp_dir},
+ #ifdef USE_PGP
+ {"usepgppass",          -1L,DT_BOL,(char *)&pgp_keeppass},
+ #endif
  {"userlevel",		-1L,DT_NUM,(char *)&user_level},
  {"username",		-1L,DT_SYN,"fullname"},
  {"usetite",		-1L,DT_BOL|FL_AND,(char *)&use_tite},
  {"visualeditor",	-1L,DT_STR,v_editor},
! {"weed",		-1L,DT_BOL,(char *)&elm_filter},
  {"weedout",		-1L,DT_WEE,(char *)weedlist},
  };
  int NUMBER_OF_SAVEABLE_OPTIONS=(sizeof(save_info_data)/sizeof(save_info_recs_init));
Index: WORK/hdrs/sysdefs.SH
*** elm2.4.25/hdrs/sysdefs.SH	Thu Dec 24 21:24:11 1992
--- WORK/hdrs/sysdefs.SH	Mon Jun  3 20:16:34 1996
***************
*** 54,60 ****
  
  /**  System level, configurable, defines for the ELM mail system.  **/
  
- 
  #define MAX_IN_WEEDLIST 150	/* max headers to weed out               */
  
  #define MAX_HOPS	35	/* max hops in return addr to E)veryone  */
--- 54,59 ----
***************
*** 81,86 ****
--- 80,86 ----
  #define system_text_file        "$lib/aliases.text"
  #define system_data_file        "$lib/aliases"
  #define system_rc_file		"$lib/elm.rc"
+ #define system_mime_types	"$lib/elm.mimetypes"
  
  #define ALIAS_TEXT		".elm/aliases.text"
  #define ALIAS_DATA		".elm/aliases"
Index: WORK/lib/Makefile.SH
*** elm2.4.25/lib/Makefile.SH	Tue Aug  3 22:28:46 1993
--- WORK/lib/Makefile.SH	Mon Jun  3 20:16:38 1996
***************
*** 172,178 ****
  # DACSNET	=	-DACSNET
  
  #	Other general variables
! CFLAGS		=	$(CCFLAGS) $(OPTIMIZE) -I$(INCLDIR) $(DEBUG) $(DACSNET) 
  INCLDIR		=	../hdrs
  LINTFLAGS	=	-I$(INCLDIR)
  SHELL		=	/bin/sh
--- 172,178 ----
  # DACSNET	=	-DACSNET
  
  #	Other general variables
! CFLAGS		=	-I$(INCLDIR) $(CCFLAGS) $(OPTIMIZE) $(DEBUG) $(DACSNET) 
  INCLDIR		=	../hdrs
  LINTFLAGS	=	-I$(INCLDIR)
  SHELL		=	/bin/sh
***************
*** 188,193 ****
--- 188,195 ----
  			can_open.c	\
  			chloc.c		\
  			date_util.c	\
+ 			dispaddr.c	\
+ 			dynarray.c	\
  			errno.c		\
  			expand.c	\
  			figadrssee.c	\
***************
*** 195,200 ****
--- 197,203 ----
  			getaddrfrm.c	\
  			getarpdate.c	\
  			getfullnam.c	\
+ 			getrealname.c	\
  			getword.c	\
  			get_tz.c	\
  			header_cmp.c	\
***************
*** 225,233 ****
  			striparens.c	\
  			$(STRSRC)	\
  			$(FTIMESRC)	\
  			strtokq.c	\
  			tail_of.c	\
! 			validname.c
  
  LIB_OBJ		=	add_site.o	\
  			addrmchusr.o	\
--- 228,238 ----
  			striparens.c	\
  			$(STRSRC)	\
  			$(FTIMESRC)	\
+ 			strmcpy.c	\
  			strtokq.c	\
  			tail_of.c	\
! 			validname.c	\
! 			safeopen.c
  
  LIB_OBJ		=	add_site.o	\
  			addrmchusr.o	\
***************
*** 239,244 ****
--- 244,251 ----
  			can_open.o	\
  			chloc.o		\
  			date_util.o	\
+ 			dispaddr.o	\
+ 			dynarray.o	\
  			errno.o		\
  			expand.o	\
  			figadrssee.o	\
***************
*** 247,252 ****
--- 254,260 ----
  			getaddrfrm.o	\
  			getarpdate.o	\
  			getfullnam.o	\
+ 			getrealname.o	\
  			getword.o	\
  			header_cmp.o	\
  			in_list.o	\
***************
*** 276,284 ****
  			striparens.o	\
  			$(STROBJ)	\
  			$(FTIMEOBJ)	\
  			strtokq.o	\
  			tail_of.o	\
! 			validname.o
  
  all:			libutil.a
  
--- 284,294 ----
  			striparens.o	\
  			$(STROBJ)	\
  			$(FTIMEOBJ)	\
+ 			strmcpy.o	\
  			strtokq.o	\
  			tail_of.o	\
! 			validname.o	\
! 			safeopen.o
  
  all:			libutil.a
  
***************
*** 326,331 ****
--- 336,342 ----
  can_open.o:	$(INCLDIR)/headers.h
  chloc.o:	$(INCLDIR)/headers.h
  date_util.o:	$(INCLDIR)/headers.h
+ dispaddr.o:     $(INCLDIR)/headers.h
  errno.o:	$(INCLDIR)/headers.h
  expand.o:	$(INCLDIR)/defs.h $(INCLDIR)/s_elmrc.h
  figadrssee.o:	$(INCLDIR)/headers.h
Index: WORK/lib/can_open.c
*** elm2.4.25/lib/can_open.c	Mon Aug 23 05:46:08 1993
--- WORK/lib/can_open.c	Mon Jun  3 20:16:39 1996
***************
*** 83,88 ****
--- 83,99 ----
  	  setgid(groupid);
  	  setuid(userid);		/** back to normal userid **/
  	  errno = 0;
+ 	  if (mode[0] == 's' && mode[1] == 'w' && ! mode[2]) {
+ 	      int filedes = open(file, O_WRONLY | O_CREAT | O_EXCL, 0600);
+ 	      if (filedes < 0 &&
+ 		  (unlink(file) ||
+ 		   (filedes = open(file, O_WRONLY|O_CREAT|O_EXCL, 0600)) < 0))
+ 		  _exit(errno);
+ 	      else {
+ 		  close(filedes);
+ 		  _exit(0);
+ 	      }
+ 	  }
  	  if (access(file, ACCESS_EXISTS) == 0)
  	    preexisted = 1;
  	  if ((fd = fopen(file, mode)) == NULL)
Index: WORK/lib/date_util.c
*** elm2.4.25/lib/date_util.c	Tue Aug  3 22:28:48 1993
--- WORK/lib/date_util.c	Mon Jun  3 20:16:39 1996
***************
*** 216,223 ****
  int month, dayofmon, year, *dayofyear_p;
  {
      /*
!      * Convert numeric month, day of month, and year to day of year
!      * (Jan 1 = 0).  Always returns TRUE.
       */
  
      int dayofyear, i;
--- 216,223 ----
  int month, dayofmon, year, *dayofyear_p;
  {
      /*
!      * Convert numeric month (1-12), day of month (1-31), and year (with
!      * century) to day of year (Jan 1 = 0).  Always returns TRUE.
       */
  
      int dayofyear, i;
***************
*** 411,417 ****
  int year, month, day, hours, mins, secs;
  {
      /*
!      * Convert date specification to seconds since epoch (1 Jan 1970 00:00).
       */
  
      long days_since_epoch, secs_since_midnight;
--- 411,418 ----
  int year, month, day, hours, mins, secs;
  {
      /*
!      * Convert date specification (year with century, month 1-12, day 1-31,
!      * and HH:MM:SS) to seconds since epoch (1 Jan 1970 00:00).
       */
  
      long days_since_epoch, secs_since_midnight;
Index: WORK/lib/dispaddr.c
*** /tmp/null.14101	Tue Aug 20 22:05:34 1996
--- WORK/lib/dispaddr.c	Mon Jun  3 20:16:39 1996
***************
*** 0 ****
--- 1,73 ----
+ /* $Id: dispaddr.c,v 1.3 1995/07/13 18:06:01 elkins Exp $
+  *
+  * $Log: dispaddr.c,v $
+  * Revision 1.3  1995/07/13  18:06:01  elkins
+  * DisplayAddress() now returns the "real name" part of the address if
+  * it is availible.
+  *
+  * Revision 1.2  1995/07/13  02:36:15  elkins
+  * fixed problem where messages in the =sent folder didn't print who the
+  * message was TO.
+  *
+  * Revision 1.1  1995/06/01  23:13:15  elkins
+  * Initial revision
+  *
+  */
+ 
+ /* NOTICE: h->from includes Full name of Sender
+  *          h->to and h->cc includes to and cc headers
+  *
+  *         If h->from contains address is is taken from "From " -line and
+  *         it don't anyway then include sender!
+  *
+  *         - K E H <hurtta@dionysos.FMi.FI>
+  */
+ 
+ #include "headers.h"
+ #include "me.h"
+ 
+ int
+ DisplayAddress (h, f, size)
+      struct header_rec *h;
+      char *f;
+      int size;
+ {
+   int i = 0, using_to = 0;
+ 
+   if ('\0' == h->to[0]) {
+     /* No To: address, must select From: address anyway.... */
+     strfcpy (f, h->from, size);
+     return using_to;
+   }
+ 
+   if (addr_matches_user (h->from, username) ||
+       /* addr_matches_user isn't needed here. This does not still
+        * take care from h->from is MIME encoded (RFC 1522) and
+        * full_username isn't
+        */
+       0 == strincmp(h->from, full_username,STRING)) {
+ 
+     /* I sent this message.  Use the TO address.  
+      * (perhaps I have also receiver... hmm.)
+      */
+     
+     get_real_name (h->to,f, size);
+     using_to = TRUE;
+   }
+   /* This does not take care when h->from is fullname -- not address.... */
+   else if (okay_address(h->to, h->from) && okay_address(h->cc, h->from)) {
+ 
+     /* This message is not addressed to me. */
+ 
+     if (showto) {
+       get_real_name (h->to,f,size);
+       using_to = 1;
+     } else
+       strfcpy (f, h->from,size);
+   }
+   else /* This message is addressed to me (or sender of mail). */
+     strfcpy (f, h->from, size);
+ 
+   return(using_to);
+ }
+ 
Index: WORK/lib/dynarray.c
*** /tmp/null.14101	Tue Aug 20 22:05:34 1996
--- WORK/lib/dynarray.c	Mon Jun  3 20:16:39 1996
***************
*** 0 ****
--- 1,60 ----
+ /* $Id: dynarray.c,v 1.2 1995/06/14 05:34:36 elkins Exp elkins $
+  *
+  * $Log: dynarray.c,v $
+  * Revision 1.2  1995/06/14 05:34:36  elkins
+  * fixed bug where DestroyDynamicArray will seg fault if exactly *max+n
+  * elements were allocated.
+  * From: weo@recco.de (Wolfgang Ocker)
+  *
+  * Revision 1.1  1995/06/01  23:14:35  elkins
+  * Initial revision
+  *
+  */
+ 
+ /** routines for handling of dynamic arrays **/
+ 
+ char **
+ DynamicArray (p, record_size, max, n)
+ char **p;
+ int record_size;
+ int *max;
+ int n;
+ {
+ 	int newmax, j;
+ 	char **c;
+ 
+ 	newmax = *max + n;
+ 
+ 	if (!p)
+ 		c = (char**)safe_malloc(record_size * (n+1));
+ 	else
+ 		c = (char**)safe_realloc(p, record_size * (newmax+1));
+ 
+ 	if (!c)
+ 		return(0);
+ 
+ 	/* We reserver in above (newmax+1) elements --
+ 	 * element c[newmax] must be always NULL so DestroyDynamicArray
+ 	 * works.
+ 	 */
+ 	for (j = *max ; j <= newmax ; j++)
+ 		c[j] = 0;
+ 
+ 	*max = newmax;
+ 
+ 	return(c);
+ }
+ 
+ void
+ DestroyDynamicArray (p)
+ char **p;
+ {
+ 	char **b;
+ 
+ 	if (!p)
+ 		return;
+ 	b = p;
+ 	while (*b)
+ 		free(*b++);
+ 	free(p);
+ }
Index: WORK/lib/errno.c
*** elm2.4.25/lib/errno.c	Thu Sep  1 22:42:07 1994
--- WORK/lib/errno.c	Mon Jun  3 20:16:39 1996
***************
*** 42,47 ****
--- 42,48 ----
  **/
  
  #include "headers.h"
+ #include "me.h"
  
  #ifndef STRERROR
  #ifdef ERRLST
Index: WORK/lib/get_tz.c
*** elm2.4.25/lib/get_tz.c	Mon May 30 19:53:43 1994
--- WORK/lib/get_tz.c	Mon Jun  3 20:16:40 1996
***************
*** 96,106 ****
  	time(&tval);
  
  	tm = localtime(&tval);
! 	t1 = make_gmttime(tm->tm_year, tm->tm_mon, tm->tm_mday,
  		tm->tm_hour, tm->tm_min, tm->tm_sec);
  
  	tm = gmtime(&tval);
! 	t2 = make_gmttime(tm->tm_year, tm->tm_mon, tm->tm_mday,
  		tm->tm_hour, tm->tm_min, tm->tm_sec);
  
  	return (int) ((t2-t1)/60);
--- 96,106 ----
  	time(&tval);
  
  	tm = localtime(&tval);
! 	t1 = make_gmttime(1900+tm->tm_year, 1+tm->tm_mon, tm->tm_mday,
  		tm->tm_hour, tm->tm_min, tm->tm_sec);
  
  	tm = gmtime(&tval);
! 	t2 = make_gmttime(1900+tm->tm_year, 1+tm->tm_mon, tm->tm_mday,
  		tm->tm_hour, tm->tm_min, tm->tm_sec);
  
  	return (int) ((t2-t1)/60);
Index: WORK/lib/getrealname.c
*** /tmp/null.14101	Tue Aug 20 22:05:34 1996
--- WORK/lib/getrealname.c	Mon Jun  3 20:16:40 1996
***************
*** 0 ****
--- 1,49 ----
+ /* $Id: getrealname.c,v 1.2 1995/08/02 17:52:27 elkins Exp $
+  *
+  * This code originally written by Michael Elkins <elkins@aero.org>
+  *
+  * $Log: getrealname.c,v $
+  * Revision 1.2  1995/08/02  17:52:27  elkins
+  * older BSD systems need <ctype.h>
+  * From: Michael Finken <finken@conware.de>
+  *
+  * Revision 1.1  1995/07/13  18:07:32  elkins
+  * Initial revision
+  *
+  */
+ 
+ #include "headers.h"
+ #include "me.h"
+ 
+ /* copies the "real name" part of s to d */
+ 
+ void
+ get_real_name (s, d, size)
+      char *s, *d;
+      int size;
+ {
+   char *p;
+   int i = 0;
+ 
+   if ((p = (char*)strchr(s, '(')) != 0) {
+     p++;
+     while (*p && *p != ')' && i < size-1)
+       d[i++] = *p++;
+     d[i] = '\0';
+   } else {
+     while (*s && (isspace(*s) || *s == '"')) ++s;
+     if (*s == '<') {
+       /* with addresses like "<elkins@aero.org>", use the email address
+          instead of a zero length string (no real name part). */
+       s++;
+       while (*s && *s!='>' && i < size-1)
+         d[i++] = *s++;
+     }
+     else {
+       while (*s && *s != '"' && *s != '<' && i < size-1)
+         d[i++] = *s++;
+     }
+     d[i] = '\0';
+     remove_possible_trailing_spaces(d);
+   }
+ }
Index: WORK/lib/in_list.c
*** elm2.4.25/lib/in_list.c	Sun Oct  4 00:42:24 1992
--- WORK/lib/in_list.c	Mon Jun  3 20:16:40 1996
***************
*** 66,71 ****
--- 66,75 ----
  	    if(strcmp(next_item, lower_target) == 0)
  		return(TRUE);
  
+             if(index(lower_target,'*')!=0){
+ 	      if (globmatch(next_item,lower_target))
+                 return(TRUE);
+             } else
  	    if(strpbrk(lower_target,"!@%:") != NULL) {
  
  	      /* Target is complex */
***************
*** 85,88 ****
--- 89,128 ----
  	    rest_of_list = NULL;
  	}
  	return(FALSE);
+ }
+ 
+ int
+ globmatch (string, pat)
+ char *string, *pat;
+ {
+   char buf[1024];
+   int i=0,j=0,k,offset=0;
+   
+   for (;;) {
+     k=0;
+     while (pat[j]!='*' && pat[j]!='\0') {
+       buf[k++]=pat[j++];
+     }
+     buf[k]='\0';
+ 
+     /* check everything up to the first '*' */
+     if (strncmp(string+offset,buf,i=strlen(buf))!=0)
+       return(FALSE);
+ 
+     /* if we have run out of pattern, then the string matches... */
+     if (pat[j]=='\0' || pat[j+1]=='\0')
+       return(TRUE);
+ 
+     ++j; /* advance to the next 'real' character in the pattern */
+ 
+     /* ffwd to the next real char that matches */
+     while (string[i] != pat[j]) {
+       /* if we still have pattern, but no string, then it doesn't match */
+       if (string[i]=='\0')
+ 	return(FALSE);
+       i++;
+     }
+     offset+=i;
+   }
+   /* not reached */
  }
Index: WORK/lib/istrcmp.c
*** elm2.4.25/lib/istrcmp.c	Tue Aug  3 22:28:51 1993
--- WORK/lib/istrcmp.c	Mon Jun  3 20:16:41 1996
***************
*** 36,41 ****
--- 36,42 ----
  **/
  
  #include "headers.h"
+ #include "me.h"
  
  int
  istrcmp(s1,s2)
Index: WORK/lib/mcprt.c
*** elm2.4.25/lib/mcprt.c	Thu Jun 30 19:44:02 1994
--- WORK/lib/mcprt.c	Mon Jun  3 20:16:41 1996
***************
*** 49,55 ****
  #include "mcprt.h"
  #include "mcprtlib.h"
  
! #ifdef	ANSI_C
  int	MCprintf(char *fmt, ...)
  #else
  int	MCprintf(fmt, va_alist)
--- 49,55 ----
  #include "mcprt.h"
  #include "mcprtlib.h"
  
! #if	ANSI_C &defined(I_STDARG)
  int	MCprintf(char *fmt, ...)
  #else
  int	MCprintf(fmt, va_alist)
***************
*** 71,77 ****
      return len;
  }
  
! #ifdef	ANSI_C
  int	MCfprintf(FILE *fptr, char *fmt, ...)
  #else
  int	MCfprintf(fptr, fmt, va_alist)
--- 71,77 ----
      return len;
  }
  
! #if	ANSI_C &defined(I_STDARG)
  int	MCfprintf(FILE *fptr, char *fmt, ...)
  #else
  int	MCfprintf(fptr, fmt, va_alist)
***************
*** 94,100 ****
      return len;
  }
  
! #ifdef	ANSI_C
  int	MCsprintf(char *cptr, char *fmt, ...)
  #else
  int	MCsprintf(cptr, fmt, va_alist)
--- 94,100 ----
      return len;
  }
  
! #if	ANSI_C &defined(I_STDARG)
  int	MCsprintf(char *cptr, char *fmt, ...)
  #else
  int	MCsprintf(cptr, fmt, va_alist)
Index: WORK/lib/qstrings.c
*** elm2.4.25/lib/qstrings.c	Tue Aug  3 22:28:56 1993
--- WORK/lib/qstrings.c	Mon Jun  3 20:16:48 1996
***************
*** 38,43 ****
--- 38,44 ----
  **/
  
  #include "headers.h"
+ #include "me.h"
  
  char *qstrpbrk(source, keys)
  char *source, *keys;
Index: WORK/lib/strincmp.c
*** elm2.4.25/lib/strincmp.c	Tue Aug  3 22:28:58 1993
--- WORK/lib/strincmp.c	Mon Jun  3 20:16:50 1996
***************
*** 36,41 ****
--- 36,42 ----
  **/
  
  #include "headers.h"
+ #include "me.h"
  
  int
  strincmp(s1,s2,n)
Index: WORK/lib/strmcpy.c
*** /tmp/null.14101	Tue Aug 20 22:05:34 1996
--- WORK/lib/strmcpy.c	Mon Jun  3 20:16:50 1996
***************
*** 0 ****
--- 1,17 ----
+ #include "headers.h"
+ #include "me.h"
+ 
+ char *
+ strmcpy (dest, src)
+ 	char *dest, *src;
+ {
+ 	int len = strlen (src) + 1;
+ 
+ 	if (dest)
+ 		dest = (char *) safe_realloc (dest, len);
+ 	else
+ 		dest = (char *) safe_malloc (len);
+ 	strcpy (dest, src);
+ 	return dest;
+ }
+ 
Index: WORK/lib/tail_of.c
*** elm2.4.25/lib/tail_of.c	Sun Oct  4 00:42:30 1992
--- WORK/lib/tail_of.c	Mon Jun  3 20:16:51 1996
***************
*** 105,110 ****
--- 105,113 ----
  	  } else
  	    strcpy(buffer, full_username);
  
+ 	} else if (showto && to != 0 && strcmp (to, username) != 0) {
+ 		tail_of (to, buffer, (char *)0);
+ 		using_to = 1;
  	} else {					/* user%host@host? */
  
  	  /** The logic here is that we're going to use 'loc' as a handy
Index: WORK/nls/C/C/C/s_elm.m
*** elm2.4.25/nls/C/C/C/s_elm.m	Tue Aug  3 21:58:06 1993
--- WORK/nls/C/C/C/s_elm.m	Sat Aug 10 20:53:28 1996
***************
*** 1000,1010 ****
  \t -dn\t\tDebug - set debug level to 'n'\n\r\
  \t -fx\t\tFolder - read folder 'x' rather than incoming mailbox\n\r\
  \t -h \t\tHelp - give this list of options\n\r\
! \t -ix\t\tInclude prepared file 'x' in edit buffer for send\n\r\
! \t -k \t\tKeypad - enable HP 2622 terminal keyboard\n\r
  $ #ArgsHelp2
! 536	\t -K \t\tKeypad&softkeys - enable use of softkeys + "-k"\n\r\
! \t -m \t\tMenu - Turn off menu, using more of the screen\n\r\
  \t -sx\t\tSubject 'x' - for batch mailing\n\r\
  \t -t \t\tTiTe - don't use termcap/terminfo ti/te entries.\n\r\
  \t -V \t\tEnable sendmail voyeur mode.\n\r\
--- 1000,1008 ----
  \t -dn\t\tDebug - set debug level to 'n'\n\r\
  \t -fx\t\tFolder - read folder 'x' rather than incoming mailbox\n\r\
  \t -h \t\tHelp - give this list of options\n\r\
! \t -ix\t\tInclude prepared file 'x' in edit buffer for send\n\r
  $ #ArgsHelp2
! 536	\t -m \t\tMenu - Turn off menu, using more of the screen\n\r\
  \t -sx\t\tSubject 'x' - for batch mailing\n\r\
  \t -t \t\tTiTe - don't use termcap/terminfo ti/te entries.\n\r\
  \t -V \t\tEnable sendmail voyeur mode.\n\r\
***************
*** 1614,1616 ****
--- 1612,1618 ----
  847	Message kept.  Can be restored at next f)orward, m)ail or r)eply.
  $ #VfyNoFieldsInForm
  848	No fields in form!\007
+ $ #HelpViewAttach
+ 849	v = View Attachments in current message.
+ $ #BadModeInElmrc
+ 850	I can't understand file permissions "%s" in line %d in your ".elm/elmrc" file\n\r
Index: WORK/nls/Makefile
*** elm2.4.25/nls/Makefile	Thu Mar 10 19:21:47 1994
--- WORK/nls/Makefile	Mon Jun  3 20:17:10 1996
***************
*** 8,13 ****
--- 8,14 ----
  HFILES=	$(HDIR)/s_aliases.h \
  	$(HDIR)/s_answer.h \
  	$(HDIR)/s_elm.h \
+ 	$(HDIR)/s_elmalias.h \
  	$(HDIR)/s_elmrc.h \
  	$(HDIR)/s_error.h \
  	$(HDIR)/s_fastmail.h \
***************
*** 20,25 ****
--- 21,27 ----
  MFILES=	$(SDIR)/s_aliases.m \
  	$(SDIR)/s_answer.m \
  	$(SDIR)/s_elm.m \
+ 	$(SDIR)/s_elmalias.m \
  	$(SDIR)/s_elmrc.m \
  	$(SDIR)/s_error.m \
  	$(SDIR)/s_fastmail.m \
Index: WORK/nls/gencat/gencat.c
*** elm2.4.25/nls/gencat/gencat.c	Mon Aug 23 05:46:29 1993
--- WORK/nls/gencat/gencat.c	Mon Jun  3 20:17:11 1996
***************
*** 68,74 ****
  #if ANSI_C || defined(__cplusplus)
  # define P_(x) x
  #else
! # define P_(x) /**/
  #endif
  
  static void writeIfChanged P_((char *fname, int lang, int orConsts));
--- 68,74 ----
  #if ANSI_C || defined(__cplusplus)
  # define P_(x) x
  #else
! # define P_(x) ()
  #endif
  
  static void writeIfChanged P_((char *fname, int lang, int orConsts));
Index: WORK/nls/gencat/gencat.h
*** elm2.4.25/nls/gencat/gencat.h	Mon Aug 23 05:46:29 1993
--- WORK/nls/gencat/gencat.h	Mon Jun  3 20:17:11 1996
***************
*** 86,92 ****
  #if ANSI_C || defined(__cplusplus)
  # define P_(x) x
  #else
! # define P_(x) /**/
  #endif
  
  extern void MCAddSet P_((int setId, char *c));
--- 86,92 ----
  #if ANSI_C || defined(__cplusplus)
  # define P_(x) x
  #else
! # define P_(x) ()
  #endif
  
  extern void MCAddSet P_((int setId, char *c));
Index: WORK/src/Makefile.SH
*** elm2.4.25/src/Makefile.SH	Thu Dec 24 23:42:05 1992
--- WORK/src/Makefile.SH	Sat Aug 10 16:22:34 1996
***************
*** 78,84 ****
  
  #	Other general variables
  BIN		=	../bin
! CFLAGS		=	$(CCFLAGS) $(OPTIMIZE) -I$(INCLDIR) $(DEBUG) $(DACSNET) 
  INCLDIR		=	../hdrs
  LINTFLAGS	=	-I$(INCLDIR)
  SHELL		=	/bin/sh
--- 78,84 ----
  
  #	Other general variables
  BIN		=	../bin
! CFLAGS		=	-I$(INCLDIR) $(CCFLAGS) $(OPTIMIZE) $(DEBUG) $(DACSNET) 
  INCLDIR		=	../hdrs
  LINTFLAGS	=	-I$(INCLDIR)
  SHELL		=	/bin/sh
***************
*** 92,99 ****
  			a_screen.c	\
  			a_sort.c	\
  			a_quit.c	\
  			bouncebk.c	\
! 			builtin.c	\
  			calendar.c	\
  			curses.c	\
  			date.c		\
--- 92,100 ----
  			a_screen.c	\
  			a_sort.c	\
  			a_quit.c	\
+ 			attach_menu.c	\
  			bouncebk.c	\
! 			builtin++.c	\
  			calendar.c	\
  			curses.c	\
  			date.c		\
***************
*** 118,133 ****
--- 119,143 ----
  			limit.c		\
  			mailmsg1.c	\
  			mailmsg2.c	\
+ 			menu.c		\
+ 			menu2.c		\
+ 			metapager.c	\
  			mime.c		\
+ 			mime_decode.c	\
+ 			mime_encode.c	\
+ 			mime_parse.c	\
+ 			parse_util.c	\
  			mkhdrs.c	\
  			newmbox.c	\
  			options.c	\
  			out_utils.c	\
  			pattern.c	\
+ 			pgp.c		\
  			pmalloc.c	\
  			quit.c		\
  			read_rc.c	\
  			remail.c	\
+ 			remailer.c	\
  			reply.c		\
  			returnadd.c	\
  			save_opts.c	\
***************
*** 136,143 ****
  			showmsg.c	\
  			showmsg_c.c	\
  			signals.c	\
- 			softkeys.c	\
  			sort.c		\
  			string2.c	\
  			strings.c	\
  			syscall.c	\
--- 146,153 ----
  			showmsg.c	\
  			showmsg_c.c	\
  			signals.c	\
  			sort.c		\
+ 			state.c		\
  			string2.c	\
  			strings.c	\
  			syscall.c	\
***************
*** 144,160 ****
  			utils.c		\
  			wildcards.c	\
  			wordwrap.c
  
  ELM_OBJ		=	addr_util.o	\
  			alias.o		\
  			aliaslib.o	\
  			args.o		\
  			a_edit.o	\
  			a_screen.o	\
  			a_sort.o	\
  			a_quit.o	\
  			bouncebk.o	\
! 			builtin.o	\
  			calendar.o	\
  			curses.o	\
  			date.o		\
--- 154,172 ----
  			utils.c		\
  			wildcards.c	\
  			wordwrap.c
+ #			softkeys.c	
  
  ELM_OBJ		=	addr_util.o	\
  			alias.o		\
  			aliaslib.o	\
  			args.o		\
+ 			attach_menu.o	\
  			a_edit.o	\
  			a_screen.o	\
  			a_sort.o	\
  			a_quit.o	\
  			bouncebk.o	\
! 			builtin++.o	\
  			calendar.o	\
  			curses.o	\
  			date.o		\
***************
*** 179,194 ****
--- 191,215 ----
  			limit.o		\
  			mailmsg1.o	\
  			mailmsg2.o	\
+ 			menu.o		\
+ 			menu2.o		\
+ 			metapager.o	\
  			mime.o		\
+ 			mime_decode.o	\
+ 			mime_encode.o   \
+ 			mime_parse.o	\
+ 			parse_util.o	\
  			mkhdrs.o	\
  			newmbox.o	\
  			options.o	\
  			out_utils.o	\
  			pattern.o	\
+ 			pgp.o		\
  			pmalloc.o	\
  			quit.o		\
  			read_rc.o	\
  			remail.o	\
+ 			remailer.o	\
  			reply.o		\
  			returnadd.o	\
  			save_opts.o	\
***************
*** 197,204 ****
  			showmsg.o	\
  			showmsg_c.o	\
  			signals.o	\
- 			softkeys.o	\
  			sort.o		\
  			string2.o	\
  			strings.o	\
  			syscall.o	\
--- 218,225 ----
  			showmsg.o	\
  			showmsg_c.o	\
  			signals.o	\
  			sort.o		\
+ 			state.o		\
  			string2.o	\
  			strings.o	\
  			syscall.o	\
***************
*** 205,210 ****
--- 226,232 ----
  			utils.o		\
  			wildcards.o	\
  			wordwrap.o
+ #			softkeys.o	
  
  # Standard targets
  all:		$(BIN)/elm
***************
*** 254,260 ****
  			$(CHMOD) u+w $@
  			$(TOUCH) $@
  
! $(INCLDIR)/headers.h:	$(INCLDIR)/curses.h $(INCLDIR)/defs.h
  			$(CHMOD) u+w $@
  			$(TOUCH) $@
  
--- 276,282 ----
  			$(CHMOD) u+w $@
  			$(TOUCH) $@
  
! $(INCLDIR)/headers.h:	$(INCLDIR)/curses.h $(INCLDIR)/defs.h $(INCLDIR)/mime.h
  			$(CHMOD) u+w $@
  			$(TOUCH) $@
  
***************
*** 267,309 ****
  a_screen.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_aliases.h
  a_sort.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_aliases.h
  a_quit.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_aliases.h
  bouncebk.o:	$(INCLDIR)/headers.h
! builtin.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
  calendar.o:	$(INCLDIR)/headers.h
! curses.o:	$(INCLDIR)/headers.h
  date.o:		$(INCLDIR)/headers.h
  delete.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
  edit.o:		$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
  editmsg.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
! elm.o:		$(INCLDIR)/elm.h $(INCLDIR)/s_elm.h
  encode.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
! exitprog.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
  expires.o:	$(INCLDIR)/headers.h
  file.o:		$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
! file_util.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
! fileio.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
  find_alias.o:	$(INCLDIR)/headers.h
  forms.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
! hdrconfg.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
  help.o:		$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
! in_utils.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
! init.o:		$(INCLDIR)/headers.h $(INCLDIR)/patchlevel.h $(INCLDIR)/s_elm.h
! leavembox.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
! lock.o:		$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
  limit.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h $(INCLDIR)/s_aliases.h
  mailmsg1.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
! mailmsg2.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
! mkhdrs.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
! mime.o:		$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
! newmbox.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
  options.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h $(INCLDIR)/save_opts.h
  out_utils.o:	$(INCLDIR)/headers.h
  pattern.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
  pmalloc.o:	$(INCLDIR)/defs.h $(INCLDIR)/s_elm.h
  quit.o:		$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
  read_rc.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h $(INCLDIR)/save_opts.h
! remail.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
! reply.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
  returnadd.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
  save_opts.o:	$(INCLDIR)/save_opts.h $(INCLDIR)/headers.h $(INCLDIR)/s_elmrc.h
  savecopy.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
--- 289,339 ----
  a_screen.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_aliases.h
  a_sort.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_aliases.h
  a_quit.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_aliases.h
+ attach_menu.o:	$(INCLDIR)/headers.h $(INCLDIR)/me.h
  bouncebk.o:	$(INCLDIR)/headers.h
! builtin++.o:	$(INCLDIR)/headers.h $(INCLDIR)/me.h
  calendar.o:	$(INCLDIR)/headers.h
! curses.o:	$(INCLDIR)/headers.h $(INCLDIR)/me.h
  date.o:		$(INCLDIR)/headers.h
  delete.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
  edit.o:		$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
  editmsg.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
! elm.o:		$(INCLDIR)/elm.h $(INCLDIR)/s_elm.h $(INCLDIR)/me.h
  encode.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
! exitprog.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h $(INCLDIR)/me.h
  expires.o:	$(INCLDIR)/headers.h
  file.o:		$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
! file_util.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h $(INCLDIR)/me.h
! fileio.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h $(INCLDIR)/me.h
  find_alias.o:	$(INCLDIR)/headers.h
  forms.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
! hdrconfg.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h $(INCLDIR)/me.h
  help.o:		$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
! in_utils.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h $(INCLDIR)/me.h
! init.o:		$(INCLDIR)/headers.h $(INCLDIR)/patchlevel.h $(INCLDIR)/s_elm.h $(INCLDIR)/me.h
! leavembox.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h $(INCLDIR)/me.h
  limit.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h $(INCLDIR)/s_aliases.h
+ lock.o:		$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
  mailmsg1.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
! mailmsg2.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h $(INCLDIR)/me.h
! metapager.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h $(INCLDIR)/me.h
! mime.o:		$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h $(INCLDIR)/me.h
! mime_decode.o:   $(INCLDIR)/headers.h $(INCLDIR)/me.h  
! mime_encode.o:   $(INCLDIR)/headers.h $(INCLDIR)/me.h
! mime_parse.o:   $(INCLDIR)/headers.h $(INCLDIR)/me.h
! parse_util.o:   $(INCLDIR)/headers.h $(INCLDIR)/me.h
! mkhdrs.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h $(INCLDIR)/me.h
! newmbox.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h $(INCLDIR)/me.h
  options.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h $(INCLDIR)/save_opts.h
  out_utils.o:	$(INCLDIR)/headers.h
  pattern.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
+ pgp.o:		$(INCLDIR)/headers.h $(INCLDIR)/me.h
  pmalloc.o:	$(INCLDIR)/defs.h $(INCLDIR)/s_elm.h
  quit.o:		$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
  read_rc.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h $(INCLDIR)/save_opts.h
! remail.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h $(INCLDIR)/me.h
! remailer.o:	$(INCLDIR)/headers.h $(INCLDIR)/me.h
! reply.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h $(INCLDIR)/me.h
  returnadd.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
  save_opts.o:	$(INCLDIR)/save_opts.h $(INCLDIR)/headers.h $(INCLDIR)/s_elmrc.h
  savecopy.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
***************
*** 313,324 ****
  signals.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
  softkeys.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
  sort.o:		$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
  string2.o:	$(INCLDIR)/headers.h
  strings.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
! syscall.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
  utils.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
  wildcards.o:	$(INCLDIR)/defs.h
! wordwrap.o:	$(INCLDIR)/headers.h
  
  #	Dependencies and rules for compiling C programs
  $(BIN)/elm:	$& $(ELM_OBJ) ../lib/libutil.a
--- 343,355 ----
  signals.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
  softkeys.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
  sort.o:		$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
+ state.o:	$(INCLDIR)/headers.h $(INCLDIR)/me.h
  string2.o:	$(INCLDIR)/headers.h
  strings.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
! syscall.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h $(INCLDIR)/me.h
  utils.o:	$(INCLDIR)/headers.h $(INCLDIR)/s_elm.h
  wildcards.o:	$(INCLDIR)/defs.h
! wordwrap.o:	$(INCLDIR)/headers.h $(INCLDIR)/me.h
  
  #	Dependencies and rules for compiling C programs
  $(BIN)/elm:	$& $(ELM_OBJ) ../lib/libutil.a
Index: WORK/src/a_quit.c
*** elm2.4.25/src/a_quit.c	Mon Apr 12 05:34:36 1993
--- WORK/src/a_quit.c	Sun Aug  4 23:16:40 1996
***************
*** 87,96 ****
--- 87,98 ----
  	ask_questions = ((!prompt) ? FALSE : question_me);
  
  	/* YES or NO on softkeys */
+ 	/*
  	if (hp_softkeys && ask_questions) {
  	  define_softkeys(YESNO);
  	  softkeys_on();
  	}
+ 	*/
  
  	/* Determine if deleted messages are really to be deleted */
  
***************
*** 113,123 ****
  			"Delete %d aliases? (%c/%c) "),
  			marked_deleted, *def_ans_yes, *def_ans_no);
  	                    
! 	    answer = want_to(buffer, answer, LINES-3, 0);
  	  }
  
  	  if(answer == *def_ans_yes) {
! 	    list = (char **) malloc(marked_deleted*sizeof(*list));
  	    for (i = 0; i < message_count; i++) {
  	      if (ison(aliases[i]->status, DELETED)) {
  		list[to_delete] = aliases[i]->alias;
--- 115,125 ----
  			"Delete %d aliases? (%c/%c) "),
  			marked_deleted, *def_ans_yes, *def_ans_no);
  	                    
! 	    answer = want_to(buffer, answer, elm_LINES-3, 0);
  	  }
  
  	  if(answer == *def_ans_yes) {
! 	    list = (char **) safe_malloc(marked_deleted*sizeof(*list));
  	    for (i = 0; i < message_count; i++) {
  	      if (ison(aliases[i]->status, DELETED)) {
  		list[to_delete] = aliases[i]->alias;
Index: WORK/src/a_screen.c
*** elm2.4.25/src/a_screen.c	Fri Apr 16 06:54:15 1993
--- WORK/src/a_screen.c	Sun Aug  4 23:18:13 1996
***************
*** 73,80 ****
  
  	show_last_error();
  
! 	if (hp_terminal)
! 	  define_softkeys(ALIAS);
  }
  
  alias_title(modified)
--- 73,79 ----
  
  	show_last_error();
  
! 	/* define_softkeys(ALIAS); */
  }
  
  alias_title(modified)
***************
*** 117,137 ****
  	/* Moved from alias.c */
  
  	if (user_level == RANK_AMATEUR) {	/* Give less options  */
! 	  Centerline(LINES-7, catgets(elm_msg_cat, AliasesSet, AliasesRMenuLn1,
  "You can use any of the following commands by pressing the first character;"));
! 	  Centerline(LINES-6, catgets(elm_msg_cat, AliasesSet, AliasesRMenuLn2,
  "a)lias current message, n)ew alias, d)elete or u)ndelete an alias,"));
! 	  Centerline(LINES-5, catgets(elm_msg_cat, AliasesSet, AliasesRMenuLn3,
  "m)ail to alias, or r)eturn to main menu.  To view an alias, press <return>."));
! 	  Centerline(LINES-4, catgets(elm_msg_cat, AliasesSet, AliasesRMenuLn4,
  "j = move down, k = move up, ? = help"));
  	}
  	else {
! 	    Centerline(LINES-7, catgets(elm_msg_cat, AliasesSet, AliasesMenuLn1,
  "Alias commands:  ?=help, <n>=set current to n, /=search pattern"));
! 	    Centerline(LINES-6, catgets(elm_msg_cat, AliasesSet, AliasesMenuLn2,
  "a)lias current message, c)hange, d)elete, e)dit aliases.text, f)ully expand,"));
! 	    Centerline(LINES-5, catgets(elm_msg_cat, AliasesSet, AliasesMenuLn3,
  "l)imit display, m)ail, n)ew alias, r)eturn, t)ag, u)ndelete, or e(x)it"));
  	}
  
--- 116,143 ----
  	/* Moved from alias.c */
  
  	if (user_level == RANK_AMATEUR) {	/* Give less options  */
! 	  Centerline(elm_LINES-7, catgets(elm_msg_cat, AliasesSet, 
! 					  AliasesRMenuLn1,
  "You can use any of the following commands by pressing the first character;"));
! 	  Centerline(elm_LINES-6, catgets(elm_msg_cat, AliasesSet, 
! 					  AliasesRMenuLn2,
  "a)lias current message, n)ew alias, d)elete or u)ndelete an alias,"));
! 	  Centerline(elm_LINES-5, catgets(elm_msg_cat, AliasesSet, 
! 					  AliasesRMenuLn3,
  "m)ail to alias, or r)eturn to main menu.  To view an alias, press <return>."));
! 	  Centerline(elm_LINES-4, catgets(elm_msg_cat, AliasesSet, 
! 					  AliasesRMenuLn4,
  "j = move down, k = move up, ? = help"));
  	}
  	else {
! 	    Centerline(elm_LINES-7, catgets(elm_msg_cat, AliasesSet, 
! 					    AliasesMenuLn1,
  "Alias commands:  ?=help, <n>=set current to n, /=search pattern"));
! 	    Centerline(elm_LINES-6, catgets(elm_msg_cat, AliasesSet, 
! 					    AliasesMenuLn2,
  "a)lias current message, c)hange, d)elete, e)dit aliases.text, f)ully expand,"));
! 	    Centerline(elm_LINES-5, catgets(elm_msg_cat, AliasesSet, 
! 					    AliasesMenuLn3,
  "l)imit display, m)ail, n)ew alias, r)eturn, t)ag, u)ndelete, or e(x)it"));
  	}
  
***************
*** 161,172 ****
  
  	sprintf(buffer, "%s%s%c%-3d ",
  		(highlight && arrow_cursor)? "->" : "  ",
! 		show_status(entry->status),
  		(entry->status & TAGGED?  '+' : ' '),
  		message_number);
  
  	/* Set the name display width. */
! 	name_width = COLUMNS-40;
  
  	/* Put the name and associated comment in local buffer */
  	if (strlen(entry->comment))
--- 167,178 ----
  
  	sprintf(buffer, "%s%s%c%-3d ",
  		(highlight && arrow_cursor)? "->" : "  ",
! 		show_status(entry->status,NULL),
  		(entry->status & TAGGED?  '+' : ' '),
  		message_number);
  
  	/* Set the name display width. */
! 	name_width = elm_COLUMNS-40;
  
  	/* Put the name and associated comment in local buffer */
  	if (strlen(entry->comment))
Index: WORK/src/alias.c
*** elm2.4.25/src/alias.c	Mon May 30 19:42:49 1994
--- WORK/src/alias.c	Mon Aug  5 19:55:48 1996
***************
*** 269,274 ****
--- 269,275 ----
  #include <sys/stat.h>
  #include "s_aliases.h"
  #include "ndbz.h"
+ #include "me.h"
  
  #define	ECHOIT	1 	/* echo on for prompting */
  
***************
*** 524,538 ****
  	  * There is only on alias tagged.  Ask the question
  	  * but the default response is NO.
  	  */
! 	    PutLine0(LINES-2,0, catgets(elm_msg_cat,
! 	            AliasesSet, AliasesOneTagged,
! 	            "There is 1 alias tagged..."));
  	    CleartoEOLN();
  	    MCsprintf(buffer, catgets(elm_msg_cat,
  	            AliasesSet, AliasesCreateGroup,
  	            "Create group alias? (%c/%c) "),
  	        *def_ans_yes, *def_ans_no);
! 	    ch = want_to(buffer, *def_ans_no, LINES-3, 0);
  	}
  	else if (tagged > 1) {
  	 /*
--- 525,539 ----
  	  * There is only on alias tagged.  Ask the question
  	  * but the default response is NO.
  	  */
! 	    PutLine0(elm_LINES-2,0, catgets(elm_msg_cat,
! 					    AliasesSet, AliasesOneTagged,
! 					    "There is 1 alias tagged..."));
  	    CleartoEOLN();
  	    MCsprintf(buffer, catgets(elm_msg_cat,
  	            AliasesSet, AliasesCreateGroup,
  	            "Create group alias? (%c/%c) "),
  	        *def_ans_yes, *def_ans_no);
! 	    ch = want_to(buffer, *def_ans_no, elm_LINES-3, 0);
  	}
  	else if (tagged > 1) {
  	 /*
***************
*** 540,554 ****
  	  * wants to create a group alias.  The default response
  	  * is YES.
  	  */
! 	    PutLine1(LINES-2,0, catgets(elm_msg_cat,
! 	            AliasesSet, AliasesManyTagged,
! 	            "There are %d aliases tagged..."), tagged);
  	    CleartoEOLN();
  	    MCsprintf(buffer, catgets(elm_msg_cat,
  	            AliasesSet, AliasesCreateGroup,
  	            "Create group alias? (%c/%c) "),
  	        *def_ans_yes, *def_ans_no);
! 	    ch = want_to(buffer, *def_ans_yes, LINES-3, 0);
  	}
  
  /*
--- 541,556 ----
  	  * wants to create a group alias.  The default response
  	  * is YES.
  	  */
! 	    PutLine1(elm_LINES-2,0, catgets(elm_msg_cat,
! 					    AliasesSet, AliasesManyTagged,
! 					    "There are %d aliases tagged..."),
! 		     tagged);
  	    CleartoEOLN();
  	    MCsprintf(buffer, catgets(elm_msg_cat,
  	            AliasesSet, AliasesCreateGroup,
  	            "Create group alias? (%c/%c) "),
  	        *def_ans_yes, *def_ans_no);
! 	    ch = want_to(buffer, *def_ans_yes, elm_LINES-3, 0);
  	}
  
  /*
***************
*** 588,594 ****
  	     *  just return.
  	     */
  	        if( ! superceed_system(to_replace, buffer)) {
! 	            ClearLine(LINES-2);
  	            return(0);
  	        }
  	    }
--- 590,596 ----
  	     *  just return.
  	     */
  	        if( ! superceed_system(to_replace, buffer)) {
! 	            ClearLine(elm_LINES-2);
  	            return(0);
  	        }
  	    }
***************
*** 595,609 ****
  	}
  	else {
  	    strcpy(buffer, catgets(elm_msg_cat,
! 	            AliasesSet, AliasesEnterAliasName, "Enter alias name: "));
! 	    PutLine0(LINES-2,0, buffer);
  	    CleartoEOLN();
  	    *aliasname = '\0';
! 	    if ((replace = get_aliasname(aliasname, buffer, &to_replace)) < 0) {
! 	        dprint(3, (debugfile, 
! 	            "Aliasname [%s] was rejected in add_alias\n", aliasname));
! 	        ClearLine(LINES-2);
! 	        return(0);
  	    }
  	}
  
--- 597,619 ----
  	}
  	else {
  	    strcpy(buffer, catgets(elm_msg_cat,
! 				   AliasesSet, AliasesEnterAliasName, 
! 				   "Enter alias name: "));
! 	    PutLine0(elm_LINES-2,0, buffer);
  	    CleartoEOLN();
  	    *aliasname = '\0';
! 
! 	    replace = get_aliasname(aliasname, buffer, &to_replace);
! 	    while (REDRAW_MARK == replace) {
! 	      PutLine0(elm_LINES-2,0, buffer);
! 	      replace = get_aliasname(aliasname, buffer, &to_replace);
! 	    }
! 
! 	    if (replace < 0) {
! 	      dprint(3, (debugfile, 
! 			 "Aliasname [%s] was rejected in add_alias\n", aliasname));
! 	      ClearLine(elm_LINES-2);
! 	      return(0);
  	    }
  	}
  
***************
*** 633,641 ****
   */
  	if (tagged == 0) {
  	    sprintf(buffer, catgets(elm_msg_cat,
! 	            AliasesSet, AliasesEnterAddress,
! 	            "Enter address for %s: "), aliasname);
! 	    PutLine0(LINES-2,0, buffer);
  	    CleartoEOLN();
  	    if (replace) {
  	        strcpy(address1, aliases[to_replace]->address);
--- 643,651 ----
   */
  	if (tagged == 0) {
  	    sprintf(buffer, catgets(elm_msg_cat,
! 				    AliasesSet, AliasesEnterAddress,
! 				    "Enter address for %s: "), aliasname);
! 	    PutLine0(elm_LINES-2,0, buffer);
  	    CleartoEOLN();
  	    if (replace) {
  	        strcpy(address1, aliases[to_replace]->address);
***************
*** 644,657 ****
  	        *address1 = '\0';
  	    }
  	    do {
! 	        optionally_enter(address1, LINES-2, strlen(buffer),
! 	                         FALSE, FALSE);
! 	        Raw(ON);
! 	        if (strlen(address1) == 0) {
! 	            error(catgets(elm_msg_cat, AliasesSet, AliasesNoAddressSpec,
! 	                    "No address specified!"));
! 	            return(0);
! 	        }
  	    } while (check_address(address1) == -1);
  
  	    clear_error();			/* Just in case */
--- 654,679 ----
  	        *address1 = '\0';
  	    }
  	    do {
! 	      int status =
! 	        optionally_enter(address1, elm_LINES-2, strlen(buffer),
! 	                         OE_REDRAW_MARK);
! 
! 	      while (REDRAW_MARK == status) {
! 		sprintf(buffer, catgets(elm_msg_cat,
! 					AliasesSet, AliasesEnterAddress,
! 					"Enter address for %s: "), aliasname);
! 		PutLine0(elm_LINES-2,0, buffer);
! 		status =
! 		  optionally_enter(address1, elm_LINES-2, strlen(buffer),
! 				   OE_REDRAW_MARK|OE_APPEND_CURRENT);
! 	      }
! 
! 	      if (0 != status ||
! 		  strlen(address1) == 0) {
! 		error(catgets(elm_msg_cat, AliasesSet, AliasesNoAddressSpec,
! 			      "No address specified!"));
! 		return(0);
! 	      }
  	    } while (check_address(address1) == -1);
  
  	    clear_error();			/* Just in case */
***************
*** 712,726 ****
  	current_header = headers[current_mail_message - 1];
  	
  	strcpy(buffer, catgets(elm_msg_cat, AliasesSet, AliasesCurrentMessage,
! 		"Current message address aliased to: "));
! 	PutLine0(LINES-2,0, buffer);
  	CleartoEOLN();
  	*aliasname = '\0';
! 	if ((replace = get_aliasname(aliasname, buffer, &to_replace)) < 0) {
  	    dprint(3, (debugfile, 
  	        "Aliasname [%s] was rejected in add_current_alias\n",
  	        aliasname));
! 	    ClearLine(LINES-2);
  	    return(0);
  	}
  
--- 734,753 ----
  	current_header = headers[current_mail_message - 1];
  	
  	strcpy(buffer, catgets(elm_msg_cat, AliasesSet, AliasesCurrentMessage,
! 			       "Current message address aliased to: "));
! 	PutLine0(elm_LINES-2,0, buffer);
  	CleartoEOLN();
  	*aliasname = '\0';
! 	replace = get_aliasname(aliasname, buffer, &to_replace);
! 	while (REDRAW_MARK == replace) {
! 	  PutLine0(elm_LINES-2,0, buffer);
! 	  replace = get_aliasname(aliasname, buffer, &to_replace);
! 	}
! 	if (replace < 0) {
  	    dprint(3, (debugfile, 
  	        "Aliasname [%s] was rejected in add_current_alias\n",
  	        aliasname));
! 	    ClearLine(elm_LINES-2);
  	    return(0);
  	}
  
***************
*** 993,998 ****
--- 1020,1026 ----
  	return(0);
  }
  
+ void
  alias()
  {
  /*
***************
*** 999,1005 ****
   *	Work with alias commands...
   */
  
! 	char name[NLEN], *address, ch, buffer[SLEN];
  	char *commap;
  	int  key_offset;        /** Position offset within keyboard string   **/
  	static int  newaliases = 0;
--- 1027,1034 ----
   *	Work with alias commands...
   */
  
! 	char name[NLEN], *address, buffer[SLEN];
! 	int ch;
  	char *commap;
  	int  key_offset;        /** Position offset within keyboard string   **/
  	static int  newaliases = 0;
***************
*** 1018,1024 ****
  	open_alias_files(FALSE);	/* First, read the alias files. RLH */
  
  	alias_screen(newaliases);
! 	define_softkeys(ALIAS);
  
  	while (1) {
  
--- 1047,1053 ----
  	open_alias_files(FALSE);	/* First, read the alias files. RLH */
  
  	alias_screen(newaliases);
! 	/* define_softkeys(ALIAS); */
  
  	while (1) {
  
***************
*** 1028,1041 ****
  
  	    ScreenSize(&newLINES, &newCOLUMNS);
  	    resize_screen = 0;
! 	    if (newLINES != LINES || newCOLUMNS != COLUMNS) {
! 	      LINES = newLINES, COLUMNS = newCOLUMNS;
  #undef max
  #define max(a,b)	       ((a) < (b) ? (b) : (a))
  	      if (mini_menu)
! 		headers_per_page = max (LINES - 13, 1);
  	      else
! 		headers_per_page = max (LINES -	 8, 1);	  /* 5 more headers! */
  #undef max
  	      redraw++;
  	    }
--- 1057,1070 ----
  
  	    ScreenSize(&newLINES, &newCOLUMNS);
  	    resize_screen = 0;
! 	    if (newLINES != elm_LINES || newCOLUMNS != elm_COLUMNS) {
! 	      elm_LINES = newLINES, elm_COLUMNS = newCOLUMNS;
  #undef max
  #define max(a,b)	       ((a) < (b) ? (b) : (a))
  	      if (mini_menu)
! 		headers_per_page = max (elm_LINES - 13, 1);
  	      else
! 		headers_per_page = max (elm_LINES -	 8, 1);	  /* 5 more headers! */
  #undef max
  	      redraw++;
  	    }
***************
*** 1049,1063 ****
  
  	  prompt(Prompt);
  	  CleartoEOLN();
! 	  ch = ReadCh();
! 	  MoveCursor(LINES-3,strlen(Prompt)); CleartoEOS();
! 	  
! 	  dprint(3, (debugfile, "\n-- Alias command: %c\n\n", ch));
  
  	  switch (ch) {
  	    case '?': redraw += alias_help();			break;
  
! 	    case '$': PutLine0(LINES-3, strlen(Prompt),
  			     catgets(elm_msg_cat, AliasesSet, AliasesResync,
  					"Resynchronize aliases..."));
  	           /*
--- 1078,1101 ----
  
  	  prompt(Prompt);
  	  CleartoEOLN();
! 	  ch = ReadCh(REDRAW_MARK|READCH_CURSOR);
! 	  MoveCursor(elm_LINES-3,strlen(Prompt)); CleartoEOS();
! 
! 	  if (isascii(ch) && isprint(ch)) {
! 	    dprint(4, (debugfile, "-- Alias command: %c [%d]\n",ch,ch));
! 	  } else {
! 	    dprint(4, (debugfile, "-- Alias command: [%d]\n",ch));
! 	  }
  
  	  switch (ch) {
+ 	  case HELP_MARK:
  	    case '?': redraw += alias_help();			break;
  
! 	    case REDRAW_MARK:
! 	    case 'L'&31: redraw++;                              break;
! 
! 
! 	    case '$': PutLine0(elm_LINES-3, strlen(Prompt),
  			     catgets(elm_msg_cat, AliasesSet, AliasesResync,
  					"Resynchronize aliases..."));
  	           /*
***************
*** 1071,1079 ****
  		      }
  		      break;
  
! 	    case 'a': PutLine0(LINES-3, strlen(Prompt),
! 			     catgets(elm_msg_cat, AliasesSet, AliasesAddCurrent,
! 					"Add address from current message..."));
  		      clear_error();
  		      if (add_current_alias()) {
  		          newaliases++;
--- 1109,1118 ----
  		      }
  		      break;
  
! 	    case 'a': PutLine0(elm_LINES-3, strlen(Prompt),
! 			       catgets(elm_msg_cat, AliasesSet, 
! 				       AliasesAddCurrent,
! 				       "Add address from current message..."));
  		      clear_error();
  		      if (add_current_alias()) {
  		          newaliases++;
***************
*** 1083,1089 ****
  
  	    case 'c':
  	              if (current > 0) {
! 	                  PutLine0(LINES-3, strlen(Prompt),
  			      catgets(elm_msg_cat,
  	                              AliasesSet, AliasesReplaceCurrent,
  	                              "Replace current alias in database..."));
--- 1122,1128 ----
  
  	    case 'c':
  	              if (current > 0) {
! 	                  PutLine0(elm_LINES-3, strlen(Prompt),
  			      catgets(elm_msg_cat,
  	                              AliasesSet, AliasesReplaceCurrent,
  	                              "Replace current alias in database..."));
***************
*** 1100,1108 ****
  	              }
  		      break;
  
! 	    case 'e': PutLine1(LINES-3, strlen(Prompt),
! 	                  catgets(elm_msg_cat, AliasesSet, AliasesEdit,
! 	                      "Edit %s..."), ALIAS_TEXT);
  	           /*
  	            * Process aliases.text for deletions, etc.  You
  	            * have to do this *before* checking current because
--- 1139,1147 ----
  	              }
  		      break;
  
! 	    case 'e': PutLine1(elm_LINES-3, strlen(Prompt),
! 			       catgets(elm_msg_cat, AliasesSet, AliasesEdit,
! 				       "Edit %s..."), ALIAS_TEXT);
  	           /*
  	            * Process aliases.text for deletions, etc.  You
  	            * have to do this *before* checking current because
***************
*** 1112,1126 ****
  	              if (edit_aliases_text()) {
  	                  newaliases = 0;
  	              }
- 	              if (cursor_control) {
- 	                  transmit_functions(ON);	/* insurance */
- 	              }
  		      redraw++;
  		      break;
  
  	    case 'm':
  	              if (current > 0) {
! 	                  PutLine0(LINES-3, strlen(Prompt),
  	                      catgets(elm_msg_cat, AliasesSet, AliasesMail,
  	                          "Mail..."));
  	                  redraw += a_sendmsg(TRUE,allow_forms);
--- 1151,1162 ----
  	              if (edit_aliases_text()) {
  	                  newaliases = 0;
  	              }
  		      redraw++;
  		      break;
  
  	    case 'm':
  	              if (current > 0) {
! 	                  PutLine0(elm_LINES-3, strlen(Prompt),
  	                      catgets(elm_msg_cat, AliasesSet, AliasesMail,
  	                          "Mail..."));
  	                  redraw += a_sendmsg(TRUE,allow_forms);
***************
*** 1132,1140 ****
  	              }
  		      break;
  
! 	    case 'n': PutLine0(LINES-3, strlen(Prompt),
! 			     catgets(elm_msg_cat, AliasesSet, AliasesAddNew,
! 					     "Add a new alias to database..."));
  		      clear_error();
  		      if (add_alias(FALSE, -1)) {
  		          newaliases++;
--- 1168,1176 ----
  	              }
  		      break;
  
! 	    case 'n': PutLine0(elm_LINES-3, strlen(Prompt),
! 			       catgets(elm_msg_cat, AliasesSet, AliasesAddNew,
! 				       "Add a new alias to database..."));
  		      clear_error();
  		      if (add_alias(FALSE, -1)) {
  		          newaliases++;
***************
*** 1147,1155 ****
  	    case 'i':
  	    case 'I':
  	    case 'r':
! 	    case 'R': PutLine0(LINES-3, strlen(Prompt),
! 			     catgets(elm_msg_cat, AliasesSet, AliasesAddReturn,
! 					"Return to main menu..."));
  	           /*
  	            * leaving the alias system.  Must check for
  	            * pending deletes, etc.  prompt is set to FALSE
--- 1183,1192 ----
  	    case 'i':
  	    case 'I':
  	    case 'r':
! 	    case 'R': PutLine0(elm_LINES-3, strlen(Prompt),
! 			       catgets(elm_msg_cat, AliasesSet, 
! 				       AliasesAddReturn,
! 				       "Return to main menu..."));
  	           /*
  	            * leaving the alias system.  Must check for
  	            * pending deletes, etc.  prompt is set to FALSE
***************
*** 1176,1188 ****
  
  	              if (current > 0) {
  	                  if (aliases[current-1]->type & GROUP) {
! 	                      PutLine1(LINES-1, 0, catgets(elm_msg_cat,
  	                              AliasesSet, AliasesGroupAlias,
  				      "Group alias: %-60.60s"),
  	                          aliases[current-1]->address);
  		          }
  		          else {
! 	                      PutLine1(LINES-1, 0, catgets(elm_msg_cat,
  	                              AliasesSet, AliasesAliasedAddress,
  				      "Aliased address: %-60.60s"), 
  	                          aliases[current-1]->address);
--- 1213,1225 ----
  
  	              if (current > 0) {
  	                  if (aliases[current-1]->type & GROUP) {
! 	                      PutLine1(elm_LINES-1, 0, catgets(elm_msg_cat,
  	                              AliasesSet, AliasesGroupAlias,
  				      "Group alias: %-60.60s"),
  	                          aliases[current-1]->address);
  		          }
  		          else {
! 	                      PutLine1(elm_LINES-1, 0, catgets(elm_msg_cat,
  	                              AliasesSet, AliasesAliasedAddress,
  				      "Aliased address: %-60.60s"), 
  	                          aliases[current-1]->address);
***************
*** 1196,1204 ****
  		      break;
  
  	    case 'x':
! 	    case 'X': PutLine0(LINES-3, strlen(Prompt),
! 			     catgets(elm_msg_cat, AliasesSet, AliasesAddReturn,
! 					"Return to main menu..."));
  	              exit_alias();
  		      clear_error();
  		      main_state();		/* Done with aliases. */
--- 1233,1242 ----
  		      break;
  
  	    case 'x':
! 	    case 'X': PutLine0(elm_LINES-3, strlen(Prompt),
! 			       catgets(elm_msg_cat, AliasesSet, 
! 				       AliasesAddReturn,
! 				       "Return to main menu..."));
  	              exit_alias();
  		      clear_error();
  		      main_state();		/* Done with aliases. */
***************
*** 1210,1223 ****
  		          clear_error();
  		          strcpy(name, aliases[current-1]->alias);
  		          if (ch == 'F') {
  		              strcpy(buffer, catgets(elm_msg_cat,
! 	                              AliasesSet, AliasesFullyExpanded,
! 				      "Fully expand alias: "));
! 		              PutLine0(LINES-2,0, buffer);
  		              CleartoEOS();
! 		              optionally_enter(name, LINES-2, strlen(buffer),
! 			          FALSE, FALSE);
  		          }
  	                  too_long = FALSE;
  		          address = get_alias_address(name, TRUE, &too_long);
  		          if (address != NULL) {
--- 1248,1276 ----
  		          clear_error();
  		          strcpy(name, aliases[current-1]->alias);
  		          if (ch == 'F') {
+ 			    int status;
+ 			    
  		              strcpy(buffer, catgets(elm_msg_cat,
! 						     AliasesSet, 
! 						     AliasesFullyExpanded,
! 						     "Fully expand alias: "));
! 		              PutLine0(elm_LINES-2,0, buffer);
  		              CleartoEOS();
! 		              status = optionally_enter(name, elm_LINES-2, 
! 					       strlen(buffer),
! 					       OE_REDRAW_MARK);
! 			      while (REDRAW_MARK == status) {
! 				PutLine0(elm_LINES-2,0, buffer);
! 				status = optionally_enter(name, elm_LINES-2, 
! 							  strlen(buffer),
! 							  OE_REDRAW_MARK|
! 							  OE_APPEND_CURRENT);
! 				redraw++;
! 			      }
! 			      if (0 != status)
! 				break;
  		          }
+ 		      redraw2:
  	                  too_long = FALSE;
  		          address = get_alias_address(name, TRUE, &too_long);
  		          if (address != NULL) {
***************
*** 1228,1234 ****
  					  "Aliased address for:\t%s\n\r"),
  	                              name);
  		                  i = 4;
! 		                  while (i < LINES-2) {
  		                      if ((commap = index(address, (int)','))
  	                                          == NULL) {
  		                          PutLine0(i, 4, address);
--- 1281,1287 ----
  					  "Aliased address for:\t%s\n\r"),
  	                              name);
  		                  i = 4;
! 		                  while (i < elm_LINES-2) {
  		                      if ((commap = index(address, (int)','))
  	                                          == NULL) {
  		                          PutLine0(i, 4, address);
***************
*** 1238,1247 ****
  		                      PutLine0(i++, 4, address);
  		                      address = commap+2;
  		                  }
! 	                          PutLine0(LINES-1, 0, catgets(elm_msg_cat,
  	                                  AliasesSet, AliasesPressReturn,
  					  "Press <return> to continue."));
! 			          (void) getchar();
  		                  if (commap == NULL) {
  			              redraw++;
  		                      break;
--- 1291,1303 ----
  		                      PutLine0(i++, 4, address);
  		                      address = commap+2;
  		                  }
! 	                          PutLine0(elm_LINES-1, 0, catgets(elm_msg_cat,
  	                                  AliasesSet, AliasesPressReturn,
  					  "Press <return> to continue."));
! 			          if (REDRAW_MARK == ReadCh(REDRAW_MARK)) {
! 				    redraw++;
! 				    goto redraw2;
! 				  }
  		                  if (commap == NULL) {
  			              redraw++;
  		                      break;
***************
*** 1287,1298 ****
  	    show_current();
  	  else if (nufoot) {
  	    if (mini_menu) {
! 	      MoveCursor(LINES-7, 0);  
                CleartoEOS();
  	      show_alias_menu();
  	    }
  	    else {
! 	      MoveCursor(LINES-4, 0);
  	      CleartoEOS();
  	    }
  	    show_last_error();	/* for those operations that have to
--- 1343,1354 ----
  	    show_current();
  	  else if (nufoot) {
  	    if (mini_menu) {
! 	      MoveCursor(elm_LINES-7, 0);  
                CleartoEOS();
  	      show_alias_menu();
  	    }
  	    else {
! 	      MoveCursor(elm_LINES-4, 0);
  	      CleartoEOS();
  	    }
  	    show_last_error();	/* for those operations that have to
***************
*** 1363,1381 ****
  		alias_prompt = catgets(elm_msg_cat, AliasesSet, AliasesLongKey,
  			"Key you want help for: ");
  
! 	MoveCursor(LINES-3, 0);	CleartoEOS();
  
  	if (mini_menu) {
! 	  Centerline(LINES-3, catgets(elm_msg_cat, AliasesSet, AliasesKeyMenu,
   "Press the key you want help for, '?' for a key list, or '.' to exit help"));
  	}
  
  	lower_prompt(alias_prompt);
  
! 	while ((ch = ReadCh()) != '.') {
  	  switch(ch) {
! 	    case EOF : leave(0);
  	               break;
  	    case '?' : display_helpfile(ALIAS_HELP);	
  		       redraw++;
  		       return(redraw);
--- 1419,1439 ----
  		alias_prompt = catgets(elm_msg_cat, AliasesSet, AliasesLongKey,
  			"Key you want help for: ");
  
! 	MoveCursor(elm_LINES-3, 0);	CleartoEOS();
  
  	if (mini_menu) {
! 	  Centerline(elm_LINES-3, catgets(elm_msg_cat, AliasesSet, 
! 					  AliasesKeyMenu,
   "Press the key you want help for, '?' for a key list, or '.' to exit help"));
  	}
  
  	lower_prompt(alias_prompt);
  
! 	while ((ch = ReadCh(0|READCH_CURSOR)) != '.') {
  	  switch(ch) {
! 	  case EOF : leave(0);
  	               break;
+ 	  case HELP_MARK:
  	    case '?' : display_helpfile(ALIAS_HELP);	
  		       redraw++;
  		       return(redraw);
***************
*** 1384,1389 ****
--- 1442,1448 ----
  "$ = Force resynchronization of aliases, processing additions and deletions."));
  		      break;
  
+ 	  case FIND_MARK:
  	    case '/': error(catgets(elm_msg_cat, AliasesSet, AliasesHelpSlash,
  			"/ = Search for specified name or alias in list."));
  		      break;
***************
*** 1480,1486 ****
  	}
  
  	/* Remove help lines */
! 	MoveCursor(LINES-3, 0);	CleartoEOS();
  	return(redraw);
  }
  
--- 1539,1545 ----
  	}
  
  	/* Remove help lines */
! 	MoveCursor(elm_LINES-3, 0);	CleartoEOS();
  	return(redraw);
  }
  
***************
*** 1730,1746 ****
   *		that the user has chosen to replace.  In this
   *		case the alias to replace is passed back in
   *		in the variable 'duplicate'.
   */
  
  	int loc;
  
  	do {
! 	    optionally_enter(aliasname, LINES-2, strlen(buffer), FALSE, FALSE);
  	/*
  	 *  Return if nothing was entered.
  	 */
! 	    if (strlen(aliasname) == 0) 
! 	        return(-1);
  
  	} while (check_alias(aliasname) == -1);
  
--- 1789,1813 ----
   *		that the user has chosen to replace.  In this
   *		case the alias to replace is passed back in
   *		in the variable 'duplicate'.
+  *
+  *   REDRAW_MARK
   */
  
  	int loc;
  
  	do {
! 	  int status =
! 	    optionally_enter(aliasname, elm_LINES-2, strlen(buffer), 
! 			     OE_REDRAW_MARK);
! 
! 	  if (REDRAW_MARK == status)
! 	    return REDRAW_MARK;
! 
  	/*
  	 *  Return if nothing was entered.
  	 */
! 	  if (0 != status || strlen(aliasname) == 0) 
! 	    return(-1);
  
  	} while (check_alias(aliasname) == -1);
  
***************
*** 1753,1763 ****
  	         "Attempt to add a duplicate alias [%s] in get_aliasname\n",
  	         aliases[loc]->alias)); 
  	    if (aliases[loc]->type & GROUP )
! 	        PutLine1(LINES-2,0, catgets(elm_msg_cat,
  	                AliasesSet, AliasesAlreadyGroup,
  	                "Already a group with name %s."), aliases[loc]->alias);
  	    else
! 	        PutLine1(LINES-2,0, catgets(elm_msg_cat,
  	                AliasesSet, AliasesAlreadyAlias,
  	                "Already an alias for %s."), aliases[loc]->alias);
  	    CleartoEOLN();
--- 1820,1830 ----
  	         "Attempt to add a duplicate alias [%s] in get_aliasname\n",
  	         aliases[loc]->alias)); 
  	    if (aliases[loc]->type & GROUP )
! 	        PutLine1(elm_LINES-2,0, catgets(elm_msg_cat,
  	                AliasesSet, AliasesAlreadyGroup,
  	                "Already a group with name %s."), aliases[loc]->alias);
  	    else
! 	        PutLine1(elm_LINES-2,0, catgets(elm_msg_cat,
  	                AliasesSet, AliasesAlreadyAlias,
  	                "Already an alias for %s."), aliases[loc]->alias);
  	    CleartoEOLN();
***************
*** 1769,1775 ****
  	  * If they don't want to replace the alias by that name
  	  * then just return.
  	  */
! 	    if (want_to(buffer, *def_ans_no, LINES-3, 0) != *def_ans_yes)
  	        return(-1);
  	    *duplicate = loc;
  	    return(1);
--- 1836,1842 ----
  	  * If they don't want to replace the alias by that name
  	  * then just return.
  	  */
! 	    if (want_to(buffer, *def_ans_no, elm_LINES-3, 0) != *def_ans_yes)
  	        return(-1);
  	    *duplicate = loc;
  	    return(1);
***************
*** 1800,1806 ****
  char *buffer;
  {
  
! 	PutLine2(LINES-2, 0, catgets(elm_msg_cat,
  	        AliasesSet, AliasesSystemAlias, "System (%6s) alias for %s."),
  	    alias_type(aliases[this_alias]->type), aliases[this_alias]->alias);
  
--- 1867,1873 ----
  char *buffer;
  {
  
! 	PutLine2(elm_LINES-2, 0, catgets(elm_msg_cat,
  	        AliasesSet, AliasesSystemAlias, "System (%6s) alias for %s."),
  	    alias_type(aliases[this_alias]->type), aliases[this_alias]->alias);
  
***************
*** 1810,1816 ****
   *	If they don't want to superceed the SYSTEM alias then
   *	return a FALSE.
   */
! 	return(want_to(buffer, *def_ans_no, LINES-3, 0) == *def_ans_yes);
  }
  
  void
--- 1877,1883 ----
   *	If they don't want to superceed the SYSTEM alias then
   *	return a FALSE.
   */
! 	return(want_to(buffer, *def_ans_no, elm_LINES-3, 0) == *def_ans_yes);
  }
  
  void
***************
*** 1817,1849 ****
  get_realnames(aliasname, firstname, lastname, comment, buffer)
  char *aliasname, *firstname, *lastname, *comment, *buffer;
  {
! 
  	sprintf(buffer, catgets(elm_msg_cat, AliasesSet, AliasesEnterLastName,
  		"Enter last name for %s: "), aliasname);
! 	PutLine0(LINES-2,0, buffer);
  	CleartoEOLN();
! 	optionally_enter(lastname, LINES-2, strlen(buffer), FALSE, FALSE);
  
  	sprintf(buffer, catgets(elm_msg_cat, AliasesSet, AliasesEnterFirstName,
  		"Enter first name for %s: "), aliasname);
! 	PutLine0(LINES-2,0, buffer);
  	CleartoEOLN();
! 	optionally_enter(firstname, LINES-2, strlen(buffer), FALSE, FALSE);
  
  	if (strlen(lastname) == 0) {
! 	    if (strlen(firstname) == 0) {
! 	        strcpy(lastname, aliasname);  
! 	    }
! 	    else {
! 	        strcpy(lastname, firstname);  
! 	        *firstname = '\0';
! 	    }
  	}
  
  	sprintf(buffer, catgets(elm_msg_cat, AliasesSet, AliasesEnterComment,
  		"Enter optional comment for %s: "), aliasname);
! 	PutLine0(LINES-2,0, buffer);
! 	optionally_enter(comment, LINES-2, strlen(buffer), FALSE, FALSE);
  
  }
  
--- 1884,1934 ----
  get_realnames(aliasname, firstname, lastname, comment, buffer)
  char *aliasname, *firstname, *lastname, *comment, *buffer;
  {
!   int status;
  	sprintf(buffer, catgets(elm_msg_cat, AliasesSet, AliasesEnterLastName,
  		"Enter last name for %s: "), aliasname);
! 	PutLine0(elm_LINES-2,0, buffer);
  	CleartoEOLN();
! 	status = optionally_enter(lastname, elm_LINES-2, strlen(buffer),
! 				  OE_REDRAW_MARK);
! 	while (REDRAW_MARK == status) {
! 	  PutLine0(elm_LINES-2,0, buffer);
! 	  status = optionally_enter(lastname, elm_LINES-2, strlen(buffer),
! 				    OE_REDRAW_MARK|OE_APPEND_CURRENT);
! 	}
  
  	sprintf(buffer, catgets(elm_msg_cat, AliasesSet, AliasesEnterFirstName,
  		"Enter first name for %s: "), aliasname);
! 	PutLine0(elm_LINES-2,0, buffer);
  	CleartoEOLN();
! 	status = optionally_enter(firstname, elm_LINES-2, strlen(buffer), 
! 				  OE_REDRAW_MARK);
! 	while (REDRAW_MARK == status) {
! 	  PutLine0(elm_LINES-2,0, buffer);
! 	  status = optionally_enter(firstname, elm_LINES-2, strlen(buffer), 
! 				    OE_REDRAW_MARK|OE_APPEND_CURRENT);
! 	}
  
  	if (strlen(lastname) == 0) {
! 	  if (strlen(firstname) == 0) {
! 	    strcpy(lastname, aliasname);  
! 	  }
! 	  else {
! 	    strcpy(lastname, firstname);  
! 	    *firstname = '\0';
! 	  }
  	}
  
  	sprintf(buffer, catgets(elm_msg_cat, AliasesSet, AliasesEnterComment,
  		"Enter optional comment for %s: "), aliasname);
! 	PutLine0(elm_LINES-2,0, buffer);
! 	status = optionally_enter(comment, elm_LINES-2, strlen(buffer), 
! 				  OE_REDRAW_MARK);
! 	while (status == REDRAW_MARK) {
! 	  PutLine0(elm_LINES-2,0, buffer);
! 	  status = optionally_enter(comment, elm_LINES-2, strlen(buffer), 
! 				    OE_REDRAW_MARK|OE_APPEND_CURRENT);
! 	}
  
  }
  
***************
*** 1871,1877 ****
  	else {
  	    sprintf(buffer, "%s %s", firstname, lastname);
  	}
! 	PutLine2(LINES-1,0, catgets(elm_msg_cat, AliasesSet, AliasesAddressAs,
  	        "Messages addressed as: %s (%s)"), address, buffer);
  	if (strlen(comment) != 0) {
  	    strcat(buffer, ", ");
--- 1956,1962 ----
  	else {
  	    sprintf(buffer, "%s %s", firstname, lastname);
  	}
! 	PutLine2(elm_LINES-1,0, catgets(elm_msg_cat, AliasesSet, AliasesAddressAs,
  	        "Messages addressed as: %s (%s)"), address, buffer);
  	if (strlen(comment) != 0) {
  	    strcat(buffer, ", ");
***************
*** 1878,1884 ****
  	    strcat(buffer, comment);
  	}
  
! 	PutLine2(LINES-2,0, catgets(elm_msg_cat, AliasesSet, AliasesAddressTo,
  	        "New alias: %s is '%s'."), aliasname, buffer);
  	CleartoEOLN();
  /*
--- 1963,1969 ----
  	    strcat(buffer, comment);
  	}
  
! 	PutLine2(elm_LINES-2,0, catgets(elm_msg_cat, AliasesSet, AliasesAddressTo,
  	        "New alias: %s is '%s'."), aliasname, buffer);
  	CleartoEOLN();
  /*
***************
*** 1888,1894 ****
   */
  	MCsprintf(buffer, catgets(elm_msg_cat, AliasesSet, AliasesAcceptNew,
  		"      Accept new alias? (%c/%c) "), *def_ans_yes, *def_ans_no);
! 	if((ch = want_to(buffer, *def_ans_yes, LINES-3, 0)) == *def_ans_yes) {
  	    if (replace) {
  	        old_alias[0] = aliases[replacement]->alias;
  	    /*
--- 1973,1979 ----
   */
  	MCsprintf(buffer, catgets(elm_msg_cat, AliasesSet, AliasesAcceptNew,
  		"      Accept new alias? (%c/%c) "), *def_ans_yes, *def_ans_no);
! 	if((ch = want_to(buffer, *def_ans_yes, elm_LINES-3, 0)) == *def_ans_yes) {
  	    if (replace) {
  	        old_alias[0] = aliases[replacement]->alias;
  	    /*
***************
*** 1922,1929 ****
  	    }
  	    add_to_alias_text(aliasname, firstname, lastname, comment, address);
  	}
! 	ClearLine(LINES-2);
! 	ClearLine(LINES-1);
  	return(ch == *def_ans_yes ? 1 : 0);
  
  }
--- 2007,2014 ----
  	    }
  	    add_to_alias_text(aliasname, firstname, lastname, comment, address);
  	}
! 	ClearLine(elm_LINES-2);
! 	ClearLine(elm_LINES-1);
  	return(ch == *def_ans_yes ? 1 : 0);
  
  }
Index: WORK/src/args.c
*** elm2.4.25/src/args.c	Mon Apr 12 06:35:24 1993
--- WORK/src/args.c	Sat Aug 10 20:31:39 1996
***************
*** 89,96 ****
  	     case '?' :
  	     case 'h' : args_help();
  	     case 'i' : strcpy(included_file, optarg);	break;
! 	     case 'k' : hp_terminal++;	break;
! 	     case 'K' : hp_terminal++; hp_softkeys++;	break;
  	     case 'm' : mini_menu = 0;	break;
  	     case 's' : strcpy(batch_subject, optarg);	break;
  	     case 't' : use_tite = 0;	break;
--- 89,97 ----
  	     case '?' :
  	     case 'h' : args_help();
  	     case 'i' : strcpy(included_file, optarg);	break;
! 	       /* case 'k' : hp_terminal++;	break;
! 		  case 'K' : hp_terminal++; hp_softkeys++;	break;
! 		  */
  	     case 'm' : mini_menu = 0;	break;
  	     case 's' : strcpy(batch_subject, optarg);	break;
  	     case 't' : use_tite = 0;	break;
***************
*** 160,170 ****
  \t -dn\t\tDebug - set debug level to 'n'\n\r\
  \t -fx\t\tFolder - read folder 'x' rather than incoming mailbox\n\r\
  \t -h \t\tHelp - give this list of options\n\r\
! \t -ix\t\tInclude prepared file 'x' in edit buffer for send\n\r\
! \t -k \t\tKeypad - enable HP 2622 terminal keyboard\n\r"));
  	printf(catgets(elm_msg_cat, ElmSet, ElmArgsHelp2,
! 	  "\t -K \t\tKeypad&softkeys - enable use of softkeys + \"-k\"\n\r\
! \t -m \t\tMenu - Turn off menu, using more of the screen\n\r\
  \t -sx\t\tSubject 'x' - for batch mailing\n\r\
  \t -t \t\tTiTe - don't use termcap/terminfo ti/te entries.\n\r\
  \t -V \t\tEnable sendmail voyeur mode.\n\r\
--- 161,169 ----
  \t -dn\t\tDebug - set debug level to 'n'\n\r\
  \t -fx\t\tFolder - read folder 'x' rather than incoming mailbox\n\r\
  \t -h \t\tHelp - give this list of options\n\r\
! \t -ix\t\tInclude prepared file 'x' in edit buffer for send\n\r"));
  	printf(catgets(elm_msg_cat, ElmSet, ElmArgsHelp2,
! 	  "\t -m \t\tMenu - Turn off menu, using more of the screen\n\r\
  \t -sx\t\tSubject 'x' - for batch mailing\n\r\
  \t -t \t\tTiTe - don't use termcap/terminfo ti/te entries.\n\r\
  \t -V \t\tEnable sendmail voyeur mode.\n\r\
***************
*** 171,176 ****
--- 170,179 ----
  \t -v \t\tPrint out ELM version information.\n\r\
  \t -z \t\tZero - don't enter ELM if no mail is pending\n\r\
  \n\n"));
+ 	/*
+ 	  \t -k \t\tKeypad - enable HP 2622 terminal keyboard\n\r
+ 	  \t -K \t\tKeypad&softkeys - enable use of softkeys + \"-k\"\n\r\
+ 	  */
  	exit(1);
  }
  
***************
*** 218,223 ****
--- 221,240 ----
  
  #ifdef MIME
  	printf("\tSupport Multipurpose Internet Mail Extensions: MIME\n");
+ 
+ #ifdef USE_8BITMIME
+       printf("\tUse 8BIT content_transfer_encoding and -B8BITMIME -option: USE_8BITMIME\n");
+ #else /* USE_8BITMIME */
+       printf("\tDon't use 8BIT content_transfer_encoding with -B8BITMIME -option: not USE_8BITMIME\n");
+ #endif /* USE_8BITMIME */
+ 
+ #ifdef USE_BINARYMIME
+       printf("\tUse BINARY content_transfer_encoding and -BBINARYMIME -option: USE_BINARYMIME");
+ #else /* USE_BINARYMIME */
+       printf("\tDon't use BINARY content_transfer_encoding with -BBINARYMIME -option: not USE_BINARYMIME");
+ #endif /* USE_BINARYMIME */
+       printf(" (This option isn't fully implemented yet.)\n");
+ 
  #else /* MIME */
  	printf("\tIgnore Multipurpose Internet Mail Extensions: not MIME\n");
  #endif /* MIME */
***************
*** 266,271 ****
--- 283,298 ----
  	printf("\tCalendar file feature disabled: not ENABLE_CALENDAR\n");
  #endif /* ENABLE_CALENDAR */
  
+ #ifdef USE_PGP
+ 	printf("\tPGP support enabled: USE_PGP\n");
+ #else
+ 	printf("\tPGP support disabled: not USE_PGP\n");
+ #endif
+ #ifdef USE_REMAILER
+ 	printf("\tRemailer support enabled: USE_REMAILER\n");
+ #else
+ 	printf("\tRemailer support disabled: not USE_REMAILER\n");
+ #endif
  	printf("\n\n");
  	exit(1);
  
Index: WORK/src/attach_menu.c
*** /tmp/null.14101	Tue Aug 20 22:05:34 1996
--- WORK/src/attach_menu.c	Sun Aug  4 20:05:52 1996
***************
*** 0 ****
--- 1,1324 ----
+ #include "headers.h"
+ #include "me.h"
+ 
+ #ifdef MIME
+ #include <sys/errno.h>
+ #include <sys/stat.h>
+ #include <sys/wait.h>
+ /* unistd.h is included in headers.h */
+ 
+ extern int errno;
+ extern int elm_COLUMNS;
+ 
+ static int can_save(filename) 
+      char *filename;
+ {
+   if (access(filename,ACCESS_EXISTS) < 0) {
+     if (errno == ENOENT)
+       return 1;    /* File not exists -- can save ! */
+     return 0;     /* Other error -- don't save with that name ! */
+   } else
+     return 0;    /* File exits -- don't save over ! */
+ }
+ 
+ static FILE * 
+ get_attachment(mail_fd,att)
+      FILE * mail_fd;
+      mime_t *att;
+ {
+   FILE * result = NULL;
+   if (att->pathname) {
+     if (can_open(att->pathname,"r") != 0) {
+       error1 ("%.50s isn't readable by user!", att->pathname);
+       sleep_message();
+       return NULL;
+     }
+ 
+     result = fopen(att->pathname,"r");
+     if (!result) {
+       error1("Can't open attachment: %.50s",att->pathname);
+       sleep_message();
+     }
+   } else if (!mail_fd) {
+       error("Internal error: no parent fd!");
+       sleep_message();
+   } else {
+     result = mail_fd;
+     if (fseek(mail_fd,att->offset,SEEK_SET) != 0) {
+       error("Failed to seek beginning of attachment!");
+       sleep_message();
+       result = NULL;
+     }
+   }
+   return result;
+ }
+ 
+ void close_attachment(mail_fd, tmpfd)
+      FILE * mail_fd, *tmpfd;
+ {
+   if (!tmpfd)
+     return;
+   if (mail_fd != tmpfd)
+     fclose(tmpfd);
+ }
+ 
+ void attachment_copy(att, tmpfd, outfd)
+      FILE *tmpfd, *outfd;
+      mime_t *att;
+ {
+   if (att->pathname) {  /* Already decoded */
+     char buf[VERY_LONG_STRING];
+     int len;
+     while (0 < (len = fread(buf,1,sizeof(buf),tmpfd))) {
+       if (fwrite(buf,1,len,outfd) != len) {
+ 	error("Write error when copying attachment!");
+ 	sleep_message();
+ 	break;
+       }
+     }
+     if (ferror(tmpfd)) {
+       error("Error reading from %.50s",att->pathname);
+       sleep_message();
+     }
+   } else { /* Needs decode */
+     in_state_t state_in;
+     out_state_t state_out;
+ 
+     in_state_clear(&state_in, STATE_in_file);
+     out_state_clear(&state_out, STATE_out_file);
+ 
+     set_out_state_file(outfd,&state_out);
+     state_out.displaying = FALSE;
+     set_in_state_file(tmpfd,&state_in);
+     mime_decode(att,&state_in, &state_out);
+ 
+     in_state_destroy(&state_in);
+     out_state_destroy(&state_out);
+   }
+ }
+ 
+ static void
+ attach_print (att)
+      mime_t *att;
+ {
+   char tempfile[STRING];
+   char buf[VERY_LONG_STRING];
+   
+   sprintf(tempfile,"%selm.%d", temp_dir, getpid());
+ 
+   if (att->type == MIME_TYPE_TEXT && istrcmp(att->subtype,"plain") == 0) {
+     FILE *f_out, *f_in;
+     int ret;
+ 
+     dprint(3,(debugfile,"attach_print: printing directly\n"));
+ 
+     
+     if (!(f_out = safeopen(tempfile))) {
+       error1("Error creating tempfile %s",tempfile);
+       sleep_message();
+       return;
+     }
+ 
+     if (!(f_in = get_attachment(mailfile,att))) {
+       fclose(f_out);
+       unlink(tempfile);
+       return;
+     }
+     attachment_copy(att,f_in,f_out);
+ 
+     (void) elm_chown (tempfile, userid, groupid);
+       
+     fclose(f_out);
+     sprintf(buf, printout, tempfile);
+     ret = system_call(buf,0);
+     if (ret == 0)
+       error("Print job spooled.");
+     else
+       error("Error while printing!");
+     unlink(tempfile);
+     close_attachment(mailfile,f_in);
+   }
+   else if (have_metamail()) {
+     dprint(3,(debugfile,"attach_print: printing via metamail: %s\n",
+ 	      metamail_path));
+     if (att->pathname)
+       sprintf(buf,"%s -m Elm -h -b -c %s/%s %s",
+ 	      metamail_path,TYPE(att->type), att->subtype, att->pathname);
+     else {
+       FILE *fpout;
+ 
+       fpout = safeopen(tempfile);
+ 
+       if (!fpout) {
+ 	error1("Error creating tempfile %s",tempfile);
+ 	sleep_message();
+ 	return;
+       }
+ 
+       (void) elm_chown (tempfile, userid, groupid);
+       fseek(mailfile,att->begin_offset,0);
+       while (ftell(mailfile) < att->offset + att->length) {
+ 	int len = mail_gets(buf,VERY_LONG_STRING,mailfile);
+ 	if (len <= 0) 
+ 	  break; /* Error ? */
+ 	fwrite(buf,1,len,fpout);
+       }
+       /* Option -z cuses that metamail unlinks tempfile */
+       fclose(fpout);
+       sprintf(buf,"%s -m Elm -h -z %s", metamail_path, tempfile);
+     }
+     Raw(OFF);
+     system_call(buf,SY_ENV_METAMAIL);
+     PressAnyKeyToContinue();
+     Raw(ON);
+   }
+   else
+     error("Don't know how to print this type of data!");
+ 
+ }
+ 
+ static void
+ attach_save (a)
+      mime_t *a;
+ {
+   char savefile[STRING], buf[VERY_LONG_STRING], tmp[STRING];
+   int bytes=0, err, is_text;
+   in_state_t state_in;
+   out_state_t state_out;
+   FILE *f_in, *f_out;
+   int code;
+ 
+   in_state_clear(&state_in, STATE_in_file);
+   out_state_clear(&state_out, STATE_out_file);
+ 
+   savefile[0] = '\0';
+   if (a->type == MIME_TYPE_APPLICATION &&
+       istrcmp (a->subtype, "octet-stream") == 0) {
+ 
+     /* See if there is a name=<...> field for the default filename */
+     tmp[0] = '\0';
+     if (a->type_opts &&
+ 	mime_get_param ("name", tmp, a->type_opts, sizeof(tmp))) {
+       char *p = strrchr (tmp, '/');
+       if (p)
+ 	p++;
+       else
+ 	p = tmp;
+       if (can_save(p))
+ 	strfcpy (savefile, p, sizeof (savefile));
+     }
+   }
+ 
+    /* See if there is a filename=<...> field for the default filename */
+   tmp[0] = '\0';
+   if (a->disposition_opts &&
+       mime_get_param ("filename", tmp, a->disposition_opts, sizeof(tmp))) {
+     char *p = strrchr (tmp, '/');
+     if (p)
+       p++;
+     else
+       p = tmp;
+     if (can_save(p))
+       strfcpy (savefile, p, sizeof (savefile));
+   }
+ 
+   ClearLine (elm_LINES-2);
+ 
+ redraw:
+   PutLine0 (elm_LINES-2, 0, "To file: ");
+   code = optionally_enter(savefile, elm_LINES-2, 9, OE_APPEND_CURRENT|
+ 			  OE_REDRAW_MARK);
+   if (REDRAW_MARK == code)
+     goto redraw;
+ 
+   if (code < 0 || 
+       savefile[0]=='\0'){
+     ClearLine(elm_LINES-2);
+     error("Mail not saved.");
+     
+     in_state_destroy(&state_in);
+     out_state_destroy(&state_out);
+     sleep_message();
+     return;
+   }
+ 
+   ClearLine(elm_LINES-2);
+ 
+   
+   if (!(f_in = get_attachment(mailfile,a)))  {
+ 
+     in_state_destroy(&state_in);
+     out_state_destroy(&state_out);
+     return;
+   }
+ 
+   if (can_open (savefile,"w") != 0) {
+     error ("You do not have permission to write that file!");
+     sleep_message();
+ 
+     in_state_destroy(&state_in);
+     out_state_destroy(&state_out);
+ 
+     close_attachment(mailfile,f_in);
+ 
+     return;
+   }
+ 
+   
+   if (! (f_out = fopen(savefile, "w"))) {
+     error ("Error opening file!");
+     sleep_message();
+ 
+     in_state_destroy(&state_in);
+     out_state_destroy(&state_out);
+ 
+     close_attachment(mailfile,f_in);
+     return;
+   }
+ 
+   is_text = is_text_type (TYPE(a->type), a->subtype, a->encoding);
+ 
+   set_in_state_file(f_in,&state_in);
+   set_out_state_file(f_out,&state_out);
+ 
+   state_out.prefix = NULL;
+   state_out.displaying = 0;
+ 
+   if (a->encoding == ENCODING_BASE64 && !a->pathname)
+      base64_decode (&state_in, &state_out, a->length, is_text);
+   else if (a->encoding == ENCODING_QUOTED && !a->pathname)
+      quoted_printable_decode (&state_in, &state_out, a->length, is_text);
+   else {
+     if (a->encoding != ENCODING_NONE && a->encoding != ENCODING_7BIT &&
+ 	a->encoding != ENCODING_8BIT && a->encoding != ENCODING_BINARY
+ 	&& !a->pathname) {
+       error("Unsupported encoding! Decode manually!");
+       sleep_message();
+ 
+       /* save without decoding ! */
+       is_text = 0;  /* We can't suppose it is text before decoding... */
+     }
+     while (bytes < a->length) {
+       int chunk = VERY_LONG_STRING;
+       int len;
+ 
+       if (chunk > a->length - bytes)
+ 	chunk = a->length - bytes;
+       if ((len = state_getl (buf, chunk, &state_in)) <= 0)
+ 	break;
+       bytes += len;
+       if (is_text > 0) { /* replace CRLF with LF */
+ 	if (len >= 2 && buf[len-2] == '\r' && buf[len-1] == '\n') {
+ 	  buf[len-2] = '\n';
+ 	  buf[len-1] = '\0';
+ 	  len--;
+ 	}
+       }
+       state_put(buf,len,&state_out);
+     }
+   }
+ 
+   err = ferror (f_out); 
+   err = err || fclose (f_out) != 0;
+   elm_chown (savefile, userid, groupid);
+ 
+   close_attachment(mailfile,f_in);
+ 
+   if (err)
+     error ("Error saving file!");
+   else
+     error ("Mail saved.");
+ 
+   in_state_destroy(&state_in);
+   out_state_destroy(&state_out);
+   return;
+ }
+ 
+ static int attach_info ();
+ 
+ static void
+ attach_edit (ptr)
+      mime_t *ptr;
+ {
+   int savetime;
+   struct stat sb;
+   char buf[STRING];
+ 
+   if (!ptr->pathname)
+     return;
+ 
+   if (-1 == stat (ptr->pathname, &sb)) {
+     error("Can't stat file!");
+     sleep_message();
+     return;
+   }
+   if (strlen(ptr->pathname) + strlen(editor) > STRING-5)
+     return;
+   savetime = sb.st_mtime;
+   Raw(OFF);
+   sprintf (buf, "%s %s", editor, ptr->pathname);
+   system_call (buf, 0);
+   Raw(ON);
+   if (stat (ptr->pathname, &sb) == -1 || sb.st_mtime != savetime)
+     (void) attach_info (ptr);  /* update the information on this attachment */
+   return;
+ }
+ 
+ static void
+ attach_viewer (a)
+      mime_t *a;
+ {
+   char buf[LONG_STRING];
+ 
+   struct header_rec tmp;
+   FILE *tmpfp = NULL;
+   struct stat sb;
+ 
+   /* The next line is required so that mime_t_clear() doesn't call
+    * mime_destroy() or free() on bad pointers
+    */
+   header_zero(&tmp);
+   mime_t_clear (&tmp.mime_rec);
+     
+   /* So that metapager() doesn't try to do special handling */
+   tmp.status = MIME_MESSAGE;  /* Now I test again MIME_MESSAGE
+ 			       * - K E H   <hurtta@dionysos.FMI.FI>
+ 			       */
+ #ifdef USE_PGP
+     tmp.pgp = 0;
+ #endif
+ 
+   if (a->pathname) {
+     ClearScreen();     /* Extra clear for attach_parse ... */
+ 
+     if (can_open(a->pathname,"r") != 0) {
+       error1 ("%.50s isn't readable by user!", a->pathname);
+       sleep_message();
+       return;
+     }
+ 
+     tmpfp = fopen (a->pathname, "r");
+     if (! tmpfp) {
+       error ("Could not open file for reading!");
+       sleep_message();
+       return;
+     }
+ 
+     tmp.mime_rec.flags = a->flags;
+     tmp.mime_rec.type = a->type;
+     strcpy (tmp.mime_rec.subtype,a->subtype);
+     if (a->type_opts) {
+       tmp.mime_rec.type_opts = strmcpy(tmp.mime_rec.type_opts,a->type_opts);
+     }
+     tmp.mime_rec.notplain = a->notplain;  
+ 
+     tmp.mime_rec.disposition = DISP_INLINE;  /* Show it ! */
+     tmp.offset = tmp.mime_rec.offset = 0;
+     tmp.mime_rec.encoding = ENCODING_7BIT;
+     stat(a->pathname, &sb);
+     tmp.content_length = tmp.mime_rec.length = sb.st_size;
+     attach_parse(&tmp, tmpfp);
+ 
+   }
+   else {
+ 
+     /* Make copy of mime structure: */
+     mime_t_copy(&(tmp.mime_rec),a);
+     tmp.mime_rec.disposition = DISP_INLINE;  /* Show it ! */
+ 
+     tmp.offset = tmp.mime_rec.offset = a -> offset;
+     tmp.content_length = tmp.mime_rec.length = a->length;
+ #ifdef USE_PGP
+     if (headers)
+       tmp.pgp = headers[current-1]->pgp;
+ #endif
+   }
+ 
+   if (tmp.lines < 1)
+     tmp.lines = tmp.content_length / 60; /* This value is used for selecting
+ 					  * external pager versus internal
+ 					  * pager.
+ 					  */
+   /* there is nothing to display! */
+   if (tmp.mime_rec.length <= 0)
+     goto fail;
+ 
+   if (!mime_notplain(&(tmp.mime_rec)) || !have_metamail()) {
+ 
+     metapager (tmpfp == NULL ? mailfile : tmpfp, &tmp, FALSE);
+   } else {
+     /* otherwise call metamail */
+ 
+     if (!a->pathname) {
+       char tmpfile[STRING], c;
+       FILE *out;
+       int bytes;
+ 
+       sprintf (tmpfile, "%selm.%d", temp_dir, getpid());
+ 
+       out = safeopen(tmpfile);
+ 
+       if (out == NULL) {
+ 	error1("Error creating tempfile %s",tmpfile);
+ 	sleep_message();
+ 	goto fail;
+       }
+       /* copy the headers plus the message to a temp file */
+       fseek (mailfile, a->begin_offset, 0);
+       bytes = a->begin_offset - a->offset;
+       while (bytes < a->length) {
+ 	c = fgetc (mailfile);
+ 	fputc (c, out);
+ 	bytes++;
+       }
+       fclose (out);
+       sprintf (buf, "%s -m Elm -p -z %s", metamail_path,tmpfile);
+     }
+     else
+       /* This is the case when we are viewing attachments for an outgoing
+        * message.
+        */
+       sprintf(buf,"%s -m Elm -p -b -c %s/%s %s", 
+ 	      metamail_path,TYPE(a->type), a->subtype, a->pathname);
+     
+ 
+     (void) elm_chown (tmpfile, userid, groupid);
+ 
+     /* Option -z causes that metamail deletes input file */
+ 
+     Raw (OFF);
+     ClearScreen();
+     printf ("Executing: %s\n", buf);
+     system_call (buf, SY_ENAB_SIGINT|SY_ENV_METAMAIL);
+     PressAnyKeyToContinue();
+     Raw (ON);
+   }
+ 
+  fail:
+   mime_destroy(tmp.mime_rec.parts);
+ 
+   if (tmpfp) {
+     fclose (tmpfp);
+   }
+ 
+   return;
+ }
+ 
+ static int
+ attach_modify (att, new)
+      mime_t *att;
+      int new;
+ {
+   char buf[STRING];
+   int update = TRUE, prompt = TRUE, need_enc = 0;
+   int is_text = -1, ch;
+ 
+   buf[0] = '\0';
+ 
+   if (new) {
+     /* set the default charset */
+     add_parameter (buf, "charset", charset, sizeof (buf), 0);
+     att->type_opts = strmcpy (att->type_opts, buf);
+ 
+     /* Default disposition for attachments: attachment */
+     att->disposition = DISP_ATTACH;
+ 
+     /* force a prompt for a filename */
+     prompt = FALSE;
+     ch = 'f';
+     att->unlink = 0;
+   }
+   
+   /* 1 if is text type (true)
+    * 0 if not text type
+    * -1 if can't be encoded (ie structured) Message/ or Multpart/
+    */
+   is_text = is_text_type (TYPE(att->type), att->subtype, att->encoding);
+ 
+   for (;;) {
+     if (update) {
+       int add = 0;
+       ClearScreen ();
+       
+       Centerline (1, "Attachment Configuration");
+       
+       if (att->unlink) 
+ 	sprintf (buf, "%-26.26s: %.*s", "Filename", 
+ 		 sizeof(buf)-30, NONULL(att->pathname));
+       else
+ 	sprintf (buf, "%-26.26s: %.*s", "F)ilename", 
+ 		 sizeof(buf)-30, NONULL(att->pathname));
+       PutLine0 (3, 0, buf);
+       sprintf (buf, "%-26.26s: %.*s", "D)escription", 
+ 	       sizeof(buf)-30, NONULL(att->description));
+       PutLine0 (4, 0, buf);
+ 
+       sprintf (buf, "%-26.26s: %.15s/%.30s", "content-T)ype",
+                TYPE(att->type), att->subtype);
+       if (att->type_opts) strcat(buf,";");
+       PutLine0 (5, 0, buf);
+       if (att->type_opts) {
+ 	PutLine0 (6+add, 28, att->type_opts);
+ 	add++;
+       }
+       sprintf (buf, "%-26.26s: %s", "content-transfer-E)ncoding",
+ 	       ENCODING(att->encoding));
+       PutLine0 (6+add, 0, buf);
+       
+ 
+       sprintf (buf, "%-26.26s: %.15s", "content-disP)osition", 
+ 	       DISPOSITION(att->disposition));
+       if (att->disposition_opts)
+         strcat(buf,";");
+       PutLine0 (7+add, 0, buf);
+       if (att->disposition_opts) {
+ 	PutLine0 (8+add, 28, att->disposition_opts);
+ 	add++;
+       }
+ 
+       if (is_text < 0)
+ 	sprintf (buf, "%-26.26s: %s", "CRLF-conversions",
+ 		 "structured (direct content-encoding not allowed)");
+       else if (is_text)
+ 	sprintf (buf, "%-26.26s: %s", "CRLF-conversions",
+ 		 "Text (line orienteed, convert LF <-> CRLF)");
+       else 
+ 	sprintf (buf, "%-26.26s: %s", "CRLF-conversions",
+ 		 "Binary (no conversions)");
+       PutLine0 (9+add, 0, buf);
+ 
+       update = FALSE;
+       show_last_error();
+     }
+     
+     if (prompt) {
+       PutLine0 (elm_LINES-2, 0, "Enter letter or RETURN to quit: ");
+       ch = ReadCh(REDRAW_MARK);
+       clear_error();
+     }
+     
+     if (ch == '\n' || ch == 'q' || ch == 'Q' || ch == 'x' || ch == 'X')
+       return (TRUE);
+     else if (ch == ctrl('L') || ch == REDRAW_MARK)
+       update = TRUE;
+     else if (ch == 'f' || ch == 'F') {
+       int code;
+ 
+       if (att->unlink)  {
+ 	error("You can't change filename!");
+ 	continue;
+       }
+       if (att->pathname)
+ 	strfcpy(buf, att->pathname, sizeof(buf));
+       else
+ 	buf[0] = '\0';
+ 
+       prompt = TRUE;
+       PutLine0 (elm_LINES-2, 0, "Filename: ");
+       code = optionally_enter (buf, elm_LINES-2, 10, OE_APPEND_CURRENT|
+ 			       OE_REDRAW_MARK);
+       if (REDRAW_MARK == code) {
+ 	update = TRUE;
+ 	prompt = FALSE;
+ 	continue;
+       }
+ 
+       if (buf[0] != '\0') {
+ 	if (access(buf,READ_ACCESS) < 0) {
+ 	  int err = errno;
+ 	  error2("%.45s: %.33s",buf,error_description(err));
+ 	  continue;
+ 	}
+         att->pathname = strmcpy (att->pathname, buf);
+ 	update = TRUE;
+ 
+       } else {
+ 	update = TRUE;
+ 
+         if (att->pathname) {
+           free (att->pathname);
+           att->pathname = NULL;
+         }
+         if (new)
+           return FALSE;
+         else
+           continue;
+       }
+ 
+       /* Set some information about this attachment */
+       need_enc = attach_info (att);
+       if (need_enc < 0)
+ 	continue;
+ 
+       /* 1 if is text type (true)
+        * 0 if not text type
+        * -1 if can't be encoded (ie structured) Message/ or Multpart/
+        */
+       is_text = is_text_type (TYPE(att->type), att->subtype, att->encoding);
+       if (is_text < 0 && (att->encoding == ENCODING_QUOTED || 
+ 			  att->encoding == ENCODING_BASE64)) {
+ 	/* Reconsider encoding ... */
+ 	ch = 'e';
+ 	prompt = FALSE;
+ 	update = TRUE;
+ 	error ("Structured types don't allow encoding of data.");
+ 	sleep_message();
+ 
+ 	break;
+       } 
+ 
+       /* now let the user do what they want */
+       if (new)
+ 	prompt = TRUE;
+       
+     }
+     else if (ch == 'd' || ch == 'D') {
+       int code;
+ 
+       PutLine0 (elm_LINES-2, 0, "Description: ");
+       buf[0] = '\0';
+       if (att->description)
+ 	strfcpy(buf,att->description,sizeof(buf));
+ 
+       prompt = TRUE;
+       code =
+ 	optionally_enter (buf, elm_LINES-2, 13, OE_APPEND_CURRENT|
+ 			  OE_REDRAW_MARK);
+       if (REDRAW_MARK == code) {
+ 	update = TRUE;
+ 	prompt = FALSE;
+ 	continue;
+       }
+       if (code != 0)
+ 	continue;
+ 
+       if (buf[0])
+         att->description = strmcpy (att->description, buf);
+       else if (att->description) {
+         free (att->description);
+ 	att->description = NULL;
+       }
+       update = TRUE;
+     }
+     else if (ch == 't' || ch == 'T') {
+       int code;
+ 
+       prompt = TRUE;
+       PutLine0 (elm_LINES-2, 0, "Content-Type: ");
+       att -> flags &= ~(MIME_RFC822);
+       att -> flags &= ~(MIME_MIXED);
+       att -> flags &= ~(MIME_DIGEST);
+       sprintf (buf, "%.15s/%.30s", TYPE(att->type), att->subtype);
+       if (att->type_opts) {
+ 	int l;
+ 
+ 	strcat (buf, "; ");
+         l = strlen (buf);
+ 	strfcpy (buf + l, att->type_opts, sizeof (buf) - l);
+       }
+       
+       code = optionally_enter (buf, elm_LINES-2, 14, OE_APPEND_CURRENT|
+ 			       OE_REDRAW_MARK);
+       if (REDRAW_MARK == code) {
+ 	update = TRUE;
+ 	prompt = FALSE;
+ 	continue;
+       }
+       if (0 != code)
+ 	continue;
+ 
+       mime_get_content (buf, att);
+       if (att->type == MIME_TYPE_TEXT && (need_enc & HAVE_8BIT) &&
+ 	  !mime_get_param("charset",buf,att->type_opts,sizeof (buf)))
+ 	add_parameter(att->type_opts, "charset", charset,
+ 		      sizeof (att->type_opts),0);
+       
+       /* 1 if is text type (true)
+        * 0 if not text type
+        * -1 if can't be encoded (ie structured) Message/ or Multpart/
+        */
+       is_text = is_text_type (mime_types[att->type], att->subtype, att->encoding);
+       update = TRUE;
+       if (is_text < 0 && (att->encoding == ENCODING_QUOTED || 
+ 			  att->encoding == ENCODING_BASE64)) {
+ 	/* Reconsider encoding ... */
+ 	ch = 'e';
+ 	prompt = FALSE;
+ 	error ("Structured types don't allow encoding of data.");
+ 	sleep_message();
+       } 
+     }
+     else if (ch == 'p' || ch == 'P') {
+       int code;
+ 
+       prompt = TRUE;
+       PutLine0 (elm_LINES-2, 0, "Content-Disposition: ");
+       strcpy (buf, DISPOSITION(att->disposition));
+       if (att->disposition_opts) {
+ 	int l;
+ 
+ 	strcat (buf,"; ");
+         l = strlen (buf);
+ 	strfcpy (buf + l, att->disposition_opts, sizeof (buf) - l);
+       }
+       
+       code = optionally_enter (buf, elm_LINES-2, 21, 
+ 			       OE_REDRAW_MARK|OE_APPEND_CURRENT);
+       if (REDRAW_MARK == code) {
+ 	update = TRUE;
+ 	prompt = FALSE;
+ 	continue;
+       }
+       if (0 != code)
+ 	continue;
+       mime_get_disposition (buf, att);
+       update = TRUE;
+     }
+     else if (ch == 'e' || ch == 'E') {
+       prompt = TRUE;
+       PutLine0 (elm_LINES-2, 0, "Content-Transfer-Encoding: ");
+       Centerline (elm_LINES-1, "<SPACE> for next value, <RETURN> to accept.");
+       for (;;) {
+ 	MoveCursor (elm_LINES-2, 27);
+ 	CleartoEOLN ();
+ 
+ #define NEXT_ENCODING  { \
+ 			   att->encoding++; \
+ 			   if (att->encoding > 5) att->encoding = 1; \
+ 			   continue; \
+ 		       }
+ 
+ #ifndef USE_8BITMIME
+ 	if (allow_no_encoding < 1) {
+ 	  if (att->encoding == ENCODING_8BIT) {  /* Mailer won't support ! */
+ 	    /* TRY next encosing instead */
+ 	    NEXT_ENCODING;
+ 	  }
+ 	}
+ #endif
+ 	
+ #ifndef USE_BINARYMIME
+ 	if (allow_no_encoding < 2) {
+ 	  if (att->encoding == ENCODING_BINARY) {  /* Mailer won't support ! */
+ 	    /* TRY next encoding instead */
+ 	    NEXT_ENCODING;
+ 	  }
+ 	}
+ #endif
+ 
+ 	/* Don't allow 7bit if the file contains 8bit chars... 
+ 	 * 7bit encoding is allowed if file includes control characters 
+ 	 */
+ 	if (att->encoding == ENCODING_7BIT && (need_enc & HAVE_8BIT)) {
+ 	  NEXT_ENCODING;
+ 	}
+ 	/* Don't allow 7bit or 8bit if the file required binary
+ 	 * encoding according of Mime Draft Standard.
+ 	 */
+ 	if ((att->encoding == ENCODING_7BIT || att->encoding == ENCODING_8BIT)
+ 	    && (need_enc & HAVE_BINARY)) {
+ 	  NEXT_ENCODING;
+ 	}
+ 
+ 	/* Don't allow encoding for Multipart/ and Message/ 
+ 	 * See mime Draft Standard. Be carefull that don't create
+ 	 * infinitive loop! */
+ 
+ 	if (is_text < 0) {
+ 	  static int again = 0;    /* Prevent looping */
+ 	  if (att->encoding == ENCODING_QUOTED || 
+ 	      att->encoding == ENCODING_BASE64) {
+ 	    if (again == att->encoding) {
+ 	      error("Structured types must be encoded in leaf type!");
+ 	      sleep_message();
+ 
+ 	      /* prompt for new content-type */
+ 	      prompt = FALSE;
+ 	      ch = 't';
+ 	      break;
+ 	    } else {
+ 	      if (!again)
+ 		again = att->encoding;
+ 	      NEXT_ENCODING;
+ 	    }
+ 	  } else
+ 	    again = 0;
+ 	}
+ 
+ 	Write_to_screen (ENCODING(att->encoding), 0);
+ 	ch = ReadCh(REDRAW_MARK);
+ 	if (ch == '\n')
+ 	  break;
+ 	else if (ch == ' ') {
+ 	  NEXT_ENCODING;
+ 	}
+ 	else if (ch == REDRAW_MARK) {
+ 	  update = TRUE;
+ 	  prompt = FALSE;
+ 	  ch =  'e';
+ 	  
+ 	  break;
+ 	}
+       }
+ 
+ #undef NEXT_ENCODING
+ 
+       ClearLine (elm_LINES-1);
+       /* 1 if is text type (true)
+        * 0 if not text type
+        * -1 if can't be encoded (ie structured) Message/ or Multpart/
+        */
+       is_text = is_text_type (mime_types[att->type], att->subtype, att->encoding);
+       update = TRUE;
+     }
+     else
+       error ("Unknown command.");
+   }
+   /* Not reached. */
+ }
+ 
+ static void
+ mime_guess_content_type (ptr)
+      mime_t *ptr;
+ {
+   /* This routine tries to guess the content-type of an attachment by looking
+    * at the suffix of ptr->pathname.  It first looks to see if it can find
+    * an entry in ~/.elm/mime.types, then in "system_mime_types", and failing
+    * that, to a small list of builtin definitions.
+    */
+   int i, found = FALSE;
+   char *p, *c, buf[LONG_STRING];
+   FILE *fp;
+ 
+   dprint (3, (debugfile, "mime_guess_content_type: pathname=%s\n",
+ 	      ptr->pathname));
+ 
+   /* Set the "filename" field for content-disposition */
+   p = strrchr (ptr->pathname, '/');
+   if (p)
+     p++;
+   else
+     p = ptr->pathname;
+   buf[0] = '\0';
+   add_parameter (buf, "filename", p, sizeof (buf), 0);
+   ptr->disposition_opts = strmcpy (ptr->disposition_opts, buf);
+ 
+   /* Try to guess the content type of the data by the filename extension */
+   p = strrchr (ptr->pathname, '.');
+   if (! p)
+     return;
+   p++;
+   for (i = 0; i < 3; i++) {
+   dprint (3, (debugfile, 
+ 	      "mime_guess_content_type: searching \"%s\", i=%d\n",
+ 	      p,i));
+     if (i == 0) {
+       
+       /* First try the user's mime.types file */
+       
+       sprintf (buf, "%s/.elm/mime.types", home);
+       fp = fopen (buf, "r");
+       if (!fp)
+ 	continue;
+     }
+     else if (i == 1) {
+       
+       /* If it wasn't there, try the system file... */
+       
+       fp = fopen (system_mime_types, "r");
+       if (! fp)
+ 	continue;
+     }
+     else {
+       /* Couldn't find user or system mime.types file,
+        * use these defaults...
+        */
+       if (istrcmp (p, "ps") == 0) {
+ 	ptr->type = MIME_TYPE_APPLICATION;
+ 	strcpy (ptr->subtype, "postscript");
+         if (ptr->type_opts) {
+           free (ptr->type_opts);
+           ptr->type_opts = NULL;
+         }
+       }
+       else if (istrcmp (p, "gif") == 0 || istrcmp (p, "jpeg") == 0 ||
+ 	       istrcmp (p, "tiff") == 0) {
+ 	ptr->type = MIME_TYPE_IMAGE;
+ 	strcpy (ptr->subtype, p);
+         if (ptr->type_opts) {
+           free (ptr->type_opts);
+           ptr->type_opts = NULL;
+         }
+       }
+       dprint (3, (debugfile, 
+ 		  "mime_guess_content_type: built-in default \"%s\" as \"%s/%s\"\n", 
+ 		  p, TYPE(ptr->type), ptr->subtype));
+     }
+     
+     if (i < 2) {
+       while (fgets (buf, LONG_STRING, fp) != NULL) {
+ 	if (buf[0] == '#') /* Skip comments */
+ 	  continue;
+ 	c = buf;
+ 	while (*c && isspace ((unsigned char) *c)) /* skip leading whitespace */
+ 	  c++;
+ 	if (! *c)
+ 	  continue;
+ 	if (strincmp (c, p, strlen (p)) == 0) {
+ 	  buf[strlen (buf) - 1] = '\0';
+ 	  mime_get_content (c + strlen (p), ptr);
+ 	  dprint (3, (debugfile, "mime_guess_content_type: user defined \"%s\" as \"%s/%s\"\n", p, TYPE(ptr->type), ptr->subtype));
+ 	  found = TRUE;
+ 	  break;
+ 	}
+       }
+       fclose (fp);
+       if (found)
+ 	break;
+     }
+   }
+   return;
+ }
+ 
+ static int
+ attach_info (ptr)
+      mime_t *ptr;
+ {
+   struct stat sb;
+   FILE *fp;
+   int need_enc;
+ 
+   if (stat (ptr->pathname, &sb) == -1) {
+     if (errno == ENOENT)
+       error ("That file does not exist!");
+     else
+       error ("Could not stat file!");
+     sleep_message();
+     return (-1);
+   }
+ 
+   ptr->length = sb.st_size;
+ 
+   if (can_open(ptr->pathname,"r") != 0) {
+     error1 ("%.50s isn't readable by user!", ptr->pathname);
+     ptr->pathname[0] = '\0';
+     sleep_message();
+     return (-1);
+   }
+ 
+   mime_guess_content_type (ptr);
+ 
+   /* Figure out what the default encoding is... */
+ 
+   error1 ("Reading %s...", ptr->pathname);
+   fp = fopen (ptr->pathname, "r");
+   if (!fp) {
+     error1 ("Can't open %s!", ptr->pathname);
+     sleep_message();
+     return -1;
+   }
+ 
+   need_enc = needs_encoding (fp);
+   
+   if (need_enc & HAVE_CTRL)
+     ptr->encoding = (need_enc & HAVE_BINARY) 
+       ? ENCODING_BASE64 : ENCODING_QUOTED;
+   else if (need_enc & HAVE_BINARY) { 
+     /* HAVE_BINARY, but not HAVE_CTRL so that have long lines! */
+ #ifdef USE_BINARYMIME
+     ptr->encoding = ENCODING_BINARY;
+ #else
+     ptr->encoding = ENCODING_QUOTED;
+ #endif
+   }
+   else if (need_enc & HAVE_8BIT) {
+ #ifdef USE_8BITMIME
+     ptr->encoding = ENCODING_8BIT;
+ #else
+     ptr->encoding = ENCODING_QUOTED;
+ #endif
+   }
+   fclose (fp);
+   clear_error();  /* Remove reading ... -message */
+ 
+   dprint(3,(debugfile,"attach_info: need_enc=%d, encoding=%d, pathname=%s\n",
+ 	    need_enc,ptr->encoding,ptr->pathname));
+   return (need_enc);
+ }
+ 
+ static void
+ attach_header (mt, num, is_cur, use_desc, offset)
+      mime_t *mt;
+      int num, is_cur, offset, use_desc;
+ {
+   /* Displays a header for a menu for the specified attachment. */
+   char *Encoding = "???";
+  
+   char buf[LONG_STRING], buf2[LONG_STRING];
+   int len, len2;
+   int Width = elm_COLUMNS;     /* Protect arbitary big values of COLUMNS */
+   if (Width > sizeof (buf)-1)
+     Width = sizeof (buf)-1;
+ 
+   Encoding = ENCODING(mt->encoding);
+ 
+   sprintf (buf,
+ 	   "%4d %-30.30s (%d) ",
+ 	   num,
+ 	   use_desc ? NONULL(mt->description) : NONULL(mt->pathname),
+ 	   mt->length);
+   if (mt->length < 10)
+     strcat (buf, "   ");
+   else if (mt->length < 100)
+     strcat (buf, "  ");
+   else if (mt->length < 1000)
+     strcat (buf, " ");
+   sprintf (buf2, "%.15s/%.30s", TYPE(mt->type), mt->subtype);
+   strcat (buf, buf2);
+   len = Width - strlen (buf);
+   len2 = strlen (Encoding) + 3;
+   if (len2 > len) {
+     buf[Width-len2] = '\0';
+     len = len2 = 0;
+   }
+   sprintf (buf2, "%s %*.*s[%s]", buf, len-len2, len-len2, "", Encoding);
+   
+   if (is_cur)
+     StartBold();
+   PutLine0 (offset, 0, buf2);
+   if (is_cur)
+     EndBold();
+ }
+ 
+ mime_t *
+ attach_menu (mt, rdonly)
+      mime_t *mt;
+      int rdonly;
+ {
+   /* A generic attachment menu.  "rdonly" controls whether or not the list
+    * of attachments "mt" may be edited.
+    */
+ 
+   mime_t **ptrs = NULL, *tmp, *ret = NULL;
+   int ptr_len = 0, ptr_max = 0, i, cur = 0, offset = 3, key_offset, ch;
+   int update = TRUE;
+   char buf[STRING];
+   int top = 0;
+ 
+   /* Generate an array of pointers so it is easier to work with. */
+   while (mt) {
+     if (ptr_len == ptr_max)
+       ptrs = (mime_t **) DynamicArray (ptrs, sizeof (mime_t *), &ptr_len, 5);
+     ptrs[ptr_max++] = mt;
+     mt = mt->next;
+   }
+ 
+   for (;;) {
+     if (cur < top || cur >= top + elm_LINES-3-offset) {
+       if (cur < top) 
+ 	top -= elm_LINES-3-offset;
+       if (cur >= top + elm_LINES-3-offset) 
+ 	top += elm_LINES-3-offset;
+       if (top >= ptr_max)
+ 	top = ptr_max - elm_LINES +3 +offset;
+       if (top < 0)
+ 	top = 0;
+       update = TRUE;
+     }
+     if (update) {
+       ClearScreen ();
+       sprintf (buf, "Attachment Menu (%d attachments)", ptr_max);
+       Centerline (1, buf);
+       if (! rdonly)
+ 	strcpy (buf, "a)dd, e)dit, d)elete, m)odify, ");
+       else
+ 	buf[0] = '\0';
+       strcat (buf, "p)rint, s)ave, v)iew subparts, q)uit");
+       Centerline (elm_LINES-1, buf);
+       for (i = top; i < ptr_max && i < top + elm_LINES -3 - offset; i++)
+ 	attach_header (ptrs[i], i + 1, i == cur, rdonly, offset + i - top);
+       update = FALSE;
+       show_last_error(); 
+     }
+     ClearLine (elm_LINES-2);
+     PutLine0 (elm_LINES-2, 0, "Attachments: ");
+     ch = ReadCh (REDRAW_MARK|READCH_CURSOR);
+     clear_error(); /* Clear the error message (from buffer also) */
+     switch (ch) {
+     case '-':
+     case LEFT_MARK:
+     case PAGEUP_MARK:
+       attach_header (ptrs[cur], cur+1, FALSE, rdonly, offset + cur - top);
+       cur -= elm_LINES -3;
+       if (cur < 0)
+ 	cur = 0;
+       break;
+     case '+':
+     case RIGHT_MARK:
+     case PAGEDOWN_MARK:
+       attach_header (ptrs[cur], cur+1, FALSE, rdonly, offset + cur - top);
+       attach_header (ptrs[cur], cur+1, FALSE, rdonly, offset + cur - top);
+       cur += elm_LINES -3;
+       if (cur > ptr_max - 1) 
+ 	cur = ptr_max - 1;
+       break;
+     case 's':
+       if (ptr_max > 0)
+         attach_save (ptrs[cur]);
+       else
+         error("There are no attachments!");
+       break;
+     case ' ':
+     case '\n':
+       if (ptr_max > 0) {
+         attach_viewer (ptrs[cur]);
+         update = TRUE;
+       }
+       else
+         error("There are no attachments!");
+       break;
+     case 'p':
+       if (ptr_max > 0)
+         attach_print(ptrs[cur]);
+       else
+         error("There are no attachments!");
+       break;
+     case 'v': /* Perhaps it is better that attachment meny shows whole
+ 	       * structure -- but this is temporary hack.... */
+       if (ptr_max == 0) {
+         error("There are no attachments!");
+         break;
+       }
+       if (ptrs[cur]->parts) {
+ 	attach_menu(ptrs[cur]->parts,TRUE);
+ 	update = TRUE;
+       }
+       break;
+     case 'e':
+       if (! rdonly) {
+         if (ptr_max == 0) {
+           error("There are no attachments!");
+           break;
+         }
+ 	attach_edit (ptrs[cur]);
+ 	update = TRUE;
+       }
+       break;
+     case 'd':
+       if (! rdonly) {
+         if (ptr_max == 0) {
+           error("There are no attachments!");
+           break;
+         }
+ 	if (question_me) {
+ 	  for(;;) {
+ 	    PutLine0(elm_LINES-2, 0, "Are you sure? (y/n): y");
+ 	    MoveCursor(elm_LINES-2, 21);
+ 	    ch = ReadCh(0);
+ 	    if (ch == 'y' || ch == '\n' || ch == 'n')
+ 	      break;
+ 	  }
+ 	  ClearLine(elm_LINES-2);
+ 	  if (ch == 'n')
+ 	    break;
+ 	}
+       delete_it:
+   	free (ptrs[cur]);
+ 	ptrs[cur] = NULL;
+ 	/* Shift the rest of the pointers down by one. */
+ 	for (i = cur + 1; i < ptr_max; i++)
+ 	  ptrs[i-1] = ptrs[i];
+ 	ptrs[ptr_max-1] = NULL;
+         ptr_max--;
+ 	update = TRUE;
+       }
+       break;
+     case 'a':
+       if (! rdonly) {
+ 	tmp = (mime_t *) mime_t_alloc ();
+ 	if (attach_modify (tmp, TRUE)) {
+ 	  if (ptr_len == ptr_max)
+ 	    ptrs = (mime_t **) DynamicArray (ptrs, sizeof (mime_t *), &ptr_len, 5);
+ 	  ptrs[ptr_max++] = tmp;
+ 	}
+ 	else
+ 	  free (tmp);
+         update = TRUE;
+       }
+       break;
+     case 'm':
+       if (! rdonly) {
+         if (ptr_max == 0) {
+           error("There are no attachments!");
+           break;
+         }
+ 	attach_modify (ptrs[cur], FALSE);
+ 	/* If there is not pathname it is otherwise assumed to be 
+ 	 * part from mailfile...!
+ 	 */
+ 	if (ptrs[cur]->pathname == NULL)
+ 	  goto delete_it;
+         update = TRUE;
+       }
+       break;
+     case 'j':
+     case 'J':
+     case 'n':
+     case DOWN_MARK:
+     case ctrl('N'):
+     NEXT_ATTACH:
+       if (cur >= ptr_max - 1) {
+ 	error ("You are on the last attachment!");
+ 	break;
+       }
+       attach_header (ptrs[cur], cur+1, FALSE, rdonly, offset + cur - top);
+       cur++;
+       if (cur < top + elm_LINES -3 - offset)
+ 	attach_header (ptrs[cur], cur+1, TRUE, rdonly, offset + cur - top);
+       break;
+     case 'k':
+     case 'K':
+     case ctrl('K'):
+     case UP_MARK:
+     PREV_ATTACH:
+       if (cur == 0) {
+ 	error ("You are on the first attachment!");
+ 	break;
+       }
+       attach_header (ptrs[cur], cur+1, FALSE, rdonly, offset + cur - top);
+       cur--;
+       if (cur >= top)
+ 	attach_header (ptrs[cur], cur+1, TRUE, rdonly, offset + cur - top);
+       break;
+     case 'i':
+       if (! rdonly)
+         break;
+       /* else fall through to next statement! */
+     case 'q':
+     case 'x':
+       if (ptrs == NULL)
+         return NULL;
+       if (! rdonly) {
+ 	/* The attachments might have been edited, so rebuild the list */
+ 	ret = tmp = ptrs[0];
+ 	for (i = 1; i < ptr_max; i++) {
+ 	  tmp->next = ptrs[i];
+ 	  tmp = tmp->next;
+ 	}
+ 	if (tmp)
+ 	  tmp->next = NULL;
+       }
+       else
+ 	ret = mt;
+       free (ptrs);
+       return ret;
+     case ctrl('L'):
+     case REDRAW_MARK:
+       update = TRUE;
+       break;
+     default:
+       error1 ("Unknown command: %c", ch);
+     }
+   }
+ }
+ #endif /* MIME */
Index: WORK/src/builtin++.c
*** /tmp/null.14101	Tue Aug 20 22:05:34 1996
--- WORK/src/builtin++.c	Sun Aug  4 23:44:21 1996
***************
*** 0 ****
--- 1,363 ----
+ #include "headers.h"
+ #include "me.h"
+ 
+ extern int errno;
+ extern int tabspacing;
+ 
+ static void
+ builtin_help () {
+   /* A help screen for the pager below. */
+ 
+ redraw:
+   ClearScreen ();
+   StartInverse();
+   Write_to_screen ("Help for builtin++", 0);
+   EndInverse();
+   NewLine ();
+   NewLine ();
+   Write_to_screen ("Key\t\tAction", 0);
+   NewLine ();
+   Write_to_screen ("---\t\t------", 0);
+   NewLine ();
+   Write_to_screen ("<SPACE>, +\tNext page.", 0);
+   NewLine ();
+   Write_to_screen ("-\t\tPrevious page.", 0);
+   NewLine ();
+   Write_to_screen ("<RETURN>\tNext line.", 0);
+   NewLine ();
+   Write_to_screen ("q, x, i\t\tReturn to the index menu.", 0);
+   NewLine ();
+   Write_to_screen ("/\t\tSearch for pattern in message.", 0);
+   NewLine ();
+   Write_to_screen ("^\t\tFirst page.", 0);
+   NewLine ();
+   Write_to_screen ("G\t\tLast page", 0);
+   NewLine ();
+   Write_to_screen ("^L\t\tRefresh display.", 0);
+   NewLine ();
+   Write_to_screen ("^P\t\tUp one line.", 0);
+   NewLine ();
+   Write_to_screen ("^D\t\tDown one-half page.", 0);
+   NewLine ();
+   Write_to_screen ("^U\t\tUp one-half page.", 0);
+   NewLine ();
+   Write_to_screen ("?\t\tThis help screen.", 0);
+   NewLine ();
+   PutLine0 (elm_LINES, 0, "Press any key to return...");
+   if (REDRAW_MARK == ReadCh (REDRAW_MARK))
+     goto redraw;
+ 
+   return;
+ }
+ 
+ int
+ builtinplusplus (fp, begin, length, text, textlen)
+      FILE *fp;
+      long begin;
+      int length, textlen;
+      char **text;
+ {
+   char buffer[LONG_STRING], searchword[STRING], *pending = NULL;
+   long **offsets = NULL;
+   int offset_len = 0, offset_max = 0;
+   int lines = 0, saveidx, ch, len, chars;
+   int slurping = FALSE; /* used to find the end of the file */
+   int searching = FALSE;
+   long end_offset = begin + length;
+   int idx = -textlen, cur_line_len;
+   int is_end = 0;
+ 
+   if (fseek (fp, begin, 0) == -1) {
+     dprint (1, (debugfile, "pager2(): fseek() returned errno %d!\n", errno));
+     error1 ("Failed to seek %d bytes into file!", begin);
+     if (sleepmsg > 0)
+       sleep (sleepmsg);
+     return (0);
+   }
+ 
+   clear_error();
+   ClearScreen();
+ 
+   for (;;) {
+     while (((ftell (fp) < end_offset) || (idx < 0)) &&
+ 	   (lines < elm_LINES || searching || slurping)) {
+ 
+       if (pending == NULL) {
+ 	/* There is no pending data to output, so we need to grab another
+ 	 * line.
+ 	 */
+ 	if (idx < 0) {
+ 	  /* Negative index numbers refer to the text block passed to pager2.
+ 	   * this is necessary for doings things like adding a title and
+ 	   * weeding unwanted headers.
+ 	   */
+ 	  pending = text[textlen+idx];
+ 	  idx++;
+ 	}
+ 	else {
+ 	  if (offset_len >= offset_max - 1)
+ 	    offsets = (long **) DynamicArray (offsets, 
+ 					      sizeof (long *), &offset_max, 
+ 					      elm_LINES + 1);
+ 	  if (idx == offset_len) {
+ 	    if (! offsets[idx]) {
+ 	      offsets[idx] = (long *) safe_malloc (sizeof (long));
+ 	      offset_len++;
+ 	    }
+ 	    *offsets[idx] = ftell (fp);
+ 	  }
+ 	
+ 	  if ((cur_line_len= mail_gets (buffer, LONG_STRING, fp)) <= 0) {
+ 	    if (slurping) {
+ 	      slurping = FALSE;
+ 	      idx -= elm_LINES;
+ 	      if (idx < -textlen)
+ 		idx = -textlen;
+ 	      fseek (fp, *offsets[idx > -1 ? idx : 0], 0);
+ 	      continue;
+ 	    }
+ 	    if (searching) {
+ 	      searching = FALSE;
+ 	      ClearLine (elm_LINES);
+ 	      PutLine0 (elm_LINES, 0, "NOT FOUND!");
+ 	      if (sleepmsg > 0)
+ 		sleep (sleepmsg);	 
+ 	      ClearLine (elm_LINES);
+ 	      /* Reposition the file at the appropriate place */
+ 	      idx = saveidx;
+ 	      fseek (fp, *offsets[idx > 0 ? idx : 0], 0);
+ 	    }
+ 	    break;
+ 	  }
+ 	  
+ 	  idx++;
+ 
+ 	  if (slurping)
+ 	    continue;
+ 	  
+ 	  if (searching) {
+ 	    if (in_string (buffer, searchword)) {
+ 	      searching = FALSE;
+ 	      idx -= 3;
+ 	      if (idx < -textlen)
+ 		idx = -textlen;
+ 	      if (idx >= 0) fseek (fp, *offsets[idx], 0);
+ 	      else fseek (fp, begin, 0);
+ 	      ClearScreen ();
+ 	      lines = 0;
+ 	    }
+ 	    continue;
+ 	  }
+ 
+ 	  if (cur_line_len > 0 && buffer[cur_line_len-1] == '\n') {
+ 	    buffer[cur_line_len-1] = '\0';
+ 	    if (cur_line_len > 1 && buffer[cur_line_len-2] == '\r') 
+ 	      buffer[cur_line_len-2] = '\0';
+ 	  }
+ 
+ 	  pending = buffer;
+ 	}
+       }
+ 
+       /* This is the part of the code that actually displays on the screen */
+       chars = 0;
+       while (*pending) {
+ 	if (chars >= elm_COLUMNS)
+ 	  break;
+ 
+ 	if (*pending == '\t') {
+ 	  Writechar('\t');
+ 	  /* 'chars += tabspacing' is INCORRENT! - K E H */ 
+ 	  chars = ((chars / tabspacing ) +1) * tabspacing; 
+ 	}
+ #ifdef ASCII_CTYPE
+         else if (!isascii((unsigned char)*pending)) {
+           Writechar('?');
+           chars++;
+         }
+ #endif
+ 	else if (!isprint((unsigned char)*pending)) {
+ 	  if (*pending >= 0 && *pending <= 31) {    
+             /* This won't fit on the line, so just skip it for now */
+             if (chars == elm_COLUMNS - 1)
+               break;
+ 
+             Writechar('^');
+             Writechar(*pending + 64);
+             chars += 2;
+ 
+             /* Honor the formfeed character */
+             if (*pending == ctrl('L')) {
+               break;
+             }
+           }
+           else {
+             Writechar('?');
+             chars++;
+           }
+ 	}
+ 	else {
+ 	  Writechar(*pending);
+ 	  chars++;
+ 	}
+ 	pending++;
+       }
+       NewLine();
+       lines++;
+ 
+       if (*pending == ctrl('L')) {
+         pending++;
+         if (*pending == '\0')
+           pending = NULL;
+         break;
+       }
+ 
+       /* Check to see if we are finished with this line */
+       if (*pending == '\0')
+ 	pending = NULL;
+     }
+     if (slurping){
+       slurping = FALSE;
+       idx -= elm_LINES;
+       if (idx < -textlen)
+         idx = -textlen;
+       if (idx >= 0) fseek (fp, *offsets[idx], 0);
+       else fseek (fp, begin, 0);
+       continue;
+     }
+ 
+     StartBold();
+     if (idx < 0) {
+       Write_to_screen ("More (you've seen 0%)", 0);
+       len = 0;
+       is_end = 0;
+     }
+     else {
+       if (length < 1)
+         len = 100;
+       else {
+         long pos = ftell (fp);
+ 
+         len = 100 * (pos - begin) / length;
+       }
+ 
+       if (len >= 100) {
+         Write_to_screen ("Command ('i' to return to index):", 0);
+         is_end = 1;
+       }
+       else {
+         sprintf (buffer, "MORE (you've seen %d%%):", len);
+         Write_to_screen (buffer, 0);
+         is_end = 0;
+       }
+     }
+     EndBold();
+ 
+     ch = ReadCh (REDRAW_MARK|READCH_CURSOR);
+     switch (ch) {
+     case ' ':
+     case '+':
+     case PAGEDOWN_MARK:
+       if (is_end) {
+ 	DestroyDynamicArray (offsets);
+ 	return (' ');
+       }
+       lines = 0;
+       ClearScreen ();
+       break;
+     case HOME_MARK:
+     case '^':      
+       idx = -textlen;
+       fseek (fp, begin, 0);
+       lines = 0;
+       ClearScreen ();
+       break;
+     case 'G':
+       idx = offset_len-1;
+       if (idx >= 0) fseek (fp, *offsets[idx], 0);
+       else fseek (fp, begin, 0);
+       slurping = TRUE;
+       lines = 0;
+       ClearScreen ();
+       break;
+     case FIND_MARK:
+     case '/':
+       ClearLine (elm_LINES);
+       PutLine0 (elm_LINES, 0, "Search: ");
+       searchword[0] = '\0';
+       {
+ 	int code = optionally_enter (searchword, elm_LINES, 8, 
+ 				     OE_REDRAW_MARK);
+ 	if (REDRAW_MARK == code)
+ 	  goto redraw;
+ 	if (code < 0)
+ 	  goto quit;
+       }
+       if (searchword[0])
+ 	searching = TRUE;
+       saveidx = idx;
+       break;	
+     case PAGEUP_MARK:
+     case '-':
+       idx -= elm_LINES * 2;
+       if (idx < -textlen)
+ 	idx = -textlen;
+       if (idx >= 0) fseek (fp, *offsets[idx], 0);
+       else fseek (fp, begin, 0);
+       ClearScreen ();
+       lines = 0;
+       break;
+     case ctrl('P'):
+       idx -= elm_LINES + 1;
+       if (idx < -textlen)
+ 	idx = -textlen;
+       if (idx >= 0) fseek (fp, *offsets[idx], 0);
+       else fseek (fp, begin, 0);
+       lines = 0;
+       ClearScreen();
+       break;
+     case ctrl('D'):
+       lines = elm_LINES / 2;
+       ClearScreen ();
+       break;
+     case ctrl('U'):
+       idx -= elm_LINES + (elm_LINES / 2);
+       if (idx < -textlen)
+ 	idx = -textlen;
+       if (idx >= 0) fseek (fp, *offsets[idx], 0);
+       else fseek (fp, begin, 0);
+       lines = 0;
+       ClearScreen ();
+       break;
+     case HELP_MARK:
+     case '?':
+       builtin_help ();
+     case REDRAW_MARK:
+     case ctrl('L'):
+     redraw:
+       idx -= elm_LINES;
+       if (idx < -textlen)
+ 	idx = -textlen;
+       if (idx >= 0) fseek (fp, *offsets[idx], 0);
+       else fseek (fp, begin, 0);
+       ClearScreen ();
+       lines = 0;
+       break;
+     case '\n':
+       {
+ 	int x, y;
+ 
+ 	GetXYLocation (&x, &y);
+ 	ClearLine (x);
+       }
+       lines = elm_LINES - 1;
+       break;
+     case EOF:
+     default:
+     quit:
+       DestroyDynamicArray (offsets);
+       return (ch == 'q' || ch == 'x' ? 0 : ch);
+     }
+   }
+ }
+ 
Index: WORK/src/curses.c
*** elm2.4.25/src/curses.c	Mon May 30 19:27:44 1994
--- WORK/src/curses.c	Tue Aug 13 15:08:48 1996
***************
*** 126,133 ****
  **/
  
  #include "headers.h"
  
! #ifdef I_STDARG
  # include <stdarg.h>
  #else
  # include <varargs.h>
--- 126,135 ----
  **/
  
  #include "headers.h"
+ #include <errno.h>
+ #include "me.h"
  
! #if ANSI_C &defined(I_STDARG)
  # include <stdarg.h>
  #else
  # include <varargs.h>
***************
*** 174,183 ****
  #define	ttgetattr(fd,where)	ioctl((fd),TCGETA,(where))
  #define	ttsetattr(fd,where)	ioctl((fd),TCSETAW,(where))
  # else
! struct sgttyb _raw_tty,
! 	      _original_tty;
! #define	ttgetattr(fd,where)	ioctl((fd),TIOCGETP,(where))
! #define	ttsetattr(fd,where)	ioctl((fd),TIOCSETP,(where))
  # endif	/*TERMIO*/
  #endif	/*TERMIOS*/
  
--- 176,187 ----
  #define	ttgetattr(fd,where)	ioctl((fd),TCGETA,(where))
  #define	ttsetattr(fd,where)	ioctl((fd),TCSETAW,(where))
  # else
! struct tty_modes {
!   struct sgttyb sgttyb;
!   struct tchars tchars;
! }  _raw_tty, _original_tty;
! static int ttgetattr P_((int,struct tty_modes *));  /* Prototype */
! static int ttsetattr P_((int,struct tty_modes *)); /* Prototype */
  # endif	/*TERMIO*/
  #endif	/*TERMIOS*/
  
***************
*** 190,206 ****
  static int _line  = -1,			/* initialize to "trash" */
             _col   = -1;
  
! static int _intransmit;			/* are we transmitting keys? */
  
  static
! char *_clearscreen, *_moveto, *_up, *_down, *_right, *_left,
!      *_setbold, *_clearbold, *_setunderline, *_clearunderline, 
!      *_sethalfbright, *_clearhalfbright, *_setinverse, *_clearinverse,
!      *_cleartoeoln, *_cleartoeos, *_transmit_on, *_transmit_off,
!      *_set_memlock, *_clear_memlock, *_start_termcap, *_end_termcap;
  
  static int _lines, _columns, _automargin, _eatnewlineglitch;
  int tabspacing;
  
  static char _terminal[1024];              /* Storage for terminal entry */
  static char _capabilities[1024];           /* String for cursor motion */
--- 194,217 ----
  static int _line  = -1,			/* initialize to "trash" */
             _col   = -1;
  
! static int _intransmit = -1;	        /* are we transmitting keys? */
  
  static
! char *_clearscreen = NULL, *_moveto = NULL, *_up = NULL, *_down = NULL, 
!   *_right = NULL, *_left = NULL, *_setbold = NULL, *_clearbold = NULL, 
!   *_setunderline = NULL, *_clearunderline = NULL, *_sethalfbright = NULL, 
!   *_clearhalfbright = NULL, *_setinverse = NULL, *_clearinverse = NULL,
!   *_cleartoeoln = NULL, *_cleartoeos = NULL, *_transmit_on = NULL, 
!   *_transmit_off = NULL, *_set_memlock = NULL, *_clear_memlock = NULL, 
!   *_start_termcap = NULL, *_end_termcap = NULL,
! 
!   *_key_up = NULL, *_key_down = NULL, *_key_left = NULL, *_key_right = NULL,
!   *_key_pageup = NULL, *_key_pagedown = NULL, *_key_home = NULL, 
!   *_key_help = NULL, *_key_find = NULL;
  
  static int _lines, _columns, _automargin, _eatnewlineglitch;
  int tabspacing;
+ static int tabexpand = 0;          /* Is terminal driver expanding tabs? */
  
  static char _terminal[1024];              /* Storage for terminal entry */
  static char _capabilities[1024];           /* String for cursor motion */
***************
*** 207,212 ****
--- 218,225 ----
  
  static char *ptr = _capabilities;	/* for buffering         */
  
+ static int  cursor_control = 0;
+ 
  int    outchar();			/* char output for tputs */
  char  *tgetstr(),     		       /* Get termcap capability */
        *tgoto();				/* and the goto stuff    */
***************
*** 263,268 ****
--- 276,294 ----
  	_start_termcap	   = tgetstr("ti", &ptr);
  	_end_termcap	   = tgetstr("te", &ptr);
  
+ 	_key_up            = tgetstr("ku", &ptr);
+ 	_key_down          = tgetstr("kd", &ptr);
+ 	_key_left          = tgetstr("kl", &ptr);
+ 	_key_right         = tgetstr("kr", &ptr);
+ 	_key_pageup        = tgetstr("kP", &ptr);
+ 	_key_pagedown      = tgetstr("kN", &ptr);
+ 	_key_home          = tgetstr("kh", &ptr);
+ 	_key_help          = tgetstr("%1", &ptr);
+ 	_key_find          = tgetstr("@0", &ptr);
+ 
+ 	if (_transmit_on && _transmit_off && _key_up && _key_down) {
+ 	  cursor_control = TRUE;
+ 	}
  
  	if (!_left) {
  		_left = "\b";
***************
*** 332,338 ****
  	/** turn function key transmission to ON | OFF **/
  
  	if (newstate != _intransmit) {
! 		_intransmit = ! _intransmit;
  		if (newstate == ON)
  		  tputs(_transmit_on, 1, outchar);
  		else 
--- 358,364 ----
  	/** turn function key transmission to ON | OFF **/
  
  	if (newstate != _intransmit) {
! 		_intransmit = newstate;
  		if (newstate == ON)
  		  tputs(_transmit_on, 1, outchar);
  		else 
***************
*** 362,368 ****
  	if (_lines == 0) _lines = DEFAULT_LINES_ON_TERMINAL;
  	if (_columns == 0) _columns = DEFAULT_COLUMNS_ON_TERMINAL;
  
! 	*lines = _lines - 1;		/* assume index from zero */
  	*columns = _columns;
  }
  
--- 388,412 ----
  	if (_lines == 0) _lines = DEFAULT_LINES_ON_TERMINAL;
  	if (_columns == 0) _columns = DEFAULT_COLUMNS_ON_TERMINAL;
  
! 
! 	/* WARNING: elm_LINES and elm_COLUMNS are inconsistent!
! 	 *
! 	 * elm_LINES    == number of lines in screen -1
! 	 * elm_COLUMNS  == number of rows in screen
! 	 *
! 	 *
! 	 * Check code in MoveCursor!
! 	 *
! 	 * row          == 0 .. elm_LINES
! 	 * col          == 0 .. elm_COLUMNS-1
! 	 *
! 	 *
! 	 * Who was this smart programmer!!!!!!!!!!!!!!!!!!!!!
! 	 *
! 	 *                         - K E H <hurtta@ozone.FMI.FI>
! 	 */
! 
! 	*lines = _lines - 1;	     
  	*columns = _columns;
  }
  
***************
*** 395,400 ****
--- 439,447 ----
  	_line = 0;	/* clear leaves us at top... */
  	_col  = 0;
  
+ 	redraw_screen = 0;
+ 	_intransmit = -1;   /* Re-set state */
+ 
  	if (!_clearscreen)
  		return(-1);
  
***************
*** 427,433 ****
  	/** move the cursor down 'n' lines **/
  	/** Caller must check that _down is not null before calling **/
  
! 	_line = (_line+n <= LINES? _line + n: LINES);    /* down 'n' lines... */
  
  	while (n-- > 0)
  		tputs(_down, 1, outchar);
--- 474,480 ----
  	/** move the cursor down 'n' lines **/
  	/** Caller must check that _down is not null before calling **/
  
! 	_line = (_line+n <= elm_LINES? _line + n: elm_LINES);    /* down 'n' lines... */
  
  	while (n-- > 0)
  		tputs(_down, 1, outchar);
***************
*** 461,467 ****
  	/** move the cursor 'n' characters to the right (nondestructive) **/
  	/** Caller must check that _right is not null before calling **/
  
! 	_col = (_col+n < COLUMNS? _col + n: COLUMNS);	/* right 'n' chars... */
  
  	while (n-- > 0)
  		tputs(_right, 1, outchar);
--- 508,515 ----
  	/** move the cursor 'n' characters to the right (nondestructive) **/
  	/** Caller must check that _right is not null before calling **/
  
! 	_col = (_col+n < elm_COLUMNS? _col + n: elm_COLUMNS);	
! 	/* right 'n' chars... */
  
  	while (n-- > 0)
  		tputs(_right, 1, outchar);
***************
*** 493,506 ****
  
  	if (col < 0)
  	  col = 0;
! 	if (col >= COLUMNS)
! 	  col = COLUMNS - 1;
  	if (row < 0)
  	  row = 0;
! 	if (row > LINES) {
  	  if (col == 0)
! 	    scrollafter = row - LINES;
! 	  row = LINES;
  	}
  
  	if (!_moveto)
--- 541,554 ----
  
  	if (col < 0)
  	  col = 0;
! 	if (col >= elm_COLUMNS)
! 	  col = elm_COLUMNS - 1;
  	if (row < 0)
  	  row = 0;
! 	if (row > elm_LINES) {
  	  if (col == 0)
! 	    scrollafter = row - elm_LINES;
! 	  row = elm_LINES;
  	}
  
  	if (!_moveto)
***************
*** 693,700 ****
  
  	if (! _memory_locked) {
  
! 	  _old_LINES = LINES;
! 	  LINES -= _line;		/* we can't use this for scrolling */
  
  	  tputs(_set_memlock, 1, outchar);
  	  fflush(stdout);
--- 741,748 ----
  
  	if (! _memory_locked) {
  
! 	  _old_LINES = elm_LINES;
! 	  elm_LINES -= _line;		/* we can't use this for scrolling */
  
  	  tputs(_set_memlock, 1, outchar);
  	  fflush(stdout);
***************
*** 713,719 ****
  	  return(-1);
  
  	if (_memory_locked) {
! 	  LINES = _old_LINES;		/* back to old setting */
    
  	  tputs(_clear_memlock, 1, outchar);
  	  fflush(stdout);
--- 761,767 ----
  	  return(-1);
  
  	if (_memory_locked) {
! 	  elm_LINES = _old_LINES;		/* back to old setting */
    
  	  tputs(_clear_memlock, 1, outchar);
  	  fflush(stdout);
***************
*** 750,756 ****
  	else if (ch == '\n') {
  	  if (!wrappedlastchar) {
  	    putchar('\n');
! 	    if (_line < LINES)
  	      ++_line;
  	  }
  	}
--- 798,804 ----
  	else if (ch == '\n') {
  	  if (!wrappedlastchar) {
  	    putchar('\n');
! 	    if (_line < elm_LINES)
  	      ++_line;
  	  }
  	}
***************
*** 762,768 ****
  		_col--;
  	    }
  	    else if (_line > 0) {
! 		_col = COLUMNS - 1;
  		_line--;
  		moveabsolute (_col, _line);
  	    }
--- 810,816 ----
  		_col--;
  	    }
  	    else if (_line > 0) {
! 		_col = elm_COLUMNS - 1;
  		_line--;
  		moveabsolute (_col, _line);
  	    }
***************
*** 776,786 ****
  
  	/* if a tab, output it */
  	else if (ch == '\t') {
! 	  putchar(ch);
! 	  if((nt=next_tab(_col+1)) > prev_tab(COLUMNS))
! 	    _col = COLUMNS-1;
  	  else
  	    _col = nt-1;
  	}
  
  	else {
--- 824,838 ----
  
  	/* if a tab, output it */
  	else if (ch == '\t') {
! 	  /* If terminal driver is expanding tabs, don't trust it ... */
! 	  if (!tabexpand)
! 	    putchar(ch);
! 	  if((nt=next_tab(_col+1)) > prev_tab(elm_COLUMNS))
! 	    _col = elm_COLUMNS-1;
  	  else
  	    _col = nt-1;
+ 	  if (tabexpand)
+ 	    moveabsolute (_col, _line);
  	}
  
  	else {
***************
*** 788,806 ****
  #ifdef ASCII_CTYPE
  	  if(!isascii(ch) || !isprint(ch))
  #else
! 	  if(!isprint(ch) && !(ch & ~0x7f))
  #endif
  	    ch = '?';
  
  	  /* if we only have one column left, simulate automargins if
  	   * the terminal doesn't have them */
! 	  if (_col == COLUMNS - 1) {
  	    putchar(ch);
  	    if (!_automargin || _eatnewlineglitch) {
  	      putchar('\r');
  	      putchar('\n');
  	    }
! 	    if (_line < LINES)
  	      ++_line;
  	    _col = 0;
  	    justwrapped = 1;
--- 840,858 ----
  #ifdef ASCII_CTYPE
  	  if(!isascii(ch) || !isprint(ch))
  #else
! 	  if(!isprint((unsigned char)ch))
  #endif
  	    ch = '?';
  
  	  /* if we only have one column left, simulate automargins if
  	   * the terminal doesn't have them */
! 	  if (_col == elm_COLUMNS - 1) {
  	    putchar(ch);
  	    if (!_automargin || _eatnewlineglitch) {
  	      putchar('\r');
  	      putchar('\n');
  	    }
! 	    if (_line < elm_LINES)
  	      ++_line;
  	    _col = 0;
  	    justwrapped = 1;
***************
*** 822,828 ****
  
  /*VARARGS2*/
  
! #ifdef	I_STDARG
  Write_to_screen(char *line, int argcount, ...)
  {
  	char *arg1, *arg2, *arg3;
--- 874,880 ----
  
  /*VARARGS2*/
  
! #if ANSI_C &defined(I_STDARG)
  Write_to_screen(char *line, int argcount, ...)
  {
  	char *arg1, *arg2, *arg3;
***************
*** 973,981 ****
--- 1025,1042 ----
  
  	state = state & ~NO_TITE;
  
+ 	dprint(4,(debugfile,
+ 		  "curses: Raw: state=%d do_tite=%d\n",state,do_tite));
+ 
  	/** state is either ON or OFF, as indicated by call **/
  
  	if (state == OFF && _inraw) {
+ 	  dprint(4,(debugfile,
+ 		    "curses: Raw: Setting Raw state OFF\n"));;
+ 
+ 	  if (cursor_control)
+ 	    transmit_functions(OFF);
+ 
  	  if (use_tite && _end_termcap && do_tite) {
  	    tputs(_end_termcap, 1, outchar);
  	    fflush(stdout);
***************
*** 985,990 ****
--- 1046,1054 ----
  	}
  	else if (state == ON && ! _inraw) {
  
+ 	  dprint(4,(debugfile,
+ 		    "curses: Raw: Setting Raw state ON\n"));;
+ 
  	  (void) ttgetattr(TTYIN, &_original_tty);
  	  (void) ttgetattr(TTYIN, &_raw_tty);    /** again! **/
  
***************
*** 991,996 ****
--- 1055,1061 ----
  #if !defined(TERMIO) && !defined(TERMIOS)
  	  _raw_tty.sg_flags &= ~(ECHO);	/* echo off */
  	  _raw_tty.sg_flags |= CBREAK;	/* raw on    */
+ 
  #else
  	  _raw_tty.c_lflag &= ~(ICANON | ECHO);	/* noecho raw mode        */
  
***************
*** 997,1034 ****
  	  _raw_tty.c_cc[VMIN] = '\01';	/* minimum # of chars to queue    */
  	  _raw_tty.c_cc[VTIME] = '\0';	/* minimum time to wait for input */
  
  #endif
  	  (void) ttsetattr(TTYIN, &_raw_tty);
! 	  if (use_tite && _start_termcap && do_tite)
  	    tputs(_start_termcap, 1, outchar);
  	  _inraw = 1;
  	}
  }
  
  int
! ReadCh()
  {
!     /*
!      *	read a character with Raw mode set!
!      *
!      *	EAGAIN & EWOULDBLOCK are recognized just in case
!      *	O_NONBLOCK happens to be in effect.
!      */
  
!     register int    result;
      unsigned char   ch;
  
!     while (((result = read(0, &ch, 1)) < 0)
! 	   && ((errno == EINTR)
  #ifdef	EAGAIN
! 	       || (errno == EAGAIN)
  #endif
  #ifdef	EWOULDBLOCK
! 	       || (errno == EWOULDBLOCK)
  #endif
-     ));
  
!     return((result <= 0 ) ? EOF : ch);
  }
  
  outchar(c)
--- 1062,1351 ----
  	  _raw_tty.c_cc[VMIN] = '\01';	/* minimum # of chars to queue    */
  	  _raw_tty.c_cc[VTIME] = '\0';	/* minimum time to wait for input */
  
+ 
+ #if defined(OXTABS)
+ 	  /* Some systems use OXTABS bit */
+ 	  if (_raw_tty.c_oflag & OXTABS) {
+ 	    dprint(4,(debugfile,
+ 		      "curses: [OXTABS] Terminal driver is expanding tabs...\n"));
+ 	    tabexpand = 1;
+ 	  } else {
+ 	    if (tabexpand) 	      
+ 	      dprint(4,(debugfile,
+ 			"curses: [OXTABS] Terminal driver isn't expanding tabs...\n"));
+ 	    tabexpand = 0;
+ 	  }
+ #endif /* defined(OXTABS) */
+ 
+ #if defined(TABDLY) && !defined(OXTABS)
+ 	  /* Some systems expands tab when TABDLY is XTABS */
+ 	  if ((_raw_tty.c_oflag & TABDLY) == 
+ #ifdef XTABS
+ 	      XTABS
+ #else
+ 	      TAB3
+ #endif
+ 	      ) {
+ 	    dprint(4,(debugfile,
+ 		      "curses: [TABDLY] Terminal driver is expanding tabs...\n"));
+ 	    tabexpand = 1;
+ 	  } else {
+ 	    if (tabexpand) 
+ 	      dprint(4,(debugfile,
+ 			"curses: [TABDLY] Terminal driver isn't expanding tabs...\n"));
+ 	    tabexpand = 0;
+ 	  }
+ #endif /* defined(TABDLY) && !defined(OXTABS) */
+ 
+ #if !defined(TABDLY) && !defined(OXTABS)
+ 
+ 	  /* If _POSIX_SOURCE is defined then OXTABS or TABDLY are not 
+ 	   * defined -- so print warning anyway
+ 	   */
+ 	  dprint(4,(debugfile,
+ 		    "curses: No information is terminal driver expanding tabs!\n"));	  
+ #endif /* !defined(TABDLY) && !defined(OXTABS) */
+ 
  #endif
  	  (void) ttsetattr(TTYIN, &_raw_tty);
! 	  if (use_tite && _start_termcap && do_tite) 
  	    tputs(_start_termcap, 1, outchar);
+ 	  _intransmit = -1; /* state unclear */
  	  _inraw = 1;
  	}
  }
  
+ #if !defined(TERMIO) && !defined(TERMIOS)
+ static int
+ ttgetattr(fd, where)
+      int fd;
+      struct tty_modes *where;
+ {
+   if (ioctl(fd, TIOCGETP, &where->sgttyb) < 0)
+     return(-1);
+   if (ioctl(fd, TIOCGETC, &where->tchars) < 0)
+     return(-1);
+   return(0);
+ }
+ 
+ static int
+ ttsetattr(fd, where)
+      int fd;
+      struct tty_modes *where;
+ {
+ 	if (ioctl(fd, TIOCSETP, &where->sgttyb) < 0)
+ 	  return(-1);
+ 	if (ioctl(fd, TIOCSETC, &where->tchars) < 0)
+ 	  return(-1);
+ 	return(0);
+ }
+ #endif
+ 
  int
! ReadCh(flags)
!      int flags;
  {
!   int redraw      = (flags & READCH_MASK);
!   int cursorkeys  = (flags & READCH_CURSOR) != 0;
!   int nocursor    = (flags & READCH_NOCURSOR) != 0 && cursor_control;
! 
! #ifdef DEBUG
!   unsigned char debug_buffer[20];
! #endif
! 
!   /*
!    *	read a character with Raw mode set!
!    *
!    *	EAGAIN & EWOULDBLOCK are recognized just in case
!    *	O_NONBLOCK happens to be in effect.
!    */
! 
!   /* This is static array so we can initialize it in here ...
!    */
!   static struct {
!     char ** const str;
!     const int result;
!     int maybe;
!   } keytable[] =
!     { { &_key_up,       UP_MARK,       0 },
!       { &_key_down,     DOWN_MARK,     0 },
!       { &_key_left,     LEFT_MARK,     0 },
!       { &_key_right,    RIGHT_MARK,    0 },
! 
!       { &_key_pageup,   PAGEUP_MARK,   0 },
!       { &_key_pagedown, PAGEDOWN_MARK, 0 },
! 
!       { &_key_home,     HOME_MARK,     0 },
!       { &_key_help,     HELP_MARK,     0 },
!       { &_key_find,     FIND_MARK,     0 },
!       { NULL,           0,             0 }
!     };
!     
!   int read_p,found_key;
! 
! reinit_ReadChar:
!   read_p = 0;
!   found_key = 0;
! 
!   fflush(stdout);
! 
!   if (redraw && !RawState()) { /* Check that we have in 'raw' mode */
!     dprint(4,(debugfile,
! 	      "ReadCh: Going to Raw mode\n"));
!     Raw(ON);
!     ClearScreen();
!     return redraw;
!   }
! 
!   if (redraw && redraw_screen) {
!     dprint(4,(debugfile,
! 	      "ReadCh: Pending redraw...\n"));
!     ClearScreen();
!     return redraw;
!   }
!   
!   if ((_intransmit != ON || redraw_screen) &&
!        cursorkeys && _transmit_on) {
!     dprint(4,(debugfile,
! 	      "ReadCh: Enabling cursor keys...\n"));
!     transmit_functions(ON);
!   }
! 
!   if ((_intransmit != OFF || redraw_screen) &&
!       nocursor && _transmit_off) {
!     dprint(4,(debugfile,
! 	      "ReadCh: Disabling cursor keys...\n"));
!     transmit_functions(OFF);
!   }
! 
!   if (cursorkeys) {
!     int i;
!     dprint(8,(debugfile,
! 	      "ReadCh: Available function keys:"));
! 
!     for (i = 0; keytable[i].str != 0; i++) {
!       char * const str = *(keytable[i].str);
!       if(str && str[0] != '\0') {
! 	keytable[i].maybe = 1;  /* Initially ewery function key is possible */
! 	dprint(8,(debugfile,
! 		  " [%d] %d",i,keytable[i].result));
! 
!       }
!     }      
!     dprint(8,(debugfile,
! 	      "\n"));
!   }
  
!   while (found_key == 0) {
!     int    result;
      unsigned char   ch;
+     
+     result = read(0, &ch, 1);
  
!     if (result < 0) {
!       int err = errno;
!       dprint(4,(debugfile,
! 		"ReadCh: errno = %d [%s]\n",err,
! 		error_description(err)));
! 
!       /* Return error: */
!       if (redraw && redraw_screen
! 	  || InGetPrompt   /* GetPrompt wants to see errors! */
! 	  ) {
! 	found_key = -1;
! 	continue;
!       }
!       if((errno == EINTR)
  #ifdef	EAGAIN
! 	 || (errno == EAGAIN)
  #endif
  #ifdef	EWOULDBLOCK
! 	 || (errno == EWOULDBLOCK)
! #endif
! 	 ) {
! 	continue;  /* Retry */
!       }
!     }
!     if (0 == result) {
!       dprint(4,(debugfile,
! 		"ReadCh: Got zero bytes...\n"));
!       found_key = -1;
!       continue;
!     }
! 
!     if (cursorkeys) {
!       int match = 0;
!       int i;
!       for (i = 0; keytable[i].str != NULL; i++) {
! 	if (keytable[i].maybe) {
! 	  unsigned char * const str = 
! 	    (unsigned char * const) *(keytable[i].str);
! 	  if (str[read_p] == ch) {
! 	    match++;
! 	    if (str[read_p+1] == '\0') {
! 	      found_key = keytable[i].result;
! 	      dprint(4,(debugfile,
! 			"ReadCh: Found function key = %d (keytable = %d, read_p =%d)\n",
! 			found_key,i,read_p));
! 	    }
! 	  } else {
! 	    keytable[i].maybe = 0;
! 	  }
! 	}
!       }
! #ifdef DEBUG
!       if (read_p < sizeof debug_buffer -1) {
! 	debug_buffer[read_p] = ch;
! 	debug_buffer[read_p+1] = '\0';
!       }
! #endif 
!       if (match == 0) {    /* Not in keytable */
! 	if (read_p == 0) 
! 	  found_key = ch;  /* Normal key */
! 	else {
! 	  int i;
! 	  dprint(4,(debugfile,
! 		    "ReadCh: Bad escape sequence; ch = %d, read_p = %d\n",
! 		    ch,read_p));
! #ifdef DEBUG
! 	  dprint(4,(debugfile,"ReadCh: Sequence was:"));
! 	  for (i = 0; i <= read_p && i < sizeof debug_buffer -1; i++) {
! 	    if (isascii(debug_buffer[i]) && isprint(debug_buffer[i])) {
! 	      dprint(4,(debugfile," %c (0x%02X)", 
! 			debug_buffer[i],debug_buffer[i]));
! 	    } else {
! 	      dprint(4,(debugfile," 0x%02X", debug_buffer[i]));
! 	    }
! 	  }
! 	  if (read_p > sizeof debug_buffer -1)
! 	    dprint(4,(debugfile," ..."));
! 	  dprint(4,(debugfile,"\n"));
  #endif
  
! 	  /* Ring a bell */
! 	  Writechar('\007');
! 	  goto reinit_ReadChar;
! 	}
!       } else
! 	read_p++;
!     } else
!       found_key = ch;
!     
!   }
! 
!   if (found_key <= 0 && redraw && redraw_screen) {
!     dprint(4,(debugfile,
! 	      "ReadCh: Redraw...\n"));
!     if(!RawState()) {  /* Check that we have in 'raw' mode */
!       dprint(4,(debugfile,
! 		"ReadCh: Going to Raw mode\n"));
!       Raw(ON);      
!     }
!     ClearScreen();
!     return redraw;
!   }
!   
!   return found_key;
  }
  
  outchar(c)
***************
*** 1039,1042 ****
  
  	putc(c, stdout);
  }
- 
--- 1356,1358 ----
Index: WORK/src/delete.c
*** elm2.4.25/src/delete.c	Sun Oct  4 00:58:49 1992
--- WORK/src/delete.c	Thu Jun 13 23:37:40 1996
***************
*** 90,96 ****
  	char tempbuf[3];
  
  	strcpy(tempbuf, show_status(ifmain(headers[msg]->status,
! 	                                   aliases[msg]->status)));
  
  	if (on_page(msg)) {
  	  MoveCursor(((compute_visible(msg+1)-1) % headers_per_page) + 4, 2);
--- 90,97 ----
  	char tempbuf[3];
  
  	strcpy(tempbuf, show_status(ifmain(headers[msg]->status,
! 	                                   aliases[msg]->status),
! 				    ifmain(headers[msg], NULL)));
  
  	if (on_page(msg)) {
  	  MoveCursor(((compute_visible(msg+1)-1) % headers_per_page) + 4, 2);
***************
*** 165,171 ****
  	    StartBold();
  	    PutLine2(((compute_visible(msg+1)-1) % headers_per_page) + 4,
  		   2, "%s%c", show_status(ifmain(headers[msg]->status,
! 		                                 aliases[msg]->status)),
  		   ison(ifmain(headers[msg]->status,
  		               aliases[msg]->status), TAGGED )? '+' : ' ');
  	    EndBold();
--- 166,173 ----
  	    StartBold();
  	    PutLine2(((compute_visible(msg+1)-1) % headers_per_page) + 4,
  		   2, "%s%c", show_status(ifmain(headers[msg]->status,
! 		                                 aliases[msg]->status),
! 					  ifmain(headers[msg], NULL)),
  		   ison(ifmain(headers[msg]->status,
  		               aliases[msg]->status), TAGGED )? '+' : ' ');
  	    EndBold();
***************
*** 173,179 ****
  	  else
  	    PutLine2(((compute_visible(msg+1)-1) % headers_per_page) + 4,
  		   2, "%s%c", show_status(ifmain(headers[msg]->status,
! 		                                 aliases[msg]->status)),
  		   ison(ifmain(headers[msg]->status,
  		               aliases[msg]->status), TAGGED )? '+' : ' ');
  }
--- 175,203 ----
  	  else
  	    PutLine2(((compute_visible(msg+1)-1) % headers_per_page) + 4,
  		   2, "%s%c", show_status(ifmain(headers[msg]->status,
! 		                                 aliases[msg]->status),
! 					ifmain(headers[msg], NULL)),
  		   ison(ifmain(headers[msg]->status,
  		               aliases[msg]->status), TAGGED )? '+' : ' ');
+ }
+ 
+ int
+ DeleteTagged()
+ {
+ /** delete all tagged messages.  return TRUE if the current message was
+     deleted. **/
+   int iindex, count = 0;
+   char buf[STRING];
+ 
+   if (!inalias) {
+     for (iindex=0; iindex < message_count; iindex++)
+       if (headers[iindex]->status & TAGGED) {
+         headers[iindex]->status |= DELETED;
+         count++;
+         show_new_status(iindex);
+       }
+     sprintf(buf, "%d message%s deleted.", count, count != 1 ? "s" : "");
+     Centerline(elm_LINES, buf);
+     return(headers[current-1]->status & DELETED ? 1 : 0);
+   }
  }
Index: WORK/src/edit.c
*** elm2.4.25/src/edit.c	Tue Aug 30 18:07:04 1994
--- WORK/src/edit.c	Thu Jun 13 23:37:48 1996
***************
*** 83,89 ****
  {
  	int err = errno;
  
! 	MoveCursor(LINES, 0);
  	Raw(OFF);
  
  	MCprintf(catgets(elm_msg_cat, ElmSet, ElmCouldntCopyMailfile,
--- 83,89 ----
  {
  	int err = errno;
  
! 	MoveCursor(elm_LINES, 0);
  	Raw(OFF);
  
  	MCprintf(catgets(elm_msg_cat, ElmSet, ElmCouldntCopyMailfile,
***************
*** 95,102 ****
  		edited_file);
  	printf("** %s. **\n", error_description(err));
  
- 	if (mailfile)
- 	    fflush (mailfile);
  	unlock();					/* ciao!*/
  	emergency_exit();
  }
--- 95,100 ----
***************
*** 139,145 ****
  
  	if (folder_type == SPOOL) {	/* uh oh... now the toughie...  */
  
! 	  fflush (mailfile);
  
  	  if (bytes(cur_folder) != mailfile_size) {
  
--- 137,143 ----
  
  	if (folder_type == SPOOL) {	/* uh oh... now the toughie...  */
  
! 	  flush_mailfile();
  
  	  if (bytes(cur_folder) != mailfile_size) {
  
***************
*** 147,154 ****
  		on the folder.  We'll have to do some strange stuff to
  	        remedy the problem... */
  
! 	     PutLine0(LINES, 0, catgets(elm_msg_cat, ElmSet, ElmWarnNewMailRecv,
! 	       "Warning: new mail received..."));
  	     CleartoEOLN();
  
  	     if ((temp_folder = fopen(edited_file, "a")) == NULL) {
--- 145,153 ----
  		on the folder.  We'll have to do some strange stuff to
  	        remedy the problem... */
  
! 	     PutLine0(elm_LINES, 0, catgets(elm_msg_cat, ElmSet, 
! 					    ElmWarnNewMailRecv,
! 					    "Warning: new mail received..."));
  	     CleartoEOLN();
  
  	     if ((temp_folder = fopen(edited_file, "a")) == NULL) {
***************
*** 171,177 ****
  		 "Couldn't open %s for reading!  Edit LOST!"), cur_folder);
  	       set_error(buffer);
  
- 		fflush (mailfile);
  	       unlock();
  	       return(1);
  	     }
--- 170,175 ----
***************
*** 182,188 ****
  	       set_error(catgets(elm_msg_cat, ElmSet, ElmCouldntSeekEnd,
  		 "Couldn't seek to end of folder.  Edit LOST!"));
  
- 		fflush (mailfile);
  	       unlock();
  	       return(1);
  	     }
--- 180,185 ----
***************
*** 226,232 ****
  	   setgid(groupid);
  #endif
  
- 	   fflush (mailfile);
  	   unlock();
  	   unlink(edited_file);	/* remove the edited mailfile */
  	   error(catgets(elm_msg_cat, ElmSet, ElmChangesIncorporated,
--- 223,228 ----
***************
*** 257,264 ****
  
  	char     buffer[SLEN];
  
! 	PutLine0(LINES-1,0, catgets(elm_msg_cat, ElmSet, ElmInvokeEditor,
! 	  "Invoking editor..."));
  
  	if (strcmp(editor, "builtin") == 0 || strcmp(editor, "none") == 0) {
  	  if (in_string(alternative_editor, "%s"))
--- 253,260 ----
  
  	char     buffer[SLEN];
  
! 	PutLine0(elm_LINES-1,0, catgets(elm_msg_cat, ElmSet, ElmInvokeEditor,
! 					"Invoking editor..."));
  
  	if (strcmp(editor, "builtin") == 0 || strcmp(editor, "none") == 0) {
  	  if (in_string(alternative_editor, "%s"))
Index: WORK/src/editmsg.c
*** elm2.4.25/src/editmsg.c	Thu Sep  1 22:42:40 1994
--- WORK/src/editmsg.c	Sun Aug  4 21:59:19 1996
***************
*** 154,159 ****
--- 154,160 ----
  
  #include "headers.h"
  #include "s_elm.h"
+ #include "me.h"
  #include <errno.h>
  
  char *error_description(), *format_long(), *strip_commas();
***************
*** 470,476 ****
  	  }
  	}
  
! 	optionally_enter(buffer, -1, -1, TRUE, FALSE);	/* already data! */
  
  	if(expanded_buffer != NULL) {
  	  build_address(strip_commas(buffer), expanded_buffer);
--- 471,477 ----
  	  }
  	}
  
! 	optionally_enter(buffer, -1, -1, OE_APPEND_CURRENT);  /* already data! */
  
  	if(expanded_buffer != NULL) {
  	  build_address(strip_commas(buffer), expanded_buffer);
***************
*** 588,595 ****
  	    return(no_editor_edit_the_message(filename));
  	}
  
! 	PutLine0(LINES, 0, catgets(elm_msg_cat, ElmSet, ElmInvokeEditor,
! 	  "Invoking editor..."));
  	fflush(stdout);
  
  	if (strlen(buffer) == 0) {
--- 589,596 ----
  	    return(no_editor_edit_the_message(filename));
  	}
  
! 	PutLine0(elm_LINES, 0, catgets(elm_msg_cat, ElmSet, ElmInvokeEditor,
! 				       "Invoking editor..."));
  	fflush(stdout);
  
  	if (strlen(buffer) == 0) {
***************
*** 604,612 ****
  	if (( old_raw = RawState()) == ON)
  	  Raw(OFF);
  
- 	if (cursor_control)
- 	  transmit_functions(OFF);		/* function keys are local */
- 
  	if ((stat = system_call(buffer, SY_ENAB_SIGHUP|SY_DUMPSTATE)) == -1) {
  	  err = errno;
  	  dprint(1,(debugfile, 
--- 605,610 ----
***************
*** 613,619 ****
  		  "System call failed with stat %d (edit_the_message)\n", 
  		  stat));
  	  dprint(1, (debugfile, "** %s **\n", error_description(err)));
! 	  ClearLine(LINES-1);
  	  error1(catgets(elm_msg_cat, ElmSet, ElmCantInvokeEditor,
  	    "Can't invoke editor '%s' for composition."), editor);
  	  if (sleepmsg > 0)
--- 611,617 ----
  		  "System call failed with stat %d (edit_the_message)\n", 
  		  stat));
  	  dprint(1, (debugfile, "** %s **\n", error_description(err)));
! 	  ClearLine(elm_LINES-1);
  	  error1(catgets(elm_msg_cat, ElmSet, ElmCantInvokeEditor,
  	    "Can't invoke editor '%s' for composition."), editor);
  	  if (sleepmsg > 0)
***************
*** 627,637 ****
  	   Raw(ON);
  
  	SetXYLocation(0, 40);	/* a location not near the next request, so an absolute is used */
! 	MoveCursor(LINES, 0);	/* dont know where we are, force last row, col 0 */
  
- 	if (cursor_control)
- 	  transmit_functions(ON);		/* function keys are local */
- 	
  	return(return_value);
  }
  
--- 625,632 ----
  	   Raw(ON);
  
  	SetXYLocation(0, 40);	/* a location not near the next request, so an absolute is used */
! 	MoveCursor(elm_LINES, 0);	/* dont know where we are, force last row, col 0 */
  
  	return(return_value);
  }
  
***************
*** 802,808 ****
  	       case 'o' : Write_to_screen(catgets(elm_msg_cat, ElmSet, ElmEnterNameEditor,
  			     "\n\rPlease enter the name of the editor: "), 0);
  			  editor_name[0] = '\0';
! 			  optionally_enter(editor_name,-1,-1, FALSE, FALSE);
  			  NewLine();
  			  if (strlen(editor_name) > 0) {
  			    strcpy(buffer, editor);
--- 797,807 ----
  	       case 'o' : Write_to_screen(catgets(elm_msg_cat, ElmSet, ElmEnterNameEditor,
  			     "\n\rPlease enter the name of the editor: "), 0);
  			  editor_name[0] = '\0';
! 			  if (optionally_enter(editor_name,-1,-1, 0) != 0) {
! 			    NewLine();
! 			    goto more_input;
! 			  }
! 
  			  NewLine();
  			  if (strlen(editor_name) > 0) {
  			    strcpy(buffer, editor);
***************
*** 833,839 ****
  	      		     read_in_file(edit_fd, (char *) buffer + 3, 0);
  			     (void) unlink((char *) buffer+3);
  			     SetXYLocation(0, 40);	/* a location not near the next request, so an absolute is used */
! 			     MoveCursor(LINES, 0);	/* and go to a known location, last row col 0 */
  			   }
  			   goto more_input; 
  
--- 832,838 ----
  	      		     read_in_file(edit_fd, (char *) buffer + 3, 0);
  			     (void) unlink((char *) buffer+3);
  			     SetXYLocation(0, 40);	/* a location not near the next request, so an absolute is used */
! 			     MoveCursor(elm_LINES, 0);	/* and go to a known location, last row col 0 */
  			   }
  			   goto more_input; 
  
***************
*** 845,851 ****
  			   if (old_raw == ON)
  			      Raw(ON);
  			   SetXYLocation(0, 40);	/* a location not near the next request, so an absolute is used */
! 			   MoveCursor(LINES, 0);	/* and go to a known location, last row col 0 */
  	    		   Write_to_screen(simple_continue, 0);
  			   goto more_input;
  
--- 844,850 ----
  			   if (old_raw == ON)
  			      Raw(ON);
  			   SetXYLocation(0, 40);	/* a location not near the next request, so an absolute is used */
! 			   MoveCursor(elm_LINES, 0);	/* and go to a known location, last row col 0 */
  	    		   Write_to_screen(simple_continue, 0);
  			   goto more_input;
  
Index: WORK/src/elm.c
*** elm2.4.25/src/elm.c	Mon May 30 19:26:14 1994
--- WORK/src/elm.c	Thu Aug  8 22:36:57 1996
***************
*** 143,148 ****
--- 143,153 ----
  #  include <sys/timeb.h>
  #endif
  
+ #ifdef MIME
+ #include "mime.h"
+ #endif
+ #include "me.h"
+ 
  long bytes();
  char *format_long(), *parse_arguments(), *error_description();
  
***************
*** 176,183 ****
  	       "Send only mode [ELM %s]"), version_buff);
  	     Centerline(1, address);
  	   }
! 	   (void) send_msg(to_whom, "", batch_subject, TRUE,
! 	     (batch_only ? NO : allow_forms), FALSE); 
  	   leave(0);
  	} else if (check_only) {
  	   do_check_only(to_whom);
--- 181,189 ----
  	       "Send only mode [ELM %s]"), version_buff);
  	     Centerline(1, address);
  	   }
! 	   (void) send_msg(to_whom, "", batch_subject, 
! 			   MAIL_EDIT_MSG,
! 			   (batch_only ? NO : allow_forms));
  	   leave(0);
  	} else if (check_only) {
  	   do_check_only(to_whom);
***************
*** 193,206 ****
  
  	    ScreenSize(&newLINES, &newCOLUMNS);
  	    resize_screen = 0;
! 	    if (newLINES != LINES || newCOLUMNS != COLUMNS) {
! 	      LINES = newLINES, COLUMNS = newCOLUMNS;
  #undef max
  #define max(a,b)	       ((a) < (b) ? (b) : (a))
  	      if (mini_menu)
! 		headers_per_page = max (LINES - 13, 1);
  	      else
! 		headers_per_page = max (LINES -	 8, 1);	  /* 5 more headers! */
  #undef max
  	      redraw++;
  	    }
--- 199,212 ----
  
  	    ScreenSize(&newLINES, &newCOLUMNS);
  	    resize_screen = 0;
! 	    if (newLINES != elm_LINES || newCOLUMNS != elm_COLUMNS) {
! 	      elm_LINES = newLINES, elm_COLUMNS = newCOLUMNS;
  #undef max
  #define max(a,b)	       ((a) < (b) ? (b) : (a))
  	      if (mini_menu)
! 		headers_per_page = max (elm_LINES - 13, 1);
  	      else
! 		headers_per_page = max (elm_LINES -	 8, 1);	  /* 5 more headers! */
  #undef max
  	      redraw++;
  	    }
***************
*** 213,219 ****
  	  nucurr = 0;
  
  	  if (mailfile)
! 		  fflush (mailfile);
  
  	  if ((num = bytes(cur_folder)) != mailfile_size) {
  	    dprint(2, (debugfile, "Just received %d bytes more mail (elm)\n", 
--- 219,225 ----
  	  nucurr = 0;
  
  	  if (mailfile)
! 	    flush_mailfile();
  
  	  if ((num = bytes(cur_folder)) != mailfile_size) {
  	    dprint(2, (debugfile, "Just received %d bytes more mail (elm)\n", 
***************
*** 245,251 ****
  	      showscreen();
  	    else {
  	      update_title();
! 	      ClearLine(LINES-1);	     /* remove reading message... */
  	      if ((message_count - last_in_folder) == 1)
  	        error(catgets(elm_msg_cat, ElmSet, ElmNewMessageRecv,
  		       "1 new message received."));
--- 251,257 ----
  	      showscreen();
  	    else {
  	      update_title();
! 	      ClearLine(elm_LINES-1);	     /* remove reading message... */
  	      if ((message_count - last_in_folder) == 1)
  	        error(catgets(elm_msg_cat, ElmSet, ElmNewMessageRecv,
  		       "1 new message received."));
***************
*** 255,268 ****
  		       message_count - last_in_folder);
  	    }
  	    /* mailfile_size = num; */
- 	    if (cursor_control)
- 	      transmit_functions(ON);	/* insurance */
  	  }
- 
  	  prompt(Prompt);
  
  	  CleartoEOLN();
  	  ch = GetPrompt();
  #ifdef SIGWINCH
  	  if (resize_screen) {
  	    int	newLINES, newCOLUMNS;
--- 261,277 ----
  		       message_count - last_in_folder);
  	    }
  	    /* mailfile_size = num; */
  	  }
  	  prompt(Prompt);
  
  	  CleartoEOLN();
  	  ch = GetPrompt();
+ 
+ 	  if (redraw_screen) {
+ 	    redraw_screen = 0;
+ 	    redraw++;
+ 	  }
+ 
  #ifdef SIGWINCH
  	  if (resize_screen) {
  	    int	newLINES, newCOLUMNS;
***************
*** 269,281 ****
  
  	    ScreenSize(&newLINES, &newCOLUMNS);
  	    resize_screen = 0;
! 	    if (newLINES != LINES || newCOLUMNS != COLUMNS) {
! 	      LINES = newLINES, COLUMNS = newCOLUMNS;
  #define max(a,b)	       ((a) < (b) ? (b) : (a))
  	      if (mini_menu)
! 		headers_per_page = max (LINES - 13, 1);
  	      else
! 		headers_per_page = max (LINES -	 8, 1);	  /* 5 more headers! */
  #undef max
  	      redraw++;
  	    }
--- 278,290 ----
  
  	    ScreenSize(&newLINES, &newCOLUMNS);
  	    resize_screen = 0;
! 	    if (newLINES != elm_LINES || newCOLUMNS != elm_COLUMNS) {
! 	      elm_LINES = newLINES, elm_COLUMNS = newCOLUMNS;
  #define max(a,b)	       ((a) < (b) ? (b) : (a))
  	      if (mini_menu)
! 		headers_per_page = max (elm_LINES - 13, 1);
  	      else
! 		headers_per_page = max (elm_LINES - 8, 1);	  /* 5 more headers! */
  #undef max
  	      redraw++;
  	    }
***************
*** 282,298 ****
  	  }
  #endif
  	  CleartoEOS();
! #ifdef DEBUG
! 	  if (! movement_command(ch))
  	    dprint(4, (debugfile, "\nCommand: %c [%d]\n\n", ch, ch));
! #endif
  
  	  set_error("");	/* clear error buffer */
  
! 	  MoveCursor(LINES-3,strlen(Prompt));
  
  	  switch (ch) {
  
  	    case '?' 	:  if (help(FALSE))
  	  		     redraw++;
  			   else
--- 291,310 ----
  	  }
  #endif
  	  CleartoEOS();
! 
! 	  if (isascii(ch) && isprint(ch)) {
  	    dprint(4, (debugfile, "\nCommand: %c [%d]\n\n", ch, ch));
! 	  } else {
! 	    dprint(4, (debugfile, "\nCommand: %d\n\n", ch, ch));
! 	  }
  
  	  set_error("");	/* clear error buffer */
  
! 	  MoveCursor(elm_LINES-3,strlen(Prompt));
  
  	  switch (ch) {
  
+ 	  case HELP_MARK:
  	    case '?' 	:  if (help(FALSE))
  	  		     redraw++;
  			   else
***************
*** 299,305 ****
  			     nufoot++;
  			   break;
  
! 	    case '$'    :  PutLine0(LINES-3, strlen(Prompt),
  			     catgets(elm_msg_cat, ElmSet, ElmResyncFolder,
  	    		     "Resynchronize folder"));
  			   redraw += resync();
--- 311,317 ----
  			     nufoot++;
  			   break;
  
! 	    case '$'    :  PutLine0(elm_LINES-3, strlen(Prompt),
  			     catgets(elm_msg_cat, ElmSet, ElmResyncFolder,
  	    		     "Resynchronize folder"));
  			   redraw += resync();
***************
*** 312,320 ****
  			       "No mail to pipe!"));
  			     fflush(stdin);
  			   } else {
! 	    		     softkeys_off();
                               redraw += do_pipe();		
! 			     softkeys_on();
  			   }
  			   break;
  
--- 324,332 ----
  			       "No mail to pipe!"));
  			     fflush(stdin);
  			   } else {
! 	    		     /* softkeys_off(); */
                               redraw += do_pipe();		
! 			     /* softkeys_on(); */
  			   }
  			   break;
  
***************
*** 327,333 ****
  	    case '%'    :  if (current > 0) {
  			     get_return(address, current-1);
  			     clear_error();
! 			     PutLine1(LINES,(COLUMNS-strlen(address))/2,
  				      "%.78s", address);	
  			   } else {
  			     error(catgets(elm_msg_cat, ElmSet, ElmNoMailReturnAddress,
--- 339,346 ----
  	    case '%'    :  if (current > 0) {
  			     get_return(address, current-1);
  			     clear_error();
! 			     PutLine1(elm_LINES,
! 				      (elm_COLUMNS-strlen(address))/2,
  				      "%.78s", address);	
  			   } else {
  			     error(catgets(elm_msg_cat, ElmSet, ElmNoMailReturnAddress,
***************
*** 344,350 ****
  			     fflush(stdin);
  			   }
  			   else {
! 			       PutLine0(LINES-3, strlen(Prompt), 	
  			           catgets(elm_msg_cat, ElmSet, ElmScanForCalendar,
  				   "Scan message for calendar entries..."));
  			       scan_calendar();
--- 357,363 ----
  			     fflush(stdin);
  			   }
  			   else {
! 			       PutLine0(elm_LINES-3, strlen(Prompt), 	
  			           catgets(elm_msg_cat, ElmSet, ElmScanForCalendar,
  				   "Scan message for calendar entries..."));
  			       scan_calendar();
***************
*** 358,366 ****
  
  	    case 'a'    :  alias();
  			   redraw++;
! 			   define_softkeys(MAIN); 	break;
  			
! 	    case 'b'    :  PutLine0(LINES-3, strlen(Prompt), 
  			     catgets(elm_msg_cat, ElmSet, ElmBounceMessage,
  			     "Bounce message"));
  			   fflush(stdout);
--- 371,379 ----
  
  	    case 'a'    :  alias();
  			   redraw++;
! 			   /* define_softkeys(MAIN); */	break;
  			
! 	    case 'b'    :  PutLine0(elm_LINES-3, strlen(Prompt), 
  			     catgets(elm_msg_cat, ElmSet, ElmBounceMessage,
  			     "Bounce message"));
  			   fflush(stdout);
***************
*** 373,394 ****
  			     nufoot = remail();
  			   break;
  
! 	    case 'c'    :  PutLine0(LINES-3, strlen(Prompt), 
  			     catgets(elm_msg_cat, ElmSet, ElmChangeFolder,
  			     "Change folder"));
! 			   define_softkeys(CHANGE);
  			   redraw += change_file();
! 			   define_softkeys(MAIN);
  			   break;
  
  #ifdef ALLOW_MAILBOX_EDITING
! 	    case 'e'    :  PutLine0(LINES-3,strlen(Prompt),
  			     catgets(elm_msg_cat, ElmSet, ElmEditFolder,
  			     "Edit folder"));
  			   if (current > 0) {
  			     edit_mailbox();
- 	    		     if (cursor_control)
- 			       transmit_functions(ON);	/* insurance */
  	   		   }
  			   else {
  			     error(catgets(elm_msg_cat, ElmSet, ElmFolderIsEmpty,
--- 386,410 ----
  			     nufoot = remail();
  			   break;
  
! 	    case 'c'    :  PutLine0(elm_LINES-3, strlen(Prompt), 
  			     catgets(elm_msg_cat, ElmSet, ElmChangeFolder,
  			     "Change folder"));
! 	                   /* define_softkeys(CHANGE); */
  			   redraw += change_file();
! 			   /* define_softkeys(MAIN); */
  			   break;
  
  #ifdef ALLOW_MAILBOX_EDITING
! 	    case 'e'    :  if (user_level < 2) {
! 				error("You are not experienced to use folder editing");
! 				fflush(stdin);
! 				break;
! 			   }
! 			   PutLine0(elm_LINES-3,strlen(Prompt),
  			     catgets(elm_msg_cat, ElmSet, ElmEditFolder,
  			     "Edit folder"));
  			   if (current > 0) {
  			     edit_mailbox();
  	   		   }
  			   else {
  			     error(catgets(elm_msg_cat, ElmSet, ElmFolderIsEmpty,
***************
*** 402,412 ****
  			  fflush(stdin);
  			  break;
  #endif
! 		
! 	    case 'f'    :  PutLine0(LINES-3, strlen(Prompt),
  			     catgets(elm_msg_cat, ElmSet, ElmForward,
  			     "Forward"));
! 			   define_softkeys(YESNO);
  			   if (current > 0) {
  			     if(forward()) redraw++;
  			     else nufoot++;
--- 418,447 ----
  			  fflush(stdin);
  			  break;
  #endif
! #ifdef USE_PGP
! 	    case ctrl('E'):
!               if (message_count < 1)
!                 error(catgets(elm_msg_cat, ElmSet, ElmNoMailInFolder,
! 			"There is no mail in this folder!"));
!               else {
!   	        Write_to_screen("Extract PGP public key",0);
! 	        if (headers[current-1]->pgp & PGP_PUBLIC_KEY)
! 	  	  redraw = pgp_extract_public_key();
! 	        else
! 		  error("This message does not contain PGP public keys!");
!               }
! 	      break;
! 
!            case ctrl('F'):
!               pgp_void_passphrase();
!               error("Passphrase forgotten!");
!               break;
! #endif
! 
! 	    case 'f'    :  PutLine0(elm_LINES-3, strlen(Prompt),
  			     catgets(elm_msg_cat, ElmSet, ElmForward,
  			     "Forward"));
! 	                   /* define_softkeys(YESNO); */
  			   if (current > 0) {
  			     if(forward()) redraw++;
  			     else nufoot++;
***************
*** 415,424 ****
  			       "No mail to forward!"));
  			     fflush(stdin);
  			   }
! 			   define_softkeys(MAIN);
  			   break;
  
! 	    case 'g'    :  PutLine0(LINES-3,strlen(Prompt),
  			     catgets(elm_msg_cat, ElmSet, ElmGroupReply,
  			     "Group reply"));
  			   fflush(stdout);
--- 450,459 ----
  			       "No mail to forward!"));
  			     fflush(stdin);
  			   }
! 			   /* define_softkeys(MAIN); */
  			   break;
  
! 	    case 'g'    :  PutLine0(elm_LINES-3,strlen(Prompt),
  			     catgets(elm_msg_cat, ElmSet, ElmGroupReply,
  			     "Group reply"));
  			   fflush(stdout);
***************
*** 429,437 ****
  			       fflush(stdin);
  			     }
  			     else {
! 			       define_softkeys(YESNO);
  			       redraw += reply_to_everyone();	
! 			       define_softkeys(MAIN);
  			     }
  			   }
  			   else {
--- 464,472 ----
  			       fflush(stdin);
  			     }
  			     else {
! 			       /* define_softkeys(YESNO); */
  			       redraw += reply_to_everyone();	
! 			       /* define_softkeys(MAIN); */
  			     }
  			   }
  			   else {
***************
*** 441,462 ****
  			   }
  			   break;
  
! 	    case 'h'    :  if (filter)
! 			     PutLine0(LINES-3, strlen(Prompt), 
  			       catgets(elm_msg_cat, ElmSet, ElmMessageWithHeaders,
  			       "Message with headers..."));
  			   else
! 			     PutLine0(LINES-3, strlen(Prompt),
  			       catgets(elm_msg_cat, ElmSet, ElmDisplayMessage,
  			       "Display message"));
  			   if(current > 0) {
  			     fflush(stdout);
! 			     j = filter;
! 			     filter = FALSE;
  			     i = show_msg(current);
  			     while (i)
  				i = process_showmsg_cmd(i);
! 			     filter = j;
  			     redraw++;
  			     (void)get_page(current);
  			   } else
--- 476,497 ----
  			   }
  			   break;
  
! 	    case 'h'    :  if (elm_filter)
! 			     PutLine0(elm_LINES-3, strlen(Prompt), 
  			       catgets(elm_msg_cat, ElmSet, ElmMessageWithHeaders,
  			       "Message with headers..."));
  			   else
! 			     PutLine0(elm_LINES-3, strlen(Prompt),
  			       catgets(elm_msg_cat, ElmSet, ElmDisplayMessage,
  			       "Display message"));
  			   if(current > 0) {
  			     fflush(stdout);
! 			     j = elm_filter;
! 			     elm_filter = FALSE;
  			     i = show_msg(current);
  			     while (i)
  				i = process_showmsg_cmd(i);
! 			     elm_filter = j;
  			     redraw++;
  			     (void)get_page(current);
  			   } else
***************
*** 464,483 ****
  			       "No mail to read!"));
  			   break;
  
! 	    case 'm'    :  PutLine0(LINES-3, strlen(Prompt),
  			     catgets(elm_msg_cat, ElmSet, ElmMail,
  			     "Mail"));
!  			   redraw += send_msg("", "", "", TRUE,allow_forms,FALSE); 
! 			   break;
  
  	    case ' '    : 
  	    case ctrl('J'):
! 	    case ctrl('M'): PutLine0(LINES-3, strlen(Prompt), 
! 			      catgets(elm_msg_cat, ElmSet, ElmDisplayMessage,
! 	    		      "Display message"));	
  			   fflush(stdout);
  			   if(current > 0 ) {
! 			     define_softkeys(READ);
  
  			     i = show_msg(current);
  			     while (i)
--- 499,527 ----
  			       "No mail to read!"));
  			   break;
  
! #ifdef USE_PGP
!             case ctrl('K'):
! 	                   PutLine0(elm_LINES-3, strlen(Prompt), 
! 				    "Mail PGP public key");
! 	                   redraw = pgp_mail_public_key ();
!                            break;
! #endif
! 	    case 'm'    :  PutLine0(elm_LINES-3, strlen(Prompt),
  			     catgets(elm_msg_cat, ElmSet, ElmMail,
  			     "Mail"));
!  			   redraw += send_msg("", "", "", MAIL_EDIT_MSG,
! 					      allow_forms);
! 	                   break;
  
  	    case ' '    : 
  	    case ctrl('J'):
! 	    case ctrl('M'): PutLine0(elm_LINES-3, strlen(Prompt), 
! 				     catgets(elm_msg_cat, ElmSet, 
! 					     ElmDisplayMessage,
! 					     "Display message"));	
  			   fflush(stdout);
  			   if(current > 0 ) {
! 			     /* define_softkeys(READ); */
  
  			     i = show_msg(current);
  			     while (i)
***************
*** 489,502 ****
  			       "No mail to read!"));
  			   break;
  
! 	    case 'n'    :  PutLine0(LINES-3,strlen(Prompt),
! 			     catgets(elm_msg_cat, ElmSet, ElmNextMessage,
! 			     "Next Message"));
  			   fflush(stdout);
! 			   define_softkeys(READ);
  
  			   if(current > 0 ) {
! 			     define_softkeys(READ);
  
  			     i = show_msg(current);
  			     while (i)
--- 533,547 ----
  			       "No mail to read!"));
  			   break;
  
! 	    case 'n'    :  PutLine0(elm_LINES-3,strlen(Prompt),
! 				    catgets(elm_msg_cat, ElmSet, 
! 					    ElmNextMessage,
! 					    "Next Message"));
  			   fflush(stdout);
! 			   /* define_softkeys(READ); */
  
  			   if(current > 0 ) {
! 			     /* define_softkeys(READ); */
  
  			     i = show_msg(current);
  			     while (i)
***************
*** 510,518 ****
  			       "No mail to read!"));
  			   break;
  
! 	    case 'o'    :  PutLine0(LINES-3, strlen(Prompt),
! 			     catgets(elm_msg_cat, ElmSet, ElmOptions,
! 			     "Options"));
  			   if((i=options()) > 0)
  			     get_page(current);
  			   else if(i < 0)
--- 555,563 ----
  			       "No mail to read!"));
  			   break;
  
! 	    case 'o'    :  PutLine0(elm_LINES-3, strlen(Prompt),
! 				    catgets(elm_msg_cat, ElmSet, ElmOptions,
! 					    "Options"));
  			   if((i=options()) > 0)
  			     get_page(current);
  			   else if(i < 0)
***************
*** 520,528 ****
  			   redraw++;	/* always fix da screen... */
  			   break;
  
! 	    case 'p'    :  PutLine0(LINES-3, strlen(Prompt),
! 			     catgets(elm_msg_cat, ElmSet, ElmPrintMail,
! 			     "Print mail"));
  			   fflush(stdout);
  			   if (message_count < 1) {
  			     error(catgets(elm_msg_cat, ElmSet, ElmNoMailToPrint,
--- 565,573 ----
  			   redraw++;	/* always fix da screen... */
  			   break;
  
! 	    case 'p'    :  PutLine0(elm_LINES-3, strlen(Prompt),
! 				    catgets(elm_msg_cat, ElmSet, ElmPrintMail,
! 					    "Print mail"));
  			   fflush(stdout);
  			   if (message_count < 1) {
  			     error(catgets(elm_msg_cat, ElmSet, ElmNoMailToPrint,
***************
*** 532,540 ****
  			     redraw++;
  			   break;
  
! 	    case 'q'    :  PutLine0(LINES-3, strlen(Prompt),
! 			     catgets(elm_msg_cat, ElmSet, ElmQuit,
! 			     "Quit"));
  
  			   if (mailfile_size != bytes(cur_folder)) {
  			     error(catgets(elm_msg_cat, ElmSet, ElmNewMailQuitCancelled,
--- 577,585 ----
  			     redraw++;
  			   break;
  
! 	    case 'q'    :  PutLine0(elm_LINES-3, strlen(Prompt),
! 				    catgets(elm_msg_cat, ElmSet, ElmQuit,
! 					    "Quit"));
  
  			   if (mailfile_size != bytes(cur_folder)) {
  			     error(catgets(elm_msg_cat, ElmSet, ElmNewMailQuitCancelled,
***************
*** 542,548 ****
  			     fflush(stdin);
  
  			     if (folder_type == SPOOL) {
- 				fflush (mailfile);
  				unlock();
  			     }
  			   }
--- 587,592 ----
***************
*** 551,565 ****
  
  			   break;
  
! 	    case 'Q'    :  PutLine0(LINES-3, strlen(Prompt),
! 			     catgets(elm_msg_cat, ElmSet, ElmQuickQuit,
! 			     "Quick quit"));
  
  			   if (mailfile_size != bytes(cur_folder)) {
  			     error(catgets(elm_msg_cat, ElmSet, ElmNewMailQuickQuitCancelled,
  			       "New Mail!  Quick Quit canceled..."));
  	  		     if (folder_type == SPOOL) {
- 				fflush (mailfile);
  				unlock();
  			     }
  			   }
--- 595,608 ----
  
  			   break;
  
! 	    case 'Q'    :  PutLine0(elm_LINES-3, strlen(Prompt),
! 				    catgets(elm_msg_cat, ElmSet, ElmQuickQuit,
! 					    "Quick quit"));
  
  			   if (mailfile_size != bytes(cur_folder)) {
  			     error(catgets(elm_msg_cat, ElmSet, ElmNewMailQuickQuitCancelled,
  			       "New Mail!  Quick Quit canceled..."));
  	  		     if (folder_type == SPOOL) {
  				unlock();
  			     }
  			   }
***************
*** 568,576 ****
  
  			   break;
  
! 	    case 'r'    :  PutLine0(LINES-3, strlen(Prompt), 
! 			     catgets(elm_msg_cat, ElmSet, ElmReplyToMessage,
! 			     "Reply to message"));
  			   if (current > 0) 
  			     redraw += reply();	
  			   else {
--- 611,620 ----
  
  			   break;
  
! 	  case 'r'    :  PutLine0(elm_LINES-3, strlen(Prompt), 
! 				  catgets(elm_msg_cat, ElmSet, 
! 					  ElmReplyToMessage,
! 					  "Reply to message"));
  			   if (current > 0) 
  			     redraw += reply();	
  			   else {
***************
*** 578,584 ****
  			       "No mail to reply to!")); 
  			     fflush(stdin);
  			   }
! 			   softkeys_on();
  			   break;
  
  	    case '>'    : /** backwards compatibility **/
--- 622,628 ----
  			       "No mail to reply to!")); 
  			     fflush(stdin);
  			   }
! 			   /* softkeys_on(); */
  			   break;
  
  	    case '>'    : /** backwards compatibility **/
***************
*** 595,610 ****
  			   }
  			   else {
  			     if (ch != 'C')
! 			       PutLine0(LINES-3, strlen(Prompt),
! 				      catgets(elm_msg_cat, ElmSet, ElmSaveToFolder,
! 				      "Save to folder"));
  			     else
! 			       PutLine0(LINES-3, strlen(Prompt),
! 				      catgets(elm_msg_cat, ElmSet, ElmCopyToFolder,
! 				      "Copy to folder"));
! 			     PutLine0(LINES-3,COLUMNS-40,
! 			        catgets(elm_msg_cat, ElmSet, ElmUseForHelp,
! 				"(Use '?' for help)"));
  			     if (save(&redraw, FALSE, (ch != 'C'))
  				 && resolve_mode && ch != 'C') {
  			       if((i=next_message(current-1, TRUE)) != -1) {
--- 639,657 ----
  			   }
  			   else {
  			     if (ch != 'C')
! 			       PutLine0(elm_LINES-3, strlen(Prompt),
! 					catgets(elm_msg_cat, ElmSet, 
! 						ElmSaveToFolder,
! 						"Save to folder"));
  			     else
! 			       PutLine0(elm_LINES-3, strlen(Prompt),
! 					catgets(elm_msg_cat, ElmSet, 
! 						ElmCopyToFolder,
! 						"Copy to folder"));
! 			     PutLine0(elm_LINES-3,elm_COLUMNS-40,
! 				      catgets(elm_msg_cat, ElmSet, 
! 					      ElmUseForHelp,
! 					      "(Use '?' for help)"));
  			     if (save(&redraw, FALSE, (ch != 'C'))
  				 && resolve_mode && ch != 'C') {
  			       if((i=next_message(current-1, TRUE)) != -1) {
***************
*** 613,632 ****
  			       }
  			     }
  			   }
! 			   ClearLine(LINES-2);		
  			   break;
! 
! 	    case 'X'    :  PutLine0(LINES-3, strlen(Prompt),
! 			     catgets(elm_msg_cat, ElmSet, ElmQuickExit,
! 			     "Quick Exit"));
                             fflush(stdout);
  			   leave(0);
  			   break;
! 
  	    case ctrl('Q') :
! 	    case 'x'    :  PutLine0(LINES-3, strlen(Prompt),
! 			     catgets(elm_msg_cat, ElmSet, ElmExit,
! 			     "Exit"));  
                             fflush(stdout);
  			   exit_prog();
  			   break;
--- 660,699 ----
  			       }
  			     }
  			   }
! 			   ClearLine(elm_LINES-2);		
  			   break;
! #ifdef MIME
! 	    case 'v'    :  if (headers) {	      
! 	                    if (headers[current-1]->status & MIME_MESSAGE) {
! 			      mime_warnings(headers[current-1]);
! 			      attach_parse (headers[current-1], mailfile);
! 			      if (headers[current-1]->mime_rec.parts)
! 				(void) attach_menu (headers[current-1]->
! 						    mime_rec.parts, TRUE);
! 			      else 
! 				/* So we can save mail in decoded ... */
! 				(void) attach_menu (&(headers[current-1]->
! 						      mime_rec),TRUE);
! 			      redraw++;
! 			    }
!                              else
!                                error ("This is not a MIME message!");
!                            }
!                            else
!                              error ("There are no messages!");
!                            break;
! #endif
! 	    case 'X'    :  PutLine0(elm_LINES-3, strlen(Prompt),
! 				    catgets(elm_msg_cat, ElmSet, ElmQuickExit,
! 					    "Quick Exit"));
                             fflush(stdout);
  			   leave(0);
  			   break;
! 		
  	    case ctrl('Q') :
! 	    case 'x'    :  PutLine0(elm_LINES-3, strlen(Prompt),
! 				    catgets(elm_msg_cat, ElmSet, ElmExit,
! 					    "Exit"));  
                             fflush(stdout);
  			   exit_prog();
  			   break;
***************
*** 664,675 ****
  	    show_current();
  	  else if (nufoot) {
  	    if (mini_menu) {
! 	      MoveCursor(LINES-7, 0);  
                CleartoEOS();
  	      show_menu();
  	    }
  	    else {
! 	      MoveCursor(LINES-4, 0);
  	      CleartoEOS();
  	    }
  	    show_last_error();	/* for those operations that have to
--- 731,742 ----
  	    show_current();
  	  else if (nufoot) {
  	    if (mini_menu) {
! 	      MoveCursor(elm_LINES-7, 0);  
                CleartoEOS();
  	      show_menu();
  	    }
  	    else {
! 	      MoveCursor(elm_LINES-4, 0);
  	      CleartoEOS();
  	    }
  	    show_last_error();	/* for those operations that have to
***************
*** 688,693 ****
--- 755,761 ----
  	register int i, j;
  	char     buffer[SLEN];
  
+ redraw:
  	ClearScreen();
  
  	PutLine2(0,0,"Current message number = %d\t\t%d message(s) total\n",
***************
*** 706,725 ****
  "Num      From                    Subject                Lines   Offset  Content\n\r\n\r",0);
  
  	while (i <= j) {
! 	   sprintf(buffer, 
! 	   "%3d %-16.16s %-35.35s %4d %8d %8d\n\r",
! 		    i+1,
! 		    headers[i]->from, 
! 		    headers[i]->subject,
! 		    headers[i]->lines,
! 		    headers[i]->offset,
! 		    headers[i]->content_length);
! 	    Write_to_screen(buffer, 0);
  	  i++;
  	}
  	
! 	PutLine0(LINES,0,"Press any key to return.");
! 	(void) ReadCh();
  }
  
  
--- 774,808 ----
  "Num      From                    Subject                Lines   Offset  Content\n\r\n\r",0);
  
  	while (i <= j) {
! 	  char buffer_2[STRING];
! 
! 	  char * From = headers[i]->from;
! 
! #ifdef MIME
! 	  if (!(headers[i] -> status & NOHDRENCODING)
! 	      && is_rfc1522(From)) {
! 	    strfcpy(buffer_2,From,sizeof(buffer_2));
! 
! 	    rfc1522_decode(buffer_2,sizeof(buffer_2));
! 	    From = buffer_2;
! 	  }
! #endif
! 	  sprintf(buffer, 
! 		  "%3d %-16.16s %-35.35s %4d %8d %8d\n\r",
! 		  i+1,
! 		  From, 
! 		  headers[i]->subject,
! 		  headers[i]->lines,
! 		  headers[i]->offset,
! 		  headers[i]->content_length);
! 	  Write_to_screen(buffer, 0);
! 
  	  i++;
  	}
  	
! 	PutLine0(elm_LINES,0,"Press any key to return.");
! 	if (REDRAW_MARK == ReadCh(REDRAW_MARK))
! 	  goto redraw;
  }
  
  
***************
*** 732,737 ****
--- 815,821 ----
  	time_t header_time;
  	register struct header_rec *current_header = headers[current-1];
  
+ redraw:
  	ClearScreen();
  
  	Write_to_screen("\t\t\t----- Message %d -----\n\r\n\r\n\r\n\r", 1,
***************
*** 738,751 ****
  		current);
  
  	Write_to_screen(     "Lines : %-5d\t\t\tStatus: A  C  D  E  F  M  D  N  N  O  P  T  U  V\n\r", 1,
! 		current_header->lines);
  	Write_to_screen("Content-Length: %-12d\t        c  o  e  x  o  i  e  p  e  l  r  a  r  i\n\r", 1,
! 		current_header->content_length);
! 	Write_to_screen(     "            \t\t\t        t  n  l  p  r  m  c  l  w  d  i  g  g  s\n\r", 0);
  	Write_to_screen(     "            \t\t\t        n  f  d  d  m  e  o  a        v  d  n  i\n\r", 0);
  
  	sprintf(buffer, 
! 		"\n\rOffset: %ld\t\t\t        %d  %d  %d  %d  %d  %d  %d  %d",
  		current_header->offset,
  		(current_header->status & ACTION) != 0,
  		(current_header->status & CONFIDENTIAL) != 0,
--- 822,836 ----
  		current);
  
  	Write_to_screen(     "Lines : %-5d\t\t\tStatus: A  C  D  E  F  M  D  N  N  O  P  T  U  V\n\r", 1,
! 			current_header->lines);
  	Write_to_screen("Content-Length: %-12d\t        c  o  e  x  o  i  e  p  e  l  r  a  r  i\n\r", 1,
! 			current_header->content_length);
! 	Write_to_screen(       "Binary: %d\t\t\t        t  n  l  p  r  m  c  l  w  d  i  g  g  s\n\r", 1,
! 			current_header->binary);
  	Write_to_screen(     "            \t\t\t        n  f  d  d  m  e  o  a        v  d  n  i\n\r", 0);
  
  	sprintf(buffer, 
! 		"\n\rOffset: %ld\t\t\t        %d  %d  %d  %d  %d  %d  ",
  		current_header->offset,
  		(current_header->status & ACTION) != 0,
  		(current_header->status & CONFIDENTIAL) != 0,
***************
*** 752,760 ****
  		(current_header->status & DELETED) != 0,
  		(current_header->status & EXPIRED) != 0,
  		(current_header->status & FORM_LETTER) != 0,
! 		(current_header->status & MIME_MESSAGE) != 0,
! 		(current_header->status & MIME_NEEDDECOD) != 0,
! 		(current_header->status & MIME_NOTPLAIN) != 0);
  	sprintf(buffer + strlen(buffer),
  		"  %d  %d  %d  %d  %d  %d\n",
  		(current_header->status & NEW) != 0,
--- 837,843 ----
  		(current_header->status & DELETED) != 0,
  		(current_header->status & EXPIRED) != 0,
  		(current_header->status & FORM_LETTER) != 0,
! 		(current_header->status & MIME_MESSAGE) != 0);
  	sprintf(buffer + strlen(buffer),
  		"  %d  %d  %d  %d  %d  %d\n",
  		(current_header->status & NEW) != 0,
***************
*** 790,798 ****
  		current_header->messageid : "<none>");
  
  	Write_to_screen("Status: %s\n\r", 1, current_header->mailx_status);
  	
! 	PutLine0(LINES,0,"Please Press any key to return.");
! 	(void) ReadCh();
  }
  
  do_check_only(to_whom)
--- 873,899 ----
  		current_header->messageid : "<none>");
  
  	Write_to_screen("Status: %s\n\r", 1, current_header->mailx_status);
+ 
+ #ifdef MIME
+ 	{
+ 	  char *tmp = "<bad value>";
+ 	  switch (current_header->mime_rec.encoding) {
+ 	  case ENCODING_ILLEGAL: tmp = "<Illegal>"; break;
+ 	  case ENCODING_NONE:    tmp = "(none)"; break;
+ 	  case ENCODING_7BIT:    tmp = ENC_NAME_7BIT; break;
+ 	  case ENCODING_8BIT:    tmp = ENC_NAME_8BIT; break;
+ 	  case ENCODING_BINARY:  tmp = ENC_NAME_BINARY; break;
+ 	  case ENCODING_QUOTED:  tmp = ENC_NAME_QUOTED; break;
+ 	  case ENCODING_BASE64:  tmp = ENC_NAME_BINARY; break;
+ 	  case ENCODING_EXPERIMENTAL: tmp="<X-*>"; break;
+ 	  }
+ 	  Write_to_screen("Content-Transfer-Encoding: %s\n\r",1,tmp);
+ 	}
+ #endif
  	
! 	PutLine0(elm_LINES,0,"Please Press any key to return.");
! 	if (REDRAW_MARK == ReadCh(REDRAW_MARK))
! 	  goto redraw;
  }
  
  do_check_only(to_whom)
***************
*** 848,855 ****
  static char *no_mail = NULL;
  static char *no_aliases = NULL;
  
  motion(ch)
! char ch;
  {
  	/* Consolidated the standard menu navigation and delete/tag
  	 * commands to a function.                                   */
--- 949,957 ----
  static char *no_mail = NULL;
  static char *no_aliases = NULL;
  
+ void
  motion(ch)
!      int ch;
  {
  	/* Consolidated the standard menu navigation and delete/tag
  	 * commands to a function.                                   */
***************
*** 866,887 ****
  
  	switch (ch) {
  
! 	    case '/'    :  /* scan mbox or aliases for string */
! 			   if  (message_count < 1) {
! 			     error1(catgets(elm_msg_cat, ElmSet,
! 				ElmNoItemToScan, "No %s to scan!"), items);
! 			     fflush(stdin);
! 			   }
! 			   else if (pattern_match())
! 			     nucurr = get_page(current);
! 			   else {
! 			     error(catgets(elm_msg_cat, ElmSet, ElmPatternNotFound,
! 			       "pattern not found!"));
! 			     fflush(stdin);
! 			   }
! 			   break;
  
  next_page:
  	    case '+'	:  /* move to next page if we're not on the last */
  			   if((selected &&
  			     ((header_page+1)*headers_per_page < selected))
--- 968,993 ----
  
  	switch (ch) {
  
! 	case FIND_MARK:
! 	case '/'    :  /* scan mbox or aliases for string */
! 	              if  (message_count < 1) {
! 			error1(catgets(elm_msg_cat, ElmSet,
! 				       ElmNoItemToScan, "No %s to scan!"), 
! 			       items);
! 			fflush(stdin);
! 		      }
! 		      else if (pattern_match())
! 			nucurr = get_page(current);
! 		      else {
! 			error(catgets(elm_msg_cat, ElmSet, ElmPatternNotFound,
! 				      "pattern not found!"));
! 			fflush(stdin);
! 		      }
! 		      break;
  
  next_page:
+ 	case PAGEDOWN_MARK :
+ 	case RIGHT_MARK :
  	    case '+'	:  /* move to next page if we're not on the last */
  			   if((selected &&
  			     ((header_page+1)*headers_per_page < selected))
***************
*** 905,910 ****
--- 1011,1018 ----
  			   break;
  
  prev_page:
+ 	case PAGEUP_MARK :
+ 	case LEFT_MARK  :
  	    case '-'	:  /* move to prev page if we're not on the first */
  			   if(header_page > 0) {
  			     header_page--;
***************
*** 924,929 ****
--- 1032,1038 ----
  			   break;
  
  first_msg:
+ 	case HOME_MARK:
  	    case '='    :  if (selected)
  			     current = visible_to_index(1)+1;
  			   else
***************
*** 978,983 ****
--- 1087,1093 ----
  			   break;
  
  next_undel_msg:
+ 	case DOWN_MARK :
  	    case 'j'    :  if(current > 0) {
  			     if((i=next_message(current-1, TRUE)) != -1) {
  			       current = i+1;
***************
*** 999,1017 ****
  			   break;
  
  prev_undel_msg:
  	    case 'k'    :  if(current > 0) {
  			     if((i=prev_message(current-1, TRUE)) != -1) {
  			       current = i+1;
  			       nucurr = get_page(current);
  			     } else
! 			       error1(catgets(elm_msg_cat, ElmSet, ElmNoMoreUndeletedAbove,
  				 "No more undeleted %s above."), items);
  			   } else error(ifmain(no_mail, no_aliases));
  			   break;
  
! 	    case 'l'    :  PutLine1(LINES-3, strlen(Prompt),
! 				   catgets(elm_msg_cat, ElmSet, ElmLimitDisplayBy,
! 				   "Limit displayed %s by..."), items);
  			   clear_error();
  			   if (limit() != 0) {
  			     get_page(current);
--- 1109,1131 ----
  			   break;
  
  prev_undel_msg:
+ 	case UP_MARK :
  	    case 'k'    :  if(current > 0) {
  			     if((i=prev_message(current-1, TRUE)) != -1) {
  			       current = i+1;
  			       nucurr = get_page(current);
  			     } else
! 			       error1(catgets(elm_msg_cat, ElmSet, 
! 					      ElmNoMoreUndeletedAbove,
  				 "No more undeleted %s above."), items);
  			   } else error(ifmain(no_mail, no_aliases));
  			   break;
  
! 	    case 'l'    :  PutLine1(elm_LINES-3, strlen(Prompt),
! 				    catgets(elm_msg_cat, ElmSet, 
! 					    ElmLimitDisplayBy,
! 					    "Limit displayed %s by..."), 
! 				    items);
  			   clear_error();
  			   if (limit() != 0) {
  			     get_page(current);
***************
*** 1076,1122 ****
  
  	    case NO_OP_COMMAND : break;	/* noop for timeout loop */
  
- 	    case ESCAPE : if (cursor_control) {
- 			    key_offset = 1;
- 			    ch = ReadCh(); 
-   
-                             if ( ch == '[' || ch == 'O')
-                             {
-                               ch = ReadCh();
-                               key_offset++;
-                             }
-   
- 			    if(ch == up[key_offset]) goto prev_undel_msg;
- 			    else if(ch == down[key_offset]) goto next_undel_msg;
- 			    else if(ch == right[key_offset]) goto next_page;
- 			    else if(ch == left[key_offset]) goto prev_page;
- 			    else if (hp_terminal) {
- 			      switch (ch) {
- 			      case 'U':		goto next_page;
- 			      case 'V':		goto prev_page;
- 			      case 'h': 	
- 			      case 'H':		goto first_msg;
- 			      case 'F':		goto last_msg;
- 			      case 'A':
- 			      case 'D':
- 			      case 'i':		goto next_undel_msg;
- 			      case 'B':
- 			      case 'I':
- 			      case 'C':		goto prev_undel_msg;
- 			      default: PutLine2(LINES-3, strlen(Prompt), 
- 					"%c%c", ESCAPE, ch);
- 			      }
- 			    } else /* false hit - output */
- 			      PutLine2(LINES-3, strlen(Prompt), 
- 					  "%c%c", ESCAPE, ch);
- 			  }
- 
- 			  /* else fall into the default error message! */
- 
  	    default	: if (ch > '0' && ch <= '9') {
! 			    PutLine1(LINES-3, strlen(Prompt), 
! 				    catgets(elm_msg_cat, ElmSet, ElmNewCurrentItem,
! 				    "New Current %s"), Item);
  			    i = read_number(ch, item);
  
  			    if( i > message_count)
--- 1190,1200 ----
  
  	    case NO_OP_COMMAND : break;	/* noop for timeout loop */
  
  	    default	: if (ch > '0' && ch <= '9') {
! 			    PutLine1(elm_LINES-3, strlen(Prompt), 
! 				     catgets(elm_msg_cat, ElmSet, 
! 					     ElmNewCurrentItem,
! 					     "New Current %s"), Item);
  			    i = read_number(ch, item);
  
  			    if( i > message_count)
Index: WORK/src/encode.c
*** elm2.4.25/src/encode.c	Sat May  8 23:25:39 1993
--- WORK/src/encode.c	Sun Jun 16 20:39:39 1996
***************
*** 57,62 ****
--- 57,63 ----
  
  #include "headers.h"
  #include "s_elm.h"
+ #include "me.h"
  
  #define RTRSZ	94
  #define RN	4
***************
*** 83,89 ****
  static char *decrypt_prompt = NULL;
  static char *first_enc_prompt = NULL;
  static char *second_enc_prompt = NULL;
! #define PROMPT_LINE		LINES-1
  
  getkey(send)
  int send;
--- 84,90 ----
  static char *decrypt_prompt = NULL;
  static char *first_enc_prompt = NULL;
  static char *second_enc_prompt = NULL;
! #define PROMPT_LINE		elm_LINES-1
  
  getkey(send)
  int send;
***************
*** 103,117 ****
  	}
  
  	while (1) {
  	  PutLine0(PROMPT_LINE, 0, (send ? first_enc_prompt : decrypt_prompt));
  	  CleartoEOLN();
! 	  optionally_enter(buffer[0], PROMPT_LINE,
! 	    strlen(send ? first_enc_prompt : decrypt_prompt), FALSE, TRUE);
  	  if (send) {
  	    PutLine0(PROMPT_LINE, 0, second_enc_prompt);
  	    CleartoEOLN();
! 	    optionally_enter(buffer[1], PROMPT_LINE, strlen(second_enc_prompt),
! 	      FALSE, TRUE);
  	    if(strcmp(buffer[0], buffer[1]) != 0) {
  	      error(catgets(elm_msg_cat, ElmSet, ElmKeysNotSame,
  		"Your keys were not the same!"));
--- 104,132 ----
  	}
  
  	while (1) {
+ 	  int code;
+ 
  	  PutLine0(PROMPT_LINE, 0, (send ? first_enc_prompt : decrypt_prompt));
  	  CleartoEOLN();
! 	  code = optionally_enter(buffer[0], PROMPT_LINE,
! 				  strlen(send ? first_enc_prompt : 
! 					 decrypt_prompt), 
! 				  OE_PASSWD|OE_REDRAW_MARK);
! 	  if (REDRAW_MARK == code)
! 	    continue;
! 	  if (code < 0)
! 	    return;
! 
  	  if (send) {
  	    PutLine0(PROMPT_LINE, 0, second_enc_prompt);
  	    CleartoEOLN();
! 	    code = optionally_enter(buffer[1], PROMPT_LINE, 
! 				    strlen(second_enc_prompt),
! 				    OE_PASSWD|OE_REDRAW_MARK);
! 	    if (REDRAW_MARK == code)
! 	      continue;
! 	    if (code < 0)
! 	      return;
  	    if(strcmp(buffer[0], buffer[1]) != 0) {
  	      error(catgets(elm_msg_cat, ElmSet, ElmKeysNotSame,
  		"Your keys were not the same!"));
Index: WORK/src/exitprog.c
*** elm2.4.25/src/exitprog.c	Mon Apr 12 05:34:38 1993
--- WORK/src/exitprog.c	Sun Aug  4 23:18:12 1996
***************
*** 64,76 ****
  	for (changes = 0, i = 0; i < message_count; i++)
  	  if (ison(headers[i]->status, DELETED) || headers[i]->status_chgd)
  	    changes++;
! 	
  	if (changes) {
  	  /* YES or NO on softkeys */
  	  if (hp_softkeys) {
  	    define_softkeys(YESNO);
  	    softkeys_on();
  	  }
  	  if (changes == 1)
  	    MCsprintf(msg, catgets(elm_msg_cat, ElmSet, ElmAbandonChange,
  		"Abandon change to mailbox? (%c/%c) "), *def_ans_yes, *def_ans_no);
--- 64,78 ----
  	for (changes = 0, i = 0; i < message_count; i++)
  	  if (ison(headers[i]->status, DELETED) || headers[i]->status_chgd)
  	    changes++;
! 		
  	if (changes) {
  	  /* YES or NO on softkeys */
+ 	  /*
  	  if (hp_softkeys) {
  	    define_softkeys(YESNO);
  	    softkeys_on();
  	  }
+ 	  */
  	  if (changes == 1)
  	    MCsprintf(msg, catgets(elm_msg_cat, ElmSet, ElmAbandonChange,
  		"Abandon change to mailbox? (%c/%c) "), *def_ans_yes, *def_ans_no);
***************
*** 77,83 ****
  	  else
  	    MCsprintf(msg, catgets(elm_msg_cat, ElmSet, ElmAbandonChangePlural,
  		"Abandon changes to mailbox? (%c/%c) "), *def_ans_yes, *def_ans_no);
! 	  answer = want_to(msg, *def_ans_no, LINES-3, 0);
  
  	  if(answer != *def_ans_yes) return -1;
  	}
--- 79,85 ----
  	  else
  	    MCsprintf(msg, catgets(elm_msg_cat, ElmSet, ElmAbandonChangePlural,
  		"Abandon changes to mailbox? (%c/%c) "), *def_ans_yes, *def_ans_no);
! 	  answer = want_to(msg, *def_ans_no, elm_LINES-3, 0);
  
  	  if(answer != *def_ans_yes) return -1;
  	}
Index: WORK/src/file.c
*** elm2.4.25/src/file.c	Tue Aug  3 22:29:06 1993
--- WORK/src/file.c	Sun Jun 16 19:27:46 1996
***************
*** 152,157 ****
--- 152,158 ----
  
  #include "s_elm.h"
  #include <errno.h>
+ #include "me.h"
  
  extern int errno;
  
***************
*** 248,253 ****
--- 249,255 ----
  	char	filename[SLEN], address[LONG_STRING], buffer[LONG_STRING],
  		ch, msg_buffer[SLEN], answer;
  	FILE *save_file;
+ 	int save_fd;
  
  	oldstat = headers[current-1]->status;	/* remember */
  	*redraw = FALSE;
***************
*** 272,282 ****
  
  Retry_Save_If_Not_Confirmed:
  	while (1) {
  	  if (tagged == 1)
! 	    PutLine1(LINES-2, 0, catgets(elm_msg_cat, ElmSet, ElmSaveMessageTo,
  		  "%s message to: "), (delete ? cap_save_word : cap_copy_word));
  	  else
! 	    PutLine1(LINES-2, 0, catgets(elm_msg_cat, ElmSet, ElmSaveMessagesTo,
  		  "%s messages to: "), (delete ? cap_save_word : cap_copy_word));
  
  	  if (save_by_name) {
--- 274,286 ----
  
  Retry_Save_If_Not_Confirmed:
  	while (1) {
+ 	  int code;
+ 
  	  if (tagged == 1)
! 	    PutLine1(elm_LINES-2, 0, catgets(elm_msg_cat, ElmSet, ElmSaveMessageTo,
  		  "%s message to: "), (delete ? cap_save_word : cap_copy_word));
  	  else
! 	    PutLine1(elm_LINES-2, 0, catgets(elm_msg_cat, ElmSet, ElmSaveMessagesTo,
  		  "%s messages to: "), (delete ? cap_save_word : cap_copy_word));
  
  	  if (save_by_name) {
***************
*** 289,300 ****
  	    filename[0] = '\0';
  
  	  if (tagged > 1)
! 	    optionally_enter(filename, LINES-2, 19, FALSE, FALSE);
  	  else	
! 	    optionally_enter(filename, LINES-2, 18, FALSE, FALSE);
    
  
! 	  if (strlen(filename) == 0) {  /** <return> means 'cancel', right? **/
  	    headers[current-1]->status = oldstat;	/* BACK! */
  	    return(0);
  	  }
--- 293,309 ----
  	    filename[0] = '\0';
  
  	  if (tagged > 1)
! 	    code = optionally_enter(filename, elm_LINES-2, 19, OE_REDRAW_MARK);
  	  else	
! 	    code = optionally_enter(filename, elm_LINES-2, 18, OE_REDRAW_MARK);
! 	  if (REDRAW_MARK == code) {
! 	    *redraw = TRUE;
! 	    continue;
! 	  }
    
  
! 	  if (0 != code || 
! 	      strlen(filename) == 0) {  /** <return> means 'cancel', right? **/
  	    headers[current-1]->status = oldstat;	/* BACK! */
  	    return(0);
  	  }
***************
*** 359,365 ****
  	              "Append to mail folder `%s'? (%c/%c) "),
  		    filename, *def_ans_yes, *def_ans_no);
  
! 	        answer = want_to(msg_buffer, *def_ans_no, LINES-1, 1);
  
  		if (answer != *def_ans_yes) {
  		    goto Retry_Save_If_Not_Confirmed;
--- 368,374 ----
  	              "Append to mail folder `%s'? (%c/%c) "),
  		    filename, *def_ans_yes, *def_ans_no);
  
! 	        answer = want_to(msg_buffer, *def_ans_no, elm_LINES-1, 1);
  
  		if (answer != *def_ans_yes) {
  		    goto Retry_Save_If_Not_Confirmed;
***************
*** 378,384 ****
  	              "Create a new mail folder `%s'? (%c/%c) "),
  		    filename, *def_ans_yes, *def_ans_no);
  
! 	        answer = want_to(msg_buffer, *def_ans_no, LINES-1, 1);
  
  		if (answer != *def_ans_yes) {
  		    goto Retry_Save_If_Not_Confirmed;
--- 387,393 ----
  	              "Create a new mail folder `%s'? (%c/%c) "),
  		    filename, *def_ans_yes, *def_ans_no);
  
! 	        answer = want_to(msg_buffer, *def_ans_no, elm_LINES-1, 1);
  
  		if (answer != *def_ans_yes) {
  		    goto Retry_Save_If_Not_Confirmed;
***************
*** 390,397 ****
  
  	/* save this filename for the next time */
  	strfcpy(prev_fold, filename, SLEN);
! 
! 	if ((save_file = fopen(filename,"a")) == NULL) {
  	  dprint(2, (debugfile,
  		"Error: couldn't append to specified folder %s (save)\n", 
  		filename));
--- 399,408 ----
  
  	/* save this filename for the next time */
  	strfcpy(prev_fold, filename, SLEN);
!       
! 	if ((save_fd = open(filename,O_RDWR|O_CREAT,0600)) == -1 ||
! 	    (save_file = fdopen(save_fd,"r+")) == NULL) {
! 	  close(save_fd);
  	  dprint(2, (debugfile,
  		"Error: couldn't append to specified folder %s (save)\n", 
  		filename));
***************
*** 401,406 ****
--- 412,429 ----
  	  return(0); 
  	}
  
+ 	/* copy_message want now seek backwards ... */
+ 	if (0 != fseek(save_file,0,SEEK_END)) {
+ 	  dprint(2, (debugfile,
+ 		"Error: couldn't seek to end of specified folder %s (save)\n", 
+ 		filename));
+ 	  error1(catgets(elm_msg_cat, ElmSet, ElmCouldntAppendFolder,
+ 		"Couldn't append to folder %s!"), filename);
+ 	  headers[current-1]->status = oldstat;	/* BACK! */
+ 	  fclose(save_file);
+ 	  return (0);
+ 	}
+ 
  	/* if we need a redraw that means index screen no longer present
  	 * so whatever silently was, now it's true - we can't show those
  	 * delete markings.
***************
*** 460,466 ****
  	 */
  	if(is_new = ison(headers[number]->status, NEW))
  	  clearit(headers[number]->status, NEW);
! 	copy_message("", fd, CM_UPDATE_STATUS);
  	if(is_new)
  	  setit(headers[number]->status, NEW);
  	current = save_current;
--- 483,490 ----
  	 */
  	if(is_new = ison(headers[number]->status, NEW))
  	  clearit(headers[number]->status, NEW);
! 	copy_message(mailfile,headers[number],
! 		     "", fd, CM_UPDATE_STATUS);
  	if(is_new)
  	  setit(headers[number]->status, NEW);
  	current = save_current;
Index: WORK/src/file_util.c
*** elm2.4.25/src/file_util.c	Fri Jun  3 20:05:32 1994
--- WORK/src/file_util.c	Thu Jun 13 23:37:27 1996
***************
*** 112,118 ****
  	if (stat(name, &buffer) != 0)
  	  if (errno != 2) {
  	    err = errno;
! 	    MoveCursor(LINES, 0);
  	    Raw(OFF);
  	    dprint(1,(debugfile,
  		     "Error: errno %s on fstat of file %s (bytes)\n", 
--- 112,118 ----
  	if (stat(name, &buffer) != 0)
  	  if (errno != 2) {
  	    err = errno;
! 	    MoveCursor(elm_LINES, 0);
  	    Raw(OFF);
  	    dprint(1,(debugfile,
  		     "Error: errno %s on fstat of file %s (bytes)\n", 
***************
*** 157,180 ****
  		       to));
  	    error1(catgets(elm_msg_cat, ElmSet, ElmCouldNotOpenFile,
  			   "Could not open file %s."), to);
  	    return(1);
  	}
  
! 	while (len = fread(buffer, 1, VERY_LONG_STRING, from_file)) {
! 	    if (fwrite(buffer, 1, len, to_file) != len) {
! 		Write_to_screen(catgets(elm_msg_cat, ElmSet, ElmWriteFailedCopy,
! 			"\n\rWrite failed to temp file in copy\n\r"), 0);
! 		perror(to);
! 		/*
! 		 *  NEVER close anything just at whim!!
! 		 *  If the file has been locked using fcntl() or lockf()
! 		 *	YOU WILL DROP ALL LOCKS refering to the file.
! 		 */
! 		fflush(to_file);
! 		fclose(to_file);
! 		fclose(from_file);
! 		return(1);
! 	    }
  	}
  
  	fclose(from_file);
--- 157,192 ----
  		       to));
  	    error1(catgets(elm_msg_cat, ElmSet, ElmCouldNotOpenFile,
  			   "Could not open file %s."), to);
+ 	    sleep_message();
  	    return(1);
  	}
  
! 	while ((len = fread(buffer, 1, VERY_LONG_STRING, from_file)) > 0) {
! 	  if (fwrite(buffer, 1, len, to_file) != len) {
! 	    int err = errno;
! 	    error2(catgets(elm_msg_cat, ElmSet, ElmWriteFailedCopy,
! 			   "Write failed in copy: %s: %s"), 
! 		   to, error_description(err));
! 	    sleep_message();
! 	    /*
! 	     *  NEVER close anything just at whim!!
! 	     *  If the file has been locked using fcntl() or lockf()
! 	     *	YOU WILL DROP ALL LOCKS refering to the file.
! 	     */
! 	    fflush(to_file);
! 	    fclose(to_file);
! 	    fclose(from_file);
! 	    return(1);
! 	  }
! 	}
! 
! 	if (ferror(from_file)) {
! 	  error("Read failed in copy");
! 	  fflush(to_file);
! 	  fclose(to_file);
! 	  fclose(from_file);
! 	  sleep_message();
! 	  return(1);
  	}
  
  	fclose(from_file);
***************
*** 181,193 ****
  	fflush(to_file);
  
  	if (fclose(to_file) == EOF) {
! 	    Write_to_screen(catgets(elm_msg_cat, ElmSet, ElmCloseFailedCopy,
! 		    "\n\rClose failed on temp file in copy\n\r"), 0);
! 	    perror(to);
! 	    return(1);
  	}
  	if (!isspool)
! 	    (void) elm_chown( to, userid, groupid);
  
  	return(0);
  }
--- 193,207 ----
  	fflush(to_file);
  
  	if (fclose(to_file) == EOF) {
! 	  int err = errno;
! 	  error2(catgets(elm_msg_cat, ElmSet, ElmCloseFailedCopy,
! 			 "Close failed in copy: %s: %s"), 
! 		 to, error_description(err));
! 	  sleep_message();
! 	  return(1);
  	}
  	if (!isspool)
! 	  (void) elm_chown( to, userid, groupid);
  
  	return(0);
  }
***************
*** 212,218 ****
  	}
  
  	if (prefix_str != NULL && fputs(prefix_str, fd) == EOF) {
! 	  MoveCursor(LINES, 0);
  	  Raw(OFF);
  	  printf(catgets(elm_msg_cat, ElmSet, ElmWriteFailedAppend,
  		"\nWrite failed to temp file in append\n"));
--- 226,232 ----
  	}
  
  	if (prefix_str != NULL && fputs(prefix_str, fd) == EOF) {
! 	  MoveCursor(elm_LINES, 0);
  	  Raw(OFF);
  	  printf(catgets(elm_msg_cat, ElmSet, ElmWriteFailedAppend,
  		"\nWrite failed to temp file in append\n"));
***************
*** 222,228 ****
  
  	while (len = fread(buffer, 1, VERY_LONG_STRING, my_fd))
  	  if (fwrite(buffer, 1, len, fd) != len) {
! 	      MoveCursor(LINES, 0);
  	      Raw(OFF);
  	      printf(catgets(elm_msg_cat, ElmSet, ElmWriteFailedAppend,
  		      "\nWrite failed to temp file in append\n"));
--- 236,242 ----
  
  	while (len = fread(buffer, 1, VERY_LONG_STRING, my_fd))
  	  if (fwrite(buffer, 1, len, fd) != len) {
! 	      MoveCursor(elm_LINES, 0);
  	      Raw(OFF);
  	      printf(catgets(elm_msg_cat, ElmSet, ElmWriteFailedAppend,
  		      "\nWrite failed to temp file in append\n"));
***************
*** 231,237 ****
  	  }
  
  	if (fclose(my_fd) == EOF) {
! 	  MoveCursor(LINES, 0);
  	  Raw(OFF);
  	  printf(catgets(elm_msg_cat, ElmSet, ElmCloseFailedAppend,
  		  "\nClose failed on temp file in append\n"));
--- 245,251 ----
  	  }
  
  	if (fclose(my_fd) == EOF) {
! 	  MoveCursor(elm_LINES, 0);
  	  Raw(OFF);
  	  printf(catgets(elm_msg_cat, ElmSet, ElmCloseFailedAppend,
  		  "\nClose failed on temp file in append\n"));
***************
*** 330,333 ****
--- 344,388 ----
  	(void) fstat(fileno(fd), &buffer);
  
  	return( (long) buffer.st_size );
+ }
+ 
+ /* Open and possible creates file for updates and seeks end of file. */
+ 
+ FILE *open_end_update(name)
+      char *name;
+ {
+   
+   FILE *fp;
+   int fd = open(name, O_RDWR | O_CREAT,0600);
+   
+   if (fd < 0) {
+     int err = errno;
+     dprint(1, (debugfile, 
+ 	       "open_end_update: could not open file %s\n\tError: %s\n", 
+ 	       name, error_description(err)));
+ 
+     return NULL;
+   }
+   
+   if (! (fp = fdopen(fd, "r+"))) {
+     dprint(1, (debugfile, 
+ 	       "open_end_update: could not fdopen(%d) file %s\n", 
+ 	       fd,name));
+     
+     close(fd);
+     return NULL;
+   }  
+   
+   if (0 != fseek(fp,0,SEEK_END)) {
+     int err = errno;
+     
+     dprint(1, (debugfile, 
+ 	       "open_end_update: could not seek to EOF %s\n\tError: %s\n", 
+ 	       name, error_description(err)));
+     
+     fclose(fp);
+     return NULL;
+   }
+   
+   return fp;
  }
Index: WORK/src/fileio.c
*** elm2.4.25/src/fileio.c	Tue Aug 30 18:08:09 1994
--- WORK/src/fileio.c	Fri Aug  9 23:02:37 1996
***************
*** 105,110 ****
--- 105,114 ----
  #include "s_elm.h"
  #include <sys/stat.h>
  #include <errno.h>
+ #ifdef BSD
+ #  include <sys/wait.h>
+ #endif
+ #include "me.h"
  
  extern int errno;
  
***************
*** 112,118 ****
  
  static void copy_write_error_exit()
  {
! 	MoveCursor(LINES, 0);
  	Raw(OFF);
  	printf(catgets(elm_msg_cat, ElmSet, ElmWriteCopyMessageFailed,
  		"\nWrite in copy_message failed\n"));
--- 116,122 ----
  
  static void copy_write_error_exit()
  {
! 	MoveCursor(elm_LINES, 0);
  	Raw(OFF);
  	printf(catgets(elm_msg_cat, ElmSet, ElmWriteCopyMessageFailed,
  		"\nWrite in copy_message failed\n"));
***************
*** 120,420 ****
  	rm_temps_exit();
  }
  
! copy_message(prefix, 
! 	     dest_file, 
! 	     cm_options)
! char *prefix;
! FILE *dest_file;
! int cm_options;
  {
! 	/** Copy current message to destination file, with optional 'prefix' 
! 	    as the prefix for each line.  If remove_header is true, it will 
! 	    skip lines in the message until it finds the end of header line...
! 	    then it will start copying into the file... If remote is true
! 	    then it will append "remote from <hostname>" at the end of the
! 	    very first line of the file (for remailing) 
! 
! 	    If "forwarding" is true then it'll do some nice things to
! 	    ensure that the forwarded message looks pleasant; e.g. remove
! 	    stuff like ">From " lines and "Received:" lines.
! 
! 	    If "update_status" is true then it will write a new Status:
! 	    line at the end of the headers.  It never copies an existing one.
! 
! 	    If "decode" is true, prompt for key if the message is encrypted,
! 	    else just copy it as it is.
! 	**/
! 
!     /*
!      *	Changed buffer[SLEN] to buffer[VERY_LONG_STRING] to make it
!      *	big enough to contain a full length header line. Any header
!      *	is allowed to be at least 1024 bytes in length. (r.t.f. RFC)
!      *	14-Sep-1993 Jukka Ukkonen <ukkonen@csc.fi>
!      */
! 
!     char buffer[VERY_LONG_STRING];
!     register struct header_rec *current_header = headers[current-1];
!     register int  lines, front_line, next_front,
! 		  in_header = 1, first_line = TRUE, ignoring = FALSE;
!     int remove_header = cm_options & CM_REMOVE_HEADER;
!     int remote = cm_options & CM_REMOTE;
!     int update_status = cm_options & CM_UPDATE_STATUS;
!     int remail = cm_options & CM_REMAIL;
!     int decode = cm_options & CM_DECODE;
!     int	end_header = 0;
!     int sender_added = 0;
!     int crypted = 0;
!     int bytes_seen = 0;
!     int buf_len, err;
! 
!       /** get to the first line of the message desired **/
  
!     if (fseek(mailfile, current_header->offset, 0) == -1) {
!        dprint(1, (debugfile, 
! 		"ERROR: Attempt to seek %d bytes into file failed (%s)",
! 		current_header->offset, "copy_message"));
!        error1(catgets(elm_msg_cat, ElmSet, ElmSeekFailed,
! 	     "ELM [seek] failed trying to read %d bytes into file."),
! 	     current_header->offset);
!        return;
      }
  
!     /* how many lines in message? */
  
!     lines = current_header->lines;
  
!     /* set up for forwarding just in case... */
  
!     if (forwarding)
!       remove_header = FALSE;
  
!     if (current_header->encrypted && decode) {
! 	getkey(OFF);
!     }
  
!     /* now while not EOF & still in message... copy it! */
  
-     next_front = TRUE;
  
!     while (lines) {
!       if (! (buf_len = mail_gets(buffer, VERY_LONG_STRING, mailfile)))
!         break;
  
!       bytes_seen += buf_len;
!       front_line = next_front;
  
!       if(buffer[buf_len - 1] == '\n') {
! 	lines--;	/* got a full line */
! 	next_front = TRUE;
!       }
!       else
! 	next_front = FALSE;
!       
!       if (front_line && ignoring)
! 	ignoring = whitespace(buffer[0]);
  
!       if (ignoring)
! 	continue;
  
- #ifdef MMDF
-       if ((cm_options & CM_MMDF_HEAD) && strcmp(buffer, MSG_SEPARATOR) == 0)
- 	continue;
- #endif /* MMDF */
  
!       /* are we still in the header? */
  
!       if (in_header && front_line) {
! 	if (buf_len < 2) {
! 	  in_header = 0;
! 	  bytes_seen = 0;
! 	  end_header = -1;
! 	  if (remail && !sender_added) {
! 	    if (fprintf(dest_file, "%sSender: %s\n", prefix, username) == EOF) {
! 	      copy_write_error_exit();
! 	    }
! 	  }
! 	}
! 	else if (!isspace(*buffer)
! 	      && index(buffer, ':') == NULL
  #ifdef MMDF
! 	      && strcmp(buffer, MSG_SEPARATOR) != 0
! #endif /* MMDF */
! 		) {
! 	  in_header = 0;
! 	  bytes_seen = 0;
! 	  end_header = 1;
! 	  if (remail && !sender_added) {
! 	    if (fprintf(dest_file, "%sSender: %s\n", prefix, username) == EOF) {
! 	      copy_write_error_exit();
! 	    }
! 	  }
! 	} else if (in_header && remote && header_cmp(buffer, "Sender", NULL)) {
! 	  if (remail)
! 	    if (fprintf(dest_file, "%sSender: %s\n", prefix, username) == EOF) {
! 	      copy_write_error_exit();
! 	    }
! 	  sender_added = TRUE;
! 	  continue;
! 	}
! 	if (end_header) {
! 	  if (update_status) {
! 	      if (isoff(current_header->status, NEW)) {
! 		if (ison(current_header->status, UNREAD)) {
! 		  if (fprintf(dest_file, "%sStatus: O\n", prefix) == EOF) {
! 		    copy_write_error_exit();
! 		  }
! 		} else	/* read */
! #ifdef BSD
! 		  if (fprintf(dest_file, "%sStatus: OR\n", prefix) == EOF) {
! #else
! 		  if (fprintf(dest_file, "%sStatus: RO\n", prefix) == EOF) {
  #endif
! 		    copy_write_error_exit();
! 		  }
! 		update_status = FALSE; /* do it only once */
! 	      }	/* else if NEW - indicate NEW with no Status: line. This is
! 		 * important if we resync a mailfile - we don't want
! 		 * NEW status lost when we copy each message out.
! 		 * It is the responsibility of the function that calls
! 		 * this function to unset NEW as appropriate to its
! 		 * reason for using this function to copy a message
! 		 */
! 
! 		/*
! 		 * add the missing newline for RFC 822
! 		 */
! 	      if (end_header > 0) {
! 		/* add the missing newline for RFC 822 */
! 		if (fprintf(dest_file, "\n") == EOF) {
! 		  copy_write_error_exit();
! 		}
! 	      }
! 	  }
! 	}
!       }
! 
!       if (in_header) {
! 	/* Process checks while in header area */
! 
! 	if (remove_header) {
! 	  ignoring = TRUE;
! 	  continue;
! 	}
! 
! 	/* add remote on to front? */
! 	if (first_line && remote) {
! 	  no_ret(buffer);
! #ifndef MMDF
  	  if (fprintf(dest_file, "%s%s remote from %s\n",
! 		  prefix, buffer, hostname) == EOF) {
! 		copy_write_error_exit();
! 	  }
! #else
! 	  if (first_word(buffer, "From ")) {
! 	    if (fprintf(dest_file, "%s%s remote from %s\n",
! 		    prefix, buffer, hostname) == EOF) {
! 		copy_write_error_exit();
! 	    }
! 	  } else {
! 	    if (fprintf(dest_file, "%s%s\n", prefix, buffer) == EOF) {
! 		copy_write_error_exit();
! 	    }
  	  }
- #endif /* MMDF */
  	  first_line = FALSE;
  	  continue;
  	}
! 
! 	if (!forwarding) {
! 	  if(! header_cmp(buffer, "Status", NULL)) {
! 	    if (fprintf(dest_file, "%s%s", prefix, buffer) == EOF) {
! 	      copy_write_error_exit();
! 	      }
! 	    continue;
! 	  } else {
! 	    ignoring = TRUE;
! 	    continue;	/* we will output a new Status: line later, if desired. */
  	  }
  	}
! 	else { /* forwarding */
! 
! 	  if (header_cmp(buffer, "Received", NULL   ) ||
! 	      first_word_nc(buffer, ">From"         ) ||
! 	      header_cmp(buffer, "Status", NULL     ) ||
! 	      header_cmp(buffer, "Return-Path", NULL))
! 	      ignoring = TRUE;
! 	  else
! 	    if (remail && header_cmp(buffer, "To", NULL)) {
! 	      if (fprintf(dest_file, "%sOrig-%s", prefix, buffer) == EOF) {
! 		copy_write_error_exit();
! 	      }
! 	    } else {
! 	      if (fprintf(dest_file, "%s%s", prefix, buffer) == EOF) {
! 		copy_write_error_exit();
! 	      }
! 	    }
! 	}
        }
!       else { /* not in header */
!         /* Process checks that occur after the header area */
! 
! 	/* perform encryption checks */
! 	if (buffer[0] == '[' && decode) {
! 		if (!strncmp(buffer, START_ENCODE, strlen(START_ENCODE))) {
! 			crypted = ON;
! 		} else if (!strncmp(buffer, END_ENCODE, strlen(END_ENCODE))) {
! 			crypted = OFF;
! 		} else if (crypted) {
! 			no_ret(buffer);
! 			encode(buffer);
! 			strcat(buffer, "\n");
! 		}
! 	} else if (crypted) {
! 		no_ret(buffer);
! 		encode(buffer);
! 		strcat(buffer, "\n");
! 	}
! 
! 
! #ifndef MMDF
! #ifndef DONT_ESCAPE_MESSAGES
! 	if(first_word(buffer, "From ") && (real_from(buffer, NULL)) &&
! 	   current_header->content_length <= bytes_seen) {
! 	  /* If we have a content-length > bytes_seen and there is lines left
! 	  ** this is probably a From line that is part of the body, as an
! 	  ** included message. A simple heuristic test.
! 	  */
! 	  dprint(1, (debugfile,
! 		 "\n*** Internal Problem...Tried to add the following;\n"));
! 	  dprint(1, (debugfile,
! 		 "  '%s'\nto output file (copy_message) ***\n", buffer));
! 	  break;	/* STOP NOW! */
! 	}
! #endif /* DONT_ESCAPE_MESSAGES */
! #endif /* MMDF */
! 
! 	err = fprintf(dest_file, "%s", prefix);
! 	if (err != EOF)
! 	  err = fwrite(buffer, 1, buf_len, dest_file);
! 	if (err != buf_len) {
! 	  copy_write_error_exit();
  	}
        }
      }
! #ifndef MMDF
!     if (buf_len + strlen(prefix) > 1)
! 	if (fprintf(dest_file, "\n") == EOF) {	/* blank line to keep mailx happy *sigh* */
  	  copy_write_error_exit();
  	}
! #endif /* MMDF */
  
!     /* Since fprintf is buffered, its return value is only useful for
!      * writes which exceed the blocksize.  Do a fflush to ensure that
!      * the message has, in fact, been written.
       */
!     if (fflush(dest_file) == EOF) {
        copy_write_error_exit();
      }
  }
  
  static struct stat saved_buf;
--- 124,785 ----
  	rm_temps_exit();
  }
  
! #ifdef USE_PGP
! /* Prototype */
! static void copy_pgp P_((char *,FILE *,int, struct header_rec *, FILE *));
! 
! static void copy_pgp(prefix,dest_file,cm_options,current_header, infile)
!      char *prefix;
!      FILE *dest_file;
!      int cm_options;
!      struct header_rec *current_header;
!      FILE * infile;
  {
!   int body_bytes = 0;
!   FILE *fpin = NULL, *fpout = NULL;
!   char buffer[VERY_LONG_STRING];
!   int buf_len,err,child;
! #if defined(BSD) && !defined(WEXITSTATUS)
!   union wait status;
! #else
!   int status;
! #endif
!   int pgp_seen = !pgp_noarmor;
  
!   dprint(5,(debugfile,
! 	    "copy_pgp called: Need read %d bytes\n",
! 	    current_header->content_length));
! 
!   if ((current_header->pgp & PGP_MESSAGE) && pgp_keeppass) {
!     if (!pgp_goodPassphrase()) {
!       error("Decrypting message... Bad PGP passphrase.");
!       fprintf(dest_file,"[Decrypting message... Bad PGP passphrase]\n");
!       return;
!     }
!   }
!   
!   Raw(OFF);
!   if ((child=pgp_decrypt_init(&fpin, &fpout, current_header->pgp & 
! 			      (PGP_MESSAGE|PGP_SIGNED_MESSAGE))) == -1) {
!     Raw(ON);
!     error("Decrypting message... Failed to init PGP.");
!     fprintf(dest_file,"[Decrypting message... Failed to init PGP.]\n");   
!     return;
!   }
! 
!   while (body_bytes < current_header->content_length) {      
!     if (! (buf_len = mail_gets(buffer, VERY_LONG_STRING, infile)))
!       break;
!     
!     if (!pgp_seen) {
!       if (strncmp(buffer, "-----BEGIN PGP", 14) == 0) {
! 	pgp_seen = 1;
! 	goto pgp_found;
!       }
!       /* text before PGP section */
!       if (0 == body_bytes)
! 	fprintf(dest_file,"[There is text before PGP section.]\n");
! 
!       err = fprintf(dest_file, "%s", prefix);
!       if (err != EOF)
! 	err = fwrite(buffer, 1, buf_len, dest_file);
!       if (err != buf_len) {
! 	copy_write_error_exit();
!       }	
!     } else {
!       /* Pass PGP section to pgp */
!     pgp_found:
!       if (EOF == fputs(buffer, fpout))
! 	copy_write_error_exit();
!     }
!     body_bytes += buf_len;
!   }
!   if (fclose(fpout) == EOF)
!     copy_write_error_exit();
!   
!   dprint(5,(debugfile,
! 	    "copy_pgp: Passed %d bytes to PGP.\n",
! 	    body_bytes));
!   body_bytes = 0;
! 
!   fprintf(dest_file,"-- Start of PGP%s%s section.\n",
! 	  current_header->pgp & PGP_SIGNED_MESSAGE ? " signed" : "",
! 	  current_header->pgp & PGP_MESSAGE ? " encoded": "");
! 
!   while (0 < (buf_len = mail_gets(buffer, VERY_LONG_STRING, fpin))) {
!     body_bytes += buf_len;
!     
!     err = fprintf(dest_file, "%s", prefix);
!     if (err != EOF)
!       err = fwrite(buffer, 1, buf_len, dest_file);
!     if (err != buf_len) {
!       copy_write_error_exit();
      }
+   }
+   fclose(fpin);
  
!   {
!     int w,stat=-1;
!     while ((w = wait(&status)) != child)
!       if (w == -1 && errno != EINTR)
! 	break;
!     if (w == child) {
! #ifdef	WEXITSTATUS
!       stat = WEXITSTATUS(status);
! #else
! # ifdef	BSD
!       stat = status.w_retcode;
! # else
!       stat = status;
! # endif
! #endif
!     }
!     fprintf(dest_file,"-- End of PGP%s%s section%s\n",
! 	  current_header->pgp & PGP_SIGNED_MESSAGE ? " signed" : "",
! 	  current_header->pgp & PGP_MESSAGE ? " encoded" : "",
! 	  stat ? ", PGP failed!" : ".");
! 
!   }
! 
!   PressAnyKeyToContinue();
!   Raw(ON);
!   dprint(5,(debugfile,
! 	    "copy_pgp: Readed %d bytes from PGP.\n",
! 	    body_bytes));
! }
! #endif /* USE_PGP */
  
! #ifdef MIME
! /* Prototype */
! void copy_mime P_((char *,FILE *,int, struct header_rec *, FILE *));
! 
! void copy_mime(prefix,dest_file,cm_options,current_header, infile)
!      char *prefix;
!      FILE *dest_file;
!      int cm_options;
!      struct header_rec *current_header;
!      FILE *infile;
! {
!   in_state_t  state_in;
!   out_state_t state_out;
!   in_state_clear(&state_in,  STATE_in_file);
!   out_state_clear(&state_out, STATE_out_file);
  
!   dprint(5,(debugfile,
! 	    "copy_mime called: Need read %d bytes\n",
! 	    current_header->content_length));
  
!   attach_parse(current_header, infile);
  
!   set_in_state_file(infile,&state_in);
!   set_out_state_file(dest_file,&state_out);
  
!   state_out.prefix = prefix;
!   state_out.displaying = (cm_options & CM_DISPLAYING) ? 1 : 0;
!   mime_decode(&(current_header->mime_rec), &state_in, &state_out);
!   
!   dprint(5,(debugfile,"copy_mime: mail decoded\n"));
  
  
!   in_state_destroy(&state_in);  
!   out_state_destroy(&state_out);  
! }
! #endif /* MIME */
  
! /* Prototype */
! static void copy_encrypted P_((char *,FILE *,int, struct header_rec *, 
! 			       FILE *));
! 
! static void copy_encrypted(prefix,dest_file,cm_options,current_header,infile)
!      char *prefix;
!      FILE *dest_file;
!      int cm_options;
!      struct header_rec *current_header;
!      FILE *infile;
! {
!   char buffer[VERY_LONG_STRING];
!   long body_bytes = 0;
!   int crypted = OFF;
!   int buf_len, err;
! 
!   dprint(5,(debugfile,
! 	    "copy_encrypted called: Need read %d bytes\n",
! 	    current_header->content_length));
! 
!   getkey(OFF);
! 
!   while (body_bytes < current_header->content_length) {      
!     if (! (buf_len = mail_gets(buffer, VERY_LONG_STRING, infile)))
!       break;
!     
!     body_bytes += buf_len;
!     
!     if (!strncmp(buffer, START_ENCODE, strlen(START_ENCODE))) {
!       crypted = ON;
!       fputs("-- Start of (Elm) encoded section.\n",dest_file);
!       continue;
!     } else if (!strncmp(buffer, END_ENCODE, strlen(END_ENCODE))) {
!       crypted = OFF;
!       fputs("-- End of (Elm) encoded section.\n",dest_file);
!       continue;
!     } else if (crypted) {
!       no_ret(buffer);
!       encode(buffer);      
!       strcat(buffer, "\n");
!     }
!     if (fprintf(dest_file, "%s%s", prefix, buffer) == EOF) {
!       copy_write_error_exit();
!     }
!   }
!   dprint(5,(debugfile,
! 	      "copy_encrypted: Readed %d bytes from body\n",body_bytes));
! }
  
! /* Prototype */
! void copy_plain P_((char *,FILE *,int, struct header_rec *, FILE *));
  
! void copy_plain(prefix,dest_file,cm_options,current_header, infile) 
!      char *prefix;
!      FILE *dest_file;
!      int cm_options;
!      struct header_rec *current_header;
!      FILE *infile;
! {
!   char buffer[VERY_LONG_STRING];
!   int body_bytes = 0;
!   int buf_len, err;
!  
!   dprint(5,(debugfile,
! 	    "copy_plain called: Need read %d bytes\n",
! 	    current_header->content_length));;
! 
! 
!   while (body_bytes < current_header->content_length) {      
!     if (! (buf_len = mail_gets(buffer, VERY_LONG_STRING, infile)))
!       break;
!     
!     body_bytes += buf_len;
!     
!     err = fprintf(dest_file, "%s", prefix);
!     if (err != EOF)
!       err = fwrite(buffer, 1, buf_len, dest_file);
!     if (err != buf_len) {
!       copy_write_error_exit();
!     }
!   }
!   dprint(5,(debugfile,
! 	      "copy_plain: Readed %d bytes from body\n",body_bytes));
! }
  
  
! copy_decoder_t select_copy_decoder (current_header) 
!      struct header_rec * current_header;
! {
!     if (0)
!       /* Do nothing -- filler */;
! #ifdef MIME
!     else if (current_header->status & MIME_MESSAGE) 
!       return copy_mime; 
! #endif
! #ifdef USE_PGP
!     else if (current_header->pgp & (PGP_MESSAGE|PGP_SIGNED_MESSAGE))
!       return copy_pgp;
! #endif
!     else if (current_header -> encrypted)
!       return copy_encrypted;
!     else
!       return copy_plain;
! }
  
! void
! copy_message(infile,
! 	     current_header,
! 	     prefix, 
! 	     dest_file, 
! 	     cm_options)
!      FILE *infile;
!      struct header_rec *current_header;
!      char *prefix;
!      FILE *dest_file;
!      int cm_options;
! {
!   /** Copy current message to destination file, with optional 'prefix' 
!     as the prefix for each line.  If remove_header is true, it will 
!     skip lines in the message until it finds the end of header line...
!     then it will start copying into the file... If remote is true
!     then it will append "remote from <hostname>" at the end of the
!     very first line of the file (for remailing) 
!     
!     If "filter_header" is true then it'll do some nice things to
!     ensure that the forwarded message looks pleasant; e.g. remove
!     stuff like ">From " lines and "Received:" lines.
!     
!     If "update_status" is true then it will write a new Status:
!     line at the end of the headers.  It never copies an existing one.
!     
!     If "decode" decode MIME, PGP and elm's (unsafe) own decoding.
!     **/
!   
!   char buffer[32*1024+1]; /* Allow one header line to be 32 KB
! 			   * after unfolding 
! 			   */
!   int in_header = 1, first_line = TRUE;
!   int remove_header = cm_options & CM_REMOVE_HEADER;
!   int remove_envelope = cm_options & CM_REMOVE_ENVELOPE;
!   int remote = cm_options & CM_REMOTE;
!   int update_status = cm_options & CM_UPDATE_STATUS;
!   int remail = cm_options & CM_REMAIL;
!   int decode = cm_options & CM_DECODE;
!   int filter_headers = cm_options & CM_FILT_HDR;
!   int bytes_seen = 0, body_bytes = 0;
!   int content_length_seen = FALSE;
!   long CL_pos = -1L, BODY_pos = -1L;
!   int was_binary = current_header -> binary && !decode;
!   
!   int buf_len, err;
!   int i;
!   
!   
!   /** get to the first line of the message desired **/
!   
!   if (fseek(infile, current_header->offset, 0) == -1) {
!     dprint(1, (debugfile, 
! 	       "ERROR: Attempt to seek %d bytes into file failed (%s)",
! 	       current_header->offset, "copy_message"));
!     error1(catgets(elm_msg_cat, ElmSet, ElmSeekFailed,
! 		   "ELM [seek] failed trying to read %d bytes into file."),
! 	   current_header->offset);
!     return;
!   }
!   
!   /* now while not EOF & still in message... copy it! */
!   
!   dprint(5,(debugfile,"copy_message: start mailbox separator section\n"));
!   
  #ifdef MMDF
!   if (!(CM_MMDF_HEAD & cm_options) && !remove_header && !remove_envelope) {
!     dprint(5,(debugfile,"copy_message: Write MMDF message separator\n"));
!     if (fprintf(dest_file, "%s", MSG_SEPARATOR) == EOF)
!       copy_write_error_exit();
!   }   
  #endif
!   
!   while (in_header) {      
!     long last_pos = ftell(infile);
!     if (last_pos < 0) {
!       dprint(5,(debugfile,"copy_message: ftell(infile) failed!\n"));
!       break;
!     }
!     
!     if (! (buf_len = mail_gets(buffer, sizeof(buffer), infile)))
!       break;
!     
! #ifdef MMDF
!     if (strcmp(buffer, MSG_SEPARATOR) == 0)
!       continue; /* MSG SEPRATOR is already written */
! #endif /* MMDF */
!     
!     if(buffer[buf_len - 1] == '\n') {
!       no_ret(buffer);
!       if (first_word(buffer, "From ")) {
! 	if (first_line && remote && !remove_header && !remove_envelope) {
  	  if (fprintf(dest_file, "%s%s remote from %s\n",
! 		      prefix, buffer, hostname) == EOF) {
! 	    copy_write_error_exit();
  	  }
  	  first_line = FALSE;
  	  continue;
  	}
! 	if (!remove_header && !remove_envelope) {
! 	  if (fprintf(dest_file, "%s%s\n", prefix, buffer) == EOF) {
! 	    copy_write_error_exit();
  	  }
  	}
! 	first_line = FALSE;
! 	continue;
        }
!       if (!first_line && first_word_nc(buffer, ">From")) {
! 	if (!filter_headers && !remove_header && !remove_envelope) {
! 	  if (fprintf(dest_file, "%s%s\n", prefix, buffer) == EOF) {
! 	    copy_write_error_exit();
! 	  }
  	}
+ 	continue;	
        }
+       /* fall thru */
      }
!     dprint(5,(debugfile,
! 	      "copy_message: Not a mailbox line -- seeking back!\n"));
!     dprint(5,(debugfile,
! 	      "copy_message- Line was: %s\n",buffer));
!     
!     if (0 != fseek(infile,last_pos,SEEK_SET)) {
!       dprint(5,(debugfile,
! 		"copy_message: seek failed!\n"));
!       copy_write_error_exit();
!     }
!     break; /* Go out of loop */
!   }
!   if (first_line) {
!     dprint(5,(debugfile,
! 	      "copy_message: No 'From ' line seen...\n"));
!     if (!remove_header && !remove_envelope) {
!       long thetime = time((long *) 0);
!       dprint(5,(debugfile,
! 		"copy_message: Create it!\n"));
!       if (fprintf(dest_file,
! 		  "%sFrom %s %s", prefix,username, ctime(&thetime)) == EOF)
! 	copy_write_error_exit();
!     }
!   }
!   
!   dprint(5,(debugfile,"copy_message: start header section\n"));
!   
!   while (in_header) {      
!     char * colptr,*hdr,*body,*ptr;
!     int header_class;
! 
!     if ( (buf_len = read_header_line(infile,buffer,sizeof(buffer),
! 				     RHL_CHECK_HEADER|RHL_MARK_FOLDING))
! 	< 2) {
!       dprint(5,(debugfile,"copy_message: End of headers: buf_len=%d\n",
! 		buf_len));
!       break;
!     }
!     
!     bytes_seen += buf_len;
!     
!     colptr = strchr(buffer, ':');
!     if (NULL == colptr) {
!       in_header = 0;
!       dprint(1,(debugfile,"copy_message: Software error; No ':' !!\n"));
!       break;
!     }
!     *colptr = '\0';
!     hdr = buffer;
!     body = colptr +1;
! 
!     if (remove_header)
!       continue;
!     
!     header_class = classify_header(hdr);
!     dprint(12,(debugfile,"copy_message: header=%s,class=%d,rest=%s\n",
! 	       hdr,header_class,body));;
!     
! #ifdef MIME
!     if (decode && !(current_header -> status & NOHDRENCODING)) {
!       
!       if (header_class & HDR_TEXT) {
! 	if (is_rfc1522 (body))
! 	  rfc1522_decode (body, sizeof (buffer) - (body - buffer) -1);
!       } else if (header_class & HDR_STRUCTURED) {
! 	rfc1522_decode_structured(header_class,
! 				  body, 
! 				  sizeof (buffer) -(body - buffer) -1);
!       }
!       
!       dprint(12,(debugfile,"copy_message: decoded rest=%s\n",body));
!     }
! #endif
!     if ((remote || remail) && 0 == istrcmp("Sender",hdr)) {
! 	continue;
!     }
! #ifdef MIME
!     /* These headers are incorrect after decoding ... */
!     if (decode && (current_header->status & MIME_MESSAGE) &&
! 	(0 == istrcmp(buffer, "MIME-Version") ||
! 	 0 == istrcmp(buffer, "Content-Type") ||
! 	 0 == istrcmp(buffer, "Content-Transfer-Encoding")))
!       continue;
! #endif
!     
!     if(0 == istrcmp(buffer, "Content-Length")) {
!       /* make correct Content-Length later */
!       content_length_seen = TRUE;
!       continue;
!     }
!     
!     if (!filter_headers) {
!       if (0 == istrcmp(buffer,"Status"))
! 	continue;   /* we will output a new Status: line later, if desired. */
!     }
!     else { /* filter_headers */
!       if (0 == istrcmp(buffer, "Received") ||
! 	  0 == istrcmp(buffer, "Status") ||
! 	  0 == istrcmp(buffer, "Return-Path"))
! 	continue;
!       if (remail && 0 == istrcmp(buffer, "To"))
! 	hdr = "Orig-To";
!     }
!     dprint(5,(debugfile,"copy_message- hdr=%s body=%s\n",hdr,body));
!     
!     for (ptr = strtok(body,"\n"); ptr; ptr = strtok(NULL,"\n")) { 
!       if (fprintf(dest_file,"%s",prefix) == EOF)
! 	copy_write_error_exit ();
!       
!       if (ptr > body) { /* Do folding */
! 	--ptr;
! 	if (*(ptr+1) == ' ')
! 	  *ptr = ' ';
! 	else
! 	  *ptr = '\t';
!       } else {
! 	if (fprintf(dest_file,"%s:",hdr) == EOF)
! 	  copy_write_error_exit ();
!       }
!       if (fprintf(dest_file,"%s%s",ptr,was_binary ? "\r\n" : "\n") == EOF)
! 	copy_write_error_exit ();
!     }       
!   }
!   
!   dprint(5,(debugfile,"copy_message: end of headers. Readed ~ %d bytes.\n",
! 	    bytes_seen));
! 
!   if (!remove_header) {  
!     if (!filter_headers && content_length_seen) {
! 	if (fprintf (dest_file, "Content-Length: ") == EOF)
! 	  copy_write_error_exit ();
! 	CL_pos = ftell(dest_file);
! 	if (fprintf (dest_file, "%5d%s",
! 		     current_header->content_length,
! 		     was_binary ? "\r\n" : "\n") == EOF)
! 	  copy_write_error_exit ();
!     }
!     if (remail) {
!       if (fprintf (dest_file, "%sSender: %s%s",
! 		   prefix,username,
! 		   was_binary ? "\r\n" : "\n") == EOF)
! 	copy_write_error_exit ();
!     }
!     if (update_status) {
!       if (isoff(current_header->status, NEW)) {
! 	if (fprintf (dest_file, "%sStatus: ", prefix) == EOF)
! 	  copy_write_error_exit ();
! 	
! 	if (ison(current_header->status, UNREAD)) {
! 	  if (fprintf(dest_file, "O") == EOF)
! 	    copy_write_error_exit();
! 	} else {	/* read */
! 	if (fprintf(dest_file, "RO") == EOF)
  	  copy_write_error_exit();
+ 	
+ 	if (ison(current_header->status, REPLIED)) {
+ 	  if (fprintf (dest_file, "r") == EOF)
+ 	    copy_write_error_exit ();
  	}
!       }
! 	
! 	/* save all the status flags that ELM doesn't understand */
! 	for (i=0; current_header->mailx_status[i] != '\0'; i++)
! 	  switch (current_header->mailx_status[i]) {
! 	  case 'R':
! 	  case 'O':
! 	  case 'r':
! 	    break;
! 	  default:
! 	    if (fprintf (dest_file, "%c", current_header->mailx_status[i]) == EOF)
! 	      copy_write_error_exit ();
! 	  }
! 	if (fprintf(dest_file, was_binary ? "\r\n" : "\n") == EOF) {
! 	  copy_write_error_exit();
! 	}      
!       }	/* else if NEW - indicate NEW with no Status: line. This is
! 	 * important if we resync a mailfile - we don't want
! 	 * NEW status lost when we copy each message out.
! 	 * It is the responsibility of the function that calls
! 	 * this function to unset NEW as appropriate to its
! 	 * reason for using this function to copy a message
! 	 */
!     }
!     
!     /*
!      * Add empty line between headers and body (that was not copied
!      *  in above)
!      */
! 
!     if (fprintf(dest_file, was_binary ? "\r\n" : "\n") == EOF) {
!       copy_write_error_exit();
!     }
!   }
!    
!   dprint(5,(debugfile,
! 	    "copy_message: Starting reading of body: %d bytes expected\n",
! 	    current_header->content_length));
!      
!   BODY_pos = ftell(dest_file);
! 
!   if (decode) {
!     copy_decoder_t decoder = select_copy_decoder(current_header);
!     decoder(prefix,dest_file,cm_options,current_header,infile);
!   } else    
!     copy_plain(prefix,dest_file,cm_options,current_header,infile);
! 
!   if (CL_pos > 0 && BODY_pos > 0) {
!     long cur_pos;
  
!     /* Actually written content length is good if conversions are
!      * not done and there was no errors ... 
       */
!     clearerr(dest_file);
!     cur_pos = ftell(dest_file);
! 
!     /* Notice that these tests indicates failure */
!     if (cur_pos < BODY_pos || 
! 	0   != fseek(dest_file,CL_pos,SEEK_SET) ||
! 	ftell(dest_file) != CL_pos ||
! 	EOF == fprintf (dest_file, "%5d", (int) (cur_pos - BODY_pos)) ||
! 	0   != fseek(dest_file,cur_pos,SEEK_SET))
        copy_write_error_exit();
+     else
+       dprint(5,(debugfile,
+ 		"copy_message: Content-length fixed: %d bytes.\n",
+ 		(int) (cur_pos - CL_pos)));
+       
+   }
+   
+   if (0 == fseek(dest_file,-2L,SEEK_CUR)) {
+     char buffer[2];
+     buffer[0] = '\0';
+     buffer[1] = '\0';
+     if (2 != fread(buffer,sizeof (char),2,dest_file) ||
+ 	0 != fseek(dest_file,0L,SEEK_CUR)) {
+       dprint(5,(debugfile,
+ 		"copy_message: Read or seek (0) error!\n")); 
      }
+     dprint(5,(debugfile,
+ 	      "copy_message: last two bytes %d %d\n",
+ 	      buffer[0], buffer[1])); 
+     if (buffer[1] != '\n') {
+       /* No \n in end ? */ 	
+       dprint(5,(debugfile,
+ 		"copy_message: NL missing from end of mail\n")); 
+       if (fprintf(dest_file, "\n") == EOF) 
+ 	copy_write_error_exit();
+     }
+ #ifndef MMDF
+     if (buffer[0] != '\n') {
+       dprint(5,(debugfile,
+ 		"copy_message: NL NL missing from end of mail\n")); 
+       /* blank line to keep mailx happy *sigh* */      
+       if (fprintf(dest_file, "\n") == EOF) 
+ 	copy_write_error_exit();
+     }
+ #endif
+ 
+   }
+   else {
+     dprint(5,(debugfile,
+ 	      "copy_message: Failed to seek backward!\n")); 
+     copy_write_error_exit();   /* Flushing failed? */
+   }
+   
+   /* Since fprintf is buffered, its return value is only useful for
+    * writes which exceed the blocksize.  Do a fflush to ensure that
+    * the message has, in fact, been written.
+    */
+   if (fflush(dest_file) == EOF) {
+     copy_write_error_exit();
+   }
  }
  
  static struct stat saved_buf;
***************
*** 461,516 ****
  	 */
  
  	int old_umask, i, new_mode, new_owner, new_group, ret_code;
! 
! 
! 	new_mode = 0600;
  	new_owner = userid;
  	new_group = groupid;
  	ret_code = 0;
  
  	if(strcmp(fname, saved_fname) == 0) {
! 	  new_mode = saved_buf.st_mode;
  	  new_owner = saved_buf.st_uid;
  	  new_group = saved_buf.st_gid;
  	  ret_code = 1;
  	}
  	dprint(2, (debugfile, "** %s file stats for %s **\n",
! 	  (ret_code ? "restoring" : "setting"), fname));
  
  	old_umask = umask(0);
! 	if((i = chmod(fname, new_mode & 0777)) == -1)
  	  ret_code = -1;
  
! 	dprint(2, (debugfile, "** chmod(%s, %.3o) returns %d [errno=%d] **\n",
! 		fname, new_mode & 0777, i, errno));
  
  	(void) umask(old_umask);
  
  #ifdef	BSD
! 	/*
! 	 * Chown is restricted to root on BSD unix
! 	 */
! 	(void) elm_chown(fname, new_owner, new_group);
  #else
  #  ifdef _PC_CHOWN_RESTRICTED
! /*
!  * Chown may or may not be restricted to root in SVR4, if it is,
!  *	then need to copy must be true, and no restore of permissions
!  *	should be performed.
!  */
!         if (!pathconf(fname, _PC_CHOWN_RESTRICTED)) {
  #  endif
! 	    if((i = elm_chown(fname, new_owner, new_group)) == -1)
  		ret_code = -1;
! 
! 	    dprint(2, (debugfile, "** elm_chown(%s, %d, %d) returns %d [errno=%d] **\n",
! 		       fname, new_owner, new_group, i, errno));
  #  ifdef _PC_CHOWN_RESTRICTED
! 	} else {
! 	    (void) elm_chown(fname, new_owner, new_group);
! 	}
  #  endif /* _PC_CHOWN_RESTRICTED */
  #endif /* BSD */
  
  	return(ret_code);
  
--- 826,912 ----
  	 */
  
  	int old_umask, i, new_mode, new_owner, new_group, ret_code;
! 	struct stat testbuf;
! 	new_mode = mail_permissions;
  	new_owner = userid;
  	new_group = groupid;
  	ret_code = 0;
  
  	if(strcmp(fname, saved_fname) == 0) {
! 	  new_mode = saved_buf.st_mode & 0777;
! 	  
! 	  /* Restore also special bits if file is NOT executable */
! 	  if (!(saved_buf.st_mode & 0111)) {
! 	    new_mode |= saved_buf.st_mode & 07000;
! 	    dprint(2, (debugfile, 
! 		       "** not excutable -- restore also special modes\n"));
! 	  }
! 
  	  new_owner = saved_buf.st_uid;
  	  new_group = saved_buf.st_gid;
  	  ret_code = 1;
  	}
+ 
  	dprint(2, (debugfile, "** %s file stats for %s **\n",
! 		   (ret_code ? "restoring" : "setting"), fname));
  
  	old_umask = umask(0);
! 	if((i = chmod(fname, new_mode)) == -1)
  	  ret_code = -1;
  
! 	dprint(2, (debugfile, "** chmod(%s, %05o) returns %d [errno=%d] **\n",
! 		   fname, new_mode, i, errno));
  
  	(void) umask(old_umask);
  
+ 	if(stat(fname, &testbuf) != -1) {
+ 	  dprint(2, (debugfile,
+ 	    "** stats for file owner = %d group = %d mode = %o %s **\n",
+ 	    testbuf.st_uid, testbuf.st_gid, testbuf.st_mode, fname));
+ 
+ 	  /* Don't do chown because it resets special modes, if not
+ 	   * neccessary 
+ 	   */
+ 	  
+ 	  if (new_owner == testbuf.st_uid && new_group == testbuf.st_gid) {
+ 	    dprint(2, (debugfile,
+ 		       "** Owner correct -- chown not needed.\n"));
+ 
+ 	  } else {
+ 
  #ifdef	BSD
! 	    /*
! 	     * Chown is restricted to root on BSD unix
! 	     */
! 	    (void) elm_chown(fname, new_owner, new_group);
  #else
  #  ifdef _PC_CHOWN_RESTRICTED
! 	    /*
! 	     * Chown may or may not be restricted to root in SVR4, if it is,
! 	     *	then need to copy must be true, and no restore of permissions
! 	     *	should be performed.
! 	     */
! 	    if (!pathconf(fname, _PC_CHOWN_RESTRICTED)) {
  #  endif
! 	      if((i = elm_chown(fname, new_owner, new_group)) == -1)
  		ret_code = -1;
! 	      
! 	      dprint(2, (debugfile, "** elm_chown(%s, %d, %d) returns %d [errno=%d] **\n",
! 			 fname, new_owner, new_group, i, errno));
  #  ifdef _PC_CHOWN_RESTRICTED
! 	    } else {
! 	      (void) elm_chown(fname, new_owner, new_group);
! 	    }
  #  endif /* _PC_CHOWN_RESTRICTED */
  #endif /* BSD */
+ 	  }
+ 	}
+ 	
+ 	if(stat(fname, &testbuf) != -1) {
+ 	  dprint(2, (debugfile,
+ 	    "** stats for file owner = %d group = %d mode = %o %s **\n",
+ 	    testbuf.st_uid, testbuf.st_gid, testbuf.st_mode, fname));
+ 	}
  
  	return(ret_code);
  
Index: WORK/src/forms.c
*** elm2.4.25/src/forms.c	Tue Aug  3 22:10:22 1993
--- WORK/src/forms.c	Mon Jun  3 20:18:26 1996
***************
*** 63,68 ****
--- 63,69 ----
  #include "headers.h"
  #include "s_elm.h"
  #include <errno.h>
+ #include "me.h"
  
  extern int errno;
  
***************
*** 124,130 ****
  
  	sprintf(newfname, "%s%s%d", temp_dir, temp_form_file, getpid());
  
! 	if ((newform = fopen(newfname, "w")) == NULL) {
  	  err = errno;
  	  error(catgets(elm_msg_cat, ElmSet, ElmCouldntOpenNewformOutput,
  		"Couldn't open newform file for form output!"));
--- 125,131 ----
  
  	sprintf(newfname, "%s%s%d", temp_dir, temp_form_file, getpid());
  
! 	if ((newform = safeopen(newfname)) == NULL) {
  	  err = errno;
  	  error(catgets(elm_msg_cat, ElmSet, ElmCouldntOpenNewformOutput,
  		"Couldn't open newform file for form output!"));
***************
*** 262,268 ****
  
  	dprint(2, (debugfile,"-- forms sending using file %s --\n", buffer));
  
! 	if ((fd = fopen(buffer,"w")) == NULL) {
  	  error2(catgets(elm_msg_cat, ElmSet, ElmCantOpenAsOutputFile,
  		"Can't open \"%s\" as output file! (%s)."),
  		buffer, error_description(errno));
--- 263,269 ----
  
  	dprint(2, (debugfile,"-- forms sending using file %s --\n", buffer));
  
! 	if ((fd = safeopen(buffer)) == NULL) {
  	  error2(catgets(elm_msg_cat, ElmSet, ElmCantOpenAsOutputFile,
  		"Can't open \"%s\" as output file! (%s)."),
  		buffer, error_description(errno));
***************
*** 315,321 ****
  
  	/** let's just mail this off now... **/
  
! 	mail_form(address, subject);
  
  	return(1);
  }
--- 316,322 ----
  
  	/** let's just mail this off now... **/
  
! 	mail_form(headers[current-1],address, subject);
  
  	return(1);
  }
Index: WORK/src/hdrconfg.c
*** elm2.4.25/src/hdrconfg.c	Tue Aug  3 22:29:09 1993
--- WORK/src/hdrconfg.c	Mon Jun 17 12:50:21 1996
***************
*** 62,70 ****
  /*
   * Placement of prompts and messages at the bottom of the screen.
   */
! #define INSTRUCT_LINE           (LINES-4)
! #define INPUT_LINE		(LINES-2)
! #define ERROR_LINE		(LINES-1)
  #define TOPMOST_PROMPTAREA_LINE INSTRUCT_LINE
  
  /*
--- 62,70 ----
  /*
   * Placement of prompts and messages at the bottom of the screen.
   */
! #define INSTRUCT_LINE           (elm_LINES-4)
! #define INPUT_LINE		(elm_LINES-2)
! #define ERROR_LINE		(elm_LINES-1)
  #define TOPMOST_PROMPTAREA_LINE INSTRUCT_LINE
  
  /*
***************
*** 179,184 ****
--- 179,185 ----
  {
      int c, i, do_redraw;
      struct hdr_menu_item *h;
+     int precmd = 0;
      
      /* expand out all of the header values */
      /* menu displays expanded values, user edits unexpended versions */
***************
*** 187,193 ****
  	    (*h->hdrproc)(h);
      }
  
!     clearerr(stdin);
      do_redraw = TRUE;
      while (TRUE) {	/* forever */
  
--- 188,194 ----
  	    (*h->hdrproc)(h);
      }
  
! redraw:
      do_redraw = TRUE;
      while (TRUE) {	/* forever */
  
***************
*** 215,221 ****
  	/* prompt for command */
  	PutLine0(INPUT_LINE, 0, catgets(elm_msg_cat, ElmSet,
  	    ElmHdrmenuPrompt, "Choice: "));
! 	c = getchar();
  	if (isupper(c))
  	    c = tolower(c);
  	hdrmenu_clear_promptarea();
--- 216,232 ----
  	/* prompt for command */
  	PutLine0(INPUT_LINE, 0, catgets(elm_msg_cat, ElmSet,
  	    ElmHdrmenuPrompt, "Choice: "));
! 	if (precmd) {
! 	  c = precmd;
! 	  precmd = 0;
! 	} else {
! 	  c = ReadCh(REDRAW_MARK);
! 	  if (c == REDRAW_MARK) {
! 	    do_redraw = TRUE;
! 	    continue;
! 	  }
! 	}
! 
  	if (isupper(c))
  	    c = tolower(c);
  	hdrmenu_clear_promptarea();
***************
*** 229,238 ****
  	case 'q':
  	    return 0;
  
! 	case 'd':
! 	    if (domainize_submenu() != 0)
! 		return 0;
! 	    break;
  
  #ifdef ALLOW_SUBSHELL
  	case '!':
--- 240,257 ----
  	case 'q':
  	    return 0;
  
! 	case 'd': {
! 	  int status =  domainize_submenu();
! 	  if (REDRAW_MARK == status) {
! 	    precmd = c;
! 	    do_redraw = TRUE;
! 	    continue;
! 	  }
! 
! 	  if ( status != 0)
! 	    return 0;
! 	}
! 	break;
  
  #ifdef ALLOW_SUBSHELL
  	case '!':
***************
*** 248,257 ****
  	default:
  	    for (h = hmenu_item_list ; h->menucmd > 0 ; ++h) {
  		if (h->menucmd == c) {
! 		    if (hdrmenu_get(h) != 0)
! 			return 0;
! 		    hdrmenu_put(h, FALSE);
  		    break;
  		}
  	    }
  	    if (h->menucmd <= 0) {
--- 267,283 ----
  	default:
  	    for (h = hmenu_item_list ; h->menucmd > 0 ; ++h) {
  		if (h->menucmd == c) {
! 		  int status = hdrmenu_get(h);
! 		  if (REDRAW_MARK == status) {
! 		    precmd = c;
! 		    do_redraw = TRUE;
  		    break;
+ 		  }
+ 
+ 		  if (status != 0)
+ 		    return 0;
+ 		  hdrmenu_put(h, FALSE);
+ 		  break;
  		}
  	    }
  	    if (h->menucmd <= 0) {
***************
*** 325,331 ****
  
      /* get input from the user */
      do_append = ((h->flags & HF_APPENDENTRY) != 0);
!     ret = optionally_enter(h->inpval, INPUT_LINE, plen, do_append, FALSE);
      hdrmenu_clear_promptarea();
  
      /* bail out on error */
--- 351,362 ----
  
      /* get input from the user */
      do_append = ((h->flags & HF_APPENDENTRY) != 0);
!     ret = optionally_enter(h->inpval, INPUT_LINE, plen, 
! 			   (do_append ? OE_APPEND_CURRENT : 0) | 
! 			   OE_REDRAW_MARK);
!     if (ret == REDRAW_MARK)
!       return REDRAW_MARK;
! 
      hdrmenu_clear_promptarea();
  
      /* bail out on error */
***************
*** 354,376 ****
      switch (h->flags & HF_DISP_MASK) {
      case HF_DISP_LEFT:
  	start_row = h->lineno;		max_row = h->lineno;
! 	start_col = 0;			max_col = COLUMNS/2 - 2;
  	break;
      case HF_DISP_RIGHT:
  	start_row = h->lineno;		max_row = h->lineno;
! 	start_col = COLUMNS/2 + 1;	max_col = COLUMNS-1;
  	break;
      case HF_DISP_3ROW:
  	start_row = h->lineno;		max_row = h->lineno+2;
! 	start_col = 0;			max_col = COLUMNS-1;
  	break;
      case HF_DISP_2ROW:
  	start_row = h->lineno;		max_row = h->lineno+1;
! 	start_col = 0;			max_col = COLUMNS-1;
  	break;
      default:
  	start_row = h->lineno;		max_row = h->lineno;
! 	start_col = 0;			max_col = COLUMNS-1;
  	break;
      }
  
--- 385,407 ----
      switch (h->flags & HF_DISP_MASK) {
      case HF_DISP_LEFT:
  	start_row = h->lineno;		max_row = h->lineno;
! 	start_col = 0;			max_col = elm_COLUMNS/2 - 2;
  	break;
      case HF_DISP_RIGHT:
  	start_row = h->lineno;		max_row = h->lineno;
! 	start_col = elm_COLUMNS/2 + 1;	max_col = elm_COLUMNS-1;
  	break;
      case HF_DISP_3ROW:
  	start_row = h->lineno;		max_row = h->lineno+2;
! 	start_col = 0;			max_col = elm_COLUMNS-1;
  	break;
      case HF_DISP_2ROW:
  	start_row = h->lineno;		max_row = h->lineno+1;
! 	start_col = 0;			max_col = elm_COLUMNS-1;
  	break;
      default:
  	start_row = h->lineno;		max_row = h->lineno;
! 	start_col = 0;			max_col = elm_COLUMNS-1;
  	break;
      }
  
***************
*** 397,403 ****
      if (!already_clear) {
  
  	/* clear out remaining space in this line of the field */
! 	if (max_col == COLUMNS-1) {
  	    /* people on slow terminals might appreciate doing it this way */
  	    CleartoEOLN();
  	} else {
--- 428,434 ----
      if (!already_clear) {
  
  	/* clear out remaining space in this line of the field */
! 	if (max_col == elm_COLUMNS-1) {
  	    /* people on slow terminals might appreciate doing it this way */
  	    CleartoEOLN();
  	} else {
***************
*** 575,581 ****
  
      for (;;) {
  
! 	c = getchar();
  
  	switch (tolower(c)) {
  	case 't':
--- 606,614 ----
  
      for (;;) {
  
! 	c = ReadCh(REDRAW_MARK);
! 	if (REDRAW_MARK == c)
! 	  return REDRAW_MARK;
  
  	switch (tolower(c)) {
  	case 't':
***************
*** 711,714 ****
  
  	*--locpart = '!';
  }
- 
--- 744,746 ----
Index: WORK/src/help.c
*** elm2.4.25/src/help.c	Mon May 30 19:42:49 1994
--- WORK/src/help.c	Mon Aug  5 11:12:50 1996
***************
*** 82,99 ****
  			  "Unknown command.  Use '?' for a list of commands.");
  	}
  
! 	MoveCursor(LINES-4,0);
  	CleartoEOS();
  
  	if(pager_help) {
  	  put_border();
! 	  Centerline(LINES, help_message);
! 	  prompt_line = LINES-3;
  	} else {
! 	  Centerline(LINES-4, catgets(elm_msg_cat, ElmSet, ElmHelpSystem,
! 		"ELM Help System"));
! 	  Centerline(LINES-3, help_message);
! 	  prompt_line = LINES-2;
  	}
  	info_line = prompt_line + 1;
  
--- 82,99 ----
  			  "Unknown command.  Use '?' for a list of commands.");
  	}
  
! 	MoveCursor(elm_LINES-4,0);
  	CleartoEOS();
  
  	if(pager_help) {
  	  put_border();
! 	  Centerline(elm_LINES, help_message);
! 	  prompt_line = elm_LINES-3;
  	} else {
! 	  Centerline(elm_LINES-4, catgets(elm_msg_cat, ElmSet, ElmHelpSystem,
! 					  "ELM Help System"));
! 	  Centerline(elm_LINES-3, help_message);
! 	  prompt_line = elm_LINES-2;
  	}
  	info_line = prompt_line + 1;
  
***************
*** 101,108 ****
  
  	do {
  	  MoveCursor(prompt_line, strlen(help_prompt));
! 	  ch = ReadCh();
  	  
  	  if (ch == '.') return(0);	/* zero means footer rewrite only */
  
  	  s = unknown_command;
--- 101,109 ----
  
  	do {
  	  MoveCursor(prompt_line, strlen(help_prompt));
! 	  ch = ReadCh(REDRAW_MARK|READCH_CURSOR);
  	  
+ 	  if (ch == REDRAW_MARK) return 1;
  	  if (ch == '.') return(0);	/* zero means footer rewrite only */
  
  	  s = unknown_command;
***************
*** 109,114 ****
--- 110,116 ----
  
  	  switch (ch) {
  
+ 	  case HELP_MARK:
  	    case '?': display_helpfile(pager_help? PAGER_HELP : MAIN_HELP);
  		      return(1);
  
***************
*** 141,150 ****
--- 143,155 ----
  				"* = Go to the last message in the current folder.");
  		      break;
  
+ 	  case LEFT_MARK:
+ 	  case PAGEUP_MARK:
  	    case '-': if(!pager_help) s = catgets(elm_msg_cat, ElmSet, ElmHelpPreviousPage,
  "- = Go to the previous page of messages.  This is the same as the LEFT arrow.");
  		      break;
  
+ 	  case HOME_MARK:
  	    case '=': if(!pager_help) s = catgets(elm_msg_cat, ElmSet, ElmHelpFirstMessage,
  			"'=' = Go to the first message in the current folder.");
  		      break;
***************
*** 157,167 ****
--- 162,175 ----
  				"<space> = Display the current message.");
  		      break;
  
+ 	  case RIGHT_MARK:
+ 	  case PAGEDOWN_MARK:
  	    case '+': if(!pager_help)
  	    		s = catgets(elm_msg_cat, ElmSet, ElmHelpNextPage,
    "+ = Go to the next page of messages.  This is the same as the RIGHT arrow.");
  		      break;
  
+ 	  case FIND_MARK:
  	    case '/': if(!pager_help)
  			s = catgets(elm_msg_cat, ElmSet, ElmHelpSearchFolder,
  				"/ = Search for specified pattern in folder.");
***************
*** 207,213 ****
  		      break;
  
  #ifdef ALLOW_MAILBOX_EDITING
! 	    case 'e': if(!pager_help) s = catgets(elm_msg_cat, ElmSet, ElmHelpEditor,
       "e = Invoke the editor on the entire folder, resynchronizing when done.");
  		      break;
  #endif
--- 215,223 ----
  		      break;
  
  #ifdef ALLOW_MAILBOX_EDITING
! 	    case 'e': if (user_level < 2)
! 			break;
! 		      if(!pager_help) s = catgets(elm_msg_cat, ElmSet, ElmHelpEditor,
       "e = Invoke the editor on the entire folder, resynchronizing when done.");
  		      break;
  #endif
***************
*** 233,238 ****
--- 243,249 ----
  			"J = Go to the next message.");
  		      break;
  
+ 	  case DOWN_MARK:
  	    case 'j': s = catgets(elm_msg_cat, ElmSet, ElmHelpNextUndeleted,
    "j = Go to the next undeleted message.  This is the same as the DOWN arrow.");
  		      break;
***************
*** 241,246 ****
--- 252,258 ----
  			"K = Go to the previous message.");
  		      break;
  
+ 	  case UP_MARK:
  	    case 'k': s = catgets(elm_msg_cat, ElmSet, ElmHelpPreviousUndeleted,
  "k = Go to the previous undeleted message.  This is the same as the UP arrow.");
  		      break;
***************
*** 306,311 ****
--- 318,328 ----
  	    case ctrl('U') : s = catgets(elm_msg_cat, ElmSet, ElmHelpUndeletePattern,
  		      "^U = Undelete all messages with the specified pattern.");
  		      break;
+ #ifdef MIME
+             case 'v':  s = catgets(elm_msg_cat, ElmSet, ElmHelpViewAttach,
+                        "v = View Attachments in current message.");
+                        break;
+ #endif
  
  	    case 'x': s = catgets(elm_msg_cat, ElmSet, ElmHelpExitFolder,
  			"x = Exit leaving the folder untouched, ask permission if changed.");
***************
*** 389,398 ****
  	ClearScreen();
  
  	while (fgets(buffer, SLEN, fileptr) != NULL) {
! 	  if (lines > LINES-3) {
! 	    PutLine0(LINES, 0, catgets(elm_msg_cat, ElmSet, ElmHelpPressSpaceToContinue,
  		"Press <space> to continue, 'q' to return."));
! 	    if(ReadCh() == 'q') {
  	      clear_error();
  	      fclose(fileptr);
  	      return(TRUE);
--- 406,416 ----
  	ClearScreen();
  
  	while (fgets(buffer, SLEN, fileptr) != NULL) {
! 	  if (lines > elm_LINES-3) {
! 	    PutLine0(elm_LINES, 0, catgets(elm_msg_cat, ElmSet, 
! 					   ElmHelpPressSpaceToContinue,
  		"Press <space> to continue, 'q' to return."));
! 	    if(ReadCh(0) == 'q') {
  	      clear_error();
  	      fclose(fileptr);
  	      return(TRUE);
***************
*** 404,416 ****
  	  else 
  	    Write_to_screen("%s\r", 1, buffer);
  
! 	  lines += strlen(buffer)/COLUMNS + 1;
  	}
  
!         PutLine0(LINES, 0, catgets(elm_msg_cat, ElmSet, ElmHelpPressAnyKeyToReturn,
  		"Press any key to return."));
  
! 	(void) ReadCh();
  	clear_error();
  
  	fclose(fileptr);
--- 422,435 ----
  	  else 
  	    Write_to_screen("%s\r", 1, buffer);
  
! 	  lines += strlen(buffer)/elm_COLUMNS + 1;
  	}
  
!         PutLine0(elm_LINES, 0, catgets(elm_msg_cat, ElmSet, 
! 				       ElmHelpPressAnyKeyToReturn,
  		"Press any key to return."));
  
! 	(void) ReadCh(0);
  	clear_error();
  
  	fclose(fileptr);
Index: WORK/src/in_utils.c
*** elm2.4.25/src/in_utils.c	Thu Sep  1 22:42:41 1994
--- WORK/src/in_utils.c	Sun Aug  4 21:45:18 1996
***************
*** 116,121 ****
--- 116,122 ----
  
  #include "headers.h"
  #include "s_elm.h"
+ #include "me.h"
  #include <errno.h>
  
  extern int errno;		/* system error number */
***************
*** 140,146 ****
  	**/
  	register int ch, cols;
  
! 	cols = COLUMNS - (strlen(question) + 5 );	/* 5 for "Yes." + 1 */
  	if (cols < 0) {
  	    cols = 0;
  	}
--- 141,148 ----
  	**/
  	register int ch, cols;
  
! redraw:
! 	cols = elm_COLUMNS - (strlen(question) + 5 );	/* 5 for "Yes." + 1 */
  	if (cols < 0) {
  	    cols = 0;
  	}
***************
*** 153,167 ****
  	fflush(stdout);
  	fflush(stdin);
  
! 	ch = ReadCh();
! 	if (ch == EOF)
  	  leave(0);
  	ch = tolower(ch);
  
  	while (!( ch == *def_ans_yes || ch == *def_ans_no || ch == '\n' || ch == '\r')) {
! 	  ch = ReadCh();
! 	  if (ch == EOF)
  	    leave(0);
  	  ch = tolower(ch);
  	}
  	if(ch == '\n' || ch == '\r')
--- 155,175 ----
  	fflush(stdout);
  	fflush(stdin);
  
! 	ch = ReadCh(REDRAW_MARK);
! 	if (ch == REDRAW_MARK)
! 	  goto redraw;
! 	if (ch == EOF) {
  	  leave(0);
+ 	}
  	ch = tolower(ch);
  
  	while (!( ch == *def_ans_yes || ch == *def_ans_no || ch == '\n' || ch == '\r')) {
! 	  ch = ReadCh(REDRAW_MARK);
! 	  if (ch == REDRAW_MARK)
! 	    goto redraw;
! 	  if (ch == EOF) {
  	    leave(0);
+ 	  }
  	  ch = tolower(ch);
  	}
  	if(ch == '\n' || ch == '\r')
***************
*** 188,203 ****
  {
  	/** Read a number, where 'ch' is the leading digit! **/
  	
! 	char buff[NLEN];
! 	int  num;
  
  	buff[0] = ch;
  	buff[1] = '\0';
  
! 	PutLine1(LINES-3, COLUMNS-40,catgets(elm_msg_cat, ElmSet, ElmSetCurrentTo,
! 		"Set current %s to :"), item);
! 	if (optionally_enter(buff, LINES-3, COLUMNS-15, TRUE, FALSE) == -1)
  	  return(current);
  
  	if (buff[0] == '\0')
  	  return(current);
--- 196,218 ----
  {
  	/** Read a number, where 'ch' is the leading digit! **/
  	
! 	char buff[SLEN+1];
! 	int  num, status;
  
  	buff[0] = ch;
  	buff[1] = '\0';
  
! redraw:
! 	PutLine1(elm_LINES-3, elm_COLUMNS-40,
! 		 catgets(elm_msg_cat, ElmSet, 
! 			 ElmSetCurrentTo,
! 			 "Set current %s to :"), item);
! 	status = optionally_enter(buff, elm_LINES-3, elm_COLUMNS-15, 
! 				  OE_APPEND_CURRENT|OE_REDRAW_MARK);
! 	if (status == -1)
  	  return(current);
+ 	if (status == REDRAW_MARK)
+ 	  goto redraw;
  
  	if (buff[0] == '\0')
  	  return(current);
***************
*** 207,216 ****
  }
  
  int
! optionally_enter(string, x, y, append_current, passwd)
! char *string;
! int  x,y, append_current, passwd;
  {
  	/** This will display the string on the screen and allow the user to
  	    either accept it (by pressing RETURN) or alter it according to
  	    what the user types.   The various flags are:
--- 222,235 ----
  }
  
  int
! optionally_enter(string, x, y, flags)
!      char *string;
!      int  x,y,flags; 
  {
+   int append_current = 0 != (flags & OE_APPEND_CURRENT);
+   int passwd         = 0 != (flags & OE_PASSWD);
+   int redraw         = (flags & OE_REDRAW_MARK) ? REDRAW_MARK : 0;
+ 
  	/** This will display the string on the screen and allow the user to
  	    either accept it (by pressing RETURN) or alter it according to
  	    what the user types.   The various flags are:
***************
*** 231,238 ****
  	register int ch_count = 0, iindex = 0, escaped = OFF;
  	register int len = strlen(string), maxbuf = SLEN;
  
- 	clearerr(stdin);
- 
  	if(!passwd) {
  	  if(!(x >=0 && y >= 0))
  	    GetXYLocation(&x, &y);
--- 250,255 ----
***************
*** 251,259 ****
  	else
  	  iindex = strlen(string);
  
- 	if (cursor_control)
- 	  transmit_functions(OFF);
- 
  	/** now we have the screen as we want it and the cursor in the 
  	    right place, we can loop around on the input and return the
  	    string as soon as the user presses <RETURN>
--- 268,273 ----
***************
*** 260,277 ****
  	**/
  
  	do {
! 	  ch = getchar();
  
! 	  if (ch == ctrl('D') || ch == EOF) {		/* we've hit EOF */
! 	    if (cursor_control)
! 	      transmit_functions(ON);
  	    return(1);
  	  }
  
  	  if (ch_count++ == 0) {
  	    if (ch == '\n' || ch == '\r') {
- 	      if (cursor_control)
- 	        transmit_functions(ON);
  	      return(0);
  	    }
  	    else if (! append_current) {
--- 274,297 ----
  	**/
  
  	do {
! 	  ch = ReadCh(redraw|READCH_NOCURSOR);
! 
! 	  if (ch == REDRAW_MARK) {
! 	    if (ch_count > 0)
! 	      string[iindex] = '\0';
! 	    return REDRAW_MARK;
! 	  }
! 
! 	  if (ch == eof_char && !escaped
! 	      || ch == EOF) {		/* we've hit EOF */
  
! 	    if (ch_count > 0)
! 	      string[iindex] = '\0';
  	    return(1);
  	  }
  
  	  if (ch_count++ == 0) {
  	    if (ch == '\n' || ch == '\r') {
  	      return(0);
  	    }
  	    else if (! append_current) {
***************
*** 309,322 ****
  	      fflush(stdout);
  	    }
  	  }
! 	  else if (ch == EOF || ch == '\n' || ch == '\r') {
! 	    escaped = OFF;
  	    string[iindex] = '\0';
- 	    if (cursor_control)
- 	      transmit_functions(ON);
  	    return(0);
  	  }
! 	  else if (!passwd && ch == ctrl('W')) {	/* back up a word! */
  	    escaped = OFF;
  	    if (iindex == 0)
  	      continue;		/* no point staying here.. */
--- 329,339 ----
  	      fflush(stdout);
  	    }
  	  }
! 	  else if (ch == '\n' || ch == '\r') {
  	    string[iindex] = '\0';
  	    return(0);
  	  }
! 	  else if (!passwd && ch == word_erase && !escaped) {	/* back up a word! */
  	    escaped = OFF;
  	    if (iindex == 0)
  	      continue;		/* no point staying here.. */
***************
*** 337,348 ****
  	      iindex++;	/* and make sure we point at the first AVAILABLE slot */
  	    }
  	  }
! 	  else if (!passwd && ch == ctrl('R')) {
  	    escaped = OFF;
  	    string[iindex] = '\0';
  	    PutLine1(x,y, "%s", string);	
  	    CleartoEOLN();
  	  }
  	  else if (!escaped && ch == kill_line) {
  	    /* needed to test if escaped since kill_line character could
  	     * be a desired valid printing character */
--- 354,372 ----
  	      iindex++;	/* and make sure we point at the first AVAILABLE slot */
  	    }
  	  }
! 	  else if (!passwd && ch == reprint_char && !escaped) {
  	    escaped = OFF;
  	    string[iindex] = '\0';
  	    PutLine1(x,y, "%s", string);	
  	    CleartoEOLN();
  	  }
+ 	  else if (!passwd && ch == ctrl('L') && redraw) {
+ 	    string[iindex] = '\0';
+ 	    ClearScreen();
+ 	    PutLine1(x,y, "%s", string);	
+ 	    CleartoEOLN();
+ 	    return REDRAW_MARK;
+ 	  }
  	  else if (!escaped && ch == kill_line) {
  	    /* needed to test if escaped since kill_line character could
  	     * be a desired valid printing character */
***************
*** 353,363 ****
  	    }
  	    iindex = 0;
  	  }
! 	  else if (ch == '\0') {
! 	    escaped = OFF;
! 	    if (cursor_control)
! 	      transmit_functions(ON);
! 	    fflush(stdin); 	/* remove extraneous chars, if any */
  	    string[0] = '\0'; /* clean up string, and... */
  	    return(-1);
  	  }
--- 377,384 ----
  	    }
  	    iindex = 0;
  	  }
! 	  else if (ch == '\0' || 
! 		   ch == interrupt_char && !escaped) {
  	    string[0] = '\0'; /* clean up string, and... */
  	    return(-1);
  	  }
***************
*** 393,408 ****
  
  	string[iindex] = '\0';
  
- 	if (cursor_control)
- 	  transmit_functions(ON);
- 
  	return(0);
  }
  
  int
  pattern_enter(string, alt_string, x, y, alternate_prompt)
! char *string, *alt_string, *alternate_prompt;
! int  x,y;
  {
  	/** This function is functionally similar to the routine
  	    optionally-enter, but if the first character pressed
--- 414,426 ----
  
  	string[iindex] = '\0';
  
  	return(0);
  }
  
  int
  pattern_enter(string, alt_string, x, y, alternate_prompt)
!      char *string, *alt_string, *alternate_prompt;
!      int  x,y;
  {
  	/** This function is functionally similar to the routine
  	    optionally-enter, but if the first character pressed
***************
*** 418,439 ****
  	CleartoEOLN();
  	MoveCursor(x,y);
  
! 	if (cursor_control)
! 	  transmit_functions(OFF);
! 
! 	ch = getchar();
  
  	if (ch == '\n' || ch == '\r') {
- 	  if (cursor_control)
- 	    transmit_functions(ON);
  	  return(0);	/* we're done.  No change needed */
  	}
  	
  	if (ch == '/') {
  	  PutLine1(x, 0, "%s", alternate_prompt);
  	  CleartoEOLN();
! 	  (void) optionally_enter(alt_string, x, strlen(alternate_prompt)+1,
! 		 FALSE, FALSE);
  	  return(1);
  	}
  
--- 436,460 ----
  	CleartoEOLN();
  	MoveCursor(x,y);
  
! 	ch = ReadCh(0|READCH_NOCURSOR);
  
  	if (ch == '\n' || ch == '\r') {
  	  return(0);	/* we're done.  No change needed */
  	}
  	
  	if (ch == '/') {
+ 	  int status;
  	  PutLine1(x, 0, "%s", alternate_prompt);
  	  CleartoEOLN();
! 	  status = optionally_enter(alt_string, x, strlen(alternate_prompt)+1,
! 				    OE_REDRAW_MARK);
! 	  while (REDRAW_MARK == status) {
! 	    PutLine1(x, 0, "%s", alternate_prompt);
! 	    status = optionally_enter(alt_string, x, 
! 				      strlen(alternate_prompt)+1,
! 				      OE_REDRAW_MARK|OE_APPEND_CURRENT);
! 	  }
! 
  	  return(1);
  	}
  
***************
*** 462,468 ****
  
  	do {
  	  fflush(stdout);
! 	  ch = getchar();
  
  	  /* the following is converted from a case statement to
  	     allow the variable characters (backspace, kill_line
--- 483,489 ----
  
  	do {
  	  fflush(stdout);
! 	  ch = ReadCh(0);
  
  	  /* the following is converted from a case statement to
  	     allow the variable characters (backspace, kill_line
***************
*** 494,504 ****
  	    else if (ch == '\n' || ch == '\r') {
  	      escaped = OFF;
  	      string[iindex] = '\0';
- 	      if (cursor_control)
- 	        transmit_functions(ON);
  	      return(0);
  	    }
! 	    else if (ch == ctrl('W')) {
  	      escaped = OFF;
  	      if (iindex == 0)
  	        continue;		/* no point staying here.. */
--- 515,523 ----
  	    else if (ch == '\n' || ch == '\r') {
  	      escaped = OFF;
  	      string[iindex] = '\0';
  	      return(0);
  	    }
! 	    else if (ch == word_erase && !escaped) {
  	      escaped = OFF;
  	      if (iindex == 0)
  	        continue;		/* no point staying here.. */
***************
*** 519,525 ****
  	        iindex++;/* and make sure we point at the first AVAILABLE slot */
  	      }
  	    }
! 	    else if (ch == ctrl('R')) {
  	      escaped = OFF;
  	      string[iindex] = '\0';
  	      PutLine1(x,y, "%s", string);	
--- 538,544 ----
  	        iindex++;/* and make sure we point at the first AVAILABLE slot */
  	      }
  	    }
! 	    else if (ch == reprint_char && !escaped) {
  	      escaped = OFF;
  	      string[iindex] = '\0';
  	      PutLine1(x,y, "%s", string);	
***************
*** 533,542 ****
                CleartoEOLN();
  	      iindex = 0;
  	    }
! 	    else if (ch == '\0') {
  	      escaped = OFF;
- 	      if (cursor_control)
- 	        transmit_functions(ON);
  	      fflush(stdin); 	/* remove extraneous chars, if any */
  	      string[0] = '\0'; /* clean up string, and... */
  	      return(-1);
--- 552,560 ----
                CleartoEOLN();
  	      iindex = 0;
  	    }
! 	    else if (ch == '\0' || 
! 		     ch == interrupt_char && !escaped) {
  	      escaped = OFF;
  	      fflush(stdin); 	/* remove extraneous chars, if any */
  	      string[0] = '\0'; /* clean up string, and... */
  	      return(-1);
***************
*** 569,577 ****
  	} while (iindex < SLEN);
  
  	string[iindex] = '\0';
- 
- 	if (cursor_control)
- 	  transmit_functions(ON);
  	return(0);
  }
  
--- 587,592 ----
***************
*** 589,612 ****
  
  	int ch;
  
! 	if (timeout > 0) {
! 	  alarm((unsigned) timeout);
! 	  if (SETJMP(GetPromptBuf)) {
! 	    InGetPrompt = 0;
! 	    ch = NO_OP_COMMAND;
! 	    alarm((unsigned) 0);
! 	  }
! 	  else {
! 	    InGetPrompt = 1;
! 	    ch = ReadCh();
! 	    InGetPrompt = 0;
! 	    alarm((unsigned) 0);
! 	  }
  	}
  	else {
! 	    errno = 0;
! 	    ch = ReadCh();
! 	    if (errno == EINTR) ch = NO_OP_COMMAND;
  	}
  	return(ch);
  }
--- 604,630 ----
  
  	int ch;
  
! 	if (elm_timeout > 0) {
! 	  alarm((unsigned) elm_timeout);
! 	}
! 	if (SETJMP(GetPromptBuf)) {
! 	  InGetPrompt = 0;
! 	  ch = NO_OP_COMMAND;
! 	  alarm((unsigned) 0);
  	}
  	else {
! 	  errno = 0;
! 	  InGetPrompt = 1;
! 	  ch = ReadCh(0|READCH_CURSOR);
! 	  if (errno == EINTR)  ch = NO_OP_COMMAND;
! #ifdef	EAGAIN
! 	  if (errno == EAGAIN) ch = NO_OP_COMMAND;
! #endif
! #ifdef	EWOULDBLOCK
! 	  if (errno == EWOULDBLOCK) ch = NO_OP_COMMAND;
! #endif
! 	  InGetPrompt = 0;
! 	  alarm((unsigned) 0);
  	}
  	return(ch);
  }
Index: WORK/src/init.c
*** elm2.4.25/src/init.c	Mon May 30 19:31:57 1994
--- WORK/src/init.c	Tue Aug 13 15:14:35 1996
***************
*** 125,130 ****
--- 125,132 ----
  #include "patchlevel.h"
  #include "s_elm.h"
  
+ #include "me.h"
+ 
  #ifdef TERMIOS
  #  include <termios.h>
     typedef struct termios term_buff;
***************
*** 135,142 ****
     typedef struct termio term_buff;
  # else
  #  include <sgtty.h>
! #  define tcgetattr(fd,buf)	ioctl((fd),TIOCGETP,(buf))
!    typedef struct sgttyb term_buff;
  # endif
  #endif
  
--- 137,150 ----
     typedef struct termio term_buff;
  # else
  #  include <sgtty.h>
! typedef struct {
!   struct sgttyb sgttyb;
!   struct tchars tchars;
! #ifdef TIOCLGET
!   struct ltchars ltchars;
! #endif
! } term_buff;
! static int tcgetattr P_((int,term_buff *));  /* Prototype */
  # endif
  #endif
  
***************
*** 472,486 ****
  	    value different to that in the termcap entry (for
  	    windowing systems, of course!) **/
  
! 	ScreenSize(&LINES, &COLUMNS);
  
  	if ((cp = getenv("LINES")) != NULL && isdigit(*cp)) {
! 	  sscanf(cp, "%d", &LINES);
! 	  LINES -= 1;	/* kludge for HP Window system? ... */
  	}
  
  	if ((cp = getenv("COLUMNS")) != NULL && isdigit(*cp))
! 	  sscanf(cp, "%d", &COLUMNS);
  
  	/** fix the shell if needed **/
  
--- 480,511 ----
  	    value different to that in the termcap entry (for
  	    windowing systems, of course!) **/
  
! 	ScreenSize(&elm_LINES, &elm_COLUMNS);
! 
! 	/* WARNING: elm_LINES and elm_COLUMNS are inconsistent!
! 	 *
! 	 * elm_LINES    == number of lines in screen -1
! 	 * elm_COLUMNS  == number of rows in screen
! 	 *
! 	 *
! 	 * Check code in MoveCursor!
! 	 *
! 	 * row          == 0 .. elm_LINES
! 	 * col          == 0 .. elm_COLUMNS-1
! 	 *
! 	 *
! 	 * Who was this smart programmer!!!!!!!!!!!!!!!!!!!!!
! 	 *
! 	 *                         - K E H <hurtta@ozone.FMI.FI>
! 	 */
  
  	if ((cp = getenv("LINES")) != NULL && isdigit(*cp)) {
! 	  sscanf(cp, "%d", &elm_LINES);
! 	  elm_LINES -= 1; 
  	}
  
  	if ((cp = getenv("COLUMNS")) != NULL && isdigit(*cp))
! 	  sscanf(cp, "%d", &elm_COLUMNS);
  
  	/** fix the shell if needed **/
  
***************
*** 491,514 ****
  
  	if (! mail_only && ! check_only) {
  
- 	  /* get the cursor control keys... */
- 
- 	  cursor_control = FALSE;
- 
- 	  if ((cp = return_value_of("ku")) != NULL) {
- 	    strcpy(up, cp);
- 	    if ((cp = return_value_of("kd")) != NULL) {
- 	      strcpy(down, cp);
- 	      if ((cp = return_value_of("kl")) != NULL) {
- 		strcpy(left, cp);
- 		if ((cp = return_value_of("kr")) != NULL) {
- 		  strcpy(right, cp);
- 		  cursor_control = TRUE;
- 		  transmit_functions(ON);
- 		}
- 	      }
- 	    }
- 	  }
  	  if (!arrow_cursor) 	/* try to use inverse bar instead */
  	    if (return_value_of("so") != NULL && return_value_of("se") != NULL)
  	        has_highlighting = TRUE;
--- 516,521 ----
***************
*** 520,534 ****
  
  	if (! mail_only && ! check_only) {
  	  if (mini_menu)
! 	    headers_per_page = LINES - 13;
  	  else
! 	    headers_per_page = LINES -  8;	/* 5 more headers! */
  
  	  if (headers_per_page <= 0) {
  	    Raw(OFF);
  	    error1(catgets(elm_msg_cat, ElmSet, ElmWindowSizeTooSmall,
  		 "The window is too small to run Elm.  It must have at least %d rows"),
! 		 1 + LINES - headers_per_page);
  	    exit(1);
  	  }
  	  newmbox(requestedmfile, FALSE);	/* read in the folder! */
--- 527,541 ----
  
  	if (! mail_only && ! check_only) {
  	  if (mini_menu)
! 	    headers_per_page = elm_LINES - 13;
  	  else
! 	    headers_per_page = elm_LINES -  8;	/* 5 more headers! */
  
  	  if (headers_per_page <= 0) {
  	    Raw(OFF);
  	    error1(catgets(elm_msg_cat, ElmSet, ElmWindowSizeTooSmall,
  		 "The window is too small to run Elm.  It must have at least %d rows"),
! 		 1 + elm_LINES - headers_per_page);
  	    exit(1);
  	  }
  	  newmbox(requestedmfile, FALSE);	/* read in the folder! */
***************
*** 579,592 ****
  	  /* set to defaults for terminal driver */
  	  backspace = BACKSPACE;
  	  kill_line = ctrl('U');
  	}
  	else {
  #if defined(TERMIO) || defined(TERMIOS)
  	  backspace = term_buffer.c_cc[VERASE];
  	  kill_line = term_buffer.c_cc[VKILL];
  #else
! 	  backspace = term_buffer.sg_erase;
! 	  kill_line = term_buffer.sg_kill;
  #endif
  	}
  }
--- 586,643 ----
  	  /* set to defaults for terminal driver */
  	  backspace = BACKSPACE;
  	  kill_line = ctrl('U');
+ 	  word_erase = ctrl('W');
+  	  interrupt_char = 0177;	/* DEL */
+  	  reprint_char = ctrl('R');
+  	  eof_char = ctrl('D');
  	}
  	else {
  #if defined(TERMIO) || defined(TERMIOS)
  	  backspace = term_buffer.c_cc[VERASE];
  	  kill_line = term_buffer.c_cc[VKILL];
+ #if   defined(TERMIOS) && defined(VWERASE)
+ 	  word_erase = term_buffer.c_cc[VWERASE];
+ #else
+ 	  word_erase = ctrl('W');
+ #endif
+  	  interrupt_char = term_buffer.c_cc[VINTR];
+ #if defined(TERMIOS) && defined(VREPRINT)
+ 	  reprint_char = term_buffer.c_cc[VREPRINT];
+ #else
+ 	  reprint_char = ctrl('R');
+ #endif
+ 	  eof_char = term_buffer.c_cc[VEOF];
+ #else
+ 	  backspace = term_buffer.sgttyb.sg_erase;
+ 	  kill_line = term_buffer.sgttyb.sg_kill;
+ #ifdef     TIOCLGET
+  	  word_erase = term_buffer.ltchars.t_werasc;
+ 	  reprint_char = term_buffer.ltchars.t_rprntc;
  #else
! 	  word_erase = ctrl('W');
! 	  reprint_char = ctrl('R');
! #endif
! 	  interrupt_char = term_buffer.tchars.t_intrc;
! 	  eof_char = term_buffer.tchars.t_eofc;
  #endif
  	}
  }
+ 
+ #if !defined(TERMIO) && !defined(TERMIOS)
+ static int
+ tcgetattr(fd, buf)
+      int fd;
+      term_buff *buf;
+ {
+ 	if (ioctl(fd, TIOCGETP, &buf->sgttyb) < 0)
+ 	  return(-1);
+ 	if (ioctl(fd, TIOCGETC, &buf->tchars) < 0)
+ 	  return(-1);
+ #ifdef TIOCLGET
+ 	if (ioctl(fd, TIOCLGET, &buf->ltchars) < 0)
+ 	  return(-1);
+ #endif
+ 	return(0);
+ }
+ #endif
+ 
Index: WORK/src/leavembox.c
*** elm2.4.25/src/leavembox.c	Fri Jun  3 20:12:44 1994
--- WORK/src/leavembox.c	Sun Aug  4 23:19:05 1996
***************
*** 160,167 ****
  #ifdef I_SYSUTIME
  #  include <sys/utime.h>
  #endif
  
- 
  /**********
     Since a number of machines don't seem to bother to define the utimbuf
     structure for some *very* obscure reason.... 
--- 160,167 ----
  #ifdef I_SYSUTIME
  #  include <sys/utime.h>
  #endif
+ #include "me.h"
  
  /**********
     Since a number of machines don't seem to bother to define the utimbuf
     structure for some *very* obscure reason.... 
***************
*** 195,200 ****
--- 195,202 ----
  			0	Folder not altered
  			-1	New mail arrived during the process and
  					closing was aborted.
+ 			-2      Leaving of folder failed
+ 			
  	    If "resyncing" we are just writing out folder to reopen it. We
  		therefore only consider deletes and keeps, not stores to mbox.
  		Also we don't remove NEW status so that it can be preserved
***************
*** 223,228 ****
--- 225,231 ----
  		     marked_deleted, marked_read, marked_unread,
  		     last_sortby, ask_questions,  asked_storage_q,
  		     num_chgd_status, need_to_copy;
+ 	int was_symlink = FALSE;
  	char answer;
  	int  err;
  	long bytes();
***************
*** 235,244 ****
--- 238,249 ----
  	ask_questions = ((quitting && !prompt) ? FALSE : question_me);
  
  	/* YES or NO on softkeys */
+ 	/*
  	if (hp_softkeys && ask_questions) {
  	  define_softkeys(YESNO);
  	  softkeys_on();
  	}
+ 	*/
  
  	/* Clear the exit dispositions of all messages, just in case
  	 * they were left set by a previous call to this function
***************
*** 263,269 ****
  	    else
  	      MCsprintf(buffer, catgets(elm_msg_cat, ElmSet, ElmLeaveDeleteMessages,
  		"Delete messages? (%c/%c) "), *def_ans_yes, *def_ans_no);
! 	    answer = want_to(buffer, answer, LINES-3, 0);
  	  }
  
  	  if(answer == *def_ans_yes) {
--- 268,274 ----
  	    else
  	      MCsprintf(buffer, catgets(elm_msg_cat, ElmSet, ElmLeaveDeleteMessages,
  		"Delete messages? (%c/%c) "), *def_ans_yes, *def_ans_no);
! 	    answer = want_to(buffer, answer, elm_LINES-3, 0);
  	  }
  
  	  if(answer == *def_ans_yes) {
***************
*** 315,321 ****
  		MCsprintf(buffer, catgets(elm_msg_cat, ElmSet, ElmLeaveMoveMessages,
  			"Move read messages to \"received\" folder? (%c/%c) "),
  			*def_ans_yes, *def_ans_no);
! 	      answer = want_to(buffer, answer, LINES-3, 0);
  	      asked_storage_q = TRUE;
  	    }
  
--- 320,326 ----
  		MCsprintf(buffer, catgets(elm_msg_cat, ElmSet, ElmLeaveMoveMessages,
  			"Move read messages to \"received\" folder? (%c/%c) "),
  			*def_ans_yes, *def_ans_no);
! 	      answer = want_to(buffer, answer, elm_LINES-3, 0);
  	      asked_storage_q = TRUE;
  	    }
  
***************
*** 369,375 ****
  		  MCsprintf(buffer, catgets(elm_msg_cat, ElmSet, ElmLeaveKeepMessages,
  		    "Keep unread messages in incoming mailbox? (%c/%c) "),
  		    *def_ans_yes, *def_ans_no);
! 		answer = want_to(buffer, answer, LINES-3, 0);
  	      }
  
  	      for (i = 0; i < message_count; i++) {
--- 374,380 ----
  		  MCsprintf(buffer, catgets(elm_msg_cat, ElmSet, ElmLeaveKeepMessages,
  		    "Keep unread messages in incoming mailbox? (%c/%c) "),
  		    *def_ans_yes, *def_ans_no);
! 		answer = want_to(buffer, answer, elm_LINES-3, 0);
  	      }
  
  	      for (i = 0; i < message_count; i++) {
***************
*** 394,400 ****
  	dprint(3, (debugfile, "Messages to keep: %d\n", to_keep));
  
  	if(to_delete + to_store + to_keep != message_count) {
! 	  MoveCursor(LINES, 0);
  	  Raw(OFF);
  	  dprint(1, (debugfile,
  	  "Error: %d to delete + %d to store + %d to keep != %d message cnt\n",
--- 399,405 ----
  	dprint(3, (debugfile, "Messages to keep: %d\n", to_keep));
  
  	if(to_delete + to_store + to_keep != message_count) {
! 	  MoveCursor(elm_LINES, 0);
  	  Raw(OFF);
  	  dprint(1, (debugfile,
  	  "Error: %d to delete + %d to store + %d to keep != %d message cnt\n",
***************
*** 523,529 ****
  	if (folder_type == SPOOL)
  	  lock(OUTGOING);
  	
! 	fflush (mailfile);
  
  	if (mailfile_size != bytes(cur_folder)) {
  	    unlock();
--- 528,534 ----
  	if (folder_type == SPOOL)
  	  lock(OUTGOING);
  	
! 	flush_mailfile();
  
  	if (mailfile_size != bytes(cur_folder)) {
  	    unlock();
***************
*** 550,587 ****
  	      recvd_mail, "leavembox"));
  	    dprint(1, (debugfile, "** %s **\n", error_description(err)));
  
- 	    fflush (mailfile);
  	    unlock();
  
  	    unblock_signals();
  	    return(0);
  	  }
! 	  if ((temp = fopen(recvd_mail,"a")) == NULL) {
  	    err = errno;
  
- 	    fflush (mailfile);
  	    unlock();
  
- 	    MoveCursor(LINES, 0);
- 	    Raw(OFF);
  	    dprint(1, (debugfile, "Error: could not append to file %s\n", 
  	      recvd_mail));
  	    dprint(1, (debugfile, "** %s **\n", error_description(err)));
! 	    printf(catgets(elm_msg_cat, ElmSet, ElmLeaveCouldNotAppend,
  		"Could not append to folder %s!\n"), recvd_mail);
! 	    emergency_exit();
  	  }
  	  dprint(2, (debugfile, "Storing message%s ", plural(to_store)));
  	  for (i = 0; i < message_count; i++) {
  	    if(headers[i]->exit_disposition == STORE) {
  	      current = i+1;
  	      dprint(2, (debugfile, "#%d, ", current));
! 	      copy_message("", temp, CM_UPDATE_STATUS);
  	    }
  	  }
  	  fclose(temp);
  	  dprint(2, (debugfile, "\n\n"));
  	  (void) elm_chown(recvd_mail, userid, groupid);
  	}
  
  	/* If there are any messages to keep, first copy them to a
--- 555,606 ----
  	      recvd_mail, "leavembox"));
  	    dprint(1, (debugfile, "** %s **\n", error_description(err)));
  
  	    unlock();
  
  	    unblock_signals();
  	    return(0);
  	  }
! 
! 	  /* open_end_update seeks to end of file */
! 	  if ((temp = open_end_update(recvd_mail)) == NULL) {
  	    err = errno;
  
  	    unlock();
  
  	    dprint(1, (debugfile, "Error: could not append to file %s\n", 
  	      recvd_mail));
  	    dprint(1, (debugfile, "** %s **\n", error_description(err)));
! 	    error1(catgets(elm_msg_cat, ElmSet, ElmLeaveCouldNotAppend,
  		"Could not append to folder %s!\n"), recvd_mail);
! 	    sleep_message();
! 
! 	    unblock_signals();
! 	    return(0);
  	  }
+ 	  
  	  dprint(2, (debugfile, "Storing message%s ", plural(to_store)));
  	  for (i = 0; i < message_count; i++) {
  	    if(headers[i]->exit_disposition == STORE) {
  	      current = i+1;
  	      dprint(2, (debugfile, "#%d, ", current));
! 	      copy_message(mailfile,headers[i],
! 			   "", temp, CM_UPDATE_STATUS);
  	    }
  	  }
  	  fclose(temp);
  	  dprint(2, (debugfile, "\n\n"));
  	  (void) elm_chown(recvd_mail, userid, groupid);
+ 	  if (ferror(mailfile)) {
+ 	    unlock();
+ 
+ 	    dprint(1, (debugfile, "error when reading mailfile\n"));
+ 	    error1("Error when reading mailfile!",cur_folder);
+ 	    sleep_message();
+ 	    clearerr(mailfile);
+ 
+ 	    unblock_signals();
+ 	    return(-2);
+ 	  }
  	}
  
  	/* If there are any messages to keep, first copy them to a
***************
*** 589,595 ****
  	 */
  	if (to_keep > 0) {
  	  sprintf(temp_keep_file, "%s%s%d", temp_dir, temp_file, getpid());
! 	  if ((err = can_open(temp_keep_file, "w"))) {
  	    error1(catgets(elm_msg_cat, ElmSet, ElmLeaveTempFileDenied,
  "Permission to create temp file %s for writing denied! Leaving folder intact."),
  	      temp_keep_file);
--- 608,614 ----
  	 */
  	if (to_keep > 0) {
  	  sprintf(temp_keep_file, "%s%s%d", temp_dir, temp_file, getpid());
! 	  if ((err = can_open(temp_keep_file, "sw"))) {
  	    error1(catgets(elm_msg_cat, ElmSet, ElmLeaveTempFileDenied,
  "Permission to create temp file %s for writing denied! Leaving folder intact."),
  	      temp_keep_file);
***************
*** 598,623 ****
  	      temp_keep_file, "leavembox"));
  	    dprint(1, (debugfile, "** %s **\n", error_description(err)));
  
- 	    fflush (mailfile);
  	    unlock();
  
  	    unblock_signals();
! 	    return(0);
  	  }
! 	  if ((temp = fopen(temp_keep_file,"w")) == NULL) {
  	    err = errno;
  
- 	    fflush (mailfile);
  	    unlock();
  
- 	    MoveCursor(LINES, 0);
- 	    Raw(OFF);
  	    dprint(1, (debugfile, "Error: could not create file %s\n", 
  	      temp_keep_file));
  	    dprint(1, (debugfile, "** %s **\n", error_description(err)));
! 	    printf(catgets(elm_msg_cat, ElmSet, ElmLeaveCouldNotCreate,
! 		"Could not create temp file %s!\n"), temp_keep_file);
! 	    emergency_exit();
  	  }
  	  dprint(2, (debugfile, "Copying to temp file message%s to be kept ",
  	    plural(to_keep)));
--- 617,640 ----
  	      temp_keep_file, "leavembox"));
  	    dprint(1, (debugfile, "** %s **\n", error_description(err)));
  
  	    unlock();
  
  	    unblock_signals();
! 	    return(-2);
  	  }
! 	  if ((temp = fopen(temp_keep_file,"w+")) == NULL) {
  	    err = errno;
  
  	    unlock();
  
  	    dprint(1, (debugfile, "Error: could not create file %s\n", 
  	      temp_keep_file));
  	    dprint(1, (debugfile, "** %s **\n", error_description(err)));
! 	    error1(catgets(elm_msg_cat, ElmSet, ElmLeaveCouldNotCreate,
! 		"Could not create temp file %s!"), temp_keep_file);
! 
! 	    unblock_signals();
! 	    return(-2);
  	  }
  	  dprint(2, (debugfile, "Copying to temp file message%s to be kept ",
  	    plural(to_keep)));
***************
*** 625,642 ****
  	    if(headers[i]->exit_disposition == KEEP) {
  	      current = i+1;
  	      dprint(2, (debugfile, "#%d, ", current));
! 	      copy_message("", temp, CM_UPDATE_STATUS);
  	    }
  	  }
  	  if ( fclose(temp) == EOF ) {
! 	    MoveCursor(LINES, 0);
! 	    Raw(OFF);
! 	    printf(catgets(elm_msg_cat, ElmSet, ElmLeaveCloseFailedTemp,
! 		"\nClose failed on temp keep file in leavembox\n"));
! 	    perror(temp_keep_file);
! 	    dprint(2, (debugfile, "\n\rfclose err on temp_keep_file - leavembox\n\r"));
! 	    rm_temps_exit();
  	  }
  	  dprint(2, (debugfile, "\n\n"));
  
  	} else if (folder_type == NON_SPOOL && !keep_empty_files && !resyncing) {
--- 642,679 ----
  	    if(headers[i]->exit_disposition == KEEP) {
  	      current = i+1;
  	      dprint(2, (debugfile, "#%d, ", current));
! 	      copy_message(mailfile,headers[i],
! 			   "", temp, CM_UPDATE_STATUS);
  	    }
  	  }
  	  if ( fclose(temp) == EOF ) {
! 	    err = errno;
! 	    unlock();
! 
! 	    error2(catgets(elm_msg_cat, ElmSet, ElmLeaveCloseFailedTemp,
! 			   "Close failed in leavembox: %s: %s"),
! 		   temp_keep_file,
! 		   error_description(err));
! 	    dprint(2, (debugfile, 
! 		       "\n\rfclose err on temp_keep_file - leavembox\n\r"));
! 	    unblock_signals();
! 	    unlink (temp_keep_file);
! 	    return -2;
! 	  }
! 	  if (ferror(mailfile)) {
! 	    unlock();
! 
! 	    dprint(1,(debugfile,"Failed to read mailfile!"));
! 	    error("Failed to read mailfile");
! 	    sleep_message();
! 
! 	    unblock_signals();
! 	    clearerr(mailfile);
! 	    unlink (temp_keep_file);
! 
! 	    return -2;
  	  }
+ 
  	  dprint(2, (debugfile, "\n\n"));
  
  	} else if (folder_type == NON_SPOOL && !keep_empty_files && !resyncing) {
***************
*** 658,665 ****
  	if(save_file_stats(cur_folder) != 0) {
  	  error1(catgets(elm_msg_cat, ElmSet, ElmLeaveProblemsSavingPerms,
  		"Problems saving permissions of folder %s!"), cur_folder);
! 	  if (sleepmsg > 0)
! 		sleep(sleepmsg);
  	}
  	  
          if (stat(cur_folder, &buf) != 0) {
--- 695,702 ----
  	if(save_file_stats(cur_folder) != 0) {
  	  error1(catgets(elm_msg_cat, ElmSet, ElmLeaveProblemsSavingPerms,
  		"Problems saving permissions of folder %s!"), cur_folder);
! 
! 	  sleep_message();
  	}
  	  
          if (stat(cur_folder, &buf) != 0) {
***************
*** 668,673 ****
--- 705,712 ----
  		     error_description(err), cur_folder));
            error2(catgets(elm_msg_cat, ElmSet, ElmLeaveErrorOnStat,
  		"Error %s on stat(%s)."), error_description(err), cur_folder);
+ 
+ 	  sleep_message();
  	}
  
  #ifdef SYMLINK
***************
*** 677,682 ****
--- 716,722 ----
  		     error_description(err), cur_folder));
            error2(catgets(elm_msg_cat, ElmSet, ElmLeaveErrorOnStat,
  		"Error %s on stat(%s)."), error_description(err), cur_folder);
+ 	  sleep_message();
  	}
  #endif
  
***************
*** 705,711 ****
  	 * individual closes in the subcases to ensure that the
  	 * mailbox is locked until we are finished with it.
  	 */
! 	fflush(mailfile);
  
  #ifdef SYSCALL_LOCKING
  	need_to_copy = (folder_type == SPOOL ? TRUE : FALSE);
--- 745,752 ----
  	 * individual closes in the subcases to ensure that the
  	 * mailbox is locked until we are finished with it.
  	 */
! 
! 	flush_mailfile();
  
  #ifdef SYSCALL_LOCKING
  	need_to_copy = (folder_type == SPOOL ? TRUE : FALSE);
***************
*** 715,721 ****
  	if (buf.st_nlink > 1)
  		need_to_copy = TRUE;
  
! 	if (buf.st_mode & 0x7000) { /* copy if special modes set */
  		need_to_copy = TRUE;    /* such as enforcement lock */
  	}
  
--- 756,762 ----
  	if (buf.st_nlink > 1)
  		need_to_copy = TRUE;
  
! 	if (buf.st_mode & 07000) { /* copy if special modes set */
  		need_to_copy = TRUE;    /* such as enforcement lock */
  	}
  
***************
*** 726,731 ****
--- 767,773 ----
  	if ((lbuf.st_mode & S_IFMT) == S_IFLNK) {
  #endif
  		need_to_copy = TRUE;
+ 		was_symlink = TRUE;
  	}
  #endif
  
***************
*** 758,764 ****
  		need_to_copy = TRUE;
  	      } else {
  		err = errno;
! 		MoveCursor(LINES, 0);
  		Raw(OFF);
  		dprint(1, (debugfile, "link(%s, %s) failed (leavembox)\n", 
  		       temp_keep_file, cur_folder));
--- 800,806 ----
  		need_to_copy = TRUE;
  	      } else {
  		err = errno;
! 		MoveCursor(elm_LINES, 0);
  		Raw(OFF);
  		dprint(1, (debugfile, "link(%s, %s) failed (leavembox)\n", 
  		       temp_keep_file, cur_folder));
***************
*** 769,775 ****
  	        if (folder_type == SPOOL)
  		  setgid(groupid);
  #endif
- 		fflush (mailfile);
  		unlock();
  		fclose(mailfile);
  		emergency_exit();
--- 811,816 ----
***************
*** 795,801 ****
  
  		/* couldn't copy to special file either */
  		err = errno;
! 		MoveCursor(LINES, 0);
  		Raw(OFF);
  		dprint(1, (debugfile, 
  			"leavembox: couldn't copy to %s either!!  Help;", 
--- 836,842 ----
  
  		/* couldn't copy to special file either */
  		err = errno;
! 		MoveCursor(elm_LINES, 0);
  		Raw(OFF);
  		dprint(1, (debugfile, 
  			"leavembox: couldn't copy to %s either!!  Help;", 
***************
*** 807,813 ****
  	        if (folder_type == SPOOL)
  		  setgid(groupid);
  #endif
- 		fflush (mailfile);
  		unlock();
  		fclose(mailfile);
  		emergency_exit();
--- 848,853 ----
***************
*** 845,851 ****
  	 * tracking down what it points to.
  	 */
  
! 	if (!need_to_copy) {
  	  if(restore_file_stats(cur_folder) != 1) {
  	    error1(catgets(elm_msg_cat, ElmSet, ElmLeaveProblemsRestoringPerms,
  		  "Problems restoring permissions of folder %s!"), cur_folder);
--- 885,891 ----
  	 * tracking down what it points to.
  	 */
  
! 	if (!was_symlink) {
  	  if(restore_file_stats(cur_folder) != 1) {
  	    error1(catgets(elm_msg_cat, ElmSet, ElmLeaveProblemsRestoringPerms,
  		  "Problems restoring permissions of folder %s!"), cur_folder);
***************
*** 881,887 ****
  	    setgid(groupid);
  #endif
  
- 	fflush (mailfile);
  	mailfile_size = bytes(cur_folder);
  	unlock();	/* remove the lock on the file ASAP! */
  	fclose(mailfile);
--- 921,926 ----
***************
*** 994,997 ****
  #  endif /* HASSIGBLOCK */
  #endif /* HASSIGPROCMASK */
  }
- 
--- 1033,1035 ----
Index: WORK/src/limit.c
*** elm2.4.25/src/limit.c	Mon May 16 02:10:11 1994
--- WORK/src/limit.c	Sun Jun 16 19:53:37 1996
***************
*** 49,59 ****
--- 49,62 ----
  #include "headers.h"
  #include "s_elm.h"
  #include "s_aliases.h"
+ #include "me.h"
  
  #define TO		1
  #define FROM		2
+ #define CC              3
  
  char *shift_lower();
+ void ClearSelection();
  
  int
  limit()
***************
*** 75,100 ****
  	  MCsprintf(msg, catgets(elm_msg_cat, ElmSet, ElmLimitAlreadyHave,
  		"Already have selection criteria - add more? (%c/%c) %c%c"),
  		*def_ans_yes, *def_ans_no, *def_ans_no, BACKSPACE);
! 	  PutLine0(LINES-2, 0, msg);
! 	  criteria[0] = ReadCh();
  	  if (tolower(criteria[0]) == *def_ans_yes) {
  	    Write_to_screen(catgets(elm_msg_cat, ElmSet, ElmYesWord, "Yes."), 0);
! 	    PutLine0(LINES-3, COLUMNS-30, catgets(elm_msg_cat, ElmSet, ElmLimitAdding,
! 		"Adding criteria..."));
  	  } else {
  	    Write_to_screen(catgets(elm_msg_cat, ElmSet, ElmNoWord, "No."), 0);
  	    selected = 0;
- 	    PutLine0(LINES-3, COLUMNS-30, catgets(elm_msg_cat, ElmSet, ElmLimitChanging,
- 		"Change criteria..."));
  	  }
  	}
  
  	while(1) {
! 	  PutLine0(LINES-2, 0, prompt);
  	  CleartoEOLN();
  
  	  criteria[0] = '\0';
! 	  optionally_enter(criteria, LINES-2, strlen(prompt), FALSE, FALSE);
  	  error("");
  	  
  	  if (strlen(criteria) == 0) {
--- 78,107 ----
  	  MCsprintf(msg, catgets(elm_msg_cat, ElmSet, ElmLimitAlreadyHave,
  		"Already have selection criteria - add more? (%c/%c) %c%c"),
  		*def_ans_yes, *def_ans_no, *def_ans_no, BACKSPACE);
! 	  PutLine0(elm_LINES-2, 0, msg);
! 	  criteria[0] = ReadCh(0);
  	  if (tolower(criteria[0]) == *def_ans_yes) {
  	    Write_to_screen(catgets(elm_msg_cat, ElmSet, ElmYesWord, "Yes."), 0);
! 	    PutLine0(elm_LINES-3, elm_COLUMNS-30, 
! 		     catgets(elm_msg_cat, ElmSet, ElmLimitAdding,
! 			     "Adding criteria..."));
  	  } else {
  	    Write_to_screen(catgets(elm_msg_cat, ElmSet, ElmNoWord, "No."), 0);
+ 	    PutLine0(elm_LINES-3, elm_COLUMNS-30, 
+ 		     catgets(elm_msg_cat, ElmSet, ElmLimitChanging,
+ 			     "Change criteria..."));
  	    selected = 0;
  	  }
  	}
  
  	while(1) {
! 	  PutLine0(elm_LINES-2, 0, prompt);
  	  CleartoEOLN();
  
  	  criteria[0] = '\0';
! 	  if (0 != optionally_enter(criteria, elm_LINES-2, strlen(prompt), 0))
! 	    return TRUE;
! 
  	  error("");
  	  
  	  if (strlen(criteria) == 0) {
***************
*** 142,151 ****
  	    if (equal(first, "?")) {
  	      if (last_selected)
  	        error(catgets(elm_msg_cat, ElmSet, ElmEnterLastSelected,
! 	          "Enter: {\"subject\",\"to\",\"from\"} [pattern] OR \"all\""));
  	      else
  	        error(catgets(elm_msg_cat, ElmSet, ElmEnterSelected,
! 		  "Enter: {\"subject\",\"to\",\"from\"} [pattern]"));
  	      continue;
  	    }
  	    else if (equal(first, "all")) {
--- 149,158 ----
  	    if (equal(first, "?")) {
  	      if (last_selected)
  	        error(catgets(elm_msg_cat, ElmSet, ElmEnterLastSelected,
! 	          "Enter: {\"subject\",\"to\",\"from\",\"cc\"} [pattern] OR \"tagged\" OR \"all\""));
  	      else
  	        error(catgets(elm_msg_cat, ElmSet, ElmEnterSelected,
! 		  "Enter: {\"subject\",\"to\",\"from\"} [pattern] OR \"tagged\""));
  	      continue;
  	    }
  	    else if (equal(first, "all")) {
***************
*** 152,171 ****
  	      all++;
  	      selected = 0;
  	    }
! 	    else if (equal(first, "subj") || equal(first, "subject"))
! 	      selected = limit_selection(SUBJECT, rest, selected);
! 	    else if (equal(first, "to"))
! 	      selected = limit_selection(TO, rest, selected);
! 	    else if (equal(first, "from"))
! 	      selected = limit_selection(FROM, rest, selected);
  	    else {
! 	      error1(catgets(elm_msg_cat, ElmSet, ElmLimitNotValidCriterion,
! 		"\"%s\" not a valid criterion."), first);
! 	      continue;
  	    }
  	    break;
  	  }
! 	}
  
  	if (all && last_selected)
  	  strcpy(msg, catgets(elm_msg_cat, ElmSet, ElmLimitReturnToUnlimited,
--- 159,216 ----
  	      all++;
  	      selected = 0;
  	    }
! 	    else if (equal(first, "tagged"))
! 	      selected = SelectTaggedMessages();
  	    else {
! 	      char *c, *p, buf[STRING], buf2[STRING];
! 	      int complx = 0, err = 0, iter = 0;
! 
! 	      if (!selected)
! 		ClearSelection();
! 		
! 	      /* this next bit of code assumes that the input string is a
! 		 list of "and"ed or "or"ed items.  NOTE: it assumes that
! 		 if the first operator is "and", then all operators are "and",
! 		 and vice-versa. */
! 	      strcpy(buf, first);
! 	      strcat(buf, " ");
! 	      strcat(buf, rest);
! 	      p = buf;
! 	      if (index(p, '&') != NULL)
! 		complx = 1;
! 	      while ((c = strtok(p, "|&")) != NULL) {
! 		while (*c && isspace(*c)) ++c;
! 		p = c;
! 		while (*p && !isspace(*p)) ++p;
! 		while (*p && isspace(*p)) ++p;
! 		strcpy(buf2, p);
! 		remove_possible_trailing_spaces(buf2);
! 		if (strncmp(c, "subj", 4) == 0)
! 		  limit_selection(SUBJECT, buf2, selected||(complx&&iter!=0));
! 		else if (strncmp(c, "to", 2) == 0)
! 		  limit_selection(TO, buf2, selected||(complx&&iter!=0));
! 		else if (strncmp(c, "cc", 2) == 0)
! 		  limit_selection(CC, buf2, selected||(complx&&iter!=0));
! 		else if (strncmp(c, "from", 4) == 0)
! 		  limit_selection(FROM, buf2, selected||(complx&&iter!=0));
! 		else {
! 		  if ((p = index(c, ' ')) != NULL)
! 		    *p = '\0';
! 		  error1(catgets(elm_msg_cat, ElmSet, ElmLimitNotValidCriterion,
! 				 "\"%s\" not a valid criterion."), c);
! 		  err = 1;
! 		  break;
! 		}
! 		p = NULL;
! 		++iter;
! 	      }
! 	      if (err)
! 		continue;
! 	      selected = TallySelection();
  	    }
  	    break;
  	  }
!         }
  
  	if (all && last_selected)
  	  strcpy(msg, catgets(elm_msg_cat, ElmSet, ElmLimitReturnToUnlimited,
***************
*** 214,230 ****
  int based_on, additional_criteria;
  char *pattern;
  {
- 	/** Given the type of criteria, and the pattern, mark all
- 	    non-matching headers as ! VISIBLE.  If additional_criteria,
- 	    don't mark as visible something that isn't currently!
- 	**/
- 
  	register int iindex;
  	register char *hdr_value;
- 	int count = 0;
- 
- 	dprint(2, (debugfile, "\n\n\n**limit on %d - '%s' - (%s) **\n\n",
- 		   based_on, pattern, additional_criteria?"add'tl":"base"));
  
  	for (iindex = 0 ; iindex < message_count ; iindex++) {
  
--- 259,266 ----
***************
*** 235,240 ****
--- 271,279 ----
  	    case TO:
  		hdr_value = headers[iindex]->to;
  		break;
+ 	    case CC:
+ 		hdr_value = headers[iindex]->cc;
+ 		break;
  	    case SUBJECT:
  	    default:
  		hdr_value = headers[iindex]->subject;
***************
*** 241,262 ****
  		break;
  	    }
  
! 	    if (!in_string(shift_lower(hdr_value), pattern))
! 		headers[iindex]->status &= ~VISIBLE;
! 	    else if (additional_criteria && !(headers[iindex]->status&VISIBLE))
! 		; /* leave this marked not visible */
! 	    else {
! 		headers[iindex]->status |= VISIBLE;
! 		count++;
! 		dprint(5, (debugfile,
! 		    "  Message %d (%s from %s) marked as visible\n",
! 		    iindex, headers[iindex]->subject, headers[iindex]->from));
! 	    }
! 
! 	}
! 
! 	dprint(4, (debugfile, "\n** returning %d selected **\n\n\n", count));
! 	return(count);
  }
  
  int
--- 280,294 ----
  		break;
  	    }
  
! 	    if (additional_criteria) {
! 	      if (headers[iindex]->status & VISIBLE) {
! 		if (!in_string(shift_lower(hdr_value), pattern))
! 		  headers[iindex]->status &= ~VISIBLE;
! 	      }
! 	    }
! 	    else if (in_string(shift_lower(hdr_value), pattern))
! 	      headers[iindex]->status |= VISIBLE;
!         }
  }
  
  int
***************
*** 438,441 ****
--- 470,504 ----
  	dprint(4, (debugfile, "index %d is NOT displayed!\n", message));
  
  	return(message_count+1);
+ }
+ 
+ void
+ ClearSelection() {
+   int iindex;
+ 
+   for (iindex = 0; iindex < message_count; iindex++)
+     headers[iindex]->status &= ~VISIBLE;
+ }
+ 
+ int
+ TallySelection() {
+   int iindex, count = 0;
+ 
+   for (iindex = 0 ; iindex < message_count ; iindex++)
+     if (headers[iindex]->status & VISIBLE)
+       ++count;
+   return(count);
+ }
+ 
+ int
+ SelectTaggedMessages() {
+   int iindex, count = 0;
+ 
+   for (iindex = 0; iindex < message_count; iindex++)
+     if (headers[iindex]->status & TAGGED) {
+       headers[iindex]->status |= VISIBLE;
+       ++count;
+     } else
+       headers[iindex]->status &= ~VISIBLE;
+   return(count);
  }
Index: WORK/src/lock.c
*** elm2.4.25/src/lock.c	Mon May 16 02:02:12 1994
--- WORK/src/lock.c	Thu Jun 13 23:37:14 1996
***************
*** 275,281 ****
  	    if (kill_status != 0 && errno != EPERM) {
  	      close(create_fd);
  	      if (unlink(lockfile) != 0) {
! 	        MoveCursor(LINES, 0);
  		Raw(OFF);
  		dprint(1, (debugfile,
  		  "Error %s\n\ttrying to unlink file %s (%s)\n", 
--- 275,281 ----
  	    if (kill_status != 0 && errno != EPERM) {
  	      close(create_fd);
  	      if (unlink(lockfile) != 0) {
! 	        MoveCursor(elm_LINES, 0);
  		Raw(OFF);
  		dprint(1, (debugfile,
  		  "Error %s\n\ttrying to unlink file %s (%s)\n", 
***************
*** 310,316 ****
              /* If /var/mail nfs mounted on Solaris 2.3 at least you can */
  	    /* get EACCES.  Treat it like EEXIST. */
  
! 	    MoveCursor(LINES, 0);
  	    Raw(OFF);
  	    if (direction == OUTGOING) {
  	      dprint(1, (debugfile, 
--- 310,316 ----
              /* If /var/mail nfs mounted on Solaris 2.3 at least you can */
  	    /* get EACCES.  Treat it like EEXIST. */
  
! 	    MoveCursor(elm_LINES, 0);
  	    Raw(OFF);
  	    if (direction == OUTGOING) {
  	      dprint(1, (debugfile, 
***************
*** 355,361 ****
  	dprint(2, (debugfile, 
  	   "Warning: I'm giving up waiting - removing lock file(lock)\n"));
  	if (direction == INCOMING)
! 	  PutLine0(LINES, 0, catgets(elm_msg_cat, ElmSet, ElmLeaveTimedOutRemoving,
  		"\nTimed out - removing current lock file..."));
  	else
  	  error(catgets(elm_msg_cat, ElmSet, ElmLeaveThrowingAwayLock,
--- 355,361 ----
  	dprint(2, (debugfile, 
  	   "Warning: I'm giving up waiting - removing lock file(lock)\n"));
  	if (direction == INCOMING)
! 	  PutLine0(elm_LINES, 0, catgets(elm_msg_cat, ElmSet, ElmLeaveTimedOutRemoving,
  		"\nTimed out - removing current lock file..."));
  	else
  	  error(catgets(elm_msg_cat, ElmSet, ElmLeaveThrowingAwayLock,
***************
*** 362,368 ****
  		"Throwing away the current lock file!"));
  
  	if (unlink(lockfile) != 0) {
! 	  MoveCursor(LINES, 0);
  	  Raw(OFF);
  	  dprint(1, (debugfile,
  	    "Error %s\n\ttrying to unlink file %s (%s)\n", 
--- 362,368 ----
  		"Throwing away the current lock file!"));
  
  	if (unlink(lockfile) != 0) {
! 	  MoveCursor(elm_LINES, 0);
  	  Raw(OFF);
  	  dprint(1, (debugfile,
  	    "Error %s\n\ttrying to unlink file %s (%s)\n", 
***************
*** 386,392 ****
  	  dprint(1, (debugfile, 
  	    "Error encountered attempting to create lock %s\n", lockfile));
  	  dprint(1, (debugfile, "** %s **\n", error_description(errno)));
! 	  MoveCursor(LINES, 0);
  	  Raw(OFF);
  	  printf(catgets(elm_msg_cat, ElmSet, ElmLeaveErrorCreatingLock,
  	  "\nError encountered while attempting to create lock file %s;\n"),
--- 386,392 ----
  	  dprint(1, (debugfile, 
  	    "Error encountered attempting to create lock %s\n", lockfile));
  	  dprint(1, (debugfile, "** %s **\n", error_description(errno)));
! 	  MoveCursor(elm_LINES, 0);
  	  Raw(OFF);
  	  printf(catgets(elm_msg_cat, ElmSet, ElmLeaveErrorCreatingLock,
  	  "\nError encountered while attempting to create lock file %s;\n"),
***************
*** 401,407 ****
  	/* Okay...we die and leave, not updating the mailfile mbox or
  	   any of those! */
  
! 	MoveCursor(LINES, 0);
  	Raw(OFF);
  	if (direction == INCOMING) {
  	  printf(catgets(elm_msg_cat, ElmSet, ElmLeaveGivingUp,
--- 401,407 ----
  	/* Okay...we die and leave, not updating the mailfile mbox or
  	   any of those! */
  
! 	MoveCursor(elm_LINES, 0);
  	Raw(OFF);
  	if (direction == INCOMING) {
  	  printf(catgets(elm_msg_cat, ElmSet, ElmLeaveGivingUp,
***************
*** 453,459 ****
  	dprint(1, (debugfile, 
  	    "Error encountered attempting to reopen %s for lock\n", cur_folder));
  	dprint(1, (debugfile, "** %s **\n", error_description(errno)));
! 	MoveCursor(LINES, 0);
  	Raw(OFF);
  	printf(catgets(elm_msg_cat, ElmSet, ElmLeaveErrorReopenMailbox,
   "\nError encountered while attempting to reopen mailbox %s for lock;\n"), 
--- 453,459 ----
  	dprint(1, (debugfile, 
  	    "Error encountered attempting to reopen %s for lock\n", cur_folder));
  	dprint(1, (debugfile, "** %s **\n", error_description(errno)));
! 	MoveCursor(elm_LINES, 0);
  	Raw(OFF);
  	printf(catgets(elm_msg_cat, ElmSet, ElmLeaveErrorReopenMailbox,
   "\nError encountered while attempting to reopen mailbox %s for lock;\n"), 
***************
*** 483,489 ****
  			"Error encountered attempting to flock %s\n",
  			cur_folder));
  	    dprint (1, (debugfile, "** %s **\n", error_description(errno)));
! 	    MoveCursor(LINES, 0);
  	    Raw(OFF);
  	    printf (catgets(elm_msg_cat, ElmSet, ElmLeaveErrorFlockMailbox,
  	 "\nError encountered while attempting to flock mailbox %s;\n"), 
--- 483,489 ----
  			"Error encountered attempting to flock %s\n",
  			cur_folder));
  	    dprint (1, (debugfile, "** %s **\n", error_description(errno)));
! 	    MoveCursor(elm_LINES, 0);
  	    Raw(OFF);
  	    printf (catgets(elm_msg_cat, ElmSet, ElmLeaveErrorFlockMailbox,
  	 "\nError encountered while attempting to flock mailbox %s;\n"), 
***************
*** 512,518 ****
  
        if(errno != 0) {
  
! 	MoveCursor(LINES, 0);
  	Raw(OFF);
  	/* We couldn't lock the file. We die and leave not updating
  	 * the mailfile mbox or any of those! */
--- 512,518 ----
  
        if(errno != 0) {
  
! 	MoveCursor(elm_LINES, 0);
  	Raw(OFF);
  	/* We couldn't lock the file. We die and leave not updating
  	 * the mailfile mbox or any of those! */
***************
*** 553,558 ****
--- 553,574 ----
  }
  
  int
+ flush_mailfile()
+ {
+ 	if (!mailfile)
+ 		return(0);
+ #ifdef ultrix
+ 	/** Ultrix returns an error if fflush is called on a file opened
+ 	    for read only, so we have to account for this.
+ 	**/
+ 
+ 	if ((mailfile->_flag & (_IOREAD|_IORW)) == _IOREAD)
+ 		return(0);
+ #endif
+ 	return(fflush(mailfile));
+ }
+ 
+ int
  unlock()
  {
  	/** Remove the lock file!    This must be part of the interrupt
***************
*** 563,568 ****
--- 579,590 ----
  	 **/
  
  	int retcode = 0;
+ 
+ 	/** Flush the mailfile buffer if necessary before removing the lock.
+ 	**/
+ 
+ 	if (mailfile)
+ 		flush_mailfile();
  
  #ifndef USE_DOTLOCK_LOCKING
  	dprint(5,
Index: WORK/src/mailmsg1.c
*** elm2.4.25/src/mailmsg1.c	Tue Jul 20 05:46:14 1993
--- WORK/src/mailmsg1.c	Sun Jun 16 20:02:10 1996
***************
*** 54,59 ****
--- 54,60 ----
  
  #include "headers.h"
  #include "s_elm.h"
+ #include "me.h"
  
  /** strings defined for the hdrconfg routines **/
  
***************
*** 132,139 ****
  	 **/
  	register int open_paren;
  
! 	to_line = mail_only ? 3 : LINES - 3;
! 	to_col = mail_only ? 0 : COLUMNS - 50;
  	if (names_only)
  	  if ((open_paren = chloc(address, '(')) > 0) {
  	    if (open_paren < chloc(address, ')')) {
--- 133,140 ----
  	 **/
  	register int open_paren;
  
! 	to_line = mail_only ? 3 : elm_LINES - 3;
! 	to_col = mail_only ? 0 : elm_COLUMNS - 50;
  	if (names_only)
  	  if ((open_paren = chloc(address, '(')) > 0) {
  	    if (open_paren < chloc(address, ')')) {
***************
*** 168,183 ****
  
  	if (strlen(to_field) == 0) {
  	  if (user_level < 2) {
! 	    PutLine0(LINES-2, 0, catgets(elm_msg_cat, ElmSet, ElmSendTheMessageTo,
! 		"Send the message to: "));
! 	    (void) optionally_enter(to_field, LINES-2, 21, FALSE, FALSE); 
  	  }
  	  else {
! 	    PutLine0(LINES-2, 0, catgets(elm_msg_cat, ElmSet, ElmTo, "To: "));
! 	    (void) optionally_enter(to_field, LINES-2, 4, FALSE, FALSE); 
  	  }
  	  if (strlen(to_field) == 0) {
! 	    ClearLine(LINES-2);	
  	    return(0);
  	  }
  	  (void) build_address(strip_commas(to_field), address); 
--- 169,206 ----
  
  	if (strlen(to_field) == 0) {
  	  if (user_level < 2) {
! 	    int code;
! 	    PutLine0(elm_LINES-2, 0, 
! 		     catgets(elm_msg_cat, ElmSet, ElmSendTheMessageTo,
! 			     "Send the message to: "));
! 	    code = optionally_enter(to_field, elm_LINES-2, 21, 
! 				    OE_REDRAW_MARK); 
! 	    while (REDRAW_MARK == code) {
! 	      PutLine0(elm_LINES-2, 0, 
! 		       catgets(elm_msg_cat, ElmSet, ElmSendTheMessageTo,
! 			       "Send the message to: "));
! 	      code = optionally_enter(to_field, elm_LINES-2, 21, 
! 				      OE_REDRAW_MARK|OE_APPEND_CURRENT); 
! 	    }
! 	    if (0 != code)
! 	      return 0;
  	  }
  	  else {
! 	    int code;
! 	    PutLine0(elm_LINES-2, 0, 
! 		     catgets(elm_msg_cat, ElmSet, ElmTo, "To: "));
! 	    code = optionally_enter(to_field, elm_LINES-2, 4, OE_REDRAW_MARK); 
! 	    while (code == REDRAW_MARK) {
! 	      PutLine0(elm_LINES-2, 0, 
! 		       catgets(elm_msg_cat, ElmSet, ElmTo, "To: "));
! 	      code = optionally_enter(to_field, elm_LINES-2, 4, 
! 				      OE_REDRAW_MARK|OE_APPEND_CURRENT); 
! 	      if (0 != code)
! 		return 0;
! 	    }
  	  }
  	  if (strlen(to_field) == 0) {
! 	    ClearLine(elm_LINES-2);	
  	    return(0);
  	  }
  	  (void) build_address(strip_commas(to_field), address); 
***************
*** 188,194 ****
  	  strcpy(address, to_field);
  	
  	if (strlen(address) == 0) {	/* bad address!  Removed!! */
! 	  ClearLine(LINES-2);
  	  return(0);
  	}
  
--- 211,217 ----
  	  strcpy(address, to_field);
  	
  	if (strlen(address) == 0) {	/* bad address!  Removed!! */
! 	  ClearLine(elm_LINES-2);
  	  return(0);
  	}
  
***************
*** 195,204 ****
  	return(1);		/* everything is okay... */
  }
  
! int
! send_msg(given_to, given_cc, given_subject, edit_message, form_letter, replying)
! char *given_to, *given_cc, *given_subject;
! int   edit_message, form_letter, replying;
  {
  	/** Prompt for fields and then call mail() to send the specified
  	    message.  If 'edit_message' is true then don't allow the
--- 218,226 ----
  	return(1);		/* everything is okay... */
  }
  
! int send_msg(given_to, given_cc, given_subject, options, form_letter)
!      char *given_to, *given_cc, *given_subject;
!      int   options, form_letter;
  {
  	/** Prompt for fields and then call mail() to send the specified
  	    message.  If 'edit_message' is true then don't allow the
***************
*** 213,218 ****
--- 235,245 ----
  	int  copy_msg = FALSE, is_a_response = FALSE;
  	char *p;
  
+ 	struct header_rec * current_header = NULL;
+       
+ 	if (0 != (options & (MAIL_REPLYING|MAIL_FORWARDING))) 
+ 	  current_header = headers[current-1];
+ 
  	/* First: zero all current global message strings */
  
  	cc[0] = bcc[0] = reply_to[0] = expires[0] = '\0';
***************
*** 229,238 ****
  	if ((p = getenv("REPLYTO")) != NULL)
  	  strcpy(reply_to, p);
  
  	/******* And now the real stuff! *******/
  
  	/* copy msg into edit buffer? */
! 	copy_msg = copy_the_msg(&is_a_response);
  
  	/* get the To: address and expand */
  	if (! get_to(to, expanded_to))
--- 256,270 ----
  	if ((p = getenv("REPLYTO")) != NULL)
  	  strcpy(reply_to, p);
  
+         /* auto bcc line */
+         if ((p = getenv("BCC")) != NULL)
+           strcpy(bcc, p);
+ 
  	/******* And now the real stuff! *******/
  
  	/* copy msg into edit buffer? */
! 	copy_msg = copy_the_msg(&is_a_response, options);
! 	if (copy_msg) options |= MAIL_COPY_MSG;
  
  	/* get the To: address and expand */
  	if (! get_to(to, expanded_to))
***************
*** 246,255 ****
  	if (reply_to[0])
  	  build_address(strip_commas(reply_to), expanded_reply_to);
  
  	/** if we're batchmailing, let's send it and GET OUTTA HERE! **/
  
  	if (batch_only) {
! 	  return(mail(FALSE, FALSE, form_letter));
  	}
  
  	display_to(expanded_to);	/* display the To: field on screen... */
--- 278,291 ----
  	if (reply_to[0])
  	  build_address(strip_commas(reply_to), expanded_reply_to);
  
+ 	/* expand the bcc address */
+ 	if (bcc[0])
+ 	  build_address(strip_commas(bcc), expanded_bcc);
+ 
  	/** if we're batchmailing, let's send it and GET OUTTA HERE! **/
  
  	if (batch_only) {
! 	  return(mail(NULL, 0, form_letter));
  	}
  
  	display_to(expanded_to);	/* display the To: field on screen... */
***************
*** 262,272 ****
  	    return(0);
  	}
  
! 	MoveCursor(LINES,0);	/* so you know you've hit <return> ! */
  
  	/** generate the In-Reply-To: header... **/
  
! 	if (is_a_response && replying)
  	  generate_reply_to(current-1);
  
  	/* and mail that puppy outta here! */
--- 298,308 ----
  	    return(0);
  	}
  
! 	MoveCursor(elm_LINES,0);	/* so you know you've hit <return> ! */
  
  	/** generate the In-Reply-To: header... **/
  
! 	if (is_a_response && 0 != (options & MAIL_REPLYING))
  	  generate_reply_to(current-1);
  
  	/* and mail that puppy outta here! */
***************
*** 276,282 ****
  	dprint(4, (debugfile, "subject=\"%s\"\n",subject));
  	dprint(5, (debugfile, "cc=\"%s\" expanded_cc=\"%s\"\n",cc,expanded_cc));
  	dprint(5, (debugfile, "bcc=\"%s\" expanded_bcc=\"%s\"\n",bcc,expanded_bcc));
! 	return(mail(copy_msg, edit_message, form_letter));
  }
  
  int
--- 312,319 ----
  	dprint(4, (debugfile, "subject=\"%s\"\n",subject));
  	dprint(5, (debugfile, "cc=\"%s\" expanded_cc=\"%s\"\n",cc,expanded_cc));
  	dprint(5, (debugfile, "bcc=\"%s\" expanded_bcc=\"%s\"\n",bcc,expanded_bcc));
! 	return(mail(current_header,options, form_letter));
! 
  }
  
  int
***************
*** 284,295 ****
  char *subject_field;
  {
  	char	ch, msgbuf[SLEN];
  
  	/** get the subject and return non-zero if all okay... **/
  	int len = 9, prompt_line;
  
! 	prompt_line = mail_only ? 4 : LINES-2;
  
  	if (user_level == 0) {
  	  PutLine0(prompt_line,0, catgets(elm_msg_cat, ElmSet, ElmSubjectOfMessage,
  		"Subject of message: "));
--- 321,334 ----
  char *subject_field;
  {
  	char	ch, msgbuf[SLEN];
+ 	int code;
  
  	/** get the subject and return non-zero if all okay... **/
  	int len = 9, prompt_line;
  
! 	prompt_line = mail_only ? 4 : elm_LINES-2;
  
+ redraw:
  	if (user_level == 0) {
  	  PutLine0(prompt_line,0, catgets(elm_msg_cat, ElmSet, ElmSubjectOfMessage,
  		"Subject of message: "));
***************
*** 300,306 ****
  
  	CleartoEOLN();
  
! 	if(optionally_enter(subject_field, prompt_line, len, TRUE, FALSE)==-1){
  	  /** User hit the BREAK key! **/
  	  MoveCursor(prompt_line,0); 	
  	  CleartoEOLN();
--- 339,350 ----
  
  	CleartoEOLN();
  
! 	code = optionally_enter(subject_field, prompt_line, len,
! 				OE_APPEND_CURRENT|OE_REDRAW_MARK);
! 	if (REDRAW_MARK == code)
! 	  goto redraw;
! 
! 	if(code==-1){
  	  /** User hit the BREAK key! **/
  	  MoveCursor(prompt_line,0); 	
  	  CleartoEOLN();
***************
*** 345,357 ****
  	    possibly rewritten Cc: line...
  	**/
  	int prompt_line;
  
! 	prompt_line = mail_only ? 5 : LINES - 1;
! 	PutLine0(prompt_line,0, catgets(elm_msg_cat, ElmSet, ElmCopiesTo, "Copies to: "));
  
  	fflush(stdout);
  
! 	if (optionally_enter(cc_field, prompt_line, 11, FALSE, FALSE) == -1) {
  	  ClearLine(prompt_line-1);
  	  ClearLine(prompt_line);
  	  
--- 389,410 ----
  	    possibly rewritten Cc: line...
  	**/
  	int prompt_line;
+ 	int code;
  
! 	prompt_line = mail_only ? 5 : elm_LINES - 1;
! 	PutLine0(prompt_line,0, 
! 		 catgets(elm_msg_cat, ElmSet, ElmCopiesTo, "Copies to: "));
  
  	fflush(stdout);
  
! 	code = optionally_enter(cc_field, prompt_line, 11, OE_REDRAW_MARK);
! 	while (REDRAW_MARK == code) {
! 	  PutLine0(prompt_line,0, 
! 		   catgets(elm_msg_cat, ElmSet, ElmCopiesTo, "Copies to: "));
! 	  code = optionally_enter(cc_field, prompt_line, 11, 
! 				  OE_REDRAW_MARK|OE_APPEND_CURRENT);
! 	}
! 	if (code == -1) {
  	  ClearLine(prompt_line-1);
  	  ClearLine(prompt_line);
  	  
***************
*** 387,418 ****
  	return(1);		/* everything looks okay! */
  }
  	
! int
! copy_the_msg(is_a_response)
! int *is_a_response;
  {
! 	/** Returns True iff the user wants to copy the message being
! 	    replied to into the edit buffer before invoking the editor! 
! 	    Sets "is_a_response" to true if message is a response...
! 	**/
! 
! 	char msg[SLEN];
! 	int answer = FALSE;
! 
! 	if (forwarding)
! 	  answer = TRUE;
! 	else if (strlen(to) > 0 && !mail_only) {  /* predefined 'to' line! */
! 	  if (auto_copy) 
! 	    answer = TRUE;
! 	  else {
! 	    MCsprintf(msg, catgets(elm_msg_cat, ElmSet, ElmCopyMessageYN,
! 		"Copy message? (%c/%c) "), *def_ans_yes, *def_ans_no);
! 	    answer = (want_to(msg, *def_ans_no, LINES-3, 0) == *def_ans_yes);
! 	  }
! 	  *is_a_response = TRUE;
! 	}
  
! 	return(answer);
  }
  
  int
--- 440,474 ----
  	return(1);		/* everything looks okay! */
  }
  	
! int copy_the_msg(is_a_response, options)
!      int *is_a_response;
!      int options;
  {
!   int forwarding = 0 != (options & MAIL_FORWARDING);
  
!   /** Returns True iff the user wants to copy the message being
!     replied to into the edit buffer before invoking the editor! 
!     Sets "is_a_response" to true if message is a response...
!     **/
! 
!   char msg[SLEN];
!   int answer = FALSE;
!   
!   if (forwarding)
!     answer = TRUE;
!   else if (strlen(to) > 0 && !mail_only) {  /* predefined 'to' line! */
!     if (auto_copy) 
!       answer = TRUE;
!     else {
!       MCsprintf(msg, catgets(elm_msg_cat, ElmSet, ElmCopyMessageYN,
! 			     "Copy message? (%c/%c) "), 
! 		*def_ans_yes, *def_ans_no);
!       answer = (want_to(msg, *def_ans_no, elm_LINES-3, 0) == *def_ans_yes);
!     }
!     *is_a_response = TRUE;
!   }
!   
!   return(answer);
  }
  
  int
***************
*** 420,427 ****
  int   edit_message, form_letter;
  {
  	/** Prompt for fields and then call mail() to send the specified
! 	    message.  If 'edit_message' is true then don't allow the
!             message to be edited. 'form_letter' can be "YES" "NO" or "MAYBE".
  	    if YES, then add the header.  If MAYBE, then add the M)ake form
  	    option to the last question (see mailsg2.c) etc. etc. 
  
--- 476,483 ----
  int   edit_message, form_letter;
  {
  	/** Prompt for fields and then call mail() to send the specified
! 	    message.  If 'edit_message' is true then by defualt go to
!             editor. 'form_letter' can be "YES" "NO" or "MAYBE".
  	    if YES, then add the header.  If MAYBE, then add the M)ake form
  	    option to the last question (see mailsg2.c) etc. etc. 
  
***************
*** 472,478 ****
  	    return(0);
  	}
  
! 	MoveCursor(LINES,0);	/* so you know you've hit <return> ! */
  
  	/* and mail that puppy outta here! */
  	
--- 528,534 ----
  	    return(0);
  	}
  
! 	MoveCursor(elm_LINES,0);	/* so you know you've hit <return> ! */
  
  	/* and mail that puppy outta here! */
  	
***************
*** 483,489 ****
  	dprint(5, (debugfile, "bcc=\"%s\" expanded_bcc=\"%s\"\n",bcc,expanded_bcc));
  
  	main_state();
! 	ret = mail(FALSE, edit_message, form_letter);
  	main_state();
  
  /*
--- 539,545 ----
  	dprint(5, (debugfile, "bcc=\"%s\" expanded_bcc=\"%s\"\n",bcc,expanded_bcc));
  
  	main_state();
! 	ret = mail(NULL, edit_message ? MAIL_EDIT_MSG : 0, form_letter);
  	main_state();
  
  /*
Index: WORK/src/mailmsg2.c
*** elm2.4.25/src/mailmsg2.c	Mon Dec  4 17:50:56 1995
--- WORK/src/mailmsg2.c	Sun Aug 11 18:29:02 1996
***************
*** 1,4 ****
- 
  static char rcsid[] = "@(#)$Id: mailmsg2.c,v 5.39 1994/05/30 17:24:38 syd Exp $";
  
  /*******************************************************************************
--- 1,3 ----
***************
*** 243,248 ****
--- 242,248 ----
  #include "headers.h"
  #include "s_elm.h"
  #include <errno.h>
+ #include "me.h"
  
  extern int errno;
  extern char version_buff[];
***************
*** 266,278 ****
  	    bcc[VERY_LONG_STRING], expanded_bcc[VERY_LONG_STRING],
  	    precedence[SLEN], expires_days[SLEN];
  
  
  #ifdef	MIME
! int msg_is_multipart;
  #endif /* MIME */
! long C_L_Position[2];   /*To Remember position of the Content-Length*/
! long C_StartData[2];    /*To Remember length of Header Area */
! long C_EndData[2];	/* To Remember the end of the BodyPart */
  
  int  gotten_key;
  char *bounce_off_remote();
--- 266,281 ----
  	    bcc[VERY_LONG_STRING], expanded_bcc[VERY_LONG_STRING],
  	    precedence[SLEN], expires_days[SLEN];
  
+ long cl_offset;
+ long cl_start;
+ long cl_end;
  
  #ifdef	MIME
! extern mime_t *attachments;
  #endif /* MIME */
! #ifdef USE_REMAILER
! extern int remailing;
! #endif
  
  int  gotten_key;
  char *bounce_off_remote();
***************
*** 314,323 ****
  	addrs[j] = 0;
  }
  
! int
! mail(copy_msg, edit_message, form)
! int  copy_msg, edit_message, form;
  {
  	/** Given the addresses and various other miscellany (specifically, 
  	    'copy-msg' indicates whether a copy of the current message should 
  	    be included, 'edit_message' indicates whether the message should 
--- 317,335 ----
  	addrs[j] = 0;
  }
  
! #ifdef MIME
! static int check_8bit_str P_((char *str));    /* Prototype */
! #endif
! 
! int mail(current_header,options,form)
!      struct header_rec * current_header;
!      int options,form;
  {
+   int copy_msg       = 0 != current_header && 0 != (options & MAIL_COPY_MSG);
+   int edit_message   =                        0 != (options & MAIL_EDIT_MSG);
+   int replying       = 0 != current_header && 0 != (options & MAIL_REPLYING);
+   int forwarding     = 0 != current_header && 0 != (options & MAIL_FORWARDING);
+ 
  	/** Given the addresses and various other miscellany (specifically, 
  	    'copy-msg' indicates whether a copy of the current message should 
  	    be included, 'edit_message' indicates whether the message should 
***************
*** 335,352 ****
  	char *whole_msg_file, *tempnam();
  	char filename[SLEN], fname[SLEN], copy_file[SLEN],
               very_long_buffer[VERY_LONG_STRING], mailerflags[NLEN];
! 	int ch, sys_status, line_len, filename_handle;
  	register int retransmit = FALSE; 
  	int      already_has_text = FALSE;		/* we need an ADDRESS */
  	int	 signature_done = FALSE;
  	int	 need_redraw = 0;
  	int	 err;
  
  	static int cancelled_msg = 0;
  
  	dprint(4, (debugfile, "\nMailing to \"%s\" (with%s editing)\n",
  		  expanded_to, edit_message? "" : "out"));
! 	
  	gotten_key = 0;		/* ignore previously gotten encryption key */
  
  	/** first generate the temporary filename **/
--- 347,392 ----
  	char *whole_msg_file, *tempnam();
  	char filename[SLEN], fname[SLEN], copy_file[SLEN],
               very_long_buffer[VERY_LONG_STRING], mailerflags[NLEN];
! 	int ch, sys_status, line_len;
  	register int retransmit = FALSE; 
  	int      already_has_text = FALSE;		/* we need an ADDRESS */
  	int	 signature_done = FALSE;
  	int	 need_redraw = 0;
  	int	 err;
+ 	int reask_verify = FALSE;
+ #ifdef MIME
+ 	mime_send_t MIME_info;
+ #endif
  
  	static int cancelled_msg = 0;
  
+         if (current_header && (options & MAIL_ISFORM))
+ 	  copy_msg = FORM;
+ 
+ #ifdef MIME
+ 	/* Initialize structure */
+ 	MIME_info.encoding_top = ENCODING_7BIT;
+         MIME_info.type_opts_top[0] = '\0';
+ 	MIME_info.encoding_text = ENCODING_7BIT;
+ 	MIME_info.Charset = charset;
+ 	MIME_info.need_enc = 0;
+ 	MIME_info.type_text = MIME_TYPE_TEXT;
+ 	strcpy (MIME_info.subtype_text, "plain");
+         MIME_info.type_opts_text[0] = '\0';
+ 	strcpy (MIME_info.encoded_subject, "");
+ 	strfcpy (MIME_info.encoded_fullname, full_username,
+ 		 sizeof(MIME_info.encoded_fullname));
+ #endif /* MIME */
+ #ifdef USE_REMAILER
+         remailing = FALSE;
+ #endif
+ 	cl_offset = cl_start = cl_end = 0;
+ 
  	dprint(4, (debugfile, "\nMailing to \"%s\" (with%s editing)\n",
  		  expanded_to, edit_message? "" : "out"));
! 	/* this will get set to 1 on a successful reply */ 
! 	me_retcode = 0;
! 
  	gotten_key = 0;		/* ignore previously gotten encryption key */
  
  	/** first generate the temporary filename **/
***************
*** 363,371 ****
  
  	if (! retransmit)
          {
!           unlink(filename); /* we don't care if it fails since the open() will catch it*/
!           if ( ( (filename_handle = open(filename, O_RDWR|O_CREAT|O_EXCL,0600)) == -1) ||
! 	       ( (reply = fdopen(filename_handle, "w")) == NULL) ) {
  	    err = errno;
  	    dprint(1, (debugfile, 
                 "Attempt to write to temp file %s failed with error %s (mail)\n",
--- 403,409 ----
  
  	if (! retransmit)
          {
! 	  if ((reply = safeopen_rdwr(filename)) == NULL) {
  	    err = errno;
  	    dprint(1, (debugfile, 
                 "Attempt to write to temp file %s failed with error %s (mail)\n",
***************
*** 443,463 ****
  	  precedence[0] = '\0';
  	}
  	else if (copy_msg && ! retransmit) {  /* if retransmit we have it! */
! 	  if (attribution[0]) {
! 	    fprintf(reply, attribution, headers[current-1]->from);
! 	    fputc('\n', reply);
! 	  }
! 	  else if (forwarding) {
! 	    fputs("Forwarded message:\n", reply);
! 	  }
! 	  if (edit_message) {
! 	    copy_message(prefixchars, reply,
! 		( noheader ? CM_REMOVE_HEADER : 0 ) | CM_MMDF_HEAD | CM_DECODE);
! 	    already_has_text = TRUE;	/* we just added it, right? */
  	  }
! 	  else
! 	    copy_message("", reply,
! 		( noheader ? CM_REMOVE_HEADER : 0 ) | CM_MMDF_HEAD);
  	}
  
          /* append signature now if we are going to use an external editor */
--- 481,590 ----
  	  precedence[0] = '\0';
  	}
  	else if (copy_msg && ! retransmit) {  /* if retransmit we have it! */
! #ifdef MIME
! 	  if (!forwarding || (forwarding && !mimeforward)) {
! #endif
! 	    if (forwarding && !quote_forward) {
! #ifdef MIME
! 	      strfcpy (very_long_buffer, current_header->from,
! 		       sizeof (very_long_buffer));
!               if ((current_header->status & MIME_MESSAGE) && 
! 		  is_rfc1522 (very_long_buffer))
! 	        rfc1522_decode (very_long_buffer, sizeof (very_long_buffer));
! 	      fprintf (reply, "----- Forwarded message from %s -----\n\n", 
! 		       very_long_buffer);
! #else
! 	      fprintf (reply, "----- Forwarded message from %s -----\n\n", 
! 		       current_header->from);
! #endif
! 	    }
! 	    else if (attribution[0]) {
! #ifdef MIME
! 	      strfcpy (very_long_buffer, current_header->from,
! 		       sizeof (very_long_buffer));
!               if ((current_header->status & MIME_MESSAGE) && 
! 		  is_rfc1522 (very_long_buffer))
! 	        rfc1522_decode (very_long_buffer, sizeof (very_long_buffer));
! 	      fprintf(reply, attribution, very_long_buffer);
! #else
! 	      fprintf(reply, attribution, current_header->from);
! #endif
! 	      fputc('\n', reply);
! 	    }
! 	    if (edit_message) {
! 	      int NOHDR = forwarding ? noheaderfwd : noheader;
! 	      int NOQUOTE = forwarding && !quote_forward; 
! 	      copy_message(mailfile,current_header,
! 			   NOQUOTE ? "" : prefixchars, reply,
! 			   ( NOHDR ? CM_REMOVE_HEADER : 0 ) 
! 			   | CM_MMDF_HEAD | CM_DECODE 
! 			   /* I think it is good idea to use CM_FILT_HDR
! 			    * even when we don't have forwarding ... -KEH
! 			    */
! 			   | CM_FILT_HDR );
! 	      already_has_text = TRUE;	/* we just added it, right? */
! 	    }
! 	    else {
! 	      int NOHDR = forwarding ? noheaderfwd : noheader;
! 	      copy_message(mailfile,current_header,
! 			   "", reply,
! 			   ( NOHDR ? CM_REMOVE_HEADER : 0 ) 
! 			   | CM_MMDF_HEAD
! 			   /* I added CM_DECODE to here -KEH */
! 			   | CM_DECODE);
! 	    }
! 	    if (forwarding && !quote_forward) {
! #ifdef MIME
! 	      strfcpy (very_long_buffer, current_header->from,
! 		       sizeof (very_long_buffer));
!               if ((current_header->status & MIME_MESSAGE) && 
! 		  is_rfc1522 (very_long_buffer))
! 	        rfc1522_decode (very_long_buffer, sizeof (very_long_buffer));
! 	      fprintf (reply, "----- End of forwarded message from %s -----\n",
! 		       very_long_buffer);
! #else
! 	      fprintf (reply, "----- End of forwarded message from %s -----\n",
! 		       current_header->from);
! #endif
! 	    }
! #ifdef MIME
  	  }
! 	  else {
! 	    FILE *tmpfp;
! 	    int bytes = 0,len,first_line = 1;
! 	    int in_headers = TRUE;
! 
! 	    /* Use MESSAGE/RFC822 to forward messages. */
! 
! 	    sprintf (very_long_buffer, "%selmfwd.%d", temp_dir, getpid ());
! 	    if (! (tmpfp = safeopen_rdwr (very_long_buffer))) {
! 	      error("Failed to create file for forwarding");
! 	    } else {
! 	      attachments = (mime_t *) mime_t_alloc ();
! 	      attachments->flags = MIME_RFC822;
! 	      attachments->pathname = (char *) strmcpy(attachments->pathname, 
! 						       very_long_buffer);
! 
! 
! 	      copy_message(mailfile,current_header,"",tmpfp,
! 			   CM_REMOVE_ENVELOPE);
! 	   
! 	      fclose (tmpfp);
! 	      attachments->unlink = 1; /* mark for later deletion */
! 	      attachments->type = MIME_TYPE_MESSAGE;
! 	      strcpy (attachments->subtype, "rfc822");
! 	      sprintf (very_long_buffer, "Forwarded message from %s", headers[current-1]->from);
! 	      attachments->description = (char *)strmcpy (attachments->description,
! 							  very_long_buffer);
! 	      
! 	      /* Pick up the encoding from the message. */
! 	      attachments->encoding = ENCODING_7BIT;
! 	      (void) update_encoding (&(attachments->encoding),
! 				      headers[current-1]->mime_rec.encoding);
! 	      attachments->length = bytes;
! 	    }
! 	  }
! #endif /* MIME */
  	}
  
          /* append signature now if we are going to use an external editor */
***************
*** 489,543 ****
  	  }
  	} else *copy_file = '\0';	/* signals to not save a copy */
  
! 	/* ask the user to confirm transmission of the message */
! 	if (!batch_only) {
  	    ch = (edit_message? 'e' : '\0');
  	    if (verify_transmission(filename, &form, &need_redraw,
! 		    already_has_text, copy_file, ch) != 0) {
! 		cancelled_msg = (bytes(filename) > 0);
! 		return need_redraw;
  	    }
  	    if (form == YES && format_form(filename) < 1) {
! 		cancelled_msg = (bytes(filename) > 0);
! 		return need_redraw;
  	    }
! 	}
  
! 	if ((reply = fopen(filename,"r")) == NULL) {
  	    err = errno;
  	    dprint(1, (debugfile,
! 		"Attempt to open file %s for reading failed with error %s (mail)\n",
! 		filename, error_description(err)));
  	    if (!batch_only) {
! 		error1(catgets(elm_msg_cat, ElmSet, ElmCouldNotOpenReply,
! 		    "Could not open reply file (%s)."), error_description(err));
  	    } else {
! 		printf(catgets(elm_msg_cat, ElmSet, ElmCouldNotOpenReply,
! 		    "Could not open reply file (%s)."), error_description(err));
! 		putchar('\n');
  	    }
  	    return need_redraw;
! 	}
  
! 	cancelled_msg = FALSE;	/* it ain't cancelled, is it? */
  
! 	/** ask about bounceback if the user wants us to.... **/
  
! 	if (uucp_hops(to) > bounceback && bounceback > 0 && copy_msg != FORM) 
! 	  if (verify_bounceback() == TRUE) {
! 	    if (strlen(cc) > 0) strcat(expanded_cc, ", ");
! 	    strcat(expanded_cc, bounce_off_remote(to));
! 	  }
  
  #ifdef	MIME
! 	/* Look if its a Multimedia/multipart Message */
! 	msg_is_multipart = check_for_multipart(reply);
  
! 	if (msg_is_multipart == -1) {
! 		return(need_redraw);
! 	}
! #endif /* MIME */
  
  	/** grab a copy if the user so desires... **/
  
  	remove_hostbang(expanded_to);
--- 616,851 ----
  	  }
  	} else *copy_file = '\0';	/* signals to not save a copy */
  
! 	do { /* So we can return here if check_for_multipart() fails
! 	      * - K E H <hurtta@dionysos.FMI.FI>    */
! 
! 	  reask_verify = 0;
! 
! 	  /* ask the user to confirm transmission of the message */
! 	  if (!batch_only) {
  	    ch = (edit_message? 'e' : '\0');
+ #ifdef USE_PGP
+ 	    if (verify_transmission(filename, &form, &need_redraw,
+ 				    already_has_text, copy_file, ch, replying) != 0) {
+ 	      cancelled_msg = (bytes(filename) > 0);
+ # ifdef MIME
+ 	      if (attachments) {
+ 		mime_destroy (attachments);
+ 		attachments = 0;
+ 	      }
+ # endif
+ 	      return need_redraw;
+ 	    }
+ #else
  	    if (verify_transmission(filename, &form, &need_redraw,
! 				    already_has_text, copy_file, ch) != 0) {
! 	      cancelled_msg = (bytes(filename) > 0);
! # ifdef MIME
! 	      if (attachments) {
! 		mime_destroy (attachments);
! 		attachments = 0;
! 	      }
! # endif
! 	      return need_redraw;
  	    }
+ #endif /* USE_PGP */
  	    if (form == YES && format_form(filename) < 1) {
! 	      cancelled_msg = (bytes(filename) > 0);
! 	      return need_redraw;
  	    }
!             /* so we can mark the reply flag */
!             me_retcode = 1;
! 	  }
  
! 	  if ((reply = fopen(filename,"r")) == NULL) {
  	    err = errno;
  	    dprint(1, (debugfile,
! 		       "Attempt to open file %s for reading failed with error %s (mail)\n",
! 		       filename, error_description(err)));
  	    if (!batch_only) {
! 	      error1(catgets(elm_msg_cat, ElmSet, ElmCouldNotOpenReply,
! 			     "Could not open reply file (%s)."), error_description(err));
  	    } else {
! 	      printf(catgets(elm_msg_cat, ElmSet, ElmCouldNotOpenReply,
! 			     "Could not open reply file (%s)."), error_description(err));
! 	      putchar('\n');
  	    }
  	    return need_redraw;
! 	  }
! #ifdef MIME
! 	  MIME_info.encoding_top  = ENCODING_7BIT;/* Encoding for Multipart/ */
! 	  MIME_info.encoding_text = ENCODING_7BIT;/* Encoding for Text/plain */
! 	  {
! 	    /* Determine how this message should be MIME encoded:
! 	     * 7BIT, 8BIT, BINARY or QUOTED-PRINTABLE.
! 	     */
! 	    MIME_info.need_enc = needs_encoding (reply);
! 	    if (allow_no_hdrencoding)
! 		MIME_info.need_enc |= check_8bit_str (subject);
! 	    
! 	    if (MIME_info.need_enc & HAVE_BINARY) {
! #ifdef USE_BINARYMIME
! 	      MIME_info.encoding_text =  ENCODING_BINARY;
! #else
! 	      if (allow_no_encoding >= 2)
! 		/* Just send BINARY anyway */
! 		MIME_info.encoding_text = ENCODING_BINARY;
! 	      else
! 		/* no -BBINARYMIME option */
! 		MIME_info.encoding_text = ENCODING_QUOTED;
! #endif
! 	    }
! 	    else if (MIME_info.need_enc & HAVE_8BIT) {
! #ifdef USE_8BITMIME
! 	      MIME_info.encoding_text =  ENCODING_8BIT;
! #else
! 	      if (allow_no_encoding >= 1)
! 		/* Just send 8BIT anyway */
! 		MIME_info.encoding_text = ENCODING_8BIT;
! 	      else
! 		/* no -B8BITMIME option */
! 		MIME_info.encoding_text = ENCODING_QUOTED;
! #endif
! 	    }
! 	    /* Control characters can send with encoding 7BIT
! 	     * HAVE_BINARY takes care really severe stuff */
! 	    if ((MIME_info.need_enc & HAVE_CTRL) &&
! 		MIME_info.encoding_text != ENCODING_QUOTED) {
! 	      if (batch_only) 		
! 		MIME_info.encoding_text =  ENCODING_QUOTED;
! 	      else { 
! 		int ch;
! 		ch = want_to("Text have control characters. \
! Encode text with quoted-printable? ",*def_ans_yes,elm_LINES-1,0);
! 		if (ch == *def_ans_yes) 
! 		  MIME_info.encoding_text =  ENCODING_QUOTED;
! 		else if (ch != *def_ans_no) {
! 		  edit_message = FALSE;
! 		  reask_verify = TRUE;
! 		  continue;    /* Go again to verify_transmission loop */
! 		}
! 	      }
! 	    }
! 	  }
  
! 	  (void) update_encoding(&MIME_info.encoding_top,
! 				 MIME_info.encoding_text);
  
! 	  /* Update Charset */
! 	  MIME_info.Charset = charset;
! 	  if (!(MIME_info.need_enc & HAVE_8BIT) &&
! 	      istrcmp(charset,"US-ASCII") != 0 &&
! 	      charset_ok(charset))
! 	    MIME_info.Charset="US-ASCII";
! 	  else if ((MIME_info.need_enc & HAVE_8BIT) &&
! 		   istrcmp(charset,"US-ASCII") == 0 &&
! 		   istrcmp(display_charset,"US-ASCII") != 0 &&
! 		   charset_ok(display_charset))
! 	    MIME_info.Charset=display_charset;
! 	  else if ((MIME_info.need_enc & HAVE_8BIT) &&
! 		   istrcmp(charset,"US-ASCII") == 0) {
! 	    error("Text has 8BIT data and charset=US-ASCII, using charset=UNKNOWN-8BIT instead.");
! 	    
! 	    if (sleepmsg > 0)
! 	      sleep(sleepmsg);
! 	    
! 	    MIME_info.Charset="UNKNOWN-8BIT";           
!          }
  
! #endif /* MIME */
! 
! 	  cancelled_msg = FALSE;	/* it ain't cancelled, is it? */
! 
! 	  /** ask about bounceback if the user wants us to.... **/
! 
! 	  if (uucp_hops(to) > bounceback && bounceback > 0 && copy_msg != FORM)
! 	    if (verify_bounceback() == TRUE) {
! 	      if (strlen(cc) > 0) strcat(expanded_cc, ", ");
! 	      strcat(expanded_cc, bounce_off_remote(to));
! 	    }
  
  #ifdef	MIME
! 	  MIME_info.msg_is_multipart = check_for_multipart(reply, &MIME_info);
! 	  if (MIME_info.msg_is_multipart < 0) { /* Error in [include ...] */
! 	    if (!batch_only) {
! 	      error ("Please fix [include ...] lines!");
! 	      if (sleepmsg > 0)
! 		sleep (sleepmsg);
  
! 	      edit_message = FALSE;
! 	      reask_verify = TRUE; /* Go to verify_transmission again. */
! 	    }
! 	  }
! 
! 	  if (attachments != 0) {
! 	    /* Determine what the top level Content-Transfer-Encoding: field
! 	     * should be.  BINARY has the highest weight, followed by
! 	     * 8BIT.  NOTE: no checking to see if the mailer supports those
! 	     * encodings since that will already have been done in the
! 	     * attach_menu() routine.
! 	     */
! 	    mime_t *tmp;
! 	    
! 	    MIME_info.msg_is_multipart = TRUE;
! 	    
! 	    for (tmp = attachments; tmp != 0; tmp = tmp->next) {
! 	      (void) update_encoding(&MIME_info.encoding_top,tmp->encoding); 
! 	      if (tmp->pathname) {
! 		if (access(tmp->pathname,READ_ACCESS) < 0) {
! 		  error1("Can't access attachment: %.50s",tmp->pathname);
! 		  reask_verify = TRUE; /* Go to verify_transmission again. */
! 		  if (sleepmsg > 0)
! 		    sleep (sleepmsg);
! 		  edit_message = FALSE;
! 		}
! 	      } else {
! 		error("Bad attachment -- no filename!");
! 	      }
! 	    }
! 	  }
  
+ #endif /* MIME */
+ 	  /* End of check_for_multipart failure loop */
+ 	} while (!batch_only && reask_verify);
+ #ifdef MIME
+ 	if (MIME_info.msg_is_multipart) {
+ 	  (void) mime_generate_boundary (MIME_info.mime_boundary);
+           add_parameter(MIME_info.type_opts_top, "boundary",
+                         MIME_info.mime_boundary, 
+ 			sizeof(MIME_info.type_opts_top),
+                         FALSE);
+ 	}
+ #ifdef USE_PGP
+         if (pgp_status & (PGP_MESSAGE | PGP_SIGNED_MESSAGE | PGP_PUBLIC_KEY)) {
+           MIME_info.type_text = MIME_TYPE_APPLICATION;
+           strcpy(MIME_info.subtype_text, "pgp");
+ 	  if (pgp_status & PGP_PUBLIC_KEY)
+             add_parameter(MIME_info.type_opts_text,"format","keys-only",
+                           sizeof(MIME_info.type_opts_text), FALSE);
+           else {
+             add_parameter(MIME_info.type_opts_text, "format", "text",
+                           sizeof(MIME_info.type_opts_text), FALSE);
+             /* This next bit is a non-non-standard, but exmh does this and it
+              * can be very useful when parsing the message.
+              */
+             if (pgp_status & PGP_MESSAGE) {
+               add_parameter(MIME_info.type_opts_text, "x-action",
+                             (pgp_status & PGP_SIGNED_MESSAGE) ? 
+ 			    "encryptsign" : "encrypt",
+                             sizeof(MIME_info.type_opts_text),FALSE);
+             }
+             else
+               add_parameter(MIME_info.type_opts_text, "x-action", "sign",
+                             sizeof(MIME_info.type_opts_text), FALSE);
+           }
+         }
+ #endif
+ 	/* charset parameter is valid for all subtypes of Text/ */
+         if (MIME_info.type_text == MIME_TYPE_TEXT)
+           add_parameter(MIME_info.type_opts_text, "charset", MIME_info.Charset,
+                         sizeof(MIME_info.type_opts_text), FALSE);
+ #endif
+          
  	/** grab a copy if the user so desires... **/
  
  	remove_hostbang(expanded_to);
***************
*** 544,552 ****
--- 852,965 ----
  	remove_hostbang(expanded_cc);
  	remove_hostbang(expanded_bcc);
  
+ #ifdef USE_REMAILER
+ 	if (remailing)
+ 	  /* Retrieves the database of remailers and sets the To: address
+ 	   * to the appropriate remailer.  This is done here so that a
+ 	   * saved copy of this message will look the same as the outgoing
+ 	   * message.
+ 	   */
+ 	  remailer_proc();
+ #endif
+ 
+ #ifdef MIME
+ 	if (allow_no_hdrencoding) {
+ 	  strfcpy(MIME_info.encoded_subject,subject,
+ 		  sizeof(MIME_info.encoded_subject));
+ 
+ 	  MIME_info.encoded_fullname[0] = '"';
+ 	  strfcpy(MIME_info.encoded_fullname+1,full_username,
+ 		  sizeof(MIME_info.encoded_fullname)-2);
+ 	  strcat(MIME_info.encoded_fullname+1,"\"");
+ 
+ 	  strfcpy(MIME_info.encoded_in_reply_to,in_reply_to,
+ 		  sizeof(MIME_info.encoded_in_reply_to));
+ 
+ 	  dprint(2,(debugfile,"Subject not encoded: %s\n",
+ 		    MIME_info.encoded_subject));
+ 	  dprint(2,(debugfile,"Fullname not encoded: %s\n",
+ 		    MIME_info.encoded_fullname));
+ 	  dprint(2,(debugfile,"In-Reply-To not encoded: %s\n",
+ 		    MIME_info.encoded_in_reply_to));
+ 
+ 	} else {
+ 	  char *ptr,*next_ptr,*rptr;
+ 	  int qcount = 0;
+ 
+ 	  rfc1522_encode_text(MIME_info.encoded_subject,
+ 			      sizeof(MIME_info.encoded_subject),
+ 			      subject,0);
+ 	  rfc1522_encode_text(MIME_info.encoded_fullname,
+ 			      sizeof(MIME_info.encoded_fullname),
+ 			      full_username,HDR_PHRASE);
+ 
+ 	  for (ptr = in_reply_to, rptr = MIME_info.encoded_in_reply_to; 
+ 	       ptr && *ptr; ptr = next_ptr) {
+ 	    int left = ((MIME_info.encoded_in_reply_to + 
+ 			 sizeof(MIME_info.encoded_in_reply_to)) - rptr)-1;
+ 	    char c = 0;
+ 	    if (left < 2)
+ 	      break;
+ 	    next_ptr = qstrpbrk(ptr,"<>");
+ 	    if (next_ptr) {
+ 	      c = *next_ptr;
+ 	      *next_ptr = '\0';
+ 	      if ('<' == c) 
+ 		qcount ++;
+ 	    }
+ 	    dprint(12,(debugfile,
+ 		       "Encoding in-reply-to - elem='%s', qcount=%d, c='%c'\n",
+ 		       ptr,qcount,c));
+ 	    if (!next_ptr || next_ptr > ptr) {
+ 	      int len;
+ 	      if (qcount > 0) {
+ 		strfcpy(rptr,ptr,left);
+ 	      } else if (0 == qcount) {
+ 		rfc1522_encode_text(rptr,left,ptr,HDR_PHRASE);
+ 	      } else {
+ 		error("Error in In-Reply-To");
+ 		*rptr = '\0';		
+ 	      }
+ 	      dprint(12,(debugfile,
+ 			 "Encoding in-reply-to - encoded='%s'\n",
+ 			 rptr));
+ 
+ 	      len = strlen(rptr);
+ 	      rptr += len;
+ 	    }
+ 	    if (next_ptr) {
+ 	      if ('>' == c) 
+ 		qcount --;
+ 	      *next_ptr = c;
+ 	      next_ptr++;
+ 	      if (rptr < (MIME_info.encoded_in_reply_to + 
+ 			  sizeof(MIME_info.encoded_in_reply_to)) -1) 
+ 		*rptr++=c;
+ 	      *rptr='\0';
+ 	    }
+ 	  }
+ 	  *rptr = '\0';
+ 	  if (qcount > 0) {
+ 	    error("Error in In-Reply-To");
+ 	  }
+ 
+ 	  dprint(2,(debugfile,"Encoded subject: %s\n",
+ 		    MIME_info.encoded_subject));
+ 	  dprint(2,(debugfile,"Encoded fullname: %s\n",
+ 		    MIME_info.encoded_fullname));
+ 	  dprint(2,(debugfile,"Encoded In-Reply-To: %s\n",
+ 		    MIME_info.encoded_in_reply_to));
+ 	}
+ #endif
+ 
  	if (*copy_file) /* i.e. if copy_file contains a name */
+ #ifdef MIME
+ 	  save_copy(expanded_to, expanded_cc, expanded_bcc,
+ 	       filename, copy_file, form, &MIME_info);
+ #else
  	  save_copy(expanded_to, expanded_cc, expanded_bcc,
  	       filename, copy_file, form);
+ #endif
  
  	/** write all header information into whole_msg_file **/
  
***************
*** 574,581 ****
  		  expanded_to, expanded_cc, expanded_bcc, subject));
  
  	if ((real_reply = 
  	   write_header_info(whole_msg_file, expanded_to,
! 	     expanded_cc, expanded_bcc, form == YES, FALSE)) == NULL) {
  
  	  /** IT FAILED!!  MEIN GOTT!  Use a dumb mailer instead! **/
  
--- 987,1000 ----
  		  expanded_to, expanded_cc, expanded_bcc, subject));
  
  	if ((real_reply = 
+ #ifdef MIME
+ 	   write_header_info(whole_msg_file, expanded_to,
+ 	     expanded_cc, expanded_bcc, form == YES, FALSE, &MIME_info)
+ #else
  	   write_header_info(whole_msg_file, expanded_to,
! 	     expanded_cc, expanded_bcc, form == YES, FALSE)
! #endif
! 	     ) == NULL) {
  
  	  /** IT FAILED!!  MEIN GOTT!  Use a dumb mailer instead! **/
  
***************
*** 603,634 ****
  
  	}
  	else {
  
! 	  C_StartData[0] = ftell(real_reply);
  
! 	  copy_message_across(reply, real_reply, FALSE);
  
            /* Append signature if not done earlier */
  
            if (!signature_done && !retransmit && copy_msg != FORM)
                 append_sig(real_reply);
- 	  
- #ifdef MIME
- 	  if (!copy_msg != FORM && msg_is_multipart) {
- 	    fprintf(real_reply, "\n--%s--\n", MIME_BOUNDARY);
- 	    if (C_L_Position[1] != 0L) {
- 	      C_EndData[1] = ftell(real_reply);
- 	      C_L_Position[1] = fseek(real_reply, C_L_Position[1], 0);
- 	      fprintf(real_reply, "%d", C_EndData[1] - C_StartData[1]);
- 	      fseek(real_reply, C_EndData[1], 0);
- 	    }
- 	  }
- #endif
  
- 	  C_EndData[0] = ftell(real_reply);
- 	    
- 	  fseek(real_reply, C_L_Position[0], 0);
- 	  fprintf(real_reply, "%d", C_EndData[0] - C_StartData[0]);
  	  fclose(real_reply);
  
  	  if (cc[0] != '\0')  				         /* copies! */
--- 1022,1092 ----
  
  	}
  	else {
+ 	  cl_start = ftell(real_reply);
+ #ifdef MIME
+ #ifdef USE_REMAILER
+ 	  if (remailing) {
+ 	    int ret;
+ 
+ 	    ret = remailer_copy_message_across(reply, real_reply, FALSE,
+ 					       &MIME_info);
+ 	    remailer_destroy_db();
+ 	    /* Check for error to ensure that the message is not sent if
+ 	     * there was a problem, or else the sender's anonymity could
+ 	     * be compromised!
+ 	     */
+ 	    if (ret == -1) {
+ 	      fclose(reply);
+ 	      fclose(real_reply);
+ 	      free(whole_msg_file);
+ 	      unlink(filename);
+ 	      return TRUE;
+ 	    }
+ 	  }
+ 	  else
+ #endif
+ 	    copy_message_across(reply, real_reply, FALSE, &MIME_info);
  
! 	  /* clean up the allocated space */
! 	  if (attachments) {
! 	    mime_destroy (attachments);
! 	    attachments = 0;
! 	  }
! #else
! #ifdef USE_REMAILER
! 	  if (remailing) {
! 	    int ret;
! 
! 	    ret = remailer_copy_message_across(reply, real_reply, FALSE);
! 	    remailer_destroy_db();
! 	    /* Check for error to ensure that the message is not sent if
! 	     * there was a problem, or else the sender's anonymity could
! 	     * be compromised!
! 	     */
! 	    if (ret == -1) {
! 	      fclose(reply);
! 	      fclose(real_reply);
! 	      free(whole_msg_file);
! 	      unlink(filename);
! 	      return TRUE;
! 	    }
! 	  }
! 	  else
! #endif
! 	    copy_message_across(reply, real_reply, FALSE);
! #endif
! 	  cl_end = ftell(real_reply);	    
! 	  fseek(real_reply, cl_offset, 0);
! 	  fprintf(real_reply, "%d", cl_end - cl_start);
  
!           /* Return to the end of the file! */
!           fseek (real_reply, 0, 2);
  
            /* Append signature if not done earlier */
  
            if (!signature_done && !retransmit && copy_msg != FORM)
                 append_sig(real_reply);
  
  	  fclose(real_reply);
  
  	  if (cc[0] != '\0')  				         /* copies! */
***************
*** 654,659 ****
--- 1112,1130 ----
  	  } else
  	    mailerflags[0] ='\0';
  
+ #ifdef MIME
+ #ifdef USE_8BITMIME
+ 	  if (MIME_info.encoding_top == ENCODING_8BIT)
+ 	    strcat(mailerflags," -B8BITMIME");
+ #endif
+ #ifdef USE_BINARYMIME
+           if (MIME_info.encoding_top == ENCODING_BINARY)
+             /* With -BBINARYMIME lines must terminate with \r\n
+              * Unix's \n is _NOT_ sufficient - K E H              */
+             strcat(mailerflags," -BBINARYMIME");
+ #endif
+ #endif
+ 
  	  if (strcmp(submitmail, mailer) == 0)
  	    strcpy(expanded_to, " ");
  	  else {
***************
*** 675,681 ****
  		"Sending mail..."));
  	  printf("\n");
  	} else {
! 	  PutLine0(LINES,0,catgets(elm_msg_cat, ElmSet, ElmSendingMail,
  		"Sending mail..."));
  	  CleartoEOLN();
  	}
--- 1146,1152 ----
  		"Sending mail..."));
  	  printf("\n");
  	} else {
! 	  PutLine0(elm_LINES,0,catgets(elm_msg_cat, ElmSet, ElmSendingMail,
  		"Sending mail..."));
  	  CleartoEOLN();
  	}
***************
*** 713,724 ****
  	 * file just hang after we're finished with it.
  	 */
  	(void)unlink(filename);
! 
  	return(need_redraw);
  }
  
! mail_form(address, subj)
! char *address, *subj;
  {
  	/** copy the appropriate variables to the shared space... */
  
--- 1184,1198 ----
  	 * file just hang after we're finished with it.
  	 */
  	(void)unlink(filename);
! #ifdef USE_PGP
!         pgp_status=0;
! #endif
  	return(need_redraw);
  }
  
! int mail_form(current_header, address, subj)
!      struct header_rec *current_header;
!      char *address, *subj;
  {
  	/** copy the appropriate variables to the shared space... */
  
***************
*** 725,732 ****
  	strcpy(subject, subj);
  	strcpy(to, address);
  	strcpy(expanded_to, address);
! 
! 	return(mail(FORM, NO, NO));
  }
  
  int
--- 1199,1205 ----
  	strcpy(subject, subj);
  	strcpy(to, address);
  	strcpy(expanded_to, address);
! 	return(mail(current_header,MAIL_ISFORM,NO));
  }
  
  int
***************
*** 757,763 ****
  		     "Recall last kept message? (%c/%c) "),
  		     *def_ans_yes, *def_ans_no);
  	  do {
! 	    ch = want_to(msg, '\0', LINES-1, 0);
  	    if (ch == *def_ans_yes) {
                retransmit++;
  	      *already_has_text = TRUE;
--- 1230,1236 ----
  		     "Recall last kept message? (%c/%c) "),
  		     *def_ans_yes, *def_ans_no);
  	  do {
! 	    ch = want_to(msg, '\0', elm_LINES-1, 0);
  	    if (ch == *def_ans_yes) {
                retransmit++;
  	      *already_has_text = TRUE;
***************
*** 783,790 ****
--- 1256,1268 ----
   * message.  Returns 0 to send it, -1 to forget it.
   */
  int
+ #ifdef USE_PGP
  verify_transmission(filename, form_p, need_redraw_p,
+ 	already_has_text, copy_file, force_cmd, replying)
+ #else
+ verify_transmission(filename, form_p, need_redraw_p,
  	already_has_text, copy_file, force_cmd)
+ #endif
  char *filename;		/* pathname to mail mssg composition file	*/
  int  *form_p;		/* pointer to form message state		*/
  int *need_redraw_p;	/* pointer to flag indicating screen stepped on	*/
***************
*** 791,799 ****
  int already_has_text;	/* indicates there is already text in the mssg	*/
  char *copy_file;	/* pointer to buffer holding copy file name	*/
  int force_cmd;		/* command to do, '\0' to prompt user for cmd	*/
  {
      char *prompt_mssg;		/* message to display prompting for cmd	*/
!     char prompt_menu[SLEN];	/* menu of available commands		*/
      int bad_cmd;		/* set TRUE to bitch about user's entry	*/
      int did_prompt;		/* TRUE if cmd prompted for and entered	*/
      int prev_form;		/* "*form_p" value last time thru loop	*/
--- 1269,1281 ----
  int already_has_text;	/* indicates there is already text in the mssg	*/
  char *copy_file;	/* pointer to buffer holding copy file name	*/
  int force_cmd;		/* command to do, '\0' to prompt user for cmd	*/
+ #ifdef USE_PGP
+ int replying;
+ #endif
  {
      char *prompt_mssg;		/* message to display prompting for cmd	*/
!     char prompt_menu[SLEN],	/* menu of available commands		*/
!          prompt_menu2[SLEN];
      int bad_cmd;		/* set TRUE to bitch about user's entry	*/
      int did_prompt;		/* TRUE if cmd prompted for and entered	*/
      int prev_form;		/* "*form_p" value last time thru loop	*/
***************
*** 814,819 ****
--- 1296,1302 ----
  		"Please choose one of the following options by parenthesized letter: s");
  	    strcpy(prompt_menu, catgets(elm_msg_cat, ElmSet, ElmVfyMenuUser0,
  		"e)dit message, edit h)eaders, s)end it, or f)orget it."));
+             strcpy(prompt_menu2, "");
  	} else {
  	    prompt_mssg = catgets(elm_msg_cat, ElmSet, ElmVfyPromptAndNow,
  		"And now: s");
***************
*** 844,849 ****
--- 1327,1349 ----
  	    strcat(prompt_menu, catgets(elm_msg_cat, ElmSet, ElmVfyMenuShell,
  		"!)shell, "));
  #endif
+             /* The previous line was getting too full... */
+             strcpy(prompt_menu2, "");
+ #ifdef MIME
+ 	    strcat(prompt_menu2, "a)ttachments");
+ #endif
+ #if defined(MIME) && defined(USE_PGP)
+ 	    strcat(prompt_menu2,", ");
+ #endif
+ #ifdef USE_PGP
+             strcat(prompt_menu2, "p)gp");
+ #endif
+ #if defined(USE_REMAILER) && defined(USE_PGP)
+ 	    strcat(prompt_menu2,", ");
+ #endif
+ #ifdef USE_REMAILER
+ 	    strcat(prompt_menu2, "r)emailer");
+ #endif
  	    strcat(prompt_menu, catgets(elm_msg_cat, ElmSet, ElmVfyMenuSndFgt,
  		"s)end, or f)orget"));
  	}
***************
*** 863,879 ****
  	    force_cmd = '\0';
  	    did_prompt = FALSE;
  	} else {
! 	    MoveCursor(LINES-2, 0);
! 	    CleartoEOS();
! 	    PutLine0(LINES-2, 0, prompt_mssg);
  	    GetXYLocation(&x_coord, &y_coord);
  	    y_coord--; /* backspace over default answer */
! 	    Centerline(LINES-1, prompt_menu);
  	    fflush(stdin);
  	    fflush(stdout);
  	    Raw(ON); /* double check... testing only... */
  	    MoveCursor(x_coord, y_coord);
! 	    cmd = ReadCh();
  	    if (cmd == EOF)
  	      leave(0);
  	    cmd = tolower(cmd);
--- 1363,1384 ----
  	    force_cmd = '\0';
  	    did_prompt = FALSE;
  	} else {
! 	redraw:
! 	    ClearLine(elm_LINES-3);
! 	    PutLine0(elm_LINES-3, 0, prompt_mssg);
  	    GetXYLocation(&x_coord, &y_coord);
  	    y_coord--; /* backspace over default answer */
! 	    ClearLine(elm_LINES-2);
! 	    Centerline(elm_LINES-2, prompt_menu);
!             ClearLine(elm_LINES-1);
!             Centerline(elm_LINES-1, prompt_menu2);
  	    fflush(stdin);
  	    fflush(stdout);
  	    Raw(ON); /* double check... testing only... */
  	    MoveCursor(x_coord, y_coord);
! 	    cmd = ReadCh(REDRAW_MARK);
! 	    if (cmd == REDRAW_MARK)
! 	      goto redraw;
  	    if (cmd == EOF)
  	      leave(0);
  	    cmd = tolower(cmd);
***************
*** 883,909 ****
  	/* handle command */
  	switch (cmd) {
  
  	case '\n':
  	case '\r':
  	case 's':
  	    if (did_prompt)
! 		Write_to_screen("Send", 0);
  	    return 0;
  	    /*NOTREACHED*/
  
! 	case 'f': 
  	    if (did_prompt)
  		Write_to_screen("Forget", 0);
  	    if (bytes(filename) <= 0) {
  		; /* forget about empty files */
  	    } else if (mail_only) {
! 		sprintf(lbuf, "%s/%s", home, dead_letter);
! 		(void) append_copy_to_file(to, cc, bcc, lbuf, filename,
! 		    *form_p);
  	    } else if (user_level > 0) {
  		set_error(catgets(elm_msg_cat, ElmSet, ElmVfyMessageKept,
  		    "Message kept.  Can be restored at next f)orward, m)ail or r)eply."));
  	    }
  	    return -1;
  	    /*NOTREACHED*/
  
--- 1388,1473 ----
  	/* handle command */
  	switch (cmd) {
  
+ #ifdef  MIME
+ 	case 'a':
+ 	  attachments = (mime_t *) attach_menu (attachments, FALSE);
+ 	  break;
+ #endif
  	case '\n':
  	case '\r':
  	case 's':
  	    if (did_prompt)
! 	        Write_to_screen("Send", 0);
! #ifdef USE_PGP
! 	    if (replying && (headers[current-1]->pgp & PGP_MESSAGE) &&
! 		! (pgp_status & PGP_MESSAGE)) {
!               ClearLine(elm_LINES-2);
! 	      PutLine0(elm_LINES-2, 0, "The recv'd message was PGP encoded, are you sure? ");
! 	      for (;;) {
! 		cmd = ReadCh(0);
! 		if (cmd == 'y' || cmd == 'Y') {
! 		  Write_to_screen("Yes", 0);
! 		  return(0);
! 		}
! 		if (cmd == 'n' || cmd == 'N')
! 		  break;
! 	      }
! 	      break;
! 	    }
! #endif /* USE_PGP */
  	    return 0;
  	    /*NOTREACHED*/
  
!        case 'f': 
  	    if (did_prompt)
  		Write_to_screen("Forget", 0);
  	    if (bytes(filename) <= 0) {
  		; /* forget about empty files */
  	    } else if (mail_only) {
! #ifdef MIME
! 	      FILE * fd;
! 	      mime_send_t MIME_info;
! 	      
! 	      MIME_info.encoding_top  = ENCODING_7BIT;
! 	      if ((fd = fopen(filename,"r")) != NULL) {
! 		MIME_info.msg_is_multipart = 
! 		  check_for_multipart(fd,&MIME_info);
! 		MIME_info.need_enc = needs_encoding (fd);
! 		if (allow_no_hdrencoding)
! 			MIME_info.need_enc |= check_8bit_str (subject);
! 		fclose(fd);
! 	      } else {
! 		MIME_info.msg_is_multipart = 0;
! 		MIME_info.need_enc = 0;
! 	      }
! 	      MIME_info.encoding_text =  ENCODING_7BIT;
! 	      MIME_info.Charset       =  charset;
! 	      
! 	      if (MIME_info.need_enc & HAVE_BINARY) 
! 		MIME_info.encoding_text =  ENCODING_BINARY;
! 	      else  if (MIME_info.need_enc & HAVE_8BIT) 
! 		MIME_info.encoding_text =  ENCODING_8BIT;
! 	      
! 	      update_encoding(&MIME_info.encoding_top,MIME_info.encoding_text);
! 	      
! 	      if (MIME_info.msg_is_multipart)
! 		(void) mime_generate_boundary (MIME_info.mime_boundary);
! 	      
! 	      sprintf(lbuf, "%s/%s", home, dead_letter);
! 	      (void) append_copy_to_file(to, cc, bcc, lbuf, filename,
! 					 *form_p, &MIME_info);
! #else
! 	      sprintf(lbuf, "%s/%s", home, dead_letter);
! 	      (void) append_copy_to_file(to, cc, bcc, lbuf, filename,
! 					 *form_p);
! #endif
  	    } else if (user_level > 0) {
  		set_error(catgets(elm_msg_cat, ElmSet, ElmVfyMessageKept,
  		    "Message kept.  Can be restored at next f)orward, m)ail or r)eply."));
  	    }
+ #ifdef USE_PGP
+             pgp_status = 0; /* make sure to reset! */
+ #endif
  	    return -1;
  	    /*NOTREACHED*/
  
***************
*** 986,992 ****
  	    }
  	    break;
  #endif
! 
  	default:
  	    bad_cmd = TRUE;
  	    break;
--- 1550,1570 ----
  	    }
  	    break;
  #endif
! #ifdef USE_PGP
!         case 'p':
! 	    if (!pgp_status) {
! 	      pgp_status = pgp_menu (filename);
! 	      *need_redraw_p = TRUE;
! 	    }
!             else
! 	      error ("This message is already encrypted and/or signed!");
!             break;
! #endif
! #ifdef USE_REMAILER
! 	case 'r':
! 		remailer_menu ();
! 		break;
! #endif
  	default:
  	    bad_cmd = TRUE;
  	    break;
***************
*** 997,1008 ****
  
  }
  
- 
  FILE *
  write_header_info(filename, long_to, long_cc, long_bcc, form, copy)
! char *filename, *long_to, *long_cc, *long_bcc;
! int   form, copy;
  {
  	/** Try to open filedesc as the specified filename.  If we can,
  	    then write all the headers into the file.  The routine returns
  	    'filedesc' if it succeeded, NULL otherwise.  Added the ability
--- 1575,1591 ----
  
  }
  
  FILE *
+ #ifdef MIME
+ write_header_info(filename, long_to, long_cc, long_bcc, form, copy, mime_info)
+      mime_send_t *mime_info;
+ #else
  write_header_info(filename, long_to, long_cc, long_bcc, form, copy)
! #endif
!      char *filename, *long_to, *long_cc, *long_bcc;
!      int   form, copy;
  {
+ 
  	/** Try to open filedesc as the specified filename.  If we can,
  	    then write all the headers into the file.  The routine returns
  	    'filedesc' if it succeeded, NULL otherwise.  Added the ability
***************
*** 1014,1023 ****
  	char opentype[3];
  	time_t time(), thetime;
  	char *ctime();
! 	static FILE *filedesc;		/* our friendly file descriptor  */
          char to_buf[VERY_LONG_STRING];
  	int err;
! 
  #ifdef SITE_HIDING
  	char  buffer[SLEN];
  	int   is_hidden_user;		/* someone we should know about?  */
--- 1597,1606 ----
  	char opentype[3];
  	time_t time(), thetime;
  	char *ctime();
! 	FILE *filedesc = NULL;		/* our friendly file descriptor  */
          char to_buf[VERY_LONG_STRING];
  	int err;
! 	char fullname_buf[STRING], *qfullname = fullname_buf; 
  #ifdef SITE_HIDING
  	char  buffer[SLEN];
  	int   is_hidden_user;		/* someone we should know about?  */
***************
*** 1025,1043 ****
  #ifdef MMDF
  	int   is_submit_mailer;		/* using submit means change From: */
  #endif /* MMDF */
! 
! 	char  *get_arpa_date();
! 
! 	if(copy) 
! 	    strcpy(opentype, "r+");
! 	else
! 	    strcpy(opentype, "w+");
  
  	save_file_stats(filename);
! 
! 	filedesc = fopen(filename, opentype);
! 	if (copy && filedesc == NULL)
! 	  filedesc = fopen(filename, "w+");
  
  	if (filedesc == NULL) {
  	  err = errno;
--- 1608,1625 ----
  #ifdef MMDF
  	int   is_submit_mailer;		/* using submit means change From: */
  #endif /* MMDF */
! #ifndef DONT_ADD_FROM
! 	char from_buf[3*40+10];
! #endif
!       	char  *get_arpa_date();
  
+ 	sprintf(fullname_buf,"\"%.*s\"",sizeof(fullname_buf)-4,full_username);
  	save_file_stats(filename);
! 	
! 	if (copy) /* Go end of (perhaps existing) file */
! 	  filedesc = open_end_update(filename);
! 	else /* Create _new_ temporary file */
! 	  filedesc = safeopen_rdwr(filename);
  
  	if (filedesc == NULL) {
  	  err = errno;
***************
*** 1053,1063 ****
  	  return(NULL);		/* couldn't open it!! */
  	}
  
- 	if (copy) {
- 		/* Position to the end of the file */
- 		fseek(filedesc, 0L, 2);
- 	}
- 
  	restore_file_stats(filename);
  
  	if(copy) {	/* Add top line that mailer would add */
--- 1635,1640 ----
***************
*** 1100,1108 ****
  	    of headers is irrelevant).  Gahhhhh....
  	**/
  
! 	fprintf(filedesc, "Subject: %s\n", subject);
  
! 	  fprintf(filedesc, "To: %s\n", format_long(long_to, strlen("To:")));
  
  	fprintf(filedesc,"Date: %s\n", get_arpa_date());
  
--- 1677,1734 ----
  	    of headers is irrelevant).  Gahhhhh....
  	**/
  
! #ifdef MIME
! 	if (!form) {
! 	  /* Our standard violations */
! 	  char OSV[100];
! 	  OSV[0] = '\0';
! 
! 	  fprintf(filedesc, "Subject: %s",mime_info ->encoded_subject);
! 	  print_EOLN(filedesc,mime_info->encoding_top);
! 	  qfullname = mime_info->encoded_fullname;
! 
! #ifndef DONT_ADD_FROM
! 	  /* Else From can still be Mime Par 2 encoded */
! 	  if (allow_no_hdrencoding && 
! 	      (check_8bit_str (mime_info ->encoded_subject) ||
! 	       is_rfc1522     (mime_info ->encoded_subject) ||
! 	       check_8bit_str (mime_info ->encoded_in_reply_to) ||
! 	       is_rfc1522     (mime_info ->encoded_in_reply_to) ||
! 	       check_8bit_str (qfullname) ||
! 	       is_rfc1522     (qfullname)))
! 	    add_parameter(OSV,"no-hdr-encoding","1",sizeof(OSV),TRUE);
! #endif
! 
! 	  if (check_8bit_str (mime_info ->encoded_subject) ||
! 	      check_8bit_str (qfullname) ||
! 	      check_8bit_str (mime_info->encoded_in_reply_to))
! 	    add_parameter(OSV,"hdr-charset",
! 			  mime_info ->Charset,sizeof(OSV),FALSE);
! 
! 	  if (strlen(mime_info->encoded_in_reply_to)) {
! 	    fprintf(filedesc, "In-Reply-To: %s", 
! 		    mime_info->encoded_in_reply_to);
! 	    print_EOLN(filedesc,mime_info->encoding_top);
! 	  }
! 
! 	  if (OSV[0]) {
! 	    fprintf(filedesc, "X-ELM-OSV: (Our standard violations) %s",OSV);
! 	    print_EOLN(filedesc,mime_info->encoding_top);
! 	  }
! 
! 	} else 
! #endif
! 	  {
! 	    fprintf(filedesc, "Subject: %s\n", subject);
! 	    qfullname = fullname_buf;	    
! 	    
! 	    if (strlen(in_reply_to) > 0)
! 	      fprintf(filedesc, "In-Reply-To: %s\n", in_reply_to);	
! 	    fprintf(filedesc, 
! 		    "X-ELM-OSV: (Our standard violations) no-mime=1; no-hdr-encoding=1\n");
! 	  }
  
! 	fprintf(filedesc, "To: %s\n", format_long(long_to, strlen("To:")));
  
  	fprintf(filedesc,"Date: %s\n", get_arpa_date());
  
***************
*** 1116,1129 ****
  # ifdef SITE_HIDING
  #    ifdef MMDF
  	if (is_submit_mailer)
! 	  fprintf(filedesc,"From: \"%s\" <%s>\n", full_username, username);
  	else
  #    endif /* MMDF */
  	if (is_hidden_user)
! 	  fprintf(filedesc,"From: \"%s\" <%s!%s!%s>\n", full_username,
  		  hostname, HIDDEN_SITE_NAME, username);
  	else
! 	  fprintf(filedesc,"From: \"%s\" <%s!%s>\n", full_username,
  		  hostname, username);
  # else
  #  ifdef  INTERNET
--- 1742,1755 ----
  # ifdef SITE_HIDING
  #    ifdef MMDF
  	if (is_submit_mailer)
! 	  sprintf(from_buf,"%.40s",username);
  	else
  #    endif /* MMDF */
  	if (is_hidden_user)
! 	  sprintf(from_buf,"%.40s!%.40s!%.40s",
  		  hostname, HIDDEN_SITE_NAME, username);
  	else
! 	  sprintf(from_buf,"%.40s!%.40s",
  		  hostname, username);
  # else
  #  ifdef  INTERNET
***************
*** 1130,1160 ****
  #   ifdef  USE_DOMAIN
  #    ifdef MMDF
  	if (is_submit_mailer)
! 	  fprintf(filedesc,"From: \"%s\" <%s>\n", full_username, username);
  	else
  #    endif /* MMDF */
! 	  fprintf(filedesc,"From: \"%s\" <%s@%s>\n", full_username, 
  		username, hostfullname);
  #   else
  #    ifdef MMDF
  	if (is_submit_mailer)
! 	  fprintf(filedesc,"From: \"%s\" <%s>\n", full_username, username);
  	else
  #    endif /* MMDF */
! 	fprintf(filedesc,"From: \"%s\" <%s@%s>\n", full_username,
  		username, hostname);
  #   endif
  #  else
  #    ifdef MMDF
  	if (is_submit_mailer)
! 	  fprintf(filedesc,"From: \"%s\" <%s>\n", full_username, username);
  	else
  #    endif /* MMDF */
! 	fprintf(filedesc,"From: \"%s\" <%s!%s>\n", full_username,
! 		hostname, username);
  #  endif
  # endif
  #endif
  
  	if (cc[0] != '\0')
  	    fprintf(filedesc, "Cc: %s\n", format_long(long_cc, strlen("Cc: ")));
--- 1756,1792 ----
  #   ifdef  USE_DOMAIN
  #    ifdef MMDF
  	if (is_submit_mailer)
! 	  sprintf(from_buf,"%.40s", username);
  	else
  #    endif /* MMDF */
! 	  sprintf(from_buf,"%.40s@%.40s",  
  		username, hostfullname);
  #   else
  #    ifdef MMDF
  	if (is_submit_mailer)
! 	  sprintf(from_buf,"%.40s", username);
  	else
  #    endif /* MMDF */
! 	sprintf(from_buf,"%.40s@%.40s",
  		username, hostname);
  #   endif
  #  else
  #    ifdef MMDF
  	if (is_submit_mailer)
! 	  sprintf(from_buf,"%.40s", username);
  	else
  #    endif /* MMDF */
! 	  sprintf(from_buf,"%.40s!%.40s", 
! 		  hostname, username);
  #  endif
  # endif
+ 	fprintf(filedesc,"From: %s <%s>",qfullname,from_buf);
+ #ifdef MIME
+ 	print_EOLN(filedesc,mime_info->encoding_top);
+ #else
+ 	fputc('\n',filedesc);
  #endif
+ #endif
  
  	if (cc[0] != '\0')
  	    fprintf(filedesc, "Cc: %s\n", format_long(long_cc, strlen("Cc: ")));
***************
*** 1177,1185 ****
  	if (strlen(expanded_reply_to) > 0)
  	    fprintf(filedesc, "Reply-To: %s\n", expanded_reply_to);
  
- 	if (strlen(in_reply_to) > 0)
- 	    fprintf(filedesc, "In-Reply-To: %s\n", in_reply_to);
- 
  	if (strlen(user_defined_header) > 0)
  	    fprintf(filedesc, "%s\n", user_defined_header);
  
--- 1809,1814 ----
***************
*** 1189,1226 ****
  	fprintf(filedesc, "X-Mailer: ELM [version %s]\n", version_buff);
  #endif /* !NO_XHEADER */
  
! 	if (form)
  	  fprintf(filedesc, "Content-Type: mailform\n");
- #ifdef MIME
- 	else if (msg_is_multipart) {
- 	  fprintf(filedesc, "%s\n", MIME_HEADER);
- 	  fprintf(filedesc,
- 		"%s multipart/mixed; boundary=%s\n", MIME_CONTENTTYPE, MIME_BOUNDARY);
- 	}
- #endif /* MIME */
  	else {
! #ifdef	MIME
! 	  fprintf(filedesc, "%s\n", MIME_HEADER);
! 	  fprintf(filedesc, "%s text/plain; charset=%s\n",
! 		  MIME_CONTENTTYPE, charset);
! 	  fprintf(filedesc, "Content-Transfer-Encoding: %s\n",
! 		  (!strincmp ("us-ascii", charset)
! 		   && strincmp ("7bit", text_encoding))
! 		  ? "7bit" : text_encoding);
  #else
  	  fprintf(filedesc, "Content-Type: text\n");
  #endif /* MIME */
  	}
  	fprintf(filedesc, "Content-Length: ");
! 	C_L_Position[0] = ftell(filedesc);
! 	fprintf(filedesc, "          \n"); /* Print Blanks as Placeholders */
! 
! 	putc('\n', filedesc);
! 
! 	return((FILE *) filedesc);
  }
  
  copy_message_across(source, dest, copy)
  FILE *source, *dest;
  int copy;
  {
--- 1818,1863 ----
  	fprintf(filedesc, "X-Mailer: ELM [version %s]\n", version_buff);
  #endif /* !NO_XHEADER */
  
! 	if (form) 
  	  fprintf(filedesc, "Content-Type: mailform\n");
  	else {
! #ifdef MIME
! #ifdef USE_REMAILER
! 	  if (!remailing)
! 	    /* Don't write the MIME header if we are remailing.  It will be
! 	     * taken care of by the remailing code.
! 	     */
! #endif
! 	    mime_write_header (filedesc, mime_info, 1);
  #else
  	  fprintf(filedesc, "Content-Type: text\n");
  #endif /* MIME */
  	}
  	fprintf(filedesc, "Content-Length: ");
! 	cl_offset = ftell(filedesc);
! 	fprintf(filedesc, "          "); /* Print Blanks as Placeholders */
! #ifdef MIME
! 	print_EOLN(filedesc,mime_info->encoding_top);
!  	if (copy) {
! 	  fprintf(filedesc, "Status: RO");
! 	  print_EOLN(filedesc,mime_info->encoding_top);
! 	}
! 	print_EOLN(filedesc,mime_info->encoding_top);
! #else
! 	fputc('\n',filedesc);
! 	if (copy) 
! 	  fprintf(filedesc, "Status: RO\n");
! 	fputc('\n',filedesc);
! #endif
! 	return(filedesc);
  }
  
+ #ifdef MIME
+ copy_message_across(source, dest, copy, mime_info)
+ mime_send_t *mime_info;
+ #else
  copy_message_across(source, dest, copy)
+ #endif
  FILE *source, *dest;
  int copy;
  {
***************
*** 1235,1251 ****
  #ifdef MIME
  	int	text_lines = 0;
  	int	at_boundary = FALSE;
- 
- 	C_L_Position[1] = 0L;
- 	C_StartData[1] = 0L;
- 	C_EndData[1] = 0L;
- 
  #endif /* MIME */
  
! 	while (line_len = mail_gets(buffer, SLEN, source)) {
  	  if (buffer[0] == '[') {
! 	    if (strncmp(buffer, START_ENCODE, strlen(START_ENCODE))==0)
  	      crypted = TRUE;
  	    else if (strncmp(buffer, END_ENCODE, strlen(END_ENCODE))==0)
  	      crypted = FALSE;
  	    else if ((strncmp(buffer, DONT_SAVE, strlen(DONT_SAVE)) == 0)
--- 1872,1902 ----
  #ifdef MIME
  	int	text_lines = 0;
  	int	at_boundary = FALSE;
  #endif /* MIME */
  
! 	/* Reserve one byte for conversion LF -> CR LF in
! 	 * case of binary mime transmission:
! 	 */
! 	while (line_len = mail_gets(buffer, SLEN-1, source)) {
  	  if (buffer[0] == '[') {
! 	    if (strncmp(buffer, START_ENCODE, strlen(START_ENCODE))==0) {
! #ifdef MIME
! 	      if (mime_info->msg_is_multipart) {
! 		if (!at_boundary) {
! 		  print_EOLN(dest,mime_info->encoding_top);
! 		  fprintf(dest,"--%s",mime_info->mime_boundary);
! 		  print_EOLN(dest,mime_info->encoding_top);
! 		}
! 		mime_info->type_text    =  MIME_TYPE_APPLICATION;
! 		strcpy(mime_info->subtype_text,"X-ELM-encode");
! 		
! 		mime_write_header (dest, mime_info, 0);
! 		print_EOLN(dest,mime_info->encoding_top);
! 		at_boundary = FALSE;
! 	      }
! #endif
  	      crypted = TRUE;
+ 	    }
  	    else if (strncmp(buffer, END_ENCODE, strlen(END_ENCODE))==0)
  	      crypted = FALSE;
  	    else if ((strncmp(buffer, DONT_SAVE, strlen(DONT_SAVE)) == 0)
***************
*** 1256,1271 ****
  	    } else if (strncmp(buffer, MIME_INCLUDE, strlen(MIME_INCLUDE))==0) {
  	      text_lines = 0;
  	      if (!at_boundary) {
! 		if (C_L_Position[1] != 0L) {
! 		  C_EndData[1] = ftell(dest);
! 		  C_L_Position[1] = fseek(dest, C_L_Position[1], 0);
! 		  fprintf(dest, "%d", C_EndData[1] - C_StartData[1]);
! 		  fseek(dest, C_EndData[1], 0);
! 		}
! 		fprintf(dest, "\n--%s\n", MIME_BOUNDARY);
  	      }
! 	      Include_Part(dest, buffer, FALSE);
! 	      fprintf(dest, "--%s\n", MIME_BOUNDARY);
  	      at_boundary = TRUE;
  	      continue;
  #endif /* MIME */
--- 1907,1920 ----
  	    } else if (strncmp(buffer, MIME_INCLUDE, strlen(MIME_INCLUDE))==0) {
  	      text_lines = 0;
  	      if (!at_boundary) {
! 		print_EOLN(dest,mime_info->encoding_top);
! 		fprintf(dest, "--%s", mime_info->mime_boundary);
! 		print_EOLN(dest,mime_info->encoding_top);
  	      }
! 	      Include_Part(dest, buffer, FALSE, mime_info, copy);
! 	      print_EOLN(dest,mime_info->encoding_top);
! 	      fprintf(dest, "--%s", mime_info->mime_boundary);
! 	      print_EOLN(dest,mime_info->encoding_top);
  	      at_boundary = TRUE;
  	      continue;
  #endif /* MIME */
***************
*** 1276,1282 ****
  	        getkey(ON);
  	      else if (! encoded_lines)
  	        get_key_no_prompt();		/* reinitialize.. */
! 	      if (strncmp(buffer, START_ENCODE, strlen(START_ENCODE))) {
  	        encode(buffer);
  	        encoded_lines++;
  	      }
--- 1925,1931 ----
  	        getkey(ON);
  	      else if (! encoded_lines)
  	        get_key_no_prompt();		/* reinitialize.. */
! 	      if (0 != strncmp(buffer, START_ENCODE, strlen(START_ENCODE))) {
  	        encode(buffer);
  	        encoded_lines++;
  	      }
***************
*** 1291,1297 ****
  	      getkey(ON);
  	    else if (! encoded_lines)
  	      get_key_no_prompt();		/* reinitialize.. */
! 	    if (strncmp(buffer, START_ENCODE, strlen(START_ENCODE))) {
  	      encode(buffer);
  	      encoded_lines++;
  	    }
--- 1940,1946 ----
  	      getkey(ON);
  	    else if (! encoded_lines)
  	      get_key_no_prompt();		/* reinitialize.. */
! 	    if (0 != strncmp(buffer, START_ENCODE, strlen(START_ENCODE))) {
  	      encode(buffer);
  	      encoded_lines++;
  	    }
***************
*** 1298,1318 ****
  #ifdef MIME
  	  } else {
  	    if (text_lines == 0) {
! 	      if (msg_is_multipart) {
  		if (!at_boundary) {
! 	 	  fprintf(dest,"--%s\n",MIME_BOUNDARY);
  		}
! 	        fprintf(dest, "%s text/plain; charset=%s\n",
! 			MIME_CONTENTTYPE, charset);
! 		fprintf(dest, "Content-Transfer-Encoding: %s\n",
! 			(!strincmp ("us-ascii", charset)
! 			 && strincmp ("7bit", text_encoding))
! 			? "7bit" : text_encoding);
! 		fprintf(dest, "Content-Length: ");
! 		C_L_Position[1] = ftell(dest);
! 		fprintf(dest, "          \n"); /* Print Placeholders */
! 	        fprintf(dest, "\n");
! 		C_StartData[1] = ftell(dest);
  		at_boundary = FALSE;
  	      }
  	    }	
--- 1947,1962 ----
  #ifdef MIME
  	  } else {
  	    if (text_lines == 0) {
! 	      char tmp[STRING];
! 	      if (mime_info->msg_is_multipart) {
  		if (!at_boundary) {
! 		  print_EOLN(dest,mime_info->encoding_top);
! 	 	  fprintf(dest,"--%s",mime_info->mime_boundary);
! 		  print_EOLN(dest,mime_info->encoding_top);
  		}
! 
! 		mime_write_header (dest, mime_info, 0);
! 		print_EOLN(dest,mime_info->encoding_top);
  		at_boundary = FALSE;
  	      }
  	    }	
***************
*** 1320,1331 ****
  #endif /* MIME */
            }
  
  #ifndef DONT_ESCAPE_MESSAGES
  	  if (copy && (strncmp(buffer, "From ", 5) == 0)) {
  	    /* Add in the > to a From on our copy */
  	    fprintf(dest, ">");
  	    if (fwrite(buffer, 1, line_len, dest) != line_len) {
! 		MoveCursor(LINES, 0);
  		Raw(OFF);
  		Write_to_screen(catgets(elm_msg_cat, ElmSet, ElmWriteFailedCopyAcross,
  			"\nWrite failed in copy_message_across\n"), 0);
--- 1964,2000 ----
  #endif /* MIME */
            }
  
+ #ifdef MIME
+ 	  if (mime_info->encoding_top == ENCODING_BINARY) {
+ 	    /* It is better perhaps use canonical eol (CRLF) when mail have
+ 	     * content transfer encoding BINARY somewhere (see notes about 
+ 	     * BINARYMIME)
+ 	     */
+ 
+ 	    if (buffer[line_len-1] == '\n') {
+ 	      int add = 1;
+ 	      if (line_len >1 && buffer[line_len-2] == '\r')
+ 		add = 0;
+ 	      if (add) {
+ 		buffer[line_len-1] = '\r';
+ 		buffer[line_len] = '\n';
+ 		line_len++;
+ 	      }	      
+ 	    }
+ 	  }
+ 
+ 	  /* Do QUOTED-PRINTABLE conversion if necessary... */
+ 	  if (mime_info->encoding_text == ENCODING_QUOTED)
+ 	    line_quoted_printable_encode(buffer,dest,copy,line_len,TRUE,
+ 					 mime_info);
+ 	  else
+ #endif
  #ifndef DONT_ESCAPE_MESSAGES
  	  if (copy && (strncmp(buffer, "From ", 5) == 0)) {
  	    /* Add in the > to a From on our copy */
  	    fprintf(dest, ">");
  	    if (fwrite(buffer, 1, line_len, dest) != line_len) {
! 		MoveCursor(elm_LINES, 0);
  		Raw(OFF);
  		Write_to_screen(catgets(elm_msg_cat, ElmSet, ElmWriteFailedCopyAcross,
  			"\nWrite failed in copy_message_across\n"), 0);
***************
*** 1342,1348 ****
    	  else
  #endif /* DONT_ESCAPE_MESSAGES */
    	    if (fwrite(buffer, 1, line_len, dest) != line_len) {
! 		MoveCursor(LINES, 0);
  		Raw(OFF);
  		Write_to_screen(catgets(elm_msg_cat, ElmSet, ElmWriteFailedCopyAcross,
  			"\nWrite failed in copy_message_across\n"), 0);
--- 2011,2017 ----
    	  else
  #endif /* DONT_ESCAPE_MESSAGES */
    	    if (fwrite(buffer, 1, line_len, dest) != line_len) {
! 		MoveCursor(elm_LINES, 0);
  		Raw(OFF);
  		Write_to_screen(catgets(elm_msg_cat, ElmSet, ElmWriteFailedCopyAcross,
  			"\nWrite failed in copy_message_across\n"), 0);
***************
*** 1349,1354 ****
--- 2018,2034 ----
  		emergency_exit();
  	    }
  	} 
+ #ifdef MIME
+ 	if (mime_info->msg_is_multipart) {
+ 	  /* now add any attachments (NEW STYLE) */
+ 	  if (attachments)
+ 	    attach_generate_message (attachments, dest, copy, mime_info);
+ 
+ 	  print_EOLN(dest,mime_info->encoding_top);
+ 	  fprintf(dest,"--%s--", mime_info->mime_boundary);
+ 	  print_EOLN(dest,mime_info->encoding_top);
+ 	}
+ #endif /* MIME */
  #ifdef MMDF
  	if (copy) fputs(MSG_SEPARATOR, dest);
  #else
***************
*** 1368,1379 ****
  	    TRUE iff the user wants to bounce a copy back.... 
  	 **/
  
! 	MoveCursor(LINES,0);
  	CleartoEOLN();
  	MCsprintf(msg, catgets(elm_msg_cat, ElmSet, ElmBounceOffRemote,
  	      "\"Bounce\" a copy off the remote machine? (%c/%c) "),
  	      *def_ans_yes, *def_ans_no);
! 	ch = want_to(msg, *def_ans_no, LINES, 0);
  	return (ch == *def_ans_yes);
  }
  
--- 2048,2059 ----
  	    TRUE iff the user wants to bounce a copy back.... 
  	 **/
  
! 	MoveCursor(elm_LINES,0);
  	CleartoEOLN();
  	MCsprintf(msg, catgets(elm_msg_cat, ElmSet, ElmBounceOffRemote,
  	      "\"Bounce\" a copy off the remote machine? (%c/%c) "),
  	      *def_ans_yes, *def_ans_no);
! 	ch = want_to(msg, *def_ans_no, elm_LINES, 0);
  	return (ch == *def_ans_yes);
  }
  
***************
*** 1450,1452 ****
--- 2130,2144 ----
  
  }
  
+ #ifdef MIME
+ static int check_8bit_str (str)
+      char *str;
+ {
+   char *s;
+ 
+   for (s = str;	*s; s++)
+     if (*s & 0x80)
+       return HAVE_8BIT;
+   return 0;
+ }
+ #endif
Index: WORK/src/menu.c
*** /tmp/null.14101	Tue Aug 20 22:05:34 1996
--- WORK/src/menu.c	Mon Aug  5 19:59:17 1996
***************
*** 0 ****
--- 1,212 ----
+ /* $Id: menu.c,v 1.2 1995/06/23 21:45:10 elkins Exp $
+  *
+  * API for creating menus in Elm.
+  * Initially written by: Michael Elkins <elkins@aero.org>, 17 May 1995.
+  *
+  * PLEASE SEND ME ANY CHANGES YOU MAKE TO THIS API!
+  *
+  * The basic sequence of using this api is as follows:
+  *
+  *  menu_t menu;
+  *
+  *  MenuInit(&menu, "Test Menu", "Please Select an option: ", "q)uit");
+  *  for (...)
+  *    MenuAdd(&menu, "Menu item n");
+  *  for (;;) {
+  *    switch(MenuLoop(&menu)) {
+  *    case '\n':
+  *      selected_item = MenuCurrent(&menu);
+  *      MenuDestroy(&menu);
+  *      return(selected_item);
+  *    }
+  *  }
+  *
+  * $Log: menu.c,v $
+  * Revision 1.2  1995/06/23  21:45:10  elkins
+  * MenuLoop() should always display the prompt.
+  *
+  * Revision 1.1  1995/06/01  23:06:50  elkins
+  * Initial revision
+  *
+  *
+  */
+ 
+ #include "menu.h"
+ #include "headers.h"
+ #include "me.h"
+ 
+ /* creates a new menu instance.  'm' is a pointer to a 'menu_t', 't' is the
+    menu title, 'p' is the prompt string and 'h' is a help string. 'h' may
+    be specified as NULL if no help line is desired.  */
+ void
+ MenuInit (m, t, p, h)
+ menu_t *m;
+ char *t, *p, *h;
+ {
+   m->data = 0;
+   m->max = m->len = m->current = 0;
+   m->update = 1; /* so we can see something on the first MenuLoop() call! */
+   m->title = (char *) safe_malloc(sizeof(char) * (strlen(t) + 1));
+   strcpy(m->title, t);
+   m->prompt = (char *) safe_malloc(sizeof(char) * (strlen(p) + 1));
+   strcpy(m->prompt, p);
+   m->prompt_length = strlen(m->prompt);
+   if (h) {
+     m->help = (char *) safe_malloc(sizeof(char) * (strlen(h) + 1));
+     strcpy(m->help, h);
+   } else
+     m->help = 0;
+   m->pagetop = 0;
+ }
+ 
+ void
+ MenuDestroy (m)
+ menu_t *m;
+ {
+   if (m->title)
+     free(m->title);
+   if (m->prompt)
+     free(m->prompt);
+   DestroyDynamicArray(m->data);
+ }
+ 
+ int
+ MenuAdd (m, s)
+ menu_t *m;
+ char *s;
+ {
+   if (m->len == m->max)
+     m->data = (char **) DynamicArray(m->data, sizeof(char*),
+ 				     &m->max, elm_LINES);
+   if (!m->data)
+     return(-1);
+   m->data[m->len] = (char *) safe_malloc(sizeof(char) * (strlen(s) + 1));
+   strcpy(m->data[m->len], s);
+   ++m->len;
+   return(0);
+ }
+ 
+ int
+ MenuPrintLine (s, voffset, isCurrent) 
+ char *s;
+ int voffset, isCurrent;
+ {
+   char *buf = (char*)safe_malloc(sizeof(char)*(elm_COLUMNS+1));
+ 
+   if (!buf)
+     return(-1);
+ 
+   if (isCurrent && !arrow_cursor)
+     StartInverse();
+   sprintf(buf, "%s %-*.*s", isCurrent && arrow_cursor ? "->" : "  ",
+ 	  elm_COLUMNS-4, elm_COLUMNS-4, s);
+   PutLine0 (voffset, 0, buf);
+   if (isCurrent && !arrow_cursor)
+     EndInverse();
+   free(buf);
+   return(0);
+ }
+ 
+ /* the main loop for a menu.  it takes care of moving the selection and
+    returns the command that the user selected. */
+ int
+ MenuLoop (m)
+ menu_t *m;
+ {
+   int j, key_offset;
+   int cmd;
+ 
+   for (;;) {
+     if (m->update) {
+       ClearScreen();
+       Centerline(1, m->title);
+       for (j = 0; j < elm_LINES-6 && m->pagetop + j < m->len; j++)
+ 	MenuPrintLine(m->data[m->pagetop+j], 3+j, m->pagetop+j == m->current);
+       if (m->help)
+ 	Centerline(elm_LINES-1, m->help);
+       m->update = 0;
+     }
+     PutLine0(elm_LINES-2, 0, m->prompt);
+ 
+     switch(cmd = ReadCh(REDRAW_MARK|READCH_CURSOR)) {
+     case RIGHT_MARK:
+     case PAGEDOWN_MARK:
+       if (m->pagetop + elm_LINES-6 < m->len) {
+ 	m->pagetop += elm_LINES-6;
+ 	m->current = m->pagetop;
+ 	m->update = 1;
+       } else
+ 	Centerline(elm_LINES, "You are already on the last page!");
+       break;
+     case LEFT_MARK:
+     case PAGEUP_MARK:
+       if (m->pagetop != 0) {
+ 	m->pagetop -= elm_LINES-6;
+ 	if (m->pagetop < 0)
+ 	  m->pagetop = 0;
+ 	m->current = m->pagetop;
+ 	m->update = 1;
+       } else
+ 	Centerline(elm_LINES, "You are on the first page!");
+       break;
+     case REDRAW_MARK:
+     case ctrl('L'):
+       m->update = 1;
+       break;
+     case HOME_MARK:
+     case '=': /* first item */
+       m->current = 0;
+       m->pagetop = 0;
+       m->update = 1;
+       break;
+     case '*': /* last item */
+       m->current = m->len - 1;
+       m->pagetop = m->len - elm_LINES + 6;
+       if (m->pagetop < 0)
+ 	m->pagetop = 0;
+       m->update = 1;
+       break;
+     case UP_MARK:
+     case 'k':
+     case 'K':
+     case ctrl('P'):
+ previous_entry:
+       if (m->current > 0) {
+ 	if (m->current != m->pagetop) {
+ 	  MenuPrintLine(m->data[m->current], 3 + m->current - m->pagetop, 0);
+ 	  --m->current;
+ 	  MenuPrintLine(m->data[m->current], 3 + m->current - m->pagetop, 1);
+ 	} else { /* move to the previous page */
+ 	  --m->current;
+ 	  m->pagetop -= elm_LINES-6;
+ 	  if (m->pagetop < 0)
+ 	    m->pagetop = 0;
+ 	  m->update = 1;
+ 	}
+       }
+       break;
+     case DOWN_MARK:
+     case 'j':
+     case 'J':
+     case ctrl('N'):
+     case 'n':
+ next_entry:
+       if (m->current < m->len-1) {
+ 	if (m->current < m->pagetop + elm_LINES-7) {
+ 	  MenuPrintLine(m->data[m->current], 3 + m->current -  m->pagetop, 0);
+ 	  ++m->current;
+ 	  MenuPrintLine(m->data[m->current], 3 + m->current - m->pagetop, 1);
+ 	} else { /* move to the next page */
+ 	  ++m->current;
+ 	  m->pagetop = m->current;
+ 	  m->update = 1;
+ 	}
+       } else
+ 	Centerline(elm_LINES, "You are on the last item!");
+       break;
+     default:
+       return(cmd);
+     }
+   }
+   /* not reached */
+ }
Index: WORK/src/menu2.c
*** /tmp/null.14101	Tue Aug 20 22:05:34 1996
--- WORK/src/menu2.c	Mon Jul 22 21:40:46 1996
***************
*** 0 ****
--- 1,130 ----
+ /* $Id: menu2.c,v 1.1 1995/08/28 02:08:24 elkins Exp $
+  *
+  * This code originally written by Michael Elkins <elkins@aero.org>.
+  *
+  * $Log: menu2.c,v $
+  * Revision 1.1  1995/08/28 02:08:24  elkins
+  * Initial revision
+  *
+  */
+ 
+ #include "headers.h"
+ #include "menu2.h"
+ #include "me.h"
+ 
+ #define BOL 1
+ #define STR 2
+ #define INT 3
+ 
+ int
+ do_item (it)
+      struct menu_item *it;
+ {
+   short len;
+   char buf[STRING];
+   int ch;
+ 
+   ClearLine (elm_LINES-2);
+   Write_to_screen (it->option, 0);
+   len = strlen (it->option) + 1;
+   if (it->type == STR)
+     return 
+       optionally_enter (it->d.c, elm_LINES-2, len, 
+ 			OE_APPEND_CURRENT|OE_REDRAW_MARK);
+   else if (it->type == BOL) {
+     for (;;) {
+       MoveCursor (elm_LINES-2, len);
+       CleartoEOLN ();
+       if (*it->d.i == TRUE)
+ 	Write_to_screen ("TRUE", 0);
+       else if (*it->d.i == FALSE)
+ 	Write_to_screen ("FALSE", 0);
+       ch = ReadCh (OE_REDRAW_MARK);
+       if (ch == EOF) 
+ 	return -1;
+       if (ch == REDRAW_MARK)
+ 	return REDRAW_MARK;
+       if (ch == '\n')
+ 	return 0;
+       else if (ch == ' ')
+ 	*it->d.i = *it->d.i ? FALSE : TRUE;
+     }
+   }
+   else if (it->type == INT) {
+     int code;
+     sprintf (buf, "%d", *it->d.i);
+     code = optionally_enter (buf, elm_LINES-2, len, 
+ 			     OE_APPEND_CURRENT|OE_REDRAW_MARK);
+     if (code != 0)
+       return code;
+     *it->d.i = atoi (buf);
+   }
+   return 0;
+ }
+ 
+ void
+ generic_menu (items, max, title, prompt)
+      struct menu_item items[];
+      short max;
+      char *prompt, *title;
+ {
+   short i = 0;
+   char buf[STRING], buf2[STRING];
+   int ch;
+   short update = TRUE;
+   int precmd = 0;
+ 
+   ClearScreen ();
+   for (;;) {
+     if (update) {
+       Centerline (1, title);
+       for (i = 0 ; i < max ; i++) {
+ 	sprintf (buf, "%-30.30s", items[i].option);
+ 	if (items[i].type == BOL) {
+ 	  if (*items[i].d.i == TRUE)
+ 	    strcat (buf, "TRUE");
+ 	  else
+ 	    strcat (buf, "FALSE");
+ 	}
+ 	else if (items[i].type == STR)
+ 	  strcat (buf, items[i].d.c);
+ 	else if (items[i].type == INT) {
+ 	  sprintf (buf2, "%d", *items[i].d.i);
+ 	  strcat (buf, buf2);
+ 	}
+ 	ClearLine(items[i].offset);
+ 	PutLine0 (items[i].offset, 0, buf);
+       }
+       update = FALSE;
+     }
+     ClearLine (elm_LINES-2);
+     PutLine0 (elm_LINES-2, 0, prompt);
+     if (precmd) {
+       ch = precmd;
+       precmd = 0;
+     } else
+       ch = ReadCh (REDRAW_MARK);
+     if (EOF == ch)
+       return;
+     switch (ch) {
+     case '\n':
+       return;
+     case REDRAW_MARK:
+       update = TRUE;
+       break;
+     default:
+       for (i = 0; i < max ; i++) {
+ 	if (ch == items[i].key) {
+ 	  int code = do_item (&items[i]);
+ 	  if (REDRAW_MARK == code)
+ 	    precmd = ch;
+ 	  if (-1 == code)
+ 	    return;
+ 	  update = TRUE;
+ 	  break;
+ 	}
+       }
+     }
+   }
+   /* Not reached. */
+ }
Index: WORK/src/metapager.c
*** /tmp/null.14101	Tue Aug 20 22:05:34 1996
--- WORK/src/metapager.c	Fri Aug  9 23:02:37 1996
***************
*** 0 ****
--- 1,409 ----
+ #include <errno.h>
+ #include "headers.h"
+ #include "s_elm.h"
+ #include "me.h"
+ 
+ #ifdef MIME
+ extern int errno;
+ #endif /* MIME */
+ 
+ void
+ PressAnyKeyToContinue()
+ {
+   Raw(ON | NO_TITE);
+ redraw:
+   PutLine0(elm_LINES, 0, "Press any key to continue...");
+   if (ReadCh(REDRAW_MARK) == REDRAW_MARK)
+     goto redraw;
+   Raw(OFF | NO_TITE);
+   printf("\n\r");
+ }
+ 
+ metapager (fp, hdr, do_headers)
+      FILE *fp;
+      struct header_rec *hdr;
+      int do_headers;
+ {
+ 
+   int wait_ret, fork_ret, builtin = 0, matched = 0, status, len, line_len;
+   long start_offset = hdr->offset, end_offset;
+   int ch = 0;
+   char buf[VERY_LONG_STRING];
+   FILE *fpout = NULL;
+   copy_decoder_t decoder;
+   int err;				/* place holder for errno */
+   char **text = 0;
+   int text_idx = 0, text_len = 0;
+   char tempfile[STRING];
+   FILE *fpin, *tfpout;
+   int wanna_tempfile = 0;
+ 
+   /* check to see if we want the internal pager */
+   if (strincmp(pager, "builtin", 7) == 0 ||
+       strincmp(pager, "internal", 8) == 0 ||
+       (builtin_lines < 0 
+        ? hdr->lines < elm_LINES + builtin_lines 
+        : hdr->lines < builtin_lines)) {
+ 
+     builtin++;
+ 
+     decoder = select_copy_decoder(hdr);
+ 
+     /* Also [encode] [clear] requires tempfile ... */
+     if (decoder != copy_plain 
+ #ifdef MIME
+ 	&&
+ 	(decoder != copy_mime || mime_needs_processing (&hdr->mime_rec))
+ #endif
+ 	) 
+       wanna_tempfile = 1;
+   } else {
+     /* FOr simplify we use tempfile always with external pager.
+      * That way we don't need take care if pager is taken terminal
+      * before routines called from copy_message want ask decode key
+      * or passhrase from user ...
+      */
+     wanna_tempfile = 1;
+   }
+ 
+   if (wanna_tempfile) {
+     sprintf (tempfile, "%selm.%d", temp_dir, getpid());
+     
+     unlink(tempfile);
+     fpout = safeopen_rdwr(tempfile);
+     unlink(tempfile); /* We can now unlink tempfile ... So nobody
+ 		       * sees data easily (and O_EXCL should prevent
+ 		       * evil playings with symlinks) ...
+ 		       */
+     if (!fpout) {
+       error("Failed to create temporary file!");
+       return 0;
+     }
+     
+     dprint (1, (debugfile, "metapager(): using tempfile %s\n", tempfile));
+   } else {
+     dprint (1, (debugfile, "metapager(): [experimental] look ma!  no tempfile!\n"));
+     builtin++;
+   }
+ 
+ 
+   if (fseek (fp, hdr->offset, 0) == -1) {
+     err = errno;
+     dprint(1, (debugfile,
+ 	       "Error: seek %d bytes into file, errno %s (show_message)\n",
+ 	       hdr->offset, error_description(err)));
+     error2(catgets(elm_msg_cat, ElmSet, ElmSeekFailedFile,
+ 		   "ELM [seek] couldn't read %d bytes into file (%s)."),
+ 	   hdr->offset, error_description(err));	
+     return (0);
+   }
+       
+   /* this is only true if metapager() is not called from ViewAttachment() */
+   if (do_headers) {
+     if (title_messages) {
+       char buf2[STRING], buf3[STRING];
+ #ifdef MIME
+       char buf4[STRING];
+       
+       strfcpy (buf4, hdr->from, sizeof (buf4));
+       if (is_rfc1522 (hdr->from))
+ 	rfc1522_decode (buf4, sizeof (buf4));
+ #endif
+       
+       /* first print a title line */
+       
+       elm_date_str(buf2, hdr->time_sent + hdr->tz_offset);
+       strcat(buf2, " ");
+       strcat(buf2, hdr->time_zone);
+       sprintf(buf, "%s %d/%d ",
+ 	      hdr->status & DELETED ? "[Deleted]" : "Message",
+ 	      current,
+ 	      message_count);
+       len = elm_COLUMNS - 2 - strlen(buf) - strlen(buf2),
+       sprintf(buf3, "%s%-*.*s %s",
+ 	      buf,
+ 	      len,
+ 	      len,
+ #ifdef MIME
+ 	      buf4,
+ #else
+ 	      hdr->from,
+ #endif
+ 	      buf2);
+       
+       if (builtin > 1) {
+ 	if (text_idx == text_len)
+ 	  text = (char **) DynamicArray (text, sizeof (char *), &text_len, 5);
+ 	text[text_idx] = strmcpy (text[text_idx], buf3);
+ 	text_idx++;
+       }
+       else {
+ 	fputs (buf3, fpout);
+ 	fputs ("\n", fpout);
+       }
+       
+       /** Print the subject line centered if there is enough room **/
+       if ((len = strlen(hdr->subject)) > 0 && matches_weedlist("subject:")) {
+         len = (elm_COLUMNS-len)/2;
+         if (len < 0)
+           len = 0;
+         sprintf(buf,"%*.*s%s",len,len,"",hdr->subject);
+         if (builtin > 1)
+           text[text_idx++] = strmcpy(text[text_idx], buf);
+         else
+           fprintf(fpout, "%s\n", buf);
+       }
+       
+       if (builtin > 1) {
+         text[text_idx] = (char *) safe_malloc(1);
+         *text[text_idx++] = '\0';
+       }
+       else
+         fputc('\n', fpout);
+       
+       /* now some information about this message */
+       
+       buf[0]='\0';
+       if (hdr->status & EXPIRED) {
+ 	if (buf[0] == '\0')
+ 	  strcpy(buf, "(** This message has EXPIRED");
+ 	else
+ 	  strcat(buf, ", and has EXPIRED");
+       }
+       if (hdr->status & CONFIDENTIAL) {
+ 	if (buf[0] == '\0')
+ 	  strcpy(buf, "(** This message is tagged CONFIDENTIAL");
+ 	else
+ 	  strcat(buf, ", and is tagged CONFIDENTIAL");
+       }      
+       if (hdr->status & URGENT) {
+ 	if (buf[0] == '\0')
+ 	  strcpy(buf, "(** This message is tagged URGENT");
+ 	else if (hdr->status & CONFIDENTIAL)
+ 	  strcat(buf, ", and URGENT");
+ 	else
+ 	  strcat(buf, ", and is tagged URGENT");
+       }
+       
+       if (buf[0] != '\0') {
+ 	strcat(buf, " **)");
+ 	if (builtin > 1) {
+ 	  text[text_idx] = strmcpy (text[text_idx], buf);
+ 	  text_idx++;
+ 	  text[text_idx] = (char *) safe_malloc (1);
+ 	  *text[text_idx] = '\0';
+ 	  text_idx++;
+ 	}
+ 	else	  {
+ 	  fputs (buf, fpout);
+ 	  fputs ("\n\n", fpout);
+ 	}
+       }
+     }
+ 
+     /** Now do the headers. **/
+ 
+     /* read_header_line with flag = 1 terminates header with \n and marks
+      * folding with \n
+      */
+     while (0 < (line_len = read_header_line (fp, buf, VERY_LONG_STRING,
+ 					     RHL_MARK_FOLDING))) {
+       char *ptr;
+ #ifdef MMDF
+       if (strcmp (buf, MSG_SEPARATOR) == 0)
+         continue;
+ #endif
+       if (elm_filter) {
+ 	if (matches_weedlist (buf)) {
+ 	  matched = 1;
+ 	  continue;
+ 	}
+ 	else
+ 	  matched = 0;
+       }
+       
+       if (buf[0] == '\n') {
+ #ifndef MIME
+ 	start_offset = ftell(fp);
+ #endif
+ 	/* strtok -hack don't print last empty line anyway ... */
+ 
+ 	break;       
+       }
+ #ifdef MIME
+       else {
+ 	ptr = strchr(buf,':');
+ 	if (ptr && !(hdr -> status & NOHDRENCODING)) {
+ 	  char *ptr2 = ptr +1;
+ 	  int class;
+ 	  *ptr = '\0';
+ 
+ 	  class = classify_header(buf);
+ 	  dprint(12,(debugfile,"metapager: header=%s,class=%d,rest=%s\n",
+ 		     buf,class,ptr2));
+ 
+ 	  if (class & HDR_TEXT) {
+ 	    if (is_rfc1522 (ptr2))
+ 	      rfc1522_decode (ptr2, sizeof (buf) - (ptr2 - buf) -1);
+  	  } else if (class & HDR_STRUCTURED) {
+ 	    rfc1522_decode_structured(class,
+ 				      ptr2, sizeof (buf) - (ptr2 - buf) -1);
+ 	  }
+ 
+ 	  dprint(12,(debugfile,"metapager: decoded rest=%s\n",ptr2));
+ 	  *ptr = ':';
+ 	}
+       }
+ #endif
+ 
+       for (ptr = strtok(buf,"\n"); ptr; ptr = strtok(NULL,"\n")) { 
+ 	if (ptr > buf) { /* Do folding */
+ 	  --ptr;
+ 	  if (*(ptr+1) == ' ')
+ 	    *ptr = ' ';
+ 	  else
+ 	    *ptr = '\t';
+ 	}
+ 	if (builtin > 1) {
+ 	  
+ 	  if (text_idx >= text_len - 1)
+ 	    text = (char **) DynamicArray (text, sizeof (char *), &text_len, 5);
+ 	  text[text_idx] = strmcpy (text[text_idx], ptr);
+ 	  text_idx++;
+ 	}
+ 	else {
+ 	  fputs (ptr, fpout);
+ 	  fputc ('\n',fpout);
+ 	}
+       }
+     }
+   }
+ 
+   if (builtin > 1) {    
+     if (text_idx >= text_len - 1)
+       text = (char **) DynamicArray (text, sizeof (char *), &text_len, 5);
+     text[text_idx] = strmcpy (text[text_idx], "");
+     text_idx++;
+   }
+   else {
+     fputc ('\n',fpout);
+   }
+ 
+ #ifdef MIME
+   start_offset = hdr->mime_rec.offset;
+ #endif
+   
+   /* finally the body */
+ 
+   if (builtin > 1) {
+ #ifdef MIME
+     if (hdr->status & MIME_MESSAGE)
+       mime_warnings(hdr);
+ #endif
+ 
+     /* No special processing needs to take place, so just start the pager! */
+     
+ #ifdef MMDF
+     /* Shorten the size of the message such that it does not include the
+      * trailing separator.
+      */
+     ch = builtinplusplus (fp, start_offset, hdr->content_length - 5,
+                           text, text_idx);
+ #else
+     ch = builtinplusplus (fp, start_offset, hdr->content_length, text,
+                           text_idx);
+ #endif
+     DestroyDynamicArray (text);
+     return ch;
+   }
+ 
+   /* Now this does decoding of MIME and PGP */
+   copy_message(fp,hdr,
+ 	       "",fpout,CM_REMOVE_HEADER|CM_DECODE|CM_DISPLAYING);
+   rewind(fpout);
+   clear_error();
+ 
+   /** Now run the pager! **/
+ 
+   if (builtin) {
+     fseek (fpout, (long)0, 2);
+     ch = builtinplusplus (fpout, (long) 0, ftell (fpout), NULL, 0);
+     fclose (fpout);
+     return (ch);
+   }
+ 
+ 
+   /** The rest of the code is for an external pager. **/
+   Raw(OFF); /* Raw(OFF) must do in parent.... 
+ 	     * Or otherwise in Raw(ON) does not
+ 	     * have effect (because Raw (ON /OFF) 
+ 	     * does nothing if it thinks that mode is
+ 	     * already correct)
+ 	     */
+   
+   if ((fork_ret = fork()) == -1) {
+     err = errno;
+     dprint(1, (debugfile, "Error: fork failed, errno %s (metapager)\n",
+ 	       error_description(err)));
+     error1(catgets(elm_msg_cat, ElmSet, ElmPreparePagerFork,
+ 		   "Could not prepare for external pager(fork()-%s)."),
+ 	   error_description(err));	
+     PressAnyKeyToContinue();
+     Raw (ON);
+     return (0);
+   } else if (fork_ret == 0) {
+     /* child fork */
+     
+     /* Direct our temporary file to standard input of child.
+      * Because we immediately unlinked it (for security reasons) 
+      * after creating we don't have name for it and
+      * we can't use < in system_call
+      */
+ 
+     if (dup2 (fileno(fpout),0) == -1) {
+       err = errno;
+       dprint(1, (debugfile, "Error: dup failed, errno %s (metapager)\n",
+ 		 error_description(err)));	
+       error1(catgets(elm_msg_cat, ElmSet, ElmPreparePagerDup,
+ 		     "Could not prepare for external pager(dup()-%s)."),
+ 	     error_description(err));	
+       _exit(err);	
+     }
+ 
+     clear_error();
+     ClearScreen();
+     
+     /* now execute pager and exit */
+     
+     /* system_call() will return user to user's normal permissions. */
+     _exit(system_call(pager, SY_ENAB_SIGINT));
+   }
+ 
+   fclose (fpout);
+ 
+   while ((wait_ret = wait (&status)) != fork_ret && wait_ret != -1
+ 	 /* Handle possible signals ... */	 
+ 	 || wait_ret == -1 && errno == EINTR)
+     ;
+   /* turn raw on **after** child terminates in case child
+    * doesn't put us back to cooked mode after we return ourselves to
+    * raw.
+    */
+   Raw(ON | NO_TITE);
+ 
+   if (prompt_after_pager) {
+     StartBold ();
+     PutLine0 (elm_LINES, 0, catgets(elm_msg_cat, ElmSet, ElmCommandIToReturn,
+ 				    " Command ('i' to return to index): "));
+     EndBold ();
+     fflush (stdout);
+     ch = ReadCh('i' | READCH_CURSOR);
+   }
+   else
+     ch = 0;
+ 
+   Raw(OFF | NO_TITE);
+   Raw(ON);
+ 
+   return (ch == 'i' || ch == 'q' ? 0 : ch);
+ }
Index: WORK/src/mime.c
*** elm2.4.25/src/mime.c	Mon Aug 23 05:55:06 1993
--- WORK/src/mime.c	Sat Aug 10 11:34:44 1996
***************
*** 125,132 ****
  #include <errno.h>
  #include <sys/stat.h>
  
! int check_for_multipart(filedesc)
! FILE *filedesc;
  {
    char buffer[SLEN];
    int Multi_Part = FALSE;
--- 125,146 ----
  #include <errno.h>
  #include <sys/stat.h>
  
! /* Notice that ENCODING_ILLEGAL is -1 
!  */
! 
! char *mime_encode_names[] = {
!   "none", /* Not used. */
!   "7bit",
!   "8bit",
!   "binary",
!   "quoted-printable",
!   "base64",
!   "X-???"         /* ENCODING_EXPERIMENTAL */
! };
! 
! int check_for_multipart(filedesc, mime_info)
!      FILE *filedesc;
!      mime_send_t *mime_info;
  {
    char buffer[SLEN];
    int Multi_Part = FALSE;
***************
*** 139,145 ****
      if (buffer[0] == '[') {
        if (strncmp(buffer, MIME_INCLUDE, strlen(MIME_INCLUDE)) == 0) {
        	Multi_Part = TRUE;
! 	if (Include_Part((FILE *)NULL, buffer, TRUE) == -1) {
  	   return(-1);
  	}
        }
--- 153,159 ----
      if (buffer[0] == '[') {
        if (strncmp(buffer, MIME_INCLUDE, strlen(MIME_INCLUDE)) == 0) {
        	Multi_Part = TRUE;
! 	if (Include_Part((FILE *)NULL, buffer, TRUE, mime_info, FALSE) == -1) {
  	   return(-1);
  	}
        }
***************
*** 148,157 ****
    return(Multi_Part);
  }
  
! Include_Part(dest, buffer, check)
! FILE *dest;
! char *buffer;
! int	check;
  {
    char *ptr;
    char *incptr;
--- 162,174 ----
    return(Multi_Part);
  }
  
! int
! Include_Part(dest, buffer, check, mime_info, copy)
!      FILE *dest;
!      char *buffer;
!      int  check;
!      mime_send_t *mime_info;
!      int copy;
  {
    char *ptr;
    char *incptr;
***************
*** 159,192 ****
    char Expanded_Filename[SLEN];
    char tmp_fn[SLEN];
    char *filename;
!   char Content_Type[SLEN];
    char Encoding[SLEN];
    char sh_buffer[SLEN];
    char Encode_Flag[3];
    int  Enc_Type;
    FILE *incfile;
-   struct stat	file_status;
    int  line_len;
  
    ptr = buffer + strlen(MIME_INCLUDE);
    while ((*ptr != '\0') && (*ptr == ' '))
      ptr++;
    incptr = Include_Filename;
!   while ((*ptr != ' ') && (*ptr != ']') && (*ptr != '\0'))
      *incptr++ = *ptr++;
    *incptr = '\0';
  
    while ((*ptr != '\0') && (*ptr == ' '))
      ptr++;
!   incptr = Content_Type;
!   while ((*ptr != ' ') && (*ptr != ']') && (*ptr != '\0'))
      *incptr++ = *ptr++;
    *incptr = '\0';
  
    while ((*ptr != '\0') && (*ptr == ' '))
      ptr++;
    incptr = Encoding;
!   while ((*ptr != ' ') && (*ptr != ']') && (*ptr != '\0'))
      *incptr++ = *ptr++;
    *incptr = '\0';
  
--- 176,248 ----
    char Expanded_Filename[SLEN];
    char tmp_fn[SLEN];
    char *filename;
!   char Primary_Type[SLEN];
!   char SubType[SLEN];
!   char Params[STRING];
    char Encoding[SLEN];
    char sh_buffer[SLEN];
    char Encode_Flag[3];
    int  Enc_Type;
    FILE *incfile;
    int  line_len;
+   int is_text;
  
    ptr = buffer + strlen(MIME_INCLUDE);
    while ((*ptr != '\0') && (*ptr == ' '))
      ptr++;
    incptr = Include_Filename;
!   while ((*ptr != ' ') && (*ptr != ']') && (*ptr != '\0') &&
! 	 (incptr < Include_Filename + sizeof(Include_Filename) -1))
      *incptr++ = *ptr++;
    *incptr = '\0';
  
    while ((*ptr != '\0') && (*ptr == ' '))
      ptr++;
!   incptr = Primary_Type;
!   while ((*ptr != ' ') && (*ptr != ']') && (*ptr != '\0') && (*ptr!='/')
! 	 && (*ptr != ';') 
! 	 && (incptr < Primary_Type + sizeof(Primary_Type) -1))
      *incptr++ = *ptr++;
    *incptr = '\0';
+   while ((*ptr != '\0') && (*ptr == ' '))
+     ptr++;
+   incptr = SubType;
+   if (*ptr == '/') {
+     ptr++;
+     while ((*ptr != '\0') && (*ptr == ' '))
+       ptr++;
+     while ((*ptr != ' ') && (*ptr != ']') && (*ptr != '\0') && (*ptr!=';')
+ 	   && (incptr < SubType + sizeof(SubType) -1))
+       *incptr++ = *ptr++;
+   }
+   *incptr = '\0';
+   while ((*ptr != '\0') && (*ptr == ' '))
+     ptr++;
+   incptr = Params;
+   while (*ptr == ';') {
+     ptr++;
+     if (incptr > Params) {
+       *incptr++ = ';';
+     } else if (*ptr == ' ')
+       ptr++;
+ 
+     while ((*ptr != '\0') && (*ptr == ' ')
+ 	   && (incptr < Params + sizeof(Params) -1))
+       *incptr++ = *ptr++;
+ 
+     while ((*ptr != ' ') && (*ptr != ']') && (*ptr != '\0') && (*ptr!=';')
+ 	   && (incptr < Params + sizeof(Params) -1))
+       *incptr++ = *ptr++;
+     while ((*ptr != '\0') && (*ptr == ' '))
+       ptr++;
+   }
+   *incptr = '\0';
  
    while ((*ptr != '\0') && (*ptr == ' '))
      ptr++;
    incptr = Encoding;
!   while ((*ptr != ' ') && (*ptr != ']') && (*ptr != '\0')
! 	 && (incptr < Encoding + sizeof(Encoding) -1))
      *incptr++ = *ptr++;
    *incptr = '\0';
  
***************
*** 199,205 ****
    }
    (void) expand_env(Expanded_Filename, Include_Filename, sizeof(Expanded_Filename));
  
!   if (strlen(Content_Type) == 0) {
      Write_to_screen(catgets(elm_msg_cat, ElmSet, ElmNoContentTypeGiven,
                      "\n\rNo Content-type given, include line ignored\n\r"), 0);
      if (sleepmsg > 0)
--- 255,261 ----
    }
    (void) expand_env(Expanded_Filename, Include_Filename, sizeof(Expanded_Filename));
  
!   if (strlen(Primary_Type) == 0 || strlen(SubType) == 0 ) {
      Write_to_screen(catgets(elm_msg_cat, ElmSet, ElmNoContentTypeGiven,
                      "\n\rNo Content-type given, include line ignored\n\r"), 0);
      if (sleepmsg > 0)
***************
*** 224,290 ****
  		sleep(sleepmsg);
  	return(-1);
    }
!   if (check) {
! 	return(0);
    }
!   if (Enc_Type == ENCODING_7BIT || Enc_Type == ENCODING_8BIT ||
! 	Enc_Type == ENCODING_BINARY || Enc_Type == ENCODING_NONE ||
! 	Enc_Type == ENCODING_EXPERIMENTAL) {
!     /* No explicit encoding, assume 7-BIT */
!     filename = Expanded_Filename;
!   } else {
!     sprintf(tmp_fn, "%semm.%d.%d", temp_dir, getpid(), getuid());
!     filename = tmp_fn;
!     if (Enc_Type == ENCODING_BASE64) {
!       strcpy(Encode_Flag, "-b");
!     } else if (Enc_Type == ENCODING_QUOTED) {
!       strcpy(Encode_Flag, "-q");
!     } else {
!       Write_to_screen(catgets(elm_msg_cat, ElmSet, ElmUnknownEncodingInInclude,
! 		      "\n\rUnknown Encoding, include line ignored\n\r"), 0);
        if (sleepmsg > 0)
! 	    sleep(sleepmsg);
!       return(-1);
      }
!     sprintf(sh_buffer, "mmencode %s %s >%s", Encode_Flag, Expanded_Filename,
! 			tmp_fn);
!     (void) system_call(sh_buffer, 0);
!   }
!   if ((incfile = fopen(filename, "r")) != NULL) {
!     if (stat(filename, &file_status) != 0) {
!         Write_to_screen(catgets(elm_msg_cat, ElmSet, ElmCantStatIncludedFile,
! 			"\n\rCan't stat included File,ignored\n\r"), 0);
! 	if (sleepmsg > 0)
! 		sleep(sleepmsg);
! 	return(-1);
      }
!     fprintf(dest, "%s %s\n", MIME_CONTENTTYPE, Content_Type);
!     fprintf(dest, "Content-Name: %s\n", Include_Filename);
!     fprintf(dest, "Content-Length: %d\n", file_status.st_size);
!     if (Enc_Type != ENCODING_NONE) {
! 	fprintf(dest, "Content-Transfer-Encoding: %s\n", Encoding);
      }
-     fprintf(dest, "\n");
-     while (line_len = fread(buffer, 1, sizeof(buffer), incfile)) {
-       if (fwrite(buffer, 1, line_len, dest) != line_len) {
- 	MoveCursor(LINES, 0);
- 	Raw(OFF);
-         Write_to_screen(catgets(elm_msg_cat, ElmSet, ElmWriteFailedCopyAcross,
- 	        "\nWrite failed in copy_message_across\n"), 0);
-         emergency_exit();
-       }
-     } 
  
! /*  write CRLF after body-part */
  
!     fprintf(dest, "\n");
  
      fclose(incfile);
!     if (filename == tmp_fn) {
! 	unlink(tmp_fn);
!     }
!   } else {
!     MoveCursor(LINES, 0);
      Raw(OFF);
      Write_to_screen(catgets(elm_msg_cat, ElmSet, ElmCantOpenIncludedFile,
  		    "\nCan't open included File\n"), 0);
--- 280,431 ----
  		sleep(sleepmsg);
  	return(-1);
    }
! 
!   /* Don't allow 7BIT if 8-bit charcters in any type,    
!    * don't allow 8BIT if 'binary' characters       - K E H */
!   if (Enc_Type == ENCODING_7BIT || Enc_Type == ENCODING_NONE
!       || Enc_Type == ENCODING_8BIT) {
!     
!     FILE * fp = fopen (Expanded_Filename, "r");
!     if (fp) {
!       int tmp = needs_encoding (fp);
!       if (tmp & HAVE_BINARY) {
! 
! 	error ("Include file has BINARY data.");
! 	
!         if (sleepmsg > 0)
! 	  sleep(sleepmsg);
! 	
! 	if (Enc_Type == ENCODING_7BIT || Enc_Type == ENCODING_8BIT) {
! 	  if (check)
! 	    return -1; /* indicate failure */
! 	}
! 	
! 	Enc_Type = ENCODING_BINARY;
! 
!       } else if ((tmp & HAVE_8BIT) && Enc_Type != ENCODING_8BIT) {
! 	
! 	error ("Include file has 8BIT data.");
! 	
!         if (sleepmsg > 0)
! 	  sleep(sleepmsg);
! 	
! 	if (Enc_Type == ENCODING_7BIT) {
! 	  if (check)
! 	    return -1; /* indicate failure */
! 	}
! 	
! 	Enc_Type = ENCODING_8BIT;
! 	
!       }
!       fclose(fp);
!     }
    }
! 
!   if (Enc_Type == ENCODING_8BIT) {
! #ifndef USE_8BITMIME
!     if (allow_no_encoding < 1) {
!       Enc_Type = ENCODING_QUOTED;
!       error ("Mailer (MTA) doesn't support 8BIT encoding.");
        if (sleepmsg > 0)
! 	sleep(sleepmsg);
!       
!       if (check)
! 	return -1; /* indicate failure */
      }
! #endif
!   }
! 
!   if (Enc_Type == ENCODING_BINARY) {
! #ifndef USE_BINARYMIME
!     if (allow_no_encoding < 2) {
!       /* Convert to QUOTED-PRINTABLE */
!       Enc_Type = ENCODING_QUOTED;
!       error ("Mailer (MTA) doesn't support BINARY encoding!");
!       if (sleepmsg > 0)
! 	sleep (sleepmsg);
!       if (check)
! 	return (-1);
      }
! #endif
!   }
! 
!   is_text = is_text_type(Primary_Type, SubType, Enc_Type);
!   /* 1 if is text type (true)
!    * 0 if not text type
!    * -1 if can't be encoded (ie structured) Message/ or Multipart/ 
!    */
!     
!   if (is_text < 0 && (Enc_Type == ENCODING_QUOTED ||
! 		      Enc_Type == ENCODING_BASE64)) {
!       error ("Content-Type don't allow encoding -- ignoring this part.");
!       if (sleepmsg > 0)
! 	sleep (sleepmsg);
!       return (-1);
!   }
! 
! 
!   (void) update_encoding(&(mime_info->encoding_top),Enc_Type);
! 
!   if (check) {
! 	return(0);
!   }
! 
!   incfile = fopen (Expanded_Filename, "r");
!   if (incfile) {
! 
!     dprint (10, (debugfile, 
! 		 "Include_Part: '%s' C-T=%s/%s Params=%s Enc=%d is_text=%d\n",
! 		 Expanded_Filename,Primary_Type,SubType, Params, Enc_Type,
! 		 is_text));
! 
!     fprintf(dest, "%s %s/%s", MIME_CONTENTTYPE, Primary_Type, SubType);
!     if (Params[0] == '\0') 
!       print_EOLN(dest,mime_info->encoding_top);
!     else { 
!       if (strlen(Primary_Type) + strlen(SubType) + strlen(Params) > 60) {
! 	fprintf(dest,";");
! 	print_EOLN(dest,mime_info->encoding_top);
! 	fputc('\t',dest);
!       } else
! 	fprintf(dest,"; ");
!       fprintf(dest,"%s",Params);
!       print_EOLN(dest,mime_info->encoding_top);
      }
  
!     {
!       char buf[STRING];
!       buf [0] = 0;
! 
!       add_parameter(buf,"filename",Include_Filename,sizeof(buf),0);
!       
!       /* When user uses [include ...] it is better use disposition
!        * 'inline' instead of 'attachment'
!        */
!       fprintf(dest,"Content-Disposition: inline; %s",buf);
!       print_EOLN(dest,mime_info->encoding_top);
!     }
  
!     if (Enc_Type != ENCODING_NONE) {
!       if (Enc_Type < ENCODING_EXPERIMENTAL) 
! 	fprintf(dest, "%s %s", MIME_CONTENTENCOD, 
! 		ENCODING(Enc_Type));
!       else /* For ENCODING_EXPERIMENTAL */
! 	fprintf(dest, "%s %s", MIME_CONTENTENCOD, Encoding);
!       print_EOLN(dest,mime_info->encoding_top);
!     }
!     print_EOLN(dest,mime_info->encoding_top);
  
+     /* encoding rules are different for text and no text 
+      * for text we must do \n -> \r\n before base64 encoding */
+     
+     /* For ENCODING_EXPERIMENTAL this is already supposed to be encoded */
+     (void)write_encoded(incfile,dest,Enc_Type,copy,is_text,mime_info);
+     
      fclose(incfile);
!   }
!   else {
!     MoveCursor(elm_LINES, 0);
      Raw(OFF);
      Write_to_screen(catgets(elm_msg_cat, ElmSet, ElmCantOpenIncludedFile,
  		    "\nCan't open included File\n"), 0);
***************
*** 311,377 ****
  	return(ENCODING_ILLEGAL);
  }
  
- needs_mmdecode(s)
- char *s;
- {
- 	char buf[SLEN];
- 	char *t;
- 	int EncType;
- 
- 	if (!s) return(1);
- 	while (*s && isspace(*s)) ++s;
- 	t = buf;
- 	while (*s && !isspace(*s) && ((t-buf) < (SLEN-1))) *t++ = *s++;
- 	*t = '\0';
- 	EncType = check_encoding(buf);
- 	if ((EncType == ENCODING_NONE) ||
- 	    (EncType == ENCODING_7BIT) ||
- 	    (EncType == ENCODING_8BIT) ||
- 	    (EncType == ENCODING_BINARY)) {
- 	    /* We don't need to go out to mmdecode, return 0 */
- 	    return(0);
- 	} else {
- 	    return(1);
- 	}
- }
- 
- notplain(s)
- char *s;
- {
- 	char *t;
- 	if (!s) return(1);
- 	while (*s && isspace(*s)) ++s;
- 	if (istrcmp(s, "text\n") == 0) {
- 		/* old MIME spec, subtype now obligat, accept it as
- 		   "text/plain; charset=us-ascii" for compatibility
- 		   reason */
- 		return(0);
- 	}
- 	if (strincmp(s, "text/plain", 10)) return(1);
- 	t = (char *) index(s, ';');
- 	while (t) {
- 		++t;
- 		while (*t && isspace(*t)) ++t;
- 		if (!strincmp(t, "charset", 7)) {
- 			s = (char *) index(t, '=');
- 			if (s) {
- 				++s;
- 				while (*s && (isspace(*s) || *s == '\"')) ++s;
- 				if (!strincmp(s, display_charset, strlen(display_charset)))
- 					return(0);
- 				if (!strincmp(s, "us-ascii", 8)) {
- 					/* check if configured charset could
- 					   display us-ascii */
- 					if(charset_ok(display_charset)) return(0);
- 				}
- 			}
- 			return(1);
- 		}
- 		t = (char *) index(t, ';');
- 	}
- 	return(0); /* no charset, was text/plain */
- }
- 
  int charset_ok(s)
  char *s;
  {
--- 452,457 ----
***************
*** 394,397 ****
--- 474,561 ----
      }
      return(TRUE);
  }
+ 
+ /* Determine whether or not the data in "fp" needs to be QUOTED-PRINTABLE
+     encoded.  Used when sending a message.
+        1 == have 8bit data                (HAVE_8BIT)
+        4 == have control charcters        (HAVE_CTRL)
+        8 == mime requires encoding BINARY (HAVE_BINARY)
+ */
+ 
+ int
+ needs_encoding (fp)
+ FILE *fp;
+ {
+   int ch;
+   int ret = FALSE;
+   int len = 0;
+ 
+   rewind (fp);
+   while ((ch = fgetc (fp)) != EOF) {
+     /* check for end of line */
+     if (ch == 13) {   /* CR */
+       ch = fgetc(fp);
+       if (ch != 10) {  /* Not CR LF */
+ 	dprint (3, (debugfile, "\nneeds_encoding(): found CR without LF\n"));
+ 	ret |= HAVE_BINARY;
+       }
+       if (ch == EOF)
+ 	break;
+     }
+     if (ch == 10) {
+       len = 0;
+       continue; /* skip newlines and tabs */
+     }
+     len++;
+     if (len > 990) {
+       dprint (3, (debugfile,"\nneeds_encoding(): Line over 990 characters\n"));
+ 	ret |= HAVE_BINARY;
+     }
+ 
+     if (ch == 9) /* skip newlines and tabs */
+       continue;
+     if (ch < 32 || ch > 126) {
+       dprint (3, (debugfile, "\nneeds_encoding(): found char decimal=%d\n", ch));
+       if (ch == 0) 
+ 	ret |= HAVE_BINARY;
+       if (ch < 32 || ch == 127)
+ 	ret |= HAVE_CTRL;
+       if (ch > 127)
+ 	ret |= HAVE_8BIT;
+     }
+     if (ret == (HAVE_8BIT | HAVE_CTRL | HAVE_BINARY))
+       break;
+ 
+   }
+   rewind (fp);
+   return (ret);
+ }
+ 
+ char *error_description();
+ 
+ int
+ have_metamail()
+ {
+   int return_value = 1;
+   
+   if (strcmp(metamail_path,"none") == 0 || 
+       metamail_path[0] == '\0') {
+     return_value = 0;
+   } else if (metamail_path[0] == '/') {
+     if (-1 == access(metamail_path,EXECUTE_ACCESS)) {
+       int err = errno;
+       error2("Can't execute metamail: %s: %s",metamail_path,
+ 	     error_description(err));
+       dprint(5,(debugfile,"have_metamail: no access %s: %s\n",metamail_path,
+ 		error_description(err)));
+       if (sleepmsg > 0)
+ 	sleep(sleepmsg);
+       return_value = 0;
+     }
+   }
+ 
+   dprint(5,(debugfile,"have_metamail=%d\n",return_value));
+   return return_value;
+ }
+ 
  #endif /* MIME */
Index: WORK/src/mime_decode.c
*** /tmp/null.14101	Tue Aug 20 22:05:34 1996
--- WORK/src/mime_decode.c	Sat Aug 10 19:43:51 1996
***************
*** 0 ****
--- 1,1472 ----
+ #include "headers.h"
+ #include "me.h"
+ 
+ #ifdef MIME
+ 
+ static int index_hex[128] = {
+     -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
+     -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
+     -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
+      0, 1, 2, 3,  4, 5, 6, 7,  8, 9,-1,-1, -1,-1,-1,-1,
+     -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1,
+     -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
+     -1,10,11,12, 13,14,15,-1, -1,-1,-1,-1, -1,-1,-1,-1,
+     -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1
+ };
+ 
+ static int index_64[128] = {
+     -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
+     -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
+     -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,
+     52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1,-1,-1,-1,
+     -1, 0, 1, 2,  3, 4, 5, 6,  7, 8, 9,10, 11,12,13,14,
+     15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1,
+     -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
+     41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1
+ };
+ 
+ #define base64(c) ((((c) > 0) && ((c) < 127)) ? index_64[ (c) ] : -1)
+ #define hex(c) ((((c) > 0) && ((c) < 127)) ? index_hex[ (c) ] : -1)
+ 
+ /* Prototype */
+ static void Xbit_decode	P_((in_state_t *, out_state_t *, int, int)); 
+ 
+ static void Xbit_decode (s_in, s_out, len, is_text)
+      in_state_t *s_in;
+      out_state_t *s_out;
+      int len;
+      int is_text;
+ {
+   char buf[VERY_LONG_STRING];
+   int offset = 0, length;
+ 
+   if (s_out->prefix) {
+     strcpy (buf, s_out->prefix);
+     offset = strlen (buf);
+   }
+   while (len > 0) {
+     if (0 ==
+ 	(length = state_getl (buf + offset, VERY_LONG_STRING - offset, s_in)))
+       break;
+     len -= length;
+ 
+     /* Take care of CRLF => LF conversion */
+     if (is_text > 0 &&
+ 	length > 1 &&
+ 	buf[offset + length - 1] == '\n' &&
+         buf[offset + length - 2] == '\r') {
+       buf[offset + length - 2] = '\n';
+       buf[offset + length - 1] = '\0';
+       length--;
+     }
+ 
+     state_put(buf,offset+length,s_out);
+   }
+ }
+ 
+ PUBLIC void base64_decode (s_in, s_out, length, astext)
+      in_state_t  *s_in;
+      out_state_t *s_out;
+      int length;
+      int astext;
+ {
+   /* Notes:  this routine assumes that strlen(line length) % 4 == 0.
+      Most intelligent software will do this, so I haven't worried
+      about being *completely* compliant with the standard.  I've
+      not run into any encoded data where this was not true.  */
+   
+   char buf[STRING], *p;
+   int
+     bytes = 0, /* the total number of bytes read so far */
+     terminate = FALSE,
+     c1, c2, c3, c4;
+   unsigned char
+     ch,
+     store_ch = 0; /* for astext */
+   int corrupted = FALSE;
+ 
+   dprint(10,(debugfile,
+            "base64_decode: length=%d, prefix=%s, astext=%d\n",
+            length,
+            s_out->prefix ? s_out->prefix : "<NULL>",
+            astext));
+ 
+   /* Make sure to quote the first line! */
+   state_add_prefix(s_out);
+ 
+   while (! terminate) {
+     int len;
+ 
+     if (bytes >= length)
+       break;
+ 
+     if ((len = state_getl (buf, VERY_LONG_STRING, s_in)) <= 0)
+ 	break;
+ 
+     bytes += len;
+ 
+     p = buf;
+     while (*p) {
+       c1 = *p++;
+ 
+       if (base64(c1) == -1) {
+         p--;
+         /* partial fix -- K E H   <hurtta@dionysos.FMi.FI>  */
+ 
+         while (*p == ' ' || *p == '\t' || *p == '\r')
+           p++;
+ 
+         if (*p != '\n')
+           corrupted = TRUE;  /* Perhaps corrupted */
+ 
+         if (*p == 0)
+           break;
+ 
+         c1 = *p++;
+       }
+ 
+       /* End of the line. */
+       if (c1 == '\n')
+ 	continue;
+ 
+       c2 = *p++;
+       
+       c1 = base64(c1);
+       if (c1 == -1)
+         corrupted = TRUE;
+       c2 = base64(c2);
+       if (c2 == -1)
+         corrupted = TRUE;
+       ch = (c1 << 2) | (c2 >> 4);
+       
+       if (store_ch && ch != '\n') /* for astext */
+ 	state_putc(store_ch,s_out);
+ 
+       store_ch = 0;
+       if (astext && ch == '\r')
+         store_ch = ch;
+       else {
+ 	state_putc(ch,s_out);
+ 	if (ch == '\n')
+ 	  state_add_prefix(s_out);
+       }      
+     
+       c3 = *p++;
+       if (c3 == '=') {
+ 	terminate = TRUE;
+ 	break;
+       }
+       c3 = base64(c3);
+       if (c3 == -1)
+ 	corrupted = TRUE;
+       ch = ((c2 & 0xf) << 4) | (c3 >> 2);
+ 
+       if (store_ch && ch != '\n')
+ 	state_putc(store_ch,s_out);
+ 
+       store_ch = 0;
+ 
+       if (astext && ch == '\r')
+ 	store_ch = ch;
+       else {
+ 	state_putc(ch,s_out);
+ 	if (ch == '\n')
+ 	  state_add_prefix(s_out);
+       }
+   
+       c4 = *p++;
+       if (c4 == '=') {
+ 	terminate = TRUE;
+ 	break;
+       }
+       
+       c4 = base64(c4);
+       if (c4 == -1)
+ 	corrupted = TRUE;
+       ch = ((c3 & 0x3) << 6) | c4;
+       
+       if (store_ch && ch != '\n')
+ 	state_putc(store_ch,s_out);
+ 
+       store_ch = 0;
+ 
+       if (astext && ch == '\r') {
+ 	store_ch = ch;
+       }
+       else {
+ 	state_putc(ch,s_out);
+ 	if (ch=='\n')
+ 	  state_add_prefix(s_out);
+       }
+     }
+   }
+ 
+   /* Make sure to flush anything left in the internal buffer. */
+   if (store_ch)  /* for astext */
+     state_putc(store_ch,s_out);
+ 
+   if (corrupted) {
+     if (s_out->displaying)
+       state_puts("\n[BASE64 data was corrupt!]\n",s_out);
+     error ("BASE64 data was corrupt!");
+     sleep_message();
+   }
+ 
+   dprint(10,(debugfile,"base64_decode: readed=%d bytes, corrupted=%d.\n",
+ 	     bytes,corrupted));   
+ 
+   return;
+ }
+   
+ PUBLIC void quoted_printable_decode (s_in, s_out, length, astext)
+      in_state_t  *s_in;
+      out_state_t *s_out;
+      int length;
+      int astext;
+ {
+   int bytes = 0; /* number of bytes read */
+   int nl = TRUE; /* flag to indicate hitting a new line */
+   char *p;
+   int c1, c2;
+   unsigned char ch, store_ch = 0;
+   char buf[VERY_LONG_STRING];
+   int corrupted = 0;
+ 
+   dprint(10,(debugfile,
+ 	     "quoted_printable_decode: length=%d, prefix=%s, astext=%d\n",
+ 	     length,
+ 	     s_out->prefix ? s_out->prefix : "<NULL>",
+ 	     astext));
+ 
+   for (;;) {
+     int len;
+ 
+     if (bytes >= length)
+       break;
+ 
+     if ((len=state_getl (buf, VERY_LONG_STRING, s_in)) <= 0)
+       break;
+     bytes += len;
+ 
+     p = buf;
+     while (*p) {
+ 
+       /* If there is a prefix and this is the beginning of a new line... */
+       if (nl) {
+ 	state_add_prefix(s_out);
+ 	nl = FALSE;
+       }
+ 
+       if (store_ch)
+ 	state_putc(store_ch,s_out);
+       
+       if (*p == '=') {
+ 	p++;
+ 	/* Ignore spaces in end of line   -- see MIME */
+ 	if (*p == '\r' || *p == ' ' || *p == '\t') {
+ 	  char *t = p;
+ 	  while (*t && (*t == '\r' || *t == ' ' || *t == '\t'))
+ 	    t++;
+ 	  if (*t && *t == '\n')
+ 	    p = t;
+ 	}
+ 
+ 	if (*p == '\n') { /* soft linebreak */
+ 	  if (length <= 0)
+ 	    break;
+ 	  p++;
+ 	}
+ 	else {
+ 	  c1 = hex(*p);
+ 	  if (c1 == -1)
+ 	    corrupted = TRUE;
+ 	  p++;
+ 	  c2 = hex(*p);
+ 	  if (c2 == -1)
+ 	    corrupted = TRUE;
+ 	  p++;
+ 	  ch = (c1 << 4) | c2;
+ 
+ 	  /* We not need here CR LF -> LF removing, because
+ 	   * CRLF's which presents end of line should NOT be encoded.
+ 	   *                             - K E H <hurtta@dionysos.FMI.FI> */
+ 
+ 	  state_putc(ch,s_out);
+ 	}
+       }
+       else {
+        if (astext && *p == '\r')
+          store_ch = *p;
+        else
+ 	 state_putc(*p,s_out);
+ 	 
+        if (*p == '\n') {
+ 	 nl = TRUE;
+ 	 if (length <= 0)
+ 	   break;
+        }
+ 
+        p++;
+       }  
+     }
+   }
+ 
+   /* Flush anything left in the buffer */
+   if (store_ch) /* for astext */
+     state_putc(store_ch,s_out);
+ 
+   if (corrupted) {
+     if (s_out -> displaying)
+       state_puts("\n[Seems that QUOTED-PRINTABLE data was corrupted.]\n",
+ 		 s_out);
+     error ("Seems that QUOTED-PRINTABLE data was corrupted.");
+     sleep_message();
+   }
+   
+   dprint(10,(debugfile,
+ 	     "quoted_printable_decode: readed=%d bytes, corrupted=%d.\n",
+ 	     bytes,corrupted));
+ 
+   return;
+ }
+ 
+ /* Prototype */
+ static void multipart_decode  P_((mime_t *, 
+ 				  in_state_t *, out_state_t *)); 
+ 
+ static void multipart_decode (att, state_in, state_out)
+      mime_t *att; /* The list of attachments for this MULTIPART data */
+      in_state_t   *state_in;
+      out_state_t  *state_out;
+ {
+   int nattach = 0;
+   char buf[VERY_LONG_STRING];
+ 
+   dprint(12,(debugfile,
+ 	     "multipart_decode -> START\n"));
+ 
+   if (state_in->magic != STATE_in_file) {
+     state_puts("[multipart_decode: unsupported input state]\n",state_out);
+     error("multipart_decode: unsupported input state");
+     sleep_message();
+     return;
+   }
+ 
+   while (att) {
+     nattach++;
+ 
+     dprint(12,(debugfile,
+ 	       "multipart_decode: [%d]: Type: %.15s/%.30s, Encoding: %d, Size: %d\n",
+ 	       nattach, 
+ 	       mime_types[att->type], att->subtype,
+ 	       att->encoding, att->length));
+ 
+     if (in_state_fseek(state_in,att->offset) != 0) {
+       state_puts("[multipart_decode: seek failed]\n",state_out);
+       error("multipart_decode: seek failed");
+       sleep_message();
+       return;
+     }
+ 
+     if (state_out->displaying) {
+       char *Encoding = "???";
+        
+       Encoding = ENCODING(att->encoding);
+       
+       /* First print out a nice display line about this attachment */
+       sprintf (buf,
+ 	       "%s[Attach #%d: \"%.60s\"]\n[Type: %.15s/%.30s, Encoding: %s, Size: %d]\n",
+                nattach > 1 ? "\n" : "",
+ 	       nattach, NONULL(att->description),
+ 	       mime_types[att->type], att->subtype,
+ 	       Encoding, att->length);
+     }
+     else {
+       buf[0] = '\0';
+       if (nattach > 1)
+         strcpy (buf, "\n");
+       if (att->description && (strlen(att->description) < sizeof(buf) -30)) {
+ 	strcat (buf, "Content-Description: ");
+ 	strcat (buf, att->description);
+ 	strcat (buf, "\n\n");
+       }
+     }
+       
+     state_puts(buf,state_out);
+     if (state_out->displaying)
+       state_putc('\n', state_out);
+     mime_decode (att, state_in, state_out);
+     att = att->next;
+   }
+   dprint(12,(debugfile,
+ 	     "multipart_decode <- END\n"));
+ }
+ 
+ /* Prototype */
+ static void multipart_0_decode P_((mime_t *, 
+ 				   in_state_t *, out_state_t *)); 
+ 
+ static void multipart_0_decode (ptr, state_in, state_out)
+      mime_t *ptr;
+      in_state_t *state_in;
+      out_state_t *state_out;
+ {
+   if (ptr->parts)
+     multipart_decode (ptr->parts, state_in, state_out);
+   else {
+     state_puts ("[Content-Type: multipart/*, no subtypes (parts = NULL)]\n", 
+ 		state_out);
+     error("Content-Type: multipart/*, no subtypes (parts = NULL)");
+     sleep_message();
+   }
+ }
+ 
+ /* Prototype */
+ static void rfc822_decode P_((mime_t *, 
+ 			      in_state_t *, out_state_t *)); 
+ 
+ static int rfc822_header_filter     P_((header_list_ptr, int));
+ static void rfc822_header_converter P_((header_list_ptr, int, char *, int));
+ 
+ static int rfc822_header_filter(hdr,flag)
+      header_list_ptr hdr;
+      int flag;                  /* elm_filter */
+ {
+   char buf[80];
+ 
+   strfcpy(buf,hdr->header_name->header,78);
+   strcat(buf,": ");
+   
+   if (flag) {
+     if (matches_weedlist (buf)) 
+       return 0;
+     else
+       return 1;
+   } else
+     return 1;
+ }
+ 
+ static void rfc822_header_converter (hdr,flag,buffer,size)
+      header_list_ptr hdr;
+      int flag;
+      char *buffer;
+      int size;
+ {
+   int class = hdr->header_name->flag;
+ 
+   if (!hdr->body) {
+     buffer[0] = '\0';
+     return;
+   }
+ 
+   dprint(12,(debugfile,"rfc822_header_converter: header=%s,class=%d,rest=%s",
+ 	     hdr->header_name->header,class,hdr->body));
+ 
+   flag++;      /* So that flag is used */
+ 
+   strfcpy(buffer,hdr->body,size);
+ 
+   if (class & HDR_TEXT) {
+     if (is_rfc1522 (buffer))
+       rfc1522_decode (buffer, size);
+   } else if (class & HDR_STRUCTURED) {
+     rfc1522_decode_structured(class,buffer,size);
+   }
+ 
+   dprint(12,(debugfile,"rfc822_header_converter: decoded rest=%s",buffer));
+ 
+ }
+ 
+ static void rfc822_decode (mt, state_in, state_out)
+      mime_t *mt;
+      in_state_t *state_in;
+      out_state_t *state_out;
+ {
+   /* This looks a lot like multipart_decode() except that we want to print
+    * the headers for the message.  NOTE: "mt" should be a pointer to the
+    * RFC822 attachment, NOT its subpart, since we need the offset in order
+    * to print out the headers.
+    */
+ 
+   header_list_ptr headers = NULL;
+   header_list_ptr From_header, mime_version, osv;
+   int decode_headers = 1;
+   
+   if (state_in->magic != STATE_in_file) {
+     state_puts("[rfc822_decode: unsupported input state]\n",state_out);
+     error("rfc822_decode: unsupported input state");
+     sleep_message();
+     return;
+   }
+ 
+   if (in_state_fseek(state_in,mt->offset) != 0) {
+     state_puts("[rfc822_decode: seek failed]\n",state_out);
+     error("rfc822_decode: seek failed");
+     sleep_message();
+     return;
+   }
+ 
+   headers = state_read_headers(state_in, RHL_MARK_FOLDING);
+ 
+   mime_version = locate_header_by_name(headers,"MIME-Version");
+   osv          = locate_header_by_name(headers,"X-ELM-OSV");
+ 
+   if (!mime_version && !req_mime_hdrencoding && !req_mime_hdrencoding)
+     decode_headers = 0;
+   if (osv && osv->body) {
+     char value[20];
+     if (mime_get_param("no-hdr-encoding",value,osv->body,
+ 		       sizeof value) && atoi(value) > 0)
+       decode_headers = 0;
+   }
+ 
+   From_header  = locate_header_by_name(headers,"From");
+ 
+   if (From_header) {
+     char buffer[1024+1],buffer2[1024+50];
+     strfcpy(buffer,From_header->body,sizeof buffer);
+     if (decode_headers && is_rfc1522 (buffer))
+       rfc1522_decode_structured (From_header->header_name->flag,
+ 				 buffer, sizeof buffer);
+     sprintf(buffer2,"-- Start of included mail From: %s\n",buffer);
+     state_puts(buffer2,state_out);
+   }
+   else
+     state_puts("-- Start of included mail.\n",state_out);
+ 
+   state_write_headers(state_out,headers,
+ 		      rfc822_header_filter,
+ 		      decode_headers ? rfc822_header_converter :
+ 		      NULL_header_converter,
+ 		      elm_filter);
+ 
+   delete_headers(headers); headers = NULL;
+ 
+   state_putc('\n',state_out);
+ 
+   if (mt->parts == NULL) {
+     state_puts("[rfc822_decode: no body of RFC 822 mail (parts = NULL)]\n",
+ 	       state_out);
+     error("rfc822_decode: no body of RFC 822 mail (parts = NULL)");
+     sleep_message();
+     return;
+   }
+ 
+   mime_decode (mt->parts, state_in, state_out);
+   state_puts("-- End of included mail.\n",state_out);
+   return;
+ }
+ 
+ static int ASCII_filter(c,st)
+      char c;
+      struct out_state * st;
+ {
+   int res = (unsigned char) c;
+   st++;
+ 
+   if (res & 128)
+     res = '_';
+   return res;
+ }
+ 
+ /* Prototype */
+ static int run_decoder P_((mime_t *, in_state_t *, out_state_t *)); 
+ 
+ static int run_decoder (ptr, state_in, state_out) 
+      mime_t *ptr;
+      in_state_t *state_in;
+      out_state_t *state_out;
+ {
+   int is_text;
+   dprint(12,(debugfile,
+ 	     "run_decoder -> state: offset=%d, length=%d\n",
+ 	     ptr -> offset, ptr -> length));
+   if (state_in->magic == STATE_in_file) {
+     dprint(12,(debugfile,
+ 	       "              (file): ftell=%ld\n",in_state_ftell(state_in))); 
+   } else {
+     dprint(12,(debugfile,
+ 	       "              (\?\?\?\?): magic=%d\n",state_in->magic));
+   }
+ 
+   is_text = is_text_type (mime_types[ptr->type], ptr->subtype, 
+ 			  ptr->encoding);
+ 
+   dprint(12,(debugfile,
+ 	     "run_decoder: is_text=%d; type=%s (%d)/%s; encoding =%s (%d)\n",
+ 	     is_text, mime_types[ptr->type], ptr->type, ptr->subtype,
+ 	     ENCODING(ptr->encoding),
+ 	     ptr->encoding));
+ 
+ 
+   if (ptr->encoding == ENCODING_BASE64)
+     base64_decode (state_in, state_out, ptr->length, is_text);
+   else if (ptr->encoding == ENCODING_QUOTED)
+     quoted_printable_decode (state_in, state_out, ptr->length, is_text);
+   else if (ptr->encoding != ENCODING_NONE && 
+ 	   ptr->encoding != ENCODING_7BIT &&
+ 	   ptr->encoding != ENCODING_8BIT &&
+ 	   ptr->encoding != ENCODING_BINARY) {
+ 
+     dprint(12,(debugfile,
+ 	       "run_decoder=0 <- END; \n"));
+     if (state_in->magic == STATE_in_file) {
+       dprint(12,(debugfile,
+ 		 "              (file); ftell=%ld\n",
+ 		 in_state_ftell(state_in))); 
+     }
+     return 0;
+   }
+   else
+     Xbit_decode (state_in, state_out, ptr->length, is_text);
+ 
+   dprint(12,(debugfile,
+ 	     "run_decoder=1 <- END; \n"));
+   if (state_in->magic == STATE_in_file) {
+     dprint(12,(debugfile,
+ 	       "              (file); ftell=%ld\n",
+ 	       in_state_ftell(state_in))); 
+   }
+   
+   return 1;
+ }
+ 
+ PUBLIC int set_filter (ptr, state) 
+      mime_t *ptr;
+      out_state_t *state;
+ {
+   char tmp[SLEN];
+   char buf[STRING];
+   int code;
+ 
+   dprint(12,(debugfile,
+ 	     "set_filter -> state: offset=%d, length=%d\n",
+ 	     ptr -> offset, ptr -> length));
+ 
+   state -> filter = NULL_filter;
+ 
+   dprint(12,(debugfile,
+ 	     "set_filter: filter=%p (NULL_filter)\n",
+ 	     (void *)(state -> filter)));
+ 
+   if (0 == (code = mime_get_charset (tmp, ptr->type_opts, sizeof(tmp)))) {
+     
+     /* Don't show this part (or copy to reply buffer) ... */
+ 	  
+     sprintf (buf, "[Charset %.15s unsupported, skipping...]\n", tmp);
+     state_puts(buf,state);
+     if (state->displaying)
+       state_puts(   "[Use 'v' to view or save this part.]\n",state);
+ 
+     dprint(12,(debugfile,
+ 	       "set_filter=0 <- END\n"));
+     return 0;
+   } else {
+     if (code < 0) {
+       sprintf (buf, "[Charset %.15s unsupported, filtering to ASCII...]\n",
+ 	       tmp);
+       state_puts(buf,state);
+       if (state->displaying)	
+ 	state_puts(   "[You can also use 'v' to view or save this part.]\n\n",
+ 		   state);
+       
+       state -> filter = ASCII_filter;
+ 
+       dprint(12,(debugfile,
+ 		 "set_filter: filter=%p (ASCII_filter)\n",
+ 		 (void *)(state -> filter)));
+     }
+     dprint(12,(debugfile,
+ 	       "set_filter=1 <- END\n"));
+     return 1;
+   }
+ }
+ 
+ /* Prototype */
+ static void text_decode	P_((mime_t *, in_state_t *, out_state_t *)); 
+ 
+ static void text_decode (ptr, state_in, state_out) 
+      mime_t *ptr;
+      in_state_t *state_in;
+      out_state_t *state_out;
+ {
+   dprint(12,(debugfile,
+ 	     "text_decode -> state: offset=%d, length=%d \n",
+ 	     ptr -> offset, ptr -> length));
+   if (state_in->magic == STATE_in_file) {
+     dprint(12,(debugfile,
+ 	       "              (file): ftell=%ld\n",
+ 	       in_state_ftell(state_in))); 
+   }
+ 
+   if (set_filter(ptr,state_out)) {
+     if (!run_decoder(ptr,state_in, state_out)) {
+       state_puts("[Unsupported encoding, skipping...]\n",state_out);
+       if (state_out->displaying)	
+ 	state_puts("[Use 'v' to save this part in encoded form.]\n",state_out);
+     }
+   }
+ 
+   state_out -> filter = NULL_filter;
+ 
+   dprint(12,(debugfile,
+ 	     "text_decode <- END; \n"));
+   if (state_in->magic == STATE_in_file) {
+     dprint(12,(debugfile,
+ 	       "          (file); ftell=%ld\n",
+ 	       in_state_ftell(state_in))); 
+   }
+ }
+ 
+ PUBLIC FILE * arrange_decoded(ptr,state_in,state_out,newstate2)
+      mime_t *ptr;
+      in_state_t  *state_in;
+      out_state_t *state_out;
+      in_state_t *newstate2;
+ {
+   FILE * tmpfp = NULL;
+   int result = 1,len;
+   char fname[STRING];
+   out_state_t newstate;
+ 
+   out_state_clear(&newstate,STATE_out_file);
+   
+   dprint(12,(debugfile,
+ 	     "arrange_decoded -> state: offset=%d, length=%d \n",
+ 	     ptr -> offset, ptr -> length));
+   if (state_in->magic == STATE_in_file) {
+     dprint(12,(debugfile,
+ 	       "                 (file): ftell=%ld\n",
+ 	       in_state_ftell(state_in))); 
+   }
+   
+   sprintf (fname, "%selmdecode.%d", temp_dir, getpid ());
+   if (NULL == (tmpfp = safeopen_rdwr(fname))) {
+     error("Failed to create file for decoding.");
+     state_puts("[Failed to create file for decoding.]\n",state_out);
+     sleep_message();
+     result = 0;
+   } else { /* Tempfile opened */
+     int crypted = OFF;
+     int bytes = 0;
+     unlink(fname);  /* We can unlink it now ... */
+     
+     newstate.displaying = state_out->displaying;
+     
+     set_out_state_file(tmpfp, &newstate);
+     newstate.prefix     = NULL;             /* No prefix in that pass */
+     newstate.filter     = state_out->filter;
+     
+     if (run_decoder(ptr,state_in,&newstate)) { 
+       int len;
+       
+       if (EOF == fflush(tmpfp)) {
+ 	error("Error when flushing temporary file.");
+ 	state_puts("[Error when flushing temporary file.]\n",state_out);
+ 	sleep_message();
+ 	result = 0;
+       }
+       rewind(tmpfp); /* Rewind it for reading */
+       
+       set_in_state_file(tmpfp,newstate2);
+     } else { /* Run decoder failed */
+       state_puts("[Unsupported content-transfer-encoding, skipping...]\n",
+ 		 state_out);
+       if (state_out->displaying)	
+ 	state_puts("[Use 'v' to save this part in encoded form.]\n",
+ 		   state_out);
+       result = 0;
+     }
+   }
+   out_state_destroy(&newstate);
+ 
+   dprint(12,(debugfile,"arrange_decoded; result=%d\n",result));
+   
+   if (!result && tmpfp) {
+     fclose(tmpfp);
+     tmpfp = NULL;
+   }
+   return tmpfp;
+ }
+ 
+ /* Prototype */
+ static void elm_decode	P_((mime_t *, in_state_t *, out_state_t *)); 
+ 
+ static void elm_decode (ptr, state_in, state_out) 
+      mime_t *ptr;
+      in_state_t  *state_in;
+      out_state_t *state_out;
+ {  
+   in_state_t newstate2;
+ 
+   FILE *tmpfp;
+   char buffer[LONG_STRING];
+   
+   in_state_clear(&newstate2,STATE_in_file);
+   
+   dprint(12,(debugfile,
+ 	     "elm_decode -> state: offset=%d, length=%d; \n",
+ 	     ptr -> offset, ptr -> length));
+   if (state_in->magic == STATE_in_file) {
+     dprint(12,(debugfile,
+ 	       "             (file): ftell=%ld\n",
+ 	       in_state_ftell(state_in))); 
+   }
+ 
+   if (tmpfp = arrange_decoded(ptr,state_in,state_out,&newstate2)) {
+     if (set_filter(ptr,state_out)) {
+       int len, crypted = 0;
+       int count = 0;
+       getkey(OFF);
+       
+       while((len = state_getl(buffer,sizeof(buffer),&newstate2)) > 0) {
+ 	count += len;
+ 	  
+ 	if (!strncmp(buffer, START_ENCODE, strlen(START_ENCODE))) {
+ 	  state_puts("-- Start of (Elm) encoded section.\n",state_out);
+ 	  crypted = ON;
+ 	  continue;
+ 	} else if (!strncmp(buffer, END_ENCODE, strlen(END_ENCODE))) {
+ 	  crypted = OFF;
+ 	  state_puts("-- End of (Elm) encoded section.\n",state_out);
+ 	  continue;
+ 	} else if (crypted) {
+ 	  no_ret(buffer);
+ 	  encode(buffer);      
+ 	  strcat(buffer, "\n");
+ 	}
+ 	state_add_prefix(state_out);
+ 	state_puts(buffer,state_out);
+       }
+ 
+       dprint(12,(debugfile,
+ 		 "elm_decode: Readed %d bytes from temp file\n",count));
+     }
+     fclose(tmpfp);
+   }
+ 
+   dprint(12,(debugfile,
+ 	     "elm_decode <- END; \n"));
+   if (state_in->magic == STATE_in_file) {
+     dprint(12,(debugfile,
+ 	       "           (file); ftell=%ld\n",
+ 	       in_state_ftell(state_in))); 
+   }
+ 
+   in_state_destroy(&newstate2);
+ }
+  /* Prototype */
+ static void text_unsupported_decode P_((mime_t *, 
+ 					in_state_t *, out_state_t *));
+ 
+ static void text_unsupported_decode (ptr, state_in, state_out) 
+      mime_t *ptr;
+      in_state_t *state_in;
+      out_state_t *state_out;
+ {
+   char buf[STRING];
+ 
+   dprint(12,(debugfile,
+ 	     "text_unsupported_decode -> state: offset=%d, length=%d; \n",
+ 	     ptr -> offset, ptr -> length));
+   if (state_in->magic == STATE_in_file) {
+     dprint(12,(debugfile,
+ 	       "                          (file): ftell=%ld\n",
+ 	       in_state_ftell(state_in))); 
+   }
+ 
+ 
+   sprintf (buf, "[%s/%.30s is unsupported, treating like TEXT/PLAIN]\n\n", 
+ 	   TYPE(ptr->type), ptr->subtype);
+   state_puts (buf,state_out);
+   text_decode (ptr, state_in, state_out);
+ 
+   dprint(12,(debugfile,
+ 	     "text_unsupported_decode <- END; \n"));
+   if (state_in->magic == STATE_in_file) {
+     dprint(12,(debugfile,
+ 	       "                        (file); ftell=%ld\n",
+ 	       in_state_ftell(state_in))); 
+   }
+ }
+ 
+ PUBLIC void null_decode (ptr, state_in, state_out) 
+      mime_t *ptr;
+      in_state_t *state_in;
+      out_state_t *state_out;
+ {
+   char buf[STRING];
+ 
+ 
+   dprint(12,(debugfile,
+ 	     "null_decode <-> state: offset=%d, length=%d; \n",
+ 	     ptr -> offset, ptr -> length));
+   if (state_in->magic == STATE_in_file) {
+     dprint(12,(debugfile,
+ 	       "               (file): ftell=%ld\n",
+ 	       in_state_ftell(state_in))); 
+   }
+ 
+   sprintf (buf, "[%.15s/%.30s is not supported, skipping...]\n",
+ 	   TYPE(ptr->type),ptr->subtype);
+   state_puts (buf,state_out);
+   if (state_out->displaying)
+     state_puts(   "[Use 'v' to view or save this part.]\n",state_out);
+ }
+ 
+ PUBLIC CT_decoder_t select_CT_decoder (ptr) 
+      mime_t *ptr;
+ {
+   if (ptr->type == MIME_TYPE_MULTIPART) {
+     dprint(12,(debugfile,
+ 	       "select_CT_decoder = multipart_0_decode\n"));
+     return multipart_0_decode;
+   }
+   else if (ptr->flags & MIME_RFC822) {
+     dprint(12,(debugfile,
+ 	       "select_CT_decoder = rfc822_decode\n"));
+     return rfc822_decode;
+   }
+   else if (ptr->type == MIME_TYPE_MESSAGE &&
+ 	   (0 == istrcmp(ptr->subtype, "delivery-status") ||
+ 	    0 == strincmp(ptr->subtype,"X-delivery-status-",18))) {
+     dprint(12,(debugfile,
+ 	       "select_CT_decoder = text_decode\n"));
+     return text_decode;
+   }
+   else if (ptr->type == MIME_TYPE_TEXT) {
+     if (0 == istrcmp(ptr->subtype, "rfc822-headers") ||
+ 	0 == istrcmp(ptr->subtype, "plain")) {
+       dprint(12,(debugfile,
+ 		 "select_CT_decoder = text_decode\n"));
+       return text_decode;
+     }
+ #ifdef USE_PGP
+     if (0 == istrcmp(ptr->subtype, "x-pgp")) {
+       dprint(12,(debugfile,
+ 		 "select_CT_decoder = pgp_decode\n"));
+       return pgp_decode;
+     }
+ #endif
+     dprint(12,(debugfile,
+ 	       "select_CT_decoder = text_unsupported_decode\n"));
+     return text_unsupported_decode; /* For that type we try use
+ 				       metamail if available! */
+   }
+ #ifdef USE_PGP
+   else if (ptr->type == MIME_TYPE_APPLICATION &&
+ 	   (istrcmp(ptr->subtype, "pgp") == 0)) {
+     dprint(12,(debugfile,
+ 	       "select_CT_decoder = pgp_decode\n"));
+     return pgp_decode;
+   }
+   else if (ptr->type == MIME_TYPE_APPLICATION &&
+ 	   (strincmp(ptr->subtype,"x-pgp",5) == 0)) {
+     dprint(12,(debugfile,
+ 	       "select_CT_decoder = pgp_decode\n"));
+     return pgp_decode;
+   }
+ #endif
+   else if (ptr->type == MIME_TYPE_APPLICATION &&
+ 	   (istrcmp(ptr->subtype, "X-ELM-encode") == 0)) {
+     dprint(12,(debugfile,
+ 	       "select_CT_decoder = elm_decode\n"));
+     return elm_decode;
+   }
+   
+   dprint(12,(debugfile,
+ 	     "select_CT_decoder = null_decode\n"));
+   return null_decode;
+ }
+ 
+ 
+ PUBLIC void mime_decode (ptr, state_in, state_out)
+      mime_t *ptr;
+      in_state_t *state_in;
+      out_state_t *state_out;
+ {
+   /* This routine calls the appropriate routine to decode the data
+    * described in "ptr".
+    */
+ 
+   dprint(12,(debugfile,"mime_decode -> state: offset=%d, length=%d\n",
+ 	     ptr -> offset, ptr -> length));
+ 
+   if (state_in->magic != STATE_in_file) {
+     error("mime_decode: unsupported state");
+     state_puts("\n[mime_decode: unsupported state]\n", state_out);
+     sleep_message();
+     return;
+   }
+ 
+   if (ptr->disposition == DISP_INLINE) {
+     CT_decoder_t decoder = select_CT_decoder(ptr);
+ 
+     dprint(12,(debugfile,"mime_decode: decoder=%p\n",decoder));
+ 
+     if (in_state_fseek(state_in,ptr->offset) != 0) {
+       state_puts("[mime_decode: seek failed]\n",state_out);
+       error("mime_decode: seek failed");
+       sleep_message();
+       return;
+     }
+ 
+     decoder (ptr, state_in, state_out);    
+   }
+   else { 
+     if (state_out->displaying)      
+       state_puts("[Attachment, skipping...  Use 'v' to view this part.]\n",
+ 		 state_out);
+     else
+       state_puts("[Attachment, skipping...]\n",state_out);
+   }
+ 
+   dprint(12,(debugfile,"mime_decode <- END\n"));
+ }
+ 
+ static int rfc1522_decode_word (ptr, state)
+      char *ptr;
+      out_state_t *state;
+ {
+   char *charset = NULL;
+   char *encoded = NULL;
+   char *buffer = NULL;
+   char *c;
+   int encoding = ENCODING_ILLEGAL;
+   int count;
+   int result = -1; /* Default to ERROR */
+  
+   count = 0;
+ 
+   /* Make a copy so the original is not destroyed */
+   c = buffer = strmcpy (buffer, ptr+2);
+ 
+   while ((c = strtok (c, "?")) != NULL) {
+     if (count == 0)
+       /* get the charset */
+       charset = c;
+     else if (count == 1) {
+       /* Check the encoding */
+       if (toupper (*c) == 'Q')
+ 	encoding = ENCODING_QUOTED;
+       else if (toupper (*c) == 'B')
+ 	encoding = ENCODING_BASE64;
+     }
+     else if (count == 2) 
+       encoded = c;
+     count++;
+     c = NULL;
+   }
+ 
+   if (charset && encoding != ENCODING_ILLEGAL && encoded) {
+     int code = class_charset(charset);
+     result = 0; /* OK */
+ 
+     dprint (14, (debugfile, 
+ 		"rfc1522_decode_word: OK: ptr=%s, code=%d\n",ptr,code));
+ 
+     if (code != 0) {
+       in_state_t state_in;
+ 
+       in_state_clear (&state_in, STATE_in_string);
+ 
+       state->filter = NULL_filter;
+ 
+       if (code < 0) {
+ 	dprint (14,(debugfile, 
+ 		   "rfc1522_decode_word: unsupported charset: %s -- filtering\n",
+ 		   charset));
+ 	state->filter = ASCII_filter;
+ 	state_puts("[",state);
+       }
+ 
+ 
+       if (encoding == ENCODING_QUOTED) { /* Hack */
+ 	char * ptr;
+ 	for (ptr = encoded; *ptr != '\0'; ptr++)
+ 	  if (*ptr == '_')
+ 	    *ptr = ' ';
+       }
+ 
+       set_in_state_buffer (encoded, &state_in);
+       
+       if (encoding == ENCODING_QUOTED)
+ 	quoted_printable_decode (&state_in, state, strlen (encoded), TRUE);
+       else if (encoding == ENCODING_BASE64)
+ 	base64_decode (&state_in,state, strlen (encoded), TRUE);
+       if (code < 0) 
+ 	state_puts("]",state);
+ 
+       state->filter = NULL_filter;
+ 
+       in_state_destroy(&state_in);
+     } else {
+       dprint (14, (debugfile, 
+ 		  "rfc1522_decode_word: unsupported charset: %s -- skipping\n",
+ 		  charset));
+       state_puts("[?",state);
+       state_puts(charset,state);
+       state_puts("?]",state); 
+     }
+   }
+ 
+   if (result == -1) {
+     
+     dprint (14, (debugfile, 
+ 		"rfc1522_decode_word: FAILED: ptr=%s\n",ptr));
+     dprint (14, (debugfile, 
+ 		"rfc1522_decode_word: -> charset=%s, encoding=%d, encoded=%s\n",
+ 		NONULL(charset),encoding,NONULL(encoded)));
+     
+   }
+   
+   free (buffer);
+   buffer = NULL;
+ 
+   return result;
+ }
+ 
+ static int rfc1522_decode_real (p, state)
+      char *p;
+      out_state_t *state;
+ {
+   /* This routine decodes RFC1522 compliant headers */
+ 
+   char *buffer = strmcpy(NULL,p);
+   char *ptr = buffer;
+   unsigned char last_char = 0;
+   int result = 0;
+ 
+   while (ptr && *ptr) {
+     char *ptr2 = strpbrk(ptr," \t\r\n");
+     unsigned char last_char2 = 0;
+     int len;
+     int is_encoded = 0;
+ 
+     if (ptr2) {
+       last_char2 = *ptr2;
+       len = ptr2 - ptr;
+       *ptr2 = '\0';
+     } else {
+       len = strlen(ptr);
+     }
+ 
+     /* Check if current word is valid encoded word */
+     if (len > 9 && ptr[0] == '=' && ptr[1] == '?' &&
+ 	ptr[len-1] == '=' && ptr[len-2] == '?') {
+       char *ptr4;
+       int count = 0;
+       for (ptr4 = ptr; ptr4 - ptr < len; ptr4++)
+ 	if (*ptr4 == '?')
+ 	  count++;
+       if (4 == count)
+ 	is_encoded = 1;
+     }
+ 
+     dprint (14, (debugfile, 
+ 		"rfc1522_decode_real: word = %s, len=%d, is_encoded=%d\n",
+ 		ptr,len,is_encoded));
+ 
+     /* Space between encoded chars must delete! --
+      * This allows splitting more than 75 character long
+      * encoded words to two encoded word and using of
+      * continuation lines!
+      */
+     if (!is_encoded && last_char) {
+       state_putc (last_char, state);
+     }
+ 
+     if (is_encoded) {
+       if (-1 == rfc1522_decode_word(ptr,state)) {
+ 	dprint (14, (debugfile, 
+ 		    "rfc1522_decode_real: Error in rfc1522_decode_word ...\n"));
+ 	result = -1;
+ 	break;
+       }
+ 	
+     } else {
+       state_put(ptr,len,state);
+     }
+ 
+     if (!is_encoded && last_char2) {
+       state_putc (last_char2, state);
+       last_char2 = 0;
+     }
+ 
+     ptr = ptr2; /* Next word if any */
+     if (ptr)
+       ptr++;
+     last_char = last_char2;
+   }
+ 
+   free(buffer);
+   return 0;
+ }
+ 
+ PUBLIC int is_rfc1522 (s)
+      char *s;
+ {
+   /* Returns TRUE if the string contains RFC 1522 format encoded data */
+ 
+   while ((s = strchr (s, '=')) != NULL) {
+     s++;
+     if (*s == '?')
+       return TRUE;
+   }
+   return FALSE;
+ }
+ 
+ PUBLIC void rfc1522_decode (ptr, len)
+      char *ptr;
+      int len; /* size of "ptr" */
+ {
+   /* Support for RFC 1522, which allows for encoding of non-ASCII characters
+    * in RFC 822 headers.
+    */
+   char *tmp = safe_malloc (len);
+   out_state_t state;
+ 
+   /* Make a working copy of the header */
+   strfcpy (tmp, ptr, len);
+ 
+   /* The output from the decoding should be put back into the memory area
+    * which was passed into this routine.
+    */
+   out_state_clear (&state, STATE_out_string);
+   set_out_state_buffer(ptr,len,&state);
+   
+   if (rfc1522_decode_real (tmp, &state) == -1) {
+     /* An error occured.  Restore the original value. */    
+     
+     strfcpy (ptr, tmp, len);
+   }
+ 
+   out_state_destroy (&state);  
+ 
+   free (tmp);
+ }
+ 
+ PUBLIC void rfc1522_decode_structured (class, ptr, len)
+      int class;
+      char *ptr;
+      int len; /* size of "ptr" */
+ {
+   /* Decodes comments from structured fields 
+    * if class & HDR_PHRASE decodes also prases (or all words outside of < >)
+    *   -- not exactly correct for address lines, but otherwise we need full
+    *      STD 11 (RFC 822) parser ....
+    */
+   char *walk, *walk2;
+   char *result = safe_malloc(len);
+   int tlen;
+   int space = 0; /* Seen space or character after what there can begin
+ 		    phrase (in address line) -- this alcorithm can result
+ 		    incorrect output if addresses are not canonical for
+ 		    -- for example 'some @ some . domain' */
+ 
+   dprint (14, (debugfile, 
+ 	      "rfc1522_decode_structured -> class=%d,len=%d,ptr=%s\n",
+ 	      class,len,ptr));
+ 
+   for (walk = ptr, walk2 = result; walk - ptr < len && *walk; walk += tlen) {
+     int decoded = 0;
+     int rlen;
+     int c = *walk;
+ 
+     tlen = rfc822_toklen(walk);
+     strfcpy(walk2,walk,tlen+1);  /* Make initial working copy */
+ 
+     /* Decode possible phrases */
+     if ((class & HDR_PHRASE) && space && 
+ 	NULL == strchr("()[]<>.:@,;\\\" \t\r\n",c) &&
+ 	NULL == strchr("[].@,;",walk[tlen])) {
+       char * walk3 = walk + tlen;
+ 
+        while (walk3 < ptr + len -1 && *walk3 && 
+ 	     NULL != strchr(" \t\r\n",*walk3)) {
+ 	char *tmp = walk3;
+ 	int nlen;
+ 
+ 	walk3 += rfc822_toklen(walk3);
+ 
+ 	nlen = rfc822_toklen(walk3);
+ 
+  	if (!*walk3 || NULL != strchr("()[]<>.:@,;\\\" \t\r\n",*walk3)
+ 	    || NULL != strchr("[].@,;",walk3[nlen])) {
+ 	  walk3 = tmp; /* back before space */
+ 	  break;
+ 	}
+ 
+ 	walk3 += nlen;
+       }
+ 
+       tlen = walk3 - walk;
+       strfcpy(walk2,walk,tlen+1);  /* Make initial working copy */
+ 
+       dprint (14, (debugfile, 
+ 		  "rfc1522_decode_structured: Possible phrase '%s'\n",walk2));
+ 
+       if (is_rfc1522(walk2)) {	
+ 	rfc1522_decode(walk2,tlen+1);
+ 	decoded = 1;
+       } else {
+ 	dprint (14, (debugfile, "rfc1522_decode_structured: '%s' NOT RFC1522\n",
+ 		    walk2));
+       }
+     }
+ 
+     space = 0;
+     /* Decode comments */
+     if (c == '(' && tlen > 9) {
+       char *tmp = walk2 + 1;
+ 
+       if (walk2[tlen-1] == ')')
+ 	walk2[tlen-1] = 0;
+ 
+       if (is_rfc1522(tmp)) {
+ 	rfc1522_decode(tmp,tlen-1);
+ 	decoded = 1;
+       } else {
+ 	dprint (14, (debugfile, "rfc1522_decode_structured: '%s' NOT RFC1522\n",
+ 		    tmp));
+       }
+ 
+       strcat(tmp,")");
+ 
+       space = 1;
+     }
+ 
+     /* Skip address */
+     if (c == '<' && tlen == 1) {
+       char *tmp = walk;
+       int t1len = tlen;
+       tlen = 0;
+ 
+       while (tmp < ptr + len && *tmp) {
+ 	t1len = rfc822_toklen(tmp);
+ 	tlen += t1len;
+ 	if (*tmp == '>' && t1len == 1)
+ 	  break;
+ 	tmp += t1len;
+       }
+       dprint (14, (debugfile, "rfc1522_decode_structured: Address '%.*s'\n",
+ 		  tlen,walk));
+     }
+     if (c == ',' && tlen == 1)
+ 	 space = 1;
+ 	 
+     if (strchr(" \t\n\r",c) != NULL)
+ 	 space = 1;
+ 
+     if (decoded) {
+       rlen = strlen(walk2);
+       dprint (14, (debugfile, "rfc1522_decode_structured: '%.*s' -> '%s'\n",
+ 		  tlen,walk,walk2));
+       walk2 += rlen;
+     } else {
+       strfcpy(walk2,walk,tlen+1);  /* Make working copy */
+       dprint (14, (debugfile, "rfc1522_decode_structured: Skip '%s'\n",walk2));
+       walk2 += tlen;
+     }
+   }
+ 
+   strcpy(ptr,result);
+   free(result);
+ 
+   dprint (14, (debugfile, "rfc1522_decode_structured <- ptr=%s\n",ptr));
+ }
+ 
+ static int can_handle(att)     
+      mime_t *att;
+ {
+   while (att) {
+     if (att->disposition == DISP_INLINE) {      
+       if (mime_notplain(att)) {
+ 	dprint(9,(debugfile,"can_handle=NO -- Failed: %s/%s\n",
+ 		  mime_types[att->type], att->subtype));
+ 	return FALSE;
+       }
+       dprint(9,(debugfile,  "can_handle:     Succeed: %s/%s\n",
+ 		mime_types[att->type], att->subtype));
+     } else {
+       dprint(9,(debugfile,  "can_handle:  Attachment: %s/%s\n",
+ 		mime_types[att->type], att->subtype));
+     }
+     att = att->next;
+   }
+   dprint(9,(debugfile,"can_handle=TRUE\n"));
+   return TRUE;
+ }
+ 
+ PUBLIC int mime_notplain (p)
+      mime_t *p;
+ {
+   CT_decoder_t decoder = select_CT_decoder(p);
+   char buf[STRING];
+  
+   if (p->encoding != ENCODING_BASE64 &&
+       p->encoding != ENCODING_QUOTED &&
+       p->encoding != ENCODING_NONE && 
+       p->encoding != ENCODING_7BIT &&
+       p->encoding != ENCODING_8BIT &&
+       p->encoding != ENCODING_BINARY) {
+     dprint(9,(debugfile,
+ 	      "mime_notplain=TRUE -- type: %s/%s; encoding=%s (%d)\n",
+ 	      mime_types[p->type], p->subtype,
+ 	      ENCODING(p->encoding),p->encoding));
+     return TRUE;      
+   }
+ 
+   if (decoder == rfc822_decode && p->parts && can_handle(p->parts)) {
+     dprint(9,(debugfile,"mime_notplain=FALSE -- type: %s/%s\n",
+ 	      mime_types[p->type], p->subtype));
+     return FALSE;      
+   }
+   if (decoder == rfc822_decode) {
+     dprint(9,(debugfile,"mime_notplain=TRUE -- type: %s/%s\n",
+ 	      mime_types[p->type], p->subtype));
+     return TRUE;
+   }
+  
+   /* Notice: if (decoder == text_unsupported_decode)
+    *         we return TRUE, because we want call metamail
+    *         if it is available
+    */
+  
+   if (decoder == text_decode || decoder == elm_decode) {
+     /* If mime_get_charsets < 0, we want call metamail
+      * (instead of filtering to US-ASCII)
+      */
+     if (mime_get_charset(buf,p->type_opts,sizeof(buf)) > 0) {
+       dprint(9,(debugfile,"mime_notplain=FALSE -- type: %s/%s; charset=%s\n",
+ 		mime_types[p->type], p->subtype,buf));
+       return FALSE;
+     }
+   }
+   else if (p->type == MIME_TYPE_MULTIPART && 
+ 	   (0 == strincmp(p->subtype,"mixed",STRING) || 
+ 	    0 == strincmp(p->subtype,"digest",STRING) || 
+ 	    0 == strincmp(p->subtype,"report",STRING)) &&
+ 	    p->parts && can_handle(p->parts)) {
+     dprint(9,(debugfile,"mime_notplain=FALSE -- type: %s/%s\n",
+ 	      mime_types[p->type], p->subtype));
+     return FALSE;	   
+   }
+   else if (p->type == MIME_TYPE_MULTIPART && pagemultipart) {
+     dprint(9,(debugfile,"mime_notplain=TRUE -- type: %s/%s\n",
+ 	      mime_types[p->type], p->subtype));
+     return FALSE;
+   }
+ #ifdef USE_PGP
+   else if (decoder == pgp_decode) {
+     dprint(9,(debugfile,"mime_notplain=FALSE -- type: %s/%s\n",
+ 	      mime_types[p->type], p->subtype));
+     return FALSE;
+   }
+ #endif
+   dprint(9,(debugfile,"mime_notplain=TRUE -- type: %s/%s\n",
+ 	    mime_types[p->type], p->subtype));
+   return TRUE;
+ }
+ 
+ #endif /* MIME */
Index: WORK/src/mime_encode.c
*** /tmp/null.14101	Tue Aug 20 22:05:34 1996
--- WORK/src/mime_encode.c	Fri Aug  9 21:52:06 1996
***************
*** 0 ****
--- 1,929 ----
+ #include <string.h>
+ 
+ #include "headers.h"
+ #include "s_elm.h"
+ #include "me.h"
+ 
+ #ifdef MIME
+ #include <sys/time.h>
+ 
+ extern short mime_count;
+ 
+ static char base64chars[64] = {
+ 	'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
+ 	'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b',
+ 	'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
+ 	'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3',
+ 	'4', '5', '6', '7', '8', '9', '+', '/'
+ };
+ #define to64(c) (((c) >= 0) && ((c) < 64)) ? base64chars[(c)] : -1
+ 
+ static char hexchars[16] = {
+ 	'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D',
+ 	'E', 'F',
+ };
+ 
+ int
+ update_encoding(top_encoding,encoding)
+ int *top_encoding;
+ int encoding;
+ {
+   if (encoding == ENCODING_8BIT &&
+       (*top_encoding) != ENCODING_BINARY)
+     (*top_encoding) = ENCODING_8BIT;
+   if (encoding == ENCODING_BINARY)
+     (*top_encoding) = ENCODING_BINARY;
+   
+   return (*top_encoding);
+ }
+ 
+ static void write_failed P_((void)) {
+   MoveCursor(elm_LINES, 0);
+   Raw(OFF);
+   Write_to_screen("\nWrite failed in mime_encode\n", 0);
+   emergency_exit();
+ }
+ 
+ #define ERROR_EOF(x) do { \
+    int error_eof = (x); if (EOF == error_eof) write_failed(); } while(0)
+ 
+ 
+ void
+ print_EOLN(fp,top_encoding) 
+      FILE *fp;
+      int top_encoding;
+ {  /* Write canoniocal end of line of we are sending binary mail */
+   if (top_encoding == ENCODING_BINARY)
+     ERROR_EOF(fputc('\r',fp));
+   ERROR_EOF(fputc('\n',fp));
+ }
+ 
+ char *
+ mime_generate_boundary (str)
+      char *str;
+ {
+   time_t t = time (NULL);
+ 	
+   sprintf (str, "ELM%d-%d-%d_", t, getpid(), mime_count++);
+   return str;
+ }
+ 
+ void 
+ add_parameter(opts,name,value,size,quoted) 
+      char *opts, *name, *value;
+      int size, quoted;
+ {
+   int len = strlen(opts);
+   int ln = strlen(name);
+   char * ptr = opts + len, *c;
+   int need_quotation = 0;
+   
+   /* Following characters require quotation: ( ) < > @ , ; : \ " / [ ] ? =
+    * Also whitespace requires quotation. See Mime Draft Standard
+    */
+   if (!quoted && (NULL != strpbrk(value,"()<>@,;:\\\"/[]?= \t")
+ 		  || value[0] == '\0'))
+     need_quotation = 1;
+ 
+   if (len + strlen(value) + ln + 4 + 2 * need_quotation > size)
+     return; /* Don't fit anyway */
+ 
+   if (ptr != opts) {
+     *ptr++ = ';'; *ptr++ = ' ';
+   }
+   strcpy(ptr,name);  ptr += ln;
+   *ptr++ = '=';
+ 
+   if (need_quotation) 
+     *ptr++ = '"';
+ 
+   for (c = value; *c != '\0'; c++) {
+     if (need_quotation && ('\\' == *c || '"' == *c)) {
+       if (ptr < opts + size - 3) {
+ 	*ptr++ = '\\';
+ 	*ptr++ = *c;
+       } else
+ 	break;
+     } else {
+       if (ptr < opts + size - need_quotation - 1) 
+ 	*ptr++ = *c;
+       else
+ 	break;
+     }
+   }
+ 
+   if (need_quotation) 
+     *ptr++ = '"';
+   *ptr = '\0';
+   return;
+ }
+ 
+ /* Prototype */
+ void write_encoded P_((FILE *, FILE *, int, int, int, mime_send_t *));
+ 
+ /* For some ANSI C compilers 'char *' and 'unsigned char *' are incompatible
+  * types -- we don't use casting macro here because it disables type checking
+  * altogether:
+  */
+ #if __STDC__
+ static char * std_str(unsigned char * str) { return (char *)str; }
+ #else
+ #define std_str(str)  (str)
+ #endif
+ 
+ static int rfc1522_encode_word(buf,size,source, hibit) 
+      unsigned char *buf, *source;
+      int size,hibit;
+ {
+   unsigned char * walk, * walk2, * startptr = NULL;
+   char * Charset = charset;
+   int charsetlen;
+ 
+   dprint (14, (debugfile, 
+ 	      "rfc1522_encode_word: (buf)size=%d, source='%s', hibit=%d\n",
+ 	      size,source,hibit));
+ 
+   size--; /* Space of \0 in end */
+ 
+   if (! hibit) { /* No 8-bit characters */
+     /* We assume that in headers we don't use other 7-bit charset
+      * than US-ASCII !
+      */
+     Charset = "us-ascii";
+   } else if (istrcmp(charset, "us-ascii") == 0) {
+     if (istrcmp(display_charset, "us-ascii") != 0 && 
+ 	charset_ok(display_charset))
+       Charset=display_charset;	    
+     else if (istrcmp(charset,"us-ascii") == 0) {
+       static int message_printed = 0;
+      
+       if (!message_printed) {
+ 	error("Header has 8BIT data and charset=US-ASCII, using charset=UNKNOWN-8BIT instead.");
+ 	sleep_message();
+ 	message_printed = 1;
+       }
+      
+       Charset = "UNKNOWN-8BIT";
+     }
+   }
+   
+   /* Even when we can use charset names what have space (they have
+    * plenty of them in ASSIGNED NUMBERS -- STD 3 (RFC 1700) --
+    * we can't use them in RFC 1522 encoded words!!!
+    */
+   if (0 != strpbrk(Charset," \t\r\n()\"")) {
+     static int message_printed = 0;
+     
+     if (!message_printed) {
+       error1("Bad charset=%s, using charset=UNKNOWN-8BIT instead.",Charset);
+       sleep_message();
+       message_printed = 1;
+     }
+     
+     Charset = "UNKNOWN-8BIT";
+   } 
+ 
+   charsetlen = strlen(Charset);
+   
+ #define LEFT (size - (walk2 - buf))
+   for (walk=source, walk2=buf; *walk != '\0'; walk++) {
+     if (startptr && (walk2 - startptr) > 60) {
+       *walk2++ = '?';
+       *walk2++ = '=';
+       dprint (14, (debugfile, 
+ 		  "rfc1522_encode_word> [%d] -> [%d] Encoded word: %.*s\n",
+ 		  walk-source,walk2-buf,walk2-startptr,startptr));
+       *walk2++ = ' ';
+       startptr = NULL;
+     }
+     
+     if (!startptr) {
+       /* Print start of encoded word */
+       if (LEFT < 11 + charsetlen) {
+ 	dprint (14, (debugfile, 
+ 		    "rfc1522_encode_word> [%d] -> [%d] No space left; bailing out\n",
+ 		    walk-source,walk2-buf));
+ 	break;
+       }
+       startptr = walk2;
+       *walk2++ = '=';  *walk2++ = '?';
+       strcpy(std_str(walk2),Charset); walk2 += charsetlen;
+       *walk2++ = '?'; *walk2++ = 'Q';
+       *walk2++ = '?';    
+     }
+     if (LEFT <= 5) {
+       dprint (14, (debugfile, 
+ 		  "rfc1522_encode_word> [%d] -> [%d] No space left; bailing out\n",
+ 		  walk-source,walk2-buf));
+       break;
+     }
+ 
+     if (NULL != strchr(" \r\n",*walk)) { /* Treat as space */
+       *walk2++ = '_';
+     } else if ((*walk >= 'A' && *walk <= 'Z') || 
+ 	       (*walk >= 'a' && *walk <= 'z') ||
+ 	       (*walk >= '0' && *walk <= '9')) { /* Can be copien always */
+       *walk2++ = *walk;
+     } else { /* Encode */
+       unsigned char value = *walk;
+       *walk2++ = '=';
+       *walk2++ = hexchars[value / 16];
+       *walk2++ = hexchars[value % 16];
+     }
+ 
+   }
+   if (startptr) {
+     *walk2++ = '?';
+     *walk2++ = '=';
+     dprint (14, (debugfile, 
+ 		"rfc1522_encode_word> [%d] -> [%d] Encoded word: %.*s\n",
+ 		walk-source,walk2-buf,walk2-startptr,startptr));
+     startptr = NULL;
+   }
+   *walk2='\0';
+ #undef LEFT
+ 
+   dprint (14, (debugfile, 
+ 	      "rfc1522_encode_word=%d; RESULT: '%s'\n",
+ 	      walk2 - buf,buf));
+   return walk2 - buf;
+ }
+ 
+ void rfc1522_encode_text(buf,size,source,flag) 
+      char *buf, *source;
+      int size, flag;
+ {
+   /* If flag & HDR_PHRASE, then consider that to be phrase */
+   unsigned char * walk, * walk2, * prvptr;
+   unsigned char * ubuf = (unsigned char *) buf;
+   unsigned tlen;
+   int was_encoded = 0;
+   
+   dprint (14, (debugfile, 
+ 	      "rfc1522_encode_text: (buf)size=%d, flag=%d, source='%s'\n",
+ 	      size,flag,source));
+ 
+   size--; /* Space of \0 in end */
+ 
+   for (walk = (unsigned char *)source, walk2 = ubuf, prvptr = walk; 
+        *walk; 
+        prvptr = walk, walk += tlen) {
+     unsigned hibit = 0, qchar = 0;
+     unsigned char *uptr, *work = walk, * workprvptr = prvptr;
+     unsigned is_encoded = 0, worklen;
+ 
+     { /* rfc822_toklen can't be used in here!! 
+        * Notice: (char *) != (unsigned char *)
+        */
+       char * nwalk = (char *)walk;
+       char * nptr = (flag & HDR_PHRASE) ? 
+ 	qstrpbrk(nwalk," \t\r\n") : 
+ 	strpbrk(nwalk," \t\r\n");
+ 
+       if (NULL == nptr)      tlen = strlen(nwalk);
+       else if (nwalk == nptr) { 
+ 	/* Special handle this */
+ 	tlen = 1;
+ 	dprint (14, (debugfile, 
+ 		    "rfc1522_encode_text> SPACE; word = '%.*s', is_encoded=%d, was_encoded=%d\n",
+ 		    tlen,walk,is_encoded,was_encoded));
+ 	if (walk2 < ubuf + size) {
+ 	  *walk2++ = *walk;
+ 	  continue;
+ 	} else
+ 	  break;
+       }
+       else                  tlen = nptr - nwalk;
+     }
+     worklen = tlen;
+ 
+     for (uptr = walk; uptr < walk + tlen ; uptr++)
+       if (*uptr & 128) 
+ 	hibit++;
+ 
+     /* Check if current word is valid encoded word */
+     if (0 == hibit && tlen > 9 && walk[0] == '=' && walk[1] == '?' &&
+ 	walk[tlen-1] == '=' && walk[tlen-2] == '?') {
+       unsigned char *ptr4;
+       int count = 0;
+       for (ptr4 = walk; ptr4 - walk < tlen; ptr4++) {
+ 	if (*ptr4 == '?')
+ 	  count++;
+ 	if (NULL != strchr(" \t\r\n",*ptr4)) {
+ 	  count = -1;
+ 	  break;
+ 	}
+       }
+       if (4 == count)
+ 	is_encoded = 1;
+     }
+     dprint (14, (debugfile, 
+ 		"rfc1522_encode_text> word = '%.*s', is_encoded=%d, hibit=%d\n",
+ 		tlen,walk,is_encoded,hibit));
+ 
+     /* Remove quotes from phrase */
+     if (flag & HDR_PHRASE) {
+       unsigned char *cptr;
+       int q = 0;
+       int plus = walk - prvptr;
+       workprvptr = (unsigned char *) safe_malloc(tlen+1+plus);
+       work = workprvptr+plus;
+       cptr = workprvptr;
+       for (uptr = prvptr; uptr < walk ; uptr++) 
+ 	*cptr++ = *uptr;
+ 
+       if (cptr != work) {
+ 	dprint (1, (debugfile, 
+ 		    "rfc1522_encode_text> FAIL! cptr != work; plus=%d\n",
+ 		    plus)); 
+       }
+ 
+       cptr = work;
+       for (uptr = walk; uptr < walk + tlen ; uptr++) {
+ 	if (q) {
+ 	  *cptr++ = *uptr;
+ 	  q = 0;
+ 	} else if ('\\' == *uptr)
+ 	  q = 1;
+ 	else if ('"' != *uptr)
+ 	  *cptr++ = *uptr;
+       }
+       worklen = cptr - work;    
+ 
+ 
+       /* Number of characters what needs quotation */
+       for (uptr = work; uptr < work + worklen ; uptr++)
+ 	if (NULL != strchr("()\\.[]\",;@:",*uptr))
+ 	  qchar++;    
+     }
+ 
+     dprint (14, (debugfile, 
+ 		"rfc1522_encode_text> work = '%.*s', qchar=%d\n",
+ 		worklen,work,qchar));
+ 
+     { unsigned char safe = work[worklen];
+       int rlen = 0;
+       int left = size - (walk2 - ubuf);
+       work[worklen] = 0;
+ 
+       dprint (14, (debugfile, 
+ 		  "rfc1522_encode_text> workprvptr = '%s', was_encoded=%d\n",
+ 		  workprvptr,was_encoded));
+ 
+       if (left > 0) {
+ 	if (hibit || is_rfc1522(std_str(work)) && !is_encoded) {
+ 	  /* Encode string */
+ 	  if (was_encoded && NULL != strchr(" \t",workprvptr[0]))
+ 	    rlen = rfc1522_encode_word(walk2,left+1,workprvptr,hibit);
+ 	  else
+ 	    rlen = rfc1522_encode_word(walk2,left+1,work,hibit);
+ 	  is_encoded = (rlen > 0);
+ 	} else if (qchar) {
+ 	  /* quote string */
+ 	  unsigned char * cptr = walk2;
+ 
+ 	  if (cptr + 1 < walk2 + left) *cptr++ = '"';
+ 	  else break;
+ 	  for (uptr = work; uptr < work + worklen ; uptr++) {
+ 	    if ('"' == *uptr || '\\' == *uptr) {
+ 	      if (cptr +2 < walk2 + left) {
+ 		*cptr++ = '\\';
+ 		*cptr++ = *uptr;
+ 	      }
+ 	    } else {
+ 	      if (cptr + 1 < walk2 + left) *cptr++ = *uptr;
+ 	    }
+ 	  }
+ 	  if (cptr < walk2 + left) *cptr++ = '"';
+ 	  rlen = cptr - walk2;
+ 	} else {
+ 	  /* copy string */
+ 	  unsigned char * cptr = walk2;
+ 	  for (uptr = work; uptr < work + worklen ; uptr++) {
+ 	    if (cptr < walk2 + left) *cptr++ = *uptr;
+ 	  }
+ 	  rlen = cptr - walk2;
+ 	}
+       }
+       work[worklen] = safe;
+     walk2[rlen] = '\0';
+       dprint (14, (debugfile, 
+ 		  "rfc1522_encode_text> rlen=%d, coded: '%s', is_encoded=%d\n",
+ 		  rlen,walk2,is_encoded));
+       walk2 += rlen;
+     }
+ 
+     if (workprvptr != prvptr)
+       free(workprvptr);
+     was_encoded = is_encoded;
+   }
+   *walk = '\0';
+   dprint (14, (debugfile, 
+ 	      "rfc1522_encode_text: RESULT: '%s'\n",buf));
+ 
+ }
+ 
+ 
+ void attach_generate_message (gopher, fpout, copy, mime_info)
+      mime_t *gopher;
+      FILE *fpout;
+      int copy;
+      mime_send_t *mime_info;
+ {
+ /* given a list of attachments, write them in MIME format to the specified
+  * output stream */
+ 
+   FILE *srcfp;
+   int is_text;
+ 
+   while (gopher) {
+     if (can_open(gopher->pathname,"r") != 0) {
+       gopher = gopher -> next;
+       continue;
+     }
+     srcfp = fopen (gopher->pathname, "r");
+ 
+     if (srcfp) {
+       
+       /* 1 if is text type (true)
+        * 0 if not text type
+        * -1 if can't be encoded (ie structured) Message/ or Multpart/
+        */
+       is_text = is_text_type (mime_types[gopher->type], gopher->subtype, 
+ 			      gopher->encoding);
+       
+       /* write the attachment header */
+       print_EOLN(fpout,mime_info->encoding_top);
+       ERROR_EOF(fprintf (fpout, "--%s", mime_info->mime_boundary));
+       print_EOLN(fpout,mime_info->encoding_top);
+       ERROR_EOF(fprintf (fpout, "Content-Type: %s/%s", 
+ 			mime_types[gopher->type], gopher->subtype));
+       if (gopher->type_opts) {
+ 	ERROR_EOF(fputc (';', fpout));
+ 	if (strlen (gopher->type_opts) > 45) {
+ 	  print_EOLN (fpout, mime_info->encoding_top);
+ 	  ERROR_EOF(fputc ('\t', fpout));
+       }
+ 	else
+ 	  ERROR_EOF(fputc (' ', fpout));
+ 	ERROR_EOF(fputs (gopher->type_opts, fpout));
+       }
+       print_EOLN (fpout, mime_info->encoding_top);
+     
+       /* Now add the Content-Disposition header */
+       ERROR_EOF(fprintf (fpout, "Content-Disposition: %s",
+ 			 DISPOSITION(gopher->disposition)));
+       if (gopher->disposition_opts) {
+ 	ERROR_EOF(fputc (';', fpout));
+ 	if (strlen (gopher->disposition_opts) > 45) {
+ 	  print_EOLN (fpout, mime_info->encoding_top);
+ 	  ERROR_EOF(fputc ('\t', fpout));
+ 	}
+ 	else
+ 	  ERROR_EOF(fputc (' ', fpout));
+ 	ERROR_EOF(fputs (gopher->disposition_opts, fpout));
+       }
+       print_EOLN (fpout, mime_info->encoding_top);
+ 
+       ERROR_EOF(fprintf (fpout, "Content-Description: "));
+       if (allow_no_hdrencoding) {
+ 	if (gopher->description)
+ 	  ERROR_EOF(fputs (gopher->description, fpout));
+  	else
+ 	  ERROR_EOF(fputs (gopher->pathname, fpout));
+       } else {
+ 	char buffer[LONG_STRING];
+ 	if (gopher->description)
+ 	  rfc1522_encode_text(buffer,sizeof(buffer),gopher->description,0);
+ 	else 
+ 	  rfc1522_encode_text(buffer,sizeof(buffer),gopher->pathname,0);
+ 	ERROR_EOF(fputs (buffer, fpout));
+       }
+       print_EOLN(fpout,mime_info->encoding_top);
+       ERROR_EOF(fprintf (fpout, "Content-Transfer-Encoding: %s",
+ 			 ENCODING(gopher->encoding)));
+       print_EOLN(fpout,mime_info->encoding_top);
+       print_EOLN(fpout,mime_info->encoding_top);
+       
+       (void) write_encoded (srcfp, fpout, gopher->encoding, copy, is_text,
+ 			    mime_info);
+ 
+       fclose (srcfp);
+     }
+     else {
+       error1 ("Error opening %s!", gopher->pathname);
+       dprint (1, (debugfile, "mime_gen_msg(): could not open %s\n", 
+ 		  gopher->pathname));
+       sleep_message();
+     }
+     
+     gopher = gopher->next;
+   }
+   return;
+ }
+ 
+ void
+ base64_encode (srcfp, fpout, istext, mime_info)
+      FILE *srcfp, *fpout;
+      int istext;
+      mime_send_t * mime_info;
+ {
+   int c1, c2, c3;
+   char ch1, ch2, ch3, ch4;
+   int chars = 0;
+   int last_c = 0;
+ 
+   for (;;) {
+     c1 = fgetc (srcfp);
+     if (c1 == -1)
+       break;
+     if (istext && last_c != '\r' && c1 == '\n') {
+       /* In text end of line must be coded as CR LF */
+       c1 = '\r';
+       c2 = '\n';
+     }
+     else
+       c2 = fgetc (srcfp);
+ 
+     if (istext && c1 != '\r' && c2 == '\n') {
+       /* In text end of line must be coded as CR LF */
+       c2 = '\r';
+       c3 = '\n';
+     }
+     else if (c2 != -1)
+       c3 = fgetc (srcfp);
+  
+     if (istext && c2 != '\r' && c3 == '\n') {
+       /* In text end of line must be coded as CR LF */
+       ungetc(c3,srcfp);
+       c3 = '\r';
+     }
+       
+     last_c = c3;
+  
+     ch1 = c1 >> 2;
+     ch1 = to64(ch1);
+     
+     if (c2 != -1) {
+       ch2 = ((c1 & 0x3) << 4) | (c2 >> 4);
+       ch2 = to64(ch2);
+       
+       if (c3 != -1) {
+ 	ch3 = ((c2 & 0xf) << 2) | (c3 >> 6);
+ 	ch3 = to64(ch3);
+ 	ch4 = c3 & 0x3f;
+ 	ch4 = to64(ch4);
+       }
+       else {
+ 	ch3 = (c2 & 0xf) << 2;
+ 	ch3 = to64(ch3);
+ 	ch4 = '=';
+       }
+     }
+     else {
+       ch2 = (c1 & 0x3) << 4;
+       ch2 = to64(ch2);
+       ch3 = '=';
+       ch4 = '=';
+     }
+     
+     ERROR_EOF(fputc (ch1, fpout));
+     ERROR_EOF(fputc (ch2, fpout));
+     ERROR_EOF(fputc (ch3, fpout));
+     ERROR_EOF(fputc (ch4, fpout));
+     chars += 4;
+     
+     if (chars >= 76) {
+       print_EOLN(fpout,mime_info->encoding_top);
+       chars = 0;
+     }	
+   }
+   print_EOLN(fpout,mime_info->encoding_top);
+   return;
+ }
+ 
+ void
+ line_quoted_printable_encode (input,fpout,copy,len,istext,mime_info) 
+      char *input;
+      FILE *fpout;
+      int copy; /* whether or not this is a copy of the message */
+      int len; /* length of data -- be binary clean */
+      int istext; /* if binary (not text) also CRLF need to be encoded */
+      mime_send_t *mime_info;
+ {
+   int chars = 0;
+   char buffer[STRING];
+   unsigned char c1, c2, c3;
+   unsigned char lastchar = 0;
+   unsigned char lastchar2 = 0;
+   
+   dprint (10, (debugfile, 
+ 	       "line_quoted_printable_encode: copy=%d, len=%d, istext=%d\n",
+ 	       copy,len,istext));
+ 
+   if (istext) {  
+     if (len > 0 && input[len-1] == '\n') {
+       lastchar = input[len-1];
+       input[len-1] = '\0';
+       len--;
+       if (len > 0 && input[len-1] == '\r')  {   /* Was CR LF */
+         lastchar2 = input[len-1];
+         input[len-1] = '\0';
+         len--;
+       } else if (mime_info->encoding_top == ENCODING_BINARY)
+ 	lastchar2 = '\r';     /* Simulate it */
+     }
+   }
+ 
+   /* I don't test agaist macros bacause these encodings are recommended
+    * according MIME Draft Standard anyway and MIME encodings are
+    * reversible.
+    *
+    * DONT_ESCAPE_MESSAGES refers '>' escaping -- not reversible
+    * MIME encoding -- '>' escaping was not reversible -- this is.
+    *
+    * We also want do these encodings when sending (copy == 0)
+    * not only when copying to another folder 
+    *            -- K E H <hurtta@dionysos.FMI.FI>                     */
+ 
+   while (len > 0)  {
+     /* Assume that buffer don't have newlines (or they have binary data) ...
+        this routine encodes one line */
+     c1 = (unsigned char) *input++;
+     len--;
+ 
+     if (c1 == '=') {
+       if (chars > 72) {	    
+ 	buffer[chars++] = '=';
+ 	buffer[chars++] = '\0';
+ 	chars = 0;
+ 
+ 	ERROR_EOF(fputs (buffer, fpout));
+ 	print_EOLN(fpout,mime_info->encoding_top);
+       }
+       buffer[chars++] = '=';
+       buffer[chars++] = '3';
+       buffer[chars++] = 'D';
+     }    
+     /*  printable characters -- EXCEPT:   Encode "From " in beginning */
+     else if ((c1 > 31 && c1 < 127) && ((c1 != ' ' || chars != 4 || 
+ 					strncmp(buffer,"From",4) != 0)
+ 				       /* Encode "." if only in line alone */
+ 				       && (c1 != '.' || chars != 0 || len > 0)
+ 				       /* Last space must encode also */
+ 				       && (c1 != ' ' || len > 0)) 
+ 	     ||
+ 	     (c1 == 9 && len > 0 && istext)) { 
+       /* Don't make sense wrap before last character, when last character
+        * is not encoded -- wrapping and character use equal number of columns.
+        * But left space for '=\n' if we will print it in end of function
+        * instead of '\n'. */
+       if (chars > 74 && (len > 0 || !lastchar)) {
+ 	buffer[chars++] = '=';
+ 	buffer[chars++] = '\0';
+ 	chars = 0;
+ 
+ 	ERROR_EOF(fputs (buffer, fpout));
+ 	print_EOLN(fpout,mime_info->encoding_top);
+       }
+       buffer[chars++] = c1;
+     }
+     else {
+       if (chars > 72) {
+ 	buffer[chars++] = '=';
+ 	buffer[chars++] = '\0';
+ 	chars = 0;
+ 
+ 	ERROR_EOF(fputs (buffer, fpout));
+ 	print_EOLN(fpout,mime_info->encoding_top);
+       }
+       c2 = (c1 >> 4) & 0xf;
+       c3 = c1 & 0xf;
+       buffer[chars++] = '=';
+       buffer[chars++] = hexchars[c2];
+       buffer[chars++] = hexchars[c3];
+     }
+   }
+ 
+   /* Make sure to flush the buffer.  */
+   if (chars > 0) {
+     buffer[chars] = '\0';
+     ERROR_EOF(fputs (buffer, fpout));
+   }
+   if (lastchar2)
+     ERROR_EOF(fputc (lastchar2, fpout));
+   if (lastchar) {
+     fputc(lastchar,fpout);
+   } else { /* If input line don't terminate NL then print shoft wrap to end
+ 	    * instead of hard NL */
+     ERROR_EOF(fputs ("=", fpout));
+     print_EOLN(fpout,mime_info->encoding_top);
+   }
+ }
+ 
+ void
+ quoted_printable_encode (srcfp, fpout, copy, istext, mime_info)
+      FILE *srcfp, *fpout;
+      int copy;    /* whether or not this is a copy of the message */
+      int istext;  /* if binary (not text) also CRLF need to be encoded */
+      mime_send_t *mime_info;
+ {
+   char buffer[VERY_LONG_STRING];
+   int len;
+ 
+   dprint (10, (debugfile, 
+ 	       "quoted_printable_encode: copy=%d, istext=%d\n",
+ 	       copy,istext));
+ 
+   if (istext) {
+     /* mail_gets is in ../lib -- it handles also NUL characters */
+     while ((len = mail_gets (buffer, VERY_LONG_STRING, srcfp)) > 0)
+       line_quoted_printable_encode (buffer, fpout, copy, len, istext,
+ 				    mime_info);
+   } else {
+     /* mail_gets may add LF to end of file if file don't end with LF
+      * So it is not good for binary data */
+     while ((len = fread(buffer, 1, sizeof(buffer), srcfp)) > 0)
+       line_quoted_printable_encode (buffer, fpout, copy, len, istext,
+ 				    mime_info);
+   }
+ 
+   return;
+ }
+ 
+ int
+ is_text_type (primary_type, subtype, enc)
+      char *primary_type, *subtype;
+      int enc;
+ {
+  /* encoding rules are different for text and no text 
+   * for text we must do \n -> \r\n before base64 encoding */
+ 
+  /* Current MIME Draft Standard says that part is text
+   * (ie. line oriented) when it is Text/ -type -- otherwise no.
+   *
+   * new draft for Mime standards allows also other parts ot be text.
+   * It says that content-transfer-encodings: 7bit and 8bit are only
+   * allowed for line orienteed types */
+ 
+   /* Actually Message/ and Multipart/ can't be newer encoded directly */
+   if ( istrcmp(primary_type,"Message") == 0 ||
+        istrcmp(primary_type,"Multipart") == 0)
+     return -1;
+ 
+   if (istrcmp(primary_type,"Text") == 0) 
+     return 1;               /* Subtypes of text are always text (ie.
+                              * line oriented). */
+ 
+   if (istrcmp(primary_type,"Application") == 0 &&
+       istrcmp(subtype,"X-ELM-encode") == 0)
+     return 1;            /*  That is text ... */
+     
+   if (enc == ENCODING_NONE || enc == ENCODING_7BIT || enc == ENCODING_8BIT)
+     return 1;             /* It is text */
+ 
+   if (enc == ENCODING_BINARY)
+     return 0;            /* It is probably binary (or very long lines) */
+ 
+   if (istrcmp(primary_type,"Application") == 0 &&
+       istrcmp(subtype,"Postscript") == 0)
+     return 1;            /*  Postscript is often text */
+   
+   return 0;              /* Default: It is binary */
+ }
+ 
+ void
+ write_encoded (srcfp, fpout, encoding, copy, is_text, mime_info)
+      FILE *srcfp, *fpout;
+      int encoding, copy, is_text;
+      mime_send_t *mime_info;
+ {
+   char buffer[VERY_LONG_STRING];
+   int line_len;
+ 
+   dprint (12, (debugfile, 
+ 	       "write_encoded: encoding=%d, copy=%d, is_text=%d\n",
+ 	       encoding,copy,is_text));
+ 
+   if (encoding == ENCODING_BASE64)
+     base64_encode (srcfp, fpout, is_text, mime_info);
+   else if (encoding == ENCODING_QUOTED)
+     quoted_printable_encode (srcfp, fpout, copy, is_text, mime_info);
+   else if (mime_info-> encoding_top == ENCODING_BINARY && is_text > 0) {
+     /* It is better perhaps use canonical eol (CRLF) when mail have
+      * content transfer encoding BINARY somewhere (see notes about BINARYMIME)
+      */
+     while ((line_len = mail_gets(buffer, sizeof(buffer)-1, srcfp)) > 0) {
+       if (buffer[line_len-1] == '\n') {
+         int add = 1;
+         if (line_len >1 && buffer[line_len-2] == '\r')
+           add = 0;
+         if (add) {
+           buffer[line_len-1] = '\r';
+           buffer[line_len] = '\n';
+           line_len++;
+         }
+       }
+       if (fwrite(buffer, 1, line_len, fpout) != line_len) {
+         MoveCursor(elm_LINES, 0);
+         Raw(OFF);
+         Write_to_screen("\nWrite failed in write_encoded\n", 0);
+         emergency_exit();
+       }
+     }
+   }
+   else {
+     /* BUG: This may add extra \n in end of file if file does not end with \n
+      * but we can't read that with fread when we to need look for escaping of
+      * "From " or lone "."
+      */
+     while (1) {
+ #ifndef DONT_ESCAPE_MESSAGES
+       if (mime_info->encoding_top != ENCODING_BINARY) {
+ 	if ((line_len = mail_gets(buffer, sizeof(buffer)-1, srcfp)) <= 0)
+ 	  break;
+       }
+       else
+ #endif
+ 	if ((line_len = fread(buffer, 1,sizeof(buffer)-1, srcfp)) <= 0)
+ 	  break;
+       
+       if (mime_info-> encoding_top != ENCODING_BINARY) {
+ #ifndef DONT_ESCAPE_MESSAGES
+ 	if (copy && (strncmp(buffer, "From ", 5) == 0)) {
+ 	  /* Add in the > to a From on our copy */
+ 	  ERROR_EOF(fprintf(fpout, ">"));
+ 	  if (fwrite(buffer, 1, line_len, fpout) != line_len) {
+ 	    MoveCursor(elm_LINES, 0);
+ 	    Raw(OFF);
+ 	    Write_to_screen("\nWrite failed in write_encoded()\n", 0);
+ 	    emergency_exit();
+ 	  }
+ 	}
+ #ifdef NEED_LONE_PERIOD_ESCAPE
+ 	else if (!copy && strcmp(buffer, ".\n") == 0)
+ 	  /* Because some mail transport agents take a lone period to
+ 	   * mean EOF, we add a blank space on outbound message.
+ 	   */
+ 	  ERROR_EOF(fputs(". \n", fpout));
+ #endif /* NEED_LONE_PERIOD_ESCAPE */
+ 	else
+ #endif /* DONT_ESCAPE_MESSAGES */
+ 	  if (fwrite(buffer, 1, line_len, fpout) != line_len) {
+ 	    MoveCursor(elm_LINES, 0);
+ 	    Raw(OFF);
+ 	    Write_to_screen("\nWrite failed in write_encoded()\n", 0);
+ 	    emergency_exit();
+ 	  }
+       }
+       else if (fwrite(buffer, 1, line_len, fpout) != line_len) {
+ 	MoveCursor(elm_LINES, 0);
+ 	Raw(OFF);
+ 	Write_to_screen("\nWrite failed in write_encoded()\n", 0);
+ 	emergency_exit();
+       }
+     }
+   }
+   return;
+ }
+ 
+ void
+ mime_write_header(fp, ptr, top)
+      FILE *fp;
+      mime_send_t *ptr;
+      int top;
+ {
+   int encoding;
+   int type;
+   char * subtype;
+   char * type_opts;
+ 
+   if (ptr->msg_is_multipart && top) {
+     encoding  = ptr->encoding_top;
+     type      = MIME_TYPE_MULTIPART;
+     subtype   = "mixed";
+     type_opts = ptr->type_opts_top;
+   } else {
+     encoding  = ptr->encoding_text;
+     type      = ptr->type_text;
+     subtype   = ptr->subtype_text;
+     type_opts = ptr->type_opts_text;
+   }
+ 
+   if (top) {
+     ERROR_EOF(fputs(MIME_HEADER, fp));
+     print_EOLN(fp, ptr->encoding_top);  
+   }
+   ERROR_EOF(fprintf(fp, "%s %s/%s", MIME_CONTENTTYPE, TYPE(type), 
+ 		    subtype));
+   if (type_opts[0])
+     ERROR_EOF(fprintf(fp, "; %s", type_opts));
+   print_EOLN(fp, ptr->encoding_top);
+   
+   if (encoding != ENCODING_NONE) {
+     ERROR_EOF(fprintf(fp, "%s %s", MIME_CONTENTENCOD, 
+ 		      ENCODING(encoding)));
+     print_EOLN(fp, ptr->encoding_top);
+   }
+ } 
+ #endif /* MIME */
Index: WORK/src/mime_parse.c
*** /tmp/null.14101	Tue Aug 20 22:05:34 1996
--- WORK/src/mime_parse.c	Sun Aug 11 18:23:08 1996
***************
*** 0 ****
--- 1,1008 ----
+ #include "headers.h"
+ #include "me.h"
+ 
+ #ifdef MIME
+ /* As ordered in mime.h */
+ char *mime_types[] = {
+ 	"*unknown*",
+ 	"application",
+ 	"audio",
+ 	"image",
+ 	"message",
+ 	"multipart",
+ 	"text",
+ 	"video",
+ 	/* Non standard main types */
+ 	"x-world",        /* x-word/x-vmrl */
+ 	"model",          /* draft-nelson-model-mail-ext-02.txt */
+         NULL
+ };
+ 
+ int
+ mime_needs_processing (p)
+      mime_t *p;
+ {
+   /* A routing which metapager() calls to determine if the message specified
+    * by "p" to determine whether or not any special MIME processing needs
+    * to be performed.  This information is used to decide if a temp file
+    * needs to be used in order to effect backwards paging, or if we can page
+    * directly out of the mailbox file.
+    */
+ 
+   if (p->disposition != DISP_INLINE)
+     return TRUE;
+ 
+   if (p->encoding != ENCODING_7BIT && p->encoding != ENCODING_8BIT)
+     return TRUE;
+ 
+   if (p->type != MIME_TYPE_TEXT)
+     return TRUE;
+ 
+   /* This is to support those poor unfortunate folk who don't have true
+    * MIME support.  Often, you see "Content-Type: text".  We'll just
+    * assume that it's normal text.
+    */
+   if (p->subtype[0] == '\0')
+     return FALSE;
+ 
+   if (istrcmp (p->subtype, "plain") != 0)
+     return TRUE;
+ 
+   return FALSE;
+ }
+ 
+ char *
+ mime_parse_content_opts (str)
+      char *str;
+ {
+   /* A routine for parsing the options in a Content-Type: field.  The
+    * important point here is to skip the semi-colon if it appears
+    * inside of quotes.  This works sort of like strtok, except that
+    * the token is already known.
+    */
+   static char *ptr;
+   char *ret;
+   int in_quote = 0;
+ 
+   /* This is the initialization call */
+   if (str)
+     ptr = str;
+   
+   if (*ptr == '\0')
+     return NULL;
+ 
+   ret = ptr;
+   while (*ptr) {
+     if (*ptr == '\\' && in_quote) {		  
+       /* \ escapes next character  
+        * (not allowed outside of quotes) */
+       ptr++;
+       if (*ptr == '\0')
+ 	break;
+     } else if (*ptr == '\"') {
+       if (in_quote)
+ 	in_quote = 0;
+       else
+ 	in_quote = 1;
+     }
+     else if (! in_quote) {
+       if (*ptr == ';') {
+ 	*ptr++ = '\0';
+ 	/* skip leading spaces */
+ 	while (*ptr && isspace ((unsigned char)*ptr))
+ 	  ptr++;
+ 	return (ret);
+       }
+     } 
+     ptr++;
+   }
+   return (ret);
+ }
+ 
+ void
+ mime_destroy (ptr)
+      mime_t *ptr;
+ {
+   mime_t *tmp;
+ 
+   dprint(20,(debugfile,"mime_destroy(%p) --> BEGIN\n",ptr));
+ 
+   while (ptr) {
+     tmp = ptr;
+     ptr = ptr->next;
+ 
+     if (tmp->description)
+       free (tmp->description);
+     if (tmp->type_opts)
+       free (tmp->type_opts);
+     if (tmp->disposition_opts)
+       free (tmp->disposition_opts);
+ 
+     if (tmp->parts)
+       mime_destroy (tmp->parts);
+ 
+     if (tmp->unlink)
+       unlink (tmp->pathname);
+ 
+     free (tmp);
+   }
+   dprint(20,(debugfile,"mime_destroy(...) <-- END\n"));
+   return;
+ }
+ 
+ void
+ mime_t_clear (mt)
+      mime_t *mt;
+ {
+   dprint(20,(debugfile,"mime_t_clear(%p) --> BEGIN\n",mt));
+ 
+   mt->flags = mt->offset = mt->begin_offset = 0;
+   mt->length = -1;
+   mt->encoding = ENCODING_7BIT;
+   mt->unlink = 0;
+   mt->type = MIME_TYPE_TEXT;
+   mt->disposition = DISP_INLINE;
+   mt->notplain = 0;
+ 
+   if (mt->parts)
+     mime_destroy (mt->parts);
+   if (mt->next)
+     mime_destroy (mt->next);
+ 
+   mt->next = mt->prev = mt->parts = NULL;
+ 
+   if (mt->description)
+     free (mt->description);
+   mt->description = NULL;
+   if (mt->type_opts)
+     free (mt->type_opts);
+   mt->type_opts = NULL;
+   if (mt->disposition_opts)
+     free (mt->disposition_opts);
+   mt->disposition_opts = NULL;
+   if (mt->pathname)
+     free (mt->pathname);
+   mt->pathname = NULL;
+ 
+   strcpy (mt->subtype, "plain");
+ 
+   dprint(20,(debugfile,"mime_t_clear(%p) <-- END\n",mt));
+   return;
+ }
+ 
+ void
+ mime_get_disposition (str, mt)
+      char *str;
+      mime_t *mt;
+ {
+   char *c, tmp[VERY_LONG_STRING];
+ 
+   dprint (2, (debugfile, "mime_get_disposition(): str=\"%s\"\n", str));
+   
+   /* Don't harm "str" */
+   strfcpy (tmp, str, sizeof(tmp));
+   
+   rfc822_reap_comments (tmp, NULL, 0);
+   
+   /* Look for the options field */
+   if ((c = strchr (tmp, ';')) != NULL) {
+     char *d = c;
+     while (d > tmp && whitespace(*(d-1)))
+       d--;
+     *d = '\0';
+     c++;
+     while (*c && whitespace(*c))
+       c++;
+     mt->disposition_opts = strmcpy (mt->disposition_opts, c);
+   }
+   else {
+     char *d = tmp + strlen(tmp);
+     while (d > tmp && whitespace(*(d-1)))
+       d--;
+     *d = '\0';
+     if (mt->disposition_opts) {
+       free (mt->disposition_opts);
+       mt->disposition_opts = NULL;
+     }
+   }
+   
+   /* All that's left now is the main disposition */
+   c = tmp;
+   while (*c && whitespace(*c))
+     c++;
+   /* No Content-Disposition -header     -> DISP_INLINE
+    *    Content-Disposition: inline     -> DISP_INLINE
+    *    Content-Disposition: attachment -> DISP_ATTACH
+    *    Content-Disposition: {unknown}  -> DISP_ATTACH
+    * See RFC 1806 (Experimental protocol) for details.
+    */   
+   if (istrcmp (c, "inline") != 0)
+     mt->disposition = DISP_ATTACH;
+   else
+     mt->disposition = DISP_INLINE;
+      
+   dprint (2, (debugfile,
+ 	     "mime_get_disposition(): disposition=\"%s\", disposition_opts=\"%s\"\n",
+ 	     DISPOSITION(mt->disposition), NONULL(mt->disposition_opts)));
+ }
+ 
+ int
+ mime_check_type (str)
+ 	char *str;
+ {
+   int i;
+   for (i = 0; mime_types[i] != NULL; i++) {
+     if (istrcmp(str,mime_types[i]) == 0)
+       return i;
+   }
+   return MIME_TYPE_UNKNOWN;
+ }
+ 
+ void
+ mime_get_content (str, mt)
+      char *str;
+      mime_t *mt;
+ {
+   char *c, tmp[VERY_LONG_STRING];
+ 
+   dprint (2, (debugfile, "mime_get_content(): str=\"%s\"\n", str));
+ 
+   /* Don't harm "str" */
+   strfcpy (tmp, str, sizeof(tmp));
+ 
+   rfc822_reap_comments (tmp, NULL, 0);
+ 
+   /* Look for the options field */
+   if ((c = strchr (tmp, ';')) != NULL) {
+     char *d = c;
+     while (d > tmp && whitespace(*(d-1)))
+       d--;
+     *d = '\0';
+     c++;
+     while (*c && whitespace(*c))
+       c++;
+     mt->type_opts = strmcpy (mt->type_opts, c);
+   }
+   else {
+     char *d = tmp + strlen(tmp);
+     while (d > tmp && whitespace(*(d-1)))
+       d--;
+     *d = '\0';
+     if (mt->type_opts) {
+       free (mt->type_opts);
+       mt->type_opts = NULL;
+     }
+   }
+   
+   mt->subtype[0] = '\0';
+   /* Get the subtype */
+   if ((c = strchr (tmp, '/')) != NULL) {
+     char *d = c;
+     while (d > tmp && whitespace(*(d-1)))
+       d--;
+     *d = '\0';
+ 
+     c++;
+     while (*c && whitespace(*c))
+       c++;
+     strfcpy (mt->subtype, c, sizeof(mt->subtype));
+   }
+   
+   /* All that's left now is the main type */
+   c = tmp;
+   while (*c && whitespace(*c))
+     c++;
+   mt->type = mime_check_type (c);
+ 
+   /* Mark MESSAGE/RFC822 so we can do special handling later */
+   if (mt->type == MIME_TYPE_MESSAGE && istrcmp (mt->subtype, "rfc822") == 0)
+     mt->flags |= MIME_RFC822;
+   else if (mt->type == MIME_TYPE_MULTIPART) {
+     if (istrcmp (mt->subtype, "mixed") == 0)
+       mt->flags |= MIME_MIXED;
+     else if (istrcmp (mt->subtype, "digest") == 0)
+       mt->flags |= MIME_DIGEST;
+   }
+ 
+   dprint (2,(debugfile,
+ 	     "mime_get_content(): type=\"%s\", subtype=\"%s\", opts=\"%s\"\n",
+ 	     mime_types[mt->type], mt->subtype, NONULL(mt->type_opts)));
+ 
+   return;
+ }
+ 
+ int
+ mime_get_param (name, value, opts, size)
+      char *name, *opts, *value;
+      int size;
+ {
+   char *c, tmp[VERY_LONG_STRING];
+   int i = 0, quoted = FALSE, found = FALSE;
+ 
+   value[0] = '\0';
+ 
+   if (!opts) {
+     dprint(11, (debugfile,"mime_get_param: name=\"%s\", opts=NULL\n",name));
+     return 0;
+   }
+ 
+   dprint(11, (debugfile,"mime_get_param: name=\"%s\", opts=\"%s\"\n",
+ 	      name,opts));
+ 
+   /* Make sure not to harm opts */
+   strfcpy (tmp, opts, sizeof (tmp));
+   rfc822_reap_comments (tmp, NULL, 0);
+ 
+   c = tmp;
+   while ((c = mime_parse_content_opts (c)) != NULL && !found) {
+     char * d = strchr(c,'=');
+     if (!d) {
+       c = NULL;
+       continue;    /* bad paramater */
+     }
+     while (d > c && (whitespace (*(d-1))))
+       d--;
+     *d = '\0';
+     
+     while (*c && whitespace(*c))
+       c++;
+     
+     if (istrcmp (c, name) == 0) {
+       found = TRUE;
+       
+       c = d+1;
+       while (*c && whitespace(*c))
+ 	c++;
+       if (*c == '"') {
+ 	c++;
+         quoted = TRUE;
+       }
+       /* Either look for a trailing quoted (if quoted==TRUE) or a SPACE */
+       while (*c && ((quoted && *c != '"') || (!quoted && *c != ' '))) {
+ 	if (*c == '\\' && quoted) {
+ 	  /* \ escapes next character */
+ 	  c++;
+ 	  if (!*c)
+ 	    break;
+ 	}
+ 	if (i >= size-1)
+ 	  break;    /* Avoid buffer overflow */
+ 	value[i++] = *c++;
+       }
+       value[i] = '\0';
+       break;
+     }
+     c = NULL;
+   }
+ 
+   dprint(11,(debugfile,"mime_get_param: found=%d, value=%s\n",found,value));
+ 
+   return found;
+ }
+ 
+ void mime_get_boundary (boundary, opts, size)
+      char *opts, *boundary;
+      int size;
+ {
+   if (!mime_get_param ("boundary", boundary, opts, size)) {
+     error ("'boundary' paramater is missing from Multipart -type!");
+     sleep_message();
+   }
+ 
+   return;
+ }
+ 
+ int class_charset(charset_value) 
+   char * charset_value;
+ {
+  /* Returns 1 if charset is displayable with charset of text
+   *     (suitable for replying)
+   * Return 2 if charset is displayable with display_charset
+   *           (when replying charset should be changed to display_charset)
+   * Return -1 if need to filter to US-ASCII
+   */
+   int ret = 0;
+ 
+   /* Check agaist charset of text */
+   if (0 == istrcmp(charset_value,"US-ASCII") && charset_ok(charset))
+     ret = 1; /* If charset of text can show us-ascii? */
+   else if (0 == istrcmp(charset_value,charset))
+     ret = 1;
+   /* Check agaist display charset */
+   else if (0 == istrcmp(charset_value,"US-ASCII") && 
+ 	   charset_ok(display_charset))
+     ret = 2; /* If display_charset can show us-ascii? */
+   else if (0 == istrcmp(charset_value,display_charset))
+     ret = 2;
+   else if (0 == istrcmp(display_charset,"US-ASCII") && 
+ 	   charset_ok(charset_value))
+     ret = -1;
+   else if (charset_ok(display_charset) && 
+ 	   charset_ok(charset_value))
+     ret = -1;
+ 
+   dprint(7,(debugfile,"class_charset: charset_value=\"%s\"\n",
+ 	    charset_value));
+   dprint(7,(debugfile,
+ 	    "             : (text)charset=\"%s\",display_charset=\"%s\"\n",
+ 	    charset,display_charset));
+   dprint(7,(debugfile,"class_charset=%d\n",ret));
+ 
+   return ret;
+ }
+ 
+ /* There should better handling in metapager (I have one idea)
+  * Perhaps in next version ...    -K E H    <hurtta@dionysos.fmi.fi>
+  */
+ int 
+ mime_get_charset (charset_value, opts, size)
+      char *opts, *charset_value;
+      int size;
+ {  /* Returns 1 if charset is displayable with charset of text
+     *     (suitable for replying)
+     * Return 2 if cahrset is displayable with display_charset
+     *           (when replying charset should be changed to display_charset)
+     * Return -1 if need to filter to US-ASCII
+     */
+   int ret = 0;
+ 
+   if (!mime_get_param("charset",charset_value,opts,size)) 
+     strcpy(charset_value,"US-ASCII"); 
+     /* Default charset if nothing specified */
+ 
+   if (!opts) {
+     dprint(9,(debugfile,"mime_get_charset: opts=NULL\n",opts));
+   } else {
+     dprint(9,(debugfile,"mime_get_charset: opts=\"%s\"\n",opts));
+   }
+   dprint(9,(debugfile,"                : charset_value=\"%s\"\n",
+ 	    charset_value));
+ 
+   ret = class_charset(charset_value);
+ 
+   dprint(9,(debugfile,"mime_get_charset=%d\n",ret));
+ 
+   return ret;
+ }
+ 
+ void
+ mime_t_zero (ptr)
+      mime_t *ptr;
+ {
+   /* This routine should be called whenever a new "mime_t" is created.  It
+    * makes sure that the pointers inside are correctly initialized to NULL
+    * so that we don't end up calling free() on an uninitialized pointer.
+    */
+   dprint(20,(debugfile,"mime_t_zero(%p)\n",ptr));
+ 
+   ptr->next = ptr->parts = NULL;
+   ptr->description = ptr->type_opts = ptr->disposition_opts = 
+     ptr->pathname = NULL;
+ }
+ 
+ void mime_t_copy(trg, src)
+      mime_t *trg, *src;
+ {
+   /* This routines make copy of mime_t structure ... */
+ 
+   dprint(20,(debugfile,"mime_t_copy(%p,%p) --> BEGIN\n",trg,src));
+   
+   mime_t_clear(trg);
+ 
+   trg->flags  =            src->flags;
+   trg->offset =            src->offset; 
+   trg->begin_offset  =     src->begin_offset; 
+   trg->length =            src->length;
+   trg->encoding =          src->encoding;
+   trg->unlink = 0; /* Don't unlink ! */
+   trg->type =              src->type;
+   trg->disposition =       src->disposition;
+   trg->notplain =          src->notplain;
+ 
+   if (src->parts) {
+     trg->parts = mime_t_alloc();
+     mime_t_copy(trg->parts,src->parts);
+   }
+ 
+   if (src->next) {
+     trg->next = mime_t_alloc();
+     mime_t_copy(trg->next,src->next);
+   }
+ 
+   if (src->description) {
+     trg->description = strmcpy(trg->description, src->description);
+   }
+ 
+   if (src->type_opts) {
+     trg->type_opts = strmcpy(trg->type_opts, src->type_opts);
+   }
+ 
+   if (src->disposition_opts) {
+     trg->disposition_opts = strmcpy(trg->disposition_opts, 
+ 				    src->disposition_opts);
+   }
+ 
+   strcpy(trg->subtype,src->subtype);
+ 
+   dprint(20,(debugfile,"mime_t_copy(%p,%p) <-- END\n",trg,src));
+ }
+ 
+ mime_t *
+ mime_t_alloc ()
+ {
+   mime_t *ptr;
+ 
+   dprint(20,(debugfile,"mime_t_alloc()     --> BEGIN\n"));
+ 
+   ptr = (mime_t *) safe_malloc (sizeof (mime_t));
+   /* Make sure to clear the pointers initially so that later we know when
+    * to reclaim memory in mime_t_clear().
+    */
+   mime_t_zero (ptr);
+   mime_t_clear (ptr);
+ 
+   dprint(20,(debugfile,"mime_t_alloc() = %p <-- END\n",ptr));
+   return ptr;
+ }
+ 
+ mime_t *
+ parse_mime_headers(header_list_ptr headers,
+ 		   long part_offset,
+ 		   long body_offset,
+ 		   int opts)
+ {
+   mime_t *ptr;
+   header_list_ptr this_header;
+ 
+   dprint(9,(debugfile, 
+ 	    "parse_mime_headers(): part_offset=%ld, body_offset=%ld, opts=%d\n",
+ 	    part_offset,body_offset,opts));
+ 
+   ptr = mime_t_alloc ();
+ 
+   /* set some defaults */
+   ptr->encoding = ENCODING_7BIT;
+   if (opts & MIME_DIGEST) {
+     ptr->type = MIME_TYPE_MESSAGE;
+     strcpy (ptr->subtype, "rfc822");
+   }
+   else {
+     ptr->type = MIME_TYPE_TEXT;
+     strcpy (ptr->subtype, "plain");
+   }
+   ptr->disposition = DISP_INLINE;
+   ptr->description = NULL;
+ 
+   ptr->begin_offset = part_offset;
+   ptr->offset       = body_offset;
+   ptr->length = -1;
+ 
+   if (NULL != (this_header = 
+ 	       locate_header_by_name(headers,"Content-Type")) &&
+       NULL != this_header->body) {
+     mime_get_content (this_header->body, ptr);
+     if (this_header->next_this_header) {
+       error("PARSE ERROR: Several Content-Type headers!");
+       sleep_message();
+     }
+   } else {
+     dprint (9,(debugfile,"parse_mime_headers: No Content-Type -header\n"));
+   }
+ 
+   if (NULL != (this_header = 
+ 	       locate_header_by_name(headers,"Content-Disposition")) &&
+       NULL != this_header->body) {
+     mime_get_disposition (this_header->body, ptr);
+     if (this_header->next_this_header) {
+       error("PARSE ERROR: Several Content-Disposition headers!");
+       sleep_message();
+     }
+   } else {
+     dprint (9,(debugfile,
+ 	       "parse_mime_headers: No Content-Disposition -header\n"));
+   }
+ 
+   if (NULL != (this_header = 
+ 	       locate_header_by_name(headers,"Content-Transfer-Encoding")) &&
+       NULL != this_header->body) {
+     char  * value = this_header->body, *c;
+ 
+     /* This removes comments from buffer this_header->body */
+ 
+     rfc822_reap_comments (value, NULL, 0);
+     c = value;
+     while (*c && isspace((unsigned char) *c))
+ 	c++;
+     ptr->encoding = check_encoding (c);
+ 
+     if (this_header->next_this_header) {
+       error("PARSE ERROR: Several Content-Transfer-Encoding headers!");
+       sleep_message();
+     }
+   } else {
+     dprint (9,(debugfile,
+ 	       "parse_mime_headers: No Content-Transfer-Encoding -header\n"));
+   }
+ 
+   if (NULL != (this_header = 
+ 	       locate_header_by_name(headers,"Content-Description"))  &&
+       NULL != this_header->body) {
+     char value [32 * 1024 +1], *c;
+     strfcpy(value,this_header->body);
+       
+     /* Content-description is unstructured text header */
+     if (is_rfc1522(value))
+       rfc1522_decode(value,sizeof(value));
+ 
+     c = value;
+     while (*c && whitespace(*c))
+       c++;
+     ptr->description = NULL;
+     ptr->description = strmcpy (ptr->description, c);
+ 
+     if (this_header->next_this_header) {
+       error("PARSE ERROR: Several Content-Description headers!");
+       sleep_message();
+     }
+   } else {
+     dprint (9,(debugfile,
+ 	       "parse_mime_headers: No Content-Description -header\n"));
+   }
+ 
+   /* mime_get_content don't set this if this is set as defualt value
+    * because of MIME_DIGEST -flag (in opt)
+    */
+   if (ptr->type == MIME_TYPE_MESSAGE && 
+       istrcmp (ptr->subtype, "rfc822") == 0)
+     ptr->flags |= MIME_RFC822;
+ 
+   dprint(12,(debugfile, 
+ 	     "parse_mime_headers- type=%s/%s; flags=%d;\n",
+ 	     mime_types[ptr->type], ptr->subtype, ptr->flags));
+   dprint(12,(debugfile, 
+ 	     "parse_mime_headers- begin=%ld, offset=%ld, length=%ld\n",
+ 	     ptr->begin_offset,ptr->offset,ptr->length));
+   dprint(9,(debugfile, "parse_mime_headers=%p <-- END\n",(void *)ptr));
+ 
+   return ptr;
+ }
+ 
+ mime_t *
+ mime_read_header (fp, opts)
+      FILE *fp;
+      int opts;
+ {
+   mime_t *ptr;
+   header_list_ptr headers = NULL;
+   long part_offset;
+   long body_offset;
+ 
+ 
+   dprint(9,(debugfile, "mime_read_header: opts=%d --> START\n",opts));
+ 
+   part_offset = ftell (fp);
+   headers = file_read_headers(fp,0);
+   body_offset = ftell(fp);
+ 
+   ptr = parse_mime_headers(headers,part_offset,body_offset,opts);
+ 
+   delete_headers(headers);
+ 
+   return ptr;
+ }
+ 
+ mime_t * multipart_parse (fp, length, boundary, opts)
+      FILE *fp;
+      int length, opts;
+      char *boundary;
+ {
+   int blen, len,last_pos;
+   long end_offset;
+   char buf[VERY_LONG_STRING], subbound[STRING];
+   mime_t *ptr = NULL, *tmp, *ret = NULL;
+ 
+   dprint(9,(debugfile,"multipart_parse --> length=%d, boundary=%s\n",
+ 	    length, boundary));
+ 
+   blen = strlen (boundary);
+   end_offset = ftell (fp) + length;
+   last_pos = ftell(fp);
+ 
+   while (ftell (fp) < end_offset) {
+     if ((len = mail_gets (buf, VERY_LONG_STRING, fp)) == 0)
+       break;
+ 
+     if (buf[0] == '-' && buf[1] == '-' &&
+         strncmp (buf + 2, boundary, blen) == 0) {
+ 
+       /* Save the length of the previous part */
+       if (ptr) {
+         ptr->length = last_pos - ptr->offset;
+ 	dprint(9,(debugfile,"multipart_parse: fixing length=%d\n",
+ 		  ptr->length));
+       }
+       /* Check for the end boundary. */
+       if (buf[blen+2] == '-' && buf[blen+3] == '-')
+         break;
+       
+       tmp = mime_read_header (fp, opts);
+ 
+       dprint(9,(debugfile,"multipart_parse: (reading) content-type=%s/%s; flags=%d\n",
+ 		mime_types[tmp->type], tmp->subtype, tmp->flags));
+ 
+       
+       if (ret == NULL)
+         ptr = ret = tmp;
+       else {
+         ptr->next = tmp;
+         ptr = ptr->next;
+       }
+ #if 0
+       if (ptr->length >= 0) {
+ 	/* If the length of this part is known, skip ahead to the next
+ 	 * part.  If the length is not known, we don't have to worry
+ 	 * about it because the algorithm will search for the next
+ 	 * boundary...
+ 	 */
+         fseek (fp, (long) (ptr->length), SEEK_CUR);
+ 	continue;
+       }
+ #endif
+     }
+     if (ptr && ptr->length < 0) { /* mark position before CR LF */
+       int pos = ftell(fp);
+       if (len > 1 && buf[len-2] == '\r' && buf[len-1] == '\n')
+ 	last_pos = pos -2;
+       else if (len > 0 && buf[len-1] == '\n')
+ 	last_pos = pos -1;
+     }
+   }
+ 
+   if (ptr && ptr->length != last_pos - ptr->offset) {
+     ptr->length = last_pos - ptr->offset;
+     dprint(9,(debugfile,"multipart_parse: fixing length=%d (corrupted?)\n",
+ 	      ptr->length));
+ 
+     error ("Seems that multipart structure was corrupted.");
+     sleep_message();
+   }
+ 
+   /* Now that we know what this message consists of, see if any of the
+    * parts contain data that needs to be parsed. */
+ 
+   for (tmp = ret; tmp != NULL; tmp = tmp->next) {
+     dprint(9,(debugfile,"multipart_parse: (parsing) content-type=%s/%s; flags=%d\n",
+ 	      mime_types[tmp->type],tmp->subtype,tmp->flags));
+ 
+     if (tmp->flags & MIME_RFC822) {
+       dprint(9,(debugfile,"multipart_parse- (parsing) RFC822\n"));
+       fseek (fp, tmp->offset, SEEK_SET);
+       tmp->parts = rfc822_parse (fp, tmp->length);
+     }
+     else if (tmp->type == MIME_TYPE_MULTIPART) {
+       fseek (fp, tmp->offset, SEEK_SET);
+       mime_get_boundary (subbound, tmp->type_opts, sizeof (subbound));
+       dprint(9,(debugfile,
+ 		"multipart_parse- (parsing) MULTIPART; boundary=%s\n",
+ 		subbound));
+       tmp->parts = multipart_parse (fp, tmp->length, subbound, tmp->flags);
+     }
+   }
+ 
+   /* Make sure to leave the stream at the end of the data since the
+    * calling function might be assuming this.  */
+   fseek (fp, end_offset, SEEK_SET);
+ 
+   dprint(9,(debugfile,"multipart_parse <-- DONE\n"));
+ 
+   return ret;
+ }
+ 
+ mime_t *
+ rfc822_parse (fp, len)
+      FILE *fp;
+      int len;
+ {
+   /* Called to read MESSAGE/RFC822 data.  First reads the header of the
+    * message for MIME information, then (when necessary) calls other
+    * functions to determine the content of MULTIPART or MESSAGE/RFC822
+    * data contained.
+    */
+   mime_t *ret = NULL;
+   long part_offset = ftell (fp);
+   long body_offset;
+   long end_offset  =  part_offset + len;
+   header_list_ptr headers = NULL, mime_version, content_type;
+   int pre_mime_content_type = 0;
+ 
+   dprint(9,(debugfile,"rfc822_parse --> len=%d\n",len));
+ 
+   headers     = file_read_headers(fp,0);
+   body_offset = ftell(fp);
+ 
+   dprint(9,(debugfile,
+ 	    "rfc822_parse- part_offset=%ld, body_offset=%ld, end_offset=%ld\n",
+ 	    part_offset, body_offset, end_offset));
+ 
+   if (!locate_header_by_name(headers,"From") &&
+       !locate_header_by_name(headers,"Subject") &&
+       !locate_header_by_name(headers,"To") &&
+       !locate_header_by_name(headers,"CC")) {
+     error ("Seems that message/rfc822 data was corrupted.");
+     sleep_message();
+   }
+ 
+   mime_version = locate_header_by_name(headers,"MIME-Version");
+   content_type = locate_header_by_name(headers,"Content-Type");
+ 
+   if (content_type && content_type ->body) {
+     ret = mime_t_alloc();
+     ret->begin_offset = part_offset;
+     ret->offset       = body_offset;
+     ret->length = -1;
+ 
+     pre_mime_content_type = is_pre_mime_content_type(ret,content_type->body);
+   }
+ 
+   if (mime_version && pre_mime_content_type) {
+     error ("Warning: message/rfc822 data with MIME-Version and pre-mime Content-type");
+     sleep_message();
+   } 
+ 
+   if (mime_version || !pre_mime_content_type && req_mime_bodyencoding) {
+     if (ret) mime_destroy(ret);
+     ret = parse_mime_headers(headers,part_offset,body_offset,MIME_MIXED);  
+   } else if (!ret) {
+     ret = mime_t_alloc();
+     ret->begin_offset = part_offset;
+     ret->offset       = body_offset;
+     ret->length = -1;
+ 
+   }
+ 
+   dprint(9,(debugfile,"rfc822_parse: content-type=%s/%s; flags=%d\n",
+ 	    mime_types[ret->type], ret->subtype,ret->flags));
+ 
+   if (ret->length < 0) { 
+     ret->length = end_offset - body_offset;
+     dprint(9,(debugfile,"rfc822_parse: fixing length=%d\n",ret->length));
+   }
+ 
+   if (ret->type == MIME_TYPE_MULTIPART) {
+     char boundary[STRING];
+ 
+     mime_get_boundary (boundary, ret->type_opts, STRING);
+     dprint(9,(debugfile,"rfc822_parse- (parsing) MULTIPART; boundary=%s\n",
+ 	      boundary));
+ 
+     ret->parts = multipart_parse (fp, ret->length, boundary, ret->flags);
+   }
+   else if (ret->flags & MIME_RFC822) {
+     dprint(9,(debugfile,"rfc822_parse- (parsing) RFC822\n"));
+     ret->parts = rfc822_parse (fp, ret->length);
+   }
+   
+   delete_headers(headers);
+ 
+   /* Make sure the leave the stream at the end of the data! */
+   fseek (fp, end_offset, SEEK_SET);
+ 
+   dprint(9,(debugfile,"rfc822_parse <-- DONE\n"));
+ 
+   return ret;
+ }
+ 
+ void
+ mime_warnings(hdr) 
+      struct header_rec *hdr;
+ {
+ 
+   if (hdr->status & PRE_MIME_CONTENT) {
+     error("Error: MIME-message has pre-MIME content-type!");
+     sleep_message();
+   }
+   if (hdr->status & MIME_UNSUPPORTED) {
+     error("Warning: Unsupported MIME-Version!");
+     sleep_message();
+   }
+ }
+ 
+ void
+ attach_parse (hdr, fp)
+      struct header_rec *hdr;
+      FILE *fp;
+ {
+   int parsing = 0;
+   /* This routine checks to see if the multipart messages specified by
+    * "hdr" has been parsed for its subparts, and if not, calls the routine
+    * to do so.
+    */
+ 
+   char boundary[STRING];
+ 
+   /* Copy value */
+   if (hdr -> content_length >= 0)
+     hdr->mime_rec.length = hdr -> content_length;
+ 
+   if (hdr->mime_rec.begin_offset <= 0) {
+ 
+     fseek(fp,hdr->offset,SEEK_SET);
+     hdr->mime_rec.begin_offset = hdr->offset;
+     /* Skip mailbox's separator lines ... */
+ 
+     dprint(9,(debugfile,"attach_parse: scanning begin_offset: %d\n",
+ 	      hdr->mime_rec.begin_offset));
+ 
+     hdr->mime_rec.begin_offset = skip_envelope(hdr,fp);
+ 
+     dprint(9,(debugfile,"attach_parse: begin_offset=%d\n",
+ 	      hdr->mime_rec.begin_offset));
+ 
+     if (hdr->mime_rec.begin_offset < 0) {
+       error("Can't parse mail...");
+       sleep_message();
+       return;
+     }
+   }
+ 
+   if (hdr->mime_rec.type == MIME_TYPE_MULTIPART) {
+     if (hdr->mime_rec.parts == NULL) {
+       mime_get_boundary (boundary, hdr->mime_rec.type_opts, STRING);
+       if (0 != fseek (fp, hdr->mime_rec.offset, SEEK_SET)) {
+ 	error("Failed to seek beginning body...");
+ 	sleep_message();
+       } else {
+ 	int tmp;
+ 	parsing = 1;
+ 	lower_prompt("Parsing MIME structure...");
+ 	hdr->mime_rec.parts = 
+ 	  multipart_parse (fp, hdr->content_length, boundary, 
+ 			 hdr->mime_rec.flags);
+ 	/* Reconsider it */
+ 	tmp = mime_notplain(&(hdr->mime_rec));
+ 	if (tmp != hdr->mime_rec.notplain) {
+ 	  hdr->mime_rec.notplain = tmp;
+ 	  if (!tmp) {
+ 	    lower_prompt("Parsing MIME structure... metamail not needed");
+ 	    parsing = 2;
+ 	  }
+ 	}
+       }
+     }
+   } else if (hdr->mime_rec.flags & MIME_RFC822) {
+     if (hdr->mime_rec.parts == NULL) {
+       if (0 != fseek (fp, hdr->mime_rec.offset, SEEK_SET)) {
+ 	error("Failed to seek beginning body...");
+ 	sleep_message();
+       } else {
+ 	int tmp;
+ 	parsing = 1;
+ 	lower_prompt("Parsing MIME structure...");
+ 	hdr->mime_rec.parts = rfc822_parse (fp, hdr->content_length);
+ 	/* Reconsider it */
+ 	tmp = mime_notplain(&(hdr->mime_rec));
+ 	if (tmp != hdr->mime_rec.notplain) {
+ 	  hdr->mime_rec.notplain = tmp;
+ 	  if (!tmp) {
+ 	    lower_prompt("Parsing MIME structure... metamail not needed");
+ 	    parsing = 2;
+ 	  }
+ 	}	
+       }
+     }
+   }
+ 
+   if (parsing) {
+     if (2 == parsing) {
+       if (sleepmsg > 0)
+ 	sleep ((sleepmsg+2)/3);
+     }
+     lower_prompt("");
+   }
+   return;
+ }
+ #endif /* MIME */
+ 
+ 
+ 
+ 
Index: WORK/src/parse_util.c
*** /tmp/null.14101	Tue Aug 20 22:05:34 1996
--- WORK/src/parse_util.c	Sat Aug 10 22:22:28 1996
***************
*** 0 ****
--- 1,578 ----
+ #include "headers.h"
+ #include "me.h"
+ 
+ static void header_panic P_((char *,int,char *, char *)); /* Prototype */
+ static void header_panic(f,ln,pr,ms) 
+      char * f;
+      int ln;
+      char *pr;
+      char *ms;
+ {
+   int do_cursor = RawState();
+ 
+   dprint(1,(debugfile,"\nHEADER PANIC in %s:%d:%s\n",f,ln,pr));
+   dprint(1,(debugfile,">>%s\n",ms));
+ 
+   /* softkeys_off(); */
+ 
+   if (do_cursor) {
+     error1("HEADER PANIC: %s",ms);
+     sleep(1);
+   }
+ 
+   if (do_cursor) {
+     MoveCursor(elm_LINES, 0);
+     Raw(OFF);
+   }
+ 
+   fprintf(stderr,"\nHEADER PANIC in %s:%d:%s\n",f,ln,pr);
+   fprintf(stderr,">>%s\n",ms);
+ 
+ #if DEBUG
+   if (debug > 10) {
+     fprintf(stderr,"ABORTING...\n");
+     fflush(stderr);
+     abort();
+   }
+ #endif
+   emergency_exit();
+ }
+ 
+ /* Removes comments from string */
+ PUBLIC void rfc822_reap_comments (ptr, comments, size) 
+      char *ptr, *comments;
+      int size;
+ {
+   char *w_ptr = ptr, *c_ptr = comments;
+   int comment_level = 0, saved_level = 0;
+   int in_quote = 0;
+   
+   while (*ptr) {
+     if (*ptr == '\\' && (in_quote || comment_level > 0)) {		  
+       /* \ escapes next character  
+        * (not allowed outside of quotes or comments) */
+       ptr++;
+       if (*ptr == '\0')
+ 	break;
+       if (comment_level > 0 && comments) {
+ 	if (c_ptr < comments + size - saved_level -3) {
+ 	  *c_ptr++ = '\\';
+ 	  *c_ptr++ = *ptr;
+ 	}
+       }
+       if (comment_level == 0) {
+ 	*w_ptr++ = '\\';
+ 	*w_ptr++ = *ptr;
+       }
+       ptr++;
+       continue;
+     } else if (comment_level > 0) {
+       if (*ptr == ')')
+ 	comment_level --;
+       if (*ptr == '(')
+ 	comment_level ++;
+       if (comments && c_ptr < comments + size - saved_level -3) {
+ 	*c_ptr++ = *ptr;
+ 	saved_level = comment_level;
+       }
+     } else if (*ptr == '\"') {
+       if (in_quote)
+ 	in_quote = 0;
+       else
+ 	in_quote = 1;
+     } else if (!in_quote && *ptr == '(') {
+       comment_level ++;
+       if (comments && c_ptr < comments + size - saved_level -4) {
+ 	if (c_ptr != comments)
+ 	  *c_ptr++ = ' ';
+ 	*c_ptr++ = *ptr;
+ 	saved_level = comment_level;
+       }
+       *w_ptr++ = ' ';  /* RFC 822 (STD 11) says that 
+ 			  comments represents one space */
+     }
+     if (comment_level == 0 && (in_quote || *ptr != ')'))
+       *w_ptr++ = *ptr;
+     ptr++;
+   }
+   while (comments && saved_level > 0) {
+     *c_ptr++ = ')';
+     saved_level--;
+   }
+ 
+   if (comments)
+     *c_ptr = '\0';
+   *w_ptr = '\0';
+ }
+ 
+ PUBLIC int read_header_line (fp, buf, size,flag) 
+      FILE *fp;
+      char *buf;
+      int size;
+      int flag;
+ {
+   in_state_t state;
+   int result;
+ 
+   in_state_clear(&state,STATE_in_file);
+ 
+   set_in_state_file(fp,&state);
+ 
+   result = state_read_hdr_line(&state,buf,size,flag);
+ 
+   in_state_destroy(&state);
+ 
+   return result;
+ }
+ 
+ PUBLIC int state_read_hdr_line (s, buf, size,flag) 
+      in_state_t *s;
+      char *buf;
+      int size;
+      int flag;
+ {
+   /* Read and unfold header line -- stores maximum size-1 bytes to buffer
+    * (plus \0). Also handle case when headers are eneded either CR LF or LF.
+    * Returns number of bytes stored. Always _read_ end of header
+    * (even when buffer fills). Returns 0 when reads empty line (only CR LF).
+    * That indicates end of headers.
+    *
+    * If flag & 1 (RHL_MARK_FOLDING) then folding is marked with '\n' 
+    * (instead of ' ' and buffer ended with '\n' before '\0'
+    * If flag & 2 (RHL_CHECK_HEADER) then check that this was header line...
+    */
+ 
+   int len = 0,c;
+   int col_seen = 0;
+   long pos;
+ 
+   dprint(12,(debugfile,"state_read_hdr_line: size=%d, flag=%d\n",size,flag));
+   size--; /* Place for \0 */
+ 
+   if ( (!in_state_seekable(s) ||
+ 	(pos = in_state_ftell(s)) < 0) && 
+        (flag & RHL_CHECK_HEADER)) {
+     dprint(12,(debugfile,"state_read_hdr_line=0; not seekable or ftell failed!"));
+     buf[0] = '\0';
+     return 0;
+   }
+ 
+ #define PUTC(c) { if (len < size) buf[len++] = (c); }
+   
+   while (EOF != (c = state_getc(s))) {
+     if ('\r' == c) {                /* Is this CR LF sequence ? */
+       if (EOF == (c = state_getc(s)))
+ 	break;
+       if (c != '\n') 
+ 	PUTC('\r');
+     }
+     if (c == '\n') {                /* Readed CR LF or LF, check folding */
+       if (!col_seen && len > 0 && (flag & RHL_CHECK_HEADER)) {
+       bad_header_line:
+ 	dprint(12,(debugfile,
+ 		   "state_read_hdr_line: Not ':' seen. Not a header line!\n"));
+ 	if (0 != in_state_fseek(s,pos)) {
+ 	  dprint(5,(debugfile,
+ 		    "read_header_line: seek failed!\n"));
+ 	}
+ 	len = 0;
+       }
+       if (len == 0)
+ 	break;                      /* End of headers ! */
+       if (EOF == (c = state_getc(s)))
+ 	break;
+       if (c != ' ' && c != '\t') {   /* Not a continuation line */
+ 	state_ungetc(c,s);
+ 	break;
+       }
+       /* CRLF LWSP sequence should be replaced with ' ' */
+       c = ' ';
+       if (flag & RHL_MARK_FOLDING)
+ 	c = '\n';
+     }
+     /* Space before ':' ? */
+     if ((' ' == c || '\t' == c) && !col_seen && (flag & RHL_CHECK_HEADER)) {
+       /* Skip to next ':' */
+       while (' ' == c || '\t' == c)
+ 	c = state_getc(s);
+       if (':' != c) 
+ 	goto bad_header_line;
+     }
+     if (':' == c)
+       col_seen = 1;
+     PUTC(c);
+   }
+ 
+   if (flag & RHL_MARK_FOLDING) {
+     PUTC('\n');
+   }
+ 
+ #undef PUTC
+   buf[len] = 0;
+ 
+   dprint(12,(debugfile,"state_read_hdr_line: len=%d, buf=%s\n",len,buf));
+ 
+   return len;
+ }
+ 
+ static struct header_info header_types[] = {
+   /* From STD 11 (RFC 822): */
+   { "Subject",    HDR_TEXT },
+   { "Comments",   HDR_TEXT },
+   { "Return-path",HDR_STRUCTURED },
+   { "Received",   HDR_STRUCTURED },
+   { "Reply-To",   HDR_STRUCTURED|HDR_PHRASE },    /* Not exactly correct .. */
+   { "From",       HDR_STRUCTURED|HDR_PHRASE },    /* Not exactly correct .. */
+   { "Sender",     HDR_STRUCTURED|HDR_PHRASE },    /* Not exactly correct .. */
+   { "Resent-Reply-To", HDR_STRUCTURED|HDR_PHRASE },/* Not exactly correct .. */
+   { "Resent-From",     HDR_STRUCTURED|HDR_PHRASE },/* Not exactly correct .. */
+   { "Resent-Sender",   HDR_STRUCTURED|HDR_PHRASE },/* Not exactly correct .. */
+   { "Date",        HDR_STRUCTURED },
+   { "Resent-Date", HDR_STRUCTURED },
+   { "To",          HDR_STRUCTURED|HDR_PHRASE }, /* Not exactly correct .. */
+   { "Resent-To",   HDR_STRUCTURED|HDR_PHRASE }, /* Not exactly correct .. */
+   { "cc",          HDR_STRUCTURED|HDR_PHRASE }, /* Not exactly correct .. */
+   { "Resent-cc",   HDR_STRUCTURED|HDR_PHRASE }, /* Not exactly correct .. */
+   { "bcc",         HDR_STRUCTURED|HDR_PHRASE }, /* Not exactly correct .. */
+   { "Resent-bcc",  HDR_STRUCTURED|HDR_PHRASE }, /* Not exactly correct .. */
+   { "Message-ID",  HDR_STRUCTURED },
+   { "Resent-Message-ID",  HDR_STRUCTURED },
+   { "In-Reply-To", HDR_STRUCTURED|HDR_PHRASE }, /* Is correct .. */
+   { "References",  HDR_STRUCTURED|HDR_PHRASE }, /* Is correct .. */
+   { "Keywords",  HDR_STRUCTURED|HDR_PHRASE },   /* Is correct :-) .. */
+   { "Encrypted", HDR_STRUCTURED },              /* Well ... */
+   /* From MIME (RFC 1521) */
+   { "MIME-Version",              HDR_STRUCTURED },     
+   { "Content-Type",              HDR_STRUCTURED },     
+   { "Content-Transfer-Encoding", HDR_STRUCTURED },
+   { "Content-ID",                HDR_STRUCTURED },     
+   { "Content-Description",       HDR_TEXT },
+   /* From RFC 1806 */
+   { "Content-Disposition",       HDR_STRUCTURED },
+   /* From RFC 1864 */
+   { "Content-MD5",               0 },
+ 
+   /* mailbox format */
+   { "Content-Length",      0 },
+   { "Status",              0 },
+ 
+   /* Sendmail */
+   { "Full-Name",           HDR_TEXT },
+   { "Return-Receipt-To",   HDR_STRUCTURED|HDR_PHRASE }, /* Not exactly correct .. */
+   { "Auto-Submitted",      HDR_STRUCTURED },
+   { "Precedence",          0 },
+ 
+ 
+   /* IDA Sendmail */
+   { "X-Charset",           0 },
+   { "X-Char-Esc",          0 },
+ 
+   /* Unknown source */
+   { "Action",              0 },
+   { "Priority",            HDR_STRUCTURED },
+   { "Expires",             HDR_STRUCTURED },
+   { "Importance",          HDR_STRUCTURED },
+   { "Sensitivity",         HDR_STRUCTURED },
+ 
+   /* Our non-standard headers */
+   { "X-ELM-OSV",                 HDR_STRUCTURED },
+   { "X-Mailer",                  HDR_TEXT },
+   { "Content-Name",              HDR_TEXT },
+   
+ 
+   /* Tailer */
+   { NULL, 0 }
+ };
+ 
+ /* Grows forever */
+ static struct hdr_list {
+   struct hdr_list * next;
+   struct header_info hdr;
+ } * extra_headers = NULL;
+ static int extra_header_count = 0;
+ 
+ PUBLIC header_ptr find_header(name, create_flag) 
+      char *name;
+      int create_flag;
+ {
+   int i;
+   struct hdr_list * walk, *last = NULL;
+ 
+   for (i = 0; header_types[i].header; i++) 
+     if (strincmp(name,header_types[i].header,STRING) == 0)
+       return &(header_types[i]);
+ 
+   for (walk = extra_headers; 
+        walk != NULL; 
+        last = walk, walk = walk -> next)
+     if (strincmp(name,walk->hdr.header,STRING) == 0)
+       return &(walk->hdr);
+   
+   if (create_flag) {
+     walk = (struct hdr_list * ) safe_malloc (sizeof(struct hdr_list));
+ 
+     if (last) last->next = walk;
+     else extra_headers   = walk;
+     extra_header_count++;
+ 
+     walk->next = NULL;
+     walk->hdr.header = strmcpy(NULL,name);
+     if (strincmp(name,"X-",2) == 0)
+       walk->hdr.flag = HDR_TEXT;     /* Default for user defined headers */
+     else
+       walk->hdr.flag = 0;            /* We don't know it, right? */
+ 
+     return &(walk->hdr);
+   }
+   
+   return NULL;
+ }
+ 
+ PUBLIC int classify_header(name)
+      char *name;
+ {
+   header_ptr P = find_header(name,0);
+ 
+   if (P)
+     return P->flag;
+ 
+   if (strincmp(name,"X-",2) == 0)
+     return HDR_TEXT;              /* Default for user defined headers */
+ 
+   return 0;
+ }
+ 
+ long skip_envelope(hdr, fp)
+      struct header_rec *hdr;
+      FILE *fp;
+ {
+   char buf[STRING];
+   int tmp;
+ 
+   long result = hdr->offset;
+ 
+   if (0 !=  fseek(fp,hdr->offset,SEEK_SET)) {
+     error1("Failed to seek beginning of mail envelope (%ld)",hdr->offset);
+     sleep_message();
+     dprint(9,(debugfile,"skip_envelope=-1 (fseek error)\n"));
+ 
+     return -1;
+   }
+ 
+   dprint(9,(debugfile,"skip_envelope: scanning offset: %ld\n",
+ 	    result));;
+ 
+   while (0 < (tmp = mail_gets(buf,sizeof(buf),fp))) {
+     dprint(9,(debugfile,"skip_envelope: len=%d, got: %s\n",tmp,buf));
+ #ifdef MMDF
+     if (0 == strcmp(buf,MSG_SEPARATOR))
+       continue;
+ #endif
+     if (0 == strncmp(buf,"From ",5))
+       continue;
+     break;
+   }
+   result = ftell(fp) - tmp;
+ 
+   dprint(9,(debugfile,"skip_envelope: beginning of headers=%ld\n",result));
+   if (0 !=  fseek(fp,result,SEEK_SET)) {
+     error1("Failed to seek beginning of mail headers (%ld)",result);
+     sleep_message();
+     dprint(9,(debugfile,"skip_envelope=-1 (fseek error)\n"));
+     return -1;
+   }
+ 
+   dprint(9,(debugfile,"skip_envelope=%ld\n",result));
+   return result;
+ }
+ 
+ PUBLIC header_list_ptr locate_header(h,n)
+      header_list_ptr h;
+      header_ptr n;
+ {
+   header_list_ptr walk;
+ 
+   for (walk = h; 
+        walk != NULL; 
+        walk = walk -> next_other_header) {
+     if (walk -> magic != HEADER_magic)
+       header_panic(__FILE__,__LINE__,"locate_header",
+ 		   "Bad magic number");
+     if (n == walk -> header_name)
+       return walk;
+   }
+   return NULL;
+ }
+ 
+ PUBLIC header_list_ptr file_read_headers(fp, flag) 
+      FILE * fp;
+      int flag;
+ {
+   in_state_t state;
+   header_list_ptr result;
+ 
+   in_state_clear(&state,STATE_in_file);
+ 
+   set_in_state_file(fp,&state);
+ 
+   result = state_read_headers(&state, flag);
+ 
+   in_state_destroy(&state);
+ 
+   return result;
+ }
+ 
+ PUBLIC header_list_ptr state_read_headers(s, flag) 
+      in_state_t * s;
+      int flag;
+ {
+   char buffer[32*1024+1];
+   int size;
+ 
+   header_list_ptr result = NULL, last = NULL;
+ 
+   while (size = state_read_hdr_line(s,buffer,sizeof buffer,
+ 				    RHL_CHECK_HEADER|flag) > 0) {
+     header_list_ptr item, last_this = NULL, walk;
+     char * k;
+     if (0 == strcmp(buffer,"\n"))
+       break;
+     k = strchr(buffer,':');
+     if (!k)
+       break;
+     *k = '\0';
+     k++;
+     item = (struct header_list *) safe_malloc(sizeof (struct header_list));
+     item -> header_name = find_header(buffer,1);
+     
+     item -> next_header       = NULL;
+     item -> next_this_header  = NULL;
+     item -> next_other_header = NULL;
+     item -> body              = strmcpy(NULL,k);
+     item -> magic             = HEADER_magic;
+     
+     for (walk = result; 
+ 	 walk != NULL; 
+ 	 last = walk, walk = walk -> next_other_header) {
+       if (walk -> magic != HEADER_magic)
+ 	header_panic(__FILE__,__LINE__,"state_read_headers",
+ 		     "Bad magic number");
+       if (item -> header_name == walk -> header_name)
+ 	break;
+     }
+ 
+     if (last) last -> next_header = item;
+     else      result              = item;
+ 
+     if (walk) {  
+       while (walk->next_this_header != NULL) {
+ 	if (walk -> magic != HEADER_magic)
+ 	  header_panic(__FILE__,__LINE__,"state_read_headers",
+ 		       "Bad magic number");
+ 	walk = walk->next_this_header;
+       }
+ 
+       walk->next_this_header = item;
+     } else if (last) {
+       last -> next_other_header = item;
+     }
+   }
+   return result;
+ }
+ 
+ PUBLIC void delete_headers(hdr)
+      header_list_ptr hdr;
+ {
+   header_list_ptr next = hdr;
+   
+   while(next) {
+     if (next -> magic != HEADER_magic)
+       header_panic(__FILE__,__LINE__,"delete_headers","Bad magic number");
+ 
+     hdr  = next;
+     next = next -> next_header;
+ 
+     if(hdr -> body) {
+       free(hdr -> body);
+       hdr -> body = NULL;
+     }
+     hdr -> next_header       = NULL;
+     hdr -> next_this_header  = NULL;
+     hdr -> next_other_header = NULL;
+     hdr -> magic             = NULL;
+     free((void *)hdr);
+   }
+ }
+ 
+ PUBLIC int NULL_header_filter(hdr,flag)
+      header_list_ptr hdr;
+      int flag;
+ {
+   if (hdr -> magic != HEADER_magic)
+     header_panic(__FILE__,__LINE__,"NULL_header_filter","Bad magic number");
+ 
+   flag++;      /* So that flag is used */
+   return 1;
+ }
+ 
+ PUBLIC void NULL_header_converter (hdr,flag,buffer,size)
+      header_list_ptr hdr;
+      int flag;
+      char *buffer;
+      int size;
+ {
+   if (hdr -> magic != HEADER_magic)
+     header_panic(__FILE__,__LINE__,"NULL_header_converter","Bad magic number");
+ 
+   flag++;      /* So that flag is used */
+   
+   if (hdr->body)
+     strfcpy(buffer,hdr->body,size);
+   else
+     buffer[0] = '\0';
+ }
+ 
+ PUBLIC void state_write_headers(s,hdr,filter,convert,flag) 
+      out_state_t * s;
+      header_list_ptr hdr;
+      header_filter    * filter;
+      header_converter * convert;
+      int                flag;
+ {
+   header_list_ptr next = hdr;
+   
+   for (next = hdr; next; next = next -> next_header) {
+     char buffer [ 32 * 1024 + 1], *ptr;
+     if (next -> magic != HEADER_magic)
+       header_panic(__FILE__,__LINE__,"state_write_headers",
+ 		   "Bad magic number");
+ 
+     if (!filter(next,flag))
+       continue;
+ 
+     buffer[0] = '\0';
+ 
+     convert(next,flag,buffer,sizeof buffer);
+     
+     buffer[sizeof buffer -1] = '\0';
+ 
+     state_add_prefix(s);
+     state_puts(next->header_name->header,s);
+     state_puts(": ",s);
+ 
+     for (ptr = strtok(buffer,"\n"); ptr; ptr = strtok(NULL,"\n")) { 
+       if (ptr > buffer) { /* Do folding */
+ 	--ptr;
+ 	if (*(ptr+1) == ' ')
+ 	  *ptr = ' ';
+ 	else
+ 	  *ptr = '\t';
+ 	state_putc('\n',s);
+ 	state_add_prefix(s);
+       }
+       state_puts(ptr,s);
+     }
+     state_putc('\n',s);
+   }
+ }
+ 
Index: WORK/src/mkhdrs.c
*** elm2.4.25/src/mkhdrs.c	Sat May  8 23:25:44 1993
--- WORK/src/mkhdrs.c	Thu Aug  8 22:39:50 1996
***************
*** 44,63 ****
  int msg;
  {
  	/** Generate an 'in-reply-to' message... **/
! 	char buffer[SLEN], date_buf[SLEN];
  
- 
  	if (msg == -1)		/* not a reply! */
  	  in_reply_to[0] = '\0';
  	else {
  	  if (chloc(headers[msg]->from, '!') != -1)
  	    tail_of(headers[msg]->from, buffer, 0);
! 	  else
! 	    strcpy(buffer, headers[msg]->from);
! 	  sprintf(in_reply_to, "%s from \"%s\" at %s",
!                   headers[msg]->messageid[0] == '\0'? "<no.id>":
  		  headers[msg]->messageid,
! 		  buffer,
  		  elm_date_str(date_buf, headers[msg]->time_sent + headers[msg]->tz_offset));
  	}
  }
--- 44,91 ----
  int msg;
  {
  	/** Generate an 'in-reply-to' message... **/
! 	char buffer[SLEN], date_buf[SLEN], buffer2[SLEN],*c,*d;
! 	int q = 0;
  
  	if (msg == -1)		/* not a reply! */
  	  in_reply_to[0] = '\0';
  	else {
  	  if (chloc(headers[msg]->from, '!') != -1)
  	    tail_of(headers[msg]->from, buffer, 0);
! 	  else {
! 	      strfcpy(buffer, headers[msg]->from, sizeof(buffer));	  
! #ifdef MIME
! 	      if (!(headers[msg] -> status & NOHDRENCODING) 
! 		  && is_rfc1522 (buffer))
! 		rfc1522_decode (buffer, sizeof (buffer));
! 	      /* We will encode in-reply-to header later.
! 	       * But we need now fullname to be decoded, because
! 	       * RFC 1522 encoded words are not recocgnized inside
! 	       * of quotes and we put fullname inside of quotes
! 	       */
! #endif
! 	  }
! 	  /* Remove unquoted " -characters from buffer.
! 	   *
! 	   * - K E H <hurtta@dionysos.FMI.FI>
! 	   */
! 	  for (c = buffer, d=buffer2; '\0' != *c; c++) {
! 	    if (q) {
! 	      *d++ = '\\';
! 	      *d++ = *c;
! 	      q = 0;
! 	    } else if ('\\' == *c) {
! 	      q = 1;
! 	    } else if ('"' != *c) {
! 	      *d++ = *c;
! 	    }
! 	  }
! 	  *d = '\0';
! 
! 	  sprintf(in_reply_to, "%s%s \"%s\" at \"%s\"",
  		  headers[msg]->messageid,
! 		  headers[msg]->messageid[0] ? " from" : "From",
! 		  buffer2,
  		  elm_date_str(date_buf, headers[msg]->time_sent + headers[msg]->tz_offset));
  	}
  }
Index: WORK/src/newmbox.c
*** elm2.4.25/src/newmbox.c	Mon Dec  4 17:50:56 1995
--- WORK/src/newmbox.c	Sun Aug 11 18:23:10 1996
***************
*** 202,207 ****
--- 202,209 ----
  #include <sys/stat.h>
  #include <errno.h>
  
+ #include "me.h"   /* for defination of null_decode and text_decode */
+ 
  #ifdef I_TIME
  #  include <time.h>
  #endif
***************
*** 218,223 ****
--- 220,227 ----
  extern long atol();
  #endif
  
+ static int read_headers P_((int));   /* Prototype */
+ 
  int
  newmbox(new_file, adds_only)
  char *new_file;
***************
*** 243,248 ****
--- 247,254 ----
  	int err;
  	char new_tempfile[SLEN];
  
+ reread:
+ 
  	/* determine type of new mailfile and calculate temp file name */
  	if((new_folder_type = get_folder_type(new_file)) == SPOOL)
  	  mk_temp_mail_fn(new_tempfile, new_file);
***************
*** 268,278 ****
  	    Centerline(18, catgets(elm_msg_cat, ElmSet, ElmAlreadyRunning3,
  		"If this is in error, then you'll need to remove the following file:"));
  	    Centerline(19, new_tempfile);
! 	    MoveCursor(LINES, 0);  /* so shell prompt upon exit is on newline */
  	    silently_exit();
  	  }
  	}
  
  	/* If we were reading a spool file and we are not just reading
  	 * in the additional new messages to the same file, we need to
  	 * remove the corresponding tempfile.
--- 274,296 ----
  	    Centerline(18, catgets(elm_msg_cat, ElmSet, ElmAlreadyRunning3,
  		"If this is in error, then you'll need to remove the following file:"));
  	    Centerline(19, new_tempfile);
! 	    MoveCursor(elm_LINES, 0);  /* so shell prompt upon exit is on newline */
  	    silently_exit();
  	  }
  	}
  
+ 
+ 	if (message_count == 0 && adds_only) {
+ 	  dprint(1, (debugfile, 
+ 		     "newmbox: message_count == 0 -- clearing adds_only flag.\n"));
+ 	  /* Clearing adds_only flag so temp folder gets created
+ 	   * It was not created in first call if mailfile was not
+ 	   * existing...
+ 	   */
+ 	  adds_only = FALSE;
+ 	}
+ 
+ 
  	/* If we were reading a spool file and we are not just reading
  	 * in the additional new messages to the same file, we need to
  	 * remove the corresponding tempfile.
***************
*** 285,290 ****
--- 303,312 ----
  		"Sorry, can't unlink the temp file %s [%s]!\n\r"),
  	        cur_tempfolder, error_description(errno));
  	      silently_exit();
+ 	    } else {
+ 	      dprint(1, (debugfile, 
+ 			 "newmbox: Unlinking tempfile (%s).\n",
+ 			 cur_tempfolder));
  	    }
  	  }
  	}
***************
*** 303,309 ****
  	if ((mailfile = fopen(cur_folder,"r")) == NULL)  {
  	  if (errno != ENOENT ) { /* error on anything but file not exist */
  	    err = errno;
! 	    MoveCursor(LINES,0);
  	    Raw(OFF);
  	    printf(catgets(elm_msg_cat, ElmSet, ElmFailOnOpenNewmbox,
  		    "\nfail on open in newmbox, open %s failed!!\n"),
--- 325,331 ----
  	if ((mailfile = fopen(cur_folder,"r")) == NULL)  {
  	  if (errno != ENOENT ) { /* error on anything but file not exist */
  	    err = errno;
! 	    MoveCursor(elm_LINES,0);
  	    Raw(OFF);
  	    printf(catgets(elm_msg_cat, ElmSet, ElmFailOnOpenNewmbox,
  		    "\nfail on open in newmbox, open %s failed!!\n"),
***************
*** 320,325 ****
--- 342,363 ----
  	  }
  	} else {                          /* folder exists, read headers */
  	  read_headers(adds_only);
+ 	  if (ferror(mailfile)) {
+ 	    dprint(1, (debugfile, "error when reading mailfile: %s\n",
+ 		       cur_folder));
+ 	    error1("Error when reading: %s",cur_folder);
+ 	    sleep_message();
+ 	    if (*def_ans_yes == want_to ("Error when reading! Reread folder?",
+ 					 *def_ans_yes,elm_LINES,0)) {
+ 	      adds_only = FALSE;
+ 
+ 	      dprint(1, (debugfile, "rereading mailfile: %s\n",
+ 			 cur_folder));
+ 	      goto reread;
+ 	    }
+ 					 
+ 	    rm_temps_exit();
+ 	  }
  	}
  
  	if(!same_file)		/* limit mode off if this is a new file */
***************
*** 347,356 ****
  	 **/
  
  	char *last_slash;
  
  	/* if filename is null or is of zero length */
! 	if((filename == NULL) || (*filename == '\0'))
  	  return(NO_NAME);
  
  	/* if filename begins with mailhome,
  	 * and there is a slash in filename,
--- 385,401 ----
  	 **/
  
  	char *last_slash;
+ 	struct stat    buf;		/* stat command  */
  
  	/* if filename is null or is of zero length */
! 	if((filename == NULL) || (*filename == '\0')) {
! 	  dprint(8, (debugfile, 
! 		     "get_folder_type=NO_NAME: no filename\n"));
  	  return(NO_NAME);
+ 	}
+ 
+ 	dprint(8, (debugfile, 
+ 		   "get_folder_type: filename=%s\n",filename));
  
  	/* if filename begins with mailhome,
  	 * and there is a slash in filename,
***************
*** 361,399 ****
  	if((first_word(filename, mailhome)) &&
  	  ((last_slash = rindex(filename, '/')) != NULL) &&
  	  (*(last_slash+1) != '\0') &&
! 	  (filename + strlen(mailhome) - 1 == last_slash))
! 	    return(SPOOL);
  	/* if file name == default mailbox, its a spool file also
  	 * even if its not in the spool directory. (SVR4)
  	 */
! 	if (strcmp(filename, defaultfile) == 0)
  	    return(SPOOL);
  
  	return(NON_SPOOL);
  }
  
  mk_temp_mail_fn(tempfn, mbox)
  char *tempfn, *mbox;
  {
! 	/** create in tempfn the name of the temp file corresponding to
! 	    mailfile mbox. Mbox is presumed to be a file in mailhome;
! 	    Strangeness may result if it is not!
! 	 **/
  
! 	char *cp;
  
! 	sprintf(tempfn, "%s%s", default_temp, temp_mbox);
! 	if((cp = rindex(mbox, '/')) != NULL) {
! 	  cp++;
! 	  if (strcmp(cp, "mbox") == 0 || strcmp(cp, "mailbox") == 0 ||
! 		strcmp(cp, "inbox") == 0 || *cp == '.')
! 	    strcat(tempfn, username);
! 	  else
! 	    strcat(tempfn, cp);
! 	}
  }
  
! int
  read_headers(add_new_only)
  int add_new_only;
  {
--- 406,632 ----
  	if((first_word(filename, mailhome)) &&
  	  ((last_slash = rindex(filename, '/')) != NULL) &&
  	  (*(last_slash+1) != '\0') &&
! 	  (filename + strlen(mailhome) - 1 == last_slash)) {
! 	  dprint(8, (debugfile, 
! 		     "get_folder_type=SPOOL\n"));
! 	  return(SPOOL);
! 	}
  	/* if file name == default mailbox, its a spool file also
  	 * even if its not in the spool directory. (SVR4)
  	 */
! 	if (strcmp(filename, defaultfile) == 0) {
! 	  dprint(8, (debugfile, 
! 		     "get_folder_type=SPOOL\n"));
! 	  return(SPOOL);
! 	  }
!         if (stat(filename, &buf) != 0) {
! 	  int err = errno;
! 	  dprint(8, (debugfile, 
! 		     "get_folder_type: errno %s attempting to stat file %s\n", 
! 		     error_description(err), filename));
! 	} else {
! 	  if (buf.st_mode & 07000) { 
! 	    /* is 'SPOOL' file is special modes set */
! 	    dprint(8, (debugfile, 
! 		       "get_folder_type=SPOOL; mode=%05o\n",buf.st_mode));
  	    return(SPOOL);
+ 	  }
+ 	}
  
+ 	dprint(8, (debugfile, 
+ 		   "get_folder_type=NON_SPOOL\n"));
  	return(NON_SPOOL);
  }
  
+ static int same_file P_((char *,char *)); /* Prototype */
+ 
+ static int same_file(name1,name2)
+      char *name1, *name2;
+ {
+   struct stat buf1, buf2;
+   
+   if (0 == strcmp(name1,name2))
+     return TRUE;
+ 
+   if (stat(name1, &buf1) != 0) {
+     int err = errno;
+     dprint(8, (debugfile, 
+ 	       "same_file=FALSE: errno %s attempting to stat file %s\n", 
+ 	       error_description(err), name1));
+     return FALSE;
+   }
+ 
+   if (stat(name2, &buf2) != 0) {
+     int err = errno;
+     dprint(8, (debugfile, 
+ 	       "same_file=FALSE: errno %s attempting to stat file %s\n", 
+ 	       error_description(err), name2));
+     return FALSE;
+   }
+ 
+   if (buf1.st_ino == buf2.st_ino && buf1.st_dev == buf2.st_dev) {
+     dprint(8, (debugfile, 
+ 	       "same_file(%s,%s)=TRUE\n",name1,name2)); 
+     return TRUE;
+   }
+   dprint(8, (debugfile, 
+ 	     "same_file(%s,%s)=FALSE\n",name1,name2)); 
+   return FALSE;
+ }
+ 
  mk_temp_mail_fn(tempfn, mbox)
  char *tempfn, *mbox;
  {
!   /** create in tempfn the name of the temp file corresponding to
!     mailfile mbox. 
!     **/
!   
!   char *cp,*ptr;
!   int in_spool = first_word(mbox, mailhome);
! 
!   dprint(8,(debugfile,"mk_temp_mail_fn: in_spool=%d, mbox=%s\n",
! 	    in_spool,mbox));
! 	       
!   if (strlen(default_temp) + strlen(temp_mbox) > SLEN-1) {
!     dprint(1,(debugfile,"mk_temp_mail_fn: Too long path!\n"));
!     strcpy(tempfn,"TEMP_MBOX");
!     return;
!   }
! 
!   sprintf(tempfn, "%s%s", default_temp, temp_mbox);
!   
!   if((cp = rindex(mbox, '/')) != NULL) {    
!     cp++;
!     if (strcmp(cp, "mbox") == 0 || strcmp(cp, "mailbox") == 0 ||
! 	strcmp(cp, "inbox") == 0 || *cp == '.') {
!       ptr = username;
!     }
!     else {
!       ptr = cp;
!     }
!   } else {
!     ptr = mbox;
!   }
! 
!   if (strlen(tempfn) + strlen(ptr) > SLEN-1) {
!     dprint(1,(debugfile,
! 	      "mk_temp_mail_fn: Too long path or mailbox!\n"));
!   } else
!     strcat(tempfn, ptr);
! 
! 
!   if (!in_spool) {
!     char tempname[SLEN];
!     if (strlen(mailhome) + strlen(ptr) > SLEN-1) {
!       dprint(1,(debugfile,
! 		"mk_temp_mail_fn: Too long path or mailbox!\n"));
!     } else {
!       sprintf(tempname,"%s%s",mailhome,ptr);
!       
!       if (same_file(tempname,mbox))
! 	in_spool = TRUE;
!       dprint(8,(debugfile,"mk_temp_mail_fn: in_spool=%d, tempname=%s\n",
! 		in_spool,tempname));
!     }
!     
!   }
! 
!   
!   if (!in_spool) {
!     /* Assume that this is user's incoming mail area */
!     if (strlen(tempfn) + strlen(username) > SLEN-2) {
!       dprint(1,(debugfile,
! 		"mk_temp_mail_fn: Too long path or username!\n"));
!     } else
!       strcat(tempfn, "-");
!     strcat(tempfn, username);
!   }
!   dprint(8,(debugfile,"mk_temp_mail_fn: tempfname=%s\n",tempfn));
! }
  
! void header_zero(h)
!      struct header_rec *h;
! {
!   static time_t now = 0;
!   if (0 == now) now = time(NULL);
  
!   h->lines            = 0;
!   h->status           = 0;
!   h->encrypted        = 0;
!   h->exit_disposition = 0;
!   h->status_chgd      = 0;
!   h->content_length   = -1;
!   h->offset           = -1;
!   h->received_time    = now;
!   h->from[0]          = '\0';
!   h->to[0]            = '\0';
!   h->cc[0]            = '\0';
!   h->messageid[0]     = '\0';
!   h->time_zone[0]     = '\0';
!   h->time_menu[0]     = '\0';
!   h->tz_offset        = 0;
!   h->subject[0]       = '\0';
!   h->mailx_status[0]  = '\0';
! #ifdef MIME
!   mime_t_zero (&(h->mime_rec));
! #endif
! #ifdef USE_PGP
!   h->pgp              = 0;
! #endif
!   h->binary           = 0;
  }
  
! #ifdef MIME
! 
! PUBLIC int is_pre_mime_content_type (ptr,content_type)
!      mime_t *ptr;
!      char *content_type;
! {
!   int result;
!   char *cptr = strpbrk(content_type,"/;()");
! 
!   dprint(12,(debugfile,"is_pre_mime_content_type(): content_type=%s\n",
! 	     content_type));
!   
!   if (!cptr || ';' == *cptr) {
!     char *ptr2;
!     char *tmp = content_type;
!     while (whitespace(*tmp))
!       tmp++;
!     
!     if (cptr)
!       *cptr = '\0';
!     
!     ptr2 = strpbrk(tmp," \t");
!     if (ptr2)
!       *ptr2 = '\0';
! 
!     if (istrcmp(tmp,"text")!=0) {
!       char buf[STRING];
!       ptr -> notplain = TRUE;
! 
!       /* Put some 'intelligent' value */
!       ptr ->type = MIME_TYPE_APPLICATION;
!       sprintf(buf,"X-RFC1049-%.30s",tmp);
!       strfcpy(ptr->subtype,buf,sizeof(ptr->subtype));
!     } else {
!       ptr -> notplain = FALSE;
!       ptr ->type = MIME_TYPE_TEXT;
!       strfcpy(ptr->subtype,"plain",sizeof(ptr->subtype));
!     }
!     result = 1;
!   } else 
!     result = 0;
! 
!   dprint(12,(debugfile,"is_pre_mime_content_type=%d\n",result));
! 
!   return result;
! }
! 
! #endif
! 
! 
! static int
  read_headers(add_new_only)
  int add_new_only;
  {
***************
*** 417,438 ****
  	  subj = 0, copyit = 0, in_header = FALSE;
  	int count_x, count_y = 17, err;
  	int in_to_list = FALSE, forwarding_mail = FALSE, first_line = TRUE,
! 	  content_length_found = FALSE;
  
  	static int first_read = 0;
  #ifdef MMDF
          int newheader = 0;
  #endif /* MMDF */
  
  	if (folder_type == SPOOL) {
  	  lock(INCOMING);	/* ensure no mail arrives while we do this! */
  	  if (! add_new_only) {
! 	    if ( (temp_handle = open(cur_tempfolder, O_RDWR|O_CREAT|O_EXCL)) == -1) {
  	      /* Hey!  What the hell is this?  The temp file already exists? */
  	      /* Looks like a potential clash of processes on the same file! */
  
- 	      fflush (mailfile);
- 
  	      unlock();				     /* so remove lock file! */
  	      error(catgets(elm_msg_cat, ElmSet, ElmWhatsThisTempExists,
  		"What's this?  The temp folder already exists??"));
--- 650,677 ----
  	  subj = 0, copyit = 0, in_header = FALSE;
  	int count_x, count_y = 17, err;
  	int in_to_list = FALSE, forwarding_mail = FALSE, first_line = TRUE,
! 	  content_length_found = FALSE, in_cc_list = FALSE;
! 	char Subject[VERY_LONG_STRING];
  
  	static int first_read = 0;
  #ifdef MMDF
          int newheader = 0;
  #endif /* MMDF */
+ #ifdef MIME
+ 	int is_content = 0;
+ 	char content_type[VERY_LONG_STRING];
+ #endif
+ 	int in_subject = 0;
+ 	Subject[0] = 0;
  
  	if (folder_type == SPOOL) {
  	  lock(INCOMING);	/* ensure no mail arrives while we do this! */
  	  if (! add_new_only) {
! 	    if ( (temp_handle = open(cur_tempfolder, O_RDWR|O_CREAT|O_EXCL,
! 				     0600)) == -1) {
  	      /* Hey!  What the hell is this?  The temp file already exists? */
  	      /* Looks like a potential clash of processes on the same file! */
  
  	      unlock();				     /* so remove lock file! */
  	      error(catgets(elm_msg_cat, ElmSet, ElmWhatsThisTempExists,
  		"What's this?  The temp folder already exists??"));
***************
*** 441,454 ****
  	      error(catgets(elm_msg_cat, ElmSet, ElmIGiveUp,
  		"Ahhhh... I give up."));
  	      silently_exit();	/* leave without tampering with it! */
  	    }
  	    if ((temp = fdopen(temp_handle,"w")) == NULL) {
  
- 	     fflush (mailfile);
- 
  	     err = errno;
  	     unlock();	/* remove lock file! */
! 	     MoveCursor(LINES, 0);
  	     Raw(OFF);
  	     printf(catgets(elm_msg_cat, ElmSet, ElmCouldntOpenForTemp,
  		     "\nCouldn't open file %s for use as temp file.\n"),
--- 680,696 ----
  	      error(catgets(elm_msg_cat, ElmSet, ElmIGiveUp,
  		"Ahhhh... I give up."));
  	      silently_exit();	/* leave without tampering with it! */
+ 	    } else {
+ 	      dprint(1, (debugfile, 
+ 			 "read_headers: Creating tempfile (%s).\n",
+ 			 cur_tempfolder));
  	    }
  	    if ((temp = fdopen(temp_handle,"w")) == NULL) {
  
  	     err = errno;
+ 	     close(temp_handle);   /* - K E H */
  	     unlock();	/* remove lock file! */
! 	     MoveCursor(elm_LINES, 0);
  	     Raw(OFF);
  	     printf(catgets(elm_msg_cat, ElmSet, ElmCouldntOpenForTemp,
  		     "\nCouldn't open file %s for use as temp file.\n"),
***************
*** 477,486 ****
  	   if ((temp = fopen(cur_tempfolder,"r+")) == NULL) {
  	     err = errno;
  
- 	     fflush (mailfile);
- 
  	     unlock();	/* remove lock file! */
! 	     MoveCursor(LINES,0);
  	     Raw(OFF);
  	     printf(catgets(elm_msg_cat, ElmSet, ElmCouldntReopenForTemp,
  		     "\nCouldn't reopen file %s for use as temp file.\n"),
--- 719,726 ----
  	   if ((temp = fopen(cur_tempfolder,"r+")) == NULL) {
  	     err = errno;
  
  	     unlock();	/* remove lock file! */
! 	     MoveCursor(elm_LINES,0);
  	     Raw(OFF);
  	     printf(catgets(elm_msg_cat, ElmSet, ElmCouldntReopenForTemp,
  		     "\nCouldn't reopen file %s for use as temp file.\n"),
***************
*** 494,504 ****
  	   if (fseek(temp, 0, 2) == -1) {
  	     err = errno;
  
- 	     fflush (mailfile);
- 
  	     unlock();	/* remove lock file! */
  	     fclose(temp);
! 	     MoveCursor(LINES,0);
  	     Raw(OFF);
  	     printf(catgets(elm_msg_cat, ElmSet, ElmCouldntSeekTempEnd,
  		     "\nCouldn't fseek to end of reopened temp mbox.\n"));
--- 734,742 ----
  	   if (fseek(temp, 0, 2) == -1) {
  	     err = errno;
  
  	     unlock();	/* remove lock file! */
  	     fclose(temp);
! 	     MoveCursor(elm_LINES,0);
  	     Raw(OFF);
  	     printf(catgets(elm_msg_cat, ElmSet, ElmCouldntSeekTempEnd,
  		     "\nCouldn't fseek to end of reopened temp mbox.\n"));
***************
*** 513,540 ****
  	}
  
  	if (! first_read++) {
! 	  ClearLine(LINES-1);
! 	  ClearLine(LINES);
  	  if (add_new_only)
! 	    PutLine2(LINES, 0, catgets(elm_msg_cat, ElmSet, ElmReadingInMessage,
! 		     "Reading in %s, message: %d"),
  		     cur_folder, message_count);
  	  else
! 	    PutLine1(LINES, 0, catgets(elm_msg_cat, ElmSet, ElmReadingInMessage0,
! 		     "Reading in %s, message: 0"), cur_folder);
! 	  count_x = LINES;
            count_y = 22 + strlen(cur_folder);
  	}
  	else {
! 	  count_x = LINES-2;
! 	  PutLine0(LINES-2, 0, catgets(elm_msg_cat, ElmSet, ElmReadingMessage0,
! 		"Reading message: 0"));
  	}
  
  	if (add_new_only) {
! 	   if (fseek(mailfile, mailfile_size, 0) == -1) {
  	     err = errno;
! 	     MoveCursor(LINES, 0);
  	     Raw(OFF);
  	     MCprintf(catgets(elm_msg_cat, ElmSet, ElmCouldntSeekEndFolder,
  		"\nCouldn't seek to %ld (end of folder) in %s!\n"),
--- 751,782 ----
  	}
  
  	if (! first_read++) {
! 	  ClearLine(elm_LINES-1);
! 	  ClearLine(elm_LINES);
  	  if (add_new_only)
! 	    PutLine2(elm_LINES, 0, catgets(elm_msg_cat, ElmSet, 
! 					   ElmReadingInMessage,
! 					   "Reading in %s, message: %d"),
  		     cur_folder, message_count);
  	  else
! 	    PutLine1(elm_LINES, 0, catgets(elm_msg_cat, ElmSet, 
! 					   ElmReadingInMessage0,
! 					   "Reading in %s, message: 0"), 
! 		     cur_folder);
! 	  count_x = elm_LINES;
            count_y = 22 + strlen(cur_folder);
  	}
  	else {
! 	  count_x = elm_LINES-2;
! 	  PutLine0(elm_LINES-2, 0, catgets(elm_msg_cat, ElmSet, 
! 					   ElmReadingMessage0,
! 					   "Reading message: 0"));
  	}
  
  	if (add_new_only) {
! 	   if (fseek(mailfile, mailfile_size, SEEK_SET) == -1) {
  	     err = errno;
! 	     MoveCursor(elm_LINES, 0);
  	     Raw(OFF);
  	     MCprintf(catgets(elm_msg_cat, ElmSet, ElmCouldntSeekEndFolder,
  		"\nCouldn't seek to %ld (end of folder) in %s!\n"),
***************
*** 551,557 ****
  
  	/** find the size of the folder then unlock the file **/
  
- 	fflush (mailfile);
  	mailfile_size = bytes(cur_folder);
  	unlock();
  
--- 793,798 ----
***************
*** 565,571 ****
  	  if (copyit)
  	    if (fwrite(buffer, 1, line_bytes, temp) != line_bytes) {
  		err = errno;
! 		MoveCursor(LINES, 0);
  		Raw(OFF);
  		printf(catgets(elm_msg_cat, ElmSet, ElmWriteToTempFailed,
  				"\nWrite to temp file %s failed!!\n"),
--- 806,812 ----
  	  if (copyit)
  	    if (fwrite(buffer, 1, line_bytes, temp) != line_bytes) {
  		err = errno;
! 		MoveCursor(elm_LINES, 0);
  		Raw(OFF);
  		printf(catgets(elm_msg_cat, ElmSet, ElmWriteToTempFailed,
  				"\nWrite to temp file %s failed!!\n"),
***************
*** 608,614 ****
  #else
  	    if (! first_word(buffer, "From ") && !forwarding_mail) {
  #endif /* MMDF */
! 	      MoveCursor(LINES,0);
  	      Raw(OFF);
  	      printf(catgets(elm_msg_cat, ElmSet, ElmFolderCorrupt,
  		  "\nFolder is corrupt!!  I can't read it!!\n\n"));
--- 849,855 ----
  #else
  	    if (! first_word(buffer, "From ") && !forwarding_mail) {
  #endif /* MMDF */
! 	      MoveCursor(elm_LINES,0);
  	      Raw(OFF);
  	      printf(catgets(elm_msg_cat, ElmSet, ElmFolderCorrupt,
  		  "\nFolder is corrupt!!  I can't read it!!\n\n"));
***************
*** 644,650 ****
  			new_max * sizeof(struct header_rec *));
  		}
  		if (new_headers == NULL) {
! 	          MoveCursor(LINES,0);
  	          Raw(OFF);
  		  printf(catgets(elm_msg_cat, ElmSet, ElmCouldntAllocMemory,
  	"\n\nCouldn't allocate enough memory! Message #%d.\n\n"),
--- 885,891 ----
  			new_max * sizeof(struct header_rec *));
  		}
  		if (new_headers == NULL) {
! 	          MoveCursor(elm_LINES,0);
  	          Raw(OFF);
  		  printf(catgets(elm_msg_cat, ElmSet, ElmCouldntAllocMemory,
  	"\n\nCouldn't allocate enough memory! Message #%d.\n\n"),
***************
*** 663,669 ****
  
  		if ((h = (struct header_rec *)
  			  malloc(sizeof(struct header_rec))) == NULL) {
! 	          MoveCursor(LINES,0);
  	          Raw(OFF);
  		  printf(catgets(elm_msg_cat, ElmSet, ElmCouldntAllocMemory,
  	"\n\nCouldn't allocate enough memory! Message #%d.\n\n"),
--- 904,910 ----
  
  		if ((h = (struct header_rec *)
  			  malloc(sizeof(struct header_rec))) == NULL) {
! 	          MoveCursor(elm_LINES,0);
  	          Raw(OFF);
  		  printf(catgets(elm_msg_cat, ElmSet, ElmCouldntAllocMemory,
  	"\n\nCouldn't allocate enough memory! Message #%d.\n\n"),
***************
*** 670,675 ****
--- 911,917 ----
  			  count);
  		  leave(0);
  		}
+ 		header_zero(h);
  		headers[count] = h;
  	      }
  
***************
*** 686,706 ****
  		current_header->content_length = -1; /* not found yet */
  		current_header->index_number = count+1;
  		content_length_found = FALSE;
- 		/* set default status - always 'visible'  - and
- 		 * if a spool file, presume 'new', otherwise
- 		 * 'read', for the time being until overridden
- 		 * by a Status: header.
- 		 * We presume 'read' for nonspool mailfile messages
- 		 * to be compatible messages stored with older versions of elm,
- 		 * which didn't support a Status: header.
- 		 */
- 		if(folder_type == SPOOL)
- 		  current_header->status = VISIBLE | NEW | UNREAD;
- 		else
- 		  current_header->status = VISIBLE;
  
  		strcpy(current_header->subject, "");	/* clear subj    */
  		strcpy(current_header->to, "");		/* clear to    */
  		strcpy(current_header->mailx_status, "");	/* clear status flags */
  		strcpy(current_header->time_menu, "");	/* clear menu date */
  		strcpy(current_header->messageid, "<no.id>"); /* set no id into message id */
--- 928,940 ----
  		current_header->content_length = -1; /* not found yet */
  		current_header->index_number = count+1;
  		content_length_found = FALSE;
  
+ 		current_header->status = VISIBLE | NEW | UNREAD;
+ 
  		strcpy(current_header->subject, "");	/* clear subj    */
+ 		strcpy(Subject,"");
  		strcpy(current_header->to, "");		/* clear to    */
+ 		strcpy(current_header->cc, "");
  		strcpy(current_header->mailx_status, "");	/* clear status flags */
  		strcpy(current_header->time_menu, "");	/* clear menu date */
  		strcpy(current_header->messageid, "<no.id>"); /* set no id into message id */
***************
*** 707,713 ****
  		current_header->encrypted = 0;		/* clear encrypted */
  		current_header->exit_disposition = UNSET;
  		current_header->status_chgd = FALSE;
! 
  		/* Set the number of lines for the _preceding_ message,
  		 * but only if there was a preceding message and
  		 * only if it wasn't calculated already. It would
--- 941,952 ----
  		current_header->encrypted = 0;		/* clear encrypted */
  		current_header->exit_disposition = UNSET;
  		current_header->status_chgd = FALSE;
! #ifdef MIME
! 		mime_t_clear (&current_header->mime_rec);
! #endif
! #ifdef USE_PGP
! 		current_header->pgp = 0;
! #endif
  		/* Set the number of lines for the _preceding_ message,
  		 * but only if there was a preceding message and
  		 * only if it wasn't calculated already. It would
***************
*** 751,757 ****
--- 990,998 ----
  
  		strcpy(current_header->from, "");		/* clear from    */
  		strcpy(current_header->subject, "");	/* clear subj    */
+ 		strcpy(Subject,"");
  		strcpy(current_header->to, "");		/* clear to    */
+ 		strcpy(current_header->cc, "");
  		strcpy(current_header->time_zone, "");	/* clear time zone name */
  		strcpy(current_header->time_menu, "");	/* clear menu date */
  		strcpy(current_header->mailx_status, "");	/* clear status flags */
***************
*** 759,765 ****
  		current_header->encrypted = 0;		/* clear encrypted */
  		current_header->exit_disposition = UNSET;
  		current_header->status_chgd = FALSE;
! 
  		/* Set the number of lines for the _preceding_ message,
  		 * but only if there was a preceding message and
  		 * only if it wasn't calculated already. It would
--- 1000,1011 ----
  		current_header->encrypted = 0;		/* clear encrypted */
  		current_header->exit_disposition = UNSET;
  		current_header->status_chgd = FALSE;
! #ifdef MIME
! 		mime_t_clear (&current_header->mime_rec);
! #endif
! #ifdef USE_PGP
! 		current_header->pgp = 0;
! #endif
  		/* Set the number of lines for the _preceding_ message,
  		 * but only if there was a preceding message and
  		 * only if it wasn't calculated already. It would
***************
*** 787,793 ****
  	      /* if this is the first "From" in file but the "From" line is
  	       * not of the proper format, we've got a corrupt folder.
  	       */
! 	      MoveCursor(LINES,0);
  	      Raw(OFF);
  	      printf(catgets(elm_msg_cat, ElmSet, ElmFolderCorrupt,
  		  "\nFolder is corrupt!!  I can't read it!!\n\n"));
--- 1033,1039 ----
  	      /* if this is the first "From" in file but the "From" line is
  	       * not of the proper format, we've got a corrupt folder.
  	       */
! 	      MoveCursor(elm_LINES,0);
  	      Raw(OFF);
  	      printf(catgets(elm_msg_cat, ElmSet, ElmFolderCorrupt,
  		  "\nFolder is corrupt!!  I can't read it!!\n\n"));
***************
*** 805,811 ****
  		 */
  	      if (fseek(mailfile, content_start, 0) == -1) {
  		err = errno;
! 		MoveCursor(LINES, 0);
  		Raw(OFF);
  		printf(catgets(elm_msg_cat, ElmSet, ElmCouldntSeekBytesIntoFolder,
  		   "\nCouldn't seek %ld bytes into folder.\n"),
--- 1051,1057 ----
  		 */
  	      if (fseek(mailfile, content_start, 0) == -1) {
  		err = errno;
! 		MoveCursor(elm_LINES, 0);
  		Raw(OFF);
  		printf(catgets(elm_msg_cat, ElmSet, ElmCouldntSeekBytesIntoFolder,
  		   "\nCouldn't seek %ld bytes into folder.\n"),
***************
*** 819,833 ****
  	      if (copyit)
  		if (fseek(temp, content_start, 0) == -1) {
  		  err = errno;
! 		  MoveCursor(LINES, 0);
  		  Raw(OFF);
  		  printf(catgets(elm_msg_cat, ElmSet, ElmCouldntSeekBytesIntoTempFile,
  		     "\nCouldn't seek %ld bytes into temp file.\n"),
! 		     mailfile_size);
  		  printf("** %s. **\n", error_description(err));
  		  dprint(1, (debugfile,
! 	"Error: Couldn't seek temp file %s: (offset %ld) Errno %s (%s)\n",
! 		     cur_tempfolder, mailfile_size, error_description(err), "reset - read_headers"));
  		  emergency_exit();
  		}
  	      fbytes = content_start;
--- 1065,1079 ----
  	      if (copyit)
  		if (fseek(temp, content_start, 0) == -1) {
  		  err = errno;
! 		  MoveCursor(elm_LINES, 0);
  		  Raw(OFF);
  		  printf(catgets(elm_msg_cat, ElmSet, ElmCouldntSeekBytesIntoTempFile,
  		     "\nCouldn't seek %ld bytes into temp file.\n"),
! 			 mailfile_size);
  		  printf("** %s. **\n", error_description(err));
  		  dprint(1, (debugfile,
! 			     "Error: Couldn't seek temp file %s: (offset %ld) Errno %s (%s)\n",
! 			     cur_tempfolder, mailfile_size, error_description(err), "reset - read_headers"));
  		  emergency_exit();
  		}
  	      fbytes = content_start;
***************
*** 836,844 ****
  	      current_header->content_length = -1; /* mark as if not found yet */
  	      line_bytes = 0;
  	    }
! 	  }
  
! 	  if (in_header == TRUE) {
  #ifdef MMDF
  	    if (strcmp(buffer, MSG_SEPARATOR) == 0) {
  	      /*
--- 1082,1213 ----
  	      current_header->content_length = -1; /* mark as if not found yet */
  	      line_bytes = 0;
  	    }
! 	    }
! 
! 	    /* Handling of continuation lines must be done before parsing
! 	     * next line!   or it don't work!   
! 	     *
! 	     * Another bug is that there can happen buffer overflow....
! 	     *   (well perhaps I can do quick fix for that)
! 	     *
! 	     *                              - K E H <hurtta@dionysos.FMi.FI>
! 	     */
! 
! 	    if (in_to_list == TRUE) {
! 	      dprint(12,(debugfile,"in_to_list; in_header=%d, buffer=%s\n",
! 			 in_header,buffer));
! 	      if (in_header && whitespace(buffer[0])) {
! 		if ((c = index(buffer, '\n')) != NULL)
! 		  *c = '\0';
! 		c = buffer;
! 		while (*c && isspace(*c)) ++c;
! 		if (strlen(current_header->to) + strlen(c)
! 		    < sizeof(current_header->to) - 4) {
! 		  strcat(current_header->to, " ");		  
! 		  strcat(current_header->to, c);
! 		} else {
! 		  dprint(12,(debugfile,"in_to_list; OVERFLOW!\n"));
! 		  in_to_list = FALSE;
! 		}
! 	      } else in_to_list = FALSE;
! 	    } 
! 	    if (in_cc_list == TRUE) {
! 	      dprint(12,(debugfile,"in_cc_list; in_header=%d, buffer=%s\n",
! 			 in_header,buffer));
!               if (in_header && whitespace(buffer[0])) {
! 		if ((c = index(buffer, '\n')) != NULL)
! 		  *c = '\0';
! 		c = buffer;
! 		while (*c && isspace(*c)) ++c;
! 		if (strlen(current_header->cc) + strlen(c)
! 		    < sizeof(current_header->cc) - 4) {
! 		  strcat(current_header->cc, " ");
! 		  strcat(current_header->cc, c);
! 		} else {
! 		  dprint(12,(debugfile,"in_cc_list; OVERFLOW!\n"));
! 		  in_cc_list = FALSE;
! 		}
! 	      } else
! 		in_cc_list = FALSE;
! 	    }
! 	    if (in_subject == TRUE) {
! 	      dprint(12,(debugfile,"in_subject; in_header=%d, buffer=%s\n",
! 			 in_header,buffer));
! 
!               if (in_header && whitespace(buffer[0])) {
! 		int l = strlen(buffer);
! 		int l1 = strlen(Subject);
! 		buffer[0] = ' ';
! 		if (l > 1 && buffer[l-2] == '\r' && buffer[l-1] == '\n')
! 		  buffer[l-2] = 0;
! 		if (buffer[l-1] == '\n')
! 		  buffer[l-1] = 0;
! 
!                 strfcpy (Subject+l1, buffer,
! 			 sizeof(Subject)-l1);
! 		dprint(12,(debugfile,
! 			   "in_subject; l=%d,l1=%d => subject=%s\n",
! 			    l,l1,Subject));
!               }
!               else {
! 		dprint(12,(debugfile,"in_subject; Subject: %s\n",Subject));
! 
! 		in_subject = FALSE;
! 	      }
! 	    }
! #ifdef MIME
! 	    if (is_content) {
! 	      dprint(12,(debugfile,"is_content; in_header=%d, buffer=%s\n",
! 			 in_header,buffer));
!               if (in_header && whitespace(buffer[0])) {
! 		int l = strlen(buffer);
! 		int l1 = strlen(content_type);
! 		buffer[0] = ' ';
! 		if (l > 1 && buffer[l-2] == '\r' && buffer[l-1] == '\n')
! 		  buffer[l-2] = 0;
! 		if (buffer[l-1] == '\n')
! 		  buffer[l-1] = 0;
! 
!                 strfcpy (content_type+l1, buffer,sizeof(content_type)-l1);
! 		dprint(12,(debugfile,
! 			   "is_content=%d,l=%d,l1=%d => content_type=%s\n",
! 			    is_content,l,l1,content_type));
!               }
!               else {
! 		char buf [STRING];
! 		dprint(12,(debugfile,
! 			   "is_content=%d => content_type=%s\n",
! 			   is_content,content_type));
! 		if (is_content == 1) {
! 
! 		  if (is_pre_mime_content_type(&current_header->mime_rec,
! 					       content_type)) {
! 
! 		    dprint(12,(debugfile,"NOT mime's content-type: %s\n",
! 			       content_type));
! 		      
! 		    current_header->status |= PRE_MIME_CONTENT;
! 		  }
!                   else {
! 		    dprint(12,(debugfile,"MIME's content-type: %s\n",
! 			       content_type));
! 
! 		    mime_get_content (content_type, &current_header->mime_rec);
!                     if (mime_notplain(&current_header->mime_rec))
!                       current_header->mime_rec.notplain = TRUE;
! 		  }
! 		}
! 		else if (is_content == 2) {
! 		  mime_get_disposition (content_type, 
! 					&current_header->mime_rec);
! 		}
! 		is_content = 0;
!               }
! 	    }
! #endif
  
! 	 if (in_header == TRUE) {
! 
  #ifdef MMDF
  	    if (strcmp(buffer, MSG_SEPARATOR) == 0) {
  	      /*
***************
*** 862,871 ****
  		     header_cmp(buffer,"Subj", NULL) ||
  		     header_cmp(buffer,"Re", NULL)) {
  	      if (! subj++) {
! 		strfcpy(tbuffer, buffer, sizeof(tbuffer));
! 	        remove_header_keyword(tbuffer);
! 	        copy_sans_escape(current_header->subject, tbuffer, STRING);
! 		remove_possible_trailing_spaces(current_header->subject);
  	      }
  	    }
  	    else if (header_cmp(buffer,"From", NULL)) {
--- 1231,1247 ----
  		     header_cmp(buffer,"Subj", NULL) ||
  		     header_cmp(buffer,"Re", NULL)) {
  	      if (! subj++) {
! 		int l = strlen(buffer);
! 		in_subject = TRUE;
! 		if (buffer[l-2] == '\r' && buffer[l-1] == '\n')
! 		  buffer[l-2] = 0;
! 		if (buffer[l-1] == '\n')
! 		  buffer[l-1] = 0;
! 		strfcpy (Subject, buffer,
! 			 sizeof(Subject));
! 		remove_header_keyword(Subject);
! 		dprint(12,(debugfile,"in_subject; START! Subject: %s\n",
! 			   Subject));
  	      }
  	    }
  	    else if (header_cmp(buffer,"From", NULL)) {
***************
*** 920,947 ****
  	      current_header->status |= PRIVATE;
  	    else if (header_cmp(buffer, "Sensitivity", "3"))
  	      current_header->status |= CONFIDENTIAL;
! 	    else if (header_cmp(buffer, "Content-Type", "mailform"))
! 	      current_header->status |= FORM_LETTER;
  	    else if (header_cmp(buffer, "Action", NULL))
  	      current_header->status |= ACTION;
  #ifdef	MIME
  	    else if (header_cmp(buffer, MIME_HEADER_NAME, MIME_HEADER_VERSION))
  	      current_header->status |= MIME_MESSAGE;
! 	    /* Next two lines for backward compatability to old drafts */
! 	    else if (header_cmp(buffer, MIME_HEADER_NAME, MIME_HEADER_OLDVERSION))
! 	      current_header->status |= MIME_MESSAGE;
! 	    /* Next two lines for minimal support for mail generated by
! 	     * Sun's Openwindows mailtool */
! 	    else if (header_cmp(buffer, "Content-Type", "X-"))
! 	      current_header->status |= MIME_MESSAGE|MIME_NOTPLAIN;
  	    else if (header_cmp(buffer, MIME_HEADER_CONTENTTYPE, NULL)) {
! 	      if (! (current_header->status & MIME_NOTPLAIN) &&
! 		  notplain(buffer+strlen(MIME_CONTENTTYPE)))
! 		current_header->status |= MIME_NOTPLAIN;
  	    }
  	    else if (header_cmp(buffer, MIME_HEADER_CONTENTENCOD, NULL)) {
! 	      if (needs_mmdecode(buffer+strlen(MIME_CONTENTENCOD)))
! 		current_header->status |= MIME_NEEDDECOD;
  	    }
  #endif /* MIME */
  
--- 1296,1358 ----
  	      current_header->status |= PRIVATE;
  	    else if (header_cmp(buffer, "Sensitivity", "3"))
  	      current_header->status |= CONFIDENTIAL;
! 	    else if (header_cmp(buffer, "Content-Type", "mailform")) 
! 	      current_header->status |= FORM_LETTER | PRE_MIME_CONTENT;
  	    else if (header_cmp(buffer, "Action", NULL))
  	      current_header->status |= ACTION;
  #ifdef	MIME
+ 	    else if (header_cmp(buffer, "X-ELM-OSV",NULL)) {
+ 	      char value [20];
+ 	      if (mime_get_param("no-hdr-encoding",value,buffer+10,
+ 				 sizeof value)) {
+ 		int i = atoi(value);
+ 		dprint(12,(debugfile,"-- no-hdr-encoding=%d\n",i));
+ 		if (i) 
+ 		  current_header->status |= NOHDRENCODING;
+ 	      }
+ 	    }
+ 	    /* We should accept headers like:
+ 	     *    MIME-Version: (MetaSend v1.7) 1.0
+ 	     * And if version number is something other accept it but give 
+ 	     * warning when message is viewed or replied.
+ 	     * Perhaps in next version. 
+ 	     */
  	    else if (header_cmp(buffer, MIME_HEADER_NAME, MIME_HEADER_VERSION))
  	      current_header->status |= MIME_MESSAGE;
!             else if (header_cmp(buffer, MIME_HEADER_NAME, NULL))
!               current_header->status |= MIME_MESSAGE|MIME_UNSUPPORTED;
  	    else if (header_cmp(buffer, MIME_HEADER_CONTENTTYPE, NULL)) {
! 	      int l = strlen(buffer);
!               is_content = 1;   /* This is quick hack -- mime headers
! 				 * should be decoded with mime_read_header
! 				 * otherwise we duplicate code ...
! 				 *     - K E H     <hurtta@dionysos.FMI.FI>
! 				 */
! 	      if (buffer[l-2] == '\r' && buffer[l-1] == '\n')
! 		buffer[l-2] = 0;
! 	      if (buffer[l-1] == '\n')
! 		buffer[l-1] = 0;
!               strfcpy (content_type, buffer + 13, sizeof(content_type));
! 	    }
! 	    else if (header_cmp(buffer, "Content-Disposition", NULL)) {
! 	      int l = strlen(buffer);
!               is_content = 2;   /* This is quick hack -- mime headers
! 				 * should be decoded with mime_read_header
! 				 * otherwise we duplicate code ...
! 				 *     - K E H     <hurtta@dionysos.FMI.FI>
! 				 */	
! 	      if (buffer[l-2] == '\r' && buffer[l-1] == '\n')
! 		buffer[l-2] = 0;
! 	      if (buffer[l-1] == '\n')
! 		buffer[l-1] = 0;
!               strfcpy (content_type, buffer + 20, sizeof(content_type));
  	    }
  	    else if (header_cmp(buffer, MIME_HEADER_CONTENTENCOD, NULL)) {
!               c = buffer + MIME_CONTENTENCOD_LEN;
!               while (*c && isspace(*c)) ++c;
!               current_header->mime_rec.encoding = check_encoding (c);
! 	      if (mime_notplain(&current_header->mime_rec))
! 		current_header->mime_rec.notplain = TRUE;
  	    }
  #endif /* MIME */
  
***************
*** 949,958 ****
  
  	    else if (header_cmp(buffer, "To", NULL)) {
  	      in_to_list = TRUE;
! 	      current_header->to[0] = '\0';	/* nothing yet */
! 	      figure_out_addressee((char *) buffer +3, 
! 				   current_header->to);
  	    }
  	    else if (header_cmp(buffer, "Status", NULL)) {
  	      strfcpy(tbuffer, buffer, sizeof(tbuffer));
  	      remove_header_keyword(tbuffer);
--- 1360,1399 ----
  
  	    else if (header_cmp(buffer, "To", NULL)) {
  	      in_to_list = TRUE;
! 
! 	      if ((c = index(buffer, '\n')) != NULL)
! 		*c = '\0';
! 	      c = buffer + 3;
! 	      while (*c && isspace(*c)) ++c;
! 
! 	      if (strlen(current_header->to) + strlen(c)
! 		  < sizeof(current_header->to) - 4) {
! 		if (current_header->to[0] != '\0')
! 		  strcat(current_header->to, ", ");
! 		strcat(current_header->to, c);
! 	      } else {
! 		dprint(12,(debugfile,"in_to_list! OVERFLOW!\n"));
! 		in_to_list = FALSE;
! 	      }
  	    }
+ 	    else if (header_cmp(buffer, "Cc", NULL)) {
+ 	      in_cc_list = TRUE;
+ 	      if ((c = index(buffer, '\n')) != NULL)
+ 		*c = '\0';
+ 	      c = buffer + 3;
+ 
+ 	      while (*c && isspace(*c)) ++c;
+ 
+ 	      if (strlen(current_header->cc) + strlen(c)
+ 		  < sizeof(current_header->cc) - 4) {
+ 		if (current_header->cc[0] != '\0')
+ 		  strcat(current_header->cc, ", ");
+ 		strcat(current_header->cc, c);
+ 	      } else {
+ 		dprint(12,(debugfile,"in_cc_list! OVERFLOW!\n"));
+ 		in_cc_list = FALSE;
+ 	      }
+ 	    }
  	    else if (header_cmp(buffer, "Status", NULL)) {
  	      strfcpy(tbuffer, buffer, sizeof(tbuffer));
  	      remove_header_keyword(tbuffer);
***************
*** 961,966 ****
--- 1402,1410 ----
  	      c = index(current_header->mailx_status, '\n');
  	      if (c != NULL)
  		*c = '\0';
+ 	      c = index(current_header->mailx_status, '\r');
+ 	      if (c != NULL)
+ 		*c = '\0';
  	      remove_possible_trailing_spaces(current_header->mailx_status);
  
  	      /* Okay readjust the status. If there's an 'R', message
***************
*** 974,1005 ****
  		current_header->status &= ~NEW;
  		current_header->status |= UNREAD;
  	      }
  	    }
  
! 	    else if (buffer[0] == LINE_FEED || buffer[0] == '\0') {
  	      in_header = FALSE;	/* in body of message! */
- 	      in_to_list = FALSE;
  	      content_remaining = current_header->content_length;
  	      content_start = fbytes + 1;
  	      lines_start = line;
  	    }
  	    if (in_header == TRUE) {
  	       if ((!whitespace(buffer[0])) && index(buffer, ':') == NULL) {
  	        in_header = FALSE;	/* in body of message! */
- 	        in_to_list = FALSE;
  	        content_remaining = current_header->content_length;
  	        content_start = fbytes;
  	        lines_start = line;
  	      }
  	    }
! 	    if (in_to_list == TRUE) {
! 	      if (whitespace(buffer[0]))
! 	        figure_out_addressee(buffer, current_header->to);
! 	      else in_to_list = FALSE;
  	    }
  	  }
- 	  if (in_header == FALSE && first_word(buffer, START_ENCODE))
- 	    current_header->encrypted = 1;
  	  fbytes += (long) line_bytes;
  	  content_remaining -= (long) line_bytes;
  	}
--- 1418,1576 ----
  		current_header->status &= ~NEW;
  		current_header->status |= UNREAD;
  	      }
+               if (index(current_header->mailx_status, 'r') != NULL)
+                 current_header->status |= REPLIED;
  	    }
  
! 	    else if (buffer[0] == LINE_FEED || buffer[0] == '\0' ||
! 		     buffer[0] == '\r' && buffer[1] == '\n') {
! 	      current_header->binary = 
! 		(buffer[0] == '\r' && buffer[1] == '\n');
  	      in_header = FALSE;	/* in body of message! */
  	      content_remaining = current_header->content_length;
  	      content_start = fbytes + 1;
+ 	      if (current_header->binary)
+ 		content_start = fbytes + 2;
  	      lines_start = line;
+ #ifdef MIME
+ 	      current_header->mime_rec.offset = ftell (mailfile);
+ #endif
  	    }
  	    if (in_header == TRUE) {
  	       if ((!whitespace(buffer[0])) && index(buffer, ':') == NULL) {
  	        in_header = FALSE;	/* in body of message! */
  	        content_remaining = current_header->content_length;
  	        content_start = fbytes;
  	        lines_start = line;
+ #ifdef MIME
+ 	      current_header->mime_rec.offset = content_start;
+ #endif
  	      }
  	    }
! 	    /* No longer in headers */
! 	    if (in_header == FALSE) {
! #ifdef MIME
! 	      if (req_mime_hdrencoding &&
! 		  !(current_header->status & MIME_MESSAGE)) {
! 		current_header -> status |= NOHDRENCODING;
! 		dprint(12,(debugfile,"-- Turning on NOHDRENCODING\n"));
! 	      }
! 
! 	      if (!req_mime_bodyencoding && 
! 		  !(current_header->status & PRE_MIME_CONTENT)) {
! 		current_header -> status |= MIME_MESSAGE;
! 		dprint(12,(debugfile,"-- Turning on MIME_MESSAGE\n"));
! 	      }
! 
! 	      if (!(current_header -> status & NOHDRENCODING) &&
! 		  is_rfc1522(Subject)) 
! 		rfc1522_decode(Subject,sizeof(Subject));
! #endif
! 	        copy_sans_escape(current_header->subject, Subject, STRING);
! 		remove_possible_trailing_spaces(current_header->subject);
! 		dprint(12,(debugfile,"-- Decoded subject: %s\n",
! 			   current_header->subject));
! 
! 
! 	    }
! 	  }
! 	  if (in_header == FALSE) {
! 	    if (first_word(buffer, START_ENCODE)) {
! 	      current_header->encrypted = 1;
! 	      dprint(12,(debugfile,"-- encrypted: %s\n",buffer));
! #ifdef MIME
! 	      /* Text/plain can be converted to application/X-ELM-encode */
! 	      if (current_header->mime_rec.type == MIME_TYPE_TEXT && 
! 		  (istrcmp(current_header->mime_rec.subtype,"plain")==0)) {
! 		  current_header->mime_rec.type = MIME_TYPE_APPLICATION;
! 		  strcpy(current_header->mime_rec.subtype, "X-ELM-encode");
! 		  /* Keep current_header->mime_rec.type_opts ! */
! 	      }
! 	      dprint(12,(debugfile,"-- encrypted, %d/%s; opts=%s\n",
! 			 current_header->mime_rec.type,
! 			 current_header->mime_rec.subtype,
! 			 NONULL(current_header->mime_rec.type_opts)));
! #endif /* MIME */
! 	    }
! #ifdef USE_PGP
! 	    if (strncmp(buffer, "-----BEGIN PGP", 14) == 0) {
! 	      if (strncmp(buffer + 15, "PUBLIC", 6) == 0) {
! 		current_header->pgp |= PGP_PUBLIC_KEY;
! 		dprint(12,(debugfile,"-- PGP PUBLIC KEY: %s\n",buffer));
! 	      } else {
! #ifdef MIME
! 		char pgpbuffer[STRING];
! 
! 		/* Text/plain can be converted to application/pgp.  There will
! 		 * a possible loss of surrounding text, but there is no way
! 		 * to get around this without having the sender use the proper
! 		 * MIME type.
! 		 */
! 		if (current_header->mime_rec.type == MIME_TYPE_TEXT && 
! 		    istrcmp(current_header->mime_rec.subtype,"plain")==0) {
! 		  current_header->mime_rec.type = MIME_TYPE_APPLICATION;
! 		  strcpy(current_header->mime_rec.subtype, "pgp");
! 		  /* Keep current_header->mime_rec.type_opts ! */
! 		}
! #endif
! 		if (strncmp(buffer + 15, "SIG", 3) == 0) {
! 		  current_header->pgp |= PGP_SIGNED_MESSAGE;
! 		  dprint(12,(debugfile,"-- PGP signed: %s\n",buffer));
! #ifdef MIME
! 		  if (current_header->mime_rec.type_opts) {
! 		    if (!mime_get_param("x-action",
! 					pgpbuffer,
! 					current_header->mime_rec.type_opts,
! 					sizeof(pgpbuffer))) {
! 		      strfcpy(pgpbuffer,current_header->mime_rec.type_opts,
! 			      sizeof(pgpbuffer));
! 		      add_parameter(pgpbuffer,
! 				    "x-action", "sign",
! 				    sizeof(pgpbuffer),
! 				    FALSE);
! 		      current_header->mime_rec.type_opts = strmcpy(current_header->mime_rec.type_opts, pgpbuffer);
! 		    }
! 		  }
! 		  else {
! 		    pgpbuffer[0] = '\0';
! 		    add_parameter(pgpbuffer,"x-action","sign",
! 				  sizeof(pgpbuffer), FALSE);
! 		    current_header->mime_rec.type_opts = strmcpy(current_header->mime_rec.type_opts, pgpbuffer);
! 		  }
! 		  dprint(12,(debugfile,"-- PGP signed, %d/%s; opts=%s\n",
! 			     current_header->mime_rec.type,
! 			     current_header->mime_rec.subtype,
! 			     NONULL(current_header->mime_rec.type_opts)));
! #endif
! 		}
! 		else {
! 		  current_header->pgp |= PGP_MESSAGE;
! 		  dprint(12,(debugfile,"-- PGP message: %s\n",buffer));
! #ifdef MIME
! 		  if (current_header->mime_rec.type_opts) {
! 		    if (!mime_get_param("x-action",pgpbuffer,current_header->mime_rec.type_opts,sizeof(pgpbuffer))) {
! 		      strcpy(pgpbuffer,current_header->mime_rec.type_opts);
! 		      add_parameter(pgpbuffer, "x-action", "encrypt",
! 				    sizeof(pgpbuffer), FALSE);
! 		      current_header->mime_rec.type_opts = strmcpy(current_header->mime_rec.type_opts, pgpbuffer);
! 		    }
! 		  }
! 		  else {
! 		    pgpbuffer[0] = '\0';
! 		    add_parameter(pgpbuffer,"x-action","encrypt",
! 				  sizeof(pgpbuffer), FALSE);
! 		    current_header->mime_rec.type_opts = strmcpy(current_header->mime_rec.type_opts, pgpbuffer);
! 		  }
! 		  dprint(12,(debugfile,"-- PGP message, %d/%s; opts=%s\n",
! 			     current_header->mime_rec.type,
! 			     current_header->mime_rec.subtype,
! 			     NONULL(current_header->mime_rec.type_opts)));
! #endif
! 		}
!               }
  	    }
+ #endif /* USE_PGP */
  	  }
  	  fbytes += (long) line_bytes;
  	  content_remaining -= (long) line_bytes;
  	}
***************
*** 1011,1021 ****
  	}
  
  	if (folder_type == SPOOL) {
- 	  fflush (mailfile);
  	  unlock();	/* remove lock file! */
  	  if ((ferror(mailfile)) || (fclose(mailfile) == EOF)) {
  	    err = errno;
! 	    MoveCursor(LINES, 0);
  	    Raw(OFF);
  	    printf(catgets(elm_msg_cat, ElmSet, ElmCloseOnFolderFailed,
  			   "\nClose on folder %s failed!!\n"),
--- 1582,1591 ----
  	}
  
  	if (folder_type == SPOOL) {
  	  unlock();	/* remove lock file! */
  	  if ((ferror(mailfile)) || (fclose(mailfile) == EOF)) {
  	    err = errno;
! 	    MoveCursor(elm_LINES, 0);
  	    Raw(OFF);
  	    printf(catgets(elm_msg_cat, ElmSet, ElmCloseOnFolderFailed,
  			   "\nClose on folder %s failed!!\n"),
***************
*** 1028,1034 ****
  
  	  if ((ferror(temp)) || (fclose(temp) == EOF)) {
  	      err = errno;
! 	      MoveCursor(LINES, 0);
  	      Raw(OFF);
  	      printf(catgets(elm_msg_cat, ElmSet, ElmCloseOnTempFailed,
  			      "\nClose on temp file %s failed!!\n"), 
--- 1598,1604 ----
  
  	  if ((ferror(temp)) || (fclose(temp) == EOF)) {
  	      err = errno;
! 	      MoveCursor(elm_LINES, 0);
  	      Raw(OFF);
  	      printf(catgets(elm_msg_cat, ElmSet, ElmCloseOnTempFailed,
  			      "\nClose on temp file %s failed!!\n"), 
***************
*** 1041,1047 ****
  
  	  /* sanity check on append - is resulting temp file longer??? */
  	  if ( bytes(cur_tempfolder) != mailfile_size) {
! 	     MoveCursor(LINES, 0);
  	     Raw(OFF);
  	     printf(catgets(elm_msg_cat, ElmSet, ElmLengthNESpool,
  	       "\nnewmbox - length of mbox. != spool mailbox length!!\n"));
--- 1611,1617 ----
  
  	  /* sanity check on append - is resulting temp file longer??? */
  	  if ( bytes(cur_tempfolder) != mailfile_size) {
! 	     MoveCursor(elm_LINES, 0);
  	     Raw(OFF);
  	     printf(catgets(elm_msg_cat, ElmSet, ElmLengthNESpool,
  	       "\nnewmbox - length of mbox. != spool mailbox length!!\n"));
***************
*** 1051,1057 ****
  
  	  if ((mailfile = fopen(cur_tempfolder,"r")) == NULL) {
  	    err = errno;
! 	    MoveCursor(LINES,0);
  	    Raw(OFF);
  	    printf(catgets(elm_msg_cat, ElmSet, ElmCouldntReopenForTemp,
  		   "\nCouldn't reopen file %s for use as temp file.\n"),
--- 1621,1627 ----
  
  	  if ((mailfile = fopen(cur_tempfolder,"r")) == NULL) {
  	    err = errno;
! 	    MoveCursor(elm_LINES,0);
  	    Raw(OFF);
  	    printf(catgets(elm_msg_cat, ElmSet, ElmCouldntReopenForTemp,
  		   "\nCouldn't reopen file %s for use as temp file.\n"),
Index: WORK/src/options.c
*** elm2.4.25/src/options.c	Mon May 30 19:42:50 1994
--- WORK/src/options.c	Sun Jun 16 18:56:55 1996
***************
*** 179,184 ****
--- 179,185 ----
  #include "headers.h"
  #include "save_opts.h"
  #include "s_elm.h"
+ #include "me.h"
  
  #undef onoff
  #define   onoff(n)	(n == 1? on_name : off_name)
***************
*** 238,244 ****
  static post_menu(f)
  int f;
  {
!     headers_per_page = LINES - (mini_menu ? 13 : 8);
  }
  
  opts_menu cfg_opts[] = {
--- 239,245 ----
  static post_menu(f)
  int f;
  {
!     headers_per_page = elm_LINES - (mini_menu ? 13 : 8);
  }
  
  opts_menu cfg_opts[] = {
***************
*** 385,398 ****
  		continue;
  	    }
              o = find_cfg_opts(*s);
!             if (o != NULL && y<LINES-5) {
  		sprintf(buf,"%-20.20s : %%s", o->menu);
  		PutLine1(y, 0, buf, str_opt_nam(o->parm, FULL));
  		}
  	    }
  	if (!printed_title) {
! 	    Centerline(LINES-5, catgets(elm_msg_cat, ElmSet, ElmOptionsEditor,
! 		"-- ELM Options Editor --"));
  	}
  }
  
--- 386,400 ----
  		continue;
  	    }
              o = find_cfg_opts(*s);
!             if (o != NULL && y<elm_LINES-5) {
  		sprintf(buf,"%-20.20s : %%s", o->menu);
  		PutLine1(y, 0, buf, str_opt_nam(o->parm, FULL));
  		}
  	    }
  	if (!printed_title) {
! 	    Centerline(elm_LINES-5, catgets(elm_msg_cat, ElmSet, 
! 					    ElmOptionsEditor,
! 					    "-- ELM Options Editor --"));
  	}
  }
  
***************
*** 405,417 ****
  	char	*ptr, *prompt;
  	int	c;
  
! 	ClearLine(LINES-2);		/* clear option prompt message */
! 	Centerline(LINES-3, catgets(elm_msg_cat, ElmSet, ElmPressKeyHelp,
    "Press the key you want help for, '?' for a key list, or '.' to exit help"));
  
  	lower_prompt(prompt = catgets(elm_msg_cat, ElmSet, ElmKeyPrompt, "Key : "));
  
! 	while ((c = ReadCh()) != '.') {
  	  if (c == EOF)
  	    leave(0);
  
--- 407,419 ----
  	char	*ptr, *prompt;
  	int	c;
  
! 	ClearLine(elm_LINES-2);		/* clear option prompt message */
! 	Centerline(elm_LINES-3, catgets(elm_msg_cat, ElmSet, ElmPressKeyHelp,
    "Press the key you want help for, '?' for a key list, or '.' to exit help"));
  
  	lower_prompt(prompt = catgets(elm_msg_cat, ElmSet, ElmKeyPrompt, "Key : "));
  
! 	while ((c = ReadCh(0)) != '.') {
  	  if (c == EOF)
  	    leave(0);
  
***************
*** 447,454 ****
  	    }
  	  lower_prompt(prompt);
  	}
! 	ClearLine(LINES-3);		/* clear Press help key message */
! 	ClearLine(LINES-1);		/* clear lower prompt message */
  }
  
  
--- 449,456 ----
  	    }
  	  lower_prompt(prompt);
  	}
! 	ClearLine(elm_LINES-3);		/* clear Press help key message */
! 	ClearLine(elm_LINES-1);		/* clear lower prompt message */
  }
  
  
***************
*** 497,503 ****
  #endif
  	}
  
! 
  	resort = 0;
  	prompt = catgets(elm_msg_cat, ElmSet, ElmPrompt, "Command: ");
  	display_options();
--- 499,505 ----
  #endif
  	}
  
! redraw:
  	resort = 0;
  	prompt = catgets(elm_msg_cat, ElmSet, ElmPrompt, "Command: ");
  	display_options();
***************
*** 505,518 ****
  	clearerr(stdin);
  
  	while(1) {
! 	  ClearLine(LINES-4);
  
! 	  Centerline(LINES-4, catgets(elm_msg_cat, ElmSet, ElmSelectOptionLetter,
   "Select letter of option line, '>' to save, or 'i' to return to index."));
  
! 	  PutLine0(LINES-2, 0, prompt);
  
! 	  ch = ReadCh();
  	  if (ch == EOF)
  	    leave(0);
  	  ch = tolower(ch);
--- 507,523 ----
  	clearerr(stdin);
  
  	while(1) {
! 	  ClearLine(elm_LINES-4);
  
! 	  Centerline(elm_LINES-4, catgets(elm_msg_cat, ElmSet, 
! 					  ElmSelectOptionLetter,
   "Select letter of option line, '>' to save, or 'i' to return to index."));
  
! 	  PutLine0(elm_LINES-2, 0, prompt);
  
! 	  ch = ReadCh(REDRAW_MARK);
! 	  if (ch == REDRAW_MARK)
! 	    goto redraw;
  	  if (ch == EOF)
  	    leave(0);
  	  ch = tolower(ch);
***************
*** 522,528 ****
  	  if (index(config_options, ch)) {
  	      y = index(config_options,ch) - config_options;
                o = find_cfg_opts(ch);
!               if (o != NULL && y < LINES-5) {
  		  one_liner(o->one_liner);
  		  y = info_enter(o->parm, y, 23, FALSE, FALSE);
  		  if (o->post)
--- 527,533 ----
  	  if (index(config_options, ch)) {
  	      y = index(config_options,ch) - config_options;
                o = find_cfg_opts(ch);
!               if (o != NULL && y < elm_LINES-5) {
  		  one_liner(o->one_liner);
  		  y = info_enter(o->parm, y, 23, FALSE, FALSE);
  		  if (o->post)
***************
*** 534,540 ****
  	      one_liner(NULL);
  	      switch (ch) {
  	    case '?' : options_help(); 
! 	               PutLine0(LINES-2,0, prompt);			break;
  	   
  	    case '>' : printf(catgets(elm_msg_cat, ElmSet, ElmSaveOptions,
  			"Save options in .elm/elmrc..."));
--- 539,545 ----
  	      one_liner(NULL);
  	      switch (ch) {
  	    case '?' : options_help(); 
! 	               PutLine0(elm_LINES-2,0, prompt);			break;
  	   
  	    case '>' : printf(catgets(elm_msg_cat, ElmSet, ElmSaveOptions,
  			"Save options in .elm/elmrc..."));
***************
*** 567,573 ****
  	MoveCursor(x,y+3);	/* at end of value... */
  
  	do {
! 	  ch = ReadCh();
  
  	  if (ch == SPACE) {
  	    *var = ! *var;
--- 572,578 ----
  	MoveCursor(x,y+3);	/* at end of value... */
  
  	do {
! 	  ch = ReadCh(0);
  
  	  if (ch == SPACE) {
  	    *var = ! *var;
***************
*** 589,595 ****
  
  	MoveCursor(x,y);	/* at end of value... */
  
! 	while (ReadCh() == ' ') {
  	  *ulevel = (*ulevel >= 2? 0 : *ulevel + 1);
  	  PutLine1(x,y, "%s", level_name(*ulevel));
  	}
--- 594,600 ----
  
  	MoveCursor(x,y);	/* at end of value... */
  
! 	while (ReadCh(0) == ' ') {
  	  *ulevel = (*ulevel >= 2? 0 : *ulevel + 1);
  	  PutLine1(x,y, "%s", level_name(*ulevel));
  	}
***************
*** 612,624 ****
  /*	*var = sortby; 	or...	*var == sortby; 	*/
  	last_sortby = sortby;	/* remember current ordering   */
  
! 	PutLine0(x, COLUMNS-29, catgets(elm_msg_cat, ElmSet, ElmSpaceForNext,
! 		"(SPACE for next, or R)everse)"));
  	sort_one_liner(sortby);
  	MoveCursor(x, y);
  
  	do {
! 	  ch = ReadCh();
  	  ch = tolower(ch);
  	  switch (ch) {
  	    case SPACE : if (sortby < 0) { 
--- 617,630 ----
  /*	*var = sortby; 	or...	*var == sortby; 	*/
  	last_sortby = sortby;	/* remember current ordering   */
  
! 	PutLine0(x, elm_COLUMNS-29, 
! 		 catgets(elm_msg_cat, ElmSet, ElmSpaceForNext,
! 			 "(SPACE for next, or R)everse)"));
  	sort_one_liner(sortby);
  	MoveCursor(x, y);
  
  	do {
! 	  ch = ReadCh(0);
  	  ch = tolower(ch);
  	  switch (ch) {
  	    case SPACE : if (sortby < 0) { 
***************
*** 640,646 ****
  	 }
          } while (ch == SPACE || ch == 'r');
  
! 	MoveCursor(x, COLUMNS-30);	CleartoEOLN();
  
  	if (sortby != last_sortby) {
  	  error(catgets(elm_msg_cat, ElmSet, ElmResortingFolder,
--- 646,652 ----
  	 }
          } while (ch == SPACE || ch == 'r');
  
! 	MoveCursor(x, elm_COLUMNS-30);	CleartoEOLN();
  
  	if (sortby != last_sortby) {
  	  error(catgets(elm_msg_cat, ElmSet, ElmResortingFolder,
***************
*** 649,655 ****
  		sleep((sleepmsg + 1) / 2);
  	  sort_mailbox(message_count, 0);
  	}
! 	ClearLine(LINES-2);		/* clear sort_one_liner()! */
  	*var=sortby;
  	sortby=last_sortby;
  	return(*var-sortby);
--- 655,661 ----
  		sleep((sleepmsg + 1) / 2);
  	  sort_mailbox(message_count, 0);
  	}
! 	ClearLine(elm_LINES-2);		/* clear sort_one_liner()! */
  	*var=sortby;
  	sortby=last_sortby;
  	return(*var-sortby);
***************
*** 661,669 ****
  {
  	/** A single-line description of the selected item... **/
  
! 	ClearLine(LINES-4);
  	if (string)
! 		Centerline(LINES-4, string);
  }
  
  
--- 667,675 ----
  {
  	/** A single-line description of the selected item... **/
  
! 	ClearLine(elm_LINES-4);
  	if (string)
! 		Centerline(elm_LINES-4, string);
  }
  
  
***************
*** 672,734 ****
  {
  	/** A one line summary of the particular sorting scheme... **/
  
! 	ClearLine(LINES-2);
  
  	switch (sorting_by) {
  	  
! 	  case REVERSE SENT_DATE:	Centerline(LINES-2,
  				catgets(elm_msg_cat, ElmSet, ElmSortRSentDate,
  "This sort will order most-recently-sent to least-recently-sent"));
  				break;
! 	  case REVERSE RECEIVED_DATE:	Centerline(LINES-2,
  				catgets(elm_msg_cat, ElmSet, ElmSortRRecvDate,
  "This sort will order most-recently-received to least-recently-received"));
  				break;
! 	  case REVERSE MAILBOX_ORDER:	Centerline(LINES-2,
  				catgets(elm_msg_cat, ElmSet, ElmSortRMailbox,
  "This sort will order most-recently-added-to-folder to least-recently"));
  				break;
! 	  case REVERSE SENDER:		Centerline(LINES-2,
  				catgets(elm_msg_cat, ElmSet, ElmSortRSender,
  "This sort will order by sender name, in reverse alphabetical order"));
  				break;
! 	  case REVERSE SIZE:		Centerline(LINES-2,
  				catgets(elm_msg_cat, ElmSet, ElmSortRSize,
  "This sort will order messages by longest to shortest"));
  				break;
! 	  case REVERSE SUBJECT:		Centerline(LINES-2,
  				catgets(elm_msg_cat, ElmSet, ElmSortRSubject,
  "This sort will order by subject, in reverse alphabetical order"));
  				break;
! 	  case REVERSE STATUS:		Centerline(LINES-2,
  				catgets(elm_msg_cat, ElmSet, ElmSortRStatus,
  "This sort will order by reverse status - Deleted through Tagged..."));
  				break;
! 	  case SENT_DATE:		Centerline(LINES-2,
  				catgets(elm_msg_cat, ElmSet, ElmSortSentDate,
  "This sort will order least-recently-sent to most-recently-sent"));
  				break;
! 	  case RECEIVED_DATE:		Centerline(LINES-2,
  				catgets(elm_msg_cat, ElmSet, ElmSortRecvDate,
  "This sort will order least-recently-received to most-recently-received"));
  				break;
! 	  case MAILBOX_ORDER:		Centerline(LINES-2,
  				catgets(elm_msg_cat, ElmSet, ElmSortMailbox,
  "This sort will order least-recently-added-to-folder to most-recently"));
  				break;
! 	  case SENDER:			Centerline(LINES-2,
  				catgets(elm_msg_cat, ElmSet, ElmSortSender,
  "This sort will order by sender name"));
  				break;
! 	  case SIZE:			Centerline(LINES-2,
  				catgets(elm_msg_cat, ElmSet, ElmSortSize,
  "This sort will order messages by shortest to longest"));
  				break;
! 	  case SUBJECT:			Centerline(LINES-2,
  				catgets(elm_msg_cat, ElmSet, ElmSortSubject,
  "This sort will order messages by subject"));
  				break;
! 	  case STATUS:			Centerline(LINES-2,
  				catgets(elm_msg_cat, ElmSet, ElmSortStatus,
  "This sort will order by status - Tagged through Deleted..."));
  				break;
--- 678,740 ----
  {
  	/** A one line summary of the particular sorting scheme... **/
  
! 	ClearLine(elm_LINES-2);
  
  	switch (sorting_by) {
  	  
! 	  case REVERSE SENT_DATE:	Centerline(elm_LINES-2,
  				catgets(elm_msg_cat, ElmSet, ElmSortRSentDate,
  "This sort will order most-recently-sent to least-recently-sent"));
  				break;
! 	  case REVERSE RECEIVED_DATE:	Centerline(elm_LINES-2,
  				catgets(elm_msg_cat, ElmSet, ElmSortRRecvDate,
  "This sort will order most-recently-received to least-recently-received"));
  				break;
! 	  case REVERSE MAILBOX_ORDER:	Centerline(elm_LINES-2,
  				catgets(elm_msg_cat, ElmSet, ElmSortRMailbox,
  "This sort will order most-recently-added-to-folder to least-recently"));
  				break;
! 	  case REVERSE SENDER:		Centerline(elm_LINES-2,
  				catgets(elm_msg_cat, ElmSet, ElmSortRSender,
  "This sort will order by sender name, in reverse alphabetical order"));
  				break;
! 	  case REVERSE SIZE:		Centerline(elm_LINES-2,
  				catgets(elm_msg_cat, ElmSet, ElmSortRSize,
  "This sort will order messages by longest to shortest"));
  				break;
! 	  case REVERSE SUBJECT:		Centerline(elm_LINES-2,
  				catgets(elm_msg_cat, ElmSet, ElmSortRSubject,
  "This sort will order by subject, in reverse alphabetical order"));
  				break;
! 	  case REVERSE STATUS:		Centerline(elm_LINES-2,
  				catgets(elm_msg_cat, ElmSet, ElmSortRStatus,
  "This sort will order by reverse status - Deleted through Tagged..."));
  				break;
! 	  case SENT_DATE:		Centerline(elm_LINES-2,
  				catgets(elm_msg_cat, ElmSet, ElmSortSentDate,
  "This sort will order least-recently-sent to most-recently-sent"));
  				break;
! 	  case RECEIVED_DATE:		Centerline(elm_LINES-2,
  				catgets(elm_msg_cat, ElmSet, ElmSortRecvDate,
  "This sort will order least-recently-received to most-recently-received"));
  				break;
! 	  case MAILBOX_ORDER:		Centerline(elm_LINES-2,
  				catgets(elm_msg_cat, ElmSet, ElmSortMailbox,
  "This sort will order least-recently-added-to-folder to most-recently"));
  				break;
! 	  case SENDER:			Centerline(elm_LINES-2,
  				catgets(elm_msg_cat, ElmSet, ElmSortSender,
  "This sort will order by sender name"));
  				break;
! 	  case SIZE:			Centerline(elm_LINES-2,
  				catgets(elm_msg_cat, ElmSet, ElmSortSize,
  "This sort will order messages by shortest to longest"));
  				break;
! 	  case SUBJECT:			Centerline(elm_LINES-2,
  				catgets(elm_msg_cat, ElmSet, ElmSortSubject,
  "This sort will order messages by subject"));
  				break;
! 	  case STATUS:			Centerline(elm_LINES-2,
  				catgets(elm_msg_cat, ElmSet, ElmSortStatus,
  "This sort will order by status - Tagged through Deleted..."));
  				break;
***************
*** 751,763 ****
  /*	*var = alias_sortby; 	or...	*var == alias_sortby; 	*/
  	last_sortby = alias_sortby;	/* remember current ordering   */
  
! 	PutLine0(x, COLUMNS-29, catgets(elm_msg_cat, ElmSet, ElmSpaceForNext,
! 		"(SPACE for next, or R)everse)"));
  	alias_sort_one_liner(alias_sortby);
  	MoveCursor(x, y);
  
  	do {
! 	  ch = ReadCh();
  	  ch = tolower(ch);
  	  switch (ch) {
  	    case SPACE : if (alias_sortby < 0) { 
--- 757,770 ----
  /*	*var = alias_sortby; 	or...	*var == alias_sortby; 	*/
  	last_sortby = alias_sortby;	/* remember current ordering   */
  
! 	PutLine0(x, elm_COLUMNS-29, 
! 		 catgets(elm_msg_cat, ElmSet, ElmSpaceForNext,
! 			 "(SPACE for next, or R)everse)"));
  	alias_sort_one_liner(alias_sortby);
  	MoveCursor(x, y);
  
  	do {
! 	  ch = ReadCh(0);
  	  ch = tolower(ch);
  	  switch (ch) {
  	    case SPACE : if (alias_sortby < 0) { 
***************
*** 780,786 ****
  	 }
          } while (ch == SPACE || ch == 'r');
  
! 	MoveCursor(x, COLUMNS-30);	CleartoEOLN();
  
  	if (alias_sortby != last_sortby) {
  	  error(catgets(elm_msg_cat, ElmSet, ElmResortingAliases,
--- 787,793 ----
  	 }
          } while (ch == SPACE || ch == 'r');
  
! 	MoveCursor(x, elm_COLUMNS-30);	CleartoEOLN();
  
  	if (alias_sortby != last_sortby) {
  	  error(catgets(elm_msg_cat, ElmSet, ElmResortingAliases,
***************
*** 791,797 ****
  	  sort_aliases(message_count, FALSE, FALSE);
  	  main_state();
  	}
! 	ClearLine(LINES-2);		/* clear alias_sort_one_liner()! */
  	*var=alias_sortby;
  	alias_sortby=last_sortby;
  	return(*var-alias_sortby);
--- 798,804 ----
  	  sort_aliases(message_count, FALSE, FALSE);
  	  main_state();
  	}
! 	ClearLine(elm_LINES-2);		/* clear alias_sort_one_liner()! */
  	*var=alias_sortby;
  	alias_sortby=last_sortby;
  	return(*var-alias_sortby);
***************
*** 802,833 ****
  {
  	/** A one line summary of the particular sorting scheme... **/
  
! 	ClearLine(LINES-2);
  
  	switch (sorting_by) {
  	  
! 	  case REVERSE ALIAS_SORT:	Centerline(LINES-2,
  				catgets(elm_msg_cat, ElmSet, ElmASortRAlias,
  "This sort will order by alias name, in reverse alphabetical order"));
  					break;
! 	  case REVERSE NAME_SORT:	Centerline(LINES-2,
  				catgets(elm_msg_cat, ElmSet, ElmASortRName,
  "This sort will order by user (real) name, in reverse alphabetical order"));
  					break;
! 	  case REVERSE TEXT_SORT:	Centerline(LINES-2,
  				catgets(elm_msg_cat, ElmSet, ElmASortRText,
  "This sort will order aliases in the reverse order as listed in aliases.text"));
  					break;
  
! 	  case ALIAS_SORT:		Centerline(LINES-2,
  				catgets(elm_msg_cat, ElmSet, ElmASortAlias,
  "This sort will order by alias name"));
  					break;
! 	  case NAME_SORT:		Centerline(LINES-2,
  				catgets(elm_msg_cat, ElmSet, ElmASortName,
  "This sort will order by user (real) name"));
  					break;
! 	  case TEXT_SORT:		Centerline(LINES-2,
  				catgets(elm_msg_cat, ElmSet, ElmASortText,
  "This sort will order aliases in the order as listed in aliases.text"));
  					break;
--- 809,840 ----
  {
  	/** A one line summary of the particular sorting scheme... **/
  
! 	ClearLine(elm_LINES-2);
  
  	switch (sorting_by) {
  	  
! 	  case REVERSE ALIAS_SORT:	Centerline(elm_LINES-2,
  				catgets(elm_msg_cat, ElmSet, ElmASortRAlias,
  "This sort will order by alias name, in reverse alphabetical order"));
  					break;
! 	  case REVERSE NAME_SORT:	Centerline(elm_LINES-2,
  				catgets(elm_msg_cat, ElmSet, ElmASortRName,
  "This sort will order by user (real) name, in reverse alphabetical order"));
  					break;
! 	  case REVERSE TEXT_SORT:	Centerline(elm_LINES-2,
  				catgets(elm_msg_cat, ElmSet, ElmASortRText,
  "This sort will order aliases in the reverse order as listed in aliases.text"));
  					break;
  
! 	  case ALIAS_SORT:		Centerline(elm_LINES-2,
  				catgets(elm_msg_cat, ElmSet, ElmASortAlias,
  "This sort will order by alias name"));
  					break;
! 	  case NAME_SORT:		Centerline(elm_LINES-2,
  				catgets(elm_msg_cat, ElmSet, ElmASortName,
  "This sort will order by user (real) name"));
  					break;
! 	  case TEXT_SORT:		Centerline(elm_LINES-2,
  				catgets(elm_msg_cat, ElmSet, ElmASortText,
  "This sort will order aliases in the order as listed in aliases.text"));
  					break;
***************
*** 867,873 ****
  			    *s='_';
  		}
  
! 		optionally_enter(buffer, ypos, xpos, append_current, passwd);
  
  		if (save_info[x].flags & FL_NOSPC) {
  		    register char *s;
--- 874,882 ----
  			    *s='_';
  		}
  
! 		optionally_enter(buffer, ypos, xpos, 
! 				 (append_current ? OE_APPEND_CURRENT : 0) |
! 				 (passwd ? OE_PASSWD : 0));
  
  		if (save_info[x].flags & FL_NOSPC) {
  		    register char *s;
Index: WORK/src/out_utils.c
*** elm2.4.25/src/out_utils.c	Wed Feb  3 21:06:50 1993
--- WORK/src/out_utils.c	Fri Jun 14 11:01:08 1996
***************
*** 29,36 ****
  **/
  
  #include "headers.h"
  
- 
  static char err_buffer[SLEN];		/* store last error message */
  
  static char central_message_buffer[SLEN];
--- 29,36 ----
  **/
  
  #include "headers.h"
+ #include "me.h"
  
  static char err_buffer[SLEN];		/* store last error message */
  
  static char central_message_buffer[SLEN];
***************
*** 44,50 ****
  
  clear_error()
  {
! 	MoveCursor(LINES,0);
  	CleartoEOLN();
  	err_buffer[0] = '\0';
  }
--- 44,50 ----
  
  clear_error()
  {
! 	MoveCursor(elm_LINES,0);
  	CleartoEOLN();
  	err_buffer[0] = '\0';
  }
***************
*** 63,71 ****
  	if(batch_only)
  	  printf("%s\n\r", s);
  	else {
! 	  MoveCursor(LINES,0);
  	  CleartoEOLN();
! 	  PutLine0(LINES,(COLUMNS-strlen(s))/2,s);
  	  fflush(stdout);
  	}
  	strcpy(err_buffer, s);	/* save it too! */
--- 63,71 ----
  	if(batch_only)
  	  printf("%s\n\r", s);
  	else {
! 	  MoveCursor(elm_LINES,0);
  	  CleartoEOLN();
! 	  PutLine0(elm_LINES,(elm_COLUMNS-strlen(s))/2,s);
  	  fflush(stdout);
  	}
  	strcpy(err_buffer, s);	/* save it too! */
***************
*** 112,118 ****
  {
  	/** prompt user for input on LINES-1 line, left justified **/
  
! 	PutLine0(LINES-1,0,s);
  	CleartoEOLN();
  }
  
--- 112,118 ----
  {
  	/** prompt user for input on LINES-1 line, left justified **/
  
! 	PutLine0(elm_LINES-1,0,s);
  	CleartoEOLN();
  }
  
***************
*** 121,127 ****
  {
  	/** prompt user for input on LINES-3 line, left justified **/
  
! 	PutLine0(LINES-3,0,s);
  	CleartoEOLN();
  }
  
--- 121,127 ----
  {
  	/** prompt user for input on LINES-3 line, left justified **/
  
! 	PutLine0(elm_LINES-3,0,s);
  	CleartoEOLN();
  }
  
***************
*** 140,147 ****
  	/** display the message if set... **/
  
  	if (central_message_buffer[0] != '\0') {
! 	  ClearLine(LINES-15);
! 	  Centerline(LINES-15, central_message_buffer);
  	  fflush(stdout);
  	}
  }
--- 140,147 ----
  	/** display the message if set... **/
  
  	if (central_message_buffer[0] != '\0') {
! 	  ClearLine(elm_LINES-15);
! 	  Centerline(elm_LINES-15, central_message_buffer);
  	  fflush(stdout);
  	}
  }
***************
*** 151,154 ****
--- 151,159 ----
  	/** clear the central message buffer **/
  
  	central_message_buffer[0] = '\0';
+ }
+ 
+ void sleep_message() {
+   if (sleepmsg > 0)
+     sleep(sleepmsg);
  }
Index: WORK/src/pattern.c
*** elm2.4.25/src/pattern.c	Mon May 16 02:05:20 1994
--- WORK/src/pattern.c	Sun Jun 16 17:58:28 1996
***************
*** 79,84 ****
--- 79,85 ----
  
  #include "headers.h"
  #include "s_elm.h"
+ #include "me.h"
  
  static char pattern[SLEN] = { "" };
  static char alt_pattern[SLEN] = { "" };
***************
*** 114,119 ****
--- 115,121 ----
  	register int i, tagged=0, count=0, curtag = 0;
  	char		msg[SLEN];
  	static char     meta_pattern[SLEN];
+ 	int status;
  
  	if (delete_word == NULL) {
  	     tag_word = catgets(elm_msg_cat, ElmSet, ElmTag, "Tag");
***************
*** 128,134 ****
  	     enter_pattern = catgets(elm_msg_cat, ElmSet, ElmEnterPattern, "Enter pattern: ");
  	}
  
! 	PutLine2(LINES-3, strlen(Prompt), catgets(elm_msg_cat, ElmSet, ElmMessagesMatchPattern,
  	     "%s %s that match pattern..."), 
  	     function==TAGGED?tag_word: function==DELETED?delete_word:undelete_word, items);
  
--- 130,136 ----
  	     enter_pattern = catgets(elm_msg_cat, ElmSet, ElmEnterPattern, "Enter pattern: ");
  	}
  
! 	PutLine2(elm_LINES-3, strlen(Prompt), catgets(elm_msg_cat, ElmSet, ElmMessagesMatchPattern,
  	     "%s %s that match pattern..."), 
  	     function==TAGGED?tag_word: function==DELETED?delete_word:undelete_word, items);
  
***************
*** 153,159 ****
  		tagmsg, *def_ans_yes, *def_ans_no);
  	    }
  	
! 	    ch = want_to(msg, *def_ans_yes, LINES-2, 0);
  	    if (ch != *def_ans_no) {	/* remove tags... */
  	      for (i=0; i < message_count; i++) {
  	        if (inalias)
--- 155,161 ----
  		tagmsg, *def_ans_yes, *def_ans_no);
  	    }
  	
! 	    ch = want_to(msg, *def_ans_yes, elm_LINES-2, 0);
  	    if (ch != *def_ans_no) {	/* remove tags... */
  	      for (i=0; i < message_count; i++) {
  	        if (inalias)
***************
*** 166,184 ****
  	  }
  	}
  	
! 	PutLine0(LINES-2,0, enter_pattern);
  	CleartoEOLN();
  
! 	optionally_enter(meta_pattern, LINES-2, strlen(enter_pattern),
! 	  FALSE, FALSE);
  
! 	if (strlen(meta_pattern) == 0) {
! 	  ClearLine(LINES-2);
  	  return(curtag);
  	}
  
  	strcpy(meta_pattern, shift_lower(meta_pattern));   /* lowercase it */
  
  	if (inalias) {
  	  for (i = 0; i < message_count; i++) {
  	    if (name_matches(i, meta_pattern) ||
--- 168,196 ----
  	  }
  	}
  	
! 	PutLine0(elm_LINES-2,0, enter_pattern);
  	CleartoEOLN();
  
! 	status = optionally_enter(meta_pattern, elm_LINES-2, 
! 				  strlen(enter_pattern),
! 				  OE_REDRAW_MARK);
! 	while (status == REDRAW_MARK) {
! 	  PutLine0(elm_LINES-2,0, enter_pattern);
! 	  status = optionally_enter(meta_pattern, elm_LINES-2, 
! 				    strlen(enter_pattern),
! 				    OE_REDRAW_MARK|OE_APPEND_CURRENT);
! 	}
  
! 	if (status != 0 || strlen(meta_pattern) == 0) {
! 	  ClearLine(elm_LINES-2);
  	  return(curtag);
  	}
  
  	strcpy(meta_pattern, shift_lower(meta_pattern));   /* lowercase it */
  
+ 	if (function == DELETED && strcmp(meta_pattern, "tagged") == 0)
+           return(DeleteTagged());
+ 
  	if (inalias) {
  	  for (i = 0; i < message_count; i++) {
  	    if (name_matches(i, meta_pattern) ||
***************
*** 201,206 ****
--- 213,221 ----
  	  }
  	}
  	else {
+           if (strcmp(meta_pattern, "all") == 0)
+             count = DoAll(function);
+           else
  	  for (i = 0; i < message_count; i++) {
  	    if (from_matches(i, meta_pattern) ||
  	        subject_matches(i, meta_pattern)) {
***************
*** 217,223 ****
  	  }
  	}
  
! 	ClearLine(LINES-2);	/* remove "pattern: " prompt */
  	
  	if (count > 1) {
  	  error3(catgets(elm_msg_cat, ElmSet, ElmTaggedMessages,
--- 232,238 ----
  	  }
  	}
  
! 	ClearLine(elm_LINES-2);	/* remove "pattern: " prompt */
  	
  	if (count > 1) {
  	  error3(catgets(elm_msg_cat, ElmSet, ElmTaggedMessages,
***************
*** 265,275 ****
  
  	MCsprintf(buffer, entire_match_pattern, item);
  
! 	PutLine1(LINES-3,40, match_anywhere, items);
  	
! 	PutLine0(LINES-1,0, match_pattern);
  
! 	if (pattern_enter(pattern, alt_pattern, LINES-1,
  		strlen(match_pattern)+1, buffer)) {
  	  if (strlen(alt_pattern) == 0) {
  	    return(1);
--- 280,290 ----
  
  	MCsprintf(buffer, entire_match_pattern, item);
  
! 	PutLine1(elm_LINES-3,40, match_anywhere, items);
  	
! 	PutLine0(elm_LINES-1,0, match_pattern);
  
! 	if (pattern_enter(pattern, alt_pattern, elm_LINES-1,
  		strlen(match_pattern)+1, buffer)) {
  	  if (strlen(alt_pattern) == 0) {
  	    return(1);
***************
*** 394,400 ****
  	result = get_alias_address(aliases[message_number]->alias,TRUE,&dummy);
  	if (result != NULL)
  		return(in_string(shift_lower(result), pat) );
! 	return(NULL);
  }
  
  match_in_message(pat)
--- 409,415 ----
  	result = get_alias_address(aliases[message_number]->alias,TRUE,&dummy);
  	if (result != NULL)
  		return(in_string(shift_lower(result), pat) );
! 	return(0);
  }
  
  match_in_message(pat)
***************
*** 451,454 ****
--- 466,490 ----
  	}
  
  	return(0);
+ }
+ 
+ /* This will tag, delete, or undelete all or the currently visible messages */
+ DoAll(func)
+ int func;
+ {
+         int i, count = 0;
+ 
+         for (i=0; i < message_count; i++)
+                 if (!selected ||
+                     (selected && ison(headers[i]->status,VISIBLE))) {
+                         if (func == TAGGED)
+                                 headers[i]->status |= TAGGED;
+                         else if (func == DELETED)
+                                 headers[i]->status |= DELETED;
+                         else if (func == UNDELETE)
+                                 headers[i]->status &= ~DELETED;
+ 			show_new_status(i);
+                         ++count;
+                 }
+         return(count);
  }
Index: WORK/src/pgp.c
*** /tmp/null.14101	Tue Aug 20 22:05:34 1996
--- WORK/src/pgp.c	Mon Jul 22 21:52:14 1996
***************
*** 0 ****
--- 1,965 ----
+ #include "headers.h"
+ #include "me.h"
+ 
+ #ifdef USE_PGP
+ #include <sys/time.h>
+ #include <errno.h>
+ #ifdef BSD
+ #  include <sys/wait.h>
+ #endif
+ #include "menu.h"
+ 
+ /* these are defined in mailmsg1.c */
+ extern char expanded_to[VERY_LONG_STRING];
+ extern char expanded_cc[VERY_LONG_STRING];
+ extern char expanded_bcc[VERY_LONG_STRING];
+ extern char subject[VERY_LONG_STRING];
+ 
+ extern int errno;
+ 
+ int pgp_keeppassfor = 300; /* 5 minutes */
+ static char pgp_passphrase[STRING];
+ static int pgp_expires;
+ 
+ /* the column in which the userid begins in the 'pgp -kv' command output */
+ #define PGP_USERID_OFFSET 30
+ 
+ void
+ pgp_void_passphrase ()
+ {
+   int i;
+ 
+   for (i = 0 ; i < STRING ; i++)
+     pgp_passphrase[i] = '\0';
+   pgp_expires = 0;
+   return;
+ }
+ 
+ static int
+ QueryExpirePassphrase()
+ {
+   struct timeval now;
+ 
+   /* negative implies never expire */
+   if (pgp_keeppassfor < 0)
+     return(0);
+   gettimeofday(&now, 0);
+   if (now.tv_sec < pgp_expires) {
+     pgp_expires = now.tv_sec + pgp_keeppassfor;
+     return(0);
+   }
+   pgp_void_passphrase ();
+   return(1);
+ }
+ 
+ /* 'n' is the key we are looking for.  'k' is the list of possible matches
+    which contains 'len' entries.  prompt the user for which key s/he really
+    wants to use. */
+ static char *
+ PGPSelectKey (n, k, len)
+ 	char *n;
+ 	char **k;
+ 	int len;
+ {
+   int i;
+   char buf[STRING];
+   menu_t menu;
+ 
+   sprintf(buf, "Multiple keys match '%s':", n);
+   MenuInit (&menu, buf, "Select key or 'q' to quit: ", 0);
+ 
+   for (i = 0; i < len; i++)
+     MenuAdd(&menu, k[i]);
+ 
+   for (;;) {
+     switch (MenuLoop(&menu)) {
+     case 'q':
+       MenuDestroy(&menu);
+       return(0);
+     case '\n':
+     case '\r':
+       MenuDestroy(&menu);
+       return(k[MenuCurrent(menu)]);
+     }
+   }
+   /* not reached */
+ }
+ 
+ static int
+ GetPGPKey (name, target)
+ 	char *name;
+ 	char *target;
+ {
+   /* given "name", return the string to use during the pgp call to specify
+      the key which the user means.  return -1 on error. */
+   char buf[STRING], address[STRING], *c, **keys=0, *pc, userpart[STRING];
+   int i=0, keys_len=0, keys_max=0, return_val=0, start=0;
+   FILE *p;
+ 
+   if (!name || !target)
+     return(-1);
+ 
+   if (index(name, '@') == NULL && index(name, '(') == NULL && index(name, '<') == NULL) {
+     /* this is either just a username, or someone's real name.  in either
+        case it only needs to be checked once. */
+ 
+     strcpy(address, name);
+     i = 2;
+   }
+   else {
+     get_address_from (name, address);
+   
+     i=0;
+     while (address[i] && address[i] != '@') {
+       userpart[i] = address[i];
+       i++;
+     }
+     userpart[i] = '\0';
+ 
+     i = 0;
+   }
+   c = address;
+ 
+   /* the following loop first checks to see if any keys with the full
+      address, or real name, or finally the username exist */
+ 
+   for (;;) {
+     int fd[2];
+ 
+     if (pipe (fd) == -1) {
+       dprint (1, (debugfile, "GetPGPKey(): ERROR: pipe (errno %d)\n", errno));
+       return -1;
+     }
+ 
+     while (*c && isspace (*c)) c++; /* move past any leading space! */
+     
+     if (fork () == 0) {
+       int tmp;
+       
+       setgid(groupid);
+       setuid(userid);
+ 
+       close (fd[0]);
+       close (1);
+       dup (fd[1]);
+       close (fd[1]);
+ 
+       execl(PGP_PATH, 
+ 	    PGP_PATH,"+verbose=0", "+language=en", "-kv", c, (char *)0);
+ 
+       tmp = errno;
+       perror(PGP_PATH);
+       _exit(tmp);
+     }
+ 
+     close (fd[1]);
+     p = fdopen (fd[0], "r");
+     if (p == NULL) {
+       dprint (1, (debugfile, 
+ 		  "GetPGPKey(): ERROR: fdopen (errno %d)\n", errno));
+       return -1;
+     }
+ 
+     while (fgets(buf, STRING, p) != NULL) {
+       /* see if we've reached the beginning of the key listings... */
+       if (!start && strncmp(buf, "pub", 3)==0)
+ 	  start=1;
+ 
+       if (start) {
+ 
+ 	/* if we've read all the keys, stop here */
+ 	if (buf[0] != 'p' && buf[0] != ' ')
+ 	  break;
+ 
+ 	if (keys_len == keys_max)
+ 	  keys = (char**)DynamicArray(keys, sizeof(char*), &keys_max, 5);
+ 	
+ 	pc = rindex(buf, '\n');
+ 	if (!pc) /* this shouldn't happen! */
+ 	  continue;
+ 	*pc = '\0';
+ 	
+ 	pc = buf + PGP_USERID_OFFSET;
+ 	keys[keys_len] = (char*)safe_malloc(sizeof(char)*(strlen(pc)+1));
+ 	strcpy(keys[keys_len], pc);
+ 	++keys_len;
+       }
+     }
+     pclose(p);
+     if (keys_len > 0 || i > 1)
+       break;
+     else {
+       if (i == 0) {
+ 	get_real_name(name, address, sizeof (address));
+ 
+ 	/* if there was no real name, go on to the userpart check */
+ 	if (strcmp(name, address) == 0) {
+ 	  c = userpart;
+ 	  i++;
+ 	}
+       } else if (i == 1)
+ 	c = userpart;
+       i++;
+     }
+   }
+ 
+   if (keys_len == 1) /* perfect match! */
+     get_address_from(keys[0], target);
+     /*
+     ** strcpy(target,keys[0]); 
+     **  changed back to get_address_from() to remove leading blanks! -VPa
+     */
+   else if (keys_len > 1) { /* ask the user which, if any, s/he meant */
+     c = PGPSelectKey(name, keys, keys_len);
+     if (c)
+       get_address_from(c, target);
+     else {
+       target[0] = '\0';
+       return_val = -1;
+     }
+   } else
+     return_val = -1;
+ 
+   DestroyDynamicArray(keys);
+ 
+   return(return_val);
+ }
+ 
+ static int
+ pgp_call (filename, opts)
+ 	char *filename;
+ 	int opts;
+ {
+   char tobuf[VERY_LONG_STRING] = {0};
+   char frombuf[VERY_LONG_STRING] = {0};
+   int status;
+ 
+   if (opts & PGP_MESSAGE) {
+     /* build up the list of recipients */
+     strcpy(tobuf, expanded_to);
+     if (expanded_cc[0] != '\0') {
+       strcat(tobuf, ", ");
+       strcat(tobuf, expanded_cc);
+     }
+     if (expanded_bcc[0] != '\0') {
+       strcat(tobuf, ", ");
+       strcat(tobuf, expanded_bcc);
+     }
+     /* If the message is to be encrypted, give the user a chance to edit
+      * the list of ids to encrypt to since the given address may not always
+      * be correct.
+      */
+   redraw:
+     PutLine0 (elm_LINES-2, 0, "To: ");
+     status = optionally_enter (tobuf, elm_LINES-2, 4, 
+ 			       OE_APPEND_CURRENT|OE_REDRAW_MARK);
+     if (REDRAW_MARK == status)
+       goto redraw;
+     if (status < 0 || tobuf[0] == '\0')
+       return FALSE;
+   }
+ 
+   if (pgp_askpgpsig && (opts & PGP_SIGNED_MESSAGE)) {
+     /* If the message is to be signed, give the user a chance to specify
+      * with which signature.
+      */
+     strcat(frombuf, username);
+   redraw2:
+     PutLine0 (elm_LINES-2, 0, "From: ");
+     status = optionally_enter (frombuf, elm_LINES-2, 6,
+ 			       OE_APPEND_CURRENT|OE_REDRAW_MARK);
+     if (REDRAW_MARK == status)
+       goto redraw2;
+     if (status < 0 || frombuf[0] == '\0')
+       return FALSE;
+   }
+   return (pgp_encrypt (filename, tobuf, frombuf, opts, auto_cc));
+ }
+ 
+ int
+ pgp_encrypt (filename, ids, sig, opts, metoo)
+ 	char *filename, *ids, *sig;
+ 	int opts, metoo;
+ {
+   int i, id_len=0, id_max=0, st, usepgppass=FALSE, fd[2];
+   char
+     keyid[STRING], buf[VERY_LONG_STRING], buf2[STRING], **id_array=0, *c,
+     *p;
+   
+   dprint (2, (debugfile, "pgp_encrypt(): ids=\"%s\", signwith=\"%s\", encrypt=%s, sign=%s\n", ids, sig, opts & PGP_MESSAGE ? "TRUE" : "FALSE", opts & PGP_SIGNED_MESSAGE ? "TRUE" : "FALSE"));
+ 
+   p = ids;
+   /* If this message is to be encrypted, look up the keys of all the
+      recipients */
+   if (opts & PGP_MESSAGE) {
+     i=0;
+     while ((c = strtok(p, ",")) != NULL) {
+       if (GetPGPKey(c, keyid) == -1) {
+ 	error1("Couldn't find key matching '%s'!",c);
+ 	return FALSE;
+       }
+       if (id_len == id_max)
+ 	id_array = (char**)DynamicArray(id_array, sizeof(char*), &id_max, 25);
+       id_array[id_len] = 
+ 	(char*)safe_malloc((strlen(keyid) + 1) * sizeof(char));
+       strcpy(id_array[id_len], keyid);
+       id_len++;
+       p=NULL;
+     }
+   }
+ 
+   if ((opts & PGP_SIGNED_MESSAGE) && pgp_keeppass && pgp_goodPassphrase()) {
+     usepgppass = TRUE;
+     pipe(fd);
+   }
+ 
+   /* build up the command */
+   buf[0] = '\0';
+   if (usepgppass) {
+     sprintf(buf2, "PGPPASSFD=%d; export PGPPASSFD; ", fd[0]);
+     strcat(buf, buf2);
+   }
+   strcat(buf, PGP_PATH);
+   if (metoo)
+     strcat(buf, " +encrypttoself=on");
+   if (usepgppass)
+     strcat(buf, " +batchmode");
+   if (opts & PGP_SIGNED_MESSAGE)
+     strcat(buf," +clearsig=on");
+ 
+   strcat(buf, " +verbose=0 -atw");
+ 
+   if (opts & PGP_SIGNED_MESSAGE)
+     strcat(buf, "s");
+   if (opts & PGP_MESSAGE)
+     strcat(buf, "e");
+ 
+   if (pgp_askpgpsig && (opts & PGP_SIGNED_MESSAGE)) {
+     strcat(buf, "u ");
+     strcat(buf, sig);
+   }
+ 
+   strcat(buf, " ");
+   strcat(buf, filename);
+ 
+   /* add all of the userid's protected inside quotes to prevent shell
+      no-no's */
+   if (opts & PGP_MESSAGE)
+     for (i=0; i<id_len; i++) {
+       strcat(buf, " '");
+       strcat(buf, id_array[i]);
+       strcat(buf, "'");
+     }
+   DestroyDynamicArray(id_array); /* don't need this any more... */
+ 
+   if (usepgppass) {
+ /*    strcat(buf, " > /dev/null 2>&1");/**/
+     Raw(OFF);
+     ClearScreen();/**/
+ 
+     write(fd[1], pgp_passphrase, strlen(pgp_passphrase));
+     write(fd[1], "\n", 1); /* pgp expects this as a line terminator! */
+     close(fd[1]);
+   }
+   else {
+     Raw(OFF);
+     ClearScreen();
+     printf("Executing: %s\n\n", buf);
+   }
+   st = system_call(buf, 0);
+ /*  if (!usepgppass)/**/
+     Raw(ON);
+   
+   if (st == 0) { /* pgp returns zero upon success */
+     /* copy the file into it's final destination */
+     sprintf(buf, "%s.asc", filename);
+ #ifdef RENAME
+     if (rename(buf, filename) < 0) {
+       error ("Could not rename temporary file!");
+       return FALSE;
+     }
+ #else
+     if (link(buf, filename) < 0) {
+       Centerline(elm_LINES, "Could not create link to temporary file!");
+       return FALSE;
+     }
+     /* this is not fatal, but a warning should be given */
+     if (unlink(buf) < 0)
+       error ("Could not unlink temporary file!");
+ #endif
+   }
+   else {
+     error ("pgp returned a non-zero value!");
+     if (pgp_keeppass)
+       pgp_void_passphrase ();
+     return FALSE;
+   }
+   return opts;
+ }
+ 
+ int
+ pgp_menu (filename)
+ 	char *filename;
+ {
+   int update = TRUE;
+ 
+   for (;;) {
+     if (update) {
+       MoveCursor (elm_LINES-3, 0);
+       CleartoEOS ();
+       Centerline (elm_LINES-2, "e)ncrypt, s)ign, b)oth encrypt and sign");
+       PutLine0 (elm_LINES-3, 0, "pgp: ");
+       update = FALSE;
+     }
+     switch(ReadCh(REDRAW_MARK)) {
+     case 'e':
+       Write_to_screen("Encrypt", 0);
+       return (pgp_call (filename, PGP_MESSAGE));
+     case 's':
+       Write_to_screen("Sign", 0);
+       return (pgp_call (filename, PGP_SIGNED_MESSAGE));
+     case 'b':
+       Write_to_screen("Sign and Encrypt", 0);
+       return (pgp_call (filename, PGP_MESSAGE | PGP_SIGNED_MESSAGE));
+     case '\n':
+     case '\r':
+       return FALSE;
+     case REDRAW_MARK:
+     case ctrl('L'):
+       update = 1;
+     }
+   }
+   /* not reached */
+ }
+ 
+ int
+ pgp_mail_public_key ()
+ {
+   char userid[SLEN], pgpkey[SLEN], tmpfil[STRING], cmd[STRING], subj[STRING];
+   int status;
+   int need_redraw = FALSE;
+ 
+   userid[0] = '\0';
+   pgpkey[0] = '\0';
+ 
+   PutLine0(elm_LINES-2, 0, "Enter userid of public key: ");
+   CleartoEOS ();
+   status = optionally_enter(userid, elm_LINES-2, 28, OE_REDRAW_MARK);
+   while(REDRAW_MARK == status) {
+     PutLine0(elm_LINES-2, 0, "Enter userid of public key: ");
+     status = optionally_enter(userid, elm_LINES-2, 28, 
+ 			      OE_REDRAW_MARK|OE_APPEND_CURRENT);
+     need_redraw = TRUE;
+   }
+   if ( status != 0)
+     return(need_redraw);
+ 
+   if (GetPGPKey(userid, pgpkey) < 0) {
+     Centerline(elm_LINES, "Sorry, couldn't find that userid.");
+     ClearLine(elm_LINES-2);
+     return(TRUE);
+   }
+   sprintf(tmpfil, "%selm.%d", temp_dir, getpid());
+   sprintf(cmd, "%s +verbose=0 -kxa '%s' %s > /dev/null 2>&1", PGP_PATH, pgpkey, tmpfil);
+   if (system_call(cmd, 0) == 0) 
+     sprintf(included_file, "%s.asc", tmpfil);
+   else {
+     ClearLine(elm_LINES);
+     Centerline(elm_LINES, "pgp returned a non-zero value!");
+     return(TRUE);
+   }
+ 
+   /* set the default subject for this message */
+   sprintf(subj, "PGP public key for %s", pgpkey);
+ 
+   pgp_status = PGP_PUBLIC_KEY;
+ 
+   /* Now send the message off! */
+   send_msg ("", "", subj, 0, 0);
+ 
+   unlink (included_file); /* make sure to clean up. */
+   included_file[0] = '\0';
+   pgp_status = 0; /* reset */
+   return(TRUE);
+ }
+ 
+ static int
+ GetPassphrase ()
+ {
+   struct timeval now;
+   int status;
+ 
+ redraw:
+   PutLine0(elm_LINES-2, 0, "Please enter your PGP passphrase: ");
+   CleartoEOS();
+   
+   status = optionally_enter(pgp_passphrase, elm_LINES-2, 34, 
+ 			    OE_PASSWD|OE_REDRAW_MARK);
+   if (REDRAW_MARK == status)
+     goto redraw;
+ 
+   if (status != 0)
+     return(0);
+   gettimeofday(&now, 0);
+   if (pgp_keeppassfor > 0)
+     pgp_expires = now.tv_sec + pgp_keeppassfor;
+   return(pgp_passphrase[0] != '\0');
+ }
+ 
+ int
+ pgp_goodPassphrase()
+ {
+   if (pgp_passphrase[0] == '\0' || QueryExpirePassphrase())
+     return(GetPassphrase());
+   else
+     return(1);
+ }
+ 
+ /* opens up a PGP process as a child and returns its stdin and stdout */
+ int
+ pgp_decrypt_init (fpin, fpout, opts)
+ FILE **fpin, **fpout;
+ int opts; /* PGP_MESSAGE or PGP_SIGNED_MESSAGE */
+ {
+   int pgp_child_in[2];
+   int pgp_child_out[2];
+   int passpipe[2];
+   int usepass=FALSE;
+   int fork_ret;
+   char cmd[STRING];
+ 
+   dprint (2, (debugfile, "pgp_descrypt_init() called with opts=%d\n", opts));
+ 
+   if (pipe(pgp_child_in) == -1)
+     return(-1);
+   if (pipe(pgp_child_out) == -1)
+     return(-1);
+   
+   if ((opts & PGP_MESSAGE) && pgp_keeppass) {
+     if (pipe(passpipe) == -1) {
+       close(pgp_child_in[0]);
+       close(pgp_child_out[0]);
+       close(pgp_child_in[1]);
+       close(pgp_child_out[1]);
+       return(-1);
+     }
+     usepass = TRUE;
+   }
+   dprint (3, (debugfile, "usepass = %d.\n", usepass));
+ 
+   Raw(OFF);
+   ClearScreen();
+ 
+   /* Tell the user why they are waiting */
+   if (opts & PGP_MESSAGE) {
+       Write_to_screen("Running pgp: Decrypting message...\n", 0);
+   } else if (opts & PGP_SIGNED_MESSAGE) {
+     Write_to_screen("Running pgp: Checking signature...\n", 0);
+   } else {
+     Write_to_screen("Running pgp ...\n", 0);
+   }
+ 
+   if ((fork_ret = fork()) == 0) {
+     close (pgp_child_in[1]);
+     close (0);
+     dup (pgp_child_in[0]);
+     close (pgp_child_in[0]);
+     
+     close (pgp_child_out[0]);
+     close (1);
+     dup (pgp_child_out[1]);
+     close (pgp_child_out[1]);
+     
+     /* build up the command */
+     if (usepass) {
+       close (passpipe[1]);
+       sprintf (cmd, "PGPPASSFD=%d; export PGPPASSFD; ",
+ 	       passpipe[0]);
+     }
+     else
+       cmd[0] = '\0';
+     strcat(cmd,PGP_PATH);
+     strcat(cmd," -f +verbose=0");
+     if (usepass || opts == PGP_SIGNED_MESSAGE)
+       strcat(cmd, " +batchmode");
+     _exit (system_call(cmd,0));	
+   }
+   
+   close (pgp_child_in[0]);
+   close (pgp_child_out[1]);
+   
+   /* now send the passphrase if needed */
+   if (usepass) {
+     dprint(3,(debugfile,"pgp_decrypt_init: sending pgp passphrase.\n"));
+     close (passpipe[0]);
+     write (passpipe[1], pgp_passphrase, strlen(pgp_passphrase));
+     write (passpipe[1], "\n", 1);
+     close (passpipe[1]);
+   }
+   
+   if ((*fpin = fdopen(pgp_child_out[0], "r")) == 0) {
+     Raw(ON);
+     return(-1);
+   }
+   if ((*fpout = fdopen(pgp_child_in[1], "w")) == 0) {
+     Raw(ON);
+     return(-1);
+   }
+   
+   return(fork_ret);
+ }
+ 
+ int
+ pgp_extract_public_key ()
+ {
+   char tempfile[STRING], buf[STRING];
+   FILE *fpout;
+   int err;
+ 
+   sprintf(tempfile,"%selm.%d",temp_dir,getpid());
+   fpout=safeopen_rdwr(tempfile);
+   if (!fpout) {
+     error1("Could not open temp file %s for writing!", tempfile);
+     return FALSE;
+   }
+   copy_message(mailfile,headers[current-1],
+ 	       "",fpout,0);
+   fclose(fpout);
+   ClearScreen();
+   Raw(OFF);
+   sprintf(buf,"%s +verbose=0 %s", PGP_PATH, tempfile);
+   printf("Executing: %s\n\n", buf);
+   system_call(buf, 0);
+   PressAnyKeyToContinue();
+   Raw(ON);
+   unlink(tempfile);
+   return TRUE;
+ }
+ 
+ #ifdef MIME
+ int
+ pgp_mime_opts (s)
+      char *s;
+ {
+   char value[STRING];
+ 
+   if (s) {
+     if (mime_get_param ("format", value, s, sizeof(value))) {
+       if (istrcmp (value, "keys-only") ==  0)
+ 	return PGP_PUBLIC_KEY;
+     }
+     if (mime_get_param ("x-action", value, s, sizeof (value))) {
+       if (istrcmp (value, "encryptsign") == 0)
+ 	return (PGP_MESSAGE | PGP_SIGNED_MESSAGE);
+       else if (istrcmp (value, "encrypt") == 0)
+ 	return PGP_MESSAGE;
+       else if (istrcmp (value, "sign") == 0)
+ 	return PGP_SIGNED_MESSAGE;
+       else if (istrcmp (value, "signclear") == 0)
+ 	return PGP_SIGNED_MESSAGE;
+     }
+   }
+   return PGP_MESSAGE;
+ }
+ 
+ static int wait_pgp P_((int,int)); /* Prototype */  
+ 
+ static int wait_pgp(raw,child)
+      int raw;
+      int child;
+ {
+ #if defined(BSD) && !defined(WEXITSTATUS)
+   union wait status;
+ #else
+   int status;
+ #endif
+ 
+   int w,stat=-1;
+   while ((w = wait(&status)) != child)
+     if (w == -1 && errno != EINTR)
+       break;
+   if (w == child) {
+ #ifdef	WEXITSTATUS
+     stat = WEXITSTATUS(status);
+ #else
+ # ifdef	BSD
+     stat = status.w_retcode;
+ # else
+     stat = status;
+ # endif
+ #endif
+   }
+   PressAnyKeyToContinue();
+ 
+   if (raw)
+     Raw (ON);
+ 
+   return stat;
+ }
+ 
+ void
+ pgp_decode (m, s_in, s_out)
+      mime_t *m;
+      in_state_t  *s_in;
+      out_state_t *s_out;
+ {
+   /* This procedure implements the de-facto standard for using PGP with MIME.
+    * Content-Type: application/pgp
+    * Required-Parameters: none
+    * Optional parameters: format, x-action
+    *     format = mime | text | keys-only
+    *         mime : indicates that the signed/encrypted body contains a MIME
+    *                compliant body and should be parsed recursively.
+    *         text : [DEFAULT if there is no format option].  This option
+    *                means that the encrypted/signed data should be presented
+    *                to the user after processing, no additional processing
+    *                needed.
+    *         keys-only:
+    *                The data in the body represents public key data only
+    *     x-action = encryptsign | encrypt | sign
+    *         This keyword is meant to be helpful to the application, but is
+    *         not required, and may not even be necessary to look at.
+    *
+    *         encryptsign : the application/pgp data is both signed and
+    *                       encrypted.
+    *         encrypt     : the data is encrypted only
+    *         sign        : the data is signed only
+    */
+ 
+   char tempfile[STRING], buffer[STRING];
+   FILE *pgpout, *pgpin, *tmpfp=NULL, *decode_fp = NULL;
+   int
+     child,
+     inbody = FALSE,
+     opts,
+     len,
+     raw,
+     stat = -1,
+     bytes = 0,
+     nested = FALSE; /* PGP output should be parsed as a MIME body */
+   mime_t *tmpmt;
+   
+   in_state_t newstate2;
+   in_state_clear(&newstate2,STATE_in_file);
+ 
+   raw = RawState ();
+ 
+   if (mime_get_param ("format", buffer, m->type_opts, sizeof (buffer)) &&
+       (istrcmp (buffer, "mime") == 0)) {
+     nested = TRUE;
+     dprint (3, (debugfile, "pgp_decode: format=mime\n"));
+     
+     sprintf (tempfile, "%selmPT%d", temp_dir, getpid ());
+     
+     if (NULL == (tmpfp = safeopen_rdwr(tempfile))) {
+       error("Failed to create file for decoding.");
+       state_puts("[Failed to create file for decoding.]\n",s_out);      
+       return;
+     }
+ 
+     unlink (tempfile); /* Filename is no longer needed ... */
+   }
+   else
+     tmpfp = NULL;
+ 
+   opts = pgp_mime_opts (m->type_opts);
+ 
+   /* Now metapager does not ask passphrase -- this is called indirectly
+    * via copy_message    -KEH
+    */
+   if ((opts & PGP_MESSAGE) && pgp_keeppass) {
+     if (!pgp_goodPassphrase()) {
+       error("Decrypting message... Bad PGP passphrase.");
+       state_puts("[Decrypting message... Bad PGP passphrase]\n",s_out);
+       return;
+     }
+   }
+ 
+   buffer[0] = '\0';
+   if (opts & PGP_PUBLIC_KEY) {
+     strcpy (buffer, "(** This message contains PGP public key(s)");
+     strcat (buffer, " **)\n\n");
+     state_puts (buffer, s_out);
+   }
+ 
+   if ((child = pgp_decrypt_init (&pgpout, &pgpin, opts)) == -1) {
+     state_puts ("[internal error while calling pgp, skipping...]\n", s_out);
+     if (raw)
+       Raw (ON);
+     return;
+   }
+ 
+   /* Decode Content-transfer-encoding */
+   
+   if (decode_fp = arrange_decoded(m,s_in,s_out,&newstate2)) {  
+     /* If arrange_decoded was treated this as text, don't consider
+      * about binary PGP files -- that happens when type is text/x-pgp
+      */
+     int was_text = is_text_type (mime_types[m->type], m->subtype, 
+ 				 m->encoding);
+ 
+     dprint (4, (debugfile, "pgp_decode: was_text = %d\n", was_text));
+ 
+     /* Print text before PGP armor 
+      *
+      */
+ 
+     len = state_getl (buffer, sizeof (buffer), &newstate2);    
+     if ( len < 1) {
+       state_puts("[No text in PGP section.]\n",s_out);
+     } else {
+       int c = (unsigned char) buffer[0],i;
+ 
+       if (!pgp_noarmor)
+ 	goto pgp_found;
+ 
+       if (!was_text) {
+ 	/* Check if that is binary PGP file */
+ 	if (c & 0x80) {
+ 	  /* In PGP block have type byte which have higgest bit set always. 
+ 	   * so if in first byte have higgest bit set assume PGP binary
+ 	   * file.
+ 	   */
+ 	  dprint (4, (debugfile, 
+ 		      "pgp_decode: first byte = %d -- assume binary PGP file\n",
+ 		    c));
+ 	  goto pgp_found;
+ 	}
+ 	/* Another check */
+ 	for (i = 0; i < len; i++) {
+ 	  if (buffer[i] == 0) {
+ 	    dprint (4, (debugfile, 
+ 			"pgp_decode: byte idx=%d is zero -- binary file?\n",
+ 			i));
+ 	    state_puts("[Binary file, but does not look like PGP]\n",s_out);
+ 	    goto pgp_found;
+ 	  }
+ 	}
+       }
+       if (strncmp(buffer, "-----BEGIN PGP", 14) == 0) 
+ 	goto pgp_found;
+ 
+       state_puts("[There is text before PGP section.]\n",s_out);
+ 
+       if (set_filter(m,s_out)) { /* Character set filtering */
+ 	do {
+ 	  state_add_prefix(s_out);
+ 
+ 	  /* Take care of CRLF => LF conversion in here because
+ 	   * arrange_decoded() is treating application/pgp as
+ 	   * binary type (it need to treate it as binary because
+ 	   * it may be binary)
+ 	   */
+ 	  if (!was_text &&
+ 	      len > 1 &&
+ 	      buffer[len - 1] == '\n' &&
+ 	      buffer[len - 2] == '\r') {
+ 	    buffer[len - 2] = '\n';
+ 	    buffer[len - 1] = '\0';
+ 	    len--;
+ 	  }
+ 
+ 	  state_put(buffer,len,s_out);
+ 
+ 	} while ((len = state_getl (buffer, sizeof (buffer), &newstate2)) > 0
+ 		 && strncmp(buffer, "-----BEGIN PGP", 14) != 0 );
+ 
+       } else {
+ 	  dprint (4, (debugfile, 
+ 		      "pgp_decode: Unsupported character set?\n"));
+       }
+ 
+     pgp_found:
+       s_out -> filter = NULL_filter;
+ 
+       if ( len < 1) {
+ 	state_puts("[No text in PGP section.]\n",s_out);
+       } else {
+ 	do {
+ 	  fwrite(buffer,1,len,pgpin);
+ 	  bytes += len;
+ 	}  while ((len = state_getl (buffer, sizeof (buffer), 
+ 				     &newstate2)) > 0);
+       }
+     }
+     fclose (pgpin);
+ 
+     sprintf(buffer,"-- Start of PGP%s%s section.\n",
+ 	    opts & PGP_SIGNED_MESSAGE ? " signed" : "",
+ 	    opts & PGP_MESSAGE ? " encoded": "");
+     state_puts(buffer,s_out);
+ 
+     bytes = 0;
+     while ((len = mail_gets (buffer, sizeof (buffer), pgpout)) > 0) {
+       if (nested) {
+ 	if (buffer[0] == '\n' || (buffer[0] == '\r' && buffer[1] == '\n'))
+ 	  inbody = TRUE;
+ 	fputs (buffer, tmpfp);
+ 	if (inbody)
+ 	  bytes += len;
+       } else {
+ 	state_add_prefix(s_out);
+ 	state_puts(buffer,s_out);
+       }
+     }
+     fclose (pgpout);
+ 
+     if (nested) {
+       struct in_state s2_in;
+       in_state_clear(&s2_in,STATE_in_file);
+       
+       dprint (3, (debugfile, "pgp_decode: parsing decrypted data as MIME\n"));
+ 
+       if (EOF == fflush(tmpfp)) {
+ 	error("Error when flushing temporary file.");
+ 	state_puts("[Error when flushing temporary file.]\n",s_out);
+       }
+       rewind(tmpfp); /* Rewind it for reading */
+ 
+       tmpmt = mime_read_header (tmpfp, 0);
+       tmpmt->length = bytes;
+ 
+       if (tmpmt->flags & MIME_RFC822) {
+ 	dprint(9,(debugfile,"pgp_decode- (parsing) RFC822\n"));
+ 	fseek (tmpfp, tmpmt->offset, SEEK_SET);
+ 	tmpmt->parts = rfc822_parse (tmpfp, tmpmt->length);
+       }
+       else if (tmpmt->type == MIME_TYPE_MULTIPART) {
+ 	char subbound[80];
+ 	fseek (tmpfp, tmpmt->offset, SEEK_SET);
+ 	mime_get_boundary (subbound, tmpmt->type_opts, sizeof (subbound));
+ 	dprint(9,(debugfile,
+ 		  "pgp_decode- (parsing) MULTIPART; boundary=%s\n",
+ 		  subbound));
+ 	tmpmt->parts = multipart_parse (tmpfp, tmpmt->length, subbound, 
+ 					tmpmt->flags);
+       }
+ 
+       set_in_state_file(tmpfp,&s2_in);
+ 
+       mime_decode (tmpmt, &s2_in, s_out);
+       mime_destroy (tmpmt);
+ 
+       in_state_destroy(&s2_in);
+ 
+       fclose (tmpfp);
+     }
+   } else { 
+     sprintf(buffer,"-- Start of PGP%s%s section -- can't decode content-transfer-encoding\n",
+ 	    opts & PGP_SIGNED_MESSAGE ? " signed" : "",
+ 	    opts & PGP_MESSAGE ? " encoded": "");
+     state_puts(buffer,s_out);    
+   }
+   
+   stat = wait_pgp(raw,child);
+ 
+   sprintf(buffer,"-- End of PGP%s%s section%s\n",
+ 	  opts & PGP_SIGNED_MESSAGE ? " signed" : "",
+ 	  opts & PGP_MESSAGE ? " encoded" : "",
+ 	  stat ? ", PGP failed!" : ".");
+   state_puts(buffer,s_out);
+ 
+   in_state_destroy(&newstate2);
+ }
+ #endif /* MIME */
+ #endif /* USE_PGP */
Index: WORK/src/pmalloc.c
*** elm2.4.25/src/pmalloc.c	Fri Mar 11 22:59:02 1994
--- WORK/src/pmalloc.c	Thu Jun 13 23:37:23 1996
***************
*** 76,82 ****
  
  	if (size > free_mem) {
  	  if ((our_block = (char *) malloc(PMALLOC_BUFFER_SIZE)) == NULL) {
! 	    MoveCursor(LINES,0);
  	    Raw(OFF);
  	    fprintf(stderr, catgets(elm_msg_cat, ElmSet, ElmCouldntMallocBytes,
  		    "\n\nCouldn't malloc %d bytes!!\n\n"),
--- 76,82 ----
  
  	if (size > free_mem) {
  	  if ((our_block = (char *) malloc(PMALLOC_BUFFER_SIZE)) == NULL) {
! 	    MoveCursor(elm_LINES,0);
  	    Raw(OFF);
  	    fprintf(stderr, catgets(elm_msg_cat, ElmSet, ElmCouldntMallocBytes,
  		    "\n\nCouldn't malloc %d bytes!!\n\n"),
Index: WORK/src/quit.c
*** elm2.4.25/src/quit.c	Thu Nov 26 02:46:43 1992
--- WORK/src/quit.c	Sun Jun 16 17:58:27 1996
***************
*** 42,47 ****
--- 42,48 ----
  
  #include "headers.h"
  #include "s_elm.h"
+ #include "me.h"
  #include <errno.h>
  
  extern int errno;		/* system error number on failure */
***************
*** 53,103 ****
  quit(prompt)
  int prompt;
  {
! 	/* a wonderfully short routine!! */
  
! 	if (leave_mbox(FALSE, TRUE, prompt) == -1)
! 	  /* new mail - leave not done - can't change to another file yet
! 	   * check for change in mailfile_size in main() will do the work
! 	   * of calling newmbox to add in the new messages to the current
! 	   * file and fix the sorting sequence that leave_mbox may have
! 	   * changed for its own purposes */
! 	  return;
  
! 	leave(0);
  }
  
  int
  resync()
  {
! 	/** Resync on the current folder. Leave current and read it back in.
! 	    Return indicates whether a redraw of the screen is needed.
! 	 **/
! 	int  err;
! 
! 	  if(leave_mbox(TRUE, FALSE, TRUE) ==-1)
! 	    /* new mail - leave not done - can't change to another file yet
! 	     * check for change in mailfile_size in main() will do the work
! 	     * of calling newmbox to add in the new messages to the current
! 	     * file and fix the sorting sequence that leave_mbox may have
! 	     * changed for its own purposes */
! 	    return(FALSE);
! 
! 	  if ((errno = can_access(cur_folder, READ_ACCESS)) != 0) {
! 	    if (strcmp(cur_folder, defaultfile) != 0 || errno != ENOENT) {
! 	      err = errno;
! 	      MoveCursor(LINES, 0);
! 	      Raw(OFF);
! 	      dprint(1, (debugfile,
! 		     "Error: given file %s as folder - unreadable (%s)!\n", 
! 		     cur_folder, error_description(err)));
! 	      fprintf(stderr, catgets(elm_msg_cat, ElmSet, ElmCantOpenFolderRead,
! 			"Can't open folder '%s' for reading!\n"), cur_folder);
! 	      leave(0);
! 	    }
! 	  }
! 
! 	  newmbox(cur_folder, FALSE);
! 	  return(TRUE);
  }
  
  char helpmsg[VERY_LONG_STRING];
--- 54,140 ----
  quit(prompt)
  int prompt;
  {
!   int status;
  
! requit:
!   status = leave_mbox(FALSE, TRUE, prompt);
!   if ( status == -1)
!     /* new mail - leave not done - can't change to another file yet
!      * check for change in mailfile_size in main() will do the work
!      * of calling newmbox to add in the new messages to the current
!      * file and fix the sorting sequence that leave_mbox may have
!      * changed for its own purposes */
!     return;
! 
!   if (status < 0) {
!     int ans;
!     error("Failed to leave folder!");
!     sleep_message();
!     
!     if (!prompt) 
!       return;
!     
!   again1:
!     ans = want_to("Failed to leave folder: Try to quit again ? [P]anic",
! 		  *def_ans_no,elm_LINES,1);
!     if (ans = ('L'&31)) {
!       ClearScreen();      
!       goto again1;
!     }
!     if (ans == *def_ans_no)
!       return;
!     if (ans == *def_ans_yes) {
!       clear_error();
!       goto requit;
!     }
!     if (ans == 'P')
!       emergency_exit();
!     return;
!   }
  
!   leave(0);
  }
  
  int
  resync()
  {
!   int result;
!   /** Resync on the current folder. Leave current and read it back in.
!     Return indicates whether a redraw of the screen is needed.
!     **/
!   int  err;
! 
!   result = leave_mbox(TRUE, FALSE, TRUE);
!   if( result == -1)
!     /* new mail - leave not done - can't change to another file yet
!      * check for change in mailfile_size in main() will do the work
!      * of calling newmbox to add in the new messages to the current
!      * file and fix the sorting sequence that leave_mbox may have
!      * changed for its own purposes */
!     return(FALSE);
! 
!   if (result < 0) {
!     error("Failed to resync folder!");
!     sleep_message();
!     return FALSE;
!   }
!   
!   if ((errno = can_access(cur_folder, READ_ACCESS)) != 0) {
!     if (strcmp(cur_folder, defaultfile) != 0 || errno != ENOENT) {
!       err = errno;
!       MoveCursor(elm_LINES, 0);
!       Raw(OFF);
!       dprint(1, (debugfile,
! 		 "Error: given file %s as folder - unreadable (%s)!\n", 
! 		 cur_folder, error_description(err)));
!       fprintf(stderr, catgets(elm_msg_cat, ElmSet, ElmCantOpenFolderRead,
! 			      "Can't open folder '%s' for reading!\n"), cur_folder);
!       leave(0);
!     }
!   }
!   
!   newmbox(cur_folder, FALSE);
!   return(TRUE);
  }
  
  char helpmsg[VERY_LONG_STRING];
***************
*** 114,119 ****
--- 151,157 ----
  
  	  int redraw = FALSE;
  	  char newfile[SLEN];
+ 	  int result;
  
  	  char	*nameof();
  
***************
*** 120,138 ****
  
  	  /* get new file name */
  
! 	  MoveCursor(LINES-3, 30);
  	  CleartoEOS();
! 	  PutLine0(LINES-3, 38, catgets(elm_msg_cat, ElmSet, ElmUseForHelp,
! 		"(Use '?' for help)"));
! 	  PutLine0(LINES-2,0, catgets(elm_msg_cat, ElmSet, ElmChangeToWhichFolder,
! 		"Change to which folder: "));
  	  while(1) {
  	    newfile[0] = '\0';
! 	    (void) optionally_enter(newfile, LINES-2, 24, FALSE, FALSE);
  	    clear_error();
  
! 	    if(*newfile == '\0') {	/* if user didn't enter a file name */
! 	      MoveCursor(LINES-3, 30);	/* abort changing file process */
  	      CleartoEOS();
  	      return(redraw);
  
--- 158,193 ----
  
  	  /* get new file name */
  
! 	  MoveCursor(elm_LINES-3, 30);
  	  CleartoEOS();
! 	  PutLine0(elm_LINES-3, 38, catgets(elm_msg_cat, ElmSet, ElmUseForHelp,
! 					    "(Use '?' for help)"));
! 	  PutLine0(elm_LINES-2,0, catgets(elm_msg_cat, ElmSet, 
! 					  ElmChangeToWhichFolder,
! 					  "Change to which folder: "));
  	  while(1) {
+ 	    int status;
+ 
  	    newfile[0] = '\0';
! 	    status = optionally_enter(newfile, elm_LINES-2, 24, 
! 				      OE_REDRAW_MARK);
! 	    while (REDRAW_MARK == status) {
! 	      redraw = TRUE;
! 	      PutLine0(elm_LINES-3, 38, 
! 		       catgets(elm_msg_cat, ElmSet, ElmUseForHelp,
! 			       "(Use '?' for help)"));
! 	      PutLine0(elm_LINES-2,0, 
! 		       catgets(elm_msg_cat, ElmSet, 
! 			       ElmChangeToWhichFolder,
! 			       "Change to which folder: "));
! 	      status = optionally_enter(newfile, elm_LINES-2, 24, 
! 					OE_REDRAW_MARK|OE_APPEND_CURRENT);
! 	    }
! 
  	    clear_error();
  
! 	    if(0 != status || *newfile == '\0') {  /* if user didn't enter a file name */
! 	      MoveCursor(elm_LINES-3, 30);         /* abort changing file process */
  	      CleartoEOS();
  	      return(redraw);
  
***************
*** 144,151 ****
  		init_helpmsg( helpmsg, change_word, FALSE );
  	      ClearScreen();
  	      printf( helpmsg ) ;
! 	      PutLine0(LINES-2,0,catgets(elm_msg_cat, ElmSet, ElmChangeToWhichFolder,
! 		"Change to which folder: "));	/* reprompt */
  	      redraw = TRUE;		/* we'll need to clean the screen */
  	      continue ;
  	    }
--- 199,210 ----
  		init_helpmsg( helpmsg, change_word, FALSE );
  	      ClearScreen();
  	      printf( helpmsg ) ;
! 
! 	      /* reprompt */
! 	      PutLine0(elm_LINES-2,0,catgets(elm_msg_cat, ElmSet, 
! 					     ElmChangeToWhichFolder,
! 					     "Change to which folder: "));
! 	      
  	      redraw = TRUE;		/* we'll need to clean the screen */
  	      continue ;
  	    }
***************
*** 153,160 ****
  	    /* if user entered wildcard, list expansions and try again */
  	    if ( has_wildcards( newfile ) ) {
  	      list_folders( 4, NULL, newfile ) ;
! 	      PutLine0(LINES-2,0,catgets(elm_msg_cat, ElmSet, ElmChangeToWhichFolder,
! 		"Change to which folder: "));	/* reprompt */
  	      redraw = TRUE ;
  	      continue ;  
  	    }
--- 212,222 ----
  	    /* if user entered wildcard, list expansions and try again */
  	    if ( has_wildcards( newfile ) ) {
  	      list_folders( 4, NULL, newfile ) ;
! 
! 	      /* reprompt */
! 	      PutLine0(elm_LINES-2,0,catgets(elm_msg_cat, ElmSet, 
! 					     ElmChangeToWhichFolder,
! 					     "Change to which folder: "));
  	      redraw = TRUE ;
  	      continue ;  
  	    }
***************
*** 182,192 ****
  	    break;	/* exit loop - we got the name of a good file */
  	  }
  
  	  /* All's clear with the new file to go ahead and leave the current. */
! 	  MoveCursor(LINES-3, 30);
  	  CleartoEOS();
  
! 	  if(leave_mbox(FALSE, FALSE, TRUE) ==-1) {
  	    /* new mail - leave not done - can't change to another file yet
  	     * check for change in mailfile_size in main() will do the work
  	     * of calling newmbox to add in the new messages to the current
--- 244,256 ----
  	    break;	/* exit loop - we got the name of a good file */
  	  }
  
+ rechange:
  	  /* All's clear with the new file to go ahead and leave the current. */
! 	  MoveCursor(elm_LINES-3, 30);
  	  CleartoEOS();
  
! 	  result = leave_mbox(FALSE, FALSE, TRUE);
! 	  if(result ==-1) {
  	    /* new mail - leave not done - can't change to another file yet
  	     * check for change in mailfile_size in main() will do the work
  	     * of calling newmbox to add in the new messages to the current
***************
*** 193,198 ****
--- 257,286 ----
  	     * file and fix the sorting sequence that leave_mbox may have
  	     * changed for its own purposes */
  	    return(redraw);
+ 	  }
+ 	  
+ 	  if (result < 0) {
+ 	    int ans;
+ 	    error("Failed to leave folder!");
+ 	    sleep_message();
+ 	    
+ 	  again1:
+ 	    ans = want_to("Failed to leave folder: Try to change again ? [P]anic",
+ 			  *def_ans_no,elm_LINES,1);
+ 	    if (ans = ('L'&31)) {
+ 	      redraw = 1;
+ 	      ClearScreen();      
+ 	      goto again1;
+ 	    }
+ 	    if (ans == *def_ans_no)
+ 	      return redraw;
+ 	    if (ans == *def_ans_yes) {
+ 	      clear_error();
+ 	      goto rechange;
+ 	    }
+ 	    if (ans == 'P')
+ 	      emergency_exit();
+ 	    return redraw;
  	  }
  
  	  redraw = 1;
Index: WORK/src/read_rc.c
*** elm2.4.25/src/read_rc.c	Mon Aug 23 05:58:06 1993
--- WORK/src/read_rc.c	Thu Aug  8 19:43:24 1996
***************
*** 261,267 ****
  extern opts_menu *find_cfg_opts();
  extern int errno;
  
! char  *error_description(), *shift_lower();
  
  #define  metachar(c)	(c == '+' || c == '%' || c == '=')
  #ifndef ok_rc_char
--- 261,267 ----
  extern opts_menu *find_cfg_opts();
  extern int errno;
  
! char  *error_description(), *shift_lower(), *mode_to_str();
  
  #define  metachar(c)	(c == '+' || c == '%' || c == '=')
  #ifndef ok_rc_char
***************
*** 367,374 ****
  #ifdef MIME
  	strcpy(charset, default_charset);
  	strcpy(charset_compatlist, COMPAT_CHARSETS);
! 	strcpy(display_charset, default_display_charset);
! 	strcpy(text_encoding, default_encoding);
  #endif
  
  	/* see if the user has a $HOME/.elm directory */
--- 367,377 ----
  #ifdef MIME
  	strcpy(charset, default_charset);
  	strcpy(charset_compatlist, COMPAT_CHARSETS);
! 	if (!getenv("NOMETAMAIL") && getenv("MM_CHARSET"))
! 	  strcpy(raw_display_charset, "$MM_CHARSET");
! 	else
! 	  strcpy(raw_display_charset, default_display_charset);
! 	strcpy(text_encoding, default_encoding);	  
  #endif
  
  	/* see if the user has a $HOME/.elm directory */
***************
*** 384,389 ****
--- 387,393 ----
  	  }
  
  	  Raw(ON | NO_TITE);
+ 	redraw1:
  	  MCprintf(catgets(elm_msg_cat, ElmSet, ElmDirNotice, "\n\rNotice:\
  \n\rThis version of ELM requires the use of a .elm directory in your home\
  \n\rdirectory to store your elmrc and alias files. Shall I create the\
***************
*** 391,397 ****
  		*def_ans_yes, *def_ans_no, *def_ans_no, BACKSPACE);
  
  	  fflush(stdout);
! 	  ch=getchar();
  	  ch = tolower(ch);
  	  if (ch == '\n' || ch == '\r') /* they took the default by pressing cr */
  		ch = *def_ans_no;
--- 395,404 ----
  		*def_ans_yes, *def_ans_no, *def_ans_no, BACKSPACE);
  
  	  fflush(stdout);
! 	  ch=ReadCh(REDRAW_MARK);
! 	  if (REDRAW_MARK == ch)
! 	    goto redraw1;
! 
  	  ch = tolower(ch);
  	  if (ch == '\n' || ch == '\r') /* they took the default by pressing cr */
  		ch = *def_ans_no;
***************
*** 506,512 ****
  		local_signature[0] = remote_signature[0] = '\0';
  	}
  
! 	if (hp_softkeys) hp_terminal=TRUE;	/* must be set also! */
  
  	allow_forms = (allow_forms?MAYBE:NO);
  	if (bounceback > MAX_HOPS) {
--- 513,519 ----
  		local_signature[0] = remote_signature[0] = '\0';
  	}
  
! 	/* if (hp_softkeys) hp_terminal=TRUE; */	/* must be set also! */
  
  	allow_forms = (allow_forms?MAYBE:NO);
  	if (bounceback > MAX_HOPS) {
***************
*** 517,527 ****
  	    bounceback = 0;
  	}
  
! 	if ((timeout != 0) && (timeout < 10)) {
  	    errors++;
  	    printf(catgets(elm_msg_cat, ElmSet, ElmTimeoutLTTen,
  		 "Warning: timeout is set to less than 10 seconds. Ignored.\n\r"));
! 	    timeout = 0;
  	}
  
  	if (readmsginc < 1) {
--- 524,534 ----
  	    bounceback = 0;
  	}
  
! 	if ((elm_timeout != 0) && (elm_timeout < 10)) {
  	    errors++;
  	    printf(catgets(elm_msg_cat, ElmSet, ElmTimeoutLTTen,
  		 "Warning: timeout is set to less than 10 seconds. Ignored.\n\r"));
! 	    elm_timeout = 0;
  	}
  
  	if (readmsginc < 1) {
***************
*** 551,556 ****
--- 558,564 ----
  	  }
  
  	  Raw( ON | NO_TITE );
+ 	redraw2:
  	  MCprintf(catgets(elm_msg_cat, ElmSet, ElmNoticeFoldersDir,"\n\rNotice:\n\r\
  ELM requires the use of a folders directory to store your mail folders in.\n\r\
  Shall I create the directory %s for you (%c/%c/q)? %c%c"),
***************
*** 557,563 ****
  		folders, *def_ans_yes, *def_ans_no, *def_ans_yes, BACKSPACE);
  
  	  fflush(stdout);
! 	  ch=getchar();
  	  ch = tolower(ch);
  	  if (ch == '\n' || ch == '\r') /* they took the default by pressing cr */
  		ch = *def_ans_yes;
--- 565,574 ----
  		folders, *def_ans_yes, *def_ans_no, *def_ans_yes, BACKSPACE);
  
  	  fflush(stdout);
! 	  ch=ReadCh(REDRAW_MARK);
! 	  if (REDRAW_MARK == ch)
! 	    goto redraw2;
! 
  	  ch = tolower(ch);
  	  if (ch == '\n' || ch == '\r') /* they took the default by pressing cr */
  		ch = *def_ans_yes;
***************
*** 611,616 ****
--- 622,646 ----
  	  sprintf(sent_mail, "%s/%s", folders, buffer);
  	}
  
+ #ifdef MIME
+ 	do_expand_env("display_charset", display_charset, raw_display_charset, 
+ 		      sizeof(display_charset));
+ 
+ 	if (strcmp(raw_metamail_path,"none") == 0 || 
+ 	    raw_metamail_path[0] == '\0') {
+ 	  strcpy(raw_metamail_path,"none");
+ 	  strcpy(metamail_path,"none");
+ 	} else if(strcmp(raw_metamail_path,"metamail") == 0) {
+ 	  if (getenv("NOMETAMAIL"))
+ 	    strcpy(metamail_path,"none");
+ 	  else
+ 	    strcpy(metamail_path,"metamail");
+ 	} else {
+ 	  do_expand_env("metamail", metamail_path, raw_metamail_path, 
+ 			sizeof(metamail_path));
+ 	}
+ #endif
+ 
  	if (debug > 10) 	/** only do this if we REALLY want debug! **/
  	  dump_rc_results();
  
***************
*** 725,730 ****
--- 755,793 ----
  		*SAVE_INFO_NUM(x) = atoi(word2);
  		break;
  
+ 	    case DT_PRM:
+ 	        {
+ 		    char *s = word2;
+ 		    int m = 0;
+ 		    char *modecharp = "rwxrwxrwx";
+ 		    int modebit = 0400;
+ 		    char c;
+ 
+ 		    while ((c = *s++) != '\0') {
+ 		    	if (c == *modecharp)
+ 			    m |= modebit;
+ 			else if (c != '-') {
+ 			    errors++;
+ 			    printf(catgets(elm_msg_cat, ElmSet, ElmBadModeInElmrc,
+ 	  "I can't understand file permissions \"%s\" in line %d in your \".elm/elmrc\" file\n\r"),
+ 			      word2, lineno);
+ 			    goto out;
+ 			}
+ 			modecharp++;
+ 			modebit >>= 1;
+ 		    }
+ 		    if (*modecharp != '\0') {
+ 			errors++;
+ 			printf(catgets(elm_msg_cat, ElmSet, ElmBadModeInElmrc,
+ 	  "I can't understand file permissions \"%s\" in line %d in your \".elm/elmrc\" file\n\r"),
+ 			  word2, lineno);
+ 			break;
+ 		    }
+ 		    *SAVE_INFO_NUM(x) = m;
+ 		}
+ 	out:
+ 	        break;
+ 
  	    case DT_BOL:
  		if (save_info[x].flags & FL_OR)
  		    *SAVE_INFO_BOL(x) |= is_it_on(word2);
***************
*** 924,929 ****
--- 987,993 ----
  		       "Content-Length", "MIME-Version",
  		       "Content-Transfer-Encoding",
  		       "From", "X-Mailer:", "Status:",
+ 		       "X-ELM-",
  		       "*end-of-defaults*", NULL
  		     };
  
***************
*** 1142,1147 ****
--- 1206,1215 ----
  			s = buf;
  			break;
  
+ 		    case DT_PRM:
+ 			s = mode_to_str(*SAVE_INFO_NUM(i));
+ 			break;
+ 
  		    case DT_BOL:
  			s = on_off(*SAVE_INFO_BOL(i));
  			break;
***************
*** 1183,1186 ****
--- 1251,1275 ----
  		 (strncmp(mybuffer, "yes",  3) == 0) ||
  		 (strncmp(mybuffer, "true", 4) == 0)
  	      );
+ }
+ 
+ char *
+ mode_to_str(mode)
+ int mode;
+ {
+ 	static char modestr[9+1];	/* "rwxrwxrwx\0" */
+ 	char *s = &modestr[0];
+ 	char *modecharp = "rwxrwxrwx";
+ 	int modebit = 0400;
+ 
+ 	while (modebit != 0) {
+ 	    if (mode & modebit)
+ 	        *s++ = *modecharp;
+ 	    else
+ 		*s++ = '-';
+ 	    modecharp++;
+ 	    modebit >>= 1;
+ 	}
+ 	*s = '\0';
+ 	return(modestr);
  }
Index: WORK/src/remail.c
*** elm2.4.25/src/remail.c	Mon Dec  4 17:50:56 1995
--- WORK/src/remail.c	Thu Jun 13 23:37:55 1996
***************
*** 98,103 ****
--- 98,104 ----
  #include "headers.h"
  #include "s_elm.h"
  #include <errno.h>
+ #include "me.h"
  
  extern int errno;
  
***************
*** 110,116 ****
  	/** remail a message... returns TRUE if new foot needed ... **/
  	
  	FILE *mailfd;
-         int mailfd_handle;
  	char entered[VERY_LONG_STRING], expanded[VERY_LONG_STRING];
  	char *filename, buffer[VERY_LONG_STRING], ch;
  	char mailerflags[NLEN];
--- 111,116 ----
***************
*** 133,140 ****
  	  return(1);
  	}
  
!         if ( ( (mailfd_handle = open(filename, O_RDWR|O_CREAT|O_EXCL,0600)) == -1) ||
!              ( (mailfd = fdopen(mailfd_handle, "w")) == NULL) ) {
  	  err = errno;
  	  dprint(1, (debugfile, "couldn't open temp file %s! (remail)\n", 
  		  filename));
--- 133,139 ----
  	  return(1);
  	}
  
!         if ((mailfd = safeopen_rdwr(filename)) == NULL) {
  	  err = errno;
  	  dprint(1, (debugfile, "couldn't open temp file %s! (remail)\n", 
  		  filename));
***************
*** 157,163 ****
  	  do_mmdf_addresses(mailfd, strip_parens(strip_commas(expanded)));
  #endif /* MMDF */
  
! 	copy_message("", mailfd, CM_REMOTE | CM_MMDF_HEAD | CM_REMAIL);
  
  	fclose(mailfd);
  
--- 156,163 ----
  	  do_mmdf_addresses(mailfd, strip_parens(strip_commas(expanded)));
  #endif /* MMDF */
  
! 	copy_message(mailfile,headers[current-1],
! 		     "", mailfd, CM_REMOTE | CM_MMDF_HEAD | CM_REMAIL);
  
  	fclose(mailfd);
  
***************
*** 164,176 ****
  	/** Got the messsage, now let's ensure the person really wants to 
  	    remail it... **/
  
! 	ClearLine(LINES-1);
! 	ClearLine(LINES);
  	MCsprintf(buffer, catgets(elm_msg_cat, ElmSet, ElmSureYouWantToRemail,
  	    "Are you sure you want to remail this message (%c/%c)? "),
  	    *def_ans_yes, *def_ans_no);
  	fflush(stdin);
! 	ch = want_to(buffer, *def_ans_yes, LINES-1, 0);
  	if (ch == *def_ans_no) { /* another day, another No... */
  	  set_error(catgets(elm_msg_cat, ElmSet, ElmBounceCancelled,
  		"Bounce of message canceled."));
--- 164,176 ----
  	/** Got the messsage, now let's ensure the person really wants to 
  	    remail it... **/
  
! 	ClearLine(elm_LINES-1);
! 	ClearLine(elm_LINES);
  	MCsprintf(buffer, catgets(elm_msg_cat, ElmSet, ElmSureYouWantToRemail,
  	    "Are you sure you want to remail this message (%c/%c)? "),
  	    *def_ans_yes, *def_ans_no);
  	fflush(stdin);
! 	ch = want_to(buffer, *def_ans_yes, elm_LINES-1, 0);
  	if (ch == *def_ans_no) { /* another day, another No... */
  	  set_error(catgets(elm_msg_cat, ElmSet, ElmBounceCancelled,
  		"Bounce of message canceled."));
***************
*** 181,190 ****
  
  	if (strcmp(sendmail, mailer) == 0
  #ifdef SITE_HIDING
! 	    && ! is_a_hidden_user(username))
! #else
! 					 )
  #endif
  	  strcpy(mailerflags, (sendmail_verbose ? smflagsv : smflags));
  	else if (strcmp(submitmail, mailer) == 0) {
  	  strcpy(mailerflags, submitflags_s);
--- 181,189 ----
  
  	if (strcmp(sendmail, mailer) == 0
  #ifdef SITE_HIDING
! 	    && ! is_a_hidden_user(username)
  #endif
+ 	  )
  	  strcpy(mailerflags, (sendmail_verbose ? smflagsv : smflags));
  	else if (strcmp(submitmail, mailer) == 0) {
  	  strcpy(mailerflags, submitflags_s);
***************
*** 192,204 ****
  	} else if (strcmp(execmail, mailer) == 0) {
  	  strcpy(mailerflags, (sendmail_verbose ? emflagsv : emflags));
  	} else
! 	  mailerflags[0] = '\0';
  	
  	sprintf(buffer,"( %s %s %s < %s ; %s %s) &", 
  	      mailer, mailerflags, strip_parens(strip_commas(expanded)), 
  	      filename, remove_cmd, filename);
  
! 	PutLine0(LINES, 0, catgets(elm_msg_cat, ElmSet, ElmResendingMail,
  		"Resending mail..."));
  	(void) system_call(buffer, 0);
  	set_error(catgets(elm_msg_cat, ElmSet, ElmMailResent, "Mail resent."));
--- 191,230 ----
  	} else if (strcmp(execmail, mailer) == 0) {
  	  strcpy(mailerflags, (sendmail_verbose ? emflagsv : emflags));
  	} else
!           mailerflags[0] = '\0';
  	
+ #ifdef MIME
+ 	{
+ 	  struct header_rec *current_header = headers[current-1];
+ 	  if (current_header -> status & MIME_MESSAGE) {
+ 	    int encoding = current_header->mime_rec.encoding;
+ 
+ 	    if (encoding == ENCODING_BINARY && 
+ 		!(headers[current-1]->binary)) {
+ 	      dprint(2,(debugfile,
+ 			"Remail: resets encoding=BINARY to encoding=8BIT\n"));
+ 	      encoding = ENCODING_8BIT;
+ 	    }
+ 
+ #ifdef USE_8BITMIME
+ 	  if (encoding == ENCODING_8BIT)
+ 	    strcat(mailerflags," -B8BITMIME");
+ #endif
+ #ifdef USE_BINARYMIME
+           if (encoding == ENCODING_BINARY)
+             /* With -BBINARYMIME lines must terminate with \r\n
+              * Unix's \n is _NOT_ sufficient - K E H              */
+             strcat(mailerflags," -BBINARYMIME");
+ #endif
+ 	  }
+ 	}
+ #endif
+ 
  	sprintf(buffer,"( %s %s %s < %s ; %s %s) &", 
  	      mailer, mailerflags, strip_parens(strip_commas(expanded)), 
  	      filename, remove_cmd, filename);
  
! 	PutLine0(elm_LINES, 0, catgets(elm_msg_cat, ElmSet, ElmResendingMail,
  		"Resending mail..."));
  	(void) system_call(buffer, 0);
  	set_error(catgets(elm_msg_cat, ElmSet, ElmMailResent, "Mail resent."));
Index: WORK/src/remailer.c
*** /tmp/null.14101	Tue Aug 20 22:05:34 1996
--- WORK/src/remailer.c	Mon Jul 22 21:20:42 1996
***************
*** 0 ****
--- 1,619 ----
+ #include <unistd.h>
+ #include <sys/wait.h>
+ #include "headers.h"
+ #include "me.h"
+ 
+ #ifdef USE_REMAILER
+ extern int errno;
+ extern int remailing;
+ 
+ #define REMAILER_SITE "remailer-list@kiwi.cs.berkeley.edu"
+ 
+ #define BOL 1
+ #define STR 2
+ #define INT 3
+ 
+ typedef struct remailer {
+ 	char name[STRING];
+ 	char path[STRING];
+ 	unsigned int pgp : 1;
+ 	unsigned int eric : 1;
+ 	unsigned int cpunk : 1;
+ 	unsigned int penet : 1;
+ 	unsigned int latent : 1;
+ 	unsigned int hash : 1;
+ 	unsigned int special : 1;
+ 	long time;
+ 	struct remailer *next;
+ } remailer_t;
+ 
+ typedef struct remail {
+   int encrypt; /* Use encryption through the servers? */
+   char path[STRING]; /* User-defined route.  Overrides "chain". */
+   int chain; /* How many sites to chain this message through? */
+   remailer_t *info;
+   char address[STRING];
+ } remail_t;
+ 
+ static remail_t remailer;
+ 
+ #include "menu2.h"
+ static struct menu_item remail_items[] = {
+   { "R)email:", 'r', 3, BOL, (char *) &remailing },
+   { "C)hain:", 'c', 5, INT, (char *) &remailer.chain },
+   { "remail P)ath:", 'p', 6, STR, (char *) &remailer.path },
+   { "E)ncrypt:", 'e', 8, BOL, (char *) &remailer.encrypt }
+ };
+ #define MAX_ITEMS 4
+ 
+ void
+ remailer_menu ()
+ {
+   /* Reset to the defaults... */
+   remailer.encrypt = FALSE;
+   remailer.path[0] = '\0';
+   remailer.chain = 3;
+   remailer.info = NULL;
+ 
+   generic_menu (&remail_items, MAX_ITEMS, "Remailer Configuration", "remailer: ");
+ }
+ 
+ static void
+ remailer_print_db (db)
+      remailer_t *db;
+ {
+   dprint(3, (debugfile, "remailer_print_db:\n"));
+   while (db) {
+     dprint(3, (debugfile, "\t%s = %d\n", db->name, db->time));
+     db = db->next;
+   }
+ }
+ 
+ static int
+ remailer_parse_opts (buf, r)
+      char *buf;
+      remailer_t *r;
+ 			       
+ {
+   short i = 0;
+   char *ptr, *ptr2;
+ 
+   ptr = strchr (buf, '"');
+   if (!ptr)
+     return 0;
+ 
+   ptr++;
+   while (*ptr && (*ptr != '"'))
+     r->name[i++] = *ptr++;
+   r->name[i] = '\0';
+ 
+   ptr = strchr (ptr, '<');
+   if (!ptr)
+     return 0;
+ 
+   ptr++;
+   i = 0;
+   while (*ptr && (*ptr != '>'))
+     r->path[i++] = *ptr++;
+   r->path[i] = '\0';
+ 
+   ptr2 = strrchr (ptr, '"');
+   if (!ptr2)
+     return 0;
+ 
+   *ptr2 = '\0';
+   while ((ptr2 = strtok (ptr, " \t\r\n")) != NULL) {
+     if (strcmp (ptr2, "pgp") == 0)
+       r->pgp = 1;
+     else if (strcmp (ptr2, "hash") == 0)
+       r->hash = 1;
+     else if (strcmp (ptr2, "eric") == 0)
+       r->eric = 1;
+     else if (strcmp (ptr2, "penet") == 0)
+       r->penet = 1;
+     else if (strcmp (ptr2, "cpunk") == 0)
+       r->cpunk = 1;
+     else if (strcmp (ptr2, "latent") == 0)
+       r->latent = 1;
+     else if (strcmp (ptr2, "special") == 0)
+       r->special = 1;
+     ptr = 0;
+   }
+   return 1;
+ }
+ 
+ static remailer_t *
+ remailer_lookup (char *name, remailer_t *db)
+ {
+   while (db) {
+     if (strcmp (name, db->name) == 0)
+       return (db);
+     db = db->next;
+   }
+   dprint (3, (debugfile, "remailer_lookup(): %s not found.\n", name));
+   return (0);
+ }
+ 
+ static remailer_t *
+ remailer_sort (remailer_t *p)
+ {
+   /* sorts the remailers in increasing response time. */
+ 
+   remailer_t *tmp;
+   remailer_t *ptr;
+   remailer_t *head;
+   remailer_t *gopher;
+ 
+   if (p == NULL)
+     return (NULL);
+ 
+   /* Pop the first element. */
+   head = gopher = p;
+   ptr = head->next;
+   head->next = 0;
+   
+   /* No go through the rest of the list */
+   while (ptr) {
+     tmp = ptr;
+     ptr = ptr->next;
+     tmp->next = 0;
+     
+     gopher = head;
+     while (gopher) {
+       if (tmp->time <= gopher->time) {
+ 	/* This case should only occur when gopher==head, so we don't have
+ 	 * to worry about this not being the beginning of the list.
+ 	 */
+ 	tmp->next = gopher;
+ 	head = tmp;
+ 	break;
+       }
+       else if (gopher->next && (tmp->time < gopher->next->time)) {
+ 	tmp->next = gopher->next;
+ 	gopher->next = tmp;
+ 	break;
+       }
+       gopher = gopher->next;
+     }
+   }
+   remailer_print_db(head);
+   return (head);
+ }
+ 
+ void
+ remailer_destroy_db ()
+ {
+   remailer_t *p, *db = remailer.info;
+ 
+   while (db) {
+     p = db;
+     db = db->next;
+     free (p);
+   }
+ }
+ 
+ static remailer_t *
+ remailer_get_db ()
+ {
+   /* This routine retrives the list of remailers and their properties.
+    * It first tries to read ~/.elm/remailers, and failing that, it
+    * fingers whatever is defined in REMAILER_SITE for that info.
+    */
+   FILE *fpin;
+   char buf[STRING], *c, buf2[STRING];
+   short i = 0;
+   int hour, min, sec;
+   remailer_t *mailers = 0;
+   remailer_t *end = 0;
+   remailer_t *tmp;
+ 
+   sprintf (buf, "%s/.elm/remailers", home);
+   fpin = fopen (buf, "r");
+   if (fpin == NULL) {
+     int fd[2];
+ 
+     if (pipe (fd) == -1) {
+       dprint (1, (debugfile, "remailer_get_db(): ERROR: pipe (errno %d)\n", errno));
+       return (NULL);
+     }
+   
+     if (fork () == 0) {
+       int tmp;
+ 
+       setgid(groupid);
+       setuid(userid);
+ 
+       close (fd[0]);
+       close (1);
+       dup (fd[1]);
+       close (fd[1]);
+       execl(FINGER_PATH,FINGER_PATH,REMAILER_SITE,(char *)0);
+       tmp = errno;
+       perror(FINGER_PATH);
+       _exit(tmp);
+     }
+   
+     close (fd[1]);
+     fpin = fdopen (fd[0], "r");
+     if (fpin == NULL) {
+       dprint (1, (debugfile, "remailer_get_db(): ERROR: fdopen (errno %d)\n", errno));
+       return (NULL);
+     }
+     error1 ("Fingering %s...", REMAILER_SITE);
+   }
+   else
+     error1 ("Reading %s...", buf);
+ 
+   while (fgets (buf, STRING, fpin) != NULL) {
+     if (strncmp (buf, "$remailer{", 10) == 0) {
+       tmp = (remailer_t *) safe_malloc (sizeof (remailer_t));
+   
+       tmp->name[0] = '\0';
+       tmp->path[0] = '\0';
+       tmp->pgp     = 0;
+       tmp->eric    = 0;
+       tmp->cpunk   = 0;
+       tmp->penet   = 0;
+       tmp->latent  = 0;
+       tmp->hash    = 0;
+       tmp->special = 0;
+       tmp->time    = 0;
+       tmp->next    = 0;
+ 
+       if (remailer_parse_opts (buf, tmp)) {
+ 	if (mailers == 0)
+ 	  mailers = end = tmp;
+ 	else {
+ 	  end->next = tmp;
+ 	  end = end->next;
+ 	}
+ 	tmp->next = 0;
+       } else {
+ 	free((void *)tmp);
+       }
+     }
+     else if (strncmp (buf, "-----", 5) == 0)
+       break;
+   }
+ 
+   /* Phase 2 : retrieve the rankings (latency). */
+   while (fgets (buf, STRING, fpin) != NULL) {
+     c = buf;
+     i = 0;
+     while (*c && !isspace (*c))
+       buf2[i++] = *c++;
+     buf2[i] = '\0';
+     tmp = remailer_lookup (buf2, mailers);
+     if (tmp != NULL) {
+       c = strchr (buf, ':');
+       while (!isspace(*c))
+ 	c--;
+       c++;
+       i = sscanf (c, "%d:%d:%d", &hour, &min, &sec);
+       if (i == 3)
+ 	tmp->time = (hour * 3600) + min * 60 + sec;
+       else if (i == 2)
+ 	tmp->time = hour * 60 + min;
+       else {
+ 	dprint (1, (debugfile, "remailer_get_db(): error parsing time: %s\n", c));
+ 	error1 ("Could not convert time for remailer %s!", tmp->name);
+ 	if (sleepmsg > 0)
+ 	  sleep(sleepmsg);
+       }
+     }
+   }
+   fclose(fpin);
+   remailer_print_db (mailers);
+   return (remailer_sort (mailers));
+ }
+ 
+ static int
+ #ifdef MIME
+ remailer_write_msg (pdb, to, subj, src, tmpfn, pgp, mime_info)
+      mime_send_t *mime_info;
+ #else
+ remailer_write_msg (pdb, to, subj, src, tmpfn, pgp)
+ #endif
+      remailer_t *pdb;
+      char *to, *subj, *src, *tmpfn;
+ {
+   FILE *fpin, *fpout;
+   char buf[VERY_LONG_STRING];
+ 
+   if (pdb == NULL) {
+     dprint (1, (debugfile, "remailer_write_msg(): ERROR!  pdb==NULL\n"));
+     error ("Could not retrieve list of remailers!");
+     if (sleepmsg > 0)
+       sleep(sleepmsg);
+     return(-1);
+   }
+ 
+   fpin = fopen (src, "r");
+   if (!fpin) {
+     dprint(1,(debugfile,"remailer_write_msg: %s: could not open for reading!\n",src));
+     error("Error opening temp file!");
+     if (sleepmsg > 0)
+       sleep(sleepmsg);
+     return(-1);
+   }
+     
+   fpout = safeopen (tmpfn);
+   if (!fpout) {
+     dprint(1,(debugfile,"remailer_write_msg: %s: could not open for writing!\n",tmpfn));
+     error("Error opening temp file!");
+     if (sleepmsg > 0)
+       sleep(sleepmsg);
+     return(-1);
+   }
+ 
+   fputs ("::\n", fpout);
+   if (pdb->cpunk)
+     fputs ("Request-Remailing-To: ", fpout);
+   else if (pdb->eric)
+     fputs ("Anon-Send-To: ", fpout);
+   else if (pdb->penet)
+     fputs ("X-Anon-To: ", fpout);
+   fprintf (fpout, "%s\n\n", to);
+   /* Some remailers require the subject line to be in the "hash" area, so
+    * use it if it's availible.
+    */
+   if (pdb->hash) {
+     fprintf (fpout, "##\nSubject: %s\n", subj);
+ #ifdef MIME
+     if (mime_info) {
+       /* If this is a MIME message, write out a header in the "hash" area
+        * so that the information will be preserved when the remailer
+        * rewrites the message.
+        */
+       mime_write_header(fpout, mime_info, 1);
+       print_EOLN(fpout, mime_info->encoding_top);
+     }
+     else
+ #endif
+       fputc('\n', fpout);
+   }  
+   while (fgets (buf, VERY_LONG_STRING, fpin) != NULL)
+     fputs (buf, fpout);
+   fclose (fpin);
+   fclose (fpout);
+ #ifdef USE_PGP
+   if (pgp && pdb->pgp) {
+     pgp_encrypt (tmpfn, pdb->path, username, PGP_MESSAGE, FALSE);
+     fpin = fopen (tmpfn, "r");
+     fpout = fopen (src, "w");
+     fputs ("::\nEncrypted: PGP\n\n", fpout);
+     while (fgets (buf, VERY_LONG_STRING, fpin) != NULL)
+       fputs (buf, fpout);
+     fclose (fpin);
+     fclose (fpout);
+     unlink (tmpfn);
+   }
+   else
+ #endif
+   {
+ #ifdef RENAME
+     if (rename (tmpfn, src) < 0) {
+       error ("Could not rename temp file!");
+       dprint (1, (debugfile, "remailer_write_msg: ERROR!  rename(%s,%s); errno=%d\n", src, tmpfn, errno));
+       return(-1);
+     }
+ #else
+     link (tmpfn, src);
+     unlink (tmpfn);
+ #endif
+   }
+   dprint (2, (debugfile, "remailer_write_msg: routing through %s.\n", 
+ 	      pdb->path));
+   return 0;
+ }
+ 
+ int remailer_proc ()
+ {
+   remailer_t *pdb;
+   int chain = remailer.chain;
+   char *c;
+ 
+   /* See if there is anything to do... */
+   if (chain > 0 || (remailer.path[0] != '\0')) {
+     extern char expanded_to[];
+       
+     /* Save this information for later use... */
+     pdb = remailer.info = remailer_get_db ();
+ 
+     if (remailer.path[0] != '\0') {
+       /* The user has specified a path to use. */
+       c = remailer.path;
+       while ((c = strtok (c, ";")) != NULL) {
+ 	while (*c && isspace (*c))
+ 	  c++;
+ 	pdb = remailer_lookup (c, remailer.info);
+ 	if (! pdb)
+ 	  return(-1);
+ 	c = NULL;
+       }
+     }
+     else {
+       remailer_t *savedb = 0;
+ 
+       while (chain > 0) {
+ 	if (remailer.encrypt) {
+ 	  /* Find the next remailer which supports pgp. */
+ 	  while (pdb && ((! pdb->pgp) || (pdb->time == 0)))
+ 	    pdb = pdb->next;
+ 	  if (! pdb)
+ 	    return (-1);
+ 	}
+ 	else {
+ 	  /* Some servers will only accept PGP encoded messages, so if PGP was
+ 	   * not requested, skip all servers marked "special".  Also, we want
+ 	   * to skip any servers with a time of zero, since that means there 
+ 	   * wasn't any information availible.
+ 	   */
+ 	  while (pdb && (pdb->special || (pdb->time == 0)))
+ 	    pdb = pdb->next;
+ 	  if (! pdb)
+ 	    return (-1);
+ 	}
+ 	savedb = pdb;
+ 	pdb = pdb->next;
+ 	chain--;
+       }
+       pdb = savedb;
+     }
+ 
+     /* "pdb" should now be set to the last entry.  We should set Elm's
+      * concept of the "To:" address to this remailer.
+      */
+     strcpy (remailer.address, expanded_to);
+     strcpy (expanded_to, pdb->path);
+   }
+   return(0);
+ }
+ 
+ static int
+ #ifdef MIME
+ remailer_genmsg (filename, to, subj, chain, pgp, mime_info)
+      mime_send_t *mime_info;
+ #else
+ remailer_genmsg (filename, to, subj, chain, pgp)
+ #endif
+      char *to, *subj, *filename;
+      int chain, pgp;
+ {
+   char tmpfn[STRING], *c;
+   char remailto[STRING];
+   remailer_t *db, *pdb;
+ 
+   /* Set the initial address */
+   strcpy(remailto, to);
+ 
+   if (chain < 1 && (remailer.path[0] == '\0'))
+     return (-1); /* nothing to do */
+ 
+   pdb = db = remailer.info;
+   if (db == NULL) {
+     dprint(1, (debugfile, "remailer_genmsg: no database found!\n"));
+     error("Could not find remailer database!");
+     if (sleepmsg>0)
+       sleep(sleepmsg);
+     return(-1);
+   }
+ 
+   sprintf (tmpfn, "%selmRT%d", temp_dir, getpid());
+ 
+   if (remailer.path[0] != '\0') {
+     /* The user has specified a path to use. */
+     c = remailer.path;
+     while ((c = strtok (c, ";")) != NULL) {
+       while (*c && isspace (*c))
+ 	c++;
+       pdb = remailer_lookup (c, db);
+       if (! pdb) {
+ 	dprint(1,(debugfile, "remailer_genmsg: could not find remailer '%s'\n",
+ 		  c));
+ 	error1("Could not find remailer '%s'.", c);
+ 	if (sleepmsg > 0)
+ 	  sleep(sleepmsg);
+         return (-1);
+       }
+ #ifdef MIME
+       remailer_write_msg (pdb, remailto, subj, filename, tmpfn, pgp, mime_info);
+ #else
+       remailer_write_msg (pdb, remailto, subj, filename, tmpfn, pgp);
+ #endif
+       strcpy(remailto, pdb->path);
+       c = NULL;
+     }
+   }
+   else
+     while (chain > 0) {
+       if (pgp) {
+ 	/* Find the next remailer which supports pgp. */
+ 	while (pdb && ((! pdb->pgp) || (pdb->time == 0)))
+ 	  pdb = pdb->next;
+ 	if (! pdb)
+ 	  return (-1);
+       }
+       else {
+ 	/* Some servers will only accept PGP encoded messages, so if PGP was
+ 	 * not requested, skip all servers marked "special".  Also, we want
+ 	 * to skip any servers with a time of zero, since that means there 
+ 	 * wasn't any information availible.
+ 	 */
+ 	while (pdb && (pdb->special || (pdb->time == 0)))
+ 	  pdb = pdb->next;
+         if (! pdb)
+           return (-1);
+       }
+ #ifdef MIME
+       remailer_write_msg (pdb, remailto, subj, filename, tmpfn, pgp, mime_info);
+ #else
+       remailer_write_msg (pdb, remailto, subj, filename, tmpfn, pgp);
+ #endif
+       strcpy(remailto, pdb->path);
+       pdb = pdb->next;
+       chain--;
+     }
+   return (0);
+ }
+ 
+ #ifdef MIME
+ remailer_copy_message_across (reply, real_reply, copy, mime_info)
+      mime_send_t *mime_info;
+ #else
+ remailer_copy_message_across (reply, real_reply, copy)
+ #endif
+      FILE *reply, *real_reply;
+      int copy;
+ {
+   FILE *tmpfp;
+   char tempfile[STRING], buf[VERY_LONG_STRING];
+   extern char subject[];
+   int ret;
+ 
+   sprintf(tempfile, "%selmR%d", temp_dir, getpid());
+ 
+   tmpfp = safeopen(tempfile);
+   if (!tmpfp) {
+     dprint(1, (debugfile, "remailer_copy_message_across: %s: could not open for writing!\n", tempfile));
+     error("Could not open temp file for writing!");
+     if (sleepmsg > 0)
+       sleep(sleepmsg);
+     return(-1);
+   }
+ 
+ #ifdef MIME
+   copy_message_across(reply, tmpfp, copy, mime_info);
+ #else
+   copy_message_across(reply, tmpfp, copy);
+ #endif
+   fclose(tmpfp);
+ #ifdef MIME
+   ret = remailer_genmsg (tempfile, remailer.address, subject, remailer.chain,
+ 			 remailer.encrypt, mime_info);
+ #else
+   ret = remailer_genmsg (tempfile, remailer.address, subject, remailer.chain,
+ 			 remailer.encrypt);
+ #endif
+   if (ret == -1) {
+     error("Error while formatting for remailer!");
+     if (sleepmsg > 0)
+       sleep(sleepmsg);
+     unlink(tempfile);
+     return(-1);
+   }
+   tmpfp = fopen(tempfile, "r");
+   if (!tmpfp) {
+     dprint(1, (debugfile, "remailer_copy_message_across: %s: could not open for reading!\n", tempfile));
+     error("Could not read temp file!");
+     if (sleepmsg>0)
+       sleep(sleepmsg);
+     unlink(tempfile);
+     return(-1);
+   }
+   while (mail_gets(buf, sizeof(buf), tmpfp) > 0)
+     fputs(buf, real_reply);
+   unlink(tempfile);
+   return 0;
+ }
+ #endif
Index: WORK/src/reply.c
*** elm2.4.25/src/reply.c	Tue Aug  3 22:29:18 1993
--- WORK/src/reply.c	Fri Aug  9 22:57:00 1996
***************
*** 114,119 ****
--- 114,120 ----
  ***/
  
  #include "headers.h"
+ #include "me.h"
  #include "s_elm.h"
  #include <errno.h>
  
***************
*** 151,158 ****
  }
  
  int
! optimize_and_add(new_address, full_address)
! char *new_address, *full_address;
  {
  	/** This routine will add the new address to the list of addresses
  	    in the full address buffer IFF it doesn't already occur.  It
--- 152,160 ----
  }
  
  int
! optimize_and_add(new_address, full_address, size)
!      char *new_address, *full_address;
!      int size;
  {
  	/** This routine will add the new address to the list of addresses
  	    in the full address buffer IFF it doesn't already occur.  It
***************
*** 177,183 ****
  	      ;
  
  	  if (i == host_count) {
! 	    strcpy(hosts[host_count++], host);
  	    if (host_count == MAX_HOPS) {
  	       dprint(2, (debugfile,
                "Error: hit max_hops limit trying to build return address (%s)\n",
--- 179,185 ----
  	      ;
  
  	  if (i == host_count) {
! 	    strfcpy(hosts[host_count++], host, SLEN);
  	    if (host_count == MAX_HOPS) {
  	       dprint(2, (debugfile,
                "Error: hit max_hops limit trying to build return address (%s)\n",
***************
*** 201,215 ****
  
  	new_address[0] = '\0';
  
! 	for (i = 0; i < host_count; i++)
  	  sprintf(new_address, "%s%s%s", new_address, 
  	          new_address[0] == '\0'? "" : "!",
  	          hosts[i]);
  
  	if (full_address[0] == '\0')
! 	  strcpy(full_address, new_address);
  	else {
  	  len = strlen(full_address);
  	  full_address[len  ] = ',';
  	  full_address[len+1] = ' ';
  	  full_address[len+2] = '\0';
--- 203,219 ----
  
  	new_address[0] = '\0';
  
! 	for (i = 0; i < host_count; i++)  
  	  sprintf(new_address, "%s%s%s", new_address, 
  	          new_address[0] == '\0'? "" : "!",
  	          hosts[i]);
  
  	if (full_address[0] == '\0')
! 	  strfcpy(full_address, new_address, size);
  	else {
  	  len = strlen(full_address);
+ 	  if (len + strlen(new_address) > size-5)
+ 	    return 1;   /* Buffer overflow */
  	  full_address[len  ] = ',';
  	  full_address[len+1] = ' ';
  	  full_address[len+2] = '\0';
***************
*** 219,227 ****
  	return(0);
  }
  
  void
! get_and_expand_everyone(return_address, full_address)
  char *return_address, *full_address;
  {
  	/** Read the current message, extracting addresses from the 'To:'
  	    and 'Cc:' lines.   As each address is taken, ensure that it
--- 223,296 ----
  	return(0);
  }
  
+ /* Kari E. Hurtta <Kari.Hurtta@Fmi.FI> */
  void
! handle_reply_to(return_address, to_address, size)
! char *return_address, *to_address;
! int size;
! {
!     char buf[VERY_LONG_STRING], 
!          address[SLEN], comment[SLEN];
!     int  iindex, line_len, err;
!     int count=0;
! 
!     /** First off, get to the first line of the message desired **/
! 
!     if (skip_envelope(headers[current-1], mailfile) == -1) {
!         err = errno;
!         dprint(1,(debugfile,"Error: seek %ld resulted in errno %s (%s)\n",
!                  headers[current-1]->offset, error_description(err),
!                  "handle_reply_to"));
!         error2(catgets(elm_msg_cat, ElmSet, ElmSeekFailedFile,
!                 "ELM [seek] couldn't read %d bytes into file (%s)."),
!                 headers[current-1]->offset, error_description(err));
!         return;
!     }
! 
! 
!     /** now let's parse the actual message! **/
! 
!     /* read_header_line reads also continuation lines ... 
!      * 2 == check that this is header line...
!      */
!     while (0 < (line_len = read_header_line(mailfile,buf,sizeof(buf),
! 					    RHL_CHECK_HEADER))) {
!       /* we only want lines with reply-to addresses */
!       if (!header_cmp(buf, "Reply-To", NULL)) 
!         continue;
! 
!       /* extract the addresses from header */
! 
!       iindex = chloc(buf, ':')+1;               /* point beyond header name */
!       dprint(2,(debugfile,"> %s\n",buf));
! 
!       /* go through all addresses in this line */
!       while (break_down_tolist(buf, &iindex, address, comment)) {
! 	/* can't use okay_address here ! */
! 
! 	/* do NOT add sendder's domain in here ! It was MTA's task
!            and if it is not added then there is good reason.
! 	   (adding of senders domain to unqualified addresses
! 	    BREAKS my local mailing lists!!!)
! 	   That is: It is possible that Reply-to is written by some
! 		    other site than From !!!
! 	   - Kari E. Hurtta <Kari.Hurtta@Fmi.Fi>
!          */
!           if (!optimize_and_add(address, to_address, size))
! 		count++;
!       }
!     }
! 
!     /* if there wasn't reply-to header */
!     if (!count)
! 	optimize_and_add(return_address, to_address, size);
! }
!  
! 
! void
! get_and_expand_everyone(return_address, full_address, size)
  char *return_address, *full_address;
+ int size;
  {
  	/** Read the current message, extracting addresses from the 'To:'
  	    and 'Cc:' lines.   As each address is taken, ensure that it
***************
*** 231,242 ****
  	**/
  
      char ret_address[SLEN], buf[VERY_LONG_STRING], new_address[SLEN],
! 	 address[SLEN], comment[SLEN], next_line[SLEN];
!     int  lines, iindex, line_pending = 0, line_len, err;
  
      /** First off, get to the first line of the message desired **/
  
!     if (fseek(mailfile, headers[current-1]->offset, 0) == -1) {
  	err = errno;
  	dprint(1,(debugfile,"Error: seek %ld resulted in errno %s (%s)\n", 
  		 headers[current-1]->offset, error_description(err), 
--- 300,311 ----
  	**/
  
      char ret_address[SLEN], buf[VERY_LONG_STRING], new_address[SLEN],
! 	 address[SLEN], comment[SLEN];
!     int  iindex, line_len, err;
  
      /** First off, get to the first line of the message desired **/
  
!     if (skip_envelope(headers[current-1], mailfile) == -1) {
  	err = errno;
  	dprint(1,(debugfile,"Error: seek %ld resulted in errno %s (%s)\n", 
  		 headers[current-1]->offset, error_description(err), 
***************
*** 256,295 ****
  
      /** now let's parse the actual message! **/
  
!     for (lines = headers[current-1]->lines;;) {
! 
!       /* read in another line if required - break out if end of mbox reached */
!       if ( !line_pending && (line_len = mail_gets(buf, SLEN, mailfile)) == 0 )
! 	  return;
!       line_pending = 0;
! 
!       /* break out at end of header or start of next message */
!       if ( line_len < 2 )
! 	return;
!       if (buf[line_len - 1] == '\n')
! 	lines--;
!       if (lines <= 0)
! 	return;
  
        /* we only want lines with addresses */
        if (!header_cmp(buf, "To", NULL) && !header_cmp(buf, "cc", NULL))
  	continue;
  
-       /* extract the addresses from this line and possible continuation lines */
-       next_line[0] = '\0';
- 
-       /* read in another line - continuation lines start with whitespace */
-       while ( (line_len = mail_gets(next_line, SLEN, mailfile)) != 0 &&
- 	      whitespace(next_line[0]) ) {
- 	no_ret(buf);
- 	strcat(buf, next_line); /* Append continuation line */
- 
- 	if (next_line[line_len - 1] == '\n')
- 	  lines--;
- 	next_line[0] = '\0';
-       }
- 
-       no_ret(buf);
        iindex = chloc(buf, ':')+1;		/* point beyond header name */
        dprint(2,(debugfile,"> %s\n",buf));
  
--- 325,340 ----
  
      /** now let's parse the actual message! **/
  
!     /* read_header_line reads also continuation lines ... 
!      * 2 == check that this is header line
!      */
!     while (0 < (line_len = read_header_line(mailfile,buf,sizeof(buf),
! 					    RHL_CHECK_HEADER))) {
  
        /* we only want lines with addresses */
        if (!header_cmp(buf, "To", NULL) && !header_cmp(buf, "cc", NULL))
  	continue;
  
        iindex = chloc(buf, ':')+1;		/* point beyond header name */
        dprint(2,(debugfile,"> %s\n",buf));
  
***************
*** 309,322 ****
  	    strcpy(new_address, address);
  	  else
  	    sprintf(new_address, ret_address, address);
! 	  optimize_and_add(new_address, full_address);
  
  	}
        }
-       if (next_line[0] != '\0') {
- 	strcpy(buf, next_line);
- 	line_pending++;
-       }
      }
  }
  
--- 354,363 ----
  	    strcpy(new_address, address);
  	  else
  	    sprintf(new_address, ret_address, address);
! 	  optimize_and_add(new_address, full_address, size);
  
  	}
        }
      }
  }
  
***************
*** 327,332 ****
--- 368,374 ----
  	    the screen has to be rewritten. **/
  
  	char return_address[SLEN], subject[SLEN];
+ 	char to_line[VERY_LONG_STRING];
  	int  return_value, form_letter;
  
  	form_letter = (headers[current-1]->status & FORM_LETTER);
***************
*** 339,348 ****
  		  catgets(elm_msg_cat, ElmSet, ElmFilledInForm, "Filled in form") :
  		  catgets(elm_msg_cat, ElmSet, ElmReYourMail, "Re: your mail") ) );
  	}
  	if (form_letter)
! 	  return_value = mail_filled_in_form(return_address, subject);
! 	else
! 	  return_value = send_msg(return_address, "", subject, TRUE, NO, TRUE);
  	return(return_value);
  }
  
--- 381,403 ----
  		  catgets(elm_msg_cat, ElmSet, ElmFilledInForm, "Filled in form") :
  		  catgets(elm_msg_cat, ElmSet, ElmReYourMail, "Re: your mail") ) );
  	}
+ #ifdef USE_EMBEDDED_ADDRESSES
+ 	to_line[0] = '\0';
+ 	handle_reply_to(return_address,to_line, sizeof (to_line));
+ #else
+ 	strcpy(to_line,return_address);
+ #endif
  	if (form_letter)
! 	  return_value = mail_filled_in_form(to_line, subject);
! 	else {
! 	  return_value = send_msg(to_line, "", subject,
! 				  MAIL_EDIT_MSG | MAIL_REPLYING,
! 				  NO);
!           if (me_retcode) {
!             headers[current-1]->status |= REPLIED;
!             headers[current-1]->status_chgd = TRUE;
!           }
!         }
  	return(return_value);
  }
  
***************
*** 356,367 ****
  
  	char return_address[SLEN], subject[SLEN];
  	char full_address[VERY_LONG_STRING];
  	int  return_value;
  
  	get_return(return_address, current-1);
  
  	full_address[0] = '\0';			/* no copies yet    */
! 	get_and_expand_everyone(return_address, full_address);
  	dprint(2,(debugfile,
  		"reply_to_everyone() - return_addr=\"%s\" full_addr=\"%s\"\n",
  		return_address,full_address));
--- 411,430 ----
  
  	char return_address[SLEN], subject[SLEN];
  	char full_address[VERY_LONG_STRING];
+ 	char to_line[VERY_LONG_STRING];
  	int  return_value;
  
  	get_return(return_address, current-1);
+ #ifdef USE_EMBEDDED_ADDRESSES
+         to_line[0] = '\0';
+         handle_reply_to(return_address,to_line, sizeof(to_line));
+ #else
+         strcpy(to_line,return_address);
+ #endif
  
  	full_address[0] = '\0';			/* no copies yet    */
! 	get_and_expand_everyone(return_address, full_address, 
! 				sizeof (full_address));
  	dprint(2,(debugfile,
  		"reply_to_everyone() - return_addr=\"%s\" full_addr=\"%s\"\n",
  		return_address,full_address));
***************
*** 369,376 ****
  	get_reply_subj( subject, headers[current-1]->subject,
  		  catgets(elm_msg_cat, ElmSet, ElmReYourMail, "Re: your mail"));
  
!         return_value = send_msg(return_address, full_address, subject, 
! 		TRUE, NO, TRUE);
  	return(return_value);
  
  }
--- 432,444 ----
  	get_reply_subj( subject, headers[current-1]->subject,
  		  catgets(elm_msg_cat, ElmSet, ElmReYourMail, "Re: your mail"));
  
!         return_value = send_msg(to_line, full_address, subject,
! 				MAIL_EDIT_MSG | MAIL_REPLYING,
! 				NO);
!         if (me_retcode) {
!           headers[current-1]->status |= REPLIED;
!           headers[current-1]->status_chgd = TRUE;
!         }
  	return(return_value);
  
  }
***************
*** 390,407 ****
  	char subject[SLEN], address[VERY_LONG_STRING];
  	int  results, edit_msg = FALSE;
  
- 	forwarding = TRUE;
- 
  	address[0] = '\0';
  
  	if (headers[current-1]->status & FORM_LETTER)
! 	  PutLine0(LINES-3,COLUMNS-40, catgets(elm_msg_cat, ElmSet, ElmNoEditingAllowed,
! 		"<No editing allowed.>"));
  	else {
  	  MCsprintf(subject, catgets(elm_msg_cat, ElmSet, ElmEditOutgoingMessage,
  		  "Edit outgoing message? (%c/%c) "), *def_ans_yes, *def_ans_no);
  	  edit_msg = (want_to(subject,
! 			      *def_ans_yes, LINES-3, 0) != *def_ans_no);
  	}
  
  	if (strlen(headers[current-1]->subject) > 0) {
--- 458,475 ----
  	char subject[SLEN], address[VERY_LONG_STRING];
  	int  results, edit_msg = FALSE;
  
  	address[0] = '\0';
  
  	if (headers[current-1]->status & FORM_LETTER)
! 	  PutLine0(elm_LINES-3,elm_COLUMNS-40, 
! 		   catgets(elm_msg_cat, ElmSet, 
! 			   ElmNoEditingAllowed,
! 			   "<No editing allowed.>"));
  	else {
  	  MCsprintf(subject, catgets(elm_msg_cat, ElmSet, ElmEditOutgoingMessage,
  		  "Edit outgoing message? (%c/%c) "), *def_ans_yes, *def_ans_no);
  	  edit_msg = (want_to(subject,
! 			      *def_ans_yes, elm_LINES-3, 0) != *def_ans_no);
  	}
  
  	if (strlen(headers[current-1]->subject) > 0) {
***************
*** 415,431 ****
  					     "(fwd)") != 0))
  	    strcat(subject, " (fwd)");
  
! 	  results = send_msg(address, "", subject, edit_msg,
! 	    headers[current-1]->status & FORM_LETTER? 
! 	    PREFORMATTED : allow_forms, FALSE);
  	}
  	else
  	  results = send_msg(address, "",
! 		catgets(elm_msg_cat, ElmSet, ElmForwardedMail, "Forwarded mail..."), edit_msg,
! 		headers[current-1]->status & FORM_LETTER ? PREFORMATTED : allow_forms, FALSE);
! 	
! 	forwarding = FALSE;
! 
  	return(results);
  }
  
--- 483,500 ----
  					     "(fwd)") != 0))
  	    strcat(subject, " (fwd)");
  
! 	  results = send_msg(address, "", subject, 
! 			     (edit_msg ? MAIL_EDIT_MSG : 0 ) | MAIL_FORWARDING,
! 			     headers[current-1]->status & FORM_LETTER ? 
! 			     PREFORMATTED : allow_forms);
  	}
  	else
  	  results = send_msg(address, "",
! 		catgets(elm_msg_cat, ElmSet, ElmForwardedMail, 
! 			"Forwarded mail..."), 
! 			     (edit_msg ? MAIL_EDIT_MSG : 0 ) | MAIL_FORWARDING,
! 			     headers[current-1]->status & FORM_LETTER ? 
! 			     PREFORMATTED : allow_forms);	
  	return(results);
  }
  
Index: WORK/src/returnadd.c
*** elm2.4.25/src/returnadd.c	Mon Apr 12 06:11:24 1993
--- WORK/src/returnadd.c	Mon Jun  3 20:19:21 1996
***************
*** 201,206 ****
--- 201,210 ----
  	    if (buf[len_buf-1] == '\n') {
  	      len_buf--;
  	      buf[len_buf] = '\0';
+ 	      if (len_buf > 0 && buf[len_buf-1] == '\r') {
+ 		len_buf--;
+ 		buf[len_buf] = '\0';
+ 	      }
  	    }
  	    strncat(buf, buf2, (SLEN-len_buf-1));
  	    len_buf = strlen(buf);
***************
*** 210,215 ****
--- 214,223 ----
  	    }
  	  }
  
+ 	  { /* Quick fix -- K E H */
+ 	    char *p = strchr(buf,'\r'); if (p) *p = '\0'; 
+ 	  }
+ 
  /* At this point, "buf" contains the unfolded header line, while "buf2" contains
     the next single line of text from the mail file */
  
***************
*** 231,241 ****
  	    get_address_from(buf, hold_return);
  	    buffer[0] = '\0';
            }
!           else if (header_cmp(buf, "Reply-To", NULL)) {
! 	    get_address_from(buf, buffer);
! 	    if (strlen(buffer) > 0) return(using_to);
!           }
! 
  #endif
  
  	  else if (len_buf < 2)	/* done with header */
--- 239,245 ----
  	    get_address_from(buf, hold_return);
  	    buffer[0] = '\0';
            }
! 	  /* reply-to is now handle in handle_reply_to */
  #endif
  
  	  else if (len_buf < 2)	/* done with header */
Index: WORK/src/save_opts.c
*** elm2.4.25/src/save_opts.c	Fri Mar 11 23:19:26 1994
--- WORK/src/save_opts.c	Mon Jun  3 20:18:57 1996
***************
*** 76,81 ****
--- 76,82 ----
  extern char version_buff[];
  
  char *error_description(), *sort_name(), *alias_sort_name(), *level_name();
+ char *mode_to_str();
  long  ftell();
  
  #include "save_opts.h"
***************
*** 160,165 ****
--- 161,170 ----
  		    s = SAVE_INFO_STR(x);
  		break;
  
+ 	    case DT_PRM:
+ 		s = mode_to_str(*SAVE_INFO_NUM(x));
+ 		break;
+ 
  	    case DT_CHR:
  		sprintf(buf, "%c", *SAVE_INFO_CHR(x));
  		s = buf;
***************
*** 295,300 ****
--- 300,306 ----
  		case DT_CHR:
  		case DT_BOL:
  		case DT_NUM:
+  		case DT_PRM:
  		    s = str_opt(x, SHORT);
  		    break;
  
Index: WORK/src/savecopy.c
*** elm2.4.25/src/savecopy.c	Mon May 16 02:10:12 1994
--- WORK/src/savecopy.c	Sun Jun 16 17:58:29 1996
***************
*** 101,118 ****
  #endif
  
  #include <errno.h>
  
  char *format_long(), *error_description(), *ctime();
  
  extern int errno;
  
! #ifdef MIME
! extern int msg_is_multipart;
! #endif
! extern long C_L_Position[2];   /*To Remember position of the Content-Length*/
! extern long C_StartData[2];    /*To Remember length of Header Area */
! extern long C_EndData[2];   /* To Remeber the End of the Data */
  
  
  /*
   * save_copy() - Append a copy of the message contained in "filename" to
--- 101,121 ----
  #endif
  
  #include <errno.h>
+ #include "me.h"
  
+ 
  char *format_long(), *error_description(), *ctime();
  
  extern int errno;
  
! /* Offsets for figuring the Content-Length header */
! extern long cl_offset;
! extern long cl_start;
! extern long cl_end;
  
+ #ifdef USE_REMAILER
+ extern int remailing;
+ #endif
  
  /*
   * save_copy() - Append a copy of the message contained in "filename" to
***************
*** 120,128 ****
--- 123,139 ----
   * the filenames right, and then invokes "append_copy_to_file()" to do
   * the dirty work.
   */
+ int
+ #ifdef MIME
+ save_copy(to, cc, bcc, filename, copy_file, form, mime_info)
+ #else
  save_copy(to, cc, bcc, filename, copy_file, form)
+ #endif
  char *to, *cc, *bcc, *filename, *copy_file;
  int form;
+ #ifdef MIME
+ mime_send_t *mime_info;
+ #endif
  {
  	char  buffer[SLEN],	/* read buffer 		       */
  	      savename[SLEN],	/* name of file saving into    */
***************
*** 197,212 ****
  			  "Append to mail folder `%s'? (%c/%c) "),
  			savename, *def_ans_yes, *def_ans_no);
  
! 		    answer = want_to(msg_buffer, *def_ans_no, LINES-2, 1);
  
  		    if (answer != *def_ans_yes) {
  			strcpy(savename, sent_mail);
! 			PutLine1 (LINES-2, 0, catgets(elm_msg_cat, ElmSet, ElmSavingToInstead,
  				  "Alright - saving to `%s' instead"),
  				  savename);
  			if (sleepmsg > 0)
  				sleep(sleepmsg);
! 			ClearLine (LINES-2);
  		    }
  		}
  	    }
--- 208,225 ----
  			  "Append to mail folder `%s'? (%c/%c) "),
  			savename, *def_ans_yes, *def_ans_no);
  
! 		    answer = want_to(msg_buffer, *def_ans_no, elm_LINES-2, 1);
  
  		    if (answer != *def_ans_yes) {
  			strcpy(savename, sent_mail);
! 			PutLine1 (elm_LINES-2, 0, catgets(elm_msg_cat, 
! 							  ElmSet, 
! 							  ElmSavingToInstead,
  				  "Alright - saving to `%s' instead"),
  				  savename);
  			if (sleepmsg > 0)
  				sleep(sleepmsg);
! 			ClearLine (elm_LINES-2);
  		    }
  		}
  	    }
***************
*** 231,246 ****
  			  "Create a new mail folder `%s'? (%c/%c) "),
  			savename, *def_ans_yes, *def_ans_no);
  
! 		    answer = want_to(msg_buffer, *def_ans_no, LINES-2, 1);
  
  		    if (answer != *def_ans_yes) {
  			strcpy(savename, sent_mail);
! 			PutLine1 (LINES-2, 0, catgets(elm_msg_cat, ElmSet, ElmSavingToInstead,
  				  "Alright - saving to `%s' instead"),
  				  savename);
  			if (sleepmsg > 0)
  				sleep(sleepmsg);
! 			ClearLine (LINES-2);
  		    }
  		}
  	    }
--- 244,261 ----
  			  "Create a new mail folder `%s'? (%c/%c) "),
  			savename, *def_ans_yes, *def_ans_no);
  
! 		    answer = want_to(msg_buffer, *def_ans_no, elm_LINES-2, 1);
  
  		    if (answer != *def_ans_yes) {
  			strcpy(savename, sent_mail);
! 			PutLine1 (elm_LINES-2, 0, catgets(elm_msg_cat, 
! 							  ElmSet, 
! 							  ElmSavingToInstead,
  				  "Alright - saving to `%s' instead"),
  				  savename);
  			if (sleepmsg > 0)
  				sleep(sleepmsg);
! 			ClearLine (elm_LINES-2);
  		    }
  		}
  	    }
***************
*** 281,288 ****
  		sleep(sleepmsg);
  	  strcpy(savename, sent_mail);
  	}
! 
  	return (append_copy_to_file(to, cc, bcc, savename, filename, form)==0);
  }
  
  char *
--- 296,307 ----
  		sleep(sleepmsg);
  	  strcpy(savename, sent_mail);
  	}
! #ifdef MIME
! 	return (append_copy_to_file(to, cc, bcc, savename, filename, form,
! 				    mime_info)==0);
! #else
  	return (append_copy_to_file(to, cc, bcc, savename, filename, form)==0);
+ #endif
  }
  
  char *
***************
*** 322,340 ****
  	ncf_prompt = catgets(elm_msg_cat, ElmSet, ElmSaveCopyInPrompt,
  			"Save copy in (use '?' for help/to list folders): ");
      }
      /* expand passed copy file name into English */
      strcpy(buffer, cf_english(fn));
  
      /* prepare screen with instructions */
!     MoveCursor(LINES-2, 0);
      CleartoEOS();
!     PutLine0(LINES-2, 0, ncf_prompt);
  
      while(1) {
  
        /* get file name from user input */
        strcpy(origbuffer, buffer);
!       optionally_enter(buffer, LINES-2, strlen(ncf_prompt), FALSE, FALSE);
  
        if(strcmp(buffer, "?") != 0) { /* got what we wanted - non-help choice */
  
--- 341,372 ----
  	ncf_prompt = catgets(elm_msg_cat, ElmSet, ElmSaveCopyInPrompt,
  			"Save copy in (use '?' for help/to list folders): ");
      }
+ 
+ redraw1:
      /* expand passed copy file name into English */
      strcpy(buffer, cf_english(fn));
  
      /* prepare screen with instructions */
!     MoveCursor(elm_LINES-2, 0);
      CleartoEOS();
!     PutLine0(elm_LINES-2, 0, ncf_prompt);
  
      while(1) {
+       int status;
  
        /* get file name from user input */
        strcpy(origbuffer, buffer);
!       status = optionally_enter(buffer, elm_LINES-2, strlen(ncf_prompt), 
! 				OE_REDRAW_MARK);
!       if (REDRAW_MARK == status) {
! 	redraw = TRUE;
! 	goto redraw1;
!       }
! 
!       if (status != 0) {
! 	fn[0] = '\0';
! 	return redraw;
!       }
  
        if(strcmp(buffer, "?") != 0) { /* got what we wanted - non-help choice */
  
***************
*** 347,357 ****
  	/* else user presumably left our English expansion - no change in fn */
  
  	/* display English expansion of new user input a while */
! 	PutLine0(LINES-2, strlen(ncf_prompt), cf_english(fn));
! 	MoveCursor(LINES, 0);
  	if (sleepmsg > 0)
  		sleep((sleepmsg + 1) / 2);
! 	MoveCursor(LINES-2, 0);
  	CleartoEOS();
  
  	return(redraw);
--- 379,389 ----
  	/* else user presumably left our English expansion - no change in fn */
  
  	/* display English expansion of new user input a while */
! 	PutLine0(elm_LINES-2, strlen(ncf_prompt), cf_english(fn));
! 	MoveCursor(elm_LINES, 0);
  	if (sleepmsg > 0)
  		sleep((sleepmsg + 1) / 2);
! 	MoveCursor(elm_LINES-2, 0);
  	CleartoEOS();
  
  	return(redraw);
***************
*** 374,380 ****
        }
  
        list_folders(4, helpmsg, NULL);
!       PutLine0(LINES-2, 0, ncf_prompt);
  
        /* restore as default to English version of the passed copy file name */
        strcpy(buffer, cf_english(fn));
--- 406,412 ----
        }
  
        list_folders(4, helpmsg, NULL);
!       PutLine0(elm_LINES-2, 0, ncf_prompt);
  
        /* restore as default to English version of the passed copy file name */
        strcpy(buffer, cf_english(fn));
***************
*** 382,390 ****
      }
  }
  
- 
  int
  append_copy_to_file(to, cc, bcc, fname_copy, fname_mssg, form)
  char *to;
  char *cc;
  char *bcc;
--- 414,425 ----
      }
  }
  
  int
+ #ifdef MIME
+ append_copy_to_file(to, cc, bcc, fname_copy, fname_mssg, form, mime_info)
+ #else
  append_copy_to_file(to, cc, bcc, fname_copy, fname_mssg, form)
+ #endif
  char *to;
  char *cc;
  char *bcc;
***************
*** 391,396 ****
--- 426,434 ----
  char *fname_copy;
  char *fname_mssg;
  int form;
+ #ifdef MIME
+ mime_send_t *mime_info;
+ #endif
  {
      int err;
      FILE *fp_copy, *fp_mssg;
***************
*** 412,444 ****
  
      /* dump the header to the end of the copy file */
      save_file_stats(fname_copy);
      fp_copy = write_header_info(fname_copy, to, cc, bcc, (form == YES), TRUE);
      if (fp_copy == NULL) {
  	(void) fclose(fp_mssg);
  	return -1;
      }
      restore_file_stats(fname_copy);
-     C_StartData[0] = ftell(fp_copy);
  
!     /* dump the contents of the message to the end of the copy file */
!     copy_message_across(fp_mssg, fp_copy, TRUE);
  
  #ifdef MIME
!     if (!form != NO && msg_is_multipart) {
! 	fprintf(fp_copy, "--%%#%%record%%#%%--\n");
! 	if (C_L_Position[1] != 0L) {
! 	    C_EndData[1] = ftell(fp_copy);
! 	    C_L_Position[1] = fseek(fp_copy, C_L_Position[1], 0);
! 	    fprintf(fp_copy, "%d", C_EndData[1] - C_StartData[1]);
! 	    fseek(fp_copy, C_EndData[1], 0);
! 	}
      }
  #endif
-     C_EndData[0] = ftell(fp_copy) ;
  
  #ifdef MMDF
      /*
!      * Actually, the C_EndData just calculated is wrong for MMDF.
       * Because we are saving a copy instead of handing off to
       * submit, copy_message_across will have added the trailing
       * MMDF MSG_SEPARATOR to the end of the saved message to ensure
--- 450,494 ----
  
      /* dump the header to the end of the copy file */
      save_file_stats(fname_copy);
+ #ifdef MIME
+     fp_copy = write_header_info(fname_copy, to, cc, bcc, (form == YES), TRUE,
+ 				mime_info);
+ #else
      fp_copy = write_header_info(fname_copy, to, cc, bcc, (form == YES), TRUE);
+ #endif
      if (fp_copy == NULL) {
  	(void) fclose(fp_mssg);
  	return -1;
      }
      restore_file_stats(fname_copy);
  
!     cl_start = ftell(fp_copy);
  
+     /* dump the contents of the message to the end of the copy file */
  #ifdef MIME
! #ifdef USE_REMAILER
!     if (remailing) {
!       if (remailer_copy_message_across(fp_mssg, fp_copy, TRUE, mime_info) == -1)
!         return(-1);
!     }
!     else
! #endif
!     copy_message_across(fp_mssg, fp_copy, TRUE, mime_info);
! #else
! #ifdef USE_REMAILER
!     if (remailing) {
!       if (remailer_copy_message_across(fp_mssg, fp_copy, TRUE) == -1)
!         return(-1);
      }
+     else
+ #endif
+     copy_message_across(fp_mssg, fp_copy, TRUE);
  #endif
  
+     cl_end = ftell(fp_copy) ;
  #ifdef MMDF
      /*
!      * Actually, the cl_end just calculated is wrong for MMDF.
       * Because we are saving a copy instead of handing off to
       * submit, copy_message_across will have added the trailing
       * MMDF MSG_SEPARATOR to the end of the saved message to ensure
***************
*** 448,459 ****
       * localized to this function, we will just subtract off the
       * length of the MSG_SEPARATOR.
       */
!     C_EndData[0] -= strlen(MSG_SEPARATOR);
  #endif /* MMDF */
  
      /* go fixup the content length header */
!     fseek(fp_copy, C_L_Position[0], 0);
!     fprintf(fp_copy, "%d", C_EndData[0] - C_StartData[0]);
  
      /* copy successfully done */
      fclose(fp_copy);
--- 498,509 ----
       * localized to this function, we will just subtract off the
       * length of the MSG_SEPARATOR.
       */
!     cl_end -= strlen(MSG_SEPARATOR);
  #endif /* MMDF */
  
      /* go fixup the content length header */
!     fseek(fp_copy, cl_offset, 0);
!     fprintf(fp_copy, "%d", cl_end - cl_start);
  
      /* copy successfully done */
      fclose(fp_copy);
***************
*** 460,463 ****
      fclose(fp_mssg);
      return 0;
  }
- 
--- 510,512 ----
Index: WORK/src/screen.c
*** elm2.4.25/src/screen.c	Wed Jan 20 05:02:41 1993
--- WORK/src/screen.c	Thu Aug  8 22:36:57 1996
***************
*** 58,65 ****
  
  	show_last_error();
  	
! 	if (hp_terminal) 
! 	  define_softkeys(MAIN);
  }
  
  update_title()
--- 58,64 ----
  
  	show_last_error();
  	
! 	/* define_softkeys(MAIN); */
  }
  
  update_title()
***************
*** 109,126 ****
  	/** write main system menu... **/
  
  	if (user_level == 0) {	/* a rank beginner.  Give less options  */
! 	  Centerline(LINES-7, catgets(elm_msg_cat, ElmSet, ElmLevel0MenuLine1,
    "You can use any of the following commands by pressing the first character;"));
!           Centerline(LINES-6, catgets(elm_msg_cat, ElmSet, ElmLevel0MenuLine2,
  "d)elete or u)ndelete mail,  m)ail a message,  r)eply or f)orward mail,  q)uit"));
! 	  Centerline(LINES-5, catgets(elm_msg_cat, ElmSet, ElmLevel0MenuLine3,
    "To read a message, press <return>.  j = move down, k = move up, ? = help"));
  	} else {
! 	Centerline(LINES-7, catgets(elm_msg_cat, ElmSet, ElmLevel1MenuLine1,
    "|=pipe, !=shell, ?=help, <n>=set current to n, /=search pattern"));
!         Centerline(LINES-6, catgets(elm_msg_cat, ElmSet, ElmLevel1MenuLine2,
  "a)lias, C)opy, c)hange folder, d)elete, e)dit, f)orward, g)roup reply, m)ail,"));
! 	Centerline(LINES-5, catgets(elm_msg_cat, ElmSet, ElmLevel1MenuLine3,
    "n)ext, o)ptions, p)rint, q)uit, r)eply, s)ave, t)ag, u)ndelete, or e(x)it"));
  	}
  }
--- 108,131 ----
  	/** write main system menu... **/
  
  	if (user_level == 0) {	/* a rank beginner.  Give less options  */
! 	  Centerline(elm_LINES-7, catgets(elm_msg_cat, ElmSet, 
! 					  ElmLevel0MenuLine1,
    "You can use any of the following commands by pressing the first character;"));
!           Centerline(elm_LINES-6, catgets(elm_msg_cat, ElmSet, 
! 					  ElmLevel0MenuLine2,
  "d)elete or u)ndelete mail,  m)ail a message,  r)eply or f)orward mail,  q)uit"));
! 	  Centerline(elm_LINES-5, catgets(elm_msg_cat, ElmSet, 
! 					  ElmLevel0MenuLine3,
    "To read a message, press <return>.  j = move down, k = move up, ? = help"));
  	} else {
! 	Centerline(elm_LINES-7, catgets(elm_msg_cat, ElmSet, 
! 					ElmLevel1MenuLine1,
    "|=pipe, !=shell, ?=help, <n>=set current to n, /=search pattern"));
!         Centerline(elm_LINES-6, catgets(elm_msg_cat, ElmSet, 
! 					ElmLevel1MenuLine2,
  "a)lias, C)opy, c)hange folder, d)elete, e)dit, f)orward, g)roup reply, m)ail,"));
! 	Centerline(elm_LINES-5, catgets(elm_msg_cat, ElmSet, 
! 					ElmLevel1MenuLine3,
    "n)ext, o)ptions, p)rint, q)uit, r)eply, s)ave, t)ag, u)ndelete, or e(x)it"));
  	}
  }
***************
*** 180,188 ****
  			       FALSE);
  	  }
  	  else {
! 	  using_to = tail_of(headers[this_msg]->from, newfrom,
! 	    headers[this_msg]->to); 
! 
  	  if (this_msg == current-1) 
  	    build_header_line(buffer, headers[this_msg], this_msg+1,
  			    TRUE, newfrom, using_to);
--- 185,197 ----
  			       FALSE);
  	  }
  	  else {
! 	    using_to = DisplayAddress(headers[this_msg], newfrom, 
! 				      sizeof (newfrom));
! #ifdef MIME
! 	    if (!(headers[this_msg] -> status & NOHDRENCODING) &&
! 		is_rfc1522 (newfrom))
! 	      rfc1522_decode (newfrom, sizeof (newfrom));
! #endif
  	  if (this_msg == current-1) 
  	    build_header_line(buffer, headers[this_msg], this_msg+1,
  			    TRUE, newfrom, using_to);
***************
*** 219,227 ****
  	/* clear unused lines */
  
  	if (mini_menu)
! 	  last_line = LINES-8;
  	else
! 	  last_line = LINES-4;
  
  	while (line < last_line) {
  	  CleartoEOLN();
--- 228,236 ----
  	/* clear unused lines */
  
  	if (mini_menu)
! 	  last_line = elm_LINES-8;
  	else
! 	  last_line = elm_LINES-4;
  
  	while (line < last_line) {
  	  CleartoEOLN();
***************
*** 277,286 ****
  	    build_alias_line(new_buffer, aliases[current-1], current,
  			     TRUE);
  	  else {
! 	  using_to = tail_of(headers[current-1]->from, newfrom,
! 	    headers[current-1]->to); 
! 	  build_header_line(new_buffer, headers[current-1],  current,
! 		  TRUE, newfrom, using_to);
  	  }
  
  	  /* clear last current if it's in proper range */
--- 286,300 ----
  	    build_alias_line(new_buffer, aliases[current-1], current,
  			     TRUE);
  	  else {
! 	    using_to = DisplayAddress(headers[current-1], newfrom,
! 				      sizeof(newfrom));
! #ifdef MIME
! 	    if (!(headers[current-1] -> status & NOHDRENCODING) &&
! 		is_rfc1522 (newfrom))
! 	      rfc1522_decode (newfrom, sizeof (newfrom));
! #endif
! 	    build_header_line(new_buffer, headers[current-1],  current,
! 			      TRUE, newfrom, using_to);
  	  }
  
  	  /* clear last current if it's in proper range */
***************
*** 298,307 ****
  	      build_alias_line(old_buffer, aliases[last_current-1],
  	                       last_current, FALSE);
  	    else {
! 	    using_to = tail_of(headers[last_current-1]->from, newfrom,
! 	      headers[last_current-1]->to); 
! 	    build_header_line(old_buffer, headers[last_current-1], 
! 		 last_current, FALSE, newfrom, using_to);
  	    }
  
  	    ClearLine(last_line);
--- 312,326 ----
  	      build_alias_line(old_buffer, aliases[last_current-1],
  	                       last_current, FALSE);
  	    else {
! 	      using_to = DisplayAddress(headers[last_current-1], newfrom,
! 					sizeof(newfrom));
! #ifdef MIME
! 	      if (!(headers[last_current-1] -> status & NOHDRENCODING) &&
! 		  is_rfc1522 (newfrom))
! 		rfc1522_decode (newfrom, sizeof (newfrom));
! #endif
! 	      build_header_line(old_buffer, headers[last_current-1], 
! 				last_current, FALSE, newfrom, using_to);
  	    }
  
  	    ClearLine(last_line);
***************
*** 369,375 ****
  
  	sprintf(buffer, "%s%s%c%-3d %s ",
  		(highlight && arrow_cursor)? "->" : "  ",
! 		show_status(entry->status),
  		(entry->status & TAGGED?  '+' : ' '),
  	        message_number,
  	        entry->time_menu); 
--- 388,394 ----
  
  	sprintf(buffer, "%s%s%c%-3d %s ",
  		(highlight && arrow_cursor)? "->" : "  ",
! 		show_status(entry->status,entry),
  		(entry->status & TAGGED?  '+' : ' '),
  	        message_number,
  	        entry->time_menu); 
***************
*** 393,400 ****
  	 * aesthetically the full length of the line.
  	 */
  	if ((highlight && !arrow_cursor)
! 		|| (COLUMNS-44 < (subj_width =strlen(entry->subject))))
! 	    subj_width = COLUMNS-44;
  
  	/* complete line with sender, length and subject. */
  	sprintf(buffer + strlen(buffer), "%-*.*s (%d) %s%-*.*s",
--- 412,419 ----
  	 * aesthetically the full length of the line.
  	 */
  	if ((highlight && !arrow_cursor)
! 		|| (elm_COLUMNS-44 < (subj_width =strlen(entry->subject))))
! 	    subj_width = elm_COLUMNS-44;
  
  	/* complete line with sender, length and subject. */
  	sprintf(buffer + strlen(buffer), "%-*.*s (%d) %s%-*.*s",
***************
*** 448,455 ****
  	return(FALSE);
  }
  
! char *show_status(status)
  int status;
  {
  	/** This routine returns a pair of characters indicative of
  	    the status of this message.  The first character represents
--- 467,475 ----
  	return(FALSE);
  }
  
! char *show_status(status,hdr)
  int status;
+ struct header_rec *hdr;
  {
  	/** This routine returns a pair of characters indicative of
  	    the status of this message.  The first character represents
***************
*** 483,488 ****
--- 503,509 ----
  	else if (status & EXPIRED)	mybuffer[0] = 'E';
  	else if (status & NEW)		mybuffer[0] = 'N';
  	else if (status & UNREAD)	mybuffer[0] = 'O';
+         else if (status & REPLIED)	mybuffer[0] = 'r';
  	else                            mybuffer[0] = ' ';
  
  	/** and the second... **/
***************
*** 492,502 ****
  	else if (status & PRIVATE)      mybuffer[1] = 'P';
  	else if (status & ACTION)       mybuffer[1] = 'A';
  	else if (status & FORM_LETTER)  mybuffer[1] = 'F';
  #ifdef MIME
! 	else if ((status & MIME_MESSAGE) &&
! 		 ((status & MIME_NOTPLAIN) ||
! 		  (status & MIME_NEEDDECOD))) mybuffer[1] = 'M';
  #endif /* MIME */
  	else 			        mybuffer[1] = ' ';
  
  	mybuffer[2] = '\0';
--- 513,536 ----
  	else if (status & PRIVATE)      mybuffer[1] = 'P';
  	else if (status & ACTION)       mybuffer[1] = 'A';
  	else if (status & FORM_LETTER)  mybuffer[1] = 'F';
+ 	else if (hdr) {
+ 	  if (hdr->encrypted)                     mybuffer[1] = 'e';
  #ifdef MIME
! 	  else if ((status & MIME_MESSAGE) && (status & MIME_UNSUPPORTED))
! 	    mybuffer[1] = '?';
! 	  else if ((status & MIME_MESSAGE) && hdr->mime_rec.notplain)
! 	    mybuffer[1] = 'M';
! 	  else if ((status & PRE_MIME_CONTENT) && hdr->mime_rec.notplain)
! 	    mybuffer[1] = 'm';
  #endif /* MIME */
+ #ifdef USE_PGP
+ 	  else if (hdr->pgp & PGP_MESSAGE)	  mybuffer[1] = 'P';
+ 	  else if (hdr->pgp & PGP_SIGNED_MESSAGE) mybuffer[1] = 'S';
+ 	  else if (hdr->pgp & PGP_PUBLIC_KEY)	  mybuffer[1] = 'K';
+ #endif /* USE_PGP */
+ 	  else	    
+ 	    mybuffer[1] = ' ';
+ 	}
  	else 			        mybuffer[1] = ' ';
  
  	mybuffer[2] = '\0';
Index: WORK/src/showmsg.c
*** elm2.4.25/src/showmsg.c	Tue Aug 30 18:09:44 1994
--- WORK/src/showmsg.c	Thu Jun 13 23:37:26 1996
***************
*** 104,130 ****
  **/
  
  #include "headers.h"
- #include "s_elm.h"
  #include <errno.h>
! 
! #ifdef BSD
! # include <sys/wait.h>
! #endif
! 
! #ifndef I_UNISTD
! void _exit();
! #endif
  
  extern int errno;
  
! extern char *elm_date_str(), *error_description();
  
! int    memory_lock = FALSE;	/* is it available?? */
! int    pipe_abort  = FALSE;	/* did we receive a SIGNAL(SIGPIPE)? */
  
! FILE *pipe_wr_fp;		/* file pointer to write to external pager */
! extern int lines_displayed,	/* defined in "builtin" */	
! 	   lines_put_on_screen;	/*    ditto too!        */
  
  int
  show_msg(number)
--- 104,136 ----
  **/
  
  #include "headers.h"
  #include <errno.h>
! #include "s_elm.h"
! #include "me.h"
  
  extern int errno;
  
! int pipe_abort = FALSE; /* not used anymore, but won't compile without it */
  
! #ifdef MIME
! static int
! need_meta (hdr)
! struct header_rec *hdr;
! {
!   /* Determine whether or not we need to call metamail to display the
!    * message contents.
!    */
!   int result = 0;
! 
!   if ((hdr->status & (MIME_MESSAGE)) && (hdr->status & MIME_UNSUPPORTED))
!       result = TRUE;
!   else if (hdr->status & (MIME_MESSAGE | PRE_MIME_CONTENT))
!     result = hdr->mime_rec.notplain;
  
!   dprint(9,(debugfile,"need_meta=%d\n",result));
!   return result;
! }
! #endif
  
  int
  show_msg(number)
***************
*** 140,183 ****
  	     the index screen (to be processed via process_showmsg_cmd()).
  	***/
  
- 	char title1[SLEN], title2[SLEN], title3[SLEN], titlebuf[SLEN];
- 	char who[LONG_STRING], buffer[VERY_LONG_STRING];
- #if defined(BSD) && !defined(WEXITSTATUS)
- 	union wait wait_stat;
- #else
- 	int wait_stat;
- #endif
- 
- 	int crypted = 0;			/* encryption */
- 	int weed_header, weeding_out = 0;	/* weeding    */ 
- 	int using_to,				/* misc use   */
- 	    pipe_fd[2],				/* pipe file descriptors */
- 	    new_pipe_fd,			/* dup'ed pipe fil des */
- 	    lines,				/* num lines in msg */
- 	    fork_ret,				/* fork return value */
- 	    wait_ret,				/* wait return value */
- 	    form_letter = FALSE,		/* Form ltr?  */
- 	    form_letter_section = 0,		/* section    */
- 	    padding = 0,			/*   counter  */
- 	    builtin = FALSE,			/* our pager? */
- 	    val = 0,				/* return val */
- 	    buf_len,				/* line length */
- 	    err;				/* place holder for errno */
  	struct header_rec *current_header = headers[number-1];
- #ifdef	SIGTSTP
- 	SIGHAND_TYPE	(*oldstop)(), (*oldcont)();
- #endif
- #ifdef	SIGWINCH
- 	SIGHAND_TYPE	(*oldwinch)();
- #endif
  
- 	lines = current_header->lines; 
- 
  	dprint(4, (debugfile,"displaying %d lines from message %d using %s\n", 
! 		lines, number, pager));
  
  	if (number > message_count || number < 1)
! 	  return(val);
  
  	if(ison(current_header->status, NEW)) {
  	  clearit(current_header->status, NEW);   /* it's been read now! */
--- 146,158 ----
  	     the index screen (to be processed via process_showmsg_cmd()).
  	***/
  
  	struct header_rec *current_header = headers[number-1];
  
  	dprint(4, (debugfile,"displaying %d lines from message %d using %s\n", 
! 		current_header->lines, number, pager));
  
  	if (number > message_count || number < 1)
! 	  return(0);
  
  	if(ison(current_header->status, NEW)) {
  	  clearit(current_header->status, NEW);   /* it's been read now! */
***************
*** 188,631 ****
  	  current_header->status_chgd = TRUE;
  	}
  
- 	memory_lock = FALSE;
- 
- 	/* some explanation for that last one - We COULD use memory locking
- 	   to speed up the paging, but the action of "ClearScreen" on a screen
- 	   with memory lock turned on seems to vary considerably (amazingly so)
- 	   so it's safer to only allow memory lock to be a viable bit of
- 	   trickery when dumping text to the screen in scroll mode.
- 	   Philosophical arguments should be forwarded to Bruce at the 
- 	   University of Walamazoo, Australia, via ACSNet  *wry chuckle* */
- 
  #ifdef MIME
! 	if ((current_header->status & MIME_MESSAGE) &&
! 	    ((current_header->status & MIME_NEEDDECOD) ||
! 	     (current_header->status & MIME_NOTPLAIN)) &&
! 	    !getenv("NOMETAMAIL") ) {
! 	    char fname[STRING], Cmd[SLEN], line[VERY_LONG_STRING];
! 	    int code, err;
! 	    long lines = current_header->lines;
! 	    FILE *fpout;
! 
! 	    if (fseek(mailfile, current_header->offset, 0) != -1) {
! 		sprintf(fname, "%semm.%d.%d", temp_dir, getpid(), getuid());
! 		if ((fpout = fopen(fname, "w")) != NULL) {
! 		    copy_message("", fpout, CM_DECODE);
! 		    (void) fclose (fpout);
! 		    sprintf(Cmd, "metamail -p -z -m Elm %s", fname);
! 		    Raw(OFF);
!                   ClearScreen();
! 		    code = system_call(Cmd, SY_ENAB_SIGINT);
! 		    Raw(ON | NO_TITE);	/* Raw on but don't switch screen */
! 		    (void) unlink (fname);
! 		    PutLine0(LINES,0, catgets(elm_msg_cat, ElmSet, ElmPressAnyKeyIndex,
! 			     "Press any key to return to index."));
! 		    (void) ReadCh();
! 		    printf("\r\n");
! 		    Raw(OFF | NO_TITE); /* Raw off so raw on takes effect */
! 		    Raw(ON); /* Finally raw on and switch screen */
  		    return(0);
  		}
! 	    }
! 	}
! #endif
! 
! 	if (fseek(mailfile, current_header->offset, 0) == -1) {
! 	  err = errno;
! 	  dprint(1, (debugfile,
! 		  "Error: seek %d bytes into file, errno %s (show_message)\n",
! 		  current_header->offset, error_description(err)));
! 	  error2(catgets(elm_msg_cat, ElmSet, ElmSeekFailedFile,
! 		  "ELM [seek] couldn't read %d bytes into file (%s)."),
! 		  current_header->offset, error_description(err));	
! 	  return(val);
! 	}
! 	if(current_header->encrypted)
! 	  getkey(OFF);
! 
! 	if(builtin=(first_word(pager,"builtin")||
! 	   first_word(pager,"internal"))||
! 	   ( builtin_lines < 0 ? lines < LINES + builtin_lines :
! 	    lines < builtin_lines))
! 
! 	  start_builtin(lines);
! 
! 	else {
! 
! 	  /* put terminal out of raw mode so external pager has normal env */
! 	  Raw(OFF);
! 
! 	  /* create pipe for external pager and fork */
! 
! 	  if(pipe(pipe_fd) == -1) {
! 	    err = errno;
! 	    dprint(1, (debugfile, "Error: pipe failed, errno %s (show_msg)\n",
! 	      error_description(err)));
! 	    error1(catgets(elm_msg_cat, ElmSet, ElmPreparePagerPipe,
! 	      "Could not prepare for external pager(pipe()-%s)."),
! 	      error_description(err));	
! 	    Raw(ON);
! 	    return(val);
! 	  }
! 
! 	  if((fork_ret = fork()) == -1) {
! 
! 	    err = errno;
! 	    dprint(1, (debugfile, "Error: fork failed, errno %s (show_msg)\n",
! 	      error_description(err)));
! 	    error1(catgets(elm_msg_cat, ElmSet, ElmPreparePagerFork,
! 	      "Could not prepare for external pager(fork()-%s)."),
! 	      error_description(err));	
! 	    Raw(ON);
! 	    return(val);
! 
! 	  } else if (fork_ret == 0) {
! 
! 	    /* child fork */
! 
! 	    /* close write-only pipe fd and fit read-only pipe fd to stdin */
! 
! 	    close(pipe_fd[1]);
! 	    close(fileno(stdin));
! 	    if((new_pipe_fd = dup(pipe_fd[0])) == -1) {
! 	      err = errno;
! 	      dprint(1, (debugfile, "Error: dup failed, errno %s (show_msg)\n",
! 		error_description(err)));
! 	      error1(catgets(elm_msg_cat, ElmSet, ElmPreparePagerDup,
! 	        "Could not prepare for external pager(dup()-%s)."),
! 		error_description(err));	
! 	      _exit(err);
! 	    }
! 	    close(pipe_fd[0]);	/* original pipe fd no longer needed */
! 
! 	    /* use stdio on new pipe fd */
! 	    if(fdopen(new_pipe_fd, "r") == NULL) {
! 	      err = errno;
! 	      dprint(1,
! 		(debugfile, "Error: child fdopen failed, errno %s (show_msg)\n",
! 		error_description(err)));
! 	      error1(catgets(elm_msg_cat, ElmSet, ElmPreparePagerChildFdopen,
! 		"Could not prepare for external pager(child fdopen()-%s)."),
! 		error_description(err));	
! 	      _exit(err);
! 	    }
! 
! 	    /* now execute pager and exit */
! 	    
! 	    /* system_call() will return user to user's normal permissions.
! 	     * This is what makes this pipe secure - user won't have elm's
! 	     * special setgid permissions (if so configured) and will only
! 	     * be able to execute a pager that user normally has permission
! 	     * to execute */
! 
! 	    _exit(system_call(pager, SY_ENAB_SIGINT));
! 	  
! 	  } /* else this is the parent fork */
! 
! 	  /* close read-only pipe fd and do write-only with stdio */
! 	  close(pipe_fd[0]);
! 
! 	  if((pipe_wr_fp = fdopen(pipe_fd[1], "w")) == NULL) {
! 	    err = errno;
! 	    dprint(1,
! 	      (debugfile, "Error: parent fdopen failed, errno %s (show_msg)\n",
! 	      error_description(err)));
! 	    error1(catgets(elm_msg_cat, ElmSet, ElmPreparePagerParentFdopen,
! 	      "Could not prepare for external pager(parent fdopen()-%s)."),
! 	      error_description(err));	
! 
! 	    /* Failure - must close pipe and wait for child */
! 	    close(pipe_fd[1]);
! 	    while ((wait_ret = wait(&wait_stat)) != fork_ret && wait_ret!= -1)
! 	      ;
! 
! 	    Raw(OFF);
! 	    return(val);	/* pager may have already touched the screen */
! 	  }
! 
! 	  /* and that's it! */
! 	  lines_displayed = 0;
! #ifdef	SIGTSTP
! 	  oldstop = signal(SIGTSTP,SIG_DFL);
! 	  oldcont = signal(SIGCONT,SIG_DFL);
! #endif 
! #ifdef	SIGWINCH
! 	  oldwinch = signal(SIGWINCH,SIG_DFL);
! #endif
! 	}
! 
! 	ClearScreen();
! 
! 	if (cursor_control) transmit_functions(OFF);
! 
! 	pipe_abort = FALSE;
! 
! 	if (form_letter = (current_header->status&FORM_LETTER)) {
! 	  if (filter)
! 	    form_letter_section = 1;	/* initialize to section 1 */
! 	}
! 
! 	if (title_messages && filter) {
! 
! 	  using_to =
! 	    tail_of(current_header->from, who, current_header->to);
! 
! 	  MCsprintf(title1, "%s %d/%d  ",
! 		    headers[current-1]->status & DELETED ? nls_deleted :
! 		    form_letter ? nls_form: nls_message,
! 		    number, message_count);
! 	  MCsprintf(title2, "%s %s", using_to? nls_to : nls_from, who);
! 	  elm_date_str(title3, current_header->time_sent + current_header->tz_offset);
! 	  strcat(title3, " ");
! 	  strcat(title3, current_header->time_zone);
! 
! 	  /* truncate or pad title2 portion on the right
! 	   * so that line fits exactly */
! 	  padding =
! 	    COLUMNS -
! 	    (strlen(title1) + (buf_len=strlen(title2)) + strlen(title3));
! 
! 	  sprintf(titlebuf, "%s%-*.*s%s\n", title1, buf_len+padding,
! 	      buf_len+padding, title2, title3);
! 
! 	  if (builtin)
! 	    display_line(titlebuf, strlen(titlebuf));
! 	  else
! 	    fprintf(pipe_wr_fp, "%s", titlebuf);
! 
! 	  /** if there's a subject, let's output it next,
! 	      centered if it fits on a single line.  **/
! 
! 	  if ((buf_len = strlen(current_header->subject)) > 0 && 
! 		matches_weedlist("Subject:")) {
! 	    padding = (buf_len < COLUMNS ? COLUMNS - buf_len : 0);
! 	    sprintf(buffer, "%*s%s\n", padding/2, "", current_header->subject);
! 	  } else
! 	    strcpy(buffer, "\n");
! 
! 	  if (builtin)
! 	    display_line(buffer, strlen(buffer));
! 	  else
! 	    fprintf(pipe_wr_fp, "%s", buffer);
! 	  
! 	  /** was this message address to us?  if not, then to whom? **/
! 
! 	  if (! using_to && matches_weedlist("To:") && filter &&
! 	      strcmp(current_header->to,username) != 0 &&
! 	      strlen(current_header->to) > 0) {
! 	    sprintf(buffer, catgets(elm_msg_cat, ElmSet, ElmMessageAddressedTo,
! 		  "%s(message addressed to %.60s)\n"), 
! 	          strlen(current_header->subject) > 0 ? "\n" : "",
! 		  current_header->to);
! 	    if (builtin)
! 	      display_line(buffer, strlen(buffer));
! 	    else
! 	      fprintf(pipe_wr_fp, "%s", buffer);
! 	  }
! 	
! 	  /** The test above is: if we didn't originally send the mail
! 	      (e.g. we're not reading "mail.sent") AND the user is currently
! 	      weeding out the "To:" line (otherwise they'll get it twice!)
! 	      AND the user is actually weeding out headers AND the message 
! 	      wasn't addressed to the user AND the 'to' address is non-zero 
! 	      (consider what happens when the message doesn't HAVE a "To:" 
! 	      line...the value is NULL but it doesn't match the username 
! 	      either.  We don't want to display something ugly like 
! 	      "(message addressed to )" which will just clutter up the 
! 	      screen!).
! 
! 	      And you thought programming was EASY!!!!
! 	  **/
! 
! 	  /** one more friendly thing - output a line indicating what sort
! 	      of status the message has (e.g. Urgent etc).  Mostly added
! 	      for X.400 support, this is nonetheless generally useful to
! 	      include...
! 	  **/
! 
! 	  buffer[0] = '\0';
! 
! 	  /* we want to flag Urgent, Confidential, Private and Expired tags */
! 
! 	  if (current_header->status & PRIVATE)
! 	    strcpy(buffer, catgets(elm_msg_cat, ElmSet, ElmTaggedPrivate,
! 		"\n(** This message is tagged Private"));
! 	  else if (current_header->status & CONFIDENTIAL) 
! 	    strcpy(buffer, catgets(elm_msg_cat, ElmSet, ElmTaggedCompanyConfidential,
! 		"\n(** This message is tagged Company Confidential"));
! 
! 	  if (current_header->status & URGENT) {
! 	    if (buffer[0] == '\0')
! 	      strcpy(buffer, catgets(elm_msg_cat, ElmSet, ElmTaggedUrgent,
! 		"\n(** This message is tagged Urgent"));
! 	    else if (current_header->status & EXPIRED)
! 	      strcat(buffer, catgets(elm_msg_cat, ElmSet, ElmCommaUrgent, ", Urgent"));
! 	    else
! 	      strcat(buffer, catgets(elm_msg_cat, ElmSet, ElmAndUrgent, " and Urgent"));
! 	  }
! 
! 	  if (current_header->status & EXPIRED) {
! 	    if (buffer[0] == '\0')
! 	      strcpy(buffer, catgets(elm_msg_cat, ElmSet, ElmMessageHasExpired,
! 		"\n(** This message has Expired"));
! 	    else
! 	      strcat(buffer, catgets(elm_msg_cat, ElmSet, ElmAndHasExpired,
! 		", and has Expired"));
! 	  }
! 
! 	  if (buffer[0] != '\0') {
! 	    strcat(buffer, " **)\n");
! 	    if (builtin)
! 	      display_line(buffer, strlen(buffer));
! 	    else
! 	      fprintf(pipe_wr_fp, buffer);
! 	  }
! 
! 	  if (builtin)			/* this is for a one-line blank    */
! 	    display_line("\n",1);	/*   separator between the title   */
! 	  else				/*   stuff and the actual message  */
! 	    fprintf(pipe_wr_fp, "\n");	/*   we're trying to display       */
! 
! 	}
! 
! 	weed_header = filter;	/* allow us to change it after header */
! 
! 	while (lines > 0 && pipe_abort == FALSE) {
! 
! 	    if ((buf_len = mail_gets(buffer, VERY_LONG_STRING, mailfile)) == 0) {
! 
! 	      dprint(1, (debugfile,
! 		"Premature end of file! Lines left = %d msg = %s (show_msg)\n",
! 		lines, number));
! 
! 	      error(catgets(elm_msg_cat, ElmSet, ElmPrematureEndOfFile,
! 		"Premature end of file!"));
! 	      if (sleepmsg > 0)
! 		    sleep(sleepmsg);
! 	      break;
! 	    }
! 	    if (buf_len > 0)  {
! 	      if(buffer[buf_len - 1] == '\n') {
! 	        lines--;
! 	        lines_displayed++;
  		}
! 	      while(buf_len > 0 && (buffer[buf_len - 1] == '\n'
! 				    ||buffer[buf_len - 1] == '\r'))
! 		--buf_len;
! 	    }
! 
!   	    if (buf_len == 0) {
! 	      weed_header = 0;		/* past header! */
! 	      weeding_out = 0;
! 	    }
! 
! 	    if (form_letter && weed_header)
! 		/* skip it.  NEVER display random headers in forms! */;
! 	    else if (weed_header && matches_weedlist(buffer)) 
! 	      weeding_out = 1;	 /* aha!  We don't want to see this! */
! 	    else if (buffer[0] == '[') {
! 	      if (strncmp(buffer, START_ENCODE, strlen(START_ENCODE))==0)
! 	        crypted = ON;
! 	      else if (strncmp(buffer, END_ENCODE, strlen(END_ENCODE))==0)
! 	        crypted = OFF;
! 	      else if (crypted) {
!                 encode(buffer);
! 	        val = show_line(buffer, buf_len, builtin);
! 	      }
! 	      else
! 	        val = show_line(buffer, buf_len, builtin);
! 	    } 
! 	    else if (crypted) {
! 	      encode(buffer);
! 	      val = show_line(buffer, buf_len, builtin); 
! 	    }
! 	    else if (weeding_out) {
! 	      weeding_out = (whitespace(buffer[0]));	/* 'n' line weed */
! 	      if (! weeding_out) 	/* just turned on! */
! 	        val = show_line(buffer, buf_len, builtin);
! 	    } 
! 	    else if (form_letter && first_word(buffer,"***") && filter) {
! 	      strcpy(buffer,
! "\n------------------------------------------------------------------------------\n");
! 	      val = show_line(buffer, buf_len, builtin);	/* hide '***' */
! 	      form_letter_section++;
! 	    }
! 	    else if (form_letter_section == 1 || form_letter_section == 3)
! 	      /** skip this stuff - we can't deal with it... **/;
! 	    else
! 	      val = show_line(buffer, buf_len, builtin);
! 	
! 	    if (val != 0)	/* discontinue the display */
! 	      break;
  	}
- 
-         if (cursor_control) transmit_functions(ON);
- 
- 	if (!builtin) {
- 	  fclose(pipe_wr_fp);
- 	  while ((wait_ret = wait(&wait_stat)) != fork_ret
- 		  && wait_ret!= -1)
- 	    ;
- 	  /* turn raw on **after** child terminates in case child
- 	   * doesn't put us back to cooked mode after we return ourselves
- 	   * to raw.
- 	   */
- 	  Raw(ON);
- #ifdef	SIGTSTP
- 	  (void)signal(SIGTSTP,oldstop);
- 	  (void)signal(SIGCONT,oldcont);
- #endif
- #ifdef	SIGWINCH
- 	  (void)signal(SIGWINCH,oldwinch);
  #endif
! 	}
! 
! 	/* If we are to prompt for a user input command and we don't
! 	 * already have one */
! 	if ((prompt_after_pager || builtin) && val == 0) {
! 	  MoveCursor(LINES,0);
! 	  StartBold();
! 	  Write_to_screen(catgets(elm_msg_cat, ElmSet, ElmCommandIToReturn,
! 		" Command ('i' to return to index): "), 0);
! 	  EndBold();
! 	  fflush(stdout);
! 	  val = ReadCh();
! 	}
! 	
! 	if (memory_lock) EndMemlock();	/* turn it off!! */
! 
! 	/* 'q' means quit current operation and pop back up to previous level -
! 	 * in this case it therefore means return to index screen.
! 	 */
! 	return(val == 'i' || val == 'q' ? 0 : val);
! }
! 
! int
! show_line(buffer, buf_len, builtin)
! char *buffer;
! int  buf_len;
! int  builtin;
! {
! 	/** Hands the given line to the output pipe.  'builtin' is true if
! 	    we're using the builtin pager.
! 	    Return the character entered by the user to indicate
! 	    a command other than continuing with the display (only possible
! 	    with the builtin pager), otherwise 0. **/
! 
! 	strcpy(buffer + buf_len, "\n");
! 	++buf_len;
! #ifdef MMDF
! 	if (strncmp(buffer, MSG_SEPARATOR, buf_len) == 0)
! 	  return(0);	/* no reason to show the ending terminator */
! #endif /* MMDF */
! 	if (builtin) {
! 	  return(display_line(buffer, buf_len));
! 	}
! 	errno = 0;
! 	fprintf(pipe_wr_fp, "%s", buffer);
! 	if (errno != 0)
! 	  dprint(1, (debugfile, "\terror %s hit!\n", error_description(errno)));
! 	return(0);
  }
- 
--- 163,223 ----
  	  current_header->status_chgd = TRUE;
  	}
  
  #ifdef MIME
! 	/* May need recheck: (Because now defination is recursive) */
! 	if ((current_header->status & MIME_MESSAGE) && 
! 	    current_header->mime_rec.notplain)
! 	  attach_parse(current_header,mailfile);
! 
!         if (need_meta(current_header) && have_metamail()) {
! 		char fname[STRING], Cmd[SLEN], line[VERY_LONG_STRING];
! 		int code, err;
! 		long lines = current_header->lines;
! 		FILE *fpout;
! 
! 		if (fseek(mailfile, current_header->offset, 0) == -1) {
! 		    err = errno;
! 		    dprint(1, (debugfile,
! 		      "Error: seek %d bytes into file, errno %s (show_message)\n",
! 		      current_header->offset, error_description(err)));
! 		    error2(catgets(elm_msg_cat, ElmSet, ElmSeekFailedFile,
! 		      "ELM [seek] couldn't read %d bytes into file (%s)."),
! 		      current_header->offset, error_description(err));	
  		    return(0);
  		}
! 		sprintf(fname, "%semm.%d.%d", temp_dir, getpid(), getuid());
! 		if ((fpout = safeopen_rdwr(fname)) == NULL) {
! 		  err = errno;
! 		  dprint(1, (debugfile,
! 			     "Error: open of temporary file %s, errno %s (show_message)\n",
! 			     fname, error_description(err)));
! 		  error2(catgets(elm_msg_cat, ElmSet, ElmCantOpenAsOutputFile,
! 				 "Can't open \"%s\" as output file! (%s)."),
! 			 fname, error_description(err));
! 		  return(0);
  		}
! 		/* Let metamail decode it! 
! 		 * (Now CM_DECODE also decodes MIME and PGP) -KEH
! 		 */
! 		copy_message(mailfile,current_header,
! 			     "", fpout, 0);
! 		(void) fclose (fpout);
! 		sprintf(Cmd, "%s -p -z -m Elm %s", metamail_path, fname);
! 		Raw(OFF);
! 		ClearScreen();
! 		printf ("Executing metamail...\n");
! 		code = system_call(Cmd, SY_ENAB_SIGINT|SY_ENV_METAMAIL);
! 		Raw(ON | NO_TITE);	/* Raw on but don't switch screen */
! 		(void) unlink (fname);
! 		PutLine0(elm_LINES,0, catgets(elm_msg_cat, ElmSet, 
! 					      ElmPressAnyKeyIndex,
! 			     "Press any key to return to index."));
! 		(void) ReadCh(0);
! 		printf("\r\n");
! 		Raw(OFF | NO_TITE); /* Raw off so raw on takes effect */
! 		Raw(ON); /* Finally raw on and switch screen */
! 		return(0);
  	}
  #endif
!         return (metapager (mailfile, current_header, TRUE));
  }
Index: WORK/src/showmsg_c.c
*** elm2.4.25/src/showmsg_c.c	Fri Mar 11 23:25:27 1994
--- WORK/src/showmsg_c.c	Sun Aug  4 21:24:50 1996
***************
*** 59,64 ****
--- 59,65 ----
  	   s    = save this message to a maibox/folder 
  	   t    = tag this message
  	   u    = undelete message
+            v    = view attachments
  	   x    = Exit Elm NOW 
  
      all commands not explicitly listed here are beeped at.  Use i)ndex
***************
*** 70,82 ****
  
  #include "headers.h"
  #include "s_elm.h"
  
  int	screen_mangled = 0;
  char    msg_line[SLEN];
  static	char *put_help_prompt = NULL;
  #define store_msg(a)	(void)strcpy(msg_line,a)
! #define put_prompt()	PutLine0(LINES-3, 0, Prompt)
! #define put_help()	PutLine0(LINES-3, 45, put_help_prompt)
  #define POST_PROMPT_COL	strlen(Prompt)
  
  
--- 71,84 ----
  
  #include "headers.h"
  #include "s_elm.h"
+ #include "me.h"
  
  int	screen_mangled = 0;
  char    msg_line[SLEN];
  static	char *put_help_prompt = NULL;
  #define store_msg(a)	(void)strcpy(msg_line,a)
! #define put_prompt()	PutLine0(elm_LINES-3, 0, Prompt)
! #define put_help()	PutLine0(elm_LINES-3, 45, put_help_prompt)
  #define POST_PROMPT_COL	strlen(Prompt)
  
  
***************
*** 148,153 ****
--- 150,164 ----
  			 goto next_undel_msg;
  		       break;
  
+ #ifdef USE_PGP
+             case ctrl('E'):
+ 			put_cmd_name("Extract PGP public key", TRUE);
+ 			if (headers[current-1]->pgp & PGP_PUBLIC_KEY)
+ 				pgp_extract_public_key ();
+ 			else
+ 				store_msg("This message does not contain any keys!");
+ 			break;
+ #endif
  	    case 'f' : put_cmd_name(catgets(elm_msg_cat, ElmSet, ElmForwardMessage,
  				"Forward message"), TRUE);
  		       if(forward()) put_border();
***************
*** 159,168 ****
  		       break;
  
  	    case 'h' : screen_mangled = 0;
! 		       if (filter) { 
! 		         filter = 0; 
  		         intbuf = show_msg(current); 
! 		         filter = 1;
  			 return(intbuf);
  		       } else
  		         return(show_msg(current)); 
--- 170,179 ----
  		       break;
  
  	    case 'h' : screen_mangled = 0;
! 		       if (elm_filter) { 
! 		         elm_filter = 0; 
  		         intbuf = show_msg(current); 
! 		         elm_filter = 1;
  			 return(intbuf);
  		       } else
  		         return(show_msg(current)); 
***************
*** 170,182 ****
  	    case 'q' :
  	    case 'i' : (void) get_page(current);
  		       clear_error();		/* zero out pending msg   */
- 		       if (cursor_control)
- 			 transmit_functions(ON);
  		       screen_mangled = 0;
  		       return(0);		/* avoid <return> looping */
   
  next_undel_msg :	/* a target for resolve mode actions */
  
  	    case ' ' :
  	    case 'j' :
  	    case 'n' : screen_mangled = 0;
--- 181,192 ----
  	    case 'q' :
  	    case 'i' : (void) get_page(current);
  		       clear_error();		/* zero out pending msg   */
  		       screen_mangled = 0;
  		       return(0);		/* avoid <return> looping */
   
  next_undel_msg :	/* a target for resolve mode actions */
  
+ 	  case DOWN_MARK :
  	    case ' ' :
  	    case 'j' :
  	    case 'n' : screen_mangled = 0;
***************
*** 191,196 ****
--- 201,207 ----
  		       else return(0);
  
  prev_undel_msg:
+ 	  case UP_MARK:
  	    case 'k' : screen_mangled = 0;
  		       if((i=prev_message(current-1, TRUE)) != -1)
  			 return(show_msg(current = i+1));
***************
*** 203,211 ****
  
  	    case 'm' : put_cmd_name(catgets(elm_msg_cat, ElmSet, ElmMailMessage,
  				"Mail message"), TRUE);
! 		       if(send_msg("","","", TRUE, allow_forms, FALSE))
  			 put_border();
! 		       break;
  
  	    case 'p' : put_cmd_name(catgets(elm_msg_cat, ElmSet, ElmPrintMessage,
  				"Print message"), FALSE);
--- 214,222 ----
  
  	    case 'm' : put_cmd_name(catgets(elm_msg_cat, ElmSet, ElmMailMessage,
  				"Mail message"), TRUE);
! 	               if(send_msg("","","", MAIL_EDIT_MSG, allow_forms))
  			 put_border();
! 	               break;
  
  	    case 'p' : put_cmd_name(catgets(elm_msg_cat, ElmSet, ElmPrintMessage,
  				"Print message"), FALSE);
***************
*** 225,230 ****
--- 236,242 ----
  			 goto next_undel_msg;
  		       break;
  
+ 	    case 'T' :
  	    case 't' : istagged=tag_message(FALSE);	
  		       if(istagged)
  			 store_msg(catgets(elm_msg_cat, ElmSet, ElmMessageTagged,
***************
*** 232,237 ****
--- 244,251 ----
  		       else 
  			 store_msg(catgets(elm_msg_cat, ElmSet, ElmMessageUntagged,
  				"Message untagged."));
+ 	               if (command == 'T')
+ 			 goto next_undel_msg;
  		       break;
  
  	    case 'u' : undelete_msg(FALSE); /* undelete it, silently */
***************
*** 249,255 ****
  			 goto next_msg;
  		       }
  		       break;
! 
  	    case 'X' : put_cmd_name(catgets(elm_msg_cat, ElmSet, ElmQuickExit,
  				"Quick Exit"), TRUE);
  		       leave(0);
--- 263,291 ----
  			 goto next_msg;
  		       }
  		       break;
! #ifdef MIME
! 	    case 'v' :
! 	      if (headers) {         
! 		if (headers[current-1]->status & MIME_MESSAGE) {
! 		  mime_warnings(headers[current-1]);
! 
! 		  attach_parse (headers[current-1], mailfile);
! 		  if (headers[current-1]->mime_rec.parts)
! 		    (void) attach_menu (headers[current-1]->
! 					mime_rec.parts, TRUE);
! 		  else 
! 		    /* So we can save mail in decoded ... */
! 		    (void) attach_menu (&(headers[current-1]->
! 					  mime_rec),TRUE);
! 		  redraw++;
! 		}
! 		else
! 		  error ("This is not a MIME message!");
! 	      }
! 	      else
! 		error ("There are no messages!");
! 	      return(0);
! #endif
  	    case 'X' : put_cmd_name(catgets(elm_msg_cat, ElmSet, ElmQuickExit,
  				"Quick Exit"), TRUE);
  		       leave(0);
***************
*** 266,305 ****
  	    case EOF    : leave(0);
                            break;
  
-             case ESCAPE : if (cursor_control) {
-   
-                             key_offset = 1;
-   
-                             ch = ReadCh(); 
-   
-                             if (ch == ESCAPE)
-                              ch = ReadCh();
-   
-                             if ( ch == '[' || ch == 'O') 
-                             {
-                               ch = ReadCh();
-                               key_offset++;
-                             }
-   
-                             if (ch == up[key_offset])
- 			      goto prev_undel_msg;
-                             else if (ch == down[key_offset])
- 			      goto next_undel_msg;
-                             else {
- 			      screen_mangled = 0;
-                               return(0);
- 			    }
-                           }
-                           else          /* Eat 2 chars for escape codes */
-                           {
-                             ch = ReadCh();
-                             ch = ReadCh();
-                             putchar((char) 007);
-                             fflush(stdout);
- 			    screen_mangled = 0;
-                             return(0);
-                            }
-   
  	    default  : putchar((char) 007);	/* BEEP! */
  	  }
  
--- 302,307 ----
***************
*** 311,321 ****
  	    put_prompt();
  	    CleartoEOS();
  	    put_help();
! 	    Centerline(LINES, msg_line);
! 	    MoveCursor(LINES-3, POST_PROMPT_COL);
  	  } else {
  	    /* display bottom line prompt with last generated message */
! 	    MoveCursor(LINES, 0);
  	    CleartoEOS();
  	    StartBold();
  	    Write_to_screen(catgets(elm_msg_cat, ElmSet, ElmCommandLine,
--- 313,323 ----
  	    put_prompt();
  	    CleartoEOS();
  	    put_help();
! 	    Centerline(elm_LINES, msg_line);
! 	    MoveCursor(elm_LINES-3, POST_PROMPT_COL);
  	  } else {
  	    /* display bottom line prompt with last generated message */
! 	    MoveCursor(elm_LINES, 0);
  	    CleartoEOS();
  	    StartBold();
  	    Write_to_screen(catgets(elm_msg_cat, ElmSet, ElmCommandLine,
***************
*** 325,331 ****
  	  }
  	  *msg_line = '\0';	/* null last generated message */
  
! 	  command = ReadCh();	/* get next command from user */
  	}
  }
  
--- 327,333 ----
  	  }
  	  *msg_line = '\0';	/* null last generated message */
  
! 	  command = ReadCh('i'|READCH_CURSOR);   /* get next command from user */
  	}
  }
  
***************
*** 343,349 ****
  	  screen_mangled = TRUE;
  	}
  	if(screen_mangled) {
! 	  PutLine0(LINES-3, POST_PROMPT_COL, command);
  	  CleartoEOS();
  	}
  }
--- 345,351 ----
  	  screen_mangled = TRUE;
  	}
  	if(screen_mangled) {
! 	  PutLine0(elm_LINES-3, POST_PROMPT_COL, command);
  	  CleartoEOS();
  	}
  }
***************
*** 350,362 ****
  
  put_border()
  {
! 	 PutLine0(LINES-4, 0, 
  "--------------------------------------------------------------------------\n");
  }
  
  build_bottom()
  {
! 	 MoveCursor(LINES-4, 0);
  	 CleartoEOS();
  	 put_border();
  	 put_prompt();
--- 352,364 ----
  
  put_border()
  {
! 	 PutLine0(elm_LINES-4, 0, 
  "--------------------------------------------------------------------------\n");
  }
  
  build_bottom()
  {
! 	 MoveCursor(elm_LINES-4, 0);
  	 CleartoEOS();
  	 put_border();
  	 put_prompt();
Index: WORK/src/signals.c
*** elm2.4.25/src/signals.c	Thu Sep  1 22:42:41 1994
--- WORK/src/signals.c	Thu Jun 13 23:37:38 1996
***************
*** 107,113 ****
  SIGHAND_TYPE
  ill_signal(sig)
  {
! 	MoveCursor(LINES,0);
  	Raw(OFF);
  	dprint(1, (debugfile, "\n\n** Received SIGILL **\n\n\n\n"));
  	printf(catgets(elm_msg_cat, ElmSet, ElmIllegalInstructionSignal,
--- 107,113 ----
  SIGHAND_TYPE
  ill_signal(sig)
  {
! 	MoveCursor(elm_LINES,0);
  	Raw(OFF);
  	dprint(1, (debugfile, "\n\n** Received SIGILL **\n\n\n\n"));
  	printf(catgets(elm_msg_cat, ElmSet, ElmIllegalInstructionSignal,
***************
*** 118,124 ****
  SIGHAND_TYPE
  fpe_signal(sig)  
  {
! 	MoveCursor(LINES,0);
  	Raw(OFF);
  	dprint(1, (debugfile, "\n\n** Received SIGFPE **\n\n\n\n"));
  	printf(catgets(elm_msg_cat, ElmSet, ElmFloatingPointSignal,
--- 118,124 ----
  SIGHAND_TYPE
  fpe_signal(sig)  
  {
! 	MoveCursor(elm_LINES,0);
  	Raw(OFF);
  	dprint(1, (debugfile, "\n\n** Received SIGFPE **\n\n\n\n"));
  	printf(catgets(elm_msg_cat, ElmSet, ElmFloatingPointSignal,
***************
*** 130,136 ****
  SIGHAND_TYPE
  bus_signal(sig)
  {
! 	MoveCursor(LINES,0);
  	Raw(OFF);
  	dprint(1, (debugfile, "\n\n** Received SIGBUS **\n\n\n\n"));
  	printf(catgets(elm_msg_cat, ElmSet, ElmBusErrorSignal,
--- 130,136 ----
  SIGHAND_TYPE
  bus_signal(sig)
  {
! 	MoveCursor(elm_LINES,0);
  	Raw(OFF);
  	dprint(1, (debugfile, "\n\n** Received SIGBUS **\n\n\n\n"));
  	printf(catgets(elm_msg_cat, ElmSet, ElmBusErrorSignal,
***************
*** 142,148 ****
  SIGHAND_TYPE
  segv_signal(sig)
  {
! 	MoveCursor(LINES,0);
  	Raw(OFF);
  	dprint(1, (debugfile,"\n\n** Received SIGSEGV **\n\n\n\n"));
  	printf(catgets(elm_msg_cat, ElmSet, ElmSegmentViolationSignal,
--- 142,148 ----
  SIGHAND_TYPE
  segv_signal(sig)
  {
! 	MoveCursor(elm_LINES,0);
  	Raw(OFF);
  	dprint(1, (debugfile,"\n\n** Received SIGSEGV **\n\n\n\n"));
  	printf(catgets(elm_msg_cat, ElmSet, ElmSegmentViolationSignal,
***************
*** 186,191 ****
--- 186,194 ----
  	/* This is called when the user presses a ^Z to stop the
  	   process within BSD 
  	*/
+ 
+ 	redraw_screen = 1;
+ 
  #ifdef	SIGTSTP
  	signal(SIGTSTP, SIG_DFL);
  #endif
***************
*** 196,210 ****
  	printf(catgets(elm_msg_cat, ElmSet, ElmStoppedUseFGToReturn,
  		"\n\nStopped.  Use \"fg\" to return to ELM\n\n"));
  
! 	kill(0, SIGSTOP);
  }
  
  SIGHAND_TYPE
  sig_return_from_user_stop(sig)
! {
  	/** this is called when returning from a ^Z stop **/
  	dprint(1, (debugfile,"\n\n** Received SIGCONT **\n\n\n\n", sig));
  
  	signal(SIGCONT, sig_return_from_user_stop);
  	signal(SIGTSTP, sig_user_stop);
  
--- 199,215 ----
  	printf(catgets(elm_msg_cat, ElmSet, ElmStoppedUseFGToReturn,
  		"\n\nStopped.  Use \"fg\" to return to ELM\n\n"));
  
! 	kill(getpid(), SIGSTOP);
  }
  
  SIGHAND_TYPE
  sig_return_from_user_stop(sig)
! {  
  	/** this is called when returning from a ^Z stop **/
  	dprint(1, (debugfile,"\n\n** Received SIGCONT **\n\n\n\n", sig));
  
+ 	redraw_screen = 1;
+ 
  	signal(SIGCONT, sig_return_from_user_stop);
  	signal(SIGTSTP, sig_user_stop);
  
***************
*** 230,235 ****
--- 235,242 ----
  winch_signal(sig)
  {
  	resize_screen = 1;
+ 	redraw_screen = 1;
+ 
  	signal(SIGWINCH, winch_signal);
  
  	if (InGetPrompt)
***************
*** 245,264 ****
  SIGHAND_TYPE
  usr1_signal(sig)
  {
! 	dprint(1, (debugfile, "\n\n** Received SIGUSR1 **\n\n\n\n"));
! 	question_me = FALSE;
! 	while ( leave_mbox(TRUE, FALSE, TRUE) == -1)
! 		newmbox(cur_folder, TRUE);
  
! 	leave(0);
  }
  
  SIGHAND_TYPE
  usr2_signal(sig)
  {
! 	dprint(1, (debugfile, "\n\n** Received SIGUSR2 **\n\n\n\n"));
! 	while ( leave_mbox(FALSE, TRUE, FALSE) == -1)
! 		newmbox(cur_folder, TRUE);
  
! 	leave(0);
  }
--- 252,287 ----
  SIGHAND_TYPE
  usr1_signal(sig)
  {
!   int result;
! 
!   dprint(1, (debugfile, "\n\n** Received SIGUSR1 **\n\n\n\n"));
!   if (!InGetPrompt) {
!     dprint(1, (debugfile, "-- Not in prompt -- can't leave folder\n"));
!     return;
!   }
! 
!   question_me = FALSE;
!   while ((result = leave_mbox(TRUE, FALSE, TRUE)) == -1)
!     newmbox(cur_folder, TRUE);
  
!   if (result >= 0) 
!     leave(0);
  }
  
  SIGHAND_TYPE
  usr2_signal(sig)
  {
!   int result;
!   
!   dprint(1, (debugfile, "\n\n** Received SIGUSR2 **\n\n\n\n"));
!   if (!InGetPrompt) {
!     dprint(1, (debugfile, "-- Not in prompt -- can't leave folder\n"));
!     return;
!   }
! 
!   while ((result = leave_mbox(FALSE, TRUE, FALSE)) == -1)
!     newmbox(cur_folder, TRUE);
  
!   if (result >= 0)
!     leave(0);
  }
Index: WORK/src/state.c
*** /tmp/null.14101	Tue Aug 20 22:05:34 1996
--- WORK/src/state.c	Tue Aug  6 20:37:19 1996
***************
*** 0 ****
--- 1,633 ----
+ #include "headers.h"
+ #include "me.h"
+ 
+ PUBLIC int NULL_filter(c,st)
+      int c;          /* unsigned char assumed */
+      struct out_state * st;
+ {
+   st++;
+   return c;
+ }
+ 
+ static void state_panic P_((char *,int,char *, char *)); /* Prototype */
+ static void state_panic(f,ln,pr,ms) 
+      char * f;
+      int ln;
+      char *pr;
+      char *ms;
+ {
+   int do_cursor = RawState();
+ 
+   dprint(1,(debugfile,"\nSTATE PANIC in %s:%d:%s\n",f,ln,pr));
+   dprint(1,(debugfile,">>%s\n",ms));
+ 
+   /* softkeys_off(); */
+ 
+   if (do_cursor) {
+     error1("STATE PANIC: %s",ms);
+     sleep(1);
+   }
+ 
+   if (do_cursor) {
+     MoveCursor(elm_LINES, 0);
+     Raw(OFF);
+   }
+ 
+   fprintf(stderr,"\nSTATE PANIC in %s:%d:%s\n",f,ln,pr);
+   fprintf(stderr,">>%s\n",ms);
+ 
+ #if DEBUG
+   if (debug > 10) {
+     fprintf(stderr,"ABORTING...\n");
+     fflush(stderr);
+     abort();
+   }
+ #endif
+   emergency_exit();
+ }
+ 
+ static void init_si_file P_((in_state_t *)); /* Prototype */
+ static void init_si_file(s)
+      in_state_t *s;
+ {
+   s->magic  = STATE_in_file;
+   s->u.file.fpin = NULL;
+ }
+ 
+ static void init_si_string P_((in_state_t *)); /* Prototype */
+ static void init_si_string(s)
+      in_state_t *s;
+ {
+   s->magic  = STATE_in_string;
+   s->u.string.inbuf = NULL;
+   s->u.string.inreadp = NULL;
+ }
+ 
+ PUBLIC void in_state_clear (s,m)
+      in_state_t *s;
+      int m;
+ {
+   s->magic = 0;  /* Not initilized yet */
+ 
+   switch(m) {
+   case STATE_in_file:   init_si_file(s);   break;
+   case STATE_in_string: init_si_string(s); break;
+   default:
+     state_panic(__FILE__,__LINE__,"in_state_clear","Bad magic number");
+   }
+ }
+ 
+ static void dest_si_file P_((in_state_t *)); /* Prototype */
+ static void dest_si_file(s)
+      in_state_t *s;
+ {
+   if (s->magic  != STATE_in_file)
+     state_panic(__FILE__,__LINE__,"dest_si_file","Bad magic number");
+   s->u.file.fpin = NULL;
+ }
+ 
+ static void dest_si_string P_((in_state_t *)); /* Prototype */
+ static void dest_si_string(s)
+      in_state_t *s;
+ {
+   if (s->magic  != STATE_in_string)
+     state_panic(__FILE__,__LINE__,"dest_si_string","Bad magic number");
+ 
+   if (s->u.string.inbuf)
+     free(s->u.string.inbuf);
+   
+   s->u.string.inbuf = NULL;
+   s->u.string.inreadp = NULL;
+ }
+ 
+ 
+ PUBLIC void in_state_destroy (s)
+      in_state_t *s;
+ {
+   switch(s->magic) {
+   case STATE_in_file:   dest_si_file(s);   break;
+   case STATE_in_string: dest_si_string(s); break;
+   default:
+     state_panic(__FILE__,__LINE__,"in_state_destroy","Bad magic number");
+   }
+   s->magic = 0; /* State destroyed */
+ }
+ 
+ PUBLIC void set_in_state_buffer (c, s)
+      char *c;
+      in_state_t *s;
+ {
+   if (s->magic  != STATE_in_string)
+     state_panic(__FILE__,__LINE__,"set_in_state_buffer","Bad magic number");
+   
+   if (s->u.string.inbuf)
+     state_panic(__FILE__,__LINE__,"set_in_state_buffer","Already called");
+   
+   s->u.string.inreadp = s->u.string.inbuf = strmcpy (s->u.string.inbuf, c);
+ }
+ 
+ PUBLIC void set_in_state_file (F, s)
+      FILE *F;
+      in_state_t *s;
+ {
+   if (s->magic  != STATE_in_file)
+     state_panic(__FILE__,__LINE__,"set_in_state_file","Bad magic number");
+ 
+   if (s->u.file.fpin)
+     state_panic(__FILE__,__LINE__,"set_in_state_file","Already called");
+ 
+   s->u.file.fpin = F;
+ }
+ 
+ PUBLIC int in_state_seekable (s)
+      in_state_t *s;
+ {
+   switch(s->magic) {
+   case STATE_in_file:   return 1;   
+   case STATE_in_string: return 0; 
+   default:
+     state_panic(__FILE__,__LINE__,"in_state_seekable","Bad magic number");
+   }
+ 
+   return 0;
+ }
+ 
+ PUBLIC int in_state_fseek (s,pos)
+      in_state_t *s;
+      long pos;
+ {
+   if (s->magic  != STATE_in_file)
+     state_panic(__FILE__,__LINE__,"in_state_fseek","Bad magic number");
+ 
+   if (s->u.file.fpin == NULL)
+     state_panic(__FILE__,__LINE__,"in_state_fseek","NULL file pointer");
+ 
+   return fseek(s->u.file.fpin,pos,SEEK_SET);
+ }
+ 
+ PUBLIC long in_state_ftell (s)
+      in_state_t *s;
+ {
+   if (s->magic  != STATE_in_file)
+     state_panic(__FILE__,__LINE__,"in_state_ftell","Bad magic number");
+   
+   if (s->u.file.fpin == NULL)
+     state_panic(__FILE__,__LINE__,"in_state_ftell","NULL file pointer");
+ 
+   return ftell(s->u.file.fpin);
+ }
+ 
+ PUBLIC FILE * in_state_FILE (s) 
+      in_state_t *s;
+ {
+   if (s->magic  != STATE_in_file)
+     state_panic(__FILE__,__LINE__,"in_state_FILE","Bad magic number");
+ 
+   if (s->u.file.fpin == NULL)
+     state_panic(__FILE__,__LINE__,"in_state_FILE","NULL file pointer");
+   
+   return s->u.file.fpin;
+ }
+ 
+ static int getc_si_file P_((in_state_t *)); /* Prototype */
+ static int getc_si_file(s)
+      in_state_t *s;
+ {
+   if (s->magic  != STATE_in_file)
+     state_panic(__FILE__,__LINE__,"getc_si_file","Bad magic number");
+   if (s->u.file.fpin == NULL)
+     state_panic(__FILE__,__LINE__,"getc_si_file","NULL filepointer");
+ 
+   return fgetc (s->u.file.fpin);
+ }
+ 
+ static int getc_si_string P_((in_state_t *)); /* Prototype */
+ static int getc_si_string(s)
+      in_state_t *s;
+ {
+   if (s->magic  != STATE_in_string)
+     state_panic(__FILE__,__LINE__,"getc_si_string","Bad magic number");
+ 
+   if (s->u.string.inbuf) {
+     unsigned char ret;
+ 
+     if (! *s->u.string.inreadp) {
+       /* No more data left in the buffer, so clean up... */
+       s->u.string.inreadp = NULL;
+       free (s->u.string.inbuf);
+       s->u.string.inbuf = NULL;
+       return EOF;
+     }
+     
+     if (*s->u.string.inreadp)
+       ret = (unsigned char) *s->u.string.inreadp++;
+     return ret;
+   }
+   
+   dprint(5, (debugfile, "getc_si_string: inbuf==NULL\n"));
+   return EOF;
+ }
+ 
+ PUBLIC int state_getc (s)
+      in_state_t *s;
+ {
+   switch(s->magic) {
+   case STATE_in_file:   return getc_si_file(s);   
+   case STATE_in_string: return getc_si_string(s); 
+   default:
+     state_panic(__FILE__,__LINE__,"state_getc","Bad magic number");
+   }
+ 
+   return EOF;
+ }
+ 
+ static int ungetc_si_file P_((int,in_state_t *)); /* Prototype */
+ static int ungetc_si_file (c,s)
+      int c;
+      in_state_t *s;
+ {
+   if (s->magic  != STATE_in_file)
+     state_panic(__FILE__,__LINE__,"ungetc_si_file","Bad magic number");
+   if (s->u.file.fpin == NULL)
+     state_panic(__FILE__,__LINE__,"umgetc_si_file","NULL filepointer");
+ 
+   return ungetc(c,s->u.file.fpin);
+ }
+ 
+ static int ungetc_si_string P_((int,in_state_t *)); /* Prototype */
+ static int ungetc_si_string (c,s)
+      int c;
+      in_state_t *s;
+ {
+   if (s->magic  != STATE_in_string)
+     state_panic(__FILE__,__LINE__,"ungetc_si_string","Bad magic number");
+ 
+   if (s->u.string.inbuf) {
+     if (s->u.string.inreadp > s->u.string.inbuf) {
+       return *(--(s->u.string.inreadp));
+     } else {
+       dprint(5, (debugfile, "ungetc_si_string: In beginning of buffer.\n"));
+       return EOF;
+     }
+   } else {
+     dprint(5, (debugfile, "ungetc_si_string: inbuf==NULL\n"));
+     return EOF;
+   }
+ }
+ 
+ PUBLIC int state_ungetc (c,s)
+      int c;
+      in_state_t *s;
+ {
+   switch(s->magic) {
+   case STATE_in_file:   return ungetc_si_file(c,s);   
+   case STATE_in_string: return ungetc_si_string(c,s); 
+   default:
+     state_panic(__FILE__,__LINE__,"state_ungetc","Bad magic number");
+   }
+   return EOF;
+ }
+ 
+ 
+ static char *gets_si_file P_((char *, int, in_state_t *));
+ static char *gets_si_file (dest, length, s)
+      char *dest;
+      int length;
+      in_state_t *s;
+ {
+   if (s->magic  != STATE_in_file)
+     state_panic(__FILE__,__LINE__,"gets_si_file","Bad magic number");
+   if (s->u.file.fpin == NULL)
+     state_panic(__FILE__,__LINE__,"gets_si_file","NULL filepointer");
+   
+   return (fgets (dest, length, s->u.file.fpin));
+ }
+ 
+ static int getl_si_file P_((char *, int, in_state_t *));
+ static int getl_si_file (dest, length, s)
+      char *dest;
+      int length;
+      in_state_t *s;
+ {
+   if (s->magic  != STATE_in_file)
+     state_panic(__FILE__,__LINE__,"getl_si_file","Bad magic number");
+   if (s->u.file.fpin == NULL)
+     state_panic(__FILE__,__LINE__,"getl_si_file","NULL filepointer");
+   
+   return (mail_gets (dest, length, s->u.file.fpin));
+ }
+ 
+ 
+ static int getl_si_string P_((char *, int, in_state_t *));
+ static int getl_si_string (dest, length, s)
+      char *dest;
+      int length;
+      in_state_t *s;
+ {
+   int i = 0, ch;
+   
+   if (s->magic  != STATE_in_string)
+     state_panic(__FILE__,__LINE__,"getl_si_string","Bad magic number");
+ 
+   while (length > 1) {
+     ch = getc_si_string (s);
+     if (ch == EOF)
+       break;
+     else if (ch == '\n') {
+       dest[i++] = '\n';
+       break;
+     }
+     else
+       dest[i++] = ch;
+     length--;
+   }
+   dest[i] = '\0';
+   return i;
+ }
+   
+ static char *gets_si_string P_((char *, int, in_state_t *));
+ static char *gets_si_string (dest, length, s)
+      char *dest;
+      int length;
+      in_state_t *s;
+ {
+   int len;
+ 
+   if (s->magic  != STATE_in_string)
+     state_panic(__FILE__,__LINE__,"getl_si_string","Bad magic number");
+ 
+   len = getl_si_string (dest, length, s);
+   if (len > 0)
+     return dest;
+   else
+     return NULL;
+ }
+ 
+ PUBLIC char *state_gets (dest, length, s)
+      char *dest;
+      int length;
+      in_state_t *s;
+ {
+   switch(s->magic) {
+   case STATE_in_file:   return gets_si_file(dest,length,s);   
+   case STATE_in_string: return gets_si_string(dest,length,s); 
+   default:
+     state_panic(__FILE__,__LINE__,"state_gets","Bad magic number");
+   }
+   return NULL;
+ }
+ 
+ PUBLIC int state_getl (dest, length, s)
+      char *dest;
+      int length;
+      in_state_t *s;
+ {
+   switch(s->magic) {
+   case STATE_in_file:   return getl_si_file(dest,length,s);   
+   case STATE_in_string: return getl_si_string(dest,length,s); 
+   default:
+     state_panic(__FILE__,__LINE__,"state_getl","Bad magic number");
+   }
+   return 0;
+ }
+ 
+ 
+ static void init_so_file P_((out_state_t *)); /* Prototype */
+ static void init_so_file(s)
+      out_state_t *s;
+ {
+   s->magic   = STATE_out_file;
+   s->u.file.fpout = NULL;
+ }
+ 
+ static void init_so_string P_((out_state_t *)); /* Prototype */
+ static void init_so_string(s)
+      out_state_t *s;
+ {
+   s->magic        = STATE_out_string;
+   s->u.string.outbuf     = NULL;
+   s->u.string.outwritep  = NULL;
+   s->u.string.outbufsize = 0;
+ }
+ 
+ PUBLIC void out_state_clear (s,m)
+      out_state_t *s;
+      int m;
+ {
+   s->magic = 0;  /* Not initilized yet */
+ 
+   s->displaying = 0;
+   s->prefix     = NULL;
+   s->filter     = NULL_filter;
+ 
+   switch(m) {
+   case STATE_out_file:   init_so_file(s);   break;
+   case STATE_out_string: init_so_string(s); break;
+   default:
+     state_panic(__FILE__,__LINE__,"out_state_clear","Bad magic number");
+   }
+ }
+ 
+ static void dest_so_file P_((out_state_t *)); /* Prototype */
+ static void dest_so_file(s)
+      out_state_t *s;
+ {
+   if (s->magic   != STATE_out_file)
+     state_panic(__FILE__,__LINE__,"dest_so_file","Bad magic number");
+   s->u.file.fpout = NULL;
+ }
+ 
+ static void dest_so_string P_((out_state_t *)); /* Prototype */
+ static void dest_so_string(s)
+      out_state_t *s;
+ {
+   if (s->magic        != STATE_out_string)
+     state_panic(__FILE__,__LINE__,"dest_so_string","Bad magic number");
+ 
+   s->u.string.outbuf     = NULL;
+   s->u.string.outwritep  = NULL;
+   s->u.string.outbufsize = 0;
+ }
+ 
+ PUBLIC void out_state_destroy (s)
+      out_state_t *s;
+ {
+ 
+   switch(s->magic) {
+   case STATE_out_file:   dest_so_file(s);   break;
+   case STATE_out_string: dest_so_string(s); break;
+   default:
+     state_panic(__FILE__,__LINE__,"out_state_destroy","Bad magic number");
+   }
+ 
+   s->displaying = 0;
+   s->prefix     = NULL;
+   s->filter     = NULL_filter;
+   s->magic      = 0; /* No longer initialized */
+ }
+ 
+ PUBLIC void set_out_state_buffer (buffer,size,s)
+      char * buffer;
+      int size;
+      out_state_t *s;
+ {
+   if (s->magic        != STATE_out_string)
+     state_panic(__FILE__,__LINE__,"set_out_state_buffer","Bad magic number");
+ 
+   if (s->u.string.outbuf     != NULL)
+     state_panic(__FILE__,__LINE__,"set_out_state_buffer","Already called");
+ 
+   s->u.string.outbuf     = buffer;
+   s->u.string.outwritep  = buffer;
+   s->u.string.outbufsize = size;
+ }
+ 
+ PUBLIC void out_state_ref_buffer (s,p,len)
+      out_state_t *s;
+      char **p;
+      int *len;
+ {
+   if (s->magic        != STATE_out_string)
+     state_panic(__FILE__,__LINE__,"out_state_ref_buffer","Bad magic number");
+ 
+   if (s->u.string.outbuf     == NULL)
+     state_panic(__FILE__,__LINE__,
+ 		"out_state_ref_buffer","NULL buffer pointer");
+ 
+   *p   = s->u.string.outbuf;
+   *len = s->u.string.outwritep - s->u.string.outbuf;
+ }
+ 
+ 
+ PUBLIC void set_out_state_file (file,s)
+      FILE * file;
+      out_state_t *s;
+ {
+   if (s->magic   != STATE_out_file)
+     state_panic(__FILE__,__LINE__,"set_out_state_file","Bad magic number");
+   if (s->u.file.fpout != NULL)
+     state_panic(__FILE__,__LINE__,"set_out_state_file","Already called");
+   s->u.file.fpout = file;
+ }
+ 
+ static int putc_so_file P_((out_state_t *, int)); /* Prototype */
+ static int putc_so_file(s,ch)
+      out_state_t *s;
+      int ch;
+ {
+   int res;
+   if (s->magic   != STATE_out_file)
+     state_panic(__FILE__,__LINE__,"putc_so_file","Bad magic number");
+   if (s->u.file.fpout == NULL)
+     state_panic(__FILE__,__LINE__,"putc_so_file","NULL file pointer");
+ 
+   res = s-> filter(ch,s);
+ 
+   if (res < 0) /* Destroy char */
+     return EOF;
+ 
+   return (fputc (res, s->u.file.fpout));
+ }
+ 
+ static int putc_so_string P_((out_state_t *, int)); /* Prototype */
+ static int putc_so_string(s,ch)
+      out_state_t *s;
+      int ch;
+ {
+   int res;
+   if (s->magic   != STATE_out_string)
+     state_panic(__FILE__,__LINE__,"putc_so_string","Bad magic number");
+   if (s->u.string.outbuf == NULL)
+     state_panic(__FILE__,__LINE__,"putc_so_string","NULL buffer pointer");
+ 
+   res = s-> filter(ch,s);
+ 
+   if (res < 0) /* Destroy char */
+     return EOF;
+ 
+   if (s->u.string.outbuf - s->u.string.outbuf < s->u.string.outbufsize-1) {
+     *s->u.string.outwritep++ = res;
+     *s->u.string.outwritep = '\0';
+     return res;
+   }
+   else
+     return EOF;
+ }
+ 
+ PUBLIC int state_putc (ch, s)
+      int ch;                        /* unsigned char assumed */
+      out_state_t *s;
+ {
+   switch(s->magic) {
+   case STATE_out_file:   return putc_so_file(s,ch);   break;
+   case STATE_out_string: return putc_so_string(s,ch); break;
+   default: state_panic(__FILE__,__LINE__,"state_putc","Bad magic number");
+   }
+   return EOF;
+ }
+ 
+ static int put_so_file P_((out_state_t *, char *,int)); /* Prototype */
+ static int put_so_file(s,string,len)
+      out_state_t *s;
+      char *string;
+      int len;
+ {
+   if (s->magic   != STATE_out_file)
+     state_panic(__FILE__,__LINE__,"put_so_file","Bad magic number");
+   if (s->u.file.fpout == NULL)
+     state_panic(__FILE__,__LINE__,"put_so_file","NULL file pointer");
+ 
+   if (s->filter == NULL_filter)
+     return fwrite (string, 1, len, s->u.file.fpout);
+   else {
+     int count;
+     
+     for (count = 0; count < len; count++) {
+       if (putc_so_file (s,(unsigned char) string[count]) == EOF)
+ 	return (count > 0 ? count : EOF);
+     }
+     return count;
+   }
+ }
+ 
+ static int put_so_string P_((out_state_t *, char *,int)); /* Prototype */
+ static int put_so_string(s,string,len)
+      out_state_t *s;
+      char *string;
+      int len;
+ {
+   int count;
+ 
+   if (s->magic   != STATE_out_string)
+     state_panic(__FILE__,__LINE__,"put_so_string","Bad magic number");
+   if (s->u.string.outbuf == NULL)
+     state_panic(__FILE__,__LINE__,"put_so_string","NULL buffer pointer");
+     
+   for (count = 0; count < len; count++) {
+     if (putc_so_string (s,(unsigned char) string[count]) == EOF)
+       return (count > 0 ? count : EOF);
+   }
+   return count;
+ }
+ 
+ PUBLIC int state_put (string, len, s)
+      char *string;
+      int len;
+      out_state_t *s;
+ {
+   switch(s->magic) {
+   case STATE_out_file:   return put_so_file(s,string,len);   break;
+   case STATE_out_string: return put_so_string(s,string,len); break;
+   default:  state_panic(__FILE__,__LINE__,"state_put","Bad magic number");
+   }
+   return EOF;
+ }
+ 
+ PUBLIC int state_puts (string, state)
+      char *string;
+      out_state_t *state;
+ {
+   return state_put(string,strlen(string),state);
+ }
+ 
+ 
Index: WORK/src/strings.c
*** elm2.4.25/src/strings.c	Tue Aug  3 22:29:23 1993
--- WORK/src/strings.c	Fri Jun 14 11:00:59 1996
***************
*** 291,300 ****
  
  	length = strlen(string);
  
! 	if (length > COLUMNS)
  	  col = 0;
  	else
! 	  col = (COLUMNS - length) / 2;
  
  	PutLine0(line, col, string);
  }
--- 291,300 ----
  
  	length = strlen(string);
  
! 	if (length > elm_COLUMNS)
  	  col = 0;
  	else
! 	  col = (elm_COLUMNS - length) / 2;
  
  	PutLine0(line, col, string);
  }
Index: WORK/src/syscall.c
*** elm2.4.25/src/syscall.c	Tue Aug 30 18:09:43 1994
--- WORK/src/syscall.c	Sun Aug  4 21:32:10 1996
***************
*** 65,70 ****
--- 65,71 ----
  
  #include "headers.h"
  #include "s_elm.h"
+ #include "me.h"
  
  #include <errno.h>
  
***************
*** 88,140 ****
  	**/
  
  	char command[SLEN];
! 	int  old_raw, helpful, ret;
  
  	helpful = (user_level == 0);
  
  	if (helpful)
! 	  PutLine0(LINES-3, COLUMNS-40, catgets(elm_msg_cat, ElmSet, ElmUseShellName,
! 		"(Use the shell name for a shell.)"));
! 	PutLine0(LINES-2, 0, catgets(elm_msg_cat, ElmSet, ElmShellCommand,
  		"Shell command: "));
  	CleartoEOS();
  	command[0] = '\0';
! 	(void) optionally_enter(command, LINES-2, 15, FALSE, FALSE);
! 	if (command[0] == 0) {
  	  if (helpful)
! 	    MoveCursor(LINES-3,COLUMNS-40);
  	  else
! 	    MoveCursor(LINES-2,0);
  	  CleartoEOS();
! 	  return 0;
  	}
  
! 	MoveCursor(LINES,0);
  	CleartoEOLN();
  
  	if ((old_raw = RawState()) == ON)
  	  Raw(OFF);
! 	softkeys_off();
! 	if (cursor_control)
! 	  transmit_functions(OFF);
  
  	umask(original_umask);	/* restore original umask so users new files are ok */
  	ret = system_call(command, SY_USER_SHELL|SY_ENAB_SIGINT|SY_DUMPSTATE);
  	umask(077);		/* now put it back to private for mail files */
  
  	SetXYLocation(0, 40);	/* a location not near the next request, so an absolute is used */
! 	PutLine0(LINES, 0, catgets(elm_msg_cat, ElmSet, ElmPressAnyKeyToReturn,
  		"\n\nPress any key to return to ELM: "));
  	Raw(ON | NO_TITE);
! 	(void) getchar();
  	printf("\r\n");
  	Raw(OFF | NO_TITE); /* Done even if old_raw == ON, to get ti/te right */
  	if (old_raw == ON)
  	  Raw(ON);
  
! 	softkeys_on();
! 	if (cursor_control)
! 	  transmit_functions(ON);
  
  	if (ret)
  	  error1(catgets(elm_msg_cat, ElmSet, ElmReturnCodeWas,
--- 89,155 ----
  	**/
  
  	char command[SLEN];
! 	int redraw = FALSE;
! 	int  old_raw, helpful, ret, status;
  
  	helpful = (user_level == 0);
  
  	if (helpful)
! 	  PutLine0(elm_LINES-3, elm_COLUMNS-40, 
! 		   catgets(elm_msg_cat, ElmSet, 
! 			   ElmUseShellName,
! 			   "(Use the shell name for a shell.)"));
! 	PutLine0(elm_LINES-2, 0, catgets(elm_msg_cat, ElmSet, ElmShellCommand,
  		"Shell command: "));
  	CleartoEOS();
  	command[0] = '\0';
! 	status = optionally_enter(command, elm_LINES-2, 15, OE_REDRAW_MARK);
! 
! 	while (REDRAW_MARK == status) {
! 	  redraw = TRUE;
! 	  PutLine0(elm_LINES-2, 0, 
! 		   catgets(elm_msg_cat, ElmSet, ElmShellCommand,
! 			   "Shell command: "));
! 	  status = optionally_enter(command, elm_LINES-2, 15, 
! 				    OE_REDRAW_MARK|OE_APPEND_CURRENT);
! 
! 	}
! 	if (0 != status && command[0] == 0) {
  	  if (helpful)
! 	    MoveCursor(elm_LINES-3,elm_COLUMNS-40);
  	  else
! 	    MoveCursor(elm_LINES-2,0);
  	  CleartoEOS();
! 	  return redraw;
  	}
  
! 	MoveCursor(elm_LINES,0);
  	CleartoEOLN();
  
  	if ((old_raw = RawState()) == ON)
  	  Raw(OFF);
! 	/* softkeys_off(); */
  
  	umask(original_umask);	/* restore original umask so users new files are ok */
  	ret = system_call(command, SY_USER_SHELL|SY_ENAB_SIGINT|SY_DUMPSTATE);
  	umask(077);		/* now put it back to private for mail files */
  
+ redraw2:
  	SetXYLocation(0, 40);	/* a location not near the next request, so an absolute is used */
! 	PutLine0(elm_LINES, 0, catgets(elm_msg_cat, ElmSet, 
! 				       ElmPressAnyKeyToReturn,
  		"\n\nPress any key to return to ELM: "));
  	Raw(ON | NO_TITE);
! 	if (ReadCh(REDRAW_MARK) == REDRAW_MARK) {
! 	  Raw(OFF | NO_TITE);
! 	  goto redraw2;
! 	}
  	printf("\r\n");
  	Raw(OFF | NO_TITE); /* Done even if old_raw == ON, to get ti/te right */
  	if (old_raw == ON)
  	  Raw(ON);
  
! 	/* softkeys_on(); */
  
  	if (ret)
  	  error1(catgets(elm_msg_cat, ElmSet, ElmReturnCodeWas,
***************
*** 145,150 ****
--- 160,205 ----
  
  #endif /* ALLOW_SUBSHELL */
  
+ static int set_child_signals P_((int));      /* Prototype */
+ 
+ static int set_child_signals(options)
+      int options;
+ {
+   /*
+    * Program to exec may or may not be able to handle
+    * interrupt, quit, hangup and stop signals.
+    */
+   if (options&SY_ENAB_SIGINT)
+     options |= SY_ENAB_SIGHUP;
+   (void) signal(SIGHUP,  (options&SY_ENAB_SIGHUP) ? SIG_DFL : SIG_IGN);
+   (void) signal(SIGINT,  (options&SY_ENAB_SIGINT) ? SIG_DFL : SIG_IGN);
+   (void) signal(SIGQUIT, (options&SY_ENAB_SIGINT) ? SIG_DFL : SIG_IGN);
+ #ifdef SIGTSTP
+   (void) signal(SIGTSTP, (options&SY_ENAB_SIGHUP) ? SIG_DFL : SIG_IGN);
+   (void) signal(SIGCONT, (options&SY_ENAB_SIGHUP) ? SIG_DFL : SIG_IGN);
+ #endif
+ }
+ 
+ static int set_child_env P_((int));         /* Prototype */
+ 
+ static int set_child_env(options)
+      int options;
+ {
+ #ifdef MIME
+   /* Optionally override the MM_CHARSET environment variable. */
+   if (options&SY_ENV_METAMAIL) {
+     static char mm[] = "MM_CHARSET=";
+ 
+     /* \0 character is included in size returned by sizeof */
+     char *p = malloc(sizeof(mm) + strlen(display_charset));
+     if (p) {
+       sprintf(p, "%s%s", mm , display_charset );
+       putenv(p);
+     }
+   }
+ #endif
+ }
+ 
  int system_call(string, options)
  char *string;
  int options;
***************
*** 179,184 ****
--- 234,243 ----
  				program.  This is so that if "readmsg" is
  				invoked it can figure out what folder we are
  				in and what message(s) are selected.
+ 
+ 	    SY_ENV_METAMAIL	When set, put "MM_CHARSET=[display_charset]"
+ 	                        to environ.
+ 
  	**/
  
  	int pfd[2], stat, pid, w, iteration;
***************
*** 243,249 ****
  	    sleep(2);
  
  #ifdef VFORK
! 	  if (options&SY_ENV_SHELL)
  	    pid = fork();
  	  else
  	    pid = vfork();
--- 302,308 ----
  	    sleep(2);
  
  #ifdef VFORK
! 	  if (options&SY_ENV_SHELL || options&SY_ENV_METAMAIL)
  	    pid = fork();
  	  else
  	    pid = vfork();
***************
*** 266,284 ****
  	  setgid(groupid);
  	  setuid(userid);
  
! 	  /*
! 	   * Program to exec may or may not be able to handle
! 	   * interrupt, quit, hangup and stop signals.
! 	   */
! 	  if (options&SY_ENAB_SIGINT)
! 		options |= SY_ENAB_SIGHUP;
! 	  (void) signal(SIGHUP,  (options&SY_ENAB_SIGHUP) ? SIG_DFL : SIG_IGN);
! 	  (void) signal(SIGINT,  (options&SY_ENAB_SIGINT) ? SIG_DFL : SIG_IGN);
! 	  (void) signal(SIGQUIT, (options&SY_ENAB_SIGINT) ? SIG_DFL : SIG_IGN);
! #ifdef SIGTSTP
! 	  (void) signal(SIGTSTP, (options&SY_ENAB_SIGHUP) ? SIG_DFL : SIG_IGN);
! 	  (void) signal(SIGCONT, (options&SY_ENAB_SIGHUP) ? SIG_DFL : SIG_IGN);
! #endif
  
  	  /* Optionally override the SHELL environment variable. */
  	  if (options&SY_ENV_SHELL) {
--- 325,331 ----
  	  setgid(groupid);
  	  setuid(userid);
  
! 	  set_child_signals(options);
  
  	  /* Optionally override the SHELL environment variable. */
  	  if (options&SY_ENV_SHELL) {
***************
*** 290,295 ****
--- 337,344 ----
  	    }
  	  }
  
+ 	  set_child_env(options);
+ 
  	  /* Go for it. */
  	  if (string) execl(sh, argv_zero(sh), "-c", string, (char *) 0);
  	  else execl(sh, argv_zero(sh), (char *) 0);
***************
*** 345,350 ****
--- 394,693 ----
  	return(stat);
  }
  
+ 
+ #ifdef MAYBE_IN_NEXT_RELEASE
+ 
+ static void child_fail P_((int [2], int, char *)); /* Prototype */
+ 
+ static void child_fail(pfd, c1, name) 
+      int pfd[2];
+      int c1;
+      char * name;
+ {
+   unsigned char err = (unsigned char)errno;
+   unsigned char c   = (unsigned char)c1;
+   write(pfd[1],&c,1);
+   write(pfd[1],&err,1);
+   if (name) {
+     write(pfd[1],name,
+ 	  strlen(name)+1);
+   }
+   _exit(127); 
+ }
+ 
+ static int pipe_old_raw = 0;    /* Stored state when give_term */
+ int start_pipes(prog,pipes,argv, options, give_term)
+      char *prog;
+      struct fdvec pipes[];
+      char * argv[];
+      int options;
+      int give_term;
+ {
+   int count,i;
+   int fail = 0;
+   char error_message[100]; /* Should be < 80 chars */
+   int pid = -1;
+     /* Open multiple pipes to program */
+   int pfd[2];
+   
+   SIGHAND_TYPE (*istat)(), (*qstat)(), (*wstat)();
+ #ifdef SIGTSTP
+   SIGHAND_TYPE (*oldstop)(), (*oldstart)();
+ #endif
+ 
+     fflush(stdout);
+   /* Count pipes */
+   for (count = 0; pipes[count].flag != FDVEC_END; count++) {
+     pipes[count].fd  = -1;
+     pipes[count].fd2 = -1;
+   }
+ 
+   pfd[0] = -1;
+   pfd[1] = -1;
+   if (pipe(pfd) == -1) {
+     int err = errno;
+      sprintf(error_message,"pipe: (%d) %.60s",err,error_description(err));
+     fail++;
+   } else {
+     fcntl(pfd[0], F_SETFD, 1);
+     fcntl(pfd[1], F_SETFD, 1);
+   }
+ 
+   istat = signal(SIGINT, SIG_IGN);
+   qstat = signal(SIGQUIT, SIG_IGN);
+ #ifdef SIGWINCH
+   wstat = signal(SIGWINCH, SIG_DFL);
+ #endif
+ #ifdef SIGTSTP
+   oldstop = signal(SIGTSTP, SIG_DFL);
+   oldstart = signal(SIGCONT, SIG_DFL);
+ #endif
+ 
+ 
+   if (!fail) {
+     /* Create other pipes */
+     for (i= 0; i < count; i++) {
+       if (!(pipes[i].flag & FDVEC_FILE)) {
+ 	int array[2];
+ 	if (-1 == pipe(array)) { int err = errno;
+ 				 sprintf(error_message,
+ 					 "pipe: (%d) %.60s",err,
+  					 error_description(err));
+ 				 fail++;
+ 				 break;
+ 			       }
+ 	if (pipes[i].flag & FDVEC_TO_PRG) {
+ 	  pipes[i].fd  = array[1];
+ 	  pipes[i].fd2 = array[0];
+ 	} else {
+ 	  pipes[i].fd  = array[0];
+ 	  pipes[i].fd2 = array[1];
+ 	}
+       }
+     }
+   }
+ 
+   if (give_term) {
+     MoveCursor(elm_LINES,0);
+     CleartoEOLN();
+     fflush(stdout);
+     if ((pipe_old_raw = RawState()) == ON)
+       Raw(OFF|NO_TITE);
+     /* softkeys_off(); */
+   }
+ 
+   if (!fail) {
+     pid = fork();
+     if (-1 == pid) { int err = errno;
+ 		     sprintf(error_message,
+  			     "fork: (%d) %.60s",err,error_description(err));
+ 		     fail++;
+ 		   }
+     else if (0 == pid) { /* child */
+       /*
+        * Set group and user back to their original values.
+        * Note that group must be set first.
+        */
+       setgid(groupid);
+       setuid(userid);
+ 
+       set_child_signals(options);
+       set_child_env(options);
+ 
+       close(pfd[0]);
+       if (!give_term) {
+ 	int fd = open("/dev/null",O_RDONLY);
+ 	if (-1 == fd) child_fail(pfd,'o',"/dev/null");
+ 	if (-1 == dup2(fd,0) ||
+ 	    -1 == dup2(fd,1) ||
+ 	    -1 == dup2(fd,2)) child_fail(pfd,'d',NULL);
+ 	close(fd);
+ 
+ #ifdef SIGTTSTP
+ 	signal(SIGTTIN, SIG_IGN); 
+ 	signal(SIGTTOU, SIG_IGN);
+ 	signal(SIGTSTP, SIG_IGN);
+ #endif
+       }
+ 
+       /* Handle pipes */
+       for (i= 0; i < count; i++) {
+ 	if (pipes[i].fd != -1) close(pipes[i].fd);
+ 	if (pipes[i].flag & FDVEC_FILE) {
+ 	  if (pipes[i].flag & FDVEC_TO_PRG) 
+ 	    pipes[i].fd2 = open(pipes[i].name,O_RDONLY);
+ 	  else 
+ 	    pipes[i].fd2 = open(pipes[i].name,O_WRONLY|O_CREAT|O_EXCL,0600);
+ 	  if (-1 == pipes[i].fd2) child_fail(pfd,'o',pipes[i].name);
+ 	}
+ 	if (pipes[i].flag & FDVEC_STDIN) {
+ 	  if (-1 == dup2(pipes[i].fd2,0)) child_fail(pfd,'d',NULL);
+ 	}
+ 	if (pipes[i].flag & FDVEC_STDOUT) {
+ 	  if (-1 == dup2(pipes[i].fd2,1)) child_fail(pfd,'d',NULL);
+ 	}
+ 	if (pipes[i].flag & FDVEC_STDERR) {
+ 	  if (-1 == dup2(pipes[i].fd2,2)) child_fail(pfd,'d',NULL);
+ 	}
+ 	if (pipes[i].flag & FDVEC_DEFINE) { 
+ 	  char *p = malloc(strlen(pipes[i].name)+10);
+ 	  if (p) {
+ 	    sprintf(p,"%s=%d",pipes[i].name,pipes[i].fd2);
+ 	    putenv(p);
+ 	  }
+ 	}
+       }
+       
+       /* Finally -- try exec program */
+       execvp(prog,argv);
+       child_fail(pfd,'e',prog);
+     } /* End of child */
+   }
+ 
+   /* Close other end of pipes */
+   if (-1 != pfd[1]) close(pfd[1]);
+   for (i= 0; i < count; i++) {
+     if (pipes[i].fd2 != -1) close(pipes[i].fd2);
+   }
+ 
+   if (!fail) {
+     unsigned char error_data[60];
+     int got;
+ 
+     /* Wait until exec succeed ... */
+     while (-1 == (got = read(pfd[0],error_data,59)) && errno == EINTR);
+     if (got > 0) {
+       char * msg = "?";
+       char * err = "";
+       error_data[got] = '\0';
+       if (got < 2) error_data[2] = '\0';
+       if (got > 1) err = error_description(error_data[1]);
+       switch(error_data[0]) {
+       case 'e': msg = "exec"; break;
+       case 'd': msg = "dup2"; break;
+       case 'o': msg = "open"; break;
+       }
+       sprintf(error_message,"%s failed:%.30s:%.55s",msg,err,error_data+2);
+       fail++;
+     }
+   }
+ 
+   (void) signal(SIGINT, istat);
+   (void) signal(SIGQUIT, qstat);
+ #ifdef SIGWINCH
+   (void) signal(SIGWINCH, wstat);
+ #endif
+ #ifdef SIGTSTP
+   (void) signal(SIGTSTP, oldstop);
+   (void) signal(SIGCONT, oldstart);
+ #endif
+ 
+ 
+   if (fail) {
+     if (pid != -1) kill(pid,SIGTERM); /* Ask child to terminate in case of
+ 					* error
+ 					*/
+     end_pipes(pid,prog,pipes,give_term,NULL);
+   }
+ }
+ 
+ int end_pipes(pid,prog,pipes,give_term, print_msg) 
+      int pid;
+      char *prog;
+      struct fdvec pipes[];
+      int give_term;
+      char * print_msg;
+ {
+   int count, fail = 0;
+   int stat = -1;
+ 
+   /* Count pipes */
+   for (count = 0; pipes[count].flag != FDVEC_END; count++) {
+     /* And close child's input */
+     if (pipes[count].flag & FDVEC_TO_PRG) 
+       if (pipes[count].fd != -1) {
+ 	close(pipes[count].fd);
+ 	pipes[count].fd = -1;
+       }
+   }
+ 
+   if (-1 != pid) {
+     int w;
+ #if defined(BSD) && !defined(WEXITSTATUS)
+     union wait status;
+ #else
+     int status;
+ #endif
+ 
+     /* Wait for termination */
+     while ((w = wait(&status)) != pid)
+       if (w == -1 && errno != EINTR)
+ 	break;
+     if (w == pid) {
+ #ifdef	WEXITSTATUS
+       stat = WEXITSTATUS(status);
+ #else
+ # ifdef	BSD
+       stat = status.w_retcode;
+ # else
+       stat = status;
+ # endif
+ #endif
+     }
+   }
+ 
+   if (give_term) {
+     
+     if (pipe_old_raw == ON)
+       Raw(ON|NO_TITE);
+ 
+     SetXYLocation(0,elm_LINES+5);      /* Hack */
+     if (stat != -1 && print_msg) {
+       PutLine2(elm_LINES,0,"%.35s %s. %.35s",prog,
+ 	       stat ? "failed": "succeed", print_msg);
+       (void) ReadCh(0);
+     }
+     /* softkeys_on(); */
+   }
+ 
+   return stat;
+ }
+ 
+ void close_pipes(pipes) 
+      struct fdvec pipes[];
+ {
+   int count;
+   for (count = 0; pipes[count].flag != FDVEC_END; count++) {
+     /* And close all pipes */
+     if (pipes[count].fd != -1) {
+       close(pipes[count].fd);
+       pipes[count].fd = -1;
+     }
+   }
+ }
+ 
+ #endif
+ 
  int
  do_pipe()
  {
***************
*** 354,394 ****
  	char command[SLEN], buffer[SLEN], *prompt;
  	register int  ret;
  	int	old_raw;
  
  	prompt = catgets(elm_msg_cat, ElmSet, ElmPipeTo, "Pipe to: ");
!         PutLine0(LINES-2, 0, prompt);
  	command[0] = '\0';
! 	(void) optionally_enter(command, LINES-2, strlen(prompt), FALSE, FALSE);
! 	if (command[0] == '\0') {
! 	  MoveCursor(LINES-2,0);
  	  CleartoEOLN();
! 	  return(0);
  	}
  
! 	MoveCursor(LINES,0);
  	CleartoEOLN();
  	if (( old_raw = RawState()) == ON)
  	  Raw(OFF);
  
- 	if (cursor_control)
- 	  transmit_functions(OFF);
- 	
  	sprintf(buffer, "%s -Ih|%s", readmsg, command);
  	ret = system_call(buffer, SY_USER_SHELL|SY_ENAB_SIGINT|SY_DUMPSTATE);
  
  	SetXYLocation(0, 40);	/* a location not near the next request, so an absolute is used */
! 	PutLine0(LINES, 0, catgets(elm_msg_cat, ElmSet, ElmPressAnyKeyToReturn,
  		"\n\nPress any key to return to ELM: "));
  
  	Raw(ON | NO_TITE);
! 	(void) getchar();
  	printf("\r\n");
  	Raw(OFF | NO_TITE); /* Done even if old_raw == ON, to get ti/te right */
  	if (old_raw == ON)
  	  Raw(ON);
  
- 	if (cursor_control)  transmit_functions(ON);
- 
  	if (ret != 0)
  	  error1(catgets(elm_msg_cat, ElmSet, ElmReturnCodeWas,
  		"Return code was %d."), ret);
--- 697,747 ----
  	char command[SLEN], buffer[SLEN], *prompt;
  	register int  ret;
  	int	old_raw;
+ 	int redraw = FALSE;
+ 	int status;
  
  	prompt = catgets(elm_msg_cat, ElmSet, ElmPipeTo, "Pipe to: ");
!         PutLine0(elm_LINES-2, 0, prompt);
  	command[0] = '\0';
! 	status = optionally_enter(command, elm_LINES-2, strlen(prompt), 
! 				  OE_REDRAW_MARK);
! 	while (status == REDRAW_MARK) {
! 	  redraw = TRUE;
! 	  PutLine0(elm_LINES-2, 0, prompt);
! 	  status = optionally_enter(command, elm_LINES-2, strlen(prompt), 
! 				    OE_REDRAW_MARK|OE_APPEND_CURRENT);
! 
! 	}
! 	if (0 != status || command[0] == '\0') {
! 	  MoveCursor(elm_LINES-2,0);
  	  CleartoEOLN();
! 	  return(redraw);
  	}
  
! 	MoveCursor(elm_LINES,0);
  	CleartoEOLN();
  	if (( old_raw = RawState()) == ON)
  	  Raw(OFF);
  
  	sprintf(buffer, "%s -Ih|%s", readmsg, command);
  	ret = system_call(buffer, SY_USER_SHELL|SY_ENAB_SIGINT|SY_DUMPSTATE);
  
+ redraw2:
  	SetXYLocation(0, 40);	/* a location not near the next request, so an absolute is used */
! 	PutLine0(elm_LINES, 0, catgets(elm_msg_cat, ElmSet, 
! 				       ElmPressAnyKeyToReturn,
  		"\n\nPress any key to return to ELM: "));
  
  	Raw(ON | NO_TITE);
! 	if (ReadCh(REDRAW_MARK) == REDRAW_MARK) {
! 	  Raw(OFF | NO_TITE);
! 	  goto redraw2;
! 	}
  	printf("\r\n");
  	Raw(OFF | NO_TITE); /* Done even if old_raw == ON, to get ti/te right */
  	if (old_raw == ON)
  	  Raw(ON);
  
  	if (ret != 0)
  	  error1(catgets(elm_msg_cat, ElmSet, ElmReturnCodeWas,
  		"Return code was %d."), ret);
***************
*** 463,471 ****
  	 */
  	if ((old_raw = RawState()) == ON)
  	    Raw(OFF | NO_TITE);
! 	softkeys_off();
! 	if (cursor_control)
! 	    transmit_functions(OFF);
  
  	/*
  	 * Run the print command in a pipe and grab the output.
--- 816,822 ----
  	 */
  	if ((old_raw = RawState()) == ON)
  	    Raw(OFF | NO_TITE);
! 	/* softkeys_off(); */
  
  	/*
  	 * Run the print command in a pipe and grab the output.
***************
*** 478,483 ****
--- 829,835 ----
  		"Cannot create pipe to print command."));
  	    goto done;
  	}
+ redraw:
  	while (fgets(buffer, sizeof(buffer), fp) != NULL) {
  	    fputs(buffer, stdout);
  	    ++nlines;
***************
*** 491,497 ****
  		"Press any key to continue:"));
  	    fflush(stdout);
  	    Raw(ON | NO_TITE);
! 	    (void) getchar();
  	}
  
  	/*
--- 843,854 ----
  		"Press any key to continue:"));
  	    fflush(stdout);
  	    Raw(ON | NO_TITE);
! 	    if (ReadCh(REDRAW_MARK) == REDRAW_MARK) {
! 	      Raw(OFF | NO_TITE);
! 	      rewind(fp);
! 	      nlines = 2;
! 	      goto redraw;
! 	    }
  	}
  
  	/*
***************
*** 518,526 ****
  
  done:
  	Raw(old_raw | NO_TITE);
! 	softkeys_on();
! 	if (cursor_control)
! 	    transmit_functions(ON);
  	(void) unlink(filename);
  	(void) remove_folder_state_file();
  	return (nlines > 1);
--- 875,881 ----
  
  done:
  	Raw(old_raw | NO_TITE);
! 	/* softkeys_on(); */
  	(void) unlink(filename);
  	(void) remove_folder_state_file();
  	return (nlines > 1);
***************
*** 549,555 ****
  
  	Raw(OFF | NO_TITE);
  	ClearScreen();
! 	MoveCursor(LINES, 0);
  	if(helpmsg)
  	  printf(helpmsg);
  	if ( NULL == wildcard )
--- 904,910 ----
  
  	Raw(OFF | NO_TITE);
  	ClearScreen();
! 	MoveCursor(elm_LINES, 0);
  	if(helpmsg)
  	  printf(helpmsg);
  	if ( NULL == wildcard )
***************
*** 622,628 ****
      folder_state_fname = folder_state_env_param + strlen(FOLDER_STATE_ENV) +1;
  
      /* open up the folder state file for writing */
!     if ((fp = fopen(folder_state_fname, "w")) == NULL) {
  	error1(catgets(elm_msg_cat, ElmSet, ElmCannotCreateFolderState,
  		"Cannot create folder state file \"%s\"."), folder_state_fname);
  	return -1;
--- 977,983 ----
      folder_state_fname = folder_state_env_param + strlen(FOLDER_STATE_ENV) +1;
  
      /* open up the folder state file for writing */
!     if ((fp = safeopen(folder_state_fname)) == NULL) {
  	error1(catgets(elm_msg_cat, ElmSet, ElmCannotCreateFolderState,
  		"Cannot create folder state file \"%s\"."), folder_state_fname);
  	return -1;
Index: WORK/src/utils.c
*** elm2.4.25/src/utils.c	Fri Jun  3 20:05:33 1994
--- WORK/src/utils.c	Sun Aug  4 21:45:17 1996
***************
*** 199,207 ****
  	  copy(source, dest, FALSE);
  	}
  
  	printf(catgets(elm_msg_cat, ElmSet, ElmWelcomeToNewElm,
  	"\n\rWelcome to the new version of ELM!\n\n\rHit return to continue."));
! 	getchar();
  }
  
  
--- 199,209 ----
  	  copy(source, dest, FALSE);
  	}
  
+ redraw:
  	printf(catgets(elm_msg_cat, ElmSet, ElmWelcomeToNewElm,
  	"\n\rWelcome to the new version of ELM!\n\n\rHit return to continue."));
! 	if (REDRAW_MARK == ReadCh(REDRAW_MARK))
! 	  goto redraw;
  }
  
  
***************
*** 212,218 ****
  /*ARGSUSED*/
  void malloc_failed_exit(proc, len)
  {
!     MoveCursor(LINES,0);
      Raw(OFF);
      fprintf(stderr, catgets(elm_msg_cat, ElmSet, ElmCouldntMallocBytes,
  	"\n\nCouldn't malloc %d bytes!!\n\n"), len);
--- 214,220 ----
  /*ARGSUSED*/
  void malloc_failed_exit(proc, len)
  {
!     MoveCursor(elm_LINES,0);
      Raw(OFF);
      fprintf(stderr, catgets(elm_msg_cat, ElmSet, ElmCouldntMallocBytes,
  	"\n\nCouldn't malloc %d bytes!!\n\n"), len);
***************
*** 253,264 ****
  	dprint(1, (debugfile,
  	     "     The composition file : %s%s%d\n", temp_dir, temp_file, getpid()));
  
! 	if (cursor_control)  transmit_functions(OFF);
! 	if (hp_terminal)     softkeys_off();
  
  	if (do_cursor) {
  	  Raw(OFF);
! 	  MoveCursor(LINES, 0);
  	  }
  
  	printf(catgets(elm_msg_cat, ElmSet, ElmEmergencyExitTaken,
--- 255,265 ----
  	dprint(1, (debugfile,
  	     "     The composition file : %s%s%d\n", temp_dir, temp_file, getpid()));
  
! 	/* softkeys_off(); */
  
  	if (do_cursor) {
  	  Raw(OFF);
! 	  MoveCursor(elm_LINES, 0);
  	  }
  
  	printf(catgets(elm_msg_cat, ElmSet, ElmEmergencyExitTaken,
***************
*** 285,296 ****
  	signal(SIGCONT,SIG_IGN);
  #endif
  
! 	PutLine0(LINES, 0, catgets(elm_msg_cat, ElmSet, ElmWriteFailedExitingIntact,
  	 "\nWrite to temp file failed, exiting leaving mailbox intact!\n\n"));
  	dprint(2, (debugfile, "\nrm_temps_exit, deleteing temp files\n"));
  
! 	if (cursor_control)  transmit_functions(OFF);
! 	if (hp_terminal)     softkeys_off();
  
  	sprintf(buffer,"%s%d",temp_file, getpid());  /* editor buffer */
  	(void) unlink(buffer);
--- 286,296 ----
  	signal(SIGCONT,SIG_IGN);
  #endif
  
! 	PutLine0(elm_LINES, 0, catgets(elm_msg_cat, ElmSet, ElmWriteFailedExitingIntact,
  	 "\nWrite to temp file failed, exiting leaving mailbox intact!\n\n"));
  	dprint(2, (debugfile, "\nrm_temps_exit, deleteing temp files\n"));
  
! 	/* softkeys_off(); */
  
  	sprintf(buffer,"%s%d",temp_file, getpid());  /* editor buffer */
  	(void) unlink(buffer);
***************
*** 299,310 ****
  	    (void) unlink(cur_tempfolder);
  	}
  
- 	if (mailfile)
- 	    fflush (mailfile);
  	unlock();                               /* remove lock file if any */
  
  	if(do_cursor) {
! 	    MoveCursor(LINES,0);
  	    NewLine();
  	    Raw(OFF);
  	}
--- 299,308 ----
  	    (void) unlink(cur_tempfolder);
  	}
  
  	unlock();                               /* remove lock file if any */
  
  	if(do_cursor) {
! 	    MoveCursor(elm_LINES,0);
  	    NewLine();
  	    Raw(OFF);
  	}
***************
*** 337,344 ****
  
  	dprint(2, (debugfile, "\nLeaving mailer normally (leave)\n"));
  
! 	if (cursor_control)  transmit_functions(OFF);
! 	if (hp_terminal)     softkeys_off();
  
  	sprintf(buffer,"%s%s%d", temp_dir, temp_file, getpid());  /* editor buffer */
  	(void) unlink(buffer);
--- 335,341 ----
  
  	dprint(2, (debugfile, "\nLeaving mailer normally (leave)\n"));
  
! 	/* softkeys_off(); */
  
  	sprintf(buffer,"%s%s%d", temp_dir, temp_file, getpid());  /* editor buffer */
  	(void) unlink(buffer);
***************
*** 347,359 ****
  	  (void) unlink(cur_tempfolder);
  	}
  
- 	if (mailfile)
- 	    fflush (mailfile);
- 
  	unlock();				/* remove lock file if any */
  
  	if (do_cursor) {
! 	  MoveCursor(LINES,0);
  	  NewLine();
  	  Raw(OFF);
  	}
--- 344,353 ----
  	  (void) unlink(cur_tempfolder);
  	}
  
  	unlock();				/* remove lock file if any */
  
  	if (do_cursor) {
! 	  MoveCursor(elm_LINES,0);
  	  NewLine();
  	  Raw(OFF);
  	}
***************
*** 386,405 ****
  
  	dprint(2, (debugfile, "\nLeaving mailer quietly (silently_exit)\n"));
  
! 	if (cursor_control)  transmit_functions(OFF);
! 	if (hp_terminal)     softkeys_off();
  
  	sprintf(buffer,"%s%s%d", temp_dir, temp_file, getpid());  /* editor buffer */
  	(void) unlink(buffer);
  
  	if (do_cursor) {
! 	  MoveCursor(LINES,0);
  	  NewLine();
  	  Raw(OFF);
  	}
  
- 	if (mailfile)
- 	    fflush (mailfile);
  	unlock ();
  
  	exit(0);
--- 380,396 ----
  
  	dprint(2, (debugfile, "\nLeaving mailer quietly (silently_exit)\n"));
  
! 	/* softkeys_off(); */
  
  	sprintf(buffer,"%s%s%d", temp_dir, temp_file, getpid());  /* editor buffer */
  	(void) unlink(buffer);
  
  	if (do_cursor) {
! 	  MoveCursor(elm_LINES,0);
  	  NewLine();
  	  Raw(OFF);
  	}
  
  	unlock ();
  
  	exit(0);
***************
*** 433,440 ****
          dprint(3, (debugfile,
  	    "\nLeaving mailer due to presence of lock file (leave_locked)\n"));
  
! 	if (cursor_control)  transmit_functions(OFF);
! 	if (hp_terminal)     softkeys_off();
  
  	sprintf(buffer,"%s%s%d", temp_dir, temp_file, getpid());  /* editor buffer */
  	(void) unlink(buffer);
--- 424,430 ----
          dprint(3, (debugfile,
  	    "\nLeaving mailer due to presence of lock file (leave_locked)\n"));
  
! 	/* softkeys_off(); */
  
  	sprintf(buffer,"%s%s%d", temp_dir, temp_file, getpid());  /* editor buffer */
  	(void) unlink(buffer);
***************
*** 442,451 ****
  	(void) unlink(cur_tempfolder);			/* temp mailbox */
  
  	if (mailfile)
! 	    fflush (mailfile);
  
  	if (do_cursor) {
! 	  MoveCursor(LINES,0);
  	  NewLine();
  	  Raw(OFF);
  	}
--- 432,441 ----
  	(void) unlink(cur_tempfolder);			/* temp mailbox */
  
  	if (mailfile)
! 	    flush_mailfile();
  
  	if (do_cursor) {
! 	  MoveCursor(elm_LINES,0);
  	  NewLine();
  	  Raw(OFF);
  	}
Index: WORK/src/wordwrap.c
*** elm2.4.25/src/wordwrap.c	Tue Aug  3 22:29:25 1993
--- WORK/src/wordwrap.c	Sun Aug  4 21:59:21 1996
***************
*** 119,127 ****
  	else
  	  iindex = strlen(string);
  
- 	if (cursor_control)
- 	  transmit_functions(OFF);
- 
  	/** now we have the screen as we want it and the cursor in the 
  	    right place, we can loop around on the input and return the
  	    string as soon as the user presses <RETURN> or the line wraps.
--- 119,124 ----
***************
*** 128,143 ****
  	**/
  
  	do {
! 	  ch = getchar();
! 
! 	  if (ch == EOF && ferror(stdin) && errno == EINTR) {
! 	    clearerr(stdin);
! 	    continue;
! 	  }
  
! 	  if (ch == ctrl('D') || ch == EOF) {		/* we've hit EOF */
! 	    if (cursor_control)
! 	      transmit_functions(ON);
  	    *append_current = 0;
  	    return(1);
  	  }
--- 125,134 ----
  	**/
  
  	do {
! 	  ch = ReadCh(0|READCH_NOCURSOR);
  
! 	  if (ch == eof_char && !escaped 
! 	      || ch == EOF) {		/* we've hit EOF */
  	    *append_current = 0;
  	    return(1);
  	  }
***************
*** 144,151 ****
  
  	  if (ch_count++ == 0) {
  	    if (ch == '\n' || ch == '\r') {
- 	      if (cursor_control)
- 	        transmit_functions(ON);
  	      *append_current = 0;
  	      return(0);
  	    }
--- 135,140 ----
***************
*** 231,242 ****
  	  else if (ch == EOF || ch == '\n' || ch == '\r') {
  	    escaped = OFF;
  	    string[iindex] = '\0';
- 	    if (cursor_control)
- 	      transmit_functions(ON);
  	    *append_current = 0;
  	    return(0);
  	  }
! 	  else if (ch == ctrl('W')) {	/* back up a word! */
  	    escaped = OFF;
  	    if (iindex == 0)
  	      continue;		/* no point staying here.. */
--- 220,229 ----
  	  else if (ch == EOF || ch == '\n' || ch == '\r') {
  	    escaped = OFF;
  	    string[iindex] = '\0';
  	    *append_current = 0;
  	    return(0);
  	  }
! 	  else if (ch == word_erase && !escaped) {	/* back up a word! */
  	    escaped = OFF;
  	    if (iindex == 0)
  	      continue;		/* no point staying here.. */
***************
*** 260,266 ****
  	      iindex++;	/* and make sure we point at the first AVAILABLE slot */
  	    }
  	  }
! 	  else if (ch == ctrl('R')) {
  	    escaped = OFF;
  	    string[iindex] = '\0';
  	    PutLine1(x,y, "%s", string);	
--- 247,253 ----
  	      iindex++;	/* and make sure we point at the first AVAILABLE slot */
  	    }
  	  }
! 	  else if (ch == reprint_char && !escaped) {
  	    escaped = OFF;
  	    string[iindex] = '\0';
  	    PutLine1(x,y, "%s", string);	
***************
*** 274,283 ****
  	    CleartoEOLN();
  	    iindex = 0;
  	  }
! 	  else if (ch == '\0') {
  	    escaped = OFF;
- 	    if (cursor_control)
- 	      transmit_functions(ON);
  	    fflush(stdin); 	/* remove extraneous chars, if any */
  	    string[0] = '\0'; /* clean up string, and... */
  	    *append_current = 0;
--- 261,269 ----
  	    CleartoEOLN();
  	    iindex = 0;
  	  }
! 	  else if (ch == '\0' || 
! 		   ch == interrupt_char && !escaped) {
  	    escaped = OFF;
  	    fflush(stdin); 	/* remove extraneous chars, if any */
  	    string[0] = '\0'; /* clean up string, and... */
  	    *append_current = 0;
***************
*** 316,323 ****
  	string[iindex] = '\0';
  	*append_current = line_wrap(string,tail,&iindex,&tabs[tindex-1]);
  
- 	if (cursor_control)
- 	  transmit_functions(ON);
  	return(0);
  }
  
--- 302,307 ----
Index: WORK/utils/Makefile.SH
*** elm2.4.25/utils/Makefile.SH	Thu Mar 10 19:20:29 1994
--- WORK/utils/Makefile.SH	Mon Jun  3 20:20:00 1996
***************
*** 83,89 ****
  
  #	Other general variables
  BIN		=	../bin
! CFLAGS		=	$(CCFLAGS) $(OPTIMIZE) -I$(INCLDIR) $(DEBUG) $(DACSNET) 
  INCLDIR		=	../hdrs
  LINTFLAGS	=	-I$(INCLDIR)
  SHELL		=	/bin/sh
--- 83,89 ----
  
  #	Other general variables
  BIN		=	../bin
! CFLAGS		=	-I$(INCLDIR) $(CCFLAGS) $(OPTIMIZE) $(DEBUG) $(DACSNET) 
  INCLDIR		=	../hdrs
  LINTFLAGS	=	-I$(INCLDIR)
  SHELL		=	/bin/sh
Index: WORK/utils/from.c
*** elm2.4.25/utils/from.c	Mon May 30 19:27:00 1994
--- WORK/utils/from.c	Mon Jun  3 20:20:02 1996
***************
*** 149,154 ****
--- 149,156 ----
  
  extern char *whos_mail(), *explain();
  
+ int showto = 0;
+ 
  #ifdef DEBUG
  int debug = 0;
  FILE *debugfile = stderr;
Index: WORK/utils/newmail.c
*** elm2.4.25/utils/newmail.c	Mon May 30 19:32:01 1994
--- WORK/utils/newmail.c	Mon Jun  3 20:20:10 1996
***************
*** 240,245 ****
--- 240,247 ----
  FILE	*fd = NULL;		/* fd to use to read folders	    */
  FILE	*debugfile = stderr;
  
+ int	showto = 0;
+ 
  #ifdef PIDCHECK
  int  parent_pid;		/* See if sucide should be attempt  */
  #endif /* PIDCHECK */
***************
*** 246,252 ****
  
  extern int errno;
  
! #if defined(BSD) && !defined(__convex__)
          time_t utime_buffer[2];         /* utime command */
  #else
          struct utimbuf utime_buffer;    /* utime command */
--- 248,254 ----
  
  extern int errno;
  
! #if defined(BSD) && !defined(__convex__) && !defined(__FreeBSD__) && !defined(__NetBSD__)
          time_t utime_buffer[2];         /* utime command */
  #else
          struct utimbuf utime_buffer;    /* utime command */
***************
*** 472,478 ****
  	      /* try to set the file access times back, ignore
  		 failures */
  
! #if defined(BSD) && !defined(__convex__)
  	      utime(cur_folder->foldername, utime_buffer);
  #else
                utime(cur_folder->foldername, &utime_buffer);
--- 474,480 ----
  	      /* try to set the file access times back, ignore
  		 failures */
  
! #if defined(BSD) && !defined(__convex__) && !defined(__FreeBSD__) && !defined(__NetBSD__)
  	      utime(cur_folder->foldername, utime_buffer);
  #else
                utime(cur_folder->foldername, &utime_buffer);
***************
*** 857,863 ****
  	
  	/* retain the access times for later use */
  
! #if defined(BSD) && !defined(__convex__)
          utime_buffer[0]     = buffer.st_atime;
          utime_buffer[1]     = buffer.st_mtime;
  #else
--- 859,865 ----
  	
  	/* retain the access times for later use */
  
! #if defined(BSD) && !defined(__convex__) && !defined(__FreeBSD__) && !defined(__NetBSD__)
          utime_buffer[0]     = buffer.st_atime;
          utime_buffer[1]     = buffer.st_mtime;
  #else
Index: WORK/utils/readmsg.c
*** elm2.4.25/utils/readmsg.c	Tue Aug  3 22:29:29 1993
--- WORK/utils/readmsg.c	Mon Jun  3 20:20:11 1996
***************
*** 636,642 ****
      if (Hdrmatch(buf, "From ")) {
  	strcpy(save_from, buf);
  	is_interesting = FALSE;
!     } else if (Hdrmatch(buf, "To:") || Hdrmatch(buf, "Subject:"))
  	is_interesting = TRUE;
      else if (Hdrmatch(buf, "Date:"))
  	got_date = is_interesting = TRUE;
--- 636,643 ----
      if (Hdrmatch(buf, "From ")) {
  	strcpy(save_from, buf);
  	is_interesting = FALSE;
!     } else if (Hdrmatch(buf, "To:") || Hdrmatch(buf, "Subject:")
! 	       || Hdrmatch(buf, "Cc:"))
  	is_interesting = TRUE;
      else if (Hdrmatch(buf, "Date:"))
  	got_date = is_interesting = TRUE;
Index: WORK/src/builtin.c
*** elm2.4.25/src/builtin.c	Mon May 30 19:42:49 1994
--- /tmp/null.14101	Tue Aug 20 22:05:34 1996
***************
*** 1,352 ****
- 
- static char rcsid[] = "@(#)$Id: builtin.c,v 5.4 1994/05/30 16:42:48 syd Exp $";
- 
- /*******************************************************************************
-  *  The Elm Mail System  -  $Revision: 5.4 $   $State: Exp $
-  *
-  * 			Copyright (c) 1988-1992 USENET Community Trust
-  * 			Copyright (c) 1986,1987 Dave Taylor
-  *******************************************************************************
-  * Bug reports, patches, comments, suggestions should be sent to:
-  *
-  *	Syd Weinstein, Elm Coordinator
-  *	elm@DSI.COM			dsinc!elm
-  *
-  *******************************************************************************
-  * $Log: builtin.c,v $
-  * Revision 5.4  1994/05/30  16:42:48  syd
-  * Just a minor fix to an impossible character comparison.
-  * From: Jukka Ukkonen <ukkonen@csc.fi>
-  *
-  * Revision 5.3  1994/05/15  22:55:25  syd
-  * I had to put in some changes to builtin+ to allow it to display
-  * 8-bit letters as they should when the message has been sent
-  * through a real 8-bit channel like ESMTP with 8bit MIME Content-
-  * Transfer-Encoding.
-  * From: Jukka Ukkonen <ukkonen@csc.fi>
-  *
-  * Revision 5.2  1993/08/03  19:28:39  syd
-  * Elm tries to replace the system toupper() and tolower() on current
-  * BSD systems, which is unnecessary.  Even worse, the replacements
-  * collide during linking with routines in isctype.o.  This patch adds
-  * a Configure test to determine whether replacements are really needed
-  * (BROKE_CTYPE definition).  The <ctype.h> header file is now included
-  * globally through hdrs/defs.h and the BROKE_CTYPE patchup is handled
-  * there.  Inclusion of <ctype.h> was removed from *all* the individual
-  * files, and the toupper() and tolower() routines in lib/opt_utils.c
-  * were dropped.
-  * From: chip@chinacat.unicom.com (Chip Rosenthal)
-  *
-  * Revision 5.1  1992/10/03  22:58:40  syd
-  * Initial checkin as of 2.4 Release at PL0
-  *
-  *
-  ******************************************************************************/
- 
- /** This is the built-in pager for displaying messages while in the Elm
-     program.  It's a bare-bones pager with precious few options. The idea
-     is that those systems that are sufficiently slow that using an external
-     pager such as 'more' is too slow, then they can use this!
- 
-     Also added support for the "builtin+" pager (clears the screen for
-     each new page) including a two-line overlap for context...
- 
- **/
- 
- #include "headers.h"
- #include "s_elm.h"
- 
- #define  BEEP		007		/* ASCII Bell character */
- 
- static	unfilled_lines,
- 	form_title;
- 
- int	lines_displayed,	    /* total number of lines displayed      */
- 	total_lines_to_display,	    /* total number of lines in message     */
- 	pages_displayed; 	    /* for the nth page titles and all      */
- 
- start_builtin(lines_in_message)
- int lines_in_message;
- {
- 	/** clears the screen and resets the internal counters... **/
- 
- 	dprint(8,(debugfile, 
- 		"displaying %d lines from message using internal pager\n",
- 		lines_in_message));
- 
- 	unfilled_lines = LINES;
- 	form_title = 1;
- 	lines_displayed = 0;
-         pages_displayed = 1;
- 
- 	total_lines_to_display = lines_in_message;
- }
- 
- extern int tabspacing;
- 
- int
- next_line(inputptr, inputlenptr, output, outputlenptr, width)
- char **inputptr, *output;
- register unsigned width;
- int *inputlenptr, *outputlenptr;
- {
- 	/* Copy characters from input to output and copy
- 	 * remainder of output to output. In copying use ^X notation for
- 	 * control characters, '?' non-ascii characters, expand tabs
- 	 * to correct number of spaces till next tab stop.
- 	 * Column zero of the next line is considered to be the tab stop
- 	 * that follows the last one that fits on a line.
- 	 * Copy until newline/return encountered, null char encountered,
- 	 * width characters producted in output buffer.
- 	 * Formfeed is handled exceptionally. If encountered it
- 	 * is removed from input and 1 is returned. Otherwise 0 is returned.
- 	 */
- 
- 	register char *optr, *iptr;
- 	register unsigned chars_output, nt;
- 	int ret_val;
- 	int ilen = *inputlenptr;
- 
- 	optr = output;
- 	iptr = *inputptr;
- 	chars_output = 0;
- 
- 	ret_val = 0;	/* presume no formfeed */
- 	while(ilen > 0) {	/* while there is something */
- 
- 	  if(chars_output >= width) {	/* no more room on line */
- 	    *optr++ = '\r';	
- 	    *optr++ = '\n';
- 	    /* if next input character is newline or return,
- 	     * we can skip over it since we are outputing a newline anyway */ 
- 	    if((*iptr == '\n') || (*iptr == '\r'))
- 	      { iptr++; --ilen; }
- 	    break;		
- 	  } else if (*iptr == '\n' || *iptr == '\r') {	/*newline or return */
- 	    *optr++ = '\r';
- 	    *optr++ = '\n';
- 	    iptr++; --ilen;
- 	    break;			/* end of line */
- 	  } else if(*iptr == '\f') {		/* formfeed */
- 	    /* if next input character is newline or return,
- 	     * we can skip over it since we are outputing a formfeed anyway */ 
- 	    if((*++iptr == '\n') || (*iptr == '\r'))
- 	      { iptr++; --ilen; }
- 	    --ilen;
- 	    ret_val = 1;
- 	    break;			/* leave rest of screen clear */
- 	  } else if(*iptr == '\t') {	/* tab stop */
- 	    if((nt=next_tab(chars_output+1)) > width) {
- 	      *optr++ = '\n';		/* won't fit on this line - autowrap */
- 	      *optr++ = '\r';		/* tab by tabbing so-to-speak to 1st */
- 	      iptr++;			/* column of next line */
- 	      --ilen;
- 	      break;
- 	    } else {		/* will fit - output proper num of spaces */
- 	      while(chars_output < nt-1) {
- 		chars_output++;
- 		*optr++ = ' ';
- 	      }
- 	      iptr++;
- 	      --ilen;
- 	    }
- 	  } else if(iscntrl(*iptr & 0xff)) {	/* Non-white ctrl char */
- 	    if (chars_output + 2 <= width) {
- 		*optr++ = '^';
- 		*optr++ = ctrl(*iptr);
- 		iptr++; --ilen;
- 		chars_output += 2;
- 	    } else {
- 		break;
- 	    }
- 	  } else {		/* Assume a printing char in case isprint */
- 	    *optr++ = *iptr++;	/* macro fails on true 8-bit characters.  */
- 	    chars_output++;
- 	    --ilen;
- 	  }
- 	}
- 	*optr = '\0';
- 	*inputptr = iptr;
- 	*inputlenptr = ilen;
- 	*outputlenptr = chars_output;
- 	return(ret_val);
- }
- 
- 
- int
- display_line(input_line, input_size)
- char *input_line;
- int  input_size;
- {
- 	int	percent_done;
- 	/** Display the given line on the screen, taking into account such
- 	    dumbness as wraparound and such.  If displaying this would put
- 	    us at the end of the screen, put out the "MORE" prompt and wait
- 	    for some input.   Return non-zero if the user terminates the
- 	    paging (e.g. 'i') or zero if we should continue. Also, 
-             this will pass back the value of any character the user types in 
- 	    at the prompt instead, if needed... (e.g. if it can't deal with
- 	    it at this point)
- 	**/
- 	
- 	char *pending, footer[SLEN], display_buffer[SLEN];
- 	int ch, formfeed, lines_more;
- 	int pending_len = input_size, display_len = 0;
- 
- #ifdef MMDF
- 	if (strcmp(input_line, MSG_SEPARATOR) == 0)
- 	  strcpy(input_line," ");
- #endif /* MMDF */
- 	pending = input_line;
- 	CarriageReturn();
- 
- 	do {
- 
- 	  /* while there is more space on the screen - leave prompt line free */
- 	  while(unfilled_lines > 0) {
- 
- 	    /* display a screen's lineful of the input line
- 	     * and reset pending to point to remainder of input line */
- 	    formfeed = next_line(&pending, &pending_len, display_buffer, &display_len, COLUMNS);
- 
- 	    if(*display_buffer == '\0') {	/* no line to display */
- 	      if(!formfeed)	/* no "formfeed" to display
- 	     			 * need more lines for screen */
- 		return(FALSE);
- 	    } else
- 	      Write_to_screen(display_buffer, 0);
- 
- 	    /* if formfeed, clear remainder of screen */
- 	    if(formfeed) {
- 	      CleartoEOS();
- 	      unfilled_lines=0;
- 	    }
- 	    else
- 	      unfilled_lines--;
- 
- 	    /* if screen is not full (leave room for prompt)
- 	     * but we've used up input line, return */
- 
- 	    if(unfilled_lines > 0 && pending_len == 0)
- 	      return(FALSE);	/* we need more lines to fill screen */
- 
- 	    /* otherwise continue to display next part of input line */
- 	  }
- 
- 	  /* screen is now full - prompt for user input */
- 	  lines_more = total_lines_to_display - lines_displayed;
- 	  percent_done = (int)((100L * lines_displayed) / total_lines_to_display);
- 	  if (user_level == 0) {
- 	    if (lines_more == 1)
- 	      MCsprintf(footer, catgets(elm_msg_cat, ElmSet, ElmMoreUser0,
- " There is 1 line left (%d%%). Press <space> for more, or 'i' to return. "),
- 		 percent_done);
- 	    else
- 	      MCsprintf(footer, catgets(elm_msg_cat, ElmSet, ElmMoreUser0Plural,
- " There are %d lines left (%d%%). Press <space> for more, or 'i' to return. "),
- 		 lines_more, percent_done);
- 	  } else if (user_level == 1) {
- 	    if (lines_more == 1)
- 	      MCsprintf(footer, catgets(elm_msg_cat, ElmSet, ElmMoreUser1,
- " 1 line more (%d%%). Press <space> for more, 'i' to return. "),
- 		 percent_done);
- 	    else
- 	      MCsprintf(footer, catgets(elm_msg_cat, ElmSet, ElmMoreUser1Plural,
- " %d lines more (%d%%). Press <space> for more, 'i' to return. "),
- 		 lines_more, percent_done);
- 	  } else {
- 	    if (lines_more == 1)
- 	      MCsprintf(footer, catgets(elm_msg_cat, ElmSet, ElmMoreUser2,
- " 1 line more (you've seen %d%%) "),
- 		 percent_done);
- 	    else
- 	      MCsprintf(footer, catgets(elm_msg_cat, ElmSet, ElmMoreUser2Plural,
- " %d lines more (you've seen %d%%) "),
- 		 lines_more, percent_done);
- 	  }
-  
- 	  MoveCursor(LINES, 0);
- 	  StartBold();
- 	  Write_to_screen(footer, 0);
- 	  EndBold();
- 
- 	  switch(ch = ReadCh()) {
- 
- 	    case '\n':
- 	    case '\r':	/* scroll down a line */
- 			unfilled_lines = 1;
- 			ClearLine(LINES);
- 			break;
- 
- 	    case ' ':	/* scroll a screenful */
- 			unfilled_lines = LINES;
- 			if(clear_pages) {
- 			  ClearScreen();
- 			  MoveCursor(0,0);
- 			  CarriageReturn();
- 
- 			  /* output title */
- 			  if(title_messages && filter) {
- 			    title_for_page(++pages_displayed);
- 			    unfilled_lines -= 2;
- 			  }
- 			} else ClearLine(LINES);
- 
- 			/* and keep last line to be first line of next
- 			 * screenful unless we had a formfeed */
- 			if(!formfeed) {
- 			  if(clear_pages)
- 			    Write_to_screen(display_buffer, 0);
- 			  unfilled_lines--;
- 			}
- 			break;
- 
- 	    default:	return(ch);
- 	  }
- 	  CarriageReturn();
- 	} while(pending_len > 0);
- 	return(FALSE);
- }
- 	  
- title_for_page(page)
- int page;
- {
- 	/** Output a nice title for the second thru last pages of the message 
- 	    we're currently reading. Note - this code is very similar to
- 	    that which produces the title for the first page, except that
- 	    page number replaces the date and the method by which it
- 	    gets to the screen **/
- 
- 	static char title1[SLEN], title2[SLEN];
- 	char titlebuf[SLEN], title3[SLEN], who[SLEN];
- 	static t1_len, t2_len;
- 	register int padding, showing_to;
- 
- 	/* format those parts of the title that are constant for a message */
- 	if(form_title) {
- 
- 	  showing_to = tail_of(headers[current-1]->from, who,
- 	    headers[current-1]->to);
- 
- 	  sprintf(title1, "%s %d/%d  ",
- 	      headers[current-1]->status & DELETED ? nls_deleted :
- 	      headers[current-1]->status & FORM_LETTER ? nls_form: nls_message,
- 	      current, message_count);
- 	  t1_len = strlen(title1);
- 	  sprintf(title2, "%s %s", showing_to? nls_to : nls_from, who);
- 	  t2_len = strlen(title2);
- 	}
- 	/* format those parts of the title that vary between pages of a mesg */
- 	sprintf(title3, nls_page, page);
- 
- 	/* truncate or pad title2 portion on the right
- 	 * so that line fits exactly to the rightmost column */
- 	padding = COLUMNS - (t1_len + t2_len + strlen(title3));
- 
- 	sprintf(titlebuf, "%s%-*.*s%s\n\r\n\r", title1, t2_len+padding,
- 	    t2_len+padding, title2, title3);
- 	    /* extra newline is to give a blank line after title */
- 
- 	Write_to_screen(titlebuf, 0);
- 	form_title = 0;
- }
--- 0 ----
Index: WORK/lib/safeopen.c
*** /tmp/null.14101	Tue Aug 20 22:05:34 1996
--- WORK/lib/safeopen.c	Mon Jun  3 20:16:51 1996
***************
*** 0 ****
--- 1,45 ----
+ /* $Id$ */
+ 
+ #include <stdio.h>
+ #include <fcntl.h>
+ #include <unistd.h>
+ 
+ #include "headers.h"
+ #include "me.h"
+ 
+ FILE *safeopen(name)
+      char *name;
+ {
+     FILE *fp;
+     int fd = open(name, O_WRONLY | O_CREAT | O_EXCL, 0600);
+ 
+     if (fd < 0 &&
+ 	(unlink(name) ||
+ 	 (fd = open(name, O_WRONLY | O_CREAT | O_EXCL, 0600)) < 0))
+ 	return NULL;
+ 
+     if (! (fp = fdopen(fd, "w"))) {
+       close(fd);
+       unlink(name);
+     }
+     return fp;
+ }
+ 
+ FILE *safeopen_rdwr(name)
+      char *name;
+ {
+     FILE *fp;
+     int fd = open(name, O_RDWR | O_CREAT | O_EXCL, 0600);
+ 
+     if (fd < 0 &&
+ 	(unlink(name) ||
+ 	 (fd = open(name, O_RDWR | O_CREAT | O_EXCL, 0600)) < 0))
+ 	return NULL;
+ 
+     if (! (fp = fdopen(fd, "w+"))) {
+       close(fd);
+       unlink(name);
+     }
+     return fp;
+ }
+ 
