* new version 2.11.8
[alpine.git] / pith / conf.c
blob7cd1f83d07fd56124876e4c4e839013fbe2ea4b0
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 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
56 #define TO_BAIL_THRESHOLD 60
60 * Internal prototypes
62 void convert_configvars_to_utf8(struct variable *, char *);
63 void convert_configvar_to_utf8(struct variable *, char *);
64 void set_current_pattern_vals(struct pine *);
65 void convert_pattern_data(void);
66 void convert_filts_pattern_data(void);
67 void convert_scores_pattern_data(void);
68 void convert_pinerc_patterns(long);
69 void convert_pinerc_filts_patterns(long);
70 void convert_pinerc_scores_patterns(long);
71 void set_old_growth_bits(struct pine *, int);
72 int var_is_in_rest_of_file(char *, char *);
73 char *skip_over_this_var(char *, char *);
74 char *native_nl(char *);
75 void set_color_val(struct variable *, int);
76 int copy_localfile_to_remotefldr(RemType, char *, char *, char *, char **);
77 char *backcompat_convert_from_utf8(char *, size_t, char *);
78 #ifdef _WINDOWS
79 char *transformed_color(char *);
80 int convert_pc_gray_names(struct pine *, PINERC_S *, EditWhich);
81 int unix_color_style_in_pinerc(PINERC_S *);
82 char *pcpine_general_help(char *);
83 char *pcpine_help(HelpType); /* defined in alpine/help */
84 #endif /* _WINDOWS */
87 /* hook too allow caller to decide what to do about failure */
88 int (*pith_opt_remote_pinerc_failure)(void);
91 /*------------------------------------
92 Some definitions to keep the static "variable" array below
93 a bit more readable...
94 ----*/
95 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\
96 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";
99 CONF_TXT_T cf_text_personal_name[] = "Over-rides your full name from Unix password file. Required for PC-Alpine.";
101 CONF_TXT_T cf_text_user_id[] = "Your login/e-mail user name";
103 CONF_TXT_T cf_text_user_domain[] = "Sets domain part of From: and local addresses in outgoing mail.";
105 CONF_TXT_T cf_text_smtp_server[] = "List of SMTP servers for sending mail. If blank: Unix Alpine uses sendmail.";
107 CONF_TXT_T cf_text_nntp_server[] = "NNTP server for posting news. Also sets news-collections for news reading.";
109 #ifdef SMIME
111 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.";
113 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.";
115 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.";
117 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.";
119 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.";
121 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.";
123 #endif /* SMIME */
125 #ifdef ENABLE_LDAP
126 CONF_TXT_T cf_text_ldap_server[] = "LDAP servers for looking up addresses.";
127 #endif /* ENABLE_LDAP */
129 CONF_TXT_T cf_text_rss_news[] = "RSS News feed";
131 CONF_TXT_T cf_text_rss_weather[] = "RSS Weather feed";
133 CONF_TXT_T cf_text_wp_indexheight[] = "Web Alpine index table row height";
135 CONF_TXT_T cf_text_wp_indexlines[] = "Web Alpine number of index lines in table";
137 CONF_TXT_T cf_text_wp_aggstate[] = "Web Alpine aggregate operations tab state";
139 CONF_TXT_T cf_text_wp_state[] = "Web Alpine various aspects of cross-session state";
141 CONF_TXT_T cf_text_wp_columns[] = "Web Alpine preferred width for message display in characters";
143 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).";
145 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";
147 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[]";
149 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}[]";
151 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";
153 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.";
155 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.";
157 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.";
159 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";
161 CONF_TXT_T cf_text_read_message_folder[] = "If set, specifies where already-read messages will be moved upon quitting.";
163 CONF_TXT_T cf_text_form_letter_folder[] = "If set, specifies where form letters should be stored.";
165 CONF_TXT_T cf_text_trash_folder[] = "If set, specifies where trash is moved to in Web Alpine.";
167 CONF_TXT_T cf_text_signature_file[] = "Over-rides default path for signature file. Default is ~/.signature";
169 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.";
171 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";
173 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";
175 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-.";
177 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)";
179 CONF_TXT_T cf_text_default_composer_hdrs[] = "Only show these headers (by default) when composing messages";
181 CONF_TXT_T cf_text_customized_hdrs[] = "Add these customized headers (and possible default values) when composing";
183 CONF_TXT_T cf_text_view_headers[] = "When viewing messages, include this list of headers";
185 CONF_TXT_T cf_text_view_margin_left[] = "When viewing messages, number of blank spaces between left display edge and text";
187 CONF_TXT_T cf_text_view_margin_right[] = "When viewing messages, number of blank spaces between right display edge and text";
189 CONF_TXT_T cf_text_quote_suppression[] = "When viewing messages, number of lines of quote displayed before suppressing";
191 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)";
193 CONF_TXT_T cf_text_color_style[] = "Controls display of color";
195 CONF_TXT_T cf_text_current_indexline_style[] = "Controls display of color for current index line";
197 CONF_TXT_T cf_text_titlebar_color_style[] = "Controls display of color for the titlebar at top of screen";
199 CONF_TXT_T cf_text_view_hdr_color[] = "When viewing messages, these are the header colors";
201 CONF_TXT_T cf_text_index_token_color[] = "Colors in which tokens will be displayed in the index screen";
203 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).";
205 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.)";
207 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\".";
209 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\".";
211 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\".";
213 CONF_TXT_T cf_text_old_char_set[] = "Character-set is obsolete, use display-character-set, keyboard-character-set,\n# and posting-character-set.";
215 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).";
217 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.";
219 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.";
221 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.";
223 CONF_TXT_T cf_text_editor[] = "Specifies the program invoked by ^_ in the Composer,\n# or the \"enable-alternate-editor-implicitly\" feature.";
225 CONF_TXT_T cf_text_speller[] = "Specifies the program invoked by ^T in the Composer.";
227 CONF_TXT_T cf_text_deadlets[] = "Specifies the number of dead letter files to keep when canceling.";
229 CONF_TXT_T cf_text_fillcol[] = "Specifies the column of the screen where the composer should wrap.";
231 CONF_TXT_T cf_text_replystr[] = "Specifies the string to insert when replying to a message.";
233 CONF_TXT_T cf_text_quotereplstr[] = "Specifies the string to replace quotes with when viewing a message.";
235 CONF_TXT_T cf_text_replyintro[] = "Specifies the introduction to insert when replying to a message.";
237 CONF_TXT_T cf_text_emptyhdr[] = "Specifies the string to use when sending a message with no to or cc.";
239 CONF_TXT_T cf_text_image_viewer[] = "Program to view images (e.g. GIF or TIFF attachments).";
241 CONF_TXT_T cf_text_browser[] = "List of programs to open Internet URLs (e.g. http or ftp references).";
243 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\".";
245 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\".";
247 CONF_TXT_T cf_reopen_rule[] = "Controls behavior when reopening an already open folder.";
249 CONF_TXT_T cf_text_thread_disp_style[] = "Style that MESSAGE INDEX is displayed in when threading.";
251 CONF_TXT_T cf_text_thread_index_style[] = "Style of THREAD INDEX or default MESSAGE INDEX when threading.";
253 CONF_TXT_T cf_text_thread_more_char[] = "When threading, character used to indicate collapsed messages underneath.";
255 CONF_TXT_T cf_text_thread_exp_char[] = "When threading, character used to indicate expanded messages underneath.";
257 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.";
259 CONF_TXT_T cf_text_use_only_domain_name[] = "If \"user-domain\" not set, strips hostname in FROM address. (Unix only)";
261 CONF_TXT_T cf_text_printer[] = "Your default printer selection";
263 CONF_TXT_T cf_text_personal_print_command[] = "List of special print commands";
265 CONF_TXT_T cf_text_personal_print_cat[] = "Which category default print command is in";
267 CONF_TXT_T cf_text_standard_printer[] = "The system wide standard printers";
269 CONF_TXT_T cf_text_last_time_prune_quest[] = "Set by Alpine; controls beginning-of-month sent-mail pruning.";
271 CONF_TXT_T cf_text_last_version_used[] = "Set by Alpine; controls display of \"new version\" message.";
273 CONF_TXT_T cf_text_disable_drivers[] = "List of mail drivers to disable.";
275 CONF_TXT_T cf_text_disable_auths[] = "List of SASL authenticators to disable.";
277 CONF_TXT_T cf_text_remote_abook_metafile[] = "Set by Alpine; contains data for caching remote address books.";
279 CONF_TXT_T cf_text_old_patterns[] = "Patterns is obsolete, use patterns-xxx";
281 CONF_TXT_T cf_text_old_filters[] = "Patterns-filters is obsolete, use patterns-filters2";
283 CONF_TXT_T cf_text_old_scores[] = "Patterns-scores is obsolete, use patterns-scores2";
285 CONF_TXT_T cf_text_patterns[] = "Patterns and their actions are stored here.";
287 CONF_TXT_T cf_text_remote_abook_history[] = "How many extra copies of remote address book should be kept. Default: 3";
289 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";
291 CONF_TXT_T cf_text_bugs_fullname[] = "Full name for bug report address used by \"Report Bug\" command";
293 CONF_TXT_T cf_text_bugs_address[] = "Email address used to send bug reports";
295 CONF_TXT_T cf_text_bugs_extras[] = "Program/Script used by \"Report Bug\" command. No default.";
297 CONF_TXT_T cf_text_suggest_fullname[] = "Full name for suggestion address used by \"Report Bug\" command";
299 CONF_TXT_T cf_text_suggest_address[] = "Email address used to send suggestions";
301 CONF_TXT_T cf_text_local_fullname[] = "Full name for \"local support\" address used by \"Report Bug\" command.\n# Default: Local Support";
303 CONF_TXT_T cf_text_local_address[] = "Email address used to send to \"local support\".\n# Default: postmaster";
305 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";
307 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.";
309 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.";
311 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)";
313 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.";
315 CONF_TXT_T cf_text_out_fltr[] = "This defines a program that message text is piped into before MIME\n# encoding, prior to sending";
317 CONF_TXT_T cf_text_alt_addrs[] = "A list of alternate addresses the user is known by";
319 CONF_TXT_T cf_text_keywords[] = "A list of keywords for use in categorizing messages";
321 CONF_TXT_T cf_text_kw_colors[] = "Colors used to display keywords in the index";
323 CONF_TXT_T cf_text_kw_braces[] = "Characters which surround keywords in SUBJKEY token.\n# Default is \"{\" \"} \"";
325 CONF_TXT_T cf_text_opening_sep[] = "Characters between subject and opening text in SUBJECTTEXT token.\n# Default is \" - \"";
327 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";
329 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";
331 CONF_TXT_T cf_text_overlap[] = "The number of lines of overlap when scrolling through message text";
333 CONF_TXT_T cf_text_maxremstreams[] = "The maximum number of non-stayopen remote connections that Alpine will use";
335 CONF_TXT_T cf_text_permlocked[] = "A list of folders that should be left open once opened (INBOX is implicit)";
337 CONF_TXT_T cf_text_margin[] = "Number of lines from top and bottom of screen where single\n# line scrolling occurs.";
339 CONF_TXT_T cf_text_stat_msg_delay[] = "The number of seconds to sleep after writing a status message";
341 CONF_TXT_T cf_text_busy_cue_rate[] = "Number of times per-second to update busy cue messages";
343 CONF_TXT_T cf_text_mailcheck[] = "The approximate number of seconds between checks for new mail";
345 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";
347 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";
349 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";
351 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\".";
353 CONF_TXT_T cf_text_news_spooldir[] = "Directory containing system's news data.\n# The default is typically \"/usr/spool/news\"";
355 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.";
357 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.";
359 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.";
361 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.";
363 CONF_TXT_T cf_text_goto_default[] = "Sets the default folder and collection offered at the Goto Command's prompt.";
365 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.";
367 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.";
369 CONF_TXT_T cf_text_newmail_fifo_path[] = "Sets the filename for the newmail fifo (named pipe). Unix only.";
371 CONF_TXT_T cf_text_nmw_width[] = "Sets the width for the NewMail screen.";
373 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.";
375 CONF_TXT_T cf_text_debug_mem[] = "Debug-memory is obsolete";
377 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).";
379 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.";
381 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.";
383 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.";
385 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.";
387 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.";
389 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\")";
391 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.";
393 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.";
395 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.";
397 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.";
399 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.";
401 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.";
403 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\")";
405 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.";
407 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.";
409 CONF_TXT_T cf_text_elm_style_save[] = "Elm-style-save is obsolete, use saved-msg-name-rule";
411 CONF_TXT_T cf_text_header_in_reply[] = "Header-in-reply is obsolete, use include-header-in-reply in feature-list";
413 CONF_TXT_T cf_text_feature_level[] = "Feature-level is obsolete, use feature-list";
415 CONF_TXT_T cf_text_old_style_reply[] = "Old-style-reply is obsolete, use signature-at-bottom in feature-list";
417 CONF_TXT_T cf_text_compose_mime[] = "Compose-mime is obsolete";
419 CONF_TXT_T cf_text_show_all_characters[] = "Show-all-characters is obsolete";
421 CONF_TXT_T cf_text_save_by_sender[] = "Save-by-sender is obsolete, use saved-msg-name-rule";
423 CONF_TXT_T cf_text_file_dir[] = "Default directory used for Attachment handling (attach and save)\n# and Export command output";
425 CONF_TXT_T cf_text_folder_extension[] = "Folder-extension is obsolete";
427 CONF_TXT_T cf_text_normal_foreground_color[] = "Choose: black, blue, green, cyan, red, magenta, yellow, or white.";
429 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.";
431 CONF_TXT_T cf_text_newsrc_path[] = "Full path and name of NEWSRC file";
434 /*----------------------------------------------------------------------
435 These are the variables that control a number of pine functions. They
436 come out of the .pinerc and the /usr/local/lib/pine.conf files. Some can
437 be set by the user while in Alpine. Eventually all the local ones should
438 be so and maybe the global ones too.
440 Each variable can have a command-line, user, global, and current value.
441 All of these values are malloc'd. The user value is the one read out of
442 the user's .pinerc, the global value is the one from the system pine
443 configuration file. There are often defaults for the global values, set
444 at the start of init_vars(). Perhaps someday there will be group values.
445 The current value is the one that is actually in use.
446 ----*/
447 /* name is_changed_val
448 remove_quotes |
449 is_outermost | |
450 is_onlymain | | |
451 is_fixed | | | |
452 is_list | | | | |
453 is_global | | | | | |
454 is_user | | | | | | |
455 been_written | | | | | | | |
456 is_used | | | | | | | | |
457 is_obsolete | | | | | | | | | |
458 | | | | | | | | | | |
459 (on following line) description | | | | | | | | | | |
460 | | | | | | | | | | | |
461 | | | | | | | | | | | | */
462 static struct variable variables[] = {
463 {"personal-name", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
464 NULL, cf_text_personal_name},
466 #if defined(DOS) || defined(OS2)
467 /* Have to have this on DOS, PC's, Macs, etc... */
468 "user-id", 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0,
469 #else /* Don't allow on UNIX machines for some security */
470 "user-id", 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0,
471 #endif
472 "User ID", cf_text_user_id},
473 {"user-domain", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
474 NULL, cf_text_user_domain},
475 {"smtp-server", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
476 "SMTP Server (for sending)", cf_text_smtp_server},
477 {"nntp-server", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
478 "NNTP Server (for news)", cf_text_nntp_server},
479 {"inbox-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
480 NULL, cf_text_inbox_path},
481 {"incoming-archive-folders", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
482 NULL, cf_text_archived_folders},
483 {"pruned-folders", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
484 NULL, cf_text_pruned_folders},
485 {"default-fcc", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
486 "Default Fcc (File carbon copy)", cf_text_default_fcc},
487 {"default-saved-msg-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
488 "Default Saved Message Folder", cf_text_default_saved},
489 {"postponed-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
490 NULL, cf_text_postponed_folder},
491 {"read-message-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
492 NULL, cf_text_read_message_folder},
493 {"form-letter-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
494 NULL, cf_text_form_letter_folder},
495 {"trash-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
496 NULL, cf_text_trash_folder},
497 {"literal-signature", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
498 NULL, cf_text_literal_sig},
499 {"signature-file", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
500 NULL, cf_text_signature_file},
501 {"feature-list", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
502 NULL, cf_text_feature_list},
503 {"initial-keystroke-list", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
504 NULL, cf_text_initial_keystroke_list},
505 {"default-composer-hdrs", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
506 "Default Composer Headers", cf_text_default_composer_hdrs},
507 {"customized-hdrs", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
508 "Customized Headers", cf_text_customized_hdrs},
509 {"viewer-hdrs", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
510 "Viewer Headers", cf_text_view_headers},
511 {"viewer-margin-left", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
512 NULL, cf_text_view_margin_left},
513 {"viewer-margin-right", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
514 NULL, cf_text_view_margin_right},
515 {"quote-suppression-threshold", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
516 NULL, cf_text_quote_suppression},
517 {"saved-msg-name-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
518 "Saved Message Name Rule", cf_text_save_msg_name_rule},
519 {"fcc-name-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
520 NULL, cf_text_fcc_name_rule},
521 {"sort-key", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
522 NULL, cf_text_sort_key},
523 {"addrbook-sort-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
524 "Address Book Sort Rule", cf_text_addrbook_sort_rule},
525 {"folder-sort-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
526 NULL, cf_text_folder_sort_rule},
527 {"goto-default-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
528 NULL, cf_text_goto_default},
529 {"incoming-startup-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
530 NULL, cf_text_inc_startup},
531 {"pruning-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
532 NULL, cf_pruning_rule},
533 {"folder-reopen-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
534 NULL, cf_reopen_rule},
535 {"threading-display-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
536 NULL, cf_text_thread_disp_style},
537 {"threading-index-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
538 NULL, cf_text_thread_index_style},
539 {"threading-indicator-character", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
540 NULL, cf_text_thread_more_char},
541 {"threading-expanded-character", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
542 NULL, cf_text_thread_exp_char},
543 {"threading-lastreply-character", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
544 "Threading Last Reply Character", cf_text_thread_lastreply_char},
545 #ifndef _WINDOWS
546 {"display-character-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
547 NULL, cf_text_disp_char_set},
548 {"character-set", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
549 NULL, cf_text_old_char_set},
550 {"keyboard-character-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
551 NULL, cf_text_key_char_set},
552 #endif /* ! _WINDOWS */
553 {"posting-character-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
554 NULL, cf_text_post_character_set},
555 {"unknown-character-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
556 NULL, cf_text_unk_character_set},
557 {"editor", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
558 NULL, cf_text_editor},
559 {"speller", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
560 NULL, cf_text_speller},
561 {"composer-wrap-column", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
562 NULL, cf_text_fillcol},
563 {"reply-indent-string", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
564 NULL, cf_text_replystr},
565 {"reply-leadin", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
566 NULL, cf_text_replyintro},
567 {"quote-replace-string", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
568 NULL, cf_text_quotereplstr},
569 {"composer-word-separators", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
570 NULL, cf_text_wordsep},
571 {"empty-header-message", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
572 NULL, cf_text_emptyhdr},
573 {"image-viewer", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
574 NULL, cf_text_image_viewer},
575 {"use-only-domain-name", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
576 NULL, cf_text_use_only_domain_name},
577 {"bugs-fullname", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
578 NULL, cf_text_bugs_fullname},
579 {"bugs-address", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
580 NULL, cf_text_bugs_address},
581 {"bugs-additional-data", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
582 NULL, cf_text_bugs_extras},
583 {"suggest-fullname", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
584 NULL, cf_text_suggest_fullname},
585 {"suggest-address", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
586 NULL, cf_text_suggest_address},
587 {"local-fullname", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
588 NULL, cf_text_local_fullname},
589 {"local-address", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
590 NULL, cf_text_local_address},
591 {"forced-abook-entry", 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0,
592 NULL, cf_text_forced_abook},
593 {"kblock-passwd-count", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
594 NULL, cf_text_kblock_passwd},
595 {"display-filters", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
596 NULL, cf_text_in_fltr},
597 {"sending-filters", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
598 NULL, cf_text_out_fltr},
599 {"alt-addresses", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
600 "Alternate Addresses", cf_text_alt_addrs},
601 {"keywords", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
602 NULL, cf_text_keywords},
603 {"keyword-surrounding-chars", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
604 "Keyword Surrounding Characters", cf_text_kw_braces},
605 {"opening-text-separator-chars", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
606 "Opening Text Separator Characters", cf_text_opening_sep},
607 {"addressbook-formats", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
608 "Address Book Formats", cf_text_abook_formats},
609 {"index-format", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
610 NULL, cf_text_index_format},
611 {"viewer-overlap", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
612 NULL, cf_text_overlap},
613 {"scroll-margin", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
614 NULL, cf_text_margin},
615 {"status-message-delay", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
616 NULL, cf_text_stat_msg_delay},
617 {"busy-cue-rate", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
618 NULL, cf_text_busy_cue_rate},
619 {"mail-check-interval", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
620 NULL, cf_text_mailcheck},
621 {"mail-check-interval-noncurrent", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
622 NULL, cf_text_mailchecknoncurr},
623 {"maildrop-check-minimum", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
624 NULL, cf_text_maildropcheck},
625 {"nntp-range", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
626 "NNTP Range", cf_text_nntprange},
627 {"newsrc-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
628 NULL, cf_text_newsrc_path},
629 {"news-active-file-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
630 NULL, cf_text_news_active},
631 {"news-spool-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
632 NULL, cf_text_news_spooldir},
633 {"upload-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
634 NULL, cf_text_upload_cmd},
635 {"upload-command-prefix", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
636 NULL, cf_text_upload_prefix},
637 {"download-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
638 NULL, cf_text_download_cmd},
639 {"download-command-prefix", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
640 NULL, cf_text_download_prefix},
641 {"mailcap-search-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
642 NULL, cf_text_mailcap_path},
643 {"mimetype-search-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
644 NULL, cf_text_mimetype_path},
645 {"url-viewers", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
646 "URL-Viewers", cf_text_browser},
647 {"max-remote-connections", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
648 "Maximum Remote Connections", cf_text_maxremstreams},
649 {"stay-open-folders", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
650 "Stayopen Folders", cf_text_permlocked},
651 {"incoming-check-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
652 NULL, cf_text_inc_check_timeo},
653 {"incoming-check-interval", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
654 NULL, cf_text_inc_check_interval},
655 {"incoming-check-interval-secondary", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
656 NULL, cf_text_inc_second_check_interval},
657 {"incoming-check-list", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
658 NULL, cf_text_inc_check_list},
659 {"dead-letter-files", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
660 NULL, cf_text_deadlets},
661 #if !defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)
662 {"newmail-fifo-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
663 "NewMail FIFO Path", cf_text_newmail_fifo_path},
664 #endif
665 {"newmail-window-width", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
666 "NewMail Window Width", cf_text_nmw_width},
668 * Starting here, the variables are hidden in the Setup/Config screen.
669 * They are exposed if feature expose-hidden-config is set.
671 {"incoming-folders", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
672 NULL, cf_text_incoming_folders},
673 {"mail-directory", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
674 NULL, cf_text_mail_directory},
675 {"folder-collections", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
676 NULL, cf_text_folder_collections},
677 {"news-collections", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
678 NULL, cf_text_news_collections},
679 {"address-book", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
680 NULL, cf_text_address_book},
681 {"global-address-book", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
682 NULL, cf_text_global_address_book},
683 {"standard-printer", 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0,
684 NULL, cf_text_standard_printer},
685 {"last-time-prune-questioned", 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0,
686 NULL, cf_text_last_time_prune_quest},
687 {"last-version-used", 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0,
688 NULL, cf_text_last_version_used},
689 {"sendmail-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
690 NULL, cf_text_sendmail_path},
691 {"operating-dir", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
692 NULL, cf_text_oper_dir},
693 {"user-input-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
694 NULL, cf_text_user_input_timeo},
695 /* OBSOLETE */
696 #ifdef DEBUGJOURNAL
697 {"debug-memory", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
698 NULL, cf_text_debug_mem},
699 #endif
700 {"tcp-open-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
701 "TCP Open Timeout", cf_text_tcp_open_timeo},
702 {"tcp-read-warning-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
703 "TCP Read Warning Timeout", cf_text_tcp_read_timeo},
704 {"tcp-write-warning-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
705 "TCP Write Warning Timeout", cf_text_tcp_write_timeo},
706 {"tcp-query-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
707 "TCP Query Timeout", cf_text_tcp_query_timeo},
708 {"rsh-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
709 NULL, cf_text_rsh_command},
710 {"rsh-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
711 NULL, cf_text_rsh_path},
712 {"rsh-open-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
713 NULL, cf_text_rsh_open_timeo},
714 {"ssh-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
715 NULL, cf_text_ssh_command},
716 {"ssh-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
717 NULL, cf_text_ssh_path},
718 {"ssh-open-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
719 NULL, cf_text_ssh_open_timeo},
720 {"new-version-threshold", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
721 NULL, cf_text_version_threshold},
722 {"disable-these-drivers", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
723 NULL, cf_text_disable_drivers},
724 {"disable-these-authenticators", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
725 NULL, cf_text_disable_auths},
726 {"remote-abook-metafile", 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0,
727 NULL, cf_text_remote_abook_metafile},
728 {"remote-abook-history", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
729 NULL, cf_text_remote_abook_history},
730 {"remote-abook-validity", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
731 NULL, cf_text_remote_abook_validity},
732 {"printer", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
733 NULL, cf_text_printer},
734 {"personal-print-command", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
735 NULL, cf_text_personal_print_command},
736 {"personal-print-category", 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0,
737 NULL, cf_text_personal_print_cat},
738 {"patterns", 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
739 NULL, cf_text_old_patterns},
740 {"patterns-roles", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
741 NULL, cf_text_patterns},
742 {"patterns-filters2", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
743 "Patterns Filters", cf_text_patterns},
744 {"patterns-filters", 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
745 NULL, cf_text_old_filters},
746 {"patterns-scores2", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
747 "Patterns Scores", cf_text_patterns},
748 {"patterns-scores", 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
749 NULL, cf_text_old_scores},
750 {"patterns-indexcolors", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
751 NULL, cf_text_patterns},
752 {"patterns-other", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
753 NULL, cf_text_patterns},
754 {"patterns-search", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
755 NULL, cf_text_patterns},
756 /* OBSOLETE VARS */
757 {"elm-style-save", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
758 NULL, cf_text_elm_style_save},
759 {"header-in-reply", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
760 NULL, cf_text_header_in_reply},
761 {"feature-level", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
762 NULL, cf_text_feature_level},
763 {"old-style-reply", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
764 NULL, cf_text_old_style_reply},
765 {"compose-mime", 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
766 NULL, cf_text_compose_mime},
767 {"show-all-characters", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
768 NULL, cf_text_show_all_characters},
769 {"save-by-sender", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
770 NULL, cf_text_save_by_sender},
771 #if defined(DOS) || defined(OS2)
772 {"file-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
773 NULL, cf_text_file_dir},
774 {"folder-extension", 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0,
775 NULL, cf_text_folder_extension},
776 #endif
777 #ifndef _WINDOWS
778 {"color-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
779 NULL, cf_text_color_style},
780 #endif
781 {"current-indexline-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
782 NULL, cf_text_current_indexline_style},
783 {"titlebar-color-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
784 NULL, cf_text_titlebar_color_style},
785 {"normal-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
786 NULL, cf_text_normal_foreground_color},
787 {"normal-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
788 {"reverse-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
789 {"reverse-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
790 {"title-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
791 {"title-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
792 {"title-closed-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
793 {"title-closed-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
794 {"folder-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
795 {"folder-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
796 {"directory-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
797 {"directory-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
798 {"folder-list-text-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
799 {"folder-list-text-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
800 {"status-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
801 {"status-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
802 {"keylabel-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
803 {"keylabel-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
804 {"keyname-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
805 {"keyname-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
806 {"selectable-item-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
807 {"selectable-item-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
808 {"meta-message-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
809 {"meta-message-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
810 {"quote1-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
811 {"quote1-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
812 {"quote2-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
813 {"quote2-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
814 {"quote3-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
815 {"quote3-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
816 {"incoming-unseen-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
817 {"incoming-unseen-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
818 {"signature-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
819 {"signature-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
820 {"prompt-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
821 {"prompt-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
822 {"header-general-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
823 {"header-general-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
824 {"index-to-me-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
825 {"index-to-me-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
826 {"index-important-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
827 {"index-important-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
828 {"index-deleted-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
829 {"index-deleted-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
830 {"index-answered-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
831 {"index-answered-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
832 {"index-new-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
833 {"index-new-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
834 {"index-recent-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
835 {"index-recent-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
836 {"index-forward-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
837 {"index-forward-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
838 {"index-unseen-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
839 {"index-unseen-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
840 {"index-highpriority-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
841 {"index-highpriority-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
842 {"index-lowpriority-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
843 {"index-lowpriority-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
844 {"index-arrow-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
845 {"index-arrow-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
846 {"index-subject-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
847 {"index-subject-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
848 {"index-from-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
849 {"index-from-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
850 {"index-opening-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
851 {"index-opening-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
852 {"index-token-colors", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
853 NULL, cf_text_index_token_color},
854 {"viewer-hdr-colors", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
855 "Viewer Header Colors", cf_text_view_hdr_color},
856 {"keyword-colors", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
857 NULL, cf_text_kw_colors},
858 #ifdef _WINDOWS
859 {"font-name", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
860 NULL, "name and size of font."},
861 {"font-size", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
862 {"font-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
863 {"font-char-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
864 {"print-font-name", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
865 NULL, "name and size of printer font."},
866 {"print-font-size", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
867 {"print-font-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
868 {"print-font-char-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
869 {"window-position", 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0,
870 NULL, cf_text_window_position},
871 {"cursor-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
872 #endif /* _WINDOWS */
873 #ifdef SMIME
874 {"smime-public-cert-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
875 "S/MIME - Public Cert Directory", cf_text_publiccertdir},
876 {"smime-public-cert-container", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
877 "S/MIME - Public Cert Container", cf_text_publiccertcontainer},
878 {"smime-private-key-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
879 "S/MIME - Private Key Directory", cf_text_privatekeydir},
880 {"smime-private-key-container", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
881 "S/MIME - Private Key Container", cf_text_privatekeycontainer},
882 {"smime-cacert-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
883 "S/MIME - Cert Authority Directory", cf_text_cacertdir},
884 {"smime-cacert-container", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
885 "S/MIME - Cert Authority Container", cf_text_cacertcontainer},
886 #endif /* SMIME */
887 #ifdef ENABLE_LDAP
888 {"ldap-servers", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
889 "LDAP Servers", cf_text_ldap_server},
890 #endif /* ENABLE_LDAP */
891 {"rss-news", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
892 "WEB ALPINE - RSS News", cf_text_rss_news},
893 {"rss-weather", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
894 "WEB ALPINE - RSS Weather", cf_text_rss_weather},
895 {"wp-indexheight", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
896 "WEB ALPINE - Index Height", cf_text_wp_indexheight},
897 {"wp-indexlines", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
898 "WEB ALPINE - Index Lines", cf_text_wp_indexlines},
899 {"wp-aggstate", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
900 "WEB ALPINE - Aggregate State", cf_text_wp_aggstate},
901 {"wp-state", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
902 "WEB ALPINE - Cross Session State", cf_text_wp_state},
903 {"wp-columns", 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0,
904 "WEB ALPINE - Columns", cf_text_wp_columns},
905 {NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL,NULL}
909 struct variable *
910 var_from_name(char *name)
912 struct variable *v;
913 int i;
915 if(!(name && name[0]))
916 return(NULL);
918 for(i = 0; (v = &variables[i]) && v->name; i++)
919 if(!strucmp(v->name,name))
920 return(v);
922 return(NULL);
926 void
927 init_init_vars(struct pine *ps)
929 ps->vars = variables;
933 #define DSIZE (25000)
934 /* this is just like dprint except it prints to a char * */
935 #ifdef DEBUG
936 #define mprint(n,x) { \
937 if(debug >= (n)){ \
938 snprintf x ; \
939 db += strlen(db); \
942 #else
943 #define mprint(n,x)
944 #endif
947 * this was split out from init_vars so we can get at the
948 * pinerc location sooner.
950 void
951 init_pinerc(struct pine *ps, char **debug_out)
953 char buf[MAXPATH+1], *p, *db;
954 #if defined(DOS) || defined(OS2)
955 char buf2[MAXPATH+1], l_pinerc[MAXPATH+1];
956 int nopinerc = 0, confregset = -1;
957 register struct variable *vars = ps->vars;
958 #endif
960 #ifdef DEBUG
962 * Since this routine is called before we've had a chance to set up
963 * the debug file for output, we put the debugging into memory and
964 * pass it back to the caller for use after init_debug(). We just
965 * allocate plenty of space.
967 if(debug_out){
968 db = *debug_out = (char *)fs_get(DSIZE * sizeof(char));
969 db[0] = '\0';
971 #endif
973 mprint(2, (db, DSIZE-(db-(*debug_out)), "\n -- init_pinerc --\n\n"));
975 #if defined(DOS) || defined(OS2)
977 * Rules for the config/support file locations under DOS are:
979 * 1) The location of the PINERC is searched for in the following
980 * order of precedence:
981 * - File pointed to by '-p' command line option
982 * - File pointed to by PINERC environment variable
983 * - $HOME\pine
984 * - same dir as argv[0]
986 * 2) The HOME environment variable, if not set, defaults to
987 * root of the current working drive (see alpine.c)
989 * 3) The default for external files (PINE.SIG and ADDRBOOK) is the
990 * same directory as the pinerc
992 * 4) The support files (PINE.HLP and PINE.NDX) are expected to be in
993 * the same directory as PINE.EXE.
996 if(ps->prc){
997 mprint(2, (db, DSIZE-(db-(*debug_out)),
998 "Personal config \"%.100s\" comes from command line\n",
999 (ps->prc && ps->prc->name) ? ps->prc->name : "<no name>"));
1001 else{
1002 mprint(2, (db, DSIZE-(db-(*debug_out)),
1003 "Personal config not set on cmdline, checking for $PINERC\n"));
1007 * First, if prc hasn't been set by a command-line -p, check to see
1008 * if PINERC is in the environment. If so, treat it just like we
1009 * would have treated it if it were a command-line arg.
1011 if(!ps->prc && (p = getenv("PINERC")) && *p){
1012 char path[MAXPATH], dir[MAXPATH];
1014 if(IS_REMOTE(p) || is_absolute_path(p)){
1015 strncpy(path, p, sizeof(path)-1);
1016 path[sizeof(path)-1] = '\0';
1018 else{
1019 getcwd(dir, sizeof(dir));
1020 build_path(path, dir, p, sizeof(path));
1023 if(!IS_REMOTE(p))
1024 ps->pinerc = cpystr(path);
1026 ps->prc = new_pinerc_s(path);
1028 if(ps->prc){
1029 mprint(2, (db, DSIZE-(db-(*debug_out)),
1030 " yes, personal config \"%.100s\" comes from $PINERC\n",
1031 (ps->prc && ps->prc->name) ? ps->prc->name : "<no name>"));
1036 * Pinerc used to be the name of the pinerc file. Then we added
1037 * the possibility of the pinerc file being remote, and we replaced
1038 * the variable pinerc with the structure prc. Unfortunately, some
1039 * parts of pine rely on the fact that pinerc is the name of the
1040 * pinerc _file_, and use the directory that the pinerc file is located
1041 * in for their own purposes. We want to preserve that so things will
1042 * keep working. So, even if the real pinerc is remote, we need to
1043 * put the name of a pinerc file in the pinerc variable so that the
1044 * directory which contains that file is writable. The file itself
1045 * doesn't have to exist for this purpose, since we are really only
1046 * using the name of the directory containing the file. Twisted.
1047 * (Alternatively, we could fix all of the code that uses the pinerc
1048 * variable for this purpose to use a new variable which really is
1049 * just a directory.) hubert 2000-sep
1051 * There are 3 cases. If pinerc is already set that means that the user
1052 * gave either a -p pinerc or an environment pinerc that is a local file,
1053 * and we are done. If pinerc is not set, then either prc is set or not.
1054 * If prc is set then the -p arg or PINERC value is a remote pinerc.
1055 * In that case we need to find a local directory to use, and put that
1056 * directory in the pinerc variable (with a fake filename tagged on).
1057 * If prc is not set, then user hasn't told us anything so we have to
1058 * try to find the default pinerc file by looking down the path of
1059 * possibilities. When we find it, we'll also use that directory.
1061 if(!ps->pinerc){
1062 *l_pinerc = '\0';
1063 *buf = '\0';
1065 if(ps->prc){ /* remote pinerc case */
1067 * We don't give them an l_pinerc unless they tell us where
1068 * to put it.
1070 if(ps->aux_files_dir)
1071 build_path(l_pinerc, ps->aux_files_dir, SYSTEM_PINERC,
1072 sizeof(l_pinerc));
1073 else{
1075 * Search for a writable directory.
1076 * Mimic what happens in !prc for local case, except we
1077 * don't need to look for the actual file.
1080 /* check if $HOME\PINE is writable */
1081 build_path(buf2, ps->home_dir, DF_PINEDIR, sizeof(buf2));
1082 if(is_writable_dir(buf2) == 0)
1083 build_path(l_pinerc, buf2, SYSTEM_PINERC, sizeof(l_pinerc));
1084 else{ /* $HOME\PINE not a writable dir */
1085 /* use this unless registry redirects us */
1086 build_path(l_pinerc, ps->pine_dir, SYSTEM_PINERC,
1087 sizeof(l_pinerc));
1088 #ifdef _WINDOWS
1089 /* if in registry, use that value */
1090 if(mswin_reg(MSWR_OP_GET, MSWR_PINE_RC, buf2, sizeof(buf2))
1091 && !IS_REMOTE(buf2)){
1092 strncpy(l_pinerc, buf2, sizeof(l_pinerc)-1);
1093 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1095 #endif
1099 else{ /* searching for pinerc file to use */
1101 * Buf2 is $HOME\PINE. If $HOME is not explicitly set,
1102 * it defaults to the current working drive (often C:).
1103 * See alpine.c to see how it is initially set.
1106 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, searching...\n"));
1107 build_path(buf2, ps->home_dir, DF_PINEDIR, sizeof(buf2));
1108 mprint(2, (db, DSIZE-(db-(*debug_out)),
1109 " checking for writable %.100s dir \"%.100s\" off of homedir\n",
1110 DF_PINEDIR, buf2));
1111 if(is_writable_dir(buf2) == 0){
1113 * $HOME\PINE exists and is writable.
1114 * See if $HOME\PINE\PINERC exists.
1116 build_path(buf, buf2, SYSTEM_PINERC, sizeof(buf));
1117 strncpy(l_pinerc, buf, sizeof(l_pinerc)-1);
1118 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1119 mprint(2, (db, DSIZE-(db-(*debug_out)), " yes, now checking for file \"%.100s\"\n",
1120 buf));
1121 if(can_access(buf, ACCESS_EXISTS) == 0){ /* found it! */
1123 * Buf is what we were looking for.
1124 * It is local and can be used for the directory, too.
1126 mprint(2, (db, DSIZE-(db-(*debug_out)), " found it\n"));
1128 else{
1130 * No $HOME\PINE\PINERC, look for
1131 * one in same dir as PINE.EXE.
1133 build_path(buf2, ps->pine_dir, SYSTEM_PINERC,
1134 sizeof(buf2));
1135 mprint(2, (db, DSIZE-(db-(*debug_out)),
1136 " no, checking for \"%.100s\" in pine.exe dir\n",
1137 buf2));
1138 if(can_access(buf2, ACCESS_EXISTS) == 0){
1139 /* found it! */
1140 mprint(2, (db, DSIZE-(db-(*debug_out)), " found it\n"));
1141 strncpy(buf, buf2, sizeof(buf)-1);
1142 buf[sizeof(buf)-1] = '\0';
1143 strncpy(l_pinerc, buf2, sizeof(l_pinerc)-1);
1144 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1146 else{
1147 #ifdef _WINDOWS
1148 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, checking in registry\n"));
1149 if(mswin_reg(MSWR_OP_GET, MSWR_PINE_RC,
1150 buf2, sizeof(buf2))){
1151 strncpy(buf, buf2, sizeof(buf)-1);
1152 buf[sizeof(buf)-1] = '\0';
1153 if(!IS_REMOTE(buf2)){
1154 strncpy(l_pinerc, buf2, sizeof(l_pinerc)-1);
1155 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1158 * Now buf is the pinerc to be used, l_pinerc is
1159 * the directory, which may be either same as buf
1160 * or it may be $HOME\PINE if registry gives us
1161 * a remote pinerc.
1163 mprint(2, (db, DSIZE-(db-(*debug_out)), " found \"%.100s\" in registry\n",
1164 buf));
1166 else{
1167 nopinerc = 1;
1168 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found, asking user\n"));
1170 #else
1171 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found\n"));
1172 #endif
1177 * Buf is the pinerc (could be remote if from registry)
1178 * and l_pinerc is the local pinerc, which may not exist.
1181 else{ /* $HOME\PINE not a writable dir */
1183 * We notice that the order of checking in the registry
1184 * and checking in the ALPINE.EXE directory are different
1185 * in this case versus the is_writable_dir(buf2) case, and
1186 * that does sort of look like a bug. However,
1187 * we don't think this is a bug since we did it on purpose
1188 * a long time ago. So even though we can't remember why
1189 * it is this way, we think we would rediscover why if we
1190 * changed it! So we won't change it.
1194 * Change the default to use to the ALPINE.EXE directory.
1196 build_path(buf, ps->pine_dir, SYSTEM_PINERC, sizeof(buf));
1197 strncpy(l_pinerc, buf, sizeof(l_pinerc)-1);
1198 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1199 #ifdef _WINDOWS
1200 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, not writable, checking in registry\n"));
1201 /* if in registry, use that value */
1202 if(mswin_reg(MSWR_OP_GET, MSWR_PINE_RC, buf2, sizeof(buf2))){
1203 strncpy(buf, buf2, sizeof(buf)-1);
1204 buf[sizeof(buf)-1] = '\0';
1205 mprint(2, (db, DSIZE-(db-(*debug_out)), " found \"%.100s\" in registry\n",
1206 buf));
1207 if(!IS_REMOTE(buf)){
1208 strncpy(l_pinerc, buf, sizeof(l_pinerc)-1);
1209 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1212 else{
1213 mprint(2, (db, DSIZE-(db-(*debug_out)),
1214 " no, checking for \"%.100s\" in alpine.exe dir\n",
1215 buf));
1217 if(can_access(buf, ACCESS_EXISTS) == 0){
1218 mprint(2, (db, DSIZE-(db-(*debug_out)), " found it\n"));
1220 else{
1221 nopinerc = 1;
1222 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found, asking user\n"));
1225 #else
1226 mprint(2, (db, DSIZE-(db-(*debug_out)),
1227 " no, checking for \"%.100s\" in alpine.exe dir\n",
1228 buf));
1230 if(can_access(buf, ACCESS_EXISTS) == 0){
1231 mprint(2, (db, DSIZE-(db-(*debug_out)), " found it\n"));
1233 else{
1234 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found, creating it\n"));
1236 #endif
1240 * When we get here we have buf set to the name of the
1241 * pinerc, which could be local or remote. We have l_pinerc
1242 * set to the same as buf if buf is local, and set to another
1243 * name otherwise, hopefully contained in a writable directory.
1245 #ifdef _WINDOWS
1246 if(nopinerc || ps_global->install_flag){
1247 char buf3[MAXPATH+1];
1249 confregset = 0;
1250 strncpy(buf3, buf, MAXPATH);
1251 buf3[MAXPATH] = '\0';
1252 if(os_config_dialog(buf3, MAXPATH,
1253 &confregset, nopinerc) == 0){
1254 strncpy(buf, buf3, MAXPATH);
1255 buf[MAXPATH] = '\0';
1256 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found, creating it\n"));
1257 mprint(2, (db, DSIZE-(db-(*debug_out)), " user says use \"%.100s\"\n", buf));
1258 if(!IS_REMOTE(buf)){
1259 strncpy(l_pinerc, buf, MAXPATH);
1260 l_pinerc[MAXPATH] = '\0';
1263 else{
1264 exit(-1);
1267 #endif
1268 ps->prc = new_pinerc_s(buf);
1271 ps->pinerc = cpystr(l_pinerc);
1274 #if defined(DOS) || defined(OS2)
1276 * The goal here is to set the auxiliary directory in the pinerc variable.
1277 * We are making the assumption that any reference to the pinerc variable
1278 * after this point is used only as a directory in which to store things,
1279 * with the prc variable being the preferred place to store pinerc location.
1280 * If -aux isn't set, then there is no change. -jpf 08/2001
1282 if(ps->aux_files_dir){
1283 l_pinerc[0] = '\0';
1284 build_path(l_pinerc, ps->aux_files_dir, SYSTEM_PINERC,
1285 sizeof(l_pinerc));
1286 if(ps->pinerc) fs_give((void **)&ps->pinerc);
1287 ps->pinerc = cpystr(l_pinerc);
1288 mprint(2, (db, DSIZE-(db-(*debug_out)), "Setting aux_files_dir to \"%.100s\"\n",
1289 ps->aux_files_dir));
1291 #endif
1293 #ifdef _WINDOWS
1294 if(confregset && (ps->update_registry != UREG_NEVER_SET))
1295 mswin_reg(MSWR_OP_SET | ((ps->update_registry == UREG_ALWAYS_SET)
1296 || confregset == 1 ? MSWR_OP_FORCE : 0),
1297 MSWR_PINE_RC,
1298 (ps->prc && ps->prc->name) ?
1299 ps->prc->name : ps->pinerc, (size_t)NULL);
1300 #endif
1303 * Now that we know the default for the PINERC, build NEWSRC default.
1304 * Backward compatibility makes this kind of funky. If what the
1305 * c-client thinks the NEWSRC should be exists *AND* it doesn't
1306 * already exist in the PINERC's dir, use c-client's default, otherwise
1307 * use the one next to the PINERC...
1309 p = last_cmpnt(ps->pinerc);
1310 buf[0] = '\0';
1311 if(p != NULL){
1312 strncpy(buf, ps->pinerc, MIN(p - ps->pinerc, sizeof(buf)-1));
1313 buf[MIN(p - ps->pinerc, sizeof(buf)-1)] = '\0';
1316 mprint(2, (db, DSIZE-(db-(*debug_out)), "Using directory \"%.100s\" for auxiliary files\n", buf));
1317 strncat(buf, "NEWSRC", sizeof(buf)-1-strlen(buf));
1319 if(!(p = (void *) mail_parameters(NULL, GET_NEWSRC, (void *)NULL))
1320 || can_access(p, ACCESS_EXISTS) < 0
1321 || can_access(buf, ACCESS_EXISTS) == 0){
1322 mail_parameters(NULL, SET_NEWSRC, (void *)buf);
1323 GLO_NEWSRC_PATH = cpystr(buf);
1325 else
1326 GLO_NEWSRC_PATH = cpystr(p);
1328 if(ps->pconf){
1329 mprint(2, (db, DSIZE-(db-(*debug_out)), "Global config \"%.100s\" comes from command line\n",
1330 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1332 else{
1333 mprint(2, (db, DSIZE-(db-(*debug_out)),
1334 "Global config not set on cmdline, checking for $PINECONF\n"));
1337 if(!ps->pconf && (p = getenv("PINECONF"))){
1338 ps->pconf = new_pinerc_s(p);
1339 if(ps->pconf){
1340 mprint(2, (db, DSIZE-(db-(*debug_out)),
1341 " yes, global config \"%.100s\" comes from $PINECONF\n",
1342 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1345 #ifdef _WINDOWS
1346 else if(!ps->pconf
1347 && mswin_reg(MSWR_OP_GET, MSWR_PINE_CONF, buf2, sizeof(buf2))){
1348 ps->pconf = new_pinerc_s(buf2);
1349 if(ps->pconf){
1350 mprint(2, (db, DSIZE-(db-(*debug_out)),
1351 " yes, global config \"%.100s\" comes from Registry\n",
1352 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1355 #endif
1356 if(!ps->pconf){
1357 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, there is no global config\n"));
1359 #ifdef _WINDOWS
1360 else if (ps->pconf && ps->pconf->name &&
1361 (ps->update_registry != UREG_NEVER_SET)){
1362 mswin_reg(MSWR_OP_SET | ((ps->update_registry == UREG_ALWAYS_SET)
1363 ? MSWR_OP_FORCE : 0),
1364 MSWR_PINE_CONF,
1365 ps->pconf->name, (size_t)NULL);
1367 #endif
1369 if(!ps->prc)
1370 ps->prc = new_pinerc_s(ps->pinerc);
1372 if(ps->exceptions){
1373 mprint(2, (db, DSIZE-(db-(*debug_out)),
1374 "Exceptions config \"%.100s\" comes from command line\n",
1375 ps->exceptions));
1377 else{
1378 mprint(2, (db, DSIZE-(db-(*debug_out)),
1379 "Exceptions config not set on cmdline, checking for $PINERCEX\n"));
1383 * Exceptions is done slightly differently from pinerc. Instead of setting
1384 * post_prc in args.c we just set the string and use it here. We do
1385 * that so that we can put it in the same directory as the pinerc if
1386 * exceptions is a relative name, and pinerc may not be set until here.
1388 * First, just like for pinerc, check environment variable if it wasn't
1389 * set on the command line.
1391 if(!ps->exceptions && (p = getenv("PINERCEX")) && *p){
1392 ps->exceptions = cpystr(p);
1393 if(ps->exceptions){
1394 mprint(2, (db, DSIZE-(db-(*debug_out)),
1395 " yes, exceptions config \"%.100s\" comes from $PINERCEX\n",
1396 ps->exceptions));
1401 * If still not set, try specific file in same dir as pinerc.
1402 * Only use it if the file exists.
1404 if(!ps->exceptions){
1405 p = last_cmpnt(ps->pinerc);
1406 buf[0] = '\0';
1407 if(p != NULL){
1408 strncpy(buf, ps->pinerc, MIN(p - ps->pinerc, sizeof(buf)-1));
1409 buf[MIN(p - ps->pinerc, sizeof(buf)-1)] = '\0';
1412 strncat(buf, "PINERCEX", sizeof(buf)-1-strlen(buf));
1414 mprint(2, (db, DSIZE-(db-(*debug_out)),
1415 " no, checking for default \"%.100s\" in pinerc dir\n", buf));
1416 if(can_access(buf, ACCESS_EXISTS) == 0) /* found it! */
1417 ps->exceptions = cpystr(buf);
1419 if(ps->exceptions){
1420 mprint(2, (db, DSIZE-(db-(*debug_out)),
1421 " yes, exceptions config \"%.100s\" comes from default\n",
1422 ps->exceptions));
1424 else{
1425 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, there is no exceptions config\n"));
1429 #else /* unix */
1431 if(ps->pconf){
1432 mprint(2, (db, DSIZE-(db-(*debug_out)), "Global config \"%.100s\" comes from command line\n",
1433 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1436 if(!ps->pconf){
1437 ps->pconf = new_pinerc_s(SYSTEM_PINERC);
1438 if(ps->pconf){
1439 mprint(2, (db, DSIZE-(db-(*debug_out)), "Global config \"%.100s\" is default\n",
1440 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1444 if(!ps->pconf){
1445 mprint(2, (db, DSIZE-(db-(*debug_out)), "No global config!\n"));
1448 if(ps->prc){
1449 mprint(2, (db, DSIZE-(db-(*debug_out)), "Personal config \"%.100s\" comes from command line\n",
1450 (ps->prc && ps->prc->name) ? ps->prc->name : "<no name>"));
1453 if(!ps->pinerc){
1454 build_path(buf, ps->home_dir, ".pinerc", sizeof(buf));
1455 ps->pinerc = cpystr(buf);
1458 if(!ps->prc){
1459 ps->prc = new_pinerc_s(ps->pinerc);
1460 if(ps->prc){
1461 mprint(2, (db, DSIZE-(db-(*debug_out)), "Personal config \"%.100s\" is default\n",
1462 (ps->prc && ps->prc->name) ? ps->prc->name : "<no name>"));
1466 if(!ps->prc){
1467 mprint(2, (db, DSIZE-(db-(*debug_out)), "No personal config!\n"));
1470 if(ps->exceptions){
1471 mprint(2, (db, DSIZE-(db-(*debug_out)),
1472 "Exceptions config \"%.100s\" comes from command line\n",
1473 ps->exceptions));
1477 * If not set, try specific file in same dir as pinerc.
1478 * Only use it if the file exists.
1480 if(!ps->exceptions){
1481 p = last_cmpnt(ps->pinerc);
1482 buf[0] = '\0';
1483 if(p != NULL){
1484 strncpy(buf, ps->pinerc, MIN(p - ps->pinerc, sizeof(buf)-1));
1485 buf[MIN(p - ps->pinerc, sizeof(buf)-1)] = '\0';
1488 strncat(buf, ".pinercex", sizeof(buf)-1-strlen(buf));
1489 mprint(2, (db, DSIZE-(db-(*debug_out)), "Exceptions config not set on cmdline\n checking for default \"%.100s\" in pinerc dir\n", buf));
1491 if(can_access(buf, ACCESS_EXISTS) == 0) /* found it! */
1492 ps->exceptions = cpystr(buf);
1494 if(ps->exceptions){
1495 mprint(2, (db, DSIZE-(db-(*debug_out)),
1496 " yes, exceptions config \"%.100s\" is default\n",
1497 ps->exceptions));
1499 else{
1500 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, there is no exceptions config\n"));
1504 #endif /* unix */
1506 if(ps->exceptions){
1508 if(!IS_REMOTE(ps->exceptions) &&
1509 !is_absolute_path(ps->exceptions)){
1510 #if defined(DOS) || defined(OS2)
1511 p = last_cmpnt(ps->pinerc);
1512 buf[0] = '\0';
1513 if(p != NULL){
1514 strncpy(buf, ps->pinerc, MIN(p - ps->pinerc, sizeof(buf)-1));
1515 buf[MIN(p - ps->pinerc, sizeof(buf)-1)] = '\0';
1518 strncat(buf, ps->exceptions, sizeof(buf)-1-strlen(buf));
1519 #else
1520 build_path(buf, ps->home_dir, ps->exceptions, sizeof(buf));
1521 #endif
1523 else{
1524 strncpy(buf, ps->exceptions, sizeof(buf)-1);
1525 buf[sizeof(buf)-1] = '\0';
1528 ps->post_prc = new_pinerc_s(buf);
1530 fs_give((void **)&ps->exceptions);
1533 mprint(2, (db, DSIZE-(db-(*debug_out)), "\n Global config: %.100s\n",
1534 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<none>"));
1535 mprint(2, (db, DSIZE-(db-(*debug_out)), " Personal config: %.100s\n",
1536 (ps->prc && ps->prc->name) ? ps->prc->name : "<none>"));
1537 mprint(2, (db, DSIZE-(db-(*debug_out)), " Exceptions config: %.100s\n",
1538 (ps->post_prc && ps->post_prc->name) ? ps->post_prc->name
1539 : "<none>"));
1540 #if !defined(DOS) && !defined(OS2)
1541 if(SYSTEM_PINERC_FIXED){
1542 mprint(2, (db, DSIZE-(db-(*debug_out)), " Fixed config: %.100s\n", SYSTEM_PINERC_FIXED));
1544 #endif
1546 mprint(2, (db, DSIZE-(db-(*debug_out)), "\n"));
1550 /*----------------------------------------------------------------------
1551 Initialize the variables
1553 Args: ps -- The usual pine structure
1555 Result:
1557 This reads the system pine configuration file and the user's pine
1558 configuration file ".pinerc" and places the results in the variables
1559 structure. It sorts out what was read and sets a few other variables
1560 based on the contents.
1561 ----*/
1562 void
1563 init_vars(struct pine *ps, void (*cmds_f) (struct pine *, char **))
1565 char buf[MAXPATH+1], *p, *q, **s;
1566 register struct variable *vars = ps->vars;
1567 int obs_header_in_reply = 0, /* the obs_ variables are to */
1568 obs_old_style_reply = 0, /* support backwards compatibility */
1569 obs_save_by_sender, i, def_sort_rev;
1570 long rvl;
1571 PINERC_S *fixedprc = NULL;
1572 FeatureLevel obs_feature_level;
1573 char *fromcharset = NULL;
1574 char *err = NULL;
1576 dprint((5, "init_vars:\n"));
1578 /*--- The defaults here are defined in os-xxx.h so they can vary
1579 per machine ---*/
1581 GLO_PRINTER = cpystr(DF_DEFAULT_PRINTER);
1582 GLO_ELM_STYLE_SAVE = cpystr(DF_ELM_STYLE_SAVE);
1583 GLO_SAVE_BY_SENDER = cpystr(DF_SAVE_BY_SENDER);
1584 GLO_HEADER_IN_REPLY = cpystr(DF_HEADER_IN_REPLY);
1585 GLO_INBOX_PATH = cpystr("inbox");
1586 GLO_DEFAULT_FCC = cpystr(DF_DEFAULT_FCC);
1587 GLO_DEFAULT_SAVE_FOLDER = cpystr(DEFAULT_SAVE);
1588 GLO_POSTPONED_FOLDER = cpystr(POSTPONED_MSGS);
1589 GLO_TRASH_FOLDER = cpystr(TRASH_FOLDER);
1590 GLO_USE_ONLY_DOMAIN_NAME = cpystr(DF_USE_ONLY_DOMAIN_NAME);
1591 GLO_FEATURE_LEVEL = cpystr("sappling");
1592 GLO_OLD_STYLE_REPLY = cpystr(DF_OLD_STYLE_REPLY);
1593 GLO_SORT_KEY = cpystr(DF_SORT_KEY);
1594 GLO_SAVED_MSG_NAME_RULE = cpystr(DF_SAVED_MSG_NAME_RULE);
1595 GLO_FCC_RULE = cpystr(DF_FCC_RULE);
1596 GLO_AB_SORT_RULE = cpystr(DF_AB_SORT_RULE);
1597 GLO_FLD_SORT_RULE = cpystr(DF_FLD_SORT_RULE);
1598 GLO_SIGNATURE_FILE = cpystr(DF_SIGNATURE_FILE);
1599 GLO_MAIL_DIRECTORY = cpystr(DF_MAIL_DIRECTORY);
1600 GLO_REMOTE_ABOOK_HISTORY = cpystr(DF_REMOTE_ABOOK_HISTORY);
1601 GLO_REMOTE_ABOOK_VALIDITY = cpystr(DF_REMOTE_ABOOK_VALIDITY);
1602 GLO_GOTO_DEFAULT_RULE = cpystr(DF_GOTO_DEFAULT_RULE);
1603 GLO_INCOMING_STARTUP = cpystr(DF_INCOMING_STARTUP);
1604 GLO_PRUNING_RULE = cpystr(DF_PRUNING_RULE);
1605 GLO_REOPEN_RULE = cpystr(DF_REOPEN_RULE);
1606 GLO_THREAD_DISP_STYLE = cpystr(DF_THREAD_DISP_STYLE);
1607 GLO_THREAD_INDEX_STYLE = cpystr(DF_THREAD_INDEX_STYLE);
1608 GLO_THREAD_MORE_CHAR = cpystr(DF_THREAD_MORE_CHAR);
1609 GLO_THREAD_EXP_CHAR = cpystr(DF_THREAD_EXP_CHAR);
1610 GLO_THREAD_LASTREPLY_CHAR = cpystr(DF_THREAD_LASTREPLY_CHAR);
1611 GLO_BUGS_FULLNAME = cpystr("Sorry No Address");
1612 GLO_BUGS_ADDRESS = cpystr("nobody");
1613 GLO_SUGGEST_FULLNAME = cpystr("Sorry No Address");
1614 GLO_SUGGEST_ADDRESS = cpystr("nobody");
1615 GLO_LOCAL_FULLNAME = cpystr(DF_LOCAL_FULLNAME);
1616 GLO_LOCAL_ADDRESS = cpystr(DF_LOCAL_ADDRESS);
1617 GLO_OVERLAP = cpystr(DF_OVERLAP);
1618 GLO_MAXREMSTREAM = cpystr(DF_MAXREMSTREAM);
1619 GLO_MARGIN = cpystr(DF_MARGIN);
1620 GLO_FILLCOL = cpystr(DF_FILLCOL);
1621 GLO_DEADLETS = cpystr(DF_DEADLETS);
1622 GLO_NMW_WIDTH = cpystr(DF_NMW_WIDTH);
1623 GLO_REPLY_STRING = cpystr("> ");
1624 GLO_REPLY_INTRO = cpystr(DEFAULT_REPLY_INTRO);
1625 GLO_EMPTY_HDR_MSG = cpystr("undisclosed-recipients");
1626 GLO_STATUS_MSG_DELAY = cpystr("0");
1627 GLO_ACTIVE_MSG_INTERVAL = cpystr("12");
1628 GLO_USERINPUTTIMEO = cpystr("0");
1629 GLO_INCCHECKTIMEO = cpystr("5");
1630 GLO_INCCHECKINTERVAL = cpystr("180");
1631 GLO_INC2NDCHECKINTERVAL = cpystr("180");
1632 GLO_MAILCHECK = cpystr(DF_MAILCHECK);
1633 GLO_MAILCHECKNONCURR = cpystr("0");
1634 GLO_MAILDROPCHECK = cpystr(DF_MAILDROPCHECK);
1635 GLO_NNTPRANGE = cpystr("0");
1636 GLO_KBLOCK_PASSWD_COUNT = cpystr(DF_KBLOCK_PASSWD_COUNT);
1637 GLO_INDEX_COLOR_STYLE = cpystr("flip-colors");
1638 GLO_TITLEBAR_COLOR_STYLE = cpystr("default");
1639 GLO_POST_CHAR_SET = cpystr("UTF-8");
1640 #ifdef DF_FOLDER_EXTENSION
1641 GLO_FOLDER_EXTENSION = cpystr(DF_FOLDER_EXTENSION);
1642 #endif
1643 #ifdef DF_SMTP_SERVER
1644 GLO_SMTP_SERVER = parse_list(DF_SMTP_SERVER, 1,
1645 PL_REMSURRQUOT, NULL);
1646 #endif
1648 #ifdef DF_SSHPATH
1649 GLO_SSHPATH = cpystr(DF_SSHPATH);
1650 #endif
1651 #ifdef DF_SSHCMD
1652 GLO_SSHCMD = cpystr(DF_SSHCMD);
1653 #endif
1655 #ifndef _WINDOWS
1656 GLO_COLOR_STYLE = cpystr("no-color");
1657 GLO_NORM_FORE_COLOR = cpystr(DEFAULT_NORM_FORE_RGB);
1658 GLO_NORM_BACK_COLOR = cpystr(DEFAULT_NORM_BACK_RGB);
1659 #endif
1660 GLO_TITLE_FORE_COLOR = cpystr(DEFAULT_TITLE_FORE_RGB);
1661 GLO_TITLE_BACK_COLOR = cpystr(DEFAULT_TITLE_BACK_RGB);
1662 GLO_TITLECLOSED_FORE_COLOR = cpystr(DEFAULT_TITLECLOSED_FORE_RGB);
1663 GLO_TITLECLOSED_BACK_COLOR = cpystr(DEFAULT_TITLECLOSED_BACK_RGB);
1664 GLO_FOLDER_FORE_COLOR = cpystr(DEFAULT_NORM_FORE_RGB);
1665 GLO_DIRECTORY_FORE_COLOR = cpystr(DEFAULT_NORM_FORE_RGB);
1666 GLO_FOLDER_LIST_FORE_COLOR = cpystr(DEFAULT_NORM_FORE_RGB);
1667 GLO_METAMSG_FORE_COLOR = cpystr(DEFAULT_METAMSG_FORE_RGB);
1668 GLO_METAMSG_BACK_COLOR = cpystr(DEFAULT_METAMSG_BACK_RGB);
1669 GLO_QUOTE1_FORE_COLOR = cpystr(DEFAULT_QUOTE1_FORE_RGB);
1670 GLO_QUOTE1_BACK_COLOR = cpystr(DEFAULT_QUOTE1_BACK_RGB);
1671 GLO_QUOTE2_FORE_COLOR = cpystr(DEFAULT_QUOTE2_FORE_RGB);
1672 GLO_QUOTE2_BACK_COLOR = cpystr(DEFAULT_QUOTE2_BACK_RGB);
1673 GLO_QUOTE3_FORE_COLOR = cpystr(DEFAULT_QUOTE3_FORE_RGB);
1674 GLO_QUOTE3_BACK_COLOR = cpystr(DEFAULT_QUOTE3_BACK_RGB);
1675 GLO_SIGNATURE_FORE_COLOR = cpystr(DEFAULT_SIGNATURE_FORE_RGB);
1676 GLO_SIGNATURE_BACK_COLOR = cpystr(DEFAULT_SIGNATURE_BACK_RGB);
1677 GLO_IND_PLUS_FORE_COLOR = cpystr(DEFAULT_IND_PLUS_FORE_RGB);
1678 GLO_IND_PLUS_BACK_COLOR = cpystr(DEFAULT_IND_PLUS_BACK_RGB);
1679 GLO_IND_IMP_FORE_COLOR = cpystr(DEFAULT_IND_IMP_FORE_RGB);
1680 GLO_IND_IMP_BACK_COLOR = cpystr(DEFAULT_IND_IMP_BACK_RGB);
1681 GLO_IND_ANS_FORE_COLOR = cpystr(DEFAULT_IND_ANS_FORE_RGB);
1682 GLO_IND_ANS_BACK_COLOR = cpystr(DEFAULT_IND_ANS_BACK_RGB);
1683 GLO_IND_NEW_FORE_COLOR = cpystr(DEFAULT_IND_NEW_FORE_RGB);
1684 GLO_IND_NEW_BACK_COLOR = cpystr(DEFAULT_IND_NEW_BACK_RGB);
1685 GLO_IND_OP_FORE_COLOR = cpystr(DEFAULT_IND_OP_FORE_RGB);
1686 GLO_IND_OP_BACK_COLOR = cpystr(DEFAULT_IND_OP_BACK_RGB);
1687 GLO_VIEW_MARGIN_LEFT = cpystr("0");
1688 GLO_VIEW_MARGIN_RIGHT = cpystr(DF_VIEW_MARGIN_RIGHT);
1689 GLO_QUOTE_SUPPRESSION = cpystr(DF_QUOTE_SUPPRESSION);
1690 GLO_KW_BRACES = cpystr("\"{\" \"} \"");
1691 GLO_OPENING_SEP = cpystr(" - ");
1692 GLO_WP_INDEXHEIGHT = cpystr("24");
1693 GLO_WP_AGGSTATE = cpystr("1");
1694 GLO_WP_STATE = cpystr("");
1695 #ifdef DF_VAR_SPELLER
1696 GLO_SPELLER = cpystr(DF_VAR_SPELLER);
1697 #endif
1698 #ifdef SMIME
1699 GLO_PUBLICCERT_DIR = cpystr(DF_PUBLICCERT_DIR);
1700 GLO_PRIVATEKEY_DIR = cpystr(DF_PRIVATEKEY_DIR);
1701 GLO_CACERT_DIR = cpystr(DF_CACERT_DIR);
1702 #endif /* SMIME */
1705 * Default first value for addrbook list if none set.
1706 * We also want to be sure to set global_val to the default
1707 * if is_fixed, so that address-book= will cause the default to happen.
1709 if(!GLO_ADDRESSBOOK && !FIX_ADDRESSBOOK)
1710 GLO_ADDRESSBOOK = parse_list(DF_ADDRESSBOOK, 1, 0, NULL);
1713 * Default first value if none set.
1715 if(!GLO_STANDARD_PRINTER && !FIX_STANDARD_PRINTER)
1716 GLO_STANDARD_PRINTER = parse_list(DF_STANDARD_PRINTER, 1, 0, NULL);
1719 * Defining this default sshpath should cause ssh to be preferred over rsh
1720 * when attempting imapd preauth calls.
1722 #ifdef DF_SSHPATH
1723 if(DF_SSHPATH
1724 && is_absolute_path(DF_SSHPATH)
1725 && can_access(DF_SSHPATH, EXECUTE_ACCESS) == 0){
1726 mail_parameters(NULL, SET_SSHPATH, (void *) DF_SSHPATH);
1728 #endif
1730 * It isn't usually necessary to define this.
1732 #ifdef DF_SSHCMD
1733 if(DF_SSHCMD){
1734 mail_parameters(NULL, SET_SSHCOMMAND, (void *) DF_SSHCMD);
1736 #endif
1738 #if !defined(DOS) && !defined(OS2)
1740 * This is here instead of in init_pinerc so that we can get by without
1741 * having a global fixedprc, since we don't need it anymore after this.
1743 fixedprc = new_pinerc_s(SYSTEM_PINERC_FIXED);
1744 #endif
1746 if(ps->pconf){
1747 read_pinerc(ps->pconf, vars, ParseGlobal);
1748 if(ps->pconf->type != Loc)
1749 rd_close_remote(ps->pconf->rd);
1752 if(ps->prc){
1753 read_pinerc(ps->prc, vars, ParsePers);
1754 if(ps->prc->type != Loc)
1755 rd_close_remote(ps->prc->rd);
1758 if(ps->post_prc){
1759 read_pinerc(ps->post_prc, vars, ParsePersPost);
1760 if(ps->post_prc->type != Loc)
1761 rd_close_remote(ps->post_prc->rd);
1764 if(fixedprc){
1765 read_pinerc(fixedprc, vars, ParseFixed);
1766 free_pinerc_s(&fixedprc);
1769 ps->ew_for_except_vars = ps->post_prc ? Post : Main;
1771 if(ps->exit_if_no_pinerc && ps->first_time_user){
1773 /* TRANSLATORS: -bail is a literal option name, don't change it. */
1774 exceptional_exit(_("Exiting because -bail option is set and config file doesn't exist."), -1);
1778 * Convert everything having to do with the config to UTF-8
1779 * in order to avoid having to worry about it all over the
1780 * place.
1781 * Set the character-set first so that we may use that in
1782 * the conversion process.
1784 set_collation(0, 1);
1786 #ifndef _WINDOWS
1787 #if (HAVE_LANGINFO_H && defined(CODESET))
1789 if(output_charset_is_supported(nl_langinfo_codeset_wrapper()))
1790 ps->GLO_CHAR_SET = cpystr(nl_langinfo_codeset_wrapper());
1791 else{
1792 ps->GLO_CHAR_SET = cpystr("UTF-8");
1793 dprint((1,"nl_langinfo(CODESET) returns unrecognized value=\"%s\", using UTF-8 as default\n", (p=nl_langinfo(CODESET)) ? p : ""));
1795 #else
1796 ps->GLO_CHAR_SET = cpystr("UTF-8");
1797 #endif
1799 set_current_val(&vars[V_CHAR_SET], TRUE, TRUE);
1800 set_current_val(&vars[V_OLD_CHAR_SET], TRUE, TRUE);
1801 set_current_val(&vars[V_KEY_CHAR_SET], TRUE, TRUE);
1802 #endif /* ! _WINDOWS */
1804 set_current_val(&vars[V_POST_CHAR_SET], TRUE, TRUE);
1807 * Also set up the feature list because we need the
1808 * Use-System-Translation feature to set up the charmaps.
1811 /* way obsolete, backwards compatibility */
1812 set_current_val(&vars[V_FEATURE_LEVEL], TRUE, TRUE);
1813 if(strucmp(VAR_FEATURE_LEVEL, "seedling") == 0)
1814 obs_feature_level = Seedling;
1815 else if(strucmp(VAR_FEATURE_LEVEL, "old-growth") == 0)
1816 obs_feature_level = Seasoned;
1817 else
1818 obs_feature_level = Sapling;
1820 /* obsolete, backwards compatibility */
1821 set_current_val(&vars[V_OLD_STYLE_REPLY], TRUE, TRUE);
1822 obs_old_style_reply = !strucmp(VAR_OLD_STYLE_REPLY, "yes");
1824 set_feature_list_current_val(&vars[V_FEATURE_LIST]);
1825 process_feature_list(ps, VAR_FEATURE_LIST,
1826 (obs_feature_level == Seasoned) ? 1 : 0,
1827 obs_header_in_reply, obs_old_style_reply);
1831 * Redo set_collation call with correct value for collation,
1832 * but we're hardwiring ctype on now. That's because nl_langinfo()
1833 * call needs it and system-dependent wcwidth and wcrtomb functions
1834 * need it.
1836 set_collation(F_OFF(F_DISABLE_SETLOCALE_COLLATE, ps_global), 1);
1839 * Set up to send the correct sequence of bytes to the display terminal.
1842 if(reset_character_set_stuff(&err) == -1)
1843 panic(err ? err : "trouble with character set setup");
1844 else if(err){
1845 init_error(ps, SM_ORDER | SM_DING, 3, 5, err);
1846 fs_give((void **) &err);
1850 * Now we use the configvars from above to convert the rest
1851 * to UTF-8. That should be ok because the ones above should
1852 * be ASCII.
1854 if(ps->keyboard_charmap && strucmp(ps->keyboard_charmap, "UTF-8")
1855 && strucmp(ps->keyboard_charmap, "US-ASCII"))
1856 fromcharset = ps->keyboard_charmap;
1857 else if(ps->display_charmap && strucmp(ps->display_charmap, "UTF-8")
1858 && strucmp(ps->display_charmap, "US-ASCII"))
1859 fromcharset = ps->display_charmap;
1860 #ifndef _WINDOWS
1861 else if(VAR_OLD_CHAR_SET && strucmp(VAR_OLD_CHAR_SET, "UTF-8")
1862 && strucmp(VAR_OLD_CHAR_SET, "US-ASCII"))
1863 fromcharset = VAR_OLD_CHAR_SET;
1864 #endif /* ! _WINDOWS */
1866 convert_configvars_to_utf8(vars, fromcharset);
1869 * If we already set this while reading the remote pinerc, don't
1870 * change it.
1872 if(!VAR_REMOTE_ABOOK_METADATA || !VAR_REMOTE_ABOOK_METADATA[0])
1873 set_current_val(&vars[V_REMOTE_ABOOK_METADATA], TRUE, TRUE);
1876 * mail-directory variable is obsolete, put its value in
1877 * default folder-collection list
1879 set_current_val(&vars[V_MAIL_DIRECTORY], TRUE, TRUE);
1880 if(!GLO_FOLDER_SPEC){
1881 build_path(tmp_20k_buf, VAR_MAIL_DIRECTORY, "[]", SIZEOF_20KBUF);
1882 GLO_FOLDER_SPEC = parse_list(tmp_20k_buf, 1, 0, NULL);
1885 set_current_val(&vars[V_FOLDER_SPEC], TRUE, TRUE);
1887 set_current_val(&vars[V_NNTP_SERVER], TRUE, TRUE);
1888 for(i = 0; VAR_NNTP_SERVER && VAR_NNTP_SERVER[i]; i++)
1889 removing_quotes(VAR_NNTP_SERVER[i]);
1891 set_news_spec_current_val(TRUE, TRUE);
1893 set_current_val(&vars[V_INBOX_PATH], TRUE, TRUE);
1895 set_current_val(&vars[V_USER_DOMAIN], TRUE, TRUE);
1896 if(VAR_USER_DOMAIN
1897 && VAR_USER_DOMAIN[0]
1898 && (p = strrindex(VAR_USER_DOMAIN, '@'))){
1899 if(*(++p)){
1900 char *q;
1902 snprintf(tmp_20k_buf, SIZEOF_20KBUF,
1903 "User-domain (%s) cannot contain \"@\", using \"%s\"",
1904 VAR_USER_DOMAIN, p);
1905 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
1906 q = VAR_USER_DOMAIN;
1907 while((*q++ = *p++) != '\0')
1908 ;/* do nothing */
1910 else{
1911 snprintf(tmp_20k_buf, SIZEOF_20KBUF,
1912 "User-domain (%s) cannot contain \"@\", deleting",
1913 VAR_USER_DOMAIN);
1914 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
1915 if(ps->vars[V_USER_DOMAIN].post_user_val.p){
1916 fs_give((void **)&ps->vars[V_USER_DOMAIN].post_user_val.p);
1917 set_current_val(&vars[V_USER_DOMAIN], TRUE, TRUE);
1920 if(VAR_USER_DOMAIN
1921 && VAR_USER_DOMAIN[0]
1922 && (p = strrindex(VAR_USER_DOMAIN, '@'))){
1923 if(ps->vars[V_USER_DOMAIN].main_user_val.p){
1924 fs_give((void **)&ps->vars[V_USER_DOMAIN].main_user_val.p);
1925 set_current_val(&vars[V_USER_DOMAIN], TRUE, TRUE);
1931 set_current_val(&vars[V_USE_ONLY_DOMAIN_NAME], TRUE, TRUE);
1932 set_current_val(&vars[V_REPLY_STRING], TRUE, TRUE);
1933 set_current_val(&vars[V_WORDSEPS], TRUE, TRUE);
1934 set_current_val(&vars[V_QUOTE_REPLACE_STRING], TRUE, TRUE);
1935 set_current_val(&vars[V_REPLY_INTRO], TRUE, TRUE);
1936 set_current_val(&vars[V_EMPTY_HDR_MSG], TRUE, TRUE);
1938 #ifdef ENABLE_LDAP
1939 set_current_val(&vars[V_LDAP_SERVERS], TRUE, TRUE);
1940 #endif /* ENABLE_LDAP */
1942 /* obsolete, backwards compatibility */
1943 set_current_val(&vars[V_HEADER_IN_REPLY], TRUE, TRUE);
1944 obs_header_in_reply=!strucmp(VAR_HEADER_IN_REPLY, "yes");
1946 set_current_val(&vars[V_PERSONAL_PRINT_COMMAND], TRUE, TRUE);
1947 set_current_val(&vars[V_STANDARD_PRINTER], TRUE, TRUE);
1948 set_current_val(&vars[V_PRINTER], TRUE, TRUE);
1949 if(vars[V_PERSONAL_PRINT_COMMAND].is_fixed && !vars[V_PRINTER].is_fixed)
1950 printer_value_check_and_adjust();
1952 set_current_val(&vars[V_LAST_TIME_PRUNE_QUESTION], TRUE, TRUE);
1953 if(VAR_LAST_TIME_PRUNE_QUESTION != NULL){
1954 /* The month value in the file runs from 1-12, the variable here
1955 runs from 0-11; the value in the file used to be 0-11, but we're
1956 fixing it in January */
1957 ps->last_expire_year = atoi(VAR_LAST_TIME_PRUNE_QUESTION);
1958 ps->last_expire_month =
1959 atoi(strindex(VAR_LAST_TIME_PRUNE_QUESTION, '.') + 1);
1960 if(ps->last_expire_month == 0){
1961 /* Fix for 0 because of old bug */
1962 snprintf(buf, sizeof(buf), "%d.%d", ps_global->last_expire_year,
1963 ps_global->last_expire_month + 1);
1964 set_variable(V_LAST_TIME_PRUNE_QUESTION, buf, 1, 1, Main);
1965 }else{
1966 ps->last_expire_month--;
1968 }else{
1969 ps->last_expire_year = -1;
1970 ps->last_expire_month = -1;
1973 set_current_val(&vars[V_BUGS_FULLNAME], TRUE, TRUE);
1974 set_current_val(&vars[V_BUGS_ADDRESS], TRUE, TRUE);
1975 set_current_val(&vars[V_SUGGEST_FULLNAME], TRUE, TRUE);
1976 set_current_val(&vars[V_SUGGEST_ADDRESS], TRUE, TRUE);
1977 set_current_val(&vars[V_LOCAL_FULLNAME], TRUE, TRUE);
1978 set_current_val(&vars[V_LOCAL_ADDRESS], TRUE, TRUE);
1979 set_current_val(&vars[V_BUGS_EXTRAS], TRUE, TRUE);
1980 set_current_val(&vars[V_KBLOCK_PASSWD_COUNT], TRUE, TRUE);
1981 set_current_val(&vars[V_DEFAULT_FCC], TRUE, TRUE);
1982 set_current_val(&vars[V_POSTPONED_FOLDER], TRUE, TRUE);
1983 set_current_val(&vars[V_TRASH_FOLDER], TRUE, TRUE);
1984 set_current_val(&vars[V_READ_MESSAGE_FOLDER], TRUE, TRUE);
1985 set_current_val(&vars[V_FORM_FOLDER], TRUE, TRUE);
1986 set_current_val(&vars[V_EDITOR], TRUE, TRUE);
1987 set_current_val(&vars[V_SPELLER], TRUE, TRUE);
1988 set_current_val(&vars[V_IMAGE_VIEWER], TRUE, TRUE);
1989 set_current_val(&vars[V_BROWSER], TRUE, TRUE);
1990 set_current_val(&vars[V_SMTP_SERVER], TRUE, TRUE);
1991 set_current_val(&vars[V_COMP_HDRS], TRUE, TRUE);
1992 set_current_val(&vars[V_CUSTOM_HDRS], TRUE, TRUE);
1993 set_current_val(&vars[V_SENDMAIL_PATH], TRUE, TRUE);
1994 set_current_val(&vars[V_DISPLAY_FILTERS], TRUE, TRUE);
1995 set_current_val(&vars[V_SEND_FILTER], TRUE, TRUE);
1996 set_current_val(&vars[V_ALT_ADDRS], TRUE, TRUE);
1997 set_current_val(&vars[V_ABOOK_FORMATS], TRUE, TRUE);
1998 set_current_val(&vars[V_KW_BRACES], TRUE, TRUE);
1999 set_current_val(&vars[V_OPENING_SEP], TRUE, TRUE);
2000 set_current_val(&vars[V_UNK_CHAR_SET], TRUE, TRUE);
2001 #ifdef SMIME
2002 set_current_val(&vars[V_PUBLICCERT_DIR], TRUE, TRUE);
2003 set_current_val(&vars[V_PUBLICCERT_CONTAINER], TRUE, TRUE);
2004 set_current_val(&vars[V_PRIVATEKEY_DIR], TRUE, TRUE);
2005 set_current_val(&vars[V_PRIVATEKEY_CONTAINER], TRUE, TRUE);
2006 set_current_val(&vars[V_CACERT_DIR], TRUE, TRUE);
2007 set_current_val(&vars[V_CACERT_CONTAINER], TRUE, TRUE);
2008 #endif /* SMIME */
2010 set_current_val(&vars[V_KEYWORDS], TRUE, TRUE);
2011 ps_global->keywords = init_keyword_list(VAR_KEYWORDS);
2013 set_current_val(&vars[V_OPER_DIR], TRUE, TRUE);
2014 if(VAR_OPER_DIR && !VAR_OPER_DIR[0]){
2015 init_error(ps, SM_ORDER | SM_DING, 3, 5,
2016 "Setting operating-dir to the empty string is not allowed. Will be ignored.");
2017 fs_give((void **)&VAR_OPER_DIR);
2018 if(FIX_OPER_DIR)
2019 fs_give((void **)&FIX_OPER_DIR);
2020 if(GLO_OPER_DIR)
2021 fs_give((void **)&GLO_OPER_DIR);
2022 if(COM_OPER_DIR)
2023 fs_give((void **)&COM_OPER_DIR);
2024 if(ps_global->vars[V_OPER_DIR].post_user_val.p)
2025 fs_give((void **)&ps_global->vars[V_OPER_DIR].post_user_val.p);
2026 if(ps_global->vars[V_OPER_DIR].main_user_val.p)
2027 fs_give((void **)&ps_global->vars[V_OPER_DIR].main_user_val.p);
2030 set_current_val(&vars[V_PERSONAL_PRINT_CATEGORY], TRUE, TRUE);
2031 ps->printer_category = -1;
2032 if(VAR_PERSONAL_PRINT_CATEGORY != NULL)
2033 ps->printer_category = atoi(VAR_PERSONAL_PRINT_CATEGORY);
2035 if(ps->printer_category < 1 || ps->printer_category > 3){
2036 char **tt;
2037 char aname[100], wname[100];
2039 strncpy(aname, ANSI_PRINTER, sizeof(aname));
2040 aname[sizeof(aname)-1] = '\0';
2041 strncat(aname, "-no-formfeed", sizeof(aname)-strlen(aname)-1);
2042 strncpy(wname, WYSE_PRINTER, sizeof(wname));
2043 wname[sizeof(wname)-1] = '\0';
2044 strncat(wname, "-no-formfeed", sizeof(wname)-strlen(wname)-1);
2045 if(strucmp(VAR_PRINTER, ANSI_PRINTER) == 0
2046 || strucmp(VAR_PRINTER, aname) == 0
2047 || strucmp(VAR_PRINTER, WYSE_PRINTER) == 0
2048 || strucmp(VAR_PRINTER, wname) == 0)
2049 ps->printer_category = 1;
2050 else if(VAR_STANDARD_PRINTER && VAR_STANDARD_PRINTER[0]){
2051 for(tt = VAR_STANDARD_PRINTER; *tt; tt++)
2052 if(strucmp(VAR_PRINTER, *tt) == 0)
2053 break;
2055 if(*tt)
2056 ps->printer_category = 2;
2059 /* didn't find it yet */
2060 if(ps->printer_category < 1 || ps->printer_category > 3){
2061 if(VAR_PERSONAL_PRINT_COMMAND && VAR_PERSONAL_PRINT_COMMAND[0]){
2062 for(tt = VAR_PERSONAL_PRINT_COMMAND; *tt; tt++)
2063 if(strucmp(VAR_PRINTER, *tt) == 0)
2064 break;
2066 if(*tt)
2067 ps->printer_category = 3;
2072 set_current_val(&vars[V_OVERLAP], TRUE, TRUE);
2073 ps->viewer_overlap = i = atoi(DF_OVERLAP);
2074 if(SVAR_OVERLAP(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2075 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2076 else
2077 ps->viewer_overlap = i;
2079 set_current_val(&vars[V_MARGIN], TRUE, TRUE);
2080 ps->scroll_margin = i = atoi(DF_MARGIN);
2081 if(SVAR_MARGIN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2082 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2083 else
2084 ps->scroll_margin = i;
2086 set_current_val(&vars[V_FILLCOL], TRUE, TRUE);
2087 ps->composer_fillcol = i = atoi(DF_FILLCOL);
2088 if(SVAR_FILLCOL(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2089 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2090 else
2091 ps->composer_fillcol = i;
2093 set_current_val(&vars[V_QUOTE_SUPPRESSION], TRUE, TRUE);
2094 ps->quote_suppression_threshold = i = atoi(DF_QUOTE_SUPPRESSION);
2095 if(SVAR_QUOTE_SUPPRESSION(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2096 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2097 else{
2098 if(i > 0 && i < Q_SUPP_LIMIT){
2099 snprintf(tmp_20k_buf, SIZEOF_20KBUF,
2100 "Ignoring Quote-Suppression-Threshold value of %.50s, see help",
2101 VAR_QUOTE_SUPPRESSION);
2102 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2104 else{
2105 if(i < 0 && i != Q_DEL_ALL)
2106 ps->quote_suppression_threshold = -i;
2107 else
2108 ps->quote_suppression_threshold = i;
2112 set_current_val(&vars[V_DEADLETS], TRUE, TRUE);
2113 ps->deadlets = i = atoi(DF_DEADLETS);
2114 if(SVAR_DEADLETS(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2115 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2116 else
2117 ps->deadlets = i;
2119 set_current_val(&vars[V_STATUS_MSG_DELAY], TRUE, TRUE);
2120 ps->status_msg_delay = i = 0;
2121 if(SVAR_MSGDLAY(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2122 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2123 else
2124 ps->status_msg_delay = i;
2126 set_current_val(&vars[V_ACTIVE_MSG_INTERVAL], TRUE, TRUE);
2127 ps->active_status_interval = i = 8;
2128 if(SVAR_ACTIVEINTERVAL(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2129 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2130 else
2131 ps->active_status_interval = i;
2133 set_current_val(&vars[V_REMOTE_ABOOK_HISTORY], TRUE, TRUE);
2134 ps->remote_abook_history = i = atoi(DF_REMOTE_ABOOK_HISTORY);
2135 if(SVAR_AB_HIST(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2136 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2137 else
2138 ps->remote_abook_history = i;
2140 set_current_val(&vars[V_REMOTE_ABOOK_VALIDITY], TRUE, TRUE);
2141 ps->remote_abook_validity = i = atoi(DF_REMOTE_ABOOK_VALIDITY);
2142 if(SVAR_AB_VALID(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2143 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2144 else
2145 ps->remote_abook_validity = i;
2147 set_current_val(&vars[V_USERINPUTTIMEO], TRUE, TRUE);
2148 ps->hours_to_timeout = i = 0;
2149 if(SVAR_USER_INPUT(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2150 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2151 else
2152 ps->hours_to_timeout = i;
2154 /* timeo is a regular extern int because it is referenced in pico */
2155 set_current_val(&vars[V_MAILCHECK], TRUE, TRUE);
2156 set_input_timeout(i = 15);
2157 if(SVAR_MAILCHK(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2158 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2159 else
2160 set_input_timeout(i);
2162 set_current_val(&vars[V_MAILCHECKNONCURR], TRUE, TRUE);
2163 ps->check_interval_for_noncurr = i = 0;
2164 if(SVAR_MAILCHKNONCURR(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2165 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2166 else
2167 ps->check_interval_for_noncurr = i;
2169 #ifdef DEBUGJOURNAL
2170 ps->debugmem = 1;
2171 #else
2172 ps->debugmem = 0;
2173 #endif
2175 i = 30;
2176 set_current_val(&vars[V_TCPOPENTIMEO], TRUE, TRUE);
2177 /* this is just for the error, we don't save the result */
2178 if(VAR_TCPOPENTIMEO && SVAR_TCP_OPEN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2179 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2181 i = 15;
2182 set_current_val(&vars[V_TCPREADWARNTIMEO], TRUE, TRUE);
2183 /* this is just for the error, we don't save the result */
2184 if(VAR_TCPREADWARNTIMEO && SVAR_TCP_READWARN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2185 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2187 i = 0;
2188 set_current_val(&vars[V_TCPWRITEWARNTIMEO], TRUE, TRUE);
2189 /* this is just for the error, we don't save the result */
2190 if(VAR_TCPWRITEWARNTIMEO && SVAR_TCP_WRITEWARN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2191 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2193 i = 15;
2194 set_current_val(&vars[V_RSHOPENTIMEO], TRUE, TRUE);
2195 /* this is just for the error, we don't save the result */
2196 if(VAR_RSHOPENTIMEO && SVAR_RSH_OPEN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2197 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2199 i = 15;
2200 set_current_val(&vars[V_SSHOPENTIMEO], TRUE, TRUE);
2201 /* this is just for the error, we don't save the result */
2202 if(VAR_SSHOPENTIMEO && SVAR_SSH_OPEN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2203 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2205 set_current_val(&vars[V_INCCHECKLIST], TRUE, TRUE);
2207 set_current_val(&vars[V_INCCHECKTIMEO], TRUE, TRUE);
2208 ps->inc_check_timeout = i = 5;
2209 if(SVAR_INC_CHECK_TIMEO(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2210 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2211 else
2212 ps->inc_check_timeout = i;
2214 set_current_val(&vars[V_INCCHECKINTERVAL], TRUE, TRUE);
2215 ps->inc_check_interval = i = 180;
2216 if(SVAR_INC_CHECK_INTERV(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2217 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2218 else
2219 ps->inc_check_interval = i;
2221 set_current_val(&vars[V_INC2NDCHECKINTERVAL], TRUE, TRUE);
2222 ps->inc_second_check_interval = i = 180;
2223 if(SVAR_INC_2NDCHECK_INTERV(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2224 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2225 else
2226 ps->inc_second_check_interval = i;
2228 rvl = 60L;
2229 set_current_val(&vars[V_MAILDROPCHECK], TRUE, TRUE);
2230 /* this is just for the error, we don't save the result */
2231 if(VAR_MAILDROPCHECK && SVAR_MAILDCHK(ps, rvl, tmp_20k_buf, SIZEOF_20KBUF))
2232 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2234 rvl = 0L;
2235 set_current_val(&vars[V_NNTPRANGE], TRUE, TRUE);
2236 /* this is just for the error, we don't save the result */
2237 if(VAR_NNTPRANGE && SVAR_NNTPRANGE(ps, rvl, tmp_20k_buf, SIZEOF_20KBUF))
2238 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2240 set_current_val(&vars[V_TCPQUERYTIMEO], TRUE, TRUE);
2241 ps->tcp_query_timeout = i = TO_BAIL_THRESHOLD;
2242 if(VAR_TCPQUERYTIMEO && SVAR_TCP_QUERY(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2243 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2244 else
2245 ps->tcp_query_timeout = i;
2247 set_current_val(&vars[V_NEWSRC_PATH], TRUE, TRUE);
2248 if(VAR_NEWSRC_PATH && VAR_NEWSRC_PATH[0])
2249 mail_parameters(NULL, SET_NEWSRC, (void *)VAR_NEWSRC_PATH);
2251 set_current_val(&vars[V_NEWS_ACTIVE_PATH], TRUE, TRUE);
2252 if(VAR_NEWS_ACTIVE_PATH)
2253 mail_parameters(NULL, SET_NEWSACTIVE,
2254 (void *)VAR_NEWS_ACTIVE_PATH);
2256 set_current_val(&vars[V_NEWS_SPOOL_DIR], TRUE, TRUE);
2257 if(VAR_NEWS_SPOOL_DIR)
2258 mail_parameters(NULL, SET_NEWSSPOOL,
2259 (void *)VAR_NEWS_SPOOL_DIR);
2261 /* guarantee a save default */
2262 set_current_val(&vars[V_DEFAULT_SAVE_FOLDER], TRUE, TRUE);
2263 if(!VAR_DEFAULT_SAVE_FOLDER || !VAR_DEFAULT_SAVE_FOLDER[0])
2264 set_variable(V_DEFAULT_SAVE_FOLDER,
2265 (GLO_DEFAULT_SAVE_FOLDER && GLO_DEFAULT_SAVE_FOLDER[0])
2266 ? GLO_DEFAULT_SAVE_FOLDER
2267 : DEFAULT_SAVE, 1, 0, Main);
2269 set_current_val(&vars[V_SIGNATURE_FILE], TRUE, TRUE);
2270 set_current_val(&vars[V_LITERAL_SIG], TRUE, TRUE);
2271 set_current_val(&vars[V_GLOB_ADDRBOOK], TRUE, TRUE);
2272 set_current_val(&vars[V_ADDRESSBOOK], TRUE, TRUE);
2273 set_current_val(&vars[V_FORCED_ABOOK_ENTRY], TRUE, TRUE);
2274 set_current_val(&vars[V_DISABLE_DRIVERS], TRUE, TRUE);
2275 set_current_val(&vars[V_DISABLE_AUTHS], TRUE, TRUE);
2277 set_current_val(&vars[V_VIEW_HEADERS], TRUE, TRUE);
2278 /* strip spaces and colons */
2279 if(ps->VAR_VIEW_HEADERS){
2280 for(s = ps->VAR_VIEW_HEADERS; (q = *s) != NULL; s++){
2281 if(q[0]){
2282 removing_leading_white_space(q);
2283 /* look for colon or space or end */
2284 for(p = q; *p && !isspace((unsigned char)*p) && *p != ':'; p++)
2285 ;/* do nothing */
2287 *p = '\0';
2288 if(strucmp(q, ALL_EXCEPT) == 0)
2289 ps->view_all_except = 1;
2294 set_current_val(&vars[V_VIEW_MARGIN_LEFT], TRUE, TRUE);
2295 set_current_val(&vars[V_VIEW_MARGIN_RIGHT], TRUE, TRUE);
2296 set_current_val(&vars[V_UPLOAD_CMD], TRUE, TRUE);
2297 set_current_val(&vars[V_UPLOAD_CMD_PREFIX], TRUE, TRUE);
2298 set_current_val(&vars[V_DOWNLOAD_CMD], TRUE, TRUE);
2299 set_current_val(&vars[V_DOWNLOAD_CMD_PREFIX], TRUE, TRUE);
2300 set_current_val(&vars[V_MAILCAP_PATH], TRUE, TRUE);
2301 set_current_val(&vars[V_MIMETYPE_PATH], TRUE, TRUE);
2302 #if !defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)
2303 set_current_val(&vars[V_FIFOPATH], TRUE, TRUE);
2304 #endif
2306 set_current_val(&vars[V_RSHPATH], TRUE, TRUE);
2307 if(VAR_RSHPATH
2308 && is_absolute_path(VAR_RSHPATH)
2309 && can_access(VAR_RSHPATH, EXECUTE_ACCESS) == 0){
2310 mail_parameters(NULL, SET_RSHPATH, (void *) VAR_RSHPATH);
2313 set_current_val(&vars[V_RSHCMD], TRUE, TRUE);
2314 if(VAR_RSHCMD){
2315 mail_parameters(NULL, SET_RSHCOMMAND, (void *) VAR_RSHCMD);
2318 set_current_val(&vars[V_SSHPATH], TRUE, TRUE);
2319 if(VAR_SSHPATH) {
2320 if(is_absolute_path(VAR_SSHPATH)
2321 && can_access(VAR_SSHPATH, EXECUTE_ACCESS) == 0){
2322 mail_parameters(NULL, SET_SSHPATH, (void *) VAR_SSHPATH);
2324 else {
2325 mail_parameters(NULL, SET_SSHPATH, (void *) NULL);
2329 set_current_val(&vars[V_SSHCMD], TRUE, TRUE);
2330 if(VAR_SSHCMD) {
2331 if(VAR_SSHCMD[0]) {
2332 mail_parameters(NULL, SET_SSHCOMMAND, (void *) VAR_SSHCMD);
2334 else {
2335 mail_parameters(NULL, SET_SSHCOMMAND, (void *) NULL);
2339 #if defined(DOS) || defined(OS2)
2341 set_current_val(&vars[V_FILE_DIR], TRUE, TRUE);
2343 #ifdef _WINDOWS
2344 set_current_val(&vars[V_FONT_NAME], TRUE, TRUE);
2345 set_current_val(&vars[V_FONT_SIZE], TRUE, TRUE);
2346 set_current_val(&vars[V_FONT_STYLE], TRUE, TRUE);
2347 set_current_val(&vars[V_FONT_CHAR_SET], TRUE, TRUE);
2348 set_current_val(&vars[V_CURSOR_STYLE], TRUE, TRUE);
2349 set_current_val(&vars[V_WINDOW_POSITION], TRUE, TRUE);
2351 if(F_OFF(F_STORE_WINPOS_IN_CONFIG, ps_global)){
2352 /* if win position is in the registry, use it */
2353 if(mswin_reg(MSWR_OP_GET, MSWR_PINE_POS, buf, sizeof(buf))){
2354 if(VAR_WINDOW_POSITION)
2355 fs_give((void **)&VAR_WINDOW_POSITION);
2357 VAR_WINDOW_POSITION = cpystr(buf);
2359 else if(VAR_WINDOW_POSITION
2360 && (ps->update_registry != UREG_NEVER_SET)){
2361 /* otherwise, put it there */
2362 mswin_reg(MSWR_OP_SET | ((ps->update_registry == UREG_ALWAYS_SET)
2363 ? MSWR_OP_FORCE : 0),
2364 MSWR_PINE_POS,
2365 VAR_WINDOW_POSITION, (size_t)NULL);
2369 mswin_setwindow (VAR_FONT_NAME, VAR_FONT_SIZE,
2370 VAR_FONT_STYLE, VAR_WINDOW_POSITION,
2371 VAR_CURSOR_STYLE, VAR_FONT_CHAR_SET);
2373 /* this is no longer used */
2374 if(VAR_WINDOW_POSITION)
2375 fs_give((void **)&VAR_WINDOW_POSITION);
2377 set_current_val(&vars[V_PRINT_FONT_NAME], TRUE, TRUE);
2378 set_current_val(&vars[V_PRINT_FONT_SIZE], TRUE, TRUE);
2379 set_current_val(&vars[V_PRINT_FONT_STYLE], TRUE, TRUE);
2380 set_current_val(&vars[V_PRINT_FONT_CHAR_SET], TRUE, TRUE);
2381 mswin_setprintfont (VAR_PRINT_FONT_NAME,
2382 VAR_PRINT_FONT_SIZE,
2383 VAR_PRINT_FONT_STYLE,
2384 VAR_PRINT_FONT_CHAR_SET);
2386 mswin_setgenhelptextcallback(pcpine_general_help);
2388 mswin_setclosetext ("Use the \"Q\" command to exit Alpine.");
2391 char foreColor[64], backColor[64];
2393 mswin_getwindow(NULL, 0, NULL, 0, NULL, 0, NULL, 0,
2394 foreColor, sizeof(foreColor), backColor, sizeof(backColor),
2395 NULL, 0, NULL, 0);
2396 if(!GLO_NORM_FORE_COLOR)
2397 GLO_NORM_FORE_COLOR = cpystr(foreColor);
2399 if(!GLO_NORM_BACK_COLOR)
2400 GLO_NORM_BACK_COLOR = cpystr(backColor);
2402 #endif /* _WINDOWS */
2403 #endif /* DOS */
2406 * We want the version number to start out as 1.0 for Alpine, but
2407 * we also want to use the same old config file that was used
2408 * with Pine. The Pine version numbers made it up to 4.64 and we
2409 * want Alpine's 1.0 to be larger than 4.64 so we keep a separate
2410 * internal version number which is the real version number
2411 * plus 4. That's what gets written in LAST_VERS_USED.
2413 strncpy(ps->vers_internal, ALPINE_VERSION, sizeof(ps->vers_internal));
2414 ps->vers_internal[sizeof(ps->vers_internal)-1] = '\0';
2415 if(isdigit(ps->vers_internal[0]) && ps->vers_internal[0] < '6')
2416 ps->vers_internal[0] = ps->vers_internal[0] + 4;
2418 set_current_val(&vars[V_LAST_VERS_USED], TRUE, TRUE);
2419 /* Check for special cases first */
2420 if(VAR_LAST_VERS_USED
2421 && (isdigit(ps->vers_internal[0])
2422 && ps->vers_internal[1] == '.'
2423 && isdigit((unsigned char)ps->vers_internal[2])
2424 && isdigit((unsigned char)ps->vers_internal[3])
2425 && isalpha((unsigned char)ps->vers_internal[4])
2426 && strncmp(VAR_LAST_VERS_USED, ps->vers_internal, 4) >= 0)){
2427 ps->show_new_version = 0;
2429 /* Otherwise just do lexicographic comparision... */
2430 else if(VAR_LAST_VERS_USED
2431 && strcmp(VAR_LAST_VERS_USED, ps->vers_internal) >= 0){
2432 ps->show_new_version = 0;
2434 else{
2435 #ifdef _WINDOWS
2437 * If this is the first time we've run a version > 4.40, and there
2438 * is evidence that the config file has not been used by unix pine,
2439 * then we convert color008 to colorlgr, color009 to colormgr, and
2440 * color010 to colordgr. If the config file is being used by
2441 * unix pine then color009 may really supposed to be red, etc.
2442 * Same if we've already run 4.41 or higher. We don't have to do
2443 * anything if we are new to alpine.
2445 ps->pre441 = (VAR_LAST_VERS_USED
2446 && strcmp(VAR_LAST_VERS_USED, "4.40") <= 0);
2447 #endif /* _WINDOWS */
2450 * Don't offer the new version message if we're told not to.
2452 set_current_val(&vars[V_NEW_VER_QUELL], TRUE, TRUE);
2453 ps->show_new_version = !(VAR_NEW_VER_QUELL
2454 && strcmp(ps->vers_internal,
2455 VAR_NEW_VER_QUELL) < 0);
2457 #ifdef _WINDOWS
2458 if(!ps_global->install_flag)
2459 #endif /* _WINDOWS */
2461 if(VAR_LAST_VERS_USED){
2462 strncpy(ps_global->pine_pre_vers, VAR_LAST_VERS_USED,
2463 sizeof(ps_global->pine_pre_vers));
2464 ps_global->pine_pre_vers[sizeof(ps_global->pine_pre_vers)-1] = '\0';
2467 set_variable(V_LAST_VERS_USED, ps->vers_internal, 1, 1,
2468 ps_global->ew_for_except_vars);
2472 /* Obsolete, backwards compatibility */
2473 set_current_val(&vars[V_ELM_STYLE_SAVE], TRUE, TRUE);
2474 /* Also obsolete */
2475 set_current_val(&vars[V_SAVE_BY_SENDER], TRUE, TRUE);
2476 if(!strucmp(VAR_ELM_STYLE_SAVE, "yes"))
2477 set_variable(V_SAVE_BY_SENDER, "yes", 1, 1, Main);
2478 obs_save_by_sender = !strucmp(VAR_SAVE_BY_SENDER, "yes");
2480 set_current_pattern_vals(ps);
2482 set_current_val(&vars[V_INDEX_FORMAT], TRUE, TRUE);
2483 init_index_format(VAR_INDEX_FORMAT, &ps->index_disp_format);
2485 /* this should come after pre441 is set or not */
2486 set_current_color_vals(ps);
2488 set_current_val(&vars[V_RSS_NEWS], TRUE, TRUE);
2489 set_current_val(&vars[V_RSS_WEATHER], TRUE, TRUE);
2490 set_current_val(&vars[V_WP_INDEXHEIGHT], TRUE, TRUE);
2491 set_current_val(&vars[V_WP_INDEXLINES], TRUE, TRUE);
2492 set_current_val(&vars[V_WP_AGGSTATE], TRUE, TRUE);
2493 set_current_val(&vars[V_WP_STATE], TRUE, TRUE);
2494 set_current_val(&vars[V_WP_COLUMNS], TRUE, TRUE);
2496 set_current_val(&vars[V_PRUNED_FOLDERS], TRUE, TRUE);
2497 set_current_val(&vars[V_ARCHIVED_FOLDERS], TRUE, TRUE);
2498 set_current_val(&vars[V_INCOMING_FOLDERS], TRUE, TRUE);
2499 set_current_val(&vars[V_SORT_KEY], TRUE, TRUE);
2500 if(decode_sort(VAR_SORT_KEY, &ps->def_sort, &def_sort_rev) == -1){
2501 snprintf(tmp_20k_buf, SIZEOF_20KBUF, "Sort type \"%.200s\" is invalid", VAR_SORT_KEY);
2502 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2503 ps->def_sort = SortArrival;
2504 ps->def_sort_rev = 0;
2506 else
2507 ps->def_sort_rev = def_sort_rev;
2509 cur_rule_value(&vars[V_SAVED_MSG_NAME_RULE], TRUE, TRUE);
2510 {NAMEVAL_S *v; int i;
2511 for(i = 0; (v = save_msg_rules(i)); i++)
2512 if(v->value == ps_global->save_msg_rule)
2513 break;
2515 /* if save_msg_rule is not default, or is explicitly set to default */
2516 if((ps_global->save_msg_rule != SAV_RULE_DEFLT) ||
2517 (v && v->name &&
2518 (!strucmp(ps_global->vars[V_SAVED_MSG_NAME_RULE].post_user_val.p,
2519 v->name) ||
2520 !strucmp(ps_global->vars[V_SAVED_MSG_NAME_RULE].main_user_val.p,
2521 v->name))))
2522 obs_save_by_sender = 0; /* don't overwrite */
2525 cur_rule_value(&vars[V_FCC_RULE], TRUE, TRUE);
2526 cur_rule_value(&vars[V_AB_SORT_RULE], TRUE, TRUE);
2528 #ifndef _WINDOWS
2529 cur_rule_value(&vars[V_COLOR_STYLE], TRUE, TRUE);
2530 #endif
2532 cur_rule_value(&vars[V_INDEX_COLOR_STYLE], TRUE, TRUE);
2533 cur_rule_value(&vars[V_TITLEBAR_COLOR_STYLE], TRUE, TRUE);
2534 cur_rule_value(&vars[V_FLD_SORT_RULE], TRUE, TRUE);
2535 cur_rule_value(&vars[V_INCOMING_STARTUP], TRUE, TRUE);
2536 cur_rule_value(&vars[V_PRUNING_RULE], TRUE, TRUE);
2537 cur_rule_value(&vars[V_REOPEN_RULE], TRUE, TRUE);
2538 cur_rule_value(&vars[V_GOTO_DEFAULT_RULE], TRUE, TRUE);
2539 cur_rule_value(&vars[V_THREAD_DISP_STYLE], TRUE, TRUE);
2540 cur_rule_value(&vars[V_THREAD_INDEX_STYLE], TRUE, TRUE);
2542 set_current_val(&vars[V_THREAD_MORE_CHAR], TRUE, TRUE);
2543 if(VAR_THREAD_MORE_CHAR[0] && VAR_THREAD_MORE_CHAR[1]){
2544 init_error(ps, SM_ORDER | SM_DING, 3, 5,
2545 _("Only using first character of threading-indicator-character option"));
2546 VAR_THREAD_MORE_CHAR[1] = '\0';
2549 set_current_val(&vars[V_THREAD_EXP_CHAR], TRUE, TRUE);
2550 if(VAR_THREAD_EXP_CHAR[0] && VAR_THREAD_EXP_CHAR[1]){
2551 init_error(ps, SM_ORDER | SM_DING, 3, 5,
2552 _("Only using first character of threading-expanded-character option"));
2553 VAR_THREAD_EXP_CHAR[1] = '\0';
2556 set_current_val(&vars[V_THREAD_LASTREPLY_CHAR], TRUE, TRUE);
2557 if(!VAR_THREAD_LASTREPLY_CHAR[0])
2558 VAR_THREAD_LASTREPLY_CHAR = cpystr(DF_THREAD_LASTREPLY_CHAR);
2560 if(VAR_THREAD_LASTREPLY_CHAR[0] && VAR_THREAD_LASTREPLY_CHAR[1]){
2561 init_error(ps, SM_ORDER | SM_DING, 3, 5,
2562 _("Only using first character of threading-lastreply-character option"));
2563 VAR_THREAD_LASTREPLY_CHAR[1] = '\0';
2566 set_current_val(&vars[V_MAXREMSTREAM], TRUE, TRUE);
2567 ps->s_pool.max_remstream = i = atoi(DF_MAXREMSTREAM);
2568 if(SVAR_MAXREMSTREAM(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2569 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2570 else
2571 ps->s_pool.max_remstream = i;
2573 set_current_val(&vars[V_PERMLOCKED], TRUE, TRUE);
2575 set_current_val(&vars[V_NMW_WIDTH], TRUE, TRUE);
2576 ps->nmw_width = i = atoi(DF_NMW_WIDTH);
2577 if(SVAR_NMW_WIDTH(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2578 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2579 else
2580 ps->nmw_width = i;
2582 /* backwards compatibility */
2583 if(obs_save_by_sender){
2584 ps->save_msg_rule = SAV_RULE_FROM;
2585 set_variable(V_SAVED_MSG_NAME_RULE, "by-from", 1, 1, Main);
2588 /* this should come after process_feature_list because of use_fkeys */
2589 if(!ps->start_in_index)
2590 set_current_val(&vars[V_INIT_CMD_LIST], FALSE, TRUE);
2591 if(VAR_INIT_CMD_LIST && VAR_INIT_CMD_LIST[0] && VAR_INIT_CMD_LIST[0][0])
2592 if(cmds_f)
2593 (*cmds_f)(ps, VAR_INIT_CMD_LIST);
2595 #ifdef _WINDOWS
2596 mswin_set_quit_confirm (F_OFF(F_QUIT_WO_CONFIRM, ps_global));
2597 #endif /* _WINDOWS */
2599 #ifdef DEBUG
2600 dump_configuration(0);
2601 #endif /* DEBUG */
2605 void
2606 convert_configvars_to_utf8(struct variable *vars, char *fromcharset)
2608 struct variable *v;
2611 * Make sure that everything is UTF-8.
2613 for(v = vars; v->name; v++)
2614 convert_configvar_to_utf8(v, fromcharset);
2618 void
2619 convert_configvar_to_utf8(struct variable *v, char *fromcharset)
2621 char **p, *conv, **valptr;
2622 int i;
2625 * Make sure that everything is UTF-8.
2627 if(v->is_list){
2628 for(i = 0; i < 7; i++){
2629 switch(i){
2630 case 1: valptr = v->current_val.l; break;
2631 case 0: valptr = v->main_user_val.l; break;
2632 case 2: valptr = v->changed_val.l; break;
2633 case 3: valptr = v->post_user_val.l; break;
2634 case 4: valptr = v->global_val.l; break;
2635 case 5: valptr = v->fixed_val.l; break;
2636 case 6: valptr = v->cmdline_val.l; break;
2637 default: panic("bad case in convert_configvar");
2640 if(valptr){
2641 for(p = valptr; *p; p++){
2642 if(**p){
2643 conv = convert_to_utf8(*p, fromcharset, 0);
2644 if(conv){
2645 fs_give((void **) p);
2646 *p = conv;
2653 else{
2654 for(i = 0; i < 7; i++){
2655 switch(i){
2656 case 1: valptr = &v->current_val.p; break;
2657 case 0: valptr = &v->main_user_val.p; break;
2658 case 2: valptr = &v->changed_val.p; break;
2659 case 3: valptr = &v->post_user_val.p; break;
2660 case 4: valptr = &v->global_val.p; break;
2661 case 5: valptr = &v->fixed_val.p; break;
2662 case 6: valptr = &v->cmdline_val.p; break;
2663 default: panic("bad case in convert_configvar");
2666 if(valptr && *valptr && (*valptr)[0]){
2667 conv = convert_to_utf8(*valptr, fromcharset, 0);
2668 if(conv){
2669 fs_give((void **) valptr);
2670 *valptr = conv;
2680 * Standard feature name sections
2682 char *
2683 feature_list_section(FEATURE_S *feature)
2685 #define PREF_NONE -1
2686 static char *feat_sect[] = {
2687 #define PREF_MISC 0
2688 /* TRANSLATORS: section heading in configuration screen */
2689 N_("Advanced User Preferences"),
2690 #define PREF_FLDR 1
2691 /* TRANSLATORS: section heading in configuration screen */
2692 N_("Folder Preferences"),
2693 #define PREF_ADDR 2
2694 /* TRANSLATORS: section heading in configuration screen */
2695 N_("Address Book Preferences"),
2696 #define PREF_COMP 3
2697 /* TRANSLATORS: section heading in configuration screen */
2698 N_("Composer Preferences"),
2699 #define PREF_NEWS 4
2700 /* TRANSLATORS: section heading in configuration screen */
2701 N_("News Preferences"),
2702 #define PREF_VIEW 5
2703 /* TRANSLATORS: section heading in configuration screen */
2704 N_("Viewer Preferences"),
2705 #define PREF_ACMD 6
2706 /* TRANSLATORS: section heading in configuration screen */
2707 N_("Advanced Command Preferences"),
2708 #define PREF_PRNT 7
2709 /* TRANSLATORS: section heading in configuration screen */
2710 N_("Printer Preferences"),
2711 #define PREF_RPLY 8
2712 /* TRANSLATORS: section heading in configuration screen */
2713 N_("Reply Preferences"),
2714 #define PREF_SEND 9
2715 /* TRANSLATORS: section heading in configuration screen */
2716 N_("Sending Preferences"),
2717 #define PREF_INDX 10
2718 /* TRANSLATORS: section heading in configuration screen */
2719 N_("Message Index Preferences"),
2720 #define PREF_HIDDEN 11
2721 HIDDEN_PREF
2724 return((feature && feature->section > PREF_NONE
2725 && feature->section < (sizeof(feat_sect)/sizeof(feat_sect[0])))
2726 ? _(feat_sect[feature->section]) : NULL);
2730 /* any os-specific exclusions */
2731 #if defined(DOS) || defined(OS2)
2732 #define PREF_OS_LWSD PREF_NONE
2733 #define PREF_OS_LCLK PREF_NONE
2734 #define PREF_OS_STSP PREF_NONE
2735 #define PREF_OS_SPWN PREF_NONE
2736 #define PREF_OS_XNML PREF_NONE
2737 #define PREF_OS_USFK PREF_MISC
2738 #define PREF_OS_MOUSE PREF_NONE
2739 #else
2740 #define PREF_OS_LWSD PREF_MISC
2741 #define PREF_OS_LCLK PREF_COMP
2742 #define PREF_OS_STSP PREF_MISC
2743 #define PREF_OS_SPWN PREF_MISC
2744 #define PREF_OS_XNML PREF_MISC
2745 #define PREF_OS_USFK PREF_NONE
2746 #define PREF_OS_MOUSE PREF_MISC
2747 #endif
2751 * Standard way to get at feature list members...
2753 FEATURE_S *
2754 feature_list(int index)
2757 * This list is alphabatized by feature string, but the
2758 * macro values need not be ordered.
2760 static FEATURE_S feat_list[] = {
2761 /* Composer prefs */
2762 {"allow-changing-from", NULL,
2763 F_ALLOW_CHANGING_FROM, h_config_allow_chg_from, PREF_COMP, 1},
2764 {"alternate-compose-menu", NULL,
2765 F_ALT_COMPOSE_MENU, h_config_alt_compose_menu, PREF_COMP, 0},
2766 {"alternate-role-menu", "Alternate Role (#) Menu",
2767 F_ALT_ROLE_MENU, h_config_alt_role_menu, PREF_COMP, 0},
2768 {"compose-cancel-confirm-uses-yes", NULL,
2769 F_CANCEL_CONFIRM, h_config_cancel_confirm, PREF_COMP, 0},
2770 {"compose-rejects-unqualified-addrs", "Compose Rejects Unqualified Addresses",
2771 F_COMPOSE_REJECTS_UNQUAL, h_config_compose_rejects_unqual, PREF_COMP, 0},
2772 {"compose-send-offers-first-filter", NULL,
2773 F_FIRST_SEND_FILTER_DFLT, h_config_send_filter_dflt, PREF_COMP, 0},
2774 {"compose-cut-from-cursor", "Ctrl-K Cuts From Cursor",
2775 F_DEL_FROM_DOT, h_config_del_from_dot, PREF_COMP, 0},
2776 {"compose-maps-delete-key-to-ctrl-d", "Delete Key Maps to Ctrl-D",
2777 F_COMPOSE_MAPS_DEL, h_config_compose_maps_del, PREF_COMP, 0},
2778 {"quell-dead-letter-on-cancel", "Do Not Save to Deadletter on Cancel",
2779 F_QUELL_DEAD_LETTER, h_config_quell_dead_letter, PREF_COMP, 0},
2780 {"enable-alternate-editor-cmd", "Enable Alternate Editor Command",
2781 F_ENABLE_ALT_ED, h_config_enable_alt_ed, PREF_COMP, 1},
2782 {"enable-alternate-editor-implicitly", NULL,
2783 F_ALT_ED_NOW, h_config_alt_ed_now, PREF_COMP, 0},
2784 {"enable-search-and-replace", "Enable Search and Replace",
2785 F_ENABLE_SEARCH_AND_REPL, h_config_enable_search_and_repl, PREF_COMP, 1},
2786 {"enable-sigdashes", NULL,
2787 F_ENABLE_SIGDASHES, h_config_sigdashes, PREF_COMP, 0},
2788 {"quell-mailchecks-composing-except-inbox", "Prevent Mailchecks While Composing Except for INBOX",
2789 F_QUELL_PINGS_COMPOSING, h_config_quell_checks_comp, PREF_COMP, 0},
2790 {"quell-mailchecks-composing-inbox", "Prevent Mailchecks While Composing for INBOX",
2791 F_QUELL_PINGS_COMPOSING_INBOX, h_config_quell_checks_comp_inbox, PREF_COMP, 0},
2792 {"quell-user-lookup-in-passwd-file", "Prevent User Lookup in Password File",
2793 F_QUELL_LOCAL_LOOKUP, h_config_quell_local_lookup, PREF_OS_LCLK, 0},
2794 {"spell-check-before-sending", NULL,
2795 F_ALWAYS_SPELL_CHECK, h_config_always_spell_check, PREF_COMP, 0},
2797 /* Reply Prefs */
2798 {"copy-to-address-to-from-if-it-is-us", "Copy To Address to From if it is Us",
2799 F_COPY_TO_TO_FROM, h_config_copy_to_to_from, PREF_RPLY, 0},
2800 {"enable-reply-indent-string-editing", NULL,
2801 F_ENABLE_EDIT_REPLY_INDENT, h_config_prefix_editing, PREF_RPLY, 0},
2802 {"include-attachments-in-reply", "Include Attachments in Reply",
2803 F_ATTACHMENTS_IN_REPLY, h_config_attach_in_reply, PREF_RPLY, 0},
2804 {"include-header-in-reply", "Include Header in Reply",
2805 F_INCLUDE_HEADER, h_config_include_header, PREF_RPLY, 0},
2806 {"include-text-in-reply", "Include Text in Reply",
2807 F_AUTO_INCLUDE_IN_REPLY, h_config_auto_include_reply, PREF_RPLY, 0},
2808 {"reply-always-uses-reply-to", "Reply Always Uses Reply-To",
2809 F_AUTO_REPLY_TO, h_config_auto_reply_to, PREF_RPLY, 0},
2810 {"signature-at-bottom", "Signature at Bottom",
2811 F_SIG_AT_BOTTOM, h_config_sig_at_bottom, PREF_RPLY, 0},
2812 {"strip-from-sigdashes-on-reply", "Strip From Sigdashes on Reply",
2813 F_ENABLE_STRIP_SIGDASHES, h_config_strip_sigdashes, PREF_RPLY, 0},
2814 {"forward-as-attachment", "Forward messages as attachments",
2815 F_FORWARD_AS_ATTACHMENT, h_config_forward_as_attachment, PREF_RPLY, 0},
2816 {"preserve-original-fields", NULL,
2817 F_PRESERVE_ORIGINAL_FIELD, h_config_preserve_field, PREF_RPLY, 0},
2819 /* Sending Prefs */
2820 {"disable-sender", "Do Not Generate Sender Header",
2821 F_DISABLE_SENDER, h_config_disable_sender, PREF_SEND, 0},
2822 {"use-sender-not-x-sender", "Use Sender Instead of X-X-Sender",
2823 F_USE_SENDER_NOT_X, h_config_use_sender_not_x, PREF_SEND, 0},
2824 {"quell-flowed-text", "Do Not Send Flowed Text",
2825 F_QUELL_FLOWED_TEXT, h_config_quell_flowed_text, PREF_SEND, 0},
2826 {"downgrade-multipart-to-text", "Downgrade Multipart to Text",
2827 F_COMPOSE_ALWAYS_DOWNGRADE, h_downgrade_multipart_to_text, PREF_SEND, 0},
2828 {"enable-8bit-esmtp-negotiation", "Enable 8bit ESMTP Negotiation",
2829 F_ENABLE_8BIT, h_config_8bit_smtp, PREF_SEND, 1},
2830 #ifdef BACKGROUND_POST
2831 {"enable-background-sending", NULL,
2832 F_BACKGROUND_POST, h_config_compose_bg_post, PREF_SEND, 0},
2833 #endif
2834 {"enable-delivery-status-notification", NULL,
2835 F_DSN, h_config_compose_dsn, PREF_SEND, 0},
2836 {"enable-verbose-smtp-posting", "Enable Verbose SMTP Posting",
2837 F_VERBOSE_POST, h_config_verbose_post, PREF_SEND, 0},
2838 {"fcc-without-attachments", "Fcc Does Not Include Attachments",
2839 F_NO_FCC_ATTACH, h_config_no_fcc_attach, PREF_SEND, 0},
2840 {"fcc-on-bounce", "Include Fcc When Bouncing Messages",
2841 F_FCC_ON_BOUNCE, h_config_fcc_on_bounce, PREF_SEND, 0},
2842 {"mark-fcc-seen", NULL,
2843 F_MARK_FCC_SEEN, h_config_mark_fcc_seen, PREF_SEND, 0},
2844 {"fcc-only-without-confirm", "Send to Fcc Only Without Confirming",
2845 F_AUTO_FCC_ONLY, h_config_auto_fcc_only, PREF_SEND, 0},
2846 {"send-without-confirm", "Send Without Confirming",
2847 F_SEND_WO_CONFIRM, h_config_send_wo_confirm, PREF_SEND, 0},
2848 {"strip-whitespace-before-send", "Strip Whitespace Before Sending",
2849 F_STRIP_WS_BEFORE_SEND, h_config_strip_ws_before_send, PREF_SEND, 0},
2850 {"warn-if-blank-fcc", "Warn if Blank Fcc",
2851 F_WARN_ABOUT_NO_FCC, h_config_warn_if_fcc_blank, PREF_SEND, 0},
2852 {"warn-if-blank-subject", "Warn if Blank Subject",
2853 F_WARN_ABOUT_NO_SUBJECT, h_config_warn_if_subj_blank, PREF_SEND, 0},
2854 {"warn-if-blank-to-and-cc-and-newsgroups", "Warn if Blank To and CC and Newsgroups",
2855 F_WARN_ABOUT_NO_TO_OR_CC, h_config_warn_if_no_to_or_cc, PREF_SEND, 0},
2857 /* Folder */
2858 {"combined-folder-display", NULL,
2859 F_CMBND_FOLDER_DISP, h_config_combined_folder_display, PREF_FLDR, 0},
2860 {"combined-subdirectory-display", NULL,
2861 F_CMBND_SUBDIR_DISP, h_config_combined_subdir_display, PREF_FLDR, 0},
2862 {"enable-lame-list-mode", "Compensate for Deficient IMAP servers",
2863 F_FIX_BROKEN_LIST, h_config_lame_list_mode, PREF_FLDR, 0},
2864 {"enable-dot-folders", "Enable Hidden Folders",
2865 F_ENABLE_DOT_FOLDERS, h_config_enable_dot_folders, PREF_FLDR, 0},
2866 {"enable-incoming-folders", "Enable Incoming Folders Collection",
2867 F_ENABLE_INCOMING, h_config_enable_incoming, PREF_FLDR, 0},
2868 {"enable-incoming-folders-checking", NULL,
2869 F_ENABLE_INCOMING_CHECKING, h_config_enable_incoming_checking, PREF_FLDR, 0},
2870 {"incoming-checking-includes-total", NULL,
2871 F_INCOMING_CHECKING_TOTAL, h_config_incoming_checking_total, PREF_FLDR, 0},
2872 {"incoming-checking-uses-recent", NULL,
2873 F_INCOMING_CHECKING_RECENT, h_config_incoming_checking_recent, PREF_FLDR, 0},
2874 {"expanded-view-of-folders", "Expanded View of Folders",
2875 F_EXPANDED_FOLDERS, h_config_expanded_folders, PREF_FLDR, 0},
2876 {"quell-empty-directories", "Hide Empty Directories",
2877 F_QUELL_EMPTY_DIRS, h_config_quell_empty_dirs, PREF_FLDR, 0},
2878 {"separate-folder-and-directory-entries", "Separate Folder and Directory Entries",
2879 F_SEPARATE_FLDR_AS_DIR, h_config_separate_fold_dir_view, PREF_FLDR, 0},
2880 {"single-column-folder-list", NULL,
2881 F_SINGLE_FOLDER_LIST, h_config_single_list, PREF_FLDR, 0},
2882 {"sort-default-fcc-alpha", "Sort Default Fcc Folder Alphabetically",
2883 F_SORT_DEFAULT_FCC_ALPHA, h_config_sort_fcc_alpha, PREF_FLDR, 0},
2884 {"sort-default-save-alpha", "Sort Default Save Folder Alphabetically",
2885 F_SORT_DEFAULT_SAVE_ALPHA, h_config_sort_save_alpha, PREF_FLDR, 0},
2886 {"vertical-folder-list", "Use Vertical Folder List",
2887 F_VERTICAL_FOLDER_LIST, h_config_vertical_list, PREF_FLDR, 0},
2889 /* Addr book */
2890 {"combined-addrbook-display", "Combined Address Book Display",
2891 F_CMBND_ABOOK_DISP, h_config_combined_abook_display, PREF_ADDR, 0},
2892 {"expanded-view-of-addressbooks", "Expanded View of Address Books",
2893 F_EXPANDED_ADDRBOOKS, h_config_expanded_addrbooks, PREF_ADDR, 0},
2894 {"expanded-view-of-distribution-lists", "Expanded View of Distribution Lists",
2895 F_EXPANDED_DISTLISTS, h_config_expanded_distlists, PREF_ADDR, 0},
2896 #ifdef ENABLE_LDAP
2897 {"ldap-result-to-addrbook-add", "LDAP Result to Addressbook Add",
2898 F_ADD_LDAP_TO_ABOOK, h_config_add_ldap, PREF_ADDR, 0},
2899 #endif
2901 /* Index prefs */
2902 {"auto-open-next-unread", NULL,
2903 F_AUTO_OPEN_NEXT_UNREAD, h_config_auto_open_unread, PREF_INDX, 0},
2904 {"continue-tab-without-confirm", "Continue NextNew Without Confirming",
2905 F_TAB_NO_CONFIRM, h_config_tab_no_prompt, PREF_INDX, 0},
2906 {"convert-dates-to-localtime", NULL,
2907 F_DATES_TO_LOCAL, h_config_dates_to_local, PREF_INDX, 0},
2908 {"delete-skips-deleted", NULL,
2909 F_DEL_SKIPS_DEL, h_config_del_skips_del, PREF_INDX, 1},
2910 {"disable-index-locale-dates", NULL,
2911 F_DISABLE_INDEX_LOCALE_DATES, h_config_disable_index_locale_dates, PREF_INDX, 0},
2912 {"enable-cruise-mode", NULL,
2913 F_ENABLE_SPACE_AS_TAB, h_config_cruise_mode, PREF_INDX, 0},
2914 {"enable-cruise-mode-delete", "Enable Cruise Mode With Deleting",
2915 F_ENABLE_TAB_DELETES, h_config_cruise_mode_delete, PREF_INDX, 0},
2916 {"mark-for-cc", "Mark for CC",
2917 F_MARK_FOR_CC, h_config_mark_for_cc, PREF_INDX, 1},
2918 {"next-thread-without-confirm", "Read Next Thread Without Confirming",
2919 F_NEXT_THRD_WO_CONFIRM, h_config_next_thrd_wo_confirm, PREF_INDX, 0},
2920 {"return-to-inbox-without-confirm", "Return to INBOX Without Confirming",
2921 F_RET_INBOX_NO_CONFIRM, h_config_inbox_no_confirm, PREF_INDX, 0},
2922 {"show-sort", "Show Sort in Titlebar",
2923 F_SHOW_SORT, h_config_show_sort, PREF_INDX, 0},
2924 {"tab-uses-unseen-for-next-folder", "Tab Uses Unseen for Next Folder",
2925 F_TAB_USES_UNSEEN, h_config_tab_uses_unseen, PREF_INDX, 0},
2926 {"tab-visits-next-new-message-only", NULL,
2927 F_TAB_TO_NEW, h_config_tab_new_only, PREF_INDX, 0},
2928 {"thread-index-shows-important-color", NULL,
2929 F_COLOR_LINE_IMPORTANT, h_config_color_thrd_import, PREF_INDX, 0},
2930 {"thread-sorts-by-arrival", "Thread Sorts by Arrival",
2931 F_THREAD_SORTS_BY_ARRIVAL, h_config_thread_sorts_by_arrival, PREF_INDX, 0},
2933 /* Viewer prefs */
2934 {"enable-msg-view-addresses", "Enable Message View Address Links",
2935 F_SCAN_ADDR, h_config_enable_view_addresses, PREF_VIEW, 0},
2936 {"enable-msg-view-attachments", "Enable Message View Attachment Links",
2937 F_VIEW_SEL_ATTACH, h_config_enable_view_attach, PREF_VIEW, 0},
2938 {"enable-msg-view-urls", "Enable Message View URL Links",
2939 F_VIEW_SEL_URL, h_config_enable_view_url, PREF_VIEW, 1},
2940 {"enable-msg-view-web-hostnames", "Enable Message View Web Hostname Links",
2941 F_VIEW_SEL_URL_HOST, h_config_enable_view_web_host, PREF_VIEW, 1},
2942 {"enable-msg-view-forced-arrows", "Enable Message View Forced Arrows",
2943 F_FORCE_ARROWS, h_config_enable_view_arrows, PREF_VIEW, 0},
2944 /* set to TRUE for windows */
2945 {"pass-c1-control-characters-as-is", NULL,
2946 F_PASS_C1_CONTROL_CHARS, h_config_pass_c1_control, PREF_VIEW, 0},
2947 {"pass-control-characters-as-is", NULL,
2948 F_PASS_CONTROL_CHARS, h_config_pass_control, PREF_VIEW, 0},
2949 {"prefer-plain-text", NULL,
2950 F_PREFER_PLAIN_TEXT, h_config_prefer_plain_text, PREF_VIEW, 0},
2951 {"quell-charset-warning", "Suppress Character Set Warning",
2952 F_QUELL_CHARSET_WARNING, h_config_quell_charset_warning, PREF_VIEW, 0},
2953 {"quell-server-after-link-in-html", "Suppress Server After Link in HTML",
2954 F_QUELL_HOST_AFTER_URL, h_config_quell_host_after_url, PREF_VIEW, 0},
2956 /* News */
2957 {"compose-sets-newsgroup-without-confirm", "Compose Sets Newsgroup Without Confirming",
2958 F_COMPOSE_TO_NEWSGRP, h_config_compose_news_wo_conf, PREF_NEWS, 0},
2959 {"enable-8bit-nntp-posting", "Enable 8bit NNTP Posting",
2960 F_ENABLE_8BIT_NNTP, h_config_8bit_nntp, PREF_NEWS, 0},
2961 {"enable-multiple-newsrcs", NULL,
2962 F_ENABLE_MULNEWSRCS, h_config_enable_mulnewsrcs, PREF_NEWS, 0},
2963 {"mult-newsrc-hostnames-as-typed", "Multiple Newsrc Hostnames as Typed",
2964 F_MULNEWSRC_HOSTNAMES_AS_TYPED, h_config_mulnews_as_typed, PREF_NEWS, 0},
2965 {"hide-nntp-path", "Hide NNTP Path",
2966 F_HIDE_NNTP_PATH, h_config_hide_nntp_path, PREF_NEWS, 0},
2967 {"news-approximates-new-status", NULL,
2968 F_FAKE_NEW_IN_NEWS, h_config_news_uses_recent, PREF_NEWS, 1},
2969 {"news-deletes-across-groups", NULL,
2970 F_NEWS_CROSS_DELETE, h_config_news_cross_deletes, PREF_NEWS, 0},
2971 {"news-offers-catchup-on-close", "News Offers Catchup on Close",
2972 F_NEWS_CATCHUP, h_config_news_catchup, PREF_NEWS, 0},
2973 {"news-post-without-validation", NULL,
2974 F_NO_NEWS_VALIDATION, h_config_post_wo_validation, PREF_NEWS, 0},
2975 {"news-read-in-newsrc-order", "News Read in Newsrc Order",
2976 F_READ_IN_NEWSRC_ORDER, h_config_read_in_newsrc_order, PREF_NEWS, 0},
2977 {"nntp-search-uses-overview", "NNTP Search Uses Overview",
2978 F_NNTP_SEARCH_USES_OVERVIEW, h_config_nntp_search_uses_overview, PREF_NEWS, 1},
2979 {"predict-nntp-server", "Predict NNTP Server",
2980 F_PREDICT_NNTP_SERVER, h_config_predict_nntp_server, PREF_NEWS, 0},
2981 {"quell-extra-post-prompt", "Suppress Extra Posting Prompt",
2982 F_QUELL_EXTRA_POST_PROMPT, h_config_quell_post_prompt, PREF_NEWS, 0},
2984 /* Print */
2985 {"enable-print-via-y-command", NULL,
2986 F_ENABLE_PRYNT, h_config_enable_y_print, PREF_PRNT, 0},
2987 {"print-formfeed-between-messages", NULL,
2988 F_AGG_PRINT_FF, h_config_ff_between_msgs, PREF_PRNT, 0},
2989 {"print-includes-from-line", NULL,
2990 F_FROM_DELIM_IN_PRINT, h_config_print_from, PREF_PRNT, 0},
2991 {"print-index-enabled", NULL,
2992 F_PRINT_INDEX, h_config_print_index, PREF_PRNT, 0},
2993 {"print-offers-custom-cmd-prompt", "Print Offers Custom Command Prompt",
2994 F_CUSTOM_PRINT, h_config_custom_print, PREF_PRNT, 0},
2996 /* adv cmd prefs */
2997 {"enable-aggregate-command-set", NULL,
2998 F_ENABLE_AGG_OPS, h_config_enable_agg_ops, PREF_ACMD, 1},
2999 {"enable-arrow-navigation", NULL,
3000 F_ARROW_NAV, h_config_arrow_nav, PREF_ACMD, 1},
3001 {"enable-arrow-navigation-relaxed", NULL,
3002 F_RELAXED_ARROW_NAV, h_config_relaxed_arrow_nav, PREF_ACMD, 1},
3003 {"enable-bounce-cmd", "Enable Bounce Command",
3004 F_ENABLE_BOUNCE, h_config_enable_bounce, PREF_ACMD, 1},
3005 {"enable-exit-via-lessthan-command", NULL,
3006 F_ENABLE_LESSTHAN_EXIT, h_config_enable_lessthan_exit, PREF_ACMD, 1},
3007 {"enable-flag-cmd", "Enable Flag Command",
3008 F_ENABLE_FLAG, h_config_enable_flag, PREF_ACMD, 1},
3009 {"enable-flag-screen-implicitly", NULL,
3010 F_FLAG_SCREEN_DFLT, h_config_flag_screen_default, PREF_ACMD, 0},
3011 {"enable-flag-screen-keyword-shortcut", NULL,
3012 F_FLAG_SCREEN_KW_SHORTCUT, h_config_flag_screen_kw_shortcut,PREF_ACMD, 1},
3013 {"enable-full-header-and-text", "Enable Full Header and Text",
3014 F_ENABLE_FULL_HDR_AND_TEXT, h_config_enable_full_hdr_and_text, PREF_ACMD, 0},
3015 {"enable-full-header-cmd", "Enable Full Header Command",
3016 F_ENABLE_FULL_HDR, h_config_enable_full_hdr, PREF_ACMD, 1},
3017 {"enable-goto-in-file-browser", "Enable Goto in File Browser",
3018 F_ALLOW_GOTO, h_config_allow_goto, PREF_ACMD, 1},
3019 {"enable-jump-shortcut", NULL,
3020 F_ENABLE_JUMP, h_config_enable_jump, PREF_ACMD, 1},
3021 {"enable-partial-match-lists", NULL,
3022 F_ENABLE_SUB_LISTS, h_config_sub_lists, PREF_ACMD, 1},
3023 {"enable-tab-completion", NULL,
3024 F_ENABLE_TAB_COMPLETE, h_config_enable_tab_complete, PREF_ACMD, 1},
3025 {"enable-unix-pipe-cmd", "Enable Unix Pipe Command",
3026 F_ENABLE_PIPE, h_config_enable_pipe, PREF_ACMD, 1},
3027 {"quell-full-header-auto-reset", "Suppress Full Header Auto Reset",
3028 F_QUELL_FULL_HDR_RESET, h_config_quell_full_hdr_reset, PREF_ACMD, 0},
3030 /* Adv user prefs */
3031 #if !defined(DOS) && !defined(OS2)
3032 {"allow-talk", NULL,
3033 F_ALLOW_TALK, h_config_allow_talk, PREF_MISC, 0},
3034 #endif
3035 {"assume-slow-link", NULL,
3036 F_FORCE_LOW_SPEED, h_config_force_low_speed, PREF_OS_LWSD, 0},
3037 {"auto-move-read-msgs", "Auto Move Read Messages",
3038 F_AUTO_READ_MSGS, h_config_auto_read_msgs, PREF_MISC, 0},
3039 {"auto-unselect-after-apply", NULL,
3040 F_AUTO_UNSELECT, h_config_auto_unselect, PREF_MISC, 0},
3041 {"auto-unzoom-after-apply", NULL,
3042 F_AUTO_UNZOOM, h_config_auto_unzoom, PREF_MISC, 1},
3043 {"auto-zoom-after-select", NULL,
3044 F_AUTO_ZOOM, h_config_auto_zoom, PREF_MISC, 1},
3045 {"busy-cue-spinner-only", NULL,
3046 F_USE_BORING_SPINNER, h_config_use_boring_spinner, PREF_MISC, 0},
3047 {"check-newmail-when-quitting", NULL,
3048 F_CHECK_MAIL_ONQUIT, h_config_check_mail_onquit, PREF_MISC, 0},
3049 {"confirm-role-even-for-default", "Confirm Role Even for Default",
3050 F_ROLE_CONFIRM_DEFAULT, h_config_confirm_role, PREF_MISC, 0},
3051 {"disable-keymenu", NULL,
3052 F_BLANK_KEYMENU, h_config_blank_keymenu, PREF_MISC, 0},
3053 {"disable-password-caching", NULL,
3054 F_DISABLE_PASSWORD_CACHING, h_config_disable_password_caching,
3055 PREF_MISC, 0},
3056 {"disable-regular-expression-matching-for-alternate-addresses", NULL,
3057 F_DISABLE_REGEX, h_config_disable_regex, PREF_MISC, 0},
3058 {"disable-save-input-history", NULL,
3059 F_DISABLE_SAVE_INPUT_HISTORY, h_config_input_history, PREF_MISC, 0},
3060 {"disable-take-fullname-in-addresses", "Disable Take Fullname in Addresses",
3061 F_DISABLE_TAKE_FULLNAMES, h_config_take_fullname, PREF_MISC, 0},
3062 {"disable-take-last-comma-first", NULL,
3063 F_DISABLE_TAKE_LASTFIRST, h_config_take_lastfirst, PREF_MISC, 0},
3064 {"disable-terminal-reset-for-display-filters", "Disable Terminal Reset for Display Filters",
3065 F_DISABLE_TERM_RESET_DISP, h_config_disable_reset_disp, PREF_MISC, 0},
3066 {"enable-dot-files", NULL,
3067 F_ENABLE_DOT_FILES, h_config_enable_dot_files, PREF_MISC, 0},
3068 {"enable-fast-recent-test", NULL,
3069 F_ENABLE_FAST_RECENT, h_config_fast_recent, PREF_MISC, 0},
3070 {"enable-mail-check-cue", NULL,
3071 F_SHOW_DELAY_CUE, h_config_show_delay_cue, PREF_MISC, 0},
3072 {"enable-mailcap-param-substitution", "Enable Mailcap Parameter Substitution",
3073 F_DO_MAILCAP_PARAM_SUBST, h_config_mailcap_params, PREF_MISC, 0},
3074 {"enable-mouse-in-xterm", "Enable Mouse in Xterm",
3075 F_ENABLE_MOUSE, h_config_enable_mouse, PREF_OS_MOUSE, 0},
3076 {"enable-newmail-in-xterm-icon", "Enable Newmail in Xterm Icon",
3077 F_ENABLE_XTERM_NEWMAIL, h_config_enable_xterm_newmail, PREF_OS_XNML, 0},
3078 {"enable-newmail-short-text-in-icon", "Enable Newmail Short Text in Icon",
3079 F_ENABLE_NEWMAIL_SHORT_TEXT, h_config_enable_newmail_short_text, PREF_OS_XNML, 0},
3080 {"enable-suspend", NULL,
3081 F_CAN_SUSPEND, h_config_can_suspend, PREF_MISC, 0},
3082 {"enable-take-export", NULL,
3083 F_ENABLE_TAKE_EXPORT, h_config_enable_take_export, PREF_MISC, 0},
3084 {"enable-rules-under-take", "Enable Take Rules",
3085 F_ENABLE_ROLE_TAKE, h_config_enable_role_take, PREF_MISC, 0},
3086 #ifdef _WINDOWS
3087 {"enable-tray-icon", NULL,
3088 F_ENABLE_TRAYICON, h_config_tray_icon, PREF_MISC, 0},
3089 #endif
3090 {"expose-hidden-config", NULL,
3091 F_EXPOSE_HIDDEN_CONFIG, h_config_expose_hidden_config, PREF_MISC, 0},
3092 {"expunge-only-manually", NULL,
3093 F_EXPUNGE_MANUALLY, h_config_expunge_manually, PREF_MISC, 0},
3094 {"expunge-without-confirm", "Expunge Without Confirming",
3095 F_AUTO_EXPUNGE, h_config_auto_expunge, PREF_MISC, 0},
3096 {"expunge-without-confirm-everywhere", "Expunge Without Confirming Everywhere",
3097 F_FULL_AUTO_EXPUNGE, h_config_full_auto_expunge, PREF_MISC, 0},
3098 {"force-arrow-cursor", NULL,
3099 F_FORCE_ARROW, h_config_force_arrow, PREF_MISC, 0},
3100 {"maildrops-preserve-state", NULL,
3101 F_MAILDROPS_PRESERVE_STATE, h_config_maildrops_preserve_state,
3102 PREF_MISC, 0},
3103 {"offer-expunge-of-inbox", "Offer Expunge of INBOX",
3104 F_EXPUNGE_INBOX, h_config_expunge_inbox, PREF_MISC, 0},
3105 {"offer-expunge-of-stayopen-folders", "Offer Expunge of Stayopen Folders",
3106 F_EXPUNGE_STAYOPENS, h_config_expunge_stayopens, PREF_MISC, 0},
3107 {"preopen-stayopen-folders", NULL,
3108 F_PREOPEN_STAYOPENS, h_config_preopen_stayopens, PREF_MISC, 0},
3109 {"preserve-start-stop-characters", "Preserve Start/Stop Characters",
3110 F_PRESERVE_START_STOP, h_config_preserve_start_stop, PREF_OS_STSP, 0},
3111 {"quell-folder-internal-msg", "Prevent Folder Internal Message",
3112 F_QUELL_INTERNAL_MSG, h_config_quell_folder_internal_msg, PREF_MISC, 0},
3113 {"quell-partial-fetching", "Prevent Partial Fetching",
3114 F_QUELL_PARTIAL_FETCH, h_config_quell_partial, PREF_MISC, 0},
3115 {"prune-uses-yyyy-mm", "Prune Uses YYYY-MM",
3116 F_PRUNE_USES_ISO, h_config_prune_uses_iso, PREF_MISC, 0},
3117 {"quit-without-confirm", "Quit Without Confirming",
3118 F_QUIT_WO_CONFIRM, h_config_quit_wo_confirm, PREF_MISC, 0},
3119 {"quote-replace-nonflowed", NULL,
3120 F_QUOTE_REPLACE_NOFLOW, h_config_quote_replace_noflow, PREF_MISC, 0},
3121 {"save-aggregates-copy-sequence", "Save Combines Copies (may be out of order)",
3122 F_AGG_SEQ_COPY, h_config_save_aggregates, PREF_MISC, 1},
3123 {"save-partial-msg-without-confirm", "Save Partial Message Without Confirming",
3124 F_SAVE_PARTIAL_WO_CONFIRM, h_config_save_part_wo_confirm, PREF_MISC, 0},
3125 {"save-will-advance", NULL,
3126 F_SAVE_ADVANCES, h_config_save_advances, PREF_MISC, 0},
3127 {"save-will-not-delete", NULL,
3128 F_SAVE_WONT_DELETE, h_config_save_wont_delete, PREF_MISC, 0},
3129 {"save-will-quote-leading-froms", NULL,
3130 F_QUOTE_ALL_FROMS, h_config_quote_all_froms, PREF_MISC, 0},
3131 {"scramble-message-id", "Scramble the Message-ID When Sending",
3132 F_ROT13_MESSAGE_ID, h_config_scramble_message_id, PREF_MISC, 0},
3133 {"select-without-confirm", "Select Ctrl-T Foldername Without Confirming",
3134 F_SELECT_WO_CONFIRM, h_config_select_wo_confirm, PREF_MISC, 0},
3135 {"show-cursor", NULL,
3136 F_SHOW_CURSOR, h_config_show_cursor, PREF_MISC, 0},
3137 {"show-plain-text-internally", NULL,
3138 F_SHOW_TEXTPLAIN_INT, h_config_textplain_int, PREF_MISC, 0},
3139 {"show-selected-in-boldface", "Show Selected in Boldface",
3140 F_SELECTED_SHOWN_BOLD, h_config_select_in_bold, PREF_MISC, 0},
3141 {"slash-collapses-entire-thread", NULL,
3142 F_SLASH_COLL_ENTIRE, h_config_slash_coll_entire, PREF_MISC, 0},
3143 #ifdef _WINDOWS
3144 {"store-window-position-in-config", "Store Window Position in Config",
3145 F_STORE_WINPOS_IN_CONFIG, h_config_winpos_in_config, PREF_MISC, 0},
3146 #endif
3147 {"suppress-asterisks-in-password-prompt", "Suppress Asterisks in Password Prompt",
3148 F_QUELL_ASTERISKS, h_config_quell_asterisks,
3149 PREF_MISC, 0},
3150 {"quell-attachment-extension-warn", "Suppress Attachment Extension Warning",
3151 F_QUELL_ATTACH_EXT_WARN, h_config_quell_attach_ext_warn,
3152 PREF_MISC, 0},
3153 {"quell-attachment-extra-prompt", "Suppress Attachment Extra Prompt",
3154 F_QUELL_ATTACH_EXTRA_PROMPT, h_config_quell_attach_extra_prompt,
3155 PREF_MISC, 0},
3156 {"quell-berkeley-format-timezone", "Suppress Berkeley Format Timezone",
3157 F_QUELL_BEZERK_TIMEZONE, h_config_no_bezerk_zone, PREF_MISC, 0},
3158 {"quell-content-id", "Suppress Content-ID",
3159 F_QUELL_CONTENT_ID, h_config_quell_content_id, PREF_MISC, 0},
3160 {"quell-filtering-done-message", "Suppress Filtering Done Message",
3161 F_QUELL_FILTER_DONE_MSG, h_config_quell_filtering_done_message,
3162 PREF_MISC, 0},
3163 {"quell-filtering-messages", "Suppress Filtering Messages",
3164 F_QUELL_FILTER_MSGS, h_config_quell_filtering_messages,
3165 PREF_MISC, 0},
3166 {"quell-imap-envelope-update", "Suppress IMAP Envelope Update",
3167 F_QUELL_IMAP_ENV_CB, h_config_quell_imap_env, PREF_MISC, 0},
3168 {"quell-lock-failure-warnings", "Suppress Lock Failure Warnings",
3169 F_QUELL_LOCK_FAILURE_MSGS, h_config_quell_lock_failure_warnings,
3170 PREF_MISC, 0},
3171 {"quell-maildomain-warning", "Suppress Maildomain Warning",
3172 F_QUELL_MAILDOMAIN_WARNING, h_config_quell_domain_warn, PREF_MISC, 0},
3173 {"quell-news-envelope-update", "Suppress News Envelope Update",
3174 F_QUELL_NEWS_ENV_CB, h_config_quell_news_env, PREF_MISC, 0},
3175 #ifdef _WINDOWS
3176 {"quell-ssl-largeblocks", "Prevent SSL Largeblocks",
3177 F_QUELL_SSL_LARGEBLOCKS, h_config_quell_ssl_largeblocks, PREF_MISC, 0},
3178 #endif
3179 {"quell-status-message-beeping", "Suppress Status Message Beeping",
3180 F_QUELL_BEEPS, h_config_quell_beeps, PREF_MISC, 0},
3181 {"quell-timezone-comment-when-sending", "Suppress Timezone Comment When Sending",
3182 F_QUELL_TIMEZONE, h_config_quell_tz_comment, PREF_MISC, 0},
3183 {"suppress-user-agent-when-sending", NULL,
3184 F_QUELL_USERAGENT, h_config_suppress_user_agent, PREF_MISC, 0},
3185 {"tab-checks-recent", "Tab Checks for Recent Messages",
3186 F_TAB_CHK_RECENT, h_config_tab_checks_recent, PREF_MISC, 0},
3187 {"termdef-takes-precedence", NULL,
3188 F_TCAP_WINS, h_config_termcap_wins, PREF_MISC, 0},
3189 {"try-alternative-authentication-driver-first", NULL,
3190 F_PREFER_ALT_AUTH, h_config_alt_auth, PREF_MISC, 0},
3191 {"unselect-will-not-advance", NULL,
3192 F_UNSELECT_WONT_ADVANCE, h_config_unsel_wont_advance, PREF_MISC, 0},
3193 {"use-current-dir", "Use Current Directory",
3194 F_USE_CURRENT_DIR, h_config_use_current_dir, PREF_MISC, 0},
3195 {"use-function-keys", NULL,
3196 F_USE_FK, h_config_use_fk, PREF_OS_USFK, 0},
3197 {"use-regular-startup-rule-for-stayopen-folders", "Use Regular Startup Rule for Stayopen Folders",
3198 F_STARTUP_STAYOPEN, h_config_use_reg_start_for_stayopen, PREF_MISC, 0},
3199 {"use-resent-to-in-rules", "Use Resent-To in Rules",
3200 F_USE_RESENTTO, h_config_use_resentto, PREF_MISC, 0},
3201 {"use-subshell-for-suspend", "Use Subshell for Suspend",
3202 F_SUSPEND_SPAWNS, h_config_suspend_spawns, PREF_OS_SPWN, 0},
3203 #ifndef _WINDOWS
3204 {"use-system-translation", NULL,
3205 F_USE_SYSTEM_TRANS, h_config_use_system_translation, PREF_MISC, 0},
3206 #endif
3208 /* Hidden Features */
3209 {"old-growth", NULL,
3210 F_OLD_GROWTH, NO_HELP, PREF_NONE, 0},
3211 {"disable-config-cmd", NULL,
3212 F_DISABLE_CONFIG_SCREEN, h_config_disable_config_cmd, PREF_HIDDEN, 0},
3213 {"disable-keyboard-lock-cmd", NULL,
3214 F_DISABLE_KBLOCK_CMD, h_config_disable_kb_lock, PREF_HIDDEN, 0},
3215 {"disable-password-cmd", NULL,
3216 F_DISABLE_PASSWORD_CMD, h_config_disable_password_cmd, PREF_HIDDEN, 0},
3217 {"disable-pipes-in-sigs", NULL,
3218 F_DISABLE_PIPES_IN_SIGS, h_config_disable_pipes_in_sigs, PREF_HIDDEN, 0},
3219 {"disable-pipes-in-templates", NULL,
3220 F_DISABLE_PIPES_IN_TEMPLATES, h_config_disable_pipes_in_templates,
3221 PREF_HIDDEN, 0},
3222 {"disable-roles-setup-cmd", NULL,
3223 F_DISABLE_ROLES_SETUP, h_config_disable_roles_setup, PREF_HIDDEN, 0},
3224 {"disable-roles-sig-edit", NULL,
3225 F_DISABLE_ROLES_SIGEDIT, h_config_disable_roles_sigedit, PREF_HIDDEN, 0},
3226 {"disable-roles-template-edit", NULL,
3227 F_DISABLE_ROLES_TEMPLEDIT, h_config_disable_roles_templateedit,
3228 PREF_HIDDEN, 0},
3229 {"disable-setlocale-collate", NULL,
3230 F_DISABLE_SETLOCALE_COLLATE, h_config_disable_collate, PREF_HIDDEN, 0},
3231 {"disable-shared-namespaces", NULL,
3232 F_DISABLE_SHARED_NAMESPACES, h_config_disable_shared, PREF_HIDDEN, 0},
3233 {"disable-signature-edit-cmd", NULL,
3234 F_DISABLE_SIGEDIT_CMD, h_config_disable_signature_edit, PREF_HIDDEN, 0},
3235 {"new-thread-on-blank-subject", "New Thread on Blank Subject",
3236 F_NEW_THREAD_ON_BLANK_SUBJECT, h_config_new_thread_blank_subject, PREF_HIDDEN, 1},
3237 {"quell-personal-name-prompt", NULL,
3238 F_QUELL_PERSONAL_NAME_PROMPT, h_config_quell_personal_name_prompt, PREF_HIDDEN, 0},
3239 {"quell-user-id-prompt", "Quell User ID Prompt",
3240 F_QUELL_USER_ID_PROMPT, h_config_quell_user_id_prompt, PREF_HIDDEN, 0},
3241 #ifdef SMIME
3242 {"smime-dont-do-smime", "S/MIME -- Turn off S/MIME",
3243 F_DONT_DO_SMIME, h_config_smime_dont_do_smime, PREF_HIDDEN, 0},
3244 {"smime-encrypt-by-default", "S/MIME -- Encrypt by Default",
3245 F_ENCRYPT_DEFAULT_ON, h_config_smime_encrypt_by_default, PREF_HIDDEN, 0},
3246 {"smime-remember-passphrase", "S/MIME -- Remember S/MIME Passphrase",
3247 F_REMEMBER_SMIME_PASSPHRASE, h_config_smime_remember_passphrase, PREF_HIDDEN, 0},
3248 {"smime-sign-by-default", "S/MIME -- Sign by Default",
3249 F_SIGN_DEFAULT_ON, h_config_smime_sign_by_default, PREF_HIDDEN, 0},
3250 #ifdef APPLEKEYCHAIN
3251 {"publiccerts-in-keychain", "S/MIME -- Public Certs in MacOS Keychain",
3252 F_PUBLICCERTS_IN_KEYCHAIN, h_config_smime_pubcerts_in_keychain, PREF_HIDDEN, 0},
3253 #endif
3254 #endif
3255 {"selectable-item-nobold", NULL,
3256 F_SLCTBL_ITEM_NOBOLD, NO_HELP, PREF_NONE, 0},
3257 {"send-confirms-only-expanded", NULL, /* exposed in Web Alpine */
3258 F_SEND_CONFIRM_ON_EXPAND, h_config_send_confirms_only_expanded, PREF_HIDDEN, 0},
3259 {"enable-jump-cmd", NULL, /* exposed in Web Alpine */
3260 F_ENABLE_JUMP_CMD, h_config_enable_jump_command, PREF_HIDDEN, 0},
3261 {"enable-newmail-sound", NULL, /* exposed in Web Alpine */
3262 F_ENABLE_NEWMAIL_SOUND, h_config_enable_newmail_sound, PREF_HIDDEN, 0},
3263 {"render-html-internally", NULL, /* exposed in Web Alpine */
3264 F_RENDER_HTML_INTERNALLY, h_config_render_html_internally, PREF_HIDDEN, 0}
3267 return((index >= 0 && index < (sizeof(feat_list)/sizeof(feat_list[0])))
3268 ? &feat_list[index] : NULL);
3273 * feature_list_index -- return index of given feature id in
3274 * feature list
3277 feature_list_index(int id)
3279 FEATURE_S *feature;
3280 int i;
3282 for(i = 0; (feature = feature_list(i)); i++)
3283 if(id == feature->id)
3284 return(i);
3286 return(-1);
3291 * feature_list_name -- return the given feature id's corresponding name
3293 char *
3294 feature_list_name(int id)
3296 FEATURE_S *f;
3298 return((f = feature_list(feature_list_index(id))) ? f->name : "");
3303 feature_list_id(char *name)
3305 FEATURE_S *f;
3306 int i;
3308 for(i = 0; (f = feature_list(i)); i++)
3309 if(!strucmp(f->name, name))
3310 return(f->id);
3312 return(-1);
3317 * feature_list_help -- return the given feature id's corresponding help
3319 HelpType
3320 feature_list_help(int id)
3322 FEATURE_S *f;
3324 return((f = feature_list(feature_list_index(id))) ? f->help : NO_HELP);
3329 * All the arguments past "list" are the backwards compatibility hacks.
3331 void
3332 process_feature_list(struct pine *ps, char **list, int old_growth, int hir, int osr)
3334 register char *q;
3335 char **p,
3336 *lvalue[BM_SIZE * 8];
3337 int i,
3338 yorn;
3339 long l;
3340 FEATURE_S *feat;
3343 /* clear all previous settings and reset them to default */
3344 for(i = 0; (feat = feature_list(i)) != NULL; i++)
3345 F_SET(feat->id, ps, feat->defval);
3347 /* backwards compatibility */
3348 if(hir)
3349 F_TURN_ON(F_INCLUDE_HEADER, ps);
3351 /* ditto */
3352 if(osr)
3353 F_TURN_ON(F_SIG_AT_BOTTOM, ps);
3355 /* ditto */
3356 if(old_growth)
3357 set_old_growth_bits(ps, 0);
3359 /* now run through the list (global, user, and cmd_line lists are here) */
3360 if(list){
3361 for(p = list; (q = *p) != NULL; p++){
3362 if(struncmp(q, "no-", 3) == 0){
3363 yorn = 0;
3364 q += 3;
3365 }else{
3366 yorn = 1;
3369 for(i = 0; (feat = feature_list(i)) != NULL; i++){
3370 if(strucmp(q, feat->name) == 0){
3371 if(feat->id == F_OLD_GROWTH){
3372 set_old_growth_bits(ps, yorn);
3373 }else{
3374 F_SET(feat->id, ps, yorn);
3376 break;
3380 /* if it wasn't in that list */
3381 if(feat == NULL)
3382 dprint((1,"Unrecognized feature in feature-list (%s%s)\n",
3383 (yorn ? "" : "no-"), q ? q : "?"));
3388 * Turn on gratuitous '>From ' quoting, if requested...
3390 mail_parameters(NULL, SET_FROMWIDGET,
3391 F_ON(F_QUOTE_ALL_FROMS, ps) ? VOIDT : NIL);
3394 * Turn off .lock creation complaints...
3396 if(F_ON(F_QUELL_LOCK_FAILURE_MSGS, ps))
3397 mail_parameters(NULL, SET_LOCKEACCESERROR, (void *) 0);
3400 * Turn on quelling of pseudo message.
3402 if(F_ON(F_QUELL_INTERNAL_MSG,ps_global))
3403 mail_parameters(NULL, SET_USERHASNOLIFE, (void *) 1);
3405 l = F_ON(F_MULNEWSRC_HOSTNAMES_AS_TYPED,ps_global) ? 0L : 1L;
3406 mail_parameters(NULL, SET_NEWSRCCANONHOST, (void *) l);
3408 ps->pass_ctrl_chars = F_ON(F_PASS_CONTROL_CHARS,ps_global) ? 1 : 0;
3409 ps->pass_c1_ctrl_chars = F_ON(F_PASS_C1_CONTROL_CHARS,ps_global) ? 1 : 0;
3411 #ifndef _WINDOWS
3412 if(F_ON(F_QUELL_BEZERK_TIMEZONE,ps_global))
3413 mail_parameters(NULL, SET_NOTIMEZONES, (void *) 1);
3414 #endif
3416 if(F_ON(F_USE_FK, ps))
3417 ps->orig_use_fkeys = 1;
3419 /* Will we have to build a new list? */
3420 if(!(old_growth || hir || osr))
3421 return;
3424 * Build a new list for feature-list. The only reason we ever need to
3425 * do this is if one of the obsolete options is being converted
3426 * into a feature-list item, and it isn't already included in the user's
3427 * feature-list.
3429 i = 0;
3430 for(p = LVAL(&ps->vars[V_FEATURE_LIST], Main);
3431 p && (q = *p); p++){
3432 /* already have it or cancelled it, don't need to add later */
3433 if(hir && (strucmp(q, "include-header-in-reply") == 0 ||
3434 strucmp(q, "no-include-header-in-reply") == 0)){
3435 hir = 0;
3436 }else if(osr && (strucmp(q, "signature-at-bottom") == 0 ||
3437 strucmp(q, "no-signature-at-bottom") == 0)){
3438 osr = 0;
3439 }else if(old_growth && (strucmp(q, "old-growth") == 0 ||
3440 strucmp(q, "no-old-growth") == 0)){
3441 old_growth = 0;
3443 lvalue[i++] = cpystr(q);
3446 /* check to see if we still need to build a new list */
3447 if(!(old_growth || hir || osr))
3448 return;
3450 if(hir)
3451 lvalue[i++] = "include-header-in-reply";
3452 if(osr)
3453 lvalue[i++] = "signature-at-bottom";
3454 if(old_growth)
3455 lvalue[i++] = "old-growth";
3456 lvalue[i] = NULL;
3457 set_variable_list(V_FEATURE_LIST, lvalue, TRUE, Main);
3461 void
3462 set_current_pattern_vals(struct pine *ps)
3464 struct variable *vars = ps->vars;
3466 set_current_val(&vars[V_PATTERNS], TRUE, TRUE);
3467 set_current_val(&vars[V_PAT_ROLES], TRUE, TRUE);
3468 set_current_val(&vars[V_PAT_FILTS], TRUE, TRUE);
3469 set_current_val(&vars[V_PAT_FILTS_OLD], TRUE, TRUE);
3470 set_current_val(&vars[V_PAT_SCORES], TRUE, TRUE);
3471 set_current_val(&vars[V_PAT_SCORES_OLD], TRUE, TRUE);
3472 set_current_val(&vars[V_PAT_INCOLS], TRUE, TRUE);
3473 set_current_val(&vars[V_PAT_OTHER], TRUE, TRUE);
3474 set_current_val(&vars[V_PAT_SRCH], TRUE, TRUE);
3477 * If old pattern variable (V_PATTERNS) is set and the new ones aren't
3478 * in the config file, then convert the old data into the new variables.
3479 * It isn't quite that simple, though, because we don't store unset
3480 * variables in remote pinercs. Check for the variables but if we
3481 * don't find any of them, also check the version number. This change was
3482 * made in version 4.30. We could just check that except that we're
3483 * worried somebody will make an incompatible version number change in
3484 * their local version, and will break this. So we check both the
3485 * version # and the var_in_pinerc things to be safer.
3487 if(vars[V_PATTERNS].current_val.l
3488 && vars[V_PATTERNS].current_val.l[0]
3489 && !var_in_pinerc(vars[V_PAT_ROLES].name)
3490 && !var_in_pinerc(vars[V_PAT_FILTS].name)
3491 && !var_in_pinerc(vars[V_PAT_FILTS_OLD].name)
3492 && !var_in_pinerc(vars[V_PAT_SCORES].name)
3493 && !var_in_pinerc(vars[V_PAT_SCORES_OLD].name)
3494 && !var_in_pinerc(vars[V_PAT_INCOLS].name)
3495 && isdigit((unsigned char) ps->pine_pre_vers[0])
3496 && ps->pine_pre_vers[1] == '.'
3497 && isdigit((unsigned char) ps->pine_pre_vers[2])
3498 && isdigit((unsigned char) ps->pine_pre_vers[3])
3499 && strncmp(ps->pine_pre_vers, "4.30", 4) < 0){
3500 convert_pattern_data();
3504 * Otherwise, if FILTS_OLD is set and FILTS isn't in the config file,
3505 * convert FILTS_OLD to FILTS. Same for SCORES.
3506 * The reason FILTS was changed was so we could change the
3507 * semantics of how rules work when there are pieces in the rule that
3508 * we don't understand. At the same time as the FILTS change we added
3509 * a rule to detect 8bitSubjects. So a user might have a filter that
3510 * deletes messages with 8bitSubjects. The problem is that that same
3511 * filter in a FILTS_OLD pine would match because it would ignore the
3512 * 8bitSubject part of the pattern and match on the rest. So we changed
3513 * the semantics so that rules with unknown bits would be ignored
3514 * instead of used. We had to change variable names at the same time
3515 * because we were adding the 8bit thing and the old pines are still
3516 * out there. Filters and Scores can both be dangerous. Roles, Colors,
3517 * and Other seem less dangerous so not worth adding a new variable.
3518 * This was changed in 4.50.
3520 else{
3521 if(vars[V_PAT_FILTS_OLD].current_val.l
3522 && vars[V_PAT_FILTS_OLD].current_val.l[0]
3523 && !var_in_pinerc(vars[V_PAT_FILTS].name)
3524 && !var_in_pinerc(vars[V_PAT_SCORES].name)
3525 && isdigit((unsigned char) ps->pine_pre_vers[0])
3526 && ps->pine_pre_vers[1] == '.'
3527 && isdigit((unsigned char) ps->pine_pre_vers[2])
3528 && isdigit((unsigned char) ps->pine_pre_vers[3])
3529 && strncmp(ps->pine_pre_vers, "4.50", 4) < 0){
3530 convert_filts_pattern_data();
3533 if(vars[V_PAT_SCORES_OLD].current_val.l
3534 && vars[V_PAT_SCORES_OLD].current_val.l[0]
3535 && !var_in_pinerc(vars[V_PAT_FILTS].name)
3536 && !var_in_pinerc(vars[V_PAT_SCORES].name)
3537 && isdigit((unsigned char) ps->pine_pre_vers[0])
3538 && ps->pine_pre_vers[1] == '.'
3539 && isdigit((unsigned char) ps->pine_pre_vers[2])
3540 && isdigit((unsigned char) ps->pine_pre_vers[3])
3541 && strncmp(ps->pine_pre_vers, "4.50", 4) < 0){
3542 convert_scores_pattern_data();
3546 if(vars[V_PAT_ROLES].post_user_val.l)
3547 ps_global->ew_for_role_take = Post;
3548 else
3549 ps_global->ew_for_role_take = Main;
3551 if(vars[V_PAT_FILTS].post_user_val.l)
3552 ps_global->ew_for_filter_take = Post;
3553 else
3554 ps_global->ew_for_filter_take = Main;
3556 if(vars[V_PAT_SCORES].post_user_val.l)
3557 ps_global->ew_for_score_take = Post;
3558 else
3559 ps_global->ew_for_score_take = Main;
3561 if(vars[V_PAT_INCOLS].post_user_val.l)
3562 ps_global->ew_for_incol_take = Post;
3563 else
3564 ps_global->ew_for_incol_take = Main;
3566 if(vars[V_PAT_OTHER].post_user_val.l)
3567 ps_global->ew_for_other_take = Post;
3568 else
3569 ps_global->ew_for_other_take = Main;
3571 if(vars[V_PAT_SRCH].post_user_val.l)
3572 ps_global->ew_for_srch_take = Post;
3573 else
3574 ps_global->ew_for_srch_take = Main;
3579 * Foreach of the config files;
3580 * transfer the data to the new variables.
3582 void
3583 convert_pattern_data(void)
3585 convert_pinerc_patterns(PAT_USE_MAIN);
3586 convert_pinerc_patterns(PAT_USE_POST);
3590 void
3591 convert_filts_pattern_data(void)
3593 convert_pinerc_filts_patterns(PAT_USE_MAIN);
3594 convert_pinerc_filts_patterns(PAT_USE_POST);
3598 void
3599 convert_scores_pattern_data(void)
3601 convert_pinerc_scores_patterns(PAT_USE_MAIN);
3602 convert_pinerc_scores_patterns(PAT_USE_POST);
3607 * Foreach of the four variables, transfer the data for this config file
3608 * from the old patterns variable. We don't have to convert OTHER patterns
3609 * or SRCH patterns because they didn't exist in pines without patterns-other.
3611 * If the original variable had patlines with type File then we convert
3612 * all of the individual patterns to type Lit, because each pattern can
3613 * be of any category. Lit patterns are better tested, anyway.
3615 void
3616 convert_pinerc_patterns(long int use_flags)
3618 long old_rflags;
3619 long rflags;
3620 PAT_S *pat;
3621 PAT_STATE pstate;
3622 ACTION_S *act;
3624 old_rflags = (ROLE_OLD_PAT | use_flags);
3626 rflags = 0L;
3627 if(any_patterns(old_rflags, &pstate)){
3628 dprint((2, "converting old patterns to new (%s)\n", (use_flags == PAT_USE_MAIN) ? "Main" : "Post"));
3629 for(pat = first_pattern(&pstate);
3630 pat;
3631 pat = next_pattern(&pstate)){
3632 if((act = pat->action) != NULL){
3633 if(act->is_a_role &&
3634 add_to_pattern(pat, ROLE_DO_ROLES | use_flags))
3635 rflags |= ROLE_DO_ROLES;
3636 if(act->is_a_incol &&
3637 add_to_pattern(pat, ROLE_DO_INCOLS | use_flags))
3638 rflags |= ROLE_DO_INCOLS;
3639 if(act->is_a_score &&
3640 add_to_pattern(pat, ROLE_DO_SCORES | use_flags))
3641 rflags |= ROLE_DO_SCORES;
3642 if(act->is_a_filter &&
3643 add_to_pattern(pat, ROLE_DO_FILTER | use_flags))
3644 rflags |= ROLE_DO_FILTER;
3648 if(rflags)
3649 if(write_patterns(rflags | use_flags))
3650 dprint((1,
3651 "Trouble converting patterns to new variable\n"));
3657 * If the original variable had patlines with type File then we convert
3658 * all of the individual patterns to type Lit, because each pattern can
3659 * be of any category. Lit patterns are better tested, anyway.
3661 void
3662 convert_pinerc_filts_patterns(long int use_flags)
3664 long old_rflags;
3665 long rflags;
3666 PAT_S *pat;
3667 PAT_STATE pstate;
3668 ACTION_S *act;
3670 old_rflags = (ROLE_OLD_FILT | use_flags);
3672 rflags = 0L;
3673 if(any_patterns(old_rflags, &pstate)){
3674 dprint((2, "converting old filter patterns to new (%s)\n", (use_flags == PAT_USE_MAIN) ? "Main" : "Post"));
3675 for(pat = first_pattern(&pstate);
3676 pat;
3677 pat = next_pattern(&pstate)){
3678 if((act = pat->action) != NULL){
3679 if(act->is_a_filter &&
3680 add_to_pattern(pat, ROLE_DO_FILTER | use_flags))
3681 rflags |= ROLE_DO_FILTER;
3685 if(rflags)
3686 if(write_patterns(rflags | use_flags))
3687 dprint((1,
3688 "Trouble converting filter patterns to new variable\n"));
3694 * If the original variable had patlines with type File then we convert
3695 * all of the individual patterns to type Lit, because each pattern can
3696 * be of any category. Lit patterns are better tested, anyway.
3698 void
3699 convert_pinerc_scores_patterns(long int use_flags)
3701 long old_rflags;
3702 long rflags;
3703 PAT_S *pat;
3704 PAT_STATE pstate;
3705 ACTION_S *act;
3707 old_rflags = (ROLE_OLD_SCORE | use_flags);
3709 rflags = 0L;
3710 if(any_patterns(old_rflags, &pstate)){
3711 dprint((2, "converting old scores patterns to new (%s)\n", (use_flags == PAT_USE_MAIN) ? "Main" : "Post"));
3712 for(pat = first_pattern(&pstate);
3713 pat;
3714 pat = next_pattern(&pstate)){
3715 if((act = pat->action) != NULL){
3716 if(act->is_a_score &&
3717 add_to_pattern(pat, ROLE_DO_SCORES | use_flags))
3718 rflags |= ROLE_DO_SCORES;
3722 if(rflags)
3723 if(write_patterns(rflags | use_flags))
3724 dprint((1,
3725 "Trouble converting scores patterns to new variable\n"));
3731 * set_old_growth_bits - Command used to set or unset old growth set
3732 * of features
3734 void
3735 set_old_growth_bits(struct pine *ps, int val)
3737 int i;
3739 for(i = 1; i <= F_FEATURE_LIST_COUNT; i++)
3740 if(test_old_growth_bits(ps, i))
3741 F_SET(i, ps, val);
3747 * test_old_growth_bits - Test to see if all the old growth bits are on,
3748 * *or* if a particular feature index is in the old
3749 * growth set.
3751 * WEIRD ALERT: if index == F_OLD_GROWTH bit values are tested
3752 * otherwise a bits existence in the set is tested!!!
3754 * BUG: this will break if an old growth feature number is ever >= 32.
3757 test_old_growth_bits(struct pine *ps, int index)
3760 * this list defines F_OLD_GROWTH set
3762 static unsigned long old_growth_bits = ((1 << F_ENABLE_FULL_HDR) |
3763 (1 << F_ENABLE_PIPE) |
3764 (1 << F_ENABLE_TAB_COMPLETE) |
3765 (1 << F_QUIT_WO_CONFIRM) |
3766 (1 << F_ENABLE_JUMP) |
3767 (1 << F_ENABLE_ALT_ED) |
3768 (1 << F_ENABLE_BOUNCE) |
3769 (1 << F_ENABLE_AGG_OPS) |
3770 (1 << F_ENABLE_FLAG) |
3771 (1 << F_CAN_SUSPEND));
3772 if(index >= 32)
3773 return(0);
3775 if(index == F_OLD_GROWTH){
3776 for(index = 1; index <= F_FEATURE_LIST_COUNT; index++)
3777 if(((1 << index) & old_growth_bits) && F_OFF(index, ps))
3778 return(0);
3780 return(1);
3782 else
3783 return((1 << index) & old_growth_bits);
3788 * Side effect is that the appropriate global variable is set, and the
3789 * appropriate current_val is set.
3791 void
3792 cur_rule_value(struct variable *var, int expand, int cmdline)
3794 int i;
3795 NAMEVAL_S *v;
3797 set_current_val(var, expand, cmdline);
3799 if(var == &ps_global->vars[V_SAVED_MSG_NAME_RULE]){
3800 if(ps_global->VAR_SAVED_MSG_NAME_RULE)
3801 for(i = 0; (v = save_msg_rules(i)); i++)
3802 if(!strucmp(ps_global->VAR_SAVED_MSG_NAME_RULE, S_OR_L(v))){
3803 ps_global->save_msg_rule = v->value;
3804 break;
3807 #ifndef _WINDOWS
3808 else if(var == &ps_global->vars[V_COLOR_STYLE]){
3809 if(ps_global->VAR_COLOR_STYLE)
3810 for(i = 0; (v = col_style(i)); i++)
3811 if(!strucmp(ps_global->VAR_COLOR_STYLE, S_OR_L(v))){
3812 ps_global->color_style = v->value;
3813 break;
3816 #endif
3817 else if(var == &ps_global->vars[V_INDEX_COLOR_STYLE]){
3818 if(ps_global->VAR_INDEX_COLOR_STYLE)
3819 for(i = 0; (v = index_col_style(i)); i++)
3820 if(!strucmp(ps_global->VAR_INDEX_COLOR_STYLE, S_OR_L(v))){
3821 ps_global->index_color_style = v->value;
3822 break;
3825 else if(var == &ps_global->vars[V_TITLEBAR_COLOR_STYLE]){
3826 if(ps_global->VAR_TITLEBAR_COLOR_STYLE)
3827 for(i = 0; (v = titlebar_col_style(i)); i++)
3828 if(!strucmp(ps_global->VAR_TITLEBAR_COLOR_STYLE, S_OR_L(v))){
3829 ps_global->titlebar_color_style = v->value;
3830 break;
3833 else if(var == &ps_global->vars[V_FCC_RULE]){
3834 if(ps_global->VAR_FCC_RULE)
3835 for(i = 0; (v = fcc_rules(i)); i++)
3836 if(!strucmp(ps_global->VAR_FCC_RULE, S_OR_L(v))){
3837 ps_global->fcc_rule = v->value;
3838 break;
3841 else if(var == &ps_global->vars[V_GOTO_DEFAULT_RULE]){
3842 if(ps_global->VAR_GOTO_DEFAULT_RULE)
3843 for(i = 0; (v = goto_rules(i)); i++)
3844 if(!strucmp(ps_global->VAR_GOTO_DEFAULT_RULE, S_OR_L(v))){
3845 ps_global->goto_default_rule = v->value;
3846 break;
3849 else if(var == &ps_global->vars[V_INCOMING_STARTUP]){
3850 if(ps_global->VAR_INCOMING_STARTUP)
3851 for(i = 0; (v = incoming_startup_rules(i)); i++)
3852 if(!strucmp(ps_global->VAR_INCOMING_STARTUP, S_OR_L(v))){
3853 ps_global->inc_startup_rule = v->value;
3854 break;
3857 else if(var == &ps_global->vars[V_PRUNING_RULE]){
3858 if(ps_global->VAR_PRUNING_RULE)
3859 for(i = 0; (v = pruning_rules(i)); i++)
3860 if(!strucmp(ps_global->VAR_PRUNING_RULE, S_OR_L(v))){
3861 ps_global->pruning_rule = v->value;
3862 break;
3865 else if(var == &ps_global->vars[V_REOPEN_RULE]){
3866 if(ps_global->VAR_REOPEN_RULE)
3867 for(i = 0; (v = reopen_rules(i)); i++)
3868 if(!strucmp(ps_global->VAR_REOPEN_RULE, S_OR_L(v))){
3869 ps_global->reopen_rule = v->value;
3870 break;
3873 else if(var == &ps_global->vars[V_FLD_SORT_RULE]){
3874 if(ps_global->VAR_FLD_SORT_RULE)
3875 for(i = 0; (v = fld_sort_rules(i)); i++)
3876 if(!strucmp(ps_global->VAR_FLD_SORT_RULE, S_OR_L(v))){
3877 ps_global->fld_sort_rule = v->value;
3878 break;
3881 else if(var == &ps_global->vars[V_AB_SORT_RULE]){
3882 if(ps_global->VAR_AB_SORT_RULE)
3883 for(i = 0; (v = ab_sort_rules(i)); i++)
3884 if(!strucmp(ps_global->VAR_AB_SORT_RULE, S_OR_L(v))){
3885 ps_global->ab_sort_rule = v->value;
3886 break;
3889 else if(var == &ps_global->vars[V_THREAD_DISP_STYLE]){
3890 if(ps_global->VAR_THREAD_DISP_STYLE)
3891 for(i = 0; (v = thread_disp_styles(i)); i++)
3892 if(!strucmp(ps_global->VAR_THREAD_DISP_STYLE, S_OR_L(v))){
3893 ps_global->thread_disp_style = v->value;
3894 break;
3897 else if(var == &ps_global->vars[V_THREAD_INDEX_STYLE]){
3898 if(ps_global->VAR_THREAD_INDEX_STYLE)
3899 for(i = 0; (v = thread_index_styles(i)); i++)
3900 if(!strucmp(ps_global->VAR_THREAD_INDEX_STYLE, S_OR_L(v))){
3901 ps_global->thread_index_style = v->value;
3902 break;
3909 * Standard way to get at save message rules...
3911 NAMEVAL_S *
3912 save_msg_rules(int index)
3914 static NAMEVAL_S save_rules[] = {
3915 {"by-from", NULL, SAV_RULE_FROM},
3916 {"by-nick-of-from", NULL, SAV_RULE_NICK_FROM_DEF},
3917 {"by-nick-of-from-then-from", NULL, SAV_RULE_NICK_FROM},
3918 {"by-fcc-of-from", NULL, SAV_RULE_FCC_FROM_DEF},
3919 {"by-fcc-of-from-then-from", NULL, SAV_RULE_FCC_FROM},
3920 {"by-realname-of-from", NULL, SAV_RULE_RN_FROM_DEF},
3921 {"by-realname-of-from-then-from", NULL, SAV_RULE_RN_FROM},
3922 {"by-sender", NULL, SAV_RULE_SENDER},
3923 {"by-nick-of-sender", NULL, SAV_RULE_NICK_SENDER_DEF},
3924 {"by-nick-of-sender-then-sender", NULL, SAV_RULE_NICK_SENDER},
3925 {"by-fcc-of-sender", NULL, SAV_RULE_FCC_SENDER_DEF},
3926 {"by-fcc-of-sender-then-sender", NULL, SAV_RULE_FCC_SENDER},
3927 {"by-realname-of-sender", NULL, SAV_RULE_RN_SENDER_DEF},
3928 {"by-realname-of-sender-then-sender", NULL, SAV_RULE_RN_SENDER},
3929 {"by-recipient", NULL, SAV_RULE_RECIP},
3930 {"by-nick-of-recip", NULL, SAV_RULE_NICK_RECIP_DEF},
3931 {"by-nick-of-recip-then-recip", NULL, SAV_RULE_NICK_RECIP},
3932 {"by-fcc-of-recip", NULL, SAV_RULE_FCC_RECIP_DEF},
3933 {"by-fcc-of-recip-then-recip", NULL, SAV_RULE_FCC_RECIP},
3934 {"by-realname-of-recip", NULL, SAV_RULE_RN_RECIP_DEF},
3935 {"by-realname-of-recip-then-recip", NULL, SAV_RULE_RN_RECIP},
3936 {"by-replyto", NULL, SAV_RULE_REPLYTO},
3937 {"by-nick-of-replyto", NULL, SAV_RULE_NICK_REPLYTO_DEF},
3938 {"by-nick-of-replyto-then-replyto", NULL, SAV_RULE_NICK_REPLYTO},
3939 {"by-fcc-of-replyto", NULL, SAV_RULE_FCC_REPLYTO_DEF},
3940 {"by-fcc-of-replyto-then-replyto", NULL, SAV_RULE_FCC_REPLYTO},
3941 {"by-realname-of-replyto", NULL, SAV_RULE_RN_REPLYTO_DEF},
3942 {"by-realname-of-replyto-then-replyto", NULL, SAV_RULE_RN_REPLYTO},
3943 {"last-folder-used", NULL, SAV_RULE_LAST},
3944 {"default-folder", NULL, SAV_RULE_DEFLT}
3947 return((index >= 0 && index < (sizeof(save_rules)/sizeof(save_rules[0])))
3948 ? &save_rules[index] : NULL);
3953 * Standard way to get at fcc rules...
3955 NAMEVAL_S *
3956 fcc_rules(int index)
3958 static NAMEVAL_S f_rules[] = {
3959 {"default-fcc", NULL, FCC_RULE_DEFLT},
3960 {"last-fcc-used", NULL, FCC_RULE_LAST},
3961 {"by-recipient", NULL, FCC_RULE_RECIP},
3962 {"by-nickname", NULL, FCC_RULE_NICK},
3963 {"by-nick-then-recip", NULL, FCC_RULE_NICK_RECIP},
3964 {"current-folder", NULL, FCC_RULE_CURRENT}
3967 return((index >= 0 && index < (sizeof(f_rules)/sizeof(f_rules[0])))
3968 ? &f_rules[index] : NULL);
3973 * Standard way to get at addrbook sort rules...
3975 NAMEVAL_S *
3976 ab_sort_rules(int index)
3978 static NAMEVAL_S ab_rules[] = {
3979 {"fullname-with-lists-last", NULL, AB_SORT_RULE_FULL_LISTS},
3980 {"fullname", NULL, AB_SORT_RULE_FULL},
3981 {"nickname-with-lists-last", NULL, AB_SORT_RULE_NICK_LISTS},
3982 {"nickname", NULL, AB_SORT_RULE_NICK},
3983 {"dont-sort", NULL, AB_SORT_RULE_NONE}
3986 return((index >= 0 && index < (sizeof(ab_rules)/sizeof(ab_rules[0])))
3987 ? &ab_rules[index] : NULL);
3992 * Standard way to get at color styles.
3994 NAMEVAL_S *
3995 col_style(int index)
3997 static NAMEVAL_S col_styles[] = {
3998 {"no-color", NULL, COL_NONE},
3999 {"use-termdef", NULL, COL_TERMDEF},
4000 {"force-ansi-8color", NULL, COL_ANSI8},
4001 {"force-ansi-16color", NULL, COL_ANSI16},
4002 {"force-xterm-256color", NULL, COL_ANSI256}
4005 return((index >= 0 && index < (sizeof(col_styles)/sizeof(col_styles[0])))
4006 ? &col_styles[index] : NULL);
4011 * Standard way to get at index color styles.
4013 NAMEVAL_S *
4014 index_col_style(int index)
4016 static NAMEVAL_S ind_col_styles[] = {
4017 {"flip-colors", NULL, IND_COL_FLIP},
4018 {"reverse", NULL, IND_COL_REV},
4019 {"reverse-fg", NULL, IND_COL_FG},
4020 {"reverse-fg-no-ambiguity", NULL, IND_COL_FG_NOAMBIG},
4021 {"reverse-bg", NULL, IND_COL_BG},
4022 {"reverse-bg-no-ambiguity", NULL, IND_COL_BG_NOAMBIG}
4025 return((index >= 0 && index < (sizeof(ind_col_styles)/sizeof(ind_col_styles[0]))) ? &ind_col_styles[index] : NULL);
4030 * Standard way to get at titlebar color styles.
4032 NAMEVAL_S *
4033 titlebar_col_style(int index)
4035 static NAMEVAL_S tbar_col_styles[] = {
4036 {"default", NULL, TBAR_COLOR_DEFAULT},
4037 {"indexline", NULL, TBAR_COLOR_INDEXLINE},
4038 {"reverse-indexline", NULL, TBAR_COLOR_REV_INDEXLINE}
4041 return((index >= 0 && index < (sizeof(tbar_col_styles)/sizeof(tbar_col_styles[0]))) ? &tbar_col_styles[index] : NULL);
4046 * Standard way to get at folder sort rules...
4048 NAMEVAL_S *
4049 fld_sort_rules(int index)
4051 static NAMEVAL_S fdl_rules[] = {
4052 {"alphabetical", NULL, FLD_SORT_ALPHA},
4053 {"alpha-with-dirs-last", NULL, FLD_SORT_ALPHA_DIR_LAST},
4054 {"alpha-with-dirs-first", NULL, FLD_SORT_ALPHA_DIR_FIRST}
4057 return((index >= 0 && index < (sizeof(fdl_rules)/sizeof(fdl_rules[0])))
4058 ? &fdl_rules[index] : NULL);
4063 * Standard way to get at incoming startup rules...
4065 NAMEVAL_S *
4066 incoming_startup_rules(int index)
4068 static NAMEVAL_S is_rules[] = {
4069 {"first-unseen", NULL, IS_FIRST_UNSEEN},
4070 {"first-recent", NULL, IS_FIRST_RECENT},
4071 {"first-important", NULL, IS_FIRST_IMPORTANT},
4072 {"first-important-or-unseen", NULL, IS_FIRST_IMPORTANT_OR_UNSEEN},
4073 {"first-important-or-recent", NULL, IS_FIRST_IMPORTANT_OR_RECENT},
4074 {"first", NULL, IS_FIRST},
4075 {"last", NULL, IS_LAST}
4078 return((index >= 0 && index < (sizeof(is_rules)/sizeof(is_rules[0])))
4079 ? &is_rules[index] : NULL);
4083 NAMEVAL_S *
4084 startup_rules(int index)
4086 static NAMEVAL_S is2_rules[] = {
4087 {"first-unseen", NULL, IS_FIRST_UNSEEN},
4088 {"first-recent", NULL, IS_FIRST_RECENT},
4089 {"first-important", NULL, IS_FIRST_IMPORTANT},
4090 {"first-important-or-unseen", NULL, IS_FIRST_IMPORTANT_OR_UNSEEN},
4091 {"first-important-or-recent", NULL, IS_FIRST_IMPORTANT_OR_RECENT},
4092 {"first", NULL, IS_FIRST},
4093 {"last", NULL, IS_LAST},
4094 {"default", NULL, IS_NOTSET}
4097 return((index >= 0 && index < (sizeof(is2_rules)/sizeof(is2_rules[0])))
4098 ? &is2_rules[index] : NULL);
4103 * Standard way to get at pruning-rule values.
4105 NAMEVAL_S *
4106 pruning_rules(int index)
4108 static NAMEVAL_S pr_rules[] = {
4109 {"ask about rename, ask about deleting","ask-ask", PRUNE_ASK_AND_ASK},
4110 {"ask about rename, don't delete", "ask-no", PRUNE_ASK_AND_NO},
4111 {"always rename, ask about deleting", "yes-ask", PRUNE_YES_AND_ASK},
4112 {"always rename, don't delete", "yes-no", PRUNE_YES_AND_NO},
4113 {"don't rename, ask about deleting", "no-ask", PRUNE_NO_AND_ASK},
4114 {"don't rename, don't delete", "no-no", PRUNE_NO_AND_NO}
4117 return((index >= 0 && index < (sizeof(pr_rules)/sizeof(pr_rules[0])))
4118 ? &pr_rules[index] : NULL);
4123 * Standard way to get at reopen-rule values.
4125 NAMEVAL_S *
4126 reopen_rules(int index)
4128 static NAMEVAL_S ro_rules[] = {
4129 /* TRANSLATORS: short description of a feature option */
4130 {"Always reopen", "yes-yes",
4131 REOPEN_YES_YES},
4132 /* TRANSLATORS: short description of a feature option, default in brackets */
4133 {"Yes for POP/NNTP, Ask about other remote [Yes]", "yes-ask-y",
4134 REOPEN_YES_ASK_Y},
4135 /* TRANSLATORS: short description of a feature option, default in brackets */
4136 {"Yes for POP/NNTP, Ask about other remote [No]", "yes-ask-n",
4137 REOPEN_YES_ASK_N},
4138 /* TRANSLATORS: short description of a feature option */
4139 {"Yes for POP/NNTP, No for other remote", "yes-no",
4140 REOPEN_YES_NO},
4141 /* TRANSLATORS: short description of a feature option, default in brackets */
4142 {"Always ask [Yes]", "ask-ask-y",
4143 REOPEN_ASK_ASK_Y},
4144 /* TRANSLATORS: short description of a feature option, default in brackets */
4145 {"Always ask [No]", "ask-ask-n",
4146 REOPEN_ASK_ASK_N},
4147 /* TRANSLATORS: short description of a feature option, default in brackets */
4148 {"Ask about POP/NNTP [Yes], No for other remote", "ask-no-y",
4149 REOPEN_ASK_NO_Y},
4150 /* TRANSLATORS: short description of a feature option, default in brackets */
4151 {"Ask about POP/NNTP [No], No for other remote", "ask-no-n",
4152 REOPEN_ASK_NO_N},
4153 /* TRANSLATORS: short description of a feature option */
4154 {"Never reopen", "no-no",
4155 REOPEN_NO_NO},
4158 return((index >= 0 && index < (sizeof(ro_rules)/sizeof(ro_rules[0])))
4159 ? &ro_rules[index] : NULL);
4164 * Standard way to get at thread_disp_style values.
4166 NAMEVAL_S *
4167 thread_disp_styles(int index)
4169 static NAMEVAL_S td_styles[] = {
4170 {"none", "none", THREAD_NONE},
4171 {"show-thread-structure", "struct", THREAD_STRUCT},
4172 {"mutt-like", "mutt", THREAD_MUTTLIKE},
4173 {"indent-subject-1", "subj1", THREAD_INDENT_SUBJ1},
4174 {"indent-subject-2", "subj2", THREAD_INDENT_SUBJ2},
4175 {"indent-from-1", "from1", THREAD_INDENT_FROM1},
4176 {"indent-from-2", "from2", THREAD_INDENT_FROM2},
4177 {"show-structure-in-from", "struct-from", THREAD_STRUCT_FROM}
4180 return((index >= 0 && index < (sizeof(td_styles)/sizeof(td_styles[0])))
4181 ? &td_styles[index] : NULL);
4186 * Standard way to get at thread_index_style values.
4188 NAMEVAL_S *
4189 thread_index_styles(int index)
4191 static NAMEVAL_S ti_styles[] = {
4192 {"regular-index-with-expanded-threads", "exp", THRDINDX_EXP},
4193 {"regular-index-with-collapsed-threads","coll", THRDINDX_COLL},
4194 {"separate-index-screen-always", "sep", THRDINDX_SEP},
4195 {"separate-index-screen-except-for-single-messages","sep-auto",
4196 THRDINDX_SEP_AUTO}
4199 return((index >= 0 && index < (sizeof(ti_styles)/sizeof(ti_styles[0])))
4200 ? &ti_styles[index] : NULL);
4205 * Standard way to get at goto default rules...
4207 NAMEVAL_S *
4208 goto_rules(int index)
4210 static NAMEVAL_S g_rules[] = {
4211 {"folder-in-first-collection", NULL, GOTO_FIRST_CLCTN},
4212 {"inbox-or-folder-in-first-collection", NULL, GOTO_INBOX_FIRST_CLCTN},
4213 {"inbox-or-folder-in-recent-collection", NULL, GOTO_INBOX_RECENT_CLCTN},
4214 {"first-collection-with-inbox-default", NULL, GOTO_FIRST_CLCTN_DEF_INBOX},
4215 {"most-recent-folder", NULL, GOTO_LAST_FLDR}
4218 return((index >= 0 && index < (sizeof(g_rules)/sizeof(g_rules[0])))
4219 ? &g_rules[index] : NULL);
4223 NAMEVAL_S *
4224 pat_fldr_types(int index)
4226 static NAMEVAL_S pat_fldr_list[] = {
4227 {"Any", "ANY", FLDR_ANY},
4228 {"News", "NEWS", FLDR_NEWS},
4229 {"Email", "EMAIL", FLDR_EMAIL},
4230 {"Specific (Enter Incoming Nicknames or use ^T)", "SPEC", FLDR_SPECIFIC}
4233 return((index >= 0 &&
4234 index < (sizeof(pat_fldr_list)/sizeof(pat_fldr_list[0])))
4235 ? &pat_fldr_list[index] : NULL);
4239 NAMEVAL_S *
4240 inabook_fldr_types(int indexarg)
4242 static NAMEVAL_S inabook_fldr_list[] = {
4243 {"Don't care, always matches", "E", IAB_EITHER},
4244 {"Yes, in any address book", "YES", IAB_YES},
4245 {"No, not in any address book", "NO", IAB_NO},
4246 {"Yes, in specific address books", "SYES", IAB_SPEC_YES},
4247 {"No, not in any of specific address books", "SNO", IAB_SPEC_NO}
4250 int index = indexarg & IAB_TYPE_MASK;
4252 return((index >= 0 &&
4253 index < (sizeof(inabook_fldr_list)/sizeof(inabook_fldr_list[0])))
4254 ? &inabook_fldr_list[index] : NULL);
4258 NAMEVAL_S *
4259 filter_types(int index)
4261 static NAMEVAL_S filter_type_list[] = {
4262 {"Just Set Message Status", "NONE", FILTER_STATE},
4263 {"Delete", "DEL", FILTER_KILL},
4264 {"Move (Enter folder name(s) in primary collection, or use ^T)",
4265 "FLDR", FILTER_FOLDER}
4268 return((index >= 0 &&
4269 index < (sizeof(filter_type_list)/sizeof(filter_type_list[0])))
4270 ? &filter_type_list[index] : NULL);
4274 NAMEVAL_S *
4275 role_repl_types(int index)
4277 static NAMEVAL_S role_repl_list[] = {
4278 {"Never", "NO", ROLE_REPL_NO},
4279 {"With confirmation", "YES", ROLE_REPL_YES},
4280 {"Without confirmation", "NC", ROLE_REPL_NOCONF}
4283 return((index >= 0 &&
4284 index < (sizeof(role_repl_list)/sizeof(role_repl_list[0])))
4285 ? &role_repl_list[index] : NULL);
4289 NAMEVAL_S *
4290 role_forw_types(int index)
4292 static NAMEVAL_S role_forw_list[] = {
4293 {"Never", "NO", ROLE_FORW_NO},
4294 {"With confirmation", "YES", ROLE_FORW_YES},
4295 {"Without confirmation", "NC", ROLE_FORW_NOCONF}
4298 return((index >= 0 &&
4299 index < (sizeof(role_forw_list)/sizeof(role_forw_list[0])))
4300 ? &role_forw_list[index] : NULL);
4304 NAMEVAL_S *
4305 role_comp_types(int index)
4307 static NAMEVAL_S role_comp_list[] = {
4308 {"Never", "NO", ROLE_COMP_NO},
4309 {"With confirmation", "YES", ROLE_COMP_YES},
4310 {"Without confirmation", "NC", ROLE_COMP_NOCONF}
4313 return((index >= 0 &&
4314 index < (sizeof(role_comp_list)/sizeof(role_comp_list[0])))
4315 ? &role_comp_list[index] : NULL);
4319 NAMEVAL_S *
4320 role_status_types(int index)
4322 static NAMEVAL_S role_status_list[] = {
4323 {"Don't care, always matches", "E", PAT_STAT_EITHER},
4324 {"Yes", "YES", PAT_STAT_YES},
4325 {"No", "NO", PAT_STAT_NO}
4328 return((index >= 0 &&
4329 index < (sizeof(role_status_list)/sizeof(role_status_list[0])))
4330 ? &role_status_list[index] : NULL);
4334 NAMEVAL_S *
4335 msg_state_types(int index)
4337 static NAMEVAL_S msg_state_list[] = {
4338 {"Don't change it", "LV", ACT_STAT_LEAVE},
4339 {"Set this state", "SET", ACT_STAT_SET},
4340 {"Clear this state", "CLR", ACT_STAT_CLEAR}
4343 return((index >= 0 &&
4344 index < (sizeof(msg_state_list)/sizeof(msg_state_list[0])))
4345 ? &msg_state_list[index] : NULL);
4349 #ifdef ENABLE_LDAP
4350 NAMEVAL_S *
4351 ldap_search_rules(int index)
4353 static NAMEVAL_S ldap_search_list[] = {
4354 {"contains", NULL, LDAP_SRCH_CONTAINS},
4355 {"equals", NULL, LDAP_SRCH_EQUALS},
4356 {"begins-with", NULL, LDAP_SRCH_BEGINS},
4357 {"ends-with", NULL, LDAP_SRCH_ENDS}
4360 return((index >= 0 &&
4361 index < (sizeof(ldap_search_list)/sizeof(ldap_search_list[0])))
4362 ? &ldap_search_list[index] : NULL);
4366 NAMEVAL_S *
4367 ldap_search_types(int index)
4369 static NAMEVAL_S ldap_types_list[] = {
4370 {"name", NULL, LDAP_TYPE_CN},
4371 {"surname", NULL, LDAP_TYPE_SUR},
4372 {"givenname", NULL, LDAP_TYPE_GIVEN},
4373 {"email", NULL, LDAP_TYPE_EMAIL},
4374 {"name-or-email", NULL, LDAP_TYPE_CN_EMAIL},
4375 {"surname-or-givenname", NULL, LDAP_TYPE_SUR_GIVEN},
4376 {"sur-or-given-or-name-or-email", NULL, LDAP_TYPE_SEVERAL}
4379 return((index >= 0 &&
4380 index < (sizeof(ldap_types_list)/sizeof(ldap_types_list[0])))
4381 ? &ldap_types_list[index] : NULL);
4385 NAMEVAL_S *
4386 ldap_search_scope(int index)
4388 static NAMEVAL_S ldap_scope_list[] = {
4389 {"base", NULL, LDAP_SCOPE_BASE},
4390 {"onelevel", NULL, LDAP_SCOPE_ONELEVEL},
4391 {"subtree", NULL, LDAP_SCOPE_SUBTREE}
4394 return((index >= 0 &&
4395 index < (sizeof(ldap_scope_list)/sizeof(ldap_scope_list[0])))
4396 ? &ldap_scope_list[index] : NULL);
4398 #endif
4402 * Choose from the global default, command line args, pinerc values to set
4403 * the actual value of the variable that we will use. Start at the top
4404 * and work down from higher to lower precedence.
4405 * For lists, we may inherit values from lower precedence
4406 * versions if that's the way the user specifies it.
4407 * The user can put INHERIT_DEFAULT as the first entry in a list and that
4408 * means it will inherit the current values, for example the values
4409 * from the global_val, or the value from the main_user_val could be
4410 * inherited in the post_user_val.
4412 void
4413 set_current_val(struct variable *var, int expand, int cmdline)
4415 int is_set[5], is_inherit[5];
4416 int i, j, k, cnt, start;
4417 char **tmp, **t, **list[5];
4418 char *p;
4420 dprint((9,
4421 "set_current_val(var=%s%s, expand=%d, cmdline=%d)\n",
4422 (var && var->name) ? var->name : "?",
4423 (var && var->is_list) ? " (list)" : "",
4424 expand, cmdline));
4426 if(!var)
4427 return;
4429 if(var->is_list){ /* variable is a list */
4431 for(j = 0; j < 5; j++){
4432 t = j==0 ? var->global_val.l :
4433 j==1 ? var->main_user_val.l :
4434 j==2 ? var->post_user_val.l :
4435 j==3 ? ((cmdline) ? var->cmdline_val.l : NULL) :
4436 var->fixed_val.l;
4438 is_set[j] = is_inherit[j] = 0;
4439 list[j] = NULL;
4441 if(t){
4442 if(!expand){
4443 is_set[j]++;
4444 list[j] = t;
4446 else{
4447 for(i = 0; t[i]; i++){
4448 if(expand_variables(tmp_20k_buf, SIZEOF_20KBUF, t[i],
4449 0)){
4450 /* successful expand */
4451 is_set[j]++;
4452 list[j] = t;
4453 break;
4458 if(list[j] && list[j][0] && !strcmp(list[j][0],INHERIT))
4459 is_inherit[j]++;
4463 cnt = 0;
4464 start = 0;
4465 /* count how many items in current_val list */
4466 /* Admin wants default, which is global_val. */
4467 if(var->is_fixed && var->fixed_val.l == NULL){
4468 cnt = 0;
4469 if(is_set[0]){
4470 for(; list[0][cnt]; cnt++)
4474 else{
4475 for(j = 0; j < 5; j++){
4476 if(is_set[j]){
4477 if(!is_inherit[j]){
4478 cnt = 0; /* reset */
4479 start = j;
4482 for(i = is_inherit[j] ? 1 : 0; list[j][i]; i++)
4483 cnt++;
4488 free_list_array(&var->current_val.l); /* clean up any old values */
4490 /* check to see if anything is set */
4491 if(is_set[0] + is_set[1] + is_set[2] + is_set[3] + is_set[4] > 0){
4492 var->current_val.l = (char **)fs_get((cnt+1)*sizeof(char *));
4493 tmp = var->current_val.l;
4494 if(var->is_fixed && var->fixed_val.l == NULL){
4495 if(is_set[0]){
4496 for(i = 0; list[0][i]; i++){
4497 if(!expand)
4498 *tmp++ = cpystr(list[0][i]);
4499 else if(expand_variables(tmp_20k_buf, SIZEOF_20KBUF,
4500 list[0][i], 0))
4501 *tmp++ = cpystr(tmp_20k_buf);
4505 else{
4506 for(j = start; j < 5; j++){
4507 if(is_set[j]){
4508 for(i = is_inherit[j] ? 1 : 0; list[j][i]; i++){
4509 if(!expand)
4510 *tmp++ = cpystr(list[j][i]);
4511 else if(expand_variables(tmp_20k_buf,SIZEOF_20KBUF,
4512 list[j][i], 0))
4513 *tmp++ = cpystr(tmp_20k_buf);
4519 *tmp = NULL;
4521 else
4522 var->current_val.l = NULL;
4524 else{ /* variable is not a list */
4525 char *strvar = NULL;
4527 for(j = 0; j < 5; j++){
4529 p = j==0 ? var->fixed_val.p :
4530 j==1 ? ((cmdline) ? var->cmdline_val.p : NULL) :
4531 j==2 ? var->post_user_val.p :
4532 j==3 ? var->main_user_val.p :
4533 var->global_val.p;
4535 is_set[j] = 0;
4537 if(p){
4538 if(!expand){
4539 is_set[j]++;
4540 if(!strvar)
4541 strvar = p;
4543 else if(expand_variables(tmp_20k_buf, SIZEOF_20KBUF, p,
4544 (var == &ps_global->vars[V_MAILCAP_PATH] ||
4545 var == &ps_global->vars[V_MIMETYPE_PATH]))){
4546 is_set[j]++;
4547 if(!strvar)
4548 strvar = p;
4553 /* Admin wants default, which is global_val. */
4554 if(var->is_fixed && var->fixed_val.p == NULL)
4555 strvar = var->global_val.p;
4557 if(var->current_val.p) /* free previous value */
4558 fs_give((void **)&var->current_val.p);
4560 if(strvar){
4561 if(!expand)
4562 var->current_val.p = cpystr(strvar);
4563 else{
4564 expand_variables(tmp_20k_buf, SIZEOF_20KBUF, strvar,
4565 (var == &ps_global->vars[V_MAILCAP_PATH] ||
4566 var == &ps_global->vars[V_MIMETYPE_PATH]));
4567 var->current_val.p = cpystr(tmp_20k_buf);
4570 else
4571 var->current_val.p = NULL;
4574 if(var->is_fixed && !is_inherit[4]){
4575 char **flist;
4576 int fixed_len, user_len;
4579 * sys mgr fixed this variable and user is trying to change it
4581 for(k = 1; !(ps_global->give_fixed_warning &&
4582 ps_global->fix_fixed_warning) && k <= 3; k++){
4583 if(is_set[k]){
4584 if(var->is_list){
4585 t = k==1 ? ((cmdline) ? var->cmdline_val.l : NULL) :
4586 k==2 ? var->post_user_val.l :
4587 var->main_user_val.l;
4589 /* If same length and same contents, don't warn. */
4590 for(flist=var->fixed_val.l; flist && *flist; flist++)
4591 ;/* just counting */
4593 fixed_len = var->fixed_val.l ? (flist - var->fixed_val.l)
4594 : 0;
4595 for(flist=t; flist && *flist; flist++)
4596 ;/* just counting */
4598 user_len = t ? (flist - t) : 0;
4599 if(user_len == fixed_len){
4600 for(i=0; i < user_len; i++){
4601 for(j=0; j < user_len; j++)
4602 if(!strucmp(t[i], var->fixed_val.l[j]))
4603 break;
4605 if(j == user_len){
4606 ps_global->give_fixed_warning = 1;
4607 if(k != 1)
4608 ps_global->fix_fixed_warning = 1;
4610 break;
4614 else{
4615 ps_global->give_fixed_warning = 1;
4616 if(k != 1)
4617 ps_global->fix_fixed_warning = 1;
4620 else{
4621 p = k==1 ? ((cmdline) ? var->cmdline_val.p : NULL) :
4622 k==2 ? var->post_user_val.p :
4623 var->main_user_val.p;
4625 if((var->fixed_val.p && !p) ||
4626 (!var->fixed_val.p && p) ||
4627 (var->fixed_val.p && p && strucmp(var->fixed_val.p, p))){
4628 ps_global->give_fixed_warning = 1;
4629 if(k != 1)
4630 ps_global->fix_fixed_warning = 1;
4639 void
4640 set_news_spec_current_val(int expand, int cmdline)
4642 struct variable *newsvar = &ps_global->vars[V_NEWS_SPEC];
4643 struct variable *fvar = &ps_global->vars[V_FOLDER_SPEC];
4645 /* check to see if it has a value */
4646 set_current_val(newsvar, expand, cmdline);
4649 * If no value, we might want to fake a value. We'll do that if
4650 * there is no news collection already defined in FOLDER_SPEC and if
4651 * there is also an NNTP_SERVER defined.
4653 if(!newsvar->current_val.l && ps_global->VAR_NNTP_SERVER &&
4654 ps_global->VAR_NNTP_SERVER[0] && ps_global->VAR_NNTP_SERVER[0][0] &&
4655 !news_in_folders(fvar)){
4656 char buf[MAXPATH];
4658 newsvar->global_val.l = (char **)fs_get(2 * sizeof(char *));
4659 snprintf(buf, sizeof(buf), "{%.*s/nntp}#news.[]", sizeof(buf)-20,
4660 ps_global->VAR_NNTP_SERVER[0]);
4661 newsvar->global_val.l[0] = cpystr(buf);
4662 newsvar->global_val.l[1] = NULL;
4663 set_current_val(newsvar, expand, cmdline);
4665 * But we're going to get rid of the fake global_val in case
4666 * things change.
4668 free_list_array(&newsvar->global_val.l);
4674 * Feature-list has to be handled separately from the other variables
4675 * because it is additive. The other variables choose one of command line,
4676 * or pine.conf, or pinerc. Feature list adds them. This could easily be
4677 * converted to a general purpose routine if we add more additive variables.
4679 * This works by replacing earlier values with later ones. That is, command
4680 * line settings have higher precedence than global settings and that is
4681 * accomplished by putting the command line features after the global
4682 * features in the list. When they are processed, the last one wins.
4684 * Feature-list also has a backwards compatibility hack.
4686 void
4687 set_feature_list_current_val(struct variable *var)
4689 char **list;
4690 char **list_fixed;
4691 char no_allow[50];
4692 int i, j, k, m,
4693 elems = 0;
4695 /* count the lists so we can allocate */
4696 for(m = 0; m < 6; m++){
4697 list = m==0 ? var->global_val.l :
4698 m==1 ? var->main_user_val.l :
4699 m==2 ? var->post_user_val.l :
4700 m==3 ? ps_global->feat_list_back_compat :
4701 m==4 ? var->cmdline_val.l :
4702 var->fixed_val.l;
4703 if(list)
4704 for(i = 0; list[i]; i++)
4705 elems++;
4708 list_fixed = var->fixed_val.l;
4710 if(var->current_val.l)
4711 free_list_array(&var->current_val.l);
4713 var->current_val.l = (char **)fs_get((elems+1) * sizeof(char *));
4716 * We need to warn the user if the sys mgr has restricted him or her
4717 * from changing a feature that he or she is trying to change.
4719 * We're not catching the old-growth macro since we're just comparing
4720 * strings. That is, it works correctly, but the user won't be warned
4721 * if the user old-growth and the mgr says no-quit-without-confirm.
4724 j = 0;
4725 strncpy(no_allow, "no-", 3);
4726 strncpy(no_allow+3, feature_list_name(F_ALLOW_CHANGING_FROM), sizeof(no_allow)-3-1);
4727 no_allow[sizeof(no_allow)-1] = '\0';
4729 for(m = 0; m < 6; m++){
4730 list = m==0 ? var->global_val.l :
4731 m==1 ? var->main_user_val.l :
4732 m==2 ? var->post_user_val.l :
4733 m==3 ? ps_global->feat_list_back_compat :
4734 m==4 ? var->cmdline_val.l :
4735 var->fixed_val.l;
4736 if(list)
4737 for(i = 0; list[i]; i++){
4738 var->current_val.l[j++] = cpystr(list[i]);
4740 /* this is the warning section */
4741 if(m >= 1 && m <= 4){
4742 for(k = 0; list_fixed && list_fixed[k]; k++){
4743 char *p, *q;
4744 p = list[i];
4745 q = list_fixed[k];
4746 if(!struncmp(p, "no-", 3))
4747 p += 3;
4748 if(!struncmp(q, "no-", 3))
4749 q += 3;
4750 if(!strucmp(q, p) && strucmp(list[i], list_fixed[k])){
4751 ps_global->give_fixed_warning = 1;
4752 if(m <= 2)
4753 ps_global->fix_fixed_warning = 1;
4757 else if(m == 5 && !strucmp(list[i], no_allow))
4758 ps_global->never_allow_changing_from = 1;
4762 #ifdef NEVER_ALLOW_CHANGING_FROM
4763 ps_global->never_allow_changing_from = 1;
4764 #endif
4766 var->current_val.l[j] = NULL;
4771 /*----------------------------------------------------------------------
4773 Expand Metacharacters/variables in file-names
4775 Read input line and expand shell-variables/meta-characters
4777 <input> <replaced by>
4778 $variable getenv("variable")
4779 ${variable} getenv("variable")
4780 ${variable:-defvalue} is getenv("variable") if variable is defined and
4781 is defvalue otherwise
4782 ~ getenv("HOME")
4783 \c c
4784 <others> <just copied>
4786 NOTE handling of braces in ${name} doesn't check much or do error recovery
4788 If colon_path is set, then we expand ~ not only at the start of linein,
4789 but also after each : in the path.
4791 ----*/
4792 #define is_allowed_envchar(C, S) ((S) == 0 ? !isspace((C)) && (C) != '/'\
4793 : (((C) >= 'a' && (C) <= 'z') \
4794 || ((C) >= 'A' && (C) <= 'Z') \
4795 || ((C) >= '0' && (C) <= '9')))
4797 char *
4798 expand_variables(char *lineout, size_t lineoutlen, char *linein, int colon_path)
4800 char *src = linein, *dest = lineout, *p;
4801 char *limit = lineout + lineoutlen;
4802 int envexpand = 0, sp;
4804 if(!linein)
4805 return(NULL);
4807 sp = strncmp(src,"LIT:pattern=\"/NICK=", strlen("LIT:pattern=\"/NICK=")) == 0;
4808 while(*src ){ /* something in input string */
4809 if(*src == '$' && *(src+1) == '$'){
4811 * $$ to escape chars we're interested in, else
4812 * it's up to the user of the variable to handle the
4813 * backslash...
4815 if(dest < limit)
4816 *dest++ = *++src; /* copy next as is */
4817 }else
4818 #if !(defined(DOS) || defined(OS2))
4819 if(*src == '\\' && *(src+1) == '$'){
4821 * backslash to escape chars we're interested in, else
4822 * it's up to the user of the variable to handle the
4823 * backslash...
4825 if(dest < limit)
4826 *dest++ = *++src; /* copy next as is */
4827 }else if(*src == '~' &&
4828 (src == linein || (colon_path && *(src-1) == ':'))){
4829 char buf[MAXPATH];
4830 int i;
4832 for(i = 0; i < sizeof(buf)-1 && src[i] && src[i] != '/'; i++)
4833 buf[i] = src[i];
4835 src += i; /* advance src pointer */
4836 buf[i] = '\0'; /* tie off buf string */
4837 fnexpand(buf, sizeof(buf)); /* expand the path */
4839 for(p = buf; dest < limit && (*dest = *p); p++, dest++)
4842 continue;
4843 }else
4844 #endif
4845 if(*src == '$'){ /* shell variable */
4846 char word[128+1], *colon = NULL, *rbrace = NULL;
4848 envexpand++; /* signal that we've expanded a var */
4849 src++; /* skip dollar */
4850 if(*src == '{'){ /* starts with brace? */
4851 src++;
4852 rbrace = strindex(src, '}');
4853 if(rbrace){
4854 /* look for default value */
4855 colon = strstr(src, ":-");
4856 if(colon && (rbrace < colon))
4857 colon = NULL;
4861 p = word;
4863 /* put the env variable to be looked up in word */
4864 if(rbrace){
4865 while(*src
4866 && (p-word < sizeof(word)-1)
4867 && ((colon && src < colon) || (!colon && src < rbrace))){
4868 if(isspace((unsigned char) *src)){
4870 * Illegal input. This should be an error of some
4871 * sort but instead of that we'll just backup to the
4872 * $ and treat it like it wasn't there.
4874 while(*src != '$')
4875 src--;
4877 envexpand--;
4878 goto just_copy;
4880 else
4881 *p++ = *src++;
4884 /* adjust src for next char */
4885 src = rbrace + 1;
4887 else{
4888 while(*src && is_allowed_envchar((unsigned char) *src, sp)
4889 && (p-word < sizeof(word)-1))
4890 *p++ = *src++;
4893 *p = '\0';
4895 if((p = getenv(word)) != NULL){ /* check for word in environment */
4896 while(*p && dest < limit)
4897 *dest++ = *p++;
4899 else if(colon){ /* else possible default value */
4900 p = colon + 2;
4901 while(*p && p < rbrace && dest < limit)
4902 *dest++ = *p++;
4905 continue;
4906 }else{ /* other cases: just copy */
4907 just_copy:
4908 if(dest < limit)
4909 *dest++ = *src;
4912 if(*src) /* next character (if any) */
4913 src++;
4916 if(dest < limit)
4917 *dest = '\0';
4918 else
4919 lineout[lineoutlen-1] = '\0';
4921 return((envexpand && lineout[0] == '\0') ? NULL : lineout);
4925 /*----------------------------------------------------------------------
4926 Sets login, full_username and home_dir
4928 Args: ps -- The Pine structure to put the user name, etc in
4930 Result: sets the fullname, login and home_dir field of the pine structure
4931 returns 0 on success, -1 if not.
4932 ----*/
4933 #define MAX_INIT_ERRS 10
4934 void
4935 init_error(struct pine *ps, int flags, int min_time, int max_time, char *message)
4937 int i;
4939 if(!ps->init_errs){
4940 ps->init_errs = (INIT_ERR_S *)fs_get((MAX_INIT_ERRS + 1) *
4941 sizeof(*ps->init_errs));
4942 memset(ps->init_errs, 0, (MAX_INIT_ERRS + 1) * sizeof(*ps->init_errs));
4945 for(i = 0; i < MAX_INIT_ERRS; i++)
4946 if(!(ps->init_errs)[i].message){
4947 (ps->init_errs)[i].message = cpystr(message);
4948 (ps->init_errs)[i].min_time = min_time;
4949 (ps->init_errs)[i].max_time = max_time;
4950 (ps->init_errs)[i].flags = flags;
4951 dprint((2, "%s\n", message ? message : "?"));
4952 break;
4957 /*----------------------------------------------------------------------
4958 Read and parse a pinerc file
4960 Args: Filename -- name of the .pinerc file to open and read
4961 vars -- The vars structure to store values in
4962 which_vars -- Whether the local or global values are being read
4964 Result:
4966 This may be the local file or the global file. The values found are
4967 merged with the values currently in vars. All values are strings and
4968 are malloced; and existing values will be freed before the assignment.
4969 Those that are <unset> will be left unset; their values will be NULL.
4970 ----*/
4971 void
4972 read_pinerc(PINERC_S *prc, struct variable *vars, ParsePinerc which_vars)
4974 char *filename, *file, *value, **lvalue, *line, *error;
4975 char *p, *p1, *free_file = NULL;
4976 struct variable *v;
4977 PINERC_LINE *pline = NULL;
4978 int line_count, was_quoted;
4979 int i;
4981 if(!prc)
4982 return;
4984 dprint((2, "reading_pinerc \"%s\"\n",
4985 prc->name ? prc->name : "?"));
4987 if(prc->type == Loc){
4988 filename = prc->name ? prc->name : "";
4989 file = free_file = read_file(filename, 0);
4992 * This is questionable. In case the user edits the pinerc
4993 * in Windows and adds a UTF-8 BOM, we skip it here. If the
4994 * user adds a Unicode BOM we're in trouble. We could write it
4995 * with the BOM ourselves but so far we leave it BOMless in
4996 * order that it's the same on Unix and Windows.
4998 if(BOM_UTF8(file))
4999 file += 3;
5001 else{
5002 if((file = read_remote_pinerc(prc, which_vars)) != NULL)
5003 ps_global->c_client_error[0] = '\0';
5005 free_file = file;
5008 if(file == NULL || *file == '\0'){
5009 #ifdef DEBUG
5010 if(file == NULL){
5011 dprint((2, "Open failed: %s\n", error_description(errno)));
5013 else{
5014 if(prc->type == Loc){
5015 dprint((1, "Read_pinerc: empty pinerc (new?)\n"));
5017 else{
5018 dprint((1, "Read_pinerc: new remote pinerc\n"));
5021 #endif /* DEBUG */
5023 if(which_vars == ParsePers){
5024 /* problems getting remote config */
5025 if(file == NULL && prc->type == RemImap){
5026 if(!pith_opt_remote_pinerc_failure
5027 || !(*pith_opt_remote_pinerc_failure)())
5028 exceptional_exit(_("Unable to read or write remote configuration"), -1);
5031 ps_global->first_time_user = 1;
5032 prc->outstanding_pinerc_changes = 1;
5035 return;
5037 else{
5038 if(prc->type == Loc &&
5039 (which_vars == ParseFixed || which_vars == ParseGlobal ||
5040 (can_access(filename, ACCESS_EXISTS) == 0 &&
5041 can_access(filename, EDIT_ACCESS) != 0))){
5042 prc->readonly = 1;
5043 if(prc == ps_global->prc)
5044 ps_global->readonly_pinerc = 1;
5048 * accept CRLF or LF newlines
5050 for(p = file; *p && *p != '\012'; p++)
5053 if(p > file && *p && *(p-1) == '\015') /* cvt crlf to lf */
5054 for(p1 = p - 1; (*p1 = *p) != '\0'; p++)
5055 if(!(*p == '\015' && *(p+1) == '\012'))
5056 p1++;
5059 dprint((2, "Read %d characters:\n", strlen(file)));
5061 if(which_vars == ParsePers || which_vars == ParsePersPost){
5062 /*--- Count up lines and allocate structures */
5063 for(line_count = 0, p = file; *p != '\0'; p++)
5064 if(*p == '\n')
5065 line_count++;
5067 prc->pinerc_lines = (PINERC_LINE *)
5068 fs_get((3 + line_count) * sizeof(PINERC_LINE));
5069 memset((void *)prc->pinerc_lines, 0,
5070 (3 + line_count) * sizeof(PINERC_LINE));
5071 pline = prc->pinerc_lines;
5074 for(p = file, line = file; *p != '\0';){
5075 /*----- Grab the line ----*/
5076 line = p;
5077 while(*p && *p != '\n')
5078 p++;
5079 if(*p == '\n'){
5080 *p++ = '\0';
5083 /*----- Comment Line -----*/
5084 if(*line == '#'){
5085 /* no comments in remote pinercs */
5086 if(pline && prc->type == Loc){
5087 pline->is_var = 0;
5088 pline->line = cpystr(line);
5089 pline++;
5091 continue;
5094 if(*line == '\0' || *line == '\t' || *line == ' '){
5095 p1 = line;
5096 while(*p1 == '\t' || *p1 == ' ')
5097 p1++;
5098 if(pline){
5100 * This could be a continuation line from some future
5101 * version of pine, or it could be a continuation line
5102 * from a PC-Pine variable we don't know about in unix.
5104 if(*p1 != '\0')
5105 pline->line = cpystr(line);
5106 else
5107 pline->line = cpystr("");
5108 pline->is_var = 0;
5109 pline++;
5111 continue;
5114 /*----- look up matching 'v' and leave "value" after '=' ----*/
5115 for(v = vars; *line && v->name; v++)
5116 if((i = strlen(v->name)) < strlen(line) && !struncmp(v->name,line,i)){
5117 int j;
5119 for(j = i; line[j] == ' ' || line[j] == '\t'; j++)
5122 if(line[j] == '='){ /* bingo! */
5123 for(value = &line[j+1];
5124 *value == ' ' || *value == '\t';
5125 value++)
5128 break;
5130 /* else either unrecognized var or bogus line */
5133 /*----- Didn't match any variable or bogus format -----*/
5135 * This could be a variable from some future
5136 * version of pine, or it could be a PC-Pine variable
5137 * we don't know about in unix. Either way, we want to preserve
5138 * it in the file.
5140 if(!v->name){
5141 if(pline){
5142 pline->is_var = 0;
5143 pline->line = cpystr(line);
5144 pline++;
5146 continue;
5150 * Previous versions have caused duplicate pinerc data to be
5151 * written to pinerc files. This clause erases the duplicate
5152 * information when we read it, and it will be removed from the file
5153 * if we call write_pinerc. We test to see if the same variable
5154 * appears later in the file, if so, we skip over it here.
5155 * We don't care about duplicates if this isn't a pinerc we might
5156 * write out, so include pline in the conditional.
5157 * Note that we will leave all of the duplicate comments and blank
5158 * lines in the file unless it is a remote pinerc. Luckily, the
5159 * bug that caused the duplicates only applied to remote pinercs,
5160 * so we should have that case covered.
5162 * If we find a duplicate, we point p to the start
5163 * of the next line that should be considered, and then skip back
5164 * to the top of the loop.
5166 if(pline && var_is_in_rest_of_file(v->name, p)){
5167 if(v->is_list)
5168 p = skip_over_this_var(line, p);
5170 continue;
5174 /*----- Obsolete variable, read it anyway below, might use it -----*/
5175 if(v->is_obsolete){
5176 if(pline){
5177 pline->obsolete_var = 1;
5178 pline->line = cpystr(line);
5179 pline->var = v;
5183 /*----- Variable is in the list but unused for some reason -----*/
5184 if(!v->is_used){
5185 if(pline){
5186 pline->is_var = 0;
5187 pline->line = cpystr(line);
5188 pline++;
5190 continue;
5193 /*--- Var is not user controlled, leave it alone for back compat ---*/
5194 if(!v->is_user && pline){
5195 pline->is_var = 0;
5196 pline->line = cpystr(line);
5197 pline++;
5198 continue;
5201 if(which_vars == ParseFixed)
5202 v->is_fixed = 1;
5204 /*---- variable is unset, or it's global but expands to nothing ----*/
5205 if(!*value
5206 || (which_vars == ParseGlobal
5207 && !expand_variables(tmp_20k_buf, SIZEOF_20KBUF, value,
5208 (v == &ps_global->vars[V_MAILCAP_PATH] ||
5209 v == &ps_global->vars[V_MIMETYPE_PATH])))){
5210 if(v->is_user && pline){
5211 pline->is_var = 1;
5212 pline->var = v;
5213 pline++;
5215 continue;
5218 /*--value is non-empty, store it handling quotes and trailing space--*/
5219 if(*value == '"' && !v->is_list && v->del_quotes){
5220 was_quoted = 1;
5221 value++;
5222 for(p1 = value; *p1 && *p1 != '"'; p1++);
5223 if(*p1 == '"')
5224 *p1 = '\0';
5225 else
5226 removing_trailing_white_space(value);
5227 }else
5228 was_quoted = 0;
5231 * List Entry Parsing
5233 * The idea is to parse a comma separated list of
5234 * elements, preserving quotes, and understanding
5235 * continuation lines (that is ',' == "\n ").
5236 * Quotes must be balanced within elements. Space
5237 * within elements is preserved, but leading and trailing
5238 * space is trimmed. This is a generic function, and it's
5239 * left to the the functions that use the lists to make sure
5240 * they contain valid data...
5242 if(v->is_list){
5244 was_quoted = 0;
5245 line_count = 0;
5246 p1 = value;
5247 while(1){ /* generous count of list elements */
5248 if(*p1 == '"') /* ignore ',' if quoted */
5249 was_quoted = (was_quoted) ? 0 : 1 ;
5251 if((*p1 == ',' && !was_quoted) || *p1 == '\n' || *p1 == '\0')
5252 line_count++; /* count this element */
5254 if(*p1 == '\0' || *p1 == '\n'){ /* deal with EOL */
5255 if(p1 < p || *p1 == '\n'){
5256 *p1++ = ','; /* fix null or newline */
5258 if(*p1 != '\t' && *p1 != ' '){
5259 *(p1-1) = '\0'; /* tie off list */
5260 p = p1; /* reset p */
5261 break;
5263 }else{
5264 p = p1; /* end of pinerc */
5265 break;
5267 }else
5268 p1++;
5271 error = NULL;
5272 lvalue = parse_list(value, line_count,
5273 v->del_quotes ? PL_REMSURRQUOT : PL_NONE,
5274 &error);
5275 if(error){
5276 dprint((1,
5277 "read_pinerc: ERROR: %s in %s = \"%s\"\n",
5278 error ? error : "?",
5279 v->name ? v->name : "?",
5280 value ? value : "?"));
5283 * Special case: turn "" strings into empty strings.
5284 * This allows users to turn off default lists. For example,
5285 * if smtp-server is set then a user could override smtp-server
5286 * with smtp-server="".
5288 for(i = 0; lvalue[i]; i++)
5289 if(lvalue[i][0] == '"' &&
5290 lvalue[i][1] == '"' &&
5291 lvalue[i][2] == '\0')
5292 lvalue[i][0] = '\0';
5295 if(pline){
5296 if(v->is_user && (which_vars == ParsePers || !v->is_onlymain)){
5297 if(v->is_list){
5298 char ***l;
5300 l = (which_vars == ParsePers) ? &v->main_user_val.l
5301 : &v->post_user_val.l;
5302 free_list_array(l);
5303 *l = lvalue;
5305 else{
5306 char **p;
5308 p = (which_vars == ParsePers) ? &v->main_user_val.p
5309 : &v->post_user_val.p;
5310 if(p && *p != NULL)
5311 fs_give((void **)p);
5313 *p = cpystr(value);
5316 if(pline){
5317 pline->is_var = 1;
5318 pline->var = v;
5319 pline->is_quoted = was_quoted;
5320 pline++;
5324 else if(which_vars == ParseGlobal){
5325 if(v->is_global){
5326 if(v->is_list){
5327 free_list_array(&v->global_val.l);
5328 v->global_val.l = lvalue;
5330 else{
5331 if(v->global_val.p != NULL)
5332 fs_give((void **) &(v->global_val.p));
5334 v->global_val.p = cpystr(value);
5338 else{ /* which_vars == ParseFixed */
5339 if(v->is_user || v->is_global){
5340 if(v->is_list){
5341 free_list_array(&v->fixed_val.l);
5342 v->fixed_val.l = lvalue;
5344 else{
5345 if(v->fixed_val.p != NULL)
5346 fs_give((void **) &(v->fixed_val.p));
5348 v->fixed_val.p = cpystr(value);
5353 #ifdef DEBUG
5354 if(v->is_list){
5355 char **l;
5356 l = (which_vars == ParsePers) ? v->main_user_val.l :
5357 (which_vars == ParsePersPost) ? v->post_user_val.l :
5358 (which_vars == ParseGlobal) ? v->global_val.l :
5359 v->fixed_val.l;
5360 if(l && *l && **l){
5361 dprint((5, " %20.20s : %s\n",
5362 v->name ? v->name : "?",
5363 *l ? *l : "?"));
5364 while(++l && *l && **l)
5365 dprint((5, " %20.20s : %s\n", "",
5366 *l ? *l : "?"));
5368 }else{
5369 char *p;
5370 p = (which_vars == ParsePers) ? v->main_user_val.p :
5371 (which_vars == ParsePersPost) ? v->post_user_val.p :
5372 (which_vars == ParseGlobal) ? v->global_val.p :
5373 v->fixed_val.p;
5374 if(p && *p)
5375 dprint((5, " %20.20s : %s\n",
5376 v->name ? v->name : "?",
5377 p ? p : "?"));
5379 #endif /* DEBUG */
5382 if(pline){
5383 pline->line = NULL;
5384 pline->is_var = 0;
5385 if(!prc->pinerc_written && prc->type == Loc){
5386 prc->pinerc_written = name_file_mtime(filename);
5387 dprint((5, "read_pinerc: time_pinerc_written = %ld\n",
5388 (long) prc->pinerc_written));
5392 if(free_file)
5393 fs_give((void **) &free_file);
5398 * Args varname The variable name we're looking for
5399 * begin Begin looking here
5401 * Returns 1 if variable varname appears in the rest of the file
5402 * 0 if not
5405 var_is_in_rest_of_file(char *varname, char *begin)
5407 char *p;
5409 if(!(varname && *varname && begin && *begin))
5410 return 0;
5412 p = begin;
5414 while((p = srchstr(p, varname)) != NULL){
5415 /* beginning of a line? */
5416 if(p > begin && (*(p-1) != '\n' && *(p-1) != '\r')){
5417 p++;
5418 continue;
5421 /* followed by [ SPACE ] < = > ? */
5422 p += strlen(varname);
5423 while(*p == ' ' || *p == '\t')
5424 p++;
5426 if(*p == '=')
5427 return 1;
5430 return 0;
5435 * Args begin Variable to skip starts here.
5436 * nextline This is where the next line starts. We need to know this
5437 * because the input has been mangled a little. A \0 has
5438 * replaced the \n at the end of the first line, but we can
5439 * use nextline to help us out of that quandry.
5441 * Return a pointer to the start of the first line after this variable
5442 * and all of its continuation lines.
5444 char *
5445 skip_over_this_var(char *begin, char *nextline)
5447 char *p;
5449 p = begin;
5451 while(1){
5452 if(*p == '\0' || *p == '\n'){ /* EOL */
5453 if(p < nextline || *p == '\n'){ /* there may be another line */
5454 p++;
5455 if(*p != ' ' && *p != '\t') /* no continuation line */
5456 return(p);
5458 else /* end of file */
5459 return(p);
5461 else
5462 p++;
5467 static char quotes[3] = {'"', '"', '\0'};
5468 /*----------------------------------------------------------------------
5469 Write out the .pinerc state information
5471 Args: ps -- The pine structure to take state to be written from
5472 which -- Which pinerc to write
5473 flags -- If bit WRP_NOUSER is set, then assume that there is
5474 not a user present to answer questions.
5476 This writes to a temporary file first, and then renames that to
5477 be the new .pinerc file to protect against disk error. This has the
5478 problem of possibly messing up file protections, ownership and links.
5479 ----*/
5481 write_pinerc(struct pine *ps, EditWhich which, int flags)
5483 char *p, *dir, *tmp = NULL, *pinrc;
5484 char *pval, **lval;
5485 int bc = 1;
5486 PINERC_LINE *pline;
5487 struct variable *var;
5488 time_t mtime;
5489 char *filename;
5490 REMDATA_S *rd = NULL;
5491 PINERC_S *prc = NULL;
5492 STORE_S *so = NULL;
5493 #ifndef _WINDOWS
5494 struct stat sbuf;
5495 char *slink = NULL;
5496 #endif
5498 dprint((2,"---- write_pinerc(%s) ----\n",
5499 (which == Main) ? "Main" : "Post"));
5501 switch(which){
5502 case Main:
5503 prc = ps ? ps->prc : NULL;
5504 break;
5505 case Post:
5506 prc = ps ? ps->post_prc : NULL;
5507 break;
5508 default:
5509 break;
5512 if(!prc)
5513 return(-1);
5515 if(prc->quit_to_edit){
5516 if(!(flags & WRP_NOUSER))
5517 quit_to_edit_msg(prc);
5519 return(-1);
5522 if(prc->type != Loc && !prc->readonly){
5524 bc = 0; /* don't do backcompat conversion */
5525 rd = prc->rd;
5526 if(!rd)
5527 return(-1);
5529 rd_check_remvalid(rd, -10L);
5531 if(rd->flags & REM_OUTOFDATE){
5532 if((flags & WRP_NOUSER) || unexpected_pinerc_change()){
5533 prc->outstanding_pinerc_changes = 1;
5534 if(!(flags & WRP_NOUSER))
5535 q_status_message1(SM_ORDER | SM_DING, 3, 3,
5536 "Pinerc \"%.200s\" NOT saved",
5537 prc->name ? prc->name : "");
5538 dprint((2, "write_pinerc: remote pinerc changed\n"));
5539 return(-1);
5541 else
5542 rd->flags &= ~REM_OUTOFDATE;
5545 rd_open_remote(rd);
5547 if(rd->access == ReadWrite){
5548 int ro;
5550 if((ro=rd_remote_is_readonly(rd)) || rd->flags & REM_OUTOFDATE){
5551 if(ro == 1){
5552 if(!(flags & WRP_NOUSER))
5553 q_status_message(SM_ORDER | SM_DING, 5, 15,
5554 _("Can't access remote config, changes NOT saved!"));
5555 dprint((1,
5556 "write_pinerc: Can't write to remote pinerc %s, aborting write\n",
5557 rd->rn ? rd->rn : "?"));
5559 else if(ro == 2){
5560 if(!(rd->flags & NO_META_UPDATE)){
5561 unsigned long save_chk_nmsgs;
5563 switch(rd->type){
5564 case RemImap:
5565 save_chk_nmsgs = rd->t.i.chk_nmsgs;
5566 rd->t.i.chk_nmsgs = 0;
5567 rd_write_metadata(rd, 0);
5568 rd->t.i.chk_nmsgs = save_chk_nmsgs;
5569 break;
5571 default:
5572 q_status_message(SM_ORDER | SM_DING, 3, 5,
5573 "Write_pinerc: Type not supported");
5574 break;
5578 if(!(flags & WRP_NOUSER))
5579 q_status_message1(SM_ORDER | SM_DING, 5, 15,
5580 _("No write permission for remote config %.200s, changes NOT saved!"),
5581 rd->rn);
5583 else{
5584 if(!(flags & WRP_NOUSER))
5585 q_status_message(SM_ORDER | SM_DING, 5, 15,
5586 _("Remote config changed, aborting our change to avoid damage..."));
5587 dprint((1,
5588 "write_pinerc: remote config %s changed since we started pine, aborting write\n",
5589 prc->name ? prc->name : "?"));
5592 rd->flags &= ~DO_REMTRIM;
5593 return(-1);
5596 filename = rd->lf;
5598 else{
5599 prc->readonly = 1;
5600 if(prc == ps->prc)
5601 ps->readonly_pinerc = 1;
5604 else
5605 filename = prc->name ? prc->name : "";
5607 pinrc = prc->name ? prc->name : "";
5609 if(prc->type == Loc){
5610 mtime = name_file_mtime(filename);
5611 if(prc->pinerc_written
5612 && prc->pinerc_written != mtime
5613 && ((flags & WRP_NOUSER) || unexpected_pinerc_change())){
5614 prc->outstanding_pinerc_changes = 1;
5616 if(!(flags & WRP_NOUSER))
5617 q_status_message1(SM_ORDER | SM_DING, 3, 3,
5618 "Pinerc \"%.200s\" NOT saved", pinrc);
5620 dprint((2,"write_pinerc: mtime mismatch: \"%s\": %ld != %ld\n",
5621 filename ? filename : "?",
5622 (long) prc->pinerc_written, (long) mtime));
5623 return(-1);
5627 /* don't write if pinerc is read-only */
5628 if(prc->readonly ||
5629 (filename &&
5630 can_access(filename, ACCESS_EXISTS) == 0 &&
5631 can_access(filename, EDIT_ACCESS) != 0)){
5632 prc->readonly = 1;
5633 if(prc == ps->prc)
5634 ps->readonly_pinerc = 1;
5636 if(!(flags & WRP_NOUSER))
5637 q_status_message1(SM_ORDER | SM_DING, 0, 5,
5638 _("Can't modify configuration file \"%.200s\": ReadOnly"),
5639 pinrc);
5640 dprint((2, "write_pinerc: fail because can't access pinerc\n"));
5642 if(rd)
5643 rd->flags &= ~DO_REMTRIM;
5645 return(-1);
5648 if(rd && rd->flags & NO_FILE){
5649 so = rd->sonofile;
5650 so_truncate(rd->sonofile, 0L); /* reset storage object */
5652 else{
5653 dir = ".";
5654 if((p = last_cmpnt(filename)) != NULL){
5655 *--p = '\0';
5656 dir = filename;
5659 #if defined(DOS) || defined(OS2)
5660 if(!(isalpha((unsigned char)dir[0]) && dir[1] == ':' && dir[2] == '\0')
5661 && (can_access(dir, EDIT_ACCESS) < 0 &&
5662 our_mkdir(dir, 0700) < 0))
5664 if(!(flags & WRP_NOUSER))
5665 q_status_message2(SM_ORDER | SM_DING, 3, 5,
5666 /* TRANSLATORS: first argument is a filename, second
5667 arg is the text of the error message */
5668 _("Error creating \"%.200s\" : %.200s"), dir,
5669 error_description(errno));
5670 if(rd)
5671 rd->flags &= ~DO_REMTRIM;
5673 return(-1);
5676 tmp = temp_nam(dir, "rc");
5678 if(*dir && tmp && !in_dir(dir, tmp)){
5679 our_unlink(tmp);
5680 fs_give((void **)&tmp);
5683 if(p)
5684 *p = '\\';
5686 if(tmp == NULL)
5687 goto io_err;
5689 #else /* !DOS */
5690 tmp = temp_nam((*dir) ? dir : "/", "pinerc");
5693 * If temp_nam can't write in dir it puts the temp file in a
5694 * temp directory, which won't help us when we go to rename.
5696 if(*dir && tmp && !in_dir(dir, tmp)){
5697 our_unlink(tmp);
5698 fs_give((void **)&tmp);
5701 if(p)
5702 *p = '/';
5704 if(tmp == NULL)
5705 goto io_err;
5707 #endif /* !DOS */
5709 if((so = so_get(FileStar, tmp, WRITE_ACCESS)) == NULL)
5710 goto io_err;
5713 if(!(flags & WRP_PRESERV_WRITTEN))
5714 for(var = ps->vars; var->name != NULL; var++)
5715 var->been_written = 0;
5717 if(prc->type == Loc && ps->first_time_user &&
5718 !so_puts(so, native_nl(cf_text_comment)))
5719 goto io_err;
5721 /* Write out what was in the .pinerc */
5722 for(pline = prc->pinerc_lines;
5723 pline && (pline->is_var || pline->line); pline++){
5724 if(pline->is_var){
5725 var = pline->var;
5727 if(var->is_list)
5728 lval = LVAL(var, which);
5729 else
5730 pval = PVAL(var, which);
5732 /* variable is not set */
5733 if((var->is_list && (!lval || !lval[0])) ||
5734 (!var->is_list && !pval)){
5735 /* leave null variables out of remote pinerc */
5736 if(prc->type == Loc &&
5737 (!so_puts(so, var->name) || !so_puts(so, "=") ||
5738 !so_puts(so, NEWLINE)))
5739 goto io_err;
5741 /* var is set to empty string */
5742 else if((var->is_list && lval[0][0] == '\0') ||
5743 (!var->is_list && pval[0] == '\0')){
5744 if(!so_puts(so, var->name) || !so_puts(so, "=") ||
5745 !so_puts(so, quotes) || !so_puts(so, NEWLINE))
5746 goto io_err;
5748 else{
5749 if(var->is_list){
5750 int i = 0;
5752 for(i = 0; lval[i]; i++){
5753 snprintf(tmp_20k_buf, 10000, "%s%s%s%s%s",
5754 (i) ? "\t" : var->name,
5755 (i) ? "" : "=",
5756 lval[i][0] ? lval[i] : quotes,
5757 lval[i+1] ? "," : "", NEWLINE);
5758 tmp_20k_buf[10000-1] = '\0';
5759 if(!so_puts(so, bc ? backcompat_convert_from_utf8(tmp_20k_buf+10000, SIZEOF_20KBUF-10000, tmp_20k_buf) : tmp_20k_buf))
5760 goto io_err;
5763 else{
5764 snprintf(tmp_20k_buf, 10000, "%s=%s%s%s%s",
5765 var->name,
5766 (pline->is_quoted && pval[0] != '\"')
5767 ? "\"" : "",
5768 pval,
5769 (pline->is_quoted && pval[0] != '\"')
5770 ? "\"" : "", NEWLINE);
5771 tmp_20k_buf[10000-1] = '\0';
5772 if(!so_puts(so, bc ? backcompat_convert_from_utf8(tmp_20k_buf+10000, SIZEOF_20KBUF-10000, tmp_20k_buf) : tmp_20k_buf))
5773 goto io_err;
5777 var->been_written = 1;
5779 }else{
5781 * The description text should be changed into a message
5782 * about the variable being obsolete when a variable is
5783 * moved to obsolete status. We add that message before
5784 * the variable unless it is already there. However, we
5785 * leave the variable itself in case the user runs an old
5786 * version of pine again. Note that we have read in the
5787 * value of the variable in read_pinerc and translated it
5788 * into a new variable if appropriate.
5790 if(pline->obsolete_var && prc->type == Loc){
5791 if(pline <= prc->pinerc_lines || (pline-1)->line == NULL ||
5792 strlen((pline-1)->line) < 3 ||
5793 strucmp((pline-1)->line+2, pline->var->descrip) != 0)
5794 if(!so_puts(so, "# ") ||
5795 !so_puts(so, native_nl(pline->var->descrip)) ||
5796 !so_puts(so, NEWLINE))
5797 goto io_err;
5800 /* remove comments from remote pinercs */
5801 if((prc->type == Loc ||
5802 (pline->line[0] != '#' && pline->line[0] != '\0')) &&
5803 (!so_puts(so, pline->line) || !so_puts(so, NEWLINE)))
5804 goto io_err;
5808 /* Now write out all the variables not in the .pinerc */
5809 for(var = ps->vars; var->name != NULL; var++){
5810 if(!var->is_user || var->been_written || !var->is_used ||
5811 var->is_obsolete || (var->is_onlymain && which != Main))
5812 continue;
5814 if(var->is_list)
5815 lval = LVAL(var, which);
5816 else
5817 pval = PVAL(var, which);
5820 * set description to NULL to eliminate preceding
5821 * blank and comment line.
5823 if(prc->type == Loc && var->descrip && *var->descrip &&
5824 (!so_puts(so, NEWLINE) || !so_puts(so, "# ") ||
5825 !so_puts(so, native_nl(var->descrip)) || !so_puts(so, NEWLINE)))
5826 goto io_err;
5828 /* variable is not set */
5829 /** Don't know what the global_val thing is for. SH, Mar 00 **/
5830 if((var->is_list && (!lval || (!lval[0] && !var->global_val.l))) ||
5831 (!var->is_list && !pval)){
5832 /* leave null variables out of remote pinerc */
5833 if(prc->type == Loc &&
5834 (!so_puts(so, var->name) || !so_puts(so, "=") ||
5835 !so_puts(so, NEWLINE)))
5836 goto io_err;
5838 /* var is set to empty string */
5839 else if((var->is_list && (!lval[0] || !lval[0][0]))
5840 || (!var->is_list && pval[0] == '\0')){
5841 if(!so_puts(so, var->name) || !so_puts(so, "=") ||
5842 !so_puts(so, quotes) || !so_puts(so, NEWLINE))
5843 goto io_err;
5845 else if(var->is_list){
5846 int i = 0;
5848 for(i = 0; lval[i] ; i++){
5849 snprintf(tmp_20k_buf, 10000, "%s%s%s%s%s",
5850 (i) ? "\t" : var->name,
5851 (i) ? "" : "=",
5852 lval[i],
5853 lval[i+1] ? "," : "", NEWLINE);
5854 tmp_20k_buf[10000-1] = '\0';
5855 if(!so_puts(so, bc ? backcompat_convert_from_utf8(tmp_20k_buf+10000, SIZEOF_20KBUF-10000, tmp_20k_buf) : tmp_20k_buf))
5856 goto io_err;
5859 else{
5860 char *pconverted;
5862 pconverted = bc ? backcompat_convert_from_utf8(tmp_20k_buf, SIZEOF_20KBUF, pval) : pval;
5864 if(!so_puts(so, var->name) || !so_puts(so, "=") ||
5865 !so_puts(so, pconverted) || !so_puts(so, NEWLINE))
5866 goto io_err;
5870 if(!(rd && rd->flags & NO_FILE)){
5871 if(so_give(&so))
5872 goto io_err;
5874 #ifndef _WINDOWS
5875 /* if .pinerc is a symbolic link, override symbolic link */
5876 if(our_lstat(filename, &sbuf) == 0
5877 && ((sbuf.st_mode & S_IFMT) == S_IFLNK)){
5878 if((slink = fs_get((sbuf.st_size+1)*sizeof(char))) != NULL){
5879 int r = -1; /* assume error */
5880 if(readlink(filename, slink, sbuf.st_size + 1) >= 0){
5881 char *slpath;
5883 slink[sbuf.st_size] = '\0';
5884 if(*slink == '/')
5885 slpath = cpystr(slink);
5886 else{
5887 char * basep;
5888 basep = strrchr(filename, '/');
5889 if(basep == NULL){
5890 *basep = '\0';
5891 slpath = (char *) fs_get((strlen(filename) + strlen(slink) + 2)*sizeof(char));
5892 sprintf(slpath, "%s/%s", filename, slink);
5893 *basep = '/';
5894 } else {
5895 slpath = (char *) fs_get((strlen(ps_global->home_dir) + strlen(slink) + 2)*sizeof(char));
5896 sprintf(slpath, "%s/%s", ps_global->home_dir, slink);
5899 file_attrib_copy(tmp, slpath);
5900 r = rename_file(tmp, slpath);
5901 fs_give((void **)&slpath);
5903 fs_give((void **)&slink);
5904 if (r < 0) goto io_err;
5907 else
5908 #endif /* _WINDOWS */
5910 file_attrib_copy(tmp, filename);
5911 if(rename_file(tmp, filename) < 0)
5912 goto io_err;
5916 if(prc->type != Loc){
5917 int e, we_cancel;
5918 char datebuf[200];
5920 datebuf[0] = '\0';
5922 if(!(flags & WRP_NOUSER))
5923 we_cancel = busy_cue(_("Copying to remote config"), NULL, 1);
5925 if((e = rd_update_remote(rd, datebuf)) != 0){
5926 dprint((1,
5927 "write_pinerc: error copying from %s to %s\n",
5928 rd->lf ? rd->lf : "<memory>", rd->rn ? rd->rn : "?"));
5929 if(!(flags & WRP_NOUSER)){
5930 q_status_message2(SM_ORDER | SM_DING, 3, 5,
5931 _("Error copying to %.200s: %.200s"),
5932 rd->rn, error_description(errno));
5934 q_status_message(SM_ORDER | SM_DING, 5, 5,
5935 _("Copy of config to remote folder failed, changes NOT saved remotely"));
5938 else{
5939 rd_update_metadata(rd, datebuf);
5940 rd->read_status = 'W';
5941 rd_trim_remdata(&rd);
5942 rd_close_remote(rd);
5945 if(we_cancel)
5946 cancel_busy_cue(-1);
5949 prc->outstanding_pinerc_changes = 0;
5951 if(prc->type == Loc){
5952 prc->pinerc_written = name_file_mtime(filename);
5953 dprint((2, "wrote pinerc: %s: time_pinerc_written = %ld\n",
5954 pinrc ? pinrc : "?", (long) prc->pinerc_written));
5956 else{
5957 dprint((2, "wrote pinerc: %s\n", pinrc ? pinrc : "?"));
5960 if(tmp){
5961 our_unlink(tmp);
5962 fs_give((void **)&tmp);
5965 return(0);
5967 io_err:
5968 if(!(flags & WRP_NOUSER))
5969 q_status_message2(SM_ORDER | SM_DING, 3, 5,
5970 _("Error saving configuration in \"%.200s\": %.200s"),
5971 pinrc, error_description(errno));
5973 dprint((1, "Error writing %s : %s\n", pinrc ? pinrc : "?",
5974 error_description(errno)));
5975 if(rd)
5976 rd->flags &= ~DO_REMTRIM;
5977 if(tmp){
5978 our_unlink(tmp);
5979 fs_give((void **)&tmp);
5982 return(-1);
5987 * The srcstr is UTF-8. In order to help the user with
5988 * running this pine and an old pre-alpine pine on the same config
5989 * file we attempt to convert the values of the config variables
5990 * to the user's character set before writing.
5992 char *
5993 backcompat_convert_from_utf8(char *buf, size_t buflen, char *srcstr)
5995 char *converted = NULL;
5996 char *p;
5997 int its_ascii = 1;
6000 for(p = srcstr; *p && its_ascii; p++)
6001 if(*p & 0x80)
6002 its_ascii = 0;
6004 /* if it is ascii, go with that */
6005 if(its_ascii)
6006 converted = srcstr;
6007 else{
6008 char *trythischarset = NULL;
6011 * If it is possible to translate the UTF-8
6012 * string into the user's character set then
6013 * do that. For backwards compatibility with
6014 * old pines.
6016 if(ps_global->keyboard_charmap && ps_global->keyboard_charmap[0])
6017 trythischarset = ps_global->keyboard_charmap;
6018 else if(ps_global->display_charmap && ps_global->display_charmap[0])
6019 trythischarset = ps_global->display_charmap;
6021 if(trythischarset){
6022 SIZEDTEXT src, dst;
6024 src.data = (unsigned char *) srcstr;
6025 src.size = strlen(srcstr);
6026 memset(&dst, 0, sizeof(dst));
6027 if(utf8_cstext(&src, trythischarset, &dst, 0)){
6028 if(dst.data){
6029 strncpy(buf, (char *) dst.data, buflen);
6030 buf[buflen-1] = '\0';
6031 fs_give((void **) &dst.data);
6032 converted = buf;
6037 if(!converted)
6038 converted = srcstr;
6041 return(converted);
6046 * Given a unix-style source string which may contain LFs,
6047 * convert those to CRLFs if appropriate.
6049 * Returns a pointer to the converted string. This will be a string
6050 * stored in tmp_20k_buf.
6052 * This is just used for the variable descriptions in the pinerc file. It
6053 * could certainly be fancier. It simply converts all \n to NEWLINE.
6055 char *
6056 native_nl(char *src)
6058 char *q, *p;
6060 tmp_20k_buf[0] = '\0';
6062 if(src){
6063 for(q = (char *)tmp_20k_buf; *src; src++){
6064 if(*src == '\n'){
6065 for(p = NEWLINE; *p; p++)
6066 *q++ = *p;
6068 else
6069 *q++ = *src;
6072 *q = '\0';
6075 return((char *)tmp_20k_buf);
6079 void
6080 quit_to_edit_msg(PINERC_S *prc)
6082 /* TRANSLATORS: The %s is either "Postload " or nothing. A Postload config file
6083 is a type of config file. */
6084 q_status_message1(SM_ORDER, 3, 4, _("Must quit Alpine to change %sconfig file."),
6085 (prc == ps_global->post_prc) ? "Postload " : "");
6089 /*------------------------------------------------------------
6090 Return TRUE if the given string was a feature name present in the
6091 pinerc as it was when pine was started...
6092 ----*/
6094 var_in_pinerc(char *s)
6096 PINERC_LINE *pline;
6098 for(pline = ps_global->prc ? ps_global->prc->pinerc_lines : NULL;
6099 pline && (pline->var || pline->line); pline++)
6100 if(pline->var && pline->var->name && !strucmp(s, pline->var->name))
6101 return(1);
6103 for(pline = ps_global->post_prc ? ps_global->post_prc->pinerc_lines : NULL;
6104 pline && (pline->var || pline->line); pline++)
6105 if(pline->var && pline->var->name && !strucmp(s, pline->var->name))
6106 return(1);
6108 return(0);
6112 /*------------------------------------------------------------
6113 Free resources associated with pinerc_lines data
6114 ----*/
6115 void
6116 free_pinerc_lines(PINERC_LINE **pinerc_lines)
6118 PINERC_LINE *pline;
6120 if(pinerc_lines && *pinerc_lines){
6121 for(pline = *pinerc_lines; pline->var || pline->line; pline++)
6122 if(pline->line)
6123 fs_give((void **)&pline->line);
6125 fs_give((void **)pinerc_lines);
6130 /*------------------------------------------------------------
6131 Dump out a global pine.conf on the standard output with fresh
6132 comments. Preserves variables currently set in SYSTEM_PINERC, if any.
6133 ----*/
6134 void
6135 dump_global_conf(void)
6137 FILE *f;
6138 struct variable *var;
6139 PINERC_S *prc;
6141 prc = new_pinerc_s(SYSTEM_PINERC);
6142 read_pinerc(prc, variables, ParseGlobal);
6143 if(prc)
6144 free_pinerc_s(&prc);
6146 f = stdout;
6147 if(f == NULL)
6148 goto io_err;
6150 fprintf(f, "# %s -- system wide pine configuration\n#\n",
6151 SYSTEM_PINERC);
6152 fprintf(f, "# Values here affect all pine users unless they've overridden the values\n");
6153 fprintf(f, "# in their .pinerc files. A copy of this file with current comments may\n");
6154 fprintf(f, "# be obtained by running \"pine -conf\". It will be printed to standard output.\n#\n");
6155 fprintf(f,"# For a variable to be unset its value must be null/blank. This is not the\n");
6156 fprintf(f,"# same as the value of \"empty string\", which can be used to effectively\n");
6157 fprintf(f,"# \"unset\" a variable that has a default or previously assigned value.\n");
6158 fprintf(f,"# To set a variable to the empty string its value should be \"\".\n");
6159 fprintf(f,"# Switch variables are set to either \"yes\" or \"no\", and default to \"no\".\n");
6160 fprintf(f,"# Except for feature-list items, which are additive, values set in the\n");
6161 fprintf(f,"# .pinerc file replace those in pine.conf, and those in pine.conf.fixed\n");
6162 fprintf(f,"# over-ride all others. Features can be over-ridden in .pinerc or\n");
6163 fprintf(f,"# pine.conf.fixed by pre-pending the feature name with \"no-\".\n#\n");
6164 fprintf(f,"# (These comments are automatically inserted.)\n");
6166 for(var = variables; var->name != NULL; var++){
6167 if(!var->is_global || !var->is_used || var->is_obsolete)
6168 continue;
6170 if(var->descrip && *var->descrip){
6171 if(fprintf(f, "\n# %s\n", var->descrip) == EOF)
6172 goto io_err;
6175 if(var->is_list){
6176 if(var->global_val.l == NULL){
6177 if(fprintf(f, "%s=\n", var->name) == EOF)
6178 goto io_err;
6179 }else{
6180 int i;
6182 for(i=0; var->global_val.l[i]; i++)
6183 if(fprintf(f, "%s%s%s%s\n", (i) ? "\t" : var->name,
6184 (i) ? "" : "=", var->global_val.l[i],
6185 var->global_val.l[i+1] ? ",":"") == EOF)
6186 goto io_err;
6188 }else{
6189 if(var->global_val.p == NULL){
6190 if(fprintf(f, "%s=\n", var->name) == EOF)
6191 goto io_err;
6192 }else if(strlen(var->global_val.p) == 0){
6193 if(fprintf(f, "%s=\"\"\n", var->name) == EOF)
6194 goto io_err;
6195 }else{
6196 if(fprintf(f,"%s=%s\n",var->name,var->global_val.p) == EOF)
6197 goto io_err;
6201 exit(0);
6204 io_err:
6205 fprintf(stderr, "Error writing config to stdout: %s\n",
6206 error_description(errno));
6207 exit(-1);
6211 /*------------------------------------------------------------
6212 Dump out a pinerc to filename with fresh
6213 comments. Preserves variables currently set in pinerc, if any.
6214 ----*/
6215 void
6216 dump_new_pinerc(char *filename)
6218 FILE *f;
6219 struct variable *var;
6220 char buf[MAXPATH], *p;
6221 PINERC_S *prc;
6224 p = ps_global->pinerc;
6226 #if defined(DOS) || defined(OS2)
6227 if(!ps_global->pinerc){
6228 char *p;
6230 if(p = getenv("PINERC")){
6231 ps_global->pinerc = cpystr(p);
6232 }else{
6233 char buf2[MAXPATH];
6234 build_path(buf2, ps_global->home_dir, DF_PINEDIR, sizeof(buf2));
6235 build_path(buf, buf2, SYSTEM_PINERC, sizeof(buf));
6238 p = buf;
6240 #else /* !DOS */
6241 if(!ps_global->pinerc){
6242 build_path(buf, ps_global->home_dir, ".pinerc", sizeof(buf));
6243 p = buf;
6245 #endif /* !DOS */
6247 prc = new_pinerc_s(p);
6248 read_pinerc(prc, variables, ParsePers);
6249 if(prc)
6250 free_pinerc_s(&prc);
6252 f = NULL;;
6253 if(filename[0] == '\0'){
6254 fprintf(stderr, "Missing argument to \"-pinerc\".\n");
6255 }else if(!strcmp(filename, "-")){
6256 f = stdout;
6257 }else{
6258 f = our_fopen(filename, "wb");
6261 if(f == NULL)
6262 goto io_err;
6264 if(fprintf(f, "%s", cf_text_comment) == EOF)
6265 goto io_err;
6267 for(var = variables; var->name != NULL; var++){
6268 dprint((7,"write_pinerc: %s = %s\n",
6269 var->name ? var->name : "?",
6270 var->main_user_val.p ? var->main_user_val.p : "<not set>"));
6271 if(!var->is_user || !var->is_used || var->is_obsolete)
6272 continue;
6275 * set description to NULL to eliminate preceding
6276 * blank and comment line.
6278 if(var->descrip && *var->descrip){
6279 if(fprintf(f, "\n# %s\n", var->descrip) == EOF)
6280 goto io_err;
6283 if(var->is_list){
6284 if(var->main_user_val.l == NULL){
6285 if(fprintf(f, "%s=\n", var->name) == EOF)
6286 goto io_err;
6287 }else{
6288 int i;
6290 for(i=0; var->main_user_val.l[i]; i++)
6291 if(fprintf(f, "%s%s%s%s\n", (i) ? "\t" : var->name,
6292 (i) ? "" : "=", var->main_user_val.l[i],
6293 var->main_user_val.l[i+1] ? ",":"") == EOF)
6294 goto io_err;
6296 }else{
6297 if(var->main_user_val.p == NULL){
6298 if(fprintf(f, "%s=\n", var->name) == EOF)
6299 goto io_err;
6300 }else if(strlen(var->main_user_val.p) == 0){
6301 if(fprintf(f, "%s=\"\"\n", var->name) == EOF)
6302 goto io_err;
6303 }else{
6304 if(fprintf(f,"%s=%s\n",var->name,var->main_user_val.p) == EOF)
6305 goto io_err;
6309 exit(0);
6312 io_err:
6313 snprintf(buf, sizeof(buf), "Error writing config to %s: %s\n",
6314 filename, error_description(errno));
6315 exceptional_exit(buf, -1);
6319 /*----------------------------------------------------------------------
6320 Set a user variable and save the .pinerc
6322 Args: var -- The index of the variable to set from conftype.h (V_....)
6323 value -- The string to set the value to
6325 Result: -1 is returned on failure and 0 is returned on success
6327 The vars data structure is updated and the pinerc saved.
6328 ----*/
6330 set_variable(int var, char *value, int expand, int commit, EditWhich which)
6332 struct variable *v;
6333 char **apval;
6334 PINERC_S *prc;
6336 v = &ps_global->vars[var];
6338 if(!v->is_user)
6339 panic1("Trying to set non-user variable %s", v->name);
6341 /* Override value of which, at most one of these should be set */
6342 if(v->is_onlymain)
6343 which = Main;
6344 else if(v->is_outermost)
6345 which = ps_global->ew_for_except_vars;
6347 apval = APVAL(v, which);
6349 if(!apval)
6350 return(-1);
6352 if(*apval)
6353 fs_give((void **)apval);
6355 *apval = value ? cpystr(value) : NULL;
6356 set_current_val(v, expand, FALSE);
6358 switch(which){
6359 case Main:
6360 prc = ps_global->prc;
6361 break;
6362 case Post:
6363 prc = ps_global->post_prc;
6364 break;
6365 default:
6366 break;
6369 if(prc)
6370 prc->outstanding_pinerc_changes = 1;
6372 return(commit ? write_pinerc(ps_global, which, WRP_NONE) : 0);
6376 /*----------------------------------------------------------------------
6377 Set a user variable list and save the .pinerc
6379 Args: var -- The index of the variable to set from conftype.h (V_....)
6380 lvalue -- The list to set the value to
6382 Result: -1 is returned on failure and 0 is returned on success
6384 The vars data structure is updated and if write_it, the pinerc is saved.
6385 ----*/
6387 set_variable_list(int var, char **lvalue, int write_it, EditWhich which)
6389 char ***alval;
6390 int i;
6391 struct variable *v = &ps_global->vars[var];
6392 PINERC_S *prc;
6394 if(!v->is_user || !v->is_list)
6395 panic1("BOTCH: Trying to set non-user or non-list variable %s", v->name);
6397 /* Override value of which, at most one of these should be set */
6398 if(v->is_onlymain)
6399 which = Main;
6400 else if(v->is_outermost)
6401 which = ps_global->ew_for_except_vars;
6403 alval = ALVAL(v, which);
6404 if(!alval)
6405 return(-1);
6407 if(*alval)
6408 free_list_array(alval);
6410 if(lvalue){
6411 for(i = 0; lvalue[i] ; i++) /* count elements */
6414 *alval = (char **) fs_get((i+1) * sizeof(char *));
6416 for(i = 0; lvalue[i] ; i++)
6417 (*alval)[i] = cpystr(lvalue[i]);
6419 (*alval)[i] = NULL;
6422 set_current_val(v, TRUE, FALSE);
6424 switch(which){
6425 case Main:
6426 prc = ps_global->prc;
6427 break;
6428 case Post:
6429 prc = ps_global->post_prc;
6430 break;
6431 default:
6432 break;
6435 if(prc)
6436 prc->outstanding_pinerc_changes = 1;
6438 return(write_it ? write_pinerc(ps_global, which, WRP_NONE) : 0);
6442 void
6443 set_current_color_vals(struct pine *ps)
6445 struct variable *vars = ps->vars;
6446 int later_color_is_set = 0;
6448 set_current_val(&vars[V_NORM_FORE_COLOR], TRUE, TRUE);
6449 set_current_val(&vars[V_NORM_BACK_COLOR], TRUE, TRUE);
6450 pico_nfcolor(VAR_NORM_FORE_COLOR);
6451 pico_nbcolor(VAR_NORM_BACK_COLOR);
6453 set_current_val(&vars[V_REV_FORE_COLOR], TRUE, TRUE);
6454 set_current_val(&vars[V_REV_BACK_COLOR], TRUE, TRUE);
6455 pico_rfcolor(VAR_REV_FORE_COLOR);
6456 pico_rbcolor(VAR_REV_BACK_COLOR);
6458 set_color_val(&vars[V_TITLE_FORE_COLOR], 1);
6459 set_color_val(&vars[V_TITLECLOSED_FORE_COLOR], 0);
6460 set_color_val(&vars[V_FOLDER_FORE_COLOR], 0);
6461 set_color_val(&vars[V_DIRECTORY_FORE_COLOR], 0);
6462 set_color_val(&vars[V_FOLDER_LIST_FORE_COLOR], 0);
6463 set_color_val(&vars[V_STATUS_FORE_COLOR], 1);
6464 set_color_val(&vars[V_KEYLABEL_FORE_COLOR], 1);
6465 set_color_val(&vars[V_KEYNAME_FORE_COLOR], 1);
6466 set_color_val(&vars[V_SLCTBL_FORE_COLOR], 1);
6467 set_color_val(&vars[V_METAMSG_FORE_COLOR], 1);
6468 set_color_val(&vars[V_PROMPT_FORE_COLOR], 1);
6469 set_color_val(&vars[V_HEADER_GENERAL_FORE_COLOR], 1);
6470 set_color_val(&vars[V_IND_PLUS_FORE_COLOR], 0);
6471 set_color_val(&vars[V_IND_IMP_FORE_COLOR], 0);
6472 set_color_val(&vars[V_IND_DEL_FORE_COLOR], 0);
6473 set_color_val(&vars[V_IND_HIPRI_FORE_COLOR], 0);
6474 set_color_val(&vars[V_IND_LOPRI_FORE_COLOR], 0);
6475 set_color_val(&vars[V_IND_ANS_FORE_COLOR], 0);
6476 set_color_val(&vars[V_IND_NEW_FORE_COLOR], 0);
6477 set_color_val(&vars[V_IND_REC_FORE_COLOR], 0);
6478 set_color_val(&vars[V_IND_FWD_FORE_COLOR], 0);
6479 set_color_val(&vars[V_IND_UNS_FORE_COLOR], 0);
6480 set_color_val(&vars[V_IND_ARR_FORE_COLOR], 0);
6481 set_color_val(&vars[V_IND_SUBJ_FORE_COLOR], 0);
6482 set_color_val(&vars[V_IND_FROM_FORE_COLOR], 0);
6483 set_color_val(&vars[V_IND_OP_FORE_COLOR], 0);
6484 set_color_val(&vars[V_INCUNSEEN_FORE_COLOR], 0);
6485 set_color_val(&vars[V_SIGNATURE_FORE_COLOR], 0);
6487 set_current_val(&ps->vars[V_INDEX_TOKEN_COLORS], TRUE, TRUE);
6488 set_current_val(&ps->vars[V_VIEW_HDR_COLORS], TRUE, TRUE);
6489 set_current_val(&ps->vars[V_KW_COLORS], TRUE, TRUE);
6490 set_custom_spec_colors(ps);
6493 * Set up the quoting colors. If a later color is set but not an earlier
6494 * color we set the earlier color to Normal to make it easier when
6495 * we go to use the colors. However, if the only quote colors set are
6496 * Normal that is the same as no settings, so delete them.
6498 set_color_val(&vars[V_QUOTE1_FORE_COLOR], 0);
6499 set_color_val(&vars[V_QUOTE2_FORE_COLOR], 0);
6500 set_color_val(&vars[V_QUOTE3_FORE_COLOR], 0);
6502 if((!(VAR_QUOTE3_FORE_COLOR && VAR_QUOTE3_BACK_COLOR) ||
6503 (!strucmp(VAR_QUOTE3_FORE_COLOR, VAR_NORM_FORE_COLOR) &&
6504 !strucmp(VAR_QUOTE3_BACK_COLOR, VAR_NORM_BACK_COLOR))) &&
6505 (!(VAR_QUOTE2_FORE_COLOR && VAR_QUOTE2_BACK_COLOR) ||
6506 (!strucmp(VAR_QUOTE2_FORE_COLOR, VAR_NORM_FORE_COLOR) &&
6507 !strucmp(VAR_QUOTE2_BACK_COLOR, VAR_NORM_BACK_COLOR))) &&
6508 (!(VAR_QUOTE1_FORE_COLOR && VAR_QUOTE1_BACK_COLOR) ||
6509 (!strucmp(VAR_QUOTE1_FORE_COLOR, VAR_NORM_FORE_COLOR) &&
6510 !strucmp(VAR_QUOTE1_BACK_COLOR, VAR_NORM_BACK_COLOR)))){
6512 * They are all either Normal or not set. Delete them all.
6514 if(VAR_QUOTE3_FORE_COLOR)
6515 fs_give((void **)&VAR_QUOTE3_FORE_COLOR);
6516 if(VAR_QUOTE3_BACK_COLOR)
6517 fs_give((void **)&VAR_QUOTE3_BACK_COLOR);
6518 if(VAR_QUOTE2_FORE_COLOR)
6519 fs_give((void **)&VAR_QUOTE2_FORE_COLOR);
6520 if(VAR_QUOTE2_BACK_COLOR)
6521 fs_give((void **)&VAR_QUOTE2_BACK_COLOR);
6522 if(VAR_QUOTE1_FORE_COLOR)
6523 fs_give((void **)&VAR_QUOTE1_FORE_COLOR);
6524 if(VAR_QUOTE1_BACK_COLOR)
6525 fs_give((void **)&VAR_QUOTE1_BACK_COLOR);
6527 else{ /* something is non-Normal */
6528 if(VAR_QUOTE3_FORE_COLOR && VAR_QUOTE3_BACK_COLOR)
6529 later_color_is_set++;
6531 /* if 3 is set but not 2, set 2 to Normal */
6532 if(VAR_QUOTE2_FORE_COLOR && VAR_QUOTE2_BACK_COLOR)
6533 later_color_is_set++;
6534 else if(later_color_is_set)
6535 set_color_val(&vars[V_QUOTE2_FORE_COLOR], 1);
6537 /* if 3 or 2 is set but not 1, set 1 to Normal */
6538 if(VAR_QUOTE1_FORE_COLOR && VAR_QUOTE1_BACK_COLOR)
6539 later_color_is_set++;
6540 else if(later_color_is_set)
6541 set_color_val(&vars[V_QUOTE1_FORE_COLOR], 1);
6544 #ifdef _WINDOWS
6545 if(ps->pre441){
6546 int conv_main = 0, conv_post = 0;
6548 ps->pre441 = 0;
6549 if(ps->prc && !unix_color_style_in_pinerc(ps->prc)){
6550 conv_main = convert_pc_gray_names(ps, ps->prc, Main);
6551 if(conv_main)
6552 ps->prc->outstanding_pinerc_changes = 1;
6556 if(ps->post_prc && !unix_color_style_in_pinerc(ps->post_prc)){
6557 conv_post = convert_pc_gray_names(ps, ps->post_prc, Post);
6558 if(conv_post)
6559 ps->post_prc->outstanding_pinerc_changes = 1;
6562 if(conv_main || conv_post){
6563 if(conv_main)
6564 write_pinerc(ps, Main, WRP_NONE);
6566 if(conv_post)
6567 write_pinerc(ps, Post, WRP_NONE);
6569 set_current_color_vals(ps);
6572 #endif /* _WINDOWS */
6574 pico_set_normal_color();
6579 * Set current_val for the foreground and background color vars, which
6580 * are assumed to be in order. If a set_current_val on them doesn't
6581 * produce current_vals, then use the colors from defvar to set those
6582 * current_vals.
6584 void
6585 set_color_val(struct variable *v, int use_default)
6587 set_current_val(v, TRUE, TRUE);
6588 set_current_val(v+1, TRUE, TRUE);
6590 if(!(v->current_val.p && v->current_val.p[0] &&
6591 (v+1)->current_val.p && (v+1)->current_val.p[0])){
6592 struct variable *defvar;
6594 if(v->current_val.p)
6595 fs_give((void **)&v->current_val.p);
6596 if((v+1)->current_val.p)
6597 fs_give((void **)&(v+1)->current_val.p);
6599 if(!use_default)
6600 return;
6602 if(var_defaults_to_rev(v))
6603 defvar = &ps_global->vars[V_REV_FORE_COLOR];
6604 else
6605 defvar = &ps_global->vars[V_NORM_FORE_COLOR];
6607 /* use default vars values instead */
6608 if(defvar && defvar->current_val.p && defvar->current_val.p[0] &&
6609 (defvar+1)->current_val.p && (defvar+1)->current_val.p[0]){
6610 v->current_val.p = cpystr(defvar->current_val.p);
6611 (v+1)->current_val.p = cpystr((defvar+1)->current_val.p);
6618 var_defaults_to_rev(struct variable *v)
6620 return(v == &ps_global->vars[V_REV_FORE_COLOR] ||
6621 v == &ps_global->vars[V_TITLE_FORE_COLOR] ||
6622 v == &ps_global->vars[V_STATUS_FORE_COLOR] ||
6623 v == &ps_global->vars[V_KEYNAME_FORE_COLOR] ||
6624 v == &ps_global->vars[V_PROMPT_FORE_COLOR]);
6630 * Each item in the list looks like:
6632 * /HDR=<header>/FG=<foreground color>/BG=<background color>
6634 * We separate the three pieces into an array of structures to make
6635 * it easier to deal with later.
6637 void
6638 set_custom_spec_colors(struct pine *ps)
6640 if(ps->index_token_colors)
6641 free_spec_colors(&ps->index_token_colors);
6643 ps->index_token_colors = spec_colors_from_varlist(ps->VAR_INDEX_TOKEN_COLORS, 1);
6645 if(ps->hdr_colors)
6646 free_spec_colors(&ps->hdr_colors);
6648 ps->hdr_colors = spec_colors_from_varlist(ps->VAR_VIEW_HDR_COLORS, 1);
6650 /* fit keyword colors into the same structures for code re-use */
6651 if(ps->kw_colors)
6652 free_spec_colors(&ps->kw_colors);
6654 ps->kw_colors = spec_colors_from_varlist(ps->VAR_KW_COLORS, 1);
6659 * Input is one item from config variable.
6661 * Return value must be freed by caller. The return is a single SPEC_COLOR_S,
6662 * not a list.
6664 SPEC_COLOR_S *
6665 spec_color_from_var(char *t, int already_expanded)
6667 char *p, *spec, *fg, *bg;
6668 PATTERN_S *val;
6669 SPEC_COLOR_S *new_hcolor = NULL;
6671 if(t && t[0] && !strcmp(t, INHERIT)){
6672 new_hcolor = (SPEC_COLOR_S *)fs_get(sizeof(*new_hcolor));
6673 memset((void *)new_hcolor, 0, sizeof(*new_hcolor));
6674 new_hcolor->inherit = 1;
6676 else if(t && t[0]){
6677 char tbuf[10000];
6679 if(!already_expanded){
6680 tbuf[0] = '\0';
6681 if(expand_variables(tbuf, sizeof(tbuf), t, 0))
6682 t = tbuf;
6685 spec = fg = bg = NULL;
6686 val = NULL;
6687 if((p = srchstr(t, "/HDR=")) != NULL)
6688 spec = remove_backslash_escapes(p+5);
6689 if((p = srchstr(t, "/FG=")) != NULL)
6690 fg = remove_backslash_escapes(p+4);
6691 if((p = srchstr(t, "/BG=")) != NULL)
6692 bg = remove_backslash_escapes(p+4);
6693 val = parse_pattern("VAL", t, 0);
6695 if(spec && *spec){
6696 /* remove colons */
6697 if((p = strindex(spec, ':')) != NULL)
6698 *p = '\0';
6700 new_hcolor = (SPEC_COLOR_S *)fs_get(sizeof(*new_hcolor));
6701 memset((void *)new_hcolor, 0, sizeof(*new_hcolor));
6702 new_hcolor->spec = spec;
6703 new_hcolor->fg = fg;
6704 new_hcolor->bg = bg;
6705 new_hcolor->val = val;
6707 else{
6708 if(spec)
6709 fs_give((void **)&spec);
6710 if(fg)
6711 fs_give((void **)&fg);
6712 if(bg)
6713 fs_give((void **)&bg);
6714 if(val)
6715 free_pattern(&val);
6719 return(new_hcolor);
6724 * Input is a list from config file.
6726 * Return value may be a list of SPEC_COLOR_S and must be freed by caller.
6728 SPEC_COLOR_S *
6729 spec_colors_from_varlist(char **varlist, int already_expanded)
6731 char **s, *t;
6732 SPEC_COLOR_S *new_hc = NULL;
6733 SPEC_COLOR_S *new_hcolor, **nexthc;
6735 nexthc = &new_hc;
6736 if(varlist){
6737 for(s = varlist; (t = *s) != NULL; s++){
6738 if(t[0]){
6739 new_hcolor = spec_color_from_var(t, already_expanded);
6740 if(new_hcolor){
6741 *nexthc = new_hcolor;
6742 nexthc = &new_hcolor->next;
6748 return(new_hc);
6753 * Returns allocated charstar suitable for config var for a single
6754 * SPEC_COLOR_S.
6756 char *
6757 var_from_spec_color(SPEC_COLOR_S *hc)
6759 char *ret_val = NULL;
6760 char *p, *spec = NULL, *fg = NULL, *bg = NULL, *val = NULL;
6761 size_t len;
6763 if(hc && hc->inherit)
6764 ret_val = cpystr(INHERIT);
6765 else if(hc){
6766 if(hc->spec)
6767 spec = add_viewerhdr_escapes(hc->spec);
6768 if(hc->fg)
6769 fg = add_viewerhdr_escapes(hc->fg);
6770 if(hc->bg)
6771 bg = add_viewerhdr_escapes(hc->bg);
6772 if(hc->val){
6773 p = pattern_to_string(hc->val);
6774 if(p){
6775 val = add_viewerhdr_escapes(p);
6776 fs_give((void **)&p);
6780 len = strlen("/HDR=/FG=/BG=") + strlen(spec ? spec : "") +
6781 strlen(fg ? fg : "") + strlen(bg ? bg : "") +
6782 strlen(val ? "/VAL=" : "") + strlen(val ? val : "");
6783 ret_val = (char *) fs_get(len + 1);
6784 snprintf(ret_val, len+1, "/HDR=%s/FG=%s/BG=%s%s%s",
6785 spec ? spec : "", fg ? fg : "", bg ? bg : "",
6786 val ? "/VAL=" : "", val ? val : "");
6788 if(spec)
6789 fs_give((void **)&spec);
6790 if(fg)
6791 fs_give((void **)&fg);
6792 if(bg)
6793 fs_give((void **)&bg);
6794 if(val)
6795 fs_give((void **)&val);
6798 return(ret_val);
6803 * Returns allocated charstar suitable for config var for a single
6804 * SPEC_COLOR_S.
6806 char **
6807 varlist_from_spec_colors(SPEC_COLOR_S *hcolors)
6809 SPEC_COLOR_S *hc;
6810 char **ret_val = NULL;
6811 int i;
6813 /* count how many */
6814 for(hc = hcolors, i = 0; hc; hc = hc->next, i++)
6817 ret_val = (char **)fs_get((i+1) * sizeof(*ret_val));
6818 memset((void *)ret_val, 0, (i+1) * sizeof(*ret_val));
6819 for(hc = hcolors, i = 0; hc; hc = hc->next, i++)
6820 ret_val[i] = var_from_spec_color(hc);
6822 return(ret_val);
6826 void
6827 update_posting_charset(struct pine *ps, int revert)
6829 #ifndef _WINDOWS
6830 if(F_ON(F_USE_SYSTEM_TRANS, ps)){
6831 if(!revert)
6832 q_status_message(SM_ORDER, 5, 5, _("This change has no effect because feature Use-System-Translation is on"));
6834 else{
6835 #endif /* ! _WINDOWS */
6836 if(ps->posting_charmap)
6837 fs_give((void **) &ps->posting_charmap);
6839 if(ps->VAR_POST_CHAR_SET){
6840 ps->posting_charmap = cpystr(ps->VAR_POST_CHAR_SET);
6841 if(!posting_charset_is_supported(ps->posting_charmap)){
6842 snprintf(tmp_20k_buf, SIZEOF_20KBUF,
6843 _("Posting-Character set \"%s\" is unsupported, using UTF-8"),
6844 ps->posting_charmap);
6845 q_status_message(SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
6846 fs_give((void **) &ps->posting_charmap);
6847 ps->posting_charmap = cpystr("UTF-8");
6850 else
6851 ps->posting_charmap = cpystr("UTF-8");
6852 #ifndef _WINDOWS
6854 #endif /* ! _WINDOWS */
6858 #define FIXED_COMMENT _("(fixed)")
6859 #define DEFAULT_COMMENT _("(default)")
6860 #define OVERRIDE_COMMENT _("(overridden)")
6863 feature_gets_an_x(struct pine *ps, struct variable *var, FEATURE_S *feature,
6864 char **comment, EditWhich ew)
6866 char **lval, **lvalexc, **lvalnorm;
6867 char *def = DEFAULT_COMMENT;
6868 int j, done = 0;
6869 int feature_fixed_on = 0, feature_fixed_off = 0;
6871 if(comment)
6872 *comment = NULL;
6874 lval = LVAL(var, ew);
6875 lvalexc = LVAL(var, ps->ew_for_except_vars);
6876 lvalnorm = LVAL(var, Main);
6878 /* feature value is administratively fixed */
6879 if((j = feature_in_list(var->fixed_val.l, feature->name)) != 0){
6880 if(j == 1)
6881 feature_fixed_on++;
6882 else if(j == -1)
6883 feature_fixed_off++;
6885 done++;
6886 if(comment)
6887 *comment = FIXED_COMMENT;
6891 * We have an exceptions config setting which overrides anything
6892 * we do here, in the normal config.
6894 if(!done &&
6895 ps->ew_for_except_vars != Main && ew == Main &&
6896 feature_in_list(lvalexc, feature->name)){
6897 done++;
6898 if(comment)
6899 *comment = OVERRIDE_COMMENT;
6903 * Feature is set On in default but not set here.
6905 if(!done &&
6906 !feature_in_list(lval, feature->name) &&
6907 ((feature_in_list(var->global_val.l, feature->name) == 1) ||
6908 ((ps->ew_for_except_vars != Main &&
6909 ew == ps->ew_for_except_vars &&
6910 feature_in_list(lvalnorm, feature->name) == 1)))){
6911 done = 17;
6912 if(comment)
6913 *comment = def;
6916 if(!done &&
6917 feature->defval &&
6918 !feature_in_list(lval, feature->name) &&
6919 !feature_in_list(var->global_val.l, feature->name) &&
6920 (ps->ew_for_except_vars == Main ||
6921 ew != ps->ew_for_except_vars ||
6922 !feature_in_list(lvalnorm, feature->name))){
6923 done = 17;
6924 if(comment)
6925 *comment = def;
6928 return(feature_fixed_on ||
6929 (!feature_fixed_off &&
6930 (done == 17 ||
6931 test_feature(lval, feature->name,
6932 test_old_growth_bits(ps, feature->id)))));
6937 longest_feature_comment(struct pine *ps, EditWhich ew)
6939 int lc = 0;
6941 lc = MAX(lc, utf8_width(FIXED_COMMENT));
6942 lc = MAX(lc, utf8_width(DEFAULT_COMMENT));
6943 if(ps->ew_for_except_vars != Main && ew == Main)
6944 lc = MAX(lc, utf8_width(OVERRIDE_COMMENT));
6946 return(lc);
6950 void
6951 toggle_feature(struct pine *ps, struct variable *var, FEATURE_S *f,
6952 int just_flip_value, EditWhich ew)
6954 char **vp, *p, **lval, ***alval;
6955 int og, on_before, was_set;
6956 char *err;
6957 long l;
6959 og = test_old_growth_bits(ps, f->id);
6962 * if this feature is in the fixed set, or old-growth is in the fixed
6963 * set and this feature is in the old-growth set, don't alter it...
6965 for(vp = var->fixed_val.l; vp && *vp; vp++){
6966 p = (struncmp(*vp, "no-", 3)) ? *vp : *vp + 3;
6967 if(!strucmp(p, f->name) || (og && !strucmp(p, "old-growth"))){
6968 q_status_message(SM_ORDER, 3, 3,
6969 /* TRANSLATORS: In the configuration screen, telling the user we
6970 can't change this option because the system administrator
6971 prohibits it. */
6972 _("Can't change value fixed by sys-admin."));
6973 return;
6977 on_before = F_ON(f->id, ps);
6979 lval = LVAL(var, ew);
6980 alval = ALVAL(var, ew);
6981 if(just_flip_value)
6982 was_set = test_feature(lval, f->name, og);
6983 else
6984 was_set = feature_gets_an_x(ps, var, f, NULL, ew);
6986 if(alval)
6987 set_feature(alval, f->name, !was_set);
6989 set_feature_list_current_val(var);
6990 process_feature_list(ps, var->current_val.l, 0, 0, 0);
6993 * Handle any features that need special attention here...
6995 if(on_before != F_ON(f->id, ps))
6996 switch(f->id){
6997 case F_QUOTE_ALL_FROMS :
6998 mail_parameters(NULL,SET_FROMWIDGET,F_ON(f->id,ps) ? VOIDT : NIL);
6999 break;
7001 case F_FAKE_NEW_IN_NEWS :
7002 if(IS_NEWS(ps->mail_stream))
7003 q_status_message(SM_ORDER | SM_DING, 3, 4,
7004 "news-approximates-new-status won't affect current newsgroup until next open");
7006 break;
7008 case F_COLOR_LINE_IMPORTANT :
7009 case F_DATES_TO_LOCAL :
7010 clear_index_cache(ps->mail_stream, 0);
7011 break;
7013 case F_DISABLE_INDEX_LOCALE_DATES :
7014 reset_index_format();
7015 clear_index_cache(ps->mail_stream, 0);
7016 break;
7018 case F_MARK_FOR_CC :
7019 clear_index_cache(ps->mail_stream, 0);
7020 if(THREADING() && sp_viewing_a_thread(ps->mail_stream))
7021 unview_thread(ps, ps->mail_stream, ps->msgmap);
7023 break;
7025 case F_HIDE_NNTP_PATH :
7026 mail_parameters(NULL, SET_NNTPHIDEPATH,
7027 F_ON(f->id, ps) ? VOIDT : NIL);
7028 break;
7030 case F_MAILDROPS_PRESERVE_STATE :
7031 mail_parameters(NULL, SET_SNARFPRESERVE,
7032 F_ON(f->id, ps) ? VOIDT : NIL);
7033 break;
7035 case F_DISABLE_SHARED_NAMESPACES :
7036 mail_parameters(NULL, SET_DISABLEAUTOSHAREDNS,
7037 F_ON(f->id, ps) ? VOIDT : NIL);
7038 break;
7040 case F_QUELL_LOCK_FAILURE_MSGS :
7041 mail_parameters(NULL, SET_LOCKEACCESERROR,
7042 F_ON(f->id, ps) ? VOIDT : NIL);
7043 break;
7045 case F_MULNEWSRC_HOSTNAMES_AS_TYPED :
7046 l = F_ON(f->id, ps) ? 0L : 1L;
7047 mail_parameters(NULL, SET_NEWSRCCANONHOST, (void *) l);
7048 break;
7050 case F_QUELL_INTERNAL_MSG :
7051 mail_parameters(NULL, SET_USERHASNOLIFE,
7052 F_ON(f->id, ps) ? VOIDT : NIL);
7053 break;
7055 case F_DISABLE_SETLOCALE_COLLATE :
7056 set_collation(F_OFF(F_DISABLE_SETLOCALE_COLLATE, ps), 1);
7057 break;
7059 #ifndef _WINDOWS
7060 case F_USE_SYSTEM_TRANS :
7061 err = NULL;
7062 reset_character_set_stuff(&err);
7063 if(err){
7064 q_status_message(SM_ORDER | SM_DING, 3, 4, err);
7065 fs_give((void **) &err);
7068 break;
7069 #endif /* ! _WINDOWS */
7071 case F_ENABLE_INCOMING_CHECKING :
7072 if(!on_before && F_OFF(F_ENABLE_INCOMING, ps))
7073 q_status_message(SM_ORDER, 0, 3, _("This option has no effect without Enable-Incoming-Folders"));
7075 clear_incoming_valid_bits();
7076 break;
7078 case F_INCOMING_CHECKING_TOTAL :
7079 case F_INCOMING_CHECKING_RECENT :
7080 if(!on_before && F_OFF(F_ENABLE_INCOMING_CHECKING, ps))
7081 q_status_message(SM_ORDER, 0, 3, _("This option has no effect without Enable-Incoming-Folders-Checking"));
7083 clear_incoming_valid_bits();
7084 break;
7086 case F_THREAD_SORTS_BY_ARRIVAL :
7087 clear_index_cache(ps->mail_stream, 0);
7088 refresh_sort(ps->mail_stream, sp_msgmap(ps->mail_stream), SRT_NON);
7089 break;
7091 #ifdef SMIME
7092 case F_DONT_DO_SMIME :
7093 smime_deinit();
7094 break;
7096 #ifdef APPLEKEYCHAIN
7097 case F_PUBLICCERTS_IN_KEYCHAIN :
7098 smime_deinit();
7099 break;
7100 #endif
7101 #endif
7103 default :
7104 break;
7110 * Returns 1 -- Feature is in the list and positive
7111 * 0 -- Feature is not in the list at all
7112 * -1 -- Feature is in the list and negative (no-)
7115 feature_in_list(char **l, char *f)
7117 char *p;
7118 int rv = 0, forced_off;
7120 for(; l && *l; l++){
7121 p = (forced_off = !struncmp(*l, "no-", 3)) ? *l + 3 : *l;
7122 if(!strucmp(p, f))
7123 rv = forced_off ? -1 : 1;
7126 return(rv);
7131 * test_feature - runs thru a feature list, and returns:
7132 * 1 if feature explicitly set and matches 'v'
7133 * 0 if feature not explicitly set *or* doesn't match 'v'
7136 test_feature(char **l, char *f, int g)
7138 char *p;
7139 int rv = 0, forced_off;
7141 for(; l && *l; l++){
7142 p = (forced_off = !struncmp(*l, "no-", 3)) ? *l + 3 : *l;
7143 if(!strucmp(p, f))
7144 rv = !forced_off;
7145 else if(g && !strucmp(p, "old-growth"))
7146 rv = !forced_off;
7149 return(rv);
7153 void
7154 set_feature(char ***l, char *f, int v)
7156 char **list = l ? *l : NULL, newval[256];
7157 int count = 0;
7159 snprintf(newval, sizeof(newval), "%s%s", v ? "" : "no-", f);
7160 for(; list && *list; list++, count++)
7161 if((**list == '\0') /* anything can replace an empty value */
7162 || !strucmp(((!struncmp(*list, "no-", 3)) ? *list + 3 : *list), f)){
7163 fs_give((void **)list); /* replace with new value */
7164 *list = cpystr(newval);
7165 return;
7169 * if we got here, we didn't find it in the list, so grow the list
7170 * and add it..
7172 if(!*l)
7173 *l = (char **)fs_get((count + 2) * sizeof(char *));
7174 else
7175 fs_resize((void **)l, (count + 2) * sizeof(char *));
7177 (*l)[count] = cpystr(newval);
7178 (*l)[count + 1] = NULL;
7183 reset_character_set_stuff(char **err)
7185 int use_system = 0;
7186 char buf[1000];
7188 if(err)
7189 *err = NULL;
7191 if(ps_global->display_charmap)
7192 fs_give((void **) &ps_global->display_charmap);
7194 if(ps_global->keyboard_charmap)
7195 fs_give((void **) &ps_global->keyboard_charmap);
7197 if(ps_global->posting_charmap)
7198 fs_give((void **) &ps_global->posting_charmap);
7200 #ifdef _WINDOWS
7201 ps_global->display_charmap = cpystr("UTF-8");
7202 #else /* UNIX */
7203 if(ps_global->VAR_CHAR_SET)
7204 ps_global->display_charmap = cpystr(ps_global->VAR_CHAR_SET);
7205 else{
7206 #if HAVE_LANGINFO_H && defined(CODESET)
7207 ps_global->display_charmap = cpystr(nl_langinfo_codeset_wrapper());
7208 #else
7209 ps_global->display_charmap = cpystr("UTF-8");
7210 #endif
7212 #endif /* UNIX */
7214 if(!ps_global->display_charmap)
7215 ps_global->display_charmap = cpystr("US-ASCII");
7217 #ifdef _WINDOWS
7218 ps_global->keyboard_charmap = cpystr("UTF-8");
7219 #else /* UNIX */
7220 if(ps_global->VAR_KEY_CHAR_SET)
7221 ps_global->keyboard_charmap = cpystr(ps_global->VAR_KEY_CHAR_SET);
7222 else
7223 ps_global->keyboard_charmap = cpystr(ps_global->display_charmap);
7225 if(!ps_global->keyboard_charmap)
7226 ps_global->keyboard_charmap = cpystr("US-ASCII");
7228 if(F_ON(F_USE_SYSTEM_TRANS, ps_global)){
7229 #if PREREQ_FOR_SYS_TRANSLATION
7230 use_system++;
7231 /* This modifies its arguments */
7232 if(setup_for_input_output(use_system, &ps_global->display_charmap,
7233 &ps_global->keyboard_charmap,
7234 &ps_global->input_cs, (err && *err) ? NULL : err) == -1)
7235 return -1;
7236 #endif
7238 #endif /* UNIX */
7240 if(!use_system){
7241 if(setup_for_input_output(use_system, &ps_global->display_charmap,
7242 &ps_global->keyboard_charmap,
7243 &ps_global->input_cs, (err && *err) ? NULL : err) == -1)
7244 return -1;
7247 if(!use_system && ps_global->VAR_POST_CHAR_SET){
7248 ps_global->posting_charmap = cpystr(ps_global->VAR_POST_CHAR_SET);
7249 if(!posting_charset_is_supported(ps_global->posting_charmap)){
7250 if(err && !*err){
7251 snprintf(buf, sizeof(buf),
7252 _("Posting-Character-Set \"%s\" is unsupported, using UTF-8"),
7253 ps_global->posting_charmap);
7254 *err = cpystr(buf);
7257 fs_give((void **) &ps_global->posting_charmap);
7258 ps_global->posting_charmap = cpystr("UTF-8");
7261 else{
7262 if(use_system && ps_global->VAR_POST_CHAR_SET
7263 && strucmp(ps_global->VAR_POST_CHAR_SET, "UTF-8"))
7264 if(err && !*err)
7265 *err = cpystr(_("Posting-Character-Set is ignored with Use-System-Translation turned on"));
7267 ps_global->posting_charmap = cpystr("UTF-8");
7270 set_locale_charmap(ps_global->keyboard_charmap);
7272 return(0);
7277 * Given a single printer string from the config file, returns pointers
7278 * to alloc'd strings containing the printer nickname, the command,
7279 * the init string, the trailer string, everything but the nickname string,
7280 * and everything but the command string. All_but_cmd includes the trailing
7281 * space at the end (the one before the command) but all_but_nick does not
7282 * include the leading space (the one before the [).
7283 * If you pass in a pointer it is guaranteed to come back pointing to an
7284 * allocated string, even if it is just an empty string. It is ok to pass
7285 * NULL for any of the six return strings.
7287 void
7288 parse_printer(char *input, char **nick, char **cmd, char **init, char **trailer,
7289 char **all_but_nick, char **all_but_cmd)
7291 char *p, *q, *start, *saved_options = NULL;
7292 int tmpsave, cnt;
7294 if(!input)
7295 input = "";
7297 if(nick || all_but_nick){
7298 if((p = srchstr(input, " [")) != NULL){
7299 if(all_but_nick)
7300 *all_but_nick = cpystr(p+1);
7302 if(nick){
7303 while(p-1 > input && isspace((unsigned char)*(p-1)))
7304 p--;
7306 tmpsave = *p;
7307 *p = '\0';
7308 *nick = cpystr(input);
7309 *p = tmpsave;
7312 else{
7313 if(nick)
7314 *nick = cpystr("");
7316 if(all_but_nick)
7317 *all_but_nick = cpystr(input);
7321 if((p = srchstr(input, "] ")) != NULL){
7323 ++p;
7324 }while(isspace((unsigned char)*p));
7326 tmpsave = *p;
7327 *p = '\0';
7328 saved_options = cpystr(input);
7329 *p = tmpsave;
7331 else
7332 p = input;
7334 if(cmd)
7335 *cmd = cpystr(p);
7337 if(init){
7338 if(saved_options && (p = srchstr(saved_options, "INIT="))){
7339 start = p + strlen("INIT=");
7340 for(cnt=0, p = start; *p && *(p+1) && isxpair(p); p += 2)
7341 cnt++;
7343 q = *init = (char *)fs_get((cnt + 1) * sizeof(char));
7344 for(p = start; *p && *(p+1) && isxpair(p); p += 2)
7345 *q++ = read_hex(p);
7347 *q = '\0';
7349 else
7350 *init = cpystr("");
7353 if(trailer){
7354 if(saved_options && (p = srchstr(saved_options, "TRAILER="))){
7355 start = p + strlen("TRAILER=");
7356 for(cnt=0, p = start; *p && *(p+1) && isxpair(p); p += 2)
7357 cnt++;
7359 q = *trailer = (char *)fs_get((cnt + 1) * sizeof(char));
7360 for(p = start; *p && *(p+1) && isxpair(p); p += 2)
7361 *q++ = read_hex(p);
7363 *q = '\0';
7365 else
7366 *trailer = cpystr("");
7369 if(all_but_cmd){
7370 if(saved_options)
7371 *all_but_cmd = saved_options;
7372 else
7373 *all_but_cmd = cpystr("");
7375 else if(saved_options)
7376 fs_give((void **)&saved_options);
7381 copy_pinerc(char *local, char *remote, char **err_msg)
7383 return(copy_localfile_to_remotefldr(RemImap, local, remote,
7384 REMOTE_PINERC_SUBTYPE,
7385 err_msg));
7390 copy_abook(char *local, char *remote, char **err_msg)
7392 return(copy_localfile_to_remotefldr(RemImap, local, remote,
7393 REMOTE_ABOOK_SUBTYPE,
7394 err_msg));
7399 * Copy local file to remote folder.
7401 * Args remotetype -- type of remote folder
7402 * local -- name of local file
7403 * remote -- name of remote folder
7404 * subtype --
7406 * Returns 0 on success.
7409 copy_localfile_to_remotefldr(RemType remotetype, char *local, char *remote,
7410 char *subtype, char **err_msg)
7412 int retfail = -1;
7413 unsigned flags;
7414 REMDATA_S *rd;
7416 dprint((9, "copy_localfile_to_remotefldr(%s,%s)\n",
7417 local ? local : "<null>",
7418 remote ? remote : "<null>"));
7420 *err_msg = (char *)fs_get(MAXPATH * sizeof(char));
7422 if(!local || !*local){
7423 snprintf(*err_msg, MAXPATH, _("No local file specified"));
7424 return(retfail);
7427 if(!remote || !*remote){
7428 snprintf(*err_msg, MAXPATH, _("No remote folder specified"));
7429 return(retfail);
7432 if(!IS_REMOTE(remote)){
7433 snprintf(*err_msg, MAXPATH, _("Remote folder name \"%s\" %s"), remote,
7434 (*remote != '{') ? _("must begin with \"{\"") : _("not valid"));
7435 return(retfail);
7438 if(IS_REMOTE(local)){
7439 snprintf(*err_msg, MAXPATH, _("First argument \"%s\" must be a local filename"),
7440 local);
7441 return(retfail);
7444 if(can_access(local, ACCESS_EXISTS) != 0){
7445 snprintf(*err_msg, MAXPATH, _("Local file \"%s\" does not exist"), local);
7446 return(retfail);
7449 if(can_access(local, READ_ACCESS) != 0){
7450 snprintf(*err_msg, MAXPATH, _("Can't read local file \"%s\": %s"),
7451 local, error_description(errno));
7452 return(retfail);
7456 * Check if remote folder exists and create it if it doesn't.
7458 flags = 0;
7459 rd = rd_create_remote(remotetype, remote, subtype,
7460 &flags, _("Error: "), _("Can't copy to remote folder."));
7462 if(!rd || rd->access == NoExists){
7463 snprintf(*err_msg, MAXPATH, _("Can't create \"%s\""), remote);
7464 if(rd)
7465 rd_free_remdata(&rd);
7467 return(retfail);
7470 if(rd->access == MaybeRorW)
7471 rd->access = ReadWrite;
7473 rd->flags |= (NO_META_UPDATE | DO_REMTRIM);
7474 rd->lf = cpystr(local);
7476 rd_open_remote(rd);
7477 if(!rd_stream_exists(rd)){
7478 snprintf(*err_msg, MAXPATH, _("Can't open remote folder \"%s\""), rd->rn);
7479 rd_free_remdata(&rd);
7480 return(retfail);
7483 if(rd_remote_is_readonly(rd)){
7484 snprintf(*err_msg, MAXPATH, _("Remote folder \"%s\" is readonly"), rd->rn);
7485 rd_free_remdata(&rd);
7486 return(retfail);
7489 switch(rd->type){
7490 case RemImap:
7492 * Empty folder, add a header msg.
7494 if(rd->t.i.stream->nmsgs == 0){
7495 if(rd_init_remote(rd, 1) != 0){
7496 snprintf(*err_msg, MAXPATH,
7497 _("Failed initializing remote folder \"%s\", check debug file"),
7498 rd->rn);
7499 rd_free_remdata(&rd);
7500 return(retfail);
7504 fs_give((void **)err_msg);
7505 *err_msg = NULL;
7506 if(rd_chk_for_hdr_msg(&(rd->t.i.stream), rd, err_msg)){
7507 rd_free_remdata(&rd);
7508 return(retfail);
7511 break;
7513 default:
7514 break;
7517 if(rd_update_remote(rd, NULL) != 0){
7518 snprintf(*err_msg, MAXPATH, _("Error copying to remote folder \"%s\""), rd->rn);
7519 rd_free_remdata(&rd);
7520 return(retfail);
7523 rd_update_metadata(rd, NULL);
7524 rd_close_remdata(&rd);
7526 fs_give((void **)err_msg);
7527 return(0);
7531 /*----------------------------------------------------------------------
7532 Panic pine - call on detected programmatic errors to exit pine, with arg
7534 Input: message -- printf styule string for panic message (see above)
7535 arg -- argument for printf string
7537 Result: The various tty modes are restored
7538 If debugging is active a core dump will be generated
7539 Exits Pine
7540 ----*/
7541 void
7542 panic1(char *message, char *arg)
7544 char buf1[1001], buf2[1001];
7546 snprintf(buf1, sizeof(buf1), "%.*s", MAX(sizeof(buf1) - 1 - strlen(message), 0), arg);
7547 snprintf(buf2, sizeof(buf2), message, buf1);
7548 panic(buf2);
7555 HelpType
7556 config_help(int var, int feature)
7558 switch(var){
7559 case V_FEATURE_LIST :
7560 return(feature_list_help(feature));
7561 break;
7563 case V_PERSONAL_NAME :
7564 return(h_config_pers_name);
7565 case V_USER_ID :
7566 return(h_config_user_id);
7567 case V_USER_DOMAIN :
7568 return(h_config_user_dom);
7569 case V_SMTP_SERVER :
7570 return(h_config_smtp_server);
7571 case V_NNTP_SERVER :
7572 return(h_config_nntp_server);
7573 case V_INBOX_PATH :
7574 return(h_config_inbox_path);
7575 case V_PRUNED_FOLDERS :
7576 return(h_config_pruned_folders);
7577 case V_DEFAULT_FCC :
7578 return(h_config_default_fcc);
7579 case V_DEFAULT_SAVE_FOLDER :
7580 return(h_config_def_save_folder);
7581 case V_POSTPONED_FOLDER :
7582 return(h_config_postponed_folder);
7583 case V_READ_MESSAGE_FOLDER :
7584 return(h_config_read_message_folder);
7585 case V_FORM_FOLDER :
7586 return(h_config_form_folder);
7587 case V_ARCHIVED_FOLDERS :
7588 return(h_config_archived_folders);
7589 case V_SIGNATURE_FILE :
7590 return(h_config_signature_file);
7591 case V_LITERAL_SIG :
7592 return(h_config_literal_sig);
7593 case V_INIT_CMD_LIST :
7594 return(h_config_init_cmd_list);
7595 case V_COMP_HDRS :
7596 return(h_config_comp_hdrs);
7597 case V_CUSTOM_HDRS :
7598 return(h_config_custom_hdrs);
7599 case V_VIEW_HEADERS :
7600 return(h_config_viewer_headers);
7601 case V_VIEW_MARGIN_LEFT :
7602 return(h_config_viewer_margin_left);
7603 case V_VIEW_MARGIN_RIGHT :
7604 return(h_config_viewer_margin_right);
7605 case V_QUOTE_SUPPRESSION :
7606 return(h_config_quote_suppression);
7607 case V_SAVED_MSG_NAME_RULE :
7608 return(h_config_saved_msg_name_rule);
7609 case V_FCC_RULE :
7610 return(h_config_fcc_rule);
7611 case V_SORT_KEY :
7612 return(h_config_sort_key);
7613 case V_AB_SORT_RULE :
7614 return(h_config_ab_sort_rule);
7615 case V_FLD_SORT_RULE :
7616 return(h_config_fld_sort_rule);
7617 case V_POST_CHAR_SET :
7618 return(h_config_post_char_set);
7619 case V_UNK_CHAR_SET :
7620 return(h_config_unk_char_set);
7621 #ifndef _WINDOWS
7622 case V_KEY_CHAR_SET :
7623 return(h_config_key_char_set);
7624 case V_CHAR_SET :
7625 return(h_config_char_set);
7626 #endif /* ! _WINDOWS */
7627 case V_EDITOR :
7628 return(h_config_editor);
7629 case V_SPELLER :
7630 return(h_config_speller);
7631 case V_DISPLAY_FILTERS :
7632 return(h_config_display_filters);
7633 case V_SEND_FILTER :
7634 return(h_config_sending_filter);
7635 case V_ALT_ADDRS :
7636 return(h_config_alt_addresses);
7637 case V_KEYWORDS :
7638 return(h_config_keywords);
7639 case V_KW_BRACES :
7640 return(h_config_kw_braces);
7641 case V_OPENING_SEP :
7642 return(h_config_opening_sep);
7643 case V_KW_COLORS :
7644 return(h_config_kw_color);
7645 case V_ABOOK_FORMATS :
7646 return(h_config_abook_formats);
7647 case V_INDEX_FORMAT :
7648 return(h_config_index_format);
7649 case V_INCCHECKTIMEO :
7650 return(h_config_incoming_timeo);
7651 case V_INCCHECKINTERVAL :
7652 return(h_config_incoming_interv);
7653 case V_INC2NDCHECKINTERVAL :
7654 return(h_config_incoming_second_interv);
7655 case V_INCCHECKLIST :
7656 return(h_config_incoming_list);
7657 case V_OVERLAP :
7658 return(h_config_viewer_overlap);
7659 case V_MAXREMSTREAM :
7660 return(h_config_maxremstream);
7661 case V_PERMLOCKED :
7662 return(h_config_permlocked);
7663 case V_MARGIN :
7664 return(h_config_scroll_margin);
7665 case V_DEADLETS :
7666 return(h_config_deadlets);
7667 case V_FILLCOL :
7668 return(h_config_composer_wrap_column);
7669 case V_TCPOPENTIMEO :
7670 return(h_config_tcp_open_timeo);
7671 case V_TCPREADWARNTIMEO :
7672 return(h_config_tcp_readwarn_timeo);
7673 case V_TCPWRITEWARNTIMEO :
7674 return(h_config_tcp_writewarn_timeo);
7675 case V_TCPQUERYTIMEO :
7676 return(h_config_tcp_query_timeo);
7677 case V_RSHOPENTIMEO :
7678 return(h_config_rsh_open_timeo);
7679 case V_SSHOPENTIMEO :
7680 return(h_config_ssh_open_timeo);
7681 case V_USERINPUTTIMEO :
7682 return(h_config_user_input_timeo);
7683 case V_REMOTE_ABOOK_VALIDITY :
7684 return(h_config_remote_abook_validity);
7685 case V_REMOTE_ABOOK_HISTORY :
7686 return(h_config_remote_abook_history);
7687 case V_INCOMING_FOLDERS :
7688 return(h_config_incoming_folders);
7689 case V_FOLDER_SPEC :
7690 return(h_config_folder_spec);
7691 case V_NEWS_SPEC :
7692 return(h_config_news_spec);
7693 case V_ADDRESSBOOK :
7694 return(h_config_address_book);
7695 case V_GLOB_ADDRBOOK :
7696 return(h_config_glob_addrbook);
7697 case V_LAST_VERS_USED :
7698 return(h_config_last_vers);
7699 case V_SENDMAIL_PATH :
7700 return(h_config_sendmail_path);
7701 case V_OPER_DIR :
7702 return(h_config_oper_dir);
7703 case V_RSHPATH :
7704 return(h_config_rshpath);
7705 case V_RSHCMD :
7706 return(h_config_rshcmd);
7707 case V_SSHPATH :
7708 return(h_config_sshpath);
7709 case V_SSHCMD :
7710 return(h_config_sshcmd);
7711 case V_NEW_VER_QUELL :
7712 return(h_config_new_ver_quell);
7713 case V_DISABLE_DRIVERS :
7714 return(h_config_disable_drivers);
7715 case V_DISABLE_AUTHS :
7716 return(h_config_disable_auths);
7717 case V_REMOTE_ABOOK_METADATA :
7718 return(h_config_abook_metafile);
7719 case V_REPLY_STRING :
7720 return(h_config_reply_indent_string);
7721 case V_WORDSEPS :
7722 return(h_config_wordseps);
7723 case V_QUOTE_REPLACE_STRING :
7724 return(h_config_quote_replace_string);
7725 case V_REPLY_INTRO :
7726 return(h_config_reply_intro);
7727 case V_EMPTY_HDR_MSG :
7728 return(h_config_empty_hdr_msg);
7729 case V_STATUS_MSG_DELAY :
7730 return(h_config_status_msg_delay);
7731 case V_ACTIVE_MSG_INTERVAL :
7732 return(h_config_active_msg_interval);
7733 case V_MAILCHECK :
7734 return(h_config_mailcheck);
7735 case V_MAILCHECKNONCURR :
7736 return(h_config_mailchecknoncurr);
7737 case V_MAILDROPCHECK :
7738 return(h_config_maildropcheck);
7739 case V_NNTPRANGE :
7740 return(h_config_nntprange);
7741 case V_NEWS_ACTIVE_PATH :
7742 return(h_config_news_active);
7743 case V_NEWS_SPOOL_DIR :
7744 return(h_config_news_spool);
7745 case V_IMAGE_VIEWER :
7746 return(h_config_image_viewer);
7747 case V_USE_ONLY_DOMAIN_NAME :
7748 return(h_config_domain_name);
7749 case V_LAST_TIME_PRUNE_QUESTION :
7750 return(h_config_prune_date);
7751 case V_UPLOAD_CMD:
7752 return(h_config_upload_cmd);
7753 case V_UPLOAD_CMD_PREFIX:
7754 return(h_config_upload_prefix);
7755 case V_DOWNLOAD_CMD:
7756 return(h_config_download_cmd);
7757 case V_DOWNLOAD_CMD_PREFIX:
7758 return(h_config_download_prefix);
7759 case V_GOTO_DEFAULT_RULE:
7760 return(h_config_goto_default);
7761 case V_INCOMING_STARTUP:
7762 return(h_config_inc_startup);
7763 case V_PRUNING_RULE:
7764 return(h_config_pruning_rule);
7765 case V_REOPEN_RULE:
7766 return(h_config_reopen_rule);
7767 case V_THREAD_DISP_STYLE:
7768 return(h_config_thread_disp_style);
7769 case V_THREAD_INDEX_STYLE:
7770 return(h_config_thread_index_style);
7771 case V_THREAD_MORE_CHAR:
7772 return(h_config_thread_indicator_char);
7773 case V_THREAD_EXP_CHAR:
7774 return(h_config_thread_exp_char);
7775 case V_THREAD_LASTREPLY_CHAR:
7776 return(h_config_thread_lastreply_char);
7777 case V_MAILCAP_PATH :
7778 return(h_config_mailcap_path);
7779 case V_MIMETYPE_PATH :
7780 return(h_config_mimetype_path);
7781 #if !defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)
7782 case V_FIFOPATH :
7783 return(h_config_fifopath);
7784 #endif
7785 case V_NMW_WIDTH :
7786 return(h_config_newmailwidth);
7787 case V_NEWSRC_PATH :
7788 return(h_config_newsrc_path);
7789 case V_BROWSER :
7790 return(h_config_browser);
7791 #if defined(DOS) || defined(OS2)
7792 case V_FILE_DIR :
7793 return(h_config_file_dir);
7794 #endif
7795 case V_NORM_FORE_COLOR :
7796 case V_NORM_BACK_COLOR :
7797 return(h_config_normal_color);
7798 case V_REV_FORE_COLOR :
7799 case V_REV_BACK_COLOR :
7800 return(h_config_reverse_color);
7801 case V_TITLE_FORE_COLOR :
7802 case V_TITLE_BACK_COLOR :
7803 return(h_config_title_color);
7804 case V_TITLECLOSED_FORE_COLOR :
7805 case V_TITLECLOSED_BACK_COLOR :
7806 return(h_config_titleclosed_color);
7807 case V_FOLDER_FORE_COLOR:
7808 return(h_config_folder_color);
7809 case V_DIRECTORY_FORE_COLOR:
7810 return(h_config_directory_color);
7811 case V_FOLDER_LIST_FORE_COLOR:
7812 return(h_config_folder_list_color);
7813 case V_STATUS_FORE_COLOR :
7814 case V_STATUS_BACK_COLOR :
7815 return(h_config_status_color);
7816 case V_SLCTBL_FORE_COLOR :
7817 case V_SLCTBL_BACK_COLOR :
7818 return(h_config_slctbl_color);
7819 case V_QUOTE1_FORE_COLOR :
7820 case V_QUOTE2_FORE_COLOR :
7821 case V_QUOTE3_FORE_COLOR :
7822 case V_QUOTE1_BACK_COLOR :
7823 case V_QUOTE2_BACK_COLOR :
7824 case V_QUOTE3_BACK_COLOR :
7825 return(h_config_quote_color);
7826 case V_INCUNSEEN_FORE_COLOR :
7827 case V_INCUNSEEN_BACK_COLOR :
7828 return(h_config_incunseen_color);
7829 case V_SIGNATURE_FORE_COLOR :
7830 case V_SIGNATURE_BACK_COLOR :
7831 return(h_config_signature_color);
7832 case V_PROMPT_FORE_COLOR :
7833 case V_PROMPT_BACK_COLOR :
7834 return(h_config_prompt_color);
7835 case V_HEADER_GENERAL_FORE_COLOR :
7836 case V_HEADER_GENERAL_BACK_COLOR :
7837 return(h_config_header_general_color);
7838 case V_IND_PLUS_FORE_COLOR :
7839 case V_IND_IMP_FORE_COLOR :
7840 case V_IND_DEL_FORE_COLOR :
7841 case V_IND_ANS_FORE_COLOR :
7842 case V_IND_NEW_FORE_COLOR :
7843 case V_IND_UNS_FORE_COLOR :
7844 case V_IND_REC_FORE_COLOR :
7845 case V_IND_FWD_FORE_COLOR :
7846 case V_IND_PLUS_BACK_COLOR :
7847 case V_IND_IMP_BACK_COLOR :
7848 case V_IND_DEL_BACK_COLOR :
7849 case V_IND_ANS_BACK_COLOR :
7850 case V_IND_NEW_BACK_COLOR :
7851 case V_IND_UNS_BACK_COLOR :
7852 case V_IND_REC_BACK_COLOR :
7853 case V_IND_FWD_BACK_COLOR :
7854 return(h_config_index_color);
7855 case V_IND_OP_FORE_COLOR :
7856 case V_IND_OP_BACK_COLOR :
7857 return(h_config_index_opening_color);
7858 case V_IND_SUBJ_FORE_COLOR :
7859 case V_IND_SUBJ_BACK_COLOR :
7860 return(h_config_index_subject_color);
7861 case V_IND_FROM_FORE_COLOR :
7862 case V_IND_FROM_BACK_COLOR :
7863 return(h_config_index_from_color);
7864 case V_IND_HIPRI_FORE_COLOR :
7865 case V_IND_HIPRI_BACK_COLOR :
7866 case V_IND_LOPRI_FORE_COLOR :
7867 case V_IND_LOPRI_BACK_COLOR :
7868 return(h_config_index_pri_color);
7869 case V_IND_ARR_FORE_COLOR :
7870 case V_IND_ARR_BACK_COLOR :
7871 return(h_config_index_arrow_color);
7872 case V_KEYLABEL_FORE_COLOR :
7873 case V_KEYLABEL_BACK_COLOR :
7874 return(h_config_keylabel_color);
7875 case V_KEYNAME_FORE_COLOR :
7876 case V_KEYNAME_BACK_COLOR :
7877 return(h_config_keyname_color);
7878 case V_METAMSG_FORE_COLOR :
7879 case V_METAMSG_BACK_COLOR :
7880 return(h_config_metamsg_color);
7881 case V_VIEW_HDR_COLORS :
7882 return(h_config_customhdr_color);
7883 case V_INDEX_TOKEN_COLORS :
7884 return(h_config_indextoken_color);
7885 case V_PRINTER :
7886 return(h_config_printer);
7887 case V_PERSONAL_PRINT_CATEGORY :
7888 return(h_config_print_cat);
7889 case V_PERSONAL_PRINT_COMMAND :
7890 return(h_config_print_command);
7891 case V_PAT_ROLES :
7892 return(h_config_pat_roles);
7893 case V_PAT_FILTS :
7894 return(h_config_pat_filts);
7895 case V_PAT_SCORES :
7896 return(h_config_pat_scores);
7897 case V_PAT_INCOLS :
7898 return(h_config_pat_incols);
7899 case V_PAT_OTHER :
7900 return(h_config_pat_other);
7901 case V_PAT_SRCH :
7902 return(h_config_pat_srch);
7903 case V_INDEX_COLOR_STYLE :
7904 return(h_config_index_color_style);
7905 case V_TITLEBAR_COLOR_STYLE :
7906 return(h_config_titlebar_color_style);
7907 #ifdef _WINDOWS
7908 case V_FONT_NAME :
7909 return(h_config_font_name);
7910 case V_FONT_SIZE :
7911 return(h_config_font_size);
7912 case V_FONT_STYLE :
7913 return(h_config_font_style);
7914 case V_FONT_CHAR_SET :
7915 return(h_config_font_char_set);
7916 case V_PRINT_FONT_NAME :
7917 return(h_config_print_font_name);
7918 case V_PRINT_FONT_SIZE :
7919 return(h_config_print_font_size);
7920 case V_PRINT_FONT_STYLE :
7921 return(h_config_print_font_style);
7922 case V_PRINT_FONT_CHAR_SET :
7923 return(h_config_print_font_char_set);
7924 case V_WINDOW_POSITION :
7925 return(h_config_window_position);
7926 case V_CURSOR_STYLE :
7927 return(h_config_cursor_style);
7928 #else
7929 case V_COLOR_STYLE :
7930 return(h_config_color_style);
7931 #endif
7932 #ifdef ENABLE_LDAP
7933 case V_LDAP_SERVERS :
7934 return(h_config_ldap_servers);
7935 #endif
7936 #ifdef SMIME
7937 case V_PUBLICCERT_DIR :
7938 return(h_config_smime_pubcertdir);
7939 case V_PUBLICCERT_CONTAINER :
7940 return(h_config_smime_pubcertcon);
7941 case V_PRIVATEKEY_DIR :
7942 return(h_config_smime_privkeydir);
7943 case V_PRIVATEKEY_CONTAINER :
7944 return(h_config_smime_privkeycon);
7945 case V_CACERT_DIR :
7946 return(h_config_smime_cacertdir);
7947 case V_CACERT_CONTAINER :
7948 return(h_config_smime_cacertcon);
7949 #endif
7950 case V_RSS_NEWS :
7951 return(h_config_rss_news);
7952 case V_RSS_WEATHER :
7953 return(h_config_rss_weather);
7954 case V_WP_INDEXHEIGHT :
7955 return(h_config_wp_indexheight);
7956 case V_WP_INDEXLINES :
7957 return(h_config_wp_indexlines);
7958 case V_WP_AGGSTATE :
7959 return(h_config_wp_aggstate);
7960 case V_WP_STATE :
7961 return(h_config_wp_state);
7962 case V_WP_COLUMNS :
7963 return(h_config_wp_columns);
7964 default :
7965 return(NO_HELP);
7971 * We don't want the user to be able to edit their pinerc and set
7972 * printer to whatever they want if personal-print-command is fixed.
7973 * So make sure printer is set to something legitimate. If it isn't,
7974 * set it to something standard and return non-zero.
7977 printer_value_check_and_adjust(void)
7979 char **tt;
7980 char aname[100], wname[100];
7981 int ok = 0;
7982 struct variable *vars = ps_global->vars;
7984 if(vars[V_PERSONAL_PRINT_COMMAND].is_fixed && !vars[V_PRINTER].is_fixed){
7985 strncpy(aname, ANSI_PRINTER, sizeof(aname));
7986 aname[sizeof(aname)-1] = '\0';
7987 strncat(aname, "-no-formfeed", sizeof(aname)-strlen(aname)-1);
7988 strncpy(wname, WYSE_PRINTER, sizeof(wname));
7989 wname[sizeof(wname)-1] = '\0';
7990 strncat(wname, "-no-formfeed", sizeof(wname)-strlen(wname)-1);
7991 if(strucmp(VAR_PRINTER, ANSI_PRINTER) == 0
7992 || strucmp(VAR_PRINTER, aname) == 0
7993 || strucmp(VAR_PRINTER, WYSE_PRINTER) == 0
7994 || strucmp(VAR_PRINTER, wname) == 0)
7995 ok++;
7996 else if(VAR_STANDARD_PRINTER && VAR_STANDARD_PRINTER[0]){
7997 for(tt = VAR_STANDARD_PRINTER; *tt; tt++)
7998 if(strucmp(VAR_PRINTER, *tt) == 0)
7999 break;
8001 if(*tt)
8002 ok++;
8005 if(!ok){
8006 char *val;
8007 struct variable *v;
8009 if(VAR_STANDARD_PRINTER && VAR_STANDARD_PRINTER[0])
8010 val = VAR_STANDARD_PRINTER[0];
8011 else
8012 val = ANSI_PRINTER;
8014 v = &vars[V_PRINTER];
8015 if(v->main_user_val.p)
8016 fs_give((void **)&v->main_user_val.p);
8017 if(v->post_user_val.p)
8018 fs_give((void **)&v->post_user_val.p);
8019 if(v->current_val.p)
8020 fs_give((void **)&v->current_val.p);
8022 v->main_user_val.p = cpystr(val);
8023 v->current_val.p = cpystr(val);
8027 return(!ok);
8031 char **
8032 get_supported_options(void)
8034 char **config;
8035 DRIVER *d;
8036 AUTHENTICATOR *a;
8037 char *title = _("Supported features in this Alpine");
8038 char sbuf[MAX_SCREEN_COLS+1];
8039 int cnt, alcnt, len, cols, disabled, any_disabled = 0;;
8042 * Line count:
8043 * Title + blank = 2
8044 * SSL Title + SSL lines + blank = 5
8045 * Auth title + blank = 2
8046 * Driver title + blank = 2
8047 * LDAP title + LDAP line = 2
8048 * Disabled explanation + blank line = 4
8049 * end = 1
8051 cnt = 18;
8052 for(a = mail_lookup_auth(1); a; a = a->next)
8053 cnt++;
8054 for(d = (DRIVER *)mail_parameters(NIL, GET_DRIVERS, NIL);
8055 d; d = d->next)
8056 cnt++;
8058 alcnt = cnt;
8059 config = (char **) fs_get(alcnt * sizeof(char *));
8060 memset(config, 0, alcnt * sizeof(char *));
8062 cols = ps_global->ttyo ? ps_global->ttyo->screen_cols : 0;
8063 len = utf8_width(title);
8064 snprintf(sbuf, sizeof(sbuf), "%*s%s", cols > len ? (cols-len)/2 : 0, "", title);
8066 cnt = 0;
8067 if(cnt < alcnt)
8068 config[cnt] = cpystr(sbuf);
8070 if(++cnt < alcnt)
8071 config[cnt] = cpystr("");
8073 if(++cnt < alcnt)
8074 /* TRANSLATORS: headings */
8075 config[cnt] = cpystr(_("Encryption:"));
8077 if(++cnt < alcnt && mail_parameters(NIL, GET_SSLDRIVER, NIL))
8078 config[cnt] = cpystr(_(" TLS and SSL"));
8079 else
8080 config[cnt] = cpystr(_(" None (no TLS or SSL)"));
8081 #ifdef SSL_SUPPORTS_TLSV1_2
8082 if(++cnt < alcnt)
8083 config[cnt] = cpystr(" TLSv1.1, TLSv1.2, and DTLSv1");
8084 #endif
8085 #ifdef SMIME
8086 if(++cnt < alcnt)
8087 config[cnt] = cpystr(" S/MIME");
8088 #endif
8090 if(++cnt < alcnt)
8091 config[cnt] = cpystr("");
8093 if(++cnt < alcnt)
8094 config[cnt] = cpystr(_("Authenticators:"));
8096 for(a = mail_lookup_auth(1); a; a = a->next){
8097 disabled = (a->client == NULL && a->server == NULL);
8098 any_disabled += disabled;
8099 snprintf(sbuf, sizeof(sbuf), " %s%s", a->name, disabled ? " (disabled)" : "");
8100 if(++cnt < alcnt)
8101 config[cnt] = cpystr(sbuf);
8104 if(++cnt < alcnt)
8105 config[cnt] = cpystr("");
8107 if(++cnt < alcnt)
8108 config[cnt] = cpystr(_("Mailbox drivers:"));
8110 for(d = (DRIVER *)mail_parameters(NIL, GET_DRIVERS, NIL);
8111 d; d = d->next){
8112 disabled = (d->flags & DR_DISABLE);
8113 any_disabled += disabled;
8114 snprintf(sbuf, sizeof(sbuf), " %s%s", d->name, disabled ? " (disabled)" : "");
8115 if(++cnt < alcnt)
8116 config[cnt] = cpystr(sbuf);
8119 if(++cnt < alcnt)
8120 config[cnt] = cpystr("");
8122 if(++cnt < alcnt)
8123 config[cnt] = cpystr(_("Directories:"));
8125 #ifdef ENABLE_LDAP
8126 if(++cnt < alcnt)
8127 config[cnt] = cpystr(" LDAP");
8128 #else
8129 if(++cnt < alcnt)
8130 config[cnt] = cpystr(" None (no LDAP)");
8131 #endif
8133 if(any_disabled){
8134 if(++cnt < alcnt)
8135 config[cnt] = cpystr("");
8137 if(ps_global->ttyo){
8138 if(++cnt < alcnt)
8139 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."));
8141 else{
8142 if(++cnt < alcnt)
8143 config[cnt] = cpystr(_("Authenticators may be disabled because of the \"disable-these-authenticators\""));
8144 if(++cnt < alcnt)
8145 config[cnt] = cpystr(_("hidden config option. Mailbox drivers may be disabled because of the"));
8146 if(++cnt < alcnt)
8147 config[cnt] = cpystr(_("\"disable-these-drivers\" hidden config option."));
8151 if(++cnt < alcnt)
8152 config[cnt] = NULL;
8154 return(config);
8158 unsigned
8159 reset_startup_rule(MAILSTREAM *stream)
8161 long rflags = ROLE_DO_OTHER;
8162 PAT_STATE pstate;
8163 PAT_S *pat;
8164 unsigned startup_rule;
8166 startup_rule = IS_NOTSET;
8168 if(stream && nonempty_patterns(rflags, &pstate)){
8169 for(pat = first_pattern(&pstate); pat; pat = next_pattern(&pstate)){
8170 if(match_pattern(pat->patgrp, stream, NULL, NULL, NULL,
8171 SE_NOSERVER|SE_NOPREFETCH))
8172 break;
8175 if(pat && pat->action && !pat->action->bogus)
8176 startup_rule = pat->action->startup_rule;
8179 return(startup_rule);
8183 #ifdef _WINDOWS
8185 char *
8186 transformed_color(old)
8187 char *old;
8189 if(!old)
8190 return("");
8192 if(!struncmp(old, "color008", 8))
8193 return("colorlgr");
8194 else if(!struncmp(old, "color009", 8))
8195 return("colormgr");
8196 else if(!struncmp(old, "color010", 8))
8197 return("colordgr");
8199 return("");
8204 * If this is the first time we've run a version > 4.40, and there
8205 * is evidence that the config file has not been used by unix pine,
8206 * then we convert color008 to colorlgr, color009 to colormgr, and
8207 * color010 to colordgr. If the config file is being used by
8208 * unix pine then color008 may really supposed to be color008, color009
8209 * may really supposed to be red, and color010 may really supposed to be
8210 * green. Same if we've already run 4.41 or higher previously.
8212 * Returns 0 if no changes, > 0 if something was changed.
8215 convert_pc_gray_names(ps, prc, which)
8216 struct pine *ps;
8217 PINERC_S *prc;
8218 EditWhich which;
8220 struct variable *v;
8221 int ret = 0, ic = 0;
8222 char **s, *t, *p, *pstr, *new, *pval, **apval, **lval;
8224 for(v = ps->vars; v->name; v++){
8225 if(!color_holding_var(ps, v) || v == &ps->vars[V_KW_COLORS])
8226 continue;
8228 if(v == &ps->vars[V_VIEW_HDR_COLORS]){
8230 if((lval = LVAL(v,which)) != NULL){
8231 /* fix these in place */
8232 for(s = lval; (t = *s) != NULL; s++){
8233 if((p = srchstr(t, "FG=color008")) ||
8234 (p = srchstr(t, "FG=color009")) ||
8235 (p = srchstr(t, "FG=color010"))){
8236 strncpy(p+3, transformed_color(p+3), 8);
8237 ret++;
8240 if((p = srchstr(t, "BG=color008")) ||
8241 (p = srchstr(t, "BG=color009")) ||
8242 (p = srchstr(t, "BG=color010"))){
8243 strncpy(p+3, transformed_color(p+3), 8);
8244 ret++;
8249 else{
8250 if((pval = PVAL(v,which)) != NULL){
8251 apval = APVAL(v,which);
8252 if(apval && (!strucmp(pval, "color008") ||
8253 !strucmp(pval, "color009") ||
8254 !strucmp(pval, "color010"))){
8255 new = transformed_color(pval);
8256 if(*apval)
8257 fs_give((void **)apval);
8259 *apval = cpystr(new);
8260 ret++;
8266 v = &ps->vars[V_PAT_INCOLS];
8267 if((lval = LVAL(v,which)) != NULL){
8268 for(s = lval; (t = *s) != NULL; s++){
8269 if((pstr = srchstr(t, "action=")) != NULL){
8270 if((p = srchstr(pstr, "FG=color008")) ||
8271 (p = srchstr(pstr, "FG=color009")) ||
8272 (p = srchstr(pstr, "FG=color010"))){
8273 strncpy(p+3, transformed_color(p+3), 8);
8274 ic++;
8277 if((p = srchstr(pstr, "BG=color008")) ||
8278 (p = srchstr(pstr, "BG=color009")) ||
8279 (p = srchstr(pstr, "BG=color010"))){
8280 strncpy(p+3, transformed_color(p+3), 8);
8281 ic++;
8287 if(ic)
8288 set_current_val(&ps->vars[V_PAT_INCOLS], TRUE, TRUE);
8290 return(ret+ic);
8295 unix_color_style_in_pinerc(prc)
8296 PINERC_S *prc;
8298 PINERC_LINE *pline;
8300 for(pline = prc ? prc->pinerc_lines : NULL;
8301 pline && (pline->var || pline->line); pline++)
8302 if(pline->line && !struncmp("color-style=", pline->line, 12))
8303 return(1);
8305 return(0);
8308 char *
8309 pcpine_general_help(titlebuf)
8310 char *titlebuf;
8312 if(titlebuf)
8313 strcpy(titlebuf, "PC Alpine For Windows");
8315 return(pcpine_help(h_pine_for_windows));
8318 #endif /* _WINDOWS */