* Bug fix: Tcp and http debug information is not printed unless the
[alpine.git] / pith / conf.c
blob809dfe6da66034609aca661acf9a97a55c45e69f
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-2021 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 CONF_TXT_T cf_html_directory[] = "Directory used by Alpine to save copies of html messages before they are\n#opened by an external web browser. The default directory is .alpine-html\n# in unix systems and alpine-html in a windows system.";
110 #ifdef SMIME
112 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.";
114 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.";
116 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.";
118 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.";
120 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.";
122 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.";
124 #endif /* SMIME */
126 #ifdef ENABLE_LDAP
127 CONF_TXT_T cf_text_ldap_server[] = "LDAP servers for looking up addresses.";
128 #endif /* ENABLE_LDAP */
130 CONF_TXT_T cf_text_rss_news[] = "RSS News feed";
132 CONF_TXT_T cf_text_rss_weather[] = "RSS Weather feed";
134 CONF_TXT_T cf_text_wp_indexheight[] = "Web Alpine index table row height";
136 CONF_TXT_T cf_text_wp_indexlines[] = "Web Alpine number of index lines in table";
138 CONF_TXT_T cf_text_wp_aggstate[] = "Web Alpine aggregate operations tab state";
140 CONF_TXT_T cf_text_wp_state[] = "Web Alpine various aspects of cross-session state";
142 CONF_TXT_T cf_text_wp_columns[] = "Web Alpine preferred width for message display in characters";
144 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).";
146 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";
148 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[]";
150 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}[]";
152 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";
154 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.";
156 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.";
158 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.";
160 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";
162 CONF_TXT_T cf_text_read_message_folder[] = "If set, specifies where already-read messages will be moved upon quitting.";
164 CONF_TXT_T cf_text_form_letter_folder[] = "If set, specifies where form letters should be stored.";
166 CONF_TXT_T cf_text_trash_folder[] = "If set, specifies where trash is moved to in Web Alpine.";
168 CONF_TXT_T cf_text_signature_file[] = "Over-rides default path for signature file. Default is ~/.signature";
170 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.";
172 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";
174 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";
176 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-.";
178 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)";
180 CONF_TXT_T cf_text_default_composer_hdrs[] = "Only show these headers (by default) when composing messages";
182 CONF_TXT_T cf_text_customized_hdrs[] = "Add these customized headers (and possible default values) when composing";
184 CONF_TXT_T cf_text_view_headers[] = "When viewing messages, include this list of headers";
186 CONF_TXT_T cf_text_view_margin_left[] = "When viewing messages, number of blank spaces between left display edge and text";
188 CONF_TXT_T cf_text_view_margin_right[] = "When viewing messages, number of blank spaces between right display edge and text";
190 CONF_TXT_T cf_text_quote_suppression[] = "When viewing messages, number of lines of quote displayed before suppressing";
192 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)";
194 CONF_TXT_T cf_text_color_style[] = "Controls display of color";
196 CONF_TXT_T cf_text_current_indexline_style[] = "Controls display of color for current index line";
198 CONF_TXT_T cf_text_titlebar_color_style[] = "Controls display of color for the titlebar at top of screen";
200 CONF_TXT_T cf_text_view_hdr_color[] = "When viewing messages, these are the header colors";
202 CONF_TXT_T cf_text_index_token_color[] = "Colors in which tokens will be displayed in the index screen";
204 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).";
206 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.)";
208 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\".";
210 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\".";
212 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\".";
214 CONF_TXT_T cf_text_old_char_set[] = "Character-set is obsolete, use display-character-set, keyboard-character-set,\n# and posting-character-set.";
216 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).";
218 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.";
220 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.";
222 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.";
224 CONF_TXT_T cf_text_editor[] = "Specifies the program invoked by ^_ in the Composer,\n# or the \"enable-alternate-editor-implicitly\" feature.";
226 CONF_TXT_T cf_text_speller[] = "Specifies the program invoked by ^T in the Composer.";
228 #ifdef _WINDOWS
229 CONF_TXT_T cf_text_speller_dictionary[] = "Specifies the list of dictionaries used by Aspell.";
230 #endif /* _WINDOWS */
232 CONF_TXT_T cf_text_deadlets[] = "Specifies the number of dead letter files to keep when canceling.";
234 CONF_TXT_T cf_text_fillcol[] = "Specifies the column of the screen where the composer should wrap.";
236 CONF_TXT_T cf_text_replystr[] = "Specifies the string to insert when replying to a message.";
238 CONF_TXT_T cf_text_quotereplstr[] = "Specifies the string to replace quotes with when viewing a message.";
240 CONF_TXT_T cf_text_replyintro[] = "Specifies the introduction to insert when replying to a message.";
242 CONF_TXT_T cf_text_emptyhdr[] = "Specifies the string to use when sending a message with no to or cc.";
244 CONF_TXT_T cf_text_image_viewer[] = "Program to view images (e.g. GIF or TIFF attachments).";
246 CONF_TXT_T cf_text_browser[] = "List of programs to open Internet URLs (e.g. http or ftp references).";
248 CONF_TXT_T cf_text_history[] = "List of directories that are preferred locations to save or export attachments.";
250 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\".";
252 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\".";
254 CONF_TXT_T cf_reopen_rule[] = "Controls behavior when reopening an already open folder.";
256 CONF_TXT_T cf_text_thread_disp_style[] = "Style that MESSAGE INDEX is displayed in when threading.";
258 CONF_TXT_T cf_text_thread_index_style[] = "Style of THREAD INDEX or default MESSAGE INDEX when threading.";
260 CONF_TXT_T cf_text_thread_more_char[] = "When threading, character used to indicate collapsed messages underneath.";
262 CONF_TXT_T cf_text_thread_exp_char[] = "When threading, character used to indicate expanded messages underneath.";
264 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.";
266 CONF_TXT_T cf_text_use_only_domain_name[] = "If \"user-domain\" not set, strips hostname in FROM address. (Unix only)";
268 CONF_TXT_T cf_text_printer[] = "Your default printer selection";
270 CONF_TXT_T cf_text_personal_print_command[] = "List of special print commands";
272 CONF_TXT_T cf_text_personal_print_cat[] = "Which category default print command is in";
274 CONF_TXT_T cf_text_standard_printer[] = "The system wide standard printers";
276 CONF_TXT_T cf_text_xoauth2_info[] = "Your client-id and client-secret information to authenticate using XOAUTH2";
278 CONF_TXT_T cf_text_last_time_prune_quest[] = "Set by Alpine; controls beginning-of-month sent-mail pruning.";
280 CONF_TXT_T cf_text_last_version_used[] = "Set by Alpine; controls display of \"new version\" message.";
282 CONF_TXT_T cf_text_disable_drivers[] = "List of mail drivers to disable.";
284 CONF_TXT_T cf_text_disable_auths[] = "List of SASL authenticators to disable.";
286 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.";
288 CONF_TXT_T cf_text_remote_abook_metafile[] = "Set by Alpine; contains data for caching remote address books.";
290 CONF_TXT_T cf_text_old_patterns[] = "Patterns is obsolete, use patterns-xxx";
292 CONF_TXT_T cf_text_old_filters[] = "Patterns-filters is obsolete, use patterns-filters2";
294 CONF_TXT_T cf_text_old_scores[] = "Patterns-scores is obsolete, use patterns-scores2";
296 CONF_TXT_T cf_text_patterns[] = "Patterns and their actions are stored here.";
298 CONF_TXT_T cf_text_remote_abook_history[] = "How many extra copies of remote address book should be kept. Default: 3";
300 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";
302 CONF_TXT_T cf_text_bugs_fullname[] = "Full name for bug report address used by \"Report Bug\" command";
304 CONF_TXT_T cf_text_bugs_address[] = "Email address used to send bug reports";
306 CONF_TXT_T cf_text_bugs_extras[] = "Program/Script used by \"Report Bug\" command. No default.";
308 CONF_TXT_T cf_text_suggest_fullname[] = "Full name for suggestion address used by \"Report Bug\" command";
310 CONF_TXT_T cf_text_suggest_address[] = "Email address used to send suggestions";
312 CONF_TXT_T cf_text_local_fullname[] = "Full name for \"local support\" address used by \"Report Bug\" command.\n# Default: Local Support";
314 CONF_TXT_T cf_text_local_address[] = "Email address used to send to \"local support\".\n# Default: postmaster";
316 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";
318 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.";
320 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.";
322 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)";
324 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.";
326 CONF_TXT_T cf_text_out_fltr[] = "This defines a program that message text is piped into before MIME\n# encoding, prior to sending";
328 CONF_TXT_T cf_text_alt_addrs[] = "A list of alternate addresses the user is known by";
330 CONF_TXT_T cf_text_keywords[] = "A list of keywords for use in categorizing messages";
332 CONF_TXT_T cf_text_kw_colors[] = "Colors used to display keywords in the index";
334 CONF_TXT_T cf_text_kw_braces[] = "Characters which surround keywords in SUBJKEY token.\n# Default is \"{\" \"} \"";
336 CONF_TXT_T cf_text_opening_sep[] = "Characters between subject and opening text in SUBJECTTEXT token.\n# Default is \" - \"";
338 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";
340 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";
342 CONF_TXT_T cf_text_overlap[] = "The number of lines of overlap when scrolling through message text";
344 CONF_TXT_T cf_text_maxremstreams[] = "The maximum number of non-stayopen remote connections that Alpine will use";
346 CONF_TXT_T cf_text_permlocked[] = "A list of folders that should be left open once opened (INBOX is implicit)";
348 CONF_TXT_T cf_text_margin[] = "Number of lines from top and bottom of screen where single\n# line scrolling occurs.";
350 CONF_TXT_T cf_text_stat_msg_delay[] = "The number of seconds to sleep after writing a status message";
352 CONF_TXT_T cf_text_busy_cue_rate[] = "Number of times per-second to update busy cue messages";
354 CONF_TXT_T cf_text_mailcheck[] = "The approximate number of seconds between checks for new mail";
356 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";
358 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";
360 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";
362 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\".";
364 CONF_TXT_T cf_text_news_spooldir[] = "Directory containing system's news data.\n# The default is typically \"/usr/spool/news\"";
366 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.";
368 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.";
370 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.";
372 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.";
374 CONF_TXT_T cf_text_goto_default[] = "Sets the default folder and collection offered at the Goto Command's prompt.";
376 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.";
378 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.";
380 #if !defined(_WINDOWS) || defined(WINDOWS_UNIXSSL_CERTS)
381 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.";
383 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.";
385 CONF_TXT_T cf_text_user_certs_path[] = "Sets the path for additional ssl certificates that the user trusts. Note\n#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.";
387 CONF_TXT_T cf_text_user_certs_file[] = "Sets the path for a file that contains certificates that a user trusts.\n#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.";
389 CONF_TXT_T cf_text_ciphers[] = "Colon separated list of ciphers that should be negotiated with the remote\n# ssl server upon connection.";
390 #endif
392 CONF_TXT_T cf_text_newmail_fifo_path[] = "Sets the filename for the newmail fifo (named pipe). Unix only.";
394 CONF_TXT_T cf_text_nmw_width[] = "Sets the width for the NewMail screen.";
396 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.";
398 CONF_TXT_T cf_text_debug_mem[] = "Debug-memory is obsolete";
400 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).";
402 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.";
404 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.";
406 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.";
408 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.";
410 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.";
412 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.";
414 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\")";
416 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.";
418 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.";
420 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.";
422 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.";
424 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.";
426 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.";
428 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\")";
430 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.";
432 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.";
434 CONF_TXT_T cf_text_elm_style_save[] = "Elm-style-save is obsolete, use saved-msg-name-rule";
436 CONF_TXT_T cf_text_header_in_reply[] = "Header-in-reply is obsolete, use include-header-in-reply in feature-list";
438 CONF_TXT_T cf_text_feature_level[] = "Feature-level is obsolete, use feature-list";
440 CONF_TXT_T cf_text_old_style_reply[] = "Old-style-reply is obsolete, use signature-at-bottom in feature-list";
442 CONF_TXT_T cf_text_compose_mime[] = "Compose-mime is obsolete";
444 CONF_TXT_T cf_text_show_all_characters[] = "Show-all-characters is obsolete";
446 CONF_TXT_T cf_text_save_by_sender[] = "Save-by-sender is obsolete, use saved-msg-name-rule";
448 CONF_TXT_T cf_text_file_dir[] = "Default directory used for Attachment handling (attach and save)\n# and Export command output";
450 CONF_TXT_T cf_text_folder_extension[] = "Folder-extension is obsolete";
452 CONF_TXT_T cf_text_normal_foreground_color[] = "Choose: black, blue, green, cyan, red, magenta, yellow, or white.";
454 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.";
456 CONF_TXT_T cf_text_newsrc_path[] = "Full path and name of NEWSRC file";
459 /*----------------------------------------------------------------------
460 These are the variables that control a number of pine functions. They
461 come out of the .pinerc and the /usr/local/lib/pine.conf files. Some can
462 be set by the user while in Alpine. Eventually all the local ones should
463 be so and maybe the global ones too.
465 Each variable can have a command-line, user, global, and current value.
466 All of these values are malloc'd. The user value is the one read out of
467 the user's .pinerc, the global value is the one from the system pine
468 configuration file. There are often defaults for the global values, set
469 at the start of init_vars(). Perhaps someday there will be group values.
470 The current value is the one that is actually in use.
471 ----*/
472 /* name is_changed_val
473 remove_quotes |
474 is_outermost | |
475 is_onlymain | | |
476 is_fixed | | | |
477 is_list | | | | |
478 is_global | | | | | |
479 is_user | | | | | | |
480 been_written | | | | | | | |
481 is_used | | | | | | | | |
482 is_obsolete | | | | | | | | | |
483 | | | | | | | | | | |
484 (on following line) description | | | | | | | | | | |
485 | | | | | | | | | | | |
486 | | | | | | | | | | | | */
487 static struct variable variables[] = {
488 {"personal-name", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
489 NULL, cf_text_personal_name},
491 #if defined(DOS) || defined(OS2)
492 /* Have to have this on DOS, PC's, Macs, etc... */
493 "user-id", 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0,
494 #else /* Don't allow on UNIX machines for some security */
495 "user-id", 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0,
496 #endif
497 "User ID", cf_text_user_id},
498 {"user-domain", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
499 NULL, cf_text_user_domain},
500 {"smtp-server", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
501 "SMTP Server (for sending)", cf_text_smtp_server},
502 {"nntp-server", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
503 "NNTP Server (for news)", cf_text_nntp_server},
504 {"inbox-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
505 NULL, cf_text_inbox_path},
506 {"incoming-archive-folders", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
507 NULL, cf_text_archived_folders},
508 {"pruned-folders", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
509 NULL, cf_text_pruned_folders},
510 {"default-fcc", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
511 "Default Fcc (File carbon copy)", cf_text_default_fcc},
512 {"default-saved-msg-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
513 "Default Saved Message Folder", cf_text_default_saved},
514 {"postponed-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
515 NULL, cf_text_postponed_folder},
516 {"read-message-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
517 NULL, cf_text_read_message_folder},
518 {"form-letter-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
519 NULL, cf_text_form_letter_folder},
520 {"trash-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
521 NULL, cf_text_trash_folder},
522 {"literal-signature", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
523 NULL, cf_text_literal_sig},
524 {"signature-file", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
525 NULL, cf_text_signature_file},
526 {"feature-list", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
527 NULL, cf_text_feature_list},
528 {"initial-keystroke-list", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
529 NULL, cf_text_initial_keystroke_list},
530 {"default-composer-hdrs", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
531 "Default Composer Headers", cf_text_default_composer_hdrs},
532 {"customized-hdrs", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
533 "Customized Headers", cf_text_customized_hdrs},
534 {"viewer-hdrs", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
535 "Viewer Headers", cf_text_view_headers},
536 {"viewer-margin-left", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
537 NULL, cf_text_view_margin_left},
538 {"viewer-margin-right", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
539 NULL, cf_text_view_margin_right},
540 {"quote-suppression-threshold", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
541 NULL, cf_text_quote_suppression},
542 {"saved-msg-name-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
543 "Saved Message Name Rule", cf_text_save_msg_name_rule},
544 {"fcc-name-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
545 NULL, cf_text_fcc_name_rule},
546 {"sort-key", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
547 NULL, cf_text_sort_key},
548 {"addrbook-sort-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
549 "Address Book Sort Rule", cf_text_addrbook_sort_rule},
550 {"folder-sort-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
551 NULL, cf_text_folder_sort_rule},
552 {"goto-default-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
553 NULL, cf_text_goto_default},
554 {"incoming-startup-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
555 NULL, cf_text_inc_startup},
556 {"pruning-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
557 NULL, cf_pruning_rule},
558 {"folder-reopen-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
559 NULL, cf_reopen_rule},
560 {"threading-display-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
561 NULL, cf_text_thread_disp_style},
562 {"threading-index-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
563 NULL, cf_text_thread_index_style},
564 {"threading-indicator-character", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
565 NULL, cf_text_thread_more_char},
566 {"threading-expanded-character", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
567 NULL, cf_text_thread_exp_char},
568 {"threading-lastreply-character", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
569 "Threading Last Reply Character", cf_text_thread_lastreply_char},
570 #ifndef _WINDOWS
571 {"display-character-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
572 NULL, cf_text_disp_char_set},
573 {"character-set", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
574 NULL, cf_text_old_char_set},
575 {"keyboard-character-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
576 NULL, cf_text_key_char_set},
577 #endif /* ! _WINDOWS */
578 {"posting-character-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
579 NULL, cf_text_post_character_set},
580 {"unknown-character-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
581 NULL, cf_text_unk_character_set},
582 {"editor", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
583 NULL, cf_text_editor},
584 {"speller", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
585 NULL, cf_text_speller},
586 #ifdef _WINDOWS
587 {"aspell-dictionary-list", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
588 "Aspell Dictionaries", cf_text_speller_dictionary},
589 #endif /* _WINDOWS */
590 {"composer-wrap-column", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
591 NULL, cf_text_fillcol},
592 {"reply-indent-string", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
593 NULL, cf_text_replystr},
594 {"reply-leadin", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
595 NULL, cf_text_replyintro},
596 {"quote-replace-string", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
597 NULL, cf_text_quotereplstr},
598 {"composer-word-separators", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
599 NULL, cf_text_wordsep},
600 {"empty-header-message", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
601 NULL, cf_text_emptyhdr},
602 {"image-viewer", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
603 NULL, cf_text_image_viewer},
604 {"use-only-domain-name", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
605 NULL, cf_text_use_only_domain_name},
606 {"bugs-fullname", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
607 NULL, cf_text_bugs_fullname},
608 {"bugs-address", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
609 NULL, cf_text_bugs_address},
610 {"bugs-additional-data", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
611 NULL, cf_text_bugs_extras},
612 {"suggest-fullname", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
613 NULL, cf_text_suggest_fullname},
614 {"suggest-address", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
615 NULL, cf_text_suggest_address},
616 {"local-fullname", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
617 NULL, cf_text_local_fullname},
618 {"local-address", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
619 NULL, cf_text_local_address},
620 {"forced-abook-entry", 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0,
621 NULL, cf_text_forced_abook},
622 {"kblock-passwd-count", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
623 NULL, cf_text_kblock_passwd},
624 {"display-filters", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
625 NULL, cf_text_in_fltr},
626 {"sending-filters", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
627 NULL, cf_text_out_fltr},
628 {"alt-addresses", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
629 "Alternate Addresses", cf_text_alt_addrs},
630 {"keywords", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
631 NULL, cf_text_keywords},
632 {"keyword-surrounding-chars", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
633 "Keyword Surrounding Characters", cf_text_kw_braces},
634 {"opening-text-separator-chars", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
635 "Opening Text Separator Characters", cf_text_opening_sep},
636 {"addressbook-formats", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
637 "Address Book Formats", cf_text_abook_formats},
638 {"index-format", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
639 NULL, cf_text_index_format},
640 {"viewer-overlap", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
641 NULL, cf_text_overlap},
642 {"scroll-margin", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
643 NULL, cf_text_margin},
644 {"status-message-delay", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
645 NULL, cf_text_stat_msg_delay},
646 {"busy-cue-rate", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
647 NULL, cf_text_busy_cue_rate},
648 {"mail-check-interval", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
649 NULL, cf_text_mailcheck},
650 {"mail-check-interval-noncurrent", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
651 NULL, cf_text_mailchecknoncurr},
652 {"maildrop-check-minimum", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
653 NULL, cf_text_maildropcheck},
654 {"nntp-range", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
655 "NNTP Range", cf_text_nntprange},
656 {"newsrc-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
657 NULL, cf_text_newsrc_path},
658 {"news-active-file-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
659 NULL, cf_text_news_active},
660 {"news-spool-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
661 NULL, cf_text_news_spooldir},
662 {"upload-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
663 NULL, cf_text_upload_cmd},
664 {"upload-command-prefix", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
665 NULL, cf_text_upload_prefix},
666 {"download-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
667 NULL, cf_text_download_cmd},
668 {"download-command-prefix", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
669 NULL, cf_text_download_prefix},
670 {"mailcap-search-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
671 NULL, cf_text_mailcap_path},
672 {"mimetype-search-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
673 NULL, cf_text_mimetype_path},
674 #if !defined(_WINDOWS) || defined(WINDOWS_UNIXSSL_CERTS)
675 {"system-certs-path", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
676 "System CACerts Dir", cf_text_system_certs_path},
677 {"system-certs-file", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
678 "System CACerts File", cf_text_system_certs_file},
679 {"user-certs-path", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
680 "User Certs Dir", cf_text_user_certs_file},
681 {"user-certs-file", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
682 "User Certs File", cf_text_user_certs_file},
683 {"ssl-ciphers", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
684 "SSL Ciphers", cf_text_ciphers},
685 #endif
686 {"url-viewers", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
687 "URL-Viewers", cf_text_browser},
688 {"default-directories", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
689 "Extra Directories for Save", cf_text_history},
690 {"max-remote-connections", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
691 "Maximum Remote Connections", cf_text_maxremstreams},
692 {"stay-open-folders", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
693 "Stayopen Folders", cf_text_permlocked},
694 {"incoming-check-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
695 NULL, cf_text_inc_check_timeo},
696 {"incoming-check-interval", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
697 NULL, cf_text_inc_check_interval},
698 {"incoming-check-interval-secondary", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
699 NULL, cf_text_inc_second_check_interval},
700 {"incoming-check-list", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
701 NULL, cf_text_inc_check_list},
702 {"dead-letter-files", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
703 NULL, cf_text_deadlets},
704 #if !defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)
705 {"newmail-fifo-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
706 "NewMail FIFO Path", cf_text_newmail_fifo_path},
707 #endif
708 {"newmail-window-width", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
709 "NewMail Window Width", cf_text_nmw_width},
711 * Starting here, the variables are hidden in the Setup/Config screen.
712 * They are exposed if feature expose-hidden-config is set.
714 {"incoming-folders", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
715 NULL, cf_text_incoming_folders},
716 {"mail-directory", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
717 NULL, cf_text_mail_directory},
718 {"folder-collections", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
719 NULL, cf_text_folder_collections},
720 {"news-collections", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
721 NULL, cf_text_news_collections},
722 {"address-book", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
723 NULL, cf_text_address_book},
724 {"global-address-book", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
725 NULL, cf_text_global_address_book},
726 {"standard-printer", 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0,
727 NULL, cf_text_standard_printer},
728 {"last-time-prune-questioned", 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0,
729 NULL, cf_text_last_time_prune_quest},
730 {"last-version-used", 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0,
731 NULL, cf_text_last_version_used},
732 {"sendmail-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
733 NULL, cf_text_sendmail_path},
734 {"operating-dir", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
735 NULL, cf_text_oper_dir},
736 {"user-input-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
737 NULL, cf_text_user_input_timeo},
738 /* OBSOLETE */
739 #ifdef DEBUGJOURNAL
740 {"debug-memory", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
741 NULL, cf_text_debug_mem},
742 #endif
743 {"tcp-open-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
744 "TCP Open Timeout", cf_text_tcp_open_timeo},
745 {"tcp-read-warning-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
746 "TCP Read Warning Timeout", cf_text_tcp_read_timeo},
747 {"tcp-write-warning-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
748 "TCP Write Warning Timeout", cf_text_tcp_write_timeo},
749 {"tcp-query-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
750 "TCP Query Timeout", cf_text_tcp_query_timeo},
751 {"close-connection-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
752 NULL, cf_text_close_connection_timeo},
753 {"rsh-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
754 NULL, cf_text_rsh_command},
755 {"rsh-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
756 NULL, cf_text_rsh_path},
757 {"rsh-open-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
758 NULL, cf_text_rsh_open_timeo},
759 {"ssh-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
760 NULL, cf_text_ssh_command},
761 {"ssh-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
762 NULL, cf_text_ssh_path},
763 {"ssh-open-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
764 NULL, cf_text_ssh_open_timeo},
765 {"new-version-threshold", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
766 NULL, cf_text_version_threshold},
767 {"disable-these-drivers", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
768 NULL, cf_text_disable_drivers},
769 {"disable-these-authenticators", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
770 NULL, cf_text_disable_auths},
771 {"encryption-protocol-range", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
772 NULL, cf_text_encryption_range},
773 {"remote-abook-metafile", 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0,
774 NULL, cf_text_remote_abook_metafile},
775 {"remote-abook-history", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
776 NULL, cf_text_remote_abook_history},
777 {"remote-abook-validity", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
778 NULL, cf_text_remote_abook_validity},
779 {"printer", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
780 NULL, cf_text_printer},
781 {"personal-print-command", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
782 NULL, cf_text_personal_print_command},
783 {"personal-print-category", 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0,
784 NULL, cf_text_personal_print_cat},
785 {"xoauth2-info", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
786 "XOAUTH2 Info", cf_text_xoauth2_info},
787 {"patterns", 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
788 NULL, cf_text_old_patterns},
789 {"patterns-roles", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
790 NULL, cf_text_patterns},
791 {"patterns-filters2", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
792 "Patterns Filters", cf_text_patterns},
793 {"patterns-filters", 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
794 NULL, cf_text_old_filters},
795 {"patterns-scores2", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
796 "Patterns Scores", cf_text_patterns},
797 {"patterns-scores", 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
798 NULL, cf_text_old_scores},
799 {"patterns-indexcolors", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
800 NULL, cf_text_patterns},
801 {"patterns-other", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
802 NULL, cf_text_patterns},
803 {"patterns-search", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
804 NULL, cf_text_patterns},
805 /* OBSOLETE VARS */
806 {"elm-style-save", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
807 NULL, cf_text_elm_style_save},
808 {"header-in-reply", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
809 NULL, cf_text_header_in_reply},
810 {"feature-level", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
811 NULL, cf_text_feature_level},
812 {"old-style-reply", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
813 NULL, cf_text_old_style_reply},
814 {"compose-mime", 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
815 NULL, cf_text_compose_mime},
816 {"show-all-characters", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
817 NULL, cf_text_show_all_characters},
818 {"save-by-sender", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
819 NULL, cf_text_save_by_sender},
820 #if defined(DOS) || defined(OS2)
821 {"file-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
822 NULL, cf_text_file_dir},
823 {"folder-extension", 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0,
824 NULL, cf_text_folder_extension},
825 #endif
826 #ifndef _WINDOWS
827 {"color-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
828 NULL, cf_text_color_style},
829 #endif
830 {"current-indexline-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
831 NULL, cf_text_current_indexline_style},
832 {"titlebar-color-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
833 NULL, cf_text_titlebar_color_style},
834 {"normal-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
835 NULL, cf_text_normal_foreground_color},
836 {"normal-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
837 {"reverse-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
838 {"reverse-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
839 {"title-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
840 {"title-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
841 {"title-closed-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
842 {"title-closed-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
843 {"folder-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
844 {"folder-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
845 {"directory-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
846 {"directory-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
847 {"folder-list-text-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
848 {"folder-list-text-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
849 {"status-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
850 {"status-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
851 {"keylabel-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
852 {"keylabel-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
853 {"keyname-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
854 {"keyname-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
855 {"selectable-item-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
856 {"selectable-item-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
857 {"meta-message-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
858 {"meta-message-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
859 {"quote1-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
860 {"quote1-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
861 {"quote2-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
862 {"quote2-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
863 {"quote3-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
864 {"quote3-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
865 {"incoming-unseen-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
866 {"incoming-unseen-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
867 {"signature-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
868 {"signature-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
869 {"prompt-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
870 {"prompt-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
871 {"header-general-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
872 {"header-general-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
873 {"index-to-me-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
874 {"index-to-me-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
875 {"index-important-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
876 {"index-important-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
877 {"index-deleted-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
878 {"index-deleted-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
879 {"index-answered-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
880 {"index-answered-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
881 {"index-new-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
882 {"index-new-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
883 {"index-recent-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
884 {"index-recent-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
885 {"index-forward-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
886 {"index-forward-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
887 {"index-unseen-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
888 {"index-unseen-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
889 {"index-highpriority-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
890 {"index-highpriority-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
891 {"index-lowpriority-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
892 {"index-lowpriority-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
893 {"index-arrow-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
894 {"index-arrow-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
895 {"index-subject-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
896 {"index-subject-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
897 {"index-from-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
898 {"index-from-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
899 {"index-opening-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
900 {"index-opening-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
901 {"index-token-colors", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
902 NULL, cf_text_index_token_color},
903 {"viewer-hdr-colors", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
904 "Viewer Header Colors", cf_text_view_hdr_color},
905 {"keyword-colors", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
906 NULL, cf_text_kw_colors},
907 #ifdef _WINDOWS
908 {"font-name", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
909 NULL, "name and size of font."},
910 {"font-size", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
911 {"font-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
912 {"font-char-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
913 {"print-font-name", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
914 NULL, "name and size of printer font."},
915 {"print-font-size", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
916 {"print-font-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
917 {"print-font-char-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
918 {"window-position", 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0,
919 NULL, cf_text_window_position},
920 {"cursor-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
921 #endif /* _WINDOWS */
922 {"html-messages-directory", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
923 NULL, cf_html_directory},
924 #ifdef SMIME
925 {"smime-public-cert-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
926 "S/MIME - Public Cert Directory", cf_text_publiccertdir},
927 {"smime-public-cert-container", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
928 "S/MIME - Public Cert Container", cf_text_publiccertcontainer},
929 {"smime-private-key-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
930 "S/MIME - Private Key Directory", cf_text_privatekeydir},
931 {"smime-private-key-container", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
932 "S/MIME - Private Key Container", cf_text_privatekeycontainer},
933 {"smime-cacert-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
934 "S/MIME - Cert Authority Directory", cf_text_cacertdir},
935 {"smime-cacert-container", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
936 "S/MIME - Cert Authority Container", cf_text_cacertcontainer},
937 #endif /* SMIME */
938 #ifdef ENABLE_LDAP
939 {"ldap-servers", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
940 "LDAP Servers", cf_text_ldap_server},
941 #endif /* ENABLE_LDAP */
942 {"rss-news", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
943 "WEB ALPINE - RSS News", cf_text_rss_news},
944 {"rss-weather", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
945 "WEB ALPINE - RSS Weather", cf_text_rss_weather},
946 {"wp-indexheight", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
947 "WEB ALPINE - Index Height", cf_text_wp_indexheight},
948 {"wp-indexlines", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
949 "WEB ALPINE - Index Lines", cf_text_wp_indexlines},
950 {"wp-aggstate", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
951 "WEB ALPINE - Aggregate State", cf_text_wp_aggstate},
952 {"wp-state", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
953 "WEB ALPINE - Cross Session State", cf_text_wp_state},
954 {"wp-columns", 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0,
955 "WEB ALPINE - Columns", cf_text_wp_columns},
956 {NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL,NULL}
960 struct variable *
961 var_from_name(char *name)
963 struct variable *v;
964 int i;
966 if(!(name && name[0]))
967 return(NULL);
969 for(i = 0; (v = &variables[i]) && v->name; i++)
970 if(!strucmp(v->name,name))
971 return(v);
973 return(NULL);
977 void
978 init_init_vars(struct pine *ps)
980 ps->vars = variables;
984 #define DSIZE (25000)
985 /* this is just like dprint except it prints to a char * */
986 #ifdef DEBUG
987 #define mprint(n,x) { \
988 if(debug >= (n)){ \
989 snprintf x ; \
990 db += strlen(db); \
993 #else
994 #define mprint(n,x)
995 #endif
998 * this was split out from init_vars so we can get at the
999 * pinerc location sooner.
1001 void
1002 init_pinerc(struct pine *ps, char **debug_out)
1004 char buf[MAXPATH+1], *p, *db = NULL;
1005 #if defined(DOS) || defined(OS2)
1006 char buf2[MAXPATH+1], l_pinerc[MAXPATH+1];
1007 int nopinerc = 0, confregset = -1;
1008 register struct variable *vars = ps->vars;
1009 #endif
1011 #ifdef DEBUG
1013 * Since this routine is called before we've had a chance to set up
1014 * the debug file for output, we put the debugging into memory and
1015 * pass it back to the caller for use after init_debug(). We just
1016 * allocate plenty of space.
1018 if(debug_out){
1019 db = *debug_out = (char *)fs_get(DSIZE * sizeof(char));
1020 db[0] = '\0';
1022 #endif
1024 mprint(2, (db, DSIZE-(db-(*debug_out)), "\n -- init_pinerc --\n\n"));
1026 #if defined(DOS) || defined(OS2)
1028 * Rules for the config/support file locations under DOS are:
1030 * 1) The location of the PINERC is searched for in the following
1031 * order of precedence:
1032 * - File pointed to by '-p' command line option
1033 * - File pointed to by PINERC environment variable
1034 * - $HOME\pine
1035 * - same dir as argv[0]
1037 * 2) The HOME environment variable, if not set, defaults to
1038 * root of the current working drive (see alpine.c)
1040 * 3) The default for external files (PINE.SIG and ADDRBOOK) is the
1041 * same directory as the pinerc
1043 * 4) The support files (PINE.HLP and PINE.NDX) are expected to be in
1044 * the same directory as PINE.EXE.
1047 if(ps->prc){
1048 mprint(2, (db, DSIZE-(db-(*debug_out)),
1049 "Personal config \"%.100s\" comes from command line\n",
1050 (ps->prc && ps->prc->name) ? ps->prc->name : "<no name>"));
1052 else{
1053 mprint(2, (db, DSIZE-(db-(*debug_out)),
1054 "Personal config not set on cmdline, checking for $PINERC\n"));
1058 * First, if prc hasn't been set by a command-line -p, check to see
1059 * if PINERC is in the environment. If so, treat it just like we
1060 * would have treated it if it were a command-line arg.
1062 if(!ps->prc && (p = getenv("PINERC")) && *p){
1063 char path[MAXPATH], dir[MAXPATH];
1065 if(IS_REMOTE(p) || is_absolute_path(p)){
1066 strncpy(path, p, sizeof(path)-1);
1067 path[sizeof(path)-1] = '\0';
1069 else{
1070 getcwd(dir, sizeof(dir));
1071 build_path(path, dir, p, sizeof(path));
1074 if(!IS_REMOTE(p))
1075 ps->pinerc = cpystr(path);
1077 ps->prc = new_pinerc_s(path);
1079 if(ps->prc){
1080 mprint(2, (db, DSIZE-(db-(*debug_out)),
1081 " yes, personal config \"%.100s\" comes from $PINERC\n",
1082 (ps->prc && ps->prc->name) ? ps->prc->name : "<no name>"));
1087 * Pinerc used to be the name of the pinerc file. Then we added
1088 * the possibility of the pinerc file being remote, and we replaced
1089 * the variable pinerc with the structure prc. Unfortunately, some
1090 * parts of pine rely on the fact that pinerc is the name of the
1091 * pinerc _file_, and use the directory that the pinerc file is located
1092 * in for their own purposes. We want to preserve that so things will
1093 * keep working. So, even if the real pinerc is remote, we need to
1094 * put the name of a pinerc file in the pinerc variable so that the
1095 * directory which contains that file is writable. The file itself
1096 * doesn't have to exist for this purpose, since we are really only
1097 * using the name of the directory containing the file. Twisted.
1098 * (Alternatively, we could fix all of the code that uses the pinerc
1099 * variable for this purpose to use a new variable which really is
1100 * just a directory.) hubert 2000-sep
1102 * There are 3 cases. If pinerc is already set that means that the user
1103 * gave either a -p pinerc or an environment pinerc that is a local file,
1104 * and we are done. If pinerc is not set, then either prc is set or not.
1105 * If prc is set then the -p arg or PINERC value is a remote pinerc.
1106 * In that case we need to find a local directory to use, and put that
1107 * directory in the pinerc variable (with a fake filename tagged on).
1108 * If prc is not set, then user hasn't told us anything so we have to
1109 * try to find the default pinerc file by looking down the path of
1110 * possibilities. When we find it, we'll also use that directory.
1112 if(!ps->pinerc){
1113 *l_pinerc = '\0';
1114 *buf = '\0';
1116 if(ps->prc){ /* remote pinerc case */
1118 * We don't give them an l_pinerc unless they tell us where
1119 * to put it.
1121 if(ps->aux_files_dir)
1122 build_path(l_pinerc, ps->aux_files_dir, SYSTEM_PINERC,
1123 sizeof(l_pinerc));
1124 else{
1126 * Search for a writable directory.
1127 * Mimic what happens in !prc for local case, except we
1128 * don't need to look for the actual file.
1131 /* check if $HOME\PINE is writable */
1132 build_path(buf2, ps->home_dir, DF_PINEDIR, sizeof(buf2));
1133 if(is_writable_dir(buf2) == 0)
1134 build_path(l_pinerc, buf2, SYSTEM_PINERC, sizeof(l_pinerc));
1135 else{ /* $HOME\PINE not a writable dir */
1136 /* use this unless registry redirects us */
1137 build_path(l_pinerc, ps->pine_dir, SYSTEM_PINERC,
1138 sizeof(l_pinerc));
1139 #ifdef _WINDOWS
1140 /* if in registry, use that value */
1141 if(mswin_reg(MSWR_OP_GET, MSWR_PINE_RC, buf2, sizeof(buf2))
1142 && !IS_REMOTE(buf2)){
1143 strncpy(l_pinerc, buf2, sizeof(l_pinerc)-1);
1144 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1146 #endif
1150 else{ /* searching for pinerc file to use */
1152 * Buf2 is $HOME\PINE. If $HOME is not explicitly set,
1153 * it defaults to the current working drive (often C:).
1154 * See alpine.c to see how it is initially set.
1157 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, searching...\n"));
1158 build_path(buf2, ps->home_dir, DF_PINEDIR, sizeof(buf2));
1159 mprint(2, (db, DSIZE-(db-(*debug_out)),
1160 " checking for writable %.100s dir \"%.100s\" off of homedir\n",
1161 DF_PINEDIR, buf2));
1162 if(is_writable_dir(buf2) == 0){
1164 * $HOME\PINE exists and is writable.
1165 * See if $HOME\PINE\PINERC exists.
1167 build_path(buf, buf2, SYSTEM_PINERC, sizeof(buf));
1168 strncpy(l_pinerc, buf, sizeof(l_pinerc)-1);
1169 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1170 mprint(2, (db, DSIZE-(db-(*debug_out)), " yes, now checking for file \"%.100s\"\n",
1171 buf));
1172 if(can_access(buf, ACCESS_EXISTS) == 0){ /* found it! */
1174 * Buf is what we were looking for.
1175 * It is local and can be used for the directory, too.
1177 mprint(2, (db, DSIZE-(db-(*debug_out)), " found it\n"));
1179 else{
1181 * No $HOME\PINE\PINERC, look for
1182 * one in same dir as PINE.EXE.
1184 build_path(buf2, ps->pine_dir, SYSTEM_PINERC,
1185 sizeof(buf2));
1186 mprint(2, (db, DSIZE-(db-(*debug_out)),
1187 " no, checking for \"%.100s\" in pine.exe dir\n",
1188 buf2));
1189 if(can_access(buf2, ACCESS_EXISTS) == 0){
1190 /* found it! */
1191 mprint(2, (db, DSIZE-(db-(*debug_out)), " found it\n"));
1192 strncpy(buf, buf2, sizeof(buf)-1);
1193 buf[sizeof(buf)-1] = '\0';
1194 strncpy(l_pinerc, buf2, sizeof(l_pinerc)-1);
1195 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1197 else{
1198 #ifdef _WINDOWS
1199 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, checking in registry\n"));
1200 if(mswin_reg(MSWR_OP_GET, MSWR_PINE_RC,
1201 buf2, sizeof(buf2))){
1202 strncpy(buf, buf2, sizeof(buf)-1);
1203 buf[sizeof(buf)-1] = '\0';
1204 if(!IS_REMOTE(buf2)){
1205 strncpy(l_pinerc, buf2, sizeof(l_pinerc)-1);
1206 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1209 * Now buf is the pinerc to be used, l_pinerc is
1210 * the directory, which may be either same as buf
1211 * or it may be $HOME\PINE if registry gives us
1212 * a remote pinerc.
1214 mprint(2, (db, DSIZE-(db-(*debug_out)), " found \"%.100s\" in registry\n",
1215 buf));
1217 else{
1218 nopinerc = 1;
1219 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found, asking user\n"));
1221 #else
1222 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found\n"));
1223 #endif
1228 * Buf is the pinerc (could be remote if from registry)
1229 * and l_pinerc is the local pinerc, which may not exist.
1232 else{ /* $HOME\PINE not a writable dir */
1234 * We notice that the order of checking in the registry
1235 * and checking in the ALPINE.EXE directory are different
1236 * in this case versus the is_writable_dir(buf2) case, and
1237 * that does sort of look like a bug. However,
1238 * we don't think this is a bug since we did it on purpose
1239 * a long time ago. So even though we can't remember why
1240 * it is this way, we think we would rediscover why if we
1241 * changed it! So we won't change it.
1245 * Change the default to use to the ALPINE.EXE directory.
1247 build_path(buf, ps->pine_dir, SYSTEM_PINERC, sizeof(buf));
1248 strncpy(l_pinerc, buf, sizeof(l_pinerc)-1);
1249 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1250 #ifdef _WINDOWS
1251 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, not writable, checking in registry\n"));
1252 /* if in registry, use that value */
1253 if(mswin_reg(MSWR_OP_GET, MSWR_PINE_RC, buf2, sizeof(buf2))){
1254 strncpy(buf, buf2, sizeof(buf)-1);
1255 buf[sizeof(buf)-1] = '\0';
1256 mprint(2, (db, DSIZE-(db-(*debug_out)), " found \"%.100s\" in registry\n",
1257 buf));
1258 if(!IS_REMOTE(buf)){
1259 strncpy(l_pinerc, buf, sizeof(l_pinerc)-1);
1260 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1263 else{
1264 mprint(2, (db, DSIZE-(db-(*debug_out)),
1265 " no, checking for \"%.100s\" in alpine.exe dir\n",
1266 buf));
1268 if(can_access(buf, ACCESS_EXISTS) == 0){
1269 mprint(2, (db, DSIZE-(db-(*debug_out)), " found it\n"));
1271 else{
1272 nopinerc = 1;
1273 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found, asking user\n"));
1276 #else
1277 mprint(2, (db, DSIZE-(db-(*debug_out)),
1278 " no, checking for \"%.100s\" in alpine.exe dir\n",
1279 buf));
1281 if(can_access(buf, ACCESS_EXISTS) == 0){
1282 mprint(2, (db, DSIZE-(db-(*debug_out)), " found it\n"));
1284 else{
1285 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found, creating it\n"));
1287 #endif
1291 * When we get here we have buf set to the name of the
1292 * pinerc, which could be local or remote. We have l_pinerc
1293 * set to the same as buf if buf is local, and set to another
1294 * name otherwise, hopefully contained in a writable directory.
1296 #ifdef _WINDOWS
1297 if(nopinerc || ps_global->install_flag){
1298 char buf3[MAXPATH+1];
1300 confregset = 0;
1301 strncpy(buf3, buf, MAXPATH);
1302 buf3[MAXPATH] = '\0';
1303 if(os_config_dialog(buf3, MAXPATH,
1304 &confregset, nopinerc) == 0){
1305 strncpy(buf, buf3, MAXPATH);
1306 buf[MAXPATH] = '\0';
1307 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found, creating it\n"));
1308 mprint(2, (db, DSIZE-(db-(*debug_out)), " user says use \"%.100s\"\n", buf));
1309 if(!IS_REMOTE(buf)){
1310 strncpy(l_pinerc, buf, MAXPATH);
1311 l_pinerc[MAXPATH] = '\0';
1314 else{
1315 exit(-1);
1318 #endif
1319 ps->prc = new_pinerc_s(buf);
1322 ps->pinerc = cpystr(l_pinerc);
1325 #if defined(DOS) || defined(OS2)
1327 * The goal here is to set the auxiliary directory in the pinerc variable.
1328 * We are making the assumption that any reference to the pinerc variable
1329 * after this point is used only as a directory in which to store things,
1330 * with the prc variable being the preferred place to store pinerc location.
1331 * If -aux isn't set, then there is no change. -jpf 08/2001
1333 if(ps->aux_files_dir){
1334 l_pinerc[0] = '\0';
1335 build_path(l_pinerc, ps->aux_files_dir, SYSTEM_PINERC,
1336 sizeof(l_pinerc));
1337 if(ps->pinerc) fs_give((void **)&ps->pinerc);
1338 ps->pinerc = cpystr(l_pinerc);
1339 mprint(2, (db, DSIZE-(db-(*debug_out)), "Setting aux_files_dir to \"%.100s\"\n",
1340 ps->aux_files_dir));
1342 #endif
1344 #ifdef _WINDOWS
1345 if(confregset && (ps->update_registry != UREG_NEVER_SET))
1346 mswin_reg(MSWR_OP_SET | ((ps->update_registry == UREG_ALWAYS_SET)
1347 || confregset == 1 ? MSWR_OP_FORCE : 0),
1348 MSWR_PINE_RC,
1349 (ps->prc && ps->prc->name) ?
1350 ps->prc->name : ps->pinerc, (size_t)NULL);
1351 #endif
1354 * Now that we know the default for the PINERC, build NEWSRC default.
1355 * Backward compatibility makes this kind of funky. If what the
1356 * c-client thinks the NEWSRC should be exists *AND* it doesn't
1357 * already exist in the PINERC's dir, use c-client's default, otherwise
1358 * use the one next to the PINERC...
1360 p = last_cmpnt(ps->pinerc);
1361 buf[0] = '\0';
1362 if(p != NULL){
1363 strncpy(buf, ps->pinerc, MIN(p - ps->pinerc, sizeof(buf)-1));
1364 buf[MIN(p - ps->pinerc, sizeof(buf)-1)] = '\0';
1367 mprint(2, (db, DSIZE-(db-(*debug_out)), "Using directory \"%.100s\" for auxiliary files\n", buf));
1368 strncat(buf, "NEWSRC", sizeof(buf)-1-strlen(buf));
1370 if(!(p = (void *) mail_parameters(NULL, GET_NEWSRC, (void *)NULL))
1371 || can_access(p, ACCESS_EXISTS) < 0
1372 || can_access(buf, ACCESS_EXISTS) == 0){
1373 mail_parameters(NULL, SET_NEWSRC, (void *)buf);
1374 GLO_NEWSRC_PATH = cpystr(buf);
1376 else
1377 GLO_NEWSRC_PATH = cpystr(p);
1379 if(ps->pconf){
1380 mprint(2, (db, DSIZE-(db-(*debug_out)), "Global config \"%.100s\" comes from command line\n",
1381 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1383 else{
1384 mprint(2, (db, DSIZE-(db-(*debug_out)),
1385 "Global config not set on cmdline, checking for $PINECONF\n"));
1388 if(!ps->pconf && (p = getenv("PINECONF"))){
1389 ps->pconf = new_pinerc_s(p);
1390 if(ps->pconf){
1391 mprint(2, (db, DSIZE-(db-(*debug_out)),
1392 " yes, global config \"%.100s\" comes from $PINECONF\n",
1393 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1396 #ifdef _WINDOWS
1397 else if(!ps->pconf
1398 && mswin_reg(MSWR_OP_GET, MSWR_PINE_CONF, buf2, sizeof(buf2))){
1399 ps->pconf = new_pinerc_s(buf2);
1400 if(ps->pconf){
1401 mprint(2, (db, DSIZE-(db-(*debug_out)),
1402 " yes, global config \"%.100s\" comes from Registry\n",
1403 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1406 #endif
1407 if(!ps->pconf){
1408 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, there is no global config\n"));
1410 #ifdef _WINDOWS
1411 else if (ps->pconf && ps->pconf->name &&
1412 (ps->update_registry != UREG_NEVER_SET)){
1413 mswin_reg(MSWR_OP_SET | ((ps->update_registry == UREG_ALWAYS_SET)
1414 ? MSWR_OP_FORCE : 0),
1415 MSWR_PINE_CONF,
1416 ps->pconf->name, (size_t)NULL);
1418 #endif
1420 if(!ps->prc)
1421 ps->prc = new_pinerc_s(ps->pinerc);
1423 if(ps->exceptions){
1424 mprint(2, (db, DSIZE-(db-(*debug_out)),
1425 "Exceptions config \"%.100s\" comes from command line\n",
1426 ps->exceptions));
1428 else{
1429 mprint(2, (db, DSIZE-(db-(*debug_out)),
1430 "Exceptions config not set on cmdline, checking for $PINERCEX\n"));
1434 * Exceptions is done slightly differently from pinerc. Instead of setting
1435 * post_prc in args.c we just set the string and use it here. We do
1436 * that so that we can put it in the same directory as the pinerc if
1437 * exceptions is a relative name, and pinerc may not be set until here.
1439 * First, just like for pinerc, check environment variable if it wasn't
1440 * set on the command line.
1442 if(!ps->exceptions && (p = getenv("PINERCEX")) && *p){
1443 ps->exceptions = cpystr(p);
1444 if(ps->exceptions){
1445 mprint(2, (db, DSIZE-(db-(*debug_out)),
1446 " yes, exceptions config \"%.100s\" comes from $PINERCEX\n",
1447 ps->exceptions));
1452 * If still not set, try specific file in same dir as pinerc.
1453 * Only use it if the file exists.
1455 if(!ps->exceptions){
1456 p = last_cmpnt(ps->pinerc);
1457 buf[0] = '\0';
1458 if(p != NULL){
1459 strncpy(buf, ps->pinerc, MIN(p - ps->pinerc, sizeof(buf)-1));
1460 buf[MIN(p - ps->pinerc, sizeof(buf)-1)] = '\0';
1463 strncat(buf, "PINERCEX", sizeof(buf)-1-strlen(buf));
1465 mprint(2, (db, DSIZE-(db-(*debug_out)),
1466 " no, checking for default \"%.100s\" in pinerc dir\n", buf));
1467 if(can_access(buf, ACCESS_EXISTS) == 0) /* found it! */
1468 ps->exceptions = cpystr(buf);
1470 if(ps->exceptions){
1471 mprint(2, (db, DSIZE-(db-(*debug_out)),
1472 " yes, exceptions config \"%.100s\" comes from default\n",
1473 ps->exceptions));
1475 else{
1476 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, there is no exceptions config\n"));
1480 #else /* unix */
1482 if(ps->pconf){
1483 mprint(2, (db, DSIZE-(db-(*debug_out)), "Global config \"%.100s\" comes from command line\n",
1484 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1487 if(!ps->pconf){
1488 ps->pconf = new_pinerc_s(SYSTEM_PINERC);
1489 if(ps->pconf){
1490 mprint(2, (db, DSIZE-(db-(*debug_out)), "Global config \"%.100s\" is default\n",
1491 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1495 if(!ps->pconf){
1496 mprint(2, (db, DSIZE-(db-(*debug_out)), "No global config!\n"));
1499 if(ps->prc){
1500 mprint(2, (db, DSIZE-(db-(*debug_out)), "Personal config \"%.100s\" comes from command line\n",
1501 (ps->prc && ps->prc->name) ? ps->prc->name : "<no name>"));
1504 if(!ps->pinerc){
1505 build_path(buf, ps->home_dir, ".pinerc", sizeof(buf));
1506 ps->pinerc = cpystr(buf);
1509 if(!ps->prc){
1510 ps->prc = new_pinerc_s(ps->pinerc);
1511 if(ps->prc){
1512 mprint(2, (db, DSIZE-(db-(*debug_out)), "Personal config \"%.100s\" is default\n",
1513 (ps->prc && ps->prc->name) ? ps->prc->name : "<no name>"));
1517 if(!ps->prc){
1518 mprint(2, (db, DSIZE-(db-(*debug_out)), "No personal config!\n"));
1521 if(ps->exceptions){
1522 mprint(2, (db, DSIZE-(db-(*debug_out)),
1523 "Exceptions config \"%.100s\" comes from command line\n",
1524 ps->exceptions));
1528 * If not set, try specific file in same dir as pinerc.
1529 * Only use it if the file exists.
1531 if(!ps->exceptions){
1532 p = last_cmpnt(ps->pinerc);
1533 buf[0] = '\0';
1534 if(p != NULL){
1535 strncpy(buf, ps->pinerc, MIN(p - ps->pinerc, sizeof(buf)-1));
1536 buf[MIN(p - ps->pinerc, sizeof(buf)-1)] = '\0';
1539 strncat(buf, ".pinercex", sizeof(buf)-1-strlen(buf));
1540 mprint(2, (db, DSIZE-(db-(*debug_out)), "Exceptions config not set on cmdline\n checking for default \"%.100s\" in pinerc dir\n", buf));
1542 if(can_access(buf, ACCESS_EXISTS) == 0) /* found it! */
1543 ps->exceptions = cpystr(buf);
1545 if(ps->exceptions){
1546 mprint(2, (db, DSIZE-(db-(*debug_out)),
1547 " yes, exceptions config \"%.100s\" is default\n",
1548 ps->exceptions));
1550 else{
1551 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, there is no exceptions config\n"));
1555 #endif /* unix */
1557 if(ps->exceptions){
1559 if(!IS_REMOTE(ps->exceptions) &&
1560 !is_absolute_path(ps->exceptions)){
1561 #if defined(DOS) || defined(OS2)
1562 p = last_cmpnt(ps->pinerc);
1563 buf[0] = '\0';
1564 if(p != NULL){
1565 strncpy(buf, ps->pinerc, MIN(p - ps->pinerc, sizeof(buf)-1));
1566 buf[MIN(p - ps->pinerc, sizeof(buf)-1)] = '\0';
1569 strncat(buf, ps->exceptions, sizeof(buf)-1-strlen(buf));
1570 #else
1571 build_path(buf, ps->home_dir, ps->exceptions, sizeof(buf));
1572 #endif
1574 else{
1575 strncpy(buf, ps->exceptions, sizeof(buf)-1);
1576 buf[sizeof(buf)-1] = '\0';
1579 ps->post_prc = new_pinerc_s(buf);
1581 fs_give((void **)&ps->exceptions);
1584 mprint(2, (db, DSIZE-(db-(*debug_out)), "\n Global config: %.100s\n",
1585 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<none>"));
1586 mprint(2, (db, DSIZE-(db-(*debug_out)), " Personal config: %.100s\n",
1587 (ps->prc && ps->prc->name) ? ps->prc->name : "<none>"));
1588 mprint(2, (db, DSIZE-(db-(*debug_out)), " Exceptions config: %.100s\n",
1589 (ps->post_prc && ps->post_prc->name) ? ps->post_prc->name
1590 : "<none>"));
1591 #if !defined(DOS) && !defined(OS2)
1592 if(SYSTEM_PINERC_FIXED){
1593 mprint(2, (db, DSIZE-(db-(*debug_out)), " Fixed config: %.100s\n", SYSTEM_PINERC_FIXED));
1595 #endif
1597 mprint(2, (db, DSIZE-(db-(*debug_out)), "\n"));
1601 /*----------------------------------------------------------------------
1602 Initialize the variables
1604 Args: ps -- The usual pine structure
1606 Result:
1608 This reads the system pine configuration file and the user's pine
1609 configuration file ".pinerc" and places the results in the variables
1610 structure. It sorts out what was read and sets a few other variables
1611 based on the contents.
1612 ----*/
1613 void
1614 init_vars(struct pine *ps, void (*cmds_f) (struct pine *, char **))
1616 char buf[MAXPATH+1], *p, *q, **s, *comma_index;
1617 register struct variable *vars = ps->vars;
1618 int obs_header_in_reply = 0, /* the obs_ variables are to */
1619 obs_old_style_reply = 0, /* support backwards compatibility */
1620 obs_save_by_sender, i, def_sort_rev;
1621 long rvl;
1622 PINERC_S *fixedprc = NULL;
1623 FeatureLevel obs_feature_level;
1624 char *fromcharset = NULL;
1625 char *err = NULL;
1627 dprint((5, "init_vars:\n"));
1629 /*--- The defaults here are defined in os-xxx.h so they can vary
1630 per machine ---*/
1632 GLO_PRINTER = cpystr(DF_DEFAULT_PRINTER);
1633 GLO_ELM_STYLE_SAVE = cpystr(DF_ELM_STYLE_SAVE);
1634 GLO_ENCRYPTION_RANGE = cpystr(DF_ENCRYPTION_RANGE);
1635 GLO_SAVE_BY_SENDER = cpystr(DF_SAVE_BY_SENDER);
1636 GLO_HEADER_IN_REPLY = cpystr(DF_HEADER_IN_REPLY);
1637 GLO_INBOX_PATH = cpystr("inbox");
1638 GLO_DEFAULT_FCC = cpystr(DF_DEFAULT_FCC);
1639 GLO_DEFAULT_SAVE_FOLDER = cpystr(DEFAULT_SAVE);
1640 GLO_POSTPONED_FOLDER = cpystr(POSTPONED_MSGS);
1641 GLO_TRASH_FOLDER = cpystr(TRASH_FOLDER);
1642 GLO_USE_ONLY_DOMAIN_NAME = cpystr(DF_USE_ONLY_DOMAIN_NAME);
1643 GLO_FEATURE_LEVEL = cpystr("sappling");
1644 GLO_OLD_STYLE_REPLY = cpystr(DF_OLD_STYLE_REPLY);
1645 GLO_SORT_KEY = cpystr(DF_SORT_KEY);
1646 GLO_SAVED_MSG_NAME_RULE = cpystr(DF_SAVED_MSG_NAME_RULE);
1647 GLO_FCC_RULE = cpystr(DF_FCC_RULE);
1648 GLO_AB_SORT_RULE = cpystr(DF_AB_SORT_RULE);
1649 GLO_FLD_SORT_RULE = cpystr(DF_FLD_SORT_RULE);
1650 GLO_SIGNATURE_FILE = cpystr(DF_SIGNATURE_FILE);
1651 GLO_MAIL_DIRECTORY = cpystr(DF_MAIL_DIRECTORY);
1652 GLO_REMOTE_ABOOK_HISTORY = cpystr(DF_REMOTE_ABOOK_HISTORY);
1653 GLO_REMOTE_ABOOK_VALIDITY = cpystr(DF_REMOTE_ABOOK_VALIDITY);
1654 GLO_GOTO_DEFAULT_RULE = cpystr(DF_GOTO_DEFAULT_RULE);
1655 GLO_INCOMING_STARTUP = cpystr(DF_INCOMING_STARTUP);
1656 GLO_PRUNING_RULE = cpystr(DF_PRUNING_RULE);
1657 GLO_REOPEN_RULE = cpystr(DF_REOPEN_RULE);
1658 GLO_THREAD_DISP_STYLE = cpystr(DF_THREAD_DISP_STYLE);
1659 GLO_THREAD_INDEX_STYLE = cpystr(DF_THREAD_INDEX_STYLE);
1660 GLO_THREAD_MORE_CHAR = cpystr(DF_THREAD_MORE_CHAR);
1661 GLO_THREAD_EXP_CHAR = cpystr(DF_THREAD_EXP_CHAR);
1662 GLO_THREAD_LASTREPLY_CHAR = cpystr(DF_THREAD_LASTREPLY_CHAR);
1663 GLO_BUGS_FULLNAME = cpystr("Sorry No Address");
1664 GLO_BUGS_ADDRESS = cpystr("nobody");
1665 GLO_SUGGEST_FULLNAME = cpystr("Sorry No Address");
1666 GLO_SUGGEST_ADDRESS = cpystr("nobody");
1667 GLO_LOCAL_FULLNAME = cpystr(DF_LOCAL_FULLNAME);
1668 GLO_LOCAL_ADDRESS = cpystr(DF_LOCAL_ADDRESS);
1669 GLO_OVERLAP = cpystr(DF_OVERLAP);
1670 GLO_MAXREMSTREAM = cpystr(DF_MAXREMSTREAM);
1671 GLO_MARGIN = cpystr(DF_MARGIN);
1672 GLO_FILLCOL = cpystr(DF_FILLCOL);
1673 GLO_DEADLETS = cpystr(DF_DEADLETS);
1674 GLO_NMW_WIDTH = cpystr(DF_NMW_WIDTH);
1675 GLO_REPLY_STRING = cpystr("> ");
1676 GLO_REPLY_INTRO = cpystr(DEFAULT_REPLY_INTRO);
1677 GLO_EMPTY_HDR_MSG = cpystr("undisclosed-recipients");
1678 GLO_STATUS_MSG_DELAY = cpystr("0");
1679 GLO_ACTIVE_MSG_INTERVAL = cpystr("12");
1680 GLO_USERINPUTTIMEO = cpystr("0");
1681 GLO_INCCHECKTIMEO = cpystr("5");
1682 GLO_INCCHECKINTERVAL = cpystr("180");
1683 GLO_INC2NDCHECKINTERVAL = cpystr("180");
1684 GLO_MAILCHECK = cpystr(DF_MAILCHECK);
1685 GLO_MAILCHECKNONCURR = cpystr("0");
1686 GLO_MAILDROPCHECK = cpystr(DF_MAILDROPCHECK);
1687 GLO_NNTPRANGE = cpystr("0");
1688 GLO_KBLOCK_PASSWD_COUNT = cpystr(DF_KBLOCK_PASSWD_COUNT);
1689 GLO_INDEX_COLOR_STYLE = cpystr("flip-colors");
1690 GLO_TITLEBAR_COLOR_STYLE = cpystr("default");
1691 GLO_POST_CHAR_SET = cpystr("UTF-8");
1692 #ifdef DF_FOLDER_EXTENSION
1693 GLO_FOLDER_EXTENSION = cpystr(DF_FOLDER_EXTENSION);
1694 #endif
1695 #ifdef DF_SMTP_SERVER
1696 GLO_SMTP_SERVER = parse_list(DF_SMTP_SERVER, 1,
1697 PL_REMSURRQUOT, NULL);
1698 #endif
1700 #ifdef DF_SSHPATH
1701 GLO_SSHPATH = cpystr(DF_SSHPATH);
1702 #endif
1703 #ifdef DF_SSHCMD
1704 GLO_SSHCMD = cpystr(DF_SSHCMD);
1705 #endif
1707 #ifndef _WINDOWS
1708 GLO_COLOR_STYLE = cpystr("no-color");
1709 GLO_NORM_FORE_COLOR = cpystr(DEFAULT_NORM_FORE_RGB);
1710 GLO_NORM_BACK_COLOR = cpystr(DEFAULT_NORM_BACK_RGB);
1711 #endif
1712 GLO_TITLE_FORE_COLOR = cpystr(DEFAULT_TITLE_FORE_RGB);
1713 GLO_TITLE_BACK_COLOR = cpystr(DEFAULT_TITLE_BACK_RGB);
1714 GLO_TITLECLOSED_FORE_COLOR = cpystr(DEFAULT_TITLECLOSED_FORE_RGB);
1715 GLO_TITLECLOSED_BACK_COLOR = cpystr(DEFAULT_TITLECLOSED_BACK_RGB);
1716 GLO_FOLDER_FORE_COLOR = cpystr(DEFAULT_NORM_FORE_RGB);
1717 GLO_DIRECTORY_FORE_COLOR = cpystr(DEFAULT_NORM_FORE_RGB);
1718 GLO_FOLDER_LIST_FORE_COLOR = cpystr(DEFAULT_NORM_FORE_RGB);
1719 GLO_METAMSG_FORE_COLOR = cpystr(DEFAULT_METAMSG_FORE_RGB);
1720 GLO_METAMSG_BACK_COLOR = cpystr(DEFAULT_METAMSG_BACK_RGB);
1721 GLO_QUOTE1_FORE_COLOR = cpystr(DEFAULT_QUOTE1_FORE_RGB);
1722 GLO_QUOTE1_BACK_COLOR = cpystr(DEFAULT_QUOTE1_BACK_RGB);
1723 GLO_QUOTE2_FORE_COLOR = cpystr(DEFAULT_QUOTE2_FORE_RGB);
1724 GLO_QUOTE2_BACK_COLOR = cpystr(DEFAULT_QUOTE2_BACK_RGB);
1725 GLO_QUOTE3_FORE_COLOR = cpystr(DEFAULT_QUOTE3_FORE_RGB);
1726 GLO_QUOTE3_BACK_COLOR = cpystr(DEFAULT_QUOTE3_BACK_RGB);
1727 GLO_SIGNATURE_FORE_COLOR = cpystr(DEFAULT_SIGNATURE_FORE_RGB);
1728 GLO_SIGNATURE_BACK_COLOR = cpystr(DEFAULT_SIGNATURE_BACK_RGB);
1729 GLO_IND_PLUS_FORE_COLOR = cpystr(DEFAULT_IND_PLUS_FORE_RGB);
1730 GLO_IND_PLUS_BACK_COLOR = cpystr(DEFAULT_IND_PLUS_BACK_RGB);
1731 GLO_IND_IMP_FORE_COLOR = cpystr(DEFAULT_IND_IMP_FORE_RGB);
1732 GLO_IND_IMP_BACK_COLOR = cpystr(DEFAULT_IND_IMP_BACK_RGB);
1733 GLO_IND_ANS_FORE_COLOR = cpystr(DEFAULT_IND_ANS_FORE_RGB);
1734 GLO_IND_ANS_BACK_COLOR = cpystr(DEFAULT_IND_ANS_BACK_RGB);
1735 GLO_IND_NEW_FORE_COLOR = cpystr(DEFAULT_IND_NEW_FORE_RGB);
1736 GLO_IND_NEW_BACK_COLOR = cpystr(DEFAULT_IND_NEW_BACK_RGB);
1737 GLO_IND_OP_FORE_COLOR = cpystr(DEFAULT_IND_OP_FORE_RGB);
1738 GLO_IND_OP_BACK_COLOR = cpystr(DEFAULT_IND_OP_BACK_RGB);
1739 GLO_VIEW_MARGIN_LEFT = cpystr("0");
1740 GLO_VIEW_MARGIN_RIGHT = cpystr(DF_VIEW_MARGIN_RIGHT);
1741 GLO_QUOTE_SUPPRESSION = cpystr(DF_QUOTE_SUPPRESSION);
1742 GLO_KW_BRACES = cpystr("\"{\" \"} \"");
1743 GLO_OPENING_SEP = cpystr(" - ");
1744 GLO_WP_INDEXHEIGHT = cpystr("24");
1745 GLO_WP_AGGSTATE = cpystr("1");
1746 GLO_WP_STATE = cpystr("");
1747 #ifdef DEFAULT_SSLCAPATH
1748 GLO_SSLCAPATH = parse_list(DEFAULT_SSLCAPATH, 1,
1749 PL_REMSURRQUOT, NULL);
1750 #endif /* DEFAULT_SSLCAPATH */
1751 #ifdef DEFAULT_SSLCAFILE
1752 GLO_SSLCAFILE = parse_list(DEFAULT_SSLCAFILE, 1,
1753 PL_REMSURRQUOT, NULL);
1754 #endif /* DEFAULT_SSLCAFILE */
1755 #ifdef DEFAULT_SSLUSERCAPATH
1756 { char **l, path[MAXPATH+1];
1757 int i;
1758 l = parse_list(DEFAULT_SSLUSERCAPATH, 1,
1759 PL_REMSURRQUOT, NULL);
1760 if(l && *l && **l){
1761 for(i = 0; l[i] && *l[i]; i++){
1762 path[0] = '\0';
1763 if(ps_global->VAR_OPER_DIR){
1764 if(strlen(ps_global->VAR_OPER_DIR) + strlen(l[i]) < MAXPATH)
1765 build_path(path, ps_global->VAR_OPER_DIR, l[i], MAXPATH);
1767 else if(ps_global->home_dir){
1768 if(strlen(ps_global->home_dir) + strlen(l[i]) < MAXPATH)
1769 build_path(path, ps_global->home_dir, l[i], MAXPATH);
1771 if(path[0]){
1772 fs_give((void **) &l[i]);
1773 l[i] = cpystr(path);
1777 GLO_SSLUSERCAPATH = l;
1779 #endif /* DEFAULT_SSLUSERCAPATH */
1780 #ifdef DEFAULT_SSLUSERCAFILE
1781 { char **l, path[MAXPATH+1];
1782 int i;
1783 l = parse_list(DEFAULT_SSLUSERCAFILE, 1,
1784 PL_REMSURRQUOT, NULL);
1785 if(l && *l && **l){
1786 for(i = 0; l[i] && *l[i]; i++){
1787 path[0] = '\0';
1788 if(ps_global->VAR_OPER_DIR){
1789 if(strlen(ps_global->VAR_OPER_DIR) + strlen(l[i]) < MAXPATH)
1790 build_path(path, ps_global->VAR_OPER_DIR, l[i], MAXPATH);
1792 else if(ps_global->home_dir){
1793 if(strlen(ps_global->home_dir) + strlen(l[i]) < MAXPATH)
1794 build_path(path, ps_global->home_dir, l[i], MAXPATH);
1796 if(path[0]){
1797 fs_give((void **) &l[i]);
1798 l[i] = cpystr(path);
1802 GLO_SSLUSERCAFILE = l;
1804 #endif /* DEFAULT_SSLUSERCAFILE */
1805 #ifdef DF_VAR_SPELLER
1806 GLO_SPELLER = cpystr(DF_VAR_SPELLER);
1807 #endif
1808 GLO_HTML_DIRECTORY = cpystr(DF_HTML_DIRECTORY);
1809 #ifdef SMIME
1810 if(ps->smimedir){
1811 snprintf(tmp_20k_buf, SIZEOF_20KBUF, "%s/public", ps->smimedir);
1812 tmp_20k_buf[SIZEOF_20KBUF-1] = '\0';
1813 GLO_PUBLICCERT_DIR = cpystr(tmp_20k_buf);
1815 snprintf(tmp_20k_buf, SIZEOF_20KBUF, "%s/private", ps->smimedir);
1816 tmp_20k_buf[SIZEOF_20KBUF-1] = '\0';
1817 GLO_PRIVATEKEY_DIR = cpystr(tmp_20k_buf);
1819 snprintf(tmp_20k_buf, SIZEOF_20KBUF, "%s/ca", ps->smimedir);
1820 tmp_20k_buf[SIZEOF_20KBUF-1] = '\0';
1821 GLO_CACERT_DIR = cpystr(tmp_20k_buf);
1823 else{
1824 GLO_PUBLICCERT_DIR = cpystr(DF_PUBLICCERT_DIR);
1825 GLO_PRIVATEKEY_DIR = cpystr(DF_PRIVATEKEY_DIR);
1826 GLO_CACERT_DIR = cpystr(DF_CACERT_DIR);
1828 #endif /* SMIME */
1831 * Default first value for addrbook list if none set.
1832 * We also want to be sure to set global_val to the default
1833 * if is_fixed, so that address-book= will cause the default to happen.
1835 if(!GLO_ADDRESSBOOK && !FIX_ADDRESSBOOK)
1836 GLO_ADDRESSBOOK = parse_list(DF_ADDRESSBOOK, 1, 0, NULL);
1839 * Default first value if none set.
1841 if(!GLO_STANDARD_PRINTER && !FIX_STANDARD_PRINTER)
1842 GLO_STANDARD_PRINTER = parse_list(DF_STANDARD_PRINTER, 1, 0, NULL);
1845 * Defining this default sshpath should cause ssh to be preferred over rsh
1846 * when attempting imapd preauth calls.
1848 #ifdef DF_SSHPATH
1849 if(DF_SSHPATH
1850 && is_absolute_path(DF_SSHPATH)
1851 && can_access(DF_SSHPATH, EXECUTE_ACCESS) == 0){
1852 mail_parameters(NULL, SET_SSHPATH, (void *) DF_SSHPATH);
1854 #endif
1856 * It isn't usually necessary to define this.
1858 #ifdef DF_SSHCMD
1859 if(DF_SSHCMD){
1860 mail_parameters(NULL, SET_SSHCOMMAND, (void *) DF_SSHCMD);
1862 #endif
1864 #if !defined(DOS) && !defined(OS2)
1866 * This is here instead of in init_pinerc so that we can get by without
1867 * having a global fixedprc, since we don't need it anymore after this.
1869 fixedprc = new_pinerc_s(SYSTEM_PINERC_FIXED);
1870 #endif
1872 if(ps->pconf){
1873 read_pinerc(ps->pconf, vars, ParseGlobal);
1874 if(ps->pconf->type != Loc)
1875 rd_close_remote(ps->pconf->rd);
1878 if(ps->prc){
1879 read_pinerc(ps->prc, vars, ParsePers);
1880 if(ps->prc->type != Loc)
1881 rd_close_remote(ps->prc->rd);
1884 if(ps->post_prc){
1885 read_pinerc(ps->post_prc, vars, ParsePersPost);
1886 if(ps->post_prc->type != Loc)
1887 rd_close_remote(ps->post_prc->rd);
1890 if(fixedprc){
1891 read_pinerc(fixedprc, vars, ParseFixed);
1892 free_pinerc_s(&fixedprc);
1895 ps->ew_for_except_vars = ps->post_prc ? Post : Main;
1897 if(ps->exit_if_no_pinerc && ps->first_time_user){
1899 /* TRANSLATORS: -bail is a literal option name, don't change it. */
1900 exceptional_exit(_("Exiting because -bail option is set and config file doesn't exist."), -1);
1904 * Convert everything having to do with the config to UTF-8
1905 * in order to avoid having to worry about it all over the
1906 * place.
1907 * Set the character-set first so that we may use that in
1908 * the conversion process.
1910 set_collation(0, 1);
1912 #ifndef _WINDOWS
1913 #if (HAVE_LANGINFO_H && defined(CODESET))
1915 if(output_charset_is_supported(nl_langinfo_codeset_wrapper()))
1916 ps->GLO_CHAR_SET = cpystr(nl_langinfo_codeset_wrapper());
1917 else{
1918 ps->GLO_CHAR_SET = cpystr("UTF-8");
1919 dprint((1,"nl_langinfo(CODESET) returns unrecognized value=\"%s\", using UTF-8 as default\n", (p=nl_langinfo(CODESET)) ? p : ""));
1921 #else
1922 ps->GLO_CHAR_SET = cpystr("UTF-8");
1923 #endif
1925 set_current_val(&vars[V_CHAR_SET], TRUE, TRUE);
1926 set_current_val(&vars[V_OLD_CHAR_SET], TRUE, TRUE);
1927 set_current_val(&vars[V_KEY_CHAR_SET], TRUE, TRUE);
1928 #endif /* ! _WINDOWS */
1930 set_current_val(&vars[V_POST_CHAR_SET], TRUE, TRUE);
1933 * Also set up the feature list because we need the
1934 * Use-System-Translation feature to set up the charmaps.
1937 /* way obsolete, backwards compatibility */
1938 set_current_val(&vars[V_FEATURE_LEVEL], TRUE, TRUE);
1939 if(strucmp(VAR_FEATURE_LEVEL, "seedling") == 0)
1940 obs_feature_level = Seedling;
1941 else if(strucmp(VAR_FEATURE_LEVEL, "old-growth") == 0)
1942 obs_feature_level = Seasoned;
1943 else
1944 obs_feature_level = Sapling;
1946 /* obsolete, backwards compatibility */
1947 set_current_val(&vars[V_OLD_STYLE_REPLY], TRUE, TRUE);
1948 obs_old_style_reply = !strucmp(VAR_OLD_STYLE_REPLY, "yes");
1950 set_feature_list_current_val(&vars[V_FEATURE_LIST]);
1951 process_feature_list(ps, VAR_FEATURE_LIST,
1952 (obs_feature_level == Seasoned) ? 1 : 0,
1953 obs_header_in_reply, obs_old_style_reply);
1957 * Redo set_collation call with correct value for collation,
1958 * but we're hardwiring ctype on now. That's because nl_langinfo()
1959 * call needs it and system-dependent wcwidth and wcrtomb functions
1960 * need it.
1962 set_collation(F_OFF(F_DISABLE_SETLOCALE_COLLATE, ps_global), 1);
1965 * Set up to send the correct sequence of bytes to the display terminal.
1968 if(reset_character_set_stuff(&err) == -1)
1969 alpine_panic(err ? err : "trouble with character set setup");
1970 else if(err){
1971 init_error(ps, SM_ORDER | SM_DING, 3, 5, err);
1972 fs_give((void **) &err);
1976 * Now we use the configvars from above to convert the rest
1977 * to UTF-8. That should be ok because the ones above should
1978 * be ASCII.
1980 if(ps->keyboard_charmap && strucmp(ps->keyboard_charmap, "UTF-8")
1981 && strucmp(ps->keyboard_charmap, "US-ASCII"))
1982 fromcharset = ps->keyboard_charmap;
1983 else if(ps->display_charmap && strucmp(ps->display_charmap, "UTF-8")
1984 && strucmp(ps->display_charmap, "US-ASCII"))
1985 fromcharset = ps->display_charmap;
1986 #ifndef _WINDOWS
1987 else if(VAR_OLD_CHAR_SET && strucmp(VAR_OLD_CHAR_SET, "UTF-8")
1988 && strucmp(VAR_OLD_CHAR_SET, "US-ASCII"))
1989 fromcharset = VAR_OLD_CHAR_SET;
1990 #endif /* ! _WINDOWS */
1992 convert_configvars_to_utf8(vars, fromcharset);
1995 * If we already set this while reading the remote pinerc, don't
1996 * change it.
1998 if(!VAR_REMOTE_ABOOK_METADATA || !VAR_REMOTE_ABOOK_METADATA[0])
1999 set_current_val(&vars[V_REMOTE_ABOOK_METADATA], TRUE, TRUE);
2002 * mail-directory variable is obsolete, put its value in
2003 * default folder-collection list
2005 set_current_val(&vars[V_MAIL_DIRECTORY], TRUE, TRUE);
2006 if(!GLO_FOLDER_SPEC){
2007 build_path(tmp_20k_buf, VAR_MAIL_DIRECTORY, "[]", SIZEOF_20KBUF);
2008 GLO_FOLDER_SPEC = parse_list(tmp_20k_buf, 1, 0, NULL);
2011 set_current_val(&vars[V_FOLDER_SPEC], TRUE, TRUE);
2013 set_current_val(&vars[V_NNTP_SERVER], TRUE, TRUE);
2014 for(i = 0; VAR_NNTP_SERVER && VAR_NNTP_SERVER[i]; i++)
2015 removing_quotes(VAR_NNTP_SERVER[i]);
2017 set_news_spec_current_val(TRUE, TRUE);
2019 set_current_val(&vars[V_INBOX_PATH], TRUE, TRUE);
2021 set_current_val(&vars[V_USER_DOMAIN], TRUE, TRUE);
2022 if(VAR_USER_DOMAIN
2023 && VAR_USER_DOMAIN[0]
2024 && (p = strrindex(VAR_USER_DOMAIN, '@'))){
2025 if(*(++p)){
2026 char *q;
2028 snprintf(tmp_20k_buf, SIZEOF_20KBUF,
2029 "User-domain (%s) cannot contain \"@\", using \"%s\"",
2030 VAR_USER_DOMAIN, p);
2031 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2032 q = VAR_USER_DOMAIN;
2033 while((*q++ = *p++) != '\0')
2034 ;/* do nothing */
2036 else{
2037 snprintf(tmp_20k_buf, SIZEOF_20KBUF,
2038 "User-domain (%s) cannot contain \"@\", deleting",
2039 VAR_USER_DOMAIN);
2040 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2041 if(ps->vars[V_USER_DOMAIN].post_user_val.p){
2042 fs_give((void **)&ps->vars[V_USER_DOMAIN].post_user_val.p);
2043 set_current_val(&vars[V_USER_DOMAIN], TRUE, TRUE);
2046 if(VAR_USER_DOMAIN
2047 && VAR_USER_DOMAIN[0]
2048 && (p = strrindex(VAR_USER_DOMAIN, '@'))){
2049 if(ps->vars[V_USER_DOMAIN].main_user_val.p){
2050 fs_give((void **)&ps->vars[V_USER_DOMAIN].main_user_val.p);
2051 set_current_val(&vars[V_USER_DOMAIN], TRUE, TRUE);
2057 set_current_val(&vars[V_USE_ONLY_DOMAIN_NAME], TRUE, TRUE);
2058 set_current_val(&vars[V_REPLY_STRING], TRUE, TRUE);
2059 set_current_val(&vars[V_WORDSEPS], TRUE, TRUE);
2060 set_current_val(&vars[V_QUOTE_REPLACE_STRING], TRUE, TRUE);
2061 set_current_val(&vars[V_REPLY_INTRO], TRUE, TRUE);
2062 set_current_val(&vars[V_EMPTY_HDR_MSG], TRUE, TRUE);
2064 #ifdef ENABLE_LDAP
2065 set_current_val(&vars[V_LDAP_SERVERS], TRUE, TRUE);
2066 #endif /* ENABLE_LDAP */
2068 /* obsolete, backwards compatibility */
2069 set_current_val(&vars[V_HEADER_IN_REPLY], TRUE, TRUE);
2070 obs_header_in_reply=!strucmp(VAR_HEADER_IN_REPLY, "yes");
2072 set_current_val(&vars[V_PERSONAL_PRINT_COMMAND], TRUE, TRUE);
2073 set_current_val(&vars[V_STANDARD_PRINTER], TRUE, TRUE);
2074 set_current_val(&vars[V_PRINTER], TRUE, TRUE);
2075 if(vars[V_PERSONAL_PRINT_COMMAND].is_fixed && !vars[V_PRINTER].is_fixed)
2076 printer_value_check_and_adjust();
2078 set_current_val(&vars[V_LAST_TIME_PRUNE_QUESTION], TRUE, TRUE);
2079 if(VAR_LAST_TIME_PRUNE_QUESTION != NULL &&
2080 (comma_index = strindex(VAR_LAST_TIME_PRUNE_QUESTION, '.')) != NULL){
2081 /* The month value in the file runs from 1-12, the variable here
2082 runs from 0-11; the value in the file used to be 0-11, but we're
2083 fixing it in January */
2084 ps->last_expire_year = atoi(VAR_LAST_TIME_PRUNE_QUESTION);
2085 ps->last_expire_month = atoi(comma_index + 1);
2086 if(ps->last_expire_month == 0){
2087 /* Fix for 0 because of old bug */
2088 snprintf(buf, sizeof(buf), "%d.%d", ps_global->last_expire_year,
2089 ps_global->last_expire_month + 1);
2090 set_variable(V_LAST_TIME_PRUNE_QUESTION, buf, 1, 1, Main);
2091 }else{
2092 ps->last_expire_month--;
2094 }else{
2095 ps->last_expire_year = -1;
2096 ps->last_expire_month = -1;
2099 set_current_val(&vars[V_BUGS_FULLNAME], TRUE, TRUE);
2100 set_current_val(&vars[V_BUGS_ADDRESS], TRUE, TRUE);
2101 set_current_val(&vars[V_SUGGEST_FULLNAME], TRUE, TRUE);
2102 set_current_val(&vars[V_SUGGEST_ADDRESS], TRUE, TRUE);
2103 set_current_val(&vars[V_LOCAL_FULLNAME], TRUE, TRUE);
2104 set_current_val(&vars[V_LOCAL_ADDRESS], TRUE, TRUE);
2105 set_current_val(&vars[V_BUGS_EXTRAS], TRUE, TRUE);
2106 set_current_val(&vars[V_KBLOCK_PASSWD_COUNT], TRUE, TRUE);
2107 set_current_val(&vars[V_DEFAULT_FCC], TRUE, TRUE);
2108 set_current_val(&vars[V_POSTPONED_FOLDER], TRUE, TRUE);
2109 set_current_val(&vars[V_TRASH_FOLDER], TRUE, TRUE);
2110 set_current_val(&vars[V_READ_MESSAGE_FOLDER], TRUE, TRUE);
2111 set_current_val(&vars[V_FORM_FOLDER], TRUE, TRUE);
2112 set_current_val(&vars[V_EDITOR], TRUE, TRUE);
2113 set_current_val(&vars[V_SPELLER], TRUE, TRUE);
2114 #ifdef _WINDOWS
2115 set_current_val(&vars[V_DICTIONARY], TRUE, TRUE);
2116 #endif /* _WINDOWS */
2117 set_current_val(&vars[V_IMAGE_VIEWER], TRUE, TRUE);
2118 set_current_val(&vars[V_BROWSER], TRUE, TRUE);
2119 set_current_val(&vars[V_HISTORY], TRUE, TRUE);
2120 set_current_val(&vars[V_SMTP_SERVER], TRUE, TRUE);
2121 set_current_val(&vars[V_COMP_HDRS], TRUE, TRUE);
2122 set_current_val(&vars[V_CUSTOM_HDRS], TRUE, TRUE);
2123 set_current_val(&vars[V_SENDMAIL_PATH], TRUE, TRUE);
2124 set_current_val(&vars[V_DISPLAY_FILTERS], TRUE, TRUE);
2125 set_current_val(&vars[V_SEND_FILTER], TRUE, TRUE);
2126 set_current_val(&vars[V_ALT_ADDRS], TRUE, TRUE);
2127 set_current_val(&vars[V_ABOOK_FORMATS], TRUE, TRUE);
2128 set_current_val(&vars[V_KW_BRACES], TRUE, TRUE);
2129 set_current_val(&vars[V_OPENING_SEP], TRUE, TRUE);
2130 set_current_val(&vars[V_UNK_CHAR_SET], TRUE, TRUE);
2131 #ifdef SMIME
2132 set_current_val(&vars[V_PUBLICCERT_DIR], TRUE, TRUE);
2133 set_current_val(&vars[V_PUBLICCERT_CONTAINER], TRUE, TRUE);
2134 set_current_val(&vars[V_PRIVATEKEY_DIR], TRUE, TRUE);
2135 set_current_val(&vars[V_PRIVATEKEY_CONTAINER], TRUE, TRUE);
2136 set_current_val(&vars[V_CACERT_DIR], TRUE, TRUE);
2137 set_current_val(&vars[V_CACERT_CONTAINER], TRUE, TRUE);
2138 #endif /* SMIME */
2140 set_current_val(&vars[V_KEYWORDS], TRUE, TRUE);
2141 ps_global->keywords = init_keyword_list(VAR_KEYWORDS);
2143 set_current_val(&vars[V_OPER_DIR], TRUE, TRUE);
2144 if(VAR_OPER_DIR && !VAR_OPER_DIR[0]){
2145 init_error(ps, SM_ORDER | SM_DING, 3, 5,
2146 "Setting operating-dir to the empty string is not allowed. Will be ignored.");
2147 fs_give((void **)&VAR_OPER_DIR);
2148 if(FIX_OPER_DIR)
2149 fs_give((void **)&FIX_OPER_DIR);
2150 if(GLO_OPER_DIR)
2151 fs_give((void **)&GLO_OPER_DIR);
2152 if(COM_OPER_DIR)
2153 fs_give((void **)&COM_OPER_DIR);
2154 if(ps_global->vars[V_OPER_DIR].post_user_val.p)
2155 fs_give((void **)&ps_global->vars[V_OPER_DIR].post_user_val.p);
2156 if(ps_global->vars[V_OPER_DIR].main_user_val.p)
2157 fs_give((void **)&ps_global->vars[V_OPER_DIR].main_user_val.p);
2160 set_current_val(&vars[V_HTML_DIRECTORY], TRUE, TRUE);
2161 set_current_val(&vars[V_PERSONAL_PRINT_CATEGORY], TRUE, TRUE);
2162 ps->printer_category = -1;
2163 if(VAR_PERSONAL_PRINT_CATEGORY != NULL)
2164 ps->printer_category = atoi(VAR_PERSONAL_PRINT_CATEGORY);
2166 if(ps->printer_category < 1 || ps->printer_category > 3){
2167 char **tt;
2168 char aname[100], wname[100];
2170 strncpy(aname, ANSI_PRINTER, sizeof(aname));
2171 aname[sizeof(aname)-1] = '\0';
2172 strncat(aname, "-no-formfeed", sizeof(aname)-strlen(aname)-1);
2173 strncpy(wname, WYSE_PRINTER, sizeof(wname));
2174 wname[sizeof(wname)-1] = '\0';
2175 strncat(wname, "-no-formfeed", sizeof(wname)-strlen(wname)-1);
2176 if(strucmp(VAR_PRINTER, ANSI_PRINTER) == 0
2177 || strucmp(VAR_PRINTER, aname) == 0
2178 || strucmp(VAR_PRINTER, WYSE_PRINTER) == 0
2179 || strucmp(VAR_PRINTER, wname) == 0)
2180 ps->printer_category = 1;
2181 else if(VAR_STANDARD_PRINTER && VAR_STANDARD_PRINTER[0]){
2182 for(tt = VAR_STANDARD_PRINTER; *tt; tt++)
2183 if(strucmp(VAR_PRINTER, *tt) == 0)
2184 break;
2186 if(*tt)
2187 ps->printer_category = 2;
2190 /* didn't find it yet */
2191 if(ps->printer_category < 1 || ps->printer_category > 3){
2192 if(VAR_PERSONAL_PRINT_COMMAND && VAR_PERSONAL_PRINT_COMMAND[0]){
2193 for(tt = VAR_PERSONAL_PRINT_COMMAND; *tt; tt++)
2194 if(strucmp(VAR_PRINTER, *tt) == 0)
2195 break;
2197 if(*tt)
2198 ps->printer_category = 3;
2203 set_current_val(&vars[V_OVERLAP], TRUE, TRUE);
2204 ps->viewer_overlap = i = atoi(DF_OVERLAP);
2205 if(SVAR_OVERLAP(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2206 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2207 else
2208 ps->viewer_overlap = i;
2210 set_current_val(&vars[V_MARGIN], TRUE, TRUE);
2211 ps->scroll_margin = i = atoi(DF_MARGIN);
2212 if(SVAR_MARGIN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2213 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2214 else
2215 ps->scroll_margin = i;
2217 set_current_val(&vars[V_FILLCOL], TRUE, TRUE);
2218 ps->composer_fillcol = i = atoi(DF_FILLCOL);
2219 if(SVAR_FILLCOL(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2220 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2221 else
2222 ps->composer_fillcol = i;
2224 set_current_val(&vars[V_QUOTE_SUPPRESSION], TRUE, TRUE);
2225 ps->quote_suppression_threshold = i = atoi(DF_QUOTE_SUPPRESSION);
2226 if(SVAR_QUOTE_SUPPRESSION(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2227 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2228 else{
2229 if(i > 0 && i < Q_SUPP_LIMIT){
2230 snprintf(tmp_20k_buf, SIZEOF_20KBUF,
2231 "Ignoring Quote-Suppression-Threshold value of %.50s, see help",
2232 VAR_QUOTE_SUPPRESSION);
2233 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2235 else{
2236 if(i < 0 && i != Q_DEL_ALL)
2237 ps->quote_suppression_threshold = -i;
2238 else
2239 ps->quote_suppression_threshold = i;
2243 set_current_val(&vars[V_DEADLETS], TRUE, TRUE);
2244 ps->deadlets = i = atoi(DF_DEADLETS);
2245 if(SVAR_DEADLETS(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2246 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2247 else
2248 ps->deadlets = i;
2250 set_current_val(&vars[V_STATUS_MSG_DELAY], TRUE, TRUE);
2251 ps->status_msg_delay = i = 0;
2252 if(SVAR_MSGDLAY(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2253 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2254 else
2255 ps->status_msg_delay = i;
2257 set_current_val(&vars[V_ACTIVE_MSG_INTERVAL], TRUE, TRUE);
2258 ps->active_status_interval = i = 8;
2259 if(SVAR_ACTIVEINTERVAL(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2260 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2261 else
2262 ps->active_status_interval = i;
2264 set_current_val(&vars[V_REMOTE_ABOOK_HISTORY], TRUE, TRUE);
2265 ps->remote_abook_history = i = atoi(DF_REMOTE_ABOOK_HISTORY);
2266 if(SVAR_AB_HIST(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2267 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2268 else
2269 ps->remote_abook_history = i;
2271 set_current_val(&vars[V_REMOTE_ABOOK_VALIDITY], TRUE, TRUE);
2272 ps->remote_abook_validity = i = atoi(DF_REMOTE_ABOOK_VALIDITY);
2273 if(SVAR_AB_VALID(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2274 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2275 else
2276 ps->remote_abook_validity = i;
2278 set_current_val(&vars[V_USERINPUTTIMEO], TRUE, TRUE);
2279 ps->hours_to_timeout = i = 0;
2280 if(SVAR_USER_INPUT(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2281 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2282 else
2283 ps->hours_to_timeout = i;
2285 /* timeo is a regular extern int because it is referenced in pico */
2286 set_current_val(&vars[V_MAILCHECK], TRUE, TRUE);
2287 set_input_timeout(i = 15);
2288 if(SVAR_MAILCHK(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2289 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2290 else
2291 set_input_timeout(i);
2293 set_current_val(&vars[V_MAILCHECKNONCURR], TRUE, TRUE);
2294 ps->check_interval_for_noncurr = i = 0;
2295 if(SVAR_MAILCHKNONCURR(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2296 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2297 else
2298 ps->check_interval_for_noncurr = i;
2300 #ifdef DEBUGJOURNAL
2301 ps->debugmem = 1;
2302 #else
2303 ps->debugmem = 0;
2304 #endif
2306 i = 30;
2307 set_current_val(&vars[V_TCPOPENTIMEO], TRUE, TRUE);
2308 /* this is just for the error, we don't save the result */
2309 if(VAR_TCPOPENTIMEO && SVAR_TCP_OPEN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2310 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2312 i = 15;
2313 set_current_val(&vars[V_TCPREADWARNTIMEO], TRUE, TRUE);
2314 /* this is just for the error, we don't save the result */
2315 if(VAR_TCPREADWARNTIMEO && SVAR_TCP_READWARN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2316 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2318 i = 0;
2319 set_current_val(&vars[V_TCPWRITEWARNTIMEO], TRUE, TRUE);
2320 /* this is just for the error, we don't save the result */
2321 if(VAR_TCPWRITEWARNTIMEO && SVAR_TCP_WRITEWARN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2322 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2324 i = 15;
2325 set_current_val(&vars[V_RSHOPENTIMEO], TRUE, TRUE);
2326 /* this is just for the error, we don't save the result */
2327 if(VAR_RSHOPENTIMEO && SVAR_RSH_OPEN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2328 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2330 i = 15;
2331 set_current_val(&vars[V_SSHOPENTIMEO], TRUE, TRUE);
2332 /* this is just for the error, we don't save the result */
2333 if(VAR_SSHOPENTIMEO && SVAR_SSH_OPEN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2334 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2336 set_current_val(&vars[V_INCCHECKLIST], TRUE, TRUE);
2338 set_current_val(&vars[V_INCCHECKTIMEO], TRUE, TRUE);
2339 ps->inc_check_timeout = i = 5;
2340 if(SVAR_INC_CHECK_TIMEO(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2341 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2342 else
2343 ps->inc_check_timeout = i;
2345 set_current_val(&vars[V_INCCHECKINTERVAL], TRUE, TRUE);
2346 ps->inc_check_interval = i = 180;
2347 if(SVAR_INC_CHECK_INTERV(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2348 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2349 else
2350 ps->inc_check_interval = i;
2352 set_current_val(&vars[V_INC2NDCHECKINTERVAL], TRUE, TRUE);
2353 ps->inc_second_check_interval = i = 180;
2354 if(SVAR_INC_2NDCHECK_INTERV(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2355 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2356 else
2357 ps->inc_second_check_interval = i;
2359 rvl = 60L;
2360 set_current_val(&vars[V_MAILDROPCHECK], TRUE, TRUE);
2361 /* this is just for the error, we don't save the result */
2362 if(VAR_MAILDROPCHECK && SVAR_MAILDCHK(ps, rvl, tmp_20k_buf, SIZEOF_20KBUF))
2363 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2365 rvl = 0L;
2366 set_current_val(&vars[V_NNTPRANGE], TRUE, TRUE);
2367 /* this is just for the error, we don't save the result */
2368 if(VAR_NNTPRANGE && SVAR_NNTPRANGE(ps, rvl, tmp_20k_buf, SIZEOF_20KBUF))
2369 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2371 set_current_val(&vars[V_TCPQUERYTIMEO], TRUE, TRUE);
2372 ps->tcp_query_timeout = i = TO_BAIL_THRESHOLD;
2373 if(VAR_TCPQUERYTIMEO && SVAR_TCP_QUERY(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2374 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2375 else
2376 ps->tcp_query_timeout = i;
2378 set_current_val(&vars[V_QUITQUERYTIMEO], TRUE, TRUE);
2379 ps->close_connection_timeout = i = 0;
2380 if(VAR_QUITQUERYTIMEO && SVAR_QUIT_QUERY_TIMEO(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2381 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2382 else
2383 ps->close_connection_timeout = i;
2385 set_current_val(&vars[V_NEWSRC_PATH], TRUE, TRUE);
2386 if(VAR_NEWSRC_PATH && VAR_NEWSRC_PATH[0])
2387 mail_parameters(NULL, SET_NEWSRC, (void *)VAR_NEWSRC_PATH);
2389 set_current_val(&vars[V_NEWS_ACTIVE_PATH], TRUE, TRUE);
2390 if(VAR_NEWS_ACTIVE_PATH)
2391 mail_parameters(NULL, SET_NEWSACTIVE,
2392 (void *)VAR_NEWS_ACTIVE_PATH);
2394 set_current_val(&vars[V_NEWS_SPOOL_DIR], TRUE, TRUE);
2395 if(VAR_NEWS_SPOOL_DIR)
2396 mail_parameters(NULL, SET_NEWSSPOOL,
2397 (void *)VAR_NEWS_SPOOL_DIR);
2399 /* guarantee a save default */
2400 set_current_val(&vars[V_DEFAULT_SAVE_FOLDER], TRUE, TRUE);
2401 if(!VAR_DEFAULT_SAVE_FOLDER || !VAR_DEFAULT_SAVE_FOLDER[0])
2402 set_variable(V_DEFAULT_SAVE_FOLDER,
2403 (GLO_DEFAULT_SAVE_FOLDER && GLO_DEFAULT_SAVE_FOLDER[0])
2404 ? GLO_DEFAULT_SAVE_FOLDER
2405 : DEFAULT_SAVE, 1, 0, Main);
2407 set_current_val(&vars[V_SIGNATURE_FILE], TRUE, TRUE);
2408 set_current_val(&vars[V_LITERAL_SIG], TRUE, TRUE);
2409 set_current_val(&vars[V_GLOB_ADDRBOOK], TRUE, TRUE);
2410 set_current_val(&vars[V_ADDRESSBOOK], TRUE, TRUE);
2411 set_current_val(&vars[V_FORCED_ABOOK_ENTRY], TRUE, TRUE);
2412 set_current_val(&vars[V_DISABLE_DRIVERS], TRUE, TRUE);
2413 set_current_val(&vars[V_DISABLE_AUTHS], TRUE, TRUE);
2414 set_current_val(&vars[V_ENCRYPTION_RANGE], TRUE, TRUE);
2416 set_current_val(&vars[V_VIEW_HEADERS], TRUE, TRUE);
2417 /* strip spaces and colons */
2418 if(ps->VAR_VIEW_HEADERS){
2419 for(s = ps->VAR_VIEW_HEADERS; (q = *s) != NULL; s++){
2420 if(q[0]){
2421 removing_leading_white_space(q);
2422 /* look for colon or space or end */
2423 for(p = q; *p && !isspace((unsigned char)*p) && *p != ':'; p++)
2424 ;/* do nothing */
2426 *p = '\0';
2427 if(strucmp(q, ALL_EXCEPT) == 0)
2428 ps->view_all_except = 1;
2433 set_current_val(&vars[V_VIEW_MARGIN_LEFT], TRUE, TRUE);
2434 set_current_val(&vars[V_VIEW_MARGIN_RIGHT], TRUE, TRUE);
2435 set_current_val(&vars[V_UPLOAD_CMD], TRUE, TRUE);
2436 set_current_val(&vars[V_UPLOAD_CMD_PREFIX], TRUE, TRUE);
2437 set_current_val(&vars[V_DOWNLOAD_CMD], TRUE, TRUE);
2438 set_current_val(&vars[V_DOWNLOAD_CMD_PREFIX], TRUE, TRUE);
2439 set_current_val(&vars[V_MAILCAP_PATH], TRUE, TRUE);
2440 set_current_val(&vars[V_MIMETYPE_PATH], TRUE, TRUE);
2441 #if !defined(_WINDOWS) || defined(WINDOWS_UNIXSSL_CERTS)
2442 set_current_val(&vars[V_SSLCAPATH], TRUE, TRUE);
2443 set_current_val(&vars[V_SSLCAFILE], TRUE, TRUE);
2444 set_current_val(&vars[V_USERSSLCAPATH], TRUE, TRUE);
2445 set_current_val(&vars[V_USERSSLCAFILE], TRUE, TRUE);
2446 set_current_val(&vars[V_SSLCIPHERS], TRUE, TRUE);
2447 #endif
2448 #if !defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)
2449 set_current_val(&vars[V_FIFOPATH], TRUE, TRUE);
2450 #endif
2452 set_current_val(&vars[V_RSHPATH], TRUE, TRUE);
2453 if(VAR_RSHPATH
2454 && is_absolute_path(VAR_RSHPATH)
2455 && can_access(VAR_RSHPATH, EXECUTE_ACCESS) == 0){
2456 mail_parameters(NULL, SET_RSHPATH, (void *) VAR_RSHPATH);
2459 set_current_val(&vars[V_RSHCMD], TRUE, TRUE);
2460 if(VAR_RSHCMD){
2461 mail_parameters(NULL, SET_RSHCOMMAND, (void *) VAR_RSHCMD);
2464 set_current_val(&vars[V_SSHPATH], TRUE, TRUE);
2465 if(VAR_SSHPATH) {
2466 if(is_absolute_path(VAR_SSHPATH)
2467 && can_access(VAR_SSHPATH, EXECUTE_ACCESS) == 0){
2468 mail_parameters(NULL, SET_SSHPATH, (void *) VAR_SSHPATH);
2470 else {
2471 mail_parameters(NULL, SET_SSHPATH, (void *) NULL);
2475 set_current_val(&vars[V_SSHCMD], TRUE, TRUE);
2476 if(VAR_SSHCMD) {
2477 if(VAR_SSHCMD[0]) {
2478 mail_parameters(NULL, SET_SSHCOMMAND, (void *) VAR_SSHCMD);
2480 else {
2481 mail_parameters(NULL, SET_SSHCOMMAND, (void *) NULL);
2485 #if defined(DOS) || defined(OS2)
2487 set_current_val(&vars[V_FILE_DIR], TRUE, TRUE);
2489 #ifdef _WINDOWS
2490 set_current_val(&vars[V_FONT_NAME], TRUE, TRUE);
2491 set_current_val(&vars[V_FONT_SIZE], TRUE, TRUE);
2492 set_current_val(&vars[V_FONT_STYLE], TRUE, TRUE);
2493 set_current_val(&vars[V_FONT_CHAR_SET], TRUE, TRUE);
2494 set_current_val(&vars[V_CURSOR_STYLE], TRUE, TRUE);
2495 set_current_val(&vars[V_WINDOW_POSITION], TRUE, TRUE);
2497 if(F_OFF(F_STORE_WINPOS_IN_CONFIG, ps_global)){
2498 /* if win position is in the registry, use it */
2499 if(mswin_reg(MSWR_OP_GET, MSWR_PINE_POS, buf, sizeof(buf))){
2500 if(VAR_WINDOW_POSITION)
2501 fs_give((void **)&VAR_WINDOW_POSITION);
2503 VAR_WINDOW_POSITION = cpystr(buf);
2505 else if(VAR_WINDOW_POSITION
2506 && (ps->update_registry != UREG_NEVER_SET)){
2507 /* otherwise, put it there */
2508 mswin_reg(MSWR_OP_SET | ((ps->update_registry == UREG_ALWAYS_SET)
2509 ? MSWR_OP_FORCE : 0),
2510 MSWR_PINE_POS,
2511 VAR_WINDOW_POSITION, (size_t)NULL);
2515 mswin_setwindow (VAR_FONT_NAME, VAR_FONT_SIZE,
2516 VAR_FONT_STYLE, VAR_WINDOW_POSITION,
2517 VAR_CURSOR_STYLE, VAR_FONT_CHAR_SET);
2519 /* this is no longer used */
2520 if(VAR_WINDOW_POSITION)
2521 fs_give((void **)&VAR_WINDOW_POSITION);
2523 set_current_val(&vars[V_PRINT_FONT_NAME], TRUE, TRUE);
2524 set_current_val(&vars[V_PRINT_FONT_SIZE], TRUE, TRUE);
2525 set_current_val(&vars[V_PRINT_FONT_STYLE], TRUE, TRUE);
2526 set_current_val(&vars[V_PRINT_FONT_CHAR_SET], TRUE, TRUE);
2527 mswin_setprintfont (VAR_PRINT_FONT_NAME,
2528 VAR_PRINT_FONT_SIZE,
2529 VAR_PRINT_FONT_STYLE,
2530 VAR_PRINT_FONT_CHAR_SET);
2532 mswin_setgenhelptextcallback(pcpine_general_help);
2534 mswin_setclosetext ("Use the \"Q\" command to exit Alpine.");
2537 char foreColor[64], backColor[64];
2539 mswin_getwindow(NULL, 0, NULL, 0, NULL, 0, NULL, 0,
2540 foreColor, sizeof(foreColor), backColor, sizeof(backColor),
2541 NULL, 0, NULL, 0);
2542 if(!GLO_NORM_FORE_COLOR)
2543 GLO_NORM_FORE_COLOR = cpystr(foreColor);
2545 if(!GLO_NORM_BACK_COLOR)
2546 GLO_NORM_BACK_COLOR = cpystr(backColor);
2548 #endif /* _WINDOWS */
2549 #endif /* DOS */
2552 * We want the version number to start out as 1.0 for Alpine, but
2553 * we also want to use the same old config file that was used
2554 * with Pine. The Pine version numbers made it up to 4.64 and we
2555 * want Alpine's 1.0 to be larger than 4.64 so we keep a separate
2556 * internal version number which is the real version number
2557 * plus 4. That's what gets written in LAST_VERS_USED.
2559 strncpy(ps->vers_internal, ALPINE_VERSION, sizeof(ps->vers_internal));
2560 ps->vers_internal[sizeof(ps->vers_internal)-1] = '\0';
2561 if(isdigit(ps->vers_internal[0]) && ps->vers_internal[0] < '6')
2562 ps->vers_internal[0] = ps->vers_internal[0] + 4;
2564 set_current_val(&vars[V_LAST_VERS_USED], TRUE, TRUE);
2565 /* Check for special cases first */
2566 if(VAR_LAST_VERS_USED
2567 && (isdigit(ps->vers_internal[0])
2568 && ps->vers_internal[1] == '.'
2569 && isdigit((unsigned char)ps->vers_internal[2])
2570 && isdigit((unsigned char)ps->vers_internal[3])
2571 && isalpha((unsigned char)ps->vers_internal[4])
2572 && strncmp(VAR_LAST_VERS_USED, ps->vers_internal, 4) >= 0)){
2573 ps->show_new_version = 0;
2575 /* Otherwise just do lexicographic comparison... */
2576 else if(VAR_LAST_VERS_USED
2577 && strcmp(VAR_LAST_VERS_USED, ps->vers_internal) >= 0){
2578 ps->show_new_version = 0;
2580 else{
2581 #ifdef _WINDOWS
2583 * If this is the first time we've run a version > 4.40, and there
2584 * is evidence that the config file has not been used by unix pine,
2585 * then we convert color008 to colorlgr, color009 to colormgr, and
2586 * color010 to colordgr. If the config file is being used by
2587 * unix pine then color009 may really supposed to be red, etc.
2588 * Same if we've already run 4.41 or higher. We don't have to do
2589 * anything if we are new to alpine.
2591 ps->pre441 = (VAR_LAST_VERS_USED
2592 && strcmp(VAR_LAST_VERS_USED, "4.40") <= 0);
2593 #endif /* _WINDOWS */
2596 * Don't offer the new version message if we're told not to.
2598 set_current_val(&vars[V_NEW_VER_QUELL], TRUE, TRUE);
2599 ps->show_new_version = !(VAR_NEW_VER_QUELL
2600 && strcmp(ps->vers_internal,
2601 VAR_NEW_VER_QUELL) < 0);
2603 #ifdef _WINDOWS
2604 if(!ps_global->install_flag)
2605 #endif /* _WINDOWS */
2607 if(VAR_LAST_VERS_USED){
2608 strncpy(ps_global->pine_pre_vers, VAR_LAST_VERS_USED,
2609 sizeof(ps_global->pine_pre_vers));
2610 ps_global->pine_pre_vers[sizeof(ps_global->pine_pre_vers)-1] = '\0';
2613 set_variable(V_LAST_VERS_USED, ps->vers_internal, 1, 1,
2614 ps_global->ew_for_except_vars);
2618 /* Obsolete, backwards compatibility */
2619 set_current_val(&vars[V_ELM_STYLE_SAVE], TRUE, TRUE);
2620 /* Also obsolete */
2621 set_current_val(&vars[V_SAVE_BY_SENDER], TRUE, TRUE);
2622 if(!strucmp(VAR_ELM_STYLE_SAVE, "yes"))
2623 set_variable(V_SAVE_BY_SENDER, "yes", 1, 1, Main);
2624 obs_save_by_sender = !strucmp(VAR_SAVE_BY_SENDER, "yes");
2626 set_current_val(&vars[V_XOAUTH2_INFO], TRUE, TRUE);
2628 set_current_pattern_vals(ps);
2630 set_current_val(&vars[V_INDEX_FORMAT], TRUE, TRUE);
2631 init_index_format(VAR_INDEX_FORMAT, &ps->index_disp_format);
2633 /* this should come after pre441 is set or not */
2634 set_current_color_vals(ps);
2636 set_current_val(&vars[V_RSS_NEWS], TRUE, TRUE);
2637 set_current_val(&vars[V_RSS_WEATHER], TRUE, TRUE);
2638 set_current_val(&vars[V_WP_INDEXHEIGHT], TRUE, TRUE);
2639 set_current_val(&vars[V_WP_INDEXLINES], TRUE, TRUE);
2640 set_current_val(&vars[V_WP_AGGSTATE], TRUE, TRUE);
2641 set_current_val(&vars[V_WP_STATE], TRUE, TRUE);
2642 set_current_val(&vars[V_WP_COLUMNS], TRUE, TRUE);
2644 set_current_val(&vars[V_PRUNED_FOLDERS], TRUE, TRUE);
2645 set_current_val(&vars[V_ARCHIVED_FOLDERS], TRUE, TRUE);
2646 set_current_val(&vars[V_INCOMING_FOLDERS], TRUE, TRUE);
2647 set_current_val(&vars[V_SORT_KEY], TRUE, TRUE);
2648 if(decode_sort(VAR_SORT_KEY, &ps->def_sort, &def_sort_rev) == -1){
2649 snprintf(tmp_20k_buf, SIZEOF_20KBUF, "Sort type \"%.200s\" is invalid", VAR_SORT_KEY);
2650 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2651 ps->def_sort = SortArrival;
2652 ps->def_sort_rev = 0;
2654 else
2655 ps->def_sort_rev = def_sort_rev;
2657 cur_rule_value(&vars[V_SAVED_MSG_NAME_RULE], TRUE, TRUE);
2658 {NAMEVAL_S *v; int i;
2659 for(i = 0; (v = save_msg_rules(i)); i++)
2660 if(v->value == ps_global->save_msg_rule)
2661 break;
2663 /* if save_msg_rule is not default, or is explicitly set to default */
2664 if((ps_global->save_msg_rule != SAV_RULE_DEFLT) ||
2665 (v && v->name &&
2666 (!strucmp(ps_global->vars[V_SAVED_MSG_NAME_RULE].post_user_val.p,
2667 v->name) ||
2668 !strucmp(ps_global->vars[V_SAVED_MSG_NAME_RULE].main_user_val.p,
2669 v->name))))
2670 obs_save_by_sender = 0; /* don't overwrite */
2673 cur_rule_value(&vars[V_FCC_RULE], TRUE, TRUE);
2674 cur_rule_value(&vars[V_AB_SORT_RULE], TRUE, TRUE);
2676 #ifndef _WINDOWS
2677 cur_rule_value(&vars[V_COLOR_STYLE], TRUE, TRUE);
2678 #endif
2680 cur_rule_value(&vars[V_INDEX_COLOR_STYLE], TRUE, TRUE);
2681 cur_rule_value(&vars[V_TITLEBAR_COLOR_STYLE], TRUE, TRUE);
2682 cur_rule_value(&vars[V_FLD_SORT_RULE], TRUE, TRUE);
2683 cur_rule_value(&vars[V_INCOMING_STARTUP], TRUE, TRUE);
2684 cur_rule_value(&vars[V_PRUNING_RULE], TRUE, TRUE);
2685 cur_rule_value(&vars[V_REOPEN_RULE], TRUE, TRUE);
2686 cur_rule_value(&vars[V_GOTO_DEFAULT_RULE], TRUE, TRUE);
2687 cur_rule_value(&vars[V_THREAD_DISP_STYLE], TRUE, TRUE);
2688 cur_rule_value(&vars[V_THREAD_INDEX_STYLE], TRUE, TRUE);
2690 set_current_val(&vars[V_THREAD_MORE_CHAR], TRUE, TRUE);
2691 if(VAR_THREAD_MORE_CHAR[0] && VAR_THREAD_MORE_CHAR[1]){
2692 init_error(ps, SM_ORDER | SM_DING, 3, 5,
2693 _("Only using first character of threading-indicator-character option"));
2694 VAR_THREAD_MORE_CHAR[1] = '\0';
2697 set_current_val(&vars[V_THREAD_EXP_CHAR], TRUE, TRUE);
2698 if(VAR_THREAD_EXP_CHAR[0] && VAR_THREAD_EXP_CHAR[1]){
2699 init_error(ps, SM_ORDER | SM_DING, 3, 5,
2700 _("Only using first character of threading-expanded-character option"));
2701 VAR_THREAD_EXP_CHAR[1] = '\0';
2704 set_current_val(&vars[V_THREAD_LASTREPLY_CHAR], TRUE, TRUE);
2705 if(!VAR_THREAD_LASTREPLY_CHAR[0])
2706 VAR_THREAD_LASTREPLY_CHAR = cpystr(DF_THREAD_LASTREPLY_CHAR);
2708 if(VAR_THREAD_LASTREPLY_CHAR[0] && VAR_THREAD_LASTREPLY_CHAR[1]){
2709 init_error(ps, SM_ORDER | SM_DING, 3, 5,
2710 _("Only using first character of threading-lastreply-character option"));
2711 VAR_THREAD_LASTREPLY_CHAR[1] = '\0';
2714 set_current_val(&vars[V_MAXREMSTREAM], TRUE, TRUE);
2715 ps->s_pool.max_remstream = i = atoi(DF_MAXREMSTREAM);
2716 if(SVAR_MAXREMSTREAM(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2717 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2718 else
2719 ps->s_pool.max_remstream = i;
2721 set_current_val(&vars[V_PERMLOCKED], TRUE, TRUE);
2723 set_current_val(&vars[V_NMW_WIDTH], TRUE, TRUE);
2724 ps->nmw_width = i = atoi(DF_NMW_WIDTH);
2725 if(SVAR_NMW_WIDTH(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2726 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2727 else
2728 ps->nmw_width = i;
2730 /* backwards compatibility */
2731 if(obs_save_by_sender){
2732 ps->save_msg_rule = SAV_RULE_FROM;
2733 set_variable(V_SAVED_MSG_NAME_RULE, "by-from", 1, 1, Main);
2736 /* this should come after process_feature_list because of use_fkeys */
2737 if(!ps->start_in_index)
2738 set_current_val(&vars[V_INIT_CMD_LIST], FALSE, TRUE);
2739 if(VAR_INIT_CMD_LIST && VAR_INIT_CMD_LIST[0] && VAR_INIT_CMD_LIST[0][0])
2740 if(cmds_f)
2741 (*cmds_f)(ps, VAR_INIT_CMD_LIST);
2743 #ifdef _WINDOWS
2744 mswin_set_quit_confirm (F_OFF(F_QUIT_WO_CONFIRM, ps_global));
2745 #endif /* _WINDOWS */
2747 #ifdef DEBUG
2748 dump_configuration(0);
2749 #endif /* DEBUG */
2753 void
2754 convert_configvars_to_utf8(struct variable *vars, char *fromcharset)
2756 struct variable *v;
2759 * Make sure that everything is UTF-8.
2761 for(v = vars; v->name; v++)
2762 convert_configvar_to_utf8(v, fromcharset);
2766 void
2767 convert_configvar_to_utf8(struct variable *v, char *fromcharset)
2769 char **p, *conv, **valptr;
2770 int i;
2773 * Make sure that everything is UTF-8.
2775 if(v->is_list){
2776 for(i = 0; i < 7; i++){
2777 switch(i){
2778 case 1: valptr = v->current_val.l; break;
2779 case 0: valptr = v->main_user_val.l; break;
2780 case 2: valptr = v->changed_val.l; break;
2781 case 3: valptr = v->post_user_val.l; break;
2782 case 4: valptr = v->global_val.l; break;
2783 case 5: valptr = v->fixed_val.l; break;
2784 case 6: valptr = v->cmdline_val.l; break;
2785 default: alpine_panic("bad case in convert_configvar");
2788 if(valptr){
2789 for(p = valptr; *p; p++){
2790 if(**p){
2791 conv = convert_to_utf8(*p, fromcharset, 0);
2792 if(conv){
2793 fs_give((void **) p);
2794 *p = conv;
2801 else{
2802 for(i = 0; i < 7; i++){
2803 switch(i){
2804 case 1: valptr = &v->current_val.p; break;
2805 case 0: valptr = &v->main_user_val.p; break;
2806 case 2: valptr = &v->changed_val.p; break;
2807 case 3: valptr = &v->post_user_val.p; break;
2808 case 4: valptr = &v->global_val.p; break;
2809 case 5: valptr = &v->fixed_val.p; break;
2810 case 6: valptr = &v->cmdline_val.p; break;
2811 default: alpine_panic("bad case in convert_configvar");
2814 if(valptr && *valptr && (*valptr)[0]){
2815 conv = convert_to_utf8(*valptr, fromcharset, 0);
2816 if(conv){
2817 fs_give((void **) valptr);
2818 *valptr = conv;
2828 * Standard feature name sections
2830 char *
2831 feature_list_section(FEATURE_S *feature)
2833 #define PREF_NONE -1
2834 static char *feat_sect[] = {
2835 #define PREF_MISC 0
2836 /* TRANSLATORS: section heading in configuration screen */
2837 N_("Advanced User Preferences"),
2838 #define PREF_FLDR 1
2839 /* TRANSLATORS: section heading in configuration screen */
2840 N_("Folder Preferences"),
2841 #define PREF_ADDR 2
2842 /* TRANSLATORS: section heading in configuration screen */
2843 N_("Address Book Preferences"),
2844 #define PREF_COMP 3
2845 /* TRANSLATORS: section heading in configuration screen */
2846 N_("Composer Preferences"),
2847 #define PREF_NEWS 4
2848 /* TRANSLATORS: section heading in configuration screen */
2849 N_("News Preferences"),
2850 #define PREF_VIEW 5
2851 /* TRANSLATORS: section heading in configuration screen */
2852 N_("Viewer Preferences"),
2853 #define PREF_ACMD 6
2854 /* TRANSLATORS: section heading in configuration screen */
2855 N_("Advanced Command Preferences"),
2856 #define PREF_PRNT 7
2857 /* TRANSLATORS: section heading in configuration screen */
2858 N_("Printer Preferences"),
2859 #define PREF_RPLY 8
2860 /* TRANSLATORS: section heading in configuration screen */
2861 N_("Reply Preferences"),
2862 #define PREF_SEND 9
2863 /* TRANSLATORS: section heading in configuration screen */
2864 N_("Sending Preferences"),
2865 #define PREF_INDX 10
2866 /* TRANSLATORS: section heading in configuration screen */
2867 N_("Message Index Preferences"),
2868 #define PREF_HIDDEN 11
2869 HIDDEN_PREF
2872 return((feature && feature->section > PREF_NONE
2873 && feature->section < (sizeof(feat_sect)/sizeof(feat_sect[0])))
2874 ? _(feat_sect[feature->section]) : NULL);
2878 /* any os-specific exclusions */
2879 #if defined(DOS) || defined(OS2)
2880 #define PREF_OS_LWSD PREF_NONE
2881 #define PREF_OS_LCLK PREF_NONE
2882 #define PREF_OS_STSP PREF_NONE
2883 #define PREF_OS_SPWN PREF_NONE
2884 #define PREF_OS_XNML PREF_NONE
2885 #define PREF_OS_USFK PREF_MISC
2886 #define PREF_OS_MOUSE PREF_NONE
2887 #else
2888 #define PREF_OS_LWSD PREF_MISC
2889 #define PREF_OS_LCLK PREF_COMP
2890 #define PREF_OS_STSP PREF_MISC
2891 #define PREF_OS_SPWN PREF_MISC
2892 #define PREF_OS_XNML PREF_MISC
2893 #define PREF_OS_USFK PREF_NONE
2894 #define PREF_OS_MOUSE PREF_MISC
2895 #endif
2899 * Standard way to get at feature list members...
2901 FEATURE_S *
2902 feature_list(int index)
2905 * This list is alphabatized by feature string, but the
2906 * macro values need not be ordered.
2908 static FEATURE_S feat_list[] = {
2909 /* Composer prefs */
2910 {"allow-changing-from", NULL,
2911 F_ALLOW_CHANGING_FROM, h_config_allow_chg_from, PREF_COMP, 1},
2912 {"alternate-compose-menu", NULL,
2913 F_ALT_COMPOSE_MENU, h_config_alt_compose_menu, PREF_COMP, 0},
2914 {"alternate-role-menu", "Alternate Role (#) Menu",
2915 F_ALT_ROLE_MENU, h_config_alt_role_menu, PREF_COMP, 0},
2916 {"compose-cancel-confirm-uses-yes", NULL,
2917 F_CANCEL_CONFIRM, h_config_cancel_confirm, PREF_COMP, 0},
2918 {"compose-rejects-unqualified-addrs", "Compose Rejects Unqualified Addresses",
2919 F_COMPOSE_REJECTS_UNQUAL, h_config_compose_rejects_unqual, PREF_COMP, 0},
2920 {"compose-send-offers-first-filter", NULL,
2921 F_FIRST_SEND_FILTER_DFLT, h_config_send_filter_dflt, PREF_COMP, 0},
2922 {"compose-cut-from-cursor", "Ctrl-K Cuts From Cursor",
2923 F_DEL_FROM_DOT, h_config_del_from_dot, PREF_COMP, 0},
2924 {"compose-maps-delete-key-to-ctrl-d", "Delete Key Maps to Ctrl-D",
2925 F_COMPOSE_MAPS_DEL, h_config_compose_maps_del, PREF_COMP, 0},
2926 {"quell-dead-letter-on-cancel", "Do Not Save to Deadletter on Cancel",
2927 F_QUELL_DEAD_LETTER, h_config_quell_dead_letter, PREF_COMP, 0},
2928 {"enable-alternate-editor-cmd", "Enable Alternate Editor Command",
2929 F_ENABLE_ALT_ED, h_config_enable_alt_ed, PREF_COMP, 1},
2930 {"enable-alternate-editor-implicitly", NULL,
2931 F_ALT_ED_NOW, h_config_alt_ed_now, PREF_COMP, 0},
2932 {"enable-search-and-replace", "Enable Search and Replace",
2933 F_ENABLE_SEARCH_AND_REPL, h_config_enable_search_and_repl, PREF_COMP, 1},
2934 {"enable-sigdashes", NULL,
2935 F_ENABLE_SIGDASHES, h_config_sigdashes, PREF_COMP, 0},
2936 {"quell-mailchecks-composing-except-inbox", "Prevent Mailchecks While Composing Except for INBOX",
2937 F_QUELL_PINGS_COMPOSING, h_config_quell_checks_comp, PREF_COMP, 0},
2938 {"quell-mailchecks-composing-inbox", "Prevent Mailchecks While Composing for INBOX",
2939 F_QUELL_PINGS_COMPOSING_INBOX, h_config_quell_checks_comp_inbox, PREF_COMP, 0},
2940 {"quell-user-lookup-in-passwd-file", "Prevent User Lookup in Password File",
2941 F_QUELL_LOCAL_LOOKUP, h_config_quell_local_lookup, PREF_OS_LCLK, 0},
2942 {"spell-check-before-sending", NULL,
2943 F_ALWAYS_SPELL_CHECK, h_config_always_spell_check, PREF_COMP, 0},
2945 /* Reply Prefs */
2946 {"alternate-reply-menu", NULL,
2947 F_ALT_REPLY_MENU, h_config_alt_reply_menu, PREF_RPLY, 0},
2948 {"copy-to-address-to-from-if-it-is-us", "Copy To Address to From if it is Us",
2949 F_COPY_TO_TO_FROM, h_config_copy_to_to_from, PREF_RPLY, 0},
2950 {"enable-reply-indent-string-editing", NULL,
2951 F_ENABLE_EDIT_REPLY_INDENT, h_config_prefix_editing, PREF_RPLY, 0},
2952 {"include-attachments-in-reply", "Include Attachments in Reply",
2953 F_ATTACHMENTS_IN_REPLY, h_config_attach_in_reply, PREF_RPLY, 0},
2954 {"include-header-in-reply", "Include Header in Reply",
2955 F_INCLUDE_HEADER, h_config_include_header, PREF_RPLY, 0},
2956 {"include-text-in-reply", "Include Text in Reply",
2957 F_AUTO_INCLUDE_IN_REPLY, h_config_auto_include_reply, PREF_RPLY, 0},
2958 {"reply-always-uses-reply-to", "Reply Always Uses Reply-To",
2959 F_AUTO_REPLY_TO, h_config_auto_reply_to, PREF_RPLY, 0},
2960 {"signature-at-bottom", "Signature at Bottom",
2961 F_SIG_AT_BOTTOM, h_config_sig_at_bottom, PREF_RPLY, 0},
2962 {"strip-from-sigdashes-on-reply", "Strip From Sigdashes on Reply",
2963 F_ENABLE_STRIP_SIGDASHES, h_config_strip_sigdashes, PREF_RPLY, 0},
2964 {"forward-as-attachment", "Forward messages as attachments",
2965 F_FORWARD_AS_ATTACHMENT, h_config_forward_as_attachment, PREF_RPLY, 0},
2966 {"preserve-original-fields", NULL,
2967 F_PRESERVE_ORIGINAL_FIELD, h_config_preserve_field, PREF_RPLY, 0},
2969 /* Sending Prefs */
2970 {"disable-sender", "Do Not Generate Sender Header",
2971 F_DISABLE_SENDER, h_config_disable_sender, PREF_SEND, 1},
2972 {"use-sender-not-x-sender", "Use Sender Instead of X-X-Sender",
2973 F_USE_SENDER_NOT_X, h_config_use_sender_not_x, PREF_SEND, 0},
2974 {"quell-flowed-text", "Do Not Send Flowed Text",
2975 F_QUELL_FLOWED_TEXT, h_config_quell_flowed_text, PREF_SEND, 0},
2976 {"downgrade-multipart-to-text", "Downgrade Multipart to Text",
2977 F_COMPOSE_ALWAYS_DOWNGRADE, h_downgrade_multipart_to_text, PREF_SEND, 0},
2978 {"enable-8bit-esmtp-negotiation", "Enable 8bit ESMTP Negotiation",
2979 F_ENABLE_8BIT, h_config_8bit_smtp, PREF_SEND, 1},
2980 #ifdef BACKGROUND_POST
2981 {"enable-background-sending", NULL,
2982 F_BACKGROUND_POST, h_config_compose_bg_post, PREF_SEND, 0},
2983 #endif
2984 {"enable-delivery-status-notification", NULL,
2985 F_DSN, h_config_compose_dsn, PREF_SEND, 0},
2986 {"enable-verbose-smtp-posting", "Enable Verbose SMTP Posting",
2987 F_VERBOSE_POST, h_config_verbose_post, PREF_SEND, 0},
2988 {"fcc-without-attachments", "Fcc Does Not Include Attachments",
2989 F_NO_FCC_ATTACH, h_config_no_fcc_attach, PREF_SEND, 0},
2990 {"fcc-on-bounce", "Include Fcc When Bouncing Messages",
2991 F_FCC_ON_BOUNCE, h_config_fcc_on_bounce, PREF_SEND, 0},
2992 {"mark-fcc-seen", NULL,
2993 F_MARK_FCC_SEEN, h_config_mark_fcc_seen, PREF_SEND, 0},
2994 {"fcc-only-without-confirm", "Send to Fcc Only Without Confirming",
2995 F_AUTO_FCC_ONLY, h_config_auto_fcc_only, PREF_SEND, 0},
2996 {"send-without-confirm", "Send Without Confirming",
2997 F_SEND_WO_CONFIRM, h_config_send_wo_confirm, PREF_SEND, 0},
2998 {"strip-whitespace-before-send", "Strip Whitespace Before Sending",
2999 F_STRIP_WS_BEFORE_SEND, h_config_strip_ws_before_send, PREF_SEND, 0},
3000 {"warn-if-blank-fcc", "Warn if Blank Fcc",
3001 F_WARN_ABOUT_NO_FCC, h_config_warn_if_fcc_blank, PREF_SEND, 0},
3002 {"warn-if-blank-subject", "Warn if Blank Subject",
3003 F_WARN_ABOUT_NO_SUBJECT, h_config_warn_if_subj_blank, PREF_SEND, 0},
3004 {"warn-if-blank-to-and-cc-and-newsgroups", "Warn if Blank To and CC and Newsgroups",
3005 F_WARN_ABOUT_NO_TO_OR_CC, h_config_warn_if_no_to_or_cc, PREF_SEND, 0},
3007 /* Folder */
3008 {"combined-folder-display", NULL,
3009 F_CMBND_FOLDER_DISP, h_config_combined_folder_display, PREF_FLDR, 0},
3010 {"combined-subdirectory-display", NULL,
3011 F_CMBND_SUBDIR_DISP, h_config_combined_subdir_display, PREF_FLDR, 0},
3012 {"enable-lame-list-mode", "Compensate for Deficient IMAP servers",
3013 F_FIX_BROKEN_LIST, h_config_lame_list_mode, PREF_FLDR, 0},
3014 {"enable-dot-folders", "Enable Hidden Folders",
3015 F_ENABLE_DOT_FOLDERS, h_config_enable_dot_folders, PREF_FLDR, 0},
3016 {"enable-incoming-folders", "Enable Incoming Folders Collection",
3017 F_ENABLE_INCOMING, h_config_enable_incoming, PREF_FLDR, 0},
3018 {"enable-incoming-folders-checking", NULL,
3019 F_ENABLE_INCOMING_CHECKING, h_config_enable_incoming_checking, PREF_FLDR, 0},
3020 {"incoming-checking-includes-total", NULL,
3021 F_INCOMING_CHECKING_TOTAL, h_config_incoming_checking_total, PREF_FLDR, 0},
3022 {"incoming-checking-uses-recent", NULL,
3023 F_INCOMING_CHECKING_RECENT, h_config_incoming_checking_recent, PREF_FLDR, 0},
3024 {"expanded-view-of-folders", "Expanded View of Folders",
3025 F_EXPANDED_FOLDERS, h_config_expanded_folders, PREF_FLDR, 0},
3026 {"quell-empty-directories", "Hide Empty Directories",
3027 F_QUELL_EMPTY_DIRS, h_config_quell_empty_dirs, PREF_FLDR, 0},
3028 {"separate-folder-and-directory-entries", "Separate Folder and Directory Entries",
3029 F_SEPARATE_FLDR_AS_DIR, h_config_separate_fold_dir_view, PREF_FLDR, 0},
3030 {"single-column-folder-list", NULL,
3031 F_SINGLE_FOLDER_LIST, h_config_single_list, PREF_FLDR, 0},
3032 {"sort-default-fcc-alpha", "Sort Default Fcc Folder Alphabetically",
3033 F_SORT_DEFAULT_FCC_ALPHA, h_config_sort_fcc_alpha, PREF_FLDR, 0},
3034 {"sort-default-save-alpha", "Sort Default Save Folder Alphabetically",
3035 F_SORT_DEFAULT_SAVE_ALPHA, h_config_sort_save_alpha, PREF_FLDR, 0},
3036 {"vertical-folder-list", "Use Vertical Folder List",
3037 F_VERTICAL_FOLDER_LIST, h_config_vertical_list, PREF_FLDR, 0},
3039 /* Addr book */
3040 {"combined-addrbook-display", "Combined Address Book Display",
3041 F_CMBND_ABOOK_DISP, h_config_combined_abook_display, PREF_ADDR, 0},
3042 {"expanded-view-of-addressbooks", "Expanded View of Address Books",
3043 F_EXPANDED_ADDRBOOKS, h_config_expanded_addrbooks, PREF_ADDR, 0},
3044 {"expanded-view-of-distribution-lists", "Expanded View of Distribution Lists",
3045 F_EXPANDED_DISTLISTS, h_config_expanded_distlists, PREF_ADDR, 0},
3046 #ifdef ENABLE_LDAP
3047 {"ldap-result-to-addrbook-add", "LDAP Result to Addressbook Add",
3048 F_ADD_LDAP_TO_ABOOK, h_config_add_ldap, PREF_ADDR, 0},
3049 #endif
3051 /* Index prefs */
3052 {"auto-open-next-unread", NULL,
3053 F_AUTO_OPEN_NEXT_UNREAD, h_config_auto_open_unread, PREF_INDX, 0},
3054 {"continue-tab-without-confirm", "Continue NextNew Without Confirming",
3055 F_TAB_NO_CONFIRM, h_config_tab_no_prompt, PREF_INDX, 0},
3056 {"convert-dates-to-localtime", NULL,
3057 F_DATES_TO_LOCAL, h_config_dates_to_local, PREF_INDX, 0},
3058 {"delete-skips-deleted", NULL,
3059 F_DEL_SKIPS_DEL, h_config_del_skips_del, PREF_INDX, 1},
3060 {"disable-index-locale-dates", NULL,
3061 F_DISABLE_INDEX_LOCALE_DATES, h_config_disable_index_locale_dates, PREF_INDX, 0},
3062 {"enable-cruise-mode", NULL,
3063 F_ENABLE_SPACE_AS_TAB, h_config_cruise_mode, PREF_INDX, 0},
3064 {"enable-cruise-mode-delete", "Enable Cruise Mode With Deleting",
3065 F_ENABLE_TAB_DELETES, h_config_cruise_mode_delete, PREF_INDX, 0},
3066 {"mark-for-cc", "Mark for CC",
3067 F_MARK_FOR_CC, h_config_mark_for_cc, PREF_INDX, 1},
3068 {"next-thread-without-confirm", "Read Next Thread Without Confirming",
3069 F_NEXT_THRD_WO_CONFIRM, h_config_next_thrd_wo_confirm, PREF_INDX, 0},
3070 {"return-to-inbox-without-confirm", "Return to INBOX Without Confirming",
3071 F_RET_INBOX_NO_CONFIRM, h_config_inbox_no_confirm, PREF_INDX, 0},
3072 {"show-sort", "Show Sort in Titlebar",
3073 F_SHOW_SORT, h_config_show_sort, PREF_INDX, 0},
3074 {"tab-uses-unseen-for-next-folder", "Tab Uses Unseen for Next Folder",
3075 F_TAB_USES_UNSEEN, h_config_tab_uses_unseen, PREF_INDX, 0},
3076 {"tab-visits-next-new-message-only", NULL,
3077 F_TAB_TO_NEW, h_config_tab_new_only, PREF_INDX, 0},
3078 {"thread-index-shows-important-color", NULL,
3079 F_COLOR_LINE_IMPORTANT, h_config_color_thrd_import, PREF_INDX, 0},
3080 {"thread-sorts-by-arrival", "Thread Sorts by Arrival",
3081 F_THREAD_SORTS_BY_ARRIVAL, h_config_thread_sorts_by_arrival, PREF_INDX, 0},
3083 /* Viewer prefs */
3084 {"enable-msg-view-addresses", "Enable Message View Address Links",
3085 F_SCAN_ADDR, h_config_enable_view_addresses, PREF_VIEW, 0},
3086 {"enable-msg-view-attachments", "Enable Message View Attachment Links",
3087 F_VIEW_SEL_ATTACH, h_config_enable_view_attach, PREF_VIEW, 0},
3088 {"enable-msg-view-urls", "Enable Message View URL Links",
3089 F_VIEW_SEL_URL, h_config_enable_view_url, PREF_VIEW, 1},
3090 {"enable-msg-view-web-hostnames", "Enable Message View Web Hostname Links",
3091 F_VIEW_SEL_URL_HOST, h_config_enable_view_web_host, PREF_VIEW, 1},
3092 {"enable-msg-view-forced-arrows", "Enable Message View Forced Arrows",
3093 F_FORCE_ARROWS, h_config_enable_view_arrows, PREF_VIEW, 0},
3094 {"external-command-loads-inline-images-only", NULL,
3095 F_EXTERNAL_INLINE_IMAGES, h_external_loads_inline_images_only, PREF_VIEW, 1},
3096 /* set to TRUE for windows */
3097 {"pass-c1-control-characters-as-is", NULL,
3098 F_PASS_C1_CONTROL_CHARS, h_config_pass_c1_control, PREF_VIEW, 0},
3099 {"pass-control-characters-as-is", NULL,
3100 F_PASS_CONTROL_CHARS, h_config_pass_control, PREF_VIEW, 0},
3101 {"prefer-plain-text", NULL,
3102 F_PREFER_PLAIN_TEXT, h_config_prefer_plain_text, PREF_VIEW, 0},
3103 {"quell-charset-warning", "Suppress Character Set Warning",
3104 F_QUELL_CHARSET_WARNING, h_config_quell_charset_warning, PREF_VIEW, 0},
3105 {"quell-server-after-link-in-html", "Suppress Server After Link in HTML",
3106 F_QUELL_HOST_AFTER_URL, h_config_quell_host_after_url, PREF_VIEW, 0},
3108 /* News */
3109 {"compose-sets-newsgroup-without-confirm", "Compose Sets Newsgroup Without Confirming",
3110 F_COMPOSE_TO_NEWSGRP, h_config_compose_news_wo_conf, PREF_NEWS, 0},
3111 {"enable-8bit-nntp-posting", "Enable 8bit NNTP Posting",
3112 F_ENABLE_8BIT_NNTP, h_config_8bit_nntp, PREF_NEWS, 0},
3113 {"enable-multiple-newsrcs", NULL,
3114 F_ENABLE_MULNEWSRCS, h_config_enable_mulnewsrcs, PREF_NEWS, 0},
3115 {"mult-newsrc-hostnames-as-typed", "Multiple Newsrc Hostnames as Typed",
3116 F_MULNEWSRC_HOSTNAMES_AS_TYPED, h_config_mulnews_as_typed, PREF_NEWS, 0},
3117 {"hide-nntp-path", "Hide NNTP Path",
3118 F_HIDE_NNTP_PATH, h_config_hide_nntp_path, PREF_NEWS, 0},
3119 {"news-approximates-new-status", NULL,
3120 F_FAKE_NEW_IN_NEWS, h_config_news_uses_recent, PREF_NEWS, 1},
3121 {"news-deletes-across-groups", NULL,
3122 F_NEWS_CROSS_DELETE, h_config_news_cross_deletes, PREF_NEWS, 0},
3123 {"news-offers-catchup-on-close", "News Offers Catchup on Close",
3124 F_NEWS_CATCHUP, h_config_news_catchup, PREF_NEWS, 0},
3125 {"news-post-without-validation", NULL,
3126 F_NO_NEWS_VALIDATION, h_config_post_wo_validation, PREF_NEWS, 0},
3127 {"news-read-in-newsrc-order", "News Read in Newsrc Order",
3128 F_READ_IN_NEWSRC_ORDER, h_config_read_in_newsrc_order, PREF_NEWS, 0},
3129 {"nntp-search-uses-overview", "NNTP Search Uses Overview",
3130 F_NNTP_SEARCH_USES_OVERVIEW, h_config_nntp_search_uses_overview, PREF_NEWS, 1},
3131 {"predict-nntp-server", "Predict NNTP Server",
3132 F_PREDICT_NNTP_SERVER, h_config_predict_nntp_server, PREF_NEWS, 0},
3133 {"quell-extra-post-prompt", "Suppress Extra Posting Prompt",
3134 F_QUELL_EXTRA_POST_PROMPT, h_config_quell_post_prompt, PREF_NEWS, 0},
3136 /* Print */
3137 {"enable-print-via-y-command", NULL,
3138 F_ENABLE_PRYNT, h_config_enable_y_print, PREF_PRNT, 0},
3139 {"print-formfeed-between-messages", NULL,
3140 F_AGG_PRINT_FF, h_config_ff_between_msgs, PREF_PRNT, 0},
3141 {"print-includes-from-line", NULL,
3142 F_FROM_DELIM_IN_PRINT, h_config_print_from, PREF_PRNT, 0},
3143 {"print-index-enabled", NULL,
3144 F_PRINT_INDEX, h_config_print_index, PREF_PRNT, 0},
3145 {"print-offers-custom-cmd-prompt", "Print Offers Custom Command Prompt",
3146 F_CUSTOM_PRINT, h_config_custom_print, PREF_PRNT, 0},
3148 /* adv cmd prefs */
3149 {"enable-aggregate-command-set", NULL,
3150 F_ENABLE_AGG_OPS, h_config_enable_agg_ops, PREF_ACMD, 1},
3151 {"enable-arrow-navigation", NULL,
3152 F_ARROW_NAV, h_config_arrow_nav, PREF_ACMD, 1},
3153 {"enable-arrow-navigation-relaxed", NULL,
3154 F_RELAXED_ARROW_NAV, h_config_relaxed_arrow_nav, PREF_ACMD, 1},
3155 {"enable-bounce-cmd", "Enable Bounce Command",
3156 F_ENABLE_BOUNCE, h_config_enable_bounce, PREF_ACMD, 1},
3157 {"enable-exit-via-lessthan-command", NULL,
3158 F_ENABLE_LESSTHAN_EXIT, h_config_enable_lessthan_exit, PREF_ACMD, 1},
3159 {"enable-flag-cmd", "Enable Flag Command",
3160 F_ENABLE_FLAG, h_config_enable_flag, PREF_ACMD, 1},
3161 {"enable-flag-screen-implicitly", NULL,
3162 F_FLAG_SCREEN_DFLT, h_config_flag_screen_default, PREF_ACMD, 0},
3163 {"enable-flag-screen-keyword-shortcut", NULL,
3164 F_FLAG_SCREEN_KW_SHORTCUT, h_config_flag_screen_kw_shortcut,PREF_ACMD, 1},
3165 {"enable-full-header-and-text", "Enable Full Header and Text",
3166 F_ENABLE_FULL_HDR_AND_TEXT, h_config_enable_full_hdr_and_text, PREF_ACMD, 0},
3167 {"enable-full-header-cmd", "Enable Full Header Command",
3168 F_ENABLE_FULL_HDR, h_config_enable_full_hdr, PREF_ACMD, 1},
3169 {"enable-goto-in-file-browser", "Enable Goto in File Browser",
3170 F_ALLOW_GOTO, h_config_allow_goto, PREF_ACMD, 1},
3171 {"enable-jump-shortcut", NULL,
3172 F_ENABLE_JUMP, h_config_enable_jump, PREF_ACMD, 1},
3173 {"enable-partial-match-lists", NULL,
3174 F_ENABLE_SUB_LISTS, h_config_sub_lists, PREF_ACMD, 1},
3175 {"enable-tab-completion", NULL,
3176 F_ENABLE_TAB_COMPLETE, h_config_enable_tab_complete, PREF_ACMD, 1},
3177 {"enable-unix-pipe-cmd", "Enable Unix Pipe Command",
3178 F_ENABLE_PIPE, h_config_enable_pipe, PREF_ACMD, 1},
3179 {"quell-full-header-auto-reset", "Suppress Full Header Auto Reset",
3180 F_QUELL_FULL_HDR_RESET, h_config_quell_full_hdr_reset, PREF_ACMD, 0},
3182 /* Adv user prefs */
3183 #if !defined(DOS) && !defined(OS2)
3184 {"allow-talk", NULL,
3185 F_ALLOW_TALK, h_config_allow_talk, PREF_MISC, 0},
3186 #endif
3187 {"assume-slow-link", NULL,
3188 F_FORCE_LOW_SPEED, h_config_force_low_speed, PREF_OS_LWSD, 0},
3189 {"auto-move-read-msgs", "Auto Move Read Messages",
3190 F_AUTO_READ_MSGS, h_config_auto_read_msgs, PREF_MISC, 0},
3191 {"auto-unselect-after-apply", NULL,
3192 F_AUTO_UNSELECT, h_config_auto_unselect, PREF_MISC, 0},
3193 {"auto-unzoom-after-apply", NULL,
3194 F_AUTO_UNZOOM, h_config_auto_unzoom, PREF_MISC, 1},
3195 {"auto-zoom-after-select", NULL,
3196 F_AUTO_ZOOM, h_config_auto_zoom, PREF_MISC, 1},
3197 {"busy-cue-spinner-only", NULL,
3198 F_USE_BORING_SPINNER, h_config_use_boring_spinner, PREF_MISC, 0},
3199 {"check-newmail-when-quitting", NULL,
3200 F_CHECK_MAIL_ONQUIT, h_config_check_mail_onquit, PREF_MISC, 0},
3201 {"confirm-role-even-for-default", "Confirm Role Even for Default",
3202 F_ROLE_CONFIRM_DEFAULT, h_config_confirm_role, PREF_MISC, 0},
3203 {"disable-keymenu", NULL,
3204 F_BLANK_KEYMENU, h_config_blank_keymenu, PREF_MISC, 0},
3205 {"disable-password-caching", NULL,
3206 F_DISABLE_PASSWORD_CACHING, h_config_disable_password_caching,
3207 PREF_MISC, 0},
3208 #ifdef LOCAL_PASSWD_CACHE
3209 {"disable-password-file-saving", NULL,
3210 F_DISABLE_PASSWORD_FILE_SAVING, h_config_disable_password_file_saving,
3211 PREF_MISC, 0},
3212 #endif /* LOCAL_PASSWD_CACHE */
3213 {"disable-regular-expression-matching-for-alternate-addresses", NULL,
3214 F_DISABLE_REGEX, h_config_disable_regex, PREF_MISC, 0},
3215 {"disable-save-input-history", NULL,
3216 F_DISABLE_SAVE_INPUT_HISTORY, h_config_input_history, PREF_MISC, 0},
3217 {"disable-take-fullname-in-addresses", "Disable Take Fullname in Addresses",
3218 F_DISABLE_TAKE_FULLNAMES, h_config_take_fullname, PREF_MISC, 0},
3219 {"disable-take-last-comma-first", NULL,
3220 F_DISABLE_TAKE_LASTFIRST, h_config_take_lastfirst, PREF_MISC, 0},
3221 {"disable-terminal-reset-for-display-filters", "Disable Terminal Reset for Display Filters",
3222 F_DISABLE_TERM_RESET_DISP, h_config_disable_reset_disp, PREF_MISC, 0},
3223 {"enable-dot-files", NULL,
3224 F_ENABLE_DOT_FILES, h_config_enable_dot_files, PREF_MISC, 0},
3225 {"enable-fast-recent-test", NULL,
3226 F_ENABLE_FAST_RECENT, h_config_fast_recent, PREF_MISC, 0},
3227 {"enable-mail-check-cue", NULL,
3228 F_SHOW_DELAY_CUE, h_config_show_delay_cue, PREF_MISC, 0},
3229 {"enable-mailcap-param-substitution", "Enable Mailcap Parameter Substitution",
3230 F_DO_MAILCAP_PARAM_SUBST, h_config_mailcap_params, PREF_MISC, 0},
3231 {"enable-mouse-in-xterm", "Enable Mouse in Xterm",
3232 F_ENABLE_MOUSE, h_config_enable_mouse, PREF_OS_MOUSE, 0},
3233 {"enable-newmail-in-xterm-icon", "Enable Newmail in Xterm Icon",
3234 F_ENABLE_XTERM_NEWMAIL, h_config_enable_xterm_newmail, PREF_OS_XNML, 0},
3235 {"enable-newmail-short-text-in-icon", "Enable Newmail Short Text in Icon",
3236 F_ENABLE_NEWMAIL_SHORT_TEXT, h_config_enable_newmail_short_text, PREF_OS_XNML, 0},
3237 {"enable-suspend", NULL,
3238 F_CAN_SUSPEND, h_config_can_suspend, PREF_MISC, 0},
3239 {"enable-take-export", NULL,
3240 F_ENABLE_TAKE_EXPORT, h_config_enable_take_export, PREF_MISC, 0},
3241 {"enable-rules-under-take", "Enable Take Rules",
3242 F_ENABLE_ROLE_TAKE, h_config_enable_role_take, PREF_MISC, 0},
3243 #ifdef _WINDOWS
3244 {"enable-tray-icon", NULL,
3245 F_ENABLE_TRAYICON, h_config_tray_icon, PREF_MISC, 0},
3246 #endif
3247 {"expose-hidden-config", NULL,
3248 F_EXPOSE_HIDDEN_CONFIG, h_config_expose_hidden_config, PREF_MISC, 0},
3249 {"expunge-only-manually", NULL,
3250 F_EXPUNGE_MANUALLY, h_config_expunge_manually, PREF_MISC, 0},
3251 {"expunge-without-confirm", "Expunge Without Confirming",
3252 F_AUTO_EXPUNGE, h_config_auto_expunge, PREF_MISC, 0},
3253 {"expunge-without-confirm-everywhere", "Expunge Without Confirming Everywhere",
3254 F_FULL_AUTO_EXPUNGE, h_config_full_auto_expunge, PREF_MISC, 0},
3255 {"force-arrow-cursor", NULL,
3256 F_FORCE_ARROW, h_config_force_arrow, PREF_MISC, 0},
3257 {"ignore-size-changes", NULL,
3258 F_IGNORE_SIZE, h_config_ignore_size, PREF_MISC, 0},
3259 {"maildrops-preserve-state", NULL,
3260 F_MAILDROPS_PRESERVE_STATE, h_config_maildrops_preserve_state,
3261 PREF_MISC, 0},
3262 {"offer-expunge-of-inbox", "Offer Expunge of INBOX",
3263 F_EXPUNGE_INBOX, h_config_expunge_inbox, PREF_MISC, 0},
3264 {"offer-expunge-of-stayopen-folders", "Offer Expunge of Stayopen Folders",
3265 F_EXPUNGE_STAYOPENS, h_config_expunge_stayopens, PREF_MISC, 0},
3266 {"preopen-stayopen-folders", NULL,
3267 F_PREOPEN_STAYOPENS, h_config_preopen_stayopens, PREF_MISC, 0},
3268 {"preserve-start-stop-characters", "Preserve Start/Stop Characters",
3269 F_PRESERVE_START_STOP, h_config_preserve_start_stop, PREF_OS_STSP, 0},
3270 {"quell-folder-internal-msg", "Prevent Folder Internal Message",
3271 F_QUELL_INTERNAL_MSG, h_config_quell_folder_internal_msg, PREF_MISC, 0},
3272 {"quell-partial-fetching", "Prevent Partial Fetching",
3273 F_QUELL_PARTIAL_FETCH, h_config_quell_partial, PREF_MISC, 0},
3274 {"prune-uses-yyyy-mm", "Prune Uses YYYY-MM",
3275 F_PRUNE_USES_ISO, h_config_prune_uses_iso, PREF_MISC, 0},
3276 {"quit-without-confirm", "Quit Without Confirming",
3277 F_QUIT_WO_CONFIRM, h_config_quit_wo_confirm, PREF_MISC, 0},
3278 {"quote-replace-nonflowed", NULL,
3279 F_QUOTE_REPLACE_NOFLOW, h_config_quote_replace_noflow, PREF_MISC, 0},
3280 {"save-aggregates-copy-sequence", "Save Combines Copies (may be out of order)",
3281 F_AGG_SEQ_COPY, h_config_save_aggregates, PREF_MISC, 1},
3282 {"save-partial-msg-without-confirm", "Save Partial Message Without Confirming",
3283 F_SAVE_PARTIAL_WO_CONFIRM, h_config_save_part_wo_confirm, PREF_MISC, 0},
3284 {"save-will-advance", NULL,
3285 F_SAVE_ADVANCES, h_config_save_advances, PREF_MISC, 0},
3286 {"save-will-not-delete", NULL,
3287 F_SAVE_WONT_DELETE, h_config_save_wont_delete, PREF_MISC, 0},
3288 {"save-will-quote-leading-froms", NULL,
3289 F_QUOTE_ALL_FROMS, h_config_quote_all_froms, PREF_MISC, 0},
3290 {"scramble-message-id", "Scramble the Message-ID When Sending",
3291 F_ROT13_MESSAGE_ID, h_config_scramble_message_id, PREF_MISC, 0},
3292 {"select-without-confirm", "Select Ctrl-T Foldername Without Confirming",
3293 F_SELECT_WO_CONFIRM, h_config_select_wo_confirm, PREF_MISC, 0},
3294 {"show-cursor", NULL,
3295 F_SHOW_CURSOR, h_config_show_cursor, PREF_MISC, 0},
3296 {"show-plain-text-internally", NULL,
3297 F_SHOW_TEXTPLAIN_INT, h_config_textplain_int, PREF_MISC, 0},
3298 {"show-selected-in-boldface", "Show Selected in Boldface",
3299 F_SELECTED_SHOWN_BOLD, h_config_select_in_bold, PREF_MISC, 0},
3300 {"slash-collapses-entire-thread", NULL,
3301 F_SLASH_COLL_ENTIRE, h_config_slash_coll_entire, PREF_MISC, 0},
3302 #ifdef _WINDOWS
3303 {"store-window-position-in-config", "Store Window Position in Config",
3304 F_STORE_WINPOS_IN_CONFIG, h_config_winpos_in_config, PREF_MISC, 0},
3305 #endif
3306 {"suppress-asterisks-in-password-prompt", "Suppress Asterisks in Password Prompt",
3307 F_QUELL_ASTERISKS, h_config_quell_asterisks,
3308 PREF_MISC, 0},
3309 {"quell-attachment-extension-warn", "Suppress Attachment Extension Warning",
3310 F_QUELL_ATTACH_EXT_WARN, h_config_quell_attach_ext_warn,
3311 PREF_MISC, 0},
3312 {"quell-attachment-extra-prompt", "Suppress Attachment Extra Prompt",
3313 F_QUELL_ATTACH_EXTRA_PROMPT, h_config_quell_attach_extra_prompt,
3314 PREF_MISC, 0},
3315 {"quell-berkeley-format-timezone", "Suppress Berkeley Format Timezone",
3316 F_QUELL_BEZERK_TIMEZONE, h_config_no_bezerk_zone, PREF_MISC, 0},
3317 {"quell-content-id", "Suppress Content-ID",
3318 F_QUELL_CONTENT_ID, h_config_quell_content_id, PREF_MISC, 0},
3319 {"quell-filtering-done-message", "Suppress Filtering Done Message",
3320 F_QUELL_FILTER_DONE_MSG, h_config_quell_filtering_done_message,
3321 PREF_MISC, 0},
3322 {"quell-filtering-messages", "Suppress Filtering Messages",
3323 F_QUELL_FILTER_MSGS, h_config_quell_filtering_messages,
3324 PREF_MISC, 0},
3325 {"quell-imap-envelope-update", "Suppress IMAP Envelope Update",
3326 F_QUELL_IMAP_ENV_CB, h_config_quell_imap_env, PREF_MISC, 0},
3327 {"quell-lock-failure-warnings", "Suppress Lock Failure Warnings",
3328 F_QUELL_LOCK_FAILURE_MSGS, h_config_quell_lock_failure_warnings,
3329 PREF_MISC, 0},
3330 {"quell-maildomain-warning", "Suppress Maildomain Warning",
3331 F_QUELL_MAILDOMAIN_WARNING, h_config_quell_domain_warn, PREF_MISC, 0},
3332 {"quell-news-envelope-update", "Suppress News Envelope Update",
3333 F_QUELL_NEWS_ENV_CB, h_config_quell_news_env, PREF_MISC, 0},
3334 #ifdef _WINDOWS
3335 {"quell-ssl-largeblocks", "Prevent SSL Largeblocks",
3336 F_QUELL_SSL_LARGEBLOCKS, h_config_quell_ssl_largeblocks, PREF_MISC, 0},
3337 #endif
3338 {"quell-status-message-beeping", "Suppress Status Message Beeping",
3339 F_QUELL_BEEPS, h_config_quell_beeps, PREF_MISC, 0},
3340 {"quell-timezone-comment-when-sending", "Suppress Timezone Comment When Sending",
3341 F_QUELL_TIMEZONE, h_config_quell_tz_comment, PREF_MISC, 0},
3342 {"suppress-user-agent-when-sending", NULL,
3343 F_QUELL_USERAGENT, h_config_suppress_user_agent, PREF_MISC, 1},
3344 {"tab-checks-recent", "Tab Checks for Recent Messages",
3345 F_TAB_CHK_RECENT, h_config_tab_checks_recent, PREF_MISC, 0},
3346 {"termdef-takes-precedence", NULL,
3347 F_TCAP_WINS, h_config_termcap_wins, PREF_MISC, 0},
3348 {"try-alternative-authentication-driver-first", NULL,
3349 F_PREFER_ALT_AUTH, h_config_alt_auth, PREF_MISC, 0},
3350 {"unselect-will-not-advance", NULL,
3351 F_UNSELECT_WONT_ADVANCE, h_config_unsel_wont_advance, PREF_MISC, 0},
3352 {"use-current-dir", "Use Current Directory",
3353 F_USE_CURRENT_DIR, h_config_use_current_dir, PREF_MISC, 0},
3354 {"use-function-keys", NULL,
3355 F_USE_FK, h_config_use_fk, PREF_OS_USFK, 0},
3356 {"use-regular-startup-rule-for-stayopen-folders", "Use Regular Startup Rule for Stayopen Folders",
3357 F_STARTUP_STAYOPEN, h_config_use_reg_start_for_stayopen, PREF_MISC, 0},
3358 {"use-resent-to-in-rules", "Use Resent-To in Rules",
3359 F_USE_RESENTTO, h_config_use_resentto, PREF_MISC, 0},
3360 {"use-subshell-for-suspend", "Use Subshell for Suspend",
3361 F_SUSPEND_SPAWNS, h_config_suspend_spawns, PREF_OS_SPWN, 0},
3362 #ifndef _WINDOWS
3363 {"use-system-translation", NULL,
3364 F_USE_SYSTEM_TRANS, h_config_use_system_translation, PREF_MISC, 0},
3365 #endif
3367 /* Hidden Features */
3368 {"old-growth", NULL,
3369 F_OLD_GROWTH, NO_HELP, PREF_NONE, 0},
3370 {"disable-config-cmd", NULL,
3371 F_DISABLE_CONFIG_SCREEN, h_config_disable_config_cmd, PREF_HIDDEN, 0},
3372 {"disable-keyboard-lock-cmd", NULL,
3373 F_DISABLE_KBLOCK_CMD, h_config_disable_kb_lock, PREF_HIDDEN, 0},
3374 {"disable-password-cmd", NULL,
3375 F_DISABLE_PASSWORD_CMD, h_config_disable_password_cmd, PREF_HIDDEN, 0},
3376 {"disable-pipes-in-sigs", NULL,
3377 F_DISABLE_PIPES_IN_SIGS, h_config_disable_pipes_in_sigs, PREF_HIDDEN, 0},
3378 {"disable-pipes-in-templates", NULL,
3379 F_DISABLE_PIPES_IN_TEMPLATES, h_config_disable_pipes_in_templates,
3380 PREF_HIDDEN, 0},
3381 {"disable-roles-setup-cmd", NULL,
3382 F_DISABLE_ROLES_SETUP, h_config_disable_roles_setup, PREF_HIDDEN, 0},
3383 {"disable-roles-sig-edit", NULL,
3384 F_DISABLE_ROLES_SIGEDIT, h_config_disable_roles_sigedit, PREF_HIDDEN, 0},
3385 {"disable-roles-template-edit", NULL,
3386 F_DISABLE_ROLES_TEMPLEDIT, h_config_disable_roles_templateedit,
3387 PREF_HIDDEN, 0},
3388 {"disable-setlocale-collate", NULL,
3389 F_DISABLE_SETLOCALE_COLLATE, h_config_disable_collate, PREF_HIDDEN, 0},
3390 {"disable-shared-namespaces", NULL,
3391 F_DISABLE_SHARED_NAMESPACES, h_config_disable_shared, PREF_HIDDEN, 0},
3392 {"disable-signature-edit-cmd", NULL,
3393 F_DISABLE_SIGEDIT_CMD, h_config_disable_signature_edit, PREF_HIDDEN, 0},
3394 {"enable-delete-before-writing", NULL,
3395 F_ENABLE_DEL_WHEN_WRITING, h_config_delete_before_writing, PREF_HIDDEN, 0},
3396 {"new-thread-on-blank-subject", "New Thread on Blank Subject",
3397 F_NEW_THREAD_ON_BLANK_SUBJECT, h_config_new_thread_blank_subject, PREF_HIDDEN, 1},
3398 {"quell-personal-name-prompt", NULL,
3399 F_QUELL_PERSONAL_NAME_PROMPT, h_config_quell_personal_name_prompt, PREF_HIDDEN, 0},
3400 {"quell-user-id-prompt", "Quell User ID Prompt",
3401 F_QUELL_USER_ID_PROMPT, h_config_quell_user_id_prompt, PREF_HIDDEN, 0},
3402 #ifdef SMIME
3403 {"smime-dont-do-smime", "S/MIME -- Turn off S/MIME",
3404 F_DONT_DO_SMIME, h_config_smime_dont_do_smime, PREF_HIDDEN, 0},
3405 {"smime-encrypt-by-default", "S/MIME -- Encrypt by Default",
3406 F_ENCRYPT_DEFAULT_ON, h_config_smime_encrypt_by_default, PREF_HIDDEN, 0},
3407 {"smime-remember-passphrase", "S/MIME -- Remember S/MIME Passphrase",
3408 F_REMEMBER_SMIME_PASSPHRASE, h_config_smime_remember_passphrase, PREF_HIDDEN, 0},
3409 {"smime-sign-by-default", "S/MIME -- Sign by Default",
3410 F_SIGN_DEFAULT_ON, h_config_smime_sign_by_default, PREF_HIDDEN, 0},
3411 {"smime-use-store-only", "S/MIME -- Validate Using Certificate Store Only",
3412 F_USE_CERT_STORE_ONLY, h_config_smime_use_cert_store, PREF_HIDDEN, 1},
3413 #ifdef APPLEKEYCHAIN
3414 {"publiccerts-in-keychain", "S/MIME -- Public Certs in MacOS Keychain",
3415 F_PUBLICCERTS_IN_KEYCHAIN, h_config_smime_pubcerts_in_keychain, PREF_HIDDEN, 0},
3416 #endif
3417 #endif
3418 {"selectable-item-nobold", NULL,
3419 F_SLCTBL_ITEM_NOBOLD, NO_HELP, PREF_NONE, 0},
3420 {"send-confirms-only-expanded", NULL, /* exposed in Web Alpine */
3421 F_SEND_CONFIRM_ON_EXPAND, h_config_send_confirms_only_expanded, PREF_HIDDEN, 0},
3422 {"enable-jump-cmd", NULL, /* exposed in Web Alpine */
3423 F_ENABLE_JUMP_CMD, h_config_enable_jump_command, PREF_HIDDEN, 0},
3424 {"enable-newmail-sound", NULL, /* exposed in Web Alpine */
3425 F_ENABLE_NEWMAIL_SOUND, h_config_enable_newmail_sound, PREF_HIDDEN, 0},
3426 {"render-html-internally", NULL, /* exposed in Web Alpine */
3427 F_RENDER_HTML_INTERNALLY, h_config_render_html_internally, PREF_HIDDEN, 0}
3430 return((index >= 0 && index < (sizeof(feat_list)/sizeof(feat_list[0])))
3431 ? &feat_list[index] : NULL);
3436 * feature_list_index -- return index of given feature id in
3437 * feature list
3440 feature_list_index(int id)
3442 FEATURE_S *feature;
3443 int i;
3445 for(i = 0; (feature = feature_list(i)); i++)
3446 if(id == feature->id)
3447 return(i);
3449 return(-1);
3454 * feature_list_name -- return the given feature id's corresponding name
3456 char *
3457 feature_list_name(int id)
3459 FEATURE_S *f;
3461 return((f = feature_list(feature_list_index(id))) ? f->name : "");
3466 feature_list_id(char *name)
3468 FEATURE_S *f;
3469 int i;
3471 for(i = 0; (f = feature_list(i)); i++)
3472 if(!strucmp(f->name, name))
3473 return(f->id);
3475 return(-1);
3480 * feature_list_help -- return the given feature id's corresponding help
3482 HelpType
3483 feature_list_help(int id)
3485 FEATURE_S *f;
3487 return((f = feature_list(feature_list_index(id))) ? f->help : NO_HELP);
3492 * All the arguments past "list" are the backwards compatibility hacks.
3494 void
3495 process_feature_list(struct pine *ps, char **list, int old_growth, int hir, int osr)
3497 register char *q;
3498 char **p,
3499 *lvalue[BM_SIZE * 8];
3500 int i,
3501 yorn;
3502 long l;
3503 FEATURE_S *feat;
3506 /* clear all previous settings and reset them to default */
3507 for(i = 0; (feat = feature_list(i)) != NULL; i++)
3508 F_SET(feat->id, ps, feat->defval);
3510 /* backwards compatibility */
3511 if(hir)
3512 F_TURN_ON(F_INCLUDE_HEADER, ps);
3514 /* ditto */
3515 if(osr)
3516 F_TURN_ON(F_SIG_AT_BOTTOM, ps);
3518 /* ditto */
3519 if(old_growth)
3520 set_old_growth_bits(ps, 0);
3522 /* now run through the list (global, user, and cmd_line lists are here) */
3523 if(list){
3524 for(p = list; (q = *p) != NULL; p++){
3525 if(struncmp(q, "no-", 3) == 0){
3526 yorn = 0;
3527 q += 3;
3528 }else{
3529 yorn = 1;
3532 for(i = 0; (feat = feature_list(i)) != NULL; i++){
3533 if(strucmp(q, feat->name) == 0){
3534 if(feat->id == F_OLD_GROWTH){
3535 set_old_growth_bits(ps, yorn);
3536 }else{
3537 F_SET(feat->id, ps, yorn);
3539 break;
3543 /* if it wasn't in that list */
3544 if(feat == NULL)
3545 dprint((1,"Unrecognized feature in feature-list (%s%s)\n",
3546 (yorn ? "" : "no-"), q ? q : "?"));
3551 * Turn on gratuitous '>From ' quoting, if requested...
3553 mail_parameters(NULL, SET_FROMWIDGET,
3554 F_ON(F_QUOTE_ALL_FROMS, ps) ? VOIDT : NIL);
3557 * Turn off .lock creation complaints...
3559 if(F_ON(F_QUELL_LOCK_FAILURE_MSGS, ps))
3560 mail_parameters(NULL, SET_LOCKEACCESERROR, (void *) 0);
3563 * Turn on quelling of pseudo message.
3565 if(F_ON(F_QUELL_INTERNAL_MSG,ps_global))
3566 mail_parameters(NULL, SET_USERHASNOLIFE, (void *) 1);
3568 l = F_ON(F_MULNEWSRC_HOSTNAMES_AS_TYPED,ps_global) ? 0L : 1L;
3569 mail_parameters(NULL, SET_NEWSRCCANONHOST, (void *) l);
3571 ps->pass_ctrl_chars = F_ON(F_PASS_CONTROL_CHARS,ps_global) ? 1 : 0;
3572 ps->pass_c1_ctrl_chars = F_ON(F_PASS_C1_CONTROL_CHARS,ps_global) ? 1 : 0;
3574 #ifndef _WINDOWS
3575 if(F_ON(F_QUELL_BEZERK_TIMEZONE,ps_global))
3576 mail_parameters(NULL, SET_NOTIMEZONES, (void *) 1);
3577 #endif
3579 if(F_ON(F_USE_FK, ps))
3580 ps->orig_use_fkeys = 1;
3582 /* Will we have to build a new list? */
3583 if(!(old_growth || hir || osr))
3584 return;
3587 * Build a new list for feature-list. The only reason we ever need to
3588 * do this is if one of the obsolete options is being converted
3589 * into a feature-list item, and it isn't already included in the user's
3590 * feature-list.
3592 i = 0;
3593 for(p = LVAL(&ps->vars[V_FEATURE_LIST], Main);
3594 p && (q = *p); p++){
3595 /* already have it or cancelled it, don't need to add later */
3596 if(hir && (strucmp(q, "include-header-in-reply") == 0 ||
3597 strucmp(q, "no-include-header-in-reply") == 0)){
3598 hir = 0;
3599 }else if(osr && (strucmp(q, "signature-at-bottom") == 0 ||
3600 strucmp(q, "no-signature-at-bottom") == 0)){
3601 osr = 0;
3602 }else if(old_growth && (strucmp(q, "old-growth") == 0 ||
3603 strucmp(q, "no-old-growth") == 0)){
3604 old_growth = 0;
3606 lvalue[i++] = cpystr(q);
3609 /* check to see if we still need to build a new list */
3610 if(!(old_growth || hir || osr))
3611 return;
3613 if(hir)
3614 lvalue[i++] = "include-header-in-reply";
3615 if(osr)
3616 lvalue[i++] = "signature-at-bottom";
3617 if(old_growth)
3618 lvalue[i++] = "old-growth";
3619 lvalue[i] = NULL;
3620 set_variable_list(V_FEATURE_LIST, lvalue, TRUE, Main);
3624 void
3625 set_current_pattern_vals(struct pine *ps)
3627 struct variable *vars = ps->vars;
3629 set_current_val(&vars[V_PATTERNS], TRUE, TRUE);
3630 set_current_val(&vars[V_PAT_ROLES], TRUE, TRUE);
3631 set_current_val(&vars[V_PAT_FILTS], TRUE, TRUE);
3632 set_current_val(&vars[V_PAT_FILTS_OLD], TRUE, TRUE);
3633 set_current_val(&vars[V_PAT_SCORES], TRUE, TRUE);
3634 set_current_val(&vars[V_PAT_SCORES_OLD], TRUE, TRUE);
3635 set_current_val(&vars[V_PAT_INCOLS], TRUE, TRUE);
3636 set_current_val(&vars[V_PAT_OTHER], TRUE, TRUE);
3637 set_current_val(&vars[V_PAT_SRCH], TRUE, TRUE);
3640 * If old pattern variable (V_PATTERNS) is set and the new ones aren't
3641 * in the config file, then convert the old data into the new variables.
3642 * It isn't quite that simple, though, because we don't store unset
3643 * variables in remote pinercs. Check for the variables but if we
3644 * don't find any of them, also check the version number. This change was
3645 * made in version 4.30. We could just check that except that we're
3646 * worried somebody will make an incompatible version number change in
3647 * their local version, and will break this. So we check both the
3648 * version # and the var_in_pinerc things to be safer.
3650 if(vars[V_PATTERNS].current_val.l
3651 && vars[V_PATTERNS].current_val.l[0]
3652 && !var_in_pinerc(vars[V_PAT_ROLES].name)
3653 && !var_in_pinerc(vars[V_PAT_FILTS].name)
3654 && !var_in_pinerc(vars[V_PAT_FILTS_OLD].name)
3655 && !var_in_pinerc(vars[V_PAT_SCORES].name)
3656 && !var_in_pinerc(vars[V_PAT_SCORES_OLD].name)
3657 && !var_in_pinerc(vars[V_PAT_INCOLS].name)
3658 && isdigit((unsigned char) ps->pine_pre_vers[0])
3659 && ps->pine_pre_vers[1] == '.'
3660 && isdigit((unsigned char) ps->pine_pre_vers[2])
3661 && isdigit((unsigned char) ps->pine_pre_vers[3])
3662 && strncmp(ps->pine_pre_vers, "4.30", 4) < 0){
3663 convert_pattern_data();
3667 * Otherwise, if FILTS_OLD is set and FILTS isn't in the config file,
3668 * convert FILTS_OLD to FILTS. Same for SCORES.
3669 * The reason FILTS was changed was so we could change the
3670 * semantics of how rules work when there are pieces in the rule that
3671 * we don't understand. At the same time as the FILTS change we added
3672 * a rule to detect 8bitSubjects. So a user might have a filter that
3673 * deletes messages with 8bitSubjects. The problem is that that same
3674 * filter in a FILTS_OLD pine would match because it would ignore the
3675 * 8bitSubject part of the pattern and match on the rest. So we changed
3676 * the semantics so that rules with unknown bits would be ignored
3677 * instead of used. We had to change variable names at the same time
3678 * because we were adding the 8bit thing and the old pines are still
3679 * out there. Filters and Scores can both be dangerous. Roles, Colors,
3680 * and Other seem less dangerous so not worth adding a new variable.
3681 * This was changed in 4.50.
3683 else{
3684 if(vars[V_PAT_FILTS_OLD].current_val.l
3685 && vars[V_PAT_FILTS_OLD].current_val.l[0]
3686 && !var_in_pinerc(vars[V_PAT_FILTS].name)
3687 && !var_in_pinerc(vars[V_PAT_SCORES].name)
3688 && isdigit((unsigned char) ps->pine_pre_vers[0])
3689 && ps->pine_pre_vers[1] == '.'
3690 && isdigit((unsigned char) ps->pine_pre_vers[2])
3691 && isdigit((unsigned char) ps->pine_pre_vers[3])
3692 && strncmp(ps->pine_pre_vers, "4.50", 4) < 0){
3693 convert_filts_pattern_data();
3696 if(vars[V_PAT_SCORES_OLD].current_val.l
3697 && vars[V_PAT_SCORES_OLD].current_val.l[0]
3698 && !var_in_pinerc(vars[V_PAT_FILTS].name)
3699 && !var_in_pinerc(vars[V_PAT_SCORES].name)
3700 && isdigit((unsigned char) ps->pine_pre_vers[0])
3701 && ps->pine_pre_vers[1] == '.'
3702 && isdigit((unsigned char) ps->pine_pre_vers[2])
3703 && isdigit((unsigned char) ps->pine_pre_vers[3])
3704 && strncmp(ps->pine_pre_vers, "4.50", 4) < 0){
3705 convert_scores_pattern_data();
3709 if(vars[V_PAT_ROLES].post_user_val.l)
3710 ps_global->ew_for_role_take = Post;
3711 else
3712 ps_global->ew_for_role_take = Main;
3714 if(vars[V_PAT_FILTS].post_user_val.l)
3715 ps_global->ew_for_filter_take = Post;
3716 else
3717 ps_global->ew_for_filter_take = Main;
3719 if(vars[V_PAT_SCORES].post_user_val.l)
3720 ps_global->ew_for_score_take = Post;
3721 else
3722 ps_global->ew_for_score_take = Main;
3724 if(vars[V_PAT_INCOLS].post_user_val.l)
3725 ps_global->ew_for_incol_take = Post;
3726 else
3727 ps_global->ew_for_incol_take = Main;
3729 if(vars[V_PAT_OTHER].post_user_val.l)
3730 ps_global->ew_for_other_take = Post;
3731 else
3732 ps_global->ew_for_other_take = Main;
3734 if(vars[V_PAT_SRCH].post_user_val.l)
3735 ps_global->ew_for_srch_take = Post;
3736 else
3737 ps_global->ew_for_srch_take = Main;
3742 * Foreach of the config files;
3743 * transfer the data to the new variables.
3745 void
3746 convert_pattern_data(void)
3748 convert_pinerc_patterns(PAT_USE_MAIN);
3749 convert_pinerc_patterns(PAT_USE_POST);
3753 void
3754 convert_filts_pattern_data(void)
3756 convert_pinerc_filts_patterns(PAT_USE_MAIN);
3757 convert_pinerc_filts_patterns(PAT_USE_POST);
3761 void
3762 convert_scores_pattern_data(void)
3764 convert_pinerc_scores_patterns(PAT_USE_MAIN);
3765 convert_pinerc_scores_patterns(PAT_USE_POST);
3770 * Foreach of the four variables, transfer the data for this config file
3771 * from the old patterns variable. We don't have to convert OTHER patterns
3772 * or SRCH patterns because they didn't exist in pines without patterns-other.
3774 * If the original variable had patlines with type File then we convert
3775 * all of the individual patterns to type Lit, because each pattern can
3776 * be of any category. Lit patterns are better tested, anyway.
3778 void
3779 convert_pinerc_patterns(long int use_flags)
3781 long old_rflags;
3782 long rflags;
3783 PAT_S *pat;
3784 PAT_STATE pstate;
3785 ACTION_S *act;
3787 old_rflags = (ROLE_OLD_PAT | use_flags);
3789 rflags = 0L;
3790 if(any_patterns(old_rflags, &pstate)){
3791 dprint((2, "converting old patterns to new (%s)\n", (use_flags == PAT_USE_MAIN) ? "Main" : "Post"));
3792 for(pat = first_pattern(&pstate);
3793 pat;
3794 pat = next_pattern(&pstate)){
3795 if((act = pat->action) != NULL){
3796 if(act->is_a_role &&
3797 add_to_pattern(pat, ROLE_DO_ROLES | use_flags))
3798 rflags |= ROLE_DO_ROLES;
3799 if(act->is_a_incol &&
3800 add_to_pattern(pat, ROLE_DO_INCOLS | use_flags))
3801 rflags |= ROLE_DO_INCOLS;
3802 if(act->is_a_score &&
3803 add_to_pattern(pat, ROLE_DO_SCORES | use_flags))
3804 rflags |= ROLE_DO_SCORES;
3805 if(act->is_a_filter &&
3806 add_to_pattern(pat, ROLE_DO_FILTER | use_flags))
3807 rflags |= ROLE_DO_FILTER;
3811 if(rflags)
3812 if(write_patterns(rflags | use_flags))
3813 dprint((1,
3814 "Trouble converting patterns to new variable\n"));
3820 * If the original variable had patlines with type File then we convert
3821 * all of the individual patterns to type Lit, because each pattern can
3822 * be of any category. Lit patterns are better tested, anyway.
3824 void
3825 convert_pinerc_filts_patterns(long int use_flags)
3827 long old_rflags;
3828 long rflags;
3829 PAT_S *pat;
3830 PAT_STATE pstate;
3831 ACTION_S *act;
3833 old_rflags = (ROLE_OLD_FILT | use_flags);
3835 rflags = 0L;
3836 if(any_patterns(old_rflags, &pstate)){
3837 dprint((2, "converting old filter patterns to new (%s)\n", (use_flags == PAT_USE_MAIN) ? "Main" : "Post"));
3838 for(pat = first_pattern(&pstate);
3839 pat;
3840 pat = next_pattern(&pstate)){
3841 if((act = pat->action) != NULL){
3842 if(act->is_a_filter &&
3843 add_to_pattern(pat, ROLE_DO_FILTER | use_flags))
3844 rflags |= ROLE_DO_FILTER;
3848 if(rflags)
3849 if(write_patterns(rflags | use_flags))
3850 dprint((1,
3851 "Trouble converting filter patterns to new variable\n"));
3857 * If the original variable had patlines with type File then we convert
3858 * all of the individual patterns to type Lit, because each pattern can
3859 * be of any category. Lit patterns are better tested, anyway.
3861 void
3862 convert_pinerc_scores_patterns(long int use_flags)
3864 long old_rflags;
3865 long rflags;
3866 PAT_S *pat;
3867 PAT_STATE pstate;
3868 ACTION_S *act;
3870 old_rflags = (ROLE_OLD_SCORE | use_flags);
3872 rflags = 0L;
3873 if(any_patterns(old_rflags, &pstate)){
3874 dprint((2, "converting old scores patterns to new (%s)\n", (use_flags == PAT_USE_MAIN) ? "Main" : "Post"));
3875 for(pat = first_pattern(&pstate);
3876 pat;
3877 pat = next_pattern(&pstate)){
3878 if((act = pat->action) != NULL){
3879 if(act->is_a_score &&
3880 add_to_pattern(pat, ROLE_DO_SCORES | use_flags))
3881 rflags |= ROLE_DO_SCORES;
3885 if(rflags)
3886 if(write_patterns(rflags | use_flags))
3887 dprint((1,
3888 "Trouble converting scores patterns to new variable\n"));
3894 * set_old_growth_bits - Command used to set or unset old growth set
3895 * of features
3897 void
3898 set_old_growth_bits(struct pine *ps, int val)
3900 int i;
3902 for(i = 1; i <= F_FEATURE_LIST_COUNT; i++)
3903 if(test_old_growth_bits(ps, i))
3904 F_SET(i, ps, val);
3910 * test_old_growth_bits - Test to see if all the old growth bits are on,
3911 * *or* if a particular feature index is in the old
3912 * growth set.
3914 * WEIRD ALERT: if index == F_OLD_GROWTH bit values are tested
3915 * otherwise a bits existence in the set is tested!!!
3917 * BUG: this will break if an old growth feature number is ever >= 32.
3920 test_old_growth_bits(struct pine *ps, int index)
3923 * this list defines F_OLD_GROWTH set
3925 static unsigned long old_growth_bits = ((1 << F_ENABLE_FULL_HDR) |
3926 (1 << F_ENABLE_PIPE) |
3927 (1 << F_ENABLE_TAB_COMPLETE) |
3928 (1 << F_QUIT_WO_CONFIRM) |
3929 (1 << F_ENABLE_JUMP) |
3930 (1 << F_ENABLE_ALT_ED) |
3931 (1 << F_ENABLE_BOUNCE) |
3932 (1 << F_ENABLE_AGG_OPS) |
3933 (1 << F_ENABLE_FLAG) |
3934 (1 << F_CAN_SUSPEND));
3935 if(index >= 32)
3936 return(0);
3938 if(index == F_OLD_GROWTH){
3939 for(index = 1; index <= F_FEATURE_LIST_COUNT; index++)
3940 if(((1 << index) & old_growth_bits) && F_OFF(index, ps))
3941 return(0);
3943 return(1);
3945 else
3946 return((1 << index) & old_growth_bits);
3951 * Side effect is that the appropriate global variable is set, and the
3952 * appropriate current_val is set.
3954 void
3955 cur_rule_value(struct variable *var, int expand, int cmdline)
3957 int i;
3958 NAMEVAL_S *v;
3960 set_current_val(var, expand, cmdline);
3962 if(var == &ps_global->vars[V_SAVED_MSG_NAME_RULE]){
3963 if(ps_global->VAR_SAVED_MSG_NAME_RULE)
3964 for(i = 0; (v = save_msg_rules(i)); i++)
3965 if(!strucmp(ps_global->VAR_SAVED_MSG_NAME_RULE, S_OR_L(v))){
3966 ps_global->save_msg_rule = v->value;
3967 break;
3970 #ifndef _WINDOWS
3971 else if(var == &ps_global->vars[V_COLOR_STYLE]){
3972 if(ps_global->VAR_COLOR_STYLE)
3973 for(i = 0; (v = col_style(i)); i++)
3974 if(!strucmp(ps_global->VAR_COLOR_STYLE, S_OR_L(v))){
3975 ps_global->color_style = v->value;
3976 break;
3979 #endif
3980 else if(var == &ps_global->vars[V_INDEX_COLOR_STYLE]){
3981 if(ps_global->VAR_INDEX_COLOR_STYLE)
3982 for(i = 0; (v = index_col_style(i)); i++)
3983 if(!strucmp(ps_global->VAR_INDEX_COLOR_STYLE, S_OR_L(v))){
3984 ps_global->index_color_style = v->value;
3985 break;
3988 else if(var == &ps_global->vars[V_TITLEBAR_COLOR_STYLE]){
3989 if(ps_global->VAR_TITLEBAR_COLOR_STYLE)
3990 for(i = 0; (v = titlebar_col_style(i)); i++)
3991 if(!strucmp(ps_global->VAR_TITLEBAR_COLOR_STYLE, S_OR_L(v))){
3992 ps_global->titlebar_color_style = v->value;
3993 break;
3996 else if(var == &ps_global->vars[V_FCC_RULE]){
3997 if(ps_global->VAR_FCC_RULE)
3998 for(i = 0; (v = fcc_rules(i)); i++)
3999 if(!strucmp(ps_global->VAR_FCC_RULE, S_OR_L(v))){
4000 ps_global->fcc_rule = v->value;
4001 break;
4004 else if(var == &ps_global->vars[V_GOTO_DEFAULT_RULE]){
4005 if(ps_global->VAR_GOTO_DEFAULT_RULE)
4006 for(i = 0; (v = goto_rules(i)); i++)
4007 if(!strucmp(ps_global->VAR_GOTO_DEFAULT_RULE, S_OR_L(v))){
4008 ps_global->goto_default_rule = v->value;
4009 break;
4012 else if(var == &ps_global->vars[V_INCOMING_STARTUP]){
4013 if(ps_global->VAR_INCOMING_STARTUP)
4014 for(i = 0; (v = incoming_startup_rules(i)); i++)
4015 if(!strucmp(ps_global->VAR_INCOMING_STARTUP, S_OR_L(v))){
4016 ps_global->inc_startup_rule = v->value;
4017 break;
4020 else if(var == &ps_global->vars[V_PRUNING_RULE]){
4021 if(ps_global->VAR_PRUNING_RULE)
4022 for(i = 0; (v = pruning_rules(i)); i++)
4023 if(!strucmp(ps_global->VAR_PRUNING_RULE, S_OR_L(v))){
4024 ps_global->pruning_rule = v->value;
4025 break;
4028 else if(var == &ps_global->vars[V_REOPEN_RULE]){
4029 if(ps_global->VAR_REOPEN_RULE)
4030 for(i = 0; (v = reopen_rules(i)); i++)
4031 if(!strucmp(ps_global->VAR_REOPEN_RULE, S_OR_L(v))){
4032 ps_global->reopen_rule = v->value;
4033 break;
4036 else if(var == &ps_global->vars[V_FLD_SORT_RULE]){
4037 if(ps_global->VAR_FLD_SORT_RULE)
4038 for(i = 0; (v = fld_sort_rules(i)); i++)
4039 if(!strucmp(ps_global->VAR_FLD_SORT_RULE, S_OR_L(v))){
4040 ps_global->fld_sort_rule = v->value;
4041 break;
4044 else if(var == &ps_global->vars[V_AB_SORT_RULE]){
4045 if(ps_global->VAR_AB_SORT_RULE)
4046 for(i = 0; (v = ab_sort_rules(i)); i++)
4047 if(!strucmp(ps_global->VAR_AB_SORT_RULE, S_OR_L(v))){
4048 ps_global->ab_sort_rule = v->value;
4049 break;
4052 else if(var == &ps_global->vars[V_THREAD_DISP_STYLE]){
4053 if(ps_global->VAR_THREAD_DISP_STYLE)
4054 for(i = 0; (v = thread_disp_styles(i)); i++)
4055 if(!strucmp(ps_global->VAR_THREAD_DISP_STYLE, S_OR_L(v))){
4056 ps_global->thread_disp_style = v->value;
4057 break;
4060 else if(var == &ps_global->vars[V_THREAD_INDEX_STYLE]){
4061 if(ps_global->VAR_THREAD_INDEX_STYLE)
4062 for(i = 0; (v = thread_index_styles(i)); i++)
4063 if(!strucmp(ps_global->VAR_THREAD_INDEX_STYLE, S_OR_L(v))){
4064 ps_global->thread_index_style = v->value;
4065 break;
4072 * Standard way to get at save message rules...
4074 NAMEVAL_S *
4075 save_msg_rules(int index)
4077 static NAMEVAL_S save_rules[] = {
4078 {"by-from", NULL, SAV_RULE_FROM},
4079 {"by-nick-of-from", NULL, SAV_RULE_NICK_FROM_DEF},
4080 {"by-nick-of-from-then-from", NULL, SAV_RULE_NICK_FROM},
4081 {"by-fcc-of-from", NULL, SAV_RULE_FCC_FROM_DEF},
4082 {"by-fcc-of-from-then-from", NULL, SAV_RULE_FCC_FROM},
4083 {"by-realname-of-from", NULL, SAV_RULE_RN_FROM_DEF},
4084 {"by-realname-of-from-then-from", NULL, SAV_RULE_RN_FROM},
4085 {"by-sender", NULL, SAV_RULE_SENDER},
4086 {"by-nick-of-sender", NULL, SAV_RULE_NICK_SENDER_DEF},
4087 {"by-nick-of-sender-then-sender", NULL, SAV_RULE_NICK_SENDER},
4088 {"by-fcc-of-sender", NULL, SAV_RULE_FCC_SENDER_DEF},
4089 {"by-fcc-of-sender-then-sender", NULL, SAV_RULE_FCC_SENDER},
4090 {"by-realname-of-sender", NULL, SAV_RULE_RN_SENDER_DEF},
4091 {"by-realname-of-sender-then-sender", NULL, SAV_RULE_RN_SENDER},
4092 {"by-recipient", NULL, SAV_RULE_RECIP},
4093 {"by-nick-of-recip", NULL, SAV_RULE_NICK_RECIP_DEF},
4094 {"by-nick-of-recip-then-recip", NULL, SAV_RULE_NICK_RECIP},
4095 {"by-fcc-of-recip", NULL, SAV_RULE_FCC_RECIP_DEF},
4096 {"by-fcc-of-recip-then-recip", NULL, SAV_RULE_FCC_RECIP},
4097 {"by-realname-of-recip", NULL, SAV_RULE_RN_RECIP_DEF},
4098 {"by-realname-of-recip-then-recip", NULL, SAV_RULE_RN_RECIP},
4099 {"by-replyto", NULL, SAV_RULE_REPLYTO},
4100 {"by-nick-of-replyto", NULL, SAV_RULE_NICK_REPLYTO_DEF},
4101 {"by-nick-of-replyto-then-replyto", NULL, SAV_RULE_NICK_REPLYTO},
4102 {"by-fcc-of-replyto", NULL, SAV_RULE_FCC_REPLYTO_DEF},
4103 {"by-fcc-of-replyto-then-replyto", NULL, SAV_RULE_FCC_REPLYTO},
4104 {"by-realname-of-replyto", NULL, SAV_RULE_RN_REPLYTO_DEF},
4105 {"by-realname-of-replyto-then-replyto", NULL, SAV_RULE_RN_REPLYTO},
4106 {"last-folder-used", NULL, SAV_RULE_LAST},
4107 {"default-folder", NULL, SAV_RULE_DEFLT}
4110 return((index >= 0 && index < (sizeof(save_rules)/sizeof(save_rules[0])))
4111 ? &save_rules[index] : NULL);
4116 * Standard way to get at fcc rules...
4118 NAMEVAL_S *
4119 fcc_rules(int index)
4121 static NAMEVAL_S f_rules[] = {
4122 {"default-fcc", NULL, FCC_RULE_DEFLT},
4123 {"last-fcc-used", NULL, FCC_RULE_LAST},
4124 {"by-recipient", NULL, FCC_RULE_RECIP},
4125 {"by-nickname", NULL, FCC_RULE_NICK},
4126 {"by-nick-then-recip", NULL, FCC_RULE_NICK_RECIP},
4127 {"current-folder", NULL, FCC_RULE_CURRENT}
4130 return((index >= 0 && index < (sizeof(f_rules)/sizeof(f_rules[0])))
4131 ? &f_rules[index] : NULL);
4136 * Standard way to get at addrbook sort rules...
4138 NAMEVAL_S *
4139 ab_sort_rules(int index)
4141 static NAMEVAL_S ab_rules[] = {
4142 {"fullname-with-lists-last", NULL, AB_SORT_RULE_FULL_LISTS},
4143 {"fullname", NULL, AB_SORT_RULE_FULL},
4144 {"nickname-with-lists-last", NULL, AB_SORT_RULE_NICK_LISTS},
4145 {"nickname", NULL, AB_SORT_RULE_NICK},
4146 {"dont-sort", NULL, AB_SORT_RULE_NONE}
4149 return((index >= 0 && index < (sizeof(ab_rules)/sizeof(ab_rules[0])))
4150 ? &ab_rules[index] : NULL);
4155 * Standard way to get at color styles.
4157 NAMEVAL_S *
4158 col_style(int index)
4160 static NAMEVAL_S col_styles[] = {
4161 {"no-color", NULL, COL_NONE},
4162 {"use-termdef", NULL, COL_TERMDEF},
4163 {"force-ansi-8color", NULL, COL_ANSI8},
4164 {"force-ansi-16color", NULL, COL_ANSI16},
4165 {"force-xterm-256color", NULL, COL_ANSI256}
4168 return((index >= 0 && index < (sizeof(col_styles)/sizeof(col_styles[0])))
4169 ? &col_styles[index] : NULL);
4174 * Standard way to get at index color styles.
4176 NAMEVAL_S *
4177 index_col_style(int index)
4179 static NAMEVAL_S ind_col_styles[] = {
4180 {"flip-colors", NULL, IND_COL_FLIP},
4181 {"reverse", NULL, IND_COL_REV},
4182 {"reverse-fg", NULL, IND_COL_FG},
4183 {"reverse-fg-no-ambiguity", NULL, IND_COL_FG_NOAMBIG},
4184 {"reverse-bg", NULL, IND_COL_BG},
4185 {"reverse-bg-no-ambiguity", NULL, IND_COL_BG_NOAMBIG}
4188 return((index >= 0 && index < (sizeof(ind_col_styles)/sizeof(ind_col_styles[0]))) ? &ind_col_styles[index] : NULL);
4193 * Standard way to get at titlebar color styles.
4195 NAMEVAL_S *
4196 titlebar_col_style(int index)
4198 static NAMEVAL_S tbar_col_styles[] = {
4199 {"default", NULL, TBAR_COLOR_DEFAULT},
4200 {"indexline", NULL, TBAR_COLOR_INDEXLINE},
4201 {"reverse-indexline", NULL, TBAR_COLOR_REV_INDEXLINE}
4204 return((index >= 0 && index < (sizeof(tbar_col_styles)/sizeof(tbar_col_styles[0]))) ? &tbar_col_styles[index] : NULL);
4209 * Standard way to get at folder sort rules...
4211 NAMEVAL_S *
4212 fld_sort_rules(int index)
4214 static NAMEVAL_S fdl_rules[] = {
4215 {"alphabetical", NULL, FLD_SORT_ALPHA},
4216 {"alpha-with-dirs-last", NULL, FLD_SORT_ALPHA_DIR_LAST},
4217 {"alpha-with-dirs-first", NULL, FLD_SORT_ALPHA_DIR_FIRST}
4220 return((index >= 0 && index < (sizeof(fdl_rules)/sizeof(fdl_rules[0])))
4221 ? &fdl_rules[index] : NULL);
4226 * Standard way to get at incoming startup rules...
4228 NAMEVAL_S *
4229 incoming_startup_rules(int index)
4231 static NAMEVAL_S is_rules[] = {
4232 {"first-unseen", NULL, IS_FIRST_UNSEEN},
4233 {"first-recent", NULL, IS_FIRST_RECENT},
4234 {"first-important", NULL, IS_FIRST_IMPORTANT},
4235 {"first-important-or-unseen", NULL, IS_FIRST_IMPORTANT_OR_UNSEEN},
4236 {"first-important-or-recent", NULL, IS_FIRST_IMPORTANT_OR_RECENT},
4237 {"first", NULL, IS_FIRST},
4238 {"last", NULL, IS_LAST}
4241 return((index >= 0 && index < (sizeof(is_rules)/sizeof(is_rules[0])))
4242 ? &is_rules[index] : NULL);
4246 NAMEVAL_S *
4247 startup_rules(int index)
4249 static NAMEVAL_S is2_rules[] = {
4250 {"first-unseen", NULL, IS_FIRST_UNSEEN},
4251 {"first-recent", NULL, IS_FIRST_RECENT},
4252 {"first-important", NULL, IS_FIRST_IMPORTANT},
4253 {"first-important-or-unseen", NULL, IS_FIRST_IMPORTANT_OR_UNSEEN},
4254 {"first-important-or-recent", NULL, IS_FIRST_IMPORTANT_OR_RECENT},
4255 {"first", NULL, IS_FIRST},
4256 {"last", NULL, IS_LAST},
4257 {"default", NULL, IS_NOTSET}
4260 return((index >= 0 && index < (sizeof(is2_rules)/sizeof(is2_rules[0])))
4261 ? &is2_rules[index] : NULL);
4266 * Standard way to get at pruning-rule values.
4268 NAMEVAL_S *
4269 pruning_rules(int index)
4271 static NAMEVAL_S pr_rules[] = {
4272 {"ask about rename, ask about deleting","ask-ask", PRUNE_ASK_AND_ASK},
4273 {"ask about rename, don't delete", "ask-no", PRUNE_ASK_AND_NO},
4274 {"always rename, ask about deleting", "yes-ask", PRUNE_YES_AND_ASK},
4275 {"always rename, don't delete", "yes-no", PRUNE_YES_AND_NO},
4276 {"don't rename, ask about deleting", "no-ask", PRUNE_NO_AND_ASK},
4277 {"don't rename, don't delete", "no-no", PRUNE_NO_AND_NO}
4280 return((index >= 0 && index < (sizeof(pr_rules)/sizeof(pr_rules[0])))
4281 ? &pr_rules[index] : NULL);
4286 * Standard way to get at reopen-rule values.
4288 NAMEVAL_S *
4289 reopen_rules(int index)
4291 static NAMEVAL_S ro_rules[] = {
4292 /* TRANSLATORS: short description of a feature option */
4293 {"Always reopen", "yes-yes",
4294 REOPEN_YES_YES},
4295 /* TRANSLATORS: short description of a feature option, default in brackets */
4296 {"Yes for POP/NNTP, Ask about other remote [Yes]", "yes-ask-y",
4297 REOPEN_YES_ASK_Y},
4298 /* TRANSLATORS: short description of a feature option, default in brackets */
4299 {"Yes for POP/NNTP, Ask about other remote [No]", "yes-ask-n",
4300 REOPEN_YES_ASK_N},
4301 /* TRANSLATORS: short description of a feature option */
4302 {"Yes for POP/NNTP, No for other remote", "yes-no",
4303 REOPEN_YES_NO},
4304 /* TRANSLATORS: short description of a feature option, default in brackets */
4305 {"Always ask [Yes]", "ask-ask-y",
4306 REOPEN_ASK_ASK_Y},
4307 /* TRANSLATORS: short description of a feature option, default in brackets */
4308 {"Always ask [No]", "ask-ask-n",
4309 REOPEN_ASK_ASK_N},
4310 /* TRANSLATORS: short description of a feature option, default in brackets */
4311 {"Ask about POP/NNTP [Yes], No for other remote", "ask-no-y",
4312 REOPEN_ASK_NO_Y},
4313 /* TRANSLATORS: short description of a feature option, default in brackets */
4314 {"Ask about POP/NNTP [No], No for other remote", "ask-no-n",
4315 REOPEN_ASK_NO_N},
4316 /* TRANSLATORS: short description of a feature option */
4317 {"Never reopen", "no-no",
4318 REOPEN_NO_NO},
4321 return((index >= 0 && index < (sizeof(ro_rules)/sizeof(ro_rules[0])))
4322 ? &ro_rules[index] : NULL);
4327 * Standard way to get at thread_disp_style values.
4329 NAMEVAL_S *
4330 thread_disp_styles(int index)
4332 static NAMEVAL_S td_styles[] = {
4333 {"none", "none", THREAD_NONE},
4334 {"show-thread-structure", "struct", THREAD_STRUCT},
4335 {"mutt-like", "mutt", THREAD_MUTTLIKE},
4336 {"indent-subject-1", "subj1", THREAD_INDENT_SUBJ1},
4337 {"indent-subject-2", "subj2", THREAD_INDENT_SUBJ2},
4338 {"indent-from-1", "from1", THREAD_INDENT_FROM1},
4339 {"indent-from-2", "from2", THREAD_INDENT_FROM2},
4340 {"show-structure-in-from", "struct-from", THREAD_STRUCT_FROM}
4343 return((index >= 0 && index < (sizeof(td_styles)/sizeof(td_styles[0])))
4344 ? &td_styles[index] : NULL);
4349 * Standard way to get at thread_index_style values.
4351 NAMEVAL_S *
4352 thread_index_styles(int index)
4354 static NAMEVAL_S ti_styles[] = {
4355 {"regular-index-with-expanded-threads", "exp", THRDINDX_EXP},
4356 {"regular-index-with-collapsed-threads","coll", THRDINDX_COLL},
4357 {"separate-index-screen-always", "sep", THRDINDX_SEP},
4358 {"separate-index-screen-except-for-single-messages","sep-auto",
4359 THRDINDX_SEP_AUTO}
4362 return((index >= 0 && index < (sizeof(ti_styles)/sizeof(ti_styles[0])))
4363 ? &ti_styles[index] : NULL);
4368 * Standard way to get at goto default rules...
4370 NAMEVAL_S *
4371 goto_rules(int index)
4373 static NAMEVAL_S g_rules[] = {
4374 {"folder-in-first-collection", NULL, GOTO_FIRST_CLCTN},
4375 {"inbox-or-folder-in-first-collection", NULL, GOTO_INBOX_FIRST_CLCTN},
4376 {"inbox-or-folder-in-recent-collection", NULL, GOTO_INBOX_RECENT_CLCTN},
4377 {"first-collection-with-inbox-default", NULL, GOTO_FIRST_CLCTN_DEF_INBOX},
4378 {"most-recent-folder", NULL, GOTO_LAST_FLDR}
4381 return((index >= 0 && index < (sizeof(g_rules)/sizeof(g_rules[0])))
4382 ? &g_rules[index] : NULL);
4386 NAMEVAL_S *
4387 pat_fldr_types(int index)
4389 static NAMEVAL_S pat_fldr_list[] = {
4390 {"Any", "ANY", FLDR_ANY},
4391 {"News", "NEWS", FLDR_NEWS},
4392 {"Email", "EMAIL", FLDR_EMAIL},
4393 {"Specific (Enter Incoming Nicknames or use ^T)", "SPEC", FLDR_SPECIFIC}
4396 return((index >= 0 &&
4397 index < (sizeof(pat_fldr_list)/sizeof(pat_fldr_list[0])))
4398 ? &pat_fldr_list[index] : NULL);
4402 NAMEVAL_S *
4403 inabook_fldr_types(int indexarg)
4405 static NAMEVAL_S inabook_fldr_list[] = {
4406 {"Don't care, always matches", "E", IAB_EITHER},
4407 {"Yes, in any address book", "YES", IAB_YES},
4408 {"No, not in any address book", "NO", IAB_NO},
4409 {"Yes, in specific address books", "SYES", IAB_SPEC_YES},
4410 {"No, not in any of specific address books", "SNO", IAB_SPEC_NO}
4413 int index = indexarg & IAB_TYPE_MASK;
4415 return((index >= 0 &&
4416 index < (sizeof(inabook_fldr_list)/sizeof(inabook_fldr_list[0])))
4417 ? &inabook_fldr_list[index] : NULL);
4421 NAMEVAL_S *
4422 filter_types(int index)
4424 static NAMEVAL_S filter_type_list[] = {
4425 {"Just Set Message Status", "NONE", FILTER_STATE},
4426 {"Delete", "DEL", FILTER_KILL},
4427 {"Move (Enter folder name(s) in primary collection, or use ^T)",
4428 "FLDR", FILTER_FOLDER}
4431 return((index >= 0 &&
4432 index < (sizeof(filter_type_list)/sizeof(filter_type_list[0])))
4433 ? &filter_type_list[index] : NULL);
4437 NAMEVAL_S *
4438 role_repl_types(int index)
4440 static NAMEVAL_S role_repl_list[] = {
4441 {"Never", "NO", ROLE_REPL_NO},
4442 {"With confirmation", "YES", ROLE_REPL_YES},
4443 {"Without confirmation", "NC", ROLE_REPL_NOCONF}
4446 return((index >= 0 &&
4447 index < (sizeof(role_repl_list)/sizeof(role_repl_list[0])))
4448 ? &role_repl_list[index] : NULL);
4452 NAMEVAL_S *
4453 role_forw_types(int index)
4455 static NAMEVAL_S role_forw_list[] = {
4456 {"Never", "NO", ROLE_FORW_NO},
4457 {"With confirmation", "YES", ROLE_FORW_YES},
4458 {"Without confirmation", "NC", ROLE_FORW_NOCONF}
4461 return((index >= 0 &&
4462 index < (sizeof(role_forw_list)/sizeof(role_forw_list[0])))
4463 ? &role_forw_list[index] : NULL);
4467 NAMEVAL_S *
4468 role_comp_types(int index)
4470 static NAMEVAL_S role_comp_list[] = {
4471 {"Never", "NO", ROLE_COMP_NO},
4472 {"With confirmation", "YES", ROLE_COMP_YES},
4473 {"Without confirmation", "NC", ROLE_COMP_NOCONF}
4476 return((index >= 0 &&
4477 index < (sizeof(role_comp_list)/sizeof(role_comp_list[0])))
4478 ? &role_comp_list[index] : NULL);
4482 NAMEVAL_S *
4483 role_status_types(int index)
4485 static NAMEVAL_S role_status_list[] = {
4486 {"Don't care, always matches", "E", PAT_STAT_EITHER},
4487 {"Yes", "YES", PAT_STAT_YES},
4488 {"No", "NO", PAT_STAT_NO}
4491 return((index >= 0 &&
4492 index < (sizeof(role_status_list)/sizeof(role_status_list[0])))
4493 ? &role_status_list[index] : NULL);
4497 NAMEVAL_S *
4498 msg_state_types(int index)
4500 static NAMEVAL_S msg_state_list[] = {
4501 {"Don't change it", "LV", ACT_STAT_LEAVE},
4502 {"Set this state", "SET", ACT_STAT_SET},
4503 {"Clear this state", "CLR", ACT_STAT_CLEAR}
4506 return((index >= 0 &&
4507 index < (sizeof(msg_state_list)/sizeof(msg_state_list[0])))
4508 ? &msg_state_list[index] : NULL);
4512 #ifdef ENABLE_LDAP
4513 NAMEVAL_S *
4514 ldap_search_rules(int index)
4516 static NAMEVAL_S ldap_search_list[] = {
4517 {"contains", NULL, LDAP_SRCH_CONTAINS},
4518 {"equals", NULL, LDAP_SRCH_EQUALS},
4519 {"begins-with", NULL, LDAP_SRCH_BEGINS},
4520 {"ends-with", NULL, LDAP_SRCH_ENDS}
4523 return((index >= 0 &&
4524 index < (sizeof(ldap_search_list)/sizeof(ldap_search_list[0])))
4525 ? &ldap_search_list[index] : NULL);
4529 NAMEVAL_S *
4530 ldap_search_types(int index)
4532 static NAMEVAL_S ldap_types_list[] = {
4533 {"name", NULL, LDAP_TYPE_CN},
4534 {"surname", NULL, LDAP_TYPE_SUR},
4535 {"givenname", NULL, LDAP_TYPE_GIVEN},
4536 {"email", NULL, LDAP_TYPE_EMAIL},
4537 {"name-or-email", NULL, LDAP_TYPE_CN_EMAIL},
4538 {"surname-or-givenname", NULL, LDAP_TYPE_SUR_GIVEN},
4539 {"sur-or-given-or-name-or-email", NULL, LDAP_TYPE_SEVERAL}
4542 return((index >= 0 &&
4543 index < (sizeof(ldap_types_list)/sizeof(ldap_types_list[0])))
4544 ? &ldap_types_list[index] : NULL);
4548 NAMEVAL_S *
4549 ldap_search_scope(int index)
4551 static NAMEVAL_S ldap_scope_list[] = {
4552 {"base", NULL, LDAP_SCOPE_BASE},
4553 {"onelevel", NULL, LDAP_SCOPE_ONELEVEL},
4554 {"subtree", NULL, LDAP_SCOPE_SUBTREE}
4557 return((index >= 0 &&
4558 index < (sizeof(ldap_scope_list)/sizeof(ldap_scope_list[0])))
4559 ? &ldap_scope_list[index] : NULL);
4561 #endif
4565 * Choose from the global default, command line args, pinerc values to set
4566 * the actual value of the variable that we will use. Start at the top
4567 * and work down from higher to lower precedence.
4568 * For lists, we may inherit values from lower precedence
4569 * versions if that's the way the user specifies it.
4570 * The user can put INHERIT_DEFAULT as the first entry in a list and that
4571 * means it will inherit the current values, for example the values
4572 * from the global_val, or the value from the main_user_val could be
4573 * inherited in the post_user_val.
4575 void
4576 set_current_val(struct variable *var, int expand, int cmdline)
4578 int is_set[5], is_inherit[5];
4579 int i, j, k, cnt, start;
4580 char **tmp, **t, **list[5];
4581 char *p;
4583 dprint((9,
4584 "set_current_val(var=%s%s, expand=%d, cmdline=%d)\n",
4585 (var && var->name) ? var->name : "?",
4586 (var && var->is_list) ? " (list)" : "",
4587 expand, cmdline));
4589 if(!var)
4590 return;
4592 if(var->is_list){ /* variable is a list */
4594 for(j = 0; j < 5; j++){
4595 t = j==0 ? var->global_val.l :
4596 j==1 ? var->main_user_val.l :
4597 j==2 ? var->post_user_val.l :
4598 j==3 ? ((cmdline) ? var->cmdline_val.l : NULL) :
4599 var->fixed_val.l;
4601 is_set[j] = is_inherit[j] = 0;
4602 list[j] = NULL;
4604 if(t){
4605 if(!expand){
4606 is_set[j]++;
4607 list[j] = t;
4609 else{
4610 for(i = 0; t[i]; i++){
4611 if(expand_variables(tmp_20k_buf, SIZEOF_20KBUF, t[i],
4612 0)){
4613 /* successful expand */
4614 is_set[j]++;
4615 list[j] = t;
4616 break;
4621 if(list[j] && list[j][0] && !strcmp(list[j][0],INHERIT))
4622 is_inherit[j]++;
4626 cnt = 0;
4627 start = 0;
4628 /* count how many items in current_val list */
4629 /* Admin wants default, which is global_val. */
4630 if(var->is_fixed && var->fixed_val.l == NULL){
4631 cnt = 0;
4632 if(is_set[0]){
4633 for(; list[0][cnt]; cnt++)
4637 else{
4638 for(j = 0; j < 5; j++){
4639 if(is_set[j]){
4640 if(!is_inherit[j]){
4641 cnt = 0; /* reset */
4642 start = j;
4645 for(i = is_inherit[j] ? 1 : 0; list[j][i]; i++)
4646 cnt++;
4651 free_list_array(&var->current_val.l); /* clean up any old values */
4653 /* check to see if anything is set */
4654 if(is_set[0] + is_set[1] + is_set[2] + is_set[3] + is_set[4] > 0){
4655 var->current_val.l = (char **)fs_get((cnt+1)*sizeof(char *));
4656 tmp = var->current_val.l;
4657 if(var->is_fixed && var->fixed_val.l == NULL){
4658 if(is_set[0]){
4659 for(i = 0; list[0][i]; i++){
4660 if(!expand)
4661 *tmp++ = cpystr(list[0][i]);
4662 else if(expand_variables(tmp_20k_buf, SIZEOF_20KBUF,
4663 list[0][i], 0))
4664 *tmp++ = cpystr(tmp_20k_buf);
4668 else{
4669 for(j = start; j < 5; j++){
4670 if(is_set[j]){
4671 for(i = is_inherit[j] ? 1 : 0; list[j][i]; i++){
4672 if(!expand)
4673 *tmp++ = cpystr(list[j][i]);
4674 else if(expand_variables(tmp_20k_buf,SIZEOF_20KBUF,
4675 list[j][i], 0))
4676 *tmp++ = cpystr(tmp_20k_buf);
4682 *tmp = NULL;
4684 else
4685 var->current_val.l = NULL;
4687 else{ /* variable is not a list */
4688 char *strvar = NULL;
4690 for(j = 0; j < 5; j++){
4692 p = j==0 ? var->fixed_val.p :
4693 j==1 ? ((cmdline) ? var->cmdline_val.p : NULL) :
4694 j==2 ? var->post_user_val.p :
4695 j==3 ? var->main_user_val.p :
4696 var->global_val.p;
4698 is_set[j] = 0;
4700 if(p){
4701 if(!expand){
4702 is_set[j]++;
4703 if(!strvar)
4704 strvar = p;
4706 else if(expand_variables(tmp_20k_buf, SIZEOF_20KBUF, p,
4707 (var == &ps_global->vars[V_MAILCAP_PATH] ||
4708 var == &ps_global->vars[V_MIMETYPE_PATH]))){
4709 is_set[j]++;
4710 if(!strvar)
4711 strvar = p;
4716 /* Admin wants default, which is global_val. */
4717 if(var->is_fixed && var->fixed_val.p == NULL)
4718 strvar = var->global_val.p;
4720 if(var->current_val.p) /* free previous value */
4721 fs_give((void **)&var->current_val.p);
4723 if(strvar){
4724 if(!expand)
4725 var->current_val.p = cpystr(strvar);
4726 else{
4727 expand_variables(tmp_20k_buf, SIZEOF_20KBUF, strvar,
4728 (var == &ps_global->vars[V_MAILCAP_PATH] ||
4729 var == &ps_global->vars[V_MIMETYPE_PATH]));
4730 var->current_val.p = cpystr(tmp_20k_buf);
4733 else
4734 var->current_val.p = NULL;
4737 if(var->is_fixed && !is_inherit[4]){
4738 char **flist;
4739 int fixed_len, user_len;
4742 * sys mgr fixed this variable and user is trying to change it
4744 for(k = 1; !(ps_global->give_fixed_warning &&
4745 ps_global->fix_fixed_warning) && k <= 3; k++){
4746 if(is_set[k]){
4747 if(var->is_list){
4748 t = k==1 ? ((cmdline) ? var->cmdline_val.l : NULL) :
4749 k==2 ? var->post_user_val.l :
4750 var->main_user_val.l;
4752 /* If same length and same contents, don't warn. */
4753 for(flist=var->fixed_val.l; flist && *flist; flist++)
4754 ;/* just counting */
4756 fixed_len = var->fixed_val.l ? (flist - var->fixed_val.l)
4757 : 0;
4758 for(flist=t; flist && *flist; flist++)
4759 ;/* just counting */
4761 user_len = t ? (flist - t) : 0;
4762 if(user_len == fixed_len){
4763 for(i=0; i < user_len; i++){
4764 for(j=0; j < user_len; j++)
4765 if(!strucmp(t[i], var->fixed_val.l[j]))
4766 break;
4768 if(j == user_len){
4769 ps_global->give_fixed_warning = 1;
4770 if(k != 1)
4771 ps_global->fix_fixed_warning = 1;
4773 break;
4777 else{
4778 ps_global->give_fixed_warning = 1;
4779 if(k != 1)
4780 ps_global->fix_fixed_warning = 1;
4783 else{
4784 p = k==1 ? ((cmdline) ? var->cmdline_val.p : NULL) :
4785 k==2 ? var->post_user_val.p :
4786 var->main_user_val.p;
4788 if((var->fixed_val.p && !p) ||
4789 (!var->fixed_val.p && p) ||
4790 (var->fixed_val.p && p && strucmp(var->fixed_val.p, p))){
4791 ps_global->give_fixed_warning = 1;
4792 if(k != 1)
4793 ps_global->fix_fixed_warning = 1;
4802 void
4803 set_news_spec_current_val(int expand, int cmdline)
4805 struct variable *newsvar = &ps_global->vars[V_NEWS_SPEC];
4806 struct variable *fvar = &ps_global->vars[V_FOLDER_SPEC];
4808 /* check to see if it has a value */
4809 set_current_val(newsvar, expand, cmdline);
4812 * If no value, we might want to fake a value. We'll do that if
4813 * there is no news collection already defined in FOLDER_SPEC and if
4814 * there is also an NNTP_SERVER defined.
4816 if(!newsvar->current_val.l && ps_global->VAR_NNTP_SERVER &&
4817 ps_global->VAR_NNTP_SERVER[0] && ps_global->VAR_NNTP_SERVER[0][0] &&
4818 !news_in_folders(fvar)){
4819 char buf[MAXPATH];
4821 newsvar->global_val.l = (char **)fs_get(2 * sizeof(char *));
4822 snprintf(buf, sizeof(buf), "{%.*s/nntp}#news.[]", MAXPATH-20,
4823 ps_global->VAR_NNTP_SERVER[0]); /* MAXPATH = sizeof(buf) */
4824 newsvar->global_val.l[0] = cpystr(buf);
4825 newsvar->global_val.l[1] = NULL;
4826 set_current_val(newsvar, expand, cmdline);
4828 * But we're going to get rid of the fake global_val in case
4829 * things change.
4831 free_list_array(&newsvar->global_val.l);
4837 * Feature-list has to be handled separately from the other variables
4838 * because it is additive. The other variables choose one of command line,
4839 * or pine.conf, or pinerc. Feature list adds them. This could easily be
4840 * converted to a general purpose routine if we add more additive variables.
4842 * This works by replacing earlier values with later ones. That is, command
4843 * line settings have higher precedence than global settings and that is
4844 * accomplished by putting the command line features after the global
4845 * features in the list. When they are processed, the last one wins.
4847 * Feature-list also has a backwards compatibility hack.
4849 void
4850 set_feature_list_current_val(struct variable *var)
4852 char **list;
4853 char **list_fixed;
4854 char no_allow[50];
4855 int i, j, k, m,
4856 elems = 0;
4858 /* count the lists so we can allocate */
4859 for(m = 0; m < 6; m++){
4860 list = m==0 ? var->global_val.l :
4861 m==1 ? var->main_user_val.l :
4862 m==2 ? var->post_user_val.l :
4863 m==3 ? ps_global->feat_list_back_compat :
4864 m==4 ? var->cmdline_val.l :
4865 var->fixed_val.l;
4866 if(list)
4867 for(i = 0; list[i]; i++)
4868 elems++;
4871 list_fixed = var->fixed_val.l;
4873 if(var->current_val.l)
4874 free_list_array(&var->current_val.l);
4876 var->current_val.l = (char **)fs_get((elems+1) * sizeof(char *));
4879 * We need to warn the user if the sys mgr has restricted him or her
4880 * from changing a feature that he or she is trying to change.
4882 * We're not catching the old-growth macro since we're just comparing
4883 * strings. That is, it works correctly, but the user won't be warned
4884 * if the user old-growth and the mgr says no-quit-without-confirm.
4887 j = 0;
4888 strncpy(no_allow, "no-", 3);
4889 strncpy(no_allow+3, feature_list_name(F_ALLOW_CHANGING_FROM), sizeof(no_allow)-3-1);
4890 no_allow[sizeof(no_allow)-1] = '\0';
4892 for(m = 0; m < 6; m++){
4893 list = m==0 ? var->global_val.l :
4894 m==1 ? var->main_user_val.l :
4895 m==2 ? var->post_user_val.l :
4896 m==3 ? ps_global->feat_list_back_compat :
4897 m==4 ? var->cmdline_val.l :
4898 var->fixed_val.l;
4899 if(list)
4900 for(i = 0; list[i]; i++){
4901 var->current_val.l[j++] = cpystr(list[i]);
4903 /* this is the warning section */
4904 if(m >= 1 && m <= 4){
4905 for(k = 0; list_fixed && list_fixed[k]; k++){
4906 char *p, *q;
4907 p = list[i];
4908 q = list_fixed[k];
4909 if(!struncmp(p, "no-", 3))
4910 p += 3;
4911 if(!struncmp(q, "no-", 3))
4912 q += 3;
4913 if(!strucmp(q, p) && strucmp(list[i], list_fixed[k])){
4914 ps_global->give_fixed_warning = 1;
4915 if(m <= 2)
4916 ps_global->fix_fixed_warning = 1;
4920 else if(m == 5 && !strucmp(list[i], no_allow))
4921 ps_global->never_allow_changing_from = 1;
4925 #ifdef NEVER_ALLOW_CHANGING_FROM
4926 ps_global->never_allow_changing_from = 1;
4927 #endif
4929 var->current_val.l[j] = NULL;
4934 /*----------------------------------------------------------------------
4936 Expand Metacharacters/variables in file-names
4938 Read input line and expand shell-variables/meta-characters
4940 <input> <replaced by>
4941 $variable getenv("variable")
4942 ${variable} getenv("variable")
4943 ${variable:-defvalue} is getenv("variable") if variable is defined and
4944 is defvalue otherwise
4945 ~ getenv("HOME")
4946 \c c
4947 <others> <just copied>
4949 NOTE handling of braces in ${name} doesn't check much or do error recovery
4951 If colon_path is set, then we expand ~ not only at the start of linein,
4952 but also after each : in the path.
4954 ----*/
4955 #define is_allowed_envchar(C, S) ((S) == 0 ? !isspace((C)) && (C) != '/'\
4956 : (((C) >= 'a' && (C) <= 'z') \
4957 || ((C) >= 'A' && (C) <= 'Z') \
4958 || ((C) >= '0' && (C) <= '9')))
4960 char *
4961 expand_variables(char *lineout, size_t lineoutlen, char *linein, int colon_path)
4963 char *src = linein, *dest = lineout, *p;
4964 char *limit = lineout + lineoutlen;
4965 int envexpand = 0, sp;
4967 if(!linein)
4968 return(NULL);
4970 sp = strncmp(src,"LIT:pattern=\"/NICK=", strlen("LIT:pattern=\"/NICK=")) == 0;
4971 while(*src ){ /* something in input string */
4972 if(*src == '$' && *(src+1) == '$'){
4974 * $$ to escape chars we're interested in, else
4975 * it's up to the user of the variable to handle the
4976 * backslash...
4978 if(dest < limit)
4979 *dest++ = *++src; /* copy next as is */
4980 }else
4981 #if !(defined(DOS) || defined(OS2))
4982 if(*src == '\\' && *(src+1) == '$'){
4984 * backslash to escape chars we're interested in, else
4985 * it's up to the user of the variable to handle the
4986 * backslash...
4988 if(dest < limit)
4989 *dest++ = *++src; /* copy next as is */
4990 }else if(*src == '~' &&
4991 (src == linein || (colon_path && *(src-1) == ':'))){
4992 char buf[MAXPATH];
4993 int i;
4995 for(i = 0; i < sizeof(buf)-1 && src[i] && src[i] != '/'; i++)
4996 buf[i] = src[i];
4998 src += i; /* advance src pointer */
4999 buf[i] = '\0'; /* tie off buf string */
5000 fnexpand(buf, sizeof(buf)); /* expand the path */
5002 for(p = buf; dest < limit && (*dest = *p); p++, dest++)
5005 continue;
5006 }else
5007 #endif
5008 if(*src == '$'){ /* shell variable */
5009 char word[128+1], *colon = NULL, *rbrace = NULL;
5011 envexpand++; /* signal that we've expanded a var */
5012 src++; /* skip dollar */
5013 if(*src == '{'){ /* starts with brace? */
5014 src++;
5015 rbrace = strindex(src, '}');
5016 if(rbrace){
5017 /* look for default value */
5018 colon = strstr(src, ":-");
5019 if(colon && (rbrace < colon))
5020 colon = NULL;
5024 p = word;
5026 /* put the env variable to be looked up in word */
5027 if(rbrace){
5028 while(*src
5029 && (p-word < sizeof(word)-1)
5030 && ((colon && src < colon) || (!colon && src < rbrace))){
5031 if(isspace((unsigned char) *src)){
5033 * Illegal input. This should be an error of some
5034 * sort but instead of that we'll just backup to the
5035 * $ and treat it like it wasn't there.
5037 while(*src != '$')
5038 src--;
5040 envexpand--;
5041 goto just_copy;
5043 else
5044 *p++ = *src++;
5047 /* adjust src for next char */
5048 src = rbrace + 1;
5050 else{
5051 while(*src && is_allowed_envchar((unsigned char) *src, sp)
5052 && (p-word < sizeof(word)-1))
5053 *p++ = *src++;
5056 *p = '\0';
5058 if((p = getenv(word)) != NULL){ /* check for word in environment */
5059 while(*p && dest < limit)
5060 *dest++ = *p++;
5062 else if(colon){ /* else possible default value */
5063 p = colon + 2;
5064 while(*p && p < rbrace && dest < limit)
5065 *dest++ = *p++;
5068 continue;
5069 }else{ /* other cases: just copy */
5070 just_copy:
5071 if(dest < limit)
5072 *dest++ = *src;
5075 if(*src) /* next character (if any) */
5076 src++;
5079 if(dest < limit)
5080 *dest = '\0';
5081 else
5082 lineout[lineoutlen-1] = '\0';
5084 return((envexpand && lineout[0] == '\0') ? NULL : lineout);
5088 /*----------------------------------------------------------------------
5089 Sets login, full_username and home_dir
5091 Args: ps -- The Pine structure to put the user name, etc in
5093 Result: sets the fullname, login and home_dir field of the pine structure
5094 returns 0 on success, -1 if not.
5095 ----*/
5096 #define MAX_INIT_ERRS 10
5097 void
5098 init_error(struct pine *ps, int flags, int min_time, int max_time, char *message)
5100 int i;
5102 if(!ps->init_errs){
5103 ps->init_errs = (INIT_ERR_S *)fs_get((MAX_INIT_ERRS + 1) *
5104 sizeof(*ps->init_errs));
5105 memset(ps->init_errs, 0, (MAX_INIT_ERRS + 1) * sizeof(*ps->init_errs));
5108 for(i = 0; i < MAX_INIT_ERRS; i++)
5109 if(!(ps->init_errs)[i].message){
5110 (ps->init_errs)[i].message = cpystr(message);
5111 (ps->init_errs)[i].min_time = min_time;
5112 (ps->init_errs)[i].max_time = max_time;
5113 (ps->init_errs)[i].flags = flags;
5114 dprint((2, "%s\n", message ? message : "?"));
5115 break;
5120 /*----------------------------------------------------------------------
5121 Read and parse a pinerc file
5123 Args: Filename -- name of the .pinerc file to open and read
5124 vars -- The vars structure to store values in
5125 which_vars -- Whether the local or global values are being read
5127 Result:
5129 This may be the local file or the global file. The values found are
5130 merged with the values currently in vars. All values are strings and
5131 are malloced; and existing values will be freed before the assignment.
5132 Those that are <unset> will be left unset; their values will be NULL.
5133 ----*/
5134 void
5135 read_pinerc(PINERC_S *prc, struct variable *vars, ParsePinerc which_vars)
5137 char *filename = NULL, *file, *value = NULL, **lvalue = NULL, *line, *error;
5138 char *p, *p1, *free_file = NULL;
5139 struct variable *v;
5140 PINERC_LINE *pline = NULL;
5141 int line_count, was_quoted;
5142 int i;
5144 if(!prc)
5145 return;
5147 dprint((2, "reading_pinerc \"%s\"\n",
5148 prc->name ? prc->name : "?"));
5150 if(prc->type == Loc){
5151 filename = prc->name ? prc->name : "";
5152 file = free_file = read_file(filename, 0);
5155 * This is questionable. In case the user edits the pinerc
5156 * in Windows and adds a UTF-8 BOM, we skip it here. If the
5157 * user adds a Unicode BOM we're in trouble. We could write it
5158 * with the BOM ourselves but so far we leave it BOMless in
5159 * order that it's the same on Unix and Windows.
5161 if(BOM_UTF8(file))
5162 file += 3;
5164 else{
5165 if((file = read_remote_pinerc(prc, which_vars)) != NULL)
5166 ps_global->c_client_error[0] = '\0';
5168 free_file = file;
5171 if(file == NULL || *file == '\0'){
5172 #ifdef DEBUG
5173 if(file == NULL){
5174 dprint((2, "Open failed: %s\n", error_description(errno)));
5176 else{
5177 if(prc->type == Loc){
5178 dprint((1, "Read_pinerc: empty pinerc (new?)\n"));
5180 else{
5181 dprint((1, "Read_pinerc: new remote pinerc\n"));
5184 #endif /* DEBUG */
5186 if(which_vars == ParsePers){
5187 /* problems getting remote config */
5188 if(file == NULL && prc->type == RemImap){
5189 if(!pith_opt_remote_pinerc_failure
5190 || !(*pith_opt_remote_pinerc_failure)())
5191 exceptional_exit(_("Unable to read or write remote configuration"), -1);
5194 ps_global->first_time_user = 1;
5195 prc->outstanding_pinerc_changes = 1;
5198 return;
5200 else{
5201 if(prc->type == Loc &&
5202 (which_vars == ParseFixed || which_vars == ParseGlobal ||
5203 (can_access(filename, ACCESS_EXISTS) == 0 &&
5204 can_access(filename, EDIT_ACCESS) != 0))){
5205 prc->readonly = 1;
5206 if(prc == ps_global->prc)
5207 ps_global->readonly_pinerc = 1;
5211 * accept CRLF or LF newlines
5213 for(p = file; *p && *p != '\012'; p++)
5216 if(p > file && *p && *(p-1) == '\015') /* cvt crlf to lf */
5217 for(p1 = p - 1; (*p1 = *p) != '\0'; p++)
5218 if(!(*p == '\015' && *(p+1) == '\012'))
5219 p1++;
5222 dprint((2, "Read %d characters:\n", strlen(file)));
5224 if(which_vars == ParsePers || which_vars == ParsePersPost){
5225 /*--- Count up lines and allocate structures */
5226 for(line_count = 0, p = file; *p != '\0'; p++)
5227 if(*p == '\n')
5228 line_count++;
5230 prc->pinerc_lines = (PINERC_LINE *)
5231 fs_get((3 + line_count) * sizeof(PINERC_LINE));
5232 memset((void *)prc->pinerc_lines, 0,
5233 (3 + line_count) * sizeof(PINERC_LINE));
5234 pline = prc->pinerc_lines;
5237 for(p = file, line = file; *p != '\0';){
5238 /*----- Grab the line ----*/
5239 line = p;
5240 while(*p && *p != '\n')
5241 p++;
5242 if(*p == '\n'){
5243 *p++ = '\0';
5246 /*----- Comment Line -----*/
5247 if(*line == '#'){
5248 /* no comments in remote pinercs */
5249 if(pline && prc->type == Loc){
5250 pline->is_var = 0;
5251 pline->line = cpystr(line);
5252 pline++;
5254 continue;
5257 if(*line == '\0' || *line == '\t' || *line == ' '){
5258 p1 = line;
5259 while(*p1 == '\t' || *p1 == ' ')
5260 p1++;
5261 if(pline){
5263 * This could be a continuation line from some future
5264 * version of pine, or it could be a continuation line
5265 * from a PC-Pine variable we don't know about in unix.
5267 if(*p1 != '\0')
5268 pline->line = cpystr(line);
5269 else
5270 pline->line = cpystr("");
5271 pline->is_var = 0;
5272 pline++;
5274 continue;
5277 /*----- look up matching 'v' and leave "value" after '=' ----*/
5278 for(v = vars; *line && v->name; v++)
5279 if((i = strlen(v->name)) < strlen(line) && !struncmp(v->name,line,i)){
5280 int j;
5282 for(j = i; line[j] == ' ' || line[j] == '\t'; j++)
5285 if(line[j] == '='){ /* bingo! */
5286 for(value = &line[j+1];
5287 *value == ' ' || *value == '\t';
5288 value++)
5291 break;
5293 /* else either unrecognized var or bogus line */
5296 /*----- Didn't match any variable or bogus format -----*/
5298 * This could be a variable from some future
5299 * version of pine, or it could be a PC-Pine variable
5300 * we don't know about in unix. Either way, we want to preserve
5301 * it in the file.
5303 if(!v->name){
5304 if(pline){
5305 pline->is_var = 0;
5306 pline->line = cpystr(line);
5307 pline++;
5309 continue;
5313 * Previous versions have caused duplicate pinerc data to be
5314 * written to pinerc files. This clause erases the duplicate
5315 * information when we read it, and it will be removed from the file
5316 * if we call write_pinerc. We test to see if the same variable
5317 * appears later in the file, if so, we skip over it here.
5318 * We don't care about duplicates if this isn't a pinerc we might
5319 * write out, so include pline in the conditional.
5320 * Note that we will leave all of the duplicate comments and blank
5321 * lines in the file unless it is a remote pinerc. Luckily, the
5322 * bug that caused the duplicates only applied to remote pinercs,
5323 * so we should have that case covered.
5325 * If we find a duplicate, we point p to the start
5326 * of the next line that should be considered, and then skip back
5327 * to the top of the loop.
5329 if(pline && var_is_in_rest_of_file(v->name, p)){
5330 if(v->is_list)
5331 p = skip_over_this_var(line, p);
5333 continue;
5337 /*----- Obsolete variable, read it anyway below, might use it -----*/
5338 if(v->is_obsolete){
5339 if(pline){
5340 pline->obsolete_var = 1;
5341 pline->line = cpystr(line);
5342 pline->var = v;
5346 /*----- Variable is in the list but unused for some reason -----*/
5347 if(!v->is_used){
5348 if(pline){
5349 pline->is_var = 0;
5350 pline->line = cpystr(line);
5351 pline++;
5353 continue;
5356 /*--- Var is not user controlled, leave it alone for back compat ---*/
5357 if(!v->is_user && pline){
5358 pline->is_var = 0;
5359 pline->line = cpystr(line);
5360 pline++;
5361 continue;
5364 if(which_vars == ParseFixed)
5365 v->is_fixed = 1;
5367 /*---- variable is unset, or it's global but expands to nothing ----*/
5368 if(!*value
5369 || (which_vars == ParseGlobal
5370 && !expand_variables(tmp_20k_buf, SIZEOF_20KBUF, value,
5371 (v == &ps_global->vars[V_MAILCAP_PATH] ||
5372 v == &ps_global->vars[V_MIMETYPE_PATH])))){
5373 if(v->is_user && pline){
5374 pline->is_var = 1;
5375 pline->var = v;
5376 pline++;
5378 continue;
5381 /*--value is non-empty, store it handling quotes and trailing space--*/
5382 if(*value == '"' && !v->is_list && v->del_quotes){
5383 was_quoted = 1;
5384 value++;
5385 for(p1 = value; *p1 && *p1 != '"'; p1++);
5386 if(*p1 == '"')
5387 *p1 = '\0';
5388 else
5389 removing_trailing_white_space(value);
5390 }else
5391 was_quoted = 0;
5394 * List Entry Parsing
5396 * The idea is to parse a comma separated list of
5397 * elements, preserving quotes, and understanding
5398 * continuation lines (that is ',' == "\n ").
5399 * Quotes must be balanced within elements. Space
5400 * within elements is preserved, but leading and trailing
5401 * space is trimmed. This is a generic function, and it's
5402 * left to the the functions that use the lists to make sure
5403 * they contain valid data...
5405 if(v->is_list){
5407 was_quoted = 0;
5408 line_count = 0;
5409 p1 = value;
5410 while(1){ /* generous count of list elements */
5411 if(*p1 == '"') /* ignore ',' if quoted */
5412 was_quoted = (was_quoted) ? 0 : 1 ;
5414 if((*p1 == ',' && !was_quoted) || *p1 == '\n' || *p1 == '\0')
5415 line_count++; /* count this element */
5417 if(*p1 == '\0' || *p1 == '\n'){ /* deal with EOL */
5418 if(p1 < p || *p1 == '\n'){
5419 *p1++ = ','; /* fix null or newline */
5421 if(*p1 != '\t' && *p1 != ' '){
5422 *(p1-1) = '\0'; /* tie off list */
5423 p = p1; /* reset p */
5424 break;
5426 }else{
5427 p = p1; /* end of pinerc */
5428 break;
5430 }else
5431 p1++;
5434 error = NULL;
5435 lvalue = parse_list(value, line_count,
5436 v->del_quotes ? PL_REMSURRQUOT : PL_NONE,
5437 &error);
5438 if(error){
5439 dprint((1,
5440 "read_pinerc: ERROR: %s in %s = \"%s\"\n",
5441 error ? error : "?",
5442 v->name ? v->name : "?",
5443 value ? value : "?"));
5446 * Special case: turn "" strings into empty strings.
5447 * This allows users to turn off default lists. For example,
5448 * if smtp-server is set then a user could override smtp-server
5449 * with smtp-server="".
5451 for(i = 0; lvalue[i]; i++)
5452 if(lvalue[i][0] == '"' &&
5453 lvalue[i][1] == '"' &&
5454 lvalue[i][2] == '\0')
5455 lvalue[i][0] = '\0';
5458 if(pline){
5459 if(v->is_user && (which_vars == ParsePers || !v->is_onlymain)){
5460 if(v->is_list){
5461 char ***l;
5463 l = (which_vars == ParsePers) ? &v->main_user_val.l
5464 : &v->post_user_val.l;
5465 free_list_array(l);
5466 *l = lvalue;
5468 else{
5469 char **p;
5471 p = (which_vars == ParsePers) ? &v->main_user_val.p
5472 : &v->post_user_val.p;
5473 if(p && *p != NULL)
5474 fs_give((void **)p);
5476 *p = cpystr(value);
5479 if(pline){
5480 pline->is_var = 1;
5481 pline->var = v;
5482 pline->is_quoted = was_quoted;
5483 pline++;
5487 else if(which_vars == ParseGlobal){
5488 if(v->is_global){
5489 if(v->is_list){
5490 free_list_array(&v->global_val.l);
5491 v->global_val.l = lvalue;
5493 else{
5494 if(v->global_val.p != NULL)
5495 fs_give((void **) &(v->global_val.p));
5497 v->global_val.p = cpystr(value);
5501 else{ /* which_vars == ParseFixed */
5502 if(v->is_user || v->is_global){
5503 if(v->is_list){
5504 free_list_array(&v->fixed_val.l);
5505 v->fixed_val.l = lvalue;
5507 else{
5508 if(v->fixed_val.p != NULL)
5509 fs_give((void **) &(v->fixed_val.p));
5511 v->fixed_val.p = cpystr(value);
5516 #ifdef DEBUG
5517 if(v->is_list){
5518 char **l;
5519 l = (which_vars == ParsePers) ? v->main_user_val.l :
5520 (which_vars == ParsePersPost) ? v->post_user_val.l :
5521 (which_vars == ParseGlobal) ? v->global_val.l :
5522 v->fixed_val.l;
5523 if(l && *l && **l){
5524 dprint((5, " %20.20s : %s\n",
5525 v->name ? v->name : "?",
5526 *l ? *l : "?"));
5527 while(++l && *l && **l)
5528 dprint((5, " %20.20s : %s\n", "",
5529 *l ? *l : "?"));
5531 }else{
5532 char *p;
5533 p = (which_vars == ParsePers) ? v->main_user_val.p :
5534 (which_vars == ParsePersPost) ? v->post_user_val.p :
5535 (which_vars == ParseGlobal) ? v->global_val.p :
5536 v->fixed_val.p;
5537 if(p && *p)
5538 dprint((5, " %20.20s : %s\n",
5539 v->name ? v->name : "?",
5540 p ? p : "?"));
5542 #endif /* DEBUG */
5545 if(pline){
5546 pline->line = NULL;
5547 pline->is_var = 0;
5548 if(!prc->pinerc_written && prc->type == Loc){
5549 prc->pinerc_written = name_file_mtime(filename);
5550 dprint((5, "read_pinerc: time_pinerc_written = %ld\n",
5551 (long) prc->pinerc_written));
5555 if(free_file)
5556 fs_give((void **) &free_file);
5561 * Args varname The variable name we're looking for
5562 * begin Begin looking here
5564 * Returns 1 if variable varname appears in the rest of the file
5565 * 0 if not
5568 var_is_in_rest_of_file(char *varname, char *begin)
5570 char *p;
5572 if(!(varname && *varname && begin && *begin))
5573 return 0;
5575 p = begin;
5577 while((p = srchstr(p, varname)) != NULL){
5578 /* beginning of a line? */
5579 if(p > begin && (*(p-1) != '\n' && *(p-1) != '\r')){
5580 p++;
5581 continue;
5584 /* followed by [ SPACE ] < = > ? */
5585 p += strlen(varname);
5586 while(*p == ' ' || *p == '\t')
5587 p++;
5589 if(*p == '=')
5590 return 1;
5593 return 0;
5598 * Args begin Variable to skip starts here.
5599 * nextline This is where the next line starts. We need to know this
5600 * because the input has been mangled a little. A \0 has
5601 * replaced the \n at the end of the first line, but we can
5602 * use nextline to help us out of that quandry.
5604 * Return a pointer to the start of the first line after this variable
5605 * and all of its continuation lines.
5607 char *
5608 skip_over_this_var(char *begin, char *nextline)
5610 char *p;
5612 p = begin;
5614 while(1){
5615 if(*p == '\0' || *p == '\n'){ /* EOL */
5616 if(p < nextline || *p == '\n'){ /* there may be another line */
5617 p++;
5618 if(*p != ' ' && *p != '\t') /* no continuation line */
5619 return(p);
5621 else /* end of file */
5622 return(p);
5624 else
5625 p++;
5630 static char quotes[3] = {'"', '"', '\0'};
5631 /*----------------------------------------------------------------------
5632 Write out the .pinerc state information
5634 Args: ps -- The pine structure to take state to be written from
5635 which -- Which pinerc to write
5636 flags -- If bit WRP_NOUSER is set, then assume that there is
5637 not a user present to answer questions.
5639 This writes to a temporary file first, and then renames that to
5640 be the new .pinerc file to protect against disk error. This has the
5641 problem of possibly messing up file protections, ownership and links.
5642 ----*/
5644 write_pinerc(struct pine *ps, EditWhich which, int flags)
5646 char *p, *dir, *tmp = NULL, *pinrc;
5647 char *pval = NULL, **lval = NULL;
5648 char *linep = NULL, *lineq = NULL;
5649 int bc = 1;
5650 int buflen;
5651 PINERC_LINE *pline;
5652 struct variable *var;
5653 time_t mtime;
5654 char *filename = NULL;
5655 REMDATA_S *rd = NULL;
5656 PINERC_S *prc = NULL;
5657 STORE_S *so = NULL;
5658 #ifndef _WINDOWS
5659 struct stat sbuf;
5660 char *slink = NULL;
5661 #endif
5663 #define MAXPLINESIZE 10000
5665 dprint((2,"---- write_pinerc(%s) ----\n",
5666 (which == Main) ? "Main" : "Post"));
5668 switch(which){
5669 case Main:
5670 prc = ps ? ps->prc : NULL;
5671 break;
5672 case Post:
5673 prc = ps ? ps->post_prc : NULL;
5674 break;
5675 default:
5676 break;
5679 if(!prc)
5680 return(-1);
5682 if(prc->quit_to_edit){
5683 if(!(flags & WRP_NOUSER))
5684 quit_to_edit_msg(prc);
5686 return(-1);
5689 if(prc->type != Loc && !prc->readonly){
5691 bc = 0; /* don't do backcompat conversion */
5692 rd = prc->rd;
5693 if(!rd)
5694 return(-1);
5696 rd_check_remvalid(rd, -10L);
5698 if(rd->flags & REM_OUTOFDATE){
5699 if((flags & WRP_NOUSER) || unexpected_pinerc_change()){
5700 prc->outstanding_pinerc_changes = 1;
5701 if(!(flags & WRP_NOUSER))
5702 q_status_message1(SM_ORDER | SM_DING, 3, 3,
5703 "Pinerc \"%.200s\" NOT saved",
5704 prc->name ? prc->name : "");
5705 dprint((2, "write_pinerc: remote pinerc changed\n"));
5706 return(-1);
5708 else
5709 rd->flags &= ~REM_OUTOFDATE;
5712 rd_open_remote(rd);
5714 if(rd->access == ReadWrite){
5715 int ro;
5717 if((ro=rd_remote_is_readonly(rd)) || rd->flags & REM_OUTOFDATE){
5718 if(ro == 1){
5719 if(!(flags & WRP_NOUSER))
5720 q_status_message(SM_ORDER | SM_DING, 5, 15,
5721 _("Can't access remote config, changes NOT saved!"));
5722 dprint((1,
5723 "write_pinerc: Can't write to remote pinerc %s, aborting write\n",
5724 rd->rn ? rd->rn : "?"));
5726 else if(ro == 2){
5727 if(!(rd->flags & NO_META_UPDATE)){
5728 unsigned long save_chk_nmsgs;
5730 switch(rd->type){
5731 case RemImap:
5732 save_chk_nmsgs = rd->t.i.chk_nmsgs;
5733 rd->t.i.chk_nmsgs = 0;
5734 rd_write_metadata(rd, 0);
5735 rd->t.i.chk_nmsgs = save_chk_nmsgs;
5736 break;
5738 default:
5739 q_status_message(SM_ORDER | SM_DING, 3, 5,
5740 "Write_pinerc: Type not supported");
5741 break;
5745 if(!(flags & WRP_NOUSER))
5746 q_status_message1(SM_ORDER | SM_DING, 5, 15,
5747 _("No write permission for remote config %.200s, changes NOT saved!"),
5748 rd->rn);
5750 else{
5751 if(!(flags & WRP_NOUSER))
5752 q_status_message(SM_ORDER | SM_DING, 5, 15,
5753 _("Remote config changed, aborting our change to avoid damage..."));
5754 dprint((1,
5755 "write_pinerc: remote config %s changed since we started pine, aborting write\n",
5756 prc->name ? prc->name : "?"));
5759 rd->flags &= ~DO_REMTRIM;
5760 return(-1);
5763 filename = rd->lf;
5765 else{
5766 prc->readonly = 1;
5767 if(prc == ps->prc)
5768 ps->readonly_pinerc = 1;
5771 else
5772 filename = prc->name ? prc->name : "";
5774 pinrc = prc->name ? prc->name : "";
5776 if(prc->type == Loc){
5777 mtime = name_file_mtime(filename);
5778 if(prc->pinerc_written
5779 && prc->pinerc_written != mtime
5780 && ((flags & WRP_NOUSER) || unexpected_pinerc_change())){
5781 prc->outstanding_pinerc_changes = 1;
5783 if(!(flags & WRP_NOUSER))
5784 q_status_message1(SM_ORDER | SM_DING, 3, 3,
5785 "Pinerc \"%.200s\" NOT saved", pinrc);
5787 dprint((2,"write_pinerc: mtime mismatch: \"%s\": %ld != %ld\n",
5788 filename ? filename : "?",
5789 (long) prc->pinerc_written, (long) mtime));
5790 return(-1);
5794 /* don't write if pinerc is read-only */
5795 if(prc->readonly ||
5796 (filename &&
5797 can_access(filename, ACCESS_EXISTS) == 0 &&
5798 can_access(filename, EDIT_ACCESS) != 0)){
5799 prc->readonly = 1;
5800 if(prc == ps->prc)
5801 ps->readonly_pinerc = 1;
5803 if(!(flags & WRP_NOUSER))
5804 q_status_message1(SM_ORDER | SM_DING, 0, 5,
5805 _("Can't modify configuration file \"%.200s\": ReadOnly"),
5806 pinrc);
5807 dprint((2, "write_pinerc: fail because can't access pinerc\n"));
5809 if(rd)
5810 rd->flags &= ~DO_REMTRIM;
5812 return(-1);
5815 if(rd && rd->flags & NO_FILE){
5816 so = rd->sonofile;
5817 so_truncate(rd->sonofile, 0L); /* reset storage object */
5819 else{
5820 dir = ".";
5821 if((p = last_cmpnt(filename)) != NULL){
5822 *--p = '\0';
5823 dir = filename;
5826 #if defined(DOS) || defined(OS2)
5827 if(!(isalpha((unsigned char)dir[0]) && dir[1] == ':' && dir[2] == '\0')
5828 && (can_access(dir, EDIT_ACCESS) < 0 &&
5829 our_mkdir(dir, 0700) < 0))
5831 if(!(flags & WRP_NOUSER))
5832 q_status_message2(SM_ORDER | SM_DING, 3, 5,
5833 /* TRANSLATORS: first argument is a filename, second
5834 arg is the text of the error message */
5835 _("Error creating \"%.200s\" : %.200s"), dir,
5836 error_description(errno));
5837 if(rd)
5838 rd->flags &= ~DO_REMTRIM;
5840 return(-1);
5843 tmp = temp_nam(dir, "rc");
5845 if(*dir && tmp && !in_dir(dir, tmp)){
5846 our_unlink(tmp);
5847 fs_give((void **)&tmp);
5850 if(p)
5851 *p = '\\';
5853 if(tmp == NULL)
5854 goto io_err;
5856 #else /* !DOS */
5857 tmp = temp_nam((*dir) ? dir : "/", "pinerc");
5860 * If temp_nam can't write in dir it puts the temp file in a
5861 * temp directory, which won't help us when we go to rename.
5863 if(*dir && tmp && !in_dir(dir, tmp)){
5864 our_unlink(tmp);
5865 fs_give((void **)&tmp);
5868 if(p)
5869 *p = '/';
5871 if(tmp == NULL)
5872 goto io_err;
5874 #endif /* !DOS */
5876 if((so = so_get(FileStar, tmp, WRITE_ACCESS)) == NULL)
5877 goto io_err;
5880 if(!(flags & WRP_PRESERV_WRITTEN))
5881 for(var = ps->vars; var->name != NULL; var++)
5882 var->been_written = 0;
5884 if(prc->type == Loc && ps->first_time_user &&
5885 !so_puts(so, native_nl(cf_text_comment)))
5886 goto io_err;
5888 linep = fs_get((MAXPLINESIZE+1)*sizeof(char));
5889 lineq = fs_get((MAXPLINESIZE+1)*sizeof(char));
5890 buflen = MAXPLINESIZE;
5892 /* Write out what was in the .pinerc */
5893 for(pline = prc->pinerc_lines;
5894 pline && (pline->is_var || pline->line); pline++){
5895 if(pline->is_var){
5896 var = pline->var;
5898 if(var->is_list)
5899 lval = LVAL(var, which);
5900 else
5901 pval = PVAL(var, which);
5903 /* variable is not set */
5904 if((var->is_list && (!lval || !lval[0])) ||
5905 (!var->is_list && !pval)){
5906 /* leave null variables out of remote pinerc */
5907 if(prc->type == Loc &&
5908 (!so_puts(so, var->name) || !so_puts(so, "=") ||
5909 !so_puts(so, NEWLINE)))
5910 goto io_err;
5912 /* var is set to empty string */
5913 else if((var->is_list && lval[0][0] == '\0') ||
5914 (!var->is_list && pval[0] == '\0')){
5915 if(!so_puts(so, var->name) || !so_puts(so, "=") ||
5916 !so_puts(so, quotes) || !so_puts(so, NEWLINE))
5917 goto io_err;
5919 else{
5920 if(var->is_list){
5921 int i = 0;
5923 for(i = 0; lval[i]; i++){
5924 if(strlen(var->name)
5925 + (lval[i][0] ? strlen(lval[i]) : 5) > buflen){
5926 buflen = strlen(var->name)
5927 + (lval[i][0] ? strlen(lval[i]) : 5);
5928 fs_resize((void **)&linep, (buflen+1)*sizeof(char));
5929 fs_resize((void **)&lineq, (buflen+1)*sizeof(char));
5931 snprintf(linep, buflen+1, "%s%s%s%s%s",
5932 (i) ? "\t" : var->name,
5933 (i) ? "" : "=",
5934 lval[i][0] ? lval[i] : quotes,
5935 lval[i+1] ? "," : "", NEWLINE);
5936 linep[buflen] = '\0';
5937 if(!so_puts(so, bc ? backcompat_convert_from_utf8(&lineq, buflen+1, linep) : linep))
5938 goto io_err;
5941 else{
5942 if(strlen(var->name)
5943 + (pval[0] ? strlen(pval) : 5) > buflen){
5944 buflen = strlen(var->name)
5945 + (pval[0] ? strlen(pval) : 5);
5946 fs_resize((void **)&linep, (buflen+1)*sizeof(char));
5947 fs_resize((void **)&lineq, (buflen+1)*sizeof(char));
5949 snprintf(linep, buflen+1, "%s=%s%s%s%s",
5950 var->name,
5951 (pline->is_quoted && pval[0] != '\"')
5952 ? "\"" : "",
5953 pval,
5954 (pline->is_quoted && pval[0] != '\"')
5955 ? "\"" : "", NEWLINE);
5956 linep[buflen] = '\0';
5957 if(!so_puts(so, bc ? backcompat_convert_from_utf8(&lineq, buflen+1, linep) : linep))
5958 goto io_err;
5962 var->been_written = 1;
5964 }else{
5966 * The description text should be changed into a message
5967 * about the variable being obsolete when a variable is
5968 * moved to obsolete status. We add that message before
5969 * the variable unless it is already there. However, we
5970 * leave the variable itself in case the user runs an old
5971 * version of pine again. Note that we have read in the
5972 * value of the variable in read_pinerc and translated it
5973 * into a new variable if appropriate.
5975 if(pline->obsolete_var && prc->type == Loc){
5976 if(pline <= prc->pinerc_lines || (pline-1)->line == NULL ||
5977 strlen((pline-1)->line) < 3 ||
5978 strucmp((pline-1)->line+2, pline->var->descrip) != 0)
5979 if(!so_puts(so, "# ") ||
5980 !so_puts(so, native_nl(pline->var->descrip)) ||
5981 !so_puts(so, NEWLINE))
5982 goto io_err;
5985 /* remove comments from remote pinercs */
5986 if((prc->type == Loc ||
5987 (pline->line[0] != '#' && pline->line[0] != '\0')) &&
5988 (!so_puts(so, pline->line) || !so_puts(so, NEWLINE)))
5989 goto io_err;
5993 /* Now write out all the variables not in the .pinerc */
5994 for(var = ps->vars; var->name != NULL; var++){
5995 if(!var->is_user || var->been_written || !var->is_used ||
5996 var->is_obsolete || (var->is_onlymain && which != Main))
5997 continue;
5999 if(var->is_list)
6000 lval = LVAL(var, which);
6001 else
6002 pval = PVAL(var, which);
6005 * set description to NULL to eliminate preceding
6006 * blank and comment line.
6008 if(prc->type == Loc && var->descrip && *var->descrip &&
6009 (!so_puts(so, NEWLINE) || !so_puts(so, "# ") ||
6010 !so_puts(so, native_nl(var->descrip)) || !so_puts(so, NEWLINE)))
6011 goto io_err;
6013 /* variable is not set */
6014 /** Don't know what the global_val thing is for. SH, Mar 00 **/
6015 if((var->is_list && (!lval || (!lval[0] && !var->global_val.l))) ||
6016 (!var->is_list && !pval)){
6017 /* leave null variables out of remote pinerc */
6018 if(prc->type == Loc &&
6019 (!so_puts(so, var->name) || !so_puts(so, "=") ||
6020 !so_puts(so, NEWLINE)))
6021 goto io_err;
6023 /* var is set to empty string */
6024 else if((var->is_list && (!lval[0] || !lval[0][0]))
6025 || (!var->is_list && pval[0] == '\0')){
6026 if(!so_puts(so, var->name) || !so_puts(so, "=") ||
6027 !so_puts(so, quotes) || !so_puts(so, NEWLINE))
6028 goto io_err;
6030 else if(var->is_list){
6031 int i = 0;
6033 for(i = 0; lval[i] ; i++){
6034 if(strlen(var->name)
6035 + (lval[i][0] ? strlen(lval[i]) : 5) > buflen){
6036 buflen = strlen(var->name)
6037 + (lval[i][0] ? strlen(lval[i]) : 5);
6038 fs_resize((void **)&linep, (buflen+1)*sizeof(char));
6039 fs_resize((void **)&lineq, (buflen+1)*sizeof(char));
6041 snprintf(linep, buflen+1, "%s%s%s%s%s",
6042 (i) ? "\t" : var->name,
6043 (i) ? "" : "=",
6044 lval[i],
6045 lval[i+1] ? "," : "", NEWLINE);
6046 linep[buflen] = '\0';
6047 if(!so_puts(so, bc ? backcompat_convert_from_utf8(&lineq, buflen+1, linep) : linep))
6048 goto io_err;
6051 else{
6052 char *pconverted;
6054 if(strlen(pval) > buflen){
6055 buflen = strlen(pval) + 1;
6056 fs_resize((void **)&linep, (buflen+1)*sizeof(char));
6057 fs_resize((void **)&lineq, (buflen+1)*sizeof(char));
6059 pconverted = bc ? backcompat_convert_from_utf8(&lineq, buflen+1, pval) : pval;
6061 if(!so_puts(so, var->name) || !so_puts(so, "=") ||
6062 !so_puts(so, pconverted) || !so_puts(so, NEWLINE))
6063 goto io_err;
6067 if(!(rd && rd->flags & NO_FILE)){
6068 char *realfilename;
6069 int realfilename_malloced;
6071 if(so_give(&so)) goto io_err;
6073 #ifndef _WINDOWS
6074 realfilename = fs_get(MAXPATH+1);
6075 if(realfilename != NULL){
6076 if(realpath(filename, realfilename) == NULL)
6077 fs_give((void **) &realfilename);
6078 realfilename_malloced = realfilename != NULL ? 1 : 0;
6080 else
6081 realfilename_malloced = 0;
6082 if (realfilename_malloced == 0){
6083 if(our_stat(filename, &sbuf) < 0 && errno == ENOENT){
6084 realfilename = filename;
6085 realfilename_malloced = 0;
6087 else
6088 goto io_err;
6090 #else
6091 realfilename = filename;
6092 realfilename_malloced = 0;
6093 #endif /* _WINDOWS */
6094 if(realfilename != NULL){
6095 int r;
6096 file_attrib_copy(tmp, realfilename);
6097 r = rename_file(tmp, realfilename);
6098 if(realfilename_malloced != 0)
6099 fs_give((void **) &realfilename);
6100 if(r < 0) goto io_err;
6104 if(prc->type != Loc){
6105 int e, we_cancel;
6106 char datebuf[200];
6108 datebuf[0] = '\0';
6109 we_cancel = 0;
6111 if(!(flags & WRP_NOUSER))
6112 we_cancel = busy_cue(_("Copying to remote config"), NULL, 1);
6114 if((e = rd_update_remote(rd, datebuf)) != 0){
6115 dprint((1,
6116 "write_pinerc: error copying from %s to %s\n",
6117 rd->lf ? rd->lf : "<memory>", rd->rn ? rd->rn : "?"));
6118 if(!(flags & WRP_NOUSER)){
6119 q_status_message2(SM_ORDER | SM_DING, 3, 5,
6120 _("Error copying to %.200s: %.200s"),
6121 rd->rn, error_description(errno));
6123 q_status_message(SM_ORDER | SM_DING, 5, 5,
6124 _("Copy of config to remote folder failed, changes NOT saved remotely"));
6127 else{
6128 rd_update_metadata(rd, datebuf);
6129 rd->read_status = 'W';
6130 rd_trim_remdata(&rd);
6131 rd_close_remote(rd);
6134 if(we_cancel)
6135 cancel_busy_cue(-1);
6138 prc->outstanding_pinerc_changes = 0;
6140 if(prc->type == Loc){
6141 prc->pinerc_written = name_file_mtime(filename);
6142 dprint((2, "wrote pinerc: %s: time_pinerc_written = %ld\n",
6143 pinrc ? pinrc : "?", (long) prc->pinerc_written));
6145 else{
6146 dprint((2, "wrote pinerc: %s\n", pinrc ? pinrc : "?"));
6149 if(tmp){
6150 our_unlink(tmp);
6151 fs_give((void **)&tmp);
6154 if(linep) fs_give((void **)&linep);
6155 if(lineq) fs_give((void **)&lineq);
6157 return(0);
6159 io_err:
6160 if(!(flags & WRP_NOUSER))
6161 q_status_message2(SM_ORDER | SM_DING, 3, 5,
6162 _("Error saving configuration in \"%.200s\": %.200s"),
6163 pinrc, error_description(errno));
6165 dprint((1, "Error writing %s : %s\n", pinrc ? pinrc : "?",
6166 error_description(errno)));
6167 if(rd)
6168 rd->flags &= ~DO_REMTRIM;
6169 if(tmp){
6170 our_unlink(tmp);
6171 fs_give((void **)&tmp);
6174 if(linep) fs_give((void **)&linep);
6175 if(lineq) fs_give((void **)&lineq);
6177 return(-1);
6182 * The srcstr is UTF-8. In order to help the user with
6183 * running this pine and an old pre-alpine pine on the same config
6184 * file we attempt to convert the values of the config variables
6185 * to the user's character set before writing.
6186 * parameters: char **buf. Memory of size_t buflen allocated by caller.
6188 char *
6189 backcompat_convert_from_utf8(char **buf, size_t buflen, char *srcstr)
6191 char *converted = NULL;
6192 char *p;
6193 int its_ascii = 1;
6196 for(p = srcstr; *p && its_ascii; p++)
6197 if(*p & 0x80)
6198 its_ascii = 0;
6200 /* if it is ascii, go with that */
6201 if(its_ascii){
6202 strncpy(*buf, srcstr, buflen);
6203 converted = *buf;
6204 (*buf)[buflen-1] = '\0';
6206 else{
6207 char *trythischarset = NULL;
6210 * If it is possible to translate the UTF-8
6211 * string into the user's character set then
6212 * do that. For backwards compatibility with
6213 * old pines.
6215 if(ps_global->keyboard_charmap && ps_global->keyboard_charmap[0])
6216 trythischarset = ps_global->keyboard_charmap;
6217 else if(ps_global->display_charmap && ps_global->display_charmap[0])
6218 trythischarset = ps_global->display_charmap;
6220 if(trythischarset){
6221 SIZEDTEXT src, dst;
6223 src.data = (unsigned char *) srcstr;
6224 src.size = strlen(srcstr);
6225 memset(&dst, 0, sizeof(dst));
6226 if(utf8_cstext(&src, trythischarset, &dst, 0)){
6227 if(dst.data){
6228 strncpy(*buf, (char *) dst.data, buflen);
6229 (*buf)[buflen-1] = '\0';
6230 fs_give((void **) &dst.data);
6235 if(!converted){
6236 strncpy(*buf, srcstr, buflen);
6237 (*buf)[buflen-1] = '\0';
6238 converted = *buf;
6242 return(converted);
6247 * Given a unix-style source string which may contain LFs,
6248 * convert those to CRLFs if appropriate.
6250 * Returns a pointer to the converted string. This will be a string
6251 * stored in tmp_20k_buf.
6253 * This is just used for the variable descriptions in the pinerc file. It
6254 * could certainly be fancier. It simply converts all \n to NEWLINE.
6256 char *
6257 native_nl(char *src)
6259 char *q, *p;
6261 tmp_20k_buf[0] = '\0';
6263 if(src){
6264 for(q = (char *)tmp_20k_buf; *src; src++){
6265 if(*src == '\n'){
6266 for(p = NEWLINE; *p; p++)
6267 *q++ = *p;
6269 else
6270 *q++ = *src;
6273 *q = '\0';
6276 return((char *)tmp_20k_buf);
6280 void
6281 quit_to_edit_msg(PINERC_S *prc)
6283 /* TRANSLATORS: The %s is either "Postload " or nothing. A Postload config file
6284 is a type of config file. */
6285 q_status_message1(SM_ORDER, 3, 4, _("Must quit Alpine to change %sconfig file."),
6286 (prc == ps_global->post_prc) ? "Postload " : "");
6290 /*------------------------------------------------------------
6291 Return TRUE if the given string was a feature name present in the
6292 pinerc as it was when pine was started...
6293 ----*/
6295 var_in_pinerc(char *s)
6297 PINERC_LINE *pline;
6299 for(pline = ps_global->prc ? ps_global->prc->pinerc_lines : NULL;
6300 pline && (pline->var || pline->line); pline++)
6301 if(pline->var && pline->var->name && !strucmp(s, pline->var->name))
6302 return(1);
6304 for(pline = ps_global->post_prc ? ps_global->post_prc->pinerc_lines : NULL;
6305 pline && (pline->var || pline->line); pline++)
6306 if(pline->var && pline->var->name && !strucmp(s, pline->var->name))
6307 return(1);
6309 return(0);
6313 /*------------------------------------------------------------
6314 Free resources associated with pinerc_lines data
6315 ----*/
6316 void
6317 free_pinerc_lines(PINERC_LINE **pinerc_lines)
6319 PINERC_LINE *pline;
6321 if(pinerc_lines && *pinerc_lines){
6322 for(pline = *pinerc_lines; pline->var || pline->line; pline++)
6323 if(pline->line)
6324 fs_give((void **)&pline->line);
6326 fs_give((void **)pinerc_lines);
6331 /*------------------------------------------------------------
6332 Dump out a global pine.conf on the standard output with fresh
6333 comments. Preserves variables currently set in SYSTEM_PINERC, if any.
6334 ----*/
6335 void
6336 dump_global_conf(void)
6338 FILE *f;
6339 struct variable *var;
6340 PINERC_S *prc;
6342 prc = new_pinerc_s(SYSTEM_PINERC);
6343 read_pinerc(prc, variables, ParseGlobal);
6344 if(prc)
6345 free_pinerc_s(&prc);
6347 f = stdout;
6348 if(f == NULL)
6349 goto io_err;
6351 fprintf(f, "# %s -- system wide pine configuration\n#\n",
6352 SYSTEM_PINERC);
6353 fprintf(f, "# Values here affect all pine users unless they've overridden the values\n");
6354 fprintf(f, "# in their .pinerc files. A copy of this file with current comments may\n");
6355 fprintf(f, "# be obtained by running \"pine -conf\". It will be printed to standard output.\n#\n");
6356 fprintf(f,"# For a variable to be unset its value must be null/blank. This is not the\n");
6357 fprintf(f,"# same as the value of \"empty string\", which can be used to effectively\n");
6358 fprintf(f,"# \"unset\" a variable that has a default or previously assigned value.\n");
6359 fprintf(f,"# To set a variable to the empty string its value should be \"\".\n");
6360 fprintf(f,"# Switch variables are set to either \"yes\" or \"no\", and default to \"no\".\n");
6361 fprintf(f,"# Except for feature-list items, which are additive, values set in the\n");
6362 fprintf(f,"# .pinerc file replace those in pine.conf, and those in pine.conf.fixed\n");
6363 fprintf(f,"# over-ride all others. Features can be over-ridden in .pinerc or\n");
6364 fprintf(f,"# pine.conf.fixed by pre-pending the feature name with \"no-\".\n#\n");
6365 fprintf(f,"# (These comments are automatically inserted.)\n");
6367 for(var = variables; var->name != NULL; var++){
6368 if(!var->is_global || !var->is_used || var->is_obsolete)
6369 continue;
6371 if(var->descrip && *var->descrip){
6372 if(fprintf(f, "\n# %s\n", var->descrip) == EOF)
6373 goto io_err;
6376 if(var->is_list){
6377 if(var->global_val.l == NULL){
6378 if(fprintf(f, "%s=\n", var->name) == EOF)
6379 goto io_err;
6380 }else{
6381 int i;
6383 for(i=0; var->global_val.l[i]; i++)
6384 if(fprintf(f, "%s%s%s%s\n", (i) ? "\t" : var->name,
6385 (i) ? "" : "=", var->global_val.l[i],
6386 var->global_val.l[i+1] ? ",":"") == EOF)
6387 goto io_err;
6389 }else{
6390 if(var->global_val.p == NULL){
6391 if(fprintf(f, "%s=\n", var->name) == EOF)
6392 goto io_err;
6393 }else if(strlen(var->global_val.p) == 0){
6394 if(fprintf(f, "%s=\"\"\n", var->name) == EOF)
6395 goto io_err;
6396 }else{
6397 if(fprintf(f,"%s=%s\n",var->name,var->global_val.p) == EOF)
6398 goto io_err;
6402 exit(0);
6405 io_err:
6406 fprintf(stderr, "Error writing config to stdout: %s\n",
6407 error_description(errno));
6408 exit(-1);
6412 /*------------------------------------------------------------
6413 Dump out a pinerc to filename with fresh
6414 comments. Preserves variables currently set in pinerc, if any.
6415 ----*/
6416 void
6417 dump_new_pinerc(char *filename)
6419 FILE *f;
6420 struct variable *var;
6421 char buf[MAXPATH], *p;
6422 PINERC_S *prc;
6425 p = ps_global->pinerc;
6427 #if defined(DOS) || defined(OS2)
6428 if(!ps_global->pinerc){
6429 char *p;
6431 if(p = getenv("PINERC")){
6432 ps_global->pinerc = cpystr(p);
6433 }else{
6434 char buf2[MAXPATH];
6435 build_path(buf2, ps_global->home_dir, DF_PINEDIR, sizeof(buf2));
6436 build_path(buf, buf2, SYSTEM_PINERC, sizeof(buf));
6439 p = buf;
6441 #else /* !DOS */
6442 if(!ps_global->pinerc){
6443 build_path(buf, ps_global->home_dir, ".pinerc", sizeof(buf));
6444 p = buf;
6446 #endif /* !DOS */
6448 prc = new_pinerc_s(p);
6449 read_pinerc(prc, variables, ParsePers);
6450 if(prc)
6451 free_pinerc_s(&prc);
6453 f = NULL;;
6454 if(filename[0] == '\0'){
6455 fprintf(stderr, "Missing argument to \"-pinerc\".\n");
6456 }else if(!strcmp(filename, "-")){
6457 f = stdout;
6458 }else{
6459 f = our_fopen(filename, "wb");
6462 if(f == NULL)
6463 goto io_err;
6465 if(fprintf(f, "%s", cf_text_comment) == EOF)
6466 goto io_err;
6468 for(var = variables; var->name != NULL; var++){
6469 dprint((7,"write_pinerc: %s = %s\n",
6470 var->name ? var->name : "?",
6471 var->main_user_val.p ? var->main_user_val.p : "<not set>"));
6472 if(!var->is_user || !var->is_used || var->is_obsolete)
6473 continue;
6476 * set description to NULL to eliminate preceding
6477 * blank and comment line.
6479 if(var->descrip && *var->descrip){
6480 if(fprintf(f, "\n# %s\n", var->descrip) == EOF)
6481 goto io_err;
6484 if(var->is_list){
6485 if(var->main_user_val.l == NULL){
6486 if(fprintf(f, "%s=\n", var->name) == EOF)
6487 goto io_err;
6488 }else{
6489 int i;
6491 for(i=0; var->main_user_val.l[i]; i++)
6492 if(fprintf(f, "%s%s%s%s\n", (i) ? "\t" : var->name,
6493 (i) ? "" : "=", var->main_user_val.l[i],
6494 var->main_user_val.l[i+1] ? ",":"") == EOF)
6495 goto io_err;
6497 }else{
6498 if(var->main_user_val.p == NULL){
6499 if(fprintf(f, "%s=\n", var->name) == EOF)
6500 goto io_err;
6501 }else if(strlen(var->main_user_val.p) == 0){
6502 if(fprintf(f, "%s=\"\"\n", var->name) == EOF)
6503 goto io_err;
6504 }else{
6505 if(fprintf(f,"%s=%s\n",var->name,var->main_user_val.p) == EOF)
6506 goto io_err;
6510 exit(0);
6513 io_err:
6514 snprintf(buf, sizeof(buf), "Error writing config to %s: %s\n",
6515 filename, error_description(errno));
6516 exceptional_exit(buf, -1);
6520 /*----------------------------------------------------------------------
6521 Set a user variable and save the .pinerc
6523 Args: var -- The index of the variable to set from conftype.h (V_....)
6524 value -- The string to set the value to
6526 Result: -1 is returned on failure and 0 is returned on success
6528 The vars data structure is updated and the pinerc saved.
6529 ----*/
6531 set_variable(int var, char *value, int expand, int commit, EditWhich which)
6533 struct variable *v;
6534 char **apval;
6535 PINERC_S *prc = NULL;
6537 v = &ps_global->vars[var];
6539 if(!v->is_user)
6540 panic1("Trying to set non-user variable %s", v->name);
6542 /* Override value of which, at most one of these should be set */
6543 if(v->is_onlymain)
6544 which = Main;
6545 else if(v->is_outermost)
6546 which = ps_global->ew_for_except_vars;
6548 apval = APVAL(v, which);
6550 if(!apval)
6551 return(-1);
6553 if(*apval)
6554 fs_give((void **)apval);
6556 *apval = value ? cpystr(value) : NULL;
6557 set_current_val(v, expand, FALSE);
6559 switch(which){
6560 case Main:
6561 prc = ps_global->prc;
6562 break;
6563 case Post:
6564 prc = ps_global->post_prc;
6565 break;
6566 default:
6567 break;
6570 if(prc)
6571 prc->outstanding_pinerc_changes = 1;
6573 return(commit ? write_pinerc(ps_global, which, WRP_NONE) : 0);
6577 /*----------------------------------------------------------------------
6578 Set a user variable list and save the .pinerc
6580 Args: var -- The index of the variable to set from conftype.h (V_....)
6581 lvalue -- The list to set the value to
6583 Result: -1 is returned on failure and 0 is returned on success
6585 The vars data structure is updated and if write_it, the pinerc is saved.
6586 ----*/
6588 set_variable_list(int var, char **lvalue, int write_it, EditWhich which)
6590 char ***alval;
6591 int i;
6592 struct variable *v = &ps_global->vars[var];
6593 PINERC_S *prc = NULL;
6595 if(!v->is_user || !v->is_list)
6596 panic1("BOTCH: Trying to set non-user or non-list variable %s", v->name);
6598 /* Override value of which, at most one of these should be set */
6599 if(v->is_onlymain)
6600 which = Main;
6601 else if(v->is_outermost)
6602 which = ps_global->ew_for_except_vars;
6604 alval = ALVAL(v, which);
6605 if(!alval)
6606 return(-1);
6608 if(*alval)
6609 free_list_array(alval);
6611 if(lvalue){
6612 for(i = 0; lvalue[i] ; i++) /* count elements */
6615 *alval = (char **) fs_get((i+1) * sizeof(char *));
6617 for(i = 0; lvalue[i] ; i++)
6618 (*alval)[i] = cpystr(lvalue[i]);
6620 (*alval)[i] = NULL;
6623 set_current_val(v, TRUE, FALSE);
6625 switch(which){
6626 case Main:
6627 prc = ps_global->prc;
6628 break;
6629 case Post:
6630 prc = ps_global->post_prc;
6631 break;
6632 default:
6633 break;
6636 if(prc)
6637 prc->outstanding_pinerc_changes = 1;
6639 return(write_it ? write_pinerc(ps_global, which, WRP_NONE) : 0);
6643 void
6644 set_current_color_vals(struct pine *ps)
6646 struct variable *vars = ps->vars;
6647 int later_color_is_set = 0;
6649 set_current_val(&vars[V_NORM_FORE_COLOR], TRUE, TRUE);
6650 set_current_val(&vars[V_NORM_BACK_COLOR], TRUE, TRUE);
6651 pico_nfcolor(VAR_NORM_FORE_COLOR);
6652 pico_nbcolor(VAR_NORM_BACK_COLOR);
6654 set_current_val(&vars[V_REV_FORE_COLOR], TRUE, TRUE);
6655 set_current_val(&vars[V_REV_BACK_COLOR], TRUE, TRUE);
6656 pico_rfcolor(VAR_REV_FORE_COLOR);
6657 pico_rbcolor(VAR_REV_BACK_COLOR);
6659 set_color_val(&vars[V_TITLE_FORE_COLOR], 1);
6660 set_color_val(&vars[V_TITLECLOSED_FORE_COLOR], 0);
6661 set_color_val(&vars[V_FOLDER_FORE_COLOR], 0);
6662 set_color_val(&vars[V_DIRECTORY_FORE_COLOR], 0);
6663 set_color_val(&vars[V_FOLDER_LIST_FORE_COLOR], 0);
6664 set_color_val(&vars[V_STATUS_FORE_COLOR], 1);
6665 set_color_val(&vars[V_KEYLABEL_FORE_COLOR], 1);
6666 set_color_val(&vars[V_KEYNAME_FORE_COLOR], 1);
6667 set_color_val(&vars[V_SLCTBL_FORE_COLOR], 1);
6668 set_color_val(&vars[V_METAMSG_FORE_COLOR], 1);
6669 set_color_val(&vars[V_PROMPT_FORE_COLOR], 1);
6670 set_color_val(&vars[V_HEADER_GENERAL_FORE_COLOR], 1);
6671 set_color_val(&vars[V_IND_PLUS_FORE_COLOR], 0);
6672 set_color_val(&vars[V_IND_IMP_FORE_COLOR], 0);
6673 set_color_val(&vars[V_IND_DEL_FORE_COLOR], 0);
6674 set_color_val(&vars[V_IND_HIPRI_FORE_COLOR], 0);
6675 set_color_val(&vars[V_IND_LOPRI_FORE_COLOR], 0);
6676 set_color_val(&vars[V_IND_ANS_FORE_COLOR], 0);
6677 set_color_val(&vars[V_IND_NEW_FORE_COLOR], 0);
6678 set_color_val(&vars[V_IND_REC_FORE_COLOR], 0);
6679 set_color_val(&vars[V_IND_FWD_FORE_COLOR], 0);
6680 set_color_val(&vars[V_IND_UNS_FORE_COLOR], 0);
6681 set_color_val(&vars[V_IND_ARR_FORE_COLOR], 0);
6682 set_color_val(&vars[V_IND_SUBJ_FORE_COLOR], 0);
6683 set_color_val(&vars[V_IND_FROM_FORE_COLOR], 0);
6684 set_color_val(&vars[V_IND_OP_FORE_COLOR], 0);
6685 set_color_val(&vars[V_INCUNSEEN_FORE_COLOR], 0);
6686 set_color_val(&vars[V_SIGNATURE_FORE_COLOR], 0);
6688 set_current_val(&ps->vars[V_INDEX_TOKEN_COLORS], TRUE, TRUE);
6689 set_current_val(&ps->vars[V_VIEW_HDR_COLORS], TRUE, TRUE);
6690 set_current_val(&ps->vars[V_KW_COLORS], TRUE, TRUE);
6691 set_custom_spec_colors(ps);
6694 * Set up the quoting colors. If a later color is set but not an earlier
6695 * color we set the earlier color to Normal to make it easier when
6696 * we go to use the colors. However, if the only quote colors set are
6697 * Normal that is the same as no settings, so delete them.
6699 set_color_val(&vars[V_QUOTE1_FORE_COLOR], 0);
6700 set_color_val(&vars[V_QUOTE2_FORE_COLOR], 0);
6701 set_color_val(&vars[V_QUOTE3_FORE_COLOR], 0);
6703 if((!(VAR_QUOTE3_FORE_COLOR && VAR_QUOTE3_BACK_COLOR) ||
6704 (!strucmp(VAR_QUOTE3_FORE_COLOR, VAR_NORM_FORE_COLOR) &&
6705 !strucmp(VAR_QUOTE3_BACK_COLOR, VAR_NORM_BACK_COLOR))) &&
6706 (!(VAR_QUOTE2_FORE_COLOR && VAR_QUOTE2_BACK_COLOR) ||
6707 (!strucmp(VAR_QUOTE2_FORE_COLOR, VAR_NORM_FORE_COLOR) &&
6708 !strucmp(VAR_QUOTE2_BACK_COLOR, VAR_NORM_BACK_COLOR))) &&
6709 (!(VAR_QUOTE1_FORE_COLOR && VAR_QUOTE1_BACK_COLOR) ||
6710 (!strucmp(VAR_QUOTE1_FORE_COLOR, VAR_NORM_FORE_COLOR) &&
6711 !strucmp(VAR_QUOTE1_BACK_COLOR, VAR_NORM_BACK_COLOR)))){
6713 * They are all either Normal or not set. Delete them all.
6715 if(VAR_QUOTE3_FORE_COLOR)
6716 fs_give((void **)&VAR_QUOTE3_FORE_COLOR);
6717 if(VAR_QUOTE3_BACK_COLOR)
6718 fs_give((void **)&VAR_QUOTE3_BACK_COLOR);
6719 if(VAR_QUOTE2_FORE_COLOR)
6720 fs_give((void **)&VAR_QUOTE2_FORE_COLOR);
6721 if(VAR_QUOTE2_BACK_COLOR)
6722 fs_give((void **)&VAR_QUOTE2_BACK_COLOR);
6723 if(VAR_QUOTE1_FORE_COLOR)
6724 fs_give((void **)&VAR_QUOTE1_FORE_COLOR);
6725 if(VAR_QUOTE1_BACK_COLOR)
6726 fs_give((void **)&VAR_QUOTE1_BACK_COLOR);
6728 else{ /* something is non-Normal */
6729 if(VAR_QUOTE3_FORE_COLOR && VAR_QUOTE3_BACK_COLOR)
6730 later_color_is_set++;
6732 /* if 3 is set but not 2, set 2 to Normal */
6733 if(VAR_QUOTE2_FORE_COLOR && VAR_QUOTE2_BACK_COLOR)
6734 later_color_is_set++;
6735 else if(later_color_is_set)
6736 set_color_val(&vars[V_QUOTE2_FORE_COLOR], 1);
6738 /* if 3 or 2 is set but not 1, set 1 to Normal */
6739 if(VAR_QUOTE1_FORE_COLOR && VAR_QUOTE1_BACK_COLOR)
6740 later_color_is_set++;
6741 else if(later_color_is_set)
6742 set_color_val(&vars[V_QUOTE1_FORE_COLOR], 1);
6745 #ifdef _WINDOWS
6746 if(ps->pre441){
6747 int conv_main = 0, conv_post = 0;
6749 ps->pre441 = 0;
6750 if(ps->prc && !unix_color_style_in_pinerc(ps->prc)){
6751 conv_main = convert_pc_gray_names(ps, ps->prc, Main);
6752 if(conv_main)
6753 ps->prc->outstanding_pinerc_changes = 1;
6757 if(ps->post_prc && !unix_color_style_in_pinerc(ps->post_prc)){
6758 conv_post = convert_pc_gray_names(ps, ps->post_prc, Post);
6759 if(conv_post)
6760 ps->post_prc->outstanding_pinerc_changes = 1;
6763 if(conv_main || conv_post){
6764 if(conv_main)
6765 write_pinerc(ps, Main, WRP_NONE);
6767 if(conv_post)
6768 write_pinerc(ps, Post, WRP_NONE);
6770 set_current_color_vals(ps);
6773 #endif /* _WINDOWS */
6775 pico_set_normal_color();
6780 * Set current_val for the foreground and background color vars, which
6781 * are assumed to be in order. If a set_current_val on them doesn't
6782 * produce current_vals, then use the colors from defvar to set those
6783 * current_vals.
6785 void
6786 set_color_val(struct variable *v, int use_default)
6788 set_current_val(v, TRUE, TRUE);
6789 set_current_val(v+1, TRUE, TRUE);
6791 if(!(v->current_val.p && v->current_val.p[0] &&
6792 (v+1)->current_val.p && (v+1)->current_val.p[0])){
6793 struct variable *defvar;
6795 if(v->current_val.p)
6796 fs_give((void **)&v->current_val.p);
6797 if((v+1)->current_val.p)
6798 fs_give((void **)&(v+1)->current_val.p);
6800 if(!use_default)
6801 return;
6803 if(var_defaults_to_rev(v))
6804 defvar = &ps_global->vars[V_REV_FORE_COLOR];
6805 else
6806 defvar = &ps_global->vars[V_NORM_FORE_COLOR];
6808 /* use default vars values instead */
6809 if(defvar && defvar->current_val.p && defvar->current_val.p[0] &&
6810 (defvar+1)->current_val.p && (defvar+1)->current_val.p[0]){
6811 v->current_val.p = cpystr(defvar->current_val.p);
6812 (v+1)->current_val.p = cpystr((defvar+1)->current_val.p);
6819 var_defaults_to_rev(struct variable *v)
6821 return(v == &ps_global->vars[V_REV_FORE_COLOR] ||
6822 v == &ps_global->vars[V_TITLE_FORE_COLOR] ||
6823 v == &ps_global->vars[V_STATUS_FORE_COLOR] ||
6824 v == &ps_global->vars[V_KEYNAME_FORE_COLOR] ||
6825 v == &ps_global->vars[V_PROMPT_FORE_COLOR]);
6831 * Each item in the list looks like:
6833 * /HDR=<header>/FG=<foreground color>/BG=<background color>
6835 * We separate the three pieces into an array of structures to make
6836 * it easier to deal with later.
6838 void
6839 set_custom_spec_colors(struct pine *ps)
6841 if(ps->index_token_colors)
6842 free_spec_colors(&ps->index_token_colors);
6844 ps->index_token_colors = spec_colors_from_varlist(ps->VAR_INDEX_TOKEN_COLORS, 1);
6846 if(ps->hdr_colors)
6847 free_spec_colors(&ps->hdr_colors);
6849 ps->hdr_colors = spec_colors_from_varlist(ps->VAR_VIEW_HDR_COLORS, 1);
6851 /* fit keyword colors into the same structures for code re-use */
6852 if(ps->kw_colors)
6853 free_spec_colors(&ps->kw_colors);
6855 ps->kw_colors = spec_colors_from_varlist(ps->VAR_KW_COLORS, 1);
6860 * Input is one item from config variable.
6862 * Return value must be freed by caller. The return is a single SPEC_COLOR_S,
6863 * not a list.
6865 SPEC_COLOR_S *
6866 spec_color_from_var(char *t, int already_expanded)
6868 char *p, *spec, *fg, *bg;
6869 PATTERN_S *val;
6870 SPEC_COLOR_S *new_hcolor = NULL;
6872 if(t && t[0] && !strcmp(t, INHERIT)){
6873 new_hcolor = (SPEC_COLOR_S *)fs_get(sizeof(*new_hcolor));
6874 memset((void *)new_hcolor, 0, sizeof(*new_hcolor));
6875 new_hcolor->inherit = 1;
6877 else if(t && t[0]){
6878 char tbuf[10000];
6880 if(!already_expanded){
6881 tbuf[0] = '\0';
6882 if(expand_variables(tbuf, sizeof(tbuf), t, 0))
6883 t = tbuf;
6886 spec = fg = bg = NULL;
6887 val = NULL;
6888 if((p = srchstr(t, "/HDR=")) != NULL)
6889 spec = remove_backslash_escapes(p+5);
6890 if((p = srchstr(t, "/FG=")) != NULL)
6891 fg = remove_backslash_escapes(p+4);
6892 if((p = srchstr(t, "/BG=")) != NULL)
6893 bg = remove_backslash_escapes(p+4);
6894 val = parse_pattern("VAL", t, 0);
6896 if(spec && *spec){
6897 /* remove colons */
6898 if((p = strindex(spec, ':')) != NULL)
6899 *p = '\0';
6901 new_hcolor = (SPEC_COLOR_S *)fs_get(sizeof(*new_hcolor));
6902 memset((void *)new_hcolor, 0, sizeof(*new_hcolor));
6903 new_hcolor->spec = spec;
6904 new_hcolor->fg = fg;
6905 new_hcolor->bg = bg;
6906 new_hcolor->val = val;
6908 else{
6909 if(spec)
6910 fs_give((void **)&spec);
6911 if(fg)
6912 fs_give((void **)&fg);
6913 if(bg)
6914 fs_give((void **)&bg);
6915 if(val)
6916 free_pattern(&val);
6920 return(new_hcolor);
6925 * Input is a list from config file.
6927 * Return value may be a list of SPEC_COLOR_S and must be freed by caller.
6929 SPEC_COLOR_S *
6930 spec_colors_from_varlist(char **varlist, int already_expanded)
6932 char **s, *t;
6933 SPEC_COLOR_S *new_hc = NULL;
6934 SPEC_COLOR_S *new_hcolor, **nexthc;
6936 nexthc = &new_hc;
6937 if(varlist){
6938 for(s = varlist; (t = *s) != NULL; s++){
6939 if(t[0]){
6940 new_hcolor = spec_color_from_var(t, already_expanded);
6941 if(new_hcolor){
6942 *nexthc = new_hcolor;
6943 nexthc = &new_hcolor->next;
6949 return(new_hc);
6954 * Returns allocated charstar suitable for config var for a single
6955 * SPEC_COLOR_S.
6957 char *
6958 var_from_spec_color(SPEC_COLOR_S *hc)
6960 char *ret_val = NULL;
6961 char *p, *spec = NULL, *fg = NULL, *bg = NULL, *val = NULL;
6962 size_t len;
6964 if(hc && hc->inherit)
6965 ret_val = cpystr(INHERIT);
6966 else if(hc){
6967 if(hc->spec)
6968 spec = add_viewerhdr_escapes(hc->spec);
6969 if(hc->fg)
6970 fg = add_viewerhdr_escapes(hc->fg);
6971 if(hc->bg)
6972 bg = add_viewerhdr_escapes(hc->bg);
6973 if(hc->val){
6974 p = pattern_to_string(hc->val);
6975 if(p){
6976 val = add_viewerhdr_escapes(p);
6977 fs_give((void **)&p);
6981 len = strlen("/HDR=/FG=/BG=") + strlen(spec ? spec : "") +
6982 strlen(fg ? fg : "") + strlen(bg ? bg : "") +
6983 strlen(val ? "/VAL=" : "") + strlen(val ? val : "");
6984 ret_val = (char *) fs_get(len + 1);
6985 snprintf(ret_val, len+1, "/HDR=%s/FG=%s/BG=%s%s%s",
6986 spec ? spec : "", fg ? fg : "", bg ? bg : "",
6987 val ? "/VAL=" : "", val ? val : "");
6989 if(spec)
6990 fs_give((void **)&spec);
6991 if(fg)
6992 fs_give((void **)&fg);
6993 if(bg)
6994 fs_give((void **)&bg);
6995 if(val)
6996 fs_give((void **)&val);
6999 return(ret_val);
7004 * Returns allocated charstar suitable for config var for a single
7005 * SPEC_COLOR_S.
7007 char **
7008 varlist_from_spec_colors(SPEC_COLOR_S *hcolors)
7010 SPEC_COLOR_S *hc;
7011 char **ret_val = NULL;
7012 int i;
7014 /* count how many */
7015 for(hc = hcolors, i = 0; hc; hc = hc->next, i++)
7018 ret_val = (char **)fs_get((i+1) * sizeof(*ret_val));
7019 memset((void *)ret_val, 0, (i+1) * sizeof(*ret_val));
7020 for(hc = hcolors, i = 0; hc; hc = hc->next, i++)
7021 ret_val[i] = var_from_spec_color(hc);
7023 return(ret_val);
7027 void
7028 update_posting_charset(struct pine *ps, int revert)
7030 #ifndef _WINDOWS
7031 if(F_ON(F_USE_SYSTEM_TRANS, ps)){
7032 if(!revert)
7033 q_status_message(SM_ORDER, 5, 5, _("This change has no effect because feature Use-System-Translation is on"));
7035 else{
7036 #endif /* ! _WINDOWS */
7037 if(ps->posting_charmap)
7038 fs_give((void **) &ps->posting_charmap);
7040 if(ps->VAR_POST_CHAR_SET){
7041 ps->posting_charmap = cpystr(ps->VAR_POST_CHAR_SET);
7042 if(!posting_charset_is_supported(ps->posting_charmap)){
7043 snprintf(tmp_20k_buf, SIZEOF_20KBUF,
7044 _("Posting-Character set \"%s\" is unsupported, using UTF-8"),
7045 ps->posting_charmap);
7046 q_status_message(SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
7047 fs_give((void **) &ps->posting_charmap);
7048 ps->posting_charmap = cpystr("UTF-8");
7051 else
7052 ps->posting_charmap = cpystr("UTF-8");
7053 #ifndef _WINDOWS
7055 #endif /* ! _WINDOWS */
7059 #define FIXED_COMMENT _("(fixed)")
7060 #define DEFAULT_COMMENT _("(default)")
7061 #define OVERRIDE_COMMENT _("(overridden)")
7064 feature_gets_an_x(struct pine *ps, struct variable *var, FEATURE_S *feature,
7065 char **comment, EditWhich ew)
7067 char **lval, **lvalexc, **lvalnorm;
7068 char *def = DEFAULT_COMMENT;
7069 int j, done = 0;
7070 int feature_fixed_on = 0, feature_fixed_off = 0;
7072 if(comment)
7073 *comment = NULL;
7075 lval = LVAL(var, ew);
7076 lvalexc = LVAL(var, ps->ew_for_except_vars);
7077 lvalnorm = LVAL(var, Main);
7079 /* feature value is administratively fixed */
7080 if((j = feature_in_list(var->fixed_val.l, feature->name)) != 0){
7081 if(j == 1)
7082 feature_fixed_on++;
7083 else if(j == -1)
7084 feature_fixed_off++;
7086 done++;
7087 if(comment)
7088 *comment = FIXED_COMMENT;
7092 * We have an exceptions config setting which overrides anything
7093 * we do here, in the normal config.
7095 if(!done &&
7096 ps->ew_for_except_vars != Main && ew == Main &&
7097 feature_in_list(lvalexc, feature->name)){
7098 done++;
7099 if(comment)
7100 *comment = OVERRIDE_COMMENT;
7104 * Feature is set On in default but not set here.
7106 if(!done &&
7107 !feature_in_list(lval, feature->name) &&
7108 ((feature_in_list(var->global_val.l, feature->name) == 1) ||
7109 ((ps->ew_for_except_vars != Main &&
7110 ew == ps->ew_for_except_vars &&
7111 feature_in_list(lvalnorm, feature->name) == 1)))){
7112 done = 17;
7113 if(comment)
7114 *comment = def;
7117 if(!done &&
7118 feature->defval &&
7119 !feature_in_list(lval, feature->name) &&
7120 !feature_in_list(var->global_val.l, feature->name) &&
7121 (ps->ew_for_except_vars == Main ||
7122 ew != ps->ew_for_except_vars ||
7123 !feature_in_list(lvalnorm, feature->name))){
7124 done = 17;
7125 if(comment)
7126 *comment = def;
7129 return(feature_fixed_on ||
7130 (!feature_fixed_off &&
7131 (done == 17 ||
7132 test_feature(lval, feature->name,
7133 test_old_growth_bits(ps, feature->id)))));
7136 #if !defined(_WINDOWS) || defined(WINDOWS_UNIXSSL_CERTS)
7137 void
7138 set_system_certs_path(struct pine *ps)
7140 char **l;
7142 for (l = ps->vars[V_SSLCAPATH].current_val.l; l && *l; l++){
7143 if(is_absolute_path(*l)
7144 && can_access(*l, ACCESS_EXISTS) == 0
7145 && can_access(*l, READ_ACCESS) == 0){
7146 mail_parameters(NULL, SET_SSLCAPATH, (void *) *l);
7147 break;
7153 void
7154 set_system_certs_container(struct pine *ps)
7156 char **l;
7158 for (l = ps->vars[V_SSLCAFILE].current_val.l; l && *l; l++){
7159 if(is_absolute_path(*l)
7160 && can_access(*l, ACCESS_EXISTS) == 0
7161 && can_access(*l, READ_ACCESS) == 0){
7162 mail_parameters(NULL, SET_SSLCAFILE, (void *) *l);
7163 break;
7168 void
7169 set_user_certs_path(struct pine *ps)
7171 char **l;
7173 for (l = ps->vars[V_USERSSLCAPATH].current_val.l; l && *l; l++){
7174 if(is_absolute_path(*l)
7175 && can_access(*l, ACCESS_EXISTS) == 0
7176 && can_access(*l, READ_ACCESS) == 0){
7177 mail_parameters(NULL, SET_SSLAPPCAPATH, (void *) *l);
7178 break;
7184 void
7185 set_user_certs_container(struct pine *ps)
7187 char **l;
7189 for (l = ps->vars[V_USERSSLCAFILE].current_val.l; l && *l; l++){
7190 if(is_absolute_path(*l)
7191 && can_access(*l, ACCESS_EXISTS) == 0
7192 && can_access(*l, READ_ACCESS) == 0){
7193 mail_parameters(NULL, SET_SSLAPPCAFILE, (void *) *l);
7194 break;
7198 #endif
7201 longest_feature_comment(struct pine *ps, EditWhich ew)
7203 int lc = 0;
7205 lc = MAX(lc, utf8_width(FIXED_COMMENT));
7206 lc = MAX(lc, utf8_width(DEFAULT_COMMENT));
7207 if(ps->ew_for_except_vars != Main && ew == Main)
7208 lc = MAX(lc, utf8_width(OVERRIDE_COMMENT));
7210 return(lc);
7214 void
7215 toggle_feature(struct pine *ps, struct variable *var, FEATURE_S *f,
7216 int just_flip_value, EditWhich ew)
7218 char **vp, *p, **lval, ***alval;
7219 int og, on_before, was_set;
7220 char *err;
7221 long l;
7223 og = test_old_growth_bits(ps, f->id);
7226 * if this feature is in the fixed set, or old-growth is in the fixed
7227 * set and this feature is in the old-growth set, don't alter it...
7229 for(vp = var->fixed_val.l; vp && *vp; vp++){
7230 p = (struncmp(*vp, "no-", 3)) ? *vp : *vp + 3;
7231 if(!strucmp(p, f->name) || (og && !strucmp(p, "old-growth"))){
7232 q_status_message(SM_ORDER, 3, 3,
7233 /* TRANSLATORS: In the configuration screen, telling the user we
7234 can't change this option because the system administrator
7235 prohibits it. */
7236 _("Can't change value fixed by sys-admin."));
7237 return;
7241 on_before = F_ON(f->id, ps);
7243 lval = LVAL(var, ew);
7244 alval = ALVAL(var, ew);
7245 if(just_flip_value)
7246 was_set = test_feature(lval, f->name, og);
7247 else
7248 was_set = feature_gets_an_x(ps, var, f, NULL, ew);
7250 if(alval)
7251 set_feature(alval, f->name, !was_set);
7253 set_feature_list_current_val(var);
7254 process_feature_list(ps, var->current_val.l, 0, 0, 0);
7257 * Handle any features that need special attention here...
7259 if(on_before != F_ON(f->id, ps))
7260 switch(f->id){
7261 case F_QUOTE_ALL_FROMS :
7262 mail_parameters(NULL,SET_FROMWIDGET,F_ON(f->id,ps) ? VOIDT : NIL);
7263 break;
7265 case F_FAKE_NEW_IN_NEWS :
7266 if(IS_NEWS(ps->mail_stream))
7267 q_status_message(SM_ORDER | SM_DING, 3, 4,
7268 "news-approximates-new-status won't affect current newsgroup until next open");
7270 break;
7272 case F_COLOR_LINE_IMPORTANT :
7273 case F_DATES_TO_LOCAL :
7274 clear_index_cache(ps->mail_stream, 0);
7275 break;
7277 case F_DISABLE_INDEX_LOCALE_DATES :
7278 reset_index_format();
7279 clear_index_cache(ps->mail_stream, 0);
7280 break;
7282 case F_MARK_FOR_CC :
7283 clear_index_cache(ps->mail_stream, 0);
7284 if(THREADING() && sp_viewing_a_thread(ps->mail_stream))
7285 unview_thread(ps, ps->mail_stream, ps->msgmap);
7287 break;
7289 case F_HIDE_NNTP_PATH :
7290 mail_parameters(NULL, SET_NNTPHIDEPATH,
7291 F_ON(f->id, ps) ? VOIDT : NIL);
7292 break;
7294 case F_MAILDROPS_PRESERVE_STATE :
7295 mail_parameters(NULL, SET_SNARFPRESERVE,
7296 F_ON(f->id, ps) ? VOIDT : NIL);
7297 break;
7299 case F_DISABLE_SHARED_NAMESPACES :
7300 mail_parameters(NULL, SET_DISABLEAUTOSHAREDNS,
7301 F_ON(f->id, ps) ? VOIDT : NIL);
7302 break;
7304 case F_QUELL_LOCK_FAILURE_MSGS :
7305 mail_parameters(NULL, SET_LOCKEACCESERROR,
7306 F_ON(f->id, ps) ? VOIDT : NIL);
7307 break;
7309 case F_MULNEWSRC_HOSTNAMES_AS_TYPED :
7310 l = F_ON(f->id, ps) ? 0L : 1L;
7311 mail_parameters(NULL, SET_NEWSRCCANONHOST, (void *) l);
7312 break;
7314 case F_QUELL_INTERNAL_MSG :
7315 mail_parameters(NULL, SET_USERHASNOLIFE,
7316 F_ON(f->id, ps) ? VOIDT : NIL);
7317 break;
7319 case F_DISABLE_SETLOCALE_COLLATE :
7320 set_collation(F_OFF(F_DISABLE_SETLOCALE_COLLATE, ps), 1);
7321 break;
7323 #ifndef _WINDOWS
7324 case F_USE_SYSTEM_TRANS :
7325 err = NULL;
7326 reset_character_set_stuff(&err);
7327 if(err){
7328 q_status_message(SM_ORDER | SM_DING, 3, 4, err);
7329 fs_give((void **) &err);
7332 break;
7333 #endif /* ! _WINDOWS */
7335 case F_ENABLE_INCOMING_CHECKING :
7336 if(!on_before && F_OFF(F_ENABLE_INCOMING, ps))
7337 q_status_message(SM_ORDER, 0, 3, _("This option has no effect without Enable-Incoming-Folders"));
7339 clear_incoming_valid_bits();
7340 break;
7342 case F_INCOMING_CHECKING_TOTAL :
7343 case F_INCOMING_CHECKING_RECENT :
7344 if(!on_before && F_OFF(F_ENABLE_INCOMING_CHECKING, ps))
7345 q_status_message(SM_ORDER, 0, 3, _("This option has no effect without Enable-Incoming-Folders-Checking"));
7347 clear_incoming_valid_bits();
7348 break;
7350 case F_THREAD_SORTS_BY_ARRIVAL :
7351 clear_index_cache(ps->mail_stream, 0);
7352 refresh_sort(ps->mail_stream, sp_msgmap(ps->mail_stream), SRT_NON);
7353 break;
7355 #ifdef SMIME
7356 case F_DONT_DO_SMIME :
7357 smime_deinit();
7358 break;
7360 #ifdef APPLEKEYCHAIN
7361 case F_PUBLICCERTS_IN_KEYCHAIN :
7362 smime_deinit();
7363 break;
7364 #endif
7365 #endif
7367 default :
7368 break;
7374 * Returns 1 -- Feature is in the list and positive
7375 * 0 -- Feature is not in the list at all
7376 * -1 -- Feature is in the list and negative (no-)
7379 feature_in_list(char **l, char *f)
7381 char *p;
7382 int rv = 0, forced_off;
7384 for(; l && *l; l++){
7385 p = (forced_off = !struncmp(*l, "no-", 3)) ? *l + 3 : *l;
7386 if(!strucmp(p, f))
7387 rv = forced_off ? -1 : 1;
7390 return(rv);
7395 * test_feature - runs thru a feature list, and returns:
7396 * 1 if feature explicitly set and matches 'v'
7397 * 0 if feature not explicitly set *or* doesn't match 'v'
7400 test_feature(char **l, char *f, int g)
7402 char *p;
7403 int rv = 0, forced_off;
7405 for(; l && *l; l++){
7406 p = (forced_off = !struncmp(*l, "no-", 3)) ? *l + 3 : *l;
7407 if(!strucmp(p, f))
7408 rv = !forced_off;
7409 else if(g && !strucmp(p, "old-growth"))
7410 rv = !forced_off;
7413 return(rv);
7417 void
7418 set_feature(char ***l, char *f, int v)
7420 char **list = l ? *l : NULL, newval[256];
7421 int count = 0;
7423 snprintf(newval, sizeof(newval), "%s%s", v ? "" : "no-", f);
7424 for(; list && *list; list++, count++)
7425 if((**list == '\0') /* anything can replace an empty value */
7426 || !strucmp(((!struncmp(*list, "no-", 3)) ? *list + 3 : *list), f)){
7427 fs_give((void **)list); /* replace with new value */
7428 *list = cpystr(newval);
7429 return;
7433 * if we got here, we didn't find it in the list, so grow the list
7434 * and add it..
7436 if(!*l)
7437 *l = (char **)fs_get((count + 2) * sizeof(char *));
7438 else
7439 fs_resize((void **)l, (count + 2) * sizeof(char *));
7441 (*l)[count] = cpystr(newval);
7442 (*l)[count + 1] = NULL;
7447 reset_character_set_stuff(char **err)
7449 int use_system = 0;
7450 char buf[1000];
7452 if(err)
7453 *err = NULL;
7455 if(ps_global->display_charmap)
7456 fs_give((void **) &ps_global->display_charmap);
7458 if(ps_global->keyboard_charmap)
7459 fs_give((void **) &ps_global->keyboard_charmap);
7461 if(ps_global->posting_charmap)
7462 fs_give((void **) &ps_global->posting_charmap);
7464 #ifdef _WINDOWS
7465 ps_global->display_charmap = cpystr("UTF-8");
7466 #else /* UNIX */
7467 if(ps_global->VAR_CHAR_SET)
7468 ps_global->display_charmap = cpystr(ps_global->VAR_CHAR_SET);
7469 else{
7470 #if HAVE_LANGINFO_H && defined(CODESET)
7471 ps_global->display_charmap = cpystr(nl_langinfo_codeset_wrapper());
7472 #else
7473 ps_global->display_charmap = cpystr("UTF-8");
7474 #endif
7476 #endif /* UNIX */
7478 if(!ps_global->display_charmap)
7479 ps_global->display_charmap = cpystr("US-ASCII");
7481 #ifdef _WINDOWS
7482 ps_global->keyboard_charmap = cpystr("UTF-8");
7483 #else /* UNIX */
7484 if(ps_global->VAR_KEY_CHAR_SET)
7485 ps_global->keyboard_charmap = cpystr(ps_global->VAR_KEY_CHAR_SET);
7486 else
7487 ps_global->keyboard_charmap = cpystr(ps_global->display_charmap);
7489 if(!ps_global->keyboard_charmap)
7490 ps_global->keyboard_charmap = cpystr("US-ASCII");
7492 if(F_ON(F_USE_SYSTEM_TRANS, ps_global)){
7493 #if PREREQ_FOR_SYS_TRANSLATION
7494 use_system++;
7495 /* This modifies its arguments */
7496 if(setup_for_input_output(use_system, &ps_global->display_charmap,
7497 &ps_global->keyboard_charmap,
7498 &ps_global->input_cs, (err && *err) ? NULL : err) == -1)
7499 return -1;
7500 #endif
7502 #endif /* UNIX */
7504 if(!use_system){
7505 if(setup_for_input_output(use_system, &ps_global->display_charmap,
7506 &ps_global->keyboard_charmap,
7507 &ps_global->input_cs, (err && *err) ? NULL : err) == -1)
7508 return -1;
7511 if(!use_system && ps_global->VAR_POST_CHAR_SET){
7512 ps_global->posting_charmap = cpystr(ps_global->VAR_POST_CHAR_SET);
7513 if(!posting_charset_is_supported(ps_global->posting_charmap)){
7514 if(err && !*err){
7515 snprintf(buf, sizeof(buf),
7516 _("Posting-Character-Set \"%s\" is unsupported, using UTF-8"),
7517 ps_global->posting_charmap);
7518 *err = cpystr(buf);
7521 fs_give((void **) &ps_global->posting_charmap);
7522 ps_global->posting_charmap = cpystr("UTF-8");
7525 else{
7526 if(use_system && ps_global->VAR_POST_CHAR_SET
7527 && strucmp(ps_global->VAR_POST_CHAR_SET, "UTF-8"))
7528 if(err && !*err)
7529 *err = cpystr(_("Posting-Character-Set is ignored with Use-System-Translation turned on"));
7531 ps_global->posting_charmap = cpystr("UTF-8");
7534 set_locale_charmap(ps_global->keyboard_charmap);
7536 return(0);
7541 * Given a single printer string from the config file, returns pointers
7542 * to alloc'd strings containing the printer nickname, the command,
7543 * the init string, the trailer string, everything but the nickname string,
7544 * and everything but the command string. All_but_cmd includes the trailing
7545 * space at the end (the one before the command) but all_but_nick does not
7546 * include the leading space (the one before the [).
7547 * If you pass in a pointer it is guaranteed to come back pointing to an
7548 * allocated string, even if it is just an empty string. It is ok to pass
7549 * NULL for any of the six return strings.
7551 void
7552 parse_printer(char *input, char **nick, char **cmd, char **init, char **trailer,
7553 char **all_but_nick, char **all_but_cmd)
7555 char *p, *q, *start, *saved_options = NULL;
7556 int tmpsave, cnt;
7558 if(!input)
7559 input = "";
7561 if(nick || all_but_nick){
7562 if((p = srchstr(input, " [")) != NULL){
7563 if(all_but_nick)
7564 *all_but_nick = cpystr(p+1);
7566 if(nick){
7567 while(p-1 > input && isspace((unsigned char)*(p-1)))
7568 p--;
7570 tmpsave = *p;
7571 *p = '\0';
7572 *nick = cpystr(input);
7573 *p = tmpsave;
7576 else{
7577 if(nick)
7578 *nick = cpystr("");
7580 if(all_but_nick)
7581 *all_but_nick = cpystr(input);
7585 if((p = srchstr(input, "] ")) != NULL){
7587 ++p;
7588 }while(isspace((unsigned char)*p));
7590 tmpsave = *p;
7591 *p = '\0';
7592 saved_options = cpystr(input);
7593 *p = tmpsave;
7595 else
7596 p = input;
7598 if(cmd)
7599 *cmd = cpystr(p);
7601 if(init){
7602 if(saved_options && (p = srchstr(saved_options, "INIT="))){
7603 start = p + strlen("INIT=");
7604 for(cnt=0, p = start; *p && *(p+1) && isxpair(p); p += 2)
7605 cnt++;
7607 q = *init = (char *)fs_get((cnt + 1) * sizeof(char));
7608 for(p = start; *p && *(p+1) && isxpair(p); p += 2)
7609 *q++ = read_hex(p);
7611 *q = '\0';
7613 else
7614 *init = cpystr("");
7617 if(trailer){
7618 if(saved_options && (p = srchstr(saved_options, "TRAILER="))){
7619 start = p + strlen("TRAILER=");
7620 for(cnt=0, p = start; *p && *(p+1) && isxpair(p); p += 2)
7621 cnt++;
7623 q = *trailer = (char *)fs_get((cnt + 1) * sizeof(char));
7624 for(p = start; *p && *(p+1) && isxpair(p); p += 2)
7625 *q++ = read_hex(p);
7627 *q = '\0';
7629 else
7630 *trailer = cpystr("");
7633 if(all_but_cmd){
7634 if(saved_options)
7635 *all_but_cmd = saved_options;
7636 else
7637 *all_but_cmd = cpystr("");
7639 else if(saved_options)
7640 fs_give((void **)&saved_options);
7645 copy_pinerc(char *local, char *remote, char **err_msg)
7647 return(copy_localfile_to_remotefldr(RemImap, local, remote,
7648 REMOTE_PINERC_SUBTYPE,
7649 err_msg));
7654 copy_abook(char *local, char *remote, char **err_msg)
7656 return(copy_localfile_to_remotefldr(RemImap, local, remote,
7657 REMOTE_ABOOK_SUBTYPE,
7658 err_msg));
7663 * Copy local file to remote folder.
7665 * Args remotetype -- type of remote folder
7666 * local -- name of local file
7667 * remote -- name of remote folder
7668 * subtype --
7670 * Returns 0 on success.
7673 copy_localfile_to_remotefldr(RemType remotetype, char *local, char *remote,
7674 char *subtype, char **err_msg)
7676 int retfail = -1;
7677 unsigned flags;
7678 REMDATA_S *rd;
7680 dprint((9, "copy_localfile_to_remotefldr(%s,%s)\n",
7681 local ? local : "<null>",
7682 remote ? remote : "<null>"));
7684 *err_msg = (char *)fs_get(MAXPATH * sizeof(char));
7686 if(!local || !*local){
7687 snprintf(*err_msg, MAXPATH, _("No local file specified"));
7688 return(retfail);
7691 if(!remote || !*remote){
7692 snprintf(*err_msg, MAXPATH, _("No remote folder specified"));
7693 return(retfail);
7696 if(!IS_REMOTE(remote)){
7697 snprintf(*err_msg, MAXPATH, _("Remote folder name \"%s\" %s"), remote,
7698 (*remote != '{') ? _("must begin with \"{\"") : _("not valid"));
7699 return(retfail);
7702 if(IS_REMOTE(local)){
7703 snprintf(*err_msg, MAXPATH, _("First argument \"%s\" must be a local filename"),
7704 local);
7705 return(retfail);
7708 if(can_access(local, ACCESS_EXISTS) != 0){
7709 snprintf(*err_msg, MAXPATH, _("Local file \"%s\" does not exist"), local);
7710 return(retfail);
7713 if(can_access(local, READ_ACCESS) != 0){
7714 snprintf(*err_msg, MAXPATH, _("Can't read local file \"%s\": %s"),
7715 local, error_description(errno));
7716 return(retfail);
7720 * Check if remote folder exists and create it if it doesn't.
7722 flags = 0;
7723 rd = rd_create_remote(remotetype, remote, subtype,
7724 &flags, _("Error: "), _("Can't copy to remote folder."));
7726 if(!rd || rd->access == NoExists){
7727 snprintf(*err_msg, MAXPATH, _("Can't create \"%s\""), remote);
7728 if(rd)
7729 rd_free_remdata(&rd);
7731 return(retfail);
7734 if(rd->access == MaybeRorW)
7735 rd->access = ReadWrite;
7737 rd->flags |= (NO_META_UPDATE | DO_REMTRIM);
7738 rd->lf = cpystr(local);
7740 rd_open_remote(rd);
7741 if(!rd_stream_exists(rd)){
7742 snprintf(*err_msg, MAXPATH, _("Can't open remote folder \"%s\""), rd->rn);
7743 rd_free_remdata(&rd);
7744 return(retfail);
7747 if(rd_remote_is_readonly(rd)){
7748 snprintf(*err_msg, MAXPATH, _("Remote folder \"%s\" is readonly"), rd->rn);
7749 rd_free_remdata(&rd);
7750 return(retfail);
7753 switch(rd->type){
7754 case RemImap:
7756 * Empty folder, add a header msg.
7758 if(rd->t.i.stream->nmsgs == 0){
7759 if(rd_init_remote(rd, 1) != 0){
7760 snprintf(*err_msg, MAXPATH,
7761 _("Failed initializing remote folder \"%s\", check debug file"),
7762 rd->rn);
7763 rd_free_remdata(&rd);
7764 return(retfail);
7768 fs_give((void **)err_msg);
7769 *err_msg = NULL;
7770 if(rd_chk_for_hdr_msg(&(rd->t.i.stream), rd, err_msg)){
7771 rd_free_remdata(&rd);
7772 return(retfail);
7775 break;
7777 default:
7778 break;
7781 if(rd_update_remote(rd, NULL) != 0){
7782 snprintf(*err_msg, MAXPATH, _("Error copying to remote folder \"%s\""), rd->rn);
7783 rd_free_remdata(&rd);
7784 return(retfail);
7787 rd_update_metadata(rd, NULL);
7788 rd_close_remdata(&rd);
7790 fs_give((void **)err_msg);
7791 return(0);
7795 /*----------------------------------------------------------------------
7796 Panic pine - call on detected programmatic errors to exit pine, with arg
7798 Input: message -- printf styule string for panic message (see above)
7799 arg -- argument for printf string
7801 Result: The various tty modes are restored
7802 If debugging is active a core dump will be generated
7803 Exits Pine
7804 ----*/
7805 void
7806 panic1(char *message, char *arg)
7808 #define SIZEOFBUF 1001
7809 char buf1[SIZEOFBUF], buf2[SIZEOFBUF];
7811 snprintf(buf1, sizeof(buf1), "%.*s", (int) MAX(SIZEOFBUF - 1 - strlen(message), 0), arg);
7812 snprintf(buf2, sizeof(buf2), message, buf1);
7813 alpine_panic(buf2);
7820 HelpType
7821 config_help(int var, int feature)
7823 switch(var){
7824 case V_FEATURE_LIST :
7825 return(feature_list_help(feature));
7826 break;
7828 case V_PERSONAL_NAME :
7829 return(h_config_pers_name);
7830 case V_USER_ID :
7831 return(h_config_user_id);
7832 case V_USER_DOMAIN :
7833 return(h_config_user_dom);
7834 case V_SMTP_SERVER :
7835 return(h_config_smtp_server);
7836 case V_NNTP_SERVER :
7837 return(h_config_nntp_server);
7838 case V_INBOX_PATH :
7839 return(h_config_inbox_path);
7840 case V_PRUNED_FOLDERS :
7841 return(h_config_pruned_folders);
7842 case V_DEFAULT_FCC :
7843 return(h_config_default_fcc);
7844 case V_DEFAULT_SAVE_FOLDER :
7845 return(h_config_def_save_folder);
7846 case V_POSTPONED_FOLDER :
7847 return(h_config_postponed_folder);
7848 case V_READ_MESSAGE_FOLDER :
7849 return(h_config_read_message_folder);
7850 case V_FORM_FOLDER :
7851 return(h_config_form_folder);
7852 case V_ARCHIVED_FOLDERS :
7853 return(h_config_archived_folders);
7854 case V_SIGNATURE_FILE :
7855 return(h_config_signature_file);
7856 case V_LITERAL_SIG :
7857 return(h_config_literal_sig);
7858 case V_INIT_CMD_LIST :
7859 return(h_config_init_cmd_list);
7860 case V_COMP_HDRS :
7861 return(h_config_comp_hdrs);
7862 case V_CUSTOM_HDRS :
7863 return(h_config_custom_hdrs);
7864 case V_VIEW_HEADERS :
7865 return(h_config_viewer_headers);
7866 case V_VIEW_MARGIN_LEFT :
7867 return(h_config_viewer_margin_left);
7868 case V_VIEW_MARGIN_RIGHT :
7869 return(h_config_viewer_margin_right);
7870 case V_QUOTE_SUPPRESSION :
7871 return(h_config_quote_suppression);
7872 case V_SAVED_MSG_NAME_RULE :
7873 return(h_config_saved_msg_name_rule);
7874 case V_FCC_RULE :
7875 return(h_config_fcc_rule);
7876 case V_SORT_KEY :
7877 return(h_config_sort_key);
7878 case V_AB_SORT_RULE :
7879 return(h_config_ab_sort_rule);
7880 case V_FLD_SORT_RULE :
7881 return(h_config_fld_sort_rule);
7882 case V_POST_CHAR_SET :
7883 return(h_config_post_char_set);
7884 case V_UNK_CHAR_SET :
7885 return(h_config_unk_char_set);
7886 #ifndef _WINDOWS
7887 case V_KEY_CHAR_SET :
7888 return(h_config_key_char_set);
7889 case V_CHAR_SET :
7890 return(h_config_char_set);
7891 #endif /* ! _WINDOWS */
7892 case V_EDITOR :
7893 return(h_config_editor);
7894 case V_SPELLER :
7895 return(h_config_speller);
7896 #ifdef _WINDOWS
7897 case V_DICTIONARY :
7898 return(h_config_aspell_dictionary);
7899 #endif /* _WINDOWS */
7900 case V_DISPLAY_FILTERS :
7901 return(h_config_display_filters);
7902 case V_SEND_FILTER :
7903 return(h_config_sending_filter);
7904 case V_ALT_ADDRS :
7905 return(h_config_alt_addresses);
7906 case V_KEYWORDS :
7907 return(h_config_keywords);
7908 case V_KW_BRACES :
7909 return(h_config_kw_braces);
7910 case V_OPENING_SEP :
7911 return(h_config_opening_sep);
7912 case V_KW_COLORS :
7913 return(h_config_kw_color);
7914 case V_ABOOK_FORMATS :
7915 return(h_config_abook_formats);
7916 case V_INDEX_FORMAT :
7917 return(h_config_index_format);
7918 case V_INCCHECKTIMEO :
7919 return(h_config_incoming_timeo);
7920 case V_INCCHECKINTERVAL :
7921 return(h_config_incoming_interv);
7922 case V_INC2NDCHECKINTERVAL :
7923 return(h_config_incoming_second_interv);
7924 case V_INCCHECKLIST :
7925 return(h_config_incoming_list);
7926 case V_OVERLAP :
7927 return(h_config_viewer_overlap);
7928 case V_MAXREMSTREAM :
7929 return(h_config_maxremstream);
7930 case V_PERMLOCKED :
7931 return(h_config_permlocked);
7932 case V_MARGIN :
7933 return(h_config_scroll_margin);
7934 case V_DEADLETS :
7935 return(h_config_deadlets);
7936 case V_FILLCOL :
7937 return(h_config_composer_wrap_column);
7938 case V_TCPOPENTIMEO :
7939 return(h_config_tcp_open_timeo);
7940 case V_TCPREADWARNTIMEO :
7941 return(h_config_tcp_readwarn_timeo);
7942 case V_TCPWRITEWARNTIMEO :
7943 return(h_config_tcp_writewarn_timeo);
7944 case V_TCPQUERYTIMEO :
7945 return(h_config_tcp_query_timeo);
7946 case V_QUITQUERYTIMEO :
7947 return(h_config_quit_query_timeo);
7948 case V_RSHOPENTIMEO :
7949 return(h_config_rsh_open_timeo);
7950 case V_SSHOPENTIMEO :
7951 return(h_config_ssh_open_timeo);
7952 case V_USERINPUTTIMEO :
7953 return(h_config_user_input_timeo);
7954 case V_REMOTE_ABOOK_VALIDITY :
7955 return(h_config_remote_abook_validity);
7956 case V_REMOTE_ABOOK_HISTORY :
7957 return(h_config_remote_abook_history);
7958 case V_INCOMING_FOLDERS :
7959 return(h_config_incoming_folders);
7960 case V_FOLDER_SPEC :
7961 return(h_config_folder_spec);
7962 case V_NEWS_SPEC :
7963 return(h_config_news_spec);
7964 case V_ADDRESSBOOK :
7965 return(h_config_address_book);
7966 case V_GLOB_ADDRBOOK :
7967 return(h_config_glob_addrbook);
7968 case V_LAST_VERS_USED :
7969 return(h_config_last_vers);
7970 case V_SENDMAIL_PATH :
7971 return(h_config_sendmail_path);
7972 case V_OPER_DIR :
7973 return(h_config_oper_dir);
7974 case V_RSHPATH :
7975 return(h_config_rshpath);
7976 case V_RSHCMD :
7977 return(h_config_rshcmd);
7978 case V_SSHPATH :
7979 return(h_config_sshpath);
7980 case V_SSHCMD :
7981 return(h_config_sshcmd);
7982 case V_NEW_VER_QUELL :
7983 return(h_config_new_ver_quell);
7984 case V_DISABLE_DRIVERS :
7985 return(h_config_disable_drivers);
7986 case V_DISABLE_AUTHS :
7987 return(h_config_disable_auths);
7988 case V_ENCRYPTION_RANGE :
7989 return(h_config_encryption_range);
7990 case V_REMOTE_ABOOK_METADATA :
7991 return(h_config_abook_metafile);
7992 case V_REPLY_STRING :
7993 return(h_config_reply_indent_string);
7994 case V_WORDSEPS :
7995 return(h_config_wordseps);
7996 case V_QUOTE_REPLACE_STRING :
7997 return(h_config_quote_replace_string);
7998 case V_REPLY_INTRO :
7999 return(h_config_reply_intro);
8000 case V_EMPTY_HDR_MSG :
8001 return(h_config_empty_hdr_msg);
8002 case V_STATUS_MSG_DELAY :
8003 return(h_config_status_msg_delay);
8004 case V_ACTIVE_MSG_INTERVAL :
8005 return(h_config_active_msg_interval);
8006 case V_MAILCHECK :
8007 return(h_config_mailcheck);
8008 case V_MAILCHECKNONCURR :
8009 return(h_config_mailchecknoncurr);
8010 case V_MAILDROPCHECK :
8011 return(h_config_maildropcheck);
8012 case V_NNTPRANGE :
8013 return(h_config_nntprange);
8014 case V_NEWS_ACTIVE_PATH :
8015 return(h_config_news_active);
8016 case V_NEWS_SPOOL_DIR :
8017 return(h_config_news_spool);
8018 case V_IMAGE_VIEWER :
8019 return(h_config_image_viewer);
8020 case V_USE_ONLY_DOMAIN_NAME :
8021 return(h_config_domain_name);
8022 case V_LAST_TIME_PRUNE_QUESTION :
8023 return(h_config_prune_date);
8024 case V_UPLOAD_CMD:
8025 return(h_config_upload_cmd);
8026 case V_UPLOAD_CMD_PREFIX:
8027 return(h_config_upload_prefix);
8028 case V_DOWNLOAD_CMD:
8029 return(h_config_download_cmd);
8030 case V_DOWNLOAD_CMD_PREFIX:
8031 return(h_config_download_prefix);
8032 case V_GOTO_DEFAULT_RULE:
8033 return(h_config_goto_default);
8034 case V_INCOMING_STARTUP:
8035 return(h_config_inc_startup);
8036 case V_PRUNING_RULE:
8037 return(h_config_pruning_rule);
8038 case V_REOPEN_RULE:
8039 return(h_config_reopen_rule);
8040 case V_THREAD_DISP_STYLE:
8041 return(h_config_thread_disp_style);
8042 case V_THREAD_INDEX_STYLE:
8043 return(h_config_thread_index_style);
8044 case V_THREAD_MORE_CHAR:
8045 return(h_config_thread_indicator_char);
8046 case V_THREAD_EXP_CHAR:
8047 return(h_config_thread_exp_char);
8048 case V_THREAD_LASTREPLY_CHAR:
8049 return(h_config_thread_lastreply_char);
8050 case V_MAILCAP_PATH :
8051 return(h_config_mailcap_path);
8052 case V_MIMETYPE_PATH :
8053 return(h_config_mimetype_path);
8054 #if !defined(_WINDOWS) || defined(WINDOWS_UNIXSSL_CERTS)
8055 case V_SSLCAPATH :
8056 return(h_config_system_certs_path);
8057 case V_SSLCAFILE :
8058 return(h_config_system_certs_file);
8059 case V_USERSSLCAPATH :
8060 return(h_config_user_certs_path);
8061 case V_USERSSLCAFILE :
8062 return(h_config_user_certs_file);
8063 case V_SSLCIPHERS :
8064 return(h_config_ssl_ciphers);
8065 #endif
8066 #if !defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)
8067 case V_FIFOPATH :
8068 return(h_config_fifopath);
8069 #endif
8070 case V_NMW_WIDTH :
8071 return(h_config_newmailwidth);
8072 case V_NEWSRC_PATH :
8073 return(h_config_newsrc_path);
8074 case V_BROWSER :
8075 return(h_config_browser);
8076 case V_HISTORY :
8077 return(h_config_history);
8078 #if defined(DOS) || defined(OS2)
8079 case V_FILE_DIR :
8080 return(h_config_file_dir);
8081 #endif
8082 case V_NORM_FORE_COLOR :
8083 case V_NORM_BACK_COLOR :
8084 return(h_config_normal_color);
8085 case V_REV_FORE_COLOR :
8086 case V_REV_BACK_COLOR :
8087 return(h_config_reverse_color);
8088 case V_TITLE_FORE_COLOR :
8089 case V_TITLE_BACK_COLOR :
8090 return(h_config_title_color);
8091 case V_TITLECLOSED_FORE_COLOR :
8092 case V_TITLECLOSED_BACK_COLOR :
8093 return(h_config_titleclosed_color);
8094 case V_FOLDER_FORE_COLOR:
8095 return(h_config_folder_color);
8096 case V_DIRECTORY_FORE_COLOR:
8097 return(h_config_directory_color);
8098 case V_FOLDER_LIST_FORE_COLOR:
8099 return(h_config_folder_list_color);
8100 case V_STATUS_FORE_COLOR :
8101 case V_STATUS_BACK_COLOR :
8102 return(h_config_status_color);
8103 case V_SLCTBL_FORE_COLOR :
8104 case V_SLCTBL_BACK_COLOR :
8105 return(h_config_slctbl_color);
8106 case V_QUOTE1_FORE_COLOR :
8107 case V_QUOTE2_FORE_COLOR :
8108 case V_QUOTE3_FORE_COLOR :
8109 case V_QUOTE1_BACK_COLOR :
8110 case V_QUOTE2_BACK_COLOR :
8111 case V_QUOTE3_BACK_COLOR :
8112 return(h_config_quote_color);
8113 case V_INCUNSEEN_FORE_COLOR :
8114 case V_INCUNSEEN_BACK_COLOR :
8115 return(h_config_incunseen_color);
8116 case V_SIGNATURE_FORE_COLOR :
8117 case V_SIGNATURE_BACK_COLOR :
8118 return(h_config_signature_color);
8119 case V_PROMPT_FORE_COLOR :
8120 case V_PROMPT_BACK_COLOR :
8121 return(h_config_prompt_color);
8122 case V_HEADER_GENERAL_FORE_COLOR :
8123 case V_HEADER_GENERAL_BACK_COLOR :
8124 return(h_config_header_general_color);
8125 case V_IND_PLUS_FORE_COLOR :
8126 case V_IND_IMP_FORE_COLOR :
8127 case V_IND_DEL_FORE_COLOR :
8128 case V_IND_ANS_FORE_COLOR :
8129 case V_IND_NEW_FORE_COLOR :
8130 case V_IND_UNS_FORE_COLOR :
8131 case V_IND_REC_FORE_COLOR :
8132 case V_IND_FWD_FORE_COLOR :
8133 case V_IND_PLUS_BACK_COLOR :
8134 case V_IND_IMP_BACK_COLOR :
8135 case V_IND_DEL_BACK_COLOR :
8136 case V_IND_ANS_BACK_COLOR :
8137 case V_IND_NEW_BACK_COLOR :
8138 case V_IND_UNS_BACK_COLOR :
8139 case V_IND_REC_BACK_COLOR :
8140 case V_IND_FWD_BACK_COLOR :
8141 return(h_config_index_color);
8142 case V_IND_OP_FORE_COLOR :
8143 case V_IND_OP_BACK_COLOR :
8144 return(h_config_index_opening_color);
8145 case V_IND_SUBJ_FORE_COLOR :
8146 case V_IND_SUBJ_BACK_COLOR :
8147 return(h_config_index_subject_color);
8148 case V_IND_FROM_FORE_COLOR :
8149 case V_IND_FROM_BACK_COLOR :
8150 return(h_config_index_from_color);
8151 case V_IND_HIPRI_FORE_COLOR :
8152 case V_IND_HIPRI_BACK_COLOR :
8153 case V_IND_LOPRI_FORE_COLOR :
8154 case V_IND_LOPRI_BACK_COLOR :
8155 return(h_config_index_pri_color);
8156 case V_IND_ARR_FORE_COLOR :
8157 case V_IND_ARR_BACK_COLOR :
8158 return(h_config_index_arrow_color);
8159 case V_KEYLABEL_FORE_COLOR :
8160 case V_KEYLABEL_BACK_COLOR :
8161 return(h_config_keylabel_color);
8162 case V_KEYNAME_FORE_COLOR :
8163 case V_KEYNAME_BACK_COLOR :
8164 return(h_config_keyname_color);
8165 case V_METAMSG_FORE_COLOR :
8166 case V_METAMSG_BACK_COLOR :
8167 return(h_config_metamsg_color);
8168 case V_VIEW_HDR_COLORS :
8169 return(h_config_customhdr_color);
8170 case V_INDEX_TOKEN_COLORS :
8171 return(h_config_indextoken_color);
8172 case V_PRINTER :
8173 return(h_config_printer);
8174 case V_PERSONAL_PRINT_CATEGORY :
8175 return(h_config_print_cat);
8176 case V_PERSONAL_PRINT_COMMAND :
8177 return(h_config_print_command);
8178 case V_PAT_ROLES :
8179 return(h_config_pat_roles);
8180 case V_PAT_FILTS :
8181 return(h_config_pat_filts);
8182 case V_PAT_SCORES :
8183 return(h_config_pat_scores);
8184 case V_PAT_INCOLS :
8185 return(h_config_pat_incols);
8186 case V_PAT_OTHER :
8187 return(h_config_pat_other);
8188 case V_PAT_SRCH :
8189 return(h_config_pat_srch);
8190 case V_INDEX_COLOR_STYLE :
8191 return(h_config_index_color_style);
8192 case V_TITLEBAR_COLOR_STYLE :
8193 return(h_config_titlebar_color_style);
8194 #ifdef _WINDOWS
8195 case V_FONT_NAME :
8196 return(h_config_font_name);
8197 case V_FONT_SIZE :
8198 return(h_config_font_size);
8199 case V_FONT_STYLE :
8200 return(h_config_font_style);
8201 case V_FONT_CHAR_SET :
8202 return(h_config_font_char_set);
8203 case V_PRINT_FONT_NAME :
8204 return(h_config_print_font_name);
8205 case V_PRINT_FONT_SIZE :
8206 return(h_config_print_font_size);
8207 case V_PRINT_FONT_STYLE :
8208 return(h_config_print_font_style);
8209 case V_PRINT_FONT_CHAR_SET :
8210 return(h_config_print_font_char_set);
8211 case V_WINDOW_POSITION :
8212 return(h_config_window_position);
8213 case V_CURSOR_STYLE :
8214 return(h_config_cursor_style);
8215 #else
8216 case V_COLOR_STYLE :
8217 return(h_config_color_style);
8218 #endif
8219 #ifdef ENABLE_LDAP
8220 case V_LDAP_SERVERS :
8221 return(h_config_ldap_servers);
8222 #endif
8223 #ifdef SMIME
8224 case V_PUBLICCERT_DIR :
8225 return(h_config_smime_pubcertdir);
8226 case V_PUBLICCERT_CONTAINER :
8227 return(h_config_smime_pubcertcon);
8228 case V_PRIVATEKEY_DIR :
8229 return(h_config_smime_privkeydir);
8230 case V_PRIVATEKEY_CONTAINER :
8231 return(h_config_smime_privkeycon);
8232 case V_CACERT_DIR :
8233 return(h_config_smime_cacertdir);
8234 case V_CACERT_CONTAINER :
8235 return(h_config_smime_cacertcon);
8236 #endif
8237 case V_RSS_NEWS :
8238 return(h_config_rss_news);
8239 case V_RSS_WEATHER :
8240 return(h_config_rss_weather);
8241 case V_WP_INDEXHEIGHT :
8242 return(h_config_wp_indexheight);
8243 case V_WP_INDEXLINES :
8244 return(h_config_wp_indexlines);
8245 case V_WP_AGGSTATE :
8246 return(h_config_wp_aggstate);
8247 case V_WP_STATE :
8248 return(h_config_wp_state);
8249 case V_WP_COLUMNS :
8250 return(h_config_wp_columns);
8251 default :
8252 return(NO_HELP);
8258 * We don't want the user to be able to edit their pinerc and set
8259 * printer to whatever they want if personal-print-command is fixed.
8260 * So make sure printer is set to something legitimate. If it isn't,
8261 * set it to something standard and return non-zero.
8264 printer_value_check_and_adjust(void)
8266 char **tt;
8267 char aname[100], wname[100];
8268 int ok = 0;
8269 struct variable *vars = ps_global->vars;
8271 if(vars[V_PERSONAL_PRINT_COMMAND].is_fixed && !vars[V_PRINTER].is_fixed){
8272 strncpy(aname, ANSI_PRINTER, sizeof(aname));
8273 aname[sizeof(aname)-1] = '\0';
8274 strncat(aname, "-no-formfeed", sizeof(aname)-strlen(aname)-1);
8275 strncpy(wname, WYSE_PRINTER, sizeof(wname));
8276 wname[sizeof(wname)-1] = '\0';
8277 strncat(wname, "-no-formfeed", sizeof(wname)-strlen(wname)-1);
8278 if(strucmp(VAR_PRINTER, ANSI_PRINTER) == 0
8279 || strucmp(VAR_PRINTER, aname) == 0
8280 || strucmp(VAR_PRINTER, WYSE_PRINTER) == 0
8281 || strucmp(VAR_PRINTER, wname) == 0)
8282 ok++;
8283 else if(VAR_STANDARD_PRINTER && VAR_STANDARD_PRINTER[0]){
8284 for(tt = VAR_STANDARD_PRINTER; *tt; tt++)
8285 if(strucmp(VAR_PRINTER, *tt) == 0)
8286 break;
8288 if(*tt)
8289 ok++;
8292 if(!ok){
8293 char *val;
8294 struct variable *v;
8296 if(VAR_STANDARD_PRINTER && VAR_STANDARD_PRINTER[0])
8297 val = VAR_STANDARD_PRINTER[0];
8298 else
8299 val = ANSI_PRINTER;
8301 v = &vars[V_PRINTER];
8302 if(v->main_user_val.p)
8303 fs_give((void **)&v->main_user_val.p);
8304 if(v->post_user_val.p)
8305 fs_give((void **)&v->post_user_val.p);
8306 if(v->current_val.p)
8307 fs_give((void **)&v->current_val.p);
8309 v->main_user_val.p = cpystr(val);
8310 v->current_val.p = cpystr(val);
8314 return(!ok);
8317 #ifdef _WINDOWS
8318 #include <schannel.h>
8319 #include <Schnlsp.h>
8320 #else
8321 #include <openssl/ssl.h>
8322 #endif /* _WINDOWS */
8324 char **
8325 get_supported_options(void)
8327 char **config;
8328 DRIVER *d;
8329 AUTHENTICATOR *a;
8330 char *title = _("Supported features in this Alpine");
8331 char sbuf[MAX_SCREEN_COLS+1], tmp[128];
8332 int cnt, alcnt, len, cols, disabled, any_disabled = 0, i;
8335 * Line count:
8336 * Title + blank = 2
8337 * SSL Title + SSL lines + blank = 5
8338 * Auth title + blank = 2
8339 * Driver title + blank = 2
8340 * LDAP title + LDAP line = 2
8341 * Disabled explanation + blank line = 4
8342 * end = 1
8344 cnt = 18;
8345 for(a = mail_lookup_auth(1); a; a = a->next)
8346 cnt++;
8347 for(d = (DRIVER *)mail_parameters(NIL, GET_DRIVERS, NIL);
8348 d; d = d->next)
8349 cnt++;
8351 alcnt = cnt;
8352 config = (char **) fs_get(alcnt * sizeof(char *));
8353 memset(config, 0, alcnt * sizeof(char *));
8355 cols = ps_global->ttyo ? ps_global->ttyo->screen_cols : 0;
8356 len = utf8_width(title);
8357 snprintf(sbuf, sizeof(sbuf), "%*s%s", cols > len ? (cols-len)/2 : 0, "", title);
8359 cnt = 0;
8360 if(cnt < alcnt)
8361 config[cnt] = cpystr(sbuf);
8363 if(++cnt < alcnt)
8364 config[cnt] = cpystr("");
8366 if(++cnt < alcnt)
8367 /* TRANSLATORS: headings */
8368 config[cnt] = cpystr(_("Encryption:"));
8370 if(++cnt < alcnt && mail_parameters(NIL, GET_SSLDRIVER, NIL)){
8371 config[cnt] = cpystr(_(" TLS and SSL"));
8372 tmp[0] = tmp[1] = ' ';
8373 tmp[2] = '\0';
8374 #ifdef _WINDOWS
8375 #ifdef SP_PROT_SSL3
8376 strcat(tmp, "SSLv3, ");
8377 #endif /* SP_PROT_SSL3 */
8378 #ifdef SP_PROT_TLS1
8379 strcat(tmp, "TLSv1, ");
8380 #endif /* SP_PROT_TLS1 */
8381 #ifdef SP_PROT_TLS1_1
8382 strcat(tmp, "TLSv1.1, ");
8383 #endif /* SP_PROT_TLS1 */
8384 #ifdef SP_PROT_TLS1_2
8385 strcat(tmp, "TLSv1.2, ");
8386 #endif /* SP_PROT_TLS1_2 */
8387 #ifdef SP_PROT_TLS1_3
8388 strcat(tmp, "TLSv1.3, ");
8389 #endif /* SP_PROT_TLS1_3 */
8390 #else
8391 #ifdef SSL3_VERSION
8392 #ifndef OPENSSL_NO_SSL3_METHOD
8393 strcat(tmp, "SSLv3, ");
8394 #endif /* OPENSSL_NO_SSL3_METHOD */
8395 #endif /* SSL3_VERSION */
8396 #ifdef TLS1_VERSION
8397 #ifndef OPENSSL_NO_TLS1_METHOD
8398 strcat(tmp, "TLSv1, ");
8399 #endif /* OPENSSL_NO_TLS1_METHOD */
8400 #endif /* TLS1_VERSION */
8401 #ifdef TLS1_1_VERSION
8402 #ifndef OPENSSL_NO_TLS1_1_METHOD
8403 strcat(tmp, "TLSv1.1, ");
8404 #endif /* OPENSSL_NO_TLS1_1_METHOD */
8405 #endif /* TLS1_1_VERSION */
8406 #ifdef TLS1_2_VERSION
8407 #ifndef OPENSSL_NO_TLS1_2_METHOD
8408 strcat(tmp, "TLSv1.2, ");
8409 #endif /* OPENSSL_NO_TLS1_2_METHOD */
8410 #endif /* TLS1_2_VERSION */
8411 #ifdef TLS1_3_VERSION
8412 #ifndef OPENSSL_NO_TLS1_3_METHOD
8413 strcat(tmp, "TLSv1.3, ");
8414 #endif /* OPENSSL_NO_TLS1_3_METHOD */
8415 #endif /* TLS1_3_VERSION */
8416 #endif /* _WINDOWS */
8417 tmp[strlen(tmp)-2] = '\0';
8419 else
8420 config[cnt] = cpystr(_(" None (no TLS or SSL)"));
8422 if(++cnt < alcnt)
8423 config[cnt] = cpystr(tmp);
8424 #ifdef SMIME
8425 if(++cnt < alcnt)
8426 config[cnt] = cpystr(" S/MIME");
8427 #endif
8429 if(++cnt < alcnt)
8430 config[cnt] = cpystr("");
8432 if(++cnt < alcnt)
8433 config[cnt] = cpystr(_("Authenticators:"));
8435 for(a = mail_lookup_auth(1); a; a = a->next){
8436 disabled = (a->client == NULL && a->server == NULL);
8437 any_disabled += disabled;
8438 snprintf(sbuf, sizeof(sbuf), " %s%s", a->name, disabled ? " (disabled)" : "");
8439 if(++cnt < alcnt)
8440 config[cnt] = cpystr(sbuf);
8443 if(++cnt < alcnt)
8444 config[cnt] = cpystr("");
8446 if(++cnt < alcnt)
8447 config[cnt] = cpystr(_("Mailbox drivers:"));
8449 for(d = (DRIVER *)mail_parameters(NIL, GET_DRIVERS, NIL);
8450 d; d = d->next){
8451 disabled = (d->flags & DR_DISABLE);
8452 any_disabled += disabled;
8453 snprintf(sbuf, sizeof(sbuf), " %s%s", d->name, disabled ? " (disabled)" : "");
8454 if(++cnt < alcnt)
8455 config[cnt] = cpystr(sbuf);
8458 if(++cnt < alcnt)
8459 config[cnt] = cpystr("");
8461 if(++cnt < alcnt)
8462 config[cnt] = cpystr(_("Directories:"));
8464 #ifdef ENABLE_LDAP
8465 if(++cnt < alcnt)
8466 config[cnt] = cpystr(" LDAP");
8467 #else
8468 if(++cnt < alcnt)
8469 config[cnt] = cpystr(" None (no LDAP)");
8470 #endif
8472 if(any_disabled){
8473 if(++cnt < alcnt)
8474 config[cnt] = cpystr("");
8476 if(ps_global->ttyo){
8477 if(++cnt < alcnt)
8478 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."));
8480 else{
8481 if(++cnt < alcnt)
8482 config[cnt] = cpystr(_("Authenticators may be disabled because of the \"disable-these-authenticators\""));
8483 if(++cnt < alcnt)
8484 config[cnt] = cpystr(_("hidden config option. Mailbox drivers may be disabled because of the"));
8485 if(++cnt < alcnt)
8486 config[cnt] = cpystr(_("\"disable-these-drivers\" hidden config option."));
8490 if(++cnt < alcnt)
8491 config[cnt] = NULL;
8493 return(config);
8497 unsigned
8498 reset_startup_rule(MAILSTREAM *stream)
8500 long rflags = ROLE_DO_OTHER;
8501 PAT_STATE pstate;
8502 PAT_S *pat;
8503 unsigned startup_rule;
8505 startup_rule = IS_NOTSET;
8507 if(stream && nonempty_patterns(rflags, &pstate)){
8508 for(pat = first_pattern(&pstate); pat; pat = next_pattern(&pstate)){
8509 if(match_pattern(pat->patgrp, stream, NULL, NULL, NULL,
8510 SE_NOSERVER|SE_NOPREFETCH))
8511 break;
8514 if(pat && pat->action && !pat->action->bogus)
8515 startup_rule = pat->action->startup_rule;
8518 return(startup_rule);
8522 #ifdef _WINDOWS
8524 char *
8525 transformed_color(old)
8526 char *old;
8528 if(!old)
8529 return("");
8531 if(!struncmp(old, "color008", 8))
8532 return("colorlgr");
8533 else if(!struncmp(old, "color009", 8))
8534 return("colormgr");
8535 else if(!struncmp(old, "color010", 8))
8536 return("colordgr");
8538 return("");
8543 * If this is the first time we've run a version > 4.40, and there
8544 * is evidence that the config file has not been used by unix pine,
8545 * then we convert color008 to colorlgr, color009 to colormgr, and
8546 * color010 to colordgr. If the config file is being used by
8547 * unix pine then color008 may really supposed to be color008, color009
8548 * may really supposed to be red, and color010 may really supposed to be
8549 * green. Same if we've already run 4.41 or higher previously.
8551 * Returns 0 if no changes, > 0 if something was changed.
8554 convert_pc_gray_names(ps, prc, which)
8555 struct pine *ps;
8556 PINERC_S *prc;
8557 EditWhich which;
8559 struct variable *v;
8560 int ret = 0, ic = 0;
8561 char **s, *t, *p, *pstr, *new, *pval, **apval, **lval;
8563 for(v = ps->vars; v->name; v++){
8564 if(!color_holding_var(ps, v) || v == &ps->vars[V_KW_COLORS])
8565 continue;
8567 if(v == &ps->vars[V_VIEW_HDR_COLORS]){
8569 if((lval = LVAL(v,which)) != NULL){
8570 /* fix these in place */
8571 for(s = lval; (t = *s) != NULL; s++){
8572 if((p = srchstr(t, "FG=color008")) ||
8573 (p = srchstr(t, "FG=color009")) ||
8574 (p = srchstr(t, "FG=color010"))){
8575 strncpy(p+3, transformed_color(p+3), 8);
8576 ret++;
8579 if((p = srchstr(t, "BG=color008")) ||
8580 (p = srchstr(t, "BG=color009")) ||
8581 (p = srchstr(t, "BG=color010"))){
8582 strncpy(p+3, transformed_color(p+3), 8);
8583 ret++;
8588 else{
8589 if((pval = PVAL(v,which)) != NULL){
8590 apval = APVAL(v,which);
8591 if(apval && (!strucmp(pval, "color008") ||
8592 !strucmp(pval, "color009") ||
8593 !strucmp(pval, "color010"))){
8594 new = transformed_color(pval);
8595 if(*apval)
8596 fs_give((void **)apval);
8598 *apval = cpystr(new);
8599 ret++;
8605 v = &ps->vars[V_PAT_INCOLS];
8606 if((lval = LVAL(v,which)) != NULL){
8607 for(s = lval; (t = *s) != NULL; s++){
8608 if((pstr = srchstr(t, "action=")) != NULL){
8609 if((p = srchstr(pstr, "FG=color008")) ||
8610 (p = srchstr(pstr, "FG=color009")) ||
8611 (p = srchstr(pstr, "FG=color010"))){
8612 strncpy(p+3, transformed_color(p+3), 8);
8613 ic++;
8616 if((p = srchstr(pstr, "BG=color008")) ||
8617 (p = srchstr(pstr, "BG=color009")) ||
8618 (p = srchstr(pstr, "BG=color010"))){
8619 strncpy(p+3, transformed_color(p+3), 8);
8620 ic++;
8626 if(ic)
8627 set_current_val(&ps->vars[V_PAT_INCOLS], TRUE, TRUE);
8629 return(ret+ic);
8634 unix_color_style_in_pinerc(prc)
8635 PINERC_S *prc;
8637 PINERC_LINE *pline;
8639 for(pline = prc ? prc->pinerc_lines : NULL;
8640 pline && (pline->var || pline->line); pline++)
8641 if(pline->line && !struncmp("color-style=", pline->line, 12))
8642 return(1);
8644 return(0);
8647 char *
8648 pcpine_general_help(titlebuf)
8649 char *titlebuf;
8651 if(titlebuf)
8652 strcpy(titlebuf, "PC Alpine For Windows");
8654 return(pcpine_help(h_pine_for_windows));
8657 #endif /* _WINDOWS */