Merge branch 'ical'
[alpine.git] / pith / conf.c
blobb689e9a2c6dda319fe9874e36bc75bac5cafa38f
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-2017 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 #ifdef _WINDOWS
228 CONF_TXT_T cf_text_speller_dictionary[] = "Specifies the list of dictionaries used by Aspell.";
229 #endif /* _WINDOWS */
231 CONF_TXT_T cf_text_deadlets[] = "Specifies the number of dead letter files to keep when canceling.";
233 CONF_TXT_T cf_text_fillcol[] = "Specifies the column of the screen where the composer should wrap.";
235 CONF_TXT_T cf_text_replystr[] = "Specifies the string to insert when replying to a message.";
237 CONF_TXT_T cf_text_quotereplstr[] = "Specifies the string to replace quotes with when viewing a message.";
239 CONF_TXT_T cf_text_replyintro[] = "Specifies the introduction to insert when replying to a message.";
241 CONF_TXT_T cf_text_emptyhdr[] = "Specifies the string to use when sending a message with no to or cc.";
243 CONF_TXT_T cf_text_image_viewer[] = "Program to view images (e.g. GIF or TIFF attachments).";
245 CONF_TXT_T cf_text_browser[] = "List of programs to open Internet URLs (e.g. http or ftp references).";
247 CONF_TXT_T cf_text_history[] = "List of directories that are preferred locations to save or export attachments.";
249 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\".";
251 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\".";
253 CONF_TXT_T cf_reopen_rule[] = "Controls behavior when reopening an already open folder.";
255 CONF_TXT_T cf_text_thread_disp_style[] = "Style that MESSAGE INDEX is displayed in when threading.";
257 CONF_TXT_T cf_text_thread_index_style[] = "Style of THREAD INDEX or default MESSAGE INDEX when threading.";
259 CONF_TXT_T cf_text_thread_more_char[] = "When threading, character used to indicate collapsed messages underneath.";
261 CONF_TXT_T cf_text_thread_exp_char[] = "When threading, character used to indicate expanded messages underneath.";
263 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.";
265 CONF_TXT_T cf_text_use_only_domain_name[] = "If \"user-domain\" not set, strips hostname in FROM address. (Unix only)";
267 CONF_TXT_T cf_text_printer[] = "Your default printer selection";
269 CONF_TXT_T cf_text_personal_print_command[] = "List of special print commands";
271 CONF_TXT_T cf_text_personal_print_cat[] = "Which category default print command is in";
273 CONF_TXT_T cf_text_standard_printer[] = "The system wide standard printers";
275 CONF_TXT_T cf_text_last_time_prune_quest[] = "Set by Alpine; controls beginning-of-month sent-mail pruning.";
277 CONF_TXT_T cf_text_last_version_used[] = "Set by Alpine; controls display of \"new version\" message.";
279 CONF_TXT_T cf_text_disable_drivers[] = "List of mail drivers to disable.";
281 CONF_TXT_T cf_text_disable_auths[] = "List of SASL authenticators to disable.";
283 CONF_TXT_T cf_text_remote_abook_metafile[] = "Set by Alpine; contains data for caching remote address books.";
285 CONF_TXT_T cf_text_old_patterns[] = "Patterns is obsolete, use patterns-xxx";
287 CONF_TXT_T cf_text_old_filters[] = "Patterns-filters is obsolete, use patterns-filters2";
289 CONF_TXT_T cf_text_old_scores[] = "Patterns-scores is obsolete, use patterns-scores2";
291 CONF_TXT_T cf_text_patterns[] = "Patterns and their actions are stored here.";
293 CONF_TXT_T cf_text_remote_abook_history[] = "How many extra copies of remote address book should be kept. Default: 3";
295 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";
297 CONF_TXT_T cf_text_bugs_fullname[] = "Full name for bug report address used by \"Report Bug\" command";
299 CONF_TXT_T cf_text_bugs_address[] = "Email address used to send bug reports";
301 CONF_TXT_T cf_text_bugs_extras[] = "Program/Script used by \"Report Bug\" command. No default.";
303 CONF_TXT_T cf_text_suggest_fullname[] = "Full name for suggestion address used by \"Report Bug\" command";
305 CONF_TXT_T cf_text_suggest_address[] = "Email address used to send suggestions";
307 CONF_TXT_T cf_text_local_fullname[] = "Full name for \"local support\" address used by \"Report Bug\" command.\n# Default: Local Support";
309 CONF_TXT_T cf_text_local_address[] = "Email address used to send to \"local support\".\n# Default: postmaster";
311 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";
313 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.";
315 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.";
317 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)";
319 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.";
321 CONF_TXT_T cf_text_out_fltr[] = "This defines a program that message text is piped into before MIME\n# encoding, prior to sending";
323 CONF_TXT_T cf_text_alt_addrs[] = "A list of alternate addresses the user is known by";
325 CONF_TXT_T cf_text_keywords[] = "A list of keywords for use in categorizing messages";
327 CONF_TXT_T cf_text_kw_colors[] = "Colors used to display keywords in the index";
329 CONF_TXT_T cf_text_kw_braces[] = "Characters which surround keywords in SUBJKEY token.\n# Default is \"{\" \"} \"";
331 CONF_TXT_T cf_text_opening_sep[] = "Characters between subject and opening text in SUBJECTTEXT token.\n# Default is \" - \"";
333 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";
335 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";
337 CONF_TXT_T cf_text_overlap[] = "The number of lines of overlap when scrolling through message text";
339 CONF_TXT_T cf_text_maxremstreams[] = "The maximum number of non-stayopen remote connections that Alpine will use";
341 CONF_TXT_T cf_text_permlocked[] = "A list of folders that should be left open once opened (INBOX is implicit)";
343 CONF_TXT_T cf_text_margin[] = "Number of lines from top and bottom of screen where single\n# line scrolling occurs.";
345 CONF_TXT_T cf_text_stat_msg_delay[] = "The number of seconds to sleep after writing a status message";
347 CONF_TXT_T cf_text_busy_cue_rate[] = "Number of times per-second to update busy cue messages";
349 CONF_TXT_T cf_text_psleep[] = "UNIX ONLY (except MAC OSX): When an attachment is opened, this variable controls the number\n#of seconds to wait between checks if the user has ended viewing the attachment.\n#minimun value: 60 seconds, maximum value: 600 seconds (10 minutes). Default: 60 seconds";
351 CONF_TXT_T cf_text_mailcheck[] = "The approximate number of seconds between checks for new mail";
353 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";
355 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";
357 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";
359 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\".";
361 CONF_TXT_T cf_text_news_spooldir[] = "Directory containing system's news data.\n# The default is typically \"/usr/spool/news\"";
363 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.";
365 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.";
367 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.";
369 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.";
371 CONF_TXT_T cf_text_goto_default[] = "Sets the default folder and collection offered at the Goto Command's prompt.";
373 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.";
375 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.";
377 CONF_TXT_T cf_text_newmail_fifo_path[] = "Sets the filename for the newmail fifo (named pipe). Unix only.";
379 CONF_TXT_T cf_text_nmw_width[] = "Sets the width for the NewMail screen.";
381 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.";
383 CONF_TXT_T cf_text_debug_mem[] = "Debug-memory is obsolete";
385 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).";
387 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.";
389 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.";
391 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.";
393 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.";
395 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.";
397 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\")";
399 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.";
401 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.";
403 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.";
405 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.";
407 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.";
409 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.";
411 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\")";
413 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.";
415 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.";
417 CONF_TXT_T cf_text_elm_style_save[] = "Elm-style-save is obsolete, use saved-msg-name-rule";
419 CONF_TXT_T cf_text_header_in_reply[] = "Header-in-reply is obsolete, use include-header-in-reply in feature-list";
421 CONF_TXT_T cf_text_feature_level[] = "Feature-level is obsolete, use feature-list";
423 CONF_TXT_T cf_text_old_style_reply[] = "Old-style-reply is obsolete, use signature-at-bottom in feature-list";
425 CONF_TXT_T cf_text_compose_mime[] = "Compose-mime is obsolete";
427 CONF_TXT_T cf_text_show_all_characters[] = "Show-all-characters is obsolete";
429 CONF_TXT_T cf_text_save_by_sender[] = "Save-by-sender is obsolete, use saved-msg-name-rule";
431 CONF_TXT_T cf_text_file_dir[] = "Default directory used for Attachment handling (attach and save)\n# and Export command output";
433 CONF_TXT_T cf_text_folder_extension[] = "Folder-extension is obsolete";
435 CONF_TXT_T cf_text_normal_foreground_color[] = "Choose: black, blue, green, cyan, red, magenta, yellow, or white.";
437 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.";
439 CONF_TXT_T cf_text_newsrc_path[] = "Full path and name of NEWSRC file";
442 /*----------------------------------------------------------------------
443 These are the variables that control a number of pine functions. They
444 come out of the .pinerc and the /usr/local/lib/pine.conf files. Some can
445 be set by the user while in Alpine. Eventually all the local ones should
446 be so and maybe the global ones too.
448 Each variable can have a command-line, user, global, and current value.
449 All of these values are malloc'd. The user value is the one read out of
450 the user's .pinerc, the global value is the one from the system pine
451 configuration file. There are often defaults for the global values, set
452 at the start of init_vars(). Perhaps someday there will be group values.
453 The current value is the one that is actually in use.
454 ----*/
455 /* name is_changed_val
456 remove_quotes |
457 is_outermost | |
458 is_onlymain | | |
459 is_fixed | | | |
460 is_list | | | | |
461 is_global | | | | | |
462 is_user | | | | | | |
463 been_written | | | | | | | |
464 is_used | | | | | | | | |
465 is_obsolete | | | | | | | | | |
466 | | | | | | | | | | |
467 (on following line) description | | | | | | | | | | |
468 | | | | | | | | | | | |
469 | | | | | | | | | | | | */
470 static struct variable variables[] = {
471 {"personal-name", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
472 NULL, cf_text_personal_name},
474 #if defined(DOS) || defined(OS2)
475 /* Have to have this on DOS, PC's, Macs, etc... */
476 "user-id", 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0,
477 #else /* Don't allow on UNIX machines for some security */
478 "user-id", 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0,
479 #endif
480 "User ID", cf_text_user_id},
481 {"user-domain", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
482 NULL, cf_text_user_domain},
483 {"smtp-server", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
484 "SMTP Server (for sending)", cf_text_smtp_server},
485 {"nntp-server", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
486 "NNTP Server (for news)", cf_text_nntp_server},
487 {"inbox-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
488 NULL, cf_text_inbox_path},
489 {"incoming-archive-folders", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
490 NULL, cf_text_archived_folders},
491 {"pruned-folders", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
492 NULL, cf_text_pruned_folders},
493 {"default-fcc", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
494 "Default Fcc (File carbon copy)", cf_text_default_fcc},
495 {"default-saved-msg-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
496 "Default Saved Message Folder", cf_text_default_saved},
497 {"postponed-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
498 NULL, cf_text_postponed_folder},
499 {"read-message-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
500 NULL, cf_text_read_message_folder},
501 {"form-letter-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
502 NULL, cf_text_form_letter_folder},
503 {"trash-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
504 NULL, cf_text_trash_folder},
505 {"literal-signature", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
506 NULL, cf_text_literal_sig},
507 {"signature-file", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
508 NULL, cf_text_signature_file},
509 {"feature-list", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
510 NULL, cf_text_feature_list},
511 {"initial-keystroke-list", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
512 NULL, cf_text_initial_keystroke_list},
513 {"default-composer-hdrs", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
514 "Default Composer Headers", cf_text_default_composer_hdrs},
515 {"customized-hdrs", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
516 "Customized Headers", cf_text_customized_hdrs},
517 {"viewer-hdrs", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
518 "Viewer Headers", cf_text_view_headers},
519 {"viewer-margin-left", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
520 NULL, cf_text_view_margin_left},
521 {"viewer-margin-right", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
522 NULL, cf_text_view_margin_right},
523 {"quote-suppression-threshold", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
524 NULL, cf_text_quote_suppression},
525 {"saved-msg-name-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
526 "Saved Message Name Rule", cf_text_save_msg_name_rule},
527 {"fcc-name-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
528 NULL, cf_text_fcc_name_rule},
529 {"sort-key", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
530 NULL, cf_text_sort_key},
531 {"addrbook-sort-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
532 "Address Book Sort Rule", cf_text_addrbook_sort_rule},
533 {"folder-sort-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
534 NULL, cf_text_folder_sort_rule},
535 {"goto-default-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
536 NULL, cf_text_goto_default},
537 {"incoming-startup-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
538 NULL, cf_text_inc_startup},
539 {"pruning-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
540 NULL, cf_pruning_rule},
541 {"folder-reopen-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
542 NULL, cf_reopen_rule},
543 {"threading-display-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
544 NULL, cf_text_thread_disp_style},
545 {"threading-index-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
546 NULL, cf_text_thread_index_style},
547 {"threading-indicator-character", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
548 NULL, cf_text_thread_more_char},
549 {"threading-expanded-character", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
550 NULL, cf_text_thread_exp_char},
551 {"threading-lastreply-character", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
552 "Threading Last Reply Character", cf_text_thread_lastreply_char},
553 #ifndef _WINDOWS
554 {"display-character-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
555 NULL, cf_text_disp_char_set},
556 {"character-set", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
557 NULL, cf_text_old_char_set},
558 {"keyboard-character-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
559 NULL, cf_text_key_char_set},
560 #endif /* ! _WINDOWS */
561 {"posting-character-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
562 NULL, cf_text_post_character_set},
563 {"unknown-character-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
564 NULL, cf_text_unk_character_set},
565 {"editor", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
566 NULL, cf_text_editor},
567 {"speller", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
568 NULL, cf_text_speller},
569 #ifdef _WINDOWS
570 {"aspell-dictionary-list", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
571 "Aspell Dictionaries", cf_text_speller_dictionary},
572 #endif /* _WINDOWS */
573 {"composer-wrap-column", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
574 NULL, cf_text_fillcol},
575 {"reply-indent-string", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
576 NULL, cf_text_replystr},
577 {"reply-leadin", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
578 NULL, cf_text_replyintro},
579 {"quote-replace-string", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
580 NULL, cf_text_quotereplstr},
581 {"composer-word-separators", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
582 NULL, cf_text_wordsep},
583 {"empty-header-message", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
584 NULL, cf_text_emptyhdr},
585 {"image-viewer", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
586 NULL, cf_text_image_viewer},
587 {"use-only-domain-name", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
588 NULL, cf_text_use_only_domain_name},
589 {"bugs-fullname", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
590 NULL, cf_text_bugs_fullname},
591 {"bugs-address", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
592 NULL, cf_text_bugs_address},
593 {"bugs-additional-data", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
594 NULL, cf_text_bugs_extras},
595 {"suggest-fullname", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
596 NULL, cf_text_suggest_fullname},
597 {"suggest-address", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
598 NULL, cf_text_suggest_address},
599 {"local-fullname", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
600 NULL, cf_text_local_fullname},
601 {"local-address", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
602 NULL, cf_text_local_address},
603 {"forced-abook-entry", 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0,
604 NULL, cf_text_forced_abook},
605 {"kblock-passwd-count", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
606 NULL, cf_text_kblock_passwd},
607 {"display-filters", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
608 NULL, cf_text_in_fltr},
609 {"sending-filters", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
610 NULL, cf_text_out_fltr},
611 {"alt-addresses", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
612 "Alternate Addresses", cf_text_alt_addrs},
613 {"keywords", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
614 NULL, cf_text_keywords},
615 {"keyword-surrounding-chars", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
616 "Keyword Surrounding Characters", cf_text_kw_braces},
617 {"opening-text-separator-chars", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
618 "Opening Text Separator Characters", cf_text_opening_sep},
619 {"addressbook-formats", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
620 "Address Book Formats", cf_text_abook_formats},
621 {"index-format", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
622 NULL, cf_text_index_format},
623 {"viewer-overlap", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
624 NULL, cf_text_overlap},
625 {"scroll-margin", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
626 NULL, cf_text_margin},
627 {"status-message-delay", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
628 NULL, cf_text_stat_msg_delay},
629 {"busy-cue-rate", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
630 NULL, cf_text_busy_cue_rate},
631 {"mailcap-check-interval", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
632 NULL, cf_text_psleep},
633 {"mail-check-interval", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
634 NULL, cf_text_mailcheck},
635 {"mail-check-interval-noncurrent", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
636 NULL, cf_text_mailchecknoncurr},
637 {"maildrop-check-minimum", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
638 NULL, cf_text_maildropcheck},
639 {"nntp-range", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
640 "NNTP Range", cf_text_nntprange},
641 {"newsrc-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
642 NULL, cf_text_newsrc_path},
643 {"news-active-file-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
644 NULL, cf_text_news_active},
645 {"news-spool-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
646 NULL, cf_text_news_spooldir},
647 {"upload-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
648 NULL, cf_text_upload_cmd},
649 {"upload-command-prefix", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
650 NULL, cf_text_upload_prefix},
651 {"download-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
652 NULL, cf_text_download_cmd},
653 {"download-command-prefix", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
654 NULL, cf_text_download_prefix},
655 {"mailcap-search-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
656 NULL, cf_text_mailcap_path},
657 {"mimetype-search-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
658 NULL, cf_text_mimetype_path},
659 {"url-viewers", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
660 "URL-Viewers", cf_text_browser},
661 {"default-directories", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
662 "Extra Directories for Save", cf_text_history},
663 {"max-remote-connections", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
664 "Maximum Remote Connections", cf_text_maxremstreams},
665 {"stay-open-folders", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
666 "Stayopen Folders", cf_text_permlocked},
667 {"incoming-check-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
668 NULL, cf_text_inc_check_timeo},
669 {"incoming-check-interval", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
670 NULL, cf_text_inc_check_interval},
671 {"incoming-check-interval-secondary", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
672 NULL, cf_text_inc_second_check_interval},
673 {"incoming-check-list", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
674 NULL, cf_text_inc_check_list},
675 {"dead-letter-files", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
676 NULL, cf_text_deadlets},
677 #if !defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)
678 {"newmail-fifo-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
679 "NewMail FIFO Path", cf_text_newmail_fifo_path},
680 #endif
681 {"newmail-window-width", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
682 "NewMail Window Width", cf_text_nmw_width},
684 * Starting here, the variables are hidden in the Setup/Config screen.
685 * They are exposed if feature expose-hidden-config is set.
687 {"incoming-folders", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
688 NULL, cf_text_incoming_folders},
689 {"mail-directory", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
690 NULL, cf_text_mail_directory},
691 {"folder-collections", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
692 NULL, cf_text_folder_collections},
693 {"news-collections", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
694 NULL, cf_text_news_collections},
695 {"address-book", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
696 NULL, cf_text_address_book},
697 {"global-address-book", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
698 NULL, cf_text_global_address_book},
699 {"standard-printer", 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0,
700 NULL, cf_text_standard_printer},
701 {"last-time-prune-questioned", 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0,
702 NULL, cf_text_last_time_prune_quest},
703 {"last-version-used", 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0,
704 NULL, cf_text_last_version_used},
705 {"sendmail-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
706 NULL, cf_text_sendmail_path},
707 {"operating-dir", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
708 NULL, cf_text_oper_dir},
709 {"user-input-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
710 NULL, cf_text_user_input_timeo},
711 /* OBSOLETE */
712 #ifdef DEBUGJOURNAL
713 {"debug-memory", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
714 NULL, cf_text_debug_mem},
715 #endif
716 {"tcp-open-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
717 "TCP Open Timeout", cf_text_tcp_open_timeo},
718 {"tcp-read-warning-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
719 "TCP Read Warning Timeout", cf_text_tcp_read_timeo},
720 {"tcp-write-warning-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
721 "TCP Write Warning Timeout", cf_text_tcp_write_timeo},
722 {"tcp-query-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
723 "TCP Query Timeout", cf_text_tcp_query_timeo},
724 {"rsh-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
725 NULL, cf_text_rsh_command},
726 {"rsh-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
727 NULL, cf_text_rsh_path},
728 {"rsh-open-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
729 NULL, cf_text_rsh_open_timeo},
730 {"ssh-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
731 NULL, cf_text_ssh_command},
732 {"ssh-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
733 NULL, cf_text_ssh_path},
734 {"ssh-open-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
735 NULL, cf_text_ssh_open_timeo},
736 {"new-version-threshold", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
737 NULL, cf_text_version_threshold},
738 {"disable-these-drivers", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
739 NULL, cf_text_disable_drivers},
740 {"disable-these-authenticators", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
741 NULL, cf_text_disable_auths},
742 {"remote-abook-metafile", 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0,
743 NULL, cf_text_remote_abook_metafile},
744 {"remote-abook-history", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
745 NULL, cf_text_remote_abook_history},
746 {"remote-abook-validity", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
747 NULL, cf_text_remote_abook_validity},
748 {"printer", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
749 NULL, cf_text_printer},
750 {"personal-print-command", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
751 NULL, cf_text_personal_print_command},
752 {"personal-print-category", 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0,
753 NULL, cf_text_personal_print_cat},
754 {"patterns", 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
755 NULL, cf_text_old_patterns},
756 {"patterns-roles", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
757 NULL, cf_text_patterns},
758 {"patterns-filters2", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
759 "Patterns Filters", cf_text_patterns},
760 {"patterns-filters", 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
761 NULL, cf_text_old_filters},
762 {"patterns-scores2", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
763 "Patterns Scores", cf_text_patterns},
764 {"patterns-scores", 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
765 NULL, cf_text_old_scores},
766 {"patterns-indexcolors", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
767 NULL, cf_text_patterns},
768 {"patterns-other", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
769 NULL, cf_text_patterns},
770 {"patterns-search", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
771 NULL, cf_text_patterns},
772 /* OBSOLETE VARS */
773 {"elm-style-save", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
774 NULL, cf_text_elm_style_save},
775 {"header-in-reply", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
776 NULL, cf_text_header_in_reply},
777 {"feature-level", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
778 NULL, cf_text_feature_level},
779 {"old-style-reply", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
780 NULL, cf_text_old_style_reply},
781 {"compose-mime", 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
782 NULL, cf_text_compose_mime},
783 {"show-all-characters", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
784 NULL, cf_text_show_all_characters},
785 {"save-by-sender", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
786 NULL, cf_text_save_by_sender},
787 #if defined(DOS) || defined(OS2)
788 {"file-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
789 NULL, cf_text_file_dir},
790 {"folder-extension", 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0,
791 NULL, cf_text_folder_extension},
792 #endif
793 #ifndef _WINDOWS
794 {"color-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
795 NULL, cf_text_color_style},
796 #endif
797 {"current-indexline-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
798 NULL, cf_text_current_indexline_style},
799 {"titlebar-color-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
800 NULL, cf_text_titlebar_color_style},
801 {"normal-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
802 NULL, cf_text_normal_foreground_color},
803 {"normal-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
804 {"reverse-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
805 {"reverse-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
806 {"title-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
807 {"title-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
808 {"title-closed-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
809 {"title-closed-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
810 {"folder-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
811 {"folder-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
812 {"directory-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
813 {"directory-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
814 {"folder-list-text-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
815 {"folder-list-text-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
816 {"status-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
817 {"status-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
818 {"keylabel-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
819 {"keylabel-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
820 {"keyname-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
821 {"keyname-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
822 {"selectable-item-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
823 {"selectable-item-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
824 {"meta-message-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
825 {"meta-message-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
826 {"quote1-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
827 {"quote1-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
828 {"quote2-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
829 {"quote2-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
830 {"quote3-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
831 {"quote3-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
832 {"incoming-unseen-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
833 {"incoming-unseen-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
834 {"signature-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
835 {"signature-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
836 {"prompt-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
837 {"prompt-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
838 {"header-general-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
839 {"header-general-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
840 {"index-to-me-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
841 {"index-to-me-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
842 {"index-important-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
843 {"index-important-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
844 {"index-deleted-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
845 {"index-deleted-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
846 {"index-answered-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
847 {"index-answered-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
848 {"index-new-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
849 {"index-new-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
850 {"index-recent-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
851 {"index-recent-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
852 {"index-forward-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
853 {"index-forward-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
854 {"index-unseen-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
855 {"index-unseen-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
856 {"index-highpriority-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
857 {"index-highpriority-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
858 {"index-lowpriority-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
859 {"index-lowpriority-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
860 {"index-arrow-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
861 {"index-arrow-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
862 {"index-subject-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
863 {"index-subject-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
864 {"index-from-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
865 {"index-from-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
866 {"index-opening-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
867 {"index-opening-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
868 {"index-token-colors", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
869 NULL, cf_text_index_token_color},
870 {"viewer-hdr-colors", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
871 "Viewer Header Colors", cf_text_view_hdr_color},
872 {"keyword-colors", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
873 NULL, cf_text_kw_colors},
874 #ifdef _WINDOWS
875 {"font-name", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
876 NULL, "name and size of font."},
877 {"font-size", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
878 {"font-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
879 {"font-char-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
880 {"print-font-name", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
881 NULL, "name and size of printer font."},
882 {"print-font-size", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
883 {"print-font-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
884 {"print-font-char-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
885 {"window-position", 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0,
886 NULL, cf_text_window_position},
887 {"cursor-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
888 #endif /* _WINDOWS */
889 #ifdef SMIME
890 {"smime-public-cert-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
891 "S/MIME - Public Cert Directory", cf_text_publiccertdir},
892 {"smime-public-cert-container", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
893 "S/MIME - Public Cert Container", cf_text_publiccertcontainer},
894 {"smime-private-key-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
895 "S/MIME - Private Key Directory", cf_text_privatekeydir},
896 {"smime-private-key-container", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
897 "S/MIME - Private Key Container", cf_text_privatekeycontainer},
898 {"smime-cacert-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
899 "S/MIME - Cert Authority Directory", cf_text_cacertdir},
900 {"smime-cacert-container", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
901 "S/MIME - Cert Authority Container", cf_text_cacertcontainer},
902 #endif /* SMIME */
903 #ifdef ENABLE_LDAP
904 {"ldap-servers", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
905 "LDAP Servers", cf_text_ldap_server},
906 #endif /* ENABLE_LDAP */
907 {"rss-news", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
908 "WEB ALPINE - RSS News", cf_text_rss_news},
909 {"rss-weather", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
910 "WEB ALPINE - RSS Weather", cf_text_rss_weather},
911 {"wp-indexheight", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
912 "WEB ALPINE - Index Height", cf_text_wp_indexheight},
913 {"wp-indexlines", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
914 "WEB ALPINE - Index Lines", cf_text_wp_indexlines},
915 {"wp-aggstate", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
916 "WEB ALPINE - Aggregate State", cf_text_wp_aggstate},
917 {"wp-state", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
918 "WEB ALPINE - Cross Session State", cf_text_wp_state},
919 {"wp-columns", 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0,
920 "WEB ALPINE - Columns", cf_text_wp_columns},
921 {NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL,NULL}
925 struct variable *
926 var_from_name(char *name)
928 struct variable *v;
929 int i;
931 if(!(name && name[0]))
932 return(NULL);
934 for(i = 0; (v = &variables[i]) && v->name; i++)
935 if(!strucmp(v->name,name))
936 return(v);
938 return(NULL);
942 void
943 init_init_vars(struct pine *ps)
945 ps->vars = variables;
949 #define DSIZE (25000)
950 /* this is just like dprint except it prints to a char * */
951 #ifdef DEBUG
952 #define mprint(n,x) { \
953 if(debug >= (n)){ \
954 snprintf x ; \
955 db += strlen(db); \
958 #else
959 #define mprint(n,x)
960 #endif
963 * this was split out from init_vars so we can get at the
964 * pinerc location sooner.
966 void
967 init_pinerc(struct pine *ps, char **debug_out)
969 char buf[MAXPATH+1], *p, *db;
970 #if defined(DOS) || defined(OS2)
971 char buf2[MAXPATH+1], l_pinerc[MAXPATH+1];
972 int nopinerc = 0, confregset = -1;
973 register struct variable *vars = ps->vars;
974 #endif
976 #ifdef DEBUG
978 * Since this routine is called before we've had a chance to set up
979 * the debug file for output, we put the debugging into memory and
980 * pass it back to the caller for use after init_debug(). We just
981 * allocate plenty of space.
983 if(debug_out){
984 db = *debug_out = (char *)fs_get(DSIZE * sizeof(char));
985 db[0] = '\0';
987 #endif
989 mprint(2, (db, DSIZE-(db-(*debug_out)), "\n -- init_pinerc --\n\n"));
991 #if defined(DOS) || defined(OS2)
993 * Rules for the config/support file locations under DOS are:
995 * 1) The location of the PINERC is searched for in the following
996 * order of precedence:
997 * - File pointed to by '-p' command line option
998 * - File pointed to by PINERC environment variable
999 * - $HOME\pine
1000 * - same dir as argv[0]
1002 * 2) The HOME environment variable, if not set, defaults to
1003 * root of the current working drive (see alpine.c)
1005 * 3) The default for external files (PINE.SIG and ADDRBOOK) is the
1006 * same directory as the pinerc
1008 * 4) The support files (PINE.HLP and PINE.NDX) are expected to be in
1009 * the same directory as PINE.EXE.
1012 if(ps->prc){
1013 mprint(2, (db, DSIZE-(db-(*debug_out)),
1014 "Personal config \"%.100s\" comes from command line\n",
1015 (ps->prc && ps->prc->name) ? ps->prc->name : "<no name>"));
1017 else{
1018 mprint(2, (db, DSIZE-(db-(*debug_out)),
1019 "Personal config not set on cmdline, checking for $PINERC\n"));
1023 * First, if prc hasn't been set by a command-line -p, check to see
1024 * if PINERC is in the environment. If so, treat it just like we
1025 * would have treated it if it were a command-line arg.
1027 if(!ps->prc && (p = getenv("PINERC")) && *p){
1028 char path[MAXPATH], dir[MAXPATH];
1030 if(IS_REMOTE(p) || is_absolute_path(p)){
1031 strncpy(path, p, sizeof(path)-1);
1032 path[sizeof(path)-1] = '\0';
1034 else{
1035 getcwd(dir, sizeof(dir));
1036 build_path(path, dir, p, sizeof(path));
1039 if(!IS_REMOTE(p))
1040 ps->pinerc = cpystr(path);
1042 ps->prc = new_pinerc_s(path);
1044 if(ps->prc){
1045 mprint(2, (db, DSIZE-(db-(*debug_out)),
1046 " yes, personal config \"%.100s\" comes from $PINERC\n",
1047 (ps->prc && ps->prc->name) ? ps->prc->name : "<no name>"));
1052 * Pinerc used to be the name of the pinerc file. Then we added
1053 * the possibility of the pinerc file being remote, and we replaced
1054 * the variable pinerc with the structure prc. Unfortunately, some
1055 * parts of pine rely on the fact that pinerc is the name of the
1056 * pinerc _file_, and use the directory that the pinerc file is located
1057 * in for their own purposes. We want to preserve that so things will
1058 * keep working. So, even if the real pinerc is remote, we need to
1059 * put the name of a pinerc file in the pinerc variable so that the
1060 * directory which contains that file is writable. The file itself
1061 * doesn't have to exist for this purpose, since we are really only
1062 * using the name of the directory containing the file. Twisted.
1063 * (Alternatively, we could fix all of the code that uses the pinerc
1064 * variable for this purpose to use a new variable which really is
1065 * just a directory.) hubert 2000-sep
1067 * There are 3 cases. If pinerc is already set that means that the user
1068 * gave either a -p pinerc or an environment pinerc that is a local file,
1069 * and we are done. If pinerc is not set, then either prc is set or not.
1070 * If prc is set then the -p arg or PINERC value is a remote pinerc.
1071 * In that case we need to find a local directory to use, and put that
1072 * directory in the pinerc variable (with a fake filename tagged on).
1073 * If prc is not set, then user hasn't told us anything so we have to
1074 * try to find the default pinerc file by looking down the path of
1075 * possibilities. When we find it, we'll also use that directory.
1077 if(!ps->pinerc){
1078 *l_pinerc = '\0';
1079 *buf = '\0';
1081 if(ps->prc){ /* remote pinerc case */
1083 * We don't give them an l_pinerc unless they tell us where
1084 * to put it.
1086 if(ps->aux_files_dir)
1087 build_path(l_pinerc, ps->aux_files_dir, SYSTEM_PINERC,
1088 sizeof(l_pinerc));
1089 else{
1091 * Search for a writable directory.
1092 * Mimic what happens in !prc for local case, except we
1093 * don't need to look for the actual file.
1096 /* check if $HOME\PINE is writable */
1097 build_path(buf2, ps->home_dir, DF_PINEDIR, sizeof(buf2));
1098 if(is_writable_dir(buf2) == 0)
1099 build_path(l_pinerc, buf2, SYSTEM_PINERC, sizeof(l_pinerc));
1100 else{ /* $HOME\PINE not a writable dir */
1101 /* use this unless registry redirects us */
1102 build_path(l_pinerc, ps->pine_dir, SYSTEM_PINERC,
1103 sizeof(l_pinerc));
1104 #ifdef _WINDOWS
1105 /* if in registry, use that value */
1106 if(mswin_reg(MSWR_OP_GET, MSWR_PINE_RC, buf2, sizeof(buf2))
1107 && !IS_REMOTE(buf2)){
1108 strncpy(l_pinerc, buf2, sizeof(l_pinerc)-1);
1109 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1111 #endif
1115 else{ /* searching for pinerc file to use */
1117 * Buf2 is $HOME\PINE. If $HOME is not explicitly set,
1118 * it defaults to the current working drive (often C:).
1119 * See alpine.c to see how it is initially set.
1122 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, searching...\n"));
1123 build_path(buf2, ps->home_dir, DF_PINEDIR, sizeof(buf2));
1124 mprint(2, (db, DSIZE-(db-(*debug_out)),
1125 " checking for writable %.100s dir \"%.100s\" off of homedir\n",
1126 DF_PINEDIR, buf2));
1127 if(is_writable_dir(buf2) == 0){
1129 * $HOME\PINE exists and is writable.
1130 * See if $HOME\PINE\PINERC exists.
1132 build_path(buf, buf2, SYSTEM_PINERC, sizeof(buf));
1133 strncpy(l_pinerc, buf, sizeof(l_pinerc)-1);
1134 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1135 mprint(2, (db, DSIZE-(db-(*debug_out)), " yes, now checking for file \"%.100s\"\n",
1136 buf));
1137 if(can_access(buf, ACCESS_EXISTS) == 0){ /* found it! */
1139 * Buf is what we were looking for.
1140 * It is local and can be used for the directory, too.
1142 mprint(2, (db, DSIZE-(db-(*debug_out)), " found it\n"));
1144 else{
1146 * No $HOME\PINE\PINERC, look for
1147 * one in same dir as PINE.EXE.
1149 build_path(buf2, ps->pine_dir, SYSTEM_PINERC,
1150 sizeof(buf2));
1151 mprint(2, (db, DSIZE-(db-(*debug_out)),
1152 " no, checking for \"%.100s\" in pine.exe dir\n",
1153 buf2));
1154 if(can_access(buf2, ACCESS_EXISTS) == 0){
1155 /* found it! */
1156 mprint(2, (db, DSIZE-(db-(*debug_out)), " found it\n"));
1157 strncpy(buf, buf2, sizeof(buf)-1);
1158 buf[sizeof(buf)-1] = '\0';
1159 strncpy(l_pinerc, buf2, sizeof(l_pinerc)-1);
1160 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1162 else{
1163 #ifdef _WINDOWS
1164 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, checking in registry\n"));
1165 if(mswin_reg(MSWR_OP_GET, MSWR_PINE_RC,
1166 buf2, sizeof(buf2))){
1167 strncpy(buf, buf2, sizeof(buf)-1);
1168 buf[sizeof(buf)-1] = '\0';
1169 if(!IS_REMOTE(buf2)){
1170 strncpy(l_pinerc, buf2, sizeof(l_pinerc)-1);
1171 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1174 * Now buf is the pinerc to be used, l_pinerc is
1175 * the directory, which may be either same as buf
1176 * or it may be $HOME\PINE if registry gives us
1177 * a remote pinerc.
1179 mprint(2, (db, DSIZE-(db-(*debug_out)), " found \"%.100s\" in registry\n",
1180 buf));
1182 else{
1183 nopinerc = 1;
1184 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found, asking user\n"));
1186 #else
1187 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found\n"));
1188 #endif
1193 * Buf is the pinerc (could be remote if from registry)
1194 * and l_pinerc is the local pinerc, which may not exist.
1197 else{ /* $HOME\PINE not a writable dir */
1199 * We notice that the order of checking in the registry
1200 * and checking in the ALPINE.EXE directory are different
1201 * in this case versus the is_writable_dir(buf2) case, and
1202 * that does sort of look like a bug. However,
1203 * we don't think this is a bug since we did it on purpose
1204 * a long time ago. So even though we can't remember why
1205 * it is this way, we think we would rediscover why if we
1206 * changed it! So we won't change it.
1210 * Change the default to use to the ALPINE.EXE directory.
1212 build_path(buf, ps->pine_dir, SYSTEM_PINERC, sizeof(buf));
1213 strncpy(l_pinerc, buf, sizeof(l_pinerc)-1);
1214 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1215 #ifdef _WINDOWS
1216 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, not writable, checking in registry\n"));
1217 /* if in registry, use that value */
1218 if(mswin_reg(MSWR_OP_GET, MSWR_PINE_RC, buf2, sizeof(buf2))){
1219 strncpy(buf, buf2, sizeof(buf)-1);
1220 buf[sizeof(buf)-1] = '\0';
1221 mprint(2, (db, DSIZE-(db-(*debug_out)), " found \"%.100s\" in registry\n",
1222 buf));
1223 if(!IS_REMOTE(buf)){
1224 strncpy(l_pinerc, buf, sizeof(l_pinerc)-1);
1225 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1228 else{
1229 mprint(2, (db, DSIZE-(db-(*debug_out)),
1230 " no, checking for \"%.100s\" in alpine.exe dir\n",
1231 buf));
1233 if(can_access(buf, ACCESS_EXISTS) == 0){
1234 mprint(2, (db, DSIZE-(db-(*debug_out)), " found it\n"));
1236 else{
1237 nopinerc = 1;
1238 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found, asking user\n"));
1241 #else
1242 mprint(2, (db, DSIZE-(db-(*debug_out)),
1243 " no, checking for \"%.100s\" in alpine.exe dir\n",
1244 buf));
1246 if(can_access(buf, ACCESS_EXISTS) == 0){
1247 mprint(2, (db, DSIZE-(db-(*debug_out)), " found it\n"));
1249 else{
1250 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found, creating it\n"));
1252 #endif
1256 * When we get here we have buf set to the name of the
1257 * pinerc, which could be local or remote. We have l_pinerc
1258 * set to the same as buf if buf is local, and set to another
1259 * name otherwise, hopefully contained in a writable directory.
1261 #ifdef _WINDOWS
1262 if(nopinerc || ps_global->install_flag){
1263 char buf3[MAXPATH+1];
1265 confregset = 0;
1266 strncpy(buf3, buf, MAXPATH);
1267 buf3[MAXPATH] = '\0';
1268 if(os_config_dialog(buf3, MAXPATH,
1269 &confregset, nopinerc) == 0){
1270 strncpy(buf, buf3, MAXPATH);
1271 buf[MAXPATH] = '\0';
1272 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found, creating it\n"));
1273 mprint(2, (db, DSIZE-(db-(*debug_out)), " user says use \"%.100s\"\n", buf));
1274 if(!IS_REMOTE(buf)){
1275 strncpy(l_pinerc, buf, MAXPATH);
1276 l_pinerc[MAXPATH] = '\0';
1279 else{
1280 exit(-1);
1283 #endif
1284 ps->prc = new_pinerc_s(buf);
1287 ps->pinerc = cpystr(l_pinerc);
1290 #if defined(DOS) || defined(OS2)
1292 * The goal here is to set the auxiliary directory in the pinerc variable.
1293 * We are making the assumption that any reference to the pinerc variable
1294 * after this point is used only as a directory in which to store things,
1295 * with the prc variable being the preferred place to store pinerc location.
1296 * If -aux isn't set, then there is no change. -jpf 08/2001
1298 if(ps->aux_files_dir){
1299 l_pinerc[0] = '\0';
1300 build_path(l_pinerc, ps->aux_files_dir, SYSTEM_PINERC,
1301 sizeof(l_pinerc));
1302 if(ps->pinerc) fs_give((void **)&ps->pinerc);
1303 ps->pinerc = cpystr(l_pinerc);
1304 mprint(2, (db, DSIZE-(db-(*debug_out)), "Setting aux_files_dir to \"%.100s\"\n",
1305 ps->aux_files_dir));
1307 #endif
1309 #ifdef _WINDOWS
1310 if(confregset && (ps->update_registry != UREG_NEVER_SET))
1311 mswin_reg(MSWR_OP_SET | ((ps->update_registry == UREG_ALWAYS_SET)
1312 || confregset == 1 ? MSWR_OP_FORCE : 0),
1313 MSWR_PINE_RC,
1314 (ps->prc && ps->prc->name) ?
1315 ps->prc->name : ps->pinerc, (size_t)NULL);
1316 #endif
1319 * Now that we know the default for the PINERC, build NEWSRC default.
1320 * Backward compatibility makes this kind of funky. If what the
1321 * c-client thinks the NEWSRC should be exists *AND* it doesn't
1322 * already exist in the PINERC's dir, use c-client's default, otherwise
1323 * use the one next to the PINERC...
1325 p = last_cmpnt(ps->pinerc);
1326 buf[0] = '\0';
1327 if(p != NULL){
1328 strncpy(buf, ps->pinerc, MIN(p - ps->pinerc, sizeof(buf)-1));
1329 buf[MIN(p - ps->pinerc, sizeof(buf)-1)] = '\0';
1332 mprint(2, (db, DSIZE-(db-(*debug_out)), "Using directory \"%.100s\" for auxiliary files\n", buf));
1333 strncat(buf, "NEWSRC", sizeof(buf)-1-strlen(buf));
1335 if(!(p = (void *) mail_parameters(NULL, GET_NEWSRC, (void *)NULL))
1336 || can_access(p, ACCESS_EXISTS) < 0
1337 || can_access(buf, ACCESS_EXISTS) == 0){
1338 mail_parameters(NULL, SET_NEWSRC, (void *)buf);
1339 GLO_NEWSRC_PATH = cpystr(buf);
1341 else
1342 GLO_NEWSRC_PATH = cpystr(p);
1344 if(ps->pconf){
1345 mprint(2, (db, DSIZE-(db-(*debug_out)), "Global config \"%.100s\" comes from command line\n",
1346 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1348 else{
1349 mprint(2, (db, DSIZE-(db-(*debug_out)),
1350 "Global config not set on cmdline, checking for $PINECONF\n"));
1353 if(!ps->pconf && (p = getenv("PINECONF"))){
1354 ps->pconf = new_pinerc_s(p);
1355 if(ps->pconf){
1356 mprint(2, (db, DSIZE-(db-(*debug_out)),
1357 " yes, global config \"%.100s\" comes from $PINECONF\n",
1358 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1361 #ifdef _WINDOWS
1362 else if(!ps->pconf
1363 && mswin_reg(MSWR_OP_GET, MSWR_PINE_CONF, buf2, sizeof(buf2))){
1364 ps->pconf = new_pinerc_s(buf2);
1365 if(ps->pconf){
1366 mprint(2, (db, DSIZE-(db-(*debug_out)),
1367 " yes, global config \"%.100s\" comes from Registry\n",
1368 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1371 #endif
1372 if(!ps->pconf){
1373 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, there is no global config\n"));
1375 #ifdef _WINDOWS
1376 else if (ps->pconf && ps->pconf->name &&
1377 (ps->update_registry != UREG_NEVER_SET)){
1378 mswin_reg(MSWR_OP_SET | ((ps->update_registry == UREG_ALWAYS_SET)
1379 ? MSWR_OP_FORCE : 0),
1380 MSWR_PINE_CONF,
1381 ps->pconf->name, (size_t)NULL);
1383 #endif
1385 if(!ps->prc)
1386 ps->prc = new_pinerc_s(ps->pinerc);
1388 if(ps->exceptions){
1389 mprint(2, (db, DSIZE-(db-(*debug_out)),
1390 "Exceptions config \"%.100s\" comes from command line\n",
1391 ps->exceptions));
1393 else{
1394 mprint(2, (db, DSIZE-(db-(*debug_out)),
1395 "Exceptions config not set on cmdline, checking for $PINERCEX\n"));
1399 * Exceptions is done slightly differently from pinerc. Instead of setting
1400 * post_prc in args.c we just set the string and use it here. We do
1401 * that so that we can put it in the same directory as the pinerc if
1402 * exceptions is a relative name, and pinerc may not be set until here.
1404 * First, just like for pinerc, check environment variable if it wasn't
1405 * set on the command line.
1407 if(!ps->exceptions && (p = getenv("PINERCEX")) && *p){
1408 ps->exceptions = cpystr(p);
1409 if(ps->exceptions){
1410 mprint(2, (db, DSIZE-(db-(*debug_out)),
1411 " yes, exceptions config \"%.100s\" comes from $PINERCEX\n",
1412 ps->exceptions));
1417 * If still not set, try specific file in same dir as pinerc.
1418 * Only use it if the file exists.
1420 if(!ps->exceptions){
1421 p = last_cmpnt(ps->pinerc);
1422 buf[0] = '\0';
1423 if(p != NULL){
1424 strncpy(buf, ps->pinerc, MIN(p - ps->pinerc, sizeof(buf)-1));
1425 buf[MIN(p - ps->pinerc, sizeof(buf)-1)] = '\0';
1428 strncat(buf, "PINERCEX", sizeof(buf)-1-strlen(buf));
1430 mprint(2, (db, DSIZE-(db-(*debug_out)),
1431 " no, checking for default \"%.100s\" in pinerc dir\n", buf));
1432 if(can_access(buf, ACCESS_EXISTS) == 0) /* found it! */
1433 ps->exceptions = cpystr(buf);
1435 if(ps->exceptions){
1436 mprint(2, (db, DSIZE-(db-(*debug_out)),
1437 " yes, exceptions config \"%.100s\" comes from default\n",
1438 ps->exceptions));
1440 else{
1441 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, there is no exceptions config\n"));
1445 #else /* unix */
1447 if(ps->pconf){
1448 mprint(2, (db, DSIZE-(db-(*debug_out)), "Global config \"%.100s\" comes from command line\n",
1449 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1452 if(!ps->pconf){
1453 ps->pconf = new_pinerc_s(SYSTEM_PINERC);
1454 if(ps->pconf){
1455 mprint(2, (db, DSIZE-(db-(*debug_out)), "Global config \"%.100s\" is default\n",
1456 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1460 if(!ps->pconf){
1461 mprint(2, (db, DSIZE-(db-(*debug_out)), "No global config!\n"));
1464 if(ps->prc){
1465 mprint(2, (db, DSIZE-(db-(*debug_out)), "Personal config \"%.100s\" comes from command line\n",
1466 (ps->prc && ps->prc->name) ? ps->prc->name : "<no name>"));
1469 if(!ps->pinerc){
1470 build_path(buf, ps->home_dir, ".pinerc", sizeof(buf));
1471 ps->pinerc = cpystr(buf);
1474 if(!ps->prc){
1475 ps->prc = new_pinerc_s(ps->pinerc);
1476 if(ps->prc){
1477 mprint(2, (db, DSIZE-(db-(*debug_out)), "Personal config \"%.100s\" is default\n",
1478 (ps->prc && ps->prc->name) ? ps->prc->name : "<no name>"));
1482 if(!ps->prc){
1483 mprint(2, (db, DSIZE-(db-(*debug_out)), "No personal config!\n"));
1486 if(ps->exceptions){
1487 mprint(2, (db, DSIZE-(db-(*debug_out)),
1488 "Exceptions config \"%.100s\" comes from command line\n",
1489 ps->exceptions));
1493 * If not set, try specific file in same dir as pinerc.
1494 * Only use it if the file exists.
1496 if(!ps->exceptions){
1497 p = last_cmpnt(ps->pinerc);
1498 buf[0] = '\0';
1499 if(p != NULL){
1500 strncpy(buf, ps->pinerc, MIN(p - ps->pinerc, sizeof(buf)-1));
1501 buf[MIN(p - ps->pinerc, sizeof(buf)-1)] = '\0';
1504 strncat(buf, ".pinercex", sizeof(buf)-1-strlen(buf));
1505 mprint(2, (db, DSIZE-(db-(*debug_out)), "Exceptions config not set on cmdline\n checking for default \"%.100s\" in pinerc dir\n", buf));
1507 if(can_access(buf, ACCESS_EXISTS) == 0) /* found it! */
1508 ps->exceptions = cpystr(buf);
1510 if(ps->exceptions){
1511 mprint(2, (db, DSIZE-(db-(*debug_out)),
1512 " yes, exceptions config \"%.100s\" is default\n",
1513 ps->exceptions));
1515 else{
1516 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, there is no exceptions config\n"));
1520 #endif /* unix */
1522 if(ps->exceptions){
1524 if(!IS_REMOTE(ps->exceptions) &&
1525 !is_absolute_path(ps->exceptions)){
1526 #if defined(DOS) || defined(OS2)
1527 p = last_cmpnt(ps->pinerc);
1528 buf[0] = '\0';
1529 if(p != NULL){
1530 strncpy(buf, ps->pinerc, MIN(p - ps->pinerc, sizeof(buf)-1));
1531 buf[MIN(p - ps->pinerc, sizeof(buf)-1)] = '\0';
1534 strncat(buf, ps->exceptions, sizeof(buf)-1-strlen(buf));
1535 #else
1536 build_path(buf, ps->home_dir, ps->exceptions, sizeof(buf));
1537 #endif
1539 else{
1540 strncpy(buf, ps->exceptions, sizeof(buf)-1);
1541 buf[sizeof(buf)-1] = '\0';
1544 ps->post_prc = new_pinerc_s(buf);
1546 fs_give((void **)&ps->exceptions);
1549 mprint(2, (db, DSIZE-(db-(*debug_out)), "\n Global config: %.100s\n",
1550 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<none>"));
1551 mprint(2, (db, DSIZE-(db-(*debug_out)), " Personal config: %.100s\n",
1552 (ps->prc && ps->prc->name) ? ps->prc->name : "<none>"));
1553 mprint(2, (db, DSIZE-(db-(*debug_out)), " Exceptions config: %.100s\n",
1554 (ps->post_prc && ps->post_prc->name) ? ps->post_prc->name
1555 : "<none>"));
1556 #if !defined(DOS) && !defined(OS2)
1557 if(SYSTEM_PINERC_FIXED){
1558 mprint(2, (db, DSIZE-(db-(*debug_out)), " Fixed config: %.100s\n", SYSTEM_PINERC_FIXED));
1560 #endif
1562 mprint(2, (db, DSIZE-(db-(*debug_out)), "\n"));
1566 /*----------------------------------------------------------------------
1567 Initialize the variables
1569 Args: ps -- The usual pine structure
1571 Result:
1573 This reads the system pine configuration file and the user's pine
1574 configuration file ".pinerc" and places the results in the variables
1575 structure. It sorts out what was read and sets a few other variables
1576 based on the contents.
1577 ----*/
1578 void
1579 init_vars(struct pine *ps, void (*cmds_f) (struct pine *, char **))
1581 char buf[MAXPATH+1], *p, *q, **s;
1582 register struct variable *vars = ps->vars;
1583 int obs_header_in_reply = 0, /* the obs_ variables are to */
1584 obs_old_style_reply = 0, /* support backwards compatibility */
1585 obs_save_by_sender, i, def_sort_rev;
1586 long rvl;
1587 PINERC_S *fixedprc = NULL;
1588 FeatureLevel obs_feature_level;
1589 char *fromcharset = NULL;
1590 char *err = NULL;
1592 dprint((5, "init_vars:\n"));
1594 /*--- The defaults here are defined in os-xxx.h so they can vary
1595 per machine ---*/
1597 GLO_PRINTER = cpystr(DF_DEFAULT_PRINTER);
1598 GLO_ELM_STYLE_SAVE = cpystr(DF_ELM_STYLE_SAVE);
1599 GLO_SAVE_BY_SENDER = cpystr(DF_SAVE_BY_SENDER);
1600 GLO_HEADER_IN_REPLY = cpystr(DF_HEADER_IN_REPLY);
1601 GLO_INBOX_PATH = cpystr("inbox");
1602 GLO_DEFAULT_FCC = cpystr(DF_DEFAULT_FCC);
1603 GLO_DEFAULT_SAVE_FOLDER = cpystr(DEFAULT_SAVE);
1604 GLO_POSTPONED_FOLDER = cpystr(POSTPONED_MSGS);
1605 GLO_TRASH_FOLDER = cpystr(TRASH_FOLDER);
1606 GLO_USE_ONLY_DOMAIN_NAME = cpystr(DF_USE_ONLY_DOMAIN_NAME);
1607 GLO_FEATURE_LEVEL = cpystr("sappling");
1608 GLO_OLD_STYLE_REPLY = cpystr(DF_OLD_STYLE_REPLY);
1609 GLO_SORT_KEY = cpystr(DF_SORT_KEY);
1610 GLO_SAVED_MSG_NAME_RULE = cpystr(DF_SAVED_MSG_NAME_RULE);
1611 GLO_FCC_RULE = cpystr(DF_FCC_RULE);
1612 GLO_AB_SORT_RULE = cpystr(DF_AB_SORT_RULE);
1613 GLO_FLD_SORT_RULE = cpystr(DF_FLD_SORT_RULE);
1614 GLO_SIGNATURE_FILE = cpystr(DF_SIGNATURE_FILE);
1615 GLO_MAIL_DIRECTORY = cpystr(DF_MAIL_DIRECTORY);
1616 GLO_REMOTE_ABOOK_HISTORY = cpystr(DF_REMOTE_ABOOK_HISTORY);
1617 GLO_REMOTE_ABOOK_VALIDITY = cpystr(DF_REMOTE_ABOOK_VALIDITY);
1618 GLO_GOTO_DEFAULT_RULE = cpystr(DF_GOTO_DEFAULT_RULE);
1619 GLO_INCOMING_STARTUP = cpystr(DF_INCOMING_STARTUP);
1620 GLO_PRUNING_RULE = cpystr(DF_PRUNING_RULE);
1621 GLO_REOPEN_RULE = cpystr(DF_REOPEN_RULE);
1622 GLO_THREAD_DISP_STYLE = cpystr(DF_THREAD_DISP_STYLE);
1623 GLO_THREAD_INDEX_STYLE = cpystr(DF_THREAD_INDEX_STYLE);
1624 GLO_THREAD_MORE_CHAR = cpystr(DF_THREAD_MORE_CHAR);
1625 GLO_THREAD_EXP_CHAR = cpystr(DF_THREAD_EXP_CHAR);
1626 GLO_THREAD_LASTREPLY_CHAR = cpystr(DF_THREAD_LASTREPLY_CHAR);
1627 GLO_BUGS_FULLNAME = cpystr("Sorry No Address");
1628 GLO_BUGS_ADDRESS = cpystr("nobody");
1629 GLO_SUGGEST_FULLNAME = cpystr("Sorry No Address");
1630 GLO_SUGGEST_ADDRESS = cpystr("nobody");
1631 GLO_LOCAL_FULLNAME = cpystr(DF_LOCAL_FULLNAME);
1632 GLO_LOCAL_ADDRESS = cpystr(DF_LOCAL_ADDRESS);
1633 GLO_OVERLAP = cpystr(DF_OVERLAP);
1634 GLO_SLEEP = cpystr("60");
1635 GLO_MAXREMSTREAM = cpystr(DF_MAXREMSTREAM);
1636 GLO_MARGIN = cpystr(DF_MARGIN);
1637 GLO_FILLCOL = cpystr(DF_FILLCOL);
1638 GLO_DEADLETS = cpystr(DF_DEADLETS);
1639 GLO_NMW_WIDTH = cpystr(DF_NMW_WIDTH);
1640 GLO_REPLY_STRING = cpystr("> ");
1641 GLO_REPLY_INTRO = cpystr(DEFAULT_REPLY_INTRO);
1642 GLO_EMPTY_HDR_MSG = cpystr("undisclosed-recipients");
1643 GLO_STATUS_MSG_DELAY = cpystr("0");
1644 GLO_ACTIVE_MSG_INTERVAL = cpystr("12");
1645 GLO_USERINPUTTIMEO = cpystr("0");
1646 GLO_INCCHECKTIMEO = cpystr("5");
1647 GLO_INCCHECKINTERVAL = cpystr("180");
1648 GLO_INC2NDCHECKINTERVAL = cpystr("180");
1649 GLO_MAILCHECK = cpystr(DF_MAILCHECK);
1650 GLO_MAILCHECKNONCURR = cpystr("0");
1651 GLO_MAILDROPCHECK = cpystr(DF_MAILDROPCHECK);
1652 GLO_NNTPRANGE = cpystr("0");
1653 GLO_KBLOCK_PASSWD_COUNT = cpystr(DF_KBLOCK_PASSWD_COUNT);
1654 GLO_INDEX_COLOR_STYLE = cpystr("flip-colors");
1655 GLO_TITLEBAR_COLOR_STYLE = cpystr("default");
1656 GLO_POST_CHAR_SET = cpystr("UTF-8");
1657 #ifdef DF_FOLDER_EXTENSION
1658 GLO_FOLDER_EXTENSION = cpystr(DF_FOLDER_EXTENSION);
1659 #endif
1660 #ifdef DF_SMTP_SERVER
1661 GLO_SMTP_SERVER = parse_list(DF_SMTP_SERVER, 1,
1662 PL_REMSURRQUOT, NULL);
1663 #endif
1665 #ifdef DF_SSHPATH
1666 GLO_SSHPATH = cpystr(DF_SSHPATH);
1667 #endif
1668 #ifdef DF_SSHCMD
1669 GLO_SSHCMD = cpystr(DF_SSHCMD);
1670 #endif
1672 #ifndef _WINDOWS
1673 GLO_COLOR_STYLE = cpystr("no-color");
1674 GLO_NORM_FORE_COLOR = cpystr(DEFAULT_NORM_FORE_RGB);
1675 GLO_NORM_BACK_COLOR = cpystr(DEFAULT_NORM_BACK_RGB);
1676 #endif
1677 GLO_TITLE_FORE_COLOR = cpystr(DEFAULT_TITLE_FORE_RGB);
1678 GLO_TITLE_BACK_COLOR = cpystr(DEFAULT_TITLE_BACK_RGB);
1679 GLO_TITLECLOSED_FORE_COLOR = cpystr(DEFAULT_TITLECLOSED_FORE_RGB);
1680 GLO_TITLECLOSED_BACK_COLOR = cpystr(DEFAULT_TITLECLOSED_BACK_RGB);
1681 GLO_FOLDER_FORE_COLOR = cpystr(DEFAULT_NORM_FORE_RGB);
1682 GLO_DIRECTORY_FORE_COLOR = cpystr(DEFAULT_NORM_FORE_RGB);
1683 GLO_FOLDER_LIST_FORE_COLOR = cpystr(DEFAULT_NORM_FORE_RGB);
1684 GLO_METAMSG_FORE_COLOR = cpystr(DEFAULT_METAMSG_FORE_RGB);
1685 GLO_METAMSG_BACK_COLOR = cpystr(DEFAULT_METAMSG_BACK_RGB);
1686 GLO_QUOTE1_FORE_COLOR = cpystr(DEFAULT_QUOTE1_FORE_RGB);
1687 GLO_QUOTE1_BACK_COLOR = cpystr(DEFAULT_QUOTE1_BACK_RGB);
1688 GLO_QUOTE2_FORE_COLOR = cpystr(DEFAULT_QUOTE2_FORE_RGB);
1689 GLO_QUOTE2_BACK_COLOR = cpystr(DEFAULT_QUOTE2_BACK_RGB);
1690 GLO_QUOTE3_FORE_COLOR = cpystr(DEFAULT_QUOTE3_FORE_RGB);
1691 GLO_QUOTE3_BACK_COLOR = cpystr(DEFAULT_QUOTE3_BACK_RGB);
1692 GLO_SIGNATURE_FORE_COLOR = cpystr(DEFAULT_SIGNATURE_FORE_RGB);
1693 GLO_SIGNATURE_BACK_COLOR = cpystr(DEFAULT_SIGNATURE_BACK_RGB);
1694 GLO_IND_PLUS_FORE_COLOR = cpystr(DEFAULT_IND_PLUS_FORE_RGB);
1695 GLO_IND_PLUS_BACK_COLOR = cpystr(DEFAULT_IND_PLUS_BACK_RGB);
1696 GLO_IND_IMP_FORE_COLOR = cpystr(DEFAULT_IND_IMP_FORE_RGB);
1697 GLO_IND_IMP_BACK_COLOR = cpystr(DEFAULT_IND_IMP_BACK_RGB);
1698 GLO_IND_ANS_FORE_COLOR = cpystr(DEFAULT_IND_ANS_FORE_RGB);
1699 GLO_IND_ANS_BACK_COLOR = cpystr(DEFAULT_IND_ANS_BACK_RGB);
1700 GLO_IND_NEW_FORE_COLOR = cpystr(DEFAULT_IND_NEW_FORE_RGB);
1701 GLO_IND_NEW_BACK_COLOR = cpystr(DEFAULT_IND_NEW_BACK_RGB);
1702 GLO_IND_OP_FORE_COLOR = cpystr(DEFAULT_IND_OP_FORE_RGB);
1703 GLO_IND_OP_BACK_COLOR = cpystr(DEFAULT_IND_OP_BACK_RGB);
1704 GLO_VIEW_MARGIN_LEFT = cpystr("0");
1705 GLO_VIEW_MARGIN_RIGHT = cpystr(DF_VIEW_MARGIN_RIGHT);
1706 GLO_QUOTE_SUPPRESSION = cpystr(DF_QUOTE_SUPPRESSION);
1707 GLO_KW_BRACES = cpystr("\"{\" \"} \"");
1708 GLO_OPENING_SEP = cpystr(" - ");
1709 GLO_WP_INDEXHEIGHT = cpystr("24");
1710 GLO_WP_AGGSTATE = cpystr("1");
1711 GLO_WP_STATE = cpystr("");
1712 #ifdef DF_VAR_SPELLER
1713 GLO_SPELLER = cpystr(DF_VAR_SPELLER);
1714 #endif
1715 #ifdef SMIME
1716 if(ps->smimedir){
1717 snprintf(tmp_20k_buf, SIZEOF_20KBUF, "%s/public", ps->smimedir);
1718 tmp_20k_buf[SIZEOF_20KBUF-1] = '\0';
1719 GLO_PUBLICCERT_DIR = cpystr(tmp_20k_buf);
1721 snprintf(tmp_20k_buf, SIZEOF_20KBUF, "%s/private", ps->smimedir);
1722 tmp_20k_buf[SIZEOF_20KBUF-1] = '\0';
1723 GLO_PRIVATEKEY_DIR = cpystr(tmp_20k_buf);
1725 snprintf(tmp_20k_buf, SIZEOF_20KBUF, "%s/ca", ps->smimedir);
1726 tmp_20k_buf[SIZEOF_20KBUF-1] = '\0';
1727 GLO_CACERT_DIR = cpystr(tmp_20k_buf);
1729 else{
1730 GLO_PUBLICCERT_DIR = cpystr(DF_PUBLICCERT_DIR);
1731 GLO_PRIVATEKEY_DIR = cpystr(DF_PRIVATEKEY_DIR);
1732 GLO_CACERT_DIR = cpystr(DF_CACERT_DIR);
1734 #endif /* SMIME */
1737 * Default first value for addrbook list if none set.
1738 * We also want to be sure to set global_val to the default
1739 * if is_fixed, so that address-book= will cause the default to happen.
1741 if(!GLO_ADDRESSBOOK && !FIX_ADDRESSBOOK)
1742 GLO_ADDRESSBOOK = parse_list(DF_ADDRESSBOOK, 1, 0, NULL);
1745 * Default first value if none set.
1747 if(!GLO_STANDARD_PRINTER && !FIX_STANDARD_PRINTER)
1748 GLO_STANDARD_PRINTER = parse_list(DF_STANDARD_PRINTER, 1, 0, NULL);
1751 * Defining this default sshpath should cause ssh to be preferred over rsh
1752 * when attempting imapd preauth calls.
1754 #ifdef DF_SSHPATH
1755 if(DF_SSHPATH
1756 && is_absolute_path(DF_SSHPATH)
1757 && can_access(DF_SSHPATH, EXECUTE_ACCESS) == 0){
1758 mail_parameters(NULL, SET_SSHPATH, (void *) DF_SSHPATH);
1760 #endif
1762 * It isn't usually necessary to define this.
1764 #ifdef DF_SSHCMD
1765 if(DF_SSHCMD){
1766 mail_parameters(NULL, SET_SSHCOMMAND, (void *) DF_SSHCMD);
1768 #endif
1770 #if !defined(DOS) && !defined(OS2)
1772 * This is here instead of in init_pinerc so that we can get by without
1773 * having a global fixedprc, since we don't need it anymore after this.
1775 fixedprc = new_pinerc_s(SYSTEM_PINERC_FIXED);
1776 #endif
1778 if(ps->pconf){
1779 read_pinerc(ps->pconf, vars, ParseGlobal);
1780 if(ps->pconf->type != Loc)
1781 rd_close_remote(ps->pconf->rd);
1784 if(ps->prc){
1785 read_pinerc(ps->prc, vars, ParsePers);
1786 if(ps->prc->type != Loc)
1787 rd_close_remote(ps->prc->rd);
1790 if(ps->post_prc){
1791 read_pinerc(ps->post_prc, vars, ParsePersPost);
1792 if(ps->post_prc->type != Loc)
1793 rd_close_remote(ps->post_prc->rd);
1796 if(fixedprc){
1797 read_pinerc(fixedprc, vars, ParseFixed);
1798 free_pinerc_s(&fixedprc);
1801 ps->ew_for_except_vars = ps->post_prc ? Post : Main;
1803 if(ps->exit_if_no_pinerc && ps->first_time_user){
1805 /* TRANSLATORS: -bail is a literal option name, don't change it. */
1806 exceptional_exit(_("Exiting because -bail option is set and config file doesn't exist."), -1);
1810 * Convert everything having to do with the config to UTF-8
1811 * in order to avoid having to worry about it all over the
1812 * place.
1813 * Set the character-set first so that we may use that in
1814 * the conversion process.
1816 set_collation(0, 1);
1818 #ifndef _WINDOWS
1819 #if (HAVE_LANGINFO_H && defined(CODESET))
1821 if(output_charset_is_supported(nl_langinfo_codeset_wrapper()))
1822 ps->GLO_CHAR_SET = cpystr(nl_langinfo_codeset_wrapper());
1823 else{
1824 ps->GLO_CHAR_SET = cpystr("UTF-8");
1825 dprint((1,"nl_langinfo(CODESET) returns unrecognized value=\"%s\", using UTF-8 as default\n", (p=nl_langinfo(CODESET)) ? p : ""));
1827 #else
1828 ps->GLO_CHAR_SET = cpystr("UTF-8");
1829 #endif
1831 set_current_val(&vars[V_CHAR_SET], TRUE, TRUE);
1832 set_current_val(&vars[V_OLD_CHAR_SET], TRUE, TRUE);
1833 set_current_val(&vars[V_KEY_CHAR_SET], TRUE, TRUE);
1834 #endif /* ! _WINDOWS */
1836 set_current_val(&vars[V_POST_CHAR_SET], TRUE, TRUE);
1839 * Also set up the feature list because we need the
1840 * Use-System-Translation feature to set up the charmaps.
1843 /* way obsolete, backwards compatibility */
1844 set_current_val(&vars[V_FEATURE_LEVEL], TRUE, TRUE);
1845 if(strucmp(VAR_FEATURE_LEVEL, "seedling") == 0)
1846 obs_feature_level = Seedling;
1847 else if(strucmp(VAR_FEATURE_LEVEL, "old-growth") == 0)
1848 obs_feature_level = Seasoned;
1849 else
1850 obs_feature_level = Sapling;
1852 /* obsolete, backwards compatibility */
1853 set_current_val(&vars[V_OLD_STYLE_REPLY], TRUE, TRUE);
1854 obs_old_style_reply = !strucmp(VAR_OLD_STYLE_REPLY, "yes");
1856 set_feature_list_current_val(&vars[V_FEATURE_LIST]);
1857 process_feature_list(ps, VAR_FEATURE_LIST,
1858 (obs_feature_level == Seasoned) ? 1 : 0,
1859 obs_header_in_reply, obs_old_style_reply);
1863 * Redo set_collation call with correct value for collation,
1864 * but we're hardwiring ctype on now. That's because nl_langinfo()
1865 * call needs it and system-dependent wcwidth and wcrtomb functions
1866 * need it.
1868 set_collation(F_OFF(F_DISABLE_SETLOCALE_COLLATE, ps_global), 1);
1871 * Set up to send the correct sequence of bytes to the display terminal.
1874 if(reset_character_set_stuff(&err) == -1)
1875 alpine_panic(err ? err : "trouble with character set setup");
1876 else if(err){
1877 init_error(ps, SM_ORDER | SM_DING, 3, 5, err);
1878 fs_give((void **) &err);
1882 * Now we use the configvars from above to convert the rest
1883 * to UTF-8. That should be ok because the ones above should
1884 * be ASCII.
1886 if(ps->keyboard_charmap && strucmp(ps->keyboard_charmap, "UTF-8")
1887 && strucmp(ps->keyboard_charmap, "US-ASCII"))
1888 fromcharset = ps->keyboard_charmap;
1889 else if(ps->display_charmap && strucmp(ps->display_charmap, "UTF-8")
1890 && strucmp(ps->display_charmap, "US-ASCII"))
1891 fromcharset = ps->display_charmap;
1892 #ifndef _WINDOWS
1893 else if(VAR_OLD_CHAR_SET && strucmp(VAR_OLD_CHAR_SET, "UTF-8")
1894 && strucmp(VAR_OLD_CHAR_SET, "US-ASCII"))
1895 fromcharset = VAR_OLD_CHAR_SET;
1896 #endif /* ! _WINDOWS */
1898 convert_configvars_to_utf8(vars, fromcharset);
1901 * If we already set this while reading the remote pinerc, don't
1902 * change it.
1904 if(!VAR_REMOTE_ABOOK_METADATA || !VAR_REMOTE_ABOOK_METADATA[0])
1905 set_current_val(&vars[V_REMOTE_ABOOK_METADATA], TRUE, TRUE);
1908 * mail-directory variable is obsolete, put its value in
1909 * default folder-collection list
1911 set_current_val(&vars[V_MAIL_DIRECTORY], TRUE, TRUE);
1912 if(!GLO_FOLDER_SPEC){
1913 build_path(tmp_20k_buf, VAR_MAIL_DIRECTORY, "[]", SIZEOF_20KBUF);
1914 GLO_FOLDER_SPEC = parse_list(tmp_20k_buf, 1, 0, NULL);
1917 set_current_val(&vars[V_FOLDER_SPEC], TRUE, TRUE);
1919 set_current_val(&vars[V_NNTP_SERVER], TRUE, TRUE);
1920 for(i = 0; VAR_NNTP_SERVER && VAR_NNTP_SERVER[i]; i++)
1921 removing_quotes(VAR_NNTP_SERVER[i]);
1923 set_news_spec_current_val(TRUE, TRUE);
1925 set_current_val(&vars[V_INBOX_PATH], TRUE, TRUE);
1927 set_current_val(&vars[V_USER_DOMAIN], TRUE, TRUE);
1928 if(VAR_USER_DOMAIN
1929 && VAR_USER_DOMAIN[0]
1930 && (p = strrindex(VAR_USER_DOMAIN, '@'))){
1931 if(*(++p)){
1932 char *q;
1934 snprintf(tmp_20k_buf, SIZEOF_20KBUF,
1935 "User-domain (%s) cannot contain \"@\", using \"%s\"",
1936 VAR_USER_DOMAIN, p);
1937 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
1938 q = VAR_USER_DOMAIN;
1939 while((*q++ = *p++) != '\0')
1940 ;/* do nothing */
1942 else{
1943 snprintf(tmp_20k_buf, SIZEOF_20KBUF,
1944 "User-domain (%s) cannot contain \"@\", deleting",
1945 VAR_USER_DOMAIN);
1946 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
1947 if(ps->vars[V_USER_DOMAIN].post_user_val.p){
1948 fs_give((void **)&ps->vars[V_USER_DOMAIN].post_user_val.p);
1949 set_current_val(&vars[V_USER_DOMAIN], TRUE, TRUE);
1952 if(VAR_USER_DOMAIN
1953 && VAR_USER_DOMAIN[0]
1954 && (p = strrindex(VAR_USER_DOMAIN, '@'))){
1955 if(ps->vars[V_USER_DOMAIN].main_user_val.p){
1956 fs_give((void **)&ps->vars[V_USER_DOMAIN].main_user_val.p);
1957 set_current_val(&vars[V_USER_DOMAIN], TRUE, TRUE);
1963 set_current_val(&vars[V_USE_ONLY_DOMAIN_NAME], TRUE, TRUE);
1964 set_current_val(&vars[V_REPLY_STRING], TRUE, TRUE);
1965 set_current_val(&vars[V_WORDSEPS], TRUE, TRUE);
1966 set_current_val(&vars[V_QUOTE_REPLACE_STRING], TRUE, TRUE);
1967 set_current_val(&vars[V_REPLY_INTRO], TRUE, TRUE);
1968 set_current_val(&vars[V_EMPTY_HDR_MSG], TRUE, TRUE);
1970 #ifdef ENABLE_LDAP
1971 set_current_val(&vars[V_LDAP_SERVERS], TRUE, TRUE);
1972 #endif /* ENABLE_LDAP */
1974 /* obsolete, backwards compatibility */
1975 set_current_val(&vars[V_HEADER_IN_REPLY], TRUE, TRUE);
1976 obs_header_in_reply=!strucmp(VAR_HEADER_IN_REPLY, "yes");
1978 set_current_val(&vars[V_PERSONAL_PRINT_COMMAND], TRUE, TRUE);
1979 set_current_val(&vars[V_STANDARD_PRINTER], TRUE, TRUE);
1980 set_current_val(&vars[V_PRINTER], TRUE, TRUE);
1981 if(vars[V_PERSONAL_PRINT_COMMAND].is_fixed && !vars[V_PRINTER].is_fixed)
1982 printer_value_check_and_adjust();
1984 set_current_val(&vars[V_LAST_TIME_PRUNE_QUESTION], TRUE, TRUE);
1985 if(VAR_LAST_TIME_PRUNE_QUESTION != NULL){
1986 /* The month value in the file runs from 1-12, the variable here
1987 runs from 0-11; the value in the file used to be 0-11, but we're
1988 fixing it in January */
1989 ps->last_expire_year = atoi(VAR_LAST_TIME_PRUNE_QUESTION);
1990 ps->last_expire_month =
1991 atoi(strindex(VAR_LAST_TIME_PRUNE_QUESTION, '.') + 1);
1992 if(ps->last_expire_month == 0){
1993 /* Fix for 0 because of old bug */
1994 snprintf(buf, sizeof(buf), "%d.%d", ps_global->last_expire_year,
1995 ps_global->last_expire_month + 1);
1996 set_variable(V_LAST_TIME_PRUNE_QUESTION, buf, 1, 1, Main);
1997 }else{
1998 ps->last_expire_month--;
2000 }else{
2001 ps->last_expire_year = -1;
2002 ps->last_expire_month = -1;
2005 set_current_val(&vars[V_BUGS_FULLNAME], TRUE, TRUE);
2006 set_current_val(&vars[V_BUGS_ADDRESS], TRUE, TRUE);
2007 set_current_val(&vars[V_SUGGEST_FULLNAME], TRUE, TRUE);
2008 set_current_val(&vars[V_SUGGEST_ADDRESS], TRUE, TRUE);
2009 set_current_val(&vars[V_LOCAL_FULLNAME], TRUE, TRUE);
2010 set_current_val(&vars[V_LOCAL_ADDRESS], TRUE, TRUE);
2011 set_current_val(&vars[V_BUGS_EXTRAS], TRUE, TRUE);
2012 set_current_val(&vars[V_KBLOCK_PASSWD_COUNT], TRUE, TRUE);
2013 set_current_val(&vars[V_DEFAULT_FCC], TRUE, TRUE);
2014 set_current_val(&vars[V_POSTPONED_FOLDER], TRUE, TRUE);
2015 set_current_val(&vars[V_TRASH_FOLDER], TRUE, TRUE);
2016 set_current_val(&vars[V_READ_MESSAGE_FOLDER], TRUE, TRUE);
2017 set_current_val(&vars[V_FORM_FOLDER], TRUE, TRUE);
2018 set_current_val(&vars[V_EDITOR], TRUE, TRUE);
2019 set_current_val(&vars[V_SPELLER], TRUE, TRUE);
2020 #ifdef _WINDOWS
2021 set_current_val(&vars[V_DICTIONARY], TRUE, TRUE);
2022 #endif /* _WINDOWS */
2023 set_current_val(&vars[V_IMAGE_VIEWER], TRUE, TRUE);
2024 set_current_val(&vars[V_BROWSER], TRUE, TRUE);
2025 set_current_val(&vars[V_HISTORY], TRUE, TRUE);
2026 set_current_val(&vars[V_SMTP_SERVER], TRUE, TRUE);
2027 set_current_val(&vars[V_COMP_HDRS], TRUE, TRUE);
2028 set_current_val(&vars[V_CUSTOM_HDRS], TRUE, TRUE);
2029 set_current_val(&vars[V_SENDMAIL_PATH], TRUE, TRUE);
2030 set_current_val(&vars[V_DISPLAY_FILTERS], TRUE, TRUE);
2031 set_current_val(&vars[V_SEND_FILTER], TRUE, TRUE);
2032 set_current_val(&vars[V_ALT_ADDRS], TRUE, TRUE);
2033 set_current_val(&vars[V_ABOOK_FORMATS], TRUE, TRUE);
2034 set_current_val(&vars[V_KW_BRACES], TRUE, TRUE);
2035 set_current_val(&vars[V_OPENING_SEP], TRUE, TRUE);
2036 set_current_val(&vars[V_UNK_CHAR_SET], TRUE, TRUE);
2037 #ifdef SMIME
2038 set_current_val(&vars[V_PUBLICCERT_DIR], TRUE, TRUE);
2039 set_current_val(&vars[V_PUBLICCERT_CONTAINER], TRUE, TRUE);
2040 set_current_val(&vars[V_PRIVATEKEY_DIR], TRUE, TRUE);
2041 set_current_val(&vars[V_PRIVATEKEY_CONTAINER], TRUE, TRUE);
2042 set_current_val(&vars[V_CACERT_DIR], TRUE, TRUE);
2043 set_current_val(&vars[V_CACERT_CONTAINER], TRUE, TRUE);
2044 #endif /* SMIME */
2046 set_current_val(&vars[V_KEYWORDS], TRUE, TRUE);
2047 ps_global->keywords = init_keyword_list(VAR_KEYWORDS);
2049 set_current_val(&vars[V_OPER_DIR], TRUE, TRUE);
2050 if(VAR_OPER_DIR && !VAR_OPER_DIR[0]){
2051 init_error(ps, SM_ORDER | SM_DING, 3, 5,
2052 "Setting operating-dir to the empty string is not allowed. Will be ignored.");
2053 fs_give((void **)&VAR_OPER_DIR);
2054 if(FIX_OPER_DIR)
2055 fs_give((void **)&FIX_OPER_DIR);
2056 if(GLO_OPER_DIR)
2057 fs_give((void **)&GLO_OPER_DIR);
2058 if(COM_OPER_DIR)
2059 fs_give((void **)&COM_OPER_DIR);
2060 if(ps_global->vars[V_OPER_DIR].post_user_val.p)
2061 fs_give((void **)&ps_global->vars[V_OPER_DIR].post_user_val.p);
2062 if(ps_global->vars[V_OPER_DIR].main_user_val.p)
2063 fs_give((void **)&ps_global->vars[V_OPER_DIR].main_user_val.p);
2066 set_current_val(&vars[V_PERSONAL_PRINT_CATEGORY], TRUE, TRUE);
2067 ps->printer_category = -1;
2068 if(VAR_PERSONAL_PRINT_CATEGORY != NULL)
2069 ps->printer_category = atoi(VAR_PERSONAL_PRINT_CATEGORY);
2071 if(ps->printer_category < 1 || ps->printer_category > 3){
2072 char **tt;
2073 char aname[100], wname[100];
2075 strncpy(aname, ANSI_PRINTER, sizeof(aname));
2076 aname[sizeof(aname)-1] = '\0';
2077 strncat(aname, "-no-formfeed", sizeof(aname)-strlen(aname)-1);
2078 strncpy(wname, WYSE_PRINTER, sizeof(wname));
2079 wname[sizeof(wname)-1] = '\0';
2080 strncat(wname, "-no-formfeed", sizeof(wname)-strlen(wname)-1);
2081 if(strucmp(VAR_PRINTER, ANSI_PRINTER) == 0
2082 || strucmp(VAR_PRINTER, aname) == 0
2083 || strucmp(VAR_PRINTER, WYSE_PRINTER) == 0
2084 || strucmp(VAR_PRINTER, wname) == 0)
2085 ps->printer_category = 1;
2086 else if(VAR_STANDARD_PRINTER && VAR_STANDARD_PRINTER[0]){
2087 for(tt = VAR_STANDARD_PRINTER; *tt; tt++)
2088 if(strucmp(VAR_PRINTER, *tt) == 0)
2089 break;
2091 if(*tt)
2092 ps->printer_category = 2;
2095 /* didn't find it yet */
2096 if(ps->printer_category < 1 || ps->printer_category > 3){
2097 if(VAR_PERSONAL_PRINT_COMMAND && VAR_PERSONAL_PRINT_COMMAND[0]){
2098 for(tt = VAR_PERSONAL_PRINT_COMMAND; *tt; tt++)
2099 if(strucmp(VAR_PRINTER, *tt) == 0)
2100 break;
2102 if(*tt)
2103 ps->printer_category = 3;
2108 set_current_val(&vars[V_SLEEP], TRUE, TRUE);
2109 ps->sleep = i = 60;
2110 if(SVAR_SLEEP(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2111 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2112 else
2113 ps->sleep = i;
2115 set_current_val(&vars[V_OVERLAP], TRUE, TRUE);
2116 ps->viewer_overlap = i = atoi(DF_OVERLAP);
2117 if(SVAR_OVERLAP(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2118 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2119 else
2120 ps->viewer_overlap = i;
2122 set_current_val(&vars[V_MARGIN], TRUE, TRUE);
2123 ps->scroll_margin = i = atoi(DF_MARGIN);
2124 if(SVAR_MARGIN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2125 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2126 else
2127 ps->scroll_margin = i;
2129 set_current_val(&vars[V_FILLCOL], TRUE, TRUE);
2130 ps->composer_fillcol = i = atoi(DF_FILLCOL);
2131 if(SVAR_FILLCOL(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2132 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2133 else
2134 ps->composer_fillcol = i;
2136 set_current_val(&vars[V_QUOTE_SUPPRESSION], TRUE, TRUE);
2137 ps->quote_suppression_threshold = i = atoi(DF_QUOTE_SUPPRESSION);
2138 if(SVAR_QUOTE_SUPPRESSION(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2139 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2140 else{
2141 if(i > 0 && i < Q_SUPP_LIMIT){
2142 snprintf(tmp_20k_buf, SIZEOF_20KBUF,
2143 "Ignoring Quote-Suppression-Threshold value of %.50s, see help",
2144 VAR_QUOTE_SUPPRESSION);
2145 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2147 else{
2148 if(i < 0 && i != Q_DEL_ALL)
2149 ps->quote_suppression_threshold = -i;
2150 else
2151 ps->quote_suppression_threshold = i;
2155 set_current_val(&vars[V_DEADLETS], TRUE, TRUE);
2156 ps->deadlets = i = atoi(DF_DEADLETS);
2157 if(SVAR_DEADLETS(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2158 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2159 else
2160 ps->deadlets = i;
2162 set_current_val(&vars[V_STATUS_MSG_DELAY], TRUE, TRUE);
2163 ps->status_msg_delay = i = 0;
2164 if(SVAR_MSGDLAY(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2165 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2166 else
2167 ps->status_msg_delay = i;
2169 set_current_val(&vars[V_ACTIVE_MSG_INTERVAL], TRUE, TRUE);
2170 ps->active_status_interval = i = 8;
2171 if(SVAR_ACTIVEINTERVAL(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2172 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2173 else
2174 ps->active_status_interval = i;
2176 set_current_val(&vars[V_REMOTE_ABOOK_HISTORY], TRUE, TRUE);
2177 ps->remote_abook_history = i = atoi(DF_REMOTE_ABOOK_HISTORY);
2178 if(SVAR_AB_HIST(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2179 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2180 else
2181 ps->remote_abook_history = i;
2183 set_current_val(&vars[V_REMOTE_ABOOK_VALIDITY], TRUE, TRUE);
2184 ps->remote_abook_validity = i = atoi(DF_REMOTE_ABOOK_VALIDITY);
2185 if(SVAR_AB_VALID(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2186 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2187 else
2188 ps->remote_abook_validity = i;
2190 set_current_val(&vars[V_USERINPUTTIMEO], TRUE, TRUE);
2191 ps->hours_to_timeout = i = 0;
2192 if(SVAR_USER_INPUT(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2193 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2194 else
2195 ps->hours_to_timeout = i;
2197 /* timeo is a regular extern int because it is referenced in pico */
2198 set_current_val(&vars[V_MAILCHECK], TRUE, TRUE);
2199 set_input_timeout(i = 15);
2200 if(SVAR_MAILCHK(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2201 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2202 else
2203 set_input_timeout(i);
2205 set_current_val(&vars[V_MAILCHECKNONCURR], TRUE, TRUE);
2206 ps->check_interval_for_noncurr = i = 0;
2207 if(SVAR_MAILCHKNONCURR(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2208 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2209 else
2210 ps->check_interval_for_noncurr = i;
2212 #ifdef DEBUGJOURNAL
2213 ps->debugmem = 1;
2214 #else
2215 ps->debugmem = 0;
2216 #endif
2218 i = 30;
2219 set_current_val(&vars[V_TCPOPENTIMEO], TRUE, TRUE);
2220 /* this is just for the error, we don't save the result */
2221 if(VAR_TCPOPENTIMEO && SVAR_TCP_OPEN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2222 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2224 i = 15;
2225 set_current_val(&vars[V_TCPREADWARNTIMEO], TRUE, TRUE);
2226 /* this is just for the error, we don't save the result */
2227 if(VAR_TCPREADWARNTIMEO && SVAR_TCP_READWARN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2228 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2230 i = 0;
2231 set_current_val(&vars[V_TCPWRITEWARNTIMEO], TRUE, TRUE);
2232 /* this is just for the error, we don't save the result */
2233 if(VAR_TCPWRITEWARNTIMEO && SVAR_TCP_WRITEWARN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2234 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2236 i = 15;
2237 set_current_val(&vars[V_RSHOPENTIMEO], TRUE, TRUE);
2238 /* this is just for the error, we don't save the result */
2239 if(VAR_RSHOPENTIMEO && SVAR_RSH_OPEN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2240 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2242 i = 15;
2243 set_current_val(&vars[V_SSHOPENTIMEO], TRUE, TRUE);
2244 /* this is just for the error, we don't save the result */
2245 if(VAR_SSHOPENTIMEO && SVAR_SSH_OPEN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2246 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2248 set_current_val(&vars[V_INCCHECKLIST], TRUE, TRUE);
2250 set_current_val(&vars[V_INCCHECKTIMEO], TRUE, TRUE);
2251 ps->inc_check_timeout = i = 5;
2252 if(SVAR_INC_CHECK_TIMEO(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2253 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2254 else
2255 ps->inc_check_timeout = i;
2257 set_current_val(&vars[V_INCCHECKINTERVAL], TRUE, TRUE);
2258 ps->inc_check_interval = i = 180;
2259 if(SVAR_INC_CHECK_INTERV(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2260 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2261 else
2262 ps->inc_check_interval = i;
2264 set_current_val(&vars[V_INC2NDCHECKINTERVAL], TRUE, TRUE);
2265 ps->inc_second_check_interval = i = 180;
2266 if(SVAR_INC_2NDCHECK_INTERV(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2267 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2268 else
2269 ps->inc_second_check_interval = i;
2271 rvl = 60L;
2272 set_current_val(&vars[V_MAILDROPCHECK], TRUE, TRUE);
2273 /* this is just for the error, we don't save the result */
2274 if(VAR_MAILDROPCHECK && SVAR_MAILDCHK(ps, rvl, tmp_20k_buf, SIZEOF_20KBUF))
2275 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2277 rvl = 0L;
2278 set_current_val(&vars[V_NNTPRANGE], TRUE, TRUE);
2279 /* this is just for the error, we don't save the result */
2280 if(VAR_NNTPRANGE && SVAR_NNTPRANGE(ps, rvl, tmp_20k_buf, SIZEOF_20KBUF))
2281 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2283 set_current_val(&vars[V_TCPQUERYTIMEO], TRUE, TRUE);
2284 ps->tcp_query_timeout = i = TO_BAIL_THRESHOLD;
2285 if(VAR_TCPQUERYTIMEO && SVAR_TCP_QUERY(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2286 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2287 else
2288 ps->tcp_query_timeout = i;
2290 set_current_val(&vars[V_NEWSRC_PATH], TRUE, TRUE);
2291 if(VAR_NEWSRC_PATH && VAR_NEWSRC_PATH[0])
2292 mail_parameters(NULL, SET_NEWSRC, (void *)VAR_NEWSRC_PATH);
2294 set_current_val(&vars[V_NEWS_ACTIVE_PATH], TRUE, TRUE);
2295 if(VAR_NEWS_ACTIVE_PATH)
2296 mail_parameters(NULL, SET_NEWSACTIVE,
2297 (void *)VAR_NEWS_ACTIVE_PATH);
2299 set_current_val(&vars[V_NEWS_SPOOL_DIR], TRUE, TRUE);
2300 if(VAR_NEWS_SPOOL_DIR)
2301 mail_parameters(NULL, SET_NEWSSPOOL,
2302 (void *)VAR_NEWS_SPOOL_DIR);
2304 /* guarantee a save default */
2305 set_current_val(&vars[V_DEFAULT_SAVE_FOLDER], TRUE, TRUE);
2306 if(!VAR_DEFAULT_SAVE_FOLDER || !VAR_DEFAULT_SAVE_FOLDER[0])
2307 set_variable(V_DEFAULT_SAVE_FOLDER,
2308 (GLO_DEFAULT_SAVE_FOLDER && GLO_DEFAULT_SAVE_FOLDER[0])
2309 ? GLO_DEFAULT_SAVE_FOLDER
2310 : DEFAULT_SAVE, 1, 0, Main);
2312 set_current_val(&vars[V_SIGNATURE_FILE], TRUE, TRUE);
2313 set_current_val(&vars[V_LITERAL_SIG], TRUE, TRUE);
2314 set_current_val(&vars[V_GLOB_ADDRBOOK], TRUE, TRUE);
2315 set_current_val(&vars[V_ADDRESSBOOK], TRUE, TRUE);
2316 set_current_val(&vars[V_FORCED_ABOOK_ENTRY], TRUE, TRUE);
2317 set_current_val(&vars[V_DISABLE_DRIVERS], TRUE, TRUE);
2318 set_current_val(&vars[V_DISABLE_AUTHS], TRUE, TRUE);
2320 set_current_val(&vars[V_VIEW_HEADERS], TRUE, TRUE);
2321 /* strip spaces and colons */
2322 if(ps->VAR_VIEW_HEADERS){
2323 for(s = ps->VAR_VIEW_HEADERS; (q = *s) != NULL; s++){
2324 if(q[0]){
2325 removing_leading_white_space(q);
2326 /* look for colon or space or end */
2327 for(p = q; *p && !isspace((unsigned char)*p) && *p != ':'; p++)
2328 ;/* do nothing */
2330 *p = '\0';
2331 if(strucmp(q, ALL_EXCEPT) == 0)
2332 ps->view_all_except = 1;
2337 set_current_val(&vars[V_VIEW_MARGIN_LEFT], TRUE, TRUE);
2338 set_current_val(&vars[V_VIEW_MARGIN_RIGHT], TRUE, TRUE);
2339 set_current_val(&vars[V_UPLOAD_CMD], TRUE, TRUE);
2340 set_current_val(&vars[V_UPLOAD_CMD_PREFIX], TRUE, TRUE);
2341 set_current_val(&vars[V_DOWNLOAD_CMD], TRUE, TRUE);
2342 set_current_val(&vars[V_DOWNLOAD_CMD_PREFIX], TRUE, TRUE);
2343 set_current_val(&vars[V_MAILCAP_PATH], TRUE, TRUE);
2344 set_current_val(&vars[V_MIMETYPE_PATH], TRUE, TRUE);
2345 #if !defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)
2346 set_current_val(&vars[V_FIFOPATH], TRUE, TRUE);
2347 #endif
2349 set_current_val(&vars[V_RSHPATH], TRUE, TRUE);
2350 if(VAR_RSHPATH
2351 && is_absolute_path(VAR_RSHPATH)
2352 && can_access(VAR_RSHPATH, EXECUTE_ACCESS) == 0){
2353 mail_parameters(NULL, SET_RSHPATH, (void *) VAR_RSHPATH);
2356 set_current_val(&vars[V_RSHCMD], TRUE, TRUE);
2357 if(VAR_RSHCMD){
2358 mail_parameters(NULL, SET_RSHCOMMAND, (void *) VAR_RSHCMD);
2361 set_current_val(&vars[V_SSHPATH], TRUE, TRUE);
2362 if(VAR_SSHPATH) {
2363 if(is_absolute_path(VAR_SSHPATH)
2364 && can_access(VAR_SSHPATH, EXECUTE_ACCESS) == 0){
2365 mail_parameters(NULL, SET_SSHPATH, (void *) VAR_SSHPATH);
2367 else {
2368 mail_parameters(NULL, SET_SSHPATH, (void *) NULL);
2372 set_current_val(&vars[V_SSHCMD], TRUE, TRUE);
2373 if(VAR_SSHCMD) {
2374 if(VAR_SSHCMD[0]) {
2375 mail_parameters(NULL, SET_SSHCOMMAND, (void *) VAR_SSHCMD);
2377 else {
2378 mail_parameters(NULL, SET_SSHCOMMAND, (void *) NULL);
2382 #if defined(DOS) || defined(OS2)
2384 set_current_val(&vars[V_FILE_DIR], TRUE, TRUE);
2386 #ifdef _WINDOWS
2387 set_current_val(&vars[V_FONT_NAME], TRUE, TRUE);
2388 set_current_val(&vars[V_FONT_SIZE], TRUE, TRUE);
2389 set_current_val(&vars[V_FONT_STYLE], TRUE, TRUE);
2390 set_current_val(&vars[V_FONT_CHAR_SET], TRUE, TRUE);
2391 set_current_val(&vars[V_CURSOR_STYLE], TRUE, TRUE);
2392 set_current_val(&vars[V_WINDOW_POSITION], TRUE, TRUE);
2394 if(F_OFF(F_STORE_WINPOS_IN_CONFIG, ps_global)){
2395 /* if win position is in the registry, use it */
2396 if(mswin_reg(MSWR_OP_GET, MSWR_PINE_POS, buf, sizeof(buf))){
2397 if(VAR_WINDOW_POSITION)
2398 fs_give((void **)&VAR_WINDOW_POSITION);
2400 VAR_WINDOW_POSITION = cpystr(buf);
2402 else if(VAR_WINDOW_POSITION
2403 && (ps->update_registry != UREG_NEVER_SET)){
2404 /* otherwise, put it there */
2405 mswin_reg(MSWR_OP_SET | ((ps->update_registry == UREG_ALWAYS_SET)
2406 ? MSWR_OP_FORCE : 0),
2407 MSWR_PINE_POS,
2408 VAR_WINDOW_POSITION, (size_t)NULL);
2412 mswin_setwindow (VAR_FONT_NAME, VAR_FONT_SIZE,
2413 VAR_FONT_STYLE, VAR_WINDOW_POSITION,
2414 VAR_CURSOR_STYLE, VAR_FONT_CHAR_SET);
2416 /* this is no longer used */
2417 if(VAR_WINDOW_POSITION)
2418 fs_give((void **)&VAR_WINDOW_POSITION);
2420 set_current_val(&vars[V_PRINT_FONT_NAME], TRUE, TRUE);
2421 set_current_val(&vars[V_PRINT_FONT_SIZE], TRUE, TRUE);
2422 set_current_val(&vars[V_PRINT_FONT_STYLE], TRUE, TRUE);
2423 set_current_val(&vars[V_PRINT_FONT_CHAR_SET], TRUE, TRUE);
2424 mswin_setprintfont (VAR_PRINT_FONT_NAME,
2425 VAR_PRINT_FONT_SIZE,
2426 VAR_PRINT_FONT_STYLE,
2427 VAR_PRINT_FONT_CHAR_SET);
2429 mswin_setgenhelptextcallback(pcpine_general_help);
2431 mswin_setclosetext ("Use the \"Q\" command to exit Alpine.");
2434 char foreColor[64], backColor[64];
2436 mswin_getwindow(NULL, 0, NULL, 0, NULL, 0, NULL, 0,
2437 foreColor, sizeof(foreColor), backColor, sizeof(backColor),
2438 NULL, 0, NULL, 0);
2439 if(!GLO_NORM_FORE_COLOR)
2440 GLO_NORM_FORE_COLOR = cpystr(foreColor);
2442 if(!GLO_NORM_BACK_COLOR)
2443 GLO_NORM_BACK_COLOR = cpystr(backColor);
2445 #endif /* _WINDOWS */
2446 #endif /* DOS */
2449 * We want the version number to start out as 1.0 for Alpine, but
2450 * we also want to use the same old config file that was used
2451 * with Pine. The Pine version numbers made it up to 4.64 and we
2452 * want Alpine's 1.0 to be larger than 4.64 so we keep a separate
2453 * internal version number which is the real version number
2454 * plus 4. That's what gets written in LAST_VERS_USED.
2456 strncpy(ps->vers_internal, ALPINE_VERSION, sizeof(ps->vers_internal));
2457 ps->vers_internal[sizeof(ps->vers_internal)-1] = '\0';
2458 if(isdigit(ps->vers_internal[0]) && ps->vers_internal[0] < '6')
2459 ps->vers_internal[0] = ps->vers_internal[0] + 4;
2461 set_current_val(&vars[V_LAST_VERS_USED], TRUE, TRUE);
2462 /* Check for special cases first */
2463 if(VAR_LAST_VERS_USED
2464 && (isdigit(ps->vers_internal[0])
2465 && ps->vers_internal[1] == '.'
2466 && isdigit((unsigned char)ps->vers_internal[2])
2467 && isdigit((unsigned char)ps->vers_internal[3])
2468 && isalpha((unsigned char)ps->vers_internal[4])
2469 && strncmp(VAR_LAST_VERS_USED, ps->vers_internal, 4) >= 0)){
2470 ps->show_new_version = 0;
2472 /* Otherwise just do lexicographic comparision... */
2473 else if(VAR_LAST_VERS_USED
2474 && strcmp(VAR_LAST_VERS_USED, ps->vers_internal) >= 0){
2475 ps->show_new_version = 0;
2477 else{
2478 #ifdef _WINDOWS
2480 * If this is the first time we've run a version > 4.40, and there
2481 * is evidence that the config file has not been used by unix pine,
2482 * then we convert color008 to colorlgr, color009 to colormgr, and
2483 * color010 to colordgr. If the config file is being used by
2484 * unix pine then color009 may really supposed to be red, etc.
2485 * Same if we've already run 4.41 or higher. We don't have to do
2486 * anything if we are new to alpine.
2488 ps->pre441 = (VAR_LAST_VERS_USED
2489 && strcmp(VAR_LAST_VERS_USED, "4.40") <= 0);
2490 #endif /* _WINDOWS */
2493 * Don't offer the new version message if we're told not to.
2495 set_current_val(&vars[V_NEW_VER_QUELL], TRUE, TRUE);
2496 ps->show_new_version = !(VAR_NEW_VER_QUELL
2497 && strcmp(ps->vers_internal,
2498 VAR_NEW_VER_QUELL) < 0);
2500 #ifdef _WINDOWS
2501 if(!ps_global->install_flag)
2502 #endif /* _WINDOWS */
2504 if(VAR_LAST_VERS_USED){
2505 strncpy(ps_global->pine_pre_vers, VAR_LAST_VERS_USED,
2506 sizeof(ps_global->pine_pre_vers));
2507 ps_global->pine_pre_vers[sizeof(ps_global->pine_pre_vers)-1] = '\0';
2510 set_variable(V_LAST_VERS_USED, ps->vers_internal, 1, 1,
2511 ps_global->ew_for_except_vars);
2515 /* Obsolete, backwards compatibility */
2516 set_current_val(&vars[V_ELM_STYLE_SAVE], TRUE, TRUE);
2517 /* Also obsolete */
2518 set_current_val(&vars[V_SAVE_BY_SENDER], TRUE, TRUE);
2519 if(!strucmp(VAR_ELM_STYLE_SAVE, "yes"))
2520 set_variable(V_SAVE_BY_SENDER, "yes", 1, 1, Main);
2521 obs_save_by_sender = !strucmp(VAR_SAVE_BY_SENDER, "yes");
2523 set_current_pattern_vals(ps);
2525 set_current_val(&vars[V_INDEX_FORMAT], TRUE, TRUE);
2526 init_index_format(VAR_INDEX_FORMAT, &ps->index_disp_format);
2528 /* this should come after pre441 is set or not */
2529 set_current_color_vals(ps);
2531 set_current_val(&vars[V_RSS_NEWS], TRUE, TRUE);
2532 set_current_val(&vars[V_RSS_WEATHER], TRUE, TRUE);
2533 set_current_val(&vars[V_WP_INDEXHEIGHT], TRUE, TRUE);
2534 set_current_val(&vars[V_WP_INDEXLINES], TRUE, TRUE);
2535 set_current_val(&vars[V_WP_AGGSTATE], TRUE, TRUE);
2536 set_current_val(&vars[V_WP_STATE], TRUE, TRUE);
2537 set_current_val(&vars[V_WP_COLUMNS], TRUE, TRUE);
2539 set_current_val(&vars[V_PRUNED_FOLDERS], TRUE, TRUE);
2540 set_current_val(&vars[V_ARCHIVED_FOLDERS], TRUE, TRUE);
2541 set_current_val(&vars[V_INCOMING_FOLDERS], TRUE, TRUE);
2542 set_current_val(&vars[V_SORT_KEY], TRUE, TRUE);
2543 if(decode_sort(VAR_SORT_KEY, &ps->def_sort, &def_sort_rev) == -1){
2544 snprintf(tmp_20k_buf, SIZEOF_20KBUF, "Sort type \"%.200s\" is invalid", VAR_SORT_KEY);
2545 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2546 ps->def_sort = SortArrival;
2547 ps->def_sort_rev = 0;
2549 else
2550 ps->def_sort_rev = def_sort_rev;
2552 cur_rule_value(&vars[V_SAVED_MSG_NAME_RULE], TRUE, TRUE);
2553 {NAMEVAL_S *v; int i;
2554 for(i = 0; (v = save_msg_rules(i)); i++)
2555 if(v->value == ps_global->save_msg_rule)
2556 break;
2558 /* if save_msg_rule is not default, or is explicitly set to default */
2559 if((ps_global->save_msg_rule != SAV_RULE_DEFLT) ||
2560 (v && v->name &&
2561 (!strucmp(ps_global->vars[V_SAVED_MSG_NAME_RULE].post_user_val.p,
2562 v->name) ||
2563 !strucmp(ps_global->vars[V_SAVED_MSG_NAME_RULE].main_user_val.p,
2564 v->name))))
2565 obs_save_by_sender = 0; /* don't overwrite */
2568 cur_rule_value(&vars[V_FCC_RULE], TRUE, TRUE);
2569 cur_rule_value(&vars[V_AB_SORT_RULE], TRUE, TRUE);
2571 #ifndef _WINDOWS
2572 cur_rule_value(&vars[V_COLOR_STYLE], TRUE, TRUE);
2573 #endif
2575 cur_rule_value(&vars[V_INDEX_COLOR_STYLE], TRUE, TRUE);
2576 cur_rule_value(&vars[V_TITLEBAR_COLOR_STYLE], TRUE, TRUE);
2577 cur_rule_value(&vars[V_FLD_SORT_RULE], TRUE, TRUE);
2578 cur_rule_value(&vars[V_INCOMING_STARTUP], TRUE, TRUE);
2579 cur_rule_value(&vars[V_PRUNING_RULE], TRUE, TRUE);
2580 cur_rule_value(&vars[V_REOPEN_RULE], TRUE, TRUE);
2581 cur_rule_value(&vars[V_GOTO_DEFAULT_RULE], TRUE, TRUE);
2582 cur_rule_value(&vars[V_THREAD_DISP_STYLE], TRUE, TRUE);
2583 cur_rule_value(&vars[V_THREAD_INDEX_STYLE], TRUE, TRUE);
2585 set_current_val(&vars[V_THREAD_MORE_CHAR], TRUE, TRUE);
2586 if(VAR_THREAD_MORE_CHAR[0] && VAR_THREAD_MORE_CHAR[1]){
2587 init_error(ps, SM_ORDER | SM_DING, 3, 5,
2588 _("Only using first character of threading-indicator-character option"));
2589 VAR_THREAD_MORE_CHAR[1] = '\0';
2592 set_current_val(&vars[V_THREAD_EXP_CHAR], TRUE, TRUE);
2593 if(VAR_THREAD_EXP_CHAR[0] && VAR_THREAD_EXP_CHAR[1]){
2594 init_error(ps, SM_ORDER | SM_DING, 3, 5,
2595 _("Only using first character of threading-expanded-character option"));
2596 VAR_THREAD_EXP_CHAR[1] = '\0';
2599 set_current_val(&vars[V_THREAD_LASTREPLY_CHAR], TRUE, TRUE);
2600 if(!VAR_THREAD_LASTREPLY_CHAR[0])
2601 VAR_THREAD_LASTREPLY_CHAR = cpystr(DF_THREAD_LASTREPLY_CHAR);
2603 if(VAR_THREAD_LASTREPLY_CHAR[0] && VAR_THREAD_LASTREPLY_CHAR[1]){
2604 init_error(ps, SM_ORDER | SM_DING, 3, 5,
2605 _("Only using first character of threading-lastreply-character option"));
2606 VAR_THREAD_LASTREPLY_CHAR[1] = '\0';
2609 set_current_val(&vars[V_MAXREMSTREAM], TRUE, TRUE);
2610 ps->s_pool.max_remstream = i = atoi(DF_MAXREMSTREAM);
2611 if(SVAR_MAXREMSTREAM(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2612 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2613 else
2614 ps->s_pool.max_remstream = i;
2616 set_current_val(&vars[V_PERMLOCKED], TRUE, TRUE);
2618 set_current_val(&vars[V_NMW_WIDTH], TRUE, TRUE);
2619 ps->nmw_width = i = atoi(DF_NMW_WIDTH);
2620 if(SVAR_NMW_WIDTH(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2621 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2622 else
2623 ps->nmw_width = i;
2625 /* backwards compatibility */
2626 if(obs_save_by_sender){
2627 ps->save_msg_rule = SAV_RULE_FROM;
2628 set_variable(V_SAVED_MSG_NAME_RULE, "by-from", 1, 1, Main);
2631 /* this should come after process_feature_list because of use_fkeys */
2632 if(!ps->start_in_index)
2633 set_current_val(&vars[V_INIT_CMD_LIST], FALSE, TRUE);
2634 if(VAR_INIT_CMD_LIST && VAR_INIT_CMD_LIST[0] && VAR_INIT_CMD_LIST[0][0])
2635 if(cmds_f)
2636 (*cmds_f)(ps, VAR_INIT_CMD_LIST);
2638 #ifdef _WINDOWS
2639 mswin_set_quit_confirm (F_OFF(F_QUIT_WO_CONFIRM, ps_global));
2640 #endif /* _WINDOWS */
2642 #ifdef DEBUG
2643 dump_configuration(0);
2644 #endif /* DEBUG */
2648 void
2649 convert_configvars_to_utf8(struct variable *vars, char *fromcharset)
2651 struct variable *v;
2654 * Make sure that everything is UTF-8.
2656 for(v = vars; v->name; v++)
2657 convert_configvar_to_utf8(v, fromcharset);
2661 void
2662 convert_configvar_to_utf8(struct variable *v, char *fromcharset)
2664 char **p, *conv, **valptr;
2665 int i;
2668 * Make sure that everything is UTF-8.
2670 if(v->is_list){
2671 for(i = 0; i < 7; i++){
2672 switch(i){
2673 case 1: valptr = v->current_val.l; break;
2674 case 0: valptr = v->main_user_val.l; break;
2675 case 2: valptr = v->changed_val.l; break;
2676 case 3: valptr = v->post_user_val.l; break;
2677 case 4: valptr = v->global_val.l; break;
2678 case 5: valptr = v->fixed_val.l; break;
2679 case 6: valptr = v->cmdline_val.l; break;
2680 default: alpine_panic("bad case in convert_configvar");
2683 if(valptr){
2684 for(p = valptr; *p; p++){
2685 if(**p){
2686 conv = convert_to_utf8(*p, fromcharset, 0);
2687 if(conv){
2688 fs_give((void **) p);
2689 *p = conv;
2696 else{
2697 for(i = 0; i < 7; i++){
2698 switch(i){
2699 case 1: valptr = &v->current_val.p; break;
2700 case 0: valptr = &v->main_user_val.p; break;
2701 case 2: valptr = &v->changed_val.p; break;
2702 case 3: valptr = &v->post_user_val.p; break;
2703 case 4: valptr = &v->global_val.p; break;
2704 case 5: valptr = &v->fixed_val.p; break;
2705 case 6: valptr = &v->cmdline_val.p; break;
2706 default: alpine_panic("bad case in convert_configvar");
2709 if(valptr && *valptr && (*valptr)[0]){
2710 conv = convert_to_utf8(*valptr, fromcharset, 0);
2711 if(conv){
2712 fs_give((void **) valptr);
2713 *valptr = conv;
2723 * Standard feature name sections
2725 char *
2726 feature_list_section(FEATURE_S *feature)
2728 #define PREF_NONE -1
2729 static char *feat_sect[] = {
2730 #define PREF_MISC 0
2731 /* TRANSLATORS: section heading in configuration screen */
2732 N_("Advanced User Preferences"),
2733 #define PREF_FLDR 1
2734 /* TRANSLATORS: section heading in configuration screen */
2735 N_("Folder Preferences"),
2736 #define PREF_ADDR 2
2737 /* TRANSLATORS: section heading in configuration screen */
2738 N_("Address Book Preferences"),
2739 #define PREF_COMP 3
2740 /* TRANSLATORS: section heading in configuration screen */
2741 N_("Composer Preferences"),
2742 #define PREF_NEWS 4
2743 /* TRANSLATORS: section heading in configuration screen */
2744 N_("News Preferences"),
2745 #define PREF_VIEW 5
2746 /* TRANSLATORS: section heading in configuration screen */
2747 N_("Viewer Preferences"),
2748 #define PREF_ACMD 6
2749 /* TRANSLATORS: section heading in configuration screen */
2750 N_("Advanced Command Preferences"),
2751 #define PREF_PRNT 7
2752 /* TRANSLATORS: section heading in configuration screen */
2753 N_("Printer Preferences"),
2754 #define PREF_RPLY 8
2755 /* TRANSLATORS: section heading in configuration screen */
2756 N_("Reply Preferences"),
2757 #define PREF_SEND 9
2758 /* TRANSLATORS: section heading in configuration screen */
2759 N_("Sending Preferences"),
2760 #define PREF_INDX 10
2761 /* TRANSLATORS: section heading in configuration screen */
2762 N_("Message Index Preferences"),
2763 #define PREF_HIDDEN 11
2764 HIDDEN_PREF
2767 return((feature && feature->section > PREF_NONE
2768 && feature->section < (sizeof(feat_sect)/sizeof(feat_sect[0])))
2769 ? _(feat_sect[feature->section]) : NULL);
2773 /* any os-specific exclusions */
2774 #if defined(DOS) || defined(OS2)
2775 #define PREF_OS_LWSD PREF_NONE
2776 #define PREF_OS_LCLK PREF_NONE
2777 #define PREF_OS_STSP PREF_NONE
2778 #define PREF_OS_SPWN PREF_NONE
2779 #define PREF_OS_XNML PREF_NONE
2780 #define PREF_OS_USFK PREF_MISC
2781 #define PREF_OS_MOUSE PREF_NONE
2782 #else
2783 #define PREF_OS_LWSD PREF_MISC
2784 #define PREF_OS_LCLK PREF_COMP
2785 #define PREF_OS_STSP PREF_MISC
2786 #define PREF_OS_SPWN PREF_MISC
2787 #define PREF_OS_XNML PREF_MISC
2788 #define PREF_OS_USFK PREF_NONE
2789 #define PREF_OS_MOUSE PREF_MISC
2790 #endif
2794 * Standard way to get at feature list members...
2796 FEATURE_S *
2797 feature_list(int index)
2800 * This list is alphabatized by feature string, but the
2801 * macro values need not be ordered.
2803 static FEATURE_S feat_list[] = {
2804 /* Composer prefs */
2805 {"allow-changing-from", NULL,
2806 F_ALLOW_CHANGING_FROM, h_config_allow_chg_from, PREF_COMP, 1},
2807 {"alternate-compose-menu", NULL,
2808 F_ALT_COMPOSE_MENU, h_config_alt_compose_menu, PREF_COMP, 0},
2809 {"alternate-role-menu", "Alternate Role (#) Menu",
2810 F_ALT_ROLE_MENU, h_config_alt_role_menu, PREF_COMP, 0},
2811 {"compose-cancel-confirm-uses-yes", NULL,
2812 F_CANCEL_CONFIRM, h_config_cancel_confirm, PREF_COMP, 0},
2813 {"compose-rejects-unqualified-addrs", "Compose Rejects Unqualified Addresses",
2814 F_COMPOSE_REJECTS_UNQUAL, h_config_compose_rejects_unqual, PREF_COMP, 0},
2815 {"compose-send-offers-first-filter", NULL,
2816 F_FIRST_SEND_FILTER_DFLT, h_config_send_filter_dflt, PREF_COMP, 0},
2817 {"compose-cut-from-cursor", "Ctrl-K Cuts From Cursor",
2818 F_DEL_FROM_DOT, h_config_del_from_dot, PREF_COMP, 0},
2819 {"compose-maps-delete-key-to-ctrl-d", "Delete Key Maps to Ctrl-D",
2820 F_COMPOSE_MAPS_DEL, h_config_compose_maps_del, PREF_COMP, 0},
2821 {"quell-dead-letter-on-cancel", "Do Not Save to Deadletter on Cancel",
2822 F_QUELL_DEAD_LETTER, h_config_quell_dead_letter, PREF_COMP, 0},
2823 {"enable-alternate-editor-cmd", "Enable Alternate Editor Command",
2824 F_ENABLE_ALT_ED, h_config_enable_alt_ed, PREF_COMP, 1},
2825 {"enable-alternate-editor-implicitly", NULL,
2826 F_ALT_ED_NOW, h_config_alt_ed_now, PREF_COMP, 0},
2827 {"enable-search-and-replace", "Enable Search and Replace",
2828 F_ENABLE_SEARCH_AND_REPL, h_config_enable_search_and_repl, PREF_COMP, 1},
2829 {"enable-sigdashes", NULL,
2830 F_ENABLE_SIGDASHES, h_config_sigdashes, PREF_COMP, 0},
2831 {"quell-mailchecks-composing-except-inbox", "Prevent Mailchecks While Composing Except for INBOX",
2832 F_QUELL_PINGS_COMPOSING, h_config_quell_checks_comp, PREF_COMP, 0},
2833 {"quell-mailchecks-composing-inbox", "Prevent Mailchecks While Composing for INBOX",
2834 F_QUELL_PINGS_COMPOSING_INBOX, h_config_quell_checks_comp_inbox, PREF_COMP, 0},
2835 {"quell-user-lookup-in-passwd-file", "Prevent User Lookup in Password File",
2836 F_QUELL_LOCAL_LOOKUP, h_config_quell_local_lookup, PREF_OS_LCLK, 0},
2837 {"spell-check-before-sending", NULL,
2838 F_ALWAYS_SPELL_CHECK, h_config_always_spell_check, PREF_COMP, 0},
2840 /* Reply Prefs */
2841 {"alternate-reply-menu", NULL,
2842 F_ALT_REPLY_MENU, h_config_alt_reply_menu, PREF_RPLY, 0},
2843 {"copy-to-address-to-from-if-it-is-us", "Copy To Address to From if it is Us",
2844 F_COPY_TO_TO_FROM, h_config_copy_to_to_from, PREF_RPLY, 0},
2845 {"enable-reply-indent-string-editing", NULL,
2846 F_ENABLE_EDIT_REPLY_INDENT, h_config_prefix_editing, PREF_RPLY, 0},
2847 {"include-attachments-in-reply", "Include Attachments in Reply",
2848 F_ATTACHMENTS_IN_REPLY, h_config_attach_in_reply, PREF_RPLY, 0},
2849 {"include-header-in-reply", "Include Header in Reply",
2850 F_INCLUDE_HEADER, h_config_include_header, PREF_RPLY, 0},
2851 {"include-text-in-reply", "Include Text in Reply",
2852 F_AUTO_INCLUDE_IN_REPLY, h_config_auto_include_reply, PREF_RPLY, 0},
2853 {"reply-always-uses-reply-to", "Reply Always Uses Reply-To",
2854 F_AUTO_REPLY_TO, h_config_auto_reply_to, PREF_RPLY, 0},
2855 {"signature-at-bottom", "Signature at Bottom",
2856 F_SIG_AT_BOTTOM, h_config_sig_at_bottom, PREF_RPLY, 0},
2857 {"strip-from-sigdashes-on-reply", "Strip From Sigdashes on Reply",
2858 F_ENABLE_STRIP_SIGDASHES, h_config_strip_sigdashes, PREF_RPLY, 0},
2859 {"forward-as-attachment", "Forward messages as attachments",
2860 F_FORWARD_AS_ATTACHMENT, h_config_forward_as_attachment, PREF_RPLY, 0},
2861 {"preserve-original-fields", NULL,
2862 F_PRESERVE_ORIGINAL_FIELD, h_config_preserve_field, PREF_RPLY, 0},
2864 /* Sending Prefs */
2865 {"disable-sender", "Do Not Generate Sender Header",
2866 F_DISABLE_SENDER, h_config_disable_sender, PREF_SEND, 0},
2867 {"use-sender-not-x-sender", "Use Sender Instead of X-X-Sender",
2868 F_USE_SENDER_NOT_X, h_config_use_sender_not_x, PREF_SEND, 0},
2869 {"quell-flowed-text", "Do Not Send Flowed Text",
2870 F_QUELL_FLOWED_TEXT, h_config_quell_flowed_text, PREF_SEND, 0},
2871 {"downgrade-multipart-to-text", "Downgrade Multipart to Text",
2872 F_COMPOSE_ALWAYS_DOWNGRADE, h_downgrade_multipart_to_text, PREF_SEND, 0},
2873 {"enable-8bit-esmtp-negotiation", "Enable 8bit ESMTP Negotiation",
2874 F_ENABLE_8BIT, h_config_8bit_smtp, PREF_SEND, 1},
2875 #ifdef BACKGROUND_POST
2876 {"enable-background-sending", NULL,
2877 F_BACKGROUND_POST, h_config_compose_bg_post, PREF_SEND, 0},
2878 #endif
2879 {"enable-delivery-status-notification", NULL,
2880 F_DSN, h_config_compose_dsn, PREF_SEND, 0},
2881 {"enable-verbose-smtp-posting", "Enable Verbose SMTP Posting",
2882 F_VERBOSE_POST, h_config_verbose_post, PREF_SEND, 0},
2883 {"fcc-without-attachments", "Fcc Does Not Include Attachments",
2884 F_NO_FCC_ATTACH, h_config_no_fcc_attach, PREF_SEND, 0},
2885 {"fcc-on-bounce", "Include Fcc When Bouncing Messages",
2886 F_FCC_ON_BOUNCE, h_config_fcc_on_bounce, PREF_SEND, 0},
2887 {"mark-fcc-seen", NULL,
2888 F_MARK_FCC_SEEN, h_config_mark_fcc_seen, PREF_SEND, 0},
2889 {"fcc-only-without-confirm", "Send to Fcc Only Without Confirming",
2890 F_AUTO_FCC_ONLY, h_config_auto_fcc_only, PREF_SEND, 0},
2891 {"send-without-confirm", "Send Without Confirming",
2892 F_SEND_WO_CONFIRM, h_config_send_wo_confirm, PREF_SEND, 0},
2893 {"strip-whitespace-before-send", "Strip Whitespace Before Sending",
2894 F_STRIP_WS_BEFORE_SEND, h_config_strip_ws_before_send, PREF_SEND, 0},
2895 {"warn-if-blank-fcc", "Warn if Blank Fcc",
2896 F_WARN_ABOUT_NO_FCC, h_config_warn_if_fcc_blank, PREF_SEND, 0},
2897 {"warn-if-blank-subject", "Warn if Blank Subject",
2898 F_WARN_ABOUT_NO_SUBJECT, h_config_warn_if_subj_blank, PREF_SEND, 0},
2899 {"warn-if-blank-to-and-cc-and-newsgroups", "Warn if Blank To and CC and Newsgroups",
2900 F_WARN_ABOUT_NO_TO_OR_CC, h_config_warn_if_no_to_or_cc, PREF_SEND, 0},
2902 /* Folder */
2903 {"combined-folder-display", NULL,
2904 F_CMBND_FOLDER_DISP, h_config_combined_folder_display, PREF_FLDR, 0},
2905 {"combined-subdirectory-display", NULL,
2906 F_CMBND_SUBDIR_DISP, h_config_combined_subdir_display, PREF_FLDR, 0},
2907 {"enable-lame-list-mode", "Compensate for Deficient IMAP servers",
2908 F_FIX_BROKEN_LIST, h_config_lame_list_mode, PREF_FLDR, 0},
2909 {"enable-dot-folders", "Enable Hidden Folders",
2910 F_ENABLE_DOT_FOLDERS, h_config_enable_dot_folders, PREF_FLDR, 0},
2911 {"enable-incoming-folders", "Enable Incoming Folders Collection",
2912 F_ENABLE_INCOMING, h_config_enable_incoming, PREF_FLDR, 0},
2913 {"enable-incoming-folders-checking", NULL,
2914 F_ENABLE_INCOMING_CHECKING, h_config_enable_incoming_checking, PREF_FLDR, 0},
2915 {"incoming-checking-includes-total", NULL,
2916 F_INCOMING_CHECKING_TOTAL, h_config_incoming_checking_total, PREF_FLDR, 0},
2917 {"incoming-checking-uses-recent", NULL,
2918 F_INCOMING_CHECKING_RECENT, h_config_incoming_checking_recent, PREF_FLDR, 0},
2919 {"expanded-view-of-folders", "Expanded View of Folders",
2920 F_EXPANDED_FOLDERS, h_config_expanded_folders, PREF_FLDR, 0},
2921 {"quell-empty-directories", "Hide Empty Directories",
2922 F_QUELL_EMPTY_DIRS, h_config_quell_empty_dirs, PREF_FLDR, 0},
2923 {"separate-folder-and-directory-entries", "Separate Folder and Directory Entries",
2924 F_SEPARATE_FLDR_AS_DIR, h_config_separate_fold_dir_view, PREF_FLDR, 0},
2925 {"single-column-folder-list", NULL,
2926 F_SINGLE_FOLDER_LIST, h_config_single_list, PREF_FLDR, 0},
2927 {"sort-default-fcc-alpha", "Sort Default Fcc Folder Alphabetically",
2928 F_SORT_DEFAULT_FCC_ALPHA, h_config_sort_fcc_alpha, PREF_FLDR, 0},
2929 {"sort-default-save-alpha", "Sort Default Save Folder Alphabetically",
2930 F_SORT_DEFAULT_SAVE_ALPHA, h_config_sort_save_alpha, PREF_FLDR, 0},
2931 {"vertical-folder-list", "Use Vertical Folder List",
2932 F_VERTICAL_FOLDER_LIST, h_config_vertical_list, PREF_FLDR, 0},
2934 /* Addr book */
2935 {"combined-addrbook-display", "Combined Address Book Display",
2936 F_CMBND_ABOOK_DISP, h_config_combined_abook_display, PREF_ADDR, 0},
2937 {"expanded-view-of-addressbooks", "Expanded View of Address Books",
2938 F_EXPANDED_ADDRBOOKS, h_config_expanded_addrbooks, PREF_ADDR, 0},
2939 {"expanded-view-of-distribution-lists", "Expanded View of Distribution Lists",
2940 F_EXPANDED_DISTLISTS, h_config_expanded_distlists, PREF_ADDR, 0},
2941 #ifdef ENABLE_LDAP
2942 {"ldap-result-to-addrbook-add", "LDAP Result to Addressbook Add",
2943 F_ADD_LDAP_TO_ABOOK, h_config_add_ldap, PREF_ADDR, 0},
2944 #endif
2946 /* Index prefs */
2947 {"auto-open-next-unread", NULL,
2948 F_AUTO_OPEN_NEXT_UNREAD, h_config_auto_open_unread, PREF_INDX, 0},
2949 {"continue-tab-without-confirm", "Continue NextNew Without Confirming",
2950 F_TAB_NO_CONFIRM, h_config_tab_no_prompt, PREF_INDX, 0},
2951 {"convert-dates-to-localtime", NULL,
2952 F_DATES_TO_LOCAL, h_config_dates_to_local, PREF_INDX, 0},
2953 {"delete-skips-deleted", NULL,
2954 F_DEL_SKIPS_DEL, h_config_del_skips_del, PREF_INDX, 1},
2955 {"disable-index-locale-dates", NULL,
2956 F_DISABLE_INDEX_LOCALE_DATES, h_config_disable_index_locale_dates, PREF_INDX, 0},
2957 {"enable-cruise-mode", NULL,
2958 F_ENABLE_SPACE_AS_TAB, h_config_cruise_mode, PREF_INDX, 0},
2959 {"enable-cruise-mode-delete", "Enable Cruise Mode With Deleting",
2960 F_ENABLE_TAB_DELETES, h_config_cruise_mode_delete, PREF_INDX, 0},
2961 {"mark-for-cc", "Mark for CC",
2962 F_MARK_FOR_CC, h_config_mark_for_cc, PREF_INDX, 1},
2963 {"next-thread-without-confirm", "Read Next Thread Without Confirming",
2964 F_NEXT_THRD_WO_CONFIRM, h_config_next_thrd_wo_confirm, PREF_INDX, 0},
2965 {"return-to-inbox-without-confirm", "Return to INBOX Without Confirming",
2966 F_RET_INBOX_NO_CONFIRM, h_config_inbox_no_confirm, PREF_INDX, 0},
2967 {"show-sort", "Show Sort in Titlebar",
2968 F_SHOW_SORT, h_config_show_sort, PREF_INDX, 0},
2969 {"tab-uses-unseen-for-next-folder", "Tab Uses Unseen for Next Folder",
2970 F_TAB_USES_UNSEEN, h_config_tab_uses_unseen, PREF_INDX, 0},
2971 {"tab-visits-next-new-message-only", NULL,
2972 F_TAB_TO_NEW, h_config_tab_new_only, PREF_INDX, 0},
2973 {"thread-index-shows-important-color", NULL,
2974 F_COLOR_LINE_IMPORTANT, h_config_color_thrd_import, PREF_INDX, 0},
2975 {"thread-sorts-by-arrival", "Thread Sorts by Arrival",
2976 F_THREAD_SORTS_BY_ARRIVAL, h_config_thread_sorts_by_arrival, PREF_INDX, 0},
2978 /* Viewer prefs */
2979 {"enable-msg-view-addresses", "Enable Message View Address Links",
2980 F_SCAN_ADDR, h_config_enable_view_addresses, PREF_VIEW, 0},
2981 {"enable-msg-view-attachments", "Enable Message View Attachment Links",
2982 F_VIEW_SEL_ATTACH, h_config_enable_view_attach, PREF_VIEW, 0},
2983 {"enable-msg-view-urls", "Enable Message View URL Links",
2984 F_VIEW_SEL_URL, h_config_enable_view_url, PREF_VIEW, 1},
2985 {"enable-msg-view-web-hostnames", "Enable Message View Web Hostname Links",
2986 F_VIEW_SEL_URL_HOST, h_config_enable_view_web_host, PREF_VIEW, 1},
2987 {"enable-msg-view-forced-arrows", "Enable Message View Forced Arrows",
2988 F_FORCE_ARROWS, h_config_enable_view_arrows, PREF_VIEW, 0},
2989 /* set to TRUE for windows */
2990 {"pass-c1-control-characters-as-is", NULL,
2991 F_PASS_C1_CONTROL_CHARS, h_config_pass_c1_control, PREF_VIEW, 0},
2992 {"pass-control-characters-as-is", NULL,
2993 F_PASS_CONTROL_CHARS, h_config_pass_control, PREF_VIEW, 0},
2994 {"prefer-plain-text", NULL,
2995 F_PREFER_PLAIN_TEXT, h_config_prefer_plain_text, PREF_VIEW, 0},
2996 {"quell-charset-warning", "Suppress Character Set Warning",
2997 F_QUELL_CHARSET_WARNING, h_config_quell_charset_warning, PREF_VIEW, 0},
2998 {"quell-server-after-link-in-html", "Suppress Server After Link in HTML",
2999 F_QUELL_HOST_AFTER_URL, h_config_quell_host_after_url, PREF_VIEW, 0},
3001 /* News */
3002 {"compose-sets-newsgroup-without-confirm", "Compose Sets Newsgroup Without Confirming",
3003 F_COMPOSE_TO_NEWSGRP, h_config_compose_news_wo_conf, PREF_NEWS, 0},
3004 {"enable-8bit-nntp-posting", "Enable 8bit NNTP Posting",
3005 F_ENABLE_8BIT_NNTP, h_config_8bit_nntp, PREF_NEWS, 0},
3006 {"enable-multiple-newsrcs", NULL,
3007 F_ENABLE_MULNEWSRCS, h_config_enable_mulnewsrcs, PREF_NEWS, 0},
3008 {"mult-newsrc-hostnames-as-typed", "Multiple Newsrc Hostnames as Typed",
3009 F_MULNEWSRC_HOSTNAMES_AS_TYPED, h_config_mulnews_as_typed, PREF_NEWS, 0},
3010 {"hide-nntp-path", "Hide NNTP Path",
3011 F_HIDE_NNTP_PATH, h_config_hide_nntp_path, PREF_NEWS, 0},
3012 {"news-approximates-new-status", NULL,
3013 F_FAKE_NEW_IN_NEWS, h_config_news_uses_recent, PREF_NEWS, 1},
3014 {"news-deletes-across-groups", NULL,
3015 F_NEWS_CROSS_DELETE, h_config_news_cross_deletes, PREF_NEWS, 0},
3016 {"news-offers-catchup-on-close", "News Offers Catchup on Close",
3017 F_NEWS_CATCHUP, h_config_news_catchup, PREF_NEWS, 0},
3018 {"news-post-without-validation", NULL,
3019 F_NO_NEWS_VALIDATION, h_config_post_wo_validation, PREF_NEWS, 0},
3020 {"news-read-in-newsrc-order", "News Read in Newsrc Order",
3021 F_READ_IN_NEWSRC_ORDER, h_config_read_in_newsrc_order, PREF_NEWS, 0},
3022 {"nntp-search-uses-overview", "NNTP Search Uses Overview",
3023 F_NNTP_SEARCH_USES_OVERVIEW, h_config_nntp_search_uses_overview, PREF_NEWS, 1},
3024 {"predict-nntp-server", "Predict NNTP Server",
3025 F_PREDICT_NNTP_SERVER, h_config_predict_nntp_server, PREF_NEWS, 0},
3026 {"quell-extra-post-prompt", "Suppress Extra Posting Prompt",
3027 F_QUELL_EXTRA_POST_PROMPT, h_config_quell_post_prompt, PREF_NEWS, 0},
3029 /* Print */
3030 {"enable-print-via-y-command", NULL,
3031 F_ENABLE_PRYNT, h_config_enable_y_print, PREF_PRNT, 0},
3032 {"print-formfeed-between-messages", NULL,
3033 F_AGG_PRINT_FF, h_config_ff_between_msgs, PREF_PRNT, 0},
3034 {"print-includes-from-line", NULL,
3035 F_FROM_DELIM_IN_PRINT, h_config_print_from, PREF_PRNT, 0},
3036 {"print-index-enabled", NULL,
3037 F_PRINT_INDEX, h_config_print_index, PREF_PRNT, 0},
3038 {"print-offers-custom-cmd-prompt", "Print Offers Custom Command Prompt",
3039 F_CUSTOM_PRINT, h_config_custom_print, PREF_PRNT, 0},
3041 /* adv cmd prefs */
3042 {"enable-aggregate-command-set", NULL,
3043 F_ENABLE_AGG_OPS, h_config_enable_agg_ops, PREF_ACMD, 1},
3044 {"enable-arrow-navigation", NULL,
3045 F_ARROW_NAV, h_config_arrow_nav, PREF_ACMD, 1},
3046 {"enable-arrow-navigation-relaxed", NULL,
3047 F_RELAXED_ARROW_NAV, h_config_relaxed_arrow_nav, PREF_ACMD, 1},
3048 {"enable-bounce-cmd", "Enable Bounce Command",
3049 F_ENABLE_BOUNCE, h_config_enable_bounce, PREF_ACMD, 1},
3050 {"enable-exit-via-lessthan-command", NULL,
3051 F_ENABLE_LESSTHAN_EXIT, h_config_enable_lessthan_exit, PREF_ACMD, 1},
3052 {"enable-flag-cmd", "Enable Flag Command",
3053 F_ENABLE_FLAG, h_config_enable_flag, PREF_ACMD, 1},
3054 {"enable-flag-screen-implicitly", NULL,
3055 F_FLAG_SCREEN_DFLT, h_config_flag_screen_default, PREF_ACMD, 0},
3056 {"enable-flag-screen-keyword-shortcut", NULL,
3057 F_FLAG_SCREEN_KW_SHORTCUT, h_config_flag_screen_kw_shortcut,PREF_ACMD, 1},
3058 {"enable-full-header-and-text", "Enable Full Header and Text",
3059 F_ENABLE_FULL_HDR_AND_TEXT, h_config_enable_full_hdr_and_text, PREF_ACMD, 0},
3060 {"enable-full-header-cmd", "Enable Full Header Command",
3061 F_ENABLE_FULL_HDR, h_config_enable_full_hdr, PREF_ACMD, 1},
3062 {"enable-goto-in-file-browser", "Enable Goto in File Browser",
3063 F_ALLOW_GOTO, h_config_allow_goto, PREF_ACMD, 1},
3064 {"enable-jump-shortcut", NULL,
3065 F_ENABLE_JUMP, h_config_enable_jump, PREF_ACMD, 1},
3066 {"enable-partial-match-lists", NULL,
3067 F_ENABLE_SUB_LISTS, h_config_sub_lists, PREF_ACMD, 1},
3068 {"enable-tab-completion", NULL,
3069 F_ENABLE_TAB_COMPLETE, h_config_enable_tab_complete, PREF_ACMD, 1},
3070 {"enable-unix-pipe-cmd", "Enable Unix Pipe Command",
3071 F_ENABLE_PIPE, h_config_enable_pipe, PREF_ACMD, 1},
3072 {"quell-full-header-auto-reset", "Suppress Full Header Auto Reset",
3073 F_QUELL_FULL_HDR_RESET, h_config_quell_full_hdr_reset, PREF_ACMD, 0},
3075 /* Adv user prefs */
3076 #if !defined(DOS) && !defined(OS2)
3077 {"allow-talk", NULL,
3078 F_ALLOW_TALK, h_config_allow_talk, PREF_MISC, 0},
3079 #endif
3080 {"assume-slow-link", NULL,
3081 F_FORCE_LOW_SPEED, h_config_force_low_speed, PREF_OS_LWSD, 0},
3082 {"auto-move-read-msgs", "Auto Move Read Messages",
3083 F_AUTO_READ_MSGS, h_config_auto_read_msgs, PREF_MISC, 0},
3084 {"auto-unselect-after-apply", NULL,
3085 F_AUTO_UNSELECT, h_config_auto_unselect, PREF_MISC, 0},
3086 {"auto-unzoom-after-apply", NULL,
3087 F_AUTO_UNZOOM, h_config_auto_unzoom, PREF_MISC, 1},
3088 {"auto-zoom-after-select", NULL,
3089 F_AUTO_ZOOM, h_config_auto_zoom, PREF_MISC, 1},
3090 {"busy-cue-spinner-only", NULL,
3091 F_USE_BORING_SPINNER, h_config_use_boring_spinner, PREF_MISC, 0},
3092 {"check-newmail-when-quitting", NULL,
3093 F_CHECK_MAIL_ONQUIT, h_config_check_mail_onquit, PREF_MISC, 0},
3094 {"confirm-role-even-for-default", "Confirm Role Even for Default",
3095 F_ROLE_CONFIRM_DEFAULT, h_config_confirm_role, PREF_MISC, 0},
3096 {"disable-keymenu", NULL,
3097 F_BLANK_KEYMENU, h_config_blank_keymenu, PREF_MISC, 0},
3098 {"disable-password-caching", NULL,
3099 F_DISABLE_PASSWORD_CACHING, h_config_disable_password_caching,
3100 PREF_MISC, 0},
3101 #ifdef PASSFILE
3102 {"disable-password-file-saving", NULL,
3103 F_DISABLE_PASSWORD_FILE_SAVING, h_config_disable_password_file_saving,
3104 PREF_MISC, 0},
3105 #endif
3106 {"disable-regular-expression-matching-for-alternate-addresses", NULL,
3107 F_DISABLE_REGEX, h_config_disable_regex, PREF_MISC, 0},
3108 {"disable-save-input-history", NULL,
3109 F_DISABLE_SAVE_INPUT_HISTORY, h_config_input_history, PREF_MISC, 0},
3110 {"disable-take-fullname-in-addresses", "Disable Take Fullname in Addresses",
3111 F_DISABLE_TAKE_FULLNAMES, h_config_take_fullname, PREF_MISC, 0},
3112 {"disable-take-last-comma-first", NULL,
3113 F_DISABLE_TAKE_LASTFIRST, h_config_take_lastfirst, PREF_MISC, 0},
3114 {"disable-terminal-reset-for-display-filters", "Disable Terminal Reset for Display Filters",
3115 F_DISABLE_TERM_RESET_DISP, h_config_disable_reset_disp, PREF_MISC, 0},
3116 {"enable-dot-files", NULL,
3117 F_ENABLE_DOT_FILES, h_config_enable_dot_files, PREF_MISC, 0},
3118 {"enable-fast-recent-test", NULL,
3119 F_ENABLE_FAST_RECENT, h_config_fast_recent, PREF_MISC, 0},
3120 {"enable-mail-check-cue", NULL,
3121 F_SHOW_DELAY_CUE, h_config_show_delay_cue, PREF_MISC, 0},
3122 {"enable-mailcap-param-substitution", "Enable Mailcap Parameter Substitution",
3123 F_DO_MAILCAP_PARAM_SUBST, h_config_mailcap_params, PREF_MISC, 0},
3124 {"enable-mouse-in-xterm", "Enable Mouse in Xterm",
3125 F_ENABLE_MOUSE, h_config_enable_mouse, PREF_OS_MOUSE, 0},
3126 {"enable-newmail-in-xterm-icon", "Enable Newmail in Xterm Icon",
3127 F_ENABLE_XTERM_NEWMAIL, h_config_enable_xterm_newmail, PREF_OS_XNML, 0},
3128 {"enable-newmail-short-text-in-icon", "Enable Newmail Short Text in Icon",
3129 F_ENABLE_NEWMAIL_SHORT_TEXT, h_config_enable_newmail_short_text, PREF_OS_XNML, 0},
3130 {"enable-suspend", NULL,
3131 F_CAN_SUSPEND, h_config_can_suspend, PREF_MISC, 0},
3132 {"enable-take-export", NULL,
3133 F_ENABLE_TAKE_EXPORT, h_config_enable_take_export, PREF_MISC, 0},
3134 {"enable-rules-under-take", "Enable Take Rules",
3135 F_ENABLE_ROLE_TAKE, h_config_enable_role_take, PREF_MISC, 0},
3136 #ifdef _WINDOWS
3137 {"enable-tray-icon", NULL,
3138 F_ENABLE_TRAYICON, h_config_tray_icon, PREF_MISC, 0},
3139 #endif
3140 {"expose-hidden-config", NULL,
3141 F_EXPOSE_HIDDEN_CONFIG, h_config_expose_hidden_config, PREF_MISC, 0},
3142 {"expunge-only-manually", NULL,
3143 F_EXPUNGE_MANUALLY, h_config_expunge_manually, PREF_MISC, 0},
3144 {"expunge-without-confirm", "Expunge Without Confirming",
3145 F_AUTO_EXPUNGE, h_config_auto_expunge, PREF_MISC, 0},
3146 {"expunge-without-confirm-everywhere", "Expunge Without Confirming Everywhere",
3147 F_FULL_AUTO_EXPUNGE, h_config_full_auto_expunge, PREF_MISC, 0},
3148 {"force-arrow-cursor", NULL,
3149 F_FORCE_ARROW, h_config_force_arrow, PREF_MISC, 0},
3150 {"ignore-size-changes", NULL,
3151 F_IGNORE_SIZE, h_config_ignore_size, PREF_MISC, 0},
3152 {"maildrops-preserve-state", NULL,
3153 F_MAILDROPS_PRESERVE_STATE, h_config_maildrops_preserve_state,
3154 PREF_MISC, 0},
3155 {"offer-expunge-of-inbox", "Offer Expunge of INBOX",
3156 F_EXPUNGE_INBOX, h_config_expunge_inbox, PREF_MISC, 0},
3157 {"offer-expunge-of-stayopen-folders", "Offer Expunge of Stayopen Folders",
3158 F_EXPUNGE_STAYOPENS, h_config_expunge_stayopens, PREF_MISC, 0},
3159 {"preopen-stayopen-folders", NULL,
3160 F_PREOPEN_STAYOPENS, h_config_preopen_stayopens, PREF_MISC, 0},
3161 {"preserve-start-stop-characters", "Preserve Start/Stop Characters",
3162 F_PRESERVE_START_STOP, h_config_preserve_start_stop, PREF_OS_STSP, 0},
3163 {"quell-folder-internal-msg", "Prevent Folder Internal Message",
3164 F_QUELL_INTERNAL_MSG, h_config_quell_folder_internal_msg, PREF_MISC, 0},
3165 {"quell-partial-fetching", "Prevent Partial Fetching",
3166 F_QUELL_PARTIAL_FETCH, h_config_quell_partial, PREF_MISC, 0},
3167 {"prune-uses-yyyy-mm", "Prune Uses YYYY-MM",
3168 F_PRUNE_USES_ISO, h_config_prune_uses_iso, PREF_MISC, 0},
3169 {"quit-without-confirm", "Quit Without Confirming",
3170 F_QUIT_WO_CONFIRM, h_config_quit_wo_confirm, PREF_MISC, 0},
3171 {"quote-replace-nonflowed", NULL,
3172 F_QUOTE_REPLACE_NOFLOW, h_config_quote_replace_noflow, PREF_MISC, 0},
3173 {"save-aggregates-copy-sequence", "Save Combines Copies (may be out of order)",
3174 F_AGG_SEQ_COPY, h_config_save_aggregates, PREF_MISC, 1},
3175 {"save-partial-msg-without-confirm", "Save Partial Message Without Confirming",
3176 F_SAVE_PARTIAL_WO_CONFIRM, h_config_save_part_wo_confirm, PREF_MISC, 0},
3177 {"save-will-advance", NULL,
3178 F_SAVE_ADVANCES, h_config_save_advances, PREF_MISC, 0},
3179 {"save-will-not-delete", NULL,
3180 F_SAVE_WONT_DELETE, h_config_save_wont_delete, PREF_MISC, 0},
3181 {"save-will-quote-leading-froms", NULL,
3182 F_QUOTE_ALL_FROMS, h_config_quote_all_froms, PREF_MISC, 0},
3183 {"scramble-message-id", "Scramble the Message-ID When Sending",
3184 F_ROT13_MESSAGE_ID, h_config_scramble_message_id, PREF_MISC, 0},
3185 {"select-without-confirm", "Select Ctrl-T Foldername Without Confirming",
3186 F_SELECT_WO_CONFIRM, h_config_select_wo_confirm, PREF_MISC, 0},
3187 {"show-cursor", NULL,
3188 F_SHOW_CURSOR, h_config_show_cursor, PREF_MISC, 0},
3189 {"show-plain-text-internally", NULL,
3190 F_SHOW_TEXTPLAIN_INT, h_config_textplain_int, PREF_MISC, 0},
3191 {"show-selected-in-boldface", "Show Selected in Boldface",
3192 F_SELECTED_SHOWN_BOLD, h_config_select_in_bold, PREF_MISC, 0},
3193 {"slash-collapses-entire-thread", NULL,
3194 F_SLASH_COLL_ENTIRE, h_config_slash_coll_entire, PREF_MISC, 0},
3195 #ifdef _WINDOWS
3196 {"store-window-position-in-config", "Store Window Position in Config",
3197 F_STORE_WINPOS_IN_CONFIG, h_config_winpos_in_config, PREF_MISC, 0},
3198 #endif
3199 {"suppress-asterisks-in-password-prompt", "Suppress Asterisks in Password Prompt",
3200 F_QUELL_ASTERISKS, h_config_quell_asterisks,
3201 PREF_MISC, 0},
3202 {"quell-attachment-extension-warn", "Suppress Attachment Extension Warning",
3203 F_QUELL_ATTACH_EXT_WARN, h_config_quell_attach_ext_warn,
3204 PREF_MISC, 0},
3205 {"quell-attachment-extra-prompt", "Suppress Attachment Extra Prompt",
3206 F_QUELL_ATTACH_EXTRA_PROMPT, h_config_quell_attach_extra_prompt,
3207 PREF_MISC, 0},
3208 {"quell-berkeley-format-timezone", "Suppress Berkeley Format Timezone",
3209 F_QUELL_BEZERK_TIMEZONE, h_config_no_bezerk_zone, PREF_MISC, 0},
3210 {"quell-content-id", "Suppress Content-ID",
3211 F_QUELL_CONTENT_ID, h_config_quell_content_id, PREF_MISC, 0},
3212 {"quell-filtering-done-message", "Suppress Filtering Done Message",
3213 F_QUELL_FILTER_DONE_MSG, h_config_quell_filtering_done_message,
3214 PREF_MISC, 0},
3215 {"quell-filtering-messages", "Suppress Filtering Messages",
3216 F_QUELL_FILTER_MSGS, h_config_quell_filtering_messages,
3217 PREF_MISC, 0},
3218 {"quell-imap-envelope-update", "Suppress IMAP Envelope Update",
3219 F_QUELL_IMAP_ENV_CB, h_config_quell_imap_env, PREF_MISC, 0},
3220 {"quell-lock-failure-warnings", "Suppress Lock Failure Warnings",
3221 F_QUELL_LOCK_FAILURE_MSGS, h_config_quell_lock_failure_warnings,
3222 PREF_MISC, 0},
3223 {"quell-maildomain-warning", "Suppress Maildomain Warning",
3224 F_QUELL_MAILDOMAIN_WARNING, h_config_quell_domain_warn, PREF_MISC, 0},
3225 {"quell-news-envelope-update", "Suppress News Envelope Update",
3226 F_QUELL_NEWS_ENV_CB, h_config_quell_news_env, PREF_MISC, 0},
3227 #ifdef _WINDOWS
3228 {"quell-ssl-largeblocks", "Prevent SSL Largeblocks",
3229 F_QUELL_SSL_LARGEBLOCKS, h_config_quell_ssl_largeblocks, PREF_MISC, 0},
3230 #endif
3231 {"quell-status-message-beeping", "Suppress Status Message Beeping",
3232 F_QUELL_BEEPS, h_config_quell_beeps, PREF_MISC, 0},
3233 {"quell-timezone-comment-when-sending", "Suppress Timezone Comment When Sending",
3234 F_QUELL_TIMEZONE, h_config_quell_tz_comment, PREF_MISC, 0},
3235 {"suppress-user-agent-when-sending", NULL,
3236 F_QUELL_USERAGENT, h_config_suppress_user_agent, PREF_MISC, 0},
3237 {"tab-checks-recent", "Tab Checks for Recent Messages",
3238 F_TAB_CHK_RECENT, h_config_tab_checks_recent, PREF_MISC, 0},
3239 {"termdef-takes-precedence", NULL,
3240 F_TCAP_WINS, h_config_termcap_wins, PREF_MISC, 0},
3241 {"try-alternative-authentication-driver-first", NULL,
3242 F_PREFER_ALT_AUTH, h_config_alt_auth, PREF_MISC, 0},
3243 {"unselect-will-not-advance", NULL,
3244 F_UNSELECT_WONT_ADVANCE, h_config_unsel_wont_advance, PREF_MISC, 0},
3245 {"use-current-dir", "Use Current Directory",
3246 F_USE_CURRENT_DIR, h_config_use_current_dir, PREF_MISC, 0},
3247 {"use-function-keys", NULL,
3248 F_USE_FK, h_config_use_fk, PREF_OS_USFK, 0},
3249 {"use-regular-startup-rule-for-stayopen-folders", "Use Regular Startup Rule for Stayopen Folders",
3250 F_STARTUP_STAYOPEN, h_config_use_reg_start_for_stayopen, PREF_MISC, 0},
3251 {"use-resent-to-in-rules", "Use Resent-To in Rules",
3252 F_USE_RESENTTO, h_config_use_resentto, PREF_MISC, 0},
3253 {"use-subshell-for-suspend", "Use Subshell for Suspend",
3254 F_SUSPEND_SPAWNS, h_config_suspend_spawns, PREF_OS_SPWN, 0},
3255 #ifndef _WINDOWS
3256 {"use-system-translation", NULL,
3257 F_USE_SYSTEM_TRANS, h_config_use_system_translation, PREF_MISC, 0},
3258 #endif
3260 /* Hidden Features */
3261 {"old-growth", NULL,
3262 F_OLD_GROWTH, NO_HELP, PREF_NONE, 0},
3263 {"disable-config-cmd", NULL,
3264 F_DISABLE_CONFIG_SCREEN, h_config_disable_config_cmd, PREF_HIDDEN, 0},
3265 {"disable-keyboard-lock-cmd", NULL,
3266 F_DISABLE_KBLOCK_CMD, h_config_disable_kb_lock, PREF_HIDDEN, 0},
3267 {"disable-password-cmd", NULL,
3268 F_DISABLE_PASSWORD_CMD, h_config_disable_password_cmd, PREF_HIDDEN, 0},
3269 {"disable-pipes-in-sigs", NULL,
3270 F_DISABLE_PIPES_IN_SIGS, h_config_disable_pipes_in_sigs, PREF_HIDDEN, 0},
3271 {"disable-pipes-in-templates", NULL,
3272 F_DISABLE_PIPES_IN_TEMPLATES, h_config_disable_pipes_in_templates,
3273 PREF_HIDDEN, 0},
3274 {"disable-roles-setup-cmd", NULL,
3275 F_DISABLE_ROLES_SETUP, h_config_disable_roles_setup, PREF_HIDDEN, 0},
3276 {"disable-roles-sig-edit", NULL,
3277 F_DISABLE_ROLES_SIGEDIT, h_config_disable_roles_sigedit, PREF_HIDDEN, 0},
3278 {"disable-roles-template-edit", NULL,
3279 F_DISABLE_ROLES_TEMPLEDIT, h_config_disable_roles_templateedit,
3280 PREF_HIDDEN, 0},
3281 {"disable-setlocale-collate", NULL,
3282 F_DISABLE_SETLOCALE_COLLATE, h_config_disable_collate, PREF_HIDDEN, 0},
3283 {"disable-shared-namespaces", NULL,
3284 F_DISABLE_SHARED_NAMESPACES, h_config_disable_shared, PREF_HIDDEN, 0},
3285 {"disable-signature-edit-cmd", NULL,
3286 F_DISABLE_SIGEDIT_CMD, h_config_disable_signature_edit, PREF_HIDDEN, 0},
3287 {"new-thread-on-blank-subject", "New Thread on Blank Subject",
3288 F_NEW_THREAD_ON_BLANK_SUBJECT, h_config_new_thread_blank_subject, PREF_HIDDEN, 1},
3289 {"quell-personal-name-prompt", NULL,
3290 F_QUELL_PERSONAL_NAME_PROMPT, h_config_quell_personal_name_prompt, PREF_HIDDEN, 0},
3291 {"quell-user-id-prompt", "Quell User ID Prompt",
3292 F_QUELL_USER_ID_PROMPT, h_config_quell_user_id_prompt, PREF_HIDDEN, 0},
3293 #ifdef SMIME
3294 {"smime-dont-do-smime", "S/MIME -- Turn off S/MIME",
3295 F_DONT_DO_SMIME, h_config_smime_dont_do_smime, PREF_HIDDEN, 0},
3296 {"smime-encrypt-by-default", "S/MIME -- Encrypt by Default",
3297 F_ENCRYPT_DEFAULT_ON, h_config_smime_encrypt_by_default, PREF_HIDDEN, 0},
3298 {"smime-remember-passphrase", "S/MIME -- Remember S/MIME Passphrase",
3299 F_REMEMBER_SMIME_PASSPHRASE, h_config_smime_remember_passphrase, PREF_HIDDEN, 0},
3300 {"smime-sign-by-default", "S/MIME -- Sign by Default",
3301 F_SIGN_DEFAULT_ON, h_config_smime_sign_by_default, PREF_HIDDEN, 0},
3302 {"smime-use-store-only", "S/MIME -- Validate Using Certificate Store Only",
3303 F_USE_CERT_STORE_ONLY, h_config_smime_use_cert_store, PREF_HIDDEN, 1},
3304 #ifdef APPLEKEYCHAIN
3305 {"publiccerts-in-keychain", "S/MIME -- Public Certs in MacOS Keychain",
3306 F_PUBLICCERTS_IN_KEYCHAIN, h_config_smime_pubcerts_in_keychain, PREF_HIDDEN, 0},
3307 #endif
3308 #endif
3309 {"selectable-item-nobold", NULL,
3310 F_SLCTBL_ITEM_NOBOLD, NO_HELP, PREF_NONE, 0},
3311 {"send-confirms-only-expanded", NULL, /* exposed in Web Alpine */
3312 F_SEND_CONFIRM_ON_EXPAND, h_config_send_confirms_only_expanded, PREF_HIDDEN, 0},
3313 {"enable-jump-cmd", NULL, /* exposed in Web Alpine */
3314 F_ENABLE_JUMP_CMD, h_config_enable_jump_command, PREF_HIDDEN, 0},
3315 {"enable-newmail-sound", NULL, /* exposed in Web Alpine */
3316 F_ENABLE_NEWMAIL_SOUND, h_config_enable_newmail_sound, PREF_HIDDEN, 0},
3317 {"render-html-internally", NULL, /* exposed in Web Alpine */
3318 F_RENDER_HTML_INTERNALLY, h_config_render_html_internally, PREF_HIDDEN, 0}
3321 return((index >= 0 && index < (sizeof(feat_list)/sizeof(feat_list[0])))
3322 ? &feat_list[index] : NULL);
3327 * feature_list_index -- return index of given feature id in
3328 * feature list
3331 feature_list_index(int id)
3333 FEATURE_S *feature;
3334 int i;
3336 for(i = 0; (feature = feature_list(i)); i++)
3337 if(id == feature->id)
3338 return(i);
3340 return(-1);
3345 * feature_list_name -- return the given feature id's corresponding name
3347 char *
3348 feature_list_name(int id)
3350 FEATURE_S *f;
3352 return((f = feature_list(feature_list_index(id))) ? f->name : "");
3357 feature_list_id(char *name)
3359 FEATURE_S *f;
3360 int i;
3362 for(i = 0; (f = feature_list(i)); i++)
3363 if(!strucmp(f->name, name))
3364 return(f->id);
3366 return(-1);
3371 * feature_list_help -- return the given feature id's corresponding help
3373 HelpType
3374 feature_list_help(int id)
3376 FEATURE_S *f;
3378 return((f = feature_list(feature_list_index(id))) ? f->help : NO_HELP);
3383 * All the arguments past "list" are the backwards compatibility hacks.
3385 void
3386 process_feature_list(struct pine *ps, char **list, int old_growth, int hir, int osr)
3388 register char *q;
3389 char **p,
3390 *lvalue[BM_SIZE * 8];
3391 int i,
3392 yorn;
3393 long l;
3394 FEATURE_S *feat;
3397 /* clear all previous settings and reset them to default */
3398 for(i = 0; (feat = feature_list(i)) != NULL; i++)
3399 F_SET(feat->id, ps, feat->defval);
3401 /* backwards compatibility */
3402 if(hir)
3403 F_TURN_ON(F_INCLUDE_HEADER, ps);
3405 /* ditto */
3406 if(osr)
3407 F_TURN_ON(F_SIG_AT_BOTTOM, ps);
3409 /* ditto */
3410 if(old_growth)
3411 set_old_growth_bits(ps, 0);
3413 /* now run through the list (global, user, and cmd_line lists are here) */
3414 if(list){
3415 for(p = list; (q = *p) != NULL; p++){
3416 if(struncmp(q, "no-", 3) == 0){
3417 yorn = 0;
3418 q += 3;
3419 }else{
3420 yorn = 1;
3423 for(i = 0; (feat = feature_list(i)) != NULL; i++){
3424 if(strucmp(q, feat->name) == 0){
3425 if(feat->id == F_OLD_GROWTH){
3426 set_old_growth_bits(ps, yorn);
3427 }else{
3428 F_SET(feat->id, ps, yorn);
3430 break;
3434 /* if it wasn't in that list */
3435 if(feat == NULL)
3436 dprint((1,"Unrecognized feature in feature-list (%s%s)\n",
3437 (yorn ? "" : "no-"), q ? q : "?"));
3442 * Turn on gratuitous '>From ' quoting, if requested...
3444 mail_parameters(NULL, SET_FROMWIDGET,
3445 F_ON(F_QUOTE_ALL_FROMS, ps) ? VOIDT : NIL);
3448 * Turn off .lock creation complaints...
3450 if(F_ON(F_QUELL_LOCK_FAILURE_MSGS, ps))
3451 mail_parameters(NULL, SET_LOCKEACCESERROR, (void *) 0);
3454 * Turn on quelling of pseudo message.
3456 if(F_ON(F_QUELL_INTERNAL_MSG,ps_global))
3457 mail_parameters(NULL, SET_USERHASNOLIFE, (void *) 1);
3459 l = F_ON(F_MULNEWSRC_HOSTNAMES_AS_TYPED,ps_global) ? 0L : 1L;
3460 mail_parameters(NULL, SET_NEWSRCCANONHOST, (void *) l);
3462 ps->pass_ctrl_chars = F_ON(F_PASS_CONTROL_CHARS,ps_global) ? 1 : 0;
3463 ps->pass_c1_ctrl_chars = F_ON(F_PASS_C1_CONTROL_CHARS,ps_global) ? 1 : 0;
3465 #ifndef _WINDOWS
3466 if(F_ON(F_QUELL_BEZERK_TIMEZONE,ps_global))
3467 mail_parameters(NULL, SET_NOTIMEZONES, (void *) 1);
3468 #endif
3470 if(F_ON(F_USE_FK, ps))
3471 ps->orig_use_fkeys = 1;
3473 /* Will we have to build a new list? */
3474 if(!(old_growth || hir || osr))
3475 return;
3478 * Build a new list for feature-list. The only reason we ever need to
3479 * do this is if one of the obsolete options is being converted
3480 * into a feature-list item, and it isn't already included in the user's
3481 * feature-list.
3483 i = 0;
3484 for(p = LVAL(&ps->vars[V_FEATURE_LIST], Main);
3485 p && (q = *p); p++){
3486 /* already have it or cancelled it, don't need to add later */
3487 if(hir && (strucmp(q, "include-header-in-reply") == 0 ||
3488 strucmp(q, "no-include-header-in-reply") == 0)){
3489 hir = 0;
3490 }else if(osr && (strucmp(q, "signature-at-bottom") == 0 ||
3491 strucmp(q, "no-signature-at-bottom") == 0)){
3492 osr = 0;
3493 }else if(old_growth && (strucmp(q, "old-growth") == 0 ||
3494 strucmp(q, "no-old-growth") == 0)){
3495 old_growth = 0;
3497 lvalue[i++] = cpystr(q);
3500 /* check to see if we still need to build a new list */
3501 if(!(old_growth || hir || osr))
3502 return;
3504 if(hir)
3505 lvalue[i++] = "include-header-in-reply";
3506 if(osr)
3507 lvalue[i++] = "signature-at-bottom";
3508 if(old_growth)
3509 lvalue[i++] = "old-growth";
3510 lvalue[i] = NULL;
3511 set_variable_list(V_FEATURE_LIST, lvalue, TRUE, Main);
3515 void
3516 set_current_pattern_vals(struct pine *ps)
3518 struct variable *vars = ps->vars;
3520 set_current_val(&vars[V_PATTERNS], TRUE, TRUE);
3521 set_current_val(&vars[V_PAT_ROLES], TRUE, TRUE);
3522 set_current_val(&vars[V_PAT_FILTS], TRUE, TRUE);
3523 set_current_val(&vars[V_PAT_FILTS_OLD], TRUE, TRUE);
3524 set_current_val(&vars[V_PAT_SCORES], TRUE, TRUE);
3525 set_current_val(&vars[V_PAT_SCORES_OLD], TRUE, TRUE);
3526 set_current_val(&vars[V_PAT_INCOLS], TRUE, TRUE);
3527 set_current_val(&vars[V_PAT_OTHER], TRUE, TRUE);
3528 set_current_val(&vars[V_PAT_SRCH], TRUE, TRUE);
3531 * If old pattern variable (V_PATTERNS) is set and the new ones aren't
3532 * in the config file, then convert the old data into the new variables.
3533 * It isn't quite that simple, though, because we don't store unset
3534 * variables in remote pinercs. Check for the variables but if we
3535 * don't find any of them, also check the version number. This change was
3536 * made in version 4.30. We could just check that except that we're
3537 * worried somebody will make an incompatible version number change in
3538 * their local version, and will break this. So we check both the
3539 * version # and the var_in_pinerc things to be safer.
3541 if(vars[V_PATTERNS].current_val.l
3542 && vars[V_PATTERNS].current_val.l[0]
3543 && !var_in_pinerc(vars[V_PAT_ROLES].name)
3544 && !var_in_pinerc(vars[V_PAT_FILTS].name)
3545 && !var_in_pinerc(vars[V_PAT_FILTS_OLD].name)
3546 && !var_in_pinerc(vars[V_PAT_SCORES].name)
3547 && !var_in_pinerc(vars[V_PAT_SCORES_OLD].name)
3548 && !var_in_pinerc(vars[V_PAT_INCOLS].name)
3549 && isdigit((unsigned char) ps->pine_pre_vers[0])
3550 && ps->pine_pre_vers[1] == '.'
3551 && isdigit((unsigned char) ps->pine_pre_vers[2])
3552 && isdigit((unsigned char) ps->pine_pre_vers[3])
3553 && strncmp(ps->pine_pre_vers, "4.30", 4) < 0){
3554 convert_pattern_data();
3558 * Otherwise, if FILTS_OLD is set and FILTS isn't in the config file,
3559 * convert FILTS_OLD to FILTS. Same for SCORES.
3560 * The reason FILTS was changed was so we could change the
3561 * semantics of how rules work when there are pieces in the rule that
3562 * we don't understand. At the same time as the FILTS change we added
3563 * a rule to detect 8bitSubjects. So a user might have a filter that
3564 * deletes messages with 8bitSubjects. The problem is that that same
3565 * filter in a FILTS_OLD pine would match because it would ignore the
3566 * 8bitSubject part of the pattern and match on the rest. So we changed
3567 * the semantics so that rules with unknown bits would be ignored
3568 * instead of used. We had to change variable names at the same time
3569 * because we were adding the 8bit thing and the old pines are still
3570 * out there. Filters and Scores can both be dangerous. Roles, Colors,
3571 * and Other seem less dangerous so not worth adding a new variable.
3572 * This was changed in 4.50.
3574 else{
3575 if(vars[V_PAT_FILTS_OLD].current_val.l
3576 && vars[V_PAT_FILTS_OLD].current_val.l[0]
3577 && !var_in_pinerc(vars[V_PAT_FILTS].name)
3578 && !var_in_pinerc(vars[V_PAT_SCORES].name)
3579 && isdigit((unsigned char) ps->pine_pre_vers[0])
3580 && ps->pine_pre_vers[1] == '.'
3581 && isdigit((unsigned char) ps->pine_pre_vers[2])
3582 && isdigit((unsigned char) ps->pine_pre_vers[3])
3583 && strncmp(ps->pine_pre_vers, "4.50", 4) < 0){
3584 convert_filts_pattern_data();
3587 if(vars[V_PAT_SCORES_OLD].current_val.l
3588 && vars[V_PAT_SCORES_OLD].current_val.l[0]
3589 && !var_in_pinerc(vars[V_PAT_FILTS].name)
3590 && !var_in_pinerc(vars[V_PAT_SCORES].name)
3591 && isdigit((unsigned char) ps->pine_pre_vers[0])
3592 && ps->pine_pre_vers[1] == '.'
3593 && isdigit((unsigned char) ps->pine_pre_vers[2])
3594 && isdigit((unsigned char) ps->pine_pre_vers[3])
3595 && strncmp(ps->pine_pre_vers, "4.50", 4) < 0){
3596 convert_scores_pattern_data();
3600 if(vars[V_PAT_ROLES].post_user_val.l)
3601 ps_global->ew_for_role_take = Post;
3602 else
3603 ps_global->ew_for_role_take = Main;
3605 if(vars[V_PAT_FILTS].post_user_val.l)
3606 ps_global->ew_for_filter_take = Post;
3607 else
3608 ps_global->ew_for_filter_take = Main;
3610 if(vars[V_PAT_SCORES].post_user_val.l)
3611 ps_global->ew_for_score_take = Post;
3612 else
3613 ps_global->ew_for_score_take = Main;
3615 if(vars[V_PAT_INCOLS].post_user_val.l)
3616 ps_global->ew_for_incol_take = Post;
3617 else
3618 ps_global->ew_for_incol_take = Main;
3620 if(vars[V_PAT_OTHER].post_user_val.l)
3621 ps_global->ew_for_other_take = Post;
3622 else
3623 ps_global->ew_for_other_take = Main;
3625 if(vars[V_PAT_SRCH].post_user_val.l)
3626 ps_global->ew_for_srch_take = Post;
3627 else
3628 ps_global->ew_for_srch_take = Main;
3633 * Foreach of the config files;
3634 * transfer the data to the new variables.
3636 void
3637 convert_pattern_data(void)
3639 convert_pinerc_patterns(PAT_USE_MAIN);
3640 convert_pinerc_patterns(PAT_USE_POST);
3644 void
3645 convert_filts_pattern_data(void)
3647 convert_pinerc_filts_patterns(PAT_USE_MAIN);
3648 convert_pinerc_filts_patterns(PAT_USE_POST);
3652 void
3653 convert_scores_pattern_data(void)
3655 convert_pinerc_scores_patterns(PAT_USE_MAIN);
3656 convert_pinerc_scores_patterns(PAT_USE_POST);
3661 * Foreach of the four variables, transfer the data for this config file
3662 * from the old patterns variable. We don't have to convert OTHER patterns
3663 * or SRCH patterns because they didn't exist in pines without patterns-other.
3665 * If the original variable had patlines with type File then we convert
3666 * all of the individual patterns to type Lit, because each pattern can
3667 * be of any category. Lit patterns are better tested, anyway.
3669 void
3670 convert_pinerc_patterns(long int use_flags)
3672 long old_rflags;
3673 long rflags;
3674 PAT_S *pat;
3675 PAT_STATE pstate;
3676 ACTION_S *act;
3678 old_rflags = (ROLE_OLD_PAT | use_flags);
3680 rflags = 0L;
3681 if(any_patterns(old_rflags, &pstate)){
3682 dprint((2, "converting old patterns to new (%s)\n", (use_flags == PAT_USE_MAIN) ? "Main" : "Post"));
3683 for(pat = first_pattern(&pstate);
3684 pat;
3685 pat = next_pattern(&pstate)){
3686 if((act = pat->action) != NULL){
3687 if(act->is_a_role &&
3688 add_to_pattern(pat, ROLE_DO_ROLES | use_flags))
3689 rflags |= ROLE_DO_ROLES;
3690 if(act->is_a_incol &&
3691 add_to_pattern(pat, ROLE_DO_INCOLS | use_flags))
3692 rflags |= ROLE_DO_INCOLS;
3693 if(act->is_a_score &&
3694 add_to_pattern(pat, ROLE_DO_SCORES | use_flags))
3695 rflags |= ROLE_DO_SCORES;
3696 if(act->is_a_filter &&
3697 add_to_pattern(pat, ROLE_DO_FILTER | use_flags))
3698 rflags |= ROLE_DO_FILTER;
3702 if(rflags)
3703 if(write_patterns(rflags | use_flags))
3704 dprint((1,
3705 "Trouble converting patterns to new variable\n"));
3711 * If the original variable had patlines with type File then we convert
3712 * all of the individual patterns to type Lit, because each pattern can
3713 * be of any category. Lit patterns are better tested, anyway.
3715 void
3716 convert_pinerc_filts_patterns(long int use_flags)
3718 long old_rflags;
3719 long rflags;
3720 PAT_S *pat;
3721 PAT_STATE pstate;
3722 ACTION_S *act;
3724 old_rflags = (ROLE_OLD_FILT | use_flags);
3726 rflags = 0L;
3727 if(any_patterns(old_rflags, &pstate)){
3728 dprint((2, "converting old filter patterns to new (%s)\n", (use_flags == PAT_USE_MAIN) ? "Main" : "Post"));
3729 for(pat = first_pattern(&pstate);
3730 pat;
3731 pat = next_pattern(&pstate)){
3732 if((act = pat->action) != NULL){
3733 if(act->is_a_filter &&
3734 add_to_pattern(pat, ROLE_DO_FILTER | use_flags))
3735 rflags |= ROLE_DO_FILTER;
3739 if(rflags)
3740 if(write_patterns(rflags | use_flags))
3741 dprint((1,
3742 "Trouble converting filter patterns to new variable\n"));
3748 * If the original variable had patlines with type File then we convert
3749 * all of the individual patterns to type Lit, because each pattern can
3750 * be of any category. Lit patterns are better tested, anyway.
3752 void
3753 convert_pinerc_scores_patterns(long int use_flags)
3755 long old_rflags;
3756 long rflags;
3757 PAT_S *pat;
3758 PAT_STATE pstate;
3759 ACTION_S *act;
3761 old_rflags = (ROLE_OLD_SCORE | use_flags);
3763 rflags = 0L;
3764 if(any_patterns(old_rflags, &pstate)){
3765 dprint((2, "converting old scores patterns to new (%s)\n", (use_flags == PAT_USE_MAIN) ? "Main" : "Post"));
3766 for(pat = first_pattern(&pstate);
3767 pat;
3768 pat = next_pattern(&pstate)){
3769 if((act = pat->action) != NULL){
3770 if(act->is_a_score &&
3771 add_to_pattern(pat, ROLE_DO_SCORES | use_flags))
3772 rflags |= ROLE_DO_SCORES;
3776 if(rflags)
3777 if(write_patterns(rflags | use_flags))
3778 dprint((1,
3779 "Trouble converting scores patterns to new variable\n"));
3785 * set_old_growth_bits - Command used to set or unset old growth set
3786 * of features
3788 void
3789 set_old_growth_bits(struct pine *ps, int val)
3791 int i;
3793 for(i = 1; i <= F_FEATURE_LIST_COUNT; i++)
3794 if(test_old_growth_bits(ps, i))
3795 F_SET(i, ps, val);
3801 * test_old_growth_bits - Test to see if all the old growth bits are on,
3802 * *or* if a particular feature index is in the old
3803 * growth set.
3805 * WEIRD ALERT: if index == F_OLD_GROWTH bit values are tested
3806 * otherwise a bits existence in the set is tested!!!
3808 * BUG: this will break if an old growth feature number is ever >= 32.
3811 test_old_growth_bits(struct pine *ps, int index)
3814 * this list defines F_OLD_GROWTH set
3816 static unsigned long old_growth_bits = ((1 << F_ENABLE_FULL_HDR) |
3817 (1 << F_ENABLE_PIPE) |
3818 (1 << F_ENABLE_TAB_COMPLETE) |
3819 (1 << F_QUIT_WO_CONFIRM) |
3820 (1 << F_ENABLE_JUMP) |
3821 (1 << F_ENABLE_ALT_ED) |
3822 (1 << F_ENABLE_BOUNCE) |
3823 (1 << F_ENABLE_AGG_OPS) |
3824 (1 << F_ENABLE_FLAG) |
3825 (1 << F_CAN_SUSPEND));
3826 if(index >= 32)
3827 return(0);
3829 if(index == F_OLD_GROWTH){
3830 for(index = 1; index <= F_FEATURE_LIST_COUNT; index++)
3831 if(((1 << index) & old_growth_bits) && F_OFF(index, ps))
3832 return(0);
3834 return(1);
3836 else
3837 return((1 << index) & old_growth_bits);
3842 * Side effect is that the appropriate global variable is set, and the
3843 * appropriate current_val is set.
3845 void
3846 cur_rule_value(struct variable *var, int expand, int cmdline)
3848 int i;
3849 NAMEVAL_S *v;
3851 set_current_val(var, expand, cmdline);
3853 if(var == &ps_global->vars[V_SAVED_MSG_NAME_RULE]){
3854 if(ps_global->VAR_SAVED_MSG_NAME_RULE)
3855 for(i = 0; (v = save_msg_rules(i)); i++)
3856 if(!strucmp(ps_global->VAR_SAVED_MSG_NAME_RULE, S_OR_L(v))){
3857 ps_global->save_msg_rule = v->value;
3858 break;
3861 #ifndef _WINDOWS
3862 else if(var == &ps_global->vars[V_COLOR_STYLE]){
3863 if(ps_global->VAR_COLOR_STYLE)
3864 for(i = 0; (v = col_style(i)); i++)
3865 if(!strucmp(ps_global->VAR_COLOR_STYLE, S_OR_L(v))){
3866 ps_global->color_style = v->value;
3867 break;
3870 #endif
3871 else if(var == &ps_global->vars[V_INDEX_COLOR_STYLE]){
3872 if(ps_global->VAR_INDEX_COLOR_STYLE)
3873 for(i = 0; (v = index_col_style(i)); i++)
3874 if(!strucmp(ps_global->VAR_INDEX_COLOR_STYLE, S_OR_L(v))){
3875 ps_global->index_color_style = v->value;
3876 break;
3879 else if(var == &ps_global->vars[V_TITLEBAR_COLOR_STYLE]){
3880 if(ps_global->VAR_TITLEBAR_COLOR_STYLE)
3881 for(i = 0; (v = titlebar_col_style(i)); i++)
3882 if(!strucmp(ps_global->VAR_TITLEBAR_COLOR_STYLE, S_OR_L(v))){
3883 ps_global->titlebar_color_style = v->value;
3884 break;
3887 else if(var == &ps_global->vars[V_FCC_RULE]){
3888 if(ps_global->VAR_FCC_RULE)
3889 for(i = 0; (v = fcc_rules(i)); i++)
3890 if(!strucmp(ps_global->VAR_FCC_RULE, S_OR_L(v))){
3891 ps_global->fcc_rule = v->value;
3892 break;
3895 else if(var == &ps_global->vars[V_GOTO_DEFAULT_RULE]){
3896 if(ps_global->VAR_GOTO_DEFAULT_RULE)
3897 for(i = 0; (v = goto_rules(i)); i++)
3898 if(!strucmp(ps_global->VAR_GOTO_DEFAULT_RULE, S_OR_L(v))){
3899 ps_global->goto_default_rule = v->value;
3900 break;
3903 else if(var == &ps_global->vars[V_INCOMING_STARTUP]){
3904 if(ps_global->VAR_INCOMING_STARTUP)
3905 for(i = 0; (v = incoming_startup_rules(i)); i++)
3906 if(!strucmp(ps_global->VAR_INCOMING_STARTUP, S_OR_L(v))){
3907 ps_global->inc_startup_rule = v->value;
3908 break;
3911 else if(var == &ps_global->vars[V_PRUNING_RULE]){
3912 if(ps_global->VAR_PRUNING_RULE)
3913 for(i = 0; (v = pruning_rules(i)); i++)
3914 if(!strucmp(ps_global->VAR_PRUNING_RULE, S_OR_L(v))){
3915 ps_global->pruning_rule = v->value;
3916 break;
3919 else if(var == &ps_global->vars[V_REOPEN_RULE]){
3920 if(ps_global->VAR_REOPEN_RULE)
3921 for(i = 0; (v = reopen_rules(i)); i++)
3922 if(!strucmp(ps_global->VAR_REOPEN_RULE, S_OR_L(v))){
3923 ps_global->reopen_rule = v->value;
3924 break;
3927 else if(var == &ps_global->vars[V_FLD_SORT_RULE]){
3928 if(ps_global->VAR_FLD_SORT_RULE)
3929 for(i = 0; (v = fld_sort_rules(i)); i++)
3930 if(!strucmp(ps_global->VAR_FLD_SORT_RULE, S_OR_L(v))){
3931 ps_global->fld_sort_rule = v->value;
3932 break;
3935 else if(var == &ps_global->vars[V_AB_SORT_RULE]){
3936 if(ps_global->VAR_AB_SORT_RULE)
3937 for(i = 0; (v = ab_sort_rules(i)); i++)
3938 if(!strucmp(ps_global->VAR_AB_SORT_RULE, S_OR_L(v))){
3939 ps_global->ab_sort_rule = v->value;
3940 break;
3943 else if(var == &ps_global->vars[V_THREAD_DISP_STYLE]){
3944 if(ps_global->VAR_THREAD_DISP_STYLE)
3945 for(i = 0; (v = thread_disp_styles(i)); i++)
3946 if(!strucmp(ps_global->VAR_THREAD_DISP_STYLE, S_OR_L(v))){
3947 ps_global->thread_disp_style = v->value;
3948 break;
3951 else if(var == &ps_global->vars[V_THREAD_INDEX_STYLE]){
3952 if(ps_global->VAR_THREAD_INDEX_STYLE)
3953 for(i = 0; (v = thread_index_styles(i)); i++)
3954 if(!strucmp(ps_global->VAR_THREAD_INDEX_STYLE, S_OR_L(v))){
3955 ps_global->thread_index_style = v->value;
3956 break;
3963 * Standard way to get at save message rules...
3965 NAMEVAL_S *
3966 save_msg_rules(int index)
3968 static NAMEVAL_S save_rules[] = {
3969 {"by-from", NULL, SAV_RULE_FROM},
3970 {"by-nick-of-from", NULL, SAV_RULE_NICK_FROM_DEF},
3971 {"by-nick-of-from-then-from", NULL, SAV_RULE_NICK_FROM},
3972 {"by-fcc-of-from", NULL, SAV_RULE_FCC_FROM_DEF},
3973 {"by-fcc-of-from-then-from", NULL, SAV_RULE_FCC_FROM},
3974 {"by-realname-of-from", NULL, SAV_RULE_RN_FROM_DEF},
3975 {"by-realname-of-from-then-from", NULL, SAV_RULE_RN_FROM},
3976 {"by-sender", NULL, SAV_RULE_SENDER},
3977 {"by-nick-of-sender", NULL, SAV_RULE_NICK_SENDER_DEF},
3978 {"by-nick-of-sender-then-sender", NULL, SAV_RULE_NICK_SENDER},
3979 {"by-fcc-of-sender", NULL, SAV_RULE_FCC_SENDER_DEF},
3980 {"by-fcc-of-sender-then-sender", NULL, SAV_RULE_FCC_SENDER},
3981 {"by-realname-of-sender", NULL, SAV_RULE_RN_SENDER_DEF},
3982 {"by-realname-of-sender-then-sender", NULL, SAV_RULE_RN_SENDER},
3983 {"by-recipient", NULL, SAV_RULE_RECIP},
3984 {"by-nick-of-recip", NULL, SAV_RULE_NICK_RECIP_DEF},
3985 {"by-nick-of-recip-then-recip", NULL, SAV_RULE_NICK_RECIP},
3986 {"by-fcc-of-recip", NULL, SAV_RULE_FCC_RECIP_DEF},
3987 {"by-fcc-of-recip-then-recip", NULL, SAV_RULE_FCC_RECIP},
3988 {"by-realname-of-recip", NULL, SAV_RULE_RN_RECIP_DEF},
3989 {"by-realname-of-recip-then-recip", NULL, SAV_RULE_RN_RECIP},
3990 {"by-replyto", NULL, SAV_RULE_REPLYTO},
3991 {"by-nick-of-replyto", NULL, SAV_RULE_NICK_REPLYTO_DEF},
3992 {"by-nick-of-replyto-then-replyto", NULL, SAV_RULE_NICK_REPLYTO},
3993 {"by-fcc-of-replyto", NULL, SAV_RULE_FCC_REPLYTO_DEF},
3994 {"by-fcc-of-replyto-then-replyto", NULL, SAV_RULE_FCC_REPLYTO},
3995 {"by-realname-of-replyto", NULL, SAV_RULE_RN_REPLYTO_DEF},
3996 {"by-realname-of-replyto-then-replyto", NULL, SAV_RULE_RN_REPLYTO},
3997 {"last-folder-used", NULL, SAV_RULE_LAST},
3998 {"default-folder", NULL, SAV_RULE_DEFLT}
4001 return((index >= 0 && index < (sizeof(save_rules)/sizeof(save_rules[0])))
4002 ? &save_rules[index] : NULL);
4007 * Standard way to get at fcc rules...
4009 NAMEVAL_S *
4010 fcc_rules(int index)
4012 static NAMEVAL_S f_rules[] = {
4013 {"default-fcc", NULL, FCC_RULE_DEFLT},
4014 {"last-fcc-used", NULL, FCC_RULE_LAST},
4015 {"by-recipient", NULL, FCC_RULE_RECIP},
4016 {"by-nickname", NULL, FCC_RULE_NICK},
4017 {"by-nick-then-recip", NULL, FCC_RULE_NICK_RECIP},
4018 {"current-folder", NULL, FCC_RULE_CURRENT}
4021 return((index >= 0 && index < (sizeof(f_rules)/sizeof(f_rules[0])))
4022 ? &f_rules[index] : NULL);
4027 * Standard way to get at addrbook sort rules...
4029 NAMEVAL_S *
4030 ab_sort_rules(int index)
4032 static NAMEVAL_S ab_rules[] = {
4033 {"fullname-with-lists-last", NULL, AB_SORT_RULE_FULL_LISTS},
4034 {"fullname", NULL, AB_SORT_RULE_FULL},
4035 {"nickname-with-lists-last", NULL, AB_SORT_RULE_NICK_LISTS},
4036 {"nickname", NULL, AB_SORT_RULE_NICK},
4037 {"dont-sort", NULL, AB_SORT_RULE_NONE}
4040 return((index >= 0 && index < (sizeof(ab_rules)/sizeof(ab_rules[0])))
4041 ? &ab_rules[index] : NULL);
4046 * Standard way to get at color styles.
4048 NAMEVAL_S *
4049 col_style(int index)
4051 static NAMEVAL_S col_styles[] = {
4052 {"no-color", NULL, COL_NONE},
4053 {"use-termdef", NULL, COL_TERMDEF},
4054 {"force-ansi-8color", NULL, COL_ANSI8},
4055 {"force-ansi-16color", NULL, COL_ANSI16},
4056 {"force-xterm-256color", NULL, COL_ANSI256}
4059 return((index >= 0 && index < (sizeof(col_styles)/sizeof(col_styles[0])))
4060 ? &col_styles[index] : NULL);
4065 * Standard way to get at index color styles.
4067 NAMEVAL_S *
4068 index_col_style(int index)
4070 static NAMEVAL_S ind_col_styles[] = {
4071 {"flip-colors", NULL, IND_COL_FLIP},
4072 {"reverse", NULL, IND_COL_REV},
4073 {"reverse-fg", NULL, IND_COL_FG},
4074 {"reverse-fg-no-ambiguity", NULL, IND_COL_FG_NOAMBIG},
4075 {"reverse-bg", NULL, IND_COL_BG},
4076 {"reverse-bg-no-ambiguity", NULL, IND_COL_BG_NOAMBIG}
4079 return((index >= 0 && index < (sizeof(ind_col_styles)/sizeof(ind_col_styles[0]))) ? &ind_col_styles[index] : NULL);
4084 * Standard way to get at titlebar color styles.
4086 NAMEVAL_S *
4087 titlebar_col_style(int index)
4089 static NAMEVAL_S tbar_col_styles[] = {
4090 {"default", NULL, TBAR_COLOR_DEFAULT},
4091 {"indexline", NULL, TBAR_COLOR_INDEXLINE},
4092 {"reverse-indexline", NULL, TBAR_COLOR_REV_INDEXLINE}
4095 return((index >= 0 && index < (sizeof(tbar_col_styles)/sizeof(tbar_col_styles[0]))) ? &tbar_col_styles[index] : NULL);
4100 * Standard way to get at folder sort rules...
4102 NAMEVAL_S *
4103 fld_sort_rules(int index)
4105 static NAMEVAL_S fdl_rules[] = {
4106 {"alphabetical", NULL, FLD_SORT_ALPHA},
4107 {"alpha-with-dirs-last", NULL, FLD_SORT_ALPHA_DIR_LAST},
4108 {"alpha-with-dirs-first", NULL, FLD_SORT_ALPHA_DIR_FIRST}
4111 return((index >= 0 && index < (sizeof(fdl_rules)/sizeof(fdl_rules[0])))
4112 ? &fdl_rules[index] : NULL);
4117 * Standard way to get at incoming startup rules...
4119 NAMEVAL_S *
4120 incoming_startup_rules(int index)
4122 static NAMEVAL_S is_rules[] = {
4123 {"first-unseen", NULL, IS_FIRST_UNSEEN},
4124 {"first-recent", NULL, IS_FIRST_RECENT},
4125 {"first-important", NULL, IS_FIRST_IMPORTANT},
4126 {"first-important-or-unseen", NULL, IS_FIRST_IMPORTANT_OR_UNSEEN},
4127 {"first-important-or-recent", NULL, IS_FIRST_IMPORTANT_OR_RECENT},
4128 {"first", NULL, IS_FIRST},
4129 {"last", NULL, IS_LAST}
4132 return((index >= 0 && index < (sizeof(is_rules)/sizeof(is_rules[0])))
4133 ? &is_rules[index] : NULL);
4137 NAMEVAL_S *
4138 startup_rules(int index)
4140 static NAMEVAL_S is2_rules[] = {
4141 {"first-unseen", NULL, IS_FIRST_UNSEEN},
4142 {"first-recent", NULL, IS_FIRST_RECENT},
4143 {"first-important", NULL, IS_FIRST_IMPORTANT},
4144 {"first-important-or-unseen", NULL, IS_FIRST_IMPORTANT_OR_UNSEEN},
4145 {"first-important-or-recent", NULL, IS_FIRST_IMPORTANT_OR_RECENT},
4146 {"first", NULL, IS_FIRST},
4147 {"last", NULL, IS_LAST},
4148 {"default", NULL, IS_NOTSET}
4151 return((index >= 0 && index < (sizeof(is2_rules)/sizeof(is2_rules[0])))
4152 ? &is2_rules[index] : NULL);
4157 * Standard way to get at pruning-rule values.
4159 NAMEVAL_S *
4160 pruning_rules(int index)
4162 static NAMEVAL_S pr_rules[] = {
4163 {"ask about rename, ask about deleting","ask-ask", PRUNE_ASK_AND_ASK},
4164 {"ask about rename, don't delete", "ask-no", PRUNE_ASK_AND_NO},
4165 {"always rename, ask about deleting", "yes-ask", PRUNE_YES_AND_ASK},
4166 {"always rename, don't delete", "yes-no", PRUNE_YES_AND_NO},
4167 {"don't rename, ask about deleting", "no-ask", PRUNE_NO_AND_ASK},
4168 {"don't rename, don't delete", "no-no", PRUNE_NO_AND_NO}
4171 return((index >= 0 && index < (sizeof(pr_rules)/sizeof(pr_rules[0])))
4172 ? &pr_rules[index] : NULL);
4177 * Standard way to get at reopen-rule values.
4179 NAMEVAL_S *
4180 reopen_rules(int index)
4182 static NAMEVAL_S ro_rules[] = {
4183 /* TRANSLATORS: short description of a feature option */
4184 {"Always reopen", "yes-yes",
4185 REOPEN_YES_YES},
4186 /* TRANSLATORS: short description of a feature option, default in brackets */
4187 {"Yes for POP/NNTP, Ask about other remote [Yes]", "yes-ask-y",
4188 REOPEN_YES_ASK_Y},
4189 /* TRANSLATORS: short description of a feature option, default in brackets */
4190 {"Yes for POP/NNTP, Ask about other remote [No]", "yes-ask-n",
4191 REOPEN_YES_ASK_N},
4192 /* TRANSLATORS: short description of a feature option */
4193 {"Yes for POP/NNTP, No for other remote", "yes-no",
4194 REOPEN_YES_NO},
4195 /* TRANSLATORS: short description of a feature option, default in brackets */
4196 {"Always ask [Yes]", "ask-ask-y",
4197 REOPEN_ASK_ASK_Y},
4198 /* TRANSLATORS: short description of a feature option, default in brackets */
4199 {"Always ask [No]", "ask-ask-n",
4200 REOPEN_ASK_ASK_N},
4201 /* TRANSLATORS: short description of a feature option, default in brackets */
4202 {"Ask about POP/NNTP [Yes], No for other remote", "ask-no-y",
4203 REOPEN_ASK_NO_Y},
4204 /* TRANSLATORS: short description of a feature option, default in brackets */
4205 {"Ask about POP/NNTP [No], No for other remote", "ask-no-n",
4206 REOPEN_ASK_NO_N},
4207 /* TRANSLATORS: short description of a feature option */
4208 {"Never reopen", "no-no",
4209 REOPEN_NO_NO},
4212 return((index >= 0 && index < (sizeof(ro_rules)/sizeof(ro_rules[0])))
4213 ? &ro_rules[index] : NULL);
4218 * Standard way to get at thread_disp_style values.
4220 NAMEVAL_S *
4221 thread_disp_styles(int index)
4223 static NAMEVAL_S td_styles[] = {
4224 {"none", "none", THREAD_NONE},
4225 {"show-thread-structure", "struct", THREAD_STRUCT},
4226 {"mutt-like", "mutt", THREAD_MUTTLIKE},
4227 {"indent-subject-1", "subj1", THREAD_INDENT_SUBJ1},
4228 {"indent-subject-2", "subj2", THREAD_INDENT_SUBJ2},
4229 {"indent-from-1", "from1", THREAD_INDENT_FROM1},
4230 {"indent-from-2", "from2", THREAD_INDENT_FROM2},
4231 {"show-structure-in-from", "struct-from", THREAD_STRUCT_FROM}
4234 return((index >= 0 && index < (sizeof(td_styles)/sizeof(td_styles[0])))
4235 ? &td_styles[index] : NULL);
4240 * Standard way to get at thread_index_style values.
4242 NAMEVAL_S *
4243 thread_index_styles(int index)
4245 static NAMEVAL_S ti_styles[] = {
4246 {"regular-index-with-expanded-threads", "exp", THRDINDX_EXP},
4247 {"regular-index-with-collapsed-threads","coll", THRDINDX_COLL},
4248 {"separate-index-screen-always", "sep", THRDINDX_SEP},
4249 {"separate-index-screen-except-for-single-messages","sep-auto",
4250 THRDINDX_SEP_AUTO}
4253 return((index >= 0 && index < (sizeof(ti_styles)/sizeof(ti_styles[0])))
4254 ? &ti_styles[index] : NULL);
4259 * Standard way to get at goto default rules...
4261 NAMEVAL_S *
4262 goto_rules(int index)
4264 static NAMEVAL_S g_rules[] = {
4265 {"folder-in-first-collection", NULL, GOTO_FIRST_CLCTN},
4266 {"inbox-or-folder-in-first-collection", NULL, GOTO_INBOX_FIRST_CLCTN},
4267 {"inbox-or-folder-in-recent-collection", NULL, GOTO_INBOX_RECENT_CLCTN},
4268 {"first-collection-with-inbox-default", NULL, GOTO_FIRST_CLCTN_DEF_INBOX},
4269 {"most-recent-folder", NULL, GOTO_LAST_FLDR}
4272 return((index >= 0 && index < (sizeof(g_rules)/sizeof(g_rules[0])))
4273 ? &g_rules[index] : NULL);
4277 NAMEVAL_S *
4278 pat_fldr_types(int index)
4280 static NAMEVAL_S pat_fldr_list[] = {
4281 {"Any", "ANY", FLDR_ANY},
4282 {"News", "NEWS", FLDR_NEWS},
4283 {"Email", "EMAIL", FLDR_EMAIL},
4284 {"Specific (Enter Incoming Nicknames or use ^T)", "SPEC", FLDR_SPECIFIC}
4287 return((index >= 0 &&
4288 index < (sizeof(pat_fldr_list)/sizeof(pat_fldr_list[0])))
4289 ? &pat_fldr_list[index] : NULL);
4293 NAMEVAL_S *
4294 inabook_fldr_types(int indexarg)
4296 static NAMEVAL_S inabook_fldr_list[] = {
4297 {"Don't care, always matches", "E", IAB_EITHER},
4298 {"Yes, in any address book", "YES", IAB_YES},
4299 {"No, not in any address book", "NO", IAB_NO},
4300 {"Yes, in specific address books", "SYES", IAB_SPEC_YES},
4301 {"No, not in any of specific address books", "SNO", IAB_SPEC_NO}
4304 int index = indexarg & IAB_TYPE_MASK;
4306 return((index >= 0 &&
4307 index < (sizeof(inabook_fldr_list)/sizeof(inabook_fldr_list[0])))
4308 ? &inabook_fldr_list[index] : NULL);
4312 NAMEVAL_S *
4313 filter_types(int index)
4315 static NAMEVAL_S filter_type_list[] = {
4316 {"Just Set Message Status", "NONE", FILTER_STATE},
4317 {"Delete", "DEL", FILTER_KILL},
4318 {"Move (Enter folder name(s) in primary collection, or use ^T)",
4319 "FLDR", FILTER_FOLDER}
4322 return((index >= 0 &&
4323 index < (sizeof(filter_type_list)/sizeof(filter_type_list[0])))
4324 ? &filter_type_list[index] : NULL);
4328 NAMEVAL_S *
4329 role_repl_types(int index)
4331 static NAMEVAL_S role_repl_list[] = {
4332 {"Never", "NO", ROLE_REPL_NO},
4333 {"With confirmation", "YES", ROLE_REPL_YES},
4334 {"Without confirmation", "NC", ROLE_REPL_NOCONF}
4337 return((index >= 0 &&
4338 index < (sizeof(role_repl_list)/sizeof(role_repl_list[0])))
4339 ? &role_repl_list[index] : NULL);
4343 NAMEVAL_S *
4344 role_forw_types(int index)
4346 static NAMEVAL_S role_forw_list[] = {
4347 {"Never", "NO", ROLE_FORW_NO},
4348 {"With confirmation", "YES", ROLE_FORW_YES},
4349 {"Without confirmation", "NC", ROLE_FORW_NOCONF}
4352 return((index >= 0 &&
4353 index < (sizeof(role_forw_list)/sizeof(role_forw_list[0])))
4354 ? &role_forw_list[index] : NULL);
4358 NAMEVAL_S *
4359 role_comp_types(int index)
4361 static NAMEVAL_S role_comp_list[] = {
4362 {"Never", "NO", ROLE_COMP_NO},
4363 {"With confirmation", "YES", ROLE_COMP_YES},
4364 {"Without confirmation", "NC", ROLE_COMP_NOCONF}
4367 return((index >= 0 &&
4368 index < (sizeof(role_comp_list)/sizeof(role_comp_list[0])))
4369 ? &role_comp_list[index] : NULL);
4373 NAMEVAL_S *
4374 role_status_types(int index)
4376 static NAMEVAL_S role_status_list[] = {
4377 {"Don't care, always matches", "E", PAT_STAT_EITHER},
4378 {"Yes", "YES", PAT_STAT_YES},
4379 {"No", "NO", PAT_STAT_NO}
4382 return((index >= 0 &&
4383 index < (sizeof(role_status_list)/sizeof(role_status_list[0])))
4384 ? &role_status_list[index] : NULL);
4388 NAMEVAL_S *
4389 msg_state_types(int index)
4391 static NAMEVAL_S msg_state_list[] = {
4392 {"Don't change it", "LV", ACT_STAT_LEAVE},
4393 {"Set this state", "SET", ACT_STAT_SET},
4394 {"Clear this state", "CLR", ACT_STAT_CLEAR}
4397 return((index >= 0 &&
4398 index < (sizeof(msg_state_list)/sizeof(msg_state_list[0])))
4399 ? &msg_state_list[index] : NULL);
4403 #ifdef ENABLE_LDAP
4404 NAMEVAL_S *
4405 ldap_search_rules(int index)
4407 static NAMEVAL_S ldap_search_list[] = {
4408 {"contains", NULL, LDAP_SRCH_CONTAINS},
4409 {"equals", NULL, LDAP_SRCH_EQUALS},
4410 {"begins-with", NULL, LDAP_SRCH_BEGINS},
4411 {"ends-with", NULL, LDAP_SRCH_ENDS}
4414 return((index >= 0 &&
4415 index < (sizeof(ldap_search_list)/sizeof(ldap_search_list[0])))
4416 ? &ldap_search_list[index] : NULL);
4420 NAMEVAL_S *
4421 ldap_search_types(int index)
4423 static NAMEVAL_S ldap_types_list[] = {
4424 {"name", NULL, LDAP_TYPE_CN},
4425 {"surname", NULL, LDAP_TYPE_SUR},
4426 {"givenname", NULL, LDAP_TYPE_GIVEN},
4427 {"email", NULL, LDAP_TYPE_EMAIL},
4428 {"name-or-email", NULL, LDAP_TYPE_CN_EMAIL},
4429 {"surname-or-givenname", NULL, LDAP_TYPE_SUR_GIVEN},
4430 {"sur-or-given-or-name-or-email", NULL, LDAP_TYPE_SEVERAL}
4433 return((index >= 0 &&
4434 index < (sizeof(ldap_types_list)/sizeof(ldap_types_list[0])))
4435 ? &ldap_types_list[index] : NULL);
4439 NAMEVAL_S *
4440 ldap_search_scope(int index)
4442 static NAMEVAL_S ldap_scope_list[] = {
4443 {"base", NULL, LDAP_SCOPE_BASE},
4444 {"onelevel", NULL, LDAP_SCOPE_ONELEVEL},
4445 {"subtree", NULL, LDAP_SCOPE_SUBTREE}
4448 return((index >= 0 &&
4449 index < (sizeof(ldap_scope_list)/sizeof(ldap_scope_list[0])))
4450 ? &ldap_scope_list[index] : NULL);
4452 #endif
4456 * Choose from the global default, command line args, pinerc values to set
4457 * the actual value of the variable that we will use. Start at the top
4458 * and work down from higher to lower precedence.
4459 * For lists, we may inherit values from lower precedence
4460 * versions if that's the way the user specifies it.
4461 * The user can put INHERIT_DEFAULT as the first entry in a list and that
4462 * means it will inherit the current values, for example the values
4463 * from the global_val, or the value from the main_user_val could be
4464 * inherited in the post_user_val.
4466 void
4467 set_current_val(struct variable *var, int expand, int cmdline)
4469 int is_set[5], is_inherit[5];
4470 int i, j, k, cnt, start;
4471 char **tmp, **t, **list[5];
4472 char *p;
4474 dprint((9,
4475 "set_current_val(var=%s%s, expand=%d, cmdline=%d)\n",
4476 (var && var->name) ? var->name : "?",
4477 (var && var->is_list) ? " (list)" : "",
4478 expand, cmdline));
4480 if(!var)
4481 return;
4483 if(var->is_list){ /* variable is a list */
4485 for(j = 0; j < 5; j++){
4486 t = j==0 ? var->global_val.l :
4487 j==1 ? var->main_user_val.l :
4488 j==2 ? var->post_user_val.l :
4489 j==3 ? ((cmdline) ? var->cmdline_val.l : NULL) :
4490 var->fixed_val.l;
4492 is_set[j] = is_inherit[j] = 0;
4493 list[j] = NULL;
4495 if(t){
4496 if(!expand){
4497 is_set[j]++;
4498 list[j] = t;
4500 else{
4501 for(i = 0; t[i]; i++){
4502 if(expand_variables(tmp_20k_buf, SIZEOF_20KBUF, t[i],
4503 0)){
4504 /* successful expand */
4505 is_set[j]++;
4506 list[j] = t;
4507 break;
4512 if(list[j] && list[j][0] && !strcmp(list[j][0],INHERIT))
4513 is_inherit[j]++;
4517 cnt = 0;
4518 start = 0;
4519 /* count how many items in current_val list */
4520 /* Admin wants default, which is global_val. */
4521 if(var->is_fixed && var->fixed_val.l == NULL){
4522 cnt = 0;
4523 if(is_set[0]){
4524 for(; list[0][cnt]; cnt++)
4528 else{
4529 for(j = 0; j < 5; j++){
4530 if(is_set[j]){
4531 if(!is_inherit[j]){
4532 cnt = 0; /* reset */
4533 start = j;
4536 for(i = is_inherit[j] ? 1 : 0; list[j][i]; i++)
4537 cnt++;
4542 free_list_array(&var->current_val.l); /* clean up any old values */
4544 /* check to see if anything is set */
4545 if(is_set[0] + is_set[1] + is_set[2] + is_set[3] + is_set[4] > 0){
4546 var->current_val.l = (char **)fs_get((cnt+1)*sizeof(char *));
4547 tmp = var->current_val.l;
4548 if(var->is_fixed && var->fixed_val.l == NULL){
4549 if(is_set[0]){
4550 for(i = 0; list[0][i]; i++){
4551 if(!expand)
4552 *tmp++ = cpystr(list[0][i]);
4553 else if(expand_variables(tmp_20k_buf, SIZEOF_20KBUF,
4554 list[0][i], 0))
4555 *tmp++ = cpystr(tmp_20k_buf);
4559 else{
4560 for(j = start; j < 5; j++){
4561 if(is_set[j]){
4562 for(i = is_inherit[j] ? 1 : 0; list[j][i]; i++){
4563 if(!expand)
4564 *tmp++ = cpystr(list[j][i]);
4565 else if(expand_variables(tmp_20k_buf,SIZEOF_20KBUF,
4566 list[j][i], 0))
4567 *tmp++ = cpystr(tmp_20k_buf);
4573 *tmp = NULL;
4575 else
4576 var->current_val.l = NULL;
4578 else{ /* variable is not a list */
4579 char *strvar = NULL;
4581 for(j = 0; j < 5; j++){
4583 p = j==0 ? var->fixed_val.p :
4584 j==1 ? ((cmdline) ? var->cmdline_val.p : NULL) :
4585 j==2 ? var->post_user_val.p :
4586 j==3 ? var->main_user_val.p :
4587 var->global_val.p;
4589 is_set[j] = 0;
4591 if(p){
4592 if(!expand){
4593 is_set[j]++;
4594 if(!strvar)
4595 strvar = p;
4597 else if(expand_variables(tmp_20k_buf, SIZEOF_20KBUF, p,
4598 (var == &ps_global->vars[V_MAILCAP_PATH] ||
4599 var == &ps_global->vars[V_MIMETYPE_PATH]))){
4600 is_set[j]++;
4601 if(!strvar)
4602 strvar = p;
4607 /* Admin wants default, which is global_val. */
4608 if(var->is_fixed && var->fixed_val.p == NULL)
4609 strvar = var->global_val.p;
4611 if(var->current_val.p) /* free previous value */
4612 fs_give((void **)&var->current_val.p);
4614 if(strvar){
4615 if(!expand)
4616 var->current_val.p = cpystr(strvar);
4617 else{
4618 expand_variables(tmp_20k_buf, SIZEOF_20KBUF, strvar,
4619 (var == &ps_global->vars[V_MAILCAP_PATH] ||
4620 var == &ps_global->vars[V_MIMETYPE_PATH]));
4621 var->current_val.p = cpystr(tmp_20k_buf);
4624 else
4625 var->current_val.p = NULL;
4628 if(var->is_fixed && !is_inherit[4]){
4629 char **flist;
4630 int fixed_len, user_len;
4633 * sys mgr fixed this variable and user is trying to change it
4635 for(k = 1; !(ps_global->give_fixed_warning &&
4636 ps_global->fix_fixed_warning) && k <= 3; k++){
4637 if(is_set[k]){
4638 if(var->is_list){
4639 t = k==1 ? ((cmdline) ? var->cmdline_val.l : NULL) :
4640 k==2 ? var->post_user_val.l :
4641 var->main_user_val.l;
4643 /* If same length and same contents, don't warn. */
4644 for(flist=var->fixed_val.l; flist && *flist; flist++)
4645 ;/* just counting */
4647 fixed_len = var->fixed_val.l ? (flist - var->fixed_val.l)
4648 : 0;
4649 for(flist=t; flist && *flist; flist++)
4650 ;/* just counting */
4652 user_len = t ? (flist - t) : 0;
4653 if(user_len == fixed_len){
4654 for(i=0; i < user_len; i++){
4655 for(j=0; j < user_len; j++)
4656 if(!strucmp(t[i], var->fixed_val.l[j]))
4657 break;
4659 if(j == user_len){
4660 ps_global->give_fixed_warning = 1;
4661 if(k != 1)
4662 ps_global->fix_fixed_warning = 1;
4664 break;
4668 else{
4669 ps_global->give_fixed_warning = 1;
4670 if(k != 1)
4671 ps_global->fix_fixed_warning = 1;
4674 else{
4675 p = k==1 ? ((cmdline) ? var->cmdline_val.p : NULL) :
4676 k==2 ? var->post_user_val.p :
4677 var->main_user_val.p;
4679 if((var->fixed_val.p && !p) ||
4680 (!var->fixed_val.p && p) ||
4681 (var->fixed_val.p && p && strucmp(var->fixed_val.p, p))){
4682 ps_global->give_fixed_warning = 1;
4683 if(k != 1)
4684 ps_global->fix_fixed_warning = 1;
4693 void
4694 set_news_spec_current_val(int expand, int cmdline)
4696 struct variable *newsvar = &ps_global->vars[V_NEWS_SPEC];
4697 struct variable *fvar = &ps_global->vars[V_FOLDER_SPEC];
4699 /* check to see if it has a value */
4700 set_current_val(newsvar, expand, cmdline);
4703 * If no value, we might want to fake a value. We'll do that if
4704 * there is no news collection already defined in FOLDER_SPEC and if
4705 * there is also an NNTP_SERVER defined.
4707 if(!newsvar->current_val.l && ps_global->VAR_NNTP_SERVER &&
4708 ps_global->VAR_NNTP_SERVER[0] && ps_global->VAR_NNTP_SERVER[0][0] &&
4709 !news_in_folders(fvar)){
4710 char buf[MAXPATH];
4712 newsvar->global_val.l = (char **)fs_get(2 * sizeof(char *));
4713 snprintf(buf, sizeof(buf), "{%.*s/nntp}#news.[]", MAXPATH-20,
4714 ps_global->VAR_NNTP_SERVER[0]); /* MAXPATH = sizeof(buf) */
4715 newsvar->global_val.l[0] = cpystr(buf);
4716 newsvar->global_val.l[1] = NULL;
4717 set_current_val(newsvar, expand, cmdline);
4719 * But we're going to get rid of the fake global_val in case
4720 * things change.
4722 free_list_array(&newsvar->global_val.l);
4728 * Feature-list has to be handled separately from the other variables
4729 * because it is additive. The other variables choose one of command line,
4730 * or pine.conf, or pinerc. Feature list adds them. This could easily be
4731 * converted to a general purpose routine if we add more additive variables.
4733 * This works by replacing earlier values with later ones. That is, command
4734 * line settings have higher precedence than global settings and that is
4735 * accomplished by putting the command line features after the global
4736 * features in the list. When they are processed, the last one wins.
4738 * Feature-list also has a backwards compatibility hack.
4740 void
4741 set_feature_list_current_val(struct variable *var)
4743 char **list;
4744 char **list_fixed;
4745 char no_allow[50];
4746 int i, j, k, m,
4747 elems = 0;
4749 /* count the lists so we can allocate */
4750 for(m = 0; m < 6; m++){
4751 list = m==0 ? var->global_val.l :
4752 m==1 ? var->main_user_val.l :
4753 m==2 ? var->post_user_val.l :
4754 m==3 ? ps_global->feat_list_back_compat :
4755 m==4 ? var->cmdline_val.l :
4756 var->fixed_val.l;
4757 if(list)
4758 for(i = 0; list[i]; i++)
4759 elems++;
4762 list_fixed = var->fixed_val.l;
4764 if(var->current_val.l)
4765 free_list_array(&var->current_val.l);
4767 var->current_val.l = (char **)fs_get((elems+1) * sizeof(char *));
4770 * We need to warn the user if the sys mgr has restricted him or her
4771 * from changing a feature that he or she is trying to change.
4773 * We're not catching the old-growth macro since we're just comparing
4774 * strings. That is, it works correctly, but the user won't be warned
4775 * if the user old-growth and the mgr says no-quit-without-confirm.
4778 j = 0;
4779 strncpy(no_allow, "no-", 3);
4780 strncpy(no_allow+3, feature_list_name(F_ALLOW_CHANGING_FROM), sizeof(no_allow)-3-1);
4781 no_allow[sizeof(no_allow)-1] = '\0';
4783 for(m = 0; m < 6; m++){
4784 list = m==0 ? var->global_val.l :
4785 m==1 ? var->main_user_val.l :
4786 m==2 ? var->post_user_val.l :
4787 m==3 ? ps_global->feat_list_back_compat :
4788 m==4 ? var->cmdline_val.l :
4789 var->fixed_val.l;
4790 if(list)
4791 for(i = 0; list[i]; i++){
4792 var->current_val.l[j++] = cpystr(list[i]);
4794 /* this is the warning section */
4795 if(m >= 1 && m <= 4){
4796 for(k = 0; list_fixed && list_fixed[k]; k++){
4797 char *p, *q;
4798 p = list[i];
4799 q = list_fixed[k];
4800 if(!struncmp(p, "no-", 3))
4801 p += 3;
4802 if(!struncmp(q, "no-", 3))
4803 q += 3;
4804 if(!strucmp(q, p) && strucmp(list[i], list_fixed[k])){
4805 ps_global->give_fixed_warning = 1;
4806 if(m <= 2)
4807 ps_global->fix_fixed_warning = 1;
4811 else if(m == 5 && !strucmp(list[i], no_allow))
4812 ps_global->never_allow_changing_from = 1;
4816 #ifdef NEVER_ALLOW_CHANGING_FROM
4817 ps_global->never_allow_changing_from = 1;
4818 #endif
4820 var->current_val.l[j] = NULL;
4825 /*----------------------------------------------------------------------
4827 Expand Metacharacters/variables in file-names
4829 Read input line and expand shell-variables/meta-characters
4831 <input> <replaced by>
4832 $variable getenv("variable")
4833 ${variable} getenv("variable")
4834 ${variable:-defvalue} is getenv("variable") if variable is defined and
4835 is defvalue otherwise
4836 ~ getenv("HOME")
4837 \c c
4838 <others> <just copied>
4840 NOTE handling of braces in ${name} doesn't check much or do error recovery
4842 If colon_path is set, then we expand ~ not only at the start of linein,
4843 but also after each : in the path.
4845 ----*/
4846 #define is_allowed_envchar(C, S) ((S) == 0 ? !isspace((C)) && (C) != '/'\
4847 : (((C) >= 'a' && (C) <= 'z') \
4848 || ((C) >= 'A' && (C) <= 'Z') \
4849 || ((C) >= '0' && (C) <= '9')))
4851 char *
4852 expand_variables(char *lineout, size_t lineoutlen, char *linein, int colon_path)
4854 char *src = linein, *dest = lineout, *p;
4855 char *limit = lineout + lineoutlen;
4856 int envexpand = 0, sp;
4858 if(!linein)
4859 return(NULL);
4861 sp = strncmp(src,"LIT:pattern=\"/NICK=", strlen("LIT:pattern=\"/NICK=")) == 0;
4862 while(*src ){ /* something in input string */
4863 if(*src == '$' && *(src+1) == '$'){
4865 * $$ to escape chars we're interested in, else
4866 * it's up to the user of the variable to handle the
4867 * backslash...
4869 if(dest < limit)
4870 *dest++ = *++src; /* copy next as is */
4871 }else
4872 #if !(defined(DOS) || defined(OS2))
4873 if(*src == '\\' && *(src+1) == '$'){
4875 * backslash to escape chars we're interested in, else
4876 * it's up to the user of the variable to handle the
4877 * backslash...
4879 if(dest < limit)
4880 *dest++ = *++src; /* copy next as is */
4881 }else if(*src == '~' &&
4882 (src == linein || (colon_path && *(src-1) == ':'))){
4883 char buf[MAXPATH];
4884 int i;
4886 for(i = 0; i < sizeof(buf)-1 && src[i] && src[i] != '/'; i++)
4887 buf[i] = src[i];
4889 src += i; /* advance src pointer */
4890 buf[i] = '\0'; /* tie off buf string */
4891 fnexpand(buf, sizeof(buf)); /* expand the path */
4893 for(p = buf; dest < limit && (*dest = *p); p++, dest++)
4896 continue;
4897 }else
4898 #endif
4899 if(*src == '$'){ /* shell variable */
4900 char word[128+1], *colon = NULL, *rbrace = NULL;
4902 envexpand++; /* signal that we've expanded a var */
4903 src++; /* skip dollar */
4904 if(*src == '{'){ /* starts with brace? */
4905 src++;
4906 rbrace = strindex(src, '}');
4907 if(rbrace){
4908 /* look for default value */
4909 colon = strstr(src, ":-");
4910 if(colon && (rbrace < colon))
4911 colon = NULL;
4915 p = word;
4917 /* put the env variable to be looked up in word */
4918 if(rbrace){
4919 while(*src
4920 && (p-word < sizeof(word)-1)
4921 && ((colon && src < colon) || (!colon && src < rbrace))){
4922 if(isspace((unsigned char) *src)){
4924 * Illegal input. This should be an error of some
4925 * sort but instead of that we'll just backup to the
4926 * $ and treat it like it wasn't there.
4928 while(*src != '$')
4929 src--;
4931 envexpand--;
4932 goto just_copy;
4934 else
4935 *p++ = *src++;
4938 /* adjust src for next char */
4939 src = rbrace + 1;
4941 else{
4942 while(*src && is_allowed_envchar((unsigned char) *src, sp)
4943 && (p-word < sizeof(word)-1))
4944 *p++ = *src++;
4947 *p = '\0';
4949 if((p = getenv(word)) != NULL){ /* check for word in environment */
4950 while(*p && dest < limit)
4951 *dest++ = *p++;
4953 else if(colon){ /* else possible default value */
4954 p = colon + 2;
4955 while(*p && p < rbrace && dest < limit)
4956 *dest++ = *p++;
4959 continue;
4960 }else{ /* other cases: just copy */
4961 just_copy:
4962 if(dest < limit)
4963 *dest++ = *src;
4966 if(*src) /* next character (if any) */
4967 src++;
4970 if(dest < limit)
4971 *dest = '\0';
4972 else
4973 lineout[lineoutlen-1] = '\0';
4975 return((envexpand && lineout[0] == '\0') ? NULL : lineout);
4979 /*----------------------------------------------------------------------
4980 Sets login, full_username and home_dir
4982 Args: ps -- The Pine structure to put the user name, etc in
4984 Result: sets the fullname, login and home_dir field of the pine structure
4985 returns 0 on success, -1 if not.
4986 ----*/
4987 #define MAX_INIT_ERRS 10
4988 void
4989 init_error(struct pine *ps, int flags, int min_time, int max_time, char *message)
4991 int i;
4993 if(!ps->init_errs){
4994 ps->init_errs = (INIT_ERR_S *)fs_get((MAX_INIT_ERRS + 1) *
4995 sizeof(*ps->init_errs));
4996 memset(ps->init_errs, 0, (MAX_INIT_ERRS + 1) * sizeof(*ps->init_errs));
4999 for(i = 0; i < MAX_INIT_ERRS; i++)
5000 if(!(ps->init_errs)[i].message){
5001 (ps->init_errs)[i].message = cpystr(message);
5002 (ps->init_errs)[i].min_time = min_time;
5003 (ps->init_errs)[i].max_time = max_time;
5004 (ps->init_errs)[i].flags = flags;
5005 dprint((2, "%s\n", message ? message : "?"));
5006 break;
5011 /*----------------------------------------------------------------------
5012 Read and parse a pinerc file
5014 Args: Filename -- name of the .pinerc file to open and read
5015 vars -- The vars structure to store values in
5016 which_vars -- Whether the local or global values are being read
5018 Result:
5020 This may be the local file or the global file. The values found are
5021 merged with the values currently in vars. All values are strings and
5022 are malloced; and existing values will be freed before the assignment.
5023 Those that are <unset> will be left unset; their values will be NULL.
5024 ----*/
5025 void
5026 read_pinerc(PINERC_S *prc, struct variable *vars, ParsePinerc which_vars)
5028 char *filename, *file, *value, **lvalue, *line, *error;
5029 char *p, *p1, *free_file = NULL;
5030 struct variable *v;
5031 PINERC_LINE *pline = NULL;
5032 int line_count, was_quoted;
5033 int i;
5035 if(!prc)
5036 return;
5038 dprint((2, "reading_pinerc \"%s\"\n",
5039 prc->name ? prc->name : "?"));
5041 if(prc->type == Loc){
5042 filename = prc->name ? prc->name : "";
5043 file = free_file = read_file(filename, 0);
5046 * This is questionable. In case the user edits the pinerc
5047 * in Windows and adds a UTF-8 BOM, we skip it here. If the
5048 * user adds a Unicode BOM we're in trouble. We could write it
5049 * with the BOM ourselves but so far we leave it BOMless in
5050 * order that it's the same on Unix and Windows.
5052 if(BOM_UTF8(file))
5053 file += 3;
5055 else{
5056 if((file = read_remote_pinerc(prc, which_vars)) != NULL)
5057 ps_global->c_client_error[0] = '\0';
5059 free_file = file;
5062 if(file == NULL || *file == '\0'){
5063 #ifdef DEBUG
5064 if(file == NULL){
5065 dprint((2, "Open failed: %s\n", error_description(errno)));
5067 else{
5068 if(prc->type == Loc){
5069 dprint((1, "Read_pinerc: empty pinerc (new?)\n"));
5071 else{
5072 dprint((1, "Read_pinerc: new remote pinerc\n"));
5075 #endif /* DEBUG */
5077 if(which_vars == ParsePers){
5078 /* problems getting remote config */
5079 if(file == NULL && prc->type == RemImap){
5080 if(!pith_opt_remote_pinerc_failure
5081 || !(*pith_opt_remote_pinerc_failure)())
5082 exceptional_exit(_("Unable to read or write remote configuration"), -1);
5085 ps_global->first_time_user = 1;
5086 prc->outstanding_pinerc_changes = 1;
5089 return;
5091 else{
5092 if(prc->type == Loc &&
5093 (which_vars == ParseFixed || which_vars == ParseGlobal ||
5094 (can_access(filename, ACCESS_EXISTS) == 0 &&
5095 can_access(filename, EDIT_ACCESS) != 0))){
5096 prc->readonly = 1;
5097 if(prc == ps_global->prc)
5098 ps_global->readonly_pinerc = 1;
5102 * accept CRLF or LF newlines
5104 for(p = file; *p && *p != '\012'; p++)
5107 if(p > file && *p && *(p-1) == '\015') /* cvt crlf to lf */
5108 for(p1 = p - 1; (*p1 = *p) != '\0'; p++)
5109 if(!(*p == '\015' && *(p+1) == '\012'))
5110 p1++;
5113 dprint((2, "Read %d characters:\n", strlen(file)));
5115 if(which_vars == ParsePers || which_vars == ParsePersPost){
5116 /*--- Count up lines and allocate structures */
5117 for(line_count = 0, p = file; *p != '\0'; p++)
5118 if(*p == '\n')
5119 line_count++;
5121 prc->pinerc_lines = (PINERC_LINE *)
5122 fs_get((3 + line_count) * sizeof(PINERC_LINE));
5123 memset((void *)prc->pinerc_lines, 0,
5124 (3 + line_count) * sizeof(PINERC_LINE));
5125 pline = prc->pinerc_lines;
5128 for(p = file, line = file; *p != '\0';){
5129 /*----- Grab the line ----*/
5130 line = p;
5131 while(*p && *p != '\n')
5132 p++;
5133 if(*p == '\n'){
5134 *p++ = '\0';
5137 /*----- Comment Line -----*/
5138 if(*line == '#'){
5139 /* no comments in remote pinercs */
5140 if(pline && prc->type == Loc){
5141 pline->is_var = 0;
5142 pline->line = cpystr(line);
5143 pline++;
5145 continue;
5148 if(*line == '\0' || *line == '\t' || *line == ' '){
5149 p1 = line;
5150 while(*p1 == '\t' || *p1 == ' ')
5151 p1++;
5152 if(pline){
5154 * This could be a continuation line from some future
5155 * version of pine, or it could be a continuation line
5156 * from a PC-Pine variable we don't know about in unix.
5158 if(*p1 != '\0')
5159 pline->line = cpystr(line);
5160 else
5161 pline->line = cpystr("");
5162 pline->is_var = 0;
5163 pline++;
5165 continue;
5168 /*----- look up matching 'v' and leave "value" after '=' ----*/
5169 for(v = vars; *line && v->name; v++)
5170 if((i = strlen(v->name)) < strlen(line) && !struncmp(v->name,line,i)){
5171 int j;
5173 for(j = i; line[j] == ' ' || line[j] == '\t'; j++)
5176 if(line[j] == '='){ /* bingo! */
5177 for(value = &line[j+1];
5178 *value == ' ' || *value == '\t';
5179 value++)
5182 break;
5184 /* else either unrecognized var or bogus line */
5187 /*----- Didn't match any variable or bogus format -----*/
5189 * This could be a variable from some future
5190 * version of pine, or it could be a PC-Pine variable
5191 * we don't know about in unix. Either way, we want to preserve
5192 * it in the file.
5194 if(!v->name){
5195 if(pline){
5196 pline->is_var = 0;
5197 pline->line = cpystr(line);
5198 pline++;
5200 continue;
5204 * Previous versions have caused duplicate pinerc data to be
5205 * written to pinerc files. This clause erases the duplicate
5206 * information when we read it, and it will be removed from the file
5207 * if we call write_pinerc. We test to see if the same variable
5208 * appears later in the file, if so, we skip over it here.
5209 * We don't care about duplicates if this isn't a pinerc we might
5210 * write out, so include pline in the conditional.
5211 * Note that we will leave all of the duplicate comments and blank
5212 * lines in the file unless it is a remote pinerc. Luckily, the
5213 * bug that caused the duplicates only applied to remote pinercs,
5214 * so we should have that case covered.
5216 * If we find a duplicate, we point p to the start
5217 * of the next line that should be considered, and then skip back
5218 * to the top of the loop.
5220 if(pline && var_is_in_rest_of_file(v->name, p)){
5221 if(v->is_list)
5222 p = skip_over_this_var(line, p);
5224 continue;
5228 /*----- Obsolete variable, read it anyway below, might use it -----*/
5229 if(v->is_obsolete){
5230 if(pline){
5231 pline->obsolete_var = 1;
5232 pline->line = cpystr(line);
5233 pline->var = v;
5237 /*----- Variable is in the list but unused for some reason -----*/
5238 if(!v->is_used){
5239 if(pline){
5240 pline->is_var = 0;
5241 pline->line = cpystr(line);
5242 pline++;
5244 continue;
5247 /*--- Var is not user controlled, leave it alone for back compat ---*/
5248 if(!v->is_user && pline){
5249 pline->is_var = 0;
5250 pline->line = cpystr(line);
5251 pline++;
5252 continue;
5255 if(which_vars == ParseFixed)
5256 v->is_fixed = 1;
5258 /*---- variable is unset, or it's global but expands to nothing ----*/
5259 if(!*value
5260 || (which_vars == ParseGlobal
5261 && !expand_variables(tmp_20k_buf, SIZEOF_20KBUF, value,
5262 (v == &ps_global->vars[V_MAILCAP_PATH] ||
5263 v == &ps_global->vars[V_MIMETYPE_PATH])))){
5264 if(v->is_user && pline){
5265 pline->is_var = 1;
5266 pline->var = v;
5267 pline++;
5269 continue;
5272 /*--value is non-empty, store it handling quotes and trailing space--*/
5273 if(*value == '"' && !v->is_list && v->del_quotes){
5274 was_quoted = 1;
5275 value++;
5276 for(p1 = value; *p1 && *p1 != '"'; p1++);
5277 if(*p1 == '"')
5278 *p1 = '\0';
5279 else
5280 removing_trailing_white_space(value);
5281 }else
5282 was_quoted = 0;
5285 * List Entry Parsing
5287 * The idea is to parse a comma separated list of
5288 * elements, preserving quotes, and understanding
5289 * continuation lines (that is ',' == "\n ").
5290 * Quotes must be balanced within elements. Space
5291 * within elements is preserved, but leading and trailing
5292 * space is trimmed. This is a generic function, and it's
5293 * left to the the functions that use the lists to make sure
5294 * they contain valid data...
5296 if(v->is_list){
5298 was_quoted = 0;
5299 line_count = 0;
5300 p1 = value;
5301 while(1){ /* generous count of list elements */
5302 if(*p1 == '"') /* ignore ',' if quoted */
5303 was_quoted = (was_quoted) ? 0 : 1 ;
5305 if((*p1 == ',' && !was_quoted) || *p1 == '\n' || *p1 == '\0')
5306 line_count++; /* count this element */
5308 if(*p1 == '\0' || *p1 == '\n'){ /* deal with EOL */
5309 if(p1 < p || *p1 == '\n'){
5310 *p1++ = ','; /* fix null or newline */
5312 if(*p1 != '\t' && *p1 != ' '){
5313 *(p1-1) = '\0'; /* tie off list */
5314 p = p1; /* reset p */
5315 break;
5317 }else{
5318 p = p1; /* end of pinerc */
5319 break;
5321 }else
5322 p1++;
5325 error = NULL;
5326 lvalue = parse_list(value, line_count,
5327 v->del_quotes ? PL_REMSURRQUOT : PL_NONE,
5328 &error);
5329 if(error){
5330 dprint((1,
5331 "read_pinerc: ERROR: %s in %s = \"%s\"\n",
5332 error ? error : "?",
5333 v->name ? v->name : "?",
5334 value ? value : "?"));
5337 * Special case: turn "" strings into empty strings.
5338 * This allows users to turn off default lists. For example,
5339 * if smtp-server is set then a user could override smtp-server
5340 * with smtp-server="".
5342 for(i = 0; lvalue[i]; i++)
5343 if(lvalue[i][0] == '"' &&
5344 lvalue[i][1] == '"' &&
5345 lvalue[i][2] == '\0')
5346 lvalue[i][0] = '\0';
5349 if(pline){
5350 if(v->is_user && (which_vars == ParsePers || !v->is_onlymain)){
5351 if(v->is_list){
5352 char ***l;
5354 l = (which_vars == ParsePers) ? &v->main_user_val.l
5355 : &v->post_user_val.l;
5356 free_list_array(l);
5357 *l = lvalue;
5359 else{
5360 char **p;
5362 p = (which_vars == ParsePers) ? &v->main_user_val.p
5363 : &v->post_user_val.p;
5364 if(p && *p != NULL)
5365 fs_give((void **)p);
5367 *p = cpystr(value);
5370 if(pline){
5371 pline->is_var = 1;
5372 pline->var = v;
5373 pline->is_quoted = was_quoted;
5374 pline++;
5378 else if(which_vars == ParseGlobal){
5379 if(v->is_global){
5380 if(v->is_list){
5381 free_list_array(&v->global_val.l);
5382 v->global_val.l = lvalue;
5384 else{
5385 if(v->global_val.p != NULL)
5386 fs_give((void **) &(v->global_val.p));
5388 v->global_val.p = cpystr(value);
5392 else{ /* which_vars == ParseFixed */
5393 if(v->is_user || v->is_global){
5394 if(v->is_list){
5395 free_list_array(&v->fixed_val.l);
5396 v->fixed_val.l = lvalue;
5398 else{
5399 if(v->fixed_val.p != NULL)
5400 fs_give((void **) &(v->fixed_val.p));
5402 v->fixed_val.p = cpystr(value);
5407 #ifdef DEBUG
5408 if(v->is_list){
5409 char **l;
5410 l = (which_vars == ParsePers) ? v->main_user_val.l :
5411 (which_vars == ParsePersPost) ? v->post_user_val.l :
5412 (which_vars == ParseGlobal) ? v->global_val.l :
5413 v->fixed_val.l;
5414 if(l && *l && **l){
5415 dprint((5, " %20.20s : %s\n",
5416 v->name ? v->name : "?",
5417 *l ? *l : "?"));
5418 while(++l && *l && **l)
5419 dprint((5, " %20.20s : %s\n", "",
5420 *l ? *l : "?"));
5422 }else{
5423 char *p;
5424 p = (which_vars == ParsePers) ? v->main_user_val.p :
5425 (which_vars == ParsePersPost) ? v->post_user_val.p :
5426 (which_vars == ParseGlobal) ? v->global_val.p :
5427 v->fixed_val.p;
5428 if(p && *p)
5429 dprint((5, " %20.20s : %s\n",
5430 v->name ? v->name : "?",
5431 p ? p : "?"));
5433 #endif /* DEBUG */
5436 if(pline){
5437 pline->line = NULL;
5438 pline->is_var = 0;
5439 if(!prc->pinerc_written && prc->type == Loc){
5440 prc->pinerc_written = name_file_mtime(filename);
5441 dprint((5, "read_pinerc: time_pinerc_written = %ld\n",
5442 (long) prc->pinerc_written));
5446 if(free_file)
5447 fs_give((void **) &free_file);
5452 * Args varname The variable name we're looking for
5453 * begin Begin looking here
5455 * Returns 1 if variable varname appears in the rest of the file
5456 * 0 if not
5459 var_is_in_rest_of_file(char *varname, char *begin)
5461 char *p;
5463 if(!(varname && *varname && begin && *begin))
5464 return 0;
5466 p = begin;
5468 while((p = srchstr(p, varname)) != NULL){
5469 /* beginning of a line? */
5470 if(p > begin && (*(p-1) != '\n' && *(p-1) != '\r')){
5471 p++;
5472 continue;
5475 /* followed by [ SPACE ] < = > ? */
5476 p += strlen(varname);
5477 while(*p == ' ' || *p == '\t')
5478 p++;
5480 if(*p == '=')
5481 return 1;
5484 return 0;
5489 * Args begin Variable to skip starts here.
5490 * nextline This is where the next line starts. We need to know this
5491 * because the input has been mangled a little. A \0 has
5492 * replaced the \n at the end of the first line, but we can
5493 * use nextline to help us out of that quandry.
5495 * Return a pointer to the start of the first line after this variable
5496 * and all of its continuation lines.
5498 char *
5499 skip_over_this_var(char *begin, char *nextline)
5501 char *p;
5503 p = begin;
5505 while(1){
5506 if(*p == '\0' || *p == '\n'){ /* EOL */
5507 if(p < nextline || *p == '\n'){ /* there may be another line */
5508 p++;
5509 if(*p != ' ' && *p != '\t') /* no continuation line */
5510 return(p);
5512 else /* end of file */
5513 return(p);
5515 else
5516 p++;
5521 static char quotes[3] = {'"', '"', '\0'};
5522 /*----------------------------------------------------------------------
5523 Write out the .pinerc state information
5525 Args: ps -- The pine structure to take state to be written from
5526 which -- Which pinerc to write
5527 flags -- If bit WRP_NOUSER is set, then assume that there is
5528 not a user present to answer questions.
5530 This writes to a temporary file first, and then renames that to
5531 be the new .pinerc file to protect against disk error. This has the
5532 problem of possibly messing up file protections, ownership and links.
5533 ----*/
5535 write_pinerc(struct pine *ps, EditWhich which, int flags)
5537 char *p, *dir, *tmp = NULL, *pinrc;
5538 char *pval, **lval;
5539 char *linep = NULL, *lineq = NULL;
5540 int bc = 1;
5541 int buflen;
5542 PINERC_LINE *pline;
5543 struct variable *var;
5544 time_t mtime;
5545 char *filename;
5546 REMDATA_S *rd = NULL;
5547 PINERC_S *prc = NULL;
5548 STORE_S *so = NULL;
5549 #ifndef _WINDOWS
5550 struct stat sbuf;
5551 char *slink = NULL;
5552 #endif
5554 #define MAXPLINESIZE 10000
5556 dprint((2,"---- write_pinerc(%s) ----\n",
5557 (which == Main) ? "Main" : "Post"));
5559 switch(which){
5560 case Main:
5561 prc = ps ? ps->prc : NULL;
5562 break;
5563 case Post:
5564 prc = ps ? ps->post_prc : NULL;
5565 break;
5566 default:
5567 break;
5570 if(!prc)
5571 return(-1);
5573 if(prc->quit_to_edit){
5574 if(!(flags & WRP_NOUSER))
5575 quit_to_edit_msg(prc);
5577 return(-1);
5580 if(prc->type != Loc && !prc->readonly){
5582 bc = 0; /* don't do backcompat conversion */
5583 rd = prc->rd;
5584 if(!rd)
5585 return(-1);
5587 rd_check_remvalid(rd, -10L);
5589 if(rd->flags & REM_OUTOFDATE){
5590 if((flags & WRP_NOUSER) || unexpected_pinerc_change()){
5591 prc->outstanding_pinerc_changes = 1;
5592 if(!(flags & WRP_NOUSER))
5593 q_status_message1(SM_ORDER | SM_DING, 3, 3,
5594 "Pinerc \"%.200s\" NOT saved",
5595 prc->name ? prc->name : "");
5596 dprint((2, "write_pinerc: remote pinerc changed\n"));
5597 return(-1);
5599 else
5600 rd->flags &= ~REM_OUTOFDATE;
5603 rd_open_remote(rd);
5605 if(rd->access == ReadWrite){
5606 int ro;
5608 if((ro=rd_remote_is_readonly(rd)) || rd->flags & REM_OUTOFDATE){
5609 if(ro == 1){
5610 if(!(flags & WRP_NOUSER))
5611 q_status_message(SM_ORDER | SM_DING, 5, 15,
5612 _("Can't access remote config, changes NOT saved!"));
5613 dprint((1,
5614 "write_pinerc: Can't write to remote pinerc %s, aborting write\n",
5615 rd->rn ? rd->rn : "?"));
5617 else if(ro == 2){
5618 if(!(rd->flags & NO_META_UPDATE)){
5619 unsigned long save_chk_nmsgs;
5621 switch(rd->type){
5622 case RemImap:
5623 save_chk_nmsgs = rd->t.i.chk_nmsgs;
5624 rd->t.i.chk_nmsgs = 0;
5625 rd_write_metadata(rd, 0);
5626 rd->t.i.chk_nmsgs = save_chk_nmsgs;
5627 break;
5629 default:
5630 q_status_message(SM_ORDER | SM_DING, 3, 5,
5631 "Write_pinerc: Type not supported");
5632 break;
5636 if(!(flags & WRP_NOUSER))
5637 q_status_message1(SM_ORDER | SM_DING, 5, 15,
5638 _("No write permission for remote config %.200s, changes NOT saved!"),
5639 rd->rn);
5641 else{
5642 if(!(flags & WRP_NOUSER))
5643 q_status_message(SM_ORDER | SM_DING, 5, 15,
5644 _("Remote config changed, aborting our change to avoid damage..."));
5645 dprint((1,
5646 "write_pinerc: remote config %s changed since we started pine, aborting write\n",
5647 prc->name ? prc->name : "?"));
5650 rd->flags &= ~DO_REMTRIM;
5651 return(-1);
5654 filename = rd->lf;
5656 else{
5657 prc->readonly = 1;
5658 if(prc == ps->prc)
5659 ps->readonly_pinerc = 1;
5662 else
5663 filename = prc->name ? prc->name : "";
5665 pinrc = prc->name ? prc->name : "";
5667 if(prc->type == Loc){
5668 mtime = name_file_mtime(filename);
5669 if(prc->pinerc_written
5670 && prc->pinerc_written != mtime
5671 && ((flags & WRP_NOUSER) || unexpected_pinerc_change())){
5672 prc->outstanding_pinerc_changes = 1;
5674 if(!(flags & WRP_NOUSER))
5675 q_status_message1(SM_ORDER | SM_DING, 3, 3,
5676 "Pinerc \"%.200s\" NOT saved", pinrc);
5678 dprint((2,"write_pinerc: mtime mismatch: \"%s\": %ld != %ld\n",
5679 filename ? filename : "?",
5680 (long) prc->pinerc_written, (long) mtime));
5681 return(-1);
5685 /* don't write if pinerc is read-only */
5686 if(prc->readonly ||
5687 (filename &&
5688 can_access(filename, ACCESS_EXISTS) == 0 &&
5689 can_access(filename, EDIT_ACCESS) != 0)){
5690 prc->readonly = 1;
5691 if(prc == ps->prc)
5692 ps->readonly_pinerc = 1;
5694 if(!(flags & WRP_NOUSER))
5695 q_status_message1(SM_ORDER | SM_DING, 0, 5,
5696 _("Can't modify configuration file \"%.200s\": ReadOnly"),
5697 pinrc);
5698 dprint((2, "write_pinerc: fail because can't access pinerc\n"));
5700 if(rd)
5701 rd->flags &= ~DO_REMTRIM;
5703 return(-1);
5706 if(rd && rd->flags & NO_FILE){
5707 so = rd->sonofile;
5708 so_truncate(rd->sonofile, 0L); /* reset storage object */
5710 else{
5711 dir = ".";
5712 if((p = last_cmpnt(filename)) != NULL){
5713 *--p = '\0';
5714 dir = filename;
5717 #if defined(DOS) || defined(OS2)
5718 if(!(isalpha((unsigned char)dir[0]) && dir[1] == ':' && dir[2] == '\0')
5719 && (can_access(dir, EDIT_ACCESS) < 0 &&
5720 our_mkdir(dir, 0700) < 0))
5722 if(!(flags & WRP_NOUSER))
5723 q_status_message2(SM_ORDER | SM_DING, 3, 5,
5724 /* TRANSLATORS: first argument is a filename, second
5725 arg is the text of the error message */
5726 _("Error creating \"%.200s\" : %.200s"), dir,
5727 error_description(errno));
5728 if(rd)
5729 rd->flags &= ~DO_REMTRIM;
5731 return(-1);
5734 tmp = temp_nam(dir, "rc");
5736 if(*dir && tmp && !in_dir(dir, tmp)){
5737 our_unlink(tmp);
5738 fs_give((void **)&tmp);
5741 if(p)
5742 *p = '\\';
5744 if(tmp == NULL)
5745 goto io_err;
5747 #else /* !DOS */
5748 tmp = temp_nam((*dir) ? dir : "/", "pinerc");
5751 * If temp_nam can't write in dir it puts the temp file in a
5752 * temp directory, which won't help us when we go to rename.
5754 if(*dir && tmp && !in_dir(dir, tmp)){
5755 our_unlink(tmp);
5756 fs_give((void **)&tmp);
5759 if(p)
5760 *p = '/';
5762 if(tmp == NULL)
5763 goto io_err;
5765 #endif /* !DOS */
5767 if((so = so_get(FileStar, tmp, WRITE_ACCESS)) == NULL)
5768 goto io_err;
5771 if(!(flags & WRP_PRESERV_WRITTEN))
5772 for(var = ps->vars; var->name != NULL; var++)
5773 var->been_written = 0;
5775 if(prc->type == Loc && ps->first_time_user &&
5776 !so_puts(so, native_nl(cf_text_comment)))
5777 goto io_err;
5779 linep = fs_get((MAXPLINESIZE+1)*sizeof(char));
5780 lineq = fs_get((MAXPLINESIZE+1)*sizeof(char));
5781 buflen = MAXPLINESIZE;
5783 /* Write out what was in the .pinerc */
5784 for(pline = prc->pinerc_lines;
5785 pline && (pline->is_var || pline->line); pline++){
5786 if(pline->is_var){
5787 var = pline->var;
5789 if(var->is_list)
5790 lval = LVAL(var, which);
5791 else
5792 pval = PVAL(var, which);
5794 /* variable is not set */
5795 if((var->is_list && (!lval || !lval[0])) ||
5796 (!var->is_list && !pval)){
5797 /* leave null variables out of remote pinerc */
5798 if(prc->type == Loc &&
5799 (!so_puts(so, var->name) || !so_puts(so, "=") ||
5800 !so_puts(so, NEWLINE)))
5801 goto io_err;
5803 /* var is set to empty string */
5804 else if((var->is_list && lval[0][0] == '\0') ||
5805 (!var->is_list && pval[0] == '\0')){
5806 if(!so_puts(so, var->name) || !so_puts(so, "=") ||
5807 !so_puts(so, quotes) || !so_puts(so, NEWLINE))
5808 goto io_err;
5810 else{
5811 if(var->is_list){
5812 int i = 0;
5814 for(i = 0; lval[i]; i++){
5815 if(strlen(var->name)
5816 + (lval[i][0] ? strlen(lval[i]) : 5) > buflen){
5817 buflen = strlen(var->name)
5818 + (lval[i][0] ? strlen(lval[i]) : 5);
5819 fs_resize((void **)&linep, (buflen+1)*sizeof(char));
5820 fs_resize((void **)&lineq, (buflen+1)*sizeof(char));
5822 snprintf(linep, buflen+1, "%s%s%s%s%s",
5823 (i) ? "\t" : var->name,
5824 (i) ? "" : "=",
5825 lval[i][0] ? lval[i] : quotes,
5826 lval[i+1] ? "," : "", NEWLINE);
5827 linep[buflen] = '\0';
5828 if(!so_puts(so, bc ? backcompat_convert_from_utf8(&lineq, buflen+1, linep) : linep))
5829 goto io_err;
5832 else{
5833 if(strlen(var->name)
5834 + (pval[0] ? strlen(pval) : 5) > buflen){
5835 buflen = strlen(var->name)
5836 + (pval[0] ? strlen(pval) : 5);
5837 fs_resize((void **)&linep, (buflen+1)*sizeof(char));
5838 fs_resize((void **)&lineq, (buflen+1)*sizeof(char));
5840 snprintf(linep, buflen+1, "%s=%s%s%s%s",
5841 var->name,
5842 (pline->is_quoted && pval[0] != '\"')
5843 ? "\"" : "",
5844 pval,
5845 (pline->is_quoted && pval[0] != '\"')
5846 ? "\"" : "", NEWLINE);
5847 linep[buflen] = '\0';
5848 if(!so_puts(so, bc ? backcompat_convert_from_utf8(&lineq, buflen+1, linep) : linep))
5849 goto io_err;
5853 var->been_written = 1;
5855 }else{
5857 * The description text should be changed into a message
5858 * about the variable being obsolete when a variable is
5859 * moved to obsolete status. We add that message before
5860 * the variable unless it is already there. However, we
5861 * leave the variable itself in case the user runs an old
5862 * version of pine again. Note that we have read in the
5863 * value of the variable in read_pinerc and translated it
5864 * into a new variable if appropriate.
5866 if(pline->obsolete_var && prc->type == Loc){
5867 if(pline <= prc->pinerc_lines || (pline-1)->line == NULL ||
5868 strlen((pline-1)->line) < 3 ||
5869 strucmp((pline-1)->line+2, pline->var->descrip) != 0)
5870 if(!so_puts(so, "# ") ||
5871 !so_puts(so, native_nl(pline->var->descrip)) ||
5872 !so_puts(so, NEWLINE))
5873 goto io_err;
5876 /* remove comments from remote pinercs */
5877 if((prc->type == Loc ||
5878 (pline->line[0] != '#' && pline->line[0] != '\0')) &&
5879 (!so_puts(so, pline->line) || !so_puts(so, NEWLINE)))
5880 goto io_err;
5884 /* Now write out all the variables not in the .pinerc */
5885 for(var = ps->vars; var->name != NULL; var++){
5886 if(!var->is_user || var->been_written || !var->is_used ||
5887 var->is_obsolete || (var->is_onlymain && which != Main))
5888 continue;
5890 if(var->is_list)
5891 lval = LVAL(var, which);
5892 else
5893 pval = PVAL(var, which);
5896 * set description to NULL to eliminate preceding
5897 * blank and comment line.
5899 if(prc->type == Loc && var->descrip && *var->descrip &&
5900 (!so_puts(so, NEWLINE) || !so_puts(so, "# ") ||
5901 !so_puts(so, native_nl(var->descrip)) || !so_puts(so, NEWLINE)))
5902 goto io_err;
5904 /* variable is not set */
5905 /** Don't know what the global_val thing is for. SH, Mar 00 **/
5906 if((var->is_list && (!lval || (!lval[0] && !var->global_val.l))) ||
5907 (!var->is_list && !pval)){
5908 /* leave null variables out of remote pinerc */
5909 if(prc->type == Loc &&
5910 (!so_puts(so, var->name) || !so_puts(so, "=") ||
5911 !so_puts(so, NEWLINE)))
5912 goto io_err;
5914 /* var is set to empty string */
5915 else if((var->is_list && (!lval[0] || !lval[0][0]))
5916 || (!var->is_list && pval[0] == '\0')){
5917 if(!so_puts(so, var->name) || !so_puts(so, "=") ||
5918 !so_puts(so, quotes) || !so_puts(so, NEWLINE))
5919 goto io_err;
5921 else if(var->is_list){
5922 int i = 0;
5924 for(i = 0; lval[i] ; i++){
5925 if(strlen(var->name)
5926 + (lval[i][0] ? strlen(lval[i]) : 5) > buflen){
5927 buflen = strlen(var->name)
5928 + (lval[i][0] ? strlen(lval[i]) : 5);
5929 fs_resize((void **)&linep, (buflen+1)*sizeof(char));
5930 fs_resize((void **)&lineq, (buflen+1)*sizeof(char));
5932 snprintf(linep, buflen+1, "%s%s%s%s%s",
5933 (i) ? "\t" : var->name,
5934 (i) ? "" : "=",
5935 lval[i],
5936 lval[i+1] ? "," : "", NEWLINE);
5937 linep[buflen] = '\0';
5938 if(!so_puts(so, bc ? backcompat_convert_from_utf8(&lineq, buflen+1, linep) : linep))
5939 goto io_err;
5942 else{
5943 char *pconverted;
5945 if(strlen(pval) > buflen){
5946 buflen = strlen(pval) + 1;
5947 fs_resize((void **)&linep, (buflen+1)*sizeof(char));
5948 fs_resize((void **)&lineq, (buflen+1)*sizeof(char));
5950 pconverted = bc ? backcompat_convert_from_utf8(&lineq, buflen+1, pval) : pval;
5952 if(!so_puts(so, var->name) || !so_puts(so, "=") ||
5953 !so_puts(so, pconverted) || !so_puts(so, NEWLINE))
5954 goto io_err;
5958 if(!(rd && rd->flags & NO_FILE)){
5959 char *realfilename;
5960 int realfilename_malloced;
5962 if(so_give(&so)) goto io_err;
5964 #ifndef _WINDOWS
5965 if ((realfilename = realpath(filename, NULL)) != NULL)
5966 realfilename_malloced = 1;
5967 else if(our_stat(filename, &sbuf) < 0 && errno == ENOENT){
5968 realfilename = filename;
5969 realfilename_malloced = 0;
5971 else
5972 goto io_err;
5973 #else
5974 realfilename = filename;
5975 realfilename_malloced = 0;
5976 #endif /* _WINDOWS */
5977 if(realfilename != NULL){
5978 int r;
5979 file_attrib_copy(tmp, realfilename);
5980 r = rename_file(tmp, realfilename);
5981 if(realfilename_malloced != 0)
5982 free((void *)realfilename);
5983 if(r < 0) goto io_err;
5987 if(prc->type != Loc){
5988 int e, we_cancel;
5989 char datebuf[200];
5991 datebuf[0] = '\0';
5992 we_cancel = 0;
5994 if(!(flags & WRP_NOUSER))
5995 we_cancel = busy_cue(_("Copying to remote config"), NULL, 1);
5997 if((e = rd_update_remote(rd, datebuf)) != 0){
5998 dprint((1,
5999 "write_pinerc: error copying from %s to %s\n",
6000 rd->lf ? rd->lf : "<memory>", rd->rn ? rd->rn : "?"));
6001 if(!(flags & WRP_NOUSER)){
6002 q_status_message2(SM_ORDER | SM_DING, 3, 5,
6003 _("Error copying to %.200s: %.200s"),
6004 rd->rn, error_description(errno));
6006 q_status_message(SM_ORDER | SM_DING, 5, 5,
6007 _("Copy of config to remote folder failed, changes NOT saved remotely"));
6010 else{
6011 rd_update_metadata(rd, datebuf);
6012 rd->read_status = 'W';
6013 rd_trim_remdata(&rd);
6014 rd_close_remote(rd);
6017 if(we_cancel)
6018 cancel_busy_cue(-1);
6021 prc->outstanding_pinerc_changes = 0;
6023 if(prc->type == Loc){
6024 prc->pinerc_written = name_file_mtime(filename);
6025 dprint((2, "wrote pinerc: %s: time_pinerc_written = %ld\n",
6026 pinrc ? pinrc : "?", (long) prc->pinerc_written));
6028 else{
6029 dprint((2, "wrote pinerc: %s\n", pinrc ? pinrc : "?"));
6032 if(tmp){
6033 our_unlink(tmp);
6034 fs_give((void **)&tmp);
6037 if(linep) fs_give((void **)&linep);
6038 if(lineq) fs_give((void **)&lineq);
6040 return(0);
6042 io_err:
6043 if(!(flags & WRP_NOUSER))
6044 q_status_message2(SM_ORDER | SM_DING, 3, 5,
6045 _("Error saving configuration in \"%.200s\": %.200s"),
6046 pinrc, error_description(errno));
6048 dprint((1, "Error writing %s : %s\n", pinrc ? pinrc : "?",
6049 error_description(errno)));
6050 if(rd)
6051 rd->flags &= ~DO_REMTRIM;
6052 if(tmp){
6053 our_unlink(tmp);
6054 fs_give((void **)&tmp);
6057 if(linep) fs_give((void **)&linep);
6058 if(lineq) fs_give((void **)&lineq);
6060 return(-1);
6065 * The srcstr is UTF-8. In order to help the user with
6066 * running this pine and an old pre-alpine pine on the same config
6067 * file we attempt to convert the values of the config variables
6068 * to the user's character set before writing.
6069 * parameters: char **buf. Memory of size_t buflen allocated by caller.
6071 char *
6072 backcompat_convert_from_utf8(char **buf, size_t buflen, char *srcstr)
6074 char *converted = NULL;
6075 char *p;
6076 int its_ascii = 1;
6079 for(p = srcstr; *p && its_ascii; p++)
6080 if(*p & 0x80)
6081 its_ascii = 0;
6083 /* if it is ascii, go with that */
6084 if(its_ascii){
6085 strncpy(*buf, srcstr, buflen);
6086 converted = *buf;
6087 (*buf)[buflen-1] = '\0';
6089 else{
6090 char *trythischarset = NULL;
6093 * If it is possible to translate the UTF-8
6094 * string into the user's character set then
6095 * do that. For backwards compatibility with
6096 * old pines.
6098 if(ps_global->keyboard_charmap && ps_global->keyboard_charmap[0])
6099 trythischarset = ps_global->keyboard_charmap;
6100 else if(ps_global->display_charmap && ps_global->display_charmap[0])
6101 trythischarset = ps_global->display_charmap;
6103 if(trythischarset){
6104 SIZEDTEXT src, dst;
6106 src.data = (unsigned char *) srcstr;
6107 src.size = strlen(srcstr);
6108 memset(&dst, 0, sizeof(dst));
6109 if(utf8_cstext(&src, trythischarset, &dst, 0)){
6110 if(dst.data){
6111 strncpy(*buf, (char *) dst.data, buflen);
6112 (*buf)[buflen-1] = '\0';
6113 fs_give((void **) &dst.data);
6118 if(!converted){
6119 strncpy(*buf, srcstr, buflen);
6120 (*buf)[buflen-1] = '\0';
6121 converted = *buf;
6125 return(converted);
6130 * Given a unix-style source string which may contain LFs,
6131 * convert those to CRLFs if appropriate.
6133 * Returns a pointer to the converted string. This will be a string
6134 * stored in tmp_20k_buf.
6136 * This is just used for the variable descriptions in the pinerc file. It
6137 * could certainly be fancier. It simply converts all \n to NEWLINE.
6139 char *
6140 native_nl(char *src)
6142 char *q, *p;
6144 tmp_20k_buf[0] = '\0';
6146 if(src){
6147 for(q = (char *)tmp_20k_buf; *src; src++){
6148 if(*src == '\n'){
6149 for(p = NEWLINE; *p; p++)
6150 *q++ = *p;
6152 else
6153 *q++ = *src;
6156 *q = '\0';
6159 return((char *)tmp_20k_buf);
6163 void
6164 quit_to_edit_msg(PINERC_S *prc)
6166 /* TRANSLATORS: The %s is either "Postload " or nothing. A Postload config file
6167 is a type of config file. */
6168 q_status_message1(SM_ORDER, 3, 4, _("Must quit Alpine to change %sconfig file."),
6169 (prc == ps_global->post_prc) ? "Postload " : "");
6173 /*------------------------------------------------------------
6174 Return TRUE if the given string was a feature name present in the
6175 pinerc as it was when pine was started...
6176 ----*/
6178 var_in_pinerc(char *s)
6180 PINERC_LINE *pline;
6182 for(pline = ps_global->prc ? ps_global->prc->pinerc_lines : NULL;
6183 pline && (pline->var || pline->line); pline++)
6184 if(pline->var && pline->var->name && !strucmp(s, pline->var->name))
6185 return(1);
6187 for(pline = ps_global->post_prc ? ps_global->post_prc->pinerc_lines : NULL;
6188 pline && (pline->var || pline->line); pline++)
6189 if(pline->var && pline->var->name && !strucmp(s, pline->var->name))
6190 return(1);
6192 return(0);
6196 /*------------------------------------------------------------
6197 Free resources associated with pinerc_lines data
6198 ----*/
6199 void
6200 free_pinerc_lines(PINERC_LINE **pinerc_lines)
6202 PINERC_LINE *pline;
6204 if(pinerc_lines && *pinerc_lines){
6205 for(pline = *pinerc_lines; pline->var || pline->line; pline++)
6206 if(pline->line)
6207 fs_give((void **)&pline->line);
6209 fs_give((void **)pinerc_lines);
6214 /*------------------------------------------------------------
6215 Dump out a global pine.conf on the standard output with fresh
6216 comments. Preserves variables currently set in SYSTEM_PINERC, if any.
6217 ----*/
6218 void
6219 dump_global_conf(void)
6221 FILE *f;
6222 struct variable *var;
6223 PINERC_S *prc;
6225 prc = new_pinerc_s(SYSTEM_PINERC);
6226 read_pinerc(prc, variables, ParseGlobal);
6227 if(prc)
6228 free_pinerc_s(&prc);
6230 f = stdout;
6231 if(f == NULL)
6232 goto io_err;
6234 fprintf(f, "# %s -- system wide pine configuration\n#\n",
6235 SYSTEM_PINERC);
6236 fprintf(f, "# Values here affect all pine users unless they've overridden the values\n");
6237 fprintf(f, "# in their .pinerc files. A copy of this file with current comments may\n");
6238 fprintf(f, "# be obtained by running \"pine -conf\". It will be printed to standard output.\n#\n");
6239 fprintf(f,"# For a variable to be unset its value must be null/blank. This is not the\n");
6240 fprintf(f,"# same as the value of \"empty string\", which can be used to effectively\n");
6241 fprintf(f,"# \"unset\" a variable that has a default or previously assigned value.\n");
6242 fprintf(f,"# To set a variable to the empty string its value should be \"\".\n");
6243 fprintf(f,"# Switch variables are set to either \"yes\" or \"no\", and default to \"no\".\n");
6244 fprintf(f,"# Except for feature-list items, which are additive, values set in the\n");
6245 fprintf(f,"# .pinerc file replace those in pine.conf, and those in pine.conf.fixed\n");
6246 fprintf(f,"# over-ride all others. Features can be over-ridden in .pinerc or\n");
6247 fprintf(f,"# pine.conf.fixed by pre-pending the feature name with \"no-\".\n#\n");
6248 fprintf(f,"# (These comments are automatically inserted.)\n");
6250 for(var = variables; var->name != NULL; var++){
6251 if(!var->is_global || !var->is_used || var->is_obsolete)
6252 continue;
6254 if(var->descrip && *var->descrip){
6255 if(fprintf(f, "\n# %s\n", var->descrip) == EOF)
6256 goto io_err;
6259 if(var->is_list){
6260 if(var->global_val.l == NULL){
6261 if(fprintf(f, "%s=\n", var->name) == EOF)
6262 goto io_err;
6263 }else{
6264 int i;
6266 for(i=0; var->global_val.l[i]; i++)
6267 if(fprintf(f, "%s%s%s%s\n", (i) ? "\t" : var->name,
6268 (i) ? "" : "=", var->global_val.l[i],
6269 var->global_val.l[i+1] ? ",":"") == EOF)
6270 goto io_err;
6272 }else{
6273 if(var->global_val.p == NULL){
6274 if(fprintf(f, "%s=\n", var->name) == EOF)
6275 goto io_err;
6276 }else if(strlen(var->global_val.p) == 0){
6277 if(fprintf(f, "%s=\"\"\n", var->name) == EOF)
6278 goto io_err;
6279 }else{
6280 if(fprintf(f,"%s=%s\n",var->name,var->global_val.p) == EOF)
6281 goto io_err;
6285 exit(0);
6288 io_err:
6289 fprintf(stderr, "Error writing config to stdout: %s\n",
6290 error_description(errno));
6291 exit(-1);
6295 /*------------------------------------------------------------
6296 Dump out a pinerc to filename with fresh
6297 comments. Preserves variables currently set in pinerc, if any.
6298 ----*/
6299 void
6300 dump_new_pinerc(char *filename)
6302 FILE *f;
6303 struct variable *var;
6304 char buf[MAXPATH], *p;
6305 PINERC_S *prc;
6308 p = ps_global->pinerc;
6310 #if defined(DOS) || defined(OS2)
6311 if(!ps_global->pinerc){
6312 char *p;
6314 if(p = getenv("PINERC")){
6315 ps_global->pinerc = cpystr(p);
6316 }else{
6317 char buf2[MAXPATH];
6318 build_path(buf2, ps_global->home_dir, DF_PINEDIR, sizeof(buf2));
6319 build_path(buf, buf2, SYSTEM_PINERC, sizeof(buf));
6322 p = buf;
6324 #else /* !DOS */
6325 if(!ps_global->pinerc){
6326 build_path(buf, ps_global->home_dir, ".pinerc", sizeof(buf));
6327 p = buf;
6329 #endif /* !DOS */
6331 prc = new_pinerc_s(p);
6332 read_pinerc(prc, variables, ParsePers);
6333 if(prc)
6334 free_pinerc_s(&prc);
6336 f = NULL;;
6337 if(filename[0] == '\0'){
6338 fprintf(stderr, "Missing argument to \"-pinerc\".\n");
6339 }else if(!strcmp(filename, "-")){
6340 f = stdout;
6341 }else{
6342 f = our_fopen(filename, "wb");
6345 if(f == NULL)
6346 goto io_err;
6348 if(fprintf(f, "%s", cf_text_comment) == EOF)
6349 goto io_err;
6351 for(var = variables; var->name != NULL; var++){
6352 dprint((7,"write_pinerc: %s = %s\n",
6353 var->name ? var->name : "?",
6354 var->main_user_val.p ? var->main_user_val.p : "<not set>"));
6355 if(!var->is_user || !var->is_used || var->is_obsolete)
6356 continue;
6359 * set description to NULL to eliminate preceding
6360 * blank and comment line.
6362 if(var->descrip && *var->descrip){
6363 if(fprintf(f, "\n# %s\n", var->descrip) == EOF)
6364 goto io_err;
6367 if(var->is_list){
6368 if(var->main_user_val.l == NULL){
6369 if(fprintf(f, "%s=\n", var->name) == EOF)
6370 goto io_err;
6371 }else{
6372 int i;
6374 for(i=0; var->main_user_val.l[i]; i++)
6375 if(fprintf(f, "%s%s%s%s\n", (i) ? "\t" : var->name,
6376 (i) ? "" : "=", var->main_user_val.l[i],
6377 var->main_user_val.l[i+1] ? ",":"") == EOF)
6378 goto io_err;
6380 }else{
6381 if(var->main_user_val.p == NULL){
6382 if(fprintf(f, "%s=\n", var->name) == EOF)
6383 goto io_err;
6384 }else if(strlen(var->main_user_val.p) == 0){
6385 if(fprintf(f, "%s=\"\"\n", var->name) == EOF)
6386 goto io_err;
6387 }else{
6388 if(fprintf(f,"%s=%s\n",var->name,var->main_user_val.p) == EOF)
6389 goto io_err;
6393 exit(0);
6396 io_err:
6397 snprintf(buf, sizeof(buf), "Error writing config to %s: %s\n",
6398 filename, error_description(errno));
6399 exceptional_exit(buf, -1);
6403 /*----------------------------------------------------------------------
6404 Set a user variable and save the .pinerc
6406 Args: var -- The index of the variable to set from conftype.h (V_....)
6407 value -- The string to set the value to
6409 Result: -1 is returned on failure and 0 is returned on success
6411 The vars data structure is updated and the pinerc saved.
6412 ----*/
6414 set_variable(int var, char *value, int expand, int commit, EditWhich which)
6416 struct variable *v;
6417 char **apval;
6418 PINERC_S *prc;
6420 v = &ps_global->vars[var];
6422 if(!v->is_user)
6423 panic1("Trying to set non-user variable %s", v->name);
6425 /* Override value of which, at most one of these should be set */
6426 if(v->is_onlymain)
6427 which = Main;
6428 else if(v->is_outermost)
6429 which = ps_global->ew_for_except_vars;
6431 apval = APVAL(v, which);
6433 if(!apval)
6434 return(-1);
6436 if(*apval)
6437 fs_give((void **)apval);
6439 *apval = value ? cpystr(value) : NULL;
6440 set_current_val(v, expand, FALSE);
6442 switch(which){
6443 case Main:
6444 prc = ps_global->prc;
6445 break;
6446 case Post:
6447 prc = ps_global->post_prc;
6448 break;
6449 default:
6450 break;
6453 if(prc)
6454 prc->outstanding_pinerc_changes = 1;
6456 return(commit ? write_pinerc(ps_global, which, WRP_NONE) : 0);
6460 /*----------------------------------------------------------------------
6461 Set a user variable list and save the .pinerc
6463 Args: var -- The index of the variable to set from conftype.h (V_....)
6464 lvalue -- The list to set the value to
6466 Result: -1 is returned on failure and 0 is returned on success
6468 The vars data structure is updated and if write_it, the pinerc is saved.
6469 ----*/
6471 set_variable_list(int var, char **lvalue, int write_it, EditWhich which)
6473 char ***alval;
6474 int i;
6475 struct variable *v = &ps_global->vars[var];
6476 PINERC_S *prc;
6478 if(!v->is_user || !v->is_list)
6479 panic1("BOTCH: Trying to set non-user or non-list variable %s", v->name);
6481 /* Override value of which, at most one of these should be set */
6482 if(v->is_onlymain)
6483 which = Main;
6484 else if(v->is_outermost)
6485 which = ps_global->ew_for_except_vars;
6487 alval = ALVAL(v, which);
6488 if(!alval)
6489 return(-1);
6491 if(*alval)
6492 free_list_array(alval);
6494 if(lvalue){
6495 for(i = 0; lvalue[i] ; i++) /* count elements */
6498 *alval = (char **) fs_get((i+1) * sizeof(char *));
6500 for(i = 0; lvalue[i] ; i++)
6501 (*alval)[i] = cpystr(lvalue[i]);
6503 (*alval)[i] = NULL;
6506 set_current_val(v, TRUE, FALSE);
6508 switch(which){
6509 case Main:
6510 prc = ps_global->prc;
6511 break;
6512 case Post:
6513 prc = ps_global->post_prc;
6514 break;
6515 default:
6516 break;
6519 if(prc)
6520 prc->outstanding_pinerc_changes = 1;
6522 return(write_it ? write_pinerc(ps_global, which, WRP_NONE) : 0);
6526 void
6527 set_current_color_vals(struct pine *ps)
6529 struct variable *vars = ps->vars;
6530 int later_color_is_set = 0;
6532 set_current_val(&vars[V_NORM_FORE_COLOR], TRUE, TRUE);
6533 set_current_val(&vars[V_NORM_BACK_COLOR], TRUE, TRUE);
6534 pico_nfcolor(VAR_NORM_FORE_COLOR);
6535 pico_nbcolor(VAR_NORM_BACK_COLOR);
6537 set_current_val(&vars[V_REV_FORE_COLOR], TRUE, TRUE);
6538 set_current_val(&vars[V_REV_BACK_COLOR], TRUE, TRUE);
6539 pico_rfcolor(VAR_REV_FORE_COLOR);
6540 pico_rbcolor(VAR_REV_BACK_COLOR);
6542 set_color_val(&vars[V_TITLE_FORE_COLOR], 1);
6543 set_color_val(&vars[V_TITLECLOSED_FORE_COLOR], 0);
6544 set_color_val(&vars[V_FOLDER_FORE_COLOR], 0);
6545 set_color_val(&vars[V_DIRECTORY_FORE_COLOR], 0);
6546 set_color_val(&vars[V_FOLDER_LIST_FORE_COLOR], 0);
6547 set_color_val(&vars[V_STATUS_FORE_COLOR], 1);
6548 set_color_val(&vars[V_KEYLABEL_FORE_COLOR], 1);
6549 set_color_val(&vars[V_KEYNAME_FORE_COLOR], 1);
6550 set_color_val(&vars[V_SLCTBL_FORE_COLOR], 1);
6551 set_color_val(&vars[V_METAMSG_FORE_COLOR], 1);
6552 set_color_val(&vars[V_PROMPT_FORE_COLOR], 1);
6553 set_color_val(&vars[V_HEADER_GENERAL_FORE_COLOR], 1);
6554 set_color_val(&vars[V_IND_PLUS_FORE_COLOR], 0);
6555 set_color_val(&vars[V_IND_IMP_FORE_COLOR], 0);
6556 set_color_val(&vars[V_IND_DEL_FORE_COLOR], 0);
6557 set_color_val(&vars[V_IND_HIPRI_FORE_COLOR], 0);
6558 set_color_val(&vars[V_IND_LOPRI_FORE_COLOR], 0);
6559 set_color_val(&vars[V_IND_ANS_FORE_COLOR], 0);
6560 set_color_val(&vars[V_IND_NEW_FORE_COLOR], 0);
6561 set_color_val(&vars[V_IND_REC_FORE_COLOR], 0);
6562 set_color_val(&vars[V_IND_FWD_FORE_COLOR], 0);
6563 set_color_val(&vars[V_IND_UNS_FORE_COLOR], 0);
6564 set_color_val(&vars[V_IND_ARR_FORE_COLOR], 0);
6565 set_color_val(&vars[V_IND_SUBJ_FORE_COLOR], 0);
6566 set_color_val(&vars[V_IND_FROM_FORE_COLOR], 0);
6567 set_color_val(&vars[V_IND_OP_FORE_COLOR], 0);
6568 set_color_val(&vars[V_INCUNSEEN_FORE_COLOR], 0);
6569 set_color_val(&vars[V_SIGNATURE_FORE_COLOR], 0);
6571 set_current_val(&ps->vars[V_INDEX_TOKEN_COLORS], TRUE, TRUE);
6572 set_current_val(&ps->vars[V_VIEW_HDR_COLORS], TRUE, TRUE);
6573 set_current_val(&ps->vars[V_KW_COLORS], TRUE, TRUE);
6574 set_custom_spec_colors(ps);
6577 * Set up the quoting colors. If a later color is set but not an earlier
6578 * color we set the earlier color to Normal to make it easier when
6579 * we go to use the colors. However, if the only quote colors set are
6580 * Normal that is the same as no settings, so delete them.
6582 set_color_val(&vars[V_QUOTE1_FORE_COLOR], 0);
6583 set_color_val(&vars[V_QUOTE2_FORE_COLOR], 0);
6584 set_color_val(&vars[V_QUOTE3_FORE_COLOR], 0);
6586 if((!(VAR_QUOTE3_FORE_COLOR && VAR_QUOTE3_BACK_COLOR) ||
6587 (!strucmp(VAR_QUOTE3_FORE_COLOR, VAR_NORM_FORE_COLOR) &&
6588 !strucmp(VAR_QUOTE3_BACK_COLOR, VAR_NORM_BACK_COLOR))) &&
6589 (!(VAR_QUOTE2_FORE_COLOR && VAR_QUOTE2_BACK_COLOR) ||
6590 (!strucmp(VAR_QUOTE2_FORE_COLOR, VAR_NORM_FORE_COLOR) &&
6591 !strucmp(VAR_QUOTE2_BACK_COLOR, VAR_NORM_BACK_COLOR))) &&
6592 (!(VAR_QUOTE1_FORE_COLOR && VAR_QUOTE1_BACK_COLOR) ||
6593 (!strucmp(VAR_QUOTE1_FORE_COLOR, VAR_NORM_FORE_COLOR) &&
6594 !strucmp(VAR_QUOTE1_BACK_COLOR, VAR_NORM_BACK_COLOR)))){
6596 * They are all either Normal or not set. Delete them all.
6598 if(VAR_QUOTE3_FORE_COLOR)
6599 fs_give((void **)&VAR_QUOTE3_FORE_COLOR);
6600 if(VAR_QUOTE3_BACK_COLOR)
6601 fs_give((void **)&VAR_QUOTE3_BACK_COLOR);
6602 if(VAR_QUOTE2_FORE_COLOR)
6603 fs_give((void **)&VAR_QUOTE2_FORE_COLOR);
6604 if(VAR_QUOTE2_BACK_COLOR)
6605 fs_give((void **)&VAR_QUOTE2_BACK_COLOR);
6606 if(VAR_QUOTE1_FORE_COLOR)
6607 fs_give((void **)&VAR_QUOTE1_FORE_COLOR);
6608 if(VAR_QUOTE1_BACK_COLOR)
6609 fs_give((void **)&VAR_QUOTE1_BACK_COLOR);
6611 else{ /* something is non-Normal */
6612 if(VAR_QUOTE3_FORE_COLOR && VAR_QUOTE3_BACK_COLOR)
6613 later_color_is_set++;
6615 /* if 3 is set but not 2, set 2 to Normal */
6616 if(VAR_QUOTE2_FORE_COLOR && VAR_QUOTE2_BACK_COLOR)
6617 later_color_is_set++;
6618 else if(later_color_is_set)
6619 set_color_val(&vars[V_QUOTE2_FORE_COLOR], 1);
6621 /* if 3 or 2 is set but not 1, set 1 to Normal */
6622 if(VAR_QUOTE1_FORE_COLOR && VAR_QUOTE1_BACK_COLOR)
6623 later_color_is_set++;
6624 else if(later_color_is_set)
6625 set_color_val(&vars[V_QUOTE1_FORE_COLOR], 1);
6628 #ifdef _WINDOWS
6629 if(ps->pre441){
6630 int conv_main = 0, conv_post = 0;
6632 ps->pre441 = 0;
6633 if(ps->prc && !unix_color_style_in_pinerc(ps->prc)){
6634 conv_main = convert_pc_gray_names(ps, ps->prc, Main);
6635 if(conv_main)
6636 ps->prc->outstanding_pinerc_changes = 1;
6640 if(ps->post_prc && !unix_color_style_in_pinerc(ps->post_prc)){
6641 conv_post = convert_pc_gray_names(ps, ps->post_prc, Post);
6642 if(conv_post)
6643 ps->post_prc->outstanding_pinerc_changes = 1;
6646 if(conv_main || conv_post){
6647 if(conv_main)
6648 write_pinerc(ps, Main, WRP_NONE);
6650 if(conv_post)
6651 write_pinerc(ps, Post, WRP_NONE);
6653 set_current_color_vals(ps);
6656 #endif /* _WINDOWS */
6658 pico_set_normal_color();
6663 * Set current_val for the foreground and background color vars, which
6664 * are assumed to be in order. If a set_current_val on them doesn't
6665 * produce current_vals, then use the colors from defvar to set those
6666 * current_vals.
6668 void
6669 set_color_val(struct variable *v, int use_default)
6671 set_current_val(v, TRUE, TRUE);
6672 set_current_val(v+1, TRUE, TRUE);
6674 if(!(v->current_val.p && v->current_val.p[0] &&
6675 (v+1)->current_val.p && (v+1)->current_val.p[0])){
6676 struct variable *defvar;
6678 if(v->current_val.p)
6679 fs_give((void **)&v->current_val.p);
6680 if((v+1)->current_val.p)
6681 fs_give((void **)&(v+1)->current_val.p);
6683 if(!use_default)
6684 return;
6686 if(var_defaults_to_rev(v))
6687 defvar = &ps_global->vars[V_REV_FORE_COLOR];
6688 else
6689 defvar = &ps_global->vars[V_NORM_FORE_COLOR];
6691 /* use default vars values instead */
6692 if(defvar && defvar->current_val.p && defvar->current_val.p[0] &&
6693 (defvar+1)->current_val.p && (defvar+1)->current_val.p[0]){
6694 v->current_val.p = cpystr(defvar->current_val.p);
6695 (v+1)->current_val.p = cpystr((defvar+1)->current_val.p);
6702 var_defaults_to_rev(struct variable *v)
6704 return(v == &ps_global->vars[V_REV_FORE_COLOR] ||
6705 v == &ps_global->vars[V_TITLE_FORE_COLOR] ||
6706 v == &ps_global->vars[V_STATUS_FORE_COLOR] ||
6707 v == &ps_global->vars[V_KEYNAME_FORE_COLOR] ||
6708 v == &ps_global->vars[V_PROMPT_FORE_COLOR]);
6714 * Each item in the list looks like:
6716 * /HDR=<header>/FG=<foreground color>/BG=<background color>
6718 * We separate the three pieces into an array of structures to make
6719 * it easier to deal with later.
6721 void
6722 set_custom_spec_colors(struct pine *ps)
6724 if(ps->index_token_colors)
6725 free_spec_colors(&ps->index_token_colors);
6727 ps->index_token_colors = spec_colors_from_varlist(ps->VAR_INDEX_TOKEN_COLORS, 1);
6729 if(ps->hdr_colors)
6730 free_spec_colors(&ps->hdr_colors);
6732 ps->hdr_colors = spec_colors_from_varlist(ps->VAR_VIEW_HDR_COLORS, 1);
6734 /* fit keyword colors into the same structures for code re-use */
6735 if(ps->kw_colors)
6736 free_spec_colors(&ps->kw_colors);
6738 ps->kw_colors = spec_colors_from_varlist(ps->VAR_KW_COLORS, 1);
6743 * Input is one item from config variable.
6745 * Return value must be freed by caller. The return is a single SPEC_COLOR_S,
6746 * not a list.
6748 SPEC_COLOR_S *
6749 spec_color_from_var(char *t, int already_expanded)
6751 char *p, *spec, *fg, *bg;
6752 PATTERN_S *val;
6753 SPEC_COLOR_S *new_hcolor = NULL;
6755 if(t && t[0] && !strcmp(t, INHERIT)){
6756 new_hcolor = (SPEC_COLOR_S *)fs_get(sizeof(*new_hcolor));
6757 memset((void *)new_hcolor, 0, sizeof(*new_hcolor));
6758 new_hcolor->inherit = 1;
6760 else if(t && t[0]){
6761 char tbuf[10000];
6763 if(!already_expanded){
6764 tbuf[0] = '\0';
6765 if(expand_variables(tbuf, sizeof(tbuf), t, 0))
6766 t = tbuf;
6769 spec = fg = bg = NULL;
6770 val = NULL;
6771 if((p = srchstr(t, "/HDR=")) != NULL)
6772 spec = remove_backslash_escapes(p+5);
6773 if((p = srchstr(t, "/FG=")) != NULL)
6774 fg = remove_backslash_escapes(p+4);
6775 if((p = srchstr(t, "/BG=")) != NULL)
6776 bg = remove_backslash_escapes(p+4);
6777 val = parse_pattern("VAL", t, 0);
6779 if(spec && *spec){
6780 /* remove colons */
6781 if((p = strindex(spec, ':')) != NULL)
6782 *p = '\0';
6784 new_hcolor = (SPEC_COLOR_S *)fs_get(sizeof(*new_hcolor));
6785 memset((void *)new_hcolor, 0, sizeof(*new_hcolor));
6786 new_hcolor->spec = spec;
6787 new_hcolor->fg = fg;
6788 new_hcolor->bg = bg;
6789 new_hcolor->val = val;
6791 else{
6792 if(spec)
6793 fs_give((void **)&spec);
6794 if(fg)
6795 fs_give((void **)&fg);
6796 if(bg)
6797 fs_give((void **)&bg);
6798 if(val)
6799 free_pattern(&val);
6803 return(new_hcolor);
6808 * Input is a list from config file.
6810 * Return value may be a list of SPEC_COLOR_S and must be freed by caller.
6812 SPEC_COLOR_S *
6813 spec_colors_from_varlist(char **varlist, int already_expanded)
6815 char **s, *t;
6816 SPEC_COLOR_S *new_hc = NULL;
6817 SPEC_COLOR_S *new_hcolor, **nexthc;
6819 nexthc = &new_hc;
6820 if(varlist){
6821 for(s = varlist; (t = *s) != NULL; s++){
6822 if(t[0]){
6823 new_hcolor = spec_color_from_var(t, already_expanded);
6824 if(new_hcolor){
6825 *nexthc = new_hcolor;
6826 nexthc = &new_hcolor->next;
6832 return(new_hc);
6837 * Returns allocated charstar suitable for config var for a single
6838 * SPEC_COLOR_S.
6840 char *
6841 var_from_spec_color(SPEC_COLOR_S *hc)
6843 char *ret_val = NULL;
6844 char *p, *spec = NULL, *fg = NULL, *bg = NULL, *val = NULL;
6845 size_t len;
6847 if(hc && hc->inherit)
6848 ret_val = cpystr(INHERIT);
6849 else if(hc){
6850 if(hc->spec)
6851 spec = add_viewerhdr_escapes(hc->spec);
6852 if(hc->fg)
6853 fg = add_viewerhdr_escapes(hc->fg);
6854 if(hc->bg)
6855 bg = add_viewerhdr_escapes(hc->bg);
6856 if(hc->val){
6857 p = pattern_to_string(hc->val);
6858 if(p){
6859 val = add_viewerhdr_escapes(p);
6860 fs_give((void **)&p);
6864 len = strlen("/HDR=/FG=/BG=") + strlen(spec ? spec : "") +
6865 strlen(fg ? fg : "") + strlen(bg ? bg : "") +
6866 strlen(val ? "/VAL=" : "") + strlen(val ? val : "");
6867 ret_val = (char *) fs_get(len + 1);
6868 snprintf(ret_val, len+1, "/HDR=%s/FG=%s/BG=%s%s%s",
6869 spec ? spec : "", fg ? fg : "", bg ? bg : "",
6870 val ? "/VAL=" : "", val ? val : "");
6872 if(spec)
6873 fs_give((void **)&spec);
6874 if(fg)
6875 fs_give((void **)&fg);
6876 if(bg)
6877 fs_give((void **)&bg);
6878 if(val)
6879 fs_give((void **)&val);
6882 return(ret_val);
6887 * Returns allocated charstar suitable for config var for a single
6888 * SPEC_COLOR_S.
6890 char **
6891 varlist_from_spec_colors(SPEC_COLOR_S *hcolors)
6893 SPEC_COLOR_S *hc;
6894 char **ret_val = NULL;
6895 int i;
6897 /* count how many */
6898 for(hc = hcolors, i = 0; hc; hc = hc->next, i++)
6901 ret_val = (char **)fs_get((i+1) * sizeof(*ret_val));
6902 memset((void *)ret_val, 0, (i+1) * sizeof(*ret_val));
6903 for(hc = hcolors, i = 0; hc; hc = hc->next, i++)
6904 ret_val[i] = var_from_spec_color(hc);
6906 return(ret_val);
6910 void
6911 update_posting_charset(struct pine *ps, int revert)
6913 #ifndef _WINDOWS
6914 if(F_ON(F_USE_SYSTEM_TRANS, ps)){
6915 if(!revert)
6916 q_status_message(SM_ORDER, 5, 5, _("This change has no effect because feature Use-System-Translation is on"));
6918 else{
6919 #endif /* ! _WINDOWS */
6920 if(ps->posting_charmap)
6921 fs_give((void **) &ps->posting_charmap);
6923 if(ps->VAR_POST_CHAR_SET){
6924 ps->posting_charmap = cpystr(ps->VAR_POST_CHAR_SET);
6925 if(!posting_charset_is_supported(ps->posting_charmap)){
6926 snprintf(tmp_20k_buf, SIZEOF_20KBUF,
6927 _("Posting-Character set \"%s\" is unsupported, using UTF-8"),
6928 ps->posting_charmap);
6929 q_status_message(SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
6930 fs_give((void **) &ps->posting_charmap);
6931 ps->posting_charmap = cpystr("UTF-8");
6934 else
6935 ps->posting_charmap = cpystr("UTF-8");
6936 #ifndef _WINDOWS
6938 #endif /* ! _WINDOWS */
6942 #define FIXED_COMMENT _("(fixed)")
6943 #define DEFAULT_COMMENT _("(default)")
6944 #define OVERRIDE_COMMENT _("(overridden)")
6947 feature_gets_an_x(struct pine *ps, struct variable *var, FEATURE_S *feature,
6948 char **comment, EditWhich ew)
6950 char **lval, **lvalexc, **lvalnorm;
6951 char *def = DEFAULT_COMMENT;
6952 int j, done = 0;
6953 int feature_fixed_on = 0, feature_fixed_off = 0;
6955 if(comment)
6956 *comment = NULL;
6958 lval = LVAL(var, ew);
6959 lvalexc = LVAL(var, ps->ew_for_except_vars);
6960 lvalnorm = LVAL(var, Main);
6962 /* feature value is administratively fixed */
6963 if((j = feature_in_list(var->fixed_val.l, feature->name)) != 0){
6964 if(j == 1)
6965 feature_fixed_on++;
6966 else if(j == -1)
6967 feature_fixed_off++;
6969 done++;
6970 if(comment)
6971 *comment = FIXED_COMMENT;
6975 * We have an exceptions config setting which overrides anything
6976 * we do here, in the normal config.
6978 if(!done &&
6979 ps->ew_for_except_vars != Main && ew == Main &&
6980 feature_in_list(lvalexc, feature->name)){
6981 done++;
6982 if(comment)
6983 *comment = OVERRIDE_COMMENT;
6987 * Feature is set On in default but not set here.
6989 if(!done &&
6990 !feature_in_list(lval, feature->name) &&
6991 ((feature_in_list(var->global_val.l, feature->name) == 1) ||
6992 ((ps->ew_for_except_vars != Main &&
6993 ew == ps->ew_for_except_vars &&
6994 feature_in_list(lvalnorm, feature->name) == 1)))){
6995 done = 17;
6996 if(comment)
6997 *comment = def;
7000 if(!done &&
7001 feature->defval &&
7002 !feature_in_list(lval, feature->name) &&
7003 !feature_in_list(var->global_val.l, feature->name) &&
7004 (ps->ew_for_except_vars == Main ||
7005 ew != ps->ew_for_except_vars ||
7006 !feature_in_list(lvalnorm, feature->name))){
7007 done = 17;
7008 if(comment)
7009 *comment = def;
7012 return(feature_fixed_on ||
7013 (!feature_fixed_off &&
7014 (done == 17 ||
7015 test_feature(lval, feature->name,
7016 test_old_growth_bits(ps, feature->id)))));
7021 longest_feature_comment(struct pine *ps, EditWhich ew)
7023 int lc = 0;
7025 lc = MAX(lc, utf8_width(FIXED_COMMENT));
7026 lc = MAX(lc, utf8_width(DEFAULT_COMMENT));
7027 if(ps->ew_for_except_vars != Main && ew == Main)
7028 lc = MAX(lc, utf8_width(OVERRIDE_COMMENT));
7030 return(lc);
7034 void
7035 toggle_feature(struct pine *ps, struct variable *var, FEATURE_S *f,
7036 int just_flip_value, EditWhich ew)
7038 char **vp, *p, **lval, ***alval;
7039 int og, on_before, was_set;
7040 char *err;
7041 long l;
7043 og = test_old_growth_bits(ps, f->id);
7046 * if this feature is in the fixed set, or old-growth is in the fixed
7047 * set and this feature is in the old-growth set, don't alter it...
7049 for(vp = var->fixed_val.l; vp && *vp; vp++){
7050 p = (struncmp(*vp, "no-", 3)) ? *vp : *vp + 3;
7051 if(!strucmp(p, f->name) || (og && !strucmp(p, "old-growth"))){
7052 q_status_message(SM_ORDER, 3, 3,
7053 /* TRANSLATORS: In the configuration screen, telling the user we
7054 can't change this option because the system administrator
7055 prohibits it. */
7056 _("Can't change value fixed by sys-admin."));
7057 return;
7061 on_before = F_ON(f->id, ps);
7063 lval = LVAL(var, ew);
7064 alval = ALVAL(var, ew);
7065 if(just_flip_value)
7066 was_set = test_feature(lval, f->name, og);
7067 else
7068 was_set = feature_gets_an_x(ps, var, f, NULL, ew);
7070 if(alval)
7071 set_feature(alval, f->name, !was_set);
7073 set_feature_list_current_val(var);
7074 process_feature_list(ps, var->current_val.l, 0, 0, 0);
7077 * Handle any features that need special attention here...
7079 if(on_before != F_ON(f->id, ps))
7080 switch(f->id){
7081 case F_QUOTE_ALL_FROMS :
7082 mail_parameters(NULL,SET_FROMWIDGET,F_ON(f->id,ps) ? VOIDT : NIL);
7083 break;
7085 case F_FAKE_NEW_IN_NEWS :
7086 if(IS_NEWS(ps->mail_stream))
7087 q_status_message(SM_ORDER | SM_DING, 3, 4,
7088 "news-approximates-new-status won't affect current newsgroup until next open");
7090 break;
7092 case F_COLOR_LINE_IMPORTANT :
7093 case F_DATES_TO_LOCAL :
7094 clear_index_cache(ps->mail_stream, 0);
7095 break;
7097 case F_DISABLE_INDEX_LOCALE_DATES :
7098 reset_index_format();
7099 clear_index_cache(ps->mail_stream, 0);
7100 break;
7102 case F_MARK_FOR_CC :
7103 clear_index_cache(ps->mail_stream, 0);
7104 if(THREADING() && sp_viewing_a_thread(ps->mail_stream))
7105 unview_thread(ps, ps->mail_stream, ps->msgmap);
7107 break;
7109 case F_HIDE_NNTP_PATH :
7110 mail_parameters(NULL, SET_NNTPHIDEPATH,
7111 F_ON(f->id, ps) ? VOIDT : NIL);
7112 break;
7114 case F_MAILDROPS_PRESERVE_STATE :
7115 mail_parameters(NULL, SET_SNARFPRESERVE,
7116 F_ON(f->id, ps) ? VOIDT : NIL);
7117 break;
7119 case F_DISABLE_SHARED_NAMESPACES :
7120 mail_parameters(NULL, SET_DISABLEAUTOSHAREDNS,
7121 F_ON(f->id, ps) ? VOIDT : NIL);
7122 break;
7124 case F_QUELL_LOCK_FAILURE_MSGS :
7125 mail_parameters(NULL, SET_LOCKEACCESERROR,
7126 F_ON(f->id, ps) ? VOIDT : NIL);
7127 break;
7129 case F_MULNEWSRC_HOSTNAMES_AS_TYPED :
7130 l = F_ON(f->id, ps) ? 0L : 1L;
7131 mail_parameters(NULL, SET_NEWSRCCANONHOST, (void *) l);
7132 break;
7134 case F_QUELL_INTERNAL_MSG :
7135 mail_parameters(NULL, SET_USERHASNOLIFE,
7136 F_ON(f->id, ps) ? VOIDT : NIL);
7137 break;
7139 case F_DISABLE_SETLOCALE_COLLATE :
7140 set_collation(F_OFF(F_DISABLE_SETLOCALE_COLLATE, ps), 1);
7141 break;
7143 #ifndef _WINDOWS
7144 case F_USE_SYSTEM_TRANS :
7145 err = NULL;
7146 reset_character_set_stuff(&err);
7147 if(err){
7148 q_status_message(SM_ORDER | SM_DING, 3, 4, err);
7149 fs_give((void **) &err);
7152 break;
7153 #endif /* ! _WINDOWS */
7155 case F_ENABLE_INCOMING_CHECKING :
7156 if(!on_before && F_OFF(F_ENABLE_INCOMING, ps))
7157 q_status_message(SM_ORDER, 0, 3, _("This option has no effect without Enable-Incoming-Folders"));
7159 clear_incoming_valid_bits();
7160 break;
7162 case F_INCOMING_CHECKING_TOTAL :
7163 case F_INCOMING_CHECKING_RECENT :
7164 if(!on_before && F_OFF(F_ENABLE_INCOMING_CHECKING, ps))
7165 q_status_message(SM_ORDER, 0, 3, _("This option has no effect without Enable-Incoming-Folders-Checking"));
7167 clear_incoming_valid_bits();
7168 break;
7170 case F_THREAD_SORTS_BY_ARRIVAL :
7171 clear_index_cache(ps->mail_stream, 0);
7172 refresh_sort(ps->mail_stream, sp_msgmap(ps->mail_stream), SRT_NON);
7173 break;
7175 #ifdef SMIME
7176 case F_DONT_DO_SMIME :
7177 smime_deinit();
7178 break;
7180 #ifdef APPLEKEYCHAIN
7181 case F_PUBLICCERTS_IN_KEYCHAIN :
7182 smime_deinit();
7183 break;
7184 #endif
7185 #endif
7187 default :
7188 break;
7194 * Returns 1 -- Feature is in the list and positive
7195 * 0 -- Feature is not in the list at all
7196 * -1 -- Feature is in the list and negative (no-)
7199 feature_in_list(char **l, char *f)
7201 char *p;
7202 int rv = 0, forced_off;
7204 for(; l && *l; l++){
7205 p = (forced_off = !struncmp(*l, "no-", 3)) ? *l + 3 : *l;
7206 if(!strucmp(p, f))
7207 rv = forced_off ? -1 : 1;
7210 return(rv);
7215 * test_feature - runs thru a feature list, and returns:
7216 * 1 if feature explicitly set and matches 'v'
7217 * 0 if feature not explicitly set *or* doesn't match 'v'
7220 test_feature(char **l, char *f, int g)
7222 char *p;
7223 int rv = 0, forced_off;
7225 for(; l && *l; l++){
7226 p = (forced_off = !struncmp(*l, "no-", 3)) ? *l + 3 : *l;
7227 if(!strucmp(p, f))
7228 rv = !forced_off;
7229 else if(g && !strucmp(p, "old-growth"))
7230 rv = !forced_off;
7233 return(rv);
7237 void
7238 set_feature(char ***l, char *f, int v)
7240 char **list = l ? *l : NULL, newval[256];
7241 int count = 0;
7243 snprintf(newval, sizeof(newval), "%s%s", v ? "" : "no-", f);
7244 for(; list && *list; list++, count++)
7245 if((**list == '\0') /* anything can replace an empty value */
7246 || !strucmp(((!struncmp(*list, "no-", 3)) ? *list + 3 : *list), f)){
7247 fs_give((void **)list); /* replace with new value */
7248 *list = cpystr(newval);
7249 return;
7253 * if we got here, we didn't find it in the list, so grow the list
7254 * and add it..
7256 if(!*l)
7257 *l = (char **)fs_get((count + 2) * sizeof(char *));
7258 else
7259 fs_resize((void **)l, (count + 2) * sizeof(char *));
7261 (*l)[count] = cpystr(newval);
7262 (*l)[count + 1] = NULL;
7267 reset_character_set_stuff(char **err)
7269 int use_system = 0;
7270 char buf[1000];
7272 if(err)
7273 *err = NULL;
7275 if(ps_global->display_charmap)
7276 fs_give((void **) &ps_global->display_charmap);
7278 if(ps_global->keyboard_charmap)
7279 fs_give((void **) &ps_global->keyboard_charmap);
7281 if(ps_global->posting_charmap)
7282 fs_give((void **) &ps_global->posting_charmap);
7284 #ifdef _WINDOWS
7285 ps_global->display_charmap = cpystr("UTF-8");
7286 #else /* UNIX */
7287 if(ps_global->VAR_CHAR_SET)
7288 ps_global->display_charmap = cpystr(ps_global->VAR_CHAR_SET);
7289 else{
7290 #if HAVE_LANGINFO_H && defined(CODESET)
7291 ps_global->display_charmap = cpystr(nl_langinfo_codeset_wrapper());
7292 #else
7293 ps_global->display_charmap = cpystr("UTF-8");
7294 #endif
7296 #endif /* UNIX */
7298 if(!ps_global->display_charmap)
7299 ps_global->display_charmap = cpystr("US-ASCII");
7301 #ifdef _WINDOWS
7302 ps_global->keyboard_charmap = cpystr("UTF-8");
7303 #else /* UNIX */
7304 if(ps_global->VAR_KEY_CHAR_SET)
7305 ps_global->keyboard_charmap = cpystr(ps_global->VAR_KEY_CHAR_SET);
7306 else
7307 ps_global->keyboard_charmap = cpystr(ps_global->display_charmap);
7309 if(!ps_global->keyboard_charmap)
7310 ps_global->keyboard_charmap = cpystr("US-ASCII");
7312 if(F_ON(F_USE_SYSTEM_TRANS, ps_global)){
7313 #if PREREQ_FOR_SYS_TRANSLATION
7314 use_system++;
7315 /* This modifies its arguments */
7316 if(setup_for_input_output(use_system, &ps_global->display_charmap,
7317 &ps_global->keyboard_charmap,
7318 &ps_global->input_cs, (err && *err) ? NULL : err) == -1)
7319 return -1;
7320 #endif
7322 #endif /* UNIX */
7324 if(!use_system){
7325 if(setup_for_input_output(use_system, &ps_global->display_charmap,
7326 &ps_global->keyboard_charmap,
7327 &ps_global->input_cs, (err && *err) ? NULL : err) == -1)
7328 return -1;
7331 if(!use_system && ps_global->VAR_POST_CHAR_SET){
7332 ps_global->posting_charmap = cpystr(ps_global->VAR_POST_CHAR_SET);
7333 if(!posting_charset_is_supported(ps_global->posting_charmap)){
7334 if(err && !*err){
7335 snprintf(buf, sizeof(buf),
7336 _("Posting-Character-Set \"%s\" is unsupported, using UTF-8"),
7337 ps_global->posting_charmap);
7338 *err = cpystr(buf);
7341 fs_give((void **) &ps_global->posting_charmap);
7342 ps_global->posting_charmap = cpystr("UTF-8");
7345 else{
7346 if(use_system && ps_global->VAR_POST_CHAR_SET
7347 && strucmp(ps_global->VAR_POST_CHAR_SET, "UTF-8"))
7348 if(err && !*err)
7349 *err = cpystr(_("Posting-Character-Set is ignored with Use-System-Translation turned on"));
7351 ps_global->posting_charmap = cpystr("UTF-8");
7354 set_locale_charmap(ps_global->keyboard_charmap);
7356 return(0);
7361 * Given a single printer string from the config file, returns pointers
7362 * to alloc'd strings containing the printer nickname, the command,
7363 * the init string, the trailer string, everything but the nickname string,
7364 * and everything but the command string. All_but_cmd includes the trailing
7365 * space at the end (the one before the command) but all_but_nick does not
7366 * include the leading space (the one before the [).
7367 * If you pass in a pointer it is guaranteed to come back pointing to an
7368 * allocated string, even if it is just an empty string. It is ok to pass
7369 * NULL for any of the six return strings.
7371 void
7372 parse_printer(char *input, char **nick, char **cmd, char **init, char **trailer,
7373 char **all_but_nick, char **all_but_cmd)
7375 char *p, *q, *start, *saved_options = NULL;
7376 int tmpsave, cnt;
7378 if(!input)
7379 input = "";
7381 if(nick || all_but_nick){
7382 if((p = srchstr(input, " [")) != NULL){
7383 if(all_but_nick)
7384 *all_but_nick = cpystr(p+1);
7386 if(nick){
7387 while(p-1 > input && isspace((unsigned char)*(p-1)))
7388 p--;
7390 tmpsave = *p;
7391 *p = '\0';
7392 *nick = cpystr(input);
7393 *p = tmpsave;
7396 else{
7397 if(nick)
7398 *nick = cpystr("");
7400 if(all_but_nick)
7401 *all_but_nick = cpystr(input);
7405 if((p = srchstr(input, "] ")) != NULL){
7407 ++p;
7408 }while(isspace((unsigned char)*p));
7410 tmpsave = *p;
7411 *p = '\0';
7412 saved_options = cpystr(input);
7413 *p = tmpsave;
7415 else
7416 p = input;
7418 if(cmd)
7419 *cmd = cpystr(p);
7421 if(init){
7422 if(saved_options && (p = srchstr(saved_options, "INIT="))){
7423 start = p + strlen("INIT=");
7424 for(cnt=0, p = start; *p && *(p+1) && isxpair(p); p += 2)
7425 cnt++;
7427 q = *init = (char *)fs_get((cnt + 1) * sizeof(char));
7428 for(p = start; *p && *(p+1) && isxpair(p); p += 2)
7429 *q++ = read_hex(p);
7431 *q = '\0';
7433 else
7434 *init = cpystr("");
7437 if(trailer){
7438 if(saved_options && (p = srchstr(saved_options, "TRAILER="))){
7439 start = p + strlen("TRAILER=");
7440 for(cnt=0, p = start; *p && *(p+1) && isxpair(p); p += 2)
7441 cnt++;
7443 q = *trailer = (char *)fs_get((cnt + 1) * sizeof(char));
7444 for(p = start; *p && *(p+1) && isxpair(p); p += 2)
7445 *q++ = read_hex(p);
7447 *q = '\0';
7449 else
7450 *trailer = cpystr("");
7453 if(all_but_cmd){
7454 if(saved_options)
7455 *all_but_cmd = saved_options;
7456 else
7457 *all_but_cmd = cpystr("");
7459 else if(saved_options)
7460 fs_give((void **)&saved_options);
7465 copy_pinerc(char *local, char *remote, char **err_msg)
7467 return(copy_localfile_to_remotefldr(RemImap, local, remote,
7468 REMOTE_PINERC_SUBTYPE,
7469 err_msg));
7474 copy_abook(char *local, char *remote, char **err_msg)
7476 return(copy_localfile_to_remotefldr(RemImap, local, remote,
7477 REMOTE_ABOOK_SUBTYPE,
7478 err_msg));
7483 * Copy local file to remote folder.
7485 * Args remotetype -- type of remote folder
7486 * local -- name of local file
7487 * remote -- name of remote folder
7488 * subtype --
7490 * Returns 0 on success.
7493 copy_localfile_to_remotefldr(RemType remotetype, char *local, char *remote,
7494 char *subtype, char **err_msg)
7496 int retfail = -1;
7497 unsigned flags;
7498 REMDATA_S *rd;
7500 dprint((9, "copy_localfile_to_remotefldr(%s,%s)\n",
7501 local ? local : "<null>",
7502 remote ? remote : "<null>"));
7504 *err_msg = (char *)fs_get(MAXPATH * sizeof(char));
7506 if(!local || !*local){
7507 snprintf(*err_msg, MAXPATH, _("No local file specified"));
7508 return(retfail);
7511 if(!remote || !*remote){
7512 snprintf(*err_msg, MAXPATH, _("No remote folder specified"));
7513 return(retfail);
7516 if(!IS_REMOTE(remote)){
7517 snprintf(*err_msg, MAXPATH, _("Remote folder name \"%s\" %s"), remote,
7518 (*remote != '{') ? _("must begin with \"{\"") : _("not valid"));
7519 return(retfail);
7522 if(IS_REMOTE(local)){
7523 snprintf(*err_msg, MAXPATH, _("First argument \"%s\" must be a local filename"),
7524 local);
7525 return(retfail);
7528 if(can_access(local, ACCESS_EXISTS) != 0){
7529 snprintf(*err_msg, MAXPATH, _("Local file \"%s\" does not exist"), local);
7530 return(retfail);
7533 if(can_access(local, READ_ACCESS) != 0){
7534 snprintf(*err_msg, MAXPATH, _("Can't read local file \"%s\": %s"),
7535 local, error_description(errno));
7536 return(retfail);
7540 * Check if remote folder exists and create it if it doesn't.
7542 flags = 0;
7543 rd = rd_create_remote(remotetype, remote, subtype,
7544 &flags, _("Error: "), _("Can't copy to remote folder."));
7546 if(!rd || rd->access == NoExists){
7547 snprintf(*err_msg, MAXPATH, _("Can't create \"%s\""), remote);
7548 if(rd)
7549 rd_free_remdata(&rd);
7551 return(retfail);
7554 if(rd->access == MaybeRorW)
7555 rd->access = ReadWrite;
7557 rd->flags |= (NO_META_UPDATE | DO_REMTRIM);
7558 rd->lf = cpystr(local);
7560 rd_open_remote(rd);
7561 if(!rd_stream_exists(rd)){
7562 snprintf(*err_msg, MAXPATH, _("Can't open remote folder \"%s\""), rd->rn);
7563 rd_free_remdata(&rd);
7564 return(retfail);
7567 if(rd_remote_is_readonly(rd)){
7568 snprintf(*err_msg, MAXPATH, _("Remote folder \"%s\" is readonly"), rd->rn);
7569 rd_free_remdata(&rd);
7570 return(retfail);
7573 switch(rd->type){
7574 case RemImap:
7576 * Empty folder, add a header msg.
7578 if(rd->t.i.stream->nmsgs == 0){
7579 if(rd_init_remote(rd, 1) != 0){
7580 snprintf(*err_msg, MAXPATH,
7581 _("Failed initializing remote folder \"%s\", check debug file"),
7582 rd->rn);
7583 rd_free_remdata(&rd);
7584 return(retfail);
7588 fs_give((void **)err_msg);
7589 *err_msg = NULL;
7590 if(rd_chk_for_hdr_msg(&(rd->t.i.stream), rd, err_msg)){
7591 rd_free_remdata(&rd);
7592 return(retfail);
7595 break;
7597 default:
7598 break;
7601 if(rd_update_remote(rd, NULL) != 0){
7602 snprintf(*err_msg, MAXPATH, _("Error copying to remote folder \"%s\""), rd->rn);
7603 rd_free_remdata(&rd);
7604 return(retfail);
7607 rd_update_metadata(rd, NULL);
7608 rd_close_remdata(&rd);
7610 fs_give((void **)err_msg);
7611 return(0);
7615 /*----------------------------------------------------------------------
7616 Panic pine - call on detected programmatic errors to exit pine, with arg
7618 Input: message -- printf styule string for panic message (see above)
7619 arg -- argument for printf string
7621 Result: The various tty modes are restored
7622 If debugging is active a core dump will be generated
7623 Exits Pine
7624 ----*/
7625 void
7626 panic1(char *message, char *arg)
7628 #define SIZEOFBUF 1001
7629 char buf1[SIZEOFBUF], buf2[SIZEOFBUF];
7631 snprintf(buf1, sizeof(buf1), "%.*s", (int) MAX(SIZEOFBUF - 1 - strlen(message), 0), arg);
7632 snprintf(buf2, sizeof(buf2), message, buf1);
7633 alpine_panic(buf2);
7640 HelpType
7641 config_help(int var, int feature)
7643 switch(var){
7644 case V_FEATURE_LIST :
7645 return(feature_list_help(feature));
7646 break;
7648 case V_PERSONAL_NAME :
7649 return(h_config_pers_name);
7650 case V_USER_ID :
7651 return(h_config_user_id);
7652 case V_USER_DOMAIN :
7653 return(h_config_user_dom);
7654 case V_SMTP_SERVER :
7655 return(h_config_smtp_server);
7656 case V_NNTP_SERVER :
7657 return(h_config_nntp_server);
7658 case V_INBOX_PATH :
7659 return(h_config_inbox_path);
7660 case V_PRUNED_FOLDERS :
7661 return(h_config_pruned_folders);
7662 case V_DEFAULT_FCC :
7663 return(h_config_default_fcc);
7664 case V_DEFAULT_SAVE_FOLDER :
7665 return(h_config_def_save_folder);
7666 case V_POSTPONED_FOLDER :
7667 return(h_config_postponed_folder);
7668 case V_READ_MESSAGE_FOLDER :
7669 return(h_config_read_message_folder);
7670 case V_FORM_FOLDER :
7671 return(h_config_form_folder);
7672 case V_ARCHIVED_FOLDERS :
7673 return(h_config_archived_folders);
7674 case V_SIGNATURE_FILE :
7675 return(h_config_signature_file);
7676 case V_LITERAL_SIG :
7677 return(h_config_literal_sig);
7678 case V_INIT_CMD_LIST :
7679 return(h_config_init_cmd_list);
7680 case V_COMP_HDRS :
7681 return(h_config_comp_hdrs);
7682 case V_CUSTOM_HDRS :
7683 return(h_config_custom_hdrs);
7684 case V_VIEW_HEADERS :
7685 return(h_config_viewer_headers);
7686 case V_VIEW_MARGIN_LEFT :
7687 return(h_config_viewer_margin_left);
7688 case V_VIEW_MARGIN_RIGHT :
7689 return(h_config_viewer_margin_right);
7690 case V_QUOTE_SUPPRESSION :
7691 return(h_config_quote_suppression);
7692 case V_SAVED_MSG_NAME_RULE :
7693 return(h_config_saved_msg_name_rule);
7694 case V_FCC_RULE :
7695 return(h_config_fcc_rule);
7696 case V_SORT_KEY :
7697 return(h_config_sort_key);
7698 case V_AB_SORT_RULE :
7699 return(h_config_ab_sort_rule);
7700 case V_FLD_SORT_RULE :
7701 return(h_config_fld_sort_rule);
7702 case V_POST_CHAR_SET :
7703 return(h_config_post_char_set);
7704 case V_UNK_CHAR_SET :
7705 return(h_config_unk_char_set);
7706 #ifndef _WINDOWS
7707 case V_KEY_CHAR_SET :
7708 return(h_config_key_char_set);
7709 case V_CHAR_SET :
7710 return(h_config_char_set);
7711 #endif /* ! _WINDOWS */
7712 case V_EDITOR :
7713 return(h_config_editor);
7714 case V_SPELLER :
7715 return(h_config_speller);
7716 #ifdef _WINDOWS
7717 case V_DICTIONARY :
7718 return(h_config_aspell_dictionary);
7719 #endif /* _WINDOWS */
7720 case V_DISPLAY_FILTERS :
7721 return(h_config_display_filters);
7722 case V_SEND_FILTER :
7723 return(h_config_sending_filter);
7724 case V_ALT_ADDRS :
7725 return(h_config_alt_addresses);
7726 case V_KEYWORDS :
7727 return(h_config_keywords);
7728 case V_KW_BRACES :
7729 return(h_config_kw_braces);
7730 case V_OPENING_SEP :
7731 return(h_config_opening_sep);
7732 case V_KW_COLORS :
7733 return(h_config_kw_color);
7734 case V_ABOOK_FORMATS :
7735 return(h_config_abook_formats);
7736 case V_INDEX_FORMAT :
7737 return(h_config_index_format);
7738 case V_INCCHECKTIMEO :
7739 return(h_config_incoming_timeo);
7740 case V_INCCHECKINTERVAL :
7741 return(h_config_incoming_interv);
7742 case V_INC2NDCHECKINTERVAL :
7743 return(h_config_incoming_second_interv);
7744 case V_INCCHECKLIST :
7745 return(h_config_incoming_list);
7746 case V_SLEEP :
7747 return(h_config_psleep);
7748 case V_OVERLAP :
7749 return(h_config_viewer_overlap);
7750 case V_MAXREMSTREAM :
7751 return(h_config_maxremstream);
7752 case V_PERMLOCKED :
7753 return(h_config_permlocked);
7754 case V_MARGIN :
7755 return(h_config_scroll_margin);
7756 case V_DEADLETS :
7757 return(h_config_deadlets);
7758 case V_FILLCOL :
7759 return(h_config_composer_wrap_column);
7760 case V_TCPOPENTIMEO :
7761 return(h_config_tcp_open_timeo);
7762 case V_TCPREADWARNTIMEO :
7763 return(h_config_tcp_readwarn_timeo);
7764 case V_TCPWRITEWARNTIMEO :
7765 return(h_config_tcp_writewarn_timeo);
7766 case V_TCPQUERYTIMEO :
7767 return(h_config_tcp_query_timeo);
7768 case V_RSHOPENTIMEO :
7769 return(h_config_rsh_open_timeo);
7770 case V_SSHOPENTIMEO :
7771 return(h_config_ssh_open_timeo);
7772 case V_USERINPUTTIMEO :
7773 return(h_config_user_input_timeo);
7774 case V_REMOTE_ABOOK_VALIDITY :
7775 return(h_config_remote_abook_validity);
7776 case V_REMOTE_ABOOK_HISTORY :
7777 return(h_config_remote_abook_history);
7778 case V_INCOMING_FOLDERS :
7779 return(h_config_incoming_folders);
7780 case V_FOLDER_SPEC :
7781 return(h_config_folder_spec);
7782 case V_NEWS_SPEC :
7783 return(h_config_news_spec);
7784 case V_ADDRESSBOOK :
7785 return(h_config_address_book);
7786 case V_GLOB_ADDRBOOK :
7787 return(h_config_glob_addrbook);
7788 case V_LAST_VERS_USED :
7789 return(h_config_last_vers);
7790 case V_SENDMAIL_PATH :
7791 return(h_config_sendmail_path);
7792 case V_OPER_DIR :
7793 return(h_config_oper_dir);
7794 case V_RSHPATH :
7795 return(h_config_rshpath);
7796 case V_RSHCMD :
7797 return(h_config_rshcmd);
7798 case V_SSHPATH :
7799 return(h_config_sshpath);
7800 case V_SSHCMD :
7801 return(h_config_sshcmd);
7802 case V_NEW_VER_QUELL :
7803 return(h_config_new_ver_quell);
7804 case V_DISABLE_DRIVERS :
7805 return(h_config_disable_drivers);
7806 case V_DISABLE_AUTHS :
7807 return(h_config_disable_auths);
7808 case V_REMOTE_ABOOK_METADATA :
7809 return(h_config_abook_metafile);
7810 case V_REPLY_STRING :
7811 return(h_config_reply_indent_string);
7812 case V_WORDSEPS :
7813 return(h_config_wordseps);
7814 case V_QUOTE_REPLACE_STRING :
7815 return(h_config_quote_replace_string);
7816 case V_REPLY_INTRO :
7817 return(h_config_reply_intro);
7818 case V_EMPTY_HDR_MSG :
7819 return(h_config_empty_hdr_msg);
7820 case V_STATUS_MSG_DELAY :
7821 return(h_config_status_msg_delay);
7822 case V_ACTIVE_MSG_INTERVAL :
7823 return(h_config_active_msg_interval);
7824 case V_MAILCHECK :
7825 return(h_config_mailcheck);
7826 case V_MAILCHECKNONCURR :
7827 return(h_config_mailchecknoncurr);
7828 case V_MAILDROPCHECK :
7829 return(h_config_maildropcheck);
7830 case V_NNTPRANGE :
7831 return(h_config_nntprange);
7832 case V_NEWS_ACTIVE_PATH :
7833 return(h_config_news_active);
7834 case V_NEWS_SPOOL_DIR :
7835 return(h_config_news_spool);
7836 case V_IMAGE_VIEWER :
7837 return(h_config_image_viewer);
7838 case V_USE_ONLY_DOMAIN_NAME :
7839 return(h_config_domain_name);
7840 case V_LAST_TIME_PRUNE_QUESTION :
7841 return(h_config_prune_date);
7842 case V_UPLOAD_CMD:
7843 return(h_config_upload_cmd);
7844 case V_UPLOAD_CMD_PREFIX:
7845 return(h_config_upload_prefix);
7846 case V_DOWNLOAD_CMD:
7847 return(h_config_download_cmd);
7848 case V_DOWNLOAD_CMD_PREFIX:
7849 return(h_config_download_prefix);
7850 case V_GOTO_DEFAULT_RULE:
7851 return(h_config_goto_default);
7852 case V_INCOMING_STARTUP:
7853 return(h_config_inc_startup);
7854 case V_PRUNING_RULE:
7855 return(h_config_pruning_rule);
7856 case V_REOPEN_RULE:
7857 return(h_config_reopen_rule);
7858 case V_THREAD_DISP_STYLE:
7859 return(h_config_thread_disp_style);
7860 case V_THREAD_INDEX_STYLE:
7861 return(h_config_thread_index_style);
7862 case V_THREAD_MORE_CHAR:
7863 return(h_config_thread_indicator_char);
7864 case V_THREAD_EXP_CHAR:
7865 return(h_config_thread_exp_char);
7866 case V_THREAD_LASTREPLY_CHAR:
7867 return(h_config_thread_lastreply_char);
7868 case V_MAILCAP_PATH :
7869 return(h_config_mailcap_path);
7870 case V_MIMETYPE_PATH :
7871 return(h_config_mimetype_path);
7872 #if !defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)
7873 case V_FIFOPATH :
7874 return(h_config_fifopath);
7875 #endif
7876 case V_NMW_WIDTH :
7877 return(h_config_newmailwidth);
7878 case V_NEWSRC_PATH :
7879 return(h_config_newsrc_path);
7880 case V_BROWSER :
7881 return(h_config_browser);
7882 case V_HISTORY :
7883 return(h_config_history);
7884 #if defined(DOS) || defined(OS2)
7885 case V_FILE_DIR :
7886 return(h_config_file_dir);
7887 #endif
7888 case V_NORM_FORE_COLOR :
7889 case V_NORM_BACK_COLOR :
7890 return(h_config_normal_color);
7891 case V_REV_FORE_COLOR :
7892 case V_REV_BACK_COLOR :
7893 return(h_config_reverse_color);
7894 case V_TITLE_FORE_COLOR :
7895 case V_TITLE_BACK_COLOR :
7896 return(h_config_title_color);
7897 case V_TITLECLOSED_FORE_COLOR :
7898 case V_TITLECLOSED_BACK_COLOR :
7899 return(h_config_titleclosed_color);
7900 case V_FOLDER_FORE_COLOR:
7901 return(h_config_folder_color);
7902 case V_DIRECTORY_FORE_COLOR:
7903 return(h_config_directory_color);
7904 case V_FOLDER_LIST_FORE_COLOR:
7905 return(h_config_folder_list_color);
7906 case V_STATUS_FORE_COLOR :
7907 case V_STATUS_BACK_COLOR :
7908 return(h_config_status_color);
7909 case V_SLCTBL_FORE_COLOR :
7910 case V_SLCTBL_BACK_COLOR :
7911 return(h_config_slctbl_color);
7912 case V_QUOTE1_FORE_COLOR :
7913 case V_QUOTE2_FORE_COLOR :
7914 case V_QUOTE3_FORE_COLOR :
7915 case V_QUOTE1_BACK_COLOR :
7916 case V_QUOTE2_BACK_COLOR :
7917 case V_QUOTE3_BACK_COLOR :
7918 return(h_config_quote_color);
7919 case V_INCUNSEEN_FORE_COLOR :
7920 case V_INCUNSEEN_BACK_COLOR :
7921 return(h_config_incunseen_color);
7922 case V_SIGNATURE_FORE_COLOR :
7923 case V_SIGNATURE_BACK_COLOR :
7924 return(h_config_signature_color);
7925 case V_PROMPT_FORE_COLOR :
7926 case V_PROMPT_BACK_COLOR :
7927 return(h_config_prompt_color);
7928 case V_HEADER_GENERAL_FORE_COLOR :
7929 case V_HEADER_GENERAL_BACK_COLOR :
7930 return(h_config_header_general_color);
7931 case V_IND_PLUS_FORE_COLOR :
7932 case V_IND_IMP_FORE_COLOR :
7933 case V_IND_DEL_FORE_COLOR :
7934 case V_IND_ANS_FORE_COLOR :
7935 case V_IND_NEW_FORE_COLOR :
7936 case V_IND_UNS_FORE_COLOR :
7937 case V_IND_REC_FORE_COLOR :
7938 case V_IND_FWD_FORE_COLOR :
7939 case V_IND_PLUS_BACK_COLOR :
7940 case V_IND_IMP_BACK_COLOR :
7941 case V_IND_DEL_BACK_COLOR :
7942 case V_IND_ANS_BACK_COLOR :
7943 case V_IND_NEW_BACK_COLOR :
7944 case V_IND_UNS_BACK_COLOR :
7945 case V_IND_REC_BACK_COLOR :
7946 case V_IND_FWD_BACK_COLOR :
7947 return(h_config_index_color);
7948 case V_IND_OP_FORE_COLOR :
7949 case V_IND_OP_BACK_COLOR :
7950 return(h_config_index_opening_color);
7951 case V_IND_SUBJ_FORE_COLOR :
7952 case V_IND_SUBJ_BACK_COLOR :
7953 return(h_config_index_subject_color);
7954 case V_IND_FROM_FORE_COLOR :
7955 case V_IND_FROM_BACK_COLOR :
7956 return(h_config_index_from_color);
7957 case V_IND_HIPRI_FORE_COLOR :
7958 case V_IND_HIPRI_BACK_COLOR :
7959 case V_IND_LOPRI_FORE_COLOR :
7960 case V_IND_LOPRI_BACK_COLOR :
7961 return(h_config_index_pri_color);
7962 case V_IND_ARR_FORE_COLOR :
7963 case V_IND_ARR_BACK_COLOR :
7964 return(h_config_index_arrow_color);
7965 case V_KEYLABEL_FORE_COLOR :
7966 case V_KEYLABEL_BACK_COLOR :
7967 return(h_config_keylabel_color);
7968 case V_KEYNAME_FORE_COLOR :
7969 case V_KEYNAME_BACK_COLOR :
7970 return(h_config_keyname_color);
7971 case V_METAMSG_FORE_COLOR :
7972 case V_METAMSG_BACK_COLOR :
7973 return(h_config_metamsg_color);
7974 case V_VIEW_HDR_COLORS :
7975 return(h_config_customhdr_color);
7976 case V_INDEX_TOKEN_COLORS :
7977 return(h_config_indextoken_color);
7978 case V_PRINTER :
7979 return(h_config_printer);
7980 case V_PERSONAL_PRINT_CATEGORY :
7981 return(h_config_print_cat);
7982 case V_PERSONAL_PRINT_COMMAND :
7983 return(h_config_print_command);
7984 case V_PAT_ROLES :
7985 return(h_config_pat_roles);
7986 case V_PAT_FILTS :
7987 return(h_config_pat_filts);
7988 case V_PAT_SCORES :
7989 return(h_config_pat_scores);
7990 case V_PAT_INCOLS :
7991 return(h_config_pat_incols);
7992 case V_PAT_OTHER :
7993 return(h_config_pat_other);
7994 case V_PAT_SRCH :
7995 return(h_config_pat_srch);
7996 case V_INDEX_COLOR_STYLE :
7997 return(h_config_index_color_style);
7998 case V_TITLEBAR_COLOR_STYLE :
7999 return(h_config_titlebar_color_style);
8000 #ifdef _WINDOWS
8001 case V_FONT_NAME :
8002 return(h_config_font_name);
8003 case V_FONT_SIZE :
8004 return(h_config_font_size);
8005 case V_FONT_STYLE :
8006 return(h_config_font_style);
8007 case V_FONT_CHAR_SET :
8008 return(h_config_font_char_set);
8009 case V_PRINT_FONT_NAME :
8010 return(h_config_print_font_name);
8011 case V_PRINT_FONT_SIZE :
8012 return(h_config_print_font_size);
8013 case V_PRINT_FONT_STYLE :
8014 return(h_config_print_font_style);
8015 case V_PRINT_FONT_CHAR_SET :
8016 return(h_config_print_font_char_set);
8017 case V_WINDOW_POSITION :
8018 return(h_config_window_position);
8019 case V_CURSOR_STYLE :
8020 return(h_config_cursor_style);
8021 #else
8022 case V_COLOR_STYLE :
8023 return(h_config_color_style);
8024 #endif
8025 #ifdef ENABLE_LDAP
8026 case V_LDAP_SERVERS :
8027 return(h_config_ldap_servers);
8028 #endif
8029 #ifdef SMIME
8030 case V_PUBLICCERT_DIR :
8031 return(h_config_smime_pubcertdir);
8032 case V_PUBLICCERT_CONTAINER :
8033 return(h_config_smime_pubcertcon);
8034 case V_PRIVATEKEY_DIR :
8035 return(h_config_smime_privkeydir);
8036 case V_PRIVATEKEY_CONTAINER :
8037 return(h_config_smime_privkeycon);
8038 case V_CACERT_DIR :
8039 return(h_config_smime_cacertdir);
8040 case V_CACERT_CONTAINER :
8041 return(h_config_smime_cacertcon);
8042 #endif
8043 case V_RSS_NEWS :
8044 return(h_config_rss_news);
8045 case V_RSS_WEATHER :
8046 return(h_config_rss_weather);
8047 case V_WP_INDEXHEIGHT :
8048 return(h_config_wp_indexheight);
8049 case V_WP_INDEXLINES :
8050 return(h_config_wp_indexlines);
8051 case V_WP_AGGSTATE :
8052 return(h_config_wp_aggstate);
8053 case V_WP_STATE :
8054 return(h_config_wp_state);
8055 case V_WP_COLUMNS :
8056 return(h_config_wp_columns);
8057 default :
8058 return(NO_HELP);
8064 * We don't want the user to be able to edit their pinerc and set
8065 * printer to whatever they want if personal-print-command is fixed.
8066 * So make sure printer is set to something legitimate. If it isn't,
8067 * set it to something standard and return non-zero.
8070 printer_value_check_and_adjust(void)
8072 char **tt;
8073 char aname[100], wname[100];
8074 int ok = 0;
8075 struct variable *vars = ps_global->vars;
8077 if(vars[V_PERSONAL_PRINT_COMMAND].is_fixed && !vars[V_PRINTER].is_fixed){
8078 strncpy(aname, ANSI_PRINTER, sizeof(aname));
8079 aname[sizeof(aname)-1] = '\0';
8080 strncat(aname, "-no-formfeed", sizeof(aname)-strlen(aname)-1);
8081 strncpy(wname, WYSE_PRINTER, sizeof(wname));
8082 wname[sizeof(wname)-1] = '\0';
8083 strncat(wname, "-no-formfeed", sizeof(wname)-strlen(wname)-1);
8084 if(strucmp(VAR_PRINTER, ANSI_PRINTER) == 0
8085 || strucmp(VAR_PRINTER, aname) == 0
8086 || strucmp(VAR_PRINTER, WYSE_PRINTER) == 0
8087 || strucmp(VAR_PRINTER, wname) == 0)
8088 ok++;
8089 else if(VAR_STANDARD_PRINTER && VAR_STANDARD_PRINTER[0]){
8090 for(tt = VAR_STANDARD_PRINTER; *tt; tt++)
8091 if(strucmp(VAR_PRINTER, *tt) == 0)
8092 break;
8094 if(*tt)
8095 ok++;
8098 if(!ok){
8099 char *val;
8100 struct variable *v;
8102 if(VAR_STANDARD_PRINTER && VAR_STANDARD_PRINTER[0])
8103 val = VAR_STANDARD_PRINTER[0];
8104 else
8105 val = ANSI_PRINTER;
8107 v = &vars[V_PRINTER];
8108 if(v->main_user_val.p)
8109 fs_give((void **)&v->main_user_val.p);
8110 if(v->post_user_val.p)
8111 fs_give((void **)&v->post_user_val.p);
8112 if(v->current_val.p)
8113 fs_give((void **)&v->current_val.p);
8115 v->main_user_val.p = cpystr(val);
8116 v->current_val.p = cpystr(val);
8120 return(!ok);
8124 char **
8125 get_supported_options(void)
8127 char **config;
8128 DRIVER *d;
8129 AUTHENTICATOR *a;
8130 char *title = _("Supported features in this Alpine");
8131 char sbuf[MAX_SCREEN_COLS+1];
8132 int cnt, alcnt, len, cols, disabled, any_disabled = 0;;
8135 * Line count:
8136 * Title + blank = 2
8137 * SSL Title + SSL lines + blank = 5
8138 * Auth title + blank = 2
8139 * Driver title + blank = 2
8140 * LDAP title + LDAP line = 2
8141 * Disabled explanation + blank line = 4
8142 * end = 1
8144 cnt = 18;
8145 for(a = mail_lookup_auth(1); a; a = a->next)
8146 cnt++;
8147 for(d = (DRIVER *)mail_parameters(NIL, GET_DRIVERS, NIL);
8148 d; d = d->next)
8149 cnt++;
8151 alcnt = cnt;
8152 config = (char **) fs_get(alcnt * sizeof(char *));
8153 memset(config, 0, alcnt * sizeof(char *));
8155 cols = ps_global->ttyo ? ps_global->ttyo->screen_cols : 0;
8156 len = utf8_width(title);
8157 snprintf(sbuf, sizeof(sbuf), "%*s%s", cols > len ? (cols-len)/2 : 0, "", title);
8159 cnt = 0;
8160 if(cnt < alcnt)
8161 config[cnt] = cpystr(sbuf);
8163 if(++cnt < alcnt)
8164 config[cnt] = cpystr("");
8166 if(++cnt < alcnt)
8167 /* TRANSLATORS: headings */
8168 config[cnt] = cpystr(_("Encryption:"));
8170 if(++cnt < alcnt && mail_parameters(NIL, GET_SSLDRIVER, NIL))
8171 config[cnt] = cpystr(_(" TLS and SSL"));
8172 else
8173 config[cnt] = cpystr(_(" None (no TLS or SSL)"));
8174 #ifdef SSL_SUPPORTS_TLSV1_2
8175 if(++cnt < alcnt)
8176 config[cnt] = cpystr(" TLSv1.1, TLSv1.2, and DTLSv1");
8177 #endif
8178 #ifdef SMIME
8179 if(++cnt < alcnt)
8180 config[cnt] = cpystr(" S/MIME");
8181 #endif
8183 if(++cnt < alcnt)
8184 config[cnt] = cpystr("");
8186 if(++cnt < alcnt)
8187 config[cnt] = cpystr(_("Authenticators:"));
8189 for(a = mail_lookup_auth(1); a; a = a->next){
8190 disabled = (a->client == NULL && a->server == NULL);
8191 any_disabled += disabled;
8192 snprintf(sbuf, sizeof(sbuf), " %s%s", a->name, disabled ? " (disabled)" : "");
8193 if(++cnt < alcnt)
8194 config[cnt] = cpystr(sbuf);
8197 if(++cnt < alcnt)
8198 config[cnt] = cpystr("");
8200 if(++cnt < alcnt)
8201 config[cnt] = cpystr(_("Mailbox drivers:"));
8203 for(d = (DRIVER *)mail_parameters(NIL, GET_DRIVERS, NIL);
8204 d; d = d->next){
8205 disabled = (d->flags & DR_DISABLE);
8206 any_disabled += disabled;
8207 snprintf(sbuf, sizeof(sbuf), " %s%s", d->name, disabled ? " (disabled)" : "");
8208 if(++cnt < alcnt)
8209 config[cnt] = cpystr(sbuf);
8212 if(++cnt < alcnt)
8213 config[cnt] = cpystr("");
8215 if(++cnt < alcnt)
8216 config[cnt] = cpystr(_("Directories:"));
8218 #ifdef ENABLE_LDAP
8219 if(++cnt < alcnt)
8220 config[cnt] = cpystr(" LDAP");
8221 #else
8222 if(++cnt < alcnt)
8223 config[cnt] = cpystr(" None (no LDAP)");
8224 #endif
8226 if(any_disabled){
8227 if(++cnt < alcnt)
8228 config[cnt] = cpystr("");
8230 if(ps_global->ttyo){
8231 if(++cnt < alcnt)
8232 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."));
8234 else{
8235 if(++cnt < alcnt)
8236 config[cnt] = cpystr(_("Authenticators may be disabled because of the \"disable-these-authenticators\""));
8237 if(++cnt < alcnt)
8238 config[cnt] = cpystr(_("hidden config option. Mailbox drivers may be disabled because of the"));
8239 if(++cnt < alcnt)
8240 config[cnt] = cpystr(_("\"disable-these-drivers\" hidden config option."));
8244 if(++cnt < alcnt)
8245 config[cnt] = NULL;
8247 return(config);
8251 unsigned
8252 reset_startup_rule(MAILSTREAM *stream)
8254 long rflags = ROLE_DO_OTHER;
8255 PAT_STATE pstate;
8256 PAT_S *pat;
8257 unsigned startup_rule;
8259 startup_rule = IS_NOTSET;
8261 if(stream && nonempty_patterns(rflags, &pstate)){
8262 for(pat = first_pattern(&pstate); pat; pat = next_pattern(&pstate)){
8263 if(match_pattern(pat->patgrp, stream, NULL, NULL, NULL,
8264 SE_NOSERVER|SE_NOPREFETCH))
8265 break;
8268 if(pat && pat->action && !pat->action->bogus)
8269 startup_rule = pat->action->startup_rule;
8272 return(startup_rule);
8276 #ifdef _WINDOWS
8278 char *
8279 transformed_color(old)
8280 char *old;
8282 if(!old)
8283 return("");
8285 if(!struncmp(old, "color008", 8))
8286 return("colorlgr");
8287 else if(!struncmp(old, "color009", 8))
8288 return("colormgr");
8289 else if(!struncmp(old, "color010", 8))
8290 return("colordgr");
8292 return("");
8297 * If this is the first time we've run a version > 4.40, and there
8298 * is evidence that the config file has not been used by unix pine,
8299 * then we convert color008 to colorlgr, color009 to colormgr, and
8300 * color010 to colordgr. If the config file is being used by
8301 * unix pine then color008 may really supposed to be color008, color009
8302 * may really supposed to be red, and color010 may really supposed to be
8303 * green. Same if we've already run 4.41 or higher previously.
8305 * Returns 0 if no changes, > 0 if something was changed.
8308 convert_pc_gray_names(ps, prc, which)
8309 struct pine *ps;
8310 PINERC_S *prc;
8311 EditWhich which;
8313 struct variable *v;
8314 int ret = 0, ic = 0;
8315 char **s, *t, *p, *pstr, *new, *pval, **apval, **lval;
8317 for(v = ps->vars; v->name; v++){
8318 if(!color_holding_var(ps, v) || v == &ps->vars[V_KW_COLORS])
8319 continue;
8321 if(v == &ps->vars[V_VIEW_HDR_COLORS]){
8323 if((lval = LVAL(v,which)) != NULL){
8324 /* fix these in place */
8325 for(s = lval; (t = *s) != NULL; s++){
8326 if((p = srchstr(t, "FG=color008")) ||
8327 (p = srchstr(t, "FG=color009")) ||
8328 (p = srchstr(t, "FG=color010"))){
8329 strncpy(p+3, transformed_color(p+3), 8);
8330 ret++;
8333 if((p = srchstr(t, "BG=color008")) ||
8334 (p = srchstr(t, "BG=color009")) ||
8335 (p = srchstr(t, "BG=color010"))){
8336 strncpy(p+3, transformed_color(p+3), 8);
8337 ret++;
8342 else{
8343 if((pval = PVAL(v,which)) != NULL){
8344 apval = APVAL(v,which);
8345 if(apval && (!strucmp(pval, "color008") ||
8346 !strucmp(pval, "color009") ||
8347 !strucmp(pval, "color010"))){
8348 new = transformed_color(pval);
8349 if(*apval)
8350 fs_give((void **)apval);
8352 *apval = cpystr(new);
8353 ret++;
8359 v = &ps->vars[V_PAT_INCOLS];
8360 if((lval = LVAL(v,which)) != NULL){
8361 for(s = lval; (t = *s) != NULL; s++){
8362 if((pstr = srchstr(t, "action=")) != NULL){
8363 if((p = srchstr(pstr, "FG=color008")) ||
8364 (p = srchstr(pstr, "FG=color009")) ||
8365 (p = srchstr(pstr, "FG=color010"))){
8366 strncpy(p+3, transformed_color(p+3), 8);
8367 ic++;
8370 if((p = srchstr(pstr, "BG=color008")) ||
8371 (p = srchstr(pstr, "BG=color009")) ||
8372 (p = srchstr(pstr, "BG=color010"))){
8373 strncpy(p+3, transformed_color(p+3), 8);
8374 ic++;
8380 if(ic)
8381 set_current_val(&ps->vars[V_PAT_INCOLS], TRUE, TRUE);
8383 return(ret+ic);
8388 unix_color_style_in_pinerc(prc)
8389 PINERC_S *prc;
8391 PINERC_LINE *pline;
8393 for(pline = prc ? prc->pinerc_lines : NULL;
8394 pline && (pline->var || pline->line); pline++)
8395 if(pline->line && !struncmp("color-style=", pline->line, 12))
8396 return(1);
8398 return(0);
8401 char *
8402 pcpine_general_help(titlebuf)
8403 char *titlebuf;
8405 if(titlebuf)
8406 strcpy(titlebuf, "PC Alpine For Windows");
8408 return(pcpine_help(h_pine_for_windows));
8411 #endif /* _WINDOWS */