* Do not define _BSD_SOURCE but define _DEFAULT_SOURCE instead.
[alpine.git] / pith / conf.c
blob79243222888dcf3a2d8785d418a0e2e08fd3e938
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-2016 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 {"copy-to-address-to-from-if-it-is-us", "Copy To Address to From if it is Us",
2842 F_COPY_TO_TO_FROM, h_config_copy_to_to_from, PREF_RPLY, 0},
2843 {"enable-reply-indent-string-editing", NULL,
2844 F_ENABLE_EDIT_REPLY_INDENT, h_config_prefix_editing, PREF_RPLY, 0},
2845 {"include-attachments-in-reply", "Include Attachments in Reply",
2846 F_ATTACHMENTS_IN_REPLY, h_config_attach_in_reply, PREF_RPLY, 0},
2847 {"include-header-in-reply", "Include Header in Reply",
2848 F_INCLUDE_HEADER, h_config_include_header, PREF_RPLY, 0},
2849 {"include-text-in-reply", "Include Text in Reply",
2850 F_AUTO_INCLUDE_IN_REPLY, h_config_auto_include_reply, PREF_RPLY, 0},
2851 {"reply-always-uses-reply-to", "Reply Always Uses Reply-To",
2852 F_AUTO_REPLY_TO, h_config_auto_reply_to, PREF_RPLY, 0},
2853 {"signature-at-bottom", "Signature at Bottom",
2854 F_SIG_AT_BOTTOM, h_config_sig_at_bottom, PREF_RPLY, 0},
2855 {"strip-from-sigdashes-on-reply", "Strip From Sigdashes on Reply",
2856 F_ENABLE_STRIP_SIGDASHES, h_config_strip_sigdashes, PREF_RPLY, 0},
2857 {"forward-as-attachment", "Forward messages as attachments",
2858 F_FORWARD_AS_ATTACHMENT, h_config_forward_as_attachment, PREF_RPLY, 0},
2859 {"preserve-original-fields", NULL,
2860 F_PRESERVE_ORIGINAL_FIELD, h_config_preserve_field, PREF_RPLY, 0},
2862 /* Sending Prefs */
2863 {"disable-sender", "Do Not Generate Sender Header",
2864 F_DISABLE_SENDER, h_config_disable_sender, PREF_SEND, 0},
2865 {"use-sender-not-x-sender", "Use Sender Instead of X-X-Sender",
2866 F_USE_SENDER_NOT_X, h_config_use_sender_not_x, PREF_SEND, 0},
2867 {"quell-flowed-text", "Do Not Send Flowed Text",
2868 F_QUELL_FLOWED_TEXT, h_config_quell_flowed_text, PREF_SEND, 0},
2869 {"downgrade-multipart-to-text", "Downgrade Multipart to Text",
2870 F_COMPOSE_ALWAYS_DOWNGRADE, h_downgrade_multipart_to_text, PREF_SEND, 0},
2871 {"enable-8bit-esmtp-negotiation", "Enable 8bit ESMTP Negotiation",
2872 F_ENABLE_8BIT, h_config_8bit_smtp, PREF_SEND, 1},
2873 #ifdef BACKGROUND_POST
2874 {"enable-background-sending", NULL,
2875 F_BACKGROUND_POST, h_config_compose_bg_post, PREF_SEND, 0},
2876 #endif
2877 {"enable-delivery-status-notification", NULL,
2878 F_DSN, h_config_compose_dsn, PREF_SEND, 0},
2879 {"enable-verbose-smtp-posting", "Enable Verbose SMTP Posting",
2880 F_VERBOSE_POST, h_config_verbose_post, PREF_SEND, 0},
2881 {"fcc-without-attachments", "Fcc Does Not Include Attachments",
2882 F_NO_FCC_ATTACH, h_config_no_fcc_attach, PREF_SEND, 0},
2883 {"fcc-on-bounce", "Include Fcc When Bouncing Messages",
2884 F_FCC_ON_BOUNCE, h_config_fcc_on_bounce, PREF_SEND, 0},
2885 {"mark-fcc-seen", NULL,
2886 F_MARK_FCC_SEEN, h_config_mark_fcc_seen, PREF_SEND, 0},
2887 {"fcc-only-without-confirm", "Send to Fcc Only Without Confirming",
2888 F_AUTO_FCC_ONLY, h_config_auto_fcc_only, PREF_SEND, 0},
2889 {"send-without-confirm", "Send Without Confirming",
2890 F_SEND_WO_CONFIRM, h_config_send_wo_confirm, PREF_SEND, 0},
2891 {"strip-whitespace-before-send", "Strip Whitespace Before Sending",
2892 F_STRIP_WS_BEFORE_SEND, h_config_strip_ws_before_send, PREF_SEND, 0},
2893 {"warn-if-blank-fcc", "Warn if Blank Fcc",
2894 F_WARN_ABOUT_NO_FCC, h_config_warn_if_fcc_blank, PREF_SEND, 0},
2895 {"warn-if-blank-subject", "Warn if Blank Subject",
2896 F_WARN_ABOUT_NO_SUBJECT, h_config_warn_if_subj_blank, PREF_SEND, 0},
2897 {"warn-if-blank-to-and-cc-and-newsgroups", "Warn if Blank To and CC and Newsgroups",
2898 F_WARN_ABOUT_NO_TO_OR_CC, h_config_warn_if_no_to_or_cc, PREF_SEND, 0},
2900 /* Folder */
2901 {"combined-folder-display", NULL,
2902 F_CMBND_FOLDER_DISP, h_config_combined_folder_display, PREF_FLDR, 0},
2903 {"combined-subdirectory-display", NULL,
2904 F_CMBND_SUBDIR_DISP, h_config_combined_subdir_display, PREF_FLDR, 0},
2905 {"enable-lame-list-mode", "Compensate for Deficient IMAP servers",
2906 F_FIX_BROKEN_LIST, h_config_lame_list_mode, PREF_FLDR, 0},
2907 {"enable-dot-folders", "Enable Hidden Folders",
2908 F_ENABLE_DOT_FOLDERS, h_config_enable_dot_folders, PREF_FLDR, 0},
2909 {"enable-incoming-folders", "Enable Incoming Folders Collection",
2910 F_ENABLE_INCOMING, h_config_enable_incoming, PREF_FLDR, 0},
2911 {"enable-incoming-folders-checking", NULL,
2912 F_ENABLE_INCOMING_CHECKING, h_config_enable_incoming_checking, PREF_FLDR, 0},
2913 {"incoming-checking-includes-total", NULL,
2914 F_INCOMING_CHECKING_TOTAL, h_config_incoming_checking_total, PREF_FLDR, 0},
2915 {"incoming-checking-uses-recent", NULL,
2916 F_INCOMING_CHECKING_RECENT, h_config_incoming_checking_recent, PREF_FLDR, 0},
2917 {"expanded-view-of-folders", "Expanded View of Folders",
2918 F_EXPANDED_FOLDERS, h_config_expanded_folders, PREF_FLDR, 0},
2919 {"quell-empty-directories", "Hide Empty Directories",
2920 F_QUELL_EMPTY_DIRS, h_config_quell_empty_dirs, PREF_FLDR, 0},
2921 {"separate-folder-and-directory-entries", "Separate Folder and Directory Entries",
2922 F_SEPARATE_FLDR_AS_DIR, h_config_separate_fold_dir_view, PREF_FLDR, 0},
2923 {"single-column-folder-list", NULL,
2924 F_SINGLE_FOLDER_LIST, h_config_single_list, PREF_FLDR, 0},
2925 {"sort-default-fcc-alpha", "Sort Default Fcc Folder Alphabetically",
2926 F_SORT_DEFAULT_FCC_ALPHA, h_config_sort_fcc_alpha, PREF_FLDR, 0},
2927 {"sort-default-save-alpha", "Sort Default Save Folder Alphabetically",
2928 F_SORT_DEFAULT_SAVE_ALPHA, h_config_sort_save_alpha, PREF_FLDR, 0},
2929 {"vertical-folder-list", "Use Vertical Folder List",
2930 F_VERTICAL_FOLDER_LIST, h_config_vertical_list, PREF_FLDR, 0},
2932 /* Addr book */
2933 {"combined-addrbook-display", "Combined Address Book Display",
2934 F_CMBND_ABOOK_DISP, h_config_combined_abook_display, PREF_ADDR, 0},
2935 {"expanded-view-of-addressbooks", "Expanded View of Address Books",
2936 F_EXPANDED_ADDRBOOKS, h_config_expanded_addrbooks, PREF_ADDR, 0},
2937 {"expanded-view-of-distribution-lists", "Expanded View of Distribution Lists",
2938 F_EXPANDED_DISTLISTS, h_config_expanded_distlists, PREF_ADDR, 0},
2939 #ifdef ENABLE_LDAP
2940 {"ldap-result-to-addrbook-add", "LDAP Result to Addressbook Add",
2941 F_ADD_LDAP_TO_ABOOK, h_config_add_ldap, PREF_ADDR, 0},
2942 #endif
2944 /* Index prefs */
2945 {"auto-open-next-unread", NULL,
2946 F_AUTO_OPEN_NEXT_UNREAD, h_config_auto_open_unread, PREF_INDX, 0},
2947 {"continue-tab-without-confirm", "Continue NextNew Without Confirming",
2948 F_TAB_NO_CONFIRM, h_config_tab_no_prompt, PREF_INDX, 0},
2949 {"convert-dates-to-localtime", NULL,
2950 F_DATES_TO_LOCAL, h_config_dates_to_local, PREF_INDX, 0},
2951 {"delete-skips-deleted", NULL,
2952 F_DEL_SKIPS_DEL, h_config_del_skips_del, PREF_INDX, 1},
2953 {"disable-index-locale-dates", NULL,
2954 F_DISABLE_INDEX_LOCALE_DATES, h_config_disable_index_locale_dates, PREF_INDX, 0},
2955 {"enable-cruise-mode", NULL,
2956 F_ENABLE_SPACE_AS_TAB, h_config_cruise_mode, PREF_INDX, 0},
2957 {"enable-cruise-mode-delete", "Enable Cruise Mode With Deleting",
2958 F_ENABLE_TAB_DELETES, h_config_cruise_mode_delete, PREF_INDX, 0},
2959 {"mark-for-cc", "Mark for CC",
2960 F_MARK_FOR_CC, h_config_mark_for_cc, PREF_INDX, 1},
2961 {"next-thread-without-confirm", "Read Next Thread Without Confirming",
2962 F_NEXT_THRD_WO_CONFIRM, h_config_next_thrd_wo_confirm, PREF_INDX, 0},
2963 {"return-to-inbox-without-confirm", "Return to INBOX Without Confirming",
2964 F_RET_INBOX_NO_CONFIRM, h_config_inbox_no_confirm, PREF_INDX, 0},
2965 {"show-sort", "Show Sort in Titlebar",
2966 F_SHOW_SORT, h_config_show_sort, PREF_INDX, 0},
2967 {"tab-uses-unseen-for-next-folder", "Tab Uses Unseen for Next Folder",
2968 F_TAB_USES_UNSEEN, h_config_tab_uses_unseen, PREF_INDX, 0},
2969 {"tab-visits-next-new-message-only", NULL,
2970 F_TAB_TO_NEW, h_config_tab_new_only, PREF_INDX, 0},
2971 {"thread-index-shows-important-color", NULL,
2972 F_COLOR_LINE_IMPORTANT, h_config_color_thrd_import, PREF_INDX, 0},
2973 {"thread-sorts-by-arrival", "Thread Sorts by Arrival",
2974 F_THREAD_SORTS_BY_ARRIVAL, h_config_thread_sorts_by_arrival, PREF_INDX, 0},
2976 /* Viewer prefs */
2977 {"enable-msg-view-addresses", "Enable Message View Address Links",
2978 F_SCAN_ADDR, h_config_enable_view_addresses, PREF_VIEW, 0},
2979 {"enable-msg-view-attachments", "Enable Message View Attachment Links",
2980 F_VIEW_SEL_ATTACH, h_config_enable_view_attach, PREF_VIEW, 0},
2981 {"enable-msg-view-urls", "Enable Message View URL Links",
2982 F_VIEW_SEL_URL, h_config_enable_view_url, PREF_VIEW, 1},
2983 {"enable-msg-view-web-hostnames", "Enable Message View Web Hostname Links",
2984 F_VIEW_SEL_URL_HOST, h_config_enable_view_web_host, PREF_VIEW, 1},
2985 {"enable-msg-view-forced-arrows", "Enable Message View Forced Arrows",
2986 F_FORCE_ARROWS, h_config_enable_view_arrows, PREF_VIEW, 0},
2987 /* set to TRUE for windows */
2988 {"pass-c1-control-characters-as-is", NULL,
2989 F_PASS_C1_CONTROL_CHARS, h_config_pass_c1_control, PREF_VIEW, 0},
2990 {"pass-control-characters-as-is", NULL,
2991 F_PASS_CONTROL_CHARS, h_config_pass_control, PREF_VIEW, 0},
2992 {"prefer-plain-text", NULL,
2993 F_PREFER_PLAIN_TEXT, h_config_prefer_plain_text, PREF_VIEW, 0},
2994 {"quell-charset-warning", "Suppress Character Set Warning",
2995 F_QUELL_CHARSET_WARNING, h_config_quell_charset_warning, PREF_VIEW, 0},
2996 {"quell-server-after-link-in-html", "Suppress Server After Link in HTML",
2997 F_QUELL_HOST_AFTER_URL, h_config_quell_host_after_url, PREF_VIEW, 0},
2999 /* News */
3000 {"compose-sets-newsgroup-without-confirm", "Compose Sets Newsgroup Without Confirming",
3001 F_COMPOSE_TO_NEWSGRP, h_config_compose_news_wo_conf, PREF_NEWS, 0},
3002 {"enable-8bit-nntp-posting", "Enable 8bit NNTP Posting",
3003 F_ENABLE_8BIT_NNTP, h_config_8bit_nntp, PREF_NEWS, 0},
3004 {"enable-multiple-newsrcs", NULL,
3005 F_ENABLE_MULNEWSRCS, h_config_enable_mulnewsrcs, PREF_NEWS, 0},
3006 {"mult-newsrc-hostnames-as-typed", "Multiple Newsrc Hostnames as Typed",
3007 F_MULNEWSRC_HOSTNAMES_AS_TYPED, h_config_mulnews_as_typed, PREF_NEWS, 0},
3008 {"hide-nntp-path", "Hide NNTP Path",
3009 F_HIDE_NNTP_PATH, h_config_hide_nntp_path, PREF_NEWS, 0},
3010 {"news-approximates-new-status", NULL,
3011 F_FAKE_NEW_IN_NEWS, h_config_news_uses_recent, PREF_NEWS, 1},
3012 {"news-deletes-across-groups", NULL,
3013 F_NEWS_CROSS_DELETE, h_config_news_cross_deletes, PREF_NEWS, 0},
3014 {"news-offers-catchup-on-close", "News Offers Catchup on Close",
3015 F_NEWS_CATCHUP, h_config_news_catchup, PREF_NEWS, 0},
3016 {"news-post-without-validation", NULL,
3017 F_NO_NEWS_VALIDATION, h_config_post_wo_validation, PREF_NEWS, 0},
3018 {"news-read-in-newsrc-order", "News Read in Newsrc Order",
3019 F_READ_IN_NEWSRC_ORDER, h_config_read_in_newsrc_order, PREF_NEWS, 0},
3020 {"nntp-search-uses-overview", "NNTP Search Uses Overview",
3021 F_NNTP_SEARCH_USES_OVERVIEW, h_config_nntp_search_uses_overview, PREF_NEWS, 1},
3022 {"predict-nntp-server", "Predict NNTP Server",
3023 F_PREDICT_NNTP_SERVER, h_config_predict_nntp_server, PREF_NEWS, 0},
3024 {"quell-extra-post-prompt", "Suppress Extra Posting Prompt",
3025 F_QUELL_EXTRA_POST_PROMPT, h_config_quell_post_prompt, PREF_NEWS, 0},
3027 /* Print */
3028 {"enable-print-via-y-command", NULL,
3029 F_ENABLE_PRYNT, h_config_enable_y_print, PREF_PRNT, 0},
3030 {"print-formfeed-between-messages", NULL,
3031 F_AGG_PRINT_FF, h_config_ff_between_msgs, PREF_PRNT, 0},
3032 {"print-includes-from-line", NULL,
3033 F_FROM_DELIM_IN_PRINT, h_config_print_from, PREF_PRNT, 0},
3034 {"print-index-enabled", NULL,
3035 F_PRINT_INDEX, h_config_print_index, PREF_PRNT, 0},
3036 {"print-offers-custom-cmd-prompt", "Print Offers Custom Command Prompt",
3037 F_CUSTOM_PRINT, h_config_custom_print, PREF_PRNT, 0},
3039 /* adv cmd prefs */
3040 {"enable-aggregate-command-set", NULL,
3041 F_ENABLE_AGG_OPS, h_config_enable_agg_ops, PREF_ACMD, 1},
3042 {"enable-arrow-navigation", NULL,
3043 F_ARROW_NAV, h_config_arrow_nav, PREF_ACMD, 1},
3044 {"enable-arrow-navigation-relaxed", NULL,
3045 F_RELAXED_ARROW_NAV, h_config_relaxed_arrow_nav, PREF_ACMD, 1},
3046 {"enable-bounce-cmd", "Enable Bounce Command",
3047 F_ENABLE_BOUNCE, h_config_enable_bounce, PREF_ACMD, 1},
3048 {"enable-exit-via-lessthan-command", NULL,
3049 F_ENABLE_LESSTHAN_EXIT, h_config_enable_lessthan_exit, PREF_ACMD, 1},
3050 {"enable-flag-cmd", "Enable Flag Command",
3051 F_ENABLE_FLAG, h_config_enable_flag, PREF_ACMD, 1},
3052 {"enable-flag-screen-implicitly", NULL,
3053 F_FLAG_SCREEN_DFLT, h_config_flag_screen_default, PREF_ACMD, 0},
3054 {"enable-flag-screen-keyword-shortcut", NULL,
3055 F_FLAG_SCREEN_KW_SHORTCUT, h_config_flag_screen_kw_shortcut,PREF_ACMD, 1},
3056 {"enable-full-header-and-text", "Enable Full Header and Text",
3057 F_ENABLE_FULL_HDR_AND_TEXT, h_config_enable_full_hdr_and_text, PREF_ACMD, 0},
3058 {"enable-full-header-cmd", "Enable Full Header Command",
3059 F_ENABLE_FULL_HDR, h_config_enable_full_hdr, PREF_ACMD, 1},
3060 {"enable-goto-in-file-browser", "Enable Goto in File Browser",
3061 F_ALLOW_GOTO, h_config_allow_goto, PREF_ACMD, 1},
3062 {"enable-jump-shortcut", NULL,
3063 F_ENABLE_JUMP, h_config_enable_jump, PREF_ACMD, 1},
3064 {"enable-partial-match-lists", NULL,
3065 F_ENABLE_SUB_LISTS, h_config_sub_lists, PREF_ACMD, 1},
3066 {"enable-tab-completion", NULL,
3067 F_ENABLE_TAB_COMPLETE, h_config_enable_tab_complete, PREF_ACMD, 1},
3068 {"enable-unix-pipe-cmd", "Enable Unix Pipe Command",
3069 F_ENABLE_PIPE, h_config_enable_pipe, PREF_ACMD, 1},
3070 {"quell-full-header-auto-reset", "Suppress Full Header Auto Reset",
3071 F_QUELL_FULL_HDR_RESET, h_config_quell_full_hdr_reset, PREF_ACMD, 0},
3073 /* Adv user prefs */
3074 #if !defined(DOS) && !defined(OS2)
3075 {"allow-talk", NULL,
3076 F_ALLOW_TALK, h_config_allow_talk, PREF_MISC, 0},
3077 #endif
3078 {"assume-slow-link", NULL,
3079 F_FORCE_LOW_SPEED, h_config_force_low_speed, PREF_OS_LWSD, 0},
3080 {"auto-move-read-msgs", "Auto Move Read Messages",
3081 F_AUTO_READ_MSGS, h_config_auto_read_msgs, PREF_MISC, 0},
3082 {"auto-unselect-after-apply", NULL,
3083 F_AUTO_UNSELECT, h_config_auto_unselect, PREF_MISC, 0},
3084 {"auto-unzoom-after-apply", NULL,
3085 F_AUTO_UNZOOM, h_config_auto_unzoom, PREF_MISC, 1},
3086 {"auto-zoom-after-select", NULL,
3087 F_AUTO_ZOOM, h_config_auto_zoom, PREF_MISC, 1},
3088 {"busy-cue-spinner-only", NULL,
3089 F_USE_BORING_SPINNER, h_config_use_boring_spinner, PREF_MISC, 0},
3090 {"check-newmail-when-quitting", NULL,
3091 F_CHECK_MAIL_ONQUIT, h_config_check_mail_onquit, PREF_MISC, 0},
3092 {"confirm-role-even-for-default", "Confirm Role Even for Default",
3093 F_ROLE_CONFIRM_DEFAULT, h_config_confirm_role, PREF_MISC, 0},
3094 {"disable-keymenu", NULL,
3095 F_BLANK_KEYMENU, h_config_blank_keymenu, PREF_MISC, 0},
3096 {"disable-password-caching", NULL,
3097 F_DISABLE_PASSWORD_CACHING, h_config_disable_password_caching,
3098 PREF_MISC, 0},
3099 #ifdef PASSFILE
3100 {"disable-password-file-saving", NULL,
3101 F_DISABLE_PASSWORD_FILE_SAVING, h_config_disable_password_file_saving,
3102 PREF_MISC, 0},
3103 #endif
3104 {"disable-regular-expression-matching-for-alternate-addresses", NULL,
3105 F_DISABLE_REGEX, h_config_disable_regex, PREF_MISC, 0},
3106 {"disable-save-input-history", NULL,
3107 F_DISABLE_SAVE_INPUT_HISTORY, h_config_input_history, PREF_MISC, 0},
3108 {"disable-take-fullname-in-addresses", "Disable Take Fullname in Addresses",
3109 F_DISABLE_TAKE_FULLNAMES, h_config_take_fullname, PREF_MISC, 0},
3110 {"disable-take-last-comma-first", NULL,
3111 F_DISABLE_TAKE_LASTFIRST, h_config_take_lastfirst, PREF_MISC, 0},
3112 {"disable-terminal-reset-for-display-filters", "Disable Terminal Reset for Display Filters",
3113 F_DISABLE_TERM_RESET_DISP, h_config_disable_reset_disp, PREF_MISC, 0},
3114 {"enable-dot-files", NULL,
3115 F_ENABLE_DOT_FILES, h_config_enable_dot_files, PREF_MISC, 0},
3116 {"enable-fast-recent-test", NULL,
3117 F_ENABLE_FAST_RECENT, h_config_fast_recent, PREF_MISC, 0},
3118 {"enable-mail-check-cue", NULL,
3119 F_SHOW_DELAY_CUE, h_config_show_delay_cue, PREF_MISC, 0},
3120 {"enable-mailcap-param-substitution", "Enable Mailcap Parameter Substitution",
3121 F_DO_MAILCAP_PARAM_SUBST, h_config_mailcap_params, PREF_MISC, 0},
3122 {"enable-mouse-in-xterm", "Enable Mouse in Xterm",
3123 F_ENABLE_MOUSE, h_config_enable_mouse, PREF_OS_MOUSE, 0},
3124 {"enable-newmail-in-xterm-icon", "Enable Newmail in Xterm Icon",
3125 F_ENABLE_XTERM_NEWMAIL, h_config_enable_xterm_newmail, PREF_OS_XNML, 0},
3126 {"enable-newmail-short-text-in-icon", "Enable Newmail Short Text in Icon",
3127 F_ENABLE_NEWMAIL_SHORT_TEXT, h_config_enable_newmail_short_text, PREF_OS_XNML, 0},
3128 {"enable-suspend", NULL,
3129 F_CAN_SUSPEND, h_config_can_suspend, PREF_MISC, 0},
3130 {"enable-take-export", NULL,
3131 F_ENABLE_TAKE_EXPORT, h_config_enable_take_export, PREF_MISC, 0},
3132 {"enable-rules-under-take", "Enable Take Rules",
3133 F_ENABLE_ROLE_TAKE, h_config_enable_role_take, PREF_MISC, 0},
3134 #ifdef _WINDOWS
3135 {"enable-tray-icon", NULL,
3136 F_ENABLE_TRAYICON, h_config_tray_icon, PREF_MISC, 0},
3137 #endif
3138 {"expose-hidden-config", NULL,
3139 F_EXPOSE_HIDDEN_CONFIG, h_config_expose_hidden_config, PREF_MISC, 0},
3140 {"expunge-only-manually", NULL,
3141 F_EXPUNGE_MANUALLY, h_config_expunge_manually, PREF_MISC, 0},
3142 {"expunge-without-confirm", "Expunge Without Confirming",
3143 F_AUTO_EXPUNGE, h_config_auto_expunge, PREF_MISC, 0},
3144 {"expunge-without-confirm-everywhere", "Expunge Without Confirming Everywhere",
3145 F_FULL_AUTO_EXPUNGE, h_config_full_auto_expunge, PREF_MISC, 0},
3146 {"force-arrow-cursor", NULL,
3147 F_FORCE_ARROW, h_config_force_arrow, PREF_MISC, 0},
3148 {"ignore-size-changes", NULL,
3149 F_IGNORE_SIZE, h_config_ignore_size, PREF_MISC, 0},
3150 {"maildrops-preserve-state", NULL,
3151 F_MAILDROPS_PRESERVE_STATE, h_config_maildrops_preserve_state,
3152 PREF_MISC, 0},
3153 {"offer-expunge-of-inbox", "Offer Expunge of INBOX",
3154 F_EXPUNGE_INBOX, h_config_expunge_inbox, PREF_MISC, 0},
3155 {"offer-expunge-of-stayopen-folders", "Offer Expunge of Stayopen Folders",
3156 F_EXPUNGE_STAYOPENS, h_config_expunge_stayopens, PREF_MISC, 0},
3157 {"preopen-stayopen-folders", NULL,
3158 F_PREOPEN_STAYOPENS, h_config_preopen_stayopens, PREF_MISC, 0},
3159 {"preserve-start-stop-characters", "Preserve Start/Stop Characters",
3160 F_PRESERVE_START_STOP, h_config_preserve_start_stop, PREF_OS_STSP, 0},
3161 {"quell-folder-internal-msg", "Prevent Folder Internal Message",
3162 F_QUELL_INTERNAL_MSG, h_config_quell_folder_internal_msg, PREF_MISC, 0},
3163 {"quell-partial-fetching", "Prevent Partial Fetching",
3164 F_QUELL_PARTIAL_FETCH, h_config_quell_partial, PREF_MISC, 0},
3165 {"prune-uses-yyyy-mm", "Prune Uses YYYY-MM",
3166 F_PRUNE_USES_ISO, h_config_prune_uses_iso, PREF_MISC, 0},
3167 {"quit-without-confirm", "Quit Without Confirming",
3168 F_QUIT_WO_CONFIRM, h_config_quit_wo_confirm, PREF_MISC, 0},
3169 {"quote-replace-nonflowed", NULL,
3170 F_QUOTE_REPLACE_NOFLOW, h_config_quote_replace_noflow, PREF_MISC, 0},
3171 {"save-aggregates-copy-sequence", "Save Combines Copies (may be out of order)",
3172 F_AGG_SEQ_COPY, h_config_save_aggregates, PREF_MISC, 1},
3173 {"save-partial-msg-without-confirm", "Save Partial Message Without Confirming",
3174 F_SAVE_PARTIAL_WO_CONFIRM, h_config_save_part_wo_confirm, PREF_MISC, 0},
3175 {"save-will-advance", NULL,
3176 F_SAVE_ADVANCES, h_config_save_advances, PREF_MISC, 0},
3177 {"save-will-not-delete", NULL,
3178 F_SAVE_WONT_DELETE, h_config_save_wont_delete, PREF_MISC, 0},
3179 {"save-will-quote-leading-froms", NULL,
3180 F_QUOTE_ALL_FROMS, h_config_quote_all_froms, PREF_MISC, 0},
3181 {"scramble-message-id", "Scramble the Message-ID When Sending",
3182 F_ROT13_MESSAGE_ID, h_config_scramble_message_id, PREF_MISC, 0},
3183 {"select-without-confirm", "Select Ctrl-T Foldername Without Confirming",
3184 F_SELECT_WO_CONFIRM, h_config_select_wo_confirm, PREF_MISC, 0},
3185 {"show-cursor", NULL,
3186 F_SHOW_CURSOR, h_config_show_cursor, PREF_MISC, 0},
3187 {"show-plain-text-internally", NULL,
3188 F_SHOW_TEXTPLAIN_INT, h_config_textplain_int, PREF_MISC, 0},
3189 {"show-selected-in-boldface", "Show Selected in Boldface",
3190 F_SELECTED_SHOWN_BOLD, h_config_select_in_bold, PREF_MISC, 0},
3191 {"slash-collapses-entire-thread", NULL,
3192 F_SLASH_COLL_ENTIRE, h_config_slash_coll_entire, PREF_MISC, 0},
3193 #ifdef _WINDOWS
3194 {"store-window-position-in-config", "Store Window Position in Config",
3195 F_STORE_WINPOS_IN_CONFIG, h_config_winpos_in_config, PREF_MISC, 0},
3196 #endif
3197 {"suppress-asterisks-in-password-prompt", "Suppress Asterisks in Password Prompt",
3198 F_QUELL_ASTERISKS, h_config_quell_asterisks,
3199 PREF_MISC, 0},
3200 {"quell-attachment-extension-warn", "Suppress Attachment Extension Warning",
3201 F_QUELL_ATTACH_EXT_WARN, h_config_quell_attach_ext_warn,
3202 PREF_MISC, 0},
3203 {"quell-attachment-extra-prompt", "Suppress Attachment Extra Prompt",
3204 F_QUELL_ATTACH_EXTRA_PROMPT, h_config_quell_attach_extra_prompt,
3205 PREF_MISC, 0},
3206 {"quell-berkeley-format-timezone", "Suppress Berkeley Format Timezone",
3207 F_QUELL_BEZERK_TIMEZONE, h_config_no_bezerk_zone, PREF_MISC, 0},
3208 {"quell-content-id", "Suppress Content-ID",
3209 F_QUELL_CONTENT_ID, h_config_quell_content_id, PREF_MISC, 0},
3210 {"quell-filtering-done-message", "Suppress Filtering Done Message",
3211 F_QUELL_FILTER_DONE_MSG, h_config_quell_filtering_done_message,
3212 PREF_MISC, 0},
3213 {"quell-filtering-messages", "Suppress Filtering Messages",
3214 F_QUELL_FILTER_MSGS, h_config_quell_filtering_messages,
3215 PREF_MISC, 0},
3216 {"quell-imap-envelope-update", "Suppress IMAP Envelope Update",
3217 F_QUELL_IMAP_ENV_CB, h_config_quell_imap_env, PREF_MISC, 0},
3218 {"quell-lock-failure-warnings", "Suppress Lock Failure Warnings",
3219 F_QUELL_LOCK_FAILURE_MSGS, h_config_quell_lock_failure_warnings,
3220 PREF_MISC, 0},
3221 {"quell-maildomain-warning", "Suppress Maildomain Warning",
3222 F_QUELL_MAILDOMAIN_WARNING, h_config_quell_domain_warn, PREF_MISC, 0},
3223 {"quell-news-envelope-update", "Suppress News Envelope Update",
3224 F_QUELL_NEWS_ENV_CB, h_config_quell_news_env, PREF_MISC, 0},
3225 #ifdef _WINDOWS
3226 {"quell-ssl-largeblocks", "Prevent SSL Largeblocks",
3227 F_QUELL_SSL_LARGEBLOCKS, h_config_quell_ssl_largeblocks, PREF_MISC, 0},
3228 #endif
3229 {"quell-status-message-beeping", "Suppress Status Message Beeping",
3230 F_QUELL_BEEPS, h_config_quell_beeps, PREF_MISC, 0},
3231 {"quell-timezone-comment-when-sending", "Suppress Timezone Comment When Sending",
3232 F_QUELL_TIMEZONE, h_config_quell_tz_comment, PREF_MISC, 0},
3233 {"suppress-user-agent-when-sending", NULL,
3234 F_QUELL_USERAGENT, h_config_suppress_user_agent, PREF_MISC, 0},
3235 {"tab-checks-recent", "Tab Checks for Recent Messages",
3236 F_TAB_CHK_RECENT, h_config_tab_checks_recent, PREF_MISC, 0},
3237 {"termdef-takes-precedence", NULL,
3238 F_TCAP_WINS, h_config_termcap_wins, PREF_MISC, 0},
3239 {"try-alternative-authentication-driver-first", NULL,
3240 F_PREFER_ALT_AUTH, h_config_alt_auth, PREF_MISC, 0},
3241 {"unselect-will-not-advance", NULL,
3242 F_UNSELECT_WONT_ADVANCE, h_config_unsel_wont_advance, PREF_MISC, 0},
3243 {"use-current-dir", "Use Current Directory",
3244 F_USE_CURRENT_DIR, h_config_use_current_dir, PREF_MISC, 0},
3245 {"use-function-keys", NULL,
3246 F_USE_FK, h_config_use_fk, PREF_OS_USFK, 0},
3247 {"use-regular-startup-rule-for-stayopen-folders", "Use Regular Startup Rule for Stayopen Folders",
3248 F_STARTUP_STAYOPEN, h_config_use_reg_start_for_stayopen, PREF_MISC, 0},
3249 {"use-resent-to-in-rules", "Use Resent-To in Rules",
3250 F_USE_RESENTTO, h_config_use_resentto, PREF_MISC, 0},
3251 {"use-subshell-for-suspend", "Use Subshell for Suspend",
3252 F_SUSPEND_SPAWNS, h_config_suspend_spawns, PREF_OS_SPWN, 0},
3253 #ifndef _WINDOWS
3254 {"use-system-translation", NULL,
3255 F_USE_SYSTEM_TRANS, h_config_use_system_translation, PREF_MISC, 0},
3256 #endif
3258 /* Hidden Features */
3259 {"old-growth", NULL,
3260 F_OLD_GROWTH, NO_HELP, PREF_NONE, 0},
3261 {"disable-config-cmd", NULL,
3262 F_DISABLE_CONFIG_SCREEN, h_config_disable_config_cmd, PREF_HIDDEN, 0},
3263 {"disable-keyboard-lock-cmd", NULL,
3264 F_DISABLE_KBLOCK_CMD, h_config_disable_kb_lock, PREF_HIDDEN, 0},
3265 {"disable-password-cmd", NULL,
3266 F_DISABLE_PASSWORD_CMD, h_config_disable_password_cmd, PREF_HIDDEN, 0},
3267 {"disable-pipes-in-sigs", NULL,
3268 F_DISABLE_PIPES_IN_SIGS, h_config_disable_pipes_in_sigs, PREF_HIDDEN, 0},
3269 {"disable-pipes-in-templates", NULL,
3270 F_DISABLE_PIPES_IN_TEMPLATES, h_config_disable_pipes_in_templates,
3271 PREF_HIDDEN, 0},
3272 {"disable-roles-setup-cmd", NULL,
3273 F_DISABLE_ROLES_SETUP, h_config_disable_roles_setup, PREF_HIDDEN, 0},
3274 {"disable-roles-sig-edit", NULL,
3275 F_DISABLE_ROLES_SIGEDIT, h_config_disable_roles_sigedit, PREF_HIDDEN, 0},
3276 {"disable-roles-template-edit", NULL,
3277 F_DISABLE_ROLES_TEMPLEDIT, h_config_disable_roles_templateedit,
3278 PREF_HIDDEN, 0},
3279 {"disable-setlocale-collate", NULL,
3280 F_DISABLE_SETLOCALE_COLLATE, h_config_disable_collate, PREF_HIDDEN, 0},
3281 {"disable-shared-namespaces", NULL,
3282 F_DISABLE_SHARED_NAMESPACES, h_config_disable_shared, PREF_HIDDEN, 0},
3283 {"disable-signature-edit-cmd", NULL,
3284 F_DISABLE_SIGEDIT_CMD, h_config_disable_signature_edit, PREF_HIDDEN, 0},
3285 {"new-thread-on-blank-subject", "New Thread on Blank Subject",
3286 F_NEW_THREAD_ON_BLANK_SUBJECT, h_config_new_thread_blank_subject, PREF_HIDDEN, 1},
3287 {"quell-personal-name-prompt", NULL,
3288 F_QUELL_PERSONAL_NAME_PROMPT, h_config_quell_personal_name_prompt, PREF_HIDDEN, 0},
3289 {"quell-user-id-prompt", "Quell User ID Prompt",
3290 F_QUELL_USER_ID_PROMPT, h_config_quell_user_id_prompt, PREF_HIDDEN, 0},
3291 #ifdef SMIME
3292 {"smime-dont-do-smime", "S/MIME -- Turn off S/MIME",
3293 F_DONT_DO_SMIME, h_config_smime_dont_do_smime, PREF_HIDDEN, 0},
3294 {"smime-encrypt-by-default", "S/MIME -- Encrypt by Default",
3295 F_ENCRYPT_DEFAULT_ON, h_config_smime_encrypt_by_default, PREF_HIDDEN, 0},
3296 {"smime-remember-passphrase", "S/MIME -- Remember S/MIME Passphrase",
3297 F_REMEMBER_SMIME_PASSPHRASE, h_config_smime_remember_passphrase, PREF_HIDDEN, 0},
3298 {"smime-sign-by-default", "S/MIME -- Sign by Default",
3299 F_SIGN_DEFAULT_ON, h_config_smime_sign_by_default, PREF_HIDDEN, 0},
3300 {"smime-use-store-only", "S/MIME -- Validate Using Certificate Store Only",
3301 F_USE_CERT_STORE_ONLY, h_config_smime_use_cert_store, PREF_HIDDEN, 1},
3302 #ifdef APPLEKEYCHAIN
3303 {"publiccerts-in-keychain", "S/MIME -- Public Certs in MacOS Keychain",
3304 F_PUBLICCERTS_IN_KEYCHAIN, h_config_smime_pubcerts_in_keychain, PREF_HIDDEN, 0},
3305 #endif
3306 #endif
3307 {"selectable-item-nobold", NULL,
3308 F_SLCTBL_ITEM_NOBOLD, NO_HELP, PREF_NONE, 0},
3309 {"send-confirms-only-expanded", NULL, /* exposed in Web Alpine */
3310 F_SEND_CONFIRM_ON_EXPAND, h_config_send_confirms_only_expanded, PREF_HIDDEN, 0},
3311 {"enable-jump-cmd", NULL, /* exposed in Web Alpine */
3312 F_ENABLE_JUMP_CMD, h_config_enable_jump_command, PREF_HIDDEN, 0},
3313 {"enable-newmail-sound", NULL, /* exposed in Web Alpine */
3314 F_ENABLE_NEWMAIL_SOUND, h_config_enable_newmail_sound, PREF_HIDDEN, 0},
3315 {"render-html-internally", NULL, /* exposed in Web Alpine */
3316 F_RENDER_HTML_INTERNALLY, h_config_render_html_internally, PREF_HIDDEN, 0}
3319 return((index >= 0 && index < (sizeof(feat_list)/sizeof(feat_list[0])))
3320 ? &feat_list[index] : NULL);
3325 * feature_list_index -- return index of given feature id in
3326 * feature list
3329 feature_list_index(int id)
3331 FEATURE_S *feature;
3332 int i;
3334 for(i = 0; (feature = feature_list(i)); i++)
3335 if(id == feature->id)
3336 return(i);
3338 return(-1);
3343 * feature_list_name -- return the given feature id's corresponding name
3345 char *
3346 feature_list_name(int id)
3348 FEATURE_S *f;
3350 return((f = feature_list(feature_list_index(id))) ? f->name : "");
3355 feature_list_id(char *name)
3357 FEATURE_S *f;
3358 int i;
3360 for(i = 0; (f = feature_list(i)); i++)
3361 if(!strucmp(f->name, name))
3362 return(f->id);
3364 return(-1);
3369 * feature_list_help -- return the given feature id's corresponding help
3371 HelpType
3372 feature_list_help(int id)
3374 FEATURE_S *f;
3376 return((f = feature_list(feature_list_index(id))) ? f->help : NO_HELP);
3381 * All the arguments past "list" are the backwards compatibility hacks.
3383 void
3384 process_feature_list(struct pine *ps, char **list, int old_growth, int hir, int osr)
3386 register char *q;
3387 char **p,
3388 *lvalue[BM_SIZE * 8];
3389 int i,
3390 yorn;
3391 long l;
3392 FEATURE_S *feat;
3395 /* clear all previous settings and reset them to default */
3396 for(i = 0; (feat = feature_list(i)) != NULL; i++)
3397 F_SET(feat->id, ps, feat->defval);
3399 /* backwards compatibility */
3400 if(hir)
3401 F_TURN_ON(F_INCLUDE_HEADER, ps);
3403 /* ditto */
3404 if(osr)
3405 F_TURN_ON(F_SIG_AT_BOTTOM, ps);
3407 /* ditto */
3408 if(old_growth)
3409 set_old_growth_bits(ps, 0);
3411 /* now run through the list (global, user, and cmd_line lists are here) */
3412 if(list){
3413 for(p = list; (q = *p) != NULL; p++){
3414 if(struncmp(q, "no-", 3) == 0){
3415 yorn = 0;
3416 q += 3;
3417 }else{
3418 yorn = 1;
3421 for(i = 0; (feat = feature_list(i)) != NULL; i++){
3422 if(strucmp(q, feat->name) == 0){
3423 if(feat->id == F_OLD_GROWTH){
3424 set_old_growth_bits(ps, yorn);
3425 }else{
3426 F_SET(feat->id, ps, yorn);
3428 break;
3432 /* if it wasn't in that list */
3433 if(feat == NULL)
3434 dprint((1,"Unrecognized feature in feature-list (%s%s)\n",
3435 (yorn ? "" : "no-"), q ? q : "?"));
3440 * Turn on gratuitous '>From ' quoting, if requested...
3442 mail_parameters(NULL, SET_FROMWIDGET,
3443 F_ON(F_QUOTE_ALL_FROMS, ps) ? VOIDT : NIL);
3446 * Turn off .lock creation complaints...
3448 if(F_ON(F_QUELL_LOCK_FAILURE_MSGS, ps))
3449 mail_parameters(NULL, SET_LOCKEACCESERROR, (void *) 0);
3452 * Turn on quelling of pseudo message.
3454 if(F_ON(F_QUELL_INTERNAL_MSG,ps_global))
3455 mail_parameters(NULL, SET_USERHASNOLIFE, (void *) 1);
3457 l = F_ON(F_MULNEWSRC_HOSTNAMES_AS_TYPED,ps_global) ? 0L : 1L;
3458 mail_parameters(NULL, SET_NEWSRCCANONHOST, (void *) l);
3460 ps->pass_ctrl_chars = F_ON(F_PASS_CONTROL_CHARS,ps_global) ? 1 : 0;
3461 ps->pass_c1_ctrl_chars = F_ON(F_PASS_C1_CONTROL_CHARS,ps_global) ? 1 : 0;
3463 #ifndef _WINDOWS
3464 if(F_ON(F_QUELL_BEZERK_TIMEZONE,ps_global))
3465 mail_parameters(NULL, SET_NOTIMEZONES, (void *) 1);
3466 #endif
3468 if(F_ON(F_USE_FK, ps))
3469 ps->orig_use_fkeys = 1;
3471 /* Will we have to build a new list? */
3472 if(!(old_growth || hir || osr))
3473 return;
3476 * Build a new list for feature-list. The only reason we ever need to
3477 * do this is if one of the obsolete options is being converted
3478 * into a feature-list item, and it isn't already included in the user's
3479 * feature-list.
3481 i = 0;
3482 for(p = LVAL(&ps->vars[V_FEATURE_LIST], Main);
3483 p && (q = *p); p++){
3484 /* already have it or cancelled it, don't need to add later */
3485 if(hir && (strucmp(q, "include-header-in-reply") == 0 ||
3486 strucmp(q, "no-include-header-in-reply") == 0)){
3487 hir = 0;
3488 }else if(osr && (strucmp(q, "signature-at-bottom") == 0 ||
3489 strucmp(q, "no-signature-at-bottom") == 0)){
3490 osr = 0;
3491 }else if(old_growth && (strucmp(q, "old-growth") == 0 ||
3492 strucmp(q, "no-old-growth") == 0)){
3493 old_growth = 0;
3495 lvalue[i++] = cpystr(q);
3498 /* check to see if we still need to build a new list */
3499 if(!(old_growth || hir || osr))
3500 return;
3502 if(hir)
3503 lvalue[i++] = "include-header-in-reply";
3504 if(osr)
3505 lvalue[i++] = "signature-at-bottom";
3506 if(old_growth)
3507 lvalue[i++] = "old-growth";
3508 lvalue[i] = NULL;
3509 set_variable_list(V_FEATURE_LIST, lvalue, TRUE, Main);
3513 void
3514 set_current_pattern_vals(struct pine *ps)
3516 struct variable *vars = ps->vars;
3518 set_current_val(&vars[V_PATTERNS], TRUE, TRUE);
3519 set_current_val(&vars[V_PAT_ROLES], TRUE, TRUE);
3520 set_current_val(&vars[V_PAT_FILTS], TRUE, TRUE);
3521 set_current_val(&vars[V_PAT_FILTS_OLD], TRUE, TRUE);
3522 set_current_val(&vars[V_PAT_SCORES], TRUE, TRUE);
3523 set_current_val(&vars[V_PAT_SCORES_OLD], TRUE, TRUE);
3524 set_current_val(&vars[V_PAT_INCOLS], TRUE, TRUE);
3525 set_current_val(&vars[V_PAT_OTHER], TRUE, TRUE);
3526 set_current_val(&vars[V_PAT_SRCH], TRUE, TRUE);
3529 * If old pattern variable (V_PATTERNS) is set and the new ones aren't
3530 * in the config file, then convert the old data into the new variables.
3531 * It isn't quite that simple, though, because we don't store unset
3532 * variables in remote pinercs. Check for the variables but if we
3533 * don't find any of them, also check the version number. This change was
3534 * made in version 4.30. We could just check that except that we're
3535 * worried somebody will make an incompatible version number change in
3536 * their local version, and will break this. So we check both the
3537 * version # and the var_in_pinerc things to be safer.
3539 if(vars[V_PATTERNS].current_val.l
3540 && vars[V_PATTERNS].current_val.l[0]
3541 && !var_in_pinerc(vars[V_PAT_ROLES].name)
3542 && !var_in_pinerc(vars[V_PAT_FILTS].name)
3543 && !var_in_pinerc(vars[V_PAT_FILTS_OLD].name)
3544 && !var_in_pinerc(vars[V_PAT_SCORES].name)
3545 && !var_in_pinerc(vars[V_PAT_SCORES_OLD].name)
3546 && !var_in_pinerc(vars[V_PAT_INCOLS].name)
3547 && isdigit((unsigned char) ps->pine_pre_vers[0])
3548 && ps->pine_pre_vers[1] == '.'
3549 && isdigit((unsigned char) ps->pine_pre_vers[2])
3550 && isdigit((unsigned char) ps->pine_pre_vers[3])
3551 && strncmp(ps->pine_pre_vers, "4.30", 4) < 0){
3552 convert_pattern_data();
3556 * Otherwise, if FILTS_OLD is set and FILTS isn't in the config file,
3557 * convert FILTS_OLD to FILTS. Same for SCORES.
3558 * The reason FILTS was changed was so we could change the
3559 * semantics of how rules work when there are pieces in the rule that
3560 * we don't understand. At the same time as the FILTS change we added
3561 * a rule to detect 8bitSubjects. So a user might have a filter that
3562 * deletes messages with 8bitSubjects. The problem is that that same
3563 * filter in a FILTS_OLD pine would match because it would ignore the
3564 * 8bitSubject part of the pattern and match on the rest. So we changed
3565 * the semantics so that rules with unknown bits would be ignored
3566 * instead of used. We had to change variable names at the same time
3567 * because we were adding the 8bit thing and the old pines are still
3568 * out there. Filters and Scores can both be dangerous. Roles, Colors,
3569 * and Other seem less dangerous so not worth adding a new variable.
3570 * This was changed in 4.50.
3572 else{
3573 if(vars[V_PAT_FILTS_OLD].current_val.l
3574 && vars[V_PAT_FILTS_OLD].current_val.l[0]
3575 && !var_in_pinerc(vars[V_PAT_FILTS].name)
3576 && !var_in_pinerc(vars[V_PAT_SCORES].name)
3577 && isdigit((unsigned char) ps->pine_pre_vers[0])
3578 && ps->pine_pre_vers[1] == '.'
3579 && isdigit((unsigned char) ps->pine_pre_vers[2])
3580 && isdigit((unsigned char) ps->pine_pre_vers[3])
3581 && strncmp(ps->pine_pre_vers, "4.50", 4) < 0){
3582 convert_filts_pattern_data();
3585 if(vars[V_PAT_SCORES_OLD].current_val.l
3586 && vars[V_PAT_SCORES_OLD].current_val.l[0]
3587 && !var_in_pinerc(vars[V_PAT_FILTS].name)
3588 && !var_in_pinerc(vars[V_PAT_SCORES].name)
3589 && isdigit((unsigned char) ps->pine_pre_vers[0])
3590 && ps->pine_pre_vers[1] == '.'
3591 && isdigit((unsigned char) ps->pine_pre_vers[2])
3592 && isdigit((unsigned char) ps->pine_pre_vers[3])
3593 && strncmp(ps->pine_pre_vers, "4.50", 4) < 0){
3594 convert_scores_pattern_data();
3598 if(vars[V_PAT_ROLES].post_user_val.l)
3599 ps_global->ew_for_role_take = Post;
3600 else
3601 ps_global->ew_for_role_take = Main;
3603 if(vars[V_PAT_FILTS].post_user_val.l)
3604 ps_global->ew_for_filter_take = Post;
3605 else
3606 ps_global->ew_for_filter_take = Main;
3608 if(vars[V_PAT_SCORES].post_user_val.l)
3609 ps_global->ew_for_score_take = Post;
3610 else
3611 ps_global->ew_for_score_take = Main;
3613 if(vars[V_PAT_INCOLS].post_user_val.l)
3614 ps_global->ew_for_incol_take = Post;
3615 else
3616 ps_global->ew_for_incol_take = Main;
3618 if(vars[V_PAT_OTHER].post_user_val.l)
3619 ps_global->ew_for_other_take = Post;
3620 else
3621 ps_global->ew_for_other_take = Main;
3623 if(vars[V_PAT_SRCH].post_user_val.l)
3624 ps_global->ew_for_srch_take = Post;
3625 else
3626 ps_global->ew_for_srch_take = Main;
3631 * Foreach of the config files;
3632 * transfer the data to the new variables.
3634 void
3635 convert_pattern_data(void)
3637 convert_pinerc_patterns(PAT_USE_MAIN);
3638 convert_pinerc_patterns(PAT_USE_POST);
3642 void
3643 convert_filts_pattern_data(void)
3645 convert_pinerc_filts_patterns(PAT_USE_MAIN);
3646 convert_pinerc_filts_patterns(PAT_USE_POST);
3650 void
3651 convert_scores_pattern_data(void)
3653 convert_pinerc_scores_patterns(PAT_USE_MAIN);
3654 convert_pinerc_scores_patterns(PAT_USE_POST);
3659 * Foreach of the four variables, transfer the data for this config file
3660 * from the old patterns variable. We don't have to convert OTHER patterns
3661 * or SRCH patterns because they didn't exist in pines without patterns-other.
3663 * If the original variable had patlines with type File then we convert
3664 * all of the individual patterns to type Lit, because each pattern can
3665 * be of any category. Lit patterns are better tested, anyway.
3667 void
3668 convert_pinerc_patterns(long int use_flags)
3670 long old_rflags;
3671 long rflags;
3672 PAT_S *pat;
3673 PAT_STATE pstate;
3674 ACTION_S *act;
3676 old_rflags = (ROLE_OLD_PAT | use_flags);
3678 rflags = 0L;
3679 if(any_patterns(old_rflags, &pstate)){
3680 dprint((2, "converting old patterns to new (%s)\n", (use_flags == PAT_USE_MAIN) ? "Main" : "Post"));
3681 for(pat = first_pattern(&pstate);
3682 pat;
3683 pat = next_pattern(&pstate)){
3684 if((act = pat->action) != NULL){
3685 if(act->is_a_role &&
3686 add_to_pattern(pat, ROLE_DO_ROLES | use_flags))
3687 rflags |= ROLE_DO_ROLES;
3688 if(act->is_a_incol &&
3689 add_to_pattern(pat, ROLE_DO_INCOLS | use_flags))
3690 rflags |= ROLE_DO_INCOLS;
3691 if(act->is_a_score &&
3692 add_to_pattern(pat, ROLE_DO_SCORES | use_flags))
3693 rflags |= ROLE_DO_SCORES;
3694 if(act->is_a_filter &&
3695 add_to_pattern(pat, ROLE_DO_FILTER | use_flags))
3696 rflags |= ROLE_DO_FILTER;
3700 if(rflags)
3701 if(write_patterns(rflags | use_flags))
3702 dprint((1,
3703 "Trouble converting patterns to new variable\n"));
3709 * If the original variable had patlines with type File then we convert
3710 * all of the individual patterns to type Lit, because each pattern can
3711 * be of any category. Lit patterns are better tested, anyway.
3713 void
3714 convert_pinerc_filts_patterns(long int use_flags)
3716 long old_rflags;
3717 long rflags;
3718 PAT_S *pat;
3719 PAT_STATE pstate;
3720 ACTION_S *act;
3722 old_rflags = (ROLE_OLD_FILT | use_flags);
3724 rflags = 0L;
3725 if(any_patterns(old_rflags, &pstate)){
3726 dprint((2, "converting old filter patterns to new (%s)\n", (use_flags == PAT_USE_MAIN) ? "Main" : "Post"));
3727 for(pat = first_pattern(&pstate);
3728 pat;
3729 pat = next_pattern(&pstate)){
3730 if((act = pat->action) != NULL){
3731 if(act->is_a_filter &&
3732 add_to_pattern(pat, ROLE_DO_FILTER | use_flags))
3733 rflags |= ROLE_DO_FILTER;
3737 if(rflags)
3738 if(write_patterns(rflags | use_flags))
3739 dprint((1,
3740 "Trouble converting filter patterns to new variable\n"));
3746 * If the original variable had patlines with type File then we convert
3747 * all of the individual patterns to type Lit, because each pattern can
3748 * be of any category. Lit patterns are better tested, anyway.
3750 void
3751 convert_pinerc_scores_patterns(long int use_flags)
3753 long old_rflags;
3754 long rflags;
3755 PAT_S *pat;
3756 PAT_STATE pstate;
3757 ACTION_S *act;
3759 old_rflags = (ROLE_OLD_SCORE | use_flags);
3761 rflags = 0L;
3762 if(any_patterns(old_rflags, &pstate)){
3763 dprint((2, "converting old scores patterns to new (%s)\n", (use_flags == PAT_USE_MAIN) ? "Main" : "Post"));
3764 for(pat = first_pattern(&pstate);
3765 pat;
3766 pat = next_pattern(&pstate)){
3767 if((act = pat->action) != NULL){
3768 if(act->is_a_score &&
3769 add_to_pattern(pat, ROLE_DO_SCORES | use_flags))
3770 rflags |= ROLE_DO_SCORES;
3774 if(rflags)
3775 if(write_patterns(rflags | use_flags))
3776 dprint((1,
3777 "Trouble converting scores patterns to new variable\n"));
3783 * set_old_growth_bits - Command used to set or unset old growth set
3784 * of features
3786 void
3787 set_old_growth_bits(struct pine *ps, int val)
3789 int i;
3791 for(i = 1; i <= F_FEATURE_LIST_COUNT; i++)
3792 if(test_old_growth_bits(ps, i))
3793 F_SET(i, ps, val);
3799 * test_old_growth_bits - Test to see if all the old growth bits are on,
3800 * *or* if a particular feature index is in the old
3801 * growth set.
3803 * WEIRD ALERT: if index == F_OLD_GROWTH bit values are tested
3804 * otherwise a bits existence in the set is tested!!!
3806 * BUG: this will break if an old growth feature number is ever >= 32.
3809 test_old_growth_bits(struct pine *ps, int index)
3812 * this list defines F_OLD_GROWTH set
3814 static unsigned long old_growth_bits = ((1 << F_ENABLE_FULL_HDR) |
3815 (1 << F_ENABLE_PIPE) |
3816 (1 << F_ENABLE_TAB_COMPLETE) |
3817 (1 << F_QUIT_WO_CONFIRM) |
3818 (1 << F_ENABLE_JUMP) |
3819 (1 << F_ENABLE_ALT_ED) |
3820 (1 << F_ENABLE_BOUNCE) |
3821 (1 << F_ENABLE_AGG_OPS) |
3822 (1 << F_ENABLE_FLAG) |
3823 (1 << F_CAN_SUSPEND));
3824 if(index >= 32)
3825 return(0);
3827 if(index == F_OLD_GROWTH){
3828 for(index = 1; index <= F_FEATURE_LIST_COUNT; index++)
3829 if(((1 << index) & old_growth_bits) && F_OFF(index, ps))
3830 return(0);
3832 return(1);
3834 else
3835 return((1 << index) & old_growth_bits);
3840 * Side effect is that the appropriate global variable is set, and the
3841 * appropriate current_val is set.
3843 void
3844 cur_rule_value(struct variable *var, int expand, int cmdline)
3846 int i;
3847 NAMEVAL_S *v;
3849 set_current_val(var, expand, cmdline);
3851 if(var == &ps_global->vars[V_SAVED_MSG_NAME_RULE]){
3852 if(ps_global->VAR_SAVED_MSG_NAME_RULE)
3853 for(i = 0; (v = save_msg_rules(i)); i++)
3854 if(!strucmp(ps_global->VAR_SAVED_MSG_NAME_RULE, S_OR_L(v))){
3855 ps_global->save_msg_rule = v->value;
3856 break;
3859 #ifndef _WINDOWS
3860 else if(var == &ps_global->vars[V_COLOR_STYLE]){
3861 if(ps_global->VAR_COLOR_STYLE)
3862 for(i = 0; (v = col_style(i)); i++)
3863 if(!strucmp(ps_global->VAR_COLOR_STYLE, S_OR_L(v))){
3864 ps_global->color_style = v->value;
3865 break;
3868 #endif
3869 else if(var == &ps_global->vars[V_INDEX_COLOR_STYLE]){
3870 if(ps_global->VAR_INDEX_COLOR_STYLE)
3871 for(i = 0; (v = index_col_style(i)); i++)
3872 if(!strucmp(ps_global->VAR_INDEX_COLOR_STYLE, S_OR_L(v))){
3873 ps_global->index_color_style = v->value;
3874 break;
3877 else if(var == &ps_global->vars[V_TITLEBAR_COLOR_STYLE]){
3878 if(ps_global->VAR_TITLEBAR_COLOR_STYLE)
3879 for(i = 0; (v = titlebar_col_style(i)); i++)
3880 if(!strucmp(ps_global->VAR_TITLEBAR_COLOR_STYLE, S_OR_L(v))){
3881 ps_global->titlebar_color_style = v->value;
3882 break;
3885 else if(var == &ps_global->vars[V_FCC_RULE]){
3886 if(ps_global->VAR_FCC_RULE)
3887 for(i = 0; (v = fcc_rules(i)); i++)
3888 if(!strucmp(ps_global->VAR_FCC_RULE, S_OR_L(v))){
3889 ps_global->fcc_rule = v->value;
3890 break;
3893 else if(var == &ps_global->vars[V_GOTO_DEFAULT_RULE]){
3894 if(ps_global->VAR_GOTO_DEFAULT_RULE)
3895 for(i = 0; (v = goto_rules(i)); i++)
3896 if(!strucmp(ps_global->VAR_GOTO_DEFAULT_RULE, S_OR_L(v))){
3897 ps_global->goto_default_rule = v->value;
3898 break;
3901 else if(var == &ps_global->vars[V_INCOMING_STARTUP]){
3902 if(ps_global->VAR_INCOMING_STARTUP)
3903 for(i = 0; (v = incoming_startup_rules(i)); i++)
3904 if(!strucmp(ps_global->VAR_INCOMING_STARTUP, S_OR_L(v))){
3905 ps_global->inc_startup_rule = v->value;
3906 break;
3909 else if(var == &ps_global->vars[V_PRUNING_RULE]){
3910 if(ps_global->VAR_PRUNING_RULE)
3911 for(i = 0; (v = pruning_rules(i)); i++)
3912 if(!strucmp(ps_global->VAR_PRUNING_RULE, S_OR_L(v))){
3913 ps_global->pruning_rule = v->value;
3914 break;
3917 else if(var == &ps_global->vars[V_REOPEN_RULE]){
3918 if(ps_global->VAR_REOPEN_RULE)
3919 for(i = 0; (v = reopen_rules(i)); i++)
3920 if(!strucmp(ps_global->VAR_REOPEN_RULE, S_OR_L(v))){
3921 ps_global->reopen_rule = v->value;
3922 break;
3925 else if(var == &ps_global->vars[V_FLD_SORT_RULE]){
3926 if(ps_global->VAR_FLD_SORT_RULE)
3927 for(i = 0; (v = fld_sort_rules(i)); i++)
3928 if(!strucmp(ps_global->VAR_FLD_SORT_RULE, S_OR_L(v))){
3929 ps_global->fld_sort_rule = v->value;
3930 break;
3933 else if(var == &ps_global->vars[V_AB_SORT_RULE]){
3934 if(ps_global->VAR_AB_SORT_RULE)
3935 for(i = 0; (v = ab_sort_rules(i)); i++)
3936 if(!strucmp(ps_global->VAR_AB_SORT_RULE, S_OR_L(v))){
3937 ps_global->ab_sort_rule = v->value;
3938 break;
3941 else if(var == &ps_global->vars[V_THREAD_DISP_STYLE]){
3942 if(ps_global->VAR_THREAD_DISP_STYLE)
3943 for(i = 0; (v = thread_disp_styles(i)); i++)
3944 if(!strucmp(ps_global->VAR_THREAD_DISP_STYLE, S_OR_L(v))){
3945 ps_global->thread_disp_style = v->value;
3946 break;
3949 else if(var == &ps_global->vars[V_THREAD_INDEX_STYLE]){
3950 if(ps_global->VAR_THREAD_INDEX_STYLE)
3951 for(i = 0; (v = thread_index_styles(i)); i++)
3952 if(!strucmp(ps_global->VAR_THREAD_INDEX_STYLE, S_OR_L(v))){
3953 ps_global->thread_index_style = v->value;
3954 break;
3961 * Standard way to get at save message rules...
3963 NAMEVAL_S *
3964 save_msg_rules(int index)
3966 static NAMEVAL_S save_rules[] = {
3967 {"by-from", NULL, SAV_RULE_FROM},
3968 {"by-nick-of-from", NULL, SAV_RULE_NICK_FROM_DEF},
3969 {"by-nick-of-from-then-from", NULL, SAV_RULE_NICK_FROM},
3970 {"by-fcc-of-from", NULL, SAV_RULE_FCC_FROM_DEF},
3971 {"by-fcc-of-from-then-from", NULL, SAV_RULE_FCC_FROM},
3972 {"by-realname-of-from", NULL, SAV_RULE_RN_FROM_DEF},
3973 {"by-realname-of-from-then-from", NULL, SAV_RULE_RN_FROM},
3974 {"by-sender", NULL, SAV_RULE_SENDER},
3975 {"by-nick-of-sender", NULL, SAV_RULE_NICK_SENDER_DEF},
3976 {"by-nick-of-sender-then-sender", NULL, SAV_RULE_NICK_SENDER},
3977 {"by-fcc-of-sender", NULL, SAV_RULE_FCC_SENDER_DEF},
3978 {"by-fcc-of-sender-then-sender", NULL, SAV_RULE_FCC_SENDER},
3979 {"by-realname-of-sender", NULL, SAV_RULE_RN_SENDER_DEF},
3980 {"by-realname-of-sender-then-sender", NULL, SAV_RULE_RN_SENDER},
3981 {"by-recipient", NULL, SAV_RULE_RECIP},
3982 {"by-nick-of-recip", NULL, SAV_RULE_NICK_RECIP_DEF},
3983 {"by-nick-of-recip-then-recip", NULL, SAV_RULE_NICK_RECIP},
3984 {"by-fcc-of-recip", NULL, SAV_RULE_FCC_RECIP_DEF},
3985 {"by-fcc-of-recip-then-recip", NULL, SAV_RULE_FCC_RECIP},
3986 {"by-realname-of-recip", NULL, SAV_RULE_RN_RECIP_DEF},
3987 {"by-realname-of-recip-then-recip", NULL, SAV_RULE_RN_RECIP},
3988 {"by-replyto", NULL, SAV_RULE_REPLYTO},
3989 {"by-nick-of-replyto", NULL, SAV_RULE_NICK_REPLYTO_DEF},
3990 {"by-nick-of-replyto-then-replyto", NULL, SAV_RULE_NICK_REPLYTO},
3991 {"by-fcc-of-replyto", NULL, SAV_RULE_FCC_REPLYTO_DEF},
3992 {"by-fcc-of-replyto-then-replyto", NULL, SAV_RULE_FCC_REPLYTO},
3993 {"by-realname-of-replyto", NULL, SAV_RULE_RN_REPLYTO_DEF},
3994 {"by-realname-of-replyto-then-replyto", NULL, SAV_RULE_RN_REPLYTO},
3995 {"last-folder-used", NULL, SAV_RULE_LAST},
3996 {"default-folder", NULL, SAV_RULE_DEFLT}
3999 return((index >= 0 && index < (sizeof(save_rules)/sizeof(save_rules[0])))
4000 ? &save_rules[index] : NULL);
4005 * Standard way to get at fcc rules...
4007 NAMEVAL_S *
4008 fcc_rules(int index)
4010 static NAMEVAL_S f_rules[] = {
4011 {"default-fcc", NULL, FCC_RULE_DEFLT},
4012 {"last-fcc-used", NULL, FCC_RULE_LAST},
4013 {"by-recipient", NULL, FCC_RULE_RECIP},
4014 {"by-nickname", NULL, FCC_RULE_NICK},
4015 {"by-nick-then-recip", NULL, FCC_RULE_NICK_RECIP},
4016 {"current-folder", NULL, FCC_RULE_CURRENT}
4019 return((index >= 0 && index < (sizeof(f_rules)/sizeof(f_rules[0])))
4020 ? &f_rules[index] : NULL);
4025 * Standard way to get at addrbook sort rules...
4027 NAMEVAL_S *
4028 ab_sort_rules(int index)
4030 static NAMEVAL_S ab_rules[] = {
4031 {"fullname-with-lists-last", NULL, AB_SORT_RULE_FULL_LISTS},
4032 {"fullname", NULL, AB_SORT_RULE_FULL},
4033 {"nickname-with-lists-last", NULL, AB_SORT_RULE_NICK_LISTS},
4034 {"nickname", NULL, AB_SORT_RULE_NICK},
4035 {"dont-sort", NULL, AB_SORT_RULE_NONE}
4038 return((index >= 0 && index < (sizeof(ab_rules)/sizeof(ab_rules[0])))
4039 ? &ab_rules[index] : NULL);
4044 * Standard way to get at color styles.
4046 NAMEVAL_S *
4047 col_style(int index)
4049 static NAMEVAL_S col_styles[] = {
4050 {"no-color", NULL, COL_NONE},
4051 {"use-termdef", NULL, COL_TERMDEF},
4052 {"force-ansi-8color", NULL, COL_ANSI8},
4053 {"force-ansi-16color", NULL, COL_ANSI16},
4054 {"force-xterm-256color", NULL, COL_ANSI256}
4057 return((index >= 0 && index < (sizeof(col_styles)/sizeof(col_styles[0])))
4058 ? &col_styles[index] : NULL);
4063 * Standard way to get at index color styles.
4065 NAMEVAL_S *
4066 index_col_style(int index)
4068 static NAMEVAL_S ind_col_styles[] = {
4069 {"flip-colors", NULL, IND_COL_FLIP},
4070 {"reverse", NULL, IND_COL_REV},
4071 {"reverse-fg", NULL, IND_COL_FG},
4072 {"reverse-fg-no-ambiguity", NULL, IND_COL_FG_NOAMBIG},
4073 {"reverse-bg", NULL, IND_COL_BG},
4074 {"reverse-bg-no-ambiguity", NULL, IND_COL_BG_NOAMBIG}
4077 return((index >= 0 && index < (sizeof(ind_col_styles)/sizeof(ind_col_styles[0]))) ? &ind_col_styles[index] : NULL);
4082 * Standard way to get at titlebar color styles.
4084 NAMEVAL_S *
4085 titlebar_col_style(int index)
4087 static NAMEVAL_S tbar_col_styles[] = {
4088 {"default", NULL, TBAR_COLOR_DEFAULT},
4089 {"indexline", NULL, TBAR_COLOR_INDEXLINE},
4090 {"reverse-indexline", NULL, TBAR_COLOR_REV_INDEXLINE}
4093 return((index >= 0 && index < (sizeof(tbar_col_styles)/sizeof(tbar_col_styles[0]))) ? &tbar_col_styles[index] : NULL);
4098 * Standard way to get at folder sort rules...
4100 NAMEVAL_S *
4101 fld_sort_rules(int index)
4103 static NAMEVAL_S fdl_rules[] = {
4104 {"alphabetical", NULL, FLD_SORT_ALPHA},
4105 {"alpha-with-dirs-last", NULL, FLD_SORT_ALPHA_DIR_LAST},
4106 {"alpha-with-dirs-first", NULL, FLD_SORT_ALPHA_DIR_FIRST}
4109 return((index >= 0 && index < (sizeof(fdl_rules)/sizeof(fdl_rules[0])))
4110 ? &fdl_rules[index] : NULL);
4115 * Standard way to get at incoming startup rules...
4117 NAMEVAL_S *
4118 incoming_startup_rules(int index)
4120 static NAMEVAL_S is_rules[] = {
4121 {"first-unseen", NULL, IS_FIRST_UNSEEN},
4122 {"first-recent", NULL, IS_FIRST_RECENT},
4123 {"first-important", NULL, IS_FIRST_IMPORTANT},
4124 {"first-important-or-unseen", NULL, IS_FIRST_IMPORTANT_OR_UNSEEN},
4125 {"first-important-or-recent", NULL, IS_FIRST_IMPORTANT_OR_RECENT},
4126 {"first", NULL, IS_FIRST},
4127 {"last", NULL, IS_LAST}
4130 return((index >= 0 && index < (sizeof(is_rules)/sizeof(is_rules[0])))
4131 ? &is_rules[index] : NULL);
4135 NAMEVAL_S *
4136 startup_rules(int index)
4138 static NAMEVAL_S is2_rules[] = {
4139 {"first-unseen", NULL, IS_FIRST_UNSEEN},
4140 {"first-recent", NULL, IS_FIRST_RECENT},
4141 {"first-important", NULL, IS_FIRST_IMPORTANT},
4142 {"first-important-or-unseen", NULL, IS_FIRST_IMPORTANT_OR_UNSEEN},
4143 {"first-important-or-recent", NULL, IS_FIRST_IMPORTANT_OR_RECENT},
4144 {"first", NULL, IS_FIRST},
4145 {"last", NULL, IS_LAST},
4146 {"default", NULL, IS_NOTSET}
4149 return((index >= 0 && index < (sizeof(is2_rules)/sizeof(is2_rules[0])))
4150 ? &is2_rules[index] : NULL);
4155 * Standard way to get at pruning-rule values.
4157 NAMEVAL_S *
4158 pruning_rules(int index)
4160 static NAMEVAL_S pr_rules[] = {
4161 {"ask about rename, ask about deleting","ask-ask", PRUNE_ASK_AND_ASK},
4162 {"ask about rename, don't delete", "ask-no", PRUNE_ASK_AND_NO},
4163 {"always rename, ask about deleting", "yes-ask", PRUNE_YES_AND_ASK},
4164 {"always rename, don't delete", "yes-no", PRUNE_YES_AND_NO},
4165 {"don't rename, ask about deleting", "no-ask", PRUNE_NO_AND_ASK},
4166 {"don't rename, don't delete", "no-no", PRUNE_NO_AND_NO}
4169 return((index >= 0 && index < (sizeof(pr_rules)/sizeof(pr_rules[0])))
4170 ? &pr_rules[index] : NULL);
4175 * Standard way to get at reopen-rule values.
4177 NAMEVAL_S *
4178 reopen_rules(int index)
4180 static NAMEVAL_S ro_rules[] = {
4181 /* TRANSLATORS: short description of a feature option */
4182 {"Always reopen", "yes-yes",
4183 REOPEN_YES_YES},
4184 /* TRANSLATORS: short description of a feature option, default in brackets */
4185 {"Yes for POP/NNTP, Ask about other remote [Yes]", "yes-ask-y",
4186 REOPEN_YES_ASK_Y},
4187 /* TRANSLATORS: short description of a feature option, default in brackets */
4188 {"Yes for POP/NNTP, Ask about other remote [No]", "yes-ask-n",
4189 REOPEN_YES_ASK_N},
4190 /* TRANSLATORS: short description of a feature option */
4191 {"Yes for POP/NNTP, No for other remote", "yes-no",
4192 REOPEN_YES_NO},
4193 /* TRANSLATORS: short description of a feature option, default in brackets */
4194 {"Always ask [Yes]", "ask-ask-y",
4195 REOPEN_ASK_ASK_Y},
4196 /* TRANSLATORS: short description of a feature option, default in brackets */
4197 {"Always ask [No]", "ask-ask-n",
4198 REOPEN_ASK_ASK_N},
4199 /* TRANSLATORS: short description of a feature option, default in brackets */
4200 {"Ask about POP/NNTP [Yes], No for other remote", "ask-no-y",
4201 REOPEN_ASK_NO_Y},
4202 /* TRANSLATORS: short description of a feature option, default in brackets */
4203 {"Ask about POP/NNTP [No], No for other remote", "ask-no-n",
4204 REOPEN_ASK_NO_N},
4205 /* TRANSLATORS: short description of a feature option */
4206 {"Never reopen", "no-no",
4207 REOPEN_NO_NO},
4210 return((index >= 0 && index < (sizeof(ro_rules)/sizeof(ro_rules[0])))
4211 ? &ro_rules[index] : NULL);
4216 * Standard way to get at thread_disp_style values.
4218 NAMEVAL_S *
4219 thread_disp_styles(int index)
4221 static NAMEVAL_S td_styles[] = {
4222 {"none", "none", THREAD_NONE},
4223 {"show-thread-structure", "struct", THREAD_STRUCT},
4224 {"mutt-like", "mutt", THREAD_MUTTLIKE},
4225 {"indent-subject-1", "subj1", THREAD_INDENT_SUBJ1},
4226 {"indent-subject-2", "subj2", THREAD_INDENT_SUBJ2},
4227 {"indent-from-1", "from1", THREAD_INDENT_FROM1},
4228 {"indent-from-2", "from2", THREAD_INDENT_FROM2},
4229 {"show-structure-in-from", "struct-from", THREAD_STRUCT_FROM}
4232 return((index >= 0 && index < (sizeof(td_styles)/sizeof(td_styles[0])))
4233 ? &td_styles[index] : NULL);
4238 * Standard way to get at thread_index_style values.
4240 NAMEVAL_S *
4241 thread_index_styles(int index)
4243 static NAMEVAL_S ti_styles[] = {
4244 {"regular-index-with-expanded-threads", "exp", THRDINDX_EXP},
4245 {"regular-index-with-collapsed-threads","coll", THRDINDX_COLL},
4246 {"separate-index-screen-always", "sep", THRDINDX_SEP},
4247 {"separate-index-screen-except-for-single-messages","sep-auto",
4248 THRDINDX_SEP_AUTO}
4251 return((index >= 0 && index < (sizeof(ti_styles)/sizeof(ti_styles[0])))
4252 ? &ti_styles[index] : NULL);
4257 * Standard way to get at goto default rules...
4259 NAMEVAL_S *
4260 goto_rules(int index)
4262 static NAMEVAL_S g_rules[] = {
4263 {"folder-in-first-collection", NULL, GOTO_FIRST_CLCTN},
4264 {"inbox-or-folder-in-first-collection", NULL, GOTO_INBOX_FIRST_CLCTN},
4265 {"inbox-or-folder-in-recent-collection", NULL, GOTO_INBOX_RECENT_CLCTN},
4266 {"first-collection-with-inbox-default", NULL, GOTO_FIRST_CLCTN_DEF_INBOX},
4267 {"most-recent-folder", NULL, GOTO_LAST_FLDR}
4270 return((index >= 0 && index < (sizeof(g_rules)/sizeof(g_rules[0])))
4271 ? &g_rules[index] : NULL);
4275 NAMEVAL_S *
4276 pat_fldr_types(int index)
4278 static NAMEVAL_S pat_fldr_list[] = {
4279 {"Any", "ANY", FLDR_ANY},
4280 {"News", "NEWS", FLDR_NEWS},
4281 {"Email", "EMAIL", FLDR_EMAIL},
4282 {"Specific (Enter Incoming Nicknames or use ^T)", "SPEC", FLDR_SPECIFIC}
4285 return((index >= 0 &&
4286 index < (sizeof(pat_fldr_list)/sizeof(pat_fldr_list[0])))
4287 ? &pat_fldr_list[index] : NULL);
4291 NAMEVAL_S *
4292 inabook_fldr_types(int indexarg)
4294 static NAMEVAL_S inabook_fldr_list[] = {
4295 {"Don't care, always matches", "E", IAB_EITHER},
4296 {"Yes, in any address book", "YES", IAB_YES},
4297 {"No, not in any address book", "NO", IAB_NO},
4298 {"Yes, in specific address books", "SYES", IAB_SPEC_YES},
4299 {"No, not in any of specific address books", "SNO", IAB_SPEC_NO}
4302 int index = indexarg & IAB_TYPE_MASK;
4304 return((index >= 0 &&
4305 index < (sizeof(inabook_fldr_list)/sizeof(inabook_fldr_list[0])))
4306 ? &inabook_fldr_list[index] : NULL);
4310 NAMEVAL_S *
4311 filter_types(int index)
4313 static NAMEVAL_S filter_type_list[] = {
4314 {"Just Set Message Status", "NONE", FILTER_STATE},
4315 {"Delete", "DEL", FILTER_KILL},
4316 {"Move (Enter folder name(s) in primary collection, or use ^T)",
4317 "FLDR", FILTER_FOLDER}
4320 return((index >= 0 &&
4321 index < (sizeof(filter_type_list)/sizeof(filter_type_list[0])))
4322 ? &filter_type_list[index] : NULL);
4326 NAMEVAL_S *
4327 role_repl_types(int index)
4329 static NAMEVAL_S role_repl_list[] = {
4330 {"Never", "NO", ROLE_REPL_NO},
4331 {"With confirmation", "YES", ROLE_REPL_YES},
4332 {"Without confirmation", "NC", ROLE_REPL_NOCONF}
4335 return((index >= 0 &&
4336 index < (sizeof(role_repl_list)/sizeof(role_repl_list[0])))
4337 ? &role_repl_list[index] : NULL);
4341 NAMEVAL_S *
4342 role_forw_types(int index)
4344 static NAMEVAL_S role_forw_list[] = {
4345 {"Never", "NO", ROLE_FORW_NO},
4346 {"With confirmation", "YES", ROLE_FORW_YES},
4347 {"Without confirmation", "NC", ROLE_FORW_NOCONF}
4350 return((index >= 0 &&
4351 index < (sizeof(role_forw_list)/sizeof(role_forw_list[0])))
4352 ? &role_forw_list[index] : NULL);
4356 NAMEVAL_S *
4357 role_comp_types(int index)
4359 static NAMEVAL_S role_comp_list[] = {
4360 {"Never", "NO", ROLE_COMP_NO},
4361 {"With confirmation", "YES", ROLE_COMP_YES},
4362 {"Without confirmation", "NC", ROLE_COMP_NOCONF}
4365 return((index >= 0 &&
4366 index < (sizeof(role_comp_list)/sizeof(role_comp_list[0])))
4367 ? &role_comp_list[index] : NULL);
4371 NAMEVAL_S *
4372 role_status_types(int index)
4374 static NAMEVAL_S role_status_list[] = {
4375 {"Don't care, always matches", "E", PAT_STAT_EITHER},
4376 {"Yes", "YES", PAT_STAT_YES},
4377 {"No", "NO", PAT_STAT_NO}
4380 return((index >= 0 &&
4381 index < (sizeof(role_status_list)/sizeof(role_status_list[0])))
4382 ? &role_status_list[index] : NULL);
4386 NAMEVAL_S *
4387 msg_state_types(int index)
4389 static NAMEVAL_S msg_state_list[] = {
4390 {"Don't change it", "LV", ACT_STAT_LEAVE},
4391 {"Set this state", "SET", ACT_STAT_SET},
4392 {"Clear this state", "CLR", ACT_STAT_CLEAR}
4395 return((index >= 0 &&
4396 index < (sizeof(msg_state_list)/sizeof(msg_state_list[0])))
4397 ? &msg_state_list[index] : NULL);
4401 #ifdef ENABLE_LDAP
4402 NAMEVAL_S *
4403 ldap_search_rules(int index)
4405 static NAMEVAL_S ldap_search_list[] = {
4406 {"contains", NULL, LDAP_SRCH_CONTAINS},
4407 {"equals", NULL, LDAP_SRCH_EQUALS},
4408 {"begins-with", NULL, LDAP_SRCH_BEGINS},
4409 {"ends-with", NULL, LDAP_SRCH_ENDS}
4412 return((index >= 0 &&
4413 index < (sizeof(ldap_search_list)/sizeof(ldap_search_list[0])))
4414 ? &ldap_search_list[index] : NULL);
4418 NAMEVAL_S *
4419 ldap_search_types(int index)
4421 static NAMEVAL_S ldap_types_list[] = {
4422 {"name", NULL, LDAP_TYPE_CN},
4423 {"surname", NULL, LDAP_TYPE_SUR},
4424 {"givenname", NULL, LDAP_TYPE_GIVEN},
4425 {"email", NULL, LDAP_TYPE_EMAIL},
4426 {"name-or-email", NULL, LDAP_TYPE_CN_EMAIL},
4427 {"surname-or-givenname", NULL, LDAP_TYPE_SUR_GIVEN},
4428 {"sur-or-given-or-name-or-email", NULL, LDAP_TYPE_SEVERAL}
4431 return((index >= 0 &&
4432 index < (sizeof(ldap_types_list)/sizeof(ldap_types_list[0])))
4433 ? &ldap_types_list[index] : NULL);
4437 NAMEVAL_S *
4438 ldap_search_scope(int index)
4440 static NAMEVAL_S ldap_scope_list[] = {
4441 {"base", NULL, LDAP_SCOPE_BASE},
4442 {"onelevel", NULL, LDAP_SCOPE_ONELEVEL},
4443 {"subtree", NULL, LDAP_SCOPE_SUBTREE}
4446 return((index >= 0 &&
4447 index < (sizeof(ldap_scope_list)/sizeof(ldap_scope_list[0])))
4448 ? &ldap_scope_list[index] : NULL);
4450 #endif
4454 * Choose from the global default, command line args, pinerc values to set
4455 * the actual value of the variable that we will use. Start at the top
4456 * and work down from higher to lower precedence.
4457 * For lists, we may inherit values from lower precedence
4458 * versions if that's the way the user specifies it.
4459 * The user can put INHERIT_DEFAULT as the first entry in a list and that
4460 * means it will inherit the current values, for example the values
4461 * from the global_val, or the value from the main_user_val could be
4462 * inherited in the post_user_val.
4464 void
4465 set_current_val(struct variable *var, int expand, int cmdline)
4467 int is_set[5], is_inherit[5];
4468 int i, j, k, cnt, start;
4469 char **tmp, **t, **list[5];
4470 char *p;
4472 dprint((9,
4473 "set_current_val(var=%s%s, expand=%d, cmdline=%d)\n",
4474 (var && var->name) ? var->name : "?",
4475 (var && var->is_list) ? " (list)" : "",
4476 expand, cmdline));
4478 if(!var)
4479 return;
4481 if(var->is_list){ /* variable is a list */
4483 for(j = 0; j < 5; j++){
4484 t = j==0 ? var->global_val.l :
4485 j==1 ? var->main_user_val.l :
4486 j==2 ? var->post_user_val.l :
4487 j==3 ? ((cmdline) ? var->cmdline_val.l : NULL) :
4488 var->fixed_val.l;
4490 is_set[j] = is_inherit[j] = 0;
4491 list[j] = NULL;
4493 if(t){
4494 if(!expand){
4495 is_set[j]++;
4496 list[j] = t;
4498 else{
4499 for(i = 0; t[i]; i++){
4500 if(expand_variables(tmp_20k_buf, SIZEOF_20KBUF, t[i],
4501 0)){
4502 /* successful expand */
4503 is_set[j]++;
4504 list[j] = t;
4505 break;
4510 if(list[j] && list[j][0] && !strcmp(list[j][0],INHERIT))
4511 is_inherit[j]++;
4515 cnt = 0;
4516 start = 0;
4517 /* count how many items in current_val list */
4518 /* Admin wants default, which is global_val. */
4519 if(var->is_fixed && var->fixed_val.l == NULL){
4520 cnt = 0;
4521 if(is_set[0]){
4522 for(; list[0][cnt]; cnt++)
4526 else{
4527 for(j = 0; j < 5; j++){
4528 if(is_set[j]){
4529 if(!is_inherit[j]){
4530 cnt = 0; /* reset */
4531 start = j;
4534 for(i = is_inherit[j] ? 1 : 0; list[j][i]; i++)
4535 cnt++;
4540 free_list_array(&var->current_val.l); /* clean up any old values */
4542 /* check to see if anything is set */
4543 if(is_set[0] + is_set[1] + is_set[2] + is_set[3] + is_set[4] > 0){
4544 var->current_val.l = (char **)fs_get((cnt+1)*sizeof(char *));
4545 tmp = var->current_val.l;
4546 if(var->is_fixed && var->fixed_val.l == NULL){
4547 if(is_set[0]){
4548 for(i = 0; list[0][i]; i++){
4549 if(!expand)
4550 *tmp++ = cpystr(list[0][i]);
4551 else if(expand_variables(tmp_20k_buf, SIZEOF_20KBUF,
4552 list[0][i], 0))
4553 *tmp++ = cpystr(tmp_20k_buf);
4557 else{
4558 for(j = start; j < 5; j++){
4559 if(is_set[j]){
4560 for(i = is_inherit[j] ? 1 : 0; list[j][i]; i++){
4561 if(!expand)
4562 *tmp++ = cpystr(list[j][i]);
4563 else if(expand_variables(tmp_20k_buf,SIZEOF_20KBUF,
4564 list[j][i], 0))
4565 *tmp++ = cpystr(tmp_20k_buf);
4571 *tmp = NULL;
4573 else
4574 var->current_val.l = NULL;
4576 else{ /* variable is not a list */
4577 char *strvar = NULL;
4579 for(j = 0; j < 5; j++){
4581 p = j==0 ? var->fixed_val.p :
4582 j==1 ? ((cmdline) ? var->cmdline_val.p : NULL) :
4583 j==2 ? var->post_user_val.p :
4584 j==3 ? var->main_user_val.p :
4585 var->global_val.p;
4587 is_set[j] = 0;
4589 if(p){
4590 if(!expand){
4591 is_set[j]++;
4592 if(!strvar)
4593 strvar = p;
4595 else if(expand_variables(tmp_20k_buf, SIZEOF_20KBUF, p,
4596 (var == &ps_global->vars[V_MAILCAP_PATH] ||
4597 var == &ps_global->vars[V_MIMETYPE_PATH]))){
4598 is_set[j]++;
4599 if(!strvar)
4600 strvar = p;
4605 /* Admin wants default, which is global_val. */
4606 if(var->is_fixed && var->fixed_val.p == NULL)
4607 strvar = var->global_val.p;
4609 if(var->current_val.p) /* free previous value */
4610 fs_give((void **)&var->current_val.p);
4612 if(strvar){
4613 if(!expand)
4614 var->current_val.p = cpystr(strvar);
4615 else{
4616 expand_variables(tmp_20k_buf, SIZEOF_20KBUF, strvar,
4617 (var == &ps_global->vars[V_MAILCAP_PATH] ||
4618 var == &ps_global->vars[V_MIMETYPE_PATH]));
4619 var->current_val.p = cpystr(tmp_20k_buf);
4622 else
4623 var->current_val.p = NULL;
4626 if(var->is_fixed && !is_inherit[4]){
4627 char **flist;
4628 int fixed_len, user_len;
4631 * sys mgr fixed this variable and user is trying to change it
4633 for(k = 1; !(ps_global->give_fixed_warning &&
4634 ps_global->fix_fixed_warning) && k <= 3; k++){
4635 if(is_set[k]){
4636 if(var->is_list){
4637 t = k==1 ? ((cmdline) ? var->cmdline_val.l : NULL) :
4638 k==2 ? var->post_user_val.l :
4639 var->main_user_val.l;
4641 /* If same length and same contents, don't warn. */
4642 for(flist=var->fixed_val.l; flist && *flist; flist++)
4643 ;/* just counting */
4645 fixed_len = var->fixed_val.l ? (flist - var->fixed_val.l)
4646 : 0;
4647 for(flist=t; flist && *flist; flist++)
4648 ;/* just counting */
4650 user_len = t ? (flist - t) : 0;
4651 if(user_len == fixed_len){
4652 for(i=0; i < user_len; i++){
4653 for(j=0; j < user_len; j++)
4654 if(!strucmp(t[i], var->fixed_val.l[j]))
4655 break;
4657 if(j == user_len){
4658 ps_global->give_fixed_warning = 1;
4659 if(k != 1)
4660 ps_global->fix_fixed_warning = 1;
4662 break;
4666 else{
4667 ps_global->give_fixed_warning = 1;
4668 if(k != 1)
4669 ps_global->fix_fixed_warning = 1;
4672 else{
4673 p = k==1 ? ((cmdline) ? var->cmdline_val.p : NULL) :
4674 k==2 ? var->post_user_val.p :
4675 var->main_user_val.p;
4677 if((var->fixed_val.p && !p) ||
4678 (!var->fixed_val.p && p) ||
4679 (var->fixed_val.p && p && strucmp(var->fixed_val.p, p))){
4680 ps_global->give_fixed_warning = 1;
4681 if(k != 1)
4682 ps_global->fix_fixed_warning = 1;
4691 void
4692 set_news_spec_current_val(int expand, int cmdline)
4694 struct variable *newsvar = &ps_global->vars[V_NEWS_SPEC];
4695 struct variable *fvar = &ps_global->vars[V_FOLDER_SPEC];
4697 /* check to see if it has a value */
4698 set_current_val(newsvar, expand, cmdline);
4701 * If no value, we might want to fake a value. We'll do that if
4702 * there is no news collection already defined in FOLDER_SPEC and if
4703 * there is also an NNTP_SERVER defined.
4705 if(!newsvar->current_val.l && ps_global->VAR_NNTP_SERVER &&
4706 ps_global->VAR_NNTP_SERVER[0] && ps_global->VAR_NNTP_SERVER[0][0] &&
4707 !news_in_folders(fvar)){
4708 char buf[MAXPATH];
4710 newsvar->global_val.l = (char **)fs_get(2 * sizeof(char *));
4711 snprintf(buf, sizeof(buf), "{%.*s/nntp}#news.[]", MAXPATH-20,
4712 ps_global->VAR_NNTP_SERVER[0]); /* MAXPATH = sizeof(buf) */
4713 newsvar->global_val.l[0] = cpystr(buf);
4714 newsvar->global_val.l[1] = NULL;
4715 set_current_val(newsvar, expand, cmdline);
4717 * But we're going to get rid of the fake global_val in case
4718 * things change.
4720 free_list_array(&newsvar->global_val.l);
4726 * Feature-list has to be handled separately from the other variables
4727 * because it is additive. The other variables choose one of command line,
4728 * or pine.conf, or pinerc. Feature list adds them. This could easily be
4729 * converted to a general purpose routine if we add more additive variables.
4731 * This works by replacing earlier values with later ones. That is, command
4732 * line settings have higher precedence than global settings and that is
4733 * accomplished by putting the command line features after the global
4734 * features in the list. When they are processed, the last one wins.
4736 * Feature-list also has a backwards compatibility hack.
4738 void
4739 set_feature_list_current_val(struct variable *var)
4741 char **list;
4742 char **list_fixed;
4743 char no_allow[50];
4744 int i, j, k, m,
4745 elems = 0;
4747 /* count the lists so we can allocate */
4748 for(m = 0; m < 6; m++){
4749 list = m==0 ? var->global_val.l :
4750 m==1 ? var->main_user_val.l :
4751 m==2 ? var->post_user_val.l :
4752 m==3 ? ps_global->feat_list_back_compat :
4753 m==4 ? var->cmdline_val.l :
4754 var->fixed_val.l;
4755 if(list)
4756 for(i = 0; list[i]; i++)
4757 elems++;
4760 list_fixed = var->fixed_val.l;
4762 if(var->current_val.l)
4763 free_list_array(&var->current_val.l);
4765 var->current_val.l = (char **)fs_get((elems+1) * sizeof(char *));
4768 * We need to warn the user if the sys mgr has restricted him or her
4769 * from changing a feature that he or she is trying to change.
4771 * We're not catching the old-growth macro since we're just comparing
4772 * strings. That is, it works correctly, but the user won't be warned
4773 * if the user old-growth and the mgr says no-quit-without-confirm.
4776 j = 0;
4777 strncpy(no_allow, "no-", 3);
4778 strncpy(no_allow+3, feature_list_name(F_ALLOW_CHANGING_FROM), sizeof(no_allow)-3-1);
4779 no_allow[sizeof(no_allow)-1] = '\0';
4781 for(m = 0; m < 6; m++){
4782 list = m==0 ? var->global_val.l :
4783 m==1 ? var->main_user_val.l :
4784 m==2 ? var->post_user_val.l :
4785 m==3 ? ps_global->feat_list_back_compat :
4786 m==4 ? var->cmdline_val.l :
4787 var->fixed_val.l;
4788 if(list)
4789 for(i = 0; list[i]; i++){
4790 var->current_val.l[j++] = cpystr(list[i]);
4792 /* this is the warning section */
4793 if(m >= 1 && m <= 4){
4794 for(k = 0; list_fixed && list_fixed[k]; k++){
4795 char *p, *q;
4796 p = list[i];
4797 q = list_fixed[k];
4798 if(!struncmp(p, "no-", 3))
4799 p += 3;
4800 if(!struncmp(q, "no-", 3))
4801 q += 3;
4802 if(!strucmp(q, p) && strucmp(list[i], list_fixed[k])){
4803 ps_global->give_fixed_warning = 1;
4804 if(m <= 2)
4805 ps_global->fix_fixed_warning = 1;
4809 else if(m == 5 && !strucmp(list[i], no_allow))
4810 ps_global->never_allow_changing_from = 1;
4814 #ifdef NEVER_ALLOW_CHANGING_FROM
4815 ps_global->never_allow_changing_from = 1;
4816 #endif
4818 var->current_val.l[j] = NULL;
4823 /*----------------------------------------------------------------------
4825 Expand Metacharacters/variables in file-names
4827 Read input line and expand shell-variables/meta-characters
4829 <input> <replaced by>
4830 $variable getenv("variable")
4831 ${variable} getenv("variable")
4832 ${variable:-defvalue} is getenv("variable") if variable is defined and
4833 is defvalue otherwise
4834 ~ getenv("HOME")
4835 \c c
4836 <others> <just copied>
4838 NOTE handling of braces in ${name} doesn't check much or do error recovery
4840 If colon_path is set, then we expand ~ not only at the start of linein,
4841 but also after each : in the path.
4843 ----*/
4844 #define is_allowed_envchar(C, S) ((S) == 0 ? !isspace((C)) && (C) != '/'\
4845 : (((C) >= 'a' && (C) <= 'z') \
4846 || ((C) >= 'A' && (C) <= 'Z') \
4847 || ((C) >= '0' && (C) <= '9')))
4849 char *
4850 expand_variables(char *lineout, size_t lineoutlen, char *linein, int colon_path)
4852 char *src = linein, *dest = lineout, *p;
4853 char *limit = lineout + lineoutlen;
4854 int envexpand = 0, sp;
4856 if(!linein)
4857 return(NULL);
4859 sp = strncmp(src,"LIT:pattern=\"/NICK=", strlen("LIT:pattern=\"/NICK=")) == 0;
4860 while(*src ){ /* something in input string */
4861 if(*src == '$' && *(src+1) == '$'){
4863 * $$ to escape chars we're interested in, else
4864 * it's up to the user of the variable to handle the
4865 * backslash...
4867 if(dest < limit)
4868 *dest++ = *++src; /* copy next as is */
4869 }else
4870 #if !(defined(DOS) || defined(OS2))
4871 if(*src == '\\' && *(src+1) == '$'){
4873 * backslash to escape chars we're interested in, else
4874 * it's up to the user of the variable to handle the
4875 * backslash...
4877 if(dest < limit)
4878 *dest++ = *++src; /* copy next as is */
4879 }else if(*src == '~' &&
4880 (src == linein || (colon_path && *(src-1) == ':'))){
4881 char buf[MAXPATH];
4882 int i;
4884 for(i = 0; i < sizeof(buf)-1 && src[i] && src[i] != '/'; i++)
4885 buf[i] = src[i];
4887 src += i; /* advance src pointer */
4888 buf[i] = '\0'; /* tie off buf string */
4889 fnexpand(buf, sizeof(buf)); /* expand the path */
4891 for(p = buf; dest < limit && (*dest = *p); p++, dest++)
4894 continue;
4895 }else
4896 #endif
4897 if(*src == '$'){ /* shell variable */
4898 char word[128+1], *colon = NULL, *rbrace = NULL;
4900 envexpand++; /* signal that we've expanded a var */
4901 src++; /* skip dollar */
4902 if(*src == '{'){ /* starts with brace? */
4903 src++;
4904 rbrace = strindex(src, '}');
4905 if(rbrace){
4906 /* look for default value */
4907 colon = strstr(src, ":-");
4908 if(colon && (rbrace < colon))
4909 colon = NULL;
4913 p = word;
4915 /* put the env variable to be looked up in word */
4916 if(rbrace){
4917 while(*src
4918 && (p-word < sizeof(word)-1)
4919 && ((colon && src < colon) || (!colon && src < rbrace))){
4920 if(isspace((unsigned char) *src)){
4922 * Illegal input. This should be an error of some
4923 * sort but instead of that we'll just backup to the
4924 * $ and treat it like it wasn't there.
4926 while(*src != '$')
4927 src--;
4929 envexpand--;
4930 goto just_copy;
4932 else
4933 *p++ = *src++;
4936 /* adjust src for next char */
4937 src = rbrace + 1;
4939 else{
4940 while(*src && is_allowed_envchar((unsigned char) *src, sp)
4941 && (p-word < sizeof(word)-1))
4942 *p++ = *src++;
4945 *p = '\0';
4947 if((p = getenv(word)) != NULL){ /* check for word in environment */
4948 while(*p && dest < limit)
4949 *dest++ = *p++;
4951 else if(colon){ /* else possible default value */
4952 p = colon + 2;
4953 while(*p && p < rbrace && dest < limit)
4954 *dest++ = *p++;
4957 continue;
4958 }else{ /* other cases: just copy */
4959 just_copy:
4960 if(dest < limit)
4961 *dest++ = *src;
4964 if(*src) /* next character (if any) */
4965 src++;
4968 if(dest < limit)
4969 *dest = '\0';
4970 else
4971 lineout[lineoutlen-1] = '\0';
4973 return((envexpand && lineout[0] == '\0') ? NULL : lineout);
4977 /*----------------------------------------------------------------------
4978 Sets login, full_username and home_dir
4980 Args: ps -- The Pine structure to put the user name, etc in
4982 Result: sets the fullname, login and home_dir field of the pine structure
4983 returns 0 on success, -1 if not.
4984 ----*/
4985 #define MAX_INIT_ERRS 10
4986 void
4987 init_error(struct pine *ps, int flags, int min_time, int max_time, char *message)
4989 int i;
4991 if(!ps->init_errs){
4992 ps->init_errs = (INIT_ERR_S *)fs_get((MAX_INIT_ERRS + 1) *
4993 sizeof(*ps->init_errs));
4994 memset(ps->init_errs, 0, (MAX_INIT_ERRS + 1) * sizeof(*ps->init_errs));
4997 for(i = 0; i < MAX_INIT_ERRS; i++)
4998 if(!(ps->init_errs)[i].message){
4999 (ps->init_errs)[i].message = cpystr(message);
5000 (ps->init_errs)[i].min_time = min_time;
5001 (ps->init_errs)[i].max_time = max_time;
5002 (ps->init_errs)[i].flags = flags;
5003 dprint((2, "%s\n", message ? message : "?"));
5004 break;
5009 /*----------------------------------------------------------------------
5010 Read and parse a pinerc file
5012 Args: Filename -- name of the .pinerc file to open and read
5013 vars -- The vars structure to store values in
5014 which_vars -- Whether the local or global values are being read
5016 Result:
5018 This may be the local file or the global file. The values found are
5019 merged with the values currently in vars. All values are strings and
5020 are malloced; and existing values will be freed before the assignment.
5021 Those that are <unset> will be left unset; their values will be NULL.
5022 ----*/
5023 void
5024 read_pinerc(PINERC_S *prc, struct variable *vars, ParsePinerc which_vars)
5026 char *filename, *file, *value, **lvalue, *line, *error;
5027 char *p, *p1, *free_file = NULL;
5028 struct variable *v;
5029 PINERC_LINE *pline = NULL;
5030 int line_count, was_quoted;
5031 int i;
5033 if(!prc)
5034 return;
5036 dprint((2, "reading_pinerc \"%s\"\n",
5037 prc->name ? prc->name : "?"));
5039 if(prc->type == Loc){
5040 filename = prc->name ? prc->name : "";
5041 file = free_file = read_file(filename, 0);
5044 * This is questionable. In case the user edits the pinerc
5045 * in Windows and adds a UTF-8 BOM, we skip it here. If the
5046 * user adds a Unicode BOM we're in trouble. We could write it
5047 * with the BOM ourselves but so far we leave it BOMless in
5048 * order that it's the same on Unix and Windows.
5050 if(BOM_UTF8(file))
5051 file += 3;
5053 else{
5054 if((file = read_remote_pinerc(prc, which_vars)) != NULL)
5055 ps_global->c_client_error[0] = '\0';
5057 free_file = file;
5060 if(file == NULL || *file == '\0'){
5061 #ifdef DEBUG
5062 if(file == NULL){
5063 dprint((2, "Open failed: %s\n", error_description(errno)));
5065 else{
5066 if(prc->type == Loc){
5067 dprint((1, "Read_pinerc: empty pinerc (new?)\n"));
5069 else{
5070 dprint((1, "Read_pinerc: new remote pinerc\n"));
5073 #endif /* DEBUG */
5075 if(which_vars == ParsePers){
5076 /* problems getting remote config */
5077 if(file == NULL && prc->type == RemImap){
5078 if(!pith_opt_remote_pinerc_failure
5079 || !(*pith_opt_remote_pinerc_failure)())
5080 exceptional_exit(_("Unable to read or write remote configuration"), -1);
5083 ps_global->first_time_user = 1;
5084 prc->outstanding_pinerc_changes = 1;
5087 return;
5089 else{
5090 if(prc->type == Loc &&
5091 (which_vars == ParseFixed || which_vars == ParseGlobal ||
5092 (can_access(filename, ACCESS_EXISTS) == 0 &&
5093 can_access(filename, EDIT_ACCESS) != 0))){
5094 prc->readonly = 1;
5095 if(prc == ps_global->prc)
5096 ps_global->readonly_pinerc = 1;
5100 * accept CRLF or LF newlines
5102 for(p = file; *p && *p != '\012'; p++)
5105 if(p > file && *p && *(p-1) == '\015') /* cvt crlf to lf */
5106 for(p1 = p - 1; (*p1 = *p) != '\0'; p++)
5107 if(!(*p == '\015' && *(p+1) == '\012'))
5108 p1++;
5111 dprint((2, "Read %d characters:\n", strlen(file)));
5113 if(which_vars == ParsePers || which_vars == ParsePersPost){
5114 /*--- Count up lines and allocate structures */
5115 for(line_count = 0, p = file; *p != '\0'; p++)
5116 if(*p == '\n')
5117 line_count++;
5119 prc->pinerc_lines = (PINERC_LINE *)
5120 fs_get((3 + line_count) * sizeof(PINERC_LINE));
5121 memset((void *)prc->pinerc_lines, 0,
5122 (3 + line_count) * sizeof(PINERC_LINE));
5123 pline = prc->pinerc_lines;
5126 for(p = file, line = file; *p != '\0';){
5127 /*----- Grab the line ----*/
5128 line = p;
5129 while(*p && *p != '\n')
5130 p++;
5131 if(*p == '\n'){
5132 *p++ = '\0';
5135 /*----- Comment Line -----*/
5136 if(*line == '#'){
5137 /* no comments in remote pinercs */
5138 if(pline && prc->type == Loc){
5139 pline->is_var = 0;
5140 pline->line = cpystr(line);
5141 pline++;
5143 continue;
5146 if(*line == '\0' || *line == '\t' || *line == ' '){
5147 p1 = line;
5148 while(*p1 == '\t' || *p1 == ' ')
5149 p1++;
5150 if(pline){
5152 * This could be a continuation line from some future
5153 * version of pine, or it could be a continuation line
5154 * from a PC-Pine variable we don't know about in unix.
5156 if(*p1 != '\0')
5157 pline->line = cpystr(line);
5158 else
5159 pline->line = cpystr("");
5160 pline->is_var = 0;
5161 pline++;
5163 continue;
5166 /*----- look up matching 'v' and leave "value" after '=' ----*/
5167 for(v = vars; *line && v->name; v++)
5168 if((i = strlen(v->name)) < strlen(line) && !struncmp(v->name,line,i)){
5169 int j;
5171 for(j = i; line[j] == ' ' || line[j] == '\t'; j++)
5174 if(line[j] == '='){ /* bingo! */
5175 for(value = &line[j+1];
5176 *value == ' ' || *value == '\t';
5177 value++)
5180 break;
5182 /* else either unrecognized var or bogus line */
5185 /*----- Didn't match any variable or bogus format -----*/
5187 * This could be a variable from some future
5188 * version of pine, or it could be a PC-Pine variable
5189 * we don't know about in unix. Either way, we want to preserve
5190 * it in the file.
5192 if(!v->name){
5193 if(pline){
5194 pline->is_var = 0;
5195 pline->line = cpystr(line);
5196 pline++;
5198 continue;
5202 * Previous versions have caused duplicate pinerc data to be
5203 * written to pinerc files. This clause erases the duplicate
5204 * information when we read it, and it will be removed from the file
5205 * if we call write_pinerc. We test to see if the same variable
5206 * appears later in the file, if so, we skip over it here.
5207 * We don't care about duplicates if this isn't a pinerc we might
5208 * write out, so include pline in the conditional.
5209 * Note that we will leave all of the duplicate comments and blank
5210 * lines in the file unless it is a remote pinerc. Luckily, the
5211 * bug that caused the duplicates only applied to remote pinercs,
5212 * so we should have that case covered.
5214 * If we find a duplicate, we point p to the start
5215 * of the next line that should be considered, and then skip back
5216 * to the top of the loop.
5218 if(pline && var_is_in_rest_of_file(v->name, p)){
5219 if(v->is_list)
5220 p = skip_over_this_var(line, p);
5222 continue;
5226 /*----- Obsolete variable, read it anyway below, might use it -----*/
5227 if(v->is_obsolete){
5228 if(pline){
5229 pline->obsolete_var = 1;
5230 pline->line = cpystr(line);
5231 pline->var = v;
5235 /*----- Variable is in the list but unused for some reason -----*/
5236 if(!v->is_used){
5237 if(pline){
5238 pline->is_var = 0;
5239 pline->line = cpystr(line);
5240 pline++;
5242 continue;
5245 /*--- Var is not user controlled, leave it alone for back compat ---*/
5246 if(!v->is_user && pline){
5247 pline->is_var = 0;
5248 pline->line = cpystr(line);
5249 pline++;
5250 continue;
5253 if(which_vars == ParseFixed)
5254 v->is_fixed = 1;
5256 /*---- variable is unset, or it's global but expands to nothing ----*/
5257 if(!*value
5258 || (which_vars == ParseGlobal
5259 && !expand_variables(tmp_20k_buf, SIZEOF_20KBUF, value,
5260 (v == &ps_global->vars[V_MAILCAP_PATH] ||
5261 v == &ps_global->vars[V_MIMETYPE_PATH])))){
5262 if(v->is_user && pline){
5263 pline->is_var = 1;
5264 pline->var = v;
5265 pline++;
5267 continue;
5270 /*--value is non-empty, store it handling quotes and trailing space--*/
5271 if(*value == '"' && !v->is_list && v->del_quotes){
5272 was_quoted = 1;
5273 value++;
5274 for(p1 = value; *p1 && *p1 != '"'; p1++);
5275 if(*p1 == '"')
5276 *p1 = '\0';
5277 else
5278 removing_trailing_white_space(value);
5279 }else
5280 was_quoted = 0;
5283 * List Entry Parsing
5285 * The idea is to parse a comma separated list of
5286 * elements, preserving quotes, and understanding
5287 * continuation lines (that is ',' == "\n ").
5288 * Quotes must be balanced within elements. Space
5289 * within elements is preserved, but leading and trailing
5290 * space is trimmed. This is a generic function, and it's
5291 * left to the the functions that use the lists to make sure
5292 * they contain valid data...
5294 if(v->is_list){
5296 was_quoted = 0;
5297 line_count = 0;
5298 p1 = value;
5299 while(1){ /* generous count of list elements */
5300 if(*p1 == '"') /* ignore ',' if quoted */
5301 was_quoted = (was_quoted) ? 0 : 1 ;
5303 if((*p1 == ',' && !was_quoted) || *p1 == '\n' || *p1 == '\0')
5304 line_count++; /* count this element */
5306 if(*p1 == '\0' || *p1 == '\n'){ /* deal with EOL */
5307 if(p1 < p || *p1 == '\n'){
5308 *p1++ = ','; /* fix null or newline */
5310 if(*p1 != '\t' && *p1 != ' '){
5311 *(p1-1) = '\0'; /* tie off list */
5312 p = p1; /* reset p */
5313 break;
5315 }else{
5316 p = p1; /* end of pinerc */
5317 break;
5319 }else
5320 p1++;
5323 error = NULL;
5324 lvalue = parse_list(value, line_count,
5325 v->del_quotes ? PL_REMSURRQUOT : PL_NONE,
5326 &error);
5327 if(error){
5328 dprint((1,
5329 "read_pinerc: ERROR: %s in %s = \"%s\"\n",
5330 error ? error : "?",
5331 v->name ? v->name : "?",
5332 value ? value : "?"));
5335 * Special case: turn "" strings into empty strings.
5336 * This allows users to turn off default lists. For example,
5337 * if smtp-server is set then a user could override smtp-server
5338 * with smtp-server="".
5340 for(i = 0; lvalue[i]; i++)
5341 if(lvalue[i][0] == '"' &&
5342 lvalue[i][1] == '"' &&
5343 lvalue[i][2] == '\0')
5344 lvalue[i][0] = '\0';
5347 if(pline){
5348 if(v->is_user && (which_vars == ParsePers || !v->is_onlymain)){
5349 if(v->is_list){
5350 char ***l;
5352 l = (which_vars == ParsePers) ? &v->main_user_val.l
5353 : &v->post_user_val.l;
5354 free_list_array(l);
5355 *l = lvalue;
5357 else{
5358 char **p;
5360 p = (which_vars == ParsePers) ? &v->main_user_val.p
5361 : &v->post_user_val.p;
5362 if(p && *p != NULL)
5363 fs_give((void **)p);
5365 *p = cpystr(value);
5368 if(pline){
5369 pline->is_var = 1;
5370 pline->var = v;
5371 pline->is_quoted = was_quoted;
5372 pline++;
5376 else if(which_vars == ParseGlobal){
5377 if(v->is_global){
5378 if(v->is_list){
5379 free_list_array(&v->global_val.l);
5380 v->global_val.l = lvalue;
5382 else{
5383 if(v->global_val.p != NULL)
5384 fs_give((void **) &(v->global_val.p));
5386 v->global_val.p = cpystr(value);
5390 else{ /* which_vars == ParseFixed */
5391 if(v->is_user || v->is_global){
5392 if(v->is_list){
5393 free_list_array(&v->fixed_val.l);
5394 v->fixed_val.l = lvalue;
5396 else{
5397 if(v->fixed_val.p != NULL)
5398 fs_give((void **) &(v->fixed_val.p));
5400 v->fixed_val.p = cpystr(value);
5405 #ifdef DEBUG
5406 if(v->is_list){
5407 char **l;
5408 l = (which_vars == ParsePers) ? v->main_user_val.l :
5409 (which_vars == ParsePersPost) ? v->post_user_val.l :
5410 (which_vars == ParseGlobal) ? v->global_val.l :
5411 v->fixed_val.l;
5412 if(l && *l && **l){
5413 dprint((5, " %20.20s : %s\n",
5414 v->name ? v->name : "?",
5415 *l ? *l : "?"));
5416 while(++l && *l && **l)
5417 dprint((5, " %20.20s : %s\n", "",
5418 *l ? *l : "?"));
5420 }else{
5421 char *p;
5422 p = (which_vars == ParsePers) ? v->main_user_val.p :
5423 (which_vars == ParsePersPost) ? v->post_user_val.p :
5424 (which_vars == ParseGlobal) ? v->global_val.p :
5425 v->fixed_val.p;
5426 if(p && *p)
5427 dprint((5, " %20.20s : %s\n",
5428 v->name ? v->name : "?",
5429 p ? p : "?"));
5431 #endif /* DEBUG */
5434 if(pline){
5435 pline->line = NULL;
5436 pline->is_var = 0;
5437 if(!prc->pinerc_written && prc->type == Loc){
5438 prc->pinerc_written = name_file_mtime(filename);
5439 dprint((5, "read_pinerc: time_pinerc_written = %ld\n",
5440 (long) prc->pinerc_written));
5444 if(free_file)
5445 fs_give((void **) &free_file);
5450 * Args varname The variable name we're looking for
5451 * begin Begin looking here
5453 * Returns 1 if variable varname appears in the rest of the file
5454 * 0 if not
5457 var_is_in_rest_of_file(char *varname, char *begin)
5459 char *p;
5461 if(!(varname && *varname && begin && *begin))
5462 return 0;
5464 p = begin;
5466 while((p = srchstr(p, varname)) != NULL){
5467 /* beginning of a line? */
5468 if(p > begin && (*(p-1) != '\n' && *(p-1) != '\r')){
5469 p++;
5470 continue;
5473 /* followed by [ SPACE ] < = > ? */
5474 p += strlen(varname);
5475 while(*p == ' ' || *p == '\t')
5476 p++;
5478 if(*p == '=')
5479 return 1;
5482 return 0;
5487 * Args begin Variable to skip starts here.
5488 * nextline This is where the next line starts. We need to know this
5489 * because the input has been mangled a little. A \0 has
5490 * replaced the \n at the end of the first line, but we can
5491 * use nextline to help us out of that quandry.
5493 * Return a pointer to the start of the first line after this variable
5494 * and all of its continuation lines.
5496 char *
5497 skip_over_this_var(char *begin, char *nextline)
5499 char *p;
5501 p = begin;
5503 while(1){
5504 if(*p == '\0' || *p == '\n'){ /* EOL */
5505 if(p < nextline || *p == '\n'){ /* there may be another line */
5506 p++;
5507 if(*p != ' ' && *p != '\t') /* no continuation line */
5508 return(p);
5510 else /* end of file */
5511 return(p);
5513 else
5514 p++;
5519 static char quotes[3] = {'"', '"', '\0'};
5520 /*----------------------------------------------------------------------
5521 Write out the .pinerc state information
5523 Args: ps -- The pine structure to take state to be written from
5524 which -- Which pinerc to write
5525 flags -- If bit WRP_NOUSER is set, then assume that there is
5526 not a user present to answer questions.
5528 This writes to a temporary file first, and then renames that to
5529 be the new .pinerc file to protect against disk error. This has the
5530 problem of possibly messing up file protections, ownership and links.
5531 ----*/
5533 write_pinerc(struct pine *ps, EditWhich which, int flags)
5535 char *p, *dir, *tmp = NULL, *pinrc;
5536 char *pval, **lval;
5537 char *linep = NULL, *lineq = NULL;
5538 int bc = 1;
5539 int buflen;
5540 PINERC_LINE *pline;
5541 struct variable *var;
5542 time_t mtime;
5543 char *filename;
5544 REMDATA_S *rd = NULL;
5545 PINERC_S *prc = NULL;
5546 STORE_S *so = NULL;
5547 #ifndef _WINDOWS
5548 struct stat sbuf;
5549 char *slink = NULL;
5550 #endif
5552 #define MAXPLINESIZE 10000
5554 dprint((2,"---- write_pinerc(%s) ----\n",
5555 (which == Main) ? "Main" : "Post"));
5557 switch(which){
5558 case Main:
5559 prc = ps ? ps->prc : NULL;
5560 break;
5561 case Post:
5562 prc = ps ? ps->post_prc : NULL;
5563 break;
5564 default:
5565 break;
5568 if(!prc)
5569 return(-1);
5571 if(prc->quit_to_edit){
5572 if(!(flags & WRP_NOUSER))
5573 quit_to_edit_msg(prc);
5575 return(-1);
5578 if(prc->type != Loc && !prc->readonly){
5580 bc = 0; /* don't do backcompat conversion */
5581 rd = prc->rd;
5582 if(!rd)
5583 return(-1);
5585 rd_check_remvalid(rd, -10L);
5587 if(rd->flags & REM_OUTOFDATE){
5588 if((flags & WRP_NOUSER) || unexpected_pinerc_change()){
5589 prc->outstanding_pinerc_changes = 1;
5590 if(!(flags & WRP_NOUSER))
5591 q_status_message1(SM_ORDER | SM_DING, 3, 3,
5592 "Pinerc \"%.200s\" NOT saved",
5593 prc->name ? prc->name : "");
5594 dprint((2, "write_pinerc: remote pinerc changed\n"));
5595 return(-1);
5597 else
5598 rd->flags &= ~REM_OUTOFDATE;
5601 rd_open_remote(rd);
5603 if(rd->access == ReadWrite){
5604 int ro;
5606 if((ro=rd_remote_is_readonly(rd)) || rd->flags & REM_OUTOFDATE){
5607 if(ro == 1){
5608 if(!(flags & WRP_NOUSER))
5609 q_status_message(SM_ORDER | SM_DING, 5, 15,
5610 _("Can't access remote config, changes NOT saved!"));
5611 dprint((1,
5612 "write_pinerc: Can't write to remote pinerc %s, aborting write\n",
5613 rd->rn ? rd->rn : "?"));
5615 else if(ro == 2){
5616 if(!(rd->flags & NO_META_UPDATE)){
5617 unsigned long save_chk_nmsgs;
5619 switch(rd->type){
5620 case RemImap:
5621 save_chk_nmsgs = rd->t.i.chk_nmsgs;
5622 rd->t.i.chk_nmsgs = 0;
5623 rd_write_metadata(rd, 0);
5624 rd->t.i.chk_nmsgs = save_chk_nmsgs;
5625 break;
5627 default:
5628 q_status_message(SM_ORDER | SM_DING, 3, 5,
5629 "Write_pinerc: Type not supported");
5630 break;
5634 if(!(flags & WRP_NOUSER))
5635 q_status_message1(SM_ORDER | SM_DING, 5, 15,
5636 _("No write permission for remote config %.200s, changes NOT saved!"),
5637 rd->rn);
5639 else{
5640 if(!(flags & WRP_NOUSER))
5641 q_status_message(SM_ORDER | SM_DING, 5, 15,
5642 _("Remote config changed, aborting our change to avoid damage..."));
5643 dprint((1,
5644 "write_pinerc: remote config %s changed since we started pine, aborting write\n",
5645 prc->name ? prc->name : "?"));
5648 rd->flags &= ~DO_REMTRIM;
5649 return(-1);
5652 filename = rd->lf;
5654 else{
5655 prc->readonly = 1;
5656 if(prc == ps->prc)
5657 ps->readonly_pinerc = 1;
5660 else
5661 filename = prc->name ? prc->name : "";
5663 pinrc = prc->name ? prc->name : "";
5665 if(prc->type == Loc){
5666 mtime = name_file_mtime(filename);
5667 if(prc->pinerc_written
5668 && prc->pinerc_written != mtime
5669 && ((flags & WRP_NOUSER) || unexpected_pinerc_change())){
5670 prc->outstanding_pinerc_changes = 1;
5672 if(!(flags & WRP_NOUSER))
5673 q_status_message1(SM_ORDER | SM_DING, 3, 3,
5674 "Pinerc \"%.200s\" NOT saved", pinrc);
5676 dprint((2,"write_pinerc: mtime mismatch: \"%s\": %ld != %ld\n",
5677 filename ? filename : "?",
5678 (long) prc->pinerc_written, (long) mtime));
5679 return(-1);
5683 /* don't write if pinerc is read-only */
5684 if(prc->readonly ||
5685 (filename &&
5686 can_access(filename, ACCESS_EXISTS) == 0 &&
5687 can_access(filename, EDIT_ACCESS) != 0)){
5688 prc->readonly = 1;
5689 if(prc == ps->prc)
5690 ps->readonly_pinerc = 1;
5692 if(!(flags & WRP_NOUSER))
5693 q_status_message1(SM_ORDER | SM_DING, 0, 5,
5694 _("Can't modify configuration file \"%.200s\": ReadOnly"),
5695 pinrc);
5696 dprint((2, "write_pinerc: fail because can't access pinerc\n"));
5698 if(rd)
5699 rd->flags &= ~DO_REMTRIM;
5701 return(-1);
5704 if(rd && rd->flags & NO_FILE){
5705 so = rd->sonofile;
5706 so_truncate(rd->sonofile, 0L); /* reset storage object */
5708 else{
5709 dir = ".";
5710 if((p = last_cmpnt(filename)) != NULL){
5711 *--p = '\0';
5712 dir = filename;
5715 #if defined(DOS) || defined(OS2)
5716 if(!(isalpha((unsigned char)dir[0]) && dir[1] == ':' && dir[2] == '\0')
5717 && (can_access(dir, EDIT_ACCESS) < 0 &&
5718 our_mkdir(dir, 0700) < 0))
5720 if(!(flags & WRP_NOUSER))
5721 q_status_message2(SM_ORDER | SM_DING, 3, 5,
5722 /* TRANSLATORS: first argument is a filename, second
5723 arg is the text of the error message */
5724 _("Error creating \"%.200s\" : %.200s"), dir,
5725 error_description(errno));
5726 if(rd)
5727 rd->flags &= ~DO_REMTRIM;
5729 return(-1);
5732 tmp = temp_nam(dir, "rc");
5734 if(*dir && tmp && !in_dir(dir, tmp)){
5735 our_unlink(tmp);
5736 fs_give((void **)&tmp);
5739 if(p)
5740 *p = '\\';
5742 if(tmp == NULL)
5743 goto io_err;
5745 #else /* !DOS */
5746 tmp = temp_nam((*dir) ? dir : "/", "pinerc");
5749 * If temp_nam can't write in dir it puts the temp file in a
5750 * temp directory, which won't help us when we go to rename.
5752 if(*dir && tmp && !in_dir(dir, tmp)){
5753 our_unlink(tmp);
5754 fs_give((void **)&tmp);
5757 if(p)
5758 *p = '/';
5760 if(tmp == NULL)
5761 goto io_err;
5763 #endif /* !DOS */
5765 if((so = so_get(FileStar, tmp, WRITE_ACCESS)) == NULL)
5766 goto io_err;
5769 if(!(flags & WRP_PRESERV_WRITTEN))
5770 for(var = ps->vars; var->name != NULL; var++)
5771 var->been_written = 0;
5773 if(prc->type == Loc && ps->first_time_user &&
5774 !so_puts(so, native_nl(cf_text_comment)))
5775 goto io_err;
5777 linep = fs_get((MAXPLINESIZE+1)*sizeof(char));
5778 lineq = fs_get((MAXPLINESIZE+1)*sizeof(char));
5779 buflen = MAXPLINESIZE;
5781 /* Write out what was in the .pinerc */
5782 for(pline = prc->pinerc_lines;
5783 pline && (pline->is_var || pline->line); pline++){
5784 if(pline->is_var){
5785 var = pline->var;
5787 if(var->is_list)
5788 lval = LVAL(var, which);
5789 else
5790 pval = PVAL(var, which);
5792 /* variable is not set */
5793 if((var->is_list && (!lval || !lval[0])) ||
5794 (!var->is_list && !pval)){
5795 /* leave null variables out of remote pinerc */
5796 if(prc->type == Loc &&
5797 (!so_puts(so, var->name) || !so_puts(so, "=") ||
5798 !so_puts(so, NEWLINE)))
5799 goto io_err;
5801 /* var is set to empty string */
5802 else if((var->is_list && lval[0][0] == '\0') ||
5803 (!var->is_list && pval[0] == '\0')){
5804 if(!so_puts(so, var->name) || !so_puts(so, "=") ||
5805 !so_puts(so, quotes) || !so_puts(so, NEWLINE))
5806 goto io_err;
5808 else{
5809 if(var->is_list){
5810 int i = 0;
5812 for(i = 0; lval[i]; i++){
5813 if(strlen(var->name)
5814 + (lval[i][0] ? strlen(lval[i]) : 5) > buflen){
5815 buflen = strlen(var->name)
5816 + (lval[i][0] ? strlen(lval[i]) : 5);
5817 fs_resize((void **)&linep, (buflen+1)*sizeof(char));
5818 fs_resize((void **)&lineq, (buflen+1)*sizeof(char));
5820 snprintf(linep, buflen+1, "%s%s%s%s%s",
5821 (i) ? "\t" : var->name,
5822 (i) ? "" : "=",
5823 lval[i][0] ? lval[i] : quotes,
5824 lval[i+1] ? "," : "", NEWLINE);
5825 linep[buflen] = '\0';
5826 if(!so_puts(so, bc ? backcompat_convert_from_utf8(&lineq, buflen+1, linep) : linep))
5827 goto io_err;
5830 else{
5831 if(strlen(var->name)
5832 + (pval[0] ? strlen(pval) : 5) > buflen){
5833 buflen = strlen(var->name)
5834 + (pval[0] ? strlen(pval) : 5);
5835 fs_resize((void **)&linep, (buflen+1)*sizeof(char));
5836 fs_resize((void **)&lineq, (buflen+1)*sizeof(char));
5838 snprintf(linep, buflen+1, "%s=%s%s%s%s",
5839 var->name,
5840 (pline->is_quoted && pval[0] != '\"')
5841 ? "\"" : "",
5842 pval,
5843 (pline->is_quoted && pval[0] != '\"')
5844 ? "\"" : "", NEWLINE);
5845 linep[buflen] = '\0';
5846 if(!so_puts(so, bc ? backcompat_convert_from_utf8(&lineq, buflen+1, linep) : linep))
5847 goto io_err;
5851 var->been_written = 1;
5853 }else{
5855 * The description text should be changed into a message
5856 * about the variable being obsolete when a variable is
5857 * moved to obsolete status. We add that message before
5858 * the variable unless it is already there. However, we
5859 * leave the variable itself in case the user runs an old
5860 * version of pine again. Note that we have read in the
5861 * value of the variable in read_pinerc and translated it
5862 * into a new variable if appropriate.
5864 if(pline->obsolete_var && prc->type == Loc){
5865 if(pline <= prc->pinerc_lines || (pline-1)->line == NULL ||
5866 strlen((pline-1)->line) < 3 ||
5867 strucmp((pline-1)->line+2, pline->var->descrip) != 0)
5868 if(!so_puts(so, "# ") ||
5869 !so_puts(so, native_nl(pline->var->descrip)) ||
5870 !so_puts(so, NEWLINE))
5871 goto io_err;
5874 /* remove comments from remote pinercs */
5875 if((prc->type == Loc ||
5876 (pline->line[0] != '#' && pline->line[0] != '\0')) &&
5877 (!so_puts(so, pline->line) || !so_puts(so, NEWLINE)))
5878 goto io_err;
5882 /* Now write out all the variables not in the .pinerc */
5883 for(var = ps->vars; var->name != NULL; var++){
5884 if(!var->is_user || var->been_written || !var->is_used ||
5885 var->is_obsolete || (var->is_onlymain && which != Main))
5886 continue;
5888 if(var->is_list)
5889 lval = LVAL(var, which);
5890 else
5891 pval = PVAL(var, which);
5894 * set description to NULL to eliminate preceding
5895 * blank and comment line.
5897 if(prc->type == Loc && var->descrip && *var->descrip &&
5898 (!so_puts(so, NEWLINE) || !so_puts(so, "# ") ||
5899 !so_puts(so, native_nl(var->descrip)) || !so_puts(so, NEWLINE)))
5900 goto io_err;
5902 /* variable is not set */
5903 /** Don't know what the global_val thing is for. SH, Mar 00 **/
5904 if((var->is_list && (!lval || (!lval[0] && !var->global_val.l))) ||
5905 (!var->is_list && !pval)){
5906 /* leave null variables out of remote pinerc */
5907 if(prc->type == Loc &&
5908 (!so_puts(so, var->name) || !so_puts(so, "=") ||
5909 !so_puts(so, NEWLINE)))
5910 goto io_err;
5912 /* var is set to empty string */
5913 else if((var->is_list && (!lval[0] || !lval[0][0]))
5914 || (!var->is_list && pval[0] == '\0')){
5915 if(!so_puts(so, var->name) || !so_puts(so, "=") ||
5916 !so_puts(so, quotes) || !so_puts(so, NEWLINE))
5917 goto io_err;
5919 else if(var->is_list){
5920 int i = 0;
5922 for(i = 0; lval[i] ; i++){
5923 if(strlen(var->name)
5924 + (lval[i][0] ? strlen(lval[i]) : 5) > buflen){
5925 buflen = strlen(var->name)
5926 + (lval[i][0] ? strlen(lval[i]) : 5);
5927 fs_resize((void **)&linep, (buflen+1)*sizeof(char));
5928 fs_resize((void **)&lineq, (buflen+1)*sizeof(char));
5930 snprintf(linep, buflen+1, "%s%s%s%s%s",
5931 (i) ? "\t" : var->name,
5932 (i) ? "" : "=",
5933 lval[i],
5934 lval[i+1] ? "," : "", NEWLINE);
5935 linep[buflen] = '\0';
5936 if(!so_puts(so, bc ? backcompat_convert_from_utf8(&lineq, buflen+1, linep) : linep))
5937 goto io_err;
5940 else{
5941 char *pconverted;
5943 if(strlen(pval) > buflen){
5944 buflen = strlen(pval) + 1;
5945 fs_resize((void **)&linep, (buflen+1)*sizeof(char));
5946 fs_resize((void **)&lineq, (buflen+1)*sizeof(char));
5948 pconverted = bc ? backcompat_convert_from_utf8(&lineq, buflen+1, pval) : pval;
5950 if(!so_puts(so, var->name) || !so_puts(so, "=") ||
5951 !so_puts(so, pconverted) || !so_puts(so, NEWLINE))
5952 goto io_err;
5956 if(!(rd && rd->flags & NO_FILE)){
5957 char *realfilename;
5958 int realfilename_malloced;
5960 if(so_give(&so)) goto io_err;
5962 #ifndef _WINDOWS
5963 if ((realfilename = realpath(filename, NULL)) != NULL)
5964 realfilename_malloced = 1;
5965 else
5966 goto io_err;
5967 #else
5968 realfilename = filename;
5969 realfilename_malloced = 0;
5970 #endif /* _WINDOWS */
5971 if(realfilename != NULL){
5972 int r;
5973 file_attrib_copy(tmp, realfilename);
5974 r = rename_file(tmp, realfilename);
5975 if(realfilename_malloced != 0)
5976 free((void *)realfilename);
5977 if(r < 0) goto io_err;
5981 if(prc->type != Loc){
5982 int e, we_cancel;
5983 char datebuf[200];
5985 datebuf[0] = '\0';
5986 we_cancel = 0;
5988 if(!(flags & WRP_NOUSER))
5989 we_cancel = busy_cue(_("Copying to remote config"), NULL, 1);
5991 if((e = rd_update_remote(rd, datebuf)) != 0){
5992 dprint((1,
5993 "write_pinerc: error copying from %s to %s\n",
5994 rd->lf ? rd->lf : "<memory>", rd->rn ? rd->rn : "?"));
5995 if(!(flags & WRP_NOUSER)){
5996 q_status_message2(SM_ORDER | SM_DING, 3, 5,
5997 _("Error copying to %.200s: %.200s"),
5998 rd->rn, error_description(errno));
6000 q_status_message(SM_ORDER | SM_DING, 5, 5,
6001 _("Copy of config to remote folder failed, changes NOT saved remotely"));
6004 else{
6005 rd_update_metadata(rd, datebuf);
6006 rd->read_status = 'W';
6007 rd_trim_remdata(&rd);
6008 rd_close_remote(rd);
6011 if(we_cancel)
6012 cancel_busy_cue(-1);
6015 prc->outstanding_pinerc_changes = 0;
6017 if(prc->type == Loc){
6018 prc->pinerc_written = name_file_mtime(filename);
6019 dprint((2, "wrote pinerc: %s: time_pinerc_written = %ld\n",
6020 pinrc ? pinrc : "?", (long) prc->pinerc_written));
6022 else{
6023 dprint((2, "wrote pinerc: %s\n", pinrc ? pinrc : "?"));
6026 if(tmp){
6027 our_unlink(tmp);
6028 fs_give((void **)&tmp);
6031 if(linep) fs_give((void **)&linep);
6032 if(lineq) fs_give((void **)&lineq);
6034 return(0);
6036 io_err:
6037 if(!(flags & WRP_NOUSER))
6038 q_status_message2(SM_ORDER | SM_DING, 3, 5,
6039 _("Error saving configuration in \"%.200s\": %.200s"),
6040 pinrc, error_description(errno));
6042 dprint((1, "Error writing %s : %s\n", pinrc ? pinrc : "?",
6043 error_description(errno)));
6044 if(rd)
6045 rd->flags &= ~DO_REMTRIM;
6046 if(tmp){
6047 our_unlink(tmp);
6048 fs_give((void **)&tmp);
6051 if(linep) fs_give((void **)&linep);
6052 if(lineq) fs_give((void **)&lineq);
6054 return(-1);
6059 * The srcstr is UTF-8. In order to help the user with
6060 * running this pine and an old pre-alpine pine on the same config
6061 * file we attempt to convert the values of the config variables
6062 * to the user's character set before writing.
6063 * parameters: char **buf. Memory of size_t buflen allocated by caller.
6065 char *
6066 backcompat_convert_from_utf8(char **buf, size_t buflen, char *srcstr)
6068 char *converted = NULL;
6069 char *p;
6070 int its_ascii = 1;
6073 for(p = srcstr; *p && its_ascii; p++)
6074 if(*p & 0x80)
6075 its_ascii = 0;
6077 /* if it is ascii, go with that */
6078 if(its_ascii){
6079 strncpy(*buf, srcstr, buflen);
6080 converted = *buf;
6081 (*buf)[buflen-1] = '\0';
6083 else{
6084 char *trythischarset = NULL;
6087 * If it is possible to translate the UTF-8
6088 * string into the user's character set then
6089 * do that. For backwards compatibility with
6090 * old pines.
6092 if(ps_global->keyboard_charmap && ps_global->keyboard_charmap[0])
6093 trythischarset = ps_global->keyboard_charmap;
6094 else if(ps_global->display_charmap && ps_global->display_charmap[0])
6095 trythischarset = ps_global->display_charmap;
6097 if(trythischarset){
6098 SIZEDTEXT src, dst;
6100 src.data = (unsigned char *) srcstr;
6101 src.size = strlen(srcstr);
6102 memset(&dst, 0, sizeof(dst));
6103 if(utf8_cstext(&src, trythischarset, &dst, 0)){
6104 if(dst.data){
6105 strncpy(*buf, (char *) dst.data, buflen);
6106 (*buf)[buflen-1] = '\0';
6107 fs_give((void **) &dst.data);
6112 if(!converted){
6113 strncpy(*buf, srcstr, buflen);
6114 (*buf)[buflen-1] = '\0';
6115 converted = *buf;
6119 return(converted);
6124 * Given a unix-style source string which may contain LFs,
6125 * convert those to CRLFs if appropriate.
6127 * Returns a pointer to the converted string. This will be a string
6128 * stored in tmp_20k_buf.
6130 * This is just used for the variable descriptions in the pinerc file. It
6131 * could certainly be fancier. It simply converts all \n to NEWLINE.
6133 char *
6134 native_nl(char *src)
6136 char *q, *p;
6138 tmp_20k_buf[0] = '\0';
6140 if(src){
6141 for(q = (char *)tmp_20k_buf; *src; src++){
6142 if(*src == '\n'){
6143 for(p = NEWLINE; *p; p++)
6144 *q++ = *p;
6146 else
6147 *q++ = *src;
6150 *q = '\0';
6153 return((char *)tmp_20k_buf);
6157 void
6158 quit_to_edit_msg(PINERC_S *prc)
6160 /* TRANSLATORS: The %s is either "Postload " or nothing. A Postload config file
6161 is a type of config file. */
6162 q_status_message1(SM_ORDER, 3, 4, _("Must quit Alpine to change %sconfig file."),
6163 (prc == ps_global->post_prc) ? "Postload " : "");
6167 /*------------------------------------------------------------
6168 Return TRUE if the given string was a feature name present in the
6169 pinerc as it was when pine was started...
6170 ----*/
6172 var_in_pinerc(char *s)
6174 PINERC_LINE *pline;
6176 for(pline = ps_global->prc ? ps_global->prc->pinerc_lines : NULL;
6177 pline && (pline->var || pline->line); pline++)
6178 if(pline->var && pline->var->name && !strucmp(s, pline->var->name))
6179 return(1);
6181 for(pline = ps_global->post_prc ? ps_global->post_prc->pinerc_lines : NULL;
6182 pline && (pline->var || pline->line); pline++)
6183 if(pline->var && pline->var->name && !strucmp(s, pline->var->name))
6184 return(1);
6186 return(0);
6190 /*------------------------------------------------------------
6191 Free resources associated with pinerc_lines data
6192 ----*/
6193 void
6194 free_pinerc_lines(PINERC_LINE **pinerc_lines)
6196 PINERC_LINE *pline;
6198 if(pinerc_lines && *pinerc_lines){
6199 for(pline = *pinerc_lines; pline->var || pline->line; pline++)
6200 if(pline->line)
6201 fs_give((void **)&pline->line);
6203 fs_give((void **)pinerc_lines);
6208 /*------------------------------------------------------------
6209 Dump out a global pine.conf on the standard output with fresh
6210 comments. Preserves variables currently set in SYSTEM_PINERC, if any.
6211 ----*/
6212 void
6213 dump_global_conf(void)
6215 FILE *f;
6216 struct variable *var;
6217 PINERC_S *prc;
6219 prc = new_pinerc_s(SYSTEM_PINERC);
6220 read_pinerc(prc, variables, ParseGlobal);
6221 if(prc)
6222 free_pinerc_s(&prc);
6224 f = stdout;
6225 if(f == NULL)
6226 goto io_err;
6228 fprintf(f, "# %s -- system wide pine configuration\n#\n",
6229 SYSTEM_PINERC);
6230 fprintf(f, "# Values here affect all pine users unless they've overridden the values\n");
6231 fprintf(f, "# in their .pinerc files. A copy of this file with current comments may\n");
6232 fprintf(f, "# be obtained by running \"pine -conf\". It will be printed to standard output.\n#\n");
6233 fprintf(f,"# For a variable to be unset its value must be null/blank. This is not the\n");
6234 fprintf(f,"# same as the value of \"empty string\", which can be used to effectively\n");
6235 fprintf(f,"# \"unset\" a variable that has a default or previously assigned value.\n");
6236 fprintf(f,"# To set a variable to the empty string its value should be \"\".\n");
6237 fprintf(f,"# Switch variables are set to either \"yes\" or \"no\", and default to \"no\".\n");
6238 fprintf(f,"# Except for feature-list items, which are additive, values set in the\n");
6239 fprintf(f,"# .pinerc file replace those in pine.conf, and those in pine.conf.fixed\n");
6240 fprintf(f,"# over-ride all others. Features can be over-ridden in .pinerc or\n");
6241 fprintf(f,"# pine.conf.fixed by pre-pending the feature name with \"no-\".\n#\n");
6242 fprintf(f,"# (These comments are automatically inserted.)\n");
6244 for(var = variables; var->name != NULL; var++){
6245 if(!var->is_global || !var->is_used || var->is_obsolete)
6246 continue;
6248 if(var->descrip && *var->descrip){
6249 if(fprintf(f, "\n# %s\n", var->descrip) == EOF)
6250 goto io_err;
6253 if(var->is_list){
6254 if(var->global_val.l == NULL){
6255 if(fprintf(f, "%s=\n", var->name) == EOF)
6256 goto io_err;
6257 }else{
6258 int i;
6260 for(i=0; var->global_val.l[i]; i++)
6261 if(fprintf(f, "%s%s%s%s\n", (i) ? "\t" : var->name,
6262 (i) ? "" : "=", var->global_val.l[i],
6263 var->global_val.l[i+1] ? ",":"") == EOF)
6264 goto io_err;
6266 }else{
6267 if(var->global_val.p == NULL){
6268 if(fprintf(f, "%s=\n", var->name) == EOF)
6269 goto io_err;
6270 }else if(strlen(var->global_val.p) == 0){
6271 if(fprintf(f, "%s=\"\"\n", var->name) == EOF)
6272 goto io_err;
6273 }else{
6274 if(fprintf(f,"%s=%s\n",var->name,var->global_val.p) == EOF)
6275 goto io_err;
6279 exit(0);
6282 io_err:
6283 fprintf(stderr, "Error writing config to stdout: %s\n",
6284 error_description(errno));
6285 exit(-1);
6289 /*------------------------------------------------------------
6290 Dump out a pinerc to filename with fresh
6291 comments. Preserves variables currently set in pinerc, if any.
6292 ----*/
6293 void
6294 dump_new_pinerc(char *filename)
6296 FILE *f;
6297 struct variable *var;
6298 char buf[MAXPATH], *p;
6299 PINERC_S *prc;
6302 p = ps_global->pinerc;
6304 #if defined(DOS) || defined(OS2)
6305 if(!ps_global->pinerc){
6306 char *p;
6308 if(p = getenv("PINERC")){
6309 ps_global->pinerc = cpystr(p);
6310 }else{
6311 char buf2[MAXPATH];
6312 build_path(buf2, ps_global->home_dir, DF_PINEDIR, sizeof(buf2));
6313 build_path(buf, buf2, SYSTEM_PINERC, sizeof(buf));
6316 p = buf;
6318 #else /* !DOS */
6319 if(!ps_global->pinerc){
6320 build_path(buf, ps_global->home_dir, ".pinerc", sizeof(buf));
6321 p = buf;
6323 #endif /* !DOS */
6325 prc = new_pinerc_s(p);
6326 read_pinerc(prc, variables, ParsePers);
6327 if(prc)
6328 free_pinerc_s(&prc);
6330 f = NULL;;
6331 if(filename[0] == '\0'){
6332 fprintf(stderr, "Missing argument to \"-pinerc\".\n");
6333 }else if(!strcmp(filename, "-")){
6334 f = stdout;
6335 }else{
6336 f = our_fopen(filename, "wb");
6339 if(f == NULL)
6340 goto io_err;
6342 if(fprintf(f, "%s", cf_text_comment) == EOF)
6343 goto io_err;
6345 for(var = variables; var->name != NULL; var++){
6346 dprint((7,"write_pinerc: %s = %s\n",
6347 var->name ? var->name : "?",
6348 var->main_user_val.p ? var->main_user_val.p : "<not set>"));
6349 if(!var->is_user || !var->is_used || var->is_obsolete)
6350 continue;
6353 * set description to NULL to eliminate preceding
6354 * blank and comment line.
6356 if(var->descrip && *var->descrip){
6357 if(fprintf(f, "\n# %s\n", var->descrip) == EOF)
6358 goto io_err;
6361 if(var->is_list){
6362 if(var->main_user_val.l == NULL){
6363 if(fprintf(f, "%s=\n", var->name) == EOF)
6364 goto io_err;
6365 }else{
6366 int i;
6368 for(i=0; var->main_user_val.l[i]; i++)
6369 if(fprintf(f, "%s%s%s%s\n", (i) ? "\t" : var->name,
6370 (i) ? "" : "=", var->main_user_val.l[i],
6371 var->main_user_val.l[i+1] ? ",":"") == EOF)
6372 goto io_err;
6374 }else{
6375 if(var->main_user_val.p == NULL){
6376 if(fprintf(f, "%s=\n", var->name) == EOF)
6377 goto io_err;
6378 }else if(strlen(var->main_user_val.p) == 0){
6379 if(fprintf(f, "%s=\"\"\n", var->name) == EOF)
6380 goto io_err;
6381 }else{
6382 if(fprintf(f,"%s=%s\n",var->name,var->main_user_val.p) == EOF)
6383 goto io_err;
6387 exit(0);
6390 io_err:
6391 snprintf(buf, sizeof(buf), "Error writing config to %s: %s\n",
6392 filename, error_description(errno));
6393 exceptional_exit(buf, -1);
6397 /*----------------------------------------------------------------------
6398 Set a user variable and save the .pinerc
6400 Args: var -- The index of the variable to set from conftype.h (V_....)
6401 value -- The string to set the value to
6403 Result: -1 is returned on failure and 0 is returned on success
6405 The vars data structure is updated and the pinerc saved.
6406 ----*/
6408 set_variable(int var, char *value, int expand, int commit, EditWhich which)
6410 struct variable *v;
6411 char **apval;
6412 PINERC_S *prc;
6414 v = &ps_global->vars[var];
6416 if(!v->is_user)
6417 panic1("Trying to set non-user variable %s", v->name);
6419 /* Override value of which, at most one of these should be set */
6420 if(v->is_onlymain)
6421 which = Main;
6422 else if(v->is_outermost)
6423 which = ps_global->ew_for_except_vars;
6425 apval = APVAL(v, which);
6427 if(!apval)
6428 return(-1);
6430 if(*apval)
6431 fs_give((void **)apval);
6433 *apval = value ? cpystr(value) : NULL;
6434 set_current_val(v, expand, FALSE);
6436 switch(which){
6437 case Main:
6438 prc = ps_global->prc;
6439 break;
6440 case Post:
6441 prc = ps_global->post_prc;
6442 break;
6443 default:
6444 break;
6447 if(prc)
6448 prc->outstanding_pinerc_changes = 1;
6450 return(commit ? write_pinerc(ps_global, which, WRP_NONE) : 0);
6454 /*----------------------------------------------------------------------
6455 Set a user variable list and save the .pinerc
6457 Args: var -- The index of the variable to set from conftype.h (V_....)
6458 lvalue -- The list to set the value to
6460 Result: -1 is returned on failure and 0 is returned on success
6462 The vars data structure is updated and if write_it, the pinerc is saved.
6463 ----*/
6465 set_variable_list(int var, char **lvalue, int write_it, EditWhich which)
6467 char ***alval;
6468 int i;
6469 struct variable *v = &ps_global->vars[var];
6470 PINERC_S *prc;
6472 if(!v->is_user || !v->is_list)
6473 panic1("BOTCH: Trying to set non-user or non-list variable %s", v->name);
6475 /* Override value of which, at most one of these should be set */
6476 if(v->is_onlymain)
6477 which = Main;
6478 else if(v->is_outermost)
6479 which = ps_global->ew_for_except_vars;
6481 alval = ALVAL(v, which);
6482 if(!alval)
6483 return(-1);
6485 if(*alval)
6486 free_list_array(alval);
6488 if(lvalue){
6489 for(i = 0; lvalue[i] ; i++) /* count elements */
6492 *alval = (char **) fs_get((i+1) * sizeof(char *));
6494 for(i = 0; lvalue[i] ; i++)
6495 (*alval)[i] = cpystr(lvalue[i]);
6497 (*alval)[i] = NULL;
6500 set_current_val(v, TRUE, FALSE);
6502 switch(which){
6503 case Main:
6504 prc = ps_global->prc;
6505 break;
6506 case Post:
6507 prc = ps_global->post_prc;
6508 break;
6509 default:
6510 break;
6513 if(prc)
6514 prc->outstanding_pinerc_changes = 1;
6516 return(write_it ? write_pinerc(ps_global, which, WRP_NONE) : 0);
6520 void
6521 set_current_color_vals(struct pine *ps)
6523 struct variable *vars = ps->vars;
6524 int later_color_is_set = 0;
6526 set_current_val(&vars[V_NORM_FORE_COLOR], TRUE, TRUE);
6527 set_current_val(&vars[V_NORM_BACK_COLOR], TRUE, TRUE);
6528 pico_nfcolor(VAR_NORM_FORE_COLOR);
6529 pico_nbcolor(VAR_NORM_BACK_COLOR);
6531 set_current_val(&vars[V_REV_FORE_COLOR], TRUE, TRUE);
6532 set_current_val(&vars[V_REV_BACK_COLOR], TRUE, TRUE);
6533 pico_rfcolor(VAR_REV_FORE_COLOR);
6534 pico_rbcolor(VAR_REV_BACK_COLOR);
6536 set_color_val(&vars[V_TITLE_FORE_COLOR], 1);
6537 set_color_val(&vars[V_TITLECLOSED_FORE_COLOR], 0);
6538 set_color_val(&vars[V_FOLDER_FORE_COLOR], 0);
6539 set_color_val(&vars[V_DIRECTORY_FORE_COLOR], 0);
6540 set_color_val(&vars[V_FOLDER_LIST_FORE_COLOR], 0);
6541 set_color_val(&vars[V_STATUS_FORE_COLOR], 1);
6542 set_color_val(&vars[V_KEYLABEL_FORE_COLOR], 1);
6543 set_color_val(&vars[V_KEYNAME_FORE_COLOR], 1);
6544 set_color_val(&vars[V_SLCTBL_FORE_COLOR], 1);
6545 set_color_val(&vars[V_METAMSG_FORE_COLOR], 1);
6546 set_color_val(&vars[V_PROMPT_FORE_COLOR], 1);
6547 set_color_val(&vars[V_HEADER_GENERAL_FORE_COLOR], 1);
6548 set_color_val(&vars[V_IND_PLUS_FORE_COLOR], 0);
6549 set_color_val(&vars[V_IND_IMP_FORE_COLOR], 0);
6550 set_color_val(&vars[V_IND_DEL_FORE_COLOR], 0);
6551 set_color_val(&vars[V_IND_HIPRI_FORE_COLOR], 0);
6552 set_color_val(&vars[V_IND_LOPRI_FORE_COLOR], 0);
6553 set_color_val(&vars[V_IND_ANS_FORE_COLOR], 0);
6554 set_color_val(&vars[V_IND_NEW_FORE_COLOR], 0);
6555 set_color_val(&vars[V_IND_REC_FORE_COLOR], 0);
6556 set_color_val(&vars[V_IND_FWD_FORE_COLOR], 0);
6557 set_color_val(&vars[V_IND_UNS_FORE_COLOR], 0);
6558 set_color_val(&vars[V_IND_ARR_FORE_COLOR], 0);
6559 set_color_val(&vars[V_IND_SUBJ_FORE_COLOR], 0);
6560 set_color_val(&vars[V_IND_FROM_FORE_COLOR], 0);
6561 set_color_val(&vars[V_IND_OP_FORE_COLOR], 0);
6562 set_color_val(&vars[V_INCUNSEEN_FORE_COLOR], 0);
6563 set_color_val(&vars[V_SIGNATURE_FORE_COLOR], 0);
6565 set_current_val(&ps->vars[V_INDEX_TOKEN_COLORS], TRUE, TRUE);
6566 set_current_val(&ps->vars[V_VIEW_HDR_COLORS], TRUE, TRUE);
6567 set_current_val(&ps->vars[V_KW_COLORS], TRUE, TRUE);
6568 set_custom_spec_colors(ps);
6571 * Set up the quoting colors. If a later color is set but not an earlier
6572 * color we set the earlier color to Normal to make it easier when
6573 * we go to use the colors. However, if the only quote colors set are
6574 * Normal that is the same as no settings, so delete them.
6576 set_color_val(&vars[V_QUOTE1_FORE_COLOR], 0);
6577 set_color_val(&vars[V_QUOTE2_FORE_COLOR], 0);
6578 set_color_val(&vars[V_QUOTE3_FORE_COLOR], 0);
6580 if((!(VAR_QUOTE3_FORE_COLOR && VAR_QUOTE3_BACK_COLOR) ||
6581 (!strucmp(VAR_QUOTE3_FORE_COLOR, VAR_NORM_FORE_COLOR) &&
6582 !strucmp(VAR_QUOTE3_BACK_COLOR, VAR_NORM_BACK_COLOR))) &&
6583 (!(VAR_QUOTE2_FORE_COLOR && VAR_QUOTE2_BACK_COLOR) ||
6584 (!strucmp(VAR_QUOTE2_FORE_COLOR, VAR_NORM_FORE_COLOR) &&
6585 !strucmp(VAR_QUOTE2_BACK_COLOR, VAR_NORM_BACK_COLOR))) &&
6586 (!(VAR_QUOTE1_FORE_COLOR && VAR_QUOTE1_BACK_COLOR) ||
6587 (!strucmp(VAR_QUOTE1_FORE_COLOR, VAR_NORM_FORE_COLOR) &&
6588 !strucmp(VAR_QUOTE1_BACK_COLOR, VAR_NORM_BACK_COLOR)))){
6590 * They are all either Normal or not set. Delete them all.
6592 if(VAR_QUOTE3_FORE_COLOR)
6593 fs_give((void **)&VAR_QUOTE3_FORE_COLOR);
6594 if(VAR_QUOTE3_BACK_COLOR)
6595 fs_give((void **)&VAR_QUOTE3_BACK_COLOR);
6596 if(VAR_QUOTE2_FORE_COLOR)
6597 fs_give((void **)&VAR_QUOTE2_FORE_COLOR);
6598 if(VAR_QUOTE2_BACK_COLOR)
6599 fs_give((void **)&VAR_QUOTE2_BACK_COLOR);
6600 if(VAR_QUOTE1_FORE_COLOR)
6601 fs_give((void **)&VAR_QUOTE1_FORE_COLOR);
6602 if(VAR_QUOTE1_BACK_COLOR)
6603 fs_give((void **)&VAR_QUOTE1_BACK_COLOR);
6605 else{ /* something is non-Normal */
6606 if(VAR_QUOTE3_FORE_COLOR && VAR_QUOTE3_BACK_COLOR)
6607 later_color_is_set++;
6609 /* if 3 is set but not 2, set 2 to Normal */
6610 if(VAR_QUOTE2_FORE_COLOR && VAR_QUOTE2_BACK_COLOR)
6611 later_color_is_set++;
6612 else if(later_color_is_set)
6613 set_color_val(&vars[V_QUOTE2_FORE_COLOR], 1);
6615 /* if 3 or 2 is set but not 1, set 1 to Normal */
6616 if(VAR_QUOTE1_FORE_COLOR && VAR_QUOTE1_BACK_COLOR)
6617 later_color_is_set++;
6618 else if(later_color_is_set)
6619 set_color_val(&vars[V_QUOTE1_FORE_COLOR], 1);
6622 #ifdef _WINDOWS
6623 if(ps->pre441){
6624 int conv_main = 0, conv_post = 0;
6626 ps->pre441 = 0;
6627 if(ps->prc && !unix_color_style_in_pinerc(ps->prc)){
6628 conv_main = convert_pc_gray_names(ps, ps->prc, Main);
6629 if(conv_main)
6630 ps->prc->outstanding_pinerc_changes = 1;
6634 if(ps->post_prc && !unix_color_style_in_pinerc(ps->post_prc)){
6635 conv_post = convert_pc_gray_names(ps, ps->post_prc, Post);
6636 if(conv_post)
6637 ps->post_prc->outstanding_pinerc_changes = 1;
6640 if(conv_main || conv_post){
6641 if(conv_main)
6642 write_pinerc(ps, Main, WRP_NONE);
6644 if(conv_post)
6645 write_pinerc(ps, Post, WRP_NONE);
6647 set_current_color_vals(ps);
6650 #endif /* _WINDOWS */
6652 pico_set_normal_color();
6657 * Set current_val for the foreground and background color vars, which
6658 * are assumed to be in order. If a set_current_val on them doesn't
6659 * produce current_vals, then use the colors from defvar to set those
6660 * current_vals.
6662 void
6663 set_color_val(struct variable *v, int use_default)
6665 set_current_val(v, TRUE, TRUE);
6666 set_current_val(v+1, TRUE, TRUE);
6668 if(!(v->current_val.p && v->current_val.p[0] &&
6669 (v+1)->current_val.p && (v+1)->current_val.p[0])){
6670 struct variable *defvar;
6672 if(v->current_val.p)
6673 fs_give((void **)&v->current_val.p);
6674 if((v+1)->current_val.p)
6675 fs_give((void **)&(v+1)->current_val.p);
6677 if(!use_default)
6678 return;
6680 if(var_defaults_to_rev(v))
6681 defvar = &ps_global->vars[V_REV_FORE_COLOR];
6682 else
6683 defvar = &ps_global->vars[V_NORM_FORE_COLOR];
6685 /* use default vars values instead */
6686 if(defvar && defvar->current_val.p && defvar->current_val.p[0] &&
6687 (defvar+1)->current_val.p && (defvar+1)->current_val.p[0]){
6688 v->current_val.p = cpystr(defvar->current_val.p);
6689 (v+1)->current_val.p = cpystr((defvar+1)->current_val.p);
6696 var_defaults_to_rev(struct variable *v)
6698 return(v == &ps_global->vars[V_REV_FORE_COLOR] ||
6699 v == &ps_global->vars[V_TITLE_FORE_COLOR] ||
6700 v == &ps_global->vars[V_STATUS_FORE_COLOR] ||
6701 v == &ps_global->vars[V_KEYNAME_FORE_COLOR] ||
6702 v == &ps_global->vars[V_PROMPT_FORE_COLOR]);
6708 * Each item in the list looks like:
6710 * /HDR=<header>/FG=<foreground color>/BG=<background color>
6712 * We separate the three pieces into an array of structures to make
6713 * it easier to deal with later.
6715 void
6716 set_custom_spec_colors(struct pine *ps)
6718 if(ps->index_token_colors)
6719 free_spec_colors(&ps->index_token_colors);
6721 ps->index_token_colors = spec_colors_from_varlist(ps->VAR_INDEX_TOKEN_COLORS, 1);
6723 if(ps->hdr_colors)
6724 free_spec_colors(&ps->hdr_colors);
6726 ps->hdr_colors = spec_colors_from_varlist(ps->VAR_VIEW_HDR_COLORS, 1);
6728 /* fit keyword colors into the same structures for code re-use */
6729 if(ps->kw_colors)
6730 free_spec_colors(&ps->kw_colors);
6732 ps->kw_colors = spec_colors_from_varlist(ps->VAR_KW_COLORS, 1);
6737 * Input is one item from config variable.
6739 * Return value must be freed by caller. The return is a single SPEC_COLOR_S,
6740 * not a list.
6742 SPEC_COLOR_S *
6743 spec_color_from_var(char *t, int already_expanded)
6745 char *p, *spec, *fg, *bg;
6746 PATTERN_S *val;
6747 SPEC_COLOR_S *new_hcolor = NULL;
6749 if(t && t[0] && !strcmp(t, INHERIT)){
6750 new_hcolor = (SPEC_COLOR_S *)fs_get(sizeof(*new_hcolor));
6751 memset((void *)new_hcolor, 0, sizeof(*new_hcolor));
6752 new_hcolor->inherit = 1;
6754 else if(t && t[0]){
6755 char tbuf[10000];
6757 if(!already_expanded){
6758 tbuf[0] = '\0';
6759 if(expand_variables(tbuf, sizeof(tbuf), t, 0))
6760 t = tbuf;
6763 spec = fg = bg = NULL;
6764 val = NULL;
6765 if((p = srchstr(t, "/HDR=")) != NULL)
6766 spec = remove_backslash_escapes(p+5);
6767 if((p = srchstr(t, "/FG=")) != NULL)
6768 fg = remove_backslash_escapes(p+4);
6769 if((p = srchstr(t, "/BG=")) != NULL)
6770 bg = remove_backslash_escapes(p+4);
6771 val = parse_pattern("VAL", t, 0);
6773 if(spec && *spec){
6774 /* remove colons */
6775 if((p = strindex(spec, ':')) != NULL)
6776 *p = '\0';
6778 new_hcolor = (SPEC_COLOR_S *)fs_get(sizeof(*new_hcolor));
6779 memset((void *)new_hcolor, 0, sizeof(*new_hcolor));
6780 new_hcolor->spec = spec;
6781 new_hcolor->fg = fg;
6782 new_hcolor->bg = bg;
6783 new_hcolor->val = val;
6785 else{
6786 if(spec)
6787 fs_give((void **)&spec);
6788 if(fg)
6789 fs_give((void **)&fg);
6790 if(bg)
6791 fs_give((void **)&bg);
6792 if(val)
6793 free_pattern(&val);
6797 return(new_hcolor);
6802 * Input is a list from config file.
6804 * Return value may be a list of SPEC_COLOR_S and must be freed by caller.
6806 SPEC_COLOR_S *
6807 spec_colors_from_varlist(char **varlist, int already_expanded)
6809 char **s, *t;
6810 SPEC_COLOR_S *new_hc = NULL;
6811 SPEC_COLOR_S *new_hcolor, **nexthc;
6813 nexthc = &new_hc;
6814 if(varlist){
6815 for(s = varlist; (t = *s) != NULL; s++){
6816 if(t[0]){
6817 new_hcolor = spec_color_from_var(t, already_expanded);
6818 if(new_hcolor){
6819 *nexthc = new_hcolor;
6820 nexthc = &new_hcolor->next;
6826 return(new_hc);
6831 * Returns allocated charstar suitable for config var for a single
6832 * SPEC_COLOR_S.
6834 char *
6835 var_from_spec_color(SPEC_COLOR_S *hc)
6837 char *ret_val = NULL;
6838 char *p, *spec = NULL, *fg = NULL, *bg = NULL, *val = NULL;
6839 size_t len;
6841 if(hc && hc->inherit)
6842 ret_val = cpystr(INHERIT);
6843 else if(hc){
6844 if(hc->spec)
6845 spec = add_viewerhdr_escapes(hc->spec);
6846 if(hc->fg)
6847 fg = add_viewerhdr_escapes(hc->fg);
6848 if(hc->bg)
6849 bg = add_viewerhdr_escapes(hc->bg);
6850 if(hc->val){
6851 p = pattern_to_string(hc->val);
6852 if(p){
6853 val = add_viewerhdr_escapes(p);
6854 fs_give((void **)&p);
6858 len = strlen("/HDR=/FG=/BG=") + strlen(spec ? spec : "") +
6859 strlen(fg ? fg : "") + strlen(bg ? bg : "") +
6860 strlen(val ? "/VAL=" : "") + strlen(val ? val : "");
6861 ret_val = (char *) fs_get(len + 1);
6862 snprintf(ret_val, len+1, "/HDR=%s/FG=%s/BG=%s%s%s",
6863 spec ? spec : "", fg ? fg : "", bg ? bg : "",
6864 val ? "/VAL=" : "", val ? val : "");
6866 if(spec)
6867 fs_give((void **)&spec);
6868 if(fg)
6869 fs_give((void **)&fg);
6870 if(bg)
6871 fs_give((void **)&bg);
6872 if(val)
6873 fs_give((void **)&val);
6876 return(ret_val);
6881 * Returns allocated charstar suitable for config var for a single
6882 * SPEC_COLOR_S.
6884 char **
6885 varlist_from_spec_colors(SPEC_COLOR_S *hcolors)
6887 SPEC_COLOR_S *hc;
6888 char **ret_val = NULL;
6889 int i;
6891 /* count how many */
6892 for(hc = hcolors, i = 0; hc; hc = hc->next, i++)
6895 ret_val = (char **)fs_get((i+1) * sizeof(*ret_val));
6896 memset((void *)ret_val, 0, (i+1) * sizeof(*ret_val));
6897 for(hc = hcolors, i = 0; hc; hc = hc->next, i++)
6898 ret_val[i] = var_from_spec_color(hc);
6900 return(ret_val);
6904 void
6905 update_posting_charset(struct pine *ps, int revert)
6907 #ifndef _WINDOWS
6908 if(F_ON(F_USE_SYSTEM_TRANS, ps)){
6909 if(!revert)
6910 q_status_message(SM_ORDER, 5, 5, _("This change has no effect because feature Use-System-Translation is on"));
6912 else{
6913 #endif /* ! _WINDOWS */
6914 if(ps->posting_charmap)
6915 fs_give((void **) &ps->posting_charmap);
6917 if(ps->VAR_POST_CHAR_SET){
6918 ps->posting_charmap = cpystr(ps->VAR_POST_CHAR_SET);
6919 if(!posting_charset_is_supported(ps->posting_charmap)){
6920 snprintf(tmp_20k_buf, SIZEOF_20KBUF,
6921 _("Posting-Character set \"%s\" is unsupported, using UTF-8"),
6922 ps->posting_charmap);
6923 q_status_message(SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
6924 fs_give((void **) &ps->posting_charmap);
6925 ps->posting_charmap = cpystr("UTF-8");
6928 else
6929 ps->posting_charmap = cpystr("UTF-8");
6930 #ifndef _WINDOWS
6932 #endif /* ! _WINDOWS */
6936 #define FIXED_COMMENT _("(fixed)")
6937 #define DEFAULT_COMMENT _("(default)")
6938 #define OVERRIDE_COMMENT _("(overridden)")
6941 feature_gets_an_x(struct pine *ps, struct variable *var, FEATURE_S *feature,
6942 char **comment, EditWhich ew)
6944 char **lval, **lvalexc, **lvalnorm;
6945 char *def = DEFAULT_COMMENT;
6946 int j, done = 0;
6947 int feature_fixed_on = 0, feature_fixed_off = 0;
6949 if(comment)
6950 *comment = NULL;
6952 lval = LVAL(var, ew);
6953 lvalexc = LVAL(var, ps->ew_for_except_vars);
6954 lvalnorm = LVAL(var, Main);
6956 /* feature value is administratively fixed */
6957 if((j = feature_in_list(var->fixed_val.l, feature->name)) != 0){
6958 if(j == 1)
6959 feature_fixed_on++;
6960 else if(j == -1)
6961 feature_fixed_off++;
6963 done++;
6964 if(comment)
6965 *comment = FIXED_COMMENT;
6969 * We have an exceptions config setting which overrides anything
6970 * we do here, in the normal config.
6972 if(!done &&
6973 ps->ew_for_except_vars != Main && ew == Main &&
6974 feature_in_list(lvalexc, feature->name)){
6975 done++;
6976 if(comment)
6977 *comment = OVERRIDE_COMMENT;
6981 * Feature is set On in default but not set here.
6983 if(!done &&
6984 !feature_in_list(lval, feature->name) &&
6985 ((feature_in_list(var->global_val.l, feature->name) == 1) ||
6986 ((ps->ew_for_except_vars != Main &&
6987 ew == ps->ew_for_except_vars &&
6988 feature_in_list(lvalnorm, feature->name) == 1)))){
6989 done = 17;
6990 if(comment)
6991 *comment = def;
6994 if(!done &&
6995 feature->defval &&
6996 !feature_in_list(lval, feature->name) &&
6997 !feature_in_list(var->global_val.l, feature->name) &&
6998 (ps->ew_for_except_vars == Main ||
6999 ew != ps->ew_for_except_vars ||
7000 !feature_in_list(lvalnorm, feature->name))){
7001 done = 17;
7002 if(comment)
7003 *comment = def;
7006 return(feature_fixed_on ||
7007 (!feature_fixed_off &&
7008 (done == 17 ||
7009 test_feature(lval, feature->name,
7010 test_old_growth_bits(ps, feature->id)))));
7015 longest_feature_comment(struct pine *ps, EditWhich ew)
7017 int lc = 0;
7019 lc = MAX(lc, utf8_width(FIXED_COMMENT));
7020 lc = MAX(lc, utf8_width(DEFAULT_COMMENT));
7021 if(ps->ew_for_except_vars != Main && ew == Main)
7022 lc = MAX(lc, utf8_width(OVERRIDE_COMMENT));
7024 return(lc);
7028 void
7029 toggle_feature(struct pine *ps, struct variable *var, FEATURE_S *f,
7030 int just_flip_value, EditWhich ew)
7032 char **vp, *p, **lval, ***alval;
7033 int og, on_before, was_set;
7034 char *err;
7035 long l;
7037 og = test_old_growth_bits(ps, f->id);
7040 * if this feature is in the fixed set, or old-growth is in the fixed
7041 * set and this feature is in the old-growth set, don't alter it...
7043 for(vp = var->fixed_val.l; vp && *vp; vp++){
7044 p = (struncmp(*vp, "no-", 3)) ? *vp : *vp + 3;
7045 if(!strucmp(p, f->name) || (og && !strucmp(p, "old-growth"))){
7046 q_status_message(SM_ORDER, 3, 3,
7047 /* TRANSLATORS: In the configuration screen, telling the user we
7048 can't change this option because the system administrator
7049 prohibits it. */
7050 _("Can't change value fixed by sys-admin."));
7051 return;
7055 on_before = F_ON(f->id, ps);
7057 lval = LVAL(var, ew);
7058 alval = ALVAL(var, ew);
7059 if(just_flip_value)
7060 was_set = test_feature(lval, f->name, og);
7061 else
7062 was_set = feature_gets_an_x(ps, var, f, NULL, ew);
7064 if(alval)
7065 set_feature(alval, f->name, !was_set);
7067 set_feature_list_current_val(var);
7068 process_feature_list(ps, var->current_val.l, 0, 0, 0);
7071 * Handle any features that need special attention here...
7073 if(on_before != F_ON(f->id, ps))
7074 switch(f->id){
7075 case F_QUOTE_ALL_FROMS :
7076 mail_parameters(NULL,SET_FROMWIDGET,F_ON(f->id,ps) ? VOIDT : NIL);
7077 break;
7079 case F_FAKE_NEW_IN_NEWS :
7080 if(IS_NEWS(ps->mail_stream))
7081 q_status_message(SM_ORDER | SM_DING, 3, 4,
7082 "news-approximates-new-status won't affect current newsgroup until next open");
7084 break;
7086 case F_COLOR_LINE_IMPORTANT :
7087 case F_DATES_TO_LOCAL :
7088 clear_index_cache(ps->mail_stream, 0);
7089 break;
7091 case F_DISABLE_INDEX_LOCALE_DATES :
7092 reset_index_format();
7093 clear_index_cache(ps->mail_stream, 0);
7094 break;
7096 case F_MARK_FOR_CC :
7097 clear_index_cache(ps->mail_stream, 0);
7098 if(THREADING() && sp_viewing_a_thread(ps->mail_stream))
7099 unview_thread(ps, ps->mail_stream, ps->msgmap);
7101 break;
7103 case F_HIDE_NNTP_PATH :
7104 mail_parameters(NULL, SET_NNTPHIDEPATH,
7105 F_ON(f->id, ps) ? VOIDT : NIL);
7106 break;
7108 case F_MAILDROPS_PRESERVE_STATE :
7109 mail_parameters(NULL, SET_SNARFPRESERVE,
7110 F_ON(f->id, ps) ? VOIDT : NIL);
7111 break;
7113 case F_DISABLE_SHARED_NAMESPACES :
7114 mail_parameters(NULL, SET_DISABLEAUTOSHAREDNS,
7115 F_ON(f->id, ps) ? VOIDT : NIL);
7116 break;
7118 case F_QUELL_LOCK_FAILURE_MSGS :
7119 mail_parameters(NULL, SET_LOCKEACCESERROR,
7120 F_ON(f->id, ps) ? VOIDT : NIL);
7121 break;
7123 case F_MULNEWSRC_HOSTNAMES_AS_TYPED :
7124 l = F_ON(f->id, ps) ? 0L : 1L;
7125 mail_parameters(NULL, SET_NEWSRCCANONHOST, (void *) l);
7126 break;
7128 case F_QUELL_INTERNAL_MSG :
7129 mail_parameters(NULL, SET_USERHASNOLIFE,
7130 F_ON(f->id, ps) ? VOIDT : NIL);
7131 break;
7133 case F_DISABLE_SETLOCALE_COLLATE :
7134 set_collation(F_OFF(F_DISABLE_SETLOCALE_COLLATE, ps), 1);
7135 break;
7137 #ifndef _WINDOWS
7138 case F_USE_SYSTEM_TRANS :
7139 err = NULL;
7140 reset_character_set_stuff(&err);
7141 if(err){
7142 q_status_message(SM_ORDER | SM_DING, 3, 4, err);
7143 fs_give((void **) &err);
7146 break;
7147 #endif /* ! _WINDOWS */
7149 case F_ENABLE_INCOMING_CHECKING :
7150 if(!on_before && F_OFF(F_ENABLE_INCOMING, ps))
7151 q_status_message(SM_ORDER, 0, 3, _("This option has no effect without Enable-Incoming-Folders"));
7153 clear_incoming_valid_bits();
7154 break;
7156 case F_INCOMING_CHECKING_TOTAL :
7157 case F_INCOMING_CHECKING_RECENT :
7158 if(!on_before && F_OFF(F_ENABLE_INCOMING_CHECKING, ps))
7159 q_status_message(SM_ORDER, 0, 3, _("This option has no effect without Enable-Incoming-Folders-Checking"));
7161 clear_incoming_valid_bits();
7162 break;
7164 case F_THREAD_SORTS_BY_ARRIVAL :
7165 clear_index_cache(ps->mail_stream, 0);
7166 refresh_sort(ps->mail_stream, sp_msgmap(ps->mail_stream), SRT_NON);
7167 break;
7169 #ifdef SMIME
7170 case F_DONT_DO_SMIME :
7171 smime_deinit();
7172 break;
7174 #ifdef APPLEKEYCHAIN
7175 case F_PUBLICCERTS_IN_KEYCHAIN :
7176 smime_deinit();
7177 break;
7178 #endif
7179 #endif
7181 default :
7182 break;
7188 * Returns 1 -- Feature is in the list and positive
7189 * 0 -- Feature is not in the list at all
7190 * -1 -- Feature is in the list and negative (no-)
7193 feature_in_list(char **l, char *f)
7195 char *p;
7196 int rv = 0, forced_off;
7198 for(; l && *l; l++){
7199 p = (forced_off = !struncmp(*l, "no-", 3)) ? *l + 3 : *l;
7200 if(!strucmp(p, f))
7201 rv = forced_off ? -1 : 1;
7204 return(rv);
7209 * test_feature - runs thru a feature list, and returns:
7210 * 1 if feature explicitly set and matches 'v'
7211 * 0 if feature not explicitly set *or* doesn't match 'v'
7214 test_feature(char **l, char *f, int g)
7216 char *p;
7217 int rv = 0, forced_off;
7219 for(; l && *l; l++){
7220 p = (forced_off = !struncmp(*l, "no-", 3)) ? *l + 3 : *l;
7221 if(!strucmp(p, f))
7222 rv = !forced_off;
7223 else if(g && !strucmp(p, "old-growth"))
7224 rv = !forced_off;
7227 return(rv);
7231 void
7232 set_feature(char ***l, char *f, int v)
7234 char **list = l ? *l : NULL, newval[256];
7235 int count = 0;
7237 snprintf(newval, sizeof(newval), "%s%s", v ? "" : "no-", f);
7238 for(; list && *list; list++, count++)
7239 if((**list == '\0') /* anything can replace an empty value */
7240 || !strucmp(((!struncmp(*list, "no-", 3)) ? *list + 3 : *list), f)){
7241 fs_give((void **)list); /* replace with new value */
7242 *list = cpystr(newval);
7243 return;
7247 * if we got here, we didn't find it in the list, so grow the list
7248 * and add it..
7250 if(!*l)
7251 *l = (char **)fs_get((count + 2) * sizeof(char *));
7252 else
7253 fs_resize((void **)l, (count + 2) * sizeof(char *));
7255 (*l)[count] = cpystr(newval);
7256 (*l)[count + 1] = NULL;
7261 reset_character_set_stuff(char **err)
7263 int use_system = 0;
7264 char buf[1000];
7266 if(err)
7267 *err = NULL;
7269 if(ps_global->display_charmap)
7270 fs_give((void **) &ps_global->display_charmap);
7272 if(ps_global->keyboard_charmap)
7273 fs_give((void **) &ps_global->keyboard_charmap);
7275 if(ps_global->posting_charmap)
7276 fs_give((void **) &ps_global->posting_charmap);
7278 #ifdef _WINDOWS
7279 ps_global->display_charmap = cpystr("UTF-8");
7280 #else /* UNIX */
7281 if(ps_global->VAR_CHAR_SET)
7282 ps_global->display_charmap = cpystr(ps_global->VAR_CHAR_SET);
7283 else{
7284 #if HAVE_LANGINFO_H && defined(CODESET)
7285 ps_global->display_charmap = cpystr(nl_langinfo_codeset_wrapper());
7286 #else
7287 ps_global->display_charmap = cpystr("UTF-8");
7288 #endif
7290 #endif /* UNIX */
7292 if(!ps_global->display_charmap)
7293 ps_global->display_charmap = cpystr("US-ASCII");
7295 #ifdef _WINDOWS
7296 ps_global->keyboard_charmap = cpystr("UTF-8");
7297 #else /* UNIX */
7298 if(ps_global->VAR_KEY_CHAR_SET)
7299 ps_global->keyboard_charmap = cpystr(ps_global->VAR_KEY_CHAR_SET);
7300 else
7301 ps_global->keyboard_charmap = cpystr(ps_global->display_charmap);
7303 if(!ps_global->keyboard_charmap)
7304 ps_global->keyboard_charmap = cpystr("US-ASCII");
7306 if(F_ON(F_USE_SYSTEM_TRANS, ps_global)){
7307 #if PREREQ_FOR_SYS_TRANSLATION
7308 use_system++;
7309 /* This modifies its arguments */
7310 if(setup_for_input_output(use_system, &ps_global->display_charmap,
7311 &ps_global->keyboard_charmap,
7312 &ps_global->input_cs, (err && *err) ? NULL : err) == -1)
7313 return -1;
7314 #endif
7316 #endif /* UNIX */
7318 if(!use_system){
7319 if(setup_for_input_output(use_system, &ps_global->display_charmap,
7320 &ps_global->keyboard_charmap,
7321 &ps_global->input_cs, (err && *err) ? NULL : err) == -1)
7322 return -1;
7325 if(!use_system && ps_global->VAR_POST_CHAR_SET){
7326 ps_global->posting_charmap = cpystr(ps_global->VAR_POST_CHAR_SET);
7327 if(!posting_charset_is_supported(ps_global->posting_charmap)){
7328 if(err && !*err){
7329 snprintf(buf, sizeof(buf),
7330 _("Posting-Character-Set \"%s\" is unsupported, using UTF-8"),
7331 ps_global->posting_charmap);
7332 *err = cpystr(buf);
7335 fs_give((void **) &ps_global->posting_charmap);
7336 ps_global->posting_charmap = cpystr("UTF-8");
7339 else{
7340 if(use_system && ps_global->VAR_POST_CHAR_SET
7341 && strucmp(ps_global->VAR_POST_CHAR_SET, "UTF-8"))
7342 if(err && !*err)
7343 *err = cpystr(_("Posting-Character-Set is ignored with Use-System-Translation turned on"));
7345 ps_global->posting_charmap = cpystr("UTF-8");
7348 set_locale_charmap(ps_global->keyboard_charmap);
7350 return(0);
7355 * Given a single printer string from the config file, returns pointers
7356 * to alloc'd strings containing the printer nickname, the command,
7357 * the init string, the trailer string, everything but the nickname string,
7358 * and everything but the command string. All_but_cmd includes the trailing
7359 * space at the end (the one before the command) but all_but_nick does not
7360 * include the leading space (the one before the [).
7361 * If you pass in a pointer it is guaranteed to come back pointing to an
7362 * allocated string, even if it is just an empty string. It is ok to pass
7363 * NULL for any of the six return strings.
7365 void
7366 parse_printer(char *input, char **nick, char **cmd, char **init, char **trailer,
7367 char **all_but_nick, char **all_but_cmd)
7369 char *p, *q, *start, *saved_options = NULL;
7370 int tmpsave, cnt;
7372 if(!input)
7373 input = "";
7375 if(nick || all_but_nick){
7376 if((p = srchstr(input, " [")) != NULL){
7377 if(all_but_nick)
7378 *all_but_nick = cpystr(p+1);
7380 if(nick){
7381 while(p-1 > input && isspace((unsigned char)*(p-1)))
7382 p--;
7384 tmpsave = *p;
7385 *p = '\0';
7386 *nick = cpystr(input);
7387 *p = tmpsave;
7390 else{
7391 if(nick)
7392 *nick = cpystr("");
7394 if(all_but_nick)
7395 *all_but_nick = cpystr(input);
7399 if((p = srchstr(input, "] ")) != NULL){
7401 ++p;
7402 }while(isspace((unsigned char)*p));
7404 tmpsave = *p;
7405 *p = '\0';
7406 saved_options = cpystr(input);
7407 *p = tmpsave;
7409 else
7410 p = input;
7412 if(cmd)
7413 *cmd = cpystr(p);
7415 if(init){
7416 if(saved_options && (p = srchstr(saved_options, "INIT="))){
7417 start = p + strlen("INIT=");
7418 for(cnt=0, p = start; *p && *(p+1) && isxpair(p); p += 2)
7419 cnt++;
7421 q = *init = (char *)fs_get((cnt + 1) * sizeof(char));
7422 for(p = start; *p && *(p+1) && isxpair(p); p += 2)
7423 *q++ = read_hex(p);
7425 *q = '\0';
7427 else
7428 *init = cpystr("");
7431 if(trailer){
7432 if(saved_options && (p = srchstr(saved_options, "TRAILER="))){
7433 start = p + strlen("TRAILER=");
7434 for(cnt=0, p = start; *p && *(p+1) && isxpair(p); p += 2)
7435 cnt++;
7437 q = *trailer = (char *)fs_get((cnt + 1) * sizeof(char));
7438 for(p = start; *p && *(p+1) && isxpair(p); p += 2)
7439 *q++ = read_hex(p);
7441 *q = '\0';
7443 else
7444 *trailer = cpystr("");
7447 if(all_but_cmd){
7448 if(saved_options)
7449 *all_but_cmd = saved_options;
7450 else
7451 *all_but_cmd = cpystr("");
7453 else if(saved_options)
7454 fs_give((void **)&saved_options);
7459 copy_pinerc(char *local, char *remote, char **err_msg)
7461 return(copy_localfile_to_remotefldr(RemImap, local, remote,
7462 REMOTE_PINERC_SUBTYPE,
7463 err_msg));
7468 copy_abook(char *local, char *remote, char **err_msg)
7470 return(copy_localfile_to_remotefldr(RemImap, local, remote,
7471 REMOTE_ABOOK_SUBTYPE,
7472 err_msg));
7477 * Copy local file to remote folder.
7479 * Args remotetype -- type of remote folder
7480 * local -- name of local file
7481 * remote -- name of remote folder
7482 * subtype --
7484 * Returns 0 on success.
7487 copy_localfile_to_remotefldr(RemType remotetype, char *local, char *remote,
7488 char *subtype, char **err_msg)
7490 int retfail = -1;
7491 unsigned flags;
7492 REMDATA_S *rd;
7494 dprint((9, "copy_localfile_to_remotefldr(%s,%s)\n",
7495 local ? local : "<null>",
7496 remote ? remote : "<null>"));
7498 *err_msg = (char *)fs_get(MAXPATH * sizeof(char));
7500 if(!local || !*local){
7501 snprintf(*err_msg, MAXPATH, _("No local file specified"));
7502 return(retfail);
7505 if(!remote || !*remote){
7506 snprintf(*err_msg, MAXPATH, _("No remote folder specified"));
7507 return(retfail);
7510 if(!IS_REMOTE(remote)){
7511 snprintf(*err_msg, MAXPATH, _("Remote folder name \"%s\" %s"), remote,
7512 (*remote != '{') ? _("must begin with \"{\"") : _("not valid"));
7513 return(retfail);
7516 if(IS_REMOTE(local)){
7517 snprintf(*err_msg, MAXPATH, _("First argument \"%s\" must be a local filename"),
7518 local);
7519 return(retfail);
7522 if(can_access(local, ACCESS_EXISTS) != 0){
7523 snprintf(*err_msg, MAXPATH, _("Local file \"%s\" does not exist"), local);
7524 return(retfail);
7527 if(can_access(local, READ_ACCESS) != 0){
7528 snprintf(*err_msg, MAXPATH, _("Can't read local file \"%s\": %s"),
7529 local, error_description(errno));
7530 return(retfail);
7534 * Check if remote folder exists and create it if it doesn't.
7536 flags = 0;
7537 rd = rd_create_remote(remotetype, remote, subtype,
7538 &flags, _("Error: "), _("Can't copy to remote folder."));
7540 if(!rd || rd->access == NoExists){
7541 snprintf(*err_msg, MAXPATH, _("Can't create \"%s\""), remote);
7542 if(rd)
7543 rd_free_remdata(&rd);
7545 return(retfail);
7548 if(rd->access == MaybeRorW)
7549 rd->access = ReadWrite;
7551 rd->flags |= (NO_META_UPDATE | DO_REMTRIM);
7552 rd->lf = cpystr(local);
7554 rd_open_remote(rd);
7555 if(!rd_stream_exists(rd)){
7556 snprintf(*err_msg, MAXPATH, _("Can't open remote folder \"%s\""), rd->rn);
7557 rd_free_remdata(&rd);
7558 return(retfail);
7561 if(rd_remote_is_readonly(rd)){
7562 snprintf(*err_msg, MAXPATH, _("Remote folder \"%s\" is readonly"), rd->rn);
7563 rd_free_remdata(&rd);
7564 return(retfail);
7567 switch(rd->type){
7568 case RemImap:
7570 * Empty folder, add a header msg.
7572 if(rd->t.i.stream->nmsgs == 0){
7573 if(rd_init_remote(rd, 1) != 0){
7574 snprintf(*err_msg, MAXPATH,
7575 _("Failed initializing remote folder \"%s\", check debug file"),
7576 rd->rn);
7577 rd_free_remdata(&rd);
7578 return(retfail);
7582 fs_give((void **)err_msg);
7583 *err_msg = NULL;
7584 if(rd_chk_for_hdr_msg(&(rd->t.i.stream), rd, err_msg)){
7585 rd_free_remdata(&rd);
7586 return(retfail);
7589 break;
7591 default:
7592 break;
7595 if(rd_update_remote(rd, NULL) != 0){
7596 snprintf(*err_msg, MAXPATH, _("Error copying to remote folder \"%s\""), rd->rn);
7597 rd_free_remdata(&rd);
7598 return(retfail);
7601 rd_update_metadata(rd, NULL);
7602 rd_close_remdata(&rd);
7604 fs_give((void **)err_msg);
7605 return(0);
7609 /*----------------------------------------------------------------------
7610 Panic pine - call on detected programmatic errors to exit pine, with arg
7612 Input: message -- printf styule string for panic message (see above)
7613 arg -- argument for printf string
7615 Result: The various tty modes are restored
7616 If debugging is active a core dump will be generated
7617 Exits Pine
7618 ----*/
7619 void
7620 panic1(char *message, char *arg)
7622 #define SIZEOFBUF 1001
7623 char buf1[SIZEOFBUF], buf2[SIZEOFBUF];
7625 snprintf(buf1, sizeof(buf1), "%.*s", (int) MAX(SIZEOFBUF - 1 - strlen(message), 0), arg);
7626 snprintf(buf2, sizeof(buf2), message, buf1);
7627 alpine_panic(buf2);
7634 HelpType
7635 config_help(int var, int feature)
7637 switch(var){
7638 case V_FEATURE_LIST :
7639 return(feature_list_help(feature));
7640 break;
7642 case V_PERSONAL_NAME :
7643 return(h_config_pers_name);
7644 case V_USER_ID :
7645 return(h_config_user_id);
7646 case V_USER_DOMAIN :
7647 return(h_config_user_dom);
7648 case V_SMTP_SERVER :
7649 return(h_config_smtp_server);
7650 case V_NNTP_SERVER :
7651 return(h_config_nntp_server);
7652 case V_INBOX_PATH :
7653 return(h_config_inbox_path);
7654 case V_PRUNED_FOLDERS :
7655 return(h_config_pruned_folders);
7656 case V_DEFAULT_FCC :
7657 return(h_config_default_fcc);
7658 case V_DEFAULT_SAVE_FOLDER :
7659 return(h_config_def_save_folder);
7660 case V_POSTPONED_FOLDER :
7661 return(h_config_postponed_folder);
7662 case V_READ_MESSAGE_FOLDER :
7663 return(h_config_read_message_folder);
7664 case V_FORM_FOLDER :
7665 return(h_config_form_folder);
7666 case V_ARCHIVED_FOLDERS :
7667 return(h_config_archived_folders);
7668 case V_SIGNATURE_FILE :
7669 return(h_config_signature_file);
7670 case V_LITERAL_SIG :
7671 return(h_config_literal_sig);
7672 case V_INIT_CMD_LIST :
7673 return(h_config_init_cmd_list);
7674 case V_COMP_HDRS :
7675 return(h_config_comp_hdrs);
7676 case V_CUSTOM_HDRS :
7677 return(h_config_custom_hdrs);
7678 case V_VIEW_HEADERS :
7679 return(h_config_viewer_headers);
7680 case V_VIEW_MARGIN_LEFT :
7681 return(h_config_viewer_margin_left);
7682 case V_VIEW_MARGIN_RIGHT :
7683 return(h_config_viewer_margin_right);
7684 case V_QUOTE_SUPPRESSION :
7685 return(h_config_quote_suppression);
7686 case V_SAVED_MSG_NAME_RULE :
7687 return(h_config_saved_msg_name_rule);
7688 case V_FCC_RULE :
7689 return(h_config_fcc_rule);
7690 case V_SORT_KEY :
7691 return(h_config_sort_key);
7692 case V_AB_SORT_RULE :
7693 return(h_config_ab_sort_rule);
7694 case V_FLD_SORT_RULE :
7695 return(h_config_fld_sort_rule);
7696 case V_POST_CHAR_SET :
7697 return(h_config_post_char_set);
7698 case V_UNK_CHAR_SET :
7699 return(h_config_unk_char_set);
7700 #ifndef _WINDOWS
7701 case V_KEY_CHAR_SET :
7702 return(h_config_key_char_set);
7703 case V_CHAR_SET :
7704 return(h_config_char_set);
7705 #endif /* ! _WINDOWS */
7706 case V_EDITOR :
7707 return(h_config_editor);
7708 case V_SPELLER :
7709 return(h_config_speller);
7710 #ifdef _WINDOWS
7711 case V_DICTIONARY :
7712 return(h_config_aspell_dictionary);
7713 #endif /* _WINDOWS */
7714 case V_DISPLAY_FILTERS :
7715 return(h_config_display_filters);
7716 case V_SEND_FILTER :
7717 return(h_config_sending_filter);
7718 case V_ALT_ADDRS :
7719 return(h_config_alt_addresses);
7720 case V_KEYWORDS :
7721 return(h_config_keywords);
7722 case V_KW_BRACES :
7723 return(h_config_kw_braces);
7724 case V_OPENING_SEP :
7725 return(h_config_opening_sep);
7726 case V_KW_COLORS :
7727 return(h_config_kw_color);
7728 case V_ABOOK_FORMATS :
7729 return(h_config_abook_formats);
7730 case V_INDEX_FORMAT :
7731 return(h_config_index_format);
7732 case V_INCCHECKTIMEO :
7733 return(h_config_incoming_timeo);
7734 case V_INCCHECKINTERVAL :
7735 return(h_config_incoming_interv);
7736 case V_INC2NDCHECKINTERVAL :
7737 return(h_config_incoming_second_interv);
7738 case V_INCCHECKLIST :
7739 return(h_config_incoming_list);
7740 case V_SLEEP :
7741 return(h_config_psleep);
7742 case V_OVERLAP :
7743 return(h_config_viewer_overlap);
7744 case V_MAXREMSTREAM :
7745 return(h_config_maxremstream);
7746 case V_PERMLOCKED :
7747 return(h_config_permlocked);
7748 case V_MARGIN :
7749 return(h_config_scroll_margin);
7750 case V_DEADLETS :
7751 return(h_config_deadlets);
7752 case V_FILLCOL :
7753 return(h_config_composer_wrap_column);
7754 case V_TCPOPENTIMEO :
7755 return(h_config_tcp_open_timeo);
7756 case V_TCPREADWARNTIMEO :
7757 return(h_config_tcp_readwarn_timeo);
7758 case V_TCPWRITEWARNTIMEO :
7759 return(h_config_tcp_writewarn_timeo);
7760 case V_TCPQUERYTIMEO :
7761 return(h_config_tcp_query_timeo);
7762 case V_RSHOPENTIMEO :
7763 return(h_config_rsh_open_timeo);
7764 case V_SSHOPENTIMEO :
7765 return(h_config_ssh_open_timeo);
7766 case V_USERINPUTTIMEO :
7767 return(h_config_user_input_timeo);
7768 case V_REMOTE_ABOOK_VALIDITY :
7769 return(h_config_remote_abook_validity);
7770 case V_REMOTE_ABOOK_HISTORY :
7771 return(h_config_remote_abook_history);
7772 case V_INCOMING_FOLDERS :
7773 return(h_config_incoming_folders);
7774 case V_FOLDER_SPEC :
7775 return(h_config_folder_spec);
7776 case V_NEWS_SPEC :
7777 return(h_config_news_spec);
7778 case V_ADDRESSBOOK :
7779 return(h_config_address_book);
7780 case V_GLOB_ADDRBOOK :
7781 return(h_config_glob_addrbook);
7782 case V_LAST_VERS_USED :
7783 return(h_config_last_vers);
7784 case V_SENDMAIL_PATH :
7785 return(h_config_sendmail_path);
7786 case V_OPER_DIR :
7787 return(h_config_oper_dir);
7788 case V_RSHPATH :
7789 return(h_config_rshpath);
7790 case V_RSHCMD :
7791 return(h_config_rshcmd);
7792 case V_SSHPATH :
7793 return(h_config_sshpath);
7794 case V_SSHCMD :
7795 return(h_config_sshcmd);
7796 case V_NEW_VER_QUELL :
7797 return(h_config_new_ver_quell);
7798 case V_DISABLE_DRIVERS :
7799 return(h_config_disable_drivers);
7800 case V_DISABLE_AUTHS :
7801 return(h_config_disable_auths);
7802 case V_REMOTE_ABOOK_METADATA :
7803 return(h_config_abook_metafile);
7804 case V_REPLY_STRING :
7805 return(h_config_reply_indent_string);
7806 case V_WORDSEPS :
7807 return(h_config_wordseps);
7808 case V_QUOTE_REPLACE_STRING :
7809 return(h_config_quote_replace_string);
7810 case V_REPLY_INTRO :
7811 return(h_config_reply_intro);
7812 case V_EMPTY_HDR_MSG :
7813 return(h_config_empty_hdr_msg);
7814 case V_STATUS_MSG_DELAY :
7815 return(h_config_status_msg_delay);
7816 case V_ACTIVE_MSG_INTERVAL :
7817 return(h_config_active_msg_interval);
7818 case V_MAILCHECK :
7819 return(h_config_mailcheck);
7820 case V_MAILCHECKNONCURR :
7821 return(h_config_mailchecknoncurr);
7822 case V_MAILDROPCHECK :
7823 return(h_config_maildropcheck);
7824 case V_NNTPRANGE :
7825 return(h_config_nntprange);
7826 case V_NEWS_ACTIVE_PATH :
7827 return(h_config_news_active);
7828 case V_NEWS_SPOOL_DIR :
7829 return(h_config_news_spool);
7830 case V_IMAGE_VIEWER :
7831 return(h_config_image_viewer);
7832 case V_USE_ONLY_DOMAIN_NAME :
7833 return(h_config_domain_name);
7834 case V_LAST_TIME_PRUNE_QUESTION :
7835 return(h_config_prune_date);
7836 case V_UPLOAD_CMD:
7837 return(h_config_upload_cmd);
7838 case V_UPLOAD_CMD_PREFIX:
7839 return(h_config_upload_prefix);
7840 case V_DOWNLOAD_CMD:
7841 return(h_config_download_cmd);
7842 case V_DOWNLOAD_CMD_PREFIX:
7843 return(h_config_download_prefix);
7844 case V_GOTO_DEFAULT_RULE:
7845 return(h_config_goto_default);
7846 case V_INCOMING_STARTUP:
7847 return(h_config_inc_startup);
7848 case V_PRUNING_RULE:
7849 return(h_config_pruning_rule);
7850 case V_REOPEN_RULE:
7851 return(h_config_reopen_rule);
7852 case V_THREAD_DISP_STYLE:
7853 return(h_config_thread_disp_style);
7854 case V_THREAD_INDEX_STYLE:
7855 return(h_config_thread_index_style);
7856 case V_THREAD_MORE_CHAR:
7857 return(h_config_thread_indicator_char);
7858 case V_THREAD_EXP_CHAR:
7859 return(h_config_thread_exp_char);
7860 case V_THREAD_LASTREPLY_CHAR:
7861 return(h_config_thread_lastreply_char);
7862 case V_MAILCAP_PATH :
7863 return(h_config_mailcap_path);
7864 case V_MIMETYPE_PATH :
7865 return(h_config_mimetype_path);
7866 #if !defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)
7867 case V_FIFOPATH :
7868 return(h_config_fifopath);
7869 #endif
7870 case V_NMW_WIDTH :
7871 return(h_config_newmailwidth);
7872 case V_NEWSRC_PATH :
7873 return(h_config_newsrc_path);
7874 case V_BROWSER :
7875 return(h_config_browser);
7876 case V_HISTORY :
7877 return(h_config_history);
7878 #if defined(DOS) || defined(OS2)
7879 case V_FILE_DIR :
7880 return(h_config_file_dir);
7881 #endif
7882 case V_NORM_FORE_COLOR :
7883 case V_NORM_BACK_COLOR :
7884 return(h_config_normal_color);
7885 case V_REV_FORE_COLOR :
7886 case V_REV_BACK_COLOR :
7887 return(h_config_reverse_color);
7888 case V_TITLE_FORE_COLOR :
7889 case V_TITLE_BACK_COLOR :
7890 return(h_config_title_color);
7891 case V_TITLECLOSED_FORE_COLOR :
7892 case V_TITLECLOSED_BACK_COLOR :
7893 return(h_config_titleclosed_color);
7894 case V_FOLDER_FORE_COLOR:
7895 return(h_config_folder_color);
7896 case V_DIRECTORY_FORE_COLOR:
7897 return(h_config_directory_color);
7898 case V_FOLDER_LIST_FORE_COLOR:
7899 return(h_config_folder_list_color);
7900 case V_STATUS_FORE_COLOR :
7901 case V_STATUS_BACK_COLOR :
7902 return(h_config_status_color);
7903 case V_SLCTBL_FORE_COLOR :
7904 case V_SLCTBL_BACK_COLOR :
7905 return(h_config_slctbl_color);
7906 case V_QUOTE1_FORE_COLOR :
7907 case V_QUOTE2_FORE_COLOR :
7908 case V_QUOTE3_FORE_COLOR :
7909 case V_QUOTE1_BACK_COLOR :
7910 case V_QUOTE2_BACK_COLOR :
7911 case V_QUOTE3_BACK_COLOR :
7912 return(h_config_quote_color);
7913 case V_INCUNSEEN_FORE_COLOR :
7914 case V_INCUNSEEN_BACK_COLOR :
7915 return(h_config_incunseen_color);
7916 case V_SIGNATURE_FORE_COLOR :
7917 case V_SIGNATURE_BACK_COLOR :
7918 return(h_config_signature_color);
7919 case V_PROMPT_FORE_COLOR :
7920 case V_PROMPT_BACK_COLOR :
7921 return(h_config_prompt_color);
7922 case V_HEADER_GENERAL_FORE_COLOR :
7923 case V_HEADER_GENERAL_BACK_COLOR :
7924 return(h_config_header_general_color);
7925 case V_IND_PLUS_FORE_COLOR :
7926 case V_IND_IMP_FORE_COLOR :
7927 case V_IND_DEL_FORE_COLOR :
7928 case V_IND_ANS_FORE_COLOR :
7929 case V_IND_NEW_FORE_COLOR :
7930 case V_IND_UNS_FORE_COLOR :
7931 case V_IND_REC_FORE_COLOR :
7932 case V_IND_FWD_FORE_COLOR :
7933 case V_IND_PLUS_BACK_COLOR :
7934 case V_IND_IMP_BACK_COLOR :
7935 case V_IND_DEL_BACK_COLOR :
7936 case V_IND_ANS_BACK_COLOR :
7937 case V_IND_NEW_BACK_COLOR :
7938 case V_IND_UNS_BACK_COLOR :
7939 case V_IND_REC_BACK_COLOR :
7940 case V_IND_FWD_BACK_COLOR :
7941 return(h_config_index_color);
7942 case V_IND_OP_FORE_COLOR :
7943 case V_IND_OP_BACK_COLOR :
7944 return(h_config_index_opening_color);
7945 case V_IND_SUBJ_FORE_COLOR :
7946 case V_IND_SUBJ_BACK_COLOR :
7947 return(h_config_index_subject_color);
7948 case V_IND_FROM_FORE_COLOR :
7949 case V_IND_FROM_BACK_COLOR :
7950 return(h_config_index_from_color);
7951 case V_IND_HIPRI_FORE_COLOR :
7952 case V_IND_HIPRI_BACK_COLOR :
7953 case V_IND_LOPRI_FORE_COLOR :
7954 case V_IND_LOPRI_BACK_COLOR :
7955 return(h_config_index_pri_color);
7956 case V_IND_ARR_FORE_COLOR :
7957 case V_IND_ARR_BACK_COLOR :
7958 return(h_config_index_arrow_color);
7959 case V_KEYLABEL_FORE_COLOR :
7960 case V_KEYLABEL_BACK_COLOR :
7961 return(h_config_keylabel_color);
7962 case V_KEYNAME_FORE_COLOR :
7963 case V_KEYNAME_BACK_COLOR :
7964 return(h_config_keyname_color);
7965 case V_METAMSG_FORE_COLOR :
7966 case V_METAMSG_BACK_COLOR :
7967 return(h_config_metamsg_color);
7968 case V_VIEW_HDR_COLORS :
7969 return(h_config_customhdr_color);
7970 case V_INDEX_TOKEN_COLORS :
7971 return(h_config_indextoken_color);
7972 case V_PRINTER :
7973 return(h_config_printer);
7974 case V_PERSONAL_PRINT_CATEGORY :
7975 return(h_config_print_cat);
7976 case V_PERSONAL_PRINT_COMMAND :
7977 return(h_config_print_command);
7978 case V_PAT_ROLES :
7979 return(h_config_pat_roles);
7980 case V_PAT_FILTS :
7981 return(h_config_pat_filts);
7982 case V_PAT_SCORES :
7983 return(h_config_pat_scores);
7984 case V_PAT_INCOLS :
7985 return(h_config_pat_incols);
7986 case V_PAT_OTHER :
7987 return(h_config_pat_other);
7988 case V_PAT_SRCH :
7989 return(h_config_pat_srch);
7990 case V_INDEX_COLOR_STYLE :
7991 return(h_config_index_color_style);
7992 case V_TITLEBAR_COLOR_STYLE :
7993 return(h_config_titlebar_color_style);
7994 #ifdef _WINDOWS
7995 case V_FONT_NAME :
7996 return(h_config_font_name);
7997 case V_FONT_SIZE :
7998 return(h_config_font_size);
7999 case V_FONT_STYLE :
8000 return(h_config_font_style);
8001 case V_FONT_CHAR_SET :
8002 return(h_config_font_char_set);
8003 case V_PRINT_FONT_NAME :
8004 return(h_config_print_font_name);
8005 case V_PRINT_FONT_SIZE :
8006 return(h_config_print_font_size);
8007 case V_PRINT_FONT_STYLE :
8008 return(h_config_print_font_style);
8009 case V_PRINT_FONT_CHAR_SET :
8010 return(h_config_print_font_char_set);
8011 case V_WINDOW_POSITION :
8012 return(h_config_window_position);
8013 case V_CURSOR_STYLE :
8014 return(h_config_cursor_style);
8015 #else
8016 case V_COLOR_STYLE :
8017 return(h_config_color_style);
8018 #endif
8019 #ifdef ENABLE_LDAP
8020 case V_LDAP_SERVERS :
8021 return(h_config_ldap_servers);
8022 #endif
8023 #ifdef SMIME
8024 case V_PUBLICCERT_DIR :
8025 return(h_config_smime_pubcertdir);
8026 case V_PUBLICCERT_CONTAINER :
8027 return(h_config_smime_pubcertcon);
8028 case V_PRIVATEKEY_DIR :
8029 return(h_config_smime_privkeydir);
8030 case V_PRIVATEKEY_CONTAINER :
8031 return(h_config_smime_privkeycon);
8032 case V_CACERT_DIR :
8033 return(h_config_smime_cacertdir);
8034 case V_CACERT_CONTAINER :
8035 return(h_config_smime_cacertcon);
8036 #endif
8037 case V_RSS_NEWS :
8038 return(h_config_rss_news);
8039 case V_RSS_WEATHER :
8040 return(h_config_rss_weather);
8041 case V_WP_INDEXHEIGHT :
8042 return(h_config_wp_indexheight);
8043 case V_WP_INDEXLINES :
8044 return(h_config_wp_indexlines);
8045 case V_WP_AGGSTATE :
8046 return(h_config_wp_aggstate);
8047 case V_WP_STATE :
8048 return(h_config_wp_state);
8049 case V_WP_COLUMNS :
8050 return(h_config_wp_columns);
8051 default :
8052 return(NO_HELP);
8058 * We don't want the user to be able to edit their pinerc and set
8059 * printer to whatever they want if personal-print-command is fixed.
8060 * So make sure printer is set to something legitimate. If it isn't,
8061 * set it to something standard and return non-zero.
8064 printer_value_check_and_adjust(void)
8066 char **tt;
8067 char aname[100], wname[100];
8068 int ok = 0;
8069 struct variable *vars = ps_global->vars;
8071 if(vars[V_PERSONAL_PRINT_COMMAND].is_fixed && !vars[V_PRINTER].is_fixed){
8072 strncpy(aname, ANSI_PRINTER, sizeof(aname));
8073 aname[sizeof(aname)-1] = '\0';
8074 strncat(aname, "-no-formfeed", sizeof(aname)-strlen(aname)-1);
8075 strncpy(wname, WYSE_PRINTER, sizeof(wname));
8076 wname[sizeof(wname)-1] = '\0';
8077 strncat(wname, "-no-formfeed", sizeof(wname)-strlen(wname)-1);
8078 if(strucmp(VAR_PRINTER, ANSI_PRINTER) == 0
8079 || strucmp(VAR_PRINTER, aname) == 0
8080 || strucmp(VAR_PRINTER, WYSE_PRINTER) == 0
8081 || strucmp(VAR_PRINTER, wname) == 0)
8082 ok++;
8083 else if(VAR_STANDARD_PRINTER && VAR_STANDARD_PRINTER[0]){
8084 for(tt = VAR_STANDARD_PRINTER; *tt; tt++)
8085 if(strucmp(VAR_PRINTER, *tt) == 0)
8086 break;
8088 if(*tt)
8089 ok++;
8092 if(!ok){
8093 char *val;
8094 struct variable *v;
8096 if(VAR_STANDARD_PRINTER && VAR_STANDARD_PRINTER[0])
8097 val = VAR_STANDARD_PRINTER[0];
8098 else
8099 val = ANSI_PRINTER;
8101 v = &vars[V_PRINTER];
8102 if(v->main_user_val.p)
8103 fs_give((void **)&v->main_user_val.p);
8104 if(v->post_user_val.p)
8105 fs_give((void **)&v->post_user_val.p);
8106 if(v->current_val.p)
8107 fs_give((void **)&v->current_val.p);
8109 v->main_user_val.p = cpystr(val);
8110 v->current_val.p = cpystr(val);
8114 return(!ok);
8118 char **
8119 get_supported_options(void)
8121 char **config;
8122 DRIVER *d;
8123 AUTHENTICATOR *a;
8124 char *title = _("Supported features in this Alpine");
8125 char sbuf[MAX_SCREEN_COLS+1];
8126 int cnt, alcnt, len, cols, disabled, any_disabled = 0;;
8129 * Line count:
8130 * Title + blank = 2
8131 * SSL Title + SSL lines + blank = 5
8132 * Auth title + blank = 2
8133 * Driver title + blank = 2
8134 * LDAP title + LDAP line = 2
8135 * Disabled explanation + blank line = 4
8136 * end = 1
8138 cnt = 18;
8139 for(a = mail_lookup_auth(1); a; a = a->next)
8140 cnt++;
8141 for(d = (DRIVER *)mail_parameters(NIL, GET_DRIVERS, NIL);
8142 d; d = d->next)
8143 cnt++;
8145 alcnt = cnt;
8146 config = (char **) fs_get(alcnt * sizeof(char *));
8147 memset(config, 0, alcnt * sizeof(char *));
8149 cols = ps_global->ttyo ? ps_global->ttyo->screen_cols : 0;
8150 len = utf8_width(title);
8151 snprintf(sbuf, sizeof(sbuf), "%*s%s", cols > len ? (cols-len)/2 : 0, "", title);
8153 cnt = 0;
8154 if(cnt < alcnt)
8155 config[cnt] = cpystr(sbuf);
8157 if(++cnt < alcnt)
8158 config[cnt] = cpystr("");
8160 if(++cnt < alcnt)
8161 /* TRANSLATORS: headings */
8162 config[cnt] = cpystr(_("Encryption:"));
8164 if(++cnt < alcnt && mail_parameters(NIL, GET_SSLDRIVER, NIL))
8165 config[cnt] = cpystr(_(" TLS and SSL"));
8166 else
8167 config[cnt] = cpystr(_(" None (no TLS or SSL)"));
8168 #ifdef SSL_SUPPORTS_TLSV1_2
8169 if(++cnt < alcnt)
8170 config[cnt] = cpystr(" TLSv1.1, TLSv1.2, and DTLSv1");
8171 #endif
8172 #ifdef SMIME
8173 if(++cnt < alcnt)
8174 config[cnt] = cpystr(" S/MIME");
8175 #endif
8177 if(++cnt < alcnt)
8178 config[cnt] = cpystr("");
8180 if(++cnt < alcnt)
8181 config[cnt] = cpystr(_("Authenticators:"));
8183 for(a = mail_lookup_auth(1); a; a = a->next){
8184 disabled = (a->client == NULL && a->server == NULL);
8185 any_disabled += disabled;
8186 snprintf(sbuf, sizeof(sbuf), " %s%s", a->name, disabled ? " (disabled)" : "");
8187 if(++cnt < alcnt)
8188 config[cnt] = cpystr(sbuf);
8191 if(++cnt < alcnt)
8192 config[cnt] = cpystr("");
8194 if(++cnt < alcnt)
8195 config[cnt] = cpystr(_("Mailbox drivers:"));
8197 for(d = (DRIVER *)mail_parameters(NIL, GET_DRIVERS, NIL);
8198 d; d = d->next){
8199 disabled = (d->flags & DR_DISABLE);
8200 any_disabled += disabled;
8201 snprintf(sbuf, sizeof(sbuf), " %s%s", d->name, disabled ? " (disabled)" : "");
8202 if(++cnt < alcnt)
8203 config[cnt] = cpystr(sbuf);
8206 if(++cnt < alcnt)
8207 config[cnt] = cpystr("");
8209 if(++cnt < alcnt)
8210 config[cnt] = cpystr(_("Directories:"));
8212 #ifdef ENABLE_LDAP
8213 if(++cnt < alcnt)
8214 config[cnt] = cpystr(" LDAP");
8215 #else
8216 if(++cnt < alcnt)
8217 config[cnt] = cpystr(" None (no LDAP)");
8218 #endif
8220 if(any_disabled){
8221 if(++cnt < alcnt)
8222 config[cnt] = cpystr("");
8224 if(ps_global->ttyo){
8225 if(++cnt < alcnt)
8226 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."));
8228 else{
8229 if(++cnt < alcnt)
8230 config[cnt] = cpystr(_("Authenticators may be disabled because of the \"disable-these-authenticators\""));
8231 if(++cnt < alcnt)
8232 config[cnt] = cpystr(_("hidden config option. Mailbox drivers may be disabled because of the"));
8233 if(++cnt < alcnt)
8234 config[cnt] = cpystr(_("\"disable-these-drivers\" hidden config option."));
8238 if(++cnt < alcnt)
8239 config[cnt] = NULL;
8241 return(config);
8245 unsigned
8246 reset_startup_rule(MAILSTREAM *stream)
8248 long rflags = ROLE_DO_OTHER;
8249 PAT_STATE pstate;
8250 PAT_S *pat;
8251 unsigned startup_rule;
8253 startup_rule = IS_NOTSET;
8255 if(stream && nonempty_patterns(rflags, &pstate)){
8256 for(pat = first_pattern(&pstate); pat; pat = next_pattern(&pstate)){
8257 if(match_pattern(pat->patgrp, stream, NULL, NULL, NULL,
8258 SE_NOSERVER|SE_NOPREFETCH))
8259 break;
8262 if(pat && pat->action && !pat->action->bogus)
8263 startup_rule = pat->action->startup_rule;
8266 return(startup_rule);
8270 #ifdef _WINDOWS
8272 char *
8273 transformed_color(old)
8274 char *old;
8276 if(!old)
8277 return("");
8279 if(!struncmp(old, "color008", 8))
8280 return("colorlgr");
8281 else if(!struncmp(old, "color009", 8))
8282 return("colormgr");
8283 else if(!struncmp(old, "color010", 8))
8284 return("colordgr");
8286 return("");
8291 * If this is the first time we've run a version > 4.40, and there
8292 * is evidence that the config file has not been used by unix pine,
8293 * then we convert color008 to colorlgr, color009 to colormgr, and
8294 * color010 to colordgr. If the config file is being used by
8295 * unix pine then color008 may really supposed to be color008, color009
8296 * may really supposed to be red, and color010 may really supposed to be
8297 * green. Same if we've already run 4.41 or higher previously.
8299 * Returns 0 if no changes, > 0 if something was changed.
8302 convert_pc_gray_names(ps, prc, which)
8303 struct pine *ps;
8304 PINERC_S *prc;
8305 EditWhich which;
8307 struct variable *v;
8308 int ret = 0, ic = 0;
8309 char **s, *t, *p, *pstr, *new, *pval, **apval, **lval;
8311 for(v = ps->vars; v->name; v++){
8312 if(!color_holding_var(ps, v) || v == &ps->vars[V_KW_COLORS])
8313 continue;
8315 if(v == &ps->vars[V_VIEW_HDR_COLORS]){
8317 if((lval = LVAL(v,which)) != NULL){
8318 /* fix these in place */
8319 for(s = lval; (t = *s) != NULL; s++){
8320 if((p = srchstr(t, "FG=color008")) ||
8321 (p = srchstr(t, "FG=color009")) ||
8322 (p = srchstr(t, "FG=color010"))){
8323 strncpy(p+3, transformed_color(p+3), 8);
8324 ret++;
8327 if((p = srchstr(t, "BG=color008")) ||
8328 (p = srchstr(t, "BG=color009")) ||
8329 (p = srchstr(t, "BG=color010"))){
8330 strncpy(p+3, transformed_color(p+3), 8);
8331 ret++;
8336 else{
8337 if((pval = PVAL(v,which)) != NULL){
8338 apval = APVAL(v,which);
8339 if(apval && (!strucmp(pval, "color008") ||
8340 !strucmp(pval, "color009") ||
8341 !strucmp(pval, "color010"))){
8342 new = transformed_color(pval);
8343 if(*apval)
8344 fs_give((void **)apval);
8346 *apval = cpystr(new);
8347 ret++;
8353 v = &ps->vars[V_PAT_INCOLS];
8354 if((lval = LVAL(v,which)) != NULL){
8355 for(s = lval; (t = *s) != NULL; s++){
8356 if((pstr = srchstr(t, "action=")) != NULL){
8357 if((p = srchstr(pstr, "FG=color008")) ||
8358 (p = srchstr(pstr, "FG=color009")) ||
8359 (p = srchstr(pstr, "FG=color010"))){
8360 strncpy(p+3, transformed_color(p+3), 8);
8361 ic++;
8364 if((p = srchstr(pstr, "BG=color008")) ||
8365 (p = srchstr(pstr, "BG=color009")) ||
8366 (p = srchstr(pstr, "BG=color010"))){
8367 strncpy(p+3, transformed_color(p+3), 8);
8368 ic++;
8374 if(ic)
8375 set_current_val(&ps->vars[V_PAT_INCOLS], TRUE, TRUE);
8377 return(ret+ic);
8382 unix_color_style_in_pinerc(prc)
8383 PINERC_S *prc;
8385 PINERC_LINE *pline;
8387 for(pline = prc ? prc->pinerc_lines : NULL;
8388 pline && (pline->var || pline->line); pline++)
8389 if(pline->line && !struncmp("color-style=", pline->line, 12))
8390 return(1);
8392 return(0);
8395 char *
8396 pcpine_general_help(titlebuf)
8397 char *titlebuf;
8399 if(titlebuf)
8400 strcpy(titlebuf, "PC Alpine For Windows");
8402 return(pcpine_help(h_pine_for_windows));
8405 #endif /* _WINDOWS */