* Add the /tls1_3 modifier to establish connections use the TLS protocol
[alpine.git] / pith / conf.c
blob607c9f820e45ce23b8f008788a6127d79a06898e
1 #if !defined(lint) && !defined(DOS)
2 static char rcsid[] = "$Id: conf.c 1266 2009-07-14 18:39:12Z hubert@u.washington.edu $";
3 #endif
5 /*
6 * ========================================================================
7 * Copyright 2013-2018 Eduardo Chappa
8 * Copyright 2006-2009 University of Washington
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * ========================================================================
19 /*======================================================================
20 conf.c
21 Implements the Pine configuration management routines
22 ====*/
25 #include "../pith/headers.h"
26 #include "../pith/init.h"
27 #include "../pith/conf.h"
28 #include "../pith/state.h"
29 #include "../pith/remote.h"
30 #include "../pith/keyword.h"
31 #include "../pith/mailview.h"
32 #include "../pith/list.h"
33 #include "../pith/status.h"
34 #include "../pith/ldap.h"
35 #include "../pith/folder.h"
36 #include "../pith/thread.h"
37 #include "../pith/news.h"
38 #include "../pith/util.h"
39 #include "../pith/pattern.h"
40 #include "../pith/color.h"
41 #include "../pith/options.h"
42 #include "../pith/busy.h"
43 #include "../pith/readfile.h"
44 #include "../pith/hist.h"
45 #include "../pith/mailindx.h"
46 #include "../pith/tempfile.h"
47 #include "../pith/icache.h"
48 #include "../pith/sort.h"
49 #include "../pith/smime.h"
50 #include "../pith/charconv/utf8.h"
51 #ifdef _WINDOWS
52 #include "../pico/osdep/mswin.h"
53 #endif
55 #include <openssl/ssl.h>
57 #define TO_BAIL_THRESHOLD 60
61 * Internal prototypes
63 void convert_configvars_to_utf8(struct variable *, char *);
64 void convert_configvar_to_utf8(struct variable *, char *);
65 void set_current_pattern_vals(struct pine *);
66 void convert_pattern_data(void);
67 void convert_filts_pattern_data(void);
68 void convert_scores_pattern_data(void);
69 void convert_pinerc_patterns(long);
70 void convert_pinerc_filts_patterns(long);
71 void convert_pinerc_scores_patterns(long);
72 void set_old_growth_bits(struct pine *, int);
73 int var_is_in_rest_of_file(char *, char *);
74 char *skip_over_this_var(char *, char *);
75 char *native_nl(char *);
76 void set_color_val(struct variable *, int);
77 int copy_localfile_to_remotefldr(RemType, char *, char *, char *, char **);
78 char *backcompat_convert_from_utf8(char **, size_t, char *);
79 #ifdef _WINDOWS
80 char *transformed_color(char *);
81 int convert_pc_gray_names(struct pine *, PINERC_S *, EditWhich);
82 int unix_color_style_in_pinerc(PINERC_S *);
83 char *pcpine_general_help(char *);
84 char *pcpine_help(HelpType); /* defined in alpine/help */
85 #endif /* _WINDOWS */
88 /* hook too allow caller to decide what to do about failure */
89 int (*pith_opt_remote_pinerc_failure)(void);
92 /*------------------------------------
93 Some definitions to keep the static "variable" array below
94 a bit more readable...
95 ----*/
96 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\
97 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";
100 CONF_TXT_T cf_text_personal_name[] = "Over-rides your full name from Unix password file. Required for PC-Alpine.";
102 CONF_TXT_T cf_text_user_id[] = "Your login/e-mail user name";
104 CONF_TXT_T cf_text_user_domain[] = "Sets domain part of From: and local addresses in outgoing mail.";
106 CONF_TXT_T cf_text_smtp_server[] = "List of SMTP servers for sending mail. If blank: Unix Alpine uses sendmail.";
108 CONF_TXT_T cf_text_nntp_server[] = "NNTP server for posting news. Also sets news-collections for news reading.";
110 #ifdef SMIME
112 CONF_TXT_T cf_text_publiccertdir[] = "Public certificates are kept in files in this directory. The files should\n# contain certificates in PEM format. The name of each file should look\n# like <emailaddress>.crt. The default directory is .alpine-smime/public.";
114 CONF_TXT_T cf_text_privatekeydir[] = "Private keys are kept in files in this directory. The files are in PEM format.\n# The name of a file should look like <emailaddress>.key.\n# The default directory is .alpine-smime/private.";
116 CONF_TXT_T cf_text_cacertdir[] = "Certificate Authority certificates (in addition to the normal CACerts for the\n# system) are kept in files in this directory. The files are in PEM format.\n# Filenames should end with .crt. The default directory is .alpine-smime/ca.";
118 CONF_TXT_T cf_text_publiccertcontainer[] = "If this option is set then public certificates are kept in a single container\n# \"file\" similar to a remote configuration file instead of in the\n# smime-publiccert-directory. The value can be a remote or local folder\n# specification like for a non-standard pinerc value. The default\n# is that it is not set.";
120 CONF_TXT_T cf_text_privatekeycontainer[] = "If this option is set then private keys are kept in a single container\n# \"file\" similar to a remote configuration file instead of in the\n# private-key-directory. The value can be a remote or local folder\n# specification like for a non-standard pinerc value. The default\n# is that it is not set.";
122 CONF_TXT_T cf_text_cacertcontainer[] = "If this option is set then CAcerts are kept in a single container\n# \"file\" similar to a remote configuration file instead of in the\n# ca-cert-directory. The value can be a remote or local folder\n# specification like for a non-standard pinerc value. The default\n# is that it is not set.";
124 #endif /* SMIME */
126 #ifdef ENABLE_LDAP
127 CONF_TXT_T cf_text_ldap_server[] = "LDAP servers for looking up addresses.";
128 #endif /* ENABLE_LDAP */
130 CONF_TXT_T cf_text_rss_news[] = "RSS News feed";
132 CONF_TXT_T cf_text_rss_weather[] = "RSS Weather feed";
134 CONF_TXT_T cf_text_wp_indexheight[] = "Web Alpine index table row height";
136 CONF_TXT_T cf_text_wp_indexlines[] = "Web Alpine number of index lines in table";
138 CONF_TXT_T cf_text_wp_aggstate[] = "Web Alpine aggregate operations tab state";
140 CONF_TXT_T cf_text_wp_state[] = "Web Alpine various aspects of cross-session state";
142 CONF_TXT_T cf_text_wp_columns[] = "Web Alpine preferred width for message display in characters";
144 CONF_TXT_T cf_text_inbox_path[] = "Path of (local or remote) INBOX, e.g. ={mail.somewhere.edu}inbox\n# Normal Unix default is the local INBOX (usually /usr/spool/mail/$USER).";
146 CONF_TXT_T cf_text_incoming_folders[] = "List of incoming msg folders besides INBOX, e.g. ={host2}inbox, {host3}inbox\n# Syntax: optnl-label {optnl-imap-host-name}folder-path";
148 CONF_TXT_T cf_text_folder_collections[] = "List of directories where saved-message folders may be. First one is\n# the default for Saves. Example: Main {host1}mail/[], Desktop mail\\[]\n# Syntax: optnl-label {optnl-imap-hostname}optnl-directory-path[]";
150 CONF_TXT_T cf_text_news_collections[] = "List, only needed if nntp-server not set, or news is on a different host\n# than used for NNTP posting. Examples: News *[] or News *{host3/nntp}[]\n# Syntax: optnl-label *{news-host/protocol}[]";
152 CONF_TXT_T cf_text_pruned_folders[] = "List of folders, assumed to be in first folder collection,\n# offered for pruning each month. For example: mumble";
154 CONF_TXT_T cf_text_default_fcc[] = "Over-rides default path for sent-mail folder, e.g. =old-mail (using first\n# folder collection dir) or ={host2}sent-mail or =\"\" (to suppress saving).\n# Default: sent-mail (Unix) or SENTMAIL.MTX (PC) in default folder collection.";
156 CONF_TXT_T cf_text_default_saved[] = "Over-rides default path for saved-msg folder, e.g. =saved-messages (using 1st\n# folder collection dir) or ={host2}saved-mail or =\"\" (to suppress saving).\n# Default: saved-messages (Unix) or SAVEMAIL.MTX (PC) in default collection.";
158 CONF_TXT_T cf_text_postponed_folder[] = "Over-rides default path for postponed messages folder, e.g. =pm (which uses\n# first folder collection dir) or ={host4}pm (using home dir on host4).\n# Default: postponed-msgs (Unix) or POSTPOND.MTX (PC) in default fldr coltn.";
160 CONF_TXT_T cf_text_mail_directory[] = "Alpine compares this value with the first folder collection directory.\n# If they match (or no folder collections are defined), and the directory\n# does not exist, Alpine will create and use it. Default: ~/mail";
162 CONF_TXT_T cf_text_read_message_folder[] = "If set, specifies where already-read messages will be moved upon quitting.";
164 CONF_TXT_T cf_text_form_letter_folder[] = "If set, specifies where form letters should be stored.";
166 CONF_TXT_T cf_text_trash_folder[] = "If set, specifies where trash is moved to in Web Alpine.";
168 CONF_TXT_T cf_text_signature_file[] = "Over-rides default path for signature file. Default is ~/.signature";
170 CONF_TXT_T cf_text_literal_sig[] = "Contains the actual signature contents as opposed to the signature filename.\n# If defined, this overrides the signature-file. Default is undefined.";
172 CONF_TXT_T cf_text_global_address_book[] = "List of file or path names for global/shared addressbook(s).\n# Default: none\n# Syntax: optnl-label path-name";
174 CONF_TXT_T cf_text_address_book[] = "List of file or path names for personal addressbook(s).\n# Default: ~/.addressbook (Unix) or \\PINE\\ADDRBOOK (PC)\n# Syntax: optnl-label path-name";
176 CONF_TXT_T cf_text_feature_list[] = "List of features; see Alpine's Setup/options menu for the current set.\n# e.g. feature-list= select-without-confirm, signature-at-bottom\n# Default condition for all of the features is no-.";
178 CONF_TXT_T cf_text_initial_keystroke_list[] = "Alpine executes these keys upon startup (e.g. to view msg 13: i,j,1,3,CR,v)";
180 CONF_TXT_T cf_text_default_composer_hdrs[] = "Only show these headers (by default) when composing messages";
182 CONF_TXT_T cf_text_customized_hdrs[] = "Add these customized headers (and possible default values) when composing";
184 CONF_TXT_T cf_text_view_headers[] = "When viewing messages, include this list of headers";
186 CONF_TXT_T cf_text_view_margin_left[] = "When viewing messages, number of blank spaces between left display edge and text";
188 CONF_TXT_T cf_text_view_margin_right[] = "When viewing messages, number of blank spaces between right display edge and text";
190 CONF_TXT_T cf_text_quote_suppression[] = "When viewing messages, number of lines of quote displayed before suppressing";
192 CONF_TXT_T cf_text_wordsep[] = "When these characters appear in the middle of a word in the composer\n# the forward word function will stop at the first text following (as happens\n# with SPACE characters by default)";
194 CONF_TXT_T cf_text_color_style[] = "Controls display of color";
196 CONF_TXT_T cf_text_current_indexline_style[] = "Controls display of color for current index line";
198 CONF_TXT_T cf_text_titlebar_color_style[] = "Controls display of color for the titlebar at top of screen";
200 CONF_TXT_T cf_text_view_hdr_color[] = "When viewing messages, these are the header colors";
202 CONF_TXT_T cf_text_index_token_color[] = "Colors in which tokens will be displayed in the index screen";
204 CONF_TXT_T cf_text_save_msg_name_rule[] = "Determines default folder name for Saves...\n# Choices: default-folder, by-sender, by-from, by-recipient, last-folder-used.\n# Default: \"default-folder\", i.e. \"saved-messages\" (Unix) or \"SAVEMAIL\" (PC).";
206 CONF_TXT_T cf_text_fcc_name_rule[] = "Determines default name for Fcc...\n# Choices: default-fcc, by-recipient, last-fcc-used.\n# Default: \"default-fcc\" (see also \"default-fcc=\" variable.)";
208 CONF_TXT_T cf_text_sort_key[] = "Sets presentation order of messages in Index. Choices:\n# Subject, From, Arrival, Date, Size, To, Cc, OrderedSubj, Score, and Thread.\n# Order may be reversed by appending /Reverse. Default: \"Arrival\".";
210 CONF_TXT_T cf_text_addrbook_sort_rule[] = "Sets presentation order of address book entries. Choices: dont-sort,\n# fullname-with-lists-last, fullname, nickname-with-lists-last, nickname\n# Default: \"fullname-with-lists-last\".";
212 CONF_TXT_T cf_text_folder_sort_rule[] = "Sets presentation order of folder list entries. Choices: alphabetical,\n# alpha-with-dirs-last, alpha-with-dirs-first.\n# Default: \"alpha-with-directories-last\".";
214 CONF_TXT_T cf_text_old_char_set[] = "Character-set is obsolete, use display-character-set, keyboard-character-set,\n# and posting-character-set.";
216 CONF_TXT_T cf_text_disp_char_set[] = "Reflects capabilities of the display you have.\n# If unset, the default is taken from your locale. That is usually the right\n# thing to use. Typical alternatives include UTF-8, ISO-8859-x, and EUC-JP\n# (where x is a number between 1 and 9).";
218 CONF_TXT_T cf_text_key_char_set[] = "Reflects capabilities of the keyboard you have.\n# If unset, the default is to use the same value\n# used for the display-character-set.";
220 CONF_TXT_T cf_text_post_character_set[] = "Defaults to UTF-8. This is used for outgoing messages.\n# It is usually correct to leave this unset.";
222 CONF_TXT_T cf_text_unk_character_set[] = "Defaults to nothing, which is equivalent to US-ASCII. This is used for\n# unlabeled incoming messages. It is ok to leave this unset but if you receive\n# unlabeled mail that is usually in some known character set, set that here.";
224 CONF_TXT_T cf_text_editor[] = "Specifies the program invoked by ^_ in the Composer,\n# or the \"enable-alternate-editor-implicitly\" feature.";
226 CONF_TXT_T cf_text_speller[] = "Specifies the program invoked by ^T in the Composer.";
228 #ifdef _WINDOWS
229 CONF_TXT_T cf_text_speller_dictionary[] = "Specifies the list of dictionaries used by Aspell.";
230 #endif /* _WINDOWS */
232 CONF_TXT_T cf_text_deadlets[] = "Specifies the number of dead letter files to keep when canceling.";
234 CONF_TXT_T cf_text_fillcol[] = "Specifies the column of the screen where the composer should wrap.";
236 CONF_TXT_T cf_text_replystr[] = "Specifies the string to insert when replying to a message.";
238 CONF_TXT_T cf_text_quotereplstr[] = "Specifies the string to replace quotes with when viewing a message.";
240 CONF_TXT_T cf_text_replyintro[] = "Specifies the introduction to insert when replying to a message.";
242 CONF_TXT_T cf_text_emptyhdr[] = "Specifies the string to use when sending a message with no to or cc.";
244 CONF_TXT_T cf_text_image_viewer[] = "Program to view images (e.g. GIF or TIFF attachments).";
246 CONF_TXT_T cf_text_browser[] = "List of programs to open Internet URLs (e.g. http or ftp references).";
248 CONF_TXT_T cf_text_history[] = "List of directories that are preferred locations to save or export attachments.";
250 CONF_TXT_T cf_text_inc_startup[] = "Sets message which cursor begins on. Choices: first-unseen, first-recent,\n# first-important, first-important-or-unseen, first-important-or-recent,\n# first, last. Default: \"first-unseen\".";
252 CONF_TXT_T cf_pruning_rule[] = "Allows a default answer for the prune folder questions. Choices: yes-ask,\n# yes-no, no-ask, no-no, ask-ask, ask-no. Default: \"ask-ask\".";
254 CONF_TXT_T cf_reopen_rule[] = "Controls behavior when reopening an already open folder.";
256 CONF_TXT_T cf_text_thread_disp_style[] = "Style that MESSAGE INDEX is displayed in when threading.";
258 CONF_TXT_T cf_text_thread_index_style[] = "Style of THREAD INDEX or default MESSAGE INDEX when threading.";
260 CONF_TXT_T cf_text_thread_more_char[] = "When threading, character used to indicate collapsed messages underneath.";
262 CONF_TXT_T cf_text_thread_exp_char[] = "When threading, character used to indicate expanded messages underneath.";
264 CONF_TXT_T cf_text_thread_lastreply_char[] = "When threading, character used to indicate this is the last reply\n# to the parent of this message.";
266 CONF_TXT_T cf_text_use_only_domain_name[] = "If \"user-domain\" not set, strips hostname in FROM address. (Unix only)";
268 CONF_TXT_T cf_text_printer[] = "Your default printer selection";
270 CONF_TXT_T cf_text_personal_print_command[] = "List of special print commands";
272 CONF_TXT_T cf_text_personal_print_cat[] = "Which category default print command is in";
274 CONF_TXT_T cf_text_standard_printer[] = "The system wide standard printers";
276 CONF_TXT_T cf_text_last_time_prune_quest[] = "Set by Alpine; controls beginning-of-month sent-mail pruning.";
278 CONF_TXT_T cf_text_last_version_used[] = "Set by Alpine; controls display of \"new version\" message.";
280 CONF_TXT_T cf_text_disable_drivers[] = "List of mail drivers to disable.";
282 CONF_TXT_T cf_text_disable_auths[] = "List of SASL authenticators to disable.";
284 CONF_TXT_T cf_text_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_psleep[] = "UNIX ONLY (except MAC OSX): When an attachment is opened, this variable controls the number\n#of seconds to wait between checks if the user has ended viewing the attachment.\n#minimun value: 60 seconds, maximum value: 600 seconds (10 minutes). Default: 60 seconds";
352 CONF_TXT_T cf_text_mailcheck[] = "The approximate number of seconds between checks for new mail";
354 CONF_TXT_T cf_text_mailchecknoncurr[] = "The approximate number of seconds between checks for new mail in folders\n# other than the current folder and inbox.\n# Default is same as mail-check-interval";
356 CONF_TXT_T cf_text_maildropcheck[] = "The minimum number of seconds between checks for new mail in a Mail Drop.\n# This is always effectively at least as large as the mail-check-interval";
358 CONF_TXT_T cf_text_nntprange[] = "For newsgroups accessed using NNTP, only messages numbered in the range\n# lastmsg-range+1 to lastmsg will be considered";
360 CONF_TXT_T cf_text_news_active[] = "Path and filename of news configuration's active file.\n# The default is typically \"/usr/lib/news/active\".";
362 CONF_TXT_T cf_text_news_spooldir[] = "Directory containing system's news data.\n# The default is typically \"/usr/spool/news\"";
364 CONF_TXT_T cf_text_upload_cmd[] = "Path and filename of the program used to upload text from your terminal\n# emulator's into Alpine's composer.";
366 CONF_TXT_T cf_text_upload_prefix[] = "Text sent to terminal emulator prior to invoking the program defined by\n# the upload-command variable.\n# Note: _FILE_ will be replaced with the temporary file used in the upload.";
368 CONF_TXT_T cf_text_download_cmd[] = "Path and filename of the program used to download text via your terminal\n# emulator from Alpine's export and save commands.";
370 CONF_TXT_T cf_text_download_prefix[] = "Text sent to terminal emulator prior to invoking the program defined by\n# the download-command variable.\n# Note: _FILE_ will be replaced with the temporary file used in the download.";
372 CONF_TXT_T cf_text_goto_default[] = "Sets the default folder and collection offered at the Goto Command's prompt.";
374 CONF_TXT_T cf_text_mailcap_path[] = "Sets the search path for the mailcap configuration file.\n# NOTE: colon delimited under UNIX, semi-colon delimited under DOS/Windows/OS2.";
376 CONF_TXT_T cf_text_mimetype_path[] = "Sets the search path for the mimetypes configuration file.\n# NOTE: colon delimited under UNIX, semi-colon delimited under DOS/Windows/OS2.";
378 CONF_TXT_T cf_text_newmail_fifo_path[] = "Sets the filename for the newmail fifo (named pipe). Unix only.";
380 CONF_TXT_T cf_text_nmw_width[] = "Sets the width for the NewMail screen.";
382 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.";
384 CONF_TXT_T cf_text_debug_mem[] = "Debug-memory is obsolete";
386 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).";
388 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.";
390 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.";
392 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.";
394 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.";
396 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.";
398 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.";
400 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\")";
402 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.";
404 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.";
406 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.";
408 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.";
410 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.";
412 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.";
414 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\")";
416 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.";
418 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.";
420 CONF_TXT_T cf_text_elm_style_save[] = "Elm-style-save is obsolete, use saved-msg-name-rule";
422 CONF_TXT_T cf_text_header_in_reply[] = "Header-in-reply is obsolete, use include-header-in-reply in feature-list";
424 CONF_TXT_T cf_text_feature_level[] = "Feature-level is obsolete, use feature-list";
426 CONF_TXT_T cf_text_old_style_reply[] = "Old-style-reply is obsolete, use signature-at-bottom in feature-list";
428 CONF_TXT_T cf_text_compose_mime[] = "Compose-mime is obsolete";
430 CONF_TXT_T cf_text_show_all_characters[] = "Show-all-characters is obsolete";
432 CONF_TXT_T cf_text_save_by_sender[] = "Save-by-sender is obsolete, use saved-msg-name-rule";
434 CONF_TXT_T cf_text_file_dir[] = "Default directory used for Attachment handling (attach and save)\n# and Export command output";
436 CONF_TXT_T cf_text_folder_extension[] = "Folder-extension is obsolete";
438 CONF_TXT_T cf_text_normal_foreground_color[] = "Choose: black, blue, green, cyan, red, magenta, yellow, or white.";
440 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.";
442 CONF_TXT_T cf_text_newsrc_path[] = "Full path and name of NEWSRC file";
445 /*----------------------------------------------------------------------
446 These are the variables that control a number of pine functions. They
447 come out of the .pinerc and the /usr/local/lib/pine.conf files. Some can
448 be set by the user while in Alpine. Eventually all the local ones should
449 be so and maybe the global ones too.
451 Each variable can have a command-line, user, global, and current value.
452 All of these values are malloc'd. The user value is the one read out of
453 the user's .pinerc, the global value is the one from the system pine
454 configuration file. There are often defaults for the global values, set
455 at the start of init_vars(). Perhaps someday there will be group values.
456 The current value is the one that is actually in use.
457 ----*/
458 /* name is_changed_val
459 remove_quotes |
460 is_outermost | |
461 is_onlymain | | |
462 is_fixed | | | |
463 is_list | | | | |
464 is_global | | | | | |
465 is_user | | | | | | |
466 been_written | | | | | | | |
467 is_used | | | | | | | | |
468 is_obsolete | | | | | | | | | |
469 | | | | | | | | | | |
470 (on following line) description | | | | | | | | | | |
471 | | | | | | | | | | | |
472 | | | | | | | | | | | | */
473 static struct variable variables[] = {
474 {"personal-name", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
475 NULL, cf_text_personal_name},
477 #if defined(DOS) || defined(OS2)
478 /* Have to have this on DOS, PC's, Macs, etc... */
479 "user-id", 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0,
480 #else /* Don't allow on UNIX machines for some security */
481 "user-id", 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0,
482 #endif
483 "User ID", cf_text_user_id},
484 {"user-domain", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
485 NULL, cf_text_user_domain},
486 {"smtp-server", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
487 "SMTP Server (for sending)", cf_text_smtp_server},
488 {"nntp-server", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
489 "NNTP Server (for news)", cf_text_nntp_server},
490 {"inbox-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
491 NULL, cf_text_inbox_path},
492 {"incoming-archive-folders", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
493 NULL, cf_text_archived_folders},
494 {"pruned-folders", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
495 NULL, cf_text_pruned_folders},
496 {"default-fcc", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
497 "Default Fcc (File carbon copy)", cf_text_default_fcc},
498 {"default-saved-msg-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
499 "Default Saved Message Folder", cf_text_default_saved},
500 {"postponed-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
501 NULL, cf_text_postponed_folder},
502 {"read-message-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
503 NULL, cf_text_read_message_folder},
504 {"form-letter-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
505 NULL, cf_text_form_letter_folder},
506 {"trash-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
507 NULL, cf_text_trash_folder},
508 {"literal-signature", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
509 NULL, cf_text_literal_sig},
510 {"signature-file", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
511 NULL, cf_text_signature_file},
512 {"feature-list", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
513 NULL, cf_text_feature_list},
514 {"initial-keystroke-list", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
515 NULL, cf_text_initial_keystroke_list},
516 {"default-composer-hdrs", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
517 "Default Composer Headers", cf_text_default_composer_hdrs},
518 {"customized-hdrs", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
519 "Customized Headers", cf_text_customized_hdrs},
520 {"viewer-hdrs", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
521 "Viewer Headers", cf_text_view_headers},
522 {"viewer-margin-left", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
523 NULL, cf_text_view_margin_left},
524 {"viewer-margin-right", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
525 NULL, cf_text_view_margin_right},
526 {"quote-suppression-threshold", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
527 NULL, cf_text_quote_suppression},
528 {"saved-msg-name-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
529 "Saved Message Name Rule", cf_text_save_msg_name_rule},
530 {"fcc-name-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
531 NULL, cf_text_fcc_name_rule},
532 {"sort-key", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
533 NULL, cf_text_sort_key},
534 {"addrbook-sort-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
535 "Address Book Sort Rule", cf_text_addrbook_sort_rule},
536 {"folder-sort-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
537 NULL, cf_text_folder_sort_rule},
538 {"goto-default-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
539 NULL, cf_text_goto_default},
540 {"incoming-startup-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
541 NULL, cf_text_inc_startup},
542 {"pruning-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
543 NULL, cf_pruning_rule},
544 {"folder-reopen-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
545 NULL, cf_reopen_rule},
546 {"threading-display-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
547 NULL, cf_text_thread_disp_style},
548 {"threading-index-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
549 NULL, cf_text_thread_index_style},
550 {"threading-indicator-character", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
551 NULL, cf_text_thread_more_char},
552 {"threading-expanded-character", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
553 NULL, cf_text_thread_exp_char},
554 {"threading-lastreply-character", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
555 "Threading Last Reply Character", cf_text_thread_lastreply_char},
556 #ifndef _WINDOWS
557 {"display-character-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
558 NULL, cf_text_disp_char_set},
559 {"character-set", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
560 NULL, cf_text_old_char_set},
561 {"keyboard-character-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
562 NULL, cf_text_key_char_set},
563 #endif /* ! _WINDOWS */
564 {"posting-character-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
565 NULL, cf_text_post_character_set},
566 {"unknown-character-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
567 NULL, cf_text_unk_character_set},
568 {"editor", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
569 NULL, cf_text_editor},
570 {"speller", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
571 NULL, cf_text_speller},
572 #ifdef _WINDOWS
573 {"aspell-dictionary-list", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
574 "Aspell Dictionaries", cf_text_speller_dictionary},
575 #endif /* _WINDOWS */
576 {"composer-wrap-column", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
577 NULL, cf_text_fillcol},
578 {"reply-indent-string", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
579 NULL, cf_text_replystr},
580 {"reply-leadin", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
581 NULL, cf_text_replyintro},
582 {"quote-replace-string", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
583 NULL, cf_text_quotereplstr},
584 {"composer-word-separators", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
585 NULL, cf_text_wordsep},
586 {"empty-header-message", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
587 NULL, cf_text_emptyhdr},
588 {"image-viewer", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
589 NULL, cf_text_image_viewer},
590 {"use-only-domain-name", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
591 NULL, cf_text_use_only_domain_name},
592 {"bugs-fullname", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
593 NULL, cf_text_bugs_fullname},
594 {"bugs-address", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
595 NULL, cf_text_bugs_address},
596 {"bugs-additional-data", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
597 NULL, cf_text_bugs_extras},
598 {"suggest-fullname", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
599 NULL, cf_text_suggest_fullname},
600 {"suggest-address", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
601 NULL, cf_text_suggest_address},
602 {"local-fullname", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
603 NULL, cf_text_local_fullname},
604 {"local-address", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
605 NULL, cf_text_local_address},
606 {"forced-abook-entry", 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0,
607 NULL, cf_text_forced_abook},
608 {"kblock-passwd-count", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
609 NULL, cf_text_kblock_passwd},
610 {"display-filters", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
611 NULL, cf_text_in_fltr},
612 {"sending-filters", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
613 NULL, cf_text_out_fltr},
614 {"alt-addresses", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
615 "Alternate Addresses", cf_text_alt_addrs},
616 {"keywords", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
617 NULL, cf_text_keywords},
618 {"keyword-surrounding-chars", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
619 "Keyword Surrounding Characters", cf_text_kw_braces},
620 {"opening-text-separator-chars", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
621 "Opening Text Separator Characters", cf_text_opening_sep},
622 {"addressbook-formats", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
623 "Address Book Formats", cf_text_abook_formats},
624 {"index-format", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
625 NULL, cf_text_index_format},
626 {"viewer-overlap", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
627 NULL, cf_text_overlap},
628 {"scroll-margin", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
629 NULL, cf_text_margin},
630 {"status-message-delay", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
631 NULL, cf_text_stat_msg_delay},
632 {"busy-cue-rate", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
633 NULL, cf_text_busy_cue_rate},
634 {"mailcap-check-interval", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
635 NULL, cf_text_psleep},
636 {"mail-check-interval", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
637 NULL, cf_text_mailcheck},
638 {"mail-check-interval-noncurrent", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
639 NULL, cf_text_mailchecknoncurr},
640 {"maildrop-check-minimum", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
641 NULL, cf_text_maildropcheck},
642 {"nntp-range", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
643 "NNTP Range", cf_text_nntprange},
644 {"newsrc-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
645 NULL, cf_text_newsrc_path},
646 {"news-active-file-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
647 NULL, cf_text_news_active},
648 {"news-spool-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
649 NULL, cf_text_news_spooldir},
650 {"upload-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
651 NULL, cf_text_upload_cmd},
652 {"upload-command-prefix", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
653 NULL, cf_text_upload_prefix},
654 {"download-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
655 NULL, cf_text_download_cmd},
656 {"download-command-prefix", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
657 NULL, cf_text_download_prefix},
658 {"mailcap-search-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
659 NULL, cf_text_mailcap_path},
660 {"mimetype-search-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
661 NULL, cf_text_mimetype_path},
662 {"url-viewers", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
663 "URL-Viewers", cf_text_browser},
664 {"default-directories", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
665 "Extra Directories for Save", cf_text_history},
666 {"max-remote-connections", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
667 "Maximum Remote Connections", cf_text_maxremstreams},
668 {"stay-open-folders", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
669 "Stayopen Folders", cf_text_permlocked},
670 {"incoming-check-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
671 NULL, cf_text_inc_check_timeo},
672 {"incoming-check-interval", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
673 NULL, cf_text_inc_check_interval},
674 {"incoming-check-interval-secondary", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
675 NULL, cf_text_inc_second_check_interval},
676 {"incoming-check-list", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
677 NULL, cf_text_inc_check_list},
678 {"dead-letter-files", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
679 NULL, cf_text_deadlets},
680 #if !defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)
681 {"newmail-fifo-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
682 "NewMail FIFO Path", cf_text_newmail_fifo_path},
683 #endif
684 {"newmail-window-width", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
685 "NewMail Window Width", cf_text_nmw_width},
687 * Starting here, the variables are hidden in the Setup/Config screen.
688 * They are exposed if feature expose-hidden-config is set.
690 {"incoming-folders", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
691 NULL, cf_text_incoming_folders},
692 {"mail-directory", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
693 NULL, cf_text_mail_directory},
694 {"folder-collections", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
695 NULL, cf_text_folder_collections},
696 {"news-collections", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
697 NULL, cf_text_news_collections},
698 {"address-book", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
699 NULL, cf_text_address_book},
700 {"global-address-book", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
701 NULL, cf_text_global_address_book},
702 {"standard-printer", 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0,
703 NULL, cf_text_standard_printer},
704 {"last-time-prune-questioned", 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0,
705 NULL, cf_text_last_time_prune_quest},
706 {"last-version-used", 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0,
707 NULL, cf_text_last_version_used},
708 {"sendmail-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
709 NULL, cf_text_sendmail_path},
710 {"operating-dir", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
711 NULL, cf_text_oper_dir},
712 {"user-input-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
713 NULL, cf_text_user_input_timeo},
714 /* OBSOLETE */
715 #ifdef DEBUGJOURNAL
716 {"debug-memory", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
717 NULL, cf_text_debug_mem},
718 #endif
719 {"tcp-open-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
720 "TCP Open Timeout", cf_text_tcp_open_timeo},
721 {"tcp-read-warning-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
722 "TCP Read Warning Timeout", cf_text_tcp_read_timeo},
723 {"tcp-write-warning-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
724 "TCP Write Warning Timeout", cf_text_tcp_write_timeo},
725 {"tcp-query-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
726 "TCP Query Timeout", cf_text_tcp_query_timeo},
727 {"close-connection-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
728 NULL, cf_text_close_connection_timeo},
729 {"rsh-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
730 NULL, cf_text_rsh_command},
731 {"rsh-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
732 NULL, cf_text_rsh_path},
733 {"rsh-open-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
734 NULL, cf_text_rsh_open_timeo},
735 {"ssh-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
736 NULL, cf_text_ssh_command},
737 {"ssh-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
738 NULL, cf_text_ssh_path},
739 {"ssh-open-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
740 NULL, cf_text_ssh_open_timeo},
741 {"new-version-threshold", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
742 NULL, cf_text_version_threshold},
743 {"disable-these-drivers", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
744 NULL, cf_text_disable_drivers},
745 {"disable-these-authenticators", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
746 NULL, cf_text_disable_auths},
747 {"remote-abook-metafile", 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0,
748 NULL, cf_text_remote_abook_metafile},
749 {"remote-abook-history", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
750 NULL, cf_text_remote_abook_history},
751 {"remote-abook-validity", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
752 NULL, cf_text_remote_abook_validity},
753 {"printer", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
754 NULL, cf_text_printer},
755 {"personal-print-command", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
756 NULL, cf_text_personal_print_command},
757 {"personal-print-category", 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0,
758 NULL, cf_text_personal_print_cat},
759 {"patterns", 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
760 NULL, cf_text_old_patterns},
761 {"patterns-roles", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
762 NULL, cf_text_patterns},
763 {"patterns-filters2", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
764 "Patterns Filters", cf_text_patterns},
765 {"patterns-filters", 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
766 NULL, cf_text_old_filters},
767 {"patterns-scores2", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
768 "Patterns Scores", cf_text_patterns},
769 {"patterns-scores", 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
770 NULL, cf_text_old_scores},
771 {"patterns-indexcolors", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
772 NULL, cf_text_patterns},
773 {"patterns-other", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
774 NULL, cf_text_patterns},
775 {"patterns-search", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
776 NULL, cf_text_patterns},
777 /* OBSOLETE VARS */
778 {"elm-style-save", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
779 NULL, cf_text_elm_style_save},
780 {"header-in-reply", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
781 NULL, cf_text_header_in_reply},
782 {"feature-level", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
783 NULL, cf_text_feature_level},
784 {"old-style-reply", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
785 NULL, cf_text_old_style_reply},
786 {"compose-mime", 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
787 NULL, cf_text_compose_mime},
788 {"show-all-characters", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
789 NULL, cf_text_show_all_characters},
790 {"save-by-sender", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
791 NULL, cf_text_save_by_sender},
792 #if defined(DOS) || defined(OS2)
793 {"file-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
794 NULL, cf_text_file_dir},
795 {"folder-extension", 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0,
796 NULL, cf_text_folder_extension},
797 #endif
798 #ifndef _WINDOWS
799 {"color-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
800 NULL, cf_text_color_style},
801 #endif
802 {"current-indexline-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
803 NULL, cf_text_current_indexline_style},
804 {"titlebar-color-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
805 NULL, cf_text_titlebar_color_style},
806 {"normal-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
807 NULL, cf_text_normal_foreground_color},
808 {"normal-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
809 {"reverse-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
810 {"reverse-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
811 {"title-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
812 {"title-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
813 {"title-closed-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
814 {"title-closed-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
815 {"folder-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
816 {"folder-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
817 {"directory-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
818 {"directory-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
819 {"folder-list-text-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
820 {"folder-list-text-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
821 {"status-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
822 {"status-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
823 {"keylabel-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
824 {"keylabel-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
825 {"keyname-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
826 {"keyname-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
827 {"selectable-item-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
828 {"selectable-item-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
829 {"meta-message-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
830 {"meta-message-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
831 {"quote1-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
832 {"quote1-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
833 {"quote2-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
834 {"quote2-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
835 {"quote3-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
836 {"quote3-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
837 {"incoming-unseen-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
838 {"incoming-unseen-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
839 {"signature-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
840 {"signature-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
841 {"prompt-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
842 {"prompt-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
843 {"header-general-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
844 {"header-general-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
845 {"index-to-me-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
846 {"index-to-me-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
847 {"index-important-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
848 {"index-important-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
849 {"index-deleted-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
850 {"index-deleted-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
851 {"index-answered-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
852 {"index-answered-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
853 {"index-new-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
854 {"index-new-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
855 {"index-recent-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
856 {"index-recent-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
857 {"index-forward-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
858 {"index-forward-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
859 {"index-unseen-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
860 {"index-unseen-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
861 {"index-highpriority-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
862 {"index-highpriority-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
863 {"index-lowpriority-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
864 {"index-lowpriority-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
865 {"index-arrow-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
866 {"index-arrow-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
867 {"index-subject-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
868 {"index-subject-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
869 {"index-from-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
870 {"index-from-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
871 {"index-opening-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
872 {"index-opening-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
873 {"index-token-colors", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
874 NULL, cf_text_index_token_color},
875 {"viewer-hdr-colors", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
876 "Viewer Header Colors", cf_text_view_hdr_color},
877 {"keyword-colors", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
878 NULL, cf_text_kw_colors},
879 #ifdef _WINDOWS
880 {"font-name", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
881 NULL, "name and size of font."},
882 {"font-size", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
883 {"font-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
884 {"font-char-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
885 {"print-font-name", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
886 NULL, "name and size of printer font."},
887 {"print-font-size", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
888 {"print-font-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
889 {"print-font-char-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
890 {"window-position", 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0,
891 NULL, cf_text_window_position},
892 {"cursor-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
893 #endif /* _WINDOWS */
894 #ifdef SMIME
895 {"smime-public-cert-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
896 "S/MIME - Public Cert Directory", cf_text_publiccertdir},
897 {"smime-public-cert-container", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
898 "S/MIME - Public Cert Container", cf_text_publiccertcontainer},
899 {"smime-private-key-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
900 "S/MIME - Private Key Directory", cf_text_privatekeydir},
901 {"smime-private-key-container", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
902 "S/MIME - Private Key Container", cf_text_privatekeycontainer},
903 {"smime-cacert-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
904 "S/MIME - Cert Authority Directory", cf_text_cacertdir},
905 {"smime-cacert-container", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
906 "S/MIME - Cert Authority Container", cf_text_cacertcontainer},
907 #endif /* SMIME */
908 #ifdef ENABLE_LDAP
909 {"ldap-servers", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
910 "LDAP Servers", cf_text_ldap_server},
911 #endif /* ENABLE_LDAP */
912 {"rss-news", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
913 "WEB ALPINE - RSS News", cf_text_rss_news},
914 {"rss-weather", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
915 "WEB ALPINE - RSS Weather", cf_text_rss_weather},
916 {"wp-indexheight", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
917 "WEB ALPINE - Index Height", cf_text_wp_indexheight},
918 {"wp-indexlines", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
919 "WEB ALPINE - Index Lines", cf_text_wp_indexlines},
920 {"wp-aggstate", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
921 "WEB ALPINE - Aggregate State", cf_text_wp_aggstate},
922 {"wp-state", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
923 "WEB ALPINE - Cross Session State", cf_text_wp_state},
924 {"wp-columns", 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0,
925 "WEB ALPINE - Columns", cf_text_wp_columns},
926 {NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL,NULL}
930 struct variable *
931 var_from_name(char *name)
933 struct variable *v;
934 int i;
936 if(!(name && name[0]))
937 return(NULL);
939 for(i = 0; (v = &variables[i]) && v->name; i++)
940 if(!strucmp(v->name,name))
941 return(v);
943 return(NULL);
947 void
948 init_init_vars(struct pine *ps)
950 ps->vars = variables;
954 #define DSIZE (25000)
955 /* this is just like dprint except it prints to a char * */
956 #ifdef DEBUG
957 #define mprint(n,x) { \
958 if(debug >= (n)){ \
959 snprintf x ; \
960 db += strlen(db); \
963 #else
964 #define mprint(n,x)
965 #endif
968 * this was split out from init_vars so we can get at the
969 * pinerc location sooner.
971 void
972 init_pinerc(struct pine *ps, char **debug_out)
974 char buf[MAXPATH+1], *p, *db;
975 #if defined(DOS) || defined(OS2)
976 char buf2[MAXPATH+1], l_pinerc[MAXPATH+1];
977 int nopinerc = 0, confregset = -1;
978 register struct variable *vars = ps->vars;
979 #endif
981 #ifdef DEBUG
983 * Since this routine is called before we've had a chance to set up
984 * the debug file for output, we put the debugging into memory and
985 * pass it back to the caller for use after init_debug(). We just
986 * allocate plenty of space.
988 if(debug_out){
989 db = *debug_out = (char *)fs_get(DSIZE * sizeof(char));
990 db[0] = '\0';
992 #endif
994 mprint(2, (db, DSIZE-(db-(*debug_out)), "\n -- init_pinerc --\n\n"));
996 #if defined(DOS) || defined(OS2)
998 * Rules for the config/support file locations under DOS are:
1000 * 1) The location of the PINERC is searched for in the following
1001 * order of precedence:
1002 * - File pointed to by '-p' command line option
1003 * - File pointed to by PINERC environment variable
1004 * - $HOME\pine
1005 * - same dir as argv[0]
1007 * 2) The HOME environment variable, if not set, defaults to
1008 * root of the current working drive (see alpine.c)
1010 * 3) The default for external files (PINE.SIG and ADDRBOOK) is the
1011 * same directory as the pinerc
1013 * 4) The support files (PINE.HLP and PINE.NDX) are expected to be in
1014 * the same directory as PINE.EXE.
1017 if(ps->prc){
1018 mprint(2, (db, DSIZE-(db-(*debug_out)),
1019 "Personal config \"%.100s\" comes from command line\n",
1020 (ps->prc && ps->prc->name) ? ps->prc->name : "<no name>"));
1022 else{
1023 mprint(2, (db, DSIZE-(db-(*debug_out)),
1024 "Personal config not set on cmdline, checking for $PINERC\n"));
1028 * First, if prc hasn't been set by a command-line -p, check to see
1029 * if PINERC is in the environment. If so, treat it just like we
1030 * would have treated it if it were a command-line arg.
1032 if(!ps->prc && (p = getenv("PINERC")) && *p){
1033 char path[MAXPATH], dir[MAXPATH];
1035 if(IS_REMOTE(p) || is_absolute_path(p)){
1036 strncpy(path, p, sizeof(path)-1);
1037 path[sizeof(path)-1] = '\0';
1039 else{
1040 getcwd(dir, sizeof(dir));
1041 build_path(path, dir, p, sizeof(path));
1044 if(!IS_REMOTE(p))
1045 ps->pinerc = cpystr(path);
1047 ps->prc = new_pinerc_s(path);
1049 if(ps->prc){
1050 mprint(2, (db, DSIZE-(db-(*debug_out)),
1051 " yes, personal config \"%.100s\" comes from $PINERC\n",
1052 (ps->prc && ps->prc->name) ? ps->prc->name : "<no name>"));
1057 * Pinerc used to be the name of the pinerc file. Then we added
1058 * the possibility of the pinerc file being remote, and we replaced
1059 * the variable pinerc with the structure prc. Unfortunately, some
1060 * parts of pine rely on the fact that pinerc is the name of the
1061 * pinerc _file_, and use the directory that the pinerc file is located
1062 * in for their own purposes. We want to preserve that so things will
1063 * keep working. So, even if the real pinerc is remote, we need to
1064 * put the name of a pinerc file in the pinerc variable so that the
1065 * directory which contains that file is writable. The file itself
1066 * doesn't have to exist for this purpose, since we are really only
1067 * using the name of the directory containing the file. Twisted.
1068 * (Alternatively, we could fix all of the code that uses the pinerc
1069 * variable for this purpose to use a new variable which really is
1070 * just a directory.) hubert 2000-sep
1072 * There are 3 cases. If pinerc is already set that means that the user
1073 * gave either a -p pinerc or an environment pinerc that is a local file,
1074 * and we are done. If pinerc is not set, then either prc is set or not.
1075 * If prc is set then the -p arg or PINERC value is a remote pinerc.
1076 * In that case we need to find a local directory to use, and put that
1077 * directory in the pinerc variable (with a fake filename tagged on).
1078 * If prc is not set, then user hasn't told us anything so we have to
1079 * try to find the default pinerc file by looking down the path of
1080 * possibilities. When we find it, we'll also use that directory.
1082 if(!ps->pinerc){
1083 *l_pinerc = '\0';
1084 *buf = '\0';
1086 if(ps->prc){ /* remote pinerc case */
1088 * We don't give them an l_pinerc unless they tell us where
1089 * to put it.
1091 if(ps->aux_files_dir)
1092 build_path(l_pinerc, ps->aux_files_dir, SYSTEM_PINERC,
1093 sizeof(l_pinerc));
1094 else{
1096 * Search for a writable directory.
1097 * Mimic what happens in !prc for local case, except we
1098 * don't need to look for the actual file.
1101 /* check if $HOME\PINE is writable */
1102 build_path(buf2, ps->home_dir, DF_PINEDIR, sizeof(buf2));
1103 if(is_writable_dir(buf2) == 0)
1104 build_path(l_pinerc, buf2, SYSTEM_PINERC, sizeof(l_pinerc));
1105 else{ /* $HOME\PINE not a writable dir */
1106 /* use this unless registry redirects us */
1107 build_path(l_pinerc, ps->pine_dir, SYSTEM_PINERC,
1108 sizeof(l_pinerc));
1109 #ifdef _WINDOWS
1110 /* if in registry, use that value */
1111 if(mswin_reg(MSWR_OP_GET, MSWR_PINE_RC, buf2, sizeof(buf2))
1112 && !IS_REMOTE(buf2)){
1113 strncpy(l_pinerc, buf2, sizeof(l_pinerc)-1);
1114 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1116 #endif
1120 else{ /* searching for pinerc file to use */
1122 * Buf2 is $HOME\PINE. If $HOME is not explicitly set,
1123 * it defaults to the current working drive (often C:).
1124 * See alpine.c to see how it is initially set.
1127 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, searching...\n"));
1128 build_path(buf2, ps->home_dir, DF_PINEDIR, sizeof(buf2));
1129 mprint(2, (db, DSIZE-(db-(*debug_out)),
1130 " checking for writable %.100s dir \"%.100s\" off of homedir\n",
1131 DF_PINEDIR, buf2));
1132 if(is_writable_dir(buf2) == 0){
1134 * $HOME\PINE exists and is writable.
1135 * See if $HOME\PINE\PINERC exists.
1137 build_path(buf, buf2, SYSTEM_PINERC, sizeof(buf));
1138 strncpy(l_pinerc, buf, sizeof(l_pinerc)-1);
1139 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1140 mprint(2, (db, DSIZE-(db-(*debug_out)), " yes, now checking for file \"%.100s\"\n",
1141 buf));
1142 if(can_access(buf, ACCESS_EXISTS) == 0){ /* found it! */
1144 * Buf is what we were looking for.
1145 * It is local and can be used for the directory, too.
1147 mprint(2, (db, DSIZE-(db-(*debug_out)), " found it\n"));
1149 else{
1151 * No $HOME\PINE\PINERC, look for
1152 * one in same dir as PINE.EXE.
1154 build_path(buf2, ps->pine_dir, SYSTEM_PINERC,
1155 sizeof(buf2));
1156 mprint(2, (db, DSIZE-(db-(*debug_out)),
1157 " no, checking for \"%.100s\" in pine.exe dir\n",
1158 buf2));
1159 if(can_access(buf2, ACCESS_EXISTS) == 0){
1160 /* found it! */
1161 mprint(2, (db, DSIZE-(db-(*debug_out)), " found it\n"));
1162 strncpy(buf, buf2, sizeof(buf)-1);
1163 buf[sizeof(buf)-1] = '\0';
1164 strncpy(l_pinerc, buf2, sizeof(l_pinerc)-1);
1165 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1167 else{
1168 #ifdef _WINDOWS
1169 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, checking in registry\n"));
1170 if(mswin_reg(MSWR_OP_GET, MSWR_PINE_RC,
1171 buf2, sizeof(buf2))){
1172 strncpy(buf, buf2, sizeof(buf)-1);
1173 buf[sizeof(buf)-1] = '\0';
1174 if(!IS_REMOTE(buf2)){
1175 strncpy(l_pinerc, buf2, sizeof(l_pinerc)-1);
1176 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1179 * Now buf is the pinerc to be used, l_pinerc is
1180 * the directory, which may be either same as buf
1181 * or it may be $HOME\PINE if registry gives us
1182 * a remote pinerc.
1184 mprint(2, (db, DSIZE-(db-(*debug_out)), " found \"%.100s\" in registry\n",
1185 buf));
1187 else{
1188 nopinerc = 1;
1189 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found, asking user\n"));
1191 #else
1192 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found\n"));
1193 #endif
1198 * Buf is the pinerc (could be remote if from registry)
1199 * and l_pinerc is the local pinerc, which may not exist.
1202 else{ /* $HOME\PINE not a writable dir */
1204 * We notice that the order of checking in the registry
1205 * and checking in the ALPINE.EXE directory are different
1206 * in this case versus the is_writable_dir(buf2) case, and
1207 * that does sort of look like a bug. However,
1208 * we don't think this is a bug since we did it on purpose
1209 * a long time ago. So even though we can't remember why
1210 * it is this way, we think we would rediscover why if we
1211 * changed it! So we won't change it.
1215 * Change the default to use to the ALPINE.EXE directory.
1217 build_path(buf, ps->pine_dir, SYSTEM_PINERC, sizeof(buf));
1218 strncpy(l_pinerc, buf, sizeof(l_pinerc)-1);
1219 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1220 #ifdef _WINDOWS
1221 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, not writable, checking in registry\n"));
1222 /* if in registry, use that value */
1223 if(mswin_reg(MSWR_OP_GET, MSWR_PINE_RC, buf2, sizeof(buf2))){
1224 strncpy(buf, buf2, sizeof(buf)-1);
1225 buf[sizeof(buf)-1] = '\0';
1226 mprint(2, (db, DSIZE-(db-(*debug_out)), " found \"%.100s\" in registry\n",
1227 buf));
1228 if(!IS_REMOTE(buf)){
1229 strncpy(l_pinerc, buf, sizeof(l_pinerc)-1);
1230 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1233 else{
1234 mprint(2, (db, DSIZE-(db-(*debug_out)),
1235 " no, checking for \"%.100s\" in alpine.exe dir\n",
1236 buf));
1238 if(can_access(buf, ACCESS_EXISTS) == 0){
1239 mprint(2, (db, DSIZE-(db-(*debug_out)), " found it\n"));
1241 else{
1242 nopinerc = 1;
1243 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found, asking user\n"));
1246 #else
1247 mprint(2, (db, DSIZE-(db-(*debug_out)),
1248 " no, checking for \"%.100s\" in alpine.exe dir\n",
1249 buf));
1251 if(can_access(buf, ACCESS_EXISTS) == 0){
1252 mprint(2, (db, DSIZE-(db-(*debug_out)), " found it\n"));
1254 else{
1255 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found, creating it\n"));
1257 #endif
1261 * When we get here we have buf set to the name of the
1262 * pinerc, which could be local or remote. We have l_pinerc
1263 * set to the same as buf if buf is local, and set to another
1264 * name otherwise, hopefully contained in a writable directory.
1266 #ifdef _WINDOWS
1267 if(nopinerc || ps_global->install_flag){
1268 char buf3[MAXPATH+1];
1270 confregset = 0;
1271 strncpy(buf3, buf, MAXPATH);
1272 buf3[MAXPATH] = '\0';
1273 if(os_config_dialog(buf3, MAXPATH,
1274 &confregset, nopinerc) == 0){
1275 strncpy(buf, buf3, MAXPATH);
1276 buf[MAXPATH] = '\0';
1277 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found, creating it\n"));
1278 mprint(2, (db, DSIZE-(db-(*debug_out)), " user says use \"%.100s\"\n", buf));
1279 if(!IS_REMOTE(buf)){
1280 strncpy(l_pinerc, buf, MAXPATH);
1281 l_pinerc[MAXPATH] = '\0';
1284 else{
1285 exit(-1);
1288 #endif
1289 ps->prc = new_pinerc_s(buf);
1292 ps->pinerc = cpystr(l_pinerc);
1295 #if defined(DOS) || defined(OS2)
1297 * The goal here is to set the auxiliary directory in the pinerc variable.
1298 * We are making the assumption that any reference to the pinerc variable
1299 * after this point is used only as a directory in which to store things,
1300 * with the prc variable being the preferred place to store pinerc location.
1301 * If -aux isn't set, then there is no change. -jpf 08/2001
1303 if(ps->aux_files_dir){
1304 l_pinerc[0] = '\0';
1305 build_path(l_pinerc, ps->aux_files_dir, SYSTEM_PINERC,
1306 sizeof(l_pinerc));
1307 if(ps->pinerc) fs_give((void **)&ps->pinerc);
1308 ps->pinerc = cpystr(l_pinerc);
1309 mprint(2, (db, DSIZE-(db-(*debug_out)), "Setting aux_files_dir to \"%.100s\"\n",
1310 ps->aux_files_dir));
1312 #endif
1314 #ifdef _WINDOWS
1315 if(confregset && (ps->update_registry != UREG_NEVER_SET))
1316 mswin_reg(MSWR_OP_SET | ((ps->update_registry == UREG_ALWAYS_SET)
1317 || confregset == 1 ? MSWR_OP_FORCE : 0),
1318 MSWR_PINE_RC,
1319 (ps->prc && ps->prc->name) ?
1320 ps->prc->name : ps->pinerc, (size_t)NULL);
1321 #endif
1324 * Now that we know the default for the PINERC, build NEWSRC default.
1325 * Backward compatibility makes this kind of funky. If what the
1326 * c-client thinks the NEWSRC should be exists *AND* it doesn't
1327 * already exist in the PINERC's dir, use c-client's default, otherwise
1328 * use the one next to the PINERC...
1330 p = last_cmpnt(ps->pinerc);
1331 buf[0] = '\0';
1332 if(p != NULL){
1333 strncpy(buf, ps->pinerc, MIN(p - ps->pinerc, sizeof(buf)-1));
1334 buf[MIN(p - ps->pinerc, sizeof(buf)-1)] = '\0';
1337 mprint(2, (db, DSIZE-(db-(*debug_out)), "Using directory \"%.100s\" for auxiliary files\n", buf));
1338 strncat(buf, "NEWSRC", sizeof(buf)-1-strlen(buf));
1340 if(!(p = (void *) mail_parameters(NULL, GET_NEWSRC, (void *)NULL))
1341 || can_access(p, ACCESS_EXISTS) < 0
1342 || can_access(buf, ACCESS_EXISTS) == 0){
1343 mail_parameters(NULL, SET_NEWSRC, (void *)buf);
1344 GLO_NEWSRC_PATH = cpystr(buf);
1346 else
1347 GLO_NEWSRC_PATH = cpystr(p);
1349 if(ps->pconf){
1350 mprint(2, (db, DSIZE-(db-(*debug_out)), "Global config \"%.100s\" comes from command line\n",
1351 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1353 else{
1354 mprint(2, (db, DSIZE-(db-(*debug_out)),
1355 "Global config not set on cmdline, checking for $PINECONF\n"));
1358 if(!ps->pconf && (p = getenv("PINECONF"))){
1359 ps->pconf = new_pinerc_s(p);
1360 if(ps->pconf){
1361 mprint(2, (db, DSIZE-(db-(*debug_out)),
1362 " yes, global config \"%.100s\" comes from $PINECONF\n",
1363 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1366 #ifdef _WINDOWS
1367 else if(!ps->pconf
1368 && mswin_reg(MSWR_OP_GET, MSWR_PINE_CONF, buf2, sizeof(buf2))){
1369 ps->pconf = new_pinerc_s(buf2);
1370 if(ps->pconf){
1371 mprint(2, (db, DSIZE-(db-(*debug_out)),
1372 " yes, global config \"%.100s\" comes from Registry\n",
1373 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1376 #endif
1377 if(!ps->pconf){
1378 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, there is no global config\n"));
1380 #ifdef _WINDOWS
1381 else if (ps->pconf && ps->pconf->name &&
1382 (ps->update_registry != UREG_NEVER_SET)){
1383 mswin_reg(MSWR_OP_SET | ((ps->update_registry == UREG_ALWAYS_SET)
1384 ? MSWR_OP_FORCE : 0),
1385 MSWR_PINE_CONF,
1386 ps->pconf->name, (size_t)NULL);
1388 #endif
1390 if(!ps->prc)
1391 ps->prc = new_pinerc_s(ps->pinerc);
1393 if(ps->exceptions){
1394 mprint(2, (db, DSIZE-(db-(*debug_out)),
1395 "Exceptions config \"%.100s\" comes from command line\n",
1396 ps->exceptions));
1398 else{
1399 mprint(2, (db, DSIZE-(db-(*debug_out)),
1400 "Exceptions config not set on cmdline, checking for $PINERCEX\n"));
1404 * Exceptions is done slightly differently from pinerc. Instead of setting
1405 * post_prc in args.c we just set the string and use it here. We do
1406 * that so that we can put it in the same directory as the pinerc if
1407 * exceptions is a relative name, and pinerc may not be set until here.
1409 * First, just like for pinerc, check environment variable if it wasn't
1410 * set on the command line.
1412 if(!ps->exceptions && (p = getenv("PINERCEX")) && *p){
1413 ps->exceptions = cpystr(p);
1414 if(ps->exceptions){
1415 mprint(2, (db, DSIZE-(db-(*debug_out)),
1416 " yes, exceptions config \"%.100s\" comes from $PINERCEX\n",
1417 ps->exceptions));
1422 * If still not set, try specific file in same dir as pinerc.
1423 * Only use it if the file exists.
1425 if(!ps->exceptions){
1426 p = last_cmpnt(ps->pinerc);
1427 buf[0] = '\0';
1428 if(p != NULL){
1429 strncpy(buf, ps->pinerc, MIN(p - ps->pinerc, sizeof(buf)-1));
1430 buf[MIN(p - ps->pinerc, sizeof(buf)-1)] = '\0';
1433 strncat(buf, "PINERCEX", sizeof(buf)-1-strlen(buf));
1435 mprint(2, (db, DSIZE-(db-(*debug_out)),
1436 " no, checking for default \"%.100s\" in pinerc dir\n", buf));
1437 if(can_access(buf, ACCESS_EXISTS) == 0) /* found it! */
1438 ps->exceptions = cpystr(buf);
1440 if(ps->exceptions){
1441 mprint(2, (db, DSIZE-(db-(*debug_out)),
1442 " yes, exceptions config \"%.100s\" comes from default\n",
1443 ps->exceptions));
1445 else{
1446 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, there is no exceptions config\n"));
1450 #else /* unix */
1452 if(ps->pconf){
1453 mprint(2, (db, DSIZE-(db-(*debug_out)), "Global config \"%.100s\" comes from command line\n",
1454 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1457 if(!ps->pconf){
1458 ps->pconf = new_pinerc_s(SYSTEM_PINERC);
1459 if(ps->pconf){
1460 mprint(2, (db, DSIZE-(db-(*debug_out)), "Global config \"%.100s\" is default\n",
1461 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1465 if(!ps->pconf){
1466 mprint(2, (db, DSIZE-(db-(*debug_out)), "No global config!\n"));
1469 if(ps->prc){
1470 mprint(2, (db, DSIZE-(db-(*debug_out)), "Personal config \"%.100s\" comes from command line\n",
1471 (ps->prc && ps->prc->name) ? ps->prc->name : "<no name>"));
1474 if(!ps->pinerc){
1475 build_path(buf, ps->home_dir, ".pinerc", sizeof(buf));
1476 ps->pinerc = cpystr(buf);
1479 if(!ps->prc){
1480 ps->prc = new_pinerc_s(ps->pinerc);
1481 if(ps->prc){
1482 mprint(2, (db, DSIZE-(db-(*debug_out)), "Personal config \"%.100s\" is default\n",
1483 (ps->prc && ps->prc->name) ? ps->prc->name : "<no name>"));
1487 if(!ps->prc){
1488 mprint(2, (db, DSIZE-(db-(*debug_out)), "No personal config!\n"));
1491 if(ps->exceptions){
1492 mprint(2, (db, DSIZE-(db-(*debug_out)),
1493 "Exceptions config \"%.100s\" comes from command line\n",
1494 ps->exceptions));
1498 * If not set, try specific file in same dir as pinerc.
1499 * Only use it if the file exists.
1501 if(!ps->exceptions){
1502 p = last_cmpnt(ps->pinerc);
1503 buf[0] = '\0';
1504 if(p != NULL){
1505 strncpy(buf, ps->pinerc, MIN(p - ps->pinerc, sizeof(buf)-1));
1506 buf[MIN(p - ps->pinerc, sizeof(buf)-1)] = '\0';
1509 strncat(buf, ".pinercex", sizeof(buf)-1-strlen(buf));
1510 mprint(2, (db, DSIZE-(db-(*debug_out)), "Exceptions config not set on cmdline\n checking for default \"%.100s\" in pinerc dir\n", buf));
1512 if(can_access(buf, ACCESS_EXISTS) == 0) /* found it! */
1513 ps->exceptions = cpystr(buf);
1515 if(ps->exceptions){
1516 mprint(2, (db, DSIZE-(db-(*debug_out)),
1517 " yes, exceptions config \"%.100s\" is default\n",
1518 ps->exceptions));
1520 else{
1521 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, there is no exceptions config\n"));
1525 #endif /* unix */
1527 if(ps->exceptions){
1529 if(!IS_REMOTE(ps->exceptions) &&
1530 !is_absolute_path(ps->exceptions)){
1531 #if defined(DOS) || defined(OS2)
1532 p = last_cmpnt(ps->pinerc);
1533 buf[0] = '\0';
1534 if(p != NULL){
1535 strncpy(buf, ps->pinerc, MIN(p - ps->pinerc, sizeof(buf)-1));
1536 buf[MIN(p - ps->pinerc, sizeof(buf)-1)] = '\0';
1539 strncat(buf, ps->exceptions, sizeof(buf)-1-strlen(buf));
1540 #else
1541 build_path(buf, ps->home_dir, ps->exceptions, sizeof(buf));
1542 #endif
1544 else{
1545 strncpy(buf, ps->exceptions, sizeof(buf)-1);
1546 buf[sizeof(buf)-1] = '\0';
1549 ps->post_prc = new_pinerc_s(buf);
1551 fs_give((void **)&ps->exceptions);
1554 mprint(2, (db, DSIZE-(db-(*debug_out)), "\n Global config: %.100s\n",
1555 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<none>"));
1556 mprint(2, (db, DSIZE-(db-(*debug_out)), " Personal config: %.100s\n",
1557 (ps->prc && ps->prc->name) ? ps->prc->name : "<none>"));
1558 mprint(2, (db, DSIZE-(db-(*debug_out)), " Exceptions config: %.100s\n",
1559 (ps->post_prc && ps->post_prc->name) ? ps->post_prc->name
1560 : "<none>"));
1561 #if !defined(DOS) && !defined(OS2)
1562 if(SYSTEM_PINERC_FIXED){
1563 mprint(2, (db, DSIZE-(db-(*debug_out)), " Fixed config: %.100s\n", SYSTEM_PINERC_FIXED));
1565 #endif
1567 mprint(2, (db, DSIZE-(db-(*debug_out)), "\n"));
1571 /*----------------------------------------------------------------------
1572 Initialize the variables
1574 Args: ps -- The usual pine structure
1576 Result:
1578 This reads the system pine configuration file and the user's pine
1579 configuration file ".pinerc" and places the results in the variables
1580 structure. It sorts out what was read and sets a few other variables
1581 based on the contents.
1582 ----*/
1583 void
1584 init_vars(struct pine *ps, void (*cmds_f) (struct pine *, char **))
1586 char buf[MAXPATH+1], *p, *q, **s;
1587 register struct variable *vars = ps->vars;
1588 int obs_header_in_reply = 0, /* the obs_ variables are to */
1589 obs_old_style_reply = 0, /* support backwards compatibility */
1590 obs_save_by_sender, i, def_sort_rev;
1591 long rvl;
1592 PINERC_S *fixedprc = NULL;
1593 FeatureLevel obs_feature_level;
1594 char *fromcharset = NULL;
1595 char *err = NULL;
1597 dprint((5, "init_vars:\n"));
1599 /*--- The defaults here are defined in os-xxx.h so they can vary
1600 per machine ---*/
1602 GLO_PRINTER = cpystr(DF_DEFAULT_PRINTER);
1603 GLO_ELM_STYLE_SAVE = cpystr(DF_ELM_STYLE_SAVE);
1604 GLO_SAVE_BY_SENDER = cpystr(DF_SAVE_BY_SENDER);
1605 GLO_HEADER_IN_REPLY = cpystr(DF_HEADER_IN_REPLY);
1606 GLO_INBOX_PATH = cpystr("inbox");
1607 GLO_DEFAULT_FCC = cpystr(DF_DEFAULT_FCC);
1608 GLO_DEFAULT_SAVE_FOLDER = cpystr(DEFAULT_SAVE);
1609 GLO_POSTPONED_FOLDER = cpystr(POSTPONED_MSGS);
1610 GLO_TRASH_FOLDER = cpystr(TRASH_FOLDER);
1611 GLO_USE_ONLY_DOMAIN_NAME = cpystr(DF_USE_ONLY_DOMAIN_NAME);
1612 GLO_FEATURE_LEVEL = cpystr("sappling");
1613 GLO_OLD_STYLE_REPLY = cpystr(DF_OLD_STYLE_REPLY);
1614 GLO_SORT_KEY = cpystr(DF_SORT_KEY);
1615 GLO_SAVED_MSG_NAME_RULE = cpystr(DF_SAVED_MSG_NAME_RULE);
1616 GLO_FCC_RULE = cpystr(DF_FCC_RULE);
1617 GLO_AB_SORT_RULE = cpystr(DF_AB_SORT_RULE);
1618 GLO_FLD_SORT_RULE = cpystr(DF_FLD_SORT_RULE);
1619 GLO_SIGNATURE_FILE = cpystr(DF_SIGNATURE_FILE);
1620 GLO_MAIL_DIRECTORY = cpystr(DF_MAIL_DIRECTORY);
1621 GLO_REMOTE_ABOOK_HISTORY = cpystr(DF_REMOTE_ABOOK_HISTORY);
1622 GLO_REMOTE_ABOOK_VALIDITY = cpystr(DF_REMOTE_ABOOK_VALIDITY);
1623 GLO_GOTO_DEFAULT_RULE = cpystr(DF_GOTO_DEFAULT_RULE);
1624 GLO_INCOMING_STARTUP = cpystr(DF_INCOMING_STARTUP);
1625 GLO_PRUNING_RULE = cpystr(DF_PRUNING_RULE);
1626 GLO_REOPEN_RULE = cpystr(DF_REOPEN_RULE);
1627 GLO_THREAD_DISP_STYLE = cpystr(DF_THREAD_DISP_STYLE);
1628 GLO_THREAD_INDEX_STYLE = cpystr(DF_THREAD_INDEX_STYLE);
1629 GLO_THREAD_MORE_CHAR = cpystr(DF_THREAD_MORE_CHAR);
1630 GLO_THREAD_EXP_CHAR = cpystr(DF_THREAD_EXP_CHAR);
1631 GLO_THREAD_LASTREPLY_CHAR = cpystr(DF_THREAD_LASTREPLY_CHAR);
1632 GLO_BUGS_FULLNAME = cpystr("Sorry No Address");
1633 GLO_BUGS_ADDRESS = cpystr("nobody");
1634 GLO_SUGGEST_FULLNAME = cpystr("Sorry No Address");
1635 GLO_SUGGEST_ADDRESS = cpystr("nobody");
1636 GLO_LOCAL_FULLNAME = cpystr(DF_LOCAL_FULLNAME);
1637 GLO_LOCAL_ADDRESS = cpystr(DF_LOCAL_ADDRESS);
1638 GLO_OVERLAP = cpystr(DF_OVERLAP);
1639 GLO_SLEEP = cpystr("60");
1640 GLO_MAXREMSTREAM = cpystr(DF_MAXREMSTREAM);
1641 GLO_MARGIN = cpystr(DF_MARGIN);
1642 GLO_FILLCOL = cpystr(DF_FILLCOL);
1643 GLO_DEADLETS = cpystr(DF_DEADLETS);
1644 GLO_NMW_WIDTH = cpystr(DF_NMW_WIDTH);
1645 GLO_REPLY_STRING = cpystr("> ");
1646 GLO_REPLY_INTRO = cpystr(DEFAULT_REPLY_INTRO);
1647 GLO_EMPTY_HDR_MSG = cpystr("undisclosed-recipients");
1648 GLO_STATUS_MSG_DELAY = cpystr("0");
1649 GLO_ACTIVE_MSG_INTERVAL = cpystr("12");
1650 GLO_USERINPUTTIMEO = cpystr("0");
1651 GLO_INCCHECKTIMEO = cpystr("5");
1652 GLO_INCCHECKINTERVAL = cpystr("180");
1653 GLO_INC2NDCHECKINTERVAL = cpystr("180");
1654 GLO_MAILCHECK = cpystr(DF_MAILCHECK);
1655 GLO_MAILCHECKNONCURR = cpystr("0");
1656 GLO_MAILDROPCHECK = cpystr(DF_MAILDROPCHECK);
1657 GLO_NNTPRANGE = cpystr("0");
1658 GLO_KBLOCK_PASSWD_COUNT = cpystr(DF_KBLOCK_PASSWD_COUNT);
1659 GLO_INDEX_COLOR_STYLE = cpystr("flip-colors");
1660 GLO_TITLEBAR_COLOR_STYLE = cpystr("default");
1661 GLO_POST_CHAR_SET = cpystr("UTF-8");
1662 #ifdef DF_FOLDER_EXTENSION
1663 GLO_FOLDER_EXTENSION = cpystr(DF_FOLDER_EXTENSION);
1664 #endif
1665 #ifdef DF_SMTP_SERVER
1666 GLO_SMTP_SERVER = parse_list(DF_SMTP_SERVER, 1,
1667 PL_REMSURRQUOT, NULL);
1668 #endif
1670 #ifdef DF_SSHPATH
1671 GLO_SSHPATH = cpystr(DF_SSHPATH);
1672 #endif
1673 #ifdef DF_SSHCMD
1674 GLO_SSHCMD = cpystr(DF_SSHCMD);
1675 #endif
1677 #ifndef _WINDOWS
1678 GLO_COLOR_STYLE = cpystr("no-color");
1679 GLO_NORM_FORE_COLOR = cpystr(DEFAULT_NORM_FORE_RGB);
1680 GLO_NORM_BACK_COLOR = cpystr(DEFAULT_NORM_BACK_RGB);
1681 #endif
1682 GLO_TITLE_FORE_COLOR = cpystr(DEFAULT_TITLE_FORE_RGB);
1683 GLO_TITLE_BACK_COLOR = cpystr(DEFAULT_TITLE_BACK_RGB);
1684 GLO_TITLECLOSED_FORE_COLOR = cpystr(DEFAULT_TITLECLOSED_FORE_RGB);
1685 GLO_TITLECLOSED_BACK_COLOR = cpystr(DEFAULT_TITLECLOSED_BACK_RGB);
1686 GLO_FOLDER_FORE_COLOR = cpystr(DEFAULT_NORM_FORE_RGB);
1687 GLO_DIRECTORY_FORE_COLOR = cpystr(DEFAULT_NORM_FORE_RGB);
1688 GLO_FOLDER_LIST_FORE_COLOR = cpystr(DEFAULT_NORM_FORE_RGB);
1689 GLO_METAMSG_FORE_COLOR = cpystr(DEFAULT_METAMSG_FORE_RGB);
1690 GLO_METAMSG_BACK_COLOR = cpystr(DEFAULT_METAMSG_BACK_RGB);
1691 GLO_QUOTE1_FORE_COLOR = cpystr(DEFAULT_QUOTE1_FORE_RGB);
1692 GLO_QUOTE1_BACK_COLOR = cpystr(DEFAULT_QUOTE1_BACK_RGB);
1693 GLO_QUOTE2_FORE_COLOR = cpystr(DEFAULT_QUOTE2_FORE_RGB);
1694 GLO_QUOTE2_BACK_COLOR = cpystr(DEFAULT_QUOTE2_BACK_RGB);
1695 GLO_QUOTE3_FORE_COLOR = cpystr(DEFAULT_QUOTE3_FORE_RGB);
1696 GLO_QUOTE3_BACK_COLOR = cpystr(DEFAULT_QUOTE3_BACK_RGB);
1697 GLO_SIGNATURE_FORE_COLOR = cpystr(DEFAULT_SIGNATURE_FORE_RGB);
1698 GLO_SIGNATURE_BACK_COLOR = cpystr(DEFAULT_SIGNATURE_BACK_RGB);
1699 GLO_IND_PLUS_FORE_COLOR = cpystr(DEFAULT_IND_PLUS_FORE_RGB);
1700 GLO_IND_PLUS_BACK_COLOR = cpystr(DEFAULT_IND_PLUS_BACK_RGB);
1701 GLO_IND_IMP_FORE_COLOR = cpystr(DEFAULT_IND_IMP_FORE_RGB);
1702 GLO_IND_IMP_BACK_COLOR = cpystr(DEFAULT_IND_IMP_BACK_RGB);
1703 GLO_IND_ANS_FORE_COLOR = cpystr(DEFAULT_IND_ANS_FORE_RGB);
1704 GLO_IND_ANS_BACK_COLOR = cpystr(DEFAULT_IND_ANS_BACK_RGB);
1705 GLO_IND_NEW_FORE_COLOR = cpystr(DEFAULT_IND_NEW_FORE_RGB);
1706 GLO_IND_NEW_BACK_COLOR = cpystr(DEFAULT_IND_NEW_BACK_RGB);
1707 GLO_IND_OP_FORE_COLOR = cpystr(DEFAULT_IND_OP_FORE_RGB);
1708 GLO_IND_OP_BACK_COLOR = cpystr(DEFAULT_IND_OP_BACK_RGB);
1709 GLO_VIEW_MARGIN_LEFT = cpystr("0");
1710 GLO_VIEW_MARGIN_RIGHT = cpystr(DF_VIEW_MARGIN_RIGHT);
1711 GLO_QUOTE_SUPPRESSION = cpystr(DF_QUOTE_SUPPRESSION);
1712 GLO_KW_BRACES = cpystr("\"{\" \"} \"");
1713 GLO_OPENING_SEP = cpystr(" - ");
1714 GLO_WP_INDEXHEIGHT = cpystr("24");
1715 GLO_WP_AGGSTATE = cpystr("1");
1716 GLO_WP_STATE = cpystr("");
1717 #ifdef DF_VAR_SPELLER
1718 GLO_SPELLER = cpystr(DF_VAR_SPELLER);
1719 #endif
1720 #ifdef SMIME
1721 if(ps->smimedir){
1722 snprintf(tmp_20k_buf, SIZEOF_20KBUF, "%s/public", ps->smimedir);
1723 tmp_20k_buf[SIZEOF_20KBUF-1] = '\0';
1724 GLO_PUBLICCERT_DIR = cpystr(tmp_20k_buf);
1726 snprintf(tmp_20k_buf, SIZEOF_20KBUF, "%s/private", ps->smimedir);
1727 tmp_20k_buf[SIZEOF_20KBUF-1] = '\0';
1728 GLO_PRIVATEKEY_DIR = cpystr(tmp_20k_buf);
1730 snprintf(tmp_20k_buf, SIZEOF_20KBUF, "%s/ca", ps->smimedir);
1731 tmp_20k_buf[SIZEOF_20KBUF-1] = '\0';
1732 GLO_CACERT_DIR = cpystr(tmp_20k_buf);
1734 else{
1735 GLO_PUBLICCERT_DIR = cpystr(DF_PUBLICCERT_DIR);
1736 GLO_PRIVATEKEY_DIR = cpystr(DF_PRIVATEKEY_DIR);
1737 GLO_CACERT_DIR = cpystr(DF_CACERT_DIR);
1739 #endif /* SMIME */
1742 * Default first value for addrbook list if none set.
1743 * We also want to be sure to set global_val to the default
1744 * if is_fixed, so that address-book= will cause the default to happen.
1746 if(!GLO_ADDRESSBOOK && !FIX_ADDRESSBOOK)
1747 GLO_ADDRESSBOOK = parse_list(DF_ADDRESSBOOK, 1, 0, NULL);
1750 * Default first value if none set.
1752 if(!GLO_STANDARD_PRINTER && !FIX_STANDARD_PRINTER)
1753 GLO_STANDARD_PRINTER = parse_list(DF_STANDARD_PRINTER, 1, 0, NULL);
1756 * Defining this default sshpath should cause ssh to be preferred over rsh
1757 * when attempting imapd preauth calls.
1759 #ifdef DF_SSHPATH
1760 if(DF_SSHPATH
1761 && is_absolute_path(DF_SSHPATH)
1762 && can_access(DF_SSHPATH, EXECUTE_ACCESS) == 0){
1763 mail_parameters(NULL, SET_SSHPATH, (void *) DF_SSHPATH);
1765 #endif
1767 * It isn't usually necessary to define this.
1769 #ifdef DF_SSHCMD
1770 if(DF_SSHCMD){
1771 mail_parameters(NULL, SET_SSHCOMMAND, (void *) DF_SSHCMD);
1773 #endif
1775 #if !defined(DOS) && !defined(OS2)
1777 * This is here instead of in init_pinerc so that we can get by without
1778 * having a global fixedprc, since we don't need it anymore after this.
1780 fixedprc = new_pinerc_s(SYSTEM_PINERC_FIXED);
1781 #endif
1783 if(ps->pconf){
1784 read_pinerc(ps->pconf, vars, ParseGlobal);
1785 if(ps->pconf->type != Loc)
1786 rd_close_remote(ps->pconf->rd);
1789 if(ps->prc){
1790 read_pinerc(ps->prc, vars, ParsePers);
1791 if(ps->prc->type != Loc)
1792 rd_close_remote(ps->prc->rd);
1795 if(ps->post_prc){
1796 read_pinerc(ps->post_prc, vars, ParsePersPost);
1797 if(ps->post_prc->type != Loc)
1798 rd_close_remote(ps->post_prc->rd);
1801 if(fixedprc){
1802 read_pinerc(fixedprc, vars, ParseFixed);
1803 free_pinerc_s(&fixedprc);
1806 ps->ew_for_except_vars = ps->post_prc ? Post : Main;
1808 if(ps->exit_if_no_pinerc && ps->first_time_user){
1810 /* TRANSLATORS: -bail is a literal option name, don't change it. */
1811 exceptional_exit(_("Exiting because -bail option is set and config file doesn't exist."), -1);
1815 * Convert everything having to do with the config to UTF-8
1816 * in order to avoid having to worry about it all over the
1817 * place.
1818 * Set the character-set first so that we may use that in
1819 * the conversion process.
1821 set_collation(0, 1);
1823 #ifndef _WINDOWS
1824 #if (HAVE_LANGINFO_H && defined(CODESET))
1826 if(output_charset_is_supported(nl_langinfo_codeset_wrapper()))
1827 ps->GLO_CHAR_SET = cpystr(nl_langinfo_codeset_wrapper());
1828 else{
1829 ps->GLO_CHAR_SET = cpystr("UTF-8");
1830 dprint((1,"nl_langinfo(CODESET) returns unrecognized value=\"%s\", using UTF-8 as default\n", (p=nl_langinfo(CODESET)) ? p : ""));
1832 #else
1833 ps->GLO_CHAR_SET = cpystr("UTF-8");
1834 #endif
1836 set_current_val(&vars[V_CHAR_SET], TRUE, TRUE);
1837 set_current_val(&vars[V_OLD_CHAR_SET], TRUE, TRUE);
1838 set_current_val(&vars[V_KEY_CHAR_SET], TRUE, TRUE);
1839 #endif /* ! _WINDOWS */
1841 set_current_val(&vars[V_POST_CHAR_SET], TRUE, TRUE);
1844 * Also set up the feature list because we need the
1845 * Use-System-Translation feature to set up the charmaps.
1848 /* way obsolete, backwards compatibility */
1849 set_current_val(&vars[V_FEATURE_LEVEL], TRUE, TRUE);
1850 if(strucmp(VAR_FEATURE_LEVEL, "seedling") == 0)
1851 obs_feature_level = Seedling;
1852 else if(strucmp(VAR_FEATURE_LEVEL, "old-growth") == 0)
1853 obs_feature_level = Seasoned;
1854 else
1855 obs_feature_level = Sapling;
1857 /* obsolete, backwards compatibility */
1858 set_current_val(&vars[V_OLD_STYLE_REPLY], TRUE, TRUE);
1859 obs_old_style_reply = !strucmp(VAR_OLD_STYLE_REPLY, "yes");
1861 set_feature_list_current_val(&vars[V_FEATURE_LIST]);
1862 process_feature_list(ps, VAR_FEATURE_LIST,
1863 (obs_feature_level == Seasoned) ? 1 : 0,
1864 obs_header_in_reply, obs_old_style_reply);
1868 * Redo set_collation call with correct value for collation,
1869 * but we're hardwiring ctype on now. That's because nl_langinfo()
1870 * call needs it and system-dependent wcwidth and wcrtomb functions
1871 * need it.
1873 set_collation(F_OFF(F_DISABLE_SETLOCALE_COLLATE, ps_global), 1);
1876 * Set up to send the correct sequence of bytes to the display terminal.
1879 if(reset_character_set_stuff(&err) == -1)
1880 alpine_panic(err ? err : "trouble with character set setup");
1881 else if(err){
1882 init_error(ps, SM_ORDER | SM_DING, 3, 5, err);
1883 fs_give((void **) &err);
1887 * Now we use the configvars from above to convert the rest
1888 * to UTF-8. That should be ok because the ones above should
1889 * be ASCII.
1891 if(ps->keyboard_charmap && strucmp(ps->keyboard_charmap, "UTF-8")
1892 && strucmp(ps->keyboard_charmap, "US-ASCII"))
1893 fromcharset = ps->keyboard_charmap;
1894 else if(ps->display_charmap && strucmp(ps->display_charmap, "UTF-8")
1895 && strucmp(ps->display_charmap, "US-ASCII"))
1896 fromcharset = ps->display_charmap;
1897 #ifndef _WINDOWS
1898 else if(VAR_OLD_CHAR_SET && strucmp(VAR_OLD_CHAR_SET, "UTF-8")
1899 && strucmp(VAR_OLD_CHAR_SET, "US-ASCII"))
1900 fromcharset = VAR_OLD_CHAR_SET;
1901 #endif /* ! _WINDOWS */
1903 convert_configvars_to_utf8(vars, fromcharset);
1906 * If we already set this while reading the remote pinerc, don't
1907 * change it.
1909 if(!VAR_REMOTE_ABOOK_METADATA || !VAR_REMOTE_ABOOK_METADATA[0])
1910 set_current_val(&vars[V_REMOTE_ABOOK_METADATA], TRUE, TRUE);
1913 * mail-directory variable is obsolete, put its value in
1914 * default folder-collection list
1916 set_current_val(&vars[V_MAIL_DIRECTORY], TRUE, TRUE);
1917 if(!GLO_FOLDER_SPEC){
1918 build_path(tmp_20k_buf, VAR_MAIL_DIRECTORY, "[]", SIZEOF_20KBUF);
1919 GLO_FOLDER_SPEC = parse_list(tmp_20k_buf, 1, 0, NULL);
1922 set_current_val(&vars[V_FOLDER_SPEC], TRUE, TRUE);
1924 set_current_val(&vars[V_NNTP_SERVER], TRUE, TRUE);
1925 for(i = 0; VAR_NNTP_SERVER && VAR_NNTP_SERVER[i]; i++)
1926 removing_quotes(VAR_NNTP_SERVER[i]);
1928 set_news_spec_current_val(TRUE, TRUE);
1930 set_current_val(&vars[V_INBOX_PATH], TRUE, TRUE);
1932 set_current_val(&vars[V_USER_DOMAIN], TRUE, TRUE);
1933 if(VAR_USER_DOMAIN
1934 && VAR_USER_DOMAIN[0]
1935 && (p = strrindex(VAR_USER_DOMAIN, '@'))){
1936 if(*(++p)){
1937 char *q;
1939 snprintf(tmp_20k_buf, SIZEOF_20KBUF,
1940 "User-domain (%s) cannot contain \"@\", using \"%s\"",
1941 VAR_USER_DOMAIN, p);
1942 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
1943 q = VAR_USER_DOMAIN;
1944 while((*q++ = *p++) != '\0')
1945 ;/* do nothing */
1947 else{
1948 snprintf(tmp_20k_buf, SIZEOF_20KBUF,
1949 "User-domain (%s) cannot contain \"@\", deleting",
1950 VAR_USER_DOMAIN);
1951 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
1952 if(ps->vars[V_USER_DOMAIN].post_user_val.p){
1953 fs_give((void **)&ps->vars[V_USER_DOMAIN].post_user_val.p);
1954 set_current_val(&vars[V_USER_DOMAIN], TRUE, TRUE);
1957 if(VAR_USER_DOMAIN
1958 && VAR_USER_DOMAIN[0]
1959 && (p = strrindex(VAR_USER_DOMAIN, '@'))){
1960 if(ps->vars[V_USER_DOMAIN].main_user_val.p){
1961 fs_give((void **)&ps->vars[V_USER_DOMAIN].main_user_val.p);
1962 set_current_val(&vars[V_USER_DOMAIN], TRUE, TRUE);
1968 set_current_val(&vars[V_USE_ONLY_DOMAIN_NAME], TRUE, TRUE);
1969 set_current_val(&vars[V_REPLY_STRING], TRUE, TRUE);
1970 set_current_val(&vars[V_WORDSEPS], TRUE, TRUE);
1971 set_current_val(&vars[V_QUOTE_REPLACE_STRING], TRUE, TRUE);
1972 set_current_val(&vars[V_REPLY_INTRO], TRUE, TRUE);
1973 set_current_val(&vars[V_EMPTY_HDR_MSG], TRUE, TRUE);
1975 #ifdef ENABLE_LDAP
1976 set_current_val(&vars[V_LDAP_SERVERS], TRUE, TRUE);
1977 #endif /* ENABLE_LDAP */
1979 /* obsolete, backwards compatibility */
1980 set_current_val(&vars[V_HEADER_IN_REPLY], TRUE, TRUE);
1981 obs_header_in_reply=!strucmp(VAR_HEADER_IN_REPLY, "yes");
1983 set_current_val(&vars[V_PERSONAL_PRINT_COMMAND], TRUE, TRUE);
1984 set_current_val(&vars[V_STANDARD_PRINTER], TRUE, TRUE);
1985 set_current_val(&vars[V_PRINTER], TRUE, TRUE);
1986 if(vars[V_PERSONAL_PRINT_COMMAND].is_fixed && !vars[V_PRINTER].is_fixed)
1987 printer_value_check_and_adjust();
1989 set_current_val(&vars[V_LAST_TIME_PRUNE_QUESTION], TRUE, TRUE);
1990 if(VAR_LAST_TIME_PRUNE_QUESTION != NULL){
1991 /* The month value in the file runs from 1-12, the variable here
1992 runs from 0-11; the value in the file used to be 0-11, but we're
1993 fixing it in January */
1994 ps->last_expire_year = atoi(VAR_LAST_TIME_PRUNE_QUESTION);
1995 ps->last_expire_month =
1996 atoi(strindex(VAR_LAST_TIME_PRUNE_QUESTION, '.') + 1);
1997 if(ps->last_expire_month == 0){
1998 /* Fix for 0 because of old bug */
1999 snprintf(buf, sizeof(buf), "%d.%d", ps_global->last_expire_year,
2000 ps_global->last_expire_month + 1);
2001 set_variable(V_LAST_TIME_PRUNE_QUESTION, buf, 1, 1, Main);
2002 }else{
2003 ps->last_expire_month--;
2005 }else{
2006 ps->last_expire_year = -1;
2007 ps->last_expire_month = -1;
2010 set_current_val(&vars[V_BUGS_FULLNAME], TRUE, TRUE);
2011 set_current_val(&vars[V_BUGS_ADDRESS], TRUE, TRUE);
2012 set_current_val(&vars[V_SUGGEST_FULLNAME], TRUE, TRUE);
2013 set_current_val(&vars[V_SUGGEST_ADDRESS], TRUE, TRUE);
2014 set_current_val(&vars[V_LOCAL_FULLNAME], TRUE, TRUE);
2015 set_current_val(&vars[V_LOCAL_ADDRESS], TRUE, TRUE);
2016 set_current_val(&vars[V_BUGS_EXTRAS], TRUE, TRUE);
2017 set_current_val(&vars[V_KBLOCK_PASSWD_COUNT], TRUE, TRUE);
2018 set_current_val(&vars[V_DEFAULT_FCC], TRUE, TRUE);
2019 set_current_val(&vars[V_POSTPONED_FOLDER], TRUE, TRUE);
2020 set_current_val(&vars[V_TRASH_FOLDER], TRUE, TRUE);
2021 set_current_val(&vars[V_READ_MESSAGE_FOLDER], TRUE, TRUE);
2022 set_current_val(&vars[V_FORM_FOLDER], TRUE, TRUE);
2023 set_current_val(&vars[V_EDITOR], TRUE, TRUE);
2024 set_current_val(&vars[V_SPELLER], TRUE, TRUE);
2025 #ifdef _WINDOWS
2026 set_current_val(&vars[V_DICTIONARY], TRUE, TRUE);
2027 #endif /* _WINDOWS */
2028 set_current_val(&vars[V_IMAGE_VIEWER], TRUE, TRUE);
2029 set_current_val(&vars[V_BROWSER], TRUE, TRUE);
2030 set_current_val(&vars[V_HISTORY], TRUE, TRUE);
2031 set_current_val(&vars[V_SMTP_SERVER], TRUE, TRUE);
2032 set_current_val(&vars[V_COMP_HDRS], TRUE, TRUE);
2033 set_current_val(&vars[V_CUSTOM_HDRS], TRUE, TRUE);
2034 set_current_val(&vars[V_SENDMAIL_PATH], TRUE, TRUE);
2035 set_current_val(&vars[V_DISPLAY_FILTERS], TRUE, TRUE);
2036 set_current_val(&vars[V_SEND_FILTER], TRUE, TRUE);
2037 set_current_val(&vars[V_ALT_ADDRS], TRUE, TRUE);
2038 set_current_val(&vars[V_ABOOK_FORMATS], TRUE, TRUE);
2039 set_current_val(&vars[V_KW_BRACES], TRUE, TRUE);
2040 set_current_val(&vars[V_OPENING_SEP], TRUE, TRUE);
2041 set_current_val(&vars[V_UNK_CHAR_SET], TRUE, TRUE);
2042 #ifdef SMIME
2043 set_current_val(&vars[V_PUBLICCERT_DIR], TRUE, TRUE);
2044 set_current_val(&vars[V_PUBLICCERT_CONTAINER], TRUE, TRUE);
2045 set_current_val(&vars[V_PRIVATEKEY_DIR], TRUE, TRUE);
2046 set_current_val(&vars[V_PRIVATEKEY_CONTAINER], TRUE, TRUE);
2047 set_current_val(&vars[V_CACERT_DIR], TRUE, TRUE);
2048 set_current_val(&vars[V_CACERT_CONTAINER], TRUE, TRUE);
2049 #endif /* SMIME */
2051 set_current_val(&vars[V_KEYWORDS], TRUE, TRUE);
2052 ps_global->keywords = init_keyword_list(VAR_KEYWORDS);
2054 set_current_val(&vars[V_OPER_DIR], TRUE, TRUE);
2055 if(VAR_OPER_DIR && !VAR_OPER_DIR[0]){
2056 init_error(ps, SM_ORDER | SM_DING, 3, 5,
2057 "Setting operating-dir to the empty string is not allowed. Will be ignored.");
2058 fs_give((void **)&VAR_OPER_DIR);
2059 if(FIX_OPER_DIR)
2060 fs_give((void **)&FIX_OPER_DIR);
2061 if(GLO_OPER_DIR)
2062 fs_give((void **)&GLO_OPER_DIR);
2063 if(COM_OPER_DIR)
2064 fs_give((void **)&COM_OPER_DIR);
2065 if(ps_global->vars[V_OPER_DIR].post_user_val.p)
2066 fs_give((void **)&ps_global->vars[V_OPER_DIR].post_user_val.p);
2067 if(ps_global->vars[V_OPER_DIR].main_user_val.p)
2068 fs_give((void **)&ps_global->vars[V_OPER_DIR].main_user_val.p);
2071 set_current_val(&vars[V_PERSONAL_PRINT_CATEGORY], TRUE, TRUE);
2072 ps->printer_category = -1;
2073 if(VAR_PERSONAL_PRINT_CATEGORY != NULL)
2074 ps->printer_category = atoi(VAR_PERSONAL_PRINT_CATEGORY);
2076 if(ps->printer_category < 1 || ps->printer_category > 3){
2077 char **tt;
2078 char aname[100], wname[100];
2080 strncpy(aname, ANSI_PRINTER, sizeof(aname));
2081 aname[sizeof(aname)-1] = '\0';
2082 strncat(aname, "-no-formfeed", sizeof(aname)-strlen(aname)-1);
2083 strncpy(wname, WYSE_PRINTER, sizeof(wname));
2084 wname[sizeof(wname)-1] = '\0';
2085 strncat(wname, "-no-formfeed", sizeof(wname)-strlen(wname)-1);
2086 if(strucmp(VAR_PRINTER, ANSI_PRINTER) == 0
2087 || strucmp(VAR_PRINTER, aname) == 0
2088 || strucmp(VAR_PRINTER, WYSE_PRINTER) == 0
2089 || strucmp(VAR_PRINTER, wname) == 0)
2090 ps->printer_category = 1;
2091 else if(VAR_STANDARD_PRINTER && VAR_STANDARD_PRINTER[0]){
2092 for(tt = VAR_STANDARD_PRINTER; *tt; tt++)
2093 if(strucmp(VAR_PRINTER, *tt) == 0)
2094 break;
2096 if(*tt)
2097 ps->printer_category = 2;
2100 /* didn't find it yet */
2101 if(ps->printer_category < 1 || ps->printer_category > 3){
2102 if(VAR_PERSONAL_PRINT_COMMAND && VAR_PERSONAL_PRINT_COMMAND[0]){
2103 for(tt = VAR_PERSONAL_PRINT_COMMAND; *tt; tt++)
2104 if(strucmp(VAR_PRINTER, *tt) == 0)
2105 break;
2107 if(*tt)
2108 ps->printer_category = 3;
2113 set_current_val(&vars[V_SLEEP], TRUE, TRUE);
2114 ps->sleep = i = 60;
2115 if(SVAR_SLEEP(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2116 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2117 else
2118 ps->sleep = i;
2120 set_current_val(&vars[V_OVERLAP], TRUE, TRUE);
2121 ps->viewer_overlap = i = atoi(DF_OVERLAP);
2122 if(SVAR_OVERLAP(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2123 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2124 else
2125 ps->viewer_overlap = i;
2127 set_current_val(&vars[V_MARGIN], TRUE, TRUE);
2128 ps->scroll_margin = i = atoi(DF_MARGIN);
2129 if(SVAR_MARGIN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2130 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2131 else
2132 ps->scroll_margin = i;
2134 set_current_val(&vars[V_FILLCOL], TRUE, TRUE);
2135 ps->composer_fillcol = i = atoi(DF_FILLCOL);
2136 if(SVAR_FILLCOL(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2137 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2138 else
2139 ps->composer_fillcol = i;
2141 set_current_val(&vars[V_QUOTE_SUPPRESSION], TRUE, TRUE);
2142 ps->quote_suppression_threshold = i = atoi(DF_QUOTE_SUPPRESSION);
2143 if(SVAR_QUOTE_SUPPRESSION(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2144 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2145 else{
2146 if(i > 0 && i < Q_SUPP_LIMIT){
2147 snprintf(tmp_20k_buf, SIZEOF_20KBUF,
2148 "Ignoring Quote-Suppression-Threshold value of %.50s, see help",
2149 VAR_QUOTE_SUPPRESSION);
2150 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2152 else{
2153 if(i < 0 && i != Q_DEL_ALL)
2154 ps->quote_suppression_threshold = -i;
2155 else
2156 ps->quote_suppression_threshold = i;
2160 set_current_val(&vars[V_DEADLETS], TRUE, TRUE);
2161 ps->deadlets = i = atoi(DF_DEADLETS);
2162 if(SVAR_DEADLETS(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2163 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2164 else
2165 ps->deadlets = i;
2167 set_current_val(&vars[V_STATUS_MSG_DELAY], TRUE, TRUE);
2168 ps->status_msg_delay = i = 0;
2169 if(SVAR_MSGDLAY(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2170 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2171 else
2172 ps->status_msg_delay = i;
2174 set_current_val(&vars[V_ACTIVE_MSG_INTERVAL], TRUE, TRUE);
2175 ps->active_status_interval = i = 8;
2176 if(SVAR_ACTIVEINTERVAL(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2177 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2178 else
2179 ps->active_status_interval = i;
2181 set_current_val(&vars[V_REMOTE_ABOOK_HISTORY], TRUE, TRUE);
2182 ps->remote_abook_history = i = atoi(DF_REMOTE_ABOOK_HISTORY);
2183 if(SVAR_AB_HIST(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2184 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2185 else
2186 ps->remote_abook_history = i;
2188 set_current_val(&vars[V_REMOTE_ABOOK_VALIDITY], TRUE, TRUE);
2189 ps->remote_abook_validity = i = atoi(DF_REMOTE_ABOOK_VALIDITY);
2190 if(SVAR_AB_VALID(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2191 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2192 else
2193 ps->remote_abook_validity = i;
2195 set_current_val(&vars[V_USERINPUTTIMEO], TRUE, TRUE);
2196 ps->hours_to_timeout = i = 0;
2197 if(SVAR_USER_INPUT(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2198 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2199 else
2200 ps->hours_to_timeout = i;
2202 /* timeo is a regular extern int because it is referenced in pico */
2203 set_current_val(&vars[V_MAILCHECK], TRUE, TRUE);
2204 set_input_timeout(i = 15);
2205 if(SVAR_MAILCHK(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2206 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2207 else
2208 set_input_timeout(i);
2210 set_current_val(&vars[V_MAILCHECKNONCURR], TRUE, TRUE);
2211 ps->check_interval_for_noncurr = i = 0;
2212 if(SVAR_MAILCHKNONCURR(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2213 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2214 else
2215 ps->check_interval_for_noncurr = i;
2217 #ifdef DEBUGJOURNAL
2218 ps->debugmem = 1;
2219 #else
2220 ps->debugmem = 0;
2221 #endif
2223 i = 30;
2224 set_current_val(&vars[V_TCPOPENTIMEO], TRUE, TRUE);
2225 /* this is just for the error, we don't save the result */
2226 if(VAR_TCPOPENTIMEO && SVAR_TCP_OPEN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2227 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2229 i = 15;
2230 set_current_val(&vars[V_TCPREADWARNTIMEO], TRUE, TRUE);
2231 /* this is just for the error, we don't save the result */
2232 if(VAR_TCPREADWARNTIMEO && SVAR_TCP_READWARN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2233 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2235 i = 0;
2236 set_current_val(&vars[V_TCPWRITEWARNTIMEO], TRUE, TRUE);
2237 /* this is just for the error, we don't save the result */
2238 if(VAR_TCPWRITEWARNTIMEO && SVAR_TCP_WRITEWARN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2239 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2241 i = 15;
2242 set_current_val(&vars[V_RSHOPENTIMEO], TRUE, TRUE);
2243 /* this is just for the error, we don't save the result */
2244 if(VAR_RSHOPENTIMEO && SVAR_RSH_OPEN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2245 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2247 i = 15;
2248 set_current_val(&vars[V_SSHOPENTIMEO], TRUE, TRUE);
2249 /* this is just for the error, we don't save the result */
2250 if(VAR_SSHOPENTIMEO && SVAR_SSH_OPEN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2251 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2253 set_current_val(&vars[V_INCCHECKLIST], TRUE, TRUE);
2255 set_current_val(&vars[V_INCCHECKTIMEO], TRUE, TRUE);
2256 ps->inc_check_timeout = i = 5;
2257 if(SVAR_INC_CHECK_TIMEO(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2258 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2259 else
2260 ps->inc_check_timeout = i;
2262 set_current_val(&vars[V_INCCHECKINTERVAL], TRUE, TRUE);
2263 ps->inc_check_interval = i = 180;
2264 if(SVAR_INC_CHECK_INTERV(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2265 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2266 else
2267 ps->inc_check_interval = i;
2269 set_current_val(&vars[V_INC2NDCHECKINTERVAL], TRUE, TRUE);
2270 ps->inc_second_check_interval = i = 180;
2271 if(SVAR_INC_2NDCHECK_INTERV(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2272 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2273 else
2274 ps->inc_second_check_interval = i;
2276 rvl = 60L;
2277 set_current_val(&vars[V_MAILDROPCHECK], TRUE, TRUE);
2278 /* this is just for the error, we don't save the result */
2279 if(VAR_MAILDROPCHECK && SVAR_MAILDCHK(ps, rvl, tmp_20k_buf, SIZEOF_20KBUF))
2280 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2282 rvl = 0L;
2283 set_current_val(&vars[V_NNTPRANGE], TRUE, TRUE);
2284 /* this is just for the error, we don't save the result */
2285 if(VAR_NNTPRANGE && SVAR_NNTPRANGE(ps, rvl, tmp_20k_buf, SIZEOF_20KBUF))
2286 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2288 set_current_val(&vars[V_TCPQUERYTIMEO], TRUE, TRUE);
2289 ps->tcp_query_timeout = i = TO_BAIL_THRESHOLD;
2290 if(VAR_TCPQUERYTIMEO && SVAR_TCP_QUERY(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2291 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2292 else
2293 ps->tcp_query_timeout = i;
2295 set_current_val(&vars[V_QUITQUERYTIMEO], TRUE, TRUE);
2296 ps->close_connection_timeout = i = 0;
2297 if(VAR_QUITQUERYTIMEO && SVAR_QUIT_QUERY_TIMEO(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2298 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2299 else
2300 ps->close_connection_timeout = i;
2302 set_current_val(&vars[V_NEWSRC_PATH], TRUE, TRUE);
2303 if(VAR_NEWSRC_PATH && VAR_NEWSRC_PATH[0])
2304 mail_parameters(NULL, SET_NEWSRC, (void *)VAR_NEWSRC_PATH);
2306 set_current_val(&vars[V_NEWS_ACTIVE_PATH], TRUE, TRUE);
2307 if(VAR_NEWS_ACTIVE_PATH)
2308 mail_parameters(NULL, SET_NEWSACTIVE,
2309 (void *)VAR_NEWS_ACTIVE_PATH);
2311 set_current_val(&vars[V_NEWS_SPOOL_DIR], TRUE, TRUE);
2312 if(VAR_NEWS_SPOOL_DIR)
2313 mail_parameters(NULL, SET_NEWSSPOOL,
2314 (void *)VAR_NEWS_SPOOL_DIR);
2316 /* guarantee a save default */
2317 set_current_val(&vars[V_DEFAULT_SAVE_FOLDER], TRUE, TRUE);
2318 if(!VAR_DEFAULT_SAVE_FOLDER || !VAR_DEFAULT_SAVE_FOLDER[0])
2319 set_variable(V_DEFAULT_SAVE_FOLDER,
2320 (GLO_DEFAULT_SAVE_FOLDER && GLO_DEFAULT_SAVE_FOLDER[0])
2321 ? GLO_DEFAULT_SAVE_FOLDER
2322 : DEFAULT_SAVE, 1, 0, Main);
2324 set_current_val(&vars[V_SIGNATURE_FILE], TRUE, TRUE);
2325 set_current_val(&vars[V_LITERAL_SIG], TRUE, TRUE);
2326 set_current_val(&vars[V_GLOB_ADDRBOOK], TRUE, TRUE);
2327 set_current_val(&vars[V_ADDRESSBOOK], TRUE, TRUE);
2328 set_current_val(&vars[V_FORCED_ABOOK_ENTRY], TRUE, TRUE);
2329 set_current_val(&vars[V_DISABLE_DRIVERS], TRUE, TRUE);
2330 set_current_val(&vars[V_DISABLE_AUTHS], TRUE, TRUE);
2332 set_current_val(&vars[V_VIEW_HEADERS], TRUE, TRUE);
2333 /* strip spaces and colons */
2334 if(ps->VAR_VIEW_HEADERS){
2335 for(s = ps->VAR_VIEW_HEADERS; (q = *s) != NULL; s++){
2336 if(q[0]){
2337 removing_leading_white_space(q);
2338 /* look for colon or space or end */
2339 for(p = q; *p && !isspace((unsigned char)*p) && *p != ':'; p++)
2340 ;/* do nothing */
2342 *p = '\0';
2343 if(strucmp(q, ALL_EXCEPT) == 0)
2344 ps->view_all_except = 1;
2349 set_current_val(&vars[V_VIEW_MARGIN_LEFT], TRUE, TRUE);
2350 set_current_val(&vars[V_VIEW_MARGIN_RIGHT], TRUE, TRUE);
2351 set_current_val(&vars[V_UPLOAD_CMD], TRUE, TRUE);
2352 set_current_val(&vars[V_UPLOAD_CMD_PREFIX], TRUE, TRUE);
2353 set_current_val(&vars[V_DOWNLOAD_CMD], TRUE, TRUE);
2354 set_current_val(&vars[V_DOWNLOAD_CMD_PREFIX], TRUE, TRUE);
2355 set_current_val(&vars[V_MAILCAP_PATH], TRUE, TRUE);
2356 set_current_val(&vars[V_MIMETYPE_PATH], TRUE, TRUE);
2357 #if !defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)
2358 set_current_val(&vars[V_FIFOPATH], TRUE, TRUE);
2359 #endif
2361 set_current_val(&vars[V_RSHPATH], TRUE, TRUE);
2362 if(VAR_RSHPATH
2363 && is_absolute_path(VAR_RSHPATH)
2364 && can_access(VAR_RSHPATH, EXECUTE_ACCESS) == 0){
2365 mail_parameters(NULL, SET_RSHPATH, (void *) VAR_RSHPATH);
2368 set_current_val(&vars[V_RSHCMD], TRUE, TRUE);
2369 if(VAR_RSHCMD){
2370 mail_parameters(NULL, SET_RSHCOMMAND, (void *) VAR_RSHCMD);
2373 set_current_val(&vars[V_SSHPATH], TRUE, TRUE);
2374 if(VAR_SSHPATH) {
2375 if(is_absolute_path(VAR_SSHPATH)
2376 && can_access(VAR_SSHPATH, EXECUTE_ACCESS) == 0){
2377 mail_parameters(NULL, SET_SSHPATH, (void *) VAR_SSHPATH);
2379 else {
2380 mail_parameters(NULL, SET_SSHPATH, (void *) NULL);
2384 set_current_val(&vars[V_SSHCMD], TRUE, TRUE);
2385 if(VAR_SSHCMD) {
2386 if(VAR_SSHCMD[0]) {
2387 mail_parameters(NULL, SET_SSHCOMMAND, (void *) VAR_SSHCMD);
2389 else {
2390 mail_parameters(NULL, SET_SSHCOMMAND, (void *) NULL);
2394 #if defined(DOS) || defined(OS2)
2396 set_current_val(&vars[V_FILE_DIR], TRUE, TRUE);
2398 #ifdef _WINDOWS
2399 set_current_val(&vars[V_FONT_NAME], TRUE, TRUE);
2400 set_current_val(&vars[V_FONT_SIZE], TRUE, TRUE);
2401 set_current_val(&vars[V_FONT_STYLE], TRUE, TRUE);
2402 set_current_val(&vars[V_FONT_CHAR_SET], TRUE, TRUE);
2403 set_current_val(&vars[V_CURSOR_STYLE], TRUE, TRUE);
2404 set_current_val(&vars[V_WINDOW_POSITION], TRUE, TRUE);
2406 if(F_OFF(F_STORE_WINPOS_IN_CONFIG, ps_global)){
2407 /* if win position is in the registry, use it */
2408 if(mswin_reg(MSWR_OP_GET, MSWR_PINE_POS, buf, sizeof(buf))){
2409 if(VAR_WINDOW_POSITION)
2410 fs_give((void **)&VAR_WINDOW_POSITION);
2412 VAR_WINDOW_POSITION = cpystr(buf);
2414 else if(VAR_WINDOW_POSITION
2415 && (ps->update_registry != UREG_NEVER_SET)){
2416 /* otherwise, put it there */
2417 mswin_reg(MSWR_OP_SET | ((ps->update_registry == UREG_ALWAYS_SET)
2418 ? MSWR_OP_FORCE : 0),
2419 MSWR_PINE_POS,
2420 VAR_WINDOW_POSITION, (size_t)NULL);
2424 mswin_setwindow (VAR_FONT_NAME, VAR_FONT_SIZE,
2425 VAR_FONT_STYLE, VAR_WINDOW_POSITION,
2426 VAR_CURSOR_STYLE, VAR_FONT_CHAR_SET);
2428 /* this is no longer used */
2429 if(VAR_WINDOW_POSITION)
2430 fs_give((void **)&VAR_WINDOW_POSITION);
2432 set_current_val(&vars[V_PRINT_FONT_NAME], TRUE, TRUE);
2433 set_current_val(&vars[V_PRINT_FONT_SIZE], TRUE, TRUE);
2434 set_current_val(&vars[V_PRINT_FONT_STYLE], TRUE, TRUE);
2435 set_current_val(&vars[V_PRINT_FONT_CHAR_SET], TRUE, TRUE);
2436 mswin_setprintfont (VAR_PRINT_FONT_NAME,
2437 VAR_PRINT_FONT_SIZE,
2438 VAR_PRINT_FONT_STYLE,
2439 VAR_PRINT_FONT_CHAR_SET);
2441 mswin_setgenhelptextcallback(pcpine_general_help);
2443 mswin_setclosetext ("Use the \"Q\" command to exit Alpine.");
2446 char foreColor[64], backColor[64];
2448 mswin_getwindow(NULL, 0, NULL, 0, NULL, 0, NULL, 0,
2449 foreColor, sizeof(foreColor), backColor, sizeof(backColor),
2450 NULL, 0, NULL, 0);
2451 if(!GLO_NORM_FORE_COLOR)
2452 GLO_NORM_FORE_COLOR = cpystr(foreColor);
2454 if(!GLO_NORM_BACK_COLOR)
2455 GLO_NORM_BACK_COLOR = cpystr(backColor);
2457 #endif /* _WINDOWS */
2458 #endif /* DOS */
2461 * We want the version number to start out as 1.0 for Alpine, but
2462 * we also want to use the same old config file that was used
2463 * with Pine. The Pine version numbers made it up to 4.64 and we
2464 * want Alpine's 1.0 to be larger than 4.64 so we keep a separate
2465 * internal version number which is the real version number
2466 * plus 4. That's what gets written in LAST_VERS_USED.
2468 strncpy(ps->vers_internal, ALPINE_VERSION, sizeof(ps->vers_internal));
2469 ps->vers_internal[sizeof(ps->vers_internal)-1] = '\0';
2470 if(isdigit(ps->vers_internal[0]) && ps->vers_internal[0] < '6')
2471 ps->vers_internal[0] = ps->vers_internal[0] + 4;
2473 set_current_val(&vars[V_LAST_VERS_USED], TRUE, TRUE);
2474 /* Check for special cases first */
2475 if(VAR_LAST_VERS_USED
2476 && (isdigit(ps->vers_internal[0])
2477 && ps->vers_internal[1] == '.'
2478 && isdigit((unsigned char)ps->vers_internal[2])
2479 && isdigit((unsigned char)ps->vers_internal[3])
2480 && isalpha((unsigned char)ps->vers_internal[4])
2481 && strncmp(VAR_LAST_VERS_USED, ps->vers_internal, 4) >= 0)){
2482 ps->show_new_version = 0;
2484 /* Otherwise just do lexicographic comparision... */
2485 else if(VAR_LAST_VERS_USED
2486 && strcmp(VAR_LAST_VERS_USED, ps->vers_internal) >= 0){
2487 ps->show_new_version = 0;
2489 else{
2490 #ifdef _WINDOWS
2492 * If this is the first time we've run a version > 4.40, and there
2493 * is evidence that the config file has not been used by unix pine,
2494 * then we convert color008 to colorlgr, color009 to colormgr, and
2495 * color010 to colordgr. If the config file is being used by
2496 * unix pine then color009 may really supposed to be red, etc.
2497 * Same if we've already run 4.41 or higher. We don't have to do
2498 * anything if we are new to alpine.
2500 ps->pre441 = (VAR_LAST_VERS_USED
2501 && strcmp(VAR_LAST_VERS_USED, "4.40") <= 0);
2502 #endif /* _WINDOWS */
2505 * Don't offer the new version message if we're told not to.
2507 set_current_val(&vars[V_NEW_VER_QUELL], TRUE, TRUE);
2508 ps->show_new_version = !(VAR_NEW_VER_QUELL
2509 && strcmp(ps->vers_internal,
2510 VAR_NEW_VER_QUELL) < 0);
2512 #ifdef _WINDOWS
2513 if(!ps_global->install_flag)
2514 #endif /* _WINDOWS */
2516 if(VAR_LAST_VERS_USED){
2517 strncpy(ps_global->pine_pre_vers, VAR_LAST_VERS_USED,
2518 sizeof(ps_global->pine_pre_vers));
2519 ps_global->pine_pre_vers[sizeof(ps_global->pine_pre_vers)-1] = '\0';
2522 set_variable(V_LAST_VERS_USED, ps->vers_internal, 1, 1,
2523 ps_global->ew_for_except_vars);
2527 /* Obsolete, backwards compatibility */
2528 set_current_val(&vars[V_ELM_STYLE_SAVE], TRUE, TRUE);
2529 /* Also obsolete */
2530 set_current_val(&vars[V_SAVE_BY_SENDER], TRUE, TRUE);
2531 if(!strucmp(VAR_ELM_STYLE_SAVE, "yes"))
2532 set_variable(V_SAVE_BY_SENDER, "yes", 1, 1, Main);
2533 obs_save_by_sender = !strucmp(VAR_SAVE_BY_SENDER, "yes");
2535 set_current_pattern_vals(ps);
2537 set_current_val(&vars[V_INDEX_FORMAT], TRUE, TRUE);
2538 init_index_format(VAR_INDEX_FORMAT, &ps->index_disp_format);
2540 /* this should come after pre441 is set or not */
2541 set_current_color_vals(ps);
2543 set_current_val(&vars[V_RSS_NEWS], TRUE, TRUE);
2544 set_current_val(&vars[V_RSS_WEATHER], TRUE, TRUE);
2545 set_current_val(&vars[V_WP_INDEXHEIGHT], TRUE, TRUE);
2546 set_current_val(&vars[V_WP_INDEXLINES], TRUE, TRUE);
2547 set_current_val(&vars[V_WP_AGGSTATE], TRUE, TRUE);
2548 set_current_val(&vars[V_WP_STATE], TRUE, TRUE);
2549 set_current_val(&vars[V_WP_COLUMNS], TRUE, TRUE);
2551 set_current_val(&vars[V_PRUNED_FOLDERS], TRUE, TRUE);
2552 set_current_val(&vars[V_ARCHIVED_FOLDERS], TRUE, TRUE);
2553 set_current_val(&vars[V_INCOMING_FOLDERS], TRUE, TRUE);
2554 set_current_val(&vars[V_SORT_KEY], TRUE, TRUE);
2555 if(decode_sort(VAR_SORT_KEY, &ps->def_sort, &def_sort_rev) == -1){
2556 snprintf(tmp_20k_buf, SIZEOF_20KBUF, "Sort type \"%.200s\" is invalid", VAR_SORT_KEY);
2557 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2558 ps->def_sort = SortArrival;
2559 ps->def_sort_rev = 0;
2561 else
2562 ps->def_sort_rev = def_sort_rev;
2564 cur_rule_value(&vars[V_SAVED_MSG_NAME_RULE], TRUE, TRUE);
2565 {NAMEVAL_S *v; int i;
2566 for(i = 0; (v = save_msg_rules(i)); i++)
2567 if(v->value == ps_global->save_msg_rule)
2568 break;
2570 /* if save_msg_rule is not default, or is explicitly set to default */
2571 if((ps_global->save_msg_rule != SAV_RULE_DEFLT) ||
2572 (v && v->name &&
2573 (!strucmp(ps_global->vars[V_SAVED_MSG_NAME_RULE].post_user_val.p,
2574 v->name) ||
2575 !strucmp(ps_global->vars[V_SAVED_MSG_NAME_RULE].main_user_val.p,
2576 v->name))))
2577 obs_save_by_sender = 0; /* don't overwrite */
2580 cur_rule_value(&vars[V_FCC_RULE], TRUE, TRUE);
2581 cur_rule_value(&vars[V_AB_SORT_RULE], TRUE, TRUE);
2583 #ifndef _WINDOWS
2584 cur_rule_value(&vars[V_COLOR_STYLE], TRUE, TRUE);
2585 #endif
2587 cur_rule_value(&vars[V_INDEX_COLOR_STYLE], TRUE, TRUE);
2588 cur_rule_value(&vars[V_TITLEBAR_COLOR_STYLE], TRUE, TRUE);
2589 cur_rule_value(&vars[V_FLD_SORT_RULE], TRUE, TRUE);
2590 cur_rule_value(&vars[V_INCOMING_STARTUP], TRUE, TRUE);
2591 cur_rule_value(&vars[V_PRUNING_RULE], TRUE, TRUE);
2592 cur_rule_value(&vars[V_REOPEN_RULE], TRUE, TRUE);
2593 cur_rule_value(&vars[V_GOTO_DEFAULT_RULE], TRUE, TRUE);
2594 cur_rule_value(&vars[V_THREAD_DISP_STYLE], TRUE, TRUE);
2595 cur_rule_value(&vars[V_THREAD_INDEX_STYLE], TRUE, TRUE);
2597 set_current_val(&vars[V_THREAD_MORE_CHAR], TRUE, TRUE);
2598 if(VAR_THREAD_MORE_CHAR[0] && VAR_THREAD_MORE_CHAR[1]){
2599 init_error(ps, SM_ORDER | SM_DING, 3, 5,
2600 _("Only using first character of threading-indicator-character option"));
2601 VAR_THREAD_MORE_CHAR[1] = '\0';
2604 set_current_val(&vars[V_THREAD_EXP_CHAR], TRUE, TRUE);
2605 if(VAR_THREAD_EXP_CHAR[0] && VAR_THREAD_EXP_CHAR[1]){
2606 init_error(ps, SM_ORDER | SM_DING, 3, 5,
2607 _("Only using first character of threading-expanded-character option"));
2608 VAR_THREAD_EXP_CHAR[1] = '\0';
2611 set_current_val(&vars[V_THREAD_LASTREPLY_CHAR], TRUE, TRUE);
2612 if(!VAR_THREAD_LASTREPLY_CHAR[0])
2613 VAR_THREAD_LASTREPLY_CHAR = cpystr(DF_THREAD_LASTREPLY_CHAR);
2615 if(VAR_THREAD_LASTREPLY_CHAR[0] && VAR_THREAD_LASTREPLY_CHAR[1]){
2616 init_error(ps, SM_ORDER | SM_DING, 3, 5,
2617 _("Only using first character of threading-lastreply-character option"));
2618 VAR_THREAD_LASTREPLY_CHAR[1] = '\0';
2621 set_current_val(&vars[V_MAXREMSTREAM], TRUE, TRUE);
2622 ps->s_pool.max_remstream = i = atoi(DF_MAXREMSTREAM);
2623 if(SVAR_MAXREMSTREAM(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2624 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2625 else
2626 ps->s_pool.max_remstream = i;
2628 set_current_val(&vars[V_PERMLOCKED], TRUE, TRUE);
2630 set_current_val(&vars[V_NMW_WIDTH], TRUE, TRUE);
2631 ps->nmw_width = i = atoi(DF_NMW_WIDTH);
2632 if(SVAR_NMW_WIDTH(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2633 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2634 else
2635 ps->nmw_width = i;
2637 /* backwards compatibility */
2638 if(obs_save_by_sender){
2639 ps->save_msg_rule = SAV_RULE_FROM;
2640 set_variable(V_SAVED_MSG_NAME_RULE, "by-from", 1, 1, Main);
2643 /* this should come after process_feature_list because of use_fkeys */
2644 if(!ps->start_in_index)
2645 set_current_val(&vars[V_INIT_CMD_LIST], FALSE, TRUE);
2646 if(VAR_INIT_CMD_LIST && VAR_INIT_CMD_LIST[0] && VAR_INIT_CMD_LIST[0][0])
2647 if(cmds_f)
2648 (*cmds_f)(ps, VAR_INIT_CMD_LIST);
2650 #ifdef _WINDOWS
2651 mswin_set_quit_confirm (F_OFF(F_QUIT_WO_CONFIRM, ps_global));
2652 #endif /* _WINDOWS */
2654 #ifdef DEBUG
2655 dump_configuration(0);
2656 #endif /* DEBUG */
2660 void
2661 convert_configvars_to_utf8(struct variable *vars, char *fromcharset)
2663 struct variable *v;
2666 * Make sure that everything is UTF-8.
2668 for(v = vars; v->name; v++)
2669 convert_configvar_to_utf8(v, fromcharset);
2673 void
2674 convert_configvar_to_utf8(struct variable *v, char *fromcharset)
2676 char **p, *conv, **valptr;
2677 int i;
2680 * Make sure that everything is UTF-8.
2682 if(v->is_list){
2683 for(i = 0; i < 7; i++){
2684 switch(i){
2685 case 1: valptr = v->current_val.l; break;
2686 case 0: valptr = v->main_user_val.l; break;
2687 case 2: valptr = v->changed_val.l; break;
2688 case 3: valptr = v->post_user_val.l; break;
2689 case 4: valptr = v->global_val.l; break;
2690 case 5: valptr = v->fixed_val.l; break;
2691 case 6: valptr = v->cmdline_val.l; break;
2692 default: alpine_panic("bad case in convert_configvar");
2695 if(valptr){
2696 for(p = valptr; *p; p++){
2697 if(**p){
2698 conv = convert_to_utf8(*p, fromcharset, 0);
2699 if(conv){
2700 fs_give((void **) p);
2701 *p = conv;
2708 else{
2709 for(i = 0; i < 7; i++){
2710 switch(i){
2711 case 1: valptr = &v->current_val.p; break;
2712 case 0: valptr = &v->main_user_val.p; break;
2713 case 2: valptr = &v->changed_val.p; break;
2714 case 3: valptr = &v->post_user_val.p; break;
2715 case 4: valptr = &v->global_val.p; break;
2716 case 5: valptr = &v->fixed_val.p; break;
2717 case 6: valptr = &v->cmdline_val.p; break;
2718 default: alpine_panic("bad case in convert_configvar");
2721 if(valptr && *valptr && (*valptr)[0]){
2722 conv = convert_to_utf8(*valptr, fromcharset, 0);
2723 if(conv){
2724 fs_give((void **) valptr);
2725 *valptr = conv;
2735 * Standard feature name sections
2737 char *
2738 feature_list_section(FEATURE_S *feature)
2740 #define PREF_NONE -1
2741 static char *feat_sect[] = {
2742 #define PREF_MISC 0
2743 /* TRANSLATORS: section heading in configuration screen */
2744 N_("Advanced User Preferences"),
2745 #define PREF_FLDR 1
2746 /* TRANSLATORS: section heading in configuration screen */
2747 N_("Folder Preferences"),
2748 #define PREF_ADDR 2
2749 /* TRANSLATORS: section heading in configuration screen */
2750 N_("Address Book Preferences"),
2751 #define PREF_COMP 3
2752 /* TRANSLATORS: section heading in configuration screen */
2753 N_("Composer Preferences"),
2754 #define PREF_NEWS 4
2755 /* TRANSLATORS: section heading in configuration screen */
2756 N_("News Preferences"),
2757 #define PREF_VIEW 5
2758 /* TRANSLATORS: section heading in configuration screen */
2759 N_("Viewer Preferences"),
2760 #define PREF_ACMD 6
2761 /* TRANSLATORS: section heading in configuration screen */
2762 N_("Advanced Command Preferences"),
2763 #define PREF_PRNT 7
2764 /* TRANSLATORS: section heading in configuration screen */
2765 N_("Printer Preferences"),
2766 #define PREF_RPLY 8
2767 /* TRANSLATORS: section heading in configuration screen */
2768 N_("Reply Preferences"),
2769 #define PREF_SEND 9
2770 /* TRANSLATORS: section heading in configuration screen */
2771 N_("Sending Preferences"),
2772 #define PREF_INDX 10
2773 /* TRANSLATORS: section heading in configuration screen */
2774 N_("Message Index Preferences"),
2775 #define PREF_HIDDEN 11
2776 HIDDEN_PREF
2779 return((feature && feature->section > PREF_NONE
2780 && feature->section < (sizeof(feat_sect)/sizeof(feat_sect[0])))
2781 ? _(feat_sect[feature->section]) : NULL);
2785 /* any os-specific exclusions */
2786 #if defined(DOS) || defined(OS2)
2787 #define PREF_OS_LWSD PREF_NONE
2788 #define PREF_OS_LCLK PREF_NONE
2789 #define PREF_OS_STSP PREF_NONE
2790 #define PREF_OS_SPWN PREF_NONE
2791 #define PREF_OS_XNML PREF_NONE
2792 #define PREF_OS_USFK PREF_MISC
2793 #define PREF_OS_MOUSE PREF_NONE
2794 #else
2795 #define PREF_OS_LWSD PREF_MISC
2796 #define PREF_OS_LCLK PREF_COMP
2797 #define PREF_OS_STSP PREF_MISC
2798 #define PREF_OS_SPWN PREF_MISC
2799 #define PREF_OS_XNML PREF_MISC
2800 #define PREF_OS_USFK PREF_NONE
2801 #define PREF_OS_MOUSE PREF_MISC
2802 #endif
2806 * Standard way to get at feature list members...
2808 FEATURE_S *
2809 feature_list(int index)
2812 * This list is alphabatized by feature string, but the
2813 * macro values need not be ordered.
2815 static FEATURE_S feat_list[] = {
2816 /* Composer prefs */
2817 {"allow-changing-from", NULL,
2818 F_ALLOW_CHANGING_FROM, h_config_allow_chg_from, PREF_COMP, 1},
2819 {"alternate-compose-menu", NULL,
2820 F_ALT_COMPOSE_MENU, h_config_alt_compose_menu, PREF_COMP, 0},
2821 {"alternate-role-menu", "Alternate Role (#) Menu",
2822 F_ALT_ROLE_MENU, h_config_alt_role_menu, PREF_COMP, 0},
2823 {"compose-cancel-confirm-uses-yes", NULL,
2824 F_CANCEL_CONFIRM, h_config_cancel_confirm, PREF_COMP, 0},
2825 {"compose-rejects-unqualified-addrs", "Compose Rejects Unqualified Addresses",
2826 F_COMPOSE_REJECTS_UNQUAL, h_config_compose_rejects_unqual, PREF_COMP, 0},
2827 {"compose-send-offers-first-filter", NULL,
2828 F_FIRST_SEND_FILTER_DFLT, h_config_send_filter_dflt, PREF_COMP, 0},
2829 {"compose-cut-from-cursor", "Ctrl-K Cuts From Cursor",
2830 F_DEL_FROM_DOT, h_config_del_from_dot, PREF_COMP, 0},
2831 {"compose-maps-delete-key-to-ctrl-d", "Delete Key Maps to Ctrl-D",
2832 F_COMPOSE_MAPS_DEL, h_config_compose_maps_del, PREF_COMP, 0},
2833 {"quell-dead-letter-on-cancel", "Do Not Save to Deadletter on Cancel",
2834 F_QUELL_DEAD_LETTER, h_config_quell_dead_letter, PREF_COMP, 0},
2835 {"enable-alternate-editor-cmd", "Enable Alternate Editor Command",
2836 F_ENABLE_ALT_ED, h_config_enable_alt_ed, PREF_COMP, 1},
2837 {"enable-alternate-editor-implicitly", NULL,
2838 F_ALT_ED_NOW, h_config_alt_ed_now, PREF_COMP, 0},
2839 {"enable-search-and-replace", "Enable Search and Replace",
2840 F_ENABLE_SEARCH_AND_REPL, h_config_enable_search_and_repl, PREF_COMP, 1},
2841 {"enable-sigdashes", NULL,
2842 F_ENABLE_SIGDASHES, h_config_sigdashes, PREF_COMP, 0},
2843 {"quell-mailchecks-composing-except-inbox", "Prevent Mailchecks While Composing Except for INBOX",
2844 F_QUELL_PINGS_COMPOSING, h_config_quell_checks_comp, PREF_COMP, 0},
2845 {"quell-mailchecks-composing-inbox", "Prevent Mailchecks While Composing for INBOX",
2846 F_QUELL_PINGS_COMPOSING_INBOX, h_config_quell_checks_comp_inbox, PREF_COMP, 0},
2847 {"quell-user-lookup-in-passwd-file", "Prevent User Lookup in Password File",
2848 F_QUELL_LOCAL_LOOKUP, h_config_quell_local_lookup, PREF_OS_LCLK, 0},
2849 {"spell-check-before-sending", NULL,
2850 F_ALWAYS_SPELL_CHECK, h_config_always_spell_check, PREF_COMP, 0},
2852 /* Reply Prefs */
2853 {"alternate-reply-menu", NULL,
2854 F_ALT_REPLY_MENU, h_config_alt_reply_menu, PREF_RPLY, 0},
2855 {"copy-to-address-to-from-if-it-is-us", "Copy To Address to From if it is Us",
2856 F_COPY_TO_TO_FROM, h_config_copy_to_to_from, PREF_RPLY, 0},
2857 {"enable-reply-indent-string-editing", NULL,
2858 F_ENABLE_EDIT_REPLY_INDENT, h_config_prefix_editing, PREF_RPLY, 0},
2859 {"include-attachments-in-reply", "Include Attachments in Reply",
2860 F_ATTACHMENTS_IN_REPLY, h_config_attach_in_reply, PREF_RPLY, 0},
2861 {"include-header-in-reply", "Include Header in Reply",
2862 F_INCLUDE_HEADER, h_config_include_header, PREF_RPLY, 0},
2863 {"include-text-in-reply", "Include Text in Reply",
2864 F_AUTO_INCLUDE_IN_REPLY, h_config_auto_include_reply, PREF_RPLY, 0},
2865 {"reply-always-uses-reply-to", "Reply Always Uses Reply-To",
2866 F_AUTO_REPLY_TO, h_config_auto_reply_to, PREF_RPLY, 0},
2867 {"signature-at-bottom", "Signature at Bottom",
2868 F_SIG_AT_BOTTOM, h_config_sig_at_bottom, PREF_RPLY, 0},
2869 {"strip-from-sigdashes-on-reply", "Strip From Sigdashes on Reply",
2870 F_ENABLE_STRIP_SIGDASHES, h_config_strip_sigdashes, PREF_RPLY, 0},
2871 {"forward-as-attachment", "Forward messages as attachments",
2872 F_FORWARD_AS_ATTACHMENT, h_config_forward_as_attachment, PREF_RPLY, 0},
2873 {"preserve-original-fields", NULL,
2874 F_PRESERVE_ORIGINAL_FIELD, h_config_preserve_field, PREF_RPLY, 0},
2876 /* Sending Prefs */
2877 {"disable-sender", "Do Not Generate Sender Header",
2878 F_DISABLE_SENDER, h_config_disable_sender, PREF_SEND, 0},
2879 {"use-sender-not-x-sender", "Use Sender Instead of X-X-Sender",
2880 F_USE_SENDER_NOT_X, h_config_use_sender_not_x, PREF_SEND, 0},
2881 {"quell-flowed-text", "Do Not Send Flowed Text",
2882 F_QUELL_FLOWED_TEXT, h_config_quell_flowed_text, PREF_SEND, 0},
2883 {"downgrade-multipart-to-text", "Downgrade Multipart to Text",
2884 F_COMPOSE_ALWAYS_DOWNGRADE, h_downgrade_multipart_to_text, PREF_SEND, 0},
2885 {"enable-8bit-esmtp-negotiation", "Enable 8bit ESMTP Negotiation",
2886 F_ENABLE_8BIT, h_config_8bit_smtp, PREF_SEND, 1},
2887 #ifdef BACKGROUND_POST
2888 {"enable-background-sending", NULL,
2889 F_BACKGROUND_POST, h_config_compose_bg_post, PREF_SEND, 0},
2890 #endif
2891 {"enable-delivery-status-notification", NULL,
2892 F_DSN, h_config_compose_dsn, PREF_SEND, 0},
2893 {"enable-verbose-smtp-posting", "Enable Verbose SMTP Posting",
2894 F_VERBOSE_POST, h_config_verbose_post, PREF_SEND, 0},
2895 {"fcc-without-attachments", "Fcc Does Not Include Attachments",
2896 F_NO_FCC_ATTACH, h_config_no_fcc_attach, PREF_SEND, 0},
2897 {"fcc-on-bounce", "Include Fcc When Bouncing Messages",
2898 F_FCC_ON_BOUNCE, h_config_fcc_on_bounce, PREF_SEND, 0},
2899 {"mark-fcc-seen", NULL,
2900 F_MARK_FCC_SEEN, h_config_mark_fcc_seen, PREF_SEND, 0},
2901 {"fcc-only-without-confirm", "Send to Fcc Only Without Confirming",
2902 F_AUTO_FCC_ONLY, h_config_auto_fcc_only, PREF_SEND, 0},
2903 {"send-without-confirm", "Send Without Confirming",
2904 F_SEND_WO_CONFIRM, h_config_send_wo_confirm, PREF_SEND, 0},
2905 {"strip-whitespace-before-send", "Strip Whitespace Before Sending",
2906 F_STRIP_WS_BEFORE_SEND, h_config_strip_ws_before_send, PREF_SEND, 0},
2907 {"warn-if-blank-fcc", "Warn if Blank Fcc",
2908 F_WARN_ABOUT_NO_FCC, h_config_warn_if_fcc_blank, PREF_SEND, 0},
2909 {"warn-if-blank-subject", "Warn if Blank Subject",
2910 F_WARN_ABOUT_NO_SUBJECT, h_config_warn_if_subj_blank, PREF_SEND, 0},
2911 {"warn-if-blank-to-and-cc-and-newsgroups", "Warn if Blank To and CC and Newsgroups",
2912 F_WARN_ABOUT_NO_TO_OR_CC, h_config_warn_if_no_to_or_cc, PREF_SEND, 0},
2914 /* Folder */
2915 {"combined-folder-display", NULL,
2916 F_CMBND_FOLDER_DISP, h_config_combined_folder_display, PREF_FLDR, 0},
2917 {"combined-subdirectory-display", NULL,
2918 F_CMBND_SUBDIR_DISP, h_config_combined_subdir_display, PREF_FLDR, 0},
2919 {"enable-lame-list-mode", "Compensate for Deficient IMAP servers",
2920 F_FIX_BROKEN_LIST, h_config_lame_list_mode, PREF_FLDR, 0},
2921 {"enable-dot-folders", "Enable Hidden Folders",
2922 F_ENABLE_DOT_FOLDERS, h_config_enable_dot_folders, PREF_FLDR, 0},
2923 {"enable-incoming-folders", "Enable Incoming Folders Collection",
2924 F_ENABLE_INCOMING, h_config_enable_incoming, PREF_FLDR, 0},
2925 {"enable-incoming-folders-checking", NULL,
2926 F_ENABLE_INCOMING_CHECKING, h_config_enable_incoming_checking, PREF_FLDR, 0},
2927 {"incoming-checking-includes-total", NULL,
2928 F_INCOMING_CHECKING_TOTAL, h_config_incoming_checking_total, PREF_FLDR, 0},
2929 {"incoming-checking-uses-recent", NULL,
2930 F_INCOMING_CHECKING_RECENT, h_config_incoming_checking_recent, PREF_FLDR, 0},
2931 {"expanded-view-of-folders", "Expanded View of Folders",
2932 F_EXPANDED_FOLDERS, h_config_expanded_folders, PREF_FLDR, 0},
2933 {"quell-empty-directories", "Hide Empty Directories",
2934 F_QUELL_EMPTY_DIRS, h_config_quell_empty_dirs, PREF_FLDR, 0},
2935 {"separate-folder-and-directory-entries", "Separate Folder and Directory Entries",
2936 F_SEPARATE_FLDR_AS_DIR, h_config_separate_fold_dir_view, PREF_FLDR, 0},
2937 {"single-column-folder-list", NULL,
2938 F_SINGLE_FOLDER_LIST, h_config_single_list, PREF_FLDR, 0},
2939 {"sort-default-fcc-alpha", "Sort Default Fcc Folder Alphabetically",
2940 F_SORT_DEFAULT_FCC_ALPHA, h_config_sort_fcc_alpha, PREF_FLDR, 0},
2941 {"sort-default-save-alpha", "Sort Default Save Folder Alphabetically",
2942 F_SORT_DEFAULT_SAVE_ALPHA, h_config_sort_save_alpha, PREF_FLDR, 0},
2943 {"vertical-folder-list", "Use Vertical Folder List",
2944 F_VERTICAL_FOLDER_LIST, h_config_vertical_list, PREF_FLDR, 0},
2946 /* Addr book */
2947 {"combined-addrbook-display", "Combined Address Book Display",
2948 F_CMBND_ABOOK_DISP, h_config_combined_abook_display, PREF_ADDR, 0},
2949 {"expanded-view-of-addressbooks", "Expanded View of Address Books",
2950 F_EXPANDED_ADDRBOOKS, h_config_expanded_addrbooks, PREF_ADDR, 0},
2951 {"expanded-view-of-distribution-lists", "Expanded View of Distribution Lists",
2952 F_EXPANDED_DISTLISTS, h_config_expanded_distlists, PREF_ADDR, 0},
2953 #ifdef ENABLE_LDAP
2954 {"ldap-result-to-addrbook-add", "LDAP Result to Addressbook Add",
2955 F_ADD_LDAP_TO_ABOOK, h_config_add_ldap, PREF_ADDR, 0},
2956 #endif
2958 /* Index prefs */
2959 {"auto-open-next-unread", NULL,
2960 F_AUTO_OPEN_NEXT_UNREAD, h_config_auto_open_unread, PREF_INDX, 0},
2961 {"continue-tab-without-confirm", "Continue NextNew Without Confirming",
2962 F_TAB_NO_CONFIRM, h_config_tab_no_prompt, PREF_INDX, 0},
2963 {"convert-dates-to-localtime", NULL,
2964 F_DATES_TO_LOCAL, h_config_dates_to_local, PREF_INDX, 0},
2965 {"delete-skips-deleted", NULL,
2966 F_DEL_SKIPS_DEL, h_config_del_skips_del, PREF_INDX, 1},
2967 {"disable-index-locale-dates", NULL,
2968 F_DISABLE_INDEX_LOCALE_DATES, h_config_disable_index_locale_dates, PREF_INDX, 0},
2969 {"enable-cruise-mode", NULL,
2970 F_ENABLE_SPACE_AS_TAB, h_config_cruise_mode, PREF_INDX, 0},
2971 {"enable-cruise-mode-delete", "Enable Cruise Mode With Deleting",
2972 F_ENABLE_TAB_DELETES, h_config_cruise_mode_delete, PREF_INDX, 0},
2973 {"mark-for-cc", "Mark for CC",
2974 F_MARK_FOR_CC, h_config_mark_for_cc, PREF_INDX, 1},
2975 {"next-thread-without-confirm", "Read Next Thread Without Confirming",
2976 F_NEXT_THRD_WO_CONFIRM, h_config_next_thrd_wo_confirm, PREF_INDX, 0},
2977 {"return-to-inbox-without-confirm", "Return to INBOX Without Confirming",
2978 F_RET_INBOX_NO_CONFIRM, h_config_inbox_no_confirm, PREF_INDX, 0},
2979 {"show-sort", "Show Sort in Titlebar",
2980 F_SHOW_SORT, h_config_show_sort, PREF_INDX, 0},
2981 {"tab-uses-unseen-for-next-folder", "Tab Uses Unseen for Next Folder",
2982 F_TAB_USES_UNSEEN, h_config_tab_uses_unseen, PREF_INDX, 0},
2983 {"tab-visits-next-new-message-only", NULL,
2984 F_TAB_TO_NEW, h_config_tab_new_only, PREF_INDX, 0},
2985 {"thread-index-shows-important-color", NULL,
2986 F_COLOR_LINE_IMPORTANT, h_config_color_thrd_import, PREF_INDX, 0},
2987 {"thread-sorts-by-arrival", "Thread Sorts by Arrival",
2988 F_THREAD_SORTS_BY_ARRIVAL, h_config_thread_sorts_by_arrival, PREF_INDX, 0},
2990 /* Viewer prefs */
2991 {"enable-msg-view-addresses", "Enable Message View Address Links",
2992 F_SCAN_ADDR, h_config_enable_view_addresses, PREF_VIEW, 0},
2993 {"enable-msg-view-attachments", "Enable Message View Attachment Links",
2994 F_VIEW_SEL_ATTACH, h_config_enable_view_attach, PREF_VIEW, 0},
2995 {"enable-msg-view-urls", "Enable Message View URL Links",
2996 F_VIEW_SEL_URL, h_config_enable_view_url, PREF_VIEW, 1},
2997 {"enable-msg-view-web-hostnames", "Enable Message View Web Hostname Links",
2998 F_VIEW_SEL_URL_HOST, h_config_enable_view_web_host, PREF_VIEW, 1},
2999 {"enable-msg-view-forced-arrows", "Enable Message View Forced Arrows",
3000 F_FORCE_ARROWS, h_config_enable_view_arrows, PREF_VIEW, 0},
3001 /* set to TRUE for windows */
3002 {"pass-c1-control-characters-as-is", NULL,
3003 F_PASS_C1_CONTROL_CHARS, h_config_pass_c1_control, PREF_VIEW, 0},
3004 {"pass-control-characters-as-is", NULL,
3005 F_PASS_CONTROL_CHARS, h_config_pass_control, PREF_VIEW, 0},
3006 {"prefer-plain-text", NULL,
3007 F_PREFER_PLAIN_TEXT, h_config_prefer_plain_text, PREF_VIEW, 0},
3008 {"quell-charset-warning", "Suppress Character Set Warning",
3009 F_QUELL_CHARSET_WARNING, h_config_quell_charset_warning, PREF_VIEW, 0},
3010 {"quell-server-after-link-in-html", "Suppress Server After Link in HTML",
3011 F_QUELL_HOST_AFTER_URL, h_config_quell_host_after_url, PREF_VIEW, 0},
3013 /* News */
3014 {"compose-sets-newsgroup-without-confirm", "Compose Sets Newsgroup Without Confirming",
3015 F_COMPOSE_TO_NEWSGRP, h_config_compose_news_wo_conf, PREF_NEWS, 0},
3016 {"enable-8bit-nntp-posting", "Enable 8bit NNTP Posting",
3017 F_ENABLE_8BIT_NNTP, h_config_8bit_nntp, PREF_NEWS, 0},
3018 {"enable-multiple-newsrcs", NULL,
3019 F_ENABLE_MULNEWSRCS, h_config_enable_mulnewsrcs, PREF_NEWS, 0},
3020 {"mult-newsrc-hostnames-as-typed", "Multiple Newsrc Hostnames as Typed",
3021 F_MULNEWSRC_HOSTNAMES_AS_TYPED, h_config_mulnews_as_typed, PREF_NEWS, 0},
3022 {"hide-nntp-path", "Hide NNTP Path",
3023 F_HIDE_NNTP_PATH, h_config_hide_nntp_path, PREF_NEWS, 0},
3024 {"news-approximates-new-status", NULL,
3025 F_FAKE_NEW_IN_NEWS, h_config_news_uses_recent, PREF_NEWS, 1},
3026 {"news-deletes-across-groups", NULL,
3027 F_NEWS_CROSS_DELETE, h_config_news_cross_deletes, PREF_NEWS, 0},
3028 {"news-offers-catchup-on-close", "News Offers Catchup on Close",
3029 F_NEWS_CATCHUP, h_config_news_catchup, PREF_NEWS, 0},
3030 {"news-post-without-validation", NULL,
3031 F_NO_NEWS_VALIDATION, h_config_post_wo_validation, PREF_NEWS, 0},
3032 {"news-read-in-newsrc-order", "News Read in Newsrc Order",
3033 F_READ_IN_NEWSRC_ORDER, h_config_read_in_newsrc_order, PREF_NEWS, 0},
3034 {"nntp-search-uses-overview", "NNTP Search Uses Overview",
3035 F_NNTP_SEARCH_USES_OVERVIEW, h_config_nntp_search_uses_overview, PREF_NEWS, 1},
3036 {"predict-nntp-server", "Predict NNTP Server",
3037 F_PREDICT_NNTP_SERVER, h_config_predict_nntp_server, PREF_NEWS, 0},
3038 {"quell-extra-post-prompt", "Suppress Extra Posting Prompt",
3039 F_QUELL_EXTRA_POST_PROMPT, h_config_quell_post_prompt, PREF_NEWS, 0},
3041 /* Print */
3042 {"enable-print-via-y-command", NULL,
3043 F_ENABLE_PRYNT, h_config_enable_y_print, PREF_PRNT, 0},
3044 {"print-formfeed-between-messages", NULL,
3045 F_AGG_PRINT_FF, h_config_ff_between_msgs, PREF_PRNT, 0},
3046 {"print-includes-from-line", NULL,
3047 F_FROM_DELIM_IN_PRINT, h_config_print_from, PREF_PRNT, 0},
3048 {"print-index-enabled", NULL,
3049 F_PRINT_INDEX, h_config_print_index, PREF_PRNT, 0},
3050 {"print-offers-custom-cmd-prompt", "Print Offers Custom Command Prompt",
3051 F_CUSTOM_PRINT, h_config_custom_print, PREF_PRNT, 0},
3053 /* adv cmd prefs */
3054 {"enable-aggregate-command-set", NULL,
3055 F_ENABLE_AGG_OPS, h_config_enable_agg_ops, PREF_ACMD, 1},
3056 {"enable-arrow-navigation", NULL,
3057 F_ARROW_NAV, h_config_arrow_nav, PREF_ACMD, 1},
3058 {"enable-arrow-navigation-relaxed", NULL,
3059 F_RELAXED_ARROW_NAV, h_config_relaxed_arrow_nav, PREF_ACMD, 1},
3060 {"enable-bounce-cmd", "Enable Bounce Command",
3061 F_ENABLE_BOUNCE, h_config_enable_bounce, PREF_ACMD, 1},
3062 {"enable-exit-via-lessthan-command", NULL,
3063 F_ENABLE_LESSTHAN_EXIT, h_config_enable_lessthan_exit, PREF_ACMD, 1},
3064 {"enable-flag-cmd", "Enable Flag Command",
3065 F_ENABLE_FLAG, h_config_enable_flag, PREF_ACMD, 1},
3066 {"enable-flag-screen-implicitly", NULL,
3067 F_FLAG_SCREEN_DFLT, h_config_flag_screen_default, PREF_ACMD, 0},
3068 {"enable-flag-screen-keyword-shortcut", NULL,
3069 F_FLAG_SCREEN_KW_SHORTCUT, h_config_flag_screen_kw_shortcut,PREF_ACMD, 1},
3070 {"enable-full-header-and-text", "Enable Full Header and Text",
3071 F_ENABLE_FULL_HDR_AND_TEXT, h_config_enable_full_hdr_and_text, PREF_ACMD, 0},
3072 {"enable-full-header-cmd", "Enable Full Header Command",
3073 F_ENABLE_FULL_HDR, h_config_enable_full_hdr, PREF_ACMD, 1},
3074 {"enable-goto-in-file-browser", "Enable Goto in File Browser",
3075 F_ALLOW_GOTO, h_config_allow_goto, PREF_ACMD, 1},
3076 {"enable-jump-shortcut", NULL,
3077 F_ENABLE_JUMP, h_config_enable_jump, PREF_ACMD, 1},
3078 {"enable-partial-match-lists", NULL,
3079 F_ENABLE_SUB_LISTS, h_config_sub_lists, PREF_ACMD, 1},
3080 {"enable-tab-completion", NULL,
3081 F_ENABLE_TAB_COMPLETE, h_config_enable_tab_complete, PREF_ACMD, 1},
3082 {"enable-unix-pipe-cmd", "Enable Unix Pipe Command",
3083 F_ENABLE_PIPE, h_config_enable_pipe, PREF_ACMD, 1},
3084 {"quell-full-header-auto-reset", "Suppress Full Header Auto Reset",
3085 F_QUELL_FULL_HDR_RESET, h_config_quell_full_hdr_reset, PREF_ACMD, 0},
3087 /* Adv user prefs */
3088 #if !defined(DOS) && !defined(OS2)
3089 {"allow-talk", NULL,
3090 F_ALLOW_TALK, h_config_allow_talk, PREF_MISC, 0},
3091 #endif
3092 {"assume-slow-link", NULL,
3093 F_FORCE_LOW_SPEED, h_config_force_low_speed, PREF_OS_LWSD, 0},
3094 {"auto-move-read-msgs", "Auto Move Read Messages",
3095 F_AUTO_READ_MSGS, h_config_auto_read_msgs, PREF_MISC, 0},
3096 {"auto-unselect-after-apply", NULL,
3097 F_AUTO_UNSELECT, h_config_auto_unselect, PREF_MISC, 0},
3098 {"auto-unzoom-after-apply", NULL,
3099 F_AUTO_UNZOOM, h_config_auto_unzoom, PREF_MISC, 1},
3100 {"auto-zoom-after-select", NULL,
3101 F_AUTO_ZOOM, h_config_auto_zoom, PREF_MISC, 1},
3102 {"busy-cue-spinner-only", NULL,
3103 F_USE_BORING_SPINNER, h_config_use_boring_spinner, PREF_MISC, 0},
3104 {"check-newmail-when-quitting", NULL,
3105 F_CHECK_MAIL_ONQUIT, h_config_check_mail_onquit, PREF_MISC, 0},
3106 {"confirm-role-even-for-default", "Confirm Role Even for Default",
3107 F_ROLE_CONFIRM_DEFAULT, h_config_confirm_role, PREF_MISC, 0},
3108 {"disable-keymenu", NULL,
3109 F_BLANK_KEYMENU, h_config_blank_keymenu, PREF_MISC, 0},
3110 {"disable-password-caching", NULL,
3111 F_DISABLE_PASSWORD_CACHING, h_config_disable_password_caching,
3112 PREF_MISC, 0},
3113 #ifdef PASSFILE
3114 {"disable-password-file-saving", NULL,
3115 F_DISABLE_PASSWORD_FILE_SAVING, h_config_disable_password_file_saving,
3116 PREF_MISC, 0},
3117 #endif
3118 {"disable-regular-expression-matching-for-alternate-addresses", NULL,
3119 F_DISABLE_REGEX, h_config_disable_regex, PREF_MISC, 0},
3120 {"disable-save-input-history", NULL,
3121 F_DISABLE_SAVE_INPUT_HISTORY, h_config_input_history, PREF_MISC, 0},
3122 {"disable-take-fullname-in-addresses", "Disable Take Fullname in Addresses",
3123 F_DISABLE_TAKE_FULLNAMES, h_config_take_fullname, PREF_MISC, 0},
3124 {"disable-take-last-comma-first", NULL,
3125 F_DISABLE_TAKE_LASTFIRST, h_config_take_lastfirst, PREF_MISC, 0},
3126 {"disable-terminal-reset-for-display-filters", "Disable Terminal Reset for Display Filters",
3127 F_DISABLE_TERM_RESET_DISP, h_config_disable_reset_disp, PREF_MISC, 0},
3128 {"enable-dot-files", NULL,
3129 F_ENABLE_DOT_FILES, h_config_enable_dot_files, PREF_MISC, 0},
3130 {"enable-fast-recent-test", NULL,
3131 F_ENABLE_FAST_RECENT, h_config_fast_recent, PREF_MISC, 0},
3132 {"enable-mail-check-cue", NULL,
3133 F_SHOW_DELAY_CUE, h_config_show_delay_cue, PREF_MISC, 0},
3134 {"enable-mailcap-param-substitution", "Enable Mailcap Parameter Substitution",
3135 F_DO_MAILCAP_PARAM_SUBST, h_config_mailcap_params, PREF_MISC, 0},
3136 {"enable-mouse-in-xterm", "Enable Mouse in Xterm",
3137 F_ENABLE_MOUSE, h_config_enable_mouse, PREF_OS_MOUSE, 0},
3138 {"enable-newmail-in-xterm-icon", "Enable Newmail in Xterm Icon",
3139 F_ENABLE_XTERM_NEWMAIL, h_config_enable_xterm_newmail, PREF_OS_XNML, 0},
3140 {"enable-newmail-short-text-in-icon", "Enable Newmail Short Text in Icon",
3141 F_ENABLE_NEWMAIL_SHORT_TEXT, h_config_enable_newmail_short_text, PREF_OS_XNML, 0},
3142 {"enable-suspend", NULL,
3143 F_CAN_SUSPEND, h_config_can_suspend, PREF_MISC, 0},
3144 {"enable-take-export", NULL,
3145 F_ENABLE_TAKE_EXPORT, h_config_enable_take_export, PREF_MISC, 0},
3146 {"enable-rules-under-take", "Enable Take Rules",
3147 F_ENABLE_ROLE_TAKE, h_config_enable_role_take, PREF_MISC, 0},
3148 #ifdef _WINDOWS
3149 {"enable-tray-icon", NULL,
3150 F_ENABLE_TRAYICON, h_config_tray_icon, PREF_MISC, 0},
3151 #endif
3152 {"expose-hidden-config", NULL,
3153 F_EXPOSE_HIDDEN_CONFIG, h_config_expose_hidden_config, PREF_MISC, 0},
3154 {"expunge-only-manually", NULL,
3155 F_EXPUNGE_MANUALLY, h_config_expunge_manually, PREF_MISC, 0},
3156 {"expunge-without-confirm", "Expunge Without Confirming",
3157 F_AUTO_EXPUNGE, h_config_auto_expunge, PREF_MISC, 0},
3158 {"expunge-without-confirm-everywhere", "Expunge Without Confirming Everywhere",
3159 F_FULL_AUTO_EXPUNGE, h_config_full_auto_expunge, PREF_MISC, 0},
3160 {"force-arrow-cursor", NULL,
3161 F_FORCE_ARROW, h_config_force_arrow, PREF_MISC, 0},
3162 {"ignore-size-changes", NULL,
3163 F_IGNORE_SIZE, h_config_ignore_size, PREF_MISC, 0},
3164 {"maildrops-preserve-state", NULL,
3165 F_MAILDROPS_PRESERVE_STATE, h_config_maildrops_preserve_state,
3166 PREF_MISC, 0},
3167 {"offer-expunge-of-inbox", "Offer Expunge of INBOX",
3168 F_EXPUNGE_INBOX, h_config_expunge_inbox, PREF_MISC, 0},
3169 {"offer-expunge-of-stayopen-folders", "Offer Expunge of Stayopen Folders",
3170 F_EXPUNGE_STAYOPENS, h_config_expunge_stayopens, PREF_MISC, 0},
3171 {"preopen-stayopen-folders", NULL,
3172 F_PREOPEN_STAYOPENS, h_config_preopen_stayopens, PREF_MISC, 0},
3173 {"preserve-start-stop-characters", "Preserve Start/Stop Characters",
3174 F_PRESERVE_START_STOP, h_config_preserve_start_stop, PREF_OS_STSP, 0},
3175 {"quell-folder-internal-msg", "Prevent Folder Internal Message",
3176 F_QUELL_INTERNAL_MSG, h_config_quell_folder_internal_msg, PREF_MISC, 0},
3177 {"quell-partial-fetching", "Prevent Partial Fetching",
3178 F_QUELL_PARTIAL_FETCH, h_config_quell_partial, PREF_MISC, 0},
3179 {"prune-uses-yyyy-mm", "Prune Uses YYYY-MM",
3180 F_PRUNE_USES_ISO, h_config_prune_uses_iso, PREF_MISC, 0},
3181 {"quit-without-confirm", "Quit Without Confirming",
3182 F_QUIT_WO_CONFIRM, h_config_quit_wo_confirm, PREF_MISC, 0},
3183 {"quote-replace-nonflowed", NULL,
3184 F_QUOTE_REPLACE_NOFLOW, h_config_quote_replace_noflow, PREF_MISC, 0},
3185 {"save-aggregates-copy-sequence", "Save Combines Copies (may be out of order)",
3186 F_AGG_SEQ_COPY, h_config_save_aggregates, PREF_MISC, 1},
3187 {"save-partial-msg-without-confirm", "Save Partial Message Without Confirming",
3188 F_SAVE_PARTIAL_WO_CONFIRM, h_config_save_part_wo_confirm, PREF_MISC, 0},
3189 {"save-will-advance", NULL,
3190 F_SAVE_ADVANCES, h_config_save_advances, PREF_MISC, 0},
3191 {"save-will-not-delete", NULL,
3192 F_SAVE_WONT_DELETE, h_config_save_wont_delete, PREF_MISC, 0},
3193 {"save-will-quote-leading-froms", NULL,
3194 F_QUOTE_ALL_FROMS, h_config_quote_all_froms, PREF_MISC, 0},
3195 {"scramble-message-id", "Scramble the Message-ID When Sending",
3196 F_ROT13_MESSAGE_ID, h_config_scramble_message_id, PREF_MISC, 0},
3197 {"select-without-confirm", "Select Ctrl-T Foldername Without Confirming",
3198 F_SELECT_WO_CONFIRM, h_config_select_wo_confirm, PREF_MISC, 0},
3199 {"show-cursor", NULL,
3200 F_SHOW_CURSOR, h_config_show_cursor, PREF_MISC, 0},
3201 {"show-plain-text-internally", NULL,
3202 F_SHOW_TEXTPLAIN_INT, h_config_textplain_int, PREF_MISC, 0},
3203 {"show-selected-in-boldface", "Show Selected in Boldface",
3204 F_SELECTED_SHOWN_BOLD, h_config_select_in_bold, PREF_MISC, 0},
3205 {"slash-collapses-entire-thread", NULL,
3206 F_SLASH_COLL_ENTIRE, h_config_slash_coll_entire, PREF_MISC, 0},
3207 #ifdef _WINDOWS
3208 {"store-window-position-in-config", "Store Window Position in Config",
3209 F_STORE_WINPOS_IN_CONFIG, h_config_winpos_in_config, PREF_MISC, 0},
3210 #endif
3211 {"suppress-asterisks-in-password-prompt", "Suppress Asterisks in Password Prompt",
3212 F_QUELL_ASTERISKS, h_config_quell_asterisks,
3213 PREF_MISC, 0},
3214 {"quell-attachment-extension-warn", "Suppress Attachment Extension Warning",
3215 F_QUELL_ATTACH_EXT_WARN, h_config_quell_attach_ext_warn,
3216 PREF_MISC, 0},
3217 {"quell-attachment-extra-prompt", "Suppress Attachment Extra Prompt",
3218 F_QUELL_ATTACH_EXTRA_PROMPT, h_config_quell_attach_extra_prompt,
3219 PREF_MISC, 0},
3220 {"quell-berkeley-format-timezone", "Suppress Berkeley Format Timezone",
3221 F_QUELL_BEZERK_TIMEZONE, h_config_no_bezerk_zone, PREF_MISC, 0},
3222 {"quell-content-id", "Suppress Content-ID",
3223 F_QUELL_CONTENT_ID, h_config_quell_content_id, PREF_MISC, 0},
3224 {"quell-filtering-done-message", "Suppress Filtering Done Message",
3225 F_QUELL_FILTER_DONE_MSG, h_config_quell_filtering_done_message,
3226 PREF_MISC, 0},
3227 {"quell-filtering-messages", "Suppress Filtering Messages",
3228 F_QUELL_FILTER_MSGS, h_config_quell_filtering_messages,
3229 PREF_MISC, 0},
3230 {"quell-imap-envelope-update", "Suppress IMAP Envelope Update",
3231 F_QUELL_IMAP_ENV_CB, h_config_quell_imap_env, PREF_MISC, 0},
3232 {"quell-lock-failure-warnings", "Suppress Lock Failure Warnings",
3233 F_QUELL_LOCK_FAILURE_MSGS, h_config_quell_lock_failure_warnings,
3234 PREF_MISC, 0},
3235 {"quell-maildomain-warning", "Suppress Maildomain Warning",
3236 F_QUELL_MAILDOMAIN_WARNING, h_config_quell_domain_warn, PREF_MISC, 0},
3237 {"quell-news-envelope-update", "Suppress News Envelope Update",
3238 F_QUELL_NEWS_ENV_CB, h_config_quell_news_env, PREF_MISC, 0},
3239 #ifdef _WINDOWS
3240 {"quell-ssl-largeblocks", "Prevent SSL Largeblocks",
3241 F_QUELL_SSL_LARGEBLOCKS, h_config_quell_ssl_largeblocks, PREF_MISC, 0},
3242 #endif
3243 {"quell-status-message-beeping", "Suppress Status Message Beeping",
3244 F_QUELL_BEEPS, h_config_quell_beeps, PREF_MISC, 0},
3245 {"quell-timezone-comment-when-sending", "Suppress Timezone Comment When Sending",
3246 F_QUELL_TIMEZONE, h_config_quell_tz_comment, PREF_MISC, 0},
3247 {"suppress-user-agent-when-sending", NULL,
3248 F_QUELL_USERAGENT, h_config_suppress_user_agent, PREF_MISC, 0},
3249 {"tab-checks-recent", "Tab Checks for Recent Messages",
3250 F_TAB_CHK_RECENT, h_config_tab_checks_recent, PREF_MISC, 0},
3251 {"termdef-takes-precedence", NULL,
3252 F_TCAP_WINS, h_config_termcap_wins, PREF_MISC, 0},
3253 {"try-alternative-authentication-driver-first", NULL,
3254 F_PREFER_ALT_AUTH, h_config_alt_auth, PREF_MISC, 0},
3255 {"unselect-will-not-advance", NULL,
3256 F_UNSELECT_WONT_ADVANCE, h_config_unsel_wont_advance, PREF_MISC, 0},
3257 {"use-current-dir", "Use Current Directory",
3258 F_USE_CURRENT_DIR, h_config_use_current_dir, PREF_MISC, 0},
3259 {"use-function-keys", NULL,
3260 F_USE_FK, h_config_use_fk, PREF_OS_USFK, 0},
3261 {"use-regular-startup-rule-for-stayopen-folders", "Use Regular Startup Rule for Stayopen Folders",
3262 F_STARTUP_STAYOPEN, h_config_use_reg_start_for_stayopen, PREF_MISC, 0},
3263 {"use-resent-to-in-rules", "Use Resent-To in Rules",
3264 F_USE_RESENTTO, h_config_use_resentto, PREF_MISC, 0},
3265 {"use-subshell-for-suspend", "Use Subshell for Suspend",
3266 F_SUSPEND_SPAWNS, h_config_suspend_spawns, PREF_OS_SPWN, 0},
3267 #ifndef _WINDOWS
3268 {"use-system-translation", NULL,
3269 F_USE_SYSTEM_TRANS, h_config_use_system_translation, PREF_MISC, 0},
3270 #endif
3272 /* Hidden Features */
3273 {"old-growth", NULL,
3274 F_OLD_GROWTH, NO_HELP, PREF_NONE, 0},
3275 {"disable-config-cmd", NULL,
3276 F_DISABLE_CONFIG_SCREEN, h_config_disable_config_cmd, PREF_HIDDEN, 0},
3277 {"disable-keyboard-lock-cmd", NULL,
3278 F_DISABLE_KBLOCK_CMD, h_config_disable_kb_lock, PREF_HIDDEN, 0},
3279 {"disable-password-cmd", NULL,
3280 F_DISABLE_PASSWORD_CMD, h_config_disable_password_cmd, PREF_HIDDEN, 0},
3281 {"disable-pipes-in-sigs", NULL,
3282 F_DISABLE_PIPES_IN_SIGS, h_config_disable_pipes_in_sigs, PREF_HIDDEN, 0},
3283 {"disable-pipes-in-templates", NULL,
3284 F_DISABLE_PIPES_IN_TEMPLATES, h_config_disable_pipes_in_templates,
3285 PREF_HIDDEN, 0},
3286 {"disable-roles-setup-cmd", NULL,
3287 F_DISABLE_ROLES_SETUP, h_config_disable_roles_setup, PREF_HIDDEN, 0},
3288 {"disable-roles-sig-edit", NULL,
3289 F_DISABLE_ROLES_SIGEDIT, h_config_disable_roles_sigedit, PREF_HIDDEN, 0},
3290 {"disable-roles-template-edit", NULL,
3291 F_DISABLE_ROLES_TEMPLEDIT, h_config_disable_roles_templateedit,
3292 PREF_HIDDEN, 0},
3293 {"disable-setlocale-collate", NULL,
3294 F_DISABLE_SETLOCALE_COLLATE, h_config_disable_collate, PREF_HIDDEN, 0},
3295 {"disable-shared-namespaces", NULL,
3296 F_DISABLE_SHARED_NAMESPACES, h_config_disable_shared, PREF_HIDDEN, 0},
3297 {"disable-signature-edit-cmd", NULL,
3298 F_DISABLE_SIGEDIT_CMD, h_config_disable_signature_edit, PREF_HIDDEN, 0},
3299 {"new-thread-on-blank-subject", "New Thread on Blank Subject",
3300 F_NEW_THREAD_ON_BLANK_SUBJECT, h_config_new_thread_blank_subject, PREF_HIDDEN, 1},
3301 {"quell-personal-name-prompt", NULL,
3302 F_QUELL_PERSONAL_NAME_PROMPT, h_config_quell_personal_name_prompt, PREF_HIDDEN, 0},
3303 {"quell-user-id-prompt", "Quell User ID Prompt",
3304 F_QUELL_USER_ID_PROMPT, h_config_quell_user_id_prompt, PREF_HIDDEN, 0},
3305 #ifdef SMIME
3306 {"smime-dont-do-smime", "S/MIME -- Turn off S/MIME",
3307 F_DONT_DO_SMIME, h_config_smime_dont_do_smime, PREF_HIDDEN, 0},
3308 {"smime-encrypt-by-default", "S/MIME -- Encrypt by Default",
3309 F_ENCRYPT_DEFAULT_ON, h_config_smime_encrypt_by_default, PREF_HIDDEN, 0},
3310 {"smime-remember-passphrase", "S/MIME -- Remember S/MIME Passphrase",
3311 F_REMEMBER_SMIME_PASSPHRASE, h_config_smime_remember_passphrase, PREF_HIDDEN, 0},
3312 {"smime-sign-by-default", "S/MIME -- Sign by Default",
3313 F_SIGN_DEFAULT_ON, h_config_smime_sign_by_default, PREF_HIDDEN, 0},
3314 {"smime-use-store-only", "S/MIME -- Validate Using Certificate Store Only",
3315 F_USE_CERT_STORE_ONLY, h_config_smime_use_cert_store, PREF_HIDDEN, 1},
3316 #ifdef APPLEKEYCHAIN
3317 {"publiccerts-in-keychain", "S/MIME -- Public Certs in MacOS Keychain",
3318 F_PUBLICCERTS_IN_KEYCHAIN, h_config_smime_pubcerts_in_keychain, PREF_HIDDEN, 0},
3319 #endif
3320 #endif
3321 {"selectable-item-nobold", NULL,
3322 F_SLCTBL_ITEM_NOBOLD, NO_HELP, PREF_NONE, 0},
3323 {"send-confirms-only-expanded", NULL, /* exposed in Web Alpine */
3324 F_SEND_CONFIRM_ON_EXPAND, h_config_send_confirms_only_expanded, PREF_HIDDEN, 0},
3325 {"enable-jump-cmd", NULL, /* exposed in Web Alpine */
3326 F_ENABLE_JUMP_CMD, h_config_enable_jump_command, PREF_HIDDEN, 0},
3327 {"enable-newmail-sound", NULL, /* exposed in Web Alpine */
3328 F_ENABLE_NEWMAIL_SOUND, h_config_enable_newmail_sound, PREF_HIDDEN, 0},
3329 {"render-html-internally", NULL, /* exposed in Web Alpine */
3330 F_RENDER_HTML_INTERNALLY, h_config_render_html_internally, PREF_HIDDEN, 0}
3333 return((index >= 0 && index < (sizeof(feat_list)/sizeof(feat_list[0])))
3334 ? &feat_list[index] : NULL);
3339 * feature_list_index -- return index of given feature id in
3340 * feature list
3343 feature_list_index(int id)
3345 FEATURE_S *feature;
3346 int i;
3348 for(i = 0; (feature = feature_list(i)); i++)
3349 if(id == feature->id)
3350 return(i);
3352 return(-1);
3357 * feature_list_name -- return the given feature id's corresponding name
3359 char *
3360 feature_list_name(int id)
3362 FEATURE_S *f;
3364 return((f = feature_list(feature_list_index(id))) ? f->name : "");
3369 feature_list_id(char *name)
3371 FEATURE_S *f;
3372 int i;
3374 for(i = 0; (f = feature_list(i)); i++)
3375 if(!strucmp(f->name, name))
3376 return(f->id);
3378 return(-1);
3383 * feature_list_help -- return the given feature id's corresponding help
3385 HelpType
3386 feature_list_help(int id)
3388 FEATURE_S *f;
3390 return((f = feature_list(feature_list_index(id))) ? f->help : NO_HELP);
3395 * All the arguments past "list" are the backwards compatibility hacks.
3397 void
3398 process_feature_list(struct pine *ps, char **list, int old_growth, int hir, int osr)
3400 register char *q;
3401 char **p,
3402 *lvalue[BM_SIZE * 8];
3403 int i,
3404 yorn;
3405 long l;
3406 FEATURE_S *feat;
3409 /* clear all previous settings and reset them to default */
3410 for(i = 0; (feat = feature_list(i)) != NULL; i++)
3411 F_SET(feat->id, ps, feat->defval);
3413 /* backwards compatibility */
3414 if(hir)
3415 F_TURN_ON(F_INCLUDE_HEADER, ps);
3417 /* ditto */
3418 if(osr)
3419 F_TURN_ON(F_SIG_AT_BOTTOM, ps);
3421 /* ditto */
3422 if(old_growth)
3423 set_old_growth_bits(ps, 0);
3425 /* now run through the list (global, user, and cmd_line lists are here) */
3426 if(list){
3427 for(p = list; (q = *p) != NULL; p++){
3428 if(struncmp(q, "no-", 3) == 0){
3429 yorn = 0;
3430 q += 3;
3431 }else{
3432 yorn = 1;
3435 for(i = 0; (feat = feature_list(i)) != NULL; i++){
3436 if(strucmp(q, feat->name) == 0){
3437 if(feat->id == F_OLD_GROWTH){
3438 set_old_growth_bits(ps, yorn);
3439 }else{
3440 F_SET(feat->id, ps, yorn);
3442 break;
3446 /* if it wasn't in that list */
3447 if(feat == NULL)
3448 dprint((1,"Unrecognized feature in feature-list (%s%s)\n",
3449 (yorn ? "" : "no-"), q ? q : "?"));
3454 * Turn on gratuitous '>From ' quoting, if requested...
3456 mail_parameters(NULL, SET_FROMWIDGET,
3457 F_ON(F_QUOTE_ALL_FROMS, ps) ? VOIDT : NIL);
3460 * Turn off .lock creation complaints...
3462 if(F_ON(F_QUELL_LOCK_FAILURE_MSGS, ps))
3463 mail_parameters(NULL, SET_LOCKEACCESERROR, (void *) 0);
3466 * Turn on quelling of pseudo message.
3468 if(F_ON(F_QUELL_INTERNAL_MSG,ps_global))
3469 mail_parameters(NULL, SET_USERHASNOLIFE, (void *) 1);
3471 l = F_ON(F_MULNEWSRC_HOSTNAMES_AS_TYPED,ps_global) ? 0L : 1L;
3472 mail_parameters(NULL, SET_NEWSRCCANONHOST, (void *) l);
3474 ps->pass_ctrl_chars = F_ON(F_PASS_CONTROL_CHARS,ps_global) ? 1 : 0;
3475 ps->pass_c1_ctrl_chars = F_ON(F_PASS_C1_CONTROL_CHARS,ps_global) ? 1 : 0;
3477 #ifndef _WINDOWS
3478 if(F_ON(F_QUELL_BEZERK_TIMEZONE,ps_global))
3479 mail_parameters(NULL, SET_NOTIMEZONES, (void *) 1);
3480 #endif
3482 if(F_ON(F_USE_FK, ps))
3483 ps->orig_use_fkeys = 1;
3485 /* Will we have to build a new list? */
3486 if(!(old_growth || hir || osr))
3487 return;
3490 * Build a new list for feature-list. The only reason we ever need to
3491 * do this is if one of the obsolete options is being converted
3492 * into a feature-list item, and it isn't already included in the user's
3493 * feature-list.
3495 i = 0;
3496 for(p = LVAL(&ps->vars[V_FEATURE_LIST], Main);
3497 p && (q = *p); p++){
3498 /* already have it or cancelled it, don't need to add later */
3499 if(hir && (strucmp(q, "include-header-in-reply") == 0 ||
3500 strucmp(q, "no-include-header-in-reply") == 0)){
3501 hir = 0;
3502 }else if(osr && (strucmp(q, "signature-at-bottom") == 0 ||
3503 strucmp(q, "no-signature-at-bottom") == 0)){
3504 osr = 0;
3505 }else if(old_growth && (strucmp(q, "old-growth") == 0 ||
3506 strucmp(q, "no-old-growth") == 0)){
3507 old_growth = 0;
3509 lvalue[i++] = cpystr(q);
3512 /* check to see if we still need to build a new list */
3513 if(!(old_growth || hir || osr))
3514 return;
3516 if(hir)
3517 lvalue[i++] = "include-header-in-reply";
3518 if(osr)
3519 lvalue[i++] = "signature-at-bottom";
3520 if(old_growth)
3521 lvalue[i++] = "old-growth";
3522 lvalue[i] = NULL;
3523 set_variable_list(V_FEATURE_LIST, lvalue, TRUE, Main);
3527 void
3528 set_current_pattern_vals(struct pine *ps)
3530 struct variable *vars = ps->vars;
3532 set_current_val(&vars[V_PATTERNS], TRUE, TRUE);
3533 set_current_val(&vars[V_PAT_ROLES], TRUE, TRUE);
3534 set_current_val(&vars[V_PAT_FILTS], TRUE, TRUE);
3535 set_current_val(&vars[V_PAT_FILTS_OLD], TRUE, TRUE);
3536 set_current_val(&vars[V_PAT_SCORES], TRUE, TRUE);
3537 set_current_val(&vars[V_PAT_SCORES_OLD], TRUE, TRUE);
3538 set_current_val(&vars[V_PAT_INCOLS], TRUE, TRUE);
3539 set_current_val(&vars[V_PAT_OTHER], TRUE, TRUE);
3540 set_current_val(&vars[V_PAT_SRCH], TRUE, TRUE);
3543 * If old pattern variable (V_PATTERNS) is set and the new ones aren't
3544 * in the config file, then convert the old data into the new variables.
3545 * It isn't quite that simple, though, because we don't store unset
3546 * variables in remote pinercs. Check for the variables but if we
3547 * don't find any of them, also check the version number. This change was
3548 * made in version 4.30. We could just check that except that we're
3549 * worried somebody will make an incompatible version number change in
3550 * their local version, and will break this. So we check both the
3551 * version # and the var_in_pinerc things to be safer.
3553 if(vars[V_PATTERNS].current_val.l
3554 && vars[V_PATTERNS].current_val.l[0]
3555 && !var_in_pinerc(vars[V_PAT_ROLES].name)
3556 && !var_in_pinerc(vars[V_PAT_FILTS].name)
3557 && !var_in_pinerc(vars[V_PAT_FILTS_OLD].name)
3558 && !var_in_pinerc(vars[V_PAT_SCORES].name)
3559 && !var_in_pinerc(vars[V_PAT_SCORES_OLD].name)
3560 && !var_in_pinerc(vars[V_PAT_INCOLS].name)
3561 && isdigit((unsigned char) ps->pine_pre_vers[0])
3562 && ps->pine_pre_vers[1] == '.'
3563 && isdigit((unsigned char) ps->pine_pre_vers[2])
3564 && isdigit((unsigned char) ps->pine_pre_vers[3])
3565 && strncmp(ps->pine_pre_vers, "4.30", 4) < 0){
3566 convert_pattern_data();
3570 * Otherwise, if FILTS_OLD is set and FILTS isn't in the config file,
3571 * convert FILTS_OLD to FILTS. Same for SCORES.
3572 * The reason FILTS was changed was so we could change the
3573 * semantics of how rules work when there are pieces in the rule that
3574 * we don't understand. At the same time as the FILTS change we added
3575 * a rule to detect 8bitSubjects. So a user might have a filter that
3576 * deletes messages with 8bitSubjects. The problem is that that same
3577 * filter in a FILTS_OLD pine would match because it would ignore the
3578 * 8bitSubject part of the pattern and match on the rest. So we changed
3579 * the semantics so that rules with unknown bits would be ignored
3580 * instead of used. We had to change variable names at the same time
3581 * because we were adding the 8bit thing and the old pines are still
3582 * out there. Filters and Scores can both be dangerous. Roles, Colors,
3583 * and Other seem less dangerous so not worth adding a new variable.
3584 * This was changed in 4.50.
3586 else{
3587 if(vars[V_PAT_FILTS_OLD].current_val.l
3588 && vars[V_PAT_FILTS_OLD].current_val.l[0]
3589 && !var_in_pinerc(vars[V_PAT_FILTS].name)
3590 && !var_in_pinerc(vars[V_PAT_SCORES].name)
3591 && isdigit((unsigned char) ps->pine_pre_vers[0])
3592 && ps->pine_pre_vers[1] == '.'
3593 && isdigit((unsigned char) ps->pine_pre_vers[2])
3594 && isdigit((unsigned char) ps->pine_pre_vers[3])
3595 && strncmp(ps->pine_pre_vers, "4.50", 4) < 0){
3596 convert_filts_pattern_data();
3599 if(vars[V_PAT_SCORES_OLD].current_val.l
3600 && vars[V_PAT_SCORES_OLD].current_val.l[0]
3601 && !var_in_pinerc(vars[V_PAT_FILTS].name)
3602 && !var_in_pinerc(vars[V_PAT_SCORES].name)
3603 && isdigit((unsigned char) ps->pine_pre_vers[0])
3604 && ps->pine_pre_vers[1] == '.'
3605 && isdigit((unsigned char) ps->pine_pre_vers[2])
3606 && isdigit((unsigned char) ps->pine_pre_vers[3])
3607 && strncmp(ps->pine_pre_vers, "4.50", 4) < 0){
3608 convert_scores_pattern_data();
3612 if(vars[V_PAT_ROLES].post_user_val.l)
3613 ps_global->ew_for_role_take = Post;
3614 else
3615 ps_global->ew_for_role_take = Main;
3617 if(vars[V_PAT_FILTS].post_user_val.l)
3618 ps_global->ew_for_filter_take = Post;
3619 else
3620 ps_global->ew_for_filter_take = Main;
3622 if(vars[V_PAT_SCORES].post_user_val.l)
3623 ps_global->ew_for_score_take = Post;
3624 else
3625 ps_global->ew_for_score_take = Main;
3627 if(vars[V_PAT_INCOLS].post_user_val.l)
3628 ps_global->ew_for_incol_take = Post;
3629 else
3630 ps_global->ew_for_incol_take = Main;
3632 if(vars[V_PAT_OTHER].post_user_val.l)
3633 ps_global->ew_for_other_take = Post;
3634 else
3635 ps_global->ew_for_other_take = Main;
3637 if(vars[V_PAT_SRCH].post_user_val.l)
3638 ps_global->ew_for_srch_take = Post;
3639 else
3640 ps_global->ew_for_srch_take = Main;
3645 * Foreach of the config files;
3646 * transfer the data to the new variables.
3648 void
3649 convert_pattern_data(void)
3651 convert_pinerc_patterns(PAT_USE_MAIN);
3652 convert_pinerc_patterns(PAT_USE_POST);
3656 void
3657 convert_filts_pattern_data(void)
3659 convert_pinerc_filts_patterns(PAT_USE_MAIN);
3660 convert_pinerc_filts_patterns(PAT_USE_POST);
3664 void
3665 convert_scores_pattern_data(void)
3667 convert_pinerc_scores_patterns(PAT_USE_MAIN);
3668 convert_pinerc_scores_patterns(PAT_USE_POST);
3673 * Foreach of the four variables, transfer the data for this config file
3674 * from the old patterns variable. We don't have to convert OTHER patterns
3675 * or SRCH patterns because they didn't exist in pines without patterns-other.
3677 * If the original variable had patlines with type File then we convert
3678 * all of the individual patterns to type Lit, because each pattern can
3679 * be of any category. Lit patterns are better tested, anyway.
3681 void
3682 convert_pinerc_patterns(long int use_flags)
3684 long old_rflags;
3685 long rflags;
3686 PAT_S *pat;
3687 PAT_STATE pstate;
3688 ACTION_S *act;
3690 old_rflags = (ROLE_OLD_PAT | use_flags);
3692 rflags = 0L;
3693 if(any_patterns(old_rflags, &pstate)){
3694 dprint((2, "converting old patterns to new (%s)\n", (use_flags == PAT_USE_MAIN) ? "Main" : "Post"));
3695 for(pat = first_pattern(&pstate);
3696 pat;
3697 pat = next_pattern(&pstate)){
3698 if((act = pat->action) != NULL){
3699 if(act->is_a_role &&
3700 add_to_pattern(pat, ROLE_DO_ROLES | use_flags))
3701 rflags |= ROLE_DO_ROLES;
3702 if(act->is_a_incol &&
3703 add_to_pattern(pat, ROLE_DO_INCOLS | use_flags))
3704 rflags |= ROLE_DO_INCOLS;
3705 if(act->is_a_score &&
3706 add_to_pattern(pat, ROLE_DO_SCORES | use_flags))
3707 rflags |= ROLE_DO_SCORES;
3708 if(act->is_a_filter &&
3709 add_to_pattern(pat, ROLE_DO_FILTER | use_flags))
3710 rflags |= ROLE_DO_FILTER;
3714 if(rflags)
3715 if(write_patterns(rflags | use_flags))
3716 dprint((1,
3717 "Trouble converting patterns to new variable\n"));
3723 * If the original variable had patlines with type File then we convert
3724 * all of the individual patterns to type Lit, because each pattern can
3725 * be of any category. Lit patterns are better tested, anyway.
3727 void
3728 convert_pinerc_filts_patterns(long int use_flags)
3730 long old_rflags;
3731 long rflags;
3732 PAT_S *pat;
3733 PAT_STATE pstate;
3734 ACTION_S *act;
3736 old_rflags = (ROLE_OLD_FILT | use_flags);
3738 rflags = 0L;
3739 if(any_patterns(old_rflags, &pstate)){
3740 dprint((2, "converting old filter patterns to new (%s)\n", (use_flags == PAT_USE_MAIN) ? "Main" : "Post"));
3741 for(pat = first_pattern(&pstate);
3742 pat;
3743 pat = next_pattern(&pstate)){
3744 if((act = pat->action) != NULL){
3745 if(act->is_a_filter &&
3746 add_to_pattern(pat, ROLE_DO_FILTER | use_flags))
3747 rflags |= ROLE_DO_FILTER;
3751 if(rflags)
3752 if(write_patterns(rflags | use_flags))
3753 dprint((1,
3754 "Trouble converting filter patterns to new variable\n"));
3760 * If the original variable had patlines with type File then we convert
3761 * all of the individual patterns to type Lit, because each pattern can
3762 * be of any category. Lit patterns are better tested, anyway.
3764 void
3765 convert_pinerc_scores_patterns(long int use_flags)
3767 long old_rflags;
3768 long rflags;
3769 PAT_S *pat;
3770 PAT_STATE pstate;
3771 ACTION_S *act;
3773 old_rflags = (ROLE_OLD_SCORE | use_flags);
3775 rflags = 0L;
3776 if(any_patterns(old_rflags, &pstate)){
3777 dprint((2, "converting old scores patterns to new (%s)\n", (use_flags == PAT_USE_MAIN) ? "Main" : "Post"));
3778 for(pat = first_pattern(&pstate);
3779 pat;
3780 pat = next_pattern(&pstate)){
3781 if((act = pat->action) != NULL){
3782 if(act->is_a_score &&
3783 add_to_pattern(pat, ROLE_DO_SCORES | use_flags))
3784 rflags |= ROLE_DO_SCORES;
3788 if(rflags)
3789 if(write_patterns(rflags | use_flags))
3790 dprint((1,
3791 "Trouble converting scores patterns to new variable\n"));
3797 * set_old_growth_bits - Command used to set or unset old growth set
3798 * of features
3800 void
3801 set_old_growth_bits(struct pine *ps, int val)
3803 int i;
3805 for(i = 1; i <= F_FEATURE_LIST_COUNT; i++)
3806 if(test_old_growth_bits(ps, i))
3807 F_SET(i, ps, val);
3813 * test_old_growth_bits - Test to see if all the old growth bits are on,
3814 * *or* if a particular feature index is in the old
3815 * growth set.
3817 * WEIRD ALERT: if index == F_OLD_GROWTH bit values are tested
3818 * otherwise a bits existence in the set is tested!!!
3820 * BUG: this will break if an old growth feature number is ever >= 32.
3823 test_old_growth_bits(struct pine *ps, int index)
3826 * this list defines F_OLD_GROWTH set
3828 static unsigned long old_growth_bits = ((1 << F_ENABLE_FULL_HDR) |
3829 (1 << F_ENABLE_PIPE) |
3830 (1 << F_ENABLE_TAB_COMPLETE) |
3831 (1 << F_QUIT_WO_CONFIRM) |
3832 (1 << F_ENABLE_JUMP) |
3833 (1 << F_ENABLE_ALT_ED) |
3834 (1 << F_ENABLE_BOUNCE) |
3835 (1 << F_ENABLE_AGG_OPS) |
3836 (1 << F_ENABLE_FLAG) |
3837 (1 << F_CAN_SUSPEND));
3838 if(index >= 32)
3839 return(0);
3841 if(index == F_OLD_GROWTH){
3842 for(index = 1; index <= F_FEATURE_LIST_COUNT; index++)
3843 if(((1 << index) & old_growth_bits) && F_OFF(index, ps))
3844 return(0);
3846 return(1);
3848 else
3849 return((1 << index) & old_growth_bits);
3854 * Side effect is that the appropriate global variable is set, and the
3855 * appropriate current_val is set.
3857 void
3858 cur_rule_value(struct variable *var, int expand, int cmdline)
3860 int i;
3861 NAMEVAL_S *v;
3863 set_current_val(var, expand, cmdline);
3865 if(var == &ps_global->vars[V_SAVED_MSG_NAME_RULE]){
3866 if(ps_global->VAR_SAVED_MSG_NAME_RULE)
3867 for(i = 0; (v = save_msg_rules(i)); i++)
3868 if(!strucmp(ps_global->VAR_SAVED_MSG_NAME_RULE, S_OR_L(v))){
3869 ps_global->save_msg_rule = v->value;
3870 break;
3873 #ifndef _WINDOWS
3874 else if(var == &ps_global->vars[V_COLOR_STYLE]){
3875 if(ps_global->VAR_COLOR_STYLE)
3876 for(i = 0; (v = col_style(i)); i++)
3877 if(!strucmp(ps_global->VAR_COLOR_STYLE, S_OR_L(v))){
3878 ps_global->color_style = v->value;
3879 break;
3882 #endif
3883 else if(var == &ps_global->vars[V_INDEX_COLOR_STYLE]){
3884 if(ps_global->VAR_INDEX_COLOR_STYLE)
3885 for(i = 0; (v = index_col_style(i)); i++)
3886 if(!strucmp(ps_global->VAR_INDEX_COLOR_STYLE, S_OR_L(v))){
3887 ps_global->index_color_style = v->value;
3888 break;
3891 else if(var == &ps_global->vars[V_TITLEBAR_COLOR_STYLE]){
3892 if(ps_global->VAR_TITLEBAR_COLOR_STYLE)
3893 for(i = 0; (v = titlebar_col_style(i)); i++)
3894 if(!strucmp(ps_global->VAR_TITLEBAR_COLOR_STYLE, S_OR_L(v))){
3895 ps_global->titlebar_color_style = v->value;
3896 break;
3899 else if(var == &ps_global->vars[V_FCC_RULE]){
3900 if(ps_global->VAR_FCC_RULE)
3901 for(i = 0; (v = fcc_rules(i)); i++)
3902 if(!strucmp(ps_global->VAR_FCC_RULE, S_OR_L(v))){
3903 ps_global->fcc_rule = v->value;
3904 break;
3907 else if(var == &ps_global->vars[V_GOTO_DEFAULT_RULE]){
3908 if(ps_global->VAR_GOTO_DEFAULT_RULE)
3909 for(i = 0; (v = goto_rules(i)); i++)
3910 if(!strucmp(ps_global->VAR_GOTO_DEFAULT_RULE, S_OR_L(v))){
3911 ps_global->goto_default_rule = v->value;
3912 break;
3915 else if(var == &ps_global->vars[V_INCOMING_STARTUP]){
3916 if(ps_global->VAR_INCOMING_STARTUP)
3917 for(i = 0; (v = incoming_startup_rules(i)); i++)
3918 if(!strucmp(ps_global->VAR_INCOMING_STARTUP, S_OR_L(v))){
3919 ps_global->inc_startup_rule = v->value;
3920 break;
3923 else if(var == &ps_global->vars[V_PRUNING_RULE]){
3924 if(ps_global->VAR_PRUNING_RULE)
3925 for(i = 0; (v = pruning_rules(i)); i++)
3926 if(!strucmp(ps_global->VAR_PRUNING_RULE, S_OR_L(v))){
3927 ps_global->pruning_rule = v->value;
3928 break;
3931 else if(var == &ps_global->vars[V_REOPEN_RULE]){
3932 if(ps_global->VAR_REOPEN_RULE)
3933 for(i = 0; (v = reopen_rules(i)); i++)
3934 if(!strucmp(ps_global->VAR_REOPEN_RULE, S_OR_L(v))){
3935 ps_global->reopen_rule = v->value;
3936 break;
3939 else if(var == &ps_global->vars[V_FLD_SORT_RULE]){
3940 if(ps_global->VAR_FLD_SORT_RULE)
3941 for(i = 0; (v = fld_sort_rules(i)); i++)
3942 if(!strucmp(ps_global->VAR_FLD_SORT_RULE, S_OR_L(v))){
3943 ps_global->fld_sort_rule = v->value;
3944 break;
3947 else if(var == &ps_global->vars[V_AB_SORT_RULE]){
3948 if(ps_global->VAR_AB_SORT_RULE)
3949 for(i = 0; (v = ab_sort_rules(i)); i++)
3950 if(!strucmp(ps_global->VAR_AB_SORT_RULE, S_OR_L(v))){
3951 ps_global->ab_sort_rule = v->value;
3952 break;
3955 else if(var == &ps_global->vars[V_THREAD_DISP_STYLE]){
3956 if(ps_global->VAR_THREAD_DISP_STYLE)
3957 for(i = 0; (v = thread_disp_styles(i)); i++)
3958 if(!strucmp(ps_global->VAR_THREAD_DISP_STYLE, S_OR_L(v))){
3959 ps_global->thread_disp_style = v->value;
3960 break;
3963 else if(var == &ps_global->vars[V_THREAD_INDEX_STYLE]){
3964 if(ps_global->VAR_THREAD_INDEX_STYLE)
3965 for(i = 0; (v = thread_index_styles(i)); i++)
3966 if(!strucmp(ps_global->VAR_THREAD_INDEX_STYLE, S_OR_L(v))){
3967 ps_global->thread_index_style = v->value;
3968 break;
3975 * Standard way to get at save message rules...
3977 NAMEVAL_S *
3978 save_msg_rules(int index)
3980 static NAMEVAL_S save_rules[] = {
3981 {"by-from", NULL, SAV_RULE_FROM},
3982 {"by-nick-of-from", NULL, SAV_RULE_NICK_FROM_DEF},
3983 {"by-nick-of-from-then-from", NULL, SAV_RULE_NICK_FROM},
3984 {"by-fcc-of-from", NULL, SAV_RULE_FCC_FROM_DEF},
3985 {"by-fcc-of-from-then-from", NULL, SAV_RULE_FCC_FROM},
3986 {"by-realname-of-from", NULL, SAV_RULE_RN_FROM_DEF},
3987 {"by-realname-of-from-then-from", NULL, SAV_RULE_RN_FROM},
3988 {"by-sender", NULL, SAV_RULE_SENDER},
3989 {"by-nick-of-sender", NULL, SAV_RULE_NICK_SENDER_DEF},
3990 {"by-nick-of-sender-then-sender", NULL, SAV_RULE_NICK_SENDER},
3991 {"by-fcc-of-sender", NULL, SAV_RULE_FCC_SENDER_DEF},
3992 {"by-fcc-of-sender-then-sender", NULL, SAV_RULE_FCC_SENDER},
3993 {"by-realname-of-sender", NULL, SAV_RULE_RN_SENDER_DEF},
3994 {"by-realname-of-sender-then-sender", NULL, SAV_RULE_RN_SENDER},
3995 {"by-recipient", NULL, SAV_RULE_RECIP},
3996 {"by-nick-of-recip", NULL, SAV_RULE_NICK_RECIP_DEF},
3997 {"by-nick-of-recip-then-recip", NULL, SAV_RULE_NICK_RECIP},
3998 {"by-fcc-of-recip", NULL, SAV_RULE_FCC_RECIP_DEF},
3999 {"by-fcc-of-recip-then-recip", NULL, SAV_RULE_FCC_RECIP},
4000 {"by-realname-of-recip", NULL, SAV_RULE_RN_RECIP_DEF},
4001 {"by-realname-of-recip-then-recip", NULL, SAV_RULE_RN_RECIP},
4002 {"by-replyto", NULL, SAV_RULE_REPLYTO},
4003 {"by-nick-of-replyto", NULL, SAV_RULE_NICK_REPLYTO_DEF},
4004 {"by-nick-of-replyto-then-replyto", NULL, SAV_RULE_NICK_REPLYTO},
4005 {"by-fcc-of-replyto", NULL, SAV_RULE_FCC_REPLYTO_DEF},
4006 {"by-fcc-of-replyto-then-replyto", NULL, SAV_RULE_FCC_REPLYTO},
4007 {"by-realname-of-replyto", NULL, SAV_RULE_RN_REPLYTO_DEF},
4008 {"by-realname-of-replyto-then-replyto", NULL, SAV_RULE_RN_REPLYTO},
4009 {"last-folder-used", NULL, SAV_RULE_LAST},
4010 {"default-folder", NULL, SAV_RULE_DEFLT}
4013 return((index >= 0 && index < (sizeof(save_rules)/sizeof(save_rules[0])))
4014 ? &save_rules[index] : NULL);
4019 * Standard way to get at fcc rules...
4021 NAMEVAL_S *
4022 fcc_rules(int index)
4024 static NAMEVAL_S f_rules[] = {
4025 {"default-fcc", NULL, FCC_RULE_DEFLT},
4026 {"last-fcc-used", NULL, FCC_RULE_LAST},
4027 {"by-recipient", NULL, FCC_RULE_RECIP},
4028 {"by-nickname", NULL, FCC_RULE_NICK},
4029 {"by-nick-then-recip", NULL, FCC_RULE_NICK_RECIP},
4030 {"current-folder", NULL, FCC_RULE_CURRENT}
4033 return((index >= 0 && index < (sizeof(f_rules)/sizeof(f_rules[0])))
4034 ? &f_rules[index] : NULL);
4039 * Standard way to get at addrbook sort rules...
4041 NAMEVAL_S *
4042 ab_sort_rules(int index)
4044 static NAMEVAL_S ab_rules[] = {
4045 {"fullname-with-lists-last", NULL, AB_SORT_RULE_FULL_LISTS},
4046 {"fullname", NULL, AB_SORT_RULE_FULL},
4047 {"nickname-with-lists-last", NULL, AB_SORT_RULE_NICK_LISTS},
4048 {"nickname", NULL, AB_SORT_RULE_NICK},
4049 {"dont-sort", NULL, AB_SORT_RULE_NONE}
4052 return((index >= 0 && index < (sizeof(ab_rules)/sizeof(ab_rules[0])))
4053 ? &ab_rules[index] : NULL);
4058 * Standard way to get at color styles.
4060 NAMEVAL_S *
4061 col_style(int index)
4063 static NAMEVAL_S col_styles[] = {
4064 {"no-color", NULL, COL_NONE},
4065 {"use-termdef", NULL, COL_TERMDEF},
4066 {"force-ansi-8color", NULL, COL_ANSI8},
4067 {"force-ansi-16color", NULL, COL_ANSI16},
4068 {"force-xterm-256color", NULL, COL_ANSI256}
4071 return((index >= 0 && index < (sizeof(col_styles)/sizeof(col_styles[0])))
4072 ? &col_styles[index] : NULL);
4077 * Standard way to get at index color styles.
4079 NAMEVAL_S *
4080 index_col_style(int index)
4082 static NAMEVAL_S ind_col_styles[] = {
4083 {"flip-colors", NULL, IND_COL_FLIP},
4084 {"reverse", NULL, IND_COL_REV},
4085 {"reverse-fg", NULL, IND_COL_FG},
4086 {"reverse-fg-no-ambiguity", NULL, IND_COL_FG_NOAMBIG},
4087 {"reverse-bg", NULL, IND_COL_BG},
4088 {"reverse-bg-no-ambiguity", NULL, IND_COL_BG_NOAMBIG}
4091 return((index >= 0 && index < (sizeof(ind_col_styles)/sizeof(ind_col_styles[0]))) ? &ind_col_styles[index] : NULL);
4096 * Standard way to get at titlebar color styles.
4098 NAMEVAL_S *
4099 titlebar_col_style(int index)
4101 static NAMEVAL_S tbar_col_styles[] = {
4102 {"default", NULL, TBAR_COLOR_DEFAULT},
4103 {"indexline", NULL, TBAR_COLOR_INDEXLINE},
4104 {"reverse-indexline", NULL, TBAR_COLOR_REV_INDEXLINE}
4107 return((index >= 0 && index < (sizeof(tbar_col_styles)/sizeof(tbar_col_styles[0]))) ? &tbar_col_styles[index] : NULL);
4112 * Standard way to get at folder sort rules...
4114 NAMEVAL_S *
4115 fld_sort_rules(int index)
4117 static NAMEVAL_S fdl_rules[] = {
4118 {"alphabetical", NULL, FLD_SORT_ALPHA},
4119 {"alpha-with-dirs-last", NULL, FLD_SORT_ALPHA_DIR_LAST},
4120 {"alpha-with-dirs-first", NULL, FLD_SORT_ALPHA_DIR_FIRST}
4123 return((index >= 0 && index < (sizeof(fdl_rules)/sizeof(fdl_rules[0])))
4124 ? &fdl_rules[index] : NULL);
4129 * Standard way to get at incoming startup rules...
4131 NAMEVAL_S *
4132 incoming_startup_rules(int index)
4134 static NAMEVAL_S is_rules[] = {
4135 {"first-unseen", NULL, IS_FIRST_UNSEEN},
4136 {"first-recent", NULL, IS_FIRST_RECENT},
4137 {"first-important", NULL, IS_FIRST_IMPORTANT},
4138 {"first-important-or-unseen", NULL, IS_FIRST_IMPORTANT_OR_UNSEEN},
4139 {"first-important-or-recent", NULL, IS_FIRST_IMPORTANT_OR_RECENT},
4140 {"first", NULL, IS_FIRST},
4141 {"last", NULL, IS_LAST}
4144 return((index >= 0 && index < (sizeof(is_rules)/sizeof(is_rules[0])))
4145 ? &is_rules[index] : NULL);
4149 NAMEVAL_S *
4150 startup_rules(int index)
4152 static NAMEVAL_S is2_rules[] = {
4153 {"first-unseen", NULL, IS_FIRST_UNSEEN},
4154 {"first-recent", NULL, IS_FIRST_RECENT},
4155 {"first-important", NULL, IS_FIRST_IMPORTANT},
4156 {"first-important-or-unseen", NULL, IS_FIRST_IMPORTANT_OR_UNSEEN},
4157 {"first-important-or-recent", NULL, IS_FIRST_IMPORTANT_OR_RECENT},
4158 {"first", NULL, IS_FIRST},
4159 {"last", NULL, IS_LAST},
4160 {"default", NULL, IS_NOTSET}
4163 return((index >= 0 && index < (sizeof(is2_rules)/sizeof(is2_rules[0])))
4164 ? &is2_rules[index] : NULL);
4169 * Standard way to get at pruning-rule values.
4171 NAMEVAL_S *
4172 pruning_rules(int index)
4174 static NAMEVAL_S pr_rules[] = {
4175 {"ask about rename, ask about deleting","ask-ask", PRUNE_ASK_AND_ASK},
4176 {"ask about rename, don't delete", "ask-no", PRUNE_ASK_AND_NO},
4177 {"always rename, ask about deleting", "yes-ask", PRUNE_YES_AND_ASK},
4178 {"always rename, don't delete", "yes-no", PRUNE_YES_AND_NO},
4179 {"don't rename, ask about deleting", "no-ask", PRUNE_NO_AND_ASK},
4180 {"don't rename, don't delete", "no-no", PRUNE_NO_AND_NO}
4183 return((index >= 0 && index < (sizeof(pr_rules)/sizeof(pr_rules[0])))
4184 ? &pr_rules[index] : NULL);
4189 * Standard way to get at reopen-rule values.
4191 NAMEVAL_S *
4192 reopen_rules(int index)
4194 static NAMEVAL_S ro_rules[] = {
4195 /* TRANSLATORS: short description of a feature option */
4196 {"Always reopen", "yes-yes",
4197 REOPEN_YES_YES},
4198 /* TRANSLATORS: short description of a feature option, default in brackets */
4199 {"Yes for POP/NNTP, Ask about other remote [Yes]", "yes-ask-y",
4200 REOPEN_YES_ASK_Y},
4201 /* TRANSLATORS: short description of a feature option, default in brackets */
4202 {"Yes for POP/NNTP, Ask about other remote [No]", "yes-ask-n",
4203 REOPEN_YES_ASK_N},
4204 /* TRANSLATORS: short description of a feature option */
4205 {"Yes for POP/NNTP, No for other remote", "yes-no",
4206 REOPEN_YES_NO},
4207 /* TRANSLATORS: short description of a feature option, default in brackets */
4208 {"Always ask [Yes]", "ask-ask-y",
4209 REOPEN_ASK_ASK_Y},
4210 /* TRANSLATORS: short description of a feature option, default in brackets */
4211 {"Always ask [No]", "ask-ask-n",
4212 REOPEN_ASK_ASK_N},
4213 /* TRANSLATORS: short description of a feature option, default in brackets */
4214 {"Ask about POP/NNTP [Yes], No for other remote", "ask-no-y",
4215 REOPEN_ASK_NO_Y},
4216 /* TRANSLATORS: short description of a feature option, default in brackets */
4217 {"Ask about POP/NNTP [No], No for other remote", "ask-no-n",
4218 REOPEN_ASK_NO_N},
4219 /* TRANSLATORS: short description of a feature option */
4220 {"Never reopen", "no-no",
4221 REOPEN_NO_NO},
4224 return((index >= 0 && index < (sizeof(ro_rules)/sizeof(ro_rules[0])))
4225 ? &ro_rules[index] : NULL);
4230 * Standard way to get at thread_disp_style values.
4232 NAMEVAL_S *
4233 thread_disp_styles(int index)
4235 static NAMEVAL_S td_styles[] = {
4236 {"none", "none", THREAD_NONE},
4237 {"show-thread-structure", "struct", THREAD_STRUCT},
4238 {"mutt-like", "mutt", THREAD_MUTTLIKE},
4239 {"indent-subject-1", "subj1", THREAD_INDENT_SUBJ1},
4240 {"indent-subject-2", "subj2", THREAD_INDENT_SUBJ2},
4241 {"indent-from-1", "from1", THREAD_INDENT_FROM1},
4242 {"indent-from-2", "from2", THREAD_INDENT_FROM2},
4243 {"show-structure-in-from", "struct-from", THREAD_STRUCT_FROM}
4246 return((index >= 0 && index < (sizeof(td_styles)/sizeof(td_styles[0])))
4247 ? &td_styles[index] : NULL);
4252 * Standard way to get at thread_index_style values.
4254 NAMEVAL_S *
4255 thread_index_styles(int index)
4257 static NAMEVAL_S ti_styles[] = {
4258 {"regular-index-with-expanded-threads", "exp", THRDINDX_EXP},
4259 {"regular-index-with-collapsed-threads","coll", THRDINDX_COLL},
4260 {"separate-index-screen-always", "sep", THRDINDX_SEP},
4261 {"separate-index-screen-except-for-single-messages","sep-auto",
4262 THRDINDX_SEP_AUTO}
4265 return((index >= 0 && index < (sizeof(ti_styles)/sizeof(ti_styles[0])))
4266 ? &ti_styles[index] : NULL);
4271 * Standard way to get at goto default rules...
4273 NAMEVAL_S *
4274 goto_rules(int index)
4276 static NAMEVAL_S g_rules[] = {
4277 {"folder-in-first-collection", NULL, GOTO_FIRST_CLCTN},
4278 {"inbox-or-folder-in-first-collection", NULL, GOTO_INBOX_FIRST_CLCTN},
4279 {"inbox-or-folder-in-recent-collection", NULL, GOTO_INBOX_RECENT_CLCTN},
4280 {"first-collection-with-inbox-default", NULL, GOTO_FIRST_CLCTN_DEF_INBOX},
4281 {"most-recent-folder", NULL, GOTO_LAST_FLDR}
4284 return((index >= 0 && index < (sizeof(g_rules)/sizeof(g_rules[0])))
4285 ? &g_rules[index] : NULL);
4289 NAMEVAL_S *
4290 pat_fldr_types(int index)
4292 static NAMEVAL_S pat_fldr_list[] = {
4293 {"Any", "ANY", FLDR_ANY},
4294 {"News", "NEWS", FLDR_NEWS},
4295 {"Email", "EMAIL", FLDR_EMAIL},
4296 {"Specific (Enter Incoming Nicknames or use ^T)", "SPEC", FLDR_SPECIFIC}
4299 return((index >= 0 &&
4300 index < (sizeof(pat_fldr_list)/sizeof(pat_fldr_list[0])))
4301 ? &pat_fldr_list[index] : NULL);
4305 NAMEVAL_S *
4306 inabook_fldr_types(int indexarg)
4308 static NAMEVAL_S inabook_fldr_list[] = {
4309 {"Don't care, always matches", "E", IAB_EITHER},
4310 {"Yes, in any address book", "YES", IAB_YES},
4311 {"No, not in any address book", "NO", IAB_NO},
4312 {"Yes, in specific address books", "SYES", IAB_SPEC_YES},
4313 {"No, not in any of specific address books", "SNO", IAB_SPEC_NO}
4316 int index = indexarg & IAB_TYPE_MASK;
4318 return((index >= 0 &&
4319 index < (sizeof(inabook_fldr_list)/sizeof(inabook_fldr_list[0])))
4320 ? &inabook_fldr_list[index] : NULL);
4324 NAMEVAL_S *
4325 filter_types(int index)
4327 static NAMEVAL_S filter_type_list[] = {
4328 {"Just Set Message Status", "NONE", FILTER_STATE},
4329 {"Delete", "DEL", FILTER_KILL},
4330 {"Move (Enter folder name(s) in primary collection, or use ^T)",
4331 "FLDR", FILTER_FOLDER}
4334 return((index >= 0 &&
4335 index < (sizeof(filter_type_list)/sizeof(filter_type_list[0])))
4336 ? &filter_type_list[index] : NULL);
4340 NAMEVAL_S *
4341 role_repl_types(int index)
4343 static NAMEVAL_S role_repl_list[] = {
4344 {"Never", "NO", ROLE_REPL_NO},
4345 {"With confirmation", "YES", ROLE_REPL_YES},
4346 {"Without confirmation", "NC", ROLE_REPL_NOCONF}
4349 return((index >= 0 &&
4350 index < (sizeof(role_repl_list)/sizeof(role_repl_list[0])))
4351 ? &role_repl_list[index] : NULL);
4355 NAMEVAL_S *
4356 role_forw_types(int index)
4358 static NAMEVAL_S role_forw_list[] = {
4359 {"Never", "NO", ROLE_FORW_NO},
4360 {"With confirmation", "YES", ROLE_FORW_YES},
4361 {"Without confirmation", "NC", ROLE_FORW_NOCONF}
4364 return((index >= 0 &&
4365 index < (sizeof(role_forw_list)/sizeof(role_forw_list[0])))
4366 ? &role_forw_list[index] : NULL);
4370 NAMEVAL_S *
4371 role_comp_types(int index)
4373 static NAMEVAL_S role_comp_list[] = {
4374 {"Never", "NO", ROLE_COMP_NO},
4375 {"With confirmation", "YES", ROLE_COMP_YES},
4376 {"Without confirmation", "NC", ROLE_COMP_NOCONF}
4379 return((index >= 0 &&
4380 index < (sizeof(role_comp_list)/sizeof(role_comp_list[0])))
4381 ? &role_comp_list[index] : NULL);
4385 NAMEVAL_S *
4386 role_status_types(int index)
4388 static NAMEVAL_S role_status_list[] = {
4389 {"Don't care, always matches", "E", PAT_STAT_EITHER},
4390 {"Yes", "YES", PAT_STAT_YES},
4391 {"No", "NO", PAT_STAT_NO}
4394 return((index >= 0 &&
4395 index < (sizeof(role_status_list)/sizeof(role_status_list[0])))
4396 ? &role_status_list[index] : NULL);
4400 NAMEVAL_S *
4401 msg_state_types(int index)
4403 static NAMEVAL_S msg_state_list[] = {
4404 {"Don't change it", "LV", ACT_STAT_LEAVE},
4405 {"Set this state", "SET", ACT_STAT_SET},
4406 {"Clear this state", "CLR", ACT_STAT_CLEAR}
4409 return((index >= 0 &&
4410 index < (sizeof(msg_state_list)/sizeof(msg_state_list[0])))
4411 ? &msg_state_list[index] : NULL);
4415 #ifdef ENABLE_LDAP
4416 NAMEVAL_S *
4417 ldap_search_rules(int index)
4419 static NAMEVAL_S ldap_search_list[] = {
4420 {"contains", NULL, LDAP_SRCH_CONTAINS},
4421 {"equals", NULL, LDAP_SRCH_EQUALS},
4422 {"begins-with", NULL, LDAP_SRCH_BEGINS},
4423 {"ends-with", NULL, LDAP_SRCH_ENDS}
4426 return((index >= 0 &&
4427 index < (sizeof(ldap_search_list)/sizeof(ldap_search_list[0])))
4428 ? &ldap_search_list[index] : NULL);
4432 NAMEVAL_S *
4433 ldap_search_types(int index)
4435 static NAMEVAL_S ldap_types_list[] = {
4436 {"name", NULL, LDAP_TYPE_CN},
4437 {"surname", NULL, LDAP_TYPE_SUR},
4438 {"givenname", NULL, LDAP_TYPE_GIVEN},
4439 {"email", NULL, LDAP_TYPE_EMAIL},
4440 {"name-or-email", NULL, LDAP_TYPE_CN_EMAIL},
4441 {"surname-or-givenname", NULL, LDAP_TYPE_SUR_GIVEN},
4442 {"sur-or-given-or-name-or-email", NULL, LDAP_TYPE_SEVERAL}
4445 return((index >= 0 &&
4446 index < (sizeof(ldap_types_list)/sizeof(ldap_types_list[0])))
4447 ? &ldap_types_list[index] : NULL);
4451 NAMEVAL_S *
4452 ldap_search_scope(int index)
4454 static NAMEVAL_S ldap_scope_list[] = {
4455 {"base", NULL, LDAP_SCOPE_BASE},
4456 {"onelevel", NULL, LDAP_SCOPE_ONELEVEL},
4457 {"subtree", NULL, LDAP_SCOPE_SUBTREE}
4460 return((index >= 0 &&
4461 index < (sizeof(ldap_scope_list)/sizeof(ldap_scope_list[0])))
4462 ? &ldap_scope_list[index] : NULL);
4464 #endif
4468 * Choose from the global default, command line args, pinerc values to set
4469 * the actual value of the variable that we will use. Start at the top
4470 * and work down from higher to lower precedence.
4471 * For lists, we may inherit values from lower precedence
4472 * versions if that's the way the user specifies it.
4473 * The user can put INHERIT_DEFAULT as the first entry in a list and that
4474 * means it will inherit the current values, for example the values
4475 * from the global_val, or the value from the main_user_val could be
4476 * inherited in the post_user_val.
4478 void
4479 set_current_val(struct variable *var, int expand, int cmdline)
4481 int is_set[5], is_inherit[5];
4482 int i, j, k, cnt, start;
4483 char **tmp, **t, **list[5];
4484 char *p;
4486 dprint((9,
4487 "set_current_val(var=%s%s, expand=%d, cmdline=%d)\n",
4488 (var && var->name) ? var->name : "?",
4489 (var && var->is_list) ? " (list)" : "",
4490 expand, cmdline));
4492 if(!var)
4493 return;
4495 if(var->is_list){ /* variable is a list */
4497 for(j = 0; j < 5; j++){
4498 t = j==0 ? var->global_val.l :
4499 j==1 ? var->main_user_val.l :
4500 j==2 ? var->post_user_val.l :
4501 j==3 ? ((cmdline) ? var->cmdline_val.l : NULL) :
4502 var->fixed_val.l;
4504 is_set[j] = is_inherit[j] = 0;
4505 list[j] = NULL;
4507 if(t){
4508 if(!expand){
4509 is_set[j]++;
4510 list[j] = t;
4512 else{
4513 for(i = 0; t[i]; i++){
4514 if(expand_variables(tmp_20k_buf, SIZEOF_20KBUF, t[i],
4515 0)){
4516 /* successful expand */
4517 is_set[j]++;
4518 list[j] = t;
4519 break;
4524 if(list[j] && list[j][0] && !strcmp(list[j][0],INHERIT))
4525 is_inherit[j]++;
4529 cnt = 0;
4530 start = 0;
4531 /* count how many items in current_val list */
4532 /* Admin wants default, which is global_val. */
4533 if(var->is_fixed && var->fixed_val.l == NULL){
4534 cnt = 0;
4535 if(is_set[0]){
4536 for(; list[0][cnt]; cnt++)
4540 else{
4541 for(j = 0; j < 5; j++){
4542 if(is_set[j]){
4543 if(!is_inherit[j]){
4544 cnt = 0; /* reset */
4545 start = j;
4548 for(i = is_inherit[j] ? 1 : 0; list[j][i]; i++)
4549 cnt++;
4554 free_list_array(&var->current_val.l); /* clean up any old values */
4556 /* check to see if anything is set */
4557 if(is_set[0] + is_set[1] + is_set[2] + is_set[3] + is_set[4] > 0){
4558 var->current_val.l = (char **)fs_get((cnt+1)*sizeof(char *));
4559 tmp = var->current_val.l;
4560 if(var->is_fixed && var->fixed_val.l == NULL){
4561 if(is_set[0]){
4562 for(i = 0; list[0][i]; i++){
4563 if(!expand)
4564 *tmp++ = cpystr(list[0][i]);
4565 else if(expand_variables(tmp_20k_buf, SIZEOF_20KBUF,
4566 list[0][i], 0))
4567 *tmp++ = cpystr(tmp_20k_buf);
4571 else{
4572 for(j = start; j < 5; j++){
4573 if(is_set[j]){
4574 for(i = is_inherit[j] ? 1 : 0; list[j][i]; i++){
4575 if(!expand)
4576 *tmp++ = cpystr(list[j][i]);
4577 else if(expand_variables(tmp_20k_buf,SIZEOF_20KBUF,
4578 list[j][i], 0))
4579 *tmp++ = cpystr(tmp_20k_buf);
4585 *tmp = NULL;
4587 else
4588 var->current_val.l = NULL;
4590 else{ /* variable is not a list */
4591 char *strvar = NULL;
4593 for(j = 0; j < 5; j++){
4595 p = j==0 ? var->fixed_val.p :
4596 j==1 ? ((cmdline) ? var->cmdline_val.p : NULL) :
4597 j==2 ? var->post_user_val.p :
4598 j==3 ? var->main_user_val.p :
4599 var->global_val.p;
4601 is_set[j] = 0;
4603 if(p){
4604 if(!expand){
4605 is_set[j]++;
4606 if(!strvar)
4607 strvar = p;
4609 else if(expand_variables(tmp_20k_buf, SIZEOF_20KBUF, p,
4610 (var == &ps_global->vars[V_MAILCAP_PATH] ||
4611 var == &ps_global->vars[V_MIMETYPE_PATH]))){
4612 is_set[j]++;
4613 if(!strvar)
4614 strvar = p;
4619 /* Admin wants default, which is global_val. */
4620 if(var->is_fixed && var->fixed_val.p == NULL)
4621 strvar = var->global_val.p;
4623 if(var->current_val.p) /* free previous value */
4624 fs_give((void **)&var->current_val.p);
4626 if(strvar){
4627 if(!expand)
4628 var->current_val.p = cpystr(strvar);
4629 else{
4630 expand_variables(tmp_20k_buf, SIZEOF_20KBUF, strvar,
4631 (var == &ps_global->vars[V_MAILCAP_PATH] ||
4632 var == &ps_global->vars[V_MIMETYPE_PATH]));
4633 var->current_val.p = cpystr(tmp_20k_buf);
4636 else
4637 var->current_val.p = NULL;
4640 if(var->is_fixed && !is_inherit[4]){
4641 char **flist;
4642 int fixed_len, user_len;
4645 * sys mgr fixed this variable and user is trying to change it
4647 for(k = 1; !(ps_global->give_fixed_warning &&
4648 ps_global->fix_fixed_warning) && k <= 3; k++){
4649 if(is_set[k]){
4650 if(var->is_list){
4651 t = k==1 ? ((cmdline) ? var->cmdline_val.l : NULL) :
4652 k==2 ? var->post_user_val.l :
4653 var->main_user_val.l;
4655 /* If same length and same contents, don't warn. */
4656 for(flist=var->fixed_val.l; flist && *flist; flist++)
4657 ;/* just counting */
4659 fixed_len = var->fixed_val.l ? (flist - var->fixed_val.l)
4660 : 0;
4661 for(flist=t; flist && *flist; flist++)
4662 ;/* just counting */
4664 user_len = t ? (flist - t) : 0;
4665 if(user_len == fixed_len){
4666 for(i=0; i < user_len; i++){
4667 for(j=0; j < user_len; j++)
4668 if(!strucmp(t[i], var->fixed_val.l[j]))
4669 break;
4671 if(j == user_len){
4672 ps_global->give_fixed_warning = 1;
4673 if(k != 1)
4674 ps_global->fix_fixed_warning = 1;
4676 break;
4680 else{
4681 ps_global->give_fixed_warning = 1;
4682 if(k != 1)
4683 ps_global->fix_fixed_warning = 1;
4686 else{
4687 p = k==1 ? ((cmdline) ? var->cmdline_val.p : NULL) :
4688 k==2 ? var->post_user_val.p :
4689 var->main_user_val.p;
4691 if((var->fixed_val.p && !p) ||
4692 (!var->fixed_val.p && p) ||
4693 (var->fixed_val.p && p && strucmp(var->fixed_val.p, p))){
4694 ps_global->give_fixed_warning = 1;
4695 if(k != 1)
4696 ps_global->fix_fixed_warning = 1;
4705 void
4706 set_news_spec_current_val(int expand, int cmdline)
4708 struct variable *newsvar = &ps_global->vars[V_NEWS_SPEC];
4709 struct variable *fvar = &ps_global->vars[V_FOLDER_SPEC];
4711 /* check to see if it has a value */
4712 set_current_val(newsvar, expand, cmdline);
4715 * If no value, we might want to fake a value. We'll do that if
4716 * there is no news collection already defined in FOLDER_SPEC and if
4717 * there is also an NNTP_SERVER defined.
4719 if(!newsvar->current_val.l && ps_global->VAR_NNTP_SERVER &&
4720 ps_global->VAR_NNTP_SERVER[0] && ps_global->VAR_NNTP_SERVER[0][0] &&
4721 !news_in_folders(fvar)){
4722 char buf[MAXPATH];
4724 newsvar->global_val.l = (char **)fs_get(2 * sizeof(char *));
4725 snprintf(buf, sizeof(buf), "{%.*s/nntp}#news.[]", MAXPATH-20,
4726 ps_global->VAR_NNTP_SERVER[0]); /* MAXPATH = sizeof(buf) */
4727 newsvar->global_val.l[0] = cpystr(buf);
4728 newsvar->global_val.l[1] = NULL;
4729 set_current_val(newsvar, expand, cmdline);
4731 * But we're going to get rid of the fake global_val in case
4732 * things change.
4734 free_list_array(&newsvar->global_val.l);
4740 * Feature-list has to be handled separately from the other variables
4741 * because it is additive. The other variables choose one of command line,
4742 * or pine.conf, or pinerc. Feature list adds them. This could easily be
4743 * converted to a general purpose routine if we add more additive variables.
4745 * This works by replacing earlier values with later ones. That is, command
4746 * line settings have higher precedence than global settings and that is
4747 * accomplished by putting the command line features after the global
4748 * features in the list. When they are processed, the last one wins.
4750 * Feature-list also has a backwards compatibility hack.
4752 void
4753 set_feature_list_current_val(struct variable *var)
4755 char **list;
4756 char **list_fixed;
4757 char no_allow[50];
4758 int i, j, k, m,
4759 elems = 0;
4761 /* count the lists so we can allocate */
4762 for(m = 0; m < 6; m++){
4763 list = m==0 ? var->global_val.l :
4764 m==1 ? var->main_user_val.l :
4765 m==2 ? var->post_user_val.l :
4766 m==3 ? ps_global->feat_list_back_compat :
4767 m==4 ? var->cmdline_val.l :
4768 var->fixed_val.l;
4769 if(list)
4770 for(i = 0; list[i]; i++)
4771 elems++;
4774 list_fixed = var->fixed_val.l;
4776 if(var->current_val.l)
4777 free_list_array(&var->current_val.l);
4779 var->current_val.l = (char **)fs_get((elems+1) * sizeof(char *));
4782 * We need to warn the user if the sys mgr has restricted him or her
4783 * from changing a feature that he or she is trying to change.
4785 * We're not catching the old-growth macro since we're just comparing
4786 * strings. That is, it works correctly, but the user won't be warned
4787 * if the user old-growth and the mgr says no-quit-without-confirm.
4790 j = 0;
4791 strncpy(no_allow, "no-", 3);
4792 strncpy(no_allow+3, feature_list_name(F_ALLOW_CHANGING_FROM), sizeof(no_allow)-3-1);
4793 no_allow[sizeof(no_allow)-1] = '\0';
4795 for(m = 0; m < 6; m++){
4796 list = m==0 ? var->global_val.l :
4797 m==1 ? var->main_user_val.l :
4798 m==2 ? var->post_user_val.l :
4799 m==3 ? ps_global->feat_list_back_compat :
4800 m==4 ? var->cmdline_val.l :
4801 var->fixed_val.l;
4802 if(list)
4803 for(i = 0; list[i]; i++){
4804 var->current_val.l[j++] = cpystr(list[i]);
4806 /* this is the warning section */
4807 if(m >= 1 && m <= 4){
4808 for(k = 0; list_fixed && list_fixed[k]; k++){
4809 char *p, *q;
4810 p = list[i];
4811 q = list_fixed[k];
4812 if(!struncmp(p, "no-", 3))
4813 p += 3;
4814 if(!struncmp(q, "no-", 3))
4815 q += 3;
4816 if(!strucmp(q, p) && strucmp(list[i], list_fixed[k])){
4817 ps_global->give_fixed_warning = 1;
4818 if(m <= 2)
4819 ps_global->fix_fixed_warning = 1;
4823 else if(m == 5 && !strucmp(list[i], no_allow))
4824 ps_global->never_allow_changing_from = 1;
4828 #ifdef NEVER_ALLOW_CHANGING_FROM
4829 ps_global->never_allow_changing_from = 1;
4830 #endif
4832 var->current_val.l[j] = NULL;
4837 /*----------------------------------------------------------------------
4839 Expand Metacharacters/variables in file-names
4841 Read input line and expand shell-variables/meta-characters
4843 <input> <replaced by>
4844 $variable getenv("variable")
4845 ${variable} getenv("variable")
4846 ${variable:-defvalue} is getenv("variable") if variable is defined and
4847 is defvalue otherwise
4848 ~ getenv("HOME")
4849 \c c
4850 <others> <just copied>
4852 NOTE handling of braces in ${name} doesn't check much or do error recovery
4854 If colon_path is set, then we expand ~ not only at the start of linein,
4855 but also after each : in the path.
4857 ----*/
4858 #define is_allowed_envchar(C, S) ((S) == 0 ? !isspace((C)) && (C) != '/'\
4859 : (((C) >= 'a' && (C) <= 'z') \
4860 || ((C) >= 'A' && (C) <= 'Z') \
4861 || ((C) >= '0' && (C) <= '9')))
4863 char *
4864 expand_variables(char *lineout, size_t lineoutlen, char *linein, int colon_path)
4866 char *src = linein, *dest = lineout, *p;
4867 char *limit = lineout + lineoutlen;
4868 int envexpand = 0, sp;
4870 if(!linein)
4871 return(NULL);
4873 sp = strncmp(src,"LIT:pattern=\"/NICK=", strlen("LIT:pattern=\"/NICK=")) == 0;
4874 while(*src ){ /* something in input string */
4875 if(*src == '$' && *(src+1) == '$'){
4877 * $$ to escape chars we're interested in, else
4878 * it's up to the user of the variable to handle the
4879 * backslash...
4881 if(dest < limit)
4882 *dest++ = *++src; /* copy next as is */
4883 }else
4884 #if !(defined(DOS) || defined(OS2))
4885 if(*src == '\\' && *(src+1) == '$'){
4887 * backslash to escape chars we're interested in, else
4888 * it's up to the user of the variable to handle the
4889 * backslash...
4891 if(dest < limit)
4892 *dest++ = *++src; /* copy next as is */
4893 }else if(*src == '~' &&
4894 (src == linein || (colon_path && *(src-1) == ':'))){
4895 char buf[MAXPATH];
4896 int i;
4898 for(i = 0; i < sizeof(buf)-1 && src[i] && src[i] != '/'; i++)
4899 buf[i] = src[i];
4901 src += i; /* advance src pointer */
4902 buf[i] = '\0'; /* tie off buf string */
4903 fnexpand(buf, sizeof(buf)); /* expand the path */
4905 for(p = buf; dest < limit && (*dest = *p); p++, dest++)
4908 continue;
4909 }else
4910 #endif
4911 if(*src == '$'){ /* shell variable */
4912 char word[128+1], *colon = NULL, *rbrace = NULL;
4914 envexpand++; /* signal that we've expanded a var */
4915 src++; /* skip dollar */
4916 if(*src == '{'){ /* starts with brace? */
4917 src++;
4918 rbrace = strindex(src, '}');
4919 if(rbrace){
4920 /* look for default value */
4921 colon = strstr(src, ":-");
4922 if(colon && (rbrace < colon))
4923 colon = NULL;
4927 p = word;
4929 /* put the env variable to be looked up in word */
4930 if(rbrace){
4931 while(*src
4932 && (p-word < sizeof(word)-1)
4933 && ((colon && src < colon) || (!colon && src < rbrace))){
4934 if(isspace((unsigned char) *src)){
4936 * Illegal input. This should be an error of some
4937 * sort but instead of that we'll just backup to the
4938 * $ and treat it like it wasn't there.
4940 while(*src != '$')
4941 src--;
4943 envexpand--;
4944 goto just_copy;
4946 else
4947 *p++ = *src++;
4950 /* adjust src for next char */
4951 src = rbrace + 1;
4953 else{
4954 while(*src && is_allowed_envchar((unsigned char) *src, sp)
4955 && (p-word < sizeof(word)-1))
4956 *p++ = *src++;
4959 *p = '\0';
4961 if((p = getenv(word)) != NULL){ /* check for word in environment */
4962 while(*p && dest < limit)
4963 *dest++ = *p++;
4965 else if(colon){ /* else possible default value */
4966 p = colon + 2;
4967 while(*p && p < rbrace && dest < limit)
4968 *dest++ = *p++;
4971 continue;
4972 }else{ /* other cases: just copy */
4973 just_copy:
4974 if(dest < limit)
4975 *dest++ = *src;
4978 if(*src) /* next character (if any) */
4979 src++;
4982 if(dest < limit)
4983 *dest = '\0';
4984 else
4985 lineout[lineoutlen-1] = '\0';
4987 return((envexpand && lineout[0] == '\0') ? NULL : lineout);
4991 /*----------------------------------------------------------------------
4992 Sets login, full_username and home_dir
4994 Args: ps -- The Pine structure to put the user name, etc in
4996 Result: sets the fullname, login and home_dir field of the pine structure
4997 returns 0 on success, -1 if not.
4998 ----*/
4999 #define MAX_INIT_ERRS 10
5000 void
5001 init_error(struct pine *ps, int flags, int min_time, int max_time, char *message)
5003 int i;
5005 if(!ps->init_errs){
5006 ps->init_errs = (INIT_ERR_S *)fs_get((MAX_INIT_ERRS + 1) *
5007 sizeof(*ps->init_errs));
5008 memset(ps->init_errs, 0, (MAX_INIT_ERRS + 1) * sizeof(*ps->init_errs));
5011 for(i = 0; i < MAX_INIT_ERRS; i++)
5012 if(!(ps->init_errs)[i].message){
5013 (ps->init_errs)[i].message = cpystr(message);
5014 (ps->init_errs)[i].min_time = min_time;
5015 (ps->init_errs)[i].max_time = max_time;
5016 (ps->init_errs)[i].flags = flags;
5017 dprint((2, "%s\n", message ? message : "?"));
5018 break;
5023 /*----------------------------------------------------------------------
5024 Read and parse a pinerc file
5026 Args: Filename -- name of the .pinerc file to open and read
5027 vars -- The vars structure to store values in
5028 which_vars -- Whether the local or global values are being read
5030 Result:
5032 This may be the local file or the global file. The values found are
5033 merged with the values currently in vars. All values are strings and
5034 are malloced; and existing values will be freed before the assignment.
5035 Those that are <unset> will be left unset; their values will be NULL.
5036 ----*/
5037 void
5038 read_pinerc(PINERC_S *prc, struct variable *vars, ParsePinerc which_vars)
5040 char *filename, *file, *value, **lvalue, *line, *error;
5041 char *p, *p1, *free_file = NULL;
5042 struct variable *v;
5043 PINERC_LINE *pline = NULL;
5044 int line_count, was_quoted;
5045 int i;
5047 if(!prc)
5048 return;
5050 dprint((2, "reading_pinerc \"%s\"\n",
5051 prc->name ? prc->name : "?"));
5053 if(prc->type == Loc){
5054 filename = prc->name ? prc->name : "";
5055 file = free_file = read_file(filename, 0);
5058 * This is questionable. In case the user edits the pinerc
5059 * in Windows and adds a UTF-8 BOM, we skip it here. If the
5060 * user adds a Unicode BOM we're in trouble. We could write it
5061 * with the BOM ourselves but so far we leave it BOMless in
5062 * order that it's the same on Unix and Windows.
5064 if(BOM_UTF8(file))
5065 file += 3;
5067 else{
5068 if((file = read_remote_pinerc(prc, which_vars)) != NULL)
5069 ps_global->c_client_error[0] = '\0';
5071 free_file = file;
5074 if(file == NULL || *file == '\0'){
5075 #ifdef DEBUG
5076 if(file == NULL){
5077 dprint((2, "Open failed: %s\n", error_description(errno)));
5079 else{
5080 if(prc->type == Loc){
5081 dprint((1, "Read_pinerc: empty pinerc (new?)\n"));
5083 else{
5084 dprint((1, "Read_pinerc: new remote pinerc\n"));
5087 #endif /* DEBUG */
5089 if(which_vars == ParsePers){
5090 /* problems getting remote config */
5091 if(file == NULL && prc->type == RemImap){
5092 if(!pith_opt_remote_pinerc_failure
5093 || !(*pith_opt_remote_pinerc_failure)())
5094 exceptional_exit(_("Unable to read or write remote configuration"), -1);
5097 ps_global->first_time_user = 1;
5098 prc->outstanding_pinerc_changes = 1;
5101 return;
5103 else{
5104 if(prc->type == Loc &&
5105 (which_vars == ParseFixed || which_vars == ParseGlobal ||
5106 (can_access(filename, ACCESS_EXISTS) == 0 &&
5107 can_access(filename, EDIT_ACCESS) != 0))){
5108 prc->readonly = 1;
5109 if(prc == ps_global->prc)
5110 ps_global->readonly_pinerc = 1;
5114 * accept CRLF or LF newlines
5116 for(p = file; *p && *p != '\012'; p++)
5119 if(p > file && *p && *(p-1) == '\015') /* cvt crlf to lf */
5120 for(p1 = p - 1; (*p1 = *p) != '\0'; p++)
5121 if(!(*p == '\015' && *(p+1) == '\012'))
5122 p1++;
5125 dprint((2, "Read %d characters:\n", strlen(file)));
5127 if(which_vars == ParsePers || which_vars == ParsePersPost){
5128 /*--- Count up lines and allocate structures */
5129 for(line_count = 0, p = file; *p != '\0'; p++)
5130 if(*p == '\n')
5131 line_count++;
5133 prc->pinerc_lines = (PINERC_LINE *)
5134 fs_get((3 + line_count) * sizeof(PINERC_LINE));
5135 memset((void *)prc->pinerc_lines, 0,
5136 (3 + line_count) * sizeof(PINERC_LINE));
5137 pline = prc->pinerc_lines;
5140 for(p = file, line = file; *p != '\0';){
5141 /*----- Grab the line ----*/
5142 line = p;
5143 while(*p && *p != '\n')
5144 p++;
5145 if(*p == '\n'){
5146 *p++ = '\0';
5149 /*----- Comment Line -----*/
5150 if(*line == '#'){
5151 /* no comments in remote pinercs */
5152 if(pline && prc->type == Loc){
5153 pline->is_var = 0;
5154 pline->line = cpystr(line);
5155 pline++;
5157 continue;
5160 if(*line == '\0' || *line == '\t' || *line == ' '){
5161 p1 = line;
5162 while(*p1 == '\t' || *p1 == ' ')
5163 p1++;
5164 if(pline){
5166 * This could be a continuation line from some future
5167 * version of pine, or it could be a continuation line
5168 * from a PC-Pine variable we don't know about in unix.
5170 if(*p1 != '\0')
5171 pline->line = cpystr(line);
5172 else
5173 pline->line = cpystr("");
5174 pline->is_var = 0;
5175 pline++;
5177 continue;
5180 /*----- look up matching 'v' and leave "value" after '=' ----*/
5181 for(v = vars; *line && v->name; v++)
5182 if((i = strlen(v->name)) < strlen(line) && !struncmp(v->name,line,i)){
5183 int j;
5185 for(j = i; line[j] == ' ' || line[j] == '\t'; j++)
5188 if(line[j] == '='){ /* bingo! */
5189 for(value = &line[j+1];
5190 *value == ' ' || *value == '\t';
5191 value++)
5194 break;
5196 /* else either unrecognized var or bogus line */
5199 /*----- Didn't match any variable or bogus format -----*/
5201 * This could be a variable from some future
5202 * version of pine, or it could be a PC-Pine variable
5203 * we don't know about in unix. Either way, we want to preserve
5204 * it in the file.
5206 if(!v->name){
5207 if(pline){
5208 pline->is_var = 0;
5209 pline->line = cpystr(line);
5210 pline++;
5212 continue;
5216 * Previous versions have caused duplicate pinerc data to be
5217 * written to pinerc files. This clause erases the duplicate
5218 * information when we read it, and it will be removed from the file
5219 * if we call write_pinerc. We test to see if the same variable
5220 * appears later in the file, if so, we skip over it here.
5221 * We don't care about duplicates if this isn't a pinerc we might
5222 * write out, so include pline in the conditional.
5223 * Note that we will leave all of the duplicate comments and blank
5224 * lines in the file unless it is a remote pinerc. Luckily, the
5225 * bug that caused the duplicates only applied to remote pinercs,
5226 * so we should have that case covered.
5228 * If we find a duplicate, we point p to the start
5229 * of the next line that should be considered, and then skip back
5230 * to the top of the loop.
5232 if(pline && var_is_in_rest_of_file(v->name, p)){
5233 if(v->is_list)
5234 p = skip_over_this_var(line, p);
5236 continue;
5240 /*----- Obsolete variable, read it anyway below, might use it -----*/
5241 if(v->is_obsolete){
5242 if(pline){
5243 pline->obsolete_var = 1;
5244 pline->line = cpystr(line);
5245 pline->var = v;
5249 /*----- Variable is in the list but unused for some reason -----*/
5250 if(!v->is_used){
5251 if(pline){
5252 pline->is_var = 0;
5253 pline->line = cpystr(line);
5254 pline++;
5256 continue;
5259 /*--- Var is not user controlled, leave it alone for back compat ---*/
5260 if(!v->is_user && pline){
5261 pline->is_var = 0;
5262 pline->line = cpystr(line);
5263 pline++;
5264 continue;
5267 if(which_vars == ParseFixed)
5268 v->is_fixed = 1;
5270 /*---- variable is unset, or it's global but expands to nothing ----*/
5271 if(!*value
5272 || (which_vars == ParseGlobal
5273 && !expand_variables(tmp_20k_buf, SIZEOF_20KBUF, value,
5274 (v == &ps_global->vars[V_MAILCAP_PATH] ||
5275 v == &ps_global->vars[V_MIMETYPE_PATH])))){
5276 if(v->is_user && pline){
5277 pline->is_var = 1;
5278 pline->var = v;
5279 pline++;
5281 continue;
5284 /*--value is non-empty, store it handling quotes and trailing space--*/
5285 if(*value == '"' && !v->is_list && v->del_quotes){
5286 was_quoted = 1;
5287 value++;
5288 for(p1 = value; *p1 && *p1 != '"'; p1++);
5289 if(*p1 == '"')
5290 *p1 = '\0';
5291 else
5292 removing_trailing_white_space(value);
5293 }else
5294 was_quoted = 0;
5297 * List Entry Parsing
5299 * The idea is to parse a comma separated list of
5300 * elements, preserving quotes, and understanding
5301 * continuation lines (that is ',' == "\n ").
5302 * Quotes must be balanced within elements. Space
5303 * within elements is preserved, but leading and trailing
5304 * space is trimmed. This is a generic function, and it's
5305 * left to the the functions that use the lists to make sure
5306 * they contain valid data...
5308 if(v->is_list){
5310 was_quoted = 0;
5311 line_count = 0;
5312 p1 = value;
5313 while(1){ /* generous count of list elements */
5314 if(*p1 == '"') /* ignore ',' if quoted */
5315 was_quoted = (was_quoted) ? 0 : 1 ;
5317 if((*p1 == ',' && !was_quoted) || *p1 == '\n' || *p1 == '\0')
5318 line_count++; /* count this element */
5320 if(*p1 == '\0' || *p1 == '\n'){ /* deal with EOL */
5321 if(p1 < p || *p1 == '\n'){
5322 *p1++ = ','; /* fix null or newline */
5324 if(*p1 != '\t' && *p1 != ' '){
5325 *(p1-1) = '\0'; /* tie off list */
5326 p = p1; /* reset p */
5327 break;
5329 }else{
5330 p = p1; /* end of pinerc */
5331 break;
5333 }else
5334 p1++;
5337 error = NULL;
5338 lvalue = parse_list(value, line_count,
5339 v->del_quotes ? PL_REMSURRQUOT : PL_NONE,
5340 &error);
5341 if(error){
5342 dprint((1,
5343 "read_pinerc: ERROR: %s in %s = \"%s\"\n",
5344 error ? error : "?",
5345 v->name ? v->name : "?",
5346 value ? value : "?"));
5349 * Special case: turn "" strings into empty strings.
5350 * This allows users to turn off default lists. For example,
5351 * if smtp-server is set then a user could override smtp-server
5352 * with smtp-server="".
5354 for(i = 0; lvalue[i]; i++)
5355 if(lvalue[i][0] == '"' &&
5356 lvalue[i][1] == '"' &&
5357 lvalue[i][2] == '\0')
5358 lvalue[i][0] = '\0';
5361 if(pline){
5362 if(v->is_user && (which_vars == ParsePers || !v->is_onlymain)){
5363 if(v->is_list){
5364 char ***l;
5366 l = (which_vars == ParsePers) ? &v->main_user_val.l
5367 : &v->post_user_val.l;
5368 free_list_array(l);
5369 *l = lvalue;
5371 else{
5372 char **p;
5374 p = (which_vars == ParsePers) ? &v->main_user_val.p
5375 : &v->post_user_val.p;
5376 if(p && *p != NULL)
5377 fs_give((void **)p);
5379 *p = cpystr(value);
5382 if(pline){
5383 pline->is_var = 1;
5384 pline->var = v;
5385 pline->is_quoted = was_quoted;
5386 pline++;
5390 else if(which_vars == ParseGlobal){
5391 if(v->is_global){
5392 if(v->is_list){
5393 free_list_array(&v->global_val.l);
5394 v->global_val.l = lvalue;
5396 else{
5397 if(v->global_val.p != NULL)
5398 fs_give((void **) &(v->global_val.p));
5400 v->global_val.p = cpystr(value);
5404 else{ /* which_vars == ParseFixed */
5405 if(v->is_user || v->is_global){
5406 if(v->is_list){
5407 free_list_array(&v->fixed_val.l);
5408 v->fixed_val.l = lvalue;
5410 else{
5411 if(v->fixed_val.p != NULL)
5412 fs_give((void **) &(v->fixed_val.p));
5414 v->fixed_val.p = cpystr(value);
5419 #ifdef DEBUG
5420 if(v->is_list){
5421 char **l;
5422 l = (which_vars == ParsePers) ? v->main_user_val.l :
5423 (which_vars == ParsePersPost) ? v->post_user_val.l :
5424 (which_vars == ParseGlobal) ? v->global_val.l :
5425 v->fixed_val.l;
5426 if(l && *l && **l){
5427 dprint((5, " %20.20s : %s\n",
5428 v->name ? v->name : "?",
5429 *l ? *l : "?"));
5430 while(++l && *l && **l)
5431 dprint((5, " %20.20s : %s\n", "",
5432 *l ? *l : "?"));
5434 }else{
5435 char *p;
5436 p = (which_vars == ParsePers) ? v->main_user_val.p :
5437 (which_vars == ParsePersPost) ? v->post_user_val.p :
5438 (which_vars == ParseGlobal) ? v->global_val.p :
5439 v->fixed_val.p;
5440 if(p && *p)
5441 dprint((5, " %20.20s : %s\n",
5442 v->name ? v->name : "?",
5443 p ? p : "?"));
5445 #endif /* DEBUG */
5448 if(pline){
5449 pline->line = NULL;
5450 pline->is_var = 0;
5451 if(!prc->pinerc_written && prc->type == Loc){
5452 prc->pinerc_written = name_file_mtime(filename);
5453 dprint((5, "read_pinerc: time_pinerc_written = %ld\n",
5454 (long) prc->pinerc_written));
5458 if(free_file)
5459 fs_give((void **) &free_file);
5464 * Args varname The variable name we're looking for
5465 * begin Begin looking here
5467 * Returns 1 if variable varname appears in the rest of the file
5468 * 0 if not
5471 var_is_in_rest_of_file(char *varname, char *begin)
5473 char *p;
5475 if(!(varname && *varname && begin && *begin))
5476 return 0;
5478 p = begin;
5480 while((p = srchstr(p, varname)) != NULL){
5481 /* beginning of a line? */
5482 if(p > begin && (*(p-1) != '\n' && *(p-1) != '\r')){
5483 p++;
5484 continue;
5487 /* followed by [ SPACE ] < = > ? */
5488 p += strlen(varname);
5489 while(*p == ' ' || *p == '\t')
5490 p++;
5492 if(*p == '=')
5493 return 1;
5496 return 0;
5501 * Args begin Variable to skip starts here.
5502 * nextline This is where the next line starts. We need to know this
5503 * because the input has been mangled a little. A \0 has
5504 * replaced the \n at the end of the first line, but we can
5505 * use nextline to help us out of that quandry.
5507 * Return a pointer to the start of the first line after this variable
5508 * and all of its continuation lines.
5510 char *
5511 skip_over_this_var(char *begin, char *nextline)
5513 char *p;
5515 p = begin;
5517 while(1){
5518 if(*p == '\0' || *p == '\n'){ /* EOL */
5519 if(p < nextline || *p == '\n'){ /* there may be another line */
5520 p++;
5521 if(*p != ' ' && *p != '\t') /* no continuation line */
5522 return(p);
5524 else /* end of file */
5525 return(p);
5527 else
5528 p++;
5533 static char quotes[3] = {'"', '"', '\0'};
5534 /*----------------------------------------------------------------------
5535 Write out the .pinerc state information
5537 Args: ps -- The pine structure to take state to be written from
5538 which -- Which pinerc to write
5539 flags -- If bit WRP_NOUSER is set, then assume that there is
5540 not a user present to answer questions.
5542 This writes to a temporary file first, and then renames that to
5543 be the new .pinerc file to protect against disk error. This has the
5544 problem of possibly messing up file protections, ownership and links.
5545 ----*/
5547 write_pinerc(struct pine *ps, EditWhich which, int flags)
5549 char *p, *dir, *tmp = NULL, *pinrc;
5550 char *pval, **lval;
5551 char *linep = NULL, *lineq = NULL;
5552 int bc = 1;
5553 int buflen;
5554 PINERC_LINE *pline;
5555 struct variable *var;
5556 time_t mtime;
5557 char *filename;
5558 REMDATA_S *rd = NULL;
5559 PINERC_S *prc = NULL;
5560 STORE_S *so = NULL;
5561 #ifndef _WINDOWS
5562 struct stat sbuf;
5563 char *slink = NULL;
5564 #endif
5566 #define MAXPLINESIZE 10000
5568 dprint((2,"---- write_pinerc(%s) ----\n",
5569 (which == Main) ? "Main" : "Post"));
5571 switch(which){
5572 case Main:
5573 prc = ps ? ps->prc : NULL;
5574 break;
5575 case Post:
5576 prc = ps ? ps->post_prc : NULL;
5577 break;
5578 default:
5579 break;
5582 if(!prc)
5583 return(-1);
5585 if(prc->quit_to_edit){
5586 if(!(flags & WRP_NOUSER))
5587 quit_to_edit_msg(prc);
5589 return(-1);
5592 if(prc->type != Loc && !prc->readonly){
5594 bc = 0; /* don't do backcompat conversion */
5595 rd = prc->rd;
5596 if(!rd)
5597 return(-1);
5599 rd_check_remvalid(rd, -10L);
5601 if(rd->flags & REM_OUTOFDATE){
5602 if((flags & WRP_NOUSER) || unexpected_pinerc_change()){
5603 prc->outstanding_pinerc_changes = 1;
5604 if(!(flags & WRP_NOUSER))
5605 q_status_message1(SM_ORDER | SM_DING, 3, 3,
5606 "Pinerc \"%.200s\" NOT saved",
5607 prc->name ? prc->name : "");
5608 dprint((2, "write_pinerc: remote pinerc changed\n"));
5609 return(-1);
5611 else
5612 rd->flags &= ~REM_OUTOFDATE;
5615 rd_open_remote(rd);
5617 if(rd->access == ReadWrite){
5618 int ro;
5620 if((ro=rd_remote_is_readonly(rd)) || rd->flags & REM_OUTOFDATE){
5621 if(ro == 1){
5622 if(!(flags & WRP_NOUSER))
5623 q_status_message(SM_ORDER | SM_DING, 5, 15,
5624 _("Can't access remote config, changes NOT saved!"));
5625 dprint((1,
5626 "write_pinerc: Can't write to remote pinerc %s, aborting write\n",
5627 rd->rn ? rd->rn : "?"));
5629 else if(ro == 2){
5630 if(!(rd->flags & NO_META_UPDATE)){
5631 unsigned long save_chk_nmsgs;
5633 switch(rd->type){
5634 case RemImap:
5635 save_chk_nmsgs = rd->t.i.chk_nmsgs;
5636 rd->t.i.chk_nmsgs = 0;
5637 rd_write_metadata(rd, 0);
5638 rd->t.i.chk_nmsgs = save_chk_nmsgs;
5639 break;
5641 default:
5642 q_status_message(SM_ORDER | SM_DING, 3, 5,
5643 "Write_pinerc: Type not supported");
5644 break;
5648 if(!(flags & WRP_NOUSER))
5649 q_status_message1(SM_ORDER | SM_DING, 5, 15,
5650 _("No write permission for remote config %.200s, changes NOT saved!"),
5651 rd->rn);
5653 else{
5654 if(!(flags & WRP_NOUSER))
5655 q_status_message(SM_ORDER | SM_DING, 5, 15,
5656 _("Remote config changed, aborting our change to avoid damage..."));
5657 dprint((1,
5658 "write_pinerc: remote config %s changed since we started pine, aborting write\n",
5659 prc->name ? prc->name : "?"));
5662 rd->flags &= ~DO_REMTRIM;
5663 return(-1);
5666 filename = rd->lf;
5668 else{
5669 prc->readonly = 1;
5670 if(prc == ps->prc)
5671 ps->readonly_pinerc = 1;
5674 else
5675 filename = prc->name ? prc->name : "";
5677 pinrc = prc->name ? prc->name : "";
5679 if(prc->type == Loc){
5680 mtime = name_file_mtime(filename);
5681 if(prc->pinerc_written
5682 && prc->pinerc_written != mtime
5683 && ((flags & WRP_NOUSER) || unexpected_pinerc_change())){
5684 prc->outstanding_pinerc_changes = 1;
5686 if(!(flags & WRP_NOUSER))
5687 q_status_message1(SM_ORDER | SM_DING, 3, 3,
5688 "Pinerc \"%.200s\" NOT saved", pinrc);
5690 dprint((2,"write_pinerc: mtime mismatch: \"%s\": %ld != %ld\n",
5691 filename ? filename : "?",
5692 (long) prc->pinerc_written, (long) mtime));
5693 return(-1);
5697 /* don't write if pinerc is read-only */
5698 if(prc->readonly ||
5699 (filename &&
5700 can_access(filename, ACCESS_EXISTS) == 0 &&
5701 can_access(filename, EDIT_ACCESS) != 0)){
5702 prc->readonly = 1;
5703 if(prc == ps->prc)
5704 ps->readonly_pinerc = 1;
5706 if(!(flags & WRP_NOUSER))
5707 q_status_message1(SM_ORDER | SM_DING, 0, 5,
5708 _("Can't modify configuration file \"%.200s\": ReadOnly"),
5709 pinrc);
5710 dprint((2, "write_pinerc: fail because can't access pinerc\n"));
5712 if(rd)
5713 rd->flags &= ~DO_REMTRIM;
5715 return(-1);
5718 if(rd && rd->flags & NO_FILE){
5719 so = rd->sonofile;
5720 so_truncate(rd->sonofile, 0L); /* reset storage object */
5722 else{
5723 dir = ".";
5724 if((p = last_cmpnt(filename)) != NULL){
5725 *--p = '\0';
5726 dir = filename;
5729 #if defined(DOS) || defined(OS2)
5730 if(!(isalpha((unsigned char)dir[0]) && dir[1] == ':' && dir[2] == '\0')
5731 && (can_access(dir, EDIT_ACCESS) < 0 &&
5732 our_mkdir(dir, 0700) < 0))
5734 if(!(flags & WRP_NOUSER))
5735 q_status_message2(SM_ORDER | SM_DING, 3, 5,
5736 /* TRANSLATORS: first argument is a filename, second
5737 arg is the text of the error message */
5738 _("Error creating \"%.200s\" : %.200s"), dir,
5739 error_description(errno));
5740 if(rd)
5741 rd->flags &= ~DO_REMTRIM;
5743 return(-1);
5746 tmp = temp_nam(dir, "rc");
5748 if(*dir && tmp && !in_dir(dir, tmp)){
5749 our_unlink(tmp);
5750 fs_give((void **)&tmp);
5753 if(p)
5754 *p = '\\';
5756 if(tmp == NULL)
5757 goto io_err;
5759 #else /* !DOS */
5760 tmp = temp_nam((*dir) ? dir : "/", "pinerc");
5763 * If temp_nam can't write in dir it puts the temp file in a
5764 * temp directory, which won't help us when we go to rename.
5766 if(*dir && tmp && !in_dir(dir, tmp)){
5767 our_unlink(tmp);
5768 fs_give((void **)&tmp);
5771 if(p)
5772 *p = '/';
5774 if(tmp == NULL)
5775 goto io_err;
5777 #endif /* !DOS */
5779 if((so = so_get(FileStar, tmp, WRITE_ACCESS)) == NULL)
5780 goto io_err;
5783 if(!(flags & WRP_PRESERV_WRITTEN))
5784 for(var = ps->vars; var->name != NULL; var++)
5785 var->been_written = 0;
5787 if(prc->type == Loc && ps->first_time_user &&
5788 !so_puts(so, native_nl(cf_text_comment)))
5789 goto io_err;
5791 linep = fs_get((MAXPLINESIZE+1)*sizeof(char));
5792 lineq = fs_get((MAXPLINESIZE+1)*sizeof(char));
5793 buflen = MAXPLINESIZE;
5795 /* Write out what was in the .pinerc */
5796 for(pline = prc->pinerc_lines;
5797 pline && (pline->is_var || pline->line); pline++){
5798 if(pline->is_var){
5799 var = pline->var;
5801 if(var->is_list)
5802 lval = LVAL(var, which);
5803 else
5804 pval = PVAL(var, which);
5806 /* variable is not set */
5807 if((var->is_list && (!lval || !lval[0])) ||
5808 (!var->is_list && !pval)){
5809 /* leave null variables out of remote pinerc */
5810 if(prc->type == Loc &&
5811 (!so_puts(so, var->name) || !so_puts(so, "=") ||
5812 !so_puts(so, NEWLINE)))
5813 goto io_err;
5815 /* var is set to empty string */
5816 else if((var->is_list && lval[0][0] == '\0') ||
5817 (!var->is_list && pval[0] == '\0')){
5818 if(!so_puts(so, var->name) || !so_puts(so, "=") ||
5819 !so_puts(so, quotes) || !so_puts(so, NEWLINE))
5820 goto io_err;
5822 else{
5823 if(var->is_list){
5824 int i = 0;
5826 for(i = 0; lval[i]; i++){
5827 if(strlen(var->name)
5828 + (lval[i][0] ? strlen(lval[i]) : 5) > buflen){
5829 buflen = strlen(var->name)
5830 + (lval[i][0] ? strlen(lval[i]) : 5);
5831 fs_resize((void **)&linep, (buflen+1)*sizeof(char));
5832 fs_resize((void **)&lineq, (buflen+1)*sizeof(char));
5834 snprintf(linep, buflen+1, "%s%s%s%s%s",
5835 (i) ? "\t" : var->name,
5836 (i) ? "" : "=",
5837 lval[i][0] ? lval[i] : quotes,
5838 lval[i+1] ? "," : "", NEWLINE);
5839 linep[buflen] = '\0';
5840 if(!so_puts(so, bc ? backcompat_convert_from_utf8(&lineq, buflen+1, linep) : linep))
5841 goto io_err;
5844 else{
5845 if(strlen(var->name)
5846 + (pval[0] ? strlen(pval) : 5) > buflen){
5847 buflen = strlen(var->name)
5848 + (pval[0] ? strlen(pval) : 5);
5849 fs_resize((void **)&linep, (buflen+1)*sizeof(char));
5850 fs_resize((void **)&lineq, (buflen+1)*sizeof(char));
5852 snprintf(linep, buflen+1, "%s=%s%s%s%s",
5853 var->name,
5854 (pline->is_quoted && pval[0] != '\"')
5855 ? "\"" : "",
5856 pval,
5857 (pline->is_quoted && pval[0] != '\"')
5858 ? "\"" : "", NEWLINE);
5859 linep[buflen] = '\0';
5860 if(!so_puts(so, bc ? backcompat_convert_from_utf8(&lineq, buflen+1, linep) : linep))
5861 goto io_err;
5865 var->been_written = 1;
5867 }else{
5869 * The description text should be changed into a message
5870 * about the variable being obsolete when a variable is
5871 * moved to obsolete status. We add that message before
5872 * the variable unless it is already there. However, we
5873 * leave the variable itself in case the user runs an old
5874 * version of pine again. Note that we have read in the
5875 * value of the variable in read_pinerc and translated it
5876 * into a new variable if appropriate.
5878 if(pline->obsolete_var && prc->type == Loc){
5879 if(pline <= prc->pinerc_lines || (pline-1)->line == NULL ||
5880 strlen((pline-1)->line) < 3 ||
5881 strucmp((pline-1)->line+2, pline->var->descrip) != 0)
5882 if(!so_puts(so, "# ") ||
5883 !so_puts(so, native_nl(pline->var->descrip)) ||
5884 !so_puts(so, NEWLINE))
5885 goto io_err;
5888 /* remove comments from remote pinercs */
5889 if((prc->type == Loc ||
5890 (pline->line[0] != '#' && pline->line[0] != '\0')) &&
5891 (!so_puts(so, pline->line) || !so_puts(so, NEWLINE)))
5892 goto io_err;
5896 /* Now write out all the variables not in the .pinerc */
5897 for(var = ps->vars; var->name != NULL; var++){
5898 if(!var->is_user || var->been_written || !var->is_used ||
5899 var->is_obsolete || (var->is_onlymain && which != Main))
5900 continue;
5902 if(var->is_list)
5903 lval = LVAL(var, which);
5904 else
5905 pval = PVAL(var, which);
5908 * set description to NULL to eliminate preceding
5909 * blank and comment line.
5911 if(prc->type == Loc && var->descrip && *var->descrip &&
5912 (!so_puts(so, NEWLINE) || !so_puts(so, "# ") ||
5913 !so_puts(so, native_nl(var->descrip)) || !so_puts(so, NEWLINE)))
5914 goto io_err;
5916 /* variable is not set */
5917 /** Don't know what the global_val thing is for. SH, Mar 00 **/
5918 if((var->is_list && (!lval || (!lval[0] && !var->global_val.l))) ||
5919 (!var->is_list && !pval)){
5920 /* leave null variables out of remote pinerc */
5921 if(prc->type == Loc &&
5922 (!so_puts(so, var->name) || !so_puts(so, "=") ||
5923 !so_puts(so, NEWLINE)))
5924 goto io_err;
5926 /* var is set to empty string */
5927 else if((var->is_list && (!lval[0] || !lval[0][0]))
5928 || (!var->is_list && pval[0] == '\0')){
5929 if(!so_puts(so, var->name) || !so_puts(so, "=") ||
5930 !so_puts(so, quotes) || !so_puts(so, NEWLINE))
5931 goto io_err;
5933 else if(var->is_list){
5934 int i = 0;
5936 for(i = 0; lval[i] ; i++){
5937 if(strlen(var->name)
5938 + (lval[i][0] ? strlen(lval[i]) : 5) > buflen){
5939 buflen = strlen(var->name)
5940 + (lval[i][0] ? strlen(lval[i]) : 5);
5941 fs_resize((void **)&linep, (buflen+1)*sizeof(char));
5942 fs_resize((void **)&lineq, (buflen+1)*sizeof(char));
5944 snprintf(linep, buflen+1, "%s%s%s%s%s",
5945 (i) ? "\t" : var->name,
5946 (i) ? "" : "=",
5947 lval[i],
5948 lval[i+1] ? "," : "", NEWLINE);
5949 linep[buflen] = '\0';
5950 if(!so_puts(so, bc ? backcompat_convert_from_utf8(&lineq, buflen+1, linep) : linep))
5951 goto io_err;
5954 else{
5955 char *pconverted;
5957 if(strlen(pval) > buflen){
5958 buflen = strlen(pval) + 1;
5959 fs_resize((void **)&linep, (buflen+1)*sizeof(char));
5960 fs_resize((void **)&lineq, (buflen+1)*sizeof(char));
5962 pconverted = bc ? backcompat_convert_from_utf8(&lineq, buflen+1, pval) : pval;
5964 if(!so_puts(so, var->name) || !so_puts(so, "=") ||
5965 !so_puts(so, pconverted) || !so_puts(so, NEWLINE))
5966 goto io_err;
5970 if(!(rd && rd->flags & NO_FILE)){
5971 char *realfilename;
5972 int realfilename_malloced;
5974 if(so_give(&so)) goto io_err;
5976 #ifndef _WINDOWS
5977 realfilename = fs_get(MAXPATH+1);
5978 if(realfilename != NULL){
5979 if(realpath(filename, realfilename) == NULL)
5980 fs_give((void **) &realfilename);
5981 realfilename_malloced = realfilename != NULL ? 1 : 0;
5983 else
5984 realfilename_malloced = 0;
5985 if (realfilename_malloced == 0){
5986 if(our_stat(filename, &sbuf) < 0 && errno == ENOENT){
5987 realfilename = filename;
5988 realfilename_malloced = 0;
5990 else
5991 goto io_err;
5993 #else
5994 realfilename = filename;
5995 realfilename_malloced = 0;
5996 #endif /* _WINDOWS */
5997 if(realfilename != NULL){
5998 int r;
5999 file_attrib_copy(tmp, realfilename);
6000 r = rename_file(tmp, realfilename);
6001 if(realfilename_malloced != 0)
6002 fs_give((void **) &realfilename);
6003 if(r < 0) goto io_err;
6007 if(prc->type != Loc){
6008 int e, we_cancel;
6009 char datebuf[200];
6011 datebuf[0] = '\0';
6012 we_cancel = 0;
6014 if(!(flags & WRP_NOUSER))
6015 we_cancel = busy_cue(_("Copying to remote config"), NULL, 1);
6017 if((e = rd_update_remote(rd, datebuf)) != 0){
6018 dprint((1,
6019 "write_pinerc: error copying from %s to %s\n",
6020 rd->lf ? rd->lf : "<memory>", rd->rn ? rd->rn : "?"));
6021 if(!(flags & WRP_NOUSER)){
6022 q_status_message2(SM_ORDER | SM_DING, 3, 5,
6023 _("Error copying to %.200s: %.200s"),
6024 rd->rn, error_description(errno));
6026 q_status_message(SM_ORDER | SM_DING, 5, 5,
6027 _("Copy of config to remote folder failed, changes NOT saved remotely"));
6030 else{
6031 rd_update_metadata(rd, datebuf);
6032 rd->read_status = 'W';
6033 rd_trim_remdata(&rd);
6034 rd_close_remote(rd);
6037 if(we_cancel)
6038 cancel_busy_cue(-1);
6041 prc->outstanding_pinerc_changes = 0;
6043 if(prc->type == Loc){
6044 prc->pinerc_written = name_file_mtime(filename);
6045 dprint((2, "wrote pinerc: %s: time_pinerc_written = %ld\n",
6046 pinrc ? pinrc : "?", (long) prc->pinerc_written));
6048 else{
6049 dprint((2, "wrote pinerc: %s\n", pinrc ? pinrc : "?"));
6052 if(tmp){
6053 our_unlink(tmp);
6054 fs_give((void **)&tmp);
6057 if(linep) fs_give((void **)&linep);
6058 if(lineq) fs_give((void **)&lineq);
6060 return(0);
6062 io_err:
6063 if(!(flags & WRP_NOUSER))
6064 q_status_message2(SM_ORDER | SM_DING, 3, 5,
6065 _("Error saving configuration in \"%.200s\": %.200s"),
6066 pinrc, error_description(errno));
6068 dprint((1, "Error writing %s : %s\n", pinrc ? pinrc : "?",
6069 error_description(errno)));
6070 if(rd)
6071 rd->flags &= ~DO_REMTRIM;
6072 if(tmp){
6073 our_unlink(tmp);
6074 fs_give((void **)&tmp);
6077 if(linep) fs_give((void **)&linep);
6078 if(lineq) fs_give((void **)&lineq);
6080 return(-1);
6085 * The srcstr is UTF-8. In order to help the user with
6086 * running this pine and an old pre-alpine pine on the same config
6087 * file we attempt to convert the values of the config variables
6088 * to the user's character set before writing.
6089 * parameters: char **buf. Memory of size_t buflen allocated by caller.
6091 char *
6092 backcompat_convert_from_utf8(char **buf, size_t buflen, char *srcstr)
6094 char *converted = NULL;
6095 char *p;
6096 int its_ascii = 1;
6099 for(p = srcstr; *p && its_ascii; p++)
6100 if(*p & 0x80)
6101 its_ascii = 0;
6103 /* if it is ascii, go with that */
6104 if(its_ascii){
6105 strncpy(*buf, srcstr, buflen);
6106 converted = *buf;
6107 (*buf)[buflen-1] = '\0';
6109 else{
6110 char *trythischarset = NULL;
6113 * If it is possible to translate the UTF-8
6114 * string into the user's character set then
6115 * do that. For backwards compatibility with
6116 * old pines.
6118 if(ps_global->keyboard_charmap && ps_global->keyboard_charmap[0])
6119 trythischarset = ps_global->keyboard_charmap;
6120 else if(ps_global->display_charmap && ps_global->display_charmap[0])
6121 trythischarset = ps_global->display_charmap;
6123 if(trythischarset){
6124 SIZEDTEXT src, dst;
6126 src.data = (unsigned char *) srcstr;
6127 src.size = strlen(srcstr);
6128 memset(&dst, 0, sizeof(dst));
6129 if(utf8_cstext(&src, trythischarset, &dst, 0)){
6130 if(dst.data){
6131 strncpy(*buf, (char *) dst.data, buflen);
6132 (*buf)[buflen-1] = '\0';
6133 fs_give((void **) &dst.data);
6138 if(!converted){
6139 strncpy(*buf, srcstr, buflen);
6140 (*buf)[buflen-1] = '\0';
6141 converted = *buf;
6145 return(converted);
6150 * Given a unix-style source string which may contain LFs,
6151 * convert those to CRLFs if appropriate.
6153 * Returns a pointer to the converted string. This will be a string
6154 * stored in tmp_20k_buf.
6156 * This is just used for the variable descriptions in the pinerc file. It
6157 * could certainly be fancier. It simply converts all \n to NEWLINE.
6159 char *
6160 native_nl(char *src)
6162 char *q, *p;
6164 tmp_20k_buf[0] = '\0';
6166 if(src){
6167 for(q = (char *)tmp_20k_buf; *src; src++){
6168 if(*src == '\n'){
6169 for(p = NEWLINE; *p; p++)
6170 *q++ = *p;
6172 else
6173 *q++ = *src;
6176 *q = '\0';
6179 return((char *)tmp_20k_buf);
6183 void
6184 quit_to_edit_msg(PINERC_S *prc)
6186 /* TRANSLATORS: The %s is either "Postload " or nothing. A Postload config file
6187 is a type of config file. */
6188 q_status_message1(SM_ORDER, 3, 4, _("Must quit Alpine to change %sconfig file."),
6189 (prc == ps_global->post_prc) ? "Postload " : "");
6193 /*------------------------------------------------------------
6194 Return TRUE if the given string was a feature name present in the
6195 pinerc as it was when pine was started...
6196 ----*/
6198 var_in_pinerc(char *s)
6200 PINERC_LINE *pline;
6202 for(pline = ps_global->prc ? ps_global->prc->pinerc_lines : NULL;
6203 pline && (pline->var || pline->line); pline++)
6204 if(pline->var && pline->var->name && !strucmp(s, pline->var->name))
6205 return(1);
6207 for(pline = ps_global->post_prc ? ps_global->post_prc->pinerc_lines : NULL;
6208 pline && (pline->var || pline->line); pline++)
6209 if(pline->var && pline->var->name && !strucmp(s, pline->var->name))
6210 return(1);
6212 return(0);
6216 /*------------------------------------------------------------
6217 Free resources associated with pinerc_lines data
6218 ----*/
6219 void
6220 free_pinerc_lines(PINERC_LINE **pinerc_lines)
6222 PINERC_LINE *pline;
6224 if(pinerc_lines && *pinerc_lines){
6225 for(pline = *pinerc_lines; pline->var || pline->line; pline++)
6226 if(pline->line)
6227 fs_give((void **)&pline->line);
6229 fs_give((void **)pinerc_lines);
6234 /*------------------------------------------------------------
6235 Dump out a global pine.conf on the standard output with fresh
6236 comments. Preserves variables currently set in SYSTEM_PINERC, if any.
6237 ----*/
6238 void
6239 dump_global_conf(void)
6241 FILE *f;
6242 struct variable *var;
6243 PINERC_S *prc;
6245 prc = new_pinerc_s(SYSTEM_PINERC);
6246 read_pinerc(prc, variables, ParseGlobal);
6247 if(prc)
6248 free_pinerc_s(&prc);
6250 f = stdout;
6251 if(f == NULL)
6252 goto io_err;
6254 fprintf(f, "# %s -- system wide pine configuration\n#\n",
6255 SYSTEM_PINERC);
6256 fprintf(f, "# Values here affect all pine users unless they've overridden the values\n");
6257 fprintf(f, "# in their .pinerc files. A copy of this file with current comments may\n");
6258 fprintf(f, "# be obtained by running \"pine -conf\". It will be printed to standard output.\n#\n");
6259 fprintf(f,"# For a variable to be unset its value must be null/blank. This is not the\n");
6260 fprintf(f,"# same as the value of \"empty string\", which can be used to effectively\n");
6261 fprintf(f,"# \"unset\" a variable that has a default or previously assigned value.\n");
6262 fprintf(f,"# To set a variable to the empty string its value should be \"\".\n");
6263 fprintf(f,"# Switch variables are set to either \"yes\" or \"no\", and default to \"no\".\n");
6264 fprintf(f,"# Except for feature-list items, which are additive, values set in the\n");
6265 fprintf(f,"# .pinerc file replace those in pine.conf, and those in pine.conf.fixed\n");
6266 fprintf(f,"# over-ride all others. Features can be over-ridden in .pinerc or\n");
6267 fprintf(f,"# pine.conf.fixed by pre-pending the feature name with \"no-\".\n#\n");
6268 fprintf(f,"# (These comments are automatically inserted.)\n");
6270 for(var = variables; var->name != NULL; var++){
6271 if(!var->is_global || !var->is_used || var->is_obsolete)
6272 continue;
6274 if(var->descrip && *var->descrip){
6275 if(fprintf(f, "\n# %s\n", var->descrip) == EOF)
6276 goto io_err;
6279 if(var->is_list){
6280 if(var->global_val.l == NULL){
6281 if(fprintf(f, "%s=\n", var->name) == EOF)
6282 goto io_err;
6283 }else{
6284 int i;
6286 for(i=0; var->global_val.l[i]; i++)
6287 if(fprintf(f, "%s%s%s%s\n", (i) ? "\t" : var->name,
6288 (i) ? "" : "=", var->global_val.l[i],
6289 var->global_val.l[i+1] ? ",":"") == EOF)
6290 goto io_err;
6292 }else{
6293 if(var->global_val.p == NULL){
6294 if(fprintf(f, "%s=\n", var->name) == EOF)
6295 goto io_err;
6296 }else if(strlen(var->global_val.p) == 0){
6297 if(fprintf(f, "%s=\"\"\n", var->name) == EOF)
6298 goto io_err;
6299 }else{
6300 if(fprintf(f,"%s=%s\n",var->name,var->global_val.p) == EOF)
6301 goto io_err;
6305 exit(0);
6308 io_err:
6309 fprintf(stderr, "Error writing config to stdout: %s\n",
6310 error_description(errno));
6311 exit(-1);
6315 /*------------------------------------------------------------
6316 Dump out a pinerc to filename with fresh
6317 comments. Preserves variables currently set in pinerc, if any.
6318 ----*/
6319 void
6320 dump_new_pinerc(char *filename)
6322 FILE *f;
6323 struct variable *var;
6324 char buf[MAXPATH], *p;
6325 PINERC_S *prc;
6328 p = ps_global->pinerc;
6330 #if defined(DOS) || defined(OS2)
6331 if(!ps_global->pinerc){
6332 char *p;
6334 if(p = getenv("PINERC")){
6335 ps_global->pinerc = cpystr(p);
6336 }else{
6337 char buf2[MAXPATH];
6338 build_path(buf2, ps_global->home_dir, DF_PINEDIR, sizeof(buf2));
6339 build_path(buf, buf2, SYSTEM_PINERC, sizeof(buf));
6342 p = buf;
6344 #else /* !DOS */
6345 if(!ps_global->pinerc){
6346 build_path(buf, ps_global->home_dir, ".pinerc", sizeof(buf));
6347 p = buf;
6349 #endif /* !DOS */
6351 prc = new_pinerc_s(p);
6352 read_pinerc(prc, variables, ParsePers);
6353 if(prc)
6354 free_pinerc_s(&prc);
6356 f = NULL;;
6357 if(filename[0] == '\0'){
6358 fprintf(stderr, "Missing argument to \"-pinerc\".\n");
6359 }else if(!strcmp(filename, "-")){
6360 f = stdout;
6361 }else{
6362 f = our_fopen(filename, "wb");
6365 if(f == NULL)
6366 goto io_err;
6368 if(fprintf(f, "%s", cf_text_comment) == EOF)
6369 goto io_err;
6371 for(var = variables; var->name != NULL; var++){
6372 dprint((7,"write_pinerc: %s = %s\n",
6373 var->name ? var->name : "?",
6374 var->main_user_val.p ? var->main_user_val.p : "<not set>"));
6375 if(!var->is_user || !var->is_used || var->is_obsolete)
6376 continue;
6379 * set description to NULL to eliminate preceding
6380 * blank and comment line.
6382 if(var->descrip && *var->descrip){
6383 if(fprintf(f, "\n# %s\n", var->descrip) == EOF)
6384 goto io_err;
6387 if(var->is_list){
6388 if(var->main_user_val.l == NULL){
6389 if(fprintf(f, "%s=\n", var->name) == EOF)
6390 goto io_err;
6391 }else{
6392 int i;
6394 for(i=0; var->main_user_val.l[i]; i++)
6395 if(fprintf(f, "%s%s%s%s\n", (i) ? "\t" : var->name,
6396 (i) ? "" : "=", var->main_user_val.l[i],
6397 var->main_user_val.l[i+1] ? ",":"") == EOF)
6398 goto io_err;
6400 }else{
6401 if(var->main_user_val.p == NULL){
6402 if(fprintf(f, "%s=\n", var->name) == EOF)
6403 goto io_err;
6404 }else if(strlen(var->main_user_val.p) == 0){
6405 if(fprintf(f, "%s=\"\"\n", var->name) == EOF)
6406 goto io_err;
6407 }else{
6408 if(fprintf(f,"%s=%s\n",var->name,var->main_user_val.p) == EOF)
6409 goto io_err;
6413 exit(0);
6416 io_err:
6417 snprintf(buf, sizeof(buf), "Error writing config to %s: %s\n",
6418 filename, error_description(errno));
6419 exceptional_exit(buf, -1);
6423 /*----------------------------------------------------------------------
6424 Set a user variable and save the .pinerc
6426 Args: var -- The index of the variable to set from conftype.h (V_....)
6427 value -- The string to set the value to
6429 Result: -1 is returned on failure and 0 is returned on success
6431 The vars data structure is updated and the pinerc saved.
6432 ----*/
6434 set_variable(int var, char *value, int expand, int commit, EditWhich which)
6436 struct variable *v;
6437 char **apval;
6438 PINERC_S *prc;
6440 v = &ps_global->vars[var];
6442 if(!v->is_user)
6443 panic1("Trying to set non-user variable %s", v->name);
6445 /* Override value of which, at most one of these should be set */
6446 if(v->is_onlymain)
6447 which = Main;
6448 else if(v->is_outermost)
6449 which = ps_global->ew_for_except_vars;
6451 apval = APVAL(v, which);
6453 if(!apval)
6454 return(-1);
6456 if(*apval)
6457 fs_give((void **)apval);
6459 *apval = value ? cpystr(value) : NULL;
6460 set_current_val(v, expand, FALSE);
6462 switch(which){
6463 case Main:
6464 prc = ps_global->prc;
6465 break;
6466 case Post:
6467 prc = ps_global->post_prc;
6468 break;
6469 default:
6470 break;
6473 if(prc)
6474 prc->outstanding_pinerc_changes = 1;
6476 return(commit ? write_pinerc(ps_global, which, WRP_NONE) : 0);
6480 /*----------------------------------------------------------------------
6481 Set a user variable list and save the .pinerc
6483 Args: var -- The index of the variable to set from conftype.h (V_....)
6484 lvalue -- The list to set the value to
6486 Result: -1 is returned on failure and 0 is returned on success
6488 The vars data structure is updated and if write_it, the pinerc is saved.
6489 ----*/
6491 set_variable_list(int var, char **lvalue, int write_it, EditWhich which)
6493 char ***alval;
6494 int i;
6495 struct variable *v = &ps_global->vars[var];
6496 PINERC_S *prc;
6498 if(!v->is_user || !v->is_list)
6499 panic1("BOTCH: Trying to set non-user or non-list variable %s", v->name);
6501 /* Override value of which, at most one of these should be set */
6502 if(v->is_onlymain)
6503 which = Main;
6504 else if(v->is_outermost)
6505 which = ps_global->ew_for_except_vars;
6507 alval = ALVAL(v, which);
6508 if(!alval)
6509 return(-1);
6511 if(*alval)
6512 free_list_array(alval);
6514 if(lvalue){
6515 for(i = 0; lvalue[i] ; i++) /* count elements */
6518 *alval = (char **) fs_get((i+1) * sizeof(char *));
6520 for(i = 0; lvalue[i] ; i++)
6521 (*alval)[i] = cpystr(lvalue[i]);
6523 (*alval)[i] = NULL;
6526 set_current_val(v, TRUE, FALSE);
6528 switch(which){
6529 case Main:
6530 prc = ps_global->prc;
6531 break;
6532 case Post:
6533 prc = ps_global->post_prc;
6534 break;
6535 default:
6536 break;
6539 if(prc)
6540 prc->outstanding_pinerc_changes = 1;
6542 return(write_it ? write_pinerc(ps_global, which, WRP_NONE) : 0);
6546 void
6547 set_current_color_vals(struct pine *ps)
6549 struct variable *vars = ps->vars;
6550 int later_color_is_set = 0;
6552 set_current_val(&vars[V_NORM_FORE_COLOR], TRUE, TRUE);
6553 set_current_val(&vars[V_NORM_BACK_COLOR], TRUE, TRUE);
6554 pico_nfcolor(VAR_NORM_FORE_COLOR);
6555 pico_nbcolor(VAR_NORM_BACK_COLOR);
6557 set_current_val(&vars[V_REV_FORE_COLOR], TRUE, TRUE);
6558 set_current_val(&vars[V_REV_BACK_COLOR], TRUE, TRUE);
6559 pico_rfcolor(VAR_REV_FORE_COLOR);
6560 pico_rbcolor(VAR_REV_BACK_COLOR);
6562 set_color_val(&vars[V_TITLE_FORE_COLOR], 1);
6563 set_color_val(&vars[V_TITLECLOSED_FORE_COLOR], 0);
6564 set_color_val(&vars[V_FOLDER_FORE_COLOR], 0);
6565 set_color_val(&vars[V_DIRECTORY_FORE_COLOR], 0);
6566 set_color_val(&vars[V_FOLDER_LIST_FORE_COLOR], 0);
6567 set_color_val(&vars[V_STATUS_FORE_COLOR], 1);
6568 set_color_val(&vars[V_KEYLABEL_FORE_COLOR], 1);
6569 set_color_val(&vars[V_KEYNAME_FORE_COLOR], 1);
6570 set_color_val(&vars[V_SLCTBL_FORE_COLOR], 1);
6571 set_color_val(&vars[V_METAMSG_FORE_COLOR], 1);
6572 set_color_val(&vars[V_PROMPT_FORE_COLOR], 1);
6573 set_color_val(&vars[V_HEADER_GENERAL_FORE_COLOR], 1);
6574 set_color_val(&vars[V_IND_PLUS_FORE_COLOR], 0);
6575 set_color_val(&vars[V_IND_IMP_FORE_COLOR], 0);
6576 set_color_val(&vars[V_IND_DEL_FORE_COLOR], 0);
6577 set_color_val(&vars[V_IND_HIPRI_FORE_COLOR], 0);
6578 set_color_val(&vars[V_IND_LOPRI_FORE_COLOR], 0);
6579 set_color_val(&vars[V_IND_ANS_FORE_COLOR], 0);
6580 set_color_val(&vars[V_IND_NEW_FORE_COLOR], 0);
6581 set_color_val(&vars[V_IND_REC_FORE_COLOR], 0);
6582 set_color_val(&vars[V_IND_FWD_FORE_COLOR], 0);
6583 set_color_val(&vars[V_IND_UNS_FORE_COLOR], 0);
6584 set_color_val(&vars[V_IND_ARR_FORE_COLOR], 0);
6585 set_color_val(&vars[V_IND_SUBJ_FORE_COLOR], 0);
6586 set_color_val(&vars[V_IND_FROM_FORE_COLOR], 0);
6587 set_color_val(&vars[V_IND_OP_FORE_COLOR], 0);
6588 set_color_val(&vars[V_INCUNSEEN_FORE_COLOR], 0);
6589 set_color_val(&vars[V_SIGNATURE_FORE_COLOR], 0);
6591 set_current_val(&ps->vars[V_INDEX_TOKEN_COLORS], TRUE, TRUE);
6592 set_current_val(&ps->vars[V_VIEW_HDR_COLORS], TRUE, TRUE);
6593 set_current_val(&ps->vars[V_KW_COLORS], TRUE, TRUE);
6594 set_custom_spec_colors(ps);
6597 * Set up the quoting colors. If a later color is set but not an earlier
6598 * color we set the earlier color to Normal to make it easier when
6599 * we go to use the colors. However, if the only quote colors set are
6600 * Normal that is the same as no settings, so delete them.
6602 set_color_val(&vars[V_QUOTE1_FORE_COLOR], 0);
6603 set_color_val(&vars[V_QUOTE2_FORE_COLOR], 0);
6604 set_color_val(&vars[V_QUOTE3_FORE_COLOR], 0);
6606 if((!(VAR_QUOTE3_FORE_COLOR && VAR_QUOTE3_BACK_COLOR) ||
6607 (!strucmp(VAR_QUOTE3_FORE_COLOR, VAR_NORM_FORE_COLOR) &&
6608 !strucmp(VAR_QUOTE3_BACK_COLOR, VAR_NORM_BACK_COLOR))) &&
6609 (!(VAR_QUOTE2_FORE_COLOR && VAR_QUOTE2_BACK_COLOR) ||
6610 (!strucmp(VAR_QUOTE2_FORE_COLOR, VAR_NORM_FORE_COLOR) &&
6611 !strucmp(VAR_QUOTE2_BACK_COLOR, VAR_NORM_BACK_COLOR))) &&
6612 (!(VAR_QUOTE1_FORE_COLOR && VAR_QUOTE1_BACK_COLOR) ||
6613 (!strucmp(VAR_QUOTE1_FORE_COLOR, VAR_NORM_FORE_COLOR) &&
6614 !strucmp(VAR_QUOTE1_BACK_COLOR, VAR_NORM_BACK_COLOR)))){
6616 * They are all either Normal or not set. Delete them all.
6618 if(VAR_QUOTE3_FORE_COLOR)
6619 fs_give((void **)&VAR_QUOTE3_FORE_COLOR);
6620 if(VAR_QUOTE3_BACK_COLOR)
6621 fs_give((void **)&VAR_QUOTE3_BACK_COLOR);
6622 if(VAR_QUOTE2_FORE_COLOR)
6623 fs_give((void **)&VAR_QUOTE2_FORE_COLOR);
6624 if(VAR_QUOTE2_BACK_COLOR)
6625 fs_give((void **)&VAR_QUOTE2_BACK_COLOR);
6626 if(VAR_QUOTE1_FORE_COLOR)
6627 fs_give((void **)&VAR_QUOTE1_FORE_COLOR);
6628 if(VAR_QUOTE1_BACK_COLOR)
6629 fs_give((void **)&VAR_QUOTE1_BACK_COLOR);
6631 else{ /* something is non-Normal */
6632 if(VAR_QUOTE3_FORE_COLOR && VAR_QUOTE3_BACK_COLOR)
6633 later_color_is_set++;
6635 /* if 3 is set but not 2, set 2 to Normal */
6636 if(VAR_QUOTE2_FORE_COLOR && VAR_QUOTE2_BACK_COLOR)
6637 later_color_is_set++;
6638 else if(later_color_is_set)
6639 set_color_val(&vars[V_QUOTE2_FORE_COLOR], 1);
6641 /* if 3 or 2 is set but not 1, set 1 to Normal */
6642 if(VAR_QUOTE1_FORE_COLOR && VAR_QUOTE1_BACK_COLOR)
6643 later_color_is_set++;
6644 else if(later_color_is_set)
6645 set_color_val(&vars[V_QUOTE1_FORE_COLOR], 1);
6648 #ifdef _WINDOWS
6649 if(ps->pre441){
6650 int conv_main = 0, conv_post = 0;
6652 ps->pre441 = 0;
6653 if(ps->prc && !unix_color_style_in_pinerc(ps->prc)){
6654 conv_main = convert_pc_gray_names(ps, ps->prc, Main);
6655 if(conv_main)
6656 ps->prc->outstanding_pinerc_changes = 1;
6660 if(ps->post_prc && !unix_color_style_in_pinerc(ps->post_prc)){
6661 conv_post = convert_pc_gray_names(ps, ps->post_prc, Post);
6662 if(conv_post)
6663 ps->post_prc->outstanding_pinerc_changes = 1;
6666 if(conv_main || conv_post){
6667 if(conv_main)
6668 write_pinerc(ps, Main, WRP_NONE);
6670 if(conv_post)
6671 write_pinerc(ps, Post, WRP_NONE);
6673 set_current_color_vals(ps);
6676 #endif /* _WINDOWS */
6678 pico_set_normal_color();
6683 * Set current_val for the foreground and background color vars, which
6684 * are assumed to be in order. If a set_current_val on them doesn't
6685 * produce current_vals, then use the colors from defvar to set those
6686 * current_vals.
6688 void
6689 set_color_val(struct variable *v, int use_default)
6691 set_current_val(v, TRUE, TRUE);
6692 set_current_val(v+1, TRUE, TRUE);
6694 if(!(v->current_val.p && v->current_val.p[0] &&
6695 (v+1)->current_val.p && (v+1)->current_val.p[0])){
6696 struct variable *defvar;
6698 if(v->current_val.p)
6699 fs_give((void **)&v->current_val.p);
6700 if((v+1)->current_val.p)
6701 fs_give((void **)&(v+1)->current_val.p);
6703 if(!use_default)
6704 return;
6706 if(var_defaults_to_rev(v))
6707 defvar = &ps_global->vars[V_REV_FORE_COLOR];
6708 else
6709 defvar = &ps_global->vars[V_NORM_FORE_COLOR];
6711 /* use default vars values instead */
6712 if(defvar && defvar->current_val.p && defvar->current_val.p[0] &&
6713 (defvar+1)->current_val.p && (defvar+1)->current_val.p[0]){
6714 v->current_val.p = cpystr(defvar->current_val.p);
6715 (v+1)->current_val.p = cpystr((defvar+1)->current_val.p);
6722 var_defaults_to_rev(struct variable *v)
6724 return(v == &ps_global->vars[V_REV_FORE_COLOR] ||
6725 v == &ps_global->vars[V_TITLE_FORE_COLOR] ||
6726 v == &ps_global->vars[V_STATUS_FORE_COLOR] ||
6727 v == &ps_global->vars[V_KEYNAME_FORE_COLOR] ||
6728 v == &ps_global->vars[V_PROMPT_FORE_COLOR]);
6734 * Each item in the list looks like:
6736 * /HDR=<header>/FG=<foreground color>/BG=<background color>
6738 * We separate the three pieces into an array of structures to make
6739 * it easier to deal with later.
6741 void
6742 set_custom_spec_colors(struct pine *ps)
6744 if(ps->index_token_colors)
6745 free_spec_colors(&ps->index_token_colors);
6747 ps->index_token_colors = spec_colors_from_varlist(ps->VAR_INDEX_TOKEN_COLORS, 1);
6749 if(ps->hdr_colors)
6750 free_spec_colors(&ps->hdr_colors);
6752 ps->hdr_colors = spec_colors_from_varlist(ps->VAR_VIEW_HDR_COLORS, 1);
6754 /* fit keyword colors into the same structures for code re-use */
6755 if(ps->kw_colors)
6756 free_spec_colors(&ps->kw_colors);
6758 ps->kw_colors = spec_colors_from_varlist(ps->VAR_KW_COLORS, 1);
6763 * Input is one item from config variable.
6765 * Return value must be freed by caller. The return is a single SPEC_COLOR_S,
6766 * not a list.
6768 SPEC_COLOR_S *
6769 spec_color_from_var(char *t, int already_expanded)
6771 char *p, *spec, *fg, *bg;
6772 PATTERN_S *val;
6773 SPEC_COLOR_S *new_hcolor = NULL;
6775 if(t && t[0] && !strcmp(t, INHERIT)){
6776 new_hcolor = (SPEC_COLOR_S *)fs_get(sizeof(*new_hcolor));
6777 memset((void *)new_hcolor, 0, sizeof(*new_hcolor));
6778 new_hcolor->inherit = 1;
6780 else if(t && t[0]){
6781 char tbuf[10000];
6783 if(!already_expanded){
6784 tbuf[0] = '\0';
6785 if(expand_variables(tbuf, sizeof(tbuf), t, 0))
6786 t = tbuf;
6789 spec = fg = bg = NULL;
6790 val = NULL;
6791 if((p = srchstr(t, "/HDR=")) != NULL)
6792 spec = remove_backslash_escapes(p+5);
6793 if((p = srchstr(t, "/FG=")) != NULL)
6794 fg = remove_backslash_escapes(p+4);
6795 if((p = srchstr(t, "/BG=")) != NULL)
6796 bg = remove_backslash_escapes(p+4);
6797 val = parse_pattern("VAL", t, 0);
6799 if(spec && *spec){
6800 /* remove colons */
6801 if((p = strindex(spec, ':')) != NULL)
6802 *p = '\0';
6804 new_hcolor = (SPEC_COLOR_S *)fs_get(sizeof(*new_hcolor));
6805 memset((void *)new_hcolor, 0, sizeof(*new_hcolor));
6806 new_hcolor->spec = spec;
6807 new_hcolor->fg = fg;
6808 new_hcolor->bg = bg;
6809 new_hcolor->val = val;
6811 else{
6812 if(spec)
6813 fs_give((void **)&spec);
6814 if(fg)
6815 fs_give((void **)&fg);
6816 if(bg)
6817 fs_give((void **)&bg);
6818 if(val)
6819 free_pattern(&val);
6823 return(new_hcolor);
6828 * Input is a list from config file.
6830 * Return value may be a list of SPEC_COLOR_S and must be freed by caller.
6832 SPEC_COLOR_S *
6833 spec_colors_from_varlist(char **varlist, int already_expanded)
6835 char **s, *t;
6836 SPEC_COLOR_S *new_hc = NULL;
6837 SPEC_COLOR_S *new_hcolor, **nexthc;
6839 nexthc = &new_hc;
6840 if(varlist){
6841 for(s = varlist; (t = *s) != NULL; s++){
6842 if(t[0]){
6843 new_hcolor = spec_color_from_var(t, already_expanded);
6844 if(new_hcolor){
6845 *nexthc = new_hcolor;
6846 nexthc = &new_hcolor->next;
6852 return(new_hc);
6857 * Returns allocated charstar suitable for config var for a single
6858 * SPEC_COLOR_S.
6860 char *
6861 var_from_spec_color(SPEC_COLOR_S *hc)
6863 char *ret_val = NULL;
6864 char *p, *spec = NULL, *fg = NULL, *bg = NULL, *val = NULL;
6865 size_t len;
6867 if(hc && hc->inherit)
6868 ret_val = cpystr(INHERIT);
6869 else if(hc){
6870 if(hc->spec)
6871 spec = add_viewerhdr_escapes(hc->spec);
6872 if(hc->fg)
6873 fg = add_viewerhdr_escapes(hc->fg);
6874 if(hc->bg)
6875 bg = add_viewerhdr_escapes(hc->bg);
6876 if(hc->val){
6877 p = pattern_to_string(hc->val);
6878 if(p){
6879 val = add_viewerhdr_escapes(p);
6880 fs_give((void **)&p);
6884 len = strlen("/HDR=/FG=/BG=") + strlen(spec ? spec : "") +
6885 strlen(fg ? fg : "") + strlen(bg ? bg : "") +
6886 strlen(val ? "/VAL=" : "") + strlen(val ? val : "");
6887 ret_val = (char *) fs_get(len + 1);
6888 snprintf(ret_val, len+1, "/HDR=%s/FG=%s/BG=%s%s%s",
6889 spec ? spec : "", fg ? fg : "", bg ? bg : "",
6890 val ? "/VAL=" : "", val ? val : "");
6892 if(spec)
6893 fs_give((void **)&spec);
6894 if(fg)
6895 fs_give((void **)&fg);
6896 if(bg)
6897 fs_give((void **)&bg);
6898 if(val)
6899 fs_give((void **)&val);
6902 return(ret_val);
6907 * Returns allocated charstar suitable for config var for a single
6908 * SPEC_COLOR_S.
6910 char **
6911 varlist_from_spec_colors(SPEC_COLOR_S *hcolors)
6913 SPEC_COLOR_S *hc;
6914 char **ret_val = NULL;
6915 int i;
6917 /* count how many */
6918 for(hc = hcolors, i = 0; hc; hc = hc->next, i++)
6921 ret_val = (char **)fs_get((i+1) * sizeof(*ret_val));
6922 memset((void *)ret_val, 0, (i+1) * sizeof(*ret_val));
6923 for(hc = hcolors, i = 0; hc; hc = hc->next, i++)
6924 ret_val[i] = var_from_spec_color(hc);
6926 return(ret_val);
6930 void
6931 update_posting_charset(struct pine *ps, int revert)
6933 #ifndef _WINDOWS
6934 if(F_ON(F_USE_SYSTEM_TRANS, ps)){
6935 if(!revert)
6936 q_status_message(SM_ORDER, 5, 5, _("This change has no effect because feature Use-System-Translation is on"));
6938 else{
6939 #endif /* ! _WINDOWS */
6940 if(ps->posting_charmap)
6941 fs_give((void **) &ps->posting_charmap);
6943 if(ps->VAR_POST_CHAR_SET){
6944 ps->posting_charmap = cpystr(ps->VAR_POST_CHAR_SET);
6945 if(!posting_charset_is_supported(ps->posting_charmap)){
6946 snprintf(tmp_20k_buf, SIZEOF_20KBUF,
6947 _("Posting-Character set \"%s\" is unsupported, using UTF-8"),
6948 ps->posting_charmap);
6949 q_status_message(SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
6950 fs_give((void **) &ps->posting_charmap);
6951 ps->posting_charmap = cpystr("UTF-8");
6954 else
6955 ps->posting_charmap = cpystr("UTF-8");
6956 #ifndef _WINDOWS
6958 #endif /* ! _WINDOWS */
6962 #define FIXED_COMMENT _("(fixed)")
6963 #define DEFAULT_COMMENT _("(default)")
6964 #define OVERRIDE_COMMENT _("(overridden)")
6967 feature_gets_an_x(struct pine *ps, struct variable *var, FEATURE_S *feature,
6968 char **comment, EditWhich ew)
6970 char **lval, **lvalexc, **lvalnorm;
6971 char *def = DEFAULT_COMMENT;
6972 int j, done = 0;
6973 int feature_fixed_on = 0, feature_fixed_off = 0;
6975 if(comment)
6976 *comment = NULL;
6978 lval = LVAL(var, ew);
6979 lvalexc = LVAL(var, ps->ew_for_except_vars);
6980 lvalnorm = LVAL(var, Main);
6982 /* feature value is administratively fixed */
6983 if((j = feature_in_list(var->fixed_val.l, feature->name)) != 0){
6984 if(j == 1)
6985 feature_fixed_on++;
6986 else if(j == -1)
6987 feature_fixed_off++;
6989 done++;
6990 if(comment)
6991 *comment = FIXED_COMMENT;
6995 * We have an exceptions config setting which overrides anything
6996 * we do here, in the normal config.
6998 if(!done &&
6999 ps->ew_for_except_vars != Main && ew == Main &&
7000 feature_in_list(lvalexc, feature->name)){
7001 done++;
7002 if(comment)
7003 *comment = OVERRIDE_COMMENT;
7007 * Feature is set On in default but not set here.
7009 if(!done &&
7010 !feature_in_list(lval, feature->name) &&
7011 ((feature_in_list(var->global_val.l, feature->name) == 1) ||
7012 ((ps->ew_for_except_vars != Main &&
7013 ew == ps->ew_for_except_vars &&
7014 feature_in_list(lvalnorm, feature->name) == 1)))){
7015 done = 17;
7016 if(comment)
7017 *comment = def;
7020 if(!done &&
7021 feature->defval &&
7022 !feature_in_list(lval, feature->name) &&
7023 !feature_in_list(var->global_val.l, feature->name) &&
7024 (ps->ew_for_except_vars == Main ||
7025 ew != ps->ew_for_except_vars ||
7026 !feature_in_list(lvalnorm, feature->name))){
7027 done = 17;
7028 if(comment)
7029 *comment = def;
7032 return(feature_fixed_on ||
7033 (!feature_fixed_off &&
7034 (done == 17 ||
7035 test_feature(lval, feature->name,
7036 test_old_growth_bits(ps, feature->id)))));
7041 longest_feature_comment(struct pine *ps, EditWhich ew)
7043 int lc = 0;
7045 lc = MAX(lc, utf8_width(FIXED_COMMENT));
7046 lc = MAX(lc, utf8_width(DEFAULT_COMMENT));
7047 if(ps->ew_for_except_vars != Main && ew == Main)
7048 lc = MAX(lc, utf8_width(OVERRIDE_COMMENT));
7050 return(lc);
7054 void
7055 toggle_feature(struct pine *ps, struct variable *var, FEATURE_S *f,
7056 int just_flip_value, EditWhich ew)
7058 char **vp, *p, **lval, ***alval;
7059 int og, on_before, was_set;
7060 char *err;
7061 long l;
7063 og = test_old_growth_bits(ps, f->id);
7066 * if this feature is in the fixed set, or old-growth is in the fixed
7067 * set and this feature is in the old-growth set, don't alter it...
7069 for(vp = var->fixed_val.l; vp && *vp; vp++){
7070 p = (struncmp(*vp, "no-", 3)) ? *vp : *vp + 3;
7071 if(!strucmp(p, f->name) || (og && !strucmp(p, "old-growth"))){
7072 q_status_message(SM_ORDER, 3, 3,
7073 /* TRANSLATORS: In the configuration screen, telling the user we
7074 can't change this option because the system administrator
7075 prohibits it. */
7076 _("Can't change value fixed by sys-admin."));
7077 return;
7081 on_before = F_ON(f->id, ps);
7083 lval = LVAL(var, ew);
7084 alval = ALVAL(var, ew);
7085 if(just_flip_value)
7086 was_set = test_feature(lval, f->name, og);
7087 else
7088 was_set = feature_gets_an_x(ps, var, f, NULL, ew);
7090 if(alval)
7091 set_feature(alval, f->name, !was_set);
7093 set_feature_list_current_val(var);
7094 process_feature_list(ps, var->current_val.l, 0, 0, 0);
7097 * Handle any features that need special attention here...
7099 if(on_before != F_ON(f->id, ps))
7100 switch(f->id){
7101 case F_QUOTE_ALL_FROMS :
7102 mail_parameters(NULL,SET_FROMWIDGET,F_ON(f->id,ps) ? VOIDT : NIL);
7103 break;
7105 case F_FAKE_NEW_IN_NEWS :
7106 if(IS_NEWS(ps->mail_stream))
7107 q_status_message(SM_ORDER | SM_DING, 3, 4,
7108 "news-approximates-new-status won't affect current newsgroup until next open");
7110 break;
7112 case F_COLOR_LINE_IMPORTANT :
7113 case F_DATES_TO_LOCAL :
7114 clear_index_cache(ps->mail_stream, 0);
7115 break;
7117 case F_DISABLE_INDEX_LOCALE_DATES :
7118 reset_index_format();
7119 clear_index_cache(ps->mail_stream, 0);
7120 break;
7122 case F_MARK_FOR_CC :
7123 clear_index_cache(ps->mail_stream, 0);
7124 if(THREADING() && sp_viewing_a_thread(ps->mail_stream))
7125 unview_thread(ps, ps->mail_stream, ps->msgmap);
7127 break;
7129 case F_HIDE_NNTP_PATH :
7130 mail_parameters(NULL, SET_NNTPHIDEPATH,
7131 F_ON(f->id, ps) ? VOIDT : NIL);
7132 break;
7134 case F_MAILDROPS_PRESERVE_STATE :
7135 mail_parameters(NULL, SET_SNARFPRESERVE,
7136 F_ON(f->id, ps) ? VOIDT : NIL);
7137 break;
7139 case F_DISABLE_SHARED_NAMESPACES :
7140 mail_parameters(NULL, SET_DISABLEAUTOSHAREDNS,
7141 F_ON(f->id, ps) ? VOIDT : NIL);
7142 break;
7144 case F_QUELL_LOCK_FAILURE_MSGS :
7145 mail_parameters(NULL, SET_LOCKEACCESERROR,
7146 F_ON(f->id, ps) ? VOIDT : NIL);
7147 break;
7149 case F_MULNEWSRC_HOSTNAMES_AS_TYPED :
7150 l = F_ON(f->id, ps) ? 0L : 1L;
7151 mail_parameters(NULL, SET_NEWSRCCANONHOST, (void *) l);
7152 break;
7154 case F_QUELL_INTERNAL_MSG :
7155 mail_parameters(NULL, SET_USERHASNOLIFE,
7156 F_ON(f->id, ps) ? VOIDT : NIL);
7157 break;
7159 case F_DISABLE_SETLOCALE_COLLATE :
7160 set_collation(F_OFF(F_DISABLE_SETLOCALE_COLLATE, ps), 1);
7161 break;
7163 #ifndef _WINDOWS
7164 case F_USE_SYSTEM_TRANS :
7165 err = NULL;
7166 reset_character_set_stuff(&err);
7167 if(err){
7168 q_status_message(SM_ORDER | SM_DING, 3, 4, err);
7169 fs_give((void **) &err);
7172 break;
7173 #endif /* ! _WINDOWS */
7175 case F_ENABLE_INCOMING_CHECKING :
7176 if(!on_before && F_OFF(F_ENABLE_INCOMING, ps))
7177 q_status_message(SM_ORDER, 0, 3, _("This option has no effect without Enable-Incoming-Folders"));
7179 clear_incoming_valid_bits();
7180 break;
7182 case F_INCOMING_CHECKING_TOTAL :
7183 case F_INCOMING_CHECKING_RECENT :
7184 if(!on_before && F_OFF(F_ENABLE_INCOMING_CHECKING, ps))
7185 q_status_message(SM_ORDER, 0, 3, _("This option has no effect without Enable-Incoming-Folders-Checking"));
7187 clear_incoming_valid_bits();
7188 break;
7190 case F_THREAD_SORTS_BY_ARRIVAL :
7191 clear_index_cache(ps->mail_stream, 0);
7192 refresh_sort(ps->mail_stream, sp_msgmap(ps->mail_stream), SRT_NON);
7193 break;
7195 #ifdef SMIME
7196 case F_DONT_DO_SMIME :
7197 smime_deinit();
7198 break;
7200 #ifdef APPLEKEYCHAIN
7201 case F_PUBLICCERTS_IN_KEYCHAIN :
7202 smime_deinit();
7203 break;
7204 #endif
7205 #endif
7207 default :
7208 break;
7214 * Returns 1 -- Feature is in the list and positive
7215 * 0 -- Feature is not in the list at all
7216 * -1 -- Feature is in the list and negative (no-)
7219 feature_in_list(char **l, char *f)
7221 char *p;
7222 int rv = 0, forced_off;
7224 for(; l && *l; l++){
7225 p = (forced_off = !struncmp(*l, "no-", 3)) ? *l + 3 : *l;
7226 if(!strucmp(p, f))
7227 rv = forced_off ? -1 : 1;
7230 return(rv);
7235 * test_feature - runs thru a feature list, and returns:
7236 * 1 if feature explicitly set and matches 'v'
7237 * 0 if feature not explicitly set *or* doesn't match 'v'
7240 test_feature(char **l, char *f, int g)
7242 char *p;
7243 int rv = 0, forced_off;
7245 for(; l && *l; l++){
7246 p = (forced_off = !struncmp(*l, "no-", 3)) ? *l + 3 : *l;
7247 if(!strucmp(p, f))
7248 rv = !forced_off;
7249 else if(g && !strucmp(p, "old-growth"))
7250 rv = !forced_off;
7253 return(rv);
7257 void
7258 set_feature(char ***l, char *f, int v)
7260 char **list = l ? *l : NULL, newval[256];
7261 int count = 0;
7263 snprintf(newval, sizeof(newval), "%s%s", v ? "" : "no-", f);
7264 for(; list && *list; list++, count++)
7265 if((**list == '\0') /* anything can replace an empty value */
7266 || !strucmp(((!struncmp(*list, "no-", 3)) ? *list + 3 : *list), f)){
7267 fs_give((void **)list); /* replace with new value */
7268 *list = cpystr(newval);
7269 return;
7273 * if we got here, we didn't find it in the list, so grow the list
7274 * and add it..
7276 if(!*l)
7277 *l = (char **)fs_get((count + 2) * sizeof(char *));
7278 else
7279 fs_resize((void **)l, (count + 2) * sizeof(char *));
7281 (*l)[count] = cpystr(newval);
7282 (*l)[count + 1] = NULL;
7287 reset_character_set_stuff(char **err)
7289 int use_system = 0;
7290 char buf[1000];
7292 if(err)
7293 *err = NULL;
7295 if(ps_global->display_charmap)
7296 fs_give((void **) &ps_global->display_charmap);
7298 if(ps_global->keyboard_charmap)
7299 fs_give((void **) &ps_global->keyboard_charmap);
7301 if(ps_global->posting_charmap)
7302 fs_give((void **) &ps_global->posting_charmap);
7304 #ifdef _WINDOWS
7305 ps_global->display_charmap = cpystr("UTF-8");
7306 #else /* UNIX */
7307 if(ps_global->VAR_CHAR_SET)
7308 ps_global->display_charmap = cpystr(ps_global->VAR_CHAR_SET);
7309 else{
7310 #if HAVE_LANGINFO_H && defined(CODESET)
7311 ps_global->display_charmap = cpystr(nl_langinfo_codeset_wrapper());
7312 #else
7313 ps_global->display_charmap = cpystr("UTF-8");
7314 #endif
7316 #endif /* UNIX */
7318 if(!ps_global->display_charmap)
7319 ps_global->display_charmap = cpystr("US-ASCII");
7321 #ifdef _WINDOWS
7322 ps_global->keyboard_charmap = cpystr("UTF-8");
7323 #else /* UNIX */
7324 if(ps_global->VAR_KEY_CHAR_SET)
7325 ps_global->keyboard_charmap = cpystr(ps_global->VAR_KEY_CHAR_SET);
7326 else
7327 ps_global->keyboard_charmap = cpystr(ps_global->display_charmap);
7329 if(!ps_global->keyboard_charmap)
7330 ps_global->keyboard_charmap = cpystr("US-ASCII");
7332 if(F_ON(F_USE_SYSTEM_TRANS, ps_global)){
7333 #if PREREQ_FOR_SYS_TRANSLATION
7334 use_system++;
7335 /* This modifies its arguments */
7336 if(setup_for_input_output(use_system, &ps_global->display_charmap,
7337 &ps_global->keyboard_charmap,
7338 &ps_global->input_cs, (err && *err) ? NULL : err) == -1)
7339 return -1;
7340 #endif
7342 #endif /* UNIX */
7344 if(!use_system){
7345 if(setup_for_input_output(use_system, &ps_global->display_charmap,
7346 &ps_global->keyboard_charmap,
7347 &ps_global->input_cs, (err && *err) ? NULL : err) == -1)
7348 return -1;
7351 if(!use_system && ps_global->VAR_POST_CHAR_SET){
7352 ps_global->posting_charmap = cpystr(ps_global->VAR_POST_CHAR_SET);
7353 if(!posting_charset_is_supported(ps_global->posting_charmap)){
7354 if(err && !*err){
7355 snprintf(buf, sizeof(buf),
7356 _("Posting-Character-Set \"%s\" is unsupported, using UTF-8"),
7357 ps_global->posting_charmap);
7358 *err = cpystr(buf);
7361 fs_give((void **) &ps_global->posting_charmap);
7362 ps_global->posting_charmap = cpystr("UTF-8");
7365 else{
7366 if(use_system && ps_global->VAR_POST_CHAR_SET
7367 && strucmp(ps_global->VAR_POST_CHAR_SET, "UTF-8"))
7368 if(err && !*err)
7369 *err = cpystr(_("Posting-Character-Set is ignored with Use-System-Translation turned on"));
7371 ps_global->posting_charmap = cpystr("UTF-8");
7374 set_locale_charmap(ps_global->keyboard_charmap);
7376 return(0);
7381 * Given a single printer string from the config file, returns pointers
7382 * to alloc'd strings containing the printer nickname, the command,
7383 * the init string, the trailer string, everything but the nickname string,
7384 * and everything but the command string. All_but_cmd includes the trailing
7385 * space at the end (the one before the command) but all_but_nick does not
7386 * include the leading space (the one before the [).
7387 * If you pass in a pointer it is guaranteed to come back pointing to an
7388 * allocated string, even if it is just an empty string. It is ok to pass
7389 * NULL for any of the six return strings.
7391 void
7392 parse_printer(char *input, char **nick, char **cmd, char **init, char **trailer,
7393 char **all_but_nick, char **all_but_cmd)
7395 char *p, *q, *start, *saved_options = NULL;
7396 int tmpsave, cnt;
7398 if(!input)
7399 input = "";
7401 if(nick || all_but_nick){
7402 if((p = srchstr(input, " [")) != NULL){
7403 if(all_but_nick)
7404 *all_but_nick = cpystr(p+1);
7406 if(nick){
7407 while(p-1 > input && isspace((unsigned char)*(p-1)))
7408 p--;
7410 tmpsave = *p;
7411 *p = '\0';
7412 *nick = cpystr(input);
7413 *p = tmpsave;
7416 else{
7417 if(nick)
7418 *nick = cpystr("");
7420 if(all_but_nick)
7421 *all_but_nick = cpystr(input);
7425 if((p = srchstr(input, "] ")) != NULL){
7427 ++p;
7428 }while(isspace((unsigned char)*p));
7430 tmpsave = *p;
7431 *p = '\0';
7432 saved_options = cpystr(input);
7433 *p = tmpsave;
7435 else
7436 p = input;
7438 if(cmd)
7439 *cmd = cpystr(p);
7441 if(init){
7442 if(saved_options && (p = srchstr(saved_options, "INIT="))){
7443 start = p + strlen("INIT=");
7444 for(cnt=0, p = start; *p && *(p+1) && isxpair(p); p += 2)
7445 cnt++;
7447 q = *init = (char *)fs_get((cnt + 1) * sizeof(char));
7448 for(p = start; *p && *(p+1) && isxpair(p); p += 2)
7449 *q++ = read_hex(p);
7451 *q = '\0';
7453 else
7454 *init = cpystr("");
7457 if(trailer){
7458 if(saved_options && (p = srchstr(saved_options, "TRAILER="))){
7459 start = p + strlen("TRAILER=");
7460 for(cnt=0, p = start; *p && *(p+1) && isxpair(p); p += 2)
7461 cnt++;
7463 q = *trailer = (char *)fs_get((cnt + 1) * sizeof(char));
7464 for(p = start; *p && *(p+1) && isxpair(p); p += 2)
7465 *q++ = read_hex(p);
7467 *q = '\0';
7469 else
7470 *trailer = cpystr("");
7473 if(all_but_cmd){
7474 if(saved_options)
7475 *all_but_cmd = saved_options;
7476 else
7477 *all_but_cmd = cpystr("");
7479 else if(saved_options)
7480 fs_give((void **)&saved_options);
7485 copy_pinerc(char *local, char *remote, char **err_msg)
7487 return(copy_localfile_to_remotefldr(RemImap, local, remote,
7488 REMOTE_PINERC_SUBTYPE,
7489 err_msg));
7494 copy_abook(char *local, char *remote, char **err_msg)
7496 return(copy_localfile_to_remotefldr(RemImap, local, remote,
7497 REMOTE_ABOOK_SUBTYPE,
7498 err_msg));
7503 * Copy local file to remote folder.
7505 * Args remotetype -- type of remote folder
7506 * local -- name of local file
7507 * remote -- name of remote folder
7508 * subtype --
7510 * Returns 0 on success.
7513 copy_localfile_to_remotefldr(RemType remotetype, char *local, char *remote,
7514 char *subtype, char **err_msg)
7516 int retfail = -1;
7517 unsigned flags;
7518 REMDATA_S *rd;
7520 dprint((9, "copy_localfile_to_remotefldr(%s,%s)\n",
7521 local ? local : "<null>",
7522 remote ? remote : "<null>"));
7524 *err_msg = (char *)fs_get(MAXPATH * sizeof(char));
7526 if(!local || !*local){
7527 snprintf(*err_msg, MAXPATH, _("No local file specified"));
7528 return(retfail);
7531 if(!remote || !*remote){
7532 snprintf(*err_msg, MAXPATH, _("No remote folder specified"));
7533 return(retfail);
7536 if(!IS_REMOTE(remote)){
7537 snprintf(*err_msg, MAXPATH, _("Remote folder name \"%s\" %s"), remote,
7538 (*remote != '{') ? _("must begin with \"{\"") : _("not valid"));
7539 return(retfail);
7542 if(IS_REMOTE(local)){
7543 snprintf(*err_msg, MAXPATH, _("First argument \"%s\" must be a local filename"),
7544 local);
7545 return(retfail);
7548 if(can_access(local, ACCESS_EXISTS) != 0){
7549 snprintf(*err_msg, MAXPATH, _("Local file \"%s\" does not exist"), local);
7550 return(retfail);
7553 if(can_access(local, READ_ACCESS) != 0){
7554 snprintf(*err_msg, MAXPATH, _("Can't read local file \"%s\": %s"),
7555 local, error_description(errno));
7556 return(retfail);
7560 * Check if remote folder exists and create it if it doesn't.
7562 flags = 0;
7563 rd = rd_create_remote(remotetype, remote, subtype,
7564 &flags, _("Error: "), _("Can't copy to remote folder."));
7566 if(!rd || rd->access == NoExists){
7567 snprintf(*err_msg, MAXPATH, _("Can't create \"%s\""), remote);
7568 if(rd)
7569 rd_free_remdata(&rd);
7571 return(retfail);
7574 if(rd->access == MaybeRorW)
7575 rd->access = ReadWrite;
7577 rd->flags |= (NO_META_UPDATE | DO_REMTRIM);
7578 rd->lf = cpystr(local);
7580 rd_open_remote(rd);
7581 if(!rd_stream_exists(rd)){
7582 snprintf(*err_msg, MAXPATH, _("Can't open remote folder \"%s\""), rd->rn);
7583 rd_free_remdata(&rd);
7584 return(retfail);
7587 if(rd_remote_is_readonly(rd)){
7588 snprintf(*err_msg, MAXPATH, _("Remote folder \"%s\" is readonly"), rd->rn);
7589 rd_free_remdata(&rd);
7590 return(retfail);
7593 switch(rd->type){
7594 case RemImap:
7596 * Empty folder, add a header msg.
7598 if(rd->t.i.stream->nmsgs == 0){
7599 if(rd_init_remote(rd, 1) != 0){
7600 snprintf(*err_msg, MAXPATH,
7601 _("Failed initializing remote folder \"%s\", check debug file"),
7602 rd->rn);
7603 rd_free_remdata(&rd);
7604 return(retfail);
7608 fs_give((void **)err_msg);
7609 *err_msg = NULL;
7610 if(rd_chk_for_hdr_msg(&(rd->t.i.stream), rd, err_msg)){
7611 rd_free_remdata(&rd);
7612 return(retfail);
7615 break;
7617 default:
7618 break;
7621 if(rd_update_remote(rd, NULL) != 0){
7622 snprintf(*err_msg, MAXPATH, _("Error copying to remote folder \"%s\""), rd->rn);
7623 rd_free_remdata(&rd);
7624 return(retfail);
7627 rd_update_metadata(rd, NULL);
7628 rd_close_remdata(&rd);
7630 fs_give((void **)err_msg);
7631 return(0);
7635 /*----------------------------------------------------------------------
7636 Panic pine - call on detected programmatic errors to exit pine, with arg
7638 Input: message -- printf styule string for panic message (see above)
7639 arg -- argument for printf string
7641 Result: The various tty modes are restored
7642 If debugging is active a core dump will be generated
7643 Exits Pine
7644 ----*/
7645 void
7646 panic1(char *message, char *arg)
7648 #define SIZEOFBUF 1001
7649 char buf1[SIZEOFBUF], buf2[SIZEOFBUF];
7651 snprintf(buf1, sizeof(buf1), "%.*s", (int) MAX(SIZEOFBUF - 1 - strlen(message), 0), arg);
7652 snprintf(buf2, sizeof(buf2), message, buf1);
7653 alpine_panic(buf2);
7660 HelpType
7661 config_help(int var, int feature)
7663 switch(var){
7664 case V_FEATURE_LIST :
7665 return(feature_list_help(feature));
7666 break;
7668 case V_PERSONAL_NAME :
7669 return(h_config_pers_name);
7670 case V_USER_ID :
7671 return(h_config_user_id);
7672 case V_USER_DOMAIN :
7673 return(h_config_user_dom);
7674 case V_SMTP_SERVER :
7675 return(h_config_smtp_server);
7676 case V_NNTP_SERVER :
7677 return(h_config_nntp_server);
7678 case V_INBOX_PATH :
7679 return(h_config_inbox_path);
7680 case V_PRUNED_FOLDERS :
7681 return(h_config_pruned_folders);
7682 case V_DEFAULT_FCC :
7683 return(h_config_default_fcc);
7684 case V_DEFAULT_SAVE_FOLDER :
7685 return(h_config_def_save_folder);
7686 case V_POSTPONED_FOLDER :
7687 return(h_config_postponed_folder);
7688 case V_READ_MESSAGE_FOLDER :
7689 return(h_config_read_message_folder);
7690 case V_FORM_FOLDER :
7691 return(h_config_form_folder);
7692 case V_ARCHIVED_FOLDERS :
7693 return(h_config_archived_folders);
7694 case V_SIGNATURE_FILE :
7695 return(h_config_signature_file);
7696 case V_LITERAL_SIG :
7697 return(h_config_literal_sig);
7698 case V_INIT_CMD_LIST :
7699 return(h_config_init_cmd_list);
7700 case V_COMP_HDRS :
7701 return(h_config_comp_hdrs);
7702 case V_CUSTOM_HDRS :
7703 return(h_config_custom_hdrs);
7704 case V_VIEW_HEADERS :
7705 return(h_config_viewer_headers);
7706 case V_VIEW_MARGIN_LEFT :
7707 return(h_config_viewer_margin_left);
7708 case V_VIEW_MARGIN_RIGHT :
7709 return(h_config_viewer_margin_right);
7710 case V_QUOTE_SUPPRESSION :
7711 return(h_config_quote_suppression);
7712 case V_SAVED_MSG_NAME_RULE :
7713 return(h_config_saved_msg_name_rule);
7714 case V_FCC_RULE :
7715 return(h_config_fcc_rule);
7716 case V_SORT_KEY :
7717 return(h_config_sort_key);
7718 case V_AB_SORT_RULE :
7719 return(h_config_ab_sort_rule);
7720 case V_FLD_SORT_RULE :
7721 return(h_config_fld_sort_rule);
7722 case V_POST_CHAR_SET :
7723 return(h_config_post_char_set);
7724 case V_UNK_CHAR_SET :
7725 return(h_config_unk_char_set);
7726 #ifndef _WINDOWS
7727 case V_KEY_CHAR_SET :
7728 return(h_config_key_char_set);
7729 case V_CHAR_SET :
7730 return(h_config_char_set);
7731 #endif /* ! _WINDOWS */
7732 case V_EDITOR :
7733 return(h_config_editor);
7734 case V_SPELLER :
7735 return(h_config_speller);
7736 #ifdef _WINDOWS
7737 case V_DICTIONARY :
7738 return(h_config_aspell_dictionary);
7739 #endif /* _WINDOWS */
7740 case V_DISPLAY_FILTERS :
7741 return(h_config_display_filters);
7742 case V_SEND_FILTER :
7743 return(h_config_sending_filter);
7744 case V_ALT_ADDRS :
7745 return(h_config_alt_addresses);
7746 case V_KEYWORDS :
7747 return(h_config_keywords);
7748 case V_KW_BRACES :
7749 return(h_config_kw_braces);
7750 case V_OPENING_SEP :
7751 return(h_config_opening_sep);
7752 case V_KW_COLORS :
7753 return(h_config_kw_color);
7754 case V_ABOOK_FORMATS :
7755 return(h_config_abook_formats);
7756 case V_INDEX_FORMAT :
7757 return(h_config_index_format);
7758 case V_INCCHECKTIMEO :
7759 return(h_config_incoming_timeo);
7760 case V_INCCHECKINTERVAL :
7761 return(h_config_incoming_interv);
7762 case V_INC2NDCHECKINTERVAL :
7763 return(h_config_incoming_second_interv);
7764 case V_INCCHECKLIST :
7765 return(h_config_incoming_list);
7766 case V_SLEEP :
7767 return(h_config_psleep);
7768 case V_OVERLAP :
7769 return(h_config_viewer_overlap);
7770 case V_MAXREMSTREAM :
7771 return(h_config_maxremstream);
7772 case V_PERMLOCKED :
7773 return(h_config_permlocked);
7774 case V_MARGIN :
7775 return(h_config_scroll_margin);
7776 case V_DEADLETS :
7777 return(h_config_deadlets);
7778 case V_FILLCOL :
7779 return(h_config_composer_wrap_column);
7780 case V_TCPOPENTIMEO :
7781 return(h_config_tcp_open_timeo);
7782 case V_TCPREADWARNTIMEO :
7783 return(h_config_tcp_readwarn_timeo);
7784 case V_TCPWRITEWARNTIMEO :
7785 return(h_config_tcp_writewarn_timeo);
7786 case V_TCPQUERYTIMEO :
7787 return(h_config_tcp_query_timeo);
7788 case V_RSHOPENTIMEO :
7789 return(h_config_rsh_open_timeo);
7790 case V_SSHOPENTIMEO :
7791 return(h_config_ssh_open_timeo);
7792 case V_USERINPUTTIMEO :
7793 return(h_config_user_input_timeo);
7794 case V_REMOTE_ABOOK_VALIDITY :
7795 return(h_config_remote_abook_validity);
7796 case V_REMOTE_ABOOK_HISTORY :
7797 return(h_config_remote_abook_history);
7798 case V_INCOMING_FOLDERS :
7799 return(h_config_incoming_folders);
7800 case V_FOLDER_SPEC :
7801 return(h_config_folder_spec);
7802 case V_NEWS_SPEC :
7803 return(h_config_news_spec);
7804 case V_ADDRESSBOOK :
7805 return(h_config_address_book);
7806 case V_GLOB_ADDRBOOK :
7807 return(h_config_glob_addrbook);
7808 case V_LAST_VERS_USED :
7809 return(h_config_last_vers);
7810 case V_SENDMAIL_PATH :
7811 return(h_config_sendmail_path);
7812 case V_OPER_DIR :
7813 return(h_config_oper_dir);
7814 case V_RSHPATH :
7815 return(h_config_rshpath);
7816 case V_RSHCMD :
7817 return(h_config_rshcmd);
7818 case V_SSHPATH :
7819 return(h_config_sshpath);
7820 case V_SSHCMD :
7821 return(h_config_sshcmd);
7822 case V_NEW_VER_QUELL :
7823 return(h_config_new_ver_quell);
7824 case V_DISABLE_DRIVERS :
7825 return(h_config_disable_drivers);
7826 case V_DISABLE_AUTHS :
7827 return(h_config_disable_auths);
7828 case V_REMOTE_ABOOK_METADATA :
7829 return(h_config_abook_metafile);
7830 case V_REPLY_STRING :
7831 return(h_config_reply_indent_string);
7832 case V_WORDSEPS :
7833 return(h_config_wordseps);
7834 case V_QUOTE_REPLACE_STRING :
7835 return(h_config_quote_replace_string);
7836 case V_REPLY_INTRO :
7837 return(h_config_reply_intro);
7838 case V_EMPTY_HDR_MSG :
7839 return(h_config_empty_hdr_msg);
7840 case V_STATUS_MSG_DELAY :
7841 return(h_config_status_msg_delay);
7842 case V_ACTIVE_MSG_INTERVAL :
7843 return(h_config_active_msg_interval);
7844 case V_MAILCHECK :
7845 return(h_config_mailcheck);
7846 case V_MAILCHECKNONCURR :
7847 return(h_config_mailchecknoncurr);
7848 case V_MAILDROPCHECK :
7849 return(h_config_maildropcheck);
7850 case V_NNTPRANGE :
7851 return(h_config_nntprange);
7852 case V_NEWS_ACTIVE_PATH :
7853 return(h_config_news_active);
7854 case V_NEWS_SPOOL_DIR :
7855 return(h_config_news_spool);
7856 case V_IMAGE_VIEWER :
7857 return(h_config_image_viewer);
7858 case V_USE_ONLY_DOMAIN_NAME :
7859 return(h_config_domain_name);
7860 case V_LAST_TIME_PRUNE_QUESTION :
7861 return(h_config_prune_date);
7862 case V_UPLOAD_CMD:
7863 return(h_config_upload_cmd);
7864 case V_UPLOAD_CMD_PREFIX:
7865 return(h_config_upload_prefix);
7866 case V_DOWNLOAD_CMD:
7867 return(h_config_download_cmd);
7868 case V_DOWNLOAD_CMD_PREFIX:
7869 return(h_config_download_prefix);
7870 case V_GOTO_DEFAULT_RULE:
7871 return(h_config_goto_default);
7872 case V_INCOMING_STARTUP:
7873 return(h_config_inc_startup);
7874 case V_PRUNING_RULE:
7875 return(h_config_pruning_rule);
7876 case V_REOPEN_RULE:
7877 return(h_config_reopen_rule);
7878 case V_THREAD_DISP_STYLE:
7879 return(h_config_thread_disp_style);
7880 case V_THREAD_INDEX_STYLE:
7881 return(h_config_thread_index_style);
7882 case V_THREAD_MORE_CHAR:
7883 return(h_config_thread_indicator_char);
7884 case V_THREAD_EXP_CHAR:
7885 return(h_config_thread_exp_char);
7886 case V_THREAD_LASTREPLY_CHAR:
7887 return(h_config_thread_lastreply_char);
7888 case V_MAILCAP_PATH :
7889 return(h_config_mailcap_path);
7890 case V_MIMETYPE_PATH :
7891 return(h_config_mimetype_path);
7892 #if !defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)
7893 case V_FIFOPATH :
7894 return(h_config_fifopath);
7895 #endif
7896 case V_NMW_WIDTH :
7897 return(h_config_newmailwidth);
7898 case V_NEWSRC_PATH :
7899 return(h_config_newsrc_path);
7900 case V_BROWSER :
7901 return(h_config_browser);
7902 case V_HISTORY :
7903 return(h_config_history);
7904 #if defined(DOS) || defined(OS2)
7905 case V_FILE_DIR :
7906 return(h_config_file_dir);
7907 #endif
7908 case V_NORM_FORE_COLOR :
7909 case V_NORM_BACK_COLOR :
7910 return(h_config_normal_color);
7911 case V_REV_FORE_COLOR :
7912 case V_REV_BACK_COLOR :
7913 return(h_config_reverse_color);
7914 case V_TITLE_FORE_COLOR :
7915 case V_TITLE_BACK_COLOR :
7916 return(h_config_title_color);
7917 case V_TITLECLOSED_FORE_COLOR :
7918 case V_TITLECLOSED_BACK_COLOR :
7919 return(h_config_titleclosed_color);
7920 case V_FOLDER_FORE_COLOR:
7921 return(h_config_folder_color);
7922 case V_DIRECTORY_FORE_COLOR:
7923 return(h_config_directory_color);
7924 case V_FOLDER_LIST_FORE_COLOR:
7925 return(h_config_folder_list_color);
7926 case V_STATUS_FORE_COLOR :
7927 case V_STATUS_BACK_COLOR :
7928 return(h_config_status_color);
7929 case V_SLCTBL_FORE_COLOR :
7930 case V_SLCTBL_BACK_COLOR :
7931 return(h_config_slctbl_color);
7932 case V_QUOTE1_FORE_COLOR :
7933 case V_QUOTE2_FORE_COLOR :
7934 case V_QUOTE3_FORE_COLOR :
7935 case V_QUOTE1_BACK_COLOR :
7936 case V_QUOTE2_BACK_COLOR :
7937 case V_QUOTE3_BACK_COLOR :
7938 return(h_config_quote_color);
7939 case V_INCUNSEEN_FORE_COLOR :
7940 case V_INCUNSEEN_BACK_COLOR :
7941 return(h_config_incunseen_color);
7942 case V_SIGNATURE_FORE_COLOR :
7943 case V_SIGNATURE_BACK_COLOR :
7944 return(h_config_signature_color);
7945 case V_PROMPT_FORE_COLOR :
7946 case V_PROMPT_BACK_COLOR :
7947 return(h_config_prompt_color);
7948 case V_HEADER_GENERAL_FORE_COLOR :
7949 case V_HEADER_GENERAL_BACK_COLOR :
7950 return(h_config_header_general_color);
7951 case V_IND_PLUS_FORE_COLOR :
7952 case V_IND_IMP_FORE_COLOR :
7953 case V_IND_DEL_FORE_COLOR :
7954 case V_IND_ANS_FORE_COLOR :
7955 case V_IND_NEW_FORE_COLOR :
7956 case V_IND_UNS_FORE_COLOR :
7957 case V_IND_REC_FORE_COLOR :
7958 case V_IND_FWD_FORE_COLOR :
7959 case V_IND_PLUS_BACK_COLOR :
7960 case V_IND_IMP_BACK_COLOR :
7961 case V_IND_DEL_BACK_COLOR :
7962 case V_IND_ANS_BACK_COLOR :
7963 case V_IND_NEW_BACK_COLOR :
7964 case V_IND_UNS_BACK_COLOR :
7965 case V_IND_REC_BACK_COLOR :
7966 case V_IND_FWD_BACK_COLOR :
7967 return(h_config_index_color);
7968 case V_IND_OP_FORE_COLOR :
7969 case V_IND_OP_BACK_COLOR :
7970 return(h_config_index_opening_color);
7971 case V_IND_SUBJ_FORE_COLOR :
7972 case V_IND_SUBJ_BACK_COLOR :
7973 return(h_config_index_subject_color);
7974 case V_IND_FROM_FORE_COLOR :
7975 case V_IND_FROM_BACK_COLOR :
7976 return(h_config_index_from_color);
7977 case V_IND_HIPRI_FORE_COLOR :
7978 case V_IND_HIPRI_BACK_COLOR :
7979 case V_IND_LOPRI_FORE_COLOR :
7980 case V_IND_LOPRI_BACK_COLOR :
7981 return(h_config_index_pri_color);
7982 case V_IND_ARR_FORE_COLOR :
7983 case V_IND_ARR_BACK_COLOR :
7984 return(h_config_index_arrow_color);
7985 case V_KEYLABEL_FORE_COLOR :
7986 case V_KEYLABEL_BACK_COLOR :
7987 return(h_config_keylabel_color);
7988 case V_KEYNAME_FORE_COLOR :
7989 case V_KEYNAME_BACK_COLOR :
7990 return(h_config_keyname_color);
7991 case V_METAMSG_FORE_COLOR :
7992 case V_METAMSG_BACK_COLOR :
7993 return(h_config_metamsg_color);
7994 case V_VIEW_HDR_COLORS :
7995 return(h_config_customhdr_color);
7996 case V_INDEX_TOKEN_COLORS :
7997 return(h_config_indextoken_color);
7998 case V_PRINTER :
7999 return(h_config_printer);
8000 case V_PERSONAL_PRINT_CATEGORY :
8001 return(h_config_print_cat);
8002 case V_PERSONAL_PRINT_COMMAND :
8003 return(h_config_print_command);
8004 case V_PAT_ROLES :
8005 return(h_config_pat_roles);
8006 case V_PAT_FILTS :
8007 return(h_config_pat_filts);
8008 case V_PAT_SCORES :
8009 return(h_config_pat_scores);
8010 case V_PAT_INCOLS :
8011 return(h_config_pat_incols);
8012 case V_PAT_OTHER :
8013 return(h_config_pat_other);
8014 case V_PAT_SRCH :
8015 return(h_config_pat_srch);
8016 case V_INDEX_COLOR_STYLE :
8017 return(h_config_index_color_style);
8018 case V_TITLEBAR_COLOR_STYLE :
8019 return(h_config_titlebar_color_style);
8020 #ifdef _WINDOWS
8021 case V_FONT_NAME :
8022 return(h_config_font_name);
8023 case V_FONT_SIZE :
8024 return(h_config_font_size);
8025 case V_FONT_STYLE :
8026 return(h_config_font_style);
8027 case V_FONT_CHAR_SET :
8028 return(h_config_font_char_set);
8029 case V_PRINT_FONT_NAME :
8030 return(h_config_print_font_name);
8031 case V_PRINT_FONT_SIZE :
8032 return(h_config_print_font_size);
8033 case V_PRINT_FONT_STYLE :
8034 return(h_config_print_font_style);
8035 case V_PRINT_FONT_CHAR_SET :
8036 return(h_config_print_font_char_set);
8037 case V_WINDOW_POSITION :
8038 return(h_config_window_position);
8039 case V_CURSOR_STYLE :
8040 return(h_config_cursor_style);
8041 #else
8042 case V_COLOR_STYLE :
8043 return(h_config_color_style);
8044 #endif
8045 #ifdef ENABLE_LDAP
8046 case V_LDAP_SERVERS :
8047 return(h_config_ldap_servers);
8048 #endif
8049 #ifdef SMIME
8050 case V_PUBLICCERT_DIR :
8051 return(h_config_smime_pubcertdir);
8052 case V_PUBLICCERT_CONTAINER :
8053 return(h_config_smime_pubcertcon);
8054 case V_PRIVATEKEY_DIR :
8055 return(h_config_smime_privkeydir);
8056 case V_PRIVATEKEY_CONTAINER :
8057 return(h_config_smime_privkeycon);
8058 case V_CACERT_DIR :
8059 return(h_config_smime_cacertdir);
8060 case V_CACERT_CONTAINER :
8061 return(h_config_smime_cacertcon);
8062 #endif
8063 case V_RSS_NEWS :
8064 return(h_config_rss_news);
8065 case V_RSS_WEATHER :
8066 return(h_config_rss_weather);
8067 case V_WP_INDEXHEIGHT :
8068 return(h_config_wp_indexheight);
8069 case V_WP_INDEXLINES :
8070 return(h_config_wp_indexlines);
8071 case V_WP_AGGSTATE :
8072 return(h_config_wp_aggstate);
8073 case V_WP_STATE :
8074 return(h_config_wp_state);
8075 case V_WP_COLUMNS :
8076 return(h_config_wp_columns);
8077 default :
8078 return(NO_HELP);
8084 * We don't want the user to be able to edit their pinerc and set
8085 * printer to whatever they want if personal-print-command is fixed.
8086 * So make sure printer is set to something legitimate. If it isn't,
8087 * set it to something standard and return non-zero.
8090 printer_value_check_and_adjust(void)
8092 char **tt;
8093 char aname[100], wname[100];
8094 int ok = 0;
8095 struct variable *vars = ps_global->vars;
8097 if(vars[V_PERSONAL_PRINT_COMMAND].is_fixed && !vars[V_PRINTER].is_fixed){
8098 strncpy(aname, ANSI_PRINTER, sizeof(aname));
8099 aname[sizeof(aname)-1] = '\0';
8100 strncat(aname, "-no-formfeed", sizeof(aname)-strlen(aname)-1);
8101 strncpy(wname, WYSE_PRINTER, sizeof(wname));
8102 wname[sizeof(wname)-1] = '\0';
8103 strncat(wname, "-no-formfeed", sizeof(wname)-strlen(wname)-1);
8104 if(strucmp(VAR_PRINTER, ANSI_PRINTER) == 0
8105 || strucmp(VAR_PRINTER, aname) == 0
8106 || strucmp(VAR_PRINTER, WYSE_PRINTER) == 0
8107 || strucmp(VAR_PRINTER, wname) == 0)
8108 ok++;
8109 else if(VAR_STANDARD_PRINTER && VAR_STANDARD_PRINTER[0]){
8110 for(tt = VAR_STANDARD_PRINTER; *tt; tt++)
8111 if(strucmp(VAR_PRINTER, *tt) == 0)
8112 break;
8114 if(*tt)
8115 ok++;
8118 if(!ok){
8119 char *val;
8120 struct variable *v;
8122 if(VAR_STANDARD_PRINTER && VAR_STANDARD_PRINTER[0])
8123 val = VAR_STANDARD_PRINTER[0];
8124 else
8125 val = ANSI_PRINTER;
8127 v = &vars[V_PRINTER];
8128 if(v->main_user_val.p)
8129 fs_give((void **)&v->main_user_val.p);
8130 if(v->post_user_val.p)
8131 fs_give((void **)&v->post_user_val.p);
8132 if(v->current_val.p)
8133 fs_give((void **)&v->current_val.p);
8135 v->main_user_val.p = cpystr(val);
8136 v->current_val.p = cpystr(val);
8140 return(!ok);
8144 char **
8145 get_supported_options(void)
8147 char **config;
8148 DRIVER *d;
8149 AUTHENTICATOR *a;
8150 char *title = _("Supported features in this Alpine");
8151 char sbuf[MAX_SCREEN_COLS+1], tmp[128];
8152 int cnt, alcnt, len, cols, disabled, any_disabled = 0, i;
8155 * Line count:
8156 * Title + blank = 2
8157 * SSL Title + SSL lines + blank = 5
8158 * Auth title + blank = 2
8159 * Driver title + blank = 2
8160 * LDAP title + LDAP line = 2
8161 * Disabled explanation + blank line = 4
8162 * end = 1
8164 cnt = 18;
8165 for(a = mail_lookup_auth(1); a; a = a->next)
8166 cnt++;
8167 for(d = (DRIVER *)mail_parameters(NIL, GET_DRIVERS, NIL);
8168 d; d = d->next)
8169 cnt++;
8171 alcnt = cnt;
8172 config = (char **) fs_get(alcnt * sizeof(char *));
8173 memset(config, 0, alcnt * sizeof(char *));
8175 cols = ps_global->ttyo ? ps_global->ttyo->screen_cols : 0;
8176 len = utf8_width(title);
8177 snprintf(sbuf, sizeof(sbuf), "%*s%s", cols > len ? (cols-len)/2 : 0, "", title);
8179 cnt = 0;
8180 if(cnt < alcnt)
8181 config[cnt] = cpystr(sbuf);
8183 if(++cnt < alcnt)
8184 config[cnt] = cpystr("");
8186 if(++cnt < alcnt)
8187 /* TRANSLATORS: headings */
8188 config[cnt] = cpystr(_("Encryption:"));
8190 if(++cnt < alcnt && mail_parameters(NIL, GET_SSLDRIVER, NIL))
8191 config[cnt] = cpystr(_(" TLS and SSL"));
8192 else
8193 config[cnt] = cpystr(_(" None (no TLS or SSL)"));
8195 tmp[0] = tmp[1] = ' ';
8196 tmp[2] = '\0';
8197 #ifndef OPENSSL_NO_TLS1_METHOD
8198 strcat(tmp, "TLSv1, ");
8199 #endif /* OPENSSL_NO_TLS1_METHOD */
8200 #ifdef TLS1_1_VERSION
8201 strcat(tmp, "TLSv1.1, ");
8202 #endif /* TLS1_1_VERSION */
8203 #ifdef TLS1_2_VERSION
8204 strcat(tmp, "TLSv1.2. ");
8205 #endif /* TLS1_2_VERSION */
8206 #ifdef TLS1_3_VERSION
8207 strcat(tmp, "TLSv1.3, ");
8208 #endif /* TLS1_3_VERSION */
8209 #ifdef DTLS1_VERSION
8210 strcat(tmp, "DTLSv1, ");
8211 #endif /* DTLS1_VERSION */
8212 #ifdef DTLS1_2_VERSION
8213 strcat(tmp, "DTLSv1.2, ");
8214 #endif /* DTLS1_2_VERSION */
8215 if(tmp[2] != '\0'){
8216 tmp[strlen(tmp)-2] = '\0';
8217 if(++cnt < alcnt)
8218 config[cnt] = cpystr(tmp);
8220 #ifdef SMIME
8221 if(++cnt < alcnt)
8222 config[cnt] = cpystr(" S/MIME");
8223 #endif
8225 if(++cnt < alcnt)
8226 config[cnt] = cpystr("");
8228 if(++cnt < alcnt)
8229 config[cnt] = cpystr(_("Authenticators:"));
8231 for(a = mail_lookup_auth(1); a; a = a->next){
8232 disabled = (a->client == NULL && a->server == NULL);
8233 any_disabled += disabled;
8234 snprintf(sbuf, sizeof(sbuf), " %s%s", a->name, disabled ? " (disabled)" : "");
8235 if(++cnt < alcnt)
8236 config[cnt] = cpystr(sbuf);
8239 if(++cnt < alcnt)
8240 config[cnt] = cpystr("");
8242 if(++cnt < alcnt)
8243 config[cnt] = cpystr(_("Mailbox drivers:"));
8245 for(d = (DRIVER *)mail_parameters(NIL, GET_DRIVERS, NIL);
8246 d; d = d->next){
8247 disabled = (d->flags & DR_DISABLE);
8248 any_disabled += disabled;
8249 snprintf(sbuf, sizeof(sbuf), " %s%s", d->name, disabled ? " (disabled)" : "");
8250 if(++cnt < alcnt)
8251 config[cnt] = cpystr(sbuf);
8254 if(++cnt < alcnt)
8255 config[cnt] = cpystr("");
8257 if(++cnt < alcnt)
8258 config[cnt] = cpystr(_("Directories:"));
8260 #ifdef ENABLE_LDAP
8261 if(++cnt < alcnt)
8262 config[cnt] = cpystr(" LDAP");
8263 #else
8264 if(++cnt < alcnt)
8265 config[cnt] = cpystr(" None (no LDAP)");
8266 #endif
8268 if(any_disabled){
8269 if(++cnt < alcnt)
8270 config[cnt] = cpystr("");
8272 if(ps_global->ttyo){
8273 if(++cnt < alcnt)
8274 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."));
8276 else{
8277 if(++cnt < alcnt)
8278 config[cnt] = cpystr(_("Authenticators may be disabled because of the \"disable-these-authenticators\""));
8279 if(++cnt < alcnt)
8280 config[cnt] = cpystr(_("hidden config option. Mailbox drivers may be disabled because of the"));
8281 if(++cnt < alcnt)
8282 config[cnt] = cpystr(_("\"disable-these-drivers\" hidden config option."));
8286 if(++cnt < alcnt)
8287 config[cnt] = NULL;
8289 return(config);
8293 unsigned
8294 reset_startup_rule(MAILSTREAM *stream)
8296 long rflags = ROLE_DO_OTHER;
8297 PAT_STATE pstate;
8298 PAT_S *pat;
8299 unsigned startup_rule;
8301 startup_rule = IS_NOTSET;
8303 if(stream && nonempty_patterns(rflags, &pstate)){
8304 for(pat = first_pattern(&pstate); pat; pat = next_pattern(&pstate)){
8305 if(match_pattern(pat->patgrp, stream, NULL, NULL, NULL,
8306 SE_NOSERVER|SE_NOPREFETCH))
8307 break;
8310 if(pat && pat->action && !pat->action->bogus)
8311 startup_rule = pat->action->startup_rule;
8314 return(startup_rule);
8318 #ifdef _WINDOWS
8320 char *
8321 transformed_color(old)
8322 char *old;
8324 if(!old)
8325 return("");
8327 if(!struncmp(old, "color008", 8))
8328 return("colorlgr");
8329 else if(!struncmp(old, "color009", 8))
8330 return("colormgr");
8331 else if(!struncmp(old, "color010", 8))
8332 return("colordgr");
8334 return("");
8339 * If this is the first time we've run a version > 4.40, and there
8340 * is evidence that the config file has not been used by unix pine,
8341 * then we convert color008 to colorlgr, color009 to colormgr, and
8342 * color010 to colordgr. If the config file is being used by
8343 * unix pine then color008 may really supposed to be color008, color009
8344 * may really supposed to be red, and color010 may really supposed to be
8345 * green. Same if we've already run 4.41 or higher previously.
8347 * Returns 0 if no changes, > 0 if something was changed.
8350 convert_pc_gray_names(ps, prc, which)
8351 struct pine *ps;
8352 PINERC_S *prc;
8353 EditWhich which;
8355 struct variable *v;
8356 int ret = 0, ic = 0;
8357 char **s, *t, *p, *pstr, *new, *pval, **apval, **lval;
8359 for(v = ps->vars; v->name; v++){
8360 if(!color_holding_var(ps, v) || v == &ps->vars[V_KW_COLORS])
8361 continue;
8363 if(v == &ps->vars[V_VIEW_HDR_COLORS]){
8365 if((lval = LVAL(v,which)) != NULL){
8366 /* fix these in place */
8367 for(s = lval; (t = *s) != NULL; s++){
8368 if((p = srchstr(t, "FG=color008")) ||
8369 (p = srchstr(t, "FG=color009")) ||
8370 (p = srchstr(t, "FG=color010"))){
8371 strncpy(p+3, transformed_color(p+3), 8);
8372 ret++;
8375 if((p = srchstr(t, "BG=color008")) ||
8376 (p = srchstr(t, "BG=color009")) ||
8377 (p = srchstr(t, "BG=color010"))){
8378 strncpy(p+3, transformed_color(p+3), 8);
8379 ret++;
8384 else{
8385 if((pval = PVAL(v,which)) != NULL){
8386 apval = APVAL(v,which);
8387 if(apval && (!strucmp(pval, "color008") ||
8388 !strucmp(pval, "color009") ||
8389 !strucmp(pval, "color010"))){
8390 new = transformed_color(pval);
8391 if(*apval)
8392 fs_give((void **)apval);
8394 *apval = cpystr(new);
8395 ret++;
8401 v = &ps->vars[V_PAT_INCOLS];
8402 if((lval = LVAL(v,which)) != NULL){
8403 for(s = lval; (t = *s) != NULL; s++){
8404 if((pstr = srchstr(t, "action=")) != NULL){
8405 if((p = srchstr(pstr, "FG=color008")) ||
8406 (p = srchstr(pstr, "FG=color009")) ||
8407 (p = srchstr(pstr, "FG=color010"))){
8408 strncpy(p+3, transformed_color(p+3), 8);
8409 ic++;
8412 if((p = srchstr(pstr, "BG=color008")) ||
8413 (p = srchstr(pstr, "BG=color009")) ||
8414 (p = srchstr(pstr, "BG=color010"))){
8415 strncpy(p+3, transformed_color(p+3), 8);
8416 ic++;
8422 if(ic)
8423 set_current_val(&ps->vars[V_PAT_INCOLS], TRUE, TRUE);
8425 return(ret+ic);
8430 unix_color_style_in_pinerc(prc)
8431 PINERC_S *prc;
8433 PINERC_LINE *pline;
8435 for(pline = prc ? prc->pinerc_lines : NULL;
8436 pline && (pline->var || pline->line); pline++)
8437 if(pline->line && !struncmp("color-style=", pline->line, 12))
8438 return(1);
8440 return(0);
8443 char *
8444 pcpine_general_help(titlebuf)
8445 char *titlebuf;
8447 if(titlebuf)
8448 strcpy(titlebuf, "PC Alpine For Windows");
8450 return(pcpine_help(h_pine_for_windows));
8453 #endif /* _WINDOWS */