* Rewrite support for specific SSL encryption protocols, including
[alpine.git] / pith / conf.c
blobc7c24dbeab72ccbfbe939174e81d0903808448ec
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_encryption_range[] = "A range in the form min,max that sets the minimum amd maximum versions of the\n# SSL protocol that Alpine will use when connecting to a secure server.";
286 CONF_TXT_T cf_text_remote_abook_metafile[] = "Set by Alpine; contains data for caching remote address books.";
288 CONF_TXT_T cf_text_old_patterns[] = "Patterns is obsolete, use patterns-xxx";
290 CONF_TXT_T cf_text_old_filters[] = "Patterns-filters is obsolete, use patterns-filters2";
292 CONF_TXT_T cf_text_old_scores[] = "Patterns-scores is obsolete, use patterns-scores2";
294 CONF_TXT_T cf_text_patterns[] = "Patterns and their actions are stored here.";
296 CONF_TXT_T cf_text_remote_abook_history[] = "How many extra copies of remote address book should be kept. Default: 3";
298 CONF_TXT_T cf_text_remote_abook_validity[] = "Minimum number of minutes between checks for remote address book changes.\n# 0 means never check except when opening a remote address book.\n# -1 means never check. Default: 5";
300 CONF_TXT_T cf_text_bugs_fullname[] = "Full name for bug report address used by \"Report Bug\" command";
302 CONF_TXT_T cf_text_bugs_address[] = "Email address used to send bug reports";
304 CONF_TXT_T cf_text_bugs_extras[] = "Program/Script used by \"Report Bug\" command. No default.";
306 CONF_TXT_T cf_text_suggest_fullname[] = "Full name for suggestion address used by \"Report Bug\" command";
308 CONF_TXT_T cf_text_suggest_address[] = "Email address used to send suggestions";
310 CONF_TXT_T cf_text_local_fullname[] = "Full name for \"local support\" address used by \"Report Bug\" command.\n# Default: Local Support";
312 CONF_TXT_T cf_text_local_address[] = "Email address used to send to \"local support\".\n# Default: postmaster";
314 CONF_TXT_T cf_text_forced_abook[] = "Force these address book entries into all writable personal address books.\n# Syntax is forced-abook-entry=nickname|fullname|address\n# This is a comma-separated list of entries, each with syntax above.\n# Existing entries with same nickname are not replaced.\n# Example: help|Help Desk|help@ourdomain.com";
316 CONF_TXT_T cf_text_kblock_passwd[] = "This is a number between 1 and 5. It is the number of times a user will\n# have to enter a password when they run the keyboard lock command in the\n# main menu. Default is 1.";
318 CONF_TXT_T cf_text_sendmail_path[] = "This names the path to an alternative program, and any necessary arguments,\n# to be used in posting mail messages. Example:\n# /usr/lib/sendmail -oem -t -oi\n# or,\n# /usr/local/bin/sendit.sh\n# The latter a script found in Alpine distribution's contrib/util directory.\n# NOTE: The program MUST read the message to be posted on standard input,\n# AND operate in the style of sendmail's \"-t\" option.";
320 CONF_TXT_T cf_text_oper_dir[] = "This names the root of the tree to which the user is restricted when reading\n# and writing folders and files. For example, on Unix ~/work confines the\n# user to the subtree beginning with their work subdirectory.\n# (Note: this alone is not sufficient for preventing access. You will also\n# need to restrict shell access and so on, see Alpine Technical Notes.)\n# Default: not set (so no restriction)";
322 CONF_TXT_T cf_text_in_fltr[] = "This variable takes a list of programs that message text is piped into\n# after MIME decoding, prior to display.";
324 CONF_TXT_T cf_text_out_fltr[] = "This defines a program that message text is piped into before MIME\n# encoding, prior to sending";
326 CONF_TXT_T cf_text_alt_addrs[] = "A list of alternate addresses the user is known by";
328 CONF_TXT_T cf_text_keywords[] = "A list of keywords for use in categorizing messages";
330 CONF_TXT_T cf_text_kw_colors[] = "Colors used to display keywords in the index";
332 CONF_TXT_T cf_text_kw_braces[] = "Characters which surround keywords in SUBJKEY token.\n# Default is \"{\" \"} \"";
334 CONF_TXT_T cf_text_opening_sep[] = "Characters between subject and opening text in SUBJECTTEXT token.\n# Default is \" - \"";
336 CONF_TXT_T cf_text_abook_formats[] = "This is a list of formats for address books. Each entry in the list is made\n# up of space-delimited tokens telling which fields are displayed and in\n# which order. See help text";
338 CONF_TXT_T cf_text_index_format[] = "This gives a format for displaying the index. It is made\n# up of space-delimited tokens telling which fields are displayed and in\n# which order. See help text";
340 CONF_TXT_T cf_text_overlap[] = "The number of lines of overlap when scrolling through message text";
342 CONF_TXT_T cf_text_maxremstreams[] = "The maximum number of non-stayopen remote connections that Alpine will use";
344 CONF_TXT_T cf_text_permlocked[] = "A list of folders that should be left open once opened (INBOX is implicit)";
346 CONF_TXT_T cf_text_margin[] = "Number of lines from top and bottom of screen where single\n# line scrolling occurs.";
348 CONF_TXT_T cf_text_stat_msg_delay[] = "The number of seconds to sleep after writing a status message";
350 CONF_TXT_T cf_text_busy_cue_rate[] = "Number of times per-second to update busy cue messages";
352 CONF_TXT_T cf_text_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";
354 CONF_TXT_T cf_text_mailcheck[] = "The approximate number of seconds between checks for new mail";
356 CONF_TXT_T cf_text_mailchecknoncurr[] = "The approximate number of seconds between checks for new mail in folders\n# other than the current folder and inbox.\n# Default is same as mail-check-interval";
358 CONF_TXT_T cf_text_maildropcheck[] = "The minimum number of seconds between checks for new mail in a Mail Drop.\n# This is always effectively at least as large as the mail-check-interval";
360 CONF_TXT_T cf_text_nntprange[] = "For newsgroups accessed using NNTP, only messages numbered in the range\n# lastmsg-range+1 to lastmsg will be considered";
362 CONF_TXT_T cf_text_news_active[] = "Path and filename of news configuration's active file.\n# The default is typically \"/usr/lib/news/active\".";
364 CONF_TXT_T cf_text_news_spooldir[] = "Directory containing system's news data.\n# The default is typically \"/usr/spool/news\"";
366 CONF_TXT_T cf_text_upload_cmd[] = "Path and filename of the program used to upload text from your terminal\n# emulator's into Alpine's composer.";
368 CONF_TXT_T cf_text_upload_prefix[] = "Text sent to terminal emulator prior to invoking the program defined by\n# the upload-command variable.\n# Note: _FILE_ will be replaced with the temporary file used in the upload.";
370 CONF_TXT_T cf_text_download_cmd[] = "Path and filename of the program used to download text via your terminal\n# emulator from Alpine's export and save commands.";
372 CONF_TXT_T cf_text_download_prefix[] = "Text sent to terminal emulator prior to invoking the program defined by\n# the download-command variable.\n# Note: _FILE_ will be replaced with the temporary file used in the download.";
374 CONF_TXT_T cf_text_goto_default[] = "Sets the default folder and collection offered at the Goto Command's prompt.";
376 CONF_TXT_T cf_text_mailcap_path[] = "Sets the search path for the mailcap configuration file.\n# NOTE: colon delimited under UNIX, semi-colon delimited under DOS/Windows/OS2.";
378 CONF_TXT_T cf_text_mimetype_path[] = "Sets the search path for the mimetypes configuration file.\n# NOTE: colon delimited under UNIX, semi-colon delimited under DOS/Windows/OS2.";
380 CONF_TXT_T cf_text_newmail_fifo_path[] = "Sets the filename for the newmail fifo (named pipe). Unix only.";
382 CONF_TXT_T cf_text_nmw_width[] = "Sets the width for the NewMail screen.";
384 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.";
386 CONF_TXT_T cf_text_debug_mem[] = "Debug-memory is obsolete";
388 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).";
390 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.";
392 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.";
394 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.";
396 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.";
398 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.";
400 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.";
402 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\")";
404 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.";
406 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.";
408 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.";
410 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.";
412 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.";
414 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.";
416 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\")";
418 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.";
420 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.";
422 CONF_TXT_T cf_text_elm_style_save[] = "Elm-style-save is obsolete, use saved-msg-name-rule";
424 CONF_TXT_T cf_text_header_in_reply[] = "Header-in-reply is obsolete, use include-header-in-reply in feature-list";
426 CONF_TXT_T cf_text_feature_level[] = "Feature-level is obsolete, use feature-list";
428 CONF_TXT_T cf_text_old_style_reply[] = "Old-style-reply is obsolete, use signature-at-bottom in feature-list";
430 CONF_TXT_T cf_text_compose_mime[] = "Compose-mime is obsolete";
432 CONF_TXT_T cf_text_show_all_characters[] = "Show-all-characters is obsolete";
434 CONF_TXT_T cf_text_save_by_sender[] = "Save-by-sender is obsolete, use saved-msg-name-rule";
436 CONF_TXT_T cf_text_file_dir[] = "Default directory used for Attachment handling (attach and save)\n# and Export command output";
438 CONF_TXT_T cf_text_folder_extension[] = "Folder-extension is obsolete";
440 CONF_TXT_T cf_text_normal_foreground_color[] = "Choose: black, blue, green, cyan, red, magenta, yellow, or white.";
442 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.";
444 CONF_TXT_T cf_text_newsrc_path[] = "Full path and name of NEWSRC file";
447 /*----------------------------------------------------------------------
448 These are the variables that control a number of pine functions. They
449 come out of the .pinerc and the /usr/local/lib/pine.conf files. Some can
450 be set by the user while in Alpine. Eventually all the local ones should
451 be so and maybe the global ones too.
453 Each variable can have a command-line, user, global, and current value.
454 All of these values are malloc'd. The user value is the one read out of
455 the user's .pinerc, the global value is the one from the system pine
456 configuration file. There are often defaults for the global values, set
457 at the start of init_vars(). Perhaps someday there will be group values.
458 The current value is the one that is actually in use.
459 ----*/
460 /* name is_changed_val
461 remove_quotes |
462 is_outermost | |
463 is_onlymain | | |
464 is_fixed | | | |
465 is_list | | | | |
466 is_global | | | | | |
467 is_user | | | | | | |
468 been_written | | | | | | | |
469 is_used | | | | | | | | |
470 is_obsolete | | | | | | | | | |
471 | | | | | | | | | | |
472 (on following line) description | | | | | | | | | | |
473 | | | | | | | | | | | |
474 | | | | | | | | | | | | */
475 static struct variable variables[] = {
476 {"personal-name", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
477 NULL, cf_text_personal_name},
479 #if defined(DOS) || defined(OS2)
480 /* Have to have this on DOS, PC's, Macs, etc... */
481 "user-id", 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0,
482 #else /* Don't allow on UNIX machines for some security */
483 "user-id", 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0,
484 #endif
485 "User ID", cf_text_user_id},
486 {"user-domain", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
487 NULL, cf_text_user_domain},
488 {"smtp-server", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
489 "SMTP Server (for sending)", cf_text_smtp_server},
490 {"nntp-server", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
491 "NNTP Server (for news)", cf_text_nntp_server},
492 {"inbox-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
493 NULL, cf_text_inbox_path},
494 {"incoming-archive-folders", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
495 NULL, cf_text_archived_folders},
496 {"pruned-folders", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
497 NULL, cf_text_pruned_folders},
498 {"default-fcc", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
499 "Default Fcc (File carbon copy)", cf_text_default_fcc},
500 {"default-saved-msg-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
501 "Default Saved Message Folder", cf_text_default_saved},
502 {"postponed-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
503 NULL, cf_text_postponed_folder},
504 {"read-message-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
505 NULL, cf_text_read_message_folder},
506 {"form-letter-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
507 NULL, cf_text_form_letter_folder},
508 {"trash-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
509 NULL, cf_text_trash_folder},
510 {"literal-signature", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
511 NULL, cf_text_literal_sig},
512 {"signature-file", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
513 NULL, cf_text_signature_file},
514 {"feature-list", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
515 NULL, cf_text_feature_list},
516 {"initial-keystroke-list", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
517 NULL, cf_text_initial_keystroke_list},
518 {"default-composer-hdrs", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
519 "Default Composer Headers", cf_text_default_composer_hdrs},
520 {"customized-hdrs", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
521 "Customized Headers", cf_text_customized_hdrs},
522 {"viewer-hdrs", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
523 "Viewer Headers", cf_text_view_headers},
524 {"viewer-margin-left", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
525 NULL, cf_text_view_margin_left},
526 {"viewer-margin-right", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
527 NULL, cf_text_view_margin_right},
528 {"quote-suppression-threshold", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
529 NULL, cf_text_quote_suppression},
530 {"saved-msg-name-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
531 "Saved Message Name Rule", cf_text_save_msg_name_rule},
532 {"fcc-name-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
533 NULL, cf_text_fcc_name_rule},
534 {"sort-key", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
535 NULL, cf_text_sort_key},
536 {"addrbook-sort-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
537 "Address Book Sort Rule", cf_text_addrbook_sort_rule},
538 {"folder-sort-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
539 NULL, cf_text_folder_sort_rule},
540 {"goto-default-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
541 NULL, cf_text_goto_default},
542 {"incoming-startup-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
543 NULL, cf_text_inc_startup},
544 {"pruning-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
545 NULL, cf_pruning_rule},
546 {"folder-reopen-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
547 NULL, cf_reopen_rule},
548 {"threading-display-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
549 NULL, cf_text_thread_disp_style},
550 {"threading-index-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
551 NULL, cf_text_thread_index_style},
552 {"threading-indicator-character", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
553 NULL, cf_text_thread_more_char},
554 {"threading-expanded-character", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
555 NULL, cf_text_thread_exp_char},
556 {"threading-lastreply-character", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
557 "Threading Last Reply Character", cf_text_thread_lastreply_char},
558 #ifndef _WINDOWS
559 {"display-character-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
560 NULL, cf_text_disp_char_set},
561 {"character-set", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
562 NULL, cf_text_old_char_set},
563 {"keyboard-character-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
564 NULL, cf_text_key_char_set},
565 #endif /* ! _WINDOWS */
566 {"posting-character-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
567 NULL, cf_text_post_character_set},
568 {"unknown-character-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
569 NULL, cf_text_unk_character_set},
570 {"editor", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
571 NULL, cf_text_editor},
572 {"speller", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
573 NULL, cf_text_speller},
574 #ifdef _WINDOWS
575 {"aspell-dictionary-list", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
576 "Aspell Dictionaries", cf_text_speller_dictionary},
577 #endif /* _WINDOWS */
578 {"composer-wrap-column", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
579 NULL, cf_text_fillcol},
580 {"reply-indent-string", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
581 NULL, cf_text_replystr},
582 {"reply-leadin", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
583 NULL, cf_text_replyintro},
584 {"quote-replace-string", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
585 NULL, cf_text_quotereplstr},
586 {"composer-word-separators", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
587 NULL, cf_text_wordsep},
588 {"empty-header-message", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
589 NULL, cf_text_emptyhdr},
590 {"image-viewer", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
591 NULL, cf_text_image_viewer},
592 {"use-only-domain-name", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
593 NULL, cf_text_use_only_domain_name},
594 {"bugs-fullname", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
595 NULL, cf_text_bugs_fullname},
596 {"bugs-address", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
597 NULL, cf_text_bugs_address},
598 {"bugs-additional-data", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
599 NULL, cf_text_bugs_extras},
600 {"suggest-fullname", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
601 NULL, cf_text_suggest_fullname},
602 {"suggest-address", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
603 NULL, cf_text_suggest_address},
604 {"local-fullname", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
605 NULL, cf_text_local_fullname},
606 {"local-address", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
607 NULL, cf_text_local_address},
608 {"forced-abook-entry", 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0,
609 NULL, cf_text_forced_abook},
610 {"kblock-passwd-count", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
611 NULL, cf_text_kblock_passwd},
612 {"display-filters", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
613 NULL, cf_text_in_fltr},
614 {"sending-filters", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
615 NULL, cf_text_out_fltr},
616 {"alt-addresses", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
617 "Alternate Addresses", cf_text_alt_addrs},
618 {"keywords", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
619 NULL, cf_text_keywords},
620 {"keyword-surrounding-chars", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
621 "Keyword Surrounding Characters", cf_text_kw_braces},
622 {"opening-text-separator-chars", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
623 "Opening Text Separator Characters", cf_text_opening_sep},
624 {"addressbook-formats", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
625 "Address Book Formats", cf_text_abook_formats},
626 {"index-format", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
627 NULL, cf_text_index_format},
628 {"viewer-overlap", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
629 NULL, cf_text_overlap},
630 {"scroll-margin", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
631 NULL, cf_text_margin},
632 {"status-message-delay", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
633 NULL, cf_text_stat_msg_delay},
634 {"busy-cue-rate", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
635 NULL, cf_text_busy_cue_rate},
636 {"mailcap-check-interval", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
637 NULL, cf_text_psleep},
638 {"mail-check-interval", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
639 NULL, cf_text_mailcheck},
640 {"mail-check-interval-noncurrent", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
641 NULL, cf_text_mailchecknoncurr},
642 {"maildrop-check-minimum", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
643 NULL, cf_text_maildropcheck},
644 {"nntp-range", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
645 "NNTP Range", cf_text_nntprange},
646 {"newsrc-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
647 NULL, cf_text_newsrc_path},
648 {"news-active-file-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
649 NULL, cf_text_news_active},
650 {"news-spool-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
651 NULL, cf_text_news_spooldir},
652 {"upload-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
653 NULL, cf_text_upload_cmd},
654 {"upload-command-prefix", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
655 NULL, cf_text_upload_prefix},
656 {"download-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
657 NULL, cf_text_download_cmd},
658 {"download-command-prefix", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
659 NULL, cf_text_download_prefix},
660 {"mailcap-search-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
661 NULL, cf_text_mailcap_path},
662 {"mimetype-search-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
663 NULL, cf_text_mimetype_path},
664 {"url-viewers", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
665 "URL-Viewers", cf_text_browser},
666 {"default-directories", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
667 "Extra Directories for Save", cf_text_history},
668 {"max-remote-connections", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
669 "Maximum Remote Connections", cf_text_maxremstreams},
670 {"stay-open-folders", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
671 "Stayopen Folders", cf_text_permlocked},
672 {"incoming-check-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
673 NULL, cf_text_inc_check_timeo},
674 {"incoming-check-interval", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
675 NULL, cf_text_inc_check_interval},
676 {"incoming-check-interval-secondary", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
677 NULL, cf_text_inc_second_check_interval},
678 {"incoming-check-list", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
679 NULL, cf_text_inc_check_list},
680 {"dead-letter-files", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
681 NULL, cf_text_deadlets},
682 #if !defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)
683 {"newmail-fifo-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
684 "NewMail FIFO Path", cf_text_newmail_fifo_path},
685 #endif
686 {"newmail-window-width", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
687 "NewMail Window Width", cf_text_nmw_width},
689 * Starting here, the variables are hidden in the Setup/Config screen.
690 * They are exposed if feature expose-hidden-config is set.
692 {"incoming-folders", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
693 NULL, cf_text_incoming_folders},
694 {"mail-directory", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
695 NULL, cf_text_mail_directory},
696 {"folder-collections", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
697 NULL, cf_text_folder_collections},
698 {"news-collections", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
699 NULL, cf_text_news_collections},
700 {"address-book", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
701 NULL, cf_text_address_book},
702 {"global-address-book", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
703 NULL, cf_text_global_address_book},
704 {"standard-printer", 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0,
705 NULL, cf_text_standard_printer},
706 {"last-time-prune-questioned", 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0,
707 NULL, cf_text_last_time_prune_quest},
708 {"last-version-used", 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0,
709 NULL, cf_text_last_version_used},
710 {"sendmail-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
711 NULL, cf_text_sendmail_path},
712 {"operating-dir", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
713 NULL, cf_text_oper_dir},
714 {"user-input-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
715 NULL, cf_text_user_input_timeo},
716 /* OBSOLETE */
717 #ifdef DEBUGJOURNAL
718 {"debug-memory", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
719 NULL, cf_text_debug_mem},
720 #endif
721 {"tcp-open-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
722 "TCP Open Timeout", cf_text_tcp_open_timeo},
723 {"tcp-read-warning-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
724 "TCP Read Warning Timeout", cf_text_tcp_read_timeo},
725 {"tcp-write-warning-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
726 "TCP Write Warning Timeout", cf_text_tcp_write_timeo},
727 {"tcp-query-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
728 "TCP Query Timeout", cf_text_tcp_query_timeo},
729 {"close-connection-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
730 NULL, cf_text_close_connection_timeo},
731 {"rsh-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
732 NULL, cf_text_rsh_command},
733 {"rsh-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
734 NULL, cf_text_rsh_path},
735 {"rsh-open-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
736 NULL, cf_text_rsh_open_timeo},
737 {"ssh-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
738 NULL, cf_text_ssh_command},
739 {"ssh-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
740 NULL, cf_text_ssh_path},
741 {"ssh-open-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
742 NULL, cf_text_ssh_open_timeo},
743 {"new-version-threshold", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
744 NULL, cf_text_version_threshold},
745 {"disable-these-drivers", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
746 NULL, cf_text_disable_drivers},
747 {"disable-these-authenticators", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
748 NULL, cf_text_disable_auths},
749 {"encryption-protocol-range", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
750 NULL, cf_text_encryption_range},
751 {"remote-abook-metafile", 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0,
752 NULL, cf_text_remote_abook_metafile},
753 {"remote-abook-history", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
754 NULL, cf_text_remote_abook_history},
755 {"remote-abook-validity", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
756 NULL, cf_text_remote_abook_validity},
757 {"printer", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
758 NULL, cf_text_printer},
759 {"personal-print-command", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
760 NULL, cf_text_personal_print_command},
761 {"personal-print-category", 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0,
762 NULL, cf_text_personal_print_cat},
763 {"patterns", 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
764 NULL, cf_text_old_patterns},
765 {"patterns-roles", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
766 NULL, cf_text_patterns},
767 {"patterns-filters2", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
768 "Patterns Filters", cf_text_patterns},
769 {"patterns-filters", 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
770 NULL, cf_text_old_filters},
771 {"patterns-scores2", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
772 "Patterns Scores", cf_text_patterns},
773 {"patterns-scores", 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
774 NULL, cf_text_old_scores},
775 {"patterns-indexcolors", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
776 NULL, cf_text_patterns},
777 {"patterns-other", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
778 NULL, cf_text_patterns},
779 {"patterns-search", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
780 NULL, cf_text_patterns},
781 /* OBSOLETE VARS */
782 {"elm-style-save", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
783 NULL, cf_text_elm_style_save},
784 {"header-in-reply", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
785 NULL, cf_text_header_in_reply},
786 {"feature-level", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
787 NULL, cf_text_feature_level},
788 {"old-style-reply", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
789 NULL, cf_text_old_style_reply},
790 {"compose-mime", 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
791 NULL, cf_text_compose_mime},
792 {"show-all-characters", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
793 NULL, cf_text_show_all_characters},
794 {"save-by-sender", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
795 NULL, cf_text_save_by_sender},
796 #if defined(DOS) || defined(OS2)
797 {"file-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
798 NULL, cf_text_file_dir},
799 {"folder-extension", 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0,
800 NULL, cf_text_folder_extension},
801 #endif
802 #ifndef _WINDOWS
803 {"color-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
804 NULL, cf_text_color_style},
805 #endif
806 {"current-indexline-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
807 NULL, cf_text_current_indexline_style},
808 {"titlebar-color-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
809 NULL, cf_text_titlebar_color_style},
810 {"normal-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
811 NULL, cf_text_normal_foreground_color},
812 {"normal-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
813 {"reverse-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
814 {"reverse-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
815 {"title-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
816 {"title-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
817 {"title-closed-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
818 {"title-closed-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
819 {"folder-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
820 {"folder-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
821 {"directory-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
822 {"directory-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
823 {"folder-list-text-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
824 {"folder-list-text-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
825 {"status-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
826 {"status-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
827 {"keylabel-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
828 {"keylabel-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
829 {"keyname-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
830 {"keyname-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
831 {"selectable-item-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
832 {"selectable-item-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
833 {"meta-message-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
834 {"meta-message-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
835 {"quote1-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
836 {"quote1-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
837 {"quote2-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
838 {"quote2-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
839 {"quote3-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
840 {"quote3-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
841 {"incoming-unseen-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
842 {"incoming-unseen-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
843 {"signature-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
844 {"signature-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
845 {"prompt-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
846 {"prompt-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
847 {"header-general-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
848 {"header-general-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
849 {"index-to-me-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
850 {"index-to-me-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
851 {"index-important-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
852 {"index-important-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
853 {"index-deleted-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
854 {"index-deleted-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
855 {"index-answered-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
856 {"index-answered-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
857 {"index-new-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
858 {"index-new-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
859 {"index-recent-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
860 {"index-recent-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
861 {"index-forward-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
862 {"index-forward-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
863 {"index-unseen-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
864 {"index-unseen-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
865 {"index-highpriority-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
866 {"index-highpriority-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
867 {"index-lowpriority-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
868 {"index-lowpriority-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
869 {"index-arrow-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
870 {"index-arrow-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
871 {"index-subject-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
872 {"index-subject-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
873 {"index-from-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
874 {"index-from-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
875 {"index-opening-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
876 {"index-opening-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
877 {"index-token-colors", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
878 NULL, cf_text_index_token_color},
879 {"viewer-hdr-colors", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
880 "Viewer Header Colors", cf_text_view_hdr_color},
881 {"keyword-colors", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
882 NULL, cf_text_kw_colors},
883 #ifdef _WINDOWS
884 {"font-name", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
885 NULL, "name and size of font."},
886 {"font-size", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
887 {"font-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
888 {"font-char-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
889 {"print-font-name", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
890 NULL, "name and size of printer font."},
891 {"print-font-size", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
892 {"print-font-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
893 {"print-font-char-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
894 {"window-position", 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0,
895 NULL, cf_text_window_position},
896 {"cursor-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
897 #endif /* _WINDOWS */
898 #ifdef SMIME
899 {"smime-public-cert-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
900 "S/MIME - Public Cert Directory", cf_text_publiccertdir},
901 {"smime-public-cert-container", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
902 "S/MIME - Public Cert Container", cf_text_publiccertcontainer},
903 {"smime-private-key-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
904 "S/MIME - Private Key Directory", cf_text_privatekeydir},
905 {"smime-private-key-container", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
906 "S/MIME - Private Key Container", cf_text_privatekeycontainer},
907 {"smime-cacert-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
908 "S/MIME - Cert Authority Directory", cf_text_cacertdir},
909 {"smime-cacert-container", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
910 "S/MIME - Cert Authority Container", cf_text_cacertcontainer},
911 #endif /* SMIME */
912 #ifdef ENABLE_LDAP
913 {"ldap-servers", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
914 "LDAP Servers", cf_text_ldap_server},
915 #endif /* ENABLE_LDAP */
916 {"rss-news", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
917 "WEB ALPINE - RSS News", cf_text_rss_news},
918 {"rss-weather", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
919 "WEB ALPINE - RSS Weather", cf_text_rss_weather},
920 {"wp-indexheight", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
921 "WEB ALPINE - Index Height", cf_text_wp_indexheight},
922 {"wp-indexlines", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
923 "WEB ALPINE - Index Lines", cf_text_wp_indexlines},
924 {"wp-aggstate", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
925 "WEB ALPINE - Aggregate State", cf_text_wp_aggstate},
926 {"wp-state", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
927 "WEB ALPINE - Cross Session State", cf_text_wp_state},
928 {"wp-columns", 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0,
929 "WEB ALPINE - Columns", cf_text_wp_columns},
930 {NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL,NULL}
934 struct variable *
935 var_from_name(char *name)
937 struct variable *v;
938 int i;
940 if(!(name && name[0]))
941 return(NULL);
943 for(i = 0; (v = &variables[i]) && v->name; i++)
944 if(!strucmp(v->name,name))
945 return(v);
947 return(NULL);
951 void
952 init_init_vars(struct pine *ps)
954 ps->vars = variables;
958 #define DSIZE (25000)
959 /* this is just like dprint except it prints to a char * */
960 #ifdef DEBUG
961 #define mprint(n,x) { \
962 if(debug >= (n)){ \
963 snprintf x ; \
964 db += strlen(db); \
967 #else
968 #define mprint(n,x)
969 #endif
972 * this was split out from init_vars so we can get at the
973 * pinerc location sooner.
975 void
976 init_pinerc(struct pine *ps, char **debug_out)
978 char buf[MAXPATH+1], *p, *db;
979 #if defined(DOS) || defined(OS2)
980 char buf2[MAXPATH+1], l_pinerc[MAXPATH+1];
981 int nopinerc = 0, confregset = -1;
982 register struct variable *vars = ps->vars;
983 #endif
985 #ifdef DEBUG
987 * Since this routine is called before we've had a chance to set up
988 * the debug file for output, we put the debugging into memory and
989 * pass it back to the caller for use after init_debug(). We just
990 * allocate plenty of space.
992 if(debug_out){
993 db = *debug_out = (char *)fs_get(DSIZE * sizeof(char));
994 db[0] = '\0';
996 #endif
998 mprint(2, (db, DSIZE-(db-(*debug_out)), "\n -- init_pinerc --\n\n"));
1000 #if defined(DOS) || defined(OS2)
1002 * Rules for the config/support file locations under DOS are:
1004 * 1) The location of the PINERC is searched for in the following
1005 * order of precedence:
1006 * - File pointed to by '-p' command line option
1007 * - File pointed to by PINERC environment variable
1008 * - $HOME\pine
1009 * - same dir as argv[0]
1011 * 2) The HOME environment variable, if not set, defaults to
1012 * root of the current working drive (see alpine.c)
1014 * 3) The default for external files (PINE.SIG and ADDRBOOK) is the
1015 * same directory as the pinerc
1017 * 4) The support files (PINE.HLP and PINE.NDX) are expected to be in
1018 * the same directory as PINE.EXE.
1021 if(ps->prc){
1022 mprint(2, (db, DSIZE-(db-(*debug_out)),
1023 "Personal config \"%.100s\" comes from command line\n",
1024 (ps->prc && ps->prc->name) ? ps->prc->name : "<no name>"));
1026 else{
1027 mprint(2, (db, DSIZE-(db-(*debug_out)),
1028 "Personal config not set on cmdline, checking for $PINERC\n"));
1032 * First, if prc hasn't been set by a command-line -p, check to see
1033 * if PINERC is in the environment. If so, treat it just like we
1034 * would have treated it if it were a command-line arg.
1036 if(!ps->prc && (p = getenv("PINERC")) && *p){
1037 char path[MAXPATH], dir[MAXPATH];
1039 if(IS_REMOTE(p) || is_absolute_path(p)){
1040 strncpy(path, p, sizeof(path)-1);
1041 path[sizeof(path)-1] = '\0';
1043 else{
1044 getcwd(dir, sizeof(dir));
1045 build_path(path, dir, p, sizeof(path));
1048 if(!IS_REMOTE(p))
1049 ps->pinerc = cpystr(path);
1051 ps->prc = new_pinerc_s(path);
1053 if(ps->prc){
1054 mprint(2, (db, DSIZE-(db-(*debug_out)),
1055 " yes, personal config \"%.100s\" comes from $PINERC\n",
1056 (ps->prc && ps->prc->name) ? ps->prc->name : "<no name>"));
1061 * Pinerc used to be the name of the pinerc file. Then we added
1062 * the possibility of the pinerc file being remote, and we replaced
1063 * the variable pinerc with the structure prc. Unfortunately, some
1064 * parts of pine rely on the fact that pinerc is the name of the
1065 * pinerc _file_, and use the directory that the pinerc file is located
1066 * in for their own purposes. We want to preserve that so things will
1067 * keep working. So, even if the real pinerc is remote, we need to
1068 * put the name of a pinerc file in the pinerc variable so that the
1069 * directory which contains that file is writable. The file itself
1070 * doesn't have to exist for this purpose, since we are really only
1071 * using the name of the directory containing the file. Twisted.
1072 * (Alternatively, we could fix all of the code that uses the pinerc
1073 * variable for this purpose to use a new variable which really is
1074 * just a directory.) hubert 2000-sep
1076 * There are 3 cases. If pinerc is already set that means that the user
1077 * gave either a -p pinerc or an environment pinerc that is a local file,
1078 * and we are done. If pinerc is not set, then either prc is set or not.
1079 * If prc is set then the -p arg or PINERC value is a remote pinerc.
1080 * In that case we need to find a local directory to use, and put that
1081 * directory in the pinerc variable (with a fake filename tagged on).
1082 * If prc is not set, then user hasn't told us anything so we have to
1083 * try to find the default pinerc file by looking down the path of
1084 * possibilities. When we find it, we'll also use that directory.
1086 if(!ps->pinerc){
1087 *l_pinerc = '\0';
1088 *buf = '\0';
1090 if(ps->prc){ /* remote pinerc case */
1092 * We don't give them an l_pinerc unless they tell us where
1093 * to put it.
1095 if(ps->aux_files_dir)
1096 build_path(l_pinerc, ps->aux_files_dir, SYSTEM_PINERC,
1097 sizeof(l_pinerc));
1098 else{
1100 * Search for a writable directory.
1101 * Mimic what happens in !prc for local case, except we
1102 * don't need to look for the actual file.
1105 /* check if $HOME\PINE is writable */
1106 build_path(buf2, ps->home_dir, DF_PINEDIR, sizeof(buf2));
1107 if(is_writable_dir(buf2) == 0)
1108 build_path(l_pinerc, buf2, SYSTEM_PINERC, sizeof(l_pinerc));
1109 else{ /* $HOME\PINE not a writable dir */
1110 /* use this unless registry redirects us */
1111 build_path(l_pinerc, ps->pine_dir, SYSTEM_PINERC,
1112 sizeof(l_pinerc));
1113 #ifdef _WINDOWS
1114 /* if in registry, use that value */
1115 if(mswin_reg(MSWR_OP_GET, MSWR_PINE_RC, buf2, sizeof(buf2))
1116 && !IS_REMOTE(buf2)){
1117 strncpy(l_pinerc, buf2, sizeof(l_pinerc)-1);
1118 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1120 #endif
1124 else{ /* searching for pinerc file to use */
1126 * Buf2 is $HOME\PINE. If $HOME is not explicitly set,
1127 * it defaults to the current working drive (often C:).
1128 * See alpine.c to see how it is initially set.
1131 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, searching...\n"));
1132 build_path(buf2, ps->home_dir, DF_PINEDIR, sizeof(buf2));
1133 mprint(2, (db, DSIZE-(db-(*debug_out)),
1134 " checking for writable %.100s dir \"%.100s\" off of homedir\n",
1135 DF_PINEDIR, buf2));
1136 if(is_writable_dir(buf2) == 0){
1138 * $HOME\PINE exists and is writable.
1139 * See if $HOME\PINE\PINERC exists.
1141 build_path(buf, buf2, SYSTEM_PINERC, sizeof(buf));
1142 strncpy(l_pinerc, buf, sizeof(l_pinerc)-1);
1143 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1144 mprint(2, (db, DSIZE-(db-(*debug_out)), " yes, now checking for file \"%.100s\"\n",
1145 buf));
1146 if(can_access(buf, ACCESS_EXISTS) == 0){ /* found it! */
1148 * Buf is what we were looking for.
1149 * It is local and can be used for the directory, too.
1151 mprint(2, (db, DSIZE-(db-(*debug_out)), " found it\n"));
1153 else{
1155 * No $HOME\PINE\PINERC, look for
1156 * one in same dir as PINE.EXE.
1158 build_path(buf2, ps->pine_dir, SYSTEM_PINERC,
1159 sizeof(buf2));
1160 mprint(2, (db, DSIZE-(db-(*debug_out)),
1161 " no, checking for \"%.100s\" in pine.exe dir\n",
1162 buf2));
1163 if(can_access(buf2, ACCESS_EXISTS) == 0){
1164 /* found it! */
1165 mprint(2, (db, DSIZE-(db-(*debug_out)), " found it\n"));
1166 strncpy(buf, buf2, sizeof(buf)-1);
1167 buf[sizeof(buf)-1] = '\0';
1168 strncpy(l_pinerc, buf2, sizeof(l_pinerc)-1);
1169 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1171 else{
1172 #ifdef _WINDOWS
1173 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, checking in registry\n"));
1174 if(mswin_reg(MSWR_OP_GET, MSWR_PINE_RC,
1175 buf2, sizeof(buf2))){
1176 strncpy(buf, buf2, sizeof(buf)-1);
1177 buf[sizeof(buf)-1] = '\0';
1178 if(!IS_REMOTE(buf2)){
1179 strncpy(l_pinerc, buf2, sizeof(l_pinerc)-1);
1180 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1183 * Now buf is the pinerc to be used, l_pinerc is
1184 * the directory, which may be either same as buf
1185 * or it may be $HOME\PINE if registry gives us
1186 * a remote pinerc.
1188 mprint(2, (db, DSIZE-(db-(*debug_out)), " found \"%.100s\" in registry\n",
1189 buf));
1191 else{
1192 nopinerc = 1;
1193 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found, asking user\n"));
1195 #else
1196 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found\n"));
1197 #endif
1202 * Buf is the pinerc (could be remote if from registry)
1203 * and l_pinerc is the local pinerc, which may not exist.
1206 else{ /* $HOME\PINE not a writable dir */
1208 * We notice that the order of checking in the registry
1209 * and checking in the ALPINE.EXE directory are different
1210 * in this case versus the is_writable_dir(buf2) case, and
1211 * that does sort of look like a bug. However,
1212 * we don't think this is a bug since we did it on purpose
1213 * a long time ago. So even though we can't remember why
1214 * it is this way, we think we would rediscover why if we
1215 * changed it! So we won't change it.
1219 * Change the default to use to the ALPINE.EXE directory.
1221 build_path(buf, ps->pine_dir, SYSTEM_PINERC, sizeof(buf));
1222 strncpy(l_pinerc, buf, sizeof(l_pinerc)-1);
1223 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1224 #ifdef _WINDOWS
1225 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, not writable, checking in registry\n"));
1226 /* if in registry, use that value */
1227 if(mswin_reg(MSWR_OP_GET, MSWR_PINE_RC, buf2, sizeof(buf2))){
1228 strncpy(buf, buf2, sizeof(buf)-1);
1229 buf[sizeof(buf)-1] = '\0';
1230 mprint(2, (db, DSIZE-(db-(*debug_out)), " found \"%.100s\" in registry\n",
1231 buf));
1232 if(!IS_REMOTE(buf)){
1233 strncpy(l_pinerc, buf, sizeof(l_pinerc)-1);
1234 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1237 else{
1238 mprint(2, (db, DSIZE-(db-(*debug_out)),
1239 " no, checking for \"%.100s\" in alpine.exe dir\n",
1240 buf));
1242 if(can_access(buf, ACCESS_EXISTS) == 0){
1243 mprint(2, (db, DSIZE-(db-(*debug_out)), " found it\n"));
1245 else{
1246 nopinerc = 1;
1247 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found, asking user\n"));
1250 #else
1251 mprint(2, (db, DSIZE-(db-(*debug_out)),
1252 " no, checking for \"%.100s\" in alpine.exe dir\n",
1253 buf));
1255 if(can_access(buf, ACCESS_EXISTS) == 0){
1256 mprint(2, (db, DSIZE-(db-(*debug_out)), " found it\n"));
1258 else{
1259 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found, creating it\n"));
1261 #endif
1265 * When we get here we have buf set to the name of the
1266 * pinerc, which could be local or remote. We have l_pinerc
1267 * set to the same as buf if buf is local, and set to another
1268 * name otherwise, hopefully contained in a writable directory.
1270 #ifdef _WINDOWS
1271 if(nopinerc || ps_global->install_flag){
1272 char buf3[MAXPATH+1];
1274 confregset = 0;
1275 strncpy(buf3, buf, MAXPATH);
1276 buf3[MAXPATH] = '\0';
1277 if(os_config_dialog(buf3, MAXPATH,
1278 &confregset, nopinerc) == 0){
1279 strncpy(buf, buf3, MAXPATH);
1280 buf[MAXPATH] = '\0';
1281 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found, creating it\n"));
1282 mprint(2, (db, DSIZE-(db-(*debug_out)), " user says use \"%.100s\"\n", buf));
1283 if(!IS_REMOTE(buf)){
1284 strncpy(l_pinerc, buf, MAXPATH);
1285 l_pinerc[MAXPATH] = '\0';
1288 else{
1289 exit(-1);
1292 #endif
1293 ps->prc = new_pinerc_s(buf);
1296 ps->pinerc = cpystr(l_pinerc);
1299 #if defined(DOS) || defined(OS2)
1301 * The goal here is to set the auxiliary directory in the pinerc variable.
1302 * We are making the assumption that any reference to the pinerc variable
1303 * after this point is used only as a directory in which to store things,
1304 * with the prc variable being the preferred place to store pinerc location.
1305 * If -aux isn't set, then there is no change. -jpf 08/2001
1307 if(ps->aux_files_dir){
1308 l_pinerc[0] = '\0';
1309 build_path(l_pinerc, ps->aux_files_dir, SYSTEM_PINERC,
1310 sizeof(l_pinerc));
1311 if(ps->pinerc) fs_give((void **)&ps->pinerc);
1312 ps->pinerc = cpystr(l_pinerc);
1313 mprint(2, (db, DSIZE-(db-(*debug_out)), "Setting aux_files_dir to \"%.100s\"\n",
1314 ps->aux_files_dir));
1316 #endif
1318 #ifdef _WINDOWS
1319 if(confregset && (ps->update_registry != UREG_NEVER_SET))
1320 mswin_reg(MSWR_OP_SET | ((ps->update_registry == UREG_ALWAYS_SET)
1321 || confregset == 1 ? MSWR_OP_FORCE : 0),
1322 MSWR_PINE_RC,
1323 (ps->prc && ps->prc->name) ?
1324 ps->prc->name : ps->pinerc, (size_t)NULL);
1325 #endif
1328 * Now that we know the default for the PINERC, build NEWSRC default.
1329 * Backward compatibility makes this kind of funky. If what the
1330 * c-client thinks the NEWSRC should be exists *AND* it doesn't
1331 * already exist in the PINERC's dir, use c-client's default, otherwise
1332 * use the one next to the PINERC...
1334 p = last_cmpnt(ps->pinerc);
1335 buf[0] = '\0';
1336 if(p != NULL){
1337 strncpy(buf, ps->pinerc, MIN(p - ps->pinerc, sizeof(buf)-1));
1338 buf[MIN(p - ps->pinerc, sizeof(buf)-1)] = '\0';
1341 mprint(2, (db, DSIZE-(db-(*debug_out)), "Using directory \"%.100s\" for auxiliary files\n", buf));
1342 strncat(buf, "NEWSRC", sizeof(buf)-1-strlen(buf));
1344 if(!(p = (void *) mail_parameters(NULL, GET_NEWSRC, (void *)NULL))
1345 || can_access(p, ACCESS_EXISTS) < 0
1346 || can_access(buf, ACCESS_EXISTS) == 0){
1347 mail_parameters(NULL, SET_NEWSRC, (void *)buf);
1348 GLO_NEWSRC_PATH = cpystr(buf);
1350 else
1351 GLO_NEWSRC_PATH = cpystr(p);
1353 if(ps->pconf){
1354 mprint(2, (db, DSIZE-(db-(*debug_out)), "Global config \"%.100s\" comes from command line\n",
1355 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1357 else{
1358 mprint(2, (db, DSIZE-(db-(*debug_out)),
1359 "Global config not set on cmdline, checking for $PINECONF\n"));
1362 if(!ps->pconf && (p = getenv("PINECONF"))){
1363 ps->pconf = new_pinerc_s(p);
1364 if(ps->pconf){
1365 mprint(2, (db, DSIZE-(db-(*debug_out)),
1366 " yes, global config \"%.100s\" comes from $PINECONF\n",
1367 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1370 #ifdef _WINDOWS
1371 else if(!ps->pconf
1372 && mswin_reg(MSWR_OP_GET, MSWR_PINE_CONF, buf2, sizeof(buf2))){
1373 ps->pconf = new_pinerc_s(buf2);
1374 if(ps->pconf){
1375 mprint(2, (db, DSIZE-(db-(*debug_out)),
1376 " yes, global config \"%.100s\" comes from Registry\n",
1377 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1380 #endif
1381 if(!ps->pconf){
1382 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, there is no global config\n"));
1384 #ifdef _WINDOWS
1385 else if (ps->pconf && ps->pconf->name &&
1386 (ps->update_registry != UREG_NEVER_SET)){
1387 mswin_reg(MSWR_OP_SET | ((ps->update_registry == UREG_ALWAYS_SET)
1388 ? MSWR_OP_FORCE : 0),
1389 MSWR_PINE_CONF,
1390 ps->pconf->name, (size_t)NULL);
1392 #endif
1394 if(!ps->prc)
1395 ps->prc = new_pinerc_s(ps->pinerc);
1397 if(ps->exceptions){
1398 mprint(2, (db, DSIZE-(db-(*debug_out)),
1399 "Exceptions config \"%.100s\" comes from command line\n",
1400 ps->exceptions));
1402 else{
1403 mprint(2, (db, DSIZE-(db-(*debug_out)),
1404 "Exceptions config not set on cmdline, checking for $PINERCEX\n"));
1408 * Exceptions is done slightly differently from pinerc. Instead of setting
1409 * post_prc in args.c we just set the string and use it here. We do
1410 * that so that we can put it in the same directory as the pinerc if
1411 * exceptions is a relative name, and pinerc may not be set until here.
1413 * First, just like for pinerc, check environment variable if it wasn't
1414 * set on the command line.
1416 if(!ps->exceptions && (p = getenv("PINERCEX")) && *p){
1417 ps->exceptions = cpystr(p);
1418 if(ps->exceptions){
1419 mprint(2, (db, DSIZE-(db-(*debug_out)),
1420 " yes, exceptions config \"%.100s\" comes from $PINERCEX\n",
1421 ps->exceptions));
1426 * If still not set, try specific file in same dir as pinerc.
1427 * Only use it if the file exists.
1429 if(!ps->exceptions){
1430 p = last_cmpnt(ps->pinerc);
1431 buf[0] = '\0';
1432 if(p != NULL){
1433 strncpy(buf, ps->pinerc, MIN(p - ps->pinerc, sizeof(buf)-1));
1434 buf[MIN(p - ps->pinerc, sizeof(buf)-1)] = '\0';
1437 strncat(buf, "PINERCEX", sizeof(buf)-1-strlen(buf));
1439 mprint(2, (db, DSIZE-(db-(*debug_out)),
1440 " no, checking for default \"%.100s\" in pinerc dir\n", buf));
1441 if(can_access(buf, ACCESS_EXISTS) == 0) /* found it! */
1442 ps->exceptions = cpystr(buf);
1444 if(ps->exceptions){
1445 mprint(2, (db, DSIZE-(db-(*debug_out)),
1446 " yes, exceptions config \"%.100s\" comes from default\n",
1447 ps->exceptions));
1449 else{
1450 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, there is no exceptions config\n"));
1454 #else /* unix */
1456 if(ps->pconf){
1457 mprint(2, (db, DSIZE-(db-(*debug_out)), "Global config \"%.100s\" comes from command line\n",
1458 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1461 if(!ps->pconf){
1462 ps->pconf = new_pinerc_s(SYSTEM_PINERC);
1463 if(ps->pconf){
1464 mprint(2, (db, DSIZE-(db-(*debug_out)), "Global config \"%.100s\" is default\n",
1465 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1469 if(!ps->pconf){
1470 mprint(2, (db, DSIZE-(db-(*debug_out)), "No global config!\n"));
1473 if(ps->prc){
1474 mprint(2, (db, DSIZE-(db-(*debug_out)), "Personal config \"%.100s\" comes from command line\n",
1475 (ps->prc && ps->prc->name) ? ps->prc->name : "<no name>"));
1478 if(!ps->pinerc){
1479 build_path(buf, ps->home_dir, ".pinerc", sizeof(buf));
1480 ps->pinerc = cpystr(buf);
1483 if(!ps->prc){
1484 ps->prc = new_pinerc_s(ps->pinerc);
1485 if(ps->prc){
1486 mprint(2, (db, DSIZE-(db-(*debug_out)), "Personal config \"%.100s\" is default\n",
1487 (ps->prc && ps->prc->name) ? ps->prc->name : "<no name>"));
1491 if(!ps->prc){
1492 mprint(2, (db, DSIZE-(db-(*debug_out)), "No personal config!\n"));
1495 if(ps->exceptions){
1496 mprint(2, (db, DSIZE-(db-(*debug_out)),
1497 "Exceptions config \"%.100s\" comes from command line\n",
1498 ps->exceptions));
1502 * If not set, try specific file in same dir as pinerc.
1503 * Only use it if the file exists.
1505 if(!ps->exceptions){
1506 p = last_cmpnt(ps->pinerc);
1507 buf[0] = '\0';
1508 if(p != NULL){
1509 strncpy(buf, ps->pinerc, MIN(p - ps->pinerc, sizeof(buf)-1));
1510 buf[MIN(p - ps->pinerc, sizeof(buf)-1)] = '\0';
1513 strncat(buf, ".pinercex", sizeof(buf)-1-strlen(buf));
1514 mprint(2, (db, DSIZE-(db-(*debug_out)), "Exceptions config not set on cmdline\n checking for default \"%.100s\" in pinerc dir\n", buf));
1516 if(can_access(buf, ACCESS_EXISTS) == 0) /* found it! */
1517 ps->exceptions = cpystr(buf);
1519 if(ps->exceptions){
1520 mprint(2, (db, DSIZE-(db-(*debug_out)),
1521 " yes, exceptions config \"%.100s\" is default\n",
1522 ps->exceptions));
1524 else{
1525 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, there is no exceptions config\n"));
1529 #endif /* unix */
1531 if(ps->exceptions){
1533 if(!IS_REMOTE(ps->exceptions) &&
1534 !is_absolute_path(ps->exceptions)){
1535 #if defined(DOS) || defined(OS2)
1536 p = last_cmpnt(ps->pinerc);
1537 buf[0] = '\0';
1538 if(p != NULL){
1539 strncpy(buf, ps->pinerc, MIN(p - ps->pinerc, sizeof(buf)-1));
1540 buf[MIN(p - ps->pinerc, sizeof(buf)-1)] = '\0';
1543 strncat(buf, ps->exceptions, sizeof(buf)-1-strlen(buf));
1544 #else
1545 build_path(buf, ps->home_dir, ps->exceptions, sizeof(buf));
1546 #endif
1548 else{
1549 strncpy(buf, ps->exceptions, sizeof(buf)-1);
1550 buf[sizeof(buf)-1] = '\0';
1553 ps->post_prc = new_pinerc_s(buf);
1555 fs_give((void **)&ps->exceptions);
1558 mprint(2, (db, DSIZE-(db-(*debug_out)), "\n Global config: %.100s\n",
1559 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<none>"));
1560 mprint(2, (db, DSIZE-(db-(*debug_out)), " Personal config: %.100s\n",
1561 (ps->prc && ps->prc->name) ? ps->prc->name : "<none>"));
1562 mprint(2, (db, DSIZE-(db-(*debug_out)), " Exceptions config: %.100s\n",
1563 (ps->post_prc && ps->post_prc->name) ? ps->post_prc->name
1564 : "<none>"));
1565 #if !defined(DOS) && !defined(OS2)
1566 if(SYSTEM_PINERC_FIXED){
1567 mprint(2, (db, DSIZE-(db-(*debug_out)), " Fixed config: %.100s\n", SYSTEM_PINERC_FIXED));
1569 #endif
1571 mprint(2, (db, DSIZE-(db-(*debug_out)), "\n"));
1575 /*----------------------------------------------------------------------
1576 Initialize the variables
1578 Args: ps -- The usual pine structure
1580 Result:
1582 This reads the system pine configuration file and the user's pine
1583 configuration file ".pinerc" and places the results in the variables
1584 structure. It sorts out what was read and sets a few other variables
1585 based on the contents.
1586 ----*/
1587 void
1588 init_vars(struct pine *ps, void (*cmds_f) (struct pine *, char **))
1590 char buf[MAXPATH+1], *p, *q, **s;
1591 register struct variable *vars = ps->vars;
1592 int obs_header_in_reply = 0, /* the obs_ variables are to */
1593 obs_old_style_reply = 0, /* support backwards compatibility */
1594 obs_save_by_sender, i, def_sort_rev;
1595 long rvl;
1596 PINERC_S *fixedprc = NULL;
1597 FeatureLevel obs_feature_level;
1598 char *fromcharset = NULL;
1599 char *err = NULL;
1601 dprint((5, "init_vars:\n"));
1603 /*--- The defaults here are defined in os-xxx.h so they can vary
1604 per machine ---*/
1606 GLO_PRINTER = cpystr(DF_DEFAULT_PRINTER);
1607 GLO_ELM_STYLE_SAVE = cpystr(DF_ELM_STYLE_SAVE);
1608 GLO_ENCRYPTION_RANGE = cpystr(DF_ENCRYPTION_RANGE);
1609 GLO_SAVE_BY_SENDER = cpystr(DF_SAVE_BY_SENDER);
1610 GLO_HEADER_IN_REPLY = cpystr(DF_HEADER_IN_REPLY);
1611 GLO_INBOX_PATH = cpystr("inbox");
1612 GLO_DEFAULT_FCC = cpystr(DF_DEFAULT_FCC);
1613 GLO_DEFAULT_SAVE_FOLDER = cpystr(DEFAULT_SAVE);
1614 GLO_POSTPONED_FOLDER = cpystr(POSTPONED_MSGS);
1615 GLO_TRASH_FOLDER = cpystr(TRASH_FOLDER);
1616 GLO_USE_ONLY_DOMAIN_NAME = cpystr(DF_USE_ONLY_DOMAIN_NAME);
1617 GLO_FEATURE_LEVEL = cpystr("sappling");
1618 GLO_OLD_STYLE_REPLY = cpystr(DF_OLD_STYLE_REPLY);
1619 GLO_SORT_KEY = cpystr(DF_SORT_KEY);
1620 GLO_SAVED_MSG_NAME_RULE = cpystr(DF_SAVED_MSG_NAME_RULE);
1621 GLO_FCC_RULE = cpystr(DF_FCC_RULE);
1622 GLO_AB_SORT_RULE = cpystr(DF_AB_SORT_RULE);
1623 GLO_FLD_SORT_RULE = cpystr(DF_FLD_SORT_RULE);
1624 GLO_SIGNATURE_FILE = cpystr(DF_SIGNATURE_FILE);
1625 GLO_MAIL_DIRECTORY = cpystr(DF_MAIL_DIRECTORY);
1626 GLO_REMOTE_ABOOK_HISTORY = cpystr(DF_REMOTE_ABOOK_HISTORY);
1627 GLO_REMOTE_ABOOK_VALIDITY = cpystr(DF_REMOTE_ABOOK_VALIDITY);
1628 GLO_GOTO_DEFAULT_RULE = cpystr(DF_GOTO_DEFAULT_RULE);
1629 GLO_INCOMING_STARTUP = cpystr(DF_INCOMING_STARTUP);
1630 GLO_PRUNING_RULE = cpystr(DF_PRUNING_RULE);
1631 GLO_REOPEN_RULE = cpystr(DF_REOPEN_RULE);
1632 GLO_THREAD_DISP_STYLE = cpystr(DF_THREAD_DISP_STYLE);
1633 GLO_THREAD_INDEX_STYLE = cpystr(DF_THREAD_INDEX_STYLE);
1634 GLO_THREAD_MORE_CHAR = cpystr(DF_THREAD_MORE_CHAR);
1635 GLO_THREAD_EXP_CHAR = cpystr(DF_THREAD_EXP_CHAR);
1636 GLO_THREAD_LASTREPLY_CHAR = cpystr(DF_THREAD_LASTREPLY_CHAR);
1637 GLO_BUGS_FULLNAME = cpystr("Sorry No Address");
1638 GLO_BUGS_ADDRESS = cpystr("nobody");
1639 GLO_SUGGEST_FULLNAME = cpystr("Sorry No Address");
1640 GLO_SUGGEST_ADDRESS = cpystr("nobody");
1641 GLO_LOCAL_FULLNAME = cpystr(DF_LOCAL_FULLNAME);
1642 GLO_LOCAL_ADDRESS = cpystr(DF_LOCAL_ADDRESS);
1643 GLO_OVERLAP = cpystr(DF_OVERLAP);
1644 GLO_SLEEP = cpystr("60");
1645 GLO_MAXREMSTREAM = cpystr(DF_MAXREMSTREAM);
1646 GLO_MARGIN = cpystr(DF_MARGIN);
1647 GLO_FILLCOL = cpystr(DF_FILLCOL);
1648 GLO_DEADLETS = cpystr(DF_DEADLETS);
1649 GLO_NMW_WIDTH = cpystr(DF_NMW_WIDTH);
1650 GLO_REPLY_STRING = cpystr("> ");
1651 GLO_REPLY_INTRO = cpystr(DEFAULT_REPLY_INTRO);
1652 GLO_EMPTY_HDR_MSG = cpystr("undisclosed-recipients");
1653 GLO_STATUS_MSG_DELAY = cpystr("0");
1654 GLO_ACTIVE_MSG_INTERVAL = cpystr("12");
1655 GLO_USERINPUTTIMEO = cpystr("0");
1656 GLO_INCCHECKTIMEO = cpystr("5");
1657 GLO_INCCHECKINTERVAL = cpystr("180");
1658 GLO_INC2NDCHECKINTERVAL = cpystr("180");
1659 GLO_MAILCHECK = cpystr(DF_MAILCHECK);
1660 GLO_MAILCHECKNONCURR = cpystr("0");
1661 GLO_MAILDROPCHECK = cpystr(DF_MAILDROPCHECK);
1662 GLO_NNTPRANGE = cpystr("0");
1663 GLO_KBLOCK_PASSWD_COUNT = cpystr(DF_KBLOCK_PASSWD_COUNT);
1664 GLO_INDEX_COLOR_STYLE = cpystr("flip-colors");
1665 GLO_TITLEBAR_COLOR_STYLE = cpystr("default");
1666 GLO_POST_CHAR_SET = cpystr("UTF-8");
1667 #ifdef DF_FOLDER_EXTENSION
1668 GLO_FOLDER_EXTENSION = cpystr(DF_FOLDER_EXTENSION);
1669 #endif
1670 #ifdef DF_SMTP_SERVER
1671 GLO_SMTP_SERVER = parse_list(DF_SMTP_SERVER, 1,
1672 PL_REMSURRQUOT, NULL);
1673 #endif
1675 #ifdef DF_SSHPATH
1676 GLO_SSHPATH = cpystr(DF_SSHPATH);
1677 #endif
1678 #ifdef DF_SSHCMD
1679 GLO_SSHCMD = cpystr(DF_SSHCMD);
1680 #endif
1682 #ifndef _WINDOWS
1683 GLO_COLOR_STYLE = cpystr("no-color");
1684 GLO_NORM_FORE_COLOR = cpystr(DEFAULT_NORM_FORE_RGB);
1685 GLO_NORM_BACK_COLOR = cpystr(DEFAULT_NORM_BACK_RGB);
1686 #endif
1687 GLO_TITLE_FORE_COLOR = cpystr(DEFAULT_TITLE_FORE_RGB);
1688 GLO_TITLE_BACK_COLOR = cpystr(DEFAULT_TITLE_BACK_RGB);
1689 GLO_TITLECLOSED_FORE_COLOR = cpystr(DEFAULT_TITLECLOSED_FORE_RGB);
1690 GLO_TITLECLOSED_BACK_COLOR = cpystr(DEFAULT_TITLECLOSED_BACK_RGB);
1691 GLO_FOLDER_FORE_COLOR = cpystr(DEFAULT_NORM_FORE_RGB);
1692 GLO_DIRECTORY_FORE_COLOR = cpystr(DEFAULT_NORM_FORE_RGB);
1693 GLO_FOLDER_LIST_FORE_COLOR = cpystr(DEFAULT_NORM_FORE_RGB);
1694 GLO_METAMSG_FORE_COLOR = cpystr(DEFAULT_METAMSG_FORE_RGB);
1695 GLO_METAMSG_BACK_COLOR = cpystr(DEFAULT_METAMSG_BACK_RGB);
1696 GLO_QUOTE1_FORE_COLOR = cpystr(DEFAULT_QUOTE1_FORE_RGB);
1697 GLO_QUOTE1_BACK_COLOR = cpystr(DEFAULT_QUOTE1_BACK_RGB);
1698 GLO_QUOTE2_FORE_COLOR = cpystr(DEFAULT_QUOTE2_FORE_RGB);
1699 GLO_QUOTE2_BACK_COLOR = cpystr(DEFAULT_QUOTE2_BACK_RGB);
1700 GLO_QUOTE3_FORE_COLOR = cpystr(DEFAULT_QUOTE3_FORE_RGB);
1701 GLO_QUOTE3_BACK_COLOR = cpystr(DEFAULT_QUOTE3_BACK_RGB);
1702 GLO_SIGNATURE_FORE_COLOR = cpystr(DEFAULT_SIGNATURE_FORE_RGB);
1703 GLO_SIGNATURE_BACK_COLOR = cpystr(DEFAULT_SIGNATURE_BACK_RGB);
1704 GLO_IND_PLUS_FORE_COLOR = cpystr(DEFAULT_IND_PLUS_FORE_RGB);
1705 GLO_IND_PLUS_BACK_COLOR = cpystr(DEFAULT_IND_PLUS_BACK_RGB);
1706 GLO_IND_IMP_FORE_COLOR = cpystr(DEFAULT_IND_IMP_FORE_RGB);
1707 GLO_IND_IMP_BACK_COLOR = cpystr(DEFAULT_IND_IMP_BACK_RGB);
1708 GLO_IND_ANS_FORE_COLOR = cpystr(DEFAULT_IND_ANS_FORE_RGB);
1709 GLO_IND_ANS_BACK_COLOR = cpystr(DEFAULT_IND_ANS_BACK_RGB);
1710 GLO_IND_NEW_FORE_COLOR = cpystr(DEFAULT_IND_NEW_FORE_RGB);
1711 GLO_IND_NEW_BACK_COLOR = cpystr(DEFAULT_IND_NEW_BACK_RGB);
1712 GLO_IND_OP_FORE_COLOR = cpystr(DEFAULT_IND_OP_FORE_RGB);
1713 GLO_IND_OP_BACK_COLOR = cpystr(DEFAULT_IND_OP_BACK_RGB);
1714 GLO_VIEW_MARGIN_LEFT = cpystr("0");
1715 GLO_VIEW_MARGIN_RIGHT = cpystr(DF_VIEW_MARGIN_RIGHT);
1716 GLO_QUOTE_SUPPRESSION = cpystr(DF_QUOTE_SUPPRESSION);
1717 GLO_KW_BRACES = cpystr("\"{\" \"} \"");
1718 GLO_OPENING_SEP = cpystr(" - ");
1719 GLO_WP_INDEXHEIGHT = cpystr("24");
1720 GLO_WP_AGGSTATE = cpystr("1");
1721 GLO_WP_STATE = cpystr("");
1722 #ifdef DF_VAR_SPELLER
1723 GLO_SPELLER = cpystr(DF_VAR_SPELLER);
1724 #endif
1725 #ifdef SMIME
1726 if(ps->smimedir){
1727 snprintf(tmp_20k_buf, SIZEOF_20KBUF, "%s/public", ps->smimedir);
1728 tmp_20k_buf[SIZEOF_20KBUF-1] = '\0';
1729 GLO_PUBLICCERT_DIR = cpystr(tmp_20k_buf);
1731 snprintf(tmp_20k_buf, SIZEOF_20KBUF, "%s/private", ps->smimedir);
1732 tmp_20k_buf[SIZEOF_20KBUF-1] = '\0';
1733 GLO_PRIVATEKEY_DIR = cpystr(tmp_20k_buf);
1735 snprintf(tmp_20k_buf, SIZEOF_20KBUF, "%s/ca", ps->smimedir);
1736 tmp_20k_buf[SIZEOF_20KBUF-1] = '\0';
1737 GLO_CACERT_DIR = cpystr(tmp_20k_buf);
1739 else{
1740 GLO_PUBLICCERT_DIR = cpystr(DF_PUBLICCERT_DIR);
1741 GLO_PRIVATEKEY_DIR = cpystr(DF_PRIVATEKEY_DIR);
1742 GLO_CACERT_DIR = cpystr(DF_CACERT_DIR);
1744 #endif /* SMIME */
1747 * Default first value for addrbook list if none set.
1748 * We also want to be sure to set global_val to the default
1749 * if is_fixed, so that address-book= will cause the default to happen.
1751 if(!GLO_ADDRESSBOOK && !FIX_ADDRESSBOOK)
1752 GLO_ADDRESSBOOK = parse_list(DF_ADDRESSBOOK, 1, 0, NULL);
1755 * Default first value if none set.
1757 if(!GLO_STANDARD_PRINTER && !FIX_STANDARD_PRINTER)
1758 GLO_STANDARD_PRINTER = parse_list(DF_STANDARD_PRINTER, 1, 0, NULL);
1761 * Defining this default sshpath should cause ssh to be preferred over rsh
1762 * when attempting imapd preauth calls.
1764 #ifdef DF_SSHPATH
1765 if(DF_SSHPATH
1766 && is_absolute_path(DF_SSHPATH)
1767 && can_access(DF_SSHPATH, EXECUTE_ACCESS) == 0){
1768 mail_parameters(NULL, SET_SSHPATH, (void *) DF_SSHPATH);
1770 #endif
1772 * It isn't usually necessary to define this.
1774 #ifdef DF_SSHCMD
1775 if(DF_SSHCMD){
1776 mail_parameters(NULL, SET_SSHCOMMAND, (void *) DF_SSHCMD);
1778 #endif
1780 #if !defined(DOS) && !defined(OS2)
1782 * This is here instead of in init_pinerc so that we can get by without
1783 * having a global fixedprc, since we don't need it anymore after this.
1785 fixedprc = new_pinerc_s(SYSTEM_PINERC_FIXED);
1786 #endif
1788 if(ps->pconf){
1789 read_pinerc(ps->pconf, vars, ParseGlobal);
1790 if(ps->pconf->type != Loc)
1791 rd_close_remote(ps->pconf->rd);
1794 if(ps->prc){
1795 read_pinerc(ps->prc, vars, ParsePers);
1796 if(ps->prc->type != Loc)
1797 rd_close_remote(ps->prc->rd);
1800 if(ps->post_prc){
1801 read_pinerc(ps->post_prc, vars, ParsePersPost);
1802 if(ps->post_prc->type != Loc)
1803 rd_close_remote(ps->post_prc->rd);
1806 if(fixedprc){
1807 read_pinerc(fixedprc, vars, ParseFixed);
1808 free_pinerc_s(&fixedprc);
1811 ps->ew_for_except_vars = ps->post_prc ? Post : Main;
1813 if(ps->exit_if_no_pinerc && ps->first_time_user){
1815 /* TRANSLATORS: -bail is a literal option name, don't change it. */
1816 exceptional_exit(_("Exiting because -bail option is set and config file doesn't exist."), -1);
1820 * Convert everything having to do with the config to UTF-8
1821 * in order to avoid having to worry about it all over the
1822 * place.
1823 * Set the character-set first so that we may use that in
1824 * the conversion process.
1826 set_collation(0, 1);
1828 #ifndef _WINDOWS
1829 #if (HAVE_LANGINFO_H && defined(CODESET))
1831 if(output_charset_is_supported(nl_langinfo_codeset_wrapper()))
1832 ps->GLO_CHAR_SET = cpystr(nl_langinfo_codeset_wrapper());
1833 else{
1834 ps->GLO_CHAR_SET = cpystr("UTF-8");
1835 dprint((1,"nl_langinfo(CODESET) returns unrecognized value=\"%s\", using UTF-8 as default\n", (p=nl_langinfo(CODESET)) ? p : ""));
1837 #else
1838 ps->GLO_CHAR_SET = cpystr("UTF-8");
1839 #endif
1841 set_current_val(&vars[V_CHAR_SET], TRUE, TRUE);
1842 set_current_val(&vars[V_OLD_CHAR_SET], TRUE, TRUE);
1843 set_current_val(&vars[V_KEY_CHAR_SET], TRUE, TRUE);
1844 #endif /* ! _WINDOWS */
1846 set_current_val(&vars[V_POST_CHAR_SET], TRUE, TRUE);
1849 * Also set up the feature list because we need the
1850 * Use-System-Translation feature to set up the charmaps.
1853 /* way obsolete, backwards compatibility */
1854 set_current_val(&vars[V_FEATURE_LEVEL], TRUE, TRUE);
1855 if(strucmp(VAR_FEATURE_LEVEL, "seedling") == 0)
1856 obs_feature_level = Seedling;
1857 else if(strucmp(VAR_FEATURE_LEVEL, "old-growth") == 0)
1858 obs_feature_level = Seasoned;
1859 else
1860 obs_feature_level = Sapling;
1862 /* obsolete, backwards compatibility */
1863 set_current_val(&vars[V_OLD_STYLE_REPLY], TRUE, TRUE);
1864 obs_old_style_reply = !strucmp(VAR_OLD_STYLE_REPLY, "yes");
1866 set_feature_list_current_val(&vars[V_FEATURE_LIST]);
1867 process_feature_list(ps, VAR_FEATURE_LIST,
1868 (obs_feature_level == Seasoned) ? 1 : 0,
1869 obs_header_in_reply, obs_old_style_reply);
1873 * Redo set_collation call with correct value for collation,
1874 * but we're hardwiring ctype on now. That's because nl_langinfo()
1875 * call needs it and system-dependent wcwidth and wcrtomb functions
1876 * need it.
1878 set_collation(F_OFF(F_DISABLE_SETLOCALE_COLLATE, ps_global), 1);
1881 * Set up to send the correct sequence of bytes to the display terminal.
1884 if(reset_character_set_stuff(&err) == -1)
1885 alpine_panic(err ? err : "trouble with character set setup");
1886 else if(err){
1887 init_error(ps, SM_ORDER | SM_DING, 3, 5, err);
1888 fs_give((void **) &err);
1892 * Now we use the configvars from above to convert the rest
1893 * to UTF-8. That should be ok because the ones above should
1894 * be ASCII.
1896 if(ps->keyboard_charmap && strucmp(ps->keyboard_charmap, "UTF-8")
1897 && strucmp(ps->keyboard_charmap, "US-ASCII"))
1898 fromcharset = ps->keyboard_charmap;
1899 else if(ps->display_charmap && strucmp(ps->display_charmap, "UTF-8")
1900 && strucmp(ps->display_charmap, "US-ASCII"))
1901 fromcharset = ps->display_charmap;
1902 #ifndef _WINDOWS
1903 else if(VAR_OLD_CHAR_SET && strucmp(VAR_OLD_CHAR_SET, "UTF-8")
1904 && strucmp(VAR_OLD_CHAR_SET, "US-ASCII"))
1905 fromcharset = VAR_OLD_CHAR_SET;
1906 #endif /* ! _WINDOWS */
1908 convert_configvars_to_utf8(vars, fromcharset);
1911 * If we already set this while reading the remote pinerc, don't
1912 * change it.
1914 if(!VAR_REMOTE_ABOOK_METADATA || !VAR_REMOTE_ABOOK_METADATA[0])
1915 set_current_val(&vars[V_REMOTE_ABOOK_METADATA], TRUE, TRUE);
1918 * mail-directory variable is obsolete, put its value in
1919 * default folder-collection list
1921 set_current_val(&vars[V_MAIL_DIRECTORY], TRUE, TRUE);
1922 if(!GLO_FOLDER_SPEC){
1923 build_path(tmp_20k_buf, VAR_MAIL_DIRECTORY, "[]", SIZEOF_20KBUF);
1924 GLO_FOLDER_SPEC = parse_list(tmp_20k_buf, 1, 0, NULL);
1927 set_current_val(&vars[V_FOLDER_SPEC], TRUE, TRUE);
1929 set_current_val(&vars[V_NNTP_SERVER], TRUE, TRUE);
1930 for(i = 0; VAR_NNTP_SERVER && VAR_NNTP_SERVER[i]; i++)
1931 removing_quotes(VAR_NNTP_SERVER[i]);
1933 set_news_spec_current_val(TRUE, TRUE);
1935 set_current_val(&vars[V_INBOX_PATH], TRUE, TRUE);
1937 set_current_val(&vars[V_USER_DOMAIN], TRUE, TRUE);
1938 if(VAR_USER_DOMAIN
1939 && VAR_USER_DOMAIN[0]
1940 && (p = strrindex(VAR_USER_DOMAIN, '@'))){
1941 if(*(++p)){
1942 char *q;
1944 snprintf(tmp_20k_buf, SIZEOF_20KBUF,
1945 "User-domain (%s) cannot contain \"@\", using \"%s\"",
1946 VAR_USER_DOMAIN, p);
1947 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
1948 q = VAR_USER_DOMAIN;
1949 while((*q++ = *p++) != '\0')
1950 ;/* do nothing */
1952 else{
1953 snprintf(tmp_20k_buf, SIZEOF_20KBUF,
1954 "User-domain (%s) cannot contain \"@\", deleting",
1955 VAR_USER_DOMAIN);
1956 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
1957 if(ps->vars[V_USER_DOMAIN].post_user_val.p){
1958 fs_give((void **)&ps->vars[V_USER_DOMAIN].post_user_val.p);
1959 set_current_val(&vars[V_USER_DOMAIN], TRUE, TRUE);
1962 if(VAR_USER_DOMAIN
1963 && VAR_USER_DOMAIN[0]
1964 && (p = strrindex(VAR_USER_DOMAIN, '@'))){
1965 if(ps->vars[V_USER_DOMAIN].main_user_val.p){
1966 fs_give((void **)&ps->vars[V_USER_DOMAIN].main_user_val.p);
1967 set_current_val(&vars[V_USER_DOMAIN], TRUE, TRUE);
1973 set_current_val(&vars[V_USE_ONLY_DOMAIN_NAME], TRUE, TRUE);
1974 set_current_val(&vars[V_REPLY_STRING], TRUE, TRUE);
1975 set_current_val(&vars[V_WORDSEPS], TRUE, TRUE);
1976 set_current_val(&vars[V_QUOTE_REPLACE_STRING], TRUE, TRUE);
1977 set_current_val(&vars[V_REPLY_INTRO], TRUE, TRUE);
1978 set_current_val(&vars[V_EMPTY_HDR_MSG], TRUE, TRUE);
1980 #ifdef ENABLE_LDAP
1981 set_current_val(&vars[V_LDAP_SERVERS], TRUE, TRUE);
1982 #endif /* ENABLE_LDAP */
1984 /* obsolete, backwards compatibility */
1985 set_current_val(&vars[V_HEADER_IN_REPLY], TRUE, TRUE);
1986 obs_header_in_reply=!strucmp(VAR_HEADER_IN_REPLY, "yes");
1988 set_current_val(&vars[V_PERSONAL_PRINT_COMMAND], TRUE, TRUE);
1989 set_current_val(&vars[V_STANDARD_PRINTER], TRUE, TRUE);
1990 set_current_val(&vars[V_PRINTER], TRUE, TRUE);
1991 if(vars[V_PERSONAL_PRINT_COMMAND].is_fixed && !vars[V_PRINTER].is_fixed)
1992 printer_value_check_and_adjust();
1994 set_current_val(&vars[V_LAST_TIME_PRUNE_QUESTION], TRUE, TRUE);
1995 if(VAR_LAST_TIME_PRUNE_QUESTION != NULL){
1996 /* The month value in the file runs from 1-12, the variable here
1997 runs from 0-11; the value in the file used to be 0-11, but we're
1998 fixing it in January */
1999 ps->last_expire_year = atoi(VAR_LAST_TIME_PRUNE_QUESTION);
2000 ps->last_expire_month =
2001 atoi(strindex(VAR_LAST_TIME_PRUNE_QUESTION, '.') + 1);
2002 if(ps->last_expire_month == 0){
2003 /* Fix for 0 because of old bug */
2004 snprintf(buf, sizeof(buf), "%d.%d", ps_global->last_expire_year,
2005 ps_global->last_expire_month + 1);
2006 set_variable(V_LAST_TIME_PRUNE_QUESTION, buf, 1, 1, Main);
2007 }else{
2008 ps->last_expire_month--;
2010 }else{
2011 ps->last_expire_year = -1;
2012 ps->last_expire_month = -1;
2015 set_current_val(&vars[V_BUGS_FULLNAME], TRUE, TRUE);
2016 set_current_val(&vars[V_BUGS_ADDRESS], TRUE, TRUE);
2017 set_current_val(&vars[V_SUGGEST_FULLNAME], TRUE, TRUE);
2018 set_current_val(&vars[V_SUGGEST_ADDRESS], TRUE, TRUE);
2019 set_current_val(&vars[V_LOCAL_FULLNAME], TRUE, TRUE);
2020 set_current_val(&vars[V_LOCAL_ADDRESS], TRUE, TRUE);
2021 set_current_val(&vars[V_BUGS_EXTRAS], TRUE, TRUE);
2022 set_current_val(&vars[V_KBLOCK_PASSWD_COUNT], TRUE, TRUE);
2023 set_current_val(&vars[V_DEFAULT_FCC], TRUE, TRUE);
2024 set_current_val(&vars[V_POSTPONED_FOLDER], TRUE, TRUE);
2025 set_current_val(&vars[V_TRASH_FOLDER], TRUE, TRUE);
2026 set_current_val(&vars[V_READ_MESSAGE_FOLDER], TRUE, TRUE);
2027 set_current_val(&vars[V_FORM_FOLDER], TRUE, TRUE);
2028 set_current_val(&vars[V_EDITOR], TRUE, TRUE);
2029 set_current_val(&vars[V_SPELLER], TRUE, TRUE);
2030 #ifdef _WINDOWS
2031 set_current_val(&vars[V_DICTIONARY], TRUE, TRUE);
2032 #endif /* _WINDOWS */
2033 set_current_val(&vars[V_IMAGE_VIEWER], TRUE, TRUE);
2034 set_current_val(&vars[V_BROWSER], TRUE, TRUE);
2035 set_current_val(&vars[V_HISTORY], TRUE, TRUE);
2036 set_current_val(&vars[V_SMTP_SERVER], TRUE, TRUE);
2037 set_current_val(&vars[V_COMP_HDRS], TRUE, TRUE);
2038 set_current_val(&vars[V_CUSTOM_HDRS], TRUE, TRUE);
2039 set_current_val(&vars[V_SENDMAIL_PATH], TRUE, TRUE);
2040 set_current_val(&vars[V_DISPLAY_FILTERS], TRUE, TRUE);
2041 set_current_val(&vars[V_SEND_FILTER], TRUE, TRUE);
2042 set_current_val(&vars[V_ALT_ADDRS], TRUE, TRUE);
2043 set_current_val(&vars[V_ABOOK_FORMATS], TRUE, TRUE);
2044 set_current_val(&vars[V_KW_BRACES], TRUE, TRUE);
2045 set_current_val(&vars[V_OPENING_SEP], TRUE, TRUE);
2046 set_current_val(&vars[V_UNK_CHAR_SET], TRUE, TRUE);
2047 #ifdef SMIME
2048 set_current_val(&vars[V_PUBLICCERT_DIR], TRUE, TRUE);
2049 set_current_val(&vars[V_PUBLICCERT_CONTAINER], TRUE, TRUE);
2050 set_current_val(&vars[V_PRIVATEKEY_DIR], TRUE, TRUE);
2051 set_current_val(&vars[V_PRIVATEKEY_CONTAINER], TRUE, TRUE);
2052 set_current_val(&vars[V_CACERT_DIR], TRUE, TRUE);
2053 set_current_val(&vars[V_CACERT_CONTAINER], TRUE, TRUE);
2054 #endif /* SMIME */
2056 set_current_val(&vars[V_KEYWORDS], TRUE, TRUE);
2057 ps_global->keywords = init_keyword_list(VAR_KEYWORDS);
2059 set_current_val(&vars[V_OPER_DIR], TRUE, TRUE);
2060 if(VAR_OPER_DIR && !VAR_OPER_DIR[0]){
2061 init_error(ps, SM_ORDER | SM_DING, 3, 5,
2062 "Setting operating-dir to the empty string is not allowed. Will be ignored.");
2063 fs_give((void **)&VAR_OPER_DIR);
2064 if(FIX_OPER_DIR)
2065 fs_give((void **)&FIX_OPER_DIR);
2066 if(GLO_OPER_DIR)
2067 fs_give((void **)&GLO_OPER_DIR);
2068 if(COM_OPER_DIR)
2069 fs_give((void **)&COM_OPER_DIR);
2070 if(ps_global->vars[V_OPER_DIR].post_user_val.p)
2071 fs_give((void **)&ps_global->vars[V_OPER_DIR].post_user_val.p);
2072 if(ps_global->vars[V_OPER_DIR].main_user_val.p)
2073 fs_give((void **)&ps_global->vars[V_OPER_DIR].main_user_val.p);
2076 set_current_val(&vars[V_PERSONAL_PRINT_CATEGORY], TRUE, TRUE);
2077 ps->printer_category = -1;
2078 if(VAR_PERSONAL_PRINT_CATEGORY != NULL)
2079 ps->printer_category = atoi(VAR_PERSONAL_PRINT_CATEGORY);
2081 if(ps->printer_category < 1 || ps->printer_category > 3){
2082 char **tt;
2083 char aname[100], wname[100];
2085 strncpy(aname, ANSI_PRINTER, sizeof(aname));
2086 aname[sizeof(aname)-1] = '\0';
2087 strncat(aname, "-no-formfeed", sizeof(aname)-strlen(aname)-1);
2088 strncpy(wname, WYSE_PRINTER, sizeof(wname));
2089 wname[sizeof(wname)-1] = '\0';
2090 strncat(wname, "-no-formfeed", sizeof(wname)-strlen(wname)-1);
2091 if(strucmp(VAR_PRINTER, ANSI_PRINTER) == 0
2092 || strucmp(VAR_PRINTER, aname) == 0
2093 || strucmp(VAR_PRINTER, WYSE_PRINTER) == 0
2094 || strucmp(VAR_PRINTER, wname) == 0)
2095 ps->printer_category = 1;
2096 else if(VAR_STANDARD_PRINTER && VAR_STANDARD_PRINTER[0]){
2097 for(tt = VAR_STANDARD_PRINTER; *tt; tt++)
2098 if(strucmp(VAR_PRINTER, *tt) == 0)
2099 break;
2101 if(*tt)
2102 ps->printer_category = 2;
2105 /* didn't find it yet */
2106 if(ps->printer_category < 1 || ps->printer_category > 3){
2107 if(VAR_PERSONAL_PRINT_COMMAND && VAR_PERSONAL_PRINT_COMMAND[0]){
2108 for(tt = VAR_PERSONAL_PRINT_COMMAND; *tt; tt++)
2109 if(strucmp(VAR_PRINTER, *tt) == 0)
2110 break;
2112 if(*tt)
2113 ps->printer_category = 3;
2118 set_current_val(&vars[V_SLEEP], TRUE, TRUE);
2119 ps->sleep = i = 60;
2120 if(SVAR_SLEEP(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2121 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2122 else
2123 ps->sleep = i;
2125 set_current_val(&vars[V_OVERLAP], TRUE, TRUE);
2126 ps->viewer_overlap = i = atoi(DF_OVERLAP);
2127 if(SVAR_OVERLAP(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2128 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2129 else
2130 ps->viewer_overlap = i;
2132 set_current_val(&vars[V_MARGIN], TRUE, TRUE);
2133 ps->scroll_margin = i = atoi(DF_MARGIN);
2134 if(SVAR_MARGIN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2135 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2136 else
2137 ps->scroll_margin = i;
2139 set_current_val(&vars[V_FILLCOL], TRUE, TRUE);
2140 ps->composer_fillcol = i = atoi(DF_FILLCOL);
2141 if(SVAR_FILLCOL(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2142 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2143 else
2144 ps->composer_fillcol = i;
2146 set_current_val(&vars[V_QUOTE_SUPPRESSION], TRUE, TRUE);
2147 ps->quote_suppression_threshold = i = atoi(DF_QUOTE_SUPPRESSION);
2148 if(SVAR_QUOTE_SUPPRESSION(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2149 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2150 else{
2151 if(i > 0 && i < Q_SUPP_LIMIT){
2152 snprintf(tmp_20k_buf, SIZEOF_20KBUF,
2153 "Ignoring Quote-Suppression-Threshold value of %.50s, see help",
2154 VAR_QUOTE_SUPPRESSION);
2155 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2157 else{
2158 if(i < 0 && i != Q_DEL_ALL)
2159 ps->quote_suppression_threshold = -i;
2160 else
2161 ps->quote_suppression_threshold = i;
2165 set_current_val(&vars[V_DEADLETS], TRUE, TRUE);
2166 ps->deadlets = i = atoi(DF_DEADLETS);
2167 if(SVAR_DEADLETS(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2168 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2169 else
2170 ps->deadlets = i;
2172 set_current_val(&vars[V_STATUS_MSG_DELAY], TRUE, TRUE);
2173 ps->status_msg_delay = i = 0;
2174 if(SVAR_MSGDLAY(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2175 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2176 else
2177 ps->status_msg_delay = i;
2179 set_current_val(&vars[V_ACTIVE_MSG_INTERVAL], TRUE, TRUE);
2180 ps->active_status_interval = i = 8;
2181 if(SVAR_ACTIVEINTERVAL(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2182 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2183 else
2184 ps->active_status_interval = i;
2186 set_current_val(&vars[V_REMOTE_ABOOK_HISTORY], TRUE, TRUE);
2187 ps->remote_abook_history = i = atoi(DF_REMOTE_ABOOK_HISTORY);
2188 if(SVAR_AB_HIST(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2189 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2190 else
2191 ps->remote_abook_history = i;
2193 set_current_val(&vars[V_REMOTE_ABOOK_VALIDITY], TRUE, TRUE);
2194 ps->remote_abook_validity = i = atoi(DF_REMOTE_ABOOK_VALIDITY);
2195 if(SVAR_AB_VALID(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2196 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2197 else
2198 ps->remote_abook_validity = i;
2200 set_current_val(&vars[V_USERINPUTTIMEO], TRUE, TRUE);
2201 ps->hours_to_timeout = i = 0;
2202 if(SVAR_USER_INPUT(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2203 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2204 else
2205 ps->hours_to_timeout = i;
2207 /* timeo is a regular extern int because it is referenced in pico */
2208 set_current_val(&vars[V_MAILCHECK], TRUE, TRUE);
2209 set_input_timeout(i = 15);
2210 if(SVAR_MAILCHK(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2211 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2212 else
2213 set_input_timeout(i);
2215 set_current_val(&vars[V_MAILCHECKNONCURR], TRUE, TRUE);
2216 ps->check_interval_for_noncurr = i = 0;
2217 if(SVAR_MAILCHKNONCURR(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2218 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2219 else
2220 ps->check_interval_for_noncurr = i;
2222 #ifdef DEBUGJOURNAL
2223 ps->debugmem = 1;
2224 #else
2225 ps->debugmem = 0;
2226 #endif
2228 i = 30;
2229 set_current_val(&vars[V_TCPOPENTIMEO], TRUE, TRUE);
2230 /* this is just for the error, we don't save the result */
2231 if(VAR_TCPOPENTIMEO && SVAR_TCP_OPEN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2232 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2234 i = 15;
2235 set_current_val(&vars[V_TCPREADWARNTIMEO], TRUE, TRUE);
2236 /* this is just for the error, we don't save the result */
2237 if(VAR_TCPREADWARNTIMEO && SVAR_TCP_READWARN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2238 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2240 i = 0;
2241 set_current_val(&vars[V_TCPWRITEWARNTIMEO], TRUE, TRUE);
2242 /* this is just for the error, we don't save the result */
2243 if(VAR_TCPWRITEWARNTIMEO && SVAR_TCP_WRITEWARN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2244 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2246 i = 15;
2247 set_current_val(&vars[V_RSHOPENTIMEO], TRUE, TRUE);
2248 /* this is just for the error, we don't save the result */
2249 if(VAR_RSHOPENTIMEO && SVAR_RSH_OPEN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2250 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2252 i = 15;
2253 set_current_val(&vars[V_SSHOPENTIMEO], TRUE, TRUE);
2254 /* this is just for the error, we don't save the result */
2255 if(VAR_SSHOPENTIMEO && SVAR_SSH_OPEN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2256 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2258 set_current_val(&vars[V_INCCHECKLIST], TRUE, TRUE);
2260 set_current_val(&vars[V_INCCHECKTIMEO], TRUE, TRUE);
2261 ps->inc_check_timeout = i = 5;
2262 if(SVAR_INC_CHECK_TIMEO(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2263 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2264 else
2265 ps->inc_check_timeout = i;
2267 set_current_val(&vars[V_INCCHECKINTERVAL], TRUE, TRUE);
2268 ps->inc_check_interval = i = 180;
2269 if(SVAR_INC_CHECK_INTERV(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2270 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2271 else
2272 ps->inc_check_interval = i;
2274 set_current_val(&vars[V_INC2NDCHECKINTERVAL], TRUE, TRUE);
2275 ps->inc_second_check_interval = i = 180;
2276 if(SVAR_INC_2NDCHECK_INTERV(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2277 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2278 else
2279 ps->inc_second_check_interval = i;
2281 rvl = 60L;
2282 set_current_val(&vars[V_MAILDROPCHECK], TRUE, TRUE);
2283 /* this is just for the error, we don't save the result */
2284 if(VAR_MAILDROPCHECK && SVAR_MAILDCHK(ps, rvl, tmp_20k_buf, SIZEOF_20KBUF))
2285 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2287 rvl = 0L;
2288 set_current_val(&vars[V_NNTPRANGE], TRUE, TRUE);
2289 /* this is just for the error, we don't save the result */
2290 if(VAR_NNTPRANGE && SVAR_NNTPRANGE(ps, rvl, tmp_20k_buf, SIZEOF_20KBUF))
2291 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2293 set_current_val(&vars[V_TCPQUERYTIMEO], TRUE, TRUE);
2294 ps->tcp_query_timeout = i = TO_BAIL_THRESHOLD;
2295 if(VAR_TCPQUERYTIMEO && SVAR_TCP_QUERY(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2296 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2297 else
2298 ps->tcp_query_timeout = i;
2300 set_current_val(&vars[V_QUITQUERYTIMEO], TRUE, TRUE);
2301 ps->close_connection_timeout = i = 0;
2302 if(VAR_QUITQUERYTIMEO && SVAR_QUIT_QUERY_TIMEO(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2303 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2304 else
2305 ps->close_connection_timeout = i;
2307 set_current_val(&vars[V_NEWSRC_PATH], TRUE, TRUE);
2308 if(VAR_NEWSRC_PATH && VAR_NEWSRC_PATH[0])
2309 mail_parameters(NULL, SET_NEWSRC, (void *)VAR_NEWSRC_PATH);
2311 set_current_val(&vars[V_NEWS_ACTIVE_PATH], TRUE, TRUE);
2312 if(VAR_NEWS_ACTIVE_PATH)
2313 mail_parameters(NULL, SET_NEWSACTIVE,
2314 (void *)VAR_NEWS_ACTIVE_PATH);
2316 set_current_val(&vars[V_NEWS_SPOOL_DIR], TRUE, TRUE);
2317 if(VAR_NEWS_SPOOL_DIR)
2318 mail_parameters(NULL, SET_NEWSSPOOL,
2319 (void *)VAR_NEWS_SPOOL_DIR);
2321 /* guarantee a save default */
2322 set_current_val(&vars[V_DEFAULT_SAVE_FOLDER], TRUE, TRUE);
2323 if(!VAR_DEFAULT_SAVE_FOLDER || !VAR_DEFAULT_SAVE_FOLDER[0])
2324 set_variable(V_DEFAULT_SAVE_FOLDER,
2325 (GLO_DEFAULT_SAVE_FOLDER && GLO_DEFAULT_SAVE_FOLDER[0])
2326 ? GLO_DEFAULT_SAVE_FOLDER
2327 : DEFAULT_SAVE, 1, 0, Main);
2329 set_current_val(&vars[V_SIGNATURE_FILE], TRUE, TRUE);
2330 set_current_val(&vars[V_LITERAL_SIG], TRUE, TRUE);
2331 set_current_val(&vars[V_GLOB_ADDRBOOK], TRUE, TRUE);
2332 set_current_val(&vars[V_ADDRESSBOOK], TRUE, TRUE);
2333 set_current_val(&vars[V_FORCED_ABOOK_ENTRY], TRUE, TRUE);
2334 set_current_val(&vars[V_DISABLE_DRIVERS], TRUE, TRUE);
2335 set_current_val(&vars[V_DISABLE_AUTHS], TRUE, TRUE);
2336 set_current_val(&vars[V_ENCRYPTION_RANGE], TRUE, TRUE);
2338 set_current_val(&vars[V_VIEW_HEADERS], TRUE, TRUE);
2339 /* strip spaces and colons */
2340 if(ps->VAR_VIEW_HEADERS){
2341 for(s = ps->VAR_VIEW_HEADERS; (q = *s) != NULL; s++){
2342 if(q[0]){
2343 removing_leading_white_space(q);
2344 /* look for colon or space or end */
2345 for(p = q; *p && !isspace((unsigned char)*p) && *p != ':'; p++)
2346 ;/* do nothing */
2348 *p = '\0';
2349 if(strucmp(q, ALL_EXCEPT) == 0)
2350 ps->view_all_except = 1;
2355 set_current_val(&vars[V_VIEW_MARGIN_LEFT], TRUE, TRUE);
2356 set_current_val(&vars[V_VIEW_MARGIN_RIGHT], TRUE, TRUE);
2357 set_current_val(&vars[V_UPLOAD_CMD], TRUE, TRUE);
2358 set_current_val(&vars[V_UPLOAD_CMD_PREFIX], TRUE, TRUE);
2359 set_current_val(&vars[V_DOWNLOAD_CMD], TRUE, TRUE);
2360 set_current_val(&vars[V_DOWNLOAD_CMD_PREFIX], TRUE, TRUE);
2361 set_current_val(&vars[V_MAILCAP_PATH], TRUE, TRUE);
2362 set_current_val(&vars[V_MIMETYPE_PATH], TRUE, TRUE);
2363 #if !defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)
2364 set_current_val(&vars[V_FIFOPATH], TRUE, TRUE);
2365 #endif
2367 set_current_val(&vars[V_RSHPATH], TRUE, TRUE);
2368 if(VAR_RSHPATH
2369 && is_absolute_path(VAR_RSHPATH)
2370 && can_access(VAR_RSHPATH, EXECUTE_ACCESS) == 0){
2371 mail_parameters(NULL, SET_RSHPATH, (void *) VAR_RSHPATH);
2374 set_current_val(&vars[V_RSHCMD], TRUE, TRUE);
2375 if(VAR_RSHCMD){
2376 mail_parameters(NULL, SET_RSHCOMMAND, (void *) VAR_RSHCMD);
2379 set_current_val(&vars[V_SSHPATH], TRUE, TRUE);
2380 if(VAR_SSHPATH) {
2381 if(is_absolute_path(VAR_SSHPATH)
2382 && can_access(VAR_SSHPATH, EXECUTE_ACCESS) == 0){
2383 mail_parameters(NULL, SET_SSHPATH, (void *) VAR_SSHPATH);
2385 else {
2386 mail_parameters(NULL, SET_SSHPATH, (void *) NULL);
2390 set_current_val(&vars[V_SSHCMD], TRUE, TRUE);
2391 if(VAR_SSHCMD) {
2392 if(VAR_SSHCMD[0]) {
2393 mail_parameters(NULL, SET_SSHCOMMAND, (void *) VAR_SSHCMD);
2395 else {
2396 mail_parameters(NULL, SET_SSHCOMMAND, (void *) NULL);
2400 #if defined(DOS) || defined(OS2)
2402 set_current_val(&vars[V_FILE_DIR], TRUE, TRUE);
2404 #ifdef _WINDOWS
2405 set_current_val(&vars[V_FONT_NAME], TRUE, TRUE);
2406 set_current_val(&vars[V_FONT_SIZE], TRUE, TRUE);
2407 set_current_val(&vars[V_FONT_STYLE], TRUE, TRUE);
2408 set_current_val(&vars[V_FONT_CHAR_SET], TRUE, TRUE);
2409 set_current_val(&vars[V_CURSOR_STYLE], TRUE, TRUE);
2410 set_current_val(&vars[V_WINDOW_POSITION], TRUE, TRUE);
2412 if(F_OFF(F_STORE_WINPOS_IN_CONFIG, ps_global)){
2413 /* if win position is in the registry, use it */
2414 if(mswin_reg(MSWR_OP_GET, MSWR_PINE_POS, buf, sizeof(buf))){
2415 if(VAR_WINDOW_POSITION)
2416 fs_give((void **)&VAR_WINDOW_POSITION);
2418 VAR_WINDOW_POSITION = cpystr(buf);
2420 else if(VAR_WINDOW_POSITION
2421 && (ps->update_registry != UREG_NEVER_SET)){
2422 /* otherwise, put it there */
2423 mswin_reg(MSWR_OP_SET | ((ps->update_registry == UREG_ALWAYS_SET)
2424 ? MSWR_OP_FORCE : 0),
2425 MSWR_PINE_POS,
2426 VAR_WINDOW_POSITION, (size_t)NULL);
2430 mswin_setwindow (VAR_FONT_NAME, VAR_FONT_SIZE,
2431 VAR_FONT_STYLE, VAR_WINDOW_POSITION,
2432 VAR_CURSOR_STYLE, VAR_FONT_CHAR_SET);
2434 /* this is no longer used */
2435 if(VAR_WINDOW_POSITION)
2436 fs_give((void **)&VAR_WINDOW_POSITION);
2438 set_current_val(&vars[V_PRINT_FONT_NAME], TRUE, TRUE);
2439 set_current_val(&vars[V_PRINT_FONT_SIZE], TRUE, TRUE);
2440 set_current_val(&vars[V_PRINT_FONT_STYLE], TRUE, TRUE);
2441 set_current_val(&vars[V_PRINT_FONT_CHAR_SET], TRUE, TRUE);
2442 mswin_setprintfont (VAR_PRINT_FONT_NAME,
2443 VAR_PRINT_FONT_SIZE,
2444 VAR_PRINT_FONT_STYLE,
2445 VAR_PRINT_FONT_CHAR_SET);
2447 mswin_setgenhelptextcallback(pcpine_general_help);
2449 mswin_setclosetext ("Use the \"Q\" command to exit Alpine.");
2452 char foreColor[64], backColor[64];
2454 mswin_getwindow(NULL, 0, NULL, 0, NULL, 0, NULL, 0,
2455 foreColor, sizeof(foreColor), backColor, sizeof(backColor),
2456 NULL, 0, NULL, 0);
2457 if(!GLO_NORM_FORE_COLOR)
2458 GLO_NORM_FORE_COLOR = cpystr(foreColor);
2460 if(!GLO_NORM_BACK_COLOR)
2461 GLO_NORM_BACK_COLOR = cpystr(backColor);
2463 #endif /* _WINDOWS */
2464 #endif /* DOS */
2467 * We want the version number to start out as 1.0 for Alpine, but
2468 * we also want to use the same old config file that was used
2469 * with Pine. The Pine version numbers made it up to 4.64 and we
2470 * want Alpine's 1.0 to be larger than 4.64 so we keep a separate
2471 * internal version number which is the real version number
2472 * plus 4. That's what gets written in LAST_VERS_USED.
2474 strncpy(ps->vers_internal, ALPINE_VERSION, sizeof(ps->vers_internal));
2475 ps->vers_internal[sizeof(ps->vers_internal)-1] = '\0';
2476 if(isdigit(ps->vers_internal[0]) && ps->vers_internal[0] < '6')
2477 ps->vers_internal[0] = ps->vers_internal[0] + 4;
2479 set_current_val(&vars[V_LAST_VERS_USED], TRUE, TRUE);
2480 /* Check for special cases first */
2481 if(VAR_LAST_VERS_USED
2482 && (isdigit(ps->vers_internal[0])
2483 && ps->vers_internal[1] == '.'
2484 && isdigit((unsigned char)ps->vers_internal[2])
2485 && isdigit((unsigned char)ps->vers_internal[3])
2486 && isalpha((unsigned char)ps->vers_internal[4])
2487 && strncmp(VAR_LAST_VERS_USED, ps->vers_internal, 4) >= 0)){
2488 ps->show_new_version = 0;
2490 /* Otherwise just do lexicographic comparision... */
2491 else if(VAR_LAST_VERS_USED
2492 && strcmp(VAR_LAST_VERS_USED, ps->vers_internal) >= 0){
2493 ps->show_new_version = 0;
2495 else{
2496 #ifdef _WINDOWS
2498 * If this is the first time we've run a version > 4.40, and there
2499 * is evidence that the config file has not been used by unix pine,
2500 * then we convert color008 to colorlgr, color009 to colormgr, and
2501 * color010 to colordgr. If the config file is being used by
2502 * unix pine then color009 may really supposed to be red, etc.
2503 * Same if we've already run 4.41 or higher. We don't have to do
2504 * anything if we are new to alpine.
2506 ps->pre441 = (VAR_LAST_VERS_USED
2507 && strcmp(VAR_LAST_VERS_USED, "4.40") <= 0);
2508 #endif /* _WINDOWS */
2511 * Don't offer the new version message if we're told not to.
2513 set_current_val(&vars[V_NEW_VER_QUELL], TRUE, TRUE);
2514 ps->show_new_version = !(VAR_NEW_VER_QUELL
2515 && strcmp(ps->vers_internal,
2516 VAR_NEW_VER_QUELL) < 0);
2518 #ifdef _WINDOWS
2519 if(!ps_global->install_flag)
2520 #endif /* _WINDOWS */
2522 if(VAR_LAST_VERS_USED){
2523 strncpy(ps_global->pine_pre_vers, VAR_LAST_VERS_USED,
2524 sizeof(ps_global->pine_pre_vers));
2525 ps_global->pine_pre_vers[sizeof(ps_global->pine_pre_vers)-1] = '\0';
2528 set_variable(V_LAST_VERS_USED, ps->vers_internal, 1, 1,
2529 ps_global->ew_for_except_vars);
2533 /* Obsolete, backwards compatibility */
2534 set_current_val(&vars[V_ELM_STYLE_SAVE], TRUE, TRUE);
2535 /* Also obsolete */
2536 set_current_val(&vars[V_SAVE_BY_SENDER], TRUE, TRUE);
2537 if(!strucmp(VAR_ELM_STYLE_SAVE, "yes"))
2538 set_variable(V_SAVE_BY_SENDER, "yes", 1, 1, Main);
2539 obs_save_by_sender = !strucmp(VAR_SAVE_BY_SENDER, "yes");
2541 set_current_pattern_vals(ps);
2543 set_current_val(&vars[V_INDEX_FORMAT], TRUE, TRUE);
2544 init_index_format(VAR_INDEX_FORMAT, &ps->index_disp_format);
2546 /* this should come after pre441 is set or not */
2547 set_current_color_vals(ps);
2549 set_current_val(&vars[V_RSS_NEWS], TRUE, TRUE);
2550 set_current_val(&vars[V_RSS_WEATHER], TRUE, TRUE);
2551 set_current_val(&vars[V_WP_INDEXHEIGHT], TRUE, TRUE);
2552 set_current_val(&vars[V_WP_INDEXLINES], TRUE, TRUE);
2553 set_current_val(&vars[V_WP_AGGSTATE], TRUE, TRUE);
2554 set_current_val(&vars[V_WP_STATE], TRUE, TRUE);
2555 set_current_val(&vars[V_WP_COLUMNS], TRUE, TRUE);
2557 set_current_val(&vars[V_PRUNED_FOLDERS], TRUE, TRUE);
2558 set_current_val(&vars[V_ARCHIVED_FOLDERS], TRUE, TRUE);
2559 set_current_val(&vars[V_INCOMING_FOLDERS], TRUE, TRUE);
2560 set_current_val(&vars[V_SORT_KEY], TRUE, TRUE);
2561 if(decode_sort(VAR_SORT_KEY, &ps->def_sort, &def_sort_rev) == -1){
2562 snprintf(tmp_20k_buf, SIZEOF_20KBUF, "Sort type \"%.200s\" is invalid", VAR_SORT_KEY);
2563 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2564 ps->def_sort = SortArrival;
2565 ps->def_sort_rev = 0;
2567 else
2568 ps->def_sort_rev = def_sort_rev;
2570 cur_rule_value(&vars[V_SAVED_MSG_NAME_RULE], TRUE, TRUE);
2571 {NAMEVAL_S *v; int i;
2572 for(i = 0; (v = save_msg_rules(i)); i++)
2573 if(v->value == ps_global->save_msg_rule)
2574 break;
2576 /* if save_msg_rule is not default, or is explicitly set to default */
2577 if((ps_global->save_msg_rule != SAV_RULE_DEFLT) ||
2578 (v && v->name &&
2579 (!strucmp(ps_global->vars[V_SAVED_MSG_NAME_RULE].post_user_val.p,
2580 v->name) ||
2581 !strucmp(ps_global->vars[V_SAVED_MSG_NAME_RULE].main_user_val.p,
2582 v->name))))
2583 obs_save_by_sender = 0; /* don't overwrite */
2586 cur_rule_value(&vars[V_FCC_RULE], TRUE, TRUE);
2587 cur_rule_value(&vars[V_AB_SORT_RULE], TRUE, TRUE);
2589 #ifndef _WINDOWS
2590 cur_rule_value(&vars[V_COLOR_STYLE], TRUE, TRUE);
2591 #endif
2593 cur_rule_value(&vars[V_INDEX_COLOR_STYLE], TRUE, TRUE);
2594 cur_rule_value(&vars[V_TITLEBAR_COLOR_STYLE], TRUE, TRUE);
2595 cur_rule_value(&vars[V_FLD_SORT_RULE], TRUE, TRUE);
2596 cur_rule_value(&vars[V_INCOMING_STARTUP], TRUE, TRUE);
2597 cur_rule_value(&vars[V_PRUNING_RULE], TRUE, TRUE);
2598 cur_rule_value(&vars[V_REOPEN_RULE], TRUE, TRUE);
2599 cur_rule_value(&vars[V_GOTO_DEFAULT_RULE], TRUE, TRUE);
2600 cur_rule_value(&vars[V_THREAD_DISP_STYLE], TRUE, TRUE);
2601 cur_rule_value(&vars[V_THREAD_INDEX_STYLE], TRUE, TRUE);
2603 set_current_val(&vars[V_THREAD_MORE_CHAR], TRUE, TRUE);
2604 if(VAR_THREAD_MORE_CHAR[0] && VAR_THREAD_MORE_CHAR[1]){
2605 init_error(ps, SM_ORDER | SM_DING, 3, 5,
2606 _("Only using first character of threading-indicator-character option"));
2607 VAR_THREAD_MORE_CHAR[1] = '\0';
2610 set_current_val(&vars[V_THREAD_EXP_CHAR], TRUE, TRUE);
2611 if(VAR_THREAD_EXP_CHAR[0] && VAR_THREAD_EXP_CHAR[1]){
2612 init_error(ps, SM_ORDER | SM_DING, 3, 5,
2613 _("Only using first character of threading-expanded-character option"));
2614 VAR_THREAD_EXP_CHAR[1] = '\0';
2617 set_current_val(&vars[V_THREAD_LASTREPLY_CHAR], TRUE, TRUE);
2618 if(!VAR_THREAD_LASTREPLY_CHAR[0])
2619 VAR_THREAD_LASTREPLY_CHAR = cpystr(DF_THREAD_LASTREPLY_CHAR);
2621 if(VAR_THREAD_LASTREPLY_CHAR[0] && VAR_THREAD_LASTREPLY_CHAR[1]){
2622 init_error(ps, SM_ORDER | SM_DING, 3, 5,
2623 _("Only using first character of threading-lastreply-character option"));
2624 VAR_THREAD_LASTREPLY_CHAR[1] = '\0';
2627 set_current_val(&vars[V_MAXREMSTREAM], TRUE, TRUE);
2628 ps->s_pool.max_remstream = i = atoi(DF_MAXREMSTREAM);
2629 if(SVAR_MAXREMSTREAM(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2630 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2631 else
2632 ps->s_pool.max_remstream = i;
2634 set_current_val(&vars[V_PERMLOCKED], TRUE, TRUE);
2636 set_current_val(&vars[V_NMW_WIDTH], TRUE, TRUE);
2637 ps->nmw_width = i = atoi(DF_NMW_WIDTH);
2638 if(SVAR_NMW_WIDTH(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2639 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2640 else
2641 ps->nmw_width = i;
2643 /* backwards compatibility */
2644 if(obs_save_by_sender){
2645 ps->save_msg_rule = SAV_RULE_FROM;
2646 set_variable(V_SAVED_MSG_NAME_RULE, "by-from", 1, 1, Main);
2649 /* this should come after process_feature_list because of use_fkeys */
2650 if(!ps->start_in_index)
2651 set_current_val(&vars[V_INIT_CMD_LIST], FALSE, TRUE);
2652 if(VAR_INIT_CMD_LIST && VAR_INIT_CMD_LIST[0] && VAR_INIT_CMD_LIST[0][0])
2653 if(cmds_f)
2654 (*cmds_f)(ps, VAR_INIT_CMD_LIST);
2656 #ifdef _WINDOWS
2657 mswin_set_quit_confirm (F_OFF(F_QUIT_WO_CONFIRM, ps_global));
2658 #endif /* _WINDOWS */
2660 #ifdef DEBUG
2661 dump_configuration(0);
2662 #endif /* DEBUG */
2666 void
2667 convert_configvars_to_utf8(struct variable *vars, char *fromcharset)
2669 struct variable *v;
2672 * Make sure that everything is UTF-8.
2674 for(v = vars; v->name; v++)
2675 convert_configvar_to_utf8(v, fromcharset);
2679 void
2680 convert_configvar_to_utf8(struct variable *v, char *fromcharset)
2682 char **p, *conv, **valptr;
2683 int i;
2686 * Make sure that everything is UTF-8.
2688 if(v->is_list){
2689 for(i = 0; i < 7; i++){
2690 switch(i){
2691 case 1: valptr = v->current_val.l; break;
2692 case 0: valptr = v->main_user_val.l; break;
2693 case 2: valptr = v->changed_val.l; break;
2694 case 3: valptr = v->post_user_val.l; break;
2695 case 4: valptr = v->global_val.l; break;
2696 case 5: valptr = v->fixed_val.l; break;
2697 case 6: valptr = v->cmdline_val.l; break;
2698 default: alpine_panic("bad case in convert_configvar");
2701 if(valptr){
2702 for(p = valptr; *p; p++){
2703 if(**p){
2704 conv = convert_to_utf8(*p, fromcharset, 0);
2705 if(conv){
2706 fs_give((void **) p);
2707 *p = conv;
2714 else{
2715 for(i = 0; i < 7; i++){
2716 switch(i){
2717 case 1: valptr = &v->current_val.p; break;
2718 case 0: valptr = &v->main_user_val.p; break;
2719 case 2: valptr = &v->changed_val.p; break;
2720 case 3: valptr = &v->post_user_val.p; break;
2721 case 4: valptr = &v->global_val.p; break;
2722 case 5: valptr = &v->fixed_val.p; break;
2723 case 6: valptr = &v->cmdline_val.p; break;
2724 default: alpine_panic("bad case in convert_configvar");
2727 if(valptr && *valptr && (*valptr)[0]){
2728 conv = convert_to_utf8(*valptr, fromcharset, 0);
2729 if(conv){
2730 fs_give((void **) valptr);
2731 *valptr = conv;
2741 * Standard feature name sections
2743 char *
2744 feature_list_section(FEATURE_S *feature)
2746 #define PREF_NONE -1
2747 static char *feat_sect[] = {
2748 #define PREF_MISC 0
2749 /* TRANSLATORS: section heading in configuration screen */
2750 N_("Advanced User Preferences"),
2751 #define PREF_FLDR 1
2752 /* TRANSLATORS: section heading in configuration screen */
2753 N_("Folder Preferences"),
2754 #define PREF_ADDR 2
2755 /* TRANSLATORS: section heading in configuration screen */
2756 N_("Address Book Preferences"),
2757 #define PREF_COMP 3
2758 /* TRANSLATORS: section heading in configuration screen */
2759 N_("Composer Preferences"),
2760 #define PREF_NEWS 4
2761 /* TRANSLATORS: section heading in configuration screen */
2762 N_("News Preferences"),
2763 #define PREF_VIEW 5
2764 /* TRANSLATORS: section heading in configuration screen */
2765 N_("Viewer Preferences"),
2766 #define PREF_ACMD 6
2767 /* TRANSLATORS: section heading in configuration screen */
2768 N_("Advanced Command Preferences"),
2769 #define PREF_PRNT 7
2770 /* TRANSLATORS: section heading in configuration screen */
2771 N_("Printer Preferences"),
2772 #define PREF_RPLY 8
2773 /* TRANSLATORS: section heading in configuration screen */
2774 N_("Reply Preferences"),
2775 #define PREF_SEND 9
2776 /* TRANSLATORS: section heading in configuration screen */
2777 N_("Sending Preferences"),
2778 #define PREF_INDX 10
2779 /* TRANSLATORS: section heading in configuration screen */
2780 N_("Message Index Preferences"),
2781 #define PREF_HIDDEN 11
2782 HIDDEN_PREF
2785 return((feature && feature->section > PREF_NONE
2786 && feature->section < (sizeof(feat_sect)/sizeof(feat_sect[0])))
2787 ? _(feat_sect[feature->section]) : NULL);
2791 /* any os-specific exclusions */
2792 #if defined(DOS) || defined(OS2)
2793 #define PREF_OS_LWSD PREF_NONE
2794 #define PREF_OS_LCLK PREF_NONE
2795 #define PREF_OS_STSP PREF_NONE
2796 #define PREF_OS_SPWN PREF_NONE
2797 #define PREF_OS_XNML PREF_NONE
2798 #define PREF_OS_USFK PREF_MISC
2799 #define PREF_OS_MOUSE PREF_NONE
2800 #else
2801 #define PREF_OS_LWSD PREF_MISC
2802 #define PREF_OS_LCLK PREF_COMP
2803 #define PREF_OS_STSP PREF_MISC
2804 #define PREF_OS_SPWN PREF_MISC
2805 #define PREF_OS_XNML PREF_MISC
2806 #define PREF_OS_USFK PREF_NONE
2807 #define PREF_OS_MOUSE PREF_MISC
2808 #endif
2812 * Standard way to get at feature list members...
2814 FEATURE_S *
2815 feature_list(int index)
2818 * This list is alphabatized by feature string, but the
2819 * macro values need not be ordered.
2821 static FEATURE_S feat_list[] = {
2822 /* Composer prefs */
2823 {"allow-changing-from", NULL,
2824 F_ALLOW_CHANGING_FROM, h_config_allow_chg_from, PREF_COMP, 1},
2825 {"alternate-compose-menu", NULL,
2826 F_ALT_COMPOSE_MENU, h_config_alt_compose_menu, PREF_COMP, 0},
2827 {"alternate-role-menu", "Alternate Role (#) Menu",
2828 F_ALT_ROLE_MENU, h_config_alt_role_menu, PREF_COMP, 0},
2829 {"compose-cancel-confirm-uses-yes", NULL,
2830 F_CANCEL_CONFIRM, h_config_cancel_confirm, PREF_COMP, 0},
2831 {"compose-rejects-unqualified-addrs", "Compose Rejects Unqualified Addresses",
2832 F_COMPOSE_REJECTS_UNQUAL, h_config_compose_rejects_unqual, PREF_COMP, 0},
2833 {"compose-send-offers-first-filter", NULL,
2834 F_FIRST_SEND_FILTER_DFLT, h_config_send_filter_dflt, PREF_COMP, 0},
2835 {"compose-cut-from-cursor", "Ctrl-K Cuts From Cursor",
2836 F_DEL_FROM_DOT, h_config_del_from_dot, PREF_COMP, 0},
2837 {"compose-maps-delete-key-to-ctrl-d", "Delete Key Maps to Ctrl-D",
2838 F_COMPOSE_MAPS_DEL, h_config_compose_maps_del, PREF_COMP, 0},
2839 {"quell-dead-letter-on-cancel", "Do Not Save to Deadletter on Cancel",
2840 F_QUELL_DEAD_LETTER, h_config_quell_dead_letter, PREF_COMP, 0},
2841 {"enable-alternate-editor-cmd", "Enable Alternate Editor Command",
2842 F_ENABLE_ALT_ED, h_config_enable_alt_ed, PREF_COMP, 1},
2843 {"enable-alternate-editor-implicitly", NULL,
2844 F_ALT_ED_NOW, h_config_alt_ed_now, PREF_COMP, 0},
2845 {"enable-search-and-replace", "Enable Search and Replace",
2846 F_ENABLE_SEARCH_AND_REPL, h_config_enable_search_and_repl, PREF_COMP, 1},
2847 {"enable-sigdashes", NULL,
2848 F_ENABLE_SIGDASHES, h_config_sigdashes, PREF_COMP, 0},
2849 {"quell-mailchecks-composing-except-inbox", "Prevent Mailchecks While Composing Except for INBOX",
2850 F_QUELL_PINGS_COMPOSING, h_config_quell_checks_comp, PREF_COMP, 0},
2851 {"quell-mailchecks-composing-inbox", "Prevent Mailchecks While Composing for INBOX",
2852 F_QUELL_PINGS_COMPOSING_INBOX, h_config_quell_checks_comp_inbox, PREF_COMP, 0},
2853 {"quell-user-lookup-in-passwd-file", "Prevent User Lookup in Password File",
2854 F_QUELL_LOCAL_LOOKUP, h_config_quell_local_lookup, PREF_OS_LCLK, 0},
2855 {"spell-check-before-sending", NULL,
2856 F_ALWAYS_SPELL_CHECK, h_config_always_spell_check, PREF_COMP, 0},
2858 /* Reply Prefs */
2859 {"alternate-reply-menu", NULL,
2860 F_ALT_REPLY_MENU, h_config_alt_reply_menu, PREF_RPLY, 0},
2861 {"copy-to-address-to-from-if-it-is-us", "Copy To Address to From if it is Us",
2862 F_COPY_TO_TO_FROM, h_config_copy_to_to_from, PREF_RPLY, 0},
2863 {"enable-reply-indent-string-editing", NULL,
2864 F_ENABLE_EDIT_REPLY_INDENT, h_config_prefix_editing, PREF_RPLY, 0},
2865 {"include-attachments-in-reply", "Include Attachments in Reply",
2866 F_ATTACHMENTS_IN_REPLY, h_config_attach_in_reply, PREF_RPLY, 0},
2867 {"include-header-in-reply", "Include Header in Reply",
2868 F_INCLUDE_HEADER, h_config_include_header, PREF_RPLY, 0},
2869 {"include-text-in-reply", "Include Text in Reply",
2870 F_AUTO_INCLUDE_IN_REPLY, h_config_auto_include_reply, PREF_RPLY, 0},
2871 {"reply-always-uses-reply-to", "Reply Always Uses Reply-To",
2872 F_AUTO_REPLY_TO, h_config_auto_reply_to, PREF_RPLY, 0},
2873 {"signature-at-bottom", "Signature at Bottom",
2874 F_SIG_AT_BOTTOM, h_config_sig_at_bottom, PREF_RPLY, 0},
2875 {"strip-from-sigdashes-on-reply", "Strip From Sigdashes on Reply",
2876 F_ENABLE_STRIP_SIGDASHES, h_config_strip_sigdashes, PREF_RPLY, 0},
2877 {"forward-as-attachment", "Forward messages as attachments",
2878 F_FORWARD_AS_ATTACHMENT, h_config_forward_as_attachment, PREF_RPLY, 0},
2879 {"preserve-original-fields", NULL,
2880 F_PRESERVE_ORIGINAL_FIELD, h_config_preserve_field, PREF_RPLY, 0},
2882 /* Sending Prefs */
2883 {"disable-sender", "Do Not Generate Sender Header",
2884 F_DISABLE_SENDER, h_config_disable_sender, PREF_SEND, 0},
2885 {"use-sender-not-x-sender", "Use Sender Instead of X-X-Sender",
2886 F_USE_SENDER_NOT_X, h_config_use_sender_not_x, PREF_SEND, 0},
2887 {"quell-flowed-text", "Do Not Send Flowed Text",
2888 F_QUELL_FLOWED_TEXT, h_config_quell_flowed_text, PREF_SEND, 0},
2889 {"downgrade-multipart-to-text", "Downgrade Multipart to Text",
2890 F_COMPOSE_ALWAYS_DOWNGRADE, h_downgrade_multipart_to_text, PREF_SEND, 0},
2891 {"enable-8bit-esmtp-negotiation", "Enable 8bit ESMTP Negotiation",
2892 F_ENABLE_8BIT, h_config_8bit_smtp, PREF_SEND, 1},
2893 #ifdef BACKGROUND_POST
2894 {"enable-background-sending", NULL,
2895 F_BACKGROUND_POST, h_config_compose_bg_post, PREF_SEND, 0},
2896 #endif
2897 {"enable-delivery-status-notification", NULL,
2898 F_DSN, h_config_compose_dsn, PREF_SEND, 0},
2899 {"enable-verbose-smtp-posting", "Enable Verbose SMTP Posting",
2900 F_VERBOSE_POST, h_config_verbose_post, PREF_SEND, 0},
2901 {"fcc-without-attachments", "Fcc Does Not Include Attachments",
2902 F_NO_FCC_ATTACH, h_config_no_fcc_attach, PREF_SEND, 0},
2903 {"fcc-on-bounce", "Include Fcc When Bouncing Messages",
2904 F_FCC_ON_BOUNCE, h_config_fcc_on_bounce, PREF_SEND, 0},
2905 {"mark-fcc-seen", NULL,
2906 F_MARK_FCC_SEEN, h_config_mark_fcc_seen, PREF_SEND, 0},
2907 {"fcc-only-without-confirm", "Send to Fcc Only Without Confirming",
2908 F_AUTO_FCC_ONLY, h_config_auto_fcc_only, PREF_SEND, 0},
2909 {"send-without-confirm", "Send Without Confirming",
2910 F_SEND_WO_CONFIRM, h_config_send_wo_confirm, PREF_SEND, 0},
2911 {"strip-whitespace-before-send", "Strip Whitespace Before Sending",
2912 F_STRIP_WS_BEFORE_SEND, h_config_strip_ws_before_send, PREF_SEND, 0},
2913 {"warn-if-blank-fcc", "Warn if Blank Fcc",
2914 F_WARN_ABOUT_NO_FCC, h_config_warn_if_fcc_blank, PREF_SEND, 0},
2915 {"warn-if-blank-subject", "Warn if Blank Subject",
2916 F_WARN_ABOUT_NO_SUBJECT, h_config_warn_if_subj_blank, PREF_SEND, 0},
2917 {"warn-if-blank-to-and-cc-and-newsgroups", "Warn if Blank To and CC and Newsgroups",
2918 F_WARN_ABOUT_NO_TO_OR_CC, h_config_warn_if_no_to_or_cc, PREF_SEND, 0},
2920 /* Folder */
2921 {"combined-folder-display", NULL,
2922 F_CMBND_FOLDER_DISP, h_config_combined_folder_display, PREF_FLDR, 0},
2923 {"combined-subdirectory-display", NULL,
2924 F_CMBND_SUBDIR_DISP, h_config_combined_subdir_display, PREF_FLDR, 0},
2925 {"enable-lame-list-mode", "Compensate for Deficient IMAP servers",
2926 F_FIX_BROKEN_LIST, h_config_lame_list_mode, PREF_FLDR, 0},
2927 {"enable-dot-folders", "Enable Hidden Folders",
2928 F_ENABLE_DOT_FOLDERS, h_config_enable_dot_folders, PREF_FLDR, 0},
2929 {"enable-incoming-folders", "Enable Incoming Folders Collection",
2930 F_ENABLE_INCOMING, h_config_enable_incoming, PREF_FLDR, 0},
2931 {"enable-incoming-folders-checking", NULL,
2932 F_ENABLE_INCOMING_CHECKING, h_config_enable_incoming_checking, PREF_FLDR, 0},
2933 {"incoming-checking-includes-total", NULL,
2934 F_INCOMING_CHECKING_TOTAL, h_config_incoming_checking_total, PREF_FLDR, 0},
2935 {"incoming-checking-uses-recent", NULL,
2936 F_INCOMING_CHECKING_RECENT, h_config_incoming_checking_recent, PREF_FLDR, 0},
2937 {"expanded-view-of-folders", "Expanded View of Folders",
2938 F_EXPANDED_FOLDERS, h_config_expanded_folders, PREF_FLDR, 0},
2939 {"quell-empty-directories", "Hide Empty Directories",
2940 F_QUELL_EMPTY_DIRS, h_config_quell_empty_dirs, PREF_FLDR, 0},
2941 {"separate-folder-and-directory-entries", "Separate Folder and Directory Entries",
2942 F_SEPARATE_FLDR_AS_DIR, h_config_separate_fold_dir_view, PREF_FLDR, 0},
2943 {"single-column-folder-list", NULL,
2944 F_SINGLE_FOLDER_LIST, h_config_single_list, PREF_FLDR, 0},
2945 {"sort-default-fcc-alpha", "Sort Default Fcc Folder Alphabetically",
2946 F_SORT_DEFAULT_FCC_ALPHA, h_config_sort_fcc_alpha, PREF_FLDR, 0},
2947 {"sort-default-save-alpha", "Sort Default Save Folder Alphabetically",
2948 F_SORT_DEFAULT_SAVE_ALPHA, h_config_sort_save_alpha, PREF_FLDR, 0},
2949 {"vertical-folder-list", "Use Vertical Folder List",
2950 F_VERTICAL_FOLDER_LIST, h_config_vertical_list, PREF_FLDR, 0},
2952 /* Addr book */
2953 {"combined-addrbook-display", "Combined Address Book Display",
2954 F_CMBND_ABOOK_DISP, h_config_combined_abook_display, PREF_ADDR, 0},
2955 {"expanded-view-of-addressbooks", "Expanded View of Address Books",
2956 F_EXPANDED_ADDRBOOKS, h_config_expanded_addrbooks, PREF_ADDR, 0},
2957 {"expanded-view-of-distribution-lists", "Expanded View of Distribution Lists",
2958 F_EXPANDED_DISTLISTS, h_config_expanded_distlists, PREF_ADDR, 0},
2959 #ifdef ENABLE_LDAP
2960 {"ldap-result-to-addrbook-add", "LDAP Result to Addressbook Add",
2961 F_ADD_LDAP_TO_ABOOK, h_config_add_ldap, PREF_ADDR, 0},
2962 #endif
2964 /* Index prefs */
2965 {"auto-open-next-unread", NULL,
2966 F_AUTO_OPEN_NEXT_UNREAD, h_config_auto_open_unread, PREF_INDX, 0},
2967 {"continue-tab-without-confirm", "Continue NextNew Without Confirming",
2968 F_TAB_NO_CONFIRM, h_config_tab_no_prompt, PREF_INDX, 0},
2969 {"convert-dates-to-localtime", NULL,
2970 F_DATES_TO_LOCAL, h_config_dates_to_local, PREF_INDX, 0},
2971 {"delete-skips-deleted", NULL,
2972 F_DEL_SKIPS_DEL, h_config_del_skips_del, PREF_INDX, 1},
2973 {"disable-index-locale-dates", NULL,
2974 F_DISABLE_INDEX_LOCALE_DATES, h_config_disable_index_locale_dates, PREF_INDX, 0},
2975 {"enable-cruise-mode", NULL,
2976 F_ENABLE_SPACE_AS_TAB, h_config_cruise_mode, PREF_INDX, 0},
2977 {"enable-cruise-mode-delete", "Enable Cruise Mode With Deleting",
2978 F_ENABLE_TAB_DELETES, h_config_cruise_mode_delete, PREF_INDX, 0},
2979 {"mark-for-cc", "Mark for CC",
2980 F_MARK_FOR_CC, h_config_mark_for_cc, PREF_INDX, 1},
2981 {"next-thread-without-confirm", "Read Next Thread Without Confirming",
2982 F_NEXT_THRD_WO_CONFIRM, h_config_next_thrd_wo_confirm, PREF_INDX, 0},
2983 {"return-to-inbox-without-confirm", "Return to INBOX Without Confirming",
2984 F_RET_INBOX_NO_CONFIRM, h_config_inbox_no_confirm, PREF_INDX, 0},
2985 {"show-sort", "Show Sort in Titlebar",
2986 F_SHOW_SORT, h_config_show_sort, PREF_INDX, 0},
2987 {"tab-uses-unseen-for-next-folder", "Tab Uses Unseen for Next Folder",
2988 F_TAB_USES_UNSEEN, h_config_tab_uses_unseen, PREF_INDX, 0},
2989 {"tab-visits-next-new-message-only", NULL,
2990 F_TAB_TO_NEW, h_config_tab_new_only, PREF_INDX, 0},
2991 {"thread-index-shows-important-color", NULL,
2992 F_COLOR_LINE_IMPORTANT, h_config_color_thrd_import, PREF_INDX, 0},
2993 {"thread-sorts-by-arrival", "Thread Sorts by Arrival",
2994 F_THREAD_SORTS_BY_ARRIVAL, h_config_thread_sorts_by_arrival, PREF_INDX, 0},
2996 /* Viewer prefs */
2997 {"enable-msg-view-addresses", "Enable Message View Address Links",
2998 F_SCAN_ADDR, h_config_enable_view_addresses, PREF_VIEW, 0},
2999 {"enable-msg-view-attachments", "Enable Message View Attachment Links",
3000 F_VIEW_SEL_ATTACH, h_config_enable_view_attach, PREF_VIEW, 0},
3001 {"enable-msg-view-urls", "Enable Message View URL Links",
3002 F_VIEW_SEL_URL, h_config_enable_view_url, PREF_VIEW, 1},
3003 {"enable-msg-view-web-hostnames", "Enable Message View Web Hostname Links",
3004 F_VIEW_SEL_URL_HOST, h_config_enable_view_web_host, PREF_VIEW, 1},
3005 {"enable-msg-view-forced-arrows", "Enable Message View Forced Arrows",
3006 F_FORCE_ARROWS, h_config_enable_view_arrows, PREF_VIEW, 0},
3007 /* set to TRUE for windows */
3008 {"pass-c1-control-characters-as-is", NULL,
3009 F_PASS_C1_CONTROL_CHARS, h_config_pass_c1_control, PREF_VIEW, 0},
3010 {"pass-control-characters-as-is", NULL,
3011 F_PASS_CONTROL_CHARS, h_config_pass_control, PREF_VIEW, 0},
3012 {"prefer-plain-text", NULL,
3013 F_PREFER_PLAIN_TEXT, h_config_prefer_plain_text, PREF_VIEW, 0},
3014 {"quell-charset-warning", "Suppress Character Set Warning",
3015 F_QUELL_CHARSET_WARNING, h_config_quell_charset_warning, PREF_VIEW, 0},
3016 {"quell-server-after-link-in-html", "Suppress Server After Link in HTML",
3017 F_QUELL_HOST_AFTER_URL, h_config_quell_host_after_url, PREF_VIEW, 0},
3019 /* News */
3020 {"compose-sets-newsgroup-without-confirm", "Compose Sets Newsgroup Without Confirming",
3021 F_COMPOSE_TO_NEWSGRP, h_config_compose_news_wo_conf, PREF_NEWS, 0},
3022 {"enable-8bit-nntp-posting", "Enable 8bit NNTP Posting",
3023 F_ENABLE_8BIT_NNTP, h_config_8bit_nntp, PREF_NEWS, 0},
3024 {"enable-multiple-newsrcs", NULL,
3025 F_ENABLE_MULNEWSRCS, h_config_enable_mulnewsrcs, PREF_NEWS, 0},
3026 {"mult-newsrc-hostnames-as-typed", "Multiple Newsrc Hostnames as Typed",
3027 F_MULNEWSRC_HOSTNAMES_AS_TYPED, h_config_mulnews_as_typed, PREF_NEWS, 0},
3028 {"hide-nntp-path", "Hide NNTP Path",
3029 F_HIDE_NNTP_PATH, h_config_hide_nntp_path, PREF_NEWS, 0},
3030 {"news-approximates-new-status", NULL,
3031 F_FAKE_NEW_IN_NEWS, h_config_news_uses_recent, PREF_NEWS, 1},
3032 {"news-deletes-across-groups", NULL,
3033 F_NEWS_CROSS_DELETE, h_config_news_cross_deletes, PREF_NEWS, 0},
3034 {"news-offers-catchup-on-close", "News Offers Catchup on Close",
3035 F_NEWS_CATCHUP, h_config_news_catchup, PREF_NEWS, 0},
3036 {"news-post-without-validation", NULL,
3037 F_NO_NEWS_VALIDATION, h_config_post_wo_validation, PREF_NEWS, 0},
3038 {"news-read-in-newsrc-order", "News Read in Newsrc Order",
3039 F_READ_IN_NEWSRC_ORDER, h_config_read_in_newsrc_order, PREF_NEWS, 0},
3040 {"nntp-search-uses-overview", "NNTP Search Uses Overview",
3041 F_NNTP_SEARCH_USES_OVERVIEW, h_config_nntp_search_uses_overview, PREF_NEWS, 1},
3042 {"predict-nntp-server", "Predict NNTP Server",
3043 F_PREDICT_NNTP_SERVER, h_config_predict_nntp_server, PREF_NEWS, 0},
3044 {"quell-extra-post-prompt", "Suppress Extra Posting Prompt",
3045 F_QUELL_EXTRA_POST_PROMPT, h_config_quell_post_prompt, PREF_NEWS, 0},
3047 /* Print */
3048 {"enable-print-via-y-command", NULL,
3049 F_ENABLE_PRYNT, h_config_enable_y_print, PREF_PRNT, 0},
3050 {"print-formfeed-between-messages", NULL,
3051 F_AGG_PRINT_FF, h_config_ff_between_msgs, PREF_PRNT, 0},
3052 {"print-includes-from-line", NULL,
3053 F_FROM_DELIM_IN_PRINT, h_config_print_from, PREF_PRNT, 0},
3054 {"print-index-enabled", NULL,
3055 F_PRINT_INDEX, h_config_print_index, PREF_PRNT, 0},
3056 {"print-offers-custom-cmd-prompt", "Print Offers Custom Command Prompt",
3057 F_CUSTOM_PRINT, h_config_custom_print, PREF_PRNT, 0},
3059 /* adv cmd prefs */
3060 {"enable-aggregate-command-set", NULL,
3061 F_ENABLE_AGG_OPS, h_config_enable_agg_ops, PREF_ACMD, 1},
3062 {"enable-arrow-navigation", NULL,
3063 F_ARROW_NAV, h_config_arrow_nav, PREF_ACMD, 1},
3064 {"enable-arrow-navigation-relaxed", NULL,
3065 F_RELAXED_ARROW_NAV, h_config_relaxed_arrow_nav, PREF_ACMD, 1},
3066 {"enable-bounce-cmd", "Enable Bounce Command",
3067 F_ENABLE_BOUNCE, h_config_enable_bounce, PREF_ACMD, 1},
3068 {"enable-exit-via-lessthan-command", NULL,
3069 F_ENABLE_LESSTHAN_EXIT, h_config_enable_lessthan_exit, PREF_ACMD, 1},
3070 {"enable-flag-cmd", "Enable Flag Command",
3071 F_ENABLE_FLAG, h_config_enable_flag, PREF_ACMD, 1},
3072 {"enable-flag-screen-implicitly", NULL,
3073 F_FLAG_SCREEN_DFLT, h_config_flag_screen_default, PREF_ACMD, 0},
3074 {"enable-flag-screen-keyword-shortcut", NULL,
3075 F_FLAG_SCREEN_KW_SHORTCUT, h_config_flag_screen_kw_shortcut,PREF_ACMD, 1},
3076 {"enable-full-header-and-text", "Enable Full Header and Text",
3077 F_ENABLE_FULL_HDR_AND_TEXT, h_config_enable_full_hdr_and_text, PREF_ACMD, 0},
3078 {"enable-full-header-cmd", "Enable Full Header Command",
3079 F_ENABLE_FULL_HDR, h_config_enable_full_hdr, PREF_ACMD, 1},
3080 {"enable-goto-in-file-browser", "Enable Goto in File Browser",
3081 F_ALLOW_GOTO, h_config_allow_goto, PREF_ACMD, 1},
3082 {"enable-jump-shortcut", NULL,
3083 F_ENABLE_JUMP, h_config_enable_jump, PREF_ACMD, 1},
3084 {"enable-partial-match-lists", NULL,
3085 F_ENABLE_SUB_LISTS, h_config_sub_lists, PREF_ACMD, 1},
3086 {"enable-tab-completion", NULL,
3087 F_ENABLE_TAB_COMPLETE, h_config_enable_tab_complete, PREF_ACMD, 1},
3088 {"enable-unix-pipe-cmd", "Enable Unix Pipe Command",
3089 F_ENABLE_PIPE, h_config_enable_pipe, PREF_ACMD, 1},
3090 {"quell-full-header-auto-reset", "Suppress Full Header Auto Reset",
3091 F_QUELL_FULL_HDR_RESET, h_config_quell_full_hdr_reset, PREF_ACMD, 0},
3093 /* Adv user prefs */
3094 #if !defined(DOS) && !defined(OS2)
3095 {"allow-talk", NULL,
3096 F_ALLOW_TALK, h_config_allow_talk, PREF_MISC, 0},
3097 #endif
3098 {"assume-slow-link", NULL,
3099 F_FORCE_LOW_SPEED, h_config_force_low_speed, PREF_OS_LWSD, 0},
3100 {"auto-move-read-msgs", "Auto Move Read Messages",
3101 F_AUTO_READ_MSGS, h_config_auto_read_msgs, PREF_MISC, 0},
3102 {"auto-unselect-after-apply", NULL,
3103 F_AUTO_UNSELECT, h_config_auto_unselect, PREF_MISC, 0},
3104 {"auto-unzoom-after-apply", NULL,
3105 F_AUTO_UNZOOM, h_config_auto_unzoom, PREF_MISC, 1},
3106 {"auto-zoom-after-select", NULL,
3107 F_AUTO_ZOOM, h_config_auto_zoom, PREF_MISC, 1},
3108 {"busy-cue-spinner-only", NULL,
3109 F_USE_BORING_SPINNER, h_config_use_boring_spinner, PREF_MISC, 0},
3110 {"check-newmail-when-quitting", NULL,
3111 F_CHECK_MAIL_ONQUIT, h_config_check_mail_onquit, PREF_MISC, 0},
3112 {"confirm-role-even-for-default", "Confirm Role Even for Default",
3113 F_ROLE_CONFIRM_DEFAULT, h_config_confirm_role, PREF_MISC, 0},
3114 {"disable-keymenu", NULL,
3115 F_BLANK_KEYMENU, h_config_blank_keymenu, PREF_MISC, 0},
3116 {"disable-password-caching", NULL,
3117 F_DISABLE_PASSWORD_CACHING, h_config_disable_password_caching,
3118 PREF_MISC, 0},
3119 #ifdef PASSFILE
3120 {"disable-password-file-saving", NULL,
3121 F_DISABLE_PASSWORD_FILE_SAVING, h_config_disable_password_file_saving,
3122 PREF_MISC, 0},
3123 #endif
3124 {"disable-regular-expression-matching-for-alternate-addresses", NULL,
3125 F_DISABLE_REGEX, h_config_disable_regex, PREF_MISC, 0},
3126 {"disable-save-input-history", NULL,
3127 F_DISABLE_SAVE_INPUT_HISTORY, h_config_input_history, PREF_MISC, 0},
3128 {"disable-take-fullname-in-addresses", "Disable Take Fullname in Addresses",
3129 F_DISABLE_TAKE_FULLNAMES, h_config_take_fullname, PREF_MISC, 0},
3130 {"disable-take-last-comma-first", NULL,
3131 F_DISABLE_TAKE_LASTFIRST, h_config_take_lastfirst, PREF_MISC, 0},
3132 {"disable-terminal-reset-for-display-filters", "Disable Terminal Reset for Display Filters",
3133 F_DISABLE_TERM_RESET_DISP, h_config_disable_reset_disp, PREF_MISC, 0},
3134 {"enable-dot-files", NULL,
3135 F_ENABLE_DOT_FILES, h_config_enable_dot_files, PREF_MISC, 0},
3136 {"enable-fast-recent-test", NULL,
3137 F_ENABLE_FAST_RECENT, h_config_fast_recent, PREF_MISC, 0},
3138 {"enable-mail-check-cue", NULL,
3139 F_SHOW_DELAY_CUE, h_config_show_delay_cue, PREF_MISC, 0},
3140 {"enable-mailcap-param-substitution", "Enable Mailcap Parameter Substitution",
3141 F_DO_MAILCAP_PARAM_SUBST, h_config_mailcap_params, PREF_MISC, 0},
3142 {"enable-mouse-in-xterm", "Enable Mouse in Xterm",
3143 F_ENABLE_MOUSE, h_config_enable_mouse, PREF_OS_MOUSE, 0},
3144 {"enable-newmail-in-xterm-icon", "Enable Newmail in Xterm Icon",
3145 F_ENABLE_XTERM_NEWMAIL, h_config_enable_xterm_newmail, PREF_OS_XNML, 0},
3146 {"enable-newmail-short-text-in-icon", "Enable Newmail Short Text in Icon",
3147 F_ENABLE_NEWMAIL_SHORT_TEXT, h_config_enable_newmail_short_text, PREF_OS_XNML, 0},
3148 {"enable-suspend", NULL,
3149 F_CAN_SUSPEND, h_config_can_suspend, PREF_MISC, 0},
3150 {"enable-take-export", NULL,
3151 F_ENABLE_TAKE_EXPORT, h_config_enable_take_export, PREF_MISC, 0},
3152 {"enable-rules-under-take", "Enable Take Rules",
3153 F_ENABLE_ROLE_TAKE, h_config_enable_role_take, PREF_MISC, 0},
3154 #ifdef _WINDOWS
3155 {"enable-tray-icon", NULL,
3156 F_ENABLE_TRAYICON, h_config_tray_icon, PREF_MISC, 0},
3157 #endif
3158 {"expose-hidden-config", NULL,
3159 F_EXPOSE_HIDDEN_CONFIG, h_config_expose_hidden_config, PREF_MISC, 0},
3160 {"expunge-only-manually", NULL,
3161 F_EXPUNGE_MANUALLY, h_config_expunge_manually, PREF_MISC, 0},
3162 {"expunge-without-confirm", "Expunge Without Confirming",
3163 F_AUTO_EXPUNGE, h_config_auto_expunge, PREF_MISC, 0},
3164 {"expunge-without-confirm-everywhere", "Expunge Without Confirming Everywhere",
3165 F_FULL_AUTO_EXPUNGE, h_config_full_auto_expunge, PREF_MISC, 0},
3166 {"force-arrow-cursor", NULL,
3167 F_FORCE_ARROW, h_config_force_arrow, PREF_MISC, 0},
3168 {"ignore-size-changes", NULL,
3169 F_IGNORE_SIZE, h_config_ignore_size, PREF_MISC, 0},
3170 {"maildrops-preserve-state", NULL,
3171 F_MAILDROPS_PRESERVE_STATE, h_config_maildrops_preserve_state,
3172 PREF_MISC, 0},
3173 {"offer-expunge-of-inbox", "Offer Expunge of INBOX",
3174 F_EXPUNGE_INBOX, h_config_expunge_inbox, PREF_MISC, 0},
3175 {"offer-expunge-of-stayopen-folders", "Offer Expunge of Stayopen Folders",
3176 F_EXPUNGE_STAYOPENS, h_config_expunge_stayopens, PREF_MISC, 0},
3177 {"preopen-stayopen-folders", NULL,
3178 F_PREOPEN_STAYOPENS, h_config_preopen_stayopens, PREF_MISC, 0},
3179 {"preserve-start-stop-characters", "Preserve Start/Stop Characters",
3180 F_PRESERVE_START_STOP, h_config_preserve_start_stop, PREF_OS_STSP, 0},
3181 {"quell-folder-internal-msg", "Prevent Folder Internal Message",
3182 F_QUELL_INTERNAL_MSG, h_config_quell_folder_internal_msg, PREF_MISC, 0},
3183 {"quell-partial-fetching", "Prevent Partial Fetching",
3184 F_QUELL_PARTIAL_FETCH, h_config_quell_partial, PREF_MISC, 0},
3185 {"prune-uses-yyyy-mm", "Prune Uses YYYY-MM",
3186 F_PRUNE_USES_ISO, h_config_prune_uses_iso, PREF_MISC, 0},
3187 {"quit-without-confirm", "Quit Without Confirming",
3188 F_QUIT_WO_CONFIRM, h_config_quit_wo_confirm, PREF_MISC, 0},
3189 {"quote-replace-nonflowed", NULL,
3190 F_QUOTE_REPLACE_NOFLOW, h_config_quote_replace_noflow, PREF_MISC, 0},
3191 {"save-aggregates-copy-sequence", "Save Combines Copies (may be out of order)",
3192 F_AGG_SEQ_COPY, h_config_save_aggregates, PREF_MISC, 1},
3193 {"save-partial-msg-without-confirm", "Save Partial Message Without Confirming",
3194 F_SAVE_PARTIAL_WO_CONFIRM, h_config_save_part_wo_confirm, PREF_MISC, 0},
3195 {"save-will-advance", NULL,
3196 F_SAVE_ADVANCES, h_config_save_advances, PREF_MISC, 0},
3197 {"save-will-not-delete", NULL,
3198 F_SAVE_WONT_DELETE, h_config_save_wont_delete, PREF_MISC, 0},
3199 {"save-will-quote-leading-froms", NULL,
3200 F_QUOTE_ALL_FROMS, h_config_quote_all_froms, PREF_MISC, 0},
3201 {"scramble-message-id", "Scramble the Message-ID When Sending",
3202 F_ROT13_MESSAGE_ID, h_config_scramble_message_id, PREF_MISC, 0},
3203 {"select-without-confirm", "Select Ctrl-T Foldername Without Confirming",
3204 F_SELECT_WO_CONFIRM, h_config_select_wo_confirm, PREF_MISC, 0},
3205 {"show-cursor", NULL,
3206 F_SHOW_CURSOR, h_config_show_cursor, PREF_MISC, 0},
3207 {"show-plain-text-internally", NULL,
3208 F_SHOW_TEXTPLAIN_INT, h_config_textplain_int, PREF_MISC, 0},
3209 {"show-selected-in-boldface", "Show Selected in Boldface",
3210 F_SELECTED_SHOWN_BOLD, h_config_select_in_bold, PREF_MISC, 0},
3211 {"slash-collapses-entire-thread", NULL,
3212 F_SLASH_COLL_ENTIRE, h_config_slash_coll_entire, PREF_MISC, 0},
3213 #ifdef _WINDOWS
3214 {"store-window-position-in-config", "Store Window Position in Config",
3215 F_STORE_WINPOS_IN_CONFIG, h_config_winpos_in_config, PREF_MISC, 0},
3216 #endif
3217 {"suppress-asterisks-in-password-prompt", "Suppress Asterisks in Password Prompt",
3218 F_QUELL_ASTERISKS, h_config_quell_asterisks,
3219 PREF_MISC, 0},
3220 {"quell-attachment-extension-warn", "Suppress Attachment Extension Warning",
3221 F_QUELL_ATTACH_EXT_WARN, h_config_quell_attach_ext_warn,
3222 PREF_MISC, 0},
3223 {"quell-attachment-extra-prompt", "Suppress Attachment Extra Prompt",
3224 F_QUELL_ATTACH_EXTRA_PROMPT, h_config_quell_attach_extra_prompt,
3225 PREF_MISC, 0},
3226 {"quell-berkeley-format-timezone", "Suppress Berkeley Format Timezone",
3227 F_QUELL_BEZERK_TIMEZONE, h_config_no_bezerk_zone, PREF_MISC, 0},
3228 {"quell-content-id", "Suppress Content-ID",
3229 F_QUELL_CONTENT_ID, h_config_quell_content_id, PREF_MISC, 0},
3230 {"quell-filtering-done-message", "Suppress Filtering Done Message",
3231 F_QUELL_FILTER_DONE_MSG, h_config_quell_filtering_done_message,
3232 PREF_MISC, 0},
3233 {"quell-filtering-messages", "Suppress Filtering Messages",
3234 F_QUELL_FILTER_MSGS, h_config_quell_filtering_messages,
3235 PREF_MISC, 0},
3236 {"quell-imap-envelope-update", "Suppress IMAP Envelope Update",
3237 F_QUELL_IMAP_ENV_CB, h_config_quell_imap_env, PREF_MISC, 0},
3238 {"quell-lock-failure-warnings", "Suppress Lock Failure Warnings",
3239 F_QUELL_LOCK_FAILURE_MSGS, h_config_quell_lock_failure_warnings,
3240 PREF_MISC, 0},
3241 {"quell-maildomain-warning", "Suppress Maildomain Warning",
3242 F_QUELL_MAILDOMAIN_WARNING, h_config_quell_domain_warn, PREF_MISC, 0},
3243 {"quell-news-envelope-update", "Suppress News Envelope Update",
3244 F_QUELL_NEWS_ENV_CB, h_config_quell_news_env, PREF_MISC, 0},
3245 #ifdef _WINDOWS
3246 {"quell-ssl-largeblocks", "Prevent SSL Largeblocks",
3247 F_QUELL_SSL_LARGEBLOCKS, h_config_quell_ssl_largeblocks, PREF_MISC, 0},
3248 #endif
3249 {"quell-status-message-beeping", "Suppress Status Message Beeping",
3250 F_QUELL_BEEPS, h_config_quell_beeps, PREF_MISC, 0},
3251 {"quell-timezone-comment-when-sending", "Suppress Timezone Comment When Sending",
3252 F_QUELL_TIMEZONE, h_config_quell_tz_comment, PREF_MISC, 0},
3253 {"suppress-user-agent-when-sending", NULL,
3254 F_QUELL_USERAGENT, h_config_suppress_user_agent, PREF_MISC, 0},
3255 {"tab-checks-recent", "Tab Checks for Recent Messages",
3256 F_TAB_CHK_RECENT, h_config_tab_checks_recent, PREF_MISC, 0},
3257 {"termdef-takes-precedence", NULL,
3258 F_TCAP_WINS, h_config_termcap_wins, PREF_MISC, 0},
3259 {"try-alternative-authentication-driver-first", NULL,
3260 F_PREFER_ALT_AUTH, h_config_alt_auth, PREF_MISC, 0},
3261 {"unselect-will-not-advance", NULL,
3262 F_UNSELECT_WONT_ADVANCE, h_config_unsel_wont_advance, PREF_MISC, 0},
3263 {"use-current-dir", "Use Current Directory",
3264 F_USE_CURRENT_DIR, h_config_use_current_dir, PREF_MISC, 0},
3265 {"use-function-keys", NULL,
3266 F_USE_FK, h_config_use_fk, PREF_OS_USFK, 0},
3267 {"use-regular-startup-rule-for-stayopen-folders", "Use Regular Startup Rule for Stayopen Folders",
3268 F_STARTUP_STAYOPEN, h_config_use_reg_start_for_stayopen, PREF_MISC, 0},
3269 {"use-resent-to-in-rules", "Use Resent-To in Rules",
3270 F_USE_RESENTTO, h_config_use_resentto, PREF_MISC, 0},
3271 {"use-subshell-for-suspend", "Use Subshell for Suspend",
3272 F_SUSPEND_SPAWNS, h_config_suspend_spawns, PREF_OS_SPWN, 0},
3273 #ifndef _WINDOWS
3274 {"use-system-translation", NULL,
3275 F_USE_SYSTEM_TRANS, h_config_use_system_translation, PREF_MISC, 0},
3276 #endif
3278 /* Hidden Features */
3279 {"old-growth", NULL,
3280 F_OLD_GROWTH, NO_HELP, PREF_NONE, 0},
3281 {"disable-config-cmd", NULL,
3282 F_DISABLE_CONFIG_SCREEN, h_config_disable_config_cmd, PREF_HIDDEN, 0},
3283 {"disable-keyboard-lock-cmd", NULL,
3284 F_DISABLE_KBLOCK_CMD, h_config_disable_kb_lock, PREF_HIDDEN, 0},
3285 {"disable-password-cmd", NULL,
3286 F_DISABLE_PASSWORD_CMD, h_config_disable_password_cmd, PREF_HIDDEN, 0},
3287 {"disable-pipes-in-sigs", NULL,
3288 F_DISABLE_PIPES_IN_SIGS, h_config_disable_pipes_in_sigs, PREF_HIDDEN, 0},
3289 {"disable-pipes-in-templates", NULL,
3290 F_DISABLE_PIPES_IN_TEMPLATES, h_config_disable_pipes_in_templates,
3291 PREF_HIDDEN, 0},
3292 {"disable-roles-setup-cmd", NULL,
3293 F_DISABLE_ROLES_SETUP, h_config_disable_roles_setup, PREF_HIDDEN, 0},
3294 {"disable-roles-sig-edit", NULL,
3295 F_DISABLE_ROLES_SIGEDIT, h_config_disable_roles_sigedit, PREF_HIDDEN, 0},
3296 {"disable-roles-template-edit", NULL,
3297 F_DISABLE_ROLES_TEMPLEDIT, h_config_disable_roles_templateedit,
3298 PREF_HIDDEN, 0},
3299 {"disable-setlocale-collate", NULL,
3300 F_DISABLE_SETLOCALE_COLLATE, h_config_disable_collate, PREF_HIDDEN, 0},
3301 {"disable-shared-namespaces", NULL,
3302 F_DISABLE_SHARED_NAMESPACES, h_config_disable_shared, PREF_HIDDEN, 0},
3303 {"disable-signature-edit-cmd", NULL,
3304 F_DISABLE_SIGEDIT_CMD, h_config_disable_signature_edit, PREF_HIDDEN, 0},
3305 {"new-thread-on-blank-subject", "New Thread on Blank Subject",
3306 F_NEW_THREAD_ON_BLANK_SUBJECT, h_config_new_thread_blank_subject, PREF_HIDDEN, 1},
3307 {"quell-personal-name-prompt", NULL,
3308 F_QUELL_PERSONAL_NAME_PROMPT, h_config_quell_personal_name_prompt, PREF_HIDDEN, 0},
3309 {"quell-user-id-prompt", "Quell User ID Prompt",
3310 F_QUELL_USER_ID_PROMPT, h_config_quell_user_id_prompt, PREF_HIDDEN, 0},
3311 #ifdef SMIME
3312 {"smime-dont-do-smime", "S/MIME -- Turn off S/MIME",
3313 F_DONT_DO_SMIME, h_config_smime_dont_do_smime, PREF_HIDDEN, 0},
3314 {"smime-encrypt-by-default", "S/MIME -- Encrypt by Default",
3315 F_ENCRYPT_DEFAULT_ON, h_config_smime_encrypt_by_default, PREF_HIDDEN, 0},
3316 {"smime-remember-passphrase", "S/MIME -- Remember S/MIME Passphrase",
3317 F_REMEMBER_SMIME_PASSPHRASE, h_config_smime_remember_passphrase, PREF_HIDDEN, 0},
3318 {"smime-sign-by-default", "S/MIME -- Sign by Default",
3319 F_SIGN_DEFAULT_ON, h_config_smime_sign_by_default, PREF_HIDDEN, 0},
3320 {"smime-use-store-only", "S/MIME -- Validate Using Certificate Store Only",
3321 F_USE_CERT_STORE_ONLY, h_config_smime_use_cert_store, PREF_HIDDEN, 1},
3322 #ifdef APPLEKEYCHAIN
3323 {"publiccerts-in-keychain", "S/MIME -- Public Certs in MacOS Keychain",
3324 F_PUBLICCERTS_IN_KEYCHAIN, h_config_smime_pubcerts_in_keychain, PREF_HIDDEN, 0},
3325 #endif
3326 #endif
3327 {"selectable-item-nobold", NULL,
3328 F_SLCTBL_ITEM_NOBOLD, NO_HELP, PREF_NONE, 0},
3329 {"send-confirms-only-expanded", NULL, /* exposed in Web Alpine */
3330 F_SEND_CONFIRM_ON_EXPAND, h_config_send_confirms_only_expanded, PREF_HIDDEN, 0},
3331 {"enable-jump-cmd", NULL, /* exposed in Web Alpine */
3332 F_ENABLE_JUMP_CMD, h_config_enable_jump_command, PREF_HIDDEN, 0},
3333 {"enable-newmail-sound", NULL, /* exposed in Web Alpine */
3334 F_ENABLE_NEWMAIL_SOUND, h_config_enable_newmail_sound, PREF_HIDDEN, 0},
3335 {"render-html-internally", NULL, /* exposed in Web Alpine */
3336 F_RENDER_HTML_INTERNALLY, h_config_render_html_internally, PREF_HIDDEN, 0}
3339 return((index >= 0 && index < (sizeof(feat_list)/sizeof(feat_list[0])))
3340 ? &feat_list[index] : NULL);
3345 * feature_list_index -- return index of given feature id in
3346 * feature list
3349 feature_list_index(int id)
3351 FEATURE_S *feature;
3352 int i;
3354 for(i = 0; (feature = feature_list(i)); i++)
3355 if(id == feature->id)
3356 return(i);
3358 return(-1);
3363 * feature_list_name -- return the given feature id's corresponding name
3365 char *
3366 feature_list_name(int id)
3368 FEATURE_S *f;
3370 return((f = feature_list(feature_list_index(id))) ? f->name : "");
3375 feature_list_id(char *name)
3377 FEATURE_S *f;
3378 int i;
3380 for(i = 0; (f = feature_list(i)); i++)
3381 if(!strucmp(f->name, name))
3382 return(f->id);
3384 return(-1);
3389 * feature_list_help -- return the given feature id's corresponding help
3391 HelpType
3392 feature_list_help(int id)
3394 FEATURE_S *f;
3396 return((f = feature_list(feature_list_index(id))) ? f->help : NO_HELP);
3401 * All the arguments past "list" are the backwards compatibility hacks.
3403 void
3404 process_feature_list(struct pine *ps, char **list, int old_growth, int hir, int osr)
3406 register char *q;
3407 char **p,
3408 *lvalue[BM_SIZE * 8];
3409 int i,
3410 yorn;
3411 long l;
3412 FEATURE_S *feat;
3415 /* clear all previous settings and reset them to default */
3416 for(i = 0; (feat = feature_list(i)) != NULL; i++)
3417 F_SET(feat->id, ps, feat->defval);
3419 /* backwards compatibility */
3420 if(hir)
3421 F_TURN_ON(F_INCLUDE_HEADER, ps);
3423 /* ditto */
3424 if(osr)
3425 F_TURN_ON(F_SIG_AT_BOTTOM, ps);
3427 /* ditto */
3428 if(old_growth)
3429 set_old_growth_bits(ps, 0);
3431 /* now run through the list (global, user, and cmd_line lists are here) */
3432 if(list){
3433 for(p = list; (q = *p) != NULL; p++){
3434 if(struncmp(q, "no-", 3) == 0){
3435 yorn = 0;
3436 q += 3;
3437 }else{
3438 yorn = 1;
3441 for(i = 0; (feat = feature_list(i)) != NULL; i++){
3442 if(strucmp(q, feat->name) == 0){
3443 if(feat->id == F_OLD_GROWTH){
3444 set_old_growth_bits(ps, yorn);
3445 }else{
3446 F_SET(feat->id, ps, yorn);
3448 break;
3452 /* if it wasn't in that list */
3453 if(feat == NULL)
3454 dprint((1,"Unrecognized feature in feature-list (%s%s)\n",
3455 (yorn ? "" : "no-"), q ? q : "?"));
3460 * Turn on gratuitous '>From ' quoting, if requested...
3462 mail_parameters(NULL, SET_FROMWIDGET,
3463 F_ON(F_QUOTE_ALL_FROMS, ps) ? VOIDT : NIL);
3466 * Turn off .lock creation complaints...
3468 if(F_ON(F_QUELL_LOCK_FAILURE_MSGS, ps))
3469 mail_parameters(NULL, SET_LOCKEACCESERROR, (void *) 0);
3472 * Turn on quelling of pseudo message.
3474 if(F_ON(F_QUELL_INTERNAL_MSG,ps_global))
3475 mail_parameters(NULL, SET_USERHASNOLIFE, (void *) 1);
3477 l = F_ON(F_MULNEWSRC_HOSTNAMES_AS_TYPED,ps_global) ? 0L : 1L;
3478 mail_parameters(NULL, SET_NEWSRCCANONHOST, (void *) l);
3480 ps->pass_ctrl_chars = F_ON(F_PASS_CONTROL_CHARS,ps_global) ? 1 : 0;
3481 ps->pass_c1_ctrl_chars = F_ON(F_PASS_C1_CONTROL_CHARS,ps_global) ? 1 : 0;
3483 #ifndef _WINDOWS
3484 if(F_ON(F_QUELL_BEZERK_TIMEZONE,ps_global))
3485 mail_parameters(NULL, SET_NOTIMEZONES, (void *) 1);
3486 #endif
3488 if(F_ON(F_USE_FK, ps))
3489 ps->orig_use_fkeys = 1;
3491 /* Will we have to build a new list? */
3492 if(!(old_growth || hir || osr))
3493 return;
3496 * Build a new list for feature-list. The only reason we ever need to
3497 * do this is if one of the obsolete options is being converted
3498 * into a feature-list item, and it isn't already included in the user's
3499 * feature-list.
3501 i = 0;
3502 for(p = LVAL(&ps->vars[V_FEATURE_LIST], Main);
3503 p && (q = *p); p++){
3504 /* already have it or cancelled it, don't need to add later */
3505 if(hir && (strucmp(q, "include-header-in-reply") == 0 ||
3506 strucmp(q, "no-include-header-in-reply") == 0)){
3507 hir = 0;
3508 }else if(osr && (strucmp(q, "signature-at-bottom") == 0 ||
3509 strucmp(q, "no-signature-at-bottom") == 0)){
3510 osr = 0;
3511 }else if(old_growth && (strucmp(q, "old-growth") == 0 ||
3512 strucmp(q, "no-old-growth") == 0)){
3513 old_growth = 0;
3515 lvalue[i++] = cpystr(q);
3518 /* check to see if we still need to build a new list */
3519 if(!(old_growth || hir || osr))
3520 return;
3522 if(hir)
3523 lvalue[i++] = "include-header-in-reply";
3524 if(osr)
3525 lvalue[i++] = "signature-at-bottom";
3526 if(old_growth)
3527 lvalue[i++] = "old-growth";
3528 lvalue[i] = NULL;
3529 set_variable_list(V_FEATURE_LIST, lvalue, TRUE, Main);
3533 void
3534 set_current_pattern_vals(struct pine *ps)
3536 struct variable *vars = ps->vars;
3538 set_current_val(&vars[V_PATTERNS], TRUE, TRUE);
3539 set_current_val(&vars[V_PAT_ROLES], TRUE, TRUE);
3540 set_current_val(&vars[V_PAT_FILTS], TRUE, TRUE);
3541 set_current_val(&vars[V_PAT_FILTS_OLD], TRUE, TRUE);
3542 set_current_val(&vars[V_PAT_SCORES], TRUE, TRUE);
3543 set_current_val(&vars[V_PAT_SCORES_OLD], TRUE, TRUE);
3544 set_current_val(&vars[V_PAT_INCOLS], TRUE, TRUE);
3545 set_current_val(&vars[V_PAT_OTHER], TRUE, TRUE);
3546 set_current_val(&vars[V_PAT_SRCH], TRUE, TRUE);
3549 * If old pattern variable (V_PATTERNS) is set and the new ones aren't
3550 * in the config file, then convert the old data into the new variables.
3551 * It isn't quite that simple, though, because we don't store unset
3552 * variables in remote pinercs. Check for the variables but if we
3553 * don't find any of them, also check the version number. This change was
3554 * made in version 4.30. We could just check that except that we're
3555 * worried somebody will make an incompatible version number change in
3556 * their local version, and will break this. So we check both the
3557 * version # and the var_in_pinerc things to be safer.
3559 if(vars[V_PATTERNS].current_val.l
3560 && vars[V_PATTERNS].current_val.l[0]
3561 && !var_in_pinerc(vars[V_PAT_ROLES].name)
3562 && !var_in_pinerc(vars[V_PAT_FILTS].name)
3563 && !var_in_pinerc(vars[V_PAT_FILTS_OLD].name)
3564 && !var_in_pinerc(vars[V_PAT_SCORES].name)
3565 && !var_in_pinerc(vars[V_PAT_SCORES_OLD].name)
3566 && !var_in_pinerc(vars[V_PAT_INCOLS].name)
3567 && isdigit((unsigned char) ps->pine_pre_vers[0])
3568 && ps->pine_pre_vers[1] == '.'
3569 && isdigit((unsigned char) ps->pine_pre_vers[2])
3570 && isdigit((unsigned char) ps->pine_pre_vers[3])
3571 && strncmp(ps->pine_pre_vers, "4.30", 4) < 0){
3572 convert_pattern_data();
3576 * Otherwise, if FILTS_OLD is set and FILTS isn't in the config file,
3577 * convert FILTS_OLD to FILTS. Same for SCORES.
3578 * The reason FILTS was changed was so we could change the
3579 * semantics of how rules work when there are pieces in the rule that
3580 * we don't understand. At the same time as the FILTS change we added
3581 * a rule to detect 8bitSubjects. So a user might have a filter that
3582 * deletes messages with 8bitSubjects. The problem is that that same
3583 * filter in a FILTS_OLD pine would match because it would ignore the
3584 * 8bitSubject part of the pattern and match on the rest. So we changed
3585 * the semantics so that rules with unknown bits would be ignored
3586 * instead of used. We had to change variable names at the same time
3587 * because we were adding the 8bit thing and the old pines are still
3588 * out there. Filters and Scores can both be dangerous. Roles, Colors,
3589 * and Other seem less dangerous so not worth adding a new variable.
3590 * This was changed in 4.50.
3592 else{
3593 if(vars[V_PAT_FILTS_OLD].current_val.l
3594 && vars[V_PAT_FILTS_OLD].current_val.l[0]
3595 && !var_in_pinerc(vars[V_PAT_FILTS].name)
3596 && !var_in_pinerc(vars[V_PAT_SCORES].name)
3597 && isdigit((unsigned char) ps->pine_pre_vers[0])
3598 && ps->pine_pre_vers[1] == '.'
3599 && isdigit((unsigned char) ps->pine_pre_vers[2])
3600 && isdigit((unsigned char) ps->pine_pre_vers[3])
3601 && strncmp(ps->pine_pre_vers, "4.50", 4) < 0){
3602 convert_filts_pattern_data();
3605 if(vars[V_PAT_SCORES_OLD].current_val.l
3606 && vars[V_PAT_SCORES_OLD].current_val.l[0]
3607 && !var_in_pinerc(vars[V_PAT_FILTS].name)
3608 && !var_in_pinerc(vars[V_PAT_SCORES].name)
3609 && isdigit((unsigned char) ps->pine_pre_vers[0])
3610 && ps->pine_pre_vers[1] == '.'
3611 && isdigit((unsigned char) ps->pine_pre_vers[2])
3612 && isdigit((unsigned char) ps->pine_pre_vers[3])
3613 && strncmp(ps->pine_pre_vers, "4.50", 4) < 0){
3614 convert_scores_pattern_data();
3618 if(vars[V_PAT_ROLES].post_user_val.l)
3619 ps_global->ew_for_role_take = Post;
3620 else
3621 ps_global->ew_for_role_take = Main;
3623 if(vars[V_PAT_FILTS].post_user_val.l)
3624 ps_global->ew_for_filter_take = Post;
3625 else
3626 ps_global->ew_for_filter_take = Main;
3628 if(vars[V_PAT_SCORES].post_user_val.l)
3629 ps_global->ew_for_score_take = Post;
3630 else
3631 ps_global->ew_for_score_take = Main;
3633 if(vars[V_PAT_INCOLS].post_user_val.l)
3634 ps_global->ew_for_incol_take = Post;
3635 else
3636 ps_global->ew_for_incol_take = Main;
3638 if(vars[V_PAT_OTHER].post_user_val.l)
3639 ps_global->ew_for_other_take = Post;
3640 else
3641 ps_global->ew_for_other_take = Main;
3643 if(vars[V_PAT_SRCH].post_user_val.l)
3644 ps_global->ew_for_srch_take = Post;
3645 else
3646 ps_global->ew_for_srch_take = Main;
3651 * Foreach of the config files;
3652 * transfer the data to the new variables.
3654 void
3655 convert_pattern_data(void)
3657 convert_pinerc_patterns(PAT_USE_MAIN);
3658 convert_pinerc_patterns(PAT_USE_POST);
3662 void
3663 convert_filts_pattern_data(void)
3665 convert_pinerc_filts_patterns(PAT_USE_MAIN);
3666 convert_pinerc_filts_patterns(PAT_USE_POST);
3670 void
3671 convert_scores_pattern_data(void)
3673 convert_pinerc_scores_patterns(PAT_USE_MAIN);
3674 convert_pinerc_scores_patterns(PAT_USE_POST);
3679 * Foreach of the four variables, transfer the data for this config file
3680 * from the old patterns variable. We don't have to convert OTHER patterns
3681 * or SRCH patterns because they didn't exist in pines without patterns-other.
3683 * If the original variable had patlines with type File then we convert
3684 * all of the individual patterns to type Lit, because each pattern can
3685 * be of any category. Lit patterns are better tested, anyway.
3687 void
3688 convert_pinerc_patterns(long int use_flags)
3690 long old_rflags;
3691 long rflags;
3692 PAT_S *pat;
3693 PAT_STATE pstate;
3694 ACTION_S *act;
3696 old_rflags = (ROLE_OLD_PAT | use_flags);
3698 rflags = 0L;
3699 if(any_patterns(old_rflags, &pstate)){
3700 dprint((2, "converting old patterns to new (%s)\n", (use_flags == PAT_USE_MAIN) ? "Main" : "Post"));
3701 for(pat = first_pattern(&pstate);
3702 pat;
3703 pat = next_pattern(&pstate)){
3704 if((act = pat->action) != NULL){
3705 if(act->is_a_role &&
3706 add_to_pattern(pat, ROLE_DO_ROLES | use_flags))
3707 rflags |= ROLE_DO_ROLES;
3708 if(act->is_a_incol &&
3709 add_to_pattern(pat, ROLE_DO_INCOLS | use_flags))
3710 rflags |= ROLE_DO_INCOLS;
3711 if(act->is_a_score &&
3712 add_to_pattern(pat, ROLE_DO_SCORES | use_flags))
3713 rflags |= ROLE_DO_SCORES;
3714 if(act->is_a_filter &&
3715 add_to_pattern(pat, ROLE_DO_FILTER | use_flags))
3716 rflags |= ROLE_DO_FILTER;
3720 if(rflags)
3721 if(write_patterns(rflags | use_flags))
3722 dprint((1,
3723 "Trouble converting patterns to new variable\n"));
3729 * If the original variable had patlines with type File then we convert
3730 * all of the individual patterns to type Lit, because each pattern can
3731 * be of any category. Lit patterns are better tested, anyway.
3733 void
3734 convert_pinerc_filts_patterns(long int use_flags)
3736 long old_rflags;
3737 long rflags;
3738 PAT_S *pat;
3739 PAT_STATE pstate;
3740 ACTION_S *act;
3742 old_rflags = (ROLE_OLD_FILT | use_flags);
3744 rflags = 0L;
3745 if(any_patterns(old_rflags, &pstate)){
3746 dprint((2, "converting old filter patterns to new (%s)\n", (use_flags == PAT_USE_MAIN) ? "Main" : "Post"));
3747 for(pat = first_pattern(&pstate);
3748 pat;
3749 pat = next_pattern(&pstate)){
3750 if((act = pat->action) != NULL){
3751 if(act->is_a_filter &&
3752 add_to_pattern(pat, ROLE_DO_FILTER | use_flags))
3753 rflags |= ROLE_DO_FILTER;
3757 if(rflags)
3758 if(write_patterns(rflags | use_flags))
3759 dprint((1,
3760 "Trouble converting filter patterns to new variable\n"));
3766 * If the original variable had patlines with type File then we convert
3767 * all of the individual patterns to type Lit, because each pattern can
3768 * be of any category. Lit patterns are better tested, anyway.
3770 void
3771 convert_pinerc_scores_patterns(long int use_flags)
3773 long old_rflags;
3774 long rflags;
3775 PAT_S *pat;
3776 PAT_STATE pstate;
3777 ACTION_S *act;
3779 old_rflags = (ROLE_OLD_SCORE | use_flags);
3781 rflags = 0L;
3782 if(any_patterns(old_rflags, &pstate)){
3783 dprint((2, "converting old scores patterns to new (%s)\n", (use_flags == PAT_USE_MAIN) ? "Main" : "Post"));
3784 for(pat = first_pattern(&pstate);
3785 pat;
3786 pat = next_pattern(&pstate)){
3787 if((act = pat->action) != NULL){
3788 if(act->is_a_score &&
3789 add_to_pattern(pat, ROLE_DO_SCORES | use_flags))
3790 rflags |= ROLE_DO_SCORES;
3794 if(rflags)
3795 if(write_patterns(rflags | use_flags))
3796 dprint((1,
3797 "Trouble converting scores patterns to new variable\n"));
3803 * set_old_growth_bits - Command used to set or unset old growth set
3804 * of features
3806 void
3807 set_old_growth_bits(struct pine *ps, int val)
3809 int i;
3811 for(i = 1; i <= F_FEATURE_LIST_COUNT; i++)
3812 if(test_old_growth_bits(ps, i))
3813 F_SET(i, ps, val);
3819 * test_old_growth_bits - Test to see if all the old growth bits are on,
3820 * *or* if a particular feature index is in the old
3821 * growth set.
3823 * WEIRD ALERT: if index == F_OLD_GROWTH bit values are tested
3824 * otherwise a bits existence in the set is tested!!!
3826 * BUG: this will break if an old growth feature number is ever >= 32.
3829 test_old_growth_bits(struct pine *ps, int index)
3832 * this list defines F_OLD_GROWTH set
3834 static unsigned long old_growth_bits = ((1 << F_ENABLE_FULL_HDR) |
3835 (1 << F_ENABLE_PIPE) |
3836 (1 << F_ENABLE_TAB_COMPLETE) |
3837 (1 << F_QUIT_WO_CONFIRM) |
3838 (1 << F_ENABLE_JUMP) |
3839 (1 << F_ENABLE_ALT_ED) |
3840 (1 << F_ENABLE_BOUNCE) |
3841 (1 << F_ENABLE_AGG_OPS) |
3842 (1 << F_ENABLE_FLAG) |
3843 (1 << F_CAN_SUSPEND));
3844 if(index >= 32)
3845 return(0);
3847 if(index == F_OLD_GROWTH){
3848 for(index = 1; index <= F_FEATURE_LIST_COUNT; index++)
3849 if(((1 << index) & old_growth_bits) && F_OFF(index, ps))
3850 return(0);
3852 return(1);
3854 else
3855 return((1 << index) & old_growth_bits);
3860 * Side effect is that the appropriate global variable is set, and the
3861 * appropriate current_val is set.
3863 void
3864 cur_rule_value(struct variable *var, int expand, int cmdline)
3866 int i;
3867 NAMEVAL_S *v;
3869 set_current_val(var, expand, cmdline);
3871 if(var == &ps_global->vars[V_SAVED_MSG_NAME_RULE]){
3872 if(ps_global->VAR_SAVED_MSG_NAME_RULE)
3873 for(i = 0; (v = save_msg_rules(i)); i++)
3874 if(!strucmp(ps_global->VAR_SAVED_MSG_NAME_RULE, S_OR_L(v))){
3875 ps_global->save_msg_rule = v->value;
3876 break;
3879 #ifndef _WINDOWS
3880 else if(var == &ps_global->vars[V_COLOR_STYLE]){
3881 if(ps_global->VAR_COLOR_STYLE)
3882 for(i = 0; (v = col_style(i)); i++)
3883 if(!strucmp(ps_global->VAR_COLOR_STYLE, S_OR_L(v))){
3884 ps_global->color_style = v->value;
3885 break;
3888 #endif
3889 else if(var == &ps_global->vars[V_INDEX_COLOR_STYLE]){
3890 if(ps_global->VAR_INDEX_COLOR_STYLE)
3891 for(i = 0; (v = index_col_style(i)); i++)
3892 if(!strucmp(ps_global->VAR_INDEX_COLOR_STYLE, S_OR_L(v))){
3893 ps_global->index_color_style = v->value;
3894 break;
3897 else if(var == &ps_global->vars[V_TITLEBAR_COLOR_STYLE]){
3898 if(ps_global->VAR_TITLEBAR_COLOR_STYLE)
3899 for(i = 0; (v = titlebar_col_style(i)); i++)
3900 if(!strucmp(ps_global->VAR_TITLEBAR_COLOR_STYLE, S_OR_L(v))){
3901 ps_global->titlebar_color_style = v->value;
3902 break;
3905 else if(var == &ps_global->vars[V_FCC_RULE]){
3906 if(ps_global->VAR_FCC_RULE)
3907 for(i = 0; (v = fcc_rules(i)); i++)
3908 if(!strucmp(ps_global->VAR_FCC_RULE, S_OR_L(v))){
3909 ps_global->fcc_rule = v->value;
3910 break;
3913 else if(var == &ps_global->vars[V_GOTO_DEFAULT_RULE]){
3914 if(ps_global->VAR_GOTO_DEFAULT_RULE)
3915 for(i = 0; (v = goto_rules(i)); i++)
3916 if(!strucmp(ps_global->VAR_GOTO_DEFAULT_RULE, S_OR_L(v))){
3917 ps_global->goto_default_rule = v->value;
3918 break;
3921 else if(var == &ps_global->vars[V_INCOMING_STARTUP]){
3922 if(ps_global->VAR_INCOMING_STARTUP)
3923 for(i = 0; (v = incoming_startup_rules(i)); i++)
3924 if(!strucmp(ps_global->VAR_INCOMING_STARTUP, S_OR_L(v))){
3925 ps_global->inc_startup_rule = v->value;
3926 break;
3929 else if(var == &ps_global->vars[V_PRUNING_RULE]){
3930 if(ps_global->VAR_PRUNING_RULE)
3931 for(i = 0; (v = pruning_rules(i)); i++)
3932 if(!strucmp(ps_global->VAR_PRUNING_RULE, S_OR_L(v))){
3933 ps_global->pruning_rule = v->value;
3934 break;
3937 else if(var == &ps_global->vars[V_REOPEN_RULE]){
3938 if(ps_global->VAR_REOPEN_RULE)
3939 for(i = 0; (v = reopen_rules(i)); i++)
3940 if(!strucmp(ps_global->VAR_REOPEN_RULE, S_OR_L(v))){
3941 ps_global->reopen_rule = v->value;
3942 break;
3945 else if(var == &ps_global->vars[V_FLD_SORT_RULE]){
3946 if(ps_global->VAR_FLD_SORT_RULE)
3947 for(i = 0; (v = fld_sort_rules(i)); i++)
3948 if(!strucmp(ps_global->VAR_FLD_SORT_RULE, S_OR_L(v))){
3949 ps_global->fld_sort_rule = v->value;
3950 break;
3953 else if(var == &ps_global->vars[V_AB_SORT_RULE]){
3954 if(ps_global->VAR_AB_SORT_RULE)
3955 for(i = 0; (v = ab_sort_rules(i)); i++)
3956 if(!strucmp(ps_global->VAR_AB_SORT_RULE, S_OR_L(v))){
3957 ps_global->ab_sort_rule = v->value;
3958 break;
3961 else if(var == &ps_global->vars[V_THREAD_DISP_STYLE]){
3962 if(ps_global->VAR_THREAD_DISP_STYLE)
3963 for(i = 0; (v = thread_disp_styles(i)); i++)
3964 if(!strucmp(ps_global->VAR_THREAD_DISP_STYLE, S_OR_L(v))){
3965 ps_global->thread_disp_style = v->value;
3966 break;
3969 else if(var == &ps_global->vars[V_THREAD_INDEX_STYLE]){
3970 if(ps_global->VAR_THREAD_INDEX_STYLE)
3971 for(i = 0; (v = thread_index_styles(i)); i++)
3972 if(!strucmp(ps_global->VAR_THREAD_INDEX_STYLE, S_OR_L(v))){
3973 ps_global->thread_index_style = v->value;
3974 break;
3981 * Standard way to get at save message rules...
3983 NAMEVAL_S *
3984 save_msg_rules(int index)
3986 static NAMEVAL_S save_rules[] = {
3987 {"by-from", NULL, SAV_RULE_FROM},
3988 {"by-nick-of-from", NULL, SAV_RULE_NICK_FROM_DEF},
3989 {"by-nick-of-from-then-from", NULL, SAV_RULE_NICK_FROM},
3990 {"by-fcc-of-from", NULL, SAV_RULE_FCC_FROM_DEF},
3991 {"by-fcc-of-from-then-from", NULL, SAV_RULE_FCC_FROM},
3992 {"by-realname-of-from", NULL, SAV_RULE_RN_FROM_DEF},
3993 {"by-realname-of-from-then-from", NULL, SAV_RULE_RN_FROM},
3994 {"by-sender", NULL, SAV_RULE_SENDER},
3995 {"by-nick-of-sender", NULL, SAV_RULE_NICK_SENDER_DEF},
3996 {"by-nick-of-sender-then-sender", NULL, SAV_RULE_NICK_SENDER},
3997 {"by-fcc-of-sender", NULL, SAV_RULE_FCC_SENDER_DEF},
3998 {"by-fcc-of-sender-then-sender", NULL, SAV_RULE_FCC_SENDER},
3999 {"by-realname-of-sender", NULL, SAV_RULE_RN_SENDER_DEF},
4000 {"by-realname-of-sender-then-sender", NULL, SAV_RULE_RN_SENDER},
4001 {"by-recipient", NULL, SAV_RULE_RECIP},
4002 {"by-nick-of-recip", NULL, SAV_RULE_NICK_RECIP_DEF},
4003 {"by-nick-of-recip-then-recip", NULL, SAV_RULE_NICK_RECIP},
4004 {"by-fcc-of-recip", NULL, SAV_RULE_FCC_RECIP_DEF},
4005 {"by-fcc-of-recip-then-recip", NULL, SAV_RULE_FCC_RECIP},
4006 {"by-realname-of-recip", NULL, SAV_RULE_RN_RECIP_DEF},
4007 {"by-realname-of-recip-then-recip", NULL, SAV_RULE_RN_RECIP},
4008 {"by-replyto", NULL, SAV_RULE_REPLYTO},
4009 {"by-nick-of-replyto", NULL, SAV_RULE_NICK_REPLYTO_DEF},
4010 {"by-nick-of-replyto-then-replyto", NULL, SAV_RULE_NICK_REPLYTO},
4011 {"by-fcc-of-replyto", NULL, SAV_RULE_FCC_REPLYTO_DEF},
4012 {"by-fcc-of-replyto-then-replyto", NULL, SAV_RULE_FCC_REPLYTO},
4013 {"by-realname-of-replyto", NULL, SAV_RULE_RN_REPLYTO_DEF},
4014 {"by-realname-of-replyto-then-replyto", NULL, SAV_RULE_RN_REPLYTO},
4015 {"last-folder-used", NULL, SAV_RULE_LAST},
4016 {"default-folder", NULL, SAV_RULE_DEFLT}
4019 return((index >= 0 && index < (sizeof(save_rules)/sizeof(save_rules[0])))
4020 ? &save_rules[index] : NULL);
4025 * Standard way to get at fcc rules...
4027 NAMEVAL_S *
4028 fcc_rules(int index)
4030 static NAMEVAL_S f_rules[] = {
4031 {"default-fcc", NULL, FCC_RULE_DEFLT},
4032 {"last-fcc-used", NULL, FCC_RULE_LAST},
4033 {"by-recipient", NULL, FCC_RULE_RECIP},
4034 {"by-nickname", NULL, FCC_RULE_NICK},
4035 {"by-nick-then-recip", NULL, FCC_RULE_NICK_RECIP},
4036 {"current-folder", NULL, FCC_RULE_CURRENT}
4039 return((index >= 0 && index < (sizeof(f_rules)/sizeof(f_rules[0])))
4040 ? &f_rules[index] : NULL);
4045 * Standard way to get at addrbook sort rules...
4047 NAMEVAL_S *
4048 ab_sort_rules(int index)
4050 static NAMEVAL_S ab_rules[] = {
4051 {"fullname-with-lists-last", NULL, AB_SORT_RULE_FULL_LISTS},
4052 {"fullname", NULL, AB_SORT_RULE_FULL},
4053 {"nickname-with-lists-last", NULL, AB_SORT_RULE_NICK_LISTS},
4054 {"nickname", NULL, AB_SORT_RULE_NICK},
4055 {"dont-sort", NULL, AB_SORT_RULE_NONE}
4058 return((index >= 0 && index < (sizeof(ab_rules)/sizeof(ab_rules[0])))
4059 ? &ab_rules[index] : NULL);
4064 * Standard way to get at color styles.
4066 NAMEVAL_S *
4067 col_style(int index)
4069 static NAMEVAL_S col_styles[] = {
4070 {"no-color", NULL, COL_NONE},
4071 {"use-termdef", NULL, COL_TERMDEF},
4072 {"force-ansi-8color", NULL, COL_ANSI8},
4073 {"force-ansi-16color", NULL, COL_ANSI16},
4074 {"force-xterm-256color", NULL, COL_ANSI256}
4077 return((index >= 0 && index < (sizeof(col_styles)/sizeof(col_styles[0])))
4078 ? &col_styles[index] : NULL);
4083 * Standard way to get at index color styles.
4085 NAMEVAL_S *
4086 index_col_style(int index)
4088 static NAMEVAL_S ind_col_styles[] = {
4089 {"flip-colors", NULL, IND_COL_FLIP},
4090 {"reverse", NULL, IND_COL_REV},
4091 {"reverse-fg", NULL, IND_COL_FG},
4092 {"reverse-fg-no-ambiguity", NULL, IND_COL_FG_NOAMBIG},
4093 {"reverse-bg", NULL, IND_COL_BG},
4094 {"reverse-bg-no-ambiguity", NULL, IND_COL_BG_NOAMBIG}
4097 return((index >= 0 && index < (sizeof(ind_col_styles)/sizeof(ind_col_styles[0]))) ? &ind_col_styles[index] : NULL);
4102 * Standard way to get at titlebar color styles.
4104 NAMEVAL_S *
4105 titlebar_col_style(int index)
4107 static NAMEVAL_S tbar_col_styles[] = {
4108 {"default", NULL, TBAR_COLOR_DEFAULT},
4109 {"indexline", NULL, TBAR_COLOR_INDEXLINE},
4110 {"reverse-indexline", NULL, TBAR_COLOR_REV_INDEXLINE}
4113 return((index >= 0 && index < (sizeof(tbar_col_styles)/sizeof(tbar_col_styles[0]))) ? &tbar_col_styles[index] : NULL);
4118 * Standard way to get at folder sort rules...
4120 NAMEVAL_S *
4121 fld_sort_rules(int index)
4123 static NAMEVAL_S fdl_rules[] = {
4124 {"alphabetical", NULL, FLD_SORT_ALPHA},
4125 {"alpha-with-dirs-last", NULL, FLD_SORT_ALPHA_DIR_LAST},
4126 {"alpha-with-dirs-first", NULL, FLD_SORT_ALPHA_DIR_FIRST}
4129 return((index >= 0 && index < (sizeof(fdl_rules)/sizeof(fdl_rules[0])))
4130 ? &fdl_rules[index] : NULL);
4135 * Standard way to get at incoming startup rules...
4137 NAMEVAL_S *
4138 incoming_startup_rules(int index)
4140 static NAMEVAL_S is_rules[] = {
4141 {"first-unseen", NULL, IS_FIRST_UNSEEN},
4142 {"first-recent", NULL, IS_FIRST_RECENT},
4143 {"first-important", NULL, IS_FIRST_IMPORTANT},
4144 {"first-important-or-unseen", NULL, IS_FIRST_IMPORTANT_OR_UNSEEN},
4145 {"first-important-or-recent", NULL, IS_FIRST_IMPORTANT_OR_RECENT},
4146 {"first", NULL, IS_FIRST},
4147 {"last", NULL, IS_LAST}
4150 return((index >= 0 && index < (sizeof(is_rules)/sizeof(is_rules[0])))
4151 ? &is_rules[index] : NULL);
4155 NAMEVAL_S *
4156 startup_rules(int index)
4158 static NAMEVAL_S is2_rules[] = {
4159 {"first-unseen", NULL, IS_FIRST_UNSEEN},
4160 {"first-recent", NULL, IS_FIRST_RECENT},
4161 {"first-important", NULL, IS_FIRST_IMPORTANT},
4162 {"first-important-or-unseen", NULL, IS_FIRST_IMPORTANT_OR_UNSEEN},
4163 {"first-important-or-recent", NULL, IS_FIRST_IMPORTANT_OR_RECENT},
4164 {"first", NULL, IS_FIRST},
4165 {"last", NULL, IS_LAST},
4166 {"default", NULL, IS_NOTSET}
4169 return((index >= 0 && index < (sizeof(is2_rules)/sizeof(is2_rules[0])))
4170 ? &is2_rules[index] : NULL);
4175 * Standard way to get at pruning-rule values.
4177 NAMEVAL_S *
4178 pruning_rules(int index)
4180 static NAMEVAL_S pr_rules[] = {
4181 {"ask about rename, ask about deleting","ask-ask", PRUNE_ASK_AND_ASK},
4182 {"ask about rename, don't delete", "ask-no", PRUNE_ASK_AND_NO},
4183 {"always rename, ask about deleting", "yes-ask", PRUNE_YES_AND_ASK},
4184 {"always rename, don't delete", "yes-no", PRUNE_YES_AND_NO},
4185 {"don't rename, ask about deleting", "no-ask", PRUNE_NO_AND_ASK},
4186 {"don't rename, don't delete", "no-no", PRUNE_NO_AND_NO}
4189 return((index >= 0 && index < (sizeof(pr_rules)/sizeof(pr_rules[0])))
4190 ? &pr_rules[index] : NULL);
4195 * Standard way to get at reopen-rule values.
4197 NAMEVAL_S *
4198 reopen_rules(int index)
4200 static NAMEVAL_S ro_rules[] = {
4201 /* TRANSLATORS: short description of a feature option */
4202 {"Always reopen", "yes-yes",
4203 REOPEN_YES_YES},
4204 /* TRANSLATORS: short description of a feature option, default in brackets */
4205 {"Yes for POP/NNTP, Ask about other remote [Yes]", "yes-ask-y",
4206 REOPEN_YES_ASK_Y},
4207 /* TRANSLATORS: short description of a feature option, default in brackets */
4208 {"Yes for POP/NNTP, Ask about other remote [No]", "yes-ask-n",
4209 REOPEN_YES_ASK_N},
4210 /* TRANSLATORS: short description of a feature option */
4211 {"Yes for POP/NNTP, No for other remote", "yes-no",
4212 REOPEN_YES_NO},
4213 /* TRANSLATORS: short description of a feature option, default in brackets */
4214 {"Always ask [Yes]", "ask-ask-y",
4215 REOPEN_ASK_ASK_Y},
4216 /* TRANSLATORS: short description of a feature option, default in brackets */
4217 {"Always ask [No]", "ask-ask-n",
4218 REOPEN_ASK_ASK_N},
4219 /* TRANSLATORS: short description of a feature option, default in brackets */
4220 {"Ask about POP/NNTP [Yes], No for other remote", "ask-no-y",
4221 REOPEN_ASK_NO_Y},
4222 /* TRANSLATORS: short description of a feature option, default in brackets */
4223 {"Ask about POP/NNTP [No], No for other remote", "ask-no-n",
4224 REOPEN_ASK_NO_N},
4225 /* TRANSLATORS: short description of a feature option */
4226 {"Never reopen", "no-no",
4227 REOPEN_NO_NO},
4230 return((index >= 0 && index < (sizeof(ro_rules)/sizeof(ro_rules[0])))
4231 ? &ro_rules[index] : NULL);
4236 * Standard way to get at thread_disp_style values.
4238 NAMEVAL_S *
4239 thread_disp_styles(int index)
4241 static NAMEVAL_S td_styles[] = {
4242 {"none", "none", THREAD_NONE},
4243 {"show-thread-structure", "struct", THREAD_STRUCT},
4244 {"mutt-like", "mutt", THREAD_MUTTLIKE},
4245 {"indent-subject-1", "subj1", THREAD_INDENT_SUBJ1},
4246 {"indent-subject-2", "subj2", THREAD_INDENT_SUBJ2},
4247 {"indent-from-1", "from1", THREAD_INDENT_FROM1},
4248 {"indent-from-2", "from2", THREAD_INDENT_FROM2},
4249 {"show-structure-in-from", "struct-from", THREAD_STRUCT_FROM}
4252 return((index >= 0 && index < (sizeof(td_styles)/sizeof(td_styles[0])))
4253 ? &td_styles[index] : NULL);
4258 * Standard way to get at thread_index_style values.
4260 NAMEVAL_S *
4261 thread_index_styles(int index)
4263 static NAMEVAL_S ti_styles[] = {
4264 {"regular-index-with-expanded-threads", "exp", THRDINDX_EXP},
4265 {"regular-index-with-collapsed-threads","coll", THRDINDX_COLL},
4266 {"separate-index-screen-always", "sep", THRDINDX_SEP},
4267 {"separate-index-screen-except-for-single-messages","sep-auto",
4268 THRDINDX_SEP_AUTO}
4271 return((index >= 0 && index < (sizeof(ti_styles)/sizeof(ti_styles[0])))
4272 ? &ti_styles[index] : NULL);
4277 * Standard way to get at goto default rules...
4279 NAMEVAL_S *
4280 goto_rules(int index)
4282 static NAMEVAL_S g_rules[] = {
4283 {"folder-in-first-collection", NULL, GOTO_FIRST_CLCTN},
4284 {"inbox-or-folder-in-first-collection", NULL, GOTO_INBOX_FIRST_CLCTN},
4285 {"inbox-or-folder-in-recent-collection", NULL, GOTO_INBOX_RECENT_CLCTN},
4286 {"first-collection-with-inbox-default", NULL, GOTO_FIRST_CLCTN_DEF_INBOX},
4287 {"most-recent-folder", NULL, GOTO_LAST_FLDR}
4290 return((index >= 0 && index < (sizeof(g_rules)/sizeof(g_rules[0])))
4291 ? &g_rules[index] : NULL);
4295 NAMEVAL_S *
4296 pat_fldr_types(int index)
4298 static NAMEVAL_S pat_fldr_list[] = {
4299 {"Any", "ANY", FLDR_ANY},
4300 {"News", "NEWS", FLDR_NEWS},
4301 {"Email", "EMAIL", FLDR_EMAIL},
4302 {"Specific (Enter Incoming Nicknames or use ^T)", "SPEC", FLDR_SPECIFIC}
4305 return((index >= 0 &&
4306 index < (sizeof(pat_fldr_list)/sizeof(pat_fldr_list[0])))
4307 ? &pat_fldr_list[index] : NULL);
4311 NAMEVAL_S *
4312 inabook_fldr_types(int indexarg)
4314 static NAMEVAL_S inabook_fldr_list[] = {
4315 {"Don't care, always matches", "E", IAB_EITHER},
4316 {"Yes, in any address book", "YES", IAB_YES},
4317 {"No, not in any address book", "NO", IAB_NO},
4318 {"Yes, in specific address books", "SYES", IAB_SPEC_YES},
4319 {"No, not in any of specific address books", "SNO", IAB_SPEC_NO}
4322 int index = indexarg & IAB_TYPE_MASK;
4324 return((index >= 0 &&
4325 index < (sizeof(inabook_fldr_list)/sizeof(inabook_fldr_list[0])))
4326 ? &inabook_fldr_list[index] : NULL);
4330 NAMEVAL_S *
4331 filter_types(int index)
4333 static NAMEVAL_S filter_type_list[] = {
4334 {"Just Set Message Status", "NONE", FILTER_STATE},
4335 {"Delete", "DEL", FILTER_KILL},
4336 {"Move (Enter folder name(s) in primary collection, or use ^T)",
4337 "FLDR", FILTER_FOLDER}
4340 return((index >= 0 &&
4341 index < (sizeof(filter_type_list)/sizeof(filter_type_list[0])))
4342 ? &filter_type_list[index] : NULL);
4346 NAMEVAL_S *
4347 role_repl_types(int index)
4349 static NAMEVAL_S role_repl_list[] = {
4350 {"Never", "NO", ROLE_REPL_NO},
4351 {"With confirmation", "YES", ROLE_REPL_YES},
4352 {"Without confirmation", "NC", ROLE_REPL_NOCONF}
4355 return((index >= 0 &&
4356 index < (sizeof(role_repl_list)/sizeof(role_repl_list[0])))
4357 ? &role_repl_list[index] : NULL);
4361 NAMEVAL_S *
4362 role_forw_types(int index)
4364 static NAMEVAL_S role_forw_list[] = {
4365 {"Never", "NO", ROLE_FORW_NO},
4366 {"With confirmation", "YES", ROLE_FORW_YES},
4367 {"Without confirmation", "NC", ROLE_FORW_NOCONF}
4370 return((index >= 0 &&
4371 index < (sizeof(role_forw_list)/sizeof(role_forw_list[0])))
4372 ? &role_forw_list[index] : NULL);
4376 NAMEVAL_S *
4377 role_comp_types(int index)
4379 static NAMEVAL_S role_comp_list[] = {
4380 {"Never", "NO", ROLE_COMP_NO},
4381 {"With confirmation", "YES", ROLE_COMP_YES},
4382 {"Without confirmation", "NC", ROLE_COMP_NOCONF}
4385 return((index >= 0 &&
4386 index < (sizeof(role_comp_list)/sizeof(role_comp_list[0])))
4387 ? &role_comp_list[index] : NULL);
4391 NAMEVAL_S *
4392 role_status_types(int index)
4394 static NAMEVAL_S role_status_list[] = {
4395 {"Don't care, always matches", "E", PAT_STAT_EITHER},
4396 {"Yes", "YES", PAT_STAT_YES},
4397 {"No", "NO", PAT_STAT_NO}
4400 return((index >= 0 &&
4401 index < (sizeof(role_status_list)/sizeof(role_status_list[0])))
4402 ? &role_status_list[index] : NULL);
4406 NAMEVAL_S *
4407 msg_state_types(int index)
4409 static NAMEVAL_S msg_state_list[] = {
4410 {"Don't change it", "LV", ACT_STAT_LEAVE},
4411 {"Set this state", "SET", ACT_STAT_SET},
4412 {"Clear this state", "CLR", ACT_STAT_CLEAR}
4415 return((index >= 0 &&
4416 index < (sizeof(msg_state_list)/sizeof(msg_state_list[0])))
4417 ? &msg_state_list[index] : NULL);
4421 #ifdef ENABLE_LDAP
4422 NAMEVAL_S *
4423 ldap_search_rules(int index)
4425 static NAMEVAL_S ldap_search_list[] = {
4426 {"contains", NULL, LDAP_SRCH_CONTAINS},
4427 {"equals", NULL, LDAP_SRCH_EQUALS},
4428 {"begins-with", NULL, LDAP_SRCH_BEGINS},
4429 {"ends-with", NULL, LDAP_SRCH_ENDS}
4432 return((index >= 0 &&
4433 index < (sizeof(ldap_search_list)/sizeof(ldap_search_list[0])))
4434 ? &ldap_search_list[index] : NULL);
4438 NAMEVAL_S *
4439 ldap_search_types(int index)
4441 static NAMEVAL_S ldap_types_list[] = {
4442 {"name", NULL, LDAP_TYPE_CN},
4443 {"surname", NULL, LDAP_TYPE_SUR},
4444 {"givenname", NULL, LDAP_TYPE_GIVEN},
4445 {"email", NULL, LDAP_TYPE_EMAIL},
4446 {"name-or-email", NULL, LDAP_TYPE_CN_EMAIL},
4447 {"surname-or-givenname", NULL, LDAP_TYPE_SUR_GIVEN},
4448 {"sur-or-given-or-name-or-email", NULL, LDAP_TYPE_SEVERAL}
4451 return((index >= 0 &&
4452 index < (sizeof(ldap_types_list)/sizeof(ldap_types_list[0])))
4453 ? &ldap_types_list[index] : NULL);
4457 NAMEVAL_S *
4458 ldap_search_scope(int index)
4460 static NAMEVAL_S ldap_scope_list[] = {
4461 {"base", NULL, LDAP_SCOPE_BASE},
4462 {"onelevel", NULL, LDAP_SCOPE_ONELEVEL},
4463 {"subtree", NULL, LDAP_SCOPE_SUBTREE}
4466 return((index >= 0 &&
4467 index < (sizeof(ldap_scope_list)/sizeof(ldap_scope_list[0])))
4468 ? &ldap_scope_list[index] : NULL);
4470 #endif
4474 * Choose from the global default, command line args, pinerc values to set
4475 * the actual value of the variable that we will use. Start at the top
4476 * and work down from higher to lower precedence.
4477 * For lists, we may inherit values from lower precedence
4478 * versions if that's the way the user specifies it.
4479 * The user can put INHERIT_DEFAULT as the first entry in a list and that
4480 * means it will inherit the current values, for example the values
4481 * from the global_val, or the value from the main_user_val could be
4482 * inherited in the post_user_val.
4484 void
4485 set_current_val(struct variable *var, int expand, int cmdline)
4487 int is_set[5], is_inherit[5];
4488 int i, j, k, cnt, start;
4489 char **tmp, **t, **list[5];
4490 char *p;
4492 dprint((9,
4493 "set_current_val(var=%s%s, expand=%d, cmdline=%d)\n",
4494 (var && var->name) ? var->name : "?",
4495 (var && var->is_list) ? " (list)" : "",
4496 expand, cmdline));
4498 if(!var)
4499 return;
4501 if(var->is_list){ /* variable is a list */
4503 for(j = 0; j < 5; j++){
4504 t = j==0 ? var->global_val.l :
4505 j==1 ? var->main_user_val.l :
4506 j==2 ? var->post_user_val.l :
4507 j==3 ? ((cmdline) ? var->cmdline_val.l : NULL) :
4508 var->fixed_val.l;
4510 is_set[j] = is_inherit[j] = 0;
4511 list[j] = NULL;
4513 if(t){
4514 if(!expand){
4515 is_set[j]++;
4516 list[j] = t;
4518 else{
4519 for(i = 0; t[i]; i++){
4520 if(expand_variables(tmp_20k_buf, SIZEOF_20KBUF, t[i],
4521 0)){
4522 /* successful expand */
4523 is_set[j]++;
4524 list[j] = t;
4525 break;
4530 if(list[j] && list[j][0] && !strcmp(list[j][0],INHERIT))
4531 is_inherit[j]++;
4535 cnt = 0;
4536 start = 0;
4537 /* count how many items in current_val list */
4538 /* Admin wants default, which is global_val. */
4539 if(var->is_fixed && var->fixed_val.l == NULL){
4540 cnt = 0;
4541 if(is_set[0]){
4542 for(; list[0][cnt]; cnt++)
4546 else{
4547 for(j = 0; j < 5; j++){
4548 if(is_set[j]){
4549 if(!is_inherit[j]){
4550 cnt = 0; /* reset */
4551 start = j;
4554 for(i = is_inherit[j] ? 1 : 0; list[j][i]; i++)
4555 cnt++;
4560 free_list_array(&var->current_val.l); /* clean up any old values */
4562 /* check to see if anything is set */
4563 if(is_set[0] + is_set[1] + is_set[2] + is_set[3] + is_set[4] > 0){
4564 var->current_val.l = (char **)fs_get((cnt+1)*sizeof(char *));
4565 tmp = var->current_val.l;
4566 if(var->is_fixed && var->fixed_val.l == NULL){
4567 if(is_set[0]){
4568 for(i = 0; list[0][i]; i++){
4569 if(!expand)
4570 *tmp++ = cpystr(list[0][i]);
4571 else if(expand_variables(tmp_20k_buf, SIZEOF_20KBUF,
4572 list[0][i], 0))
4573 *tmp++ = cpystr(tmp_20k_buf);
4577 else{
4578 for(j = start; j < 5; j++){
4579 if(is_set[j]){
4580 for(i = is_inherit[j] ? 1 : 0; list[j][i]; i++){
4581 if(!expand)
4582 *tmp++ = cpystr(list[j][i]);
4583 else if(expand_variables(tmp_20k_buf,SIZEOF_20KBUF,
4584 list[j][i], 0))
4585 *tmp++ = cpystr(tmp_20k_buf);
4591 *tmp = NULL;
4593 else
4594 var->current_val.l = NULL;
4596 else{ /* variable is not a list */
4597 char *strvar = NULL;
4599 for(j = 0; j < 5; j++){
4601 p = j==0 ? var->fixed_val.p :
4602 j==1 ? ((cmdline) ? var->cmdline_val.p : NULL) :
4603 j==2 ? var->post_user_val.p :
4604 j==3 ? var->main_user_val.p :
4605 var->global_val.p;
4607 is_set[j] = 0;
4609 if(p){
4610 if(!expand){
4611 is_set[j]++;
4612 if(!strvar)
4613 strvar = p;
4615 else if(expand_variables(tmp_20k_buf, SIZEOF_20KBUF, p,
4616 (var == &ps_global->vars[V_MAILCAP_PATH] ||
4617 var == &ps_global->vars[V_MIMETYPE_PATH]))){
4618 is_set[j]++;
4619 if(!strvar)
4620 strvar = p;
4625 /* Admin wants default, which is global_val. */
4626 if(var->is_fixed && var->fixed_val.p == NULL)
4627 strvar = var->global_val.p;
4629 if(var->current_val.p) /* free previous value */
4630 fs_give((void **)&var->current_val.p);
4632 if(strvar){
4633 if(!expand)
4634 var->current_val.p = cpystr(strvar);
4635 else{
4636 expand_variables(tmp_20k_buf, SIZEOF_20KBUF, strvar,
4637 (var == &ps_global->vars[V_MAILCAP_PATH] ||
4638 var == &ps_global->vars[V_MIMETYPE_PATH]));
4639 var->current_val.p = cpystr(tmp_20k_buf);
4642 else
4643 var->current_val.p = NULL;
4646 if(var->is_fixed && !is_inherit[4]){
4647 char **flist;
4648 int fixed_len, user_len;
4651 * sys mgr fixed this variable and user is trying to change it
4653 for(k = 1; !(ps_global->give_fixed_warning &&
4654 ps_global->fix_fixed_warning) && k <= 3; k++){
4655 if(is_set[k]){
4656 if(var->is_list){
4657 t = k==1 ? ((cmdline) ? var->cmdline_val.l : NULL) :
4658 k==2 ? var->post_user_val.l :
4659 var->main_user_val.l;
4661 /* If same length and same contents, don't warn. */
4662 for(flist=var->fixed_val.l; flist && *flist; flist++)
4663 ;/* just counting */
4665 fixed_len = var->fixed_val.l ? (flist - var->fixed_val.l)
4666 : 0;
4667 for(flist=t; flist && *flist; flist++)
4668 ;/* just counting */
4670 user_len = t ? (flist - t) : 0;
4671 if(user_len == fixed_len){
4672 for(i=0; i < user_len; i++){
4673 for(j=0; j < user_len; j++)
4674 if(!strucmp(t[i], var->fixed_val.l[j]))
4675 break;
4677 if(j == user_len){
4678 ps_global->give_fixed_warning = 1;
4679 if(k != 1)
4680 ps_global->fix_fixed_warning = 1;
4682 break;
4686 else{
4687 ps_global->give_fixed_warning = 1;
4688 if(k != 1)
4689 ps_global->fix_fixed_warning = 1;
4692 else{
4693 p = k==1 ? ((cmdline) ? var->cmdline_val.p : NULL) :
4694 k==2 ? var->post_user_val.p :
4695 var->main_user_val.p;
4697 if((var->fixed_val.p && !p) ||
4698 (!var->fixed_val.p && p) ||
4699 (var->fixed_val.p && p && strucmp(var->fixed_val.p, p))){
4700 ps_global->give_fixed_warning = 1;
4701 if(k != 1)
4702 ps_global->fix_fixed_warning = 1;
4711 void
4712 set_news_spec_current_val(int expand, int cmdline)
4714 struct variable *newsvar = &ps_global->vars[V_NEWS_SPEC];
4715 struct variable *fvar = &ps_global->vars[V_FOLDER_SPEC];
4717 /* check to see if it has a value */
4718 set_current_val(newsvar, expand, cmdline);
4721 * If no value, we might want to fake a value. We'll do that if
4722 * there is no news collection already defined in FOLDER_SPEC and if
4723 * there is also an NNTP_SERVER defined.
4725 if(!newsvar->current_val.l && ps_global->VAR_NNTP_SERVER &&
4726 ps_global->VAR_NNTP_SERVER[0] && ps_global->VAR_NNTP_SERVER[0][0] &&
4727 !news_in_folders(fvar)){
4728 char buf[MAXPATH];
4730 newsvar->global_val.l = (char **)fs_get(2 * sizeof(char *));
4731 snprintf(buf, sizeof(buf), "{%.*s/nntp}#news.[]", MAXPATH-20,
4732 ps_global->VAR_NNTP_SERVER[0]); /* MAXPATH = sizeof(buf) */
4733 newsvar->global_val.l[0] = cpystr(buf);
4734 newsvar->global_val.l[1] = NULL;
4735 set_current_val(newsvar, expand, cmdline);
4737 * But we're going to get rid of the fake global_val in case
4738 * things change.
4740 free_list_array(&newsvar->global_val.l);
4746 * Feature-list has to be handled separately from the other variables
4747 * because it is additive. The other variables choose one of command line,
4748 * or pine.conf, or pinerc. Feature list adds them. This could easily be
4749 * converted to a general purpose routine if we add more additive variables.
4751 * This works by replacing earlier values with later ones. That is, command
4752 * line settings have higher precedence than global settings and that is
4753 * accomplished by putting the command line features after the global
4754 * features in the list. When they are processed, the last one wins.
4756 * Feature-list also has a backwards compatibility hack.
4758 void
4759 set_feature_list_current_val(struct variable *var)
4761 char **list;
4762 char **list_fixed;
4763 char no_allow[50];
4764 int i, j, k, m,
4765 elems = 0;
4767 /* count the lists so we can allocate */
4768 for(m = 0; m < 6; m++){
4769 list = m==0 ? var->global_val.l :
4770 m==1 ? var->main_user_val.l :
4771 m==2 ? var->post_user_val.l :
4772 m==3 ? ps_global->feat_list_back_compat :
4773 m==4 ? var->cmdline_val.l :
4774 var->fixed_val.l;
4775 if(list)
4776 for(i = 0; list[i]; i++)
4777 elems++;
4780 list_fixed = var->fixed_val.l;
4782 if(var->current_val.l)
4783 free_list_array(&var->current_val.l);
4785 var->current_val.l = (char **)fs_get((elems+1) * sizeof(char *));
4788 * We need to warn the user if the sys mgr has restricted him or her
4789 * from changing a feature that he or she is trying to change.
4791 * We're not catching the old-growth macro since we're just comparing
4792 * strings. That is, it works correctly, but the user won't be warned
4793 * if the user old-growth and the mgr says no-quit-without-confirm.
4796 j = 0;
4797 strncpy(no_allow, "no-", 3);
4798 strncpy(no_allow+3, feature_list_name(F_ALLOW_CHANGING_FROM), sizeof(no_allow)-3-1);
4799 no_allow[sizeof(no_allow)-1] = '\0';
4801 for(m = 0; m < 6; m++){
4802 list = m==0 ? var->global_val.l :
4803 m==1 ? var->main_user_val.l :
4804 m==2 ? var->post_user_val.l :
4805 m==3 ? ps_global->feat_list_back_compat :
4806 m==4 ? var->cmdline_val.l :
4807 var->fixed_val.l;
4808 if(list)
4809 for(i = 0; list[i]; i++){
4810 var->current_val.l[j++] = cpystr(list[i]);
4812 /* this is the warning section */
4813 if(m >= 1 && m <= 4){
4814 for(k = 0; list_fixed && list_fixed[k]; k++){
4815 char *p, *q;
4816 p = list[i];
4817 q = list_fixed[k];
4818 if(!struncmp(p, "no-", 3))
4819 p += 3;
4820 if(!struncmp(q, "no-", 3))
4821 q += 3;
4822 if(!strucmp(q, p) && strucmp(list[i], list_fixed[k])){
4823 ps_global->give_fixed_warning = 1;
4824 if(m <= 2)
4825 ps_global->fix_fixed_warning = 1;
4829 else if(m == 5 && !strucmp(list[i], no_allow))
4830 ps_global->never_allow_changing_from = 1;
4834 #ifdef NEVER_ALLOW_CHANGING_FROM
4835 ps_global->never_allow_changing_from = 1;
4836 #endif
4838 var->current_val.l[j] = NULL;
4843 /*----------------------------------------------------------------------
4845 Expand Metacharacters/variables in file-names
4847 Read input line and expand shell-variables/meta-characters
4849 <input> <replaced by>
4850 $variable getenv("variable")
4851 ${variable} getenv("variable")
4852 ${variable:-defvalue} is getenv("variable") if variable is defined and
4853 is defvalue otherwise
4854 ~ getenv("HOME")
4855 \c c
4856 <others> <just copied>
4858 NOTE handling of braces in ${name} doesn't check much or do error recovery
4860 If colon_path is set, then we expand ~ not only at the start of linein,
4861 but also after each : in the path.
4863 ----*/
4864 #define is_allowed_envchar(C, S) ((S) == 0 ? !isspace((C)) && (C) != '/'\
4865 : (((C) >= 'a' && (C) <= 'z') \
4866 || ((C) >= 'A' && (C) <= 'Z') \
4867 || ((C) >= '0' && (C) <= '9')))
4869 char *
4870 expand_variables(char *lineout, size_t lineoutlen, char *linein, int colon_path)
4872 char *src = linein, *dest = lineout, *p;
4873 char *limit = lineout + lineoutlen;
4874 int envexpand = 0, sp;
4876 if(!linein)
4877 return(NULL);
4879 sp = strncmp(src,"LIT:pattern=\"/NICK=", strlen("LIT:pattern=\"/NICK=")) == 0;
4880 while(*src ){ /* something in input string */
4881 if(*src == '$' && *(src+1) == '$'){
4883 * $$ to escape chars we're interested in, else
4884 * it's up to the user of the variable to handle the
4885 * backslash...
4887 if(dest < limit)
4888 *dest++ = *++src; /* copy next as is */
4889 }else
4890 #if !(defined(DOS) || defined(OS2))
4891 if(*src == '\\' && *(src+1) == '$'){
4893 * backslash to escape chars we're interested in, else
4894 * it's up to the user of the variable to handle the
4895 * backslash...
4897 if(dest < limit)
4898 *dest++ = *++src; /* copy next as is */
4899 }else if(*src == '~' &&
4900 (src == linein || (colon_path && *(src-1) == ':'))){
4901 char buf[MAXPATH];
4902 int i;
4904 for(i = 0; i < sizeof(buf)-1 && src[i] && src[i] != '/'; i++)
4905 buf[i] = src[i];
4907 src += i; /* advance src pointer */
4908 buf[i] = '\0'; /* tie off buf string */
4909 fnexpand(buf, sizeof(buf)); /* expand the path */
4911 for(p = buf; dest < limit && (*dest = *p); p++, dest++)
4914 continue;
4915 }else
4916 #endif
4917 if(*src == '$'){ /* shell variable */
4918 char word[128+1], *colon = NULL, *rbrace = NULL;
4920 envexpand++; /* signal that we've expanded a var */
4921 src++; /* skip dollar */
4922 if(*src == '{'){ /* starts with brace? */
4923 src++;
4924 rbrace = strindex(src, '}');
4925 if(rbrace){
4926 /* look for default value */
4927 colon = strstr(src, ":-");
4928 if(colon && (rbrace < colon))
4929 colon = NULL;
4933 p = word;
4935 /* put the env variable to be looked up in word */
4936 if(rbrace){
4937 while(*src
4938 && (p-word < sizeof(word)-1)
4939 && ((colon && src < colon) || (!colon && src < rbrace))){
4940 if(isspace((unsigned char) *src)){
4942 * Illegal input. This should be an error of some
4943 * sort but instead of that we'll just backup to the
4944 * $ and treat it like it wasn't there.
4946 while(*src != '$')
4947 src--;
4949 envexpand--;
4950 goto just_copy;
4952 else
4953 *p++ = *src++;
4956 /* adjust src for next char */
4957 src = rbrace + 1;
4959 else{
4960 while(*src && is_allowed_envchar((unsigned char) *src, sp)
4961 && (p-word < sizeof(word)-1))
4962 *p++ = *src++;
4965 *p = '\0';
4967 if((p = getenv(word)) != NULL){ /* check for word in environment */
4968 while(*p && dest < limit)
4969 *dest++ = *p++;
4971 else if(colon){ /* else possible default value */
4972 p = colon + 2;
4973 while(*p && p < rbrace && dest < limit)
4974 *dest++ = *p++;
4977 continue;
4978 }else{ /* other cases: just copy */
4979 just_copy:
4980 if(dest < limit)
4981 *dest++ = *src;
4984 if(*src) /* next character (if any) */
4985 src++;
4988 if(dest < limit)
4989 *dest = '\0';
4990 else
4991 lineout[lineoutlen-1] = '\0';
4993 return((envexpand && lineout[0] == '\0') ? NULL : lineout);
4997 /*----------------------------------------------------------------------
4998 Sets login, full_username and home_dir
5000 Args: ps -- The Pine structure to put the user name, etc in
5002 Result: sets the fullname, login and home_dir field of the pine structure
5003 returns 0 on success, -1 if not.
5004 ----*/
5005 #define MAX_INIT_ERRS 10
5006 void
5007 init_error(struct pine *ps, int flags, int min_time, int max_time, char *message)
5009 int i;
5011 if(!ps->init_errs){
5012 ps->init_errs = (INIT_ERR_S *)fs_get((MAX_INIT_ERRS + 1) *
5013 sizeof(*ps->init_errs));
5014 memset(ps->init_errs, 0, (MAX_INIT_ERRS + 1) * sizeof(*ps->init_errs));
5017 for(i = 0; i < MAX_INIT_ERRS; i++)
5018 if(!(ps->init_errs)[i].message){
5019 (ps->init_errs)[i].message = cpystr(message);
5020 (ps->init_errs)[i].min_time = min_time;
5021 (ps->init_errs)[i].max_time = max_time;
5022 (ps->init_errs)[i].flags = flags;
5023 dprint((2, "%s\n", message ? message : "?"));
5024 break;
5029 /*----------------------------------------------------------------------
5030 Read and parse a pinerc file
5032 Args: Filename -- name of the .pinerc file to open and read
5033 vars -- The vars structure to store values in
5034 which_vars -- Whether the local or global values are being read
5036 Result:
5038 This may be the local file or the global file. The values found are
5039 merged with the values currently in vars. All values are strings and
5040 are malloced; and existing values will be freed before the assignment.
5041 Those that are <unset> will be left unset; their values will be NULL.
5042 ----*/
5043 void
5044 read_pinerc(PINERC_S *prc, struct variable *vars, ParsePinerc which_vars)
5046 char *filename, *file, *value, **lvalue, *line, *error;
5047 char *p, *p1, *free_file = NULL;
5048 struct variable *v;
5049 PINERC_LINE *pline = NULL;
5050 int line_count, was_quoted;
5051 int i;
5053 if(!prc)
5054 return;
5056 dprint((2, "reading_pinerc \"%s\"\n",
5057 prc->name ? prc->name : "?"));
5059 if(prc->type == Loc){
5060 filename = prc->name ? prc->name : "";
5061 file = free_file = read_file(filename, 0);
5064 * This is questionable. In case the user edits the pinerc
5065 * in Windows and adds a UTF-8 BOM, we skip it here. If the
5066 * user adds a Unicode BOM we're in trouble. We could write it
5067 * with the BOM ourselves but so far we leave it BOMless in
5068 * order that it's the same on Unix and Windows.
5070 if(BOM_UTF8(file))
5071 file += 3;
5073 else{
5074 if((file = read_remote_pinerc(prc, which_vars)) != NULL)
5075 ps_global->c_client_error[0] = '\0';
5077 free_file = file;
5080 if(file == NULL || *file == '\0'){
5081 #ifdef DEBUG
5082 if(file == NULL){
5083 dprint((2, "Open failed: %s\n", error_description(errno)));
5085 else{
5086 if(prc->type == Loc){
5087 dprint((1, "Read_pinerc: empty pinerc (new?)\n"));
5089 else{
5090 dprint((1, "Read_pinerc: new remote pinerc\n"));
5093 #endif /* DEBUG */
5095 if(which_vars == ParsePers){
5096 /* problems getting remote config */
5097 if(file == NULL && prc->type == RemImap){
5098 if(!pith_opt_remote_pinerc_failure
5099 || !(*pith_opt_remote_pinerc_failure)())
5100 exceptional_exit(_("Unable to read or write remote configuration"), -1);
5103 ps_global->first_time_user = 1;
5104 prc->outstanding_pinerc_changes = 1;
5107 return;
5109 else{
5110 if(prc->type == Loc &&
5111 (which_vars == ParseFixed || which_vars == ParseGlobal ||
5112 (can_access(filename, ACCESS_EXISTS) == 0 &&
5113 can_access(filename, EDIT_ACCESS) != 0))){
5114 prc->readonly = 1;
5115 if(prc == ps_global->prc)
5116 ps_global->readonly_pinerc = 1;
5120 * accept CRLF or LF newlines
5122 for(p = file; *p && *p != '\012'; p++)
5125 if(p > file && *p && *(p-1) == '\015') /* cvt crlf to lf */
5126 for(p1 = p - 1; (*p1 = *p) != '\0'; p++)
5127 if(!(*p == '\015' && *(p+1) == '\012'))
5128 p1++;
5131 dprint((2, "Read %d characters:\n", strlen(file)));
5133 if(which_vars == ParsePers || which_vars == ParsePersPost){
5134 /*--- Count up lines and allocate structures */
5135 for(line_count = 0, p = file; *p != '\0'; p++)
5136 if(*p == '\n')
5137 line_count++;
5139 prc->pinerc_lines = (PINERC_LINE *)
5140 fs_get((3 + line_count) * sizeof(PINERC_LINE));
5141 memset((void *)prc->pinerc_lines, 0,
5142 (3 + line_count) * sizeof(PINERC_LINE));
5143 pline = prc->pinerc_lines;
5146 for(p = file, line = file; *p != '\0';){
5147 /*----- Grab the line ----*/
5148 line = p;
5149 while(*p && *p != '\n')
5150 p++;
5151 if(*p == '\n'){
5152 *p++ = '\0';
5155 /*----- Comment Line -----*/
5156 if(*line == '#'){
5157 /* no comments in remote pinercs */
5158 if(pline && prc->type == Loc){
5159 pline->is_var = 0;
5160 pline->line = cpystr(line);
5161 pline++;
5163 continue;
5166 if(*line == '\0' || *line == '\t' || *line == ' '){
5167 p1 = line;
5168 while(*p1 == '\t' || *p1 == ' ')
5169 p1++;
5170 if(pline){
5172 * This could be a continuation line from some future
5173 * version of pine, or it could be a continuation line
5174 * from a PC-Pine variable we don't know about in unix.
5176 if(*p1 != '\0')
5177 pline->line = cpystr(line);
5178 else
5179 pline->line = cpystr("");
5180 pline->is_var = 0;
5181 pline++;
5183 continue;
5186 /*----- look up matching 'v' and leave "value" after '=' ----*/
5187 for(v = vars; *line && v->name; v++)
5188 if((i = strlen(v->name)) < strlen(line) && !struncmp(v->name,line,i)){
5189 int j;
5191 for(j = i; line[j] == ' ' || line[j] == '\t'; j++)
5194 if(line[j] == '='){ /* bingo! */
5195 for(value = &line[j+1];
5196 *value == ' ' || *value == '\t';
5197 value++)
5200 break;
5202 /* else either unrecognized var or bogus line */
5205 /*----- Didn't match any variable or bogus format -----*/
5207 * This could be a variable from some future
5208 * version of pine, or it could be a PC-Pine variable
5209 * we don't know about in unix. Either way, we want to preserve
5210 * it in the file.
5212 if(!v->name){
5213 if(pline){
5214 pline->is_var = 0;
5215 pline->line = cpystr(line);
5216 pline++;
5218 continue;
5222 * Previous versions have caused duplicate pinerc data to be
5223 * written to pinerc files. This clause erases the duplicate
5224 * information when we read it, and it will be removed from the file
5225 * if we call write_pinerc. We test to see if the same variable
5226 * appears later in the file, if so, we skip over it here.
5227 * We don't care about duplicates if this isn't a pinerc we might
5228 * write out, so include pline in the conditional.
5229 * Note that we will leave all of the duplicate comments and blank
5230 * lines in the file unless it is a remote pinerc. Luckily, the
5231 * bug that caused the duplicates only applied to remote pinercs,
5232 * so we should have that case covered.
5234 * If we find a duplicate, we point p to the start
5235 * of the next line that should be considered, and then skip back
5236 * to the top of the loop.
5238 if(pline && var_is_in_rest_of_file(v->name, p)){
5239 if(v->is_list)
5240 p = skip_over_this_var(line, p);
5242 continue;
5246 /*----- Obsolete variable, read it anyway below, might use it -----*/
5247 if(v->is_obsolete){
5248 if(pline){
5249 pline->obsolete_var = 1;
5250 pline->line = cpystr(line);
5251 pline->var = v;
5255 /*----- Variable is in the list but unused for some reason -----*/
5256 if(!v->is_used){
5257 if(pline){
5258 pline->is_var = 0;
5259 pline->line = cpystr(line);
5260 pline++;
5262 continue;
5265 /*--- Var is not user controlled, leave it alone for back compat ---*/
5266 if(!v->is_user && pline){
5267 pline->is_var = 0;
5268 pline->line = cpystr(line);
5269 pline++;
5270 continue;
5273 if(which_vars == ParseFixed)
5274 v->is_fixed = 1;
5276 /*---- variable is unset, or it's global but expands to nothing ----*/
5277 if(!*value
5278 || (which_vars == ParseGlobal
5279 && !expand_variables(tmp_20k_buf, SIZEOF_20KBUF, value,
5280 (v == &ps_global->vars[V_MAILCAP_PATH] ||
5281 v == &ps_global->vars[V_MIMETYPE_PATH])))){
5282 if(v->is_user && pline){
5283 pline->is_var = 1;
5284 pline->var = v;
5285 pline++;
5287 continue;
5290 /*--value is non-empty, store it handling quotes and trailing space--*/
5291 if(*value == '"' && !v->is_list && v->del_quotes){
5292 was_quoted = 1;
5293 value++;
5294 for(p1 = value; *p1 && *p1 != '"'; p1++);
5295 if(*p1 == '"')
5296 *p1 = '\0';
5297 else
5298 removing_trailing_white_space(value);
5299 }else
5300 was_quoted = 0;
5303 * List Entry Parsing
5305 * The idea is to parse a comma separated list of
5306 * elements, preserving quotes, and understanding
5307 * continuation lines (that is ',' == "\n ").
5308 * Quotes must be balanced within elements. Space
5309 * within elements is preserved, but leading and trailing
5310 * space is trimmed. This is a generic function, and it's
5311 * left to the the functions that use the lists to make sure
5312 * they contain valid data...
5314 if(v->is_list){
5316 was_quoted = 0;
5317 line_count = 0;
5318 p1 = value;
5319 while(1){ /* generous count of list elements */
5320 if(*p1 == '"') /* ignore ',' if quoted */
5321 was_quoted = (was_quoted) ? 0 : 1 ;
5323 if((*p1 == ',' && !was_quoted) || *p1 == '\n' || *p1 == '\0')
5324 line_count++; /* count this element */
5326 if(*p1 == '\0' || *p1 == '\n'){ /* deal with EOL */
5327 if(p1 < p || *p1 == '\n'){
5328 *p1++ = ','; /* fix null or newline */
5330 if(*p1 != '\t' && *p1 != ' '){
5331 *(p1-1) = '\0'; /* tie off list */
5332 p = p1; /* reset p */
5333 break;
5335 }else{
5336 p = p1; /* end of pinerc */
5337 break;
5339 }else
5340 p1++;
5343 error = NULL;
5344 lvalue = parse_list(value, line_count,
5345 v->del_quotes ? PL_REMSURRQUOT : PL_NONE,
5346 &error);
5347 if(error){
5348 dprint((1,
5349 "read_pinerc: ERROR: %s in %s = \"%s\"\n",
5350 error ? error : "?",
5351 v->name ? v->name : "?",
5352 value ? value : "?"));
5355 * Special case: turn "" strings into empty strings.
5356 * This allows users to turn off default lists. For example,
5357 * if smtp-server is set then a user could override smtp-server
5358 * with smtp-server="".
5360 for(i = 0; lvalue[i]; i++)
5361 if(lvalue[i][0] == '"' &&
5362 lvalue[i][1] == '"' &&
5363 lvalue[i][2] == '\0')
5364 lvalue[i][0] = '\0';
5367 if(pline){
5368 if(v->is_user && (which_vars == ParsePers || !v->is_onlymain)){
5369 if(v->is_list){
5370 char ***l;
5372 l = (which_vars == ParsePers) ? &v->main_user_val.l
5373 : &v->post_user_val.l;
5374 free_list_array(l);
5375 *l = lvalue;
5377 else{
5378 char **p;
5380 p = (which_vars == ParsePers) ? &v->main_user_val.p
5381 : &v->post_user_val.p;
5382 if(p && *p != NULL)
5383 fs_give((void **)p);
5385 *p = cpystr(value);
5388 if(pline){
5389 pline->is_var = 1;
5390 pline->var = v;
5391 pline->is_quoted = was_quoted;
5392 pline++;
5396 else if(which_vars == ParseGlobal){
5397 if(v->is_global){
5398 if(v->is_list){
5399 free_list_array(&v->global_val.l);
5400 v->global_val.l = lvalue;
5402 else{
5403 if(v->global_val.p != NULL)
5404 fs_give((void **) &(v->global_val.p));
5406 v->global_val.p = cpystr(value);
5410 else{ /* which_vars == ParseFixed */
5411 if(v->is_user || v->is_global){
5412 if(v->is_list){
5413 free_list_array(&v->fixed_val.l);
5414 v->fixed_val.l = lvalue;
5416 else{
5417 if(v->fixed_val.p != NULL)
5418 fs_give((void **) &(v->fixed_val.p));
5420 v->fixed_val.p = cpystr(value);
5425 #ifdef DEBUG
5426 if(v->is_list){
5427 char **l;
5428 l = (which_vars == ParsePers) ? v->main_user_val.l :
5429 (which_vars == ParsePersPost) ? v->post_user_val.l :
5430 (which_vars == ParseGlobal) ? v->global_val.l :
5431 v->fixed_val.l;
5432 if(l && *l && **l){
5433 dprint((5, " %20.20s : %s\n",
5434 v->name ? v->name : "?",
5435 *l ? *l : "?"));
5436 while(++l && *l && **l)
5437 dprint((5, " %20.20s : %s\n", "",
5438 *l ? *l : "?"));
5440 }else{
5441 char *p;
5442 p = (which_vars == ParsePers) ? v->main_user_val.p :
5443 (which_vars == ParsePersPost) ? v->post_user_val.p :
5444 (which_vars == ParseGlobal) ? v->global_val.p :
5445 v->fixed_val.p;
5446 if(p && *p)
5447 dprint((5, " %20.20s : %s\n",
5448 v->name ? v->name : "?",
5449 p ? p : "?"));
5451 #endif /* DEBUG */
5454 if(pline){
5455 pline->line = NULL;
5456 pline->is_var = 0;
5457 if(!prc->pinerc_written && prc->type == Loc){
5458 prc->pinerc_written = name_file_mtime(filename);
5459 dprint((5, "read_pinerc: time_pinerc_written = %ld\n",
5460 (long) prc->pinerc_written));
5464 if(free_file)
5465 fs_give((void **) &free_file);
5470 * Args varname The variable name we're looking for
5471 * begin Begin looking here
5473 * Returns 1 if variable varname appears in the rest of the file
5474 * 0 if not
5477 var_is_in_rest_of_file(char *varname, char *begin)
5479 char *p;
5481 if(!(varname && *varname && begin && *begin))
5482 return 0;
5484 p = begin;
5486 while((p = srchstr(p, varname)) != NULL){
5487 /* beginning of a line? */
5488 if(p > begin && (*(p-1) != '\n' && *(p-1) != '\r')){
5489 p++;
5490 continue;
5493 /* followed by [ SPACE ] < = > ? */
5494 p += strlen(varname);
5495 while(*p == ' ' || *p == '\t')
5496 p++;
5498 if(*p == '=')
5499 return 1;
5502 return 0;
5507 * Args begin Variable to skip starts here.
5508 * nextline This is where the next line starts. We need to know this
5509 * because the input has been mangled a little. A \0 has
5510 * replaced the \n at the end of the first line, but we can
5511 * use nextline to help us out of that quandry.
5513 * Return a pointer to the start of the first line after this variable
5514 * and all of its continuation lines.
5516 char *
5517 skip_over_this_var(char *begin, char *nextline)
5519 char *p;
5521 p = begin;
5523 while(1){
5524 if(*p == '\0' || *p == '\n'){ /* EOL */
5525 if(p < nextline || *p == '\n'){ /* there may be another line */
5526 p++;
5527 if(*p != ' ' && *p != '\t') /* no continuation line */
5528 return(p);
5530 else /* end of file */
5531 return(p);
5533 else
5534 p++;
5539 static char quotes[3] = {'"', '"', '\0'};
5540 /*----------------------------------------------------------------------
5541 Write out the .pinerc state information
5543 Args: ps -- The pine structure to take state to be written from
5544 which -- Which pinerc to write
5545 flags -- If bit WRP_NOUSER is set, then assume that there is
5546 not a user present to answer questions.
5548 This writes to a temporary file first, and then renames that to
5549 be the new .pinerc file to protect against disk error. This has the
5550 problem of possibly messing up file protections, ownership and links.
5551 ----*/
5553 write_pinerc(struct pine *ps, EditWhich which, int flags)
5555 char *p, *dir, *tmp = NULL, *pinrc;
5556 char *pval, **lval;
5557 char *linep = NULL, *lineq = NULL;
5558 int bc = 1;
5559 int buflen;
5560 PINERC_LINE *pline;
5561 struct variable *var;
5562 time_t mtime;
5563 char *filename;
5564 REMDATA_S *rd = NULL;
5565 PINERC_S *prc = NULL;
5566 STORE_S *so = NULL;
5567 #ifndef _WINDOWS
5568 struct stat sbuf;
5569 char *slink = NULL;
5570 #endif
5572 #define MAXPLINESIZE 10000
5574 dprint((2,"---- write_pinerc(%s) ----\n",
5575 (which == Main) ? "Main" : "Post"));
5577 switch(which){
5578 case Main:
5579 prc = ps ? ps->prc : NULL;
5580 break;
5581 case Post:
5582 prc = ps ? ps->post_prc : NULL;
5583 break;
5584 default:
5585 break;
5588 if(!prc)
5589 return(-1);
5591 if(prc->quit_to_edit){
5592 if(!(flags & WRP_NOUSER))
5593 quit_to_edit_msg(prc);
5595 return(-1);
5598 if(prc->type != Loc && !prc->readonly){
5600 bc = 0; /* don't do backcompat conversion */
5601 rd = prc->rd;
5602 if(!rd)
5603 return(-1);
5605 rd_check_remvalid(rd, -10L);
5607 if(rd->flags & REM_OUTOFDATE){
5608 if((flags & WRP_NOUSER) || unexpected_pinerc_change()){
5609 prc->outstanding_pinerc_changes = 1;
5610 if(!(flags & WRP_NOUSER))
5611 q_status_message1(SM_ORDER | SM_DING, 3, 3,
5612 "Pinerc \"%.200s\" NOT saved",
5613 prc->name ? prc->name : "");
5614 dprint((2, "write_pinerc: remote pinerc changed\n"));
5615 return(-1);
5617 else
5618 rd->flags &= ~REM_OUTOFDATE;
5621 rd_open_remote(rd);
5623 if(rd->access == ReadWrite){
5624 int ro;
5626 if((ro=rd_remote_is_readonly(rd)) || rd->flags & REM_OUTOFDATE){
5627 if(ro == 1){
5628 if(!(flags & WRP_NOUSER))
5629 q_status_message(SM_ORDER | SM_DING, 5, 15,
5630 _("Can't access remote config, changes NOT saved!"));
5631 dprint((1,
5632 "write_pinerc: Can't write to remote pinerc %s, aborting write\n",
5633 rd->rn ? rd->rn : "?"));
5635 else if(ro == 2){
5636 if(!(rd->flags & NO_META_UPDATE)){
5637 unsigned long save_chk_nmsgs;
5639 switch(rd->type){
5640 case RemImap:
5641 save_chk_nmsgs = rd->t.i.chk_nmsgs;
5642 rd->t.i.chk_nmsgs = 0;
5643 rd_write_metadata(rd, 0);
5644 rd->t.i.chk_nmsgs = save_chk_nmsgs;
5645 break;
5647 default:
5648 q_status_message(SM_ORDER | SM_DING, 3, 5,
5649 "Write_pinerc: Type not supported");
5650 break;
5654 if(!(flags & WRP_NOUSER))
5655 q_status_message1(SM_ORDER | SM_DING, 5, 15,
5656 _("No write permission for remote config %.200s, changes NOT saved!"),
5657 rd->rn);
5659 else{
5660 if(!(flags & WRP_NOUSER))
5661 q_status_message(SM_ORDER | SM_DING, 5, 15,
5662 _("Remote config changed, aborting our change to avoid damage..."));
5663 dprint((1,
5664 "write_pinerc: remote config %s changed since we started pine, aborting write\n",
5665 prc->name ? prc->name : "?"));
5668 rd->flags &= ~DO_REMTRIM;
5669 return(-1);
5672 filename = rd->lf;
5674 else{
5675 prc->readonly = 1;
5676 if(prc == ps->prc)
5677 ps->readonly_pinerc = 1;
5680 else
5681 filename = prc->name ? prc->name : "";
5683 pinrc = prc->name ? prc->name : "";
5685 if(prc->type == Loc){
5686 mtime = name_file_mtime(filename);
5687 if(prc->pinerc_written
5688 && prc->pinerc_written != mtime
5689 && ((flags & WRP_NOUSER) || unexpected_pinerc_change())){
5690 prc->outstanding_pinerc_changes = 1;
5692 if(!(flags & WRP_NOUSER))
5693 q_status_message1(SM_ORDER | SM_DING, 3, 3,
5694 "Pinerc \"%.200s\" NOT saved", pinrc);
5696 dprint((2,"write_pinerc: mtime mismatch: \"%s\": %ld != %ld\n",
5697 filename ? filename : "?",
5698 (long) prc->pinerc_written, (long) mtime));
5699 return(-1);
5703 /* don't write if pinerc is read-only */
5704 if(prc->readonly ||
5705 (filename &&
5706 can_access(filename, ACCESS_EXISTS) == 0 &&
5707 can_access(filename, EDIT_ACCESS) != 0)){
5708 prc->readonly = 1;
5709 if(prc == ps->prc)
5710 ps->readonly_pinerc = 1;
5712 if(!(flags & WRP_NOUSER))
5713 q_status_message1(SM_ORDER | SM_DING, 0, 5,
5714 _("Can't modify configuration file \"%.200s\": ReadOnly"),
5715 pinrc);
5716 dprint((2, "write_pinerc: fail because can't access pinerc\n"));
5718 if(rd)
5719 rd->flags &= ~DO_REMTRIM;
5721 return(-1);
5724 if(rd && rd->flags & NO_FILE){
5725 so = rd->sonofile;
5726 so_truncate(rd->sonofile, 0L); /* reset storage object */
5728 else{
5729 dir = ".";
5730 if((p = last_cmpnt(filename)) != NULL){
5731 *--p = '\0';
5732 dir = filename;
5735 #if defined(DOS) || defined(OS2)
5736 if(!(isalpha((unsigned char)dir[0]) && dir[1] == ':' && dir[2] == '\0')
5737 && (can_access(dir, EDIT_ACCESS) < 0 &&
5738 our_mkdir(dir, 0700) < 0))
5740 if(!(flags & WRP_NOUSER))
5741 q_status_message2(SM_ORDER | SM_DING, 3, 5,
5742 /* TRANSLATORS: first argument is a filename, second
5743 arg is the text of the error message */
5744 _("Error creating \"%.200s\" : %.200s"), dir,
5745 error_description(errno));
5746 if(rd)
5747 rd->flags &= ~DO_REMTRIM;
5749 return(-1);
5752 tmp = temp_nam(dir, "rc");
5754 if(*dir && tmp && !in_dir(dir, tmp)){
5755 our_unlink(tmp);
5756 fs_give((void **)&tmp);
5759 if(p)
5760 *p = '\\';
5762 if(tmp == NULL)
5763 goto io_err;
5765 #else /* !DOS */
5766 tmp = temp_nam((*dir) ? dir : "/", "pinerc");
5769 * If temp_nam can't write in dir it puts the temp file in a
5770 * temp directory, which won't help us when we go to rename.
5772 if(*dir && tmp && !in_dir(dir, tmp)){
5773 our_unlink(tmp);
5774 fs_give((void **)&tmp);
5777 if(p)
5778 *p = '/';
5780 if(tmp == NULL)
5781 goto io_err;
5783 #endif /* !DOS */
5785 if((so = so_get(FileStar, tmp, WRITE_ACCESS)) == NULL)
5786 goto io_err;
5789 if(!(flags & WRP_PRESERV_WRITTEN))
5790 for(var = ps->vars; var->name != NULL; var++)
5791 var->been_written = 0;
5793 if(prc->type == Loc && ps->first_time_user &&
5794 !so_puts(so, native_nl(cf_text_comment)))
5795 goto io_err;
5797 linep = fs_get((MAXPLINESIZE+1)*sizeof(char));
5798 lineq = fs_get((MAXPLINESIZE+1)*sizeof(char));
5799 buflen = MAXPLINESIZE;
5801 /* Write out what was in the .pinerc */
5802 for(pline = prc->pinerc_lines;
5803 pline && (pline->is_var || pline->line); pline++){
5804 if(pline->is_var){
5805 var = pline->var;
5807 if(var->is_list)
5808 lval = LVAL(var, which);
5809 else
5810 pval = PVAL(var, which);
5812 /* variable is not set */
5813 if((var->is_list && (!lval || !lval[0])) ||
5814 (!var->is_list && !pval)){
5815 /* leave null variables out of remote pinerc */
5816 if(prc->type == Loc &&
5817 (!so_puts(so, var->name) || !so_puts(so, "=") ||
5818 !so_puts(so, NEWLINE)))
5819 goto io_err;
5821 /* var is set to empty string */
5822 else if((var->is_list && lval[0][0] == '\0') ||
5823 (!var->is_list && pval[0] == '\0')){
5824 if(!so_puts(so, var->name) || !so_puts(so, "=") ||
5825 !so_puts(so, quotes) || !so_puts(so, NEWLINE))
5826 goto io_err;
5828 else{
5829 if(var->is_list){
5830 int i = 0;
5832 for(i = 0; lval[i]; i++){
5833 if(strlen(var->name)
5834 + (lval[i][0] ? strlen(lval[i]) : 5) > buflen){
5835 buflen = strlen(var->name)
5836 + (lval[i][0] ? strlen(lval[i]) : 5);
5837 fs_resize((void **)&linep, (buflen+1)*sizeof(char));
5838 fs_resize((void **)&lineq, (buflen+1)*sizeof(char));
5840 snprintf(linep, buflen+1, "%s%s%s%s%s",
5841 (i) ? "\t" : var->name,
5842 (i) ? "" : "=",
5843 lval[i][0] ? lval[i] : quotes,
5844 lval[i+1] ? "," : "", NEWLINE);
5845 linep[buflen] = '\0';
5846 if(!so_puts(so, bc ? backcompat_convert_from_utf8(&lineq, buflen+1, linep) : linep))
5847 goto io_err;
5850 else{
5851 if(strlen(var->name)
5852 + (pval[0] ? strlen(pval) : 5) > buflen){
5853 buflen = strlen(var->name)
5854 + (pval[0] ? strlen(pval) : 5);
5855 fs_resize((void **)&linep, (buflen+1)*sizeof(char));
5856 fs_resize((void **)&lineq, (buflen+1)*sizeof(char));
5858 snprintf(linep, buflen+1, "%s=%s%s%s%s",
5859 var->name,
5860 (pline->is_quoted && pval[0] != '\"')
5861 ? "\"" : "",
5862 pval,
5863 (pline->is_quoted && pval[0] != '\"')
5864 ? "\"" : "", NEWLINE);
5865 linep[buflen] = '\0';
5866 if(!so_puts(so, bc ? backcompat_convert_from_utf8(&lineq, buflen+1, linep) : linep))
5867 goto io_err;
5871 var->been_written = 1;
5873 }else{
5875 * The description text should be changed into a message
5876 * about the variable being obsolete when a variable is
5877 * moved to obsolete status. We add that message before
5878 * the variable unless it is already there. However, we
5879 * leave the variable itself in case the user runs an old
5880 * version of pine again. Note that we have read in the
5881 * value of the variable in read_pinerc and translated it
5882 * into a new variable if appropriate.
5884 if(pline->obsolete_var && prc->type == Loc){
5885 if(pline <= prc->pinerc_lines || (pline-1)->line == NULL ||
5886 strlen((pline-1)->line) < 3 ||
5887 strucmp((pline-1)->line+2, pline->var->descrip) != 0)
5888 if(!so_puts(so, "# ") ||
5889 !so_puts(so, native_nl(pline->var->descrip)) ||
5890 !so_puts(so, NEWLINE))
5891 goto io_err;
5894 /* remove comments from remote pinercs */
5895 if((prc->type == Loc ||
5896 (pline->line[0] != '#' && pline->line[0] != '\0')) &&
5897 (!so_puts(so, pline->line) || !so_puts(so, NEWLINE)))
5898 goto io_err;
5902 /* Now write out all the variables not in the .pinerc */
5903 for(var = ps->vars; var->name != NULL; var++){
5904 if(!var->is_user || var->been_written || !var->is_used ||
5905 var->is_obsolete || (var->is_onlymain && which != Main))
5906 continue;
5908 if(var->is_list)
5909 lval = LVAL(var, which);
5910 else
5911 pval = PVAL(var, which);
5914 * set description to NULL to eliminate preceding
5915 * blank and comment line.
5917 if(prc->type == Loc && var->descrip && *var->descrip &&
5918 (!so_puts(so, NEWLINE) || !so_puts(so, "# ") ||
5919 !so_puts(so, native_nl(var->descrip)) || !so_puts(so, NEWLINE)))
5920 goto io_err;
5922 /* variable is not set */
5923 /** Don't know what the global_val thing is for. SH, Mar 00 **/
5924 if((var->is_list && (!lval || (!lval[0] && !var->global_val.l))) ||
5925 (!var->is_list && !pval)){
5926 /* leave null variables out of remote pinerc */
5927 if(prc->type == Loc &&
5928 (!so_puts(so, var->name) || !so_puts(so, "=") ||
5929 !so_puts(so, NEWLINE)))
5930 goto io_err;
5932 /* var is set to empty string */
5933 else if((var->is_list && (!lval[0] || !lval[0][0]))
5934 || (!var->is_list && pval[0] == '\0')){
5935 if(!so_puts(so, var->name) || !so_puts(so, "=") ||
5936 !so_puts(so, quotes) || !so_puts(so, NEWLINE))
5937 goto io_err;
5939 else if(var->is_list){
5940 int i = 0;
5942 for(i = 0; lval[i] ; i++){
5943 if(strlen(var->name)
5944 + (lval[i][0] ? strlen(lval[i]) : 5) > buflen){
5945 buflen = strlen(var->name)
5946 + (lval[i][0] ? strlen(lval[i]) : 5);
5947 fs_resize((void **)&linep, (buflen+1)*sizeof(char));
5948 fs_resize((void **)&lineq, (buflen+1)*sizeof(char));
5950 snprintf(linep, buflen+1, "%s%s%s%s%s",
5951 (i) ? "\t" : var->name,
5952 (i) ? "" : "=",
5953 lval[i],
5954 lval[i+1] ? "," : "", NEWLINE);
5955 linep[buflen] = '\0';
5956 if(!so_puts(so, bc ? backcompat_convert_from_utf8(&lineq, buflen+1, linep) : linep))
5957 goto io_err;
5960 else{
5961 char *pconverted;
5963 if(strlen(pval) > buflen){
5964 buflen = strlen(pval) + 1;
5965 fs_resize((void **)&linep, (buflen+1)*sizeof(char));
5966 fs_resize((void **)&lineq, (buflen+1)*sizeof(char));
5968 pconverted = bc ? backcompat_convert_from_utf8(&lineq, buflen+1, pval) : pval;
5970 if(!so_puts(so, var->name) || !so_puts(so, "=") ||
5971 !so_puts(so, pconverted) || !so_puts(so, NEWLINE))
5972 goto io_err;
5976 if(!(rd && rd->flags & NO_FILE)){
5977 char *realfilename;
5978 int realfilename_malloced;
5980 if(so_give(&so)) goto io_err;
5982 #ifndef _WINDOWS
5983 realfilename = fs_get(MAXPATH+1);
5984 if(realfilename != NULL){
5985 if(realpath(filename, realfilename) == NULL)
5986 fs_give((void **) &realfilename);
5987 realfilename_malloced = realfilename != NULL ? 1 : 0;
5989 else
5990 realfilename_malloced = 0;
5991 if (realfilename_malloced == 0){
5992 if(our_stat(filename, &sbuf) < 0 && errno == ENOENT){
5993 realfilename = filename;
5994 realfilename_malloced = 0;
5996 else
5997 goto io_err;
5999 #else
6000 realfilename = filename;
6001 realfilename_malloced = 0;
6002 #endif /* _WINDOWS */
6003 if(realfilename != NULL){
6004 int r;
6005 file_attrib_copy(tmp, realfilename);
6006 r = rename_file(tmp, realfilename);
6007 if(realfilename_malloced != 0)
6008 fs_give((void **) &realfilename);
6009 if(r < 0) goto io_err;
6013 if(prc->type != Loc){
6014 int e, we_cancel;
6015 char datebuf[200];
6017 datebuf[0] = '\0';
6018 we_cancel = 0;
6020 if(!(flags & WRP_NOUSER))
6021 we_cancel = busy_cue(_("Copying to remote config"), NULL, 1);
6023 if((e = rd_update_remote(rd, datebuf)) != 0){
6024 dprint((1,
6025 "write_pinerc: error copying from %s to %s\n",
6026 rd->lf ? rd->lf : "<memory>", rd->rn ? rd->rn : "?"));
6027 if(!(flags & WRP_NOUSER)){
6028 q_status_message2(SM_ORDER | SM_DING, 3, 5,
6029 _("Error copying to %.200s: %.200s"),
6030 rd->rn, error_description(errno));
6032 q_status_message(SM_ORDER | SM_DING, 5, 5,
6033 _("Copy of config to remote folder failed, changes NOT saved remotely"));
6036 else{
6037 rd_update_metadata(rd, datebuf);
6038 rd->read_status = 'W';
6039 rd_trim_remdata(&rd);
6040 rd_close_remote(rd);
6043 if(we_cancel)
6044 cancel_busy_cue(-1);
6047 prc->outstanding_pinerc_changes = 0;
6049 if(prc->type == Loc){
6050 prc->pinerc_written = name_file_mtime(filename);
6051 dprint((2, "wrote pinerc: %s: time_pinerc_written = %ld\n",
6052 pinrc ? pinrc : "?", (long) prc->pinerc_written));
6054 else{
6055 dprint((2, "wrote pinerc: %s\n", pinrc ? pinrc : "?"));
6058 if(tmp){
6059 our_unlink(tmp);
6060 fs_give((void **)&tmp);
6063 if(linep) fs_give((void **)&linep);
6064 if(lineq) fs_give((void **)&lineq);
6066 return(0);
6068 io_err:
6069 if(!(flags & WRP_NOUSER))
6070 q_status_message2(SM_ORDER | SM_DING, 3, 5,
6071 _("Error saving configuration in \"%.200s\": %.200s"),
6072 pinrc, error_description(errno));
6074 dprint((1, "Error writing %s : %s\n", pinrc ? pinrc : "?",
6075 error_description(errno)));
6076 if(rd)
6077 rd->flags &= ~DO_REMTRIM;
6078 if(tmp){
6079 our_unlink(tmp);
6080 fs_give((void **)&tmp);
6083 if(linep) fs_give((void **)&linep);
6084 if(lineq) fs_give((void **)&lineq);
6086 return(-1);
6091 * The srcstr is UTF-8. In order to help the user with
6092 * running this pine and an old pre-alpine pine on the same config
6093 * file we attempt to convert the values of the config variables
6094 * to the user's character set before writing.
6095 * parameters: char **buf. Memory of size_t buflen allocated by caller.
6097 char *
6098 backcompat_convert_from_utf8(char **buf, size_t buflen, char *srcstr)
6100 char *converted = NULL;
6101 char *p;
6102 int its_ascii = 1;
6105 for(p = srcstr; *p && its_ascii; p++)
6106 if(*p & 0x80)
6107 its_ascii = 0;
6109 /* if it is ascii, go with that */
6110 if(its_ascii){
6111 strncpy(*buf, srcstr, buflen);
6112 converted = *buf;
6113 (*buf)[buflen-1] = '\0';
6115 else{
6116 char *trythischarset = NULL;
6119 * If it is possible to translate the UTF-8
6120 * string into the user's character set then
6121 * do that. For backwards compatibility with
6122 * old pines.
6124 if(ps_global->keyboard_charmap && ps_global->keyboard_charmap[0])
6125 trythischarset = ps_global->keyboard_charmap;
6126 else if(ps_global->display_charmap && ps_global->display_charmap[0])
6127 trythischarset = ps_global->display_charmap;
6129 if(trythischarset){
6130 SIZEDTEXT src, dst;
6132 src.data = (unsigned char *) srcstr;
6133 src.size = strlen(srcstr);
6134 memset(&dst, 0, sizeof(dst));
6135 if(utf8_cstext(&src, trythischarset, &dst, 0)){
6136 if(dst.data){
6137 strncpy(*buf, (char *) dst.data, buflen);
6138 (*buf)[buflen-1] = '\0';
6139 fs_give((void **) &dst.data);
6144 if(!converted){
6145 strncpy(*buf, srcstr, buflen);
6146 (*buf)[buflen-1] = '\0';
6147 converted = *buf;
6151 return(converted);
6156 * Given a unix-style source string which may contain LFs,
6157 * convert those to CRLFs if appropriate.
6159 * Returns a pointer to the converted string. This will be a string
6160 * stored in tmp_20k_buf.
6162 * This is just used for the variable descriptions in the pinerc file. It
6163 * could certainly be fancier. It simply converts all \n to NEWLINE.
6165 char *
6166 native_nl(char *src)
6168 char *q, *p;
6170 tmp_20k_buf[0] = '\0';
6172 if(src){
6173 for(q = (char *)tmp_20k_buf; *src; src++){
6174 if(*src == '\n'){
6175 for(p = NEWLINE; *p; p++)
6176 *q++ = *p;
6178 else
6179 *q++ = *src;
6182 *q = '\0';
6185 return((char *)tmp_20k_buf);
6189 void
6190 quit_to_edit_msg(PINERC_S *prc)
6192 /* TRANSLATORS: The %s is either "Postload " or nothing. A Postload config file
6193 is a type of config file. */
6194 q_status_message1(SM_ORDER, 3, 4, _("Must quit Alpine to change %sconfig file."),
6195 (prc == ps_global->post_prc) ? "Postload " : "");
6199 /*------------------------------------------------------------
6200 Return TRUE if the given string was a feature name present in the
6201 pinerc as it was when pine was started...
6202 ----*/
6204 var_in_pinerc(char *s)
6206 PINERC_LINE *pline;
6208 for(pline = ps_global->prc ? ps_global->prc->pinerc_lines : NULL;
6209 pline && (pline->var || pline->line); pline++)
6210 if(pline->var && pline->var->name && !strucmp(s, pline->var->name))
6211 return(1);
6213 for(pline = ps_global->post_prc ? ps_global->post_prc->pinerc_lines : NULL;
6214 pline && (pline->var || pline->line); pline++)
6215 if(pline->var && pline->var->name && !strucmp(s, pline->var->name))
6216 return(1);
6218 return(0);
6222 /*------------------------------------------------------------
6223 Free resources associated with pinerc_lines data
6224 ----*/
6225 void
6226 free_pinerc_lines(PINERC_LINE **pinerc_lines)
6228 PINERC_LINE *pline;
6230 if(pinerc_lines && *pinerc_lines){
6231 for(pline = *pinerc_lines; pline->var || pline->line; pline++)
6232 if(pline->line)
6233 fs_give((void **)&pline->line);
6235 fs_give((void **)pinerc_lines);
6240 /*------------------------------------------------------------
6241 Dump out a global pine.conf on the standard output with fresh
6242 comments. Preserves variables currently set in SYSTEM_PINERC, if any.
6243 ----*/
6244 void
6245 dump_global_conf(void)
6247 FILE *f;
6248 struct variable *var;
6249 PINERC_S *prc;
6251 prc = new_pinerc_s(SYSTEM_PINERC);
6252 read_pinerc(prc, variables, ParseGlobal);
6253 if(prc)
6254 free_pinerc_s(&prc);
6256 f = stdout;
6257 if(f == NULL)
6258 goto io_err;
6260 fprintf(f, "# %s -- system wide pine configuration\n#\n",
6261 SYSTEM_PINERC);
6262 fprintf(f, "# Values here affect all pine users unless they've overridden the values\n");
6263 fprintf(f, "# in their .pinerc files. A copy of this file with current comments may\n");
6264 fprintf(f, "# be obtained by running \"pine -conf\". It will be printed to standard output.\n#\n");
6265 fprintf(f,"# For a variable to be unset its value must be null/blank. This is not the\n");
6266 fprintf(f,"# same as the value of \"empty string\", which can be used to effectively\n");
6267 fprintf(f,"# \"unset\" a variable that has a default or previously assigned value.\n");
6268 fprintf(f,"# To set a variable to the empty string its value should be \"\".\n");
6269 fprintf(f,"# Switch variables are set to either \"yes\" or \"no\", and default to \"no\".\n");
6270 fprintf(f,"# Except for feature-list items, which are additive, values set in the\n");
6271 fprintf(f,"# .pinerc file replace those in pine.conf, and those in pine.conf.fixed\n");
6272 fprintf(f,"# over-ride all others. Features can be over-ridden in .pinerc or\n");
6273 fprintf(f,"# pine.conf.fixed by pre-pending the feature name with \"no-\".\n#\n");
6274 fprintf(f,"# (These comments are automatically inserted.)\n");
6276 for(var = variables; var->name != NULL; var++){
6277 if(!var->is_global || !var->is_used || var->is_obsolete)
6278 continue;
6280 if(var->descrip && *var->descrip){
6281 if(fprintf(f, "\n# %s\n", var->descrip) == EOF)
6282 goto io_err;
6285 if(var->is_list){
6286 if(var->global_val.l == NULL){
6287 if(fprintf(f, "%s=\n", var->name) == EOF)
6288 goto io_err;
6289 }else{
6290 int i;
6292 for(i=0; var->global_val.l[i]; i++)
6293 if(fprintf(f, "%s%s%s%s\n", (i) ? "\t" : var->name,
6294 (i) ? "" : "=", var->global_val.l[i],
6295 var->global_val.l[i+1] ? ",":"") == EOF)
6296 goto io_err;
6298 }else{
6299 if(var->global_val.p == NULL){
6300 if(fprintf(f, "%s=\n", var->name) == EOF)
6301 goto io_err;
6302 }else if(strlen(var->global_val.p) == 0){
6303 if(fprintf(f, "%s=\"\"\n", var->name) == EOF)
6304 goto io_err;
6305 }else{
6306 if(fprintf(f,"%s=%s\n",var->name,var->global_val.p) == EOF)
6307 goto io_err;
6311 exit(0);
6314 io_err:
6315 fprintf(stderr, "Error writing config to stdout: %s\n",
6316 error_description(errno));
6317 exit(-1);
6321 /*------------------------------------------------------------
6322 Dump out a pinerc to filename with fresh
6323 comments. Preserves variables currently set in pinerc, if any.
6324 ----*/
6325 void
6326 dump_new_pinerc(char *filename)
6328 FILE *f;
6329 struct variable *var;
6330 char buf[MAXPATH], *p;
6331 PINERC_S *prc;
6334 p = ps_global->pinerc;
6336 #if defined(DOS) || defined(OS2)
6337 if(!ps_global->pinerc){
6338 char *p;
6340 if(p = getenv("PINERC")){
6341 ps_global->pinerc = cpystr(p);
6342 }else{
6343 char buf2[MAXPATH];
6344 build_path(buf2, ps_global->home_dir, DF_PINEDIR, sizeof(buf2));
6345 build_path(buf, buf2, SYSTEM_PINERC, sizeof(buf));
6348 p = buf;
6350 #else /* !DOS */
6351 if(!ps_global->pinerc){
6352 build_path(buf, ps_global->home_dir, ".pinerc", sizeof(buf));
6353 p = buf;
6355 #endif /* !DOS */
6357 prc = new_pinerc_s(p);
6358 read_pinerc(prc, variables, ParsePers);
6359 if(prc)
6360 free_pinerc_s(&prc);
6362 f = NULL;;
6363 if(filename[0] == '\0'){
6364 fprintf(stderr, "Missing argument to \"-pinerc\".\n");
6365 }else if(!strcmp(filename, "-")){
6366 f = stdout;
6367 }else{
6368 f = our_fopen(filename, "wb");
6371 if(f == NULL)
6372 goto io_err;
6374 if(fprintf(f, "%s", cf_text_comment) == EOF)
6375 goto io_err;
6377 for(var = variables; var->name != NULL; var++){
6378 dprint((7,"write_pinerc: %s = %s\n",
6379 var->name ? var->name : "?",
6380 var->main_user_val.p ? var->main_user_val.p : "<not set>"));
6381 if(!var->is_user || !var->is_used || var->is_obsolete)
6382 continue;
6385 * set description to NULL to eliminate preceding
6386 * blank and comment line.
6388 if(var->descrip && *var->descrip){
6389 if(fprintf(f, "\n# %s\n", var->descrip) == EOF)
6390 goto io_err;
6393 if(var->is_list){
6394 if(var->main_user_val.l == NULL){
6395 if(fprintf(f, "%s=\n", var->name) == EOF)
6396 goto io_err;
6397 }else{
6398 int i;
6400 for(i=0; var->main_user_val.l[i]; i++)
6401 if(fprintf(f, "%s%s%s%s\n", (i) ? "\t" : var->name,
6402 (i) ? "" : "=", var->main_user_val.l[i],
6403 var->main_user_val.l[i+1] ? ",":"") == EOF)
6404 goto io_err;
6406 }else{
6407 if(var->main_user_val.p == NULL){
6408 if(fprintf(f, "%s=\n", var->name) == EOF)
6409 goto io_err;
6410 }else if(strlen(var->main_user_val.p) == 0){
6411 if(fprintf(f, "%s=\"\"\n", var->name) == EOF)
6412 goto io_err;
6413 }else{
6414 if(fprintf(f,"%s=%s\n",var->name,var->main_user_val.p) == EOF)
6415 goto io_err;
6419 exit(0);
6422 io_err:
6423 snprintf(buf, sizeof(buf), "Error writing config to %s: %s\n",
6424 filename, error_description(errno));
6425 exceptional_exit(buf, -1);
6429 /*----------------------------------------------------------------------
6430 Set a user variable and save the .pinerc
6432 Args: var -- The index of the variable to set from conftype.h (V_....)
6433 value -- The string to set the value to
6435 Result: -1 is returned on failure and 0 is returned on success
6437 The vars data structure is updated and the pinerc saved.
6438 ----*/
6440 set_variable(int var, char *value, int expand, int commit, EditWhich which)
6442 struct variable *v;
6443 char **apval;
6444 PINERC_S *prc;
6446 v = &ps_global->vars[var];
6448 if(!v->is_user)
6449 panic1("Trying to set non-user variable %s", v->name);
6451 /* Override value of which, at most one of these should be set */
6452 if(v->is_onlymain)
6453 which = Main;
6454 else if(v->is_outermost)
6455 which = ps_global->ew_for_except_vars;
6457 apval = APVAL(v, which);
6459 if(!apval)
6460 return(-1);
6462 if(*apval)
6463 fs_give((void **)apval);
6465 *apval = value ? cpystr(value) : NULL;
6466 set_current_val(v, expand, FALSE);
6468 switch(which){
6469 case Main:
6470 prc = ps_global->prc;
6471 break;
6472 case Post:
6473 prc = ps_global->post_prc;
6474 break;
6475 default:
6476 break;
6479 if(prc)
6480 prc->outstanding_pinerc_changes = 1;
6482 return(commit ? write_pinerc(ps_global, which, WRP_NONE) : 0);
6486 /*----------------------------------------------------------------------
6487 Set a user variable list and save the .pinerc
6489 Args: var -- The index of the variable to set from conftype.h (V_....)
6490 lvalue -- The list to set the value to
6492 Result: -1 is returned on failure and 0 is returned on success
6494 The vars data structure is updated and if write_it, the pinerc is saved.
6495 ----*/
6497 set_variable_list(int var, char **lvalue, int write_it, EditWhich which)
6499 char ***alval;
6500 int i;
6501 struct variable *v = &ps_global->vars[var];
6502 PINERC_S *prc;
6504 if(!v->is_user || !v->is_list)
6505 panic1("BOTCH: Trying to set non-user or non-list variable %s", v->name);
6507 /* Override value of which, at most one of these should be set */
6508 if(v->is_onlymain)
6509 which = Main;
6510 else if(v->is_outermost)
6511 which = ps_global->ew_for_except_vars;
6513 alval = ALVAL(v, which);
6514 if(!alval)
6515 return(-1);
6517 if(*alval)
6518 free_list_array(alval);
6520 if(lvalue){
6521 for(i = 0; lvalue[i] ; i++) /* count elements */
6524 *alval = (char **) fs_get((i+1) * sizeof(char *));
6526 for(i = 0; lvalue[i] ; i++)
6527 (*alval)[i] = cpystr(lvalue[i]);
6529 (*alval)[i] = NULL;
6532 set_current_val(v, TRUE, FALSE);
6534 switch(which){
6535 case Main:
6536 prc = ps_global->prc;
6537 break;
6538 case Post:
6539 prc = ps_global->post_prc;
6540 break;
6541 default:
6542 break;
6545 if(prc)
6546 prc->outstanding_pinerc_changes = 1;
6548 return(write_it ? write_pinerc(ps_global, which, WRP_NONE) : 0);
6552 void
6553 set_current_color_vals(struct pine *ps)
6555 struct variable *vars = ps->vars;
6556 int later_color_is_set = 0;
6558 set_current_val(&vars[V_NORM_FORE_COLOR], TRUE, TRUE);
6559 set_current_val(&vars[V_NORM_BACK_COLOR], TRUE, TRUE);
6560 pico_nfcolor(VAR_NORM_FORE_COLOR);
6561 pico_nbcolor(VAR_NORM_BACK_COLOR);
6563 set_current_val(&vars[V_REV_FORE_COLOR], TRUE, TRUE);
6564 set_current_val(&vars[V_REV_BACK_COLOR], TRUE, TRUE);
6565 pico_rfcolor(VAR_REV_FORE_COLOR);
6566 pico_rbcolor(VAR_REV_BACK_COLOR);
6568 set_color_val(&vars[V_TITLE_FORE_COLOR], 1);
6569 set_color_val(&vars[V_TITLECLOSED_FORE_COLOR], 0);
6570 set_color_val(&vars[V_FOLDER_FORE_COLOR], 0);
6571 set_color_val(&vars[V_DIRECTORY_FORE_COLOR], 0);
6572 set_color_val(&vars[V_FOLDER_LIST_FORE_COLOR], 0);
6573 set_color_val(&vars[V_STATUS_FORE_COLOR], 1);
6574 set_color_val(&vars[V_KEYLABEL_FORE_COLOR], 1);
6575 set_color_val(&vars[V_KEYNAME_FORE_COLOR], 1);
6576 set_color_val(&vars[V_SLCTBL_FORE_COLOR], 1);
6577 set_color_val(&vars[V_METAMSG_FORE_COLOR], 1);
6578 set_color_val(&vars[V_PROMPT_FORE_COLOR], 1);
6579 set_color_val(&vars[V_HEADER_GENERAL_FORE_COLOR], 1);
6580 set_color_val(&vars[V_IND_PLUS_FORE_COLOR], 0);
6581 set_color_val(&vars[V_IND_IMP_FORE_COLOR], 0);
6582 set_color_val(&vars[V_IND_DEL_FORE_COLOR], 0);
6583 set_color_val(&vars[V_IND_HIPRI_FORE_COLOR], 0);
6584 set_color_val(&vars[V_IND_LOPRI_FORE_COLOR], 0);
6585 set_color_val(&vars[V_IND_ANS_FORE_COLOR], 0);
6586 set_color_val(&vars[V_IND_NEW_FORE_COLOR], 0);
6587 set_color_val(&vars[V_IND_REC_FORE_COLOR], 0);
6588 set_color_val(&vars[V_IND_FWD_FORE_COLOR], 0);
6589 set_color_val(&vars[V_IND_UNS_FORE_COLOR], 0);
6590 set_color_val(&vars[V_IND_ARR_FORE_COLOR], 0);
6591 set_color_val(&vars[V_IND_SUBJ_FORE_COLOR], 0);
6592 set_color_val(&vars[V_IND_FROM_FORE_COLOR], 0);
6593 set_color_val(&vars[V_IND_OP_FORE_COLOR], 0);
6594 set_color_val(&vars[V_INCUNSEEN_FORE_COLOR], 0);
6595 set_color_val(&vars[V_SIGNATURE_FORE_COLOR], 0);
6597 set_current_val(&ps->vars[V_INDEX_TOKEN_COLORS], TRUE, TRUE);
6598 set_current_val(&ps->vars[V_VIEW_HDR_COLORS], TRUE, TRUE);
6599 set_current_val(&ps->vars[V_KW_COLORS], TRUE, TRUE);
6600 set_custom_spec_colors(ps);
6603 * Set up the quoting colors. If a later color is set but not an earlier
6604 * color we set the earlier color to Normal to make it easier when
6605 * we go to use the colors. However, if the only quote colors set are
6606 * Normal that is the same as no settings, so delete them.
6608 set_color_val(&vars[V_QUOTE1_FORE_COLOR], 0);
6609 set_color_val(&vars[V_QUOTE2_FORE_COLOR], 0);
6610 set_color_val(&vars[V_QUOTE3_FORE_COLOR], 0);
6612 if((!(VAR_QUOTE3_FORE_COLOR && VAR_QUOTE3_BACK_COLOR) ||
6613 (!strucmp(VAR_QUOTE3_FORE_COLOR, VAR_NORM_FORE_COLOR) &&
6614 !strucmp(VAR_QUOTE3_BACK_COLOR, VAR_NORM_BACK_COLOR))) &&
6615 (!(VAR_QUOTE2_FORE_COLOR && VAR_QUOTE2_BACK_COLOR) ||
6616 (!strucmp(VAR_QUOTE2_FORE_COLOR, VAR_NORM_FORE_COLOR) &&
6617 !strucmp(VAR_QUOTE2_BACK_COLOR, VAR_NORM_BACK_COLOR))) &&
6618 (!(VAR_QUOTE1_FORE_COLOR && VAR_QUOTE1_BACK_COLOR) ||
6619 (!strucmp(VAR_QUOTE1_FORE_COLOR, VAR_NORM_FORE_COLOR) &&
6620 !strucmp(VAR_QUOTE1_BACK_COLOR, VAR_NORM_BACK_COLOR)))){
6622 * They are all either Normal or not set. Delete them all.
6624 if(VAR_QUOTE3_FORE_COLOR)
6625 fs_give((void **)&VAR_QUOTE3_FORE_COLOR);
6626 if(VAR_QUOTE3_BACK_COLOR)
6627 fs_give((void **)&VAR_QUOTE3_BACK_COLOR);
6628 if(VAR_QUOTE2_FORE_COLOR)
6629 fs_give((void **)&VAR_QUOTE2_FORE_COLOR);
6630 if(VAR_QUOTE2_BACK_COLOR)
6631 fs_give((void **)&VAR_QUOTE2_BACK_COLOR);
6632 if(VAR_QUOTE1_FORE_COLOR)
6633 fs_give((void **)&VAR_QUOTE1_FORE_COLOR);
6634 if(VAR_QUOTE1_BACK_COLOR)
6635 fs_give((void **)&VAR_QUOTE1_BACK_COLOR);
6637 else{ /* something is non-Normal */
6638 if(VAR_QUOTE3_FORE_COLOR && VAR_QUOTE3_BACK_COLOR)
6639 later_color_is_set++;
6641 /* if 3 is set but not 2, set 2 to Normal */
6642 if(VAR_QUOTE2_FORE_COLOR && VAR_QUOTE2_BACK_COLOR)
6643 later_color_is_set++;
6644 else if(later_color_is_set)
6645 set_color_val(&vars[V_QUOTE2_FORE_COLOR], 1);
6647 /* if 3 or 2 is set but not 1, set 1 to Normal */
6648 if(VAR_QUOTE1_FORE_COLOR && VAR_QUOTE1_BACK_COLOR)
6649 later_color_is_set++;
6650 else if(later_color_is_set)
6651 set_color_val(&vars[V_QUOTE1_FORE_COLOR], 1);
6654 #ifdef _WINDOWS
6655 if(ps->pre441){
6656 int conv_main = 0, conv_post = 0;
6658 ps->pre441 = 0;
6659 if(ps->prc && !unix_color_style_in_pinerc(ps->prc)){
6660 conv_main = convert_pc_gray_names(ps, ps->prc, Main);
6661 if(conv_main)
6662 ps->prc->outstanding_pinerc_changes = 1;
6666 if(ps->post_prc && !unix_color_style_in_pinerc(ps->post_prc)){
6667 conv_post = convert_pc_gray_names(ps, ps->post_prc, Post);
6668 if(conv_post)
6669 ps->post_prc->outstanding_pinerc_changes = 1;
6672 if(conv_main || conv_post){
6673 if(conv_main)
6674 write_pinerc(ps, Main, WRP_NONE);
6676 if(conv_post)
6677 write_pinerc(ps, Post, WRP_NONE);
6679 set_current_color_vals(ps);
6682 #endif /* _WINDOWS */
6684 pico_set_normal_color();
6689 * Set current_val for the foreground and background color vars, which
6690 * are assumed to be in order. If a set_current_val on them doesn't
6691 * produce current_vals, then use the colors from defvar to set those
6692 * current_vals.
6694 void
6695 set_color_val(struct variable *v, int use_default)
6697 set_current_val(v, TRUE, TRUE);
6698 set_current_val(v+1, TRUE, TRUE);
6700 if(!(v->current_val.p && v->current_val.p[0] &&
6701 (v+1)->current_val.p && (v+1)->current_val.p[0])){
6702 struct variable *defvar;
6704 if(v->current_val.p)
6705 fs_give((void **)&v->current_val.p);
6706 if((v+1)->current_val.p)
6707 fs_give((void **)&(v+1)->current_val.p);
6709 if(!use_default)
6710 return;
6712 if(var_defaults_to_rev(v))
6713 defvar = &ps_global->vars[V_REV_FORE_COLOR];
6714 else
6715 defvar = &ps_global->vars[V_NORM_FORE_COLOR];
6717 /* use default vars values instead */
6718 if(defvar && defvar->current_val.p && defvar->current_val.p[0] &&
6719 (defvar+1)->current_val.p && (defvar+1)->current_val.p[0]){
6720 v->current_val.p = cpystr(defvar->current_val.p);
6721 (v+1)->current_val.p = cpystr((defvar+1)->current_val.p);
6728 var_defaults_to_rev(struct variable *v)
6730 return(v == &ps_global->vars[V_REV_FORE_COLOR] ||
6731 v == &ps_global->vars[V_TITLE_FORE_COLOR] ||
6732 v == &ps_global->vars[V_STATUS_FORE_COLOR] ||
6733 v == &ps_global->vars[V_KEYNAME_FORE_COLOR] ||
6734 v == &ps_global->vars[V_PROMPT_FORE_COLOR]);
6740 * Each item in the list looks like:
6742 * /HDR=<header>/FG=<foreground color>/BG=<background color>
6744 * We separate the three pieces into an array of structures to make
6745 * it easier to deal with later.
6747 void
6748 set_custom_spec_colors(struct pine *ps)
6750 if(ps->index_token_colors)
6751 free_spec_colors(&ps->index_token_colors);
6753 ps->index_token_colors = spec_colors_from_varlist(ps->VAR_INDEX_TOKEN_COLORS, 1);
6755 if(ps->hdr_colors)
6756 free_spec_colors(&ps->hdr_colors);
6758 ps->hdr_colors = spec_colors_from_varlist(ps->VAR_VIEW_HDR_COLORS, 1);
6760 /* fit keyword colors into the same structures for code re-use */
6761 if(ps->kw_colors)
6762 free_spec_colors(&ps->kw_colors);
6764 ps->kw_colors = spec_colors_from_varlist(ps->VAR_KW_COLORS, 1);
6769 * Input is one item from config variable.
6771 * Return value must be freed by caller. The return is a single SPEC_COLOR_S,
6772 * not a list.
6774 SPEC_COLOR_S *
6775 spec_color_from_var(char *t, int already_expanded)
6777 char *p, *spec, *fg, *bg;
6778 PATTERN_S *val;
6779 SPEC_COLOR_S *new_hcolor = NULL;
6781 if(t && t[0] && !strcmp(t, INHERIT)){
6782 new_hcolor = (SPEC_COLOR_S *)fs_get(sizeof(*new_hcolor));
6783 memset((void *)new_hcolor, 0, sizeof(*new_hcolor));
6784 new_hcolor->inherit = 1;
6786 else if(t && t[0]){
6787 char tbuf[10000];
6789 if(!already_expanded){
6790 tbuf[0] = '\0';
6791 if(expand_variables(tbuf, sizeof(tbuf), t, 0))
6792 t = tbuf;
6795 spec = fg = bg = NULL;
6796 val = NULL;
6797 if((p = srchstr(t, "/HDR=")) != NULL)
6798 spec = remove_backslash_escapes(p+5);
6799 if((p = srchstr(t, "/FG=")) != NULL)
6800 fg = remove_backslash_escapes(p+4);
6801 if((p = srchstr(t, "/BG=")) != NULL)
6802 bg = remove_backslash_escapes(p+4);
6803 val = parse_pattern("VAL", t, 0);
6805 if(spec && *spec){
6806 /* remove colons */
6807 if((p = strindex(spec, ':')) != NULL)
6808 *p = '\0';
6810 new_hcolor = (SPEC_COLOR_S *)fs_get(sizeof(*new_hcolor));
6811 memset((void *)new_hcolor, 0, sizeof(*new_hcolor));
6812 new_hcolor->spec = spec;
6813 new_hcolor->fg = fg;
6814 new_hcolor->bg = bg;
6815 new_hcolor->val = val;
6817 else{
6818 if(spec)
6819 fs_give((void **)&spec);
6820 if(fg)
6821 fs_give((void **)&fg);
6822 if(bg)
6823 fs_give((void **)&bg);
6824 if(val)
6825 free_pattern(&val);
6829 return(new_hcolor);
6834 * Input is a list from config file.
6836 * Return value may be a list of SPEC_COLOR_S and must be freed by caller.
6838 SPEC_COLOR_S *
6839 spec_colors_from_varlist(char **varlist, int already_expanded)
6841 char **s, *t;
6842 SPEC_COLOR_S *new_hc = NULL;
6843 SPEC_COLOR_S *new_hcolor, **nexthc;
6845 nexthc = &new_hc;
6846 if(varlist){
6847 for(s = varlist; (t = *s) != NULL; s++){
6848 if(t[0]){
6849 new_hcolor = spec_color_from_var(t, already_expanded);
6850 if(new_hcolor){
6851 *nexthc = new_hcolor;
6852 nexthc = &new_hcolor->next;
6858 return(new_hc);
6863 * Returns allocated charstar suitable for config var for a single
6864 * SPEC_COLOR_S.
6866 char *
6867 var_from_spec_color(SPEC_COLOR_S *hc)
6869 char *ret_val = NULL;
6870 char *p, *spec = NULL, *fg = NULL, *bg = NULL, *val = NULL;
6871 size_t len;
6873 if(hc && hc->inherit)
6874 ret_val = cpystr(INHERIT);
6875 else if(hc){
6876 if(hc->spec)
6877 spec = add_viewerhdr_escapes(hc->spec);
6878 if(hc->fg)
6879 fg = add_viewerhdr_escapes(hc->fg);
6880 if(hc->bg)
6881 bg = add_viewerhdr_escapes(hc->bg);
6882 if(hc->val){
6883 p = pattern_to_string(hc->val);
6884 if(p){
6885 val = add_viewerhdr_escapes(p);
6886 fs_give((void **)&p);
6890 len = strlen("/HDR=/FG=/BG=") + strlen(spec ? spec : "") +
6891 strlen(fg ? fg : "") + strlen(bg ? bg : "") +
6892 strlen(val ? "/VAL=" : "") + strlen(val ? val : "");
6893 ret_val = (char *) fs_get(len + 1);
6894 snprintf(ret_val, len+1, "/HDR=%s/FG=%s/BG=%s%s%s",
6895 spec ? spec : "", fg ? fg : "", bg ? bg : "",
6896 val ? "/VAL=" : "", val ? val : "");
6898 if(spec)
6899 fs_give((void **)&spec);
6900 if(fg)
6901 fs_give((void **)&fg);
6902 if(bg)
6903 fs_give((void **)&bg);
6904 if(val)
6905 fs_give((void **)&val);
6908 return(ret_val);
6913 * Returns allocated charstar suitable for config var for a single
6914 * SPEC_COLOR_S.
6916 char **
6917 varlist_from_spec_colors(SPEC_COLOR_S *hcolors)
6919 SPEC_COLOR_S *hc;
6920 char **ret_val = NULL;
6921 int i;
6923 /* count how many */
6924 for(hc = hcolors, i = 0; hc; hc = hc->next, i++)
6927 ret_val = (char **)fs_get((i+1) * sizeof(*ret_val));
6928 memset((void *)ret_val, 0, (i+1) * sizeof(*ret_val));
6929 for(hc = hcolors, i = 0; hc; hc = hc->next, i++)
6930 ret_val[i] = var_from_spec_color(hc);
6932 return(ret_val);
6936 void
6937 update_posting_charset(struct pine *ps, int revert)
6939 #ifndef _WINDOWS
6940 if(F_ON(F_USE_SYSTEM_TRANS, ps)){
6941 if(!revert)
6942 q_status_message(SM_ORDER, 5, 5, _("This change has no effect because feature Use-System-Translation is on"));
6944 else{
6945 #endif /* ! _WINDOWS */
6946 if(ps->posting_charmap)
6947 fs_give((void **) &ps->posting_charmap);
6949 if(ps->VAR_POST_CHAR_SET){
6950 ps->posting_charmap = cpystr(ps->VAR_POST_CHAR_SET);
6951 if(!posting_charset_is_supported(ps->posting_charmap)){
6952 snprintf(tmp_20k_buf, SIZEOF_20KBUF,
6953 _("Posting-Character set \"%s\" is unsupported, using UTF-8"),
6954 ps->posting_charmap);
6955 q_status_message(SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
6956 fs_give((void **) &ps->posting_charmap);
6957 ps->posting_charmap = cpystr("UTF-8");
6960 else
6961 ps->posting_charmap = cpystr("UTF-8");
6962 #ifndef _WINDOWS
6964 #endif /* ! _WINDOWS */
6968 #define FIXED_COMMENT _("(fixed)")
6969 #define DEFAULT_COMMENT _("(default)")
6970 #define OVERRIDE_COMMENT _("(overridden)")
6973 feature_gets_an_x(struct pine *ps, struct variable *var, FEATURE_S *feature,
6974 char **comment, EditWhich ew)
6976 char **lval, **lvalexc, **lvalnorm;
6977 char *def = DEFAULT_COMMENT;
6978 int j, done = 0;
6979 int feature_fixed_on = 0, feature_fixed_off = 0;
6981 if(comment)
6982 *comment = NULL;
6984 lval = LVAL(var, ew);
6985 lvalexc = LVAL(var, ps->ew_for_except_vars);
6986 lvalnorm = LVAL(var, Main);
6988 /* feature value is administratively fixed */
6989 if((j = feature_in_list(var->fixed_val.l, feature->name)) != 0){
6990 if(j == 1)
6991 feature_fixed_on++;
6992 else if(j == -1)
6993 feature_fixed_off++;
6995 done++;
6996 if(comment)
6997 *comment = FIXED_COMMENT;
7001 * We have an exceptions config setting which overrides anything
7002 * we do here, in the normal config.
7004 if(!done &&
7005 ps->ew_for_except_vars != Main && ew == Main &&
7006 feature_in_list(lvalexc, feature->name)){
7007 done++;
7008 if(comment)
7009 *comment = OVERRIDE_COMMENT;
7013 * Feature is set On in default but not set here.
7015 if(!done &&
7016 !feature_in_list(lval, feature->name) &&
7017 ((feature_in_list(var->global_val.l, feature->name) == 1) ||
7018 ((ps->ew_for_except_vars != Main &&
7019 ew == ps->ew_for_except_vars &&
7020 feature_in_list(lvalnorm, feature->name) == 1)))){
7021 done = 17;
7022 if(comment)
7023 *comment = def;
7026 if(!done &&
7027 feature->defval &&
7028 !feature_in_list(lval, feature->name) &&
7029 !feature_in_list(var->global_val.l, feature->name) &&
7030 (ps->ew_for_except_vars == Main ||
7031 ew != ps->ew_for_except_vars ||
7032 !feature_in_list(lvalnorm, feature->name))){
7033 done = 17;
7034 if(comment)
7035 *comment = def;
7038 return(feature_fixed_on ||
7039 (!feature_fixed_off &&
7040 (done == 17 ||
7041 test_feature(lval, feature->name,
7042 test_old_growth_bits(ps, feature->id)))));
7047 longest_feature_comment(struct pine *ps, EditWhich ew)
7049 int lc = 0;
7051 lc = MAX(lc, utf8_width(FIXED_COMMENT));
7052 lc = MAX(lc, utf8_width(DEFAULT_COMMENT));
7053 if(ps->ew_for_except_vars != Main && ew == Main)
7054 lc = MAX(lc, utf8_width(OVERRIDE_COMMENT));
7056 return(lc);
7060 void
7061 toggle_feature(struct pine *ps, struct variable *var, FEATURE_S *f,
7062 int just_flip_value, EditWhich ew)
7064 char **vp, *p, **lval, ***alval;
7065 int og, on_before, was_set;
7066 char *err;
7067 long l;
7069 og = test_old_growth_bits(ps, f->id);
7072 * if this feature is in the fixed set, or old-growth is in the fixed
7073 * set and this feature is in the old-growth set, don't alter it...
7075 for(vp = var->fixed_val.l; vp && *vp; vp++){
7076 p = (struncmp(*vp, "no-", 3)) ? *vp : *vp + 3;
7077 if(!strucmp(p, f->name) || (og && !strucmp(p, "old-growth"))){
7078 q_status_message(SM_ORDER, 3, 3,
7079 /* TRANSLATORS: In the configuration screen, telling the user we
7080 can't change this option because the system administrator
7081 prohibits it. */
7082 _("Can't change value fixed by sys-admin."));
7083 return;
7087 on_before = F_ON(f->id, ps);
7089 lval = LVAL(var, ew);
7090 alval = ALVAL(var, ew);
7091 if(just_flip_value)
7092 was_set = test_feature(lval, f->name, og);
7093 else
7094 was_set = feature_gets_an_x(ps, var, f, NULL, ew);
7096 if(alval)
7097 set_feature(alval, f->name, !was_set);
7099 set_feature_list_current_val(var);
7100 process_feature_list(ps, var->current_val.l, 0, 0, 0);
7103 * Handle any features that need special attention here...
7105 if(on_before != F_ON(f->id, ps))
7106 switch(f->id){
7107 case F_QUOTE_ALL_FROMS :
7108 mail_parameters(NULL,SET_FROMWIDGET,F_ON(f->id,ps) ? VOIDT : NIL);
7109 break;
7111 case F_FAKE_NEW_IN_NEWS :
7112 if(IS_NEWS(ps->mail_stream))
7113 q_status_message(SM_ORDER | SM_DING, 3, 4,
7114 "news-approximates-new-status won't affect current newsgroup until next open");
7116 break;
7118 case F_COLOR_LINE_IMPORTANT :
7119 case F_DATES_TO_LOCAL :
7120 clear_index_cache(ps->mail_stream, 0);
7121 break;
7123 case F_DISABLE_INDEX_LOCALE_DATES :
7124 reset_index_format();
7125 clear_index_cache(ps->mail_stream, 0);
7126 break;
7128 case F_MARK_FOR_CC :
7129 clear_index_cache(ps->mail_stream, 0);
7130 if(THREADING() && sp_viewing_a_thread(ps->mail_stream))
7131 unview_thread(ps, ps->mail_stream, ps->msgmap);
7133 break;
7135 case F_HIDE_NNTP_PATH :
7136 mail_parameters(NULL, SET_NNTPHIDEPATH,
7137 F_ON(f->id, ps) ? VOIDT : NIL);
7138 break;
7140 case F_MAILDROPS_PRESERVE_STATE :
7141 mail_parameters(NULL, SET_SNARFPRESERVE,
7142 F_ON(f->id, ps) ? VOIDT : NIL);
7143 break;
7145 case F_DISABLE_SHARED_NAMESPACES :
7146 mail_parameters(NULL, SET_DISABLEAUTOSHAREDNS,
7147 F_ON(f->id, ps) ? VOIDT : NIL);
7148 break;
7150 case F_QUELL_LOCK_FAILURE_MSGS :
7151 mail_parameters(NULL, SET_LOCKEACCESERROR,
7152 F_ON(f->id, ps) ? VOIDT : NIL);
7153 break;
7155 case F_MULNEWSRC_HOSTNAMES_AS_TYPED :
7156 l = F_ON(f->id, ps) ? 0L : 1L;
7157 mail_parameters(NULL, SET_NEWSRCCANONHOST, (void *) l);
7158 break;
7160 case F_QUELL_INTERNAL_MSG :
7161 mail_parameters(NULL, SET_USERHASNOLIFE,
7162 F_ON(f->id, ps) ? VOIDT : NIL);
7163 break;
7165 case F_DISABLE_SETLOCALE_COLLATE :
7166 set_collation(F_OFF(F_DISABLE_SETLOCALE_COLLATE, ps), 1);
7167 break;
7169 #ifndef _WINDOWS
7170 case F_USE_SYSTEM_TRANS :
7171 err = NULL;
7172 reset_character_set_stuff(&err);
7173 if(err){
7174 q_status_message(SM_ORDER | SM_DING, 3, 4, err);
7175 fs_give((void **) &err);
7178 break;
7179 #endif /* ! _WINDOWS */
7181 case F_ENABLE_INCOMING_CHECKING :
7182 if(!on_before && F_OFF(F_ENABLE_INCOMING, ps))
7183 q_status_message(SM_ORDER, 0, 3, _("This option has no effect without Enable-Incoming-Folders"));
7185 clear_incoming_valid_bits();
7186 break;
7188 case F_INCOMING_CHECKING_TOTAL :
7189 case F_INCOMING_CHECKING_RECENT :
7190 if(!on_before && F_OFF(F_ENABLE_INCOMING_CHECKING, ps))
7191 q_status_message(SM_ORDER, 0, 3, _("This option has no effect without Enable-Incoming-Folders-Checking"));
7193 clear_incoming_valid_bits();
7194 break;
7196 case F_THREAD_SORTS_BY_ARRIVAL :
7197 clear_index_cache(ps->mail_stream, 0);
7198 refresh_sort(ps->mail_stream, sp_msgmap(ps->mail_stream), SRT_NON);
7199 break;
7201 #ifdef SMIME
7202 case F_DONT_DO_SMIME :
7203 smime_deinit();
7204 break;
7206 #ifdef APPLEKEYCHAIN
7207 case F_PUBLICCERTS_IN_KEYCHAIN :
7208 smime_deinit();
7209 break;
7210 #endif
7211 #endif
7213 default :
7214 break;
7220 * Returns 1 -- Feature is in the list and positive
7221 * 0 -- Feature is not in the list at all
7222 * -1 -- Feature is in the list and negative (no-)
7225 feature_in_list(char **l, char *f)
7227 char *p;
7228 int rv = 0, forced_off;
7230 for(; l && *l; l++){
7231 p = (forced_off = !struncmp(*l, "no-", 3)) ? *l + 3 : *l;
7232 if(!strucmp(p, f))
7233 rv = forced_off ? -1 : 1;
7236 return(rv);
7241 * test_feature - runs thru a feature list, and returns:
7242 * 1 if feature explicitly set and matches 'v'
7243 * 0 if feature not explicitly set *or* doesn't match 'v'
7246 test_feature(char **l, char *f, int g)
7248 char *p;
7249 int rv = 0, forced_off;
7251 for(; l && *l; l++){
7252 p = (forced_off = !struncmp(*l, "no-", 3)) ? *l + 3 : *l;
7253 if(!strucmp(p, f))
7254 rv = !forced_off;
7255 else if(g && !strucmp(p, "old-growth"))
7256 rv = !forced_off;
7259 return(rv);
7263 void
7264 set_feature(char ***l, char *f, int v)
7266 char **list = l ? *l : NULL, newval[256];
7267 int count = 0;
7269 snprintf(newval, sizeof(newval), "%s%s", v ? "" : "no-", f);
7270 for(; list && *list; list++, count++)
7271 if((**list == '\0') /* anything can replace an empty value */
7272 || !strucmp(((!struncmp(*list, "no-", 3)) ? *list + 3 : *list), f)){
7273 fs_give((void **)list); /* replace with new value */
7274 *list = cpystr(newval);
7275 return;
7279 * if we got here, we didn't find it in the list, so grow the list
7280 * and add it..
7282 if(!*l)
7283 *l = (char **)fs_get((count + 2) * sizeof(char *));
7284 else
7285 fs_resize((void **)l, (count + 2) * sizeof(char *));
7287 (*l)[count] = cpystr(newval);
7288 (*l)[count + 1] = NULL;
7293 reset_character_set_stuff(char **err)
7295 int use_system = 0;
7296 char buf[1000];
7298 if(err)
7299 *err = NULL;
7301 if(ps_global->display_charmap)
7302 fs_give((void **) &ps_global->display_charmap);
7304 if(ps_global->keyboard_charmap)
7305 fs_give((void **) &ps_global->keyboard_charmap);
7307 if(ps_global->posting_charmap)
7308 fs_give((void **) &ps_global->posting_charmap);
7310 #ifdef _WINDOWS
7311 ps_global->display_charmap = cpystr("UTF-8");
7312 #else /* UNIX */
7313 if(ps_global->VAR_CHAR_SET)
7314 ps_global->display_charmap = cpystr(ps_global->VAR_CHAR_SET);
7315 else{
7316 #if HAVE_LANGINFO_H && defined(CODESET)
7317 ps_global->display_charmap = cpystr(nl_langinfo_codeset_wrapper());
7318 #else
7319 ps_global->display_charmap = cpystr("UTF-8");
7320 #endif
7322 #endif /* UNIX */
7324 if(!ps_global->display_charmap)
7325 ps_global->display_charmap = cpystr("US-ASCII");
7327 #ifdef _WINDOWS
7328 ps_global->keyboard_charmap = cpystr("UTF-8");
7329 #else /* UNIX */
7330 if(ps_global->VAR_KEY_CHAR_SET)
7331 ps_global->keyboard_charmap = cpystr(ps_global->VAR_KEY_CHAR_SET);
7332 else
7333 ps_global->keyboard_charmap = cpystr(ps_global->display_charmap);
7335 if(!ps_global->keyboard_charmap)
7336 ps_global->keyboard_charmap = cpystr("US-ASCII");
7338 if(F_ON(F_USE_SYSTEM_TRANS, ps_global)){
7339 #if PREREQ_FOR_SYS_TRANSLATION
7340 use_system++;
7341 /* This modifies its arguments */
7342 if(setup_for_input_output(use_system, &ps_global->display_charmap,
7343 &ps_global->keyboard_charmap,
7344 &ps_global->input_cs, (err && *err) ? NULL : err) == -1)
7345 return -1;
7346 #endif
7348 #endif /* UNIX */
7350 if(!use_system){
7351 if(setup_for_input_output(use_system, &ps_global->display_charmap,
7352 &ps_global->keyboard_charmap,
7353 &ps_global->input_cs, (err && *err) ? NULL : err) == -1)
7354 return -1;
7357 if(!use_system && ps_global->VAR_POST_CHAR_SET){
7358 ps_global->posting_charmap = cpystr(ps_global->VAR_POST_CHAR_SET);
7359 if(!posting_charset_is_supported(ps_global->posting_charmap)){
7360 if(err && !*err){
7361 snprintf(buf, sizeof(buf),
7362 _("Posting-Character-Set \"%s\" is unsupported, using UTF-8"),
7363 ps_global->posting_charmap);
7364 *err = cpystr(buf);
7367 fs_give((void **) &ps_global->posting_charmap);
7368 ps_global->posting_charmap = cpystr("UTF-8");
7371 else{
7372 if(use_system && ps_global->VAR_POST_CHAR_SET
7373 && strucmp(ps_global->VAR_POST_CHAR_SET, "UTF-8"))
7374 if(err && !*err)
7375 *err = cpystr(_("Posting-Character-Set is ignored with Use-System-Translation turned on"));
7377 ps_global->posting_charmap = cpystr("UTF-8");
7380 set_locale_charmap(ps_global->keyboard_charmap);
7382 return(0);
7387 * Given a single printer string from the config file, returns pointers
7388 * to alloc'd strings containing the printer nickname, the command,
7389 * the init string, the trailer string, everything but the nickname string,
7390 * and everything but the command string. All_but_cmd includes the trailing
7391 * space at the end (the one before the command) but all_but_nick does not
7392 * include the leading space (the one before the [).
7393 * If you pass in a pointer it is guaranteed to come back pointing to an
7394 * allocated string, even if it is just an empty string. It is ok to pass
7395 * NULL for any of the six return strings.
7397 void
7398 parse_printer(char *input, char **nick, char **cmd, char **init, char **trailer,
7399 char **all_but_nick, char **all_but_cmd)
7401 char *p, *q, *start, *saved_options = NULL;
7402 int tmpsave, cnt;
7404 if(!input)
7405 input = "";
7407 if(nick || all_but_nick){
7408 if((p = srchstr(input, " [")) != NULL){
7409 if(all_but_nick)
7410 *all_but_nick = cpystr(p+1);
7412 if(nick){
7413 while(p-1 > input && isspace((unsigned char)*(p-1)))
7414 p--;
7416 tmpsave = *p;
7417 *p = '\0';
7418 *nick = cpystr(input);
7419 *p = tmpsave;
7422 else{
7423 if(nick)
7424 *nick = cpystr("");
7426 if(all_but_nick)
7427 *all_but_nick = cpystr(input);
7431 if((p = srchstr(input, "] ")) != NULL){
7433 ++p;
7434 }while(isspace((unsigned char)*p));
7436 tmpsave = *p;
7437 *p = '\0';
7438 saved_options = cpystr(input);
7439 *p = tmpsave;
7441 else
7442 p = input;
7444 if(cmd)
7445 *cmd = cpystr(p);
7447 if(init){
7448 if(saved_options && (p = srchstr(saved_options, "INIT="))){
7449 start = p + strlen("INIT=");
7450 for(cnt=0, p = start; *p && *(p+1) && isxpair(p); p += 2)
7451 cnt++;
7453 q = *init = (char *)fs_get((cnt + 1) * sizeof(char));
7454 for(p = start; *p && *(p+1) && isxpair(p); p += 2)
7455 *q++ = read_hex(p);
7457 *q = '\0';
7459 else
7460 *init = cpystr("");
7463 if(trailer){
7464 if(saved_options && (p = srchstr(saved_options, "TRAILER="))){
7465 start = p + strlen("TRAILER=");
7466 for(cnt=0, p = start; *p && *(p+1) && isxpair(p); p += 2)
7467 cnt++;
7469 q = *trailer = (char *)fs_get((cnt + 1) * sizeof(char));
7470 for(p = start; *p && *(p+1) && isxpair(p); p += 2)
7471 *q++ = read_hex(p);
7473 *q = '\0';
7475 else
7476 *trailer = cpystr("");
7479 if(all_but_cmd){
7480 if(saved_options)
7481 *all_but_cmd = saved_options;
7482 else
7483 *all_but_cmd = cpystr("");
7485 else if(saved_options)
7486 fs_give((void **)&saved_options);
7491 copy_pinerc(char *local, char *remote, char **err_msg)
7493 return(copy_localfile_to_remotefldr(RemImap, local, remote,
7494 REMOTE_PINERC_SUBTYPE,
7495 err_msg));
7500 copy_abook(char *local, char *remote, char **err_msg)
7502 return(copy_localfile_to_remotefldr(RemImap, local, remote,
7503 REMOTE_ABOOK_SUBTYPE,
7504 err_msg));
7509 * Copy local file to remote folder.
7511 * Args remotetype -- type of remote folder
7512 * local -- name of local file
7513 * remote -- name of remote folder
7514 * subtype --
7516 * Returns 0 on success.
7519 copy_localfile_to_remotefldr(RemType remotetype, char *local, char *remote,
7520 char *subtype, char **err_msg)
7522 int retfail = -1;
7523 unsigned flags;
7524 REMDATA_S *rd;
7526 dprint((9, "copy_localfile_to_remotefldr(%s,%s)\n",
7527 local ? local : "<null>",
7528 remote ? remote : "<null>"));
7530 *err_msg = (char *)fs_get(MAXPATH * sizeof(char));
7532 if(!local || !*local){
7533 snprintf(*err_msg, MAXPATH, _("No local file specified"));
7534 return(retfail);
7537 if(!remote || !*remote){
7538 snprintf(*err_msg, MAXPATH, _("No remote folder specified"));
7539 return(retfail);
7542 if(!IS_REMOTE(remote)){
7543 snprintf(*err_msg, MAXPATH, _("Remote folder name \"%s\" %s"), remote,
7544 (*remote != '{') ? _("must begin with \"{\"") : _("not valid"));
7545 return(retfail);
7548 if(IS_REMOTE(local)){
7549 snprintf(*err_msg, MAXPATH, _("First argument \"%s\" must be a local filename"),
7550 local);
7551 return(retfail);
7554 if(can_access(local, ACCESS_EXISTS) != 0){
7555 snprintf(*err_msg, MAXPATH, _("Local file \"%s\" does not exist"), local);
7556 return(retfail);
7559 if(can_access(local, READ_ACCESS) != 0){
7560 snprintf(*err_msg, MAXPATH, _("Can't read local file \"%s\": %s"),
7561 local, error_description(errno));
7562 return(retfail);
7566 * Check if remote folder exists and create it if it doesn't.
7568 flags = 0;
7569 rd = rd_create_remote(remotetype, remote, subtype,
7570 &flags, _("Error: "), _("Can't copy to remote folder."));
7572 if(!rd || rd->access == NoExists){
7573 snprintf(*err_msg, MAXPATH, _("Can't create \"%s\""), remote);
7574 if(rd)
7575 rd_free_remdata(&rd);
7577 return(retfail);
7580 if(rd->access == MaybeRorW)
7581 rd->access = ReadWrite;
7583 rd->flags |= (NO_META_UPDATE | DO_REMTRIM);
7584 rd->lf = cpystr(local);
7586 rd_open_remote(rd);
7587 if(!rd_stream_exists(rd)){
7588 snprintf(*err_msg, MAXPATH, _("Can't open remote folder \"%s\""), rd->rn);
7589 rd_free_remdata(&rd);
7590 return(retfail);
7593 if(rd_remote_is_readonly(rd)){
7594 snprintf(*err_msg, MAXPATH, _("Remote folder \"%s\" is readonly"), rd->rn);
7595 rd_free_remdata(&rd);
7596 return(retfail);
7599 switch(rd->type){
7600 case RemImap:
7602 * Empty folder, add a header msg.
7604 if(rd->t.i.stream->nmsgs == 0){
7605 if(rd_init_remote(rd, 1) != 0){
7606 snprintf(*err_msg, MAXPATH,
7607 _("Failed initializing remote folder \"%s\", check debug file"),
7608 rd->rn);
7609 rd_free_remdata(&rd);
7610 return(retfail);
7614 fs_give((void **)err_msg);
7615 *err_msg = NULL;
7616 if(rd_chk_for_hdr_msg(&(rd->t.i.stream), rd, err_msg)){
7617 rd_free_remdata(&rd);
7618 return(retfail);
7621 break;
7623 default:
7624 break;
7627 if(rd_update_remote(rd, NULL) != 0){
7628 snprintf(*err_msg, MAXPATH, _("Error copying to remote folder \"%s\""), rd->rn);
7629 rd_free_remdata(&rd);
7630 return(retfail);
7633 rd_update_metadata(rd, NULL);
7634 rd_close_remdata(&rd);
7636 fs_give((void **)err_msg);
7637 return(0);
7641 /*----------------------------------------------------------------------
7642 Panic pine - call on detected programmatic errors to exit pine, with arg
7644 Input: message -- printf styule string for panic message (see above)
7645 arg -- argument for printf string
7647 Result: The various tty modes are restored
7648 If debugging is active a core dump will be generated
7649 Exits Pine
7650 ----*/
7651 void
7652 panic1(char *message, char *arg)
7654 #define SIZEOFBUF 1001
7655 char buf1[SIZEOFBUF], buf2[SIZEOFBUF];
7657 snprintf(buf1, sizeof(buf1), "%.*s", (int) MAX(SIZEOFBUF - 1 - strlen(message), 0), arg);
7658 snprintf(buf2, sizeof(buf2), message, buf1);
7659 alpine_panic(buf2);
7666 HelpType
7667 config_help(int var, int feature)
7669 switch(var){
7670 case V_FEATURE_LIST :
7671 return(feature_list_help(feature));
7672 break;
7674 case V_PERSONAL_NAME :
7675 return(h_config_pers_name);
7676 case V_USER_ID :
7677 return(h_config_user_id);
7678 case V_USER_DOMAIN :
7679 return(h_config_user_dom);
7680 case V_SMTP_SERVER :
7681 return(h_config_smtp_server);
7682 case V_NNTP_SERVER :
7683 return(h_config_nntp_server);
7684 case V_INBOX_PATH :
7685 return(h_config_inbox_path);
7686 case V_PRUNED_FOLDERS :
7687 return(h_config_pruned_folders);
7688 case V_DEFAULT_FCC :
7689 return(h_config_default_fcc);
7690 case V_DEFAULT_SAVE_FOLDER :
7691 return(h_config_def_save_folder);
7692 case V_POSTPONED_FOLDER :
7693 return(h_config_postponed_folder);
7694 case V_READ_MESSAGE_FOLDER :
7695 return(h_config_read_message_folder);
7696 case V_FORM_FOLDER :
7697 return(h_config_form_folder);
7698 case V_ARCHIVED_FOLDERS :
7699 return(h_config_archived_folders);
7700 case V_SIGNATURE_FILE :
7701 return(h_config_signature_file);
7702 case V_LITERAL_SIG :
7703 return(h_config_literal_sig);
7704 case V_INIT_CMD_LIST :
7705 return(h_config_init_cmd_list);
7706 case V_COMP_HDRS :
7707 return(h_config_comp_hdrs);
7708 case V_CUSTOM_HDRS :
7709 return(h_config_custom_hdrs);
7710 case V_VIEW_HEADERS :
7711 return(h_config_viewer_headers);
7712 case V_VIEW_MARGIN_LEFT :
7713 return(h_config_viewer_margin_left);
7714 case V_VIEW_MARGIN_RIGHT :
7715 return(h_config_viewer_margin_right);
7716 case V_QUOTE_SUPPRESSION :
7717 return(h_config_quote_suppression);
7718 case V_SAVED_MSG_NAME_RULE :
7719 return(h_config_saved_msg_name_rule);
7720 case V_FCC_RULE :
7721 return(h_config_fcc_rule);
7722 case V_SORT_KEY :
7723 return(h_config_sort_key);
7724 case V_AB_SORT_RULE :
7725 return(h_config_ab_sort_rule);
7726 case V_FLD_SORT_RULE :
7727 return(h_config_fld_sort_rule);
7728 case V_POST_CHAR_SET :
7729 return(h_config_post_char_set);
7730 case V_UNK_CHAR_SET :
7731 return(h_config_unk_char_set);
7732 #ifndef _WINDOWS
7733 case V_KEY_CHAR_SET :
7734 return(h_config_key_char_set);
7735 case V_CHAR_SET :
7736 return(h_config_char_set);
7737 #endif /* ! _WINDOWS */
7738 case V_EDITOR :
7739 return(h_config_editor);
7740 case V_SPELLER :
7741 return(h_config_speller);
7742 #ifdef _WINDOWS
7743 case V_DICTIONARY :
7744 return(h_config_aspell_dictionary);
7745 #endif /* _WINDOWS */
7746 case V_DISPLAY_FILTERS :
7747 return(h_config_display_filters);
7748 case V_SEND_FILTER :
7749 return(h_config_sending_filter);
7750 case V_ALT_ADDRS :
7751 return(h_config_alt_addresses);
7752 case V_KEYWORDS :
7753 return(h_config_keywords);
7754 case V_KW_BRACES :
7755 return(h_config_kw_braces);
7756 case V_OPENING_SEP :
7757 return(h_config_opening_sep);
7758 case V_KW_COLORS :
7759 return(h_config_kw_color);
7760 case V_ABOOK_FORMATS :
7761 return(h_config_abook_formats);
7762 case V_INDEX_FORMAT :
7763 return(h_config_index_format);
7764 case V_INCCHECKTIMEO :
7765 return(h_config_incoming_timeo);
7766 case V_INCCHECKINTERVAL :
7767 return(h_config_incoming_interv);
7768 case V_INC2NDCHECKINTERVAL :
7769 return(h_config_incoming_second_interv);
7770 case V_INCCHECKLIST :
7771 return(h_config_incoming_list);
7772 case V_SLEEP :
7773 return(h_config_psleep);
7774 case V_OVERLAP :
7775 return(h_config_viewer_overlap);
7776 case V_MAXREMSTREAM :
7777 return(h_config_maxremstream);
7778 case V_PERMLOCKED :
7779 return(h_config_permlocked);
7780 case V_MARGIN :
7781 return(h_config_scroll_margin);
7782 case V_DEADLETS :
7783 return(h_config_deadlets);
7784 case V_FILLCOL :
7785 return(h_config_composer_wrap_column);
7786 case V_TCPOPENTIMEO :
7787 return(h_config_tcp_open_timeo);
7788 case V_TCPREADWARNTIMEO :
7789 return(h_config_tcp_readwarn_timeo);
7790 case V_TCPWRITEWARNTIMEO :
7791 return(h_config_tcp_writewarn_timeo);
7792 case V_TCPQUERYTIMEO :
7793 return(h_config_tcp_query_timeo);
7794 case V_RSHOPENTIMEO :
7795 return(h_config_rsh_open_timeo);
7796 case V_SSHOPENTIMEO :
7797 return(h_config_ssh_open_timeo);
7798 case V_USERINPUTTIMEO :
7799 return(h_config_user_input_timeo);
7800 case V_REMOTE_ABOOK_VALIDITY :
7801 return(h_config_remote_abook_validity);
7802 case V_REMOTE_ABOOK_HISTORY :
7803 return(h_config_remote_abook_history);
7804 case V_INCOMING_FOLDERS :
7805 return(h_config_incoming_folders);
7806 case V_FOLDER_SPEC :
7807 return(h_config_folder_spec);
7808 case V_NEWS_SPEC :
7809 return(h_config_news_spec);
7810 case V_ADDRESSBOOK :
7811 return(h_config_address_book);
7812 case V_GLOB_ADDRBOOK :
7813 return(h_config_glob_addrbook);
7814 case V_LAST_VERS_USED :
7815 return(h_config_last_vers);
7816 case V_SENDMAIL_PATH :
7817 return(h_config_sendmail_path);
7818 case V_OPER_DIR :
7819 return(h_config_oper_dir);
7820 case V_RSHPATH :
7821 return(h_config_rshpath);
7822 case V_RSHCMD :
7823 return(h_config_rshcmd);
7824 case V_SSHPATH :
7825 return(h_config_sshpath);
7826 case V_SSHCMD :
7827 return(h_config_sshcmd);
7828 case V_NEW_VER_QUELL :
7829 return(h_config_new_ver_quell);
7830 case V_DISABLE_DRIVERS :
7831 return(h_config_disable_drivers);
7832 case V_DISABLE_AUTHS :
7833 return(h_config_disable_auths);
7834 case V_ENCRYPTION_RANGE :
7835 return(h_config_encryption_range);
7836 case V_REMOTE_ABOOK_METADATA :
7837 return(h_config_abook_metafile);
7838 case V_REPLY_STRING :
7839 return(h_config_reply_indent_string);
7840 case V_WORDSEPS :
7841 return(h_config_wordseps);
7842 case V_QUOTE_REPLACE_STRING :
7843 return(h_config_quote_replace_string);
7844 case V_REPLY_INTRO :
7845 return(h_config_reply_intro);
7846 case V_EMPTY_HDR_MSG :
7847 return(h_config_empty_hdr_msg);
7848 case V_STATUS_MSG_DELAY :
7849 return(h_config_status_msg_delay);
7850 case V_ACTIVE_MSG_INTERVAL :
7851 return(h_config_active_msg_interval);
7852 case V_MAILCHECK :
7853 return(h_config_mailcheck);
7854 case V_MAILCHECKNONCURR :
7855 return(h_config_mailchecknoncurr);
7856 case V_MAILDROPCHECK :
7857 return(h_config_maildropcheck);
7858 case V_NNTPRANGE :
7859 return(h_config_nntprange);
7860 case V_NEWS_ACTIVE_PATH :
7861 return(h_config_news_active);
7862 case V_NEWS_SPOOL_DIR :
7863 return(h_config_news_spool);
7864 case V_IMAGE_VIEWER :
7865 return(h_config_image_viewer);
7866 case V_USE_ONLY_DOMAIN_NAME :
7867 return(h_config_domain_name);
7868 case V_LAST_TIME_PRUNE_QUESTION :
7869 return(h_config_prune_date);
7870 case V_UPLOAD_CMD:
7871 return(h_config_upload_cmd);
7872 case V_UPLOAD_CMD_PREFIX:
7873 return(h_config_upload_prefix);
7874 case V_DOWNLOAD_CMD:
7875 return(h_config_download_cmd);
7876 case V_DOWNLOAD_CMD_PREFIX:
7877 return(h_config_download_prefix);
7878 case V_GOTO_DEFAULT_RULE:
7879 return(h_config_goto_default);
7880 case V_INCOMING_STARTUP:
7881 return(h_config_inc_startup);
7882 case V_PRUNING_RULE:
7883 return(h_config_pruning_rule);
7884 case V_REOPEN_RULE:
7885 return(h_config_reopen_rule);
7886 case V_THREAD_DISP_STYLE:
7887 return(h_config_thread_disp_style);
7888 case V_THREAD_INDEX_STYLE:
7889 return(h_config_thread_index_style);
7890 case V_THREAD_MORE_CHAR:
7891 return(h_config_thread_indicator_char);
7892 case V_THREAD_EXP_CHAR:
7893 return(h_config_thread_exp_char);
7894 case V_THREAD_LASTREPLY_CHAR:
7895 return(h_config_thread_lastreply_char);
7896 case V_MAILCAP_PATH :
7897 return(h_config_mailcap_path);
7898 case V_MIMETYPE_PATH :
7899 return(h_config_mimetype_path);
7900 #if !defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)
7901 case V_FIFOPATH :
7902 return(h_config_fifopath);
7903 #endif
7904 case V_NMW_WIDTH :
7905 return(h_config_newmailwidth);
7906 case V_NEWSRC_PATH :
7907 return(h_config_newsrc_path);
7908 case V_BROWSER :
7909 return(h_config_browser);
7910 case V_HISTORY :
7911 return(h_config_history);
7912 #if defined(DOS) || defined(OS2)
7913 case V_FILE_DIR :
7914 return(h_config_file_dir);
7915 #endif
7916 case V_NORM_FORE_COLOR :
7917 case V_NORM_BACK_COLOR :
7918 return(h_config_normal_color);
7919 case V_REV_FORE_COLOR :
7920 case V_REV_BACK_COLOR :
7921 return(h_config_reverse_color);
7922 case V_TITLE_FORE_COLOR :
7923 case V_TITLE_BACK_COLOR :
7924 return(h_config_title_color);
7925 case V_TITLECLOSED_FORE_COLOR :
7926 case V_TITLECLOSED_BACK_COLOR :
7927 return(h_config_titleclosed_color);
7928 case V_FOLDER_FORE_COLOR:
7929 return(h_config_folder_color);
7930 case V_DIRECTORY_FORE_COLOR:
7931 return(h_config_directory_color);
7932 case V_FOLDER_LIST_FORE_COLOR:
7933 return(h_config_folder_list_color);
7934 case V_STATUS_FORE_COLOR :
7935 case V_STATUS_BACK_COLOR :
7936 return(h_config_status_color);
7937 case V_SLCTBL_FORE_COLOR :
7938 case V_SLCTBL_BACK_COLOR :
7939 return(h_config_slctbl_color);
7940 case V_QUOTE1_FORE_COLOR :
7941 case V_QUOTE2_FORE_COLOR :
7942 case V_QUOTE3_FORE_COLOR :
7943 case V_QUOTE1_BACK_COLOR :
7944 case V_QUOTE2_BACK_COLOR :
7945 case V_QUOTE3_BACK_COLOR :
7946 return(h_config_quote_color);
7947 case V_INCUNSEEN_FORE_COLOR :
7948 case V_INCUNSEEN_BACK_COLOR :
7949 return(h_config_incunseen_color);
7950 case V_SIGNATURE_FORE_COLOR :
7951 case V_SIGNATURE_BACK_COLOR :
7952 return(h_config_signature_color);
7953 case V_PROMPT_FORE_COLOR :
7954 case V_PROMPT_BACK_COLOR :
7955 return(h_config_prompt_color);
7956 case V_HEADER_GENERAL_FORE_COLOR :
7957 case V_HEADER_GENERAL_BACK_COLOR :
7958 return(h_config_header_general_color);
7959 case V_IND_PLUS_FORE_COLOR :
7960 case V_IND_IMP_FORE_COLOR :
7961 case V_IND_DEL_FORE_COLOR :
7962 case V_IND_ANS_FORE_COLOR :
7963 case V_IND_NEW_FORE_COLOR :
7964 case V_IND_UNS_FORE_COLOR :
7965 case V_IND_REC_FORE_COLOR :
7966 case V_IND_FWD_FORE_COLOR :
7967 case V_IND_PLUS_BACK_COLOR :
7968 case V_IND_IMP_BACK_COLOR :
7969 case V_IND_DEL_BACK_COLOR :
7970 case V_IND_ANS_BACK_COLOR :
7971 case V_IND_NEW_BACK_COLOR :
7972 case V_IND_UNS_BACK_COLOR :
7973 case V_IND_REC_BACK_COLOR :
7974 case V_IND_FWD_BACK_COLOR :
7975 return(h_config_index_color);
7976 case V_IND_OP_FORE_COLOR :
7977 case V_IND_OP_BACK_COLOR :
7978 return(h_config_index_opening_color);
7979 case V_IND_SUBJ_FORE_COLOR :
7980 case V_IND_SUBJ_BACK_COLOR :
7981 return(h_config_index_subject_color);
7982 case V_IND_FROM_FORE_COLOR :
7983 case V_IND_FROM_BACK_COLOR :
7984 return(h_config_index_from_color);
7985 case V_IND_HIPRI_FORE_COLOR :
7986 case V_IND_HIPRI_BACK_COLOR :
7987 case V_IND_LOPRI_FORE_COLOR :
7988 case V_IND_LOPRI_BACK_COLOR :
7989 return(h_config_index_pri_color);
7990 case V_IND_ARR_FORE_COLOR :
7991 case V_IND_ARR_BACK_COLOR :
7992 return(h_config_index_arrow_color);
7993 case V_KEYLABEL_FORE_COLOR :
7994 case V_KEYLABEL_BACK_COLOR :
7995 return(h_config_keylabel_color);
7996 case V_KEYNAME_FORE_COLOR :
7997 case V_KEYNAME_BACK_COLOR :
7998 return(h_config_keyname_color);
7999 case V_METAMSG_FORE_COLOR :
8000 case V_METAMSG_BACK_COLOR :
8001 return(h_config_metamsg_color);
8002 case V_VIEW_HDR_COLORS :
8003 return(h_config_customhdr_color);
8004 case V_INDEX_TOKEN_COLORS :
8005 return(h_config_indextoken_color);
8006 case V_PRINTER :
8007 return(h_config_printer);
8008 case V_PERSONAL_PRINT_CATEGORY :
8009 return(h_config_print_cat);
8010 case V_PERSONAL_PRINT_COMMAND :
8011 return(h_config_print_command);
8012 case V_PAT_ROLES :
8013 return(h_config_pat_roles);
8014 case V_PAT_FILTS :
8015 return(h_config_pat_filts);
8016 case V_PAT_SCORES :
8017 return(h_config_pat_scores);
8018 case V_PAT_INCOLS :
8019 return(h_config_pat_incols);
8020 case V_PAT_OTHER :
8021 return(h_config_pat_other);
8022 case V_PAT_SRCH :
8023 return(h_config_pat_srch);
8024 case V_INDEX_COLOR_STYLE :
8025 return(h_config_index_color_style);
8026 case V_TITLEBAR_COLOR_STYLE :
8027 return(h_config_titlebar_color_style);
8028 #ifdef _WINDOWS
8029 case V_FONT_NAME :
8030 return(h_config_font_name);
8031 case V_FONT_SIZE :
8032 return(h_config_font_size);
8033 case V_FONT_STYLE :
8034 return(h_config_font_style);
8035 case V_FONT_CHAR_SET :
8036 return(h_config_font_char_set);
8037 case V_PRINT_FONT_NAME :
8038 return(h_config_print_font_name);
8039 case V_PRINT_FONT_SIZE :
8040 return(h_config_print_font_size);
8041 case V_PRINT_FONT_STYLE :
8042 return(h_config_print_font_style);
8043 case V_PRINT_FONT_CHAR_SET :
8044 return(h_config_print_font_char_set);
8045 case V_WINDOW_POSITION :
8046 return(h_config_window_position);
8047 case V_CURSOR_STYLE :
8048 return(h_config_cursor_style);
8049 #else
8050 case V_COLOR_STYLE :
8051 return(h_config_color_style);
8052 #endif
8053 #ifdef ENABLE_LDAP
8054 case V_LDAP_SERVERS :
8055 return(h_config_ldap_servers);
8056 #endif
8057 #ifdef SMIME
8058 case V_PUBLICCERT_DIR :
8059 return(h_config_smime_pubcertdir);
8060 case V_PUBLICCERT_CONTAINER :
8061 return(h_config_smime_pubcertcon);
8062 case V_PRIVATEKEY_DIR :
8063 return(h_config_smime_privkeydir);
8064 case V_PRIVATEKEY_CONTAINER :
8065 return(h_config_smime_privkeycon);
8066 case V_CACERT_DIR :
8067 return(h_config_smime_cacertdir);
8068 case V_CACERT_CONTAINER :
8069 return(h_config_smime_cacertcon);
8070 #endif
8071 case V_RSS_NEWS :
8072 return(h_config_rss_news);
8073 case V_RSS_WEATHER :
8074 return(h_config_rss_weather);
8075 case V_WP_INDEXHEIGHT :
8076 return(h_config_wp_indexheight);
8077 case V_WP_INDEXLINES :
8078 return(h_config_wp_indexlines);
8079 case V_WP_AGGSTATE :
8080 return(h_config_wp_aggstate);
8081 case V_WP_STATE :
8082 return(h_config_wp_state);
8083 case V_WP_COLUMNS :
8084 return(h_config_wp_columns);
8085 default :
8086 return(NO_HELP);
8092 * We don't want the user to be able to edit their pinerc and set
8093 * printer to whatever they want if personal-print-command is fixed.
8094 * So make sure printer is set to something legitimate. If it isn't,
8095 * set it to something standard and return non-zero.
8098 printer_value_check_and_adjust(void)
8100 char **tt;
8101 char aname[100], wname[100];
8102 int ok = 0;
8103 struct variable *vars = ps_global->vars;
8105 if(vars[V_PERSONAL_PRINT_COMMAND].is_fixed && !vars[V_PRINTER].is_fixed){
8106 strncpy(aname, ANSI_PRINTER, sizeof(aname));
8107 aname[sizeof(aname)-1] = '\0';
8108 strncat(aname, "-no-formfeed", sizeof(aname)-strlen(aname)-1);
8109 strncpy(wname, WYSE_PRINTER, sizeof(wname));
8110 wname[sizeof(wname)-1] = '\0';
8111 strncat(wname, "-no-formfeed", sizeof(wname)-strlen(wname)-1);
8112 if(strucmp(VAR_PRINTER, ANSI_PRINTER) == 0
8113 || strucmp(VAR_PRINTER, aname) == 0
8114 || strucmp(VAR_PRINTER, WYSE_PRINTER) == 0
8115 || strucmp(VAR_PRINTER, wname) == 0)
8116 ok++;
8117 else if(VAR_STANDARD_PRINTER && VAR_STANDARD_PRINTER[0]){
8118 for(tt = VAR_STANDARD_PRINTER; *tt; tt++)
8119 if(strucmp(VAR_PRINTER, *tt) == 0)
8120 break;
8122 if(*tt)
8123 ok++;
8126 if(!ok){
8127 char *val;
8128 struct variable *v;
8130 if(VAR_STANDARD_PRINTER && VAR_STANDARD_PRINTER[0])
8131 val = VAR_STANDARD_PRINTER[0];
8132 else
8133 val = ANSI_PRINTER;
8135 v = &vars[V_PRINTER];
8136 if(v->main_user_val.p)
8137 fs_give((void **)&v->main_user_val.p);
8138 if(v->post_user_val.p)
8139 fs_give((void **)&v->post_user_val.p);
8140 if(v->current_val.p)
8141 fs_give((void **)&v->current_val.p);
8143 v->main_user_val.p = cpystr(val);
8144 v->current_val.p = cpystr(val);
8148 return(!ok);
8152 char **
8153 get_supported_options(void)
8155 char **config;
8156 DRIVER *d;
8157 AUTHENTICATOR *a;
8158 char *title = _("Supported features in this Alpine");
8159 char sbuf[MAX_SCREEN_COLS+1], tmp[128];
8160 int cnt, alcnt, len, cols, disabled, any_disabled = 0, i;
8163 * Line count:
8164 * Title + blank = 2
8165 * SSL Title + SSL lines + blank = 5
8166 * Auth title + blank = 2
8167 * Driver title + blank = 2
8168 * LDAP title + LDAP line = 2
8169 * Disabled explanation + blank line = 4
8170 * end = 1
8172 cnt = 18;
8173 for(a = mail_lookup_auth(1); a; a = a->next)
8174 cnt++;
8175 for(d = (DRIVER *)mail_parameters(NIL, GET_DRIVERS, NIL);
8176 d; d = d->next)
8177 cnt++;
8179 alcnt = cnt;
8180 config = (char **) fs_get(alcnt * sizeof(char *));
8181 memset(config, 0, alcnt * sizeof(char *));
8183 cols = ps_global->ttyo ? ps_global->ttyo->screen_cols : 0;
8184 len = utf8_width(title);
8185 snprintf(sbuf, sizeof(sbuf), "%*s%s", cols > len ? (cols-len)/2 : 0, "", title);
8187 cnt = 0;
8188 if(cnt < alcnt)
8189 config[cnt] = cpystr(sbuf);
8191 if(++cnt < alcnt)
8192 config[cnt] = cpystr("");
8194 if(++cnt < alcnt)
8195 /* TRANSLATORS: headings */
8196 config[cnt] = cpystr(_("Encryption:"));
8198 if(++cnt < alcnt && mail_parameters(NIL, GET_SSLDRIVER, NIL)){
8199 config[cnt] = cpystr(_(" TLS and SSL"));
8200 tmp[0] = tmp[1] = ' ';
8201 tmp[2] = '\0';
8202 strcat(tmp, "TLSv1, ");
8203 strcat(tmp, "TLSv1.1, ");
8204 strcat(tmp, "TLSv1.2, ");
8205 #ifdef TLS1_3_VERSION
8206 strcat(tmp, "TLSv1.3, ");
8207 #endif /* TLS1_3_VERSION */
8208 strcat(tmp, "DTLSv1, ");
8209 strcat(tmp, "DTLSv1.2, ");
8210 tmp[strlen(tmp)-2] = '.';
8211 tmp[strlen(tmp)-1] = '\0';
8213 else
8214 config[cnt] = cpystr(_(" None (no TLS or SSL)"));
8216 if(++cnt < alcnt)
8217 config[cnt] = cpystr(tmp);
8218 #ifdef SMIME
8219 if(++cnt < alcnt)
8220 config[cnt] = cpystr(" S/MIME");
8221 #endif
8223 if(++cnt < alcnt)
8224 config[cnt] = cpystr("");
8226 if(++cnt < alcnt)
8227 config[cnt] = cpystr(_("Authenticators:"));
8229 for(a = mail_lookup_auth(1); a; a = a->next){
8230 disabled = (a->client == NULL && a->server == NULL);
8231 any_disabled += disabled;
8232 snprintf(sbuf, sizeof(sbuf), " %s%s", a->name, disabled ? " (disabled)" : "");
8233 if(++cnt < alcnt)
8234 config[cnt] = cpystr(sbuf);
8237 if(++cnt < alcnt)
8238 config[cnt] = cpystr("");
8240 if(++cnt < alcnt)
8241 config[cnt] = cpystr(_("Mailbox drivers:"));
8243 for(d = (DRIVER *)mail_parameters(NIL, GET_DRIVERS, NIL);
8244 d; d = d->next){
8245 disabled = (d->flags & DR_DISABLE);
8246 any_disabled += disabled;
8247 snprintf(sbuf, sizeof(sbuf), " %s%s", d->name, disabled ? " (disabled)" : "");
8248 if(++cnt < alcnt)
8249 config[cnt] = cpystr(sbuf);
8252 if(++cnt < alcnt)
8253 config[cnt] = cpystr("");
8255 if(++cnt < alcnt)
8256 config[cnt] = cpystr(_("Directories:"));
8258 #ifdef ENABLE_LDAP
8259 if(++cnt < alcnt)
8260 config[cnt] = cpystr(" LDAP");
8261 #else
8262 if(++cnt < alcnt)
8263 config[cnt] = cpystr(" None (no LDAP)");
8264 #endif
8266 if(any_disabled){
8267 if(++cnt < alcnt)
8268 config[cnt] = cpystr("");
8270 if(ps_global->ttyo){
8271 if(++cnt < alcnt)
8272 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."));
8274 else{
8275 if(++cnt < alcnt)
8276 config[cnt] = cpystr(_("Authenticators may be disabled because of the \"disable-these-authenticators\""));
8277 if(++cnt < alcnt)
8278 config[cnt] = cpystr(_("hidden config option. Mailbox drivers may be disabled because of the"));
8279 if(++cnt < alcnt)
8280 config[cnt] = cpystr(_("\"disable-these-drivers\" hidden config option."));
8284 if(++cnt < alcnt)
8285 config[cnt] = NULL;
8287 return(config);
8291 unsigned
8292 reset_startup_rule(MAILSTREAM *stream)
8294 long rflags = ROLE_DO_OTHER;
8295 PAT_STATE pstate;
8296 PAT_S *pat;
8297 unsigned startup_rule;
8299 startup_rule = IS_NOTSET;
8301 if(stream && nonempty_patterns(rflags, &pstate)){
8302 for(pat = first_pattern(&pstate); pat; pat = next_pattern(&pstate)){
8303 if(match_pattern(pat->patgrp, stream, NULL, NULL, NULL,
8304 SE_NOSERVER|SE_NOPREFETCH))
8305 break;
8308 if(pat && pat->action && !pat->action->bogus)
8309 startup_rule = pat->action->startup_rule;
8312 return(startup_rule);
8316 #ifdef _WINDOWS
8318 char *
8319 transformed_color(old)
8320 char *old;
8322 if(!old)
8323 return("");
8325 if(!struncmp(old, "color008", 8))
8326 return("colorlgr");
8327 else if(!struncmp(old, "color009", 8))
8328 return("colormgr");
8329 else if(!struncmp(old, "color010", 8))
8330 return("colordgr");
8332 return("");
8337 * If this is the first time we've run a version > 4.40, and there
8338 * is evidence that the config file has not been used by unix pine,
8339 * then we convert color008 to colorlgr, color009 to colormgr, and
8340 * color010 to colordgr. If the config file is being used by
8341 * unix pine then color008 may really supposed to be color008, color009
8342 * may really supposed to be red, and color010 may really supposed to be
8343 * green. Same if we've already run 4.41 or higher previously.
8345 * Returns 0 if no changes, > 0 if something was changed.
8348 convert_pc_gray_names(ps, prc, which)
8349 struct pine *ps;
8350 PINERC_S *prc;
8351 EditWhich which;
8353 struct variable *v;
8354 int ret = 0, ic = 0;
8355 char **s, *t, *p, *pstr, *new, *pval, **apval, **lval;
8357 for(v = ps->vars; v->name; v++){
8358 if(!color_holding_var(ps, v) || v == &ps->vars[V_KW_COLORS])
8359 continue;
8361 if(v == &ps->vars[V_VIEW_HDR_COLORS]){
8363 if((lval = LVAL(v,which)) != NULL){
8364 /* fix these in place */
8365 for(s = lval; (t = *s) != NULL; s++){
8366 if((p = srchstr(t, "FG=color008")) ||
8367 (p = srchstr(t, "FG=color009")) ||
8368 (p = srchstr(t, "FG=color010"))){
8369 strncpy(p+3, transformed_color(p+3), 8);
8370 ret++;
8373 if((p = srchstr(t, "BG=color008")) ||
8374 (p = srchstr(t, "BG=color009")) ||
8375 (p = srchstr(t, "BG=color010"))){
8376 strncpy(p+3, transformed_color(p+3), 8);
8377 ret++;
8382 else{
8383 if((pval = PVAL(v,which)) != NULL){
8384 apval = APVAL(v,which);
8385 if(apval && (!strucmp(pval, "color008") ||
8386 !strucmp(pval, "color009") ||
8387 !strucmp(pval, "color010"))){
8388 new = transformed_color(pval);
8389 if(*apval)
8390 fs_give((void **)apval);
8392 *apval = cpystr(new);
8393 ret++;
8399 v = &ps->vars[V_PAT_INCOLS];
8400 if((lval = LVAL(v,which)) != NULL){
8401 for(s = lval; (t = *s) != NULL; s++){
8402 if((pstr = srchstr(t, "action=")) != NULL){
8403 if((p = srchstr(pstr, "FG=color008")) ||
8404 (p = srchstr(pstr, "FG=color009")) ||
8405 (p = srchstr(pstr, "FG=color010"))){
8406 strncpy(p+3, transformed_color(p+3), 8);
8407 ic++;
8410 if((p = srchstr(pstr, "BG=color008")) ||
8411 (p = srchstr(pstr, "BG=color009")) ||
8412 (p = srchstr(pstr, "BG=color010"))){
8413 strncpy(p+3, transformed_color(p+3), 8);
8414 ic++;
8420 if(ic)
8421 set_current_val(&ps->vars[V_PAT_INCOLS], TRUE, TRUE);
8423 return(ret+ic);
8428 unix_color_style_in_pinerc(prc)
8429 PINERC_S *prc;
8431 PINERC_LINE *pline;
8433 for(pline = prc ? prc->pinerc_lines : NULL;
8434 pline && (pline->var || pline->line); pline++)
8435 if(pline->line && !struncmp("color-style=", pline->line, 12))
8436 return(1);
8438 return(0);
8441 char *
8442 pcpine_general_help(titlebuf)
8443 char *titlebuf;
8445 if(titlebuf)
8446 strcpy(titlebuf, "PC Alpine For Windows");
8448 return(pcpine_help(h_pine_for_windows));
8451 #endif /* _WINDOWS */
8453 typedef struct ssl_versions_s {
8454 char *name;
8455 int version;
8456 } SSL_VERSIONS_S;
8459 pith_ssl_encryption_version(char *s)
8461 SSL_VERSIONS_S ssl_versions[] = {
8462 {"no_min", 0},
8463 {"ssl3", SSL3_VERSION},
8464 {"tls1", TLS1_VERSION},
8465 {"tls1_1", TLS1_1_VERSION },
8466 {"tls1_2", TLS1_2_VERSION},
8467 #ifdef TLS1_3_VERSION
8468 {"tls1_3", TLS1_3_VERSION},
8469 #endif /* TLS1_3_VERSION */
8470 {"no_max", 0}, /* set this last in the list */
8471 { NULL, 0},
8473 int i;
8475 if(s == NULL || *s == '\0')
8476 return -1;
8478 for(i = 0; ssl_versions[i].name != NULL; i++)
8479 if(strcmp(ssl_versions[i].name, s) == 0)
8480 break;
8482 if(strcmp(s, "no_max") == 0) i--;
8484 return ssl_versions[i].name != NULL ? ssl_versions[i].version : -1;