* For mailing lists, Alpine adds a description of the type of link
[alpine.git] / pith / conf.c
blobd25bf14f5da6cc25e4e5b0bd97dac89f969ae2ac
1 /*
2 * ========================================================================
3 * Copyright 2013-2022 Eduardo Chappa
4 * Copyright 2006-2009 University of Washington
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * ========================================================================
15 /*======================================================================
16 conf.c
17 Implements the Pine configuration management routines
18 ====*/
21 #include "../pith/headers.h"
22 #include "../pith/init.h"
23 #include "../pith/conf.h"
24 #include "../pith/state.h"
25 #include "../pith/remote.h"
26 #include "../pith/keyword.h"
27 #include "../pith/mailview.h"
28 #include "../pith/list.h"
29 #include "../pith/status.h"
30 #include "../pith/ldap.h"
31 #include "../pith/folder.h"
32 #include "../pith/thread.h"
33 #include "../pith/news.h"
34 #include "../pith/util.h"
35 #include "../pith/pattern.h"
36 #include "../pith/color.h"
37 #include "../pith/options.h"
38 #include "../pith/busy.h"
39 #include "../pith/readfile.h"
40 #include "../pith/hist.h"
41 #include "../pith/mailindx.h"
42 #include "../pith/tempfile.h"
43 #include "../pith/icache.h"
44 #include "../pith/sort.h"
45 #include "../pith/smime.h"
46 #include "../pith/charconv/utf8.h"
47 #ifdef _WINDOWS
48 #include "../pico/osdep/mswin.h"
49 #endif
51 #define TO_BAIL_THRESHOLD 60
55 * Internal prototypes
57 void convert_configvars_to_utf8(struct variable *, char *);
58 void convert_configvar_to_utf8(struct variable *, char *);
59 void set_current_pattern_vals(struct pine *);
60 void convert_pattern_data(void);
61 void convert_filts_pattern_data(void);
62 void convert_scores_pattern_data(void);
63 void convert_pinerc_patterns(long);
64 void convert_pinerc_filts_patterns(long);
65 void convert_pinerc_scores_patterns(long);
66 void set_old_growth_bits(struct pine *, int);
67 int var_is_in_rest_of_file(char *, char *);
68 char *skip_over_this_var(char *, char *);
69 char *native_nl(char *);
70 void set_color_val(struct variable *, int);
71 int copy_localfile_to_remotefldr(RemType, char *, char *, char *, char **);
72 char *backcompat_convert_from_utf8(char **, size_t, char *);
73 #ifdef _WINDOWS
74 char *transformed_color(char *);
75 int convert_pc_gray_names(struct pine *, PINERC_S *, EditWhich);
76 int unix_color_style_in_pinerc(PINERC_S *);
77 char *pcpine_general_help(char *);
78 char *pcpine_help(HelpType); /* defined in alpine/help */
79 #endif /* _WINDOWS */
82 /* hook too allow caller to decide what to do about failure */
83 int (*pith_opt_remote_pinerc_failure)(void);
86 /*------------------------------------
87 Some definitions to keep the static "variable" array below
88 a bit more readable...
89 ----*/
90 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\
91 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";
94 CONF_TXT_T cf_text_personal_name[] = "Over-rides your full name from Unix password file. Required for PC-Alpine.";
96 CONF_TXT_T cf_text_user_id[] = "Your login/e-mail user name";
98 CONF_TXT_T cf_text_user_domain[] = "Sets domain part of From: and local addresses in outgoing mail.";
100 CONF_TXT_T cf_text_smtp_server[] = "List of SMTP servers for sending mail. If blank: Unix Alpine uses sendmail.";
102 CONF_TXT_T cf_text_nntp_server[] = "NNTP server for posting news. Also sets news-collections for news reading.";
104 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.";
106 #ifdef SMIME
108 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.";
110 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.";
112 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.";
114 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.";
116 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.";
118 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.";
120 #endif /* SMIME */
122 #ifdef ENABLE_LDAP
123 CONF_TXT_T cf_text_ldap_server[] = "LDAP servers for looking up addresses.";
124 #endif /* ENABLE_LDAP */
126 CONF_TXT_T cf_text_rss_news[] = "RSS News feed";
128 CONF_TXT_T cf_text_rss_weather[] = "RSS Weather feed";
130 CONF_TXT_T cf_text_wp_indexheight[] = "Web Alpine index table row height";
132 CONF_TXT_T cf_text_wp_indexlines[] = "Web Alpine number of index lines in table";
134 CONF_TXT_T cf_text_wp_aggstate[] = "Web Alpine aggregate operations tab state";
136 CONF_TXT_T cf_text_wp_state[] = "Web Alpine various aspects of cross-session state";
138 CONF_TXT_T cf_text_wp_columns[] = "Web Alpine preferred width for message display in characters";
140 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).";
142 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";
144 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[]";
146 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}[]";
148 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";
150 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.";
152 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.";
154 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.";
156 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";
158 CONF_TXT_T cf_text_read_message_folder[] = "If set, specifies where already-read messages will be moved upon quitting.";
160 CONF_TXT_T cf_text_form_letter_folder[] = "If set, specifies where form letters should be stored.";
162 CONF_TXT_T cf_text_trash_folder[] = "If set, specifies where trash is moved to in Web Alpine.";
164 CONF_TXT_T cf_text_signature_file[] = "Over-rides default path for signature file. Default is ~/.signature";
166 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.";
168 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";
170 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";
172 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-.";
174 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)";
176 CONF_TXT_T cf_text_default_composer_hdrs[] = "Only show these headers (by default) when composing messages";
178 CONF_TXT_T cf_text_customized_hdrs[] = "Add these customized headers (and possible default values) when composing";
180 CONF_TXT_T cf_text_view_headers[] = "When viewing messages, include this list of headers";
182 CONF_TXT_T cf_text_view_margin_left[] = "When viewing messages, number of blank spaces between left display edge and text";
184 CONF_TXT_T cf_text_view_margin_right[] = "When viewing messages, number of blank spaces between right display edge and text";
186 CONF_TXT_T cf_text_quote_suppression[] = "When viewing messages, number of lines of quote displayed before suppressing";
188 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)";
190 CONF_TXT_T cf_text_color_style[] = "Controls display of color";
192 CONF_TXT_T cf_text_current_indexline_style[] = "Controls display of color for current index line";
194 CONF_TXT_T cf_text_titlebar_color_style[] = "Controls display of color for the titlebar at top of screen";
196 CONF_TXT_T cf_text_view_hdr_color[] = "When viewing messages, these are the header colors";
198 CONF_TXT_T cf_text_index_token_color[] = "Colors in which tokens will be displayed in the index screen";
200 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).";
202 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.)";
204 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\".";
206 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\".";
208 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\".";
210 CONF_TXT_T cf_text_old_char_set[] = "Character-set is obsolete, use display-character-set, keyboard-character-set,\n# and posting-character-set.";
212 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).";
214 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.";
216 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.";
218 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.";
220 CONF_TXT_T cf_text_editor[] = "Specifies the program invoked by ^_ in the Composer,\n# or the \"enable-alternate-editor-implicitly\" feature.";
222 CONF_TXT_T cf_text_speller[] = "Specifies the program invoked by ^T in the Composer.";
224 #ifdef _WINDOWS
225 CONF_TXT_T cf_text_speller_dictionary[] = "Specifies the list of dictionaries used by Aspell.";
226 #endif /* _WINDOWS */
228 CONF_TXT_T cf_text_deadlets[] = "Specifies the number of dead letter files to keep when canceling.";
230 CONF_TXT_T cf_text_fillcol[] = "Specifies the column of the screen where the composer should wrap.";
232 CONF_TXT_T cf_text_replystr[] = "Specifies the string to insert when replying to a message.";
234 CONF_TXT_T cf_text_quotereplstr[] = "Specifies the string to replace quotes with when viewing a message.";
236 CONF_TXT_T cf_text_replyintro[] = "Specifies the introduction to insert when replying to a message.";
238 CONF_TXT_T cf_text_emptyhdr[] = "Specifies the string to use when sending a message with no to or cc.";
240 CONF_TXT_T cf_text_image_viewer[] = "Program to view images (e.g. GIF or TIFF attachments).";
242 CONF_TXT_T cf_text_browser[] = "List of programs to open Internet URLs (e.g. http or ftp references).";
244 CONF_TXT_T cf_text_history[] = "List of directories that are preferred locations to save or export attachments.";
246 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\".";
248 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\".";
250 CONF_TXT_T cf_reopen_rule[] = "Controls behavior when reopening an already open folder.";
252 CONF_TXT_T cf_text_thread_disp_style[] = "Style that MESSAGE INDEX is displayed in when threading.";
254 CONF_TXT_T cf_text_thread_index_style[] = "Style of THREAD INDEX or default MESSAGE INDEX when threading.";
256 CONF_TXT_T cf_text_thread_more_char[] = "When threading, character used to indicate collapsed messages underneath.";
258 CONF_TXT_T cf_text_thread_exp_char[] = "When threading, character used to indicate expanded messages underneath.";
260 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.";
262 CONF_TXT_T cf_text_use_only_domain_name[] = "If \"user-domain\" not set, strips hostname in FROM address. (Unix only)";
264 CONF_TXT_T cf_text_printer[] = "Your default printer selection";
266 CONF_TXT_T cf_text_personal_print_command[] = "List of special print commands";
268 CONF_TXT_T cf_text_personal_print_cat[] = "Which category default print command is in";
270 CONF_TXT_T cf_text_standard_printer[] = "The system wide standard printers";
272 CONF_TXT_T cf_text_xoauth2_info[] = "Your client-id and client-secret information to authenticate using XOAUTH2";
274 CONF_TXT_T cf_text_last_time_prune_quest[] = "Set by Alpine; controls beginning-of-month sent-mail pruning.";
276 CONF_TXT_T cf_text_last_version_used[] = "Set by Alpine; controls display of \"new version\" message.";
278 CONF_TXT_T cf_text_disable_drivers[] = "List of mail drivers to disable.";
280 CONF_TXT_T cf_text_disable_auths[] = "List of SASL authenticators to disable.";
282 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.";
284 CONF_TXT_T cf_text_remote_abook_metafile[] = "Set by Alpine; contains data for caching remote address books.";
286 CONF_TXT_T cf_text_old_patterns[] = "Patterns is obsolete, use patterns-xxx";
288 CONF_TXT_T cf_text_old_filters[] = "Patterns-filters is obsolete, use patterns-filters2";
290 CONF_TXT_T cf_text_old_scores[] = "Patterns-scores is obsolete, use patterns-scores2";
292 CONF_TXT_T cf_text_patterns[] = "Patterns and their actions are stored here.";
294 CONF_TXT_T cf_text_remote_abook_history[] = "How many extra copies of remote address book should be kept. Default: 3";
296 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";
298 CONF_TXT_T cf_text_bugs_fullname[] = "Full name for bug report address used by \"Report Bug\" command";
300 CONF_TXT_T cf_text_bugs_address[] = "Email address used to send bug reports";
302 CONF_TXT_T cf_text_bugs_extras[] = "Program/Script used by \"Report Bug\" command. No default.";
304 CONF_TXT_T cf_text_suggest_fullname[] = "Full name for suggestion address used by \"Report Bug\" command";
306 CONF_TXT_T cf_text_suggest_address[] = "Email address used to send suggestions";
308 CONF_TXT_T cf_text_local_fullname[] = "Full name for \"local support\" address used by \"Report Bug\" command.\n# Default: Local Support";
310 CONF_TXT_T cf_text_local_address[] = "Email address used to send to \"local support\".\n# Default: postmaster";
312 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";
314 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.";
316 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.";
318 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)";
320 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.";
322 CONF_TXT_T cf_text_out_fltr[] = "This defines a program that message text is piped into before MIME\n# encoding, prior to sending";
324 CONF_TXT_T cf_text_alt_addrs[] = "A list of alternate addresses the user is known by";
326 CONF_TXT_T cf_text_keywords[] = "A list of keywords for use in categorizing messages";
328 CONF_TXT_T cf_text_kw_colors[] = "Colors used to display keywords in the index";
330 CONF_TXT_T cf_text_kw_braces[] = "Characters which surround keywords in SUBJKEY token.\n# Default is \"{\" \"} \"";
332 CONF_TXT_T cf_text_opening_sep[] = "Characters between subject and opening text in SUBJECTTEXT token.\n# Default is \" - \"";
334 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";
336 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";
338 CONF_TXT_T cf_text_overlap[] = "The number of lines of overlap when scrolling through message text";
340 CONF_TXT_T cf_text_maxremstreams[] = "The maximum number of non-stayopen remote connections that Alpine will use";
342 CONF_TXT_T cf_text_permlocked[] = "A list of folders that should be left open once opened (INBOX is implicit)";
344 CONF_TXT_T cf_text_margin[] = "Number of lines from top and bottom of screen where single\n# line scrolling occurs.";
346 CONF_TXT_T cf_text_stat_msg_delay[] = "The number of seconds to sleep after writing a status message";
348 CONF_TXT_T cf_text_busy_cue_rate[] = "Number of times per-second to update busy cue messages";
350 CONF_TXT_T cf_text_mailcheck[] = "The approximate number of seconds between checks for new mail";
352 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";
354 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";
356 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";
358 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\".";
360 CONF_TXT_T cf_text_news_spooldir[] = "Directory containing system's news data.\n# The default is typically \"/usr/spool/news\"";
362 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.";
364 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.";
366 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.";
368 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.";
370 CONF_TXT_T cf_text_goto_default[] = "Sets the default folder and collection offered at the Goto Command's prompt.";
372 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.";
374 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.";
376 #if !defined(_WINDOWS) || defined(WINDOWS_UNIXSSL_CERTS)
377 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.";
379 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.";
381 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.";
383 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.";
385 CONF_TXT_T cf_text_ciphers[] = "Colon separated list of ciphers that should be negotiated with the remote\n# ssl server upon connection.";
386 #endif
388 CONF_TXT_T cf_text_newmail_fifo_path[] = "Sets the filename for the newmail fifo (named pipe). Unix only.";
390 CONF_TXT_T cf_text_nmw_width[] = "Sets the width for the NewMail screen.";
392 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.";
394 CONF_TXT_T cf_text_debug_mem[] = "Debug-memory is obsolete";
396 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).";
398 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.";
400 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.";
402 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.";
404 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.";
406 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.";
408 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.";
410 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\")";
412 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.";
414 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.";
416 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.";
418 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.";
420 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.";
422 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.";
424 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\")";
426 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.";
428 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.";
430 CONF_TXT_T cf_text_elm_style_save[] = "Elm-style-save is obsolete, use saved-msg-name-rule";
432 CONF_TXT_T cf_text_header_in_reply[] = "Header-in-reply is obsolete, use include-header-in-reply in feature-list";
434 CONF_TXT_T cf_text_feature_level[] = "Feature-level is obsolete, use feature-list";
436 CONF_TXT_T cf_text_old_style_reply[] = "Old-style-reply is obsolete, use signature-at-bottom in feature-list";
438 CONF_TXT_T cf_text_compose_mime[] = "Compose-mime is obsolete";
440 CONF_TXT_T cf_text_show_all_characters[] = "Show-all-characters is obsolete";
442 CONF_TXT_T cf_text_save_by_sender[] = "Save-by-sender is obsolete, use saved-msg-name-rule";
444 CONF_TXT_T cf_text_file_dir[] = "Default directory used for Attachment handling (attach and save)\n# and Export command output";
446 CONF_TXT_T cf_text_folder_extension[] = "Folder-extension is obsolete";
448 CONF_TXT_T cf_text_normal_foreground_color[] = "Choose: black, blue, green, cyan, red, magenta, yellow, or white.";
450 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.";
452 CONF_TXT_T cf_text_newsrc_path[] = "Full path and name of NEWSRC file";
455 /*----------------------------------------------------------------------
456 These are the variables that control a number of pine functions. They
457 come out of the .pinerc and the /usr/local/lib/pine.conf files. Some can
458 be set by the user while in Alpine. Eventually all the local ones should
459 be so and maybe the global ones too.
461 Each variable can have a command-line, user, global, and current value.
462 All of these values are malloc'd. The user value is the one read out of
463 the user's .pinerc, the global value is the one from the system pine
464 configuration file. There are often defaults for the global values, set
465 at the start of init_vars(). Perhaps someday there will be group values.
466 The current value is the one that is actually in use.
467 ----*/
468 /* name is_changed_val
469 remove_quotes |
470 is_outermost | |
471 is_onlymain | | |
472 is_fixed | | | |
473 is_list | | | | |
474 is_global | | | | | |
475 is_user | | | | | | |
476 been_written | | | | | | | |
477 is_used | | | | | | | | |
478 is_obsolete | | | | | | | | | |
479 | | | | | | | | | | |
480 (on following line) description | | | | | | | | | | |
481 | | | | | | | | | | | |
482 | | | | | | | | | | | | */
483 static struct variable variables[] = {
484 {"personal-name", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
485 NULL, cf_text_personal_name},
487 #if defined(DOS) || defined(OS2)
488 /* Have to have this on DOS, PC's, Macs, etc... */
489 "user-id", 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0,
490 #else /* Don't allow on UNIX machines for some security */
491 "user-id", 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0,
492 #endif
493 "User ID", cf_text_user_id},
494 {"user-domain", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
495 NULL, cf_text_user_domain},
496 {"smtp-server", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
497 "SMTP Server (for sending)", cf_text_smtp_server},
498 {"nntp-server", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
499 "NNTP Server (for news)", cf_text_nntp_server},
500 {"inbox-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
501 NULL, cf_text_inbox_path},
502 {"incoming-archive-folders", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
503 NULL, cf_text_archived_folders},
504 {"pruned-folders", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
505 NULL, cf_text_pruned_folders},
506 {"default-fcc", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
507 "Default Fcc (File carbon copy)", cf_text_default_fcc},
508 {"default-saved-msg-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
509 "Default Saved Message Folder", cf_text_default_saved},
510 {"postponed-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
511 NULL, cf_text_postponed_folder},
512 {"read-message-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
513 NULL, cf_text_read_message_folder},
514 {"form-letter-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
515 NULL, cf_text_form_letter_folder},
516 {"trash-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
517 NULL, cf_text_trash_folder},
518 {"literal-signature", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
519 NULL, cf_text_literal_sig},
520 {"signature-file", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
521 NULL, cf_text_signature_file},
522 {"feature-list", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
523 NULL, cf_text_feature_list},
524 {"initial-keystroke-list", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
525 NULL, cf_text_initial_keystroke_list},
526 {"default-composer-hdrs", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
527 "Default Composer Headers", cf_text_default_composer_hdrs},
528 {"customized-hdrs", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
529 "Customized Headers", cf_text_customized_hdrs},
530 {"viewer-hdrs", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
531 "Viewer Headers", cf_text_view_headers},
532 {"viewer-margin-left", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
533 NULL, cf_text_view_margin_left},
534 {"viewer-margin-right", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
535 NULL, cf_text_view_margin_right},
536 {"quote-suppression-threshold", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
537 NULL, cf_text_quote_suppression},
538 {"saved-msg-name-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
539 "Saved Message Name Rule", cf_text_save_msg_name_rule},
540 {"fcc-name-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
541 NULL, cf_text_fcc_name_rule},
542 {"sort-key", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
543 NULL, cf_text_sort_key},
544 {"addrbook-sort-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
545 "Address Book Sort Rule", cf_text_addrbook_sort_rule},
546 {"folder-sort-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
547 NULL, cf_text_folder_sort_rule},
548 {"goto-default-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
549 NULL, cf_text_goto_default},
550 {"incoming-startup-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
551 NULL, cf_text_inc_startup},
552 {"pruning-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
553 NULL, cf_pruning_rule},
554 {"folder-reopen-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
555 NULL, cf_reopen_rule},
556 {"threading-display-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
557 NULL, cf_text_thread_disp_style},
558 {"threading-index-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
559 NULL, cf_text_thread_index_style},
560 {"threading-indicator-character", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
561 NULL, cf_text_thread_more_char},
562 {"threading-expanded-character", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
563 NULL, cf_text_thread_exp_char},
564 {"threading-lastreply-character", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
565 "Threading Last Reply Character", cf_text_thread_lastreply_char},
566 #ifndef _WINDOWS
567 {"display-character-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
568 NULL, cf_text_disp_char_set},
569 {"character-set", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
570 NULL, cf_text_old_char_set},
571 {"keyboard-character-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
572 NULL, cf_text_key_char_set},
573 #endif /* ! _WINDOWS */
574 {"posting-character-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
575 NULL, cf_text_post_character_set},
576 {"unknown-character-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
577 NULL, cf_text_unk_character_set},
578 {"editor", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
579 NULL, cf_text_editor},
580 {"speller", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
581 NULL, cf_text_speller},
582 #ifdef _WINDOWS
583 {"aspell-dictionary-list", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
584 "Aspell Dictionaries", cf_text_speller_dictionary},
585 #endif /* _WINDOWS */
586 {"composer-wrap-column", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
587 NULL, cf_text_fillcol},
588 {"reply-indent-string", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
589 NULL, cf_text_replystr},
590 {"reply-leadin", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
591 NULL, cf_text_replyintro},
592 {"quote-replace-string", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
593 NULL, cf_text_quotereplstr},
594 {"composer-word-separators", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
595 NULL, cf_text_wordsep},
596 {"empty-header-message", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
597 NULL, cf_text_emptyhdr},
598 {"image-viewer", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
599 NULL, cf_text_image_viewer},
600 {"use-only-domain-name", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
601 NULL, cf_text_use_only_domain_name},
602 {"bugs-fullname", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
603 NULL, cf_text_bugs_fullname},
604 {"bugs-address", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
605 NULL, cf_text_bugs_address},
606 {"bugs-additional-data", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
607 NULL, cf_text_bugs_extras},
608 {"suggest-fullname", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
609 NULL, cf_text_suggest_fullname},
610 {"suggest-address", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
611 NULL, cf_text_suggest_address},
612 {"local-fullname", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
613 NULL, cf_text_local_fullname},
614 {"local-address", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
615 NULL, cf_text_local_address},
616 {"forced-abook-entry", 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0,
617 NULL, cf_text_forced_abook},
618 {"kblock-passwd-count", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
619 NULL, cf_text_kblock_passwd},
620 {"display-filters", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
621 NULL, cf_text_in_fltr},
622 {"sending-filters", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
623 NULL, cf_text_out_fltr},
624 {"alt-addresses", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
625 "Alternate Addresses", cf_text_alt_addrs},
626 {"keywords", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
627 NULL, cf_text_keywords},
628 {"keyword-surrounding-chars", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
629 "Keyword Surrounding Characters", cf_text_kw_braces},
630 {"opening-text-separator-chars", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
631 "Opening Text Separator Characters", cf_text_opening_sep},
632 {"addressbook-formats", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
633 "Address Book Formats", cf_text_abook_formats},
634 {"index-format", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
635 NULL, cf_text_index_format},
636 {"viewer-overlap", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
637 NULL, cf_text_overlap},
638 {"scroll-margin", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
639 NULL, cf_text_margin},
640 {"status-message-delay", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
641 NULL, cf_text_stat_msg_delay},
642 {"busy-cue-rate", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
643 NULL, cf_text_busy_cue_rate},
644 {"mail-check-interval", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
645 NULL, cf_text_mailcheck},
646 {"mail-check-interval-noncurrent", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
647 NULL, cf_text_mailchecknoncurr},
648 {"maildrop-check-minimum", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
649 NULL, cf_text_maildropcheck},
650 {"nntp-range", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
651 "NNTP Range", cf_text_nntprange},
652 {"newsrc-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
653 NULL, cf_text_newsrc_path},
654 {"news-active-file-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
655 NULL, cf_text_news_active},
656 {"news-spool-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
657 NULL, cf_text_news_spooldir},
658 {"upload-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
659 NULL, cf_text_upload_cmd},
660 {"upload-command-prefix", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
661 NULL, cf_text_upload_prefix},
662 {"download-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
663 NULL, cf_text_download_cmd},
664 {"download-command-prefix", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
665 NULL, cf_text_download_prefix},
666 {"mailcap-search-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
667 NULL, cf_text_mailcap_path},
668 {"mimetype-search-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
669 NULL, cf_text_mimetype_path},
670 #if !defined(_WINDOWS) || defined(WINDOWS_UNIXSSL_CERTS)
671 {"system-certs-path", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
672 "System CACerts Dir", cf_text_system_certs_path},
673 {"system-certs-file", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
674 "System CACerts File", cf_text_system_certs_file},
675 {"user-certs-path", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
676 "User Certs Dir", cf_text_user_certs_file},
677 {"user-certs-file", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
678 "User Certs File", cf_text_user_certs_file},
679 {"ssl-ciphers", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
680 "SSL Ciphers", cf_text_ciphers},
681 #endif
682 {"url-viewers", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
683 "URL-Viewers", cf_text_browser},
684 {"default-directories", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
685 "Extra Directories for Save", cf_text_history},
686 {"max-remote-connections", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
687 "Maximum Remote Connections", cf_text_maxremstreams},
688 {"stay-open-folders", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
689 "Stayopen Folders", cf_text_permlocked},
690 {"incoming-check-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
691 NULL, cf_text_inc_check_timeo},
692 {"incoming-check-interval", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
693 NULL, cf_text_inc_check_interval},
694 {"incoming-check-interval-secondary", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
695 NULL, cf_text_inc_second_check_interval},
696 {"incoming-check-list", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
697 NULL, cf_text_inc_check_list},
698 {"dead-letter-files", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
699 NULL, cf_text_deadlets},
700 #if !defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)
701 {"newmail-fifo-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
702 "NewMail FIFO Path", cf_text_newmail_fifo_path},
703 #endif
704 {"newmail-window-width", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
705 "NewMail Window Width", cf_text_nmw_width},
707 * Starting here, the variables are hidden in the Setup/Config screen.
708 * They are exposed if feature expose-hidden-config is set.
710 {"incoming-folders", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
711 NULL, cf_text_incoming_folders},
712 {"mail-directory", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
713 NULL, cf_text_mail_directory},
714 {"folder-collections", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
715 NULL, cf_text_folder_collections},
716 {"news-collections", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
717 NULL, cf_text_news_collections},
718 {"address-book", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
719 NULL, cf_text_address_book},
720 {"global-address-book", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
721 NULL, cf_text_global_address_book},
722 {"standard-printer", 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0,
723 NULL, cf_text_standard_printer},
724 {"last-time-prune-questioned", 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0,
725 NULL, cf_text_last_time_prune_quest},
726 {"last-version-used", 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0,
727 NULL, cf_text_last_version_used},
728 {"sendmail-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
729 NULL, cf_text_sendmail_path},
730 {"operating-dir", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
731 NULL, cf_text_oper_dir},
732 {"user-input-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
733 NULL, cf_text_user_input_timeo},
734 /* OBSOLETE */
735 #ifdef DEBUGJOURNAL
736 {"debug-memory", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
737 NULL, cf_text_debug_mem},
738 #endif
739 {"tcp-open-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
740 "TCP Open Timeout", cf_text_tcp_open_timeo},
741 {"tcp-read-warning-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
742 "TCP Read Warning Timeout", cf_text_tcp_read_timeo},
743 {"tcp-write-warning-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
744 "TCP Write Warning Timeout", cf_text_tcp_write_timeo},
745 {"tcp-query-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
746 "TCP Query Timeout", cf_text_tcp_query_timeo},
747 {"close-connection-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
748 NULL, cf_text_close_connection_timeo},
749 {"rsh-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
750 NULL, cf_text_rsh_command},
751 {"rsh-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
752 NULL, cf_text_rsh_path},
753 {"rsh-open-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
754 NULL, cf_text_rsh_open_timeo},
755 {"ssh-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
756 NULL, cf_text_ssh_command},
757 {"ssh-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
758 NULL, cf_text_ssh_path},
759 {"ssh-open-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
760 NULL, cf_text_ssh_open_timeo},
761 {"new-version-threshold", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
762 NULL, cf_text_version_threshold},
763 {"disable-these-drivers", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
764 NULL, cf_text_disable_drivers},
765 {"disable-these-authenticators", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
766 NULL, cf_text_disable_auths},
767 #ifdef DF_ENCRYPTION_RANGE
768 {"encryption-protocol-range", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
769 NULL, cf_text_encryption_range},
770 #endif /* DF_ENCRYPTION_RANGE */
771 {"remote-abook-metafile", 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0,
772 NULL, cf_text_remote_abook_metafile},
773 {"remote-abook-history", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
774 NULL, cf_text_remote_abook_history},
775 {"remote-abook-validity", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
776 NULL, cf_text_remote_abook_validity},
777 {"printer", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
778 NULL, cf_text_printer},
779 {"personal-print-command", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
780 NULL, cf_text_personal_print_command},
781 {"personal-print-category", 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0,
782 NULL, cf_text_personal_print_cat},
783 {"xoauth2-info", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
784 "XOAUTH2 Info", cf_text_xoauth2_info},
785 {"patterns", 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
786 NULL, cf_text_old_patterns},
787 {"patterns-roles", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
788 NULL, cf_text_patterns},
789 {"patterns-filters2", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
790 "Patterns Filters", cf_text_patterns},
791 {"patterns-filters", 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
792 NULL, cf_text_old_filters},
793 {"patterns-scores2", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
794 "Patterns Scores", cf_text_patterns},
795 {"patterns-scores", 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
796 NULL, cf_text_old_scores},
797 {"patterns-indexcolors", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
798 NULL, cf_text_patterns},
799 {"patterns-other", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
800 NULL, cf_text_patterns},
801 {"patterns-search", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
802 NULL, cf_text_patterns},
803 /* OBSOLETE VARS */
804 {"elm-style-save", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
805 NULL, cf_text_elm_style_save},
806 {"header-in-reply", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
807 NULL, cf_text_header_in_reply},
808 {"feature-level", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
809 NULL, cf_text_feature_level},
810 {"old-style-reply", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
811 NULL, cf_text_old_style_reply},
812 {"compose-mime", 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
813 NULL, cf_text_compose_mime},
814 {"show-all-characters", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
815 NULL, cf_text_show_all_characters},
816 {"save-by-sender", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
817 NULL, cf_text_save_by_sender},
818 #if defined(DOS) || defined(OS2)
819 {"file-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
820 NULL, cf_text_file_dir},
821 {"folder-extension", 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0,
822 NULL, cf_text_folder_extension},
823 #endif
824 #ifndef _WINDOWS
825 {"color-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
826 NULL, cf_text_color_style},
827 #endif
828 {"current-indexline-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
829 NULL, cf_text_current_indexline_style},
830 {"titlebar-color-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
831 NULL, cf_text_titlebar_color_style},
832 {"normal-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
833 NULL, cf_text_normal_foreground_color},
834 {"normal-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
835 {"reverse-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
836 {"reverse-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
837 {"title-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
838 {"title-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
839 {"title-closed-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
840 {"title-closed-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
841 {"folder-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
842 {"folder-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
843 {"directory-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
844 {"directory-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
845 {"folder-list-text-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
846 {"folder-list-text-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
847 {"status-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
848 {"status-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
849 {"keylabel-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
850 {"keylabel-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
851 {"keyname-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
852 {"keyname-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
853 {"selectable-item-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
854 {"selectable-item-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
855 {"meta-message-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
856 {"meta-message-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
857 {"quote1-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
858 {"quote1-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
859 {"quote2-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
860 {"quote2-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
861 {"quote3-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
862 {"quote3-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
863 {"incoming-unseen-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
864 {"incoming-unseen-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
865 {"signature-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
866 {"signature-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
867 {"prompt-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
868 {"prompt-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
869 {"header-general-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
870 {"header-general-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
871 {"index-to-me-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
872 {"index-to-me-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
873 {"index-important-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
874 {"index-important-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
875 {"index-deleted-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
876 {"index-deleted-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
877 {"index-answered-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
878 {"index-answered-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
879 {"index-new-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
880 {"index-new-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
881 {"index-recent-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
882 {"index-recent-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
883 {"index-forward-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
884 {"index-forward-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
885 {"index-unseen-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
886 {"index-unseen-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
887 {"index-highpriority-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
888 {"index-highpriority-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
889 {"index-lowpriority-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
890 {"index-lowpriority-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
891 {"index-arrow-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
892 {"index-arrow-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
893 {"index-subject-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
894 {"index-subject-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
895 {"index-from-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
896 {"index-from-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
897 {"index-opening-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
898 {"index-opening-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
899 {"index-token-colors", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
900 NULL, cf_text_index_token_color},
901 {"viewer-hdr-colors", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
902 "Viewer Header Colors", cf_text_view_hdr_color},
903 {"keyword-colors", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
904 NULL, cf_text_kw_colors},
905 #ifdef _WINDOWS
906 {"font-name", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
907 NULL, "name and size of font."},
908 {"font-size", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
909 {"font-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
910 {"font-char-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
911 {"print-font-name", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
912 NULL, "name and size of printer font."},
913 {"print-font-size", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
914 {"print-font-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
915 {"print-font-char-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
916 {"window-position", 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0,
917 NULL, cf_text_window_position},
918 {"cursor-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
919 #endif /* _WINDOWS */
920 {"html-messages-directory", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
921 NULL, cf_html_directory},
922 #ifdef SMIME
923 {"smime-public-cert-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
924 "S/MIME - Public Cert Directory", cf_text_publiccertdir},
925 {"smime-public-cert-container", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
926 "S/MIME - Public Cert Container", cf_text_publiccertcontainer},
927 {"smime-private-key-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
928 "S/MIME - Private Key Directory", cf_text_privatekeydir},
929 {"smime-private-key-container", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
930 "S/MIME - Private Key Container", cf_text_privatekeycontainer},
931 {"smime-cacert-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
932 "S/MIME - Cert Authority Directory", cf_text_cacertdir},
933 {"smime-cacert-container", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
934 "S/MIME - Cert Authority Container", cf_text_cacertcontainer},
935 #endif /* SMIME */
936 #ifdef ENABLE_LDAP
937 {"ldap-servers", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
938 "LDAP Servers", cf_text_ldap_server},
939 #endif /* ENABLE_LDAP */
940 {"rss-news", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
941 "WEB ALPINE - RSS News", cf_text_rss_news},
942 {"rss-weather", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
943 "WEB ALPINE - RSS Weather", cf_text_rss_weather},
944 {"wp-indexheight", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
945 "WEB ALPINE - Index Height", cf_text_wp_indexheight},
946 {"wp-indexlines", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
947 "WEB ALPINE - Index Lines", cf_text_wp_indexlines},
948 {"wp-aggstate", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
949 "WEB ALPINE - Aggregate State", cf_text_wp_aggstate},
950 {"wp-state", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
951 "WEB ALPINE - Cross Session State", cf_text_wp_state},
952 {"wp-columns", 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0,
953 "WEB ALPINE - Columns", cf_text_wp_columns},
954 {NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL,NULL}
958 struct variable *
959 var_from_name(char *name)
961 struct variable *v;
962 int i;
964 if(!(name && name[0]))
965 return(NULL);
967 for(i = 0; (v = &variables[i]) && v->name; i++)
968 if(!strucmp(v->name,name))
969 return(v);
971 return(NULL);
975 void
976 init_init_vars(struct pine *ps)
978 ps->vars = variables;
982 #define DSIZE (25000)
983 /* this is just like dprint except it prints to a char * */
984 #ifdef DEBUG
985 #define mprint(n,x) { \
986 if(debug >= (n)){ \
987 snprintf x ; \
988 db += strlen(db); \
991 #else
992 #define mprint(n,x)
993 #endif
996 * this was split out from init_vars so we can get at the
997 * pinerc location sooner.
999 void
1000 init_pinerc(struct pine *ps, char **debug_out)
1002 char buf[MAXPATH+1], *p, *db = NULL;
1003 #if defined(DOS) || defined(OS2)
1004 char buf2[MAXPATH+1], l_pinerc[MAXPATH+1];
1005 int nopinerc = 0, confregset = -1;
1006 register struct variable *vars = ps->vars;
1007 #endif
1009 #ifdef DEBUG
1011 * Since this routine is called before we've had a chance to set up
1012 * the debug file for output, we put the debugging into memory and
1013 * pass it back to the caller for use after init_debug(). We just
1014 * allocate plenty of space.
1016 if(debug_out){
1017 db = *debug_out = (char *)fs_get(DSIZE * sizeof(char));
1018 db[0] = '\0';
1020 #endif
1022 mprint(2, (db, DSIZE-(db-(*debug_out)), "\n -- init_pinerc --\n\n"));
1024 #if defined(DOS) || defined(OS2)
1026 * Rules for the config/support file locations under DOS are:
1028 * 1) The location of the PINERC is searched for in the following
1029 * order of precedence:
1030 * - File pointed to by '-p' command line option
1031 * - File pointed to by PINERC environment variable
1032 * - $HOME\pine
1033 * - same dir as argv[0]
1035 * 2) The HOME environment variable, if not set, defaults to
1036 * root of the current working drive (see alpine.c)
1038 * 3) The default for external files (PINE.SIG and ADDRBOOK) is the
1039 * same directory as the pinerc
1041 * 4) The support files (PINE.HLP and PINE.NDX) are expected to be in
1042 * the same directory as PINE.EXE.
1045 if(ps->prc){
1046 mprint(2, (db, DSIZE-(db-(*debug_out)),
1047 "Personal config \"%.100s\" comes from command line\n",
1048 (ps->prc && ps->prc->name) ? ps->prc->name : "<no name>"));
1050 else{
1051 mprint(2, (db, DSIZE-(db-(*debug_out)),
1052 "Personal config not set on cmdline, checking for $PINERC\n"));
1056 * First, if prc hasn't been set by a command-line -p, check to see
1057 * if PINERC is in the environment. If so, treat it just like we
1058 * would have treated it if it were a command-line arg.
1060 if(!ps->prc && (p = getenv("PINERC")) && *p){
1061 char path[MAXPATH], dir[MAXPATH];
1063 if(IS_REMOTE(p) || is_absolute_path(p)){
1064 strncpy(path, p, sizeof(path)-1);
1065 path[sizeof(path)-1] = '\0';
1067 else{
1068 getcwd(dir, sizeof(dir));
1069 build_path(path, dir, p, sizeof(path));
1072 if(!IS_REMOTE(p))
1073 ps->pinerc = cpystr(path);
1075 ps->prc = new_pinerc_s(path);
1077 if(ps->prc){
1078 mprint(2, (db, DSIZE-(db-(*debug_out)),
1079 " yes, personal config \"%.100s\" comes from $PINERC\n",
1080 (ps->prc && ps->prc->name) ? ps->prc->name : "<no name>"));
1085 * Pinerc used to be the name of the pinerc file. Then we added
1086 * the possibility of the pinerc file being remote, and we replaced
1087 * the variable pinerc with the structure prc. Unfortunately, some
1088 * parts of pine rely on the fact that pinerc is the name of the
1089 * pinerc _file_, and use the directory that the pinerc file is located
1090 * in for their own purposes. We want to preserve that so things will
1091 * keep working. So, even if the real pinerc is remote, we need to
1092 * put the name of a pinerc file in the pinerc variable so that the
1093 * directory which contains that file is writable. The file itself
1094 * doesn't have to exist for this purpose, since we are really only
1095 * using the name of the directory containing the file. Twisted.
1096 * (Alternatively, we could fix all of the code that uses the pinerc
1097 * variable for this purpose to use a new variable which really is
1098 * just a directory.) hubert 2000-sep
1100 * There are 3 cases. If pinerc is already set that means that the user
1101 * gave either a -p pinerc or an environment pinerc that is a local file,
1102 * and we are done. If pinerc is not set, then either prc is set or not.
1103 * If prc is set then the -p arg or PINERC value is a remote pinerc.
1104 * In that case we need to find a local directory to use, and put that
1105 * directory in the pinerc variable (with a fake filename tagged on).
1106 * If prc is not set, then user hasn't told us anything so we have to
1107 * try to find the default pinerc file by looking down the path of
1108 * possibilities. When we find it, we'll also use that directory.
1110 if(!ps->pinerc){
1111 *l_pinerc = '\0';
1112 *buf = '\0';
1114 if(ps->prc){ /* remote pinerc case */
1116 * We don't give them an l_pinerc unless they tell us where
1117 * to put it.
1119 if(ps->aux_files_dir)
1120 build_path(l_pinerc, ps->aux_files_dir, SYSTEM_PINERC,
1121 sizeof(l_pinerc));
1122 else{
1124 * Search for a writable directory.
1125 * Mimic what happens in !prc for local case, except we
1126 * don't need to look for the actual file.
1129 /* check if $HOME\PINE is writable */
1130 build_path(buf2, ps->home_dir, DF_PINEDIR, sizeof(buf2));
1131 if(is_writable_dir(buf2) == 0)
1132 build_path(l_pinerc, buf2, SYSTEM_PINERC, sizeof(l_pinerc));
1133 else{ /* $HOME\PINE not a writable dir */
1134 /* use this unless registry redirects us */
1135 build_path(l_pinerc, ps->pine_dir, SYSTEM_PINERC,
1136 sizeof(l_pinerc));
1137 #ifdef _WINDOWS
1138 /* if in registry, use that value */
1139 if(mswin_reg(MSWR_OP_GET, MSWR_PINE_RC, buf2, sizeof(buf2))
1140 && !IS_REMOTE(buf2)){
1141 strncpy(l_pinerc, buf2, sizeof(l_pinerc)-1);
1142 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1144 #endif
1148 else{ /* searching for pinerc file to use */
1150 * Buf2 is $HOME\PINE. If $HOME is not explicitly set,
1151 * it defaults to the current working drive (often C:).
1152 * See alpine.c to see how it is initially set.
1155 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, searching...\n"));
1156 build_path(buf2, ps->home_dir, DF_PINEDIR, sizeof(buf2));
1157 mprint(2, (db, DSIZE-(db-(*debug_out)),
1158 " checking for writable %.100s dir \"%.100s\" off of homedir\n",
1159 DF_PINEDIR, buf2));
1160 if(is_writable_dir(buf2) == 0){
1162 * $HOME\PINE exists and is writable.
1163 * See if $HOME\PINE\PINERC exists.
1165 build_path(buf, buf2, SYSTEM_PINERC, sizeof(buf));
1166 strncpy(l_pinerc, buf, sizeof(l_pinerc)-1);
1167 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1168 mprint(2, (db, DSIZE-(db-(*debug_out)), " yes, now checking for file \"%.100s\"\n",
1169 buf));
1170 if(can_access(buf, ACCESS_EXISTS) == 0){ /* found it! */
1172 * Buf is what we were looking for.
1173 * It is local and can be used for the directory, too.
1175 mprint(2, (db, DSIZE-(db-(*debug_out)), " found it\n"));
1177 else{
1179 * No $HOME\PINE\PINERC, look for
1180 * one in same dir as PINE.EXE.
1182 build_path(buf2, ps->pine_dir, SYSTEM_PINERC,
1183 sizeof(buf2));
1184 mprint(2, (db, DSIZE-(db-(*debug_out)),
1185 " no, checking for \"%.100s\" in pine.exe dir\n",
1186 buf2));
1187 if(can_access(buf2, ACCESS_EXISTS) == 0){
1188 /* found it! */
1189 mprint(2, (db, DSIZE-(db-(*debug_out)), " found it\n"));
1190 strncpy(buf, buf2, sizeof(buf)-1);
1191 buf[sizeof(buf)-1] = '\0';
1192 strncpy(l_pinerc, buf2, sizeof(l_pinerc)-1);
1193 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1195 else{
1196 #ifdef _WINDOWS
1197 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, checking in registry\n"));
1198 if(mswin_reg(MSWR_OP_GET, MSWR_PINE_RC,
1199 buf2, sizeof(buf2))){
1200 strncpy(buf, buf2, sizeof(buf)-1);
1201 buf[sizeof(buf)-1] = '\0';
1202 if(!IS_REMOTE(buf2)){
1203 strncpy(l_pinerc, buf2, sizeof(l_pinerc)-1);
1204 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1207 * Now buf is the pinerc to be used, l_pinerc is
1208 * the directory, which may be either same as buf
1209 * or it may be $HOME\PINE if registry gives us
1210 * a remote pinerc.
1212 mprint(2, (db, DSIZE-(db-(*debug_out)), " found \"%.100s\" in registry\n",
1213 buf));
1215 else{
1216 nopinerc = 1;
1217 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found, asking user\n"));
1219 #else
1220 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found\n"));
1221 #endif
1226 * Buf is the pinerc (could be remote if from registry)
1227 * and l_pinerc is the local pinerc, which may not exist.
1230 else{ /* $HOME\PINE not a writable dir */
1232 * We notice that the order of checking in the registry
1233 * and checking in the ALPINE.EXE directory are different
1234 * in this case versus the is_writable_dir(buf2) case, and
1235 * that does sort of look like a bug. However,
1236 * we don't think this is a bug since we did it on purpose
1237 * a long time ago. So even though we can't remember why
1238 * it is this way, we think we would rediscover why if we
1239 * changed it! So we won't change it.
1243 * Change the default to use to the ALPINE.EXE directory.
1245 build_path(buf, ps->pine_dir, SYSTEM_PINERC, sizeof(buf));
1246 strncpy(l_pinerc, buf, sizeof(l_pinerc)-1);
1247 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1248 #ifdef _WINDOWS
1249 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, not writable, checking in registry\n"));
1250 /* if in registry, use that value */
1251 if(mswin_reg(MSWR_OP_GET, MSWR_PINE_RC, buf2, sizeof(buf2))){
1252 strncpy(buf, buf2, sizeof(buf)-1);
1253 buf[sizeof(buf)-1] = '\0';
1254 mprint(2, (db, DSIZE-(db-(*debug_out)), " found \"%.100s\" in registry\n",
1255 buf));
1256 if(!IS_REMOTE(buf)){
1257 strncpy(l_pinerc, buf, sizeof(l_pinerc)-1);
1258 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1261 else{
1262 mprint(2, (db, DSIZE-(db-(*debug_out)),
1263 " no, checking for \"%.100s\" in alpine.exe dir\n",
1264 buf));
1266 if(can_access(buf, ACCESS_EXISTS) == 0){
1267 mprint(2, (db, DSIZE-(db-(*debug_out)), " found it\n"));
1269 else{
1270 nopinerc = 1;
1271 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found, asking user\n"));
1274 #else
1275 mprint(2, (db, DSIZE-(db-(*debug_out)),
1276 " no, checking for \"%.100s\" in alpine.exe dir\n",
1277 buf));
1279 if(can_access(buf, ACCESS_EXISTS) == 0){
1280 mprint(2, (db, DSIZE-(db-(*debug_out)), " found it\n"));
1282 else{
1283 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found, creating it\n"));
1285 #endif
1289 * When we get here we have buf set to the name of the
1290 * pinerc, which could be local or remote. We have l_pinerc
1291 * set to the same as buf if buf is local, and set to another
1292 * name otherwise, hopefully contained in a writable directory.
1294 #ifdef _WINDOWS
1295 if(nopinerc || ps_global->install_flag){
1296 char buf3[MAXPATH+1];
1298 confregset = 0;
1299 strncpy(buf3, buf, MAXPATH);
1300 buf3[MAXPATH] = '\0';
1301 if(os_config_dialog(buf3, MAXPATH,
1302 &confregset, nopinerc) == 0){
1303 strncpy(buf, buf3, MAXPATH);
1304 buf[MAXPATH] = '\0';
1305 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found, creating it\n"));
1306 mprint(2, (db, DSIZE-(db-(*debug_out)), " user says use \"%.100s\"\n", buf));
1307 if(!IS_REMOTE(buf)){
1308 strncpy(l_pinerc, buf, MAXPATH);
1309 l_pinerc[MAXPATH] = '\0';
1312 else{
1313 exit(-1);
1316 #endif
1317 ps->prc = new_pinerc_s(buf);
1320 ps->pinerc = cpystr(l_pinerc);
1323 #if defined(DOS) || defined(OS2)
1325 * The goal here is to set the auxiliary directory in the pinerc variable.
1326 * We are making the assumption that any reference to the pinerc variable
1327 * after this point is used only as a directory in which to store things,
1328 * with the prc variable being the preferred place to store pinerc location.
1329 * If -aux isn't set, then there is no change. -jpf 08/2001
1331 if(ps->aux_files_dir){
1332 l_pinerc[0] = '\0';
1333 build_path(l_pinerc, ps->aux_files_dir, SYSTEM_PINERC,
1334 sizeof(l_pinerc));
1335 if(ps->pinerc) fs_give((void **)&ps->pinerc);
1336 ps->pinerc = cpystr(l_pinerc);
1337 mprint(2, (db, DSIZE-(db-(*debug_out)), "Setting aux_files_dir to \"%.100s\"\n",
1338 ps->aux_files_dir));
1340 #endif
1342 #ifdef _WINDOWS
1343 if(confregset && (ps->update_registry != UREG_NEVER_SET))
1344 mswin_reg(MSWR_OP_SET | ((ps->update_registry == UREG_ALWAYS_SET)
1345 || confregset == 1 ? MSWR_OP_FORCE : 0),
1346 MSWR_PINE_RC,
1347 (ps->prc && ps->prc->name) ?
1348 ps->prc->name : ps->pinerc, (size_t)NULL);
1349 #endif
1352 * Now that we know the default for the PINERC, build NEWSRC default.
1353 * Backward compatibility makes this kind of funky. If what the
1354 * c-client thinks the NEWSRC should be exists *AND* it doesn't
1355 * already exist in the PINERC's dir, use c-client's default, otherwise
1356 * use the one next to the PINERC...
1358 p = last_cmpnt(ps->pinerc);
1359 buf[0] = '\0';
1360 if(p != NULL){
1361 strncpy(buf, ps->pinerc, MIN(p - ps->pinerc, sizeof(buf)-1));
1362 buf[MIN(p - ps->pinerc, sizeof(buf)-1)] = '\0';
1365 mprint(2, (db, DSIZE-(db-(*debug_out)), "Using directory \"%.100s\" for auxiliary files\n", buf));
1366 strncat(buf, "NEWSRC", sizeof(buf)-1-strlen(buf));
1368 if(!(p = (void *) mail_parameters(NULL, GET_NEWSRC, (void *)NULL))
1369 || can_access(p, ACCESS_EXISTS) < 0
1370 || can_access(buf, ACCESS_EXISTS) == 0){
1371 mail_parameters(NULL, SET_NEWSRC, (void *)buf);
1372 GLO_NEWSRC_PATH = cpystr(buf);
1374 else
1375 GLO_NEWSRC_PATH = cpystr(p);
1377 if(ps->pconf){
1378 mprint(2, (db, DSIZE-(db-(*debug_out)), "Global config \"%.100s\" comes from command line\n",
1379 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1381 else{
1382 mprint(2, (db, DSIZE-(db-(*debug_out)),
1383 "Global config not set on cmdline, checking for $PINECONF\n"));
1386 if(!ps->pconf && (p = getenv("PINECONF"))){
1387 ps->pconf = new_pinerc_s(p);
1388 if(ps->pconf){
1389 mprint(2, (db, DSIZE-(db-(*debug_out)),
1390 " yes, global config \"%.100s\" comes from $PINECONF\n",
1391 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1394 #ifdef _WINDOWS
1395 else if(!ps->pconf
1396 && mswin_reg(MSWR_OP_GET, MSWR_PINE_CONF, buf2, sizeof(buf2))){
1397 ps->pconf = new_pinerc_s(buf2);
1398 if(ps->pconf){
1399 mprint(2, (db, DSIZE-(db-(*debug_out)),
1400 " yes, global config \"%.100s\" comes from Registry\n",
1401 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1404 #endif
1405 if(!ps->pconf){
1406 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, there is no global config\n"));
1408 #ifdef _WINDOWS
1409 else if (ps->pconf && ps->pconf->name &&
1410 (ps->update_registry != UREG_NEVER_SET)){
1411 mswin_reg(MSWR_OP_SET | ((ps->update_registry == UREG_ALWAYS_SET)
1412 ? MSWR_OP_FORCE : 0),
1413 MSWR_PINE_CONF,
1414 ps->pconf->name, (size_t)NULL);
1416 #endif
1418 if(!ps->prc)
1419 ps->prc = new_pinerc_s(ps->pinerc);
1421 if(ps->exceptions){
1422 mprint(2, (db, DSIZE-(db-(*debug_out)),
1423 "Exceptions config \"%.100s\" comes from command line\n",
1424 ps->exceptions));
1426 else{
1427 mprint(2, (db, DSIZE-(db-(*debug_out)),
1428 "Exceptions config not set on cmdline, checking for $PINERCEX\n"));
1432 * Exceptions is done slightly differently from pinerc. Instead of setting
1433 * post_prc in args.c we just set the string and use it here. We do
1434 * that so that we can put it in the same directory as the pinerc if
1435 * exceptions is a relative name, and pinerc may not be set until here.
1437 * First, just like for pinerc, check environment variable if it wasn't
1438 * set on the command line.
1440 if(!ps->exceptions && (p = getenv("PINERCEX")) && *p){
1441 ps->exceptions = cpystr(p);
1442 if(ps->exceptions){
1443 mprint(2, (db, DSIZE-(db-(*debug_out)),
1444 " yes, exceptions config \"%.100s\" comes from $PINERCEX\n",
1445 ps->exceptions));
1450 * If still not set, try specific file in same dir as pinerc.
1451 * Only use it if the file exists.
1453 if(!ps->exceptions){
1454 p = last_cmpnt(ps->pinerc);
1455 buf[0] = '\0';
1456 if(p != NULL){
1457 strncpy(buf, ps->pinerc, MIN(p - ps->pinerc, sizeof(buf)-1));
1458 buf[MIN(p - ps->pinerc, sizeof(buf)-1)] = '\0';
1461 strncat(buf, "PINERCEX", sizeof(buf)-1-strlen(buf));
1463 mprint(2, (db, DSIZE-(db-(*debug_out)),
1464 " no, checking for default \"%.100s\" in pinerc dir\n", buf));
1465 if(can_access(buf, ACCESS_EXISTS) == 0) /* found it! */
1466 ps->exceptions = cpystr(buf);
1468 if(ps->exceptions){
1469 mprint(2, (db, DSIZE-(db-(*debug_out)),
1470 " yes, exceptions config \"%.100s\" comes from default\n",
1471 ps->exceptions));
1473 else{
1474 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, there is no exceptions config\n"));
1478 #else /* unix */
1480 if(ps->pconf){
1481 mprint(2, (db, DSIZE-(db-(*debug_out)), "Global config \"%.100s\" comes from command line\n",
1482 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1485 if(!ps->pconf){
1486 ps->pconf = new_pinerc_s(SYSTEM_PINERC);
1487 if(ps->pconf){
1488 mprint(2, (db, DSIZE-(db-(*debug_out)), "Global config \"%.100s\" is default\n",
1489 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1493 if(!ps->pconf){
1494 mprint(2, (db, DSIZE-(db-(*debug_out)), "No global config!\n"));
1497 if(ps->prc){
1498 mprint(2, (db, DSIZE-(db-(*debug_out)), "Personal config \"%.100s\" comes from command line\n",
1499 (ps->prc && ps->prc->name) ? ps->prc->name : "<no name>"));
1502 if(!ps->pinerc){
1503 build_path(buf, ps->home_dir, ".pinerc", sizeof(buf));
1504 ps->pinerc = cpystr(buf);
1507 if(!ps->prc){
1508 ps->prc = new_pinerc_s(ps->pinerc);
1509 if(ps->prc){
1510 mprint(2, (db, DSIZE-(db-(*debug_out)), "Personal config \"%.100s\" is default\n",
1511 (ps->prc && ps->prc->name) ? ps->prc->name : "<no name>"));
1515 if(!ps->prc){
1516 mprint(2, (db, DSIZE-(db-(*debug_out)), "No personal config!\n"));
1519 if(ps->exceptions){
1520 mprint(2, (db, DSIZE-(db-(*debug_out)),
1521 "Exceptions config \"%.100s\" comes from command line\n",
1522 ps->exceptions));
1526 * If not set, try specific file in same dir as pinerc.
1527 * Only use it if the file exists.
1529 if(!ps->exceptions){
1530 p = last_cmpnt(ps->pinerc);
1531 buf[0] = '\0';
1532 if(p != NULL){
1533 strncpy(buf, ps->pinerc, MIN(p - ps->pinerc, sizeof(buf)-1));
1534 buf[MIN(p - ps->pinerc, sizeof(buf)-1)] = '\0';
1537 strncat(buf, ".pinercex", sizeof(buf)-1-strlen(buf));
1538 mprint(2, (db, DSIZE-(db-(*debug_out)), "Exceptions config not set on cmdline\n checking for default \"%.100s\" in pinerc dir\n", buf));
1540 if(can_access(buf, ACCESS_EXISTS) == 0) /* found it! */
1541 ps->exceptions = cpystr(buf);
1543 if(ps->exceptions){
1544 mprint(2, (db, DSIZE-(db-(*debug_out)),
1545 " yes, exceptions config \"%.100s\" is default\n",
1546 ps->exceptions));
1548 else{
1549 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, there is no exceptions config\n"));
1553 #endif /* unix */
1555 if(ps->exceptions){
1557 if(!IS_REMOTE(ps->exceptions) &&
1558 !is_absolute_path(ps->exceptions)){
1559 #if defined(DOS) || defined(OS2)
1560 p = last_cmpnt(ps->pinerc);
1561 buf[0] = '\0';
1562 if(p != NULL){
1563 strncpy(buf, ps->pinerc, MIN(p - ps->pinerc, sizeof(buf)-1));
1564 buf[MIN(p - ps->pinerc, sizeof(buf)-1)] = '\0';
1567 strncat(buf, ps->exceptions, sizeof(buf)-1-strlen(buf));
1568 #else
1569 build_path(buf, ps->home_dir, ps->exceptions, sizeof(buf));
1570 #endif
1572 else{
1573 strncpy(buf, ps->exceptions, sizeof(buf)-1);
1574 buf[sizeof(buf)-1] = '\0';
1577 ps->post_prc = new_pinerc_s(buf);
1579 fs_give((void **)&ps->exceptions);
1582 mprint(2, (db, DSIZE-(db-(*debug_out)), "\n Global config: %.100s\n",
1583 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<none>"));
1584 mprint(2, (db, DSIZE-(db-(*debug_out)), " Personal config: %.100s\n",
1585 (ps->prc && ps->prc->name) ? ps->prc->name : "<none>"));
1586 mprint(2, (db, DSIZE-(db-(*debug_out)), " Exceptions config: %.100s\n",
1587 (ps->post_prc && ps->post_prc->name) ? ps->post_prc->name
1588 : "<none>"));
1589 #if !defined(DOS) && !defined(OS2)
1590 if(SYSTEM_PINERC_FIXED){
1591 mprint(2, (db, DSIZE-(db-(*debug_out)), " Fixed config: %.100s\n", SYSTEM_PINERC_FIXED));
1593 #endif
1595 mprint(2, (db, DSIZE-(db-(*debug_out)), "\n"));
1599 /*----------------------------------------------------------------------
1600 Initialize the variables
1602 Args: ps -- The usual pine structure
1604 Result:
1606 This reads the system pine configuration file and the user's pine
1607 configuration file ".pinerc" and places the results in the variables
1608 structure. It sorts out what was read and sets a few other variables
1609 based on the contents.
1610 ----*/
1611 void
1612 init_vars(struct pine *ps, void (*cmds_f) (struct pine *, char **))
1614 char buf[MAXPATH+1], *p, *q, **s, *comma_index;
1615 register struct variable *vars = ps->vars;
1616 int obs_header_in_reply = 0, /* the obs_ variables are to */
1617 obs_old_style_reply = 0, /* support backwards compatibility */
1618 obs_save_by_sender, i, def_sort_rev;
1619 long rvl;
1620 PINERC_S *fixedprc = NULL;
1621 FeatureLevel obs_feature_level;
1622 char *fromcharset = NULL;
1623 char *err = NULL;
1625 dprint((5, "init_vars:\n"));
1627 /*--- The defaults here are defined in os-xxx.h so they can vary
1628 per machine ---*/
1630 GLO_PRINTER = cpystr(DF_DEFAULT_PRINTER);
1631 GLO_ELM_STYLE_SAVE = cpystr(DF_ELM_STYLE_SAVE);
1632 #ifdef DF_ENCRYPTION_RANGE
1633 GLO_ENCRYPTION_RANGE = cpystr(DF_ENCRYPTION_RANGE);
1634 #endif /* 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 #ifdef DF_ENCRYPTION_RANGE
2415 set_current_val(&vars[V_ENCRYPTION_RANGE], TRUE, TRUE);
2416 #endif /* DF_ENCRYPTION_RANGE */
2418 set_current_val(&vars[V_VIEW_HEADERS], TRUE, TRUE);
2419 /* strip spaces and colons */
2420 if(ps->VAR_VIEW_HEADERS){
2421 for(s = ps->VAR_VIEW_HEADERS; (q = *s) != NULL; s++){
2422 if(q[0]){
2423 removing_leading_white_space(q);
2424 /* look for colon or space or end */
2425 for(p = q; *p && !isspace((unsigned char)*p) && *p != ':'; p++)
2426 ;/* do nothing */
2428 *p = '\0';
2429 if(strucmp(q, ALL_EXCEPT) == 0)
2430 ps->view_all_except = 1;
2435 set_current_val(&vars[V_VIEW_MARGIN_LEFT], TRUE, TRUE);
2436 set_current_val(&vars[V_VIEW_MARGIN_RIGHT], TRUE, TRUE);
2437 set_current_val(&vars[V_UPLOAD_CMD], TRUE, TRUE);
2438 set_current_val(&vars[V_UPLOAD_CMD_PREFIX], TRUE, TRUE);
2439 set_current_val(&vars[V_DOWNLOAD_CMD], TRUE, TRUE);
2440 set_current_val(&vars[V_DOWNLOAD_CMD_PREFIX], TRUE, TRUE);
2441 set_current_val(&vars[V_MAILCAP_PATH], TRUE, TRUE);
2442 set_current_val(&vars[V_MIMETYPE_PATH], TRUE, TRUE);
2443 #if !defined(_WINDOWS) || defined(WINDOWS_UNIXSSL_CERTS)
2444 set_current_val(&vars[V_SSLCAPATH], TRUE, TRUE);
2445 set_current_val(&vars[V_SSLCAFILE], TRUE, TRUE);
2446 set_current_val(&vars[V_USERSSLCAPATH], TRUE, TRUE);
2447 set_current_val(&vars[V_USERSSLCAFILE], TRUE, TRUE);
2448 set_current_val(&vars[V_SSLCIPHERS], TRUE, TRUE);
2449 #endif
2450 #if !defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)
2451 set_current_val(&vars[V_FIFOPATH], TRUE, TRUE);
2452 #endif
2454 set_current_val(&vars[V_RSHPATH], TRUE, TRUE);
2455 if(VAR_RSHPATH
2456 && is_absolute_path(VAR_RSHPATH)
2457 && can_access(VAR_RSHPATH, EXECUTE_ACCESS) == 0){
2458 mail_parameters(NULL, SET_RSHPATH, (void *) VAR_RSHPATH);
2461 set_current_val(&vars[V_RSHCMD], TRUE, TRUE);
2462 if(VAR_RSHCMD){
2463 mail_parameters(NULL, SET_RSHCOMMAND, (void *) VAR_RSHCMD);
2466 set_current_val(&vars[V_SSHPATH], TRUE, TRUE);
2467 if(VAR_SSHPATH) {
2468 if(is_absolute_path(VAR_SSHPATH)
2469 && can_access(VAR_SSHPATH, EXECUTE_ACCESS) == 0){
2470 mail_parameters(NULL, SET_SSHPATH, (void *) VAR_SSHPATH);
2472 else {
2473 mail_parameters(NULL, SET_SSHPATH, (void *) NULL);
2477 set_current_val(&vars[V_SSHCMD], TRUE, TRUE);
2478 if(VAR_SSHCMD) {
2479 if(VAR_SSHCMD[0]) {
2480 mail_parameters(NULL, SET_SSHCOMMAND, (void *) VAR_SSHCMD);
2482 else {
2483 mail_parameters(NULL, SET_SSHCOMMAND, (void *) NULL);
2487 #if defined(DOS) || defined(OS2)
2489 set_current_val(&vars[V_FILE_DIR], TRUE, TRUE);
2491 #ifdef _WINDOWS
2492 set_current_val(&vars[V_FONT_NAME], TRUE, TRUE);
2493 set_current_val(&vars[V_FONT_SIZE], TRUE, TRUE);
2494 set_current_val(&vars[V_FONT_STYLE], TRUE, TRUE);
2495 set_current_val(&vars[V_FONT_CHAR_SET], TRUE, TRUE);
2496 set_current_val(&vars[V_CURSOR_STYLE], TRUE, TRUE);
2497 set_current_val(&vars[V_WINDOW_POSITION], TRUE, TRUE);
2499 if(F_OFF(F_STORE_WINPOS_IN_CONFIG, ps_global)){
2500 /* if win position is in the registry, use it */
2501 if(mswin_reg(MSWR_OP_GET, MSWR_PINE_POS, buf, sizeof(buf))){
2502 if(VAR_WINDOW_POSITION)
2503 fs_give((void **)&VAR_WINDOW_POSITION);
2505 VAR_WINDOW_POSITION = cpystr(buf);
2507 else if(VAR_WINDOW_POSITION
2508 && (ps->update_registry != UREG_NEVER_SET)){
2509 /* otherwise, put it there */
2510 mswin_reg(MSWR_OP_SET | ((ps->update_registry == UREG_ALWAYS_SET)
2511 ? MSWR_OP_FORCE : 0),
2512 MSWR_PINE_POS,
2513 VAR_WINDOW_POSITION, (size_t)NULL);
2517 mswin_setwindow (VAR_FONT_NAME, VAR_FONT_SIZE,
2518 VAR_FONT_STYLE, VAR_WINDOW_POSITION,
2519 VAR_CURSOR_STYLE, VAR_FONT_CHAR_SET);
2521 /* this is no longer used */
2522 if(VAR_WINDOW_POSITION)
2523 fs_give((void **)&VAR_WINDOW_POSITION);
2525 set_current_val(&vars[V_PRINT_FONT_NAME], TRUE, TRUE);
2526 set_current_val(&vars[V_PRINT_FONT_SIZE], TRUE, TRUE);
2527 set_current_val(&vars[V_PRINT_FONT_STYLE], TRUE, TRUE);
2528 set_current_val(&vars[V_PRINT_FONT_CHAR_SET], TRUE, TRUE);
2529 mswin_setprintfont (VAR_PRINT_FONT_NAME,
2530 VAR_PRINT_FONT_SIZE,
2531 VAR_PRINT_FONT_STYLE,
2532 VAR_PRINT_FONT_CHAR_SET);
2534 mswin_setgenhelptextcallback(pcpine_general_help);
2536 mswin_setclosetext ("Use the \"Q\" command to exit Alpine.");
2539 char foreColor[64], backColor[64];
2541 mswin_getwindow(NULL, 0, NULL, 0, NULL, 0, NULL, 0,
2542 foreColor, sizeof(foreColor), backColor, sizeof(backColor),
2543 NULL, 0, NULL, 0);
2544 if(!GLO_NORM_FORE_COLOR)
2545 GLO_NORM_FORE_COLOR = cpystr(foreColor);
2547 if(!GLO_NORM_BACK_COLOR)
2548 GLO_NORM_BACK_COLOR = cpystr(backColor);
2550 #endif /* _WINDOWS */
2551 #endif /* DOS */
2554 * We want the version number to start out as 1.0 for Alpine, but
2555 * we also want to use the same old config file that was used
2556 * with Pine. The Pine version numbers made it up to 4.64 and we
2557 * want Alpine's 1.0 to be larger than 4.64 so we keep a separate
2558 * internal version number which is the real version number
2559 * plus 4. That's what gets written in LAST_VERS_USED.
2561 strncpy(ps->vers_internal, ALPINE_VERSION, sizeof(ps->vers_internal));
2562 ps->vers_internal[sizeof(ps->vers_internal)-1] = '\0';
2563 if(isdigit(ps->vers_internal[0]) && ps->vers_internal[0] < '6')
2564 ps->vers_internal[0] = ps->vers_internal[0] + 4;
2566 set_current_val(&vars[V_LAST_VERS_USED], TRUE, TRUE);
2567 /* Check for special cases first */
2568 if(VAR_LAST_VERS_USED
2569 && (isdigit(ps->vers_internal[0])
2570 && ps->vers_internal[1] == '.'
2571 && isdigit((unsigned char)ps->vers_internal[2])
2572 && isdigit((unsigned char)ps->vers_internal[3])
2573 && isalpha((unsigned char)ps->vers_internal[4])
2574 && strncmp(VAR_LAST_VERS_USED, ps->vers_internal, 4) >= 0)){
2575 ps->show_new_version = 0;
2577 /* Otherwise just do lexicographic comparison... */
2578 else if(VAR_LAST_VERS_USED
2579 && strcmp(VAR_LAST_VERS_USED, ps->vers_internal) >= 0){
2580 ps->show_new_version = 0;
2582 else{
2583 #ifdef _WINDOWS
2585 * If this is the first time we've run a version > 4.40, and there
2586 * is evidence that the config file has not been used by unix pine,
2587 * then we convert color008 to colorlgr, color009 to colormgr, and
2588 * color010 to colordgr. If the config file is being used by
2589 * unix pine then color009 may really supposed to be red, etc.
2590 * Same if we've already run 4.41 or higher. We don't have to do
2591 * anything if we are new to alpine.
2593 ps->pre441 = (VAR_LAST_VERS_USED
2594 && strcmp(VAR_LAST_VERS_USED, "4.40") <= 0);
2595 #endif /* _WINDOWS */
2598 * Don't offer the new version message if we're told not to.
2600 set_current_val(&vars[V_NEW_VER_QUELL], TRUE, TRUE);
2601 ps->show_new_version = !(VAR_NEW_VER_QUELL
2602 && strcmp(ps->vers_internal,
2603 VAR_NEW_VER_QUELL) < 0);
2605 #ifdef _WINDOWS
2606 if(!ps_global->install_flag)
2607 #endif /* _WINDOWS */
2609 if(VAR_LAST_VERS_USED){
2610 strncpy(ps_global->pine_pre_vers, VAR_LAST_VERS_USED,
2611 sizeof(ps_global->pine_pre_vers));
2612 ps_global->pine_pre_vers[sizeof(ps_global->pine_pre_vers)-1] = '\0';
2615 set_variable(V_LAST_VERS_USED, ps->vers_internal, 1, 1,
2616 ps_global->ew_for_except_vars);
2620 /* Obsolete, backwards compatibility */
2621 set_current_val(&vars[V_ELM_STYLE_SAVE], TRUE, TRUE);
2622 /* Also obsolete */
2623 set_current_val(&vars[V_SAVE_BY_SENDER], TRUE, TRUE);
2624 if(!strucmp(VAR_ELM_STYLE_SAVE, "yes"))
2625 set_variable(V_SAVE_BY_SENDER, "yes", 1, 1, Main);
2626 obs_save_by_sender = !strucmp(VAR_SAVE_BY_SENDER, "yes");
2628 set_current_val(&vars[V_XOAUTH2_INFO], TRUE, TRUE);
2630 set_current_pattern_vals(ps);
2632 set_current_val(&vars[V_INDEX_FORMAT], TRUE, TRUE);
2633 init_index_format(VAR_INDEX_FORMAT, &ps->index_disp_format);
2635 /* this should come after pre441 is set or not */
2636 set_current_color_vals(ps);
2638 set_current_val(&vars[V_RSS_NEWS], TRUE, TRUE);
2639 set_current_val(&vars[V_RSS_WEATHER], TRUE, TRUE);
2640 set_current_val(&vars[V_WP_INDEXHEIGHT], TRUE, TRUE);
2641 set_current_val(&vars[V_WP_INDEXLINES], TRUE, TRUE);
2642 set_current_val(&vars[V_WP_AGGSTATE], TRUE, TRUE);
2643 set_current_val(&vars[V_WP_STATE], TRUE, TRUE);
2644 set_current_val(&vars[V_WP_COLUMNS], TRUE, TRUE);
2646 set_current_val(&vars[V_PRUNED_FOLDERS], TRUE, TRUE);
2647 set_current_val(&vars[V_ARCHIVED_FOLDERS], TRUE, TRUE);
2648 set_current_val(&vars[V_INCOMING_FOLDERS], TRUE, TRUE);
2649 set_current_val(&vars[V_SORT_KEY], TRUE, TRUE);
2650 if(decode_sort(VAR_SORT_KEY, &ps->def_sort, &def_sort_rev) == -1){
2651 snprintf(tmp_20k_buf, SIZEOF_20KBUF, "Sort type \"%.200s\" is invalid", VAR_SORT_KEY);
2652 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2653 ps->def_sort = SortArrival;
2654 ps->def_sort_rev = 0;
2656 else
2657 ps->def_sort_rev = def_sort_rev;
2659 cur_rule_value(&vars[V_SAVED_MSG_NAME_RULE], TRUE, TRUE);
2660 {NAMEVAL_S *v; int i;
2661 for(i = 0; (v = save_msg_rules(i)); i++)
2662 if(v->value == ps_global->save_msg_rule)
2663 break;
2665 /* if save_msg_rule is not default, or is explicitly set to default */
2666 if((ps_global->save_msg_rule != SAV_RULE_DEFLT) ||
2667 (v && v->name &&
2668 (!strucmp(ps_global->vars[V_SAVED_MSG_NAME_RULE].post_user_val.p,
2669 v->name) ||
2670 !strucmp(ps_global->vars[V_SAVED_MSG_NAME_RULE].main_user_val.p,
2671 v->name))))
2672 obs_save_by_sender = 0; /* don't overwrite */
2675 cur_rule_value(&vars[V_FCC_RULE], TRUE, TRUE);
2676 cur_rule_value(&vars[V_AB_SORT_RULE], TRUE, TRUE);
2678 #ifndef _WINDOWS
2679 cur_rule_value(&vars[V_COLOR_STYLE], TRUE, TRUE);
2680 #endif
2682 cur_rule_value(&vars[V_INDEX_COLOR_STYLE], TRUE, TRUE);
2683 cur_rule_value(&vars[V_TITLEBAR_COLOR_STYLE], TRUE, TRUE);
2684 cur_rule_value(&vars[V_FLD_SORT_RULE], TRUE, TRUE);
2685 cur_rule_value(&vars[V_INCOMING_STARTUP], TRUE, TRUE);
2686 cur_rule_value(&vars[V_PRUNING_RULE], TRUE, TRUE);
2687 cur_rule_value(&vars[V_REOPEN_RULE], TRUE, TRUE);
2688 cur_rule_value(&vars[V_GOTO_DEFAULT_RULE], TRUE, TRUE);
2689 cur_rule_value(&vars[V_THREAD_DISP_STYLE], TRUE, TRUE);
2690 cur_rule_value(&vars[V_THREAD_INDEX_STYLE], TRUE, TRUE);
2692 set_current_val(&vars[V_THREAD_MORE_CHAR], TRUE, TRUE);
2693 if(VAR_THREAD_MORE_CHAR[0] && VAR_THREAD_MORE_CHAR[1]){
2694 init_error(ps, SM_ORDER | SM_DING, 3, 5,
2695 _("Only using first character of threading-indicator-character option"));
2696 VAR_THREAD_MORE_CHAR[1] = '\0';
2699 set_current_val(&vars[V_THREAD_EXP_CHAR], TRUE, TRUE);
2700 if(VAR_THREAD_EXP_CHAR[0] && VAR_THREAD_EXP_CHAR[1]){
2701 init_error(ps, SM_ORDER | SM_DING, 3, 5,
2702 _("Only using first character of threading-expanded-character option"));
2703 VAR_THREAD_EXP_CHAR[1] = '\0';
2706 set_current_val(&vars[V_THREAD_LASTREPLY_CHAR], TRUE, TRUE);
2707 if(!VAR_THREAD_LASTREPLY_CHAR[0])
2708 VAR_THREAD_LASTREPLY_CHAR = cpystr(DF_THREAD_LASTREPLY_CHAR);
2710 if(VAR_THREAD_LASTREPLY_CHAR[0] && VAR_THREAD_LASTREPLY_CHAR[1]){
2711 init_error(ps, SM_ORDER | SM_DING, 3, 5,
2712 _("Only using first character of threading-lastreply-character option"));
2713 VAR_THREAD_LASTREPLY_CHAR[1] = '\0';
2716 set_current_val(&vars[V_MAXREMSTREAM], TRUE, TRUE);
2717 ps->s_pool.max_remstream = i = atoi(DF_MAXREMSTREAM);
2718 if(SVAR_MAXREMSTREAM(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2719 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2720 else
2721 ps->s_pool.max_remstream = i;
2723 set_current_val(&vars[V_PERMLOCKED], TRUE, TRUE);
2725 set_current_val(&vars[V_NMW_WIDTH], TRUE, TRUE);
2726 ps->nmw_width = i = atoi(DF_NMW_WIDTH);
2727 if(SVAR_NMW_WIDTH(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2728 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2729 else
2730 ps->nmw_width = i;
2732 /* backwards compatibility */
2733 if(obs_save_by_sender){
2734 ps->save_msg_rule = SAV_RULE_FROM;
2735 set_variable(V_SAVED_MSG_NAME_RULE, "by-from", 1, 1, Main);
2738 /* this should come after process_feature_list because of use_fkeys */
2739 if(!ps->start_in_index)
2740 set_current_val(&vars[V_INIT_CMD_LIST], FALSE, TRUE);
2741 if(VAR_INIT_CMD_LIST && VAR_INIT_CMD_LIST[0] && VAR_INIT_CMD_LIST[0][0])
2742 if(cmds_f)
2743 (*cmds_f)(ps, VAR_INIT_CMD_LIST);
2745 #ifdef _WINDOWS
2746 mswin_set_quit_confirm (F_OFF(F_QUIT_WO_CONFIRM, ps_global));
2747 #endif /* _WINDOWS */
2749 #ifdef DEBUG
2750 dump_configuration(0);
2751 #endif /* DEBUG */
2755 void
2756 convert_configvars_to_utf8(struct variable *vars, char *fromcharset)
2758 struct variable *v;
2761 * Make sure that everything is UTF-8.
2763 for(v = vars; v->name; v++)
2764 convert_configvar_to_utf8(v, fromcharset);
2768 void
2769 convert_configvar_to_utf8(struct variable *v, char *fromcharset)
2771 char **p, *conv, **valptr;
2772 int i;
2775 * Make sure that everything is UTF-8.
2777 if(v->is_list){
2778 for(i = 0; i < 7; i++){
2779 switch(i){
2780 case 1: valptr = v->current_val.l; break;
2781 case 0: valptr = v->main_user_val.l; break;
2782 case 2: valptr = v->changed_val.l; break;
2783 case 3: valptr = v->post_user_val.l; break;
2784 case 4: valptr = v->global_val.l; break;
2785 case 5: valptr = v->fixed_val.l; break;
2786 case 6: valptr = v->cmdline_val.l; break;
2787 default: alpine_panic("bad case in convert_configvar");
2790 if(valptr){
2791 for(p = valptr; *p; p++){
2792 if(**p){
2793 conv = convert_to_utf8(*p, fromcharset, 0);
2794 if(conv){
2795 fs_give((void **) p);
2796 *p = conv;
2803 else{
2804 for(i = 0; i < 7; i++){
2805 switch(i){
2806 case 1: valptr = &v->current_val.p; break;
2807 case 0: valptr = &v->main_user_val.p; break;
2808 case 2: valptr = &v->changed_val.p; break;
2809 case 3: valptr = &v->post_user_val.p; break;
2810 case 4: valptr = &v->global_val.p; break;
2811 case 5: valptr = &v->fixed_val.p; break;
2812 case 6: valptr = &v->cmdline_val.p; break;
2813 default: alpine_panic("bad case in convert_configvar");
2816 if(valptr && *valptr && (*valptr)[0]){
2817 conv = convert_to_utf8(*valptr, fromcharset, 0);
2818 if(conv){
2819 fs_give((void **) valptr);
2820 *valptr = conv;
2830 * Standard feature name sections
2832 char *
2833 feature_list_section(FEATURE_S *feature)
2835 #define PREF_NONE -1
2836 static char *feat_sect[] = {
2837 #define PREF_MISC 0
2838 /* TRANSLATORS: section heading in configuration screen */
2839 N_("Advanced User Preferences"),
2840 #define PREF_FLDR 1
2841 /* TRANSLATORS: section heading in configuration screen */
2842 N_("Folder Preferences"),
2843 #define PREF_ADDR 2
2844 /* TRANSLATORS: section heading in configuration screen */
2845 N_("Address Book Preferences"),
2846 #define PREF_COMP 3
2847 /* TRANSLATORS: section heading in configuration screen */
2848 N_("Composer Preferences"),
2849 #define PREF_NEWS 4
2850 /* TRANSLATORS: section heading in configuration screen */
2851 N_("News Preferences"),
2852 #define PREF_VIEW 5
2853 /* TRANSLATORS: section heading in configuration screen */
2854 N_("Viewer Preferences"),
2855 #define PREF_ACMD 6
2856 /* TRANSLATORS: section heading in configuration screen */
2857 N_("Advanced Command Preferences"),
2858 #define PREF_PRNT 7
2859 /* TRANSLATORS: section heading in configuration screen */
2860 N_("Printer Preferences"),
2861 #define PREF_RPLY 8
2862 /* TRANSLATORS: section heading in configuration screen */
2863 N_("Reply Preferences"),
2864 #define PREF_SEND 9
2865 /* TRANSLATORS: section heading in configuration screen */
2866 N_("Sending Preferences"),
2867 #define PREF_INDX 10
2868 /* TRANSLATORS: section heading in configuration screen */
2869 N_("Message Index Preferences"),
2870 #define PREF_HIDDEN 11
2871 HIDDEN_PREF
2874 return((feature && feature->section > PREF_NONE
2875 && feature->section < (sizeof(feat_sect)/sizeof(feat_sect[0])))
2876 ? _(feat_sect[feature->section]) : NULL);
2880 /* any os-specific exclusions */
2881 #if defined(DOS) || defined(OS2)
2882 #define PREF_OS_LWSD PREF_NONE
2883 #define PREF_OS_LCLK PREF_NONE
2884 #define PREF_OS_STSP PREF_NONE
2885 #define PREF_OS_SPWN PREF_NONE
2886 #define PREF_OS_XNML PREF_NONE
2887 #define PREF_OS_USFK PREF_MISC
2888 #define PREF_OS_MOUSE PREF_NONE
2889 #else
2890 #define PREF_OS_LWSD PREF_MISC
2891 #define PREF_OS_LCLK PREF_COMP
2892 #define PREF_OS_STSP PREF_MISC
2893 #define PREF_OS_SPWN PREF_MISC
2894 #define PREF_OS_XNML PREF_MISC
2895 #define PREF_OS_USFK PREF_NONE
2896 #define PREF_OS_MOUSE PREF_MISC
2897 #endif
2901 * Standard way to get at feature list members...
2903 FEATURE_S *
2904 feature_list(int index)
2907 * This list is alphabatized by feature string, but the
2908 * macro values need not be ordered.
2910 static FEATURE_S feat_list[] = {
2911 /* Composer prefs */
2912 {"allow-changing-from", NULL,
2913 F_ALLOW_CHANGING_FROM, h_config_allow_chg_from, PREF_COMP, 1},
2914 {"alternate-compose-menu", NULL,
2915 F_ALT_COMPOSE_MENU, h_config_alt_compose_menu, PREF_COMP, 0},
2916 {"alternate-role-menu", "Alternate Role (#) Menu",
2917 F_ALT_ROLE_MENU, h_config_alt_role_menu, PREF_COMP, 0},
2918 {"compose-cancel-confirm-uses-yes", NULL,
2919 F_CANCEL_CONFIRM, h_config_cancel_confirm, PREF_COMP, 0},
2920 {"compose-rejects-unqualified-addrs", "Compose Rejects Unqualified Addresses",
2921 F_COMPOSE_REJECTS_UNQUAL, h_config_compose_rejects_unqual, PREF_COMP, 0},
2922 {"compose-send-offers-first-filter", NULL,
2923 F_FIRST_SEND_FILTER_DFLT, h_config_send_filter_dflt, PREF_COMP, 0},
2924 {"compose-cut-from-cursor", "Ctrl-K Cuts From Cursor",
2925 F_DEL_FROM_DOT, h_config_del_from_dot, PREF_COMP, 0},
2926 {"compose-maps-delete-key-to-ctrl-d", "Delete Key Maps to Ctrl-D",
2927 F_COMPOSE_MAPS_DEL, h_config_compose_maps_del, PREF_COMP, 0},
2928 {"quell-dead-letter-on-cancel", "Do Not Save to Deadletter on Cancel",
2929 F_QUELL_DEAD_LETTER, h_config_quell_dead_letter, PREF_COMP, 0},
2930 {"enable-alternate-editor-cmd", "Enable Alternate Editor Command",
2931 F_ENABLE_ALT_ED, h_config_enable_alt_ed, PREF_COMP, 1},
2932 {"enable-alternate-editor-implicitly", NULL,
2933 F_ALT_ED_NOW, h_config_alt_ed_now, PREF_COMP, 0},
2934 {"enable-search-and-replace", "Enable Search and Replace",
2935 F_ENABLE_SEARCH_AND_REPL, h_config_enable_search_and_repl, PREF_COMP, 1},
2936 {"enable-sigdashes", NULL,
2937 F_ENABLE_SIGDASHES, h_config_sigdashes, PREF_COMP, 0},
2938 {"quell-mailchecks-composing-except-inbox", "Prevent Mailchecks While Composing Except for INBOX",
2939 F_QUELL_PINGS_COMPOSING, h_config_quell_checks_comp, PREF_COMP, 0},
2940 {"quell-mailchecks-composing-inbox", "Prevent Mailchecks While Composing for INBOX",
2941 F_QUELL_PINGS_COMPOSING_INBOX, h_config_quell_checks_comp_inbox, PREF_COMP, 0},
2942 {"quell-user-lookup-in-passwd-file", "Prevent User Lookup in Password File",
2943 F_QUELL_LOCAL_LOOKUP, h_config_quell_local_lookup, PREF_OS_LCLK, 0},
2944 {"spell-check-before-sending", NULL,
2945 F_ALWAYS_SPELL_CHECK, h_config_always_spell_check, PREF_COMP, 0},
2947 /* Reply Prefs */
2948 {"alternate-reply-menu", NULL,
2949 F_ALT_REPLY_MENU, h_config_alt_reply_menu, PREF_RPLY, 0},
2950 {"copy-to-address-to-from-if-it-is-us", "Copy To Address to From if it is Us",
2951 F_COPY_TO_TO_FROM, h_config_copy_to_to_from, PREF_RPLY, 0},
2952 {"enable-reply-indent-string-editing", NULL,
2953 F_ENABLE_EDIT_REPLY_INDENT, h_config_prefix_editing, PREF_RPLY, 0},
2954 {"include-attachments-in-reply", "Include Attachments in Reply",
2955 F_ATTACHMENTS_IN_REPLY, h_config_attach_in_reply, PREF_RPLY, 0},
2956 {"include-header-in-reply", "Include Header in Reply",
2957 F_INCLUDE_HEADER, h_config_include_header, PREF_RPLY, 0},
2958 {"include-text-in-reply", "Include Text in Reply",
2959 F_AUTO_INCLUDE_IN_REPLY, h_config_auto_include_reply, PREF_RPLY, 0},
2960 {"reply-always-uses-reply-to", "Reply Always Uses Reply-To",
2961 F_AUTO_REPLY_TO, h_config_auto_reply_to, PREF_RPLY, 0},
2962 {"signature-at-bottom", "Signature at Bottom",
2963 F_SIG_AT_BOTTOM, h_config_sig_at_bottom, PREF_RPLY, 0},
2964 {"strip-from-sigdashes-on-reply", "Strip From Sigdashes on Reply",
2965 F_ENABLE_STRIP_SIGDASHES, h_config_strip_sigdashes, PREF_RPLY, 0},
2966 {"forward-as-attachment", "Forward messages as attachments",
2967 F_FORWARD_AS_ATTACHMENT, h_config_forward_as_attachment, PREF_RPLY, 0},
2968 {"preserve-original-fields", NULL,
2969 F_PRESERVE_ORIGINAL_FIELD, h_config_preserve_field, PREF_RPLY, 0},
2971 /* Sending Prefs */
2972 {"disable-sender", "Do Not Generate Sender Header",
2973 F_DISABLE_SENDER, h_config_disable_sender, PREF_SEND, 1},
2974 {"use-sender-not-x-sender", "Use Sender Instead of X-X-Sender",
2975 F_USE_SENDER_NOT_X, h_config_use_sender_not_x, PREF_SEND, 0},
2976 {"quell-flowed-text", "Do Not Send Flowed Text",
2977 F_QUELL_FLOWED_TEXT, h_config_quell_flowed_text, PREF_SEND, 0},
2978 {"downgrade-multipart-to-text", "Downgrade Multipart to Text",
2979 F_COMPOSE_ALWAYS_DOWNGRADE, h_downgrade_multipart_to_text, PREF_SEND, 0},
2980 {"enable-8bit-esmtp-negotiation", "Enable 8bit ESMTP Negotiation",
2981 F_ENABLE_8BIT, h_config_8bit_smtp, PREF_SEND, 1},
2982 #ifdef BACKGROUND_POST
2983 {"enable-background-sending", NULL,
2984 F_BACKGROUND_POST, h_config_compose_bg_post, PREF_SEND, 0},
2985 #endif
2986 {"enable-delivery-status-notification", NULL,
2987 F_DSN, h_config_compose_dsn, PREF_SEND, 0},
2988 {"enable-verbose-smtp-posting", "Enable Verbose SMTP Posting",
2989 F_VERBOSE_POST, h_config_verbose_post, PREF_SEND, 0},
2990 {"fcc-without-attachments", "Fcc Does Not Include Attachments",
2991 F_NO_FCC_ATTACH, h_config_no_fcc_attach, PREF_SEND, 0},
2992 {"fcc-on-bounce", "Include Fcc When Bouncing Messages",
2993 F_FCC_ON_BOUNCE, h_config_fcc_on_bounce, PREF_SEND, 0},
2994 {"mark-fcc-seen", NULL,
2995 F_MARK_FCC_SEEN, h_config_mark_fcc_seen, PREF_SEND, 0},
2996 {"fcc-only-without-confirm", "Send to Fcc Only Without Confirming",
2997 F_AUTO_FCC_ONLY, h_config_auto_fcc_only, PREF_SEND, 0},
2998 {"send-without-confirm", "Send Without Confirming",
2999 F_SEND_WO_CONFIRM, h_config_send_wo_confirm, PREF_SEND, 0},
3000 {"strip-whitespace-before-send", "Strip Whitespace Before Sending",
3001 F_STRIP_WS_BEFORE_SEND, h_config_strip_ws_before_send, PREF_SEND, 0},
3002 {"warn-if-blank-fcc", "Warn if Blank Fcc",
3003 F_WARN_ABOUT_NO_FCC, h_config_warn_if_fcc_blank, PREF_SEND, 0},
3004 {"warn-if-blank-subject", "Warn if Blank Subject",
3005 F_WARN_ABOUT_NO_SUBJECT, h_config_warn_if_subj_blank, PREF_SEND, 0},
3006 {"warn-if-blank-to-and-cc-and-newsgroups", "Warn if Blank To and CC and Newsgroups",
3007 F_WARN_ABOUT_NO_TO_OR_CC, h_config_warn_if_no_to_or_cc, PREF_SEND, 0},
3009 /* Folder */
3010 {"combined-folder-display", NULL,
3011 F_CMBND_FOLDER_DISP, h_config_combined_folder_display, PREF_FLDR, 0},
3012 {"combined-subdirectory-display", NULL,
3013 F_CMBND_SUBDIR_DISP, h_config_combined_subdir_display, PREF_FLDR, 0},
3014 {"enable-lame-list-mode", "Compensate for Deficient IMAP servers",
3015 F_FIX_BROKEN_LIST, h_config_lame_list_mode, PREF_FLDR, 0},
3016 {"enable-dot-folders", "Enable Hidden Folders",
3017 F_ENABLE_DOT_FOLDERS, h_config_enable_dot_folders, PREF_FLDR, 0},
3018 {"enable-incoming-folders", "Enable Incoming Folders Collection",
3019 F_ENABLE_INCOMING, h_config_enable_incoming, PREF_FLDR, 0},
3020 {"enable-incoming-folders-checking", NULL,
3021 F_ENABLE_INCOMING_CHECKING, h_config_enable_incoming_checking, PREF_FLDR, 0},
3022 {"incoming-checking-includes-total", NULL,
3023 F_INCOMING_CHECKING_TOTAL, h_config_incoming_checking_total, PREF_FLDR, 0},
3024 {"incoming-checking-uses-recent", NULL,
3025 F_INCOMING_CHECKING_RECENT, h_config_incoming_checking_recent, PREF_FLDR, 0},
3026 {"expanded-view-of-folders", "Expanded View of Folders",
3027 F_EXPANDED_FOLDERS, h_config_expanded_folders, PREF_FLDR, 0},
3028 {"quell-empty-directories", "Hide Empty Directories",
3029 F_QUELL_EMPTY_DIRS, h_config_quell_empty_dirs, PREF_FLDR, 0},
3030 {"separate-folder-and-directory-entries", "Separate Folder and Directory Entries",
3031 F_SEPARATE_FLDR_AS_DIR, h_config_separate_fold_dir_view, PREF_FLDR, 0},
3032 {"single-column-folder-list", NULL,
3033 F_SINGLE_FOLDER_LIST, h_config_single_list, PREF_FLDR, 0},
3034 {"sort-default-fcc-alpha", "Sort Default Fcc Folder Alphabetically",
3035 F_SORT_DEFAULT_FCC_ALPHA, h_config_sort_fcc_alpha, PREF_FLDR, 0},
3036 {"sort-default-save-alpha", "Sort Default Save Folder Alphabetically",
3037 F_SORT_DEFAULT_SAVE_ALPHA, h_config_sort_save_alpha, PREF_FLDR, 0},
3038 {"vertical-folder-list", "Use Vertical Folder List",
3039 F_VERTICAL_FOLDER_LIST, h_config_vertical_list, PREF_FLDR, 0},
3041 /* Addr book */
3042 {"combined-addrbook-display", "Combined Address Book Display",
3043 F_CMBND_ABOOK_DISP, h_config_combined_abook_display, PREF_ADDR, 0},
3044 {"expanded-view-of-addressbooks", "Expanded View of Address Books",
3045 F_EXPANDED_ADDRBOOKS, h_config_expanded_addrbooks, PREF_ADDR, 0},
3046 {"expanded-view-of-distribution-lists", "Expanded View of Distribution Lists",
3047 F_EXPANDED_DISTLISTS, h_config_expanded_distlists, PREF_ADDR, 0},
3048 #ifdef ENABLE_LDAP
3049 {"ldap-result-to-addrbook-add", "LDAP Result to Addressbook Add",
3050 F_ADD_LDAP_TO_ABOOK, h_config_add_ldap, PREF_ADDR, 0},
3051 #endif
3053 /* Index prefs */
3054 {"auto-open-next-unread", NULL,
3055 F_AUTO_OPEN_NEXT_UNREAD, h_config_auto_open_unread, PREF_INDX, 0},
3056 {"continue-tab-without-confirm", "Continue NextNew Without Confirming",
3057 F_TAB_NO_CONFIRM, h_config_tab_no_prompt, PREF_INDX, 0},
3058 {"convert-dates-to-localtime", NULL,
3059 F_DATES_TO_LOCAL, h_config_dates_to_local, PREF_INDX, 0},
3060 {"delete-skips-deleted", NULL,
3061 F_DEL_SKIPS_DEL, h_config_del_skips_del, PREF_INDX, 1},
3062 {"disable-index-locale-dates", NULL,
3063 F_DISABLE_INDEX_LOCALE_DATES, h_config_disable_index_locale_dates, PREF_INDX, 0},
3064 {"enable-cruise-mode", NULL,
3065 F_ENABLE_SPACE_AS_TAB, h_config_cruise_mode, PREF_INDX, 0},
3066 {"enable-cruise-mode-delete", "Enable Cruise Mode With Deleting",
3067 F_ENABLE_TAB_DELETES, h_config_cruise_mode_delete, PREF_INDX, 0},
3068 {"mark-for-cc", "Mark for CC",
3069 F_MARK_FOR_CC, h_config_mark_for_cc, PREF_INDX, 1},
3070 {"next-thread-without-confirm", "Read Next Thread Without Confirming",
3071 F_NEXT_THRD_WO_CONFIRM, h_config_next_thrd_wo_confirm, PREF_INDX, 0},
3072 {"return-to-inbox-without-confirm", "Return to INBOX Without Confirming",
3073 F_RET_INBOX_NO_CONFIRM, h_config_inbox_no_confirm, PREF_INDX, 0},
3074 {"show-sort", "Show Sort in Titlebar",
3075 F_SHOW_SORT, h_config_show_sort, PREF_INDX, 0},
3076 {"tab-uses-unseen-for-next-folder", "Tab Uses Unseen for Next Folder",
3077 F_TAB_USES_UNSEEN, h_config_tab_uses_unseen, PREF_INDX, 0},
3078 {"tab-visits-next-new-message-only", NULL,
3079 F_TAB_TO_NEW, h_config_tab_new_only, PREF_INDX, 0},
3080 {"thread-index-shows-important-color", NULL,
3081 F_COLOR_LINE_IMPORTANT, h_config_color_thrd_import, PREF_INDX, 0},
3082 {"thread-sorts-by-arrival", "Thread Sorts by Arrival",
3083 F_THREAD_SORTS_BY_ARRIVAL, h_config_thread_sorts_by_arrival, PREF_INDX, 0},
3085 /* Viewer prefs */
3086 {"enable-msg-view-addresses", "Enable Message View Address Links",
3087 F_SCAN_ADDR, h_config_enable_view_addresses, PREF_VIEW, 0},
3088 {"enable-msg-view-attachments", "Enable Message View Attachment Links",
3089 F_VIEW_SEL_ATTACH, h_config_enable_view_attach, PREF_VIEW, 0},
3090 {"enable-msg-view-urls", "Enable Message View URL Links",
3091 F_VIEW_SEL_URL, h_config_enable_view_url, PREF_VIEW, 1},
3092 {"enable-msg-view-web-hostnames", "Enable Message View Web Hostname Links",
3093 F_VIEW_SEL_URL_HOST, h_config_enable_view_web_host, PREF_VIEW, 1},
3094 {"enable-msg-view-forced-arrows", "Enable Message View Forced Arrows",
3095 F_FORCE_ARROWS, h_config_enable_view_arrows, PREF_VIEW, 0},
3096 {"external-command-loads-inline-images-only", NULL,
3097 F_EXTERNAL_INLINE_IMAGES, h_external_loads_inline_images_only, PREF_VIEW, 1},
3098 /* set to TRUE for windows */
3099 {"pass-c1-control-characters-as-is", NULL,
3100 F_PASS_C1_CONTROL_CHARS, h_config_pass_c1_control, PREF_VIEW, 0},
3101 {"pass-control-characters-as-is", NULL,
3102 F_PASS_CONTROL_CHARS, h_config_pass_control, PREF_VIEW, 0},
3103 {"prefer-plain-text", NULL,
3104 F_PREFER_PLAIN_TEXT, h_config_prefer_plain_text, PREF_VIEW, 0},
3105 {"quell-charset-warning", "Suppress Character Set Warning",
3106 F_QUELL_CHARSET_WARNING, h_config_quell_charset_warning, PREF_VIEW, 0},
3107 {"quell-server-after-link-in-html", "Suppress Server After Link in HTML",
3108 F_QUELL_HOST_AFTER_URL, h_config_quell_host_after_url, PREF_VIEW, 0},
3110 /* News */
3111 {"compose-sets-newsgroup-without-confirm", "Compose Sets Newsgroup Without Confirming",
3112 F_COMPOSE_TO_NEWSGRP, h_config_compose_news_wo_conf, PREF_NEWS, 0},
3113 {"enable-8bit-nntp-posting", "Enable 8bit NNTP Posting",
3114 F_ENABLE_8BIT_NNTP, h_config_8bit_nntp, PREF_NEWS, 0},
3115 {"enable-multiple-newsrcs", NULL,
3116 F_ENABLE_MULNEWSRCS, h_config_enable_mulnewsrcs, PREF_NEWS, 0},
3117 {"mult-newsrc-hostnames-as-typed", "Multiple Newsrc Hostnames as Typed",
3118 F_MULNEWSRC_HOSTNAMES_AS_TYPED, h_config_mulnews_as_typed, PREF_NEWS, 0},
3119 {"hide-nntp-path", "Hide NNTP Path",
3120 F_HIDE_NNTP_PATH, h_config_hide_nntp_path, PREF_NEWS, 0},
3121 {"news-approximates-new-status", NULL,
3122 F_FAKE_NEW_IN_NEWS, h_config_news_uses_recent, PREF_NEWS, 1},
3123 {"news-deletes-across-groups", NULL,
3124 F_NEWS_CROSS_DELETE, h_config_news_cross_deletes, PREF_NEWS, 0},
3125 {"news-offers-catchup-on-close", "News Offers Catchup on Close",
3126 F_NEWS_CATCHUP, h_config_news_catchup, PREF_NEWS, 0},
3127 {"news-post-without-validation", NULL,
3128 F_NO_NEWS_VALIDATION, h_config_post_wo_validation, PREF_NEWS, 0},
3129 {"news-read-in-newsrc-order", "News Read in Newsrc Order",
3130 F_READ_IN_NEWSRC_ORDER, h_config_read_in_newsrc_order, PREF_NEWS, 0},
3131 {"nntp-search-uses-overview", "NNTP Search Uses Overview",
3132 F_NNTP_SEARCH_USES_OVERVIEW, h_config_nntp_search_uses_overview, PREF_NEWS, 1},
3133 {"predict-nntp-server", "Predict NNTP Server",
3134 F_PREDICT_NNTP_SERVER, h_config_predict_nntp_server, PREF_NEWS, 0},
3135 {"quell-extra-post-prompt", "Suppress Extra Posting Prompt",
3136 F_QUELL_EXTRA_POST_PROMPT, h_config_quell_post_prompt, PREF_NEWS, 0},
3138 /* Print */
3139 {"enable-print-via-y-command", NULL,
3140 F_ENABLE_PRYNT, h_config_enable_y_print, PREF_PRNT, 0},
3141 {"print-formfeed-between-messages", NULL,
3142 F_AGG_PRINT_FF, h_config_ff_between_msgs, PREF_PRNT, 0},
3143 {"print-includes-from-line", NULL,
3144 F_FROM_DELIM_IN_PRINT, h_config_print_from, PREF_PRNT, 0},
3145 {"print-index-enabled", NULL,
3146 F_PRINT_INDEX, h_config_print_index, PREF_PRNT, 0},
3147 {"print-offers-custom-cmd-prompt", "Print Offers Custom Command Prompt",
3148 F_CUSTOM_PRINT, h_config_custom_print, PREF_PRNT, 0},
3150 /* adv cmd prefs */
3151 {"enable-aggregate-command-set", NULL,
3152 F_ENABLE_AGG_OPS, h_config_enable_agg_ops, PREF_ACMD, 1},
3153 {"enable-arrow-navigation", NULL,
3154 F_ARROW_NAV, h_config_arrow_nav, PREF_ACMD, 1},
3155 {"enable-arrow-navigation-relaxed", NULL,
3156 F_RELAXED_ARROW_NAV, h_config_relaxed_arrow_nav, PREF_ACMD, 1},
3157 {"enable-bounce-cmd", "Enable Bounce Command",
3158 F_ENABLE_BOUNCE, h_config_enable_bounce, PREF_ACMD, 1},
3159 {"enable-exit-via-lessthan-command", NULL,
3160 F_ENABLE_LESSTHAN_EXIT, h_config_enable_lessthan_exit, PREF_ACMD, 1},
3161 {"enable-flag-cmd", "Enable Flag Command",
3162 F_ENABLE_FLAG, h_config_enable_flag, PREF_ACMD, 1},
3163 {"enable-flag-screen-implicitly", NULL,
3164 F_FLAG_SCREEN_DFLT, h_config_flag_screen_default, PREF_ACMD, 0},
3165 {"enable-flag-screen-keyword-shortcut", NULL,
3166 F_FLAG_SCREEN_KW_SHORTCUT, h_config_flag_screen_kw_shortcut,PREF_ACMD, 1},
3167 {"enable-full-header-and-text", "Enable Full Header and Text",
3168 F_ENABLE_FULL_HDR_AND_TEXT, h_config_enable_full_hdr_and_text, PREF_ACMD, 0},
3169 {"enable-full-header-cmd", "Enable Full Header Command",
3170 F_ENABLE_FULL_HDR, h_config_enable_full_hdr, PREF_ACMD, 1},
3171 {"enable-goto-in-file-browser", "Enable Goto in File Browser",
3172 F_ALLOW_GOTO, h_config_allow_goto, PREF_ACMD, 1},
3173 {"enable-jump-shortcut", NULL,
3174 F_ENABLE_JUMP, h_config_enable_jump, PREF_ACMD, 1},
3175 {"enable-partial-match-lists", NULL,
3176 F_ENABLE_SUB_LISTS, h_config_sub_lists, PREF_ACMD, 1},
3177 {"enable-tab-completion", NULL,
3178 F_ENABLE_TAB_COMPLETE, h_config_enable_tab_complete, PREF_ACMD, 1},
3179 {"enable-unix-pipe-cmd", "Enable Unix Pipe Command",
3180 F_ENABLE_PIPE, h_config_enable_pipe, PREF_ACMD, 1},
3181 {"quell-full-header-auto-reset", "Suppress Full Header Auto Reset",
3182 F_QUELL_FULL_HDR_RESET, h_config_quell_full_hdr_reset, PREF_ACMD, 0},
3184 /* Adv user prefs */
3185 #if !defined(DOS) && !defined(OS2)
3186 {"allow-talk", NULL,
3187 F_ALLOW_TALK, h_config_allow_talk, PREF_MISC, 0},
3188 #endif
3189 {"assume-slow-link", NULL,
3190 F_FORCE_LOW_SPEED, h_config_force_low_speed, PREF_OS_LWSD, 0},
3191 {"auto-move-read-msgs", "Auto Move Read Messages",
3192 F_AUTO_READ_MSGS, h_config_auto_read_msgs, PREF_MISC, 0},
3193 {"auto-unselect-after-apply", NULL,
3194 F_AUTO_UNSELECT, h_config_auto_unselect, PREF_MISC, 0},
3195 {"auto-unzoom-after-apply", NULL,
3196 F_AUTO_UNZOOM, h_config_auto_unzoom, PREF_MISC, 1},
3197 {"auto-zoom-after-select", NULL,
3198 F_AUTO_ZOOM, h_config_auto_zoom, PREF_MISC, 1},
3199 {"busy-cue-spinner-only", NULL,
3200 F_USE_BORING_SPINNER, h_config_use_boring_spinner, PREF_MISC, 0},
3201 {"check-newmail-when-quitting", NULL,
3202 F_CHECK_MAIL_ONQUIT, h_config_check_mail_onquit, PREF_MISC, 0},
3203 {"confirm-role-even-for-default", "Confirm Role Even for Default",
3204 F_ROLE_CONFIRM_DEFAULT, h_config_confirm_role, PREF_MISC, 0},
3205 {"disable-keymenu", NULL,
3206 F_BLANK_KEYMENU, h_config_blank_keymenu, PREF_MISC, 0},
3207 {"disable-password-caching", NULL,
3208 F_DISABLE_PASSWORD_CACHING, h_config_disable_password_caching,
3209 PREF_MISC, 0},
3210 #ifdef LOCAL_PASSWD_CACHE
3211 {"disable-password-file-saving", NULL,
3212 F_DISABLE_PASSWORD_FILE_SAVING, h_config_disable_password_file_saving,
3213 PREF_MISC, 0},
3214 #endif /* LOCAL_PASSWD_CACHE */
3215 {"disable-regular-expression-matching-for-alternate-addresses", NULL,
3216 F_DISABLE_REGEX, h_config_disable_regex, PREF_MISC, 0},
3217 {"disable-save-input-history", NULL,
3218 F_DISABLE_SAVE_INPUT_HISTORY, h_config_input_history, PREF_MISC, 0},
3219 {"disable-take-fullname-in-addresses", "Disable Take Fullname in Addresses",
3220 F_DISABLE_TAKE_FULLNAMES, h_config_take_fullname, PREF_MISC, 0},
3221 {"disable-take-last-comma-first", NULL,
3222 F_DISABLE_TAKE_LASTFIRST, h_config_take_lastfirst, PREF_MISC, 0},
3223 {"disable-terminal-reset-for-display-filters", "Disable Terminal Reset for Display Filters",
3224 F_DISABLE_TERM_RESET_DISP, h_config_disable_reset_disp, PREF_MISC, 0},
3225 {"enable-dot-files", NULL,
3226 F_ENABLE_DOT_FILES, h_config_enable_dot_files, PREF_MISC, 0},
3227 {"enable-fast-recent-test", NULL,
3228 F_ENABLE_FAST_RECENT, h_config_fast_recent, PREF_MISC, 0},
3229 {"enable-mail-check-cue", NULL,
3230 F_SHOW_DELAY_CUE, h_config_show_delay_cue, PREF_MISC, 0},
3231 {"enable-mailcap-param-substitution", "Enable Mailcap Parameter Substitution",
3232 F_DO_MAILCAP_PARAM_SUBST, h_config_mailcap_params, PREF_MISC, 0},
3233 {"enable-mouse-in-xterm", "Enable Mouse in Xterm",
3234 F_ENABLE_MOUSE, h_config_enable_mouse, PREF_OS_MOUSE, 0},
3235 {"enable-newmail-in-xterm-icon", "Enable Newmail in Xterm Icon",
3236 F_ENABLE_XTERM_NEWMAIL, h_config_enable_xterm_newmail, PREF_OS_XNML, 0},
3237 {"enable-newmail-short-text-in-icon", "Enable Newmail Short Text in Icon",
3238 F_ENABLE_NEWMAIL_SHORT_TEXT, h_config_enable_newmail_short_text, PREF_OS_XNML, 0},
3239 {"enable-suspend", NULL,
3240 F_CAN_SUSPEND, h_config_can_suspend, PREF_MISC, 0},
3241 {"enable-take-export", NULL,
3242 F_ENABLE_TAKE_EXPORT, h_config_enable_take_export, PREF_MISC, 0},
3243 {"enable-rules-under-take", "Enable Take Rules",
3244 F_ENABLE_ROLE_TAKE, h_config_enable_role_take, PREF_MISC, 0},
3245 #ifdef _WINDOWS
3246 {"enable-tray-icon", NULL,
3247 F_ENABLE_TRAYICON, h_config_tray_icon, PREF_MISC, 0},
3248 #endif
3249 {"expose-hidden-config", NULL,
3250 F_EXPOSE_HIDDEN_CONFIG, h_config_expose_hidden_config, PREF_MISC, 0},
3251 {"expunge-only-manually", NULL,
3252 F_EXPUNGE_MANUALLY, h_config_expunge_manually, PREF_MISC, 0},
3253 {"expunge-without-confirm", "Expunge Without Confirming",
3254 F_AUTO_EXPUNGE, h_config_auto_expunge, PREF_MISC, 0},
3255 {"expunge-without-confirm-everywhere", "Expunge Without Confirming Everywhere",
3256 F_FULL_AUTO_EXPUNGE, h_config_full_auto_expunge, PREF_MISC, 0},
3257 {"force-arrow-cursor", NULL,
3258 F_FORCE_ARROW, h_config_force_arrow, PREF_MISC, 0},
3259 {"ignore-size-changes", NULL,
3260 F_IGNORE_SIZE, h_config_ignore_size, PREF_MISC, 0},
3261 {"maildrops-preserve-state", NULL,
3262 F_MAILDROPS_PRESERVE_STATE, h_config_maildrops_preserve_state,
3263 PREF_MISC, 0},
3264 {"offer-expunge-of-inbox", "Offer Expunge of INBOX",
3265 F_EXPUNGE_INBOX, h_config_expunge_inbox, PREF_MISC, 0},
3266 {"offer-expunge-of-stayopen-folders", "Offer Expunge of Stayopen Folders",
3267 F_EXPUNGE_STAYOPENS, h_config_expunge_stayopens, PREF_MISC, 0},
3268 {"preopen-stayopen-folders", NULL,
3269 F_PREOPEN_STAYOPENS, h_config_preopen_stayopens, PREF_MISC, 0},
3270 {"preserve-start-stop-characters", "Preserve Start/Stop Characters",
3271 F_PRESERVE_START_STOP, h_config_preserve_start_stop, PREF_OS_STSP, 0},
3272 {"quell-folder-internal-msg", "Prevent Folder Internal Message",
3273 F_QUELL_INTERNAL_MSG, h_config_quell_folder_internal_msg, PREF_MISC, 0},
3274 {"quell-partial-fetching", "Prevent Partial Fetching",
3275 F_QUELL_PARTIAL_FETCH, h_config_quell_partial, PREF_MISC, 0},
3276 {"prune-uses-yyyy-mm", "Prune Uses YYYY-MM",
3277 F_PRUNE_USES_ISO, h_config_prune_uses_iso, PREF_MISC, 0},
3278 {"quit-without-confirm", "Quit Without Confirming",
3279 F_QUIT_WO_CONFIRM, h_config_quit_wo_confirm, PREF_MISC, 0},
3280 {"quote-replace-nonflowed", NULL,
3281 F_QUOTE_REPLACE_NOFLOW, h_config_quote_replace_noflow, PREF_MISC, 0},
3282 {"save-aggregates-copy-sequence", "Save Combines Copies (may be out of order)",
3283 F_AGG_SEQ_COPY, h_config_save_aggregates, PREF_MISC, 1},
3284 {"save-partial-msg-without-confirm", "Save Partial Message Without Confirming",
3285 F_SAVE_PARTIAL_WO_CONFIRM, h_config_save_part_wo_confirm, PREF_MISC, 0},
3286 {"save-will-advance", NULL,
3287 F_SAVE_ADVANCES, h_config_save_advances, PREF_MISC, 0},
3288 {"save-will-not-delete", NULL,
3289 F_SAVE_WONT_DELETE, h_config_save_wont_delete, PREF_MISC, 0},
3290 {"save-will-quote-leading-froms", NULL,
3291 F_QUOTE_ALL_FROMS, h_config_quote_all_froms, PREF_MISC, 0},
3292 {"scramble-message-id", "Scramble the Message-ID When Sending",
3293 F_ROT13_MESSAGE_ID, h_config_scramble_message_id, PREF_MISC, 0},
3294 {"select-without-confirm", "Select Ctrl-T Foldername Without Confirming",
3295 F_SELECT_WO_CONFIRM, h_config_select_wo_confirm, PREF_MISC, 0},
3296 {"show-cursor", NULL,
3297 F_SHOW_CURSOR, h_config_show_cursor, PREF_MISC, 0},
3298 {"show-plain-text-internally", NULL,
3299 F_SHOW_TEXTPLAIN_INT, h_config_textplain_int, PREF_MISC, 0},
3300 {"show-selected-in-boldface", "Show Selected in Boldface",
3301 F_SELECTED_SHOWN_BOLD, h_config_select_in_bold, PREF_MISC, 0},
3302 {"slash-collapses-entire-thread", NULL,
3303 F_SLASH_COLL_ENTIRE, h_config_slash_coll_entire, PREF_MISC, 0},
3304 #ifdef _WINDOWS
3305 {"store-window-position-in-config", "Store Window Position in Config",
3306 F_STORE_WINPOS_IN_CONFIG, h_config_winpos_in_config, PREF_MISC, 0},
3307 #endif
3308 {"suppress-asterisks-in-password-prompt", "Suppress Asterisks in Password Prompt",
3309 F_QUELL_ASTERISKS, h_config_quell_asterisks,
3310 PREF_MISC, 0},
3311 {"quell-attachment-extension-warn", "Suppress Attachment Extension Warning",
3312 F_QUELL_ATTACH_EXT_WARN, h_config_quell_attach_ext_warn,
3313 PREF_MISC, 0},
3314 {"quell-attachment-extra-prompt", "Suppress Attachment Extra Prompt",
3315 F_QUELL_ATTACH_EXTRA_PROMPT, h_config_quell_attach_extra_prompt,
3316 PREF_MISC, 0},
3317 {"quell-berkeley-format-timezone", "Suppress Berkeley Format Timezone",
3318 F_QUELL_BEZERK_TIMEZONE, h_config_no_bezerk_zone, PREF_MISC, 0},
3319 {"quell-content-id", "Suppress Content-ID",
3320 F_QUELL_CONTENT_ID, h_config_quell_content_id, PREF_MISC, 0},
3321 {"quell-filtering-done-message", "Suppress Filtering Done Message",
3322 F_QUELL_FILTER_DONE_MSG, h_config_quell_filtering_done_message,
3323 PREF_MISC, 0},
3324 {"quell-filtering-messages", "Suppress Filtering Messages",
3325 F_QUELL_FILTER_MSGS, h_config_quell_filtering_messages,
3326 PREF_MISC, 0},
3327 {"quell-imap-envelope-update", "Suppress IMAP Envelope Update",
3328 F_QUELL_IMAP_ENV_CB, h_config_quell_imap_env, PREF_MISC, 0},
3329 {"quell-lock-failure-warnings", "Suppress Lock Failure Warnings",
3330 F_QUELL_LOCK_FAILURE_MSGS, h_config_quell_lock_failure_warnings,
3331 PREF_MISC, 0},
3332 {"quell-maildomain-warning", "Suppress Maildomain Warning",
3333 F_QUELL_MAILDOMAIN_WARNING, h_config_quell_domain_warn, PREF_MISC, 0},
3334 {"quell-news-envelope-update", "Suppress News Envelope Update",
3335 F_QUELL_NEWS_ENV_CB, h_config_quell_news_env, PREF_MISC, 0},
3336 #ifdef _WINDOWS
3337 {"quell-ssl-largeblocks", "Prevent SSL Largeblocks",
3338 F_QUELL_SSL_LARGEBLOCKS, h_config_quell_ssl_largeblocks, PREF_MISC, 0},
3339 #endif
3340 {"quell-status-message-beeping", "Suppress Status Message Beeping",
3341 F_QUELL_BEEPS, h_config_quell_beeps, PREF_MISC, 0},
3342 {"quell-timezone-comment-when-sending", "Suppress Timezone Comment When Sending",
3343 F_QUELL_TIMEZONE, h_config_quell_tz_comment, PREF_MISC, 0},
3344 {"suppress-user-agent-when-sending", NULL,
3345 F_QUELL_USERAGENT, h_config_suppress_user_agent, PREF_MISC, 1},
3346 {"tab-checks-recent", "Tab Checks for Recent Messages",
3347 F_TAB_CHK_RECENT, h_config_tab_checks_recent, PREF_MISC, 0},
3348 {"termdef-takes-precedence", NULL,
3349 F_TCAP_WINS, h_config_termcap_wins, PREF_MISC, 0},
3350 {"try-alternative-authentication-driver-first", NULL,
3351 F_PREFER_ALT_AUTH, h_config_alt_auth, PREF_MISC, 0},
3352 {"unselect-will-not-advance", NULL,
3353 F_UNSELECT_WONT_ADVANCE, h_config_unsel_wont_advance, PREF_MISC, 0},
3354 {"use-current-dir", "Use Current Directory",
3355 F_USE_CURRENT_DIR, h_config_use_current_dir, PREF_MISC, 0},
3356 {"use-function-keys", NULL,
3357 F_USE_FK, h_config_use_fk, PREF_OS_USFK, 0},
3358 {"use-regular-startup-rule-for-stayopen-folders", "Use Regular Startup Rule for Stayopen Folders",
3359 F_STARTUP_STAYOPEN, h_config_use_reg_start_for_stayopen, PREF_MISC, 0},
3360 {"use-resent-to-in-rules", "Use Resent-To in Rules",
3361 F_USE_RESENTTO, h_config_use_resentto, PREF_MISC, 0},
3362 {"use-subshell-for-suspend", "Use Subshell for Suspend",
3363 F_SUSPEND_SPAWNS, h_config_suspend_spawns, PREF_OS_SPWN, 0},
3364 #ifndef _WINDOWS
3365 {"use-system-translation", NULL,
3366 F_USE_SYSTEM_TRANS, h_config_use_system_translation, PREF_MISC, 0},
3367 #endif
3369 /* Hidden Features */
3370 {"old-growth", NULL,
3371 F_OLD_GROWTH, NO_HELP, PREF_NONE, 0},
3372 {"disable-config-cmd", NULL,
3373 F_DISABLE_CONFIG_SCREEN, h_config_disable_config_cmd, PREF_HIDDEN, 0},
3374 {"disable-keyboard-lock-cmd", NULL,
3375 F_DISABLE_KBLOCK_CMD, h_config_disable_kb_lock, PREF_HIDDEN, 0},
3376 {"disable-password-cmd", NULL,
3377 F_DISABLE_PASSWORD_CMD, h_config_disable_password_cmd, PREF_HIDDEN, 0},
3378 {"disable-pipes-in-sigs", NULL,
3379 F_DISABLE_PIPES_IN_SIGS, h_config_disable_pipes_in_sigs, PREF_HIDDEN, 0},
3380 {"disable-pipes-in-templates", NULL,
3381 F_DISABLE_PIPES_IN_TEMPLATES, h_config_disable_pipes_in_templates,
3382 PREF_HIDDEN, 0},
3383 {"disable-roles-setup-cmd", NULL,
3384 F_DISABLE_ROLES_SETUP, h_config_disable_roles_setup, PREF_HIDDEN, 0},
3385 {"disable-roles-sig-edit", NULL,
3386 F_DISABLE_ROLES_SIGEDIT, h_config_disable_roles_sigedit, PREF_HIDDEN, 0},
3387 {"disable-roles-template-edit", NULL,
3388 F_DISABLE_ROLES_TEMPLEDIT, h_config_disable_roles_templateedit,
3389 PREF_HIDDEN, 0},
3390 {"disable-setlocale-collate", NULL,
3391 F_DISABLE_SETLOCALE_COLLATE, h_config_disable_collate, PREF_HIDDEN, 0},
3392 {"disable-shared-namespaces", NULL,
3393 F_DISABLE_SHARED_NAMESPACES, h_config_disable_shared, PREF_HIDDEN, 0},
3394 {"disable-signature-edit-cmd", NULL,
3395 F_DISABLE_SIGEDIT_CMD, h_config_disable_signature_edit, PREF_HIDDEN, 0},
3396 {"enable-delete-before-writing", NULL,
3397 F_ENABLE_DEL_WHEN_WRITING, h_config_delete_before_writing, PREF_HIDDEN, 0},
3398 {"new-thread-on-blank-subject", "New Thread on Blank Subject",
3399 F_NEW_THREAD_ON_BLANK_SUBJECT, h_config_new_thread_blank_subject, PREF_HIDDEN, 1},
3400 {"quell-personal-name-prompt", NULL,
3401 F_QUELL_PERSONAL_NAME_PROMPT, h_config_quell_personal_name_prompt, PREF_HIDDEN, 0},
3402 {"quell-user-id-prompt", "Quell User ID Prompt",
3403 F_QUELL_USER_ID_PROMPT, h_config_quell_user_id_prompt, PREF_HIDDEN, 0},
3404 #ifdef SMIME
3405 {"smime-dont-do-smime", "S/MIME -- Turn off S/MIME",
3406 F_DONT_DO_SMIME, h_config_smime_dont_do_smime, PREF_HIDDEN, 0},
3407 {"smime-encrypt-by-default", "S/MIME -- Encrypt by Default",
3408 F_ENCRYPT_DEFAULT_ON, h_config_smime_encrypt_by_default, PREF_HIDDEN, 0},
3409 {"smime-remember-passphrase", "S/MIME -- Remember S/MIME Passphrase",
3410 F_REMEMBER_SMIME_PASSPHRASE, h_config_smime_remember_passphrase, PREF_HIDDEN, 0},
3411 {"smime-sign-by-default", "S/MIME -- Sign by Default",
3412 F_SIGN_DEFAULT_ON, h_config_smime_sign_by_default, PREF_HIDDEN, 0},
3413 {"smime-use-store-only", "S/MIME -- Validate Using Certificate Store Only",
3414 F_USE_CERT_STORE_ONLY, h_config_smime_use_cert_store, PREF_HIDDEN, 1},
3415 #ifdef APPLEKEYCHAIN
3416 {"publiccerts-in-keychain", "S/MIME -- Public Certs in MacOS Keychain",
3417 F_PUBLICCERTS_IN_KEYCHAIN, h_config_smime_pubcerts_in_keychain, PREF_HIDDEN, 0},
3418 #endif
3419 #endif
3420 {"selectable-item-nobold", NULL,
3421 F_SLCTBL_ITEM_NOBOLD, NO_HELP, PREF_NONE, 0},
3422 {"send-confirms-only-expanded", NULL, /* exposed in Web Alpine */
3423 F_SEND_CONFIRM_ON_EXPAND, h_config_send_confirms_only_expanded, PREF_HIDDEN, 0},
3424 {"enable-jump-cmd", NULL, /* exposed in Web Alpine */
3425 F_ENABLE_JUMP_CMD, h_config_enable_jump_command, PREF_HIDDEN, 0},
3426 {"enable-newmail-sound", NULL, /* exposed in Web Alpine */
3427 F_ENABLE_NEWMAIL_SOUND, h_config_enable_newmail_sound, PREF_HIDDEN, 0},
3428 {"render-html-internally", NULL, /* exposed in Web Alpine */
3429 F_RENDER_HTML_INTERNALLY, h_config_render_html_internally, PREF_HIDDEN, 0}
3432 return((index >= 0 && index < (sizeof(feat_list)/sizeof(feat_list[0])))
3433 ? &feat_list[index] : NULL);
3438 * feature_list_index -- return index of given feature id in
3439 * feature list
3442 feature_list_index(int id)
3444 FEATURE_S *feature;
3445 int i;
3447 for(i = 0; (feature = feature_list(i)); i++)
3448 if(id == feature->id)
3449 return(i);
3451 return(-1);
3456 * feature_list_name -- return the given feature id's corresponding name
3458 char *
3459 feature_list_name(int id)
3461 FEATURE_S *f;
3463 return((f = feature_list(feature_list_index(id))) ? f->name : "");
3468 feature_list_id(char *name)
3470 FEATURE_S *f;
3471 int i;
3473 for(i = 0; (f = feature_list(i)); i++)
3474 if(!strucmp(f->name, name))
3475 return(f->id);
3477 return(-1);
3482 * feature_list_help -- return the given feature id's corresponding help
3484 HelpType
3485 feature_list_help(int id)
3487 FEATURE_S *f;
3489 return((f = feature_list(feature_list_index(id))) ? f->help : NO_HELP);
3494 * All the arguments past "list" are the backwards compatibility hacks.
3496 void
3497 process_feature_list(struct pine *ps, char **list, int old_growth, int hir, int osr)
3499 register char *q;
3500 char **p,
3501 *lvalue[BM_SIZE * 8];
3502 int i,
3503 yorn;
3504 long l;
3505 FEATURE_S *feat;
3508 /* clear all previous settings and reset them to default */
3509 for(i = 0; (feat = feature_list(i)) != NULL; i++)
3510 F_SET(feat->id, ps, feat->defval);
3512 /* backwards compatibility */
3513 if(hir)
3514 F_TURN_ON(F_INCLUDE_HEADER, ps);
3516 /* ditto */
3517 if(osr)
3518 F_TURN_ON(F_SIG_AT_BOTTOM, ps);
3520 /* ditto */
3521 if(old_growth)
3522 set_old_growth_bits(ps, 0);
3524 /* now run through the list (global, user, and cmd_line lists are here) */
3525 if(list){
3526 for(p = list; (q = *p) != NULL; p++){
3527 if(struncmp(q, "no-", 3) == 0){
3528 yorn = 0;
3529 q += 3;
3530 }else{
3531 yorn = 1;
3534 for(i = 0; (feat = feature_list(i)) != NULL; i++){
3535 if(strucmp(q, feat->name) == 0){
3536 if(feat->id == F_OLD_GROWTH){
3537 set_old_growth_bits(ps, yorn);
3538 }else{
3539 F_SET(feat->id, ps, yorn);
3541 break;
3545 /* if it wasn't in that list */
3546 if(feat == NULL)
3547 dprint((1,"Unrecognized feature in feature-list (%s%s)\n",
3548 (yorn ? "" : "no-"), q ? q : "?"));
3553 * Turn on gratuitous '>From ' quoting, if requested...
3555 mail_parameters(NULL, SET_FROMWIDGET,
3556 F_ON(F_QUOTE_ALL_FROMS, ps) ? VOIDT : NIL);
3559 * Turn off .lock creation complaints...
3561 if(F_ON(F_QUELL_LOCK_FAILURE_MSGS, ps))
3562 mail_parameters(NULL, SET_LOCKEACCESERROR, (void *) 0);
3565 * Turn on quelling of pseudo message.
3567 if(F_ON(F_QUELL_INTERNAL_MSG,ps_global))
3568 mail_parameters(NULL, SET_USERHASNOLIFE, (void *) 1);
3570 l = F_ON(F_MULNEWSRC_HOSTNAMES_AS_TYPED,ps_global) ? 0L : 1L;
3571 mail_parameters(NULL, SET_NEWSRCCANONHOST, (void *) l);
3573 ps->pass_ctrl_chars = F_ON(F_PASS_CONTROL_CHARS,ps_global) ? 1 : 0;
3574 ps->pass_c1_ctrl_chars = F_ON(F_PASS_C1_CONTROL_CHARS,ps_global) ? 1 : 0;
3576 #ifndef _WINDOWS
3577 if(F_ON(F_QUELL_BEZERK_TIMEZONE,ps_global))
3578 mail_parameters(NULL, SET_NOTIMEZONES, (void *) 1);
3579 #endif
3581 if(F_ON(F_USE_FK, ps))
3582 ps->orig_use_fkeys = 1;
3584 /* Will we have to build a new list? */
3585 if(!(old_growth || hir || osr))
3586 return;
3589 * Build a new list for feature-list. The only reason we ever need to
3590 * do this is if one of the obsolete options is being converted
3591 * into a feature-list item, and it isn't already included in the user's
3592 * feature-list.
3594 i = 0;
3595 for(p = LVAL(&ps->vars[V_FEATURE_LIST], Main);
3596 p && (q = *p); p++){
3597 /* already have it or cancelled it, don't need to add later */
3598 if(hir && (strucmp(q, "include-header-in-reply") == 0 ||
3599 strucmp(q, "no-include-header-in-reply") == 0)){
3600 hir = 0;
3601 }else if(osr && (strucmp(q, "signature-at-bottom") == 0 ||
3602 strucmp(q, "no-signature-at-bottom") == 0)){
3603 osr = 0;
3604 }else if(old_growth && (strucmp(q, "old-growth") == 0 ||
3605 strucmp(q, "no-old-growth") == 0)){
3606 old_growth = 0;
3608 lvalue[i++] = cpystr(q);
3611 /* check to see if we still need to build a new list */
3612 if(!(old_growth || hir || osr))
3613 return;
3615 if(hir)
3616 lvalue[i++] = "include-header-in-reply";
3617 if(osr)
3618 lvalue[i++] = "signature-at-bottom";
3619 if(old_growth)
3620 lvalue[i++] = "old-growth";
3621 lvalue[i] = NULL;
3622 set_variable_list(V_FEATURE_LIST, lvalue, TRUE, Main);
3626 void
3627 set_current_pattern_vals(struct pine *ps)
3629 struct variable *vars = ps->vars;
3631 set_current_val(&vars[V_PATTERNS], TRUE, TRUE);
3632 set_current_val(&vars[V_PAT_ROLES], TRUE, TRUE);
3633 set_current_val(&vars[V_PAT_FILTS], TRUE, TRUE);
3634 set_current_val(&vars[V_PAT_FILTS_OLD], TRUE, TRUE);
3635 set_current_val(&vars[V_PAT_SCORES], TRUE, TRUE);
3636 set_current_val(&vars[V_PAT_SCORES_OLD], TRUE, TRUE);
3637 set_current_val(&vars[V_PAT_INCOLS], TRUE, TRUE);
3638 set_current_val(&vars[V_PAT_OTHER], TRUE, TRUE);
3639 set_current_val(&vars[V_PAT_SRCH], TRUE, TRUE);
3642 * If old pattern variable (V_PATTERNS) is set and the new ones aren't
3643 * in the config file, then convert the old data into the new variables.
3644 * It isn't quite that simple, though, because we don't store unset
3645 * variables in remote pinercs. Check for the variables but if we
3646 * don't find any of them, also check the version number. This change was
3647 * made in version 4.30. We could just check that except that we're
3648 * worried somebody will make an incompatible version number change in
3649 * their local version, and will break this. So we check both the
3650 * version # and the var_in_pinerc things to be safer.
3652 if(vars[V_PATTERNS].current_val.l
3653 && vars[V_PATTERNS].current_val.l[0]
3654 && !var_in_pinerc(vars[V_PAT_ROLES].name)
3655 && !var_in_pinerc(vars[V_PAT_FILTS].name)
3656 && !var_in_pinerc(vars[V_PAT_FILTS_OLD].name)
3657 && !var_in_pinerc(vars[V_PAT_SCORES].name)
3658 && !var_in_pinerc(vars[V_PAT_SCORES_OLD].name)
3659 && !var_in_pinerc(vars[V_PAT_INCOLS].name)
3660 && isdigit((unsigned char) ps->pine_pre_vers[0])
3661 && ps->pine_pre_vers[1] == '.'
3662 && isdigit((unsigned char) ps->pine_pre_vers[2])
3663 && isdigit((unsigned char) ps->pine_pre_vers[3])
3664 && strncmp(ps->pine_pre_vers, "4.30", 4) < 0){
3665 convert_pattern_data();
3669 * Otherwise, if FILTS_OLD is set and FILTS isn't in the config file,
3670 * convert FILTS_OLD to FILTS. Same for SCORES.
3671 * The reason FILTS was changed was so we could change the
3672 * semantics of how rules work when there are pieces in the rule that
3673 * we don't understand. At the same time as the FILTS change we added
3674 * a rule to detect 8bitSubjects. So a user might have a filter that
3675 * deletes messages with 8bitSubjects. The problem is that that same
3676 * filter in a FILTS_OLD pine would match because it would ignore the
3677 * 8bitSubject part of the pattern and match on the rest. So we changed
3678 * the semantics so that rules with unknown bits would be ignored
3679 * instead of used. We had to change variable names at the same time
3680 * because we were adding the 8bit thing and the old pines are still
3681 * out there. Filters and Scores can both be dangerous. Roles, Colors,
3682 * and Other seem less dangerous so not worth adding a new variable.
3683 * This was changed in 4.50.
3685 else{
3686 if(vars[V_PAT_FILTS_OLD].current_val.l
3687 && vars[V_PAT_FILTS_OLD].current_val.l[0]
3688 && !var_in_pinerc(vars[V_PAT_FILTS].name)
3689 && !var_in_pinerc(vars[V_PAT_SCORES].name)
3690 && isdigit((unsigned char) ps->pine_pre_vers[0])
3691 && ps->pine_pre_vers[1] == '.'
3692 && isdigit((unsigned char) ps->pine_pre_vers[2])
3693 && isdigit((unsigned char) ps->pine_pre_vers[3])
3694 && strncmp(ps->pine_pre_vers, "4.50", 4) < 0){
3695 convert_filts_pattern_data();
3698 if(vars[V_PAT_SCORES_OLD].current_val.l
3699 && vars[V_PAT_SCORES_OLD].current_val.l[0]
3700 && !var_in_pinerc(vars[V_PAT_FILTS].name)
3701 && !var_in_pinerc(vars[V_PAT_SCORES].name)
3702 && isdigit((unsigned char) ps->pine_pre_vers[0])
3703 && ps->pine_pre_vers[1] == '.'
3704 && isdigit((unsigned char) ps->pine_pre_vers[2])
3705 && isdigit((unsigned char) ps->pine_pre_vers[3])
3706 && strncmp(ps->pine_pre_vers, "4.50", 4) < 0){
3707 convert_scores_pattern_data();
3711 if(vars[V_PAT_ROLES].post_user_val.l)
3712 ps_global->ew_for_role_take = Post;
3713 else
3714 ps_global->ew_for_role_take = Main;
3716 if(vars[V_PAT_FILTS].post_user_val.l)
3717 ps_global->ew_for_filter_take = Post;
3718 else
3719 ps_global->ew_for_filter_take = Main;
3721 if(vars[V_PAT_SCORES].post_user_val.l)
3722 ps_global->ew_for_score_take = Post;
3723 else
3724 ps_global->ew_for_score_take = Main;
3726 if(vars[V_PAT_INCOLS].post_user_val.l)
3727 ps_global->ew_for_incol_take = Post;
3728 else
3729 ps_global->ew_for_incol_take = Main;
3731 if(vars[V_PAT_OTHER].post_user_val.l)
3732 ps_global->ew_for_other_take = Post;
3733 else
3734 ps_global->ew_for_other_take = Main;
3736 if(vars[V_PAT_SRCH].post_user_val.l)
3737 ps_global->ew_for_srch_take = Post;
3738 else
3739 ps_global->ew_for_srch_take = Main;
3744 * Foreach of the config files;
3745 * transfer the data to the new variables.
3747 void
3748 convert_pattern_data(void)
3750 convert_pinerc_patterns(PAT_USE_MAIN);
3751 convert_pinerc_patterns(PAT_USE_POST);
3755 void
3756 convert_filts_pattern_data(void)
3758 convert_pinerc_filts_patterns(PAT_USE_MAIN);
3759 convert_pinerc_filts_patterns(PAT_USE_POST);
3763 void
3764 convert_scores_pattern_data(void)
3766 convert_pinerc_scores_patterns(PAT_USE_MAIN);
3767 convert_pinerc_scores_patterns(PAT_USE_POST);
3772 * Foreach of the four variables, transfer the data for this config file
3773 * from the old patterns variable. We don't have to convert OTHER patterns
3774 * or SRCH patterns because they didn't exist in pines without patterns-other.
3776 * If the original variable had patlines with type File then we convert
3777 * all of the individual patterns to type Lit, because each pattern can
3778 * be of any category. Lit patterns are better tested, anyway.
3780 void
3781 convert_pinerc_patterns(long int use_flags)
3783 long old_rflags;
3784 long rflags;
3785 PAT_S *pat;
3786 PAT_STATE pstate;
3787 ACTION_S *act;
3789 old_rflags = (ROLE_OLD_PAT | use_flags);
3791 rflags = 0L;
3792 if(any_patterns(old_rflags, &pstate)){
3793 dprint((2, "converting old patterns to new (%s)\n", (use_flags == PAT_USE_MAIN) ? "Main" : "Post"));
3794 for(pat = first_pattern(&pstate);
3795 pat;
3796 pat = next_pattern(&pstate)){
3797 if((act = pat->action) != NULL){
3798 if(act->is_a_role &&
3799 add_to_pattern(pat, ROLE_DO_ROLES | use_flags))
3800 rflags |= ROLE_DO_ROLES;
3801 if(act->is_a_incol &&
3802 add_to_pattern(pat, ROLE_DO_INCOLS | use_flags))
3803 rflags |= ROLE_DO_INCOLS;
3804 if(act->is_a_score &&
3805 add_to_pattern(pat, ROLE_DO_SCORES | use_flags))
3806 rflags |= ROLE_DO_SCORES;
3807 if(act->is_a_filter &&
3808 add_to_pattern(pat, ROLE_DO_FILTER | use_flags))
3809 rflags |= ROLE_DO_FILTER;
3813 if(rflags)
3814 if(write_patterns(rflags | use_flags))
3815 dprint((1,
3816 "Trouble converting patterns to new variable\n"));
3822 * If the original variable had patlines with type File then we convert
3823 * all of the individual patterns to type Lit, because each pattern can
3824 * be of any category. Lit patterns are better tested, anyway.
3826 void
3827 convert_pinerc_filts_patterns(long int use_flags)
3829 long old_rflags;
3830 long rflags;
3831 PAT_S *pat;
3832 PAT_STATE pstate;
3833 ACTION_S *act;
3835 old_rflags = (ROLE_OLD_FILT | use_flags);
3837 rflags = 0L;
3838 if(any_patterns(old_rflags, &pstate)){
3839 dprint((2, "converting old filter patterns to new (%s)\n", (use_flags == PAT_USE_MAIN) ? "Main" : "Post"));
3840 for(pat = first_pattern(&pstate);
3841 pat;
3842 pat = next_pattern(&pstate)){
3843 if((act = pat->action) != NULL){
3844 if(act->is_a_filter &&
3845 add_to_pattern(pat, ROLE_DO_FILTER | use_flags))
3846 rflags |= ROLE_DO_FILTER;
3850 if(rflags)
3851 if(write_patterns(rflags | use_flags))
3852 dprint((1,
3853 "Trouble converting filter patterns to new variable\n"));
3859 * If the original variable had patlines with type File then we convert
3860 * all of the individual patterns to type Lit, because each pattern can
3861 * be of any category. Lit patterns are better tested, anyway.
3863 void
3864 convert_pinerc_scores_patterns(long int use_flags)
3866 long old_rflags;
3867 long rflags;
3868 PAT_S *pat;
3869 PAT_STATE pstate;
3870 ACTION_S *act;
3872 old_rflags = (ROLE_OLD_SCORE | use_flags);
3874 rflags = 0L;
3875 if(any_patterns(old_rflags, &pstate)){
3876 dprint((2, "converting old scores patterns to new (%s)\n", (use_flags == PAT_USE_MAIN) ? "Main" : "Post"));
3877 for(pat = first_pattern(&pstate);
3878 pat;
3879 pat = next_pattern(&pstate)){
3880 if((act = pat->action) != NULL){
3881 if(act->is_a_score &&
3882 add_to_pattern(pat, ROLE_DO_SCORES | use_flags))
3883 rflags |= ROLE_DO_SCORES;
3887 if(rflags)
3888 if(write_patterns(rflags | use_flags))
3889 dprint((1,
3890 "Trouble converting scores patterns to new variable\n"));
3896 * set_old_growth_bits - Command used to set or unset old growth set
3897 * of features
3899 void
3900 set_old_growth_bits(struct pine *ps, int val)
3902 int i;
3904 for(i = 1; i <= F_FEATURE_LIST_COUNT; i++)
3905 if(test_old_growth_bits(ps, i))
3906 F_SET(i, ps, val);
3912 * test_old_growth_bits - Test to see if all the old growth bits are on,
3913 * *or* if a particular feature index is in the old
3914 * growth set.
3916 * WEIRD ALERT: if index == F_OLD_GROWTH bit values are tested
3917 * otherwise a bits existence in the set is tested!!!
3919 * BUG: this will break if an old growth feature number is ever >= 32.
3922 test_old_growth_bits(struct pine *ps, int index)
3925 * this list defines F_OLD_GROWTH set
3927 static unsigned long old_growth_bits = ((1 << F_ENABLE_FULL_HDR) |
3928 (1 << F_ENABLE_PIPE) |
3929 (1 << F_ENABLE_TAB_COMPLETE) |
3930 (1 << F_QUIT_WO_CONFIRM) |
3931 (1 << F_ENABLE_JUMP) |
3932 (1 << F_ENABLE_ALT_ED) |
3933 (1 << F_ENABLE_BOUNCE) |
3934 (1 << F_ENABLE_AGG_OPS) |
3935 (1 << F_ENABLE_FLAG) |
3936 (1 << F_CAN_SUSPEND));
3937 if(index >= 32)
3938 return(0);
3940 if(index == F_OLD_GROWTH){
3941 for(index = 1; index <= F_FEATURE_LIST_COUNT; index++)
3942 if(((1 << index) & old_growth_bits) && F_OFF(index, ps))
3943 return(0);
3945 return(1);
3947 else
3948 return((1 << index) & old_growth_bits);
3953 * Side effect is that the appropriate global variable is set, and the
3954 * appropriate current_val is set.
3956 void
3957 cur_rule_value(struct variable *var, int expand, int cmdline)
3959 int i;
3960 NAMEVAL_S *v;
3962 set_current_val(var, expand, cmdline);
3964 if(var == &ps_global->vars[V_SAVED_MSG_NAME_RULE]){
3965 if(ps_global->VAR_SAVED_MSG_NAME_RULE)
3966 for(i = 0; (v = save_msg_rules(i)); i++)
3967 if(!strucmp(ps_global->VAR_SAVED_MSG_NAME_RULE, S_OR_L(v))){
3968 ps_global->save_msg_rule = v->value;
3969 break;
3972 #ifndef _WINDOWS
3973 else if(var == &ps_global->vars[V_COLOR_STYLE]){
3974 if(ps_global->VAR_COLOR_STYLE)
3975 for(i = 0; (v = col_style(i)); i++)
3976 if(!strucmp(ps_global->VAR_COLOR_STYLE, S_OR_L(v))){
3977 ps_global->color_style = v->value;
3978 break;
3981 #endif
3982 else if(var == &ps_global->vars[V_INDEX_COLOR_STYLE]){
3983 if(ps_global->VAR_INDEX_COLOR_STYLE)
3984 for(i = 0; (v = index_col_style(i)); i++)
3985 if(!strucmp(ps_global->VAR_INDEX_COLOR_STYLE, S_OR_L(v))){
3986 ps_global->index_color_style = v->value;
3987 break;
3990 else if(var == &ps_global->vars[V_TITLEBAR_COLOR_STYLE]){
3991 if(ps_global->VAR_TITLEBAR_COLOR_STYLE)
3992 for(i = 0; (v = titlebar_col_style(i)); i++)
3993 if(!strucmp(ps_global->VAR_TITLEBAR_COLOR_STYLE, S_OR_L(v))){
3994 ps_global->titlebar_color_style = v->value;
3995 break;
3998 else if(var == &ps_global->vars[V_FCC_RULE]){
3999 if(ps_global->VAR_FCC_RULE)
4000 for(i = 0; (v = fcc_rules(i)); i++)
4001 if(!strucmp(ps_global->VAR_FCC_RULE, S_OR_L(v))){
4002 ps_global->fcc_rule = v->value;
4003 break;
4006 else if(var == &ps_global->vars[V_GOTO_DEFAULT_RULE]){
4007 if(ps_global->VAR_GOTO_DEFAULT_RULE)
4008 for(i = 0; (v = goto_rules(i)); i++)
4009 if(!strucmp(ps_global->VAR_GOTO_DEFAULT_RULE, S_OR_L(v))){
4010 ps_global->goto_default_rule = v->value;
4011 break;
4014 else if(var == &ps_global->vars[V_INCOMING_STARTUP]){
4015 if(ps_global->VAR_INCOMING_STARTUP)
4016 for(i = 0; (v = incoming_startup_rules(i)); i++)
4017 if(!strucmp(ps_global->VAR_INCOMING_STARTUP, S_OR_L(v))){
4018 ps_global->inc_startup_rule = v->value;
4019 break;
4022 else if(var == &ps_global->vars[V_PRUNING_RULE]){
4023 if(ps_global->VAR_PRUNING_RULE)
4024 for(i = 0; (v = pruning_rules(i)); i++)
4025 if(!strucmp(ps_global->VAR_PRUNING_RULE, S_OR_L(v))){
4026 ps_global->pruning_rule = v->value;
4027 break;
4030 else if(var == &ps_global->vars[V_REOPEN_RULE]){
4031 if(ps_global->VAR_REOPEN_RULE)
4032 for(i = 0; (v = reopen_rules(i)); i++)
4033 if(!strucmp(ps_global->VAR_REOPEN_RULE, S_OR_L(v))){
4034 ps_global->reopen_rule = v->value;
4035 break;
4038 else if(var == &ps_global->vars[V_FLD_SORT_RULE]){
4039 if(ps_global->VAR_FLD_SORT_RULE)
4040 for(i = 0; (v = fld_sort_rules(i)); i++)
4041 if(!strucmp(ps_global->VAR_FLD_SORT_RULE, S_OR_L(v))){
4042 ps_global->fld_sort_rule = v->value;
4043 break;
4046 else if(var == &ps_global->vars[V_AB_SORT_RULE]){
4047 if(ps_global->VAR_AB_SORT_RULE)
4048 for(i = 0; (v = ab_sort_rules(i)); i++)
4049 if(!strucmp(ps_global->VAR_AB_SORT_RULE, S_OR_L(v))){
4050 ps_global->ab_sort_rule = v->value;
4051 break;
4054 else if(var == &ps_global->vars[V_THREAD_DISP_STYLE]){
4055 if(ps_global->VAR_THREAD_DISP_STYLE)
4056 for(i = 0; (v = thread_disp_styles(i)); i++)
4057 if(!strucmp(ps_global->VAR_THREAD_DISP_STYLE, S_OR_L(v))){
4058 ps_global->thread_disp_style = v->value;
4059 break;
4062 else if(var == &ps_global->vars[V_THREAD_INDEX_STYLE]){
4063 if(ps_global->VAR_THREAD_INDEX_STYLE)
4064 for(i = 0; (v = thread_index_styles(i)); i++)
4065 if(!strucmp(ps_global->VAR_THREAD_INDEX_STYLE, S_OR_L(v))){
4066 ps_global->thread_index_style = v->value;
4067 break;
4074 * Standard way to get at save message rules...
4076 NAMEVAL_S *
4077 save_msg_rules(int index)
4079 static NAMEVAL_S save_rules[] = {
4080 {"by-from", NULL, SAV_RULE_FROM},
4081 {"by-nick-of-from", NULL, SAV_RULE_NICK_FROM_DEF},
4082 {"by-nick-of-from-then-from", NULL, SAV_RULE_NICK_FROM},
4083 {"by-fcc-of-from", NULL, SAV_RULE_FCC_FROM_DEF},
4084 {"by-fcc-of-from-then-from", NULL, SAV_RULE_FCC_FROM},
4085 {"by-realname-of-from", NULL, SAV_RULE_RN_FROM_DEF},
4086 {"by-realname-of-from-then-from", NULL, SAV_RULE_RN_FROM},
4087 {"by-sender", NULL, SAV_RULE_SENDER},
4088 {"by-nick-of-sender", NULL, SAV_RULE_NICK_SENDER_DEF},
4089 {"by-nick-of-sender-then-sender", NULL, SAV_RULE_NICK_SENDER},
4090 {"by-fcc-of-sender", NULL, SAV_RULE_FCC_SENDER_DEF},
4091 {"by-fcc-of-sender-then-sender", NULL, SAV_RULE_FCC_SENDER},
4092 {"by-realname-of-sender", NULL, SAV_RULE_RN_SENDER_DEF},
4093 {"by-realname-of-sender-then-sender", NULL, SAV_RULE_RN_SENDER},
4094 {"by-recipient", NULL, SAV_RULE_RECIP},
4095 {"by-nick-of-recip", NULL, SAV_RULE_NICK_RECIP_DEF},
4096 {"by-nick-of-recip-then-recip", NULL, SAV_RULE_NICK_RECIP},
4097 {"by-fcc-of-recip", NULL, SAV_RULE_FCC_RECIP_DEF},
4098 {"by-fcc-of-recip-then-recip", NULL, SAV_RULE_FCC_RECIP},
4099 {"by-realname-of-recip", NULL, SAV_RULE_RN_RECIP_DEF},
4100 {"by-realname-of-recip-then-recip", NULL, SAV_RULE_RN_RECIP},
4101 {"by-replyto", NULL, SAV_RULE_REPLYTO},
4102 {"by-nick-of-replyto", NULL, SAV_RULE_NICK_REPLYTO_DEF},
4103 {"by-nick-of-replyto-then-replyto", NULL, SAV_RULE_NICK_REPLYTO},
4104 {"by-fcc-of-replyto", NULL, SAV_RULE_FCC_REPLYTO_DEF},
4105 {"by-fcc-of-replyto-then-replyto", NULL, SAV_RULE_FCC_REPLYTO},
4106 {"by-realname-of-replyto", NULL, SAV_RULE_RN_REPLYTO_DEF},
4107 {"by-realname-of-replyto-then-replyto", NULL, SAV_RULE_RN_REPLYTO},
4108 {"last-folder-used", NULL, SAV_RULE_LAST},
4109 {"default-folder", NULL, SAV_RULE_DEFLT}
4112 return((index >= 0 && index < (sizeof(save_rules)/sizeof(save_rules[0])))
4113 ? &save_rules[index] : NULL);
4118 * Standard way to get at fcc rules...
4120 NAMEVAL_S *
4121 fcc_rules(int index)
4123 static NAMEVAL_S f_rules[] = {
4124 {"default-fcc", NULL, FCC_RULE_DEFLT},
4125 {"last-fcc-used", NULL, FCC_RULE_LAST},
4126 {"by-recipient", NULL, FCC_RULE_RECIP},
4127 {"by-nickname", NULL, FCC_RULE_NICK},
4128 {"by-nick-then-recip", NULL, FCC_RULE_NICK_RECIP},
4129 {"current-folder", NULL, FCC_RULE_CURRENT}
4132 return((index >= 0 && index < (sizeof(f_rules)/sizeof(f_rules[0])))
4133 ? &f_rules[index] : NULL);
4138 * Standard way to get at addrbook sort rules...
4140 NAMEVAL_S *
4141 ab_sort_rules(int index)
4143 static NAMEVAL_S ab_rules[] = {
4144 {"fullname-with-lists-last", NULL, AB_SORT_RULE_FULL_LISTS},
4145 {"fullname", NULL, AB_SORT_RULE_FULL},
4146 {"nickname-with-lists-last", NULL, AB_SORT_RULE_NICK_LISTS},
4147 {"nickname", NULL, AB_SORT_RULE_NICK},
4148 {"dont-sort", NULL, AB_SORT_RULE_NONE}
4151 return((index >= 0 && index < (sizeof(ab_rules)/sizeof(ab_rules[0])))
4152 ? &ab_rules[index] : NULL);
4157 * Standard way to get at color styles.
4159 NAMEVAL_S *
4160 col_style(int index)
4162 static NAMEVAL_S col_styles[] = {
4163 {"no-color", NULL, COL_NONE},
4164 {"use-termdef", NULL, COL_TERMDEF},
4165 {"force-ansi-8color", NULL, COL_ANSI8},
4166 {"force-ansi-16color", NULL, COL_ANSI16},
4167 {"force-xterm-256color", NULL, COL_ANSI256}
4170 return((index >= 0 && index < (sizeof(col_styles)/sizeof(col_styles[0])))
4171 ? &col_styles[index] : NULL);
4176 * Standard way to get at index color styles.
4178 NAMEVAL_S *
4179 index_col_style(int index)
4181 static NAMEVAL_S ind_col_styles[] = {
4182 {"flip-colors", NULL, IND_COL_FLIP},
4183 {"reverse", NULL, IND_COL_REV},
4184 {"reverse-fg", NULL, IND_COL_FG},
4185 {"reverse-fg-no-ambiguity", NULL, IND_COL_FG_NOAMBIG},
4186 {"reverse-bg", NULL, IND_COL_BG},
4187 {"reverse-bg-no-ambiguity", NULL, IND_COL_BG_NOAMBIG}
4190 return((index >= 0 && index < (sizeof(ind_col_styles)/sizeof(ind_col_styles[0]))) ? &ind_col_styles[index] : NULL);
4195 * Standard way to get at titlebar color styles.
4197 NAMEVAL_S *
4198 titlebar_col_style(int index)
4200 static NAMEVAL_S tbar_col_styles[] = {
4201 {"default", NULL, TBAR_COLOR_DEFAULT},
4202 {"indexline", NULL, TBAR_COLOR_INDEXLINE},
4203 {"reverse-indexline", NULL, TBAR_COLOR_REV_INDEXLINE}
4206 return((index >= 0 && index < (sizeof(tbar_col_styles)/sizeof(tbar_col_styles[0]))) ? &tbar_col_styles[index] : NULL);
4211 * Standard way to get at folder sort rules...
4213 NAMEVAL_S *
4214 fld_sort_rules(int index)
4216 static NAMEVAL_S fdl_rules[] = {
4217 {"alphabetical", NULL, FLD_SORT_ALPHA},
4218 {"alpha-with-dirs-last", NULL, FLD_SORT_ALPHA_DIR_LAST},
4219 {"alpha-with-dirs-first", NULL, FLD_SORT_ALPHA_DIR_FIRST}
4222 return((index >= 0 && index < (sizeof(fdl_rules)/sizeof(fdl_rules[0])))
4223 ? &fdl_rules[index] : NULL);
4228 * Standard way to get at incoming startup rules...
4230 NAMEVAL_S *
4231 incoming_startup_rules(int index)
4233 static NAMEVAL_S is_rules[] = {
4234 {"first-unseen", NULL, IS_FIRST_UNSEEN},
4235 {"first-recent", NULL, IS_FIRST_RECENT},
4236 {"first-important", NULL, IS_FIRST_IMPORTANT},
4237 {"first-important-or-unseen", NULL, IS_FIRST_IMPORTANT_OR_UNSEEN},
4238 {"first-important-or-recent", NULL, IS_FIRST_IMPORTANT_OR_RECENT},
4239 {"first", NULL, IS_FIRST},
4240 {"last", NULL, IS_LAST}
4243 return((index >= 0 && index < (sizeof(is_rules)/sizeof(is_rules[0])))
4244 ? &is_rules[index] : NULL);
4248 NAMEVAL_S *
4249 startup_rules(int index)
4251 static NAMEVAL_S is2_rules[] = {
4252 {"first-unseen", NULL, IS_FIRST_UNSEEN},
4253 {"first-recent", NULL, IS_FIRST_RECENT},
4254 {"first-important", NULL, IS_FIRST_IMPORTANT},
4255 {"first-important-or-unseen", NULL, IS_FIRST_IMPORTANT_OR_UNSEEN},
4256 {"first-important-or-recent", NULL, IS_FIRST_IMPORTANT_OR_RECENT},
4257 {"first", NULL, IS_FIRST},
4258 {"last", NULL, IS_LAST},
4259 {"default", NULL, IS_NOTSET}
4262 return((index >= 0 && index < (sizeof(is2_rules)/sizeof(is2_rules[0])))
4263 ? &is2_rules[index] : NULL);
4268 * Standard way to get at pruning-rule values.
4270 NAMEVAL_S *
4271 pruning_rules(int index)
4273 static NAMEVAL_S pr_rules[] = {
4274 {"ask about rename, ask about deleting","ask-ask", PRUNE_ASK_AND_ASK},
4275 {"ask about rename, don't delete", "ask-no", PRUNE_ASK_AND_NO},
4276 {"always rename, ask about deleting", "yes-ask", PRUNE_YES_AND_ASK},
4277 {"always rename, don't delete", "yes-no", PRUNE_YES_AND_NO},
4278 {"don't rename, ask about deleting", "no-ask", PRUNE_NO_AND_ASK},
4279 {"don't rename, don't delete", "no-no", PRUNE_NO_AND_NO}
4282 return((index >= 0 && index < (sizeof(pr_rules)/sizeof(pr_rules[0])))
4283 ? &pr_rules[index] : NULL);
4288 * Standard way to get at reopen-rule values.
4290 NAMEVAL_S *
4291 reopen_rules(int index)
4293 static NAMEVAL_S ro_rules[] = {
4294 /* TRANSLATORS: short description of a feature option */
4295 {"Always reopen", "yes-yes",
4296 REOPEN_YES_YES},
4297 /* TRANSLATORS: short description of a feature option, default in brackets */
4298 {"Yes for POP/NNTP, Ask about other remote [Yes]", "yes-ask-y",
4299 REOPEN_YES_ASK_Y},
4300 /* TRANSLATORS: short description of a feature option, default in brackets */
4301 {"Yes for POP/NNTP, Ask about other remote [No]", "yes-ask-n",
4302 REOPEN_YES_ASK_N},
4303 /* TRANSLATORS: short description of a feature option */
4304 {"Yes for POP/NNTP, No for other remote", "yes-no",
4305 REOPEN_YES_NO},
4306 /* TRANSLATORS: short description of a feature option, default in brackets */
4307 {"Always ask [Yes]", "ask-ask-y",
4308 REOPEN_ASK_ASK_Y},
4309 /* TRANSLATORS: short description of a feature option, default in brackets */
4310 {"Always ask [No]", "ask-ask-n",
4311 REOPEN_ASK_ASK_N},
4312 /* TRANSLATORS: short description of a feature option, default in brackets */
4313 {"Ask about POP/NNTP [Yes], No for other remote", "ask-no-y",
4314 REOPEN_ASK_NO_Y},
4315 /* TRANSLATORS: short description of a feature option, default in brackets */
4316 {"Ask about POP/NNTP [No], No for other remote", "ask-no-n",
4317 REOPEN_ASK_NO_N},
4318 /* TRANSLATORS: short description of a feature option */
4319 {"Never reopen", "no-no",
4320 REOPEN_NO_NO},
4323 return((index >= 0 && index < (sizeof(ro_rules)/sizeof(ro_rules[0])))
4324 ? &ro_rules[index] : NULL);
4329 * Standard way to get at thread_disp_style values.
4331 NAMEVAL_S *
4332 thread_disp_styles(int index)
4334 static NAMEVAL_S td_styles[] = {
4335 {"none", "none", THREAD_NONE},
4336 {"show-thread-structure", "struct", THREAD_STRUCT},
4337 {"mutt-like", "mutt", THREAD_MUTTLIKE},
4338 {"indent-subject-1", "subj1", THREAD_INDENT_SUBJ1},
4339 {"indent-subject-2", "subj2", THREAD_INDENT_SUBJ2},
4340 {"indent-from-1", "from1", THREAD_INDENT_FROM1},
4341 {"indent-from-2", "from2", THREAD_INDENT_FROM2},
4342 {"show-structure-in-from", "struct-from", THREAD_STRUCT_FROM}
4345 return((index >= 0 && index < (sizeof(td_styles)/sizeof(td_styles[0])))
4346 ? &td_styles[index] : NULL);
4351 * Standard way to get at thread_index_style values.
4353 NAMEVAL_S *
4354 thread_index_styles(int index)
4356 static NAMEVAL_S ti_styles[] = {
4357 {"regular-index-with-expanded-threads", "exp", THRDINDX_EXP},
4358 {"regular-index-with-collapsed-threads","coll", THRDINDX_COLL},
4359 {"separate-index-screen-always", "sep", THRDINDX_SEP},
4360 {"separate-index-screen-except-for-single-messages","sep-auto",
4361 THRDINDX_SEP_AUTO}
4364 return((index >= 0 && index < (sizeof(ti_styles)/sizeof(ti_styles[0])))
4365 ? &ti_styles[index] : NULL);
4370 * Standard way to get at goto default rules...
4372 NAMEVAL_S *
4373 goto_rules(int index)
4375 static NAMEVAL_S g_rules[] = {
4376 {"folder-in-first-collection", NULL, GOTO_FIRST_CLCTN},
4377 {"inbox-or-folder-in-first-collection", NULL, GOTO_INBOX_FIRST_CLCTN},
4378 {"inbox-or-folder-in-recent-collection", NULL, GOTO_INBOX_RECENT_CLCTN},
4379 {"first-collection-with-inbox-default", NULL, GOTO_FIRST_CLCTN_DEF_INBOX},
4380 {"most-recent-folder", NULL, GOTO_LAST_FLDR}
4383 return((index >= 0 && index < (sizeof(g_rules)/sizeof(g_rules[0])))
4384 ? &g_rules[index] : NULL);
4388 NAMEVAL_S *
4389 pat_fldr_types(int index)
4391 static NAMEVAL_S pat_fldr_list[] = {
4392 {"Any", "ANY", FLDR_ANY},
4393 {"News", "NEWS", FLDR_NEWS},
4394 {"Email", "EMAIL", FLDR_EMAIL},
4395 {"Specific (Enter Incoming Nicknames or use ^T)", "SPEC", FLDR_SPECIFIC}
4398 return((index >= 0 &&
4399 index < (sizeof(pat_fldr_list)/sizeof(pat_fldr_list[0])))
4400 ? &pat_fldr_list[index] : NULL);
4404 NAMEVAL_S *
4405 inabook_fldr_types(int indexarg)
4407 static NAMEVAL_S inabook_fldr_list[] = {
4408 {"Don't care, always matches", "E", IAB_EITHER},
4409 {"Yes, in any address book", "YES", IAB_YES},
4410 {"No, not in any address book", "NO", IAB_NO},
4411 {"Yes, in specific address books", "SYES", IAB_SPEC_YES},
4412 {"No, not in any of specific address books", "SNO", IAB_SPEC_NO}
4415 int index = indexarg & IAB_TYPE_MASK;
4417 return((index >= 0 &&
4418 index < (sizeof(inabook_fldr_list)/sizeof(inabook_fldr_list[0])))
4419 ? &inabook_fldr_list[index] : NULL);
4423 NAMEVAL_S *
4424 filter_types(int index)
4426 static NAMEVAL_S filter_type_list[] = {
4427 {"Just Set Message Status", "NONE", FILTER_STATE},
4428 {"Delete", "DEL", FILTER_KILL},
4429 {"Move (Enter folder name(s) in primary collection, or use ^T)",
4430 "FLDR", FILTER_FOLDER}
4433 return((index >= 0 &&
4434 index < (sizeof(filter_type_list)/sizeof(filter_type_list[0])))
4435 ? &filter_type_list[index] : NULL);
4439 NAMEVAL_S *
4440 role_repl_types(int index)
4442 static NAMEVAL_S role_repl_list[] = {
4443 {"Never", "NO", ROLE_REPL_NO},
4444 {"With confirmation", "YES", ROLE_REPL_YES},
4445 {"Without confirmation", "NC", ROLE_REPL_NOCONF}
4448 return((index >= 0 &&
4449 index < (sizeof(role_repl_list)/sizeof(role_repl_list[0])))
4450 ? &role_repl_list[index] : NULL);
4454 NAMEVAL_S *
4455 role_forw_types(int index)
4457 static NAMEVAL_S role_forw_list[] = {
4458 {"Never", "NO", ROLE_FORW_NO},
4459 {"With confirmation", "YES", ROLE_FORW_YES},
4460 {"Without confirmation", "NC", ROLE_FORW_NOCONF}
4463 return((index >= 0 &&
4464 index < (sizeof(role_forw_list)/sizeof(role_forw_list[0])))
4465 ? &role_forw_list[index] : NULL);
4469 NAMEVAL_S *
4470 role_comp_types(int index)
4472 static NAMEVAL_S role_comp_list[] = {
4473 {"Never", "NO", ROLE_COMP_NO},
4474 {"With confirmation", "YES", ROLE_COMP_YES},
4475 {"Without confirmation", "NC", ROLE_COMP_NOCONF}
4478 return((index >= 0 &&
4479 index < (sizeof(role_comp_list)/sizeof(role_comp_list[0])))
4480 ? &role_comp_list[index] : NULL);
4484 NAMEVAL_S *
4485 role_status_types(int index)
4487 static NAMEVAL_S role_status_list[] = {
4488 {"Don't care, always matches", "E", PAT_STAT_EITHER},
4489 {"Yes", "YES", PAT_STAT_YES},
4490 {"No", "NO", PAT_STAT_NO}
4493 return((index >= 0 &&
4494 index < (sizeof(role_status_list)/sizeof(role_status_list[0])))
4495 ? &role_status_list[index] : NULL);
4499 NAMEVAL_S *
4500 msg_state_types(int index)
4502 static NAMEVAL_S msg_state_list[] = {
4503 {"Don't change it", "LV", ACT_STAT_LEAVE},
4504 {"Set this state", "SET", ACT_STAT_SET},
4505 {"Clear this state", "CLR", ACT_STAT_CLEAR}
4508 return((index >= 0 &&
4509 index < (sizeof(msg_state_list)/sizeof(msg_state_list[0])))
4510 ? &msg_state_list[index] : NULL);
4514 #ifdef ENABLE_LDAP
4515 NAMEVAL_S *
4516 ldap_search_rules(int index)
4518 static NAMEVAL_S ldap_search_list[] = {
4519 {"contains", NULL, LDAP_SRCH_CONTAINS},
4520 {"equals", NULL, LDAP_SRCH_EQUALS},
4521 {"begins-with", NULL, LDAP_SRCH_BEGINS},
4522 {"ends-with", NULL, LDAP_SRCH_ENDS}
4525 return((index >= 0 &&
4526 index < (sizeof(ldap_search_list)/sizeof(ldap_search_list[0])))
4527 ? &ldap_search_list[index] : NULL);
4531 NAMEVAL_S *
4532 ldap_search_types(int index)
4534 static NAMEVAL_S ldap_types_list[] = {
4535 {"name", NULL, LDAP_TYPE_CN},
4536 {"surname", NULL, LDAP_TYPE_SUR},
4537 {"givenname", NULL, LDAP_TYPE_GIVEN},
4538 {"email", NULL, LDAP_TYPE_EMAIL},
4539 {"name-or-email", NULL, LDAP_TYPE_CN_EMAIL},
4540 {"surname-or-givenname", NULL, LDAP_TYPE_SUR_GIVEN},
4541 {"sur-or-given-or-name-or-email", NULL, LDAP_TYPE_SEVERAL}
4544 return((index >= 0 &&
4545 index < (sizeof(ldap_types_list)/sizeof(ldap_types_list[0])))
4546 ? &ldap_types_list[index] : NULL);
4550 NAMEVAL_S *
4551 ldap_search_scope(int index)
4553 static NAMEVAL_S ldap_scope_list[] = {
4554 {"base", NULL, LDAP_SCOPE_BASE},
4555 {"onelevel", NULL, LDAP_SCOPE_ONELEVEL},
4556 {"subtree", NULL, LDAP_SCOPE_SUBTREE}
4559 return((index >= 0 &&
4560 index < (sizeof(ldap_scope_list)/sizeof(ldap_scope_list[0])))
4561 ? &ldap_scope_list[index] : NULL);
4563 #endif
4567 * Choose from the global default, command line args, pinerc values to set
4568 * the actual value of the variable that we will use. Start at the top
4569 * and work down from higher to lower precedence.
4570 * For lists, we may inherit values from lower precedence
4571 * versions if that's the way the user specifies it.
4572 * The user can put INHERIT_DEFAULT as the first entry in a list and that
4573 * means it will inherit the current values, for example the values
4574 * from the global_val, or the value from the main_user_val could be
4575 * inherited in the post_user_val.
4577 void
4578 set_current_val(struct variable *var, int expand, int cmdline)
4580 int is_set[5], is_inherit[5];
4581 int i, j, k, cnt, start;
4582 char **tmp, **t, **list[5];
4583 char *p;
4585 dprint((9,
4586 "set_current_val(var=%s%s, expand=%d, cmdline=%d)\n",
4587 (var && var->name) ? var->name : "?",
4588 (var && var->is_list) ? " (list)" : "",
4589 expand, cmdline));
4591 if(!var)
4592 return;
4594 if(var->is_list){ /* variable is a list */
4596 for(j = 0; j < 5; j++){
4597 t = j==0 ? var->global_val.l :
4598 j==1 ? var->main_user_val.l :
4599 j==2 ? var->post_user_val.l :
4600 j==3 ? ((cmdline) ? var->cmdline_val.l : NULL) :
4601 var->fixed_val.l;
4603 is_set[j] = is_inherit[j] = 0;
4604 list[j] = NULL;
4606 if(t){
4607 if(!expand){
4608 is_set[j]++;
4609 list[j] = t;
4611 else{
4612 for(i = 0; t[i]; i++){
4613 if(expand_variables(tmp_20k_buf, SIZEOF_20KBUF, t[i],
4614 0)){
4615 /* successful expand */
4616 is_set[j]++;
4617 list[j] = t;
4618 break;
4623 if(list[j] && list[j][0] && !strcmp(list[j][0],INHERIT))
4624 is_inherit[j]++;
4628 cnt = 0;
4629 start = 0;
4630 /* count how many items in current_val list */
4631 /* Admin wants default, which is global_val. */
4632 if(var->is_fixed && var->fixed_val.l == NULL){
4633 cnt = 0;
4634 if(is_set[0]){
4635 for(; list[0][cnt]; cnt++)
4639 else{
4640 for(j = 0; j < 5; j++){
4641 if(is_set[j]){
4642 if(!is_inherit[j]){
4643 cnt = 0; /* reset */
4644 start = j;
4647 for(i = is_inherit[j] ? 1 : 0; list[j][i]; i++)
4648 cnt++;
4653 free_list_array(&var->current_val.l); /* clean up any old values */
4655 /* check to see if anything is set */
4656 if(is_set[0] + is_set[1] + is_set[2] + is_set[3] + is_set[4] > 0){
4657 var->current_val.l = (char **)fs_get((cnt+1)*sizeof(char *));
4658 tmp = var->current_val.l;
4659 if(var->is_fixed && var->fixed_val.l == NULL){
4660 if(is_set[0]){
4661 for(i = 0; list[0][i]; i++){
4662 if(!expand)
4663 *tmp++ = cpystr(list[0][i]);
4664 else if(expand_variables(tmp_20k_buf, SIZEOF_20KBUF,
4665 list[0][i], 0))
4666 *tmp++ = cpystr(tmp_20k_buf);
4670 else{
4671 for(j = start; j < 5; j++){
4672 if(is_set[j]){
4673 for(i = is_inherit[j] ? 1 : 0; list[j][i]; i++){
4674 if(!expand)
4675 *tmp++ = cpystr(list[j][i]);
4676 else if(expand_variables(tmp_20k_buf,SIZEOF_20KBUF,
4677 list[j][i], 0))
4678 *tmp++ = cpystr(tmp_20k_buf);
4684 *tmp = NULL;
4686 else
4687 var->current_val.l = NULL;
4689 else{ /* variable is not a list */
4690 char *strvar = NULL;
4692 for(j = 0; j < 5; j++){
4694 p = j==0 ? var->fixed_val.p :
4695 j==1 ? ((cmdline) ? var->cmdline_val.p : NULL) :
4696 j==2 ? var->post_user_val.p :
4697 j==3 ? var->main_user_val.p :
4698 var->global_val.p;
4700 is_set[j] = 0;
4702 if(p){
4703 if(!expand){
4704 is_set[j]++;
4705 if(!strvar)
4706 strvar = p;
4708 else if(expand_variables(tmp_20k_buf, SIZEOF_20KBUF, p,
4709 (var == &ps_global->vars[V_MAILCAP_PATH] ||
4710 var == &ps_global->vars[V_MIMETYPE_PATH]))){
4711 is_set[j]++;
4712 if(!strvar)
4713 strvar = p;
4718 /* Admin wants default, which is global_val. */
4719 if(var->is_fixed && var->fixed_val.p == NULL)
4720 strvar = var->global_val.p;
4722 if(var->current_val.p) /* free previous value */
4723 fs_give((void **)&var->current_val.p);
4725 if(strvar){
4726 if(!expand)
4727 var->current_val.p = cpystr(strvar);
4728 else{
4729 expand_variables(tmp_20k_buf, SIZEOF_20KBUF, strvar,
4730 (var == &ps_global->vars[V_MAILCAP_PATH] ||
4731 var == &ps_global->vars[V_MIMETYPE_PATH]));
4732 var->current_val.p = cpystr(tmp_20k_buf);
4735 else
4736 var->current_val.p = NULL;
4739 if(var->is_fixed && !is_inherit[4]){
4740 char **flist;
4741 int fixed_len, user_len;
4744 * sys mgr fixed this variable and user is trying to change it
4746 for(k = 1; !(ps_global->give_fixed_warning &&
4747 ps_global->fix_fixed_warning) && k <= 3; k++){
4748 if(is_set[k]){
4749 if(var->is_list){
4750 t = k==1 ? ((cmdline) ? var->cmdline_val.l : NULL) :
4751 k==2 ? var->post_user_val.l :
4752 var->main_user_val.l;
4754 /* If same length and same contents, don't warn. */
4755 for(flist=var->fixed_val.l; flist && *flist; flist++)
4756 ;/* just counting */
4758 fixed_len = var->fixed_val.l ? (flist - var->fixed_val.l)
4759 : 0;
4760 for(flist=t; flist && *flist; flist++)
4761 ;/* just counting */
4763 user_len = t ? (flist - t) : 0;
4764 if(user_len == fixed_len){
4765 for(i=0; i < user_len; i++){
4766 for(j=0; j < user_len; j++)
4767 if(!strucmp(t[i], var->fixed_val.l[j]))
4768 break;
4770 if(j == user_len){
4771 ps_global->give_fixed_warning = 1;
4772 if(k != 1)
4773 ps_global->fix_fixed_warning = 1;
4775 break;
4779 else{
4780 ps_global->give_fixed_warning = 1;
4781 if(k != 1)
4782 ps_global->fix_fixed_warning = 1;
4785 else{
4786 p = k==1 ? ((cmdline) ? var->cmdline_val.p : NULL) :
4787 k==2 ? var->post_user_val.p :
4788 var->main_user_val.p;
4790 if((var->fixed_val.p && !p) ||
4791 (!var->fixed_val.p && p) ||
4792 (var->fixed_val.p && p && strucmp(var->fixed_val.p, p))){
4793 ps_global->give_fixed_warning = 1;
4794 if(k != 1)
4795 ps_global->fix_fixed_warning = 1;
4804 void
4805 set_news_spec_current_val(int expand, int cmdline)
4807 struct variable *newsvar = &ps_global->vars[V_NEWS_SPEC];
4808 struct variable *fvar = &ps_global->vars[V_FOLDER_SPEC];
4810 /* check to see if it has a value */
4811 set_current_val(newsvar, expand, cmdline);
4814 * If no value, we might want to fake a value. We'll do that if
4815 * there is no news collection already defined in FOLDER_SPEC and if
4816 * there is also an NNTP_SERVER defined.
4818 if(!newsvar->current_val.l && ps_global->VAR_NNTP_SERVER &&
4819 ps_global->VAR_NNTP_SERVER[0] && ps_global->VAR_NNTP_SERVER[0][0] &&
4820 !news_in_folders(fvar)){
4821 char buf[MAXPATH];
4823 newsvar->global_val.l = (char **)fs_get(2 * sizeof(char *));
4824 snprintf(buf, sizeof(buf), "{%.*s/nntp}#news.[]", MAXPATH-20,
4825 ps_global->VAR_NNTP_SERVER[0]); /* MAXPATH = sizeof(buf) */
4826 newsvar->global_val.l[0] = cpystr(buf);
4827 newsvar->global_val.l[1] = NULL;
4828 set_current_val(newsvar, expand, cmdline);
4830 * But we're going to get rid of the fake global_val in case
4831 * things change.
4833 free_list_array(&newsvar->global_val.l);
4839 * Feature-list has to be handled separately from the other variables
4840 * because it is additive. The other variables choose one of command line,
4841 * or pine.conf, or pinerc. Feature list adds them. This could easily be
4842 * converted to a general purpose routine if we add more additive variables.
4844 * This works by replacing earlier values with later ones. That is, command
4845 * line settings have higher precedence than global settings and that is
4846 * accomplished by putting the command line features after the global
4847 * features in the list. When they are processed, the last one wins.
4849 * Feature-list also has a backwards compatibility hack.
4851 void
4852 set_feature_list_current_val(struct variable *var)
4854 char **list;
4855 char **list_fixed;
4856 char no_allow[50];
4857 int i, j, k, m,
4858 elems = 0;
4860 /* count the lists so we can allocate */
4861 for(m = 0; m < 6; m++){
4862 list = m==0 ? var->global_val.l :
4863 m==1 ? var->main_user_val.l :
4864 m==2 ? var->post_user_val.l :
4865 m==3 ? ps_global->feat_list_back_compat :
4866 m==4 ? var->cmdline_val.l :
4867 var->fixed_val.l;
4868 if(list)
4869 for(i = 0; list[i]; i++)
4870 elems++;
4873 list_fixed = var->fixed_val.l;
4875 if(var->current_val.l)
4876 free_list_array(&var->current_val.l);
4878 var->current_val.l = (char **)fs_get((elems+1) * sizeof(char *));
4881 * We need to warn the user if the sys mgr has restricted him or her
4882 * from changing a feature that he or she is trying to change.
4884 * We're not catching the old-growth macro since we're just comparing
4885 * strings. That is, it works correctly, but the user won't be warned
4886 * if the user old-growth and the mgr says no-quit-without-confirm.
4889 j = 0;
4890 strcpy(no_allow, "no-");
4891 strncpy(no_allow+3, feature_list_name(F_ALLOW_CHANGING_FROM), sizeof(no_allow)-3-1);
4892 no_allow[sizeof(no_allow)-1] = '\0';
4894 for(m = 0; m < 6; m++){
4895 list = m==0 ? var->global_val.l :
4896 m==1 ? var->main_user_val.l :
4897 m==2 ? var->post_user_val.l :
4898 m==3 ? ps_global->feat_list_back_compat :
4899 m==4 ? var->cmdline_val.l :
4900 var->fixed_val.l;
4901 if(list)
4902 for(i = 0; list[i]; i++){
4903 var->current_val.l[j++] = cpystr(list[i]);
4905 /* this is the warning section */
4906 if(m >= 1 && m <= 4){
4907 for(k = 0; list_fixed && list_fixed[k]; k++){
4908 char *p, *q;
4909 p = list[i];
4910 q = list_fixed[k];
4911 if(!struncmp(p, "no-", 3))
4912 p += 3;
4913 if(!struncmp(q, "no-", 3))
4914 q += 3;
4915 if(!strucmp(q, p) && strucmp(list[i], list_fixed[k])){
4916 ps_global->give_fixed_warning = 1;
4917 if(m <= 2)
4918 ps_global->fix_fixed_warning = 1;
4922 else if(m == 5 && !strucmp(list[i], no_allow))
4923 ps_global->never_allow_changing_from = 1;
4927 #ifdef NEVER_ALLOW_CHANGING_FROM
4928 ps_global->never_allow_changing_from = 1;
4929 #endif
4931 var->current_val.l[j] = NULL;
4936 /*----------------------------------------------------------------------
4938 Expand Metacharacters/variables in file-names
4940 Read input line and expand shell-variables/meta-characters
4942 <input> <replaced by>
4943 $variable getenv("variable")
4944 ${variable} getenv("variable")
4945 ${variable:-defvalue} is getenv("variable") if variable is defined and
4946 is defvalue otherwise
4947 ~ getenv("HOME")
4948 \c c
4949 <others> <just copied>
4951 NOTE handling of braces in ${name} doesn't check much or do error recovery
4953 If colon_path is set, then we expand ~ not only at the start of linein,
4954 but also after each : in the path.
4956 ----*/
4957 #define is_allowed_envchar(C, S) ((S) == 0 ? !isspace((C)) && (C) != '/'\
4958 : (((C) >= 'a' && (C) <= 'z') \
4959 || ((C) >= 'A' && (C) <= 'Z') \
4960 || ((C) >= '0' && (C) <= '9')))
4962 char *
4963 expand_variables(char *lineout, size_t lineoutlen, char *linein, int colon_path)
4965 char *src = linein, *dest = lineout, *p;
4966 char *limit = lineout + lineoutlen;
4967 int envexpand = 0, sp;
4969 if(!linein)
4970 return(NULL);
4972 sp = strncmp(src,"LIT:pattern=\"/NICK=", strlen("LIT:pattern=\"/NICK=")) == 0;
4973 while(*src ){ /* something in input string */
4974 if(*src == '$' && *(src+1) == '$'){
4976 * $$ to escape chars we're interested in, else
4977 * it's up to the user of the variable to handle the
4978 * backslash...
4980 if(dest < limit)
4981 *dest++ = *++src; /* copy next as is */
4982 }else
4983 #if !(defined(DOS) || defined(OS2))
4984 if(*src == '\\' && *(src+1) == '$'){
4986 * backslash to escape chars we're interested in, else
4987 * it's up to the user of the variable to handle the
4988 * backslash...
4990 if(dest < limit)
4991 *dest++ = *++src; /* copy next as is */
4992 }else if(*src == '~' &&
4993 (src == linein || (colon_path && *(src-1) == ':'))){
4994 char buf[MAXPATH];
4995 int i;
4997 for(i = 0; i < sizeof(buf)-1 && src[i] && src[i] != '/'; i++)
4998 buf[i] = src[i];
5000 src += i; /* advance src pointer */
5001 buf[i] = '\0'; /* tie off buf string */
5002 fnexpand(buf, sizeof(buf)); /* expand the path */
5004 for(p = buf; dest < limit && (*dest = *p); p++, dest++)
5007 continue;
5008 }else
5009 #endif
5010 if(*src == '$'){ /* shell variable */
5011 char word[128+1], *colon = NULL, *rbrace = NULL;
5013 envexpand++; /* signal that we've expanded a var */
5014 src++; /* skip dollar */
5015 if(*src == '{'){ /* starts with brace? */
5016 src++;
5017 rbrace = strindex(src, '}');
5018 if(rbrace){
5019 /* look for default value */
5020 colon = strstr(src, ":-");
5021 if(colon && (rbrace < colon))
5022 colon = NULL;
5026 p = word;
5028 /* put the env variable to be looked up in word */
5029 if(rbrace){
5030 while(*src
5031 && (p-word < sizeof(word)-1)
5032 && ((colon && src < colon) || (!colon && src < rbrace))){
5033 if(isspace((unsigned char) *src)){
5035 * Illegal input. This should be an error of some
5036 * sort but instead of that we'll just backup to the
5037 * $ and treat it like it wasn't there.
5039 while(*src != '$')
5040 src--;
5042 envexpand--;
5043 goto just_copy;
5045 else
5046 *p++ = *src++;
5049 /* adjust src for next char */
5050 src = rbrace + 1;
5052 else{
5053 while(*src && is_allowed_envchar((unsigned char) *src, sp)
5054 && (p-word < sizeof(word)-1))
5055 *p++ = *src++;
5058 *p = '\0';
5060 if((p = getenv(word)) != NULL){ /* check for word in environment */
5061 while(*p && dest < limit)
5062 *dest++ = *p++;
5064 else if(colon){ /* else possible default value */
5065 p = colon + 2;
5066 while(*p && p < rbrace && dest < limit)
5067 *dest++ = *p++;
5070 continue;
5071 }else{ /* other cases: just copy */
5072 just_copy:
5073 if(dest < limit)
5074 *dest++ = *src;
5077 if(*src) /* next character (if any) */
5078 src++;
5081 if(dest < limit)
5082 *dest = '\0';
5083 else
5084 lineout[lineoutlen-1] = '\0';
5086 return((envexpand && lineout[0] == '\0') ? NULL : lineout);
5090 /*----------------------------------------------------------------------
5091 Sets login, full_username and home_dir
5093 Args: ps -- The Pine structure to put the user name, etc in
5095 Result: sets the fullname, login and home_dir field of the pine structure
5096 returns 0 on success, -1 if not.
5097 ----*/
5098 #define MAX_INIT_ERRS 10
5099 void
5100 init_error(struct pine *ps, int flags, int min_time, int max_time, char *message)
5102 int i;
5104 if(!ps->init_errs){
5105 ps->init_errs = (INIT_ERR_S *)fs_get((MAX_INIT_ERRS + 1) *
5106 sizeof(*ps->init_errs));
5107 memset(ps->init_errs, 0, (MAX_INIT_ERRS + 1) * sizeof(*ps->init_errs));
5110 for(i = 0; i < MAX_INIT_ERRS; i++)
5111 if(!(ps->init_errs)[i].message){
5112 (ps->init_errs)[i].message = cpystr(message);
5113 (ps->init_errs)[i].min_time = min_time;
5114 (ps->init_errs)[i].max_time = max_time;
5115 (ps->init_errs)[i].flags = flags;
5116 dprint((2, "%s\n", message ? message : "?"));
5117 break;
5122 /*----------------------------------------------------------------------
5123 Read and parse a pinerc file
5125 Args: Filename -- name of the .pinerc file to open and read
5126 vars -- The vars structure to store values in
5127 which_vars -- Whether the local or global values are being read
5129 Result:
5131 This may be the local file or the global file. The values found are
5132 merged with the values currently in vars. All values are strings and
5133 are malloced; and existing values will be freed before the assignment.
5134 Those that are <unset> will be left unset; their values will be NULL.
5135 ----*/
5136 void
5137 read_pinerc(PINERC_S *prc, struct variable *vars, ParsePinerc which_vars)
5139 char *filename = NULL, *file, *value = NULL, **lvalue = NULL, *line, *error;
5140 char *p, *p1, *free_file = NULL;
5141 struct variable *v;
5142 PINERC_LINE *pline = NULL;
5143 int line_count, was_quoted;
5144 int i;
5146 if(!prc)
5147 return;
5149 dprint((2, "reading_pinerc \"%s\"\n",
5150 prc->name ? prc->name : "?"));
5152 if(prc->type == Loc){
5153 filename = prc->name ? prc->name : "";
5154 file = free_file = read_file(filename, 0);
5157 * This is questionable. In case the user edits the pinerc
5158 * in Windows and adds a UTF-8 BOM, we skip it here. If the
5159 * user adds a Unicode BOM we're in trouble. We could write it
5160 * with the BOM ourselves but so far we leave it BOMless in
5161 * order that it's the same on Unix and Windows.
5163 if(BOM_UTF8(file))
5164 file += 3;
5166 else{
5167 if((file = read_remote_pinerc(prc, which_vars)) != NULL)
5168 ps_global->c_client_error[0] = '\0';
5170 free_file = file;
5173 if(file == NULL || *file == '\0'){
5174 #ifdef DEBUG
5175 if(file == NULL){
5176 dprint((2, "Open failed: %s\n", error_description(errno)));
5178 else{
5179 if(prc->type == Loc){
5180 dprint((1, "Read_pinerc: empty pinerc (new?)\n"));
5182 else{
5183 dprint((1, "Read_pinerc: new remote pinerc\n"));
5186 #endif /* DEBUG */
5188 if(which_vars == ParsePers){
5189 /* problems getting remote config */
5190 if(file == NULL && prc->type == RemImap){
5191 if(!pith_opt_remote_pinerc_failure
5192 || !(*pith_opt_remote_pinerc_failure)())
5193 exceptional_exit(_("Unable to read or write remote configuration"), -1);
5196 ps_global->first_time_user = 1;
5197 prc->outstanding_pinerc_changes = 1;
5200 return;
5202 else{
5203 if(prc->type == Loc &&
5204 (which_vars == ParseFixed || which_vars == ParseGlobal ||
5205 (can_access(filename, ACCESS_EXISTS) == 0 &&
5206 can_access(filename, EDIT_ACCESS) != 0))){
5207 prc->readonly = 1;
5208 if(prc == ps_global->prc)
5209 ps_global->readonly_pinerc = 1;
5213 * accept CRLF or LF newlines
5215 for(p = file; *p && *p != '\012'; p++)
5218 if(p > file && *p && *(p-1) == '\015') /* cvt crlf to lf */
5219 for(p1 = p - 1; (*p1 = *p) != '\0'; p++)
5220 if(!(*p == '\015' && *(p+1) == '\012'))
5221 p1++;
5224 dprint((2, "Read %d characters:\n", strlen(file)));
5226 if(which_vars == ParsePers || which_vars == ParsePersPost){
5227 /*--- Count up lines and allocate structures */
5228 for(line_count = 0, p = file; *p != '\0'; p++)
5229 if(*p == '\n')
5230 line_count++;
5232 prc->pinerc_lines = (PINERC_LINE *)
5233 fs_get((3 + line_count) * sizeof(PINERC_LINE));
5234 memset((void *)prc->pinerc_lines, 0,
5235 (3 + line_count) * sizeof(PINERC_LINE));
5236 pline = prc->pinerc_lines;
5239 for(p = file, line = file; *p != '\0';){
5240 /*----- Grab the line ----*/
5241 line = p;
5242 while(*p && *p != '\n')
5243 p++;
5244 if(*p == '\n'){
5245 *p++ = '\0';
5248 /*----- Comment Line -----*/
5249 if(*line == '#'){
5250 /* no comments in remote pinercs */
5251 if(pline && prc->type == Loc){
5252 pline->is_var = 0;
5253 pline->line = cpystr(line);
5254 pline++;
5256 continue;
5259 if(*line == '\0' || *line == '\t' || *line == ' '){
5260 p1 = line;
5261 while(*p1 == '\t' || *p1 == ' ')
5262 p1++;
5263 if(pline){
5265 * This could be a continuation line from some future
5266 * version of pine, or it could be a continuation line
5267 * from a PC-Pine variable we don't know about in unix.
5269 if(*p1 != '\0')
5270 pline->line = cpystr(line);
5271 else
5272 pline->line = cpystr("");
5273 pline->is_var = 0;
5274 pline++;
5276 continue;
5279 /*----- look up matching 'v' and leave "value" after '=' ----*/
5280 for(v = vars; *line && v->name; v++)
5281 if((i = strlen(v->name)) < strlen(line) && !struncmp(v->name,line,i)){
5282 int j;
5284 for(j = i; line[j] == ' ' || line[j] == '\t'; j++)
5287 if(line[j] == '='){ /* bingo! */
5288 for(value = &line[j+1];
5289 *value == ' ' || *value == '\t';
5290 value++)
5293 break;
5295 /* else either unrecognized var or bogus line */
5298 /*----- Didn't match any variable or bogus format -----*/
5300 * This could be a variable from some future
5301 * version of pine, or it could be a PC-Pine variable
5302 * we don't know about in unix. Either way, we want to preserve
5303 * it in the file.
5305 if(!v->name){
5306 if(pline){
5307 pline->is_var = 0;
5308 pline->line = cpystr(line);
5309 pline++;
5311 continue;
5315 * Previous versions have caused duplicate pinerc data to be
5316 * written to pinerc files. This clause erases the duplicate
5317 * information when we read it, and it will be removed from the file
5318 * if we call write_pinerc. We test to see if the same variable
5319 * appears later in the file, if so, we skip over it here.
5320 * We don't care about duplicates if this isn't a pinerc we might
5321 * write out, so include pline in the conditional.
5322 * Note that we will leave all of the duplicate comments and blank
5323 * lines in the file unless it is a remote pinerc. Luckily, the
5324 * bug that caused the duplicates only applied to remote pinercs,
5325 * so we should have that case covered.
5327 * If we find a duplicate, we point p to the start
5328 * of the next line that should be considered, and then skip back
5329 * to the top of the loop.
5331 if(pline && var_is_in_rest_of_file(v->name, p)){
5332 if(v->is_list)
5333 p = skip_over_this_var(line, p);
5335 continue;
5339 /*----- Obsolete variable, read it anyway below, might use it -----*/
5340 if(v->is_obsolete){
5341 if(pline){
5342 pline->obsolete_var = 1;
5343 pline->line = cpystr(line);
5344 pline->var = v;
5348 /*----- Variable is in the list but unused for some reason -----*/
5349 if(!v->is_used){
5350 if(pline){
5351 pline->is_var = 0;
5352 pline->line = cpystr(line);
5353 pline++;
5355 continue;
5358 /*--- Var is not user controlled, leave it alone for back compat ---*/
5359 if(!v->is_user && pline){
5360 pline->is_var = 0;
5361 pline->line = cpystr(line);
5362 pline++;
5363 continue;
5366 if(which_vars == ParseFixed)
5367 v->is_fixed = 1;
5369 /*---- variable is unset, or it's global but expands to nothing ----*/
5370 if(!*value
5371 || (which_vars == ParseGlobal
5372 && !expand_variables(tmp_20k_buf, SIZEOF_20KBUF, value,
5373 (v == &ps_global->vars[V_MAILCAP_PATH] ||
5374 v == &ps_global->vars[V_MIMETYPE_PATH])))){
5375 if(v->is_user && pline){
5376 pline->is_var = 1;
5377 pline->var = v;
5378 pline++;
5380 continue;
5383 /*--value is non-empty, store it handling quotes and trailing space--*/
5384 if(*value == '"' && !v->is_list && v->del_quotes){
5385 was_quoted = 1;
5386 value++;
5387 for(p1 = value; *p1 && *p1 != '"'; p1++);
5388 if(*p1 == '"')
5389 *p1 = '\0';
5390 else
5391 removing_trailing_white_space(value);
5392 }else
5393 was_quoted = 0;
5396 * List Entry Parsing
5398 * The idea is to parse a comma separated list of
5399 * elements, preserving quotes, and understanding
5400 * continuation lines (that is ',' == "\n ").
5401 * Quotes must be balanced within elements. Space
5402 * within elements is preserved, but leading and trailing
5403 * space is trimmed. This is a generic function, and it's
5404 * left to the the functions that use the lists to make sure
5405 * they contain valid data...
5407 if(v->is_list){
5409 was_quoted = 0;
5410 line_count = 0;
5411 p1 = value;
5412 while(1){ /* generous count of list elements */
5413 if(*p1 == '"') /* ignore ',' if quoted */
5414 was_quoted = (was_quoted) ? 0 : 1 ;
5416 if((*p1 == ',' && !was_quoted) || *p1 == '\n' || *p1 == '\0')
5417 line_count++; /* count this element */
5419 if(*p1 == '\0' || *p1 == '\n'){ /* deal with EOL */
5420 if(p1 < p || *p1 == '\n'){
5421 *p1++ = ','; /* fix null or newline */
5423 if(*p1 != '\t' && *p1 != ' '){
5424 *(p1-1) = '\0'; /* tie off list */
5425 p = p1; /* reset p */
5426 break;
5428 }else{
5429 p = p1; /* end of pinerc */
5430 break;
5432 }else
5433 p1++;
5436 error = NULL;
5437 lvalue = parse_list(value, line_count,
5438 v->del_quotes ? PL_REMSURRQUOT : PL_NONE,
5439 &error);
5440 if(error){
5441 dprint((1,
5442 "read_pinerc: ERROR: %s in %s = \"%s\"\n",
5443 error ? error : "?",
5444 v->name ? v->name : "?",
5445 value ? value : "?"));
5448 * Special case: turn "" strings into empty strings.
5449 * This allows users to turn off default lists. For example,
5450 * if smtp-server is set then a user could override smtp-server
5451 * with smtp-server="".
5453 for(i = 0; lvalue[i]; i++)
5454 if(lvalue[i][0] == '"' &&
5455 lvalue[i][1] == '"' &&
5456 lvalue[i][2] == '\0')
5457 lvalue[i][0] = '\0';
5460 if(pline){
5461 if(v->is_user && (which_vars == ParsePers || !v->is_onlymain)){
5462 if(v->is_list){
5463 char ***l;
5465 l = (which_vars == ParsePers) ? &v->main_user_val.l
5466 : &v->post_user_val.l;
5467 free_list_array(l);
5468 *l = lvalue;
5470 else{
5471 char **p;
5473 p = (which_vars == ParsePers) ? &v->main_user_val.p
5474 : &v->post_user_val.p;
5475 if(p && *p != NULL)
5476 fs_give((void **)p);
5478 *p = cpystr(value);
5481 if(pline){
5482 pline->is_var = 1;
5483 pline->var = v;
5484 pline->is_quoted = was_quoted;
5485 pline++;
5489 else if(which_vars == ParseGlobal){
5490 if(v->is_global){
5491 if(v->is_list){
5492 free_list_array(&v->global_val.l);
5493 v->global_val.l = lvalue;
5495 else{
5496 if(v->global_val.p != NULL)
5497 fs_give((void **) &(v->global_val.p));
5499 v->global_val.p = cpystr(value);
5503 else{ /* which_vars == ParseFixed */
5504 if(v->is_user || v->is_global){
5505 if(v->is_list){
5506 free_list_array(&v->fixed_val.l);
5507 v->fixed_val.l = lvalue;
5509 else{
5510 if(v->fixed_val.p != NULL)
5511 fs_give((void **) &(v->fixed_val.p));
5513 v->fixed_val.p = cpystr(value);
5518 #ifdef DEBUG
5519 if(v->is_list){
5520 char **l;
5521 l = (which_vars == ParsePers) ? v->main_user_val.l :
5522 (which_vars == ParsePersPost) ? v->post_user_val.l :
5523 (which_vars == ParseGlobal) ? v->global_val.l :
5524 v->fixed_val.l;
5525 if(l && *l && **l){
5526 dprint((5, " %20.20s : %s\n",
5527 v->name ? v->name : "?",
5528 *l ? *l : "?"));
5529 while(++l && *l && **l)
5530 dprint((5, " %20.20s : %s\n", "",
5531 *l ? *l : "?"));
5533 }else{
5534 char *p;
5535 p = (which_vars == ParsePers) ? v->main_user_val.p :
5536 (which_vars == ParsePersPost) ? v->post_user_val.p :
5537 (which_vars == ParseGlobal) ? v->global_val.p :
5538 v->fixed_val.p;
5539 if(p && *p)
5540 dprint((5, " %20.20s : %s\n",
5541 v->name ? v->name : "?",
5542 p ? p : "?"));
5544 #endif /* DEBUG */
5547 if(pline){
5548 pline->line = NULL;
5549 pline->is_var = 0;
5550 if(!prc->pinerc_written && prc->type == Loc){
5551 prc->pinerc_written = name_file_mtime(filename);
5552 dprint((5, "read_pinerc: time_pinerc_written = %ld\n",
5553 (long) prc->pinerc_written));
5557 if(free_file)
5558 fs_give((void **) &free_file);
5563 * Args varname The variable name we're looking for
5564 * begin Begin looking here
5566 * Returns 1 if variable varname appears in the rest of the file
5567 * 0 if not
5570 var_is_in_rest_of_file(char *varname, char *begin)
5572 char *p;
5574 if(!(varname && *varname && begin && *begin))
5575 return 0;
5577 p = begin;
5579 while((p = srchstr(p, varname)) != NULL){
5580 /* beginning of a line? */
5581 if(p > begin && (*(p-1) != '\n' && *(p-1) != '\r')){
5582 p++;
5583 continue;
5586 /* followed by [ SPACE ] < = > ? */
5587 p += strlen(varname);
5588 while(*p == ' ' || *p == '\t')
5589 p++;
5591 if(*p == '=')
5592 return 1;
5595 return 0;
5600 * Args begin Variable to skip starts here.
5601 * nextline This is where the next line starts. We need to know this
5602 * because the input has been mangled a little. A \0 has
5603 * replaced the \n at the end of the first line, but we can
5604 * use nextline to help us out of that quandry.
5606 * Return a pointer to the start of the first line after this variable
5607 * and all of its continuation lines.
5609 char *
5610 skip_over_this_var(char *begin, char *nextline)
5612 char *p;
5614 p = begin;
5616 while(1){
5617 if(*p == '\0' || *p == '\n'){ /* EOL */
5618 if(p < nextline || *p == '\n'){ /* there may be another line */
5619 p++;
5620 if(*p != ' ' && *p != '\t') /* no continuation line */
5621 return(p);
5623 else /* end of file */
5624 return(p);
5626 else
5627 p++;
5632 static char quotes[3] = {'"', '"', '\0'};
5633 /*----------------------------------------------------------------------
5634 Write out the .pinerc state information
5636 Args: ps -- The pine structure to take state to be written from
5637 which -- Which pinerc to write
5638 flags -- If bit WRP_NOUSER is set, then assume that there is
5639 not a user present to answer questions.
5641 This writes to a temporary file first, and then renames that to
5642 be the new .pinerc file to protect against disk error. This has the
5643 problem of possibly messing up file protections, ownership and links.
5644 ----*/
5646 write_pinerc(struct pine *ps, EditWhich which, int flags)
5648 char *p, *dir, *tmp = NULL, *pinrc;
5649 char *pval = NULL, **lval = NULL;
5650 char *linep = NULL, *lineq = NULL;
5651 int bc = 1;
5652 int buflen;
5653 PINERC_LINE *pline;
5654 struct variable *var;
5655 time_t mtime;
5656 char *filename = NULL;
5657 REMDATA_S *rd = NULL;
5658 PINERC_S *prc = NULL;
5659 STORE_S *so = NULL;
5660 #ifndef _WINDOWS
5661 struct stat sbuf;
5662 #endif
5664 #define MAXPLINESIZE 10000
5666 dprint((2,"---- write_pinerc(%s) ----\n",
5667 (which == Main) ? "Main" : "Post"));
5669 switch(which){
5670 case Main:
5671 prc = ps ? ps->prc : NULL;
5672 break;
5673 case Post:
5674 prc = ps ? ps->post_prc : NULL;
5675 break;
5676 default:
5677 break;
5680 if(!prc)
5681 return(-1);
5683 if(prc->quit_to_edit){
5684 if(!(flags & WRP_NOUSER))
5685 quit_to_edit_msg(prc);
5687 return(-1);
5690 if(prc->type != Loc && !prc->readonly){
5692 bc = 0; /* don't do backcompat conversion */
5693 rd = prc->rd;
5694 if(!rd)
5695 return(-1);
5697 rd_check_remvalid(rd, -10L);
5699 if(rd->flags & REM_OUTOFDATE){
5700 if((flags & WRP_NOUSER) || unexpected_pinerc_change()){
5701 prc->outstanding_pinerc_changes = 1;
5702 if(!(flags & WRP_NOUSER))
5703 q_status_message1(SM_ORDER | SM_DING, 3, 3,
5704 "Pinerc \"%.200s\" NOT saved",
5705 prc->name ? prc->name : "");
5706 dprint((2, "write_pinerc: remote pinerc changed\n"));
5707 return(-1);
5709 else
5710 rd->flags &= ~REM_OUTOFDATE;
5713 rd_open_remote(rd);
5715 if(rd->access == ReadWrite){
5716 int ro;
5718 if((ro=rd_remote_is_readonly(rd)) || rd->flags & REM_OUTOFDATE){
5719 if(ro == 1){
5720 if(!(flags & WRP_NOUSER))
5721 q_status_message(SM_ORDER | SM_DING, 5, 15,
5722 _("Can't access remote config, changes NOT saved!"));
5723 dprint((1,
5724 "write_pinerc: Can't write to remote pinerc %s, aborting write\n",
5725 rd->rn ? rd->rn : "?"));
5727 else if(ro == 2){
5728 if(!(rd->flags & NO_META_UPDATE)){
5729 unsigned long save_chk_nmsgs;
5731 switch(rd->type){
5732 case RemImap:
5733 save_chk_nmsgs = rd->t.i.chk_nmsgs;
5734 rd->t.i.chk_nmsgs = 0;
5735 rd_write_metadata(rd, 0);
5736 rd->t.i.chk_nmsgs = save_chk_nmsgs;
5737 break;
5739 default:
5740 q_status_message(SM_ORDER | SM_DING, 3, 5,
5741 "Write_pinerc: Type not supported");
5742 break;
5746 if(!(flags & WRP_NOUSER))
5747 q_status_message1(SM_ORDER | SM_DING, 5, 15,
5748 _("No write permission for remote config %.200s, changes NOT saved!"),
5749 rd->rn);
5751 else{
5752 if(!(flags & WRP_NOUSER))
5753 q_status_message(SM_ORDER | SM_DING, 5, 15,
5754 _("Remote config changed, aborting our change to avoid damage..."));
5755 dprint((1,
5756 "write_pinerc: remote config %s changed since we started pine, aborting write\n",
5757 prc->name ? prc->name : "?"));
5760 rd->flags &= ~DO_REMTRIM;
5761 return(-1);
5764 filename = rd->lf;
5766 else{
5767 prc->readonly = 1;
5768 if(prc == ps->prc)
5769 ps->readonly_pinerc = 1;
5772 else
5773 filename = prc->name ? prc->name : "";
5775 pinrc = prc->name ? prc->name : "";
5777 if(prc->type == Loc){
5778 mtime = name_file_mtime(filename);
5779 if(prc->pinerc_written
5780 && prc->pinerc_written != mtime
5781 && ((flags & WRP_NOUSER) || unexpected_pinerc_change())){
5782 prc->outstanding_pinerc_changes = 1;
5784 if(!(flags & WRP_NOUSER))
5785 q_status_message1(SM_ORDER | SM_DING, 3, 3,
5786 "Pinerc \"%.200s\" NOT saved", pinrc);
5788 dprint((2,"write_pinerc: mtime mismatch: \"%s\": %ld != %ld\n",
5789 filename ? filename : "?",
5790 (long) prc->pinerc_written, (long) mtime));
5791 return(-1);
5795 /* don't write if pinerc is read-only */
5796 if(prc->readonly ||
5797 (filename &&
5798 can_access(filename, ACCESS_EXISTS) == 0 &&
5799 can_access(filename, EDIT_ACCESS) != 0)){
5800 prc->readonly = 1;
5801 if(prc == ps->prc)
5802 ps->readonly_pinerc = 1;
5804 if(!(flags & WRP_NOUSER))
5805 q_status_message1(SM_ORDER | SM_DING, 0, 5,
5806 _("Can't modify configuration file \"%.200s\": ReadOnly"),
5807 pinrc);
5808 dprint((2, "write_pinerc: fail because can't access pinerc\n"));
5810 if(rd)
5811 rd->flags &= ~DO_REMTRIM;
5813 return(-1);
5816 if(rd && rd->flags & NO_FILE){
5817 so = rd->sonofile;
5818 so_truncate(rd->sonofile, 0L); /* reset storage object */
5820 else{
5821 dir = ".";
5822 if((p = last_cmpnt(filename)) != NULL){
5823 *--p = '\0';
5824 dir = filename;
5827 #if defined(DOS) || defined(OS2)
5828 if(!(isalpha((unsigned char)dir[0]) && dir[1] == ':' && dir[2] == '\0')
5829 && (can_access(dir, EDIT_ACCESS) < 0 &&
5830 our_mkdir(dir, 0700) < 0))
5832 if(!(flags & WRP_NOUSER))
5833 q_status_message2(SM_ORDER | SM_DING, 3, 5,
5834 /* TRANSLATORS: first argument is a filename, second
5835 arg is the text of the error message */
5836 _("Error creating \"%.200s\" : %.200s"), dir,
5837 error_description(errno));
5838 if(rd)
5839 rd->flags &= ~DO_REMTRIM;
5841 return(-1);
5844 tmp = temp_nam(dir, "rc");
5846 if(*dir && tmp && !in_dir(dir, tmp)){
5847 our_unlink(tmp);
5848 fs_give((void **)&tmp);
5851 if(p)
5852 *p = '\\';
5854 if(tmp == NULL)
5855 goto io_err;
5857 #else /* !DOS */
5858 tmp = temp_nam((*dir) ? dir : "/", "pinerc");
5861 * If temp_nam can't write in dir it puts the temp file in a
5862 * temp directory, which won't help us when we go to rename.
5864 if(*dir && tmp && !in_dir(dir, tmp)){
5865 our_unlink(tmp);
5866 fs_give((void **)&tmp);
5869 if(p)
5870 *p = '/';
5872 if(tmp == NULL)
5873 goto io_err;
5875 #endif /* !DOS */
5877 if((so = so_get(FileStar, tmp, WRITE_ACCESS)) == NULL)
5878 goto io_err;
5881 if(!(flags & WRP_PRESERV_WRITTEN))
5882 for(var = ps->vars; var->name != NULL; var++)
5883 var->been_written = 0;
5885 if(prc->type == Loc && ps->first_time_user &&
5886 !so_puts(so, native_nl(cf_text_comment)))
5887 goto io_err;
5889 linep = fs_get((MAXPLINESIZE+1)*sizeof(char));
5890 lineq = fs_get((MAXPLINESIZE+1)*sizeof(char));
5891 buflen = MAXPLINESIZE;
5893 /* Write out what was in the .pinerc */
5894 for(pline = prc->pinerc_lines;
5895 pline && (pline->is_var || pline->line); pline++){
5896 if(pline->is_var){
5897 var = pline->var;
5899 if(var->is_list)
5900 lval = LVAL(var, which);
5901 else
5902 pval = PVAL(var, which);
5904 /* variable is not set */
5905 if((var->is_list && (!lval || !lval[0])) ||
5906 (!var->is_list && !pval)){
5907 /* leave null variables out of remote pinerc */
5908 if(prc->type == Loc &&
5909 (!so_puts(so, var->name) || !so_puts(so, "=") ||
5910 !so_puts(so, NEWLINE)))
5911 goto io_err;
5913 /* var is set to empty string */
5914 else if((var->is_list && lval[0][0] == '\0') ||
5915 (!var->is_list && pval[0] == '\0')){
5916 if(!so_puts(so, var->name) || !so_puts(so, "=") ||
5917 !so_puts(so, quotes) || !so_puts(so, NEWLINE))
5918 goto io_err;
5920 else{
5921 if(var->is_list){
5922 int i = 0;
5924 for(i = 0; lval[i]; i++){
5925 if(strlen(var->name)
5926 + (lval[i][0] ? strlen(lval[i]) : 5) > buflen){
5927 buflen = strlen(var->name)
5928 + (lval[i][0] ? strlen(lval[i]) : 5);
5929 fs_resize((void **)&linep, (buflen+1)*sizeof(char));
5930 fs_resize((void **)&lineq, (buflen+1)*sizeof(char));
5932 snprintf(linep, buflen+1, "%s%s%s%s%s",
5933 (i) ? "\t" : var->name,
5934 (i) ? "" : "=",
5935 lval[i][0] ? lval[i] : quotes,
5936 lval[i+1] ? "," : "", NEWLINE);
5937 linep[buflen] = '\0';
5938 if(!so_puts(so, bc ? backcompat_convert_from_utf8(&lineq, buflen+1, linep) : linep))
5939 goto io_err;
5942 else{
5943 if(strlen(var->name)
5944 + (pval[0] ? strlen(pval) : 5) > buflen){
5945 buflen = strlen(var->name)
5946 + (pval[0] ? strlen(pval) : 5);
5947 fs_resize((void **)&linep, (buflen+1)*sizeof(char));
5948 fs_resize((void **)&lineq, (buflen+1)*sizeof(char));
5950 snprintf(linep, buflen+1, "%s=%s%s%s%s",
5951 var->name,
5952 (pline->is_quoted && pval[0] != '\"')
5953 ? "\"" : "",
5954 pval,
5955 (pline->is_quoted && pval[0] != '\"')
5956 ? "\"" : "", NEWLINE);
5957 linep[buflen] = '\0';
5958 if(!so_puts(so, bc ? backcompat_convert_from_utf8(&lineq, buflen+1, linep) : linep))
5959 goto io_err;
5963 var->been_written = 1;
5965 }else{
5967 * The description text should be changed into a message
5968 * about the variable being obsolete when a variable is
5969 * moved to obsolete status. We add that message before
5970 * the variable unless it is already there. However, we
5971 * leave the variable itself in case the user runs an old
5972 * version of pine again. Note that we have read in the
5973 * value of the variable in read_pinerc and translated it
5974 * into a new variable if appropriate.
5976 if(pline->obsolete_var && prc->type == Loc){
5977 if(pline <= prc->pinerc_lines || (pline-1)->line == NULL ||
5978 strlen((pline-1)->line) < 3 ||
5979 strucmp((pline-1)->line+2, pline->var->descrip) != 0)
5980 if(!so_puts(so, "# ") ||
5981 !so_puts(so, native_nl(pline->var->descrip)) ||
5982 !so_puts(so, NEWLINE))
5983 goto io_err;
5986 /* remove comments from remote pinercs */
5987 if((prc->type == Loc ||
5988 (pline->line[0] != '#' && pline->line[0] != '\0')) &&
5989 (!so_puts(so, pline->line) || !so_puts(so, NEWLINE)))
5990 goto io_err;
5994 /* Now write out all the variables not in the .pinerc */
5995 for(var = ps->vars; var->name != NULL; var++){
5996 if(!var->is_user || var->been_written || !var->is_used ||
5997 var->is_obsolete || (var->is_onlymain && which != Main))
5998 continue;
6000 if(var->is_list)
6001 lval = LVAL(var, which);
6002 else
6003 pval = PVAL(var, which);
6006 * set description to NULL to eliminate preceding
6007 * blank and comment line.
6009 if(prc->type == Loc && var->descrip && *var->descrip &&
6010 (!so_puts(so, NEWLINE) || !so_puts(so, "# ") ||
6011 !so_puts(so, native_nl(var->descrip)) || !so_puts(so, NEWLINE)))
6012 goto io_err;
6014 /* variable is not set */
6015 /** Don't know what the global_val thing is for. SH, Mar 00 **/
6016 if((var->is_list && (!lval || (!lval[0] && !var->global_val.l))) ||
6017 (!var->is_list && !pval)){
6018 /* leave null variables out of remote pinerc */
6019 if(prc->type == Loc &&
6020 (!so_puts(so, var->name) || !so_puts(so, "=") ||
6021 !so_puts(so, NEWLINE)))
6022 goto io_err;
6024 /* var is set to empty string */
6025 else if((var->is_list && (!lval[0] || !lval[0][0]))
6026 || (!var->is_list && pval[0] == '\0')){
6027 if(!so_puts(so, var->name) || !so_puts(so, "=") ||
6028 !so_puts(so, quotes) || !so_puts(so, NEWLINE))
6029 goto io_err;
6031 else if(var->is_list){
6032 int i = 0;
6034 for(i = 0; lval[i] ; i++){
6035 if(strlen(var->name)
6036 + (lval[i][0] ? strlen(lval[i]) : 5) > buflen){
6037 buflen = strlen(var->name)
6038 + (lval[i][0] ? strlen(lval[i]) : 5);
6039 fs_resize((void **)&linep, (buflen+1)*sizeof(char));
6040 fs_resize((void **)&lineq, (buflen+1)*sizeof(char));
6042 snprintf(linep, buflen+1, "%s%s%s%s%s",
6043 (i) ? "\t" : var->name,
6044 (i) ? "" : "=",
6045 lval[i],
6046 lval[i+1] ? "," : "", NEWLINE);
6047 linep[buflen] = '\0';
6048 if(!so_puts(so, bc ? backcompat_convert_from_utf8(&lineq, buflen+1, linep) : linep))
6049 goto io_err;
6052 else{
6053 char *pconverted;
6055 if(strlen(pval) > buflen){
6056 buflen = strlen(pval) + 1;
6057 fs_resize((void **)&linep, (buflen+1)*sizeof(char));
6058 fs_resize((void **)&lineq, (buflen+1)*sizeof(char));
6060 pconverted = bc ? backcompat_convert_from_utf8(&lineq, buflen+1, pval) : pval;
6062 if(!so_puts(so, var->name) || !so_puts(so, "=") ||
6063 !so_puts(so, pconverted) || !so_puts(so, NEWLINE))
6064 goto io_err;
6068 if(!(rd && rd->flags & NO_FILE)){
6069 char *realfilename;
6070 int realfilename_malloced;
6072 if(so_give(&so)) goto io_err;
6074 #ifndef _WINDOWS
6075 realfilename = fs_get(MAXPATH+1);
6076 if(realfilename != NULL){
6077 if(realpath(filename, realfilename) == NULL)
6078 fs_give((void **) &realfilename);
6079 realfilename_malloced = realfilename != NULL ? 1 : 0;
6081 else
6082 realfilename_malloced = 0;
6083 if (realfilename_malloced == 0){
6084 if(our_stat(filename, &sbuf) < 0 && errno == ENOENT){
6085 realfilename = filename;
6086 realfilename_malloced = 0;
6088 else
6089 goto io_err;
6091 #else
6092 realfilename = filename;
6093 realfilename_malloced = 0;
6094 #endif /* _WINDOWS */
6095 if(realfilename != NULL){
6096 int r;
6097 file_attrib_copy(tmp, realfilename);
6098 r = rename_file(tmp, realfilename);
6099 if(realfilename_malloced != 0)
6100 fs_give((void **) &realfilename);
6101 if(r < 0) goto io_err;
6105 if(prc->type != Loc){
6106 int e, we_cancel;
6107 char datebuf[200];
6109 datebuf[0] = '\0';
6110 we_cancel = 0;
6112 if(!(flags & WRP_NOUSER))
6113 we_cancel = busy_cue(_("Copying to remote config"), NULL, 1);
6115 if((e = rd_update_remote(rd, datebuf)) != 0){
6116 dprint((1,
6117 "write_pinerc: error copying from %s to %s\n",
6118 rd->lf ? rd->lf : "<memory>", rd->rn ? rd->rn : "?"));
6119 if(!(flags & WRP_NOUSER)){
6120 q_status_message2(SM_ORDER | SM_DING, 3, 5,
6121 _("Error copying to %.200s: %.200s"),
6122 rd->rn, error_description(errno));
6124 q_status_message(SM_ORDER | SM_DING, 5, 5,
6125 _("Copy of config to remote folder failed, changes NOT saved remotely"));
6128 else{
6129 rd_update_metadata(rd, datebuf);
6130 rd->read_status = 'W';
6131 rd_trim_remdata(&rd);
6132 rd_close_remote(rd);
6135 if(we_cancel)
6136 cancel_busy_cue(-1);
6139 prc->outstanding_pinerc_changes = 0;
6141 if(prc->type == Loc){
6142 prc->pinerc_written = name_file_mtime(filename);
6143 dprint((2, "wrote pinerc: %s: time_pinerc_written = %ld\n",
6144 pinrc ? pinrc : "?", (long) prc->pinerc_written));
6146 else{
6147 dprint((2, "wrote pinerc: %s\n", pinrc ? pinrc : "?"));
6150 if(tmp){
6151 our_unlink(tmp);
6152 fs_give((void **)&tmp);
6155 if(linep) fs_give((void **)&linep);
6156 if(lineq) fs_give((void **)&lineq);
6158 return(0);
6160 io_err:
6161 if(!(flags & WRP_NOUSER))
6162 q_status_message2(SM_ORDER | SM_DING, 3, 5,
6163 _("Error saving configuration in \"%.200s\": %.200s"),
6164 pinrc, error_description(errno));
6166 dprint((1, "Error writing %s : %s\n", pinrc ? pinrc : "?",
6167 error_description(errno)));
6168 if(rd)
6169 rd->flags &= ~DO_REMTRIM;
6170 if(tmp){
6171 our_unlink(tmp);
6172 fs_give((void **)&tmp);
6175 if(linep) fs_give((void **)&linep);
6176 if(lineq) fs_give((void **)&lineq);
6178 return(-1);
6183 * The srcstr is UTF-8. In order to help the user with
6184 * running this pine and an old pre-alpine pine on the same config
6185 * file we attempt to convert the values of the config variables
6186 * to the user's character set before writing.
6187 * parameters: char **buf. Memory of size_t buflen allocated by caller.
6189 char *
6190 backcompat_convert_from_utf8(char **buf, size_t buflen, char *srcstr)
6192 char *converted = NULL;
6193 char *p;
6194 int its_ascii = 1;
6197 for(p = srcstr; *p && its_ascii; p++)
6198 if(*p & 0x80)
6199 its_ascii = 0;
6201 /* if it is ascii, go with that */
6202 if(its_ascii){
6203 strncpy(*buf, srcstr, buflen);
6204 converted = *buf;
6205 (*buf)[buflen-1] = '\0';
6207 else{
6208 char *trythischarset = NULL;
6211 * If it is possible to translate the UTF-8
6212 * string into the user's character set then
6213 * do that. For backwards compatibility with
6214 * old pines.
6216 if(ps_global->keyboard_charmap && ps_global->keyboard_charmap[0])
6217 trythischarset = ps_global->keyboard_charmap;
6218 else if(ps_global->display_charmap && ps_global->display_charmap[0])
6219 trythischarset = ps_global->display_charmap;
6221 if(trythischarset){
6222 SIZEDTEXT src, dst;
6224 src.data = (unsigned char *) srcstr;
6225 src.size = strlen(srcstr);
6226 memset(&dst, 0, sizeof(dst));
6227 if(utf8_cstext(&src, trythischarset, &dst, 0)){
6228 if(dst.data){
6229 strncpy(*buf, (char *) dst.data, buflen);
6230 (*buf)[buflen-1] = '\0';
6231 fs_give((void **) &dst.data);
6236 if(!converted){
6237 strncpy(*buf, srcstr, buflen);
6238 (*buf)[buflen-1] = '\0';
6239 converted = *buf;
6243 return(converted);
6248 * Given a unix-style source string which may contain LFs,
6249 * convert those to CRLFs if appropriate.
6251 * Returns a pointer to the converted string. This will be a string
6252 * stored in tmp_20k_buf.
6254 * This is just used for the variable descriptions in the pinerc file. It
6255 * could certainly be fancier. It simply converts all \n to NEWLINE.
6257 char *
6258 native_nl(char *src)
6260 char *q, *p;
6262 tmp_20k_buf[0] = '\0';
6264 if(src){
6265 for(q = (char *)tmp_20k_buf; *src; src++){
6266 if(*src == '\n'){
6267 for(p = NEWLINE; *p; p++)
6268 *q++ = *p;
6270 else
6271 *q++ = *src;
6274 *q = '\0';
6277 return((char *)tmp_20k_buf);
6281 void
6282 quit_to_edit_msg(PINERC_S *prc)
6284 /* TRANSLATORS: The %s is either "Postload " or nothing. A Postload config file
6285 is a type of config file. */
6286 q_status_message1(SM_ORDER, 3, 4, _("Must quit Alpine to change %sconfig file."),
6287 (prc == ps_global->post_prc) ? "Postload " : "");
6291 /*------------------------------------------------------------
6292 Return TRUE if the given string was a feature name present in the
6293 pinerc as it was when pine was started...
6294 ----*/
6296 var_in_pinerc(char *s)
6298 PINERC_LINE *pline;
6300 for(pline = ps_global->prc ? ps_global->prc->pinerc_lines : NULL;
6301 pline && (pline->var || pline->line); pline++)
6302 if(pline->var && pline->var->name && !strucmp(s, pline->var->name))
6303 return(1);
6305 for(pline = ps_global->post_prc ? ps_global->post_prc->pinerc_lines : NULL;
6306 pline && (pline->var || pline->line); pline++)
6307 if(pline->var && pline->var->name && !strucmp(s, pline->var->name))
6308 return(1);
6310 return(0);
6314 /*------------------------------------------------------------
6315 Free resources associated with pinerc_lines data
6316 ----*/
6317 void
6318 free_pinerc_lines(PINERC_LINE **pinerc_lines)
6320 PINERC_LINE *pline;
6322 if(pinerc_lines && *pinerc_lines){
6323 for(pline = *pinerc_lines; pline->var || pline->line; pline++)
6324 if(pline->line)
6325 fs_give((void **)&pline->line);
6327 fs_give((void **)pinerc_lines);
6332 /*------------------------------------------------------------
6333 Dump out a global pine.conf on the standard output with fresh
6334 comments. Preserves variables currently set in SYSTEM_PINERC, if any.
6335 ----*/
6336 void
6337 dump_global_conf(void)
6339 FILE *f;
6340 struct variable *var;
6341 PINERC_S *prc;
6343 prc = new_pinerc_s(SYSTEM_PINERC);
6344 read_pinerc(prc, variables, ParseGlobal);
6345 if(prc)
6346 free_pinerc_s(&prc);
6348 f = stdout;
6349 if(f == NULL)
6350 goto io_err;
6352 fprintf(f, "# %s -- system wide pine configuration\n#\n",
6353 SYSTEM_PINERC);
6354 fprintf(f, "# Values here affect all pine users unless they've overridden the values\n");
6355 fprintf(f, "# in their .pinerc files. A copy of this file with current comments may\n");
6356 fprintf(f, "# be obtained by running \"pine -conf\". It will be printed to standard output.\n#\n");
6357 fprintf(f,"# For a variable to be unset its value must be null/blank. This is not the\n");
6358 fprintf(f,"# same as the value of \"empty string\", which can be used to effectively\n");
6359 fprintf(f,"# \"unset\" a variable that has a default or previously assigned value.\n");
6360 fprintf(f,"# To set a variable to the empty string its value should be \"\".\n");
6361 fprintf(f,"# Switch variables are set to either \"yes\" or \"no\", and default to \"no\".\n");
6362 fprintf(f,"# Except for feature-list items, which are additive, values set in the\n");
6363 fprintf(f,"# .pinerc file replace those in pine.conf, and those in pine.conf.fixed\n");
6364 fprintf(f,"# over-ride all others. Features can be over-ridden in .pinerc or\n");
6365 fprintf(f,"# pine.conf.fixed by pre-pending the feature name with \"no-\".\n#\n");
6366 fprintf(f,"# (These comments are automatically inserted.)\n");
6368 for(var = variables; var->name != NULL; var++){
6369 if(!var->is_global || !var->is_used || var->is_obsolete)
6370 continue;
6372 if(var->descrip && *var->descrip){
6373 if(fprintf(f, "\n# %s\n", var->descrip) == EOF)
6374 goto io_err;
6377 if(var->is_list){
6378 if(var->global_val.l == NULL){
6379 if(fprintf(f, "%s=\n", var->name) == EOF)
6380 goto io_err;
6381 }else{
6382 int i;
6384 for(i=0; var->global_val.l[i]; i++)
6385 if(fprintf(f, "%s%s%s%s\n", (i) ? "\t" : var->name,
6386 (i) ? "" : "=", var->global_val.l[i],
6387 var->global_val.l[i+1] ? ",":"") == EOF)
6388 goto io_err;
6390 }else{
6391 if(var->global_val.p == NULL){
6392 if(fprintf(f, "%s=\n", var->name) == EOF)
6393 goto io_err;
6394 }else if(strlen(var->global_val.p) == 0){
6395 if(fprintf(f, "%s=\"\"\n", var->name) == EOF)
6396 goto io_err;
6397 }else{
6398 if(fprintf(f,"%s=%s\n",var->name,var->global_val.p) == EOF)
6399 goto io_err;
6403 exit(0);
6406 io_err:
6407 fprintf(stderr, "Error writing config to stdout: %s\n",
6408 error_description(errno));
6409 exit(-1);
6413 /*------------------------------------------------------------
6414 Dump out a pinerc to filename with fresh
6415 comments. Preserves variables currently set in pinerc, if any.
6416 ----*/
6417 void
6418 dump_new_pinerc(char *filename)
6420 FILE *f;
6421 struct variable *var;
6422 char buf[MAXPATH], *p;
6423 PINERC_S *prc;
6426 p = ps_global->pinerc;
6428 #if defined(DOS) || defined(OS2)
6429 if(!ps_global->pinerc){
6430 char *p;
6432 if(p = getenv("PINERC")){
6433 ps_global->pinerc = cpystr(p);
6434 }else{
6435 char buf2[MAXPATH];
6436 build_path(buf2, ps_global->home_dir, DF_PINEDIR, sizeof(buf2));
6437 build_path(buf, buf2, SYSTEM_PINERC, sizeof(buf));
6440 p = buf;
6442 #else /* !DOS */
6443 if(!ps_global->pinerc){
6444 build_path(buf, ps_global->home_dir, ".pinerc", sizeof(buf));
6445 p = buf;
6447 #endif /* !DOS */
6449 prc = new_pinerc_s(p);
6450 read_pinerc(prc, variables, ParsePers);
6451 if(prc)
6452 free_pinerc_s(&prc);
6454 f = NULL;;
6455 if(filename[0] == '\0'){
6456 fprintf(stderr, "Missing argument to \"-pinerc\".\n");
6457 }else if(!strcmp(filename, "-")){
6458 f = stdout;
6459 }else{
6460 f = our_fopen(filename, "wb");
6463 if(f == NULL)
6464 goto io_err;
6466 if(fprintf(f, "%s", cf_text_comment) == EOF)
6467 goto io_err;
6469 for(var = variables; var->name != NULL; var++){
6470 dprint((7,"write_pinerc: %s = %s\n",
6471 var->name ? var->name : "?",
6472 var->main_user_val.p ? var->main_user_val.p : "<not set>"));
6473 if(!var->is_user || !var->is_used || var->is_obsolete)
6474 continue;
6477 * set description to NULL to eliminate preceding
6478 * blank and comment line.
6480 if(var->descrip && *var->descrip){
6481 if(fprintf(f, "\n# %s\n", var->descrip) == EOF)
6482 goto io_err;
6485 if(var->is_list){
6486 if(var->main_user_val.l == NULL){
6487 if(fprintf(f, "%s=\n", var->name) == EOF)
6488 goto io_err;
6489 }else{
6490 int i;
6492 for(i=0; var->main_user_val.l[i]; i++)
6493 if(fprintf(f, "%s%s%s%s\n", (i) ? "\t" : var->name,
6494 (i) ? "" : "=", var->main_user_val.l[i],
6495 var->main_user_val.l[i+1] ? ",":"") == EOF)
6496 goto io_err;
6498 }else{
6499 if(var->main_user_val.p == NULL){
6500 if(fprintf(f, "%s=\n", var->name) == EOF)
6501 goto io_err;
6502 }else if(strlen(var->main_user_val.p) == 0){
6503 if(fprintf(f, "%s=\"\"\n", var->name) == EOF)
6504 goto io_err;
6505 }else{
6506 if(fprintf(f,"%s=%s\n",var->name,var->main_user_val.p) == EOF)
6507 goto io_err;
6511 exit(0);
6514 io_err:
6515 snprintf(buf, sizeof(buf), "Error writing config to %s: %s\n",
6516 filename, error_description(errno));
6517 exceptional_exit(buf, -1);
6521 /*----------------------------------------------------------------------
6522 Set a user variable and save the .pinerc
6524 Args: var -- The index of the variable to set from conftype.h (V_....)
6525 value -- The string to set the value to
6527 Result: -1 is returned on failure and 0 is returned on success
6529 The vars data structure is updated and the pinerc saved.
6530 ----*/
6532 set_variable(int var, char *value, int expand, int commit, EditWhich which)
6534 struct variable *v;
6535 char **apval;
6536 PINERC_S *prc = NULL;
6538 v = &ps_global->vars[var];
6540 if(!v->is_user)
6541 panic1("Trying to set non-user variable %s", v->name);
6543 /* Override value of which, at most one of these should be set */
6544 if(v->is_onlymain)
6545 which = Main;
6546 else if(v->is_outermost)
6547 which = ps_global->ew_for_except_vars;
6549 apval = APVAL(v, which);
6551 if(!apval)
6552 return(-1);
6554 if(*apval)
6555 fs_give((void **)apval);
6557 *apval = value ? cpystr(value) : NULL;
6558 set_current_val(v, expand, FALSE);
6560 switch(which){
6561 case Main:
6562 prc = ps_global->prc;
6563 break;
6564 case Post:
6565 prc = ps_global->post_prc;
6566 break;
6567 default:
6568 break;
6571 if(prc)
6572 prc->outstanding_pinerc_changes = 1;
6574 return(commit ? write_pinerc(ps_global, which, WRP_NONE) : 0);
6578 /*----------------------------------------------------------------------
6579 Set a user variable list and save the .pinerc
6581 Args: var -- The index of the variable to set from conftype.h (V_....)
6582 lvalue -- The list to set the value to
6584 Result: -1 is returned on failure and 0 is returned on success
6586 The vars data structure is updated and if write_it, the pinerc is saved.
6587 ----*/
6589 set_variable_list(int var, char **lvalue, int write_it, EditWhich which)
6591 char ***alval;
6592 int i;
6593 struct variable *v = &ps_global->vars[var];
6594 PINERC_S *prc = NULL;
6596 if(!v->is_user || !v->is_list)
6597 panic1("BOTCH: Trying to set non-user or non-list variable %s", v->name);
6599 /* Override value of which, at most one of these should be set */
6600 if(v->is_onlymain)
6601 which = Main;
6602 else if(v->is_outermost)
6603 which = ps_global->ew_for_except_vars;
6605 alval = ALVAL(v, which);
6606 if(!alval)
6607 return(-1);
6609 if(*alval)
6610 free_list_array(alval);
6612 if(lvalue){
6613 for(i = 0; lvalue[i] ; i++) /* count elements */
6616 *alval = (char **) fs_get((i+1) * sizeof(char *));
6618 for(i = 0; lvalue[i] ; i++)
6619 (*alval)[i] = cpystr(lvalue[i]);
6621 (*alval)[i] = NULL;
6624 set_current_val(v, TRUE, FALSE);
6626 switch(which){
6627 case Main:
6628 prc = ps_global->prc;
6629 break;
6630 case Post:
6631 prc = ps_global->post_prc;
6632 break;
6633 default:
6634 break;
6637 if(prc)
6638 prc->outstanding_pinerc_changes = 1;
6640 return(write_it ? write_pinerc(ps_global, which, WRP_NONE) : 0);
6644 void
6645 set_current_color_vals(struct pine *ps)
6647 struct variable *vars = ps->vars;
6648 int later_color_is_set = 0;
6650 set_current_val(&vars[V_NORM_FORE_COLOR], TRUE, TRUE);
6651 set_current_val(&vars[V_NORM_BACK_COLOR], TRUE, TRUE);
6652 pico_nfcolor(VAR_NORM_FORE_COLOR);
6653 pico_nbcolor(VAR_NORM_BACK_COLOR);
6655 set_current_val(&vars[V_REV_FORE_COLOR], TRUE, TRUE);
6656 set_current_val(&vars[V_REV_BACK_COLOR], TRUE, TRUE);
6657 pico_rfcolor(VAR_REV_FORE_COLOR);
6658 pico_rbcolor(VAR_REV_BACK_COLOR);
6660 set_color_val(&vars[V_TITLE_FORE_COLOR], 1);
6661 set_color_val(&vars[V_TITLECLOSED_FORE_COLOR], 0);
6662 set_color_val(&vars[V_FOLDER_FORE_COLOR], 0);
6663 set_color_val(&vars[V_DIRECTORY_FORE_COLOR], 0);
6664 set_color_val(&vars[V_FOLDER_LIST_FORE_COLOR], 0);
6665 set_color_val(&vars[V_STATUS_FORE_COLOR], 1);
6666 set_color_val(&vars[V_KEYLABEL_FORE_COLOR], 1);
6667 set_color_val(&vars[V_KEYNAME_FORE_COLOR], 1);
6668 set_color_val(&vars[V_SLCTBL_FORE_COLOR], 1);
6669 set_color_val(&vars[V_METAMSG_FORE_COLOR], 1);
6670 set_color_val(&vars[V_PROMPT_FORE_COLOR], 1);
6671 set_color_val(&vars[V_HEADER_GENERAL_FORE_COLOR], 1);
6672 set_color_val(&vars[V_IND_PLUS_FORE_COLOR], 0);
6673 set_color_val(&vars[V_IND_IMP_FORE_COLOR], 0);
6674 set_color_val(&vars[V_IND_DEL_FORE_COLOR], 0);
6675 set_color_val(&vars[V_IND_HIPRI_FORE_COLOR], 0);
6676 set_color_val(&vars[V_IND_LOPRI_FORE_COLOR], 0);
6677 set_color_val(&vars[V_IND_ANS_FORE_COLOR], 0);
6678 set_color_val(&vars[V_IND_NEW_FORE_COLOR], 0);
6679 set_color_val(&vars[V_IND_REC_FORE_COLOR], 0);
6680 set_color_val(&vars[V_IND_FWD_FORE_COLOR], 0);
6681 set_color_val(&vars[V_IND_UNS_FORE_COLOR], 0);
6682 set_color_val(&vars[V_IND_ARR_FORE_COLOR], 0);
6683 set_color_val(&vars[V_IND_SUBJ_FORE_COLOR], 0);
6684 set_color_val(&vars[V_IND_FROM_FORE_COLOR], 0);
6685 set_color_val(&vars[V_IND_OP_FORE_COLOR], 0);
6686 set_color_val(&vars[V_INCUNSEEN_FORE_COLOR], 0);
6687 set_color_val(&vars[V_SIGNATURE_FORE_COLOR], 0);
6689 set_current_val(&ps->vars[V_INDEX_TOKEN_COLORS], TRUE, TRUE);
6690 set_current_val(&ps->vars[V_VIEW_HDR_COLORS], TRUE, TRUE);
6691 set_current_val(&ps->vars[V_KW_COLORS], TRUE, TRUE);
6692 set_custom_spec_colors(ps);
6695 * Set up the quoting colors. If a later color is set but not an earlier
6696 * color we set the earlier color to Normal to make it easier when
6697 * we go to use the colors. However, if the only quote colors set are
6698 * Normal that is the same as no settings, so delete them.
6700 set_color_val(&vars[V_QUOTE1_FORE_COLOR], 0);
6701 set_color_val(&vars[V_QUOTE2_FORE_COLOR], 0);
6702 set_color_val(&vars[V_QUOTE3_FORE_COLOR], 0);
6704 if((!(VAR_QUOTE3_FORE_COLOR && VAR_QUOTE3_BACK_COLOR) ||
6705 (!strucmp(VAR_QUOTE3_FORE_COLOR, VAR_NORM_FORE_COLOR) &&
6706 !strucmp(VAR_QUOTE3_BACK_COLOR, VAR_NORM_BACK_COLOR))) &&
6707 (!(VAR_QUOTE2_FORE_COLOR && VAR_QUOTE2_BACK_COLOR) ||
6708 (!strucmp(VAR_QUOTE2_FORE_COLOR, VAR_NORM_FORE_COLOR) &&
6709 !strucmp(VAR_QUOTE2_BACK_COLOR, VAR_NORM_BACK_COLOR))) &&
6710 (!(VAR_QUOTE1_FORE_COLOR && VAR_QUOTE1_BACK_COLOR) ||
6711 (!strucmp(VAR_QUOTE1_FORE_COLOR, VAR_NORM_FORE_COLOR) &&
6712 !strucmp(VAR_QUOTE1_BACK_COLOR, VAR_NORM_BACK_COLOR)))){
6714 * They are all either Normal or not set. Delete them all.
6716 if(VAR_QUOTE3_FORE_COLOR)
6717 fs_give((void **)&VAR_QUOTE3_FORE_COLOR);
6718 if(VAR_QUOTE3_BACK_COLOR)
6719 fs_give((void **)&VAR_QUOTE3_BACK_COLOR);
6720 if(VAR_QUOTE2_FORE_COLOR)
6721 fs_give((void **)&VAR_QUOTE2_FORE_COLOR);
6722 if(VAR_QUOTE2_BACK_COLOR)
6723 fs_give((void **)&VAR_QUOTE2_BACK_COLOR);
6724 if(VAR_QUOTE1_FORE_COLOR)
6725 fs_give((void **)&VAR_QUOTE1_FORE_COLOR);
6726 if(VAR_QUOTE1_BACK_COLOR)
6727 fs_give((void **)&VAR_QUOTE1_BACK_COLOR);
6729 else{ /* something is non-Normal */
6730 if(VAR_QUOTE3_FORE_COLOR && VAR_QUOTE3_BACK_COLOR)
6731 later_color_is_set++;
6733 /* if 3 is set but not 2, set 2 to Normal */
6734 if(VAR_QUOTE2_FORE_COLOR && VAR_QUOTE2_BACK_COLOR)
6735 later_color_is_set++;
6736 else if(later_color_is_set)
6737 set_color_val(&vars[V_QUOTE2_FORE_COLOR], 1);
6739 /* if 3 or 2 is set but not 1, set 1 to Normal */
6740 if(VAR_QUOTE1_FORE_COLOR && VAR_QUOTE1_BACK_COLOR)
6741 later_color_is_set++;
6742 else if(later_color_is_set)
6743 set_color_val(&vars[V_QUOTE1_FORE_COLOR], 1);
6746 #ifdef _WINDOWS
6747 if(ps->pre441){
6748 int conv_main = 0, conv_post = 0;
6750 ps->pre441 = 0;
6751 if(ps->prc && !unix_color_style_in_pinerc(ps->prc)){
6752 conv_main = convert_pc_gray_names(ps, ps->prc, Main);
6753 if(conv_main)
6754 ps->prc->outstanding_pinerc_changes = 1;
6758 if(ps->post_prc && !unix_color_style_in_pinerc(ps->post_prc)){
6759 conv_post = convert_pc_gray_names(ps, ps->post_prc, Post);
6760 if(conv_post)
6761 ps->post_prc->outstanding_pinerc_changes = 1;
6764 if(conv_main || conv_post){
6765 if(conv_main)
6766 write_pinerc(ps, Main, WRP_NONE);
6768 if(conv_post)
6769 write_pinerc(ps, Post, WRP_NONE);
6771 set_current_color_vals(ps);
6774 #endif /* _WINDOWS */
6776 pico_set_normal_color();
6781 * Set current_val for the foreground and background color vars, which
6782 * are assumed to be in order. If a set_current_val on them doesn't
6783 * produce current_vals, then use the colors from defvar to set those
6784 * current_vals.
6786 void
6787 set_color_val(struct variable *v, int use_default)
6789 set_current_val(v, TRUE, TRUE);
6790 set_current_val(v+1, TRUE, TRUE);
6792 if(!(v->current_val.p && v->current_val.p[0] &&
6793 (v+1)->current_val.p && (v+1)->current_val.p[0])){
6794 struct variable *defvar;
6796 if(v->current_val.p)
6797 fs_give((void **)&v->current_val.p);
6798 if((v+1)->current_val.p)
6799 fs_give((void **)&(v+1)->current_val.p);
6801 if(!use_default)
6802 return;
6804 if(var_defaults_to_rev(v))
6805 defvar = &ps_global->vars[V_REV_FORE_COLOR];
6806 else
6807 defvar = &ps_global->vars[V_NORM_FORE_COLOR];
6809 /* use default vars values instead */
6810 if(defvar && defvar->current_val.p && defvar->current_val.p[0] &&
6811 (defvar+1)->current_val.p && (defvar+1)->current_val.p[0]){
6812 v->current_val.p = cpystr(defvar->current_val.p);
6813 (v+1)->current_val.p = cpystr((defvar+1)->current_val.p);
6820 var_defaults_to_rev(struct variable *v)
6822 return(v == &ps_global->vars[V_REV_FORE_COLOR] ||
6823 v == &ps_global->vars[V_TITLE_FORE_COLOR] ||
6824 v == &ps_global->vars[V_STATUS_FORE_COLOR] ||
6825 v == &ps_global->vars[V_KEYNAME_FORE_COLOR] ||
6826 v == &ps_global->vars[V_PROMPT_FORE_COLOR]);
6832 * Each item in the list looks like:
6834 * /HDR=<header>/FG=<foreground color>/BG=<background color>
6836 * We separate the three pieces into an array of structures to make
6837 * it easier to deal with later.
6839 void
6840 set_custom_spec_colors(struct pine *ps)
6842 if(ps->index_token_colors)
6843 free_spec_colors(&ps->index_token_colors);
6845 ps->index_token_colors = spec_colors_from_varlist(ps->VAR_INDEX_TOKEN_COLORS, 1);
6847 if(ps->hdr_colors)
6848 free_spec_colors(&ps->hdr_colors);
6850 ps->hdr_colors = spec_colors_from_varlist(ps->VAR_VIEW_HDR_COLORS, 1);
6852 /* fit keyword colors into the same structures for code re-use */
6853 if(ps->kw_colors)
6854 free_spec_colors(&ps->kw_colors);
6856 ps->kw_colors = spec_colors_from_varlist(ps->VAR_KW_COLORS, 1);
6861 * Input is one item from config variable.
6863 * Return value must be freed by caller. The return is a single SPEC_COLOR_S,
6864 * not a list.
6866 SPEC_COLOR_S *
6867 spec_color_from_var(char *t, int already_expanded)
6869 char *p, *spec, *fg, *bg;
6870 PATTERN_S *val;
6871 SPEC_COLOR_S *new_hcolor = NULL;
6873 if(t && t[0] && !strcmp(t, INHERIT)){
6874 new_hcolor = (SPEC_COLOR_S *)fs_get(sizeof(*new_hcolor));
6875 memset((void *)new_hcolor, 0, sizeof(*new_hcolor));
6876 new_hcolor->inherit = 1;
6878 else if(t && t[0]){
6879 char tbuf[10000];
6881 if(!already_expanded){
6882 tbuf[0] = '\0';
6883 if(expand_variables(tbuf, sizeof(tbuf), t, 0))
6884 t = tbuf;
6887 spec = fg = bg = NULL;
6888 val = NULL;
6889 if((p = srchstr(t, "/HDR=")) != NULL)
6890 spec = remove_backslash_escapes(p+5);
6891 if((p = srchstr(t, "/FG=")) != NULL)
6892 fg = remove_backslash_escapes(p+4);
6893 if((p = srchstr(t, "/BG=")) != NULL)
6894 bg = remove_backslash_escapes(p+4);
6895 val = parse_pattern("VAL", t, 0);
6897 if(spec && *spec){
6898 /* remove colons */
6899 if((p = strindex(spec, ':')) != NULL)
6900 *p = '\0';
6902 new_hcolor = (SPEC_COLOR_S *)fs_get(sizeof(*new_hcolor));
6903 memset((void *)new_hcolor, 0, sizeof(*new_hcolor));
6904 new_hcolor->spec = spec;
6905 new_hcolor->fg = fg;
6906 new_hcolor->bg = bg;
6907 new_hcolor->val = val;
6909 else{
6910 if(spec)
6911 fs_give((void **)&spec);
6912 if(fg)
6913 fs_give((void **)&fg);
6914 if(bg)
6915 fs_give((void **)&bg);
6916 if(val)
6917 free_pattern(&val);
6921 return(new_hcolor);
6926 * Input is a list from config file.
6928 * Return value may be a list of SPEC_COLOR_S and must be freed by caller.
6930 SPEC_COLOR_S *
6931 spec_colors_from_varlist(char **varlist, int already_expanded)
6933 char **s, *t;
6934 SPEC_COLOR_S *new_hc = NULL;
6935 SPEC_COLOR_S *new_hcolor, **nexthc;
6937 nexthc = &new_hc;
6938 if(varlist){
6939 for(s = varlist; (t = *s) != NULL; s++){
6940 if(t[0]){
6941 new_hcolor = spec_color_from_var(t, already_expanded);
6942 if(new_hcolor){
6943 *nexthc = new_hcolor;
6944 nexthc = &new_hcolor->next;
6950 return(new_hc);
6955 * Returns allocated charstar suitable for config var for a single
6956 * SPEC_COLOR_S.
6958 char *
6959 var_from_spec_color(SPEC_COLOR_S *hc)
6961 char *ret_val = NULL;
6962 char *p, *spec = NULL, *fg = NULL, *bg = NULL, *val = NULL;
6963 size_t len;
6965 if(hc && hc->inherit)
6966 ret_val = cpystr(INHERIT);
6967 else if(hc){
6968 if(hc->spec)
6969 spec = add_viewerhdr_escapes(hc->spec);
6970 if(hc->fg)
6971 fg = add_viewerhdr_escapes(hc->fg);
6972 if(hc->bg)
6973 bg = add_viewerhdr_escapes(hc->bg);
6974 if(hc->val){
6975 p = pattern_to_string(hc->val);
6976 if(p){
6977 val = add_viewerhdr_escapes(p);
6978 fs_give((void **)&p);
6982 len = strlen("/HDR=/FG=/BG=") + strlen(spec ? spec : "") +
6983 strlen(fg ? fg : "") + strlen(bg ? bg : "") +
6984 strlen(val ? "/VAL=" : "") + strlen(val ? val : "");
6985 ret_val = (char *) fs_get(len + 1);
6986 snprintf(ret_val, len+1, "/HDR=%s/FG=%s/BG=%s%s%s",
6987 spec ? spec : "", fg ? fg : "", bg ? bg : "",
6988 val ? "/VAL=" : "", val ? val : "");
6990 if(spec)
6991 fs_give((void **)&spec);
6992 if(fg)
6993 fs_give((void **)&fg);
6994 if(bg)
6995 fs_give((void **)&bg);
6996 if(val)
6997 fs_give((void **)&val);
7000 return(ret_val);
7005 * Returns allocated charstar suitable for config var for a single
7006 * SPEC_COLOR_S.
7008 char **
7009 varlist_from_spec_colors(SPEC_COLOR_S *hcolors)
7011 SPEC_COLOR_S *hc;
7012 char **ret_val = NULL;
7013 int i;
7015 /* count how many */
7016 for(hc = hcolors, i = 0; hc; hc = hc->next, i++)
7019 ret_val = (char **)fs_get((i+1) * sizeof(*ret_val));
7020 memset((void *)ret_val, 0, (i+1) * sizeof(*ret_val));
7021 for(hc = hcolors, i = 0; hc; hc = hc->next, i++)
7022 ret_val[i] = var_from_spec_color(hc);
7024 return(ret_val);
7028 void
7029 update_posting_charset(struct pine *ps, int revert)
7031 #ifndef _WINDOWS
7032 if(F_ON(F_USE_SYSTEM_TRANS, ps)){
7033 if(!revert)
7034 q_status_message(SM_ORDER, 5, 5, _("This change has no effect because feature Use-System-Translation is on"));
7036 else{
7037 #endif /* ! _WINDOWS */
7038 if(ps->posting_charmap)
7039 fs_give((void **) &ps->posting_charmap);
7041 if(ps->VAR_POST_CHAR_SET){
7042 ps->posting_charmap = cpystr(ps->VAR_POST_CHAR_SET);
7043 if(!posting_charset_is_supported(ps->posting_charmap)){
7044 snprintf(tmp_20k_buf, SIZEOF_20KBUF,
7045 _("Posting-Character set \"%s\" is unsupported, using UTF-8"),
7046 ps->posting_charmap);
7047 q_status_message(SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
7048 fs_give((void **) &ps->posting_charmap);
7049 ps->posting_charmap = cpystr("UTF-8");
7052 else
7053 ps->posting_charmap = cpystr("UTF-8");
7054 #ifndef _WINDOWS
7056 #endif /* ! _WINDOWS */
7060 #define FIXED_COMMENT _("(fixed)")
7061 #define DEFAULT_COMMENT _("(default)")
7062 #define OVERRIDE_COMMENT _("(overridden)")
7065 feature_gets_an_x(struct pine *ps, struct variable *var, FEATURE_S *feature,
7066 char **comment, EditWhich ew)
7068 char **lval, **lvalexc, **lvalnorm;
7069 char *def = DEFAULT_COMMENT;
7070 int j, done = 0;
7071 int feature_fixed_on = 0, feature_fixed_off = 0;
7073 if(comment)
7074 *comment = NULL;
7076 lval = LVAL(var, ew);
7077 lvalexc = LVAL(var, ps->ew_for_except_vars);
7078 lvalnorm = LVAL(var, Main);
7080 /* feature value is administratively fixed */
7081 if((j = feature_in_list(var->fixed_val.l, feature->name)) != 0){
7082 if(j == 1)
7083 feature_fixed_on++;
7084 else if(j == -1)
7085 feature_fixed_off++;
7087 done++;
7088 if(comment)
7089 *comment = FIXED_COMMENT;
7093 * We have an exceptions config setting which overrides anything
7094 * we do here, in the normal config.
7096 if(!done &&
7097 ps->ew_for_except_vars != Main && ew == Main &&
7098 feature_in_list(lvalexc, feature->name)){
7099 done++;
7100 if(comment)
7101 *comment = OVERRIDE_COMMENT;
7105 * Feature is set On in default but not set here.
7107 if(!done &&
7108 !feature_in_list(lval, feature->name) &&
7109 ((feature_in_list(var->global_val.l, feature->name) == 1) ||
7110 ((ps->ew_for_except_vars != Main &&
7111 ew == ps->ew_for_except_vars &&
7112 feature_in_list(lvalnorm, feature->name) == 1)))){
7113 done = 17;
7114 if(comment)
7115 *comment = def;
7118 if(!done &&
7119 feature->defval &&
7120 !feature_in_list(lval, feature->name) &&
7121 !feature_in_list(var->global_val.l, feature->name) &&
7122 (ps->ew_for_except_vars == Main ||
7123 ew != ps->ew_for_except_vars ||
7124 !feature_in_list(lvalnorm, feature->name))){
7125 done = 17;
7126 if(comment)
7127 *comment = def;
7130 return(feature_fixed_on ||
7131 (!feature_fixed_off &&
7132 (done == 17 ||
7133 test_feature(lval, feature->name,
7134 test_old_growth_bits(ps, feature->id)))));
7137 #if !defined(_WINDOWS) || defined(WINDOWS_UNIXSSL_CERTS)
7138 void
7139 set_system_certs_path(struct pine *ps)
7141 char **l;
7143 for (l = ps->vars[V_SSLCAPATH].current_val.l; l && *l; l++){
7144 if(is_absolute_path(*l)
7145 && can_access(*l, ACCESS_EXISTS) == 0
7146 && can_access(*l, READ_ACCESS) == 0){
7147 mail_parameters(NULL, SET_SSLCAPATH, (void *) *l);
7148 break;
7154 void
7155 set_system_certs_container(struct pine *ps)
7157 char **l;
7159 for (l = ps->vars[V_SSLCAFILE].current_val.l; l && *l; l++){
7160 if(is_absolute_path(*l)
7161 && can_access(*l, ACCESS_EXISTS) == 0
7162 && can_access(*l, READ_ACCESS) == 0){
7163 mail_parameters(NULL, SET_SSLCAFILE, (void *) *l);
7164 break;
7169 void
7170 set_user_certs_path(struct pine *ps)
7172 char **l;
7174 for (l = ps->vars[V_USERSSLCAPATH].current_val.l; l && *l; l++){
7175 if(is_absolute_path(*l)
7176 && can_access(*l, ACCESS_EXISTS) == 0
7177 && can_access(*l, READ_ACCESS) == 0){
7178 mail_parameters(NULL, SET_SSLAPPCAPATH, (void *) *l);
7179 break;
7185 void
7186 set_user_certs_container(struct pine *ps)
7188 char **l;
7190 for (l = ps->vars[V_USERSSLCAFILE].current_val.l; l && *l; l++){
7191 if(is_absolute_path(*l)
7192 && can_access(*l, ACCESS_EXISTS) == 0
7193 && can_access(*l, READ_ACCESS) == 0){
7194 mail_parameters(NULL, SET_SSLAPPCAFILE, (void *) *l);
7195 break;
7199 #endif
7202 longest_feature_comment(struct pine *ps, EditWhich ew)
7204 int lc = 0;
7206 lc = MAX(lc, utf8_width(FIXED_COMMENT));
7207 lc = MAX(lc, utf8_width(DEFAULT_COMMENT));
7208 if(ps->ew_for_except_vars != Main && ew == Main)
7209 lc = MAX(lc, utf8_width(OVERRIDE_COMMENT));
7211 return(lc);
7215 void
7216 toggle_feature(struct pine *ps, struct variable *var, FEATURE_S *f,
7217 int just_flip_value, EditWhich ew)
7219 char **vp, *p, **lval, ***alval;
7220 int og, on_before, was_set;
7221 char *err;
7222 long l;
7224 og = test_old_growth_bits(ps, f->id);
7227 * if this feature is in the fixed set, or old-growth is in the fixed
7228 * set and this feature is in the old-growth set, don't alter it...
7230 for(vp = var->fixed_val.l; vp && *vp; vp++){
7231 p = (struncmp(*vp, "no-", 3)) ? *vp : *vp + 3;
7232 if(!strucmp(p, f->name) || (og && !strucmp(p, "old-growth"))){
7233 q_status_message(SM_ORDER, 3, 3,
7234 /* TRANSLATORS: In the configuration screen, telling the user we
7235 can't change this option because the system administrator
7236 prohibits it. */
7237 _("Can't change value fixed by sys-admin."));
7238 return;
7242 on_before = F_ON(f->id, ps);
7244 lval = LVAL(var, ew);
7245 alval = ALVAL(var, ew);
7246 if(just_flip_value)
7247 was_set = test_feature(lval, f->name, og);
7248 else
7249 was_set = feature_gets_an_x(ps, var, f, NULL, ew);
7251 if(alval)
7252 set_feature(alval, f->name, !was_set);
7254 set_feature_list_current_val(var);
7255 process_feature_list(ps, var->current_val.l, 0, 0, 0);
7258 * Handle any features that need special attention here...
7260 if(on_before != F_ON(f->id, ps))
7261 switch(f->id){
7262 case F_QUOTE_ALL_FROMS :
7263 mail_parameters(NULL,SET_FROMWIDGET,F_ON(f->id,ps) ? VOIDT : NIL);
7264 break;
7266 case F_FAKE_NEW_IN_NEWS :
7267 if(IS_NEWS(ps->mail_stream))
7268 q_status_message(SM_ORDER | SM_DING, 3, 4,
7269 "news-approximates-new-status won't affect current newsgroup until next open");
7271 break;
7273 case F_COLOR_LINE_IMPORTANT :
7274 case F_DATES_TO_LOCAL :
7275 clear_index_cache(ps->mail_stream, 0);
7276 break;
7278 case F_DISABLE_INDEX_LOCALE_DATES :
7279 reset_index_format();
7280 clear_index_cache(ps->mail_stream, 0);
7281 break;
7283 case F_MARK_FOR_CC :
7284 clear_index_cache(ps->mail_stream, 0);
7285 if(THREADING() && sp_viewing_a_thread(ps->mail_stream))
7286 unview_thread(ps, ps->mail_stream, ps->msgmap);
7288 break;
7290 case F_HIDE_NNTP_PATH :
7291 mail_parameters(NULL, SET_NNTPHIDEPATH,
7292 F_ON(f->id, ps) ? VOIDT : NIL);
7293 break;
7295 case F_MAILDROPS_PRESERVE_STATE :
7296 mail_parameters(NULL, SET_SNARFPRESERVE,
7297 F_ON(f->id, ps) ? VOIDT : NIL);
7298 break;
7300 case F_DISABLE_SHARED_NAMESPACES :
7301 mail_parameters(NULL, SET_DISABLEAUTOSHAREDNS,
7302 F_ON(f->id, ps) ? VOIDT : NIL);
7303 break;
7305 case F_QUELL_LOCK_FAILURE_MSGS :
7306 mail_parameters(NULL, SET_LOCKEACCESERROR,
7307 F_ON(f->id, ps) ? VOIDT : NIL);
7308 break;
7310 case F_MULNEWSRC_HOSTNAMES_AS_TYPED :
7311 l = F_ON(f->id, ps) ? 0L : 1L;
7312 mail_parameters(NULL, SET_NEWSRCCANONHOST, (void *) l);
7313 break;
7315 case F_QUELL_INTERNAL_MSG :
7316 mail_parameters(NULL, SET_USERHASNOLIFE,
7317 F_ON(f->id, ps) ? VOIDT : NIL);
7318 break;
7320 case F_DISABLE_SETLOCALE_COLLATE :
7321 set_collation(F_OFF(F_DISABLE_SETLOCALE_COLLATE, ps), 1);
7322 break;
7324 #ifndef _WINDOWS
7325 case F_USE_SYSTEM_TRANS :
7326 err = NULL;
7327 reset_character_set_stuff(&err);
7328 if(err){
7329 q_status_message(SM_ORDER | SM_DING, 3, 4, err);
7330 fs_give((void **) &err);
7333 break;
7334 #endif /* ! _WINDOWS */
7336 case F_ENABLE_INCOMING_CHECKING :
7337 if(!on_before && F_OFF(F_ENABLE_INCOMING, ps))
7338 q_status_message(SM_ORDER, 0, 3, _("This option has no effect without Enable-Incoming-Folders"));
7340 clear_incoming_valid_bits();
7341 break;
7343 case F_INCOMING_CHECKING_TOTAL :
7344 case F_INCOMING_CHECKING_RECENT :
7345 if(!on_before && F_OFF(F_ENABLE_INCOMING_CHECKING, ps))
7346 q_status_message(SM_ORDER, 0, 3, _("This option has no effect without Enable-Incoming-Folders-Checking"));
7348 clear_incoming_valid_bits();
7349 break;
7351 case F_THREAD_SORTS_BY_ARRIVAL :
7352 clear_index_cache(ps->mail_stream, 0);
7353 refresh_sort(ps->mail_stream, sp_msgmap(ps->mail_stream), SRT_NON);
7354 break;
7356 #ifdef SMIME
7357 case F_DONT_DO_SMIME :
7358 smime_deinit();
7359 break;
7361 #ifdef APPLEKEYCHAIN
7362 case F_PUBLICCERTS_IN_KEYCHAIN :
7363 smime_deinit();
7364 break;
7365 #endif
7366 #endif
7368 default :
7369 break;
7375 * Returns 1 -- Feature is in the list and positive
7376 * 0 -- Feature is not in the list at all
7377 * -1 -- Feature is in the list and negative (no-)
7380 feature_in_list(char **l, char *f)
7382 char *p;
7383 int rv = 0, forced_off;
7385 for(; l && *l; l++){
7386 p = (forced_off = !struncmp(*l, "no-", 3)) ? *l + 3 : *l;
7387 if(!strucmp(p, f))
7388 rv = forced_off ? -1 : 1;
7391 return(rv);
7396 * test_feature - runs thru a feature list, and returns:
7397 * 1 if feature explicitly set and matches 'v'
7398 * 0 if feature not explicitly set *or* doesn't match 'v'
7401 test_feature(char **l, char *f, int g)
7403 char *p;
7404 int rv = 0, forced_off;
7406 for(; l && *l; l++){
7407 p = (forced_off = !struncmp(*l, "no-", 3)) ? *l + 3 : *l;
7408 if(!strucmp(p, f))
7409 rv = !forced_off;
7410 else if(g && !strucmp(p, "old-growth"))
7411 rv = !forced_off;
7414 return(rv);
7418 void
7419 set_feature(char ***l, char *f, int v)
7421 char **list = l ? *l : NULL, newval[256];
7422 int count = 0;
7424 snprintf(newval, sizeof(newval), "%s%s", v ? "" : "no-", f);
7425 for(; list && *list; list++, count++)
7426 if((**list == '\0') /* anything can replace an empty value */
7427 || !strucmp(((!struncmp(*list, "no-", 3)) ? *list + 3 : *list), f)){
7428 fs_give((void **)list); /* replace with new value */
7429 *list = cpystr(newval);
7430 return;
7434 * if we got here, we didn't find it in the list, so grow the list
7435 * and add it..
7437 if(!*l)
7438 *l = (char **)fs_get((count + 2) * sizeof(char *));
7439 else
7440 fs_resize((void **)l, (count + 2) * sizeof(char *));
7442 (*l)[count] = cpystr(newval);
7443 (*l)[count + 1] = NULL;
7448 reset_character_set_stuff(char **err)
7450 int use_system = 0;
7451 char buf[1000];
7453 if(err)
7454 *err = NULL;
7456 if(ps_global->display_charmap)
7457 fs_give((void **) &ps_global->display_charmap);
7459 if(ps_global->keyboard_charmap)
7460 fs_give((void **) &ps_global->keyboard_charmap);
7462 if(ps_global->posting_charmap)
7463 fs_give((void **) &ps_global->posting_charmap);
7465 #ifdef _WINDOWS
7466 ps_global->display_charmap = cpystr("UTF-8");
7467 #else /* UNIX */
7468 if(ps_global->VAR_CHAR_SET)
7469 ps_global->display_charmap = cpystr(ps_global->VAR_CHAR_SET);
7470 else{
7471 #if HAVE_LANGINFO_H && defined(CODESET)
7472 ps_global->display_charmap = cpystr(nl_langinfo_codeset_wrapper());
7473 #else
7474 ps_global->display_charmap = cpystr("UTF-8");
7475 #endif
7477 #endif /* UNIX */
7479 if(!ps_global->display_charmap)
7480 ps_global->display_charmap = cpystr("US-ASCII");
7482 #ifdef _WINDOWS
7483 ps_global->keyboard_charmap = cpystr("UTF-8");
7484 #else /* UNIX */
7485 if(ps_global->VAR_KEY_CHAR_SET)
7486 ps_global->keyboard_charmap = cpystr(ps_global->VAR_KEY_CHAR_SET);
7487 else
7488 ps_global->keyboard_charmap = cpystr(ps_global->display_charmap);
7490 if(!ps_global->keyboard_charmap)
7491 ps_global->keyboard_charmap = cpystr("US-ASCII");
7493 if(F_ON(F_USE_SYSTEM_TRANS, ps_global)){
7494 #if PREREQ_FOR_SYS_TRANSLATION
7495 use_system++;
7496 /* This modifies its arguments */
7497 if(setup_for_input_output(use_system, &ps_global->display_charmap,
7498 &ps_global->keyboard_charmap,
7499 &ps_global->input_cs, (err && *err) ? NULL : err) == -1)
7500 return -1;
7501 #endif
7503 #endif /* UNIX */
7505 if(!use_system){
7506 if(setup_for_input_output(use_system, &ps_global->display_charmap,
7507 &ps_global->keyboard_charmap,
7508 &ps_global->input_cs, (err && *err) ? NULL : err) == -1)
7509 return -1;
7512 if(!use_system && ps_global->VAR_POST_CHAR_SET){
7513 ps_global->posting_charmap = cpystr(ps_global->VAR_POST_CHAR_SET);
7514 if(!posting_charset_is_supported(ps_global->posting_charmap)){
7515 if(err && !*err){
7516 snprintf(buf, sizeof(buf),
7517 _("Posting-Character-Set \"%s\" is unsupported, using UTF-8"),
7518 ps_global->posting_charmap);
7519 *err = cpystr(buf);
7522 fs_give((void **) &ps_global->posting_charmap);
7523 ps_global->posting_charmap = cpystr("UTF-8");
7526 else{
7527 if(use_system && ps_global->VAR_POST_CHAR_SET
7528 && strucmp(ps_global->VAR_POST_CHAR_SET, "UTF-8"))
7529 if(err && !*err)
7530 *err = cpystr(_("Posting-Character-Set is ignored with Use-System-Translation turned on"));
7532 ps_global->posting_charmap = cpystr("UTF-8");
7535 set_locale_charmap(ps_global->keyboard_charmap);
7537 return(0);
7542 * Given a single printer string from the config file, returns pointers
7543 * to alloc'd strings containing the printer nickname, the command,
7544 * the init string, the trailer string, everything but the nickname string,
7545 * and everything but the command string. All_but_cmd includes the trailing
7546 * space at the end (the one before the command) but all_but_nick does not
7547 * include the leading space (the one before the [).
7548 * If you pass in a pointer it is guaranteed to come back pointing to an
7549 * allocated string, even if it is just an empty string. It is ok to pass
7550 * NULL for any of the six return strings.
7552 void
7553 parse_printer(char *input, char **nick, char **cmd, char **init, char **trailer,
7554 char **all_but_nick, char **all_but_cmd)
7556 char *p, *q, *start, *saved_options = NULL;
7557 int tmpsave, cnt;
7559 if(!input)
7560 input = "";
7562 if(nick || all_but_nick){
7563 if((p = srchstr(input, " [")) != NULL){
7564 if(all_but_nick)
7565 *all_but_nick = cpystr(p+1);
7567 if(nick){
7568 while(p-1 > input && isspace((unsigned char)*(p-1)))
7569 p--;
7571 tmpsave = *p;
7572 *p = '\0';
7573 *nick = cpystr(input);
7574 *p = tmpsave;
7577 else{
7578 if(nick)
7579 *nick = cpystr("");
7581 if(all_but_nick)
7582 *all_but_nick = cpystr(input);
7586 if((p = srchstr(input, "] ")) != NULL){
7588 ++p;
7589 }while(isspace((unsigned char)*p));
7591 tmpsave = *p;
7592 *p = '\0';
7593 saved_options = cpystr(input);
7594 *p = tmpsave;
7596 else
7597 p = input;
7599 if(cmd)
7600 *cmd = cpystr(p);
7602 if(init){
7603 if(saved_options && (p = srchstr(saved_options, "INIT="))){
7604 start = p + strlen("INIT=");
7605 for(cnt=0, p = start; *p && *(p+1) && isxpair(p); p += 2)
7606 cnt++;
7608 q = *init = (char *)fs_get((cnt + 1) * sizeof(char));
7609 for(p = start; *p && *(p+1) && isxpair(p); p += 2)
7610 *q++ = read_hex(p);
7612 *q = '\0';
7614 else
7615 *init = cpystr("");
7618 if(trailer){
7619 if(saved_options && (p = srchstr(saved_options, "TRAILER="))){
7620 start = p + strlen("TRAILER=");
7621 for(cnt=0, p = start; *p && *(p+1) && isxpair(p); p += 2)
7622 cnt++;
7624 q = *trailer = (char *)fs_get((cnt + 1) * sizeof(char));
7625 for(p = start; *p && *(p+1) && isxpair(p); p += 2)
7626 *q++ = read_hex(p);
7628 *q = '\0';
7630 else
7631 *trailer = cpystr("");
7634 if(all_but_cmd){
7635 if(saved_options)
7636 *all_but_cmd = saved_options;
7637 else
7638 *all_but_cmd = cpystr("");
7640 else if(saved_options)
7641 fs_give((void **)&saved_options);
7646 copy_pinerc(char *local, char *remote, char **err_msg)
7648 return(copy_localfile_to_remotefldr(RemImap, local, remote,
7649 REMOTE_PINERC_SUBTYPE,
7650 err_msg));
7655 copy_abook(char *local, char *remote, char **err_msg)
7657 return(copy_localfile_to_remotefldr(RemImap, local, remote,
7658 REMOTE_ABOOK_SUBTYPE,
7659 err_msg));
7664 * Copy local file to remote folder.
7666 * Args remotetype -- type of remote folder
7667 * local -- name of local file
7668 * remote -- name of remote folder
7669 * subtype --
7671 * Returns 0 on success.
7674 copy_localfile_to_remotefldr(RemType remotetype, char *local, char *remote,
7675 char *subtype, char **err_msg)
7677 int retfail = -1;
7678 unsigned flags;
7679 REMDATA_S *rd;
7681 dprint((9, "copy_localfile_to_remotefldr(%s,%s)\n",
7682 local ? local : "<null>",
7683 remote ? remote : "<null>"));
7685 *err_msg = (char *)fs_get(MAXPATH * sizeof(char));
7687 if(!local || !*local){
7688 snprintf(*err_msg, MAXPATH, _("No local file specified"));
7689 return(retfail);
7692 if(!remote || !*remote){
7693 snprintf(*err_msg, MAXPATH, _("No remote folder specified"));
7694 return(retfail);
7697 if(!IS_REMOTE(remote)){
7698 snprintf(*err_msg, MAXPATH, _("Remote folder name \"%s\" %s"), remote,
7699 (*remote != '{') ? _("must begin with \"{\"") : _("not valid"));
7700 return(retfail);
7703 if(IS_REMOTE(local)){
7704 snprintf(*err_msg, MAXPATH, _("First argument \"%s\" must be a local filename"),
7705 local);
7706 return(retfail);
7709 if(can_access(local, ACCESS_EXISTS) != 0){
7710 snprintf(*err_msg, MAXPATH, _("Local file \"%s\" does not exist"), local);
7711 return(retfail);
7714 if(can_access(local, READ_ACCESS) != 0){
7715 snprintf(*err_msg, MAXPATH, _("Can't read local file \"%s\": %s"),
7716 local, error_description(errno));
7717 return(retfail);
7721 * Check if remote folder exists and create it if it doesn't.
7723 flags = 0;
7724 rd = rd_create_remote(remotetype, remote, subtype,
7725 &flags, _("Error: "), _("Can't copy to remote folder."));
7727 if(!rd || rd->access == NoExists){
7728 snprintf(*err_msg, MAXPATH, _("Can't create \"%s\""), remote);
7729 if(rd)
7730 rd_free_remdata(&rd);
7732 return(retfail);
7735 if(rd->access == MaybeRorW)
7736 rd->access = ReadWrite;
7738 rd->flags |= (NO_META_UPDATE | DO_REMTRIM);
7739 rd->lf = cpystr(local);
7741 rd_open_remote(rd);
7742 if(!rd_stream_exists(rd)){
7743 snprintf(*err_msg, MAXPATH, _("Can't open remote folder \"%s\""), rd->rn);
7744 rd_free_remdata(&rd);
7745 return(retfail);
7748 if(rd_remote_is_readonly(rd)){
7749 snprintf(*err_msg, MAXPATH, _("Remote folder \"%s\" is readonly"), rd->rn);
7750 rd_free_remdata(&rd);
7751 return(retfail);
7754 switch(rd->type){
7755 case RemImap:
7757 * Empty folder, add a header msg.
7759 if(rd->t.i.stream->nmsgs == 0){
7760 if(rd_init_remote(rd, 1) != 0){
7761 snprintf(*err_msg, MAXPATH,
7762 _("Failed initializing remote folder \"%s\", check debug file"),
7763 rd->rn);
7764 rd_free_remdata(&rd);
7765 return(retfail);
7769 fs_give((void **)err_msg);
7770 *err_msg = NULL;
7771 if(rd_chk_for_hdr_msg(&(rd->t.i.stream), rd, err_msg)){
7772 rd_free_remdata(&rd);
7773 return(retfail);
7776 break;
7778 default:
7779 break;
7782 if(rd_update_remote(rd, NULL) != 0){
7783 snprintf(*err_msg, MAXPATH, _("Error copying to remote folder \"%s\""), rd->rn);
7784 rd_free_remdata(&rd);
7785 return(retfail);
7788 rd_update_metadata(rd, NULL);
7789 rd_close_remdata(&rd);
7791 fs_give((void **)err_msg);
7792 return(0);
7796 /*----------------------------------------------------------------------
7797 Panic pine - call on detected programmatic errors to exit pine, with arg
7799 Input: message -- printf styule string for panic message (see above)
7800 arg -- argument for printf string
7802 Result: The various tty modes are restored
7803 If debugging is active a core dump will be generated
7804 Exits Pine
7805 ----*/
7806 void
7807 panic1(char *message, char *arg)
7809 #define SIZEOFBUF 1001
7810 char buf1[SIZEOFBUF], buf2[SIZEOFBUF];
7812 snprintf(buf1, sizeof(buf1), "%.*s", (int) MAX(SIZEOFBUF - 1 - strlen(message), 0), arg);
7813 snprintf(buf2, sizeof(buf2), message, buf1);
7814 alpine_panic(buf2);
7821 HelpType
7822 config_help(int var, int feature)
7824 switch(var){
7825 case V_FEATURE_LIST :
7826 return(feature_list_help(feature));
7827 break;
7829 case V_PERSONAL_NAME :
7830 return(h_config_pers_name);
7831 case V_USER_ID :
7832 return(h_config_user_id);
7833 case V_USER_DOMAIN :
7834 return(h_config_user_dom);
7835 case V_SMTP_SERVER :
7836 return(h_config_smtp_server);
7837 case V_NNTP_SERVER :
7838 return(h_config_nntp_server);
7839 case V_INBOX_PATH :
7840 return(h_config_inbox_path);
7841 case V_PRUNED_FOLDERS :
7842 return(h_config_pruned_folders);
7843 case V_DEFAULT_FCC :
7844 return(h_config_default_fcc);
7845 case V_DEFAULT_SAVE_FOLDER :
7846 return(h_config_def_save_folder);
7847 case V_POSTPONED_FOLDER :
7848 return(h_config_postponed_folder);
7849 case V_READ_MESSAGE_FOLDER :
7850 return(h_config_read_message_folder);
7851 case V_FORM_FOLDER :
7852 return(h_config_form_folder);
7853 case V_ARCHIVED_FOLDERS :
7854 return(h_config_archived_folders);
7855 case V_SIGNATURE_FILE :
7856 return(h_config_signature_file);
7857 case V_LITERAL_SIG :
7858 return(h_config_literal_sig);
7859 case V_INIT_CMD_LIST :
7860 return(h_config_init_cmd_list);
7861 case V_COMP_HDRS :
7862 return(h_config_comp_hdrs);
7863 case V_CUSTOM_HDRS :
7864 return(h_config_custom_hdrs);
7865 case V_VIEW_HEADERS :
7866 return(h_config_viewer_headers);
7867 case V_VIEW_MARGIN_LEFT :
7868 return(h_config_viewer_margin_left);
7869 case V_VIEW_MARGIN_RIGHT :
7870 return(h_config_viewer_margin_right);
7871 case V_QUOTE_SUPPRESSION :
7872 return(h_config_quote_suppression);
7873 case V_SAVED_MSG_NAME_RULE :
7874 return(h_config_saved_msg_name_rule);
7875 case V_FCC_RULE :
7876 return(h_config_fcc_rule);
7877 case V_SORT_KEY :
7878 return(h_config_sort_key);
7879 case V_AB_SORT_RULE :
7880 return(h_config_ab_sort_rule);
7881 case V_FLD_SORT_RULE :
7882 return(h_config_fld_sort_rule);
7883 case V_POST_CHAR_SET :
7884 return(h_config_post_char_set);
7885 case V_UNK_CHAR_SET :
7886 return(h_config_unk_char_set);
7887 #ifndef _WINDOWS
7888 case V_KEY_CHAR_SET :
7889 return(h_config_key_char_set);
7890 case V_CHAR_SET :
7891 return(h_config_char_set);
7892 #endif /* ! _WINDOWS */
7893 case V_EDITOR :
7894 return(h_config_editor);
7895 case V_SPELLER :
7896 return(h_config_speller);
7897 #ifdef _WINDOWS
7898 case V_DICTIONARY :
7899 return(h_config_aspell_dictionary);
7900 #endif /* _WINDOWS */
7901 case V_DISPLAY_FILTERS :
7902 return(h_config_display_filters);
7903 case V_SEND_FILTER :
7904 return(h_config_sending_filter);
7905 case V_ALT_ADDRS :
7906 return(h_config_alt_addresses);
7907 case V_KEYWORDS :
7908 return(h_config_keywords);
7909 case V_KW_BRACES :
7910 return(h_config_kw_braces);
7911 case V_OPENING_SEP :
7912 return(h_config_opening_sep);
7913 case V_KW_COLORS :
7914 return(h_config_kw_color);
7915 case V_ABOOK_FORMATS :
7916 return(h_config_abook_formats);
7917 case V_INDEX_FORMAT :
7918 return(h_config_index_format);
7919 case V_INCCHECKTIMEO :
7920 return(h_config_incoming_timeo);
7921 case V_INCCHECKINTERVAL :
7922 return(h_config_incoming_interv);
7923 case V_INC2NDCHECKINTERVAL :
7924 return(h_config_incoming_second_interv);
7925 case V_INCCHECKLIST :
7926 return(h_config_incoming_list);
7927 case V_OVERLAP :
7928 return(h_config_viewer_overlap);
7929 case V_MAXREMSTREAM :
7930 return(h_config_maxremstream);
7931 case V_PERMLOCKED :
7932 return(h_config_permlocked);
7933 case V_MARGIN :
7934 return(h_config_scroll_margin);
7935 case V_DEADLETS :
7936 return(h_config_deadlets);
7937 case V_FILLCOL :
7938 return(h_config_composer_wrap_column);
7939 case V_TCPOPENTIMEO :
7940 return(h_config_tcp_open_timeo);
7941 case V_TCPREADWARNTIMEO :
7942 return(h_config_tcp_readwarn_timeo);
7943 case V_TCPWRITEWARNTIMEO :
7944 return(h_config_tcp_writewarn_timeo);
7945 case V_TCPQUERYTIMEO :
7946 return(h_config_tcp_query_timeo);
7947 case V_QUITQUERYTIMEO :
7948 return(h_config_quit_query_timeo);
7949 case V_RSHOPENTIMEO :
7950 return(h_config_rsh_open_timeo);
7951 case V_SSHOPENTIMEO :
7952 return(h_config_ssh_open_timeo);
7953 case V_USERINPUTTIMEO :
7954 return(h_config_user_input_timeo);
7955 case V_REMOTE_ABOOK_VALIDITY :
7956 return(h_config_remote_abook_validity);
7957 case V_REMOTE_ABOOK_HISTORY :
7958 return(h_config_remote_abook_history);
7959 case V_INCOMING_FOLDERS :
7960 return(h_config_incoming_folders);
7961 case V_FOLDER_SPEC :
7962 return(h_config_folder_spec);
7963 case V_NEWS_SPEC :
7964 return(h_config_news_spec);
7965 case V_ADDRESSBOOK :
7966 return(h_config_address_book);
7967 case V_GLOB_ADDRBOOK :
7968 return(h_config_glob_addrbook);
7969 case V_LAST_VERS_USED :
7970 return(h_config_last_vers);
7971 case V_SENDMAIL_PATH :
7972 return(h_config_sendmail_path);
7973 case V_OPER_DIR :
7974 return(h_config_oper_dir);
7975 case V_RSHPATH :
7976 return(h_config_rshpath);
7977 case V_RSHCMD :
7978 return(h_config_rshcmd);
7979 case V_SSHPATH :
7980 return(h_config_sshpath);
7981 case V_SSHCMD :
7982 return(h_config_sshcmd);
7983 case V_NEW_VER_QUELL :
7984 return(h_config_new_ver_quell);
7985 case V_DISABLE_DRIVERS :
7986 return(h_config_disable_drivers);
7987 case V_DISABLE_AUTHS :
7988 return(h_config_disable_auths);
7989 #ifdef DF_ENCRYPTION_RANGE
7990 case V_ENCRYPTION_RANGE :
7991 return(h_config_encryption_range);
7992 #endif /* DF_ENCRYPTION_RANGE */
7993 case V_REMOTE_ABOOK_METADATA :
7994 return(h_config_abook_metafile);
7995 case V_REPLY_STRING :
7996 return(h_config_reply_indent_string);
7997 case V_WORDSEPS :
7998 return(h_config_wordseps);
7999 case V_QUOTE_REPLACE_STRING :
8000 return(h_config_quote_replace_string);
8001 case V_REPLY_INTRO :
8002 return(h_config_reply_intro);
8003 case V_EMPTY_HDR_MSG :
8004 return(h_config_empty_hdr_msg);
8005 case V_STATUS_MSG_DELAY :
8006 return(h_config_status_msg_delay);
8007 case V_ACTIVE_MSG_INTERVAL :
8008 return(h_config_active_msg_interval);
8009 case V_MAILCHECK :
8010 return(h_config_mailcheck);
8011 case V_MAILCHECKNONCURR :
8012 return(h_config_mailchecknoncurr);
8013 case V_MAILDROPCHECK :
8014 return(h_config_maildropcheck);
8015 case V_NNTPRANGE :
8016 return(h_config_nntprange);
8017 case V_NEWS_ACTIVE_PATH :
8018 return(h_config_news_active);
8019 case V_NEWS_SPOOL_DIR :
8020 return(h_config_news_spool);
8021 case V_IMAGE_VIEWER :
8022 return(h_config_image_viewer);
8023 case V_USE_ONLY_DOMAIN_NAME :
8024 return(h_config_domain_name);
8025 case V_LAST_TIME_PRUNE_QUESTION :
8026 return(h_config_prune_date);
8027 case V_UPLOAD_CMD:
8028 return(h_config_upload_cmd);
8029 case V_UPLOAD_CMD_PREFIX:
8030 return(h_config_upload_prefix);
8031 case V_DOWNLOAD_CMD:
8032 return(h_config_download_cmd);
8033 case V_DOWNLOAD_CMD_PREFIX:
8034 return(h_config_download_prefix);
8035 case V_GOTO_DEFAULT_RULE:
8036 return(h_config_goto_default);
8037 case V_INCOMING_STARTUP:
8038 return(h_config_inc_startup);
8039 case V_PRUNING_RULE:
8040 return(h_config_pruning_rule);
8041 case V_REOPEN_RULE:
8042 return(h_config_reopen_rule);
8043 case V_THREAD_DISP_STYLE:
8044 return(h_config_thread_disp_style);
8045 case V_THREAD_INDEX_STYLE:
8046 return(h_config_thread_index_style);
8047 case V_THREAD_MORE_CHAR:
8048 return(h_config_thread_indicator_char);
8049 case V_THREAD_EXP_CHAR:
8050 return(h_config_thread_exp_char);
8051 case V_THREAD_LASTREPLY_CHAR:
8052 return(h_config_thread_lastreply_char);
8053 case V_MAILCAP_PATH :
8054 return(h_config_mailcap_path);
8055 case V_MIMETYPE_PATH :
8056 return(h_config_mimetype_path);
8057 #if !defined(_WINDOWS) || defined(WINDOWS_UNIXSSL_CERTS)
8058 case V_SSLCAPATH :
8059 return(h_config_system_certs_path);
8060 case V_SSLCAFILE :
8061 return(h_config_system_certs_file);
8062 case V_USERSSLCAPATH :
8063 return(h_config_user_certs_path);
8064 case V_USERSSLCAFILE :
8065 return(h_config_user_certs_file);
8066 case V_SSLCIPHERS :
8067 return(h_config_ssl_ciphers);
8068 #endif
8069 #if !defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)
8070 case V_FIFOPATH :
8071 return(h_config_fifopath);
8072 #endif
8073 case V_NMW_WIDTH :
8074 return(h_config_newmailwidth);
8075 case V_NEWSRC_PATH :
8076 return(h_config_newsrc_path);
8077 case V_BROWSER :
8078 return(h_config_browser);
8079 case V_HISTORY :
8080 return(h_config_history);
8081 #if defined(DOS) || defined(OS2)
8082 case V_FILE_DIR :
8083 return(h_config_file_dir);
8084 #endif
8085 case V_NORM_FORE_COLOR :
8086 case V_NORM_BACK_COLOR :
8087 return(h_config_normal_color);
8088 case V_REV_FORE_COLOR :
8089 case V_REV_BACK_COLOR :
8090 return(h_config_reverse_color);
8091 case V_TITLE_FORE_COLOR :
8092 case V_TITLE_BACK_COLOR :
8093 return(h_config_title_color);
8094 case V_TITLECLOSED_FORE_COLOR :
8095 case V_TITLECLOSED_BACK_COLOR :
8096 return(h_config_titleclosed_color);
8097 case V_FOLDER_FORE_COLOR:
8098 return(h_config_folder_color);
8099 case V_DIRECTORY_FORE_COLOR:
8100 return(h_config_directory_color);
8101 case V_FOLDER_LIST_FORE_COLOR:
8102 return(h_config_folder_list_color);
8103 case V_STATUS_FORE_COLOR :
8104 case V_STATUS_BACK_COLOR :
8105 return(h_config_status_color);
8106 case V_SLCTBL_FORE_COLOR :
8107 case V_SLCTBL_BACK_COLOR :
8108 return(h_config_slctbl_color);
8109 case V_QUOTE1_FORE_COLOR :
8110 case V_QUOTE2_FORE_COLOR :
8111 case V_QUOTE3_FORE_COLOR :
8112 case V_QUOTE1_BACK_COLOR :
8113 case V_QUOTE2_BACK_COLOR :
8114 case V_QUOTE3_BACK_COLOR :
8115 return(h_config_quote_color);
8116 case V_INCUNSEEN_FORE_COLOR :
8117 case V_INCUNSEEN_BACK_COLOR :
8118 return(h_config_incunseen_color);
8119 case V_SIGNATURE_FORE_COLOR :
8120 case V_SIGNATURE_BACK_COLOR :
8121 return(h_config_signature_color);
8122 case V_PROMPT_FORE_COLOR :
8123 case V_PROMPT_BACK_COLOR :
8124 return(h_config_prompt_color);
8125 case V_HEADER_GENERAL_FORE_COLOR :
8126 case V_HEADER_GENERAL_BACK_COLOR :
8127 return(h_config_header_general_color);
8128 case V_IND_PLUS_FORE_COLOR :
8129 case V_IND_IMP_FORE_COLOR :
8130 case V_IND_DEL_FORE_COLOR :
8131 case V_IND_ANS_FORE_COLOR :
8132 case V_IND_NEW_FORE_COLOR :
8133 case V_IND_UNS_FORE_COLOR :
8134 case V_IND_REC_FORE_COLOR :
8135 case V_IND_FWD_FORE_COLOR :
8136 case V_IND_PLUS_BACK_COLOR :
8137 case V_IND_IMP_BACK_COLOR :
8138 case V_IND_DEL_BACK_COLOR :
8139 case V_IND_ANS_BACK_COLOR :
8140 case V_IND_NEW_BACK_COLOR :
8141 case V_IND_UNS_BACK_COLOR :
8142 case V_IND_REC_BACK_COLOR :
8143 case V_IND_FWD_BACK_COLOR :
8144 return(h_config_index_color);
8145 case V_IND_OP_FORE_COLOR :
8146 case V_IND_OP_BACK_COLOR :
8147 return(h_config_index_opening_color);
8148 case V_IND_SUBJ_FORE_COLOR :
8149 case V_IND_SUBJ_BACK_COLOR :
8150 return(h_config_index_subject_color);
8151 case V_IND_FROM_FORE_COLOR :
8152 case V_IND_FROM_BACK_COLOR :
8153 return(h_config_index_from_color);
8154 case V_IND_HIPRI_FORE_COLOR :
8155 case V_IND_HIPRI_BACK_COLOR :
8156 case V_IND_LOPRI_FORE_COLOR :
8157 case V_IND_LOPRI_BACK_COLOR :
8158 return(h_config_index_pri_color);
8159 case V_IND_ARR_FORE_COLOR :
8160 case V_IND_ARR_BACK_COLOR :
8161 return(h_config_index_arrow_color);
8162 case V_KEYLABEL_FORE_COLOR :
8163 case V_KEYLABEL_BACK_COLOR :
8164 return(h_config_keylabel_color);
8165 case V_KEYNAME_FORE_COLOR :
8166 case V_KEYNAME_BACK_COLOR :
8167 return(h_config_keyname_color);
8168 case V_METAMSG_FORE_COLOR :
8169 case V_METAMSG_BACK_COLOR :
8170 return(h_config_metamsg_color);
8171 case V_VIEW_HDR_COLORS :
8172 return(h_config_customhdr_color);
8173 case V_INDEX_TOKEN_COLORS :
8174 return(h_config_indextoken_color);
8175 case V_PRINTER :
8176 return(h_config_printer);
8177 case V_PERSONAL_PRINT_CATEGORY :
8178 return(h_config_print_cat);
8179 case V_PERSONAL_PRINT_COMMAND :
8180 return(h_config_print_command);
8181 case V_PAT_ROLES :
8182 return(h_config_pat_roles);
8183 case V_PAT_FILTS :
8184 return(h_config_pat_filts);
8185 case V_PAT_SCORES :
8186 return(h_config_pat_scores);
8187 case V_PAT_INCOLS :
8188 return(h_config_pat_incols);
8189 case V_PAT_OTHER :
8190 return(h_config_pat_other);
8191 case V_PAT_SRCH :
8192 return(h_config_pat_srch);
8193 case V_INDEX_COLOR_STYLE :
8194 return(h_config_index_color_style);
8195 case V_TITLEBAR_COLOR_STYLE :
8196 return(h_config_titlebar_color_style);
8197 #ifdef _WINDOWS
8198 case V_FONT_NAME :
8199 return(h_config_font_name);
8200 case V_FONT_SIZE :
8201 return(h_config_font_size);
8202 case V_FONT_STYLE :
8203 return(h_config_font_style);
8204 case V_FONT_CHAR_SET :
8205 return(h_config_font_char_set);
8206 case V_PRINT_FONT_NAME :
8207 return(h_config_print_font_name);
8208 case V_PRINT_FONT_SIZE :
8209 return(h_config_print_font_size);
8210 case V_PRINT_FONT_STYLE :
8211 return(h_config_print_font_style);
8212 case V_PRINT_FONT_CHAR_SET :
8213 return(h_config_print_font_char_set);
8214 case V_WINDOW_POSITION :
8215 return(h_config_window_position);
8216 case V_CURSOR_STYLE :
8217 return(h_config_cursor_style);
8218 #else
8219 case V_COLOR_STYLE :
8220 return(h_config_color_style);
8221 #endif
8222 #ifdef ENABLE_LDAP
8223 case V_LDAP_SERVERS :
8224 return(h_config_ldap_servers);
8225 #endif
8226 #ifdef SMIME
8227 case V_PUBLICCERT_DIR :
8228 return(h_config_smime_pubcertdir);
8229 case V_PUBLICCERT_CONTAINER :
8230 return(h_config_smime_pubcertcon);
8231 case V_PRIVATEKEY_DIR :
8232 return(h_config_smime_privkeydir);
8233 case V_PRIVATEKEY_CONTAINER :
8234 return(h_config_smime_privkeycon);
8235 case V_CACERT_DIR :
8236 return(h_config_smime_cacertdir);
8237 case V_CACERT_CONTAINER :
8238 return(h_config_smime_cacertcon);
8239 #endif
8240 case V_RSS_NEWS :
8241 return(h_config_rss_news);
8242 case V_RSS_WEATHER :
8243 return(h_config_rss_weather);
8244 case V_WP_INDEXHEIGHT :
8245 return(h_config_wp_indexheight);
8246 case V_WP_INDEXLINES :
8247 return(h_config_wp_indexlines);
8248 case V_WP_AGGSTATE :
8249 return(h_config_wp_aggstate);
8250 case V_WP_STATE :
8251 return(h_config_wp_state);
8252 case V_WP_COLUMNS :
8253 return(h_config_wp_columns);
8254 default :
8255 return(NO_HELP);
8261 * We don't want the user to be able to edit their pinerc and set
8262 * printer to whatever they want if personal-print-command is fixed.
8263 * So make sure printer is set to something legitimate. If it isn't,
8264 * set it to something standard and return non-zero.
8267 printer_value_check_and_adjust(void)
8269 char **tt;
8270 char aname[100], wname[100];
8271 int ok = 0;
8272 struct variable *vars = ps_global->vars;
8274 if(vars[V_PERSONAL_PRINT_COMMAND].is_fixed && !vars[V_PRINTER].is_fixed){
8275 strncpy(aname, ANSI_PRINTER, sizeof(aname));
8276 aname[sizeof(aname)-1] = '\0';
8277 strncat(aname, "-no-formfeed", sizeof(aname)-strlen(aname)-1);
8278 strncpy(wname, WYSE_PRINTER, sizeof(wname));
8279 wname[sizeof(wname)-1] = '\0';
8280 strncat(wname, "-no-formfeed", sizeof(wname)-strlen(wname)-1);
8281 if(strucmp(VAR_PRINTER, ANSI_PRINTER) == 0
8282 || strucmp(VAR_PRINTER, aname) == 0
8283 || strucmp(VAR_PRINTER, WYSE_PRINTER) == 0
8284 || strucmp(VAR_PRINTER, wname) == 0)
8285 ok++;
8286 else if(VAR_STANDARD_PRINTER && VAR_STANDARD_PRINTER[0]){
8287 for(tt = VAR_STANDARD_PRINTER; *tt; tt++)
8288 if(strucmp(VAR_PRINTER, *tt) == 0)
8289 break;
8291 if(*tt)
8292 ok++;
8295 if(!ok){
8296 char *val;
8297 struct variable *v;
8299 if(VAR_STANDARD_PRINTER && VAR_STANDARD_PRINTER[0])
8300 val = VAR_STANDARD_PRINTER[0];
8301 else
8302 val = ANSI_PRINTER;
8304 v = &vars[V_PRINTER];
8305 if(v->main_user_val.p)
8306 fs_give((void **)&v->main_user_val.p);
8307 if(v->post_user_val.p)
8308 fs_give((void **)&v->post_user_val.p);
8309 if(v->current_val.p)
8310 fs_give((void **)&v->current_val.p);
8312 v->main_user_val.p = cpystr(val);
8313 v->current_val.p = cpystr(val);
8317 return(!ok);
8320 #ifdef _WINDOWS
8321 #include <schannel.h>
8322 #include <Schnlsp.h>
8323 #else
8324 #include <openssl/ssl.h>
8325 #endif /* _WINDOWS */
8327 char **
8328 get_supported_options(void)
8330 char **config;
8331 DRIVER *d;
8332 AUTHENTICATOR *a;
8333 char *title = _("Supported features in this Alpine");
8334 char sbuf[MAX_SCREEN_COLS+1], tmp[128];
8335 int cnt, alcnt, len, cols, disabled, any_disabled = 0;
8338 * Line count:
8339 * Title + blank = 2
8340 * SSL Title + SSL lines + blank = 5
8341 * Auth title + blank = 2
8342 * Driver title + blank = 2
8343 * LDAP title + LDAP line = 2
8344 * Disabled explanation + blank line = 4
8345 * end = 1
8347 cnt = 18;
8348 for(a = mail_lookup_auth(1); a; a = a->next)
8349 cnt++;
8350 for(d = (DRIVER *)mail_parameters(NIL, GET_DRIVERS, NIL);
8351 d; d = d->next)
8352 cnt++;
8354 alcnt = cnt;
8355 config = (char **) fs_get(alcnt * sizeof(char *));
8356 memset(config, 0, alcnt * sizeof(char *));
8358 cols = ps_global->ttyo ? ps_global->ttyo->screen_cols : 0;
8359 len = utf8_width(title);
8360 snprintf(sbuf, sizeof(sbuf), "%*s%s", cols > len ? (cols-len)/2 : 0, "", title);
8362 cnt = 0;
8363 if(cnt < alcnt)
8364 config[cnt] = cpystr(sbuf);
8366 if(++cnt < alcnt)
8367 config[cnt] = cpystr("");
8369 if(++cnt < alcnt)
8370 /* TRANSLATORS: headings */
8371 config[cnt] = cpystr(_("Encryption:"));
8373 if(++cnt < alcnt && mail_parameters(NIL, GET_SSLDRIVER, NIL)){
8374 config[cnt] = cpystr(_(" TLS and SSL"));
8375 tmp[0] = tmp[1] = ' ';
8376 tmp[2] = '\0';
8377 #ifdef _WINDOWS
8378 #ifdef SP_PROT_SSL3
8379 strcat(tmp, "SSLv3, ");
8380 #endif /* SP_PROT_SSL3 */
8381 #ifdef SP_PROT_TLS1
8382 strcat(tmp, "TLSv1, ");
8383 #endif /* SP_PROT_TLS1 */
8384 #ifdef SP_PROT_TLS1_1
8385 strcat(tmp, "TLSv1.1, ");
8386 #endif /* SP_PROT_TLS1 */
8387 #ifdef SP_PROT_TLS1_2
8388 strcat(tmp, "TLSv1.2, ");
8389 #endif /* SP_PROT_TLS1_2 */
8390 #ifdef SP_PROT_TLS1_3
8391 strcat(tmp, "TLSv1.3, ");
8392 #endif /* SP_PROT_TLS1_3 */
8393 #else
8394 #ifdef SSL3_VERSION
8395 #ifndef OPENSSL_NO_SSL3_METHOD
8396 strcat(tmp, "SSLv3, ");
8397 #endif /* OPENSSL_NO_SSL3_METHOD */
8398 #endif /* SSL3_VERSION */
8399 #ifdef TLS1_VERSION
8400 #ifndef OPENSSL_NO_TLS1_METHOD
8401 strcat(tmp, "TLSv1, ");
8402 #endif /* OPENSSL_NO_TLS1_METHOD */
8403 #endif /* TLS1_VERSION */
8404 #ifdef TLS1_1_VERSION
8405 #ifndef OPENSSL_NO_TLS1_1_METHOD
8406 strcat(tmp, "TLSv1.1, ");
8407 #endif /* OPENSSL_NO_TLS1_1_METHOD */
8408 #endif /* TLS1_1_VERSION */
8409 #ifdef TLS1_2_VERSION
8410 #ifndef OPENSSL_NO_TLS1_2_METHOD
8411 strcat(tmp, "TLSv1.2, ");
8412 #endif /* OPENSSL_NO_TLS1_2_METHOD */
8413 #endif /* TLS1_2_VERSION */
8414 #ifdef TLS1_3_VERSION
8415 #ifndef OPENSSL_NO_TLS1_3_METHOD
8416 strcat(tmp, "TLSv1.3, ");
8417 #endif /* OPENSSL_NO_TLS1_3_METHOD */
8418 #endif /* TLS1_3_VERSION */
8419 #endif /* _WINDOWS */
8420 tmp[strlen(tmp)-2] = '\0';
8422 else
8423 config[cnt] = cpystr(_(" None (no TLS or SSL)"));
8425 if(++cnt < alcnt)
8426 config[cnt] = cpystr(tmp);
8427 #ifdef SMIME
8428 if(++cnt < alcnt)
8429 config[cnt] = cpystr(" S/MIME");
8430 #endif
8432 if(++cnt < alcnt)
8433 config[cnt] = cpystr("");
8435 if(++cnt < alcnt)
8436 config[cnt] = cpystr(_("Authenticators:"));
8438 for(a = mail_lookup_auth(1); a; a = a->next){
8439 disabled = (a->client == NULL && a->server == NULL);
8440 any_disabled += disabled;
8441 snprintf(sbuf, sizeof(sbuf), " %s%s", a->name, disabled ? " (disabled)" : "");
8442 if(++cnt < alcnt)
8443 config[cnt] = cpystr(sbuf);
8446 if(++cnt < alcnt)
8447 config[cnt] = cpystr("");
8449 if(++cnt < alcnt)
8450 config[cnt] = cpystr(_("Mailbox drivers:"));
8452 for(d = (DRIVER *)mail_parameters(NIL, GET_DRIVERS, NIL);
8453 d; d = d->next){
8454 disabled = (d->flags & DR_DISABLE);
8455 any_disabled += disabled;
8456 snprintf(sbuf, sizeof(sbuf), " %s%s", d->name, disabled ? " (disabled)" : "");
8457 if(++cnt < alcnt)
8458 config[cnt] = cpystr(sbuf);
8461 if(++cnt < alcnt)
8462 config[cnt] = cpystr("");
8464 if(++cnt < alcnt)
8465 config[cnt] = cpystr(_("Directories:"));
8467 #ifdef ENABLE_LDAP
8468 if(++cnt < alcnt)
8469 config[cnt] = cpystr(" LDAP");
8470 #else
8471 if(++cnt < alcnt)
8472 config[cnt] = cpystr(" None (no LDAP)");
8473 #endif
8475 if(any_disabled){
8476 if(++cnt < alcnt)
8477 config[cnt] = cpystr("");
8479 if(ps_global->ttyo){
8480 if(++cnt < alcnt)
8481 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."));
8483 else{
8484 if(++cnt < alcnt)
8485 config[cnt] = cpystr(_("Authenticators may be disabled because of the \"disable-these-authenticators\""));
8486 if(++cnt < alcnt)
8487 config[cnt] = cpystr(_("hidden config option. Mailbox drivers may be disabled because of the"));
8488 if(++cnt < alcnt)
8489 config[cnt] = cpystr(_("\"disable-these-drivers\" hidden config option."));
8493 if(++cnt < alcnt)
8494 config[cnt] = NULL;
8496 return(config);
8500 unsigned
8501 reset_startup_rule(MAILSTREAM *stream)
8503 long rflags = ROLE_DO_OTHER;
8504 PAT_STATE pstate;
8505 PAT_S *pat;
8506 unsigned startup_rule;
8508 startup_rule = IS_NOTSET;
8510 if(stream && nonempty_patterns(rflags, &pstate)){
8511 for(pat = first_pattern(&pstate); pat; pat = next_pattern(&pstate)){
8512 if(match_pattern(pat->patgrp, stream, NULL, NULL, NULL,
8513 SE_NOSERVER|SE_NOPREFETCH))
8514 break;
8517 if(pat && pat->action && !pat->action->bogus)
8518 startup_rule = pat->action->startup_rule;
8521 return(startup_rule);
8525 #ifdef _WINDOWS
8527 char *
8528 transformed_color(old)
8529 char *old;
8531 if(!old)
8532 return("");
8534 if(!struncmp(old, "color008", 8))
8535 return("colorlgr");
8536 else if(!struncmp(old, "color009", 8))
8537 return("colormgr");
8538 else if(!struncmp(old, "color010", 8))
8539 return("colordgr");
8541 return("");
8546 * If this is the first time we've run a version > 4.40, and there
8547 * is evidence that the config file has not been used by unix pine,
8548 * then we convert color008 to colorlgr, color009 to colormgr, and
8549 * color010 to colordgr. If the config file is being used by
8550 * unix pine then color008 may really supposed to be color008, color009
8551 * may really supposed to be red, and color010 may really supposed to be
8552 * green. Same if we've already run 4.41 or higher previously.
8554 * Returns 0 if no changes, > 0 if something was changed.
8557 convert_pc_gray_names(ps, prc, which)
8558 struct pine *ps;
8559 PINERC_S *prc;
8560 EditWhich which;
8562 struct variable *v;
8563 int ret = 0, ic = 0;
8564 char **s, *t, *p, *pstr, *new, *pval, **apval, **lval;
8566 for(v = ps->vars; v->name; v++){
8567 if(!color_holding_var(ps, v) || v == &ps->vars[V_KW_COLORS])
8568 continue;
8570 if(v == &ps->vars[V_VIEW_HDR_COLORS]){
8572 if((lval = LVAL(v,which)) != NULL){
8573 /* fix these in place */
8574 for(s = lval; (t = *s) != NULL; s++){
8575 if((p = srchstr(t, "FG=color008")) ||
8576 (p = srchstr(t, "FG=color009")) ||
8577 (p = srchstr(t, "FG=color010"))){
8578 strncpy(p+3, transformed_color(p+3), 8);
8579 ret++;
8582 if((p = srchstr(t, "BG=color008")) ||
8583 (p = srchstr(t, "BG=color009")) ||
8584 (p = srchstr(t, "BG=color010"))){
8585 strncpy(p+3, transformed_color(p+3), 8);
8586 ret++;
8591 else{
8592 if((pval = PVAL(v,which)) != NULL){
8593 apval = APVAL(v,which);
8594 if(apval && (!strucmp(pval, "color008") ||
8595 !strucmp(pval, "color009") ||
8596 !strucmp(pval, "color010"))){
8597 new = transformed_color(pval);
8598 if(*apval)
8599 fs_give((void **)apval);
8601 *apval = cpystr(new);
8602 ret++;
8608 v = &ps->vars[V_PAT_INCOLS];
8609 if((lval = LVAL(v,which)) != NULL){
8610 for(s = lval; (t = *s) != NULL; s++){
8611 if((pstr = srchstr(t, "action=")) != NULL){
8612 if((p = srchstr(pstr, "FG=color008")) ||
8613 (p = srchstr(pstr, "FG=color009")) ||
8614 (p = srchstr(pstr, "FG=color010"))){
8615 strncpy(p+3, transformed_color(p+3), 8);
8616 ic++;
8619 if((p = srchstr(pstr, "BG=color008")) ||
8620 (p = srchstr(pstr, "BG=color009")) ||
8621 (p = srchstr(pstr, "BG=color010"))){
8622 strncpy(p+3, transformed_color(p+3), 8);
8623 ic++;
8629 if(ic)
8630 set_current_val(&ps->vars[V_PAT_INCOLS], TRUE, TRUE);
8632 return(ret+ic);
8637 unix_color_style_in_pinerc(prc)
8638 PINERC_S *prc;
8640 PINERC_LINE *pline;
8642 for(pline = prc ? prc->pinerc_lines : NULL;
8643 pline && (pline->var || pline->line); pline++)
8644 if(pline->line && !struncmp("color-style=", pline->line, 12))
8645 return(1);
8647 return(0);
8650 char *
8651 pcpine_general_help(titlebuf)
8652 char *titlebuf;
8654 if(titlebuf)
8655 strcpy(titlebuf, "PC Alpine For Windows");
8657 return(pcpine_help(h_pine_for_windows));
8660 #endif /* _WINDOWS */