From: Thomas Roessler Date: Tue, 25 Aug 1998 22:33:07 +0000 (+0000) Subject: CVS branch clean-up. X-Git-Tag: mutt-0-94-5i-rel~26 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=986ab5e943db7aaed2aed98f8b74e4c26666fdd8;p=mutt CVS branch clean-up. --- diff --git a/ChangeLog b/ChangeLog index 2a49ca45..fc2c1211 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,1806 +1,899 @@ -Changes since 0.88 ------------------- +Mon Aug 24 09:24:28 1998 Thomas Roessler + + * doc/manual.txt, doc/manual.sgml: Documenting $hidden_host. + + * thread.c, curs_main.c: Fix "previous-subthread" + in reverse-threads mode, allow next-(sub)thread + and previous-(sub)thread to work in limited mode. + (From: Liviu Daia) + +Sun Aug 23 10:05:41 1998 Thomas Roessler + + * sendlib.c, send.c, protos.h, mutt.h, main.c, + init.h, init.c, configure.in, configure, + config.h.in, alias.c, acconfig.h, INSTALL: + [patch-0.94.3i.tlr.hidden_host.1] Replace the + --enable-hidden-host configure switch by a + configuration variable $hidden_host which can be + changed at run-time. This variable will _not_ + affect the generation of message-IDs since we'll + get into uniqueness problems if we just use the + domain here. + + Needs to be documented. + + * doc/manual.txt: Committing the latest manual + changes. + + * Attic/socket.c, imap.c: + [patch-0.94.3.bl.imap_buffy.1-2] Fixing the + buffered read stuff. + + * Attic/mutt_socket.h: Ups, this one was missing + from Brandon's IMAP patch. + +Sat Aug 22 14:24:18 1998 Thomas Roessler + + * help.c: [patch-0.94.3i.gt.beautify_help.1.gz] + General help beautification. From Gero Treuner. + + * doc/manual.sgml, keymap.h, keymap.c, help.c, + Muttrc.in: [patch-0.94.3i.gt.description.1] + Introduce macro descriptions. + + * doc/manual.sgml, init.h, init.c, browser.c: Add + a negation operator "!" to $mask's syntax (as in + the *-hooks). From Liviu. + + * recvattach.c: Make Vikas' attach_split and + Brandon's other_type patches fit together. + + * recvattach.c, mutt.h, init.h, globals.h, + compose.c: [patch-0.94.3.vikas.attach_split.3] + Re-introduce attach_split. + + * Attic/socket.c: [patch-0.94.3.bl.imap_buffy.1] + Adding Brandon's IMAP buffy support. + + * mx.c, mutt.h, mailbox.h, imap.h, imap.c, + curs_lib.c, configure.in, configure, buffy.c, + browser.c, Attic/BUGS: + [patch-0.94.3.bl.imap_buffy.1] Adding Brandon's + IMAP buffy support. -- [patch-0.88.me.buffy_zero.1] 0 length mbox and MMDF mailboxes should never - be marked as having new mail in them +Fri Aug 21 08:17:09 1998 Thomas Roessler + + * browser.c: Enter the file browser, type a mask + which doesn't match any file in the current + directory, clean the mask. Segfault. Fix from + Liviu Daia. + +Thu Aug 20 22:32:46 1998 Thomas Roessler + + * sendlib.c, recvattach.c, parse.c, mutt.h, + mime.h, lib.c, handler.c, globals.h, compose.c, + commands.c, attach.c, Attic/BUGS: + [patch-0.94.3.bl.other_types.1] This patch adds + support for the model MIME type. Additionally, + along the lines of "strict in what you generate, + accepting in what you receive", this patch will + keep the name of major mime types it doesn't + recognize (instead of using x-unknown). + + * compose.c, Attic/BUGS: + [patch-0.94.3i.jmy.attachmessage-fix.1] This patch + fixes a bug in the allocation of space for new + pointers to the attachments, it would make mutt + seg-fault when attaching 5 or more messages at the + same time. (From: Jimmy Mäkelä + ) + + * handler.c: [SECURITY] mutt_sanitize_filename() + should be called when creating temporary files for + autoview. (From: Liviu Daia.) + + * sendlib.c, send.c, attach.c: Try this: set + $mime_forward, forward a PGP-encrypted message, + then in the "compose" menu try to view the + forwarded message. If you didn't enter a + passphrase before, Mutt won't ask for it either. + (From: Liviu Daia) + + * sendlib.c, attach.c: When you forward a message + with $mime_forward set, or when you attach a + message with the "attach-message" command from the + "compose" menu, there is a memory leak. The real + reason for this leak is that multipart attachments + are not supported in the "compose" menu, so you + need to go through quite a few contortions in + order to handle message/rfc822 attachments. + Consequently, the patch below is just an ugly + hack. (From: Liviu Daia) + +Sun Aug 16 06:22:51 1998 Thomas Roessler + + * rfc822.c: Bringing 128-byte strings to "STRING". -- [patch-0.88.me.enter_string.1] rewrote ci_enter_string() to remove - duplicated redraw code, and renamed to mutt_enter_string() + * sendlib.c: Use add_option, not add_arg, for + strings such as "--". -- [patch-0.88.ld.ctx_changed.1] fixed problem with setting the changed flag - for the mailbox when recovering from an externally modified mailbox + * sendlib.c: Pass an "--" argument to sendmail + before the address arguments, so addresses with a + leading dash don't lead to problems. (From Liviu.) -- [patch-0.88.pk.signed.1] fixed comparison between short and unsigned short - in the pager + * sendlib.c, rfc822.c, rfc1524.c, parse.c, mx.c, + main.c, lib.c, keymap.c, hash.c, handler.c, + edit.c, curs_lib.c, alias.c: Replacing a bunch of + free() and malloc() calls by safe_free() and + safe_malloc(). (From Liviu.) -- [patch-0.88.me.set_no.1] makes "unset no" equivalent to "set " +Sat Aug 15 18:27:45 1998 Thomas Roessler -- [patch-0.88.me.state_flag] removes the OPTVERIFYSIG pseudo-option and - replaces it with a "flags" member in the STATE structure + * imap.c: read() can't read buffers larger than + SSIZE_MAX. -- [patch-0.88.me.short] use 'int' instead of 'unsigned short' for message - numbers to allow mutt to read mailboxes larger than 65535 messages + * hook.c: [patch-0.94.3i.tlr.empty_hook.1] Ignore + empty hooks instead of segfaulting. -- [patch-0.88.me.hold.1] removed the $hold variable. the same functionality - is provided by "set nomove" + * protos.h, init.c, Attic/history.h: + [patch-0.94.3i.tlr.history.1] Adding history class + support. -- [patch-0.88.me.buffy_notify.1] move the notification of new mail out of - mutt_buffy_check() into a separate routine + * Attic/history.c: [patch-0.94.3i.tlr.history.1] + Adding history class support. -- [patch-0.88.me.empty_fields.1] skip processing of empty header fields in - _mutt_read_rfc822_header() + * enter.c, TODO, Makefile.in: + [patch-0.94.3i.tlr.history.1] Adding history class + support. -- [patch-0.88.me.var_table.1] use the .data field instead of .bit for - storing the option for DT_BOOL and DT_QUAD vars + * sendlib.c: + [patch-0.94.3i.tlr.attach_msg_fmt.1-2] When + generating a message/rfc822 type attachment, parse + its header so that the attachment format routines + can properly display the default description. -- [patch-0.88.me.rx_not.1] regexps in the *-hook commands can now optionally - be prefixed with a "!" (exclamation point) to indicate that the hook - should be executed when the target does NOT match the following pattern + * init.h: Change attach_format's default to limit + the attachment description's length. -- [patch-0.88.me.sig.2] removes the $local_site, $remote_sig and $local_sig - variables. the same functionality is provided by using a send-hook to set - the $signature variable: - send-hook . set signature=~/.sig-local - send-hook !hmc\\.edu set signature=~/.sig-remote +Thu Aug 13 22:09:16 1998 Thomas Roessler -- [patch-0.88.me.from.1] honor $reverse_name even when $use_from is unset + * pgppubring.c: Fixing another memory leak in the + pubring parser. -- [patch-0.88.bj.status_color.1] removed hack needed to reset the background - color before the buffy_notify patch + * recvattach.c, Attic/BUGS: + [patch-0.94.3i.tlr.attach_msg_fmt.1] When parsing + the "%d" format option in the attachment format, + use the message format as a fall-back if no + explicit description is provided. This fixes the + following bug: -- [patch-0.88.me.parse_param.2] whitespace after a MIME content-type - parameter was not stripped (eg. "charset =us-ascii" would result in the - parameter "charset " in the structure) + set mime_forward. Forward any mesage. The + compose menu will show the description as + "Forwarded message from ...." which is fine. + Pressing 'd' to edit the description brings up + the above string for editing. -Changes since 0.88.1 --------------------- + Now hit Enter on the message/rfc822 attachment + to view it. Quit out of the pager. -- split up mutt.h into several smaller files with groups of related data - in order to reduce the dependencies on mutt.h + The description field has now changed to the + Subject: of the forwarded message. Pressing 'd' + still brings up the 'Forwarded message from....' + string. -- removed the $point_new variable + (Noted by Vikas.) -- the .not member of the REGEXP struct was not initialized for the *-hook - commands, thus causing them not to work properly + * doc/manual.txt, doc/manual.sgml, sendlib.c, + mutt.h, init.h: [patch-0.94.3i.tlr.write_bcc.1] + This patch adds an option $write_bcc which + controls whether the Bcc header is written out or + not. This can be used to work around broken MTA's + (Exim seems to leave Bcc headers in). -- removed bogus ! handling code in the DT_RX variables + The problem was noted independently by Peter + Radcliffe and by Dave Holland + (Debian Bug #25687). -- [patch-0.88.ld.magic.1] fix to return type MBOX for the default magic - for zero length files if $mbox_type is something other than "mbox" or - "mmdf" + * pgppubring.c: [patch-0.94.3i.tlr.pubring_leak.1] + Fixing a memory leak. Bug noted by Liviu Daia. -Changes since 0.88.2 --------------------- + * reldate.h: 0.94.3i. -- [patch-0.88.2.kd.buffy_pop.2] support for --enable-buffy-size and - --enable-pop were broken after the reorganization of mutt.h + * configure.in, configure, ChangeLog: Preparing + 0.94.3i. -- [patch-0.88.2.me.ignore_rx.1] removes the ignore and unignore commands and - replaces them with the $ignore and $unignore variables, which are regular - expressions used for matching lines to weed/show + * compose.c: indentation cosmetics. -- [patch-0.88.2.me.followup.1] adds support for the Mail-Reply-To: and - Mail-Followup-To: header fields + * compose.c: Update menu->data when OP_COMPOSE_EDIT_HDRS is called. + From Vikas. -- [patch-0.88.me.hdrline.1] fixed segfault with %t in $hdr_format if neither - the to: or cc: field exists + * compose.c: Update the encoding after using ispell from the compose + menu. From Vikas. -- [patch-0.88.me.abort_subject.1] print error message if - $abort_nosubject=yes and the user deletes the default subject and tries to - send instead of just silently ignoring the send + * sendlib.c, send.c, protos.h, pgppubring.c, + pattern.c, lib.c, curs_main.c, compose.c, + attach.c: Various nits from Liviu; encoding fixes. -- [patch-0.88.me.long_re.1] increased the max length for regexp's in - send-hook's to be 256 chars + * rfc822.c: Fixing a buffer overflow in rfc822_cat(). tmplen could + underflow. -- [patch-0.88.bj.isprint.1] treat chars >= 0xa0 as printable +Wed Aug 12 11:50:59 1998 Thomas Roessler -- [patch-0.88.me.half_page.1] adds the half-up and half-down functions to - the index and generic key maps. scrolls the page 1/2 screen up or down + * init.c: Yet another memory leak fix from Liviu. -- [patch-0.88.me.useraddr.1] $alternates would not be consulted when the - address to be matches was not fully qualified + * rfc2047.c: Fixing a stupid buffer overflow plus some flawed logic. -- [patch-0.88.me.from_quote.1] add support for messages separators in mbox - mailboxes where the mailbox part of the return-path is a quoted-string - eg: From "michael elkins"@cs.hmc.edu Sat Nov 22 15:55:07 PST 1997 + * functions.h, compose.c, OPS: + Adding an update-encoding function to the compose menu. + This is useful if the user has externally modified an + attachment and _wants_ to adjust the encoding afterwards. + Also, this patch fixes some redraw-related problems in the + compose menu. -- [patch-0.88.me.mx.1] moved code for adding the From_ line to new messages - in mbox/mmdf mailboxes to mx_open_new_message(), and removes the - postponed_mail() func from send.c in favor of mutt_num_postponed() + * sendlib.c, mutt.h, compose.c, Attic/BUGS: + When changing or deleting attachments, the compose menu + now notices this and complains or asks accordingly. + Partially from Vikas. -- [patch-0.88.2.me.post_err.1] abort exiting the compose menu if there was a - problem writing the message to the $postponed mailbox +Tue Aug 11 08:14:38 1998 Thomas Roessler -- [patch-0.88.2.me.find_lists.1] if the to: list was missing, the cc: list - was not searched for mailing lists when doing a list-reply + * Attic/BUGS: Yet another outstanding bug. -- [patch-0.88.2.me.buffy_notify.1] makes mutt keep track of the number of - mailboxes for which the user has not been notified of new mail so that - mutt_buffy_notify() can exit immediately without traversing the mailbox - list if there are no pending notifications + * doc/manual.txt: This now contains the latest changes to manual.sgml. -- [patch-0.88.2.bugfix.mtsirkin.buffy_size.1] fixed some bugs with the - buffy_size pacth + * sendlib.c, rfc2047.c, rfc1524.c, pgppubring.c, pager.c, hdrline.c: + Fixing various nits noted by Liviu and his colleagues. -Changes since 0.88.3 --------------------- +Mon Aug 10 15:30:02 1998 Thomas Roessler -- undid previous patch-0.88.2.me.ignore_rx.1 which changed `ignore' and - `unignore' to regexp vars instead of commands + * sendlib.c: This patches makes the message-id persistant when + postponing messages. (From: Janos Farkas) -- [patch-0.88.3.me.attach_file.2] with $edit_hdrs set, files can be attached - to the message by placing `Attach: ' in the message header while - editing the message + * doc/manual.sgml, sample.muttrc, lib.c, init.h: + This patch introduces "unhdr_order" to reset the hdr_order + command's effect. (From: Janos Farkas) -- [patch-0.88.3.me.find_lists.1] fixed bug in the list-reply function + * color.c: Drop the free_rx parameter from muitt_free_color_line(), + as it's always 1. -- [patch-0.88.3.me.followup.1] the mail-followup-to: field should be set for - all types of messages, not just group-reply + * color.c: Adding mutt_free_color_line() and replacing varous + "manual" free()s of color lines by calls to this function. -- [patch-0.88.3.pk.fccdate.1] the date in fcc:'s to mbox/mmdf mailboxes was - incorrect + * bind.c: Removing bind.c. Pointed out by Gero Treuner + . -- [patch-0.88.3.bugfix.mtsirkin.buffy_size.1] fixed some more bugs in the - buffy_size handling +Sun Aug 9 18:43:45 1998 Thomas Roessler -- [patch-0.88.3.me.menu.1] adds the $menu_scroll which causes mutt not to do - an implicit next-page when doing a next-message on the last message - displayed on the screen, and adds the current-top, current-middle, - current-bottom functions to reposition the current message at the top, - middle and bottom of the screen, respectively + * color.c: With SLang, init_pair is (void), so we must not check its + return value. -- [patch-0.88.3.me.buffy.1] avoid the double-stat() in mutt_buffy_check() by - saving the magic in the BUFFY struct + * color.c: Restructuring color.c. This patch fixes the "default" + problem from 0.94.2i and makes the code more + comprehensible than that version and more consie than + 0.94.1i. -- [patch-0.88.3.me.buffy_config.1] the interval that mutt will check for new - mail in the `mailboxes' list is now configurable via the $mail_check - variable (default: 3 seconds) +Sat Aug 8 21:40:12 1998 Thomas Roessler -- [patch-0.88.3.me.hook.1] fixed the !-handling in the *-hook commands to - allow specification of ! (shortcut for $spoolfile) in folder-hook by - placing quotes around it (eg., folder-hook '!' set signature=~/.signature) + * rfc2047.c: Fixing the "=?" detection in rfc2047_encode_string(). Bug + noted by David Jeske . -Changes since 0.88.4 --------------------- + * compose.c: If you press t to add a recipient in the compose menu, + then press tab, q, and aborts with ctrl-g, mutt won't + redraw the menu. Noted by Jimmy Mäkelä + . -- changed default value of $move to `no' + * alias.c: Entering an un-parsable address when creating an alias + would make mutt segfault. Noted by brian moore + . -- [patch-0.88.4.me.from.1] fixed problem with duplicate From_ lines when - saving from mbox/mmdf mailboxes + * browser.c: If you press tab in the file-browser to see the inboxes + and the current row is greater than the inbox-screens + max-rows then the screen gets garbled. + (From: Jimmy Mäkelä ) -- [patch-0.88.4.thread.1] modified threading algorithm such that the entire - mailbox does not need to be rethreaded when new mail arrives or when - switching among the different sorting methods + * doc/manual.txt, doc/manual.sgml: I made the manual more up to date: -- [patch-0.88.4.de.buffy_stuff.1] removed code for testing newly created - mailboxes based upon the magic type + * new version + * new mailing list and home page addresses + * made the terminology a bit more consistent regarding + 'pattern' and 'regular expression' + * added a note about expanding UNIX environments + * added a note about <, >, in range patterns like ~m + * added a note about the urlview program + * changed tables to not use tabs, because it doesn't work + right in my favourite web browsers lynx and netscape -- [patch-0.884.de.buffy_new_folder.1] adds support for detecting created - buffy mailboxes + (From: Gero Treuner ) -- [patch-0.88.4.speedup.mtsirkin.buffy_size.1] speeds up startup time with - the --enable-buffy-size configure option + * pattern.c: This patch makes pattern ranges more logical. Before '~m + <5' would show message 1-5, with this patch it shows 1-4. + Inclusive ranges is still avaible if you use '~m -5'. + (From: Jimmy Mäkelä ) -Changes since 0.88.5 --------------------- + * init.c: Various improvements to the mutt_command_complete + function. From Stephen Hack . -- [patch-0.88.5.bugfix.mtsirkin.buffy_size.1] fix bug in buffy_size + * browser.c: If you specify 'mailboxes ""' mutt will seg-fault. (From: + Jimmy Mäkelä ) -- [patch-0.88.5.de.pop_var.1] remove unneeded variable + * color.c: Fixing a memory leak. Thanks, Liviu. -- [patch-0.88.5.me.thread.2] fix segfault on sync + * commands.c: When printing a message, headers are now sorted according + to hdr_order. From Liviu. -- [patch-0.88.5.me.rx.1] a path may now be specified with --with-rx + * browser.c: Fixing an off-by-one buffer overflow in browser.c. Noted + by Liviu. -- [patch-0.88.5.de.aliasnull.1] fixed segfault when creating an alias while - in limited view + * lib.c, attach.c: This patch adds some more "safe" characters to + mutt_sanitize_filename and fixes its usage in + mutt_view_attachment(). (From: Liviu Daia + ) -- [patch-0.88.5.me.hook.1] fixed a bug which caused *-hook's with the same - regexp to be ignored + * status.c, sort.h, sendlib.c, send.c, query.c, protos.h, postpone.c, pager.h, pager.c, mutt_menu.h, menu.c, main.c, init.c, headers.c, functions.h, curs_main.c, curs_lib.c, compose.c, commands.c, browser.c, addrbook.c, OPS: + Adding the attach message patch. From Vikas Agnihotri + . -- [patch-0.88.5.me.followup.1] the Mail-Followup-To: field was not rfc2047 - encoded + * Makefile.in: There is no "compile" rule for dotlock in the Makefile. + (From: Dan Nelson ) -- [patch-0.88.5.me.menu.2] fixed some miscellaneous redraw problems related - to the menu movement commands + * imap.c: Thispatch to imap.c allows the user to specify a port + number in the folder name in the general form + {hostname:portnum}foldername. (From: Andy Sloane + ) -- [patch-0.88.4.me.str_sub.2] moves handling of backquotes (``) in muttrc - commands to mutt_extract_token() so that they are only evaluated in - appropriate places + * imap.c: imap_close_connection() was being called even though the + client was using mulitple mailboxes over the same + connection. (From: Brandon Long ) -- [patch-0.88.5.me.generic_menu.2] created the `generic' keymap which the - other menus (except for pager and editor) default to if a key is not found - in the menu specific keymap -- [patch-0.88.5.nit.mtsirkin.buffy_time.1] disable the utime() call when - BUFFY_SIZE is enabled +Fri Jul 31 08:17:50 1998 Thomas Roessler -- [patch-0.88.5.me.mx_cleanup.1] separates append code out of - mx_open_mailbox() into mx_open_mailbox_append() for better code - readability. + * rfc1524.c: Changing an sprintf to an snprintf (which it was meant to + be.) -- [patch-0.88.5.me.pattern.2] rewrite of searching/limiting code to - pre-compile the search pattern + * protos.h: mutt_sanitize_filename takes char *, not const char *. -Changes since 0.88.6 --------------------- + * protos.h, lib.c, attach.c: + Introducing mutt_sanitize_filename(). The code is similar + to patch-0.91.1i.tlr.rfc1524_sanitize.1 and to Peter + Holzer's patch against 0.91. -- [patch-0.88.6.bigfix.init.mtsirkin.1] fixed variable type problem + * rfc1524.h, rfc1524.c, postpone.c, attach.c: + Avoid possible buffer overflows in mutt_adv_mktemp(). -- [patch-0.88.6.jf.followup.1] fix off by 1 error in parsing of the - mail-followup-to: field + * sendlib.c: Interpret sysexits-style exit values from sendmail. -- [patch-0.88.6.me.backtic.2] backtics were not handled in the alias and - my_hdr commands + * configure.in, configure, config.h.in, acconfig.h: + Check for sysexits.h. -- [patch-0.88.6.me.bindings.1] added missing J and K bindings for the index - menu +Thu Jul 30 09:30:38 1998 Thomas Roessler -- [patch-0.88.6.me.pattern.2] fixed bugs in the search pattern compiler + * edit.c: When reading in files, be_snarf_file() wouldn't recognize + '~' as the user's home directory. -- [patch-0.88.6.de.sortbug.1] fixed coredump when resorting when new mail - arrives in an empty box +Wed Jul 29 10:54:09 1998 Thomas Roessler -- [patch-0.88.6.de.in_reply_to.1] increased length of buffer used to store - the message-id from the in-reply-to: header field + * README, Changes: Finalizing 0.93.2i. -- [patch-0.88.6.bl.doc_nits.1] updated docs on the alias expansion + * configure.in, configure: Bumping to 0.93.2(i). -- [patch-0.88.6.de.remove_search_body.1] removes the search-body function - from the index menu now that the same feature is supported with the - rewritten search functions + * parse.c: Fixing a buffer overflow in parse.c which presented a + serious security thread. Noted by Paul Boehm + . -- [patch-0.88.6.de.search-body-doc.1] removes documentation references for - the search-body command +Tue Jul 28 08:21:49 1998 Thomas Roessler -- [patch-0.88.6.nit.pattern.mtsirkin.1] fixed compiler warning about const - being ignored + * Attic/patch.slang-1.2.2.keypad.1: Adding a patch for a SLang bug. -- [patch-0.88.6.me.help_unbound.1] unbound functions are now displayed in - the help menus + * INSTALL: Adding a patch for a SLang bug. -- [patch-0.88.6.me.received.1] if no From_ line is found, parse the first - Received: header field to get the local delivery date instead of using the - file modification time + * mx.c: Doing 'mutt -f NoSuchFile' just flickers the screen and + silently exits. Earlier (0.92.14 at least), it used to + spit out the error 'NoSuchFile: no such file or directory + (errno = 2)'. (Noted and tracked down by Vikas Agnihotri + ) -- [patch-0.88.6.kd.half_up.1] fixed bug in half-up function + * color.c: The index cache should be updated even without color + support. -- fixed the eat_regexp() function to use _mutt_extract_token() so that - things like \n and \t get expanded +Mon Jul 27 13:39:39 1998 Thomas Roessler -- extended _mutt_extract_token() to be able to be used in eat_regexp() - by adding the option not to reap quotes, and to recognize the logic - operators for the pattern matching + * Attic/BUGS: Adding a notice about some more nits. -Changes since 0.88.7 --------------------- + * main.c: Change the error reporting mail address from + to . -- changed handling of \ to not be interpreted inside of single quotes + * protos.h, init.h, color.c: + This patch fixes index "color" patterns when using a + non-color capable curses library. While working on color + support, I've thrown together the mutt_parse_color() and + mutt_parse_mono() functions as they are sharing most of + their code. Additionally, a new directive called "unmono" + is introduced. The implementation consists in adding a + flag and very few lines of code (plus ifdefs) to + mutt_parse_uncolor(). -- runs of quotes in muttrc commands are now supported, so that - the following are equivalent: - michael\ elkins - michael' 'elkins - "michael"' 'elkins + * snprintf.c, rfc1524.h, rfc1524.c, date.c: + Fixing some minor nits: missing #includes in date.c and + snprintf.c, and a not-so-nice declaration of + rfc1524_new_entry(). Noted by Digital cc and gcc. -- fixed backtic handling so that the output is considered as separate tokens - unless, so that you may do: mailboxes `echo ~/Mail/Lists/*` +Fri Jul 24 08:12:46 1998 Thomas Roessler -- "ignore from_" is no longer supported, you should use - ignore "From " + * copy.c, attach.c: + Fiddling around with message/rfc822 attachments once again. -- created new menu function menu_check_recenter() in menu.c which is - responsible for checking if the current message has moved off the current - displayed range and recenters if needed +Thu Jul 23 20:57:50 1998 Thomas Roessler -- removed support for old-style Mutt postponed mailboxes which used the - X-Mutt-Attachment: header field + * status.c, sendlib.c, send.c, rfc2047.c, pop.c, pager.c, mx.c, mh.c, mbox.c, lib.c, init.c, imap.c, edit.c, curs_lib.c, compose.c, commands.c, color.c, browser.c, attach.c, alias.c: + Guard lots of global (char *) variable deferences against + NULL pointers. -- [patch-0.88.7.me.alias.1] fix segfault on recursive aliases + * copy.c, attach.c: + Yet another patch about saving message/rfc822 attachments. -- [patch-0.88.7.me.attach_desc.1] allow optional specification of the - attachment description after the filename in the 'Attach:' header field - with $edit_hdrs + * main.c, send.c: Fixing potential NULL pointer deferences. -- [patch-0.88.7.me.help.1] fixed display of unbound functions in help to - crossref between the generic and menu specific keymaps so that functions - which are bound do not show up as unbound +Wed Jul 22 22:47:57 1998 Thomas Roessler -- [patch-0.88.7.me.pager_search.1] regexps should be compiled with - REG_NEWLINE + * recvattach.c: Another fix from Liviu. -- [patch-0.88.7.me.rx.1] use macro REGCOMP() instead of directly calling - regcomp() + * recvattach.c, from.c, attach.c: + Another patch from liviu to fix the message/rfc822 + behaviour. -- [patch-0.88.7.me.parse.1] received: parsing did not work, and copying a - message to =postponed and recalling it resulted in some duplicate fields - in the header + * recvattach.c, mx.c, attach.c: + This patch fixes the saving of message/rfc822 attachments + to mail folders. Additionally, it fixes an outstanding + bug with From_ lines being written to MH folders. -- [patch-0.88.6.kd.help_length.1] shortened descriptions of several help - strings + (From: Liviu Daia ) -- [patch-0.88.7.de.pattern.1] fixed off by one errors in selecting ranges of - messages + * menu.c, functions.h, browser.c, OPS: + 1. When I hit 'c' (change dir) in browser, it gives me the + directory, but without the final '/', so I have to add + '/' to add a subdirectory name. This patch fixes it. -- [patch-0.88.7.kd.half_down.1] fixed half-down op to mimic the next-page op - where if there is no next page, the pointer is moved to the last entry in - the menu instead of printing an error + 2. check-new now will recheck mailbox folders for new + mail. -- added a sleep() call after the info about the state of the mailbox after a - sync operation so that the user has time to read it before the message - about sorting pops up + 3. added a function toggle-mailboxes which toggles in + browser between mailboxes view and directory view. + (bound to TAB by default). -Changes since 0.88.8 --------------------- + (From: "Michael S. Tsirkin" ) -- [patch-0.88.8.me.no_url.1, patch-0.88.8.no_url.1-2] the url menu and all - referecnes to it has been removed. equivalent functionality can be - obtained by using the external program - ftp://ftp.cs.hmc.edu/pub/me/urlview-0.3.tar.gz and the following macro: - macro index \cb |urlview\n + * send.c: Correct an error message in send.c. + (From: Byrial Jensen ) -- [patch-0.88.8.me.refresh.1] patch to avoid calls to refresh() in the - middle of executing macros + * sendlib.c, recvattach.c, protos.h, postpone.c, + pager.c, mx.c, mutt.h, lib.c, keymap.c, handler.c, + compose.c, commands.c, attach.h, attach.c: -- [patch-0.88.8.me.nested_quote.1] fixed problem with nested quotes in - muttrc commands + These changes fix some of the bugs which were + recently reported to mutt-dev. To be more specific, + message-type attachments are saved to mail folders + from the receive attachment menu, some of the + sending code has been made more robust against + disappearing attachments, and "tag" is rebound to + "T" on the compose menu. -- [patch-0.88.8.me.tag_thread.1] adds the tag-thread (ESC-t) function + (Some part of this patch comes from Vikas Agnihotri + .) -- [patch-0.88.me.reply_self.1] change handling of $metoo so that it will - leave the user's address on the to: line if it is the only address in the - list + * send.c: Avoid a potential segmentation fault when + trying to postpone, but Postponed equals NULL. -- [patch-0.88.me.decode_copy.1] removes the $forw_decode, $decode_format - variables, the decode-save and decode-copy functions, and rewrite of the - attachment handling functions to be much simpler + * Attic/BUGS: This file is intended to contain known + bugs which still have to be fixed. -- [patch-0.88.8.me.thread.1] fixed segfault on thread resort when new mail - arrives is a message in the mailbox has no message-id: field + * doc/manual.txt: + Committing the changes previously made to manual.sgml. -- mutt would dump core if given a bad date for the ~d search pattern + * imap.c: Include Message-ID and Reply-To headers + when fetching a message's headers from an IMAP + server. (From: Andy Sloane ) -- [patch-0.88.8i.de.fast_forward.1] skip prompt for subject when forwarding - if $fast_reply is set +Tue Jul 21 07:54:03 1998 Thomas Roessler -- fixed compilation error on systems without support for color related to - the color quoting support (SunOS 4.1.x) + * recvattach.c: + The old behaviour of the %d (for description) specifier is + recreated by this patch. + (From: Byrial Jensen ) -- [patch-0.88.8-bugfix.buffy_size.mtsirkin.2] fixed a bug in buffy_size - support + * protos.h, lib.c, attach.c: + You should never _ever_ do something like this: + + [process A] ---[piped write until EOF]---> [process B] + [process A] <---[piped read until EOF]--- [process B] -- [patch-0.88.8.kd.help_length.1] fix to truncate macro descriptions in the - help menu at the screen edge, and updated docs with new short function - descriptions + Basically, what happens is something like this: A + feeds data to B; B processes the data, and feeds it + to the pipe until the pipe buffer is full; at this + point, A writes to its pipe until its buffer is full + too, and if it still has more data to write, that's + it, it never gets to the read part to flush B's + buffer --- both processes are blocked on write. -- increased size of buffer used to store regepxs for the *-hook commands - from SHORT_STRING to STRING + This patch fixes such a situation in the compose menu. -Changes since 0.88.9 --------------------- + (From: Liviu Daia ) -- [patch-0.88.8-bugfix.buffy_size.mtsirkin.1] missed patch from previous - buffy_size fix +Mon Jul 20 21:01:05 1998 Thomas Roessler + + * reap.pl: Perl lies in /usr/bin on my machines. -- [patch-0.89.9.bl.fcc_fix.1] body of message was not written out for fcc - and postponement + * pop.c: It seems that if you don't enter any + password at all when prompted for the POP password, + Mutt will die with a segmentation fault also. (Bug + reported by Steve Mayer via the + Debian bug tracking system, fix from Thomas + Roessler.) + + * postpone.c: When you send a message which have + been postponed before sending, then all its + attachments (if there are more than one) will have a + content-disposition header which includes a + filename, even if there isn't a real filename but + only random choosen temporary one. (From: Byrial + Jensen ) + +Sat Jul 18 09:18:31 1998 Thomas Roessler + + * recvattach.c: "Set mime_forward, and forward a + message --- Mutt will segfault." The obvious fix for + this is to check for aptr->content->hdr in + mutt_attach_fmt() before invoking + _mutt_make_string(). Anyway, I suspect that the + real fix may involve something like parsing the + rfc822 attachment in question. + + * sendlib.c: Postponing messages behaves funny when the $postponed + folder is in Maildir format; I traced this down to the + fact that postponed messages are saved in "cur" while + mutt_num_postponed() is looking at "new". + (From: Liviu Daia ) + +Fri Jul 17 08:37:02 1998 Thomas Roessler + + * compose.c: Removing the old snd_entry() code. + + * doc/manual.sgml, protos.h, pgp.c, mutt.h, init.h, hook.c: + When sending encrypted messages, it may arrive that Mutt + can't determine the PGP key of the recipient (presumably + because her address has changed, but she hasn't updated + her PGP key yet). In this situation it's convenient to be + able to associate a keyID with an address automatically. + The attached patch is an attempt to implement this idea + using a "pgp-hook". (From: Liviu Daia ). + + * recvattach.c: Removing the old attach_entry() code. + + * recvattach.c, protos.h, mutt.h, init.h, globals.h, compose.c: + This patch adds a string variable $attach_format which + controls the look of the compose and attach menus. + Unfortunately, I was not able to make things so that it + would look exactly the same as the hardcoded versions, so + the default format is a bit different, but I think it is + quite usable. (From Michael Elkins ). + + * functions.h, browser.c, OPS: + This patch allows you to view files from the browser + window, useful if you are searching for a file to attach + to your message. It uses the standard mailcap stuff (and + the lookup mime types) to use the correct "viewer" for the + file. (From Brandon Long ) + + * doc/Attic/dotlock.man.in, doc/Makefile.in, configure.in, configure, Makefile.in: + Dotlock-related changes: We call it mutt.dotlock to avoid + conflicts with certain NFS versions' dotlocking utilities + (pointed out by Liviu Daia). Additionally, we need to + compile it as an external utility on systems which don't + have an fchdir(2) system call. + +Thu Jul 16 16:39:53 1998 Thomas Roessler + + * mx.c: Fixing a small typographic error. + + * mx.c: Mutt doesn't retry locking if it doesn't succeed at once. + The code in mx_lock_file is supposed to retry but it + doesn't work because of a mistake in operator precedence. + (From: Petri Kaukasoina ) -- [patch-0.88.9i.me.copy.1] created unified functions to copying/appending - messages. adds $forw_decode, $forw_quote, decode-save and decode-copy + * Attic/dotlock.c: + The dotlock.c file tries to include if + _POSIX_PATH_MAX isn't defined but it doesn't include + , where this symbol should be defined. (From + Marc.Baudoin@solsoft.com) -- [patch-0.88.9.me.refresh.1] use mutt_refresh() instead of refresh() in - mutt_enter_string() + * send.c: When several messages are tagged and the user applies + reply, group-reply, or list-reply to these messages, the + reply's references and in-reply-to headers are constructed + from the tagged message which comes last in the current + index. This patch constructs the references header from + _all_ messages' message-id and references headers. (tlr) -- with $edit_hdrs, if you delete the in-reply-to: field Mutt will - automatically remove the References: field as well + * reldate.h, configure.in, configure, Changes, ChangeLog: + Preparing mutt 0.94. -- mutt_query_exit() should call timeout(-1) so the prompt doesn't abort. + * imap.c: "My two remaining issues are the speed at which it + downloads the headers, and support of PREAUTH. I'm + enclosing a patch (to stock mutt-0.92.13i) which addresses + these issues." (From Brian Marcotte + ) -- [patch-0.88.9.me.fcc.1] removed the fcc-hook command + * color.c: This patch fixes two problems reported on mutt-users. -- the return value of mutt_send_message() was not checked so if sending mail - failed for some reason (like a full $tmpdir or error invoking $sendmail), - Mutt would incorrectly report that the mail had been sent + (1) the error message about "default colors not supported" + when not using a color xterm should not be printed. The + existing code did not check the value of has_colors() in + conjunction with use_default_colors() -- [patch-0.88.9.me.pseudo_thread.1] fixed problem with rethreading messages - with no real reference when new mail arrives + (2) mutt would crash when sending mail in batch mode + because use_default_colors() could be used without doing + an initscr() -- [patch-0.88.9i.kd.first_entry.1] fixed segfault on first-entry function if - there are no entries in the menu + (From Michael Elkins.) -- added a section to the doc describing the features of $edit_hdrs (fcc:, - attach: and references-magic) +Wed Jul 15 17:15:46 1998 Thomas Roessler -- [patch-0.88.bj.browser.1] fixed some problems with the file browser + * mx.h, mx.c, main.c, Attic/dotlock.h, + Attic/dotlock.c, configure.in, configure, + Makefile.in: Finalizing the external dotlock + support: If group mail privileges are needed, the + dotlock is compiled as a separate program. If + there is no need for privileges, it remains a + module which is compiled into mutt. Also, there is + no more need for the SLang buffer overflow + work-around in main(). We drop it, but let mutt + bail out instead if it's installed setgid + something. -Changes since 0.88.10 ---------------------- + * doc/Attic/dotlock.man.in, Attic/dotlock.c: + Fix the race condition in dotlock.c. -- return is now bound to `tag-entry' for the alias menu + * doc/Attic/mutt.man.in: + Putting the manual page under autoconf control. -- configure --with-homespool is now equivalent to --with-homespool=mailbox + * doc/Attic/mutt.man.in: + file mutt.man.in was initially added on branch mutt-0-94. -- [patch-0.88.10.me.invoke_sendmail.1] remove check for return value of - invoke_sendmail() since mutt_system() always returns -1 on some systems + * doc/mutt.man: Putting the manual page under autoconf control. -- [patch-0.88.10.me.push_refresh.1] fixed bug with mailbox parsing status - not being displayed if the user has a `push' command in their muttrc or in - a folder-hook + * doc/Attic/dotlock.man.in: + Adding external dotlocking. For bugs, see the manual page + and the comments in dotlock.c. -- [patch-0.88.10.de.thread-commands.1] cleans up the subthread operations + * doc/Attic/dotlock.man.in: + file dotlock.man.in was initially added on branch mutt-0-94. -- [patch-0.88.10i.de.sort_case.1] sorting by subject/author should be case - insensitive + * doc/Makefile.in, protos.h, mx.c, mbox.c, main.c, globals.h, Attic/dotlock.h: + Adding external dotlocking. For bugs, see the manual page + and the comments in dotlock.c. -- [patch-0.88.10.me.pipe_attach.2] piping attachments did not work + * Attic/dotlock.h: + file dotlock.h was initially added on branch mutt-0-94. -- [patch-0.88.10.kd.doc_nit.1] fixed doc bug wrt $forw_quote + * Attic/dotlock.c: + Adding external dotlocking. For bugs, see the manual page + and the comments in dotlock.c. -- manual.html readded to the `all' target in doc/makefile + * Attic/dotlock.c: + file dotlock.c was initially added on branch mutt-0-94. -Changes since 0.88.11 ---------------------- + * configure.in, configure, Makefile.in: + Adding external dotlocking. For bugs, see the manual page + and the comments in dotlock.c. -- changed default binding of pipe-entry to `|' in the compose menu + * doc/mutt.man: More roff fixes. -- changed default binding of filter-entry to `F' in the compose menu + * doc/mutt.man: More groff fixes. -- auto_view was not used when decoding messages with $pipe_decode set +Tue Jul 14 16:01:07 1998 Thomas Roessler -- piping messages did not use the new mutt_copy_message() function + * reldate.h, configure.in, configure, Changes, ChangeLog: + Preparing mutt 0.93.1i. -- use AC_REPLACE_FUNCS for check of strcasecmp() instead of AC_CHECK_FUNCS + * rfc2047.c, mime.h, handler.c: More unsigned fixes. -- [patch-0.88.11.me.copy_header.1] fixed problem when message header is - terminated by CRLF instead of just LF + * pattern.c, parse.c: + Changing (int) casts in is* arguments to (unsigned char). -- [patch-0.88.11.de.reverse_name.1] $reverse_name should override a default - `my_hdr' command + * rfc2047.c: Removing a superfluous (unsigned char) cast in an IsPrint + argument. -Changes since 0.88.12 ---------------------- +Mon Jul 13 10:50:39 1998 Thomas Roessler -- [patch-0.88.12.me.broswer.1] fixed bug in status line for generic menu - code, and added entry numbers so that `jump' can be used effectively in - the file browser + * doc/mutt.sgml, doc/mutt.man, doc/Makefile.in: + Since manual page generation seems to be broken in the + SGML-tools package, we remove the SGML version of mutt.man + and make the troff source the master copy. Suggested by + Roland Rosenfeld who also provided + the corrected mutt.man file. -- [patch-0.88.12.me.attach_reply.1] fixed segfault when replying to a single - message/rfc822 attachment +Sun Jul 12 13:15:31 1998 Thomas Roessler -- [patch-0.88.12.kd.alias_redraw.1] fixed redraw bug when exiting the alias - menu + * protos.h: Replace calloc by safe_calloc in new_pattern. -- [patch-0.88.12.kd.help_wrap.2] fixed display of long macros in the help - display +Sat Jul 11 05:10:29 1998 Thomas Roessler -- [patch-0.88.12.kd.resort.1] cause a resort on ':set sort=xxx' + * doc/manual.txt, doc/manual.sgml: Key bindings documentation. -- fixed bug where it was impossible to search for strings with any of - !, ~ or | in them +Fri Jul 10 17:58:26 1998 Thomas Roessler -- removed prototype for mutt_new_address() in rfc822.h since it is a macro + * NEWS: s/fwd_decode/forward_decode/ (Noted by Lars Hecking) -- added doc blurb for $forw_decode + * pop.c: tmp[] wasn't initialized when asking for the POP password. -- optimized loop for marking messages as `old' by checking if OPTMARKOLD is - set before entering the loop + * buffy.c: On SunOS 4.1, one must include unistd.h in order to + declare SEEK_END. (Fabrice Noilhan) -- $timeout should only affect the first keystroke of a multi-key command in - the `index' menu + * mutt.h: include if limits.h doesn't defile + _POSIX_PATH_MAX. -Changes since 0.88.13 ---------------------- + * Changes, ChangeLog: *** empty log message *** -- [patch-0.88.13.me.date.1] fixed problems with the date (~d) pattern - matching code + * doc/PGP-Notes.txt: Adding a notice about core dumps. -- [patch-0.88.13.me.send.2] fixed some deficiencies in replying to tagged - messages + * reldate.h, README, INSTALL: Preparing 0.93i. -- fixed segfault when downloading POP3 mail + * handler.c: Fix text/enriched decoding: if there's a tag mismatch in + the last paragraph in the attachment, the whole paragraph + wouldn't be displayed. -- [patch-0.88.13.me.cache.1] fixed problem with search cache when status - flags on messages change +Thu Jul 9 19:51:36 1998 Thomas Roessler -- [patch-0.88.13.me.fcc_hook.1] restored the fcc-hook command + * configure.in, configure, Attic/config.sub: + Use CC -Ae -D_HPUX_SOURCE on HP/UX. + * Attic/config.sub: + file config.sub was initially added on branch mutt-0-93. -PGP related changes since 0.88.13i ----------------------------------- + * Attic/config.guess: Use CC -Ae -D_HPUX_SOURCE on HP/UX. -- [patch-0.88.13i.tlr.pgp3_fingerprint.1] Code clean-up - with respect to PGP version 3 fingerprints. + * Attic/config.guess: + file config.guess was initially added on branch mutt-0-93. -- [patch-0.88.13i.tlr.pgp_invoke.1] New PGP invocation - code which enables PGP 5 to check signatures and will - make the integration of other PGP implementations with - mutt easier. + * INSTALL: Use CC -Ae -D_HPUX_SOURCE on HP/UX. -Changes since 0.88.15 ---------------------- +Wed Jul 8 21:59:43 1998 Thomas Roessler -- [patch-0.88.14i.ds.flagdoc.1] fixed the description of the flags in - $hdr_format in the manual + * snprintf.c, pattern.c, parse.c, mx.c, mh.c, lib.c, keymap.c, init.c, from.c, edit.c, curs_main.c: + Changing (int) casts in is* arguments to (unsigned char) + casts to avoid mis-casting of signed chars. (From Michael + Elkins.) -- messages were not included in replies in the non-PGP version of Mutt +Tue Jul 7 09:22:40 1998 Thomas Roessler -- [patch-0.88.15.me.reply_attach.1] fixed segfault when using replying to an - attachment from the `attach' menu + * rfc822.c: Change one int to size_t in rfc822.c. -- [patch-0.88.15.me.followup.1] fixed bug in generation of the - mail-followup-to: field + * rfc822.c: Fix the parsing of route addresses a la RFC 822. Patch + from Michael Elkins. -- [patch-0.88.15.me.ret_val.1] fixed some unchecked return values from - mx_open_new_message() and mx_append() + * snprintf.c, sendlib.c, pattern.c, parse.c, mx.c, mh.c, lib.c, keymap.c, init.c, from.c, edit.c, curs_main.c: + Cast the arguments of the is* functions to int. Patch + from Michael Elkins. +Thu Jul 2 21:15:18 1998 Thomas Roessler -PGP related changes since 0.88.14i ----------------------------------- + * hdrline.c: + Using the correct version of O'Shaughnessy Evans' %O patch. -- [patch-0.88.14i.tlr.pgp_cleanup.1] Random clean-up + * configure.in, configure, Changes, ChangeLog: Preparig 0.92.14i -- [patch-0.88.14i.tlr.pgp_flags.2] Display key - capabilities as ls(1) style flags on the key selection - menu. + * doc/manual.txt, doc/manual.sgml: s/∖/\/ -- [patch-0.88.14i.tlr.pgp_invoke.1] Fix a typo in - pgpinvoke.c. + * hdrline.c: Adding the %O expansion. -- [patch-0.88.14i.tlr.pgp_long_ids.1] Introduces a - pgp_long_ids option. If set, 64 Bit Key IDs will be - passed to PGP. - -- [patch-0.88.14i.tlr.pgp_sendkey.1] Fixes a segmentation - fault when sending PGP keys. + * doc/manual.sgml: Applying the various manual_nits patches. -- [patch-0.88.14i.tlr.pgp_tempfiles.2] Cleans up a - temporary file leak in the PGP code. +Wed Jul 1 17:01:50 1998 Thomas Roessler -Changes since 0.89 ------------------- + * curs_main.c: Fixing a reverse-threading problem. -- [patch-0.89i.de.no_subj.1] fixed possible coredump on NULL subject + * imap.c: Fixing an imap-related segmentation fault. -- [patch-0.89i.tlr.snprintf.1] added unsigned hexadecimal support to the - supplied snprintf() routine +Tue Jun 30 06:38:02 1998 Thomas Roessler -- [patch-0.89.bl.rfc1524_ws.1] fixed problem with whitespace in mailcap - entries + * reldate.h, Changes, ChangeLog: + These are the last tiny bits of preparing 0.92.13i. -- [patch-0.89.bj.slang10config.1] fixed configure script to work with - slang-1.0 beta + * configure.in, configure, TODO, README, NEWS: + Updating some of the documentation for 0.93. -- [patch-0.89.bugfix.buffycheck.mtsirkin.1] fixed bug with buffy - notification not being updated when entering a mailbox + * doc/Attic/NEWS: *** empty log message *** -- when compiling with slang, set ESCDELAY to 300 because the default is too - fast for slow terminals (this is what ncurses uses by default) + * doc/Attic/NEWS: file NEWS was initially added on branch mutt-0-93. -- [patch-0.88.13i.de.buffy_notify.1] fixed problem with new mail - notification in the current mailbox being clobbered by notifications in - other mailboxes + * doc/manual.txt: Incorporate the recent changes to manual.sgml. -- truncated the ChangeLog to entries after version 0.88 + * main.c: Work around a buffer overflow in SLang. (This is the same + bug which is fixed by 0.91.2i.) -- [patch-0.88.14.tlr.msg_7bit.1] fixed problem with $mime_fwd +Fri Jun 26 10:31:28 1998 Thomas Roessler -- [patch-0.89.bj.set_followup_to.1] the user's address was added to the - mail-followup-to field if $metoo is set + * doc/manual.sgml, send.c, init.h, globals.h, Muttrc.in: + Removing $empty_to. -PGP related changes since 0.89i -------------------------------- +Thu Jun 25 22:31:46 1998 Thomas Roessler -- [patch-0.89i.tlr.pgp_sigvrfy.1] When verifying PGP/MIME - signatures, the LF -> CRLF could fail under certain - circumstances. + * hdrline.c: Moved a break statement where it belongs. -- [tlr] Some long -> unsigned long changes in the pgp code - which are more of an aesthetical nature. + * mx.c: Fix an imap-related typo. -- [tlr] The default of the $pgp_strict_enc variable has - been changed to "set". + * handler.c: Don't generate non-terminated last lines when quoting + 8bit-"encoded" text-plain body parts. -- [tlr] pgp-Notes.txt has been somewhat extended. + * Makefile.in: Don't use GNU make specific features. -Changes since 0.89.1 --------------------- +Sun Jun 21 07:13:03 1998 Thomas Roessler -- [patch-0.89i.me.pointer.1] fix to use `unsigned long' instead of `void *' - for arguments where the data may be either an integer or a pointer. this - was needed for 64bit systems where `sizeof(void*)!=sizeof(int)' + * doc/mutt.man, doc/Makefile.in, reldate.h, configure.in, configure, Changes, ChangeLog: + Bumping the release to 0.92.12i. -- [patch-0.89i.me.pattern_hook.4] the pattern matching language can now be - used in send-hook, save-hook and fcc-hook instead of a single regular - expression +Sat Jun 20 06:12:38 1998 Thomas Roessler -- [patch-0.89.bl.alter_weed.1] improves the mutlipart/alternative handler to - use auto_view, and adds viewing of MIME headers for attachments with - 'display-headers' + * doc/manual.txt: *** empty log message *** -- [patch-0.89.1.sec.expires_hdr.1] added support for the Expires: field. - auto-deletion of expiried messages is controlled with $expires + * handler.c: Fixing the quoted-printable decoder. -- [patch-0.89.1i.co.mailx.1] added feedback for the `~r' command in mailx - mode + * handler.c, copy.c: Make mutt handle messages containing null bytes. -- [patch-0.89.r.buf.1] buffer for backtic expansion of `mailboxes' was not - long enough + * doc/manual.sgml: documenting alias-path -- [patch-0.89.1i.de.mail_followup_to-leak.1] fixed memory leak in freeing - the mail-followup-to: field from the ENVELOPE struct +Fri Jun 19 12:52:16 1998 Thomas Roessler -- [patch-0.89.1i.de.list-reply-leak.1] fixed memory leak in the list-reply - function + * sendlib.c, send.c, protos.h, postpone.c, pattern.c, menu.c, main.c, headers.c, functions.h, curs_main.c, compose.c, OPS: + Removing the Attach-Menu feature for the next release + version. -- [patch-0.89.1i.de.send-menu-leak.1] fixed memory leak when attaching files - to messages +Thu Jun 18 20:37:59 1998 Thomas Roessler -- [patch-0.89.1i.de.remove_user.1] fixed bug in removing the user's address - from the list if it is the only recipient + * protos.h, lib.c, alias.c: + Bradon long's alias_path patch, for the sake of Elm + compatibility. -- [patch-0.89.1i.de.pattern-regexp-leak.1] fixed memory leak with regular - expression compiled by mutt_pattern_comp() were never free()d +Tue Jun 16 20:59:20 1998 Thomas Roessler -- [patch-0.89.1i.de.beep_new.1] adds the $beep_new variable to control - whether or not mutt will beep when new mail arrives + * mx.c: Avoid pointless error messages from mx_get_magic() when + called from an mx_open_mailbox_append() on a non-existing + mailbox. -- [patch-0.89i.de.fcc-save-hook.1] adds new command `fcc-save-hook' which - creates a hook for use with either fcc-hook or save-hook + * doc/manual.txt, doc/Makefile.in, configure.in, configure, Makefile.in: + Have "make install" install manual.txt as well. -- [patch-0.89.1i.de.buffy_sanity.1] fixes a problem with the buffy code + * doc/Attic/makefile, doc/Makefile.in: + Putting Makefile under autoconf control. -- restored blank line between the "----- Forwarded message from..." line and - the text of the message + * main.c: Switch the error reporting address from mutt-users to + mutt-dev. -- [patch-0.89.1i.de.tag-subthread.1] adds the `tag-subthread' command to the - pager + * reldate.h, configure.in, configure, Changes, ChangeLog: + Bump the version to 0.92.11i. -PGP related changes since 0.89.1i ---------------------------------- + * imap.h: Check in a proper version of imap.h. -- [patch-0.89i.dme.attach-key.1], [patch-0.89i.dme.extract-key.1] Fixes to - the PGP 5 invocation code. + * color.c: Fix the "unknown color" bug reported by Vikas. -- [patch-0.89.1i.tlr.pgp_extract.2] Fixes various problems with the PGP - code and attachment menu, in particular with respect to extracting keys. + * mx.c: Remove a spurious #include "imap.h" from mx.c. -Changes since 0.90 --------------------- + * doc/style-guide: Add a note about the global Muttrc to style-guide. -- [patch-0.90.me.sort.2] $sort_aux is now used for all primary sorting - methods + * configure.in, Muttrc.in, configure, Attic/Muttrc, Makefile.in: + The global Muttrc contains a list of default settings + which can be used as a starting-point for the user's own + configuration. -- [patch-0.90i.me.pattern.1] extended date matching language (~d) to accept - relative dates offset from the current date + * pgppubring.c, pgp.h, gnupgparse.c: + Removing some duplicate code from gnupgparse.c and + pgppubring.c. -- [patch-0.90.me.thread_hash.3] modified threading algorithm to use hash - tables instead of a linear search + * pgpinvoke.c, gnupgparse.c: + Include part of Werner Koch's latest GPG patches. -- [patch-0.90i.de.difftime.1] remove use of difftime() since it is not - portable + * Changes: *** empty log message *** -- [patch-0.89.1i.de-bj.buffy_sanity.1-2] cleanup of the buffy check routine - -- [patch-0.90.me.addr_pattern.1] fixed some problems with the address - matching routines which caused problems for the send-hook and fcc-hook - commands - -- the size of the temp buffer used to expand regexps into patterns in - mutt_check_simple() was too short (SHORT_STRING) to handle the - patterns for send-hook, save-hook and fcc-hook, so it was increased to - LONG_STRING (1024) bytes - -- [patch-0.90.me.safe_path.1] fixed segfault when trying to save a message - with no recipients - -- [patch-0.89i.de.index-percentage.1] adds `%P' to $status_format to display - the percentage of the menu already seen (similar to the way the pager - works) - -- [patch-0.89.1i.bj.pager-redraw-clenaup.1] fixed some redraw problems in - the pager with $pager_index_lines set - -- [patch-0.89.1i.fp.filter.1] screen was not updated when filtering an - attachment an the the cte changed - -PGP related changes since 0.90i -------------------------------- - -- [patch-0.90i.tlr.pgp_attach_keys.1] Fixes a core dump on - the compose menu when attaching PGP public keys. - -- [patch-0.90i.tlr.pgp_encrflags.1] There were several - points in the code where a message's pgp flag was - evaluated the wrong way (namely, ...->pgp == PGPENCRYPT - instead of ... & PGPENCR). - -Changes since 0.90.1 --------------------- - -- [patch-0.90.1i.tlr.hdrignore.1] fixed bug with weeding headers with the - CH_MIME bit set in mutt_copy_hdr() - -- [patch-0.90.1i.de.buffy-cleanup.1] cleaned up buffy to remove some - duplicated code and share some common global information - -- [patch-0.90.1i.arl.fcc-save.1] fixed some typos in the manual wrt to the - fcc-save-hook command - -- expansion of environment variables in mutt_extract_token() did not accept - underscore (_) as a valid value in variable names - -- fixed possible segfault in mutt_extract_token() if the result of a backtic - expansion was longer than the buffer used to store the expanded version of - the string - -- expansion of backtics is now option and controlled by whether or not the - `expn' argument in non-NULL. this is needed by eat_regexp() where we - don't want backtic expansion - -- the ->personal member of the address was not matched in match_adrlist() - -- [patch-0.90.1.me.hash.1] fixed bug in hash_delete_hash() where the wrong - entry could be deleted when the key matched, but had a different data - pointer even if the data pointer was specified in the call - -- changed default expansion for save-hook to '~f %s' and fcc/send-hook to - '~t %s | ~c %s' - -- the current search pattern was not invalidated if $simple_search changed - while in the middle of a search - -- [patch-0.90.1i.dme.nit-to_chars.1] fixed bug in docs wrt to $to_chars - -- added documentation for the `pattern_hook' patch - -- [patch-0.90.1.me.sort_to.1] adds support for sorting by the to: field with - `set sort=to' - -Changes since 0.90.2 --------------------- - -- [patch-0.90.2i.de.toggle-quoted-redraw.1] fixed redraw problem with the - toggle-quoted function - -- [patch-0.90.2.de.buffy_check.1] fixed problem with -Z option - -- [patch-0.90.2.de.buffy_times.1] fixed problem of buffy reporting new mail - when saving messags from within mutt - -- [patch-0.90.1i.bj.in-reply-to-decode.1] fix to rfc2047 decode the - in-reply-to field before extracting the message-id - -- [patch-0.90.2.me.resort.1] fix to resort mailbox with $sort_aux or - $strict_threads changes - -- [patch-0.90.2.de.pretty_size.1] fixed rounding error which could cause the - display to be more than 4 chars - -- [patch-0.90.2.me.score.3] adds scoring support - -- [patch-0.90.2i.jg.pipe_from.1] the `From ' line was missing when piping a - message - -- [patch-0.89.1i.bj.skip_quoted.1] adds a `skip-quoted' (default: S) - function to the pager - -- tag-prefix was broken in the generic menu code when $auto_tag was unset - -- fixed bug in mutt_extract_token() wrt expanding backtics (``) - -- [patch-90.2i.tlr.addrbook.1] fixes address book so that select-entry - returns the current or tagged messages and exits - -- ESCDELAY default for slang is used again instead of setting it to 300ms - -- added `~R' to match references in the mutt_pattern_comp() - -PGP related changes since 0.90.2i ---------------------------------- - -- [patch-0.90.2i.tlr.pgp-disptrust.1] The trust status of - a key-user id relation is always displayed on the key - selection menu. - -- [patch-0.90.2i.tlr.pgp-subkeys.1] Subkeys are always - referred to using the principal key's numerical user ID. - This seems to be necessary to make PGP 5.0 extract them - properly. - -- The bit count for DSA keys is now displayed correctly. - -- A new option pgp_language (default: "en") is introduced. - This can be used to achieve an effect similar to the - alt_pgp patch. See doc/pgp-Notes.txt for details. A - big Thank You to Roland Rosenfeld for this idea! - -Changes since 0.90.3 --------------------- - -- [patch-0.90.3.me.sort.1] fixed several bug relating to sorting by to or - score - -- %s in $status_format no longer includes $sort_aux, use %S to get the - $sort_aux value if desired (default value for $status_format now uses - (%s/%S) to mimic the old behavior) - -- [patch-0.90.3i.tlr.addrbook.1] fixed bug selecting the first alias in the - address book display - -- fixed bug in create-alias where mutt would dump core on a message with a - malformed address - -- parse_date() now always returns -1 on error - -- mailbox was not rethreaded when $sort_re changes - -- [patch-0.90.3.de.I_DECL.1] changes a few remaining variables in init.h to - the new I_DECL format - -- since most of the pattern matching commands were `envelope' types, changed - the semantics so that header and body matching are only done if the - M_FULL_MSG flag is set with mutt_pattern_comp() - -- backslash quoting did not work for the folder-hook and send-hook commands - -- use mutt_mktime() instead of mktime() in is_from() - -- [patch-0.90.3i.bj.skip-quoted.2] fixed bug in the skip-quoted function - -- [patch-0.90.3i.me.attach_pager.1] allows use of save/pipe/next/prev while - viewing attachments from the attach or compose menus - -- mutt_gen_msgid() changed to use getpid() so that unique id's are created - when mutt is invoked quickly in batch mode - -- Mutt now reports an error if the file specified by the `-F' command line - option does not exist - -- [jkj@sco.com] adds the $meta_key boolean option to case 8bit input to be - delivered as ESC + the char with the hi bit stripped - -- [patch-0.90.3i.me.editor_ext.1] improved line editor to be able to handle - unprintable control chars and to be able to bind the completion character - -- [patch-0.90.2i.bj.copy_hdr.2] rewrite of mutt_copy_hdr() to do reordering - in a single pass and to correctly unwrap fields for rfc2047 decoding - -- moved mutt_copy_hdr() to copy.c, and mutt_print_message() to commands.c - and eliminated print.c - -- `mutt -v' now displays the release date along with the version number. - the release date is also displayed with the `display-version' function - - -PGP related changes since 0.90.3i ---------------------------------- - -- [patch-0.90.3i.tlr.pgpkeyssort.1] If two keys have the - same User ID (i.e., mail address), use the numerical key - ID as the second sorting criteria for the key selection - menu. - -- [patch-0.90.3i.doc_pgp.1] Documentation for the PGP - support. (By Roland Rosenfeld - ). - -Changes since 0.90.4 --------------------- - -- [patch-0.90.4i.bj.show_version.1] reduce code size required to print - compile time options - -- fix so that specifying more than two -v's on the command line always - prints the copyright statement instead of ignoring them - -- [patch-0.90.4.me.veryclean.1] adds a `veryclean' target to the Makefile to - remove files created by `configure' - -- the `inv' prefix now works for quadoptions - -- [patch-0.90.4.me.editor.1] adds `quote-char' function, and displays - control chars with the `markers' color, fixes bug in `buffy-cycle' - -- [patch-0.90.4i.me.unscore.1] adds the `unscore' command - -- [patch-0.89.1i.bj.tag-save.1] fixed bug in tag-save command - -- [patch-0.90.4i.me.help.1] added mutt_compile_help() to generate help - strings from `struct mapping_t' - -- [patch-0.90.4i.bj.hdr_fmt_recv.1] adds the %(fmt) to $hdr_format to - display the received time of a message - -- [patch-0.90.4i.bj.compose-disp-hdrs.3] fixes bug wrt to header weeding - with display-headers in the compose menu - -- [patch-0.90.4i.bjdeme.time.1] fixed calculation of local timezone and - added speedup when parsing mbox/mmdf mailbox and calculating the received - time from the `From ' line - -- added `flag' argument to mutt_pattern_exec() so that the - M_MATCH_FULL_ADDRESS option could be passed so that searching will match - the real name while the *-hook commands will not - - -PGP related changes since 0.90.3i ---------------------------------- - -- [patch-0.90.3i.tlr.pgpkeyssort.1] If two keys have the - same User ID (i.e., mail address), use the numerical key - ID as the second sorting criteria for the key selection - menu. - -- [patch-0.90.3i.doc_pgp.1] Documentation for the PGP - support. (By Roland Rosenfeld - ). -Changes since 0.90.5 --------------------- - -- [patch-0.90.5i.me.new_addr.1] replaces rfc822 address parser and related - data structures - -- [patch-0.90.5.bj.parse-speedup.new_addr-2] rewrite of - mutt_read_rfc822_line() and mutt_read_rfc822_header() to be more efficient - -- [patch-0.90.5i.me.hash_ext.1] added support for unique keys in the hash - table, and optional argument to the destroy functions to free the - associated data - -- [patch-0.90.5i.me.alias_sort.1] the sorting method and alias menu format - are now configurable via $alias_sort and $alias_format, respectively - -- [tlr] mx_open_mailbox() did not correctly free the created CONTEXT struct - upon failure - -- created function mutt_version() to display Mutt's version number - -- [patch-0.90.5i.rc.exactcompile.1] fixed warning about unused function when - compiling with `#undef EXACT_ADDRESS' in rfc822.c - -- [patch-0.90.5.sec.expires_new.1] adds ~S and ~E to match superceded and - expired messages - -- [patch-0.90.5.me.decode_followup.1] addresses in mail-followup-to: were - not rfc2047 decoded - -- [patch-0.90.5.bj.manual-nits.1] adds missing docs relating $status_format - -Changes since 0.90.6 --------------------- - -- [patch-0.90.6.me.unwrap_line.1] fixed bug in read_rfc822_line() wrt to - unwrapping folded lines - -- [patch-0.90.6.co.exactadd.1] fixed botched #ifdef in rfc822.c when - compiling with EXACT_ADDRESS - -- [patch-0.90.6i.jg.supersedes.2] changed `supercedes' to `supersedes' as - described in the current mailext I-D - -- added blurb on `--enable-exact-address' to the INSTALL file - -- fixed bug where messages with invalid dates showed up as being sent on Dec - 31, 1969 - -- added '-e' command line option to specify a config command to be run - _after_ parsing of initialization files - (eg. mutt -e 'set edit_hdrs' mutt-dev) - -- added `edit-from' function to the `compose' menu (the From: field is now - also displayed) - -- added real bounds checking to rfc2047_encode_string() and friends - -- [tlr] fixed several bugs in the rfc2047 `Q' encoding (tabs were not - encoded, chars with hex value less than 0x10 were not padded with 0, =? in - a string was not encoded) - -- [patch-0.90.6.bugfix.locktimeout.1] added optional timeout to the locking - code so that the check for new mail will not to acquire a lock wait while - large mail is being delivered - -- [fvl] mutt_get_name() would segfault if a NULL address was passed in - -- [patch-0.90.6i.de.old-unread.1] adds %o and %u to $status_format to allow - display the number of `old' and `unread' messages - -- [patch-0.90.6.co.fwd.1] adds a blank line before the `---End of forwarded - message' line - -- the confirmation prompt for bounce-message will now only display the - address without the personal name to conserve space - -- [vl] arg to isspace() was not cast to `unsigned char' in rfc822.c - -- updated the pattern matching functions to add the following operators: - ~p matches personal mail (finds $alternates in to: or cc:) - ~l matches mail addressed to `lists' - ~L finds in to:, cc:, from: or sender: - ~C finds in to: or cc: - - -PGP related changes since 0.90.6 --------------------------------- - -- [patch-0.90.5i.rs.pgp_hdr.1] Preserve a message's PGP - settings when postponing - -Changes since 0.90.7 --------------------- - -- included state.h, list.h, send.h in mutt.h and removed the others from the - distribution - -- [patch-0.90.7.me.default_from.1] - -- [patch-0.90.7i.de.limit.1] full name in addresses was not matched for `limit' - -- [patch-0.90.6.bugfix.locktimeout.1-2] changed `timeout' to `retry' in the - locking code since the former was misleading - -- [patch-0.90.7i.jg.help_line.1] offset of attachment was not calculated - correctly in the compose menu, cause the help line to be overwritten - -- fixed memory leak in rfc822_parse_address() when a parse error occurs (the - previously parsed address list was not returned and not freed) - -- [patch-0.90.7.me.vsnprintf.1] fixed bug where existence of snprintf() - assumed the existence of vsnprintf() - -- create-alias suggested the full email address as the default alias name - instead of just the mailbox portion - -- documented the `score' and `unscore' commands, and added %N to the - $hdr_format description - -- [patch-0.90.7i.bj.fgets_nit.1] size of buffer passed to fgets() was - incorrect - -- [patch-0.90.7i.bj.read_line.1] create common function mutt_read_line() for - reading lines which may contain a backslash on the end to wrap to the next - line - -- [patch-0.90.7i.bj.source_rc.1] makes source_rc() use the new - mutt_read_line() function - -- [patch-0.90.7.bugfix.buffycheck.mtsirkin.1] fixed another problem with - buffy - -- [patch-0.90.7.me.group_addr.1] fixed segfault when $use_domain is set and - you try to send to a group mailbox address - -- you can now use `mono normal' to set to normal attribute - -- [patch-0.90.7i.de.hook.2] adds the $default_hook variable to control the - expansion of `simple' patterns in the send-hook, fcc-hook and save-hook - commands - -- it was not possible to use the $hdr_format sequences in $indent_str when - the switch to the new mutt_copy_message() and mutt_copy_hdr() - -- new common function km_get_table() which retrives the mapping of function - names based upon the MENU_* value - -- [patch-0.90.7i.bj.mailcap_parse.1] rewrote the mailcap parsing routines to - fix some bugs and be more efficient - -- [mac@eecg.utoronto.ca] added the `search-opposite' to search for the - current pattern in the opposite direction from the last search - - -Changes since 0.90.8 --------------------- - -- [patch-0.90.8.bj.display_loop.1] toggle of header weeding in the attach - and compose menus did not work - -- [patch-0.90.8.bj.manual_nit.1] documentation for displaying recieve date - in $hdr_format was missing - -- [patch-0.90.8.bj.pager_compile_help.1] pager did not use new function - mutt_compile_help() - -- [patch-0.90.8.bj.rename_file.1] changes mutt_rename_file() return codes - to be consistent with rename() - -- [patch-0.90.8.me.search.1] was not possible to bind the search functions - in the pager - -- [patch-0.90.8.me.time.1] fixed bug with the `~d >N' pattern - -- [patch-0.90.8.bj.reading_attachments.1] switching between viewing - attachments without returing to the attach menu was broken - -- [patch-0.90.8.bj.SKIPWS.1] removed unnecessary check for \0 in the - SKIPWS() macro - -- dest->fp was used directly in mx_open_new_message() where it should have - used msg->fp - -- `shell-escape' was moved to the generic keymap so that all menus can make - use of the function - -- added documentation on the `search-opposite' function - -- [patch-0.90.8i.tlr.rfc1524_fclose.1] fixed bug where fclose() could be - called with a NULL argument - - -PGP related changes since 0.90.7 --------------------------------- - -- [patch-0.90.7i.bj.pgp_hdr.1] Fixes some nits in - conection with the pgp_hdr patch. - -- [patch-0.90.7i.rs.pgp_hdr_doc.1] Adds documentation for - the pgp_hdr patche's effects. - -- [patch-0.90.7i.tlr.pgp_keysel.1] Fixes uniqueness - problems with the pgp key selection code. - -- [patch-0.90.8i.rr.pgp_get_table.1] The help function - wouldn't work on the PGP key selection menu. - -- [patch-0.90.8i.tlr.pgp_asymm.1] This patch replaces the - pgp_version variable by three variables: - pgp_receive_version, pgp_send_version, pgp_key_version. - -- [patch-0.90.8i.tlr.pgp_micalg.1] This patch enables the - user to generate correct "micalg" parameters when - composing PGP/MIME signed messages. - -Changes since 0.90.9 --------------------- - -- [patch-0.90.9.me.personal_hook.1] fixed bug where ~P in send-hook patterns - did not work - -- [patch-0.90.9i.tlr.mutt_add_list.1] mutt_add_list() could create memory - which was unitialized to 0 - -- [patch-0.90.9.me.group_alias.1] fixed bug where group address names were - expanded if a matching alias was found - -- definition of SKIPWS() in rfc822.c changed to match that in protos.h - -- [patch-0.90.9.josh.write_percent.1] the %-done is now shown when writing - out mbox/mmdf mailboxes just as is done for reading - -- body of message was not quoted with $indent_str if $forw_quote was set, - but $forw_decode is unset - -- changed initial value of $default_hook to "~f %s !~P | (~P ~C %s)" - - -PGP related changes since 0.90.9i ---------------------------------- - -- [patch-0.90.9i.tlr.pgppath.1] Properly check whether - PGPV2PATH and PGPV3PATH are defined in init.c. - -- [patch-0.90.9i.rr.pgp_key_version.1] Fixes a typo in the - pgp_key_version entry in init.h. - -- configure.in has been fixed so that _PGPPATH is not - defined unless at least one version of PGP exists on the - system. - -- A +nobatchinvalidkeys=off parameter has been added to - the pgpe invocation in pgpinvoke.c. -Changes since 0.90.10 ---------------------- - -- added check for empty string arguments to the bind and macro commands - -- moved bit fields in CONTEXT and BODY structs to the end of the struct def - since there were not enough bits to fit into a 32-bit word - -- split include_message() into include_forward() and include_reply() since - little code was shared for the two cases - -- $forw_decode no longer controls weeding of the header when replying and - $headers is set - -- added doc blurb for $mime_fwd on the effects of decoding when this - variable is unset - -- [patch-0.90.10.me.unread.1] fixed error in calculation of unread messages - when the `new' bit is cleared from a message - -- fixed y2k problem in ~d pattern - -- an error was reported in the ~d pattern if using the open-ended form (eg. - 1/1/98-) and any more text followed the pattern - - -PGP related changes since 0.90.10i ----------------------------------- - -- mutt -v now correctly displays the various PGPPATH - variables. -Changes since 0.90.11 ---------------------- - -- [patch-0.89.1i.bj.enriched.1] fixed buffer overflow in the text/enriched - handler - -- [patch-0.90.10.bl.sort_alias.1] adds the `unsorted' method for $sort_alias - -- [patch-0.90.10i.co.reply_regexp.1] changed initial value for $reply_regexp - to catch the `Re[2]:' style - -- changed check for new mail in MH-style mailboxes to consider messages new - if mtime >= atime - -- forwarded messages with $mime_fwd set are no longer forced to 7-bits when - not using PGP - -- updated the NEWS file with comments from the dev list - -- [patch-0.90.11i.de.stdin.2] fixed bugs with using stdin for -i or -H - command line arguments - -- [patch-0.90.11i.de.safe_fopen.1] changed many instances of fopen() to - safe_fopen() to avoid tempfile race conditions - -- the generic menu code did not print "Tag-" when using tag-prefix - -- [0.90.11-vikas.doc_nit] fixed bug with use of > in the description of - $status_format - -- [patch-0.90.11i.ds.man_tilde_nit.1] fixed use of ~ where ˜ should - have been used in manual - -- [patch-0.90.11i.rr.date_received.1] the parser table for ~r in the pattern - language used eat_regexp() instead of eat_date() - -- [patch-0.90.11i.me.attach_reply] fixes reply/forward of (tagged) - attachments from the attach menu - -- [patch-0.90.11.bj.make_string.1] fixes display of control chars and other - non-printable chars in the $*_format variables - -- [patch-0.90.11i.tlr.cdisp.2] fixes message_to_7bit() to not destroy the - existing content-disposition `filename' information - -- fixed bug in rfc822 parser where quoted-pair was not accepted in the - `mailbox' or `domain' tokens - - -PGP related changes since 0.90.11i ----------------------------------- - -- [patch-0.90.11i.roro.doc.1.gz] Added some more PGP - documentation. Spelling and grammar corrections from - native speakers are welcome! -Changes since 0.90.12 ---------------------- - -- [patch-0.90.11i.me.boundary.1] mutt_write_mime_body() did not use - mutt_get_parameter() to fetch the MIME boundary - -- [patch-0.90.12i.tlr.recall.1] fixed segfault when attempting to recall - postponed messages - -- [patch-0.90.12i.rr.hdrline.1] fixed misapplied patch for the make_string - support - -- fixed error message on nonexistant file specified with -i or -H - -- [patch-0.90.12.me.safe_fopen.1] safe_fopen should not be used when it is - desirable for the specified file to be overwritten - - -PGP related changes since 0.90.12i ----------------------------------- - -- [patch-0.90.12i.maj.pgp_extract_keys_nit.1] Correct the - behaviour when typing C-K in an empty folder. -Changes since 0.90.13 ---------------------- - -- [patch-0.90.13i.de.enter_fname.1] buffy-cycle should act like complete - when in the save/copy message prompts - -- [patch-0.90.13i.rr.normalize_time.1] mutt_normalize_time() didn't handle - the case where a date rolled over to the previous year when selecting by - number of months in the past - -Changes since 0.91 ------------------- - -- fixed bug in rfc822_parse_adrlist() where it would segfault on a bad address - which contained only a comment - -- [patch-0.90.12i.tlr.recall.1] fixed segfault when attempting to recall a - postponed message which was a reply to another message - -- [patch-0.91.me.exit_main.1] fixes collision in function name for "exit" in - the "generic" and "index" keymaps - -- corrected documentation on $hdrs which erroneously stated that user defined - headers are never included in batch mode sending - -Changes since 0.91.1 --------------------- - -- [patch-0.91i.me.dyn_str.2] changes global string variables to `char *' - instead of fixed size arrays, and moves defaults for variables to the - MuttVars[] array - -- [patch-0.91.me.format_string.1] creates common function - mutt_FormatString() for handling %-substituted strings in a generic manner - -- [patch-0.91.vikas.limit_size.4] adds %L to $hdr_format to display the - total size of all visible messages when limited - -- [patch-0.91.me.followup.1] Adds boolean $followup_to to control - generatation of the Mail-Followup-To field. Also allows user to edit this - field and not have it overwritten. - -- [patch-0.91i.me.sendmail.1] Removes $sendmail_bounce. Mutt now passes all - recipients on the command line for normal sending. - -- [patch-0.90.10i.bj.current_time.1] adds sequence % to $hdr_format to - display the current time using strftime(fmt) - -- [patch-0.90.10.bl.alternative_order.1] allows user specification of the - order in which to choose types from multipart/alternative messages - -- [my_hdr-subject-patch2] allows specification of a default subject (if none is - given using the `my_hdr' command - -- [patch-0.91i.as.revname.1] makes $reverse_name look at from: if the message - you are replying to is from you - -- added new operator ~B to pattern matching language which matches a regexp - anywhere in a message (more efficient than ~h %s | ~b %s). - -- changed the `source' command to use mutt_open_read() instead of fopen() so - that you can read from the output of a script (eg. "source - ~/bin/mutt_commands|"). - -- fixed typos in the description of `forget-passphrase' in the manual - -- the -e option was not document in either the man page nor the manual - -- [patch-0.91.bl.composetyped.1] adds support for creating non-text body - parts from within the compose menu - -- $reverse_name is now handled before send-hook so that user's can match on - the from field with ~f - -- [patch-0.91i.de.threadlimit.1] allows drawing of thread trees while in - limited display - -- [mutt-0.89i-quadopt_mimefwd.patch] turns $mime_fwd into a quad-option - -- [patch-0.91i.jmy.folder_format.1] the display of the `browser' menu is now - configurable via the $folder_format variable - -- [patch-0.91i.jmy.pattern-size.1] adds ~z operator to the pattern matching - function to match by size - -- rfc822.c now uses some functions from mutt proper (safe_strdup and - mutt_substrdup) instead of attempting to be a self-contained library - - -PGP related changes since 0.91.1 --------------------------------- - -- [patch-0.91.1i.tlr.pgp_obsolete_vars.1] Removes the - obsolete pgp_v3_* variables. -Changes since 0.92 ------------------- - -- [patch-0.91.me.reuse_hook.1] the result portion of those hooks which can - have only a single matching pattern (ie. send-hook) were not updated if the - same pattern was specified with a different result. - -- [patch-0.92.me.empty_pop_str.1] fixes core when fetching POP3 mail if any - of the $pop_* string variables were empty - -- [patch-0.92.me.empty_route.1] - -- [patch-0.92.me.regexp_case.1] REG_ICASE was not set for regexp variable - defaults in mutt_restore_default() - -- [patch-0.92.de.threadlimitfix.1] fixes small bug in the threadlimit code - which could cause extra work to be done when not needed - -- [patch-0.92.me.format_pad.1] fixed segfault when the value of - $status_format is wider than the screen - -- [patch-0.92.me.draft_path.1] the paths for neither -i nor -H were being - expanded before use - -- [patch-0.92.vikas.nits] - 1. %M in $status_format was getting truncated after 3 digits because of a - tiny mistake in mu - 2. The ~z pattern matching has a small nit at the boundaries where - ~z<1024 matches Content-length: 1024 as well. I just changed the inclusive - ranges ( <= and >= ) to exclusive ranges ( < and > ) in pattern.c - 3. Added a line about the new %L format specifier for $status_format - - -PGP related changes since 0.92 ------------------------------- - -- No more (char *) deferences of (char **) in pgp_invoke.c. -Changes since 0.92.1 --------------------- - -- [0.92.1.me.format_pad.1] fixed another problem with the result of - subtracting two size_t's and the result being negative - -- [0.92.1.me.batch_copy.1] $copy was ignored when sending mail in batch mode - -- [patch-0.92.1.josh.sort_re-tilde.1] reset default values of $sort_re and - $tilde to their 0.91.1 values. - -- [patch-0.92.me.func_macro.1] changes function key names to use <> around - then (eg. ) and allows them to be used in macros as well - (eg. macro index Y *) - -- [patch-0.92.1i.rr.reset.2] adds the `reset' command and the `&' prefix to - `set' to allow resetting variables to the default value - -- changed the %g (group) and %u (userid) sequences of $folder_format to - print the gid and uid, respectively, if they can't be resolved to names, - instead of diplaying "(null)" - -- [patch-0.92.1i.me.sendmail_wait.2] adds $sendmail_wait which specifies the - number of seconds to wait for sendmail to finish before background it - -- [patch-0.92.1.co.bounce.2] fixes problem with the bounce-message - confirmation prompt - -- [patch-0.92.1.bl.attach_del.2] adds the ability to delete attachments - -- [patch-0.92.1i.jg.default_opts.2] changed var defaults to match what is in - the manual - -- [patch-0.92.1i.rr.no_signature.1] fixed segfault with - set signature='' - when composing mail - -- [patch-0.92.1i.rr.manual_nits.1] fixed some spelling errors in the manual - -- [mutt-0.91.1a.patch (partial)] if KEY_RESIZE is defined, mutt_getch() will - ignore it (generated by ncurses 4.2 on SIGWINCH) - -- [patch-0.92.1.bl.query.1] adds support for querying an external database - for email addresses - - -PGP related changes since 0.92.1i ---------------------------------- - -- [patch-0.92.1i.wn.verify_sig-pgp_timeout.1] Make the - verify_sig and pgp_timeout defaults consistent between - init.h and the manual. - -- [patch-0.92.1i.tlr.pgp_keysel.1] Fix a segmentation - fault in the key selection code. - -- [patch-0.92.1i.tlr.pgpsign.1] The PGP signing code works - again. - -- Changed $verify_sig to $pgp_verify_sig. -Changes since 0.92.2 --------------------- - -- [patch-0.92.2i.tlr.sendlib_args.1] fixes segfault when sending mail - -- [patch-0.92.2.me.reverse_name.1] fixed problem with $reverse_name altering - the HEADER struct for the message being replied to. - -- [patch-0.92.2.sort_flag.1] fixed problem with `score' command not updating - the score when $sort or $sort_aux was not `score' - -- [patch-0.92.2i.me.sendmail.1] adds debugging info to the send_msg() - command - -- [patch-0.92.2i.dme.generic-op_jump.1] fixed missing binding for 3-9 to - `jump' in the generic keymap - -- [patch-0.92.2.me.sort_alias.1] fixed problems with $sort_alias not working - -- [patch-0.92.2i.me.msg_search.1] fixed bugs in the ~h, ~B and ~b search - patterns - -- [patch-0.92.2i.me.postpone.1] x-mutt-references was not removed when - recalling a postponed reply when no mailbox is open - -- included for def of SEEK_SET in copy.c (SunOS 4.1.4) - -- [patch.sendlib.2] fixes signal handling in send_msg(), and fixes leftover - temporary files after sending the message - -- [patch-0.91.1i.aw.purgeprompt.1] the prompt for $delete now shows how many - messages will be purged - -- [patch-0.92.1i.jg.empty_to.1] makes the string used for the group mailbox - name when there are no to: or cc: recipients configurable via the - $empty_to variable - -- moved mutt_signal_init() before initscr() in start_curses() so that - ncurses 4.2 will not attempt to install its on SIGWINCH handler - - -PGP related changes since 0.92.2i ---------------------------------- - -- White space problems around "#ifdef _PGPPATH" should be - fixed now. - -- The .spec file for RedHat is gone. -Changes since 0.92.3 --------------------- - -- alarm() was not actually set to put sendmail in the background when - $sendmail_wait > 0 - -- [patch-0.92.3.de.threadlimitfix.1] - -- [patch-0.92.3.josh.delete_format.1] changes default for $delete_format - -- [patch-0.92.3.me.var_syn.1] renames some variables and creats a synonym - data type - -- [patch-0.92.3.vikas.sort_alias] fixed bug with `set sort_alias=unsorted' - -- [patch-0.92.3i.de.hashtable-leak.1] fixed memory leak when destroying - hash tables - -- [de] fixed memory leak in init.c where the value of $alias_file was not - free()d before assigning the default from the default muttrc to use - -- [patch-0.92.3i.tlr.keymaps.1] fixed missing keybindings for the `jump' - command - -- fixed typo "Purpge" in mx_close_mailbox() - -- [patch-0.91.1.ldm.ignore_list_reply_to] fixed bug with handling of - $ignore_list_reply_to - -- fixed signal initialization to call before initscr() for ncurses and after - initscr() for slang - -- [patch-0.92.3.vikas.alias_search] makes searching in the alias menu - WYSIWYG - -- fixed memory leak in parse_route_addr() when the route-addr portion of an - address was unable to be parsed - -- [patch-0.92.3i.tlr.query_real.1] - -- [patch-0.92.3.color_index.7] adds the ability to color lines in the index - using the searching language - - -PGP related changes since 0.92.3i ---------------------------------- - -- [patch-0.92.3i.tlr.keymaps.1] Add some lost keymap - bindings for the generic menu. - -- [patch-0.92.3i.tlr.pgp_default_version.1] The default - value of $pgp_default_version is now set correctly. - -- [patch-0.92.3.bl.pgp_attach_del.1] Handle PGP/MIME - messages correctly when deleting attachments. - -- [patch-0.92.3i.rr.postpone_pgp.1] Corrects some bugs - with respect to postponing PGP signed messages. -Changes since 0.92.4 --------------------- - -- [patch-0.92.4.josh.empty_querycmd.2] fixed segfault on $query_command - being set to '' - -- [recv.diff] the warning from filter-attachment was not cleared when you - answer no or abort - -- [patch-0.92.4i.rr.mime_forward_decode.1] splits $forward_decode into - $forward_decode and $mime_forward_decode - -- [patch-0.92.1.optional_list.2] makes the %L in $header_format an optional - string using the %?L?...? syntax - -- [patch-0.92.4.me.savehook.1] makes it possible to use ~b and ~h in - save-hook commands - -- [patch-0.92.4i.me.token.2] upgrades the muttrc parser to use dynamic - buffer allocation, and allows multiple commands on a single line separated - by semicolons - -- the bcc: field is again output to the $sendmail program, and is assumed - that the MTA will take care of removing it - -- fixed memory leak in parse_route_addr() - - -PGP related changes since 0.92.3i ---------------------------------- - -- [patch-0.92.3i.tlr.keymaps.1] Add some lost keymap - bindings for the generic menu. - -- [patch-0.92.3i.tlr.pgp_default_version.1] The default - value of $pgp_default_version is now set correctly. - -- [patch-0.92.3.bl.pgp_attach_del.1] Handle PGP/MIME - messages correctly when deleting attachments. - -- [patch-0.92.3i.rr.postpone_pgp.1] Corrects some bugs - with respect to postponing PGP signed messages. -Changes since 0.92.5 --------------------- - -- [patch-0.92.4i.de.parse_date.1] better recovery from badly formatted - timezones - -- [patch-0.92.5.de.Muttrc-memleak.1] fixed memory leak when using the -F - command line option - -- [patch-0.92.5i.bj.pgp_bitfield.1] - -- [patch-0.92.5i.jg.empty_to_doc.1] adds documentation for the $empty_to - variable - -- [patch-0.92.5i.rr.ask_quit.1] new variable $quit which controls the prompt - for exiting mutt - -- [patch-0.92.5.vikas.color_index.7-10] fixed bugs in the `uncolor' command - -- fixed coredump if $to_chars is set to '' - -- [patch-0.92.5.vikas.wrap_search] new variable $wrap_search which controls - whether or not searches wrap around the first or last message - -- [patch-0.92.4i.dj.addr_hook_patterns.3] the mailbox specified in a - save-hook is now %-expanded using $header_format - -- the default save mailbox no longer looks at defined `lists'. to get the - old behavior, use - save-hook ~l %B - -- optional strings in format strings have been extended to allow for an - `else' clause. the new syntax is: - %??&? - or if no `else' clause is desired (backwards compatibility): - %??? - -- [patch-0.92.5.bj.interrupt_search.1] allows interruption of `search' using - the shell's interupt (SIGINT) character - -- [patch-0.92.5i.jg.attach_split_sep.1] removed useless code and docs - relating to $attach_split and $attach_sep - -- [patch-0.92.5.vikas.toggle_write] if the mailbox is read-only and the - user attempts to sync, a more informative error message is now displayed - - -Changes since 0.92.6 --------------------- - -- [patch-0.92.6.vikas.limit_new.3] adds support for new mail delivery while - a limit is in effect - -- [patch-0.92.6.vikas.wrap_search.2] adds docs for $wrap_search - -- [patch-0.92.6i.de.quit.1] changes the default for $quit to `yes' - -- [patch-0.92.6.me.rfc822.1] fixed buffer overrun error in - rfc822_write_address_real() - -- [mutt-0.92.6i-mhsupport.patch] - -- [patch-0.92.6i.de.reopen_unread.1] - -- consolidated common code for editing address lists in edit_envelope() - -- changed parse_alias() to use mutt_parse_adrlist() instead of - rfc822_parse_adrlist() so that you can have simple aliases like: - alias group bob joe - with no commas (mailx compatibility) - -Changes since 0.92.7 --------------------- - -- [patch-0.92.7.handler.empty_cc_bcc.1] fixed bug in edit_envelope() which - caused the message to be aborted if the cc or bcc field was empty - -- buffer used to store the error message in mutt_pattern_comp() called - sizeof() on the wrong variable - -- renamed $header_format to $index_format ($hdr_format is still accepted) - -- [patch-0.92.7.vikas.postpone.1] fixed typo for binding the `postpone' - menu, and changes the menu to use $index_format for display of postponed - messages - -- mutt_error() is now a function pointer which either has the value of - mutt_curses_error() or mutt_nocurses_error() which simplifies the muttrc - parsing code - -- "source '~/bin/myscript|'" was fixed so that it works correctly - -- [patch-0.92.7.me.mh_sync.1] fixed bug where syncing mh mailboxes silently - failed - -- [patch-0.92.7.me.pattern.1] fixes bug with mismatched backtics in the - pattern language - -- mutt_default_from() no longer sets the "real name" portion of the return - address so that it can be delayed until after execution of send-hook - commands - - -PGP-related changes since 0.92.6i ---------------------------------- - -- [patch-0.92.6i.tlr.pgp_longids.1] Correct the - calculation of 64 bit "v4" key IDs. - -Changes since 0.92.8 --------------------- - -- [patch-0.90.12i.jmydaes.command-complete.1] Command completion - -- [patch-0.92.8.mtsirkin.attach-viewer.1] When viewing - attachments, fall back to the attachment's file name if - no description is available. - -- [patch-0.92.8i.ds.attachmsg.1] Attach messages from the compose menu. - -- [patch-0.92.8i.tlr.make_string_context.1] Fix a - segmentation fault when invoking mutt -p from the - command line. - -- [patch-0.92.8i.tlr.mh_sequences.1] Don't generate - .mh_sequences files for maildir folders. - -- fix a NULL pointer deference in hdrline.c - -- [patch-0.92.8i.jmy.hook-bugfix.1] Fix a segmentation - fault in the send-hook code. - -- [patch-0.92.8i.tlr.addrbook.1] Untag all aliases before - entering the address-book menu. - -- Enforce a non-NULL QueryCmd in the beginning of - mutt_query_complete() and mutt_query_menu(). - -- Make all query.c functions except mutt_query_complete() - and mutt_query_menu() static. - -- The latest IMAP patch from Andy Sloane has been added. - -PGP related Changes since 0.92.8i ---------------------------------- - -- [patch-0.92.8i.maj.MIC_alg.1] Properly initializes a - variable in the PGP part of the Compose menu. - -- [patch-0.92.8i.tlr.pgpkey_dflt.1] Avoid possible - segmentation faults when determining the default value - of the PGP key selection prompt. - -- [patch-0.92.8i.wk.opgp_5bytelength.1] Recognize - OpenPGP's public key algorithm #20 (i.e., ElGamal for - Signing and Encrypting). - -- Moved doc/pgp-Notes.txt to doc/PGP-Notes.txt, and - updated that part of the documentation. - - -Changes since 0.92.9i ---------------------- - -Tue Jun 16 00:22:28 1998 Thomas Roessler + * configure.in, configure, Changes, ChangeLog: Preparing 0.92.10i. * doc/PGP-Notes.txt: Including Roland's new procmail recipe. @@ -1811,14 +904,3 @@ Mon Jun 15 15:19:49 1998 Thomas Roessler * mx.c, main.c, mailbox.h, imap.c, commands.c: Brandon's IMAP patch. -Mon Jun 8 20:05:54 1998 Thomas Roessler - - * recvattach.c, pgppubring.c, pgpkey.c, - pgpinvoke.c, pgp.h, pgp.c, main.c, init.h, - gnupgparse.c, init.c, configure.in, configure, - config.h.in, compose.c, acconfig.h, Makefile.in: - GPG support, first take. - - * hdrline.c: Fixing the %a format. - - * hdrline.c: Fixing a segmentation fault in the hdr_line code. diff --git a/Changes b/Changes deleted file mode 100644 index 5e668d23..00000000 --- a/Changes +++ /dev/null @@ -1,25 +0,0 @@ -Changes since 0.92.10i ----------------------- - -Tue Jun 16 15:15:00 1998 Thomas Roessler - - * imap.h: Check in a proper version of imap.h. - - * color.c: Fix the "unknown color" bug reported by Vikas. - - * mx.c: Remove a spurious #include "imap.h" from mx.c. - - * doc/style-guide: Add a note about the global Muttrc to style-guide. - - * configure.in, Muttrc.in, configure, Attic/Muttrc, Makefile.in: - The global Muttrc contains a list of default settings - which can be used as a starting-point for the user's own - configuration. - - * pgppubring.c, pgp.h, gnupgparse.c: - Removing some duplicate code from gnupgparse.c and - pgppubring.c. - - * pgpinvoke.c, gnupgparse.c: - Include part of Werner Koch's latest GPG patches. - diff --git a/INSTALL b/INSTALL index edef9e84..34f7fce7 100644 --- a/INSTALL +++ b/INSTALL @@ -18,6 +18,7 @@ systems: MkLinux NetBSD QNX + SCO Unix 3.2v4/5 Solaris SunOS Ultrix @@ -37,11 +38,12 @@ systems: Installation ============ -Installing Mutt is rather painless through the use of the GNU autoconf -package. Simply untar the Mutt distribution, and run the ``configure'' -script. In most cases, it will automatically determine everything it needs -to know in order to compile. However, there are a few options to -``configure'' to help it out, or change the default behavior: +Installing Mutt is rather painless through the use of the GNU +autoconf package. Simply untar the Mutt distribution, and run the +``configure'' script. In most cases, it will automatically determine +everything it needs to know in order to compile. However, there are +a few options to ``configure'' to help it out, or change the default +behavior: --prefix=DIR install Mutt in DIR instead of /usr/local @@ -71,22 +73,19 @@ to know in order to compile. However, there are a few options to --enable-pop enable POP3 support ---enable-hidden-host - local hostname is not part of the FQDN. - --with-rx use GNU rx instead of local regexp routines. Many systems don't have the POSIX compliant regcomp/regexec/regfree routines, so this provides a way to support them. --enable-flock - use flock() to lock files + use flock() to lock files. --disable-fcntl by default, Mutt uses fcntl() to lock files. Over NFS this can result in poor performance on read/write. Note that using this - option could be dangerous if dotlocking is also disabled - + option could be dangerous if dotlocking is also disabled. + --enable-nfs-fix some implementations of NFS do not always write the atime/mtime of small files. This means that Mutt's ``mailboxes'' @@ -114,12 +113,17 @@ to know in order to compile. However, there are a few options to when you press '!'. Only use this option to solve the above problem, and only specify one of the above shells as its argument. + (If you encounter this problem with your platform's native + Bourne shell, please send a short report to mutt-dev@cs.hmc.edu, + so a short note on this topic can be added to the Platform notes + section below.) + --enable-exact-address By default, Mutt will rewrite all addresses in the form Personal Name regardless of the input. By enabling this option, Mutt will write addresses in the same form they are parsed. NOTE: this requires - significantly more memory + significantly more memory. Once ``configure'' has completed, simply type ``make install.'' @@ -129,9 +133,18 @@ A_NORMAL or KEY_MIN, then you probably don't have a SysV compliant curses library. You should install either ncurses or S-Lang (see above), and then run the ``configure'' script again. + Platform Notes ============== +All platforms + + There is a bug in most (if not all) S-Lang versions which + prevents the Meta key from working with mutt. A patch can be + found in the file patch.slang-1.2.2.keypad.1 in this mutt + distribution. + + Solaris 2.4 The system regcomp() and regexec() routines are very badly broken. @@ -142,3 +155,34 @@ Solaris 2.4 Color does not work right with Solaris curses. You will have to compile with either ncurses or slang to get working color support. + +Linux + + On recent Linux systems, flock() and fcntl() locks don't mix. If + you use the --enable-flock switch on such systems, be sure to + give the --disable-fcntl argument as well. + + The Linux libc 5.4.45 disables locale support in programs running + setgid mail. You'll need to use the configure switch + "--enable-locales-fix". If you're using a non-iso-8859 font, you + lose. This is not an issue on glibc (libc 6) based systems. + + +Digital Unix (OSF/1) + + Don't try "--with-rx", because you won't be able to match + anything (using system's regex functions seems to work fine + though). + + Also, the system curses library is said to be badly broken. Use + GNU ncurses or SLang instead. + + +FreeBSD 3.0 + + /bin/sh is broken on this platform. You need the + "--with-exec-shell" configuration switch here; ksh + and bash are reported to be fine. + + This may also be an issue with earlier FreeBSD + versions. diff --git a/Makefile.in b/Makefile.in index d02a7ca5..e28b5d53 100644 --- a/Makefile.in +++ b/Makefile.in @@ -32,21 +32,22 @@ VPATH=@srcdir@ INSTALL=@INSTALL@ CC=@CC@ -XCPPFLAGS=-I. @CPPFLAGS@ -CFLAGS=@CFLAGS@ -DSHAREDIR=\"$(sharedir)\" $(XCPPFLAGS) +XCPPFLAGS=-I. @CPPFLAGS@ -DSHAREDIR=\"$(sharedir)\" -DDOTLOCK=\"$(bindir)/mutt.dotlock\" +CFLAGS=@CFLAGS@ $(XCPPFLAGS) LDFLAGS=@LDFLAGS@ LIBS=@LIBS@ OPS=@OPS@ OBJS= addrbook.o alias.o attach.o browser.o buffy.o color.o \ commands.o complete.o compose.o copy.o curs_lib.o curs_main.o date.o \ edit.o enter.o flags.o init.o filter.o from.o getdomain.o \ - handler.o hash.o hdrline.o headers.o help.o hook.o keymap.o lib.o \ + handler.o hash.o hdrline.o headers.o help.o \ + history.o hook.o keymap.o lib.o \ main.o mbox.o menu.o mh.o mx.o pager.o parse.o pattern.o \ postpone.o query.o recvattach.o rfc822.o \ rfc1524.o rfc2047.o score.o send.o sendlib.o signal.o sort.o \ status.o system.o thread.o @LIBOBJS@ -CLEANFILES=mutt *.o core +CLEANFILES=dotlock mutt *.o core VERYCLEANFILES=$(CLEANFILES) Makefile config.cache config.log \ config.status config.h Muttrc DISTCLEANFILES=$(VERYCLEANFILES) tags keymap_defs.h *.rej *.orig *~ Makefile.bak @@ -56,19 +57,22 @@ NONEXPORT=pgp.c pgp.h pgpinvoke.c pgpkey.c pgppubring.c sha.h sha1dgst.c \ gnupgparse.c sha_locl.h OPS.PGP doc/pgp-Notes.txt doc/language.txt \ doc/language50.txt -all: mutt +all: mutt @DOTLOCK_TARGET@ mutt: keymap_defs.h $(OBJS) $(REGEX) $(CC) -o mutt $(OBJS) $(REGEX) $(LDFLAGS) $(LIBS) +dotlock: dotlock.o @SNPRINTFOBJS@ + $(CC) -o dotlock dotlock.o @SNPRINTFOBJS@ + keymap_defs.h: Makefile $(OPS) rm -f keymap_defs.h $(srcdir)/gen_defs $(OPS) > keymap_defs.h -install: mutt install.doc +install: mutt install.doc @DOTLOCK_INSTALL_TARGET@ $(srcdir)/mkinstalldirs $(bindir) -mv -f $(bindir)/mutt $(bindir)/mutt.old - $(INSTALL) @MUTT_GROUP@ -m @MUTT_PERMISSION@ mutt $(bindir) + $(INSTALL) -m 755 mutt $(bindir) -if [ ! -f $(sharedir)/Muttrc ]; then \ $(srcdir)/mkinstalldirs $(sharedir); \ $(INSTALL) -m 644 $(srcdir)/Muttrc $(sharedir); \ @@ -77,14 +81,19 @@ install: mutt install.doc $(INSTALL) -m 644 $(srcdir)/mime.types $(sharedir); \ fi +install.dotlock: dotlock + $(srcdir)/mkinstalldirs $(bindir) + -mv -f $(bindir)/mutt.dotlock $(bindir)/mutt.dotlock.old + $(INSTALL) @DOTLOCK_GROUP@ -m @DOTLOCK_PERMISSION@ dotlock $(bindir)/mutt.dotlock + install.doc: - make -C $(srcdir)/doc/ install + ( cd $(srcdir)/doc && make install ) uninstall: uninstall.doc - rm -f $(bindir)/mutt $(sharedir)/Muttrc + rm -f $(bindir)/mutt $(sharedir)/Muttrc $(bindir)/mutt.dotlock uninstall.doc: - make -C $(srcdir)/doc/ uninstall + ( cd $(srcdir)/doc/ && make uninstall ) $(srcdir)/configure: $(srcdir)/configure.in autoconf diff --git a/Muttrc.in b/Muttrc.in index c524dc32..4d00cd1d 100644 --- a/Muttrc.in +++ b/Muttrc.in @@ -8,11 +8,11 @@ ignore "from " received content- mime-version status x-status message-id ignore sender references return-path lines # imitate the old search-body function -macro index \eb '/~b ' +macro index \eb '/~b ' 'search in message bodies' # simluate the old url menu -macro index \cb |urlview\n -macro pager \cb |urlview\n +macro index \cb |urlview\n 'call urlview to extract URLs out of a message' +macro pager \cb |urlview\n 'call urlview to extract URLs out of a message' # If Mutt is unable to determine your sites domain name correctly, you can # set the default here. @@ -55,7 +55,6 @@ macro pager \cb |urlview\n # set dsn_return="" # unset edit_headers # set editor="" -# set empty_to="undisclosed-recipients" # set escape="~" # unset fast_reply # unset fcc_attach diff --git a/NEWS b/NEWS index bab7ea60..ff4cb3a7 100644 --- a/NEWS +++ b/NEWS @@ -1,79 +1,111 @@ -Announcing Mutt 0.91 -==================== +Major changes since 0.91.1 +-------------------------- -NOTE: PLEASE read the following list of changes carefully, especially the -first couple entries related to changes in variables/commands and see the -manual before posting questions. Taking a little time to read this notice -will significantly reduce the amount of confusion as to why some things -might seem broken at first. - -Major changes since 0.89.1: - -- The matching for the send-hook, save-hook and fcc-hook commands has been - extended so that it understands Mutt's matching language (used for - searching and limits). You may still use a "simple" regular expression, - but Mutt will expand that with the value of $default_hook (similar to - $simple_search). Additionally, all hooks are now executed in the order - they appear in your .muttrc instead of first doing `to', then `cc'. - -- new config command `score' which allows you to assign a numerical value to - a message based upon header information (similar to scoring in slrn). the - score can be displed in $hdr_format with %N, you can sort by `score' and - you can match messages with a certain score (or range) with the `~n' - operator - -- new variable $beep_new which causes Mutt to beep when new mail is - delivered to a mailbox specified by the `mailboxes' command - -- new sort method `to' for sorting by who messages are addressed to - -- new variable $meta_key which causes Mutt to interpet keystrokes with the - hi bit set as ESC plus the key with the hi bit stripped (eg. ALT-x will - get interpetted as "\ex") - -- new variable $sort_alias which controls the order the aliases appear in - the menu (may be either "alias" or "address") - -- new variable $alias_format to control the way the aliases are displayed in - the alias menu +- additional format for $hdr_format + %L displays the total size of all visible messages in a + limited view + % displays current time using strftime(fmt) - additional operators to the pattern matching lanauge: - ~S superseded messages - ~E expired messages - ~p personal mail (finds $alternates in to: or cc:) - ~P mail from you (finds $alternates in from: or sender:) - ~l list mail (finds `lists' in to: or cc:) - ~L finds in to:, cc:, from: or sender: - ~C finds in to: or cc: - -- additional formats for $hdr_format - %N displays the message score - %(fmt) displayes the message's received time using strftime() - -- additional formats for $status_format - %P percentage of menu seen - %S current value of $sort_aux (%s no longer displays $sort_aux) - %o number of old messages - %u number of unread messages - -- new configure option `--enable-exact-address' which causes Mutt to rewrite - addresses in the same format they were parsed instead of rewriting them in - the form `Name ' - -- new command line argument `-e' which allows you to specify configuration - commands to be executed *after* your .muttrc is parsed - (eg. mutt -e 'set edit_hdrs' mutt-dev) - -- you can now use `mono normal' to set to normal attribute - -- new function `search-opposite' which searches for the current search - pattern in the opposition direction from the previous search - -Mutt's primary distribution point is ftp://ftp.cs.hmc.edu/pub/me/mutt. -See the Mutt Home Page (http://www.cs.hmc.edu/~me/mutt/) for mirror sites. - -Bug reports should be sent to the Mutt User's Mailing List -. - -Michael Elkins -April 10, 1998 + ~B finds pattern anywhere in the message (more + efficient than ~h %s | ~b %s + ~z finds messages of size + E.g. + ~z<10k #finds messages smaller than 10KB + ~z>10k #finds messages larger than 10KB + ~z10k #finds messages exactly 10KB in length + + +- the $hdr_format variable is renamed to $index_format + $hdr_format is still accepted for backwards compatibility + +- new variable $folder_format to display entries in the 'browser' menu. + +- new variable $followup_to to control generation of Mail-Followup-To + field. You can edit this field and Mutt will not overwrite it. + +- new variable $sendmail_wait + + Specifies the number of seconds to wait for the ``sendmail'' process + to finish before giving up and putting delivery in the background. + + Mutt interprets the value of this variable as follows: + + >0 number of seconds to wait for sendmail to finish before continuing + 0 wait forever for sendmail to finish + <0 always put sendmail in the background without waiting + + Note that if you specify a value other than 0, the output of the child + process will be put in a temporary file. If there is some error, you + will be informed as to where to find the output. + +- Variable $sendmail_bounce has been removed. Mutt now passes all + recipients on the command line for normal sending. + +- new variable $query_command + Adds support for querying an external database for email addresses. + +- The $forward_decode variable has been removed. This has been split into 2 + variables + + $forward_decode - used when $mime_fwd is not set + $mime_forward_decode - used when $mime_fwd is set + +- new variable $wrap_search. This controls whether searches wrap around the + end of the mailbox. + + When set, searches will wrap around the first (or last) message. When + unset, searches will not wrap + + +- New command 'reset' to reset variables to their default compile-time + definitions. When used with special keyword 'all', all variables are + reset to their default values. When used with the 'set' command and the + variable name prefixed with '&', this has the same behaviour as the + 'reset' command. + + Eg. + reset move + reset all + set &move + set &all + +- Function key names used in muttrc need to be enclosed in <>. + Function keys can be used in macros also. + + Eg. + macro index Y * + bind index next-entry + +- You can now delete a message's attachments by pressing 'd' (delete-entry) + on the attachment in the attachment menu. + +- You can now color index menu entries using the pattern matching language. + The 'uncolor' command resets the entry to its default color. The '*' + token can be used to reset all index entries to their default colors. + + Eg. + color index blue white ~fvikas + color index red white ~z>100k + uncolor index ~fvikas + uncolor index * + +- mailboxes specified in save-hooks can be %-expanded using $header_format + +- the default save mailbox no longer looks at defined `lists'. To get the + old behaviour, use + save-hook ~l %B + +- optional strings in format strings have been extended to allow for an + `else' clause. the new syntax is: + %??&? + or if no `else' clause is desired (backwards compatibility): + %??? + +- If new mail is delivered to a folder when Mutt is displaying a limited + view of the folder, it is added to the limited view only if it satisfies + the current limit criteria. + +- the key on the command-line now completes commands and variable + names. The longest non-ambiguous part is put on the command-line. + Entering additional text and using will perform completion again. diff --git a/OPS b/OPS index 049e8922..39282f6d 100644 --- a/OPS +++ b/OPS @@ -4,9 +4,11 @@ OP_ATTACH_VIEW_TEXT "view attachment as text" OP_BOTTOM_PAGE "move to the bottom of the page" OP_BOUNCE_MESSAGE "remail a message to another user" OP_BROWSER_NEW_FILE "select a new file in this directory" +OP_BROWSER_VIEW_FILE "view file" OP_CHANGE_DIRECTORY "change directories" OP_CHECK_NEW "check mailboxes for new mail" OP_COMPOSE_ATTACH_FILE "attach a file(s) to this message" +OP_COMPOSE_ATTACH_MESSAGE "attach message(s) to this message" OP_COMPOSE_EDIT_BCC "edit the BCC list" OP_COMPOSE_EDIT_CC "edit the CC list" OP_COMPOSE_EDIT_DESCRIPTION "edit attachment description" @@ -27,6 +29,7 @@ OP_COMPOSE_POSTPONE_MESSAGE "save this message to send later" OP_COMPOSE_RENAME_FILE "rename/move an attached file" OP_COMPOSE_SEND_MESSAGE "send the message" OP_COMPOSE_TOGGLE_UNLINK "toggle whether to delete file after sending it" +OP_COMPOSE_UPDATE_ENCODING "update an attachment's encoding info" OP_COPY_MESSAGE "copy a message to a file/mailbox" OP_CREATE_ALIAS "create an alias from a message sender" OP_CURRENT_BOTTOM "move entry to bottom of screen" @@ -132,6 +135,7 @@ OP_TAG_SUBTHREAD "tag the current subthread" OP_TAG_THREAD "tag the current thread" OP_TOGGLE_NEW "toggle a message's 'new' flag" OP_TOGGLE_WRITE "toggle whether the mailbox will be rewritten" +OP_TOGGLE_MAILBOXES "toggle wether to browse mailboxes or all files" OP_TOP_PAGE "move to the top of the page" OP_UNDELETE "undelete the current entry" OP_UNDELETE_THREAD "undelete all messages in thread" diff --git a/README b/README index 90c2a969..4f9995cf 100644 --- a/README +++ b/README @@ -1,18 +1,38 @@ -README for mutt-0.90i -======================= +README for mutt-0.93i +===================== -Installation instructructions are detailed in ``INSTALL''. +Installation instructions are detailed in ``INSTALL''. -The user manual is in doc/manual.txt. +The user manual is in doc/manual.txt. A list of major +changes since the last public version can be found under +NEWS. PGP users please read doc/PGP-Notes.txt before proceeding. -For more information, see the Mutt home page, -http://www.cs.hmc.edu/~me/mutt/index.html. +For more information, see the Mutt home page: -The primary distribution point for Mutt is -ftp://ftp.cs.hmc.edu/pub/me/mutt. See the home page for -mirror sites. + http://www.cs.hmc.edu/~me/mutt/index.html -Michael Elkins , January 22, 1998 -Thomas Roessler , February 3, 1998 +The primary distribution points for Mutt are: + + ftp://riemann.iam.uni-bonn.de/pub/mutt/ + ftp://ftp.guug.de/pub/mutt + +Mirror sites for the pgp-enabled version of mutt can be +found at the following places: + + ftp://ftp.gbnet.net/pub/mutt-international/ + ftp://ftp.fu-berlin.de/pub/unix/mail/mutt/ + ftp://pgp.rasip.fer.hr/pub/mutt/international/ + ftp://ftp.gwdg.de/pub/unix/mail/mutt + ftp://ftp.iks-jena.de/pub/mitarb/lutz/crypt/software/pgp/mutt + ftp://ftp.lip6.fr/pub/unix/mail/mutt + ftp://ftp.arch.pwr.wroc.pl/pub/mutt/ + ftp://ftp.uib.no/pub/mutt + +Mirror sites for the pgp-disabled version: + + ftp://ftp.ewd.3com.com/pub/mutt/ + + +Thomas Roessler , July 10, 1998 diff --git a/TODO b/TODO index 8b4c410d..11b0c84b 100644 --- a/TODO +++ b/TODO @@ -1,49 +1,132 @@ -- Other than multipart/mixed and PGP/MIME, Mutt should allow the user to - specify what to do with other types of multipart messages (i.e., so a user - can deal with S/MIME messages reasonably) +This list tries to cover the open problems we have with +mutt. It's compiled from the old BUGS and TODO files in +the distribution, from recent mutt-dev postings, and from +other messages relating to problems and/or wishes with +mutt. + +I'm listing the problems in approximate order of priority. + +- Fix the "unexpected EXPUNGE" IMAP bug. + +- Ask IMAP servers for hierarchy separators. (-> Brandon's + note from Aug 18) + +- Apply proper quoting when sending imap "ASTRING"s. (-> + John Prevost wrote something on this on Aug 19). + + +- When using EXACT_ADDRESS, the following memory leak may + occur (insure++ output): + +| [rfc822.c:400] **LEAK_ASSIGN** +| >> last->val = mutt_substrdup (begin, s); +| +| Memory leaked due to pointer reassignment: (void *) malloc(siz) +| +| Lost block : 0x082e7da0 thru 0x082e7db6 (23 bytes) +| (void *) malloc(siz), allocated at: +| safe_malloc() lib.c, 283 +| mutt_substrdup() lib.c, 861 +| rfc822_parse_adrlist() rfc822.c, 377 +| mutt_read_rfc822_header() parse.c, 1112 +| mbox_parse_mailbox() mbox.c, 272 +| mbox_open_mailbox() mbox.c, 390 +| mx_open_mailbox() mx.c, 598 +| mutt_index_menu() curs_main.c, 874 +| +| Stack trace where the error occurred: +| rfc822_parse_adrlist() rfc822.c, 400 +| mutt_read_rfc822_header() parse.c, 1112 +| mbox_parse_mailbox() mbox.c, 272 +| mbox_open_mailbox() mbox.c, 390 +| mx_open_mailbox() mx.c, 598 +| mutt_index_menu() curs_main.c, 874 +| main() main.c, 635 +| +| ************************** INSURE SUMMARY ************************* v4.1 ** +| * Program : mutt * +| * Arguments : * +| * Directory : /home/olga/Mail * +| * Compiled on : Aug 18, 1998 19:52:01 * +| * Run on : Aug 18, 1998 19:57:08 * +| * Elapsed time : 00:04:26 * +| * Malloc HWM : 855,258 bytes (835K) * +| *************************************************************************** +| +| PROBLEM SUMMARY - by type +| =============== +| +| Problem Reported Suppressed +| ------------------------------------------------- +| LEAK_ASSIGN 1 1 +| RETURN_FAILURE 0 70 +| USER_ERROR 0 24 +| ------------------------------------------------- +| TOTAL 1 95 +| ------------------------------------------------- +| +| PROBLEM SUMMARY - by location +| =============== +| +| LEAK_ASSIGN: Memory leaked due to pointer reassignment, 1 unique occurrence +| 2 at rfc822.c, 400 +| + +- In the "attachment" menu, assume this: + + 1 [text/plain, 7bit, 1.1K] + 2 [message/rfc822, 7bit, 6.1K] A test message + 3 [text/plain, 7bit, 0.1K] |-> + 4 [message/rfc822, base64, 2.5K] |-> + 5 [message/rfc822, base64, 2.7K] `-> + + (please note the "message/rfc822" attachments encoded as + Base64; that's illegal, but Sun's Mailtool sends that + kind of messages); then go to, say, attachment "4", + delete it, and go to the main menu; you won't be able to + quit the mailbox (ok, 'x' works, but 'q' doesn't). + + The problem here lies in the fact that mutt uses mailbox + handling functions to access message/rfc822 type + attachments. We'd need to perform an additional + decoding step before using these functions to fix this + bug. + + Please note that mutt's just assuming RFC-compliant mail + here. Fixing this stuff may become a PITA. + + + +- mailbox resync code for mh and maildir mailboxes. This + will most probably help to fix the following problems: + + In maildir folders, the cursor will jump to an + unpredictible message when new mail arrives. + + When accessing maildir folders with two mutts in + parallel, messages which have been marked read (and thus + moved to the cur/ subdirectory) by one of the mutts + can't be read from the other one. + + +- Re-visit nametemplate support. Currently, we use + symbolic links in our temporary directory for this. + + +- BODY struct should probably have a pointer to its + corresponding HEADER struct. this is needed for + mh/maildir mailboxes so the correct pathname can be + found. Or perhaps all we need is a .hdr member of the + STATE struct so that all of the MIME handlers can look + up the corresponding HEADERs if need be? - option to not include attachments in replies - handle message/external-body in some fashion - handle message/partial reconstruction - -- not possible to view the header of a single part message which contains - something that requires a mailcap entry to view - -- need to clean up the error recovery when running out of space when syncing - a mbox/mmdf mailbox - -- BODY struct should probably have a pointer to its corresponding HEADER - struct. this is needed for mh/maildir mailboxes so the correct pathname - can be found. Or perhaps all we need is a .hdr member of the STATE struct - so that all of the MIME handlers can look up the corresponding HEADERs if - need be? - -- mailbox resync code for mh and maildir mailboxes - -- fold long user-defined header fields - -- history classes - -- document honored environment variables - -- add -v flag to pass to sendmail... - -- ordered tag - -- rfc822 parser needs to do something with the @host1@host2: portion of the - route-addr - -- command completion for `enter-command' - -- new forward command to include first attachment in the editor and attach - other attachments to the message - -- adjust the names of *adr() and *adrlist() and calling routines for - consistency - -- mbox-hook entries should override $move? - -- add a preserved flag to messages - + +- not possible to view the header of a single part message + which contains something that requires a mailcap entry to + view + diff --git a/acconfig.h b/acconfig.h index 1e79d39a..ab805047 100644 --- a/acconfig.h +++ b/acconfig.h @@ -48,9 +48,6 @@ /* Where new mail is spooled */ #undef MAILPATH -/* Should I just use the domain name? (--enable-hidden-host) */ -#undef HIDDEN_HOST - /* Does your system have the srand48() suite? */ #undef HAVE_SRAND48 @@ -111,3 +108,6 @@ /* Does your system have the vsnprintf() call? */ #undef HAVE_VSNPRINTF + +/* Does your system have the fchdir() call? */ +#undef HAVE_FCHDIR diff --git a/addrbook.c b/addrbook.c index e14ca9b1..9334796b 100644 --- a/addrbook.c +++ b/addrbook.c @@ -18,6 +18,7 @@ #include "mutt.h" #include "mutt_menu.h" +#include "mapping.h" #include "sort.h" #include diff --git a/alias.c b/alias.c index d927fbc5..84dcc04c 100644 --- a/alias.c +++ b/alias.c @@ -18,6 +18,7 @@ #include "mutt.h" #include "mutt_regex.h" +#include "mutt_curses.h" #include #include @@ -37,7 +38,8 @@ static ADDRESS *mutt_expand_aliases_r (ADDRESS *a, LIST **expn) ADDRESS *head = NULL, *last = NULL, *t, *w; LIST *u; char i; - + const char *fqdn; + while (a) { if (!a->group && !a->personal && a->mailbox && strchr (a->mailbox, '@') == NULL) @@ -90,8 +92,7 @@ static ADDRESS *mutt_expand_aliases_r (ADDRESS *a, LIST **expn) *p = 0; a->personal = safe_strdup (buffer); #ifdef EXACT_ADDRESS - free (a->val); - a->val = NULL; + FREE (&a->val); #endif } } @@ -108,10 +109,10 @@ static ADDRESS *mutt_expand_aliases_r (ADDRESS *a, LIST **expn) last->next = NULL; } - if (option (OPTUSEDOMAIN) && Fqdn[0] != '@') + if (option (OPTUSEDOMAIN) && (fqdn = mutt_fqdn(1))) { /* now qualify all local addresses */ - rfc822_qualify (head, Fqdn); + rfc822_qualify (head, fqdn); } return (head); @@ -205,13 +206,19 @@ void mutt_create_alias (ENVELOPE *cur, ADDRESS *iadr) else buf[0] = 0; - if (mutt_get_field ("Address: ", buf, sizeof (buf), 0) != 0 || !buf[0]) + do { - mutt_free_alias (&new); - return; + if (mutt_get_field ("Address: ", buf, sizeof (buf), 0) != 0 || !buf[0]) + { + mutt_free_alias (&new); + return; + } + + if((new->addr = rfc822_parse_adrlist (new->addr, buf)) == NULL) + BEEP (); } - new->addr = rfc822_parse_adrlist (new->addr, buf); - + while(new->addr == NULL); + if (adr && adr->personal && !mutt_is_mail_list (adr)) strfcpy (buf, adr->personal, sizeof (buf)); else @@ -366,28 +373,39 @@ int mutt_alias_complete (char *s, size_t buflen) return 1; } -/* returns TRUE if the given address belongs to the user. */ -int mutt_addr_is_user (ADDRESS *addr) +static int string_is_address(const char *str, const char *u, const char *d) { char buf[LONG_STRING]; + + snprintf(buf, sizeof(buf), "%s@%s", NONULL(u), NONULL(d)); + if (strcasecmp(str, buf) == 0) + return 1; + + return 0; +} +/* returns TRUE if the given address belongs to the user. */ +int mutt_addr_is_user (ADDRESS *addr) +{ /* NULL address is assumed to be the user. */ if (!addr) return 1; if (!addr->mailbox) return 0; - if (strcasecmp (addr->mailbox, Username) == 0) + + if (strcasecmp (addr->mailbox, NONULL(Username)) == 0) return 1; - snprintf (buf, sizeof (buf), "%s@%s", Username, Hostname); - if (strcasecmp (addr->mailbox, buf) == 0) + if(string_is_address(addr->mailbox, Username, Hostname)) return 1; - snprintf (buf, sizeof (buf), "%s@%s", Username, Fqdn); - if (strcasecmp (addr->mailbox, buf) == 0) + if(string_is_address(addr->mailbox, Username, mutt_fqdn(0))) + return 1; + if(string_is_address(addr->mailbox, Username, mutt_fqdn(1))) return 1; if (Alternates.pattern && regexec (Alternates.rx, addr->mailbox, 0, NULL, 0) == 0) return 1; + return 0; } diff --git a/attach.c b/attach.c index 4345d093..d0a887e1 100644 --- a/attach.c +++ b/attach.c @@ -23,12 +23,20 @@ #include "rfc1524.h" #include "mime.h" #include "pager.h" +#include "mailbox.h" +#include "copy.h" +#include "mx.h" + +#ifdef _PGPPATH +#include "pgp.h" +#endif #include #include #include #include #include +#include #include #include @@ -37,14 +45,16 @@ int mutt_compose_attachment (BODY *a) { char type[STRING]; char command[STRING]; + char newfile[_POSIX_PATH_MAX] = ""; rfc1524_entry *entry = rfc1524_new_entry (); - - snprintf (type, sizeof (type), "%s/%s", TYPE (a->type), a->subtype); + short unlink_newfile = 0; + int rc = 0; + + snprintf (type, sizeof (type), "%s/%s", TYPE (a), a->subtype); if (rfc1524_mailcap_lookup (a, type, entry, M_COMPOSE)) { if (entry->composecommand || entry->composetypecommand) { - char newfile[_POSIX_PATH_MAX] = ""; if (entry->composetypecommand) strfcpy (command, entry->composetypecommand, sizeof (command)); @@ -55,19 +65,17 @@ int mutt_compose_attachment (BODY *a) { dprint(1, (debugfile, "oldfile: %s\t newfile: %s\n", a->filename, newfile)); - if (!mutt_rename_file (a->filename, newfile)) + if (symlink (a->filename, newfile) == -1) { if (!mutt_yesorno ("Can't match nametemplate, continue?", 1)) - return 0; - } - else - { - safe_free ((void **) &a->filename); - a->filename = safe_strdup (newfile); + goto bailout; } + unlink_newfile = 1; } - - if (rfc1524_expand_command (a, a->filename, type, + else + strfcpy(newfile, a->filename, sizeof(newfile)); + + if (rfc1524_expand_command (a, newfile, type, command, sizeof (command))) { /* For now, editing requires a file, no piping */ @@ -86,7 +94,7 @@ int mutt_compose_attachment (BODY *a) if ((fp = safe_fopen (a->filename, "r")) == NULL) { mutt_perror ("Failure to open file to parse headers."); - return 0; + goto bailout; } b = mutt_read_mime_header (fp, 0); @@ -117,7 +125,7 @@ int mutt_compose_attachment (BODY *a) if ((tfp = safe_fopen (tempfile, "w")) == NULL) { mutt_perror ("Failure to open file to strip headers."); - return 0; + goto bailout; } mutt_copy_stream (fp, tfp); fclose (fp); @@ -138,8 +146,15 @@ int mutt_compose_attachment (BODY *a) return 1; } + rc = 1; + + bailout: + + if(unlink_newfile) + unlink(newfile); + rfc1524_free_entry (&entry); - return 1; + return rc; } /* @@ -151,18 +166,20 @@ int mutt_compose_attachment (BODY *a) * Returns 1 if editor found, 0 if not (useful to tell calling menu to * redraw) */ -int mutt_edit_attachment (BODY *a, int opt) +int mutt_edit_attachment (BODY *a) { char type[STRING]; char command[STRING]; + char newfile[_POSIX_PATH_MAX] = ""; rfc1524_entry *entry = rfc1524_new_entry (); - - snprintf (type, sizeof (type), "%s/%s", TYPE (a->type), a->subtype); + short unlink_newfile = 0; + int rc = 0; + + snprintf (type, sizeof (type), "%s/%s", TYPE (a), a->subtype); if (rfc1524_mailcap_lookup (a, type, entry, M_EDIT)) { if (entry->editcommand) { - char newfile[_POSIX_PATH_MAX] = ""; strfcpy (command, entry->editcommand, sizeof (command)); if (rfc1524_expand_filename (entry->nametemplate, @@ -170,19 +187,17 @@ int mutt_edit_attachment (BODY *a, int opt) { dprint(1, (debugfile, "oldfile: %s\t newfile: %s\n", a->filename, newfile)); - if (mutt_rename_file (a->filename, newfile)) + if (symlink (a->filename, newfile) == -1) { if (!mutt_yesorno ("Can't match nametemplate, continue?", 1)) - return 0; - } - else - { - safe_free ((void **) &a->filename); - a->filename = safe_strdup (newfile); + goto bailout; } + unlink_newfile = 1; } + else + strfcpy(newfile, a->filename, sizeof(newfile)); - if (rfc1524_expand_command (a, a->filename, type, + if (rfc1524_expand_command (a, newfile, type, command, sizeof (command))) { /* For now, editing requires a file, no piping */ @@ -198,8 +213,8 @@ int mutt_edit_attachment (BODY *a, int opt) else if (a->type == TYPETEXT) { /* On text, default to editor */ - mutt_edit_file (strcmp ("builtin", Editor) == 0 ? Visual : Editor, - a->filename); + mutt_edit_file ((!Editor || strcmp ("builtin", Editor) == 0) ? + NONULL(Visual) : NONULL(Editor), newfile); } else { @@ -208,8 +223,15 @@ int mutt_edit_attachment (BODY *a, int opt) return 0; } + rc = 1; + + bailout: + + if(unlink_newfile) + unlink(newfile); + rfc1524_free_entry (&entry); - return 1; + return rc; } int mutt_is_autoview (char *type) @@ -242,15 +264,19 @@ int mutt_view_attachment (FILE *fp, BODY *a, int flag) char type[STRING]; char command[STRING]; char descrip[STRING]; + char *fname; rfc1524_entry *entry = NULL; int rc = -1; - - is_message = (a->type == TYPEMESSAGE && a->subtype && - (!strcasecmp (a->subtype,"rfc822") || - !strcasecmp (a->subtype, "news"))); + int unlink_tempfile = 0; + + is_message = mutt_is_message_type(a->type, a->subtype); +#ifdef _PGPPATH + if (is_message && (a->hdr->pgp & PGPENCRYPT) && !pgp_valid_passphrase()) + return (rc); +#endif /* _PGPPATH */ use_mailcap = (flag == M_MAILCAP || (flag == M_REGULAR && mutt_needs_mailcap (a))); - snprintf (type, sizeof (type), "%s/%s", TYPE (a->type), a->subtype); + snprintf (type, sizeof (type), "%s/%s", TYPE (a), a->subtype); if (use_mailcap) { @@ -279,13 +305,21 @@ int mutt_view_attachment (FILE *fp, BODY *a, int flag) } strfcpy (command, entry->command, sizeof (command)); - if (rfc1524_expand_filename (entry->nametemplate, a->filename, + if (fp) + { + fname = safe_strdup (a->filename); + mutt_sanitize_filename (fname); + } + else + fname = a->filename; + + if (rfc1524_expand_filename (entry->nametemplate, fname, tempfile, sizeof (tempfile))) { if (fp == NULL) { /* send case: the file is already there */ - if (mutt_rename_file (a->filename, tempfile)) + if (symlink (a->filename, tempfile) == -1) { if (mutt_yesorno ("Can't match nametemplate, continue?", 1) == M_YES) strfcpy (tempfile, a->filename, sizeof (tempfile)); @@ -293,19 +327,17 @@ int mutt_view_attachment (FILE *fp, BODY *a, int flag) goto return_error; } else - { - safe_free ((void **) &a->filename); - a->filename = safe_strdup (tempfile); - } + unlink_tempfile = 1; } } else if (fp == NULL) /* send case */ strfcpy (tempfile, a->filename, sizeof (tempfile)); - + if (fp) { /* recv case: we need to save the attachment to a file */ - if (mutt_save_attachment (fp, a, tempfile, 0) == -1) + FREE (&fname); + if (mutt_save_attachment (fp, a, tempfile, 0, NULL) == -1) goto return_error; } @@ -320,7 +352,7 @@ int mutt_view_attachment (FILE *fp, BODY *a, int flag) { /* recv case */ strfcpy (pagerfile, a->filename, sizeof (pagerfile)); - mutt_adv_mktemp (pagerfile); + mutt_adv_mktemp (pagerfile, sizeof(pagerfile)); } else mutt_mktemp (pagerfile); @@ -402,7 +434,7 @@ int mutt_view_attachment (FILE *fp, BODY *a, int flag) if (flag == M_AS_TEXT) { /* just let me see the raw data */ - if (mutt_save_attachment (fp, a, pagerfile, 0)) + if (mutt_save_attachment (fp, a, pagerfile, 0, NULL)) goto return_error; } else @@ -448,6 +480,9 @@ int mutt_view_attachment (FILE *fp, BODY *a, int flag) rfc1524_free_entry (&entry); if (fp && tempfile[0]) mutt_unlink (tempfile); + else if (unlink_tempfile) + unlink(tempfile); + if (pagerfile[0]) mutt_unlink (pagerfile); @@ -457,15 +492,13 @@ int mutt_view_attachment (FILE *fp, BODY *a, int flag) /* returns 1 on success, 0 on error */ int mutt_pipe_attachment (FILE *fp, BODY *b, const char *path, char *outfile) { - STATE o; pid_t thepid; - - memset (&o, 0, sizeof (STATE)); + int out = -1; if (outfile && *outfile) - if ((o.fpout = safe_fopen (outfile, "w")) == NULL) + if ((out = safe_open (outfile, O_CREAT | O_EXCL | O_WRONLY)) < 0) { - mutt_perror ("fopen"); + mutt_perror ("open"); return 0; } @@ -480,7 +513,7 @@ int mutt_pipe_attachment (FILE *fp, BODY *b, const char *path, char *outfile) memset (&s, 0, sizeof (STATE)); if (outfile && *outfile) - thepid = mutt_create_filter (path, &s.fpout, &o.fpin, NULL); + thepid = mutt_create_filter_fd (path, &s.fpout, NULL, NULL, -1, out, -1); else thepid = mutt_create_filter (path, &s.fpout, NULL, NULL); @@ -497,12 +530,16 @@ int mutt_pipe_attachment (FILE *fp, BODY *b, const char *path, char *outfile) if ((ifp = fopen (b->filename, "r")) == NULL) { mutt_perror ("fopen"); - fclose (o.fpout); + if (outfile && *outfile) + { + close (out); + unlink (outfile); + } return 0; } if (outfile && *outfile) - thepid = mutt_create_filter (path, &ofp, &o.fpin, NULL); + thepid = mutt_create_filter_fd (path, &ofp, NULL, NULL, -1, out, -1); else thepid = mutt_create_filter (path, &ofp, NULL, NULL); @@ -512,11 +549,7 @@ int mutt_pipe_attachment (FILE *fp, BODY *b, const char *path, char *outfile) } if (outfile && *outfile) - { - mutt_copy_stream (o.fpin, o.fpout); - fclose (o.fpin); - fclose (o.fpout); - } + close (out); if (mutt_wait_filter (thepid) != 0 || option (OPTWAITKEY)) mutt_any_key_to_continue (NULL); @@ -524,31 +557,76 @@ int mutt_pipe_attachment (FILE *fp, BODY *b, const char *path, char *outfile) } /* returns 0 on success, -1 on error */ -int mutt_save_attachment (FILE *fp, BODY *m, char *path, int flags) +int mutt_save_attachment (FILE *fp, BODY *m, char *path, int flags, HEADER *hdr) { if (fp) { - /* In recv mode, extract from folder and decode */ + + /* recv mode */ - STATE s; - - memset (&s, 0, sizeof (s)); - if (flags == M_SAVE_APPEND) - s.fpout = safe_fopen (path, "a"); - else - s.fpout = fopen (path, "w"); - if (s.fpout == NULL) + if(hdr && + m->hdr && + m->encoding != ENCBASE64 && + m->encoding != ENCQUOTEDPRINTABLE && + mutt_is_message_type(m->type, m->subtype)) { - mutt_perror ("fopen"); - return (-1); + /* message type attachments are written to mail folders. */ + + char buf[HUGE_STRING]; + HEADER *hn; + CONTEXT ctx; + MESSAGE *msg; + int chflags = 0; + int r = -1; + + hn = m->hdr; + hn->msgno = hdr->msgno; /* required for MH/maildir */ + hn->read = 1; + + fseek (fp, m->offset, 0); + if (fgets (buf, sizeof (buf), fp) == NULL) + return -1; + if (mx_open_mailbox(path, M_APPEND | M_QUIET, &ctx) == NULL) + return -1; + if ((msg = mx_open_new_message (&ctx, hn, is_from (buf, NULL, 0) ? 0 : M_ADD_FROM)) == NULL) + { + mx_close_mailbox(&ctx); + return -1; + } + if (ctx.magic == M_MBOX || ctx.magic == M_MMDF) + chflags = CH_FROM; + chflags |= (ctx.magic == M_MAILDIR ? CH_NOSTATUS : CH_UPDATE); + if ((r = _mutt_copy_message (msg->fp, fp, hn, hn->content, 0, chflags)) == 0) + mutt_message("Attachment saved."); + + mx_close_message (&msg); + mx_close_mailbox(&ctx); + return r; } - fseek ((s.fpin = fp), m->offset, 0); - mutt_decode_attachment (m, &s); - - if (fclose (s.fpout) != 0) + else { - mutt_perror ("fclose"); - return (-1); + /* In recv mode, extract from folder and decode */ + + STATE s; + + memset (&s, 0, sizeof (s)); + if (flags == M_SAVE_APPEND) + s.fpout = safe_fopen (path, "a"); + else + s.fpout = fopen (path, "w"); + if (s.fpout == NULL) + { + mutt_perror ("fopen"); + return (-1); + } + fseek ((s.fpin = fp), m->offset, 0); + mutt_decode_attachment (m, &s); + + if (fclose (s.fpout) != 0) + { + mutt_perror ("fclose"); + return (-1); + } } } else @@ -590,6 +668,8 @@ int mutt_decode_save_attachment (FILE *fp, BODY *m, char *path, { STATE s; unsigned int saved_encoding = 0; + BODY *saved_parts = NULL; + HEADER *saved_hdr = NULL; memset (&s, 0, sizeof (s)); s.flags = displaying ? M_DISPLAY : 0; @@ -627,10 +707,12 @@ int mutt_decode_save_attachment (FILE *fp, BODY *m, char *path, m->length = st.st_size; m->encoding = ENC8BIT; m->offset = 0; - if (m->type == TYPEMESSAGE && m->subtype && - (!strcasecmp (m->subtype,"rfc822") || - !strcasecmp (m->subtype, "news"))) + if (mutt_is_message_type(m->type, m->subtype)) + { + saved_parts = m->parts; + saved_hdr = m->hdr; m->parts = mutt_parse_messageRFC822 (s.fpin, m); + } } else s.fpin = fp; @@ -642,8 +724,12 @@ int mutt_decode_save_attachment (FILE *fp, BODY *m, char *path, { m->length = 0; m->encoding = saved_encoding; - if (m->parts) - mutt_free_body (&m->parts); + if (saved_parts) + { + mutt_free_header (&m->hdr); + m->parts = saved_parts; + m->hdr = saved_hdr; + } fclose (s.fpin); } @@ -663,8 +749,9 @@ int mutt_print_attachment (FILE *fp, BODY *a) char type[STRING]; pid_t thepid; FILE *ifp, *fpout; - - snprintf (type, sizeof (type), "%s/%s", TYPE (a->type), a->subtype); + short unlink_newfile = 0; + + snprintf (type, sizeof (type), "%s/%s", TYPE (a), a->subtype); if (rfc1524_mailcap_lookup (a, type, NULL, M_PRINT)) { @@ -679,9 +766,7 @@ int mutt_print_attachment (FILE *fp, BODY *a) { if (!fp) { - /* only attempt file move in send mode */ - - if (mutt_rename_file (a->filename, newfile)) + if (symlink(a->filename, newfile) == -1) { if (mutt_yesorno ("Can't match nametemplate, continue?", 1) != M_YES) { @@ -691,16 +776,13 @@ int mutt_print_attachment (FILE *fp, BODY *a) strfcpy (newfile, a->filename, sizeof (newfile)); } else - { - safe_free ((void **)&a->filename); - a->filename = safe_strdup (newfile); - } + unlink_newfile = 1; } } /* in recv mode, save file to newfile first */ if (fp) - mutt_save_attachment (fp, a, newfile, 0); + mutt_save_attachment (fp, a, newfile, 0, NULL); strfcpy (command, entry->printcommand, sizeof (command)); piped = rfc1524_expand_command (a, newfile, type, command, sizeof (command)); @@ -732,6 +814,8 @@ int mutt_print_attachment (FILE *fp, BODY *a) if (fp) mutt_unlink (newfile); + else if (unlink_newfile) + unlink(newfile); rfc1524_free_entry (&entry); return (1); @@ -739,7 +823,9 @@ int mutt_print_attachment (FILE *fp, BODY *a) if (!strcasecmp ("text/plain", a->subtype) || !strcasecmp ("application/postscript", a->subtype)) - return (mutt_pipe_attachment (fp, a, PrintCmd, NULL)); + { + return (mutt_pipe_attachment (fp, a, NONULL(PrintCmd), NULL)); + } else if (mutt_can_decode (a)) { /* decode and print */ @@ -752,7 +838,7 @@ int mutt_print_attachment (FILE *fp, BODY *a) if ((ifp = fopen (newfile, "r")) != NULL) { endwin (); - thepid = mutt_create_filter (PrintCmd, &fpout, NULL, NULL); + thepid = mutt_create_filter (NONULL(PrintCmd), &fpout, NULL, NULL); mutt_copy_stream (ifp, fpout); fclose (ifp); fclose (fpout); diff --git a/attach.h b/attach.h index 46e374dc..32e9d0d5 100644 --- a/attach.h +++ b/attach.h @@ -20,7 +20,7 @@ int mutt_tag_attach (MUTTMENU *menu, int n); -void mutt_save_attachment_list (FILE *fp, int tag, BODY *top); +void mutt_save_attachment_list (FILE *fp, int tag, BODY *top, HEADER *hdr); void mutt_pipe_attachment_list (FILE *fp, int tag, BODY *top, int filter); void mutt_print_attachment_list (FILE *fp, int tag, BODY *top); void mutt_attach_display_loop (MUTTMENU *menu, int op, FILE *fp, ATTACHPTR **idx); diff --git a/bind.c b/bind.c deleted file mode 100644 index a327bf70..00000000 --- a/bind.c +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (C) 1996-8 Michael R. Elkins - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include "mutt.h" -#include "mutt_curses.h" -#include "keymap.h" -#include "mapping.h" - -#include - -static struct mapping_t Menus[] = { - { "alias", MENU_ALIAS }, - { "attach", MENU_ATTACH }, - { "browser", MENU_FOLDER }, - { "compose", MENU_COMPOSE }, - { "editor", MENU_EDITOR }, - { "generic", MENU_GENERIC }, - { "index", MENU_MAIN }, - { "pager", MENU_PAGER }, - - - -#ifdef _PGPPATH - { "pgp", MENU_PGP }, -#endif /* _PGPPATH */ - - - - { NULL, 0 } -}; - -#define mutt_check_menu(s) mutt_getvaluebyname(s, Menus) - -/* expects to see: */ -static const char *parse_keymap (int *menu, - char *key, - size_t keylen, - const char *s, - char *err, - size_t errlen) -{ - char buf[SHORT_STRING]; - char expn[SHORT_STRING]; - - /* menu name */ - s = mutt_extract_token (buf, sizeof (buf), s, expn, sizeof (expn), 0); - - if (s) - { - if ((*menu = mutt_check_menu (buf)) == -1) - { - snprintf (err, errlen, "%s: no such menu", s); - return (NULL); - } - - /* key sequence */ - s = mutt_extract_token (key, keylen, s, expn, sizeof (expn), 0); - - if (s) - return s; - } - - strfcpy (err, "too few arguments", errlen); - return (NULL); -} - -static int -try_bind (char *key, int menu, char *func, struct binding_t *bindings) -{ - int i; - - for (i = 0; bindings[i].name; i++) - if (strcmp (func, bindings[i].name) == 0) - { - km_bindkey (key, menu, bindings[i].op, NULL); - return (0); - } - return (-1); -} - -/* bind menu-name '' function-name */ -int mutt_parse_bind (const char *s, unsigned long data, char *err, size_t errlen) -{ - struct binding_t *bindings = NULL; - char buf[SHORT_STRING]; - char key[SHORT_STRING]; - char expn[SHORT_STRING]; - int menu; - - if ((s = parse_keymap (&menu, key, sizeof (key), s, err, errlen)) == NULL) - return (-1); - - switch (menu) - { - case MENU_MAIN: - bindings = OpMain; - break; - case MENU_GENERIC: - bindings = OpGeneric; - break; - case MENU_COMPOSE: - bindings = OpCompose; - break; - case MENU_PAGER: - bindings = OpPager; - break; - case MENU_POST: - bindings = OpPost; - break; - case MENU_FOLDER: - bindings = OpBrowser; - break; - case MENU_ATTACH: - bindings = OpAttach; - break; - case MENU_EDITOR: - bindings = OpEditor; - break; - case MENU_ALIAS: - bindings = OpAlias; - break; - - - -#ifdef _PGPPATH - case MENU_PGP: - bindings = OpPgp; - break; -#endif /* _PGPPATH */ - - - - } - - /* function to execute */ - s = mutt_extract_token (buf, sizeof (buf), s, expn, sizeof (expn), 0); - if (s) - { - strfcpy (err, "too many arguments", errlen); - return (-1); - } - - if (strcasecmp ("noop", buf) == 0) - { - km_bindkey (key, menu, OP_NULL, NULL); - return 0; - } - - if (menu != MENU_PAGER && menu != MENU_EDITOR && menu != MENU_GENERIC) - { - /* First check the "generic" list of commands. */ - if (try_bind (key, menu, buf, OpGeneric) == 0) - return 0; - } - - /* Now check the menu-specific list of commands (if they exist). */ - if (bindings && try_bind (key, menu, buf, bindings) == 0) - return 0; - - snprintf (err, errlen, "%s: no such function in map", buf); - return (-1); -} - -/* macro */ -int mutt_parse_macro (const char *s, unsigned long data, char *err, size_t errlen) -{ - int menu; - char key[SHORT_STRING]; - char buf[SHORT_STRING]; - char expn[SHORT_STRING]; - - if ((s = parse_keymap (&menu, key, sizeof (key), s, err, errlen)) == NULL) - return (-1); - - s = mutt_extract_token (buf, sizeof (buf), s, expn, sizeof (expn), M_CONDENSE); - if (s) - { - strfcpy (err, "too many arguments", errlen); - return (-1); - } - - km_bindkey (key, menu, OP_MACRO, buf); - - return 0; -} diff --git a/browser.c b/browser.c index b66982cf..a90d5173 100644 --- a/browser.c +++ b/browser.c @@ -20,12 +20,14 @@ #include "mutt_curses.h" #include "mutt_menu.h" #include "buffy.h" +#include "mapping.h" #include "sort.h" #include "mailbox.h" #include #include #include +#include #include #include #include @@ -149,79 +151,135 @@ folder_format_str (char *dest, size_t destlen, char op, const char *src, const char *fmt, const char *ifstring, const char *elsestring, unsigned long data, format_flag flags) { - char fn[SHORT_STRING], tmp[SHORT_STRING], permission[10]; + char fn[SHORT_STRING], tmp[SHORT_STRING], permission[11]; char date[16], *t_fmt; time_t tnow; FOLDER *folder = (FOLDER *) data; struct passwd *pw; struct group *gr; - + switch (op) { case 'd': - tnow = time (NULL); - t_fmt = tnow - folder->f->st_mtime < 31536000 ? "%b %d %H:%M" : "%b %d %Y"; - strftime (date, sizeof (date), t_fmt, localtime (&folder->f->st_mtime)); - snprintf (tmp, sizeof (tmp), "%%%ss", fmt); - snprintf (dest, destlen, tmp, date); + if (folder->f != NULL) + { + tnow = time (NULL); + t_fmt = tnow - folder->f->st_mtime < 31536000 ? "%b %d %H:%M" : "%b %d %Y"; + strftime (date, sizeof (date), t_fmt, localtime (&folder->f->st_mtime)); + snprintf (tmp, sizeof (tmp), "%%%ss", fmt); + snprintf (dest, destlen, tmp, date); + } + else + { + snprintf (tmp, sizeof (tmp), "%%%ss", fmt); + snprintf (dest, destlen, tmp, ""); + } break; case 'f': strncpy (fn, folder->name, sizeof(fn) - 1); - strcat (fn, S_ISLNK (folder->f->st_mode) ? "@" : - (S_ISDIR (folder->f->st_mode) ? "/" : - ((folder->f->st_mode & S_IXUSR) != 0 ? "*" : ""))); + if (folder->f != NULL) + { + strcat (fn, S_ISLNK (folder->f->st_mode) ? "@" : + (S_ISDIR (folder->f->st_mode) ? "/" : + ((folder->f->st_mode & S_IXUSR) != 0 ? "*" : ""))); + } snprintf (tmp, sizeof (tmp), "%%%ss", fmt); snprintf (dest, destlen, tmp, fn); break; case 'F': - sprintf (permission, "%c%c%c%c%c%c%c%c%c%c", - S_ISDIR(folder->f->st_mode) ? 'd' : (S_ISLNK(folder->f->st_mode) ? 'l' : '-'), - (folder->f->st_mode & S_IRUSR) != 0 ? 'r': '-', - (folder->f->st_mode & S_IWUSR) != 0 ? 'w' : '-', - (folder->f->st_mode & S_ISUID) != 0 ? 's' : (folder->f->st_mode & S_IXUSR) != 0 ? 'x': '-', - (folder->f->st_mode & S_IRGRP) != 0 ? 'r' : '-', - (folder->f->st_mode & S_IWGRP) != 0 ? 'w' : '-', - (folder->f->st_mode & S_ISGID) != 0 ? 's' : (folder->f->st_mode & S_IXGRP) != 0 ? 'x': '-', - (folder->f->st_mode & S_IROTH) != 0 ? 'r' : '-', - (folder->f->st_mode & S_IWOTH) != 0 ? 'w' : '-', - (folder->f->st_mode & S_ISVTX) != 0 ? 't' : (folder->f->st_mode & S_IXOTH) != 0 ? 'x': '-'); - snprintf (tmp, sizeof (tmp), "%%%ss", fmt); - snprintf (dest, destlen, tmp, permission); + if (folder->f != NULL) + { + sprintf (permission, "%c%c%c%c%c%c%c%c%c%c", + S_ISDIR(folder->f->st_mode) ? 'd' : (S_ISLNK(folder->f->st_mode) ? 'l' : '-'), + (folder->f->st_mode & S_IRUSR) != 0 ? 'r': '-', + (folder->f->st_mode & S_IWUSR) != 0 ? 'w' : '-', + (folder->f->st_mode & S_ISUID) != 0 ? 's' : (folder->f->st_mode & S_IXUSR) != 0 ? 'x': '-', + (folder->f->st_mode & S_IRGRP) != 0 ? 'r' : '-', + (folder->f->st_mode & S_IWGRP) != 0 ? 'w' : '-', + (folder->f->st_mode & S_ISGID) != 0 ? 's' : (folder->f->st_mode & S_IXGRP) != 0 ? 'x': '-', + (folder->f->st_mode & S_IROTH) != 0 ? 'r' : '-', + (folder->f->st_mode & S_IWOTH) != 0 ? 'w' : '-', + (folder->f->st_mode & S_ISVTX) != 0 ? 't' : (folder->f->st_mode & S_IXOTH) != 0 ? 'x': '-'); + snprintf (tmp, sizeof (tmp), "%%%ss", fmt); + snprintf (dest, destlen, tmp, permission); + } + else + { +#ifdef USE_IMAP + if (strchr(folder->name, '{')) + { + snprintf (tmp, sizeof (tmp), "%%%ss", fmt); + snprintf (dest, destlen, tmp, "IMAP"); + } +#endif + } break; case 'g': - if ((gr = getgrgid (folder->f->st_gid))) + if (folder->f != NULL) { - snprintf (tmp, sizeof (tmp), "%%%ss", fmt); - snprintf (dest, destlen, tmp, gr->gr_name); + if ((gr = getgrgid (folder->f->st_gid))) + { + snprintf (tmp, sizeof (tmp), "%%%ss", fmt); + snprintf (dest, destlen, tmp, gr->gr_name); + } + else + { + snprintf (tmp, sizeof (tmp), "%%%sld", fmt); + snprintf (dest, destlen, tmp, folder->f->st_gid); + } } else { - snprintf (tmp, sizeof (tmp), "%%%sld", fmt); - snprintf (dest, destlen, tmp, folder->f->st_gid); + snprintf (tmp, sizeof (tmp), "%%%ss", fmt); + snprintf (dest, destlen, tmp, ""); } break; case 'l': - snprintf (tmp, sizeof (tmp), "%%%sd", fmt); - snprintf (dest, destlen, tmp, folder->f->st_nlink); + if (folder->f != NULL) + { + snprintf (tmp, sizeof (tmp), "%%%sd", fmt); + snprintf (dest, destlen, tmp, folder->f->st_nlink); + } + else + { + snprintf (tmp, sizeof (tmp), "%%%ss", fmt); + snprintf (dest, destlen, tmp, ""); + } break; case 'N': snprintf (tmp, sizeof (tmp), "%%%sc", fmt); snprintf (dest, destlen, tmp, folder->new ? 'N' : ' '); break; case 's': - snprintf (tmp, sizeof (tmp), "%%%sld", fmt); - snprintf (dest, destlen, tmp, (long) folder->f->st_size); + if (folder->f != NULL) + { + snprintf (tmp, sizeof (tmp), "%%%sld", fmt); + snprintf (dest, destlen, tmp, (long) folder->f->st_size); + } + else + { + snprintf (tmp, sizeof (tmp), "%%%ss", fmt); + snprintf (dest, destlen, tmp, ""); + } break; case 'u': - if ((pw = getpwuid (folder->f->st_uid))) + if (folder->f != NULL) { - snprintf (tmp, sizeof (tmp), "%%%ss", fmt); - snprintf (dest, destlen, tmp, pw->pw_name); + if ((pw = getpwuid (folder->f->st_uid))) + { + snprintf (tmp, sizeof (tmp), "%%%ss", fmt); + snprintf (dest, destlen, tmp, pw->pw_name); + } + else + { + snprintf (tmp, sizeof (tmp), "%%%sld", fmt); + snprintf (dest, destlen, tmp, folder->f->st_uid); + } } else { - snprintf (tmp, sizeof (tmp), "%%%sld", fmt); - snprintf (dest, destlen, tmp, folder->f->st_uid); + snprintf (tmp, sizeof (tmp), "%%%ss", fmt); + snprintf (dest, destlen, tmp, ""); } break; } @@ -237,7 +295,7 @@ static void add_folder (MUTTMENU *m, struct browser_state *state, folder.name = name; folder.f = s; folder.new = new; - mutt_FormatString (buffer, sizeof (buffer), FolderFormat, folder_format_str, + mutt_FormatString (buffer, sizeof (buffer), NONULL(FolderFormat), folder_format_str, (unsigned long) &folder, 0); if (state->entrylen == state->entrymax) @@ -249,9 +307,12 @@ static void add_folder (MUTTMENU *m, struct browser_state *state, m->data = state->entry; } + if (s != NULL) + { (state->entry)[state->entrylen].mode = s->st_mode; (state->entry)[state->entrylen].mtime = s->st_mtime; (state->entry)[state->entrylen].size = s->st_size; + } (state->entry)[state->entrylen].name = safe_strdup (name); (state->entry)[state->entrylen].desc = safe_strdup (buffer); @@ -305,7 +366,7 @@ static int examine_directory (MUTTMENU *menu, struct browser_state *state, if (prefix && *prefix && strncmp (prefix, de->d_name, strlen (prefix)) != 0) continue; - if (regexec (Mask.rx, de->d_name, 0, NULL, 0) != 0) + if (!((regexec (Mask.rx, de->d_name, 0, NULL, 0) == 0) ^ Mask.not)) continue; snprintf (buffer, sizeof (buffer), "%s/%s", d, de->d_name); @@ -317,7 +378,7 @@ static int examine_directory (MUTTMENU *menu, struct browser_state *state, continue; tmp = Incoming; - while (tmp && strcmp (buffer, tmp->path)) + while (tmp && strcmp (buffer, NONULL(tmp->path))) tmp = tmp->next; add_folder (menu, state, de->d_name, &s, (tmp) ? tmp->new : 0); } @@ -340,6 +401,13 @@ static int examine_mailboxes (MUTTMENU *menu, struct browser_state *state) do { +#ifdef USE_IMAP + if (tmp->path[0] == '{') + { + add_folder (menu, state, tmp->path, NULL, tmp->new); + continue; + } +#endif if (lstat (tmp->path, &s) == -1) continue; @@ -347,7 +415,7 @@ static int examine_mailboxes (MUTTMENU *menu, struct browser_state *state) (! S_ISLNK (s.st_mode))) continue; - strfcpy (buffer, tmp->path, sizeof (buffer)); + strfcpy (buffer, NONULL(tmp->path), sizeof (buffer)); mutt_pretty_mailbox (buffer); add_folder (menu, state, buffer, &s, tmp->new); @@ -372,9 +440,13 @@ static void init_menu (struct browser_state *state, MUTTMENU *menu, char *title, { char path[_POSIX_PATH_MAX]; - menu->current = 0; - menu->top = 0; menu->max = state->entrylen; + + if(menu->current >= menu->max) + menu->current = menu->max - 1; + if (menu->current < 0) + menu->current = 0; + if (buffy) snprintf (title, titlelen, "Mailboxes [%d]", mutt_buffy_check (0)); else @@ -389,7 +461,7 @@ static void init_menu (struct browser_state *state, MUTTMENU *menu, char *title, void mutt_select_file (char *f, size_t flen, int buffy) { - char buf[STRING]; + char buf[_POSIX_PATH_MAX]; char prefix[_POSIX_PATH_MAX] = ""; char helpstr[SHORT_STRING]; char title[STRING]; @@ -434,7 +506,7 @@ void mutt_select_file (char *f, size_t flen, int buffy) killPrefix = 1; } else if (!LastDir[0]) - strfcpy (LastDir, Maildir, sizeof (LastDir)); + strfcpy (LastDir, NONULL(Maildir), sizeof (LastDir)); *f = 0; @@ -531,10 +603,12 @@ void mutt_select_file (char *f, size_t flen, int buffy) strfcpy (LastDir, OldLastDir, sizeof (LastDir)); if (examine_directory (menu, &state, LastDir, prefix) == -1) { - strfcpy (LastDir, Homedir, sizeof (LastDir)); + strfcpy (LastDir, NONULL(Homedir), sizeof (LastDir)); return; } } + menu->current = 0; + menu->top = 0; init_menu (&state, menu, title, sizeof (title), buffy); break; } @@ -559,6 +633,12 @@ void mutt_select_file (char *f, size_t flen, int buffy) case OP_CHANGE_DIRECTORY: strfcpy (buf, LastDir, sizeof (buf)); + {/* add '/' at the end of the directory name */ + int len=strlen(LastDir); + if (sizeof (buf) > len) + buf[len]='/'; + } + if (mutt_get_field ("Chdir to: ", buf, sizeof (buf), M_FILE) == 0 && buf[0]) { @@ -571,7 +651,11 @@ void mutt_select_file (char *f, size_t flen, int buffy) strfcpy (LastDir, buf, sizeof (LastDir)); destroy_state (&state); if (examine_directory (menu, &state, LastDir, prefix) == 0) + { + menu->current = 0; + menu->top = 0; init_menu (&state, menu, title, sizeof (title), buffy); + } else { mutt_error ("Error scanning directory."); @@ -595,14 +679,22 @@ void mutt_select_file (char *f, size_t flen, int buffy) if (mutt_get_field ("File Mask: ", buf, sizeof (buf), 0) == 0) { regex_t *rx = (regex_t *) safe_malloc (sizeof (regex_t)); - int err; + char *s = buf; + int not = 0, err; buffy = 0; /* assume that the user wants to see everything */ if (!buf[0]) strfcpy (buf, ".", sizeof (buf)); + SKIPWS (s); + if (*s == '!') + { + s++; + SKIPWS (s); + not = 1; + } - if ((err = REGCOMP (rx, buf, REG_NOSUB | mutt_which_case (buf))) != 0) + if ((err = REGCOMP (rx, s, REG_NOSUB)) != 0) { regerror (err, rx, buf, sizeof (buf)); regfree (rx); @@ -616,6 +708,7 @@ void mutt_select_file (char *f, size_t flen, int buffy) safe_free ((void **) &Mask.rx); Mask.pattern = safe_strdup (buf); Mask.rx = rx; + Mask.not = not; destroy_state (&state); if (examine_directory (menu, &state, LastDir, NULL) == 0) @@ -627,6 +720,11 @@ void mutt_select_file (char *f, size_t flen, int buffy) return; } killPrefix = 0; + if (!state.entrylen) + { + mutt_error ("No files match the file mask"); + break; + } } } MAYBE_REDRAW (menu->redraw); @@ -680,9 +778,10 @@ void mutt_select_file (char *f, size_t flen, int buffy) break; - case OP_CHECK_NEW: - + case OP_TOGGLE_MAILBOXES: buffy = 1 - buffy; + + case OP_CHECK_NEW: destroy_state (&state); prefix[0] = 0; killPrefix = 0; @@ -708,6 +807,38 @@ void mutt_select_file (char *f, size_t flen, int buffy) } MAYBE_REDRAW (menu->redraw); break; + + case OP_BROWSER_VIEW_FILE: + if (!state.entrylen) + { + mutt_error ("No files match the file mask"); + break; + } + + if (S_ISDIR (state.entry[menu->current].mode) || + (S_ISLNK (state.entry[menu->current].mode) && + link_is_dir (state.entry[menu->current].name))) + { + mutt_error ("Can't view a directory"); + break; + } + else + { + BODY *b; + char buf[_POSIX_PATH_MAX]; + + snprintf (buf, sizeof (buf), "%s/%s", LastDir, + state.entry[menu->current].name); + b = mutt_make_file_attach (buf); + if (b != NULL) + { + mutt_view_attachment (NULL, b, M_REGULAR); + mutt_free_body (&b); + menu->redraw = REDRAW_FULL; + } + else + mutt_error ("Error trying to view file"); + } } } /* not reached */ diff --git a/buffy.c b/buffy.c index 1fa1d7cf..98c1a0ef 100644 --- a/buffy.c +++ b/buffy.c @@ -20,12 +20,16 @@ #include "buffy.h" #include "mx.h" #include "mailbox.h" +#ifdef USE_IMAP +#include "imap.h" +#endif #include #include #include #include #include +#include #include @@ -241,6 +245,13 @@ int mutt_buffy_check (int force) { tmp->new = 0; +#ifdef USE_IMAP + if ((tmp->magic == M_IMAP) || mx_is_imap (tmp->path)) + { + tmp->magic = M_IMAP; + } + else +#endif if (stat (tmp->path, &sb) != 0 || (!tmp->magic && (tmp->magic = mx_get_magic (tmp->path)) <= 0)) { @@ -315,6 +326,16 @@ int mutt_buffy_check (int force) tmp->magic = 0; } break; + +#ifdef USE_IMAP + case M_IMAP: + if (imap_buffy_check (tmp->path) > 0) + { + BuffyCount++; + tmp->new = 1; + } + break; +#endif } } #ifdef BUFFY_SIZE diff --git a/color.c b/color.c index 66bcd8b3..11872f0a 100644 --- a/color.c +++ b/color.c @@ -94,6 +94,40 @@ static struct mapping_t Fields[] = #define COLOR_QUOTE_INIT 8 +static COLOR_LINE *mutt_new_color_line (void) +{ + COLOR_LINE *p = safe_calloc (1, sizeof (COLOR_LINE)); + + p->fg = p->bg = -1; + + return (p); +} + +static void mutt_free_color_line(COLOR_LINE **l, + int free_colors) +{ + COLOR_LINE *tmp; + + if(!l || !*l) + return; + + tmp = *l; + +#ifdef HAVE_COLOR + if(free_colors && tmp->fg != -1 && tmp->bg != -1) + mutt_free_color(tmp->fg, tmp->bg); +#endif + + /* we should really introduce a container + * type for regular expressions. + */ + + regfree(&tmp->rx); + mutt_pattern_free(&tmp->color_pattern); + safe_free((void **)&tmp->pattern); + safe_free((void **)l); +} + void ci_start_color (void) { memset (ColorDefs, A_NORMAL, sizeof (int) * MT_COLOR_MAX); @@ -198,7 +232,7 @@ int mutt_alloc_color (int fg, int bg) bg = -1; #endif - init_pair (i, fg, bg); + init_pair(i, fg, bg); dprint(1,(debugfile,"mutt_alloc_color(): Color pairs used so far: %d\n", UserColors)); @@ -247,87 +281,6 @@ void mutt_free_color (int fg, int bg) #endif /* HAVE_COLOR */ -static COLOR_LINE *mutt_new_color_line (void) -{ - COLOR_LINE *p = safe_calloc (1, sizeof (COLOR_LINE)); - - return (p); -} - -static int add_pattern (COLOR_LINE **top, const char *s, int sensitive, - int fg, int bg, int attr, BUFFER *err, - /* is_index used to store compiled pattern - only for `index' color object - when called from mutt_parse_color() */ - int is_index) -{ - COLOR_LINE *tmp = *top; - - while (tmp) - { - if (sensitive) - { - if (strcmp (s, tmp->pattern) == 0) - break; - } - else - { - if (strcasecmp (s, tmp->pattern) == 0) - break; - } - tmp = tmp->next; - } - - if (tmp) - { -#ifdef HAVE_COLOR - if (fg != -1 && bg != -1) - { - if (tmp->fg != fg || tmp->bg != bg) - { - mutt_free_color (tmp->fg, tmp->bg); - tmp->fg = fg; - tmp->bg = bg; - attr |= mutt_alloc_color (fg, bg); - } - else - attr |= (tmp->pair & ~A_BOLD); - } -#endif /* HAVE_COLOR */ - tmp->pair = attr; - } - else - { - int r; - char buf[STRING]; - - tmp = mutt_new_color_line (); - if ((r = REGCOMP (&tmp->rx, s, (sensitive ? mutt_which_case (s) : REG_ICASE))) != 0) - { - regerror (r, &tmp->rx, err->data, err->dsize); - regfree (&tmp->rx); - safe_free ((void **) &tmp); - return (-1); - } - tmp->next = *top; - tmp->pattern = safe_strdup (s); -#ifdef HAVE_COLOR - tmp->fg = fg; - tmp->bg = bg; - attr |= mutt_alloc_color (fg, bg); - if (is_index) - { - strcpy(buf,tmp->pattern); - mutt_check_simple (buf, sizeof (buf), SimpleSearch); - tmp->color_pattern = mutt_pattern_comp (buf, M_FULL_MSG, err); - } -#endif - tmp->pair = attr; - *top = tmp; - } - - return 0; -} #ifdef HAVE_COLOR @@ -360,19 +313,40 @@ parse_color_name (const char *s, int *col, int *attr, int brite, BUFFER *err) return (-1); } -#ifdef HAVE_USE_DEFAULT_COLORS - if (*col == COLOR_DEFAULT && use_default_colors () != OK) - { - strfcpy (err->data, "default colors not supported", err->dsize); - return (-1); - } + return 0; +} + #endif - return 0; + +/* usage: uncolor index pattern [pattern...] + * unmono index pattern [pattern...] + */ + +static int +_mutt_parse_uncolor (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err, + short parse_uncolor); + + +#ifdef HAVE_COLOR + +int mutt_parse_uncolor (BUFFER *buf, BUFFER *s, unsigned long data, + BUFFER *err) +{ + return _mutt_parse_uncolor(buf, s, data, err, 1); } -/* usage: uncolor index pattern [pattern...] */ -int mutt_parse_uncolor (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err) +#endif + +int mutt_parse_unmono (BUFFER *buf, BUFFER *s, unsigned long data, + BUFFER *err) +{ + return _mutt_parse_uncolor(buf, s, data, err, 0); +} + +static int +_mutt_parse_uncolor (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err, + short parse_uncolor) { int object = 0, do_cache = 0; COLOR_LINE *tmp, *last = NULL; @@ -387,17 +361,33 @@ int mutt_parse_uncolor (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err) if (strncmp (buf->data, "index", 5) != 0) { - strfcpy (err->data, "uncolor: command valid only for index object", err->dsize); - return (-1); + snprintf (err->data, err->dsize, + "%s: command valid only for index object", + parse_uncolor ? "uncolor" : "unmono"); + return (-1); } - + if (!MoreArgs (s)) { - strfcpy (err->data, "uncolor: too few arguments", err->dsize); + snprintf (err->data, err->dsize, + "%s: too few arguments", parse_uncolor ? "uncolor" : "unmono"); return (-1); } - while (MoreArgs (s)) + if( +#ifdef HAVE_COLOR + (parse_uncolor && !has_colors()) + || (!parse_uncolor && has_colors()) +#else + parse_uncolor +#endif + ) + { + return 0; + } + + + do { mutt_extract_token (buf, s, 0); if (!strcmp ("*", buf->data)) @@ -408,9 +398,7 @@ int mutt_parse_uncolor (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err) do_cache = 1; last = tmp; tmp = tmp->next; - mutt_pattern_free (&last->color_pattern); - mutt_free_color(last->fg,last->bg); - safe_free ((void **) &last); + mutt_free_color_line(&last, parse_uncolor); } ColorIndexList = NULL; } @@ -428,194 +416,187 @@ int mutt_parse_uncolor (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err) last->next = tmp->next; else ColorIndexList = tmp->next; - mutt_pattern_free (&tmp->color_pattern); - mutt_free_color(tmp->fg,tmp->bg); - safe_free ((void **) &tmp); + mutt_free_color_line(&tmp, parse_uncolor); break; } } } } - - if (do_cache && !option (OPTNOCURSES) && has_colors ()) - { - mutt_cache_index_colors (Context); - set_option (OPTFORCEREDRAWINDEX); - } - - return (0); -} + while (MoreArgs (s)); -/* usage: color [ ] */ -int mutt_parse_color (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err) -{ - int object = 0, bold = 0, fg = 0, bg = 0, q_level = 0; - int r = 0; - char *eptr; - mutt_extract_token (buf, s, 0); - if (!strncmp (buf->data, "quoted", 6)) + if (do_cache && !option (OPTNOCURSES)) { - if (buf->data[6]) - { - q_level = strtol (buf->data + 6, &eptr, 10); - if (*eptr || q_level < 0) - { - snprintf (err->data, err->dsize, "%s: no such object", buf->data); - return (-1); - } - } - object = MT_COLOR_QUOTED; - } - else if ((object = mutt_getvaluebyname (buf->data, Fields)) == -1) - { - snprintf (err->data, err->dsize, "%s: no such object", buf->data); - return (-1); + mutt_cache_index_colors (Context); + set_option (OPTFORCEREDRAWINDEX); } + return (0); +} - /* first color */ - if (! MoreArgs (s)) - { - strfcpy (err->data, "color: too few arguments", err->dsize); - return (-1); - } - mutt_extract_token (buf, s, 0); - if (parse_color_name (buf->data, &fg, &bold, A_BOLD, err) != 0) - return (-1); +static int +add_pattern (COLOR_LINE **top, const char *s, int sensitive, + int fg, int bg, int attr, BUFFER *err, + int is_index) +{ - /* second color */ - if (! MoreArgs (s)) - { - strfcpy (err->data, "color: too few arguments", err->dsize); - return (-1); - } - mutt_extract_token (buf, s, 0); + /* is_index used to store compiled pattern + * only for `index' color object + * when called from mutt_parse_color() */ - /* A_BLINK turns the background color brite on some terms */ - if (parse_color_name (buf->data, &bg, &bold, A_BLINK, err) != 0) - return (-1); + COLOR_LINE *tmp = *top; - if (object == MT_COLOR_HEADER || object == MT_COLOR_BODY || object == MT_COLOR_INDEX) + while (tmp) { - if (! MoreArgs (s)) - { - strfcpy (err->data, "color: too few arguments", err->dsize); - return (-1); - } - - mutt_extract_token (buf, s, 0); - if (MoreArgs (s)) + if (sensitive) { - strfcpy (err->data, "color: too many arguments", err->dsize); - return (-1); + if (strcmp (s, tmp->pattern) == 0) + break; } - - /* don't parse curses command if we're not using the screen */ - /* ignore color commands if we're running on a mono terminal */ - if (option (OPTNOCURSES) || !has_colors ()) + else { - return 0; + if (strcasecmp (s, tmp->pattern) == 0) + break; } + tmp = tmp->next; + } - if (object == MT_COLOR_HEADER) - r = add_pattern (&ColorHdrList, buf->data, 0, fg, bg, bold, err,0); - else if (object == MT_COLOR_BODY) - r = add_pattern (&ColorBodyList, buf->data, 1, fg, bg, bold, err, 0); - else if (object == MT_COLOR_INDEX) + if (tmp) + { +#ifdef HAVE_COLOR + if (fg != -1 && bg != -1) { - pattern_t *pat; - char tempbuf[LONG_STRING]; - - strfcpy (tempbuf, buf->data, sizeof (tempbuf)); - mutt_check_simple (tempbuf, sizeof (tempbuf), SimpleSearch); - if ((pat = mutt_pattern_comp (tempbuf, M_FULL_MSG, err)) == NULL) + if (tmp->fg != fg || tmp->bg != bg) { - mutt_pattern_free (&pat); - return (-1); + mutt_free_color (tmp->fg, tmp->bg); + tmp->fg = fg; + tmp->bg = bg; + attr |= mutt_alloc_color (fg, bg); } - r = add_pattern (&ColorIndexList, buf->data, 1, fg, bg, bold, err, 1); - mutt_cache_index_colors(Context); - set_option (OPTFORCEREDRAWINDEX); + else + attr |= (tmp->pair & ~A_BOLD); } +#endif /* HAVE_COLOR */ + tmp->pair = attr; } else { - /* don't parse curses command if we're not using the screen */ - /* ignore color commands if we're running on a mono terminal */ - if (option (OPTNOCURSES) || !has_colors ()) + int r; + char buf[STRING]; + + tmp = mutt_new_color_line (); + if ((r = REGCOMP (&tmp->rx, s, (sensitive ? mutt_which_case (s) : REG_ICASE))) != 0) { - return 0; + regerror (r, &tmp->rx, err->data, err->dsize); + mutt_free_color_line(&tmp, 1); + return (-1); } - - if (object == MT_COLOR_QUOTED) + tmp->next = *top; + tmp->pattern = safe_strdup (s); +#ifdef HAVE_COLOR + if(fg != -1 && bg != -1) { - if (q_level >= ColorQuoteSize) - { - safe_realloc ((void **) &ColorQuote, (ColorQuoteSize += 2) * sizeof (int)); - ColorQuote[ColorQuoteSize-2] = ColorDefs[MT_COLOR_QUOTED]; - ColorQuote[ColorQuoteSize-1] = ColorDefs[MT_COLOR_QUOTED]; - } - if (q_level >= ColorQuoteUsed) - ColorQuoteUsed = q_level + 1; - if (q_level == 0) + tmp->fg = fg; + tmp->bg = bg; + attr |= mutt_alloc_color (fg, bg); + } +#endif + if (is_index) + { + strfcpy(buf, tmp->pattern, sizeof(buf)); + mutt_check_simple (buf, sizeof (buf), NONULL(SimpleSearch)); + if((tmp->color_pattern = mutt_pattern_comp (buf, M_FULL_MSG, err)) == NULL) { - ColorDefs[MT_COLOR_QUOTED] = bold | mutt_alloc_color (fg, bg); - - ColorQuote[0] = ColorDefs[MT_COLOR_QUOTED]; - for (q_level = 1; q_level < ColorQuoteUsed; q_level++) - { - if (ColorQuote[q_level] == A_NORMAL) - ColorQuote[q_level] = ColorDefs[MT_COLOR_QUOTED]; - } + mutt_free_color_line(&tmp, 1); + return -1; } - else - ColorQuote[q_level] = bold | mutt_alloc_color (fg, bg); } - else - ColorDefs[object] = bold | mutt_alloc_color (fg, bg); + tmp->pair = attr; + *top = tmp; } -#ifdef HAVE_BKGDSET - if (object == MT_COLOR_NORMAL) - BKGDSET (MT_COLOR_NORMAL); -#endif - - return (r); + return 0; } -#endif /* HAVE_COLOR */ - -/* - * command: mono - * - * set attribute for an object when using a terminal with no color support - */ -int mutt_parse_mono (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err) +static int +parse_object(BUFFER *buf, BUFFER *s, int *o, int *ql, BUFFER *err) { - int r = 0, object, q_level = 0, attr = A_NORMAL; + int q_level = 0; char *eptr; - - mutt_extract_token (buf, s, 0); - if (strncmp (buf->data, "quoted", 6) == 0) + + if(!MoreArgs(s)) { - if (buf->data[6]) + strfcpy(err->data, "Missing arguments.", err->dsize); + return -1; + } + + mutt_extract_token(buf, s, 0); + if(!strncmp(buf->data, "quoted", 6)) + { + if(buf->data[6]) { - q_level = strtol (buf->data + 6, &eptr, 10); - if (*eptr || q_level < 0) + *ql = strtol(buf->data + 6, &eptr, 10); + if(*eptr || q_level < 0) { - snprintf (err->data, err->dsize, "%s: no such object", buf->data); - return (-1); + snprintf(err->data, err->dsize, "%s: no such object", buf->data); + return -1; } } - object = MT_COLOR_QUOTED; + else + *ql = 0; + + *o = MT_COLOR_QUOTED; } - else if ((object = mutt_getvaluebyname (buf->data, Fields)) == -1) + else if ((*o = mutt_getvaluebyname (buf->data, Fields)) == -1) { snprintf (err->data, err->dsize, "%s: no such object", buf->data); return (-1); } + return 0; +} + +typedef int (*parser_callback_t)(BUFFER *, BUFFER *, int *, int *, int *, BUFFER *); + +#ifdef HAVE_COLOR + +static int +parse_color_pair(BUFFER *buf, BUFFER *s, int *fg, int *bg, int *attr, BUFFER *err) +{ + if (! MoreArgs (s)) + { + strfcpy (err->data, "color: too few arguments", err->dsize); + return (-1); + } + + mutt_extract_token (buf, s, 0); + + if (parse_color_name (buf->data, fg, attr, A_BOLD, err) != 0) + return (-1); + + if (! MoreArgs (s)) + { + strfcpy (err->data, "color: too few arguments", err->dsize); + return (-1); + } + + mutt_extract_token (buf, s, 0); + + if (parse_color_name (buf->data, bg, attr, A_BLINK, err) != 0) + return (-1); + + return 0; +} + +#endif + +static int +parse_attr_spec(BUFFER *buf, BUFFER *s, int *fg, int *bg, int *attr, BUFFER *err) +{ + + if(fg) *fg = -1; + if(bg) *bg = -1; + if (! MoreArgs (s)) { strfcpy (err->data, "mono: too few arguments", err->dsize); @@ -625,108 +606,156 @@ int mutt_parse_mono (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err) mutt_extract_token (buf, s, 0); if (strcasecmp ("bold", buf->data) == 0) - attr |= A_BOLD; + *attr |= A_BOLD; else if (strcasecmp ("underline", buf->data) == 0) - attr |= A_UNDERLINE; + *attr |= A_UNDERLINE; else if (strcasecmp ("none", buf->data) == 0) - attr = A_NORMAL; + *attr = A_NORMAL; else if (strcasecmp ("reverse", buf->data) == 0) - attr |= A_REVERSE; + *attr |= A_REVERSE; else if (strcasecmp ("standout", buf->data) == 0) - attr |= A_STANDOUT; + *attr |= A_STANDOUT; else if (strcasecmp ("normal", buf->data) == 0) - attr = A_NORMAL; /* needs use = instead of |= to clear other bits */ + *attr = A_NORMAL; /* needs use = instead of |= to clear other bits */ else { snprintf (err->data, err->dsize, "%s: no such attribute", buf->data); return (-1); } + + return 0; +} + +static int fgbgattr_to_color(int fg, int bg, int attr) +{ +#ifdef HAVE_COLOR + if(fg != -1 && bg != -1) + return attr | mutt_alloc_color(fg, bg); + else +#endif + return attr; +} +/* usage: color [ ] + * mono [ ] + */ + +static int +_mutt_parse_color (BUFFER *buf, BUFFER *s, BUFFER *err, + parser_callback_t callback, short dry_run) +{ + int object = 0, attr = 0, fg = 0, bg = 0, q_level = 0; + int r = 0; + + if(parse_object(buf, s, &object, &q_level, err) == -1) + return -1; + + if(callback(buf, s, &fg, &bg, &attr, err) == -1) + return -1; + + /* extract a regular expression if needed */ + if (object == MT_COLOR_HEADER || object == MT_COLOR_BODY || object == MT_COLOR_INDEX) { - if (! MoreArgs (s)) + if (!MoreArgs (s)) { - snprintf (err->data, err->dsize, "mono: missing regexp"); + strfcpy (err->data, "too few arguments", err->dsize); return (-1); } mutt_extract_token (buf, s, 0); - if (MoreArgs (s)) - { - strfcpy (err->data, "mono: too many arguments", err->dsize); - return (-1); - } + } + + if (MoreArgs (s)) + { + strfcpy (err->data, "too many arguments", err->dsize); + return (-1); + } + + /* dry run? */ + + if(dry_run) return 0; - /* if we have color, ignore the mono commands */ - if (option (OPTNOCURSES) + #ifdef HAVE_COLOR - || has_colors () +# ifdef HAVE_USE_DEFAULT_COLORS + if (has_colors() && use_default_colors () != OK + && (fg == COLOR_DEFAULT || bg == COLOR_DEFAULT)) + { + strfcpy (err->data, "default colors not supported", err->dsize); + return (-1); + } +# endif /* HAVE_USE_DEFAULT_COLORS */ #endif - ) + + if (object == MT_COLOR_HEADER) + r = add_pattern (&ColorHdrList, buf->data, 0, fg, bg, attr, err,0); + else if (object == MT_COLOR_BODY) + r = add_pattern (&ColorBodyList, buf->data, 1, fg, bg, attr, err, 0); + else if (object == MT_COLOR_INDEX) + { + r = add_pattern (&ColorIndexList, buf->data, 1, fg, bg, attr, err, 1); + mutt_cache_index_colors(Context); + set_option (OPTFORCEREDRAWINDEX); + } + else if (object == MT_COLOR_QUOTED) + { + if (q_level >= ColorQuoteSize) { - return 0; + safe_realloc ((void **) &ColorQuote, (ColorQuoteSize += 2) * sizeof (int)); + ColorQuote[ColorQuoteSize-2] = ColorDefs[MT_COLOR_QUOTED]; + ColorQuote[ColorQuoteSize-1] = ColorDefs[MT_COLOR_QUOTED]; } - - if (object == MT_COLOR_HEADER) - r = add_pattern (&ColorHdrList, buf->data, 0, -1, -1, attr, err, 0); - else if (object == MT_COLOR_BODY) - r = add_pattern (&ColorBodyList, buf->data, 1, -1, -1, attr, err, 0); - else if (object == MT_COLOR_INDEX) + if (q_level >= ColorQuoteUsed) + ColorQuoteUsed = q_level + 1; + if (q_level == 0) { - pattern_t *pat; - char tempbuf[LONG_STRING]; - - strfcpy (tempbuf, buf->data, sizeof (tempbuf)); - mutt_check_simple (tempbuf, sizeof (tempbuf), SimpleSearch); - if ((pat = mutt_pattern_comp (tempbuf, M_FULL_MSG, err)) == NULL) + ColorDefs[MT_COLOR_QUOTED] = fgbgattr_to_color(fg, bg, attr); + + ColorQuote[0] = ColorDefs[MT_COLOR_QUOTED]; + for (q_level = 1; q_level < ColorQuoteUsed; q_level++) { - mutt_pattern_free (&pat); - return (-1); + if (ColorQuote[q_level] == A_NORMAL) + ColorQuote[q_level] = ColorDefs[MT_COLOR_QUOTED]; } - r = add_pattern (&ColorIndexList, buf->data, 1, -1, -1, attr, err, 1); - mutt_cache_index_colors (Context); - set_option (OPTFORCEREDRAWINDEX); } + else + ColorQuote[q_level] = fgbgattr_to_color(fg, bg, attr); } else - { - /* if we have color, ignore the mono commands */ - if (option (OPTNOCURSES) + ColorDefs[object] = fgbgattr_to_color(fg, bg, attr); + #ifdef HAVE_COLOR - || has_colors () +# ifdef HAVE_BKGDSET + if (object == MT_COLOR_NORMAL && has_colors()) + BKGDSET (MT_COLOR_NORMAL); +# endif #endif - ) - { - return 0; - } - if (object == MT_COLOR_QUOTED) - { - if (q_level >= ColorQuoteSize) - { - safe_realloc ((void **) &ColorQuote, (ColorQuoteSize += 2) * sizeof (int)); - ColorQuote[ColorQuoteSize-2] = ColorDefs[MT_COLOR_QUOTED]; - ColorQuote[ColorQuoteSize-1] = ColorDefs[MT_COLOR_QUOTED]; - } - if (q_level >= ColorQuoteUsed) - ColorQuoteUsed = q_level + 1; - if (q_level == 0) - { - ColorDefs[MT_COLOR_QUOTED] = attr; + return (r); +} - ColorQuote[0] = ColorDefs[MT_COLOR_QUOTED]; - for (q_level = 1; q_level < ColorQuoteUsed; q_level++) - { - if (ColorQuote[q_level] == A_NORMAL) - ColorQuote[q_level] = ColorDefs[MT_COLOR_QUOTED]; - } - } - else - ColorQuote[q_level] = attr; - } - else - ColorDefs[object] = attr; - } +#ifdef HAVE_COLOR - return (r); +int mutt_parse_color(BUFFER *buff, BUFFER *s, unsigned long data, BUFFER *err) +{ + int dry_run = 0; + + if(option(OPTNOCURSES) || !has_colors()) + dry_run = 1; + + return _mutt_parse_color(buff, s, err, parse_color_pair, dry_run); +} + +#endif + +int mutt_parse_mono(BUFFER *buff, BUFFER *s, unsigned long data, BUFFER *err) +{ + int dry_run = 0; + + if(option(OPTNOCURSES) || has_colors()) + dry_run = 1; + + return _mutt_parse_color(buff, s, err, parse_attr_spec, dry_run); } + diff --git a/commands.c b/commands.c index 0144238f..2536a790 100644 --- a/commands.c +++ b/commands.c @@ -103,14 +103,14 @@ static int is_mmnoask (const char *buf) return (0); } -int mutt_display_message (HEADER *cur) +int mutt_display_message (HEADER *cur, const char *attach_msg_status) { char tempfile[_POSIX_PATH_MAX], buf[LONG_STRING]; int rc = 0, builtin = 0; int cmflags = M_CM_DECODE | M_CM_DISPLAY; FILE *fpout; - snprintf (buf, sizeof (buf), "%s/%s", TYPE (cur->content->type), + snprintf (buf, sizeof (buf), "%s/%s", TYPE (cur->content), cur->content->subtype); if (cur->mailcap && !mutt_is_autoview (buf)) @@ -176,11 +176,11 @@ int mutt_display_message (HEADER *cur) return (0); } - if (strcmp (Pager, "builtin") == 0) + if (!Pager || strcmp (Pager, "builtin") == 0) builtin = 1; else { - mutt_make_string (buf, sizeof (buf), PagerFmt, Context, cur); + mutt_make_string (buf, sizeof (buf), NONULL(PagerFmt), Context, cur); fputs (buf, fpout); fputs ("\n\n", fpout); } @@ -208,12 +208,12 @@ int mutt_display_message (HEADER *cur) memset (&info, 0, sizeof (pager_t)); info.hdr = cur; info.ctx = Context; - rc = mutt_pager (NULL, tempfile, 1, &info); + rc = mutt_pager (NULL, tempfile, 1, &info, attach_msg_status); } else { endwin (); - snprintf (buf, sizeof (buf), "%s %s", Pager, tempfile); + snprintf (buf, sizeof (buf), "%s %s", NONULL(Pager), tempfile); mutt_system (buf); unlink (tempfile); keypad (stdscr, TRUE); @@ -455,13 +455,16 @@ void mutt_shell_escape (void) buf[0] = 0; if (mutt_get_field ("Shell command: ", buf, sizeof (buf), M_CMD) == 0) { - if (!buf[0]) + if (!buf[0] && Shell) strfcpy (buf, Shell, sizeof (buf)); - CLEARLINE (LINES-1); - endwin (); - fflush (stdout); - if (mutt_system (buf) != 0 || option (OPTWAITKEY)) - mutt_any_key_to_continue (NULL); + if(buf[0]) + { + CLEARLINE (LINES-1); + endwin (); + fflush (stdout); + if (mutt_system (buf) != 0 || option (OPTWAITKEY)) + mutt_any_key_to_continue (NULL); + } } } @@ -506,58 +509,6 @@ void mutt_display_address (ADDRESS *adr) mutt_message ("%s", buf); } -/* returns 1 if OK to proceed, 0 to abort */ -static int save_confirm_func (const char *s, struct stat *st) -{ - char tmp[_POSIX_PATH_MAX]; - int ret = 1; - int magic = 0; - - magic = mx_get_magic (s); - - if (stat (s, st) != -1) - { - if (magic == -1) - { - mutt_error ("%s is not a mailbox!", s); - return 0; - } - - if (option (OPTCONFIRMAPPEND)) - { - snprintf (tmp, sizeof (tmp), "Append messages to %s?", s); - if (mutt_yesorno (tmp, 1) < 1) - ret = 0; - } - } - else - { - if (magic != M_IMAP) - { - st->st_mtime = 0; - st->st_atime = 0; - - if (errno == ENOENT) - { - if (option (OPTCONFIRMCREATE)) - { - snprintf (tmp, sizeof (tmp), "Create %s?", s); - if (mutt_yesorno (tmp, 1) < 1) - ret = 0; - } - } - else - { - mutt_perror (s); - return 0; - } - } - } - - CLEARLINE (LINES-1); - return (ret); -} - /* returns 0 if the copy/save was successful, or -1 on error/abort */ int mutt_save_message (HEADER *h, int delete, int decode, int *redraw) { @@ -627,7 +578,7 @@ int mutt_save_message (HEADER *h, int delete, int decode, int *redraw) mutt_expand_path (buf, sizeof (buf)); /* check to make sure that this file is really the one the user wants */ - if (!save_confirm_func (buf, &st)) + if (!mutt_save_confirm (buf, &st)) { CLEARLINE (LINES-1); return (-1); @@ -640,7 +591,16 @@ int mutt_save_message (HEADER *h, int delete, int decode, int *redraw) if (h) { if (decode) + { mutt_parse_mime_message (Context, h); +#ifdef _PGPPATH + if((h->pgp & PGPENCRYPT) && !pgp_valid_passphrase()) + { + mx_close_mailbox (&ctx); + return (-1); + } +#endif /* _PGPPATH */ + } if (mutt_append_message (&ctx, Context, h, cmflags, chflags) == 0 && delete) { mutt_set_flag (Context, h, M_DELETE, 1); @@ -655,7 +615,13 @@ int mutt_save_message (HEADER *h, int delete, int decode, int *redraw) { h = Context->hdrs[Context->v2r[i]]; if (decode) + { mutt_parse_mime_message (Context, h); +#ifdef _PGPPATH + if((h->pgp & PGPENCRYPT) && !pgp_valid_passphrase()) + continue; +#endif /* _PGPPATH */ + } mutt_append_message (&ctx, Context, h, cmflags, chflags); if (delete) { @@ -712,7 +678,7 @@ static void print_msg (FILE *fp, CONTEXT *ctx, HEADER *h) mutt_parse_mime_message (ctx, h); - mutt_copy_message (fp, ctx, h, M_CM_DECODE, CH_WEED | CH_DECODE); + mutt_copy_message (fp, ctx, h, M_CM_DECODE, CH_WEED | CH_DECODE | CH_REORDER); } void mutt_print_message (HEADER *h) @@ -725,7 +691,7 @@ void mutt_print_message (HEADER *h) h ? "Print message?" : "Print tagged messages?") != M_YES) return; endwin (); - if ((thepid = mutt_create_filter (PrintCmd, &fp, NULL, NULL)) == -1) + if ((thepid = mutt_create_filter (NONULL(PrintCmd), &fp, NULL, NULL)) == -1) return; if (h) { diff --git a/compose.c b/compose.c index 5c2dfac5..5f9c0e38 100644 --- a/compose.c +++ b/compose.c @@ -23,6 +23,8 @@ #include "mime.h" #include "attach.h" #include "mapping.h" +#include "mailbox.h" +#include "sort.h" #include #include @@ -71,40 +73,9 @@ static struct mapping_t ComposeHelp[] = { void snd_entry (char *b, size_t blen, MUTTMENU *menu, int num) { - char t[SHORT_STRING], size[SHORT_STRING]; - char tmp[_POSIX_PATH_MAX]; - BODY *m; - ATTACHPTR **idx = (ATTACHPTR **) menu->data; - struct stat finfo; - - m = idx[num]->content; - - if (m->filename && m->filename[0]) - { - if (stat (m->filename, &finfo) != -1) - mutt_pretty_size (size, sizeof (size), finfo.st_size); - else - strcpy (size, "0K"); - strfcpy (tmp, m->filename, sizeof (tmp)); - } - else - { - strcpy (size, "0K"); - strcpy (tmp, ""); - } - mutt_pretty_mailbox (tmp); - - snprintf (t, sizeof (t), "[%.7s/%.10s, %.6s, %s]", - TYPE (m->type), m->subtype, ENCODING (m->encoding), size); - - snprintf (b, blen, "%c%c%2d %-34.34s %s%s <%s>", - m->unlink ? '-' : ' ', - m->tagged ? '*' : ' ', - num + 1, - t, - idx[num]->tree ? idx[num]->tree : "", - tmp, - m->description ? m->description : "no description"); + mutt_FormatString (b, blen, NONULL (AttachFormat), mutt_attach_fmt, + (unsigned long)(((ATTACHPTR **) menu->data)[num]), + M_FORMAT_STAT_FILE); } @@ -172,7 +143,7 @@ static int pgp_send_menu (int bits) else { /* Copy the existing MIC algorithm into place */ - strfcpy(input_micalg, PgpSignMicalg, sizeof(input_micalg)); + strfcpy(input_micalg, NONULL(PgpSignMicalg), sizeof(input_micalg)); if(mutt_get_field("MIC algorithm: ", input_micalg, sizeof(input_micalg), 0) == 0) { @@ -210,7 +181,39 @@ static int pgp_send_menu (int bits) } #endif /* _PGPPATH */ +static int +check_attachments(ATTACHPTR **idx, short idxlen) +{ + int i, r; + struct stat st; + char pretty[_POSIX_PATH_MAX], msg[_POSIX_PATH_MAX + SHORT_STRING]; + + for (i = 0; i < idxlen; i++) + { + strfcpy(pretty, idx[i]->content->filename, sizeof(pretty)); + if(stat(idx[i]->content->filename, &st) != 0) + { + mutt_pretty_mailbox(pretty); + mutt_error("%s [#%d] no longer exists!", + pretty, i+1); + return -1; + } + + if(idx[i]->content->stamp < st.st_mtime) + { + mutt_pretty_mailbox(pretty); + snprintf(msg, sizeof(msg), "%s [#%d] modified. Update encoding?", + pretty, i+1); + + if((r = mutt_yesorno(msg, M_YES)) == M_YES) + mutt_update_encoding(idx[i]->content); + else if(r == -1) + return -1; + } + } + return 0; +} static void draw_envelope (HEADER *msg, char *fcc) { @@ -336,13 +339,13 @@ static int edit_address_list (int line, ENVELOPE *env) } rfc822_write_address (buf, sizeof (buf), *addr); - if (mutt_get_field (prompt, buf, sizeof (buf), M_ALIAS) != 0) - return 0; - - rfc822_free_address (addr); - *addr = mutt_parse_adrlist (*addr, buf); - *addr = mutt_expand_aliases (*addr); - + if (mutt_get_field (prompt, buf, sizeof (buf), M_ALIAS) == 0) + { + rfc822_free_address (addr); + *addr = mutt_parse_adrlist (*addr, buf); + *addr = mutt_expand_aliases (*addr); + } + if (option (OPTNEEDREDRAW)) { unset_option (OPTNEEDREDRAW); @@ -393,6 +396,18 @@ static int delete_attachment (MUTTMENU *menu, short *idxlen, int x) return (0); } +static void update_idx (MUTTMENU *menu, ATTACHPTR **idx, short idxlen) +{ + idx[idxlen]->level = (idxlen > 0) ? idx[idxlen-1]->level : 0; + if (idxlen) + idx[idxlen - 1]->content->next = idx[idxlen]->content; + menu->current = idxlen++; + mutt_update_tree (idx, idxlen); + menu->max = idxlen; + return; +} + + /* return values: * * 1 message should be postponed @@ -411,11 +426,16 @@ int mutt_send_menu (HEADER *msg, /* structure for new message */ ATTACHPTR **idx = NULL; short idxlen = 0; short idxmax = 0; - int i; + int i, close = 0; int r = -1; /* return value */ int op = 0; int loop = 1; int fccSet = 0; /* has the user edited the Fcc: field ? */ + CONTEXT *ctx = NULL, *this = NULL; + /* Sort, SortAux could be changed in mutt_index_menu() */ + int oldSort = Sort, oldSortAux = SortAux; + HEADER **hdrs = NULL; + struct stat st; idx = mutt_gen_attach_list (msg->content, idx, &idxlen, &idxmax, 0, 1); @@ -482,7 +502,7 @@ int mutt_send_menu (HEADER *msg, /* structure for new message */ MAYBE_REDRAW (menu->redraw); break; case OP_COMPOSE_EDIT_MESSAGE: - if (strcmp ("builtin", Editor) != 0 && !option (OPTEDITHDRS)) + if (Editor && (strcmp ("builtin", Editor) != 0) && !option (OPTEDITHDRS)) { mutt_edit_file (Editor, msg->content->filename); mutt_update_encoding (msg->content); @@ -494,7 +514,7 @@ int mutt_send_menu (HEADER *msg, /* structure for new message */ if (op == OP_COMPOSE_EDIT_HEADERS || (op == OP_COMPOSE_EDIT_MESSAGE && option (OPTEDITHDRS))) { - mutt_edit_headers (strcmp ("builtin", Editor) == 0 ? Visual : Editor, + mutt_edit_headers ((!Editor || strcmp ("builtin", Editor) == 0) ? NONULL(Visual) : NONULL(Editor), msg->content->filename, msg, fcc, fcclen); } else @@ -514,6 +534,7 @@ int mutt_send_menu (HEADER *msg, /* structure for new message */ safe_free ((void **) &idx[i]); idxlen = 0; idx = mutt_gen_attach_list (msg->content, idx, &idxlen, &idxmax, 0, 1); + menu->data = idx; menu->max = idxlen; } @@ -571,10 +592,33 @@ int mutt_send_menu (HEADER *msg, /* structure for new message */ case OP_COMPOSE_ATTACH_FILE: + case OP_COMPOSE_ATTACH_MESSAGE: + fname[0] = 0; - if (mutt_enter_fname ("Attach file", fname, sizeof (fname), - &menu->redraw, 0) == -1) - break; + { + char* prompt; + int flag; + + if (op == OP_COMPOSE_ATTACH_FILE) + { + prompt = "Attach file"; + flag = 0; + } + else + { + prompt = "Open mailbox to attach message from"; + if (Context) + { + strfcpy (fname, NONULL (Context->path), sizeof (fname)); + mutt_pretty_mailbox (fname); + } + flag = 1; + } + + if (mutt_enter_fname (prompt, fname, sizeof (fname), &menu->redraw, flag) == -1) + break; + } + if (!fname[0]) continue; mutt_expand_path (fname, sizeof (fname)); @@ -586,29 +630,100 @@ int mutt_send_menu (HEADER *msg, /* structure for new message */ break; } - if (idxlen == idxmax) + if (op == OP_COMPOSE_ATTACH_MESSAGE) { - safe_realloc ((void **) &idx, sizeof (ATTACHPTR *) * (idxmax += 5)); - menu->data = idx; - } + menu->redraw = REDRAW_FULL; - idx[idxlen] = (ATTACHPTR *) safe_calloc (1, sizeof (ATTACHPTR)); - if ((idx[idxlen]->content = mutt_make_attach (fname)) != NULL) - { - idx[idxlen]->level = (idxlen > 0) ? idx[idxlen-1]->level : 0; + ctx = mx_open_mailbox (fname, M_READONLY, NULL); + if (ctx == NULL) + { + mutt_perror (fname); + break; + } - if (idxlen) - idx[idxlen - 1]->content->next = idx[idxlen]->content; + if (!ctx->msgcount) + { + mx_close_mailbox (ctx); + safe_free ((void **) &ctx); + mutt_error ("No messages in that folder."); + break; + } + + { + int i, j; + this = Context; /* remember current folder */ + + Context = ctx; + close = mutt_index_menu (1); + /* allocate memory to store pointers to tagged headers */ + hdrs = safe_calloc (Context->tagged, sizeof (HEADER *)); + for (i=0, j=0; i < Context->vcount; i++) + { + HEADER *cur = Context->hdrs[Context->v2r[i]]; + /* store the headers of the tagged messages */ + if (cur->tagged) hdrs[j++] = cur; + } + } + } + { + int numtag = 0; - menu->current = idxlen++; - mutt_update_tree (idx, idxlen); - menu->max = idxlen; - menu->redraw |= REDRAW_INDEX | REDRAW_STATUS; + if (op == OP_COMPOSE_ATTACH_MESSAGE) + numtag = Context->tagged; + if (idxlen + numtag >= idxmax) + { + safe_realloc ((void **) &idx, sizeof (ATTACHPTR *) * (idxmax += 5 + numtag)); + menu->data = idx; } + } + + if (op == OP_COMPOSE_ATTACH_FILE) + { + idx[idxlen] = (ATTACHPTR *) safe_calloc (1, sizeof (ATTACHPTR)); + idx[idxlen]->content = mutt_make_file_attach (fname); + if (idx[idxlen]->content != NULL) + update_idx (menu, idx, idxlen); + else + { + mutt_error ("Unable to attach!"); + safe_free ((void **) &idx[idxlen]); + } + menu->redraw |= REDRAW_INDEX | REDRAW_STATUS; + idxlen++; + break; + } else { - mutt_error ("Unable to attach file!"); - safe_free ((void **) &idx[idxlen]); + int i = 0; + /* Did we tag any messages? */ + while (Context->tagged--) + { + idx[idxlen] = (ATTACHPTR *) safe_calloc (1, sizeof (ATTACHPTR)); + idx[idxlen]->content = mutt_make_message_attach (Context, hdrs[i], 1); + i++; + if (idx[idxlen]->content != NULL) + update_idx (menu, idx, idxlen); + else + { + mutt_error ("Unable to attach!"); + safe_free ((void **) &idx[idxlen]); + } + idxlen++; + } + menu->redraw |= REDRAW_FULL; + + if (close == OP_QUIT) + mx_close_mailbox (Context); + else + mx_fastclose_mailbox (Context); + safe_free ((void **) &Context); + FREE (&hdrs); + + /* go back to the folder we started from */ + Context = this; + /* Restore old $sort and $sort_aux */ + Sort = oldSort; + SortAux = oldSortAux; } break; @@ -643,10 +758,16 @@ int mutt_send_menu (HEADER *msg, /* structure for new message */ } break; + case OP_COMPOSE_UPDATE_ENCODING: + CHECK_COUNT; + mutt_update_encoding(idx[menu->current]->content); + menu->redraw = REDRAW_CURRENT; + break; + case OP_COMPOSE_EDIT_TYPE: CHECK_COUNT; snprintf (buf, sizeof (buf), "%s/%s", - TYPE (idx[menu->current]->content->type), + TYPE (idx[menu->current]->content), idx[menu->current]->content->subtype); if (mutt_get_field ("Content-Type: ", buf, sizeof (buf), 0) == 0 && buf[0]) { @@ -684,6 +805,13 @@ int mutt_send_menu (HEADER *msg, /* structure for new message */ break; case OP_COMPOSE_SEND_MESSAGE: + + if(check_attachments(idx, idxlen) != 0) + { + menu->redraw = REDRAW_FULL; + break; + } + if (!fccSet && *fcc) { if ((i = query_quadoption (OPT_COPY, "Save a copy of this message?")) @@ -699,7 +827,7 @@ int mutt_send_menu (HEADER *msg, /* structure for new message */ case OP_COMPOSE_EDIT_FILE: CHECK_COUNT; - mutt_edit_file (strcmp ("builtin", Editor) == 0 ? Visual : Editor, + mutt_edit_file ((!Editor || strcmp ("builtin", Editor) == 0) ? NONULL(Visual) : NONULL(Editor), idx[menu->current]->content->filename); mutt_update_encoding (idx[menu->current]->content); menu->redraw = REDRAW_CURRENT; @@ -718,13 +846,23 @@ int mutt_send_menu (HEADER *msg, /* structure for new message */ if (mutt_get_field ("Rename to: ", fname, sizeof (fname), M_FILE) == 0 && fname[0]) { - mutt_expand_path (fname, sizeof (fname)); - if (!mutt_rename_file (idx[menu->current]->content->filename, fname)) + if(stat(idx[menu->current]->content->filename, &st) == -1) { - safe_free ((void **) &idx[menu->current]->content->filename); - idx[menu->current]->content->filename = safe_strdup (fname); - menu->redraw = REDRAW_CURRENT; + mutt_error("Can't stat: %s", fname); + break; } + + mutt_expand_path (fname, sizeof (fname)); + if(mutt_rename_file (idx[menu->current]->content->filename, fname)) + break; + + safe_free ((void **) &idx[menu->current]->content->filename); + idx[menu->current]->content->filename = safe_strdup (fname); + menu->redraw = REDRAW_CURRENT; + + if(idx[menu->current]->content->stamp >= st.st_mtime) + mutt_stamp_attachment(idx[menu->current]->content); + } break; @@ -775,7 +913,7 @@ int mutt_send_menu (HEADER *msg, /* structure for new message */ } fclose (fp); - if ((idx[idxlen]->content = mutt_make_attach (fname)) == NULL) + if ((idx[idxlen]->content = mutt_make_file_attach (fname)) == NULL) { mutt_error ("What we have here is a failure to make an attachment"); continue; @@ -810,7 +948,7 @@ int mutt_send_menu (HEADER *msg, /* structure for new message */ case OP_COMPOSE_EDIT_MIME: CHECK_COUNT; - if (mutt_edit_attachment (idx[menu->current]->content, 0)) + if (mutt_edit_attachment (idx[menu->current]->content)) { mutt_update_encoding (idx[menu->current]->content); menu->redraw = REDRAW_FULL; @@ -827,7 +965,7 @@ int mutt_send_menu (HEADER *msg, /* structure for new message */ case OP_SAVE: CHECK_COUNT; - mutt_save_attachment_list (NULL, menu->tagprefix, menu->tagprefix ? msg->content : idx[menu->current]->content); + mutt_save_attachment_list (NULL, menu->tagprefix, menu->tagprefix ? msg->content : idx[menu->current]->content, NULL); break; case OP_PRINT: @@ -839,8 +977,8 @@ int mutt_send_menu (HEADER *msg, /* structure for new message */ case OP_FILTER: CHECK_COUNT; mutt_pipe_attachment_list (NULL, menu->tagprefix, menu->tagprefix ? msg->content : idx[menu->current]->content, op == OP_FILTER); - if (op == OP_FILTER) - menu->redraw = REDRAW_CURRENT; /* cte might have changed */ + if (op == OP_FILTER) /* cte might have changed */ + menu->redraw = menu->tagprefix ? REDRAW_FULL : REDRAW_CURRENT; break; @@ -873,14 +1011,22 @@ int mutt_send_menu (HEADER *msg, /* structure for new message */ /* fall through to postpone! */ case OP_COMPOSE_POSTPONE_MESSAGE: + + if(check_attachments(idx, idxlen) != 0) + { + menu->redraw = REDRAW_FULL; + break; + } + loop = 0; r = 1; break; case OP_COMPOSE_ISPELL: endwin (); - snprintf (buf, sizeof (buf), "%s -x %s", Ispell, msg->content->filename); + snprintf (buf, sizeof (buf), "%s -x %s", NONULL(Ispell), msg->content->filename); mutt_system (buf); + mutt_update_encoding(msg->content); break; diff --git a/config.guess b/config.guess new file mode 100755 index 00000000..30230b3d --- /dev/null +++ b/config.guess @@ -0,0 +1,890 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc. +# +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Written by Per Bothner . +# The master version of this file is at the FSF in /home/gd/gnu/lib. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit system type (host/target name). +# +# Only a few systems have been added to this list; please add others +# (but try to keep the structure clean). +# + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 8/24/94.) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +trap 'rm -f dummy.c dummy.o dummy; exit 1' 1 2 15 + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + alpha:OSF1:*:*) + if test $UNAME_RELEASE = "V4.0"; then + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + fi + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + cat <dummy.s + .globl main + .ent main +main: + .frame \$30,0,\$26,0 + .prologue 0 + .long 0x47e03d80 # implver $0 + lda \$2,259 + .long 0x47e20c21 # amask $2,$1 + srl \$1,8,\$2 + sll \$2,2,\$2 + sll \$0,3,\$0 + addl \$1,\$0,\$0 + addl \$2,\$0,\$0 + ret \$31,(\$26),1 + .end main +EOF + ${CC-cc} dummy.s -o dummy 2>/dev/null + if test "$?" = 0 ; then + ./dummy + case "$?" in + 7) + UNAME_MACHINE="alpha" + ;; + 15) + UNAME_MACHINE="alphaev5" + ;; + 14) + UNAME_MACHINE="alphaev56" + ;; + 10) + UNAME_MACHINE="alphapca56" + ;; + 16) + UNAME_MACHINE="alphaev6" + ;; + esac + fi + rm -f dummy.s dummy + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr [[A-Z]] [[a-z]]` + exit 0 ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit 0 ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-cbm-sysv4 + exit 0;; + amiga:NetBSD:*:*) + echo m68k-cbm-netbsd${UNAME_RELEASE} + exit 0 ;; + amiga:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + arc64:OpenBSD:*:*) + echo mips64el-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + arc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + hkmips:OpenBSD:*:*) + echo mips-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + pmax:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sgi:OpenBSD:*:*) + echo mips-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + wgrisc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit 0;; + arm32:NetBSD:*:*) + echo arm-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + exit 0 ;; + SR2?01:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit 0;; + Pyramid*:OSx*:*:*|MIS*:OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit 0 ;; + NILE:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit 0 ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + i86pc:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit 0 ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit 0 ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(head -1 /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit 0 ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit 0 ;; + atari*:NetBSD:*:*) + echo m68k-atari-netbsd${UNAME_RELEASE} + exit 0 ;; + atari*:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sun3*:NetBSD:*:*) + echo m68k-sun-netbsd${UNAME_RELEASE} + exit 0 ;; + sun3*:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mac68k:NetBSD:*:*) + echo m68k-apple-netbsd${UNAME_RELEASE} + exit 0 ;; + mac68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme88k:OpenBSD:*:*) + echo m88k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit 0 ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit 0 ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + 2020:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit 0 ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + sed 's/^ //' << EOF >dummy.c + int main (argc, argv) int argc; char **argv; { + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + ${CC-cc} dummy.c -o dummy \ + && ./dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ + && rm dummy.c dummy && exit 0 + rm -f dummy.c dummy + echo mips-mips-riscos${UNAME_RELEASE} + exit 0 ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit 0 ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit 0 ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit 0 ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit 0 ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 -o $UNAME_PROCESSOR = mc88110 ] ; then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx \ + -o ${TARGET_BINARY_INTERFACE}x = x ] ; then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else echo i586-dg-dgux${UNAME_RELEASE} + fi + exit 0 ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit 0 ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit 0 ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit 0 ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit 0 ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit 0 ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i?86:AIX:*:*) + echo i386-ibm-aix + exit 0 ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + sed 's/^ //' << EOF >dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0 + rm -f dummy.c dummy + echo rs6000-ibm-aix3.2.5 + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit 0 ;; + *:AIX:*:4) + if /usr/sbin/lsattr -EHl proc0 | grep POWER >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=4.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit 0 ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit 0 ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC NetBSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit 0 ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit 0 ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit 0 ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit 0 ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit 0 ;; + 9000/[3478]??:HP-UX:*:*) + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/7?? | 9000/8?[1679] ) HP_ARCH=hppa1.1 ;; + 9000/8?? ) HP_ARCH=hppa1.0 ;; + esac + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit 0 ;; + 3050*:HI-UX:*:*) + sed 's/^ //' << EOF >dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + ${CC-cc} dummy.c -o dummy && ./dummy && rm dummy.c dummy && exit 0 + rm -f dummy.c dummy + echo unknown-hitachi-hiuxwe2 + exit 0 ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit 0 ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit 0 ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit 0 ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit 0 ;; + i?86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit 0 ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit 0 ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit 0 ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit 0 ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit 0 ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit 0 ;; + CRAY*X-MP:*:*:*) + echo xmp-cray-unicos + exit 0 ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} + exit 0 ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ + exit 0 ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} + exit 0 ;; + CRAY-2:*:*:*) + echo cray2-cray-unicos + exit 0 ;; + F300:UNIX_System_V:*:*) + FUJITSU_SYS=`uname -p | tr [A-Z] [a-z] | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "f300-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit 0 ;; + F301:UNIX_System_V:*:*) + echo f301-fujitsu-uxpv`echo $UNAME_RELEASE | sed 's/ .*//'` + exit 0 ;; + hp3[0-9][05]:NetBSD:*:*) + echo m68k-hp-netbsd${UNAME_RELEASE} + exit 0 ;; + hp300:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + i?86:BSD/386:*:* | *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit 0 ;; + *:FreeBSD:*:*) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit 0 ;; + *:NetBSD:*:*) + echo ${UNAME_MACHINE}-unknown-netbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + exit 0 ;; + *:OpenBSD:*:*) + echo ${UNAME_MACHINE}-unknown-openbsd`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + exit 0 ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin32 + exit 0 ;; + i*:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit 0 ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin32 + exit 0 ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + *:GNU:*:*) + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit 0 ;; + *:Linux:*:*) + # uname on the ARM produces all sorts of strangeness, and we need to + # filter it out. + case "$UNAME_MACHINE" in + arm* | sa110*) UNAME_MACHINE="arm" ;; + esac + + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. + ld_help_string=`ld --help 2>&1` + ld_supported_emulations=`echo $ld_help_string \ + | sed -ne '/supported emulations:/!d + s/[ ][ ]*/ /g + s/.*supported emulations: *// + s/ .*// + p'` + case "$ld_supported_emulations" in + i?86linux) echo "${UNAME_MACHINE}-pc-linux-gnuaout" ; exit 0 ;; + i?86coff) echo "${UNAME_MACHINE}-pc-linux-gnucoff" ; exit 0 ;; + sparclinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;; + armlinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;; + m68klinux) echo "${UNAME_MACHINE}-unknown-linux-gnuaout" ; exit 0 ;; + elf32ppc) echo "powerpc-unknown-linux-gnu" ; exit 0 ;; + esac + + if test "${UNAME_MACHINE}" = "alpha" ; then + sed 's/^ //' <dummy.s + .globl main + .ent main + main: + .frame \$30,0,\$26,0 + .prologue 0 + .long 0x47e03d80 # implver $0 + lda \$2,259 + .long 0x47e20c21 # amask $2,$1 + srl \$1,8,\$2 + sll \$2,2,\$2 + sll \$0,3,\$0 + addl \$1,\$0,\$0 + addl \$2,\$0,\$0 + ret \$31,(\$26),1 + .end main +EOF + LIBC="" + ${CC-cc} dummy.s -o dummy 2>/dev/null + if test "$?" = 0 ; then + ./dummy + case "$?" in + 7) + UNAME_MACHINE="alpha" + ;; + 15) + UNAME_MACHINE="alphaev5" + ;; + 14) + UNAME_MACHINE="alphaev56" + ;; + 10) + UNAME_MACHINE="alphapca56" + ;; + 16) + UNAME_MACHINE="alphaev6" + ;; + esac + + objdump --private-headers dummy | \ + grep ld.so.1 > /dev/null + if test "$?" = 0 ; then + LIBC="libc1" + fi + fi + rm -f dummy.s dummy + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} ; exit 0 + elif test "${UNAME_MACHINE}" = "mips" ; then + cat >dummy.c </dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0 + rm -f dummy.c dummy + else + # Either a pre-BFD a.out linker (linux-gnuoldld) + # or one that does not give us useful --help. + # GCC wants to distinguish between linux-gnuoldld and linux-gnuaout. + # If ld does not provide *any* "supported emulations:" + # that means it is gnuoldld. + echo "$ld_help_string" | grep >/dev/null 2>&1 "supported emulations:" + test $? != 0 && echo "${UNAME_MACHINE}-pc-linux-gnuoldld" && exit 0 + + case "${UNAME_MACHINE}" in + i?86) + VENDOR=pc; + ;; + *) + VENDOR=unknown; + ;; + esac + # Determine whether the default compiler is a.out or elf + cat >dummy.c < +main(argc, argv) + int argc; + char *argv[]; +{ +#ifdef __ELF__ +# ifdef __GLIBC__ +# if __GLIBC__ >= 2 + printf ("%s-${VENDOR}-linux-gnu\n", argv[1]); +# else + printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]); +# endif +# else + printf ("%s-${VENDOR}-linux-gnulibc1\n", argv[1]); +# endif +#else + printf ("%s-${VENDOR}-linux-gnuaout\n", argv[1]); +#endif + return 0; +} +EOF + ${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy "${UNAME_MACHINE}" && rm dummy.c dummy && exit 0 + rm -f dummy.c dummy + fi ;; +# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. earlier versions +# are messed up and put the nodename in both sysname and nodename. + i?86:DYNIX/ptx:4*:*) + echo i386-sequent-sysv4 + exit 0 ;; + i?86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit 0 ;; + i?86:*:4.*:* | i?86:SYSTEM_V:4.*:*) + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_RELEASE} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_RELEASE} + fi + exit 0 ;; + i?86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|egrep Release|sed -e 's/.*= //')` + (/bin/uname -X|egrep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|egrep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit 0 ;; + pc:*:*:*) + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit 0 ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit 0 ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit 0 ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit 0 ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit 0 ;; + M68*:*:R3V[567]*:*) + test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; + 3[34]??:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 4850:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4.3${OS_REL} && exit 0 + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4 && exit 0 ;; + m68*:LynxOS:2.*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit 0 ;; + i?86:LynxOS:2.*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + rs6000:LynxOS:2.*:* | PowerPC:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit 0 ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit 0 ;; + PENTIUM:CPunix:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit 0 ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit 0 ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit 0 ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit 0 ;; + news*:NEWS-OS:*:6*) + echo mips-sony-newsos6 + exit 0 ;; + R3000:*System_V*:*:* | R4000:UNIX_SYSV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit 0 ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +cat >dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +#if !defined (ultrix) + printf ("vax-dec-bsd\n"); exit (0); +#else + printf ("vax-dec-ultrix\n"); exit (0); +#endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +${CC-cc} dummy.c -o dummy 2>/dev/null && ./dummy && rm dummy.c dummy && exit 0 +rm -f dummy.c dummy + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit 0 ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + c34*) + echo c34-convex-bsd + exit 0 ;; + c38*) + echo c38-convex-bsd + exit 0 ;; + c4*) + echo c4-convex-bsd + exit 0 ;; + esac +fi + +#echo '(Unable to guess system type)' 1>&2 + +exit 1 diff --git a/config.h.in b/config.h.in index cc48687e..c273e202 100644 --- a/config.h.in +++ b/config.h.in @@ -60,9 +60,6 @@ /* Where new mail is spooled */ #undef MAILPATH -/* Should I just use the domain name? (--enable-hidden-host) */ -#undef HIDDEN_HOST - /* Where to find sendmail on your system */ #undef SENDMAIL @@ -121,6 +118,9 @@ /* Does your system have the vsnprintf() call? */ #undef HAVE_VSNPRINTF +/* Does your system have the fchdir() call? */ +#undef HAVE_FCHDIR + /* The number of bytes in a long. */ #undef SIZEOF_LONG @@ -130,6 +130,9 @@ /* Define if you have the curs_set function. */ #undef HAVE_CURS_SET +/* Define if you have the fchdir function. */ +#undef HAVE_FCHDIR + /* Define if you have the ftruncate function. */ #undef HAVE_FTRUNCATE @@ -172,6 +175,9 @@ /* Define if you have the header file. */ #undef HAVE_SYS_IOCTL_H +/* Define if you have the header file. */ +#undef HAVE_SYSEXITS_H + /* Define if you have the intl library (-lintl). */ #undef HAVE_LIBINTL diff --git a/config.sub b/config.sub new file mode 100755 index 00000000..e24b8504 --- /dev/null +++ b/config.sub @@ -0,0 +1,952 @@ +#! /bin/sh +# Configuration validation subroutine script, version 1.1. +# Copyright (C) 1991, 92-97, 1998 Free Software Foundation, Inc. +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +if [ x$1 = x ] +then + echo Configuration name missing. 1>&2 + echo "Usage: $0 CPU-MFR-OPSYS" 1>&2 + echo "or $0 ALIAS" 1>&2 + echo where ALIAS is a recognized configuration type. 1>&2 + exit 1 +fi + +# First pass through any local machine types. +case $1 in + *local*) + echo $1 + exit 0 + ;; + *) + ;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + linux-gnu*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple) + os= + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco5) + os=sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + tahoe | i860 | m32r | m68k | m68000 | m88k | ns32k | arc | arm \ + | arme[lb] | pyramid | mn10200 | mn10300 \ + | tron | a29k | 580 | i960 | h8300 | hppa | hppa1.0 | hppa1.1 \ + | alpha | alphaev5 | alphaev56 | we32k | ns16k | clipper \ + | i370 | sh | powerpc | powerpcle | 1750a | dsp16xx | pdp11 \ + | mips64 | mipsel | mips64el | mips64orion | mips64orionel \ + | mipstx39 | mipstx39el \ + | sparc | sparclet | sparclite | sparc64 | v850) + basic_machine=$basic_machine-unknown + ;; + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i[34567]86) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + vax-* | tahoe-* | i[34567]86-* | i860-* | m32r-* | m68k-* | m68000-* \ + | m88k-* | sparc-* | ns32k-* | fx80-* | arc-* | arm-* | c[123]* \ + | mips-* | pyramid-* | tron-* | a29k-* | romp-* | rs6000-* \ + | power-* | none-* | 580-* | cray2-* | h8300-* | i960-* \ + | xmp-* | ymp-* | hppa-* | hppa1.0-* | hppa1.1-* \ + | alpha-* | alphaev5-* | alphaev56-* | we32k-* | cydra-* \ + | ns16k-* | pn-* | np1-* | xps100-* | clipper-* | orion-* \ + | sparclite-* | pdp11-* | sh-* | powerpc-* | powerpcle-* \ + | sparc64-* | mips64-* | mipsel-* \ + | mips64el-* | mips64orion-* | mips64orionel-* \ + | mipstx39-* | mipstx39el-* \ + | f301-*) + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-cbm + ;; + amigaos | amigados) + basic_machine=m68k-cbm + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-cbm + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | ymp) + basic_machine=ymp-cray + os=-unicos + ;; + cray2) + basic_machine=cray2-cray + os=-unicos + ;; + [ctj]90-cray) + basic_machine=c90-cray + os=-unicos + ;; + crds | unos) + basic_machine=m68k-crds + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k7[0-9][0-9] | hp7[0-9][0-9] | hp9k8[0-9]7 | hp8[0-9]7) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + os=-mvs + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i[34567]86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i[34567]86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i[34567]86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i[34567]86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + miniframe) + basic_machine=m68000-convergent + ;; + mipsel*-linux*) + basic_machine=mipsel-unknown + os=-linux-gnu + ;; + mips*-linux*) + basic_machine=mips-unknown + os=-linux-gnu + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + np1) + basic_machine=np1-gould + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pentium | p5 | k5 | nexen) + basic_machine=i586-pc + ;; + pentiumpro | p6 | k6 | 6x86) + basic_machine=i686-pc + ;; + pentiumii | pentium2) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | nexen-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | k6-* | 6x86-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=rs6000-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + xmp) + basic_machine=xmp-cray + os=-unicos + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + mips) + if [ x$os = x-linux-gnu ]; then + basic_machine=mips-unknown + else + basic_machine=mips-mips + fi + ;; + romp) + basic_machine=romp-ibm + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sparc) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ + | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -cygwin32* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -uxpv*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -ctix* | -uts*) + os=-sysv + ;; + -ns2 ) + os=-nextstep2 + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -xenix) + os=-xenix + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + *-acorn) + os=-riscix1.2 + ;; + arm*-semi) + os=-aout + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-ibm) + os=-aix + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f301-fujitsu) + os=-uxpv + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -aix*) + vendor=ibm + ;; + -hpux*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -vxsim* | -vxworks*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os diff --git a/configure b/configure index 240f6658..60b1e9fb 100755 --- a/configure +++ b/configure @@ -21,14 +21,14 @@ ac_help="$ac_help --with-homespool[=FILE] file in user's directory where new mail is spooled" ac_help="$ac_help --with-mailpath=DIR directory where spool mailboxes are located" +ac_help="$ac_help + --with-libdir=PATH specify where to put arch dependent files" ac_help="$ac_help --with-sharedir=PATH specify where to put arch independent files" ac_help="$ac_help --with-docdir=PATH specify where to put the documentation" ac_help="$ac_help --with-domain=DOMAIN Specify your DNS domain name " -ac_help="$ac_help - --enable-hidden-host Only use the domain name for local addresses" ac_help="$ac_help --enable-pop Enable POP3 support" ac_help="$ac_help @@ -557,11 +557,58 @@ fi -VERSION=0.92.11 +VERSION=0.94.4 SUBVERSION='' +ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; } +fi +ac_config_guess=$ac_aux_dir/config.guess +ac_config_sub=$ac_aux_dir/config.sub +ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. + + +# Make sure we can run config.sub. +if $ac_config_sub sun4 >/dev/null 2>&1; then : +else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } +fi + +echo $ac_n "checking host system type""... $ac_c" 1>&6 +echo "configure:590: checking host system type" >&5 + +host_alias=$host +case "$host_alias" in +NONE) + case $nonopt in + NONE) + if host_alias=`$ac_config_guess`; then : + else { echo "configure: error: can not guess host type; you must specify one" 1>&2; exit 1; } + fi ;; + *) host_alias=$nonopt ;; + esac ;; +esac + +host=`$ac_config_sub $host_alias` +host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +echo "$ac_t""$host" 1>&6 + + echo $ac_n "checking for prefix""... $ac_c" 1>&6 -echo "configure:565: checking for prefix" >&5 +echo "configure:612: checking for prefix" >&5 if test x$prefix = xNONE; then mutt_cv_prefix=$ac_default_prefix else @@ -572,7 +619,7 @@ echo "$ac_t""$mutt_cv_prefix" 1>&6 # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:576: checking for $ac_word" >&5 +echo "configure:623: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -601,7 +648,7 @@ if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:605: checking for $ac_word" >&5 +echo "configure:652: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -649,7 +696,7 @@ fi fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:653: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 +echo "configure:700: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. @@ -659,11 +706,11 @@ ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS cross_compiling=$ac_cv_prog_cc_cross cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:714: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then ac_cv_prog_cc_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then @@ -683,12 +730,12 @@ if test $ac_cv_prog_cc_works = no; then { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:687: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "configure:734: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 -echo "configure:692: checking whether we are using GNU C" >&5 +echo "configure:739: checking whether we are using GNU C" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -697,7 +744,7 @@ else yes; #endif EOF -if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:701: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:748: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no @@ -712,7 +759,7 @@ if test $ac_cv_prog_gcc = yes; then ac_save_CFLAGS="$CFLAGS" CFLAGS= echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 -echo "configure:716: checking whether ${CC-cc} accepts -g" >&5 +echo "configure:763: checking whether ${CC-cc} accepts -g" >&5 if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -740,7 +787,7 @@ else fi echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 -echo "configure:744: checking whether ${MAKE-make} sets \${MAKE}" >&5 +echo "configure:791: checking whether ${MAKE-make} sets \${MAKE}" >&5 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -766,25 +813,6 @@ else SET_MAKE="MAKE=${MAKE-make}" fi -ac_aux_dir= -for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do - if test -f $ac_dir/install-sh; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install-sh -c" - break - elif test -f $ac_dir/install.sh; then - ac_aux_dir=$ac_dir - ac_install_sh="$ac_aux_dir/install.sh -c" - break - fi -done -if test -z "$ac_aux_dir"; then - { echo "configure: error: can not find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." 1>&2; exit 1; } -fi -ac_config_guess=$ac_aux_dir/config.guess -ac_config_sub=$ac_aux_dir/config.sub -ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. - # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: @@ -796,7 +824,7 @@ ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 -echo "configure:800: checking for a BSD compatible install" >&5 +echo "configure:828: checking for a BSD compatible install" >&5 if test -z "$INSTALL"; then if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -846,10 +874,18 @@ test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' +case "$host" in +*-*-hpux*) + if test -z "$GCC" ; then + CFLAGS="$CFLAGS -Ae -D_HPUX_SOURCE" + fi + ;; +esac + # Extract the first word of "sendmail", so it can be a program name with args. set dummy sendmail; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:853: checking for $ac_word" >&5 +echo "configure:889: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_SENDMAIL'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -891,7 +927,7 @@ if test -f $srcdir/pgp.c; then # Extract the first word of "gpg", so it can be a program name with args. set dummy gpg; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:895: checking for $ac_word" >&5 +echo "configure:931: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_GPG'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -935,7 +971,7 @@ EOF # Extract the first word of "pgpk", so it can be a program name with args. set dummy pgpk; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:939: checking for $ac_word" >&5 +echo "configure:975: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_PGPK'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -980,7 +1016,7 @@ EOF # Extract the first word of "pgp", so it can be a program name with args. set dummy pgp; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:984: checking for $ac_word" >&5 +echo "configure:1020: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_PGP'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1044,7 +1080,7 @@ EOF # Extract the first word of "ispell", so it can be a program name with args. set dummy ispell; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:1048: checking for $ac_word" >&5 +echo "configure:1084: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_ISPELL'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1081,7 +1117,7 @@ EOF fi echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 -echo "configure:1085: checking how to run the C preprocessor" >&5 +echo "configure:1121: checking how to run the C preprocessor" >&5 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= @@ -1096,13 +1132,13 @@ else # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1106: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1142: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then : @@ -1113,13 +1149,13 @@ else rm -rf conftest* CPP="${CC-cc} -E -traditional-cpp" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1123: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1159: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then : @@ -1145,7 +1181,7 @@ echo "$ac_t""$CPP" 1>&6 if test "${with_slang+set}" = set; then withval="$with_slang" echo $ac_n "checking if -ltermlib is required""... $ac_c" 1>&6 -echo "configure:1149: checking if -ltermlib is required" >&5 +echo "configure:1185: checking if -ltermlib is required" >&5 if eval "test \"`echo '$''{'mutt_cv_bsdish'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1153,7 +1189,7 @@ else { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext < @@ -1166,7 +1202,7 @@ main () #endif } EOF -if { (eval echo configure:1170: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +if { (eval echo configure:1206: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then mutt_cv_bsdish=yes else @@ -1183,7 +1219,7 @@ fi echo "$ac_t""$mutt_cv_bsdish" 1>&6 echo $ac_n "checking for S-Lang""... $ac_c" 1>&6 -echo "configure:1187: checking for S-Lang" >&5 +echo "configure:1223: checking for S-Lang" >&5 if test $withval = yes; then if test -d $srcdir/../slang; then mutt_cv_slang=$srcdir/../slang/src @@ -1229,16 +1265,16 @@ EOF echo $ac_n "checking if I can compile a test SLang program""... $ac_c" 1>&6 -echo "configure:1233: checking if I can compile a test SLang program" >&5 +echo "configure:1269: checking if I can compile a test SLang program" >&5 cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:1278: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* echo "$ac_t""yes" 1>&6 else @@ -1266,7 +1302,7 @@ fi echo $ac_n "checking for initscr in -lncurses""... $ac_c" 1>&6 -echo "configure:1270: checking for initscr in -lncurses" >&5 +echo "configure:1306: checking for initscr in -lncurses" >&5 ac_lib_var=`echo ncurses'_'initscr | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1274,7 +1310,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lncurses $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:1325: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -1308,17 +1344,17 @@ if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:1312: checking for $ac_hdr" >&5 +echo "configure:1348: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1322: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1358: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -1359,12 +1395,12 @@ fi echo $ac_n "checking for start_color""... $ac_c" 1>&6 -echo "configure:1363: checking for start_color" >&5 +echo "configure:1399: checking for start_color" >&5 if eval "test \"`echo '$''{'ac_cv_func_start_color'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:1427: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_start_color=yes" else @@ -1412,12 +1448,12 @@ fi for ac_func in typeahead bkgdset curs_set meta use_default_colors do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:1416: checking for $ac_func" >&5 +echo "configure:1452: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:1480: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -1467,12 +1503,12 @@ done for ac_func in resizeterm do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:1471: checking for $ac_func" >&5 +echo "configure:1507: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:1535: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -1524,12 +1560,12 @@ fi echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 -echo "configure:1528: checking for ANSI C header files" >&5 +echo "configure:1564: checking for ANSI C header files" >&5 if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -1537,7 +1573,7 @@ else #include EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1541: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1577: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -1554,7 +1590,7 @@ rm -f conftest* if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat > conftest.$ac_ext < EOF @@ -1572,7 +1608,7 @@ fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat > conftest.$ac_ext < EOF @@ -1593,7 +1629,7 @@ if test "$cross_compiling" = yes; then : else cat > conftest.$ac_ext < #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') @@ -1604,7 +1640,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } EOF -if { (eval echo configure:1608: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +if { (eval echo configure:1644: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then : else @@ -1628,21 +1664,21 @@ EOF fi -for ac_hdr in stdarg.h sys/ioctl.h +for ac_hdr in stdarg.h sys/ioctl.h sysexits.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:1636: checking for $ac_hdr" >&5 +echo "configure:1672: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1646: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1682: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* @@ -1670,12 +1706,12 @@ done echo $ac_n "checking return type of signal handlers""... $ac_c" 1>&6 -echo "configure:1674: checking return type of signal handlers" >&5 +echo "configure:1710: checking return type of signal handlers" >&5 if eval "test \"`echo '$''{'ac_cv_type_signal'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -1692,7 +1728,7 @@ int main() { int i; ; return 0; } EOF -if { (eval echo configure:1696: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1732: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_type_signal=void else @@ -1712,12 +1748,12 @@ EOF echo $ac_n "checking for sys_siglist declaration in signal.h or unistd.h""... $ac_c" 1>&6 -echo "configure:1716: checking for sys_siglist declaration in signal.h or unistd.h" >&5 +echo "configure:1752: checking for sys_siglist declaration in signal.h or unistd.h" >&5 if eval "test \"`echo '$''{'ac_cv_decl_sys_siglist'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -1729,7 +1765,7 @@ int main() { char *msg = *(sys_siglist + 1); ; return 0; } EOF -if { (eval echo configure:1733: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1769: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_decl_sys_siglist=yes else @@ -1751,7 +1787,7 @@ fi echo $ac_n "checking size of long""... $ac_c" 1>&6 -echo "configure:1755: checking size of long" >&5 +echo "configure:1791: checking size of long" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_long'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1759,7 +1795,7 @@ else { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext < main() @@ -1770,7 +1806,7 @@ main() exit(0); } EOF -if { (eval echo configure:1774: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +if { (eval echo configure:1810: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_long=`cat conftestval` else @@ -1791,12 +1827,12 @@ EOF echo $ac_n "checking for pid_t""... $ac_c" 1>&6 -echo "configure:1795: checking for pid_t" >&5 +echo "configure:1831: checking for pid_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_pid_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -1827,12 +1863,12 @@ fi for ac_func in setegid srand48 strerror do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:1831: checking for $ac_func" >&5 +echo "configure:1867: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:1895: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -1883,12 +1919,12 @@ done for ac_func in strcasecmp do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:1887: checking for $ac_func" >&5 +echo "configure:1923: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:1951: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -1939,13 +1975,14 @@ done mutt_cv_snprintf=no +SNPRINTFOBJS="" echo $ac_n "checking for snprintf""... $ac_c" 1>&6 -echo "configure:1944: checking for snprintf" >&5 +echo "configure:1981: checking for snprintf" >&5 if eval "test \"`echo '$''{'ac_cv_func_snprintf'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:2009: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_snprintf=yes" else @@ -1992,12 +2029,12 @@ mutt_cv_snprintf=yes fi echo $ac_n "checking for vsnprintf""... $ac_c" 1>&6 -echo "configure:1996: checking for vsnprintf" >&5 +echo "configure:2033: checking for vsnprintf" >&5 if eval "test \"`echo '$''{'ac_cv_func_vsnprintf'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:2061: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_vsnprintf=yes" else @@ -2045,17 +2082,19 @@ fi if test $mutt_cv_snprintf = yes; then LIBOBJS="$LIBOBJS snprintf.o" + SNPRINTFOBJS="snprintf.o" fi + for ac_func in ftruncate do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:2054: checking for $ac_func" >&5 +echo "configure:2093: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:2121: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -2100,7 +2139,7 @@ EOF else echo "$ac_t""no" 1>&6 echo $ac_n "checking for chsize in -lx""... $ac_c" 1>&6 -echo "configure:2104: checking for chsize in -lx" >&5 +echo "configure:2143: checking for chsize in -lx" >&5 ac_lib_var=`echo x'_'chsize | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -2108,7 +2147,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lx $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:2162: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -2153,12 +2192,12 @@ done for ac_func in strftime do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:2157: checking for $ac_func" >&5 +echo "configure:2196: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:2224: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -2203,7 +2242,7 @@ EOF else echo "$ac_t""no" 1>&6 echo $ac_n "checking for strftime in -lintl""... $ac_c" 1>&6 -echo "configure:2207: checking for strftime in -lintl" >&5 +echo "configure:2246: checking for strftime in -lintl" >&5 ac_lib_var=`echo intl'_'strftime | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -2211,7 +2250,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lintl $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:2265: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -2253,6 +2292,67 @@ fi done +for ac_func in fchdir +do +echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 +echo "configure:2299: checking for $ac_func" >&5 +if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char $ac_func(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_$ac_func) || defined (__stub___$ac_func) +choke me +#else +$ac_func(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2327: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + rm -rf conftest* + eval "ac_cv_func_$ac_func=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_$ac_func=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'$ac_func`\" = yes"; then + echo "$ac_t""yes" 1>&6 + ac_tr_func=HAVE_`echo $ac_func | tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'` + cat >> confdefs.h <> confdefs.h <<\EOF +#define HAVE_FCHDIR 1 +EOF + +else + echo "$ac_t""no" 1>&6 +mutt_cv_fchdir=no +fi +done + + + mutt_cv_regex=yes # Check whether --with-rx or --without-rx was given. if test "${with_rx+set}" = set; then @@ -2275,12 +2375,12 @@ else for ac_func in regcomp do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:2279: checking for $ac_func" >&5 +echo "configure:2379: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:2407: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -2374,7 +2474,7 @@ if test "${with_mailpath+set}" = set; then mutt_cv_mailpath=$withval else echo $ac_n "checking where new mail is stored""... $ac_c" 1>&6 -echo "configure:2378: checking where new mail is stored" >&5 +echo "configure:2478: checking where new mail is stored" >&5 if eval "test \"`echo '$''{'mutt_cv_mailpath'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2403,7 +2503,7 @@ EOF echo $ac_n "checking if $mutt_cv_mailpath is world writable""... $ac_c" 1>&6 -echo "configure:2407: checking if $mutt_cv_mailpath is world writable" >&5 +echo "configure:2507: checking if $mutt_cv_mailpath is world writable" >&5 if eval "test \"`echo '$''{'mutt_cv_worldwrite'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2411,7 +2511,7 @@ else { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext < #include @@ -2425,7 +2525,7 @@ int main (int argc, char **argv) exit (1); } EOF -if { (eval echo configure:2429: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +if { (eval echo configure:2529: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then mutt_cv_worldwrite=yes else @@ -2450,7 +2550,7 @@ EOF else echo $ac_n "checking if $mutt_cv_mailpath is group writable""... $ac_c" 1>&6 -echo "configure:2454: checking if $mutt_cv_mailpath is group writable" >&5 +echo "configure:2554: checking if $mutt_cv_mailpath is group writable" >&5 if eval "test \"`echo '$''{'mutt_cv_groupwrite'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2458,7 +2558,7 @@ else { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext < #include @@ -2472,7 +2572,7 @@ int main (int argc, char **argv) exit (1); } EOF -if { (eval echo configure:2476: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +if { (eval echo configure:2576: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null then mutt_cv_groupwrite=yes else @@ -2502,29 +2602,63 @@ EOF fi fi +if test "x$mutt_cv_setgid" = "xyes" || test "x$mutt_cv_fchdir" = "xno" +then + CPPFLAGS="$CPPFLAGS -DDL_STANDALONE" + DOTLOCK_TARGET="dotlock" + DOTLOCK_INSTALL_TARGET="install.dotlock" +else + LIBOBJS="$LIBOBJS dotlock.o" +fi + + + + + + +# Check whether --with-libdir or --without-libdir was given. +if test "${with_libdir+set}" = set; then + withval="$with_libdir" + mutt_cv_libdir=$withval +else + echo $ac_n "checking where to put architecture-dependent files""... $ac_c" 1>&6 +echo "configure:2626: checking where to put architecture-dependent files" >&5 +if eval "test \"`echo '$''{'mutt_cv_libdir'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -d ${mutt_cv_prefix}/lib/misc; then + mutt_cv_libdir="${mutt_cv_prefix}/lib/misc" + else + mutt_cv_libdir="${mutt_cv_prefix}/lib" + fi +fi + +echo "$ac_t""$mutt_cv_libdir" 1>&6 + +fi + + +libdir=$mutt_cv_libdir + + # Check whether --with-sharedir or --without-sharedir was given. if test "${with_sharedir+set}" = set; then withval="$with_sharedir" mutt_cv_sharedir=$withval else echo $ac_n "checking where to put architecture-independent data files""... $ac_c" 1>&6 -echo "configure:2512: checking where to put architecture-independent data files" >&5 +echo "configure:2651: checking where to put architecture-independent data files" >&5 if eval "test \"`echo '$''{'mutt_cv_sharedir'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else - if test x$prefix = xNONE; then - mutt_cv_prefix=$ac_default_prefix - else - mutt_cv_prefix=$prefix - fi - if test -d ${mutt_cv_prefix}/share; then + if test -d ${mutt_cv_prefix}/share; then if test -d ${mutt_cv_prefix}/share/misc; then - mutt_cv_sharedir='${prefix}/share/misc' + mutt_cv_sharedir="${mutt_cv_prefix}/share/misc" else - mutt_cv_sharedir='${prefix}/share' + mutt_cv_sharedir="${mutt_cv_prefix}/share" fi else - mutt_cv_sharedir='${libdir}' + mutt_cv_sharedir="$libdir" fi fi @@ -2536,13 +2670,14 @@ fi sharedir=$mutt_cv_sharedir + # Check whether --with-docdir or --without-docdir was given. if test "${with_docdir+set}" = set; then withval="$with_docdir" mutt_cv_docdir=$withval else echo $ac_n "checking where to put the documentation""... $ac_c" 1>&6 -echo "configure:2546: checking where to put the documentation" >&5 +echo "configure:2681: checking where to put the documentation" >&5 if eval "test \"`echo '$''{'mutt_cv_docdir'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2564,11 +2699,11 @@ docdir=$mutt_cv_docdir if test x$mutt_cv_setgid = xyes; then - MUTT_GROUP='-g mail' - MUTT_PERMISSION=2755 + DOTLOCK_GROUP='-g mail' + DOTLOCK_PERMISSION=2755 else - MUTT_GROUP='' - MUTT_PERMISSION=755 + DOTLOCK_GROUP='' + DOTLOCK_PERMISSION=755 fi @@ -2585,16 +2720,6 @@ EOF fi -# Check whether --enable-hidden-host or --disable-hidden-host was given. -if test "${enable_hidden_host+set}" = set; then - enableval="$enable_hidden_host" - cat >> confdefs.h <<\EOF -#define HIDDEN_HOST 1 -EOF - -fi - - # Check whether --enable-pop or --disable-pop was given. if test "${enable_pop+set}" = set; then enableval="$enable_pop" @@ -2603,7 +2728,7 @@ if test "${enable_pop+set}" = set; then EOF echo $ac_n "checking for socket in -lsocket""... $ac_c" 1>&6 -echo "configure:2607: checking for socket in -lsocket" >&5 +echo "configure:2732: checking for socket in -lsocket" >&5 ac_lib_var=`echo socket'_'socket | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -2611,7 +2736,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lsocket $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:2751: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -2650,7 +2775,7 @@ else fi echo $ac_n "checking for gethostbyname in -lnsl""... $ac_c" 1>&6 -echo "configure:2654: checking for gethostbyname in -lnsl" >&5 +echo "configure:2779: checking for gethostbyname in -lnsl" >&5 ac_lib_var=`echo nsl'_'gethostbyname | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -2658,7 +2783,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lnsl $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:2798: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -2709,7 +2834,7 @@ if test "${enable_imap+set}" = set; then EOF echo $ac_n "checking for socket in -lsocket""... $ac_c" 1>&6 -echo "configure:2713: checking for socket in -lsocket" >&5 +echo "configure:2838: checking for socket in -lsocket" >&5 ac_lib_var=`echo socket'_'socket | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -2717,7 +2842,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lsocket $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:2857: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -2756,7 +2881,7 @@ else fi echo $ac_n "checking for gethostbyname in -lnsl""... $ac_c" 1>&6 -echo "configure:2760: checking for gethostbyname in -lnsl" >&5 +echo "configure:2885: checking for gethostbyname in -lnsl" >&5 ac_lib_var=`echo nsl'_'gethostbyname | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -2764,7 +2889,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lnsl $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest; then +if { (eval echo configure:2904: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -2802,7 +2927,7 @@ else echo "$ac_t""no" 1>&6 fi - LIBOBJS="$LIBOBJS imap.o" + LIBOBJS="$LIBOBJS imap.o socket.o" fi @@ -3009,7 +3134,7 @@ done ac_given_srcdir=$srcdir ac_given_INSTALL="$INSTALL" -trap 'rm -fr `echo "Makefile rx/Makefile Muttrc doc/Makefile config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +trap 'rm -fr `echo "Makefile rx/Makefile Muttrc doc/Makefile doc/dotlock.man doc/mutt.man config.h" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 EOF cat >> $CONFIG_STATUS <> $CONFIG_STATUS <> $CONFIG_STATUS <<\EOF for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then diff --git a/configure.in b/configure.in index 36f06507..e4a19da5 100644 --- a/configure.in +++ b/configure.in @@ -1,9 +1,11 @@ dnl Process this file with autoconf to produce a configure script. AC_INIT(mutt.h) AC_CONFIG_HEADER(config.h) -VERSION=0.92.11 +VERSION=0.94.4 SUBVERSION='' +AC_CANONICAL_HOST + AC_MSG_CHECKING(for prefix) if test x$prefix = xNONE; then mutt_cv_prefix=$ac_default_prefix @@ -16,6 +18,14 @@ AC_PROG_CC AC_PROG_MAKE_SET AC_PROG_INSTALL +case "$host" in +*-*-hpux*) + if test -z "$GCC" ; then + CFLAGS="$CFLAGS -Ae -D_HPUX_SOURCE" + fi + ;; +esac + AC_PATH_PROG(SENDMAIL, sendmail, no, `echo $PATH | sed "s/:/ /"` /usr/sbin /usr/lib) AC_DEFINE_UNQUOTED(SENDMAIL, "$ac_cv_path_SENDMAIL") @@ -164,7 +174,7 @@ main () AC_HEADER_STDC -AC_CHECK_HEADERS(stdarg.h sys/ioctl.h) +AC_CHECK_HEADERS(stdarg.h sys/ioctl.h sysexits.h) AC_TYPE_SIGNAL @@ -180,11 +190,14 @@ AC_CHECK_FUNCS(setegid srand48 strerror) AC_REPLACE_FUNCS(strcasecmp) mutt_cv_snprintf=no +SNPRINTFOBJS="" AC_CHECK_FUNC(snprintf, [AC_DEFINE(HAVE_SNPRINTF)], [mutt_cv_snprintf=yes]) AC_CHECK_FUNC(vsnprintf, [AC_DEFINE(HAVE_VSNPRINTF)], [mutt_cv_snprintf=yes]) if test $mutt_cv_snprintf = yes; then LIBOBJS="$LIBOBJS snprintf.o" + SNPRINTFOBJS="snprintf.o" fi +AC_SUBST(SNPRINTFOBJS) dnl SCO uses chsize() instead of ftruncate() AC_CHECK_FUNCS(ftruncate, break, [AC_CHECK_LIB(x, chsize)]) @@ -192,6 +205,10 @@ AC_CHECK_FUNCS(ftruncate, break, [AC_CHECK_LIB(x, chsize)]) dnl SCO has strftime() in libintl AC_CHECK_FUNCS(strftime, break, [AC_CHECK_LIB(intl, strftime)]) +dnl AIX may not have fchdir() +AC_CHECK_FUNCS(fchdir, [AC_DEFINE(HAVE_FCHDIR)], [mutt_cv_fchdir=no]) + + mutt_cv_regex=yes AC_ARG_WITH(rx, [ --with-rx[=DIR] Use GNU rx ], [if test $withval != yes; then @@ -284,29 +301,53 @@ int main (int argc, char **argv) fi fi +if test "x$mutt_cv_setgid" = "xyes" || test "x$mutt_cv_fchdir" = "xno" +then + CPPFLAGS="$CPPFLAGS -DDL_STANDALONE" + DOTLOCK_TARGET="dotlock" + DOTLOCK_INSTALL_TARGET="install.dotlock" +else + LIBOBJS="$LIBOBJS dotlock.o" +fi + +AC_SUBST(DOTLOCK_TARGET) +AC_SUBST(DOTLOCK_INSTALL_TARGET) + + + +AC_ARG_WITH(libdir, [ --with-libdir=PATH specify where to put arch dependent files], + [mutt_cv_libdir=$withval], + [ AC_CACHE_CHECK(where to put architecture-dependent files, + mutt_cv_libdir, + [if test -d ${mutt_cv_prefix}/lib/misc; then + mutt_cv_libdir="${mutt_cv_prefix}/lib/misc" + else + mutt_cv_libdir="${mutt_cv_prefix}/lib" + fi]) + ]) + +libdir=$mutt_cv_libdir +AC_SUBST(libdir) + AC_ARG_WITH(sharedir, [ --with-sharedir=PATH specify where to put arch independent files], [mutt_cv_sharedir=$withval], [ AC_CACHE_CHECK(where to put architecture-independent data files, mutt_cv_sharedir, - [if test x$prefix = xNONE; then - mutt_cv_prefix=$ac_default_prefix - else - mutt_cv_prefix=$prefix - fi - if test -d ${mutt_cv_prefix}/share; then + [if test -d ${mutt_cv_prefix}/share; then if test -d ${mutt_cv_prefix}/share/misc; then - mutt_cv_sharedir='${prefix}/share/misc' + mutt_cv_sharedir="${mutt_cv_prefix}/share/misc" else - mutt_cv_sharedir='${prefix}/share' + mutt_cv_sharedir="${mutt_cv_prefix}/share" fi else - mutt_cv_sharedir='${libdir}' + mutt_cv_sharedir="$libdir" fi]) ]) sharedir=$mutt_cv_sharedir AC_SUBST(sharedir) + AC_ARG_WITH(docdir, [ --with-docdir=PATH specify where to put the documentation], [mutt_cv_docdir=$withval], [ AC_CACHE_CHECK(where to put the documentation, @@ -324,22 +365,20 @@ AC_SUBST(docdir) if test x$mutt_cv_setgid = xyes; then - MUTT_GROUP='-g mail' - MUTT_PERMISSION=2755 + DOTLOCK_GROUP='-g mail' + DOTLOCK_PERMISSION=2755 else - MUTT_GROUP='' - MUTT_PERMISSION=755 + DOTLOCK_GROUP='' + DOTLOCK_PERMISSION=755 fi -AC_SUBST(MUTT_GROUP) -AC_SUBST(MUTT_PERMISSION) +AC_SUBST(DOTLOCK_GROUP) +AC_SUBST(DOTLOCK_PERMISSION) AC_ARG_WITH(domain, [ --with-domain=DOMAIN Specify your DNS domain name ], [if test $withval != yes; then AC_DEFINE_UNQUOTED(DOMAIN, "$withval") fi]) -AC_ARG_ENABLE(hidden-host, [ --enable-hidden-host Only use the domain name for local addresses], AC_DEFINE(HIDDEN_HOST)) - AC_ARG_ENABLE(pop, [ --enable-pop Enable POP3 support], [ AC_DEFINE(USE_POP) AC_CHECK_LIB(socket, socket) @@ -351,7 +390,7 @@ AC_ARG_ENABLE(imap, [ --enable-imap Enable IMAP support], [ AC_DEFINE(USE_IMAP) AC_CHECK_LIB(socket, socket) AC_CHECK_LIB(nsl, gethostbyname) - LIBOBJS="$LIBOBJS imap.o" + LIBOBJS="$LIBOBJS imap.o socket.o" ]) AC_ARG_ENABLE(flock, [ --enable-flock Use flock() to lock files], @@ -402,4 +441,4 @@ AC_ARG_ENABLE(exact-address, [ --enable-exact-address enable regeneration o AC_DEFINE(EXACT_ADDRESS) fi]) -AC_OUTPUT(Makefile rx/Makefile Muttrc doc/Makefile) +AC_OUTPUT(Makefile rx/Makefile Muttrc doc/Makefile doc/dotlock.man doc/mutt.man) diff --git a/copy.c b/copy.c index 9dcbe98c..ebd59794 100644 --- a/copy.c +++ b/copy.c @@ -415,18 +415,19 @@ _mutt_copy_message (FILE *fpout, FILE *fpin, HEADER *hdr, BODY *body, fseek (fpin, body->offset, 0); if (flags & M_CM_PREFIX) { - char buf[LONG_STRING]; + int c; size_t bytes = body->length; - - buf[sizeof (buf) - 1] = 0; - while (bytes > 0) + + fputs(prefix, fpout); + + while((c = fgetc(fpin)) != EOF && bytes--) { - if (fgets (buf, sizeof (buf) - 1, fpin) == NULL) - break; - bytes -= strlen (buf); - fputs (prefix, fpout); - fputs (buf, fpout); - } + fputc(c, fpout); + if(c == '\n') + { + fputs(prefix, fpout); + } + } } else { diff --git a/curs_lib.c b/curs_lib.c index c2177fc2..fa7feb19 100644 --- a/curs_lib.c +++ b/curs_lib.c @@ -178,6 +178,7 @@ void mutt_curses_error (const char *fmt, ...) vsnprintf (Errorbuf, sizeof (Errorbuf), fmt, ap); va_end (ap); + dprint (1, (debugfile, "%s\n", Errorbuf)); Errorbuf[ (COLS < sizeof (Errorbuf) ? COLS : sizeof (Errorbuf)) - 2 ] = 0; BEEP (); @@ -232,6 +233,8 @@ void mutt_perror (const char *s) { char *p = strerror (errno); + dprint (1, (debugfile, "%s: %s (errno = %d)\n", s, + p ? p : "unknown error", errno)); mutt_error ("%s: %s (errno = %d)", s, p ? p : "unknown error", errno); } @@ -269,14 +272,14 @@ int mutt_do_pager (const char *banner, { int rc; - if (strcmp (Pager, "builtin") == 0) - rc = mutt_pager (banner, tempfile, do_color, info); + if (!Pager || strcmp (Pager, "builtin") == 0) + rc = mutt_pager (banner, tempfile, do_color, info, ""); else { char cmd[STRING]; endwin (); - snprintf (cmd, sizeof (cmd), "%s %s", Pager, tempfile); + snprintf (cmd, sizeof (cmd), "%s %s", NONULL(Pager), tempfile); mutt_system (cmd); mutt_unlink (tempfile); rc = 0; @@ -318,7 +321,7 @@ int mutt_enter_fname (const char *prompt, char *buf, size_t blen, int *redraw, i != 0) buf[0] = 0; MAYBE_REDRAW (*redraw); - free (pc); + FREE (&pc); } return 0; diff --git a/curs_main.c b/curs_main.c index cf06bcf9..d1be5a8b 100644 --- a/curs_main.c +++ b/curs_main.c @@ -20,6 +20,7 @@ #include "mutt_curses.h" #include "mutt_menu.h" #include "mailbox.h" +#include "mapping.h" #include "sort.h" #include "buffy.h" @@ -85,7 +86,16 @@ void index_make_entry (char *s, size_t l, MUTTMENU *menu, int num) flag |= M_FORMAT_FORCESUBJ; else { - edgemsgno = Context->v2r[menu->top + (reverse ? menu->pagelen - 1 : 0)]; + if (reverse) + { + if (menu->top + menu->pagelen > menu->max) + edgemsgno = Context->v2r[menu->max - 1]; + else + edgemsgno = Context->v2r[menu->top + menu->pagelen - 1]; + } + else + edgemsgno = Context->v2r[menu->top]; + for (tmp = h->parent; tmp; tmp = tmp->parent) { if ((reverse && tmp->msgno > edgemsgno) @@ -220,9 +230,9 @@ struct mapping_t IndexHelp[] = { /* This function handles the message index window as well as commands returned * from the pager (MENU_PAGER). */ -void mutt_index_menu (void) +int mutt_index_menu (int attach_msg /* invoked while attaching a message */) { - char buf[LONG_STRING], helpstr[SHORT_STRING]; + char buf[LONG_STRING], attach_msg_status[LONG_STRING] = "", helpstr[SHORT_STRING]; int op = OP_NULL; /* function to execute */ int done = 0; /* controls when to exit the "event" loop */ int i = 0, j; @@ -234,6 +244,7 @@ void mutt_index_menu (void) char *cp; /* temporary variable. */ int index_hint; /* used to restore cursor position */ int do_buffy_notify = 1; + int close = 0; /* did we OP_QUIT or OP_EXIT out of this menu? */ menu = mutt_new_menu (); menu->menu = MENU_MAIN; @@ -244,7 +255,8 @@ void mutt_index_menu (void) menu->current = ci_first_message (); menu->help = mutt_compile_help (helpstr, sizeof (helpstr), MENU_MAIN, IndexHelp); - mutt_buffy_check(1); /* force the buffy check after we enter the folder */ + if (!attach_msg) + mutt_buffy_check(1); /* force the buffy check after we enter the folder */ FOREVER { @@ -253,7 +265,7 @@ void mutt_index_menu (void) menu->max = Context ? Context->vcount : 0; oldcount = Context ? Context->msgcount : 0; - if (Context) + if (Context && !attach_msg) { /* check for new mail in the mailbox. If nonzero, then something has * changed about the file (either we got new mail or the file was @@ -345,17 +357,20 @@ void mutt_index_menu (void) } } - /* check for new mail in the incoming folders */ - oldcount = newcount; - if ((newcount = mutt_buffy_check (0)) != oldcount) - menu->redraw |= REDRAW_STATUS; - if (do_buffy_notify) + if (!attach_msg) { - if (mutt_buffy_notify () && option (OPTBEEPNEW)) - beep (); + /* check for new mail in the incoming folders */ + oldcount = newcount; + if ((newcount = mutt_buffy_check (0)) != oldcount) + menu->redraw |= REDRAW_STATUS; + if (do_buffy_notify) + { + if (mutt_buffy_notify () && option (OPTBEEPNEW)) + beep (); + } + else + do_buffy_notify = 1; } - else - do_buffy_notify = 1; mutt_curs_set (0); @@ -384,7 +399,19 @@ void mutt_index_menu (void) if (menu->redraw & REDRAW_STATUS) { - menu_status_line (buf, sizeof (buf), menu, NONULL (Status)); + if (attach_msg) + { + char from_folder [STRING]; + strfcpy(from_folder, Context->path, sizeof (from_folder)); + mutt_pretty_mailbox (from_folder); + snprintf (attach_msg_status, sizeof (attach_msg_status), + "Folder: %s Tagged messages will be attached upon exiting", + from_folder); + snprintf (buf, sizeof (buf), M_MODEFMT, attach_msg_status); + } + else + menu_status_line (buf, sizeof (buf), menu, NONULL (Status)); + CLEARLINE (option (OPTSTATUSONTOP) ? 0 : LINES-2); SETCOLOR (MT_COLOR_STATUS); printw ("%-*.*s", COLS, COLS, buf); @@ -527,7 +554,7 @@ void mutt_index_menu (void) !buf[0]) break; - if (! isdigit (buf[0])) + if (! isdigit ((unsigned char) buf[0])) { mutt_error ("Argument must be a message number."); break; @@ -577,7 +604,7 @@ void mutt_index_menu (void) CHECK_MSGCOUNT; CHECK_READONLY; - mutt_pattern_func (M_DELETE, "Delete messages matching: ", CURHDR); + mutt_pattern_func (M_DELETE, "Delete messages matching: "); menu->redraw = REDRAW_INDEX | REDRAW_STATUS; break; @@ -611,7 +638,7 @@ void mutt_index_menu (void) CHECK_MSGCOUNT; menu->oldcurrent = Context->vcount ? CURHDR->index : -1; - if (mutt_pattern_func (M_LIMIT, "Limit to messages matching: ", CURHDR) == 0) + if (mutt_pattern_func (M_LIMIT, "Limit to messages matching: ") == 0) { if (menu->oldcurrent >= 0) { @@ -634,6 +661,13 @@ void mutt_index_menu (void) case OP_QUIT: + close = op; + if (attach_msg) + { + done = 1; + break; + } + if (query_quadoption (OPT_QUIT, "Quit Mutt?") == M_YES) { if (!Context || mx_close_mailbox (Context) == 0) @@ -702,13 +736,15 @@ void mutt_index_menu (void) if (mx_sync_mailbox (Context) == 0) { if (Context->vcount != oldvcount) - { menu->current -= dcount; - if (menu->current < 0 || menu->current >= Context->vcount) - menu->current = ci_first_message (); - } set_option (OPTSEARCHINVALID); } + + /* do a sanity check even if mx_sync_mailbox failed. + */ + + if (menu->current < 0 || menu->current >= Context->vcount) + menu->current = ci_first_message (); } /* check for a fatal error, or all messages deleted */ @@ -743,7 +779,7 @@ void mutt_index_menu (void) case OP_MAIN_TAG_PATTERN: CHECK_MSGCOUNT; - mutt_pattern_func (M_TAG, "Tag messages matching: ", CURHDR); + mutt_pattern_func (M_TAG, "Tag messages matching: "); menu->redraw = REDRAW_INDEX | REDRAW_STATUS; break; @@ -751,14 +787,14 @@ void mutt_index_menu (void) CHECK_MSGCOUNT; CHECK_READONLY; - if (mutt_pattern_func (M_UNDELETE, "Undelete messages matching: ", CURHDR) == 0) + if (mutt_pattern_func (M_UNDELETE, "Undelete messages matching: ") == 0) menu->redraw = REDRAW_INDEX | REDRAW_STATUS; break; case OP_MAIN_UNTAG_PATTERN: CHECK_MSGCOUNT; - if (mutt_pattern_func (M_UNTAG, "Untag messages matching: ", CURHDR) == 0) + if (mutt_pattern_func (M_UNTAG, "Untag messages matching: ") == 0) menu->redraw = REDRAW_INDEX | REDRAW_STATUS; break; @@ -768,7 +804,7 @@ void mutt_index_menu (void) case OP_MAIN_CHANGE_FOLDER: - if (option (OPTREADONLY)) + if (attach_msg || option (OPTREADONLY)) op = OP_MAIN_CHANGE_FOLDER_READONLY; /* fallback to the readonly case */ @@ -847,7 +883,7 @@ void mutt_index_menu (void) unset_option (OPTNEEDRESORT); - if ((op = mutt_display_message (CURHDR)) == -1) + if ((op = mutt_display_message (CURHDR, attach_msg_status)) == -1) { unset_option (OPTNEEDRESORT); break; @@ -873,17 +909,17 @@ void mutt_index_menu (void) case OP_EXIT: + close = op; + if (menu->menu == MENU_MAIN && attach_msg) + { + done = 1; + break; + } + if ((menu->menu == MENU_MAIN) && (query_quadoption (OPT_QUIT, "Exit Mutt without saving?") == M_YES)) - { - if (Context) - { - mx_fastclose_mailbox (Context); - safe_free ((void **)&Context); - } done = 1; - } break; case OP_MAIN_NEXT_UNDELETED: @@ -1130,12 +1166,6 @@ void mutt_index_menu (void) case OP_MAIN_PREV_SUBTHREAD: CHECK_MSGCOUNT; - if (Context->msgcount != Context->vcount) - { - mutt_error ("No threads in limit mode."); - break; - } - switch (op) { case OP_MAIN_NEXT_THREAD: @@ -1511,6 +1541,7 @@ void mutt_index_menu (void) } mutt_menuDestroy (&menu); + return (close); } void mutt_set_header_color (CONTEXT *ctx, HEADER *curhdr) diff --git a/date.c b/date.c index 9cd20897..35f4ebfd 100644 --- a/date.c +++ b/date.c @@ -17,6 +17,7 @@ */ #include "mutt.h" +#include /* returns the seconds west of UTC given `g' and its corresponding gmtime() representation */ diff --git a/doc/Makefile.in b/doc/Makefile.in index a8f0d9be..44ba7c5e 100644 --- a/doc/Makefile.in +++ b/doc/Makefile.in @@ -19,15 +19,22 @@ CFLAGS=@CFLAGS@ -DSHAREDIR=\"$(sharedir)\" $(XCPPFLAGS) LDFLAGS=@LDFLAGS@ -all: manual.txt mutt.man manual.html +all: mutt.man dotlock.man manual.txt manual.html -install: mutt.man manual.txt +install: dotlock.man mutt.man manual.txt ../mkinstalldirs $(mandir)/man1 $(INSTALL) -m 644 mutt.man $(mandir)/man1/mutt.1 + $(INSTALL) -m 644 dotlock.man $(mandir)/man1/mutt.dotlock.1 ../mkinstalldirs $(docdir) $(INSTALL) -m 644 manual.txt $(docdir) $(INSTALL) -m 644 PGP-Notes.txt $(docdir) +mutt.man: mutt.man.in + (cd .. ; ./config.status) + +dotlock.man: dotlock.man.in + (cd .. ; ./config.status) + uninstall: -rm -f $(mandir)/man1/mutt.1 $(docdir)/manual.txt \ $(docdir)/PGP-Notes.txt @@ -38,8 +45,11 @@ manual.txt: manual.sgml manual.html: manual.sgml sgml2html manual -mutt.man: mutt.sgml - sgml2txt -man mutt +clean: + rm -f *~ *.html *.orig *.rej *.man + +clean-real: + rm -f manual.txt -clean clean-real distclean: - rm -f *~ *.html *.orig *.rej +distclean: clean + rm -f Makefile diff --git a/doc/PGP-Notes.txt b/doc/PGP-Notes.txt index bfc09299..3081198e 100644 --- a/doc/PGP-Notes.txt +++ b/doc/PGP-Notes.txt @@ -1,11 +1,10 @@ - USING PGP FROM WITHIN MUTT Thomas Roessler - Fri Jun 5 12:28:52 CEST 1998 + Fri Jul 10 10:57:50 MEST 1998 While encryption, verification and signing of messages are @@ -175,3 +174,16 @@ $PGPPATH and add the following line to your muttrc: For PGP 2.6, a German version called "muttde" is available as well. + + + +Q: "Isn't there a security problem that mutt leaves the + passphrase in memory which will be dumped into core + files upon errors?" + +Yes, you may consider this a security problem. To work +around this, disable core dumps using resource limits. On +most systems, this will be the following instruction in +your shell: + + ulimit -c 0 diff --git a/doc/dotlock.man.in b/doc/dotlock.man.in new file mode 100644 index 00000000..609251d8 --- /dev/null +++ b/doc/dotlock.man.in @@ -0,0 +1,144 @@ +.\" -*-nroff-*- +.\" +.\" +.\" Copyright (C) 1996-8 Michael R. Elkins +.\" Copyright (C) 1998 Thomas Roessler +.\" +.\" This program is free software; you can redistribute it and/or modify +.\" it under the terms of the GNU General Public License as published by +.\" the Free Software Foundation; either version 2 of the License, or +.\" (at your option) any later version. +.\" +.\" This program is distributed in the hope that it will be useful, +.\" but WITHOUT ANY WARRANTY; without even the implied warranty of +.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +.\" GNU General Public License for more details. +.\" +.\" You should have received a copy of the GNU General Public License +.\" along with this program; if not, write to the Free Software +.\" Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +.\" +.TH dotlock 1 "JULY 1998" Unix "User Manuals" +.SH NAME +.PP +mutt.dotlock \- Lock mail spool files. +.SH SYNOPSIS +.PP +.B mutt.dotlock +[-t|-f|-u] [-p] [-r \fIretries\fP] \fIfile\fP +.SH DESCRIPTION +.PP +.B dotlock +implements the traditional mail spool file locking method: +To lock \fIfile\fP, a file named \fIfile\fP.lock is +created. The program operates with group mail privileges +if necessary. +.SH OPTIONS +.PP +.IP "-t" +Just try. +.B dotlock +won't actually lock a file, but inform the invoking +process if it's at all possible to lock \fIfile\fP. +.IP "-f" +Force the lock. If another process holds a lock on +\fIfile\fP longer than a certain amount of time, +.B dotlock +will break that lock by removing the lockfile. +.IP "-u" +Unlock. +.B dotlock +will remove \fIfile\fP.lock. +.IP "-p" +Use privileges. If given this option, +.B dotlock +will operate with group mail privileges when creating and +deleting lock files. +.IP "-r \fIretries\fP" +This command line option tells +.B dotlock +to try locking +\fIretries\fP times before giving up or (if invoked with +the +.B -f +command line option) break a lock. The default value is 5. +.B dotlock +waits one second between successive locking attempts. +.SH FILES +.PP +.IP "\fIfile\fP.lock" +The lock file +.B dotlock +generates. +.SH SEE ALSO +.PP +.BR fcntl (2), +.BR flock (2), +.BR lockfile (1), +.BR mutt (1) +.SH DIAGNOSTICS +.PP +.B dotlock +gives all diagnostics in its return values: +.TP +.B "0 \- DL_EX_OK" +The program was successful. +.TP +.B "1 \- DL_EX_ERROR" +An unspecified error such as bad command line parameters, +lack of system memory and the like has occured. +.TP +.B "3 \- DL_EX_EXIST" +The +user wants to lock a file which has been locked by +another process already. If +.B dotlock +is invoked with the +.B -f +command line option, +.B dotlock +won't generate this error, but break other processes' +locks. +.TP +.B "4 \- DL_EX_NEED_RPIVS" +This return value only occurs if +.B dotlock +has been invoked +with the +.B -t +command line option. It means that +.B dotlock +will have to use its group mail privileges to lock +\fIfile\fP. +.TP +.B "5 \- DL_EX_IMPOSSIBLE" +This return value only occurs if +.B dotlock +has been invoked with the +.B -t +command line option. It means that +.B dotlock +is unable to lock \fIfile\fP even with group mail +privileges. +.SH NOTES +.PP +.B dotlock +tries to implement an NFS-safe dotlocking method which was +borrowed from +.B lockfile +(1). +.PP +If the user can't open \fIfile\fP for reading with his +normal privileges, dotlock will return the +.B DL_EX_ERROR +exit value to avoid certain attacks against other users' +spool files. The code carefully avoids race conditions +when checking permissions; for details of all this see the +comments in dotlock.c. +.SH HISTORY +.PP +.B dotlock +is part of the Mutt mail user agent package. It has been +created to avoid running mutt with group mail privileges. +.SH AUTHOR +Thomas Roessler diff --git a/doc/manual.sgml b/doc/manual.sgml index a86f2260..f11a6ca6 100644 --- a/doc/manual.sgml +++ b/doc/manual.sgml @@ -4,7 +4,7 @@ The Mutt E-Mail Client <author>by Michael Elkins <htmlurl url="mailto:me@cs.hmc.edu" name="<me@cs.hmc.edu>"> -<date>v0.92.2, 23 April 1998 +<date>v0.94.2, 31 July 1998 <abstract> ``All mail clients suck. This one just sucks less.'' -me, circa 1995 </abstract> @@ -19,21 +19,21 @@ groups of messages. <sect1>Mutt Home Page <p> -<htmlurl url="http://www.cs.hmc.edu/~me/mutt/index.html" -name="http://www.cs.hmc.edu/~me/mutt/index.html"> +<htmlurl url="http://www.mutt.org/" +name="http://www.mutt.org/"> <sect1>Mailing Lists <p> To subscribe to one of the following mailing lists, send a message with the word <em/subscribe/ in the subject to -<tt/list-name/<em/-request/<tt/@cs.hmc.edu/. +<tt/list-name/<em/-request/<tt/@mutt.org/. <itemize> -<item><htmlurl url="mailto:mutt-announce-request@cs.hmc.edu" -name="mutt-announce@cs.hmc.edu"> -- low traffic list for announcements -<item><htmlurl url="mailto:mutt-users-request@cs.hmc.edu" -name="mutt-users@cs.hmc.edu"> -- help, bug reports and feature requests -<item><htmlurl url="mailto:mutt-dev-request@cs.hmc.edu" name="mutt-dev@cs.hmc.edu"> -- development mailing list +<item><htmlurl url="mailto:mutt-announce-request@mutt.org" +name="mutt-announce@mutt.org"> -- low traffic list for announcements +<item><htmlurl url="mailto:mutt-users-request@mutt.org" +name="mutt-users@mutt.org"> -- help, bug reports and feature requests +<item><htmlurl url="mailto:mutt-dev-request@mutt.org" name="mutt-dev@mutt.org"> -- development mailing list </itemize> <bf/Note:/ all messages posted to <em/mutt-announce/ are automatically @@ -43,8 +43,8 @@ lists. <sect1>Software Distribution Sites <p> <itemize> -<item><htmlurl url="ftp://ftp.cs.hmc.edu/pub/me/mutt/" -name="ftp://ftp.cs.hmc.edu/pub/me/mutt/"> +<item><htmlurl url="ftp://ftp.guug.de/pub/mutt/" +name="ftp://ftp.guug.de/pub/mutt/"> </itemize> <sect1>IRC @@ -80,7 +80,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. This section is intended as a brief overview of how to use Mutt. There are many other features which are described elsewhere in the manual. There is even more information available in the Mutt FAQ and various web -pages. See the <htmlurl url="http://www.cs.hmc.edu/~me/mutt/" +pages. See the <htmlurl url="http://www.mutt.org/mutt/" name="Mutt Page"> for more details. The keybindings described in this section are the defaults as distributed. @@ -98,14 +98,14 @@ Information is presented in menus, very similar to ELM. Here is a table showing the common keys used to navigate menus in Mutt. <tscreen><verb> -j or Down next-entry move to the next entry -k or Up previous-entry move to the previous entry -z or PageDn page-down go to the next page -Z or PageUp page-up go to the previous page -= or Home first-entry jump to the first entry -* or End last-entry jump to the last entry -q quit exit the current menu -? help list all keybindings for the current menu +j or Down next-entry move to the next entry +k or Up previous-entry move to the previous entry +z or PageDn page-down go to the next page +Z or PageUp page-up go to the previous page += or Home first-entry jump to the first entry +* or End last-entry jump to the last entry +q quit exit the current menu +? help list all keybindings for the current menu </verb></tscreen> <sect1>Editing Input Fields<label id="editing"> @@ -115,20 +115,20 @@ textual data such as email addresses or filenames. The keys used to move around while editing are very similar to those of Emacs. <tscreen><verb> -^A or <Home> bol move to the start of the line -^B or <Left> backward-char move back one char -^D or <Delete> delete-char delete the char under the cursor -^E or <End> eol move to the end of the line -^F or <Right> forward-char move forward one char -^K kill-eol delete to the end of the line -^U kill-line delete entire line -^W kill-word kill the word in front of the cursor -<Up> history-up recall previous string from history -<Down> history-down recall next string from history -<BackSpace> backspace kill the char in front of the cursor -^G n/a abort -<Tab> n/a complete filename (only when prompting for a file) -<Return> n/a finish editing +^A or <Home> bol move to the start of the line +^B or <Left> backward-char move back one char +^D or <Delete> delete-char delete the char under the cursor +^E or <End> eol move to the end of the line +^F or <Right> forward-char move forward one char +^K kill-eol delete to the end of the line +^U kill-line delete entire line +^W kill-word kill the word in front of the cursor +<Up> history-up recall previous string from history +<Down> history-down recall next string from history +<BackSpace> backspace kill the char in front of the cursor +^G n/a abort +<Tab> n/a complete filename (only when prompting for a file) +<Return> n/a finish editing </verb></tscreen> You can remap the <em/editor/ functions using the <ref id="bind" name="bind"> @@ -152,34 +152,34 @@ modes. <p> <tscreen><verb> -c change to a different mailbox -ESC c change to a folder in read-only mode -C copy the current message to another mailbox -ESC C decode a message and copy it to a folder -ESC s decode a message and save it to a folder -D delete messages matching a pattern -d delete the current message -F mark as important -l show messages matching a pattern -N mark message as new -o change the current sort method -O reverse sort the mailbox -q save changes and exit -s save-message -t toggle the tag on a message -ESC t toggle tag on entire message thread -u undelete-message -v view-attachments -x abort changes and exit -<Return> display-message -<Tab> jump to the next new message -@ show the author's full e-mail address -$ save changes to mailbox -/ search -ESC / search-reverse -^L clear and redraw the screen -^T tag messages matching a pattern -^U undelete messages matching a pattern +c change to a different mailbox +ESC c change to a folder in read-only mode +C copy the current message to another mailbox +ESC C decode a message and copy it to a folder +ESC s decode a message and save it to a folder +D delete messages matching a pattern +d delete the current message +F mark as important +l show messages matching a pattern +N mark message as new +o change the current sort method +O reverse sort the mailbox +q save changes and exit +s save-message +t toggle the tag on a message +ESC t toggle tag on entire message thread +u undelete-message +v view-attachments +x abort changes and exit +<Return> display-message +<Tab> jump to the next new message +@ show the author's full e-mail address +$ save changes to mailbox +/ search +ESC / search-reverse +^L clear and redraw the screen +^T tag messages matching a pattern +^U undelete messages matching a pattern </verb></tscreen> <sect3>Status Flags @@ -191,16 +191,16 @@ Zero or more of the following ``flags'' may appear, which mean: <p> <tscreen><verb> -D message is deleted -K contains a PGP public key -M requires mailcap to view -N message is new -O message is old -P message is PGP encrypted -r message has been replied to -S message is PGP signed -! message is flagged -* message is tagged +D message is deleted +K contains a PGP public key +M requires mailcap to view +N message is new +O message is old +P message is PGP encrypted +r message has been replied to +S message is PGP signed +! message is flagged +* message is tagged </verb></tscreen> Some of the status flags can be turned on or off using @@ -216,10 +216,10 @@ to. They can be customized with the <p> <tscreen><verb> -+ message is to you and you only -T message is to you, but also to or cc'ed to others -C message is cc'ed to you -F message is from you ++ message is to you and you only +T message is to you, but also to or cc'ed to others +C message is cc'ed to you +F message is from you </verb></tscreen> <sect2>The Pager @@ -230,13 +230,13 @@ The pager is very similar to the Unix program <em/less/ though not nearly as featureful. <tscreen><verb> -<Return> go down one line -<Space> display the next page (or next message if at the end of a message) -- go back to the previous page -n display the next message -? show keybindings -/ search for a regular expression (pattern) -\ toggle search pattern coloring +<Return> go down one line +<Space> display the next page (or next message if at the end of a message) +- go back to the previous page +n display the next message +? show keybindings +/ search for a regular expression (pattern) +\ toggle search pattern coloring </verb></tscreen> In addition, many of the functions from the <em/index/ are available in @@ -291,17 +291,17 @@ When the mailbox is <ref id="sort" name="sorted"> by <em/threads/, there are a few additional functions available in the <em/index/ and <em/pager/ modes. <tscreen><verb> -^D delete-thread delete all messages in the current thread -^U undelete-thread undelete all messages in the current thread -^N next-thread jump to the start of the next thread -^P previous-thread jump to the start of the previous thread -^R read-thread mark the current thread as read -ESC d delete-subthread delete all messages in the current subthread -ESC u undelete-subthread undelete all messages in the current subthread -ESC n next-subthread jump to the start of the next subthread -ESC p previous-subthread jump to the start of the previous subthread -ESC r read-subthread mark the current subthread as read -ESC t tag-thread toggle the tag on the current thread +^D delete-thread delete all messages in the current thread +^U undelete-thread undelete all messages in the current thread +^N next-thread jump to the start of the next thread +^P previous-thread jump to the start of the previous thread +^R read-thread mark the current thread as read +ESC d delete-subthread delete all messages in the current subthread +ESC u undelete-subthread undelete all messages in the current subthread +ESC n next-subthread jump to the start of the next subthread +ESC p previous-subthread jump to the start of the previous subthread +ESC r read-subthread mark the current subthread as read +ESC t tag-thread toggle the tag on the current thread </verb></tscreen> See also: <ref id="strict_threads" name="$strict_threads">. @@ -391,13 +391,13 @@ The following bindings are available in the <em/index/ for sending messages. <tscreen><verb> -m compose compose a new message -r reply reply to sender -g group-reply reply to all recipients -L list-reply reply to mailing list address -f forward forward message -b bounce bounce (remail) message -ESC k mail-key mail a PGP public key to someone +m compose compose a new message +r reply reply to sender +g group-reply reply to all recipients +L list-reply reply to mailing list address +f forward forward message +b bounce bounce (remail) message +ESC k mail-key mail a PGP public key to someone </verb></tscreen> Bouncing a message sends the message as is to the recipient you @@ -434,21 +434,21 @@ Once you have finished editing the body of your mail message, you are returned to the <em/compose/ menu. The following options are available: <tscreen><verb> -a attach-file attach a file -ESC k attach-key attach a PGP public key -d edit-description edit description on attachment -D detach-file detach a file -T edit-to edit the To field -c edit-cc edit the Cc field -b edit-bcc edit the Bcc field -y send-message send the message -s edit-subject edit the Subject -f edit-fcc specify an ``Fcc'' mailbox -p pgp-menu select PGP options (``i'' version only) -P postpone-message postpone this message until later -q quit quit (abort) sending the message -i ispell check spelling (if available on your system) -^F forget-passphrase whipe PGP passphrase from memory +a attach-file attach a file +ESC k attach-key attach a PGP public key +d edit-description edit description on attachment +D detach-file detach a file +T edit-to edit the To field +c edit-cc edit the Cc field +b edit-bcc edit the Bcc field +y send-message send the message +s edit-subject edit the Subject +f edit-fcc specify an ``Fcc'' mailbox +p pgp-menu select PGP options (``i'' version only) +P postpone-message postpone this message until later +q quit quit (abort) sending the message +i ispell check spelling (if available on your system) +^F forget-passphrase whipe PGP passphrase from memory </verb></tscreen> <sect2>Editing the message header<label id="edit_headers"> @@ -536,7 +536,7 @@ An initialization file consists of a series of <ref id="commands" name="commands">. Each line of the file may contain one or more commands. When multiple commands are used, they must be separated by a semicolon (;). <tscreen><verb> - set realname='Mutt user' ; ignore x- +set realname='Mutt user' ; ignore x- </verb></tscreen> The hash mark, or pound sign (``#''), is used as a ``comment'' character. You can use it to @@ -582,8 +582,15 @@ The output of the Unix command ``uname -a'' will be substituted before the line is parsed. Note that since initialization files are line oriented, only the first line of output from the Unix command will be substituted. -For a complete list of the commands understood by mutt, see the -<ref id="commands" name="command reference">. +UNIX environments can be accessed like the way it is done in shells like +sh and bash: Prepend the name of the environment by a ``$dollar;''. For +example, +<tscreen><verb> +set record=+sent_on_$HOSTNAME +</verb></tscreen> + +The commands understood by mutt are explained in the next paragraphs. +For a complete list, see the <ref id="commands" name="command reference">. <sect1>Defining/Using aliases<label id="alias"> <p> @@ -664,7 +671,6 @@ defined maps are: <item>compose <item>pager <item>pgp -<item>url </itemize> <em/key/ is the key (or key sequence) you wish to bind. To specify a @@ -679,24 +685,24 @@ equivalent to <em/\c?/). In addition, <em/key/ may consist of: <tscreen><verb> -\t tab -\r carriage return -\n newline -\e escape -up up arrow -down down arrow -left left arrow -right right arrow -pageup Page Up -pagedown Page Down -backspace Backspace -delete Delete -insert Insert -enter Enter -home Home -end End -f1 function key 1 -f10 function key 10 +\t tab +\r carriage return +\n newline +\e escape +<up> up arrow +<down> down arrow +<left> left arrow +<right> right arrow +<pageup> Page Up +<pagedown> Page Down +<backspace> Backspace +<delete> Delete +<insert> Insert +<enter> Enter +<home> Home +<end> End +f1 function key 1 +f10 function key 10 </verb></tscreen> <em/key/ does not need to be enclosed in quotes unless it contains a @@ -709,7 +715,7 @@ sequence. <sect1>Setting variables based upon mailbox<label id="folder-hook"> <p> -Usage: <tt/folder-hook/ [!]<em/pattern/ <em/command/ +Usage: <tt/folder-hook/ [!]<em/regexp/ <em/command/ It is often desirable to change settings based on which mailbox you are reading. The folder-hook command provides a method by which you can execute @@ -742,7 +748,7 @@ folder-hook . set sort=date-sent <sect1>Keyboard macros<label id="macro"> <p> -Usage: <tt/macro/ <em/menu/ <em/key/ <em/sequence/ +Usage: <tt/macro/ <em/menu/ <em/key/ <em/sequence/ [ <em/description/ ] Macros are useful when you would like a single key to perform a series of actions. When you press <em/key/ in menu <em/menu/, Mutt will behave as if @@ -755,6 +761,9 @@ id="bind" name="key bindings">, with the addition that control characters in <em/sequence/ can also be specified as <em/ˆx/. In order to get a caret (``ˆ'') you need to use <em/ˆˆ/. +Optionally you can specify a descriptive text, which is shown in the +help screens. + <bf/Note:/ Macro definitions (if any) listed in the help screen(s), are silently truncated at the screen width, and are not wrapped. @@ -889,11 +898,11 @@ Mutt has a few nice features for <ref id="using_lists" name="handling mailing lists">. In order to take advantage of them, you must specify which addresses belong to mailing lists. -It is important to note that you should <bf/never/ specify the domain name ( -the part after the ``@'') with the lists command. You should only +It is important to note that you should <bf/never/ specify the domain name +(the part after the ``@'') with the lists command. You should only specify the ``mailbox'' portion of the address (the part before the ``@''). For example, if you've subscribed to the Mutt mailing list, you will receive -mail addressed to <em/mutt-users@cs.hmc.edu/. So, to tell Mutt that this is a +mail addressed to <em/mutt-users@mutt.org/. So, to tell Mutt that this is a mailing list, you would add ``lists mutt-users'' to your initialization file. The ``unlists'' command is to remove a token from the list of mailing-lists. @@ -986,13 +995,17 @@ Usage: <tt/hdr_order/ <em/header1/ <em/header2/ <em/header3/ With this command, you can specify an order in which mutt will attempt to present headers to you when viewing messages. +``unhdr_order *'' will clear all previous headers from the order list, +thus removing the header order effects set by the system-wide startup +file. + <tscreen><verb> hdr_order From Date: From: To: Cc: Subject: </verb></tscreen> <sect1>Specify default save filename<label id="save-hook"> <p> -Usage: <tt/save-hook/ [!]<em/regexp/ <em/filename/ +Usage: <tt/save-hook/ [!]<em/pattern/ <em/filename/ This command is used to override the default filename used when saving messages. <em/filename/ will be used as the default filename if the message is @@ -1000,7 +1013,7 @@ messages. <em/filename/ will be used as the default filename if the message is message is addressed <em/to:/ something matching <em/regexp/. See <ref id="pattern_hook" name="matching messages"> for information on the -exact format of <em/regexp/. +exact format of <em/pattern/. Examples: @@ -1013,7 +1026,7 @@ Also see the <ref id="fcc-save-hook" name="fcc-save-hook"> command. <sect1>Specify default Fcc: mailbox when composing<label id="fcc-hook"> <p> -Usage: <tt/fcc-hook/ [!]<em/regexp/ <em/mailbox/ +Usage: <tt/fcc-hook/ [!]<em/pattern/ <em/mailbox/ This command is used to save outgoing mail in a mailbox other than <ref id="record" name="$record">. Mutt searches the initial list of @@ -1022,7 +1035,7 @@ as the default Fcc: mailbox. If no match is found the message will be saved to <ref id="record" name="$record"> mailbox. See <ref id="pattern_hook" name="matching messages"> for information on the -exact format of <em/regexp/. +exact format of <em/pattern/. Example: <tt/fcc-hook aol.com$ +spammers/ @@ -1033,23 +1046,23 @@ name="fcc-save-hook"> command. <sect1>Specify default save filename and default Fcc: mailbox at once<label id="fcc-save-hook"> <p> -Usage: <tt/fcc-save-hook/ [!]<em/regexp/ <em/mailbox/ +Usage: <tt/fcc-save-hook/ [!]<em/pattern/ <em/mailbox/ This command is a shortcut, equivalent to doing both a <ref id="fcc-hook" name="fcc-hook"> and a <ref id="save-hook" name="save-hook"> with its arguments. <sect1>Change settings based upon message recipients<label id="send-hook"> <p> -Usage: <tt/send-hook/ [!]<em/regexp/ <em/command/ +Usage: <tt/send-hook/ [!]<em/pattern/ <em/command/ This command can be used to execute arbitrary configuration commands based -upon recipients of the message. <em/regexp/ is a regular expression +upon recipients of the message. <em/pattern/ is a regular expression matching the desired address. <em/command/ is executed when <em/regexp/ matches recipients of the message. When multiple matches occur, commands are executed in the order they are specified in the muttrc. See <ref id="pattern_hook" name="matching messages"> for information on the -exact format of <em/regexp/. +exact format of <em/pattern/. Example: <tt/send-hook mutt &dquot;set mime_forward signature=''&dquot;/ @@ -1063,6 +1076,18 @@ signatures based upon the recipients. list of recipients. Adding a recipient after replying or editing the message will NOT cause any send-hook to be executed. +<sect1>Choosing the PGP key of the recipient<label id="pgp-hook"> +<p> +Usage: <tt/pgp-hook/ <em/pattern/ <em/keyid/ + +When encrypting messages with PGP, you may want to associate a certain +PGP key with a given e-mail address automatically, either because the +recipient's public key can't be deduced from the destination address, +or because, for some reasons, you need to override the key Mutt would +normally use. The pgp-hook command provides a method by which you can +specify the ID of the public key to be used when encrypting messages to +a certain recipient. + <sect1>Adding key sequences to the keyboard buffer<label id="push"> <p> Usage: <tt/push/ <em/string/ @@ -1078,7 +1103,7 @@ Usage: <tt/unscore/ <em/pattern/ [ <em/pattern/ ... ] The <tt/score/ commands adds <em/value/ to a message's score if <em/pattern/ matches it. <em/pattern/ is a string in the format described in the <ref -id="searching" name="searching"> section. <em/value/ is a positive or +id="pattern" name="patterns"> section. <em/value/ is a positive or negative integer. A message's final score is the sum total of all matching <tt/score/ entries. However, you may optionally prefix <em/value/ with an equal sign (=) to cause evaluation to stop at a particular entry if there is @@ -1159,25 +1184,23 @@ path of your home directory. If the filename ends with a vertical bar (|), then <em/filename/ is considered to be an executable program from which to read input (eg. -<tt/source ~/bin/myscript|/. +<tt/source ~/bin/myscript|/). <sect>Advanced Usage -<sect1>Searching and Regular Expressions<label id="regex"> +<sect1>Regular Expressions<label id="regexp"> <p> -All text patterns for searching and matching in Mutt must be specified -as regular expressions (regexp) in the ``POSIX extended'' syntax (which +All string patterns in Mutt including those in more complex +<ref id="pattern" name="patterns"> must be specified +using regular expressions (regexp) in the ``POSIX extended'' syntax (which is more or less the syntax used by egrep and GNU awk). For your convenience, we have included below a brief description of this syntax. The search is case sensitive if the pattern contains at least one upper case letter, and case insensitive otherwise. Note that ``\'' must be quoted if used for a regular expression in an initialization -command: ``\\''. For more information, see the section on -<ref id="searching" name="searching"> below. +command: ``\\''. -<sect2>Regular Expressions<label id="regexps"> -<p> A regular expression is a pattern that describes a set of strings. Regular expressions are constructed analogously to arithmetic expressions, by using various operators to combine smaller expressions. @@ -1270,7 +1293,7 @@ of several repetition operators: <descrip> <tag/?/ The preceding item is optional and matched at most once. -<tag/*/ +<tag/*/ The preceding item will be matched zero or more times. <tag/+/ The preceding item will be matched one or more times. @@ -1322,48 +1345,54 @@ Matches the empty string at the end of a buffer. Please note however that these operators are not defined by POSIX, so they may or may not be available in stock libraries on various systems. -<sect2>Searching<label id="searching"> +<sect1>Patterns<label id="pattern"> <p> Many of Mutt's commands allow you to specify a pattern to match (limit, tag-pattern, delete-pattern, etc.). There are several ways to select messages: <tscreen><verb> -~A all messages -~b PATTERN messages which contain PATTERN in the message body -~c USER messages carbon-copied to USER -~C PATTERN message is either to: or cc: PATTERN -~D deleted messages -~d [MIN]-[MAX] messages with ``date-sent'' in a Date range -~E expired messages -~e PATTERN message which contains PATTERN in the ``Sender'' field -~F flagged messages -~f USER messages originating from USER -~h PATTERN messages which contain PATTERN in the message header -~i ID message which match ID in the ``Message-ID'' field -~L PATTERN message is either originated or received by PATTERN -~l message is addressed to a known mailing list -~m [MIN]-[MAX] message in the range MIN to MAX -~n [MIN]-[MAX] messages with a score in the range MIN to MAX -~N new messages -~O old messages -~p message is addressed to you (consults $alternates) -~P message is from you (consults $alternates) -~Q messages which have been replied to -~R read messages -~r [MIN]-[MAX] messages with ``date-received'' in a Date range -~S superseded messages -~s SUBJECT messages having SUBJECT in the ``Subject'' field. -~T tagged messages -~t USER messages addressed to USER -~U unread messages -~x PATTERN messages which contain PATTERN in the `References' field +~A all messages +~b EXPR messages which contain EXPR in the message body +~B EXPR messages which contain EXPR in the whole message +~c USER messages carbon-copied to USER +~C EXPR message is either to: or cc: EXPR +~D deleted messages +~d [MIN]-[MAX] messages with ``date-sent'' in a Date range +~E expired messages +~e EXPR message which contains EXPR in the ``Sender'' field +~F flagged messages +~f USER messages originating from USER +~h EXPR messages which contain EXPR in the message header +~i ID message which match ID in the ``Message-ID'' field +~L EXPR message is either originated or received by EXPR +~l message is addressed to a known mailing list +~m [MIN]-[MAX] message in the range MIN to MAX *) +~n [MIN]-[MAX] messages with a score in the range MIN to MAX *) +~N new messages +~O old messages +~p message is addressed to you (consults $alternates) +~P message is from you (consults $alternates) +~Q messages which have been replied to +~R read messages +~r [MIN]-[MAX] messages with ``date-received'' in a Date range +~S superseded messages +~s SUBJECT messages having SUBJECT in the ``Subject'' field. +~T tagged messages +~t USER messages addressed to USER +~U unread messages +~x EXPR messages which contain EXPR in the `References' field +~z [MIN]-[MAX] messages with a size in the range MIN to MAX *) </verb></tscreen> -Where PATTERN, USER, ID, and SUBJECT are -<ref id="regex" name="regular expressions">. +Where EXPR, USER, ID, and SUBJECT are +<ref id="regexp" name="regular expressions">. + +*) The forms <tt/<[MAX]/, <tt/>[MIN]/, +<tt/[MIN]-/ and <tt/-[MAX]/ +are allowed, too. -<sect2>Complex Searches +<sect2>Complex Patterns <p> Logical AND is performed by specifying more than one criterion. For @@ -1423,10 +1452,10 @@ be specified as: <em/offset/ is specified as a positive number with one of the following units: <verb> -y years -m months -w weeks -d days +y years +m months +w weeks +d days </verb> Example: to select messages less than 1 month old, you would use @@ -1449,8 +1478,8 @@ a mailing list to a separate folder, or to delete all messages with a given subject. To tag all messages matching a pattern, use the tag-pattern function, which is bound to ``control-T'' by default. Or you can select individual messages by hand using the ``tag-message'' function, which is -bound to ``t'' by default. See <ref id="searching" name="searching"> for -Mutt's searching syntax. +bound to ``t'' by default. See <ref id="pattern" name="patterns"> for +Mutt's pattern matching syntax. Once you have tagged the desired messages, you can use the ``tag-prefix'' operator, which is the ``;'' (semicolon) key by default. @@ -1466,7 +1495,8 @@ A <em/hook/ is a concept borrowed from the EMACS editor which allows you to execute arbitrary commands before performing some operation. For example, you may wish to tailor your configuration based upon which mailbox you are reading, or to whom you are sending mail. In the Mutt world, a <em/hook/ -consists of a <ref id="regex" name="regular expression"> along with a +consists of a <ref id="regexp" name="regular expression"> or +<ref id="pattern" name="pattern"> along with a configuration option/command. See <itemize> <item><ref id="folder-hook" name="folder-hook"> @@ -1482,11 +1512,11 @@ for specific details on each type of <em/hook/ available. <p> Hooks that act upon messages (<tt/send-hook, save-hook, fcc-hook/) are evaluated in a slightly different manner. For the other types of hooks, a -<ref id="regex" name="regular expression">. But in dealing with messages a -finer grain of control is needed for matching since for different purposes -you want to match different criteria. +<ref id="regexp" name="regular expression"> is sufficient. But in dealing +with messages a finer grain of control is needed for matching since for +different purposes you want to match different criteria. -Mutt allows the use of the <ref id="searching" name="search pattern"> +Mutt allows the use of the <ref id="pattern" name="search pattern"> language for matching messages in hook commands. This works in exactly the same way as it would when <em/limiting/ or <em/searching/ the mailbox, except that you are restricted to those operators which match information @@ -1504,8 +1534,8 @@ However, it is not required that you write the pattern to match using the full searching language. You can still specify a simple <em/regular expression/ like the other hooks, in which case Mutt will translate your pattern into the full language, using the translation specified by the -<ref id="default_hook" name="$dfault_hook"> variable. The pattern -is translated at the time the hook is declared, so the value of +<ref id="default_hook" name="$default_hook"> variable. The +pattern is translated at the time the hook is declared, so the value of <ref id="default_hook" name="$dfault_hook"> that is in effect at that time will be used. @@ -1530,9 +1560,9 @@ addresses, return a non-zero exit code and a one line error message. An example multiple response output: <tscreen><verb> Searching database ... 20 entries ... 3 matching: -me@cs.hmc.edu Michael Elkins mutt dude -blong@fiction.net Brandon Long mutt and more -roessler@guug.de Thomas Roessler mutt pgp +me@cs.hmc.edu Michael Elkins mutt dude +blong@fiction.net Brandon Long mutt and more +roessler@guug.de Thomas Roessler mutt pgp </verb></tscreen> There are two mechanisms for accessing the query function of mutt. One @@ -1603,6 +1633,8 @@ path. <item>- -- refers to the file you've last visited <item>˜ -- refers to your home directory <item>= or + -- refers to your <ref id="folder" name="$folder"> directory +<item>@<em/alias/ -- refers to the <ref id="save-hook" +name="default save folder"> as determined by the address of the alias </itemize> <sect1>Handling Mailing Lists<label id="using_lists"> @@ -1687,6 +1719,39 @@ and it's rather limited. If you need more functionality you should consider using a specialized program, such as <htmlurl url="http://www.ccil.org/~esr/fetchmail" name="fetchmail"> +<sect1>IMAP Support (OPTIONAL) +<p> + +If Mutt was compiled with IMAP support (by running the <em/configure/ +script with the <em/--enable-imap/ flag), it has the ability to work +with folders located on a remote imap server. + +You can access the remote inbox by selecting the folder +<tt/{imapserver}inbox/, where <tt/imapserver/ is the name of the IMAP +server and <tt/inbox/ is the special name for your spool mailbox on +the IMAP server. If you want to access another mail folder at the IMAP +server, you should use <tt>{imapserver}path/to/folder</tt> where +<tt>path/to/folder</tt> is the path of the folder you want to access +relative to your home directory. + +<bf/Note:/ The IMAP support is in a very early state and quite +unstable at the moment. If you need a more stable way to access your +IMAP folder, consider using a specialized program, such as <htmlurl +url="http://www.ccil.org/~esr/fetchmail" name="fetchmail">. + +<sect1>Start a WWW Browser on URLs (EXTERNAL)<label id="urlview"> +<p> +If a message contains URLs (<em/unified ressource locator/ = address in the +WWW space like <em>http://www.mutt.org/</em>), it is efficient to get +a menu with all the URLs and start a WWW browser on one of them. This +functionality is provided by the external urlview program which can be +retrieved at <htmlurl url="ftp://ftp.cs.hmc.edu/pub/me/" +name="ftp://ftp.cs.hmc.edu/pub/me/"> and the configuration commands: +<tscreen><verb> +macro index \cb |urlview\n +macro pager \cb |urlview\n +</verb></tscreen> + <sect>Mutt's MIME Support <p> Quite a bit of effort has been made to make Mutt the premier text-mode @@ -1974,9 +2039,9 @@ attempting to print an <tt>image/gif</tt>, and you have the following entries in your mailcap file, Mutt will search for an entry with the print command: <tscreen><verb> -image/*; xv %s -image/gif; ; print= anytopnm %s | pnmtops | lpr; \ - nametemplate=%s.gif +image/*; xv %s +image/gif; ; print= anytopnm %s | pnmtops | lpr; \ + nametemplate=%s.gif </verb></tscreen> Mutt will skip the <tt>image/*</tt> entry and use the <tt>image/gif</tt> entry with the print command. @@ -1987,9 +2052,9 @@ automatically, the other to be viewed interactively from the attachment menu. In addition, you can then use the test feature to determine which viewer to use interactively depending on your environment. <tscreen><verb> -text/html; netscape -remote 'openURL(%s)' ; test=RunningX -text/html; lynx %s; nametemplate=%s.html -text/html; lynx -dump %s; nametemplate=%s.html; copiousoutput +text/html; netscape -remote 'openURL(%s)' ; test=RunningX +text/html; lynx %s; nametemplate=%s.html +text/html; lynx -dump %s; nametemplate=%s.html; copiousoutput </verb></tscreen> For <ref id="auto_view" name="Autoview">, Mutt will choose the third entry because of the copiousoutput tag. For interactive viewing, Mutt @@ -2027,7 +2092,7 @@ Content-Type: text/plain; charset=iso-8859-1 then Mutt will expand %{charset} to iso-8859-1. The default metamail mailcap file uses this feature to test the charset to spawn an xterm using the right charset to view the message. -<tag>∖%</tag> +<tag>\%</tag> This will be replaced by a % </descrip> Mutt does not currently support the %F and %n keywords @@ -2039,11 +2104,11 @@ multipart messages, which is handled internally by Mutt. This mailcap file is fairly simple and standard: <code> # I'm always running X :) -video/*; xanim %s > /dev/null -image/*; xv %s > /dev/null +video/*; xanim %s > /dev/null +image/*; xv %s > /dev/null # I'm always running netscape (if my computer had more memory, maybe) -text/html; netscape -remote 'openURL(%s)' +text/html; netscape -remote 'openURL(%s)' </code> This mailcap file shows quite a number of examples: @@ -2051,27 +2116,27 @@ This mailcap file shows quite a number of examples: <code> # Use xanim to view all videos Xanim produces a header on startup, # send that to /dev/null so I don't see it -video/*; xanim %s > /dev/null +video/*; xanim %s > /dev/null # Send html to a running netscape by remote -text/html; netscape -remote 'openURL(%s)'; test=RunningNetscape +text/html; netscape -remote 'openURL(%s)'; test=RunningNetscape # If I'm not running netscape but I am running X, start netscape on the # object -text/html; netscape %s; test=RunningX +text/html; netscape %s; test=RunningX # Else use lynx to view it as text -text/html; lynx %s +text/html; lynx %s # This version would convert the text/html to text/plain -text/html; lynx -dump %s; copiousoutput +text/html; lynx -dump %s; copiousoutput # enriched.sh converts text/enriched to text/html and then uses # lynx -dump to convert it to text/plain -text/enriched; enriched.sh ; copiousoutput +text/enriched; enriched.sh ; copiousoutput # I use enscript to print text in two columns to a page -text/*; more %s; print=enscript -2Gr %s +text/*; more %s; print=enscript -2Gr %s # Netscape adds a flag to tell itself to view jpegs internally image/jpeg;xv %s; x-mozilla-flags=internal @@ -2080,7 +2145,7 @@ image/jpeg;xv %s; x-mozilla-flags=internal # In addition, this uses the \ to extend the line and set my editor # for images image/*;xv %s; test=RunningX; \ - edit=xpaint %s + edit=xpaint %s # Convert images to text using the netpbm tools image/*; (anytopnm %s | pnmscale -xysize 80 46 | ppmtopgm | pgmtopbm | @@ -2119,6 +2184,7 @@ application/x-gunzip; gzcat; copiousoutput application/x-tar-gz; gunzip -c %s | tar -tf - ; copiousoutput application/postscript; ps2ascii %s; copiousoutput </verb></tscreen> + <sect1>MIME Multipart/Alternative<label id="alternative_order"> <p> Mutt has some heuristics for determining which attachment of a @@ -2144,24 +2210,24 @@ mailbox. However, it is possible to read other mailboxes and to send messages from the command line as well. <tscreen><verb> --a attach a file to a message --c specify a carbon-copy (Cc) address --e specify a config command to be run after initilization files are read --F specify an alternate file to read initialization commands --f specify a mailbox to load --h print help on command line options --H specify a draft file from which to read a header and body --i specify a file to include in a message composition --n do not read the system Muttrc --m specify a default mailbox type --p recall a postponed message --R open mailbox in read-only mode --s specify a subject (enclose in quotes if it contains spaces) --v show version number and compile-time definitions --x simulate the mailx(1) compose mode --y show a menu containing the files specified by the mailboxes command --z exit immediately if there are no messages in the mailbox --Z open the first folder with new message,exit immediately if none +-a attach a file to a message +-c specify a carbon-copy (Cc) address +-e specify a config command to be run after initilization files are read +-F specify an alternate file to read initialization commands +-f specify a mailbox to load +-h print help on command line options +-H specify a draft file from which to read a header and body +-i specify a file to include in a message composition +-n do not read the system Muttrc +-m specify a default mailbox type +-p recall a postponed message +-R open mailbox in read-only mode +-s specify a subject (enclose in quotes if it contains spaces) +-v show version number and compile-time definitions +-x simulate the mailx(1) compose mode +-y show a menu containing the files specified by the mailboxes command +-z exit immediately if there are no messages in the mailbox +-Z open the first folder with new message,exit immediately if none </verb></tscreen> To read messages in a mailbox @@ -2208,6 +2274,8 @@ The following are the commands understood by mutt. <item> <tt><ref id="hdr_order" name="hdr_order"></tt> <em/header/ [ <em/header/ ... ] <item> +<tt><ref id="hdr_order" name="unhdr_order"></tt> <em/header/ [ <em/header/ ... ] +<item> <tt><ref id="lists" name="lists"></tt> <em/address/ [ <em/address/ ... ] <item> <tt><ref id="lists" name="unlists"></tt> <em/address/ [ <em/address/ ... ] @@ -2283,10 +2351,10 @@ Specifies the format of the data displayed for the `alias' menu. The following printf(3)-style sequences are available. <verb> -%a alias name -%n index number -%r address which alias expands to -%t character which indicates if the alias is tagged for inclusion (*/ ) +%a alias name +%n index number +%r address which alias expands to +%t character which indicates if the alias is tagged for inclusion (*/ ) </verb> <sect2>allow_8bit @@ -2538,14 +2606,6 @@ Default: value of environment variable $VISUAL, $EDITOR, or &dquot This variable specifies which editor to use when composing messages. -<sect2>empty_to<label id="empty_to"> -<p> -Type: string<newline> -Default: undisclosed-recipients - -Specifies the text Mutt inserts in the <tt/To:/ header of a message you're -sending, if the <tt/To:/ and <tt/Cc:/ fields are empty. - <sect2>escape<label id="escape"> <p> Type: string<newline> @@ -2584,6 +2644,30 @@ Note that if you change this variable from the default value you need to make sure that the assignment occurs <em/before/ you use `+' or `=' for any other variables since expansion takes place during the `set' command. +<sect2>folder_format<label id="folder_format"> +<p> +Type: format string<newline> +Default: &dquot;%N %F %2l %-8.8u %-8.8g %8s %d %f&dquot; + +This variable allows you to customize the file browser display to +your personal taste. This string is similar to <ref id="index_format" +name="$index_format">, but has its own set of printf()-like +sequences: + +<tscreen><verb> +%d date/time folder was last modified +%f filename +%F file permissions +%g group name (or numeric gid, if missing) +%l number of hard links +%N N if folder has new mail, blank otherwise +%s size in bytes +%u owner name (or numeric uid, if missing) + +%>X right justify the rest of the string and pad with character "X" +%|X pad to the end of the line with character "X" +</verb></tscreen> + <sect2>followup_to<label id="followup_to"> <p> Type: boolean<newline> @@ -2625,7 +2709,7 @@ used instead. <sect2>forward_format<label id="forward_format"> <p> Type: format string<newline> -Default: "[%a: %s]" +Default: &dquot;[%a: %s]&dquot This variable controls the default subject when forwarding a message. It uses the same format sequences as the <ref id="index_format" @@ -2640,61 +2724,6 @@ When <em/set/ forwarded messages included in the main body of the message (when <ref id="mime_forward" name="mime_forward"> is <em/unset/) will be quoted using <ref id="indent_string" name="indent_string">. -<sect2>index_format<label id="index_format"> -<p> -Type: format string<newline> -Default: &dquot;%4C %Z %{%b %d} %-15.15L (%4l) %s&dquot; - -This variable allows you to customize the message index display to your -personal taste. - -``Format strings'' are similar to the strings used in the ``C'' function -<tt/printf/ to format output (see the man page for more detail). The -following sequences are defined in Mutt: - -<tscreen><verb> -%a address of the author -%b filename of the original message folder (think mailBox) -%B the list to which the letter was sent, or else the folder name (%b). -%c number of characters (bytes) in the message -%C current message number -%d date and time of the message in the format specified by - ``date_format'' -%f entire From: line (address + real name) -%F author name, or recipient name if the message is from you -%i message-id of the current message -%l number of lines in the message -%L list-from function -%m total number of message in the mailbox -%N message score -%n author's real name (or address if missing) -%O (_O_riginal save folder) Where mutt would formerly have stashed the - message: list name or recipient name if no list -%s subject of the message -%S status of the message (N/D/d/!/*/r) -%t `to:' field (recipients) -%T the appropriate character from the $to_chars string -%u user (login) name of the author -%Z message status flags - -%{fmt} the date and time of the message is converted to sender's - time zone, and ``fmt'' is expanded by the system call - ``strftime''; a leading bang disables locales -%[fmt] the date and time of the message is converted to the local - time zone, and ``fmt'' is expanded by the system call - ``strftime''; a leading bang disables locales -%(fmt) the local date and time when the message was received. - ``fmt'' is expanded by the system call ``strftime''; - a leading bang disables locales -%<fmt> the current local time. ``fmt'' is expanded by the system - call ``strftime''; a leading bang disables locales. - -%>X right justify the rest of the string and pad with character "X" -%|X pad to the end of the line with character "X" -</verb></tscreen> - -See also: <ref id="to_chars" name="$to_chars">. - <sect2>hdrs<label id="hdrs"> <p> Type: boolean<newline> @@ -2727,6 +2756,17 @@ may not be updated if a binding is changed while Mutt is running. Since this variable is primarily aimed at new users, neither of these should present a major problem. +<sect2>hidden_host<label id="hidden_host"> +<p> +Type: boolean<newline> +Default: unset + +When set, mutt will skip the host name part of <ref +id="hostname" name="hostname"> variable when adding the +domain part to addresses. This variable does not affect +the generation, and it will not lead to the cut-off of +first-level domains. + <sect2>history<label id="history"> <p> Type: number<newline> @@ -2758,6 +2798,32 @@ to the list, and will ignore this field. To direct a response to the mailing list when this option is set, use the <em/list-reply/ function; <em/group-reply/ will reply to both the sender and the list. +<sect2>imap_checkinterval<label id="imap_checkinterval"> +<p> +Type: number<newline> +Default: 0 + +This variable configures how often (in seconds) IMAP should look for +new mail. + +<sect2>imap_pass<label id="imap_pass"> +<p> +Type: string<newline> +Default: unset + +Specifies the password for your IMAP account. If unset, Mutt will prompt you +for your password when you invoke the fetch-mail function. <bf/Warning/: +you should only use this option when you are on a fairly secure machine, +because the superuser can read your muttrc even if you are the only one who +can read the file. + +<sect2>imap_user<label id="imap_user"> +<p> +Type: string<newline> +Default: login name on local system + +Your login name on the IMAP server. + <sect2>in_reply_to <p> Type: format string<newline> @@ -2779,12 +2845,67 @@ included in your reply. <sect2>indent_string<label id="indent_string"> <p> Type: format string<newline> -Default: "> " +Default: &dquot;> &dquot; Specifies the string to prepend to each line of text quoted in a message to which you are replying. You are strongly encouraged not to change this value, as it tends to agitate the more fanatical netizens. +<sect2>index_format<label id="index_format"> +<p> +Type: format string<newline> +Default: &dquot;%4C %Z %{%b %d} %-15.15L (%4l) %s&dquot; + +This variable allows you to customize the message index display to your +personal taste. + +``Format strings'' are similar to the strings used in the ``C'' function +<tt/printf/ to format output (see the man page for more detail). The +following sequences are defined in Mutt: + +<tscreen><verb> +%a address of the author +%b filename of the original message folder (think mailBox) +%B the list to which the letter was sent, or else the folder name (%b). +%c number of characters (bytes) in the message +%C current message number +%d date and time of the message in the format specified by + ``date_format'' +%f entire From: line (address + real name) +%F author name, or recipient name if the message is from you +%i message-id of the current message +%l number of lines in the message +%L list-from function +%m total number of message in the mailbox +%N message score +%n author's real name (or address if missing) +%O (_O_riginal save folder) Where mutt would formerly have stashed the + message: list name or recipient name if no list +%s subject of the message +%S status of the message (N/D/d/!/*/r) +%t `to:' field (recipients) +%T the appropriate character from the $to_chars string +%u user (login) name of the author +%Z message status flags + +%{fmt} the date and time of the message is converted to sender's + time zone, and ``fmt'' is expanded by the system call + ``strftime''; a leading bang disables locales +%[fmt] the date and time of the message is converted to the local + time zone, and ``fmt'' is expanded by the system call + ``strftime''; a leading bang disables locales +%(fmt) the local date and time when the message was received. + ``fmt'' is expanded by the system call ``strftime''; + a leading bang disables locales +%<fmt> the current local time. ``fmt'' is expanded by the system + call ``strftime''; a leading bang disables locales. + +%>X right justify the rest of the string and pad with character "X" +%|X pad to the end of the line with character "X" +</verb></tscreen> + +See also: <ref id="to_chars" name="$to_chars">. + <sect2>ispell<label id="ispell"> <p> Type: string<newline> @@ -2808,9 +2929,17 @@ Default: $MAILCAPS or ˜/.mailcap:/usr/local/share/mailcap:/etc/mail This variable specifies which files to consult when attempting to display MIME bodies not directly supported by Mutt. +<sect2>mail_check<label id="mail_check"> +<p> +Type: number<newline> +Default: 5 + +This variable configures how often (in seconds) mutt should look for +new mail. + <sect2>mark_old <p> -Type: Boolean<newline> +Type: boolean<newline> Default: set Controls whether or not Mutt makes the distinction between <em/new/ messages @@ -2832,10 +2961,15 @@ the <ref id="smart_wrap" name="$smart_wrap"> variable. <sect2>mask<label id="mask"> <p> Type: string<newline> -Default: "^(\.\.$|[^.])" +Default: "!^\.[^.]" + +A regular expression used in the file browser, optionally preceded by +the <em/not/ operator ``!''. Files whose names don't match this mask +will not be shown. The match is always case-sensitive. -A regular expression used in the file browser. Files whose names don't -match this mask will not be shown. +<bf/Note:/ if you need ``!'' at the beginning of the regular expression +you should enclose it in paranthesis, in order to distinguish it from +the logical <em/not/ operator for the expression. <sect2>mbox<label id="mbox"> <p> @@ -2875,7 +3009,7 @@ avoid many redraws). <sect2>meta_key<label id="meta_key"> <p> -Type: Boolean<newline> +Type: boolean<newline> Default: unset If set, forces Mutt to interpret keystrokes with the high bit (bit 8) set as @@ -2887,13 +3021,14 @@ which is the ASCII character ``x''. <sect2>mime_forward<label id="mime_forward"> <p> -Type: boolean<newline> +Type: quadoption<newline> Default: unset When set, the message you are forwarding will be attached as a separate MIME part instead of included in the main body of the message. This is useful for forwarding MIME messages so the receiver can properly view the -message as it was delivered to you. +message as it was delivered to you. If you like to switch between MIME +and not MIME from mail to mail, set this variable to ask-no or ask-yes. Also see <ref id="forward_decode" name="forward_decode"> and <ref id="mime_forward_decode" @@ -2920,8 +3055,8 @@ result of a <ref id="mbox-hook" name="mbox-hook"> command. <sect2>message_format<label id="message_format"> <p> -Type: string<newline> -Default: &dquot%s&dquot; +Type: format string<newline> +Default: &dquot;%s&dquot; This is the string displayed in the <ref id="attach_menu" name="attachment"> menu for attachments of type <em>message/rfc822</em>. @@ -3006,11 +3141,13 @@ when signing is not required or encryption is requested as well. <sect2>pgp_default_version<label id="pgp_default_version"> <p> Type: string<newline> -Default: pgp2 (or pgp5, if PGP 2.* is not installed) +Default: pgp2 (or pgp5, if PGP 2.* is not installed, or gpg, if none +of them is installed) -Set this to pgp2 (PGP 2.*), or pgp5 (PGP 5.*) depending on the -version, you are using primary. This variable is directly used, but it -is the default for the variables <ref id="pgp_receive_version" +Set this to pgp2 (PGP 2.*), pgp5 (PGP 5.*), or gpg (GNU privacy guard), +depending on the version that you primarily use. This variable is +not directly used, but it is the default for the variables <ref +id="pgp_receive_version" name="$pgp_receive_version">, <ref id="pgp_send_version" name="$pgp_send_version">, and <ref id="pgp_key_version" @@ -3023,18 +3160,26 @@ Default: set If set, the PGP <em/+encrypttoself/ flag is used when encrypting messages. +<sect2>pgp_gpg<label id="pgp_gpg"> +<p> +Type: string<newline> +Default: system dependent + +This variable allows you to override the compile time definition of +where the gpg (GNU Privacy Guard) binary resides on your system. + <sect2>pgp_key_version<label id="pgp_key_version"> <p> Type: string<newline> Default: ``default'' -This variable determines, which PGP version used for key ring +This variable determines which PGP version is used for key ring operations like extracting keys from messages and extracting keys from your keyring. If you set this to default, the default defined in <ref id="pgp_default_version" name="$pgp_default_version"> is used. Set this to -pgp2 (PGP 2.*), or pgp5 (PGP 5.*) if you want a different PGP version -for key operations. +pgp2 (PGP 2.*), pgp5 (PGP 5.*), or gpg (GNU privacy guard) if you want +to use a different PGP version for key operations. <sect2>pgp_long_ids<label id="pgp_long_ids"> <p> @@ -3048,12 +3193,12 @@ If set, use 64 bit PGP key IDs. Unset uses the normal 32 bit Key IDs. Type: string<newline> Default: ``default'' -This variable determines, which PGP version used for decrypting +This variable determines which PGP version is used for decrypting messages and verifying signatures. If you set this to default, the default defined in <ref id="pgp_default_version" name="$pgp_default_version"> will be used. Set -this to pgp2 (PGP 2.*), or pgp5 (PGP 5.*) if you want a different PGP -version for receiving operations. +this to pgp2 (PGP 2.*), pgp5 (PGP 5.*), or gpg (GNU privacy guard) if +you want to use a different PGP version for receiving operations. <sect2>pgp_replyencrypt<label id="pgp_replyencrypt"> <p> @@ -3077,12 +3222,12 @@ signed! Type: string<newline> Default: ``default'' -This variable determines, which PGP version used for composing new +This variable determines which PGP version is used for composing new messages like encrypting and signing. If you set this to default, the default defined in <ref id="pgp_default_version" name="$pgp_default_version"> will be used. Set -this to pgp2 (PGP 2.*), or pgp5 (PGP 5.*) if you want a different PGP -version for sending operations. +this to pgp2 (PGP 2.*), pgp5 (PGP 5.*), or gpg (GNU privacy guard) if +you want to use a different PGP version for sending operations. <sect2>pgp_sign_as<label id="pgp_sign_as"> <p> @@ -3247,7 +3392,7 @@ The name or address of your POP3 server. Type: string<newline> Default: unset -Specifies the password for you POP account. If unset, Mutt will prompt you +Specifies the password for your POP account. If unset, Mutt will prompt you for your password when you invoke the fetch-mail function. <bf/Warning/: you should only use this option when you are on a fairly secure machine, because the superuser can read your muttrc even if you are the only one who @@ -3517,8 +3662,8 @@ Type: string<newline> Default: /usr/lib/sendmail -oi -oem Specifies the program and arguments used to deliver mail sent by Mutt. -Mutt expects that the specified program will read the message header for -recipients. +Mutt expects that the specified program interprets +additional arguments as recipient addresses. <sect2>sendmail_wait<label id="sendmail_wait"> <p> @@ -3531,9 +3676,9 @@ the background. Mutt interprets the value of this variable as follows: <verb> ->0 number of seconds to wait for sendmail to finish before continuing -0 wait forever for sendmail to finish -<0 always put sendmail in the background without waiting +>0 number of seconds to wait for sendmail to finish before continuing +0 wait forever for sendmail to finish +<0 always put sendmail in the background without waiting </verb> Note that if you specify a value other than 0, the output of the child @@ -3575,7 +3720,7 @@ Default: &dquot;˜f %s | ˜s %s&dquot; Specifies how Mutt should expand a simple search into a real search pattern. A simple search is one that does not contain any of the <tt/˜/ -operators. See <ref id="searching" name="searching"> for more information +operators. See <ref id="pattern" name="patterns"> for more information on search patterns. For example, if you simply type <tt/joe/ at a search or limit prompt, Mutt @@ -3623,9 +3768,9 @@ Default: alias Specifies how the entries in the `alias' menu are sorted. The following are legal values: <verb> -alias sort alphabetically by alias name -address sort alphabetically by email address -unsorted leave in order specified in .muttrc +alias sort alphabetically by alias name +address sort alphabetically by email address +unsorted leave in order specified in .muttrc </verb> <sect2>sort_aux<label id="sort_aux"> @@ -3710,29 +3855,29 @@ name="$index_format">, but has its own set of printf()-like sequences: <tscreen><verb> -%b number of mailboxes with new mail * -%d number of deleted messages * -%h local hostname -%f the full pathname of the current mailbox -%F number of flagged messages * -%l size (in bytes) of the current mailbox * -%L size (in bytes) of the messages shown (i.e., which match the current limit) * -%m the number of messages in the mailbox * -%M the number of messages shown (i.e., which match the current limit) * -%n number of new messages in the mailbox * -%o number of old unread messages -%p number of postponed messages * -%P percentage of the way through the index -%r modified/read-only/won't-write indicator, according to $status_chars -%s current sorting mode ($sort) -%S current aux sorting method ($sort_aux) -%t number of tagged messages * -%u number of unread messages * -%v Mutt version string -%V currently active limit pattern, if any * - -%>X right justify the rest of the string and pad with "X" -%|X pad to the end of the line with "X" +%b number of mailboxes with new mail * +%d number of deleted messages * +%h local hostname +%f the full pathname of the current mailbox +%F number of flagged messages * +%l size (in bytes) of the current mailbox * +%L size (in bytes) of the messages shown (i.e., which match the current limit) * +%m the number of messages in the mailbox * +%M the number of messages shown (i.e., which match the current limit) * +%n number of new messages in the mailbox * +%o number of old unread messages +%p number of postponed messages * +%P percentage of the way through the index +%r modified/read-only/won't-write indicator, according to $status_chars +%s current sorting mode ($sort) +%S current aux sorting method ($sort_aux) +%t number of tagged messages * +%u number of unread messages * +%v Mutt version string +%V currently active limit pattern, if any * + +%>X right justify the rest of the string and pad with "X" +%|X pad to the end of the line with "X" * = can be optionally printed if nonzero </verb></tscreen> @@ -3744,7 +3889,7 @@ meaningful. To optionally print a string based upon one of the above sequences, the following construct is used <tscreen><verb> - %?<sequence_char>?<optional_string>? + %?<sequence_char>?<optional_string>? </verb></tscreen> where <em/sequence_char/ is a character from the table above, and @@ -3757,7 +3902,15 @@ Here is an example illustrating how to optionally print the number of new messages in a mailbox: <tscreen><verb> - %?n?%n new messages.? + %?n?%n new messages.? +</verb></tscreen> + +Additionally you can switch between two strings, the first one, if a +value is zero, the second one, if the value is nonzero, by using the +following construct: + +<tscreen><verb> + %?<sequence_char>?<if_string>&<else_string>? </verb></tscreen> <sect2>status_on_top<label id="status_on_top"> @@ -3797,7 +3950,7 @@ Type: boolean<newline> Default: unset Affects the <em/˜b/ and <em/˜h/ search operations described -in section <ref id="searching" name="Searching"> above. If set, the +in section <ref id="pattern" name="patterns"> above. If set, the headers and attachments of messages to be searched are decoded before searching. If unset, messages are searched as they appear in the folder. @@ -3944,6 +4097,15 @@ a single message will be displayed before writing a mailbox. Also see the <ref id="read_inc" name="$read_inc"> variable. +<sect2>write_bcc<label id="write_bcc"> +<p> +Type: boolean<newline> +Default: set + +Controls whether mutt writes out the Bcc header when +preparing messages to be sent. Exim users may wish to use +this. + <sect1>Functions<label id="functions"> <p> The following is the list of available functions listed by the mapping @@ -4119,7 +4281,7 @@ search-reverse ESC / search backwards for a regular expression search-toggle \ toggle search pattern coloring shell-escape ! invoke a command in a subshell show-version V show the Mutt version number and date -skip-quoted S skip beyond quoted text +skip-quoted S skip beyond quoted text tag-message t tag a message toggle-quoted T toggle display of quoted text top ^ jump to the top of the message @@ -4253,7 +4415,7 @@ quote-char ^V quote the next typed key <sect1>Acknowledgements <p> -Kari Hurrta +Kari Hurtta <htmlurl url="mailto:kari.hurtta@fmi.fi" name="<kari.hurtta@fmi.fi>"> co-developed the original MIME parsing code back in the ELM-ME days. diff --git a/doc/manual.txt b/doc/manual.txt index 9dfa57e2..04d985a9 100644 --- a/doc/manual.txt +++ b/doc/manual.txt @@ -1,6 +1,6 @@ The Mutt E-Mail Client by Michael Elkins <me@cs.hmc.edu> - v0.92.2, 23 April 1998 + v0.94.2, 31 July 1998 ``All mail clients suck. This one just sucks less.'' -me, circa 1995 @@ -15,21 +15,20 @@ 11..11.. MMuutttt HHoommee PPaaggee - http://www.cs.hmc.edu/~me/mutt/index.html + http://www.mutt.org/ 11..22.. MMaaiilliinngg LLiissttss To subscribe to one of the following mailing lists, send a message - with the word _s_u_b_s_c_r_i_b_e in the subject to list-name_- - _r_e_q_u_e_s_t@cs.hmc.edu. + with the word _s_u_b_s_c_r_i_b_e in the subject to list-name_-_r_e_q_u_e_s_t@mutt.org. - +o mutt-announce@cs.hmc.edu -- low traffic list for announcements + +o mutt-announce@mutt.org -- low traffic list for announcements - +o mutt-users@cs.hmc.edu -- help, bug reports and feature requests + +o mutt-users@mutt.org -- help, bug reports and feature requests - +o mutt-dev@cs.hmc.edu -- development mailing list + +o mutt-dev@mutt.org -- development mailing list NNoottee:: all messages posted to _m_u_t_t_-_a_n_n_o_u_n_c_e are automatically forwarded to _m_u_t_t_-_u_s_e_r_s, so you do not need to be subscribed to both lists. @@ -38,7 +37,7 @@ 11..33.. SSooffttwwaarree DDiissttrriibbuuttiioonn SSiitteess - +o ftp://ftp.cs.hmc.edu/pub/me/mutt/ + +o ftp://ftp.guug.de/pub/mutt/ 11..44.. IIRRCC @@ -65,7 +64,6 @@ WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. @@ -130,6 +128,8 @@ + + ^A or <Home> bol move to the start of the line ^B or <Left> backward-char move back one char ^D or <Delete> delete-char delete the char under the cursor @@ -292,7 +292,7 @@ n display the next message ? show keybindings / search for a regular expression (pattern) - \ toggle search pattern coloring + \ toggle search pattern coloring @@ -612,7 +612,7 @@ commands are used, they must be separated by a semicolon (;). - set realname='Mutt user' ; ignore x- + set realname='Mutt user' ; ignore x- @@ -673,8 +673,18 @@ oriented, only the first line of output from the Unix command will be substituted. - For a complete list of the commands understood by mutt, see the - ``command reference''. + UNIX environments can be accessed like the way it is done in shells + like sh and bash: Prepend the name of the environment by a + ``$dollar;''. For example, + + + set record=+sent_on_$HOSTNAME + + + + + The commands understood by mutt are explained in the next paragraphs. + For a complete list, see the ``command reference''. 33..22.. DDeeffiinniinngg//UUssiinngg aalliiaasseess @@ -714,7 +724,6 @@ that Mutt will happily append aliases to any file, but in order for the new aliases to take effect you need to explicitly ``source'' this file too. - For example: @@ -724,6 +733,8 @@ set alias_file=~/.mail_aliases + + To use aliases, you merely use the alias at any place in mutt where mutt prompts for addresses, such as the _T_o_: or _C_c_: prompt. You can also enter aliases in your editor at the appropriate headers if you @@ -770,8 +781,6 @@ +o pgp - +o url - _k_e_y is the key (or key sequence) you wish to bind. To specify a control character, use the sequence _\_C_x, where _x is the letter of the control character (for example, to specify control-A use ``\Ca''). @@ -780,34 +789,29 @@ key as a three digit octal number prefixed with a ``\'' (for example _\_1_7_7 is equivalent to _\_c_?). - In addition, _k_e_y may consist of: - - - - - + In addition, _k_e_y may consist of: - \t tab - \r carriage return - \n newline - \e escape - up up arrow - down down arrow - left left arrow - right right arrow - pageup Page Up - pagedown Page Down - backspace Backspace - delete Delete - insert Insert - enter Enter - home Home - end End - f1 function key 1 - f10 function key 10 + \t tab + \r carriage return + \n newline + \e escape + <up> up arrow + <down> down arrow + <left> left arrow + <right> right arrow + <pageup> Page Up + <pagedown> Page Down + <backspace> Backspace + <delete> Delete + <insert> Insert + <enter> Enter + <home> Home + <end> End + f1 function key 1 + f10 function key 10 @@ -822,7 +826,7 @@ 33..44.. SSeettttiinngg vvaarriiaabblleess bbaasseedd uuppoonn mmaaiillbbooxx - Usage: folder-hook [!]_p_a_t_t_e_r_n _c_o_m_m_a_n_d + Usage: folder-hook [!]_r_e_g_e_x_p _c_o_m_m_a_n_d It is often desirable to change settings based on which mailbox you are reading. The folder-hook command provides a method by which you @@ -852,13 +856,15 @@ pattern ``.'': + folder-hook . set sort=date-sent + + - folder-hook . set sort=date-sent 33..55.. KKeeyybbooaarrdd mmaaccrrooss - Usage: macro _m_e_n_u _k_e_y _s_e_q_u_e_n_c_e + Usage: macro _m_e_n_u _k_e_y _s_e_q_u_e_n_c_e [ _d_e_s_c_r_i_p_t_i_o_n ] Macros are useful when you would like a single key to perform a series of actions. When you press _k_e_y in menu _m_e_n_u, Mutt will behave as if @@ -871,6 +877,9 @@ also be specified as _^_x. In order to get a caret (``^'') you need to use _^_^. + Optionally you can specify a descriptive text, which is shown in the + help screens. + NNoottee:: Macro definitions (if any) listed in the help screen(s), are silently truncated at the screen width, and are not wrapped. @@ -912,6 +921,7 @@ +o message (informational messages) + +o normal +o quoted (text matching ``$quote_regexp'' in the body of a message) @@ -988,6 +998,7 @@ If your terminal does not support color, it is still possible change the video attributes through the use of the ``mono'' command: + Usage: mono _<_o_b_j_e_c_t_> _<_a_t_t_r_i_b_u_t_e_> [ _r_e_g_e_x_p ] where _a_t_t_r_i_b_u_t_e is one of the following: @@ -1046,14 +1057,13 @@ mailing lists. It is important to note that you should nneevveerr specify the domain name - ( the part after the ``@'') with the lists command. You should only + (the part after the ``@'') with the lists command. You should only specify the ``mailbox'' portion of the address (the part before the ``@''). For example, if you've subscribed to the Mutt mailing list, - you will receive mail addressed to _m_u_t_t_-_u_s_e_r_s_@_c_s_._h_m_c_._e_d_u. So, to tell + you will receive mail addressed to _m_u_t_t_-_u_s_e_r_s_@_m_u_t_t_._o_r_g. So, to tell Mutt that this is a mailing list, you would add ``lists mutt-users'' to your initialization file. - The ``unlists'' command is to remove a token from the list of mailing- lists. Use ``unlists *'' to remove all tokens. @@ -1110,7 +1120,6 @@ The ``my_hdr'' command allows you to create your own header fields which will be added to every message you send. - For example, if you would like to add an ``Organization:'' header field to all of your outgoing messages, you can put the command @@ -1146,6 +1155,10 @@ With this command, you can specify an order in which mutt will attempt to present headers to you when viewing messages. + ``unhdr_order *'' will clear all previous headers from the order list, + thus removing the header order effects set by the system-wide startup + file. + hdr_order From Date: From: To: Cc: Subject: @@ -1156,7 +1169,7 @@ 33..1133.. SSppeecciiffyy ddeeffaauulltt ssaavvee ffiilleennaammee - Usage: save-hook [!]_r_e_g_e_x_p _f_i_l_e_n_a_m_e + Usage: save-hook [!]_p_a_t_t_e_r_n _f_i_l_e_n_a_m_e This command is used to override the default filename used when saving messages. _f_i_l_e_n_a_m_e will be used as the default filename if the @@ -1164,7 +1177,7 @@ and the message is addressed _t_o_: something matching _r_e_g_e_x_p. See ``matching messages'' for information on the exact format of - _r_e_g_e_x_p. + _p_a_t_t_e_r_n. Examples: @@ -1173,15 +1186,12 @@ save-hook me@(turing\\.)?cs\\.hmc\\.edu$ +elkins save-hook aol\\.com$ +spam - - - Also see the ``fcc-save-hook'' command. 33..1144.. SSppeecciiffyy ddeeffaauulltt FFcccc:: mmaaiillbbooxx wwhheenn ccoommppoossiinngg - Usage: fcc-hook [!]_r_e_g_e_x_p _m_a_i_l_b_o_x + Usage: fcc-hook [!]_p_a_t_t_e_r_n _m_a_i_l_b_o_x This command is used to save outgoing mail in a mailbox other than ``$record''. Mutt searches the initial list of message recipients for @@ -1190,7 +1200,7 @@ ``$record'' mailbox. See ``matching messages'' for information on the exact format of - _r_e_g_e_x_p. + _p_a_t_t_e_r_n. Example: fcc-hook aol.com$ +spammers @@ -1201,7 +1211,7 @@ 33..1155.. SSppeecciiffyy ddeeffaauulltt ssaavvee ffiilleennaammee aanndd ddeeffaauulltt FFcccc:: mmaaiillbbooxx aatt oonnccee - Usage: fcc-save-hook [!]_r_e_g_e_x_p _m_a_i_l_b_o_x + Usage: fcc-save-hook [!]_p_a_t_t_e_r_n _m_a_i_l_b_o_x This command is a shortcut, equivalent to doing both a ``fcc-hook'' and a ``save-hook'' with its arguments. @@ -1209,16 +1219,16 @@ 33..1166.. CChhaannggee sseettttiinnggss bbaasseedd uuppoonn mmeessssaaggee rreecciippiieennttss - Usage: send-hook [!]_r_e_g_e_x_p _c_o_m_m_a_n_d + Usage: send-hook [!]_p_a_t_t_e_r_n _c_o_m_m_a_n_d This command can be used to execute arbitrary configuration commands - based upon recipients of the message. _r_e_g_e_x_p is a regular expression + based upon recipients of the message. _p_a_t_t_e_r_n is a regular expression matching the desired address. _c_o_m_m_a_n_d is executed when _r_e_g_e_x_p matches recipients of the message. When multiple matches occur, commands are executed in the order they are specified in the muttrc. See ``matching messages'' for information on the exact format of - _r_e_g_e_x_p. + _p_a_t_t_e_r_n. Example: send-hook mutt "set mime_forward signature=''" @@ -1232,7 +1242,20 @@ message will NOT cause any send-hook to be executed. - 33..1177.. AAddddiinngg kkeeyy sseeqquueenncceess ttoo tthhee kkeeyybbooaarrdd bbuuffffeerr + 33..1177.. CChhoooossiinngg tthhee PPGGPP kkeeyy ooff tthhee rreecciippiieenntt + + Usage: pgp-hook _p_a_t_t_e_r_n _k_e_y_i_d + + When encrypting messages with PGP, you may want to associate a certain + PGP key with a given e-mail address automatically, either because the + recipient's public key can't be deduced from the destination address, + or because, for some reasons, you need to override the key Mutt would + normally use. The pgp-hook command provides a method by which you can + specify the ID of the public key to be used when encrypting messages + to a certain recipient. + + + 33..1188.. AAddddiinngg kkeeyy sseeqquueenncceess ttoo tthhee kkeeyybbooaarrdd bbuuffffeerr Usage: push _s_t_r_i_n_g @@ -1241,13 +1264,13 @@ entering certain folders. - 33..1188.. MMeessssaaggee SSccoorriinngg + 33..1199.. MMeessssaaggee SSccoorriinngg Usage: score _p_a_t_t_e_r_n _v_a_l_u_e Usage: unscore _p_a_t_t_e_r_n [ _p_a_t_t_e_r_n ... ] The score commands adds _v_a_l_u_e to a message's score if _p_a_t_t_e_r_n matches - it. _p_a_t_t_e_r_n is a string in the format described in the ``searching'' + it. _p_a_t_t_e_r_n is a string in the format described in the ``patterns'' section. _v_a_l_u_e is a positive or negative integer. A message's final score is the sum total of all matching score entries. However, you may optionally prefix _v_a_l_u_e with an equal sign (=) to cause evaluation @@ -1260,7 +1283,7 @@ the list of all score entries. - 33..1199.. SSeettttiinngg vvaarriiaabblleess + 33..2200.. SSeettttiinngg vvaarriiaabblleess Usage: set [no|inv]_v_a_r_i_a_b_l_e[=_v_a_l_u_e] [ _v_a_r_i_a_b_l_e ... ] Usage: toggle _v_a_r_i_a_b_l_e [_v_a_r_i_a_b_l_e ... ] @@ -1318,7 +1341,9 @@ With the reset command there exists the special variable ``all'', which allows you to reset all variables to their system defaults. - 33..2200.. RReeaaddiinngg iinniittiiaalliizzaattiioonn ccoommmmaannddss ffrroomm aannootthheerr ffiillee + + + 33..2211.. RReeaaddiinngg iinniittiiaalliizzaattiioonn ccoommmmaannddss ffrroomm aannootthheerr ffiillee Usage: source _f_i_l_e_n_a_m_e @@ -1332,27 +1357,23 @@ If the filename ends with a vertical bar (|), then _f_i_l_e_n_a_m_e is considered to be an executable program from which to read input (eg. - source ~bin/myscript|/. + source ~bin/myscript|/). 44.. AAddvvaanncceedd UUssaaggee - 44..11.. SSeeaarrcchhiinngg aanndd RReegguullaarr EExxpprreessssiioonnss + 44..11.. RReegguullaarr EExxpprreessssiioonnss - All text patterns for searching and matching in Mutt must be specified - as regular expressions (regexp) in the ``POSIX extended'' syntax - (which is more or less the syntax used by egrep and GNU awk). For - your convenience, we have included below a brief description of this - syntax. + All string patterns in Mutt including those in more complex + ``patterns'' must be specified using regular expressions (regexp) in + the ``POSIX extended'' syntax (which is more or less the syntax used + by egrep and GNU awk). For your convenience, we have included below a + brief description of this syntax. The search is case sensitive if the pattern contains at least one upper case letter, and case insensitive otherwise. Note that ``\'' must be quoted if used for a regular expression in an initialization - command: ``\\''. For more information, see the section on - ``searching'' below. - - - 44..11..11.. RReegguullaarr EExxpprreessssiioonnss + command: ``\\''. A regular expression is a pattern that describes a set of strings. Regular expressions are constructed analogously to arithmetic @@ -1384,6 +1405,7 @@ consist of ``[:'', a keyword denoting the class, and ``:]''. The following classes are defined by the POSIX standard: + [[::aallnnuumm::]] Alphanumeric characters. @@ -1450,6 +1472,7 @@ and ``=]''. For example, the name ``e'' might be used to represent all of ``e'' ``e'' and ``e''. In this case, [[[[==ee==]]]] is a regexp that matches any of ``e'', ``e'' and ``e''. + A regular expression matching a single character may be followed by one of several repetition operators: @@ -1492,6 +1515,7 @@ \\yy Matches the empty string at either the beginning or the end of a word. + \\BB Matches the empty string within a word. \\<< Matches the empty string at the beginning of a word. @@ -1512,7 +1536,7 @@ systems. - 44..11..22.. SSeeaarrcchhiinngg + 44..22.. PPaatttteerrnnss Many of Mutt's commands allow you to specify a pattern to match (limit, tag-pattern, delete-pattern, etc.). There are several ways to @@ -1521,21 +1545,22 @@ ~A all messages - ~b PATTERN messages which contain PATTERN in the message body + ~b EXPR messages which contain EXPR in the message body + ~B EXPR messages which contain EXPR in the whole message ~c USER messages carbon-copied to USER - ~C PATTERN message is either to: or cc: PATTERN + ~C EXPR message is either to: or cc: EXPR ~D deleted messages ~d [MIN]-[MAX] messages with ``date-sent'' in a Date range ~E expired messages - ~e PATTERN message which contains PATTERN in the ``Sender'' field + ~e EXPR message which contains EXPR in the ``Sender'' field ~F flagged messages ~f USER messages originating from USER - ~h PATTERN messages which contain PATTERN in the message header + ~h EXPR messages which contain EXPR in the message header ~i ID message which match ID in the ``Message-ID'' field - ~L PATTERN message is either originated or received by PATTERN + ~L EXPR message is either originated or received by EXPR ~l message is addressed to a known mailing list - ~m [MIN]-[MAX] message in the range MIN to MAX - ~n [MIN]-[MAX] messages with a score in the range MIN to MAX + ~m [MIN]-[MAX] message in the range MIN to MAX *) + ~n [MIN]-[MAX] messages with a score in the range MIN to MAX *) ~N new messages ~O old messages ~p message is addressed to you (consults $alternates) @@ -1548,15 +1573,19 @@ ~T tagged messages ~t USER messages addressed to USER ~U unread messages - ~x PATTERN messages which contain PATTERN in the `References' field + ~x EXPR messages which contain EXPR in the `References' field + ~z [MIN]-[MAX] messages with a size in the range MIN to MAX *) + + Where EXPR, USER, ID, and SUBJECT are ``regular expressions''. - Where PATTERN, USER, ID, and SUBJECT are ``regular expressions''. + *) The forms <[MAX], >[MIN], [MIN]- and -[MAX] are allowed, too. - 44..11..33.. CCoommpplleexx SSeeaarrcchheess + + 44..22..11.. CCoommpplleexx PPaatttteerrnnss Logical AND is performed by specifying more than one criterion. For @@ -1581,7 +1610,6 @@ +o | -- logical OR operator - +o () -- logical grouping operator Here is an example illustrating a complex search pattern. This @@ -1596,7 +1624,7 @@ - 44..11..44.. SSeeaarrcchhiinngg bbyy DDaattee + 44..22..22.. SSeeaarrcchhiinngg bbyy DDaattee Mutt supports two types of dates, _a_b_s_o_l_u_t_e and _r_e_l_a_t_i_v_e. @@ -1648,7 +1676,9 @@ zone, so unless you change the setting of your ``$index_format'' to include a %[...] format, these are nnoott the dates shown in the main index. - 44..22.. UUssiinngg TTaaggss + + + 44..33.. UUssiinngg TTaaggss Sometimes it is desirable to perform an operation on a group of @@ -1658,7 +1688,7 @@ pattern, use the tag-pattern function, which is bound to ``control-T'' by default. Or you can select individual messages by hand using the ``tag-message'' function, which is bound to ``t'' by default. See - ``searching'' for Mutt's searching syntax. + ``patterns'' for Mutt's pattern matching syntax. Once you have tagged the desired messages, you can use the ``tag- prefix'' operator, which is the ``;'' (semicolon) key by default. @@ -1669,14 +1699,14 @@ ``tag-prefix''. - 44..33.. UUssiinngg HHooookkss + 44..44.. UUssiinngg HHooookkss A _h_o_o_k is a concept borrowed from the EMACS editor which allows you to execute arbitrary commands before performing some operation. For example, you may wish to tailor your configuration based upon which mailbox you are reading, or to whom you are sending mail. In the Mutt - world, a _h_o_o_k consists of a ``regular expression'' along with a - configuration option/command. See + world, a _h_o_o_k consists of a ``regular expression'' or ``pattern'' + along with a configuration option/command. See +o ``folder-hook'' @@ -1693,13 +1723,13 @@ for specific details on each type of _h_o_o_k available. - 44..33..11.. MMeessssaaggee MMaattcchhiinngg iinn HHooookkss + 44..44..11.. MMeessssaaggee MMaattcchhiinngg iinn HHooookkss Hooks that act upon messages (send-hook, save-hook, fcc-hook) are evaluated in a slightly different manner. For the other types of - hooks, a ``regular expression''. But in dealing with messages a finer - grain of control is needed for matching since for different purposes - you want to match different criteria. + hooks, a ``regular expression'' is sufficient. But in dealing with + messages a finer grain of control is needed for matching since for + different purposes you want to match different criteria. Mutt allows the use of the ``search pattern'' language for matching messages in hook commands. This works in exactly the same way as it @@ -1714,6 +1744,8 @@ send-hook '~t ^me@cs\.hmc\.edu$' 'my_hdr From: Mutt User <user@host>' + + which would execute the given command when sending mail to _m_e_@_c_s_._h_m_c_._e_d_u. @@ -1721,12 +1753,12 @@ the full searching language. You can still specify a simple _r_e_g_u_l_a_r _e_x_p_r_e_s_s_i_o_n like the other hooks, in which case Mutt will translate your pattern into the full language, using the translation specified - by the ``$dfault_hook'' variable. The pattern is translated at the + by the ``$default_hook'' variable. The pattern is translated at the time the hook is declared, so the value of ``$dfault_hook'' that is in effect at that time will be used. - 44..44.. EExxtteerrnnaall AAddddrreessss QQuueerriieess + 44..55.. EExxtteerrnnaall AAddddrreessss QQuueerriieess Mutt supports connecting to external directory databases such as LDAP, ph/qi, bbdb, or NIS through a wrapper script which connects to mutt @@ -1747,11 +1779,12 @@ matching addresses, return a non-zero exit code and a one line error message. + An example multiple response output: Searching database ... 20 entries ... 3 matching: - me@cs.hmc.edu Michael Elkins mutt dude + me@cs.hmc.edu Michael Elkins mutt dude blong@fiction.net Brandon Long mutt and more roessler@guug.de Thomas Roessler mutt pgp @@ -1777,10 +1810,7 @@ or more addresses to be added to the prompt. - - - - 44..55.. MMaaiillbbooxx FFoorrmmaattss + 44..66.. MMaaiillbbooxx FFoorrmmaattss Mutt supports reading and writing of four different mailbox formats: mbox, MMDF, MH and Maildir. The mailbox type is autodetected, so @@ -1822,7 +1852,7 @@ locking is needed. - 44..66.. MMaaiillbbooxx SShhoorrttccuuttss + 44..77.. MMaaiillbbooxx SShhoorrttccuuttss There are a number of built in shortcuts which refer to specific mailboxes. These shortcuts can be used anywhere you are prompted for @@ -1841,9 +1871,11 @@ +o = or + -- refers to your ``$folder'' directory + +o @_a_l_i_a_s -- refers to the ``default save folder'' as determined by + the address of the alias - 44..77.. HHaannddlliinngg MMaaiilliinngg LLiissttss + 44..88.. HHaannddlliinngg MMaaiilliinngg LLiissttss Mutt has a few configuration options that make dealing with large @@ -1889,7 +1921,7 @@ delete uninteresting threads and quickly find topics of value. - 44..88.. DDeelliivveerryy SSttaattuuss NNoottiiffiiccaattiioonn ((DDSSNN)) SSuuppppoorrtt + 44..99.. DDeelliivveerryy SSttaattuuss NNoottiiffiiccaattiioonn ((DDSSNN)) SSuuppppoorrtt RFC1894 defines a set of MIME content types for relaying information about the status of electronic mail messages. These can be thought of @@ -1904,7 +1936,7 @@ Refer to the man page on sendmail for more details on DSN. - 44..99.. PPOOPP33 SSuuppppoorrtt ((OOPPTTIIOONNAALL)) + 44..1100.. PPOOPP33 SSuuppppoorrtt ((OOPPTTIIOONNAALL)) If Mutt was compiled with POP3 support (by running the _c_o_n_f_i_g_u_r_e @@ -1924,6 +1956,45 @@ specialized program, such as fetchmail + 44..1111.. IIMMAAPP SSuuppppoorrtt ((OOPPTTIIOONNAALL)) + + + If Mutt was compiled with IMAP support (by running the _c_o_n_f_i_g_u_r_e + script with the _-_-_e_n_a_b_l_e_-_i_m_a_p flag), it has the ability to work with + folders located on a remote imap server. + + You can access the remote inbox by selecting the folder + {imapserver}inbox, where imapserver is the name of the IMAP server and + inbox is the special name for your spool mailbox on the IMAP server. + If you want to access another mail folder at the IMAP server, you + should use {imapserver}path/to/folder where path/to/folder is the path + of the folder you want to access relative to your home directory. + + NNoottee:: The IMAP support is in a very early state and quite unstable at + the moment. If you need a more stable way to access your IMAP folder, + consider using a specialized program, such as fetchmail. + + + + + + 44..1122.. SSttaarrtt aa WWWWWW BBrroowwsseerr oonn UURRLLss ((EEXXTTEERRNNAALL)) + + If a message contains URLs (_u_n_i_f_i_e_d _r_e_s_s_o_u_r_c_e _l_o_c_a_t_o_r = address in the + WWW space like _h_t_t_p_:_/_/_w_w_w_._m_u_t_t_._o_r_g_/), it is efficient to get a menu + with all the URLs and start a WWW browser on one of them. This + functionality is provided by the external urlview program which can be + retrieved at ftp://ftp.cs.hmc.edu/pub/me/ and the configuration + commands: + + + macro index \cb |urlview\n + macro pager \cb |urlview\n + + + + + 55.. MMuutttt''ss MMIIMMEE SSuuppppoorrtt Quite a bit of effort has been made to make Mutt the premier text-mode @@ -1973,11 +2044,6 @@ - - - - - 55..11..22.. TThhee AAttttaacchhmmeenntt MMeennuu The default binding for view-attachments is `v', which displays the @@ -2345,7 +2411,7 @@ mail mailcap file uses this feature to test the charset to spawn an xterm using the right charset to view the message. - %% This will be replaced by a % + This will be replaced by a % Mutt does not currently support the %F and %n keywords specified in RFC 1524. The main purpose of these parameters is for multipart mes- @@ -2454,6 +2520,7 @@ + 55..55.. MMIIMMEE MMuullttiippaarrtt//AAlltteerrnnaattiivvee Mutt has some heuristics for determining which attachment of a @@ -2505,7 +2572,6 @@ -Z open the first folder with new message,exit immediately if none - To read messages in a mailbox mutt [ -nz ] [ -F _m_u_t_t_r_c ] [ -m _t_y_p_e ] [ -f _m_a_i_l_b_o_x ] @@ -2550,6 +2616,8 @@ +o ``hdr_order'' _h_e_a_d_e_r [ _h_e_a_d_e_r ... ] + +o ``unhdr_order'' _h_e_a_d_e_r [ _h_e_a_d_e_r ... ] + +o ``lists'' _a_d_d_r_e_s_s [ _a_d_d_r_e_s_s ... ] +o ``unlists'' _a_d_d_r_e_s_s [ _a_d_d_r_e_s_s ... ] @@ -2636,8 +2704,6 @@ - - 66..33..55.. aallllooww__88bbiitt Type: boolean @@ -2902,16 +2968,7 @@ - 66..33..2299.. eemmppttyy__ttoo - - Type: string - Default: undisclosed-recipients - - Specifies the text Mutt inserts in the To: header of a message you're - sending, if the To: and Cc: fields are empty. - - - 66..33..3300.. eessccaappee + 66..33..2299.. eessccaappee Type: string Default: ~ @@ -2919,7 +2976,7 @@ Escape character to use for functions in the builtin editor. - 66..33..3311.. ffaasstt__rreeppllyy + 66..33..3300.. ffaasstt__rreeppllyy Type: boolean Default: unset @@ -2932,7 +2989,7 @@ set. - 66..33..3322.. ffcccc__aattttaacchh + 66..33..3311.. ffcccc__aattttaacchh Type: boolean Default: set @@ -2941,7 +2998,7 @@ are saved along with the main body of your message. - 66..33..3333.. ffoollddeerr + 66..33..3322.. ffoollddeerr Type: String Default: ~/Mail @@ -2954,6 +3011,29 @@ the `set' command. + 66..33..3333.. ffoollddeerr__ffoorrmmaatt + + Type: format string + Default: "%N %F %2l %-8.8u %-8.8g %8s %d %f" + + This variable allows you to customize the file browser display to your + personal taste. This string is similar to ``$index_format'', but has + its own set of printf()-like sequences: + + + + %d date/time folder was last modified + %f filename + %F file permissions + %g group name (or numeric gid, if missing) + %l number of hard links + %N N if folder has new mail, blank otherwise + %s size in bytes + %u owner name (or numeric uid, if missing) + + %>X right justify the rest of the string and pad with character "X" + %|X pad to the end of the line with character "X" + 66..33..3344.. ffoolllloowwuupp__ttoo Type: boolean @@ -2968,6 +3048,8 @@ will receive a copy of the message if it is addressed to the mailing list (and thus there is no need to also include your address in a group reply). + + 66..33..3355.. ffoorrccee__nnaammee Type: boolean @@ -3010,76 +3092,7 @@ ``indent_string''. - 66..33..3399.. iinnddeexx__ffoorrmmaatt - - Type: format string - Default: "%4C %Z %{%b %d} %-15.15L (%4l) %s" - - This variable allows you to customize the message index display to - your personal taste. - - ``Format strings'' are similar to the strings used in the ``C'' - function printf to format output (see the man page for more detail). - The following sequences are defined in Mutt: - - - - - - - - - - - - - - %a address of the author - %b filename of the original message folder (think mailBox) - %B the list to which the letter was sent, or else the folder name (%b). - %c number of characters (bytes) in the message - %C current message number - %d date and time of the message in the format specified by - ``date_format'' - %f entire From: line (address + real name) - %F author name, or recipient name if the message is from you - %i message-id of the current message - %l number of lines in the message - %L list-from function - %m total number of message in the mailbox - %N message score - %n author's real name (or address if missing) - %O (_O_riginal save folder) Where mutt would formerly have stashed the - message: list name or recipient name if no list - %s subject of the message - %S status of the message (N/D/d/!/*/r) - %t `to:' field (recipients) - %T the appropriate character from the $to_chars string - %u user (login) name of the author - %Z message status flags - - %{fmt} the date and time of the message is converted to sender's - time zone, and ``fmt'' is expanded by the system call - ``strftime''; a leading bang disables locales - %[fmt] the date and time of the message is converted to the local - time zone, and ``fmt'' is expanded by the system call - ``strftime''; a leading bang disables locales - %(fmt) the local date and time when the message was received. - ``fmt'' is expanded by the system call ``strftime''; - a leading bang disables locales - %<fmt> the current local time. ``fmt'' is expanded by the system - call ``strftime''; a leading bang disables locales. - - %>X right justify the rest of the string and pad with character "X" - %|X pad to the end of the line with character "X" - - - - - See also: ``$to_chars''. - - - 66..33..4400.. hhddrrss + 66..33..3399.. hhddrrss Type: boolean Default: set @@ -3090,7 +3103,7 @@ header fields are added to every new message. - 66..33..4411.. hheeaaddeerr + 66..33..4400.. hheeaaddeerr Type: boolean Default: unset @@ -3099,8 +3112,7 @@ message you are replying to into the edit buffer. - - 66..33..4422.. hheellpp + 66..33..4411.. hheellpp Type: boolean Default: set @@ -3115,6 +3127,17 @@ should present a major problem. + 66..33..4422.. hhiiddddeenn__hhoosstt + + Type: boolean + Default: unset + + When set, mutt will skip the host name part of ``hostname'' variable + when adding the domain part to addresses. This variable does not + affect the generation, and it will not lead to the cut-off of first- + level domains. + + 66..33..4433.. hhiissttoorryy Type: number @@ -3149,7 +3172,36 @@ will reply to both the sender and the list. - 66..33..4466.. iinn__rreeppllyy__ttoo + 66..33..4466.. iimmaapp__cchheecckkiinntteerrvvaall + + Type: number + Default: 0 + + This variable configures how often (in seconds) IMAP should look for + new mail. + + + 66..33..4477.. iimmaapp__ppaassss + + Type: string + Default: unset + + Specifies the password for your IMAP account. If unset, Mutt will + prompt you for your password when you invoke the fetch-mail function. + WWaarrnniinngg: you should only use this option when you are on a fairly + secure machine, because the superuser can read your muttrc even if you + are the only one who can read the file. + + + 66..33..4488.. iimmaapp__uusseerr + + Type: string + Default: login name on local system + + Your login name on the IMAP server. + + + 66..33..4499.. iinn__rreeppllyy__ttoo Type: format string Default: "%i; from \"%n\" on %{!%a, %b %d, %Y at %I:%M:%S%p}" @@ -3159,14 +3211,16 @@ see the section on ``$index_format''. - 66..33..4477.. iinncclluuddee + 66..33..5500.. iinncclluuddee Type: quadoption Default: ask-yes Controls whether or not a copy of the message(s) you are replying to is included in your reply. - 66..33..4488.. iinnddeenntt__ssttrriinngg + + + 66..33..5511.. iinnddeenntt__ssttrriinngg Type: format string Default: "> " @@ -3176,15 +3230,75 @@ change this value, as it tends to agitate the more fanatical netizens. - 66..33..4499.. iissppeellll + + + 66..33..5522.. iinnddeexx__ffoorrmmaatt + + Type: format string + Default: "%4C %Z %{%b %d} %-15.15L (%4l) %s" + + This variable allows you to customize the message index display to + your personal taste. + + ``Format strings'' are similar to the strings used in the ``C'' + function printf to format output (see the man page for more detail). + The following sequences are defined in Mutt: + + + + %a address of the author + %b filename of the original message folder (think mailBox) + %B the list to which the letter was sent, or else the folder name (%b). + %c number of characters (bytes) in the message + %C current message number + %d date and time of the message in the format specified by + ``date_format'' + %f entire From: line (address + real name) + %F author name, or recipient name if the message is from you + %i message-id of the current message + %l number of lines in the message + %L list-from function + %m total number of message in the mailbox + %N message score + %n author's real name (or address if missing) + %O (_O_riginal save folder) Where mutt would formerly have stashed the + message: list name or recipient name if no list + %s subject of the message + %S status of the message (N/D/d/!/*/r) + %t `to:' field (recipients) + %T the appropriate character from the $to_chars string + %u user (login) name of the author + %Z message status flags + + %{fmt} the date and time of the message is converted to sender's + time zone, and ``fmt'' is expanded by the system call + ``strftime''; a leading bang disables locales + %[fmt] the date and time of the message is converted to the local + time zone, and ``fmt'' is expanded by the system call + ``strftime''; a leading bang disables locales + %(fmt) the local date and time when the message was received. + ``fmt'' is expanded by the system call ``strftime''; + a leading bang disables locales + %<fmt> the current local time. ``fmt'' is expanded by the system + call ``strftime''; a leading bang disables locales. + + %>X right justify the rest of the string and pad with character "X" + %|X pad to the end of the line with character "X" + + + + + See also: ``$to_chars''. + + + 66..33..5533.. iissppeellll Type: string Default: "ispell" How to invoke ispell (GNU's spell-checking software). - - 66..33..5500.. llooccaallee + 66..33..5544.. llooccaallee Type: string Default: "C" @@ -3193,7 +3307,7 @@ strings your system accepts for the locale variable _L_C___T_I_M_E. - 66..33..5511.. mmaaiillccaapp__ppaatthh + 66..33..5555.. mmaaiillccaapp__ppaatthh Type: string Default: $MAILCAPS or @@ -3203,9 +3317,18 @@ display MIME bodies not directly supported by Mutt. - 66..33..5522.. mmaarrkk__oolldd + 66..33..5566.. mmaaiill__cchheecckk + + Type: number + Default: 5 + + This variable configures how often (in seconds) mutt should look for + new mail. + + + 66..33..5577.. mmaarrkk__oolldd - Type: Boolean + Type: boolean Default: set Controls whether or not Mutt makes the distinction between _n_e_w @@ -3217,7 +3340,7 @@ variable. - 66..33..5533.. mmaarrkkeerrss + 66..33..5588.. mmaarrkkeerrss Type: boolean Default: set @@ -3227,16 +3350,21 @@ the ``$smart_wrap'' variable. - 66..33..5544.. mmaasskk + 66..33..5599.. mmaasskk Type: string - Default: "^(\.\.$|[^.])" + Default: "!^\.[^.]" + + A regular expression used in the file browser, optionally preceded by + the _n_o_t operator ``!''. Files whose names don't match this mask will + not be shown. The match is always case-sensitive. - A regular expression used in the file browser. Files whose names don't - match this mask will not be shown. + NNoottee:: if you need ``!'' at the beginning of the regular expression you + should enclose it in paranthesis, in order to distinguish it from the + logical _n_o_t operator for the expression. - 66..33..5555.. mmbbooxx + 66..33..6600.. mmbbooxx Type: String Default: +inbox @@ -3245,7 +3373,7 @@ folder will be appended. - 66..33..5566.. mmbbooxx__ttyyppee + 66..33..6611.. mmbbooxx__ttyyppee Type: String Default: mbox @@ -3254,7 +3382,7 @@ mbox, MMDF, MH and Maildir. - 66..33..5577.. mmeettoooo + 66..33..6622.. mmeettoooo Type: boolean Default: unset @@ -3265,7 +3393,7 @@ that message rather than to yourself. - 66..33..5588.. mmeennuu__ssccrroollll + 66..33..6633.. mmeennuu__ssccrroollll Type: boolean Default: unset @@ -3276,9 +3404,9 @@ links to avoid many redraws). - 66..33..5599.. mmeettaa__kkeeyy + 66..33..6644.. mmeettaa__kkeeyy - Type: Boolean + Type: boolean Default: unset If set, forces Mutt to interpret keystrokes with the high bit (bit 8) @@ -3290,20 +3418,22 @@ ``x''. - 66..33..6600.. mmiimmee__ffoorrwwaarrdd + 66..33..6655.. mmiimmee__ffoorrwwaarrdd - Type: boolean + Type: quadoption Default: unset When set, the message you are forwarding will be attached as a separate MIME part instead of included in the main body of the message. This is useful for forwarding MIME messages so the receiver - can properly view the message as it was delivered to you. + can properly view the message as it was delivered to you. If you like + to switch between MIME and not MIME from mail to mail, set this + variable to ask-no or ask-yes. Also see ``forward_decode'' and ``mime_forward_decode''. - 66..33..6611.. mmiimmee__ffoorrwwaarrdd__ddeeccooddee + 66..33..6666.. mmiimmee__ffoorrwwaarrdd__ddeeccooddee Type: boolean Default: unset @@ -3313,7 +3443,7 @@ ``forward_decode'' is used instead. - 66..33..6622.. mmoovvee + 66..33..6677.. mmoovvee Type: quadoption Default: ask-no @@ -3323,9 +3453,9 @@ ``mbox-hook'' command. - 66..33..6633.. mmeessssaaggee__ffoorrmmaatt + 66..33..6688.. mmeessssaaggee__ffoorrmmaatt - Type: string + Type: format string Default: "%s" This is the string displayed in the ``attachment'' menu for @@ -3333,7 +3463,7 @@ escape sequences see the section on ``index_format''. - 66..33..6644.. ppaaggeerr + 66..33..6699.. ppaaggeerr Type: string Default: builtin @@ -3344,7 +3474,7 @@ like to use. - 66..33..6655.. ppaaggeerr__ccoonntteexxtt + 66..33..7700.. ppaaggeerr__ccoonntteexxtt Type: number Default: 0 @@ -3355,7 +3485,7 @@ at the top of the next page (0 lines of context). - 66..33..6666.. ppaaggeerr__ffoorrmmaatt + 66..33..7711.. ppaaggeerr__ffoorrmmaatt Type: format string Default: "-%S- %C/%m: %-20.20n %s" @@ -3364,7 +3494,9 @@ displayed before each message in either the internal or an external pager. The valid sequences are listed in the ``index_format'' section. - 66..33..6677.. ppaaggeerr__iinnddeexx__lliinneess + + + 66..33..7722.. ppaaggeerr__iinnddeexx__lliinneess Type: number Default: 0 @@ -3382,7 +3514,7 @@ lines as it needs. - 66..33..6688.. ppaaggeerr__ssttoopp + 66..33..7733.. ppaaggeerr__ssttoopp Type: boolean Default: unset @@ -3391,7 +3523,7 @@ you are at the end of a message and invoke the _n_e_x_t_-_p_a_g_e function. - 66..33..6699.. ppggpp__aauuttooeennccrryypptt + 66..33..7744.. ppggpp__aauuttooeennccrryypptt Type: boolean Default: unset @@ -3402,7 +3534,7 @@ _m_e_n_u, when encryption is not required or signing is requested as well. - 66..33..7700.. ppggpp__aauuttoossiiggnn + 66..33..7755.. ppggpp__aauuttoossiiggnn Type: boolean Default: unset @@ -3412,37 +3544,50 @@ _m_e_n_u, when signing is not required or encryption is requested as well. - 66..33..7711.. ppggpp__ddeeffaauulltt__vveerrssiioonn + 66..33..7766.. ppggpp__ddeeffaauulltt__vveerrssiioonn Type: string - Default: pgp2 (or pgp5, if PGP 2.* is not installed) + Default: pgp2 (or pgp5, if PGP 2.* is not installed, or gpg, if none + of them is installed) - Set this to pgp2 (PGP 2.*), or pgp5 (PGP 5.*) depending on the - version, you are using primary. This variable is directly used, but it - is the default for the variables ``$pgp_receive_version'', - ``$pgp_send_version'', and ``$pgp_key_version''. + Set this to pgp2 (PGP 2.*), pgp5 (PGP 5.*), or gpg (GNU privacy + guard), depending on the version that you primarily use. This variable + is not directly used, but it is the default for the variables + ``$pgp_receive_version'', ``$pgp_send_version'', and + ``$pgp_key_version''. - 66..33..7722.. ppggpp__eennccrryyppttsseellff + 66..33..7777.. ppggpp__eennccrryyppttsseellff Type: boolean Default: set If set, the PGP _+_e_n_c_r_y_p_t_t_o_s_e_l_f flag is used when encrypting messages. - 66..33..7733.. ppggpp__kkeeyy__vveerrssiioonn + + 66..33..7788.. ppggpp__ggppgg + + Type: string + Default: system dependent + + This variable allows you to override the compile time definition of + where the gpg (GNU Privacy Guard) binary resides on your system. + + + 66..33..7799.. ppggpp__kkeeyy__vveerrssiioonn Type: string Default: ``default'' - This variable determines, which PGP version used for key ring + This variable determines which PGP version is used for key ring operations like extracting keys from messages and extracting keys from your keyring. If you set this to default, the default defined in - ``$pgp_default_version'' is used. Set this to pgp2 (PGP 2.*), or pgp5 - (PGP 5.*) if you want a different PGP version for key operations. + ``$pgp_default_version'' is used. Set this to pgp2 (PGP 2.*), pgp5 + (PGP 5.*), or gpg (GNU privacy guard) if you want to use a different + PGP version for key operations. - 66..33..7744.. ppggpp__lloonngg__iiddss + 66..33..8800.. ppggpp__lloonngg__iiddss Type: boolean Default: unset @@ -3450,19 +3595,19 @@ If set, use 64 bit PGP key IDs. Unset uses the normal 32 bit Key IDs. - 66..33..7755.. ppggpp__rreecceeiivvee__vveerrssiioonn + 66..33..8811.. ppggpp__rreecceeiivvee__vveerrssiioonn Type: string Default: ``default'' - This variable determines, which PGP version used for decrypting + This variable determines which PGP version is used for decrypting messages and verifying signatures. If you set this to default, the default defined in ``$pgp_default_version'' will be used. Set this to - pgp2 (PGP 2.*), or pgp5 (PGP 5.*) if you want a different PGP version - for receiving operations. + pgp2 (PGP 2.*), pgp5 (PGP 5.*), or gpg (GNU privacy guard) if you want + to use a different PGP version for receiving operations. - 66..33..7766.. ppggpp__rreeppllyyeennccrryypptt + 66..33..8822.. ppggpp__rreeppllyyeennccrryypptt Type: boolean Default: unset @@ -3471,7 +3616,7 @@ encrypted. - 66..33..7777.. ppggpp__rreeppllyyssiiggnn + 66..33..8833.. ppggpp__rreeppllyyssiiggnn Type: boolean Default: unset @@ -3481,22 +3626,21 @@ NNoottee:: this does not work on messages, that are encrypted aanndd signed! - 66..33..7788.. ppggpp__sseenndd__vveerrssiioonn + + + 66..33..8844.. ppggpp__sseenndd__vveerrssiioonn Type: string Default: ``default'' - This variable determines, which PGP version used for composing new + This variable determines which PGP version is used for composing new messages like encrypting and signing. If you set this to default, the default defined in ``$pgp_default_version'' will be used. Set this to - pgp2 (PGP 2.*), or pgp5 (PGP 5.*) if you want a different PGP version - for sending operations. - - + pgp2 (PGP 2.*), pgp5 (PGP 5.*), or gpg (GNU privacy guard) if you want + to use a different PGP version for sending operations. - - 66..33..7799.. ppggpp__ssiiggnn__aass + 66..33..8855.. ppggpp__ssiiggnn__aass Type: string Default: unset @@ -3506,7 +3650,7 @@ keyid form to specify your key (e.g., ``0xABCDEFGH''). - 66..33..8800.. ppggpp__ssiiggnn__mmiiccaallgg + 66..33..8866.. ppggpp__ssiiggnn__mmiiccaallgg Type: string Default: pgp-md5 @@ -3523,7 +3667,7 @@ of MIME headers when creating RFC 2015 signatures. - 66..33..8811.. ppggpp__ssttrriicctt__eenncc + 66..33..8877.. ppggpp__ssttrriicctt__eenncc Type: boolean Default: set @@ -3534,7 +3678,7 @@ you know what you are doing. - 66..33..8822.. ppggpp__ttiimmeeoouutt + 66..33..8888.. ppggpp__ttiimmeeoouutt Type: number Default: 300 @@ -3543,16 +3687,14 @@ not used. - 66..33..8833.. ppggpp__vv22 + 66..33..8899.. ppggpp__vv22 Type: string Default: system dependent This variable allows you to override the compile time definition of where the PGP 2.* binary resides on your system. - - - 66..33..8844.. ppggpp__vv22__llaanngguuaaggee + 66..33..9900.. ppggpp__vv22__llaanngguuaaggee Type: string Default: en @@ -3562,7 +3704,7 @@ (English) or "muttde" (German) to reduce the noise produced by pgp. - 66..33..8855.. ppggpp__vv22__ppuubbrriinngg + 66..33..9911.. ppggpp__vv22__ppuubbrriinngg Type: string Default: $PGPPATH/pubring.pgp or ~/.pgp/pubring.pgp if $PGPPATH isn't @@ -3571,7 +3713,7 @@ Points to the PGP 2.* public keyring. - 66..33..8866.. ppggpp__vv22__sseeccrriinngg + 66..33..9922.. ppggpp__vv22__sseeccrriinngg Type: string Default: $PGPPATH/secring.pgp or ~/.pgp/secring.pgp if $PGPPATH isn't @@ -3580,7 +3722,7 @@ Points to the PGP 2.* secret keyring. - 66..33..8877.. ppggpp__vv55 + 66..33..9933.. ppggpp__vv55 Type: string Default: system dependent @@ -3589,7 +3731,7 @@ where the PGP 5.* binary resides on your system. - 66..33..8888.. ppggpp__vv55__llaanngguuaaggee + 66..33..9944.. ppggpp__vv55__llaanngguuaaggee Type: string Default: en @@ -3599,7 +3741,7 @@ (English) to reduce the noise produced by pgp. - 66..33..8899.. ppggpp__vv55__ppuubbrriinngg + 66..33..9955.. ppggpp__vv55__ppuubbrriinngg Type: string Default: $PGPPATH/pubring.pkr or ~/.pgp/pubring.pkr if $PGPPATH isn't @@ -3608,7 +3750,7 @@ Points to the PGP 5.* public keyring. - 66..33..9900.. ppggpp__vv55__sseeccrriinngg + 66..33..9966.. ppggpp__vv55__sseeccrriinngg Type: string Default: $PGPPATH/secring.skr or ~/.pgp/secring.skr if $PGPPATH isn't @@ -3617,7 +3759,8 @@ Points to the PGP 5.* secret keyring. - 66..33..9911.. ppiippee__ddeeccooddee + + 66..33..9977.. ppiippee__ddeeccooddee Type: boolean Default: unset @@ -3627,8 +3770,7 @@ weed headers and will attempt to PGP/MIME decode the messages first. - - 66..33..9922.. ppiippee__sseepp + 66..33..9988.. ppiippee__sseepp Type: string Default: newline @@ -3637,7 +3779,7 @@ messages to an external Unix command. - 66..33..9933.. ppiippee__sspplliitt + 66..33..9999.. ppiippee__sspplliitt Type: boolean Default: unset @@ -3650,7 +3792,7 @@ and the ``$pipe_sep'' separator is added after each message. - 66..33..9944.. ppoopp__ddeelleettee + 66..33..110000.. ppoopp__ddeelleettee Type: boolean Default: unset @@ -3660,7 +3802,7 @@ download messages but also leave them on the POP server. - 66..33..9955.. ppoopp__hhoosstt + 66..33..110011.. ppoopp__hhoosstt Type: string Default: none @@ -3668,36 +3810,34 @@ The name or address of your POP3 server. - 66..33..9966.. ppoopp__ppaassss + 66..33..110022.. ppoopp__ppaassss Type: string Default: unset - Specifies the password for you POP account. If unset, Mutt will + Specifies the password for your POP account. If unset, Mutt will prompt you for your password when you invoke the fetch-mail function. WWaarrnniinngg: you should only use this option when you are on a fairly secure machine, because the superuser can read your muttrc even if you are the only one who can read the file. - 66..33..9977.. ppoopp__ppoorrtt + 66..33..110033.. ppoopp__ppoorrtt Type: number Default: 110 - This variable specifies which port your POP server is listening on. - 66..33..9988.. ppoopp__uusseerr + 66..33..110044.. ppoopp__uusseerr Type: string Default: login name on local system - Your login name on the POP3 server. - 66..33..9999.. ppoosstt__iinnddeenntt__ssttrriinngg + 66..33..110055.. ppoosstt__iinnddeenntt__ssttrriinngg Type: format string Default: none @@ -3706,7 +3846,7 @@ after the inclusion of a message which is being replied to. - 66..33..110000.. ppoossttppoonnee + 66..33..110066.. ppoossttppoonnee Type: quadoption Default: ask-yes @@ -3715,7 +3855,7 @@ mailbox when you elect not to send immediately. - 66..33..110011.. ppoossttppoonneedd + 66..33..110077.. ppoossttppoonneedd Type: string Default: ~/postponed @@ -3726,7 +3866,7 @@ variable. - 66..33..110022.. pprriinntt + 66..33..110088.. pprriinntt Type: quadoption Default: ask-no @@ -3735,7 +3875,7 @@ This is useful for people (like me) who accidentally hit ``p'' often. - 66..33..110033.. pprriinntt__ccoommmmaanndd + 66..33..110099.. pprriinntt__ccoommmmaanndd Type: string Default: lpr @@ -3743,7 +3883,7 @@ This specifies the command pipe that should be used to print messages. - 66..33..110044.. pprroommpptt__aafftteerr + 66..33..111100.. pprroommpptt__aafftteerr Type: boolean Default: set @@ -3752,21 +3892,18 @@ Mutt to prompt you for a command when the pager exits rather than returning to the index menu. If unset, Mutt will return to the index menu when the external pager exits. - - - 66..33..110055.. qquueerryy__ccoommmmaanndd + 66..33..111111.. qquueerryy__ccoommmmaanndd Type: string Default: null - This specifies the command that mutt will use to make external address queries. The string should contain a %s, which will be substituted with the query string the user types. See ``query'' for more information. - 66..33..110066.. qquuiitt + 66..33..111122.. qquuiitt Type: quadoption Default: yes @@ -3777,7 +3914,7 @@ prompted for confirmation when you try to quit. - 66..33..110077.. qquuoottee__rreeggeexxpp + 66..33..111133.. qquuoottee__rreeggeexxpp Type: string Default: "^([ \t]*[>|#:}])+" @@ -3790,7 +3927,7 @@ quote characters at the beginning of quoted lines. - 66..33..110088.. rreeaadd__iinncc + 66..33..111144.. rreeaadd__iinncc Type: number Default: 10 @@ -3808,7 +3945,7 @@ Also see the ``$write_inc'' variable. - 66..33..110099.. rreeaadd__oonnllyy + 66..33..111155.. rreeaadd__oonnllyy Type: boolean Default: unset @@ -3816,7 +3953,7 @@ If set, all folders are opened in read-only mode. - 66..33..111100.. rreeaallnnaammee + 66..33..111166.. rreeaallnnaammee Type: string Default: GCOS field from /etc/passwd @@ -3825,8 +3962,7 @@ when sending messages. - - 66..33..111111.. rreeccaallll + 66..33..111177.. rreeccaallll Type: quadoption Default: ask-yes @@ -3835,7 +3971,7 @@ when composing a new message. Also see ``postponed'' - 66..33..111122.. rreeccoorrdd + 66..33..111188.. rreeccoorrdd Type: string Default: none @@ -3849,7 +3985,7 @@ ``$save_name'' variables, and the ``fcc-hook'' command. - 66..33..111133.. rreeppllyy__rreeggeexxpp + 66..33..111199.. rreeppllyy__rreeggeexxpp Type: string Default: "^(re|aw):[ \t]*" @@ -3859,7 +3995,7 @@ the German "Aw:". - 66..33..111144.. rreeppllyy__ttoo + 66..33..112200.. rreeppllyy__ttoo Type: quadoption Default: ask-yes @@ -3872,7 +4008,7 @@ message to the author of a message. - 66..33..111155.. rreessoollvvee + 66..33..112211.. rreessoollvvee Type: boolean Default: set @@ -3882,16 +4018,19 @@ current message is executed. - 66..33..111166.. rreevveerrssee__aalliiaass + 66..33..112222.. rreevveerrssee__aalliiaass Type: boolean Default: unset + This variable controls whether or not Mutt will display the "personal" name from your aliases in the index menu if it finds an alias that matches the message's sender. For example, if you have the following alias: + + alias juser abd30425@somewhere.net (Joe User) @@ -3911,7 +4050,7 @@ address is not human friendly (like Compu$erve addresses). - 66..33..111177.. rreevveerrssee__nnaammee + 66..33..112233.. rreevveerrssee__nnaammee Type: boolean Default: unset @@ -3924,7 +4063,7 @@ line will use your address on the current machine. - 66..33..111188.. ssaavvee__aaddddrreessss + 66..33..112244.. ssaavvee__aaddddrreessss Type: boolean Default: unset @@ -3934,7 +4073,7 @@ is set too, the selection of the fcc folder will be changed as well. - 66..33..111199.. ssaavvee__eemmppttyy + 66..33..112255.. ssaavvee__eemmppttyy Type: boolean Default: set @@ -3947,11 +4086,10 @@ MH and Maildir directories. - 66..33..112200.. ssaavvee__nnaammee + 66..33..112266.. ssaavvee__nnaammee Type: boolean Default: unset - This variable controls how copies of outgoing messages are saved. When set, a check is made to see if a mailbox specified by the recipient address exists (this is done by searching for a mailbox in @@ -3963,17 +4101,17 @@ Also see the ``$force_name'' variable. - 66..33..112211.. sseennddmmaaiill + 66..33..112277.. sseennddmmaaiill Type: string Default: /usr/lib/sendmail -oi -oem Specifies the program and arguments used to deliver mail sent by Mutt. - Mutt expects that the specified program will read the message header - for recipients. + Mutt expects that the specified program interprets additional + arguments as recipient addresses. - 66..33..112222.. sseennddmmaaiill__wwaaiitt + 66..33..112288.. sseennddmmaaiill__wwaaiitt Type: number Default: 0 @@ -3994,7 +4132,7 @@ will be informed as to where to find the output. - 66..33..112233.. sshheellll + 66..33..112299.. sshheellll Type: string Default: retrieved from passwd file @@ -4002,7 +4140,7 @@ Command to use when spawning a subshell. - 66..33..112244.. ssiigg__ddaasshheess + 66..33..113300.. ssiigg__ddaasshheess Type: boolean Default: set @@ -4015,7 +4153,10 @@ the signature in a different color in the builtin pager. - 66..33..112255.. ssiiggnnaattuurree + + + + 66..33..113311.. ssiiggnnaattuurree Type: string Default: ~/.signature @@ -4024,14 +4165,16 @@ outgoing messages. If the filename ends with a pipe (``|''), it is assumed that filename is a shell command and input should be read from its stdout. - 66..33..112266.. ssiimmppllee__sseeaarrcchh + + + 66..33..113322.. ssiimmppllee__sseeaarrcchh Type: string Default: "~f %s | ~s %s" Specifies how Mutt should expand a simple search into a real search pattern. A simple search is one that does not contain any of the ~ - operators. See ``searching'' for more information on search patterns. + operators. See ``patterns'' for more information on search patterns. For example, if you simply type joe at a search or limit prompt, Mutt will automatically expand it to the value specified by this variable. @@ -4040,7 +4183,7 @@ ~f joe | ~s joe - 66..33..112277.. ssmmaarrtt__wwrraapp + 66..33..113333.. ssmmaarrtt__wwrraapp Type: boolean Default: set @@ -4051,7 +4194,7 @@ ``$markers'' variable. - 66..33..112288.. ssoorrtt + 66..33..113344.. ssoorrtt Type: string Default: date-sent @@ -4079,7 +4222,7 @@ order (example: set sort=reverse-date-sent). - 66..33..112299.. ssoorrtt__aalliiaass + 66..33..113355.. ssoorrtt__aalliiaass Type: string Default: alias @@ -4087,9 +4230,6 @@ Specifies how the entries in the `alias' menu are sorted. The following are legal values: - - - alias sort alphabetically by alias name address sort alphabetically by email address unsorted leave in order specified in .muttrc @@ -4097,7 +4237,7 @@ - 66..33..113300.. ssoorrtt__aauuxx + 66..33..113366.. ssoorrtt__aauuxx Type: string Default: date-sent @@ -4115,7 +4255,7 @@ you have set sort=reverse-threads.) - 66..33..113311.. ssoorrtt__bbrroowwsseerr + 66..33..113377.. ssoorrtt__bbrroowwsseerr Type: string @@ -4131,7 +4271,7 @@ order (example: set sort_browser=reverse-date). - 66..33..113322.. ssppoooollffiillee + 66..33..113388.. ssppoooollffiillee Type: string Default: most likely /var/mail/$USER or /usr/spool/mail/$USER @@ -4142,7 +4282,7 @@ variable $MAIL if it is not set. - 66..33..113333.. ssoorrtt__rree + 66..33..113399.. ssoorrtt__rree Type: boolean Default: set @@ -4156,7 +4296,7 @@ non-``reply_regexp'' parts of both messages are identical. - 66..33..113344.. ssttaattuuss__cchhaarrss + 66..33..114400.. ssttaattuuss__cchhaarrss Type: string Default: "-*%" @@ -4170,7 +4310,7 @@ with the toggle-write operation, bound by default to "%"). - 66..33..113355.. ssttaattuuss__ffoorrmmaatt + 66..33..114411.. ssttaattuuss__ffoorrmmaatt Type: string Default: "-%r-Mutt: %f [Msgs:%?M?%M/?%m%?n? New:%n?%?o? Old:%o?%?d? @@ -4222,6 +4362,9 @@ %?<sequence_char>?<optional_string>? + + + where _s_e_q_u_e_n_c_e___c_h_a_r is a character from the table above, and _o_p_t_i_o_n_a_l___s_t_r_i_n_g is the string you would like printed if _s_t_a_t_u_s___c_h_a_r is nonzero. _o_p_t_i_o_n_a_l___s_t_r_i_n_g mmaayy contain other sequence as well as normal @@ -4237,8 +4380,19 @@ + Additionally you can switch between two strings, the first one, if a + value is zero, the second one, if the value is nonzero, by using the + following construct: + + + + %?<sequence_char>?<if_string>&<else_string>? + + + + - 66..33..113366.. ssttaattuuss__oonn__ttoopp + 66..33..114422.. ssttaattuuss__oonn__ttoopp Type: boolean Default: unset @@ -4247,7 +4401,7 @@ first line of the screen rather than near the bottom. - 66..33..113377.. ssttrriicctt__tthhrreeaaddss + 66..33..114433.. ssttrriicctt__tthhrreeaaddss Type: boolean Default: unset @@ -4260,35 +4414,38 @@ the subject ``hi'' which will get grouped together. - 66..33..113388.. ssuussppeenndd + 66..33..114444.. ssuussppeenndd Type: boolean Default: set + When _u_n_s_e_t, mutt won't stop when the user presses the terminal's _s_u_s_p key, usually ``control-Z''. This is useful if you run mutt inside an xterm using a command like xterm -e mutt. - 66..33..113399.. tthhoorroouugghh__sseeaarrcchh + 66..33..114455.. tthhoorroouugghh__sseeaarrcchh Type: boolean Default: unset Affects the _~_b and _~_h search operations described in section - ``Searching'' above. If set, the headers and attachments of messages + ``patterns'' above. If set, the headers and attachments of messages to be searched are decoded before searching. If unset, messages are searched as they appear in the folder. - 66..33..114400.. ttiillddee + 66..33..114466.. ttiillddee Type: boolean Default: unset When set, the internal-pager will pad blank lines to the bottom of the screen with a tilde (~). - 66..33..114411.. ttiimmeeoouutt + + + 66..33..114477.. ttiimmeeoouutt Type: number Default: 600 @@ -4298,7 +4455,7 @@ mail. A value of zero or less will cause Mutt not to ever time out. - 66..33..114422.. ttmmppddiirr + 66..33..114488.. ttmmppddiirr Type: string Default: /tmp @@ -4307,7 +4464,7 @@ temporary files needed for displaying and composing messages. - 66..33..114433.. ttoo__cchhaarrss + 66..33..114499.. ttoo__cchhaarrss Type: string Default: " +TCF" @@ -4323,11 +4480,12 @@ by _y_o_u. - 66..33..114444.. uussee__88bbiittmmiimmee + 66..33..115500.. uussee__88bbiittmmiimmee Type: boolean Default: unset + WWaarrnniinngg:: do not set this variable unless you are using a version of sendmail which supports the -B8BITMIME flag (such as sendmail 8.8.x) or you may not be able to send mail. @@ -4336,7 +4494,7 @@ sending 8-bit messages to enable ESMTP negotiation. - 66..33..114455.. uussee__ddoommaaiinn + 66..33..115511.. uussee__ddoommaaiinn Type: boolean Default: set @@ -4346,7 +4504,7 @@ addresses will be qualified. - 66..33..114466.. uussee__ffrroomm + 66..33..115522.. uussee__ffrroomm Type: boolean Default: set @@ -4354,7 +4512,9 @@ When _s_e_t, Mutt will generate the `From:' header field when sending messages. If _u_n_s_e_t, no `From:' header field will be generated unless the user explicitly sets one using the ``my_hdr'' command. - 66..33..114477.. uussee__mmaaiillccaapp + + + 66..33..115533.. uussee__mmaaiillccaapp Type: quad-option Default: ask @@ -4372,7 +4532,7 @@ display MIME parts without prompting the user for confirmation. - 66..33..114488.. ppggpp__vveerriiffyy__ssiigg + 66..33..115544.. ppggpp__vveerriiffyy__ssiigg Type: quad-option Default: yes @@ -4382,7 +4542,7 @@ to verify PGP/MIME signatures. - 66..33..114499.. vviissuuaall + 66..33..115555.. vviissuuaall Type: string Default: $VISUAL @@ -4391,7 +4551,8 @@ the builtin editor. - 66..33..115500.. wwaaiitt__kkeeyy + + 66..33..115566.. wwaaiitt__kkeeyy Type: boolean Default: set @@ -4407,7 +4568,7 @@ for a key only if the external command returned a non-zero status. - 66..33..115511.. wwrraapp__sseeaarrcchh + 66..33..115577.. wwrraapp__sseeaarrcchh Type: boolean Default: set @@ -4418,9 +4579,7 @@ unset, searches will not wrap. - - - 66..33..115522.. wwrriittee__iinncc + 66..33..115588.. wwrriittee__iinncc Type: number Default: 10 @@ -4432,6 +4591,15 @@ Also see the ``$read_inc'' variable. + 66..33..115599.. wwrriittee__bbcccc + + Type: boolean + Default: set + + Controls whether mutt writes out the Bcc header when preparing + messages to be sent. Exim users may wish to use this. + + 66..44.. FFuunnccttiioonnss The following is the list of available functions listed by the mapping @@ -4449,6 +4617,7 @@ all menus (except as noted). + bottom-page L move to the bottom of the page current-bottom not bound move current entry to bottom of page current-middle not bound move current entry to middle of page @@ -4486,6 +4655,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + bounce-message b remail a message to another user change-folder c open a different folder change-folder-readonly ESC c open a different folder in read only mode @@ -4844,7 +5042,7 @@ 77..11.. AAcckknnoowwlleeddggeemmeennttss - Kari Hurrta <kari.hurtta@fmi.fi> co-developed the original MIME + Kari Hurtta <kari.hurtta@fmi.fi> co-developed the original MIME parsing code back in the ELM-ME days. The following people have been very helpful to the development of diff --git a/doc/mutt.man b/doc/mutt.man.in similarity index 64% rename from doc/mutt.man rename to doc/mutt.man.in index 7fcc3ced..d46fb938 100644 --- a/doc/mutt.man +++ b/doc/mutt.man.in @@ -1,259 +1,151 @@ -.if n .ds Q \&" -.if t .ds Q `` -.if n .ds U \&" -.if t .ds U '' -.TH "Mutt" 1 -.tr \& -.nr bi 0 -.nr ll 0 -.nr el 0 -.de DS -.. -.de DE -.. -.de Pp -.ie \\n(ll>0 \{\ -.ie \\n(bi=1 \{\ -.nr bi 0 -.if \\n(t\\n(ll=0 \{.IP \\(bu\} -.if \\n(t\\n(ll=1 \{.IP \\n+(e\\n(el.\} -.\} -.el .sp -.\} -.el \{\ -.ie \\nh=1 \{\ -.LP -.nr h 0 -.\} -.el .PP -.\} -.. +.\" -*-nroff-*- +.\" +.\" +.\" Copyright (C) 1996-8 Michael R. Elkins <me@cs.hmc.edu> +.\" +.\" This program is free software; you can redistribute it and/or modify +.\" it under the terms of the GNU General Public License as published by +.\" the Free Software Foundation; either version 2 of the License, or +.\" (at your option) any later version. +.\" +.\" This program is distributed in the hope that it will be useful, +.\" but WITHOUT ANY WARRANTY; without even the implied warranty of +.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +.\" GNU General Public License for more details. +.\" +.\" You should have received a copy of the GNU General Public License +.\" along with this program; if not, write to the Free Software +.\" Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +.\" +.TH mutt 1 "JULY 1998" Unix "User Manuals" .SH NAME - -.Pp -mutt - The Mutt Mail User Agent -.Pp +.PP +mutt \- The Mutt Mail User Agent .SH SYNOPSIS - -.Pp -mutt [ -hnpRvxyzZ ] -[ -a \fIfile\fP ] -[ -b \fIaddress\fP ] -[ -c \fIaddress\fP ] -[ -e \fIcommand\fP ] -[ -f \fImailbox\fP ] -[ -F \fImuttrc\fP ] -[ -H \fIdraftfile\fP ] -[ -i \fIinclude\fP ] -[ -m \fItype\fP ] -[ -s \fIsubject\fP ] -[ \fIaddress\fP ... ] -.Pp +.PP +.B mutt +[-hnpRvxyzZ] +[-a \fIfile\fP] +[-b \fIaddress\fP] +[-c \fIaddress\fP] +[-e \fIcommand\fP] +[-f \fImailbox\fP] +[-F \fImuttrc\fP] +[-H \fIdraftfile\fP] +[-i \fIinclude\fP] +[-m \fItype\fP] +[-s \fIsubject\fP] .SH DESCRIPTION - -.Pp +.PP Mutt is a small but very powerful text based program for reading electronic mail under unix operating systems, including support color terminals, MIME, and a threaded sorting mode. -.Pp .SH OPTIONS - -.Pp -.nr ll +1 -.nr t\n(ll 2 -.if \n(ll>1 .RS +.PP .IP "-a \fIfile\fP" -.nr bi 1 -.Pp Attach a file to your message using MIME. .IP "-b \fIaddress\fP" -.nr bi 1 -.Pp Specify a blind-carbon-copy (BCC) recipient .IP "-c \fIaddress\fP" -.nr bi 1 -.Pp Specify a carbon-copy (CC) recipient .IP "-e \fIcommand\fP" -.nr bi 1 -.Pp Specify a configuration command to be run after processing of initialization files. .IP "-f \fImailbox\fP" -.nr bi 1 -.Pp Specify which mailbox to load. .IP "-F \fImuttrc\fP" -.nr bi 1 -.Pp Specify an initialization file to read instead of ~/.muttrc .IP "-h" -.nr bi 1 -.Pp Display help. .IP "-H \fIdraft\fP" -.nr bi 1 -.Pp Specify a draft file which contains header and body to use to send a message. .IP "-i \fIinclude\fP" -.nr bi 1 -.Pp Specify a file to include into the body of a message. -.IP "-m \fItype\fP " -.nr bi 1 -.Pp +.IP "-m \fItype\fP " specify a default mailbox type .IP "-n" -.nr bi 1 -.Pp Causes Mutt to bypass the system configuration file. .IP "-p" -.nr bi 1 -.Pp Resume a postponed message. .IP "-R" -.nr bi 1 -.Pp Open a mailbox in \fIread-only\fP mode. .IP "-s \fIsubject\fP" -.nr bi 1 -.Pp Specify the subject of the message. .IP "-v" -.nr bi 1 -.Pp Display the Mutt version number and compile-time definitions. .IP "-x" -.nr bi 1 -.Pp Emulate the mailx compose mode. .IP "-y" -.nr bi 1 -.Pp Start Mutt with a listing of all mailboxes specified by the \fImailboxes\fP command. .IP "-z" -.nr bi 1 -.Pp When used with -f, causes Mutt not to start if there are no messages in the mailbox. .IP "-Z" -.nr bi 1 -.Pp Causes Mutt to open the first mailbox specified by the \fImailboxes\fP command which contains new mail. -.if \n(ll>1 .RE -.nr ll -1 -.Pp .SH ENVIRONMENT - -.Pp -.nr ll +1 -.nr t\n(ll 2 -.if \n(ll>1 .RS +.PP .IP "EDITOR" -.nr bi 1 -.Pp Editor to invoke when composing a message. .IP "HOME" -.nr bi 1 -.Pp Full path of the user's home directory. .IP "MAIL" -.nr bi 1 -.Pp Full path of the user's spool mailbox. .IP "MAILCAPS" -.nr bi 1 -.Pp Path to search for mailcap files. .IP "MM_NOASK" -.nr bi 1 -.Pp If this variable is set, mailcap are always used without prompting first. .IP "PGPPATH" -.nr bi 1 -.Pp Directory in which the user's PGP public keyring can be found. .IP "TMPDIR" -.nr bi 1 -.Pp Directory in which temporary files are created. .IP "REPLYTO" -.nr bi 1 -.Pp Default Reply-To address. .IP "VISUAL" -.nr bi 1 -.Pp Editor to invoke when the ~v command is given in the builtin editor. -.if \n(ll>1 .RE -.nr ll -1 -.Pp .SH FILES - -.Pp -.nr ll +1 -.nr t\n(ll 2 -.if \n(ll>1 .RS +.PP .IP "~/.muttrc" -.nr bi 1 -.Pp User configuration file. -.IP "/usr/local/share/Muttrc" -.nr bi 1 -.Pp +.IP "@sharedir@/Muttrc" System-wide configuration file. .IP "/tmp/muttXXXXXX" -.nr bi 1 -.Pp Temporary files created by Mutt. .IP "~/.mailcap" -.nr bi 1 -.Pp User definition for handling non-text MIME types. -.IP "/usr/local/share/mailcap" -.nr bi 1 -.Pp +.IP "@sharedir@/mailcap" System definition for handing non-text MIME types. .IP "~/.mime.types" -.nr bi 1 -.Pp User's personal mapping between MIME types and file extensions. -.IP "/usr/local/share/mime.types" -.nr bi 1 -.Pp +.IP "@sharedir@/mime.types" System mapping between MIME types and file extensions. -.Pp -.if \n(ll>1 .RE -.nr ll -1 -.Pp +.IP "@libdir@/dotlock" +The privileged dotlocking program. .SH BUGS - -.Pp -suspend/resume while editing a file with an external editor does not work +.PP +Suspend/resume while editing a file with an external editor does not work under SunOS 4.x if you use the curses lib in /usr/5lib. It \fIdoes\fP work with the S-Lang library, however. -.Pp +.PP Resizing the screen while using an external pager causes Mutt to go haywire on some systems. -.Pp +.PP suspend/resume does not work under Ultrix. -.Pp +.PP The help line for the index menu is not updated if you change the bindings for one of the functions listed while Mutt is running. -.Pp .SH SEE ALSO - -.Pp -curses(3), ncurses(3), sendmail(1), smail(1), mailcap(5) -.Pp +.PP +.BR curses (3), +.BR dotlock (1), +.BR ncurses (3), +.BR sendmail (1), +.BR smail (1), +.BR mailcap (5) +.PP Mutt Home Page: http://www.cs.hmc.edu/~me/mutt/ -.Pp .SH AUTHOR - -.Pp Michael Elkins <me@cs.hmc.edu> -.Pp -http://www.cs.hmc.edu/~me \ No newline at end of file +http://www.cs.hmc.edu/~me/ diff --git a/dotlock.c b/dotlock.c new file mode 100644 index 00000000..0b978fdb --- /dev/null +++ b/dotlock.c @@ -0,0 +1,714 @@ +/* + * Copyright (C) 1996-8 Michael R. Elkins <me@cs.hmc.edu> + * Copyright (C) 1998 Thomas Roessler <roessler@guug.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +/* + * This module either be compiled into Mutt, or it can be + * built as a separate program. For building it + * separately, define the DL_STANDALONE preprocessor + * macro. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <unistd.h> +#include <dirent.h> +#include <sys/file.h> +#include <sys/stat.h> +#include <sys/utsname.h> +#include <errno.h> +#include <time.h> +#include <fcntl.h> +#include <limits.h> + +#ifndef _POSIX_PATH_MAX +#include <posix1_lim.h> +#endif + +#include "dotlock.h" +#include "config.h" + +#ifdef DL_STANDALONE +#include "reldate.h" +#endif + +# define MAXLINKS 1024 /* maximum link depth */ + +# ifdef DL_STANDALONE + +# define LONG_STRING 1024 +# define MAXLOCKATTEMPT 5 + +# define strfcpy(A,B,C) strncpy(A,B,C), *(A+(C)-1)=0 + +# ifdef USE_SETGID + +# ifdef HAVE_SETEGID +# define SETEGID setegid +# else +# define SETEGID setgid +# endif +# ifndef S_ISLNK +# define S_ISLNK(x) (((x) & S_IFMT) == S_IFLNK ? 1 : 0) +# endif + +# endif + +# ifndef HAVE_SNPRINTF +extern int snprintf(char *, size_t, const char *, ...); +# endif + +#else /* DL_STANDALONE */ + +# ifdef USE_SETGID +# error Do not try to compile dotlock as a mutt module when requiring egid switching! +# endif + +# include "mutt.h" +# include "mx.h" + +#endif /* DL_STANDALONE */ + +static short f_try = 0; +static short f_force = 0; +static short f_unlock = 0; +static short f_priv = 0; +static int Retry = MAXLOCKATTEMPT; + +#ifdef DL_STANDALONE +static char *Hostname; +#endif + +#ifdef USE_SETGID +static gid_t UserGid; +static gid_t MailGid; +#endif + +static int dotlock_deference_symlink(char *, size_t, const char *); +static int dotlock_prepare(char *, size_t, const char *); + +#ifdef DL_STANDALONE +static int dotlock_init_privs(void); +static void usage(const char *); +#endif + +static void dotlock_expand_link(char *, const char *, const char *); +static void BEGIN_PRIVILEGED(void); +static void END_PRIVILEGED(void); + +/* These functions work on the current directory. + * Invoke dotlock_prepare() before and check their + * return value. + */ + +static int dotlock_try(void); +static int dotlock_unlock(const char *); +static int dotlock_lock(const char *); + + +#ifdef DL_STANDALONE + +int main(int argc, char **argv) +{ + int i; + char *p; + const char *f; + struct utsname utsname; + char realpath[_POSIX_PATH_MAX]; + + + /* first, drop privileges */ + + if(dotlock_init_privs() == -1) + return DL_EX_ERROR; + + + /* determine the system's host name */ + + uname(&utsname); + if(!(Hostname = strdup(utsname.nodename))) + return DL_EX_ERROR; + if((p = strchr(Hostname, '.'))) + *p = '\0'; + + + /* parse the command line options. */ + + while((i = getopt(argc, argv, "tfupr:")) != EOF) + { + switch(i) + { + case 't': f_try = 1; break; + case 'f': f_force = 1; break; + case 'u': f_unlock = 1; break; + case 'p': f_priv = 1; break; + case 'r': Retry = atoi(optarg); break; + default: usage(argv[0]); + } + } + + if(optind == argc || f_try + f_force + f_unlock > 1 || Retry < 0) + usage(argv[0]); + + f = argv[optind]; + + + /* If dotlock_prepare() succeeds [return value == 0], + * realpath contains the basename of f, and we have + * successfully changed our working directory to + * `dirname $f`. Additionally, f has been opened for + * reading to verify that the user has at least read + * permissions on that file. + * + * For a more detailed explanation of all this, see the + * lengthy comment below. + */ + + if(dotlock_prepare(realpath, sizeof(realpath), f) != 0) + return DL_EX_ERROR; + + /* Finally, actually perform the locking operation. */ + + if(f_try) + return dotlock_try(); + else if(f_unlock) + return dotlock_unlock(realpath); + else /* lock */ + return dotlock_lock(realpath); + +} + +/* + * Determine our effective group ID, and drop + * privileges. + * + * Return value: + * + * 0 - everything went fine + * -1 - we couldn't drop privileges. + * + */ + + +static int +dotlock_init_privs(void) +{ + +# ifdef USE_SETGID + + UserGid = getgid(); + MailGid = getegid(); + + if(SETEGID(UserGid) != 0) + return -1; + +# endif + + return 0; +} + + +#else /* DL_STANDALONE */ + +/* + * This function is intended to be invoked from within + * mutt instead of mx.c's invoke_dotlock(). + * + */ + +int dotlock_invoke(const char *path, int flags, int retry) +{ + int currdir; + int r; + char realpath[_POSIX_PATH_MAX]; + + if((currdir = open(".", O_RDONLY)) == -1) + return DL_EX_ERROR; + + if(!(flags & DL_FL_RETRY) || retry) + Retry = MAXLOCKATTEMPT; + else + Retry = 0; + + f_priv = f_try = f_unlock = f_force = 0; + + if(flags & DL_FL_FORCE) + f_force = 1; + + r = DL_EX_ERROR; + if(dotlock_prepare(realpath, sizeof(realpath), path) == -1) + goto bail; + + if(flags & DL_FL_TRY) + r = dotlock_try(); + else if(flags & DL_FL_UNLOCK) + r = dotlock_unlock(realpath); + else /* lock */ + r = dotlock_lock(realpath); + + bail: + + fchdir(currdir); + close(currdir); + + return r; +} + +#endif /* DL_STANDALONE */ + + +/* + * Get privileges + * + * This function re-acquires the privileges we may have + * if the user told us to do so by giving the "-p" + * command line option. + * + * BEGIN_PRIVILEGES() won't return if an error occurs. + * + */ + +static void +BEGIN_PRIVILEGED(void) +{ +#ifdef USE_SETGID + if(f_priv) + { + if(SETEGID(MailGid) != 0) + { + /* perror("setegid"); */ + exit(DL_EX_ERROR); + } + } +#endif +} + +/* + * Drop privileges + * + * This function drops the group privileges we may have. + * + * END_PRIVILEGED() won't return if an error occurs. + * + */ + +static void +END_PRIVILEGED(void) +{ +#ifdef USE_SETGID + if(f_priv) + { + if(SETEGID(UserGid) != 0) + { + /* perror("setegid"); */ + exit(DL_EX_ERROR); + } + } +#endif +} + +#ifdef DL_STANDALONE + +/* + * Usage information. + * + * This function doesn't return. + * + */ + +static void +usage(const char *av0) +{ + fprintf(stderr, "dotlock [Mutt %s (%s)]\n", VERSION, ReleaseDate); + fprintf(stderr, "usage: %s [-t|-f|-u] [-p] [-r <retries>] file\n", + av0); + + fputs("\noptions:" + "\n -t\t\ttry" + "\n -f\t\tforce" + "\n -u\t\tunlock" + "\n -p\t\tprivileged" +#ifndef USE_SETGID + " (ignored)" +#endif + "\n -r <retries>\tRetry locking" + "\n", stderr); + + exit(DL_EX_ERROR); +} + +#endif + +/* + * Access checking: Let's avoid to lock other users' mail + * spool files if we aren't permitted to read them. + * + * Some simple-minded access(2) checking isn't sufficient + * here: The problem is that the user may give us a + * deeply nested path to a file which has the same name + * as the file he wants to lock, but different + * permissions, say, e.g. + * /tmp/lots/of/subdirs/var/spool/mail/root. + * + * He may then try to replace /tmp/lots/of/subdirs by a + * symbolic link to / after we have invoked access() to + * check the file's permissions. The lockfile we'd + * create or remove would then actually be + * /var/spool/mail/root. + * + * To avoid this attack, we proceed as follows: + * + * - First, follow symbolic links a la + * dotlock_deference_symlink(). + * + * - get the result's dirname. + * + * - chdir to this directory. If you can't, bail out. + * + * - try to open the file in question, only using its + * basename. If you can't, bail out. + * + * - fstat that file and compare the result to a + * subsequent lstat (only using the basename). If + * the comparison fails, bail out. + * + * dotlock_prepare() is invoked from main() directly + * after the command line parsing has been done. + * + * Return values: + * + * 0 - Evereything's fine. The program's new current + * directory is the contains the file to be locked. + * The string pointed to by bn contains the name of + * the file to be locked. + * + * -1 - Something failed. Don't continue. + * + * tlr, Jul 15 1998 + */ + +static int +dotlock_prepare(char *bn, size_t l, const char *f) +{ + struct stat fsb, lsb; + char realpath[_POSIX_PATH_MAX]; + char *basename, *dirname; + char *p; + int fd; + int r; + + if(dotlock_deference_symlink(realpath, sizeof(realpath), f) == -1) + return -1; + + if((p = strrchr(realpath, '/'))) + { + *p = '\0'; + basename = p + 1; + dirname = realpath; + } + else + { + basename = realpath; + dirname = "."; + } + + if(strlen(basename) + 1 > l) + return -1; + + strfcpy(bn, basename, l); + + if(chdir(dirname) == -1) + return -1; + + if((fd = open(basename, O_RDONLY)) == -1) + return -1; + + r = fstat(fd, &fsb); + close(fd); + + if(r == -1) + return -1; + + if(lstat(basename, &lsb) == -1) + return -1; + + if(S_ISLNK(lsb.st_mode)) + return -1; + + if((lsb.st_dev != fsb.st_dev) || + (lsb.st_ino != fsb.st_ino) || + (lsb.st_mode != fsb.st_mode) || + (lsb.st_nlink != fsb.st_nlink) || + (lsb.st_uid != fsb.st_uid) || + (lsb.st_gid != fsb.st_gid) || + (lsb.st_rdev != fsb.st_rdev) || + (lsb.st_size != fsb.st_size)) + { + /* something's fishy */ + return -1; + } + + return 0; +} + +/* + * Expand a symbolic link. + * + * This function expects newpath to have space for + * at least _POSIX_PATH_MAX characters. + * + */ + +static void +dotlock_expand_link (char *newpath, const char *path, const char *link) +{ + const char *lb = NULL; + size_t len; + + /* link is full path */ + if (*link == '/') + { + strfcpy (newpath, link, _POSIX_PATH_MAX); + return; + } + + if ((lb = strrchr (path, '/')) == NULL) + { + /* no path in link */ + strfcpy (newpath, link, _POSIX_PATH_MAX); + return; + } + + len = lb - path + 1; + memcpy (newpath, path, len); + strfcpy (newpath + len, link, _POSIX_PATH_MAX - len); +} + + +/* + * Deference a chain of symbolic links + * + * The final path is written to d. + * + */ + +static int +dotlock_deference_symlink(char *d, size_t l, const char *path) +{ + struct stat sb; + char realpath[_POSIX_PATH_MAX]; + const char *pathptr = path; + int count = 0; + + while(count++ < MAXLINKS) + { + if(lstat(pathptr, &sb) == -1) + { + /* perror(pathptr); */ + return -1; + } + + if(S_ISLNK (sb.st_mode)) + { + char linkfile[_POSIX_PATH_MAX]; + char linkpath[_POSIX_PATH_MAX]; + int len; + + if((len = readlink(pathptr, linkfile, sizeof(linkfile))) == -1) + { + /* perror(pathptr); */ + return -1; + } + + linkfile[len] = '\0'; + dotlock_expand_link(linkpath, pathptr, linkfile); + strfcpy(realpath, linkpath, sizeof(realpath)); + pathptr = realpath; + } + else + break; + } + + strfcpy(d, pathptr, l); + return 0; +} + +/* + * Dotlock a file. + * + * realpath is assumed _not_ to be an absolute path to + * the file we are about to lock. Invoke + * dotlock_prepare() before using this function! + * + */ + +static int +dotlock_lock(const char *realpath) +{ + char lockfile[_POSIX_PATH_MAX + LONG_STRING]; + char nfslockfile[_POSIX_PATH_MAX + LONG_STRING]; + size_t prev_size = 0; + int fd; + int count = 0; + struct stat sb; + time_t t; + + snprintf(nfslockfile, sizeof(nfslockfile), "%s.%s.%d", + realpath, Hostname, (int) getpid()); + snprintf(lockfile, sizeof(lockfile), "%s.lock", realpath); + + + BEGIN_PRIVILEGED(); + + unlink(nfslockfile); + + while ((fd = open (nfslockfile, O_WRONLY | O_EXCL | O_CREAT, 0)) < 0) + { + END_PRIVILEGED(); + + + if (errno != EAGAIN) + { + /* perror ("cannot open NFS lock file"); */ + return DL_EX_ERROR; + } + + + BEGIN_PRIVILEGED(); + } + + END_PRIVILEGED(); + + + close(fd); + + while(1) + { + + BEGIN_PRIVILEGED(); + link(nfslockfile, lockfile); + END_PRIVILEGED(); + + if(stat(nfslockfile, &sb) != 0) + { + /* perror("stat"); */ + return DL_EX_ERROR; + } + + if(sb.st_nlink == 2) + break; + + if(count == 0) + prev_size = sb.st_size; + + if(prev_size == sb.st_size && ++count > Retry) + { + if(f_force) + { + BEGIN_PRIVILEGED(); + unlink(lockfile); + END_PRIVILEGED(); + + count = 0; + continue; + } + else + { + BEGIN_PRIVILEGED(); + unlink(nfslockfile); + END_PRIVILEGED(); + return DL_EX_EXIST; + } + } + + prev_size = sb.st_size; + + /* don't trust sleep(3) as it may be interrupted + * by users sending signals. + */ + + t = time(NULL); + do { + sleep(1); + } while (time(NULL) == t); + } + + BEGIN_PRIVILEGED(); + unlink(nfslockfile); + END_PRIVILEGED(); + + return DL_EX_OK; +} + + +/* + * Unlock a file. + * + * The same comment as for dotlock_lock() applies here. + * + */ + +static int +dotlock_unlock(const char *realpath) +{ + char lockfile[_POSIX_PATH_MAX + LONG_STRING]; + int i; + + snprintf(lockfile, sizeof(lockfile), "%s.lock", + realpath); + + BEGIN_PRIVILEGED(); + i = unlink(lockfile); + END_PRIVILEGED(); + + if(i == -1) + return DL_EX_ERROR; + + return DL_EX_OK; +} + + +/* + * Check if a file can be locked at all. + * + * The same comment as for dotlock_lock() applies here. + * + */ + +static int +dotlock_try(void) +{ +#ifdef USE_SETGID + struct stat sb; +#endif + + if(access(".", W_OK) == 0) + return DL_EX_OK; + +#ifdef USE_SETGID + if(stat(".", &sb) == 0) + { + if((sb.st_mode & S_IWGRP) == S_IWGRP && sb.st_gid == MailGid) + return DL_EX_NEED_PRIVS; + } +#endif + + return DL_EX_IMPOSSIBLE; +} diff --git a/dotlock.h b/dotlock.h new file mode 100644 index 00000000..4dde522c --- /dev/null +++ b/dotlock.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 1996-8 Michael R. Elkins <me@cs.hmc.edu> + * Copyright (C) 1998 Thomas Roessler <roessler@guug.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _DOTLOCK_H +#define _DOTLOCK_H + +/* exit values */ + +#define DL_EX_OK 0 +#define DL_EX_ERROR 1 +#define DL_EX_EXIST 3 +#define DL_EX_NEED_PRIVS 4 +#define DL_EX_IMPOSSIBLE 5 + +/* flags */ + +#define DL_FL_TRY (1 << 0) +#define DL_FL_UNLOCK (1 << 1) +#define DL_FL_USEPRIV (1 << 2) +#define DL_FL_FORCE (1 << 3) +#define DL_FL_RETRY (1 << 4) + +#ifndef DL_STANDALONE +int dotlock_invoke(const char *, int, int); +#endif + +#endif diff --git a/edit.c b/edit.c index 6d310d6f..77afba40 100644 --- a/edit.c +++ b/edit.c @@ -64,7 +64,7 @@ be_snarf_data (FILE *f, char **buf, int *bufmax, int *buflen, int offset, tmp[sizeof (tmp) - 1] = 0; if (prefix) { - strfcpy (tmp, Prefix, sizeof (tmp)); + strfcpy (tmp, NONULL(Prefix), sizeof (tmp)); tmplen = strlen (tmp); p = tmp + tmplen; tmplen = sizeof (tmp) - tmplen; @@ -129,9 +129,9 @@ static int be_barf_file (const char *path, char **buf, int buflen) static void be_free_memory (char **buf, int buflen) { while (buflen-- > 0) - free (buf[buflen]); + FREE (&buf[buflen]); if (buf) - free (buf); + FREE (&buf); } static char ** @@ -323,7 +323,7 @@ int mutt_builtin_editor (const char *path, HEADER *msg, HEADER *cur) } addch ('\n'); - if (tmp[0] == EscChar[0] && tmp[1] != EscChar[0]) + if (EscChar && tmp[0] == EscChar[0] && tmp[1] != EscChar[0]) { /* remove trailing whitespace from the line */ p = tmp + strlen (tmp) - 1; @@ -364,7 +364,7 @@ int mutt_builtin_editor (const char *path, HEADER *msg, HEADER *cur) } buf = be_include_messages (p, buf, &bufmax, &buflen, (tolower (tmp[1]) == 'm'), - (isupper (tmp[1]))); + (isupper ((unsigned char) tmp[1]))); } else addstr ("No mailbox.\n"); @@ -382,7 +382,11 @@ int mutt_builtin_editor (const char *path, HEADER *msg, HEADER *cur) break; case 'r': if (*p) - buf = be_snarf_file (p, buf, &bufmax, &buflen, 1); + { + strncpy(tmp, p, sizeof(tmp)); + mutt_expand_path(tmp, sizeof(tmp)); + buf = be_snarf_file (tmp, buf, &bufmax, &buflen, 1); + } else addstr ("missing filename.\n"); break; @@ -400,7 +404,7 @@ int mutt_builtin_editor (const char *path, HEADER *msg, HEADER *cur) buflen--; strfcpy (tmp, buf[buflen], sizeof (tmp)); tmp[strlen (tmp)-1] = 0; - free (buf[buflen]); + FREE (&buf[buflen]); buf[buflen] = NULL; continue; } @@ -417,9 +421,9 @@ int mutt_builtin_editor (const char *path, HEADER *msg, HEADER *cur) bufmax = buflen = 0; if (option (OPTEDITHDRS)) - mutt_edit_headers (Visual, path, msg, NULL, 0); + mutt_edit_headers (NONULL(Visual), path, msg, NULL, 0); else - mutt_edit_file (Visual, path); + mutt_edit_file (NONULL(Visual), path); buf = be_snarf_file (path, buf, &bufmax, &buflen, 0); diff --git a/enter.c b/enter.c index b575db04..f9968b2c 100644 --- a/enter.c +++ b/enter.c @@ -20,6 +20,7 @@ #include "mutt_menu.h" #include "mutt_curses.h" #include "keymap.h" +#include "history.h" #include <termios.h> #include <sys/types.h> @@ -33,89 +34,6 @@ /* macro to print control chars in reverse-video */ #define ADDCH(x) addch (IsPrint (x) ? x : (ColorDefs[MT_COLOR_MARKERS] | (x + '@'))) -/* global vars used for the string-history routines */ -static char **Hist = NULL; -static short HistCur = 0; -static short HistLast = 0; - -void mutt_init_history (void) -{ - int i; - static int OldSize = 0; - - if (Hist) - { - for (i = 0 ; i < OldSize ; i ++) - safe_free ((void **) &Hist[i]); - safe_free ((void **) &Hist); - } - - if (HistSize) - Hist = safe_calloc (HistSize, sizeof (char *)); - HistCur = 0; - HistLast = 0; - OldSize = HistSize; -} - -static void sh_add (char *s) -{ - int prev; - - if (!HistSize) - return; /* disabled */ - - if (*s) - { - prev = HistLast - 1; - if (prev < 0) prev = HistSize - 1; - if (!Hist[prev] || strcmp (Hist[prev], s) != 0) - { - safe_free ((void **) &Hist[HistLast]); - Hist[HistLast++] = safe_strdup (s); - if (HistLast > HistSize - 1) - HistLast = 0; - } - } - HistCur = HistLast; /* reset to the last entry */ -} - -static char *sh_next (void) -{ - int next; - - if (!HistSize) - return (""); /* disabled */ - - next = HistCur + 1; - if (next > HistLast - 1) - next = 0; - if (Hist[next]) - HistCur = next; - return (Hist[HistCur] ? Hist[HistCur] : ""); -} - -static char *sh_prev (void) -{ - int prev; - - if (!HistSize) - return (""); /* disabled */ - - prev = HistCur - 1; - if (prev < 0) - { - prev = HistLast - 1; - if (prev < 0) - { - prev = HistSize - 1; - while (prev > 0 && Hist[prev] == NULL) - prev--; - } - } - if (Hist[prev]) - HistCur = prev; - return (Hist[HistCur] ? Hist[HistCur] : ""); -} /* redraw flags for mutt_enter_string() */ enum @@ -145,6 +63,16 @@ int mutt_enter_string (unsigned char *buf, size_t buflen, int y, int x, int first = 1; int j; char tempbuf[_POSIX_PATH_MAX] = ""; + history_class_t hclass; + + if(flags & (M_FILE | M_EFILE)) + hclass = HC_FILE; + else if(flags & M_CMD) + hclass = HC_CMD; + else if(flags & M_ALIAS) + hclass = HC_ALIAS; + else + hclass = HC_OTHER; FOREVER { @@ -197,14 +125,14 @@ int mutt_enter_string (unsigned char *buf, size_t buflen, int y, int x, case OP_EDITOR_HISTORY_UP: if (!pass) { - strfcpy ((char *) buf, sh_prev (), buflen); + strfcpy ((char *) buf, mutt_history_prev (hclass), buflen); redraw = M_REDRAW_INIT; } break; case OP_EDITOR_HISTORY_DOWN: if (!pass) { - strfcpy ((char *) buf, sh_next (), buflen); + strfcpy ((char *) buf, mutt_history_next (hclass), buflen); redraw = M_REDRAW_INIT; } break; @@ -433,7 +361,7 @@ int mutt_enter_string (unsigned char *buf, size_t buflen, int y, int x, if (buf[0]) { mutt_pretty_mailbox ((char *) buf); - sh_add ((char *) buf); + mutt_history_add (hclass, (char *) buf); return (0); } return (-1); @@ -500,7 +428,7 @@ self_insert: { buf[lastchar] = 0; if (!pass) - sh_add ((char *) buf); + mutt_history_add (hclass, (char *) buf); return (0); } else if ((ch < ' ' || IsPrint (ch)) && (lastchar + 1 < buflen)) diff --git a/from.c b/from.c index 4279f9a8..f5d29749 100644 --- a/from.c +++ b/from.c @@ -62,7 +62,8 @@ time_t is_from (const char *s, char *path, size_t pathlen) struct tm tm; int yr; - *path = 0; + if (path) + *path = 0; if (strncmp ("From ", s, 5) != 0) return 0; @@ -102,11 +103,14 @@ time_t is_from (const char *s, char *path, size_t pathlen) if ((p = strchr (s, ' ')) == NULL) return 0; } - len = (size_t) (p - s); - if (len + 1 > pathlen) - len = pathlen - 1; - memcpy (path, s, len); - path[len] = 0; + if (path) + { + len = (size_t) (p - s); + if (len + 1 > pathlen) + len = pathlen - 1; + memcpy (path, s, len); + path[len] = 0; + } s = p + 1; SKIPWS (s); @@ -156,7 +160,7 @@ time_t is_from (const char *s, char *path, size_t pathlen) if (!*s) return 0; /* timezone? */ - if (isalpha (*s) || *s == '+' || *s == '-') + if (isalpha ((unsigned char) *s) || *s == '+' || *s == '-') { s = next_word (s); if (!*s) return 0; @@ -165,7 +169,7 @@ time_t is_from (const char *s, char *path, size_t pathlen) * some places have two timezone fields after the time, e.g. * From xxxx@yyyyyyy.fr Wed Aug 2 00:39:12 MET DST 1995 */ - if (isalpha (*s)) + if (isalpha ((unsigned char) *s)) { s = next_word (s); if (!*s) return 0; diff --git a/functions.h b/functions.h index f8a1af17..7877f3e2 100644 --- a/functions.h +++ b/functions.h @@ -307,6 +307,7 @@ struct binding_t OpAttach[] = { struct binding_t OpCompose[] = { { "attach-file", OP_COMPOSE_ATTACH_FILE, "a" }, + { "attach-message", OP_COMPOSE_ATTACH_MESSAGE, "A" }, { "edit-bcc", OP_COMPOSE_EDIT_BCC, "b" }, { "edit-cc", OP_COMPOSE_EDIT_CC, "c" }, { "copy-file", OP_SAVE, "C" }, @@ -332,6 +333,7 @@ struct binding_t OpCompose[] = { { "edit-to", OP_COMPOSE_EDIT_TO, "t" }, { "edit-type", OP_COMPOSE_EDIT_TYPE, "\024" }, { "toggle-unlink", OP_COMPOSE_TOGGLE_UNLINK, "u" }, + { "update-encoding", OP_COMPOSE_UPDATE_ENCODING, "U" }, { "view-attach", OP_VIEW_ATTACH, M_ENTER_S }, { "send-message", OP_COMPOSE_SEND_MESSAGE, "y" }, { "pipe-entry", OP_PIPE, "|" }, @@ -358,7 +360,9 @@ struct binding_t OpBrowser[] = { { "sort", OP_SORT, "o" }, { "sort-reverse", OP_SORT_REVERSE, "O" }, { "select-new", OP_BROWSER_NEW_FILE, "N" }, - { "check-new", OP_CHECK_NEW, "\t" }, + { "check-new", OP_CHECK_NEW, NULL }, + { "toggle-mailboxes", OP_TOGGLE_MAILBOXES, "\t" }, + { "view-file", OP_BROWSER_VIEW_FILE, " " }, { NULL, 0, NULL } }; diff --git a/globals.h b/globals.h index d01f4666..9854d0f8 100644 --- a/globals.h +++ b/globals.h @@ -24,7 +24,9 @@ WHERE char Errorbuf[SHORT_STRING]; WHERE char *AliasFile; WHERE char *AliasFmt; +WHERE char *AttachSep; WHERE char *Attribution; +WHERE char *AttachFormat; WHERE char *Charset; WHERE char *DefaultHook; WHERE char *DateFmt; @@ -32,7 +34,6 @@ WHERE char *DeleteFmt; WHERE char *DsnNotify; WHERE char *DsnReturn; WHERE char *Editor; -WHERE char *EmptyTo; WHERE char *EscChar; WHERE char *FolderFormat; WHERE char *ForwFmt; @@ -121,16 +122,11 @@ WHERE FILE *debugfile INITVAL (0); WHERE int debuglevel INITVAL (0); #endif -#ifdef USE_SETGID -WHERE gid_t MailGid; -WHERE gid_t UserGid; -#endif /* USE_SETGID */ - #ifdef MAIN_C const char *Weekdays[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; const char *Months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", "ERR" }; -const char *BodyTypes[] = { "x-unknown", "audio", "application", "image", "message", "multipart", "text", "video" }; +const char *BodyTypes[] = { "x-unknown", "audio", "application", "image", "message", "model", "multipart", "text", "video" }; const char *BodyEncodings[] = { "x-unknown", "7bit", "8bit", "quoted-printable", "base64", "binary" }; #else extern const char *Weekdays[]; diff --git a/handler.c b/handler.c index 15a0ca99..0ab05b6e 100644 --- a/handler.c +++ b/handler.c @@ -65,74 +65,127 @@ int Index_64[128] = { void mutt_decode_xbit (STATE *s, long len, int istext) { - int linelen; - char buffer[LONG_STRING]; - + int c; + int lbreak = 1; + if (istext) { - while (len > 0) + while ((c = fgetc(s->fpin)) != EOF && len--) { - if (fgets (buffer, LONG_STRING, s->fpin) == 0) return; - linelen = strlen (buffer); - len -= linelen; - if (linelen >= 2 && buffer[linelen-2] == '\r') + if(lbreak && s->prefix) { - buffer[linelen-2] = '\n'; - buffer[linelen-1] = 0; + state_puts(s->prefix, s); + lbreak = 0; } - if (s->prefix) state_puts (s->prefix, s); - state_puts (buffer, s); + + if (c == '\r' && len) + { + int ch; + + if((ch = fgetc(s->fpin)) != '\n') + ungetc(ch, s->fpin); + else + { + c = ch; + len--; + } + + } + fputc(c, s->fpout); + if(c == '\n') + lbreak = 1; } } else mutt_copy_bytes (s->fpin, s->fpout, len); } +static int handler_state_fgetc(STATE *s) +{ + int ch; + + if((ch = fgetc(s->fpin)) == EOF) + { + dprint(1, (debugfile, "handler_state_fgetc: unexpected EOF.\n")); + state_puts ("[-- Error: unexpected end of file! --]\n", s); + } + return ch; +} + void mutt_decode_quoted (STATE *s, long len, int istext) { - char *c, buffer[LONG_STRING]; - int ch, soft = 0; + int ch, lbreak = 1; while (len > 0) { - if (fgets (buffer, LONG_STRING, s->fpin) == NULL) - { - dprint (1, (debugfile, "mutt_decode_quoted: unexpected EOF.\n")); - state_puts ("[-- Error: unexpected end of file! --]\n", s); + if ((ch = handler_state_fgetc(s)) == EOF) break; - } - c = buffer; - len -= strlen (buffer); - if (s->prefix && !soft) state_puts (s->prefix, s); - soft = 0; - while (*c) + + len--; + + if (s->prefix && lbreak) + state_puts (s->prefix, s); + + lbreak = 0; + if (ch == '=') { - if (*c == '=') + int ch1, ch2; + + if(!len || (ch1 = handler_state_fgetc(s)) == EOF) + break; + + len--; + + if (ch1 == '\n' || ch1 == '\r' || ch1 == ' ' || ch1 == '\t') { - if (c[1] == '\n' || c[1] == '\r' || c[1] == ' ' || c[1] == '\t') + /* Skip whitespace at the end of the line since MIME does not + * allow for it + */ + if(ch1 != '\n') { - /* Skip whitespace at the end of the line since MIME does not - * allow for it - */ - soft = 1; - break; - } - ch = hexval ((int) c[1]) << 4; - ch |= hexval ((int) c[2]); - state_putc (ch, s); - c += 3; + while(len && (ch1 = handler_state_fgetc(s)) != EOF) + { + len--; + if(ch1 == '\n') + break; + } + } + + if(ch1 == EOF) + break; + + ch = EOF; + } - else if (istext && c[0] == '\r' && c[1] == '\n') + else { - state_putc ('\n', s); - break; + if(!len || (ch2 = handler_state_fgetc(s)) == EOF) + break; + + len--; + + ch = hexval (ch1) << 4; + ch |= hexval (ch2); } - else + } /* ch == '=' */ + else if (istext && ch == '\r') + { + int ch1; + + if((ch1 =fgetc(s->fpin)) == '\n') { - state_putc (*c, s); - c++; + ch = ch1; + len--; } + else + ungetc(ch1, s->fpin); } + + if(ch != EOF) + state_putc (ch, s); + + if(ch == '\n') + lbreak = 1; } } @@ -157,8 +210,8 @@ void mutt_decode_base64 (STATE *s, long len, int istext) if (i != 4) return; /* didn't get a multiple of four chars! */ - c1 = base64val ((int) buf[0]); - c2 = base64val ((int) buf[1]); + c1 = base64val (buf[0]); + c2 = base64val (buf[1]); ch = (c1 << 2) | (c2 >> 4); if (cr && ch != '\n') state_putc ('\r', s); @@ -174,7 +227,7 @@ void mutt_decode_base64 (STATE *s, long len, int istext) if (buf[2] == '=') break; - c3 = base64val ((int) buf[2]); + c3 = base64val (buf[2]); ch = ((c2 & 0xf) << 4) | (c3 >> 2); if (cr && ch != '\n') @@ -191,7 +244,7 @@ void mutt_decode_base64 (STATE *s, long len, int istext) } if (buf[3] == '=') break; - c4 = base64val ((int) buf[3]); + c4 = base64val (buf[3]); ch = ((c3 & 0x3) << 6) | c4; if (cr && ch != '\n') @@ -655,6 +708,7 @@ void text_enriched_handler (BODY *a, STATE *s) case ST_EOF : enriched_putc ('\0', &stte); + enriched_flush (&stte, 1); state = DONE; break; @@ -665,10 +719,9 @@ void text_enriched_handler (BODY *a, STATE *s) state_putc ('\n', s); /* add a final newline */ - if (stte.buffer) - free (stte.buffer); - free (stte.line); - free (stte.param); + FREE (&(stte.buffer)); + FREE (&(stte.line)); + FREE (&(stte.param)); } #define TXTPLAIN 1 @@ -700,14 +753,14 @@ void alternative_handler (BODY *a, STATE *s) if (!strchr(t->data, '/') || (i > 0 && t->data[i-1] == '/' && t->data[i] == '*')) { - if (!strcasecmp(t->data, TYPE(b->type))) + if (!strcasecmp(t->data, TYPE(b))) { choice = b; } } else { - snprintf (buf, sizeof (buf), "%s/%s", TYPE (b->type), b->subtype); + snprintf (buf, sizeof (buf), "%s/%s", TYPE (b), b->subtype); if (!strcasecmp(t->data, buf)) { choice = b; @@ -724,7 +777,7 @@ void alternative_handler (BODY *a, STATE *s) b = a; while (b && !choice) { - snprintf (buf, sizeof (buf), "%s/%s", TYPE (b->type), b->subtype); + snprintf (buf, sizeof (buf), "%s/%s", TYPE (b), b->subtype); if (mutt_is_autoview (buf)) { rfc1524_entry *entry = rfc1524_new_entry (); @@ -844,7 +897,7 @@ int mutt_can_decode (BODY *a) { char type[STRING]; - snprintf (type, sizeof (type), "%s/%s", TYPE (a->type), a->subtype); + snprintf (type, sizeof (type), "%s/%s", TYPE (a), a->subtype); if (mutt_is_autoview (type)) return (rfc1524_mailcap_lookup (a, type, NULL, M_AUTOVIEW)); else if (a->type == TYPETEXT) @@ -932,7 +985,7 @@ void multipart_handler (BODY *a, STATE *s) snprintf (buffer, sizeof (buffer), "[-- Type: %s/%s, Encoding: %s, Size: %s --]\n", - TYPE (p->type), p->subtype, ENCODING (p->encoding), length); + TYPE (p), p->subtype, ENCODING (p->encoding), length); state_puts (buffer, s); if (!option (OPTWEED)) { @@ -971,16 +1024,20 @@ void autoview_handler (BODY *a, STATE *s) char type[STRING]; char command[LONG_STRING]; char tempfile[_POSIX_PATH_MAX] = ""; + char *fname; FILE *fpin = NULL; FILE *fpout = NULL; FILE *fperr = NULL; int piped = FALSE; pid_t thepid; - snprintf (type, sizeof (type), "%s/%s", TYPE (a->type), a->subtype); + snprintf (type, sizeof (type), "%s/%s", TYPE (a), a->subtype); rfc1524_mailcap_lookup (a, type, entry, M_AUTOVIEW); - rfc1524_expand_filename (entry->nametemplate, a->filename, tempfile, sizeof (tempfile)); + fname = safe_strdup (a->filename); + mutt_sanitize_filename (fname); + rfc1524_expand_filename (entry->nametemplate, fname, tempfile, sizeof (tempfile)); + FREE (&fname); if (entry->command) { @@ -1104,7 +1161,7 @@ void mutt_body_handler (BODY *b, STATE *s) /* first determine which handler to use to process this part */ - snprintf (type, sizeof (type), "%s/%s", TYPE (b->type), b->subtype); + snprintf (type, sizeof (type), "%s/%s", TYPE (b), b->subtype); if (mutt_is_autoview (type)) { rfc1524_entry *entry = rfc1524_new_entry (); @@ -1129,7 +1186,7 @@ void mutt_body_handler (BODY *b, STATE *s) } else if (b->type == TYPEMESSAGE) { - if (!strcasecmp ("rfc822", b->subtype) || !strcasecmp ("news", b->subtype)) + if(mutt_is_message_type(b->type, b->subtype)) handler = message_handler; else if (!strcasecmp ("delivery-status", b->subtype)) plaintext = 1; @@ -1275,7 +1332,7 @@ void mutt_body_handler (BODY *b, STATE *s) } else if (s->flags & M_DISPLAY) { - fprintf (s->fpout, "[-- %s/%s is unsupported ", TYPE (b->type), b->subtype); + fprintf (s->fpout, "[-- %s/%s is unsupported ", TYPE (b), b->subtype); if (!option (OPTVIEWATTACH)) { if (km_expand_key (type, sizeof(type), diff --git a/hash.c b/hash.c index f670eb4a..efd63a6f 100644 --- a/hash.c +++ b/hash.c @@ -44,9 +44,11 @@ HASH *hash_create (int nelem) allow_dup if nonzero, duplicate keys are allowed in the table */ int hash_insert (HASH * table, const char *key, void *data, int allow_dup) { - struct hash_elem *ptr = malloc (sizeof (struct hash_elem)); - int h = hash_string ((unsigned char *) key, table->nelem); + struct hash_elem *ptr; + int h; + ptr = (struct hash_elem *) safe_malloc (sizeof (struct hash_elem)); + h = hash_string ((unsigned char *) key, table->nelem); ptr->key = key; ptr->data = data; @@ -65,7 +67,7 @@ int hash_insert (HASH * table, const char *key, void *data, int allow_dup) r = strcmp (tmp->key, key); if (r == 0) { - free (ptr); + FREE (&ptr); return (-1); } if (r > 0) @@ -109,9 +111,7 @@ void hash_delete_hash (HASH * table, int hash, const char *key, const void *data table->table[hash] = ptr->next; if (destroy) destroy (ptr->data); - memset (ptr, 0, sizeof (struct hash_elem)); - free (ptr); - ptr = 0; + FREE (&ptr); return; } } diff --git a/hdrline.c b/hdrline.c index 5f8ddf9d..2e9710b9 100644 --- a/hdrline.c +++ b/hdrline.c @@ -45,6 +45,10 @@ int mutt_is_mail_list (ADDRESS *addr) return 0; } +/* Search for a mailing list in the list of addresses pointed to by adr. + * If one is found, print pfx and the name of the list into buf, then + * return 1. Otherwise, simply return 0. + */ static int check_for_mailing_list (ADDRESS *adr, char *pfx, char *buf, int buflen) { @@ -60,6 +64,26 @@ check_for_mailing_list (ADDRESS *adr, char *pfx, char *buf, int buflen) return 0; } +/* Search for a mailing list in the list of addresses pointed to by adr. + * If one is found, print the address of the list into buf, then return 1. + * Otherwise, simply return 0. + */ +static int +check_for_mailing_list_addr (ADDRESS *adr, char *buf, int buflen) +{ + for (; adr; adr = adr->next) + { + if (mutt_is_mail_list (adr)) + { + if (buf && buflen) + snprintf (buf, buflen, "%s", adr->mailbox); + return 1; + } + } + return 0; +} + + static int first_mailing_list (char *buf, size_t buflen, ADDRESS *a) { for (; a; a = a->next) @@ -97,6 +121,30 @@ static void make_from (ENVELOPE *hdr, char *buf, size_t len, int do_lists) *buf = 0; } +static void make_from_addr (ENVELOPE *hdr, char *buf, size_t len, int do_lists) +{ + int me; + + me = mutt_addr_is_user (hdr->from); + + if (do_lists || me) + { + if (check_for_mailing_list_addr (hdr->to, buf, len)) + return; + if (check_for_mailing_list_addr (hdr->cc, buf, len)) + return; + } + + if (me && hdr->to) + snprintf (buf, len, "%s", hdr->to->mailbox); + else if (me && hdr->cc) + snprintf (buf, len, "%s", hdr->cc->mailbox); + else if (hdr->from) + strfcpy (buf, hdr->from->mailbox, len); + else + *buf = 0; +} + int mutt_user_is_recipient (ADDRESS *a) { for (; a; a = a->next) @@ -145,6 +193,7 @@ static int user_is_recipient (ENVELOPE *hdr) * %m = number of messages in the mailbox * %n = name of author * %N = score + * %O = like %L, except using address instead of name * %s = subject * %S = short message status (e.g., N/O/D/!/r/-) * %t = `to:' field (recipients) @@ -206,11 +255,11 @@ hdr_format_str (char *dest, strfcpy (dest, p + 1, destlen); else strfcpy (dest, ctx->path, destlen); - break; } else strfcpy(dest, "(null)", destlen); - + break; + case 'c': mutt_pretty_size (buf2, sizeof (buf2), (long) hdr->content->length); snprintf (fmt, sizeof (fmt), "%%%ss", prefix); @@ -259,7 +308,7 @@ hdr_format_str (char *dest, { if (len >= 5) { - sprintf (p, "%c%02d%02d", hdr->zoccident ? '-' : '+', + sprintf (p, "%c%02u%02u", hdr->zoccident ? '-' : '+', hdr->zhours, hdr->zminutes); p += 5; len -= 5; @@ -380,6 +429,22 @@ hdr_format_str (char *dest, snprintf (dest, destlen, fmt, hdr->score); break; + case 'O': + if (!optional) + { + make_from_addr (hdr->env, buf2, sizeof (buf2), 1); + if (!option (OPTSAVEADDRESS) && (p = strpbrk (buf2, "%@"))) + *p = 0; + snprintf (fmt, sizeof (fmt), "%%%ss", prefix); + snprintf (dest, destlen, fmt, buf2); + } + else if (!check_for_mailing_list_addr (hdr->env->to, NULL, 0) && + !check_for_mailing_list_addr (hdr->env->cc, NULL, 0)) + { + optional = 0; + } + break; + case 's': snprintf (fmt, sizeof (fmt), "%%%ss", prefix); if (flags & M_FORMAT_TREE) diff --git a/headers.c b/headers.c index b718eaf1..c9bc49b2 100644 --- a/headers.c +++ b/headers.c @@ -189,7 +189,7 @@ void mutt_edit_headers (const char *editor, else strfcpy (path, p, sizeof (path)); mutt_expand_path (path, sizeof (path)); - if ((body = mutt_make_attach (path))) + if ((body = mutt_make_file_attach (path))) { body->description = safe_strdup (q); for (parts = msg->content; parts->next; parts = parts->next) ; diff --git a/help.c b/help.c index fa79b4ce..d1a29a91 100644 --- a/help.c +++ b/help.c @@ -84,11 +84,11 @@ mutt_compile_help (char *buf, size_t buflen, int menu, struct mapping_t *items) return buf; } -static void print_macro (FILE *f, const char *macro) +static int print_macro (FILE *f, int maxchar, const char *macro) { int i; - for (i = 0; *macro && i < COLS - 34; macro++, i++) + for (i = 0; *macro && i < maxchar; macro++, i++) { switch (*macro) { @@ -113,6 +113,25 @@ static void print_macro (FILE *f, const char *macro) break; } } + return (i); +} + +static int pad (FILE *f, int col, int i) +{ + char fmt[8]; + + if (i < col) + { + snprintf (fmt, sizeof(fmt), "%%-%ds", col - i); + fprintf (f, fmt, ""); + i = col; + } + else + { + fputc (' ', f); + ++i; + } + return (i); } static void dump_menu (FILE *f, int menu) @@ -120,24 +139,51 @@ static void dump_menu (FILE *f, int menu) struct keymap_t *map; struct binding_t *b; char buf[SHORT_STRING]; + int col; /* browse through the keymap table */ for (map = Keymaps[menu]; map; map = map->next) { - km_expand_key (buf, sizeof (buf), map); - - if (map->op == OP_MACRO) - { - fprintf (f, "%s\t%-20s\t", buf, "macro"); - print_macro (f, map->macro); - fputc ('\n', f); - } - else if (map->op != OP_NULL) + if (map->op != OP_NULL) { - b = help_lookupFunction (map->op, menu); - fprintf (f, "%s\t%-20s\t%s\n", buf, - b ? b->name : "UNKNOWN", + km_expand_key (buf, sizeof (buf), map); + fputs (buf, f); + col = pad (f, 12, strlen (buf)); + + if (map->op == OP_MACRO) + { + if (map->descr == NULL) + { + fputs ("macro ", f); + col = pad (f, 35, col + 6); + print_macro (f, COLS - col, map->macro); + } + else + { + fputs ("macro: ", f); + col += 7; + if (strlen (map->macro) < (34 - col)) + { + col += print_macro (f, 34 - col, map->macro); + col = pad (f, 35, col); + } + else + { + if (col < 31) + col += print_macro (f, 31 - col, map->macro); + fputs ("... ", f); + col += 4; + } + print_macro (f, COLS - col, map->descr); + } + fputc ('\n', f); + } + else + { + b = help_lookupFunction (map->op, menu); + fprintf (f, "%-22s %s\n", b ? b->name : "UNKNOWN", b ? HelpStrings[b->op] : "ERROR: please report this bug"); + } } } } @@ -161,7 +207,7 @@ static void dump_unbound (FILE *f, { if (! is_bound (map, funcs[i].op) && (!aux || ! is_bound (aux, funcs[i].op))) - fprintf (f, "%s\t\t%s\n", funcs[i].name, HelpStrings[funcs[i].op]); + fprintf (f, "%-35s%s\n", funcs[i].name, HelpStrings[funcs[i].op]); } } diff --git a/history.c b/history.c new file mode 100644 index 00000000..53fe0890 --- /dev/null +++ b/history.c @@ -0,0 +1,126 @@ +/* + * Copyright (C) 1996-8 Michael R. Elkins <me@cs.hmc.edu> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "mutt.h" +#include "history.h" + +/* global vars used for the string-history routines */ + +struct history +{ + char **hist; + short cur; + short last; +}; + +static struct history History[HC_LAST]; +static int OldSize = 0; + +static void init_history (struct history *h) +{ + int i; + + if(OldSize) + { + if (h->hist) + { + for (i = 0 ; i < OldSize ; i ++) + safe_free ((void **) &h->hist[i]); + safe_free ((void **) &h->hist); + } + } + + if (HistSize) + h->hist = safe_calloc (HistSize, sizeof (char *)); + + h->cur = 0; + h->last = 0; +} + +void mutt_init_history(void) +{ + history_class_t hclass; + + for(hclass = HC_FIRST; hclass < HC_LAST; hclass++) + init_history(&History[hclass]); + + OldSize = HistSize; +} + +void mutt_history_add (history_class_t hclass, const char *s) +{ + int prev; + struct history *h = &History[hclass]; + + if (!HistSize) + return; /* disabled */ + + if (*s) + { + prev = h->last - 1; + if (prev < 0) prev = HistSize - 1; + if (!h->hist[prev] || strcmp (h->hist[prev], s) != 0) + { + safe_free ((void **) &h->hist[h->last]); + h->hist[h->last++] = safe_strdup (s); + if (h->last > HistSize - 1) + h->last = 0; + } + } + h->cur = h->last; /* reset to the last entry */ +} + +char *mutt_history_next (history_class_t hclass) +{ + int next; + struct history *h = &History[hclass]; + + if (!HistSize) + return (""); /* disabled */ + + next = h->cur + 1; + if (next > h->last - 1) + next = 0; + if (h->hist[next]) + h->cur = next; + return (h->hist[h->cur] ? h->hist[h->cur] : ""); +} + +char *mutt_history_prev (history_class_t hclass) +{ + int prev; + struct history *h = &History[hclass]; + + if (!HistSize) + return (""); /* disabled */ + + prev = h->cur - 1; + if (prev < 0) + { + prev = h->last - 1; + if (prev < 0) + { + prev = HistSize - 1; + while (prev > 0 && h->hist[prev] == NULL) + prev--; + } + } + if (h->hist[prev]) + h->cur = prev; + return (h->hist[h->cur] ? h->hist[h->cur] : ""); +} diff --git a/history.h b/history.h new file mode 100644 index 00000000..94af71d0 --- /dev/null +++ b/history.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 1996-8 Michael R. Elkins <me@cs.hmc.edu> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _HISTORY_H +#define _HISTORY_H + +enum history_class +{ + HC_CMD, + HC_ALIAS, + HC_COMMAND, + HC_FILE, + HC_OTHER, + HC_LAST +}; + +#define HC_FIRST HC_CMD + +typedef enum history_class history_class_t; + +void mutt_init_history(void); +void mutt_history_add(history_class_t, const char *); +char *mutt_history_next(history_class_t); +char *mutt_history_prev(history_class_t); + +#endif diff --git a/hook.c b/hook.c index be7e516e..259c2352 100644 --- a/hook.c +++ b/hook.c @@ -84,7 +84,11 @@ int mutt_parse_hook (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err) memset (&pattern, 0, sizeof (pattern)); pattern.data = safe_strdup (path); } - else if (DefaultHook) + else if (DefaultHook +#ifdef _PGPPATH + && !(data & M_PGPHOOK) +#endif /* _PGPPATH */ + ) { char tmp[HUGE_STRING]; @@ -148,7 +152,11 @@ int mutt_parse_hook (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err) else { rx = safe_malloc (sizeof (regex_t)); +#ifdef _PGPPATH + if ((rc = REGCOMP (rx, pattern.data, ((data & M_PGPHOOK) ? REG_ICASE : 0))) != 0) +#else if ((rc = REGCOMP (rx, pattern.data, 0)) != 0) +#endif /* _PGPPATH */ { regerror (rc, rx, err->data, err->dsize); regfree (rx); @@ -188,6 +196,10 @@ void mutt_folder_hook (char *path) err.dsize = sizeof (buf); memset (&token, 0, sizeof (token)); for (; tmp; tmp = tmp->next) + { + if(!tmp->command) + continue; + if (tmp->type & M_FOLDERHOOK) { if ((regexec (tmp->rx.rx, path, 0, NULL, 0) == 0) ^ tmp->rx.not) @@ -201,6 +213,7 @@ void mutt_folder_hook (char *path) } } } + } FREE (&token.data); } @@ -227,6 +240,10 @@ void mutt_send_hook (HEADER *hdr) err.dsize = sizeof (buf); memset (&token, 0, sizeof (token)); for (hook = Hooks; hook; hook = hook->next) + { + if(!hook->command) + continue; + if (hook->type & M_SENDHOOK) if ((mutt_pattern_exec (hook->pattern, 0, NULL, hdr) > 0) ^ hook->rx.not) if (mutt_parse_rc_line (hook->command, &token, &err) != 0) @@ -236,6 +253,7 @@ void mutt_send_hook (HEADER *hdr) sleep (1); return; } + } FREE (&token.data); } @@ -246,12 +264,17 @@ mutt_addr_hook (char *path, size_t pathlen, int type, CONTEXT *ctx, HEADER *hdr) /* determine if a matching hook exists */ for (hook = Hooks; hook; hook = hook->next) + { + if(!hook->command) + continue; + if (hook->type & type) if ((mutt_pattern_exec (hook->pattern, 0, ctx, hdr) > 0) ^ hook->rx.not) { mutt_make_string (path, pathlen, hook->command, ctx, hdr); return 0; } + } return -1; } @@ -306,3 +329,19 @@ void mutt_select_fcc (char *path, size_t pathlen, HEADER *hdr) } mutt_pretty_mailbox (path); } + +#ifdef _PGPPATH +char *mutt_pgp_hook (ADDRESS *adr) +{ + HOOK *tmp = Hooks; + + for (; tmp; tmp = tmp->next) + { + if ((tmp->type & M_PGPHOOK) && ((adr->mailbox && + regexec (tmp->rx.rx, adr->mailbox, 0, NULL, 0) == 0) ^ tmp->rx.not)) + return (tmp->command); + } + return (NULL); +} +#endif /* _PGPPATH */ + diff --git a/imap.c b/imap.c index 872e019b..34440247 100644 --- a/imap.c +++ b/imap.c @@ -21,6 +21,7 @@ #include "mx.h" #include "mailbox.h" #include "globals.h" +#include "mutt_socket.h" #include <unistd.h> #include <netinet/in.h> @@ -47,30 +48,18 @@ enum IMAP_NEW_MAIL, IMAP_EXPUNGE, IMAP_BYE, - IMAP_OK_FAIL, - IMAP_OPEN_NEW + IMAP_OK_FAIL }; typedef struct { - char *server; - int uses; - int fd; - char inbuf[LONG_STRING]; - int bufpos; - int available; -} CONNECTION; - -typedef struct -{ - int index; + unsigned int index; char *path; } IMAP_CACHE; typedef struct { short status; - unsigned short sequence; unsigned short newMailCount; char *mailbox; short xxx; @@ -80,92 +69,35 @@ typedef struct #define CTX_DATA ((IMAP_DATA *) ctx->data) -static CONNECTION *Connections = NULL; -static int NumConnections = 0; - -/* simple read buffering to speed things up. */ -static int imap_readchar (CONNECTION *conn, char *c) -{ - if (conn->bufpos >= conn->available) - { - conn->available = read (conn->fd, conn->inbuf, sizeof(LONG_STRING)); - conn->bufpos = 0; - if (conn->available <= 0) - return conn->available; /* returns 0 for EOF or -1 for other error */ - } - *c = conn->inbuf[conn->bufpos]; - conn->bufpos++; - return 1; -} - -static int imap_read_line (char *buf, size_t buflen, CONNECTION *conn) +/* Linked list to hold header information while downloading message + * headers + */ +typedef struct imap_header_info { - char ch; - int i; + unsigned int read : 1; + unsigned int old : 1; + unsigned int deleted : 1; + unsigned int flagged : 1; + unsigned int replied : 1; + unsigned int changed : 1; - for (i = 0; i < buflen; i++) - { - if (imap_readchar (conn, &ch) != 1) - return (-1); - if (ch == '\n') - break; - buf[i] = ch; - } - buf[i-1] = 0; - return (i + 1); -} + time_t received; + long content_length; + struct imap_header_info *next; +} IMAP_HEADER_INFO; -static int imap_read_line_d (char *buf, size_t buflen, CONNECTION *conn) -{ - int r = imap_read_line (buf, buflen, conn); - dprint (1,(debugfile,"imap_read_line_d():%s\n", buf)); - return r; -} -static void imap_make_sequence (char *buf, size_t buflen, CONTEXT *ctx) +static void imap_make_sequence (char *buf, size_t buflen) { - snprintf (buf, buflen, "a%04d", CTX_DATA->sequence++); + static int sequence = 0; + + snprintf (buf, buflen, "a%04d", sequence++); } -static int imap_write (CONNECTION *conn, const char *buf) -{ - dprint (1,(debugfile,"imap_write():%s", buf)); - return (write (conn->fd, buf, strlen (buf))); -} static void imap_error (const char *where, const char *msg) { - dprint (1, (debugfile, "imap_error(): unexpected response in %s: %s\n", where, msg)); -} - -static CONNECTION *imap_select_connection (char *host, int flags) -{ - int x; - - if (flags != IMAP_OPEN_NEW) - { - for (x = 0; x < NumConnections; x++) - { - if (!strcmp (host, Connections[x].server)) - return &Connections[x]; - } - } - if (NumConnections == 0) - { - NumConnections = 1; - Connections = (CONNECTION *) safe_malloc (sizeof (CONNECTION)); - } - else - { - NumConnections++; - safe_realloc ((void *)Connections, sizeof (CONNECTION) * NumConnections); - } - Connections[NumConnections - 1].bufpos = 0; - Connections[NumConnections - 1].available = 0; - Connections[NumConnections - 1].uses = 0; - Connections[NumConnections - 1].server = safe_strdup (host); - - return &Connections[NumConnections - 1]; + mutt_error ("imap_error(): unexpected response in %s: %s\n", where, msg); } /* date is of the form: DD-MMM-YYYY HH:MM:SS +ZZzz */ @@ -216,7 +148,7 @@ static time_t imap_parse_date (char *s) return (mutt_mktime (&t, 0) + tz); } -static int imap_parse_fetch (HEADER *h, char *s) +static int imap_parse_fetch (IMAP_HEADER_INFO *h, char *s) { char tmp[SHORT_STRING]; char *ptmp; @@ -278,11 +210,11 @@ static int imap_parse_fetch (HEADER *h, char *s) while (isdigit (*s)) *ptmp++ = *s++; *ptmp = 0; - h->content->length += atoi (tmp); + h->content_length += atoi (tmp); } else if (*s == ')') s++; /* end of request */ - else + else if (*s) { /* got something i don't understand */ imap_error ("imap_parse_fetch()", s); @@ -334,7 +266,7 @@ static int imap_read_bytes (FILE *fp, CONNECTION *conn, long bytes) for (pos = 0; pos < bytes; ) { - len = imap_read_line (buf, sizeof (buf), conn); + len = mutt_socket_read_line (buf, sizeof (buf), conn); if (len < 0) return (-1); pos += len; @@ -426,102 +358,168 @@ static int imap_handle_untagged (CONTEXT *ctx, char *s) return 0; } -static int imap_read_header (CONTEXT *ctx, int msgno) +/* + * Changed to read many headers instead of just one. It will return the + * msgno of the last message read. It will return a value other than + * msgend if mail comes in while downloading headers (in theory). + */ +static int imap_read_headers (CONTEXT *ctx, int msgbegin, int msgend) { - char buf[LONG_STRING]; + char buf[LONG_STRING],fetchbuf[LONG_STRING]; FILE *fp; char tempfile[_POSIX_PATH_MAX]; char seq[8]; - char *pc; + char *pc,*fpc,*hdr; char *pn; + long ploc; long bytes = 0; + int msgno,fetchlast; + IMAP_HEADER_INFO *h0,*h,*htemp; - ctx->hdrs[ctx->msgcount]->index = ctx->msgcount; + fetchlast = 0; + /* + * We now download all of the headers into one file. This should be + * faster on most systems. + */ mutt_mktemp (tempfile); if (!(fp = safe_fopen (tempfile, "w+"))) { return (-1); } - imap_make_sequence (seq, sizeof (seq), ctx); - snprintf (buf, sizeof (buf), "%s FETCH %d RFC822.HEADER\r\n", seq, msgno + 1); - imap_write (CTX_DATA->conn, buf); - - do + h0=safe_malloc(sizeof(IMAP_HEADER_INFO)); + h=h0; + for (msgno=msgbegin; msgno <= msgend ; msgno++) { - if (imap_read_line_d (buf, sizeof (buf), CTX_DATA->conn) < 0) + snprintf (buf, sizeof (buf), "Fetching message headers... [%d/%d]", + msgno + 1, msgend + 1); + mutt_message (buf); + + if (msgno + 1 > fetchlast) { - return (-1); + imap_make_sequence (seq, sizeof (seq)); + /* + * Make one request for everything. This makes fetching headers an + * order of magnitude faster if you have a large mailbox. + * + * If we get more messages while doing this, we make another + * request for all the new messages. + */ + snprintf (buf, sizeof (buf), "%s FETCH %d:%d (FLAGS INTERNALDATE RFC822.SIZE BODY.PEEK[HEADER.FIELDS (DATE FROM SUBJECT TO CC MESSAGE-ID REFERENCES CONTENT-TYPE IN-REPLY-TO REPLY-TO)])\r\n", seq, msgno + 1, msgend + 1); + mutt_socket_write (CTX_DATA->conn, buf); + fetchlast = msgend + 1; } - if (buf[0] == '*') + do { - pc = buf; - pc = imap_next_word (pc); - pc = imap_next_word (pc); - if (strncasecmp ("FETCH", pc, 5) == 0) + if (mutt_socket_read_line_d (buf, sizeof (buf), CTX_DATA->conn) < 0) { - if (!(pc = strchr (pc, '{'))) - { - imap_error ("imap_read_header()", buf); - return (-1); - } - pc++; - pn = pc; - while (isdigit (*pc)) - pc++; - *pc = 0; - bytes = atoi (pn); + return (-1); + } - imap_read_bytes (fp, CTX_DATA->conn, bytes); + if (buf[0] == '*') + { + pc = buf; + pc = imap_next_word (pc); + pc = imap_next_word (pc); + if (strncasecmp ("FETCH", pc, 5) == 0) + { + if (!(pc = strchr (pc, '('))) + { + imap_error ("imap_read_headers()", buf); + return (-1); + } + pc++; + fpc=fetchbuf; + while (*pc != '\0' && *pc != ')') + { + hdr=strstr(pc,"BODY"); + strncpy(fpc,pc,hdr-pc); + fpc += hdr-pc; + *fpc = '\0'; + pc=hdr; + /* get some number of bytes */ + if (!(pc = strchr (pc, '{'))) + { + imap_error ("imap_read_headers()", buf); + return (-1); + } + pc++; + pn = pc; + while (isdigit (*pc)) + pc++; + *pc = 0; + bytes = atoi (pn); + + imap_read_bytes (fp, CTX_DATA->conn, bytes); + if (mutt_socket_read_line_d (buf, sizeof (buf), CTX_DATA->conn) < 0) + { + return (-1); + } + pc = buf; + } + } + else if (imap_handle_untagged (ctx, buf) != 0) + return (-1); } - else if (imap_handle_untagged (ctx, buf) != 0) - return (-1); } - } - while (strncmp (seq, buf, SEQLEN) != 0); - - rewind (fp); - ctx->hdrs[msgno]->env = mutt_read_rfc822_header (fp, ctx->hdrs[msgno]); + while ((msgno + 1) >= fetchlast && strncmp (seq, buf, SEQLEN) != 0); -/* subtract the header length; the total message size will be added to this */ - ctx->hdrs[msgno]->content->length = -bytes; + h->content_length = -bytes; + if (imap_parse_fetch (h, fetchbuf) == -1) + return (-1); - fclose (fp); - unlink (tempfile); + /* subtract the header length; the total message size will be + added to this */ - /* get the status of this message */ - imap_make_sequence (seq, sizeof (seq), ctx); - snprintf (buf, sizeof (buf), "%s FETCH %d FAST\r\n", seq, msgno + 1); - imap_write (CTX_DATA->conn, buf); - do - { - if (imap_read_line_d (buf, sizeof (buf), CTX_DATA->conn) < 0) - break; - if (buf[0] == '*') + /* in case we get new mail while fetching the headers */ + if (((IMAP_DATA *) ctx->data)->status == IMAP_NEW_MAIL) { - pc = buf; - pc = imap_next_word (pc); - pc = imap_next_word (pc); - if (strncasecmp ("FETCH", pc, 5) == 0) - { - if (!(pc = strchr (pc, '('))) - { - imap_error ("imap_read_header()", buf); - return (-1); - } - if (imap_parse_fetch (ctx->hdrs[msgno], pc + 1) != 0) - return (-1); - } - else if (imap_handle_untagged (ctx, buf) != 0) - return (-1); + msgend = ((IMAP_DATA *) ctx->data)->newMailCount - 1; + while ((msgend + 1) > ctx->hdrmax) + mx_alloc_memory (ctx); + ((IMAP_DATA *) ctx->data)->status = 0; } + + h->next=safe_malloc(sizeof(IMAP_HEADER_INFO)); + h=h->next; } - while (strncmp (seq, buf, SEQLEN) != 0) - ; - return 0; + rewind(fp); + h=h0; + + /* + * Now that we have all the header information, we can tell mutt about + * it. + */ + ploc=0; + for (msgno = msgbegin; msgno <= msgend;msgno++) + { + ctx->hdrs[ctx->msgcount] = mutt_new_header (); + ctx->hdrs[ctx->msgcount]->index = ctx->msgcount; + + ctx->hdrs[msgno]->env = mutt_read_rfc822_header (fp, ctx->hdrs[msgno]); + ploc=ftell(fp); + ctx->hdrs[msgno]->read = h->read; + ctx->hdrs[msgno]->old = h->old; + ctx->hdrs[msgno]->deleted = h->deleted; + ctx->hdrs[msgno]->flagged = h->flagged; + ctx->hdrs[msgno]->replied = h->replied; + ctx->hdrs[msgno]->changed = h->changed; + ctx->hdrs[msgno]->received = h->received; + ctx->hdrs[msgno]->content->length = h->content_length; + + mx_update_context(ctx); /* increments ->msgcount */ + + htemp=h; + h=h->next; + safe_free((void **) &htemp); + } + fclose(fp); + unlink(tempfile); + + return (msgend); } static int imap_exec (char *buf, size_t buflen, @@ -529,11 +527,11 @@ static int imap_exec (char *buf, size_t buflen, { int count; - imap_write (CTX_DATA->conn, cmd); + mutt_socket_write (CTX_DATA->conn, cmd); do { - if (imap_read_line_d (buf, buflen, CTX_DATA->conn) < 0) + if (mutt_socket_read_line_d (buf, buflen, CTX_DATA->conn) < 0) return (-1); if (buf[0] == '*' && imap_handle_untagged (ctx, buf) != 0) @@ -546,7 +544,6 @@ static int imap_exec (char *buf, size_t buflen, /* read new mail messages */ dprint (1, (debugfile, "imap_exec(): new mail detected\n")); - mutt_message ("Fetching headers for new mail..."); CTX_DATA->status = 0; @@ -554,23 +551,7 @@ static int imap_exec (char *buf, size_t buflen, while (count > ctx->hdrmax) mx_alloc_memory (ctx); - while (ctx->msgcount < count) - { - ctx->hdrs[ctx->msgcount] = mutt_new_header (); - imap_read_header (ctx, ctx->msgcount); - mx_update_context (ctx); /* incremements ->msgcount */ - - /* check to make sure that new mail hasn't arrived in the middle of - * checking for new mail (sigh) - */ - if (CTX_DATA->status == IMAP_NEW_MAIL) - { - count = CTX_DATA->newMailCount; - while (count > ctx->hdrmax) - mx_alloc_memory (ctx); - CTX_DATA->status = 0; - } - } + count=imap_read_headers (ctx, ctx->msgcount, count - 1) + 1; mutt_clear_error (); } @@ -593,8 +574,30 @@ static int imap_exec (char *buf, size_t buflen, return 0; } +static int imap_parse_path (char *path, char *host, size_t hlen, char **mbox) +{ + int n; + char *pc; + + pc = path; + if (*pc != '{') + return (-1); + pc++; + n = 0; + while (*pc && *pc != '}' && (n < hlen-1)) + host[n++] = *pc++; + host[n] = 0; + if (!*pc) + return (-1); + pc++; + + *mbox = pc; + return 0; +} + static int imap_open_connection (CONTEXT *ctx, CONNECTION *conn) { + char *portnum, *hostname; struct sockaddr_in sin; struct hostent *he; char buf[LONG_STRING]; @@ -602,40 +605,19 @@ static int imap_open_connection (CONTEXT *ctx, CONNECTION *conn) char pass[SHORT_STRING]; char seq[16]; - if (!ImapUser) - { - strfcpy (user, Username, sizeof (user)); - if (mutt_get_field ("IMAP Username: ", user, sizeof (user), 0) != 0 || - !user[0]) - { - user[0] = 0; - return (-1); - } - } - else - strfcpy (user, ImapUser, sizeof (user)); - - if (!ImapPass) - { - pass[0]=0; - snprintf (buf, sizeof (buf), "Password for %s@%s: ", user, conn->server); - if (mutt_get_field (buf, pass, sizeof (pass), M_PASS) != 0 || - !pass[0]) - { - return (-1); - } - } - else - strfcpy (pass, ImapPass, sizeof (pass)); - memset (&sin, 0, sizeof (sin)); - sin.sin_port = htons (IMAP_PORT); + hostname = safe_strdup(conn->server); + portnum = strrchr(hostname, ':'); + if(portnum) { *portnum=0; portnum++; } + sin.sin_port = htons (portnum ? atoi(portnum) : IMAP_PORT); sin.sin_family = AF_INET; - if ((he = gethostbyname (conn->server)) == NULL) + if ((he = gethostbyname (hostname)) == NULL) { + safe_free((void*)&hostname); mutt_perror (conn->server); return (-1); } + safe_free((void*)&hostname); memcpy (&sin.sin_addr, he->h_addr_list[0], he->h_length); if ((conn->fd = socket (AF_INET, SOCK_STREAM, IPPROTO_IP)) < 0) @@ -652,34 +634,60 @@ static int imap_open_connection (CONTEXT *ctx, CONNECTION *conn) close (conn->fd); } - if (imap_read_line_d (buf, sizeof (buf), conn) < 0) + if (mutt_socket_read_line_d (buf, sizeof (buf), conn) < 0) { close (conn->fd); return (-1); } - if (strncmp ("* OK", buf, 4) != 0) + if (strncmp ("* OK", buf, 4) == 0) { - imap_error ("imap_open_connection()", buf); - close (conn->fd); - return (-1); - } + if (!ImapUser) + { + strfcpy (user, NONULL(Username), sizeof (user)); + if (mutt_get_field ("IMAP Username: ", user, sizeof (user), 0) != 0 || + !user[0]) + { + user[0] = 0; + return (-1); + } + } + else + strfcpy (user, ImapUser, sizeof (user)); - mutt_message ("Logging in..."); - /* sequence numbers are currently context dependent, so just make one - * up for this first access to the server */ - strcpy (seq, "l0000"); - snprintf (buf, sizeof (buf), "%s LOGIN %s %s\r\n", seq, user, pass); - if (imap_exec (buf, sizeof (buf), ctx, seq, buf, 0) != 0) + if (!ImapPass) + { + pass[0]=0; + snprintf (buf, sizeof (buf), "Password for %s@%s: ", user, conn->server); + if (mutt_get_field (buf, pass, sizeof (pass), M_PASS) != 0 || + !pass[0]) + { + return (-1); + } + } + else + strfcpy (pass, ImapPass, sizeof (pass)); + + mutt_message ("Logging in..."); + imap_make_sequence (seq, sizeof (seq)); + snprintf (buf, sizeof (buf), "%s LOGIN %s %s\r\n", seq, user, pass); + if (imap_exec (buf, sizeof (buf), ctx, seq, buf, 0) != 0) + { + imap_error ("imap_open_connection()", buf); + return (-1); + } + /* If they have a successful login, we may as well cache the user/password. */ + if (!ImapUser) + ImapUser = safe_strdup (user); + if (!ImapPass) + ImapPass = safe_strdup (pass); + } + else if (strncmp ("* PREAUTH", buf, 9) != 0) { imap_error ("imap_open_connection()", buf); + close (conn->fd); return (-1); } - /* If they have a successful login, we may as well cache the user/password. */ - if (!ImapUser) - ImapUser = safe_strdup (user); - if (!ImapPass) - ImapPass = safe_strdup (pass); return 0; } @@ -691,29 +699,20 @@ int imap_open_mailbox (CONTEXT *ctx) char bufout[LONG_STRING]; char host[SHORT_STRING]; char seq[16]; + char *pc = NULL; int count = 0; int n; - char *pc; + + if (imap_parse_path (ctx->path, host, sizeof (host), &pc)) + return (-1); /* create IMAP-specific state struct */ ctx->data = safe_malloc (sizeof (IMAP_DATA)); memset (ctx->data, 0, sizeof (IMAP_DATA)); - pc = ctx->path; - if (*pc != '{') - return (-1); - pc++; - n = 0; - while (*pc && *pc != '}') - host[n++] = *pc++; - host[n] = 0; - if (!*pc) - return (-1); - pc++; - CTX_DATA->mailbox = safe_strdup (pc); - conn = imap_select_connection (host, IMAP_OPEN_NEW); + conn = mutt_socket_select_connection (host, IMAP_PORT, M_NEW_SOCKET); CTX_DATA->conn = conn; if (conn->uses == 0) @@ -722,13 +721,13 @@ int imap_open_mailbox (CONTEXT *ctx) conn->uses++; mutt_message ("Selecting %s...", CTX_DATA->mailbox); - imap_make_sequence (seq, sizeof (seq), ctx); + imap_make_sequence (seq, sizeof (seq)); snprintf (bufout, sizeof (bufout), "%s SELECT %s\r\n", seq, CTX_DATA->mailbox); - imap_write (CTX_DATA->conn, bufout); + mutt_socket_write (CTX_DATA->conn, bufout); do { - if (imap_read_line_d (buf, sizeof (buf), CTX_DATA->conn) < 0) + if (mutt_socket_read_line_d (buf, sizeof (buf), CTX_DATA->conn) < 0) break; if (buf[0] == '*') @@ -756,32 +755,8 @@ int imap_open_mailbox (CONTEXT *ctx) ctx->hdrmax = count; ctx->hdrs = safe_malloc (count * sizeof (HEADER *)); ctx->v2r = safe_malloc (count * sizeof (int)); - for (ctx->msgcount = 0; ctx->msgcount < count; ) - { - snprintf (buf, sizeof (buf), "Fetching message headers... [%d/%d]", - ctx->msgcount + 1, count); - mutt_message (buf); - ctx->hdrs[ctx->msgcount] = mutt_new_header (); - - /* `count' can get modified if new mail arrives while fetching the - * header for this message - */ - if (imap_read_header (ctx, ctx->msgcount) != 0) - { - mx_fastclose_mailbox (ctx); - return (-1); - } - mx_update_context (ctx); /* increments ->msgcount */ - - /* in case we get new mail while fetching the headers */ - if (CTX_DATA->status == IMAP_NEW_MAIL) - { - count = CTX_DATA->newMailCount; - while (count > ctx->hdrmax) - mx_alloc_memory (ctx); - CTX_DATA->status = 0; - } - } + ctx->msgcount = 0; + count=imap_read_headers (ctx, 0, count - 1) + 1; return 0; } @@ -791,7 +766,7 @@ static int imap_create_mailbox (CONTEXT *ctx) char seq[8]; char buf[LONG_STRING]; - imap_make_sequence (seq, sizeof (seq), ctx); + imap_make_sequence (seq, sizeof (seq)); snprintf (buf, sizeof (buf), "%s CREATE %s\r\n", seq, CTX_DATA->mailbox); if (imap_exec (buf, sizeof (buf), ctx, seq, buf, 0) != 0) @@ -808,28 +783,19 @@ int imap_open_mailbox_append (CONTEXT *ctx) char host[SHORT_STRING]; char buf[LONG_STRING]; char seq[16]; - int n; char *pc; + if (imap_parse_path (ctx->path, host, sizeof (host), &pc)) + return (-1); + /* create IMAP-specific state struct */ ctx->data = safe_malloc (sizeof (IMAP_DATA)); memset (ctx->data, 0, sizeof (IMAP_DATA)); - - pc = ctx->path; - if (*pc != '{') - return (-1); - pc++; - n = 0; - while (*pc && *pc != '}') - host[n++] = *pc++; - host[n] = 0; - if (!*pc) - return (-1); - pc++; + ctx->magic = M_IMAP; CTX_DATA->mailbox = pc; - conn = imap_select_connection (host, 0); + conn = mutt_socket_select_connection (host, IMAP_PORT, 0); CTX_DATA->conn = conn; if (conn->uses == 0) @@ -839,7 +805,7 @@ int imap_open_mailbox_append (CONTEXT *ctx) /* check mailbox existance */ - imap_make_sequence (seq, sizeof (seq), ctx); + imap_make_sequence (seq, sizeof (seq)); snprintf (buf, sizeof (buf), "%s STATUS %s (UIDVALIDITY)\r\n", seq, CTX_DATA->mailbox); @@ -865,6 +831,7 @@ int imap_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno) char *pc; char *pn; long bytes; + int pos,len,onbody=0; IMAP_CACHE *cache; /* see if we already have the message in our cache */ @@ -886,7 +853,7 @@ int imap_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno) { /* clear the previous entry */ unlink (cache->path); - free (cache->path); + FREE (&cache->path); } } @@ -901,13 +868,13 @@ int imap_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno) return (-1); } - imap_make_sequence (seq, sizeof (seq), ctx); + imap_make_sequence (seq, sizeof (seq)); snprintf (buf, sizeof (buf), "%s FETCH %d RFC822\r\n", seq, ctx->hdrs[msgno]->index + 1); - imap_write (CTX_DATA->conn, buf); + mutt_socket_write (CTX_DATA->conn, buf); do { - if (imap_read_line (buf, sizeof (buf), CTX_DATA->conn) < 0) + if (mutt_socket_read_line (buf, sizeof (buf), CTX_DATA->conn) < 0) { return (-1); } @@ -930,7 +897,25 @@ int imap_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno) pc++; *pc = 0; bytes = atoi (pn); - imap_read_bytes (msg->fp, CTX_DATA->conn, bytes); + for (pos = 0; pos < bytes; ) + { + len = mutt_socket_read_line (buf, sizeof (buf), CTX_DATA->conn); + if (len < 0) + return (-1); + pos += len; + fputs (buf, msg->fp); + fputs ("\n", msg->fp); + if (! onbody && len == 2) + { + /* + * This is the first time we really know how long the full + * header is. We must set it now, or mutt will not display + * the message properly + */ + ctx->hdrs[msgno]->content->offset=ftell(msg->fp); + onbody=1; + } + } } else if (imap_handle_untagged (ctx, buf) != 0) return (-1); @@ -947,35 +932,47 @@ int imap_fetch_message (MESSAGE *msg, CONTEXT *ctx, int msgno) return 0; } +static void +flush_buffer(char *buf, size_t *len, CONNECTION *conn) +{ + buf[*len] = '\0'; + mutt_socket_write(conn, buf); + *len = 0; +} + int imap_append_message (CONTEXT *ctx, MESSAGE *msg) { FILE *fp; - struct stat s; char seq[8]; char buf[LONG_STRING]; - - if (stat (msg->path, &s) == -1) + size_t len; + int c, last; + + if ((fp = fopen (msg->path, "r")) == NULL) { mutt_perror (msg->path); return (-1); } - if ((fp = safe_fopen (msg->path, "r")) == NULL) + for(last = EOF, len = 0; (c = fgetc(fp)) != EOF; last = c) { - mutt_perror (msg->path); - return (-1); - } + if(c == '\n' && last != '\r') + len++; + len++; + } + rewind(fp); + mutt_message ("Sending APPEND command ..."); - imap_make_sequence (seq, sizeof (seq), ctx); + imap_make_sequence (seq, sizeof (seq)); snprintf (buf, sizeof (buf), "%s APPEND %s {%d}\r\n", seq, - CTX_DATA->mailbox, s.st_size); + CTX_DATA->mailbox, len); - imap_write (CTX_DATA->conn, buf); + mutt_socket_write (CTX_DATA->conn, buf); do { - if (imap_read_line_d (buf, sizeof (buf), CTX_DATA->conn) < 0) + if (mutt_socket_read_line_d (buf, sizeof (buf), CTX_DATA->conn) < 0) { fclose (fp); return (-1); @@ -1005,16 +1002,28 @@ int imap_append_message (CONTEXT *ctx, MESSAGE *msg) } mutt_message ("Uploading message ..."); - while (fgets (buf, sizeof (buf), fp) != NULL) + + for(last = EOF, len = 0; (c = fgetc(fp)) != EOF; last = c) { - imap_write (CTX_DATA->conn, buf); + if(c == '\n' && last != '\r') + buf[len++] = '\r'; + + buf[len++] = c; + + if(len > sizeof(buf) - 3) + flush_buffer(buf, &len, CTX_DATA->conn); } - imap_write (CTX_DATA->conn, "\r\n"); + + if(len) + flush_buffer(buf, &len, CTX_DATA->conn); + + + mutt_socket_write (CTX_DATA->conn, "\r\n"); fclose (fp); do { - if (imap_read_line_d (buf, sizeof (buf), CTX_DATA->conn) < 0) + if (mutt_socket_read_line_d (buf, sizeof (buf), CTX_DATA->conn) < 0) return (-1); if (buf[0] == '*' && imap_handle_untagged (ctx, buf) != 0) @@ -1043,23 +1052,24 @@ int imap_close_connection (CONTEXT *ctx) char buf[LONG_STRING]; char seq[8]; + dprint (1, (debugfile, "imap_close_connection(): closing connection\n")); /* if the server didn't shut down on us, close the connection gracefully */ if (CTX_DATA->status != IMAP_BYE) { mutt_message ("Closing connection to IMAP server..."); - imap_make_sequence (seq, sizeof (seq), ctx); + imap_make_sequence (seq, sizeof (seq)); snprintf (buf, sizeof (buf), "%s LOGOUT\r\n", seq); - imap_write (CTX_DATA->conn, buf); + mutt_socket_write (CTX_DATA->conn, buf); do { - if (imap_read_line_d (buf, sizeof (buf), CTX_DATA->conn) < 0) + if (mutt_socket_read_line_d (buf, sizeof (buf), CTX_DATA->conn) < 0) break; } while (strncmp (seq, buf, SEQLEN) != 0); mutt_clear_error (); } close (CTX_DATA->conn->fd); - CTX_DATA->conn->uses--; + CTX_DATA->conn->uses = 0; return 0; } @@ -1090,7 +1100,7 @@ int imap_sync_mailbox (CONTEXT *ctx) mutt_remove_trailing_ws (tmp); if (!*tmp) continue; /* imapd doesn't like empty flags. */ - imap_make_sequence (seq, sizeof (seq), ctx); + imap_make_sequence (seq, sizeof (seq)); snprintf (buf, sizeof (buf), "%s STORE %d FLAGS.SILENT (%s)\r\n", seq, ctx->hdrs[n]->index + 1, tmp); if (imap_exec (buf, sizeof (buf), ctx, seq, buf, 0) != 0) @@ -1103,7 +1113,7 @@ int imap_sync_mailbox (CONTEXT *ctx) mutt_message ("Expunging messages from server..."); CTX_DATA->status = IMAP_EXPUNGE; - imap_make_sequence (seq, sizeof (seq), ctx); + imap_make_sequence (seq, sizeof (seq)); snprintf (buf, sizeof (buf), "%s EXPUNGE\r\n", seq); if (imap_exec (buf, sizeof (buf), ctx, seq, buf, 0) != 0) { @@ -1131,7 +1141,9 @@ void imap_fastclose_mailbox (CONTEXT *ctx) /* Check to see if the mailbox is actually open */ if (!ctx->data) return; - imap_close_connection (ctx); + CTX_DATA->conn->uses--; + if ((CTX_DATA->conn->uses == 0) || (CTX_DATA->status == IMAP_BYE)) + imap_close_connection (ctx); for (i = 0; i < IMAP_CACHE_LEN; i++) { if (CTX_DATA->cache[i].path) @@ -1151,7 +1163,7 @@ int imap_close_mailbox (CONTEXT *ctx) /* tell the server to commit changes */ mutt_message ("Closing mailbox..."); - imap_make_sequence (seq, sizeof (seq), ctx); + imap_make_sequence (seq, sizeof (seq)); snprintf (buf, sizeof (buf), "%s CLOSE\r\n", seq); if (imap_exec (buf, sizeof (buf), ctx, seq, buf, 0) != 0) { @@ -1176,7 +1188,7 @@ int imap_check_mailbox (CONTEXT *ctx, int *index_hint) checktime=k; } - imap_make_sequence (seq, sizeof (seq), ctx); + imap_make_sequence (seq, sizeof (seq)); snprintf (buf, sizeof (buf), "%s NOOP\r\n", seq); if (imap_exec (buf, sizeof (buf), ctx, seq, buf, 0) != 0) { @@ -1186,3 +1198,78 @@ int imap_check_mailbox (CONTEXT *ctx, int *index_hint) return (msgcount != ctx->msgcount); } + +int imap_buffy_check (char *path) +{ + CONNECTION *conn; + char host[SHORT_STRING]; + char buf[LONG_STRING]; + char seq[8]; + char *mbox; + char *s; + char recent = FALSE; + + if (imap_parse_path (path, host, sizeof (host), &mbox)) + return -1; + + conn = mutt_socket_select_connection (host, IMAP_PORT, 0); + + /* Currently, we don't open a connection to check, but we'll check + * over an existing connection */ + if (conn->uses == 0) + return (-1); + conn->uses++; + + imap_make_sequence (seq, sizeof (seq)); + snprintf (buf, sizeof (buf), "%s STATUS %s (RECENT)\r\n", seq, mbox); + + mutt_socket_write (conn, buf); + + do + { + if (mutt_socket_read_line_d (buf, sizeof (buf), conn) < 0) + { + return (-1); + } + + /* BUG: We don't handle other untagged messages here. This is + * actually because of a more general problem in that this + * connection is being used for a different mailbox, and all + * untagged messages we don't handle here (ie, STATUS) need to be + * sent to imap_handle_untagged() but with the CONTEXT of the + * currently selected mailbox. The same is broken in the APPEND + * stuff above. + */ +/* if (buf[0] == '*' && imap_handle_untagged (ctx, buf) != 0) */ + if (buf[0] == '*') + { + s = imap_next_word (buf); + if (strncasecmp ("STATUS", s, 6) == 0) + { + s = imap_next_word (s); + if (strncmp (mbox, s, strlen (mbox)) == 0) + { + s = imap_next_word (s); + s = imap_next_word (s); + if (isdigit (*s)) + { + if (*s != '0') + { + dprint (1, (debugfile, "New mail in %s\n", path)); + recent = TRUE; + } + } + } + } + else + { + mutt_error ("BUG! Untagged IMAP Response during BUFFY Check"); + } + } + } + while ((strncmp (buf, seq, SEQLEN) != 0)); + + conn->uses--; + + return recent; +} diff --git a/imap.h b/imap.h index ce18c723..d7c1357c 100644 --- a/imap.h +++ b/imap.h @@ -26,5 +26,6 @@ extern int imap_open_mailbox (CONTEXT *ctx); extern int imap_open_mailbox_append (CONTEXT *ctx); extern int imap_sync_mailbox (CONTEXT *ctx); extern void imap_fastclose_mailbox (CONTEXT *ctx); +extern int imap_buffy_check (char *path); #endif diff --git a/init.c b/init.c index d4ae1897..95cdee93 100644 --- a/init.c +++ b/init.c @@ -17,9 +17,10 @@ */ #include "mutt.h" +#include "mapping.h" #include "mutt_curses.h" #include "mutt_regex.h" - +#include "history.h" #ifdef _PGPPATH @@ -168,9 +169,9 @@ int mutt_extract_token (BUFFER *dest, BUFFER *tok, int flags) add_char (dest, '\033'); break; default: - if (isdigit (ch) && - isdigit (*tok->dptr) && - isdigit (*(tok->dptr + 1))) + if (isdigit ((unsigned char) ch) && + isdigit ((unsigned char) *tok->dptr) && + isdigit ((unsigned char) *(tok->dptr + 1))) { add_char (dest, (ch << 6) + (*tok->dptr << 3) + *(tok->dptr + 1) - 3504); @@ -187,7 +188,7 @@ int mutt_extract_token (BUFFER *dest, BUFFER *tok, int flags) add_char (dest, ch); else if (ch == '[') add_char (dest, '\033'); - else if (isalpha (ch)) + else if (isalpha ((unsigned char) ch)) add_char (dest, toupper (ch) - '@'); else { @@ -252,7 +253,7 @@ int mutt_extract_token (BUFFER *dest, BUFFER *tok, int flags) FREE (&expn.data); } } - else if (ch == '$' && (!qc || qc == '"') && (*tok->dptr == '{' || isalpha (*tok->dptr))) + else if (ch == '$' && (!qc || qc == '"') && (*tok->dptr == '{' || isalpha ((unsigned char) *tok->dptr))) { char *env, *var; @@ -267,7 +268,7 @@ int mutt_extract_token (BUFFER *dest, BUFFER *tok, int flags) } else { - for (pc = tok->dptr; isalpha (*pc) || *pc == '_'; pc++) + for (pc = tok->dptr; isalpha ((unsigned char) *pc) || *pc == '_'; pc++) ; var = mutt_substrdup (tok->dptr, pc); tok->dptr = pc; @@ -629,18 +630,36 @@ static void mutt_restore_default (struct option_t *p) case DT_RX: { REGEXP *pp = (REGEXP *) p->data; + int flags = 0; + FREE (&pp->pattern); + if (pp->rx) + { + regfree (pp->rx); + FREE (&pp->rx); + } if (p->init) { - if (pp->rx) - regfree (pp->rx); - else - pp->rx = safe_calloc (1, sizeof (regex_t)); + char *s = (char *) p->init; + + pp->rx = safe_calloc (1, sizeof (regex_t)); pp->pattern = safe_strdup ((char *) p->init); - if (REGCOMP (pp->rx, pp->pattern, mutt_which_case (pp->pattern)) != 0) + if (strcmp (p->option, "alternates") == 0) + flags |= REG_ICASE; + else if (strcmp (p->option, "mask") != 0) + flags |= mutt_which_case ((const char *) p->init); + if (strcmp (p->option, "mask") == 0 && *s == '!') + { + s++; + pp->not = 1; + } + if (REGCOMP (pp->rx, s, flags) != 0) { fprintf (stderr, "mutt_restore_default: error in regexp: %s\n", pp->pattern); + FREE (&pp->pattern); + regfree (pp->rx); + FREE (&pp->rx); } } } @@ -794,15 +813,27 @@ static int parse_set (BUFFER *tmp, BUFFER *s, unsigned long data, BUFFER *err) if (!ptr->pattern || strcmp (ptr->pattern, tmp->data) != 0) { + int not = 0; + /* $alternates is case-insensitive, $mask is case-sensitive */ if (strcmp (MuttVars[idx].option, "alternates") == 0) flags |= REG_ICASE; else if (strcmp (MuttVars[idx].option, "mask") != 0) flags |= mutt_which_case (tmp->data); - + + p = tmp->data; + if (strcmp (MuttVars[idx].option, "mask") == 0) + { + if (*p == '!') + { + not = 1; + p++; + } + } + rx = (regex_t *) safe_malloc (sizeof (regex_t)); - if ((e = REGCOMP (rx, tmp->data, flags)) != 0) + if ((e = REGCOMP (rx, p, flags)) != 0) { regerror (e, rx, err->data, err->dsize); regfree (rx); @@ -820,6 +851,7 @@ static int parse_set (BUFFER *tmp, BUFFER *s, unsigned long data, BUFFER *err) ptr->pattern = safe_strdup (tmp->data); ptr->rx = rx; + ptr->not = not; /* $reply_regexp requires special treatment */ if (Context && Context->msgcount && @@ -1158,12 +1190,12 @@ int mutt_command_complete (char *buffer, size_t len, int pos) strncpy (cmd, buffer, pos); pt = cmd; pt[pos] = 0; - while (!isspace (*pt)) + while (!isspace ((unsigned char) *pt)) pt++; *pt = 0; pt = buffer + pos; - while ((pt > buffer) && !isspace (*pt)) + while ((pt > buffer) && !isspace ((unsigned char) *pt)) pt--; if (pt == buffer) /* complete cmd */ { @@ -1174,16 +1206,46 @@ int mutt_command_complete (char *buffer, size_t len, int pos) return 0; strncpy (buffer, completed, len); } - else if (!strncasecmp (cmd, "set", 3) - || !strncasecmp (cmd, "unset", 5) - || !strncasecmp (cmd, "toggle", 6)) + else if (!strcasecmp (cmd, "set") + || !strcasecmp (cmd, "unset") + || !strcasecmp (cmd, "reset") + || !strcasecmp (cmd, "toggle")) { /* complete variables */ + char *prefixes[] = { "no", "inv", "?", "&", 0 }; + int prefix_index; + char tmpbuffer[STRING]; + int prefix_len; + + /* remember if the command is set to decide whether we want to attempt the + * prefixes */ + int cmd_is_set = !strcasecmp (cmd, "set"); + pt++; if (*pt == 0) return 0; strncpy (cmd, pt, sizeof (cmd)); for (num = 0; MuttVars[num].option; num++) candidate (completed, cmd, MuttVars[num].option, sizeof (completed)); + + if ( cmd_is_set ) { + /* loop through all the possible prefixes (no, inv, ...) */ + for ( prefix_index = 0; prefixes[prefix_index]; prefix_index++ ) + { + prefix_len = strlen(prefixes[prefix_index]); + strncpy( tmpbuffer, prefixes[prefix_index], sizeof(tmpbuffer) ); + + /* if the current option is prepended with the prefix */ + if ( !strncasecmp(cmd, tmpbuffer, prefix_len )) { + for (num = 0; MuttVars[num].option; num++) { + strncpy( &tmpbuffer[prefix_len], + MuttVars[num].option, + sizeof(tmpbuffer) - prefix_len ); + candidate (completed, cmd, tmpbuffer, sizeof (completed)); + } + } + } + } + if (completed[0] == 0) return 0; strncpy (pt, completed, buffer + len - pt); @@ -1224,8 +1286,8 @@ static void start_debug (void) /* rotate the old debug logs */ for (i=3; i>=0; i--) { - snprintf (buf, sizeof(buf), "%s/.muttdebug%d", Homedir, i); - snprintf (buf2, sizeof(buf2), "%s/.muttdebug%d", Homedir, i+1); + snprintf (buf, sizeof(buf), "%s/.muttdebug%d", NONULL(Homedir), i); + snprintf (buf2, sizeof(buf2), "%s/.muttdebug%d", NONULL(Homedir), i+1); rename (buf, buf2); } if ((debugfile = safe_fopen(buf, "w")) != NULL) @@ -1332,12 +1394,8 @@ void mutt_init (int skip_sys_rc, LIST *commands) else #endif /* DOMAIN */ { -# ifdef HIDDEN_HOST - Fqdn = safe_strdup (DOMAIN); -# else - Fqdn = safe_malloc (strlen (DOMAIN) + strlen (Hostname) + 2); - sprintf (Fqdn, "%s.%s", Hostname, DOMAIN); -# endif /* HIDDEN_HOST */ + Fqdn = safe_malloc (strlen (DOMAIN) + strlen (NONULL(Hostname)) + 2); + sprintf (Fqdn, "%s.%s", NONULL(Hostname), DOMAIN); } if ((p = getenv ("MAIL"))) @@ -1345,9 +1403,9 @@ void mutt_init (int skip_sys_rc, LIST *commands) else { #ifdef HOMESPOOL - snprintf (buffer, sizeof (buffer), "%s/%s", Homedir, MAILPATH); + snprintf (buffer, sizeof (buffer), "%s/%s", NONULL(Homedir), MAILPATH); #else - snprintf (buffer, sizeof (buffer), "%s/%s", MAILPATH, Username); + snprintf (buffer, sizeof (buffer), "%s/%s", MAILPATH, NONULL(Username)); #endif Spoolfile = safe_strdup (buffer); } @@ -1376,9 +1434,9 @@ void mutt_init (int skip_sys_rc, LIST *commands) } else { - snprintf (buffer, sizeof (buffer), "%s/.pgp/pubring.pgp", Homedir); + snprintf (buffer, sizeof (buffer), "%s/.pgp/pubring.pgp", NONULL(Homedir)); PgpV2Pubring = safe_strdup (buffer); - snprintf (buffer, sizeof (buffer), "%s/.pgp/secring.pgp", Homedir); + snprintf (buffer, sizeof (buffer), "%s/.pgp/secring.pgp", NONULL(Homedir)); PgpV2Secring = safe_strdup (buffer); } #endif @@ -1394,9 +1452,9 @@ void mutt_init (int skip_sys_rc, LIST *commands) } else { - snprintf (buffer, sizeof (buffer), "%s/.pgp/pubring.pkr", Homedir); + snprintf (buffer, sizeof (buffer), "%s/.pgp/pubring.pkr", NONULL(Homedir)); PgpV3Pubring = safe_strdup (buffer); - snprintf (buffer, sizeof (buffer), "%s/.pgp/secring.skr", Homedir); + snprintf (buffer, sizeof (buffer), "%s/.pgp/secring.skr", NONULL(Homedir)); PgpV3Secring = safe_strdup (buffer); } #endif @@ -1447,9 +1505,9 @@ void mutt_init (int skip_sys_rc, LIST *commands) if (!Muttrc) { - snprintf (buffer, sizeof (buffer), "%s/.muttrc-%s", Homedir, VERSION); + snprintf (buffer, sizeof (buffer), "%s/.muttrc-%s", NONULL(Homedir), VERSION); if (access (buffer, F_OK) == -1) - snprintf (buffer, sizeof (buffer), "%s/.muttrc", Homedir); + snprintf (buffer, sizeof (buffer), "%s/.muttrc", NONULL(Homedir)); default_rc = 1; Muttrc = safe_strdup (buffer); } @@ -1461,7 +1519,7 @@ void mutt_init (int skip_sys_rc, LIST *commands) Muttrc = safe_strdup (buffer); } FREE (&AliasFile); - AliasFile = safe_strdup (Muttrc); + AliasFile = safe_strdup (NONULL(Muttrc)); /* Process the global rc file if it exists and the user hasn't explicity requested not to via "-n". */ diff --git a/init.h b/init.h index 452b4988..397a8237 100644 --- a/init.h +++ b/init.h @@ -77,6 +77,9 @@ struct option_t MuttVars[] = { { "ascii_chars", DT_BOOL, R_BOTH, OPTASCIICHARS, 0 }, { "askbcc", DT_BOOL, R_NONE, OPTASKBCC, 0 }, { "askcc", DT_BOOL, R_NONE, OPTASKCC, 0 }, + { "attach_format", DT_STR, R_NONE, UL &AttachFormat, UL "%u%D%t%2n %T%.40d%> [%.7m/%.10M, %.6e, %s] " }, + { "attach_split", DT_BOOL, R_NONE, OPTATTACHSPLIT, 1 }, + { "attach_sep", DT_STR, R_NONE, UL &AttachSep, UL "\n" }, { "attribution", DT_STR, R_NONE, UL &Attribution, UL "On %d, %n wrote:" }, { "autoedit", DT_BOOL, R_NONE, OPTAUTOEDIT, 0 }, { "auto_tag", DT_BOOL, R_NONE, OPTAUTOTAG, 0 }, @@ -96,7 +99,6 @@ struct option_t MuttVars[] = { { "edit_headers", DT_BOOL, R_NONE, OPTEDITHDRS, 0 }, { "edit_hdrs", DT_SYN, R_NONE, UL "edit_headers", 0 }, { "editor", DT_PATH, R_NONE, UL &Editor, 0 }, - { "empty_to", DT_STR, R_NONE, UL &EmptyTo, UL "undisclosed-recipients" }, { "escape", DT_STR, R_NONE, UL &EscChar, UL "~" }, { "fast_reply", DT_BOOL, R_NONE, OPTFASTREPLY, 0 }, { "fcc_attach", DT_BOOL, R_NONE, OPTFCCATTACH, 1 }, @@ -114,6 +116,7 @@ struct option_t MuttVars[] = { { "hdrs", DT_BOOL, R_NONE, OPTHDRS, 1 }, { "header", DT_BOOL, R_NONE, OPTHEADER, 0 }, { "help", DT_BOOL, R_BOTH, OPTHELP, 1 }, + { "hidden_host", DT_BOOL, R_NONE, OPTHIDDENHOST, 0 }, { "history", DT_NUM, R_NONE, UL &HistSize, 10 }, { "hostname", DT_STR, R_NONE, UL &Fqdn, 0 }, #ifdef USE_IMAP @@ -133,7 +136,7 @@ struct option_t MuttVars[] = { { "mailcap_path", DT_STR, R_NONE, UL &MailcapPath, 0 }, { "mark_old", DT_BOOL, R_BOTH, OPTMARKOLD, 1 }, { "markers", DT_BOOL, R_PAGER, OPTMARKERS, 1 }, - { "mask", DT_RX, R_NONE, UL &Mask, UL "^(\\.\\.$|[^.])" }, + { "mask", DT_RX, R_NONE, UL &Mask, UL "!^\\.[^.]" }, { "mbox", DT_PATH, R_BOTH, UL &Inbox, UL "~/mbox" }, { "mbox_type", DT_MAGIC,R_NONE, UL &DefaultMagic, M_MBOX }, { "metoo", DT_BOOL, R_NONE, OPTMETOO, 0 }, @@ -263,6 +266,7 @@ struct option_t MuttVars[] = { { "wait_key", DT_BOOL, R_NONE, OPTWAITKEY, 1 }, { "wrap_search", DT_BOOL, R_NONE, OPTWRAPSEARCH, 1 }, { "write_inc", DT_NUM, R_NONE, UL &WriteInc, 10 }, + { "write_bcc", DT_BOOL, R_NONE, OPTWRITEBCC, 1}, { NULL } }; @@ -335,6 +339,9 @@ struct command_t Commands[] = { { "mbox-hook", mutt_parse_hook, M_MBOXHOOK }, { "mono", mutt_parse_mono, 0 }, { "my_hdr", parse_my_hdr, 0 }, +#ifdef _PGPPATH + { "pgp-hook", mutt_parse_hook, M_PGPHOOK }, +#endif /* _PGPPATH */ { "push", mutt_parse_push, 0 }, { "reset", parse_set, M_SET_RESET }, { "save-hook", mutt_parse_hook, M_SAVEHOOK }, @@ -344,8 +351,10 @@ struct command_t Commands[] = { { "source", parse_source, 0 }, { "toggle", parse_set, M_SET_INV }, { "unalias", parse_unalias, 0 }, + { "unhdr_order", parse_unlist, UL &HeaderOrderList }, { "unignore", parse_unignore, 0 }, { "unlists", parse_unlist, UL &MailLists }, + { "unmono", mutt_parse_unmono, 0 }, { "unmy_hdr", parse_unmy_hdr, 0 }, { "unscore", mutt_parse_unscore, 0 }, { "unset", parse_set, M_SET_UNSET }, diff --git a/keymap.c b/keymap.c index 0eebfd32..b3f8c0e3 100644 --- a/keymap.c +++ b/keymap.c @@ -97,10 +97,10 @@ static int parsekeys (char *s, keycode_t *d, int max) s += strlen (s); *d = n; } - else if (tolower (*s) == 'f' && isdigit (s[1])) + else if (tolower (*s) == 'f' && isdigit ((unsigned char) s[1])) { n = 0; - for (s++; isdigit (*s) ; s++) + for (s++; isdigit ((unsigned char) *s) ; s++) { n *= 10; n += *s - '0'; @@ -122,7 +122,7 @@ static int parsekeys (char *s, keycode_t *d, int max) /* insert a key sequence into the specified map. the map is sorted by ASCII * value (lowest to highest) */ -void km_bindkey (char *s, int menu, int op, char *macro) +void km_bind (char *s, int menu, int op, char *macro, char *descr) { struct keymap_t *map, *tmp, *last = NULL, *next; keycode_t buf[MAX_SEQ]; @@ -133,6 +133,7 @@ void km_bindkey (char *s, int menu, int op, char *macro) map = allocKeys (len, buf); map->op = op; map->macro = safe_strdup (macro); + map->descr = safe_strdup (descr); tmp = Keymaps[menu]; @@ -145,10 +146,10 @@ void km_bindkey (char *s, int menu, int op, char *macro) { len = tmp->eq; next = tmp->next; - if (tmp->macro) - free (tmp->macro); - free (tmp->keys); - free (tmp); + FREE (&tmp->macro); + FREE (&tmp->keys); + FREE (&tmp->descr); + FREE (&tmp); tmp = next; } while (tmp && len >= pos); @@ -183,6 +184,11 @@ void km_bindkey (char *s, int menu, int op, char *macro) Keymaps[menu] = map; } +void km_bindkey (char *s, int menu, int op) +{ + km_bind (s, menu, op, NULL, NULL); +} + static void push_string (char *s) { char *pp, *p = s + strlen (s) - 1; @@ -292,7 +298,7 @@ static void create_bindings (struct binding_t *map, int menu) for (i = 0 ; map[i].name ; i++) if (map[i].seq) - km_bindkey (map[i].seq, menu, map[i].op, NULL); + km_bindkey (map[i].seq, menu, map[i].op); } char *km_keyname (int c) @@ -395,68 +401,72 @@ void km_init (void) /* bindings for the line editor */ create_bindings (OpEditor, MENU_EDITOR); - km_bindkey ("<up>", MENU_EDITOR, OP_EDITOR_HISTORY_UP, NULL); - km_bindkey ("<down>", MENU_EDITOR, OP_EDITOR_HISTORY_DOWN, NULL); - km_bindkey ("<left>", MENU_EDITOR, OP_EDITOR_BACKWARD_CHAR, NULL); - km_bindkey ("<right>", MENU_EDITOR, OP_EDITOR_FORWARD_CHAR, NULL); - km_bindkey ("<home>", MENU_EDITOR, OP_EDITOR_BOL, NULL); - km_bindkey ("<end>", MENU_EDITOR, OP_EDITOR_EOL, NULL); - km_bindkey ("<backspace>", MENU_EDITOR, OP_EDITOR_BACKSPACE, NULL); - km_bindkey ("<delete>", MENU_EDITOR, OP_EDITOR_BACKSPACE, NULL); - km_bindkey ("\177", MENU_EDITOR, OP_EDITOR_BACKSPACE, NULL); + km_bindkey ("<up>", MENU_EDITOR, OP_EDITOR_HISTORY_UP); + km_bindkey ("<down>", MENU_EDITOR, OP_EDITOR_HISTORY_DOWN); + km_bindkey ("<left>", MENU_EDITOR, OP_EDITOR_BACKWARD_CHAR); + km_bindkey ("<right>", MENU_EDITOR, OP_EDITOR_FORWARD_CHAR); + km_bindkey ("<home>", MENU_EDITOR, OP_EDITOR_BOL); + km_bindkey ("<end>", MENU_EDITOR, OP_EDITOR_EOL); + km_bindkey ("<backspace>", MENU_EDITOR, OP_EDITOR_BACKSPACE); + km_bindkey ("<delete>", MENU_EDITOR, OP_EDITOR_BACKSPACE); + km_bindkey ("\177", MENU_EDITOR, OP_EDITOR_BACKSPACE); /* generic menu keymap */ create_bindings (OpGeneric, MENU_GENERIC); - km_bindkey ("<home>", MENU_GENERIC, OP_FIRST_ENTRY, NULL); - km_bindkey ("<end>", MENU_GENERIC, OP_LAST_ENTRY, NULL); - km_bindkey ("<pagedown>", MENU_GENERIC, OP_NEXT_PAGE, NULL); - km_bindkey ("<pageup>", MENU_GENERIC, OP_PREV_PAGE, NULL); - km_bindkey ("<right>", MENU_GENERIC, OP_NEXT_PAGE, NULL); - km_bindkey ("<left>", MENU_GENERIC, OP_PREV_PAGE, NULL); - km_bindkey ("<up>", MENU_GENERIC, OP_PREV_ENTRY, NULL); - km_bindkey ("<down>", MENU_GENERIC, OP_NEXT_ENTRY, NULL); - km_bindkey ("1", MENU_GENERIC, OP_JUMP, NULL); - km_bindkey ("2", MENU_GENERIC, OP_JUMP, NULL); - km_bindkey ("3", MENU_GENERIC, OP_JUMP, NULL); - km_bindkey ("4", MENU_GENERIC, OP_JUMP, NULL); - km_bindkey ("5", MENU_GENERIC, OP_JUMP, NULL); - km_bindkey ("6", MENU_GENERIC, OP_JUMP, NULL); - km_bindkey ("7", MENU_GENERIC, OP_JUMP, NULL); - km_bindkey ("8", MENU_GENERIC, OP_JUMP, NULL); - km_bindkey ("9", MENU_GENERIC, OP_JUMP, NULL); + km_bindkey ("<home>", MENU_GENERIC, OP_FIRST_ENTRY); + km_bindkey ("<end>", MENU_GENERIC, OP_LAST_ENTRY); + km_bindkey ("<pagedown>", MENU_GENERIC, OP_NEXT_PAGE); + km_bindkey ("<pageup>", MENU_GENERIC, OP_PREV_PAGE); + km_bindkey ("<right>", MENU_GENERIC, OP_NEXT_PAGE); + km_bindkey ("<left>", MENU_GENERIC, OP_PREV_PAGE); + km_bindkey ("<up>", MENU_GENERIC, OP_PREV_ENTRY); + km_bindkey ("<down>", MENU_GENERIC, OP_NEXT_ENTRY); + km_bindkey ("1", MENU_GENERIC, OP_JUMP); + km_bindkey ("2", MENU_GENERIC, OP_JUMP); + km_bindkey ("3", MENU_GENERIC, OP_JUMP); + km_bindkey ("4", MENU_GENERIC, OP_JUMP); + km_bindkey ("5", MENU_GENERIC, OP_JUMP); + km_bindkey ("6", MENU_GENERIC, OP_JUMP); + km_bindkey ("7", MENU_GENERIC, OP_JUMP); + km_bindkey ("8", MENU_GENERIC, OP_JUMP); + km_bindkey ("9", MENU_GENERIC, OP_JUMP); /* Miscellaneous extra bindings */ - km_bindkey (" ", MENU_MAIN, OP_DISPLAY_MESSAGE, NULL); - km_bindkey ("<up>", MENU_MAIN, OP_MAIN_PREV_UNDELETED, NULL); - km_bindkey ("<down>", MENU_MAIN, OP_MAIN_NEXT_UNDELETED, NULL); - km_bindkey ("J", MENU_MAIN, OP_NEXT_ENTRY, NULL); - km_bindkey ("K", MENU_MAIN, OP_PREV_ENTRY, NULL); - km_bindkey ("x", MENU_MAIN, OP_EXIT, NULL); - - km_bindkey ("x", MENU_PAGER, OP_PAGER_EXIT, NULL); - km_bindkey ("q", MENU_PAGER, OP_PAGER_EXIT, NULL); - km_bindkey ("<backspace>", MENU_PAGER, OP_PREV_LINE, NULL); - km_bindkey ("<pagedown>", MENU_PAGER, OP_NEXT_PAGE, NULL); - km_bindkey ("<pageup>", MENU_PAGER, OP_PREV_PAGE, NULL); - km_bindkey ("<up>", MENU_PAGER, OP_MAIN_PREV_UNDELETED, NULL); - km_bindkey ("<right>", MENU_PAGER, OP_MAIN_NEXT_UNDELETED, NULL); - km_bindkey ("<down>", MENU_PAGER, OP_MAIN_NEXT_UNDELETED, NULL); - km_bindkey ("<left>", MENU_PAGER, OP_MAIN_PREV_UNDELETED, NULL); - km_bindkey ("<home>", MENU_PAGER, OP_PAGER_TOP, NULL); - km_bindkey ("<end>", MENU_PAGER, OP_PAGER_BOTTOM, NULL); - km_bindkey ("1", MENU_PAGER, OP_JUMP, NULL); - km_bindkey ("2", MENU_PAGER, OP_JUMP, NULL); - km_bindkey ("3", MENU_PAGER, OP_JUMP, NULL); - km_bindkey ("4", MENU_PAGER, OP_JUMP, NULL); - km_bindkey ("5", MENU_PAGER, OP_JUMP, NULL); - km_bindkey ("6", MENU_PAGER, OP_JUMP, NULL); - km_bindkey ("7", MENU_PAGER, OP_JUMP, NULL); - km_bindkey ("8", MENU_PAGER, OP_JUMP, NULL); - km_bindkey ("9", MENU_PAGER, OP_JUMP, NULL); - - km_bindkey ("<return>", MENU_ALIAS, OP_TAG, NULL); + km_bindkey (" ", MENU_MAIN, OP_DISPLAY_MESSAGE); + km_bindkey ("<up>", MENU_MAIN, OP_MAIN_PREV_UNDELETED); + km_bindkey ("<down>", MENU_MAIN, OP_MAIN_NEXT_UNDELETED); + km_bindkey ("J", MENU_MAIN, OP_NEXT_ENTRY); + km_bindkey ("K", MENU_MAIN, OP_PREV_ENTRY); + km_bindkey ("x", MENU_MAIN, OP_EXIT); + + km_bindkey ("x", MENU_PAGER, OP_PAGER_EXIT); + km_bindkey ("q", MENU_PAGER, OP_PAGER_EXIT); + km_bindkey ("<backspace>", MENU_PAGER, OP_PREV_LINE); + km_bindkey ("<pagedown>", MENU_PAGER, OP_NEXT_PAGE); + km_bindkey ("<pageup>", MENU_PAGER, OP_PREV_PAGE); + km_bindkey ("<up>", MENU_PAGER, OP_MAIN_PREV_UNDELETED); + km_bindkey ("<right>", MENU_PAGER, OP_MAIN_NEXT_UNDELETED); + km_bindkey ("<down>", MENU_PAGER, OP_MAIN_NEXT_UNDELETED); + km_bindkey ("<left>", MENU_PAGER, OP_MAIN_PREV_UNDELETED); + km_bindkey ("<home>", MENU_PAGER, OP_PAGER_TOP); + km_bindkey ("<end>", MENU_PAGER, OP_PAGER_BOTTOM); + km_bindkey ("1", MENU_PAGER, OP_JUMP); + km_bindkey ("2", MENU_PAGER, OP_JUMP); + km_bindkey ("3", MENU_PAGER, OP_JUMP); + km_bindkey ("4", MENU_PAGER, OP_JUMP); + km_bindkey ("5", MENU_PAGER, OP_JUMP); + km_bindkey ("6", MENU_PAGER, OP_JUMP); + km_bindkey ("7", MENU_PAGER, OP_JUMP); + km_bindkey ("8", MENU_PAGER, OP_JUMP); + km_bindkey ("9", MENU_PAGER, OP_JUMP); + + km_bindkey ("<return>", MENU_ALIAS, OP_TAG); + + /* edit-to (default "t") hides generic tag-entry in Compose menu + This will bind tag-entry to "T" in the Compose menu */ + km_bindkey ("T", MENU_COMPOSE, OP_TAG); } void km_error_key (int menu) @@ -528,7 +538,7 @@ try_bind (char *key, int menu, char *func, struct binding_t *bindings) for (i = 0; bindings[i].name; i++) if (strcmp (func, bindings[i].name) == 0) { - km_bindkey (key, menu, bindings[i].op, NULL); + km_bindkey (key, menu, bindings[i].op); return (0); } return (-1); @@ -588,7 +598,7 @@ int mutt_parse_bind (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err) r = -1; } else if (strcasecmp ("noop", buf->data) == 0) - km_bindkey (key, menu, OP_NULL, NULL); /* the `unbind' command */ + km_bindkey (key, menu, OP_NULL); /* the `unbind' command */ else { /* First check the "generic" list of commands */ @@ -608,10 +618,11 @@ int mutt_parse_bind (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err) return (r); } -/* macro <menu> <key> <macro> */ +/* macro <menu> <key> <macro> <description> */ int mutt_parse_macro (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err) { int menu, r = -1; + char *seq = NULL; char *key; if ((key = parse_keymap (&menu, s, err)) == NULL) @@ -623,14 +634,30 @@ int mutt_parse_macro (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err) { strfcpy (err->data, "macro: empty key sequence", err->dsize); } - else if (MoreArgs (s)) - { - strfcpy (err->data, "macro: too many arguments", err->dsize); - } else { - km_bindkey (key, menu, OP_MACRO, buf->data); - r = 0; + if (MoreArgs (s)) + { + seq = strdup (buf->data); + mutt_extract_token (buf, s, M_TOKEN_CONDENSE); + + if (MoreArgs (s)) + { + strfcpy (err->data, "macro: too many arguments", err->dsize); + } + else + { + km_bind (key, menu, OP_MACRO, seq, buf->data); + r = 0; + } + + FREE (&seq); + } + else + { + km_bind (key, menu, OP_MACRO, buf->data, NULL); + r = 0; + } } FREE (&key); return (r); diff --git a/keymap.h b/keymap.h index 580bc2ba..7ec44a5c 100644 --- a/keymap.h +++ b/keymap.h @@ -25,13 +25,15 @@ /* type for key storage, the rest of mutt works fine with int type */ typedef short keycode_t; -void km_bindkey (char *, int, int, char *); +void km_bind (char *, int, int, char *, char *); +void km_bindkey (char *, int, int); int km_dokey (int); /* entry in the keymap tree */ struct keymap_t { char *macro; /* macro expansion (op == OP_MACRO) */ + char *descr; /* description of a macro for the help menu */ struct keymap_t *next; /* next key in map */ short op; /* operation to perform */ short eq; /* number of leading keys equal to next entry */ diff --git a/lib.c b/lib.c index 3c14bc68..2134c5a9 100644 --- a/lib.c +++ b/lib.c @@ -19,6 +19,8 @@ #include "mutt.h" #include "mutt_curses.h" #include "mime.h" +#include "mailbox.h" +#include "mx.h" #include <string.h> #include <ctype.h> @@ -63,6 +65,7 @@ void mutt_free_body (BODY **p) unlink (b->filename); safe_free ((void **) &b->filename); safe_free ((void **) &b->content); + safe_free ((void **) &b->xtype); safe_free ((void **) &b->subtype); safe_free ((void **) &b->description); safe_free ((void **) &b->form_name); @@ -194,7 +197,7 @@ char *mutt_expand_path (char *s, size_t slen) if (*s == '~') { if (*(s + 1) == '/' || *(s + 1) == 0) - snprintf (p, sizeof (p), "%s%s", Homedir, s + 1); + snprintf (p, sizeof (p), "%s%s", NONULL(Homedir), s + 1); else { struct passwd *pw; @@ -468,7 +471,7 @@ void mutt_tabs_to_spaces (char *s) void mutt_mktemp (char *s) { - snprintf (s, _POSIX_PATH_MAX, "%s/mutt-%s-%d-%d", NONULL (Tempdir), Hostname, (int) getpid (), Counter++); + snprintf (s, _POSIX_PATH_MAX, "%s/mutt-%s-%d-%d", NONULL (Tempdir), NONULL(Hostname), (int) getpid (), Counter++); unlink (s); } @@ -510,7 +513,7 @@ void mutt_free_alias (ALIAS **p) *p = (*p)->next; safe_free ((void **) &t->name); rfc822_free_address (&t->addr); - free (t); + safe_free ((void **) &t); } } @@ -543,7 +546,7 @@ void mutt_pretty_mailbox (char *s) *s++ = '='; strcpy (s, s + len); } - else if (strncmp (s, Homedir, (len = strlen (Homedir))) == 0 && + else if (strncmp (s, NONULL(Homedir), (len = strlen (NONULL(Homedir)))) == 0 && s[len] == '/') { *s++ = '~'; @@ -642,13 +645,32 @@ void mutt_expand_fmt (char *dest, size_t destlen, const char *fmt, const char *s snprintf (dest, destlen, "%s '%s'", fmt, src); } +int safe_open (const char *path, int flags) +{ + struct stat osb, nsb; + int fd; + + if ((fd = open (path, flags, 0600)) < 0) + return fd; + + /* make sure the file is not symlink */ + if (lstat (path, &osb) < 0 || fstat (fd, &nsb) < 0 || + osb.st_dev != nsb.st_dev || osb.st_ino != nsb.st_ino || + osb.st_rdev != nsb.st_rdev) + { + dprint (1, (debugfile, "safe_open(): %s is a symlink!\n", path)); + close (fd); + return (-1); + } + + return (fd); +} + /* when opening files for writing, make sure the file doesn't already exist * to avoid race conditions. */ FILE *safe_fopen (const char *path, const char *mode) { - struct stat osb, nsb; - if (mode[0] == 'w') { int fd; @@ -659,18 +681,8 @@ FILE *safe_fopen (const char *path, const char *mode) else flags |= O_WRONLY; - if ((fd = open (path, flags, 0600)) < 0) - return NULL; - - /* make sure the file is not symlink */ - if (lstat (path, &osb) < 0 || fstat (fd, &nsb) < 0 || - osb.st_dev != nsb.st_dev || osb.st_ino != nsb.st_ino || - osb.st_rdev != nsb.st_rdev) - { - dprint (1, (debugfile, "safe_fopen():%s is a symlink!\n", path)); - close (fd); + if ((fd = safe_open (path, flags)) < 0) return (NULL); - } return (fdopen (fd, mode)); } @@ -772,6 +784,19 @@ void mutt_safe_path (char *s, size_t l, ADDRESS *a) *p = '_'; } +static char safe_chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+@{}._-:%"; + +void mutt_sanitize_filename(char *f) +{ + if(!f) return; + + for(; *f; f++) + { + if(!strchr(safe_chars, *f)) + *f = '_'; + } +} + /* Read a line from ``fp'' into the dynamically allocated ``s'', * increasing ``s'' if necessary. The ending "\n" or "\r\n" is removed. * If a line ends with "\", this char and the linefeed is removed, @@ -792,7 +817,7 @@ char *mutt_read_line (char *s, size_t *size, FILE *fp, int *line) { if (fgets (s + offset, *size - offset, fp) == NULL) { - free (s); + safe_free ((void **) &s); return NULL; } if ((ch = strchr (s + offset, '\n')) != NULL) @@ -877,7 +902,7 @@ void mutt_FormatString (char *dest, /* output buffer */ cp = prefix; count = 0; while (count < sizeof (prefix) && - (isdigit (*src) || *src == '.' || *src == '-')) + (isdigit ((unsigned char) *src) || *src == '.' || *src == '-')) { *cp++ = *src++; count++; @@ -972,10 +997,7 @@ void mutt_FormatString (char *dest, /* output buffer */ src = callback (buf, sizeof (buf), ch, src, prefix, ifstring, elsestring, data, flags); if ((len = strlen (buf)) + wlen > destlen) - { - if ((len = destlen - wlen) < 0) - len = 0; - } + len = (destlen - wlen > 0) ? (destlen - wlen) : 0; memcpy (wptr, buf, len); wptr += len; wlen += len; @@ -1046,7 +1068,7 @@ FILE *mutt_open_read (const char *path, pid_t *thepid) s[len - 1] = 0; endwin (); *thepid = mutt_create_filter (s, NULL, &f, NULL); - free (s); + safe_free ((void **) &s); } else { @@ -1055,3 +1077,55 @@ FILE *mutt_open_read (const char *path, pid_t *thepid) } return (f); } + +/* returns 1 if OK to proceed, 0 to abort */ +int mutt_save_confirm (const char *s, struct stat *st) +{ + char tmp[_POSIX_PATH_MAX]; + int ret = 1; + int magic = 0; + + magic = mx_get_magic (s); + + if (stat (s, st) != -1) + { + if (magic == -1) + { + mutt_error ("%s is not a mailbox!", s); + return 0; + } + + if (option (OPTCONFIRMAPPEND)) + { + snprintf (tmp, sizeof (tmp), "Append messages to %s?", s); + if (mutt_yesorno (tmp, 1) < 1) + ret = 0; + } + } + else + { + if (magic != M_IMAP) + { + st->st_mtime = 0; + st->st_atime = 0; + + if (errno == ENOENT) + { + if (option (OPTCONFIRMCREATE)) + { + snprintf (tmp, sizeof (tmp), "Create %s?", s); + if (mutt_yesorno (tmp, 1) < 1) + ret = 0; + } + } + else + { + mutt_perror (s); + return 0; + } + } + } + + CLEARLINE (LINES-1); + return (ret); +} diff --git a/mailbox.h b/mailbox.h index 44b227ce..66e74738 100644 --- a/mailbox.h +++ b/mailbox.h @@ -57,3 +57,7 @@ int mx_close_message (MESSAGE **msg); int mx_get_magic (const char *); int mx_set_magic (const char *); int mx_check_mailbox (CONTEXT *, int *); +#ifdef USE_IMAP +int mx_is_imap (const char *); +#endif + diff --git a/main.c b/main.c index c0e2177a..b6b45aaa 100644 --- a/main.c +++ b/main.c @@ -126,11 +126,6 @@ static void show_version (void) #endif puts ( -#ifdef HIDDEN_HOST - "+HIDDEN_HOST " -#else - "-HIDDEN_HOST " -#endif #ifdef HOMESPOOL "+HOMESPOOL " @@ -251,7 +246,7 @@ static void show_version (void) - puts ("\nMail bug reports along with this output to <mutt-dev@cs.hmc.edu>."); + puts ("\nMail bug reports along with this output to <mutt-dev@mutt.org>."); exit (0); } @@ -312,34 +307,21 @@ int main (int argc, char **argv) extern char *optarg; extern int optind; - mutt_error = mutt_nocurses_error; + /* sanity check against stupid administrators */ + + if(getegid() != getgid()) + { + fprintf(stderr, "%s: I don't want to run with privileges!\n", + argv[0]); + exit(1); + } + + mutt_error = mutt_nocurses_error; SRAND (time (NULL)); setlocale (LC_CTYPE, ""); umask (077); -#ifdef USE_SETGID - /* Determine the user's default gid and the gid to use for locking the spool - * mailbox on those systems which require setgid "mail" to write to the - * directory. This function also resets the gid to "normal" since the - * effective gid will be "mail" when we start (Mutt attempts to run - * non-setgid whenever possible to reduce the possibility of security holes). - */ - - /* Get the default gid for the user */ - UserGid = getgid (); - - /* it is assumed that we are setgid to the correct gid to begin with */ - MailGid = getegid (); - - /* reset the effective gid to the normal gid */ - if (SETEGID (UserGid) != 0) - { - perror ("setegid"); - exit (0); - } -#endif - memset (Options, 0, sizeof (Options)); while ((i = getopt (argc, argv, "a:b:F:f:c:d:e:H:s:i:hm:npRvxyzZ")) != EOF) @@ -553,7 +535,7 @@ int main (int argc, char **argv) mutt_endwin (NULL); perror (tempfile); fclose (fin); - free (tempfile); + FREE (&tempfile); exit (1); } @@ -573,11 +555,11 @@ int main (int argc, char **argv) { if (a) { - a->next = mutt_make_attach (t->data); + a->next = mutt_make_file_attach (t->data); a = a->next; } else - msg->content = a = mutt_make_attach (t->data); + msg->content = a = mutt_make_file_attach (t->data); if (!a) { if (!option (OPTNOCURSES)) @@ -620,7 +602,7 @@ int main (int argc, char **argv) } if (!folder[0]) - strfcpy (folder, Spoolfile, sizeof (folder)); + strfcpy (folder, NONULL(Spoolfile), sizeof (folder)); mutt_expand_path (folder, sizeof (folder)); if (flags & M_IGNORE) @@ -645,7 +627,17 @@ int main (int argc, char **argv) if ((Context = mx_open_mailbox (folder, ((flags & M_RO) || option (OPTREADONLY)) ? M_READONLY : 0, NULL)) != NULL) { - mutt_index_menu (); + int close = mutt_index_menu (0); + + if (Context) + { + if (close == OP_QUIT) + mx_close_mailbox (Context); + else + mx_fastclose_mailbox (Context); + } + + safe_free ((void **)&Context); mutt_endwin (NULL); } else diff --git a/mbox.c b/mbox.c index 0e3211f4..edae95fd 100644 --- a/mbox.c +++ b/mbox.c @@ -40,60 +40,6 @@ struct m_update_t long body; }; -#ifdef USE_DOTLOCK -/* - * Determine whether or not to use a dotlock to lock the indicated file. - * On some systems, the spool directory is not world-writable. If it is - * group-writable, we might need to be setgid() to write the lock. If not - * group-writable, then we assume that fcntl() locking is enough and skip - * the dotlocking. - * - * return values: - * 2 need to be setgid to dotlock - * 1 can use a dotlock - * 0 don't use a dotlock - * -1 error - */ -static int can_dotlock (const char *path) -{ - char tmp[_POSIX_PATH_MAX]; - char *p; -#ifdef USE_SETGID - struct stat sb; -#endif - - strfcpy (tmp, path, sizeof (tmp)); - if ((p = strrchr (tmp, '/'))) - *p = 0; - else - strfcpy (tmp, ".", sizeof (tmp)); /* use current directory */ - - if (access (tmp, W_OK) == 0) return 1; - -#ifdef USE_SETGID - if (stat (tmp, &sb) == 0) - { - if ((sb.st_mode & S_IWGRP) == S_IWGRP) - { - /* can dotlock, but need to be setgid */ - if (sb.st_gid == MailGid) - return (2); - else - { - mutt_error ("Need to be running setgid %d to lock mailbox!", sb.st_gid); - return (-1); - } - } - } -#endif - - if (mutt_yesorno ("Can't dotlock mailbox, continue anyway?", 0) == 1) - return 0; - - return (-1); -} -#endif - /* parameters: * ctx - context to lock * excl - exclusive lock? @@ -101,36 +47,15 @@ static int can_dotlock (const char *path) */ int mbox_lock_mailbox (CONTEXT *ctx, int excl, int retry) { - int r = 0; - -#ifdef USE_DOTLOCK - r = can_dotlock (ctx->path); - - if (r == -1) - return (-1); -#ifdef USE_SETGID - else if (r == 2) - { - /* need to be setgid to lock the mailbox */ - if (SETEGID (MailGid) != 0) - { - mutt_perror ("setegid"); - return (-1); - } + int r; - ctx->setgid = 1; - } -#endif /* USE_SETGID */ -#endif /* USE_DOTLOCK */ + /* XXX - Currently, we force dotlocking. + * Use dotlock -t here. + */ - if ((r = mx_lock_file (ctx->path, fileno (ctx->fp), excl, r, retry)) == 0) + if ((r = mx_lock_file (ctx->path, fileno (ctx->fp), excl, 1, retry)) == 0) ctx->locked = 1; -#ifdef USE_SETGID - if (ctx->setgid) - SETEGID (UserGid); -#endif - return (r); } @@ -140,21 +65,8 @@ void mbox_unlock_mailbox (CONTEXT *ctx) { fflush (ctx->fp); -#ifdef USE_SETGID - if (ctx->setgid) - SETEGID (MailGid); -#endif /* USE_SETGID */ - mx_unlock_file (ctx->path, fileno (ctx->fp)); ctx->locked = 0; - -#ifdef USE_SETGID - if (ctx->setgid) - { - SETEGID (UserGid); - ctx->setgid = 0; - } -#endif } } @@ -915,7 +827,7 @@ int mbox_sync_mailbox (CONTEXT *ctx) char savefile[_POSIX_PATH_MAX]; snprintf (savefile, sizeof (savefile), "%s/mutt.%s-%s-%d", - NONULL (Tempdir), Username, Hostname, getpid ()); + NONULL (Tempdir), NONULL(Username), NONULL(Hostname), getpid ()); rename (tempfile, savefile); mutt_unblock_signals (); mx_fastclose_mailbox (ctx); @@ -987,21 +899,7 @@ bail: /* Come here in case of disaster */ /* close a mailbox opened in write-mode */ int mbox_close_mailbox (CONTEXT *ctx) { -#ifdef USE_SETGID - if (ctx->setgid) - SETEGID (MailGid); -#endif - mx_unlock_file (ctx->path, fileno (ctx->fp)); - -#ifdef USE_SETGID - if (ctx->setgid) - { - SETEGID (UserGid); - ctx->setgid = 0; - } -#endif - mutt_unblock_signals (); mx_fastclose_mailbox (ctx); return 0; diff --git a/menu.c b/menu.c index f582a1eb..734a0312 100644 --- a/menu.c +++ b/menu.c @@ -23,8 +23,6 @@ #include <string.h> #include <stdlib.h> -#define M_MODEFMT "-- Mutt: %s" - static void print_enriched_string (int attr, unsigned char *s, int do_color) { while (*s) @@ -555,6 +553,8 @@ MUTTMENU *mutt_new_menu (void) { MUTTMENU *p = (MUTTMENU *) safe_calloc (1, sizeof (MUTTMENU)); + p->current = 0; + p->top = 0; p->offset = 1; p->redraw = REDRAW_FULL; p->pagelen = PAGELEN; @@ -574,14 +574,16 @@ void mutt_menuDestroy (MUTTMENU **p) static int menu_search (MUTTMENU *menu, int op) { int r; - int searchDir = (menu->searchDir == M_SEARCH_UP) ? -1 : 1; + int searchDir; regex_t re; char buf[SHORT_STRING]; if (op != OP_SEARCH_NEXT && op != OP_SEARCH_OPPOSITE) { strfcpy (buf, menu->searchBuf ? menu->searchBuf : "", sizeof (buf)); - if (mutt_get_field ("Search for: ", buf, sizeof (buf), M_CLEAR) != 0 || !buf[0]) + if (mutt_get_field ((op == OP_SEARCH) ? "Search for: " : + "Reverse search for: ", + buf, sizeof (buf), M_CLEAR) != 0 || !buf[0]) return (-1); safe_free ((void **) &menu->searchBuf); menu->searchBuf = safe_strdup (buf); @@ -594,11 +596,12 @@ static int menu_search (MUTTMENU *menu, int op) mutt_error ("No search pattern."); return (-1); } - - if (op == OP_SEARCH_OPPOSITE) - searchDir = -searchDir; } + searchDir = (menu->searchDir == M_SEARCH_UP) ? -1 : 1; + if (op == OP_SEARCH_OPPOSITE) + searchDir = -searchDir; + if ((r = REGCOMP (&re, menu->searchBuf, REG_NOSUB | mutt_which_case (menu->searchBuf))) != 0) { regerror (r, &re, buf, sizeof (buf)); diff --git a/mh.c b/mh.c index ce724f3e..3ea7f158 100644 --- a/mh.c +++ b/mh.c @@ -324,7 +324,7 @@ int mh_valid_message (const char *s) { for (; *s; s++) { - if (!isdigit (*s)) + if (!isdigit ((unsigned char) *s)) return 0; } return 1; @@ -452,7 +452,7 @@ void maildir_create_filename (const char *path, HEADER *hdr, char *msg, char *fu FOREVER { snprintf (msg, _POSIX_PATH_MAX, "%s/%ld.%d_%d.%s%s", - subdir, time (NULL), getpid (), Counter++, Hostname, suffix); + subdir, time (NULL), getpid (), Counter++, NONULL(Hostname), suffix); snprintf (full, _POSIX_PATH_MAX, "%s/%s", path, msg); if (stat (full, &sb) == -1 && errno == ENOENT) return; } diff --git a/mime.h b/mime.h index 662bae1c..5dd30701 100644 --- a/mime.h +++ b/mime.h @@ -24,6 +24,7 @@ enum TYPEAPPLICATION, TYPEIMAGE, TYPEMESSAGE, + TYPEMODEL, TYPEMULTIPART, TYPETEXT, TYPEVIDEO @@ -53,8 +54,8 @@ extern int Index_hex[]; extern int Index_64[]; extern char Base64_chars[]; -#define hexval(c) Index_hex[(int)(c)] -#define base64val(c) Index_64[(int)(c)] +#define hexval(c) Index_hex[(unsigned int)(c)] +#define base64val(c) Index_64[(unsigned int)(c)] #define is_multipart(x) \ ((x)->type == TYPEMULTIPART \ @@ -64,5 +65,5 @@ extern char Base64_chars[]; extern const char *BodyTypes[]; extern const char *BodyEncodings[]; -#define TYPE(X) BodyTypes[(X)] +#define TYPE(X) ((X->type == TYPEOTHER) && (X->xtype != NULL) ? X->xtype : BodyTypes[(X->type)]) #define ENCODING(X) BodyEncodings[(X)] diff --git a/mutt.h b/mutt.h index 4620764d..2b7bc5f6 100644 --- a/mutt.h +++ b/mutt.h @@ -20,10 +20,15 @@ #include <stdio.h> #include <sys/types.h> +#include <sys/stat.h> #include <time.h> #include <limits.h> #include <stdarg.h> +#ifndef _POSIX_PATH_MAX +#include <posix1_lim.h> +#endif + #include "rfc822.h" #include "hash.h" @@ -93,7 +98,8 @@ typedef enum M_FORMAT_FORCESUBJ = (1<<0), /* print the subject even if unchanged */ M_FORMAT_TREE = (1<<1), /* draw the thread tree */ M_FORMAT_MAKEPRINT = (1<<2), /* make sure that all chars are printable */ - M_FORMAT_OPTIONAL = (1<<3) + M_FORMAT_OPTIONAL = (1<<3), + M_FORMAT_STAT_FILE = (1<<4) /* used by mutt_attach_fmt */ } format_flag; /* types for mutt_add_hook() */ @@ -102,6 +108,7 @@ typedef enum #define M_SENDHOOK (1<<2) #define M_FCCHOOK (1<<3) #define M_SAVEHOOK (1<<4) +#define M_PGPHOOK (1<<5) /* tree characters for linearize_tree and print_enriched_string */ #define M_TREE_LLCORNER 1 @@ -170,6 +177,9 @@ enum M_PRINT, M_AUTOVIEW, + /* options for socket code */ + M_NEW_SOCKET, + /* Options for mutt_save_attachment */ M_SAVE_APPEND }; @@ -219,23 +229,67 @@ enum /* boolean vars */ enum { - OPTPROMPTAFTER, - OPTSTATUSONTOP, OPTALLOW8BIT, - OPTASCIICHARS, - OPTMETOO, - OPTEDITHDRS, OPTARROWCURSOR, + OPTASCIICHARS, + OPTASKBCC, OPTASKCC, + OPTATTACHSPLIT, + OPTAUTOEDIT, + OPTAUTOTAG, + OPTBEEP, + OPTBEEPNEW, + OPTCHECKNEW, + OPTCONFIRMAPPEND, + OPTCONFIRMCREATE, + OPTEDITHDRS, + OPTFASTREPLY, + OPTFCCATTACH, + OPTFOLLOWUPTO, + OPTFORCENAME, + OPTFORWDECODE, + OPTFORWQUOTE, + OPTHDRS, OPTHEADER, + OPTHELP, + OPTHIDDENHOST, + OPTIGNORELISTREPLYTO, + OPTMARKERS, + OPTMARKOLD, + OPTMENUSCROLL, /* scroll menu instead of implicit next-page */ + OPTMETAKEY, /* interpret ALT-x as ESC-x */ + OPTMETOO, + OPTMIMEFORWDECODE, + OPTPAGERSTOP, + OPTPIPEDECODE, + OPTPIPESPLIT, + OPTPOPDELETE, + OPTPROMPTAFTER, + OPTREADONLY, + OPTRESOLVE, OPTREVALIAS, OPTREVNAME, - OPTFORCENAME, + OPTSAVEADDRESS, OPTSAVEEMPTY, - OPTPAGERSTOP, + OPTSAVENAME, OPTSIGDASHES, - OPTASKBCC, - OPTAUTOEDIT, + OPTSORTRE, + OPTSTATUSONTOP, + OPTSTRICTTHREADS, + OPTSUSPEND, + OPTTHOROUGHSRC, + OPTTILDE, + OPTUSE8BITMIME, + OPTUSEDOMAIN, + OPTUSEFROM, + OPTWAITKEY, + OPTWEED, + OPTWRAP, + OPTWRAPSEARCH, + OPTWRITEBCC, /* write out a bcc header? */ + + /* PGP options */ + #ifdef _PGPPATH OPTPGPAUTOSIGN, OPTPGPAUTOENCRYPT, @@ -245,44 +299,9 @@ enum OPTPGPENCRYPTSELF, OPTPGPSTRICTENC, #endif - OPTMARKOLD, - OPTCONFIRMCREATE, - OPTCONFIRMAPPEND, - OPTPOPDELETE, - OPTSAVENAME, - OPTTHOROUGHSRC, - OPTTILDE, - OPTMARKERS, - OPTFCCATTACH, - OPTPIPESPLIT, - OPTPIPEDECODE, - OPTREADONLY, - OPTRESOLVE, - OPTSTRICTTHREADS, - OPTAUTOTAG, - OPTBEEP, - OPTHELP, - OPTHDRS, - OPTWEED, - OPTWRAP, - OPTCHECKNEW, - OPTFASTREPLY, - OPTWAITKEY, - OPTWRAPSEARCH, - OPTIGNORELISTREPLYTO, - OPTSAVEADDRESS, - OPTSUSPEND, - OPTSORTRE, - OPTUSEDOMAIN, - OPTUSEFROM, - OPTUSE8BITMIME, - OPTFORWDECODE, - OPTMIMEFORWDECODE, - OPTFORWQUOTE, - OPTBEEPNEW, - OPTFOLLOWUPTO, - OPTMENUSCROLL, /* scroll menu instead of implicit next-page */ - OPTMETAKEY, /* interpret ALT-x as ESC-x */ + + /* pseudo options */ + OPTAUXSORT, /* (pseudo) using auxillary sort function */ OPTFORCEREFRESH, /* (pseudo) refresh even during macros */ OPTLOCALES, /* (pseudo) set if user has valid locale definition */ @@ -392,6 +411,7 @@ typedef struct content typedef struct body { + char *xtype; /* content-type if x-unknown */ char *subtype; /* content-type subtype */ PARAMETER *parameter; /* parameters of the content-type */ char *description; /* content-description */ @@ -420,6 +440,10 @@ typedef struct body struct body *parts; /* parts of a multipart or message/rfc822 */ struct header *hdr; /* header information for message/rfc822 */ + time_t stamp; /* time stamp of last + * encoding update. + */ + unsigned int type : 3; /* content-type primary type */ unsigned int encoding : 3; /* content-transfer-encoding */ unsigned int disposition : 2; /* content-disposition */ @@ -546,7 +570,6 @@ typedef struct int msgnotreadyet; /* which msg "new" in pager, -1 if none */ #ifdef USE_IMAP void *data; /* driver specific data */ - int fd; #endif /* USE_IMAP */ short magic; /* mailbox type */ @@ -566,6 +589,7 @@ typedef struct attachptr BODY *content; char *tree; int level; + int num; } ATTACHPTR; typedef struct diff --git a/mutt_menu.h b/mutt_menu.h index e30da697..fdbaf77e 100644 --- a/mutt_menu.h +++ b/mutt_menu.h @@ -31,6 +31,8 @@ #define REDRAW_FULL (1<<5) #define REDRAW_BODY (1<<6) +#define M_MODEFMT "-- Mutt: %s" + typedef struct menu_t { char *title; /* the title of this menu */ diff --git a/mutt_socket.h b/mutt_socket.h new file mode 100644 index 00000000..b3d53035 --- /dev/null +++ b/mutt_socket.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 1998 Brandon Long <blong@fiction.net> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _MUTT_SOCKET_H_ +#define _MUTT_SOCKET_H_ 1 + +typedef struct +{ + char *server; + int port; + int uses; + int fd; + char inbuf[LONG_STRING]; + int bufpos; + int available; +} CONNECTION; + +int mutt_socket_readchar (CONNECTION *conn, char *c); +int mutt_socket_read_line (char *buf, size_t buflen, CONNECTION *conn); +int mutt_socket_read_line_d (char *buf, size_t buflen, CONNECTION *conn); +int mutt_socket_write (CONNECTION *conn, const char *buf); +CONNECTION *mutt_socket_select_connection (char *host, int port, int flags); + +#endif /* _MUTT_SOCKET_H_ */ diff --git a/mx.c b/mx.c index 8147a64e..aaf1c45a 100644 --- a/mx.c +++ b/mx.c @@ -37,6 +37,10 @@ #include "buffy.h" #endif +#ifdef USE_DOTLOCK +#include "dotlock.h" +#endif + #include <dirent.h> #include <fcntl.h> #include <sys/file.h> @@ -55,156 +59,74 @@ #define S_ISLNK(x) (((x) & S_IFMT) == S_IFLNK ? 1 : 0) #endif -#define mutt_is_spool(s) (strcmp (Spoolfile, s) == 0) - -#define MAXLOCKATTEMPT 5 +#define mutt_is_spool(s) (strcmp (NONULL(Spoolfile), s) == 0) #ifdef USE_DOTLOCK /* parameters: * path - file to lock * retry - should retry if unable to lock? */ -static int dotlock_file (const char *path, int retry) -{ - const char *pathptr = path; - char lockfile[_POSIX_PATH_MAX]; - char nfslockfile[_POSIX_PATH_MAX]; - char realpath[_POSIX_PATH_MAX]; - struct stat sb; - size_t prev_size = 0; - int count = 0; - int attempt = 0; - int fd; - /* if the file is a symlink, find the real file to which it refers */ - FOREVER - { - dprint(2,(debugfile,"dotlock_file(): locking %s\n", pathptr)); +#ifdef DL_STANDALONE - if (lstat (pathptr, &sb) != 0) - { - mutt_perror (pathptr); - return (-1); - } +static int invoke_dotlock(const char *path, int flags, int retry) +{ + char cmd[LONG_STRING + _POSIX_PATH_MAX]; + char r[SHORT_STRING]; + + if(flags & DL_FL_RETRY) + snprintf(r, sizeof(r), "-r %d ", retry ? MAXLOCKATTEMPT : 0); + + snprintf(cmd, sizeof(cmd), + "%s %s%s%s%s%s%s", + DOTLOCK, + flags & DL_FL_TRY ? "-t " : "", + flags & DL_FL_UNLOCK ? "-u " : "", + flags & DL_FL_USEPRIV ? "-p " : "", + flags & DL_FL_FORCE ? "-f " : "", + flags & DL_FL_RETRY ? r : "", + path); + + return mutt_system(cmd); +} - if (S_ISLNK (sb.st_mode)) - { - char linkfile[_POSIX_PATH_MAX]; - char linkpath[_POSIX_PATH_MAX]; +#else - if ((count = readlink (pathptr, linkfile, sizeof (linkfile))) == -1) - { - mutt_perror (path); - return (-1); - } - linkfile[count] = 0; /* readlink() does not NUL terminate the string! */ - mutt_expand_link (linkpath, pathptr, linkfile); - strfcpy (realpath, linkpath, sizeof (realpath)); - pathptr = realpath; - } - else - break; - } - - snprintf (nfslockfile, sizeof (nfslockfile), "%s.%s.%d", pathptr, Hostname, (int) getpid ()); - snprintf (lockfile, sizeof (lockfile), "%s.lock", pathptr); - unlink (nfslockfile); +#define invoke_dotlock dotlock_invoke - while ((fd = open (nfslockfile, O_WRONLY | O_EXCL | O_CREAT, 0)) < 0) - if (errno != EAGAIN) - { - mutt_perror ("cannot open NFS lock file!"); - return (-1); - } +#endif - close (fd); +static int dotlock_file (const char *path, int retry) +{ + int r; + int flags = DL_FL_USEPRIV | DL_FL_RETRY; + + if(retry) retry = 1; - count = 0; - FOREVER +retry_lock: + mutt_clear_error(); + if((r = invoke_dotlock(path, flags, retry)) == DL_EX_EXIST) { - link (nfslockfile, lockfile); - if (stat (nfslockfile, &sb) != 0) - { - mutt_perror ("stat"); - return (-1); - } - - if (sb.st_nlink == 2) - break; - - if (stat (path, &sb) != 0) - sb.st_size = 0; - - if (count == 0) - prev_size = sb.st_size; + char msg[LONG_STRING]; - /* only try to remove the lock if the file is not changing */ - if (prev_size == sb.st_size && ++count >= retry ? MAXLOCKATTEMPT : 0) + snprintf(msg, sizeof(msg), "Lock count exceeded, remove lock for %s?", + path); + if(retry && mutt_yesorno(msg, 1) == 1) { - if (retry && mutt_yesorno ("Lock count exceeded, remove lock?", 1) == 1) - { - unlink (lockfile); - count = 0; - attempt = 0; - continue; - } - else - return (-1); + flags |= DL_FL_FORCE; + retry--; + goto retry_lock; } - - prev_size = sb.st_size; - - mutt_message ("Waiting for lock attempt #%d...", ++attempt); - sleep (1); } - - unlink (nfslockfile); - - return 0; + return (r == DL_EX_OK ? 0 : -1); } static int undotlock_file (const char *path) { - const char *pathptr = path; - char lockfile[_POSIX_PATH_MAX]; - char realpath[_POSIX_PATH_MAX]; - struct stat sb; - int n; - - FOREVER - { - dprint (2,(debugfile,"undotlock: unlocking %s\n",path)); - - if (lstat (pathptr, &sb) != 0) - { - mutt_perror (pathptr); - return (-1); - } - - if (S_ISLNK (sb.st_mode)) - { - char linkfile[_POSIX_PATH_MAX]; - char linkpath[_POSIX_PATH_MAX]; - - if ((n = readlink (pathptr, linkfile, sizeof (linkfile))) == -1) - { - mutt_perror (pathptr); - return (-1); - } - linkfile[n] = 0; /* readlink() does not NUL terminate the string! */ - mutt_expand_link (linkpath, pathptr, linkfile); - strfcpy (realpath, linkpath, sizeof (realpath)); - pathptr = realpath; - continue; - } - else - break; - } - - snprintf (lockfile, sizeof (lockfile), "%s.lock", pathptr); - unlink (lockfile); - return 0; + return (invoke_dotlock(path, DL_FL_USEPRIV | DL_FL_UNLOCK, 0) == DL_EX_OK ? + 0 : -1); } + #endif /* USE_DOTLOCK */ /* Args: @@ -248,7 +170,7 @@ int mx_lock_file (const char *path, int fd, int excl, int dot, int timeout) prev_sb = sb; /* only unlock file if it is unchanged */ - if (prev_sb.st_size == sb.st_size && ++count >= timeout?MAXLOCKATTEMPT:0) + if (prev_sb.st_size == sb.st_size && ++count >= (timeout?MAXLOCKATTEMPT:0)) { if (timeout) mutt_error ("Timeout exceeded while attempting fcntl lock!"); @@ -282,7 +204,7 @@ int mx_lock_file (const char *path, int fd, int excl, int dot, int timeout) prev_sb=sb; /* only unlock file if it is unchanged */ - if (prev_sb.st_size == sb.st_size && ++count >= timeout?MAXLOCKATTEMPT:0) + if (prev_sb.st_size == sb.st_size && ++count >= (timeout?MAXLOCKATTEMPT:0)) { if (timeout) mutt_error ("Timeout exceeded while attempting flock lock!"); @@ -370,7 +292,7 @@ FILE *mx_open_file_lock (const char *path, const char *mode) #ifdef USE_IMAP -static int mx_is_imap(const char *p) +int mx_is_imap(const char *p) { return p && (*p == '{'); } @@ -393,7 +315,6 @@ int mx_get_magic (const char *path) { dprint (1, (debugfile, "mx_get_magic(): unable to stat %s: %s (errno %d).\n", path, strerror (errno), errno)); - mutt_perror (path); return (-1); } @@ -483,7 +404,7 @@ static int mx_open_mailbox_append (CONTEXT *ctx) #ifdef USE_IMAP - if(mx_is_imap(ctx)) + if(mx_is_imap(ctx->path)) return imap_open_mailbox_append (ctx); #endif @@ -632,19 +553,22 @@ CONTEXT *mx_open_mailbox (const char *path, int flags, CONTEXT *pctx) return ctx; } - switch (ctx->magic = mx_get_magic (path)) - { - case 0: - mutt_error ("%s is not a mailbox.", path); - /* fall through */ + ctx->magic = mx_get_magic (path); + + if(ctx->magic == 0) + mutt_error ("%s is not a mailbox.", path); - case -1: - mx_fastclose_mailbox (ctx); - if (!pctx) - free (ctx); - return (NULL); + if(ctx->magic == -1) + mutt_perror(path); + + if(ctx->magic <= 0) + { + mx_fastclose_mailbox (ctx); + if (!pctx) + FREE (&ctx); + return (NULL); } - + /* if the user has a `push' command in their .muttrc, or in a folder-hook, * it will cause the progress messages not to be displayed because * mutt_refresh() will think we are in the middle of a macro. so set a @@ -817,7 +741,7 @@ int mx_close_mailbox (CONTEXT *ctx) } else { - strfcpy (mbox, Inbox, sizeof (mbox)); + strfcpy (mbox, NONULL(Inbox), sizeof (mbox)); isSpool = mutt_is_spool (ctx->path) && !mutt_is_spool (mbox); } mutt_expand_path (mbox, sizeof (mbox)); @@ -895,7 +819,7 @@ int mx_close_mailbox (CONTEXT *ctx) if (ctx->msgcount == ctx->deleted && (ctx->magic == M_MMDF || ctx->magic == M_MBOX) && - strcmp (ctx->path, Spoolfile) != 0 && !option (OPTSAVEEMPTY)) + !mutt_is_spool(ctx->path) && !option (OPTSAVEEMPTY)) unlink (ctx->path); mx_fastclose_mailbox (ctx); @@ -963,7 +887,7 @@ int mx_sync_mailbox (CONTEXT *ctx) if (ctx->msgcount == ctx->deleted && (ctx->magic == M_MBOX || ctx->magic == M_MMDF) && - strcmp (ctx->path, Spoolfile) != 0 && !option (OPTSAVEEMPTY)) + !mutt_is_spool(ctx->path) && !option (OPTSAVEEMPTY)) { unlink (ctx->path); mx_fastclose_mailbox (ctx); @@ -1056,7 +980,7 @@ int mh_open_new_message (MESSAGE *msg, CONTEXT *dest, HEADER *hdr) cp = de->d_name; while (*cp) { - if (!isdigit (*cp)) + if (!isdigit ((unsigned char) *cp)) break; cp++; } @@ -1162,7 +1086,7 @@ MESSAGE *mx_open_new_message (CONTEXT *dest, HEADER *hdr, int flags) if (dest->magic == M_MMDF) fputs (MMDF_SEP, msg->fp); - if ((msg->magic != M_MAILDIR) && (msg->magic != M_IMAP) && + if ((msg->magic != M_MAILDIR) && ((msg->magic != M_MH) && msg->magic != M_IMAP) && (flags & M_ADD_FROM)) { if (hdr) @@ -1181,7 +1105,7 @@ MESSAGE *mx_open_new_message (CONTEXT *dest, HEADER *hdr, int flags) else t = time (NULL); - fprintf (msg->fp, "From %s %s", p ? p->mailbox : Username, ctime (&t)); + fprintf (msg->fp, "From %s %s", p ? p->mailbox : NONULL(Username), ctime (&t)); } } else @@ -1417,8 +1341,7 @@ MESSAGE *mx_open_message (CONTEXT *ctx, int msgno) mutt_perror (path); dprint (1, (debugfile, "mx_open_message: fopen: %s: %s (errno %d).\n", path, strerror (errno), errno)); - free (msg); - msg = NULL; + FREE (&msg); } } break; @@ -1426,17 +1349,14 @@ MESSAGE *mx_open_message (CONTEXT *ctx, int msgno) #ifdef USE_IMAP case M_IMAP: if (imap_fetch_message (msg, ctx, msgno) != 0) - { - free (msg); - msg = NULL; - } + FREE (&msg); break; #endif /* USE_IMAP */ default: dprint (1, (debugfile, "mx_open_message(): function not implemented for mailbox type %d.\n", ctx->magic)); - safe_free ((void **) &msg); + FREE (&msg); break; } return (msg); @@ -1483,8 +1403,7 @@ int mx_close_message (MESSAGE **msg) break; } - free (*msg); - *msg = NULL; + FREE (msg); return (r); } diff --git a/mx.h b/mx.h index f03c5908..a430f1d8 100644 --- a/mx.h +++ b/mx.h @@ -34,6 +34,7 @@ enum WHERE short DefaultMagic INITVAL (M_MBOX); #define MMDF_SEP "\001\001\001\001\n" +#define MAXLOCKATTEMPT 5 int mbox_sync_mailbox (CONTEXT *); int mbox_open_mailbox (CONTEXT *); diff --git a/pager.c b/pager.c index 02fd2c79..3109dcfb 100644 --- a/pager.c +++ b/pager.c @@ -21,6 +21,7 @@ #include "mutt_regex.h" #include "keymap.h" #include "mutt_menu.h" +#include "mapping.h" #include "sort.h" #include "pager.h" #include "attach.h" @@ -1247,7 +1248,8 @@ upNLines (int nlines, struct line_t *info, int cur, int hiding) is there so that we can do operations on the current message without the need to pop back out to the main-menu. */ int -mutt_pager (const char *banner, const char *fname, int do_color, pager_t *extra) +mutt_pager (const char *banner, const char *fname, int do_color, pager_t *extra, + const char *attach_msg_status /* invoked while attaching a message */) { static char searchbuf[STRING]; char buffer[LONG_STRING]; @@ -1482,7 +1484,11 @@ mutt_pager (const char *banner, const char *fname, int do_color, pager_t *extra) menu_redraw_current (index); /* print out the index status bar */ - menu_status_line (buffer, sizeof (buffer), index, Status); + if (*attach_msg_status) + snprintf (buffer, sizeof (buffer), M_MODEFMT, attach_msg_status); + else + menu_status_line (buffer, sizeof (buffer), index, NONULL(Status)); + move (indexoffset + (option (OPTSTATUSONTOP) ? 0 : (indexlen - 1)), 0); SETCOLOR (MT_COLOR_STATUS); printw ("%-*.*s", COLS, COLS, buffer); @@ -1876,7 +1882,7 @@ mutt_pager (const char *banner, const char *fname, int do_color, pager_t *extra) { ch = -1; rc = OP_MAIN_NEXT_UNDELETED; - }; + } break; case OP_DELETE_THREAD: @@ -2050,7 +2056,7 @@ mutt_pager (const char *banner, const char *fname, int do_color, pager_t *extra) case OP_SAVE: if (IsAttach (extra)) { - mutt_save_attachment_list (extra->fp, 0, extra->bdy); + mutt_save_attachment_list (extra->fp, 0, extra->bdy, extra->hdr); break; } /* fall through */ diff --git a/pager.h b/pager.h index bc3fab23..b218addc 100644 --- a/pager.h +++ b/pager.h @@ -25,4 +25,4 @@ typedef struct } pager_t; int mutt_do_pager (const char *, const char *, int, pager_t *); -int mutt_pager (const char *, const char *, int, pager_t *); +int mutt_pager (const char *, const char *, int, pager_t *, const char *); diff --git a/parse.c b/parse.c index 3ae7f944..d1ab50a8 100644 --- a/parse.c +++ b/parse.c @@ -245,8 +245,7 @@ int mutt_check_mime_type (const char *s) static void parse_content_type (char *s, BODY *ct) { char *pc; - char buffer[SHORT_STRING]; - short i = 0; + char *subtype; safe_free((void **)&ct->subtype); mutt_free_parameter(&ct->parameter); @@ -265,21 +264,23 @@ static void parse_content_type (char *s, BODY *ct) } /* Now get the subtype */ - if ((pc = strchr(s, '/'))) + if ((subtype = strchr(s, '/'))) { - *pc++ = 0; - while (*pc && !ISSPACE (*pc) && *pc != ';') - { - buffer[i++] = *pc; - pc++; - } - buffer[i] = 0; - ct->subtype = safe_strdup (buffer); + *subtype++ = '\0'; + for(pc = subtype; *pc && !ISSPACE(*pc) && *pc != ';'; pc++) + ; + *pc = '\0'; + ct->subtype = safe_strdup (subtype); } /* Finally, get the major type */ ct->type = mutt_check_mime_type (s); + if (ct->type == TYPEOTHER) + { + ct->xtype = safe_strdup (s); + } + if (ct->subtype == NULL) { /* Some older non-MIME mailers (i.e., mailtool, elm) have a content-type @@ -293,6 +294,8 @@ static void parse_content_type (char *s, BODY *ct) ct->subtype = safe_strdup ("rfc822"); else if (ct->type == TYPEOTHER) { + char buffer[SHORT_STRING]; + ct->type = TYPEAPPLICATION; snprintf (buffer, sizeof (buffer), "x-%s", s); ct->subtype = safe_strdup (buffer); @@ -300,6 +303,7 @@ static void parse_content_type (char *s, BODY *ct) else ct->subtype = safe_strdup ("x-unknown"); } + } static void parse_content_disposition (char *s, BODY *ct) @@ -394,7 +398,7 @@ BODY *mutt_read_mime_header (FILE *fp, int digest) else if (p->type == TYPEMESSAGE && !p->subtype) p->subtype = safe_strdup ("rfc822"); - free (line); + FREE (&line); return (p); } @@ -665,7 +669,7 @@ static time_t parse_date (char *s, HEADER *h) switch (count) { case 0: /* day of the month */ - if (!isdigit (*t)) + if (!isdigit ((unsigned char) *t)) return (-1); tm.tm_mday = atoi (t); if (tm.tm_mday > 31) @@ -708,8 +712,8 @@ static time_t parse_date (char *s, HEADER *h) if (*ptz == '+' || *ptz == '-') { if (ptz[1] && ptz[2] && ptz[3] && ptz[4] - && isdigit (ptz[1]) && isdigit (ptz[2]) - && isdigit (ptz[3]) && isdigit (ptz[4])) + && isdigit ((unsigned char) ptz[1]) && isdigit ((unsigned char) ptz[2]) + && isdigit ((unsigned char) ptz[3]) && isdigit ((unsigned char) ptz[4])) { zhours = (ptz[1] - '0') * 10 + (ptz[2] - '0'); zminutes = (ptz[3] - '0') * 10 + (ptz[4] - '0'); @@ -1167,7 +1171,7 @@ ENVELOPE *mutt_read_rfc822_header (FILE *f, HEADER *hdr) loc = ftell (f); } - free (line); + FREE (&line); if (hdr) { diff --git a/patch.slang-1.2.2.keypad.1 b/patch.slang-1.2.2.keypad.1 new file mode 100644 index 00000000..93df4d72 --- /dev/null +++ b/patch.slang-1.2.2.keypad.1 @@ -0,0 +1,76 @@ +diff -ur slang.old/src/slcurses.c slang/src/slcurses.c +--- slang.old/src/slcurses.c Fri Apr 24 09:16:46 1998 ++++ slang/src/slcurses.c Sat Jul 4 07:30:31 1998 +@@ -134,7 +134,10 @@ + } + else if (ch == 0xFFFF) return ERR; + SLang_ungetkey (ch); +- return SLkp_getkey (); ++ if ((ch = SLkp_getkey ()) != SL_KEY_ERR) ++ return ch; ++ else ++ return SLang_getkey (); + } + return SLang_getkey (); + } +diff -ur slang.old/src/slkeymap.c slang/src/slkeymap.c +--- slang.old/src/slkeymap.c Fri Apr 24 09:16:47 1998 ++++ slang/src/slkeymap.c Sat Jul 4 07:41:42 1998 +@@ -343,6 +343,8 @@ + + SLang_Key_Type *SLang_do_key(SLKeyMap_List_Type *kml, int (*getkey)(void)) + { ++ unsigned char SLang_Undo_Buffer [SL_MAX_INPUT_BUFFER_LEN]; ++ int SLang_Undo_Len = 0; + register SLang_Key_Type *key, *next, *kmax; + unsigned int len; + unsigned char input_ch; +@@ -356,6 +358,7 @@ + return NULL; + + input_ch = (unsigned char) SLang_Last_Key_Char; ++ SLang_Undo_Buffer [SLang_Undo_Len++] = input_ch; + + key = (SLang_Key_Type *) &((kml->keymap)[input_ch]); + +@@ -372,7 +375,11 @@ + + key = kml->keymap + input_ch; + if (key->type == 0) ++ { ++ if (getkey == (int (*)(void)) SLang_getkey) ++ SLang_ungetkey_string (SLang_Undo_Buffer, SLang_Undo_Len); + return NULL; ++ } + } + + /* It appears to be a prefix character in a key sequence. */ +@@ -385,6 +392,7 @@ + { + SLang_Key_TimeOut_Flag = 1; + SLang_Last_Key_Char = (*getkey)(); ++ SLang_Undo_Buffer [SLang_Undo_Len++] = (unsigned char) SLang_Last_Key_Char; + SLang_Key_TimeOut_Flag = 0; + + len++; +@@ -458,6 +466,8 @@ + kmax = next; + } + ++ if (getkey == (int (*)(void)) SLang_getkey) ++ SLang_ungetkey_string (SLang_Undo_Buffer, SLang_Undo_Len); + return NULL; + } + +diff -ur slang.old/src/slkeypad.c slang/src/slkeypad.c +--- slang.old/src/slkeypad.c Fri Apr 24 09:16:47 1998 ++++ slang/src/slkeypad.c Sat Jul 4 07:30:31 1998 +@@ -110,7 +110,7 @@ + key = SLang_do_key (Keymap_List, (int (*)(void)) SLang_getkey); + if ((key == NULL) || (key->type != SLKEY_F_KEYSYM)) + { +- SLang_flush_input (); ++ /* SLang_flush_input (); */ + return SL_KEY_ERR; + } + diff --git a/pattern.c b/pattern.c index 0435ac76..2b6d857c 100644 --- a/pattern.c +++ b/pattern.c @@ -108,7 +108,7 @@ int mutt_which_case (const char *s) { while (*s) { - if (isalpha (*s) && isupper (*s)) + if (isalpha ((unsigned char) *s) && isupper ((unsigned char) *s)) return 0; /* case-sensitive */ s++; } @@ -242,14 +242,17 @@ int eat_regexp (pattern_t *pat, BUFFER *s, BUFFER *err) int eat_range (pattern_t *pat, BUFFER *s, BUFFER *err) { char *tmp; - + int do_exclusive = 0; + + if (*s->dptr == '<') + do_exclusive = 1; if ((*s->dptr != '-') && (*s->dptr != '<')) { /* range minimum */ if (*s->dptr == '>') { pat->max = M_MAXRANGE; - pat->min = strtol (s->dptr + 1, &tmp, 0); + pat->min = strtol (s->dptr + 1, &tmp, 0) + 1; /* exclusive range */ } else pat->min = strtol (s->dptr, &tmp, 0); @@ -283,7 +286,7 @@ int eat_range (pattern_t *pat, BUFFER *s, BUFFER *err) tmp = s->dptr; } - if (isdigit (*tmp)) + if (isdigit ((unsigned char) *tmp)) { /* range maximum */ pat->max = strtol (tmp, &tmp, 0); @@ -297,6 +300,8 @@ int eat_range (pattern_t *pat, BUFFER *s, BUFFER *err) pat->max *= 1048576; tmp++; } + if (do_exclusive) + (pat->max)--; } else pat->max = M_MAXRANGE; @@ -792,7 +797,7 @@ mutt_pattern_exec (struct pattern_t *pat, pattern_exec_flag flags, CONTEXT *ctx, return (pat->not ^ (h->score >= pat->min && (pat->max == M_MAXRANGE || h->score <= pat->max))); case M_SIZE: - return (pat->not ^ (h->content->length > pat->min && (pat->max == M_MAXRANGE || h->content->length < pat->max))); + return (pat->not ^ (h->content->length >= pat->min && (pat->max == M_MAXRANGE || h->content->length <= pat->max))); case M_REFERENCE: return (pat->not ^ match_reference (pat->rx, h->env->references)); case M_ADDRESS: @@ -865,7 +870,7 @@ void mutt_check_simple (char *s, size_t len, const char *simple) } } -int mutt_pattern_func (int op, char *prompt, HEADER *hdr) +int mutt_pattern_func (int op, char *prompt) { pattern_t *pat; char buf[LONG_STRING] = "", *simple, error[STRING]; diff --git a/pgp.c b/pgp.c index 36e4497b..28c1fac8 100644 --- a/pgp.c +++ b/pgp.c @@ -1110,7 +1110,7 @@ BODY *pgp_sign_message (BODY *a) */ char *pgp_findKeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc) { - char *key, *keylist = NULL; + char *key, *keyID, *keylist = NULL; size_t keylist_size = 0; size_t keylist_used = 0; ADDRESS *tmp = NULL; @@ -1145,9 +1145,17 @@ char *pgp_findKeys (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc) for (p = tmp; p ; p = p->next) { - if ((k_info = ki_getkeybyaddr (pgp, p, db, KEYFLAG_CANENCRYPT)) == NULL) + char buf[LONG_STRING]; + + k_info = NULL; + if ((keyID = mutt_pgp_hook (p)) != NULL) + { + snprintf (buf, sizeof (buf), "Use keyID = \"%s\" for %s?", keyID, p->mailbox); + if (mutt_yesorno (buf, M_YES) == M_YES) + k_info = ki_getkeybystr (pgp, keyID, db, KEYFLAG_CANENCRYPT); + } + if (k_info == NULL && (k_info = ki_getkeybyaddr (pgp, p, db, KEYFLAG_CANENCRYPT)) == NULL) { - char buf[LONG_STRING]; snprintf (buf, sizeof (buf), "Enter keyID for %s: ", p->mailbox); if ((key = pgp_ask_for_key (pgp, db, buf, p->mailbox, diff --git a/pgppubring.c b/pgppubring.c index cbd53c1c..c3499ea6 100644 --- a/pgppubring.c +++ b/pgppubring.c @@ -542,8 +542,6 @@ static KEYINFO *pgp_parse_keyinfo(unsigned char *buff, size_t l) static int pgp_parse_pgp2_sig(unsigned char *buff, size_t l, KEYINFO *p) { unsigned char sigtype; - unsigned char pkalg; - unsigned char hashalg; long sig_gen_time; unsigned long signerid; size_t j; @@ -564,9 +562,6 @@ static int pgp_parse_pgp2_sig(unsigned char *buff, size_t l, KEYINFO *p) for(i = 0; i < 4; i++) signerid = (signerid << 8) + buff[j++]; - pkalg = buff[j++]; - hashalg = buff[j++]; - if(sigtype == 0x20 || sigtype == 0x28) p->flags |= KEYFLAG_REVOKED; @@ -621,9 +616,9 @@ static int pgp_parse_pgp3_sig(unsigned char *buff, size_t l, KEYINFO *p) if(!--ml) break; } - ml -= skl; - if(ml < 0) + if((int) ml - (int) skl < 0) break; + ml -= skl; nextone = j + skl; skt = buff[j++]; @@ -795,6 +790,9 @@ static KEYINFO *pgp_read_keyring(const char *fname) case PT_NAME: { char *chr; + + if(!addr) break; + chr = safe_malloc(l); memcpy(chr, buff + 1, l - 1); chr[l-1] = '\0'; @@ -835,13 +833,21 @@ KEYINFO *pgp_read_secring(struct pgp_vinfo *pgp) void pgp_close_keydb (KEYINFO **ki) { KEYINFO *tmp, *k = *ki; - LIST *q; + PGPUID *uid; + LIST *p, *q; while (k) { if (k->keyid) safe_free ((void **)&k->keyid); - for(q = k->address; q; q = q-> next) + for(q = k->address; q; q = p) + { + uid = (PGPUID *) q->data; + p = q->next; + + safe_free((void **)&uid->addr); safe_free((void **)&q->data); + safe_free((void **)&q); + } tmp = k; k = k->next; safe_free ((void **)&tmp); diff --git a/pop.c b/pop.c index c3495a04..76e7fd50 100644 --- a/pop.c +++ b/pop.c @@ -62,7 +62,9 @@ static int getPass (void) if (!PopPass) { char tmp[SHORT_STRING]; - if (mutt_get_password ("POP Password: ", tmp, sizeof (tmp)) != 0) + tmp[0] = '\0'; + if (mutt_get_password ("POP Password: ", tmp, sizeof (tmp)) != 0 + || *tmp == '\0') return 0; PopPass = safe_strdup (tmp); } @@ -104,10 +106,10 @@ void mutt_fetchPopMail (void) sin.sin_family = AF_INET; sin.sin_port = htons (PopPort); - if ((n = inet_addr (PopHost)) == -1) + if ((n = inet_addr (NONULL(PopHost))) == -1) { /* Must be a DNS name */ - if ((he = gethostbyname (PopHost)) == NULL) + if ((he = gethostbyname (NONULL(PopHost))) == NULL) { mutt_error ("Could not find address for host %s.", PopHost); return; @@ -135,7 +137,7 @@ void mutt_fetchPopMail (void) goto finish; } - sprintf (buffer, "user %s\r\n", PopUser); + snprintf (buffer, sizeof(buffer), "user %s\r\n", PopUser); write (s, buffer, strlen (buffer)); if (getLine (s, buffer, sizeof (buffer)) == -1) @@ -148,7 +150,7 @@ void mutt_fetchPopMail (void) goto finish; } - sprintf (buffer, "pass %s\r\n", PopPass); + snprintf (buffer, sizeof(buffer), "pass %s\r\n", NONULL(PopPass)); write (s, buffer, strlen (buffer)); if (getLine (s, buffer, sizeof (buffer)) == -1) @@ -156,7 +158,10 @@ void mutt_fetchPopMail (void) if (strncmp (buffer, "+OK", 3) != 0) { - PopPass[0] = 0; /* void the given password */ + if(PopPass) + memset(PopPass, 0, strlen(PopPass)); + + safe_free((void **) &PopPass); /* void the given password */ mutt_remove_trailing_ws (buffer); mutt_error (buffer[0] ? buffer : "Server closed connection!"); goto finish; @@ -183,7 +188,7 @@ void mutt_fetchPopMail (void) goto finish; } - if (mx_open_mailbox (Spoolfile, M_APPEND, &ctx) == NULL) + if (mx_open_mailbox (NONULL(Spoolfile), M_APPEND, &ctx) == NULL) goto finish; snprintf (msgbuf, sizeof (msgbuf), @@ -192,7 +197,7 @@ void mutt_fetchPopMail (void) for (i = 1 ; i <= msgs ; i++) { - sprintf (buffer, "retr %d\r\n", i); + snprintf (buffer, sizeof(buffer), "retr %d\r\n", i); write (s, buffer, strlen (buffer)); if (getLine (s, buffer, sizeof (buffer)) == -1) @@ -268,7 +273,7 @@ void mutt_fetchPopMail (void) if (option (OPTPOPDELETE)) { /* delete the message on the server */ - sprintf (buffer, "dele %d\r\n", i); + snprintf (buffer, sizeof(buffer), "dele %d\r\n", i); write (s, buffer, strlen (buffer)); /* eat the server response */ diff --git a/postpone.c b/postpone.c index b8bf6cf8..0ef74fbe 100644 --- a/postpone.c +++ b/postpone.c @@ -241,8 +241,12 @@ int mutt_get_postponed (CONTEXT *ctx, HEADER *hdr, HEADER **cur) file[0] = '\0'; if (b->filename) strfcpy (file, b->filename, sizeof (file)); - mutt_adv_mktemp (file); - if (mutt_save_attachment (msg->fp, b, file, 0) == -1) + else + /* avoid Content-Disposition: header with temporary filename */ + b->use_disp = 0; + + mutt_adv_mktemp (file, sizeof(file)); + if (mutt_save_attachment (msg->fp, b, file, 0, NULL) == -1) { mutt_free_envelope (&hdr->env); mutt_free_body (&hdr->content); @@ -255,6 +259,7 @@ int mutt_get_postponed (CONTEXT *ctx, HEADER *hdr, HEADER **cur) b->filename = safe_strdup (file); b->unlink = 1; mutt_free_body (&b->parts); + mutt_stamp_attachment(b); b = b->next; } h->content->parts = NULL; @@ -262,7 +267,7 @@ int mutt_get_postponed (CONTEXT *ctx, HEADER *hdr, HEADER **cur) else { mutt_mktemp (file); - if (mutt_save_attachment (msg->fp, h->content, file, 0) == -1) + if (mutt_save_attachment (msg->fp, h->content, file, 0, NULL) == -1) { mutt_free_envelope (&hdr->env); mx_close_message (&msg); @@ -270,7 +275,7 @@ int mutt_get_postponed (CONTEXT *ctx, HEADER *hdr, HEADER **cur) safe_free ((void **) &PostContext); return (-1); } - hdr->content = mutt_make_attach (file); + hdr->content = mutt_make_file_attach (file); hdr->content->use_disp = 0; /* no content-disposition */ hdr->content->unlink = 1; /* delete when we are done */ } diff --git a/protos.h b/protos.h index 38a1ad29..808b009d 100644 --- a/protos.h +++ b/protos.h @@ -70,7 +70,8 @@ ADDRESS *mutt_expand_aliases (ADDRESS *); ADDRESS *mutt_parse_adrlist (ADDRESS *, const char *); BODY *mutt_dup_body (BODY *); -BODY *mutt_make_attach (const char *); +BODY *mutt_make_file_attach (const char *); +BODY *mutt_make_message_attach (CONTEXT *, HEADER *, int); BODY *mutt_make_multipart (BODY *); BODY *mutt_new_body (void); BODY *mutt_parse_multipart (FILE *, const char *, long, int); @@ -86,18 +87,34 @@ time_t mutt_local_tz (void); time_t mutt_mktime (struct tm *, int); time_t is_from (const char *, char *, size_t); +const char *mutt_attach_fmt ( + char *dest, + size_t destlen, + char op, + const char *src, + const char *prefix, + const char *ifstring, + const char *elsestring, + unsigned long data, + format_flag flags); + char *mutt_expand_path (char *, size_t); char *mutt_find_hook (int, const char *); char *mutt_generate_boundary (void); char *mutt_gen_msgid (void); char *mutt_get_name (ADDRESS *); char *mutt_get_parameter (const char *, PARAMETER *); +#ifdef _PGPPATH +char *mutt_pgp_hook (ADDRESS *); +#endif /* _PGPPATH */ char *mutt_read_line (char *, size_t *, FILE *, int *); char *mutt_strlower (char *); char *mutt_skip_whitespace (char *); char *mutt_substrcpy (char *, const char *, const char *, size_t); char *mutt_substrdup (const char *, const char *); +const char *mutt_fqdn(short); + void mutt_add_child_pid (pid_t); void mutt_alias_menu (char *, size_t, ALIAS *); void mutt_block_signals (void); @@ -128,8 +145,6 @@ void mutt_free_header (HEADER **); void mutt_free_parameter (PARAMETER **); void mutt_generate_header (char *, size_t, HEADER *, int); void mutt_help (int); -void mutt_index_menu (void); -void mutt_init_history (void); void mutt_linearize_tree (CONTEXT *, int); void mutt_make_help (char *, size_t, char *, int, int); void mutt_message (const char *, ...); @@ -147,6 +162,7 @@ void mutt_remove_trailing_ws (char *); void mutt_query_exit (void); void mutt_query_menu (char *, size_t); void mutt_safe_path (char *s, size_t l, ADDRESS *a); +void mutt_sanitize_filename (char *); void mutt_save_path (char *s, size_t l, ADDRESS *a); void mutt_score_message (HEADER *); void mutt_select_fcc (char *, size_t, HEADER *); @@ -156,6 +172,7 @@ void mutt_set_flag (CONTEXT *, HEADER *, int, int); void mutt_shell_escape (void); void mutt_show_error (void); void mutt_signal_init (void); +void mutt_stamp_attachment (BODY *a); void mutt_tabs_to_spaces (char *); void mutt_tag_set_flag (int, int); void mutt_unblock_signals (void); @@ -187,15 +204,17 @@ int mutt_compose_attachment (BODY *a); int mutt_copy_bytes (FILE *, FILE *, size_t); int mutt_copy_stream (FILE *, FILE *); int mutt_decode_save_attachment (FILE *, BODY *, char *, int, int); -int mutt_display_message (HEADER *h); -int mutt_edit_attachment(BODY *, int); +int mutt_display_message (HEADER *h, const char *); +int mutt_edit_attachment(BODY *); int mutt_enter_fname (const char *, char *, size_t, int *, int); int mutt_enter_string (unsigned char *, size_t, int, int, int); int mutt_get_field (char *, char *, size_t, int); int mutt_get_password (char *, char *, size_t); int mutt_get_postponed (CONTEXT *, HEADER *, HEADER **); +int mutt_index_menu (int); int mutt_is_autoview (char *); int mutt_is_mail_list (ADDRESS *); +int mutt_is_message_type(int, const char *); int mutt_is_list_recipient (ADDRESS *a); int mutt_is_text_type (int, char *); int mutt_is_valid_mailbox (const char *); @@ -208,16 +227,17 @@ int mutt_parse_hook (BUFFER *, BUFFER *, unsigned long, BUFFER *); int mutt_parse_macro (BUFFER *, BUFFER *, unsigned long, BUFFER *); int mutt_parse_mailboxes (BUFFER *, BUFFER *, unsigned long, BUFFER *); int mutt_parse_mono (BUFFER *, BUFFER *, unsigned long, BUFFER *); +int mutt_parse_unmono (BUFFER *, BUFFER *, unsigned long, BUFFER *); int mutt_parse_push (BUFFER *, BUFFER *, unsigned long, BUFFER *); int mutt_parse_rc_line (/* const */ char *, BUFFER *, BUFFER *); int mutt_parse_score (BUFFER *, BUFFER *, unsigned long, BUFFER *); int mutt_parse_unscore (BUFFER *, BUFFER *, unsigned long, BUFFER *); -int mutt_pattern_func (int, char *, HEADER *); +int mutt_pattern_func (int, char *); int mutt_pipe_attachment (FILE *, BODY *, const char *, char *); int mutt_pipe_message (HEADER *); int mutt_print_attachment (FILE *, BODY *); int mutt_query_complete (char *, size_t); -int mutt_save_attachment (FILE *, BODY *, char *, int); +int mutt_save_attachment (FILE *, BODY *, char *, int, HEADER *); int mutt_save_message (HEADER *, int, int, int *); int mutt_search_command (int, int); int mutt_send_menu (HEADER *, char *, size_t, HEADER *); @@ -234,6 +254,7 @@ int mutt_write_rfc822_header (FILE *, ENVELOPE *, BODY *, int); int mutt_yesorno (const char *, int); void mutt_cache_index_colors(CONTEXT *); void mutt_set_header_color(CONTEXT *, HEADER *); +int mutt_save_confirm (const char *, struct stat *); int mh_valid_message (const char *); @@ -248,6 +269,7 @@ void *safe_malloc (unsigned int); void safe_realloc (void **, size_t); void safe_free (void **); +int safe_open (const char *, int); FILE *safe_fopen (const char *, const char *); ADDRESS *alias_reverse_lookup (ADDRESS *); @@ -267,7 +289,7 @@ ADDRESS *alias_reverse_lookup (ADDRESS *); ((unsigned char)(c) >= 0xa0))) #endif -#define new_pattern() calloc(1, sizeof (pattern_t)) +#define new_pattern() safe_calloc(1, sizeof (pattern_t)) int mutt_pattern_exec (struct pattern_t *pat, pattern_exec_flag flags, CONTEXT *ctx, HEADER *h); pattern_t *mutt_pattern_comp (/* const */ char *s, int flags, BUFFER *err); @@ -288,12 +310,6 @@ void mutt_pattern_free (pattern_t **pat); #define DRAND (double)rand #endif /* HAVE_SRAND48 */ -#ifdef HAVE_SETEGID -#define SETEGID setegid -#else -#define SETEGID setgid -#endif - int getdnsdomainname (char *, size_t); /* According to SCO support, this is how to detect SCO */ diff --git a/query.c b/query.c index b8cfe09b..d8ae80ae 100644 --- a/query.c +++ b/query.c @@ -18,6 +18,7 @@ #include "mutt.h" #include "mutt_menu.h" +#include "mapping.h" #include "sort.h" #include <string.h> diff --git a/reap.pl b/reap.pl index 90e532bd..43b44646 100755 --- a/reap.pl +++ b/reap.pl @@ -1,4 +1,4 @@ -#!/usr/local/bin/perl +#!/usr/bin/perl # # A small script to strip out any "illegal" PGP code to make sure it is # safe for International export. diff --git a/recvattach.c b/recvattach.c index 670bf495..cd16309d 100644 --- a/recvattach.c +++ b/recvattach.c @@ -39,6 +39,7 @@ #include <stdlib.h> #include <unistd.h> #include <sys/wait.h> +#include <sys/stat.h> #include <string.h> #include <errno.h> @@ -59,6 +60,7 @@ void mutt_update_tree (ATTACHPTR **idx, short idxlen) for (x = 0; x < idxlen; x++) { + idx[x]->num = x; if (2 * (idx[x]->level + 2) < sizeof (buf)) { if (idx[x]->level) @@ -118,9 +120,7 @@ ATTACHPTR **mutt_gen_attach_list (BODY *m, new->level = level; /* We don't support multipart messages in the compose menu yet */ - if (!compose && m->type == TYPEMESSAGE && - (!strcasecmp (m->subtype, "rfc822") || - !strcasecmp (m->subtype, "news")) && is_multipart (m->parts)) + if (!compose && mutt_is_message_type(m->type, m->subtype) && is_multipart (m->parts)) { idx = mutt_gen_attach_list (m->parts, idx, idxlen, idxmax, level + 1, compose); } @@ -133,32 +133,117 @@ ATTACHPTR **mutt_gen_attach_list (BODY *m, return (idx); } +/* %D = deleted flag + %d = description + %e = MIME content-transfer-encoding + %f = filename + %t = tagged flag + %m = major MIME type + %M = MIME subtype + %n = attachment number + %s = size + %u = unlink */ +const char *mutt_attach_fmt (char *dest, + size_t destlen, + char op, + const char *src, + const char *prefix, + const char *ifstring, + const char *elsestring, + unsigned long data, + format_flag flags) +{ + char fmt[16]; + ATTACHPTR *aptr = (ATTACHPTR *) data; + + switch (op) + { + case 'd': + snprintf (fmt, sizeof (fmt), "%%%ss", prefix); + if (aptr->content->description) + { + snprintf (dest, destlen, fmt, aptr->content->description); + break; + } + if (mutt_is_message_type(aptr->content->type, aptr->content->subtype) && + MsgFmt && aptr->content->hdr) + { + char s[SHORT_STRING]; + _mutt_make_string (s, sizeof (s), MsgFmt, NULL, aptr->content->hdr, + M_FORMAT_FORCESUBJ | M_FORMAT_MAKEPRINT); + if (*s) + { + snprintf (dest, destlen, fmt, s); + break; + } + } + if (!aptr->content->filename) + { + snprintf (dest, destlen, fmt, "<no description>"); + break; + } + /* FALLS THROUGH TO 'f' */ + case 'f': + snprintf (fmt, sizeof (fmt), "%%%ss", prefix); + if (aptr->content->filename && *aptr->content->filename == '/') + { + char path[_POSIX_PATH_MAX]; + + strfcpy (path, aptr->content->filename, sizeof (path)); + mutt_pretty_mailbox (path); + snprintf (dest, destlen, fmt, path); + } + else + snprintf (dest, destlen, fmt, NONULL (aptr->content->filename)); + break; + case 'D': + snprintf (dest, destlen, "%c", aptr->content->deleted ? 'D' : ' '); + break; + case 'e': + snprintf (fmt, sizeof (fmt), "%%%ss", prefix); + snprintf (dest, destlen, fmt, ENCODING (aptr->content->encoding)); + break; + case 'm': + snprintf (fmt, sizeof (fmt), "%%%ss", prefix); + snprintf (dest, destlen, fmt, TYPE (aptr->content)); + break; + case 'M': + snprintf (fmt, sizeof (fmt), "%%%ss", prefix); + snprintf (dest, destlen, fmt, aptr->content->subtype); + break; + case 'n': + snprintf (fmt, sizeof (fmt), "%%%sd", prefix); + snprintf (dest, destlen, fmt, aptr->num + 1); + break; + case 's': + if (flags & M_FORMAT_STAT_FILE) + { + struct stat st; + + stat (aptr->content->filename, &st); + mutt_pretty_size (dest, destlen, st.st_size); + } + else + mutt_pretty_size (dest, destlen, aptr->content->length); + break; + case 't': + snprintf (dest, destlen, "%c", aptr->content->tagged ? '*' : ' '); + break; + case 'T': + snprintf (dest, destlen, "%s", NONULL (aptr->tree)); + break; + case 'u': + snprintf (dest, destlen, "%c", aptr->content->unlink ? '-' : ' '); + break; + default: + *dest = 0; + } + return (src); +} + void attach_entry (char *b, size_t blen, MUTTMENU *menu, int num) { - char t[SHORT_STRING]; - char s[SHORT_STRING]; - char size[SHORT_STRING]; - ATTACHPTR **idx = (ATTACHPTR **) menu->data; - BODY *m; - - m = idx[num]->content; - s[0] = 0; - if (m->type == TYPEMESSAGE && (!strcasecmp ("rfc822", m->subtype) || - !strcasecmp ("news", m->subtype)) && MsgFmt[0]) - _mutt_make_string (s, sizeof (s), MsgFmt, NULL, m->hdr, - M_FORMAT_FORCESUBJ | M_FORMAT_MAKEPRINT); - - mutt_pretty_size (size, sizeof (size), m->length); - snprintf (t, sizeof (t), "[%.7s/%.10s, %.6s, %s]", - TYPE (m->type), m->subtype, ENCODING (m->encoding), size); - snprintf (b, blen, " %c%c %2d %-34.34s %s%s", - m->deleted ? 'D' : ' ', - m->tagged ? '*' : ' ', - num + 1, - t, - idx[num]->tree ? idx[num]->tree : "", - s[0] ? s : (m->description ? m->description : - (m->filename ? m->filename : "<no description>"))); + mutt_FormatString (b, blen, NONULL (AttachFormat), mutt_attach_fmt, (unsigned long) (((ATTACHPTR **)menu->data)[num]), 0); } int mutt_tag_attach (MUTTMENU *menu, int n) @@ -166,35 +251,119 @@ int mutt_tag_attach (MUTTMENU *menu, int n) return (((ATTACHPTR **) menu->data)[n]->content->tagged = !((ATTACHPTR **) menu->data)[n]->content->tagged); } -static void mutt_query_save_attachment (FILE *fp, BODY *body) +int mutt_is_message_type (int type, const char *subtype) { - char buf[_POSIX_PATH_MAX], tfile[_POSIX_PATH_MAX]; + if (type != TYPEMESSAGE) + return 0; + + subtype = NONULL(subtype); + return (strcasecmp (subtype, "rfc822") == 0 || strcasecmp (subtype, "news") == 0); +} - if (fp && body->filename) +static int mutt_query_save_attachment (FILE *fp, BODY *body, HEADER *hdr) +{ + char buf[_POSIX_PATH_MAX], tfile[_POSIX_PATH_MAX]; + int is_message; + + if (body->filename) strfcpy (buf, body->filename, sizeof (buf)); + else if(body->hdr && + body->encoding != ENCBASE64 && + body->encoding != ENCQUOTEDPRINTABLE && + mutt_is_message_type(body->type, body->subtype)) + mutt_default_save(buf, sizeof(buf), body->hdr); else buf[0] = 0; - if (mutt_get_field ("Save to file: ", buf, sizeof (buf), M_FILE | M_CLEAR) != 0 || !buf[0]) - return; + + if (mutt_get_field ("Save to file: ", buf, sizeof (buf), M_FILE | M_CLEAR) != 0 + || !buf[0]) + return -1; + mutt_expand_path (buf, sizeof (buf)); - if (mutt_check_overwrite (body->filename, buf, tfile, sizeof (tfile), 0)) - return; + + is_message = (fp && + body->hdr && + body->encoding != ENCBASE64 && + body->encoding != ENCQUOTEDPRINTABLE && + mutt_is_message_type (body->type, body->subtype)); + + if (is_message) + { + struct stat st; + + /* check to make sure that this file is really the one the user wants */ + if (!mutt_save_confirm (buf, &st)) + { + CLEARLINE (LINES-1); + return -1; + } + strfcpy(tfile, buf, sizeof(tfile)); + } + else if (mutt_check_overwrite (body->filename, buf, tfile, sizeof (tfile), 0)) + return -1; + mutt_message ("Saving..."); - if (mutt_save_attachment (fp, body, tfile, 0) == 0) + if (mutt_save_attachment (fp, body, tfile, 0, (hdr || !is_message) ? hdr : body->hdr) == 0) + { mutt_message ("Attachment saved."); + return 0; + } + + return -1; + } -void mutt_save_attachment_list (FILE *fp, int tag, BODY *top) +void mutt_save_attachment_list (FILE *fp, int tag, BODY *top, HEADER *hdr) { + char buf[_POSIX_PATH_MAX], tfile[_POSIX_PATH_MAX]; + int rc = 1; + FILE *fpout; + + buf[0] = 0; + for (; top; top = top->next) { if (!tag || top->tagged) - mutt_query_save_attachment (fp, top); + { + if (!option (OPTATTACHSPLIT)) + { + if (!buf[0]) + { + strfcpy (buf, NONULL (top->filename), sizeof (buf)); + if (mutt_get_field ("Save to file: ", buf, sizeof (buf), + M_FILE | M_CLEAR) != 0 || !buf[0]) + return; + mutt_expand_path (buf, sizeof (buf)); + if (mutt_check_overwrite (top->filename, buf, tfile, sizeof (tfile), 0)) + return; + rc = mutt_save_attachment (fp, top, tfile, 0, hdr); + if (rc == 0 && AttachSep && (fpout = fopen (tfile,"a")) != NULL) + { + fprintf(fpout, "%s", AttachSep); + fclose (fpout); + } + } + else + { + rc = mutt_save_attachment (fp, top, tfile, M_SAVE_APPEND, hdr); + if (rc == 0 && AttachSep && (fpout = fopen (tfile,"a")) != NULL) + { + fprintf(fpout, "%s", AttachSep); + fclose (fpout); + } + } + } + else + mutt_query_save_attachment (fp, top, hdr); + } else if (top->parts) - mutt_save_attachment_list (fp, 1, top->parts); + mutt_save_attachment_list (fp, 1, top->parts, hdr); if (!tag) return; } + + if (!option (OPTATTACHSPLIT) && (rc == 0)) + mutt_message ("Attachment saved"); } static void @@ -234,13 +403,44 @@ mutt_query_pipe_attachment (char *command, FILE *fp, BODY *body, int filter) } } +static STATE state; +static void pipe_attachment (FILE *fp, BODY *b) +{ + FILE *ifp; + + if (fp) + { + state.fpin = fp; + mutt_decode_attachment (b, &state); + if (AttachSep) + state_puts (AttachSep, &state); + } + else + { + if ((ifp = fopen (b->filename, "r")) == NULL) + { + mutt_perror ("fopen"); + return; + } + mutt_copy_stream (ifp, state.fpout); + fclose (ifp); + if (AttachSep) + state_puts (AttachSep, &state); + } +} + static void pipe_attachment_list (char *command, FILE *fp, int tag, BODY *top, int filter) { for (; top; top = top->next) { if (!tag || top->tagged) - mutt_query_pipe_attachment (command, fp, top, filter); + { + if (!filter && !option (OPTATTACHSPLIT)) + pipe_attachment (fp, top); + else + mutt_query_pipe_attachment (command, fp, top, filter); + } else if (top->parts) pipe_attachment_list (command, fp, tag, top->parts, filter); if (!tag) @@ -251,26 +451,104 @@ pipe_attachment_list (char *command, FILE *fp, int tag, BODY *top, int filter) void mutt_pipe_attachment_list (FILE *fp, int tag, BODY *top, int filter) { char buf[SHORT_STRING]; + pid_t thepid; if (fp) filter = 0; /* sanity check: we can't filter in the recv case yet */ buf[0] = 0; + memset (&state, 0, sizeof (STATE)); + if (mutt_get_field ((filter ? "Filter through: " : "Pipe to: "), buf, sizeof (buf), 0) != 0 || !buf[0]) return; + mutt_expand_path (buf, sizeof (buf)); - pipe_attachment_list (buf, fp, tag, top, filter); + + if (!filter && !option (OPTATTACHSPLIT)) + { + endwin (); + thepid = mutt_create_filter (buf, &state.fpout, NULL, NULL); + pipe_attachment_list (buf, fp, tag, top, filter); + fclose (state.fpout); + if (mutt_wait_filter (thepid) != 0 || option (OPTWAITKEY)) + mutt_any_key_to_continue (NULL); + } + else + pipe_attachment_list (buf, fp, tag, top, filter); +} + +static int can_print (BODY *top, int tag) +{ + char type [STRING]; + + for (; top; top = top->next) + { + snprintf (type, sizeof (type), "%s/%s", TYPE (top), top->subtype); + if (!tag || top->tagged) + { + if (!rfc1524_mailcap_lookup (top, type, NULL, M_PRINT)) + { + if (strcasecmp ("text/plain", top->subtype) && + strcasecmp ("application/postscript", top->subtype)) + { + if (!mutt_can_decode (top)) + { + mutt_error ("I dont know how to print %s attachments!", type); + return (0); + } + } + } + } + else if (top->parts) + return (can_print (top->parts, tag)); + if (!tag) + break; + } + return (1); } static void print_attachment_list (FILE *fp, int tag, BODY *top) { + char type [STRING]; + + for (; top; top = top->next) { if (!tag || top->tagged) - mutt_print_attachment (fp, top); + { + snprintf (type, sizeof (type), "%s/%s", TYPE (top), top->subtype); + if (!option (OPTATTACHSPLIT) && !rfc1524_mailcap_lookup (top, type, NULL, M_PRINT)) + { + if (!strcasecmp ("text/plain", top->subtype) || + !strcasecmp ("application/postscript", top->subtype)) + pipe_attachment (fp, top); + else if (mutt_can_decode (top)) + { + /* decode and print */ + + char newfile[_POSIX_PATH_MAX] = ""; + FILE *ifp; + + mutt_mktemp (newfile); + if (mutt_decode_save_attachment (fp, top, newfile, 0, 0) == 0) + { + if ((ifp = fopen (newfile, "r")) != NULL) + { + mutt_copy_stream (ifp, state.fpout); + fclose (ifp); + if (AttachSep) + state_puts (AttachSep, &state); + } + } + mutt_unlink (newfile); + } + } + else + mutt_print_attachment (fp, top); + } else if (top->parts) - mutt_print_attachment_list (fp, tag, top->parts); + print_attachment_list (fp, tag, top->parts); if (!tag) return; } @@ -278,18 +556,24 @@ static void print_attachment_list (FILE *fp, int tag, BODY *top) void mutt_print_attachment_list (FILE *fp, int tag, BODY *top) { + pid_t thepid; if (query_quadoption (OPT_PRINT, tag ? "Print tagged attachment(s)?" : "Print attachment?") != M_YES) return; - print_attachment_list (fp, tag, top); -} -int mutt_is_message_type (int type, char *subtype) -{ - if (type != TYPEMESSAGE) - return 0; - if (strcasecmp (subtype, "rfc822") == 0 || strcasecmp (subtype, "news") == 0) - return 1; - return 0; + if (!option (OPTATTACHSPLIT)) + { + if (!can_print (top, tag)) + return; + endwin (); + memset (&state, 0, sizeof (STATE)); + thepid = mutt_create_filter (NONULL (PrintCmd), &state.fpout, NULL, NULL); + print_attachment_list (fp, tag, top); + fclose (state.fpout); + if (mutt_wait_filter (thepid) != 0 || option (OPTWAITKEY)) + mutt_any_key_to_continue (NULL); + } + else + print_attachment_list (fp, tag, top); } static void @@ -404,9 +688,10 @@ create_tagged_message (const char *tempfile, } /* op flag to ci_send_message() - tag operate on tagged attachments? - hdr current message - body current attachment */ + * tag operate on tagged attachments? + * hdr current message + * body current attachment + */ static void reply_attachment_list (int op, int tag, HEADER *hdr, BODY *body) { HEADER *hn; @@ -617,14 +902,11 @@ void mutt_view_attachments (HEADER *hdr) break; case OP_SAVE: - mutt_save_attachment_list (fp, menu->tagprefix, menu->tagprefix ? cur : idx[menu->current]->content); + mutt_save_attachment_list (fp, menu->tagprefix, menu->tagprefix ? cur : idx[menu->current]->content, hdr); if (option (OPTRESOLVE) && menu->current < menu->max - 1) - { menu->current++; - menu->redraw = REDRAW_MOTION_RESYNCH; - } - else - menu->redraw = REDRAW_CURRENT; + + menu->redraw = REDRAW_MOTION_RESYNCH | REDRAW_FULL; break; case OP_DELETE: diff --git a/reldate.h b/reldate.h index 7cece852..7381eb7d 100644 --- a/reldate.h +++ b/reldate.h @@ -1 +1 @@ -const char *ReleaseDate = "1998-06-16"; +const char *ReleaseDate = "1998-08-24"; diff --git a/rfc1524.c b/rfc1524.c index ac16ae8b..d35a0ad1 100644 --- a/rfc1524.c +++ b/rfc1524.c @@ -55,14 +55,17 @@ int rfc1524_expand_command (BODY *a, char *filename, char *type, int needspipe = TRUE; char buf[LONG_STRING]; - while (command[x] && x<clen && y<sizeof(buf)) { + while (command[x] && x<clen && y<sizeof(buf)) + { if (command[x] == '\\') { x++; buf[y++] = command[x++]; } - else if (command[x] == '%') { + else if (command[x] == '%') + { x++; - if (command[x] == '{') { + if (command[x] == '{') + { char param[STRING]; int z = 0; char *ret = NULL; @@ -138,7 +141,8 @@ static int get_field_text (char *field, char **entry, { if (entry) { - field = mutt_skip_whitespace (++field); + field++; + field = mutt_skip_whitespace (field); safe_free ((void **) entry); *entry = safe_strdup (field); } @@ -289,7 +293,7 @@ static int rfc1524_mailcap_parse (BODY *a, /* a non-zero exit code means test failed */ found = FALSE; } - free (test_command); + FREE (&test_command); } } } /* while (ch) */ @@ -338,14 +342,9 @@ static int rfc1524_mailcap_parse (BODY *a, return found; } -rfc1524_entry *rfc1524_new_entry() +rfc1524_entry *rfc1524_new_entry(void) { - rfc1524_entry *tmp; - - tmp = (rfc1524_entry *)safe_malloc(sizeof(rfc1524_entry)); - memset(tmp,0,sizeof(rfc1524_entry)); - - return tmp; + return (rfc1524_entry *)safe_calloc(1, sizeof(rfc1524_entry)); } void rfc1524_free_entry(rfc1524_entry **entry) @@ -420,156 +419,171 @@ int rfc1524_mailcap_lookup (BODY *a, char *type, rfc1524_entry *entry, int opt) * Renamed to mutt_adv_mktemp so I only have to change where it's * called, and not all possible cases. */ -void mutt_adv_mktemp (char *s) +void mutt_adv_mktemp (char *s, size_t l) { char buf[_POSIX_PATH_MAX]; char tmp[_POSIX_PATH_MAX]; char *period; - + size_t sl; + strfcpy (buf, NONULL (Tempdir), sizeof (buf)); mutt_expand_path (buf, sizeof (buf)); if (s[0] == '\0') { - sprintf (s, "%s/muttXXXXXX", buf); + snprintf (s, l, "%s/muttXXXXXX", buf); mktemp (s); } else { strfcpy (tmp, s, sizeof (tmp)); - sprintf (s, "%s/%s", buf, tmp); + snprintf (s, l, "%s/%s", buf, tmp); if (access (s, F_OK) != 0) return; if ((period = strrchr (tmp, '.')) != NULL) *period = 0; - sprintf (s, "%s/%s.XXXXXX", buf, tmp); + snprintf (s, l, "%s/%s.XXXXXX", buf, tmp); mktemp (s); if (period != NULL) { *period = '.'; - strcat (s, period); + sl = strlen(s); + strfcpy(s + sl, period, l - sl); } } } -/* This routine expands the filename given to match the format of the - * nametemplate given. It returns various values based on what operations - * it performs. - * +/* This routine will create a _temporary_ filename matching the + * name template given if this needs to be done. + * + * Please note that only the last path element of the + * template and/or the old file name will be used for the + * comparison and the temporary file name. + * * Returns 0 if oldfile is fine as is. * Returns 1 if newfile specified */ +static void strnfcpy(char *d, char *s, size_t siz, size_t len) +{ + if(len > siz) + len = siz - 1; + strfcpy(d, s, len); +} + int rfc1524_expand_filename (char *nametemplate, char *oldfile, char *newfile, size_t nflen) { - int z = 0; - int i = 0, j = 0; - int lmatch = TRUE; - int match = TRUE; - size_t len = 0; + int i, j, k, ps, r; char *s; - + short lmatch = 0, rmatch = 0; + char left[_POSIX_PATH_MAX]; + char right[_POSIX_PATH_MAX]; + newfile[0] = 0; + /* first, ignore leading path components. + */ + if (nametemplate && (s = strrchr (nametemplate, '/'))) nametemplate = s + 1; if (oldfile && (s = strrchr (oldfile, '/'))) - { - len = s - oldfile + 1; - if (len > nflen) - len = nflen; - strfcpy (newfile, oldfile, len + 1); - oldfile += len; - } - - /* If nametemplate is NULL, create a newfile from oldfile and return 0 */ + oldfile = s + 1; + if (!nametemplate) { if (oldfile) strfcpy (newfile, oldfile, nflen); - mutt_adv_mktemp (newfile); - return 0; } - - /* If oldfile is NULL, just return a newfile name */ - if (!oldfile) + else if (!oldfile) { snprintf (newfile, nflen, nametemplate, "mutt"); - mutt_adv_mktemp (newfile); - return 0; } - - /* Next, attempt to determine if the oldfile already matches nametemplate */ - /* Nametemplate is of the form pre%spost, only replace pre or post if - * they don't already match the oldfilename */ - /* Test pre */ - - if ((s = strrchr (nametemplate, '%')) != NULL) + else /* oldfile && nametemplate */ { - newfile[len] = '\0'; - z = s - nametemplate; - - for (i = 0; i < z && i < nflen; i++) + /* first, compare everything left from the "%s" + * (if there is one). + */ + + lmatch = 1; ps = 0; + for(i = 0; nametemplate[i]; i++) { - if (oldfile[i] != nametemplate[i]) - { - lmatch=FALSE; + if(nametemplate[i] == '%' && nametemplate[i+1] == 's') + { + ps = 1; break; } - } - if (!lmatch) - { - match = FALSE; - i = nflen - len; - if (i > z) - i = z; - strfcpy (newfile + len, nametemplate, i); - } - - strfcpy (newfile + strlen (newfile), - oldfile, nflen - strlen (newfile)); + /* note that the following will _not_ read beyond oldfile's end. */ - dprint (1, (debugfile,"template: %s, oldfile: %s, newfile: %s\n", - nametemplate, oldfile, newfile)); + if(lmatch && nametemplate[i] != oldfile[i]) + lmatch = 0; + } - /* test post */ - lmatch = TRUE; + if(ps) + { + + /* If we had a "%s", check the rest. */ + + /* now, for the right part: compare everything right from + * the "%s" to the final part of oldfile. + * + * The logic here is as follows: + * + * - We start reading from the end. + * - There must be a match _right_ from the "%s", + * thus the i + 2. + * - If there was a left hand match, this stuff + * must not be counted again. That's done by the + * condition (j >= (lmatch ? i : 0)). + */ + + rmatch = 1; - for (z += 2, i = strlen (oldfile) - 1, j = strlen (nametemplate) - 1; - i && j > z; i--, j--) - if (oldfile[i] != nametemplate[j]) + for(r = 0, j = strlen(oldfile) - 1, k = strlen(nametemplate) - 1 ; + j >= (lmatch ? i : 0) && k >= i + 2; + j--, k--) { - lmatch = FALSE; - break; + if(nametemplate[k] != oldfile[j]) + { + rmatch = 0; + break; + } } - - if (!lmatch) + + /* Now, check if we had a full match. */ + + if(k >= i + 2) + rmatch = 0; + + if(lmatch) *left = 0; + else strnfcpy(left, nametemplate, sizeof(left), i); + + if(rmatch) *right = 0; + else strfcpy(right, nametemplate + i + 2, sizeof(right)); + + snprintf(newfile, nflen, "%s%s%s", left, oldfile, right); + } + else { - match = FALSE; - strfcpy (newfile + strlen (newfile), - nametemplate + z, nflen - strlen (newfile)); + /* no "%s" in the name template. */ + strfcpy(newfile, nametemplate, nflen); } - - if (match) - return 0; - - return 1; } - else - { - /* no %s in nametemplate, graft unto path of oldfile */ - strfcpy (newfile, nametemplate, nflen); + + mutt_adv_mktemp(newfile, nflen); + + if(rmatch && lmatch) + return 0; + else return 1; - } + } -/* For nametemplate support, we may need to rename a file. - * If rfc1524_expand_command() is used on a recv'd message, then +/* If rfc1524_expand_command() is used on a recv'd message, then * the filename doesn't exist yet, but if its used while sending a message, * then we need to rename the existing file. * diff --git a/rfc1524.h b/rfc1524.h index a34e7fee..1051f111 100644 --- a/rfc1524.h +++ b/rfc1524.h @@ -34,12 +34,12 @@ typedef struct rfc1524_mailcap_entry { unsigned int copiousoutput : 1; /* needs pager, basically */ } rfc1524_entry; -rfc1524_entry *rfc1524_new_entry (); +rfc1524_entry *rfc1524_new_entry (void); void rfc1524_free_entry (rfc1524_entry **); int rfc1524_expand_command (BODY *, char *, char *, char *, int); int rfc1524_expand_filename (char *, char *, char *, size_t); int rfc1524_mailcap_lookup (BODY *, char *, rfc1524_entry *, int); -void mutt_adv_mktemp (char *); +void mutt_adv_mktemp (char *, size_t); int mutt_rename_file (char *, char *); #endif /* _RFC1524_H */ diff --git a/rfc2047.c b/rfc2047.c index 733a8d25..25ba7914 100644 --- a/rfc2047.c +++ b/rfc2047.c @@ -35,7 +35,7 @@ static void q_encode_string (char *d, size_t dlen, const unsigned char *s) char *wptr = d; snprintf (charset, sizeof (charset), "=?%s?Q?", - strcasecmp ("us-ascii", charset) == 0 ? "unknown-8bit" : Charset); + strcasecmp ("us-ascii", NONULL(Charset)) == 0 ? "unknown-8bit" : NONULL(Charset)); cslen = strlen (charset); strcpy (wptr, charset); @@ -110,7 +110,7 @@ static void b_encode_string (char *d, size_t dlen, const unsigned char *s) int cslen; int wordlen; - snprintf (charset, sizeof (charset), "=?%s?B?", Charset); + snprintf (charset, sizeof (charset), "=?%s?B?", NONULL(Charset)); cslen = strlen (charset); strcpy (wptr, charset); wptr += cslen; @@ -176,7 +176,7 @@ void rfc2047_encode_string (char *d, size_t dlen, const unsigned char *s) { if (*p & 0x80) count++; - else if (*p == '=' && *p == '?') + else if (*p == '=' && *(p+1) == '?') { count += 2; p++; @@ -188,8 +188,8 @@ void rfc2047_encode_string (char *d, size_t dlen, const unsigned char *s) return; } - if (strcasecmp("us-ascii", Charset) == 0 || - strncasecmp("iso-8859", Charset, 8) == 0) + if (strcasecmp("us-ascii", NONULL(Charset)) == 0 || + strncasecmp("iso-8859", NONULL(Charset), 8) == 0) encoder = q_encode_string; else { @@ -251,7 +251,7 @@ static int rfc2047_decode_word (char *d, const char *s, size_t len) switch (count) { case 2: - if (strcasecmp (pp, Charset) != 0) + if (strcasecmp (pp, NONULL(Charset)) != 0) filter = 1; break; case 3: @@ -291,14 +291,14 @@ static int rfc2047_decode_word (char *d, const char *s, size_t len) { while (*pp && len > 0) { - c1 = Index_64[(int) pp[0]]; - c2 = Index_64[(int) pp[1]]; + c1 = base64val(pp[0]); + c2 = base64val(pp[1]); *pd++ = (c1 << 2) | ((c2 >> 4) & 0x3); if (--len == 0) break; if (pp[2] == '=') break; - c3 = Index_64[(int) pp[2]]; + c3 = base64val(pp[2]); *pd++ = ((c2 & 0xf) << 4) | ((c3 >> 2) & 0xf); if (--len == 0) break; @@ -306,7 +306,7 @@ static int rfc2047_decode_word (char *d, const char *s, size_t len) if (pp[3] == '=') break; - c4 = Index_64[(int) pp[3]]; + c4 = base64val(pp[3]); *pd++ = ((c3 & 0x3) << 6) | c4; if (--len == 0) break; @@ -325,7 +325,7 @@ static int rfc2047_decode_word (char *d, const char *s, size_t len) pd = d; while (*pd) { - if (!IsPrint ((unsigned char) *pd)) + if (!IsPrint (*pd)) *pd = '?'; pd++; } diff --git a/rfc822.c b/rfc822.c index 487bea10..2c990486 100644 --- a/rfc822.c +++ b/rfc822.c @@ -198,30 +198,28 @@ parse_mailboxdomain (const char *s, const char *nonspecial, static const char * parse_address (const char *s, + char *token, size_t *tokenlen, size_t tokenmax, char *comment, size_t *commentlen, size_t commentmax, ADDRESS *addr) { - char token[128]; - size_t tokenlen = 0; - s = parse_mailboxdomain (s, ".\"(\\", - token, &tokenlen, sizeof (token) - 1, + token, tokenlen, tokenmax, comment, commentlen, commentmax); if (!s) return NULL; if (*s == '@') { - if (tokenlen < sizeof (token) - 1) - token[tokenlen++] = '@'; + if (*tokenlen < tokenmax) + token[(*tokenlen)++] = '@'; s = parse_mailboxdomain (s + 1, ".([]\\", - token, &tokenlen, sizeof (token) - 1, + token, tokenlen, tokenmax, comment, commentlen, commentmax); if (!s) return NULL; } - token[tokenlen] = 0; + token[*tokenlen] = 0; addr->mailbox = safe_strdup (token); if (*commentlen && !addr->personal) @@ -238,27 +236,34 @@ parse_route_addr (const char *s, char *comment, size_t *commentlen, size_t commentmax, ADDRESS *addr) { + char token[STRING]; + size_t tokenlen = 0; + SKIPWS (s); /* find the end of the route */ if (*s == '@') { - char token[128]; - size_t tokenlen = 0; - while (s && *s == '@') - s = parse_mailboxdomain (s + 1, ".[](\\", token, + { + if (tokenlen < sizeof (token) - 1) + token[tokenlen++] = '@'; + s = parse_mailboxdomain (s + 1, ".\\[](", token, &tokenlen, sizeof (token) - 1, comment, commentlen, commentmax); + } if (!s || *s != ':') { RFC822Error = ERR_BAD_ROUTE; return NULL; /* invalid route */ } + + if (tokenlen < sizeof (token) - 1) + token[tokenlen++] = ':'; s++; } - if ((s = parse_address (s, comment, commentlen, commentmax, addr)) == NULL) + if ((s = parse_address (s, token, &tokenlen, sizeof (token) - 1, comment, commentlen, commentmax, addr)) == NULL) return NULL; if (*s != '>' || !addr->mailbox) @@ -276,7 +281,10 @@ parse_addr_spec (const char *s, char *comment, size_t *commentlen, size_t commentmax, ADDRESS *addr) { - s = parse_address (s, comment, commentlen, commentmax, addr); + char token[STRING]; + size_t tokenlen = 0; + + s = parse_address (s, token, &tokenlen, sizeof (token) - 1, comment, commentlen, commentmax, addr); if (s && *s && *s != ',' && *s != ';') { RFC822Error = ERR_BAD_ADDR_SPEC; @@ -304,7 +312,7 @@ add_addrspec (ADDRESS **top, ADDRESS **last, const char *phrase, ADDRESS *rfc822_parse_adrlist (ADDRESS *top, const char *s) { const char *begin, *ps; - char comment[128], phrase[128]; + char comment[STRING], phrase[STRING]; size_t phraselen = 0, commentlen = 0; ADDRESS *cur, *last = NULL; @@ -413,7 +421,7 @@ ADDRESS *rfc822_parse_adrlist (ADDRESS *top, const char *s) if (phraselen) { if (cur->personal) - free (cur->personal); + FREE (&cur->personal); /* if we get something like "Michael R. Elkins" remove the quotes */ rfc822_dequote_comment (phrase); cur->personal = safe_strdup (phrase); @@ -475,10 +483,9 @@ void rfc822_qualify (ADDRESS *addr, const char *host) for (; addr; addr = addr->next) if (!addr->group && addr->mailbox && strchr (addr->mailbox, '@') == NULL) { - if (!(p = malloc (strlen (addr->mailbox) + strlen (host) + 2))) - return; + p = safe_malloc (strlen (addr->mailbox) + strlen (host) + 2); sprintf (p, "%s@%s", addr->mailbox, host); - free (addr->mailbox); + safe_free ((void **) &addr->mailbox); addr->mailbox = p; } } @@ -492,7 +499,7 @@ rfc822_cat (char *buf, size_t buflen, const char *value, const char *specials) size_t tmplen = sizeof (tmp) - 3; *pc++ = '"'; - for (; *value && tmplen; value++) + for (; *value && tmplen > 1; value++) { if (*value == '\\' || *value == '"') { @@ -583,7 +590,10 @@ void rfc822_write_address_single (char *buf, size_t buflen, ADDRESS *addr) goto done; *pbuf++ = ' '; buflen--; + } + if (addr->personal || (addr->mailbox && *addr->mailbox == '@')) + { if (!buflen) goto done; *pbuf++ = '<'; @@ -599,7 +609,7 @@ void rfc822_write_address_single (char *buf, size_t buflen, ADDRESS *addr) pbuf += len; buflen -= len; - if (addr->personal) + if (addr->personal || (addr->mailbox && *addr->mailbox == '@')) { if (!buflen) goto done; @@ -668,7 +678,10 @@ void rfc822_write_address (char *buf, size_t buflen, ADDRESS *addr) len = strlen (pbuf); pbuf += len; buflen -= len; - if (addr->next && !addr->group) + + /* if there is another address, and its not a group mailbox name or + group terminator, add a comma to separate the addresses */ + if (addr->next && addr->next->mailbox && !addr->group) { if (!buflen) goto done; @@ -745,12 +758,7 @@ int main (int argc, char **argv) { ADDRESS *list; char buf[256]; - char *str = "aaaaaaaaaaaaaa <bbbbbbbbbbbbbbbb>, ccccccc <dddddddddddddddd>,\n\ - eeeeeeeeee <ffffffffffffffff>, ggggggggggg <hhhhhhhhhhhhhhhhhhh>,\n\ - iiiiiiiiiiiiiiii <jjjjjjjjjjjjjjjjjjjj>,\n\ - kkkkkkkkkkkkkk <lllllllllllllllll>,\n\ - mmmmmmmmmmmmm <nnnnnnnnnnnnnnnnnn>, ooooooooooo <pppppppppppppp>,\n\ - qqqqqqqqqqqqq <rrrrrrrrrrrrrrrr>\n"; + char *str = "michael, Michael Elkins <me@cs.hmc.edu>, testing a really complex address: this example <@contains.a.source.route@with.multiple.hosts:address@example.com>;, lothar@of.the.hillpeople (lothar)"; list = rfc822_parse_adrlist (NULL, str); buf[0] = 0; diff --git a/sample.muttrc b/sample.muttrc index f0bff294..8bce3bbe 100644 --- a/sample.muttrc +++ b/sample.muttrc @@ -288,6 +288,7 @@ mailboxes ! +mutt-dev +mutt-users +open-pgp +wmaker +hurricane +vim +ietf \ # hdr_order <hdr1> [ <hdr2> ... ] # +unhdr_order * # forget the previous settings hdr_order date from subject to cc # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/send.c b/send.c index 44e80eed..91dbf2c4 100644 --- a/send.c +++ b/send.c @@ -44,7 +44,7 @@ extern char RFC822Specials[]; -static void append_signature (ENVELOPE *env, FILE *f) +static void append_signature (FILE *f) { FILE *tmpfp; pid_t thepid; @@ -323,13 +323,10 @@ static int include_forward (CONTEXT *ctx, HEADER *cur, FILE *out) #ifdef _PGPPATH - if (cur->pgp) + if ((cur->pgp & PGPENCRYPT) && option (OPTFORWDECODE)) { - if (cur->pgp & PGPENCRYPT) - { - /* make sure we have the user's passphrase before proceeding... */ - pgp_valid_passphrase (); - } + /* make sure we have the user's passphrase before proceeding... */ + pgp_valid_passphrase (); } #endif /* _PGPPATH */ @@ -392,38 +389,6 @@ static int include_reply (CONTEXT *ctx, HEADER *cur, FILE *out) return 0; } -static BODY *make_forward (CONTEXT *ctx, HEADER *hdr) -{ - char buffer[LONG_STRING]; - BODY *body; - FILE *fpout; - - mutt_mktemp (buffer); - if ((fpout = safe_fopen (buffer, "w")) == NULL) - return NULL; - - body = mutt_new_body (); - body->type = TYPEMESSAGE; - body->subtype = safe_strdup ("rfc822"); - body->filename = safe_strdup (buffer); - body->unlink = 1; - body->use_disp = 0; - - /* this MUST come after setting ->filename because we reuse buffer[] */ - strfcpy (buffer, "Forwarded message from ", sizeof (buffer)); - rfc822_write_address (buffer + 23, sizeof (buffer) - 23, hdr->env->from); - body->description = safe_strdup (buffer); - - mutt_parse_mime_message (ctx, hdr); - mutt_copy_message (fpout, ctx, hdr, - option (OPTMIMEFORWDECODE) ? M_CM_DECODE : 0, - CH_XMIT | (option (OPTMIMEFORWDECODE) ? (CH_MIME | CH_TXTPLAIN ) : 0)); - - fclose (fpout); - mutt_update_encoding (body); - return (body); -} - static int default_to (ADDRESS **to, ENVELOPE *env, int group) { char prompt[STRING]; @@ -482,6 +447,23 @@ static int default_to (ADDRESS **to, ENVELOPE *env, int group) return (0); } +static LIST *make_references(ENVELOPE *e) +{ + LIST *t, *l; + + l = mutt_copy_list(e->references); + + if(e->message_id) + { + t = mutt_new_list(); + t->data = safe_strdup(e->message_id); + t->next = l; + l = t; + } + + return l; +} + static int fetch_recips (ENVELOPE *out, ENVELOPE *in, int flags) { ADDRESS *tmp; @@ -598,22 +580,30 @@ envelope_defaults (ENVELOPE *env, CONTEXT *ctx, HEADER *cur, int flags) tmp->data = safe_strdup (buffer); } - env->references = mutt_copy_list (curenv->references); - - if (curenv->message_id) + if(tag) { - LIST *t; + HEADER *h; + LIST **p; - t = mutt_new_list (); - t->data = safe_strdup (curenv->message_id); - t->next = env->references; - env->references = t; + env->references = NULL; + p = &env->references; + + for(i = 0; i < ctx->vcount; i++) + { + while(*p) p = &(*p)->next; + h = ctx->hdrs[ctx->v2r[i]]; + if(h->tagged) + *p = make_references(h->env); + } } + else + env->references = make_references(curenv); + } else if (flags & SENDFORWARD) { /* set the default subject for the message. */ - mutt_make_string (buffer, sizeof (buffer), ForwFmt, ctx, cur); + mutt_make_string (buffer, sizeof (buffer), NONULL(ForwFmt), ctx, cur); env->subject = safe_strdup (buffer); } @@ -669,7 +659,7 @@ generate_body (FILE *tempfp, /* stream for outgoing message */ if (cur) { - tmp = make_forward (ctx, cur); + tmp = mutt_make_message_attach (ctx, cur, 0); if (last) last->next = tmp; else @@ -681,7 +671,7 @@ generate_body (FILE *tempfp, /* stream for outgoing message */ { if (ctx->hdrs[ctx->v2r[i]]->tagged) { - tmp = make_forward (ctx, ctx->hdrs[ctx->v2r[i]]); + tmp = mutt_make_message_attach (ctx, ctx->hdrs[ctx->v2r[i]], 0); if (last) { last->next = tmp; @@ -794,16 +784,17 @@ static ADDRESS *set_reverse_name (ENVELOPE *env) static ADDRESS *mutt_default_from (void) { ADDRESS *adr = rfc822_new_address (); - + const char *fqdn = mutt_fqdn(1); + /* don't set realname here, it will be set later */ if (option (OPTUSEDOMAIN)) { - adr->mailbox = safe_malloc (strlen (Username) + strlen (Fqdn) + 2); - sprintf (adr->mailbox, "%s@%s", Username, Fqdn); + adr->mailbox = safe_malloc (strlen (NONULL(Username)) + strlen (NONULL(fqdn)) + 2); + sprintf (adr->mailbox, "%s@%s", NONULL(Username), NONULL(fqdn)); } else - adr->mailbox = safe_strdup (Username); + adr->mailbox = safe_strdup (NONULL(Username)); return (adr); } @@ -903,8 +894,8 @@ ci_send_message (int flags, /* send mode */ if (!tempfp) { - dprint(1,(debugfile, "newsend_message: can't create tempfile %s (errno=%d)\n", tempfile, errno)); - mutt_perror (tempfile); + dprint(1,(debugfile, "newsend_message: can't create tempfile %s (errno=%d)\n", msg->content->filename, errno)); + mutt_perror (msg->content->filename); goto cleanup; } } @@ -992,8 +983,8 @@ ci_send_message (int flags, /* send mode */ if (generate_body (tempfp, msg, flags, ctx, cur) == -1) goto cleanup; - if (! (flags & (SENDMAILX | SENDKEY)) && strcmp (Editor, "builtin") != 0) - append_signature (msg->env, tempfp); + if (! (flags & (SENDMAILX | SENDKEY)) && Editor && strcmp (Editor, "builtin") != 0) + append_signature (tempfp); } /* wait until now to set the real name portion of our return address so that $realname can be set in a send-hook */ @@ -1043,8 +1034,8 @@ ci_send_message (int flags, /* send mode */ if(! (flags & SENDKEY)) { if (mutt_needs_mailcap (msg->content)) - mutt_edit_attachment (msg->content, 0); - else if (strcmp ("builtin", Editor) == 0) + mutt_edit_attachment (msg->content); + else if (!Editor || strcmp ("builtin", Editor) == 0) mutt_builtin_editor (msg->content->filename, msg, cur); else if (option (OPTEDITHDRS)) mutt_edit_headers (Editor, msg->content->filename, msg, fcc, sizeof (fcc)); @@ -1105,7 +1096,7 @@ main_loop: /* postpone the message until later. */ if (msg->content->next) msg->content = mutt_make_multipart (msg->content); - if (mutt_write_fcc (NONULL (Postponed), msg, (cur && (flags & SENDREPLY)) ? cur->env->message_id : NULL, 1) < 0) + if (!Postponed || mutt_write_fcc (Postponed, msg, (cur && (flags & SENDREPLY)) ? cur->env->message_id : NULL, 1) < 0) { msg->content = remove_multipart (msg->content); goto main_loop; @@ -1175,7 +1166,7 @@ main_loop: * it by using an empty To: field. */ msg->env->to = rfc822_new_address (); - msg->env->to->mailbox = safe_strdup (EmptyTo); + msg->env->to->mailbox = safe_strdup ("undisclosed-recipients:;"); msg->env->to->group = 1; msg->env->to->next = rfc822_new_address (); diff --git a/sendlib.c b/sendlib.c index b6eaac64..52ec8fb2 100644 --- a/sendlib.c +++ b/sendlib.c @@ -33,10 +33,64 @@ #include <signal.h> #include <sys/wait.h> #include <fcntl.h> -#include <sysexits.h> - +#ifdef HAVE_SYSEXITS_H +#include <sysexits.h> +#endif +static struct sysexits +{ + int v; + const char *str; +} +sysexits_h[] = +{ +#ifdef EX_USAGE + { EX_USAGE, "The command was used incorrectly." }, +#endif +#ifdef EX_DATAERR + { EX_DATAERR, "The input data was incorrect." }, +#endif +#ifdef EX_NOINPUT + { EX_NOINPUT, "No input." }, +#endif +#ifdef EX_NOUSER + { EX_NOUSER, "No such user." }, +#endif +#ifdef EX_NOHOST + { EX_NOHOST, "Host not found." }, +#endif +#ifdef EX_UNAVAILABLE + { EX_UNAVAILABLE, "Service unavailable." }, +#endif +#ifdef EX_SOFTWARE + { EX_SOFTWARE, "Software error." }, +#endif +#ifdef EX_OSERR + { EX_OSERR, "Operating system error." }, +#endif +#ifdef EX_OSFILE + { EX_OSFILE, "System file is missing." }, +#endif +#ifdef EX_CANTCREAT + { EX_CANTCREAT, "Can't create output." }, +#endif +#ifdef EX_IOERR + { EX_IOERR, "I/O error." }, +#endif +#ifdef EX_TEMPFAIL + { EX_TEMPFAIL, "Temporary failure." }, +#endif +#ifdef EX_PROTOCOL + { EX_PROTOCOL, "Protocol error." }, +#endif +#ifdef EX_NOPERM + { EX_NOPERM, "Permission denied." }, +#endif + { -1, NULL} +}; + + #ifdef _PGPPATH #include "pgp.h" #endif /* _PGPPATH */ @@ -111,11 +165,11 @@ static void encode_quoted (FILE * fin, FILE *fout, int istext) if (c == '\n' && istext) { /* Check to make sure there is no trailing space on this line. */ - if (line[linelen-1] == ' ' || line[linelen-1] == '\t') + if (linelen > 0 && (line[linelen-1] == ' ' || line[linelen-1] == '\t')) { if (linelen < 74) { - sprintf (line+linelen-1, "=%2.2X", line[linelen-1]); + sprintf (line+linelen-1, "=%2.2X", (unsigned char) line[linelen-1]); fputs (line, fout); } else @@ -125,7 +179,7 @@ static void encode_quoted (FILE * fin, FILE *fout, int istext) line[linelen-1] = '='; line[linelen] = 0; fputs (line, fout); - fprintf (fout, "\n=%2.2X", savechar); + fprintf (fout, "\n=%2.2X", (unsigned char) savechar); } } else @@ -149,7 +203,7 @@ static void encode_quoted (FILE * fin, FILE *fout, int istext) fputc ('\n', fout); linelen = 0; } - sprintf (line+linelen,"=%2.2X", c); + sprintf (line+linelen,"=%2.2X", (unsigned char) c); linelen += 3; } else @@ -168,7 +222,7 @@ static void encode_quoted (FILE * fin, FILE *fout, int istext) { /* take care of trailing whitespace */ if (linelen < 74) - sprintf (line+linelen-1, "=%2.2X", line[linelen-1]); + sprintf (line+linelen-1, "=%2.2X", (unsigned char) line[linelen-1]); else { savechar = line[linelen-1]; @@ -176,7 +230,7 @@ static void encode_quoted (FILE * fin, FILE *fout, int istext) line[linelen] = 0; fputs (line, fout); fputc ('\n', fout); - sprintf (line, "=%2.2X", savechar); + sprintf (line, "=%2.2X", (unsigned char) savechar); } } else @@ -311,7 +365,7 @@ int mutt_write_mime_header (BODY *a, FILE *f) int len; int tmplen; - fprintf (f, "Content-Type: %s/%s", TYPE (a->type), a->subtype); + fprintf (f, "Content-Type: %s/%s", TYPE (a), a->subtype); if (a->parameter) { @@ -391,6 +445,7 @@ int mutt_write_mime_body (BODY *a, FILE *f) if (!(p = mutt_get_parameter ("boundary", a->parameter))) { dprint (1, (debugfile, "mutt_write_mime_body(): no boundary parameter found!\n")); + mutt_error ("No boundary parameter found! [report this error]"); return (-1); } strfcpy (boundary, p, sizeof (boundary)); @@ -424,6 +479,7 @@ int mutt_write_mime_body (BODY *a, FILE *f) if ((fpin = fopen (a->filename, "r")) == NULL) { dprint(1,(debugfile, "write_mime_body: %s no longer exists!\n",a->filename)); + mutt_error ("%s no longer exists!", a->filename); return -1; } @@ -573,7 +629,7 @@ static int lookup_mime_type (char *d, const char *s) switch (count) { case 0: - snprintf (buf, sizeof (buf), "%s/.mime.types", Homedir); + snprintf (buf, sizeof (buf), "%s/.mime.types", NONULL(Homedir)); break; case 1: strfcpy (buf, SHAREDIR"/mime.types", sizeof (buf)); @@ -653,7 +709,6 @@ static char *set_text_charset (CONTENT *info) void mutt_message_to_7bit (BODY *a, FILE *fp) { char temp[_POSIX_PATH_MAX]; - size_t linelen = 0; char *line = NULL; FILE *fpin = NULL; FILE *fpout = NULL; @@ -699,7 +754,6 @@ void mutt_message_to_7bit (BODY *a, FILE *fp) cleanup: safe_free ((void **) &line); - linelen = 0; if (fpin && !fp) fclose (fpin); @@ -809,6 +863,11 @@ static void mutt_set_encoding (BODY *b, CONTENT *info) b->encoding = ENC7BIT; } +void mutt_stamp_attachment(BODY *a) +{ + a->stamp = time(NULL); +} + /* Assumes called from send mode where BODY->filename points to actual file */ void mutt_update_encoding (BODY *a) { @@ -818,7 +877,8 @@ void mutt_update_encoding (BODY *a) return; mutt_set_encoding (a, info); - + mutt_stamp_attachment(a); + if (a->type == TYPETEXT) { /* make sure the charset is valid */ @@ -849,7 +909,55 @@ void mutt_update_encoding (BODY *a) safe_free ((void **) &info); } -BODY *mutt_make_attach (const char *path) +BODY *mutt_make_message_attach (CONTEXT *ctx, HEADER *hdr, int attach_msg) +{ + char buffer[LONG_STRING]; + BODY *body; + FILE *fp; + + mutt_mktemp (buffer); + if ((fp = safe_fopen (buffer, "w+")) == NULL) + return NULL; + + body = mutt_new_body (); + body->type = TYPEMESSAGE; + body->subtype = safe_strdup ("rfc822"); + body->filename = safe_strdup (buffer); + body->unlink = 1; + body->use_disp = 0; + +#if 0 + /* this MUST come after setting ->filename because we reuse buffer[] */ + strfcpy (buffer, "Forwarded message from ", sizeof (buffer)); + rfc822_write_address (buffer + 23, sizeof (buffer) - 23, hdr->env->from); + body->description = safe_strdup (buffer); +#endif + + mutt_parse_mime_message (ctx, hdr); + + /* If we are attaching a message, ignore OPTMIMEFORWDECODE */ + mutt_copy_message (fp, ctx, hdr, + (!attach_msg && option (OPTMIMEFORWDECODE)) ? M_CM_DECODE : 0, + CH_XMIT | ((!attach_msg && option (OPTMIMEFORWDECODE)) ? (CH_MIME | CH_TXTPLAIN ) : 0)); + + fflush(fp); + rewind(fp); + + body->hdr = mutt_new_header(); + body->hdr->offset = 0; + body->hdr->env = mutt_read_rfc822_header(fp, body->hdr); +#ifdef _PGPPATH + body->hdr->pgp = hdr->pgp; +#endif + mutt_update_encoding (body); + body->parts = body->hdr->content; + + fclose(fp); + + return (body); +} + +BODY *mutt_make_file_attach (const char *path) { BODY *att; CONTENT *info; @@ -893,8 +1001,7 @@ BODY *mutt_make_attach (const char *path) } mutt_set_encoding (att, info); - - + mutt_stamp_attachment(att); #ifdef _PGPPATH /* @@ -1055,11 +1162,7 @@ int mutt_write_rfc822_header (FILE *fp, ENVELOPE *env, BODY *attach, int mode) LIST *tmp = env->userhdrs; if (mode == 0) - { - if (env->message_id) - fprintf (fp, "Message-ID: %s\n", env->message_id); fputs (mutt_make_date (buffer), fp); - } /* OPTUSEFROM is not consulted here so that we can still write a From: * field if the user sets it with the `my_hdr' command @@ -1089,8 +1192,11 @@ int mutt_write_rfc822_header (FILE *fp, ENVELOPE *env, BODY *attach, int mode) if (env->bcc) { - fputs ("Bcc: ", fp); - mutt_write_address_list (env->bcc, fp, 5); + if(mode != 0 || option(OPTWRITEBCC)) + { + fputs ("Bcc: ", fp); + mutt_write_address_list (env->bcc, fp, 5); + } } else if (mode > 0) fputs ("Bcc: \n", fp); @@ -1100,6 +1206,10 @@ int mutt_write_rfc822_header (FILE *fp, ENVELOPE *env, BODY *attach, int mode) else if (mode == 1) fputs ("Subject: \n", fp); + /* save message id if the user has set it */ + if (env->message_id) + fprintf (fp, "Message-ID: %s\n", env->message_id); + if (env->reply_to) { fputs ("Reply-To: ", fp); @@ -1186,18 +1296,46 @@ static void encode_descriptions (BODY *b) } } +const char *mutt_fqdn(short may_hide_host) +{ + char *p = NULL, *q; + + if(Fqdn && Fqdn[0] != '@') + { + p = Fqdn; + + if(may_hide_host && option(OPTHIDDENHOST)) + { + if((p = strchr(Fqdn, '.'))) + p++; + + /* sanity check: don't hide the host if + * the fqdn is something like detebe.org. + */ + + if(!p || !(q = strchr(p, '.'))) + p = Fqdn; + } + } + + return p; +} + char *mutt_gen_msgid (void) { char buf[SHORT_STRING]; time_t now; struct tm *tm; + const char *fqdn; now = time (NULL); tm = localtime (&now); + if(!(fqdn = mutt_fqdn(0))) + fqdn = NONULL(Hostname); + snprintf (buf, sizeof (buf), "<%d%02d%02d%02d%02d%02d.%c%d@%s>", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, - tm->tm_min, tm->tm_sec, MsgIdPfx, getpid (), - Fqdn[0] != '@' ? Fqdn : Hostname); + tm->tm_min, tm->tm_sec, MsgIdPfx, getpid (), fqdn); MsgIdPfx = (MsgIdPfx == 'Z') ? 'A' : MsgIdPfx + 1; return (safe_strdup (buf)); } @@ -1352,9 +1490,13 @@ send_msg (const char *path, char **args, const char *msg, char **tempfile) { #ifdef DEBUG if (WIFEXITED (st)) + { dprint (1, (debugfile, "send_msg(): child exited %d\n", WEXITSTATUS (st))); + } else + { dprint (1, (debugfile, "send_msg(): child did not exit\n")); + } #endif /* DEBUG */ st = WIFEXITED (st) ? WEXITSTATUS (st) : -1; /* return child status */ } @@ -1390,6 +1532,21 @@ add_option (char **args, size_t *argslen, size_t *argsmax, char *s) return (args); } +static const char * +strsysexit(int e) +{ + int i; + + for(i = 0; sysexits_h[i].str; i++) + { + if(e == sysexits_h[i].v) + break; + } + + return sysexits_h[i].str; +} + + static int invoke_sendmail (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc, /* recips */ const char *msg, /* file containing message */ @@ -1434,6 +1591,7 @@ invoke_sendmail (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc, /* recips */ args = add_option (args, &argslen, &argsmax, "-R"); args = add_option (args, &argslen, &argsmax, DsnReturn); } + args = add_option (args, &argslen, &argsmax, "--"); args = add_args (args, &argslen, &argsmax, to); args = add_args (args, &argslen, &argsmax, cc); args = add_args (args, &argslen, &argsmax, bcc); @@ -1447,7 +1605,7 @@ invoke_sendmail (ADDRESS *to, ADDRESS *cc, ADDRESS *bcc, /* recips */ endwin (); if ((i = send_msg (path, args, msg, &childout)) != (EX_OK & 0xff)) { - char *e = strerror (errno); + const char *e = strsysexit(i); fprintf (stderr, "Error sending message, child exited %d (%s).\n", i, NONULL (e)); if (childout) @@ -1501,7 +1659,7 @@ char *mutt_quote_string (const char *s) size_t rlen; rlen = strlen (s) + 3; - pr = r = malloc (rlen); + pr = r = (char *) safe_malloc (rlen); *pr++ = '"'; while (*s) { @@ -1551,7 +1709,13 @@ int mutt_send_message (HEADER *msg, const char *fcc) mutt_write_rfc822_header (tempfp, msg->env, msg->content, 0); fputc ('\n', tempfp); /* tie off the header. */ - mutt_write_mime_body (msg->content, tempfp); + if ((mutt_write_mime_body (msg->content, tempfp) == -1)) + { + fclose(tempfp); + unlink (tempfile); + return (-1); + } + if (fclose (tempfp) != 0) { mutt_perror (tempfile); @@ -1601,11 +1765,13 @@ void mutt_bounce_message (HEADER *h, ADDRESS *to) mutt_mktemp (tempfile); if ((f = safe_fopen (tempfile, "w")) != NULL) { + const char *fqdn; + fseek (msg->fp, h->offset, 0); mutt_copy_header (msg->fp, h, f, CH_XMIT | CH_NONEWLINE, NULL); - fprintf (f, "Resent-From: %s", Username); - if (Fqdn[0] != '@') - fprintf (f, "@%s", Fqdn); + fprintf (f, "Resent-From: %s", NONULL(Username)); + if((fqdn = mutt_fqdn(1))) + fprintf (f, "@%s", fqdn); fprintf (f, "\nResent-%s", mutt_make_date (date)); fputs ("Resent-To: ", f); mutt_write_address_list (to, f, 11); @@ -1688,7 +1854,7 @@ int mutt_write_fcc (const char *path, HEADER *hdr, const char *msgid, int post) } } - hdr->read = 1; /* make sure to put it in the `cur' directory (maildir) */ + hdr->read = !post; /* make sure to put it in the `cur' directory (maildir) */ if ((msg = mx_open_new_message (&f, hdr, M_ADD_FROM)) == NULL) { mx_close_mailbox (&f); diff --git a/snprintf.c b/snprintf.c index c03aa878..4716ee29 100644 --- a/snprintf.c +++ b/snprintf.c @@ -44,7 +44,8 @@ #if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) -#include <ctype.h> +#include <string.h> +# include <ctype.h> #include <sys/types.h> /* Define this as a fall through, HAVE_STDARG_H is probably already set */ @@ -178,7 +179,7 @@ static void dopr (char *buffer, size_t maxlen, const char *format, va_list args) } break; case DP_S_MIN: - if (isdigit(ch)) + if (isdigit((unsigned char)ch)) { min = 10*min + char_to_int (ch); ch = *format++; @@ -202,7 +203,7 @@ static void dopr (char *buffer, size_t maxlen, const char *format, va_list args) state = DP_S_MOD; break; case DP_S_MAX: - if (isdigit(ch)) + if (isdigit((unsigned char)ch)) { if (max < 0) max = 0; diff --git a/socket.c b/socket.c new file mode 100644 index 00000000..63a4f461 --- /dev/null +++ b/socket.c @@ -0,0 +1,112 @@ +/* + * Copyright (C) 1998 Michael R. Elkins <me@cs.hmc.edu> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "mutt.h" +#include "globals.h" +#include "mutt_socket.h" + +#include <unistd.h> +#include <netinet/in.h> +#include <netdb.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/socket.h> + +/* support for multiple socket connections */ + +static CONNECTION *Connections = NULL; +static int NumConnections = 0; + +/* simple read buffering to speed things up. */ +int mutt_socket_readchar (CONNECTION *conn, char *c) +{ + if (conn->bufpos >= conn->available) + { + conn->available = read (conn->fd, conn->inbuf, LONG_STRING); + dprint (1, (debugfile, "mutt_socket_readchar(): buffered %d chars\n", conn->available)); + conn->bufpos = 0; + if (conn->available <= 0) + return conn->available; /* returns 0 for EOF or -1 for other error */ + } + *c = conn->inbuf[conn->bufpos]; + conn->bufpos++; + return 1; +} + +int mutt_socket_read_line (char *buf, size_t buflen, CONNECTION *conn) +{ + char ch; + int i; + + for (i = 0; i < buflen; i++) + { + if (mutt_socket_readchar (conn, &ch) != 1) + return (-1); + if (ch == '\n') + break; + buf[i] = ch; + } + buf[i-1] = 0; + return (i + 1); +} + +int mutt_socket_read_line_d (char *buf, size_t buflen, CONNECTION *conn) +{ + int r = mutt_socket_read_line (buf, buflen, conn); + dprint (1,(debugfile,"mutt_socket_read_line_d():%s\n", buf)); + return r; +} + +int mutt_socket_write (CONNECTION *conn, const char *buf) +{ + dprint (1,(debugfile,"mutt_socket_write():%s", buf)); + return (write (conn->fd, buf, strlen (buf))); +} + +CONNECTION *mutt_socket_select_connection (char *host, int port, int flags) +{ + int x; + + if (flags != M_NEW_SOCKET) + { + for (x = 0; x < NumConnections; x++) + { + if (!strcmp (host, Connections[x].server) && + (port == Connections[x].port)) + return &Connections[x]; + } + } + if (NumConnections == 0) + { + NumConnections = 1; + Connections = (CONNECTION *) safe_malloc (sizeof (CONNECTION)); + } + else + { + NumConnections++; + safe_realloc ((void *)&Connections, sizeof (CONNECTION) * NumConnections); + } + Connections[NumConnections - 1].bufpos = 0; + Connections[NumConnections - 1].available = 0; + Connections[NumConnections - 1].uses = 0; + Connections[NumConnections - 1].server = safe_strdup (host); + Connections[NumConnections - 1].port = port; + + return &Connections[NumConnections - 1]; +} + diff --git a/sort.h b/sort.h index 75500249..7e7c41e2 100644 --- a/sort.h +++ b/sort.h @@ -16,8 +16,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "mapping.h" - #define SORT_DATE 1 /* the date the mail was sent. */ #define SORT_SIZE 2 #define SORT_SUBJECT 3 diff --git a/status.c b/status.c index dd61d757..7cf86807 100644 --- a/status.c +++ b/status.c @@ -20,6 +20,7 @@ #include "mutt_menu.h" #include "mutt_curses.h" #include "sort.h" +#include "mapping.h" #include <string.h> #include <ctype.h> @@ -86,7 +87,7 @@ status_format_str (char *buf, size_t buflen, char op, const char *src, case 'h': snprintf (fmt, sizeof (fmt), "%%%ss", prefix); - snprintf (buf, buflen, fmt, Hostname); + snprintf (buf, buflen, fmt, NONULL(Hostname)); break; case 'f': diff --git a/thread.c b/thread.c index 2c2570a1..8336e91d 100644 --- a/thread.c +++ b/thread.c @@ -585,8 +585,44 @@ void mutt_sort_threads (CONTEXT *ctx, int init) mutt_linearize_tree (ctx, 1); } +static HEADER *find_virtual (HEADER *cur) +{ + HEADER *top; + + if (cur->virtual >= 0) + return (cur); + + top = cur; + if ((cur = cur->child) == NULL) + return (NULL); + + FOREVER + { + if (cur->virtual >= 0) + return (cur); + + if (cur->child) + cur = cur->child; + else if (cur->next) + cur = cur->next; + else + { + while (!cur->next) + { + cur = cur->parent; + if (cur == top) + return (NULL); + } + cur = cur->next; + } + /* not reached */ + } +} + int _mutt_aside_thread (HEADER *hdr, short dir, short subthreads) { + HEADER *tmp; + if ((Sort & SORT_MASK) != SORT_THREADS) { mutt_error ("Threading is not enabled."); @@ -600,7 +636,7 @@ int _mutt_aside_thread (HEADER *hdr, short dir, short subthreads) } else { - if (dir) + if ((dir != 0) ^ ((Sort & SORT_REVERSE) != 0)) { while (!hdr->next && hdr->parent) hdr = hdr->parent; @@ -611,15 +647,27 @@ int _mutt_aside_thread (HEADER *hdr, short dir, short subthreads) hdr = hdr->parent; } } - - hdr = (dir != 0) ^ ((Sort & SORT_REVERSE) != 0) ? hdr->next : hdr->prev; - if (hdr) + + if ((dir != 0) ^ ((Sort & SORT_REVERSE) != 0)) { - if (Sort & SORT_REVERSE) - return (hdr->next ? hdr->next->virtual + 1 : 0); - else - return (hdr->virtual); + do + { + hdr = hdr->next; + if (!hdr) + return (-1); + tmp = find_virtual (hdr); + } while (!tmp); } else - return (-1); + { + do + { + hdr = hdr->prev; + if (!hdr) + return (-1); + tmp = find_virtual (hdr); + } while (!tmp); + } + + return (tmp->virtual); }