* New version 2.20.11
[alpine.git] / pith / conf.c
blob6a803932cca6ee9a3d42722ad10f0d9a54a39e98
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_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\".";
249 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\".";
251 CONF_TXT_T cf_reopen_rule[] = "Controls behavior when reopening an already open folder.";
253 CONF_TXT_T cf_text_thread_disp_style[] = "Style that MESSAGE INDEX is displayed in when threading.";
255 CONF_TXT_T cf_text_thread_index_style[] = "Style of THREAD INDEX or default MESSAGE INDEX when threading.";
257 CONF_TXT_T cf_text_thread_more_char[] = "When threading, character used to indicate collapsed messages underneath.";
259 CONF_TXT_T cf_text_thread_exp_char[] = "When threading, character used to indicate expanded messages underneath.";
261 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.";
263 CONF_TXT_T cf_text_use_only_domain_name[] = "If \"user-domain\" not set, strips hostname in FROM address. (Unix only)";
265 CONF_TXT_T cf_text_printer[] = "Your default printer selection";
267 CONF_TXT_T cf_text_personal_print_command[] = "List of special print commands";
269 CONF_TXT_T cf_text_personal_print_cat[] = "Which category default print command is in";
271 CONF_TXT_T cf_text_standard_printer[] = "The system wide standard printers";
273 CONF_TXT_T cf_text_last_time_prune_quest[] = "Set by Alpine; controls beginning-of-month sent-mail pruning.";
275 CONF_TXT_T cf_text_last_version_used[] = "Set by Alpine; controls display of \"new version\" message.";
277 CONF_TXT_T cf_text_disable_drivers[] = "List of mail drivers to disable.";
279 CONF_TXT_T cf_text_disable_auths[] = "List of SASL authenticators to disable.";
281 CONF_TXT_T cf_text_remote_abook_metafile[] = "Set by Alpine; contains data for caching remote address books.";
283 CONF_TXT_T cf_text_old_patterns[] = "Patterns is obsolete, use patterns-xxx";
285 CONF_TXT_T cf_text_old_filters[] = "Patterns-filters is obsolete, use patterns-filters2";
287 CONF_TXT_T cf_text_old_scores[] = "Patterns-scores is obsolete, use patterns-scores2";
289 CONF_TXT_T cf_text_patterns[] = "Patterns and their actions are stored here.";
291 CONF_TXT_T cf_text_remote_abook_history[] = "How many extra copies of remote address book should be kept. Default: 3";
293 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";
295 CONF_TXT_T cf_text_bugs_fullname[] = "Full name for bug report address used by \"Report Bug\" command";
297 CONF_TXT_T cf_text_bugs_address[] = "Email address used to send bug reports";
299 CONF_TXT_T cf_text_bugs_extras[] = "Program/Script used by \"Report Bug\" command. No default.";
301 CONF_TXT_T cf_text_suggest_fullname[] = "Full name for suggestion address used by \"Report Bug\" command";
303 CONF_TXT_T cf_text_suggest_address[] = "Email address used to send suggestions";
305 CONF_TXT_T cf_text_local_fullname[] = "Full name for \"local support\" address used by \"Report Bug\" command.\n# Default: Local Support";
307 CONF_TXT_T cf_text_local_address[] = "Email address used to send to \"local support\".\n# Default: postmaster";
309 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";
311 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.";
313 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.";
315 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)";
317 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.";
319 CONF_TXT_T cf_text_out_fltr[] = "This defines a program that message text is piped into before MIME\n# encoding, prior to sending";
321 CONF_TXT_T cf_text_alt_addrs[] = "A list of alternate addresses the user is known by";
323 CONF_TXT_T cf_text_keywords[] = "A list of keywords for use in categorizing messages";
325 CONF_TXT_T cf_text_kw_colors[] = "Colors used to display keywords in the index";
327 CONF_TXT_T cf_text_kw_braces[] = "Characters which surround keywords in SUBJKEY token.\n# Default is \"{\" \"} \"";
329 CONF_TXT_T cf_text_opening_sep[] = "Characters between subject and opening text in SUBJECTTEXT token.\n# Default is \" - \"";
331 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";
333 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";
335 CONF_TXT_T cf_text_overlap[] = "The number of lines of overlap when scrolling through message text";
337 CONF_TXT_T cf_text_maxremstreams[] = "The maximum number of non-stayopen remote connections that Alpine will use";
339 CONF_TXT_T cf_text_permlocked[] = "A list of folders that should be left open once opened (INBOX is implicit)";
341 CONF_TXT_T cf_text_margin[] = "Number of lines from top and bottom of screen where single\n# line scrolling occurs.";
343 CONF_TXT_T cf_text_stat_msg_delay[] = "The number of seconds to sleep after writing a status message";
345 CONF_TXT_T cf_text_busy_cue_rate[] = "Number of times per-second to update busy cue messages";
347 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";
349 CONF_TXT_T cf_text_mailcheck[] = "The approximate number of seconds between checks for new mail";
351 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";
353 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";
355 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";
357 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\".";
359 CONF_TXT_T cf_text_news_spooldir[] = "Directory containing system's news data.\n# The default is typically \"/usr/spool/news\"";
361 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.";
363 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.";
365 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.";
367 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.";
369 CONF_TXT_T cf_text_goto_default[] = "Sets the default folder and collection offered at the Goto Command's prompt.";
371 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.";
373 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.";
375 CONF_TXT_T cf_text_newmail_fifo_path[] = "Sets the filename for the newmail fifo (named pipe). Unix only.";
377 CONF_TXT_T cf_text_nmw_width[] = "Sets the width for the NewMail screen.";
379 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.";
381 CONF_TXT_T cf_text_debug_mem[] = "Debug-memory is obsolete";
383 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).";
385 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.";
387 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.";
389 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.";
391 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.";
393 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.";
395 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\")";
397 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.";
399 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.";
401 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.";
403 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.";
405 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.";
407 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.";
409 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\")";
411 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.";
413 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.";
415 CONF_TXT_T cf_text_elm_style_save[] = "Elm-style-save is obsolete, use saved-msg-name-rule";
417 CONF_TXT_T cf_text_header_in_reply[] = "Header-in-reply is obsolete, use include-header-in-reply in feature-list";
419 CONF_TXT_T cf_text_feature_level[] = "Feature-level is obsolete, use feature-list";
421 CONF_TXT_T cf_text_old_style_reply[] = "Old-style-reply is obsolete, use signature-at-bottom in feature-list";
423 CONF_TXT_T cf_text_compose_mime[] = "Compose-mime is obsolete";
425 CONF_TXT_T cf_text_show_all_characters[] = "Show-all-characters is obsolete";
427 CONF_TXT_T cf_text_save_by_sender[] = "Save-by-sender is obsolete, use saved-msg-name-rule";
429 CONF_TXT_T cf_text_file_dir[] = "Default directory used for Attachment handling (attach and save)\n# and Export command output";
431 CONF_TXT_T cf_text_folder_extension[] = "Folder-extension is obsolete";
433 CONF_TXT_T cf_text_normal_foreground_color[] = "Choose: black, blue, green, cyan, red, magenta, yellow, or white.";
435 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.";
437 CONF_TXT_T cf_text_newsrc_path[] = "Full path and name of NEWSRC file";
440 /*----------------------------------------------------------------------
441 These are the variables that control a number of pine functions. They
442 come out of the .pinerc and the /usr/local/lib/pine.conf files. Some can
443 be set by the user while in Alpine. Eventually all the local ones should
444 be so and maybe the global ones too.
446 Each variable can have a command-line, user, global, and current value.
447 All of these values are malloc'd. The user value is the one read out of
448 the user's .pinerc, the global value is the one from the system pine
449 configuration file. There are often defaults for the global values, set
450 at the start of init_vars(). Perhaps someday there will be group values.
451 The current value is the one that is actually in use.
452 ----*/
453 /* name is_changed_val
454 remove_quotes |
455 is_outermost | |
456 is_onlymain | | |
457 is_fixed | | | |
458 is_list | | | | |
459 is_global | | | | | |
460 is_user | | | | | | |
461 been_written | | | | | | | |
462 is_used | | | | | | | | |
463 is_obsolete | | | | | | | | | |
464 | | | | | | | | | | |
465 (on following line) description | | | | | | | | | | |
466 | | | | | | | | | | | |
467 | | | | | | | | | | | | */
468 static struct variable variables[] = {
469 {"personal-name", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
470 NULL, cf_text_personal_name},
472 #if defined(DOS) || defined(OS2)
473 /* Have to have this on DOS, PC's, Macs, etc... */
474 "user-id", 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0,
475 #else /* Don't allow on UNIX machines for some security */
476 "user-id", 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0,
477 #endif
478 "User ID", cf_text_user_id},
479 {"user-domain", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
480 NULL, cf_text_user_domain},
481 {"smtp-server", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
482 "SMTP Server (for sending)", cf_text_smtp_server},
483 {"nntp-server", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
484 "NNTP Server (for news)", cf_text_nntp_server},
485 {"inbox-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
486 NULL, cf_text_inbox_path},
487 {"incoming-archive-folders", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
488 NULL, cf_text_archived_folders},
489 {"pruned-folders", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
490 NULL, cf_text_pruned_folders},
491 {"default-fcc", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
492 "Default Fcc (File carbon copy)", cf_text_default_fcc},
493 {"default-saved-msg-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
494 "Default Saved Message Folder", cf_text_default_saved},
495 {"postponed-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
496 NULL, cf_text_postponed_folder},
497 {"read-message-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
498 NULL, cf_text_read_message_folder},
499 {"form-letter-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
500 NULL, cf_text_form_letter_folder},
501 {"trash-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
502 NULL, cf_text_trash_folder},
503 {"literal-signature", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
504 NULL, cf_text_literal_sig},
505 {"signature-file", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
506 NULL, cf_text_signature_file},
507 {"feature-list", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
508 NULL, cf_text_feature_list},
509 {"initial-keystroke-list", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
510 NULL, cf_text_initial_keystroke_list},
511 {"default-composer-hdrs", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
512 "Default Composer Headers", cf_text_default_composer_hdrs},
513 {"customized-hdrs", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
514 "Customized Headers", cf_text_customized_hdrs},
515 {"viewer-hdrs", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
516 "Viewer Headers", cf_text_view_headers},
517 {"viewer-margin-left", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
518 NULL, cf_text_view_margin_left},
519 {"viewer-margin-right", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
520 NULL, cf_text_view_margin_right},
521 {"quote-suppression-threshold", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
522 NULL, cf_text_quote_suppression},
523 {"saved-msg-name-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
524 "Saved Message Name Rule", cf_text_save_msg_name_rule},
525 {"fcc-name-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
526 NULL, cf_text_fcc_name_rule},
527 {"sort-key", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
528 NULL, cf_text_sort_key},
529 {"addrbook-sort-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
530 "Address Book Sort Rule", cf_text_addrbook_sort_rule},
531 {"folder-sort-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
532 NULL, cf_text_folder_sort_rule},
533 {"goto-default-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
534 NULL, cf_text_goto_default},
535 {"incoming-startup-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
536 NULL, cf_text_inc_startup},
537 {"pruning-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
538 NULL, cf_pruning_rule},
539 {"folder-reopen-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
540 NULL, cf_reopen_rule},
541 {"threading-display-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
542 NULL, cf_text_thread_disp_style},
543 {"threading-index-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
544 NULL, cf_text_thread_index_style},
545 {"threading-indicator-character", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
546 NULL, cf_text_thread_more_char},
547 {"threading-expanded-character", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
548 NULL, cf_text_thread_exp_char},
549 {"threading-lastreply-character", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
550 "Threading Last Reply Character", cf_text_thread_lastreply_char},
551 #ifndef _WINDOWS
552 {"display-character-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
553 NULL, cf_text_disp_char_set},
554 {"character-set", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
555 NULL, cf_text_old_char_set},
556 {"keyboard-character-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
557 NULL, cf_text_key_char_set},
558 #endif /* ! _WINDOWS */
559 {"posting-character-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
560 NULL, cf_text_post_character_set},
561 {"unknown-character-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
562 NULL, cf_text_unk_character_set},
563 {"editor", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
564 NULL, cf_text_editor},
565 {"speller", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
566 NULL, cf_text_speller},
567 #ifdef _WINDOWS
568 {"aspell-dictionary-list", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
569 "Aspell Dictionaries", cf_text_speller_dictionary},
570 #endif /* _WINDOWS */
571 {"composer-wrap-column", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
572 NULL, cf_text_fillcol},
573 {"reply-indent-string", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
574 NULL, cf_text_replystr},
575 {"reply-leadin", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
576 NULL, cf_text_replyintro},
577 {"quote-replace-string", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
578 NULL, cf_text_quotereplstr},
579 {"composer-word-separators", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
580 NULL, cf_text_wordsep},
581 {"empty-header-message", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
582 NULL, cf_text_emptyhdr},
583 {"image-viewer", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
584 NULL, cf_text_image_viewer},
585 {"use-only-domain-name", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
586 NULL, cf_text_use_only_domain_name},
587 {"bugs-fullname", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
588 NULL, cf_text_bugs_fullname},
589 {"bugs-address", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
590 NULL, cf_text_bugs_address},
591 {"bugs-additional-data", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
592 NULL, cf_text_bugs_extras},
593 {"suggest-fullname", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
594 NULL, cf_text_suggest_fullname},
595 {"suggest-address", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
596 NULL, cf_text_suggest_address},
597 {"local-fullname", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
598 NULL, cf_text_local_fullname},
599 {"local-address", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
600 NULL, cf_text_local_address},
601 {"forced-abook-entry", 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0,
602 NULL, cf_text_forced_abook},
603 {"kblock-passwd-count", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
604 NULL, cf_text_kblock_passwd},
605 {"display-filters", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
606 NULL, cf_text_in_fltr},
607 {"sending-filters", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
608 NULL, cf_text_out_fltr},
609 {"alt-addresses", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
610 "Alternate Addresses", cf_text_alt_addrs},
611 {"keywords", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
612 NULL, cf_text_keywords},
613 {"keyword-surrounding-chars", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
614 "Keyword Surrounding Characters", cf_text_kw_braces},
615 {"opening-text-separator-chars", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
616 "Opening Text Separator Characters", cf_text_opening_sep},
617 {"addressbook-formats", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
618 "Address Book Formats", cf_text_abook_formats},
619 {"index-format", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
620 NULL, cf_text_index_format},
621 {"viewer-overlap", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
622 NULL, cf_text_overlap},
623 {"scroll-margin", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
624 NULL, cf_text_margin},
625 {"status-message-delay", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
626 NULL, cf_text_stat_msg_delay},
627 {"busy-cue-rate", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
628 NULL, cf_text_busy_cue_rate},
629 {"mailcap-check-interval", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
630 NULL, cf_text_psleep},
631 {"mail-check-interval", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
632 NULL, cf_text_mailcheck},
633 {"mail-check-interval-noncurrent", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
634 NULL, cf_text_mailchecknoncurr},
635 {"maildrop-check-minimum", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
636 NULL, cf_text_maildropcheck},
637 {"nntp-range", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
638 "NNTP Range", cf_text_nntprange},
639 {"newsrc-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
640 NULL, cf_text_newsrc_path},
641 {"news-active-file-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
642 NULL, cf_text_news_active},
643 {"news-spool-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
644 NULL, cf_text_news_spooldir},
645 {"upload-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
646 NULL, cf_text_upload_cmd},
647 {"upload-command-prefix", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
648 NULL, cf_text_upload_prefix},
649 {"download-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
650 NULL, cf_text_download_cmd},
651 {"download-command-prefix", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
652 NULL, cf_text_download_prefix},
653 {"mailcap-search-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
654 NULL, cf_text_mailcap_path},
655 {"mimetype-search-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
656 NULL, cf_text_mimetype_path},
657 {"url-viewers", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
658 "URL-Viewers", cf_text_browser},
659 {"max-remote-connections", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
660 "Maximum Remote Connections", cf_text_maxremstreams},
661 {"stay-open-folders", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
662 "Stayopen Folders", cf_text_permlocked},
663 {"incoming-check-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
664 NULL, cf_text_inc_check_timeo},
665 {"incoming-check-interval", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
666 NULL, cf_text_inc_check_interval},
667 {"incoming-check-interval-secondary", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
668 NULL, cf_text_inc_second_check_interval},
669 {"incoming-check-list", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
670 NULL, cf_text_inc_check_list},
671 {"dead-letter-files", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
672 NULL, cf_text_deadlets},
673 #if !defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)
674 {"newmail-fifo-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
675 "NewMail FIFO Path", cf_text_newmail_fifo_path},
676 #endif
677 {"newmail-window-width", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
678 "NewMail Window Width", cf_text_nmw_width},
680 * Starting here, the variables are hidden in the Setup/Config screen.
681 * They are exposed if feature expose-hidden-config is set.
683 {"incoming-folders", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
684 NULL, cf_text_incoming_folders},
685 {"mail-directory", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
686 NULL, cf_text_mail_directory},
687 {"folder-collections", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
688 NULL, cf_text_folder_collections},
689 {"news-collections", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
690 NULL, cf_text_news_collections},
691 {"address-book", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
692 NULL, cf_text_address_book},
693 {"global-address-book", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
694 NULL, cf_text_global_address_book},
695 {"standard-printer", 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0,
696 NULL, cf_text_standard_printer},
697 {"last-time-prune-questioned", 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0,
698 NULL, cf_text_last_time_prune_quest},
699 {"last-version-used", 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0,
700 NULL, cf_text_last_version_used},
701 {"sendmail-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
702 NULL, cf_text_sendmail_path},
703 {"operating-dir", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
704 NULL, cf_text_oper_dir},
705 {"user-input-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
706 NULL, cf_text_user_input_timeo},
707 /* OBSOLETE */
708 #ifdef DEBUGJOURNAL
709 {"debug-memory", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
710 NULL, cf_text_debug_mem},
711 #endif
712 {"tcp-open-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
713 "TCP Open Timeout", cf_text_tcp_open_timeo},
714 {"tcp-read-warning-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
715 "TCP Read Warning Timeout", cf_text_tcp_read_timeo},
716 {"tcp-write-warning-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
717 "TCP Write Warning Timeout", cf_text_tcp_write_timeo},
718 {"tcp-query-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
719 "TCP Query Timeout", cf_text_tcp_query_timeo},
720 {"rsh-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
721 NULL, cf_text_rsh_command},
722 {"rsh-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
723 NULL, cf_text_rsh_path},
724 {"rsh-open-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
725 NULL, cf_text_rsh_open_timeo},
726 {"ssh-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
727 NULL, cf_text_ssh_command},
728 {"ssh-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
729 NULL, cf_text_ssh_path},
730 {"ssh-open-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
731 NULL, cf_text_ssh_open_timeo},
732 {"new-version-threshold", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
733 NULL, cf_text_version_threshold},
734 {"disable-these-drivers", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
735 NULL, cf_text_disable_drivers},
736 {"disable-these-authenticators", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
737 NULL, cf_text_disable_auths},
738 {"remote-abook-metafile", 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0,
739 NULL, cf_text_remote_abook_metafile},
740 {"remote-abook-history", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
741 NULL, cf_text_remote_abook_history},
742 {"remote-abook-validity", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
743 NULL, cf_text_remote_abook_validity},
744 {"printer", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
745 NULL, cf_text_printer},
746 {"personal-print-command", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
747 NULL, cf_text_personal_print_command},
748 {"personal-print-category", 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0,
749 NULL, cf_text_personal_print_cat},
750 {"patterns", 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
751 NULL, cf_text_old_patterns},
752 {"patterns-roles", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
753 NULL, cf_text_patterns},
754 {"patterns-filters2", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
755 "Patterns Filters", cf_text_patterns},
756 {"patterns-filters", 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
757 NULL, cf_text_old_filters},
758 {"patterns-scores2", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
759 "Patterns Scores", cf_text_patterns},
760 {"patterns-scores", 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
761 NULL, cf_text_old_scores},
762 {"patterns-indexcolors", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
763 NULL, cf_text_patterns},
764 {"patterns-other", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
765 NULL, cf_text_patterns},
766 {"patterns-search", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
767 NULL, cf_text_patterns},
768 /* OBSOLETE VARS */
769 {"elm-style-save", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
770 NULL, cf_text_elm_style_save},
771 {"header-in-reply", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
772 NULL, cf_text_header_in_reply},
773 {"feature-level", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
774 NULL, cf_text_feature_level},
775 {"old-style-reply", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
776 NULL, cf_text_old_style_reply},
777 {"compose-mime", 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
778 NULL, cf_text_compose_mime},
779 {"show-all-characters", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
780 NULL, cf_text_show_all_characters},
781 {"save-by-sender", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
782 NULL, cf_text_save_by_sender},
783 #if defined(DOS) || defined(OS2)
784 {"file-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
785 NULL, cf_text_file_dir},
786 {"folder-extension", 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0,
787 NULL, cf_text_folder_extension},
788 #endif
789 #ifndef _WINDOWS
790 {"color-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
791 NULL, cf_text_color_style},
792 #endif
793 {"current-indexline-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
794 NULL, cf_text_current_indexline_style},
795 {"titlebar-color-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
796 NULL, cf_text_titlebar_color_style},
797 {"normal-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
798 NULL, cf_text_normal_foreground_color},
799 {"normal-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
800 {"reverse-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
801 {"reverse-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
802 {"title-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
803 {"title-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
804 {"title-closed-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
805 {"title-closed-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
806 {"folder-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
807 {"folder-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
808 {"directory-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
809 {"directory-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
810 {"folder-list-text-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
811 {"folder-list-text-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
812 {"status-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
813 {"status-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
814 {"keylabel-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
815 {"keylabel-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
816 {"keyname-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
817 {"keyname-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
818 {"selectable-item-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
819 {"selectable-item-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
820 {"meta-message-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
821 {"meta-message-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
822 {"quote1-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
823 {"quote1-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
824 {"quote2-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
825 {"quote2-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
826 {"quote3-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
827 {"quote3-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
828 {"incoming-unseen-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
829 {"incoming-unseen-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
830 {"signature-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
831 {"signature-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
832 {"prompt-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
833 {"prompt-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
834 {"header-general-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
835 {"header-general-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
836 {"index-to-me-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
837 {"index-to-me-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
838 {"index-important-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
839 {"index-important-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
840 {"index-deleted-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
841 {"index-deleted-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
842 {"index-answered-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
843 {"index-answered-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
844 {"index-new-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
845 {"index-new-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
846 {"index-recent-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
847 {"index-recent-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
848 {"index-forward-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
849 {"index-forward-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
850 {"index-unseen-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
851 {"index-unseen-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
852 {"index-highpriority-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
853 {"index-highpriority-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
854 {"index-lowpriority-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
855 {"index-lowpriority-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
856 {"index-arrow-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
857 {"index-arrow-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
858 {"index-subject-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
859 {"index-subject-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
860 {"index-from-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
861 {"index-from-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
862 {"index-opening-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
863 {"index-opening-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
864 {"index-token-colors", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
865 NULL, cf_text_index_token_color},
866 {"viewer-hdr-colors", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
867 "Viewer Header Colors", cf_text_view_hdr_color},
868 {"keyword-colors", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
869 NULL, cf_text_kw_colors},
870 #ifdef _WINDOWS
871 {"font-name", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
872 NULL, "name and size of font."},
873 {"font-size", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
874 {"font-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
875 {"font-char-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
876 {"print-font-name", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
877 NULL, "name and size of printer font."},
878 {"print-font-size", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
879 {"print-font-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
880 {"print-font-char-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
881 {"window-position", 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0,
882 NULL, cf_text_window_position},
883 {"cursor-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
884 #endif /* _WINDOWS */
885 #ifdef SMIME
886 {"smime-public-cert-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
887 "S/MIME - Public Cert Directory", cf_text_publiccertdir},
888 {"smime-public-cert-container", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
889 "S/MIME - Public Cert Container", cf_text_publiccertcontainer},
890 {"smime-private-key-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
891 "S/MIME - Private Key Directory", cf_text_privatekeydir},
892 {"smime-private-key-container", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
893 "S/MIME - Private Key Container", cf_text_privatekeycontainer},
894 {"smime-cacert-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
895 "S/MIME - Cert Authority Directory", cf_text_cacertdir},
896 {"smime-cacert-container", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
897 "S/MIME - Cert Authority Container", cf_text_cacertcontainer},
898 #endif /* SMIME */
899 #ifdef ENABLE_LDAP
900 {"ldap-servers", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
901 "LDAP Servers", cf_text_ldap_server},
902 #endif /* ENABLE_LDAP */
903 {"rss-news", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
904 "WEB ALPINE - RSS News", cf_text_rss_news},
905 {"rss-weather", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
906 "WEB ALPINE - RSS Weather", cf_text_rss_weather},
907 {"wp-indexheight", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
908 "WEB ALPINE - Index Height", cf_text_wp_indexheight},
909 {"wp-indexlines", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
910 "WEB ALPINE - Index Lines", cf_text_wp_indexlines},
911 {"wp-aggstate", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
912 "WEB ALPINE - Aggregate State", cf_text_wp_aggstate},
913 {"wp-state", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
914 "WEB ALPINE - Cross Session State", cf_text_wp_state},
915 {"wp-columns", 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0,
916 "WEB ALPINE - Columns", cf_text_wp_columns},
917 {NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL,NULL}
921 struct variable *
922 var_from_name(char *name)
924 struct variable *v;
925 int i;
927 if(!(name && name[0]))
928 return(NULL);
930 for(i = 0; (v = &variables[i]) && v->name; i++)
931 if(!strucmp(v->name,name))
932 return(v);
934 return(NULL);
938 void
939 init_init_vars(struct pine *ps)
941 ps->vars = variables;
945 #define DSIZE (25000)
946 /* this is just like dprint except it prints to a char * */
947 #ifdef DEBUG
948 #define mprint(n,x) { \
949 if(debug >= (n)){ \
950 snprintf x ; \
951 db += strlen(db); \
954 #else
955 #define mprint(n,x)
956 #endif
959 * this was split out from init_vars so we can get at the
960 * pinerc location sooner.
962 void
963 init_pinerc(struct pine *ps, char **debug_out)
965 char buf[MAXPATH+1], *p, *db;
966 #if defined(DOS) || defined(OS2)
967 char buf2[MAXPATH+1], l_pinerc[MAXPATH+1];
968 int nopinerc = 0, confregset = -1;
969 register struct variable *vars = ps->vars;
970 #endif
972 #ifdef DEBUG
974 * Since this routine is called before we've had a chance to set up
975 * the debug file for output, we put the debugging into memory and
976 * pass it back to the caller for use after init_debug(). We just
977 * allocate plenty of space.
979 if(debug_out){
980 db = *debug_out = (char *)fs_get(DSIZE * sizeof(char));
981 db[0] = '\0';
983 #endif
985 mprint(2, (db, DSIZE-(db-(*debug_out)), "\n -- init_pinerc --\n\n"));
987 #if defined(DOS) || defined(OS2)
989 * Rules for the config/support file locations under DOS are:
991 * 1) The location of the PINERC is searched for in the following
992 * order of precedence:
993 * - File pointed to by '-p' command line option
994 * - File pointed to by PINERC environment variable
995 * - $HOME\pine
996 * - same dir as argv[0]
998 * 2) The HOME environment variable, if not set, defaults to
999 * root of the current working drive (see alpine.c)
1001 * 3) The default for external files (PINE.SIG and ADDRBOOK) is the
1002 * same directory as the pinerc
1004 * 4) The support files (PINE.HLP and PINE.NDX) are expected to be in
1005 * the same directory as PINE.EXE.
1008 if(ps->prc){
1009 mprint(2, (db, DSIZE-(db-(*debug_out)),
1010 "Personal config \"%.100s\" comes from command line\n",
1011 (ps->prc && ps->prc->name) ? ps->prc->name : "<no name>"));
1013 else{
1014 mprint(2, (db, DSIZE-(db-(*debug_out)),
1015 "Personal config not set on cmdline, checking for $PINERC\n"));
1019 * First, if prc hasn't been set by a command-line -p, check to see
1020 * if PINERC is in the environment. If so, treat it just like we
1021 * would have treated it if it were a command-line arg.
1023 if(!ps->prc && (p = getenv("PINERC")) && *p){
1024 char path[MAXPATH], dir[MAXPATH];
1026 if(IS_REMOTE(p) || is_absolute_path(p)){
1027 strncpy(path, p, sizeof(path)-1);
1028 path[sizeof(path)-1] = '\0';
1030 else{
1031 getcwd(dir, sizeof(dir));
1032 build_path(path, dir, p, sizeof(path));
1035 if(!IS_REMOTE(p))
1036 ps->pinerc = cpystr(path);
1038 ps->prc = new_pinerc_s(path);
1040 if(ps->prc){
1041 mprint(2, (db, DSIZE-(db-(*debug_out)),
1042 " yes, personal config \"%.100s\" comes from $PINERC\n",
1043 (ps->prc && ps->prc->name) ? ps->prc->name : "<no name>"));
1048 * Pinerc used to be the name of the pinerc file. Then we added
1049 * the possibility of the pinerc file being remote, and we replaced
1050 * the variable pinerc with the structure prc. Unfortunately, some
1051 * parts of pine rely on the fact that pinerc is the name of the
1052 * pinerc _file_, and use the directory that the pinerc file is located
1053 * in for their own purposes. We want to preserve that so things will
1054 * keep working. So, even if the real pinerc is remote, we need to
1055 * put the name of a pinerc file in the pinerc variable so that the
1056 * directory which contains that file is writable. The file itself
1057 * doesn't have to exist for this purpose, since we are really only
1058 * using the name of the directory containing the file. Twisted.
1059 * (Alternatively, we could fix all of the code that uses the pinerc
1060 * variable for this purpose to use a new variable which really is
1061 * just a directory.) hubert 2000-sep
1063 * There are 3 cases. If pinerc is already set that means that the user
1064 * gave either a -p pinerc or an environment pinerc that is a local file,
1065 * and we are done. If pinerc is not set, then either prc is set or not.
1066 * If prc is set then the -p arg or PINERC value is a remote pinerc.
1067 * In that case we need to find a local directory to use, and put that
1068 * directory in the pinerc variable (with a fake filename tagged on).
1069 * If prc is not set, then user hasn't told us anything so we have to
1070 * try to find the default pinerc file by looking down the path of
1071 * possibilities. When we find it, we'll also use that directory.
1073 if(!ps->pinerc){
1074 *l_pinerc = '\0';
1075 *buf = '\0';
1077 if(ps->prc){ /* remote pinerc case */
1079 * We don't give them an l_pinerc unless they tell us where
1080 * to put it.
1082 if(ps->aux_files_dir)
1083 build_path(l_pinerc, ps->aux_files_dir, SYSTEM_PINERC,
1084 sizeof(l_pinerc));
1085 else{
1087 * Search for a writable directory.
1088 * Mimic what happens in !prc for local case, except we
1089 * don't need to look for the actual file.
1092 /* check if $HOME\PINE is writable */
1093 build_path(buf2, ps->home_dir, DF_PINEDIR, sizeof(buf2));
1094 if(is_writable_dir(buf2) == 0)
1095 build_path(l_pinerc, buf2, SYSTEM_PINERC, sizeof(l_pinerc));
1096 else{ /* $HOME\PINE not a writable dir */
1097 /* use this unless registry redirects us */
1098 build_path(l_pinerc, ps->pine_dir, SYSTEM_PINERC,
1099 sizeof(l_pinerc));
1100 #ifdef _WINDOWS
1101 /* if in registry, use that value */
1102 if(mswin_reg(MSWR_OP_GET, MSWR_PINE_RC, buf2, sizeof(buf2))
1103 && !IS_REMOTE(buf2)){
1104 strncpy(l_pinerc, buf2, sizeof(l_pinerc)-1);
1105 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1107 #endif
1111 else{ /* searching for pinerc file to use */
1113 * Buf2 is $HOME\PINE. If $HOME is not explicitly set,
1114 * it defaults to the current working drive (often C:).
1115 * See alpine.c to see how it is initially set.
1118 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, searching...\n"));
1119 build_path(buf2, ps->home_dir, DF_PINEDIR, sizeof(buf2));
1120 mprint(2, (db, DSIZE-(db-(*debug_out)),
1121 " checking for writable %.100s dir \"%.100s\" off of homedir\n",
1122 DF_PINEDIR, buf2));
1123 if(is_writable_dir(buf2) == 0){
1125 * $HOME\PINE exists and is writable.
1126 * See if $HOME\PINE\PINERC exists.
1128 build_path(buf, buf2, SYSTEM_PINERC, sizeof(buf));
1129 strncpy(l_pinerc, buf, sizeof(l_pinerc)-1);
1130 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1131 mprint(2, (db, DSIZE-(db-(*debug_out)), " yes, now checking for file \"%.100s\"\n",
1132 buf));
1133 if(can_access(buf, ACCESS_EXISTS) == 0){ /* found it! */
1135 * Buf is what we were looking for.
1136 * It is local and can be used for the directory, too.
1138 mprint(2, (db, DSIZE-(db-(*debug_out)), " found it\n"));
1140 else{
1142 * No $HOME\PINE\PINERC, look for
1143 * one in same dir as PINE.EXE.
1145 build_path(buf2, ps->pine_dir, SYSTEM_PINERC,
1146 sizeof(buf2));
1147 mprint(2, (db, DSIZE-(db-(*debug_out)),
1148 " no, checking for \"%.100s\" in pine.exe dir\n",
1149 buf2));
1150 if(can_access(buf2, ACCESS_EXISTS) == 0){
1151 /* found it! */
1152 mprint(2, (db, DSIZE-(db-(*debug_out)), " found it\n"));
1153 strncpy(buf, buf2, sizeof(buf)-1);
1154 buf[sizeof(buf)-1] = '\0';
1155 strncpy(l_pinerc, buf2, sizeof(l_pinerc)-1);
1156 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1158 else{
1159 #ifdef _WINDOWS
1160 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, checking in registry\n"));
1161 if(mswin_reg(MSWR_OP_GET, MSWR_PINE_RC,
1162 buf2, sizeof(buf2))){
1163 strncpy(buf, buf2, sizeof(buf)-1);
1164 buf[sizeof(buf)-1] = '\0';
1165 if(!IS_REMOTE(buf2)){
1166 strncpy(l_pinerc, buf2, sizeof(l_pinerc)-1);
1167 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1170 * Now buf is the pinerc to be used, l_pinerc is
1171 * the directory, which may be either same as buf
1172 * or it may be $HOME\PINE if registry gives us
1173 * a remote pinerc.
1175 mprint(2, (db, DSIZE-(db-(*debug_out)), " found \"%.100s\" in registry\n",
1176 buf));
1178 else{
1179 nopinerc = 1;
1180 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found, asking user\n"));
1182 #else
1183 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found\n"));
1184 #endif
1189 * Buf is the pinerc (could be remote if from registry)
1190 * and l_pinerc is the local pinerc, which may not exist.
1193 else{ /* $HOME\PINE not a writable dir */
1195 * We notice that the order of checking in the registry
1196 * and checking in the ALPINE.EXE directory are different
1197 * in this case versus the is_writable_dir(buf2) case, and
1198 * that does sort of look like a bug. However,
1199 * we don't think this is a bug since we did it on purpose
1200 * a long time ago. So even though we can't remember why
1201 * it is this way, we think we would rediscover why if we
1202 * changed it! So we won't change it.
1206 * Change the default to use to the ALPINE.EXE directory.
1208 build_path(buf, ps->pine_dir, SYSTEM_PINERC, sizeof(buf));
1209 strncpy(l_pinerc, buf, sizeof(l_pinerc)-1);
1210 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1211 #ifdef _WINDOWS
1212 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, not writable, checking in registry\n"));
1213 /* if in registry, use that value */
1214 if(mswin_reg(MSWR_OP_GET, MSWR_PINE_RC, buf2, sizeof(buf2))){
1215 strncpy(buf, buf2, sizeof(buf)-1);
1216 buf[sizeof(buf)-1] = '\0';
1217 mprint(2, (db, DSIZE-(db-(*debug_out)), " found \"%.100s\" in registry\n",
1218 buf));
1219 if(!IS_REMOTE(buf)){
1220 strncpy(l_pinerc, buf, sizeof(l_pinerc)-1);
1221 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1224 else{
1225 mprint(2, (db, DSIZE-(db-(*debug_out)),
1226 " no, checking for \"%.100s\" in alpine.exe dir\n",
1227 buf));
1229 if(can_access(buf, ACCESS_EXISTS) == 0){
1230 mprint(2, (db, DSIZE-(db-(*debug_out)), " found it\n"));
1232 else{
1233 nopinerc = 1;
1234 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found, asking user\n"));
1237 #else
1238 mprint(2, (db, DSIZE-(db-(*debug_out)),
1239 " no, checking for \"%.100s\" in alpine.exe dir\n",
1240 buf));
1242 if(can_access(buf, ACCESS_EXISTS) == 0){
1243 mprint(2, (db, DSIZE-(db-(*debug_out)), " found it\n"));
1245 else{
1246 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found, creating it\n"));
1248 #endif
1252 * When we get here we have buf set to the name of the
1253 * pinerc, which could be local or remote. We have l_pinerc
1254 * set to the same as buf if buf is local, and set to another
1255 * name otherwise, hopefully contained in a writable directory.
1257 #ifdef _WINDOWS
1258 if(nopinerc || ps_global->install_flag){
1259 char buf3[MAXPATH+1];
1261 confregset = 0;
1262 strncpy(buf3, buf, MAXPATH);
1263 buf3[MAXPATH] = '\0';
1264 if(os_config_dialog(buf3, MAXPATH,
1265 &confregset, nopinerc) == 0){
1266 strncpy(buf, buf3, MAXPATH);
1267 buf[MAXPATH] = '\0';
1268 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found, creating it\n"));
1269 mprint(2, (db, DSIZE-(db-(*debug_out)), " user says use \"%.100s\"\n", buf));
1270 if(!IS_REMOTE(buf)){
1271 strncpy(l_pinerc, buf, MAXPATH);
1272 l_pinerc[MAXPATH] = '\0';
1275 else{
1276 exit(-1);
1279 #endif
1280 ps->prc = new_pinerc_s(buf);
1283 ps->pinerc = cpystr(l_pinerc);
1286 #if defined(DOS) || defined(OS2)
1288 * The goal here is to set the auxiliary directory in the pinerc variable.
1289 * We are making the assumption that any reference to the pinerc variable
1290 * after this point is used only as a directory in which to store things,
1291 * with the prc variable being the preferred place to store pinerc location.
1292 * If -aux isn't set, then there is no change. -jpf 08/2001
1294 if(ps->aux_files_dir){
1295 l_pinerc[0] = '\0';
1296 build_path(l_pinerc, ps->aux_files_dir, SYSTEM_PINERC,
1297 sizeof(l_pinerc));
1298 if(ps->pinerc) fs_give((void **)&ps->pinerc);
1299 ps->pinerc = cpystr(l_pinerc);
1300 mprint(2, (db, DSIZE-(db-(*debug_out)), "Setting aux_files_dir to \"%.100s\"\n",
1301 ps->aux_files_dir));
1303 #endif
1305 #ifdef _WINDOWS
1306 if(confregset && (ps->update_registry != UREG_NEVER_SET))
1307 mswin_reg(MSWR_OP_SET | ((ps->update_registry == UREG_ALWAYS_SET)
1308 || confregset == 1 ? MSWR_OP_FORCE : 0),
1309 MSWR_PINE_RC,
1310 (ps->prc && ps->prc->name) ?
1311 ps->prc->name : ps->pinerc, (size_t)NULL);
1312 #endif
1315 * Now that we know the default for the PINERC, build NEWSRC default.
1316 * Backward compatibility makes this kind of funky. If what the
1317 * c-client thinks the NEWSRC should be exists *AND* it doesn't
1318 * already exist in the PINERC's dir, use c-client's default, otherwise
1319 * use the one next to the PINERC...
1321 p = last_cmpnt(ps->pinerc);
1322 buf[0] = '\0';
1323 if(p != NULL){
1324 strncpy(buf, ps->pinerc, MIN(p - ps->pinerc, sizeof(buf)-1));
1325 buf[MIN(p - ps->pinerc, sizeof(buf)-1)] = '\0';
1328 mprint(2, (db, DSIZE-(db-(*debug_out)), "Using directory \"%.100s\" for auxiliary files\n", buf));
1329 strncat(buf, "NEWSRC", sizeof(buf)-1-strlen(buf));
1331 if(!(p = (void *) mail_parameters(NULL, GET_NEWSRC, (void *)NULL))
1332 || can_access(p, ACCESS_EXISTS) < 0
1333 || can_access(buf, ACCESS_EXISTS) == 0){
1334 mail_parameters(NULL, SET_NEWSRC, (void *)buf);
1335 GLO_NEWSRC_PATH = cpystr(buf);
1337 else
1338 GLO_NEWSRC_PATH = cpystr(p);
1340 if(ps->pconf){
1341 mprint(2, (db, DSIZE-(db-(*debug_out)), "Global config \"%.100s\" comes from command line\n",
1342 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1344 else{
1345 mprint(2, (db, DSIZE-(db-(*debug_out)),
1346 "Global config not set on cmdline, checking for $PINECONF\n"));
1349 if(!ps->pconf && (p = getenv("PINECONF"))){
1350 ps->pconf = new_pinerc_s(p);
1351 if(ps->pconf){
1352 mprint(2, (db, DSIZE-(db-(*debug_out)),
1353 " yes, global config \"%.100s\" comes from $PINECONF\n",
1354 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1357 #ifdef _WINDOWS
1358 else if(!ps->pconf
1359 && mswin_reg(MSWR_OP_GET, MSWR_PINE_CONF, buf2, sizeof(buf2))){
1360 ps->pconf = new_pinerc_s(buf2);
1361 if(ps->pconf){
1362 mprint(2, (db, DSIZE-(db-(*debug_out)),
1363 " yes, global config \"%.100s\" comes from Registry\n",
1364 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1367 #endif
1368 if(!ps->pconf){
1369 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, there is no global config\n"));
1371 #ifdef _WINDOWS
1372 else if (ps->pconf && ps->pconf->name &&
1373 (ps->update_registry != UREG_NEVER_SET)){
1374 mswin_reg(MSWR_OP_SET | ((ps->update_registry == UREG_ALWAYS_SET)
1375 ? MSWR_OP_FORCE : 0),
1376 MSWR_PINE_CONF,
1377 ps->pconf->name, (size_t)NULL);
1379 #endif
1381 if(!ps->prc)
1382 ps->prc = new_pinerc_s(ps->pinerc);
1384 if(ps->exceptions){
1385 mprint(2, (db, DSIZE-(db-(*debug_out)),
1386 "Exceptions config \"%.100s\" comes from command line\n",
1387 ps->exceptions));
1389 else{
1390 mprint(2, (db, DSIZE-(db-(*debug_out)),
1391 "Exceptions config not set on cmdline, checking for $PINERCEX\n"));
1395 * Exceptions is done slightly differently from pinerc. Instead of setting
1396 * post_prc in args.c we just set the string and use it here. We do
1397 * that so that we can put it in the same directory as the pinerc if
1398 * exceptions is a relative name, and pinerc may not be set until here.
1400 * First, just like for pinerc, check environment variable if it wasn't
1401 * set on the command line.
1403 if(!ps->exceptions && (p = getenv("PINERCEX")) && *p){
1404 ps->exceptions = cpystr(p);
1405 if(ps->exceptions){
1406 mprint(2, (db, DSIZE-(db-(*debug_out)),
1407 " yes, exceptions config \"%.100s\" comes from $PINERCEX\n",
1408 ps->exceptions));
1413 * If still not set, try specific file in same dir as pinerc.
1414 * Only use it if the file exists.
1416 if(!ps->exceptions){
1417 p = last_cmpnt(ps->pinerc);
1418 buf[0] = '\0';
1419 if(p != NULL){
1420 strncpy(buf, ps->pinerc, MIN(p - ps->pinerc, sizeof(buf)-1));
1421 buf[MIN(p - ps->pinerc, sizeof(buf)-1)] = '\0';
1424 strncat(buf, "PINERCEX", sizeof(buf)-1-strlen(buf));
1426 mprint(2, (db, DSIZE-(db-(*debug_out)),
1427 " no, checking for default \"%.100s\" in pinerc dir\n", buf));
1428 if(can_access(buf, ACCESS_EXISTS) == 0) /* found it! */
1429 ps->exceptions = cpystr(buf);
1431 if(ps->exceptions){
1432 mprint(2, (db, DSIZE-(db-(*debug_out)),
1433 " yes, exceptions config \"%.100s\" comes from default\n",
1434 ps->exceptions));
1436 else{
1437 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, there is no exceptions config\n"));
1441 #else /* unix */
1443 if(ps->pconf){
1444 mprint(2, (db, DSIZE-(db-(*debug_out)), "Global config \"%.100s\" comes from command line\n",
1445 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1448 if(!ps->pconf){
1449 ps->pconf = new_pinerc_s(SYSTEM_PINERC);
1450 if(ps->pconf){
1451 mprint(2, (db, DSIZE-(db-(*debug_out)), "Global config \"%.100s\" is default\n",
1452 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1456 if(!ps->pconf){
1457 mprint(2, (db, DSIZE-(db-(*debug_out)), "No global config!\n"));
1460 if(ps->prc){
1461 mprint(2, (db, DSIZE-(db-(*debug_out)), "Personal config \"%.100s\" comes from command line\n",
1462 (ps->prc && ps->prc->name) ? ps->prc->name : "<no name>"));
1465 if(!ps->pinerc){
1466 build_path(buf, ps->home_dir, ".pinerc", sizeof(buf));
1467 ps->pinerc = cpystr(buf);
1470 if(!ps->prc){
1471 ps->prc = new_pinerc_s(ps->pinerc);
1472 if(ps->prc){
1473 mprint(2, (db, DSIZE-(db-(*debug_out)), "Personal config \"%.100s\" is default\n",
1474 (ps->prc && ps->prc->name) ? ps->prc->name : "<no name>"));
1478 if(!ps->prc){
1479 mprint(2, (db, DSIZE-(db-(*debug_out)), "No personal config!\n"));
1482 if(ps->exceptions){
1483 mprint(2, (db, DSIZE-(db-(*debug_out)),
1484 "Exceptions config \"%.100s\" comes from command line\n",
1485 ps->exceptions));
1489 * If not set, try specific file in same dir as pinerc.
1490 * Only use it if the file exists.
1492 if(!ps->exceptions){
1493 p = last_cmpnt(ps->pinerc);
1494 buf[0] = '\0';
1495 if(p != NULL){
1496 strncpy(buf, ps->pinerc, MIN(p - ps->pinerc, sizeof(buf)-1));
1497 buf[MIN(p - ps->pinerc, sizeof(buf)-1)] = '\0';
1500 strncat(buf, ".pinercex", sizeof(buf)-1-strlen(buf));
1501 mprint(2, (db, DSIZE-(db-(*debug_out)), "Exceptions config not set on cmdline\n checking for default \"%.100s\" in pinerc dir\n", buf));
1503 if(can_access(buf, ACCESS_EXISTS) == 0) /* found it! */
1504 ps->exceptions = cpystr(buf);
1506 if(ps->exceptions){
1507 mprint(2, (db, DSIZE-(db-(*debug_out)),
1508 " yes, exceptions config \"%.100s\" is default\n",
1509 ps->exceptions));
1511 else{
1512 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, there is no exceptions config\n"));
1516 #endif /* unix */
1518 if(ps->exceptions){
1520 if(!IS_REMOTE(ps->exceptions) &&
1521 !is_absolute_path(ps->exceptions)){
1522 #if defined(DOS) || defined(OS2)
1523 p = last_cmpnt(ps->pinerc);
1524 buf[0] = '\0';
1525 if(p != NULL){
1526 strncpy(buf, ps->pinerc, MIN(p - ps->pinerc, sizeof(buf)-1));
1527 buf[MIN(p - ps->pinerc, sizeof(buf)-1)] = '\0';
1530 strncat(buf, ps->exceptions, sizeof(buf)-1-strlen(buf));
1531 #else
1532 build_path(buf, ps->home_dir, ps->exceptions, sizeof(buf));
1533 #endif
1535 else{
1536 strncpy(buf, ps->exceptions, sizeof(buf)-1);
1537 buf[sizeof(buf)-1] = '\0';
1540 ps->post_prc = new_pinerc_s(buf);
1542 fs_give((void **)&ps->exceptions);
1545 mprint(2, (db, DSIZE-(db-(*debug_out)), "\n Global config: %.100s\n",
1546 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<none>"));
1547 mprint(2, (db, DSIZE-(db-(*debug_out)), " Personal config: %.100s\n",
1548 (ps->prc && ps->prc->name) ? ps->prc->name : "<none>"));
1549 mprint(2, (db, DSIZE-(db-(*debug_out)), " Exceptions config: %.100s\n",
1550 (ps->post_prc && ps->post_prc->name) ? ps->post_prc->name
1551 : "<none>"));
1552 #if !defined(DOS) && !defined(OS2)
1553 if(SYSTEM_PINERC_FIXED){
1554 mprint(2, (db, DSIZE-(db-(*debug_out)), " Fixed config: %.100s\n", SYSTEM_PINERC_FIXED));
1556 #endif
1558 mprint(2, (db, DSIZE-(db-(*debug_out)), "\n"));
1562 /*----------------------------------------------------------------------
1563 Initialize the variables
1565 Args: ps -- The usual pine structure
1567 Result:
1569 This reads the system pine configuration file and the user's pine
1570 configuration file ".pinerc" and places the results in the variables
1571 structure. It sorts out what was read and sets a few other variables
1572 based on the contents.
1573 ----*/
1574 void
1575 init_vars(struct pine *ps, void (*cmds_f) (struct pine *, char **))
1577 char buf[MAXPATH+1], *p, *q, **s;
1578 register struct variable *vars = ps->vars;
1579 int obs_header_in_reply = 0, /* the obs_ variables are to */
1580 obs_old_style_reply = 0, /* support backwards compatibility */
1581 obs_save_by_sender, i, def_sort_rev;
1582 long rvl;
1583 PINERC_S *fixedprc = NULL;
1584 FeatureLevel obs_feature_level;
1585 char *fromcharset = NULL;
1586 char *err = NULL;
1588 dprint((5, "init_vars:\n"));
1590 /*--- The defaults here are defined in os-xxx.h so they can vary
1591 per machine ---*/
1593 GLO_PRINTER = cpystr(DF_DEFAULT_PRINTER);
1594 GLO_ELM_STYLE_SAVE = cpystr(DF_ELM_STYLE_SAVE);
1595 GLO_SAVE_BY_SENDER = cpystr(DF_SAVE_BY_SENDER);
1596 GLO_HEADER_IN_REPLY = cpystr(DF_HEADER_IN_REPLY);
1597 GLO_INBOX_PATH = cpystr("inbox");
1598 GLO_DEFAULT_FCC = cpystr(DF_DEFAULT_FCC);
1599 GLO_DEFAULT_SAVE_FOLDER = cpystr(DEFAULT_SAVE);
1600 GLO_POSTPONED_FOLDER = cpystr(POSTPONED_MSGS);
1601 GLO_TRASH_FOLDER = cpystr(TRASH_FOLDER);
1602 GLO_USE_ONLY_DOMAIN_NAME = cpystr(DF_USE_ONLY_DOMAIN_NAME);
1603 GLO_FEATURE_LEVEL = cpystr("sappling");
1604 GLO_OLD_STYLE_REPLY = cpystr(DF_OLD_STYLE_REPLY);
1605 GLO_SORT_KEY = cpystr(DF_SORT_KEY);
1606 GLO_SAVED_MSG_NAME_RULE = cpystr(DF_SAVED_MSG_NAME_RULE);
1607 GLO_FCC_RULE = cpystr(DF_FCC_RULE);
1608 GLO_AB_SORT_RULE = cpystr(DF_AB_SORT_RULE);
1609 GLO_FLD_SORT_RULE = cpystr(DF_FLD_SORT_RULE);
1610 GLO_SIGNATURE_FILE = cpystr(DF_SIGNATURE_FILE);
1611 GLO_MAIL_DIRECTORY = cpystr(DF_MAIL_DIRECTORY);
1612 GLO_REMOTE_ABOOK_HISTORY = cpystr(DF_REMOTE_ABOOK_HISTORY);
1613 GLO_REMOTE_ABOOK_VALIDITY = cpystr(DF_REMOTE_ABOOK_VALIDITY);
1614 GLO_GOTO_DEFAULT_RULE = cpystr(DF_GOTO_DEFAULT_RULE);
1615 GLO_INCOMING_STARTUP = cpystr(DF_INCOMING_STARTUP);
1616 GLO_PRUNING_RULE = cpystr(DF_PRUNING_RULE);
1617 GLO_REOPEN_RULE = cpystr(DF_REOPEN_RULE);
1618 GLO_THREAD_DISP_STYLE = cpystr(DF_THREAD_DISP_STYLE);
1619 GLO_THREAD_INDEX_STYLE = cpystr(DF_THREAD_INDEX_STYLE);
1620 GLO_THREAD_MORE_CHAR = cpystr(DF_THREAD_MORE_CHAR);
1621 GLO_THREAD_EXP_CHAR = cpystr(DF_THREAD_EXP_CHAR);
1622 GLO_THREAD_LASTREPLY_CHAR = cpystr(DF_THREAD_LASTREPLY_CHAR);
1623 GLO_BUGS_FULLNAME = cpystr("Sorry No Address");
1624 GLO_BUGS_ADDRESS = cpystr("nobody");
1625 GLO_SUGGEST_FULLNAME = cpystr("Sorry No Address");
1626 GLO_SUGGEST_ADDRESS = cpystr("nobody");
1627 GLO_LOCAL_FULLNAME = cpystr(DF_LOCAL_FULLNAME);
1628 GLO_LOCAL_ADDRESS = cpystr(DF_LOCAL_ADDRESS);
1629 GLO_OVERLAP = cpystr(DF_OVERLAP);
1630 GLO_SLEEP = cpystr("60");
1631 GLO_MAXREMSTREAM = cpystr(DF_MAXREMSTREAM);
1632 GLO_MARGIN = cpystr(DF_MARGIN);
1633 GLO_FILLCOL = cpystr(DF_FILLCOL);
1634 GLO_DEADLETS = cpystr(DF_DEADLETS);
1635 GLO_NMW_WIDTH = cpystr(DF_NMW_WIDTH);
1636 GLO_REPLY_STRING = cpystr("> ");
1637 GLO_REPLY_INTRO = cpystr(DEFAULT_REPLY_INTRO);
1638 GLO_EMPTY_HDR_MSG = cpystr("undisclosed-recipients");
1639 GLO_STATUS_MSG_DELAY = cpystr("0");
1640 GLO_ACTIVE_MSG_INTERVAL = cpystr("12");
1641 GLO_USERINPUTTIMEO = cpystr("0");
1642 GLO_INCCHECKTIMEO = cpystr("5");
1643 GLO_INCCHECKINTERVAL = cpystr("180");
1644 GLO_INC2NDCHECKINTERVAL = cpystr("180");
1645 GLO_MAILCHECK = cpystr(DF_MAILCHECK);
1646 GLO_MAILCHECKNONCURR = cpystr("0");
1647 GLO_MAILDROPCHECK = cpystr(DF_MAILDROPCHECK);
1648 GLO_NNTPRANGE = cpystr("0");
1649 GLO_KBLOCK_PASSWD_COUNT = cpystr(DF_KBLOCK_PASSWD_COUNT);
1650 GLO_INDEX_COLOR_STYLE = cpystr("flip-colors");
1651 GLO_TITLEBAR_COLOR_STYLE = cpystr("default");
1652 GLO_POST_CHAR_SET = cpystr("UTF-8");
1653 #ifdef DF_FOLDER_EXTENSION
1654 GLO_FOLDER_EXTENSION = cpystr(DF_FOLDER_EXTENSION);
1655 #endif
1656 #ifdef DF_SMTP_SERVER
1657 GLO_SMTP_SERVER = parse_list(DF_SMTP_SERVER, 1,
1658 PL_REMSURRQUOT, NULL);
1659 #endif
1661 #ifdef DF_SSHPATH
1662 GLO_SSHPATH = cpystr(DF_SSHPATH);
1663 #endif
1664 #ifdef DF_SSHCMD
1665 GLO_SSHCMD = cpystr(DF_SSHCMD);
1666 #endif
1668 #ifndef _WINDOWS
1669 GLO_COLOR_STYLE = cpystr("no-color");
1670 GLO_NORM_FORE_COLOR = cpystr(DEFAULT_NORM_FORE_RGB);
1671 GLO_NORM_BACK_COLOR = cpystr(DEFAULT_NORM_BACK_RGB);
1672 #endif
1673 GLO_TITLE_FORE_COLOR = cpystr(DEFAULT_TITLE_FORE_RGB);
1674 GLO_TITLE_BACK_COLOR = cpystr(DEFAULT_TITLE_BACK_RGB);
1675 GLO_TITLECLOSED_FORE_COLOR = cpystr(DEFAULT_TITLECLOSED_FORE_RGB);
1676 GLO_TITLECLOSED_BACK_COLOR = cpystr(DEFAULT_TITLECLOSED_BACK_RGB);
1677 GLO_FOLDER_FORE_COLOR = cpystr(DEFAULT_NORM_FORE_RGB);
1678 GLO_DIRECTORY_FORE_COLOR = cpystr(DEFAULT_NORM_FORE_RGB);
1679 GLO_FOLDER_LIST_FORE_COLOR = cpystr(DEFAULT_NORM_FORE_RGB);
1680 GLO_METAMSG_FORE_COLOR = cpystr(DEFAULT_METAMSG_FORE_RGB);
1681 GLO_METAMSG_BACK_COLOR = cpystr(DEFAULT_METAMSG_BACK_RGB);
1682 GLO_QUOTE1_FORE_COLOR = cpystr(DEFAULT_QUOTE1_FORE_RGB);
1683 GLO_QUOTE1_BACK_COLOR = cpystr(DEFAULT_QUOTE1_BACK_RGB);
1684 GLO_QUOTE2_FORE_COLOR = cpystr(DEFAULT_QUOTE2_FORE_RGB);
1685 GLO_QUOTE2_BACK_COLOR = cpystr(DEFAULT_QUOTE2_BACK_RGB);
1686 GLO_QUOTE3_FORE_COLOR = cpystr(DEFAULT_QUOTE3_FORE_RGB);
1687 GLO_QUOTE3_BACK_COLOR = cpystr(DEFAULT_QUOTE3_BACK_RGB);
1688 GLO_SIGNATURE_FORE_COLOR = cpystr(DEFAULT_SIGNATURE_FORE_RGB);
1689 GLO_SIGNATURE_BACK_COLOR = cpystr(DEFAULT_SIGNATURE_BACK_RGB);
1690 GLO_IND_PLUS_FORE_COLOR = cpystr(DEFAULT_IND_PLUS_FORE_RGB);
1691 GLO_IND_PLUS_BACK_COLOR = cpystr(DEFAULT_IND_PLUS_BACK_RGB);
1692 GLO_IND_IMP_FORE_COLOR = cpystr(DEFAULT_IND_IMP_FORE_RGB);
1693 GLO_IND_IMP_BACK_COLOR = cpystr(DEFAULT_IND_IMP_BACK_RGB);
1694 GLO_IND_ANS_FORE_COLOR = cpystr(DEFAULT_IND_ANS_FORE_RGB);
1695 GLO_IND_ANS_BACK_COLOR = cpystr(DEFAULT_IND_ANS_BACK_RGB);
1696 GLO_IND_NEW_FORE_COLOR = cpystr(DEFAULT_IND_NEW_FORE_RGB);
1697 GLO_IND_NEW_BACK_COLOR = cpystr(DEFAULT_IND_NEW_BACK_RGB);
1698 GLO_IND_OP_FORE_COLOR = cpystr(DEFAULT_IND_OP_FORE_RGB);
1699 GLO_IND_OP_BACK_COLOR = cpystr(DEFAULT_IND_OP_BACK_RGB);
1700 GLO_VIEW_MARGIN_LEFT = cpystr("0");
1701 GLO_VIEW_MARGIN_RIGHT = cpystr(DF_VIEW_MARGIN_RIGHT);
1702 GLO_QUOTE_SUPPRESSION = cpystr(DF_QUOTE_SUPPRESSION);
1703 GLO_KW_BRACES = cpystr("\"{\" \"} \"");
1704 GLO_OPENING_SEP = cpystr(" - ");
1705 GLO_WP_INDEXHEIGHT = cpystr("24");
1706 GLO_WP_AGGSTATE = cpystr("1");
1707 GLO_WP_STATE = cpystr("");
1708 #ifdef DF_VAR_SPELLER
1709 GLO_SPELLER = cpystr(DF_VAR_SPELLER);
1710 #endif
1711 #ifdef SMIME
1712 if(ps->smimedir){
1713 snprintf(tmp_20k_buf, SIZEOF_20KBUF, "%s/public", ps->smimedir);
1714 tmp_20k_buf[SIZEOF_20KBUF-1] = '\0';
1715 GLO_PUBLICCERT_DIR = cpystr(tmp_20k_buf);
1717 snprintf(tmp_20k_buf, SIZEOF_20KBUF, "%s/private", ps->smimedir);
1718 tmp_20k_buf[SIZEOF_20KBUF-1] = '\0';
1719 GLO_PRIVATEKEY_DIR = cpystr(tmp_20k_buf);
1721 snprintf(tmp_20k_buf, SIZEOF_20KBUF, "%s/ca", ps->smimedir);
1722 tmp_20k_buf[SIZEOF_20KBUF-1] = '\0';
1723 GLO_CACERT_DIR = cpystr(tmp_20k_buf);
1725 else{
1726 GLO_PUBLICCERT_DIR = cpystr(DF_PUBLICCERT_DIR);
1727 GLO_PRIVATEKEY_DIR = cpystr(DF_PRIVATEKEY_DIR);
1728 GLO_CACERT_DIR = cpystr(DF_CACERT_DIR);
1730 #endif /* SMIME */
1733 * Default first value for addrbook list if none set.
1734 * We also want to be sure to set global_val to the default
1735 * if is_fixed, so that address-book= will cause the default to happen.
1737 if(!GLO_ADDRESSBOOK && !FIX_ADDRESSBOOK)
1738 GLO_ADDRESSBOOK = parse_list(DF_ADDRESSBOOK, 1, 0, NULL);
1741 * Default first value if none set.
1743 if(!GLO_STANDARD_PRINTER && !FIX_STANDARD_PRINTER)
1744 GLO_STANDARD_PRINTER = parse_list(DF_STANDARD_PRINTER, 1, 0, NULL);
1747 * Defining this default sshpath should cause ssh to be preferred over rsh
1748 * when attempting imapd preauth calls.
1750 #ifdef DF_SSHPATH
1751 if(DF_SSHPATH
1752 && is_absolute_path(DF_SSHPATH)
1753 && can_access(DF_SSHPATH, EXECUTE_ACCESS) == 0){
1754 mail_parameters(NULL, SET_SSHPATH, (void *) DF_SSHPATH);
1756 #endif
1758 * It isn't usually necessary to define this.
1760 #ifdef DF_SSHCMD
1761 if(DF_SSHCMD){
1762 mail_parameters(NULL, SET_SSHCOMMAND, (void *) DF_SSHCMD);
1764 #endif
1766 #if !defined(DOS) && !defined(OS2)
1768 * This is here instead of in init_pinerc so that we can get by without
1769 * having a global fixedprc, since we don't need it anymore after this.
1771 fixedprc = new_pinerc_s(SYSTEM_PINERC_FIXED);
1772 #endif
1774 if(ps->pconf){
1775 read_pinerc(ps->pconf, vars, ParseGlobal);
1776 if(ps->pconf->type != Loc)
1777 rd_close_remote(ps->pconf->rd);
1780 if(ps->prc){
1781 read_pinerc(ps->prc, vars, ParsePers);
1782 if(ps->prc->type != Loc)
1783 rd_close_remote(ps->prc->rd);
1786 if(ps->post_prc){
1787 read_pinerc(ps->post_prc, vars, ParsePersPost);
1788 if(ps->post_prc->type != Loc)
1789 rd_close_remote(ps->post_prc->rd);
1792 if(fixedprc){
1793 read_pinerc(fixedprc, vars, ParseFixed);
1794 free_pinerc_s(&fixedprc);
1797 ps->ew_for_except_vars = ps->post_prc ? Post : Main;
1799 if(ps->exit_if_no_pinerc && ps->first_time_user){
1801 /* TRANSLATORS: -bail is a literal option name, don't change it. */
1802 exceptional_exit(_("Exiting because -bail option is set and config file doesn't exist."), -1);
1806 * Convert everything having to do with the config to UTF-8
1807 * in order to avoid having to worry about it all over the
1808 * place.
1809 * Set the character-set first so that we may use that in
1810 * the conversion process.
1812 set_collation(0, 1);
1814 #ifndef _WINDOWS
1815 #if (HAVE_LANGINFO_H && defined(CODESET))
1817 if(output_charset_is_supported(nl_langinfo_codeset_wrapper()))
1818 ps->GLO_CHAR_SET = cpystr(nl_langinfo_codeset_wrapper());
1819 else{
1820 ps->GLO_CHAR_SET = cpystr("UTF-8");
1821 dprint((1,"nl_langinfo(CODESET) returns unrecognized value=\"%s\", using UTF-8 as default\n", (p=nl_langinfo(CODESET)) ? p : ""));
1823 #else
1824 ps->GLO_CHAR_SET = cpystr("UTF-8");
1825 #endif
1827 set_current_val(&vars[V_CHAR_SET], TRUE, TRUE);
1828 set_current_val(&vars[V_OLD_CHAR_SET], TRUE, TRUE);
1829 set_current_val(&vars[V_KEY_CHAR_SET], TRUE, TRUE);
1830 #endif /* ! _WINDOWS */
1832 set_current_val(&vars[V_POST_CHAR_SET], TRUE, TRUE);
1835 * Also set up the feature list because we need the
1836 * Use-System-Translation feature to set up the charmaps.
1839 /* way obsolete, backwards compatibility */
1840 set_current_val(&vars[V_FEATURE_LEVEL], TRUE, TRUE);
1841 if(strucmp(VAR_FEATURE_LEVEL, "seedling") == 0)
1842 obs_feature_level = Seedling;
1843 else if(strucmp(VAR_FEATURE_LEVEL, "old-growth") == 0)
1844 obs_feature_level = Seasoned;
1845 else
1846 obs_feature_level = Sapling;
1848 /* obsolete, backwards compatibility */
1849 set_current_val(&vars[V_OLD_STYLE_REPLY], TRUE, TRUE);
1850 obs_old_style_reply = !strucmp(VAR_OLD_STYLE_REPLY, "yes");
1852 set_feature_list_current_val(&vars[V_FEATURE_LIST]);
1853 process_feature_list(ps, VAR_FEATURE_LIST,
1854 (obs_feature_level == Seasoned) ? 1 : 0,
1855 obs_header_in_reply, obs_old_style_reply);
1859 * Redo set_collation call with correct value for collation,
1860 * but we're hardwiring ctype on now. That's because nl_langinfo()
1861 * call needs it and system-dependent wcwidth and wcrtomb functions
1862 * need it.
1864 set_collation(F_OFF(F_DISABLE_SETLOCALE_COLLATE, ps_global), 1);
1867 * Set up to send the correct sequence of bytes to the display terminal.
1870 if(reset_character_set_stuff(&err) == -1)
1871 alpine_panic(err ? err : "trouble with character set setup");
1872 else if(err){
1873 init_error(ps, SM_ORDER | SM_DING, 3, 5, err);
1874 fs_give((void **) &err);
1878 * Now we use the configvars from above to convert the rest
1879 * to UTF-8. That should be ok because the ones above should
1880 * be ASCII.
1882 if(ps->keyboard_charmap && strucmp(ps->keyboard_charmap, "UTF-8")
1883 && strucmp(ps->keyboard_charmap, "US-ASCII"))
1884 fromcharset = ps->keyboard_charmap;
1885 else if(ps->display_charmap && strucmp(ps->display_charmap, "UTF-8")
1886 && strucmp(ps->display_charmap, "US-ASCII"))
1887 fromcharset = ps->display_charmap;
1888 #ifndef _WINDOWS
1889 else if(VAR_OLD_CHAR_SET && strucmp(VAR_OLD_CHAR_SET, "UTF-8")
1890 && strucmp(VAR_OLD_CHAR_SET, "US-ASCII"))
1891 fromcharset = VAR_OLD_CHAR_SET;
1892 #endif /* ! _WINDOWS */
1894 convert_configvars_to_utf8(vars, fromcharset);
1897 * If we already set this while reading the remote pinerc, don't
1898 * change it.
1900 if(!VAR_REMOTE_ABOOK_METADATA || !VAR_REMOTE_ABOOK_METADATA[0])
1901 set_current_val(&vars[V_REMOTE_ABOOK_METADATA], TRUE, TRUE);
1904 * mail-directory variable is obsolete, put its value in
1905 * default folder-collection list
1907 set_current_val(&vars[V_MAIL_DIRECTORY], TRUE, TRUE);
1908 if(!GLO_FOLDER_SPEC){
1909 build_path(tmp_20k_buf, VAR_MAIL_DIRECTORY, "[]", SIZEOF_20KBUF);
1910 GLO_FOLDER_SPEC = parse_list(tmp_20k_buf, 1, 0, NULL);
1913 set_current_val(&vars[V_FOLDER_SPEC], TRUE, TRUE);
1915 set_current_val(&vars[V_NNTP_SERVER], TRUE, TRUE);
1916 for(i = 0; VAR_NNTP_SERVER && VAR_NNTP_SERVER[i]; i++)
1917 removing_quotes(VAR_NNTP_SERVER[i]);
1919 set_news_spec_current_val(TRUE, TRUE);
1921 set_current_val(&vars[V_INBOX_PATH], TRUE, TRUE);
1923 set_current_val(&vars[V_USER_DOMAIN], TRUE, TRUE);
1924 if(VAR_USER_DOMAIN
1925 && VAR_USER_DOMAIN[0]
1926 && (p = strrindex(VAR_USER_DOMAIN, '@'))){
1927 if(*(++p)){
1928 char *q;
1930 snprintf(tmp_20k_buf, SIZEOF_20KBUF,
1931 "User-domain (%s) cannot contain \"@\", using \"%s\"",
1932 VAR_USER_DOMAIN, p);
1933 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
1934 q = VAR_USER_DOMAIN;
1935 while((*q++ = *p++) != '\0')
1936 ;/* do nothing */
1938 else{
1939 snprintf(tmp_20k_buf, SIZEOF_20KBUF,
1940 "User-domain (%s) cannot contain \"@\", deleting",
1941 VAR_USER_DOMAIN);
1942 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
1943 if(ps->vars[V_USER_DOMAIN].post_user_val.p){
1944 fs_give((void **)&ps->vars[V_USER_DOMAIN].post_user_val.p);
1945 set_current_val(&vars[V_USER_DOMAIN], TRUE, TRUE);
1948 if(VAR_USER_DOMAIN
1949 && VAR_USER_DOMAIN[0]
1950 && (p = strrindex(VAR_USER_DOMAIN, '@'))){
1951 if(ps->vars[V_USER_DOMAIN].main_user_val.p){
1952 fs_give((void **)&ps->vars[V_USER_DOMAIN].main_user_val.p);
1953 set_current_val(&vars[V_USER_DOMAIN], TRUE, TRUE);
1959 set_current_val(&vars[V_USE_ONLY_DOMAIN_NAME], TRUE, TRUE);
1960 set_current_val(&vars[V_REPLY_STRING], TRUE, TRUE);
1961 set_current_val(&vars[V_WORDSEPS], TRUE, TRUE);
1962 set_current_val(&vars[V_QUOTE_REPLACE_STRING], TRUE, TRUE);
1963 set_current_val(&vars[V_REPLY_INTRO], TRUE, TRUE);
1964 set_current_val(&vars[V_EMPTY_HDR_MSG], TRUE, TRUE);
1966 #ifdef ENABLE_LDAP
1967 set_current_val(&vars[V_LDAP_SERVERS], TRUE, TRUE);
1968 #endif /* ENABLE_LDAP */
1970 /* obsolete, backwards compatibility */
1971 set_current_val(&vars[V_HEADER_IN_REPLY], TRUE, TRUE);
1972 obs_header_in_reply=!strucmp(VAR_HEADER_IN_REPLY, "yes");
1974 set_current_val(&vars[V_PERSONAL_PRINT_COMMAND], TRUE, TRUE);
1975 set_current_val(&vars[V_STANDARD_PRINTER], TRUE, TRUE);
1976 set_current_val(&vars[V_PRINTER], TRUE, TRUE);
1977 if(vars[V_PERSONAL_PRINT_COMMAND].is_fixed && !vars[V_PRINTER].is_fixed)
1978 printer_value_check_and_adjust();
1980 set_current_val(&vars[V_LAST_TIME_PRUNE_QUESTION], TRUE, TRUE);
1981 if(VAR_LAST_TIME_PRUNE_QUESTION != NULL){
1982 /* The month value in the file runs from 1-12, the variable here
1983 runs from 0-11; the value in the file used to be 0-11, but we're
1984 fixing it in January */
1985 ps->last_expire_year = atoi(VAR_LAST_TIME_PRUNE_QUESTION);
1986 ps->last_expire_month =
1987 atoi(strindex(VAR_LAST_TIME_PRUNE_QUESTION, '.') + 1);
1988 if(ps->last_expire_month == 0){
1989 /* Fix for 0 because of old bug */
1990 snprintf(buf, sizeof(buf), "%d.%d", ps_global->last_expire_year,
1991 ps_global->last_expire_month + 1);
1992 set_variable(V_LAST_TIME_PRUNE_QUESTION, buf, 1, 1, Main);
1993 }else{
1994 ps->last_expire_month--;
1996 }else{
1997 ps->last_expire_year = -1;
1998 ps->last_expire_month = -1;
2001 set_current_val(&vars[V_BUGS_FULLNAME], TRUE, TRUE);
2002 set_current_val(&vars[V_BUGS_ADDRESS], TRUE, TRUE);
2003 set_current_val(&vars[V_SUGGEST_FULLNAME], TRUE, TRUE);
2004 set_current_val(&vars[V_SUGGEST_ADDRESS], TRUE, TRUE);
2005 set_current_val(&vars[V_LOCAL_FULLNAME], TRUE, TRUE);
2006 set_current_val(&vars[V_LOCAL_ADDRESS], TRUE, TRUE);
2007 set_current_val(&vars[V_BUGS_EXTRAS], TRUE, TRUE);
2008 set_current_val(&vars[V_KBLOCK_PASSWD_COUNT], TRUE, TRUE);
2009 set_current_val(&vars[V_DEFAULT_FCC], TRUE, TRUE);
2010 set_current_val(&vars[V_POSTPONED_FOLDER], TRUE, TRUE);
2011 set_current_val(&vars[V_TRASH_FOLDER], TRUE, TRUE);
2012 set_current_val(&vars[V_READ_MESSAGE_FOLDER], TRUE, TRUE);
2013 set_current_val(&vars[V_FORM_FOLDER], TRUE, TRUE);
2014 set_current_val(&vars[V_EDITOR], TRUE, TRUE);
2015 set_current_val(&vars[V_SPELLER], TRUE, TRUE);
2016 #ifdef _WINDOWS
2017 set_current_val(&vars[V_DICTIONARY], TRUE, TRUE);
2018 #endif /* _WINDOWS */
2019 set_current_val(&vars[V_IMAGE_VIEWER], TRUE, TRUE);
2020 set_current_val(&vars[V_BROWSER], TRUE, TRUE);
2021 set_current_val(&vars[V_SMTP_SERVER], TRUE, TRUE);
2022 set_current_val(&vars[V_COMP_HDRS], TRUE, TRUE);
2023 set_current_val(&vars[V_CUSTOM_HDRS], TRUE, TRUE);
2024 set_current_val(&vars[V_SENDMAIL_PATH], TRUE, TRUE);
2025 set_current_val(&vars[V_DISPLAY_FILTERS], TRUE, TRUE);
2026 set_current_val(&vars[V_SEND_FILTER], TRUE, TRUE);
2027 set_current_val(&vars[V_ALT_ADDRS], TRUE, TRUE);
2028 set_current_val(&vars[V_ABOOK_FORMATS], TRUE, TRUE);
2029 set_current_val(&vars[V_KW_BRACES], TRUE, TRUE);
2030 set_current_val(&vars[V_OPENING_SEP], TRUE, TRUE);
2031 set_current_val(&vars[V_UNK_CHAR_SET], TRUE, TRUE);
2032 #ifdef SMIME
2033 set_current_val(&vars[V_PUBLICCERT_DIR], TRUE, TRUE);
2034 set_current_val(&vars[V_PUBLICCERT_CONTAINER], TRUE, TRUE);
2035 set_current_val(&vars[V_PRIVATEKEY_DIR], TRUE, TRUE);
2036 set_current_val(&vars[V_PRIVATEKEY_CONTAINER], TRUE, TRUE);
2037 set_current_val(&vars[V_CACERT_DIR], TRUE, TRUE);
2038 set_current_val(&vars[V_CACERT_CONTAINER], TRUE, TRUE);
2039 #endif /* SMIME */
2041 set_current_val(&vars[V_KEYWORDS], TRUE, TRUE);
2042 ps_global->keywords = init_keyword_list(VAR_KEYWORDS);
2044 set_current_val(&vars[V_OPER_DIR], TRUE, TRUE);
2045 if(VAR_OPER_DIR && !VAR_OPER_DIR[0]){
2046 init_error(ps, SM_ORDER | SM_DING, 3, 5,
2047 "Setting operating-dir to the empty string is not allowed. Will be ignored.");
2048 fs_give((void **)&VAR_OPER_DIR);
2049 if(FIX_OPER_DIR)
2050 fs_give((void **)&FIX_OPER_DIR);
2051 if(GLO_OPER_DIR)
2052 fs_give((void **)&GLO_OPER_DIR);
2053 if(COM_OPER_DIR)
2054 fs_give((void **)&COM_OPER_DIR);
2055 if(ps_global->vars[V_OPER_DIR].post_user_val.p)
2056 fs_give((void **)&ps_global->vars[V_OPER_DIR].post_user_val.p);
2057 if(ps_global->vars[V_OPER_DIR].main_user_val.p)
2058 fs_give((void **)&ps_global->vars[V_OPER_DIR].main_user_val.p);
2061 set_current_val(&vars[V_PERSONAL_PRINT_CATEGORY], TRUE, TRUE);
2062 ps->printer_category = -1;
2063 if(VAR_PERSONAL_PRINT_CATEGORY != NULL)
2064 ps->printer_category = atoi(VAR_PERSONAL_PRINT_CATEGORY);
2066 if(ps->printer_category < 1 || ps->printer_category > 3){
2067 char **tt;
2068 char aname[100], wname[100];
2070 strncpy(aname, ANSI_PRINTER, sizeof(aname));
2071 aname[sizeof(aname)-1] = '\0';
2072 strncat(aname, "-no-formfeed", sizeof(aname)-strlen(aname)-1);
2073 strncpy(wname, WYSE_PRINTER, sizeof(wname));
2074 wname[sizeof(wname)-1] = '\0';
2075 strncat(wname, "-no-formfeed", sizeof(wname)-strlen(wname)-1);
2076 if(strucmp(VAR_PRINTER, ANSI_PRINTER) == 0
2077 || strucmp(VAR_PRINTER, aname) == 0
2078 || strucmp(VAR_PRINTER, WYSE_PRINTER) == 0
2079 || strucmp(VAR_PRINTER, wname) == 0)
2080 ps->printer_category = 1;
2081 else if(VAR_STANDARD_PRINTER && VAR_STANDARD_PRINTER[0]){
2082 for(tt = VAR_STANDARD_PRINTER; *tt; tt++)
2083 if(strucmp(VAR_PRINTER, *tt) == 0)
2084 break;
2086 if(*tt)
2087 ps->printer_category = 2;
2090 /* didn't find it yet */
2091 if(ps->printer_category < 1 || ps->printer_category > 3){
2092 if(VAR_PERSONAL_PRINT_COMMAND && VAR_PERSONAL_PRINT_COMMAND[0]){
2093 for(tt = VAR_PERSONAL_PRINT_COMMAND; *tt; tt++)
2094 if(strucmp(VAR_PRINTER, *tt) == 0)
2095 break;
2097 if(*tt)
2098 ps->printer_category = 3;
2103 set_current_val(&vars[V_SLEEP], TRUE, TRUE);
2104 ps->sleep = i = 60;
2105 if(SVAR_SLEEP(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2106 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2107 else
2108 ps->sleep = i;
2110 set_current_val(&vars[V_OVERLAP], TRUE, TRUE);
2111 ps->viewer_overlap = i = atoi(DF_OVERLAP);
2112 if(SVAR_OVERLAP(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2113 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2114 else
2115 ps->viewer_overlap = i;
2117 set_current_val(&vars[V_MARGIN], TRUE, TRUE);
2118 ps->scroll_margin = i = atoi(DF_MARGIN);
2119 if(SVAR_MARGIN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2120 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2121 else
2122 ps->scroll_margin = i;
2124 set_current_val(&vars[V_FILLCOL], TRUE, TRUE);
2125 ps->composer_fillcol = i = atoi(DF_FILLCOL);
2126 if(SVAR_FILLCOL(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2127 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2128 else
2129 ps->composer_fillcol = i;
2131 set_current_val(&vars[V_QUOTE_SUPPRESSION], TRUE, TRUE);
2132 ps->quote_suppression_threshold = i = atoi(DF_QUOTE_SUPPRESSION);
2133 if(SVAR_QUOTE_SUPPRESSION(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2134 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2135 else{
2136 if(i > 0 && i < Q_SUPP_LIMIT){
2137 snprintf(tmp_20k_buf, SIZEOF_20KBUF,
2138 "Ignoring Quote-Suppression-Threshold value of %.50s, see help",
2139 VAR_QUOTE_SUPPRESSION);
2140 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2142 else{
2143 if(i < 0 && i != Q_DEL_ALL)
2144 ps->quote_suppression_threshold = -i;
2145 else
2146 ps->quote_suppression_threshold = i;
2150 set_current_val(&vars[V_DEADLETS], TRUE, TRUE);
2151 ps->deadlets = i = atoi(DF_DEADLETS);
2152 if(SVAR_DEADLETS(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2153 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2154 else
2155 ps->deadlets = i;
2157 set_current_val(&vars[V_STATUS_MSG_DELAY], TRUE, TRUE);
2158 ps->status_msg_delay = i = 0;
2159 if(SVAR_MSGDLAY(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2160 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2161 else
2162 ps->status_msg_delay = i;
2164 set_current_val(&vars[V_ACTIVE_MSG_INTERVAL], TRUE, TRUE);
2165 ps->active_status_interval = i = 8;
2166 if(SVAR_ACTIVEINTERVAL(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2167 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2168 else
2169 ps->active_status_interval = i;
2171 set_current_val(&vars[V_REMOTE_ABOOK_HISTORY], TRUE, TRUE);
2172 ps->remote_abook_history = i = atoi(DF_REMOTE_ABOOK_HISTORY);
2173 if(SVAR_AB_HIST(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2174 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2175 else
2176 ps->remote_abook_history = i;
2178 set_current_val(&vars[V_REMOTE_ABOOK_VALIDITY], TRUE, TRUE);
2179 ps->remote_abook_validity = i = atoi(DF_REMOTE_ABOOK_VALIDITY);
2180 if(SVAR_AB_VALID(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2181 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2182 else
2183 ps->remote_abook_validity = i;
2185 set_current_val(&vars[V_USERINPUTTIMEO], TRUE, TRUE);
2186 ps->hours_to_timeout = i = 0;
2187 if(SVAR_USER_INPUT(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2188 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2189 else
2190 ps->hours_to_timeout = i;
2192 /* timeo is a regular extern int because it is referenced in pico */
2193 set_current_val(&vars[V_MAILCHECK], TRUE, TRUE);
2194 set_input_timeout(i = 15);
2195 if(SVAR_MAILCHK(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2196 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2197 else
2198 set_input_timeout(i);
2200 set_current_val(&vars[V_MAILCHECKNONCURR], TRUE, TRUE);
2201 ps->check_interval_for_noncurr = i = 0;
2202 if(SVAR_MAILCHKNONCURR(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2203 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2204 else
2205 ps->check_interval_for_noncurr = i;
2207 #ifdef DEBUGJOURNAL
2208 ps->debugmem = 1;
2209 #else
2210 ps->debugmem = 0;
2211 #endif
2213 i = 30;
2214 set_current_val(&vars[V_TCPOPENTIMEO], TRUE, TRUE);
2215 /* this is just for the error, we don't save the result */
2216 if(VAR_TCPOPENTIMEO && SVAR_TCP_OPEN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2217 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2219 i = 15;
2220 set_current_val(&vars[V_TCPREADWARNTIMEO], TRUE, TRUE);
2221 /* this is just for the error, we don't save the result */
2222 if(VAR_TCPREADWARNTIMEO && SVAR_TCP_READWARN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2223 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2225 i = 0;
2226 set_current_val(&vars[V_TCPWRITEWARNTIMEO], TRUE, TRUE);
2227 /* this is just for the error, we don't save the result */
2228 if(VAR_TCPWRITEWARNTIMEO && SVAR_TCP_WRITEWARN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2229 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2231 i = 15;
2232 set_current_val(&vars[V_RSHOPENTIMEO], TRUE, TRUE);
2233 /* this is just for the error, we don't save the result */
2234 if(VAR_RSHOPENTIMEO && SVAR_RSH_OPEN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2235 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2237 i = 15;
2238 set_current_val(&vars[V_SSHOPENTIMEO], TRUE, TRUE);
2239 /* this is just for the error, we don't save the result */
2240 if(VAR_SSHOPENTIMEO && SVAR_SSH_OPEN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2241 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2243 set_current_val(&vars[V_INCCHECKLIST], TRUE, TRUE);
2245 set_current_val(&vars[V_INCCHECKTIMEO], TRUE, TRUE);
2246 ps->inc_check_timeout = i = 5;
2247 if(SVAR_INC_CHECK_TIMEO(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2248 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2249 else
2250 ps->inc_check_timeout = i;
2252 set_current_val(&vars[V_INCCHECKINTERVAL], TRUE, TRUE);
2253 ps->inc_check_interval = i = 180;
2254 if(SVAR_INC_CHECK_INTERV(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2255 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2256 else
2257 ps->inc_check_interval = i;
2259 set_current_val(&vars[V_INC2NDCHECKINTERVAL], TRUE, TRUE);
2260 ps->inc_second_check_interval = i = 180;
2261 if(SVAR_INC_2NDCHECK_INTERV(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2262 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2263 else
2264 ps->inc_second_check_interval = i;
2266 rvl = 60L;
2267 set_current_val(&vars[V_MAILDROPCHECK], TRUE, TRUE);
2268 /* this is just for the error, we don't save the result */
2269 if(VAR_MAILDROPCHECK && SVAR_MAILDCHK(ps, rvl, tmp_20k_buf, SIZEOF_20KBUF))
2270 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2272 rvl = 0L;
2273 set_current_val(&vars[V_NNTPRANGE], TRUE, TRUE);
2274 /* this is just for the error, we don't save the result */
2275 if(VAR_NNTPRANGE && SVAR_NNTPRANGE(ps, rvl, tmp_20k_buf, SIZEOF_20KBUF))
2276 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2278 set_current_val(&vars[V_TCPQUERYTIMEO], TRUE, TRUE);
2279 ps->tcp_query_timeout = i = TO_BAIL_THRESHOLD;
2280 if(VAR_TCPQUERYTIMEO && SVAR_TCP_QUERY(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2281 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2282 else
2283 ps->tcp_query_timeout = i;
2285 set_current_val(&vars[V_NEWSRC_PATH], TRUE, TRUE);
2286 if(VAR_NEWSRC_PATH && VAR_NEWSRC_PATH[0])
2287 mail_parameters(NULL, SET_NEWSRC, (void *)VAR_NEWSRC_PATH);
2289 set_current_val(&vars[V_NEWS_ACTIVE_PATH], TRUE, TRUE);
2290 if(VAR_NEWS_ACTIVE_PATH)
2291 mail_parameters(NULL, SET_NEWSACTIVE,
2292 (void *)VAR_NEWS_ACTIVE_PATH);
2294 set_current_val(&vars[V_NEWS_SPOOL_DIR], TRUE, TRUE);
2295 if(VAR_NEWS_SPOOL_DIR)
2296 mail_parameters(NULL, SET_NEWSSPOOL,
2297 (void *)VAR_NEWS_SPOOL_DIR);
2299 /* guarantee a save default */
2300 set_current_val(&vars[V_DEFAULT_SAVE_FOLDER], TRUE, TRUE);
2301 if(!VAR_DEFAULT_SAVE_FOLDER || !VAR_DEFAULT_SAVE_FOLDER[0])
2302 set_variable(V_DEFAULT_SAVE_FOLDER,
2303 (GLO_DEFAULT_SAVE_FOLDER && GLO_DEFAULT_SAVE_FOLDER[0])
2304 ? GLO_DEFAULT_SAVE_FOLDER
2305 : DEFAULT_SAVE, 1, 0, Main);
2307 set_current_val(&vars[V_SIGNATURE_FILE], TRUE, TRUE);
2308 set_current_val(&vars[V_LITERAL_SIG], TRUE, TRUE);
2309 set_current_val(&vars[V_GLOB_ADDRBOOK], TRUE, TRUE);
2310 set_current_val(&vars[V_ADDRESSBOOK], TRUE, TRUE);
2311 set_current_val(&vars[V_FORCED_ABOOK_ENTRY], TRUE, TRUE);
2312 set_current_val(&vars[V_DISABLE_DRIVERS], TRUE, TRUE);
2313 set_current_val(&vars[V_DISABLE_AUTHS], TRUE, TRUE);
2315 set_current_val(&vars[V_VIEW_HEADERS], TRUE, TRUE);
2316 /* strip spaces and colons */
2317 if(ps->VAR_VIEW_HEADERS){
2318 for(s = ps->VAR_VIEW_HEADERS; (q = *s) != NULL; s++){
2319 if(q[0]){
2320 removing_leading_white_space(q);
2321 /* look for colon or space or end */
2322 for(p = q; *p && !isspace((unsigned char)*p) && *p != ':'; p++)
2323 ;/* do nothing */
2325 *p = '\0';
2326 if(strucmp(q, ALL_EXCEPT) == 0)
2327 ps->view_all_except = 1;
2332 set_current_val(&vars[V_VIEW_MARGIN_LEFT], TRUE, TRUE);
2333 set_current_val(&vars[V_VIEW_MARGIN_RIGHT], TRUE, TRUE);
2334 set_current_val(&vars[V_UPLOAD_CMD], TRUE, TRUE);
2335 set_current_val(&vars[V_UPLOAD_CMD_PREFIX], TRUE, TRUE);
2336 set_current_val(&vars[V_DOWNLOAD_CMD], TRUE, TRUE);
2337 set_current_val(&vars[V_DOWNLOAD_CMD_PREFIX], TRUE, TRUE);
2338 set_current_val(&vars[V_MAILCAP_PATH], TRUE, TRUE);
2339 set_current_val(&vars[V_MIMETYPE_PATH], TRUE, TRUE);
2340 #if !defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)
2341 set_current_val(&vars[V_FIFOPATH], TRUE, TRUE);
2342 #endif
2344 set_current_val(&vars[V_RSHPATH], TRUE, TRUE);
2345 if(VAR_RSHPATH
2346 && is_absolute_path(VAR_RSHPATH)
2347 && can_access(VAR_RSHPATH, EXECUTE_ACCESS) == 0){
2348 mail_parameters(NULL, SET_RSHPATH, (void *) VAR_RSHPATH);
2351 set_current_val(&vars[V_RSHCMD], TRUE, TRUE);
2352 if(VAR_RSHCMD){
2353 mail_parameters(NULL, SET_RSHCOMMAND, (void *) VAR_RSHCMD);
2356 set_current_val(&vars[V_SSHPATH], TRUE, TRUE);
2357 if(VAR_SSHPATH) {
2358 if(is_absolute_path(VAR_SSHPATH)
2359 && can_access(VAR_SSHPATH, EXECUTE_ACCESS) == 0){
2360 mail_parameters(NULL, SET_SSHPATH, (void *) VAR_SSHPATH);
2362 else {
2363 mail_parameters(NULL, SET_SSHPATH, (void *) NULL);
2367 set_current_val(&vars[V_SSHCMD], TRUE, TRUE);
2368 if(VAR_SSHCMD) {
2369 if(VAR_SSHCMD[0]) {
2370 mail_parameters(NULL, SET_SSHCOMMAND, (void *) VAR_SSHCMD);
2372 else {
2373 mail_parameters(NULL, SET_SSHCOMMAND, (void *) NULL);
2377 #if defined(DOS) || defined(OS2)
2379 set_current_val(&vars[V_FILE_DIR], TRUE, TRUE);
2381 #ifdef _WINDOWS
2382 set_current_val(&vars[V_FONT_NAME], TRUE, TRUE);
2383 set_current_val(&vars[V_FONT_SIZE], TRUE, TRUE);
2384 set_current_val(&vars[V_FONT_STYLE], TRUE, TRUE);
2385 set_current_val(&vars[V_FONT_CHAR_SET], TRUE, TRUE);
2386 set_current_val(&vars[V_CURSOR_STYLE], TRUE, TRUE);
2387 set_current_val(&vars[V_WINDOW_POSITION], TRUE, TRUE);
2389 if(F_OFF(F_STORE_WINPOS_IN_CONFIG, ps_global)){
2390 /* if win position is in the registry, use it */
2391 if(mswin_reg(MSWR_OP_GET, MSWR_PINE_POS, buf, sizeof(buf))){
2392 if(VAR_WINDOW_POSITION)
2393 fs_give((void **)&VAR_WINDOW_POSITION);
2395 VAR_WINDOW_POSITION = cpystr(buf);
2397 else if(VAR_WINDOW_POSITION
2398 && (ps->update_registry != UREG_NEVER_SET)){
2399 /* otherwise, put it there */
2400 mswin_reg(MSWR_OP_SET | ((ps->update_registry == UREG_ALWAYS_SET)
2401 ? MSWR_OP_FORCE : 0),
2402 MSWR_PINE_POS,
2403 VAR_WINDOW_POSITION, (size_t)NULL);
2407 mswin_setwindow (VAR_FONT_NAME, VAR_FONT_SIZE,
2408 VAR_FONT_STYLE, VAR_WINDOW_POSITION,
2409 VAR_CURSOR_STYLE, VAR_FONT_CHAR_SET);
2411 /* this is no longer used */
2412 if(VAR_WINDOW_POSITION)
2413 fs_give((void **)&VAR_WINDOW_POSITION);
2415 set_current_val(&vars[V_PRINT_FONT_NAME], TRUE, TRUE);
2416 set_current_val(&vars[V_PRINT_FONT_SIZE], TRUE, TRUE);
2417 set_current_val(&vars[V_PRINT_FONT_STYLE], TRUE, TRUE);
2418 set_current_val(&vars[V_PRINT_FONT_CHAR_SET], TRUE, TRUE);
2419 mswin_setprintfont (VAR_PRINT_FONT_NAME,
2420 VAR_PRINT_FONT_SIZE,
2421 VAR_PRINT_FONT_STYLE,
2422 VAR_PRINT_FONT_CHAR_SET);
2424 mswin_setgenhelptextcallback(pcpine_general_help);
2426 mswin_setclosetext ("Use the \"Q\" command to exit Alpine.");
2429 char foreColor[64], backColor[64];
2431 mswin_getwindow(NULL, 0, NULL, 0, NULL, 0, NULL, 0,
2432 foreColor, sizeof(foreColor), backColor, sizeof(backColor),
2433 NULL, 0, NULL, 0);
2434 if(!GLO_NORM_FORE_COLOR)
2435 GLO_NORM_FORE_COLOR = cpystr(foreColor);
2437 if(!GLO_NORM_BACK_COLOR)
2438 GLO_NORM_BACK_COLOR = cpystr(backColor);
2440 #endif /* _WINDOWS */
2441 #endif /* DOS */
2444 * We want the version number to start out as 1.0 for Alpine, but
2445 * we also want to use the same old config file that was used
2446 * with Pine. The Pine version numbers made it up to 4.64 and we
2447 * want Alpine's 1.0 to be larger than 4.64 so we keep a separate
2448 * internal version number which is the real version number
2449 * plus 4. That's what gets written in LAST_VERS_USED.
2451 strncpy(ps->vers_internal, ALPINE_VERSION, sizeof(ps->vers_internal));
2452 ps->vers_internal[sizeof(ps->vers_internal)-1] = '\0';
2453 if(isdigit(ps->vers_internal[0]) && ps->vers_internal[0] < '6')
2454 ps->vers_internal[0] = ps->vers_internal[0] + 4;
2456 set_current_val(&vars[V_LAST_VERS_USED], TRUE, TRUE);
2457 /* Check for special cases first */
2458 if(VAR_LAST_VERS_USED
2459 && (isdigit(ps->vers_internal[0])
2460 && ps->vers_internal[1] == '.'
2461 && isdigit((unsigned char)ps->vers_internal[2])
2462 && isdigit((unsigned char)ps->vers_internal[3])
2463 && isalpha((unsigned char)ps->vers_internal[4])
2464 && strncmp(VAR_LAST_VERS_USED, ps->vers_internal, 4) >= 0)){
2465 ps->show_new_version = 0;
2467 /* Otherwise just do lexicographic comparision... */
2468 else if(VAR_LAST_VERS_USED
2469 && strcmp(VAR_LAST_VERS_USED, ps->vers_internal) >= 0){
2470 ps->show_new_version = 0;
2472 else{
2473 #ifdef _WINDOWS
2475 * If this is the first time we've run a version > 4.40, and there
2476 * is evidence that the config file has not been used by unix pine,
2477 * then we convert color008 to colorlgr, color009 to colormgr, and
2478 * color010 to colordgr. If the config file is being used by
2479 * unix pine then color009 may really supposed to be red, etc.
2480 * Same if we've already run 4.41 or higher. We don't have to do
2481 * anything if we are new to alpine.
2483 ps->pre441 = (VAR_LAST_VERS_USED
2484 && strcmp(VAR_LAST_VERS_USED, "4.40") <= 0);
2485 #endif /* _WINDOWS */
2488 * Don't offer the new version message if we're told not to.
2490 set_current_val(&vars[V_NEW_VER_QUELL], TRUE, TRUE);
2491 ps->show_new_version = !(VAR_NEW_VER_QUELL
2492 && strcmp(ps->vers_internal,
2493 VAR_NEW_VER_QUELL) < 0);
2495 #ifdef _WINDOWS
2496 if(!ps_global->install_flag)
2497 #endif /* _WINDOWS */
2499 if(VAR_LAST_VERS_USED){
2500 strncpy(ps_global->pine_pre_vers, VAR_LAST_VERS_USED,
2501 sizeof(ps_global->pine_pre_vers));
2502 ps_global->pine_pre_vers[sizeof(ps_global->pine_pre_vers)-1] = '\0';
2505 set_variable(V_LAST_VERS_USED, ps->vers_internal, 1, 1,
2506 ps_global->ew_for_except_vars);
2510 /* Obsolete, backwards compatibility */
2511 set_current_val(&vars[V_ELM_STYLE_SAVE], TRUE, TRUE);
2512 /* Also obsolete */
2513 set_current_val(&vars[V_SAVE_BY_SENDER], TRUE, TRUE);
2514 if(!strucmp(VAR_ELM_STYLE_SAVE, "yes"))
2515 set_variable(V_SAVE_BY_SENDER, "yes", 1, 1, Main);
2516 obs_save_by_sender = !strucmp(VAR_SAVE_BY_SENDER, "yes");
2518 set_current_pattern_vals(ps);
2520 set_current_val(&vars[V_INDEX_FORMAT], TRUE, TRUE);
2521 init_index_format(VAR_INDEX_FORMAT, &ps->index_disp_format);
2523 /* this should come after pre441 is set or not */
2524 set_current_color_vals(ps);
2526 set_current_val(&vars[V_RSS_NEWS], TRUE, TRUE);
2527 set_current_val(&vars[V_RSS_WEATHER], TRUE, TRUE);
2528 set_current_val(&vars[V_WP_INDEXHEIGHT], TRUE, TRUE);
2529 set_current_val(&vars[V_WP_INDEXLINES], TRUE, TRUE);
2530 set_current_val(&vars[V_WP_AGGSTATE], TRUE, TRUE);
2531 set_current_val(&vars[V_WP_STATE], TRUE, TRUE);
2532 set_current_val(&vars[V_WP_COLUMNS], TRUE, TRUE);
2534 set_current_val(&vars[V_PRUNED_FOLDERS], TRUE, TRUE);
2535 set_current_val(&vars[V_ARCHIVED_FOLDERS], TRUE, TRUE);
2536 set_current_val(&vars[V_INCOMING_FOLDERS], TRUE, TRUE);
2537 set_current_val(&vars[V_SORT_KEY], TRUE, TRUE);
2538 if(decode_sort(VAR_SORT_KEY, &ps->def_sort, &def_sort_rev) == -1){
2539 snprintf(tmp_20k_buf, SIZEOF_20KBUF, "Sort type \"%.200s\" is invalid", VAR_SORT_KEY);
2540 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2541 ps->def_sort = SortArrival;
2542 ps->def_sort_rev = 0;
2544 else
2545 ps->def_sort_rev = def_sort_rev;
2547 cur_rule_value(&vars[V_SAVED_MSG_NAME_RULE], TRUE, TRUE);
2548 {NAMEVAL_S *v; int i;
2549 for(i = 0; (v = save_msg_rules(i)); i++)
2550 if(v->value == ps_global->save_msg_rule)
2551 break;
2553 /* if save_msg_rule is not default, or is explicitly set to default */
2554 if((ps_global->save_msg_rule != SAV_RULE_DEFLT) ||
2555 (v && v->name &&
2556 (!strucmp(ps_global->vars[V_SAVED_MSG_NAME_RULE].post_user_val.p,
2557 v->name) ||
2558 !strucmp(ps_global->vars[V_SAVED_MSG_NAME_RULE].main_user_val.p,
2559 v->name))))
2560 obs_save_by_sender = 0; /* don't overwrite */
2563 cur_rule_value(&vars[V_FCC_RULE], TRUE, TRUE);
2564 cur_rule_value(&vars[V_AB_SORT_RULE], TRUE, TRUE);
2566 #ifndef _WINDOWS
2567 cur_rule_value(&vars[V_COLOR_STYLE], TRUE, TRUE);
2568 #endif
2570 cur_rule_value(&vars[V_INDEX_COLOR_STYLE], TRUE, TRUE);
2571 cur_rule_value(&vars[V_TITLEBAR_COLOR_STYLE], TRUE, TRUE);
2572 cur_rule_value(&vars[V_FLD_SORT_RULE], TRUE, TRUE);
2573 cur_rule_value(&vars[V_INCOMING_STARTUP], TRUE, TRUE);
2574 cur_rule_value(&vars[V_PRUNING_RULE], TRUE, TRUE);
2575 cur_rule_value(&vars[V_REOPEN_RULE], TRUE, TRUE);
2576 cur_rule_value(&vars[V_GOTO_DEFAULT_RULE], TRUE, TRUE);
2577 cur_rule_value(&vars[V_THREAD_DISP_STYLE], TRUE, TRUE);
2578 cur_rule_value(&vars[V_THREAD_INDEX_STYLE], TRUE, TRUE);
2580 set_current_val(&vars[V_THREAD_MORE_CHAR], TRUE, TRUE);
2581 if(VAR_THREAD_MORE_CHAR[0] && VAR_THREAD_MORE_CHAR[1]){
2582 init_error(ps, SM_ORDER | SM_DING, 3, 5,
2583 _("Only using first character of threading-indicator-character option"));
2584 VAR_THREAD_MORE_CHAR[1] = '\0';
2587 set_current_val(&vars[V_THREAD_EXP_CHAR], TRUE, TRUE);
2588 if(VAR_THREAD_EXP_CHAR[0] && VAR_THREAD_EXP_CHAR[1]){
2589 init_error(ps, SM_ORDER | SM_DING, 3, 5,
2590 _("Only using first character of threading-expanded-character option"));
2591 VAR_THREAD_EXP_CHAR[1] = '\0';
2594 set_current_val(&vars[V_THREAD_LASTREPLY_CHAR], TRUE, TRUE);
2595 if(!VAR_THREAD_LASTREPLY_CHAR[0])
2596 VAR_THREAD_LASTREPLY_CHAR = cpystr(DF_THREAD_LASTREPLY_CHAR);
2598 if(VAR_THREAD_LASTREPLY_CHAR[0] && VAR_THREAD_LASTREPLY_CHAR[1]){
2599 init_error(ps, SM_ORDER | SM_DING, 3, 5,
2600 _("Only using first character of threading-lastreply-character option"));
2601 VAR_THREAD_LASTREPLY_CHAR[1] = '\0';
2604 set_current_val(&vars[V_MAXREMSTREAM], TRUE, TRUE);
2605 ps->s_pool.max_remstream = i = atoi(DF_MAXREMSTREAM);
2606 if(SVAR_MAXREMSTREAM(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2607 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2608 else
2609 ps->s_pool.max_remstream = i;
2611 set_current_val(&vars[V_PERMLOCKED], TRUE, TRUE);
2613 set_current_val(&vars[V_NMW_WIDTH], TRUE, TRUE);
2614 ps->nmw_width = i = atoi(DF_NMW_WIDTH);
2615 if(SVAR_NMW_WIDTH(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2616 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2617 else
2618 ps->nmw_width = i;
2620 /* backwards compatibility */
2621 if(obs_save_by_sender){
2622 ps->save_msg_rule = SAV_RULE_FROM;
2623 set_variable(V_SAVED_MSG_NAME_RULE, "by-from", 1, 1, Main);
2626 /* this should come after process_feature_list because of use_fkeys */
2627 if(!ps->start_in_index)
2628 set_current_val(&vars[V_INIT_CMD_LIST], FALSE, TRUE);
2629 if(VAR_INIT_CMD_LIST && VAR_INIT_CMD_LIST[0] && VAR_INIT_CMD_LIST[0][0])
2630 if(cmds_f)
2631 (*cmds_f)(ps, VAR_INIT_CMD_LIST);
2633 #ifdef _WINDOWS
2634 mswin_set_quit_confirm (F_OFF(F_QUIT_WO_CONFIRM, ps_global));
2635 #endif /* _WINDOWS */
2637 #ifdef DEBUG
2638 dump_configuration(0);
2639 #endif /* DEBUG */
2643 void
2644 convert_configvars_to_utf8(struct variable *vars, char *fromcharset)
2646 struct variable *v;
2649 * Make sure that everything is UTF-8.
2651 for(v = vars; v->name; v++)
2652 convert_configvar_to_utf8(v, fromcharset);
2656 void
2657 convert_configvar_to_utf8(struct variable *v, char *fromcharset)
2659 char **p, *conv, **valptr;
2660 int i;
2663 * Make sure that everything is UTF-8.
2665 if(v->is_list){
2666 for(i = 0; i < 7; i++){
2667 switch(i){
2668 case 1: valptr = v->current_val.l; break;
2669 case 0: valptr = v->main_user_val.l; break;
2670 case 2: valptr = v->changed_val.l; break;
2671 case 3: valptr = v->post_user_val.l; break;
2672 case 4: valptr = v->global_val.l; break;
2673 case 5: valptr = v->fixed_val.l; break;
2674 case 6: valptr = v->cmdline_val.l; break;
2675 default: alpine_panic("bad case in convert_configvar");
2678 if(valptr){
2679 for(p = valptr; *p; p++){
2680 if(**p){
2681 conv = convert_to_utf8(*p, fromcharset, 0);
2682 if(conv){
2683 fs_give((void **) p);
2684 *p = conv;
2691 else{
2692 for(i = 0; i < 7; i++){
2693 switch(i){
2694 case 1: valptr = &v->current_val.p; break;
2695 case 0: valptr = &v->main_user_val.p; break;
2696 case 2: valptr = &v->changed_val.p; break;
2697 case 3: valptr = &v->post_user_val.p; break;
2698 case 4: valptr = &v->global_val.p; break;
2699 case 5: valptr = &v->fixed_val.p; break;
2700 case 6: valptr = &v->cmdline_val.p; break;
2701 default: alpine_panic("bad case in convert_configvar");
2704 if(valptr && *valptr && (*valptr)[0]){
2705 conv = convert_to_utf8(*valptr, fromcharset, 0);
2706 if(conv){
2707 fs_give((void **) valptr);
2708 *valptr = conv;
2718 * Standard feature name sections
2720 char *
2721 feature_list_section(FEATURE_S *feature)
2723 #define PREF_NONE -1
2724 static char *feat_sect[] = {
2725 #define PREF_MISC 0
2726 /* TRANSLATORS: section heading in configuration screen */
2727 N_("Advanced User Preferences"),
2728 #define PREF_FLDR 1
2729 /* TRANSLATORS: section heading in configuration screen */
2730 N_("Folder Preferences"),
2731 #define PREF_ADDR 2
2732 /* TRANSLATORS: section heading in configuration screen */
2733 N_("Address Book Preferences"),
2734 #define PREF_COMP 3
2735 /* TRANSLATORS: section heading in configuration screen */
2736 N_("Composer Preferences"),
2737 #define PREF_NEWS 4
2738 /* TRANSLATORS: section heading in configuration screen */
2739 N_("News Preferences"),
2740 #define PREF_VIEW 5
2741 /* TRANSLATORS: section heading in configuration screen */
2742 N_("Viewer Preferences"),
2743 #define PREF_ACMD 6
2744 /* TRANSLATORS: section heading in configuration screen */
2745 N_("Advanced Command Preferences"),
2746 #define PREF_PRNT 7
2747 /* TRANSLATORS: section heading in configuration screen */
2748 N_("Printer Preferences"),
2749 #define PREF_RPLY 8
2750 /* TRANSLATORS: section heading in configuration screen */
2751 N_("Reply Preferences"),
2752 #define PREF_SEND 9
2753 /* TRANSLATORS: section heading in configuration screen */
2754 N_("Sending Preferences"),
2755 #define PREF_INDX 10
2756 /* TRANSLATORS: section heading in configuration screen */
2757 N_("Message Index Preferences"),
2758 #define PREF_HIDDEN 11
2759 HIDDEN_PREF
2762 return((feature && feature->section > PREF_NONE
2763 && feature->section < (sizeof(feat_sect)/sizeof(feat_sect[0])))
2764 ? _(feat_sect[feature->section]) : NULL);
2768 /* any os-specific exclusions */
2769 #if defined(DOS) || defined(OS2)
2770 #define PREF_OS_LWSD PREF_NONE
2771 #define PREF_OS_LCLK PREF_NONE
2772 #define PREF_OS_STSP PREF_NONE
2773 #define PREF_OS_SPWN PREF_NONE
2774 #define PREF_OS_XNML PREF_NONE
2775 #define PREF_OS_USFK PREF_MISC
2776 #define PREF_OS_MOUSE PREF_NONE
2777 #else
2778 #define PREF_OS_LWSD PREF_MISC
2779 #define PREF_OS_LCLK PREF_COMP
2780 #define PREF_OS_STSP PREF_MISC
2781 #define PREF_OS_SPWN PREF_MISC
2782 #define PREF_OS_XNML PREF_MISC
2783 #define PREF_OS_USFK PREF_NONE
2784 #define PREF_OS_MOUSE PREF_MISC
2785 #endif
2789 * Standard way to get at feature list members...
2791 FEATURE_S *
2792 feature_list(int index)
2795 * This list is alphabatized by feature string, but the
2796 * macro values need not be ordered.
2798 static FEATURE_S feat_list[] = {
2799 /* Composer prefs */
2800 {"allow-changing-from", NULL,
2801 F_ALLOW_CHANGING_FROM, h_config_allow_chg_from, PREF_COMP, 1},
2802 {"alternate-compose-menu", NULL,
2803 F_ALT_COMPOSE_MENU, h_config_alt_compose_menu, PREF_COMP, 0},
2804 {"alternate-role-menu", "Alternate Role (#) Menu",
2805 F_ALT_ROLE_MENU, h_config_alt_role_menu, PREF_COMP, 0},
2806 {"compose-cancel-confirm-uses-yes", NULL,
2807 F_CANCEL_CONFIRM, h_config_cancel_confirm, PREF_COMP, 0},
2808 {"compose-rejects-unqualified-addrs", "Compose Rejects Unqualified Addresses",
2809 F_COMPOSE_REJECTS_UNQUAL, h_config_compose_rejects_unqual, PREF_COMP, 0},
2810 {"compose-send-offers-first-filter", NULL,
2811 F_FIRST_SEND_FILTER_DFLT, h_config_send_filter_dflt, PREF_COMP, 0},
2812 {"compose-cut-from-cursor", "Ctrl-K Cuts From Cursor",
2813 F_DEL_FROM_DOT, h_config_del_from_dot, PREF_COMP, 0},
2814 {"compose-maps-delete-key-to-ctrl-d", "Delete Key Maps to Ctrl-D",
2815 F_COMPOSE_MAPS_DEL, h_config_compose_maps_del, PREF_COMP, 0},
2816 {"quell-dead-letter-on-cancel", "Do Not Save to Deadletter on Cancel",
2817 F_QUELL_DEAD_LETTER, h_config_quell_dead_letter, PREF_COMP, 0},
2818 {"enable-alternate-editor-cmd", "Enable Alternate Editor Command",
2819 F_ENABLE_ALT_ED, h_config_enable_alt_ed, PREF_COMP, 1},
2820 {"enable-alternate-editor-implicitly", NULL,
2821 F_ALT_ED_NOW, h_config_alt_ed_now, PREF_COMP, 0},
2822 {"enable-search-and-replace", "Enable Search and Replace",
2823 F_ENABLE_SEARCH_AND_REPL, h_config_enable_search_and_repl, PREF_COMP, 1},
2824 {"enable-sigdashes", NULL,
2825 F_ENABLE_SIGDASHES, h_config_sigdashes, PREF_COMP, 0},
2826 {"quell-mailchecks-composing-except-inbox", "Prevent Mailchecks While Composing Except for INBOX",
2827 F_QUELL_PINGS_COMPOSING, h_config_quell_checks_comp, PREF_COMP, 0},
2828 {"quell-mailchecks-composing-inbox", "Prevent Mailchecks While Composing for INBOX",
2829 F_QUELL_PINGS_COMPOSING_INBOX, h_config_quell_checks_comp_inbox, PREF_COMP, 0},
2830 {"quell-user-lookup-in-passwd-file", "Prevent User Lookup in Password File",
2831 F_QUELL_LOCAL_LOOKUP, h_config_quell_local_lookup, PREF_OS_LCLK, 0},
2832 {"spell-check-before-sending", NULL,
2833 F_ALWAYS_SPELL_CHECK, h_config_always_spell_check, PREF_COMP, 0},
2835 /* Reply Prefs */
2836 {"copy-to-address-to-from-if-it-is-us", "Copy To Address to From if it is Us",
2837 F_COPY_TO_TO_FROM, h_config_copy_to_to_from, PREF_RPLY, 0},
2838 {"enable-reply-indent-string-editing", NULL,
2839 F_ENABLE_EDIT_REPLY_INDENT, h_config_prefix_editing, PREF_RPLY, 0},
2840 {"include-attachments-in-reply", "Include Attachments in Reply",
2841 F_ATTACHMENTS_IN_REPLY, h_config_attach_in_reply, PREF_RPLY, 0},
2842 {"include-header-in-reply", "Include Header in Reply",
2843 F_INCLUDE_HEADER, h_config_include_header, PREF_RPLY, 0},
2844 {"include-text-in-reply", "Include Text in Reply",
2845 F_AUTO_INCLUDE_IN_REPLY, h_config_auto_include_reply, PREF_RPLY, 0},
2846 {"reply-always-uses-reply-to", "Reply Always Uses Reply-To",
2847 F_AUTO_REPLY_TO, h_config_auto_reply_to, PREF_RPLY, 0},
2848 {"signature-at-bottom", "Signature at Bottom",
2849 F_SIG_AT_BOTTOM, h_config_sig_at_bottom, PREF_RPLY, 0},
2850 {"strip-from-sigdashes-on-reply", "Strip From Sigdashes on Reply",
2851 F_ENABLE_STRIP_SIGDASHES, h_config_strip_sigdashes, PREF_RPLY, 0},
2852 {"forward-as-attachment", "Forward messages as attachments",
2853 F_FORWARD_AS_ATTACHMENT, h_config_forward_as_attachment, PREF_RPLY, 0},
2854 {"preserve-original-fields", NULL,
2855 F_PRESERVE_ORIGINAL_FIELD, h_config_preserve_field, PREF_RPLY, 0},
2857 /* Sending Prefs */
2858 {"disable-sender", "Do Not Generate Sender Header",
2859 F_DISABLE_SENDER, h_config_disable_sender, PREF_SEND, 0},
2860 {"use-sender-not-x-sender", "Use Sender Instead of X-X-Sender",
2861 F_USE_SENDER_NOT_X, h_config_use_sender_not_x, PREF_SEND, 0},
2862 {"quell-flowed-text", "Do Not Send Flowed Text",
2863 F_QUELL_FLOWED_TEXT, h_config_quell_flowed_text, PREF_SEND, 0},
2864 {"downgrade-multipart-to-text", "Downgrade Multipart to Text",
2865 F_COMPOSE_ALWAYS_DOWNGRADE, h_downgrade_multipart_to_text, PREF_SEND, 0},
2866 {"enable-8bit-esmtp-negotiation", "Enable 8bit ESMTP Negotiation",
2867 F_ENABLE_8BIT, h_config_8bit_smtp, PREF_SEND, 1},
2868 #ifdef BACKGROUND_POST
2869 {"enable-background-sending", NULL,
2870 F_BACKGROUND_POST, h_config_compose_bg_post, PREF_SEND, 0},
2871 #endif
2872 {"enable-delivery-status-notification", NULL,
2873 F_DSN, h_config_compose_dsn, PREF_SEND, 0},
2874 {"enable-verbose-smtp-posting", "Enable Verbose SMTP Posting",
2875 F_VERBOSE_POST, h_config_verbose_post, PREF_SEND, 0},
2876 {"fcc-without-attachments", "Fcc Does Not Include Attachments",
2877 F_NO_FCC_ATTACH, h_config_no_fcc_attach, PREF_SEND, 0},
2878 {"fcc-on-bounce", "Include Fcc When Bouncing Messages",
2879 F_FCC_ON_BOUNCE, h_config_fcc_on_bounce, PREF_SEND, 0},
2880 {"mark-fcc-seen", NULL,
2881 F_MARK_FCC_SEEN, h_config_mark_fcc_seen, PREF_SEND, 0},
2882 {"fcc-only-without-confirm", "Send to Fcc Only Without Confirming",
2883 F_AUTO_FCC_ONLY, h_config_auto_fcc_only, PREF_SEND, 0},
2884 {"send-without-confirm", "Send Without Confirming",
2885 F_SEND_WO_CONFIRM, h_config_send_wo_confirm, PREF_SEND, 0},
2886 {"strip-whitespace-before-send", "Strip Whitespace Before Sending",
2887 F_STRIP_WS_BEFORE_SEND, h_config_strip_ws_before_send, PREF_SEND, 0},
2888 {"warn-if-blank-fcc", "Warn if Blank Fcc",
2889 F_WARN_ABOUT_NO_FCC, h_config_warn_if_fcc_blank, PREF_SEND, 0},
2890 {"warn-if-blank-subject", "Warn if Blank Subject",
2891 F_WARN_ABOUT_NO_SUBJECT, h_config_warn_if_subj_blank, PREF_SEND, 0},
2892 {"warn-if-blank-to-and-cc-and-newsgroups", "Warn if Blank To and CC and Newsgroups",
2893 F_WARN_ABOUT_NO_TO_OR_CC, h_config_warn_if_no_to_or_cc, PREF_SEND, 0},
2895 /* Folder */
2896 {"combined-folder-display", NULL,
2897 F_CMBND_FOLDER_DISP, h_config_combined_folder_display, PREF_FLDR, 0},
2898 {"combined-subdirectory-display", NULL,
2899 F_CMBND_SUBDIR_DISP, h_config_combined_subdir_display, PREF_FLDR, 0},
2900 {"enable-lame-list-mode", "Compensate for Deficient IMAP servers",
2901 F_FIX_BROKEN_LIST, h_config_lame_list_mode, PREF_FLDR, 0},
2902 {"enable-dot-folders", "Enable Hidden Folders",
2903 F_ENABLE_DOT_FOLDERS, h_config_enable_dot_folders, PREF_FLDR, 0},
2904 {"enable-incoming-folders", "Enable Incoming Folders Collection",
2905 F_ENABLE_INCOMING, h_config_enable_incoming, PREF_FLDR, 0},
2906 {"enable-incoming-folders-checking", NULL,
2907 F_ENABLE_INCOMING_CHECKING, h_config_enable_incoming_checking, PREF_FLDR, 0},
2908 {"incoming-checking-includes-total", NULL,
2909 F_INCOMING_CHECKING_TOTAL, h_config_incoming_checking_total, PREF_FLDR, 0},
2910 {"incoming-checking-uses-recent", NULL,
2911 F_INCOMING_CHECKING_RECENT, h_config_incoming_checking_recent, PREF_FLDR, 0},
2912 {"expanded-view-of-folders", "Expanded View of Folders",
2913 F_EXPANDED_FOLDERS, h_config_expanded_folders, PREF_FLDR, 0},
2914 {"quell-empty-directories", "Hide Empty Directories",
2915 F_QUELL_EMPTY_DIRS, h_config_quell_empty_dirs, PREF_FLDR, 0},
2916 {"separate-folder-and-directory-entries", "Separate Folder and Directory Entries",
2917 F_SEPARATE_FLDR_AS_DIR, h_config_separate_fold_dir_view, PREF_FLDR, 0},
2918 {"single-column-folder-list", NULL,
2919 F_SINGLE_FOLDER_LIST, h_config_single_list, PREF_FLDR, 0},
2920 {"sort-default-fcc-alpha", "Sort Default Fcc Folder Alphabetically",
2921 F_SORT_DEFAULT_FCC_ALPHA, h_config_sort_fcc_alpha, PREF_FLDR, 0},
2922 {"sort-default-save-alpha", "Sort Default Save Folder Alphabetically",
2923 F_SORT_DEFAULT_SAVE_ALPHA, h_config_sort_save_alpha, PREF_FLDR, 0},
2924 {"vertical-folder-list", "Use Vertical Folder List",
2925 F_VERTICAL_FOLDER_LIST, h_config_vertical_list, PREF_FLDR, 0},
2927 /* Addr book */
2928 {"combined-addrbook-display", "Combined Address Book Display",
2929 F_CMBND_ABOOK_DISP, h_config_combined_abook_display, PREF_ADDR, 0},
2930 {"expanded-view-of-addressbooks", "Expanded View of Address Books",
2931 F_EXPANDED_ADDRBOOKS, h_config_expanded_addrbooks, PREF_ADDR, 0},
2932 {"expanded-view-of-distribution-lists", "Expanded View of Distribution Lists",
2933 F_EXPANDED_DISTLISTS, h_config_expanded_distlists, PREF_ADDR, 0},
2934 #ifdef ENABLE_LDAP
2935 {"ldap-result-to-addrbook-add", "LDAP Result to Addressbook Add",
2936 F_ADD_LDAP_TO_ABOOK, h_config_add_ldap, PREF_ADDR, 0},
2937 #endif
2939 /* Index prefs */
2940 {"auto-open-next-unread", NULL,
2941 F_AUTO_OPEN_NEXT_UNREAD, h_config_auto_open_unread, PREF_INDX, 0},
2942 {"continue-tab-without-confirm", "Continue NextNew Without Confirming",
2943 F_TAB_NO_CONFIRM, h_config_tab_no_prompt, PREF_INDX, 0},
2944 {"convert-dates-to-localtime", NULL,
2945 F_DATES_TO_LOCAL, h_config_dates_to_local, PREF_INDX, 0},
2946 {"delete-skips-deleted", NULL,
2947 F_DEL_SKIPS_DEL, h_config_del_skips_del, PREF_INDX, 1},
2948 {"disable-index-locale-dates", NULL,
2949 F_DISABLE_INDEX_LOCALE_DATES, h_config_disable_index_locale_dates, PREF_INDX, 0},
2950 {"enable-cruise-mode", NULL,
2951 F_ENABLE_SPACE_AS_TAB, h_config_cruise_mode, PREF_INDX, 0},
2952 {"enable-cruise-mode-delete", "Enable Cruise Mode With Deleting",
2953 F_ENABLE_TAB_DELETES, h_config_cruise_mode_delete, PREF_INDX, 0},
2954 {"mark-for-cc", "Mark for CC",
2955 F_MARK_FOR_CC, h_config_mark_for_cc, PREF_INDX, 1},
2956 {"next-thread-without-confirm", "Read Next Thread Without Confirming",
2957 F_NEXT_THRD_WO_CONFIRM, h_config_next_thrd_wo_confirm, PREF_INDX, 0},
2958 {"return-to-inbox-without-confirm", "Return to INBOX Without Confirming",
2959 F_RET_INBOX_NO_CONFIRM, h_config_inbox_no_confirm, PREF_INDX, 0},
2960 {"show-sort", "Show Sort in Titlebar",
2961 F_SHOW_SORT, h_config_show_sort, PREF_INDX, 0},
2962 {"tab-uses-unseen-for-next-folder", "Tab Uses Unseen for Next Folder",
2963 F_TAB_USES_UNSEEN, h_config_tab_uses_unseen, PREF_INDX, 0},
2964 {"tab-visits-next-new-message-only", NULL,
2965 F_TAB_TO_NEW, h_config_tab_new_only, PREF_INDX, 0},
2966 {"thread-index-shows-important-color", NULL,
2967 F_COLOR_LINE_IMPORTANT, h_config_color_thrd_import, PREF_INDX, 0},
2968 {"thread-sorts-by-arrival", "Thread Sorts by Arrival",
2969 F_THREAD_SORTS_BY_ARRIVAL, h_config_thread_sorts_by_arrival, PREF_INDX, 0},
2971 /* Viewer prefs */
2972 {"enable-msg-view-addresses", "Enable Message View Address Links",
2973 F_SCAN_ADDR, h_config_enable_view_addresses, PREF_VIEW, 0},
2974 {"enable-msg-view-attachments", "Enable Message View Attachment Links",
2975 F_VIEW_SEL_ATTACH, h_config_enable_view_attach, PREF_VIEW, 0},
2976 {"enable-msg-view-urls", "Enable Message View URL Links",
2977 F_VIEW_SEL_URL, h_config_enable_view_url, PREF_VIEW, 1},
2978 {"enable-msg-view-web-hostnames", "Enable Message View Web Hostname Links",
2979 F_VIEW_SEL_URL_HOST, h_config_enable_view_web_host, PREF_VIEW, 1},
2980 {"enable-msg-view-forced-arrows", "Enable Message View Forced Arrows",
2981 F_FORCE_ARROWS, h_config_enable_view_arrows, PREF_VIEW, 0},
2982 /* set to TRUE for windows */
2983 {"pass-c1-control-characters-as-is", NULL,
2984 F_PASS_C1_CONTROL_CHARS, h_config_pass_c1_control, PREF_VIEW, 0},
2985 {"pass-control-characters-as-is", NULL,
2986 F_PASS_CONTROL_CHARS, h_config_pass_control, PREF_VIEW, 0},
2987 {"prefer-plain-text", NULL,
2988 F_PREFER_PLAIN_TEXT, h_config_prefer_plain_text, PREF_VIEW, 0},
2989 {"quell-charset-warning", "Suppress Character Set Warning",
2990 F_QUELL_CHARSET_WARNING, h_config_quell_charset_warning, PREF_VIEW, 0},
2991 {"quell-server-after-link-in-html", "Suppress Server After Link in HTML",
2992 F_QUELL_HOST_AFTER_URL, h_config_quell_host_after_url, PREF_VIEW, 0},
2994 /* News */
2995 {"compose-sets-newsgroup-without-confirm", "Compose Sets Newsgroup Without Confirming",
2996 F_COMPOSE_TO_NEWSGRP, h_config_compose_news_wo_conf, PREF_NEWS, 0},
2997 {"enable-8bit-nntp-posting", "Enable 8bit NNTP Posting",
2998 F_ENABLE_8BIT_NNTP, h_config_8bit_nntp, PREF_NEWS, 0},
2999 {"enable-multiple-newsrcs", NULL,
3000 F_ENABLE_MULNEWSRCS, h_config_enable_mulnewsrcs, PREF_NEWS, 0},
3001 {"mult-newsrc-hostnames-as-typed", "Multiple Newsrc Hostnames as Typed",
3002 F_MULNEWSRC_HOSTNAMES_AS_TYPED, h_config_mulnews_as_typed, PREF_NEWS, 0},
3003 {"hide-nntp-path", "Hide NNTP Path",
3004 F_HIDE_NNTP_PATH, h_config_hide_nntp_path, PREF_NEWS, 0},
3005 {"news-approximates-new-status", NULL,
3006 F_FAKE_NEW_IN_NEWS, h_config_news_uses_recent, PREF_NEWS, 1},
3007 {"news-deletes-across-groups", NULL,
3008 F_NEWS_CROSS_DELETE, h_config_news_cross_deletes, PREF_NEWS, 0},
3009 {"news-offers-catchup-on-close", "News Offers Catchup on Close",
3010 F_NEWS_CATCHUP, h_config_news_catchup, PREF_NEWS, 0},
3011 {"news-post-without-validation", NULL,
3012 F_NO_NEWS_VALIDATION, h_config_post_wo_validation, PREF_NEWS, 0},
3013 {"news-read-in-newsrc-order", "News Read in Newsrc Order",
3014 F_READ_IN_NEWSRC_ORDER, h_config_read_in_newsrc_order, PREF_NEWS, 0},
3015 {"nntp-search-uses-overview", "NNTP Search Uses Overview",
3016 F_NNTP_SEARCH_USES_OVERVIEW, h_config_nntp_search_uses_overview, PREF_NEWS, 1},
3017 {"predict-nntp-server", "Predict NNTP Server",
3018 F_PREDICT_NNTP_SERVER, h_config_predict_nntp_server, PREF_NEWS, 0},
3019 {"quell-extra-post-prompt", "Suppress Extra Posting Prompt",
3020 F_QUELL_EXTRA_POST_PROMPT, h_config_quell_post_prompt, PREF_NEWS, 0},
3022 /* Print */
3023 {"enable-print-via-y-command", NULL,
3024 F_ENABLE_PRYNT, h_config_enable_y_print, PREF_PRNT, 0},
3025 {"print-formfeed-between-messages", NULL,
3026 F_AGG_PRINT_FF, h_config_ff_between_msgs, PREF_PRNT, 0},
3027 {"print-includes-from-line", NULL,
3028 F_FROM_DELIM_IN_PRINT, h_config_print_from, PREF_PRNT, 0},
3029 {"print-index-enabled", NULL,
3030 F_PRINT_INDEX, h_config_print_index, PREF_PRNT, 0},
3031 {"print-offers-custom-cmd-prompt", "Print Offers Custom Command Prompt",
3032 F_CUSTOM_PRINT, h_config_custom_print, PREF_PRNT, 0},
3034 /* adv cmd prefs */
3035 {"enable-aggregate-command-set", NULL,
3036 F_ENABLE_AGG_OPS, h_config_enable_agg_ops, PREF_ACMD, 1},
3037 {"enable-arrow-navigation", NULL,
3038 F_ARROW_NAV, h_config_arrow_nav, PREF_ACMD, 1},
3039 {"enable-arrow-navigation-relaxed", NULL,
3040 F_RELAXED_ARROW_NAV, h_config_relaxed_arrow_nav, PREF_ACMD, 1},
3041 {"enable-bounce-cmd", "Enable Bounce Command",
3042 F_ENABLE_BOUNCE, h_config_enable_bounce, PREF_ACMD, 1},
3043 {"enable-exit-via-lessthan-command", NULL,
3044 F_ENABLE_LESSTHAN_EXIT, h_config_enable_lessthan_exit, PREF_ACMD, 1},
3045 {"enable-flag-cmd", "Enable Flag Command",
3046 F_ENABLE_FLAG, h_config_enable_flag, PREF_ACMD, 1},
3047 {"enable-flag-screen-implicitly", NULL,
3048 F_FLAG_SCREEN_DFLT, h_config_flag_screen_default, PREF_ACMD, 0},
3049 {"enable-flag-screen-keyword-shortcut", NULL,
3050 F_FLAG_SCREEN_KW_SHORTCUT, h_config_flag_screen_kw_shortcut,PREF_ACMD, 1},
3051 {"enable-full-header-and-text", "Enable Full Header and Text",
3052 F_ENABLE_FULL_HDR_AND_TEXT, h_config_enable_full_hdr_and_text, PREF_ACMD, 0},
3053 {"enable-full-header-cmd", "Enable Full Header Command",
3054 F_ENABLE_FULL_HDR, h_config_enable_full_hdr, PREF_ACMD, 1},
3055 {"enable-goto-in-file-browser", "Enable Goto in File Browser",
3056 F_ALLOW_GOTO, h_config_allow_goto, PREF_ACMD, 1},
3057 {"enable-jump-shortcut", NULL,
3058 F_ENABLE_JUMP, h_config_enable_jump, PREF_ACMD, 1},
3059 {"enable-partial-match-lists", NULL,
3060 F_ENABLE_SUB_LISTS, h_config_sub_lists, PREF_ACMD, 1},
3061 {"enable-tab-completion", NULL,
3062 F_ENABLE_TAB_COMPLETE, h_config_enable_tab_complete, PREF_ACMD, 1},
3063 {"enable-unix-pipe-cmd", "Enable Unix Pipe Command",
3064 F_ENABLE_PIPE, h_config_enable_pipe, PREF_ACMD, 1},
3065 {"quell-full-header-auto-reset", "Suppress Full Header Auto Reset",
3066 F_QUELL_FULL_HDR_RESET, h_config_quell_full_hdr_reset, PREF_ACMD, 0},
3068 /* Adv user prefs */
3069 #if !defined(DOS) && !defined(OS2)
3070 {"allow-talk", NULL,
3071 F_ALLOW_TALK, h_config_allow_talk, PREF_MISC, 0},
3072 #endif
3073 {"assume-slow-link", NULL,
3074 F_FORCE_LOW_SPEED, h_config_force_low_speed, PREF_OS_LWSD, 0},
3075 {"auto-move-read-msgs", "Auto Move Read Messages",
3076 F_AUTO_READ_MSGS, h_config_auto_read_msgs, PREF_MISC, 0},
3077 {"auto-unselect-after-apply", NULL,
3078 F_AUTO_UNSELECT, h_config_auto_unselect, PREF_MISC, 0},
3079 {"auto-unzoom-after-apply", NULL,
3080 F_AUTO_UNZOOM, h_config_auto_unzoom, PREF_MISC, 1},
3081 {"auto-zoom-after-select", NULL,
3082 F_AUTO_ZOOM, h_config_auto_zoom, PREF_MISC, 1},
3083 {"busy-cue-spinner-only", NULL,
3084 F_USE_BORING_SPINNER, h_config_use_boring_spinner, PREF_MISC, 0},
3085 {"check-newmail-when-quitting", NULL,
3086 F_CHECK_MAIL_ONQUIT, h_config_check_mail_onquit, PREF_MISC, 0},
3087 {"confirm-role-even-for-default", "Confirm Role Even for Default",
3088 F_ROLE_CONFIRM_DEFAULT, h_config_confirm_role, PREF_MISC, 0},
3089 {"disable-keymenu", NULL,
3090 F_BLANK_KEYMENU, h_config_blank_keymenu, PREF_MISC, 0},
3091 {"disable-password-caching", NULL,
3092 F_DISABLE_PASSWORD_CACHING, h_config_disable_password_caching,
3093 PREF_MISC, 0},
3094 #ifdef PASSFILE
3095 {"disable-password-file-saving", NULL,
3096 F_DISABLE_PASSWORD_FILE_SAVING, h_config_disable_password_file_saving,
3097 PREF_MISC, 0},
3098 #endif
3099 {"disable-regular-expression-matching-for-alternate-addresses", NULL,
3100 F_DISABLE_REGEX, h_config_disable_regex, PREF_MISC, 0},
3101 {"disable-save-input-history", NULL,
3102 F_DISABLE_SAVE_INPUT_HISTORY, h_config_input_history, PREF_MISC, 0},
3103 {"disable-take-fullname-in-addresses", "Disable Take Fullname in Addresses",
3104 F_DISABLE_TAKE_FULLNAMES, h_config_take_fullname, PREF_MISC, 0},
3105 {"disable-take-last-comma-first", NULL,
3106 F_DISABLE_TAKE_LASTFIRST, h_config_take_lastfirst, PREF_MISC, 0},
3107 {"disable-terminal-reset-for-display-filters", "Disable Terminal Reset for Display Filters",
3108 F_DISABLE_TERM_RESET_DISP, h_config_disable_reset_disp, PREF_MISC, 0},
3109 {"enable-dot-files", NULL,
3110 F_ENABLE_DOT_FILES, h_config_enable_dot_files, PREF_MISC, 0},
3111 {"enable-fast-recent-test", NULL,
3112 F_ENABLE_FAST_RECENT, h_config_fast_recent, PREF_MISC, 0},
3113 {"enable-mail-check-cue", NULL,
3114 F_SHOW_DELAY_CUE, h_config_show_delay_cue, PREF_MISC, 0},
3115 {"enable-mailcap-param-substitution", "Enable Mailcap Parameter Substitution",
3116 F_DO_MAILCAP_PARAM_SUBST, h_config_mailcap_params, PREF_MISC, 0},
3117 {"enable-mouse-in-xterm", "Enable Mouse in Xterm",
3118 F_ENABLE_MOUSE, h_config_enable_mouse, PREF_OS_MOUSE, 0},
3119 {"enable-newmail-in-xterm-icon", "Enable Newmail in Xterm Icon",
3120 F_ENABLE_XTERM_NEWMAIL, h_config_enable_xterm_newmail, PREF_OS_XNML, 0},
3121 {"enable-newmail-short-text-in-icon", "Enable Newmail Short Text in Icon",
3122 F_ENABLE_NEWMAIL_SHORT_TEXT, h_config_enable_newmail_short_text, PREF_OS_XNML, 0},
3123 {"enable-suspend", NULL,
3124 F_CAN_SUSPEND, h_config_can_suspend, PREF_MISC, 0},
3125 {"enable-take-export", NULL,
3126 F_ENABLE_TAKE_EXPORT, h_config_enable_take_export, PREF_MISC, 0},
3127 {"enable-rules-under-take", "Enable Take Rules",
3128 F_ENABLE_ROLE_TAKE, h_config_enable_role_take, PREF_MISC, 0},
3129 #ifdef _WINDOWS
3130 {"enable-tray-icon", NULL,
3131 F_ENABLE_TRAYICON, h_config_tray_icon, PREF_MISC, 0},
3132 #endif
3133 {"expose-hidden-config", NULL,
3134 F_EXPOSE_HIDDEN_CONFIG, h_config_expose_hidden_config, PREF_MISC, 0},
3135 {"expunge-only-manually", NULL,
3136 F_EXPUNGE_MANUALLY, h_config_expunge_manually, PREF_MISC, 0},
3137 {"expunge-without-confirm", "Expunge Without Confirming",
3138 F_AUTO_EXPUNGE, h_config_auto_expunge, PREF_MISC, 0},
3139 {"expunge-without-confirm-everywhere", "Expunge Without Confirming Everywhere",
3140 F_FULL_AUTO_EXPUNGE, h_config_full_auto_expunge, PREF_MISC, 0},
3141 {"force-arrow-cursor", NULL,
3142 F_FORCE_ARROW, h_config_force_arrow, PREF_MISC, 0},
3143 {"maildrops-preserve-state", NULL,
3144 F_MAILDROPS_PRESERVE_STATE, h_config_maildrops_preserve_state,
3145 PREF_MISC, 0},
3146 {"offer-expunge-of-inbox", "Offer Expunge of INBOX",
3147 F_EXPUNGE_INBOX, h_config_expunge_inbox, PREF_MISC, 0},
3148 {"offer-expunge-of-stayopen-folders", "Offer Expunge of Stayopen Folders",
3149 F_EXPUNGE_STAYOPENS, h_config_expunge_stayopens, PREF_MISC, 0},
3150 {"preopen-stayopen-folders", NULL,
3151 F_PREOPEN_STAYOPENS, h_config_preopen_stayopens, PREF_MISC, 0},
3152 {"preserve-start-stop-characters", "Preserve Start/Stop Characters",
3153 F_PRESERVE_START_STOP, h_config_preserve_start_stop, PREF_OS_STSP, 0},
3154 {"quell-folder-internal-msg", "Prevent Folder Internal Message",
3155 F_QUELL_INTERNAL_MSG, h_config_quell_folder_internal_msg, PREF_MISC, 0},
3156 {"quell-partial-fetching", "Prevent Partial Fetching",
3157 F_QUELL_PARTIAL_FETCH, h_config_quell_partial, PREF_MISC, 0},
3158 {"prune-uses-yyyy-mm", "Prune Uses YYYY-MM",
3159 F_PRUNE_USES_ISO, h_config_prune_uses_iso, PREF_MISC, 0},
3160 {"quit-without-confirm", "Quit Without Confirming",
3161 F_QUIT_WO_CONFIRM, h_config_quit_wo_confirm, PREF_MISC, 0},
3162 {"quote-replace-nonflowed", NULL,
3163 F_QUOTE_REPLACE_NOFLOW, h_config_quote_replace_noflow, PREF_MISC, 0},
3164 {"save-aggregates-copy-sequence", "Save Combines Copies (may be out of order)",
3165 F_AGG_SEQ_COPY, h_config_save_aggregates, PREF_MISC, 1},
3166 {"save-partial-msg-without-confirm", "Save Partial Message Without Confirming",
3167 F_SAVE_PARTIAL_WO_CONFIRM, h_config_save_part_wo_confirm, PREF_MISC, 0},
3168 {"save-will-advance", NULL,
3169 F_SAVE_ADVANCES, h_config_save_advances, PREF_MISC, 0},
3170 {"save-will-not-delete", NULL,
3171 F_SAVE_WONT_DELETE, h_config_save_wont_delete, PREF_MISC, 0},
3172 {"save-will-quote-leading-froms", NULL,
3173 F_QUOTE_ALL_FROMS, h_config_quote_all_froms, PREF_MISC, 0},
3174 {"scramble-message-id", "Scramble the Message-ID When Sending",
3175 F_ROT13_MESSAGE_ID, h_config_scramble_message_id, PREF_MISC, 0},
3176 {"select-without-confirm", "Select Ctrl-T Foldername Without Confirming",
3177 F_SELECT_WO_CONFIRM, h_config_select_wo_confirm, PREF_MISC, 0},
3178 {"show-cursor", NULL,
3179 F_SHOW_CURSOR, h_config_show_cursor, PREF_MISC, 0},
3180 {"show-plain-text-internally", NULL,
3181 F_SHOW_TEXTPLAIN_INT, h_config_textplain_int, PREF_MISC, 0},
3182 {"show-selected-in-boldface", "Show Selected in Boldface",
3183 F_SELECTED_SHOWN_BOLD, h_config_select_in_bold, PREF_MISC, 0},
3184 {"slash-collapses-entire-thread", NULL,
3185 F_SLASH_COLL_ENTIRE, h_config_slash_coll_entire, PREF_MISC, 0},
3186 #ifdef _WINDOWS
3187 {"store-window-position-in-config", "Store Window Position in Config",
3188 F_STORE_WINPOS_IN_CONFIG, h_config_winpos_in_config, PREF_MISC, 0},
3189 #endif
3190 {"suppress-asterisks-in-password-prompt", "Suppress Asterisks in Password Prompt",
3191 F_QUELL_ASTERISKS, h_config_quell_asterisks,
3192 PREF_MISC, 0},
3193 {"quell-attachment-extension-warn", "Suppress Attachment Extension Warning",
3194 F_QUELL_ATTACH_EXT_WARN, h_config_quell_attach_ext_warn,
3195 PREF_MISC, 0},
3196 {"quell-attachment-extra-prompt", "Suppress Attachment Extra Prompt",
3197 F_QUELL_ATTACH_EXTRA_PROMPT, h_config_quell_attach_extra_prompt,
3198 PREF_MISC, 0},
3199 {"quell-berkeley-format-timezone", "Suppress Berkeley Format Timezone",
3200 F_QUELL_BEZERK_TIMEZONE, h_config_no_bezerk_zone, PREF_MISC, 0},
3201 {"quell-content-id", "Suppress Content-ID",
3202 F_QUELL_CONTENT_ID, h_config_quell_content_id, PREF_MISC, 0},
3203 {"quell-filtering-done-message", "Suppress Filtering Done Message",
3204 F_QUELL_FILTER_DONE_MSG, h_config_quell_filtering_done_message,
3205 PREF_MISC, 0},
3206 {"quell-filtering-messages", "Suppress Filtering Messages",
3207 F_QUELL_FILTER_MSGS, h_config_quell_filtering_messages,
3208 PREF_MISC, 0},
3209 {"quell-imap-envelope-update", "Suppress IMAP Envelope Update",
3210 F_QUELL_IMAP_ENV_CB, h_config_quell_imap_env, PREF_MISC, 0},
3211 {"quell-lock-failure-warnings", "Suppress Lock Failure Warnings",
3212 F_QUELL_LOCK_FAILURE_MSGS, h_config_quell_lock_failure_warnings,
3213 PREF_MISC, 0},
3214 {"quell-maildomain-warning", "Suppress Maildomain Warning",
3215 F_QUELL_MAILDOMAIN_WARNING, h_config_quell_domain_warn, PREF_MISC, 0},
3216 {"quell-news-envelope-update", "Suppress News Envelope Update",
3217 F_QUELL_NEWS_ENV_CB, h_config_quell_news_env, PREF_MISC, 0},
3218 #ifdef _WINDOWS
3219 {"quell-ssl-largeblocks", "Prevent SSL Largeblocks",
3220 F_QUELL_SSL_LARGEBLOCKS, h_config_quell_ssl_largeblocks, PREF_MISC, 0},
3221 #endif
3222 {"quell-status-message-beeping", "Suppress Status Message Beeping",
3223 F_QUELL_BEEPS, h_config_quell_beeps, PREF_MISC, 0},
3224 {"quell-timezone-comment-when-sending", "Suppress Timezone Comment When Sending",
3225 F_QUELL_TIMEZONE, h_config_quell_tz_comment, PREF_MISC, 0},
3226 {"suppress-user-agent-when-sending", NULL,
3227 F_QUELL_USERAGENT, h_config_suppress_user_agent, PREF_MISC, 0},
3228 {"tab-checks-recent", "Tab Checks for Recent Messages",
3229 F_TAB_CHK_RECENT, h_config_tab_checks_recent, PREF_MISC, 0},
3230 {"termdef-takes-precedence", NULL,
3231 F_TCAP_WINS, h_config_termcap_wins, PREF_MISC, 0},
3232 {"try-alternative-authentication-driver-first", NULL,
3233 F_PREFER_ALT_AUTH, h_config_alt_auth, PREF_MISC, 0},
3234 {"unselect-will-not-advance", NULL,
3235 F_UNSELECT_WONT_ADVANCE, h_config_unsel_wont_advance, PREF_MISC, 0},
3236 {"use-current-dir", "Use Current Directory",
3237 F_USE_CURRENT_DIR, h_config_use_current_dir, PREF_MISC, 0},
3238 {"use-function-keys", NULL,
3239 F_USE_FK, h_config_use_fk, PREF_OS_USFK, 0},
3240 {"use-regular-startup-rule-for-stayopen-folders", "Use Regular Startup Rule for Stayopen Folders",
3241 F_STARTUP_STAYOPEN, h_config_use_reg_start_for_stayopen, PREF_MISC, 0},
3242 {"use-resent-to-in-rules", "Use Resent-To in Rules",
3243 F_USE_RESENTTO, h_config_use_resentto, PREF_MISC, 0},
3244 {"use-subshell-for-suspend", "Use Subshell for Suspend",
3245 F_SUSPEND_SPAWNS, h_config_suspend_spawns, PREF_OS_SPWN, 0},
3246 #ifndef _WINDOWS
3247 {"use-system-translation", NULL,
3248 F_USE_SYSTEM_TRANS, h_config_use_system_translation, PREF_MISC, 0},
3249 #endif
3251 /* Hidden Features */
3252 {"old-growth", NULL,
3253 F_OLD_GROWTH, NO_HELP, PREF_NONE, 0},
3254 {"disable-config-cmd", NULL,
3255 F_DISABLE_CONFIG_SCREEN, h_config_disable_config_cmd, PREF_HIDDEN, 0},
3256 {"disable-keyboard-lock-cmd", NULL,
3257 F_DISABLE_KBLOCK_CMD, h_config_disable_kb_lock, PREF_HIDDEN, 0},
3258 {"disable-password-cmd", NULL,
3259 F_DISABLE_PASSWORD_CMD, h_config_disable_password_cmd, PREF_HIDDEN, 0},
3260 {"disable-pipes-in-sigs", NULL,
3261 F_DISABLE_PIPES_IN_SIGS, h_config_disable_pipes_in_sigs, PREF_HIDDEN, 0},
3262 {"disable-pipes-in-templates", NULL,
3263 F_DISABLE_PIPES_IN_TEMPLATES, h_config_disable_pipes_in_templates,
3264 PREF_HIDDEN, 0},
3265 {"disable-roles-setup-cmd", NULL,
3266 F_DISABLE_ROLES_SETUP, h_config_disable_roles_setup, PREF_HIDDEN, 0},
3267 {"disable-roles-sig-edit", NULL,
3268 F_DISABLE_ROLES_SIGEDIT, h_config_disable_roles_sigedit, PREF_HIDDEN, 0},
3269 {"disable-roles-template-edit", NULL,
3270 F_DISABLE_ROLES_TEMPLEDIT, h_config_disable_roles_templateedit,
3271 PREF_HIDDEN, 0},
3272 {"disable-setlocale-collate", NULL,
3273 F_DISABLE_SETLOCALE_COLLATE, h_config_disable_collate, PREF_HIDDEN, 0},
3274 {"disable-shared-namespaces", NULL,
3275 F_DISABLE_SHARED_NAMESPACES, h_config_disable_shared, PREF_HIDDEN, 0},
3276 {"disable-signature-edit-cmd", NULL,
3277 F_DISABLE_SIGEDIT_CMD, h_config_disable_signature_edit, PREF_HIDDEN, 0},
3278 {"new-thread-on-blank-subject", "New Thread on Blank Subject",
3279 F_NEW_THREAD_ON_BLANK_SUBJECT, h_config_new_thread_blank_subject, PREF_HIDDEN, 1},
3280 {"quell-personal-name-prompt", NULL,
3281 F_QUELL_PERSONAL_NAME_PROMPT, h_config_quell_personal_name_prompt, PREF_HIDDEN, 0},
3282 {"quell-user-id-prompt", "Quell User ID Prompt",
3283 F_QUELL_USER_ID_PROMPT, h_config_quell_user_id_prompt, PREF_HIDDEN, 0},
3284 #ifdef SMIME
3285 {"smime-dont-do-smime", "S/MIME -- Turn off S/MIME",
3286 F_DONT_DO_SMIME, h_config_smime_dont_do_smime, PREF_HIDDEN, 0},
3287 {"smime-encrypt-by-default", "S/MIME -- Encrypt by Default",
3288 F_ENCRYPT_DEFAULT_ON, h_config_smime_encrypt_by_default, PREF_HIDDEN, 0},
3289 {"smime-remember-passphrase", "S/MIME -- Remember S/MIME Passphrase",
3290 F_REMEMBER_SMIME_PASSPHRASE, h_config_smime_remember_passphrase, PREF_HIDDEN, 0},
3291 {"smime-sign-by-default", "S/MIME -- Sign by Default",
3292 F_SIGN_DEFAULT_ON, h_config_smime_sign_by_default, PREF_HIDDEN, 0},
3293 {"smime-use-store-only", "S/MIME -- Validate Using Certificate Store Only",
3294 F_USE_CERT_STORE_ONLY, h_config_smime_use_cert_store, PREF_HIDDEN, 1},
3295 #ifdef APPLEKEYCHAIN
3296 {"publiccerts-in-keychain", "S/MIME -- Public Certs in MacOS Keychain",
3297 F_PUBLICCERTS_IN_KEYCHAIN, h_config_smime_pubcerts_in_keychain, PREF_HIDDEN, 0},
3298 #endif
3299 #endif
3300 {"selectable-item-nobold", NULL,
3301 F_SLCTBL_ITEM_NOBOLD, NO_HELP, PREF_NONE, 0},
3302 {"send-confirms-only-expanded", NULL, /* exposed in Web Alpine */
3303 F_SEND_CONFIRM_ON_EXPAND, h_config_send_confirms_only_expanded, PREF_HIDDEN, 0},
3304 {"enable-jump-cmd", NULL, /* exposed in Web Alpine */
3305 F_ENABLE_JUMP_CMD, h_config_enable_jump_command, PREF_HIDDEN, 0},
3306 {"enable-newmail-sound", NULL, /* exposed in Web Alpine */
3307 F_ENABLE_NEWMAIL_SOUND, h_config_enable_newmail_sound, PREF_HIDDEN, 0},
3308 {"render-html-internally", NULL, /* exposed in Web Alpine */
3309 F_RENDER_HTML_INTERNALLY, h_config_render_html_internally, PREF_HIDDEN, 0}
3312 return((index >= 0 && index < (sizeof(feat_list)/sizeof(feat_list[0])))
3313 ? &feat_list[index] : NULL);
3318 * feature_list_index -- return index of given feature id in
3319 * feature list
3322 feature_list_index(int id)
3324 FEATURE_S *feature;
3325 int i;
3327 for(i = 0; (feature = feature_list(i)); i++)
3328 if(id == feature->id)
3329 return(i);
3331 return(-1);
3336 * feature_list_name -- return the given feature id's corresponding name
3338 char *
3339 feature_list_name(int id)
3341 FEATURE_S *f;
3343 return((f = feature_list(feature_list_index(id))) ? f->name : "");
3348 feature_list_id(char *name)
3350 FEATURE_S *f;
3351 int i;
3353 for(i = 0; (f = feature_list(i)); i++)
3354 if(!strucmp(f->name, name))
3355 return(f->id);
3357 return(-1);
3362 * feature_list_help -- return the given feature id's corresponding help
3364 HelpType
3365 feature_list_help(int id)
3367 FEATURE_S *f;
3369 return((f = feature_list(feature_list_index(id))) ? f->help : NO_HELP);
3374 * All the arguments past "list" are the backwards compatibility hacks.
3376 void
3377 process_feature_list(struct pine *ps, char **list, int old_growth, int hir, int osr)
3379 register char *q;
3380 char **p,
3381 *lvalue[BM_SIZE * 8];
3382 int i,
3383 yorn;
3384 long l;
3385 FEATURE_S *feat;
3388 /* clear all previous settings and reset them to default */
3389 for(i = 0; (feat = feature_list(i)) != NULL; i++)
3390 F_SET(feat->id, ps, feat->defval);
3392 /* backwards compatibility */
3393 if(hir)
3394 F_TURN_ON(F_INCLUDE_HEADER, ps);
3396 /* ditto */
3397 if(osr)
3398 F_TURN_ON(F_SIG_AT_BOTTOM, ps);
3400 /* ditto */
3401 if(old_growth)
3402 set_old_growth_bits(ps, 0);
3404 /* now run through the list (global, user, and cmd_line lists are here) */
3405 if(list){
3406 for(p = list; (q = *p) != NULL; p++){
3407 if(struncmp(q, "no-", 3) == 0){
3408 yorn = 0;
3409 q += 3;
3410 }else{
3411 yorn = 1;
3414 for(i = 0; (feat = feature_list(i)) != NULL; i++){
3415 if(strucmp(q, feat->name) == 0){
3416 if(feat->id == F_OLD_GROWTH){
3417 set_old_growth_bits(ps, yorn);
3418 }else{
3419 F_SET(feat->id, ps, yorn);
3421 break;
3425 /* if it wasn't in that list */
3426 if(feat == NULL)
3427 dprint((1,"Unrecognized feature in feature-list (%s%s)\n",
3428 (yorn ? "" : "no-"), q ? q : "?"));
3433 * Turn on gratuitous '>From ' quoting, if requested...
3435 mail_parameters(NULL, SET_FROMWIDGET,
3436 F_ON(F_QUOTE_ALL_FROMS, ps) ? VOIDT : NIL);
3439 * Turn off .lock creation complaints...
3441 if(F_ON(F_QUELL_LOCK_FAILURE_MSGS, ps))
3442 mail_parameters(NULL, SET_LOCKEACCESERROR, (void *) 0);
3445 * Turn on quelling of pseudo message.
3447 if(F_ON(F_QUELL_INTERNAL_MSG,ps_global))
3448 mail_parameters(NULL, SET_USERHASNOLIFE, (void *) 1);
3450 l = F_ON(F_MULNEWSRC_HOSTNAMES_AS_TYPED,ps_global) ? 0L : 1L;
3451 mail_parameters(NULL, SET_NEWSRCCANONHOST, (void *) l);
3453 ps->pass_ctrl_chars = F_ON(F_PASS_CONTROL_CHARS,ps_global) ? 1 : 0;
3454 ps->pass_c1_ctrl_chars = F_ON(F_PASS_C1_CONTROL_CHARS,ps_global) ? 1 : 0;
3456 #ifndef _WINDOWS
3457 if(F_ON(F_QUELL_BEZERK_TIMEZONE,ps_global))
3458 mail_parameters(NULL, SET_NOTIMEZONES, (void *) 1);
3459 #endif
3461 if(F_ON(F_USE_FK, ps))
3462 ps->orig_use_fkeys = 1;
3464 /* Will we have to build a new list? */
3465 if(!(old_growth || hir || osr))
3466 return;
3469 * Build a new list for feature-list. The only reason we ever need to
3470 * do this is if one of the obsolete options is being converted
3471 * into a feature-list item, and it isn't already included in the user's
3472 * feature-list.
3474 i = 0;
3475 for(p = LVAL(&ps->vars[V_FEATURE_LIST], Main);
3476 p && (q = *p); p++){
3477 /* already have it or cancelled it, don't need to add later */
3478 if(hir && (strucmp(q, "include-header-in-reply") == 0 ||
3479 strucmp(q, "no-include-header-in-reply") == 0)){
3480 hir = 0;
3481 }else if(osr && (strucmp(q, "signature-at-bottom") == 0 ||
3482 strucmp(q, "no-signature-at-bottom") == 0)){
3483 osr = 0;
3484 }else if(old_growth && (strucmp(q, "old-growth") == 0 ||
3485 strucmp(q, "no-old-growth") == 0)){
3486 old_growth = 0;
3488 lvalue[i++] = cpystr(q);
3491 /* check to see if we still need to build a new list */
3492 if(!(old_growth || hir || osr))
3493 return;
3495 if(hir)
3496 lvalue[i++] = "include-header-in-reply";
3497 if(osr)
3498 lvalue[i++] = "signature-at-bottom";
3499 if(old_growth)
3500 lvalue[i++] = "old-growth";
3501 lvalue[i] = NULL;
3502 set_variable_list(V_FEATURE_LIST, lvalue, TRUE, Main);
3506 void
3507 set_current_pattern_vals(struct pine *ps)
3509 struct variable *vars = ps->vars;
3511 set_current_val(&vars[V_PATTERNS], TRUE, TRUE);
3512 set_current_val(&vars[V_PAT_ROLES], TRUE, TRUE);
3513 set_current_val(&vars[V_PAT_FILTS], TRUE, TRUE);
3514 set_current_val(&vars[V_PAT_FILTS_OLD], TRUE, TRUE);
3515 set_current_val(&vars[V_PAT_SCORES], TRUE, TRUE);
3516 set_current_val(&vars[V_PAT_SCORES_OLD], TRUE, TRUE);
3517 set_current_val(&vars[V_PAT_INCOLS], TRUE, TRUE);
3518 set_current_val(&vars[V_PAT_OTHER], TRUE, TRUE);
3519 set_current_val(&vars[V_PAT_SRCH], TRUE, TRUE);
3522 * If old pattern variable (V_PATTERNS) is set and the new ones aren't
3523 * in the config file, then convert the old data into the new variables.
3524 * It isn't quite that simple, though, because we don't store unset
3525 * variables in remote pinercs. Check for the variables but if we
3526 * don't find any of them, also check the version number. This change was
3527 * made in version 4.30. We could just check that except that we're
3528 * worried somebody will make an incompatible version number change in
3529 * their local version, and will break this. So we check both the
3530 * version # and the var_in_pinerc things to be safer.
3532 if(vars[V_PATTERNS].current_val.l
3533 && vars[V_PATTERNS].current_val.l[0]
3534 && !var_in_pinerc(vars[V_PAT_ROLES].name)
3535 && !var_in_pinerc(vars[V_PAT_FILTS].name)
3536 && !var_in_pinerc(vars[V_PAT_FILTS_OLD].name)
3537 && !var_in_pinerc(vars[V_PAT_SCORES].name)
3538 && !var_in_pinerc(vars[V_PAT_SCORES_OLD].name)
3539 && !var_in_pinerc(vars[V_PAT_INCOLS].name)
3540 && isdigit((unsigned char) ps->pine_pre_vers[0])
3541 && ps->pine_pre_vers[1] == '.'
3542 && isdigit((unsigned char) ps->pine_pre_vers[2])
3543 && isdigit((unsigned char) ps->pine_pre_vers[3])
3544 && strncmp(ps->pine_pre_vers, "4.30", 4) < 0){
3545 convert_pattern_data();
3549 * Otherwise, if FILTS_OLD is set and FILTS isn't in the config file,
3550 * convert FILTS_OLD to FILTS. Same for SCORES.
3551 * The reason FILTS was changed was so we could change the
3552 * semantics of how rules work when there are pieces in the rule that
3553 * we don't understand. At the same time as the FILTS change we added
3554 * a rule to detect 8bitSubjects. So a user might have a filter that
3555 * deletes messages with 8bitSubjects. The problem is that that same
3556 * filter in a FILTS_OLD pine would match because it would ignore the
3557 * 8bitSubject part of the pattern and match on the rest. So we changed
3558 * the semantics so that rules with unknown bits would be ignored
3559 * instead of used. We had to change variable names at the same time
3560 * because we were adding the 8bit thing and the old pines are still
3561 * out there. Filters and Scores can both be dangerous. Roles, Colors,
3562 * and Other seem less dangerous so not worth adding a new variable.
3563 * This was changed in 4.50.
3565 else{
3566 if(vars[V_PAT_FILTS_OLD].current_val.l
3567 && vars[V_PAT_FILTS_OLD].current_val.l[0]
3568 && !var_in_pinerc(vars[V_PAT_FILTS].name)
3569 && !var_in_pinerc(vars[V_PAT_SCORES].name)
3570 && isdigit((unsigned char) ps->pine_pre_vers[0])
3571 && ps->pine_pre_vers[1] == '.'
3572 && isdigit((unsigned char) ps->pine_pre_vers[2])
3573 && isdigit((unsigned char) ps->pine_pre_vers[3])
3574 && strncmp(ps->pine_pre_vers, "4.50", 4) < 0){
3575 convert_filts_pattern_data();
3578 if(vars[V_PAT_SCORES_OLD].current_val.l
3579 && vars[V_PAT_SCORES_OLD].current_val.l[0]
3580 && !var_in_pinerc(vars[V_PAT_FILTS].name)
3581 && !var_in_pinerc(vars[V_PAT_SCORES].name)
3582 && isdigit((unsigned char) ps->pine_pre_vers[0])
3583 && ps->pine_pre_vers[1] == '.'
3584 && isdigit((unsigned char) ps->pine_pre_vers[2])
3585 && isdigit((unsigned char) ps->pine_pre_vers[3])
3586 && strncmp(ps->pine_pre_vers, "4.50", 4) < 0){
3587 convert_scores_pattern_data();
3591 if(vars[V_PAT_ROLES].post_user_val.l)
3592 ps_global->ew_for_role_take = Post;
3593 else
3594 ps_global->ew_for_role_take = Main;
3596 if(vars[V_PAT_FILTS].post_user_val.l)
3597 ps_global->ew_for_filter_take = Post;
3598 else
3599 ps_global->ew_for_filter_take = Main;
3601 if(vars[V_PAT_SCORES].post_user_val.l)
3602 ps_global->ew_for_score_take = Post;
3603 else
3604 ps_global->ew_for_score_take = Main;
3606 if(vars[V_PAT_INCOLS].post_user_val.l)
3607 ps_global->ew_for_incol_take = Post;
3608 else
3609 ps_global->ew_for_incol_take = Main;
3611 if(vars[V_PAT_OTHER].post_user_val.l)
3612 ps_global->ew_for_other_take = Post;
3613 else
3614 ps_global->ew_for_other_take = Main;
3616 if(vars[V_PAT_SRCH].post_user_val.l)
3617 ps_global->ew_for_srch_take = Post;
3618 else
3619 ps_global->ew_for_srch_take = Main;
3624 * Foreach of the config files;
3625 * transfer the data to the new variables.
3627 void
3628 convert_pattern_data(void)
3630 convert_pinerc_patterns(PAT_USE_MAIN);
3631 convert_pinerc_patterns(PAT_USE_POST);
3635 void
3636 convert_filts_pattern_data(void)
3638 convert_pinerc_filts_patterns(PAT_USE_MAIN);
3639 convert_pinerc_filts_patterns(PAT_USE_POST);
3643 void
3644 convert_scores_pattern_data(void)
3646 convert_pinerc_scores_patterns(PAT_USE_MAIN);
3647 convert_pinerc_scores_patterns(PAT_USE_POST);
3652 * Foreach of the four variables, transfer the data for this config file
3653 * from the old patterns variable. We don't have to convert OTHER patterns
3654 * or SRCH patterns because they didn't exist in pines without patterns-other.
3656 * If the original variable had patlines with type File then we convert
3657 * all of the individual patterns to type Lit, because each pattern can
3658 * be of any category. Lit patterns are better tested, anyway.
3660 void
3661 convert_pinerc_patterns(long int use_flags)
3663 long old_rflags;
3664 long rflags;
3665 PAT_S *pat;
3666 PAT_STATE pstate;
3667 ACTION_S *act;
3669 old_rflags = (ROLE_OLD_PAT | use_flags);
3671 rflags = 0L;
3672 if(any_patterns(old_rflags, &pstate)){
3673 dprint((2, "converting old patterns to new (%s)\n", (use_flags == PAT_USE_MAIN) ? "Main" : "Post"));
3674 for(pat = first_pattern(&pstate);
3675 pat;
3676 pat = next_pattern(&pstate)){
3677 if((act = pat->action) != NULL){
3678 if(act->is_a_role &&
3679 add_to_pattern(pat, ROLE_DO_ROLES | use_flags))
3680 rflags |= ROLE_DO_ROLES;
3681 if(act->is_a_incol &&
3682 add_to_pattern(pat, ROLE_DO_INCOLS | use_flags))
3683 rflags |= ROLE_DO_INCOLS;
3684 if(act->is_a_score &&
3685 add_to_pattern(pat, ROLE_DO_SCORES | use_flags))
3686 rflags |= ROLE_DO_SCORES;
3687 if(act->is_a_filter &&
3688 add_to_pattern(pat, ROLE_DO_FILTER | use_flags))
3689 rflags |= ROLE_DO_FILTER;
3693 if(rflags)
3694 if(write_patterns(rflags | use_flags))
3695 dprint((1,
3696 "Trouble converting patterns to new variable\n"));
3702 * If the original variable had patlines with type File then we convert
3703 * all of the individual patterns to type Lit, because each pattern can
3704 * be of any category. Lit patterns are better tested, anyway.
3706 void
3707 convert_pinerc_filts_patterns(long int use_flags)
3709 long old_rflags;
3710 long rflags;
3711 PAT_S *pat;
3712 PAT_STATE pstate;
3713 ACTION_S *act;
3715 old_rflags = (ROLE_OLD_FILT | use_flags);
3717 rflags = 0L;
3718 if(any_patterns(old_rflags, &pstate)){
3719 dprint((2, "converting old filter patterns to new (%s)\n", (use_flags == PAT_USE_MAIN) ? "Main" : "Post"));
3720 for(pat = first_pattern(&pstate);
3721 pat;
3722 pat = next_pattern(&pstate)){
3723 if((act = pat->action) != NULL){
3724 if(act->is_a_filter &&
3725 add_to_pattern(pat, ROLE_DO_FILTER | use_flags))
3726 rflags |= ROLE_DO_FILTER;
3730 if(rflags)
3731 if(write_patterns(rflags | use_flags))
3732 dprint((1,
3733 "Trouble converting filter patterns to new variable\n"));
3739 * If the original variable had patlines with type File then we convert
3740 * all of the individual patterns to type Lit, because each pattern can
3741 * be of any category. Lit patterns are better tested, anyway.
3743 void
3744 convert_pinerc_scores_patterns(long int use_flags)
3746 long old_rflags;
3747 long rflags;
3748 PAT_S *pat;
3749 PAT_STATE pstate;
3750 ACTION_S *act;
3752 old_rflags = (ROLE_OLD_SCORE | use_flags);
3754 rflags = 0L;
3755 if(any_patterns(old_rflags, &pstate)){
3756 dprint((2, "converting old scores patterns to new (%s)\n", (use_flags == PAT_USE_MAIN) ? "Main" : "Post"));
3757 for(pat = first_pattern(&pstate);
3758 pat;
3759 pat = next_pattern(&pstate)){
3760 if((act = pat->action) != NULL){
3761 if(act->is_a_score &&
3762 add_to_pattern(pat, ROLE_DO_SCORES | use_flags))
3763 rflags |= ROLE_DO_SCORES;
3767 if(rflags)
3768 if(write_patterns(rflags | use_flags))
3769 dprint((1,
3770 "Trouble converting scores patterns to new variable\n"));
3776 * set_old_growth_bits - Command used to set or unset old growth set
3777 * of features
3779 void
3780 set_old_growth_bits(struct pine *ps, int val)
3782 int i;
3784 for(i = 1; i <= F_FEATURE_LIST_COUNT; i++)
3785 if(test_old_growth_bits(ps, i))
3786 F_SET(i, ps, val);
3792 * test_old_growth_bits - Test to see if all the old growth bits are on,
3793 * *or* if a particular feature index is in the old
3794 * growth set.
3796 * WEIRD ALERT: if index == F_OLD_GROWTH bit values are tested
3797 * otherwise a bits existence in the set is tested!!!
3799 * BUG: this will break if an old growth feature number is ever >= 32.
3802 test_old_growth_bits(struct pine *ps, int index)
3805 * this list defines F_OLD_GROWTH set
3807 static unsigned long old_growth_bits = ((1 << F_ENABLE_FULL_HDR) |
3808 (1 << F_ENABLE_PIPE) |
3809 (1 << F_ENABLE_TAB_COMPLETE) |
3810 (1 << F_QUIT_WO_CONFIRM) |
3811 (1 << F_ENABLE_JUMP) |
3812 (1 << F_ENABLE_ALT_ED) |
3813 (1 << F_ENABLE_BOUNCE) |
3814 (1 << F_ENABLE_AGG_OPS) |
3815 (1 << F_ENABLE_FLAG) |
3816 (1 << F_CAN_SUSPEND));
3817 if(index >= 32)
3818 return(0);
3820 if(index == F_OLD_GROWTH){
3821 for(index = 1; index <= F_FEATURE_LIST_COUNT; index++)
3822 if(((1 << index) & old_growth_bits) && F_OFF(index, ps))
3823 return(0);
3825 return(1);
3827 else
3828 return((1 << index) & old_growth_bits);
3833 * Side effect is that the appropriate global variable is set, and the
3834 * appropriate current_val is set.
3836 void
3837 cur_rule_value(struct variable *var, int expand, int cmdline)
3839 int i;
3840 NAMEVAL_S *v;
3842 set_current_val(var, expand, cmdline);
3844 if(var == &ps_global->vars[V_SAVED_MSG_NAME_RULE]){
3845 if(ps_global->VAR_SAVED_MSG_NAME_RULE)
3846 for(i = 0; (v = save_msg_rules(i)); i++)
3847 if(!strucmp(ps_global->VAR_SAVED_MSG_NAME_RULE, S_OR_L(v))){
3848 ps_global->save_msg_rule = v->value;
3849 break;
3852 #ifndef _WINDOWS
3853 else if(var == &ps_global->vars[V_COLOR_STYLE]){
3854 if(ps_global->VAR_COLOR_STYLE)
3855 for(i = 0; (v = col_style(i)); i++)
3856 if(!strucmp(ps_global->VAR_COLOR_STYLE, S_OR_L(v))){
3857 ps_global->color_style = v->value;
3858 break;
3861 #endif
3862 else if(var == &ps_global->vars[V_INDEX_COLOR_STYLE]){
3863 if(ps_global->VAR_INDEX_COLOR_STYLE)
3864 for(i = 0; (v = index_col_style(i)); i++)
3865 if(!strucmp(ps_global->VAR_INDEX_COLOR_STYLE, S_OR_L(v))){
3866 ps_global->index_color_style = v->value;
3867 break;
3870 else if(var == &ps_global->vars[V_TITLEBAR_COLOR_STYLE]){
3871 if(ps_global->VAR_TITLEBAR_COLOR_STYLE)
3872 for(i = 0; (v = titlebar_col_style(i)); i++)
3873 if(!strucmp(ps_global->VAR_TITLEBAR_COLOR_STYLE, S_OR_L(v))){
3874 ps_global->titlebar_color_style = v->value;
3875 break;
3878 else if(var == &ps_global->vars[V_FCC_RULE]){
3879 if(ps_global->VAR_FCC_RULE)
3880 for(i = 0; (v = fcc_rules(i)); i++)
3881 if(!strucmp(ps_global->VAR_FCC_RULE, S_OR_L(v))){
3882 ps_global->fcc_rule = v->value;
3883 break;
3886 else if(var == &ps_global->vars[V_GOTO_DEFAULT_RULE]){
3887 if(ps_global->VAR_GOTO_DEFAULT_RULE)
3888 for(i = 0; (v = goto_rules(i)); i++)
3889 if(!strucmp(ps_global->VAR_GOTO_DEFAULT_RULE, S_OR_L(v))){
3890 ps_global->goto_default_rule = v->value;
3891 break;
3894 else if(var == &ps_global->vars[V_INCOMING_STARTUP]){
3895 if(ps_global->VAR_INCOMING_STARTUP)
3896 for(i = 0; (v = incoming_startup_rules(i)); i++)
3897 if(!strucmp(ps_global->VAR_INCOMING_STARTUP, S_OR_L(v))){
3898 ps_global->inc_startup_rule = v->value;
3899 break;
3902 else if(var == &ps_global->vars[V_PRUNING_RULE]){
3903 if(ps_global->VAR_PRUNING_RULE)
3904 for(i = 0; (v = pruning_rules(i)); i++)
3905 if(!strucmp(ps_global->VAR_PRUNING_RULE, S_OR_L(v))){
3906 ps_global->pruning_rule = v->value;
3907 break;
3910 else if(var == &ps_global->vars[V_REOPEN_RULE]){
3911 if(ps_global->VAR_REOPEN_RULE)
3912 for(i = 0; (v = reopen_rules(i)); i++)
3913 if(!strucmp(ps_global->VAR_REOPEN_RULE, S_OR_L(v))){
3914 ps_global->reopen_rule = v->value;
3915 break;
3918 else if(var == &ps_global->vars[V_FLD_SORT_RULE]){
3919 if(ps_global->VAR_FLD_SORT_RULE)
3920 for(i = 0; (v = fld_sort_rules(i)); i++)
3921 if(!strucmp(ps_global->VAR_FLD_SORT_RULE, S_OR_L(v))){
3922 ps_global->fld_sort_rule = v->value;
3923 break;
3926 else if(var == &ps_global->vars[V_AB_SORT_RULE]){
3927 if(ps_global->VAR_AB_SORT_RULE)
3928 for(i = 0; (v = ab_sort_rules(i)); i++)
3929 if(!strucmp(ps_global->VAR_AB_SORT_RULE, S_OR_L(v))){
3930 ps_global->ab_sort_rule = v->value;
3931 break;
3934 else if(var == &ps_global->vars[V_THREAD_DISP_STYLE]){
3935 if(ps_global->VAR_THREAD_DISP_STYLE)
3936 for(i = 0; (v = thread_disp_styles(i)); i++)
3937 if(!strucmp(ps_global->VAR_THREAD_DISP_STYLE, S_OR_L(v))){
3938 ps_global->thread_disp_style = v->value;
3939 break;
3942 else if(var == &ps_global->vars[V_THREAD_INDEX_STYLE]){
3943 if(ps_global->VAR_THREAD_INDEX_STYLE)
3944 for(i = 0; (v = thread_index_styles(i)); i++)
3945 if(!strucmp(ps_global->VAR_THREAD_INDEX_STYLE, S_OR_L(v))){
3946 ps_global->thread_index_style = v->value;
3947 break;
3954 * Standard way to get at save message rules...
3956 NAMEVAL_S *
3957 save_msg_rules(int index)
3959 static NAMEVAL_S save_rules[] = {
3960 {"by-from", NULL, SAV_RULE_FROM},
3961 {"by-nick-of-from", NULL, SAV_RULE_NICK_FROM_DEF},
3962 {"by-nick-of-from-then-from", NULL, SAV_RULE_NICK_FROM},
3963 {"by-fcc-of-from", NULL, SAV_RULE_FCC_FROM_DEF},
3964 {"by-fcc-of-from-then-from", NULL, SAV_RULE_FCC_FROM},
3965 {"by-realname-of-from", NULL, SAV_RULE_RN_FROM_DEF},
3966 {"by-realname-of-from-then-from", NULL, SAV_RULE_RN_FROM},
3967 {"by-sender", NULL, SAV_RULE_SENDER},
3968 {"by-nick-of-sender", NULL, SAV_RULE_NICK_SENDER_DEF},
3969 {"by-nick-of-sender-then-sender", NULL, SAV_RULE_NICK_SENDER},
3970 {"by-fcc-of-sender", NULL, SAV_RULE_FCC_SENDER_DEF},
3971 {"by-fcc-of-sender-then-sender", NULL, SAV_RULE_FCC_SENDER},
3972 {"by-realname-of-sender", NULL, SAV_RULE_RN_SENDER_DEF},
3973 {"by-realname-of-sender-then-sender", NULL, SAV_RULE_RN_SENDER},
3974 {"by-recipient", NULL, SAV_RULE_RECIP},
3975 {"by-nick-of-recip", NULL, SAV_RULE_NICK_RECIP_DEF},
3976 {"by-nick-of-recip-then-recip", NULL, SAV_RULE_NICK_RECIP},
3977 {"by-fcc-of-recip", NULL, SAV_RULE_FCC_RECIP_DEF},
3978 {"by-fcc-of-recip-then-recip", NULL, SAV_RULE_FCC_RECIP},
3979 {"by-realname-of-recip", NULL, SAV_RULE_RN_RECIP_DEF},
3980 {"by-realname-of-recip-then-recip", NULL, SAV_RULE_RN_RECIP},
3981 {"by-replyto", NULL, SAV_RULE_REPLYTO},
3982 {"by-nick-of-replyto", NULL, SAV_RULE_NICK_REPLYTO_DEF},
3983 {"by-nick-of-replyto-then-replyto", NULL, SAV_RULE_NICK_REPLYTO},
3984 {"by-fcc-of-replyto", NULL, SAV_RULE_FCC_REPLYTO_DEF},
3985 {"by-fcc-of-replyto-then-replyto", NULL, SAV_RULE_FCC_REPLYTO},
3986 {"by-realname-of-replyto", NULL, SAV_RULE_RN_REPLYTO_DEF},
3987 {"by-realname-of-replyto-then-replyto", NULL, SAV_RULE_RN_REPLYTO},
3988 {"last-folder-used", NULL, SAV_RULE_LAST},
3989 {"default-folder", NULL, SAV_RULE_DEFLT}
3992 return((index >= 0 && index < (sizeof(save_rules)/sizeof(save_rules[0])))
3993 ? &save_rules[index] : NULL);
3998 * Standard way to get at fcc rules...
4000 NAMEVAL_S *
4001 fcc_rules(int index)
4003 static NAMEVAL_S f_rules[] = {
4004 {"default-fcc", NULL, FCC_RULE_DEFLT},
4005 {"last-fcc-used", NULL, FCC_RULE_LAST},
4006 {"by-recipient", NULL, FCC_RULE_RECIP},
4007 {"by-nickname", NULL, FCC_RULE_NICK},
4008 {"by-nick-then-recip", NULL, FCC_RULE_NICK_RECIP},
4009 {"current-folder", NULL, FCC_RULE_CURRENT}
4012 return((index >= 0 && index < (sizeof(f_rules)/sizeof(f_rules[0])))
4013 ? &f_rules[index] : NULL);
4018 * Standard way to get at addrbook sort rules...
4020 NAMEVAL_S *
4021 ab_sort_rules(int index)
4023 static NAMEVAL_S ab_rules[] = {
4024 {"fullname-with-lists-last", NULL, AB_SORT_RULE_FULL_LISTS},
4025 {"fullname", NULL, AB_SORT_RULE_FULL},
4026 {"nickname-with-lists-last", NULL, AB_SORT_RULE_NICK_LISTS},
4027 {"nickname", NULL, AB_SORT_RULE_NICK},
4028 {"dont-sort", NULL, AB_SORT_RULE_NONE}
4031 return((index >= 0 && index < (sizeof(ab_rules)/sizeof(ab_rules[0])))
4032 ? &ab_rules[index] : NULL);
4037 * Standard way to get at color styles.
4039 NAMEVAL_S *
4040 col_style(int index)
4042 static NAMEVAL_S col_styles[] = {
4043 {"no-color", NULL, COL_NONE},
4044 {"use-termdef", NULL, COL_TERMDEF},
4045 {"force-ansi-8color", NULL, COL_ANSI8},
4046 {"force-ansi-16color", NULL, COL_ANSI16},
4047 {"force-xterm-256color", NULL, COL_ANSI256}
4050 return((index >= 0 && index < (sizeof(col_styles)/sizeof(col_styles[0])))
4051 ? &col_styles[index] : NULL);
4056 * Standard way to get at index color styles.
4058 NAMEVAL_S *
4059 index_col_style(int index)
4061 static NAMEVAL_S ind_col_styles[] = {
4062 {"flip-colors", NULL, IND_COL_FLIP},
4063 {"reverse", NULL, IND_COL_REV},
4064 {"reverse-fg", NULL, IND_COL_FG},
4065 {"reverse-fg-no-ambiguity", NULL, IND_COL_FG_NOAMBIG},
4066 {"reverse-bg", NULL, IND_COL_BG},
4067 {"reverse-bg-no-ambiguity", NULL, IND_COL_BG_NOAMBIG}
4070 return((index >= 0 && index < (sizeof(ind_col_styles)/sizeof(ind_col_styles[0]))) ? &ind_col_styles[index] : NULL);
4075 * Standard way to get at titlebar color styles.
4077 NAMEVAL_S *
4078 titlebar_col_style(int index)
4080 static NAMEVAL_S tbar_col_styles[] = {
4081 {"default", NULL, TBAR_COLOR_DEFAULT},
4082 {"indexline", NULL, TBAR_COLOR_INDEXLINE},
4083 {"reverse-indexline", NULL, TBAR_COLOR_REV_INDEXLINE}
4086 return((index >= 0 && index < (sizeof(tbar_col_styles)/sizeof(tbar_col_styles[0]))) ? &tbar_col_styles[index] : NULL);
4091 * Standard way to get at folder sort rules...
4093 NAMEVAL_S *
4094 fld_sort_rules(int index)
4096 static NAMEVAL_S fdl_rules[] = {
4097 {"alphabetical", NULL, FLD_SORT_ALPHA},
4098 {"alpha-with-dirs-last", NULL, FLD_SORT_ALPHA_DIR_LAST},
4099 {"alpha-with-dirs-first", NULL, FLD_SORT_ALPHA_DIR_FIRST}
4102 return((index >= 0 && index < (sizeof(fdl_rules)/sizeof(fdl_rules[0])))
4103 ? &fdl_rules[index] : NULL);
4108 * Standard way to get at incoming startup rules...
4110 NAMEVAL_S *
4111 incoming_startup_rules(int index)
4113 static NAMEVAL_S is_rules[] = {
4114 {"first-unseen", NULL, IS_FIRST_UNSEEN},
4115 {"first-recent", NULL, IS_FIRST_RECENT},
4116 {"first-important", NULL, IS_FIRST_IMPORTANT},
4117 {"first-important-or-unseen", NULL, IS_FIRST_IMPORTANT_OR_UNSEEN},
4118 {"first-important-or-recent", NULL, IS_FIRST_IMPORTANT_OR_RECENT},
4119 {"first", NULL, IS_FIRST},
4120 {"last", NULL, IS_LAST}
4123 return((index >= 0 && index < (sizeof(is_rules)/sizeof(is_rules[0])))
4124 ? &is_rules[index] : NULL);
4128 NAMEVAL_S *
4129 startup_rules(int index)
4131 static NAMEVAL_S is2_rules[] = {
4132 {"first-unseen", NULL, IS_FIRST_UNSEEN},
4133 {"first-recent", NULL, IS_FIRST_RECENT},
4134 {"first-important", NULL, IS_FIRST_IMPORTANT},
4135 {"first-important-or-unseen", NULL, IS_FIRST_IMPORTANT_OR_UNSEEN},
4136 {"first-important-or-recent", NULL, IS_FIRST_IMPORTANT_OR_RECENT},
4137 {"first", NULL, IS_FIRST},
4138 {"last", NULL, IS_LAST},
4139 {"default", NULL, IS_NOTSET}
4142 return((index >= 0 && index < (sizeof(is2_rules)/sizeof(is2_rules[0])))
4143 ? &is2_rules[index] : NULL);
4148 * Standard way to get at pruning-rule values.
4150 NAMEVAL_S *
4151 pruning_rules(int index)
4153 static NAMEVAL_S pr_rules[] = {
4154 {"ask about rename, ask about deleting","ask-ask", PRUNE_ASK_AND_ASK},
4155 {"ask about rename, don't delete", "ask-no", PRUNE_ASK_AND_NO},
4156 {"always rename, ask about deleting", "yes-ask", PRUNE_YES_AND_ASK},
4157 {"always rename, don't delete", "yes-no", PRUNE_YES_AND_NO},
4158 {"don't rename, ask about deleting", "no-ask", PRUNE_NO_AND_ASK},
4159 {"don't rename, don't delete", "no-no", PRUNE_NO_AND_NO}
4162 return((index >= 0 && index < (sizeof(pr_rules)/sizeof(pr_rules[0])))
4163 ? &pr_rules[index] : NULL);
4168 * Standard way to get at reopen-rule values.
4170 NAMEVAL_S *
4171 reopen_rules(int index)
4173 static NAMEVAL_S ro_rules[] = {
4174 /* TRANSLATORS: short description of a feature option */
4175 {"Always reopen", "yes-yes",
4176 REOPEN_YES_YES},
4177 /* TRANSLATORS: short description of a feature option, default in brackets */
4178 {"Yes for POP/NNTP, Ask about other remote [Yes]", "yes-ask-y",
4179 REOPEN_YES_ASK_Y},
4180 /* TRANSLATORS: short description of a feature option, default in brackets */
4181 {"Yes for POP/NNTP, Ask about other remote [No]", "yes-ask-n",
4182 REOPEN_YES_ASK_N},
4183 /* TRANSLATORS: short description of a feature option */
4184 {"Yes for POP/NNTP, No for other remote", "yes-no",
4185 REOPEN_YES_NO},
4186 /* TRANSLATORS: short description of a feature option, default in brackets */
4187 {"Always ask [Yes]", "ask-ask-y",
4188 REOPEN_ASK_ASK_Y},
4189 /* TRANSLATORS: short description of a feature option, default in brackets */
4190 {"Always ask [No]", "ask-ask-n",
4191 REOPEN_ASK_ASK_N},
4192 /* TRANSLATORS: short description of a feature option, default in brackets */
4193 {"Ask about POP/NNTP [Yes], No for other remote", "ask-no-y",
4194 REOPEN_ASK_NO_Y},
4195 /* TRANSLATORS: short description of a feature option, default in brackets */
4196 {"Ask about POP/NNTP [No], No for other remote", "ask-no-n",
4197 REOPEN_ASK_NO_N},
4198 /* TRANSLATORS: short description of a feature option */
4199 {"Never reopen", "no-no",
4200 REOPEN_NO_NO},
4203 return((index >= 0 && index < (sizeof(ro_rules)/sizeof(ro_rules[0])))
4204 ? &ro_rules[index] : NULL);
4209 * Standard way to get at thread_disp_style values.
4211 NAMEVAL_S *
4212 thread_disp_styles(int index)
4214 static NAMEVAL_S td_styles[] = {
4215 {"none", "none", THREAD_NONE},
4216 {"show-thread-structure", "struct", THREAD_STRUCT},
4217 {"mutt-like", "mutt", THREAD_MUTTLIKE},
4218 {"indent-subject-1", "subj1", THREAD_INDENT_SUBJ1},
4219 {"indent-subject-2", "subj2", THREAD_INDENT_SUBJ2},
4220 {"indent-from-1", "from1", THREAD_INDENT_FROM1},
4221 {"indent-from-2", "from2", THREAD_INDENT_FROM2},
4222 {"show-structure-in-from", "struct-from", THREAD_STRUCT_FROM}
4225 return((index >= 0 && index < (sizeof(td_styles)/sizeof(td_styles[0])))
4226 ? &td_styles[index] : NULL);
4231 * Standard way to get at thread_index_style values.
4233 NAMEVAL_S *
4234 thread_index_styles(int index)
4236 static NAMEVAL_S ti_styles[] = {
4237 {"regular-index-with-expanded-threads", "exp", THRDINDX_EXP},
4238 {"regular-index-with-collapsed-threads","coll", THRDINDX_COLL},
4239 {"separate-index-screen-always", "sep", THRDINDX_SEP},
4240 {"separate-index-screen-except-for-single-messages","sep-auto",
4241 THRDINDX_SEP_AUTO}
4244 return((index >= 0 && index < (sizeof(ti_styles)/sizeof(ti_styles[0])))
4245 ? &ti_styles[index] : NULL);
4250 * Standard way to get at goto default rules...
4252 NAMEVAL_S *
4253 goto_rules(int index)
4255 static NAMEVAL_S g_rules[] = {
4256 {"folder-in-first-collection", NULL, GOTO_FIRST_CLCTN},
4257 {"inbox-or-folder-in-first-collection", NULL, GOTO_INBOX_FIRST_CLCTN},
4258 {"inbox-or-folder-in-recent-collection", NULL, GOTO_INBOX_RECENT_CLCTN},
4259 {"first-collection-with-inbox-default", NULL, GOTO_FIRST_CLCTN_DEF_INBOX},
4260 {"most-recent-folder", NULL, GOTO_LAST_FLDR}
4263 return((index >= 0 && index < (sizeof(g_rules)/sizeof(g_rules[0])))
4264 ? &g_rules[index] : NULL);
4268 NAMEVAL_S *
4269 pat_fldr_types(int index)
4271 static NAMEVAL_S pat_fldr_list[] = {
4272 {"Any", "ANY", FLDR_ANY},
4273 {"News", "NEWS", FLDR_NEWS},
4274 {"Email", "EMAIL", FLDR_EMAIL},
4275 {"Specific (Enter Incoming Nicknames or use ^T)", "SPEC", FLDR_SPECIFIC}
4278 return((index >= 0 &&
4279 index < (sizeof(pat_fldr_list)/sizeof(pat_fldr_list[0])))
4280 ? &pat_fldr_list[index] : NULL);
4284 NAMEVAL_S *
4285 inabook_fldr_types(int indexarg)
4287 static NAMEVAL_S inabook_fldr_list[] = {
4288 {"Don't care, always matches", "E", IAB_EITHER},
4289 {"Yes, in any address book", "YES", IAB_YES},
4290 {"No, not in any address book", "NO", IAB_NO},
4291 {"Yes, in specific address books", "SYES", IAB_SPEC_YES},
4292 {"No, not in any of specific address books", "SNO", IAB_SPEC_NO}
4295 int index = indexarg & IAB_TYPE_MASK;
4297 return((index >= 0 &&
4298 index < (sizeof(inabook_fldr_list)/sizeof(inabook_fldr_list[0])))
4299 ? &inabook_fldr_list[index] : NULL);
4303 NAMEVAL_S *
4304 filter_types(int index)
4306 static NAMEVAL_S filter_type_list[] = {
4307 {"Just Set Message Status", "NONE", FILTER_STATE},
4308 {"Delete", "DEL", FILTER_KILL},
4309 {"Move (Enter folder name(s) in primary collection, or use ^T)",
4310 "FLDR", FILTER_FOLDER}
4313 return((index >= 0 &&
4314 index < (sizeof(filter_type_list)/sizeof(filter_type_list[0])))
4315 ? &filter_type_list[index] : NULL);
4319 NAMEVAL_S *
4320 role_repl_types(int index)
4322 static NAMEVAL_S role_repl_list[] = {
4323 {"Never", "NO", ROLE_REPL_NO},
4324 {"With confirmation", "YES", ROLE_REPL_YES},
4325 {"Without confirmation", "NC", ROLE_REPL_NOCONF}
4328 return((index >= 0 &&
4329 index < (sizeof(role_repl_list)/sizeof(role_repl_list[0])))
4330 ? &role_repl_list[index] : NULL);
4334 NAMEVAL_S *
4335 role_forw_types(int index)
4337 static NAMEVAL_S role_forw_list[] = {
4338 {"Never", "NO", ROLE_FORW_NO},
4339 {"With confirmation", "YES", ROLE_FORW_YES},
4340 {"Without confirmation", "NC", ROLE_FORW_NOCONF}
4343 return((index >= 0 &&
4344 index < (sizeof(role_forw_list)/sizeof(role_forw_list[0])))
4345 ? &role_forw_list[index] : NULL);
4349 NAMEVAL_S *
4350 role_comp_types(int index)
4352 static NAMEVAL_S role_comp_list[] = {
4353 {"Never", "NO", ROLE_COMP_NO},
4354 {"With confirmation", "YES", ROLE_COMP_YES},
4355 {"Without confirmation", "NC", ROLE_COMP_NOCONF}
4358 return((index >= 0 &&
4359 index < (sizeof(role_comp_list)/sizeof(role_comp_list[0])))
4360 ? &role_comp_list[index] : NULL);
4364 NAMEVAL_S *
4365 role_status_types(int index)
4367 static NAMEVAL_S role_status_list[] = {
4368 {"Don't care, always matches", "E", PAT_STAT_EITHER},
4369 {"Yes", "YES", PAT_STAT_YES},
4370 {"No", "NO", PAT_STAT_NO}
4373 return((index >= 0 &&
4374 index < (sizeof(role_status_list)/sizeof(role_status_list[0])))
4375 ? &role_status_list[index] : NULL);
4379 NAMEVAL_S *
4380 msg_state_types(int index)
4382 static NAMEVAL_S msg_state_list[] = {
4383 {"Don't change it", "LV", ACT_STAT_LEAVE},
4384 {"Set this state", "SET", ACT_STAT_SET},
4385 {"Clear this state", "CLR", ACT_STAT_CLEAR}
4388 return((index >= 0 &&
4389 index < (sizeof(msg_state_list)/sizeof(msg_state_list[0])))
4390 ? &msg_state_list[index] : NULL);
4394 #ifdef ENABLE_LDAP
4395 NAMEVAL_S *
4396 ldap_search_rules(int index)
4398 static NAMEVAL_S ldap_search_list[] = {
4399 {"contains", NULL, LDAP_SRCH_CONTAINS},
4400 {"equals", NULL, LDAP_SRCH_EQUALS},
4401 {"begins-with", NULL, LDAP_SRCH_BEGINS},
4402 {"ends-with", NULL, LDAP_SRCH_ENDS}
4405 return((index >= 0 &&
4406 index < (sizeof(ldap_search_list)/sizeof(ldap_search_list[0])))
4407 ? &ldap_search_list[index] : NULL);
4411 NAMEVAL_S *
4412 ldap_search_types(int index)
4414 static NAMEVAL_S ldap_types_list[] = {
4415 {"name", NULL, LDAP_TYPE_CN},
4416 {"surname", NULL, LDAP_TYPE_SUR},
4417 {"givenname", NULL, LDAP_TYPE_GIVEN},
4418 {"email", NULL, LDAP_TYPE_EMAIL},
4419 {"name-or-email", NULL, LDAP_TYPE_CN_EMAIL},
4420 {"surname-or-givenname", NULL, LDAP_TYPE_SUR_GIVEN},
4421 {"sur-or-given-or-name-or-email", NULL, LDAP_TYPE_SEVERAL}
4424 return((index >= 0 &&
4425 index < (sizeof(ldap_types_list)/sizeof(ldap_types_list[0])))
4426 ? &ldap_types_list[index] : NULL);
4430 NAMEVAL_S *
4431 ldap_search_scope(int index)
4433 static NAMEVAL_S ldap_scope_list[] = {
4434 {"base", NULL, LDAP_SCOPE_BASE},
4435 {"onelevel", NULL, LDAP_SCOPE_ONELEVEL},
4436 {"subtree", NULL, LDAP_SCOPE_SUBTREE}
4439 return((index >= 0 &&
4440 index < (sizeof(ldap_scope_list)/sizeof(ldap_scope_list[0])))
4441 ? &ldap_scope_list[index] : NULL);
4443 #endif
4447 * Choose from the global default, command line args, pinerc values to set
4448 * the actual value of the variable that we will use. Start at the top
4449 * and work down from higher to lower precedence.
4450 * For lists, we may inherit values from lower precedence
4451 * versions if that's the way the user specifies it.
4452 * The user can put INHERIT_DEFAULT as the first entry in a list and that
4453 * means it will inherit the current values, for example the values
4454 * from the global_val, or the value from the main_user_val could be
4455 * inherited in the post_user_val.
4457 void
4458 set_current_val(struct variable *var, int expand, int cmdline)
4460 int is_set[5], is_inherit[5];
4461 int i, j, k, cnt, start;
4462 char **tmp, **t, **list[5];
4463 char *p;
4465 dprint((9,
4466 "set_current_val(var=%s%s, expand=%d, cmdline=%d)\n",
4467 (var && var->name) ? var->name : "?",
4468 (var && var->is_list) ? " (list)" : "",
4469 expand, cmdline));
4471 if(!var)
4472 return;
4474 if(var->is_list){ /* variable is a list */
4476 for(j = 0; j < 5; j++){
4477 t = j==0 ? var->global_val.l :
4478 j==1 ? var->main_user_val.l :
4479 j==2 ? var->post_user_val.l :
4480 j==3 ? ((cmdline) ? var->cmdline_val.l : NULL) :
4481 var->fixed_val.l;
4483 is_set[j] = is_inherit[j] = 0;
4484 list[j] = NULL;
4486 if(t){
4487 if(!expand){
4488 is_set[j]++;
4489 list[j] = t;
4491 else{
4492 for(i = 0; t[i]; i++){
4493 if(expand_variables(tmp_20k_buf, SIZEOF_20KBUF, t[i],
4494 0)){
4495 /* successful expand */
4496 is_set[j]++;
4497 list[j] = t;
4498 break;
4503 if(list[j] && list[j][0] && !strcmp(list[j][0],INHERIT))
4504 is_inherit[j]++;
4508 cnt = 0;
4509 start = 0;
4510 /* count how many items in current_val list */
4511 /* Admin wants default, which is global_val. */
4512 if(var->is_fixed && var->fixed_val.l == NULL){
4513 cnt = 0;
4514 if(is_set[0]){
4515 for(; list[0][cnt]; cnt++)
4519 else{
4520 for(j = 0; j < 5; j++){
4521 if(is_set[j]){
4522 if(!is_inherit[j]){
4523 cnt = 0; /* reset */
4524 start = j;
4527 for(i = is_inherit[j] ? 1 : 0; list[j][i]; i++)
4528 cnt++;
4533 free_list_array(&var->current_val.l); /* clean up any old values */
4535 /* check to see if anything is set */
4536 if(is_set[0] + is_set[1] + is_set[2] + is_set[3] + is_set[4] > 0){
4537 var->current_val.l = (char **)fs_get((cnt+1)*sizeof(char *));
4538 tmp = var->current_val.l;
4539 if(var->is_fixed && var->fixed_val.l == NULL){
4540 if(is_set[0]){
4541 for(i = 0; list[0][i]; i++){
4542 if(!expand)
4543 *tmp++ = cpystr(list[0][i]);
4544 else if(expand_variables(tmp_20k_buf, SIZEOF_20KBUF,
4545 list[0][i], 0))
4546 *tmp++ = cpystr(tmp_20k_buf);
4550 else{
4551 for(j = start; j < 5; j++){
4552 if(is_set[j]){
4553 for(i = is_inherit[j] ? 1 : 0; list[j][i]; i++){
4554 if(!expand)
4555 *tmp++ = cpystr(list[j][i]);
4556 else if(expand_variables(tmp_20k_buf,SIZEOF_20KBUF,
4557 list[j][i], 0))
4558 *tmp++ = cpystr(tmp_20k_buf);
4564 *tmp = NULL;
4566 else
4567 var->current_val.l = NULL;
4569 else{ /* variable is not a list */
4570 char *strvar = NULL;
4572 for(j = 0; j < 5; j++){
4574 p = j==0 ? var->fixed_val.p :
4575 j==1 ? ((cmdline) ? var->cmdline_val.p : NULL) :
4576 j==2 ? var->post_user_val.p :
4577 j==3 ? var->main_user_val.p :
4578 var->global_val.p;
4580 is_set[j] = 0;
4582 if(p){
4583 if(!expand){
4584 is_set[j]++;
4585 if(!strvar)
4586 strvar = p;
4588 else if(expand_variables(tmp_20k_buf, SIZEOF_20KBUF, p,
4589 (var == &ps_global->vars[V_MAILCAP_PATH] ||
4590 var == &ps_global->vars[V_MIMETYPE_PATH]))){
4591 is_set[j]++;
4592 if(!strvar)
4593 strvar = p;
4598 /* Admin wants default, which is global_val. */
4599 if(var->is_fixed && var->fixed_val.p == NULL)
4600 strvar = var->global_val.p;
4602 if(var->current_val.p) /* free previous value */
4603 fs_give((void **)&var->current_val.p);
4605 if(strvar){
4606 if(!expand)
4607 var->current_val.p = cpystr(strvar);
4608 else{
4609 expand_variables(tmp_20k_buf, SIZEOF_20KBUF, strvar,
4610 (var == &ps_global->vars[V_MAILCAP_PATH] ||
4611 var == &ps_global->vars[V_MIMETYPE_PATH]));
4612 var->current_val.p = cpystr(tmp_20k_buf);
4615 else
4616 var->current_val.p = NULL;
4619 if(var->is_fixed && !is_inherit[4]){
4620 char **flist;
4621 int fixed_len, user_len;
4624 * sys mgr fixed this variable and user is trying to change it
4626 for(k = 1; !(ps_global->give_fixed_warning &&
4627 ps_global->fix_fixed_warning) && k <= 3; k++){
4628 if(is_set[k]){
4629 if(var->is_list){
4630 t = k==1 ? ((cmdline) ? var->cmdline_val.l : NULL) :
4631 k==2 ? var->post_user_val.l :
4632 var->main_user_val.l;
4634 /* If same length and same contents, don't warn. */
4635 for(flist=var->fixed_val.l; flist && *flist; flist++)
4636 ;/* just counting */
4638 fixed_len = var->fixed_val.l ? (flist - var->fixed_val.l)
4639 : 0;
4640 for(flist=t; flist && *flist; flist++)
4641 ;/* just counting */
4643 user_len = t ? (flist - t) : 0;
4644 if(user_len == fixed_len){
4645 for(i=0; i < user_len; i++){
4646 for(j=0; j < user_len; j++)
4647 if(!strucmp(t[i], var->fixed_val.l[j]))
4648 break;
4650 if(j == user_len){
4651 ps_global->give_fixed_warning = 1;
4652 if(k != 1)
4653 ps_global->fix_fixed_warning = 1;
4655 break;
4659 else{
4660 ps_global->give_fixed_warning = 1;
4661 if(k != 1)
4662 ps_global->fix_fixed_warning = 1;
4665 else{
4666 p = k==1 ? ((cmdline) ? var->cmdline_val.p : NULL) :
4667 k==2 ? var->post_user_val.p :
4668 var->main_user_val.p;
4670 if((var->fixed_val.p && !p) ||
4671 (!var->fixed_val.p && p) ||
4672 (var->fixed_val.p && p && strucmp(var->fixed_val.p, p))){
4673 ps_global->give_fixed_warning = 1;
4674 if(k != 1)
4675 ps_global->fix_fixed_warning = 1;
4684 void
4685 set_news_spec_current_val(int expand, int cmdline)
4687 struct variable *newsvar = &ps_global->vars[V_NEWS_SPEC];
4688 struct variable *fvar = &ps_global->vars[V_FOLDER_SPEC];
4690 /* check to see if it has a value */
4691 set_current_val(newsvar, expand, cmdline);
4694 * If no value, we might want to fake a value. We'll do that if
4695 * there is no news collection already defined in FOLDER_SPEC and if
4696 * there is also an NNTP_SERVER defined.
4698 if(!newsvar->current_val.l && ps_global->VAR_NNTP_SERVER &&
4699 ps_global->VAR_NNTP_SERVER[0] && ps_global->VAR_NNTP_SERVER[0][0] &&
4700 !news_in_folders(fvar)){
4701 char buf[MAXPATH];
4703 newsvar->global_val.l = (char **)fs_get(2 * sizeof(char *));
4704 snprintf(buf, sizeof(buf), "{%.*s/nntp}#news.[]", MAXPATH-20,
4705 ps_global->VAR_NNTP_SERVER[0]); /* MAXPATH = sizeof(buf) */
4706 newsvar->global_val.l[0] = cpystr(buf);
4707 newsvar->global_val.l[1] = NULL;
4708 set_current_val(newsvar, expand, cmdline);
4710 * But we're going to get rid of the fake global_val in case
4711 * things change.
4713 free_list_array(&newsvar->global_val.l);
4719 * Feature-list has to be handled separately from the other variables
4720 * because it is additive. The other variables choose one of command line,
4721 * or pine.conf, or pinerc. Feature list adds them. This could easily be
4722 * converted to a general purpose routine if we add more additive variables.
4724 * This works by replacing earlier values with later ones. That is, command
4725 * line settings have higher precedence than global settings and that is
4726 * accomplished by putting the command line features after the global
4727 * features in the list. When they are processed, the last one wins.
4729 * Feature-list also has a backwards compatibility hack.
4731 void
4732 set_feature_list_current_val(struct variable *var)
4734 char **list;
4735 char **list_fixed;
4736 char no_allow[50];
4737 int i, j, k, m,
4738 elems = 0;
4740 /* count the lists so we can allocate */
4741 for(m = 0; m < 6; m++){
4742 list = m==0 ? var->global_val.l :
4743 m==1 ? var->main_user_val.l :
4744 m==2 ? var->post_user_val.l :
4745 m==3 ? ps_global->feat_list_back_compat :
4746 m==4 ? var->cmdline_val.l :
4747 var->fixed_val.l;
4748 if(list)
4749 for(i = 0; list[i]; i++)
4750 elems++;
4753 list_fixed = var->fixed_val.l;
4755 if(var->current_val.l)
4756 free_list_array(&var->current_val.l);
4758 var->current_val.l = (char **)fs_get((elems+1) * sizeof(char *));
4761 * We need to warn the user if the sys mgr has restricted him or her
4762 * from changing a feature that he or she is trying to change.
4764 * We're not catching the old-growth macro since we're just comparing
4765 * strings. That is, it works correctly, but the user won't be warned
4766 * if the user old-growth and the mgr says no-quit-without-confirm.
4769 j = 0;
4770 strncpy(no_allow, "no-", 3);
4771 strncpy(no_allow+3, feature_list_name(F_ALLOW_CHANGING_FROM), sizeof(no_allow)-3-1);
4772 no_allow[sizeof(no_allow)-1] = '\0';
4774 for(m = 0; m < 6; m++){
4775 list = m==0 ? var->global_val.l :
4776 m==1 ? var->main_user_val.l :
4777 m==2 ? var->post_user_val.l :
4778 m==3 ? ps_global->feat_list_back_compat :
4779 m==4 ? var->cmdline_val.l :
4780 var->fixed_val.l;
4781 if(list)
4782 for(i = 0; list[i]; i++){
4783 var->current_val.l[j++] = cpystr(list[i]);
4785 /* this is the warning section */
4786 if(m >= 1 && m <= 4){
4787 for(k = 0; list_fixed && list_fixed[k]; k++){
4788 char *p, *q;
4789 p = list[i];
4790 q = list_fixed[k];
4791 if(!struncmp(p, "no-", 3))
4792 p += 3;
4793 if(!struncmp(q, "no-", 3))
4794 q += 3;
4795 if(!strucmp(q, p) && strucmp(list[i], list_fixed[k])){
4796 ps_global->give_fixed_warning = 1;
4797 if(m <= 2)
4798 ps_global->fix_fixed_warning = 1;
4802 else if(m == 5 && !strucmp(list[i], no_allow))
4803 ps_global->never_allow_changing_from = 1;
4807 #ifdef NEVER_ALLOW_CHANGING_FROM
4808 ps_global->never_allow_changing_from = 1;
4809 #endif
4811 var->current_val.l[j] = NULL;
4816 /*----------------------------------------------------------------------
4818 Expand Metacharacters/variables in file-names
4820 Read input line and expand shell-variables/meta-characters
4822 <input> <replaced by>
4823 $variable getenv("variable")
4824 ${variable} getenv("variable")
4825 ${variable:-defvalue} is getenv("variable") if variable is defined and
4826 is defvalue otherwise
4827 ~ getenv("HOME")
4828 \c c
4829 <others> <just copied>
4831 NOTE handling of braces in ${name} doesn't check much or do error recovery
4833 If colon_path is set, then we expand ~ not only at the start of linein,
4834 but also after each : in the path.
4836 ----*/
4837 #define is_allowed_envchar(C, S) ((S) == 0 ? !isspace((C)) && (C) != '/'\
4838 : (((C) >= 'a' && (C) <= 'z') \
4839 || ((C) >= 'A' && (C) <= 'Z') \
4840 || ((C) >= '0' && (C) <= '9')))
4842 char *
4843 expand_variables(char *lineout, size_t lineoutlen, char *linein, int colon_path)
4845 char *src = linein, *dest = lineout, *p;
4846 char *limit = lineout + lineoutlen;
4847 int envexpand = 0, sp;
4849 if(!linein)
4850 return(NULL);
4852 sp = strncmp(src,"LIT:pattern=\"/NICK=", strlen("LIT:pattern=\"/NICK=")) == 0;
4853 while(*src ){ /* something in input string */
4854 if(*src == '$' && *(src+1) == '$'){
4856 * $$ to escape chars we're interested in, else
4857 * it's up to the user of the variable to handle the
4858 * backslash...
4860 if(dest < limit)
4861 *dest++ = *++src; /* copy next as is */
4862 }else
4863 #if !(defined(DOS) || defined(OS2))
4864 if(*src == '\\' && *(src+1) == '$'){
4866 * backslash to escape chars we're interested in, else
4867 * it's up to the user of the variable to handle the
4868 * backslash...
4870 if(dest < limit)
4871 *dest++ = *++src; /* copy next as is */
4872 }else if(*src == '~' &&
4873 (src == linein || (colon_path && *(src-1) == ':'))){
4874 char buf[MAXPATH];
4875 int i;
4877 for(i = 0; i < sizeof(buf)-1 && src[i] && src[i] != '/'; i++)
4878 buf[i] = src[i];
4880 src += i; /* advance src pointer */
4881 buf[i] = '\0'; /* tie off buf string */
4882 fnexpand(buf, sizeof(buf)); /* expand the path */
4884 for(p = buf; dest < limit && (*dest = *p); p++, dest++)
4887 continue;
4888 }else
4889 #endif
4890 if(*src == '$'){ /* shell variable */
4891 char word[128+1], *colon = NULL, *rbrace = NULL;
4893 envexpand++; /* signal that we've expanded a var */
4894 src++; /* skip dollar */
4895 if(*src == '{'){ /* starts with brace? */
4896 src++;
4897 rbrace = strindex(src, '}');
4898 if(rbrace){
4899 /* look for default value */
4900 colon = strstr(src, ":-");
4901 if(colon && (rbrace < colon))
4902 colon = NULL;
4906 p = word;
4908 /* put the env variable to be looked up in word */
4909 if(rbrace){
4910 while(*src
4911 && (p-word < sizeof(word)-1)
4912 && ((colon && src < colon) || (!colon && src < rbrace))){
4913 if(isspace((unsigned char) *src)){
4915 * Illegal input. This should be an error of some
4916 * sort but instead of that we'll just backup to the
4917 * $ and treat it like it wasn't there.
4919 while(*src != '$')
4920 src--;
4922 envexpand--;
4923 goto just_copy;
4925 else
4926 *p++ = *src++;
4929 /* adjust src for next char */
4930 src = rbrace + 1;
4932 else{
4933 while(*src && is_allowed_envchar((unsigned char) *src, sp)
4934 && (p-word < sizeof(word)-1))
4935 *p++ = *src++;
4938 *p = '\0';
4940 if((p = getenv(word)) != NULL){ /* check for word in environment */
4941 while(*p && dest < limit)
4942 *dest++ = *p++;
4944 else if(colon){ /* else possible default value */
4945 p = colon + 2;
4946 while(*p && p < rbrace && dest < limit)
4947 *dest++ = *p++;
4950 continue;
4951 }else{ /* other cases: just copy */
4952 just_copy:
4953 if(dest < limit)
4954 *dest++ = *src;
4957 if(*src) /* next character (if any) */
4958 src++;
4961 if(dest < limit)
4962 *dest = '\0';
4963 else
4964 lineout[lineoutlen-1] = '\0';
4966 return((envexpand && lineout[0] == '\0') ? NULL : lineout);
4970 /*----------------------------------------------------------------------
4971 Sets login, full_username and home_dir
4973 Args: ps -- The Pine structure to put the user name, etc in
4975 Result: sets the fullname, login and home_dir field of the pine structure
4976 returns 0 on success, -1 if not.
4977 ----*/
4978 #define MAX_INIT_ERRS 10
4979 void
4980 init_error(struct pine *ps, int flags, int min_time, int max_time, char *message)
4982 int i;
4984 if(!ps->init_errs){
4985 ps->init_errs = (INIT_ERR_S *)fs_get((MAX_INIT_ERRS + 1) *
4986 sizeof(*ps->init_errs));
4987 memset(ps->init_errs, 0, (MAX_INIT_ERRS + 1) * sizeof(*ps->init_errs));
4990 for(i = 0; i < MAX_INIT_ERRS; i++)
4991 if(!(ps->init_errs)[i].message){
4992 (ps->init_errs)[i].message = cpystr(message);
4993 (ps->init_errs)[i].min_time = min_time;
4994 (ps->init_errs)[i].max_time = max_time;
4995 (ps->init_errs)[i].flags = flags;
4996 dprint((2, "%s\n", message ? message : "?"));
4997 break;
5002 /*----------------------------------------------------------------------
5003 Read and parse a pinerc file
5005 Args: Filename -- name of the .pinerc file to open and read
5006 vars -- The vars structure to store values in
5007 which_vars -- Whether the local or global values are being read
5009 Result:
5011 This may be the local file or the global file. The values found are
5012 merged with the values currently in vars. All values are strings and
5013 are malloced; and existing values will be freed before the assignment.
5014 Those that are <unset> will be left unset; their values will be NULL.
5015 ----*/
5016 void
5017 read_pinerc(PINERC_S *prc, struct variable *vars, ParsePinerc which_vars)
5019 char *filename, *file, *value, **lvalue, *line, *error;
5020 char *p, *p1, *free_file = NULL;
5021 struct variable *v;
5022 PINERC_LINE *pline = NULL;
5023 int line_count, was_quoted;
5024 int i;
5026 if(!prc)
5027 return;
5029 dprint((2, "reading_pinerc \"%s\"\n",
5030 prc->name ? prc->name : "?"));
5032 if(prc->type == Loc){
5033 filename = prc->name ? prc->name : "";
5034 file = free_file = read_file(filename, 0);
5037 * This is questionable. In case the user edits the pinerc
5038 * in Windows and adds a UTF-8 BOM, we skip it here. If the
5039 * user adds a Unicode BOM we're in trouble. We could write it
5040 * with the BOM ourselves but so far we leave it BOMless in
5041 * order that it's the same on Unix and Windows.
5043 if(BOM_UTF8(file))
5044 file += 3;
5046 else{
5047 if((file = read_remote_pinerc(prc, which_vars)) != NULL)
5048 ps_global->c_client_error[0] = '\0';
5050 free_file = file;
5053 if(file == NULL || *file == '\0'){
5054 #ifdef DEBUG
5055 if(file == NULL){
5056 dprint((2, "Open failed: %s\n", error_description(errno)));
5058 else{
5059 if(prc->type == Loc){
5060 dprint((1, "Read_pinerc: empty pinerc (new?)\n"));
5062 else{
5063 dprint((1, "Read_pinerc: new remote pinerc\n"));
5066 #endif /* DEBUG */
5068 if(which_vars == ParsePers){
5069 /* problems getting remote config */
5070 if(file == NULL && prc->type == RemImap){
5071 if(!pith_opt_remote_pinerc_failure
5072 || !(*pith_opt_remote_pinerc_failure)())
5073 exceptional_exit(_("Unable to read or write remote configuration"), -1);
5076 ps_global->first_time_user = 1;
5077 prc->outstanding_pinerc_changes = 1;
5080 return;
5082 else{
5083 if(prc->type == Loc &&
5084 (which_vars == ParseFixed || which_vars == ParseGlobal ||
5085 (can_access(filename, ACCESS_EXISTS) == 0 &&
5086 can_access(filename, EDIT_ACCESS) != 0))){
5087 prc->readonly = 1;
5088 if(prc == ps_global->prc)
5089 ps_global->readonly_pinerc = 1;
5093 * accept CRLF or LF newlines
5095 for(p = file; *p && *p != '\012'; p++)
5098 if(p > file && *p && *(p-1) == '\015') /* cvt crlf to lf */
5099 for(p1 = p - 1; (*p1 = *p) != '\0'; p++)
5100 if(!(*p == '\015' && *(p+1) == '\012'))
5101 p1++;
5104 dprint((2, "Read %d characters:\n", strlen(file)));
5106 if(which_vars == ParsePers || which_vars == ParsePersPost){
5107 /*--- Count up lines and allocate structures */
5108 for(line_count = 0, p = file; *p != '\0'; p++)
5109 if(*p == '\n')
5110 line_count++;
5112 prc->pinerc_lines = (PINERC_LINE *)
5113 fs_get((3 + line_count) * sizeof(PINERC_LINE));
5114 memset((void *)prc->pinerc_lines, 0,
5115 (3 + line_count) * sizeof(PINERC_LINE));
5116 pline = prc->pinerc_lines;
5119 for(p = file, line = file; *p != '\0';){
5120 /*----- Grab the line ----*/
5121 line = p;
5122 while(*p && *p != '\n')
5123 p++;
5124 if(*p == '\n'){
5125 *p++ = '\0';
5128 /*----- Comment Line -----*/
5129 if(*line == '#'){
5130 /* no comments in remote pinercs */
5131 if(pline && prc->type == Loc){
5132 pline->is_var = 0;
5133 pline->line = cpystr(line);
5134 pline++;
5136 continue;
5139 if(*line == '\0' || *line == '\t' || *line == ' '){
5140 p1 = line;
5141 while(*p1 == '\t' || *p1 == ' ')
5142 p1++;
5143 if(pline){
5145 * This could be a continuation line from some future
5146 * version of pine, or it could be a continuation line
5147 * from a PC-Pine variable we don't know about in unix.
5149 if(*p1 != '\0')
5150 pline->line = cpystr(line);
5151 else
5152 pline->line = cpystr("");
5153 pline->is_var = 0;
5154 pline++;
5156 continue;
5159 /*----- look up matching 'v' and leave "value" after '=' ----*/
5160 for(v = vars; *line && v->name; v++)
5161 if((i = strlen(v->name)) < strlen(line) && !struncmp(v->name,line,i)){
5162 int j;
5164 for(j = i; line[j] == ' ' || line[j] == '\t'; j++)
5167 if(line[j] == '='){ /* bingo! */
5168 for(value = &line[j+1];
5169 *value == ' ' || *value == '\t';
5170 value++)
5173 break;
5175 /* else either unrecognized var or bogus line */
5178 /*----- Didn't match any variable or bogus format -----*/
5180 * This could be a variable from some future
5181 * version of pine, or it could be a PC-Pine variable
5182 * we don't know about in unix. Either way, we want to preserve
5183 * it in the file.
5185 if(!v->name){
5186 if(pline){
5187 pline->is_var = 0;
5188 pline->line = cpystr(line);
5189 pline++;
5191 continue;
5195 * Previous versions have caused duplicate pinerc data to be
5196 * written to pinerc files. This clause erases the duplicate
5197 * information when we read it, and it will be removed from the file
5198 * if we call write_pinerc. We test to see if the same variable
5199 * appears later in the file, if so, we skip over it here.
5200 * We don't care about duplicates if this isn't a pinerc we might
5201 * write out, so include pline in the conditional.
5202 * Note that we will leave all of the duplicate comments and blank
5203 * lines in the file unless it is a remote pinerc. Luckily, the
5204 * bug that caused the duplicates only applied to remote pinercs,
5205 * so we should have that case covered.
5207 * If we find a duplicate, we point p to the start
5208 * of the next line that should be considered, and then skip back
5209 * to the top of the loop.
5211 if(pline && var_is_in_rest_of_file(v->name, p)){
5212 if(v->is_list)
5213 p = skip_over_this_var(line, p);
5215 continue;
5219 /*----- Obsolete variable, read it anyway below, might use it -----*/
5220 if(v->is_obsolete){
5221 if(pline){
5222 pline->obsolete_var = 1;
5223 pline->line = cpystr(line);
5224 pline->var = v;
5228 /*----- Variable is in the list but unused for some reason -----*/
5229 if(!v->is_used){
5230 if(pline){
5231 pline->is_var = 0;
5232 pline->line = cpystr(line);
5233 pline++;
5235 continue;
5238 /*--- Var is not user controlled, leave it alone for back compat ---*/
5239 if(!v->is_user && pline){
5240 pline->is_var = 0;
5241 pline->line = cpystr(line);
5242 pline++;
5243 continue;
5246 if(which_vars == ParseFixed)
5247 v->is_fixed = 1;
5249 /*---- variable is unset, or it's global but expands to nothing ----*/
5250 if(!*value
5251 || (which_vars == ParseGlobal
5252 && !expand_variables(tmp_20k_buf, SIZEOF_20KBUF, value,
5253 (v == &ps_global->vars[V_MAILCAP_PATH] ||
5254 v == &ps_global->vars[V_MIMETYPE_PATH])))){
5255 if(v->is_user && pline){
5256 pline->is_var = 1;
5257 pline->var = v;
5258 pline++;
5260 continue;
5263 /*--value is non-empty, store it handling quotes and trailing space--*/
5264 if(*value == '"' && !v->is_list && v->del_quotes){
5265 was_quoted = 1;
5266 value++;
5267 for(p1 = value; *p1 && *p1 != '"'; p1++);
5268 if(*p1 == '"')
5269 *p1 = '\0';
5270 else
5271 removing_trailing_white_space(value);
5272 }else
5273 was_quoted = 0;
5276 * List Entry Parsing
5278 * The idea is to parse a comma separated list of
5279 * elements, preserving quotes, and understanding
5280 * continuation lines (that is ',' == "\n ").
5281 * Quotes must be balanced within elements. Space
5282 * within elements is preserved, but leading and trailing
5283 * space is trimmed. This is a generic function, and it's
5284 * left to the the functions that use the lists to make sure
5285 * they contain valid data...
5287 if(v->is_list){
5289 was_quoted = 0;
5290 line_count = 0;
5291 p1 = value;
5292 while(1){ /* generous count of list elements */
5293 if(*p1 == '"') /* ignore ',' if quoted */
5294 was_quoted = (was_quoted) ? 0 : 1 ;
5296 if((*p1 == ',' && !was_quoted) || *p1 == '\n' || *p1 == '\0')
5297 line_count++; /* count this element */
5299 if(*p1 == '\0' || *p1 == '\n'){ /* deal with EOL */
5300 if(p1 < p || *p1 == '\n'){
5301 *p1++ = ','; /* fix null or newline */
5303 if(*p1 != '\t' && *p1 != ' '){
5304 *(p1-1) = '\0'; /* tie off list */
5305 p = p1; /* reset p */
5306 break;
5308 }else{
5309 p = p1; /* end of pinerc */
5310 break;
5312 }else
5313 p1++;
5316 error = NULL;
5317 lvalue = parse_list(value, line_count,
5318 v->del_quotes ? PL_REMSURRQUOT : PL_NONE,
5319 &error);
5320 if(error){
5321 dprint((1,
5322 "read_pinerc: ERROR: %s in %s = \"%s\"\n",
5323 error ? error : "?",
5324 v->name ? v->name : "?",
5325 value ? value : "?"));
5328 * Special case: turn "" strings into empty strings.
5329 * This allows users to turn off default lists. For example,
5330 * if smtp-server is set then a user could override smtp-server
5331 * with smtp-server="".
5333 for(i = 0; lvalue[i]; i++)
5334 if(lvalue[i][0] == '"' &&
5335 lvalue[i][1] == '"' &&
5336 lvalue[i][2] == '\0')
5337 lvalue[i][0] = '\0';
5340 if(pline){
5341 if(v->is_user && (which_vars == ParsePers || !v->is_onlymain)){
5342 if(v->is_list){
5343 char ***l;
5345 l = (which_vars == ParsePers) ? &v->main_user_val.l
5346 : &v->post_user_val.l;
5347 free_list_array(l);
5348 *l = lvalue;
5350 else{
5351 char **p;
5353 p = (which_vars == ParsePers) ? &v->main_user_val.p
5354 : &v->post_user_val.p;
5355 if(p && *p != NULL)
5356 fs_give((void **)p);
5358 *p = cpystr(value);
5361 if(pline){
5362 pline->is_var = 1;
5363 pline->var = v;
5364 pline->is_quoted = was_quoted;
5365 pline++;
5369 else if(which_vars == ParseGlobal){
5370 if(v->is_global){
5371 if(v->is_list){
5372 free_list_array(&v->global_val.l);
5373 v->global_val.l = lvalue;
5375 else{
5376 if(v->global_val.p != NULL)
5377 fs_give((void **) &(v->global_val.p));
5379 v->global_val.p = cpystr(value);
5383 else{ /* which_vars == ParseFixed */
5384 if(v->is_user || v->is_global){
5385 if(v->is_list){
5386 free_list_array(&v->fixed_val.l);
5387 v->fixed_val.l = lvalue;
5389 else{
5390 if(v->fixed_val.p != NULL)
5391 fs_give((void **) &(v->fixed_val.p));
5393 v->fixed_val.p = cpystr(value);
5398 #ifdef DEBUG
5399 if(v->is_list){
5400 char **l;
5401 l = (which_vars == ParsePers) ? v->main_user_val.l :
5402 (which_vars == ParsePersPost) ? v->post_user_val.l :
5403 (which_vars == ParseGlobal) ? v->global_val.l :
5404 v->fixed_val.l;
5405 if(l && *l && **l){
5406 dprint((5, " %20.20s : %s\n",
5407 v->name ? v->name : "?",
5408 *l ? *l : "?"));
5409 while(++l && *l && **l)
5410 dprint((5, " %20.20s : %s\n", "",
5411 *l ? *l : "?"));
5413 }else{
5414 char *p;
5415 p = (which_vars == ParsePers) ? v->main_user_val.p :
5416 (which_vars == ParsePersPost) ? v->post_user_val.p :
5417 (which_vars == ParseGlobal) ? v->global_val.p :
5418 v->fixed_val.p;
5419 if(p && *p)
5420 dprint((5, " %20.20s : %s\n",
5421 v->name ? v->name : "?",
5422 p ? p : "?"));
5424 #endif /* DEBUG */
5427 if(pline){
5428 pline->line = NULL;
5429 pline->is_var = 0;
5430 if(!prc->pinerc_written && prc->type == Loc){
5431 prc->pinerc_written = name_file_mtime(filename);
5432 dprint((5, "read_pinerc: time_pinerc_written = %ld\n",
5433 (long) prc->pinerc_written));
5437 if(free_file)
5438 fs_give((void **) &free_file);
5443 * Args varname The variable name we're looking for
5444 * begin Begin looking here
5446 * Returns 1 if variable varname appears in the rest of the file
5447 * 0 if not
5450 var_is_in_rest_of_file(char *varname, char *begin)
5452 char *p;
5454 if(!(varname && *varname && begin && *begin))
5455 return 0;
5457 p = begin;
5459 while((p = srchstr(p, varname)) != NULL){
5460 /* beginning of a line? */
5461 if(p > begin && (*(p-1) != '\n' && *(p-1) != '\r')){
5462 p++;
5463 continue;
5466 /* followed by [ SPACE ] < = > ? */
5467 p += strlen(varname);
5468 while(*p == ' ' || *p == '\t')
5469 p++;
5471 if(*p == '=')
5472 return 1;
5475 return 0;
5480 * Args begin Variable to skip starts here.
5481 * nextline This is where the next line starts. We need to know this
5482 * because the input has been mangled a little. A \0 has
5483 * replaced the \n at the end of the first line, but we can
5484 * use nextline to help us out of that quandry.
5486 * Return a pointer to the start of the first line after this variable
5487 * and all of its continuation lines.
5489 char *
5490 skip_over_this_var(char *begin, char *nextline)
5492 char *p;
5494 p = begin;
5496 while(1){
5497 if(*p == '\0' || *p == '\n'){ /* EOL */
5498 if(p < nextline || *p == '\n'){ /* there may be another line */
5499 p++;
5500 if(*p != ' ' && *p != '\t') /* no continuation line */
5501 return(p);
5503 else /* end of file */
5504 return(p);
5506 else
5507 p++;
5512 static char quotes[3] = {'"', '"', '\0'};
5513 /*----------------------------------------------------------------------
5514 Write out the .pinerc state information
5516 Args: ps -- The pine structure to take state to be written from
5517 which -- Which pinerc to write
5518 flags -- If bit WRP_NOUSER is set, then assume that there is
5519 not a user present to answer questions.
5521 This writes to a temporary file first, and then renames that to
5522 be the new .pinerc file to protect against disk error. This has the
5523 problem of possibly messing up file protections, ownership and links.
5524 ----*/
5526 write_pinerc(struct pine *ps, EditWhich which, int flags)
5528 char *p, *dir, *tmp = NULL, *pinrc;
5529 char *pval, **lval;
5530 char *linep = NULL, *lineq = NULL;
5531 int bc = 1;
5532 int buflen;
5533 PINERC_LINE *pline;
5534 struct variable *var;
5535 time_t mtime;
5536 char *filename;
5537 REMDATA_S *rd = NULL;
5538 PINERC_S *prc = NULL;
5539 STORE_S *so = NULL;
5540 #ifndef _WINDOWS
5541 struct stat sbuf;
5542 char *slink = NULL;
5543 #endif
5545 #define MAXPLINESIZE 10000
5547 dprint((2,"---- write_pinerc(%s) ----\n",
5548 (which == Main) ? "Main" : "Post"));
5550 switch(which){
5551 case Main:
5552 prc = ps ? ps->prc : NULL;
5553 break;
5554 case Post:
5555 prc = ps ? ps->post_prc : NULL;
5556 break;
5557 default:
5558 break;
5561 if(!prc)
5562 return(-1);
5564 if(prc->quit_to_edit){
5565 if(!(flags & WRP_NOUSER))
5566 quit_to_edit_msg(prc);
5568 return(-1);
5571 if(prc->type != Loc && !prc->readonly){
5573 bc = 0; /* don't do backcompat conversion */
5574 rd = prc->rd;
5575 if(!rd)
5576 return(-1);
5578 rd_check_remvalid(rd, -10L);
5580 if(rd->flags & REM_OUTOFDATE){
5581 if((flags & WRP_NOUSER) || unexpected_pinerc_change()){
5582 prc->outstanding_pinerc_changes = 1;
5583 if(!(flags & WRP_NOUSER))
5584 q_status_message1(SM_ORDER | SM_DING, 3, 3,
5585 "Pinerc \"%.200s\" NOT saved",
5586 prc->name ? prc->name : "");
5587 dprint((2, "write_pinerc: remote pinerc changed\n"));
5588 return(-1);
5590 else
5591 rd->flags &= ~REM_OUTOFDATE;
5594 rd_open_remote(rd);
5596 if(rd->access == ReadWrite){
5597 int ro;
5599 if((ro=rd_remote_is_readonly(rd)) || rd->flags & REM_OUTOFDATE){
5600 if(ro == 1){
5601 if(!(flags & WRP_NOUSER))
5602 q_status_message(SM_ORDER | SM_DING, 5, 15,
5603 _("Can't access remote config, changes NOT saved!"));
5604 dprint((1,
5605 "write_pinerc: Can't write to remote pinerc %s, aborting write\n",
5606 rd->rn ? rd->rn : "?"));
5608 else if(ro == 2){
5609 if(!(rd->flags & NO_META_UPDATE)){
5610 unsigned long save_chk_nmsgs;
5612 switch(rd->type){
5613 case RemImap:
5614 save_chk_nmsgs = rd->t.i.chk_nmsgs;
5615 rd->t.i.chk_nmsgs = 0;
5616 rd_write_metadata(rd, 0);
5617 rd->t.i.chk_nmsgs = save_chk_nmsgs;
5618 break;
5620 default:
5621 q_status_message(SM_ORDER | SM_DING, 3, 5,
5622 "Write_pinerc: Type not supported");
5623 break;
5627 if(!(flags & WRP_NOUSER))
5628 q_status_message1(SM_ORDER | SM_DING, 5, 15,
5629 _("No write permission for remote config %.200s, changes NOT saved!"),
5630 rd->rn);
5632 else{
5633 if(!(flags & WRP_NOUSER))
5634 q_status_message(SM_ORDER | SM_DING, 5, 15,
5635 _("Remote config changed, aborting our change to avoid damage..."));
5636 dprint((1,
5637 "write_pinerc: remote config %s changed since we started pine, aborting write\n",
5638 prc->name ? prc->name : "?"));
5641 rd->flags &= ~DO_REMTRIM;
5642 return(-1);
5645 filename = rd->lf;
5647 else{
5648 prc->readonly = 1;
5649 if(prc == ps->prc)
5650 ps->readonly_pinerc = 1;
5653 else
5654 filename = prc->name ? prc->name : "";
5656 pinrc = prc->name ? prc->name : "";
5658 if(prc->type == Loc){
5659 mtime = name_file_mtime(filename);
5660 if(prc->pinerc_written
5661 && prc->pinerc_written != mtime
5662 && ((flags & WRP_NOUSER) || unexpected_pinerc_change())){
5663 prc->outstanding_pinerc_changes = 1;
5665 if(!(flags & WRP_NOUSER))
5666 q_status_message1(SM_ORDER | SM_DING, 3, 3,
5667 "Pinerc \"%.200s\" NOT saved", pinrc);
5669 dprint((2,"write_pinerc: mtime mismatch: \"%s\": %ld != %ld\n",
5670 filename ? filename : "?",
5671 (long) prc->pinerc_written, (long) mtime));
5672 return(-1);
5676 /* don't write if pinerc is read-only */
5677 if(prc->readonly ||
5678 (filename &&
5679 can_access(filename, ACCESS_EXISTS) == 0 &&
5680 can_access(filename, EDIT_ACCESS) != 0)){
5681 prc->readonly = 1;
5682 if(prc == ps->prc)
5683 ps->readonly_pinerc = 1;
5685 if(!(flags & WRP_NOUSER))
5686 q_status_message1(SM_ORDER | SM_DING, 0, 5,
5687 _("Can't modify configuration file \"%.200s\": ReadOnly"),
5688 pinrc);
5689 dprint((2, "write_pinerc: fail because can't access pinerc\n"));
5691 if(rd)
5692 rd->flags &= ~DO_REMTRIM;
5694 return(-1);
5697 if(rd && rd->flags & NO_FILE){
5698 so = rd->sonofile;
5699 so_truncate(rd->sonofile, 0L); /* reset storage object */
5701 else{
5702 dir = ".";
5703 if((p = last_cmpnt(filename)) != NULL){
5704 *--p = '\0';
5705 dir = filename;
5708 #if defined(DOS) || defined(OS2)
5709 if(!(isalpha((unsigned char)dir[0]) && dir[1] == ':' && dir[2] == '\0')
5710 && (can_access(dir, EDIT_ACCESS) < 0 &&
5711 our_mkdir(dir, 0700) < 0))
5713 if(!(flags & WRP_NOUSER))
5714 q_status_message2(SM_ORDER | SM_DING, 3, 5,
5715 /* TRANSLATORS: first argument is a filename, second
5716 arg is the text of the error message */
5717 _("Error creating \"%.200s\" : %.200s"), dir,
5718 error_description(errno));
5719 if(rd)
5720 rd->flags &= ~DO_REMTRIM;
5722 return(-1);
5725 tmp = temp_nam(dir, "rc");
5727 if(*dir && tmp && !in_dir(dir, tmp)){
5728 our_unlink(tmp);
5729 fs_give((void **)&tmp);
5732 if(p)
5733 *p = '\\';
5735 if(tmp == NULL)
5736 goto io_err;
5738 #else /* !DOS */
5739 tmp = temp_nam((*dir) ? dir : "/", "pinerc");
5742 * If temp_nam can't write in dir it puts the temp file in a
5743 * temp directory, which won't help us when we go to rename.
5745 if(*dir && tmp && !in_dir(dir, tmp)){
5746 our_unlink(tmp);
5747 fs_give((void **)&tmp);
5750 if(p)
5751 *p = '/';
5753 if(tmp == NULL)
5754 goto io_err;
5756 #endif /* !DOS */
5758 if((so = so_get(FileStar, tmp, WRITE_ACCESS)) == NULL)
5759 goto io_err;
5762 if(!(flags & WRP_PRESERV_WRITTEN))
5763 for(var = ps->vars; var->name != NULL; var++)
5764 var->been_written = 0;
5766 if(prc->type == Loc && ps->first_time_user &&
5767 !so_puts(so, native_nl(cf_text_comment)))
5768 goto io_err;
5770 linep = fs_get((MAXPLINESIZE+1)*sizeof(char));
5771 lineq = fs_get((MAXPLINESIZE+1)*sizeof(char));
5772 buflen = MAXPLINESIZE;
5774 /* Write out what was in the .pinerc */
5775 for(pline = prc->pinerc_lines;
5776 pline && (pline->is_var || pline->line); pline++){
5777 if(pline->is_var){
5778 var = pline->var;
5780 if(var->is_list)
5781 lval = LVAL(var, which);
5782 else
5783 pval = PVAL(var, which);
5785 /* variable is not set */
5786 if((var->is_list && (!lval || !lval[0])) ||
5787 (!var->is_list && !pval)){
5788 /* leave null variables out of remote pinerc */
5789 if(prc->type == Loc &&
5790 (!so_puts(so, var->name) || !so_puts(so, "=") ||
5791 !so_puts(so, NEWLINE)))
5792 goto io_err;
5794 /* var is set to empty string */
5795 else if((var->is_list && lval[0][0] == '\0') ||
5796 (!var->is_list && pval[0] == '\0')){
5797 if(!so_puts(so, var->name) || !so_puts(so, "=") ||
5798 !so_puts(so, quotes) || !so_puts(so, NEWLINE))
5799 goto io_err;
5801 else{
5802 if(var->is_list){
5803 int i = 0;
5805 for(i = 0; lval[i]; i++){
5806 if(strlen(var->name)
5807 + (lval[i][0] ? strlen(lval[i]) : 5) > buflen){
5808 buflen = strlen(var->name)
5809 + (lval[i][0] ? strlen(lval[i]) : 5);
5810 fs_resize((void **)&linep, (buflen+1)*sizeof(char));
5811 fs_resize((void **)&lineq, (buflen+1)*sizeof(char));
5813 snprintf(linep, buflen+1, "%s%s%s%s%s",
5814 (i) ? "\t" : var->name,
5815 (i) ? "" : "=",
5816 lval[i][0] ? lval[i] : quotes,
5817 lval[i+1] ? "," : "", NEWLINE);
5818 linep[buflen] = '\0';
5819 if(!so_puts(so, bc ? backcompat_convert_from_utf8(&lineq, buflen+1, linep) : linep))
5820 goto io_err;
5823 else{
5824 if(strlen(var->name)
5825 + (pval[0] ? strlen(pval) : 5) > buflen){
5826 buflen = strlen(var->name)
5827 + (pval[0] ? strlen(pval) : 5);
5828 fs_resize((void **)&linep, (buflen+1)*sizeof(char));
5829 fs_resize((void **)&lineq, (buflen+1)*sizeof(char));
5831 snprintf(linep, buflen+1, "%s=%s%s%s%s",
5832 var->name,
5833 (pline->is_quoted && pval[0] != '\"')
5834 ? "\"" : "",
5835 pval,
5836 (pline->is_quoted && pval[0] != '\"')
5837 ? "\"" : "", NEWLINE);
5838 linep[buflen] = '\0';
5839 if(!so_puts(so, bc ? backcompat_convert_from_utf8(&lineq, buflen+1, linep) : linep))
5840 goto io_err;
5844 var->been_written = 1;
5846 }else{
5848 * The description text should be changed into a message
5849 * about the variable being obsolete when a variable is
5850 * moved to obsolete status. We add that message before
5851 * the variable unless it is already there. However, we
5852 * leave the variable itself in case the user runs an old
5853 * version of pine again. Note that we have read in the
5854 * value of the variable in read_pinerc and translated it
5855 * into a new variable if appropriate.
5857 if(pline->obsolete_var && prc->type == Loc){
5858 if(pline <= prc->pinerc_lines || (pline-1)->line == NULL ||
5859 strlen((pline-1)->line) < 3 ||
5860 strucmp((pline-1)->line+2, pline->var->descrip) != 0)
5861 if(!so_puts(so, "# ") ||
5862 !so_puts(so, native_nl(pline->var->descrip)) ||
5863 !so_puts(so, NEWLINE))
5864 goto io_err;
5867 /* remove comments from remote pinercs */
5868 if((prc->type == Loc ||
5869 (pline->line[0] != '#' && pline->line[0] != '\0')) &&
5870 (!so_puts(so, pline->line) || !so_puts(so, NEWLINE)))
5871 goto io_err;
5875 /* Now write out all the variables not in the .pinerc */
5876 for(var = ps->vars; var->name != NULL; var++){
5877 if(!var->is_user || var->been_written || !var->is_used ||
5878 var->is_obsolete || (var->is_onlymain && which != Main))
5879 continue;
5881 if(var->is_list)
5882 lval = LVAL(var, which);
5883 else
5884 pval = PVAL(var, which);
5887 * set description to NULL to eliminate preceding
5888 * blank and comment line.
5890 if(prc->type == Loc && var->descrip && *var->descrip &&
5891 (!so_puts(so, NEWLINE) || !so_puts(so, "# ") ||
5892 !so_puts(so, native_nl(var->descrip)) || !so_puts(so, NEWLINE)))
5893 goto io_err;
5895 /* variable is not set */
5896 /** Don't know what the global_val thing is for. SH, Mar 00 **/
5897 if((var->is_list && (!lval || (!lval[0] && !var->global_val.l))) ||
5898 (!var->is_list && !pval)){
5899 /* leave null variables out of remote pinerc */
5900 if(prc->type == Loc &&
5901 (!so_puts(so, var->name) || !so_puts(so, "=") ||
5902 !so_puts(so, NEWLINE)))
5903 goto io_err;
5905 /* var is set to empty string */
5906 else if((var->is_list && (!lval[0] || !lval[0][0]))
5907 || (!var->is_list && pval[0] == '\0')){
5908 if(!so_puts(so, var->name) || !so_puts(so, "=") ||
5909 !so_puts(so, quotes) || !so_puts(so, NEWLINE))
5910 goto io_err;
5912 else if(var->is_list){
5913 int i = 0;
5915 for(i = 0; lval[i] ; i++){
5916 if(strlen(var->name)
5917 + (lval[i][0] ? strlen(lval[i]) : 5) > buflen){
5918 buflen = strlen(var->name)
5919 + (lval[i][0] ? strlen(lval[i]) : 5);
5920 fs_resize((void **)&linep, (buflen+1)*sizeof(char));
5921 fs_resize((void **)&lineq, (buflen+1)*sizeof(char));
5923 snprintf(linep, buflen+1, "%s%s%s%s%s",
5924 (i) ? "\t" : var->name,
5925 (i) ? "" : "=",
5926 lval[i],
5927 lval[i+1] ? "," : "", NEWLINE);
5928 linep[buflen] = '\0';
5929 if(!so_puts(so, bc ? backcompat_convert_from_utf8(&lineq, buflen+1, linep) : linep))
5930 goto io_err;
5933 else{
5934 char *pconverted;
5936 if(strlen(pval) > buflen){
5937 buflen = strlen(pval) + 1;
5938 fs_resize((void **)&linep, (buflen+1)*sizeof(char));
5939 fs_resize((void **)&lineq, (buflen+1)*sizeof(char));
5941 pconverted = bc ? backcompat_convert_from_utf8(&lineq, buflen+1, pval) : pval;
5943 if(!so_puts(so, var->name) || !so_puts(so, "=") ||
5944 !so_puts(so, pconverted) || !so_puts(so, NEWLINE))
5945 goto io_err;
5949 if(!(rd && rd->flags & NO_FILE)){
5950 char *realfilename;
5951 int realfilename_malloced;
5953 if(so_give(&so)) goto io_err;
5955 #ifndef _WINDOWS
5956 if ((realfilename = realpath(filename, NULL)) != NULL)
5957 realfilename_malloced = 1;
5958 else
5959 goto io_err;
5960 #else
5961 realfilename = filename;
5962 realfilename_malloced = 0;
5963 #endif /* _WINDOWS */
5964 if(realfilename != NULL){
5965 int r;
5966 file_attrib_copy(tmp, realfilename);
5967 r = rename_file(tmp, realfilename);
5968 if(realfilename_malloced != 0)
5969 free((void *)realfilename);
5970 if(r < 0) goto io_err;
5974 if(prc->type != Loc){
5975 int e, we_cancel;
5976 char datebuf[200];
5978 datebuf[0] = '\0';
5979 we_cancel = 0;
5981 if(!(flags & WRP_NOUSER))
5982 we_cancel = busy_cue(_("Copying to remote config"), NULL, 1);
5984 if((e = rd_update_remote(rd, datebuf)) != 0){
5985 dprint((1,
5986 "write_pinerc: error copying from %s to %s\n",
5987 rd->lf ? rd->lf : "<memory>", rd->rn ? rd->rn : "?"));
5988 if(!(flags & WRP_NOUSER)){
5989 q_status_message2(SM_ORDER | SM_DING, 3, 5,
5990 _("Error copying to %.200s: %.200s"),
5991 rd->rn, error_description(errno));
5993 q_status_message(SM_ORDER | SM_DING, 5, 5,
5994 _("Copy of config to remote folder failed, changes NOT saved remotely"));
5997 else{
5998 rd_update_metadata(rd, datebuf);
5999 rd->read_status = 'W';
6000 rd_trim_remdata(&rd);
6001 rd_close_remote(rd);
6004 if(we_cancel)
6005 cancel_busy_cue(-1);
6008 prc->outstanding_pinerc_changes = 0;
6010 if(prc->type == Loc){
6011 prc->pinerc_written = name_file_mtime(filename);
6012 dprint((2, "wrote pinerc: %s: time_pinerc_written = %ld\n",
6013 pinrc ? pinrc : "?", (long) prc->pinerc_written));
6015 else{
6016 dprint((2, "wrote pinerc: %s\n", pinrc ? pinrc : "?"));
6019 if(tmp){
6020 our_unlink(tmp);
6021 fs_give((void **)&tmp);
6024 if(linep) fs_give((void **)&linep);
6025 if(lineq) fs_give((void **)&lineq);
6027 return(0);
6029 io_err:
6030 if(!(flags & WRP_NOUSER))
6031 q_status_message2(SM_ORDER | SM_DING, 3, 5,
6032 _("Error saving configuration in \"%.200s\": %.200s"),
6033 pinrc, error_description(errno));
6035 dprint((1, "Error writing %s : %s\n", pinrc ? pinrc : "?",
6036 error_description(errno)));
6037 if(rd)
6038 rd->flags &= ~DO_REMTRIM;
6039 if(tmp){
6040 our_unlink(tmp);
6041 fs_give((void **)&tmp);
6044 if(linep) fs_give((void **)&linep);
6045 if(lineq) fs_give((void **)&lineq);
6047 return(-1);
6052 * The srcstr is UTF-8. In order to help the user with
6053 * running this pine and an old pre-alpine pine on the same config
6054 * file we attempt to convert the values of the config variables
6055 * to the user's character set before writing.
6056 * parameters: char **buf. Memory of size_t buflen allocated by caller.
6058 char *
6059 backcompat_convert_from_utf8(char **buf, size_t buflen, char *srcstr)
6061 char *converted = NULL;
6062 char *p;
6063 int its_ascii = 1;
6066 for(p = srcstr; *p && its_ascii; p++)
6067 if(*p & 0x80)
6068 its_ascii = 0;
6070 /* if it is ascii, go with that */
6071 if(its_ascii){
6072 strncpy(*buf, srcstr, buflen);
6073 converted = *buf;
6074 (*buf)[buflen-1] = '\0';
6076 else{
6077 char *trythischarset = NULL;
6080 * If it is possible to translate the UTF-8
6081 * string into the user's character set then
6082 * do that. For backwards compatibility with
6083 * old pines.
6085 if(ps_global->keyboard_charmap && ps_global->keyboard_charmap[0])
6086 trythischarset = ps_global->keyboard_charmap;
6087 else if(ps_global->display_charmap && ps_global->display_charmap[0])
6088 trythischarset = ps_global->display_charmap;
6090 if(trythischarset){
6091 SIZEDTEXT src, dst;
6093 src.data = (unsigned char *) srcstr;
6094 src.size = strlen(srcstr);
6095 memset(&dst, 0, sizeof(dst));
6096 if(utf8_cstext(&src, trythischarset, &dst, 0)){
6097 if(dst.data){
6098 strncpy(*buf, (char *) dst.data, buflen);
6099 (*buf)[buflen-1] = '\0';
6100 fs_give((void **) &dst.data);
6105 if(!converted){
6106 strncpy(*buf, srcstr, buflen);
6107 (*buf)[buflen-1] = '\0';
6108 converted = *buf;
6112 return(converted);
6117 * Given a unix-style source string which may contain LFs,
6118 * convert those to CRLFs if appropriate.
6120 * Returns a pointer to the converted string. This will be a string
6121 * stored in tmp_20k_buf.
6123 * This is just used for the variable descriptions in the pinerc file. It
6124 * could certainly be fancier. It simply converts all \n to NEWLINE.
6126 char *
6127 native_nl(char *src)
6129 char *q, *p;
6131 tmp_20k_buf[0] = '\0';
6133 if(src){
6134 for(q = (char *)tmp_20k_buf; *src; src++){
6135 if(*src == '\n'){
6136 for(p = NEWLINE; *p; p++)
6137 *q++ = *p;
6139 else
6140 *q++ = *src;
6143 *q = '\0';
6146 return((char *)tmp_20k_buf);
6150 void
6151 quit_to_edit_msg(PINERC_S *prc)
6153 /* TRANSLATORS: The %s is either "Postload " or nothing. A Postload config file
6154 is a type of config file. */
6155 q_status_message1(SM_ORDER, 3, 4, _("Must quit Alpine to change %sconfig file."),
6156 (prc == ps_global->post_prc) ? "Postload " : "");
6160 /*------------------------------------------------------------
6161 Return TRUE if the given string was a feature name present in the
6162 pinerc as it was when pine was started...
6163 ----*/
6165 var_in_pinerc(char *s)
6167 PINERC_LINE *pline;
6169 for(pline = ps_global->prc ? ps_global->prc->pinerc_lines : NULL;
6170 pline && (pline->var || pline->line); pline++)
6171 if(pline->var && pline->var->name && !strucmp(s, pline->var->name))
6172 return(1);
6174 for(pline = ps_global->post_prc ? ps_global->post_prc->pinerc_lines : NULL;
6175 pline && (pline->var || pline->line); pline++)
6176 if(pline->var && pline->var->name && !strucmp(s, pline->var->name))
6177 return(1);
6179 return(0);
6183 /*------------------------------------------------------------
6184 Free resources associated with pinerc_lines data
6185 ----*/
6186 void
6187 free_pinerc_lines(PINERC_LINE **pinerc_lines)
6189 PINERC_LINE *pline;
6191 if(pinerc_lines && *pinerc_lines){
6192 for(pline = *pinerc_lines; pline->var || pline->line; pline++)
6193 if(pline->line)
6194 fs_give((void **)&pline->line);
6196 fs_give((void **)pinerc_lines);
6201 /*------------------------------------------------------------
6202 Dump out a global pine.conf on the standard output with fresh
6203 comments. Preserves variables currently set in SYSTEM_PINERC, if any.
6204 ----*/
6205 void
6206 dump_global_conf(void)
6208 FILE *f;
6209 struct variable *var;
6210 PINERC_S *prc;
6212 prc = new_pinerc_s(SYSTEM_PINERC);
6213 read_pinerc(prc, variables, ParseGlobal);
6214 if(prc)
6215 free_pinerc_s(&prc);
6217 f = stdout;
6218 if(f == NULL)
6219 goto io_err;
6221 fprintf(f, "# %s -- system wide pine configuration\n#\n",
6222 SYSTEM_PINERC);
6223 fprintf(f, "# Values here affect all pine users unless they've overridden the values\n");
6224 fprintf(f, "# in their .pinerc files. A copy of this file with current comments may\n");
6225 fprintf(f, "# be obtained by running \"pine -conf\". It will be printed to standard output.\n#\n");
6226 fprintf(f,"# For a variable to be unset its value must be null/blank. This is not the\n");
6227 fprintf(f,"# same as the value of \"empty string\", which can be used to effectively\n");
6228 fprintf(f,"# \"unset\" a variable that has a default or previously assigned value.\n");
6229 fprintf(f,"# To set a variable to the empty string its value should be \"\".\n");
6230 fprintf(f,"# Switch variables are set to either \"yes\" or \"no\", and default to \"no\".\n");
6231 fprintf(f,"# Except for feature-list items, which are additive, values set in the\n");
6232 fprintf(f,"# .pinerc file replace those in pine.conf, and those in pine.conf.fixed\n");
6233 fprintf(f,"# over-ride all others. Features can be over-ridden in .pinerc or\n");
6234 fprintf(f,"# pine.conf.fixed by pre-pending the feature name with \"no-\".\n#\n");
6235 fprintf(f,"# (These comments are automatically inserted.)\n");
6237 for(var = variables; var->name != NULL; var++){
6238 if(!var->is_global || !var->is_used || var->is_obsolete)
6239 continue;
6241 if(var->descrip && *var->descrip){
6242 if(fprintf(f, "\n# %s\n", var->descrip) == EOF)
6243 goto io_err;
6246 if(var->is_list){
6247 if(var->global_val.l == NULL){
6248 if(fprintf(f, "%s=\n", var->name) == EOF)
6249 goto io_err;
6250 }else{
6251 int i;
6253 for(i=0; var->global_val.l[i]; i++)
6254 if(fprintf(f, "%s%s%s%s\n", (i) ? "\t" : var->name,
6255 (i) ? "" : "=", var->global_val.l[i],
6256 var->global_val.l[i+1] ? ",":"") == EOF)
6257 goto io_err;
6259 }else{
6260 if(var->global_val.p == NULL){
6261 if(fprintf(f, "%s=\n", var->name) == EOF)
6262 goto io_err;
6263 }else if(strlen(var->global_val.p) == 0){
6264 if(fprintf(f, "%s=\"\"\n", var->name) == EOF)
6265 goto io_err;
6266 }else{
6267 if(fprintf(f,"%s=%s\n",var->name,var->global_val.p) == EOF)
6268 goto io_err;
6272 exit(0);
6275 io_err:
6276 fprintf(stderr, "Error writing config to stdout: %s\n",
6277 error_description(errno));
6278 exit(-1);
6282 /*------------------------------------------------------------
6283 Dump out a pinerc to filename with fresh
6284 comments. Preserves variables currently set in pinerc, if any.
6285 ----*/
6286 void
6287 dump_new_pinerc(char *filename)
6289 FILE *f;
6290 struct variable *var;
6291 char buf[MAXPATH], *p;
6292 PINERC_S *prc;
6295 p = ps_global->pinerc;
6297 #if defined(DOS) || defined(OS2)
6298 if(!ps_global->pinerc){
6299 char *p;
6301 if(p = getenv("PINERC")){
6302 ps_global->pinerc = cpystr(p);
6303 }else{
6304 char buf2[MAXPATH];
6305 build_path(buf2, ps_global->home_dir, DF_PINEDIR, sizeof(buf2));
6306 build_path(buf, buf2, SYSTEM_PINERC, sizeof(buf));
6309 p = buf;
6311 #else /* !DOS */
6312 if(!ps_global->pinerc){
6313 build_path(buf, ps_global->home_dir, ".pinerc", sizeof(buf));
6314 p = buf;
6316 #endif /* !DOS */
6318 prc = new_pinerc_s(p);
6319 read_pinerc(prc, variables, ParsePers);
6320 if(prc)
6321 free_pinerc_s(&prc);
6323 f = NULL;;
6324 if(filename[0] == '\0'){
6325 fprintf(stderr, "Missing argument to \"-pinerc\".\n");
6326 }else if(!strcmp(filename, "-")){
6327 f = stdout;
6328 }else{
6329 f = our_fopen(filename, "wb");
6332 if(f == NULL)
6333 goto io_err;
6335 if(fprintf(f, "%s", cf_text_comment) == EOF)
6336 goto io_err;
6338 for(var = variables; var->name != NULL; var++){
6339 dprint((7,"write_pinerc: %s = %s\n",
6340 var->name ? var->name : "?",
6341 var->main_user_val.p ? var->main_user_val.p : "<not set>"));
6342 if(!var->is_user || !var->is_used || var->is_obsolete)
6343 continue;
6346 * set description to NULL to eliminate preceding
6347 * blank and comment line.
6349 if(var->descrip && *var->descrip){
6350 if(fprintf(f, "\n# %s\n", var->descrip) == EOF)
6351 goto io_err;
6354 if(var->is_list){
6355 if(var->main_user_val.l == NULL){
6356 if(fprintf(f, "%s=\n", var->name) == EOF)
6357 goto io_err;
6358 }else{
6359 int i;
6361 for(i=0; var->main_user_val.l[i]; i++)
6362 if(fprintf(f, "%s%s%s%s\n", (i) ? "\t" : var->name,
6363 (i) ? "" : "=", var->main_user_val.l[i],
6364 var->main_user_val.l[i+1] ? ",":"") == EOF)
6365 goto io_err;
6367 }else{
6368 if(var->main_user_val.p == NULL){
6369 if(fprintf(f, "%s=\n", var->name) == EOF)
6370 goto io_err;
6371 }else if(strlen(var->main_user_val.p) == 0){
6372 if(fprintf(f, "%s=\"\"\n", var->name) == EOF)
6373 goto io_err;
6374 }else{
6375 if(fprintf(f,"%s=%s\n",var->name,var->main_user_val.p) == EOF)
6376 goto io_err;
6380 exit(0);
6383 io_err:
6384 snprintf(buf, sizeof(buf), "Error writing config to %s: %s\n",
6385 filename, error_description(errno));
6386 exceptional_exit(buf, -1);
6390 /*----------------------------------------------------------------------
6391 Set a user variable and save the .pinerc
6393 Args: var -- The index of the variable to set from conftype.h (V_....)
6394 value -- The string to set the value to
6396 Result: -1 is returned on failure and 0 is returned on success
6398 The vars data structure is updated and the pinerc saved.
6399 ----*/
6401 set_variable(int var, char *value, int expand, int commit, EditWhich which)
6403 struct variable *v;
6404 char **apval;
6405 PINERC_S *prc;
6407 v = &ps_global->vars[var];
6409 if(!v->is_user)
6410 panic1("Trying to set non-user variable %s", v->name);
6412 /* Override value of which, at most one of these should be set */
6413 if(v->is_onlymain)
6414 which = Main;
6415 else if(v->is_outermost)
6416 which = ps_global->ew_for_except_vars;
6418 apval = APVAL(v, which);
6420 if(!apval)
6421 return(-1);
6423 if(*apval)
6424 fs_give((void **)apval);
6426 *apval = value ? cpystr(value) : NULL;
6427 set_current_val(v, expand, FALSE);
6429 switch(which){
6430 case Main:
6431 prc = ps_global->prc;
6432 break;
6433 case Post:
6434 prc = ps_global->post_prc;
6435 break;
6436 default:
6437 break;
6440 if(prc)
6441 prc->outstanding_pinerc_changes = 1;
6443 return(commit ? write_pinerc(ps_global, which, WRP_NONE) : 0);
6447 /*----------------------------------------------------------------------
6448 Set a user variable list and save the .pinerc
6450 Args: var -- The index of the variable to set from conftype.h (V_....)
6451 lvalue -- The list to set the value to
6453 Result: -1 is returned on failure and 0 is returned on success
6455 The vars data structure is updated and if write_it, the pinerc is saved.
6456 ----*/
6458 set_variable_list(int var, char **lvalue, int write_it, EditWhich which)
6460 char ***alval;
6461 int i;
6462 struct variable *v = &ps_global->vars[var];
6463 PINERC_S *prc;
6465 if(!v->is_user || !v->is_list)
6466 panic1("BOTCH: Trying to set non-user or non-list variable %s", v->name);
6468 /* Override value of which, at most one of these should be set */
6469 if(v->is_onlymain)
6470 which = Main;
6471 else if(v->is_outermost)
6472 which = ps_global->ew_for_except_vars;
6474 alval = ALVAL(v, which);
6475 if(!alval)
6476 return(-1);
6478 if(*alval)
6479 free_list_array(alval);
6481 if(lvalue){
6482 for(i = 0; lvalue[i] ; i++) /* count elements */
6485 *alval = (char **) fs_get((i+1) * sizeof(char *));
6487 for(i = 0; lvalue[i] ; i++)
6488 (*alval)[i] = cpystr(lvalue[i]);
6490 (*alval)[i] = NULL;
6493 set_current_val(v, TRUE, FALSE);
6495 switch(which){
6496 case Main:
6497 prc = ps_global->prc;
6498 break;
6499 case Post:
6500 prc = ps_global->post_prc;
6501 break;
6502 default:
6503 break;
6506 if(prc)
6507 prc->outstanding_pinerc_changes = 1;
6509 return(write_it ? write_pinerc(ps_global, which, WRP_NONE) : 0);
6513 void
6514 set_current_color_vals(struct pine *ps)
6516 struct variable *vars = ps->vars;
6517 int later_color_is_set = 0;
6519 set_current_val(&vars[V_NORM_FORE_COLOR], TRUE, TRUE);
6520 set_current_val(&vars[V_NORM_BACK_COLOR], TRUE, TRUE);
6521 pico_nfcolor(VAR_NORM_FORE_COLOR);
6522 pico_nbcolor(VAR_NORM_BACK_COLOR);
6524 set_current_val(&vars[V_REV_FORE_COLOR], TRUE, TRUE);
6525 set_current_val(&vars[V_REV_BACK_COLOR], TRUE, TRUE);
6526 pico_rfcolor(VAR_REV_FORE_COLOR);
6527 pico_rbcolor(VAR_REV_BACK_COLOR);
6529 set_color_val(&vars[V_TITLE_FORE_COLOR], 1);
6530 set_color_val(&vars[V_TITLECLOSED_FORE_COLOR], 0);
6531 set_color_val(&vars[V_FOLDER_FORE_COLOR], 0);
6532 set_color_val(&vars[V_DIRECTORY_FORE_COLOR], 0);
6533 set_color_val(&vars[V_FOLDER_LIST_FORE_COLOR], 0);
6534 set_color_val(&vars[V_STATUS_FORE_COLOR], 1);
6535 set_color_val(&vars[V_KEYLABEL_FORE_COLOR], 1);
6536 set_color_val(&vars[V_KEYNAME_FORE_COLOR], 1);
6537 set_color_val(&vars[V_SLCTBL_FORE_COLOR], 1);
6538 set_color_val(&vars[V_METAMSG_FORE_COLOR], 1);
6539 set_color_val(&vars[V_PROMPT_FORE_COLOR], 1);
6540 set_color_val(&vars[V_HEADER_GENERAL_FORE_COLOR], 1);
6541 set_color_val(&vars[V_IND_PLUS_FORE_COLOR], 0);
6542 set_color_val(&vars[V_IND_IMP_FORE_COLOR], 0);
6543 set_color_val(&vars[V_IND_DEL_FORE_COLOR], 0);
6544 set_color_val(&vars[V_IND_HIPRI_FORE_COLOR], 0);
6545 set_color_val(&vars[V_IND_LOPRI_FORE_COLOR], 0);
6546 set_color_val(&vars[V_IND_ANS_FORE_COLOR], 0);
6547 set_color_val(&vars[V_IND_NEW_FORE_COLOR], 0);
6548 set_color_val(&vars[V_IND_REC_FORE_COLOR], 0);
6549 set_color_val(&vars[V_IND_FWD_FORE_COLOR], 0);
6550 set_color_val(&vars[V_IND_UNS_FORE_COLOR], 0);
6551 set_color_val(&vars[V_IND_ARR_FORE_COLOR], 0);
6552 set_color_val(&vars[V_IND_SUBJ_FORE_COLOR], 0);
6553 set_color_val(&vars[V_IND_FROM_FORE_COLOR], 0);
6554 set_color_val(&vars[V_IND_OP_FORE_COLOR], 0);
6555 set_color_val(&vars[V_INCUNSEEN_FORE_COLOR], 0);
6556 set_color_val(&vars[V_SIGNATURE_FORE_COLOR], 0);
6558 set_current_val(&ps->vars[V_INDEX_TOKEN_COLORS], TRUE, TRUE);
6559 set_current_val(&ps->vars[V_VIEW_HDR_COLORS], TRUE, TRUE);
6560 set_current_val(&ps->vars[V_KW_COLORS], TRUE, TRUE);
6561 set_custom_spec_colors(ps);
6564 * Set up the quoting colors. If a later color is set but not an earlier
6565 * color we set the earlier color to Normal to make it easier when
6566 * we go to use the colors. However, if the only quote colors set are
6567 * Normal that is the same as no settings, so delete them.
6569 set_color_val(&vars[V_QUOTE1_FORE_COLOR], 0);
6570 set_color_val(&vars[V_QUOTE2_FORE_COLOR], 0);
6571 set_color_val(&vars[V_QUOTE3_FORE_COLOR], 0);
6573 if((!(VAR_QUOTE3_FORE_COLOR && VAR_QUOTE3_BACK_COLOR) ||
6574 (!strucmp(VAR_QUOTE3_FORE_COLOR, VAR_NORM_FORE_COLOR) &&
6575 !strucmp(VAR_QUOTE3_BACK_COLOR, VAR_NORM_BACK_COLOR))) &&
6576 (!(VAR_QUOTE2_FORE_COLOR && VAR_QUOTE2_BACK_COLOR) ||
6577 (!strucmp(VAR_QUOTE2_FORE_COLOR, VAR_NORM_FORE_COLOR) &&
6578 !strucmp(VAR_QUOTE2_BACK_COLOR, VAR_NORM_BACK_COLOR))) &&
6579 (!(VAR_QUOTE1_FORE_COLOR && VAR_QUOTE1_BACK_COLOR) ||
6580 (!strucmp(VAR_QUOTE1_FORE_COLOR, VAR_NORM_FORE_COLOR) &&
6581 !strucmp(VAR_QUOTE1_BACK_COLOR, VAR_NORM_BACK_COLOR)))){
6583 * They are all either Normal or not set. Delete them all.
6585 if(VAR_QUOTE3_FORE_COLOR)
6586 fs_give((void **)&VAR_QUOTE3_FORE_COLOR);
6587 if(VAR_QUOTE3_BACK_COLOR)
6588 fs_give((void **)&VAR_QUOTE3_BACK_COLOR);
6589 if(VAR_QUOTE2_FORE_COLOR)
6590 fs_give((void **)&VAR_QUOTE2_FORE_COLOR);
6591 if(VAR_QUOTE2_BACK_COLOR)
6592 fs_give((void **)&VAR_QUOTE2_BACK_COLOR);
6593 if(VAR_QUOTE1_FORE_COLOR)
6594 fs_give((void **)&VAR_QUOTE1_FORE_COLOR);
6595 if(VAR_QUOTE1_BACK_COLOR)
6596 fs_give((void **)&VAR_QUOTE1_BACK_COLOR);
6598 else{ /* something is non-Normal */
6599 if(VAR_QUOTE3_FORE_COLOR && VAR_QUOTE3_BACK_COLOR)
6600 later_color_is_set++;
6602 /* if 3 is set but not 2, set 2 to Normal */
6603 if(VAR_QUOTE2_FORE_COLOR && VAR_QUOTE2_BACK_COLOR)
6604 later_color_is_set++;
6605 else if(later_color_is_set)
6606 set_color_val(&vars[V_QUOTE2_FORE_COLOR], 1);
6608 /* if 3 or 2 is set but not 1, set 1 to Normal */
6609 if(VAR_QUOTE1_FORE_COLOR && VAR_QUOTE1_BACK_COLOR)
6610 later_color_is_set++;
6611 else if(later_color_is_set)
6612 set_color_val(&vars[V_QUOTE1_FORE_COLOR], 1);
6615 #ifdef _WINDOWS
6616 if(ps->pre441){
6617 int conv_main = 0, conv_post = 0;
6619 ps->pre441 = 0;
6620 if(ps->prc && !unix_color_style_in_pinerc(ps->prc)){
6621 conv_main = convert_pc_gray_names(ps, ps->prc, Main);
6622 if(conv_main)
6623 ps->prc->outstanding_pinerc_changes = 1;
6627 if(ps->post_prc && !unix_color_style_in_pinerc(ps->post_prc)){
6628 conv_post = convert_pc_gray_names(ps, ps->post_prc, Post);
6629 if(conv_post)
6630 ps->post_prc->outstanding_pinerc_changes = 1;
6633 if(conv_main || conv_post){
6634 if(conv_main)
6635 write_pinerc(ps, Main, WRP_NONE);
6637 if(conv_post)
6638 write_pinerc(ps, Post, WRP_NONE);
6640 set_current_color_vals(ps);
6643 #endif /* _WINDOWS */
6645 pico_set_normal_color();
6650 * Set current_val for the foreground and background color vars, which
6651 * are assumed to be in order. If a set_current_val on them doesn't
6652 * produce current_vals, then use the colors from defvar to set those
6653 * current_vals.
6655 void
6656 set_color_val(struct variable *v, int use_default)
6658 set_current_val(v, TRUE, TRUE);
6659 set_current_val(v+1, TRUE, TRUE);
6661 if(!(v->current_val.p && v->current_val.p[0] &&
6662 (v+1)->current_val.p && (v+1)->current_val.p[0])){
6663 struct variable *defvar;
6665 if(v->current_val.p)
6666 fs_give((void **)&v->current_val.p);
6667 if((v+1)->current_val.p)
6668 fs_give((void **)&(v+1)->current_val.p);
6670 if(!use_default)
6671 return;
6673 if(var_defaults_to_rev(v))
6674 defvar = &ps_global->vars[V_REV_FORE_COLOR];
6675 else
6676 defvar = &ps_global->vars[V_NORM_FORE_COLOR];
6678 /* use default vars values instead */
6679 if(defvar && defvar->current_val.p && defvar->current_val.p[0] &&
6680 (defvar+1)->current_val.p && (defvar+1)->current_val.p[0]){
6681 v->current_val.p = cpystr(defvar->current_val.p);
6682 (v+1)->current_val.p = cpystr((defvar+1)->current_val.p);
6689 var_defaults_to_rev(struct variable *v)
6691 return(v == &ps_global->vars[V_REV_FORE_COLOR] ||
6692 v == &ps_global->vars[V_TITLE_FORE_COLOR] ||
6693 v == &ps_global->vars[V_STATUS_FORE_COLOR] ||
6694 v == &ps_global->vars[V_KEYNAME_FORE_COLOR] ||
6695 v == &ps_global->vars[V_PROMPT_FORE_COLOR]);
6701 * Each item in the list looks like:
6703 * /HDR=<header>/FG=<foreground color>/BG=<background color>
6705 * We separate the three pieces into an array of structures to make
6706 * it easier to deal with later.
6708 void
6709 set_custom_spec_colors(struct pine *ps)
6711 if(ps->index_token_colors)
6712 free_spec_colors(&ps->index_token_colors);
6714 ps->index_token_colors = spec_colors_from_varlist(ps->VAR_INDEX_TOKEN_COLORS, 1);
6716 if(ps->hdr_colors)
6717 free_spec_colors(&ps->hdr_colors);
6719 ps->hdr_colors = spec_colors_from_varlist(ps->VAR_VIEW_HDR_COLORS, 1);
6721 /* fit keyword colors into the same structures for code re-use */
6722 if(ps->kw_colors)
6723 free_spec_colors(&ps->kw_colors);
6725 ps->kw_colors = spec_colors_from_varlist(ps->VAR_KW_COLORS, 1);
6730 * Input is one item from config variable.
6732 * Return value must be freed by caller. The return is a single SPEC_COLOR_S,
6733 * not a list.
6735 SPEC_COLOR_S *
6736 spec_color_from_var(char *t, int already_expanded)
6738 char *p, *spec, *fg, *bg;
6739 PATTERN_S *val;
6740 SPEC_COLOR_S *new_hcolor = NULL;
6742 if(t && t[0] && !strcmp(t, INHERIT)){
6743 new_hcolor = (SPEC_COLOR_S *)fs_get(sizeof(*new_hcolor));
6744 memset((void *)new_hcolor, 0, sizeof(*new_hcolor));
6745 new_hcolor->inherit = 1;
6747 else if(t && t[0]){
6748 char tbuf[10000];
6750 if(!already_expanded){
6751 tbuf[0] = '\0';
6752 if(expand_variables(tbuf, sizeof(tbuf), t, 0))
6753 t = tbuf;
6756 spec = fg = bg = NULL;
6757 val = NULL;
6758 if((p = srchstr(t, "/HDR=")) != NULL)
6759 spec = remove_backslash_escapes(p+5);
6760 if((p = srchstr(t, "/FG=")) != NULL)
6761 fg = remove_backslash_escapes(p+4);
6762 if((p = srchstr(t, "/BG=")) != NULL)
6763 bg = remove_backslash_escapes(p+4);
6764 val = parse_pattern("VAL", t, 0);
6766 if(spec && *spec){
6767 /* remove colons */
6768 if((p = strindex(spec, ':')) != NULL)
6769 *p = '\0';
6771 new_hcolor = (SPEC_COLOR_S *)fs_get(sizeof(*new_hcolor));
6772 memset((void *)new_hcolor, 0, sizeof(*new_hcolor));
6773 new_hcolor->spec = spec;
6774 new_hcolor->fg = fg;
6775 new_hcolor->bg = bg;
6776 new_hcolor->val = val;
6778 else{
6779 if(spec)
6780 fs_give((void **)&spec);
6781 if(fg)
6782 fs_give((void **)&fg);
6783 if(bg)
6784 fs_give((void **)&bg);
6785 if(val)
6786 free_pattern(&val);
6790 return(new_hcolor);
6795 * Input is a list from config file.
6797 * Return value may be a list of SPEC_COLOR_S and must be freed by caller.
6799 SPEC_COLOR_S *
6800 spec_colors_from_varlist(char **varlist, int already_expanded)
6802 char **s, *t;
6803 SPEC_COLOR_S *new_hc = NULL;
6804 SPEC_COLOR_S *new_hcolor, **nexthc;
6806 nexthc = &new_hc;
6807 if(varlist){
6808 for(s = varlist; (t = *s) != NULL; s++){
6809 if(t[0]){
6810 new_hcolor = spec_color_from_var(t, already_expanded);
6811 if(new_hcolor){
6812 *nexthc = new_hcolor;
6813 nexthc = &new_hcolor->next;
6819 return(new_hc);
6824 * Returns allocated charstar suitable for config var for a single
6825 * SPEC_COLOR_S.
6827 char *
6828 var_from_spec_color(SPEC_COLOR_S *hc)
6830 char *ret_val = NULL;
6831 char *p, *spec = NULL, *fg = NULL, *bg = NULL, *val = NULL;
6832 size_t len;
6834 if(hc && hc->inherit)
6835 ret_val = cpystr(INHERIT);
6836 else if(hc){
6837 if(hc->spec)
6838 spec = add_viewerhdr_escapes(hc->spec);
6839 if(hc->fg)
6840 fg = add_viewerhdr_escapes(hc->fg);
6841 if(hc->bg)
6842 bg = add_viewerhdr_escapes(hc->bg);
6843 if(hc->val){
6844 p = pattern_to_string(hc->val);
6845 if(p){
6846 val = add_viewerhdr_escapes(p);
6847 fs_give((void **)&p);
6851 len = strlen("/HDR=/FG=/BG=") + strlen(spec ? spec : "") +
6852 strlen(fg ? fg : "") + strlen(bg ? bg : "") +
6853 strlen(val ? "/VAL=" : "") + strlen(val ? val : "");
6854 ret_val = (char *) fs_get(len + 1);
6855 snprintf(ret_val, len+1, "/HDR=%s/FG=%s/BG=%s%s%s",
6856 spec ? spec : "", fg ? fg : "", bg ? bg : "",
6857 val ? "/VAL=" : "", val ? val : "");
6859 if(spec)
6860 fs_give((void **)&spec);
6861 if(fg)
6862 fs_give((void **)&fg);
6863 if(bg)
6864 fs_give((void **)&bg);
6865 if(val)
6866 fs_give((void **)&val);
6869 return(ret_val);
6874 * Returns allocated charstar suitable for config var for a single
6875 * SPEC_COLOR_S.
6877 char **
6878 varlist_from_spec_colors(SPEC_COLOR_S *hcolors)
6880 SPEC_COLOR_S *hc;
6881 char **ret_val = NULL;
6882 int i;
6884 /* count how many */
6885 for(hc = hcolors, i = 0; hc; hc = hc->next, i++)
6888 ret_val = (char **)fs_get((i+1) * sizeof(*ret_val));
6889 memset((void *)ret_val, 0, (i+1) * sizeof(*ret_val));
6890 for(hc = hcolors, i = 0; hc; hc = hc->next, i++)
6891 ret_val[i] = var_from_spec_color(hc);
6893 return(ret_val);
6897 void
6898 update_posting_charset(struct pine *ps, int revert)
6900 #ifndef _WINDOWS
6901 if(F_ON(F_USE_SYSTEM_TRANS, ps)){
6902 if(!revert)
6903 q_status_message(SM_ORDER, 5, 5, _("This change has no effect because feature Use-System-Translation is on"));
6905 else{
6906 #endif /* ! _WINDOWS */
6907 if(ps->posting_charmap)
6908 fs_give((void **) &ps->posting_charmap);
6910 if(ps->VAR_POST_CHAR_SET){
6911 ps->posting_charmap = cpystr(ps->VAR_POST_CHAR_SET);
6912 if(!posting_charset_is_supported(ps->posting_charmap)){
6913 snprintf(tmp_20k_buf, SIZEOF_20KBUF,
6914 _("Posting-Character set \"%s\" is unsupported, using UTF-8"),
6915 ps->posting_charmap);
6916 q_status_message(SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
6917 fs_give((void **) &ps->posting_charmap);
6918 ps->posting_charmap = cpystr("UTF-8");
6921 else
6922 ps->posting_charmap = cpystr("UTF-8");
6923 #ifndef _WINDOWS
6925 #endif /* ! _WINDOWS */
6929 #define FIXED_COMMENT _("(fixed)")
6930 #define DEFAULT_COMMENT _("(default)")
6931 #define OVERRIDE_COMMENT _("(overridden)")
6934 feature_gets_an_x(struct pine *ps, struct variable *var, FEATURE_S *feature,
6935 char **comment, EditWhich ew)
6937 char **lval, **lvalexc, **lvalnorm;
6938 char *def = DEFAULT_COMMENT;
6939 int j, done = 0;
6940 int feature_fixed_on = 0, feature_fixed_off = 0;
6942 if(comment)
6943 *comment = NULL;
6945 lval = LVAL(var, ew);
6946 lvalexc = LVAL(var, ps->ew_for_except_vars);
6947 lvalnorm = LVAL(var, Main);
6949 /* feature value is administratively fixed */
6950 if((j = feature_in_list(var->fixed_val.l, feature->name)) != 0){
6951 if(j == 1)
6952 feature_fixed_on++;
6953 else if(j == -1)
6954 feature_fixed_off++;
6956 done++;
6957 if(comment)
6958 *comment = FIXED_COMMENT;
6962 * We have an exceptions config setting which overrides anything
6963 * we do here, in the normal config.
6965 if(!done &&
6966 ps->ew_for_except_vars != Main && ew == Main &&
6967 feature_in_list(lvalexc, feature->name)){
6968 done++;
6969 if(comment)
6970 *comment = OVERRIDE_COMMENT;
6974 * Feature is set On in default but not set here.
6976 if(!done &&
6977 !feature_in_list(lval, feature->name) &&
6978 ((feature_in_list(var->global_val.l, feature->name) == 1) ||
6979 ((ps->ew_for_except_vars != Main &&
6980 ew == ps->ew_for_except_vars &&
6981 feature_in_list(lvalnorm, feature->name) == 1)))){
6982 done = 17;
6983 if(comment)
6984 *comment = def;
6987 if(!done &&
6988 feature->defval &&
6989 !feature_in_list(lval, feature->name) &&
6990 !feature_in_list(var->global_val.l, feature->name) &&
6991 (ps->ew_for_except_vars == Main ||
6992 ew != ps->ew_for_except_vars ||
6993 !feature_in_list(lvalnorm, feature->name))){
6994 done = 17;
6995 if(comment)
6996 *comment = def;
6999 return(feature_fixed_on ||
7000 (!feature_fixed_off &&
7001 (done == 17 ||
7002 test_feature(lval, feature->name,
7003 test_old_growth_bits(ps, feature->id)))));
7008 longest_feature_comment(struct pine *ps, EditWhich ew)
7010 int lc = 0;
7012 lc = MAX(lc, utf8_width(FIXED_COMMENT));
7013 lc = MAX(lc, utf8_width(DEFAULT_COMMENT));
7014 if(ps->ew_for_except_vars != Main && ew == Main)
7015 lc = MAX(lc, utf8_width(OVERRIDE_COMMENT));
7017 return(lc);
7021 void
7022 toggle_feature(struct pine *ps, struct variable *var, FEATURE_S *f,
7023 int just_flip_value, EditWhich ew)
7025 char **vp, *p, **lval, ***alval;
7026 int og, on_before, was_set;
7027 char *err;
7028 long l;
7030 og = test_old_growth_bits(ps, f->id);
7033 * if this feature is in the fixed set, or old-growth is in the fixed
7034 * set and this feature is in the old-growth set, don't alter it...
7036 for(vp = var->fixed_val.l; vp && *vp; vp++){
7037 p = (struncmp(*vp, "no-", 3)) ? *vp : *vp + 3;
7038 if(!strucmp(p, f->name) || (og && !strucmp(p, "old-growth"))){
7039 q_status_message(SM_ORDER, 3, 3,
7040 /* TRANSLATORS: In the configuration screen, telling the user we
7041 can't change this option because the system administrator
7042 prohibits it. */
7043 _("Can't change value fixed by sys-admin."));
7044 return;
7048 on_before = F_ON(f->id, ps);
7050 lval = LVAL(var, ew);
7051 alval = ALVAL(var, ew);
7052 if(just_flip_value)
7053 was_set = test_feature(lval, f->name, og);
7054 else
7055 was_set = feature_gets_an_x(ps, var, f, NULL, ew);
7057 if(alval)
7058 set_feature(alval, f->name, !was_set);
7060 set_feature_list_current_val(var);
7061 process_feature_list(ps, var->current_val.l, 0, 0, 0);
7064 * Handle any features that need special attention here...
7066 if(on_before != F_ON(f->id, ps))
7067 switch(f->id){
7068 case F_QUOTE_ALL_FROMS :
7069 mail_parameters(NULL,SET_FROMWIDGET,F_ON(f->id,ps) ? VOIDT : NIL);
7070 break;
7072 case F_FAKE_NEW_IN_NEWS :
7073 if(IS_NEWS(ps->mail_stream))
7074 q_status_message(SM_ORDER | SM_DING, 3, 4,
7075 "news-approximates-new-status won't affect current newsgroup until next open");
7077 break;
7079 case F_COLOR_LINE_IMPORTANT :
7080 case F_DATES_TO_LOCAL :
7081 clear_index_cache(ps->mail_stream, 0);
7082 break;
7084 case F_DISABLE_INDEX_LOCALE_DATES :
7085 reset_index_format();
7086 clear_index_cache(ps->mail_stream, 0);
7087 break;
7089 case F_MARK_FOR_CC :
7090 clear_index_cache(ps->mail_stream, 0);
7091 if(THREADING() && sp_viewing_a_thread(ps->mail_stream))
7092 unview_thread(ps, ps->mail_stream, ps->msgmap);
7094 break;
7096 case F_HIDE_NNTP_PATH :
7097 mail_parameters(NULL, SET_NNTPHIDEPATH,
7098 F_ON(f->id, ps) ? VOIDT : NIL);
7099 break;
7101 case F_MAILDROPS_PRESERVE_STATE :
7102 mail_parameters(NULL, SET_SNARFPRESERVE,
7103 F_ON(f->id, ps) ? VOIDT : NIL);
7104 break;
7106 case F_DISABLE_SHARED_NAMESPACES :
7107 mail_parameters(NULL, SET_DISABLEAUTOSHAREDNS,
7108 F_ON(f->id, ps) ? VOIDT : NIL);
7109 break;
7111 case F_QUELL_LOCK_FAILURE_MSGS :
7112 mail_parameters(NULL, SET_LOCKEACCESERROR,
7113 F_ON(f->id, ps) ? VOIDT : NIL);
7114 break;
7116 case F_MULNEWSRC_HOSTNAMES_AS_TYPED :
7117 l = F_ON(f->id, ps) ? 0L : 1L;
7118 mail_parameters(NULL, SET_NEWSRCCANONHOST, (void *) l);
7119 break;
7121 case F_QUELL_INTERNAL_MSG :
7122 mail_parameters(NULL, SET_USERHASNOLIFE,
7123 F_ON(f->id, ps) ? VOIDT : NIL);
7124 break;
7126 case F_DISABLE_SETLOCALE_COLLATE :
7127 set_collation(F_OFF(F_DISABLE_SETLOCALE_COLLATE, ps), 1);
7128 break;
7130 #ifndef _WINDOWS
7131 case F_USE_SYSTEM_TRANS :
7132 err = NULL;
7133 reset_character_set_stuff(&err);
7134 if(err){
7135 q_status_message(SM_ORDER | SM_DING, 3, 4, err);
7136 fs_give((void **) &err);
7139 break;
7140 #endif /* ! _WINDOWS */
7142 case F_ENABLE_INCOMING_CHECKING :
7143 if(!on_before && F_OFF(F_ENABLE_INCOMING, ps))
7144 q_status_message(SM_ORDER, 0, 3, _("This option has no effect without Enable-Incoming-Folders"));
7146 clear_incoming_valid_bits();
7147 break;
7149 case F_INCOMING_CHECKING_TOTAL :
7150 case F_INCOMING_CHECKING_RECENT :
7151 if(!on_before && F_OFF(F_ENABLE_INCOMING_CHECKING, ps))
7152 q_status_message(SM_ORDER, 0, 3, _("This option has no effect without Enable-Incoming-Folders-Checking"));
7154 clear_incoming_valid_bits();
7155 break;
7157 case F_THREAD_SORTS_BY_ARRIVAL :
7158 clear_index_cache(ps->mail_stream, 0);
7159 refresh_sort(ps->mail_stream, sp_msgmap(ps->mail_stream), SRT_NON);
7160 break;
7162 #ifdef SMIME
7163 case F_DONT_DO_SMIME :
7164 smime_deinit();
7165 break;
7167 #ifdef APPLEKEYCHAIN
7168 case F_PUBLICCERTS_IN_KEYCHAIN :
7169 smime_deinit();
7170 break;
7171 #endif
7172 #endif
7174 default :
7175 break;
7181 * Returns 1 -- Feature is in the list and positive
7182 * 0 -- Feature is not in the list at all
7183 * -1 -- Feature is in the list and negative (no-)
7186 feature_in_list(char **l, char *f)
7188 char *p;
7189 int rv = 0, forced_off;
7191 for(; l && *l; l++){
7192 p = (forced_off = !struncmp(*l, "no-", 3)) ? *l + 3 : *l;
7193 if(!strucmp(p, f))
7194 rv = forced_off ? -1 : 1;
7197 return(rv);
7202 * test_feature - runs thru a feature list, and returns:
7203 * 1 if feature explicitly set and matches 'v'
7204 * 0 if feature not explicitly set *or* doesn't match 'v'
7207 test_feature(char **l, char *f, int g)
7209 char *p;
7210 int rv = 0, forced_off;
7212 for(; l && *l; l++){
7213 p = (forced_off = !struncmp(*l, "no-", 3)) ? *l + 3 : *l;
7214 if(!strucmp(p, f))
7215 rv = !forced_off;
7216 else if(g && !strucmp(p, "old-growth"))
7217 rv = !forced_off;
7220 return(rv);
7224 void
7225 set_feature(char ***l, char *f, int v)
7227 char **list = l ? *l : NULL, newval[256];
7228 int count = 0;
7230 snprintf(newval, sizeof(newval), "%s%s", v ? "" : "no-", f);
7231 for(; list && *list; list++, count++)
7232 if((**list == '\0') /* anything can replace an empty value */
7233 || !strucmp(((!struncmp(*list, "no-", 3)) ? *list + 3 : *list), f)){
7234 fs_give((void **)list); /* replace with new value */
7235 *list = cpystr(newval);
7236 return;
7240 * if we got here, we didn't find it in the list, so grow the list
7241 * and add it..
7243 if(!*l)
7244 *l = (char **)fs_get((count + 2) * sizeof(char *));
7245 else
7246 fs_resize((void **)l, (count + 2) * sizeof(char *));
7248 (*l)[count] = cpystr(newval);
7249 (*l)[count + 1] = NULL;
7254 reset_character_set_stuff(char **err)
7256 int use_system = 0;
7257 char buf[1000];
7259 if(err)
7260 *err = NULL;
7262 if(ps_global->display_charmap)
7263 fs_give((void **) &ps_global->display_charmap);
7265 if(ps_global->keyboard_charmap)
7266 fs_give((void **) &ps_global->keyboard_charmap);
7268 if(ps_global->posting_charmap)
7269 fs_give((void **) &ps_global->posting_charmap);
7271 #ifdef _WINDOWS
7272 ps_global->display_charmap = cpystr("UTF-8");
7273 #else /* UNIX */
7274 if(ps_global->VAR_CHAR_SET)
7275 ps_global->display_charmap = cpystr(ps_global->VAR_CHAR_SET);
7276 else{
7277 #if HAVE_LANGINFO_H && defined(CODESET)
7278 ps_global->display_charmap = cpystr(nl_langinfo_codeset_wrapper());
7279 #else
7280 ps_global->display_charmap = cpystr("UTF-8");
7281 #endif
7283 #endif /* UNIX */
7285 if(!ps_global->display_charmap)
7286 ps_global->display_charmap = cpystr("US-ASCII");
7288 #ifdef _WINDOWS
7289 ps_global->keyboard_charmap = cpystr("UTF-8");
7290 #else /* UNIX */
7291 if(ps_global->VAR_KEY_CHAR_SET)
7292 ps_global->keyboard_charmap = cpystr(ps_global->VAR_KEY_CHAR_SET);
7293 else
7294 ps_global->keyboard_charmap = cpystr(ps_global->display_charmap);
7296 if(!ps_global->keyboard_charmap)
7297 ps_global->keyboard_charmap = cpystr("US-ASCII");
7299 if(F_ON(F_USE_SYSTEM_TRANS, ps_global)){
7300 #if PREREQ_FOR_SYS_TRANSLATION
7301 use_system++;
7302 /* This modifies its arguments */
7303 if(setup_for_input_output(use_system, &ps_global->display_charmap,
7304 &ps_global->keyboard_charmap,
7305 &ps_global->input_cs, (err && *err) ? NULL : err) == -1)
7306 return -1;
7307 #endif
7309 #endif /* UNIX */
7311 if(!use_system){
7312 if(setup_for_input_output(use_system, &ps_global->display_charmap,
7313 &ps_global->keyboard_charmap,
7314 &ps_global->input_cs, (err && *err) ? NULL : err) == -1)
7315 return -1;
7318 if(!use_system && ps_global->VAR_POST_CHAR_SET){
7319 ps_global->posting_charmap = cpystr(ps_global->VAR_POST_CHAR_SET);
7320 if(!posting_charset_is_supported(ps_global->posting_charmap)){
7321 if(err && !*err){
7322 snprintf(buf, sizeof(buf),
7323 _("Posting-Character-Set \"%s\" is unsupported, using UTF-8"),
7324 ps_global->posting_charmap);
7325 *err = cpystr(buf);
7328 fs_give((void **) &ps_global->posting_charmap);
7329 ps_global->posting_charmap = cpystr("UTF-8");
7332 else{
7333 if(use_system && ps_global->VAR_POST_CHAR_SET
7334 && strucmp(ps_global->VAR_POST_CHAR_SET, "UTF-8"))
7335 if(err && !*err)
7336 *err = cpystr(_("Posting-Character-Set is ignored with Use-System-Translation turned on"));
7338 ps_global->posting_charmap = cpystr("UTF-8");
7341 set_locale_charmap(ps_global->keyboard_charmap);
7343 return(0);
7348 * Given a single printer string from the config file, returns pointers
7349 * to alloc'd strings containing the printer nickname, the command,
7350 * the init string, the trailer string, everything but the nickname string,
7351 * and everything but the command string. All_but_cmd includes the trailing
7352 * space at the end (the one before the command) but all_but_nick does not
7353 * include the leading space (the one before the [).
7354 * If you pass in a pointer it is guaranteed to come back pointing to an
7355 * allocated string, even if it is just an empty string. It is ok to pass
7356 * NULL for any of the six return strings.
7358 void
7359 parse_printer(char *input, char **nick, char **cmd, char **init, char **trailer,
7360 char **all_but_nick, char **all_but_cmd)
7362 char *p, *q, *start, *saved_options = NULL;
7363 int tmpsave, cnt;
7365 if(!input)
7366 input = "";
7368 if(nick || all_but_nick){
7369 if((p = srchstr(input, " [")) != NULL){
7370 if(all_but_nick)
7371 *all_but_nick = cpystr(p+1);
7373 if(nick){
7374 while(p-1 > input && isspace((unsigned char)*(p-1)))
7375 p--;
7377 tmpsave = *p;
7378 *p = '\0';
7379 *nick = cpystr(input);
7380 *p = tmpsave;
7383 else{
7384 if(nick)
7385 *nick = cpystr("");
7387 if(all_but_nick)
7388 *all_but_nick = cpystr(input);
7392 if((p = srchstr(input, "] ")) != NULL){
7394 ++p;
7395 }while(isspace((unsigned char)*p));
7397 tmpsave = *p;
7398 *p = '\0';
7399 saved_options = cpystr(input);
7400 *p = tmpsave;
7402 else
7403 p = input;
7405 if(cmd)
7406 *cmd = cpystr(p);
7408 if(init){
7409 if(saved_options && (p = srchstr(saved_options, "INIT="))){
7410 start = p + strlen("INIT=");
7411 for(cnt=0, p = start; *p && *(p+1) && isxpair(p); p += 2)
7412 cnt++;
7414 q = *init = (char *)fs_get((cnt + 1) * sizeof(char));
7415 for(p = start; *p && *(p+1) && isxpair(p); p += 2)
7416 *q++ = read_hex(p);
7418 *q = '\0';
7420 else
7421 *init = cpystr("");
7424 if(trailer){
7425 if(saved_options && (p = srchstr(saved_options, "TRAILER="))){
7426 start = p + strlen("TRAILER=");
7427 for(cnt=0, p = start; *p && *(p+1) && isxpair(p); p += 2)
7428 cnt++;
7430 q = *trailer = (char *)fs_get((cnt + 1) * sizeof(char));
7431 for(p = start; *p && *(p+1) && isxpair(p); p += 2)
7432 *q++ = read_hex(p);
7434 *q = '\0';
7436 else
7437 *trailer = cpystr("");
7440 if(all_but_cmd){
7441 if(saved_options)
7442 *all_but_cmd = saved_options;
7443 else
7444 *all_but_cmd = cpystr("");
7446 else if(saved_options)
7447 fs_give((void **)&saved_options);
7452 copy_pinerc(char *local, char *remote, char **err_msg)
7454 return(copy_localfile_to_remotefldr(RemImap, local, remote,
7455 REMOTE_PINERC_SUBTYPE,
7456 err_msg));
7461 copy_abook(char *local, char *remote, char **err_msg)
7463 return(copy_localfile_to_remotefldr(RemImap, local, remote,
7464 REMOTE_ABOOK_SUBTYPE,
7465 err_msg));
7470 * Copy local file to remote folder.
7472 * Args remotetype -- type of remote folder
7473 * local -- name of local file
7474 * remote -- name of remote folder
7475 * subtype --
7477 * Returns 0 on success.
7480 copy_localfile_to_remotefldr(RemType remotetype, char *local, char *remote,
7481 char *subtype, char **err_msg)
7483 int retfail = -1;
7484 unsigned flags;
7485 REMDATA_S *rd;
7487 dprint((9, "copy_localfile_to_remotefldr(%s,%s)\n",
7488 local ? local : "<null>",
7489 remote ? remote : "<null>"));
7491 *err_msg = (char *)fs_get(MAXPATH * sizeof(char));
7493 if(!local || !*local){
7494 snprintf(*err_msg, MAXPATH, _("No local file specified"));
7495 return(retfail);
7498 if(!remote || !*remote){
7499 snprintf(*err_msg, MAXPATH, _("No remote folder specified"));
7500 return(retfail);
7503 if(!IS_REMOTE(remote)){
7504 snprintf(*err_msg, MAXPATH, _("Remote folder name \"%s\" %s"), remote,
7505 (*remote != '{') ? _("must begin with \"{\"") : _("not valid"));
7506 return(retfail);
7509 if(IS_REMOTE(local)){
7510 snprintf(*err_msg, MAXPATH, _("First argument \"%s\" must be a local filename"),
7511 local);
7512 return(retfail);
7515 if(can_access(local, ACCESS_EXISTS) != 0){
7516 snprintf(*err_msg, MAXPATH, _("Local file \"%s\" does not exist"), local);
7517 return(retfail);
7520 if(can_access(local, READ_ACCESS) != 0){
7521 snprintf(*err_msg, MAXPATH, _("Can't read local file \"%s\": %s"),
7522 local, error_description(errno));
7523 return(retfail);
7527 * Check if remote folder exists and create it if it doesn't.
7529 flags = 0;
7530 rd = rd_create_remote(remotetype, remote, subtype,
7531 &flags, _("Error: "), _("Can't copy to remote folder."));
7533 if(!rd || rd->access == NoExists){
7534 snprintf(*err_msg, MAXPATH, _("Can't create \"%s\""), remote);
7535 if(rd)
7536 rd_free_remdata(&rd);
7538 return(retfail);
7541 if(rd->access == MaybeRorW)
7542 rd->access = ReadWrite;
7544 rd->flags |= (NO_META_UPDATE | DO_REMTRIM);
7545 rd->lf = cpystr(local);
7547 rd_open_remote(rd);
7548 if(!rd_stream_exists(rd)){
7549 snprintf(*err_msg, MAXPATH, _("Can't open remote folder \"%s\""), rd->rn);
7550 rd_free_remdata(&rd);
7551 return(retfail);
7554 if(rd_remote_is_readonly(rd)){
7555 snprintf(*err_msg, MAXPATH, _("Remote folder \"%s\" is readonly"), rd->rn);
7556 rd_free_remdata(&rd);
7557 return(retfail);
7560 switch(rd->type){
7561 case RemImap:
7563 * Empty folder, add a header msg.
7565 if(rd->t.i.stream->nmsgs == 0){
7566 if(rd_init_remote(rd, 1) != 0){
7567 snprintf(*err_msg, MAXPATH,
7568 _("Failed initializing remote folder \"%s\", check debug file"),
7569 rd->rn);
7570 rd_free_remdata(&rd);
7571 return(retfail);
7575 fs_give((void **)err_msg);
7576 *err_msg = NULL;
7577 if(rd_chk_for_hdr_msg(&(rd->t.i.stream), rd, err_msg)){
7578 rd_free_remdata(&rd);
7579 return(retfail);
7582 break;
7584 default:
7585 break;
7588 if(rd_update_remote(rd, NULL) != 0){
7589 snprintf(*err_msg, MAXPATH, _("Error copying to remote folder \"%s\""), rd->rn);
7590 rd_free_remdata(&rd);
7591 return(retfail);
7594 rd_update_metadata(rd, NULL);
7595 rd_close_remdata(&rd);
7597 fs_give((void **)err_msg);
7598 return(0);
7602 /*----------------------------------------------------------------------
7603 Panic pine - call on detected programmatic errors to exit pine, with arg
7605 Input: message -- printf styule string for panic message (see above)
7606 arg -- argument for printf string
7608 Result: The various tty modes are restored
7609 If debugging is active a core dump will be generated
7610 Exits Pine
7611 ----*/
7612 void
7613 panic1(char *message, char *arg)
7615 #define SIZEOFBUF 1001
7616 char buf1[SIZEOFBUF], buf2[SIZEOFBUF];
7618 snprintf(buf1, sizeof(buf1), "%.*s", (int) MAX(SIZEOFBUF - 1 - strlen(message), 0), arg);
7619 snprintf(buf2, sizeof(buf2), message, buf1);
7620 alpine_panic(buf2);
7627 HelpType
7628 config_help(int var, int feature)
7630 switch(var){
7631 case V_FEATURE_LIST :
7632 return(feature_list_help(feature));
7633 break;
7635 case V_PERSONAL_NAME :
7636 return(h_config_pers_name);
7637 case V_USER_ID :
7638 return(h_config_user_id);
7639 case V_USER_DOMAIN :
7640 return(h_config_user_dom);
7641 case V_SMTP_SERVER :
7642 return(h_config_smtp_server);
7643 case V_NNTP_SERVER :
7644 return(h_config_nntp_server);
7645 case V_INBOX_PATH :
7646 return(h_config_inbox_path);
7647 case V_PRUNED_FOLDERS :
7648 return(h_config_pruned_folders);
7649 case V_DEFAULT_FCC :
7650 return(h_config_default_fcc);
7651 case V_DEFAULT_SAVE_FOLDER :
7652 return(h_config_def_save_folder);
7653 case V_POSTPONED_FOLDER :
7654 return(h_config_postponed_folder);
7655 case V_READ_MESSAGE_FOLDER :
7656 return(h_config_read_message_folder);
7657 case V_FORM_FOLDER :
7658 return(h_config_form_folder);
7659 case V_ARCHIVED_FOLDERS :
7660 return(h_config_archived_folders);
7661 case V_SIGNATURE_FILE :
7662 return(h_config_signature_file);
7663 case V_LITERAL_SIG :
7664 return(h_config_literal_sig);
7665 case V_INIT_CMD_LIST :
7666 return(h_config_init_cmd_list);
7667 case V_COMP_HDRS :
7668 return(h_config_comp_hdrs);
7669 case V_CUSTOM_HDRS :
7670 return(h_config_custom_hdrs);
7671 case V_VIEW_HEADERS :
7672 return(h_config_viewer_headers);
7673 case V_VIEW_MARGIN_LEFT :
7674 return(h_config_viewer_margin_left);
7675 case V_VIEW_MARGIN_RIGHT :
7676 return(h_config_viewer_margin_right);
7677 case V_QUOTE_SUPPRESSION :
7678 return(h_config_quote_suppression);
7679 case V_SAVED_MSG_NAME_RULE :
7680 return(h_config_saved_msg_name_rule);
7681 case V_FCC_RULE :
7682 return(h_config_fcc_rule);
7683 case V_SORT_KEY :
7684 return(h_config_sort_key);
7685 case V_AB_SORT_RULE :
7686 return(h_config_ab_sort_rule);
7687 case V_FLD_SORT_RULE :
7688 return(h_config_fld_sort_rule);
7689 case V_POST_CHAR_SET :
7690 return(h_config_post_char_set);
7691 case V_UNK_CHAR_SET :
7692 return(h_config_unk_char_set);
7693 #ifndef _WINDOWS
7694 case V_KEY_CHAR_SET :
7695 return(h_config_key_char_set);
7696 case V_CHAR_SET :
7697 return(h_config_char_set);
7698 #endif /* ! _WINDOWS */
7699 case V_EDITOR :
7700 return(h_config_editor);
7701 case V_SPELLER :
7702 return(h_config_speller);
7703 #ifdef _WINDOWS
7704 case V_DICTIONARY :
7705 return(h_config_aspell_dictionary);
7706 #endif /* _WINDOWS */
7707 case V_DISPLAY_FILTERS :
7708 return(h_config_display_filters);
7709 case V_SEND_FILTER :
7710 return(h_config_sending_filter);
7711 case V_ALT_ADDRS :
7712 return(h_config_alt_addresses);
7713 case V_KEYWORDS :
7714 return(h_config_keywords);
7715 case V_KW_BRACES :
7716 return(h_config_kw_braces);
7717 case V_OPENING_SEP :
7718 return(h_config_opening_sep);
7719 case V_KW_COLORS :
7720 return(h_config_kw_color);
7721 case V_ABOOK_FORMATS :
7722 return(h_config_abook_formats);
7723 case V_INDEX_FORMAT :
7724 return(h_config_index_format);
7725 case V_INCCHECKTIMEO :
7726 return(h_config_incoming_timeo);
7727 case V_INCCHECKINTERVAL :
7728 return(h_config_incoming_interv);
7729 case V_INC2NDCHECKINTERVAL :
7730 return(h_config_incoming_second_interv);
7731 case V_INCCHECKLIST :
7732 return(h_config_incoming_list);
7733 case V_SLEEP :
7734 return(h_config_psleep);
7735 case V_OVERLAP :
7736 return(h_config_viewer_overlap);
7737 case V_MAXREMSTREAM :
7738 return(h_config_maxremstream);
7739 case V_PERMLOCKED :
7740 return(h_config_permlocked);
7741 case V_MARGIN :
7742 return(h_config_scroll_margin);
7743 case V_DEADLETS :
7744 return(h_config_deadlets);
7745 case V_FILLCOL :
7746 return(h_config_composer_wrap_column);
7747 case V_TCPOPENTIMEO :
7748 return(h_config_tcp_open_timeo);
7749 case V_TCPREADWARNTIMEO :
7750 return(h_config_tcp_readwarn_timeo);
7751 case V_TCPWRITEWARNTIMEO :
7752 return(h_config_tcp_writewarn_timeo);
7753 case V_TCPQUERYTIMEO :
7754 return(h_config_tcp_query_timeo);
7755 case V_RSHOPENTIMEO :
7756 return(h_config_rsh_open_timeo);
7757 case V_SSHOPENTIMEO :
7758 return(h_config_ssh_open_timeo);
7759 case V_USERINPUTTIMEO :
7760 return(h_config_user_input_timeo);
7761 case V_REMOTE_ABOOK_VALIDITY :
7762 return(h_config_remote_abook_validity);
7763 case V_REMOTE_ABOOK_HISTORY :
7764 return(h_config_remote_abook_history);
7765 case V_INCOMING_FOLDERS :
7766 return(h_config_incoming_folders);
7767 case V_FOLDER_SPEC :
7768 return(h_config_folder_spec);
7769 case V_NEWS_SPEC :
7770 return(h_config_news_spec);
7771 case V_ADDRESSBOOK :
7772 return(h_config_address_book);
7773 case V_GLOB_ADDRBOOK :
7774 return(h_config_glob_addrbook);
7775 case V_LAST_VERS_USED :
7776 return(h_config_last_vers);
7777 case V_SENDMAIL_PATH :
7778 return(h_config_sendmail_path);
7779 case V_OPER_DIR :
7780 return(h_config_oper_dir);
7781 case V_RSHPATH :
7782 return(h_config_rshpath);
7783 case V_RSHCMD :
7784 return(h_config_rshcmd);
7785 case V_SSHPATH :
7786 return(h_config_sshpath);
7787 case V_SSHCMD :
7788 return(h_config_sshcmd);
7789 case V_NEW_VER_QUELL :
7790 return(h_config_new_ver_quell);
7791 case V_DISABLE_DRIVERS :
7792 return(h_config_disable_drivers);
7793 case V_DISABLE_AUTHS :
7794 return(h_config_disable_auths);
7795 case V_REMOTE_ABOOK_METADATA :
7796 return(h_config_abook_metafile);
7797 case V_REPLY_STRING :
7798 return(h_config_reply_indent_string);
7799 case V_WORDSEPS :
7800 return(h_config_wordseps);
7801 case V_QUOTE_REPLACE_STRING :
7802 return(h_config_quote_replace_string);
7803 case V_REPLY_INTRO :
7804 return(h_config_reply_intro);
7805 case V_EMPTY_HDR_MSG :
7806 return(h_config_empty_hdr_msg);
7807 case V_STATUS_MSG_DELAY :
7808 return(h_config_status_msg_delay);
7809 case V_ACTIVE_MSG_INTERVAL :
7810 return(h_config_active_msg_interval);
7811 case V_MAILCHECK :
7812 return(h_config_mailcheck);
7813 case V_MAILCHECKNONCURR :
7814 return(h_config_mailchecknoncurr);
7815 case V_MAILDROPCHECK :
7816 return(h_config_maildropcheck);
7817 case V_NNTPRANGE :
7818 return(h_config_nntprange);
7819 case V_NEWS_ACTIVE_PATH :
7820 return(h_config_news_active);
7821 case V_NEWS_SPOOL_DIR :
7822 return(h_config_news_spool);
7823 case V_IMAGE_VIEWER :
7824 return(h_config_image_viewer);
7825 case V_USE_ONLY_DOMAIN_NAME :
7826 return(h_config_domain_name);
7827 case V_LAST_TIME_PRUNE_QUESTION :
7828 return(h_config_prune_date);
7829 case V_UPLOAD_CMD:
7830 return(h_config_upload_cmd);
7831 case V_UPLOAD_CMD_PREFIX:
7832 return(h_config_upload_prefix);
7833 case V_DOWNLOAD_CMD:
7834 return(h_config_download_cmd);
7835 case V_DOWNLOAD_CMD_PREFIX:
7836 return(h_config_download_prefix);
7837 case V_GOTO_DEFAULT_RULE:
7838 return(h_config_goto_default);
7839 case V_INCOMING_STARTUP:
7840 return(h_config_inc_startup);
7841 case V_PRUNING_RULE:
7842 return(h_config_pruning_rule);
7843 case V_REOPEN_RULE:
7844 return(h_config_reopen_rule);
7845 case V_THREAD_DISP_STYLE:
7846 return(h_config_thread_disp_style);
7847 case V_THREAD_INDEX_STYLE:
7848 return(h_config_thread_index_style);
7849 case V_THREAD_MORE_CHAR:
7850 return(h_config_thread_indicator_char);
7851 case V_THREAD_EXP_CHAR:
7852 return(h_config_thread_exp_char);
7853 case V_THREAD_LASTREPLY_CHAR:
7854 return(h_config_thread_lastreply_char);
7855 case V_MAILCAP_PATH :
7856 return(h_config_mailcap_path);
7857 case V_MIMETYPE_PATH :
7858 return(h_config_mimetype_path);
7859 #if !defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)
7860 case V_FIFOPATH :
7861 return(h_config_fifopath);
7862 #endif
7863 case V_NMW_WIDTH :
7864 return(h_config_newmailwidth);
7865 case V_NEWSRC_PATH :
7866 return(h_config_newsrc_path);
7867 case V_BROWSER :
7868 return(h_config_browser);
7869 #if defined(DOS) || defined(OS2)
7870 case V_FILE_DIR :
7871 return(h_config_file_dir);
7872 #endif
7873 case V_NORM_FORE_COLOR :
7874 case V_NORM_BACK_COLOR :
7875 return(h_config_normal_color);
7876 case V_REV_FORE_COLOR :
7877 case V_REV_BACK_COLOR :
7878 return(h_config_reverse_color);
7879 case V_TITLE_FORE_COLOR :
7880 case V_TITLE_BACK_COLOR :
7881 return(h_config_title_color);
7882 case V_TITLECLOSED_FORE_COLOR :
7883 case V_TITLECLOSED_BACK_COLOR :
7884 return(h_config_titleclosed_color);
7885 case V_FOLDER_FORE_COLOR:
7886 return(h_config_folder_color);
7887 case V_DIRECTORY_FORE_COLOR:
7888 return(h_config_directory_color);
7889 case V_FOLDER_LIST_FORE_COLOR:
7890 return(h_config_folder_list_color);
7891 case V_STATUS_FORE_COLOR :
7892 case V_STATUS_BACK_COLOR :
7893 return(h_config_status_color);
7894 case V_SLCTBL_FORE_COLOR :
7895 case V_SLCTBL_BACK_COLOR :
7896 return(h_config_slctbl_color);
7897 case V_QUOTE1_FORE_COLOR :
7898 case V_QUOTE2_FORE_COLOR :
7899 case V_QUOTE3_FORE_COLOR :
7900 case V_QUOTE1_BACK_COLOR :
7901 case V_QUOTE2_BACK_COLOR :
7902 case V_QUOTE3_BACK_COLOR :
7903 return(h_config_quote_color);
7904 case V_INCUNSEEN_FORE_COLOR :
7905 case V_INCUNSEEN_BACK_COLOR :
7906 return(h_config_incunseen_color);
7907 case V_SIGNATURE_FORE_COLOR :
7908 case V_SIGNATURE_BACK_COLOR :
7909 return(h_config_signature_color);
7910 case V_PROMPT_FORE_COLOR :
7911 case V_PROMPT_BACK_COLOR :
7912 return(h_config_prompt_color);
7913 case V_HEADER_GENERAL_FORE_COLOR :
7914 case V_HEADER_GENERAL_BACK_COLOR :
7915 return(h_config_header_general_color);
7916 case V_IND_PLUS_FORE_COLOR :
7917 case V_IND_IMP_FORE_COLOR :
7918 case V_IND_DEL_FORE_COLOR :
7919 case V_IND_ANS_FORE_COLOR :
7920 case V_IND_NEW_FORE_COLOR :
7921 case V_IND_UNS_FORE_COLOR :
7922 case V_IND_REC_FORE_COLOR :
7923 case V_IND_FWD_FORE_COLOR :
7924 case V_IND_PLUS_BACK_COLOR :
7925 case V_IND_IMP_BACK_COLOR :
7926 case V_IND_DEL_BACK_COLOR :
7927 case V_IND_ANS_BACK_COLOR :
7928 case V_IND_NEW_BACK_COLOR :
7929 case V_IND_UNS_BACK_COLOR :
7930 case V_IND_REC_BACK_COLOR :
7931 case V_IND_FWD_BACK_COLOR :
7932 return(h_config_index_color);
7933 case V_IND_OP_FORE_COLOR :
7934 case V_IND_OP_BACK_COLOR :
7935 return(h_config_index_opening_color);
7936 case V_IND_SUBJ_FORE_COLOR :
7937 case V_IND_SUBJ_BACK_COLOR :
7938 return(h_config_index_subject_color);
7939 case V_IND_FROM_FORE_COLOR :
7940 case V_IND_FROM_BACK_COLOR :
7941 return(h_config_index_from_color);
7942 case V_IND_HIPRI_FORE_COLOR :
7943 case V_IND_HIPRI_BACK_COLOR :
7944 case V_IND_LOPRI_FORE_COLOR :
7945 case V_IND_LOPRI_BACK_COLOR :
7946 return(h_config_index_pri_color);
7947 case V_IND_ARR_FORE_COLOR :
7948 case V_IND_ARR_BACK_COLOR :
7949 return(h_config_index_arrow_color);
7950 case V_KEYLABEL_FORE_COLOR :
7951 case V_KEYLABEL_BACK_COLOR :
7952 return(h_config_keylabel_color);
7953 case V_KEYNAME_FORE_COLOR :
7954 case V_KEYNAME_BACK_COLOR :
7955 return(h_config_keyname_color);
7956 case V_METAMSG_FORE_COLOR :
7957 case V_METAMSG_BACK_COLOR :
7958 return(h_config_metamsg_color);
7959 case V_VIEW_HDR_COLORS :
7960 return(h_config_customhdr_color);
7961 case V_INDEX_TOKEN_COLORS :
7962 return(h_config_indextoken_color);
7963 case V_PRINTER :
7964 return(h_config_printer);
7965 case V_PERSONAL_PRINT_CATEGORY :
7966 return(h_config_print_cat);
7967 case V_PERSONAL_PRINT_COMMAND :
7968 return(h_config_print_command);
7969 case V_PAT_ROLES :
7970 return(h_config_pat_roles);
7971 case V_PAT_FILTS :
7972 return(h_config_pat_filts);
7973 case V_PAT_SCORES :
7974 return(h_config_pat_scores);
7975 case V_PAT_INCOLS :
7976 return(h_config_pat_incols);
7977 case V_PAT_OTHER :
7978 return(h_config_pat_other);
7979 case V_PAT_SRCH :
7980 return(h_config_pat_srch);
7981 case V_INDEX_COLOR_STYLE :
7982 return(h_config_index_color_style);
7983 case V_TITLEBAR_COLOR_STYLE :
7984 return(h_config_titlebar_color_style);
7985 #ifdef _WINDOWS
7986 case V_FONT_NAME :
7987 return(h_config_font_name);
7988 case V_FONT_SIZE :
7989 return(h_config_font_size);
7990 case V_FONT_STYLE :
7991 return(h_config_font_style);
7992 case V_FONT_CHAR_SET :
7993 return(h_config_font_char_set);
7994 case V_PRINT_FONT_NAME :
7995 return(h_config_print_font_name);
7996 case V_PRINT_FONT_SIZE :
7997 return(h_config_print_font_size);
7998 case V_PRINT_FONT_STYLE :
7999 return(h_config_print_font_style);
8000 case V_PRINT_FONT_CHAR_SET :
8001 return(h_config_print_font_char_set);
8002 case V_WINDOW_POSITION :
8003 return(h_config_window_position);
8004 case V_CURSOR_STYLE :
8005 return(h_config_cursor_style);
8006 #else
8007 case V_COLOR_STYLE :
8008 return(h_config_color_style);
8009 #endif
8010 #ifdef ENABLE_LDAP
8011 case V_LDAP_SERVERS :
8012 return(h_config_ldap_servers);
8013 #endif
8014 #ifdef SMIME
8015 case V_PUBLICCERT_DIR :
8016 return(h_config_smime_pubcertdir);
8017 case V_PUBLICCERT_CONTAINER :
8018 return(h_config_smime_pubcertcon);
8019 case V_PRIVATEKEY_DIR :
8020 return(h_config_smime_privkeydir);
8021 case V_PRIVATEKEY_CONTAINER :
8022 return(h_config_smime_privkeycon);
8023 case V_CACERT_DIR :
8024 return(h_config_smime_cacertdir);
8025 case V_CACERT_CONTAINER :
8026 return(h_config_smime_cacertcon);
8027 #endif
8028 case V_RSS_NEWS :
8029 return(h_config_rss_news);
8030 case V_RSS_WEATHER :
8031 return(h_config_rss_weather);
8032 case V_WP_INDEXHEIGHT :
8033 return(h_config_wp_indexheight);
8034 case V_WP_INDEXLINES :
8035 return(h_config_wp_indexlines);
8036 case V_WP_AGGSTATE :
8037 return(h_config_wp_aggstate);
8038 case V_WP_STATE :
8039 return(h_config_wp_state);
8040 case V_WP_COLUMNS :
8041 return(h_config_wp_columns);
8042 default :
8043 return(NO_HELP);
8049 * We don't want the user to be able to edit their pinerc and set
8050 * printer to whatever they want if personal-print-command is fixed.
8051 * So make sure printer is set to something legitimate. If it isn't,
8052 * set it to something standard and return non-zero.
8055 printer_value_check_and_adjust(void)
8057 char **tt;
8058 char aname[100], wname[100];
8059 int ok = 0;
8060 struct variable *vars = ps_global->vars;
8062 if(vars[V_PERSONAL_PRINT_COMMAND].is_fixed && !vars[V_PRINTER].is_fixed){
8063 strncpy(aname, ANSI_PRINTER, sizeof(aname));
8064 aname[sizeof(aname)-1] = '\0';
8065 strncat(aname, "-no-formfeed", sizeof(aname)-strlen(aname)-1);
8066 strncpy(wname, WYSE_PRINTER, sizeof(wname));
8067 wname[sizeof(wname)-1] = '\0';
8068 strncat(wname, "-no-formfeed", sizeof(wname)-strlen(wname)-1);
8069 if(strucmp(VAR_PRINTER, ANSI_PRINTER) == 0
8070 || strucmp(VAR_PRINTER, aname) == 0
8071 || strucmp(VAR_PRINTER, WYSE_PRINTER) == 0
8072 || strucmp(VAR_PRINTER, wname) == 0)
8073 ok++;
8074 else if(VAR_STANDARD_PRINTER && VAR_STANDARD_PRINTER[0]){
8075 for(tt = VAR_STANDARD_PRINTER; *tt; tt++)
8076 if(strucmp(VAR_PRINTER, *tt) == 0)
8077 break;
8079 if(*tt)
8080 ok++;
8083 if(!ok){
8084 char *val;
8085 struct variable *v;
8087 if(VAR_STANDARD_PRINTER && VAR_STANDARD_PRINTER[0])
8088 val = VAR_STANDARD_PRINTER[0];
8089 else
8090 val = ANSI_PRINTER;
8092 v = &vars[V_PRINTER];
8093 if(v->main_user_val.p)
8094 fs_give((void **)&v->main_user_val.p);
8095 if(v->post_user_val.p)
8096 fs_give((void **)&v->post_user_val.p);
8097 if(v->current_val.p)
8098 fs_give((void **)&v->current_val.p);
8100 v->main_user_val.p = cpystr(val);
8101 v->current_val.p = cpystr(val);
8105 return(!ok);
8109 char **
8110 get_supported_options(void)
8112 char **config;
8113 DRIVER *d;
8114 AUTHENTICATOR *a;
8115 char *title = _("Supported features in this Alpine");
8116 char sbuf[MAX_SCREEN_COLS+1];
8117 int cnt, alcnt, len, cols, disabled, any_disabled = 0;;
8120 * Line count:
8121 * Title + blank = 2
8122 * SSL Title + SSL lines + blank = 5
8123 * Auth title + blank = 2
8124 * Driver title + blank = 2
8125 * LDAP title + LDAP line = 2
8126 * Disabled explanation + blank line = 4
8127 * end = 1
8129 cnt = 18;
8130 for(a = mail_lookup_auth(1); a; a = a->next)
8131 cnt++;
8132 for(d = (DRIVER *)mail_parameters(NIL, GET_DRIVERS, NIL);
8133 d; d = d->next)
8134 cnt++;
8136 alcnt = cnt;
8137 config = (char **) fs_get(alcnt * sizeof(char *));
8138 memset(config, 0, alcnt * sizeof(char *));
8140 cols = ps_global->ttyo ? ps_global->ttyo->screen_cols : 0;
8141 len = utf8_width(title);
8142 snprintf(sbuf, sizeof(sbuf), "%*s%s", cols > len ? (cols-len)/2 : 0, "", title);
8144 cnt = 0;
8145 if(cnt < alcnt)
8146 config[cnt] = cpystr(sbuf);
8148 if(++cnt < alcnt)
8149 config[cnt] = cpystr("");
8151 if(++cnt < alcnt)
8152 /* TRANSLATORS: headings */
8153 config[cnt] = cpystr(_("Encryption:"));
8155 if(++cnt < alcnt && mail_parameters(NIL, GET_SSLDRIVER, NIL))
8156 config[cnt] = cpystr(_(" TLS and SSL"));
8157 else
8158 config[cnt] = cpystr(_(" None (no TLS or SSL)"));
8159 #ifdef SSL_SUPPORTS_TLSV1_2
8160 if(++cnt < alcnt)
8161 config[cnt] = cpystr(" TLSv1.1, TLSv1.2, and DTLSv1");
8162 #endif
8163 #ifdef SMIME
8164 if(++cnt < alcnt)
8165 config[cnt] = cpystr(" S/MIME");
8166 #endif
8168 if(++cnt < alcnt)
8169 config[cnt] = cpystr("");
8171 if(++cnt < alcnt)
8172 config[cnt] = cpystr(_("Authenticators:"));
8174 for(a = mail_lookup_auth(1); a; a = a->next){
8175 disabled = (a->client == NULL && a->server == NULL);
8176 any_disabled += disabled;
8177 snprintf(sbuf, sizeof(sbuf), " %s%s", a->name, disabled ? " (disabled)" : "");
8178 if(++cnt < alcnt)
8179 config[cnt] = cpystr(sbuf);
8182 if(++cnt < alcnt)
8183 config[cnt] = cpystr("");
8185 if(++cnt < alcnt)
8186 config[cnt] = cpystr(_("Mailbox drivers:"));
8188 for(d = (DRIVER *)mail_parameters(NIL, GET_DRIVERS, NIL);
8189 d; d = d->next){
8190 disabled = (d->flags & DR_DISABLE);
8191 any_disabled += disabled;
8192 snprintf(sbuf, sizeof(sbuf), " %s%s", d->name, disabled ? " (disabled)" : "");
8193 if(++cnt < alcnt)
8194 config[cnt] = cpystr(sbuf);
8197 if(++cnt < alcnt)
8198 config[cnt] = cpystr("");
8200 if(++cnt < alcnt)
8201 config[cnt] = cpystr(_("Directories:"));
8203 #ifdef ENABLE_LDAP
8204 if(++cnt < alcnt)
8205 config[cnt] = cpystr(" LDAP");
8206 #else
8207 if(++cnt < alcnt)
8208 config[cnt] = cpystr(" None (no LDAP)");
8209 #endif
8211 if(any_disabled){
8212 if(++cnt < alcnt)
8213 config[cnt] = cpystr("");
8215 if(ps_global->ttyo){
8216 if(++cnt < alcnt)
8217 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."));
8219 else{
8220 if(++cnt < alcnt)
8221 config[cnt] = cpystr(_("Authenticators may be disabled because of the \"disable-these-authenticators\""));
8222 if(++cnt < alcnt)
8223 config[cnt] = cpystr(_("hidden config option. Mailbox drivers may be disabled because of the"));
8224 if(++cnt < alcnt)
8225 config[cnt] = cpystr(_("\"disable-these-drivers\" hidden config option."));
8229 if(++cnt < alcnt)
8230 config[cnt] = NULL;
8232 return(config);
8236 unsigned
8237 reset_startup_rule(MAILSTREAM *stream)
8239 long rflags = ROLE_DO_OTHER;
8240 PAT_STATE pstate;
8241 PAT_S *pat;
8242 unsigned startup_rule;
8244 startup_rule = IS_NOTSET;
8246 if(stream && nonempty_patterns(rflags, &pstate)){
8247 for(pat = first_pattern(&pstate); pat; pat = next_pattern(&pstate)){
8248 if(match_pattern(pat->patgrp, stream, NULL, NULL, NULL,
8249 SE_NOSERVER|SE_NOPREFETCH))
8250 break;
8253 if(pat && pat->action && !pat->action->bogus)
8254 startup_rule = pat->action->startup_rule;
8257 return(startup_rule);
8261 #ifdef _WINDOWS
8263 char *
8264 transformed_color(old)
8265 char *old;
8267 if(!old)
8268 return("");
8270 if(!struncmp(old, "color008", 8))
8271 return("colorlgr");
8272 else if(!struncmp(old, "color009", 8))
8273 return("colormgr");
8274 else if(!struncmp(old, "color010", 8))
8275 return("colordgr");
8277 return("");
8282 * If this is the first time we've run a version > 4.40, and there
8283 * is evidence that the config file has not been used by unix pine,
8284 * then we convert color008 to colorlgr, color009 to colormgr, and
8285 * color010 to colordgr. If the config file is being used by
8286 * unix pine then color008 may really supposed to be color008, color009
8287 * may really supposed to be red, and color010 may really supposed to be
8288 * green. Same if we've already run 4.41 or higher previously.
8290 * Returns 0 if no changes, > 0 if something was changed.
8293 convert_pc_gray_names(ps, prc, which)
8294 struct pine *ps;
8295 PINERC_S *prc;
8296 EditWhich which;
8298 struct variable *v;
8299 int ret = 0, ic = 0;
8300 char **s, *t, *p, *pstr, *new, *pval, **apval, **lval;
8302 for(v = ps->vars; v->name; v++){
8303 if(!color_holding_var(ps, v) || v == &ps->vars[V_KW_COLORS])
8304 continue;
8306 if(v == &ps->vars[V_VIEW_HDR_COLORS]){
8308 if((lval = LVAL(v,which)) != NULL){
8309 /* fix these in place */
8310 for(s = lval; (t = *s) != NULL; s++){
8311 if((p = srchstr(t, "FG=color008")) ||
8312 (p = srchstr(t, "FG=color009")) ||
8313 (p = srchstr(t, "FG=color010"))){
8314 strncpy(p+3, transformed_color(p+3), 8);
8315 ret++;
8318 if((p = srchstr(t, "BG=color008")) ||
8319 (p = srchstr(t, "BG=color009")) ||
8320 (p = srchstr(t, "BG=color010"))){
8321 strncpy(p+3, transformed_color(p+3), 8);
8322 ret++;
8327 else{
8328 if((pval = PVAL(v,which)) != NULL){
8329 apval = APVAL(v,which);
8330 if(apval && (!strucmp(pval, "color008") ||
8331 !strucmp(pval, "color009") ||
8332 !strucmp(pval, "color010"))){
8333 new = transformed_color(pval);
8334 if(*apval)
8335 fs_give((void **)apval);
8337 *apval = cpystr(new);
8338 ret++;
8344 v = &ps->vars[V_PAT_INCOLS];
8345 if((lval = LVAL(v,which)) != NULL){
8346 for(s = lval; (t = *s) != NULL; s++){
8347 if((pstr = srchstr(t, "action=")) != NULL){
8348 if((p = srchstr(pstr, "FG=color008")) ||
8349 (p = srchstr(pstr, "FG=color009")) ||
8350 (p = srchstr(pstr, "FG=color010"))){
8351 strncpy(p+3, transformed_color(p+3), 8);
8352 ic++;
8355 if((p = srchstr(pstr, "BG=color008")) ||
8356 (p = srchstr(pstr, "BG=color009")) ||
8357 (p = srchstr(pstr, "BG=color010"))){
8358 strncpy(p+3, transformed_color(p+3), 8);
8359 ic++;
8365 if(ic)
8366 set_current_val(&ps->vars[V_PAT_INCOLS], TRUE, TRUE);
8368 return(ret+ic);
8373 unix_color_style_in_pinerc(prc)
8374 PINERC_S *prc;
8376 PINERC_LINE *pline;
8378 for(pline = prc ? prc->pinerc_lines : NULL;
8379 pline && (pline->var || pline->line); pline++)
8380 if(pline->line && !struncmp("color-style=", pline->line, 12))
8381 return(1);
8383 return(0);
8386 char *
8387 pcpine_general_help(titlebuf)
8388 char *titlebuf;
8390 if(titlebuf)
8391 strcpy(titlebuf, "PC Alpine For Windows");
8393 return(pcpine_help(h_pine_for_windows));
8396 #endif /* _WINDOWS */