* A few improvements to the http code, which make the http_* functions not return...
[alpine.git] / pith / conf.c
bloba3f50b397b1c60d16521d9e5789f457b9dbab5af
1 #if !defined(lint) && !defined(DOS)
2 static char rcsid[] = "$Id: conf.c 1266 2009-07-14 18:39:12Z hubert@u.washington.edu $";
3 #endif
5 /*
6 * ========================================================================
7 * Copyright 2013-2020 Eduardo Chappa
8 * Copyright 2006-2009 University of Washington
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * ========================================================================
19 /*======================================================================
20 conf.c
21 Implements the Pine configuration management routines
22 ====*/
25 #include "../pith/headers.h"
26 #include "../pith/init.h"
27 #include "../pith/conf.h"
28 #include "../pith/state.h"
29 #include "../pith/remote.h"
30 #include "../pith/keyword.h"
31 #include "../pith/mailview.h"
32 #include "../pith/list.h"
33 #include "../pith/status.h"
34 #include "../pith/ldap.h"
35 #include "../pith/folder.h"
36 #include "../pith/thread.h"
37 #include "../pith/news.h"
38 #include "../pith/util.h"
39 #include "../pith/pattern.h"
40 #include "../pith/color.h"
41 #include "../pith/options.h"
42 #include "../pith/busy.h"
43 #include "../pith/readfile.h"
44 #include "../pith/hist.h"
45 #include "../pith/mailindx.h"
46 #include "../pith/tempfile.h"
47 #include "../pith/icache.h"
48 #include "../pith/sort.h"
49 #include "../pith/smime.h"
50 #include "../pith/charconv/utf8.h"
51 #ifdef _WINDOWS
52 #include "../pico/osdep/mswin.h"
53 #endif
55 #define TO_BAIL_THRESHOLD 60
59 * Internal prototypes
61 void convert_configvars_to_utf8(struct variable *, char *);
62 void convert_configvar_to_utf8(struct variable *, char *);
63 void set_current_pattern_vals(struct pine *);
64 void convert_pattern_data(void);
65 void convert_filts_pattern_data(void);
66 void convert_scores_pattern_data(void);
67 void convert_pinerc_patterns(long);
68 void convert_pinerc_filts_patterns(long);
69 void convert_pinerc_scores_patterns(long);
70 void set_old_growth_bits(struct pine *, int);
71 int var_is_in_rest_of_file(char *, char *);
72 char *skip_over_this_var(char *, char *);
73 char *native_nl(char *);
74 void set_color_val(struct variable *, int);
75 int copy_localfile_to_remotefldr(RemType, char *, char *, char *, char **);
76 char *backcompat_convert_from_utf8(char **, size_t, char *);
77 #ifdef _WINDOWS
78 char *transformed_color(char *);
79 int convert_pc_gray_names(struct pine *, PINERC_S *, EditWhich);
80 int unix_color_style_in_pinerc(PINERC_S *);
81 char *pcpine_general_help(char *);
82 char *pcpine_help(HelpType); /* defined in alpine/help */
83 #endif /* _WINDOWS */
86 /* hook too allow caller to decide what to do about failure */
87 int (*pith_opt_remote_pinerc_failure)(void);
90 /*------------------------------------
91 Some definitions to keep the static "variable" array below
92 a bit more readable...
93 ----*/
94 CONF_TXT_T cf_text_comment[] = "#\n# Alpine configuration file\n#\n# This file sets the configuration options used by Alpine and PC-Alpine. These\n# options are usually set from within Alpine or PC-Alpine. There may be a\n# system-wide configuration file which sets the defaults for some of the\n# variables. On Unix, run alpine -conf to see how system defaults have been set.\n# For variables that accept multiple values, list elements are\
95 separated by\n# commas. A line beginning with a space or tab is considered to be a\n# continuation of the previous line. For a variable to be unset its value must\n# be blank. To set a variable to the empty string its value should be \"\".\n# You can override system defaults by setting a variable to the empty string.\n# Lines beginning with \"#\" are comments, and ignored by Alpine.\n";
98 CONF_TXT_T cf_text_personal_name[] = "Over-rides your full name from Unix password file. Required for PC-Alpine.";
100 CONF_TXT_T cf_text_user_id[] = "Your login/e-mail user name";
102 CONF_TXT_T cf_text_user_domain[] = "Sets domain part of From: and local addresses in outgoing mail.";
104 CONF_TXT_T cf_text_smtp_server[] = "List of SMTP servers for sending mail. If blank: Unix Alpine uses sendmail.";
106 CONF_TXT_T cf_text_nntp_server[] = "NNTP server for posting news. Also sets news-collections for news reading.";
108 #ifdef SMIME
110 CONF_TXT_T cf_text_publiccertdir[] = "Public certificates are kept in files in this directory. The files should\n# contain certificates in PEM format. The name of each file should look\n# like <emailaddress>.crt. The default directory is .alpine-smime/public.";
112 CONF_TXT_T cf_text_privatekeydir[] = "Private keys are kept in files in this directory. The files are in PEM format.\n# The name of a file should look like <emailaddress>.key.\n# The default directory is .alpine-smime/private.";
114 CONF_TXT_T cf_text_cacertdir[] = "Certificate Authority certificates (in addition to the normal CACerts for the\n# system) are kept in files in this directory. The files are in PEM format.\n# Filenames should end with .crt. The default directory is .alpine-smime/ca.";
116 CONF_TXT_T cf_text_publiccertcontainer[] = "If this option is set then public certificates are kept in a single container\n# \"file\" similar to a remote configuration file instead of in the\n# smime-publiccert-directory. The value can be a remote or local folder\n# specification like for a non-standard pinerc value. The default\n# is that it is not set.";
118 CONF_TXT_T cf_text_privatekeycontainer[] = "If this option is set then private keys are kept in a single container\n# \"file\" similar to a remote configuration file instead of in the\n# private-key-directory. The value can be a remote or local folder\n# specification like for a non-standard pinerc value. The default\n# is that it is not set.";
120 CONF_TXT_T cf_text_cacertcontainer[] = "If this option is set then CAcerts are kept in a single container\n# \"file\" similar to a remote configuration file instead of in the\n# ca-cert-directory. The value can be a remote or local folder\n# specification like for a non-standard pinerc value. The default\n# is that it is not set.";
122 #endif /* SMIME */
124 #ifdef ENABLE_LDAP
125 CONF_TXT_T cf_text_ldap_server[] = "LDAP servers for looking up addresses.";
126 #endif /* ENABLE_LDAP */
128 CONF_TXT_T cf_text_rss_news[] = "RSS News feed";
130 CONF_TXT_T cf_text_rss_weather[] = "RSS Weather feed";
132 CONF_TXT_T cf_text_wp_indexheight[] = "Web Alpine index table row height";
134 CONF_TXT_T cf_text_wp_indexlines[] = "Web Alpine number of index lines in table";
136 CONF_TXT_T cf_text_wp_aggstate[] = "Web Alpine aggregate operations tab state";
138 CONF_TXT_T cf_text_wp_state[] = "Web Alpine various aspects of cross-session state";
140 CONF_TXT_T cf_text_wp_columns[] = "Web Alpine preferred width for message display in characters";
142 CONF_TXT_T cf_text_inbox_path[] = "Path of (local or remote) INBOX, e.g. ={mail.somewhere.edu}inbox\n# Normal Unix default is the local INBOX (usually /usr/spool/mail/$USER).";
144 CONF_TXT_T cf_text_incoming_folders[] = "List of incoming msg folders besides INBOX, e.g. ={host2}inbox, {host3}inbox\n# Syntax: optnl-label {optnl-imap-host-name}folder-path";
146 CONF_TXT_T cf_text_folder_collections[] = "List of directories where saved-message folders may be. First one is\n# the default for Saves. Example: Main {host1}mail/[], Desktop mail\\[]\n# Syntax: optnl-label {optnl-imap-hostname}optnl-directory-path[]";
148 CONF_TXT_T cf_text_news_collections[] = "List, only needed if nntp-server not set, or news is on a different host\n# than used for NNTP posting. Examples: News *[] or News *{host3/nntp}[]\n# Syntax: optnl-label *{news-host/protocol}[]";
150 CONF_TXT_T cf_text_pruned_folders[] = "List of folders, assumed to be in first folder collection,\n# offered for pruning each month. For example: mumble";
152 CONF_TXT_T cf_text_default_fcc[] = "Over-rides default path for sent-mail folder, e.g. =old-mail (using first\n# folder collection dir) or ={host2}sent-mail or =\"\" (to suppress saving).\n# Default: sent-mail (Unix) or SENTMAIL.MTX (PC) in default folder collection.";
154 CONF_TXT_T cf_text_default_saved[] = "Over-rides default path for saved-msg folder, e.g. =saved-messages (using 1st\n# folder collection dir) or ={host2}saved-mail or =\"\" (to suppress saving).\n# Default: saved-messages (Unix) or SAVEMAIL.MTX (PC) in default collection.";
156 CONF_TXT_T cf_text_postponed_folder[] = "Over-rides default path for postponed messages folder, e.g. =pm (which uses\n# first folder collection dir) or ={host4}pm (using home dir on host4).\n# Default: postponed-msgs (Unix) or POSTPOND.MTX (PC) in default fldr coltn.";
158 CONF_TXT_T cf_text_mail_directory[] = "Alpine compares this value with the first folder collection directory.\n# If they match (or no folder collections are defined), and the directory\n# does not exist, Alpine will create and use it. Default: ~/mail";
160 CONF_TXT_T cf_text_read_message_folder[] = "If set, specifies where already-read messages will be moved upon quitting.";
162 CONF_TXT_T cf_text_form_letter_folder[] = "If set, specifies where form letters should be stored.";
164 CONF_TXT_T cf_text_trash_folder[] = "If set, specifies where trash is moved to in Web Alpine.";
166 CONF_TXT_T cf_text_signature_file[] = "Over-rides default path for signature file. Default is ~/.signature";
168 CONF_TXT_T cf_text_literal_sig[] = "Contains the actual signature contents as opposed to the signature filename.\n# If defined, this overrides the signature-file. Default is undefined.";
170 CONF_TXT_T cf_text_global_address_book[] = "List of file or path names for global/shared addressbook(s).\n# Default: none\n# Syntax: optnl-label path-name";
172 CONF_TXT_T cf_text_address_book[] = "List of file or path names for personal addressbook(s).\n# Default: ~/.addressbook (Unix) or \\PINE\\ADDRBOOK (PC)\n# Syntax: optnl-label path-name";
174 CONF_TXT_T cf_text_feature_list[] = "List of features; see Alpine's Setup/options menu for the current set.\n# e.g. feature-list= select-without-confirm, signature-at-bottom\n# Default condition for all of the features is no-.";
176 CONF_TXT_T cf_text_initial_keystroke_list[] = "Alpine executes these keys upon startup (e.g. to view msg 13: i,j,1,3,CR,v)";
178 CONF_TXT_T cf_text_default_composer_hdrs[] = "Only show these headers (by default) when composing messages";
180 CONF_TXT_T cf_text_customized_hdrs[] = "Add these customized headers (and possible default values) when composing";
182 CONF_TXT_T cf_text_view_headers[] = "When viewing messages, include this list of headers";
184 CONF_TXT_T cf_text_view_margin_left[] = "When viewing messages, number of blank spaces between left display edge and text";
186 CONF_TXT_T cf_text_view_margin_right[] = "When viewing messages, number of blank spaces between right display edge and text";
188 CONF_TXT_T cf_text_quote_suppression[] = "When viewing messages, number of lines of quote displayed before suppressing";
190 CONF_TXT_T cf_text_wordsep[] = "When these characters appear in the middle of a word in the composer\n# the forward word function will stop at the first text following (as happens\n# with SPACE characters by default)";
192 CONF_TXT_T cf_text_color_style[] = "Controls display of color";
194 CONF_TXT_T cf_text_current_indexline_style[] = "Controls display of color for current index line";
196 CONF_TXT_T cf_text_titlebar_color_style[] = "Controls display of color for the titlebar at top of screen";
198 CONF_TXT_T cf_text_view_hdr_color[] = "When viewing messages, these are the header colors";
200 CONF_TXT_T cf_text_index_token_color[] = "Colors in which tokens will be displayed in the index screen";
202 CONF_TXT_T cf_text_save_msg_name_rule[] = "Determines default folder name for Saves...\n# Choices: default-folder, by-sender, by-from, by-recipient, last-folder-used.\n# Default: \"default-folder\", i.e. \"saved-messages\" (Unix) or \"SAVEMAIL\" (PC).";
204 CONF_TXT_T cf_text_fcc_name_rule[] = "Determines default name for Fcc...\n# Choices: default-fcc, by-recipient, last-fcc-used.\n# Default: \"default-fcc\" (see also \"default-fcc=\" variable.)";
206 CONF_TXT_T cf_text_sort_key[] = "Sets presentation order of messages in Index. Choices:\n# Subject, From, Arrival, Date, Size, To, Cc, OrderedSubj, Score, and Thread.\n# Order may be reversed by appending /Reverse. Default: \"Arrival\".";
208 CONF_TXT_T cf_text_addrbook_sort_rule[] = "Sets presentation order of address book entries. Choices: dont-sort,\n# fullname-with-lists-last, fullname, nickname-with-lists-last, nickname\n# Default: \"fullname-with-lists-last\".";
210 CONF_TXT_T cf_text_folder_sort_rule[] = "Sets presentation order of folder list entries. Choices: alphabetical,\n# alpha-with-dirs-last, alpha-with-dirs-first.\n# Default: \"alpha-with-directories-last\".";
212 CONF_TXT_T cf_text_old_char_set[] = "Character-set is obsolete, use display-character-set, keyboard-character-set,\n# and posting-character-set.";
214 CONF_TXT_T cf_text_disp_char_set[] = "Reflects capabilities of the display you have.\n# If unset, the default is taken from your locale. That is usually the right\n# thing to use. Typical alternatives include UTF-8, ISO-8859-x, and EUC-JP\n# (where x is a number between 1 and 9).";
216 CONF_TXT_T cf_text_key_char_set[] = "Reflects capabilities of the keyboard you have.\n# If unset, the default is to use the same value\n# used for the display-character-set.";
218 CONF_TXT_T cf_text_post_character_set[] = "Defaults to UTF-8. This is used for outgoing messages.\n# It is usually correct to leave this unset.";
220 CONF_TXT_T cf_text_unk_character_set[] = "Defaults to nothing, which is equivalent to US-ASCII. This is used for\n# unlabeled incoming messages. It is ok to leave this unset but if you receive\n# unlabeled mail that is usually in some known character set, set that here.";
222 CONF_TXT_T cf_text_editor[] = "Specifies the program invoked by ^_ in the Composer,\n# or the \"enable-alternate-editor-implicitly\" feature.";
224 CONF_TXT_T cf_text_speller[] = "Specifies the program invoked by ^T in the Composer.";
226 #ifdef _WINDOWS
227 CONF_TXT_T cf_text_speller_dictionary[] = "Specifies the list of dictionaries used by Aspell.";
228 #endif /* _WINDOWS */
230 CONF_TXT_T cf_text_deadlets[] = "Specifies the number of dead letter files to keep when canceling.";
232 CONF_TXT_T cf_text_fillcol[] = "Specifies the column of the screen where the composer should wrap.";
234 CONF_TXT_T cf_text_replystr[] = "Specifies the string to insert when replying to a message.";
236 CONF_TXT_T cf_text_quotereplstr[] = "Specifies the string to replace quotes with when viewing a message.";
238 CONF_TXT_T cf_text_replyintro[] = "Specifies the introduction to insert when replying to a message.";
240 CONF_TXT_T cf_text_emptyhdr[] = "Specifies the string to use when sending a message with no to or cc.";
242 CONF_TXT_T cf_text_image_viewer[] = "Program to view images (e.g. GIF or TIFF attachments).";
244 CONF_TXT_T cf_text_browser[] = "List of programs to open Internet URLs (e.g. http or ftp references).";
246 CONF_TXT_T cf_text_history[] = "List of directories that are preferred locations to save or export attachments.";
248 CONF_TXT_T cf_text_inc_startup[] = "Sets message which cursor begins on. Choices: first-unseen, first-recent,\n# first-important, first-important-or-unseen, first-important-or-recent,\n# first, last. Default: \"first-unseen\".";
250 CONF_TXT_T cf_pruning_rule[] = "Allows a default answer for the prune folder questions. Choices: yes-ask,\n# yes-no, no-ask, no-no, ask-ask, ask-no. Default: \"ask-ask\".";
252 CONF_TXT_T cf_reopen_rule[] = "Controls behavior when reopening an already open folder.";
254 CONF_TXT_T cf_text_thread_disp_style[] = "Style that MESSAGE INDEX is displayed in when threading.";
256 CONF_TXT_T cf_text_thread_index_style[] = "Style of THREAD INDEX or default MESSAGE INDEX when threading.";
258 CONF_TXT_T cf_text_thread_more_char[] = "When threading, character used to indicate collapsed messages underneath.";
260 CONF_TXT_T cf_text_thread_exp_char[] = "When threading, character used to indicate expanded messages underneath.";
262 CONF_TXT_T cf_text_thread_lastreply_char[] = "When threading, character used to indicate this is the last reply\n# to the parent of this message.";
264 CONF_TXT_T cf_text_use_only_domain_name[] = "If \"user-domain\" not set, strips hostname in FROM address. (Unix only)";
266 CONF_TXT_T cf_text_printer[] = "Your default printer selection";
268 CONF_TXT_T cf_text_personal_print_command[] = "List of special print commands";
270 CONF_TXT_T cf_text_personal_print_cat[] = "Which category default print command is in";
272 CONF_TXT_T cf_text_standard_printer[] = "The system wide standard printers";
274 CONF_TXT_T cf_text_xoauth2_info[] = "Your client-id and client-secret information to authenticate using XOAUTH2";
276 CONF_TXT_T cf_text_last_time_prune_quest[] = "Set by Alpine; controls beginning-of-month sent-mail pruning.";
278 CONF_TXT_T cf_text_last_version_used[] = "Set by Alpine; controls display of \"new version\" message.";
280 CONF_TXT_T cf_text_disable_drivers[] = "List of mail drivers to disable.";
282 CONF_TXT_T cf_text_disable_auths[] = "List of SASL authenticators to disable.";
284 CONF_TXT_T cf_text_encryption_range[] = "A range in the form min,max that sets the minimum amd maximum versions of the\n# SSL protocol that Alpine will use when connecting to a secure server.";
286 CONF_TXT_T cf_text_remote_abook_metafile[] = "Set by Alpine; contains data for caching remote address books.";
288 CONF_TXT_T cf_text_old_patterns[] = "Patterns is obsolete, use patterns-xxx";
290 CONF_TXT_T cf_text_old_filters[] = "Patterns-filters is obsolete, use patterns-filters2";
292 CONF_TXT_T cf_text_old_scores[] = "Patterns-scores is obsolete, use patterns-scores2";
294 CONF_TXT_T cf_text_patterns[] = "Patterns and their actions are stored here.";
296 CONF_TXT_T cf_text_remote_abook_history[] = "How many extra copies of remote address book should be kept. Default: 3";
298 CONF_TXT_T cf_text_remote_abook_validity[] = "Minimum number of minutes between checks for remote address book changes.\n# 0 means never check except when opening a remote address book.\n# -1 means never check. Default: 5";
300 CONF_TXT_T cf_text_bugs_fullname[] = "Full name for bug report address used by \"Report Bug\" command";
302 CONF_TXT_T cf_text_bugs_address[] = "Email address used to send bug reports";
304 CONF_TXT_T cf_text_bugs_extras[] = "Program/Script used by \"Report Bug\" command. No default.";
306 CONF_TXT_T cf_text_suggest_fullname[] = "Full name for suggestion address used by \"Report Bug\" command";
308 CONF_TXT_T cf_text_suggest_address[] = "Email address used to send suggestions";
310 CONF_TXT_T cf_text_local_fullname[] = "Full name for \"local support\" address used by \"Report Bug\" command.\n# Default: Local Support";
312 CONF_TXT_T cf_text_local_address[] = "Email address used to send to \"local support\".\n# Default: postmaster";
314 CONF_TXT_T cf_text_forced_abook[] = "Force these address book entries into all writable personal address books.\n# Syntax is forced-abook-entry=nickname|fullname|address\n# This is a comma-separated list of entries, each with syntax above.\n# Existing entries with same nickname are not replaced.\n# Example: help|Help Desk|help@ourdomain.com";
316 CONF_TXT_T cf_text_kblock_passwd[] = "This is a number between 1 and 5. It is the number of times a user will\n# have to enter a password when they run the keyboard lock command in the\n# main menu. Default is 1.";
318 CONF_TXT_T cf_text_sendmail_path[] = "This names the path to an alternative program, and any necessary arguments,\n# to be used in posting mail messages. Example:\n# /usr/lib/sendmail -oem -t -oi\n# or,\n# /usr/local/bin/sendit.sh\n# The latter a script found in Alpine distribution's contrib/util directory.\n# NOTE: The program MUST read the message to be posted on standard input,\n# AND operate in the style of sendmail's \"-t\" option.";
320 CONF_TXT_T cf_text_oper_dir[] = "This names the root of the tree to which the user is restricted when reading\n# and writing folders and files. For example, on Unix ~/work confines the\n# user to the subtree beginning with their work subdirectory.\n# (Note: this alone is not sufficient for preventing access. You will also\n# need to restrict shell access and so on, see Alpine Technical Notes.)\n# Default: not set (so no restriction)";
322 CONF_TXT_T cf_text_in_fltr[] = "This variable takes a list of programs that message text is piped into\n# after MIME decoding, prior to display.";
324 CONF_TXT_T cf_text_out_fltr[] = "This defines a program that message text is piped into before MIME\n# encoding, prior to sending";
326 CONF_TXT_T cf_text_alt_addrs[] = "A list of alternate addresses the user is known by";
328 CONF_TXT_T cf_text_keywords[] = "A list of keywords for use in categorizing messages";
330 CONF_TXT_T cf_text_kw_colors[] = "Colors used to display keywords in the index";
332 CONF_TXT_T cf_text_kw_braces[] = "Characters which surround keywords in SUBJKEY token.\n# Default is \"{\" \"} \"";
334 CONF_TXT_T cf_text_opening_sep[] = "Characters between subject and opening text in SUBJECTTEXT token.\n# Default is \" - \"";
336 CONF_TXT_T cf_text_abook_formats[] = "This is a list of formats for address books. Each entry in the list is made\n# up of space-delimited tokens telling which fields are displayed and in\n# which order. See help text";
338 CONF_TXT_T cf_text_index_format[] = "This gives a format for displaying the index. It is made\n# up of space-delimited tokens telling which fields are displayed and in\n# which order. See help text";
340 CONF_TXT_T cf_text_overlap[] = "The number of lines of overlap when scrolling through message text";
342 CONF_TXT_T cf_text_maxremstreams[] = "The maximum number of non-stayopen remote connections that Alpine will use";
344 CONF_TXT_T cf_text_permlocked[] = "A list of folders that should be left open once opened (INBOX is implicit)";
346 CONF_TXT_T cf_text_margin[] = "Number of lines from top and bottom of screen where single\n# line scrolling occurs.";
348 CONF_TXT_T cf_text_stat_msg_delay[] = "The number of seconds to sleep after writing a status message";
350 CONF_TXT_T cf_text_busy_cue_rate[] = "Number of times per-second to update busy cue messages";
352 CONF_TXT_T cf_text_mailcheck[] = "The approximate number of seconds between checks for new mail";
354 CONF_TXT_T cf_text_mailchecknoncurr[] = "The approximate number of seconds between checks for new mail in folders\n# other than the current folder and inbox.\n# Default is same as mail-check-interval";
356 CONF_TXT_T cf_text_maildropcheck[] = "The minimum number of seconds between checks for new mail in a Mail Drop.\n# This is always effectively at least as large as the mail-check-interval";
358 CONF_TXT_T cf_text_nntprange[] = "For newsgroups accessed using NNTP, only messages numbered in the range\n# lastmsg-range+1 to lastmsg will be considered";
360 CONF_TXT_T cf_text_news_active[] = "Path and filename of news configuration's active file.\n# The default is typically \"/usr/lib/news/active\".";
362 CONF_TXT_T cf_text_news_spooldir[] = "Directory containing system's news data.\n# The default is typically \"/usr/spool/news\"";
364 CONF_TXT_T cf_text_upload_cmd[] = "Path and filename of the program used to upload text from your terminal\n# emulator's into Alpine's composer.";
366 CONF_TXT_T cf_text_upload_prefix[] = "Text sent to terminal emulator prior to invoking the program defined by\n# the upload-command variable.\n# Note: _FILE_ will be replaced with the temporary file used in the upload.";
368 CONF_TXT_T cf_text_download_cmd[] = "Path and filename of the program used to download text via your terminal\n# emulator from Alpine's export and save commands.";
370 CONF_TXT_T cf_text_download_prefix[] = "Text sent to terminal emulator prior to invoking the program defined by\n# the download-command variable.\n# Note: _FILE_ will be replaced with the temporary file used in the download.";
372 CONF_TXT_T cf_text_goto_default[] = "Sets the default folder and collection offered at the Goto Command's prompt.";
374 CONF_TXT_T cf_text_mailcap_path[] = "Sets the search path for the mailcap configuration file.\n# NOTE: colon delimited under UNIX, semi-colon delimited under DOS/Windows/OS2.";
376 CONF_TXT_T cf_text_mimetype_path[] = "Sets the search path for the mimetypes configuration file.\n# NOTE: colon delimited under UNIX, semi-colon delimited under DOS/Windows/OS2.";
378 #if !defined(_WINDOWS) || defined(WINDOWS_LIBRESSL_CERTS)
379 CONF_TXT_T cf_text_system_certs_path[] = "Sets the path for the system ssl certificates issued by a trusted\n# certificate authority. Note that this could be a list of paths, if the same\n# pinerc is used in different systems. Alpine always chooses the first one that\n# it finds. Value must be an absolute path.";
381 CONF_TXT_T cf_text_system_certs_file[] = "Sets the path for the system ssl file container of certificates issued by a\n# certificate authority. Note that this could be a list of container files,\n# if the same pinerc is used in different systems. Alpine always chooses the,\n# first one that it finds. Value must be an absolute path.";
382 #endif
384 CONF_TXT_T cf_text_newmail_fifo_path[] = "Sets the filename for the newmail fifo (named pipe). Unix only.";
386 CONF_TXT_T cf_text_nmw_width[] = "Sets the width for the NewMail screen.";
388 CONF_TXT_T cf_text_user_input_timeo[] = "If no user input for this many hours, Alpine will exit if in an idle loop\n# waiting for a new command. If set to zero (the default), then there will\n# be no timeout.";
390 CONF_TXT_T cf_text_debug_mem[] = "Debug-memory is obsolete";
392 CONF_TXT_T cf_text_tcp_open_timeo[] = "Sets the time in seconds that Alpine will attempt to open a network\n# connection. The default is 30, the minimum is 5, and the maximum is\n# system defined (typically 75).";
394 CONF_TXT_T cf_text_tcp_read_timeo[] = "Network read warning timeout. The default is 15, the minimum is 5, and the\n# maximum is 1000.";
396 CONF_TXT_T cf_text_tcp_write_timeo[] = "Network write warning timeout. The default is 0 (unset), the minimum\n# is 5 (if not 0), and the maximum is 1000.";
398 CONF_TXT_T cf_text_tcp_query_timeo[] = "If this much time has elapsed at the time of a tcp read or write\n# timeout, Alpine will ask if you want to break the connection.\n# Default is 60 seconds, minimum is 5, maximum is 1000.";
400 CONF_TXT_T cf_text_close_connection_timeo[] = "If this much time has elapsed at the time of a tcp read or write timeout,\n# Alpine will close the connection automatically without user intervention.\n# Setting this value to zero (the default) disables this. Setting this variable\n# to a smaller value than tcp-query-timeout will close the connection\n# automatically, and you will never be asked if you want to wait.";
402 CONF_TXT_T cf_text_rsh_open_timeo[] = "Sets the time in seconds that Alpine will attempt to open a UNIX remote\n# shell connection. The default is 15, min is 5, and max is unlimited.\n# Zero disables rsh altogether.";
404 CONF_TXT_T cf_text_rsh_path[] = "Sets the name of the command used to open a UNIX remote shell connection.\n# The default is typically /usr/ucb/rsh.";
406 CONF_TXT_T cf_text_rsh_command[] = "Sets the format of the command used to open a UNIX remote\n# shell connection. The default is \"%s %s -l %s exec /etc/r%sd\"\n# NOTE: the 4 (four) \"%s\" entries MUST exist in the provided command\n# where the first is for the command's path, the second is for the\n# host to connect to, the third is for the user to connect as, and the\n# fourth is for the connection method (typically \"imap\")";
408 CONF_TXT_T cf_text_ssh_open_timeo[] = "Sets the time in seconds that Alpine will attempt to open a UNIX secure\n# shell connection. The default is 15, min is 5, and max is unlimited.\n# Zero disables ssh altogether.";
410 CONF_TXT_T cf_text_inc_check_timeo[] = "Sets the time in seconds that Alpine will attempt to open a network\n# connection when checking for new unseen messages in an incoming folder.\n# The default is 5.";
412 CONF_TXT_T cf_text_inc_check_interval[] = "Sets the approximate number of seconds between checks for unseen messages\n# in incoming folders. The default is 180.";
414 CONF_TXT_T cf_text_inc_second_check_interval[] = "Sets the approximate number of seconds between checks for unseen messages\n# for other than local or IMAP folders. The default is 180.";
416 CONF_TXT_T cf_text_inc_check_list[] = "List of incoming folders to check for unseen messages. The default if left\n# blank is to check all incoming folders.";
418 CONF_TXT_T cf_text_ssh_path[] = "Sets the name of the command used to open a UNIX secure shell connection.\n# Typically this is /usr/bin/ssh.";
420 CONF_TXT_T cf_text_ssh_command[] = "Sets the format of the command used to open a UNIX secure\n# shell connection. The default is \"%s %s -l %s exec /etc/r%sd\"\n# NOTE: the 4 (four) \"%s\" entries MUST exist in the provided command\n# where the first is for the command's path, the second is for the\n# host to connect to, the third is for the user to connect as, and the\n# fourth is for the connection method (typically \"imap\")";
422 CONF_TXT_T cf_text_version_threshold[] = "Sets the version number Alpine will use as a threshold for offering\n# its new version message on startup.";
424 CONF_TXT_T cf_text_archived_folders[] = "List of folder pairs; the first indicates a folder to archive, and the\n# second indicates the folder read messages in the first should\n# be moved to.";
426 CONF_TXT_T cf_text_elm_style_save[] = "Elm-style-save is obsolete, use saved-msg-name-rule";
428 CONF_TXT_T cf_text_header_in_reply[] = "Header-in-reply is obsolete, use include-header-in-reply in feature-list";
430 CONF_TXT_T cf_text_feature_level[] = "Feature-level is obsolete, use feature-list";
432 CONF_TXT_T cf_text_old_style_reply[] = "Old-style-reply is obsolete, use signature-at-bottom in feature-list";
434 CONF_TXT_T cf_text_compose_mime[] = "Compose-mime is obsolete";
436 CONF_TXT_T cf_text_show_all_characters[] = "Show-all-characters is obsolete";
438 CONF_TXT_T cf_text_save_by_sender[] = "Save-by-sender is obsolete, use saved-msg-name-rule";
440 CONF_TXT_T cf_text_file_dir[] = "Default directory used for Attachment handling (attach and save)\n# and Export command output";
442 CONF_TXT_T cf_text_folder_extension[] = "Folder-extension is obsolete";
444 CONF_TXT_T cf_text_normal_foreground_color[] = "Choose: black, blue, green, cyan, red, magenta, yellow, or white.";
446 CONF_TXT_T cf_text_window_position[] = "Window position in the format: CxR+X+Y\n# Where C and R are the window size in characters and X and Y are the\n# screen position of the top left corner of the window.\n# This is no longer used unless position is not set in registry.";
448 CONF_TXT_T cf_text_newsrc_path[] = "Full path and name of NEWSRC file";
451 /*----------------------------------------------------------------------
452 These are the variables that control a number of pine functions. They
453 come out of the .pinerc and the /usr/local/lib/pine.conf files. Some can
454 be set by the user while in Alpine. Eventually all the local ones should
455 be so and maybe the global ones too.
457 Each variable can have a command-line, user, global, and current value.
458 All of these values are malloc'd. The user value is the one read out of
459 the user's .pinerc, the global value is the one from the system pine
460 configuration file. There are often defaults for the global values, set
461 at the start of init_vars(). Perhaps someday there will be group values.
462 The current value is the one that is actually in use.
463 ----*/
464 /* name is_changed_val
465 remove_quotes |
466 is_outermost | |
467 is_onlymain | | |
468 is_fixed | | | |
469 is_list | | | | |
470 is_global | | | | | |
471 is_user | | | | | | |
472 been_written | | | | | | | |
473 is_used | | | | | | | | |
474 is_obsolete | | | | | | | | | |
475 | | | | | | | | | | |
476 (on following line) description | | | | | | | | | | |
477 | | | | | | | | | | | |
478 | | | | | | | | | | | | */
479 static struct variable variables[] = {
480 {"personal-name", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
481 NULL, cf_text_personal_name},
483 #if defined(DOS) || defined(OS2)
484 /* Have to have this on DOS, PC's, Macs, etc... */
485 "user-id", 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0,
486 #else /* Don't allow on UNIX machines for some security */
487 "user-id", 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0,
488 #endif
489 "User ID", cf_text_user_id},
490 {"user-domain", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
491 NULL, cf_text_user_domain},
492 {"smtp-server", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
493 "SMTP Server (for sending)", cf_text_smtp_server},
494 {"nntp-server", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
495 "NNTP Server (for news)", cf_text_nntp_server},
496 {"inbox-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
497 NULL, cf_text_inbox_path},
498 {"incoming-archive-folders", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
499 NULL, cf_text_archived_folders},
500 {"pruned-folders", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
501 NULL, cf_text_pruned_folders},
502 {"default-fcc", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
503 "Default Fcc (File carbon copy)", cf_text_default_fcc},
504 {"default-saved-msg-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
505 "Default Saved Message Folder", cf_text_default_saved},
506 {"postponed-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
507 NULL, cf_text_postponed_folder},
508 {"read-message-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
509 NULL, cf_text_read_message_folder},
510 {"form-letter-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
511 NULL, cf_text_form_letter_folder},
512 {"trash-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
513 NULL, cf_text_trash_folder},
514 {"literal-signature", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
515 NULL, cf_text_literal_sig},
516 {"signature-file", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
517 NULL, cf_text_signature_file},
518 {"feature-list", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
519 NULL, cf_text_feature_list},
520 {"initial-keystroke-list", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
521 NULL, cf_text_initial_keystroke_list},
522 {"default-composer-hdrs", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
523 "Default Composer Headers", cf_text_default_composer_hdrs},
524 {"customized-hdrs", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
525 "Customized Headers", cf_text_customized_hdrs},
526 {"viewer-hdrs", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
527 "Viewer Headers", cf_text_view_headers},
528 {"viewer-margin-left", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
529 NULL, cf_text_view_margin_left},
530 {"viewer-margin-right", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
531 NULL, cf_text_view_margin_right},
532 {"quote-suppression-threshold", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
533 NULL, cf_text_quote_suppression},
534 {"saved-msg-name-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
535 "Saved Message Name Rule", cf_text_save_msg_name_rule},
536 {"fcc-name-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
537 NULL, cf_text_fcc_name_rule},
538 {"sort-key", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
539 NULL, cf_text_sort_key},
540 {"addrbook-sort-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
541 "Address Book Sort Rule", cf_text_addrbook_sort_rule},
542 {"folder-sort-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
543 NULL, cf_text_folder_sort_rule},
544 {"goto-default-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
545 NULL, cf_text_goto_default},
546 {"incoming-startup-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
547 NULL, cf_text_inc_startup},
548 {"pruning-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
549 NULL, cf_pruning_rule},
550 {"folder-reopen-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
551 NULL, cf_reopen_rule},
552 {"threading-display-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
553 NULL, cf_text_thread_disp_style},
554 {"threading-index-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
555 NULL, cf_text_thread_index_style},
556 {"threading-indicator-character", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
557 NULL, cf_text_thread_more_char},
558 {"threading-expanded-character", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
559 NULL, cf_text_thread_exp_char},
560 {"threading-lastreply-character", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
561 "Threading Last Reply Character", cf_text_thread_lastreply_char},
562 #ifndef _WINDOWS
563 {"display-character-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
564 NULL, cf_text_disp_char_set},
565 {"character-set", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
566 NULL, cf_text_old_char_set},
567 {"keyboard-character-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
568 NULL, cf_text_key_char_set},
569 #endif /* ! _WINDOWS */
570 {"posting-character-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
571 NULL, cf_text_post_character_set},
572 {"unknown-character-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
573 NULL, cf_text_unk_character_set},
574 {"editor", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
575 NULL, cf_text_editor},
576 {"speller", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
577 NULL, cf_text_speller},
578 #ifdef _WINDOWS
579 {"aspell-dictionary-list", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
580 "Aspell Dictionaries", cf_text_speller_dictionary},
581 #endif /* _WINDOWS */
582 {"composer-wrap-column", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
583 NULL, cf_text_fillcol},
584 {"reply-indent-string", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
585 NULL, cf_text_replystr},
586 {"reply-leadin", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
587 NULL, cf_text_replyintro},
588 {"quote-replace-string", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
589 NULL, cf_text_quotereplstr},
590 {"composer-word-separators", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
591 NULL, cf_text_wordsep},
592 {"empty-header-message", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
593 NULL, cf_text_emptyhdr},
594 {"image-viewer", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
595 NULL, cf_text_image_viewer},
596 {"use-only-domain-name", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
597 NULL, cf_text_use_only_domain_name},
598 {"bugs-fullname", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
599 NULL, cf_text_bugs_fullname},
600 {"bugs-address", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
601 NULL, cf_text_bugs_address},
602 {"bugs-additional-data", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
603 NULL, cf_text_bugs_extras},
604 {"suggest-fullname", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
605 NULL, cf_text_suggest_fullname},
606 {"suggest-address", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
607 NULL, cf_text_suggest_address},
608 {"local-fullname", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
609 NULL, cf_text_local_fullname},
610 {"local-address", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
611 NULL, cf_text_local_address},
612 {"forced-abook-entry", 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0,
613 NULL, cf_text_forced_abook},
614 {"kblock-passwd-count", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
615 NULL, cf_text_kblock_passwd},
616 {"display-filters", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
617 NULL, cf_text_in_fltr},
618 {"sending-filters", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
619 NULL, cf_text_out_fltr},
620 {"alt-addresses", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
621 "Alternate Addresses", cf_text_alt_addrs},
622 {"keywords", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
623 NULL, cf_text_keywords},
624 {"keyword-surrounding-chars", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
625 "Keyword Surrounding Characters", cf_text_kw_braces},
626 {"opening-text-separator-chars", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
627 "Opening Text Separator Characters", cf_text_opening_sep},
628 {"addressbook-formats", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
629 "Address Book Formats", cf_text_abook_formats},
630 {"index-format", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
631 NULL, cf_text_index_format},
632 {"viewer-overlap", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
633 NULL, cf_text_overlap},
634 {"scroll-margin", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
635 NULL, cf_text_margin},
636 {"status-message-delay", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
637 NULL, cf_text_stat_msg_delay},
638 {"busy-cue-rate", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
639 NULL, cf_text_busy_cue_rate},
640 {"mail-check-interval", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
641 NULL, cf_text_mailcheck},
642 {"mail-check-interval-noncurrent", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
643 NULL, cf_text_mailchecknoncurr},
644 {"maildrop-check-minimum", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
645 NULL, cf_text_maildropcheck},
646 {"nntp-range", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
647 "NNTP Range", cf_text_nntprange},
648 {"newsrc-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
649 NULL, cf_text_newsrc_path},
650 {"news-active-file-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
651 NULL, cf_text_news_active},
652 {"news-spool-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
653 NULL, cf_text_news_spooldir},
654 {"upload-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
655 NULL, cf_text_upload_cmd},
656 {"upload-command-prefix", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
657 NULL, cf_text_upload_prefix},
658 {"download-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
659 NULL, cf_text_download_cmd},
660 {"download-command-prefix", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
661 NULL, cf_text_download_prefix},
662 {"mailcap-search-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
663 NULL, cf_text_mailcap_path},
664 {"mimetype-search-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
665 NULL, cf_text_mimetype_path},
666 #if !defined(_WINDOWS) || defined(WINDOWS_LIBRESSL_CERTS)
667 {"system-certs-path", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
668 "System CACerts Dir", cf_text_system_certs_path},
669 {"system-certs-file", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
670 "System CACerts File", cf_text_system_certs_file},
671 #endif
672 {"url-viewers", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
673 "URL-Viewers", cf_text_browser},
674 {"default-directories", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
675 "Extra Directories for Save", cf_text_history},
676 {"max-remote-connections", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
677 "Maximum Remote Connections", cf_text_maxremstreams},
678 {"stay-open-folders", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
679 "Stayopen Folders", cf_text_permlocked},
680 {"incoming-check-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
681 NULL, cf_text_inc_check_timeo},
682 {"incoming-check-interval", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
683 NULL, cf_text_inc_check_interval},
684 {"incoming-check-interval-secondary", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
685 NULL, cf_text_inc_second_check_interval},
686 {"incoming-check-list", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
687 NULL, cf_text_inc_check_list},
688 {"dead-letter-files", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
689 NULL, cf_text_deadlets},
690 #if !defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)
691 {"newmail-fifo-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
692 "NewMail FIFO Path", cf_text_newmail_fifo_path},
693 #endif
694 {"newmail-window-width", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
695 "NewMail Window Width", cf_text_nmw_width},
697 * Starting here, the variables are hidden in the Setup/Config screen.
698 * They are exposed if feature expose-hidden-config is set.
700 {"incoming-folders", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
701 NULL, cf_text_incoming_folders},
702 {"mail-directory", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
703 NULL, cf_text_mail_directory},
704 {"folder-collections", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
705 NULL, cf_text_folder_collections},
706 {"news-collections", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
707 NULL, cf_text_news_collections},
708 {"address-book", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
709 NULL, cf_text_address_book},
710 {"global-address-book", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
711 NULL, cf_text_global_address_book},
712 {"standard-printer", 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0,
713 NULL, cf_text_standard_printer},
714 {"last-time-prune-questioned", 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0,
715 NULL, cf_text_last_time_prune_quest},
716 {"last-version-used", 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0,
717 NULL, cf_text_last_version_used},
718 {"sendmail-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
719 NULL, cf_text_sendmail_path},
720 {"operating-dir", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
721 NULL, cf_text_oper_dir},
722 {"user-input-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
723 NULL, cf_text_user_input_timeo},
724 /* OBSOLETE */
725 #ifdef DEBUGJOURNAL
726 {"debug-memory", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
727 NULL, cf_text_debug_mem},
728 #endif
729 {"tcp-open-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
730 "TCP Open Timeout", cf_text_tcp_open_timeo},
731 {"tcp-read-warning-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
732 "TCP Read Warning Timeout", cf_text_tcp_read_timeo},
733 {"tcp-write-warning-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
734 "TCP Write Warning Timeout", cf_text_tcp_write_timeo},
735 {"tcp-query-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
736 "TCP Query Timeout", cf_text_tcp_query_timeo},
737 {"close-connection-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
738 NULL, cf_text_close_connection_timeo},
739 {"rsh-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
740 NULL, cf_text_rsh_command},
741 {"rsh-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
742 NULL, cf_text_rsh_path},
743 {"rsh-open-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
744 NULL, cf_text_rsh_open_timeo},
745 {"ssh-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
746 NULL, cf_text_ssh_command},
747 {"ssh-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
748 NULL, cf_text_ssh_path},
749 {"ssh-open-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
750 NULL, cf_text_ssh_open_timeo},
751 {"new-version-threshold", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
752 NULL, cf_text_version_threshold},
753 {"disable-these-drivers", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
754 NULL, cf_text_disable_drivers},
755 {"disable-these-authenticators", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
756 NULL, cf_text_disable_auths},
757 #ifdef DF_ENCRYPTION_RANGE
758 {"encryption-protocol-range", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
759 NULL, cf_text_encryption_range},
760 #endif
761 {"remote-abook-metafile", 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0,
762 NULL, cf_text_remote_abook_metafile},
763 {"remote-abook-history", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
764 NULL, cf_text_remote_abook_history},
765 {"remote-abook-validity", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
766 NULL, cf_text_remote_abook_validity},
767 {"printer", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
768 NULL, cf_text_printer},
769 {"personal-print-command", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
770 NULL, cf_text_personal_print_command},
771 {"personal-print-category", 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0,
772 NULL, cf_text_personal_print_cat},
773 {"xoauth2-info", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
774 "XOAUTH2 Info", cf_text_xoauth2_info},
775 {"patterns", 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
776 NULL, cf_text_old_patterns},
777 {"patterns-roles", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
778 NULL, cf_text_patterns},
779 {"patterns-filters2", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
780 "Patterns Filters", cf_text_patterns},
781 {"patterns-filters", 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
782 NULL, cf_text_old_filters},
783 {"patterns-scores2", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
784 "Patterns Scores", cf_text_patterns},
785 {"patterns-scores", 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
786 NULL, cf_text_old_scores},
787 {"patterns-indexcolors", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
788 NULL, cf_text_patterns},
789 {"patterns-other", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
790 NULL, cf_text_patterns},
791 {"patterns-search", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
792 NULL, cf_text_patterns},
793 /* OBSOLETE VARS */
794 {"elm-style-save", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
795 NULL, cf_text_elm_style_save},
796 {"header-in-reply", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
797 NULL, cf_text_header_in_reply},
798 {"feature-level", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
799 NULL, cf_text_feature_level},
800 {"old-style-reply", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
801 NULL, cf_text_old_style_reply},
802 {"compose-mime", 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
803 NULL, cf_text_compose_mime},
804 {"show-all-characters", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
805 NULL, cf_text_show_all_characters},
806 {"save-by-sender", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
807 NULL, cf_text_save_by_sender},
808 #if defined(DOS) || defined(OS2)
809 {"file-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
810 NULL, cf_text_file_dir},
811 {"folder-extension", 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0,
812 NULL, cf_text_folder_extension},
813 #endif
814 #ifndef _WINDOWS
815 {"color-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
816 NULL, cf_text_color_style},
817 #endif
818 {"current-indexline-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
819 NULL, cf_text_current_indexline_style},
820 {"titlebar-color-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
821 NULL, cf_text_titlebar_color_style},
822 {"normal-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
823 NULL, cf_text_normal_foreground_color},
824 {"normal-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
825 {"reverse-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
826 {"reverse-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
827 {"title-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
828 {"title-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
829 {"title-closed-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
830 {"title-closed-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
831 {"folder-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
832 {"folder-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
833 {"directory-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
834 {"directory-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
835 {"folder-list-text-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
836 {"folder-list-text-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
837 {"status-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
838 {"status-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
839 {"keylabel-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
840 {"keylabel-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
841 {"keyname-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
842 {"keyname-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
843 {"selectable-item-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
844 {"selectable-item-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
845 {"meta-message-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
846 {"meta-message-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
847 {"quote1-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
848 {"quote1-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
849 {"quote2-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
850 {"quote2-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
851 {"quote3-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
852 {"quote3-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
853 {"incoming-unseen-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
854 {"incoming-unseen-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
855 {"signature-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
856 {"signature-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
857 {"prompt-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
858 {"prompt-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
859 {"header-general-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
860 {"header-general-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
861 {"index-to-me-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
862 {"index-to-me-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
863 {"index-important-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
864 {"index-important-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
865 {"index-deleted-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
866 {"index-deleted-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
867 {"index-answered-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
868 {"index-answered-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
869 {"index-new-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
870 {"index-new-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
871 {"index-recent-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
872 {"index-recent-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
873 {"index-forward-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
874 {"index-forward-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
875 {"index-unseen-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
876 {"index-unseen-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
877 {"index-highpriority-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
878 {"index-highpriority-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
879 {"index-lowpriority-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
880 {"index-lowpriority-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
881 {"index-arrow-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
882 {"index-arrow-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
883 {"index-subject-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
884 {"index-subject-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
885 {"index-from-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
886 {"index-from-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
887 {"index-opening-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
888 {"index-opening-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
889 {"index-token-colors", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
890 NULL, cf_text_index_token_color},
891 {"viewer-hdr-colors", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
892 "Viewer Header Colors", cf_text_view_hdr_color},
893 {"keyword-colors", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
894 NULL, cf_text_kw_colors},
895 #ifdef _WINDOWS
896 {"font-name", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
897 NULL, "name and size of font."},
898 {"font-size", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
899 {"font-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
900 {"font-char-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
901 {"print-font-name", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
902 NULL, "name and size of printer font."},
903 {"print-font-size", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
904 {"print-font-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
905 {"print-font-char-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
906 {"window-position", 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0,
907 NULL, cf_text_window_position},
908 {"cursor-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
909 #endif /* _WINDOWS */
910 #ifdef SMIME
911 {"smime-public-cert-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
912 "S/MIME - Public Cert Directory", cf_text_publiccertdir},
913 {"smime-public-cert-container", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
914 "S/MIME - Public Cert Container", cf_text_publiccertcontainer},
915 {"smime-private-key-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
916 "S/MIME - Private Key Directory", cf_text_privatekeydir},
917 {"smime-private-key-container", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
918 "S/MIME - Private Key Container", cf_text_privatekeycontainer},
919 {"smime-cacert-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
920 "S/MIME - Cert Authority Directory", cf_text_cacertdir},
921 {"smime-cacert-container", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
922 "S/MIME - Cert Authority Container", cf_text_cacertcontainer},
923 #endif /* SMIME */
924 #ifdef ENABLE_LDAP
925 {"ldap-servers", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
926 "LDAP Servers", cf_text_ldap_server},
927 #endif /* ENABLE_LDAP */
928 {"rss-news", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
929 "WEB ALPINE - RSS News", cf_text_rss_news},
930 {"rss-weather", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
931 "WEB ALPINE - RSS Weather", cf_text_rss_weather},
932 {"wp-indexheight", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
933 "WEB ALPINE - Index Height", cf_text_wp_indexheight},
934 {"wp-indexlines", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
935 "WEB ALPINE - Index Lines", cf_text_wp_indexlines},
936 {"wp-aggstate", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
937 "WEB ALPINE - Aggregate State", cf_text_wp_aggstate},
938 {"wp-state", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
939 "WEB ALPINE - Cross Session State", cf_text_wp_state},
940 {"wp-columns", 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0,
941 "WEB ALPINE - Columns", cf_text_wp_columns},
942 {NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL,NULL}
946 struct variable *
947 var_from_name(char *name)
949 struct variable *v;
950 int i;
952 if(!(name && name[0]))
953 return(NULL);
955 for(i = 0; (v = &variables[i]) && v->name; i++)
956 if(!strucmp(v->name,name))
957 return(v);
959 return(NULL);
963 void
964 init_init_vars(struct pine *ps)
966 ps->vars = variables;
970 #define DSIZE (25000)
971 /* this is just like dprint except it prints to a char * */
972 #ifdef DEBUG
973 #define mprint(n,x) { \
974 if(debug >= (n)){ \
975 snprintf x ; \
976 db += strlen(db); \
979 #else
980 #define mprint(n,x)
981 #endif
984 * this was split out from init_vars so we can get at the
985 * pinerc location sooner.
987 void
988 init_pinerc(struct pine *ps, char **debug_out)
990 char buf[MAXPATH+1], *p, *db;
991 #if defined(DOS) || defined(OS2)
992 char buf2[MAXPATH+1], l_pinerc[MAXPATH+1];
993 int nopinerc = 0, confregset = -1;
994 register struct variable *vars = ps->vars;
995 #endif
997 #ifdef DEBUG
999 * Since this routine is called before we've had a chance to set up
1000 * the debug file for output, we put the debugging into memory and
1001 * pass it back to the caller for use after init_debug(). We just
1002 * allocate plenty of space.
1004 if(debug_out){
1005 db = *debug_out = (char *)fs_get(DSIZE * sizeof(char));
1006 db[0] = '\0';
1008 #endif
1010 mprint(2, (db, DSIZE-(db-(*debug_out)), "\n -- init_pinerc --\n\n"));
1012 #if defined(DOS) || defined(OS2)
1014 * Rules for the config/support file locations under DOS are:
1016 * 1) The location of the PINERC is searched for in the following
1017 * order of precedence:
1018 * - File pointed to by '-p' command line option
1019 * - File pointed to by PINERC environment variable
1020 * - $HOME\pine
1021 * - same dir as argv[0]
1023 * 2) The HOME environment variable, if not set, defaults to
1024 * root of the current working drive (see alpine.c)
1026 * 3) The default for external files (PINE.SIG and ADDRBOOK) is the
1027 * same directory as the pinerc
1029 * 4) The support files (PINE.HLP and PINE.NDX) are expected to be in
1030 * the same directory as PINE.EXE.
1033 if(ps->prc){
1034 mprint(2, (db, DSIZE-(db-(*debug_out)),
1035 "Personal config \"%.100s\" comes from command line\n",
1036 (ps->prc && ps->prc->name) ? ps->prc->name : "<no name>"));
1038 else{
1039 mprint(2, (db, DSIZE-(db-(*debug_out)),
1040 "Personal config not set on cmdline, checking for $PINERC\n"));
1044 * First, if prc hasn't been set by a command-line -p, check to see
1045 * if PINERC is in the environment. If so, treat it just like we
1046 * would have treated it if it were a command-line arg.
1048 if(!ps->prc && (p = getenv("PINERC")) && *p){
1049 char path[MAXPATH], dir[MAXPATH];
1051 if(IS_REMOTE(p) || is_absolute_path(p)){
1052 strncpy(path, p, sizeof(path)-1);
1053 path[sizeof(path)-1] = '\0';
1055 else{
1056 getcwd(dir, sizeof(dir));
1057 build_path(path, dir, p, sizeof(path));
1060 if(!IS_REMOTE(p))
1061 ps->pinerc = cpystr(path);
1063 ps->prc = new_pinerc_s(path);
1065 if(ps->prc){
1066 mprint(2, (db, DSIZE-(db-(*debug_out)),
1067 " yes, personal config \"%.100s\" comes from $PINERC\n",
1068 (ps->prc && ps->prc->name) ? ps->prc->name : "<no name>"));
1073 * Pinerc used to be the name of the pinerc file. Then we added
1074 * the possibility of the pinerc file being remote, and we replaced
1075 * the variable pinerc with the structure prc. Unfortunately, some
1076 * parts of pine rely on the fact that pinerc is the name of the
1077 * pinerc _file_, and use the directory that the pinerc file is located
1078 * in for their own purposes. We want to preserve that so things will
1079 * keep working. So, even if the real pinerc is remote, we need to
1080 * put the name of a pinerc file in the pinerc variable so that the
1081 * directory which contains that file is writable. The file itself
1082 * doesn't have to exist for this purpose, since we are really only
1083 * using the name of the directory containing the file. Twisted.
1084 * (Alternatively, we could fix all of the code that uses the pinerc
1085 * variable for this purpose to use a new variable which really is
1086 * just a directory.) hubert 2000-sep
1088 * There are 3 cases. If pinerc is already set that means that the user
1089 * gave either a -p pinerc or an environment pinerc that is a local file,
1090 * and we are done. If pinerc is not set, then either prc is set or not.
1091 * If prc is set then the -p arg or PINERC value is a remote pinerc.
1092 * In that case we need to find a local directory to use, and put that
1093 * directory in the pinerc variable (with a fake filename tagged on).
1094 * If prc is not set, then user hasn't told us anything so we have to
1095 * try to find the default pinerc file by looking down the path of
1096 * possibilities. When we find it, we'll also use that directory.
1098 if(!ps->pinerc){
1099 *l_pinerc = '\0';
1100 *buf = '\0';
1102 if(ps->prc){ /* remote pinerc case */
1104 * We don't give them an l_pinerc unless they tell us where
1105 * to put it.
1107 if(ps->aux_files_dir)
1108 build_path(l_pinerc, ps->aux_files_dir, SYSTEM_PINERC,
1109 sizeof(l_pinerc));
1110 else{
1112 * Search for a writable directory.
1113 * Mimic what happens in !prc for local case, except we
1114 * don't need to look for the actual file.
1117 /* check if $HOME\PINE is writable */
1118 build_path(buf2, ps->home_dir, DF_PINEDIR, sizeof(buf2));
1119 if(is_writable_dir(buf2) == 0)
1120 build_path(l_pinerc, buf2, SYSTEM_PINERC, sizeof(l_pinerc));
1121 else{ /* $HOME\PINE not a writable dir */
1122 /* use this unless registry redirects us */
1123 build_path(l_pinerc, ps->pine_dir, SYSTEM_PINERC,
1124 sizeof(l_pinerc));
1125 #ifdef _WINDOWS
1126 /* if in registry, use that value */
1127 if(mswin_reg(MSWR_OP_GET, MSWR_PINE_RC, buf2, sizeof(buf2))
1128 && !IS_REMOTE(buf2)){
1129 strncpy(l_pinerc, buf2, sizeof(l_pinerc)-1);
1130 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1132 #endif
1136 else{ /* searching for pinerc file to use */
1138 * Buf2 is $HOME\PINE. If $HOME is not explicitly set,
1139 * it defaults to the current working drive (often C:).
1140 * See alpine.c to see how it is initially set.
1143 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, searching...\n"));
1144 build_path(buf2, ps->home_dir, DF_PINEDIR, sizeof(buf2));
1145 mprint(2, (db, DSIZE-(db-(*debug_out)),
1146 " checking for writable %.100s dir \"%.100s\" off of homedir\n",
1147 DF_PINEDIR, buf2));
1148 if(is_writable_dir(buf2) == 0){
1150 * $HOME\PINE exists and is writable.
1151 * See if $HOME\PINE\PINERC exists.
1153 build_path(buf, buf2, SYSTEM_PINERC, sizeof(buf));
1154 strncpy(l_pinerc, buf, sizeof(l_pinerc)-1);
1155 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1156 mprint(2, (db, DSIZE-(db-(*debug_out)), " yes, now checking for file \"%.100s\"\n",
1157 buf));
1158 if(can_access(buf, ACCESS_EXISTS) == 0){ /* found it! */
1160 * Buf is what we were looking for.
1161 * It is local and can be used for the directory, too.
1163 mprint(2, (db, DSIZE-(db-(*debug_out)), " found it\n"));
1165 else{
1167 * No $HOME\PINE\PINERC, look for
1168 * one in same dir as PINE.EXE.
1170 build_path(buf2, ps->pine_dir, SYSTEM_PINERC,
1171 sizeof(buf2));
1172 mprint(2, (db, DSIZE-(db-(*debug_out)),
1173 " no, checking for \"%.100s\" in pine.exe dir\n",
1174 buf2));
1175 if(can_access(buf2, ACCESS_EXISTS) == 0){
1176 /* found it! */
1177 mprint(2, (db, DSIZE-(db-(*debug_out)), " found it\n"));
1178 strncpy(buf, buf2, sizeof(buf)-1);
1179 buf[sizeof(buf)-1] = '\0';
1180 strncpy(l_pinerc, buf2, sizeof(l_pinerc)-1);
1181 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1183 else{
1184 #ifdef _WINDOWS
1185 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, checking in registry\n"));
1186 if(mswin_reg(MSWR_OP_GET, MSWR_PINE_RC,
1187 buf2, sizeof(buf2))){
1188 strncpy(buf, buf2, sizeof(buf)-1);
1189 buf[sizeof(buf)-1] = '\0';
1190 if(!IS_REMOTE(buf2)){
1191 strncpy(l_pinerc, buf2, sizeof(l_pinerc)-1);
1192 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1195 * Now buf is the pinerc to be used, l_pinerc is
1196 * the directory, which may be either same as buf
1197 * or it may be $HOME\PINE if registry gives us
1198 * a remote pinerc.
1200 mprint(2, (db, DSIZE-(db-(*debug_out)), " found \"%.100s\" in registry\n",
1201 buf));
1203 else{
1204 nopinerc = 1;
1205 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found, asking user\n"));
1207 #else
1208 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found\n"));
1209 #endif
1214 * Buf is the pinerc (could be remote if from registry)
1215 * and l_pinerc is the local pinerc, which may not exist.
1218 else{ /* $HOME\PINE not a writable dir */
1220 * We notice that the order of checking in the registry
1221 * and checking in the ALPINE.EXE directory are different
1222 * in this case versus the is_writable_dir(buf2) case, and
1223 * that does sort of look like a bug. However,
1224 * we don't think this is a bug since we did it on purpose
1225 * a long time ago. So even though we can't remember why
1226 * it is this way, we think we would rediscover why if we
1227 * changed it! So we won't change it.
1231 * Change the default to use to the ALPINE.EXE directory.
1233 build_path(buf, ps->pine_dir, SYSTEM_PINERC, sizeof(buf));
1234 strncpy(l_pinerc, buf, sizeof(l_pinerc)-1);
1235 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1236 #ifdef _WINDOWS
1237 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, not writable, checking in registry\n"));
1238 /* if in registry, use that value */
1239 if(mswin_reg(MSWR_OP_GET, MSWR_PINE_RC, buf2, sizeof(buf2))){
1240 strncpy(buf, buf2, sizeof(buf)-1);
1241 buf[sizeof(buf)-1] = '\0';
1242 mprint(2, (db, DSIZE-(db-(*debug_out)), " found \"%.100s\" in registry\n",
1243 buf));
1244 if(!IS_REMOTE(buf)){
1245 strncpy(l_pinerc, buf, sizeof(l_pinerc)-1);
1246 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1249 else{
1250 mprint(2, (db, DSIZE-(db-(*debug_out)),
1251 " no, checking for \"%.100s\" in alpine.exe dir\n",
1252 buf));
1254 if(can_access(buf, ACCESS_EXISTS) == 0){
1255 mprint(2, (db, DSIZE-(db-(*debug_out)), " found it\n"));
1257 else{
1258 nopinerc = 1;
1259 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found, asking user\n"));
1262 #else
1263 mprint(2, (db, DSIZE-(db-(*debug_out)),
1264 " no, checking for \"%.100s\" in alpine.exe dir\n",
1265 buf));
1267 if(can_access(buf, ACCESS_EXISTS) == 0){
1268 mprint(2, (db, DSIZE-(db-(*debug_out)), " found it\n"));
1270 else{
1271 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found, creating it\n"));
1273 #endif
1277 * When we get here we have buf set to the name of the
1278 * pinerc, which could be local or remote. We have l_pinerc
1279 * set to the same as buf if buf is local, and set to another
1280 * name otherwise, hopefully contained in a writable directory.
1282 #ifdef _WINDOWS
1283 if(nopinerc || ps_global->install_flag){
1284 char buf3[MAXPATH+1];
1286 confregset = 0;
1287 strncpy(buf3, buf, MAXPATH);
1288 buf3[MAXPATH] = '\0';
1289 if(os_config_dialog(buf3, MAXPATH,
1290 &confregset, nopinerc) == 0){
1291 strncpy(buf, buf3, MAXPATH);
1292 buf[MAXPATH] = '\0';
1293 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found, creating it\n"));
1294 mprint(2, (db, DSIZE-(db-(*debug_out)), " user says use \"%.100s\"\n", buf));
1295 if(!IS_REMOTE(buf)){
1296 strncpy(l_pinerc, buf, MAXPATH);
1297 l_pinerc[MAXPATH] = '\0';
1300 else{
1301 exit(-1);
1304 #endif
1305 ps->prc = new_pinerc_s(buf);
1308 ps->pinerc = cpystr(l_pinerc);
1311 #if defined(DOS) || defined(OS2)
1313 * The goal here is to set the auxiliary directory in the pinerc variable.
1314 * We are making the assumption that any reference to the pinerc variable
1315 * after this point is used only as a directory in which to store things,
1316 * with the prc variable being the preferred place to store pinerc location.
1317 * If -aux isn't set, then there is no change. -jpf 08/2001
1319 if(ps->aux_files_dir){
1320 l_pinerc[0] = '\0';
1321 build_path(l_pinerc, ps->aux_files_dir, SYSTEM_PINERC,
1322 sizeof(l_pinerc));
1323 if(ps->pinerc) fs_give((void **)&ps->pinerc);
1324 ps->pinerc = cpystr(l_pinerc);
1325 mprint(2, (db, DSIZE-(db-(*debug_out)), "Setting aux_files_dir to \"%.100s\"\n",
1326 ps->aux_files_dir));
1328 #endif
1330 #ifdef _WINDOWS
1331 if(confregset && (ps->update_registry != UREG_NEVER_SET))
1332 mswin_reg(MSWR_OP_SET | ((ps->update_registry == UREG_ALWAYS_SET)
1333 || confregset == 1 ? MSWR_OP_FORCE : 0),
1334 MSWR_PINE_RC,
1335 (ps->prc && ps->prc->name) ?
1336 ps->prc->name : ps->pinerc, (size_t)NULL);
1337 #endif
1340 * Now that we know the default for the PINERC, build NEWSRC default.
1341 * Backward compatibility makes this kind of funky. If what the
1342 * c-client thinks the NEWSRC should be exists *AND* it doesn't
1343 * already exist in the PINERC's dir, use c-client's default, otherwise
1344 * use the one next to the PINERC...
1346 p = last_cmpnt(ps->pinerc);
1347 buf[0] = '\0';
1348 if(p != NULL){
1349 strncpy(buf, ps->pinerc, MIN(p - ps->pinerc, sizeof(buf)-1));
1350 buf[MIN(p - ps->pinerc, sizeof(buf)-1)] = '\0';
1353 mprint(2, (db, DSIZE-(db-(*debug_out)), "Using directory \"%.100s\" for auxiliary files\n", buf));
1354 strncat(buf, "NEWSRC", sizeof(buf)-1-strlen(buf));
1356 if(!(p = (void *) mail_parameters(NULL, GET_NEWSRC, (void *)NULL))
1357 || can_access(p, ACCESS_EXISTS) < 0
1358 || can_access(buf, ACCESS_EXISTS) == 0){
1359 mail_parameters(NULL, SET_NEWSRC, (void *)buf);
1360 GLO_NEWSRC_PATH = cpystr(buf);
1362 else
1363 GLO_NEWSRC_PATH = cpystr(p);
1365 if(ps->pconf){
1366 mprint(2, (db, DSIZE-(db-(*debug_out)), "Global config \"%.100s\" comes from command line\n",
1367 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1369 else{
1370 mprint(2, (db, DSIZE-(db-(*debug_out)),
1371 "Global config not set on cmdline, checking for $PINECONF\n"));
1374 if(!ps->pconf && (p = getenv("PINECONF"))){
1375 ps->pconf = new_pinerc_s(p);
1376 if(ps->pconf){
1377 mprint(2, (db, DSIZE-(db-(*debug_out)),
1378 " yes, global config \"%.100s\" comes from $PINECONF\n",
1379 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1382 #ifdef _WINDOWS
1383 else if(!ps->pconf
1384 && mswin_reg(MSWR_OP_GET, MSWR_PINE_CONF, buf2, sizeof(buf2))){
1385 ps->pconf = new_pinerc_s(buf2);
1386 if(ps->pconf){
1387 mprint(2, (db, DSIZE-(db-(*debug_out)),
1388 " yes, global config \"%.100s\" comes from Registry\n",
1389 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1392 #endif
1393 if(!ps->pconf){
1394 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, there is no global config\n"));
1396 #ifdef _WINDOWS
1397 else if (ps->pconf && ps->pconf->name &&
1398 (ps->update_registry != UREG_NEVER_SET)){
1399 mswin_reg(MSWR_OP_SET | ((ps->update_registry == UREG_ALWAYS_SET)
1400 ? MSWR_OP_FORCE : 0),
1401 MSWR_PINE_CONF,
1402 ps->pconf->name, (size_t)NULL);
1404 #endif
1406 if(!ps->prc)
1407 ps->prc = new_pinerc_s(ps->pinerc);
1409 if(ps->exceptions){
1410 mprint(2, (db, DSIZE-(db-(*debug_out)),
1411 "Exceptions config \"%.100s\" comes from command line\n",
1412 ps->exceptions));
1414 else{
1415 mprint(2, (db, DSIZE-(db-(*debug_out)),
1416 "Exceptions config not set on cmdline, checking for $PINERCEX\n"));
1420 * Exceptions is done slightly differently from pinerc. Instead of setting
1421 * post_prc in args.c we just set the string and use it here. We do
1422 * that so that we can put it in the same directory as the pinerc if
1423 * exceptions is a relative name, and pinerc may not be set until here.
1425 * First, just like for pinerc, check environment variable if it wasn't
1426 * set on the command line.
1428 if(!ps->exceptions && (p = getenv("PINERCEX")) && *p){
1429 ps->exceptions = cpystr(p);
1430 if(ps->exceptions){
1431 mprint(2, (db, DSIZE-(db-(*debug_out)),
1432 " yes, exceptions config \"%.100s\" comes from $PINERCEX\n",
1433 ps->exceptions));
1438 * If still not set, try specific file in same dir as pinerc.
1439 * Only use it if the file exists.
1441 if(!ps->exceptions){
1442 p = last_cmpnt(ps->pinerc);
1443 buf[0] = '\0';
1444 if(p != NULL){
1445 strncpy(buf, ps->pinerc, MIN(p - ps->pinerc, sizeof(buf)-1));
1446 buf[MIN(p - ps->pinerc, sizeof(buf)-1)] = '\0';
1449 strncat(buf, "PINERCEX", sizeof(buf)-1-strlen(buf));
1451 mprint(2, (db, DSIZE-(db-(*debug_out)),
1452 " no, checking for default \"%.100s\" in pinerc dir\n", buf));
1453 if(can_access(buf, ACCESS_EXISTS) == 0) /* found it! */
1454 ps->exceptions = cpystr(buf);
1456 if(ps->exceptions){
1457 mprint(2, (db, DSIZE-(db-(*debug_out)),
1458 " yes, exceptions config \"%.100s\" comes from default\n",
1459 ps->exceptions));
1461 else{
1462 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, there is no exceptions config\n"));
1466 #else /* unix */
1468 if(ps->pconf){
1469 mprint(2, (db, DSIZE-(db-(*debug_out)), "Global config \"%.100s\" comes from command line\n",
1470 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1473 if(!ps->pconf){
1474 ps->pconf = new_pinerc_s(SYSTEM_PINERC);
1475 if(ps->pconf){
1476 mprint(2, (db, DSIZE-(db-(*debug_out)), "Global config \"%.100s\" is default\n",
1477 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1481 if(!ps->pconf){
1482 mprint(2, (db, DSIZE-(db-(*debug_out)), "No global config!\n"));
1485 if(ps->prc){
1486 mprint(2, (db, DSIZE-(db-(*debug_out)), "Personal config \"%.100s\" comes from command line\n",
1487 (ps->prc && ps->prc->name) ? ps->prc->name : "<no name>"));
1490 if(!ps->pinerc){
1491 build_path(buf, ps->home_dir, ".pinerc", sizeof(buf));
1492 ps->pinerc = cpystr(buf);
1495 if(!ps->prc){
1496 ps->prc = new_pinerc_s(ps->pinerc);
1497 if(ps->prc){
1498 mprint(2, (db, DSIZE-(db-(*debug_out)), "Personal config \"%.100s\" is default\n",
1499 (ps->prc && ps->prc->name) ? ps->prc->name : "<no name>"));
1503 if(!ps->prc){
1504 mprint(2, (db, DSIZE-(db-(*debug_out)), "No personal config!\n"));
1507 if(ps->exceptions){
1508 mprint(2, (db, DSIZE-(db-(*debug_out)),
1509 "Exceptions config \"%.100s\" comes from command line\n",
1510 ps->exceptions));
1514 * If not set, try specific file in same dir as pinerc.
1515 * Only use it if the file exists.
1517 if(!ps->exceptions){
1518 p = last_cmpnt(ps->pinerc);
1519 buf[0] = '\0';
1520 if(p != NULL){
1521 strncpy(buf, ps->pinerc, MIN(p - ps->pinerc, sizeof(buf)-1));
1522 buf[MIN(p - ps->pinerc, sizeof(buf)-1)] = '\0';
1525 strncat(buf, ".pinercex", sizeof(buf)-1-strlen(buf));
1526 mprint(2, (db, DSIZE-(db-(*debug_out)), "Exceptions config not set on cmdline\n checking for default \"%.100s\" in pinerc dir\n", buf));
1528 if(can_access(buf, ACCESS_EXISTS) == 0) /* found it! */
1529 ps->exceptions = cpystr(buf);
1531 if(ps->exceptions){
1532 mprint(2, (db, DSIZE-(db-(*debug_out)),
1533 " yes, exceptions config \"%.100s\" is default\n",
1534 ps->exceptions));
1536 else{
1537 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, there is no exceptions config\n"));
1541 #endif /* unix */
1543 if(ps->exceptions){
1545 if(!IS_REMOTE(ps->exceptions) &&
1546 !is_absolute_path(ps->exceptions)){
1547 #if defined(DOS) || defined(OS2)
1548 p = last_cmpnt(ps->pinerc);
1549 buf[0] = '\0';
1550 if(p != NULL){
1551 strncpy(buf, ps->pinerc, MIN(p - ps->pinerc, sizeof(buf)-1));
1552 buf[MIN(p - ps->pinerc, sizeof(buf)-1)] = '\0';
1555 strncat(buf, ps->exceptions, sizeof(buf)-1-strlen(buf));
1556 #else
1557 build_path(buf, ps->home_dir, ps->exceptions, sizeof(buf));
1558 #endif
1560 else{
1561 strncpy(buf, ps->exceptions, sizeof(buf)-1);
1562 buf[sizeof(buf)-1] = '\0';
1565 ps->post_prc = new_pinerc_s(buf);
1567 fs_give((void **)&ps->exceptions);
1570 mprint(2, (db, DSIZE-(db-(*debug_out)), "\n Global config: %.100s\n",
1571 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<none>"));
1572 mprint(2, (db, DSIZE-(db-(*debug_out)), " Personal config: %.100s\n",
1573 (ps->prc && ps->prc->name) ? ps->prc->name : "<none>"));
1574 mprint(2, (db, DSIZE-(db-(*debug_out)), " Exceptions config: %.100s\n",
1575 (ps->post_prc && ps->post_prc->name) ? ps->post_prc->name
1576 : "<none>"));
1577 #if !defined(DOS) && !defined(OS2)
1578 if(SYSTEM_PINERC_FIXED){
1579 mprint(2, (db, DSIZE-(db-(*debug_out)), " Fixed config: %.100s\n", SYSTEM_PINERC_FIXED));
1581 #endif
1583 mprint(2, (db, DSIZE-(db-(*debug_out)), "\n"));
1587 /*----------------------------------------------------------------------
1588 Initialize the variables
1590 Args: ps -- The usual pine structure
1592 Result:
1594 This reads the system pine configuration file and the user's pine
1595 configuration file ".pinerc" and places the results in the variables
1596 structure. It sorts out what was read and sets a few other variables
1597 based on the contents.
1598 ----*/
1599 void
1600 init_vars(struct pine *ps, void (*cmds_f) (struct pine *, char **))
1602 char buf[MAXPATH+1], *p, *q, **s, *comma_index;
1603 register struct variable *vars = ps->vars;
1604 int obs_header_in_reply = 0, /* the obs_ variables are to */
1605 obs_old_style_reply = 0, /* support backwards compatibility */
1606 obs_save_by_sender, i, def_sort_rev;
1607 long rvl;
1608 PINERC_S *fixedprc = NULL;
1609 FeatureLevel obs_feature_level;
1610 char *fromcharset = NULL;
1611 char *err = NULL;
1613 dprint((5, "init_vars:\n"));
1615 /*--- The defaults here are defined in os-xxx.h so they can vary
1616 per machine ---*/
1618 GLO_PRINTER = cpystr(DF_DEFAULT_PRINTER);
1619 GLO_ELM_STYLE_SAVE = cpystr(DF_ELM_STYLE_SAVE);
1620 #ifdef DF_ENCRYPTION_RANGE
1621 GLO_ENCRYPTION_RANGE = cpystr(DF_ENCRYPTION_RANGE);
1622 #endif
1623 GLO_SAVE_BY_SENDER = cpystr(DF_SAVE_BY_SENDER);
1624 GLO_HEADER_IN_REPLY = cpystr(DF_HEADER_IN_REPLY);
1625 GLO_INBOX_PATH = cpystr("inbox");
1626 GLO_DEFAULT_FCC = cpystr(DF_DEFAULT_FCC);
1627 GLO_DEFAULT_SAVE_FOLDER = cpystr(DEFAULT_SAVE);
1628 GLO_POSTPONED_FOLDER = cpystr(POSTPONED_MSGS);
1629 GLO_TRASH_FOLDER = cpystr(TRASH_FOLDER);
1630 GLO_USE_ONLY_DOMAIN_NAME = cpystr(DF_USE_ONLY_DOMAIN_NAME);
1631 GLO_FEATURE_LEVEL = cpystr("sappling");
1632 GLO_OLD_STYLE_REPLY = cpystr(DF_OLD_STYLE_REPLY);
1633 GLO_SORT_KEY = cpystr(DF_SORT_KEY);
1634 GLO_SAVED_MSG_NAME_RULE = cpystr(DF_SAVED_MSG_NAME_RULE);
1635 GLO_FCC_RULE = cpystr(DF_FCC_RULE);
1636 GLO_AB_SORT_RULE = cpystr(DF_AB_SORT_RULE);
1637 GLO_FLD_SORT_RULE = cpystr(DF_FLD_SORT_RULE);
1638 GLO_SIGNATURE_FILE = cpystr(DF_SIGNATURE_FILE);
1639 GLO_MAIL_DIRECTORY = cpystr(DF_MAIL_DIRECTORY);
1640 GLO_REMOTE_ABOOK_HISTORY = cpystr(DF_REMOTE_ABOOK_HISTORY);
1641 GLO_REMOTE_ABOOK_VALIDITY = cpystr(DF_REMOTE_ABOOK_VALIDITY);
1642 GLO_GOTO_DEFAULT_RULE = cpystr(DF_GOTO_DEFAULT_RULE);
1643 GLO_INCOMING_STARTUP = cpystr(DF_INCOMING_STARTUP);
1644 GLO_PRUNING_RULE = cpystr(DF_PRUNING_RULE);
1645 GLO_REOPEN_RULE = cpystr(DF_REOPEN_RULE);
1646 GLO_THREAD_DISP_STYLE = cpystr(DF_THREAD_DISP_STYLE);
1647 GLO_THREAD_INDEX_STYLE = cpystr(DF_THREAD_INDEX_STYLE);
1648 GLO_THREAD_MORE_CHAR = cpystr(DF_THREAD_MORE_CHAR);
1649 GLO_THREAD_EXP_CHAR = cpystr(DF_THREAD_EXP_CHAR);
1650 GLO_THREAD_LASTREPLY_CHAR = cpystr(DF_THREAD_LASTREPLY_CHAR);
1651 GLO_BUGS_FULLNAME = cpystr("Sorry No Address");
1652 GLO_BUGS_ADDRESS = cpystr("nobody");
1653 GLO_SUGGEST_FULLNAME = cpystr("Sorry No Address");
1654 GLO_SUGGEST_ADDRESS = cpystr("nobody");
1655 GLO_LOCAL_FULLNAME = cpystr(DF_LOCAL_FULLNAME);
1656 GLO_LOCAL_ADDRESS = cpystr(DF_LOCAL_ADDRESS);
1657 GLO_OVERLAP = cpystr(DF_OVERLAP);
1658 GLO_MAXREMSTREAM = cpystr(DF_MAXREMSTREAM);
1659 GLO_MARGIN = cpystr(DF_MARGIN);
1660 GLO_FILLCOL = cpystr(DF_FILLCOL);
1661 GLO_DEADLETS = cpystr(DF_DEADLETS);
1662 GLO_NMW_WIDTH = cpystr(DF_NMW_WIDTH);
1663 GLO_REPLY_STRING = cpystr("> ");
1664 GLO_REPLY_INTRO = cpystr(DEFAULT_REPLY_INTRO);
1665 GLO_EMPTY_HDR_MSG = cpystr("undisclosed-recipients");
1666 GLO_STATUS_MSG_DELAY = cpystr("0");
1667 GLO_ACTIVE_MSG_INTERVAL = cpystr("12");
1668 GLO_USERINPUTTIMEO = cpystr("0");
1669 GLO_INCCHECKTIMEO = cpystr("5");
1670 GLO_INCCHECKINTERVAL = cpystr("180");
1671 GLO_INC2NDCHECKINTERVAL = cpystr("180");
1672 GLO_MAILCHECK = cpystr(DF_MAILCHECK);
1673 GLO_MAILCHECKNONCURR = cpystr("0");
1674 GLO_MAILDROPCHECK = cpystr(DF_MAILDROPCHECK);
1675 GLO_NNTPRANGE = cpystr("0");
1676 GLO_KBLOCK_PASSWD_COUNT = cpystr(DF_KBLOCK_PASSWD_COUNT);
1677 GLO_INDEX_COLOR_STYLE = cpystr("flip-colors");
1678 GLO_TITLEBAR_COLOR_STYLE = cpystr("default");
1679 GLO_POST_CHAR_SET = cpystr("UTF-8");
1680 #ifdef DF_FOLDER_EXTENSION
1681 GLO_FOLDER_EXTENSION = cpystr(DF_FOLDER_EXTENSION);
1682 #endif
1683 #ifdef DF_SMTP_SERVER
1684 GLO_SMTP_SERVER = parse_list(DF_SMTP_SERVER, 1,
1685 PL_REMSURRQUOT, NULL);
1686 #endif
1688 #ifdef DF_SSHPATH
1689 GLO_SSHPATH = cpystr(DF_SSHPATH);
1690 #endif
1691 #ifdef DF_SSHCMD
1692 GLO_SSHCMD = cpystr(DF_SSHCMD);
1693 #endif
1695 #ifndef _WINDOWS
1696 GLO_COLOR_STYLE = cpystr("no-color");
1697 GLO_NORM_FORE_COLOR = cpystr(DEFAULT_NORM_FORE_RGB);
1698 GLO_NORM_BACK_COLOR = cpystr(DEFAULT_NORM_BACK_RGB);
1699 #endif
1700 GLO_TITLE_FORE_COLOR = cpystr(DEFAULT_TITLE_FORE_RGB);
1701 GLO_TITLE_BACK_COLOR = cpystr(DEFAULT_TITLE_BACK_RGB);
1702 GLO_TITLECLOSED_FORE_COLOR = cpystr(DEFAULT_TITLECLOSED_FORE_RGB);
1703 GLO_TITLECLOSED_BACK_COLOR = cpystr(DEFAULT_TITLECLOSED_BACK_RGB);
1704 GLO_FOLDER_FORE_COLOR = cpystr(DEFAULT_NORM_FORE_RGB);
1705 GLO_DIRECTORY_FORE_COLOR = cpystr(DEFAULT_NORM_FORE_RGB);
1706 GLO_FOLDER_LIST_FORE_COLOR = cpystr(DEFAULT_NORM_FORE_RGB);
1707 GLO_METAMSG_FORE_COLOR = cpystr(DEFAULT_METAMSG_FORE_RGB);
1708 GLO_METAMSG_BACK_COLOR = cpystr(DEFAULT_METAMSG_BACK_RGB);
1709 GLO_QUOTE1_FORE_COLOR = cpystr(DEFAULT_QUOTE1_FORE_RGB);
1710 GLO_QUOTE1_BACK_COLOR = cpystr(DEFAULT_QUOTE1_BACK_RGB);
1711 GLO_QUOTE2_FORE_COLOR = cpystr(DEFAULT_QUOTE2_FORE_RGB);
1712 GLO_QUOTE2_BACK_COLOR = cpystr(DEFAULT_QUOTE2_BACK_RGB);
1713 GLO_QUOTE3_FORE_COLOR = cpystr(DEFAULT_QUOTE3_FORE_RGB);
1714 GLO_QUOTE3_BACK_COLOR = cpystr(DEFAULT_QUOTE3_BACK_RGB);
1715 GLO_SIGNATURE_FORE_COLOR = cpystr(DEFAULT_SIGNATURE_FORE_RGB);
1716 GLO_SIGNATURE_BACK_COLOR = cpystr(DEFAULT_SIGNATURE_BACK_RGB);
1717 GLO_IND_PLUS_FORE_COLOR = cpystr(DEFAULT_IND_PLUS_FORE_RGB);
1718 GLO_IND_PLUS_BACK_COLOR = cpystr(DEFAULT_IND_PLUS_BACK_RGB);
1719 GLO_IND_IMP_FORE_COLOR = cpystr(DEFAULT_IND_IMP_FORE_RGB);
1720 GLO_IND_IMP_BACK_COLOR = cpystr(DEFAULT_IND_IMP_BACK_RGB);
1721 GLO_IND_ANS_FORE_COLOR = cpystr(DEFAULT_IND_ANS_FORE_RGB);
1722 GLO_IND_ANS_BACK_COLOR = cpystr(DEFAULT_IND_ANS_BACK_RGB);
1723 GLO_IND_NEW_FORE_COLOR = cpystr(DEFAULT_IND_NEW_FORE_RGB);
1724 GLO_IND_NEW_BACK_COLOR = cpystr(DEFAULT_IND_NEW_BACK_RGB);
1725 GLO_IND_OP_FORE_COLOR = cpystr(DEFAULT_IND_OP_FORE_RGB);
1726 GLO_IND_OP_BACK_COLOR = cpystr(DEFAULT_IND_OP_BACK_RGB);
1727 GLO_VIEW_MARGIN_LEFT = cpystr("0");
1728 GLO_VIEW_MARGIN_RIGHT = cpystr(DF_VIEW_MARGIN_RIGHT);
1729 GLO_QUOTE_SUPPRESSION = cpystr(DF_QUOTE_SUPPRESSION);
1730 GLO_KW_BRACES = cpystr("\"{\" \"} \"");
1731 GLO_OPENING_SEP = cpystr(" - ");
1732 GLO_WP_INDEXHEIGHT = cpystr("24");
1733 GLO_WP_AGGSTATE = cpystr("1");
1734 GLO_WP_STATE = cpystr("");
1735 #ifdef DEFAULT_SSLCAPATH
1736 GLO_SSLCAPATH = parse_list(DEFAULT_SSLCAPATH, 1,
1737 PL_REMSURRQUOT, NULL);
1738 #endif /* DEFAULT_SSLCAPATH */
1739 #ifdef DEFAULT_SSLCAFILE
1740 GLO_SSLCAFILE = parse_list(DEFAULT_SSLCAFILE, 1,
1741 PL_REMSURRQUOT, NULL);
1742 #endif /* DEFAULT_SSLCAFILE */
1743 #ifdef DF_VAR_SPELLER
1744 GLO_SPELLER = cpystr(DF_VAR_SPELLER);
1745 #endif
1746 #ifdef SMIME
1747 if(ps->smimedir){
1748 snprintf(tmp_20k_buf, SIZEOF_20KBUF, "%s/public", ps->smimedir);
1749 tmp_20k_buf[SIZEOF_20KBUF-1] = '\0';
1750 GLO_PUBLICCERT_DIR = cpystr(tmp_20k_buf);
1752 snprintf(tmp_20k_buf, SIZEOF_20KBUF, "%s/private", ps->smimedir);
1753 tmp_20k_buf[SIZEOF_20KBUF-1] = '\0';
1754 GLO_PRIVATEKEY_DIR = cpystr(tmp_20k_buf);
1756 snprintf(tmp_20k_buf, SIZEOF_20KBUF, "%s/ca", ps->smimedir);
1757 tmp_20k_buf[SIZEOF_20KBUF-1] = '\0';
1758 GLO_CACERT_DIR = cpystr(tmp_20k_buf);
1760 else{
1761 GLO_PUBLICCERT_DIR = cpystr(DF_PUBLICCERT_DIR);
1762 GLO_PRIVATEKEY_DIR = cpystr(DF_PRIVATEKEY_DIR);
1763 GLO_CACERT_DIR = cpystr(DF_CACERT_DIR);
1765 #endif /* SMIME */
1768 * Default first value for addrbook list if none set.
1769 * We also want to be sure to set global_val to the default
1770 * if is_fixed, so that address-book= will cause the default to happen.
1772 if(!GLO_ADDRESSBOOK && !FIX_ADDRESSBOOK)
1773 GLO_ADDRESSBOOK = parse_list(DF_ADDRESSBOOK, 1, 0, NULL);
1776 * Default first value if none set.
1778 if(!GLO_STANDARD_PRINTER && !FIX_STANDARD_PRINTER)
1779 GLO_STANDARD_PRINTER = parse_list(DF_STANDARD_PRINTER, 1, 0, NULL);
1782 * Defining this default sshpath should cause ssh to be preferred over rsh
1783 * when attempting imapd preauth calls.
1785 #ifdef DF_SSHPATH
1786 if(DF_SSHPATH
1787 && is_absolute_path(DF_SSHPATH)
1788 && can_access(DF_SSHPATH, EXECUTE_ACCESS) == 0){
1789 mail_parameters(NULL, SET_SSHPATH, (void *) DF_SSHPATH);
1791 #endif
1793 * It isn't usually necessary to define this.
1795 #ifdef DF_SSHCMD
1796 if(DF_SSHCMD){
1797 mail_parameters(NULL, SET_SSHCOMMAND, (void *) DF_SSHCMD);
1799 #endif
1801 #if !defined(DOS) && !defined(OS2)
1803 * This is here instead of in init_pinerc so that we can get by without
1804 * having a global fixedprc, since we don't need it anymore after this.
1806 fixedprc = new_pinerc_s(SYSTEM_PINERC_FIXED);
1807 #endif
1809 if(ps->pconf){
1810 read_pinerc(ps->pconf, vars, ParseGlobal);
1811 if(ps->pconf->type != Loc)
1812 rd_close_remote(ps->pconf->rd);
1815 if(ps->prc){
1816 read_pinerc(ps->prc, vars, ParsePers);
1817 if(ps->prc->type != Loc)
1818 rd_close_remote(ps->prc->rd);
1821 if(ps->post_prc){
1822 read_pinerc(ps->post_prc, vars, ParsePersPost);
1823 if(ps->post_prc->type != Loc)
1824 rd_close_remote(ps->post_prc->rd);
1827 if(fixedprc){
1828 read_pinerc(fixedprc, vars, ParseFixed);
1829 free_pinerc_s(&fixedprc);
1832 ps->ew_for_except_vars = ps->post_prc ? Post : Main;
1834 if(ps->exit_if_no_pinerc && ps->first_time_user){
1836 /* TRANSLATORS: -bail is a literal option name, don't change it. */
1837 exceptional_exit(_("Exiting because -bail option is set and config file doesn't exist."), -1);
1841 * Convert everything having to do with the config to UTF-8
1842 * in order to avoid having to worry about it all over the
1843 * place.
1844 * Set the character-set first so that we may use that in
1845 * the conversion process.
1847 set_collation(0, 1);
1849 #ifndef _WINDOWS
1850 #if (HAVE_LANGINFO_H && defined(CODESET))
1852 if(output_charset_is_supported(nl_langinfo_codeset_wrapper()))
1853 ps->GLO_CHAR_SET = cpystr(nl_langinfo_codeset_wrapper());
1854 else{
1855 ps->GLO_CHAR_SET = cpystr("UTF-8");
1856 dprint((1,"nl_langinfo(CODESET) returns unrecognized value=\"%s\", using UTF-8 as default\n", (p=nl_langinfo(CODESET)) ? p : ""));
1858 #else
1859 ps->GLO_CHAR_SET = cpystr("UTF-8");
1860 #endif
1862 set_current_val(&vars[V_CHAR_SET], TRUE, TRUE);
1863 set_current_val(&vars[V_OLD_CHAR_SET], TRUE, TRUE);
1864 set_current_val(&vars[V_KEY_CHAR_SET], TRUE, TRUE);
1865 #endif /* ! _WINDOWS */
1867 set_current_val(&vars[V_POST_CHAR_SET], TRUE, TRUE);
1870 * Also set up the feature list because we need the
1871 * Use-System-Translation feature to set up the charmaps.
1874 /* way obsolete, backwards compatibility */
1875 set_current_val(&vars[V_FEATURE_LEVEL], TRUE, TRUE);
1876 if(strucmp(VAR_FEATURE_LEVEL, "seedling") == 0)
1877 obs_feature_level = Seedling;
1878 else if(strucmp(VAR_FEATURE_LEVEL, "old-growth") == 0)
1879 obs_feature_level = Seasoned;
1880 else
1881 obs_feature_level = Sapling;
1883 /* obsolete, backwards compatibility */
1884 set_current_val(&vars[V_OLD_STYLE_REPLY], TRUE, TRUE);
1885 obs_old_style_reply = !strucmp(VAR_OLD_STYLE_REPLY, "yes");
1887 set_feature_list_current_val(&vars[V_FEATURE_LIST]);
1888 process_feature_list(ps, VAR_FEATURE_LIST,
1889 (obs_feature_level == Seasoned) ? 1 : 0,
1890 obs_header_in_reply, obs_old_style_reply);
1894 * Redo set_collation call with correct value for collation,
1895 * but we're hardwiring ctype on now. That's because nl_langinfo()
1896 * call needs it and system-dependent wcwidth and wcrtomb functions
1897 * need it.
1899 set_collation(F_OFF(F_DISABLE_SETLOCALE_COLLATE, ps_global), 1);
1902 * Set up to send the correct sequence of bytes to the display terminal.
1905 if(reset_character_set_stuff(&err) == -1)
1906 alpine_panic(err ? err : "trouble with character set setup");
1907 else if(err){
1908 init_error(ps, SM_ORDER | SM_DING, 3, 5, err);
1909 fs_give((void **) &err);
1913 * Now we use the configvars from above to convert the rest
1914 * to UTF-8. That should be ok because the ones above should
1915 * be ASCII.
1917 if(ps->keyboard_charmap && strucmp(ps->keyboard_charmap, "UTF-8")
1918 && strucmp(ps->keyboard_charmap, "US-ASCII"))
1919 fromcharset = ps->keyboard_charmap;
1920 else if(ps->display_charmap && strucmp(ps->display_charmap, "UTF-8")
1921 && strucmp(ps->display_charmap, "US-ASCII"))
1922 fromcharset = ps->display_charmap;
1923 #ifndef _WINDOWS
1924 else if(VAR_OLD_CHAR_SET && strucmp(VAR_OLD_CHAR_SET, "UTF-8")
1925 && strucmp(VAR_OLD_CHAR_SET, "US-ASCII"))
1926 fromcharset = VAR_OLD_CHAR_SET;
1927 #endif /* ! _WINDOWS */
1929 convert_configvars_to_utf8(vars, fromcharset);
1932 * If we already set this while reading the remote pinerc, don't
1933 * change it.
1935 if(!VAR_REMOTE_ABOOK_METADATA || !VAR_REMOTE_ABOOK_METADATA[0])
1936 set_current_val(&vars[V_REMOTE_ABOOK_METADATA], TRUE, TRUE);
1939 * mail-directory variable is obsolete, put its value in
1940 * default folder-collection list
1942 set_current_val(&vars[V_MAIL_DIRECTORY], TRUE, TRUE);
1943 if(!GLO_FOLDER_SPEC){
1944 build_path(tmp_20k_buf, VAR_MAIL_DIRECTORY, "[]", SIZEOF_20KBUF);
1945 GLO_FOLDER_SPEC = parse_list(tmp_20k_buf, 1, 0, NULL);
1948 set_current_val(&vars[V_FOLDER_SPEC], TRUE, TRUE);
1950 set_current_val(&vars[V_NNTP_SERVER], TRUE, TRUE);
1951 for(i = 0; VAR_NNTP_SERVER && VAR_NNTP_SERVER[i]; i++)
1952 removing_quotes(VAR_NNTP_SERVER[i]);
1954 set_news_spec_current_val(TRUE, TRUE);
1956 set_current_val(&vars[V_INBOX_PATH], TRUE, TRUE);
1958 set_current_val(&vars[V_USER_DOMAIN], TRUE, TRUE);
1959 if(VAR_USER_DOMAIN
1960 && VAR_USER_DOMAIN[0]
1961 && (p = strrindex(VAR_USER_DOMAIN, '@'))){
1962 if(*(++p)){
1963 char *q;
1965 snprintf(tmp_20k_buf, SIZEOF_20KBUF,
1966 "User-domain (%s) cannot contain \"@\", using \"%s\"",
1967 VAR_USER_DOMAIN, p);
1968 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
1969 q = VAR_USER_DOMAIN;
1970 while((*q++ = *p++) != '\0')
1971 ;/* do nothing */
1973 else{
1974 snprintf(tmp_20k_buf, SIZEOF_20KBUF,
1975 "User-domain (%s) cannot contain \"@\", deleting",
1976 VAR_USER_DOMAIN);
1977 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
1978 if(ps->vars[V_USER_DOMAIN].post_user_val.p){
1979 fs_give((void **)&ps->vars[V_USER_DOMAIN].post_user_val.p);
1980 set_current_val(&vars[V_USER_DOMAIN], TRUE, TRUE);
1983 if(VAR_USER_DOMAIN
1984 && VAR_USER_DOMAIN[0]
1985 && (p = strrindex(VAR_USER_DOMAIN, '@'))){
1986 if(ps->vars[V_USER_DOMAIN].main_user_val.p){
1987 fs_give((void **)&ps->vars[V_USER_DOMAIN].main_user_val.p);
1988 set_current_val(&vars[V_USER_DOMAIN], TRUE, TRUE);
1994 set_current_val(&vars[V_USE_ONLY_DOMAIN_NAME], TRUE, TRUE);
1995 set_current_val(&vars[V_REPLY_STRING], TRUE, TRUE);
1996 set_current_val(&vars[V_WORDSEPS], TRUE, TRUE);
1997 set_current_val(&vars[V_QUOTE_REPLACE_STRING], TRUE, TRUE);
1998 set_current_val(&vars[V_REPLY_INTRO], TRUE, TRUE);
1999 set_current_val(&vars[V_EMPTY_HDR_MSG], TRUE, TRUE);
2001 #ifdef ENABLE_LDAP
2002 set_current_val(&vars[V_LDAP_SERVERS], TRUE, TRUE);
2003 #endif /* ENABLE_LDAP */
2005 /* obsolete, backwards compatibility */
2006 set_current_val(&vars[V_HEADER_IN_REPLY], TRUE, TRUE);
2007 obs_header_in_reply=!strucmp(VAR_HEADER_IN_REPLY, "yes");
2009 set_current_val(&vars[V_PERSONAL_PRINT_COMMAND], TRUE, TRUE);
2010 set_current_val(&vars[V_STANDARD_PRINTER], TRUE, TRUE);
2011 set_current_val(&vars[V_PRINTER], TRUE, TRUE);
2012 if(vars[V_PERSONAL_PRINT_COMMAND].is_fixed && !vars[V_PRINTER].is_fixed)
2013 printer_value_check_and_adjust();
2015 set_current_val(&vars[V_LAST_TIME_PRUNE_QUESTION], TRUE, TRUE);
2016 if(VAR_LAST_TIME_PRUNE_QUESTION != NULL &&
2017 (comma_index = strindex(VAR_LAST_TIME_PRUNE_QUESTION, '.')) != NULL){
2018 /* The month value in the file runs from 1-12, the variable here
2019 runs from 0-11; the value in the file used to be 0-11, but we're
2020 fixing it in January */
2021 ps->last_expire_year = atoi(VAR_LAST_TIME_PRUNE_QUESTION);
2022 ps->last_expire_month = atoi(comma_index + 1);
2023 if(ps->last_expire_month == 0){
2024 /* Fix for 0 because of old bug */
2025 snprintf(buf, sizeof(buf), "%d.%d", ps_global->last_expire_year,
2026 ps_global->last_expire_month + 1);
2027 set_variable(V_LAST_TIME_PRUNE_QUESTION, buf, 1, 1, Main);
2028 }else{
2029 ps->last_expire_month--;
2031 }else{
2032 ps->last_expire_year = -1;
2033 ps->last_expire_month = -1;
2036 set_current_val(&vars[V_BUGS_FULLNAME], TRUE, TRUE);
2037 set_current_val(&vars[V_BUGS_ADDRESS], TRUE, TRUE);
2038 set_current_val(&vars[V_SUGGEST_FULLNAME], TRUE, TRUE);
2039 set_current_val(&vars[V_SUGGEST_ADDRESS], TRUE, TRUE);
2040 set_current_val(&vars[V_LOCAL_FULLNAME], TRUE, TRUE);
2041 set_current_val(&vars[V_LOCAL_ADDRESS], TRUE, TRUE);
2042 set_current_val(&vars[V_BUGS_EXTRAS], TRUE, TRUE);
2043 set_current_val(&vars[V_KBLOCK_PASSWD_COUNT], TRUE, TRUE);
2044 set_current_val(&vars[V_DEFAULT_FCC], TRUE, TRUE);
2045 set_current_val(&vars[V_POSTPONED_FOLDER], TRUE, TRUE);
2046 set_current_val(&vars[V_TRASH_FOLDER], TRUE, TRUE);
2047 set_current_val(&vars[V_READ_MESSAGE_FOLDER], TRUE, TRUE);
2048 set_current_val(&vars[V_FORM_FOLDER], TRUE, TRUE);
2049 set_current_val(&vars[V_EDITOR], TRUE, TRUE);
2050 set_current_val(&vars[V_SPELLER], TRUE, TRUE);
2051 #ifdef _WINDOWS
2052 set_current_val(&vars[V_DICTIONARY], TRUE, TRUE);
2053 #endif /* _WINDOWS */
2054 set_current_val(&vars[V_IMAGE_VIEWER], TRUE, TRUE);
2055 set_current_val(&vars[V_BROWSER], TRUE, TRUE);
2056 set_current_val(&vars[V_HISTORY], TRUE, TRUE);
2057 set_current_val(&vars[V_SMTP_SERVER], TRUE, TRUE);
2058 set_current_val(&vars[V_COMP_HDRS], TRUE, TRUE);
2059 set_current_val(&vars[V_CUSTOM_HDRS], TRUE, TRUE);
2060 set_current_val(&vars[V_SENDMAIL_PATH], TRUE, TRUE);
2061 set_current_val(&vars[V_DISPLAY_FILTERS], TRUE, TRUE);
2062 set_current_val(&vars[V_SEND_FILTER], TRUE, TRUE);
2063 set_current_val(&vars[V_ALT_ADDRS], TRUE, TRUE);
2064 set_current_val(&vars[V_ABOOK_FORMATS], TRUE, TRUE);
2065 set_current_val(&vars[V_KW_BRACES], TRUE, TRUE);
2066 set_current_val(&vars[V_OPENING_SEP], TRUE, TRUE);
2067 set_current_val(&vars[V_UNK_CHAR_SET], TRUE, TRUE);
2068 #ifdef SMIME
2069 set_current_val(&vars[V_PUBLICCERT_DIR], TRUE, TRUE);
2070 set_current_val(&vars[V_PUBLICCERT_CONTAINER], TRUE, TRUE);
2071 set_current_val(&vars[V_PRIVATEKEY_DIR], TRUE, TRUE);
2072 set_current_val(&vars[V_PRIVATEKEY_CONTAINER], TRUE, TRUE);
2073 set_current_val(&vars[V_CACERT_DIR], TRUE, TRUE);
2074 set_current_val(&vars[V_CACERT_CONTAINER], TRUE, TRUE);
2075 #endif /* SMIME */
2077 set_current_val(&vars[V_KEYWORDS], TRUE, TRUE);
2078 ps_global->keywords = init_keyword_list(VAR_KEYWORDS);
2080 set_current_val(&vars[V_OPER_DIR], TRUE, TRUE);
2081 if(VAR_OPER_DIR && !VAR_OPER_DIR[0]){
2082 init_error(ps, SM_ORDER | SM_DING, 3, 5,
2083 "Setting operating-dir to the empty string is not allowed. Will be ignored.");
2084 fs_give((void **)&VAR_OPER_DIR);
2085 if(FIX_OPER_DIR)
2086 fs_give((void **)&FIX_OPER_DIR);
2087 if(GLO_OPER_DIR)
2088 fs_give((void **)&GLO_OPER_DIR);
2089 if(COM_OPER_DIR)
2090 fs_give((void **)&COM_OPER_DIR);
2091 if(ps_global->vars[V_OPER_DIR].post_user_val.p)
2092 fs_give((void **)&ps_global->vars[V_OPER_DIR].post_user_val.p);
2093 if(ps_global->vars[V_OPER_DIR].main_user_val.p)
2094 fs_give((void **)&ps_global->vars[V_OPER_DIR].main_user_val.p);
2097 set_current_val(&vars[V_PERSONAL_PRINT_CATEGORY], TRUE, TRUE);
2098 ps->printer_category = -1;
2099 if(VAR_PERSONAL_PRINT_CATEGORY != NULL)
2100 ps->printer_category = atoi(VAR_PERSONAL_PRINT_CATEGORY);
2102 if(ps->printer_category < 1 || ps->printer_category > 3){
2103 char **tt;
2104 char aname[100], wname[100];
2106 strncpy(aname, ANSI_PRINTER, sizeof(aname));
2107 aname[sizeof(aname)-1] = '\0';
2108 strncat(aname, "-no-formfeed", sizeof(aname)-strlen(aname)-1);
2109 strncpy(wname, WYSE_PRINTER, sizeof(wname));
2110 wname[sizeof(wname)-1] = '\0';
2111 strncat(wname, "-no-formfeed", sizeof(wname)-strlen(wname)-1);
2112 if(strucmp(VAR_PRINTER, ANSI_PRINTER) == 0
2113 || strucmp(VAR_PRINTER, aname) == 0
2114 || strucmp(VAR_PRINTER, WYSE_PRINTER) == 0
2115 || strucmp(VAR_PRINTER, wname) == 0)
2116 ps->printer_category = 1;
2117 else if(VAR_STANDARD_PRINTER && VAR_STANDARD_PRINTER[0]){
2118 for(tt = VAR_STANDARD_PRINTER; *tt; tt++)
2119 if(strucmp(VAR_PRINTER, *tt) == 0)
2120 break;
2122 if(*tt)
2123 ps->printer_category = 2;
2126 /* didn't find it yet */
2127 if(ps->printer_category < 1 || ps->printer_category > 3){
2128 if(VAR_PERSONAL_PRINT_COMMAND && VAR_PERSONAL_PRINT_COMMAND[0]){
2129 for(tt = VAR_PERSONAL_PRINT_COMMAND; *tt; tt++)
2130 if(strucmp(VAR_PRINTER, *tt) == 0)
2131 break;
2133 if(*tt)
2134 ps->printer_category = 3;
2139 set_current_val(&vars[V_OVERLAP], TRUE, TRUE);
2140 ps->viewer_overlap = i = atoi(DF_OVERLAP);
2141 if(SVAR_OVERLAP(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2142 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2143 else
2144 ps->viewer_overlap = i;
2146 set_current_val(&vars[V_MARGIN], TRUE, TRUE);
2147 ps->scroll_margin = i = atoi(DF_MARGIN);
2148 if(SVAR_MARGIN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2149 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2150 else
2151 ps->scroll_margin = i;
2153 set_current_val(&vars[V_FILLCOL], TRUE, TRUE);
2154 ps->composer_fillcol = i = atoi(DF_FILLCOL);
2155 if(SVAR_FILLCOL(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2156 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2157 else
2158 ps->composer_fillcol = i;
2160 set_current_val(&vars[V_QUOTE_SUPPRESSION], TRUE, TRUE);
2161 ps->quote_suppression_threshold = i = atoi(DF_QUOTE_SUPPRESSION);
2162 if(SVAR_QUOTE_SUPPRESSION(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2163 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2164 else{
2165 if(i > 0 && i < Q_SUPP_LIMIT){
2166 snprintf(tmp_20k_buf, SIZEOF_20KBUF,
2167 "Ignoring Quote-Suppression-Threshold value of %.50s, see help",
2168 VAR_QUOTE_SUPPRESSION);
2169 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2171 else{
2172 if(i < 0 && i != Q_DEL_ALL)
2173 ps->quote_suppression_threshold = -i;
2174 else
2175 ps->quote_suppression_threshold = i;
2179 set_current_val(&vars[V_DEADLETS], TRUE, TRUE);
2180 ps->deadlets = i = atoi(DF_DEADLETS);
2181 if(SVAR_DEADLETS(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2182 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2183 else
2184 ps->deadlets = i;
2186 set_current_val(&vars[V_STATUS_MSG_DELAY], TRUE, TRUE);
2187 ps->status_msg_delay = i = 0;
2188 if(SVAR_MSGDLAY(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2189 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2190 else
2191 ps->status_msg_delay = i;
2193 set_current_val(&vars[V_ACTIVE_MSG_INTERVAL], TRUE, TRUE);
2194 ps->active_status_interval = i = 8;
2195 if(SVAR_ACTIVEINTERVAL(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2196 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2197 else
2198 ps->active_status_interval = i;
2200 set_current_val(&vars[V_REMOTE_ABOOK_HISTORY], TRUE, TRUE);
2201 ps->remote_abook_history = i = atoi(DF_REMOTE_ABOOK_HISTORY);
2202 if(SVAR_AB_HIST(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2203 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2204 else
2205 ps->remote_abook_history = i;
2207 set_current_val(&vars[V_REMOTE_ABOOK_VALIDITY], TRUE, TRUE);
2208 ps->remote_abook_validity = i = atoi(DF_REMOTE_ABOOK_VALIDITY);
2209 if(SVAR_AB_VALID(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2210 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2211 else
2212 ps->remote_abook_validity = i;
2214 set_current_val(&vars[V_USERINPUTTIMEO], TRUE, TRUE);
2215 ps->hours_to_timeout = i = 0;
2216 if(SVAR_USER_INPUT(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2217 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2218 else
2219 ps->hours_to_timeout = i;
2221 /* timeo is a regular extern int because it is referenced in pico */
2222 set_current_val(&vars[V_MAILCHECK], TRUE, TRUE);
2223 set_input_timeout(i = 15);
2224 if(SVAR_MAILCHK(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2225 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2226 else
2227 set_input_timeout(i);
2229 set_current_val(&vars[V_MAILCHECKNONCURR], TRUE, TRUE);
2230 ps->check_interval_for_noncurr = i = 0;
2231 if(SVAR_MAILCHKNONCURR(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2232 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2233 else
2234 ps->check_interval_for_noncurr = i;
2236 #ifdef DEBUGJOURNAL
2237 ps->debugmem = 1;
2238 #else
2239 ps->debugmem = 0;
2240 #endif
2242 i = 30;
2243 set_current_val(&vars[V_TCPOPENTIMEO], TRUE, TRUE);
2244 /* this is just for the error, we don't save the result */
2245 if(VAR_TCPOPENTIMEO && SVAR_TCP_OPEN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2246 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2248 i = 15;
2249 set_current_val(&vars[V_TCPREADWARNTIMEO], TRUE, TRUE);
2250 /* this is just for the error, we don't save the result */
2251 if(VAR_TCPREADWARNTIMEO && SVAR_TCP_READWARN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2252 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2254 i = 0;
2255 set_current_val(&vars[V_TCPWRITEWARNTIMEO], TRUE, TRUE);
2256 /* this is just for the error, we don't save the result */
2257 if(VAR_TCPWRITEWARNTIMEO && SVAR_TCP_WRITEWARN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2258 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2260 i = 15;
2261 set_current_val(&vars[V_RSHOPENTIMEO], TRUE, TRUE);
2262 /* this is just for the error, we don't save the result */
2263 if(VAR_RSHOPENTIMEO && SVAR_RSH_OPEN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2264 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2266 i = 15;
2267 set_current_val(&vars[V_SSHOPENTIMEO], TRUE, TRUE);
2268 /* this is just for the error, we don't save the result */
2269 if(VAR_SSHOPENTIMEO && SVAR_SSH_OPEN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2270 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2272 set_current_val(&vars[V_INCCHECKLIST], TRUE, TRUE);
2274 set_current_val(&vars[V_INCCHECKTIMEO], TRUE, TRUE);
2275 ps->inc_check_timeout = i = 5;
2276 if(SVAR_INC_CHECK_TIMEO(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2277 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2278 else
2279 ps->inc_check_timeout = i;
2281 set_current_val(&vars[V_INCCHECKINTERVAL], TRUE, TRUE);
2282 ps->inc_check_interval = i = 180;
2283 if(SVAR_INC_CHECK_INTERV(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2284 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2285 else
2286 ps->inc_check_interval = i;
2288 set_current_val(&vars[V_INC2NDCHECKINTERVAL], TRUE, TRUE);
2289 ps->inc_second_check_interval = i = 180;
2290 if(SVAR_INC_2NDCHECK_INTERV(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2291 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2292 else
2293 ps->inc_second_check_interval = i;
2295 rvl = 60L;
2296 set_current_val(&vars[V_MAILDROPCHECK], TRUE, TRUE);
2297 /* this is just for the error, we don't save the result */
2298 if(VAR_MAILDROPCHECK && SVAR_MAILDCHK(ps, rvl, tmp_20k_buf, SIZEOF_20KBUF))
2299 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2301 rvl = 0L;
2302 set_current_val(&vars[V_NNTPRANGE], TRUE, TRUE);
2303 /* this is just for the error, we don't save the result */
2304 if(VAR_NNTPRANGE && SVAR_NNTPRANGE(ps, rvl, tmp_20k_buf, SIZEOF_20KBUF))
2305 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2307 set_current_val(&vars[V_TCPQUERYTIMEO], TRUE, TRUE);
2308 ps->tcp_query_timeout = i = TO_BAIL_THRESHOLD;
2309 if(VAR_TCPQUERYTIMEO && SVAR_TCP_QUERY(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2310 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2311 else
2312 ps->tcp_query_timeout = i;
2314 set_current_val(&vars[V_QUITQUERYTIMEO], TRUE, TRUE);
2315 ps->close_connection_timeout = i = 0;
2316 if(VAR_QUITQUERYTIMEO && SVAR_QUIT_QUERY_TIMEO(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2317 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2318 else
2319 ps->close_connection_timeout = i;
2321 set_current_val(&vars[V_NEWSRC_PATH], TRUE, TRUE);
2322 if(VAR_NEWSRC_PATH && VAR_NEWSRC_PATH[0])
2323 mail_parameters(NULL, SET_NEWSRC, (void *)VAR_NEWSRC_PATH);
2325 set_current_val(&vars[V_NEWS_ACTIVE_PATH], TRUE, TRUE);
2326 if(VAR_NEWS_ACTIVE_PATH)
2327 mail_parameters(NULL, SET_NEWSACTIVE,
2328 (void *)VAR_NEWS_ACTIVE_PATH);
2330 set_current_val(&vars[V_NEWS_SPOOL_DIR], TRUE, TRUE);
2331 if(VAR_NEWS_SPOOL_DIR)
2332 mail_parameters(NULL, SET_NEWSSPOOL,
2333 (void *)VAR_NEWS_SPOOL_DIR);
2335 /* guarantee a save default */
2336 set_current_val(&vars[V_DEFAULT_SAVE_FOLDER], TRUE, TRUE);
2337 if(!VAR_DEFAULT_SAVE_FOLDER || !VAR_DEFAULT_SAVE_FOLDER[0])
2338 set_variable(V_DEFAULT_SAVE_FOLDER,
2339 (GLO_DEFAULT_SAVE_FOLDER && GLO_DEFAULT_SAVE_FOLDER[0])
2340 ? GLO_DEFAULT_SAVE_FOLDER
2341 : DEFAULT_SAVE, 1, 0, Main);
2343 set_current_val(&vars[V_SIGNATURE_FILE], TRUE, TRUE);
2344 set_current_val(&vars[V_LITERAL_SIG], TRUE, TRUE);
2345 set_current_val(&vars[V_GLOB_ADDRBOOK], TRUE, TRUE);
2346 set_current_val(&vars[V_ADDRESSBOOK], TRUE, TRUE);
2347 set_current_val(&vars[V_FORCED_ABOOK_ENTRY], TRUE, TRUE);
2348 set_current_val(&vars[V_DISABLE_DRIVERS], TRUE, TRUE);
2349 set_current_val(&vars[V_DISABLE_AUTHS], TRUE, TRUE);
2350 #ifdef DF_ENCRYPTION_RANGE
2351 set_current_val(&vars[V_ENCRYPTION_RANGE], TRUE, TRUE);
2352 #endif
2354 set_current_val(&vars[V_VIEW_HEADERS], TRUE, TRUE);
2355 /* strip spaces and colons */
2356 if(ps->VAR_VIEW_HEADERS){
2357 for(s = ps->VAR_VIEW_HEADERS; (q = *s) != NULL; s++){
2358 if(q[0]){
2359 removing_leading_white_space(q);
2360 /* look for colon or space or end */
2361 for(p = q; *p && !isspace((unsigned char)*p) && *p != ':'; p++)
2362 ;/* do nothing */
2364 *p = '\0';
2365 if(strucmp(q, ALL_EXCEPT) == 0)
2366 ps->view_all_except = 1;
2371 set_current_val(&vars[V_VIEW_MARGIN_LEFT], TRUE, TRUE);
2372 set_current_val(&vars[V_VIEW_MARGIN_RIGHT], TRUE, TRUE);
2373 set_current_val(&vars[V_UPLOAD_CMD], TRUE, TRUE);
2374 set_current_val(&vars[V_UPLOAD_CMD_PREFIX], TRUE, TRUE);
2375 set_current_val(&vars[V_DOWNLOAD_CMD], TRUE, TRUE);
2376 set_current_val(&vars[V_DOWNLOAD_CMD_PREFIX], TRUE, TRUE);
2377 set_current_val(&vars[V_MAILCAP_PATH], TRUE, TRUE);
2378 set_current_val(&vars[V_MIMETYPE_PATH], TRUE, TRUE);
2379 #if !defined(_WINDOWS) || defined(WINDOWS_LIBRESSL_CERTS)
2380 set_current_val(&vars[V_SSLCAPATH], TRUE, TRUE);
2381 set_current_val(&vars[V_SSLCAFILE], TRUE, TRUE);
2382 #endif
2383 #if !defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)
2384 set_current_val(&vars[V_FIFOPATH], TRUE, TRUE);
2385 #endif
2387 set_current_val(&vars[V_RSHPATH], TRUE, TRUE);
2388 if(VAR_RSHPATH
2389 && is_absolute_path(VAR_RSHPATH)
2390 && can_access(VAR_RSHPATH, EXECUTE_ACCESS) == 0){
2391 mail_parameters(NULL, SET_RSHPATH, (void *) VAR_RSHPATH);
2394 set_current_val(&vars[V_RSHCMD], TRUE, TRUE);
2395 if(VAR_RSHCMD){
2396 mail_parameters(NULL, SET_RSHCOMMAND, (void *) VAR_RSHCMD);
2399 set_current_val(&vars[V_SSHPATH], TRUE, TRUE);
2400 if(VAR_SSHPATH) {
2401 if(is_absolute_path(VAR_SSHPATH)
2402 && can_access(VAR_SSHPATH, EXECUTE_ACCESS) == 0){
2403 mail_parameters(NULL, SET_SSHPATH, (void *) VAR_SSHPATH);
2405 else {
2406 mail_parameters(NULL, SET_SSHPATH, (void *) NULL);
2410 set_current_val(&vars[V_SSHCMD], TRUE, TRUE);
2411 if(VAR_SSHCMD) {
2412 if(VAR_SSHCMD[0]) {
2413 mail_parameters(NULL, SET_SSHCOMMAND, (void *) VAR_SSHCMD);
2415 else {
2416 mail_parameters(NULL, SET_SSHCOMMAND, (void *) NULL);
2420 #if defined(DOS) || defined(OS2)
2422 set_current_val(&vars[V_FILE_DIR], TRUE, TRUE);
2424 #ifdef _WINDOWS
2425 set_current_val(&vars[V_FONT_NAME], TRUE, TRUE);
2426 set_current_val(&vars[V_FONT_SIZE], TRUE, TRUE);
2427 set_current_val(&vars[V_FONT_STYLE], TRUE, TRUE);
2428 set_current_val(&vars[V_FONT_CHAR_SET], TRUE, TRUE);
2429 set_current_val(&vars[V_CURSOR_STYLE], TRUE, TRUE);
2430 set_current_val(&vars[V_WINDOW_POSITION], TRUE, TRUE);
2432 if(F_OFF(F_STORE_WINPOS_IN_CONFIG, ps_global)){
2433 /* if win position is in the registry, use it */
2434 if(mswin_reg(MSWR_OP_GET, MSWR_PINE_POS, buf, sizeof(buf))){
2435 if(VAR_WINDOW_POSITION)
2436 fs_give((void **)&VAR_WINDOW_POSITION);
2438 VAR_WINDOW_POSITION = cpystr(buf);
2440 else if(VAR_WINDOW_POSITION
2441 && (ps->update_registry != UREG_NEVER_SET)){
2442 /* otherwise, put it there */
2443 mswin_reg(MSWR_OP_SET | ((ps->update_registry == UREG_ALWAYS_SET)
2444 ? MSWR_OP_FORCE : 0),
2445 MSWR_PINE_POS,
2446 VAR_WINDOW_POSITION, (size_t)NULL);
2450 mswin_setwindow (VAR_FONT_NAME, VAR_FONT_SIZE,
2451 VAR_FONT_STYLE, VAR_WINDOW_POSITION,
2452 VAR_CURSOR_STYLE, VAR_FONT_CHAR_SET);
2454 /* this is no longer used */
2455 if(VAR_WINDOW_POSITION)
2456 fs_give((void **)&VAR_WINDOW_POSITION);
2458 set_current_val(&vars[V_PRINT_FONT_NAME], TRUE, TRUE);
2459 set_current_val(&vars[V_PRINT_FONT_SIZE], TRUE, TRUE);
2460 set_current_val(&vars[V_PRINT_FONT_STYLE], TRUE, TRUE);
2461 set_current_val(&vars[V_PRINT_FONT_CHAR_SET], TRUE, TRUE);
2462 mswin_setprintfont (VAR_PRINT_FONT_NAME,
2463 VAR_PRINT_FONT_SIZE,
2464 VAR_PRINT_FONT_STYLE,
2465 VAR_PRINT_FONT_CHAR_SET);
2467 mswin_setgenhelptextcallback(pcpine_general_help);
2469 mswin_setclosetext ("Use the \"Q\" command to exit Alpine.");
2472 char foreColor[64], backColor[64];
2474 mswin_getwindow(NULL, 0, NULL, 0, NULL, 0, NULL, 0,
2475 foreColor, sizeof(foreColor), backColor, sizeof(backColor),
2476 NULL, 0, NULL, 0);
2477 if(!GLO_NORM_FORE_COLOR)
2478 GLO_NORM_FORE_COLOR = cpystr(foreColor);
2480 if(!GLO_NORM_BACK_COLOR)
2481 GLO_NORM_BACK_COLOR = cpystr(backColor);
2483 #endif /* _WINDOWS */
2484 #endif /* DOS */
2487 * We want the version number to start out as 1.0 for Alpine, but
2488 * we also want to use the same old config file that was used
2489 * with Pine. The Pine version numbers made it up to 4.64 and we
2490 * want Alpine's 1.0 to be larger than 4.64 so we keep a separate
2491 * internal version number which is the real version number
2492 * plus 4. That's what gets written in LAST_VERS_USED.
2494 strncpy(ps->vers_internal, ALPINE_VERSION, sizeof(ps->vers_internal));
2495 ps->vers_internal[sizeof(ps->vers_internal)-1] = '\0';
2496 if(isdigit(ps->vers_internal[0]) && ps->vers_internal[0] < '6')
2497 ps->vers_internal[0] = ps->vers_internal[0] + 4;
2499 set_current_val(&vars[V_LAST_VERS_USED], TRUE, TRUE);
2500 /* Check for special cases first */
2501 if(VAR_LAST_VERS_USED
2502 && (isdigit(ps->vers_internal[0])
2503 && ps->vers_internal[1] == '.'
2504 && isdigit((unsigned char)ps->vers_internal[2])
2505 && isdigit((unsigned char)ps->vers_internal[3])
2506 && isalpha((unsigned char)ps->vers_internal[4])
2507 && strncmp(VAR_LAST_VERS_USED, ps->vers_internal, 4) >= 0)){
2508 ps->show_new_version = 0;
2510 /* Otherwise just do lexicographic comparison... */
2511 else if(VAR_LAST_VERS_USED
2512 && strcmp(VAR_LAST_VERS_USED, ps->vers_internal) >= 0){
2513 ps->show_new_version = 0;
2515 else{
2516 #ifdef _WINDOWS
2518 * If this is the first time we've run a version > 4.40, and there
2519 * is evidence that the config file has not been used by unix pine,
2520 * then we convert color008 to colorlgr, color009 to colormgr, and
2521 * color010 to colordgr. If the config file is being used by
2522 * unix pine then color009 may really supposed to be red, etc.
2523 * Same if we've already run 4.41 or higher. We don't have to do
2524 * anything if we are new to alpine.
2526 ps->pre441 = (VAR_LAST_VERS_USED
2527 && strcmp(VAR_LAST_VERS_USED, "4.40") <= 0);
2528 #endif /* _WINDOWS */
2531 * Don't offer the new version message if we're told not to.
2533 set_current_val(&vars[V_NEW_VER_QUELL], TRUE, TRUE);
2534 ps->show_new_version = !(VAR_NEW_VER_QUELL
2535 && strcmp(ps->vers_internal,
2536 VAR_NEW_VER_QUELL) < 0);
2538 #ifdef _WINDOWS
2539 if(!ps_global->install_flag)
2540 #endif /* _WINDOWS */
2542 if(VAR_LAST_VERS_USED){
2543 strncpy(ps_global->pine_pre_vers, VAR_LAST_VERS_USED,
2544 sizeof(ps_global->pine_pre_vers));
2545 ps_global->pine_pre_vers[sizeof(ps_global->pine_pre_vers)-1] = '\0';
2548 set_variable(V_LAST_VERS_USED, ps->vers_internal, 1, 1,
2549 ps_global->ew_for_except_vars);
2553 /* Obsolete, backwards compatibility */
2554 set_current_val(&vars[V_ELM_STYLE_SAVE], TRUE, TRUE);
2555 /* Also obsolete */
2556 set_current_val(&vars[V_SAVE_BY_SENDER], TRUE, TRUE);
2557 if(!strucmp(VAR_ELM_STYLE_SAVE, "yes"))
2558 set_variable(V_SAVE_BY_SENDER, "yes", 1, 1, Main);
2559 obs_save_by_sender = !strucmp(VAR_SAVE_BY_SENDER, "yes");
2561 set_current_val(&vars[V_XOAUTH2_INFO], TRUE, TRUE);
2563 set_current_pattern_vals(ps);
2565 set_current_val(&vars[V_INDEX_FORMAT], TRUE, TRUE);
2566 init_index_format(VAR_INDEX_FORMAT, &ps->index_disp_format);
2568 /* this should come after pre441 is set or not */
2569 set_current_color_vals(ps);
2571 set_current_val(&vars[V_RSS_NEWS], TRUE, TRUE);
2572 set_current_val(&vars[V_RSS_WEATHER], TRUE, TRUE);
2573 set_current_val(&vars[V_WP_INDEXHEIGHT], TRUE, TRUE);
2574 set_current_val(&vars[V_WP_INDEXLINES], TRUE, TRUE);
2575 set_current_val(&vars[V_WP_AGGSTATE], TRUE, TRUE);
2576 set_current_val(&vars[V_WP_STATE], TRUE, TRUE);
2577 set_current_val(&vars[V_WP_COLUMNS], TRUE, TRUE);
2579 set_current_val(&vars[V_PRUNED_FOLDERS], TRUE, TRUE);
2580 set_current_val(&vars[V_ARCHIVED_FOLDERS], TRUE, TRUE);
2581 set_current_val(&vars[V_INCOMING_FOLDERS], TRUE, TRUE);
2582 set_current_val(&vars[V_SORT_KEY], TRUE, TRUE);
2583 if(decode_sort(VAR_SORT_KEY, &ps->def_sort, &def_sort_rev) == -1){
2584 snprintf(tmp_20k_buf, SIZEOF_20KBUF, "Sort type \"%.200s\" is invalid", VAR_SORT_KEY);
2585 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2586 ps->def_sort = SortArrival;
2587 ps->def_sort_rev = 0;
2589 else
2590 ps->def_sort_rev = def_sort_rev;
2592 cur_rule_value(&vars[V_SAVED_MSG_NAME_RULE], TRUE, TRUE);
2593 {NAMEVAL_S *v; int i;
2594 for(i = 0; (v = save_msg_rules(i)); i++)
2595 if(v->value == ps_global->save_msg_rule)
2596 break;
2598 /* if save_msg_rule is not default, or is explicitly set to default */
2599 if((ps_global->save_msg_rule != SAV_RULE_DEFLT) ||
2600 (v && v->name &&
2601 (!strucmp(ps_global->vars[V_SAVED_MSG_NAME_RULE].post_user_val.p,
2602 v->name) ||
2603 !strucmp(ps_global->vars[V_SAVED_MSG_NAME_RULE].main_user_val.p,
2604 v->name))))
2605 obs_save_by_sender = 0; /* don't overwrite */
2608 cur_rule_value(&vars[V_FCC_RULE], TRUE, TRUE);
2609 cur_rule_value(&vars[V_AB_SORT_RULE], TRUE, TRUE);
2611 #ifndef _WINDOWS
2612 cur_rule_value(&vars[V_COLOR_STYLE], TRUE, TRUE);
2613 #endif
2615 cur_rule_value(&vars[V_INDEX_COLOR_STYLE], TRUE, TRUE);
2616 cur_rule_value(&vars[V_TITLEBAR_COLOR_STYLE], TRUE, TRUE);
2617 cur_rule_value(&vars[V_FLD_SORT_RULE], TRUE, TRUE);
2618 cur_rule_value(&vars[V_INCOMING_STARTUP], TRUE, TRUE);
2619 cur_rule_value(&vars[V_PRUNING_RULE], TRUE, TRUE);
2620 cur_rule_value(&vars[V_REOPEN_RULE], TRUE, TRUE);
2621 cur_rule_value(&vars[V_GOTO_DEFAULT_RULE], TRUE, TRUE);
2622 cur_rule_value(&vars[V_THREAD_DISP_STYLE], TRUE, TRUE);
2623 cur_rule_value(&vars[V_THREAD_INDEX_STYLE], TRUE, TRUE);
2625 set_current_val(&vars[V_THREAD_MORE_CHAR], TRUE, TRUE);
2626 if(VAR_THREAD_MORE_CHAR[0] && VAR_THREAD_MORE_CHAR[1]){
2627 init_error(ps, SM_ORDER | SM_DING, 3, 5,
2628 _("Only using first character of threading-indicator-character option"));
2629 VAR_THREAD_MORE_CHAR[1] = '\0';
2632 set_current_val(&vars[V_THREAD_EXP_CHAR], TRUE, TRUE);
2633 if(VAR_THREAD_EXP_CHAR[0] && VAR_THREAD_EXP_CHAR[1]){
2634 init_error(ps, SM_ORDER | SM_DING, 3, 5,
2635 _("Only using first character of threading-expanded-character option"));
2636 VAR_THREAD_EXP_CHAR[1] = '\0';
2639 set_current_val(&vars[V_THREAD_LASTREPLY_CHAR], TRUE, TRUE);
2640 if(!VAR_THREAD_LASTREPLY_CHAR[0])
2641 VAR_THREAD_LASTREPLY_CHAR = cpystr(DF_THREAD_LASTREPLY_CHAR);
2643 if(VAR_THREAD_LASTREPLY_CHAR[0] && VAR_THREAD_LASTREPLY_CHAR[1]){
2644 init_error(ps, SM_ORDER | SM_DING, 3, 5,
2645 _("Only using first character of threading-lastreply-character option"));
2646 VAR_THREAD_LASTREPLY_CHAR[1] = '\0';
2649 set_current_val(&vars[V_MAXREMSTREAM], TRUE, TRUE);
2650 ps->s_pool.max_remstream = i = atoi(DF_MAXREMSTREAM);
2651 if(SVAR_MAXREMSTREAM(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2652 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2653 else
2654 ps->s_pool.max_remstream = i;
2656 set_current_val(&vars[V_PERMLOCKED], TRUE, TRUE);
2658 set_current_val(&vars[V_NMW_WIDTH], TRUE, TRUE);
2659 ps->nmw_width = i = atoi(DF_NMW_WIDTH);
2660 if(SVAR_NMW_WIDTH(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2661 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2662 else
2663 ps->nmw_width = i;
2665 /* backwards compatibility */
2666 if(obs_save_by_sender){
2667 ps->save_msg_rule = SAV_RULE_FROM;
2668 set_variable(V_SAVED_MSG_NAME_RULE, "by-from", 1, 1, Main);
2671 /* this should come after process_feature_list because of use_fkeys */
2672 if(!ps->start_in_index)
2673 set_current_val(&vars[V_INIT_CMD_LIST], FALSE, TRUE);
2674 if(VAR_INIT_CMD_LIST && VAR_INIT_CMD_LIST[0] && VAR_INIT_CMD_LIST[0][0])
2675 if(cmds_f)
2676 (*cmds_f)(ps, VAR_INIT_CMD_LIST);
2678 #ifdef _WINDOWS
2679 mswin_set_quit_confirm (F_OFF(F_QUIT_WO_CONFIRM, ps_global));
2680 #endif /* _WINDOWS */
2682 #ifdef DEBUG
2683 dump_configuration(0);
2684 #endif /* DEBUG */
2688 void
2689 convert_configvars_to_utf8(struct variable *vars, char *fromcharset)
2691 struct variable *v;
2694 * Make sure that everything is UTF-8.
2696 for(v = vars; v->name; v++)
2697 convert_configvar_to_utf8(v, fromcharset);
2701 void
2702 convert_configvar_to_utf8(struct variable *v, char *fromcharset)
2704 char **p, *conv, **valptr;
2705 int i;
2708 * Make sure that everything is UTF-8.
2710 if(v->is_list){
2711 for(i = 0; i < 7; i++){
2712 switch(i){
2713 case 1: valptr = v->current_val.l; break;
2714 case 0: valptr = v->main_user_val.l; break;
2715 case 2: valptr = v->changed_val.l; break;
2716 case 3: valptr = v->post_user_val.l; break;
2717 case 4: valptr = v->global_val.l; break;
2718 case 5: valptr = v->fixed_val.l; break;
2719 case 6: valptr = v->cmdline_val.l; break;
2720 default: alpine_panic("bad case in convert_configvar");
2723 if(valptr){
2724 for(p = valptr; *p; p++){
2725 if(**p){
2726 conv = convert_to_utf8(*p, fromcharset, 0);
2727 if(conv){
2728 fs_give((void **) p);
2729 *p = conv;
2736 else{
2737 for(i = 0; i < 7; i++){
2738 switch(i){
2739 case 1: valptr = &v->current_val.p; break;
2740 case 0: valptr = &v->main_user_val.p; break;
2741 case 2: valptr = &v->changed_val.p; break;
2742 case 3: valptr = &v->post_user_val.p; break;
2743 case 4: valptr = &v->global_val.p; break;
2744 case 5: valptr = &v->fixed_val.p; break;
2745 case 6: valptr = &v->cmdline_val.p; break;
2746 default: alpine_panic("bad case in convert_configvar");
2749 if(valptr && *valptr && (*valptr)[0]){
2750 conv = convert_to_utf8(*valptr, fromcharset, 0);
2751 if(conv){
2752 fs_give((void **) valptr);
2753 *valptr = conv;
2763 * Standard feature name sections
2765 char *
2766 feature_list_section(FEATURE_S *feature)
2768 #define PREF_NONE -1
2769 static char *feat_sect[] = {
2770 #define PREF_MISC 0
2771 /* TRANSLATORS: section heading in configuration screen */
2772 N_("Advanced User Preferences"),
2773 #define PREF_FLDR 1
2774 /* TRANSLATORS: section heading in configuration screen */
2775 N_("Folder Preferences"),
2776 #define PREF_ADDR 2
2777 /* TRANSLATORS: section heading in configuration screen */
2778 N_("Address Book Preferences"),
2779 #define PREF_COMP 3
2780 /* TRANSLATORS: section heading in configuration screen */
2781 N_("Composer Preferences"),
2782 #define PREF_NEWS 4
2783 /* TRANSLATORS: section heading in configuration screen */
2784 N_("News Preferences"),
2785 #define PREF_VIEW 5
2786 /* TRANSLATORS: section heading in configuration screen */
2787 N_("Viewer Preferences"),
2788 #define PREF_ACMD 6
2789 /* TRANSLATORS: section heading in configuration screen */
2790 N_("Advanced Command Preferences"),
2791 #define PREF_PRNT 7
2792 /* TRANSLATORS: section heading in configuration screen */
2793 N_("Printer Preferences"),
2794 #define PREF_RPLY 8
2795 /* TRANSLATORS: section heading in configuration screen */
2796 N_("Reply Preferences"),
2797 #define PREF_SEND 9
2798 /* TRANSLATORS: section heading in configuration screen */
2799 N_("Sending Preferences"),
2800 #define PREF_INDX 10
2801 /* TRANSLATORS: section heading in configuration screen */
2802 N_("Message Index Preferences"),
2803 #define PREF_HIDDEN 11
2804 HIDDEN_PREF
2807 return((feature && feature->section > PREF_NONE
2808 && feature->section < (sizeof(feat_sect)/sizeof(feat_sect[0])))
2809 ? _(feat_sect[feature->section]) : NULL);
2813 /* any os-specific exclusions */
2814 #if defined(DOS) || defined(OS2)
2815 #define PREF_OS_LWSD PREF_NONE
2816 #define PREF_OS_LCLK PREF_NONE
2817 #define PREF_OS_STSP PREF_NONE
2818 #define PREF_OS_SPWN PREF_NONE
2819 #define PREF_OS_XNML PREF_NONE
2820 #define PREF_OS_USFK PREF_MISC
2821 #define PREF_OS_MOUSE PREF_NONE
2822 #else
2823 #define PREF_OS_LWSD PREF_MISC
2824 #define PREF_OS_LCLK PREF_COMP
2825 #define PREF_OS_STSP PREF_MISC
2826 #define PREF_OS_SPWN PREF_MISC
2827 #define PREF_OS_XNML PREF_MISC
2828 #define PREF_OS_USFK PREF_NONE
2829 #define PREF_OS_MOUSE PREF_MISC
2830 #endif
2834 * Standard way to get at feature list members...
2836 FEATURE_S *
2837 feature_list(int index)
2840 * This list is alphabatized by feature string, but the
2841 * macro values need not be ordered.
2843 static FEATURE_S feat_list[] = {
2844 /* Composer prefs */
2845 {"allow-changing-from", NULL,
2846 F_ALLOW_CHANGING_FROM, h_config_allow_chg_from, PREF_COMP, 1},
2847 {"alternate-compose-menu", NULL,
2848 F_ALT_COMPOSE_MENU, h_config_alt_compose_menu, PREF_COMP, 0},
2849 {"alternate-role-menu", "Alternate Role (#) Menu",
2850 F_ALT_ROLE_MENU, h_config_alt_role_menu, PREF_COMP, 0},
2851 {"compose-cancel-confirm-uses-yes", NULL,
2852 F_CANCEL_CONFIRM, h_config_cancel_confirm, PREF_COMP, 0},
2853 {"compose-rejects-unqualified-addrs", "Compose Rejects Unqualified Addresses",
2854 F_COMPOSE_REJECTS_UNQUAL, h_config_compose_rejects_unqual, PREF_COMP, 0},
2855 {"compose-send-offers-first-filter", NULL,
2856 F_FIRST_SEND_FILTER_DFLT, h_config_send_filter_dflt, PREF_COMP, 0},
2857 {"compose-cut-from-cursor", "Ctrl-K Cuts From Cursor",
2858 F_DEL_FROM_DOT, h_config_del_from_dot, PREF_COMP, 0},
2859 {"compose-maps-delete-key-to-ctrl-d", "Delete Key Maps to Ctrl-D",
2860 F_COMPOSE_MAPS_DEL, h_config_compose_maps_del, PREF_COMP, 0},
2861 {"quell-dead-letter-on-cancel", "Do Not Save to Deadletter on Cancel",
2862 F_QUELL_DEAD_LETTER, h_config_quell_dead_letter, PREF_COMP, 0},
2863 {"enable-alternate-editor-cmd", "Enable Alternate Editor Command",
2864 F_ENABLE_ALT_ED, h_config_enable_alt_ed, PREF_COMP, 1},
2865 {"enable-alternate-editor-implicitly", NULL,
2866 F_ALT_ED_NOW, h_config_alt_ed_now, PREF_COMP, 0},
2867 {"enable-search-and-replace", "Enable Search and Replace",
2868 F_ENABLE_SEARCH_AND_REPL, h_config_enable_search_and_repl, PREF_COMP, 1},
2869 {"enable-sigdashes", NULL,
2870 F_ENABLE_SIGDASHES, h_config_sigdashes, PREF_COMP, 0},
2871 {"quell-mailchecks-composing-except-inbox", "Prevent Mailchecks While Composing Except for INBOX",
2872 F_QUELL_PINGS_COMPOSING, h_config_quell_checks_comp, PREF_COMP, 0},
2873 {"quell-mailchecks-composing-inbox", "Prevent Mailchecks While Composing for INBOX",
2874 F_QUELL_PINGS_COMPOSING_INBOX, h_config_quell_checks_comp_inbox, PREF_COMP, 0},
2875 {"quell-user-lookup-in-passwd-file", "Prevent User Lookup in Password File",
2876 F_QUELL_LOCAL_LOOKUP, h_config_quell_local_lookup, PREF_OS_LCLK, 0},
2877 {"spell-check-before-sending", NULL,
2878 F_ALWAYS_SPELL_CHECK, h_config_always_spell_check, PREF_COMP, 0},
2880 /* Reply Prefs */
2881 {"alternate-reply-menu", NULL,
2882 F_ALT_REPLY_MENU, h_config_alt_reply_menu, PREF_RPLY, 0},
2883 {"copy-to-address-to-from-if-it-is-us", "Copy To Address to From if it is Us",
2884 F_COPY_TO_TO_FROM, h_config_copy_to_to_from, PREF_RPLY, 0},
2885 {"enable-reply-indent-string-editing", NULL,
2886 F_ENABLE_EDIT_REPLY_INDENT, h_config_prefix_editing, PREF_RPLY, 0},
2887 {"include-attachments-in-reply", "Include Attachments in Reply",
2888 F_ATTACHMENTS_IN_REPLY, h_config_attach_in_reply, PREF_RPLY, 0},
2889 {"include-header-in-reply", "Include Header in Reply",
2890 F_INCLUDE_HEADER, h_config_include_header, PREF_RPLY, 0},
2891 {"include-text-in-reply", "Include Text in Reply",
2892 F_AUTO_INCLUDE_IN_REPLY, h_config_auto_include_reply, PREF_RPLY, 0},
2893 {"reply-always-uses-reply-to", "Reply Always Uses Reply-To",
2894 F_AUTO_REPLY_TO, h_config_auto_reply_to, PREF_RPLY, 0},
2895 {"signature-at-bottom", "Signature at Bottom",
2896 F_SIG_AT_BOTTOM, h_config_sig_at_bottom, PREF_RPLY, 0},
2897 {"strip-from-sigdashes-on-reply", "Strip From Sigdashes on Reply",
2898 F_ENABLE_STRIP_SIGDASHES, h_config_strip_sigdashes, PREF_RPLY, 0},
2899 {"forward-as-attachment", "Forward messages as attachments",
2900 F_FORWARD_AS_ATTACHMENT, h_config_forward_as_attachment, PREF_RPLY, 0},
2901 {"preserve-original-fields", NULL,
2902 F_PRESERVE_ORIGINAL_FIELD, h_config_preserve_field, PREF_RPLY, 0},
2904 /* Sending Prefs */
2905 {"disable-sender", "Do Not Generate Sender Header",
2906 F_DISABLE_SENDER, h_config_disable_sender, PREF_SEND, 0},
2907 {"use-sender-not-x-sender", "Use Sender Instead of X-X-Sender",
2908 F_USE_SENDER_NOT_X, h_config_use_sender_not_x, PREF_SEND, 0},
2909 {"quell-flowed-text", "Do Not Send Flowed Text",
2910 F_QUELL_FLOWED_TEXT, h_config_quell_flowed_text, PREF_SEND, 0},
2911 {"downgrade-multipart-to-text", "Downgrade Multipart to Text",
2912 F_COMPOSE_ALWAYS_DOWNGRADE, h_downgrade_multipart_to_text, PREF_SEND, 0},
2913 {"enable-8bit-esmtp-negotiation", "Enable 8bit ESMTP Negotiation",
2914 F_ENABLE_8BIT, h_config_8bit_smtp, PREF_SEND, 1},
2915 #ifdef BACKGROUND_POST
2916 {"enable-background-sending", NULL,
2917 F_BACKGROUND_POST, h_config_compose_bg_post, PREF_SEND, 0},
2918 #endif
2919 {"enable-delivery-status-notification", NULL,
2920 F_DSN, h_config_compose_dsn, PREF_SEND, 0},
2921 {"enable-verbose-smtp-posting", "Enable Verbose SMTP Posting",
2922 F_VERBOSE_POST, h_config_verbose_post, PREF_SEND, 0},
2923 {"fcc-without-attachments", "Fcc Does Not Include Attachments",
2924 F_NO_FCC_ATTACH, h_config_no_fcc_attach, PREF_SEND, 0},
2925 {"fcc-on-bounce", "Include Fcc When Bouncing Messages",
2926 F_FCC_ON_BOUNCE, h_config_fcc_on_bounce, PREF_SEND, 0},
2927 {"mark-fcc-seen", NULL,
2928 F_MARK_FCC_SEEN, h_config_mark_fcc_seen, PREF_SEND, 0},
2929 {"fcc-only-without-confirm", "Send to Fcc Only Without Confirming",
2930 F_AUTO_FCC_ONLY, h_config_auto_fcc_only, PREF_SEND, 0},
2931 {"send-without-confirm", "Send Without Confirming",
2932 F_SEND_WO_CONFIRM, h_config_send_wo_confirm, PREF_SEND, 0},
2933 {"strip-whitespace-before-send", "Strip Whitespace Before Sending",
2934 F_STRIP_WS_BEFORE_SEND, h_config_strip_ws_before_send, PREF_SEND, 0},
2935 {"warn-if-blank-fcc", "Warn if Blank Fcc",
2936 F_WARN_ABOUT_NO_FCC, h_config_warn_if_fcc_blank, PREF_SEND, 0},
2937 {"warn-if-blank-subject", "Warn if Blank Subject",
2938 F_WARN_ABOUT_NO_SUBJECT, h_config_warn_if_subj_blank, PREF_SEND, 0},
2939 {"warn-if-blank-to-and-cc-and-newsgroups", "Warn if Blank To and CC and Newsgroups",
2940 F_WARN_ABOUT_NO_TO_OR_CC, h_config_warn_if_no_to_or_cc, PREF_SEND, 0},
2942 /* Folder */
2943 {"combined-folder-display", NULL,
2944 F_CMBND_FOLDER_DISP, h_config_combined_folder_display, PREF_FLDR, 0},
2945 {"combined-subdirectory-display", NULL,
2946 F_CMBND_SUBDIR_DISP, h_config_combined_subdir_display, PREF_FLDR, 0},
2947 {"enable-lame-list-mode", "Compensate for Deficient IMAP servers",
2948 F_FIX_BROKEN_LIST, h_config_lame_list_mode, PREF_FLDR, 0},
2949 {"enable-dot-folders", "Enable Hidden Folders",
2950 F_ENABLE_DOT_FOLDERS, h_config_enable_dot_folders, PREF_FLDR, 0},
2951 {"enable-incoming-folders", "Enable Incoming Folders Collection",
2952 F_ENABLE_INCOMING, h_config_enable_incoming, PREF_FLDR, 0},
2953 {"enable-incoming-folders-checking", NULL,
2954 F_ENABLE_INCOMING_CHECKING, h_config_enable_incoming_checking, PREF_FLDR, 0},
2955 {"incoming-checking-includes-total", NULL,
2956 F_INCOMING_CHECKING_TOTAL, h_config_incoming_checking_total, PREF_FLDR, 0},
2957 {"incoming-checking-uses-recent", NULL,
2958 F_INCOMING_CHECKING_RECENT, h_config_incoming_checking_recent, PREF_FLDR, 0},
2959 {"expanded-view-of-folders", "Expanded View of Folders",
2960 F_EXPANDED_FOLDERS, h_config_expanded_folders, PREF_FLDR, 0},
2961 {"quell-empty-directories", "Hide Empty Directories",
2962 F_QUELL_EMPTY_DIRS, h_config_quell_empty_dirs, PREF_FLDR, 0},
2963 {"separate-folder-and-directory-entries", "Separate Folder and Directory Entries",
2964 F_SEPARATE_FLDR_AS_DIR, h_config_separate_fold_dir_view, PREF_FLDR, 0},
2965 {"single-column-folder-list", NULL,
2966 F_SINGLE_FOLDER_LIST, h_config_single_list, PREF_FLDR, 0},
2967 {"sort-default-fcc-alpha", "Sort Default Fcc Folder Alphabetically",
2968 F_SORT_DEFAULT_FCC_ALPHA, h_config_sort_fcc_alpha, PREF_FLDR, 0},
2969 {"sort-default-save-alpha", "Sort Default Save Folder Alphabetically",
2970 F_SORT_DEFAULT_SAVE_ALPHA, h_config_sort_save_alpha, PREF_FLDR, 0},
2971 {"vertical-folder-list", "Use Vertical Folder List",
2972 F_VERTICAL_FOLDER_LIST, h_config_vertical_list, PREF_FLDR, 0},
2974 /* Addr book */
2975 {"combined-addrbook-display", "Combined Address Book Display",
2976 F_CMBND_ABOOK_DISP, h_config_combined_abook_display, PREF_ADDR, 0},
2977 {"expanded-view-of-addressbooks", "Expanded View of Address Books",
2978 F_EXPANDED_ADDRBOOKS, h_config_expanded_addrbooks, PREF_ADDR, 0},
2979 {"expanded-view-of-distribution-lists", "Expanded View of Distribution Lists",
2980 F_EXPANDED_DISTLISTS, h_config_expanded_distlists, PREF_ADDR, 0},
2981 #ifdef ENABLE_LDAP
2982 {"ldap-result-to-addrbook-add", "LDAP Result to Addressbook Add",
2983 F_ADD_LDAP_TO_ABOOK, h_config_add_ldap, PREF_ADDR, 0},
2984 #endif
2986 /* Index prefs */
2987 {"auto-open-next-unread", NULL,
2988 F_AUTO_OPEN_NEXT_UNREAD, h_config_auto_open_unread, PREF_INDX, 0},
2989 {"continue-tab-without-confirm", "Continue NextNew Without Confirming",
2990 F_TAB_NO_CONFIRM, h_config_tab_no_prompt, PREF_INDX, 0},
2991 {"convert-dates-to-localtime", NULL,
2992 F_DATES_TO_LOCAL, h_config_dates_to_local, PREF_INDX, 0},
2993 {"delete-skips-deleted", NULL,
2994 F_DEL_SKIPS_DEL, h_config_del_skips_del, PREF_INDX, 1},
2995 {"disable-index-locale-dates", NULL,
2996 F_DISABLE_INDEX_LOCALE_DATES, h_config_disable_index_locale_dates, PREF_INDX, 0},
2997 {"enable-cruise-mode", NULL,
2998 F_ENABLE_SPACE_AS_TAB, h_config_cruise_mode, PREF_INDX, 0},
2999 {"enable-cruise-mode-delete", "Enable Cruise Mode With Deleting",
3000 F_ENABLE_TAB_DELETES, h_config_cruise_mode_delete, PREF_INDX, 0},
3001 {"mark-for-cc", "Mark for CC",
3002 F_MARK_FOR_CC, h_config_mark_for_cc, PREF_INDX, 1},
3003 {"next-thread-without-confirm", "Read Next Thread Without Confirming",
3004 F_NEXT_THRD_WO_CONFIRM, h_config_next_thrd_wo_confirm, PREF_INDX, 0},
3005 {"return-to-inbox-without-confirm", "Return to INBOX Without Confirming",
3006 F_RET_INBOX_NO_CONFIRM, h_config_inbox_no_confirm, PREF_INDX, 0},
3007 {"show-sort", "Show Sort in Titlebar",
3008 F_SHOW_SORT, h_config_show_sort, PREF_INDX, 0},
3009 {"tab-uses-unseen-for-next-folder", "Tab Uses Unseen for Next Folder",
3010 F_TAB_USES_UNSEEN, h_config_tab_uses_unseen, PREF_INDX, 0},
3011 {"tab-visits-next-new-message-only", NULL,
3012 F_TAB_TO_NEW, h_config_tab_new_only, PREF_INDX, 0},
3013 {"thread-index-shows-important-color", NULL,
3014 F_COLOR_LINE_IMPORTANT, h_config_color_thrd_import, PREF_INDX, 0},
3015 {"thread-sorts-by-arrival", "Thread Sorts by Arrival",
3016 F_THREAD_SORTS_BY_ARRIVAL, h_config_thread_sorts_by_arrival, PREF_INDX, 0},
3018 /* Viewer prefs */
3019 {"enable-msg-view-addresses", "Enable Message View Address Links",
3020 F_SCAN_ADDR, h_config_enable_view_addresses, PREF_VIEW, 0},
3021 {"enable-msg-view-attachments", "Enable Message View Attachment Links",
3022 F_VIEW_SEL_ATTACH, h_config_enable_view_attach, PREF_VIEW, 0},
3023 {"enable-msg-view-urls", "Enable Message View URL Links",
3024 F_VIEW_SEL_URL, h_config_enable_view_url, PREF_VIEW, 1},
3025 {"enable-msg-view-web-hostnames", "Enable Message View Web Hostname Links",
3026 F_VIEW_SEL_URL_HOST, h_config_enable_view_web_host, PREF_VIEW, 1},
3027 {"enable-msg-view-forced-arrows", "Enable Message View Forced Arrows",
3028 F_FORCE_ARROWS, h_config_enable_view_arrows, PREF_VIEW, 0},
3029 /* set to TRUE for windows */
3030 {"pass-c1-control-characters-as-is", NULL,
3031 F_PASS_C1_CONTROL_CHARS, h_config_pass_c1_control, PREF_VIEW, 0},
3032 {"pass-control-characters-as-is", NULL,
3033 F_PASS_CONTROL_CHARS, h_config_pass_control, PREF_VIEW, 0},
3034 {"prefer-plain-text", NULL,
3035 F_PREFER_PLAIN_TEXT, h_config_prefer_plain_text, PREF_VIEW, 0},
3036 {"quell-charset-warning", "Suppress Character Set Warning",
3037 F_QUELL_CHARSET_WARNING, h_config_quell_charset_warning, PREF_VIEW, 0},
3038 {"quell-server-after-link-in-html", "Suppress Server After Link in HTML",
3039 F_QUELL_HOST_AFTER_URL, h_config_quell_host_after_url, PREF_VIEW, 0},
3041 /* News */
3042 {"compose-sets-newsgroup-without-confirm", "Compose Sets Newsgroup Without Confirming",
3043 F_COMPOSE_TO_NEWSGRP, h_config_compose_news_wo_conf, PREF_NEWS, 0},
3044 {"enable-8bit-nntp-posting", "Enable 8bit NNTP Posting",
3045 F_ENABLE_8BIT_NNTP, h_config_8bit_nntp, PREF_NEWS, 0},
3046 {"enable-multiple-newsrcs", NULL,
3047 F_ENABLE_MULNEWSRCS, h_config_enable_mulnewsrcs, PREF_NEWS, 0},
3048 {"mult-newsrc-hostnames-as-typed", "Multiple Newsrc Hostnames as Typed",
3049 F_MULNEWSRC_HOSTNAMES_AS_TYPED, h_config_mulnews_as_typed, PREF_NEWS, 0},
3050 {"hide-nntp-path", "Hide NNTP Path",
3051 F_HIDE_NNTP_PATH, h_config_hide_nntp_path, PREF_NEWS, 0},
3052 {"news-approximates-new-status", NULL,
3053 F_FAKE_NEW_IN_NEWS, h_config_news_uses_recent, PREF_NEWS, 1},
3054 {"news-deletes-across-groups", NULL,
3055 F_NEWS_CROSS_DELETE, h_config_news_cross_deletes, PREF_NEWS, 0},
3056 {"news-offers-catchup-on-close", "News Offers Catchup on Close",
3057 F_NEWS_CATCHUP, h_config_news_catchup, PREF_NEWS, 0},
3058 {"news-post-without-validation", NULL,
3059 F_NO_NEWS_VALIDATION, h_config_post_wo_validation, PREF_NEWS, 0},
3060 {"news-read-in-newsrc-order", "News Read in Newsrc Order",
3061 F_READ_IN_NEWSRC_ORDER, h_config_read_in_newsrc_order, PREF_NEWS, 0},
3062 {"nntp-search-uses-overview", "NNTP Search Uses Overview",
3063 F_NNTP_SEARCH_USES_OVERVIEW, h_config_nntp_search_uses_overview, PREF_NEWS, 1},
3064 {"predict-nntp-server", "Predict NNTP Server",
3065 F_PREDICT_NNTP_SERVER, h_config_predict_nntp_server, PREF_NEWS, 0},
3066 {"quell-extra-post-prompt", "Suppress Extra Posting Prompt",
3067 F_QUELL_EXTRA_POST_PROMPT, h_config_quell_post_prompt, PREF_NEWS, 0},
3069 /* Print */
3070 {"enable-print-via-y-command", NULL,
3071 F_ENABLE_PRYNT, h_config_enable_y_print, PREF_PRNT, 0},
3072 {"print-formfeed-between-messages", NULL,
3073 F_AGG_PRINT_FF, h_config_ff_between_msgs, PREF_PRNT, 0},
3074 {"print-includes-from-line", NULL,
3075 F_FROM_DELIM_IN_PRINT, h_config_print_from, PREF_PRNT, 0},
3076 {"print-index-enabled", NULL,
3077 F_PRINT_INDEX, h_config_print_index, PREF_PRNT, 0},
3078 {"print-offers-custom-cmd-prompt", "Print Offers Custom Command Prompt",
3079 F_CUSTOM_PRINT, h_config_custom_print, PREF_PRNT, 0},
3081 /* adv cmd prefs */
3082 {"enable-aggregate-command-set", NULL,
3083 F_ENABLE_AGG_OPS, h_config_enable_agg_ops, PREF_ACMD, 1},
3084 {"enable-arrow-navigation", NULL,
3085 F_ARROW_NAV, h_config_arrow_nav, PREF_ACMD, 1},
3086 {"enable-arrow-navigation-relaxed", NULL,
3087 F_RELAXED_ARROW_NAV, h_config_relaxed_arrow_nav, PREF_ACMD, 1},
3088 {"enable-bounce-cmd", "Enable Bounce Command",
3089 F_ENABLE_BOUNCE, h_config_enable_bounce, PREF_ACMD, 1},
3090 {"enable-exit-via-lessthan-command", NULL,
3091 F_ENABLE_LESSTHAN_EXIT, h_config_enable_lessthan_exit, PREF_ACMD, 1},
3092 {"enable-flag-cmd", "Enable Flag Command",
3093 F_ENABLE_FLAG, h_config_enable_flag, PREF_ACMD, 1},
3094 {"enable-flag-screen-implicitly", NULL,
3095 F_FLAG_SCREEN_DFLT, h_config_flag_screen_default, PREF_ACMD, 0},
3096 {"enable-flag-screen-keyword-shortcut", NULL,
3097 F_FLAG_SCREEN_KW_SHORTCUT, h_config_flag_screen_kw_shortcut,PREF_ACMD, 1},
3098 {"enable-full-header-and-text", "Enable Full Header and Text",
3099 F_ENABLE_FULL_HDR_AND_TEXT, h_config_enable_full_hdr_and_text, PREF_ACMD, 0},
3100 {"enable-full-header-cmd", "Enable Full Header Command",
3101 F_ENABLE_FULL_HDR, h_config_enable_full_hdr, PREF_ACMD, 1},
3102 {"enable-goto-in-file-browser", "Enable Goto in File Browser",
3103 F_ALLOW_GOTO, h_config_allow_goto, PREF_ACMD, 1},
3104 {"enable-jump-shortcut", NULL,
3105 F_ENABLE_JUMP, h_config_enable_jump, PREF_ACMD, 1},
3106 {"enable-partial-match-lists", NULL,
3107 F_ENABLE_SUB_LISTS, h_config_sub_lists, PREF_ACMD, 1},
3108 {"enable-tab-completion", NULL,
3109 F_ENABLE_TAB_COMPLETE, h_config_enable_tab_complete, PREF_ACMD, 1},
3110 {"enable-unix-pipe-cmd", "Enable Unix Pipe Command",
3111 F_ENABLE_PIPE, h_config_enable_pipe, PREF_ACMD, 1},
3112 {"quell-full-header-auto-reset", "Suppress Full Header Auto Reset",
3113 F_QUELL_FULL_HDR_RESET, h_config_quell_full_hdr_reset, PREF_ACMD, 0},
3115 /* Adv user prefs */
3116 #if !defined(DOS) && !defined(OS2)
3117 {"allow-talk", NULL,
3118 F_ALLOW_TALK, h_config_allow_talk, PREF_MISC, 0},
3119 #endif
3120 {"assume-slow-link", NULL,
3121 F_FORCE_LOW_SPEED, h_config_force_low_speed, PREF_OS_LWSD, 0},
3122 {"auto-move-read-msgs", "Auto Move Read Messages",
3123 F_AUTO_READ_MSGS, h_config_auto_read_msgs, PREF_MISC, 0},
3124 {"auto-unselect-after-apply", NULL,
3125 F_AUTO_UNSELECT, h_config_auto_unselect, PREF_MISC, 0},
3126 {"auto-unzoom-after-apply", NULL,
3127 F_AUTO_UNZOOM, h_config_auto_unzoom, PREF_MISC, 1},
3128 {"auto-zoom-after-select", NULL,
3129 F_AUTO_ZOOM, h_config_auto_zoom, PREF_MISC, 1},
3130 {"busy-cue-spinner-only", NULL,
3131 F_USE_BORING_SPINNER, h_config_use_boring_spinner, PREF_MISC, 0},
3132 {"check-newmail-when-quitting", NULL,
3133 F_CHECK_MAIL_ONQUIT, h_config_check_mail_onquit, PREF_MISC, 0},
3134 {"confirm-role-even-for-default", "Confirm Role Even for Default",
3135 F_ROLE_CONFIRM_DEFAULT, h_config_confirm_role, PREF_MISC, 0},
3136 {"disable-keymenu", NULL,
3137 F_BLANK_KEYMENU, h_config_blank_keymenu, PREF_MISC, 0},
3138 {"disable-password-caching", NULL,
3139 F_DISABLE_PASSWORD_CACHING, h_config_disable_password_caching,
3140 PREF_MISC, 0},
3141 #ifdef LOCAL_PASSWD_CACHE
3142 {"disable-password-file-saving", NULL,
3143 F_DISABLE_PASSWORD_FILE_SAVING, h_config_disable_password_file_saving,
3144 PREF_MISC, 0},
3145 #endif /* LOCAL_PASSWD_CACHE */
3146 {"disable-regular-expression-matching-for-alternate-addresses", NULL,
3147 F_DISABLE_REGEX, h_config_disable_regex, PREF_MISC, 0},
3148 {"disable-save-input-history", NULL,
3149 F_DISABLE_SAVE_INPUT_HISTORY, h_config_input_history, PREF_MISC, 0},
3150 {"disable-take-fullname-in-addresses", "Disable Take Fullname in Addresses",
3151 F_DISABLE_TAKE_FULLNAMES, h_config_take_fullname, PREF_MISC, 0},
3152 {"disable-take-last-comma-first", NULL,
3153 F_DISABLE_TAKE_LASTFIRST, h_config_take_lastfirst, PREF_MISC, 0},
3154 {"disable-terminal-reset-for-display-filters", "Disable Terminal Reset for Display Filters",
3155 F_DISABLE_TERM_RESET_DISP, h_config_disable_reset_disp, PREF_MISC, 0},
3156 {"enable-dot-files", NULL,
3157 F_ENABLE_DOT_FILES, h_config_enable_dot_files, PREF_MISC, 0},
3158 {"enable-fast-recent-test", NULL,
3159 F_ENABLE_FAST_RECENT, h_config_fast_recent, PREF_MISC, 0},
3160 {"enable-mail-check-cue", NULL,
3161 F_SHOW_DELAY_CUE, h_config_show_delay_cue, PREF_MISC, 0},
3162 {"enable-mailcap-param-substitution", "Enable Mailcap Parameter Substitution",
3163 F_DO_MAILCAP_PARAM_SUBST, h_config_mailcap_params, PREF_MISC, 0},
3164 {"enable-mouse-in-xterm", "Enable Mouse in Xterm",
3165 F_ENABLE_MOUSE, h_config_enable_mouse, PREF_OS_MOUSE, 0},
3166 {"enable-newmail-in-xterm-icon", "Enable Newmail in Xterm Icon",
3167 F_ENABLE_XTERM_NEWMAIL, h_config_enable_xterm_newmail, PREF_OS_XNML, 0},
3168 {"enable-newmail-short-text-in-icon", "Enable Newmail Short Text in Icon",
3169 F_ENABLE_NEWMAIL_SHORT_TEXT, h_config_enable_newmail_short_text, PREF_OS_XNML, 0},
3170 {"enable-suspend", NULL,
3171 F_CAN_SUSPEND, h_config_can_suspend, PREF_MISC, 0},
3172 {"enable-take-export", NULL,
3173 F_ENABLE_TAKE_EXPORT, h_config_enable_take_export, PREF_MISC, 0},
3174 {"enable-rules-under-take", "Enable Take Rules",
3175 F_ENABLE_ROLE_TAKE, h_config_enable_role_take, PREF_MISC, 0},
3176 #ifdef _WINDOWS
3177 {"enable-tray-icon", NULL,
3178 F_ENABLE_TRAYICON, h_config_tray_icon, PREF_MISC, 0},
3179 #endif
3180 {"expose-hidden-config", NULL,
3181 F_EXPOSE_HIDDEN_CONFIG, h_config_expose_hidden_config, PREF_MISC, 0},
3182 {"expunge-only-manually", NULL,
3183 F_EXPUNGE_MANUALLY, h_config_expunge_manually, PREF_MISC, 0},
3184 {"expunge-without-confirm", "Expunge Without Confirming",
3185 F_AUTO_EXPUNGE, h_config_auto_expunge, PREF_MISC, 0},
3186 {"expunge-without-confirm-everywhere", "Expunge Without Confirming Everywhere",
3187 F_FULL_AUTO_EXPUNGE, h_config_full_auto_expunge, PREF_MISC, 0},
3188 {"force-arrow-cursor", NULL,
3189 F_FORCE_ARROW, h_config_force_arrow, PREF_MISC, 0},
3190 {"ignore-size-changes", NULL,
3191 F_IGNORE_SIZE, h_config_ignore_size, PREF_MISC, 0},
3192 {"maildrops-preserve-state", NULL,
3193 F_MAILDROPS_PRESERVE_STATE, h_config_maildrops_preserve_state,
3194 PREF_MISC, 0},
3195 {"offer-expunge-of-inbox", "Offer Expunge of INBOX",
3196 F_EXPUNGE_INBOX, h_config_expunge_inbox, PREF_MISC, 0},
3197 {"offer-expunge-of-stayopen-folders", "Offer Expunge of Stayopen Folders",
3198 F_EXPUNGE_STAYOPENS, h_config_expunge_stayopens, PREF_MISC, 0},
3199 {"preopen-stayopen-folders", NULL,
3200 F_PREOPEN_STAYOPENS, h_config_preopen_stayopens, PREF_MISC, 0},
3201 {"preserve-start-stop-characters", "Preserve Start/Stop Characters",
3202 F_PRESERVE_START_STOP, h_config_preserve_start_stop, PREF_OS_STSP, 0},
3203 {"quell-folder-internal-msg", "Prevent Folder Internal Message",
3204 F_QUELL_INTERNAL_MSG, h_config_quell_folder_internal_msg, PREF_MISC, 0},
3205 {"quell-partial-fetching", "Prevent Partial Fetching",
3206 F_QUELL_PARTIAL_FETCH, h_config_quell_partial, PREF_MISC, 0},
3207 {"prune-uses-yyyy-mm", "Prune Uses YYYY-MM",
3208 F_PRUNE_USES_ISO, h_config_prune_uses_iso, PREF_MISC, 0},
3209 {"quit-without-confirm", "Quit Without Confirming",
3210 F_QUIT_WO_CONFIRM, h_config_quit_wo_confirm, PREF_MISC, 0},
3211 {"quote-replace-nonflowed", NULL,
3212 F_QUOTE_REPLACE_NOFLOW, h_config_quote_replace_noflow, PREF_MISC, 0},
3213 {"save-aggregates-copy-sequence", "Save Combines Copies (may be out of order)",
3214 F_AGG_SEQ_COPY, h_config_save_aggregates, PREF_MISC, 1},
3215 {"save-partial-msg-without-confirm", "Save Partial Message Without Confirming",
3216 F_SAVE_PARTIAL_WO_CONFIRM, h_config_save_part_wo_confirm, PREF_MISC, 0},
3217 {"save-will-advance", NULL,
3218 F_SAVE_ADVANCES, h_config_save_advances, PREF_MISC, 0},
3219 {"save-will-not-delete", NULL,
3220 F_SAVE_WONT_DELETE, h_config_save_wont_delete, PREF_MISC, 0},
3221 {"save-will-quote-leading-froms", NULL,
3222 F_QUOTE_ALL_FROMS, h_config_quote_all_froms, PREF_MISC, 0},
3223 {"scramble-message-id", "Scramble the Message-ID When Sending",
3224 F_ROT13_MESSAGE_ID, h_config_scramble_message_id, PREF_MISC, 0},
3225 {"select-without-confirm", "Select Ctrl-T Foldername Without Confirming",
3226 F_SELECT_WO_CONFIRM, h_config_select_wo_confirm, PREF_MISC, 0},
3227 {"show-cursor", NULL,
3228 F_SHOW_CURSOR, h_config_show_cursor, PREF_MISC, 0},
3229 {"show-plain-text-internally", NULL,
3230 F_SHOW_TEXTPLAIN_INT, h_config_textplain_int, PREF_MISC, 0},
3231 {"show-selected-in-boldface", "Show Selected in Boldface",
3232 F_SELECTED_SHOWN_BOLD, h_config_select_in_bold, PREF_MISC, 0},
3233 {"slash-collapses-entire-thread", NULL,
3234 F_SLASH_COLL_ENTIRE, h_config_slash_coll_entire, PREF_MISC, 0},
3235 #ifdef _WINDOWS
3236 {"store-window-position-in-config", "Store Window Position in Config",
3237 F_STORE_WINPOS_IN_CONFIG, h_config_winpos_in_config, PREF_MISC, 0},
3238 #endif
3239 {"suppress-asterisks-in-password-prompt", "Suppress Asterisks in Password Prompt",
3240 F_QUELL_ASTERISKS, h_config_quell_asterisks,
3241 PREF_MISC, 0},
3242 {"quell-attachment-extension-warn", "Suppress Attachment Extension Warning",
3243 F_QUELL_ATTACH_EXT_WARN, h_config_quell_attach_ext_warn,
3244 PREF_MISC, 0},
3245 {"quell-attachment-extra-prompt", "Suppress Attachment Extra Prompt",
3246 F_QUELL_ATTACH_EXTRA_PROMPT, h_config_quell_attach_extra_prompt,
3247 PREF_MISC, 0},
3248 {"quell-berkeley-format-timezone", "Suppress Berkeley Format Timezone",
3249 F_QUELL_BEZERK_TIMEZONE, h_config_no_bezerk_zone, PREF_MISC, 0},
3250 {"quell-content-id", "Suppress Content-ID",
3251 F_QUELL_CONTENT_ID, h_config_quell_content_id, PREF_MISC, 0},
3252 {"quell-filtering-done-message", "Suppress Filtering Done Message",
3253 F_QUELL_FILTER_DONE_MSG, h_config_quell_filtering_done_message,
3254 PREF_MISC, 0},
3255 {"quell-filtering-messages", "Suppress Filtering Messages",
3256 F_QUELL_FILTER_MSGS, h_config_quell_filtering_messages,
3257 PREF_MISC, 0},
3258 {"quell-imap-envelope-update", "Suppress IMAP Envelope Update",
3259 F_QUELL_IMAP_ENV_CB, h_config_quell_imap_env, PREF_MISC, 0},
3260 {"quell-lock-failure-warnings", "Suppress Lock Failure Warnings",
3261 F_QUELL_LOCK_FAILURE_MSGS, h_config_quell_lock_failure_warnings,
3262 PREF_MISC, 0},
3263 {"quell-maildomain-warning", "Suppress Maildomain Warning",
3264 F_QUELL_MAILDOMAIN_WARNING, h_config_quell_domain_warn, PREF_MISC, 0},
3265 {"quell-news-envelope-update", "Suppress News Envelope Update",
3266 F_QUELL_NEWS_ENV_CB, h_config_quell_news_env, PREF_MISC, 0},
3267 #ifdef _WINDOWS
3268 {"quell-ssl-largeblocks", "Prevent SSL Largeblocks",
3269 F_QUELL_SSL_LARGEBLOCKS, h_config_quell_ssl_largeblocks, PREF_MISC, 0},
3270 #endif
3271 {"quell-status-message-beeping", "Suppress Status Message Beeping",
3272 F_QUELL_BEEPS, h_config_quell_beeps, PREF_MISC, 0},
3273 {"quell-timezone-comment-when-sending", "Suppress Timezone Comment When Sending",
3274 F_QUELL_TIMEZONE, h_config_quell_tz_comment, PREF_MISC, 0},
3275 {"suppress-user-agent-when-sending", NULL,
3276 F_QUELL_USERAGENT, h_config_suppress_user_agent, PREF_MISC, 0},
3277 {"tab-checks-recent", "Tab Checks for Recent Messages",
3278 F_TAB_CHK_RECENT, h_config_tab_checks_recent, PREF_MISC, 0},
3279 {"termdef-takes-precedence", NULL,
3280 F_TCAP_WINS, h_config_termcap_wins, PREF_MISC, 0},
3281 {"try-alternative-authentication-driver-first", NULL,
3282 F_PREFER_ALT_AUTH, h_config_alt_auth, PREF_MISC, 0},
3283 {"unselect-will-not-advance", NULL,
3284 F_UNSELECT_WONT_ADVANCE, h_config_unsel_wont_advance, PREF_MISC, 0},
3285 {"use-current-dir", "Use Current Directory",
3286 F_USE_CURRENT_DIR, h_config_use_current_dir, PREF_MISC, 0},
3287 {"use-function-keys", NULL,
3288 F_USE_FK, h_config_use_fk, PREF_OS_USFK, 0},
3289 {"use-regular-startup-rule-for-stayopen-folders", "Use Regular Startup Rule for Stayopen Folders",
3290 F_STARTUP_STAYOPEN, h_config_use_reg_start_for_stayopen, PREF_MISC, 0},
3291 {"use-resent-to-in-rules", "Use Resent-To in Rules",
3292 F_USE_RESENTTO, h_config_use_resentto, PREF_MISC, 0},
3293 {"use-subshell-for-suspend", "Use Subshell for Suspend",
3294 F_SUSPEND_SPAWNS, h_config_suspend_spawns, PREF_OS_SPWN, 0},
3295 #ifndef _WINDOWS
3296 {"use-system-translation", NULL,
3297 F_USE_SYSTEM_TRANS, h_config_use_system_translation, PREF_MISC, 0},
3298 #endif
3300 /* Hidden Features */
3301 {"old-growth", NULL,
3302 F_OLD_GROWTH, NO_HELP, PREF_NONE, 0},
3303 {"disable-config-cmd", NULL,
3304 F_DISABLE_CONFIG_SCREEN, h_config_disable_config_cmd, PREF_HIDDEN, 0},
3305 {"disable-keyboard-lock-cmd", NULL,
3306 F_DISABLE_KBLOCK_CMD, h_config_disable_kb_lock, PREF_HIDDEN, 0},
3307 {"disable-password-cmd", NULL,
3308 F_DISABLE_PASSWORD_CMD, h_config_disable_password_cmd, PREF_HIDDEN, 0},
3309 {"disable-pipes-in-sigs", NULL,
3310 F_DISABLE_PIPES_IN_SIGS, h_config_disable_pipes_in_sigs, PREF_HIDDEN, 0},
3311 {"disable-pipes-in-templates", NULL,
3312 F_DISABLE_PIPES_IN_TEMPLATES, h_config_disable_pipes_in_templates,
3313 PREF_HIDDEN, 0},
3314 {"disable-roles-setup-cmd", NULL,
3315 F_DISABLE_ROLES_SETUP, h_config_disable_roles_setup, PREF_HIDDEN, 0},
3316 {"disable-roles-sig-edit", NULL,
3317 F_DISABLE_ROLES_SIGEDIT, h_config_disable_roles_sigedit, PREF_HIDDEN, 0},
3318 {"disable-roles-template-edit", NULL,
3319 F_DISABLE_ROLES_TEMPLEDIT, h_config_disable_roles_templateedit,
3320 PREF_HIDDEN, 0},
3321 {"disable-setlocale-collate", NULL,
3322 F_DISABLE_SETLOCALE_COLLATE, h_config_disable_collate, PREF_HIDDEN, 0},
3323 {"disable-shared-namespaces", NULL,
3324 F_DISABLE_SHARED_NAMESPACES, h_config_disable_shared, PREF_HIDDEN, 0},
3325 {"disable-signature-edit-cmd", NULL,
3326 F_DISABLE_SIGEDIT_CMD, h_config_disable_signature_edit, PREF_HIDDEN, 0},
3327 {"new-thread-on-blank-subject", "New Thread on Blank Subject",
3328 F_NEW_THREAD_ON_BLANK_SUBJECT, h_config_new_thread_blank_subject, PREF_HIDDEN, 1},
3329 {"quell-personal-name-prompt", NULL,
3330 F_QUELL_PERSONAL_NAME_PROMPT, h_config_quell_personal_name_prompt, PREF_HIDDEN, 0},
3331 {"quell-user-id-prompt", "Quell User ID Prompt",
3332 F_QUELL_USER_ID_PROMPT, h_config_quell_user_id_prompt, PREF_HIDDEN, 0},
3333 #ifdef SMIME
3334 {"smime-dont-do-smime", "S/MIME -- Turn off S/MIME",
3335 F_DONT_DO_SMIME, h_config_smime_dont_do_smime, PREF_HIDDEN, 0},
3336 {"smime-encrypt-by-default", "S/MIME -- Encrypt by Default",
3337 F_ENCRYPT_DEFAULT_ON, h_config_smime_encrypt_by_default, PREF_HIDDEN, 0},
3338 {"smime-remember-passphrase", "S/MIME -- Remember S/MIME Passphrase",
3339 F_REMEMBER_SMIME_PASSPHRASE, h_config_smime_remember_passphrase, PREF_HIDDEN, 0},
3340 {"smime-sign-by-default", "S/MIME -- Sign by Default",
3341 F_SIGN_DEFAULT_ON, h_config_smime_sign_by_default, PREF_HIDDEN, 0},
3342 {"smime-use-store-only", "S/MIME -- Validate Using Certificate Store Only",
3343 F_USE_CERT_STORE_ONLY, h_config_smime_use_cert_store, PREF_HIDDEN, 1},
3344 #ifdef APPLEKEYCHAIN
3345 {"publiccerts-in-keychain", "S/MIME -- Public Certs in MacOS Keychain",
3346 F_PUBLICCERTS_IN_KEYCHAIN, h_config_smime_pubcerts_in_keychain, PREF_HIDDEN, 0},
3347 #endif
3348 #endif
3349 {"selectable-item-nobold", NULL,
3350 F_SLCTBL_ITEM_NOBOLD, NO_HELP, PREF_NONE, 0},
3351 {"send-confirms-only-expanded", NULL, /* exposed in Web Alpine */
3352 F_SEND_CONFIRM_ON_EXPAND, h_config_send_confirms_only_expanded, PREF_HIDDEN, 0},
3353 {"enable-jump-cmd", NULL, /* exposed in Web Alpine */
3354 F_ENABLE_JUMP_CMD, h_config_enable_jump_command, PREF_HIDDEN, 0},
3355 {"enable-newmail-sound", NULL, /* exposed in Web Alpine */
3356 F_ENABLE_NEWMAIL_SOUND, h_config_enable_newmail_sound, PREF_HIDDEN, 0},
3357 {"render-html-internally", NULL, /* exposed in Web Alpine */
3358 F_RENDER_HTML_INTERNALLY, h_config_render_html_internally, PREF_HIDDEN, 0}
3361 return((index >= 0 && index < (sizeof(feat_list)/sizeof(feat_list[0])))
3362 ? &feat_list[index] : NULL);
3367 * feature_list_index -- return index of given feature id in
3368 * feature list
3371 feature_list_index(int id)
3373 FEATURE_S *feature;
3374 int i;
3376 for(i = 0; (feature = feature_list(i)); i++)
3377 if(id == feature->id)
3378 return(i);
3380 return(-1);
3385 * feature_list_name -- return the given feature id's corresponding name
3387 char *
3388 feature_list_name(int id)
3390 FEATURE_S *f;
3392 return((f = feature_list(feature_list_index(id))) ? f->name : "");
3397 feature_list_id(char *name)
3399 FEATURE_S *f;
3400 int i;
3402 for(i = 0; (f = feature_list(i)); i++)
3403 if(!strucmp(f->name, name))
3404 return(f->id);
3406 return(-1);
3411 * feature_list_help -- return the given feature id's corresponding help
3413 HelpType
3414 feature_list_help(int id)
3416 FEATURE_S *f;
3418 return((f = feature_list(feature_list_index(id))) ? f->help : NO_HELP);
3423 * All the arguments past "list" are the backwards compatibility hacks.
3425 void
3426 process_feature_list(struct pine *ps, char **list, int old_growth, int hir, int osr)
3428 register char *q;
3429 char **p,
3430 *lvalue[BM_SIZE * 8];
3431 int i,
3432 yorn;
3433 long l;
3434 FEATURE_S *feat;
3437 /* clear all previous settings and reset them to default */
3438 for(i = 0; (feat = feature_list(i)) != NULL; i++)
3439 F_SET(feat->id, ps, feat->defval);
3441 /* backwards compatibility */
3442 if(hir)
3443 F_TURN_ON(F_INCLUDE_HEADER, ps);
3445 /* ditto */
3446 if(osr)
3447 F_TURN_ON(F_SIG_AT_BOTTOM, ps);
3449 /* ditto */
3450 if(old_growth)
3451 set_old_growth_bits(ps, 0);
3453 /* now run through the list (global, user, and cmd_line lists are here) */
3454 if(list){
3455 for(p = list; (q = *p) != NULL; p++){
3456 if(struncmp(q, "no-", 3) == 0){
3457 yorn = 0;
3458 q += 3;
3459 }else{
3460 yorn = 1;
3463 for(i = 0; (feat = feature_list(i)) != NULL; i++){
3464 if(strucmp(q, feat->name) == 0){
3465 if(feat->id == F_OLD_GROWTH){
3466 set_old_growth_bits(ps, yorn);
3467 }else{
3468 F_SET(feat->id, ps, yorn);
3470 break;
3474 /* if it wasn't in that list */
3475 if(feat == NULL)
3476 dprint((1,"Unrecognized feature in feature-list (%s%s)\n",
3477 (yorn ? "" : "no-"), q ? q : "?"));
3482 * Turn on gratuitous '>From ' quoting, if requested...
3484 mail_parameters(NULL, SET_FROMWIDGET,
3485 F_ON(F_QUOTE_ALL_FROMS, ps) ? VOIDT : NIL);
3488 * Turn off .lock creation complaints...
3490 if(F_ON(F_QUELL_LOCK_FAILURE_MSGS, ps))
3491 mail_parameters(NULL, SET_LOCKEACCESERROR, (void *) 0);
3494 * Turn on quelling of pseudo message.
3496 if(F_ON(F_QUELL_INTERNAL_MSG,ps_global))
3497 mail_parameters(NULL, SET_USERHASNOLIFE, (void *) 1);
3499 l = F_ON(F_MULNEWSRC_HOSTNAMES_AS_TYPED,ps_global) ? 0L : 1L;
3500 mail_parameters(NULL, SET_NEWSRCCANONHOST, (void *) l);
3502 ps->pass_ctrl_chars = F_ON(F_PASS_CONTROL_CHARS,ps_global) ? 1 : 0;
3503 ps->pass_c1_ctrl_chars = F_ON(F_PASS_C1_CONTROL_CHARS,ps_global) ? 1 : 0;
3505 #ifndef _WINDOWS
3506 if(F_ON(F_QUELL_BEZERK_TIMEZONE,ps_global))
3507 mail_parameters(NULL, SET_NOTIMEZONES, (void *) 1);
3508 #endif
3510 if(F_ON(F_USE_FK, ps))
3511 ps->orig_use_fkeys = 1;
3513 /* Will we have to build a new list? */
3514 if(!(old_growth || hir || osr))
3515 return;
3518 * Build a new list for feature-list. The only reason we ever need to
3519 * do this is if one of the obsolete options is being converted
3520 * into a feature-list item, and it isn't already included in the user's
3521 * feature-list.
3523 i = 0;
3524 for(p = LVAL(&ps->vars[V_FEATURE_LIST], Main);
3525 p && (q = *p); p++){
3526 /* already have it or cancelled it, don't need to add later */
3527 if(hir && (strucmp(q, "include-header-in-reply") == 0 ||
3528 strucmp(q, "no-include-header-in-reply") == 0)){
3529 hir = 0;
3530 }else if(osr && (strucmp(q, "signature-at-bottom") == 0 ||
3531 strucmp(q, "no-signature-at-bottom") == 0)){
3532 osr = 0;
3533 }else if(old_growth && (strucmp(q, "old-growth") == 0 ||
3534 strucmp(q, "no-old-growth") == 0)){
3535 old_growth = 0;
3537 lvalue[i++] = cpystr(q);
3540 /* check to see if we still need to build a new list */
3541 if(!(old_growth || hir || osr))
3542 return;
3544 if(hir)
3545 lvalue[i++] = "include-header-in-reply";
3546 if(osr)
3547 lvalue[i++] = "signature-at-bottom";
3548 if(old_growth)
3549 lvalue[i++] = "old-growth";
3550 lvalue[i] = NULL;
3551 set_variable_list(V_FEATURE_LIST, lvalue, TRUE, Main);
3555 void
3556 set_current_pattern_vals(struct pine *ps)
3558 struct variable *vars = ps->vars;
3560 set_current_val(&vars[V_PATTERNS], TRUE, TRUE);
3561 set_current_val(&vars[V_PAT_ROLES], TRUE, TRUE);
3562 set_current_val(&vars[V_PAT_FILTS], TRUE, TRUE);
3563 set_current_val(&vars[V_PAT_FILTS_OLD], TRUE, TRUE);
3564 set_current_val(&vars[V_PAT_SCORES], TRUE, TRUE);
3565 set_current_val(&vars[V_PAT_SCORES_OLD], TRUE, TRUE);
3566 set_current_val(&vars[V_PAT_INCOLS], TRUE, TRUE);
3567 set_current_val(&vars[V_PAT_OTHER], TRUE, TRUE);
3568 set_current_val(&vars[V_PAT_SRCH], TRUE, TRUE);
3571 * If old pattern variable (V_PATTERNS) is set and the new ones aren't
3572 * in the config file, then convert the old data into the new variables.
3573 * It isn't quite that simple, though, because we don't store unset
3574 * variables in remote pinercs. Check for the variables but if we
3575 * don't find any of them, also check the version number. This change was
3576 * made in version 4.30. We could just check that except that we're
3577 * worried somebody will make an incompatible version number change in
3578 * their local version, and will break this. So we check both the
3579 * version # and the var_in_pinerc things to be safer.
3581 if(vars[V_PATTERNS].current_val.l
3582 && vars[V_PATTERNS].current_val.l[0]
3583 && !var_in_pinerc(vars[V_PAT_ROLES].name)
3584 && !var_in_pinerc(vars[V_PAT_FILTS].name)
3585 && !var_in_pinerc(vars[V_PAT_FILTS_OLD].name)
3586 && !var_in_pinerc(vars[V_PAT_SCORES].name)
3587 && !var_in_pinerc(vars[V_PAT_SCORES_OLD].name)
3588 && !var_in_pinerc(vars[V_PAT_INCOLS].name)
3589 && isdigit((unsigned char) ps->pine_pre_vers[0])
3590 && ps->pine_pre_vers[1] == '.'
3591 && isdigit((unsigned char) ps->pine_pre_vers[2])
3592 && isdigit((unsigned char) ps->pine_pre_vers[3])
3593 && strncmp(ps->pine_pre_vers, "4.30", 4) < 0){
3594 convert_pattern_data();
3598 * Otherwise, if FILTS_OLD is set and FILTS isn't in the config file,
3599 * convert FILTS_OLD to FILTS. Same for SCORES.
3600 * The reason FILTS was changed was so we could change the
3601 * semantics of how rules work when there are pieces in the rule that
3602 * we don't understand. At the same time as the FILTS change we added
3603 * a rule to detect 8bitSubjects. So a user might have a filter that
3604 * deletes messages with 8bitSubjects. The problem is that that same
3605 * filter in a FILTS_OLD pine would match because it would ignore the
3606 * 8bitSubject part of the pattern and match on the rest. So we changed
3607 * the semantics so that rules with unknown bits would be ignored
3608 * instead of used. We had to change variable names at the same time
3609 * because we were adding the 8bit thing and the old pines are still
3610 * out there. Filters and Scores can both be dangerous. Roles, Colors,
3611 * and Other seem less dangerous so not worth adding a new variable.
3612 * This was changed in 4.50.
3614 else{
3615 if(vars[V_PAT_FILTS_OLD].current_val.l
3616 && vars[V_PAT_FILTS_OLD].current_val.l[0]
3617 && !var_in_pinerc(vars[V_PAT_FILTS].name)
3618 && !var_in_pinerc(vars[V_PAT_SCORES].name)
3619 && isdigit((unsigned char) ps->pine_pre_vers[0])
3620 && ps->pine_pre_vers[1] == '.'
3621 && isdigit((unsigned char) ps->pine_pre_vers[2])
3622 && isdigit((unsigned char) ps->pine_pre_vers[3])
3623 && strncmp(ps->pine_pre_vers, "4.50", 4) < 0){
3624 convert_filts_pattern_data();
3627 if(vars[V_PAT_SCORES_OLD].current_val.l
3628 && vars[V_PAT_SCORES_OLD].current_val.l[0]
3629 && !var_in_pinerc(vars[V_PAT_FILTS].name)
3630 && !var_in_pinerc(vars[V_PAT_SCORES].name)
3631 && isdigit((unsigned char) ps->pine_pre_vers[0])
3632 && ps->pine_pre_vers[1] == '.'
3633 && isdigit((unsigned char) ps->pine_pre_vers[2])
3634 && isdigit((unsigned char) ps->pine_pre_vers[3])
3635 && strncmp(ps->pine_pre_vers, "4.50", 4) < 0){
3636 convert_scores_pattern_data();
3640 if(vars[V_PAT_ROLES].post_user_val.l)
3641 ps_global->ew_for_role_take = Post;
3642 else
3643 ps_global->ew_for_role_take = Main;
3645 if(vars[V_PAT_FILTS].post_user_val.l)
3646 ps_global->ew_for_filter_take = Post;
3647 else
3648 ps_global->ew_for_filter_take = Main;
3650 if(vars[V_PAT_SCORES].post_user_val.l)
3651 ps_global->ew_for_score_take = Post;
3652 else
3653 ps_global->ew_for_score_take = Main;
3655 if(vars[V_PAT_INCOLS].post_user_val.l)
3656 ps_global->ew_for_incol_take = Post;
3657 else
3658 ps_global->ew_for_incol_take = Main;
3660 if(vars[V_PAT_OTHER].post_user_val.l)
3661 ps_global->ew_for_other_take = Post;
3662 else
3663 ps_global->ew_for_other_take = Main;
3665 if(vars[V_PAT_SRCH].post_user_val.l)
3666 ps_global->ew_for_srch_take = Post;
3667 else
3668 ps_global->ew_for_srch_take = Main;
3673 * Foreach of the config files;
3674 * transfer the data to the new variables.
3676 void
3677 convert_pattern_data(void)
3679 convert_pinerc_patterns(PAT_USE_MAIN);
3680 convert_pinerc_patterns(PAT_USE_POST);
3684 void
3685 convert_filts_pattern_data(void)
3687 convert_pinerc_filts_patterns(PAT_USE_MAIN);
3688 convert_pinerc_filts_patterns(PAT_USE_POST);
3692 void
3693 convert_scores_pattern_data(void)
3695 convert_pinerc_scores_patterns(PAT_USE_MAIN);
3696 convert_pinerc_scores_patterns(PAT_USE_POST);
3701 * Foreach of the four variables, transfer the data for this config file
3702 * from the old patterns variable. We don't have to convert OTHER patterns
3703 * or SRCH patterns because they didn't exist in pines without patterns-other.
3705 * If the original variable had patlines with type File then we convert
3706 * all of the individual patterns to type Lit, because each pattern can
3707 * be of any category. Lit patterns are better tested, anyway.
3709 void
3710 convert_pinerc_patterns(long int use_flags)
3712 long old_rflags;
3713 long rflags;
3714 PAT_S *pat;
3715 PAT_STATE pstate;
3716 ACTION_S *act;
3718 old_rflags = (ROLE_OLD_PAT | use_flags);
3720 rflags = 0L;
3721 if(any_patterns(old_rflags, &pstate)){
3722 dprint((2, "converting old patterns to new (%s)\n", (use_flags == PAT_USE_MAIN) ? "Main" : "Post"));
3723 for(pat = first_pattern(&pstate);
3724 pat;
3725 pat = next_pattern(&pstate)){
3726 if((act = pat->action) != NULL){
3727 if(act->is_a_role &&
3728 add_to_pattern(pat, ROLE_DO_ROLES | use_flags))
3729 rflags |= ROLE_DO_ROLES;
3730 if(act->is_a_incol &&
3731 add_to_pattern(pat, ROLE_DO_INCOLS | use_flags))
3732 rflags |= ROLE_DO_INCOLS;
3733 if(act->is_a_score &&
3734 add_to_pattern(pat, ROLE_DO_SCORES | use_flags))
3735 rflags |= ROLE_DO_SCORES;
3736 if(act->is_a_filter &&
3737 add_to_pattern(pat, ROLE_DO_FILTER | use_flags))
3738 rflags |= ROLE_DO_FILTER;
3742 if(rflags)
3743 if(write_patterns(rflags | use_flags))
3744 dprint((1,
3745 "Trouble converting patterns to new variable\n"));
3751 * If the original variable had patlines with type File then we convert
3752 * all of the individual patterns to type Lit, because each pattern can
3753 * be of any category. Lit patterns are better tested, anyway.
3755 void
3756 convert_pinerc_filts_patterns(long int use_flags)
3758 long old_rflags;
3759 long rflags;
3760 PAT_S *pat;
3761 PAT_STATE pstate;
3762 ACTION_S *act;
3764 old_rflags = (ROLE_OLD_FILT | use_flags);
3766 rflags = 0L;
3767 if(any_patterns(old_rflags, &pstate)){
3768 dprint((2, "converting old filter patterns to new (%s)\n", (use_flags == PAT_USE_MAIN) ? "Main" : "Post"));
3769 for(pat = first_pattern(&pstate);
3770 pat;
3771 pat = next_pattern(&pstate)){
3772 if((act = pat->action) != NULL){
3773 if(act->is_a_filter &&
3774 add_to_pattern(pat, ROLE_DO_FILTER | use_flags))
3775 rflags |= ROLE_DO_FILTER;
3779 if(rflags)
3780 if(write_patterns(rflags | use_flags))
3781 dprint((1,
3782 "Trouble converting filter patterns to new variable\n"));
3788 * If the original variable had patlines with type File then we convert
3789 * all of the individual patterns to type Lit, because each pattern can
3790 * be of any category. Lit patterns are better tested, anyway.
3792 void
3793 convert_pinerc_scores_patterns(long int use_flags)
3795 long old_rflags;
3796 long rflags;
3797 PAT_S *pat;
3798 PAT_STATE pstate;
3799 ACTION_S *act;
3801 old_rflags = (ROLE_OLD_SCORE | use_flags);
3803 rflags = 0L;
3804 if(any_patterns(old_rflags, &pstate)){
3805 dprint((2, "converting old scores patterns to new (%s)\n", (use_flags == PAT_USE_MAIN) ? "Main" : "Post"));
3806 for(pat = first_pattern(&pstate);
3807 pat;
3808 pat = next_pattern(&pstate)){
3809 if((act = pat->action) != NULL){
3810 if(act->is_a_score &&
3811 add_to_pattern(pat, ROLE_DO_SCORES | use_flags))
3812 rflags |= ROLE_DO_SCORES;
3816 if(rflags)
3817 if(write_patterns(rflags | use_flags))
3818 dprint((1,
3819 "Trouble converting scores patterns to new variable\n"));
3825 * set_old_growth_bits - Command used to set or unset old growth set
3826 * of features
3828 void
3829 set_old_growth_bits(struct pine *ps, int val)
3831 int i;
3833 for(i = 1; i <= F_FEATURE_LIST_COUNT; i++)
3834 if(test_old_growth_bits(ps, i))
3835 F_SET(i, ps, val);
3841 * test_old_growth_bits - Test to see if all the old growth bits are on,
3842 * *or* if a particular feature index is in the old
3843 * growth set.
3845 * WEIRD ALERT: if index == F_OLD_GROWTH bit values are tested
3846 * otherwise a bits existence in the set is tested!!!
3848 * BUG: this will break if an old growth feature number is ever >= 32.
3851 test_old_growth_bits(struct pine *ps, int index)
3854 * this list defines F_OLD_GROWTH set
3856 static unsigned long old_growth_bits = ((1 << F_ENABLE_FULL_HDR) |
3857 (1 << F_ENABLE_PIPE) |
3858 (1 << F_ENABLE_TAB_COMPLETE) |
3859 (1 << F_QUIT_WO_CONFIRM) |
3860 (1 << F_ENABLE_JUMP) |
3861 (1 << F_ENABLE_ALT_ED) |
3862 (1 << F_ENABLE_BOUNCE) |
3863 (1 << F_ENABLE_AGG_OPS) |
3864 (1 << F_ENABLE_FLAG) |
3865 (1 << F_CAN_SUSPEND));
3866 if(index >= 32)
3867 return(0);
3869 if(index == F_OLD_GROWTH){
3870 for(index = 1; index <= F_FEATURE_LIST_COUNT; index++)
3871 if(((1 << index) & old_growth_bits) && F_OFF(index, ps))
3872 return(0);
3874 return(1);
3876 else
3877 return((1 << index) & old_growth_bits);
3882 * Side effect is that the appropriate global variable is set, and the
3883 * appropriate current_val is set.
3885 void
3886 cur_rule_value(struct variable *var, int expand, int cmdline)
3888 int i;
3889 NAMEVAL_S *v;
3891 set_current_val(var, expand, cmdline);
3893 if(var == &ps_global->vars[V_SAVED_MSG_NAME_RULE]){
3894 if(ps_global->VAR_SAVED_MSG_NAME_RULE)
3895 for(i = 0; (v = save_msg_rules(i)); i++)
3896 if(!strucmp(ps_global->VAR_SAVED_MSG_NAME_RULE, S_OR_L(v))){
3897 ps_global->save_msg_rule = v->value;
3898 break;
3901 #ifndef _WINDOWS
3902 else if(var == &ps_global->vars[V_COLOR_STYLE]){
3903 if(ps_global->VAR_COLOR_STYLE)
3904 for(i = 0; (v = col_style(i)); i++)
3905 if(!strucmp(ps_global->VAR_COLOR_STYLE, S_OR_L(v))){
3906 ps_global->color_style = v->value;
3907 break;
3910 #endif
3911 else if(var == &ps_global->vars[V_INDEX_COLOR_STYLE]){
3912 if(ps_global->VAR_INDEX_COLOR_STYLE)
3913 for(i = 0; (v = index_col_style(i)); i++)
3914 if(!strucmp(ps_global->VAR_INDEX_COLOR_STYLE, S_OR_L(v))){
3915 ps_global->index_color_style = v->value;
3916 break;
3919 else if(var == &ps_global->vars[V_TITLEBAR_COLOR_STYLE]){
3920 if(ps_global->VAR_TITLEBAR_COLOR_STYLE)
3921 for(i = 0; (v = titlebar_col_style(i)); i++)
3922 if(!strucmp(ps_global->VAR_TITLEBAR_COLOR_STYLE, S_OR_L(v))){
3923 ps_global->titlebar_color_style = v->value;
3924 break;
3927 else if(var == &ps_global->vars[V_FCC_RULE]){
3928 if(ps_global->VAR_FCC_RULE)
3929 for(i = 0; (v = fcc_rules(i)); i++)
3930 if(!strucmp(ps_global->VAR_FCC_RULE, S_OR_L(v))){
3931 ps_global->fcc_rule = v->value;
3932 break;
3935 else if(var == &ps_global->vars[V_GOTO_DEFAULT_RULE]){
3936 if(ps_global->VAR_GOTO_DEFAULT_RULE)
3937 for(i = 0; (v = goto_rules(i)); i++)
3938 if(!strucmp(ps_global->VAR_GOTO_DEFAULT_RULE, S_OR_L(v))){
3939 ps_global->goto_default_rule = v->value;
3940 break;
3943 else if(var == &ps_global->vars[V_INCOMING_STARTUP]){
3944 if(ps_global->VAR_INCOMING_STARTUP)
3945 for(i = 0; (v = incoming_startup_rules(i)); i++)
3946 if(!strucmp(ps_global->VAR_INCOMING_STARTUP, S_OR_L(v))){
3947 ps_global->inc_startup_rule = v->value;
3948 break;
3951 else if(var == &ps_global->vars[V_PRUNING_RULE]){
3952 if(ps_global->VAR_PRUNING_RULE)
3953 for(i = 0; (v = pruning_rules(i)); i++)
3954 if(!strucmp(ps_global->VAR_PRUNING_RULE, S_OR_L(v))){
3955 ps_global->pruning_rule = v->value;
3956 break;
3959 else if(var == &ps_global->vars[V_REOPEN_RULE]){
3960 if(ps_global->VAR_REOPEN_RULE)
3961 for(i = 0; (v = reopen_rules(i)); i++)
3962 if(!strucmp(ps_global->VAR_REOPEN_RULE, S_OR_L(v))){
3963 ps_global->reopen_rule = v->value;
3964 break;
3967 else if(var == &ps_global->vars[V_FLD_SORT_RULE]){
3968 if(ps_global->VAR_FLD_SORT_RULE)
3969 for(i = 0; (v = fld_sort_rules(i)); i++)
3970 if(!strucmp(ps_global->VAR_FLD_SORT_RULE, S_OR_L(v))){
3971 ps_global->fld_sort_rule = v->value;
3972 break;
3975 else if(var == &ps_global->vars[V_AB_SORT_RULE]){
3976 if(ps_global->VAR_AB_SORT_RULE)
3977 for(i = 0; (v = ab_sort_rules(i)); i++)
3978 if(!strucmp(ps_global->VAR_AB_SORT_RULE, S_OR_L(v))){
3979 ps_global->ab_sort_rule = v->value;
3980 break;
3983 else if(var == &ps_global->vars[V_THREAD_DISP_STYLE]){
3984 if(ps_global->VAR_THREAD_DISP_STYLE)
3985 for(i = 0; (v = thread_disp_styles(i)); i++)
3986 if(!strucmp(ps_global->VAR_THREAD_DISP_STYLE, S_OR_L(v))){
3987 ps_global->thread_disp_style = v->value;
3988 break;
3991 else if(var == &ps_global->vars[V_THREAD_INDEX_STYLE]){
3992 if(ps_global->VAR_THREAD_INDEX_STYLE)
3993 for(i = 0; (v = thread_index_styles(i)); i++)
3994 if(!strucmp(ps_global->VAR_THREAD_INDEX_STYLE, S_OR_L(v))){
3995 ps_global->thread_index_style = v->value;
3996 break;
4003 * Standard way to get at save message rules...
4005 NAMEVAL_S *
4006 save_msg_rules(int index)
4008 static NAMEVAL_S save_rules[] = {
4009 {"by-from", NULL, SAV_RULE_FROM},
4010 {"by-nick-of-from", NULL, SAV_RULE_NICK_FROM_DEF},
4011 {"by-nick-of-from-then-from", NULL, SAV_RULE_NICK_FROM},
4012 {"by-fcc-of-from", NULL, SAV_RULE_FCC_FROM_DEF},
4013 {"by-fcc-of-from-then-from", NULL, SAV_RULE_FCC_FROM},
4014 {"by-realname-of-from", NULL, SAV_RULE_RN_FROM_DEF},
4015 {"by-realname-of-from-then-from", NULL, SAV_RULE_RN_FROM},
4016 {"by-sender", NULL, SAV_RULE_SENDER},
4017 {"by-nick-of-sender", NULL, SAV_RULE_NICK_SENDER_DEF},
4018 {"by-nick-of-sender-then-sender", NULL, SAV_RULE_NICK_SENDER},
4019 {"by-fcc-of-sender", NULL, SAV_RULE_FCC_SENDER_DEF},
4020 {"by-fcc-of-sender-then-sender", NULL, SAV_RULE_FCC_SENDER},
4021 {"by-realname-of-sender", NULL, SAV_RULE_RN_SENDER_DEF},
4022 {"by-realname-of-sender-then-sender", NULL, SAV_RULE_RN_SENDER},
4023 {"by-recipient", NULL, SAV_RULE_RECIP},
4024 {"by-nick-of-recip", NULL, SAV_RULE_NICK_RECIP_DEF},
4025 {"by-nick-of-recip-then-recip", NULL, SAV_RULE_NICK_RECIP},
4026 {"by-fcc-of-recip", NULL, SAV_RULE_FCC_RECIP_DEF},
4027 {"by-fcc-of-recip-then-recip", NULL, SAV_RULE_FCC_RECIP},
4028 {"by-realname-of-recip", NULL, SAV_RULE_RN_RECIP_DEF},
4029 {"by-realname-of-recip-then-recip", NULL, SAV_RULE_RN_RECIP},
4030 {"by-replyto", NULL, SAV_RULE_REPLYTO},
4031 {"by-nick-of-replyto", NULL, SAV_RULE_NICK_REPLYTO_DEF},
4032 {"by-nick-of-replyto-then-replyto", NULL, SAV_RULE_NICK_REPLYTO},
4033 {"by-fcc-of-replyto", NULL, SAV_RULE_FCC_REPLYTO_DEF},
4034 {"by-fcc-of-replyto-then-replyto", NULL, SAV_RULE_FCC_REPLYTO},
4035 {"by-realname-of-replyto", NULL, SAV_RULE_RN_REPLYTO_DEF},
4036 {"by-realname-of-replyto-then-replyto", NULL, SAV_RULE_RN_REPLYTO},
4037 {"last-folder-used", NULL, SAV_RULE_LAST},
4038 {"default-folder", NULL, SAV_RULE_DEFLT}
4041 return((index >= 0 && index < (sizeof(save_rules)/sizeof(save_rules[0])))
4042 ? &save_rules[index] : NULL);
4047 * Standard way to get at fcc rules...
4049 NAMEVAL_S *
4050 fcc_rules(int index)
4052 static NAMEVAL_S f_rules[] = {
4053 {"default-fcc", NULL, FCC_RULE_DEFLT},
4054 {"last-fcc-used", NULL, FCC_RULE_LAST},
4055 {"by-recipient", NULL, FCC_RULE_RECIP},
4056 {"by-nickname", NULL, FCC_RULE_NICK},
4057 {"by-nick-then-recip", NULL, FCC_RULE_NICK_RECIP},
4058 {"current-folder", NULL, FCC_RULE_CURRENT}
4061 return((index >= 0 && index < (sizeof(f_rules)/sizeof(f_rules[0])))
4062 ? &f_rules[index] : NULL);
4067 * Standard way to get at addrbook sort rules...
4069 NAMEVAL_S *
4070 ab_sort_rules(int index)
4072 static NAMEVAL_S ab_rules[] = {
4073 {"fullname-with-lists-last", NULL, AB_SORT_RULE_FULL_LISTS},
4074 {"fullname", NULL, AB_SORT_RULE_FULL},
4075 {"nickname-with-lists-last", NULL, AB_SORT_RULE_NICK_LISTS},
4076 {"nickname", NULL, AB_SORT_RULE_NICK},
4077 {"dont-sort", NULL, AB_SORT_RULE_NONE}
4080 return((index >= 0 && index < (sizeof(ab_rules)/sizeof(ab_rules[0])))
4081 ? &ab_rules[index] : NULL);
4086 * Standard way to get at color styles.
4088 NAMEVAL_S *
4089 col_style(int index)
4091 static NAMEVAL_S col_styles[] = {
4092 {"no-color", NULL, COL_NONE},
4093 {"use-termdef", NULL, COL_TERMDEF},
4094 {"force-ansi-8color", NULL, COL_ANSI8},
4095 {"force-ansi-16color", NULL, COL_ANSI16},
4096 {"force-xterm-256color", NULL, COL_ANSI256}
4099 return((index >= 0 && index < (sizeof(col_styles)/sizeof(col_styles[0])))
4100 ? &col_styles[index] : NULL);
4105 * Standard way to get at index color styles.
4107 NAMEVAL_S *
4108 index_col_style(int index)
4110 static NAMEVAL_S ind_col_styles[] = {
4111 {"flip-colors", NULL, IND_COL_FLIP},
4112 {"reverse", NULL, IND_COL_REV},
4113 {"reverse-fg", NULL, IND_COL_FG},
4114 {"reverse-fg-no-ambiguity", NULL, IND_COL_FG_NOAMBIG},
4115 {"reverse-bg", NULL, IND_COL_BG},
4116 {"reverse-bg-no-ambiguity", NULL, IND_COL_BG_NOAMBIG}
4119 return((index >= 0 && index < (sizeof(ind_col_styles)/sizeof(ind_col_styles[0]))) ? &ind_col_styles[index] : NULL);
4124 * Standard way to get at titlebar color styles.
4126 NAMEVAL_S *
4127 titlebar_col_style(int index)
4129 static NAMEVAL_S tbar_col_styles[] = {
4130 {"default", NULL, TBAR_COLOR_DEFAULT},
4131 {"indexline", NULL, TBAR_COLOR_INDEXLINE},
4132 {"reverse-indexline", NULL, TBAR_COLOR_REV_INDEXLINE}
4135 return((index >= 0 && index < (sizeof(tbar_col_styles)/sizeof(tbar_col_styles[0]))) ? &tbar_col_styles[index] : NULL);
4140 * Standard way to get at folder sort rules...
4142 NAMEVAL_S *
4143 fld_sort_rules(int index)
4145 static NAMEVAL_S fdl_rules[] = {
4146 {"alphabetical", NULL, FLD_SORT_ALPHA},
4147 {"alpha-with-dirs-last", NULL, FLD_SORT_ALPHA_DIR_LAST},
4148 {"alpha-with-dirs-first", NULL, FLD_SORT_ALPHA_DIR_FIRST}
4151 return((index >= 0 && index < (sizeof(fdl_rules)/sizeof(fdl_rules[0])))
4152 ? &fdl_rules[index] : NULL);
4157 * Standard way to get at incoming startup rules...
4159 NAMEVAL_S *
4160 incoming_startup_rules(int index)
4162 static NAMEVAL_S is_rules[] = {
4163 {"first-unseen", NULL, IS_FIRST_UNSEEN},
4164 {"first-recent", NULL, IS_FIRST_RECENT},
4165 {"first-important", NULL, IS_FIRST_IMPORTANT},
4166 {"first-important-or-unseen", NULL, IS_FIRST_IMPORTANT_OR_UNSEEN},
4167 {"first-important-or-recent", NULL, IS_FIRST_IMPORTANT_OR_RECENT},
4168 {"first", NULL, IS_FIRST},
4169 {"last", NULL, IS_LAST}
4172 return((index >= 0 && index < (sizeof(is_rules)/sizeof(is_rules[0])))
4173 ? &is_rules[index] : NULL);
4177 NAMEVAL_S *
4178 startup_rules(int index)
4180 static NAMEVAL_S is2_rules[] = {
4181 {"first-unseen", NULL, IS_FIRST_UNSEEN},
4182 {"first-recent", NULL, IS_FIRST_RECENT},
4183 {"first-important", NULL, IS_FIRST_IMPORTANT},
4184 {"first-important-or-unseen", NULL, IS_FIRST_IMPORTANT_OR_UNSEEN},
4185 {"first-important-or-recent", NULL, IS_FIRST_IMPORTANT_OR_RECENT},
4186 {"first", NULL, IS_FIRST},
4187 {"last", NULL, IS_LAST},
4188 {"default", NULL, IS_NOTSET}
4191 return((index >= 0 && index < (sizeof(is2_rules)/sizeof(is2_rules[0])))
4192 ? &is2_rules[index] : NULL);
4197 * Standard way to get at pruning-rule values.
4199 NAMEVAL_S *
4200 pruning_rules(int index)
4202 static NAMEVAL_S pr_rules[] = {
4203 {"ask about rename, ask about deleting","ask-ask", PRUNE_ASK_AND_ASK},
4204 {"ask about rename, don't delete", "ask-no", PRUNE_ASK_AND_NO},
4205 {"always rename, ask about deleting", "yes-ask", PRUNE_YES_AND_ASK},
4206 {"always rename, don't delete", "yes-no", PRUNE_YES_AND_NO},
4207 {"don't rename, ask about deleting", "no-ask", PRUNE_NO_AND_ASK},
4208 {"don't rename, don't delete", "no-no", PRUNE_NO_AND_NO}
4211 return((index >= 0 && index < (sizeof(pr_rules)/sizeof(pr_rules[0])))
4212 ? &pr_rules[index] : NULL);
4217 * Standard way to get at reopen-rule values.
4219 NAMEVAL_S *
4220 reopen_rules(int index)
4222 static NAMEVAL_S ro_rules[] = {
4223 /* TRANSLATORS: short description of a feature option */
4224 {"Always reopen", "yes-yes",
4225 REOPEN_YES_YES},
4226 /* TRANSLATORS: short description of a feature option, default in brackets */
4227 {"Yes for POP/NNTP, Ask about other remote [Yes]", "yes-ask-y",
4228 REOPEN_YES_ASK_Y},
4229 /* TRANSLATORS: short description of a feature option, default in brackets */
4230 {"Yes for POP/NNTP, Ask about other remote [No]", "yes-ask-n",
4231 REOPEN_YES_ASK_N},
4232 /* TRANSLATORS: short description of a feature option */
4233 {"Yes for POP/NNTP, No for other remote", "yes-no",
4234 REOPEN_YES_NO},
4235 /* TRANSLATORS: short description of a feature option, default in brackets */
4236 {"Always ask [Yes]", "ask-ask-y",
4237 REOPEN_ASK_ASK_Y},
4238 /* TRANSLATORS: short description of a feature option, default in brackets */
4239 {"Always ask [No]", "ask-ask-n",
4240 REOPEN_ASK_ASK_N},
4241 /* TRANSLATORS: short description of a feature option, default in brackets */
4242 {"Ask about POP/NNTP [Yes], No for other remote", "ask-no-y",
4243 REOPEN_ASK_NO_Y},
4244 /* TRANSLATORS: short description of a feature option, default in brackets */
4245 {"Ask about POP/NNTP [No], No for other remote", "ask-no-n",
4246 REOPEN_ASK_NO_N},
4247 /* TRANSLATORS: short description of a feature option */
4248 {"Never reopen", "no-no",
4249 REOPEN_NO_NO},
4252 return((index >= 0 && index < (sizeof(ro_rules)/sizeof(ro_rules[0])))
4253 ? &ro_rules[index] : NULL);
4258 * Standard way to get at thread_disp_style values.
4260 NAMEVAL_S *
4261 thread_disp_styles(int index)
4263 static NAMEVAL_S td_styles[] = {
4264 {"none", "none", THREAD_NONE},
4265 {"show-thread-structure", "struct", THREAD_STRUCT},
4266 {"mutt-like", "mutt", THREAD_MUTTLIKE},
4267 {"indent-subject-1", "subj1", THREAD_INDENT_SUBJ1},
4268 {"indent-subject-2", "subj2", THREAD_INDENT_SUBJ2},
4269 {"indent-from-1", "from1", THREAD_INDENT_FROM1},
4270 {"indent-from-2", "from2", THREAD_INDENT_FROM2},
4271 {"show-structure-in-from", "struct-from", THREAD_STRUCT_FROM}
4274 return((index >= 0 && index < (sizeof(td_styles)/sizeof(td_styles[0])))
4275 ? &td_styles[index] : NULL);
4280 * Standard way to get at thread_index_style values.
4282 NAMEVAL_S *
4283 thread_index_styles(int index)
4285 static NAMEVAL_S ti_styles[] = {
4286 {"regular-index-with-expanded-threads", "exp", THRDINDX_EXP},
4287 {"regular-index-with-collapsed-threads","coll", THRDINDX_COLL},
4288 {"separate-index-screen-always", "sep", THRDINDX_SEP},
4289 {"separate-index-screen-except-for-single-messages","sep-auto",
4290 THRDINDX_SEP_AUTO}
4293 return((index >= 0 && index < (sizeof(ti_styles)/sizeof(ti_styles[0])))
4294 ? &ti_styles[index] : NULL);
4299 * Standard way to get at goto default rules...
4301 NAMEVAL_S *
4302 goto_rules(int index)
4304 static NAMEVAL_S g_rules[] = {
4305 {"folder-in-first-collection", NULL, GOTO_FIRST_CLCTN},
4306 {"inbox-or-folder-in-first-collection", NULL, GOTO_INBOX_FIRST_CLCTN},
4307 {"inbox-or-folder-in-recent-collection", NULL, GOTO_INBOX_RECENT_CLCTN},
4308 {"first-collection-with-inbox-default", NULL, GOTO_FIRST_CLCTN_DEF_INBOX},
4309 {"most-recent-folder", NULL, GOTO_LAST_FLDR}
4312 return((index >= 0 && index < (sizeof(g_rules)/sizeof(g_rules[0])))
4313 ? &g_rules[index] : NULL);
4317 NAMEVAL_S *
4318 pat_fldr_types(int index)
4320 static NAMEVAL_S pat_fldr_list[] = {
4321 {"Any", "ANY", FLDR_ANY},
4322 {"News", "NEWS", FLDR_NEWS},
4323 {"Email", "EMAIL", FLDR_EMAIL},
4324 {"Specific (Enter Incoming Nicknames or use ^T)", "SPEC", FLDR_SPECIFIC}
4327 return((index >= 0 &&
4328 index < (sizeof(pat_fldr_list)/sizeof(pat_fldr_list[0])))
4329 ? &pat_fldr_list[index] : NULL);
4333 NAMEVAL_S *
4334 inabook_fldr_types(int indexarg)
4336 static NAMEVAL_S inabook_fldr_list[] = {
4337 {"Don't care, always matches", "E", IAB_EITHER},
4338 {"Yes, in any address book", "YES", IAB_YES},
4339 {"No, not in any address book", "NO", IAB_NO},
4340 {"Yes, in specific address books", "SYES", IAB_SPEC_YES},
4341 {"No, not in any of specific address books", "SNO", IAB_SPEC_NO}
4344 int index = indexarg & IAB_TYPE_MASK;
4346 return((index >= 0 &&
4347 index < (sizeof(inabook_fldr_list)/sizeof(inabook_fldr_list[0])))
4348 ? &inabook_fldr_list[index] : NULL);
4352 NAMEVAL_S *
4353 filter_types(int index)
4355 static NAMEVAL_S filter_type_list[] = {
4356 {"Just Set Message Status", "NONE", FILTER_STATE},
4357 {"Delete", "DEL", FILTER_KILL},
4358 {"Move (Enter folder name(s) in primary collection, or use ^T)",
4359 "FLDR", FILTER_FOLDER}
4362 return((index >= 0 &&
4363 index < (sizeof(filter_type_list)/sizeof(filter_type_list[0])))
4364 ? &filter_type_list[index] : NULL);
4368 NAMEVAL_S *
4369 role_repl_types(int index)
4371 static NAMEVAL_S role_repl_list[] = {
4372 {"Never", "NO", ROLE_REPL_NO},
4373 {"With confirmation", "YES", ROLE_REPL_YES},
4374 {"Without confirmation", "NC", ROLE_REPL_NOCONF}
4377 return((index >= 0 &&
4378 index < (sizeof(role_repl_list)/sizeof(role_repl_list[0])))
4379 ? &role_repl_list[index] : NULL);
4383 NAMEVAL_S *
4384 role_forw_types(int index)
4386 static NAMEVAL_S role_forw_list[] = {
4387 {"Never", "NO", ROLE_FORW_NO},
4388 {"With confirmation", "YES", ROLE_FORW_YES},
4389 {"Without confirmation", "NC", ROLE_FORW_NOCONF}
4392 return((index >= 0 &&
4393 index < (sizeof(role_forw_list)/sizeof(role_forw_list[0])))
4394 ? &role_forw_list[index] : NULL);
4398 NAMEVAL_S *
4399 role_comp_types(int index)
4401 static NAMEVAL_S role_comp_list[] = {
4402 {"Never", "NO", ROLE_COMP_NO},
4403 {"With confirmation", "YES", ROLE_COMP_YES},
4404 {"Without confirmation", "NC", ROLE_COMP_NOCONF}
4407 return((index >= 0 &&
4408 index < (sizeof(role_comp_list)/sizeof(role_comp_list[0])))
4409 ? &role_comp_list[index] : NULL);
4413 NAMEVAL_S *
4414 role_status_types(int index)
4416 static NAMEVAL_S role_status_list[] = {
4417 {"Don't care, always matches", "E", PAT_STAT_EITHER},
4418 {"Yes", "YES", PAT_STAT_YES},
4419 {"No", "NO", PAT_STAT_NO}
4422 return((index >= 0 &&
4423 index < (sizeof(role_status_list)/sizeof(role_status_list[0])))
4424 ? &role_status_list[index] : NULL);
4428 NAMEVAL_S *
4429 msg_state_types(int index)
4431 static NAMEVAL_S msg_state_list[] = {
4432 {"Don't change it", "LV", ACT_STAT_LEAVE},
4433 {"Set this state", "SET", ACT_STAT_SET},
4434 {"Clear this state", "CLR", ACT_STAT_CLEAR}
4437 return((index >= 0 &&
4438 index < (sizeof(msg_state_list)/sizeof(msg_state_list[0])))
4439 ? &msg_state_list[index] : NULL);
4443 #ifdef ENABLE_LDAP
4444 NAMEVAL_S *
4445 ldap_search_rules(int index)
4447 static NAMEVAL_S ldap_search_list[] = {
4448 {"contains", NULL, LDAP_SRCH_CONTAINS},
4449 {"equals", NULL, LDAP_SRCH_EQUALS},
4450 {"begins-with", NULL, LDAP_SRCH_BEGINS},
4451 {"ends-with", NULL, LDAP_SRCH_ENDS}
4454 return((index >= 0 &&
4455 index < (sizeof(ldap_search_list)/sizeof(ldap_search_list[0])))
4456 ? &ldap_search_list[index] : NULL);
4460 NAMEVAL_S *
4461 ldap_search_types(int index)
4463 static NAMEVAL_S ldap_types_list[] = {
4464 {"name", NULL, LDAP_TYPE_CN},
4465 {"surname", NULL, LDAP_TYPE_SUR},
4466 {"givenname", NULL, LDAP_TYPE_GIVEN},
4467 {"email", NULL, LDAP_TYPE_EMAIL},
4468 {"name-or-email", NULL, LDAP_TYPE_CN_EMAIL},
4469 {"surname-or-givenname", NULL, LDAP_TYPE_SUR_GIVEN},
4470 {"sur-or-given-or-name-or-email", NULL, LDAP_TYPE_SEVERAL}
4473 return((index >= 0 &&
4474 index < (sizeof(ldap_types_list)/sizeof(ldap_types_list[0])))
4475 ? &ldap_types_list[index] : NULL);
4479 NAMEVAL_S *
4480 ldap_search_scope(int index)
4482 static NAMEVAL_S ldap_scope_list[] = {
4483 {"base", NULL, LDAP_SCOPE_BASE},
4484 {"onelevel", NULL, LDAP_SCOPE_ONELEVEL},
4485 {"subtree", NULL, LDAP_SCOPE_SUBTREE}
4488 return((index >= 0 &&
4489 index < (sizeof(ldap_scope_list)/sizeof(ldap_scope_list[0])))
4490 ? &ldap_scope_list[index] : NULL);
4492 #endif
4496 * Choose from the global default, command line args, pinerc values to set
4497 * the actual value of the variable that we will use. Start at the top
4498 * and work down from higher to lower precedence.
4499 * For lists, we may inherit values from lower precedence
4500 * versions if that's the way the user specifies it.
4501 * The user can put INHERIT_DEFAULT as the first entry in a list and that
4502 * means it will inherit the current values, for example the values
4503 * from the global_val, or the value from the main_user_val could be
4504 * inherited in the post_user_val.
4506 void
4507 set_current_val(struct variable *var, int expand, int cmdline)
4509 int is_set[5], is_inherit[5];
4510 int i, j, k, cnt, start;
4511 char **tmp, **t, **list[5];
4512 char *p;
4514 dprint((9,
4515 "set_current_val(var=%s%s, expand=%d, cmdline=%d)\n",
4516 (var && var->name) ? var->name : "?",
4517 (var && var->is_list) ? " (list)" : "",
4518 expand, cmdline));
4520 if(!var)
4521 return;
4523 if(var->is_list){ /* variable is a list */
4525 for(j = 0; j < 5; j++){
4526 t = j==0 ? var->global_val.l :
4527 j==1 ? var->main_user_val.l :
4528 j==2 ? var->post_user_val.l :
4529 j==3 ? ((cmdline) ? var->cmdline_val.l : NULL) :
4530 var->fixed_val.l;
4532 is_set[j] = is_inherit[j] = 0;
4533 list[j] = NULL;
4535 if(t){
4536 if(!expand){
4537 is_set[j]++;
4538 list[j] = t;
4540 else{
4541 for(i = 0; t[i]; i++){
4542 if(expand_variables(tmp_20k_buf, SIZEOF_20KBUF, t[i],
4543 0)){
4544 /* successful expand */
4545 is_set[j]++;
4546 list[j] = t;
4547 break;
4552 if(list[j] && list[j][0] && !strcmp(list[j][0],INHERIT))
4553 is_inherit[j]++;
4557 cnt = 0;
4558 start = 0;
4559 /* count how many items in current_val list */
4560 /* Admin wants default, which is global_val. */
4561 if(var->is_fixed && var->fixed_val.l == NULL){
4562 cnt = 0;
4563 if(is_set[0]){
4564 for(; list[0][cnt]; cnt++)
4568 else{
4569 for(j = 0; j < 5; j++){
4570 if(is_set[j]){
4571 if(!is_inherit[j]){
4572 cnt = 0; /* reset */
4573 start = j;
4576 for(i = is_inherit[j] ? 1 : 0; list[j][i]; i++)
4577 cnt++;
4582 free_list_array(&var->current_val.l); /* clean up any old values */
4584 /* check to see if anything is set */
4585 if(is_set[0] + is_set[1] + is_set[2] + is_set[3] + is_set[4] > 0){
4586 var->current_val.l = (char **)fs_get((cnt+1)*sizeof(char *));
4587 tmp = var->current_val.l;
4588 if(var->is_fixed && var->fixed_val.l == NULL){
4589 if(is_set[0]){
4590 for(i = 0; list[0][i]; i++){
4591 if(!expand)
4592 *tmp++ = cpystr(list[0][i]);
4593 else if(expand_variables(tmp_20k_buf, SIZEOF_20KBUF,
4594 list[0][i], 0))
4595 *tmp++ = cpystr(tmp_20k_buf);
4599 else{
4600 for(j = start; j < 5; j++){
4601 if(is_set[j]){
4602 for(i = is_inherit[j] ? 1 : 0; list[j][i]; i++){
4603 if(!expand)
4604 *tmp++ = cpystr(list[j][i]);
4605 else if(expand_variables(tmp_20k_buf,SIZEOF_20KBUF,
4606 list[j][i], 0))
4607 *tmp++ = cpystr(tmp_20k_buf);
4613 *tmp = NULL;
4615 else
4616 var->current_val.l = NULL;
4618 else{ /* variable is not a list */
4619 char *strvar = NULL;
4621 for(j = 0; j < 5; j++){
4623 p = j==0 ? var->fixed_val.p :
4624 j==1 ? ((cmdline) ? var->cmdline_val.p : NULL) :
4625 j==2 ? var->post_user_val.p :
4626 j==3 ? var->main_user_val.p :
4627 var->global_val.p;
4629 is_set[j] = 0;
4631 if(p){
4632 if(!expand){
4633 is_set[j]++;
4634 if(!strvar)
4635 strvar = p;
4637 else if(expand_variables(tmp_20k_buf, SIZEOF_20KBUF, p,
4638 (var == &ps_global->vars[V_MAILCAP_PATH] ||
4639 var == &ps_global->vars[V_MIMETYPE_PATH]))){
4640 is_set[j]++;
4641 if(!strvar)
4642 strvar = p;
4647 /* Admin wants default, which is global_val. */
4648 if(var->is_fixed && var->fixed_val.p == NULL)
4649 strvar = var->global_val.p;
4651 if(var->current_val.p) /* free previous value */
4652 fs_give((void **)&var->current_val.p);
4654 if(strvar){
4655 if(!expand)
4656 var->current_val.p = cpystr(strvar);
4657 else{
4658 expand_variables(tmp_20k_buf, SIZEOF_20KBUF, strvar,
4659 (var == &ps_global->vars[V_MAILCAP_PATH] ||
4660 var == &ps_global->vars[V_MIMETYPE_PATH]));
4661 var->current_val.p = cpystr(tmp_20k_buf);
4664 else
4665 var->current_val.p = NULL;
4668 if(var->is_fixed && !is_inherit[4]){
4669 char **flist;
4670 int fixed_len, user_len;
4673 * sys mgr fixed this variable and user is trying to change it
4675 for(k = 1; !(ps_global->give_fixed_warning &&
4676 ps_global->fix_fixed_warning) && k <= 3; k++){
4677 if(is_set[k]){
4678 if(var->is_list){
4679 t = k==1 ? ((cmdline) ? var->cmdline_val.l : NULL) :
4680 k==2 ? var->post_user_val.l :
4681 var->main_user_val.l;
4683 /* If same length and same contents, don't warn. */
4684 for(flist=var->fixed_val.l; flist && *flist; flist++)
4685 ;/* just counting */
4687 fixed_len = var->fixed_val.l ? (flist - var->fixed_val.l)
4688 : 0;
4689 for(flist=t; flist && *flist; flist++)
4690 ;/* just counting */
4692 user_len = t ? (flist - t) : 0;
4693 if(user_len == fixed_len){
4694 for(i=0; i < user_len; i++){
4695 for(j=0; j < user_len; j++)
4696 if(!strucmp(t[i], var->fixed_val.l[j]))
4697 break;
4699 if(j == user_len){
4700 ps_global->give_fixed_warning = 1;
4701 if(k != 1)
4702 ps_global->fix_fixed_warning = 1;
4704 break;
4708 else{
4709 ps_global->give_fixed_warning = 1;
4710 if(k != 1)
4711 ps_global->fix_fixed_warning = 1;
4714 else{
4715 p = k==1 ? ((cmdline) ? var->cmdline_val.p : NULL) :
4716 k==2 ? var->post_user_val.p :
4717 var->main_user_val.p;
4719 if((var->fixed_val.p && !p) ||
4720 (!var->fixed_val.p && p) ||
4721 (var->fixed_val.p && p && strucmp(var->fixed_val.p, p))){
4722 ps_global->give_fixed_warning = 1;
4723 if(k != 1)
4724 ps_global->fix_fixed_warning = 1;
4733 void
4734 set_news_spec_current_val(int expand, int cmdline)
4736 struct variable *newsvar = &ps_global->vars[V_NEWS_SPEC];
4737 struct variable *fvar = &ps_global->vars[V_FOLDER_SPEC];
4739 /* check to see if it has a value */
4740 set_current_val(newsvar, expand, cmdline);
4743 * If no value, we might want to fake a value. We'll do that if
4744 * there is no news collection already defined in FOLDER_SPEC and if
4745 * there is also an NNTP_SERVER defined.
4747 if(!newsvar->current_val.l && ps_global->VAR_NNTP_SERVER &&
4748 ps_global->VAR_NNTP_SERVER[0] && ps_global->VAR_NNTP_SERVER[0][0] &&
4749 !news_in_folders(fvar)){
4750 char buf[MAXPATH];
4752 newsvar->global_val.l = (char **)fs_get(2 * sizeof(char *));
4753 snprintf(buf, sizeof(buf), "{%.*s/nntp}#news.[]", MAXPATH-20,
4754 ps_global->VAR_NNTP_SERVER[0]); /* MAXPATH = sizeof(buf) */
4755 newsvar->global_val.l[0] = cpystr(buf);
4756 newsvar->global_val.l[1] = NULL;
4757 set_current_val(newsvar, expand, cmdline);
4759 * But we're going to get rid of the fake global_val in case
4760 * things change.
4762 free_list_array(&newsvar->global_val.l);
4768 * Feature-list has to be handled separately from the other variables
4769 * because it is additive. The other variables choose one of command line,
4770 * or pine.conf, or pinerc. Feature list adds them. This could easily be
4771 * converted to a general purpose routine if we add more additive variables.
4773 * This works by replacing earlier values with later ones. That is, command
4774 * line settings have higher precedence than global settings and that is
4775 * accomplished by putting the command line features after the global
4776 * features in the list. When they are processed, the last one wins.
4778 * Feature-list also has a backwards compatibility hack.
4780 void
4781 set_feature_list_current_val(struct variable *var)
4783 char **list;
4784 char **list_fixed;
4785 char no_allow[50];
4786 int i, j, k, m,
4787 elems = 0;
4789 /* count the lists so we can allocate */
4790 for(m = 0; m < 6; m++){
4791 list = m==0 ? var->global_val.l :
4792 m==1 ? var->main_user_val.l :
4793 m==2 ? var->post_user_val.l :
4794 m==3 ? ps_global->feat_list_back_compat :
4795 m==4 ? var->cmdline_val.l :
4796 var->fixed_val.l;
4797 if(list)
4798 for(i = 0; list[i]; i++)
4799 elems++;
4802 list_fixed = var->fixed_val.l;
4804 if(var->current_val.l)
4805 free_list_array(&var->current_val.l);
4807 var->current_val.l = (char **)fs_get((elems+1) * sizeof(char *));
4810 * We need to warn the user if the sys mgr has restricted him or her
4811 * from changing a feature that he or she is trying to change.
4813 * We're not catching the old-growth macro since we're just comparing
4814 * strings. That is, it works correctly, but the user won't be warned
4815 * if the user old-growth and the mgr says no-quit-without-confirm.
4818 j = 0;
4819 strncpy(no_allow, "no-", 3);
4820 strncpy(no_allow+3, feature_list_name(F_ALLOW_CHANGING_FROM), sizeof(no_allow)-3-1);
4821 no_allow[sizeof(no_allow)-1] = '\0';
4823 for(m = 0; m < 6; m++){
4824 list = m==0 ? var->global_val.l :
4825 m==1 ? var->main_user_val.l :
4826 m==2 ? var->post_user_val.l :
4827 m==3 ? ps_global->feat_list_back_compat :
4828 m==4 ? var->cmdline_val.l :
4829 var->fixed_val.l;
4830 if(list)
4831 for(i = 0; list[i]; i++){
4832 var->current_val.l[j++] = cpystr(list[i]);
4834 /* this is the warning section */
4835 if(m >= 1 && m <= 4){
4836 for(k = 0; list_fixed && list_fixed[k]; k++){
4837 char *p, *q;
4838 p = list[i];
4839 q = list_fixed[k];
4840 if(!struncmp(p, "no-", 3))
4841 p += 3;
4842 if(!struncmp(q, "no-", 3))
4843 q += 3;
4844 if(!strucmp(q, p) && strucmp(list[i], list_fixed[k])){
4845 ps_global->give_fixed_warning = 1;
4846 if(m <= 2)
4847 ps_global->fix_fixed_warning = 1;
4851 else if(m == 5 && !strucmp(list[i], no_allow))
4852 ps_global->never_allow_changing_from = 1;
4856 #ifdef NEVER_ALLOW_CHANGING_FROM
4857 ps_global->never_allow_changing_from = 1;
4858 #endif
4860 var->current_val.l[j] = NULL;
4865 /*----------------------------------------------------------------------
4867 Expand Metacharacters/variables in file-names
4869 Read input line and expand shell-variables/meta-characters
4871 <input> <replaced by>
4872 $variable getenv("variable")
4873 ${variable} getenv("variable")
4874 ${variable:-defvalue} is getenv("variable") if variable is defined and
4875 is defvalue otherwise
4876 ~ getenv("HOME")
4877 \c c
4878 <others> <just copied>
4880 NOTE handling of braces in ${name} doesn't check much or do error recovery
4882 If colon_path is set, then we expand ~ not only at the start of linein,
4883 but also after each : in the path.
4885 ----*/
4886 #define is_allowed_envchar(C, S) ((S) == 0 ? !isspace((C)) && (C) != '/'\
4887 : (((C) >= 'a' && (C) <= 'z') \
4888 || ((C) >= 'A' && (C) <= 'Z') \
4889 || ((C) >= '0' && (C) <= '9')))
4891 char *
4892 expand_variables(char *lineout, size_t lineoutlen, char *linein, int colon_path)
4894 char *src = linein, *dest = lineout, *p;
4895 char *limit = lineout + lineoutlen;
4896 int envexpand = 0, sp;
4898 if(!linein)
4899 return(NULL);
4901 sp = strncmp(src,"LIT:pattern=\"/NICK=", strlen("LIT:pattern=\"/NICK=")) == 0;
4902 while(*src ){ /* something in input string */
4903 if(*src == '$' && *(src+1) == '$'){
4905 * $$ to escape chars we're interested in, else
4906 * it's up to the user of the variable to handle the
4907 * backslash...
4909 if(dest < limit)
4910 *dest++ = *++src; /* copy next as is */
4911 }else
4912 #if !(defined(DOS) || defined(OS2))
4913 if(*src == '\\' && *(src+1) == '$'){
4915 * backslash to escape chars we're interested in, else
4916 * it's up to the user of the variable to handle the
4917 * backslash...
4919 if(dest < limit)
4920 *dest++ = *++src; /* copy next as is */
4921 }else if(*src == '~' &&
4922 (src == linein || (colon_path && *(src-1) == ':'))){
4923 char buf[MAXPATH];
4924 int i;
4926 for(i = 0; i < sizeof(buf)-1 && src[i] && src[i] != '/'; i++)
4927 buf[i] = src[i];
4929 src += i; /* advance src pointer */
4930 buf[i] = '\0'; /* tie off buf string */
4931 fnexpand(buf, sizeof(buf)); /* expand the path */
4933 for(p = buf; dest < limit && (*dest = *p); p++, dest++)
4936 continue;
4937 }else
4938 #endif
4939 if(*src == '$'){ /* shell variable */
4940 char word[128+1], *colon = NULL, *rbrace = NULL;
4942 envexpand++; /* signal that we've expanded a var */
4943 src++; /* skip dollar */
4944 if(*src == '{'){ /* starts with brace? */
4945 src++;
4946 rbrace = strindex(src, '}');
4947 if(rbrace){
4948 /* look for default value */
4949 colon = strstr(src, ":-");
4950 if(colon && (rbrace < colon))
4951 colon = NULL;
4955 p = word;
4957 /* put the env variable to be looked up in word */
4958 if(rbrace){
4959 while(*src
4960 && (p-word < sizeof(word)-1)
4961 && ((colon && src < colon) || (!colon && src < rbrace))){
4962 if(isspace((unsigned char) *src)){
4964 * Illegal input. This should be an error of some
4965 * sort but instead of that we'll just backup to the
4966 * $ and treat it like it wasn't there.
4968 while(*src != '$')
4969 src--;
4971 envexpand--;
4972 goto just_copy;
4974 else
4975 *p++ = *src++;
4978 /* adjust src for next char */
4979 src = rbrace + 1;
4981 else{
4982 while(*src && is_allowed_envchar((unsigned char) *src, sp)
4983 && (p-word < sizeof(word)-1))
4984 *p++ = *src++;
4987 *p = '\0';
4989 if((p = getenv(word)) != NULL){ /* check for word in environment */
4990 while(*p && dest < limit)
4991 *dest++ = *p++;
4993 else if(colon){ /* else possible default value */
4994 p = colon + 2;
4995 while(*p && p < rbrace && dest < limit)
4996 *dest++ = *p++;
4999 continue;
5000 }else{ /* other cases: just copy */
5001 just_copy:
5002 if(dest < limit)
5003 *dest++ = *src;
5006 if(*src) /* next character (if any) */
5007 src++;
5010 if(dest < limit)
5011 *dest = '\0';
5012 else
5013 lineout[lineoutlen-1] = '\0';
5015 return((envexpand && lineout[0] == '\0') ? NULL : lineout);
5019 /*----------------------------------------------------------------------
5020 Sets login, full_username and home_dir
5022 Args: ps -- The Pine structure to put the user name, etc in
5024 Result: sets the fullname, login and home_dir field of the pine structure
5025 returns 0 on success, -1 if not.
5026 ----*/
5027 #define MAX_INIT_ERRS 10
5028 void
5029 init_error(struct pine *ps, int flags, int min_time, int max_time, char *message)
5031 int i;
5033 if(!ps->init_errs){
5034 ps->init_errs = (INIT_ERR_S *)fs_get((MAX_INIT_ERRS + 1) *
5035 sizeof(*ps->init_errs));
5036 memset(ps->init_errs, 0, (MAX_INIT_ERRS + 1) * sizeof(*ps->init_errs));
5039 for(i = 0; i < MAX_INIT_ERRS; i++)
5040 if(!(ps->init_errs)[i].message){
5041 (ps->init_errs)[i].message = cpystr(message);
5042 (ps->init_errs)[i].min_time = min_time;
5043 (ps->init_errs)[i].max_time = max_time;
5044 (ps->init_errs)[i].flags = flags;
5045 dprint((2, "%s\n", message ? message : "?"));
5046 break;
5051 /*----------------------------------------------------------------------
5052 Read and parse a pinerc file
5054 Args: Filename -- name of the .pinerc file to open and read
5055 vars -- The vars structure to store values in
5056 which_vars -- Whether the local or global values are being read
5058 Result:
5060 This may be the local file or the global file. The values found are
5061 merged with the values currently in vars. All values are strings and
5062 are malloced; and existing values will be freed before the assignment.
5063 Those that are <unset> will be left unset; their values will be NULL.
5064 ----*/
5065 void
5066 read_pinerc(PINERC_S *prc, struct variable *vars, ParsePinerc which_vars)
5068 char *filename, *file, *value, **lvalue, *line, *error;
5069 char *p, *p1, *free_file = NULL;
5070 struct variable *v;
5071 PINERC_LINE *pline = NULL;
5072 int line_count, was_quoted;
5073 int i;
5075 if(!prc)
5076 return;
5078 dprint((2, "reading_pinerc \"%s\"\n",
5079 prc->name ? prc->name : "?"));
5081 if(prc->type == Loc){
5082 filename = prc->name ? prc->name : "";
5083 file = free_file = read_file(filename, 0);
5086 * This is questionable. In case the user edits the pinerc
5087 * in Windows and adds a UTF-8 BOM, we skip it here. If the
5088 * user adds a Unicode BOM we're in trouble. We could write it
5089 * with the BOM ourselves but so far we leave it BOMless in
5090 * order that it's the same on Unix and Windows.
5092 if(BOM_UTF8(file))
5093 file += 3;
5095 else{
5096 if((file = read_remote_pinerc(prc, which_vars)) != NULL)
5097 ps_global->c_client_error[0] = '\0';
5099 free_file = file;
5102 if(file == NULL || *file == '\0'){
5103 #ifdef DEBUG
5104 if(file == NULL){
5105 dprint((2, "Open failed: %s\n", error_description(errno)));
5107 else{
5108 if(prc->type == Loc){
5109 dprint((1, "Read_pinerc: empty pinerc (new?)\n"));
5111 else{
5112 dprint((1, "Read_pinerc: new remote pinerc\n"));
5115 #endif /* DEBUG */
5117 if(which_vars == ParsePers){
5118 /* problems getting remote config */
5119 if(file == NULL && prc->type == RemImap){
5120 if(!pith_opt_remote_pinerc_failure
5121 || !(*pith_opt_remote_pinerc_failure)())
5122 exceptional_exit(_("Unable to read or write remote configuration"), -1);
5125 ps_global->first_time_user = 1;
5126 prc->outstanding_pinerc_changes = 1;
5129 return;
5131 else{
5132 if(prc->type == Loc &&
5133 (which_vars == ParseFixed || which_vars == ParseGlobal ||
5134 (can_access(filename, ACCESS_EXISTS) == 0 &&
5135 can_access(filename, EDIT_ACCESS) != 0))){
5136 prc->readonly = 1;
5137 if(prc == ps_global->prc)
5138 ps_global->readonly_pinerc = 1;
5142 * accept CRLF or LF newlines
5144 for(p = file; *p && *p != '\012'; p++)
5147 if(p > file && *p && *(p-1) == '\015') /* cvt crlf to lf */
5148 for(p1 = p - 1; (*p1 = *p) != '\0'; p++)
5149 if(!(*p == '\015' && *(p+1) == '\012'))
5150 p1++;
5153 dprint((2, "Read %d characters:\n", strlen(file)));
5155 if(which_vars == ParsePers || which_vars == ParsePersPost){
5156 /*--- Count up lines and allocate structures */
5157 for(line_count = 0, p = file; *p != '\0'; p++)
5158 if(*p == '\n')
5159 line_count++;
5161 prc->pinerc_lines = (PINERC_LINE *)
5162 fs_get((3 + line_count) * sizeof(PINERC_LINE));
5163 memset((void *)prc->pinerc_lines, 0,
5164 (3 + line_count) * sizeof(PINERC_LINE));
5165 pline = prc->pinerc_lines;
5168 for(p = file, line = file; *p != '\0';){
5169 /*----- Grab the line ----*/
5170 line = p;
5171 while(*p && *p != '\n')
5172 p++;
5173 if(*p == '\n'){
5174 *p++ = '\0';
5177 /*----- Comment Line -----*/
5178 if(*line == '#'){
5179 /* no comments in remote pinercs */
5180 if(pline && prc->type == Loc){
5181 pline->is_var = 0;
5182 pline->line = cpystr(line);
5183 pline++;
5185 continue;
5188 if(*line == '\0' || *line == '\t' || *line == ' '){
5189 p1 = line;
5190 while(*p1 == '\t' || *p1 == ' ')
5191 p1++;
5192 if(pline){
5194 * This could be a continuation line from some future
5195 * version of pine, or it could be a continuation line
5196 * from a PC-Pine variable we don't know about in unix.
5198 if(*p1 != '\0')
5199 pline->line = cpystr(line);
5200 else
5201 pline->line = cpystr("");
5202 pline->is_var = 0;
5203 pline++;
5205 continue;
5208 /*----- look up matching 'v' and leave "value" after '=' ----*/
5209 for(v = vars; *line && v->name; v++)
5210 if((i = strlen(v->name)) < strlen(line) && !struncmp(v->name,line,i)){
5211 int j;
5213 for(j = i; line[j] == ' ' || line[j] == '\t'; j++)
5216 if(line[j] == '='){ /* bingo! */
5217 for(value = &line[j+1];
5218 *value == ' ' || *value == '\t';
5219 value++)
5222 break;
5224 /* else either unrecognized var or bogus line */
5227 /*----- Didn't match any variable or bogus format -----*/
5229 * This could be a variable from some future
5230 * version of pine, or it could be a PC-Pine variable
5231 * we don't know about in unix. Either way, we want to preserve
5232 * it in the file.
5234 if(!v->name){
5235 if(pline){
5236 pline->is_var = 0;
5237 pline->line = cpystr(line);
5238 pline++;
5240 continue;
5244 * Previous versions have caused duplicate pinerc data to be
5245 * written to pinerc files. This clause erases the duplicate
5246 * information when we read it, and it will be removed from the file
5247 * if we call write_pinerc. We test to see if the same variable
5248 * appears later in the file, if so, we skip over it here.
5249 * We don't care about duplicates if this isn't a pinerc we might
5250 * write out, so include pline in the conditional.
5251 * Note that we will leave all of the duplicate comments and blank
5252 * lines in the file unless it is a remote pinerc. Luckily, the
5253 * bug that caused the duplicates only applied to remote pinercs,
5254 * so we should have that case covered.
5256 * If we find a duplicate, we point p to the start
5257 * of the next line that should be considered, and then skip back
5258 * to the top of the loop.
5260 if(pline && var_is_in_rest_of_file(v->name, p)){
5261 if(v->is_list)
5262 p = skip_over_this_var(line, p);
5264 continue;
5268 /*----- Obsolete variable, read it anyway below, might use it -----*/
5269 if(v->is_obsolete){
5270 if(pline){
5271 pline->obsolete_var = 1;
5272 pline->line = cpystr(line);
5273 pline->var = v;
5277 /*----- Variable is in the list but unused for some reason -----*/
5278 if(!v->is_used){
5279 if(pline){
5280 pline->is_var = 0;
5281 pline->line = cpystr(line);
5282 pline++;
5284 continue;
5287 /*--- Var is not user controlled, leave it alone for back compat ---*/
5288 if(!v->is_user && pline){
5289 pline->is_var = 0;
5290 pline->line = cpystr(line);
5291 pline++;
5292 continue;
5295 if(which_vars == ParseFixed)
5296 v->is_fixed = 1;
5298 /*---- variable is unset, or it's global but expands to nothing ----*/
5299 if(!*value
5300 || (which_vars == ParseGlobal
5301 && !expand_variables(tmp_20k_buf, SIZEOF_20KBUF, value,
5302 (v == &ps_global->vars[V_MAILCAP_PATH] ||
5303 v == &ps_global->vars[V_MIMETYPE_PATH])))){
5304 if(v->is_user && pline){
5305 pline->is_var = 1;
5306 pline->var = v;
5307 pline++;
5309 continue;
5312 /*--value is non-empty, store it handling quotes and trailing space--*/
5313 if(*value == '"' && !v->is_list && v->del_quotes){
5314 was_quoted = 1;
5315 value++;
5316 for(p1 = value; *p1 && *p1 != '"'; p1++);
5317 if(*p1 == '"')
5318 *p1 = '\0';
5319 else
5320 removing_trailing_white_space(value);
5321 }else
5322 was_quoted = 0;
5325 * List Entry Parsing
5327 * The idea is to parse a comma separated list of
5328 * elements, preserving quotes, and understanding
5329 * continuation lines (that is ',' == "\n ").
5330 * Quotes must be balanced within elements. Space
5331 * within elements is preserved, but leading and trailing
5332 * space is trimmed. This is a generic function, and it's
5333 * left to the the functions that use the lists to make sure
5334 * they contain valid data...
5336 if(v->is_list){
5338 was_quoted = 0;
5339 line_count = 0;
5340 p1 = value;
5341 while(1){ /* generous count of list elements */
5342 if(*p1 == '"') /* ignore ',' if quoted */
5343 was_quoted = (was_quoted) ? 0 : 1 ;
5345 if((*p1 == ',' && !was_quoted) || *p1 == '\n' || *p1 == '\0')
5346 line_count++; /* count this element */
5348 if(*p1 == '\0' || *p1 == '\n'){ /* deal with EOL */
5349 if(p1 < p || *p1 == '\n'){
5350 *p1++ = ','; /* fix null or newline */
5352 if(*p1 != '\t' && *p1 != ' '){
5353 *(p1-1) = '\0'; /* tie off list */
5354 p = p1; /* reset p */
5355 break;
5357 }else{
5358 p = p1; /* end of pinerc */
5359 break;
5361 }else
5362 p1++;
5365 error = NULL;
5366 lvalue = parse_list(value, line_count,
5367 v->del_quotes ? PL_REMSURRQUOT : PL_NONE,
5368 &error);
5369 if(error){
5370 dprint((1,
5371 "read_pinerc: ERROR: %s in %s = \"%s\"\n",
5372 error ? error : "?",
5373 v->name ? v->name : "?",
5374 value ? value : "?"));
5377 * Special case: turn "" strings into empty strings.
5378 * This allows users to turn off default lists. For example,
5379 * if smtp-server is set then a user could override smtp-server
5380 * with smtp-server="".
5382 for(i = 0; lvalue[i]; i++)
5383 if(lvalue[i][0] == '"' &&
5384 lvalue[i][1] == '"' &&
5385 lvalue[i][2] == '\0')
5386 lvalue[i][0] = '\0';
5389 if(pline){
5390 if(v->is_user && (which_vars == ParsePers || !v->is_onlymain)){
5391 if(v->is_list){
5392 char ***l;
5394 l = (which_vars == ParsePers) ? &v->main_user_val.l
5395 : &v->post_user_val.l;
5396 free_list_array(l);
5397 *l = lvalue;
5399 else{
5400 char **p;
5402 p = (which_vars == ParsePers) ? &v->main_user_val.p
5403 : &v->post_user_val.p;
5404 if(p && *p != NULL)
5405 fs_give((void **)p);
5407 *p = cpystr(value);
5410 if(pline){
5411 pline->is_var = 1;
5412 pline->var = v;
5413 pline->is_quoted = was_quoted;
5414 pline++;
5418 else if(which_vars == ParseGlobal){
5419 if(v->is_global){
5420 if(v->is_list){
5421 free_list_array(&v->global_val.l);
5422 v->global_val.l = lvalue;
5424 else{
5425 if(v->global_val.p != NULL)
5426 fs_give((void **) &(v->global_val.p));
5428 v->global_val.p = cpystr(value);
5432 else{ /* which_vars == ParseFixed */
5433 if(v->is_user || v->is_global){
5434 if(v->is_list){
5435 free_list_array(&v->fixed_val.l);
5436 v->fixed_val.l = lvalue;
5438 else{
5439 if(v->fixed_val.p != NULL)
5440 fs_give((void **) &(v->fixed_val.p));
5442 v->fixed_val.p = cpystr(value);
5447 #ifdef DEBUG
5448 if(v->is_list){
5449 char **l;
5450 l = (which_vars == ParsePers) ? v->main_user_val.l :
5451 (which_vars == ParsePersPost) ? v->post_user_val.l :
5452 (which_vars == ParseGlobal) ? v->global_val.l :
5453 v->fixed_val.l;
5454 if(l && *l && **l){
5455 dprint((5, " %20.20s : %s\n",
5456 v->name ? v->name : "?",
5457 *l ? *l : "?"));
5458 while(++l && *l && **l)
5459 dprint((5, " %20.20s : %s\n", "",
5460 *l ? *l : "?"));
5462 }else{
5463 char *p;
5464 p = (which_vars == ParsePers) ? v->main_user_val.p :
5465 (which_vars == ParsePersPost) ? v->post_user_val.p :
5466 (which_vars == ParseGlobal) ? v->global_val.p :
5467 v->fixed_val.p;
5468 if(p && *p)
5469 dprint((5, " %20.20s : %s\n",
5470 v->name ? v->name : "?",
5471 p ? p : "?"));
5473 #endif /* DEBUG */
5476 if(pline){
5477 pline->line = NULL;
5478 pline->is_var = 0;
5479 if(!prc->pinerc_written && prc->type == Loc){
5480 prc->pinerc_written = name_file_mtime(filename);
5481 dprint((5, "read_pinerc: time_pinerc_written = %ld\n",
5482 (long) prc->pinerc_written));
5486 if(free_file)
5487 fs_give((void **) &free_file);
5492 * Args varname The variable name we're looking for
5493 * begin Begin looking here
5495 * Returns 1 if variable varname appears in the rest of the file
5496 * 0 if not
5499 var_is_in_rest_of_file(char *varname, char *begin)
5501 char *p;
5503 if(!(varname && *varname && begin && *begin))
5504 return 0;
5506 p = begin;
5508 while((p = srchstr(p, varname)) != NULL){
5509 /* beginning of a line? */
5510 if(p > begin && (*(p-1) != '\n' && *(p-1) != '\r')){
5511 p++;
5512 continue;
5515 /* followed by [ SPACE ] < = > ? */
5516 p += strlen(varname);
5517 while(*p == ' ' || *p == '\t')
5518 p++;
5520 if(*p == '=')
5521 return 1;
5524 return 0;
5529 * Args begin Variable to skip starts here.
5530 * nextline This is where the next line starts. We need to know this
5531 * because the input has been mangled a little. A \0 has
5532 * replaced the \n at the end of the first line, but we can
5533 * use nextline to help us out of that quandry.
5535 * Return a pointer to the start of the first line after this variable
5536 * and all of its continuation lines.
5538 char *
5539 skip_over_this_var(char *begin, char *nextline)
5541 char *p;
5543 p = begin;
5545 while(1){
5546 if(*p == '\0' || *p == '\n'){ /* EOL */
5547 if(p < nextline || *p == '\n'){ /* there may be another line */
5548 p++;
5549 if(*p != ' ' && *p != '\t') /* no continuation line */
5550 return(p);
5552 else /* end of file */
5553 return(p);
5555 else
5556 p++;
5561 static char quotes[3] = {'"', '"', '\0'};
5562 /*----------------------------------------------------------------------
5563 Write out the .pinerc state information
5565 Args: ps -- The pine structure to take state to be written from
5566 which -- Which pinerc to write
5567 flags -- If bit WRP_NOUSER is set, then assume that there is
5568 not a user present to answer questions.
5570 This writes to a temporary file first, and then renames that to
5571 be the new .pinerc file to protect against disk error. This has the
5572 problem of possibly messing up file protections, ownership and links.
5573 ----*/
5575 write_pinerc(struct pine *ps, EditWhich which, int flags)
5577 char *p, *dir, *tmp = NULL, *pinrc;
5578 char *pval, **lval;
5579 char *linep = NULL, *lineq = NULL;
5580 int bc = 1;
5581 int buflen;
5582 PINERC_LINE *pline;
5583 struct variable *var;
5584 time_t mtime;
5585 char *filename;
5586 REMDATA_S *rd = NULL;
5587 PINERC_S *prc = NULL;
5588 STORE_S *so = NULL;
5589 #ifndef _WINDOWS
5590 struct stat sbuf;
5591 char *slink = NULL;
5592 #endif
5594 #define MAXPLINESIZE 10000
5596 dprint((2,"---- write_pinerc(%s) ----\n",
5597 (which == Main) ? "Main" : "Post"));
5599 switch(which){
5600 case Main:
5601 prc = ps ? ps->prc : NULL;
5602 break;
5603 case Post:
5604 prc = ps ? ps->post_prc : NULL;
5605 break;
5606 default:
5607 break;
5610 if(!prc)
5611 return(-1);
5613 if(prc->quit_to_edit){
5614 if(!(flags & WRP_NOUSER))
5615 quit_to_edit_msg(prc);
5617 return(-1);
5620 if(prc->type != Loc && !prc->readonly){
5622 bc = 0; /* don't do backcompat conversion */
5623 rd = prc->rd;
5624 if(!rd)
5625 return(-1);
5627 rd_check_remvalid(rd, -10L);
5629 if(rd->flags & REM_OUTOFDATE){
5630 if((flags & WRP_NOUSER) || unexpected_pinerc_change()){
5631 prc->outstanding_pinerc_changes = 1;
5632 if(!(flags & WRP_NOUSER))
5633 q_status_message1(SM_ORDER | SM_DING, 3, 3,
5634 "Pinerc \"%.200s\" NOT saved",
5635 prc->name ? prc->name : "");
5636 dprint((2, "write_pinerc: remote pinerc changed\n"));
5637 return(-1);
5639 else
5640 rd->flags &= ~REM_OUTOFDATE;
5643 rd_open_remote(rd);
5645 if(rd->access == ReadWrite){
5646 int ro;
5648 if((ro=rd_remote_is_readonly(rd)) || rd->flags & REM_OUTOFDATE){
5649 if(ro == 1){
5650 if(!(flags & WRP_NOUSER))
5651 q_status_message(SM_ORDER | SM_DING, 5, 15,
5652 _("Can't access remote config, changes NOT saved!"));
5653 dprint((1,
5654 "write_pinerc: Can't write to remote pinerc %s, aborting write\n",
5655 rd->rn ? rd->rn : "?"));
5657 else if(ro == 2){
5658 if(!(rd->flags & NO_META_UPDATE)){
5659 unsigned long save_chk_nmsgs;
5661 switch(rd->type){
5662 case RemImap:
5663 save_chk_nmsgs = rd->t.i.chk_nmsgs;
5664 rd->t.i.chk_nmsgs = 0;
5665 rd_write_metadata(rd, 0);
5666 rd->t.i.chk_nmsgs = save_chk_nmsgs;
5667 break;
5669 default:
5670 q_status_message(SM_ORDER | SM_DING, 3, 5,
5671 "Write_pinerc: Type not supported");
5672 break;
5676 if(!(flags & WRP_NOUSER))
5677 q_status_message1(SM_ORDER | SM_DING, 5, 15,
5678 _("No write permission for remote config %.200s, changes NOT saved!"),
5679 rd->rn);
5681 else{
5682 if(!(flags & WRP_NOUSER))
5683 q_status_message(SM_ORDER | SM_DING, 5, 15,
5684 _("Remote config changed, aborting our change to avoid damage..."));
5685 dprint((1,
5686 "write_pinerc: remote config %s changed since we started pine, aborting write\n",
5687 prc->name ? prc->name : "?"));
5690 rd->flags &= ~DO_REMTRIM;
5691 return(-1);
5694 filename = rd->lf;
5696 else{
5697 prc->readonly = 1;
5698 if(prc == ps->prc)
5699 ps->readonly_pinerc = 1;
5702 else
5703 filename = prc->name ? prc->name : "";
5705 pinrc = prc->name ? prc->name : "";
5707 if(prc->type == Loc){
5708 mtime = name_file_mtime(filename);
5709 if(prc->pinerc_written
5710 && prc->pinerc_written != mtime
5711 && ((flags & WRP_NOUSER) || unexpected_pinerc_change())){
5712 prc->outstanding_pinerc_changes = 1;
5714 if(!(flags & WRP_NOUSER))
5715 q_status_message1(SM_ORDER | SM_DING, 3, 3,
5716 "Pinerc \"%.200s\" NOT saved", pinrc);
5718 dprint((2,"write_pinerc: mtime mismatch: \"%s\": %ld != %ld\n",
5719 filename ? filename : "?",
5720 (long) prc->pinerc_written, (long) mtime));
5721 return(-1);
5725 /* don't write if pinerc is read-only */
5726 if(prc->readonly ||
5727 (filename &&
5728 can_access(filename, ACCESS_EXISTS) == 0 &&
5729 can_access(filename, EDIT_ACCESS) != 0)){
5730 prc->readonly = 1;
5731 if(prc == ps->prc)
5732 ps->readonly_pinerc = 1;
5734 if(!(flags & WRP_NOUSER))
5735 q_status_message1(SM_ORDER | SM_DING, 0, 5,
5736 _("Can't modify configuration file \"%.200s\": ReadOnly"),
5737 pinrc);
5738 dprint((2, "write_pinerc: fail because can't access pinerc\n"));
5740 if(rd)
5741 rd->flags &= ~DO_REMTRIM;
5743 return(-1);
5746 if(rd && rd->flags & NO_FILE){
5747 so = rd->sonofile;
5748 so_truncate(rd->sonofile, 0L); /* reset storage object */
5750 else{
5751 dir = ".";
5752 if((p = last_cmpnt(filename)) != NULL){
5753 *--p = '\0';
5754 dir = filename;
5757 #if defined(DOS) || defined(OS2)
5758 if(!(isalpha((unsigned char)dir[0]) && dir[1] == ':' && dir[2] == '\0')
5759 && (can_access(dir, EDIT_ACCESS) < 0 &&
5760 our_mkdir(dir, 0700) < 0))
5762 if(!(flags & WRP_NOUSER))
5763 q_status_message2(SM_ORDER | SM_DING, 3, 5,
5764 /* TRANSLATORS: first argument is a filename, second
5765 arg is the text of the error message */
5766 _("Error creating \"%.200s\" : %.200s"), dir,
5767 error_description(errno));
5768 if(rd)
5769 rd->flags &= ~DO_REMTRIM;
5771 return(-1);
5774 tmp = temp_nam(dir, "rc");
5776 if(*dir && tmp && !in_dir(dir, tmp)){
5777 our_unlink(tmp);
5778 fs_give((void **)&tmp);
5781 if(p)
5782 *p = '\\';
5784 if(tmp == NULL)
5785 goto io_err;
5787 #else /* !DOS */
5788 tmp = temp_nam((*dir) ? dir : "/", "pinerc");
5791 * If temp_nam can't write in dir it puts the temp file in a
5792 * temp directory, which won't help us when we go to rename.
5794 if(*dir && tmp && !in_dir(dir, tmp)){
5795 our_unlink(tmp);
5796 fs_give((void **)&tmp);
5799 if(p)
5800 *p = '/';
5802 if(tmp == NULL)
5803 goto io_err;
5805 #endif /* !DOS */
5807 if((so = so_get(FileStar, tmp, WRITE_ACCESS)) == NULL)
5808 goto io_err;
5811 if(!(flags & WRP_PRESERV_WRITTEN))
5812 for(var = ps->vars; var->name != NULL; var++)
5813 var->been_written = 0;
5815 if(prc->type == Loc && ps->first_time_user &&
5816 !so_puts(so, native_nl(cf_text_comment)))
5817 goto io_err;
5819 linep = fs_get((MAXPLINESIZE+1)*sizeof(char));
5820 lineq = fs_get((MAXPLINESIZE+1)*sizeof(char));
5821 buflen = MAXPLINESIZE;
5823 /* Write out what was in the .pinerc */
5824 for(pline = prc->pinerc_lines;
5825 pline && (pline->is_var || pline->line); pline++){
5826 if(pline->is_var){
5827 var = pline->var;
5829 if(var->is_list)
5830 lval = LVAL(var, which);
5831 else
5832 pval = PVAL(var, which);
5834 /* variable is not set */
5835 if((var->is_list && (!lval || !lval[0])) ||
5836 (!var->is_list && !pval)){
5837 /* leave null variables out of remote pinerc */
5838 if(prc->type == Loc &&
5839 (!so_puts(so, var->name) || !so_puts(so, "=") ||
5840 !so_puts(so, NEWLINE)))
5841 goto io_err;
5843 /* var is set to empty string */
5844 else if((var->is_list && lval[0][0] == '\0') ||
5845 (!var->is_list && pval[0] == '\0')){
5846 if(!so_puts(so, var->name) || !so_puts(so, "=") ||
5847 !so_puts(so, quotes) || !so_puts(so, NEWLINE))
5848 goto io_err;
5850 else{
5851 if(var->is_list){
5852 int i = 0;
5854 for(i = 0; lval[i]; i++){
5855 if(strlen(var->name)
5856 + (lval[i][0] ? strlen(lval[i]) : 5) > buflen){
5857 buflen = strlen(var->name)
5858 + (lval[i][0] ? strlen(lval[i]) : 5);
5859 fs_resize((void **)&linep, (buflen+1)*sizeof(char));
5860 fs_resize((void **)&lineq, (buflen+1)*sizeof(char));
5862 snprintf(linep, buflen+1, "%s%s%s%s%s",
5863 (i) ? "\t" : var->name,
5864 (i) ? "" : "=",
5865 lval[i][0] ? lval[i] : quotes,
5866 lval[i+1] ? "," : "", NEWLINE);
5867 linep[buflen] = '\0';
5868 if(!so_puts(so, bc ? backcompat_convert_from_utf8(&lineq, buflen+1, linep) : linep))
5869 goto io_err;
5872 else{
5873 if(strlen(var->name)
5874 + (pval[0] ? strlen(pval) : 5) > buflen){
5875 buflen = strlen(var->name)
5876 + (pval[0] ? strlen(pval) : 5);
5877 fs_resize((void **)&linep, (buflen+1)*sizeof(char));
5878 fs_resize((void **)&lineq, (buflen+1)*sizeof(char));
5880 snprintf(linep, buflen+1, "%s=%s%s%s%s",
5881 var->name,
5882 (pline->is_quoted && pval[0] != '\"')
5883 ? "\"" : "",
5884 pval,
5885 (pline->is_quoted && pval[0] != '\"')
5886 ? "\"" : "", NEWLINE);
5887 linep[buflen] = '\0';
5888 if(!so_puts(so, bc ? backcompat_convert_from_utf8(&lineq, buflen+1, linep) : linep))
5889 goto io_err;
5893 var->been_written = 1;
5895 }else{
5897 * The description text should be changed into a message
5898 * about the variable being obsolete when a variable is
5899 * moved to obsolete status. We add that message before
5900 * the variable unless it is already there. However, we
5901 * leave the variable itself in case the user runs an old
5902 * version of pine again. Note that we have read in the
5903 * value of the variable in read_pinerc and translated it
5904 * into a new variable if appropriate.
5906 if(pline->obsolete_var && prc->type == Loc){
5907 if(pline <= prc->pinerc_lines || (pline-1)->line == NULL ||
5908 strlen((pline-1)->line) < 3 ||
5909 strucmp((pline-1)->line+2, pline->var->descrip) != 0)
5910 if(!so_puts(so, "# ") ||
5911 !so_puts(so, native_nl(pline->var->descrip)) ||
5912 !so_puts(so, NEWLINE))
5913 goto io_err;
5916 /* remove comments from remote pinercs */
5917 if((prc->type == Loc ||
5918 (pline->line[0] != '#' && pline->line[0] != '\0')) &&
5919 (!so_puts(so, pline->line) || !so_puts(so, NEWLINE)))
5920 goto io_err;
5924 /* Now write out all the variables not in the .pinerc */
5925 for(var = ps->vars; var->name != NULL; var++){
5926 if(!var->is_user || var->been_written || !var->is_used ||
5927 var->is_obsolete || (var->is_onlymain && which != Main))
5928 continue;
5930 if(var->is_list)
5931 lval = LVAL(var, which);
5932 else
5933 pval = PVAL(var, which);
5936 * set description to NULL to eliminate preceding
5937 * blank and comment line.
5939 if(prc->type == Loc && var->descrip && *var->descrip &&
5940 (!so_puts(so, NEWLINE) || !so_puts(so, "# ") ||
5941 !so_puts(so, native_nl(var->descrip)) || !so_puts(so, NEWLINE)))
5942 goto io_err;
5944 /* variable is not set */
5945 /** Don't know what the global_val thing is for. SH, Mar 00 **/
5946 if((var->is_list && (!lval || (!lval[0] && !var->global_val.l))) ||
5947 (!var->is_list && !pval)){
5948 /* leave null variables out of remote pinerc */
5949 if(prc->type == Loc &&
5950 (!so_puts(so, var->name) || !so_puts(so, "=") ||
5951 !so_puts(so, NEWLINE)))
5952 goto io_err;
5954 /* var is set to empty string */
5955 else if((var->is_list && (!lval[0] || !lval[0][0]))
5956 || (!var->is_list && pval[0] == '\0')){
5957 if(!so_puts(so, var->name) || !so_puts(so, "=") ||
5958 !so_puts(so, quotes) || !so_puts(so, NEWLINE))
5959 goto io_err;
5961 else if(var->is_list){
5962 int i = 0;
5964 for(i = 0; lval[i] ; i++){
5965 if(strlen(var->name)
5966 + (lval[i][0] ? strlen(lval[i]) : 5) > buflen){
5967 buflen = strlen(var->name)
5968 + (lval[i][0] ? strlen(lval[i]) : 5);
5969 fs_resize((void **)&linep, (buflen+1)*sizeof(char));
5970 fs_resize((void **)&lineq, (buflen+1)*sizeof(char));
5972 snprintf(linep, buflen+1, "%s%s%s%s%s",
5973 (i) ? "\t" : var->name,
5974 (i) ? "" : "=",
5975 lval[i],
5976 lval[i+1] ? "," : "", NEWLINE);
5977 linep[buflen] = '\0';
5978 if(!so_puts(so, bc ? backcompat_convert_from_utf8(&lineq, buflen+1, linep) : linep))
5979 goto io_err;
5982 else{
5983 char *pconverted;
5985 if(strlen(pval) > buflen){
5986 buflen = strlen(pval) + 1;
5987 fs_resize((void **)&linep, (buflen+1)*sizeof(char));
5988 fs_resize((void **)&lineq, (buflen+1)*sizeof(char));
5990 pconverted = bc ? backcompat_convert_from_utf8(&lineq, buflen+1, pval) : pval;
5992 if(!so_puts(so, var->name) || !so_puts(so, "=") ||
5993 !so_puts(so, pconverted) || !so_puts(so, NEWLINE))
5994 goto io_err;
5998 if(!(rd && rd->flags & NO_FILE)){
5999 char *realfilename;
6000 int realfilename_malloced;
6002 if(so_give(&so)) goto io_err;
6004 #ifndef _WINDOWS
6005 realfilename = fs_get(MAXPATH+1);
6006 if(realfilename != NULL){
6007 if(realpath(filename, realfilename) == NULL)
6008 fs_give((void **) &realfilename);
6009 realfilename_malloced = realfilename != NULL ? 1 : 0;
6011 else
6012 realfilename_malloced = 0;
6013 if (realfilename_malloced == 0){
6014 if(our_stat(filename, &sbuf) < 0 && errno == ENOENT){
6015 realfilename = filename;
6016 realfilename_malloced = 0;
6018 else
6019 goto io_err;
6021 #else
6022 realfilename = filename;
6023 realfilename_malloced = 0;
6024 #endif /* _WINDOWS */
6025 if(realfilename != NULL){
6026 int r;
6027 file_attrib_copy(tmp, realfilename);
6028 r = rename_file(tmp, realfilename);
6029 if(realfilename_malloced != 0)
6030 fs_give((void **) &realfilename);
6031 if(r < 0) goto io_err;
6035 if(prc->type != Loc){
6036 int e, we_cancel;
6037 char datebuf[200];
6039 datebuf[0] = '\0';
6040 we_cancel = 0;
6042 if(!(flags & WRP_NOUSER))
6043 we_cancel = busy_cue(_("Copying to remote config"), NULL, 1);
6045 if((e = rd_update_remote(rd, datebuf)) != 0){
6046 dprint((1,
6047 "write_pinerc: error copying from %s to %s\n",
6048 rd->lf ? rd->lf : "<memory>", rd->rn ? rd->rn : "?"));
6049 if(!(flags & WRP_NOUSER)){
6050 q_status_message2(SM_ORDER | SM_DING, 3, 5,
6051 _("Error copying to %.200s: %.200s"),
6052 rd->rn, error_description(errno));
6054 q_status_message(SM_ORDER | SM_DING, 5, 5,
6055 _("Copy of config to remote folder failed, changes NOT saved remotely"));
6058 else{
6059 rd_update_metadata(rd, datebuf);
6060 rd->read_status = 'W';
6061 rd_trim_remdata(&rd);
6062 rd_close_remote(rd);
6065 if(we_cancel)
6066 cancel_busy_cue(-1);
6069 prc->outstanding_pinerc_changes = 0;
6071 if(prc->type == Loc){
6072 prc->pinerc_written = name_file_mtime(filename);
6073 dprint((2, "wrote pinerc: %s: time_pinerc_written = %ld\n",
6074 pinrc ? pinrc : "?", (long) prc->pinerc_written));
6076 else{
6077 dprint((2, "wrote pinerc: %s\n", pinrc ? pinrc : "?"));
6080 if(tmp){
6081 our_unlink(tmp);
6082 fs_give((void **)&tmp);
6085 if(linep) fs_give((void **)&linep);
6086 if(lineq) fs_give((void **)&lineq);
6088 return(0);
6090 io_err:
6091 if(!(flags & WRP_NOUSER))
6092 q_status_message2(SM_ORDER | SM_DING, 3, 5,
6093 _("Error saving configuration in \"%.200s\": %.200s"),
6094 pinrc, error_description(errno));
6096 dprint((1, "Error writing %s : %s\n", pinrc ? pinrc : "?",
6097 error_description(errno)));
6098 if(rd)
6099 rd->flags &= ~DO_REMTRIM;
6100 if(tmp){
6101 our_unlink(tmp);
6102 fs_give((void **)&tmp);
6105 if(linep) fs_give((void **)&linep);
6106 if(lineq) fs_give((void **)&lineq);
6108 return(-1);
6113 * The srcstr is UTF-8. In order to help the user with
6114 * running this pine and an old pre-alpine pine on the same config
6115 * file we attempt to convert the values of the config variables
6116 * to the user's character set before writing.
6117 * parameters: char **buf. Memory of size_t buflen allocated by caller.
6119 char *
6120 backcompat_convert_from_utf8(char **buf, size_t buflen, char *srcstr)
6122 char *converted = NULL;
6123 char *p;
6124 int its_ascii = 1;
6127 for(p = srcstr; *p && its_ascii; p++)
6128 if(*p & 0x80)
6129 its_ascii = 0;
6131 /* if it is ascii, go with that */
6132 if(its_ascii){
6133 strncpy(*buf, srcstr, buflen);
6134 converted = *buf;
6135 (*buf)[buflen-1] = '\0';
6137 else{
6138 char *trythischarset = NULL;
6141 * If it is possible to translate the UTF-8
6142 * string into the user's character set then
6143 * do that. For backwards compatibility with
6144 * old pines.
6146 if(ps_global->keyboard_charmap && ps_global->keyboard_charmap[0])
6147 trythischarset = ps_global->keyboard_charmap;
6148 else if(ps_global->display_charmap && ps_global->display_charmap[0])
6149 trythischarset = ps_global->display_charmap;
6151 if(trythischarset){
6152 SIZEDTEXT src, dst;
6154 src.data = (unsigned char *) srcstr;
6155 src.size = strlen(srcstr);
6156 memset(&dst, 0, sizeof(dst));
6157 if(utf8_cstext(&src, trythischarset, &dst, 0)){
6158 if(dst.data){
6159 strncpy(*buf, (char *) dst.data, buflen);
6160 (*buf)[buflen-1] = '\0';
6161 fs_give((void **) &dst.data);
6166 if(!converted){
6167 strncpy(*buf, srcstr, buflen);
6168 (*buf)[buflen-1] = '\0';
6169 converted = *buf;
6173 return(converted);
6178 * Given a unix-style source string which may contain LFs,
6179 * convert those to CRLFs if appropriate.
6181 * Returns a pointer to the converted string. This will be a string
6182 * stored in tmp_20k_buf.
6184 * This is just used for the variable descriptions in the pinerc file. It
6185 * could certainly be fancier. It simply converts all \n to NEWLINE.
6187 char *
6188 native_nl(char *src)
6190 char *q, *p;
6192 tmp_20k_buf[0] = '\0';
6194 if(src){
6195 for(q = (char *)tmp_20k_buf; *src; src++){
6196 if(*src == '\n'){
6197 for(p = NEWLINE; *p; p++)
6198 *q++ = *p;
6200 else
6201 *q++ = *src;
6204 *q = '\0';
6207 return((char *)tmp_20k_buf);
6211 void
6212 quit_to_edit_msg(PINERC_S *prc)
6214 /* TRANSLATORS: The %s is either "Postload " or nothing. A Postload config file
6215 is a type of config file. */
6216 q_status_message1(SM_ORDER, 3, 4, _("Must quit Alpine to change %sconfig file."),
6217 (prc == ps_global->post_prc) ? "Postload " : "");
6221 /*------------------------------------------------------------
6222 Return TRUE if the given string was a feature name present in the
6223 pinerc as it was when pine was started...
6224 ----*/
6226 var_in_pinerc(char *s)
6228 PINERC_LINE *pline;
6230 for(pline = ps_global->prc ? ps_global->prc->pinerc_lines : NULL;
6231 pline && (pline->var || pline->line); pline++)
6232 if(pline->var && pline->var->name && !strucmp(s, pline->var->name))
6233 return(1);
6235 for(pline = ps_global->post_prc ? ps_global->post_prc->pinerc_lines : NULL;
6236 pline && (pline->var || pline->line); pline++)
6237 if(pline->var && pline->var->name && !strucmp(s, pline->var->name))
6238 return(1);
6240 return(0);
6244 /*------------------------------------------------------------
6245 Free resources associated with pinerc_lines data
6246 ----*/
6247 void
6248 free_pinerc_lines(PINERC_LINE **pinerc_lines)
6250 PINERC_LINE *pline;
6252 if(pinerc_lines && *pinerc_lines){
6253 for(pline = *pinerc_lines; pline->var || pline->line; pline++)
6254 if(pline->line)
6255 fs_give((void **)&pline->line);
6257 fs_give((void **)pinerc_lines);
6262 /*------------------------------------------------------------
6263 Dump out a global pine.conf on the standard output with fresh
6264 comments. Preserves variables currently set in SYSTEM_PINERC, if any.
6265 ----*/
6266 void
6267 dump_global_conf(void)
6269 FILE *f;
6270 struct variable *var;
6271 PINERC_S *prc;
6273 prc = new_pinerc_s(SYSTEM_PINERC);
6274 read_pinerc(prc, variables, ParseGlobal);
6275 if(prc)
6276 free_pinerc_s(&prc);
6278 f = stdout;
6279 if(f == NULL)
6280 goto io_err;
6282 fprintf(f, "# %s -- system wide pine configuration\n#\n",
6283 SYSTEM_PINERC);
6284 fprintf(f, "# Values here affect all pine users unless they've overridden the values\n");
6285 fprintf(f, "# in their .pinerc files. A copy of this file with current comments may\n");
6286 fprintf(f, "# be obtained by running \"pine -conf\". It will be printed to standard output.\n#\n");
6287 fprintf(f,"# For a variable to be unset its value must be null/blank. This is not the\n");
6288 fprintf(f,"# same as the value of \"empty string\", which can be used to effectively\n");
6289 fprintf(f,"# \"unset\" a variable that has a default or previously assigned value.\n");
6290 fprintf(f,"# To set a variable to the empty string its value should be \"\".\n");
6291 fprintf(f,"# Switch variables are set to either \"yes\" or \"no\", and default to \"no\".\n");
6292 fprintf(f,"# Except for feature-list items, which are additive, values set in the\n");
6293 fprintf(f,"# .pinerc file replace those in pine.conf, and those in pine.conf.fixed\n");
6294 fprintf(f,"# over-ride all others. Features can be over-ridden in .pinerc or\n");
6295 fprintf(f,"# pine.conf.fixed by pre-pending the feature name with \"no-\".\n#\n");
6296 fprintf(f,"# (These comments are automatically inserted.)\n");
6298 for(var = variables; var->name != NULL; var++){
6299 if(!var->is_global || !var->is_used || var->is_obsolete)
6300 continue;
6302 if(var->descrip && *var->descrip){
6303 if(fprintf(f, "\n# %s\n", var->descrip) == EOF)
6304 goto io_err;
6307 if(var->is_list){
6308 if(var->global_val.l == NULL){
6309 if(fprintf(f, "%s=\n", var->name) == EOF)
6310 goto io_err;
6311 }else{
6312 int i;
6314 for(i=0; var->global_val.l[i]; i++)
6315 if(fprintf(f, "%s%s%s%s\n", (i) ? "\t" : var->name,
6316 (i) ? "" : "=", var->global_val.l[i],
6317 var->global_val.l[i+1] ? ",":"") == EOF)
6318 goto io_err;
6320 }else{
6321 if(var->global_val.p == NULL){
6322 if(fprintf(f, "%s=\n", var->name) == EOF)
6323 goto io_err;
6324 }else if(strlen(var->global_val.p) == 0){
6325 if(fprintf(f, "%s=\"\"\n", var->name) == EOF)
6326 goto io_err;
6327 }else{
6328 if(fprintf(f,"%s=%s\n",var->name,var->global_val.p) == EOF)
6329 goto io_err;
6333 exit(0);
6336 io_err:
6337 fprintf(stderr, "Error writing config to stdout: %s\n",
6338 error_description(errno));
6339 exit(-1);
6343 /*------------------------------------------------------------
6344 Dump out a pinerc to filename with fresh
6345 comments. Preserves variables currently set in pinerc, if any.
6346 ----*/
6347 void
6348 dump_new_pinerc(char *filename)
6350 FILE *f;
6351 struct variable *var;
6352 char buf[MAXPATH], *p;
6353 PINERC_S *prc;
6356 p = ps_global->pinerc;
6358 #if defined(DOS) || defined(OS2)
6359 if(!ps_global->pinerc){
6360 char *p;
6362 if(p = getenv("PINERC")){
6363 ps_global->pinerc = cpystr(p);
6364 }else{
6365 char buf2[MAXPATH];
6366 build_path(buf2, ps_global->home_dir, DF_PINEDIR, sizeof(buf2));
6367 build_path(buf, buf2, SYSTEM_PINERC, sizeof(buf));
6370 p = buf;
6372 #else /* !DOS */
6373 if(!ps_global->pinerc){
6374 build_path(buf, ps_global->home_dir, ".pinerc", sizeof(buf));
6375 p = buf;
6377 #endif /* !DOS */
6379 prc = new_pinerc_s(p);
6380 read_pinerc(prc, variables, ParsePers);
6381 if(prc)
6382 free_pinerc_s(&prc);
6384 f = NULL;;
6385 if(filename[0] == '\0'){
6386 fprintf(stderr, "Missing argument to \"-pinerc\".\n");
6387 }else if(!strcmp(filename, "-")){
6388 f = stdout;
6389 }else{
6390 f = our_fopen(filename, "wb");
6393 if(f == NULL)
6394 goto io_err;
6396 if(fprintf(f, "%s", cf_text_comment) == EOF)
6397 goto io_err;
6399 for(var = variables; var->name != NULL; var++){
6400 dprint((7,"write_pinerc: %s = %s\n",
6401 var->name ? var->name : "?",
6402 var->main_user_val.p ? var->main_user_val.p : "<not set>"));
6403 if(!var->is_user || !var->is_used || var->is_obsolete)
6404 continue;
6407 * set description to NULL to eliminate preceding
6408 * blank and comment line.
6410 if(var->descrip && *var->descrip){
6411 if(fprintf(f, "\n# %s\n", var->descrip) == EOF)
6412 goto io_err;
6415 if(var->is_list){
6416 if(var->main_user_val.l == NULL){
6417 if(fprintf(f, "%s=\n", var->name) == EOF)
6418 goto io_err;
6419 }else{
6420 int i;
6422 for(i=0; var->main_user_val.l[i]; i++)
6423 if(fprintf(f, "%s%s%s%s\n", (i) ? "\t" : var->name,
6424 (i) ? "" : "=", var->main_user_val.l[i],
6425 var->main_user_val.l[i+1] ? ",":"") == EOF)
6426 goto io_err;
6428 }else{
6429 if(var->main_user_val.p == NULL){
6430 if(fprintf(f, "%s=\n", var->name) == EOF)
6431 goto io_err;
6432 }else if(strlen(var->main_user_val.p) == 0){
6433 if(fprintf(f, "%s=\"\"\n", var->name) == EOF)
6434 goto io_err;
6435 }else{
6436 if(fprintf(f,"%s=%s\n",var->name,var->main_user_val.p) == EOF)
6437 goto io_err;
6441 exit(0);
6444 io_err:
6445 snprintf(buf, sizeof(buf), "Error writing config to %s: %s\n",
6446 filename, error_description(errno));
6447 exceptional_exit(buf, -1);
6451 /*----------------------------------------------------------------------
6452 Set a user variable and save the .pinerc
6454 Args: var -- The index of the variable to set from conftype.h (V_....)
6455 value -- The string to set the value to
6457 Result: -1 is returned on failure and 0 is returned on success
6459 The vars data structure is updated and the pinerc saved.
6460 ----*/
6462 set_variable(int var, char *value, int expand, int commit, EditWhich which)
6464 struct variable *v;
6465 char **apval;
6466 PINERC_S *prc;
6468 v = &ps_global->vars[var];
6470 if(!v->is_user)
6471 panic1("Trying to set non-user variable %s", v->name);
6473 /* Override value of which, at most one of these should be set */
6474 if(v->is_onlymain)
6475 which = Main;
6476 else if(v->is_outermost)
6477 which = ps_global->ew_for_except_vars;
6479 apval = APVAL(v, which);
6481 if(!apval)
6482 return(-1);
6484 if(*apval)
6485 fs_give((void **)apval);
6487 *apval = value ? cpystr(value) : NULL;
6488 set_current_val(v, expand, FALSE);
6490 switch(which){
6491 case Main:
6492 prc = ps_global->prc;
6493 break;
6494 case Post:
6495 prc = ps_global->post_prc;
6496 break;
6497 default:
6498 break;
6501 if(prc)
6502 prc->outstanding_pinerc_changes = 1;
6504 return(commit ? write_pinerc(ps_global, which, WRP_NONE) : 0);
6508 /*----------------------------------------------------------------------
6509 Set a user variable list and save the .pinerc
6511 Args: var -- The index of the variable to set from conftype.h (V_....)
6512 lvalue -- The list to set the value to
6514 Result: -1 is returned on failure and 0 is returned on success
6516 The vars data structure is updated and if write_it, the pinerc is saved.
6517 ----*/
6519 set_variable_list(int var, char **lvalue, int write_it, EditWhich which)
6521 char ***alval;
6522 int i;
6523 struct variable *v = &ps_global->vars[var];
6524 PINERC_S *prc;
6526 if(!v->is_user || !v->is_list)
6527 panic1("BOTCH: Trying to set non-user or non-list variable %s", v->name);
6529 /* Override value of which, at most one of these should be set */
6530 if(v->is_onlymain)
6531 which = Main;
6532 else if(v->is_outermost)
6533 which = ps_global->ew_for_except_vars;
6535 alval = ALVAL(v, which);
6536 if(!alval)
6537 return(-1);
6539 if(*alval)
6540 free_list_array(alval);
6542 if(lvalue){
6543 for(i = 0; lvalue[i] ; i++) /* count elements */
6546 *alval = (char **) fs_get((i+1) * sizeof(char *));
6548 for(i = 0; lvalue[i] ; i++)
6549 (*alval)[i] = cpystr(lvalue[i]);
6551 (*alval)[i] = NULL;
6554 set_current_val(v, TRUE, FALSE);
6556 switch(which){
6557 case Main:
6558 prc = ps_global->prc;
6559 break;
6560 case Post:
6561 prc = ps_global->post_prc;
6562 break;
6563 default:
6564 break;
6567 if(prc)
6568 prc->outstanding_pinerc_changes = 1;
6570 return(write_it ? write_pinerc(ps_global, which, WRP_NONE) : 0);
6574 void
6575 set_current_color_vals(struct pine *ps)
6577 struct variable *vars = ps->vars;
6578 int later_color_is_set = 0;
6580 set_current_val(&vars[V_NORM_FORE_COLOR], TRUE, TRUE);
6581 set_current_val(&vars[V_NORM_BACK_COLOR], TRUE, TRUE);
6582 pico_nfcolor(VAR_NORM_FORE_COLOR);
6583 pico_nbcolor(VAR_NORM_BACK_COLOR);
6585 set_current_val(&vars[V_REV_FORE_COLOR], TRUE, TRUE);
6586 set_current_val(&vars[V_REV_BACK_COLOR], TRUE, TRUE);
6587 pico_rfcolor(VAR_REV_FORE_COLOR);
6588 pico_rbcolor(VAR_REV_BACK_COLOR);
6590 set_color_val(&vars[V_TITLE_FORE_COLOR], 1);
6591 set_color_val(&vars[V_TITLECLOSED_FORE_COLOR], 0);
6592 set_color_val(&vars[V_FOLDER_FORE_COLOR], 0);
6593 set_color_val(&vars[V_DIRECTORY_FORE_COLOR], 0);
6594 set_color_val(&vars[V_FOLDER_LIST_FORE_COLOR], 0);
6595 set_color_val(&vars[V_STATUS_FORE_COLOR], 1);
6596 set_color_val(&vars[V_KEYLABEL_FORE_COLOR], 1);
6597 set_color_val(&vars[V_KEYNAME_FORE_COLOR], 1);
6598 set_color_val(&vars[V_SLCTBL_FORE_COLOR], 1);
6599 set_color_val(&vars[V_METAMSG_FORE_COLOR], 1);
6600 set_color_val(&vars[V_PROMPT_FORE_COLOR], 1);
6601 set_color_val(&vars[V_HEADER_GENERAL_FORE_COLOR], 1);
6602 set_color_val(&vars[V_IND_PLUS_FORE_COLOR], 0);
6603 set_color_val(&vars[V_IND_IMP_FORE_COLOR], 0);
6604 set_color_val(&vars[V_IND_DEL_FORE_COLOR], 0);
6605 set_color_val(&vars[V_IND_HIPRI_FORE_COLOR], 0);
6606 set_color_val(&vars[V_IND_LOPRI_FORE_COLOR], 0);
6607 set_color_val(&vars[V_IND_ANS_FORE_COLOR], 0);
6608 set_color_val(&vars[V_IND_NEW_FORE_COLOR], 0);
6609 set_color_val(&vars[V_IND_REC_FORE_COLOR], 0);
6610 set_color_val(&vars[V_IND_FWD_FORE_COLOR], 0);
6611 set_color_val(&vars[V_IND_UNS_FORE_COLOR], 0);
6612 set_color_val(&vars[V_IND_ARR_FORE_COLOR], 0);
6613 set_color_val(&vars[V_IND_SUBJ_FORE_COLOR], 0);
6614 set_color_val(&vars[V_IND_FROM_FORE_COLOR], 0);
6615 set_color_val(&vars[V_IND_OP_FORE_COLOR], 0);
6616 set_color_val(&vars[V_INCUNSEEN_FORE_COLOR], 0);
6617 set_color_val(&vars[V_SIGNATURE_FORE_COLOR], 0);
6619 set_current_val(&ps->vars[V_INDEX_TOKEN_COLORS], TRUE, TRUE);
6620 set_current_val(&ps->vars[V_VIEW_HDR_COLORS], TRUE, TRUE);
6621 set_current_val(&ps->vars[V_KW_COLORS], TRUE, TRUE);
6622 set_custom_spec_colors(ps);
6625 * Set up the quoting colors. If a later color is set but not an earlier
6626 * color we set the earlier color to Normal to make it easier when
6627 * we go to use the colors. However, if the only quote colors set are
6628 * Normal that is the same as no settings, so delete them.
6630 set_color_val(&vars[V_QUOTE1_FORE_COLOR], 0);
6631 set_color_val(&vars[V_QUOTE2_FORE_COLOR], 0);
6632 set_color_val(&vars[V_QUOTE3_FORE_COLOR], 0);
6634 if((!(VAR_QUOTE3_FORE_COLOR && VAR_QUOTE3_BACK_COLOR) ||
6635 (!strucmp(VAR_QUOTE3_FORE_COLOR, VAR_NORM_FORE_COLOR) &&
6636 !strucmp(VAR_QUOTE3_BACK_COLOR, VAR_NORM_BACK_COLOR))) &&
6637 (!(VAR_QUOTE2_FORE_COLOR && VAR_QUOTE2_BACK_COLOR) ||
6638 (!strucmp(VAR_QUOTE2_FORE_COLOR, VAR_NORM_FORE_COLOR) &&
6639 !strucmp(VAR_QUOTE2_BACK_COLOR, VAR_NORM_BACK_COLOR))) &&
6640 (!(VAR_QUOTE1_FORE_COLOR && VAR_QUOTE1_BACK_COLOR) ||
6641 (!strucmp(VAR_QUOTE1_FORE_COLOR, VAR_NORM_FORE_COLOR) &&
6642 !strucmp(VAR_QUOTE1_BACK_COLOR, VAR_NORM_BACK_COLOR)))){
6644 * They are all either Normal or not set. Delete them all.
6646 if(VAR_QUOTE3_FORE_COLOR)
6647 fs_give((void **)&VAR_QUOTE3_FORE_COLOR);
6648 if(VAR_QUOTE3_BACK_COLOR)
6649 fs_give((void **)&VAR_QUOTE3_BACK_COLOR);
6650 if(VAR_QUOTE2_FORE_COLOR)
6651 fs_give((void **)&VAR_QUOTE2_FORE_COLOR);
6652 if(VAR_QUOTE2_BACK_COLOR)
6653 fs_give((void **)&VAR_QUOTE2_BACK_COLOR);
6654 if(VAR_QUOTE1_FORE_COLOR)
6655 fs_give((void **)&VAR_QUOTE1_FORE_COLOR);
6656 if(VAR_QUOTE1_BACK_COLOR)
6657 fs_give((void **)&VAR_QUOTE1_BACK_COLOR);
6659 else{ /* something is non-Normal */
6660 if(VAR_QUOTE3_FORE_COLOR && VAR_QUOTE3_BACK_COLOR)
6661 later_color_is_set++;
6663 /* if 3 is set but not 2, set 2 to Normal */
6664 if(VAR_QUOTE2_FORE_COLOR && VAR_QUOTE2_BACK_COLOR)
6665 later_color_is_set++;
6666 else if(later_color_is_set)
6667 set_color_val(&vars[V_QUOTE2_FORE_COLOR], 1);
6669 /* if 3 or 2 is set but not 1, set 1 to Normal */
6670 if(VAR_QUOTE1_FORE_COLOR && VAR_QUOTE1_BACK_COLOR)
6671 later_color_is_set++;
6672 else if(later_color_is_set)
6673 set_color_val(&vars[V_QUOTE1_FORE_COLOR], 1);
6676 #ifdef _WINDOWS
6677 if(ps->pre441){
6678 int conv_main = 0, conv_post = 0;
6680 ps->pre441 = 0;
6681 if(ps->prc && !unix_color_style_in_pinerc(ps->prc)){
6682 conv_main = convert_pc_gray_names(ps, ps->prc, Main);
6683 if(conv_main)
6684 ps->prc->outstanding_pinerc_changes = 1;
6688 if(ps->post_prc && !unix_color_style_in_pinerc(ps->post_prc)){
6689 conv_post = convert_pc_gray_names(ps, ps->post_prc, Post);
6690 if(conv_post)
6691 ps->post_prc->outstanding_pinerc_changes = 1;
6694 if(conv_main || conv_post){
6695 if(conv_main)
6696 write_pinerc(ps, Main, WRP_NONE);
6698 if(conv_post)
6699 write_pinerc(ps, Post, WRP_NONE);
6701 set_current_color_vals(ps);
6704 #endif /* _WINDOWS */
6706 pico_set_normal_color();
6711 * Set current_val for the foreground and background color vars, which
6712 * are assumed to be in order. If a set_current_val on them doesn't
6713 * produce current_vals, then use the colors from defvar to set those
6714 * current_vals.
6716 void
6717 set_color_val(struct variable *v, int use_default)
6719 set_current_val(v, TRUE, TRUE);
6720 set_current_val(v+1, TRUE, TRUE);
6722 if(!(v->current_val.p && v->current_val.p[0] &&
6723 (v+1)->current_val.p && (v+1)->current_val.p[0])){
6724 struct variable *defvar;
6726 if(v->current_val.p)
6727 fs_give((void **)&v->current_val.p);
6728 if((v+1)->current_val.p)
6729 fs_give((void **)&(v+1)->current_val.p);
6731 if(!use_default)
6732 return;
6734 if(var_defaults_to_rev(v))
6735 defvar = &ps_global->vars[V_REV_FORE_COLOR];
6736 else
6737 defvar = &ps_global->vars[V_NORM_FORE_COLOR];
6739 /* use default vars values instead */
6740 if(defvar && defvar->current_val.p && defvar->current_val.p[0] &&
6741 (defvar+1)->current_val.p && (defvar+1)->current_val.p[0]){
6742 v->current_val.p = cpystr(defvar->current_val.p);
6743 (v+1)->current_val.p = cpystr((defvar+1)->current_val.p);
6750 var_defaults_to_rev(struct variable *v)
6752 return(v == &ps_global->vars[V_REV_FORE_COLOR] ||
6753 v == &ps_global->vars[V_TITLE_FORE_COLOR] ||
6754 v == &ps_global->vars[V_STATUS_FORE_COLOR] ||
6755 v == &ps_global->vars[V_KEYNAME_FORE_COLOR] ||
6756 v == &ps_global->vars[V_PROMPT_FORE_COLOR]);
6762 * Each item in the list looks like:
6764 * /HDR=<header>/FG=<foreground color>/BG=<background color>
6766 * We separate the three pieces into an array of structures to make
6767 * it easier to deal with later.
6769 void
6770 set_custom_spec_colors(struct pine *ps)
6772 if(ps->index_token_colors)
6773 free_spec_colors(&ps->index_token_colors);
6775 ps->index_token_colors = spec_colors_from_varlist(ps->VAR_INDEX_TOKEN_COLORS, 1);
6777 if(ps->hdr_colors)
6778 free_spec_colors(&ps->hdr_colors);
6780 ps->hdr_colors = spec_colors_from_varlist(ps->VAR_VIEW_HDR_COLORS, 1);
6782 /* fit keyword colors into the same structures for code re-use */
6783 if(ps->kw_colors)
6784 free_spec_colors(&ps->kw_colors);
6786 ps->kw_colors = spec_colors_from_varlist(ps->VAR_KW_COLORS, 1);
6791 * Input is one item from config variable.
6793 * Return value must be freed by caller. The return is a single SPEC_COLOR_S,
6794 * not a list.
6796 SPEC_COLOR_S *
6797 spec_color_from_var(char *t, int already_expanded)
6799 char *p, *spec, *fg, *bg;
6800 PATTERN_S *val;
6801 SPEC_COLOR_S *new_hcolor = NULL;
6803 if(t && t[0] && !strcmp(t, INHERIT)){
6804 new_hcolor = (SPEC_COLOR_S *)fs_get(sizeof(*new_hcolor));
6805 memset((void *)new_hcolor, 0, sizeof(*new_hcolor));
6806 new_hcolor->inherit = 1;
6808 else if(t && t[0]){
6809 char tbuf[10000];
6811 if(!already_expanded){
6812 tbuf[0] = '\0';
6813 if(expand_variables(tbuf, sizeof(tbuf), t, 0))
6814 t = tbuf;
6817 spec = fg = bg = NULL;
6818 val = NULL;
6819 if((p = srchstr(t, "/HDR=")) != NULL)
6820 spec = remove_backslash_escapes(p+5);
6821 if((p = srchstr(t, "/FG=")) != NULL)
6822 fg = remove_backslash_escapes(p+4);
6823 if((p = srchstr(t, "/BG=")) != NULL)
6824 bg = remove_backslash_escapes(p+4);
6825 val = parse_pattern("VAL", t, 0);
6827 if(spec && *spec){
6828 /* remove colons */
6829 if((p = strindex(spec, ':')) != NULL)
6830 *p = '\0';
6832 new_hcolor = (SPEC_COLOR_S *)fs_get(sizeof(*new_hcolor));
6833 memset((void *)new_hcolor, 0, sizeof(*new_hcolor));
6834 new_hcolor->spec = spec;
6835 new_hcolor->fg = fg;
6836 new_hcolor->bg = bg;
6837 new_hcolor->val = val;
6839 else{
6840 if(spec)
6841 fs_give((void **)&spec);
6842 if(fg)
6843 fs_give((void **)&fg);
6844 if(bg)
6845 fs_give((void **)&bg);
6846 if(val)
6847 free_pattern(&val);
6851 return(new_hcolor);
6856 * Input is a list from config file.
6858 * Return value may be a list of SPEC_COLOR_S and must be freed by caller.
6860 SPEC_COLOR_S *
6861 spec_colors_from_varlist(char **varlist, int already_expanded)
6863 char **s, *t;
6864 SPEC_COLOR_S *new_hc = NULL;
6865 SPEC_COLOR_S *new_hcolor, **nexthc;
6867 nexthc = &new_hc;
6868 if(varlist){
6869 for(s = varlist; (t = *s) != NULL; s++){
6870 if(t[0]){
6871 new_hcolor = spec_color_from_var(t, already_expanded);
6872 if(new_hcolor){
6873 *nexthc = new_hcolor;
6874 nexthc = &new_hcolor->next;
6880 return(new_hc);
6885 * Returns allocated charstar suitable for config var for a single
6886 * SPEC_COLOR_S.
6888 char *
6889 var_from_spec_color(SPEC_COLOR_S *hc)
6891 char *ret_val = NULL;
6892 char *p, *spec = NULL, *fg = NULL, *bg = NULL, *val = NULL;
6893 size_t len;
6895 if(hc && hc->inherit)
6896 ret_val = cpystr(INHERIT);
6897 else if(hc){
6898 if(hc->spec)
6899 spec = add_viewerhdr_escapes(hc->spec);
6900 if(hc->fg)
6901 fg = add_viewerhdr_escapes(hc->fg);
6902 if(hc->bg)
6903 bg = add_viewerhdr_escapes(hc->bg);
6904 if(hc->val){
6905 p = pattern_to_string(hc->val);
6906 if(p){
6907 val = add_viewerhdr_escapes(p);
6908 fs_give((void **)&p);
6912 len = strlen("/HDR=/FG=/BG=") + strlen(spec ? spec : "") +
6913 strlen(fg ? fg : "") + strlen(bg ? bg : "") +
6914 strlen(val ? "/VAL=" : "") + strlen(val ? val : "");
6915 ret_val = (char *) fs_get(len + 1);
6916 snprintf(ret_val, len+1, "/HDR=%s/FG=%s/BG=%s%s%s",
6917 spec ? spec : "", fg ? fg : "", bg ? bg : "",
6918 val ? "/VAL=" : "", val ? val : "");
6920 if(spec)
6921 fs_give((void **)&spec);
6922 if(fg)
6923 fs_give((void **)&fg);
6924 if(bg)
6925 fs_give((void **)&bg);
6926 if(val)
6927 fs_give((void **)&val);
6930 return(ret_val);
6935 * Returns allocated charstar suitable for config var for a single
6936 * SPEC_COLOR_S.
6938 char **
6939 varlist_from_spec_colors(SPEC_COLOR_S *hcolors)
6941 SPEC_COLOR_S *hc;
6942 char **ret_val = NULL;
6943 int i;
6945 /* count how many */
6946 for(hc = hcolors, i = 0; hc; hc = hc->next, i++)
6949 ret_val = (char **)fs_get((i+1) * sizeof(*ret_val));
6950 memset((void *)ret_val, 0, (i+1) * sizeof(*ret_val));
6951 for(hc = hcolors, i = 0; hc; hc = hc->next, i++)
6952 ret_val[i] = var_from_spec_color(hc);
6954 return(ret_val);
6958 void
6959 update_posting_charset(struct pine *ps, int revert)
6961 #ifndef _WINDOWS
6962 if(F_ON(F_USE_SYSTEM_TRANS, ps)){
6963 if(!revert)
6964 q_status_message(SM_ORDER, 5, 5, _("This change has no effect because feature Use-System-Translation is on"));
6966 else{
6967 #endif /* ! _WINDOWS */
6968 if(ps->posting_charmap)
6969 fs_give((void **) &ps->posting_charmap);
6971 if(ps->VAR_POST_CHAR_SET){
6972 ps->posting_charmap = cpystr(ps->VAR_POST_CHAR_SET);
6973 if(!posting_charset_is_supported(ps->posting_charmap)){
6974 snprintf(tmp_20k_buf, SIZEOF_20KBUF,
6975 _("Posting-Character set \"%s\" is unsupported, using UTF-8"),
6976 ps->posting_charmap);
6977 q_status_message(SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
6978 fs_give((void **) &ps->posting_charmap);
6979 ps->posting_charmap = cpystr("UTF-8");
6982 else
6983 ps->posting_charmap = cpystr("UTF-8");
6984 #ifndef _WINDOWS
6986 #endif /* ! _WINDOWS */
6990 #define FIXED_COMMENT _("(fixed)")
6991 #define DEFAULT_COMMENT _("(default)")
6992 #define OVERRIDE_COMMENT _("(overridden)")
6995 feature_gets_an_x(struct pine *ps, struct variable *var, FEATURE_S *feature,
6996 char **comment, EditWhich ew)
6998 char **lval, **lvalexc, **lvalnorm;
6999 char *def = DEFAULT_COMMENT;
7000 int j, done = 0;
7001 int feature_fixed_on = 0, feature_fixed_off = 0;
7003 if(comment)
7004 *comment = NULL;
7006 lval = LVAL(var, ew);
7007 lvalexc = LVAL(var, ps->ew_for_except_vars);
7008 lvalnorm = LVAL(var, Main);
7010 /* feature value is administratively fixed */
7011 if((j = feature_in_list(var->fixed_val.l, feature->name)) != 0){
7012 if(j == 1)
7013 feature_fixed_on++;
7014 else if(j == -1)
7015 feature_fixed_off++;
7017 done++;
7018 if(comment)
7019 *comment = FIXED_COMMENT;
7023 * We have an exceptions config setting which overrides anything
7024 * we do here, in the normal config.
7026 if(!done &&
7027 ps->ew_for_except_vars != Main && ew == Main &&
7028 feature_in_list(lvalexc, feature->name)){
7029 done++;
7030 if(comment)
7031 *comment = OVERRIDE_COMMENT;
7035 * Feature is set On in default but not set here.
7037 if(!done &&
7038 !feature_in_list(lval, feature->name) &&
7039 ((feature_in_list(var->global_val.l, feature->name) == 1) ||
7040 ((ps->ew_for_except_vars != Main &&
7041 ew == ps->ew_for_except_vars &&
7042 feature_in_list(lvalnorm, feature->name) == 1)))){
7043 done = 17;
7044 if(comment)
7045 *comment = def;
7048 if(!done &&
7049 feature->defval &&
7050 !feature_in_list(lval, feature->name) &&
7051 !feature_in_list(var->global_val.l, feature->name) &&
7052 (ps->ew_for_except_vars == Main ||
7053 ew != ps->ew_for_except_vars ||
7054 !feature_in_list(lvalnorm, feature->name))){
7055 done = 17;
7056 if(comment)
7057 *comment = def;
7060 return(feature_fixed_on ||
7061 (!feature_fixed_off &&
7062 (done == 17 ||
7063 test_feature(lval, feature->name,
7064 test_old_growth_bits(ps, feature->id)))));
7067 #if !defined(_WINDOWS) || defined(WINDOWS_LIBRESSL_CERTS)
7068 void
7069 set_system_certs_path(struct pine *ps)
7071 char **l;
7073 for (l = ps->vars[V_SSLCAPATH].current_val.l; l && *l; l++){
7074 if(is_absolute_path(*l)
7075 && can_access(*l, ACCESS_EXISTS) == 0
7076 && can_access(*l, READ_ACCESS) == 0){
7077 mail_parameters(NULL, SET_SSLCAPATH, (void *) *l);
7078 break;
7084 void
7085 set_system_certs_container(struct pine *ps)
7087 char **l;
7089 for (l = ps->vars[V_SSLCAPATH].current_val.l; l && *l; l++){
7090 if(is_absolute_path(*l)
7091 && can_access(*l, ACCESS_EXISTS) == 0
7092 && can_access(*l, READ_ACCESS) == 0){
7093 mail_parameters(NULL, SET_SSLCAFILE, (void *) *l);
7094 break;
7098 #endif
7101 longest_feature_comment(struct pine *ps, EditWhich ew)
7103 int lc = 0;
7105 lc = MAX(lc, utf8_width(FIXED_COMMENT));
7106 lc = MAX(lc, utf8_width(DEFAULT_COMMENT));
7107 if(ps->ew_for_except_vars != Main && ew == Main)
7108 lc = MAX(lc, utf8_width(OVERRIDE_COMMENT));
7110 return(lc);
7114 void
7115 toggle_feature(struct pine *ps, struct variable *var, FEATURE_S *f,
7116 int just_flip_value, EditWhich ew)
7118 char **vp, *p, **lval, ***alval;
7119 int og, on_before, was_set;
7120 char *err;
7121 long l;
7123 og = test_old_growth_bits(ps, f->id);
7126 * if this feature is in the fixed set, or old-growth is in the fixed
7127 * set and this feature is in the old-growth set, don't alter it...
7129 for(vp = var->fixed_val.l; vp && *vp; vp++){
7130 p = (struncmp(*vp, "no-", 3)) ? *vp : *vp + 3;
7131 if(!strucmp(p, f->name) || (og && !strucmp(p, "old-growth"))){
7132 q_status_message(SM_ORDER, 3, 3,
7133 /* TRANSLATORS: In the configuration screen, telling the user we
7134 can't change this option because the system administrator
7135 prohibits it. */
7136 _("Can't change value fixed by sys-admin."));
7137 return;
7141 on_before = F_ON(f->id, ps);
7143 lval = LVAL(var, ew);
7144 alval = ALVAL(var, ew);
7145 if(just_flip_value)
7146 was_set = test_feature(lval, f->name, og);
7147 else
7148 was_set = feature_gets_an_x(ps, var, f, NULL, ew);
7150 if(alval)
7151 set_feature(alval, f->name, !was_set);
7153 set_feature_list_current_val(var);
7154 process_feature_list(ps, var->current_val.l, 0, 0, 0);
7157 * Handle any features that need special attention here...
7159 if(on_before != F_ON(f->id, ps))
7160 switch(f->id){
7161 case F_QUOTE_ALL_FROMS :
7162 mail_parameters(NULL,SET_FROMWIDGET,F_ON(f->id,ps) ? VOIDT : NIL);
7163 break;
7165 case F_FAKE_NEW_IN_NEWS :
7166 if(IS_NEWS(ps->mail_stream))
7167 q_status_message(SM_ORDER | SM_DING, 3, 4,
7168 "news-approximates-new-status won't affect current newsgroup until next open");
7170 break;
7172 case F_COLOR_LINE_IMPORTANT :
7173 case F_DATES_TO_LOCAL :
7174 clear_index_cache(ps->mail_stream, 0);
7175 break;
7177 case F_DISABLE_INDEX_LOCALE_DATES :
7178 reset_index_format();
7179 clear_index_cache(ps->mail_stream, 0);
7180 break;
7182 case F_MARK_FOR_CC :
7183 clear_index_cache(ps->mail_stream, 0);
7184 if(THREADING() && sp_viewing_a_thread(ps->mail_stream))
7185 unview_thread(ps, ps->mail_stream, ps->msgmap);
7187 break;
7189 case F_HIDE_NNTP_PATH :
7190 mail_parameters(NULL, SET_NNTPHIDEPATH,
7191 F_ON(f->id, ps) ? VOIDT : NIL);
7192 break;
7194 case F_MAILDROPS_PRESERVE_STATE :
7195 mail_parameters(NULL, SET_SNARFPRESERVE,
7196 F_ON(f->id, ps) ? VOIDT : NIL);
7197 break;
7199 case F_DISABLE_SHARED_NAMESPACES :
7200 mail_parameters(NULL, SET_DISABLEAUTOSHAREDNS,
7201 F_ON(f->id, ps) ? VOIDT : NIL);
7202 break;
7204 case F_QUELL_LOCK_FAILURE_MSGS :
7205 mail_parameters(NULL, SET_LOCKEACCESERROR,
7206 F_ON(f->id, ps) ? VOIDT : NIL);
7207 break;
7209 case F_MULNEWSRC_HOSTNAMES_AS_TYPED :
7210 l = F_ON(f->id, ps) ? 0L : 1L;
7211 mail_parameters(NULL, SET_NEWSRCCANONHOST, (void *) l);
7212 break;
7214 case F_QUELL_INTERNAL_MSG :
7215 mail_parameters(NULL, SET_USERHASNOLIFE,
7216 F_ON(f->id, ps) ? VOIDT : NIL);
7217 break;
7219 case F_DISABLE_SETLOCALE_COLLATE :
7220 set_collation(F_OFF(F_DISABLE_SETLOCALE_COLLATE, ps), 1);
7221 break;
7223 #ifndef _WINDOWS
7224 case F_USE_SYSTEM_TRANS :
7225 err = NULL;
7226 reset_character_set_stuff(&err);
7227 if(err){
7228 q_status_message(SM_ORDER | SM_DING, 3, 4, err);
7229 fs_give((void **) &err);
7232 break;
7233 #endif /* ! _WINDOWS */
7235 case F_ENABLE_INCOMING_CHECKING :
7236 if(!on_before && F_OFF(F_ENABLE_INCOMING, ps))
7237 q_status_message(SM_ORDER, 0, 3, _("This option has no effect without Enable-Incoming-Folders"));
7239 clear_incoming_valid_bits();
7240 break;
7242 case F_INCOMING_CHECKING_TOTAL :
7243 case F_INCOMING_CHECKING_RECENT :
7244 if(!on_before && F_OFF(F_ENABLE_INCOMING_CHECKING, ps))
7245 q_status_message(SM_ORDER, 0, 3, _("This option has no effect without Enable-Incoming-Folders-Checking"));
7247 clear_incoming_valid_bits();
7248 break;
7250 case F_THREAD_SORTS_BY_ARRIVAL :
7251 clear_index_cache(ps->mail_stream, 0);
7252 refresh_sort(ps->mail_stream, sp_msgmap(ps->mail_stream), SRT_NON);
7253 break;
7255 #ifdef SMIME
7256 case F_DONT_DO_SMIME :
7257 smime_deinit();
7258 break;
7260 #ifdef APPLEKEYCHAIN
7261 case F_PUBLICCERTS_IN_KEYCHAIN :
7262 smime_deinit();
7263 break;
7264 #endif
7265 #endif
7267 default :
7268 break;
7274 * Returns 1 -- Feature is in the list and positive
7275 * 0 -- Feature is not in the list at all
7276 * -1 -- Feature is in the list and negative (no-)
7279 feature_in_list(char **l, char *f)
7281 char *p;
7282 int rv = 0, forced_off;
7284 for(; l && *l; l++){
7285 p = (forced_off = !struncmp(*l, "no-", 3)) ? *l + 3 : *l;
7286 if(!strucmp(p, f))
7287 rv = forced_off ? -1 : 1;
7290 return(rv);
7295 * test_feature - runs thru a feature list, and returns:
7296 * 1 if feature explicitly set and matches 'v'
7297 * 0 if feature not explicitly set *or* doesn't match 'v'
7300 test_feature(char **l, char *f, int g)
7302 char *p;
7303 int rv = 0, forced_off;
7305 for(; l && *l; l++){
7306 p = (forced_off = !struncmp(*l, "no-", 3)) ? *l + 3 : *l;
7307 if(!strucmp(p, f))
7308 rv = !forced_off;
7309 else if(g && !strucmp(p, "old-growth"))
7310 rv = !forced_off;
7313 return(rv);
7317 void
7318 set_feature(char ***l, char *f, int v)
7320 char **list = l ? *l : NULL, newval[256];
7321 int count = 0;
7323 snprintf(newval, sizeof(newval), "%s%s", v ? "" : "no-", f);
7324 for(; list && *list; list++, count++)
7325 if((**list == '\0') /* anything can replace an empty value */
7326 || !strucmp(((!struncmp(*list, "no-", 3)) ? *list + 3 : *list), f)){
7327 fs_give((void **)list); /* replace with new value */
7328 *list = cpystr(newval);
7329 return;
7333 * if we got here, we didn't find it in the list, so grow the list
7334 * and add it..
7336 if(!*l)
7337 *l = (char **)fs_get((count + 2) * sizeof(char *));
7338 else
7339 fs_resize((void **)l, (count + 2) * sizeof(char *));
7341 (*l)[count] = cpystr(newval);
7342 (*l)[count + 1] = NULL;
7347 reset_character_set_stuff(char **err)
7349 int use_system = 0;
7350 char buf[1000];
7352 if(err)
7353 *err = NULL;
7355 if(ps_global->display_charmap)
7356 fs_give((void **) &ps_global->display_charmap);
7358 if(ps_global->keyboard_charmap)
7359 fs_give((void **) &ps_global->keyboard_charmap);
7361 if(ps_global->posting_charmap)
7362 fs_give((void **) &ps_global->posting_charmap);
7364 #ifdef _WINDOWS
7365 ps_global->display_charmap = cpystr("UTF-8");
7366 #else /* UNIX */
7367 if(ps_global->VAR_CHAR_SET)
7368 ps_global->display_charmap = cpystr(ps_global->VAR_CHAR_SET);
7369 else{
7370 #if HAVE_LANGINFO_H && defined(CODESET)
7371 ps_global->display_charmap = cpystr(nl_langinfo_codeset_wrapper());
7372 #else
7373 ps_global->display_charmap = cpystr("UTF-8");
7374 #endif
7376 #endif /* UNIX */
7378 if(!ps_global->display_charmap)
7379 ps_global->display_charmap = cpystr("US-ASCII");
7381 #ifdef _WINDOWS
7382 ps_global->keyboard_charmap = cpystr("UTF-8");
7383 #else /* UNIX */
7384 if(ps_global->VAR_KEY_CHAR_SET)
7385 ps_global->keyboard_charmap = cpystr(ps_global->VAR_KEY_CHAR_SET);
7386 else
7387 ps_global->keyboard_charmap = cpystr(ps_global->display_charmap);
7389 if(!ps_global->keyboard_charmap)
7390 ps_global->keyboard_charmap = cpystr("US-ASCII");
7392 if(F_ON(F_USE_SYSTEM_TRANS, ps_global)){
7393 #if PREREQ_FOR_SYS_TRANSLATION
7394 use_system++;
7395 /* This modifies its arguments */
7396 if(setup_for_input_output(use_system, &ps_global->display_charmap,
7397 &ps_global->keyboard_charmap,
7398 &ps_global->input_cs, (err && *err) ? NULL : err) == -1)
7399 return -1;
7400 #endif
7402 #endif /* UNIX */
7404 if(!use_system){
7405 if(setup_for_input_output(use_system, &ps_global->display_charmap,
7406 &ps_global->keyboard_charmap,
7407 &ps_global->input_cs, (err && *err) ? NULL : err) == -1)
7408 return -1;
7411 if(!use_system && ps_global->VAR_POST_CHAR_SET){
7412 ps_global->posting_charmap = cpystr(ps_global->VAR_POST_CHAR_SET);
7413 if(!posting_charset_is_supported(ps_global->posting_charmap)){
7414 if(err && !*err){
7415 snprintf(buf, sizeof(buf),
7416 _("Posting-Character-Set \"%s\" is unsupported, using UTF-8"),
7417 ps_global->posting_charmap);
7418 *err = cpystr(buf);
7421 fs_give((void **) &ps_global->posting_charmap);
7422 ps_global->posting_charmap = cpystr("UTF-8");
7425 else{
7426 if(use_system && ps_global->VAR_POST_CHAR_SET
7427 && strucmp(ps_global->VAR_POST_CHAR_SET, "UTF-8"))
7428 if(err && !*err)
7429 *err = cpystr(_("Posting-Character-Set is ignored with Use-System-Translation turned on"));
7431 ps_global->posting_charmap = cpystr("UTF-8");
7434 set_locale_charmap(ps_global->keyboard_charmap);
7436 return(0);
7441 * Given a single printer string from the config file, returns pointers
7442 * to alloc'd strings containing the printer nickname, the command,
7443 * the init string, the trailer string, everything but the nickname string,
7444 * and everything but the command string. All_but_cmd includes the trailing
7445 * space at the end (the one before the command) but all_but_nick does not
7446 * include the leading space (the one before the [).
7447 * If you pass in a pointer it is guaranteed to come back pointing to an
7448 * allocated string, even if it is just an empty string. It is ok to pass
7449 * NULL for any of the six return strings.
7451 void
7452 parse_printer(char *input, char **nick, char **cmd, char **init, char **trailer,
7453 char **all_but_nick, char **all_but_cmd)
7455 char *p, *q, *start, *saved_options = NULL;
7456 int tmpsave, cnt;
7458 if(!input)
7459 input = "";
7461 if(nick || all_but_nick){
7462 if((p = srchstr(input, " [")) != NULL){
7463 if(all_but_nick)
7464 *all_but_nick = cpystr(p+1);
7466 if(nick){
7467 while(p-1 > input && isspace((unsigned char)*(p-1)))
7468 p--;
7470 tmpsave = *p;
7471 *p = '\0';
7472 *nick = cpystr(input);
7473 *p = tmpsave;
7476 else{
7477 if(nick)
7478 *nick = cpystr("");
7480 if(all_but_nick)
7481 *all_but_nick = cpystr(input);
7485 if((p = srchstr(input, "] ")) != NULL){
7487 ++p;
7488 }while(isspace((unsigned char)*p));
7490 tmpsave = *p;
7491 *p = '\0';
7492 saved_options = cpystr(input);
7493 *p = tmpsave;
7495 else
7496 p = input;
7498 if(cmd)
7499 *cmd = cpystr(p);
7501 if(init){
7502 if(saved_options && (p = srchstr(saved_options, "INIT="))){
7503 start = p + strlen("INIT=");
7504 for(cnt=0, p = start; *p && *(p+1) && isxpair(p); p += 2)
7505 cnt++;
7507 q = *init = (char *)fs_get((cnt + 1) * sizeof(char));
7508 for(p = start; *p && *(p+1) && isxpair(p); p += 2)
7509 *q++ = read_hex(p);
7511 *q = '\0';
7513 else
7514 *init = cpystr("");
7517 if(trailer){
7518 if(saved_options && (p = srchstr(saved_options, "TRAILER="))){
7519 start = p + strlen("TRAILER=");
7520 for(cnt=0, p = start; *p && *(p+1) && isxpair(p); p += 2)
7521 cnt++;
7523 q = *trailer = (char *)fs_get((cnt + 1) * sizeof(char));
7524 for(p = start; *p && *(p+1) && isxpair(p); p += 2)
7525 *q++ = read_hex(p);
7527 *q = '\0';
7529 else
7530 *trailer = cpystr("");
7533 if(all_but_cmd){
7534 if(saved_options)
7535 *all_but_cmd = saved_options;
7536 else
7537 *all_but_cmd = cpystr("");
7539 else if(saved_options)
7540 fs_give((void **)&saved_options);
7545 copy_pinerc(char *local, char *remote, char **err_msg)
7547 return(copy_localfile_to_remotefldr(RemImap, local, remote,
7548 REMOTE_PINERC_SUBTYPE,
7549 err_msg));
7554 copy_abook(char *local, char *remote, char **err_msg)
7556 return(copy_localfile_to_remotefldr(RemImap, local, remote,
7557 REMOTE_ABOOK_SUBTYPE,
7558 err_msg));
7563 * Copy local file to remote folder.
7565 * Args remotetype -- type of remote folder
7566 * local -- name of local file
7567 * remote -- name of remote folder
7568 * subtype --
7570 * Returns 0 on success.
7573 copy_localfile_to_remotefldr(RemType remotetype, char *local, char *remote,
7574 char *subtype, char **err_msg)
7576 int retfail = -1;
7577 unsigned flags;
7578 REMDATA_S *rd;
7580 dprint((9, "copy_localfile_to_remotefldr(%s,%s)\n",
7581 local ? local : "<null>",
7582 remote ? remote : "<null>"));
7584 *err_msg = (char *)fs_get(MAXPATH * sizeof(char));
7586 if(!local || !*local){
7587 snprintf(*err_msg, MAXPATH, _("No local file specified"));
7588 return(retfail);
7591 if(!remote || !*remote){
7592 snprintf(*err_msg, MAXPATH, _("No remote folder specified"));
7593 return(retfail);
7596 if(!IS_REMOTE(remote)){
7597 snprintf(*err_msg, MAXPATH, _("Remote folder name \"%s\" %s"), remote,
7598 (*remote != '{') ? _("must begin with \"{\"") : _("not valid"));
7599 return(retfail);
7602 if(IS_REMOTE(local)){
7603 snprintf(*err_msg, MAXPATH, _("First argument \"%s\" must be a local filename"),
7604 local);
7605 return(retfail);
7608 if(can_access(local, ACCESS_EXISTS) != 0){
7609 snprintf(*err_msg, MAXPATH, _("Local file \"%s\" does not exist"), local);
7610 return(retfail);
7613 if(can_access(local, READ_ACCESS) != 0){
7614 snprintf(*err_msg, MAXPATH, _("Can't read local file \"%s\": %s"),
7615 local, error_description(errno));
7616 return(retfail);
7620 * Check if remote folder exists and create it if it doesn't.
7622 flags = 0;
7623 rd = rd_create_remote(remotetype, remote, subtype,
7624 &flags, _("Error: "), _("Can't copy to remote folder."));
7626 if(!rd || rd->access == NoExists){
7627 snprintf(*err_msg, MAXPATH, _("Can't create \"%s\""), remote);
7628 if(rd)
7629 rd_free_remdata(&rd);
7631 return(retfail);
7634 if(rd->access == MaybeRorW)
7635 rd->access = ReadWrite;
7637 rd->flags |= (NO_META_UPDATE | DO_REMTRIM);
7638 rd->lf = cpystr(local);
7640 rd_open_remote(rd);
7641 if(!rd_stream_exists(rd)){
7642 snprintf(*err_msg, MAXPATH, _("Can't open remote folder \"%s\""), rd->rn);
7643 rd_free_remdata(&rd);
7644 return(retfail);
7647 if(rd_remote_is_readonly(rd)){
7648 snprintf(*err_msg, MAXPATH, _("Remote folder \"%s\" is readonly"), rd->rn);
7649 rd_free_remdata(&rd);
7650 return(retfail);
7653 switch(rd->type){
7654 case RemImap:
7656 * Empty folder, add a header msg.
7658 if(rd->t.i.stream->nmsgs == 0){
7659 if(rd_init_remote(rd, 1) != 0){
7660 snprintf(*err_msg, MAXPATH,
7661 _("Failed initializing remote folder \"%s\", check debug file"),
7662 rd->rn);
7663 rd_free_remdata(&rd);
7664 return(retfail);
7668 fs_give((void **)err_msg);
7669 *err_msg = NULL;
7670 if(rd_chk_for_hdr_msg(&(rd->t.i.stream), rd, err_msg)){
7671 rd_free_remdata(&rd);
7672 return(retfail);
7675 break;
7677 default:
7678 break;
7681 if(rd_update_remote(rd, NULL) != 0){
7682 snprintf(*err_msg, MAXPATH, _("Error copying to remote folder \"%s\""), rd->rn);
7683 rd_free_remdata(&rd);
7684 return(retfail);
7687 rd_update_metadata(rd, NULL);
7688 rd_close_remdata(&rd);
7690 fs_give((void **)err_msg);
7691 return(0);
7695 /*----------------------------------------------------------------------
7696 Panic pine - call on detected programmatic errors to exit pine, with arg
7698 Input: message -- printf styule string for panic message (see above)
7699 arg -- argument for printf string
7701 Result: The various tty modes are restored
7702 If debugging is active a core dump will be generated
7703 Exits Pine
7704 ----*/
7705 void
7706 panic1(char *message, char *arg)
7708 #define SIZEOFBUF 1001
7709 char buf1[SIZEOFBUF], buf2[SIZEOFBUF];
7711 snprintf(buf1, sizeof(buf1), "%.*s", (int) MAX(SIZEOFBUF - 1 - strlen(message), 0), arg);
7712 snprintf(buf2, sizeof(buf2), message, buf1);
7713 alpine_panic(buf2);
7720 HelpType
7721 config_help(int var, int feature)
7723 switch(var){
7724 case V_FEATURE_LIST :
7725 return(feature_list_help(feature));
7726 break;
7728 case V_PERSONAL_NAME :
7729 return(h_config_pers_name);
7730 case V_USER_ID :
7731 return(h_config_user_id);
7732 case V_USER_DOMAIN :
7733 return(h_config_user_dom);
7734 case V_SMTP_SERVER :
7735 return(h_config_smtp_server);
7736 case V_NNTP_SERVER :
7737 return(h_config_nntp_server);
7738 case V_INBOX_PATH :
7739 return(h_config_inbox_path);
7740 case V_PRUNED_FOLDERS :
7741 return(h_config_pruned_folders);
7742 case V_DEFAULT_FCC :
7743 return(h_config_default_fcc);
7744 case V_DEFAULT_SAVE_FOLDER :
7745 return(h_config_def_save_folder);
7746 case V_POSTPONED_FOLDER :
7747 return(h_config_postponed_folder);
7748 case V_READ_MESSAGE_FOLDER :
7749 return(h_config_read_message_folder);
7750 case V_FORM_FOLDER :
7751 return(h_config_form_folder);
7752 case V_ARCHIVED_FOLDERS :
7753 return(h_config_archived_folders);
7754 case V_SIGNATURE_FILE :
7755 return(h_config_signature_file);
7756 case V_LITERAL_SIG :
7757 return(h_config_literal_sig);
7758 case V_INIT_CMD_LIST :
7759 return(h_config_init_cmd_list);
7760 case V_COMP_HDRS :
7761 return(h_config_comp_hdrs);
7762 case V_CUSTOM_HDRS :
7763 return(h_config_custom_hdrs);
7764 case V_VIEW_HEADERS :
7765 return(h_config_viewer_headers);
7766 case V_VIEW_MARGIN_LEFT :
7767 return(h_config_viewer_margin_left);
7768 case V_VIEW_MARGIN_RIGHT :
7769 return(h_config_viewer_margin_right);
7770 case V_QUOTE_SUPPRESSION :
7771 return(h_config_quote_suppression);
7772 case V_SAVED_MSG_NAME_RULE :
7773 return(h_config_saved_msg_name_rule);
7774 case V_FCC_RULE :
7775 return(h_config_fcc_rule);
7776 case V_SORT_KEY :
7777 return(h_config_sort_key);
7778 case V_AB_SORT_RULE :
7779 return(h_config_ab_sort_rule);
7780 case V_FLD_SORT_RULE :
7781 return(h_config_fld_sort_rule);
7782 case V_POST_CHAR_SET :
7783 return(h_config_post_char_set);
7784 case V_UNK_CHAR_SET :
7785 return(h_config_unk_char_set);
7786 #ifndef _WINDOWS
7787 case V_KEY_CHAR_SET :
7788 return(h_config_key_char_set);
7789 case V_CHAR_SET :
7790 return(h_config_char_set);
7791 #endif /* ! _WINDOWS */
7792 case V_EDITOR :
7793 return(h_config_editor);
7794 case V_SPELLER :
7795 return(h_config_speller);
7796 #ifdef _WINDOWS
7797 case V_DICTIONARY :
7798 return(h_config_aspell_dictionary);
7799 #endif /* _WINDOWS */
7800 case V_DISPLAY_FILTERS :
7801 return(h_config_display_filters);
7802 case V_SEND_FILTER :
7803 return(h_config_sending_filter);
7804 case V_ALT_ADDRS :
7805 return(h_config_alt_addresses);
7806 case V_KEYWORDS :
7807 return(h_config_keywords);
7808 case V_KW_BRACES :
7809 return(h_config_kw_braces);
7810 case V_OPENING_SEP :
7811 return(h_config_opening_sep);
7812 case V_KW_COLORS :
7813 return(h_config_kw_color);
7814 case V_ABOOK_FORMATS :
7815 return(h_config_abook_formats);
7816 case V_INDEX_FORMAT :
7817 return(h_config_index_format);
7818 case V_INCCHECKTIMEO :
7819 return(h_config_incoming_timeo);
7820 case V_INCCHECKINTERVAL :
7821 return(h_config_incoming_interv);
7822 case V_INC2NDCHECKINTERVAL :
7823 return(h_config_incoming_second_interv);
7824 case V_INCCHECKLIST :
7825 return(h_config_incoming_list);
7826 case V_OVERLAP :
7827 return(h_config_viewer_overlap);
7828 case V_MAXREMSTREAM :
7829 return(h_config_maxremstream);
7830 case V_PERMLOCKED :
7831 return(h_config_permlocked);
7832 case V_MARGIN :
7833 return(h_config_scroll_margin);
7834 case V_DEADLETS :
7835 return(h_config_deadlets);
7836 case V_FILLCOL :
7837 return(h_config_composer_wrap_column);
7838 case V_TCPOPENTIMEO :
7839 return(h_config_tcp_open_timeo);
7840 case V_TCPREADWARNTIMEO :
7841 return(h_config_tcp_readwarn_timeo);
7842 case V_TCPWRITEWARNTIMEO :
7843 return(h_config_tcp_writewarn_timeo);
7844 case V_TCPQUERYTIMEO :
7845 return(h_config_tcp_query_timeo);
7846 case V_QUITQUERYTIMEO :
7847 return(h_config_quit_query_timeo);
7848 case V_RSHOPENTIMEO :
7849 return(h_config_rsh_open_timeo);
7850 case V_SSHOPENTIMEO :
7851 return(h_config_ssh_open_timeo);
7852 case V_USERINPUTTIMEO :
7853 return(h_config_user_input_timeo);
7854 case V_REMOTE_ABOOK_VALIDITY :
7855 return(h_config_remote_abook_validity);
7856 case V_REMOTE_ABOOK_HISTORY :
7857 return(h_config_remote_abook_history);
7858 case V_INCOMING_FOLDERS :
7859 return(h_config_incoming_folders);
7860 case V_FOLDER_SPEC :
7861 return(h_config_folder_spec);
7862 case V_NEWS_SPEC :
7863 return(h_config_news_spec);
7864 case V_ADDRESSBOOK :
7865 return(h_config_address_book);
7866 case V_GLOB_ADDRBOOK :
7867 return(h_config_glob_addrbook);
7868 case V_LAST_VERS_USED :
7869 return(h_config_last_vers);
7870 case V_SENDMAIL_PATH :
7871 return(h_config_sendmail_path);
7872 case V_OPER_DIR :
7873 return(h_config_oper_dir);
7874 case V_RSHPATH :
7875 return(h_config_rshpath);
7876 case V_RSHCMD :
7877 return(h_config_rshcmd);
7878 case V_SSHPATH :
7879 return(h_config_sshpath);
7880 case V_SSHCMD :
7881 return(h_config_sshcmd);
7882 case V_NEW_VER_QUELL :
7883 return(h_config_new_ver_quell);
7884 case V_DISABLE_DRIVERS :
7885 return(h_config_disable_drivers);
7886 case V_DISABLE_AUTHS :
7887 return(h_config_disable_auths);
7888 #ifdef DF_ENCRYPTION_RANGE
7889 case V_ENCRYPTION_RANGE :
7890 return(h_config_encryption_range);
7891 #endif
7892 case V_REMOTE_ABOOK_METADATA :
7893 return(h_config_abook_metafile);
7894 case V_REPLY_STRING :
7895 return(h_config_reply_indent_string);
7896 case V_WORDSEPS :
7897 return(h_config_wordseps);
7898 case V_QUOTE_REPLACE_STRING :
7899 return(h_config_quote_replace_string);
7900 case V_REPLY_INTRO :
7901 return(h_config_reply_intro);
7902 case V_EMPTY_HDR_MSG :
7903 return(h_config_empty_hdr_msg);
7904 case V_STATUS_MSG_DELAY :
7905 return(h_config_status_msg_delay);
7906 case V_ACTIVE_MSG_INTERVAL :
7907 return(h_config_active_msg_interval);
7908 case V_MAILCHECK :
7909 return(h_config_mailcheck);
7910 case V_MAILCHECKNONCURR :
7911 return(h_config_mailchecknoncurr);
7912 case V_MAILDROPCHECK :
7913 return(h_config_maildropcheck);
7914 case V_NNTPRANGE :
7915 return(h_config_nntprange);
7916 case V_NEWS_ACTIVE_PATH :
7917 return(h_config_news_active);
7918 case V_NEWS_SPOOL_DIR :
7919 return(h_config_news_spool);
7920 case V_IMAGE_VIEWER :
7921 return(h_config_image_viewer);
7922 case V_USE_ONLY_DOMAIN_NAME :
7923 return(h_config_domain_name);
7924 case V_LAST_TIME_PRUNE_QUESTION :
7925 return(h_config_prune_date);
7926 case V_UPLOAD_CMD:
7927 return(h_config_upload_cmd);
7928 case V_UPLOAD_CMD_PREFIX:
7929 return(h_config_upload_prefix);
7930 case V_DOWNLOAD_CMD:
7931 return(h_config_download_cmd);
7932 case V_DOWNLOAD_CMD_PREFIX:
7933 return(h_config_download_prefix);
7934 case V_GOTO_DEFAULT_RULE:
7935 return(h_config_goto_default);
7936 case V_INCOMING_STARTUP:
7937 return(h_config_inc_startup);
7938 case V_PRUNING_RULE:
7939 return(h_config_pruning_rule);
7940 case V_REOPEN_RULE:
7941 return(h_config_reopen_rule);
7942 case V_THREAD_DISP_STYLE:
7943 return(h_config_thread_disp_style);
7944 case V_THREAD_INDEX_STYLE:
7945 return(h_config_thread_index_style);
7946 case V_THREAD_MORE_CHAR:
7947 return(h_config_thread_indicator_char);
7948 case V_THREAD_EXP_CHAR:
7949 return(h_config_thread_exp_char);
7950 case V_THREAD_LASTREPLY_CHAR:
7951 return(h_config_thread_lastreply_char);
7952 case V_MAILCAP_PATH :
7953 return(h_config_mailcap_path);
7954 case V_MIMETYPE_PATH :
7955 return(h_config_mimetype_path);
7956 #if !defined(_WINDOWS) || defined(WINDOWS_LIBRESSL_CERTS)
7957 case V_SSLCAPATH :
7958 return(h_config_system_certs_path);
7959 case V_SSLCAFILE :
7960 return(h_config_system_certs_file);
7961 #endif
7962 #if !defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)
7963 case V_FIFOPATH :
7964 return(h_config_fifopath);
7965 #endif
7966 case V_NMW_WIDTH :
7967 return(h_config_newmailwidth);
7968 case V_NEWSRC_PATH :
7969 return(h_config_newsrc_path);
7970 case V_BROWSER :
7971 return(h_config_browser);
7972 case V_HISTORY :
7973 return(h_config_history);
7974 #if defined(DOS) || defined(OS2)
7975 case V_FILE_DIR :
7976 return(h_config_file_dir);
7977 #endif
7978 case V_NORM_FORE_COLOR :
7979 case V_NORM_BACK_COLOR :
7980 return(h_config_normal_color);
7981 case V_REV_FORE_COLOR :
7982 case V_REV_BACK_COLOR :
7983 return(h_config_reverse_color);
7984 case V_TITLE_FORE_COLOR :
7985 case V_TITLE_BACK_COLOR :
7986 return(h_config_title_color);
7987 case V_TITLECLOSED_FORE_COLOR :
7988 case V_TITLECLOSED_BACK_COLOR :
7989 return(h_config_titleclosed_color);
7990 case V_FOLDER_FORE_COLOR:
7991 return(h_config_folder_color);
7992 case V_DIRECTORY_FORE_COLOR:
7993 return(h_config_directory_color);
7994 case V_FOLDER_LIST_FORE_COLOR:
7995 return(h_config_folder_list_color);
7996 case V_STATUS_FORE_COLOR :
7997 case V_STATUS_BACK_COLOR :
7998 return(h_config_status_color);
7999 case V_SLCTBL_FORE_COLOR :
8000 case V_SLCTBL_BACK_COLOR :
8001 return(h_config_slctbl_color);
8002 case V_QUOTE1_FORE_COLOR :
8003 case V_QUOTE2_FORE_COLOR :
8004 case V_QUOTE3_FORE_COLOR :
8005 case V_QUOTE1_BACK_COLOR :
8006 case V_QUOTE2_BACK_COLOR :
8007 case V_QUOTE3_BACK_COLOR :
8008 return(h_config_quote_color);
8009 case V_INCUNSEEN_FORE_COLOR :
8010 case V_INCUNSEEN_BACK_COLOR :
8011 return(h_config_incunseen_color);
8012 case V_SIGNATURE_FORE_COLOR :
8013 case V_SIGNATURE_BACK_COLOR :
8014 return(h_config_signature_color);
8015 case V_PROMPT_FORE_COLOR :
8016 case V_PROMPT_BACK_COLOR :
8017 return(h_config_prompt_color);
8018 case V_HEADER_GENERAL_FORE_COLOR :
8019 case V_HEADER_GENERAL_BACK_COLOR :
8020 return(h_config_header_general_color);
8021 case V_IND_PLUS_FORE_COLOR :
8022 case V_IND_IMP_FORE_COLOR :
8023 case V_IND_DEL_FORE_COLOR :
8024 case V_IND_ANS_FORE_COLOR :
8025 case V_IND_NEW_FORE_COLOR :
8026 case V_IND_UNS_FORE_COLOR :
8027 case V_IND_REC_FORE_COLOR :
8028 case V_IND_FWD_FORE_COLOR :
8029 case V_IND_PLUS_BACK_COLOR :
8030 case V_IND_IMP_BACK_COLOR :
8031 case V_IND_DEL_BACK_COLOR :
8032 case V_IND_ANS_BACK_COLOR :
8033 case V_IND_NEW_BACK_COLOR :
8034 case V_IND_UNS_BACK_COLOR :
8035 case V_IND_REC_BACK_COLOR :
8036 case V_IND_FWD_BACK_COLOR :
8037 return(h_config_index_color);
8038 case V_IND_OP_FORE_COLOR :
8039 case V_IND_OP_BACK_COLOR :
8040 return(h_config_index_opening_color);
8041 case V_IND_SUBJ_FORE_COLOR :
8042 case V_IND_SUBJ_BACK_COLOR :
8043 return(h_config_index_subject_color);
8044 case V_IND_FROM_FORE_COLOR :
8045 case V_IND_FROM_BACK_COLOR :
8046 return(h_config_index_from_color);
8047 case V_IND_HIPRI_FORE_COLOR :
8048 case V_IND_HIPRI_BACK_COLOR :
8049 case V_IND_LOPRI_FORE_COLOR :
8050 case V_IND_LOPRI_BACK_COLOR :
8051 return(h_config_index_pri_color);
8052 case V_IND_ARR_FORE_COLOR :
8053 case V_IND_ARR_BACK_COLOR :
8054 return(h_config_index_arrow_color);
8055 case V_KEYLABEL_FORE_COLOR :
8056 case V_KEYLABEL_BACK_COLOR :
8057 return(h_config_keylabel_color);
8058 case V_KEYNAME_FORE_COLOR :
8059 case V_KEYNAME_BACK_COLOR :
8060 return(h_config_keyname_color);
8061 case V_METAMSG_FORE_COLOR :
8062 case V_METAMSG_BACK_COLOR :
8063 return(h_config_metamsg_color);
8064 case V_VIEW_HDR_COLORS :
8065 return(h_config_customhdr_color);
8066 case V_INDEX_TOKEN_COLORS :
8067 return(h_config_indextoken_color);
8068 case V_PRINTER :
8069 return(h_config_printer);
8070 case V_PERSONAL_PRINT_CATEGORY :
8071 return(h_config_print_cat);
8072 case V_PERSONAL_PRINT_COMMAND :
8073 return(h_config_print_command);
8074 case V_PAT_ROLES :
8075 return(h_config_pat_roles);
8076 case V_PAT_FILTS :
8077 return(h_config_pat_filts);
8078 case V_PAT_SCORES :
8079 return(h_config_pat_scores);
8080 case V_PAT_INCOLS :
8081 return(h_config_pat_incols);
8082 case V_PAT_OTHER :
8083 return(h_config_pat_other);
8084 case V_PAT_SRCH :
8085 return(h_config_pat_srch);
8086 case V_INDEX_COLOR_STYLE :
8087 return(h_config_index_color_style);
8088 case V_TITLEBAR_COLOR_STYLE :
8089 return(h_config_titlebar_color_style);
8090 #ifdef _WINDOWS
8091 case V_FONT_NAME :
8092 return(h_config_font_name);
8093 case V_FONT_SIZE :
8094 return(h_config_font_size);
8095 case V_FONT_STYLE :
8096 return(h_config_font_style);
8097 case V_FONT_CHAR_SET :
8098 return(h_config_font_char_set);
8099 case V_PRINT_FONT_NAME :
8100 return(h_config_print_font_name);
8101 case V_PRINT_FONT_SIZE :
8102 return(h_config_print_font_size);
8103 case V_PRINT_FONT_STYLE :
8104 return(h_config_print_font_style);
8105 case V_PRINT_FONT_CHAR_SET :
8106 return(h_config_print_font_char_set);
8107 case V_WINDOW_POSITION :
8108 return(h_config_window_position);
8109 case V_CURSOR_STYLE :
8110 return(h_config_cursor_style);
8111 #else
8112 case V_COLOR_STYLE :
8113 return(h_config_color_style);
8114 #endif
8115 #ifdef ENABLE_LDAP
8116 case V_LDAP_SERVERS :
8117 return(h_config_ldap_servers);
8118 #endif
8119 #ifdef SMIME
8120 case V_PUBLICCERT_DIR :
8121 return(h_config_smime_pubcertdir);
8122 case V_PUBLICCERT_CONTAINER :
8123 return(h_config_smime_pubcertcon);
8124 case V_PRIVATEKEY_DIR :
8125 return(h_config_smime_privkeydir);
8126 case V_PRIVATEKEY_CONTAINER :
8127 return(h_config_smime_privkeycon);
8128 case V_CACERT_DIR :
8129 return(h_config_smime_cacertdir);
8130 case V_CACERT_CONTAINER :
8131 return(h_config_smime_cacertcon);
8132 #endif
8133 case V_RSS_NEWS :
8134 return(h_config_rss_news);
8135 case V_RSS_WEATHER :
8136 return(h_config_rss_weather);
8137 case V_WP_INDEXHEIGHT :
8138 return(h_config_wp_indexheight);
8139 case V_WP_INDEXLINES :
8140 return(h_config_wp_indexlines);
8141 case V_WP_AGGSTATE :
8142 return(h_config_wp_aggstate);
8143 case V_WP_STATE :
8144 return(h_config_wp_state);
8145 case V_WP_COLUMNS :
8146 return(h_config_wp_columns);
8147 default :
8148 return(NO_HELP);
8154 * We don't want the user to be able to edit their pinerc and set
8155 * printer to whatever they want if personal-print-command is fixed.
8156 * So make sure printer is set to something legitimate. If it isn't,
8157 * set it to something standard and return non-zero.
8160 printer_value_check_and_adjust(void)
8162 char **tt;
8163 char aname[100], wname[100];
8164 int ok = 0;
8165 struct variable *vars = ps_global->vars;
8167 if(vars[V_PERSONAL_PRINT_COMMAND].is_fixed && !vars[V_PRINTER].is_fixed){
8168 strncpy(aname, ANSI_PRINTER, sizeof(aname));
8169 aname[sizeof(aname)-1] = '\0';
8170 strncat(aname, "-no-formfeed", sizeof(aname)-strlen(aname)-1);
8171 strncpy(wname, WYSE_PRINTER, sizeof(wname));
8172 wname[sizeof(wname)-1] = '\0';
8173 strncat(wname, "-no-formfeed", sizeof(wname)-strlen(wname)-1);
8174 if(strucmp(VAR_PRINTER, ANSI_PRINTER) == 0
8175 || strucmp(VAR_PRINTER, aname) == 0
8176 || strucmp(VAR_PRINTER, WYSE_PRINTER) == 0
8177 || strucmp(VAR_PRINTER, wname) == 0)
8178 ok++;
8179 else if(VAR_STANDARD_PRINTER && VAR_STANDARD_PRINTER[0]){
8180 for(tt = VAR_STANDARD_PRINTER; *tt; tt++)
8181 if(strucmp(VAR_PRINTER, *tt) == 0)
8182 break;
8184 if(*tt)
8185 ok++;
8188 if(!ok){
8189 char *val;
8190 struct variable *v;
8192 if(VAR_STANDARD_PRINTER && VAR_STANDARD_PRINTER[0])
8193 val = VAR_STANDARD_PRINTER[0];
8194 else
8195 val = ANSI_PRINTER;
8197 v = &vars[V_PRINTER];
8198 if(v->main_user_val.p)
8199 fs_give((void **)&v->main_user_val.p);
8200 if(v->post_user_val.p)
8201 fs_give((void **)&v->post_user_val.p);
8202 if(v->current_val.p)
8203 fs_give((void **)&v->current_val.p);
8205 v->main_user_val.p = cpystr(val);
8206 v->current_val.p = cpystr(val);
8210 return(!ok);
8214 char **
8215 get_supported_options(void)
8217 char **config;
8218 DRIVER *d;
8219 AUTHENTICATOR *a;
8220 char *title = _("Supported features in this Alpine");
8221 char sbuf[MAX_SCREEN_COLS+1], tmp[128];
8222 int cnt, alcnt, len, cols, disabled, any_disabled = 0, i;
8225 * Line count:
8226 * Title + blank = 2
8227 * SSL Title + SSL lines + blank = 5
8228 * Auth title + blank = 2
8229 * Driver title + blank = 2
8230 * LDAP title + LDAP line = 2
8231 * Disabled explanation + blank line = 4
8232 * end = 1
8234 cnt = 18;
8235 for(a = mail_lookup_auth(1); a; a = a->next)
8236 cnt++;
8237 for(d = (DRIVER *)mail_parameters(NIL, GET_DRIVERS, NIL);
8238 d; d = d->next)
8239 cnt++;
8241 alcnt = cnt;
8242 config = (char **) fs_get(alcnt * sizeof(char *));
8243 memset(config, 0, alcnt * sizeof(char *));
8245 cols = ps_global->ttyo ? ps_global->ttyo->screen_cols : 0;
8246 len = utf8_width(title);
8247 snprintf(sbuf, sizeof(sbuf), "%*s%s", cols > len ? (cols-len)/2 : 0, "", title);
8249 cnt = 0;
8250 if(cnt < alcnt)
8251 config[cnt] = cpystr(sbuf);
8253 if(++cnt < alcnt)
8254 config[cnt] = cpystr("");
8256 if(++cnt < alcnt)
8257 /* TRANSLATORS: headings */
8258 config[cnt] = cpystr(_("Encryption:"));
8260 if(++cnt < alcnt && mail_parameters(NIL, GET_SSLDRIVER, NIL)){
8261 config[cnt] = cpystr(_(" TLS and SSL"));
8262 tmp[0] = tmp[1] = ' ';
8263 tmp[2] = '\0';
8264 strcat(tmp, "TLSv1, ");
8265 strcat(tmp, "TLSv1.1, ");
8266 strcat(tmp, "TLSv1.2, ");
8267 #ifdef TLS1_3_VERSION
8268 strcat(tmp, "TLSv1.3, ");
8269 #endif /* TLS1_3_VERSION */
8270 tmp[strlen(tmp)-2] = '.';
8271 tmp[strlen(tmp)-1] = '\0';
8273 else
8274 config[cnt] = cpystr(_(" None (no TLS or SSL)"));
8276 if(++cnt < alcnt)
8277 config[cnt] = cpystr(tmp);
8278 #ifdef SMIME
8279 if(++cnt < alcnt)
8280 config[cnt] = cpystr(" S/MIME");
8281 #endif
8283 if(++cnt < alcnt)
8284 config[cnt] = cpystr("");
8286 if(++cnt < alcnt)
8287 config[cnt] = cpystr(_("Authenticators:"));
8289 for(a = mail_lookup_auth(1); a; a = a->next){
8290 disabled = (a->client == NULL && a->server == NULL);
8291 any_disabled += disabled;
8292 snprintf(sbuf, sizeof(sbuf), " %s%s", a->name, disabled ? " (disabled)" : "");
8293 if(++cnt < alcnt)
8294 config[cnt] = cpystr(sbuf);
8297 if(++cnt < alcnt)
8298 config[cnt] = cpystr("");
8300 if(++cnt < alcnt)
8301 config[cnt] = cpystr(_("Mailbox drivers:"));
8303 for(d = (DRIVER *)mail_parameters(NIL, GET_DRIVERS, NIL);
8304 d; d = d->next){
8305 disabled = (d->flags & DR_DISABLE);
8306 any_disabled += disabled;
8307 snprintf(sbuf, sizeof(sbuf), " %s%s", d->name, disabled ? " (disabled)" : "");
8308 if(++cnt < alcnt)
8309 config[cnt] = cpystr(sbuf);
8312 if(++cnt < alcnt)
8313 config[cnt] = cpystr("");
8315 if(++cnt < alcnt)
8316 config[cnt] = cpystr(_("Directories:"));
8318 #ifdef ENABLE_LDAP
8319 if(++cnt < alcnt)
8320 config[cnt] = cpystr(" LDAP");
8321 #else
8322 if(++cnt < alcnt)
8323 config[cnt] = cpystr(" None (no LDAP)");
8324 #endif
8326 if(any_disabled){
8327 if(++cnt < alcnt)
8328 config[cnt] = cpystr("");
8330 if(ps_global->ttyo){
8331 if(++cnt < alcnt)
8332 config[cnt] = cpystr(_("Authenticators may be disabled because of the \"disable-these-authenticators\" hidden config option. Mailbox drivers may be disabled because of the \"disable-these-drivers\" hidden config option."));
8334 else{
8335 if(++cnt < alcnt)
8336 config[cnt] = cpystr(_("Authenticators may be disabled because of the \"disable-these-authenticators\""));
8337 if(++cnt < alcnt)
8338 config[cnt] = cpystr(_("hidden config option. Mailbox drivers may be disabled because of the"));
8339 if(++cnt < alcnt)
8340 config[cnt] = cpystr(_("\"disable-these-drivers\" hidden config option."));
8344 if(++cnt < alcnt)
8345 config[cnt] = NULL;
8347 return(config);
8351 unsigned
8352 reset_startup_rule(MAILSTREAM *stream)
8354 long rflags = ROLE_DO_OTHER;
8355 PAT_STATE pstate;
8356 PAT_S *pat;
8357 unsigned startup_rule;
8359 startup_rule = IS_NOTSET;
8361 if(stream && nonempty_patterns(rflags, &pstate)){
8362 for(pat = first_pattern(&pstate); pat; pat = next_pattern(&pstate)){
8363 if(match_pattern(pat->patgrp, stream, NULL, NULL, NULL,
8364 SE_NOSERVER|SE_NOPREFETCH))
8365 break;
8368 if(pat && pat->action && !pat->action->bogus)
8369 startup_rule = pat->action->startup_rule;
8372 return(startup_rule);
8376 #ifdef _WINDOWS
8378 char *
8379 transformed_color(old)
8380 char *old;
8382 if(!old)
8383 return("");
8385 if(!struncmp(old, "color008", 8))
8386 return("colorlgr");
8387 else if(!struncmp(old, "color009", 8))
8388 return("colormgr");
8389 else if(!struncmp(old, "color010", 8))
8390 return("colordgr");
8392 return("");
8397 * If this is the first time we've run a version > 4.40, and there
8398 * is evidence that the config file has not been used by unix pine,
8399 * then we convert color008 to colorlgr, color009 to colormgr, and
8400 * color010 to colordgr. If the config file is being used by
8401 * unix pine then color008 may really supposed to be color008, color009
8402 * may really supposed to be red, and color010 may really supposed to be
8403 * green. Same if we've already run 4.41 or higher previously.
8405 * Returns 0 if no changes, > 0 if something was changed.
8408 convert_pc_gray_names(ps, prc, which)
8409 struct pine *ps;
8410 PINERC_S *prc;
8411 EditWhich which;
8413 struct variable *v;
8414 int ret = 0, ic = 0;
8415 char **s, *t, *p, *pstr, *new, *pval, **apval, **lval;
8417 for(v = ps->vars; v->name; v++){
8418 if(!color_holding_var(ps, v) || v == &ps->vars[V_KW_COLORS])
8419 continue;
8421 if(v == &ps->vars[V_VIEW_HDR_COLORS]){
8423 if((lval = LVAL(v,which)) != NULL){
8424 /* fix these in place */
8425 for(s = lval; (t = *s) != NULL; s++){
8426 if((p = srchstr(t, "FG=color008")) ||
8427 (p = srchstr(t, "FG=color009")) ||
8428 (p = srchstr(t, "FG=color010"))){
8429 strncpy(p+3, transformed_color(p+3), 8);
8430 ret++;
8433 if((p = srchstr(t, "BG=color008")) ||
8434 (p = srchstr(t, "BG=color009")) ||
8435 (p = srchstr(t, "BG=color010"))){
8436 strncpy(p+3, transformed_color(p+3), 8);
8437 ret++;
8442 else{
8443 if((pval = PVAL(v,which)) != NULL){
8444 apval = APVAL(v,which);
8445 if(apval && (!strucmp(pval, "color008") ||
8446 !strucmp(pval, "color009") ||
8447 !strucmp(pval, "color010"))){
8448 new = transformed_color(pval);
8449 if(*apval)
8450 fs_give((void **)apval);
8452 *apval = cpystr(new);
8453 ret++;
8459 v = &ps->vars[V_PAT_INCOLS];
8460 if((lval = LVAL(v,which)) != NULL){
8461 for(s = lval; (t = *s) != NULL; s++){
8462 if((pstr = srchstr(t, "action=")) != NULL){
8463 if((p = srchstr(pstr, "FG=color008")) ||
8464 (p = srchstr(pstr, "FG=color009")) ||
8465 (p = srchstr(pstr, "FG=color010"))){
8466 strncpy(p+3, transformed_color(p+3), 8);
8467 ic++;
8470 if((p = srchstr(pstr, "BG=color008")) ||
8471 (p = srchstr(pstr, "BG=color009")) ||
8472 (p = srchstr(pstr, "BG=color010"))){
8473 strncpy(p+3, transformed_color(p+3), 8);
8474 ic++;
8480 if(ic)
8481 set_current_val(&ps->vars[V_PAT_INCOLS], TRUE, TRUE);
8483 return(ret+ic);
8488 unix_color_style_in_pinerc(prc)
8489 PINERC_S *prc;
8491 PINERC_LINE *pline;
8493 for(pline = prc ? prc->pinerc_lines : NULL;
8494 pline && (pline->var || pline->line); pline++)
8495 if(pline->line && !struncmp("color-style=", pline->line, 12))
8496 return(1);
8498 return(0);
8501 char *
8502 pcpine_general_help(titlebuf)
8503 char *titlebuf;
8505 if(titlebuf)
8506 strcpy(titlebuf, "PC Alpine For Windows");
8508 return(pcpine_help(h_pine_for_windows));
8511 #endif /* _WINDOWS */