* new version 2.19.9993
[alpine.git] / pith / conf.c
blobd6083f0171def323de0a258d5fa8a035c00bfc22
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-2014 Eduardo Chappa
8 * Copyright 2006-2009 University of Washington
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * ========================================================================
19 /*======================================================================
20 conf.c
21 Implements the Pine configuration management routines
22 ====*/
25 #include "../pith/headers.h"
26 #include "../pith/init.h"
27 #include "../pith/conf.h"
28 #include "../pith/state.h"
29 #include "../pith/remote.h"
30 #include "../pith/keyword.h"
31 #include "../pith/mailview.h"
32 #include "../pith/list.h"
33 #include "../pith/status.h"
34 #include "../pith/ldap.h"
35 #include "../pith/folder.h"
36 #include "../pith/thread.h"
37 #include "../pith/news.h"
38 #include "../pith/util.h"
39 #include "../pith/pattern.h"
40 #include "../pith/color.h"
41 #include "../pith/options.h"
42 #include "../pith/busy.h"
43 #include "../pith/readfile.h"
44 #include "../pith/hist.h"
45 #include "../pith/mailindx.h"
46 #include "../pith/tempfile.h"
47 #include "../pith/icache.h"
48 #include "../pith/sort.h"
49 #include "../pith/smime.h"
50 #include "../pith/charconv/utf8.h"
51 #ifdef _WINDOWS
52 #include "../pico/osdep/mswin.h"
53 #endif
56 #define TO_BAIL_THRESHOLD 60
60 * Internal prototypes
62 void convert_configvars_to_utf8(struct variable *, char *);
63 void convert_configvar_to_utf8(struct variable *, char *);
64 void set_current_pattern_vals(struct pine *);
65 void convert_pattern_data(void);
66 void convert_filts_pattern_data(void);
67 void convert_scores_pattern_data(void);
68 void convert_pinerc_patterns(long);
69 void convert_pinerc_filts_patterns(long);
70 void convert_pinerc_scores_patterns(long);
71 void set_old_growth_bits(struct pine *, int);
72 int var_is_in_rest_of_file(char *, char *);
73 char *skip_over_this_var(char *, char *);
74 char *native_nl(char *);
75 void set_color_val(struct variable *, int);
76 int copy_localfile_to_remotefldr(RemType, char *, char *, char *, char **);
77 char *backcompat_convert_from_utf8(char **, size_t, char *);
78 #ifdef _WINDOWS
79 char *transformed_color(char *);
80 int convert_pc_gray_names(struct pine *, PINERC_S *, EditWhich);
81 int unix_color_style_in_pinerc(PINERC_S *);
82 char *pcpine_general_help(char *);
83 char *pcpine_help(HelpType); /* defined in alpine/help */
84 #endif /* _WINDOWS */
87 /* hook too allow caller to decide what to do about failure */
88 int (*pith_opt_remote_pinerc_failure)(void);
91 /*------------------------------------
92 Some definitions to keep the static "variable" array below
93 a bit more readable...
94 ----*/
95 CONF_TXT_T cf_text_comment[] = "#\n# Alpine configuration file\n#\n# This file sets the configuration options used by Alpine and PC-Alpine. These\n# options are usually set from within Alpine or PC-Alpine. There may be a\n# system-wide configuration file which sets the defaults for some of the\n# variables. On Unix, run alpine -conf to see how system defaults have been set.\n# For variables that accept multiple values, list elements are\
96 separated by\n# commas. A line beginning with a space or tab is considered to be a\n# continuation of the previous line. For a variable to be unset its value must\n# be blank. To set a variable to the empty string its value should be \"\".\n# You can override system defaults by setting a variable to the empty string.\n# Lines beginning with \"#\" are comments, and ignored by Alpine.\n";
99 CONF_TXT_T cf_text_personal_name[] = "Over-rides your full name from Unix password file. Required for PC-Alpine.";
101 CONF_TXT_T cf_text_user_id[] = "Your login/e-mail user name";
103 CONF_TXT_T cf_text_user_domain[] = "Sets domain part of From: and local addresses in outgoing mail.";
105 CONF_TXT_T cf_text_smtp_server[] = "List of SMTP servers for sending mail. If blank: Unix Alpine uses sendmail.";
107 CONF_TXT_T cf_text_nntp_server[] = "NNTP server for posting news. Also sets news-collections for news reading.";
109 #ifdef SMIME
111 CONF_TXT_T cf_text_publiccertdir[] = "Public certificates are kept in files in this directory. The files should\n# contain certificates in PEM format. The name of each file should look\n# like <emailaddress>.crt. The default directory is .alpine-smime/public.";
113 CONF_TXT_T cf_text_privatekeydir[] = "Private keys are kept in files in this directory. The files are in PEM format.\n# The name of a file should look like <emailaddress>.key.\n# The default directory is .alpine-smime/private.";
115 CONF_TXT_T cf_text_cacertdir[] = "Certificate Authority certificates (in addition to the normal CACerts for the\n# system) are kept in files in this directory. The files are in PEM format.\n# Filenames should end with .crt. The default directory is .alpine-smime/ca.";
117 CONF_TXT_T cf_text_publiccertcontainer[] = "If this option is set then public certificates are kept in a single container\n# \"file\" similar to a remote configuration file instead of in the\n# smime-publiccert-directory. The value can be a remote or local folder\n# specification like for a non-standard pinerc value. The default\n# is that it is not set.";
119 CONF_TXT_T cf_text_privatekeycontainer[] = "If this option is set then private keys are kept in a single container\n# \"file\" similar to a remote configuration file instead of in the\n# private-key-directory. The value can be a remote or local folder\n# specification like for a non-standard pinerc value. The default\n# is that it is not set.";
121 CONF_TXT_T cf_text_cacertcontainer[] = "If this option is set then CAcerts are kept in a single container\n# \"file\" similar to a remote configuration file instead of in the\n# ca-cert-directory. The value can be a remote or local folder\n# specification like for a non-standard pinerc value. The default\n# is that it is not set.";
123 #endif /* SMIME */
125 #ifdef ENABLE_LDAP
126 CONF_TXT_T cf_text_ldap_server[] = "LDAP servers for looking up addresses.";
127 #endif /* ENABLE_LDAP */
129 CONF_TXT_T cf_text_rss_news[] = "RSS News feed";
131 CONF_TXT_T cf_text_rss_weather[] = "RSS Weather feed";
133 CONF_TXT_T cf_text_wp_indexheight[] = "Web Alpine index table row height";
135 CONF_TXT_T cf_text_wp_indexlines[] = "Web Alpine number of index lines in table";
137 CONF_TXT_T cf_text_wp_aggstate[] = "Web Alpine aggregate operations tab state";
139 CONF_TXT_T cf_text_wp_state[] = "Web Alpine various aspects of cross-session state";
141 CONF_TXT_T cf_text_wp_columns[] = "Web Alpine preferred width for message display in characters";
143 CONF_TXT_T cf_text_inbox_path[] = "Path of (local or remote) INBOX, e.g. ={mail.somewhere.edu}inbox\n# Normal Unix default is the local INBOX (usually /usr/spool/mail/$USER).";
145 CONF_TXT_T cf_text_incoming_folders[] = "List of incoming msg folders besides INBOX, e.g. ={host2}inbox, {host3}inbox\n# Syntax: optnl-label {optnl-imap-host-name}folder-path";
147 CONF_TXT_T cf_text_folder_collections[] = "List of directories where saved-message folders may be. First one is\n# the default for Saves. Example: Main {host1}mail/[], Desktop mail\\[]\n# Syntax: optnl-label {optnl-imap-hostname}optnl-directory-path[]";
149 CONF_TXT_T cf_text_news_collections[] = "List, only needed if nntp-server not set, or news is on a different host\n# than used for NNTP posting. Examples: News *[] or News *{host3/nntp}[]\n# Syntax: optnl-label *{news-host/protocol}[]";
151 CONF_TXT_T cf_text_pruned_folders[] = "List of folders, assumed to be in first folder collection,\n# offered for pruning each month. For example: mumble";
153 CONF_TXT_T cf_text_default_fcc[] = "Over-rides default path for sent-mail folder, e.g. =old-mail (using first\n# folder collection dir) or ={host2}sent-mail or =\"\" (to suppress saving).\n# Default: sent-mail (Unix) or SENTMAIL.MTX (PC) in default folder collection.";
155 CONF_TXT_T cf_text_default_saved[] = "Over-rides default path for saved-msg folder, e.g. =saved-messages (using 1st\n# folder collection dir) or ={host2}saved-mail or =\"\" (to suppress saving).\n# Default: saved-messages (Unix) or SAVEMAIL.MTX (PC) in default collection.";
157 CONF_TXT_T cf_text_postponed_folder[] = "Over-rides default path for postponed messages folder, e.g. =pm (which uses\n# first folder collection dir) or ={host4}pm (using home dir on host4).\n# Default: postponed-msgs (Unix) or POSTPOND.MTX (PC) in default fldr coltn.";
159 CONF_TXT_T cf_text_mail_directory[] = "Alpine compares this value with the first folder collection directory.\n# If they match (or no folder collections are defined), and the directory\n# does not exist, Alpine will create and use it. Default: ~/mail";
161 CONF_TXT_T cf_text_read_message_folder[] = "If set, specifies where already-read messages will be moved upon quitting.";
163 CONF_TXT_T cf_text_form_letter_folder[] = "If set, specifies where form letters should be stored.";
165 CONF_TXT_T cf_text_trash_folder[] = "If set, specifies where trash is moved to in Web Alpine.";
167 CONF_TXT_T cf_text_signature_file[] = "Over-rides default path for signature file. Default is ~/.signature";
169 CONF_TXT_T cf_text_literal_sig[] = "Contains the actual signature contents as opposed to the signature filename.\n# If defined, this overrides the signature-file. Default is undefined.";
171 CONF_TXT_T cf_text_global_address_book[] = "List of file or path names for global/shared addressbook(s).\n# Default: none\n# Syntax: optnl-label path-name";
173 CONF_TXT_T cf_text_address_book[] = "List of file or path names for personal addressbook(s).\n# Default: ~/.addressbook (Unix) or \\PINE\\ADDRBOOK (PC)\n# Syntax: optnl-label path-name";
175 CONF_TXT_T cf_text_feature_list[] = "List of features; see Alpine's Setup/options menu for the current set.\n# e.g. feature-list= select-without-confirm, signature-at-bottom\n# Default condition for all of the features is no-.";
177 CONF_TXT_T cf_text_initial_keystroke_list[] = "Alpine executes these keys upon startup (e.g. to view msg 13: i,j,1,3,CR,v)";
179 CONF_TXT_T cf_text_default_composer_hdrs[] = "Only show these headers (by default) when composing messages";
181 CONF_TXT_T cf_text_customized_hdrs[] = "Add these customized headers (and possible default values) when composing";
183 CONF_TXT_T cf_text_view_headers[] = "When viewing messages, include this list of headers";
185 CONF_TXT_T cf_text_view_margin_left[] = "When viewing messages, number of blank spaces between left display edge and text";
187 CONF_TXT_T cf_text_view_margin_right[] = "When viewing messages, number of blank spaces between right display edge and text";
189 CONF_TXT_T cf_text_quote_suppression[] = "When viewing messages, number of lines of quote displayed before suppressing";
191 CONF_TXT_T cf_text_wordsep[] = "When these characters appear in the middle of a word in the composer\n# the forward word function will stop at the first text following (as happens\n# with SPACE characters by default)";
193 CONF_TXT_T cf_text_color_style[] = "Controls display of color";
195 CONF_TXT_T cf_text_current_indexline_style[] = "Controls display of color for current index line";
197 CONF_TXT_T cf_text_titlebar_color_style[] = "Controls display of color for the titlebar at top of screen";
199 CONF_TXT_T cf_text_view_hdr_color[] = "When viewing messages, these are the header colors";
201 CONF_TXT_T cf_text_index_token_color[] = "Colors in which tokens will be displayed in the index screen";
203 CONF_TXT_T cf_text_save_msg_name_rule[] = "Determines default folder name for Saves...\n# Choices: default-folder, by-sender, by-from, by-recipient, last-folder-used.\n# Default: \"default-folder\", i.e. \"saved-messages\" (Unix) or \"SAVEMAIL\" (PC).";
205 CONF_TXT_T cf_text_fcc_name_rule[] = "Determines default name for Fcc...\n# Choices: default-fcc, by-recipient, last-fcc-used.\n# Default: \"default-fcc\" (see also \"default-fcc=\" variable.)";
207 CONF_TXT_T cf_text_sort_key[] = "Sets presentation order of messages in Index. Choices:\n# Subject, From, Arrival, Date, Size, To, Cc, OrderedSubj, Score, and Thread.\n# Order may be reversed by appending /Reverse. Default: \"Arrival\".";
209 CONF_TXT_T cf_text_addrbook_sort_rule[] = "Sets presentation order of address book entries. Choices: dont-sort,\n# fullname-with-lists-last, fullname, nickname-with-lists-last, nickname\n# Default: \"fullname-with-lists-last\".";
211 CONF_TXT_T cf_text_folder_sort_rule[] = "Sets presentation order of folder list entries. Choices: alphabetical,\n# alpha-with-dirs-last, alpha-with-dirs-first.\n# Default: \"alpha-with-directories-last\".";
213 CONF_TXT_T cf_text_old_char_set[] = "Character-set is obsolete, use display-character-set, keyboard-character-set,\n# and posting-character-set.";
215 CONF_TXT_T cf_text_disp_char_set[] = "Reflects capabilities of the display you have.\n# If unset, the default is taken from your locale. That is usually the right\n# thing to use. Typical alternatives include UTF-8, ISO-8859-x, and EUC-JP\n# (where x is a number between 1 and 9).";
217 CONF_TXT_T cf_text_key_char_set[] = "Reflects capabilities of the keyboard you have.\n# If unset, the default is to use the same value\n# used for the display-character-set.";
219 CONF_TXT_T cf_text_post_character_set[] = "Defaults to UTF-8. This is used for outgoing messages.\n# It is usually correct to leave this unset.";
221 CONF_TXT_T cf_text_unk_character_set[] = "Defaults to nothing, which is equivalent to US-ASCII. This is used for\n# unlabeled incoming messages. It is ok to leave this unset but if you receive\n# unlabeled mail that is usually in some known character set, set that here.";
223 CONF_TXT_T cf_text_editor[] = "Specifies the program invoked by ^_ in the Composer,\n# or the \"enable-alternate-editor-implicitly\" feature.";
225 CONF_TXT_T cf_text_speller[] = "Specifies the program invoked by ^T in the Composer.";
227 CONF_TXT_T cf_text_deadlets[] = "Specifies the number of dead letter files to keep when canceling.";
229 CONF_TXT_T cf_text_fillcol[] = "Specifies the column of the screen where the composer should wrap.";
231 CONF_TXT_T cf_text_replystr[] = "Specifies the string to insert when replying to a message.";
233 CONF_TXT_T cf_text_quotereplstr[] = "Specifies the string to replace quotes with when viewing a message.";
235 CONF_TXT_T cf_text_replyintro[] = "Specifies the introduction to insert when replying to a message.";
237 CONF_TXT_T cf_text_emptyhdr[] = "Specifies the string to use when sending a message with no to or cc.";
239 CONF_TXT_T cf_text_image_viewer[] = "Program to view images (e.g. GIF or TIFF attachments).";
241 CONF_TXT_T cf_text_browser[] = "List of programs to open Internet URLs (e.g. http or ftp references).";
243 CONF_TXT_T cf_text_inc_startup[] = "Sets message which cursor begins on. Choices: first-unseen, first-recent,\n# first-important, first-important-or-unseen, first-important-or-recent,\n# first, last. Default: \"first-unseen\".";
245 CONF_TXT_T cf_pruning_rule[] = "Allows a default answer for the prune folder questions. Choices: yes-ask,\n# yes-no, no-ask, no-no, ask-ask, ask-no. Default: \"ask-ask\".";
247 CONF_TXT_T cf_reopen_rule[] = "Controls behavior when reopening an already open folder.";
249 CONF_TXT_T cf_text_thread_disp_style[] = "Style that MESSAGE INDEX is displayed in when threading.";
251 CONF_TXT_T cf_text_thread_index_style[] = "Style of THREAD INDEX or default MESSAGE INDEX when threading.";
253 CONF_TXT_T cf_text_thread_more_char[] = "When threading, character used to indicate collapsed messages underneath.";
255 CONF_TXT_T cf_text_thread_exp_char[] = "When threading, character used to indicate expanded messages underneath.";
257 CONF_TXT_T cf_text_thread_lastreply_char[] = "When threading, character used to indicate this is the last reply\n# to the parent of this message.";
259 CONF_TXT_T cf_text_use_only_domain_name[] = "If \"user-domain\" not set, strips hostname in FROM address. (Unix only)";
261 CONF_TXT_T cf_text_printer[] = "Your default printer selection";
263 CONF_TXT_T cf_text_personal_print_command[] = "List of special print commands";
265 CONF_TXT_T cf_text_personal_print_cat[] = "Which category default print command is in";
267 CONF_TXT_T cf_text_standard_printer[] = "The system wide standard printers";
269 CONF_TXT_T cf_text_last_time_prune_quest[] = "Set by Alpine; controls beginning-of-month sent-mail pruning.";
271 CONF_TXT_T cf_text_last_version_used[] = "Set by Alpine; controls display of \"new version\" message.";
273 CONF_TXT_T cf_text_disable_drivers[] = "List of mail drivers to disable.";
275 CONF_TXT_T cf_text_disable_auths[] = "List of SASL authenticators to disable.";
277 CONF_TXT_T cf_text_remote_abook_metafile[] = "Set by Alpine; contains data for caching remote address books.";
279 CONF_TXT_T cf_text_old_patterns[] = "Patterns is obsolete, use patterns-xxx";
281 CONF_TXT_T cf_text_old_filters[] = "Patterns-filters is obsolete, use patterns-filters2";
283 CONF_TXT_T cf_text_old_scores[] = "Patterns-scores is obsolete, use patterns-scores2";
285 CONF_TXT_T cf_text_patterns[] = "Patterns and their actions are stored here.";
287 CONF_TXT_T cf_text_remote_abook_history[] = "How many extra copies of remote address book should be kept. Default: 3";
289 CONF_TXT_T cf_text_remote_abook_validity[] = "Minimum number of minutes between checks for remote address book changes.\n# 0 means never check except when opening a remote address book.\n# -1 means never check. Default: 5";
291 CONF_TXT_T cf_text_bugs_fullname[] = "Full name for bug report address used by \"Report Bug\" command";
293 CONF_TXT_T cf_text_bugs_address[] = "Email address used to send bug reports";
295 CONF_TXT_T cf_text_bugs_extras[] = "Program/Script used by \"Report Bug\" command. No default.";
297 CONF_TXT_T cf_text_suggest_fullname[] = "Full name for suggestion address used by \"Report Bug\" command";
299 CONF_TXT_T cf_text_suggest_address[] = "Email address used to send suggestions";
301 CONF_TXT_T cf_text_local_fullname[] = "Full name for \"local support\" address used by \"Report Bug\" command.\n# Default: Local Support";
303 CONF_TXT_T cf_text_local_address[] = "Email address used to send to \"local support\".\n# Default: postmaster";
305 CONF_TXT_T cf_text_forced_abook[] = "Force these address book entries into all writable personal address books.\n# Syntax is forced-abook-entry=nickname|fullname|address\n# This is a comma-separated list of entries, each with syntax above.\n# Existing entries with same nickname are not replaced.\n# Example: help|Help Desk|help@ourdomain.com";
307 CONF_TXT_T cf_text_kblock_passwd[] = "This is a number between 1 and 5. It is the number of times a user will\n# have to enter a password when they run the keyboard lock command in the\n# main menu. Default is 1.";
309 CONF_TXT_T cf_text_sendmail_path[] = "This names the path to an alternative program, and any necessary arguments,\n# to be used in posting mail messages. Example:\n# /usr/lib/sendmail -oem -t -oi\n# or,\n# /usr/local/bin/sendit.sh\n# The latter a script found in Alpine distribution's contrib/util directory.\n# NOTE: The program MUST read the message to be posted on standard input,\n# AND operate in the style of sendmail's \"-t\" option.";
311 CONF_TXT_T cf_text_oper_dir[] = "This names the root of the tree to which the user is restricted when reading\n# and writing folders and files. For example, on Unix ~/work confines the\n# user to the subtree beginning with their work subdirectory.\n# (Note: this alone is not sufficient for preventing access. You will also\n# need to restrict shell access and so on, see Alpine Technical Notes.)\n# Default: not set (so no restriction)";
313 CONF_TXT_T cf_text_in_fltr[] = "This variable takes a list of programs that message text is piped into\n# after MIME decoding, prior to display.";
315 CONF_TXT_T cf_text_out_fltr[] = "This defines a program that message text is piped into before MIME\n# encoding, prior to sending";
317 CONF_TXT_T cf_text_alt_addrs[] = "A list of alternate addresses the user is known by";
319 CONF_TXT_T cf_text_keywords[] = "A list of keywords for use in categorizing messages";
321 CONF_TXT_T cf_text_kw_colors[] = "Colors used to display keywords in the index";
323 CONF_TXT_T cf_text_kw_braces[] = "Characters which surround keywords in SUBJKEY token.\n# Default is \"{\" \"} \"";
325 CONF_TXT_T cf_text_opening_sep[] = "Characters between subject and opening text in SUBJECTTEXT token.\n# Default is \" - \"";
327 CONF_TXT_T cf_text_abook_formats[] = "This is a list of formats for address books. Each entry in the list is made\n# up of space-delimited tokens telling which fields are displayed and in\n# which order. See help text";
329 CONF_TXT_T cf_text_index_format[] = "This gives a format for displaying the index. It is made\n# up of space-delimited tokens telling which fields are displayed and in\n# which order. See help text";
331 CONF_TXT_T cf_text_overlap[] = "The number of lines of overlap when scrolling through message text";
333 CONF_TXT_T cf_text_maxremstreams[] = "The maximum number of non-stayopen remote connections that Alpine will use";
335 CONF_TXT_T cf_text_permlocked[] = "A list of folders that should be left open once opened (INBOX is implicit)";
337 CONF_TXT_T cf_text_margin[] = "Number of lines from top and bottom of screen where single\n# line scrolling occurs.";
339 CONF_TXT_T cf_text_stat_msg_delay[] = "The number of seconds to sleep after writing a status message";
341 CONF_TXT_T cf_text_busy_cue_rate[] = "Number of times per-second to update busy cue messages";
343 CONF_TXT_T cf_text_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";
345 CONF_TXT_T cf_text_mailcheck[] = "The approximate number of seconds between checks for new mail";
347 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";
349 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";
351 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";
353 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\".";
355 CONF_TXT_T cf_text_news_spooldir[] = "Directory containing system's news data.\n# The default is typically \"/usr/spool/news\"";
357 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.";
359 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.";
361 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.";
363 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.";
365 CONF_TXT_T cf_text_goto_default[] = "Sets the default folder and collection offered at the Goto Command's prompt.";
367 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.";
369 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.";
371 CONF_TXT_T cf_text_newmail_fifo_path[] = "Sets the filename for the newmail fifo (named pipe). Unix only.";
373 CONF_TXT_T cf_text_nmw_width[] = "Sets the width for the NewMail screen.";
375 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.";
377 CONF_TXT_T cf_text_debug_mem[] = "Debug-memory is obsolete";
379 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).";
381 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.";
383 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.";
385 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.";
387 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.";
389 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.";
391 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\")";
393 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.";
395 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.";
397 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.";
399 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.";
401 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.";
403 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.";
405 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\")";
407 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.";
409 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.";
411 CONF_TXT_T cf_text_elm_style_save[] = "Elm-style-save is obsolete, use saved-msg-name-rule";
413 CONF_TXT_T cf_text_header_in_reply[] = "Header-in-reply is obsolete, use include-header-in-reply in feature-list";
415 CONF_TXT_T cf_text_feature_level[] = "Feature-level is obsolete, use feature-list";
417 CONF_TXT_T cf_text_old_style_reply[] = "Old-style-reply is obsolete, use signature-at-bottom in feature-list";
419 CONF_TXT_T cf_text_compose_mime[] = "Compose-mime is obsolete";
421 CONF_TXT_T cf_text_show_all_characters[] = "Show-all-characters is obsolete";
423 CONF_TXT_T cf_text_save_by_sender[] = "Save-by-sender is obsolete, use saved-msg-name-rule";
425 CONF_TXT_T cf_text_file_dir[] = "Default directory used for Attachment handling (attach and save)\n# and Export command output";
427 CONF_TXT_T cf_text_folder_extension[] = "Folder-extension is obsolete";
429 CONF_TXT_T cf_text_normal_foreground_color[] = "Choose: black, blue, green, cyan, red, magenta, yellow, or white.";
431 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.";
433 CONF_TXT_T cf_text_newsrc_path[] = "Full path and name of NEWSRC file";
436 /*----------------------------------------------------------------------
437 These are the variables that control a number of pine functions. They
438 come out of the .pinerc and the /usr/local/lib/pine.conf files. Some can
439 be set by the user while in Alpine. Eventually all the local ones should
440 be so and maybe the global ones too.
442 Each variable can have a command-line, user, global, and current value.
443 All of these values are malloc'd. The user value is the one read out of
444 the user's .pinerc, the global value is the one from the system pine
445 configuration file. There are often defaults for the global values, set
446 at the start of init_vars(). Perhaps someday there will be group values.
447 The current value is the one that is actually in use.
448 ----*/
449 /* name is_changed_val
450 remove_quotes |
451 is_outermost | |
452 is_onlymain | | |
453 is_fixed | | | |
454 is_list | | | | |
455 is_global | | | | | |
456 is_user | | | | | | |
457 been_written | | | | | | | |
458 is_used | | | | | | | | |
459 is_obsolete | | | | | | | | | |
460 | | | | | | | | | | |
461 (on following line) description | | | | | | | | | | |
462 | | | | | | | | | | | |
463 | | | | | | | | | | | | */
464 static struct variable variables[] = {
465 {"personal-name", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
466 NULL, cf_text_personal_name},
468 #if defined(DOS) || defined(OS2)
469 /* Have to have this on DOS, PC's, Macs, etc... */
470 "user-id", 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0,
471 #else /* Don't allow on UNIX machines for some security */
472 "user-id", 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0,
473 #endif
474 "User ID", cf_text_user_id},
475 {"user-domain", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
476 NULL, cf_text_user_domain},
477 {"smtp-server", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
478 "SMTP Server (for sending)", cf_text_smtp_server},
479 {"nntp-server", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
480 "NNTP Server (for news)", cf_text_nntp_server},
481 {"inbox-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
482 NULL, cf_text_inbox_path},
483 {"incoming-archive-folders", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
484 NULL, cf_text_archived_folders},
485 {"pruned-folders", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
486 NULL, cf_text_pruned_folders},
487 {"default-fcc", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
488 "Default Fcc (File carbon copy)", cf_text_default_fcc},
489 {"default-saved-msg-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
490 "Default Saved Message Folder", cf_text_default_saved},
491 {"postponed-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
492 NULL, cf_text_postponed_folder},
493 {"read-message-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
494 NULL, cf_text_read_message_folder},
495 {"form-letter-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
496 NULL, cf_text_form_letter_folder},
497 {"trash-folder", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
498 NULL, cf_text_trash_folder},
499 {"literal-signature", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
500 NULL, cf_text_literal_sig},
501 {"signature-file", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
502 NULL, cf_text_signature_file},
503 {"feature-list", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
504 NULL, cf_text_feature_list},
505 {"initial-keystroke-list", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
506 NULL, cf_text_initial_keystroke_list},
507 {"default-composer-hdrs", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
508 "Default Composer Headers", cf_text_default_composer_hdrs},
509 {"customized-hdrs", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
510 "Customized Headers", cf_text_customized_hdrs},
511 {"viewer-hdrs", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
512 "Viewer Headers", cf_text_view_headers},
513 {"viewer-margin-left", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
514 NULL, cf_text_view_margin_left},
515 {"viewer-margin-right", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
516 NULL, cf_text_view_margin_right},
517 {"quote-suppression-threshold", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
518 NULL, cf_text_quote_suppression},
519 {"saved-msg-name-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
520 "Saved Message Name Rule", cf_text_save_msg_name_rule},
521 {"fcc-name-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
522 NULL, cf_text_fcc_name_rule},
523 {"sort-key", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
524 NULL, cf_text_sort_key},
525 {"addrbook-sort-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
526 "Address Book Sort Rule", cf_text_addrbook_sort_rule},
527 {"folder-sort-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
528 NULL, cf_text_folder_sort_rule},
529 {"goto-default-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
530 NULL, cf_text_goto_default},
531 {"incoming-startup-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
532 NULL, cf_text_inc_startup},
533 {"pruning-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
534 NULL, cf_pruning_rule},
535 {"folder-reopen-rule", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
536 NULL, cf_reopen_rule},
537 {"threading-display-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
538 NULL, cf_text_thread_disp_style},
539 {"threading-index-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
540 NULL, cf_text_thread_index_style},
541 {"threading-indicator-character", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
542 NULL, cf_text_thread_more_char},
543 {"threading-expanded-character", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
544 NULL, cf_text_thread_exp_char},
545 {"threading-lastreply-character", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
546 "Threading Last Reply Character", cf_text_thread_lastreply_char},
547 #ifndef _WINDOWS
548 {"display-character-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
549 NULL, cf_text_disp_char_set},
550 {"character-set", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
551 NULL, cf_text_old_char_set},
552 {"keyboard-character-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
553 NULL, cf_text_key_char_set},
554 #endif /* ! _WINDOWS */
555 {"posting-character-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
556 NULL, cf_text_post_character_set},
557 {"unknown-character-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
558 NULL, cf_text_unk_character_set},
559 {"editor", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
560 NULL, cf_text_editor},
561 {"speller", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
562 NULL, cf_text_speller},
563 {"composer-wrap-column", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
564 NULL, cf_text_fillcol},
565 {"reply-indent-string", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
566 NULL, cf_text_replystr},
567 {"reply-leadin", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
568 NULL, cf_text_replyintro},
569 {"quote-replace-string", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
570 NULL, cf_text_quotereplstr},
571 {"composer-word-separators", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
572 NULL, cf_text_wordsep},
573 {"empty-header-message", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
574 NULL, cf_text_emptyhdr},
575 {"image-viewer", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
576 NULL, cf_text_image_viewer},
577 {"use-only-domain-name", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
578 NULL, cf_text_use_only_domain_name},
579 {"bugs-fullname", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
580 NULL, cf_text_bugs_fullname},
581 {"bugs-address", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
582 NULL, cf_text_bugs_address},
583 {"bugs-additional-data", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
584 NULL, cf_text_bugs_extras},
585 {"suggest-fullname", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
586 NULL, cf_text_suggest_fullname},
587 {"suggest-address", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
588 NULL, cf_text_suggest_address},
589 {"local-fullname", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
590 NULL, cf_text_local_fullname},
591 {"local-address", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
592 NULL, cf_text_local_address},
593 {"forced-abook-entry", 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0,
594 NULL, cf_text_forced_abook},
595 {"kblock-passwd-count", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
596 NULL, cf_text_kblock_passwd},
597 {"display-filters", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
598 NULL, cf_text_in_fltr},
599 {"sending-filters", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
600 NULL, cf_text_out_fltr},
601 {"alt-addresses", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
602 "Alternate Addresses", cf_text_alt_addrs},
603 {"keywords", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
604 NULL, cf_text_keywords},
605 {"keyword-surrounding-chars", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
606 "Keyword Surrounding Characters", cf_text_kw_braces},
607 {"opening-text-separator-chars", 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0,
608 "Opening Text Separator Characters", cf_text_opening_sep},
609 {"addressbook-formats", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
610 "Address Book Formats", cf_text_abook_formats},
611 {"index-format", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
612 NULL, cf_text_index_format},
613 {"viewer-overlap", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
614 NULL, cf_text_overlap},
615 {"scroll-margin", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
616 NULL, cf_text_margin},
617 {"status-message-delay", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
618 NULL, cf_text_stat_msg_delay},
619 {"busy-cue-rate", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
620 NULL, cf_text_busy_cue_rate},
621 {"mailcap-check-interval", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
622 NULL, cf_text_psleep},
623 {"mail-check-interval", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
624 NULL, cf_text_mailcheck},
625 {"mail-check-interval-noncurrent", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
626 NULL, cf_text_mailchecknoncurr},
627 {"maildrop-check-minimum", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
628 NULL, cf_text_maildropcheck},
629 {"nntp-range", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
630 "NNTP Range", cf_text_nntprange},
631 {"newsrc-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
632 NULL, cf_text_newsrc_path},
633 {"news-active-file-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
634 NULL, cf_text_news_active},
635 {"news-spool-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
636 NULL, cf_text_news_spooldir},
637 {"upload-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
638 NULL, cf_text_upload_cmd},
639 {"upload-command-prefix", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
640 NULL, cf_text_upload_prefix},
641 {"download-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
642 NULL, cf_text_download_cmd},
643 {"download-command-prefix", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
644 NULL, cf_text_download_prefix},
645 {"mailcap-search-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
646 NULL, cf_text_mailcap_path},
647 {"mimetype-search-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
648 NULL, cf_text_mimetype_path},
649 {"url-viewers", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
650 "URL-Viewers", cf_text_browser},
651 {"max-remote-connections", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
652 "Maximum Remote Connections", cf_text_maxremstreams},
653 {"stay-open-folders", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
654 "Stayopen Folders", cf_text_permlocked},
655 {"incoming-check-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
656 NULL, cf_text_inc_check_timeo},
657 {"incoming-check-interval", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
658 NULL, cf_text_inc_check_interval},
659 {"incoming-check-interval-secondary", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
660 NULL, cf_text_inc_second_check_interval},
661 {"incoming-check-list", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
662 NULL, cf_text_inc_check_list},
663 {"dead-letter-files", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
664 NULL, cf_text_deadlets},
665 #if !defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)
666 {"newmail-fifo-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
667 "NewMail FIFO Path", cf_text_newmail_fifo_path},
668 #endif
669 {"newmail-window-width", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
670 "NewMail Window Width", cf_text_nmw_width},
672 * Starting here, the variables are hidden in the Setup/Config screen.
673 * They are exposed if feature expose-hidden-config is set.
675 {"incoming-folders", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
676 NULL, cf_text_incoming_folders},
677 {"mail-directory", 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
678 NULL, cf_text_mail_directory},
679 {"folder-collections", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
680 NULL, cf_text_folder_collections},
681 {"news-collections", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
682 NULL, cf_text_news_collections},
683 {"address-book", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
684 NULL, cf_text_address_book},
685 {"global-address-book", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
686 NULL, cf_text_global_address_book},
687 {"standard-printer", 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0,
688 NULL, cf_text_standard_printer},
689 {"last-time-prune-questioned", 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0,
690 NULL, cf_text_last_time_prune_quest},
691 {"last-version-used", 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0,
692 NULL, cf_text_last_version_used},
693 {"sendmail-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
694 NULL, cf_text_sendmail_path},
695 {"operating-dir", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
696 NULL, cf_text_oper_dir},
697 {"user-input-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
698 NULL, cf_text_user_input_timeo},
699 /* OBSOLETE */
700 #ifdef DEBUGJOURNAL
701 {"debug-memory", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
702 NULL, cf_text_debug_mem},
703 #endif
704 {"tcp-open-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
705 "TCP Open Timeout", cf_text_tcp_open_timeo},
706 {"tcp-read-warning-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
707 "TCP Read Warning Timeout", cf_text_tcp_read_timeo},
708 {"tcp-write-warning-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
709 "TCP Write Warning Timeout", cf_text_tcp_write_timeo},
710 {"tcp-query-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
711 "TCP Query Timeout", cf_text_tcp_query_timeo},
712 {"rsh-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
713 NULL, cf_text_rsh_command},
714 {"rsh-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
715 NULL, cf_text_rsh_path},
716 {"rsh-open-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
717 NULL, cf_text_rsh_open_timeo},
718 {"ssh-command", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
719 NULL, cf_text_ssh_command},
720 {"ssh-path", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
721 NULL, cf_text_ssh_path},
722 {"ssh-open-timeout", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
723 NULL, cf_text_ssh_open_timeo},
724 {"new-version-threshold", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
725 NULL, cf_text_version_threshold},
726 {"disable-these-drivers", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
727 NULL, cf_text_disable_drivers},
728 {"disable-these-authenticators", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
729 NULL, cf_text_disable_auths},
730 {"remote-abook-metafile", 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0,
731 NULL, cf_text_remote_abook_metafile},
732 {"remote-abook-history", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
733 NULL, cf_text_remote_abook_history},
734 {"remote-abook-validity", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
735 NULL, cf_text_remote_abook_validity},
736 {"printer", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
737 NULL, cf_text_printer},
738 {"personal-print-command", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
739 NULL, cf_text_personal_print_command},
740 {"personal-print-category", 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0,
741 NULL, cf_text_personal_print_cat},
742 {"patterns", 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
743 NULL, cf_text_old_patterns},
744 {"patterns-roles", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
745 NULL, cf_text_patterns},
746 {"patterns-filters2", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
747 "Patterns Filters", cf_text_patterns},
748 {"patterns-filters", 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
749 NULL, cf_text_old_filters},
750 {"patterns-scores2", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
751 "Patterns Scores", cf_text_patterns},
752 {"patterns-scores", 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
753 NULL, cf_text_old_scores},
754 {"patterns-indexcolors", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
755 NULL, cf_text_patterns},
756 {"patterns-other", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
757 NULL, cf_text_patterns},
758 {"patterns-search", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
759 NULL, cf_text_patterns},
760 /* OBSOLETE VARS */
761 {"elm-style-save", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
762 NULL, cf_text_elm_style_save},
763 {"header-in-reply", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
764 NULL, cf_text_header_in_reply},
765 {"feature-level", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
766 NULL, cf_text_feature_level},
767 {"old-style-reply", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
768 NULL, cf_text_old_style_reply},
769 {"compose-mime", 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0,
770 NULL, cf_text_compose_mime},
771 {"show-all-characters", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
772 NULL, cf_text_show_all_characters},
773 {"save-by-sender", 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
774 NULL, cf_text_save_by_sender},
775 #if defined(DOS) || defined(OS2)
776 {"file-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
777 NULL, cf_text_file_dir},
778 {"folder-extension", 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0,
779 NULL, cf_text_folder_extension},
780 #endif
781 #ifndef _WINDOWS
782 {"color-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
783 NULL, cf_text_color_style},
784 #endif
785 {"current-indexline-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
786 NULL, cf_text_current_indexline_style},
787 {"titlebar-color-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
788 NULL, cf_text_titlebar_color_style},
789 {"normal-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
790 NULL, cf_text_normal_foreground_color},
791 {"normal-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
792 {"reverse-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
793 {"reverse-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
794 {"title-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
795 {"title-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
796 {"title-closed-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
797 {"title-closed-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
798 {"folder-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
799 {"folder-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
800 {"directory-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
801 {"directory-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
802 {"folder-list-text-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
803 {"folder-list-text-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
804 {"status-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
805 {"status-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
806 {"keylabel-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
807 {"keylabel-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
808 {"keyname-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
809 {"keyname-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
810 {"selectable-item-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
811 {"selectable-item-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
812 {"meta-message-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
813 {"meta-message-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
814 {"quote1-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
815 {"quote1-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
816 {"quote2-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
817 {"quote2-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
818 {"quote3-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
819 {"quote3-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
820 {"incoming-unseen-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
821 {"incoming-unseen-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
822 {"signature-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
823 {"signature-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
824 {"prompt-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
825 {"prompt-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
826 {"header-general-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
827 {"header-general-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
828 {"index-to-me-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
829 {"index-to-me-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
830 {"index-important-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
831 {"index-important-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
832 {"index-deleted-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
833 {"index-deleted-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
834 {"index-answered-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
835 {"index-answered-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
836 {"index-new-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
837 {"index-new-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
838 {"index-recent-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
839 {"index-recent-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
840 {"index-forward-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
841 {"index-forward-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
842 {"index-unseen-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
843 {"index-unseen-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
844 {"index-highpriority-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
845 {"index-highpriority-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
846 {"index-lowpriority-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
847 {"index-lowpriority-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
848 {"index-arrow-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
849 {"index-arrow-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
850 {"index-subject-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
851 {"index-subject-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
852 {"index-from-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
853 {"index-from-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
854 {"index-opening-foreground-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
855 {"index-opening-background-color", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0},
856 {"index-token-colors", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
857 NULL, cf_text_index_token_color},
858 {"viewer-hdr-colors", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
859 "Viewer Header Colors", cf_text_view_hdr_color},
860 {"keyword-colors", 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0,
861 NULL, cf_text_kw_colors},
862 #ifdef _WINDOWS
863 {"font-name", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
864 NULL, "name and size of font."},
865 {"font-size", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
866 {"font-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
867 {"font-char-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
868 {"print-font-name", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
869 NULL, "name and size of printer font."},
870 {"print-font-size", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
871 {"print-font-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
872 {"print-font-char-set", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
873 {"window-position", 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0,
874 NULL, cf_text_window_position},
875 {"cursor-style", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, NULL},
876 #endif /* _WINDOWS */
877 #ifdef SMIME
878 {"smime-public-cert-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
879 "S/MIME - Public Cert Directory", cf_text_publiccertdir},
880 {"smime-public-cert-container", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
881 "S/MIME - Public Cert Container", cf_text_publiccertcontainer},
882 {"smime-private-key-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
883 "S/MIME - Private Key Directory", cf_text_privatekeydir},
884 {"smime-private-key-container", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
885 "S/MIME - Private Key Container", cf_text_privatekeycontainer},
886 {"smime-cacert-directory", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
887 "S/MIME - Cert Authority Directory", cf_text_cacertdir},
888 {"smime-cacert-container", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
889 "S/MIME - Cert Authority Container", cf_text_cacertcontainer},
890 #endif /* SMIME */
891 #ifdef ENABLE_LDAP
892 {"ldap-servers", 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0,
893 "LDAP Servers", cf_text_ldap_server},
894 #endif /* ENABLE_LDAP */
895 {"rss-news", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
896 "WEB ALPINE - RSS News", cf_text_rss_news},
897 {"rss-weather", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
898 "WEB ALPINE - RSS Weather", cf_text_rss_weather},
899 {"wp-indexheight", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
900 "WEB ALPINE - Index Height", cf_text_wp_indexheight},
901 {"wp-indexlines", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
902 "WEB ALPINE - Index Lines", cf_text_wp_indexlines},
903 {"wp-aggstate", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
904 "WEB ALPINE - Aggregate State", cf_text_wp_aggstate},
905 {"wp-state", 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0,
906 "WEB ALPINE - Cross Session State", cf_text_wp_state},
907 {"wp-columns", 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0,
908 "WEB ALPINE - Columns", cf_text_wp_columns},
909 {NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NULL,NULL}
913 struct variable *
914 var_from_name(char *name)
916 struct variable *v;
917 int i;
919 if(!(name && name[0]))
920 return(NULL);
922 for(i = 0; (v = &variables[i]) && v->name; i++)
923 if(!strucmp(v->name,name))
924 return(v);
926 return(NULL);
930 void
931 init_init_vars(struct pine *ps)
933 ps->vars = variables;
937 #define DSIZE (25000)
938 /* this is just like dprint except it prints to a char * */
939 #ifdef DEBUG
940 #define mprint(n,x) { \
941 if(debug >= (n)){ \
942 snprintf x ; \
943 db += strlen(db); \
946 #else
947 #define mprint(n,x)
948 #endif
951 * this was split out from init_vars so we can get at the
952 * pinerc location sooner.
954 void
955 init_pinerc(struct pine *ps, char **debug_out)
957 char buf[MAXPATH+1], *p, *db;
958 #if defined(DOS) || defined(OS2)
959 char buf2[MAXPATH+1], l_pinerc[MAXPATH+1];
960 int nopinerc = 0, confregset = -1;
961 register struct variable *vars = ps->vars;
962 #endif
964 #ifdef DEBUG
966 * Since this routine is called before we've had a chance to set up
967 * the debug file for output, we put the debugging into memory and
968 * pass it back to the caller for use after init_debug(). We just
969 * allocate plenty of space.
971 if(debug_out){
972 db = *debug_out = (char *)fs_get(DSIZE * sizeof(char));
973 db[0] = '\0';
975 #endif
977 mprint(2, (db, DSIZE-(db-(*debug_out)), "\n -- init_pinerc --\n\n"));
979 #if defined(DOS) || defined(OS2)
981 * Rules for the config/support file locations under DOS are:
983 * 1) The location of the PINERC is searched for in the following
984 * order of precedence:
985 * - File pointed to by '-p' command line option
986 * - File pointed to by PINERC environment variable
987 * - $HOME\pine
988 * - same dir as argv[0]
990 * 2) The HOME environment variable, if not set, defaults to
991 * root of the current working drive (see alpine.c)
993 * 3) The default for external files (PINE.SIG and ADDRBOOK) is the
994 * same directory as the pinerc
996 * 4) The support files (PINE.HLP and PINE.NDX) are expected to be in
997 * the same directory as PINE.EXE.
1000 if(ps->prc){
1001 mprint(2, (db, DSIZE-(db-(*debug_out)),
1002 "Personal config \"%.100s\" comes from command line\n",
1003 (ps->prc && ps->prc->name) ? ps->prc->name : "<no name>"));
1005 else{
1006 mprint(2, (db, DSIZE-(db-(*debug_out)),
1007 "Personal config not set on cmdline, checking for $PINERC\n"));
1011 * First, if prc hasn't been set by a command-line -p, check to see
1012 * if PINERC is in the environment. If so, treat it just like we
1013 * would have treated it if it were a command-line arg.
1015 if(!ps->prc && (p = getenv("PINERC")) && *p){
1016 char path[MAXPATH], dir[MAXPATH];
1018 if(IS_REMOTE(p) || is_absolute_path(p)){
1019 strncpy(path, p, sizeof(path)-1);
1020 path[sizeof(path)-1] = '\0';
1022 else{
1023 getcwd(dir, sizeof(dir));
1024 build_path(path, dir, p, sizeof(path));
1027 if(!IS_REMOTE(p))
1028 ps->pinerc = cpystr(path);
1030 ps->prc = new_pinerc_s(path);
1032 if(ps->prc){
1033 mprint(2, (db, DSIZE-(db-(*debug_out)),
1034 " yes, personal config \"%.100s\" comes from $PINERC\n",
1035 (ps->prc && ps->prc->name) ? ps->prc->name : "<no name>"));
1040 * Pinerc used to be the name of the pinerc file. Then we added
1041 * the possibility of the pinerc file being remote, and we replaced
1042 * the variable pinerc with the structure prc. Unfortunately, some
1043 * parts of pine rely on the fact that pinerc is the name of the
1044 * pinerc _file_, and use the directory that the pinerc file is located
1045 * in for their own purposes. We want to preserve that so things will
1046 * keep working. So, even if the real pinerc is remote, we need to
1047 * put the name of a pinerc file in the pinerc variable so that the
1048 * directory which contains that file is writable. The file itself
1049 * doesn't have to exist for this purpose, since we are really only
1050 * using the name of the directory containing the file. Twisted.
1051 * (Alternatively, we could fix all of the code that uses the pinerc
1052 * variable for this purpose to use a new variable which really is
1053 * just a directory.) hubert 2000-sep
1055 * There are 3 cases. If pinerc is already set that means that the user
1056 * gave either a -p pinerc or an environment pinerc that is a local file,
1057 * and we are done. If pinerc is not set, then either prc is set or not.
1058 * If prc is set then the -p arg or PINERC value is a remote pinerc.
1059 * In that case we need to find a local directory to use, and put that
1060 * directory in the pinerc variable (with a fake filename tagged on).
1061 * If prc is not set, then user hasn't told us anything so we have to
1062 * try to find the default pinerc file by looking down the path of
1063 * possibilities. When we find it, we'll also use that directory.
1065 if(!ps->pinerc){
1066 *l_pinerc = '\0';
1067 *buf = '\0';
1069 if(ps->prc){ /* remote pinerc case */
1071 * We don't give them an l_pinerc unless they tell us where
1072 * to put it.
1074 if(ps->aux_files_dir)
1075 build_path(l_pinerc, ps->aux_files_dir, SYSTEM_PINERC,
1076 sizeof(l_pinerc));
1077 else{
1079 * Search for a writable directory.
1080 * Mimic what happens in !prc for local case, except we
1081 * don't need to look for the actual file.
1084 /* check if $HOME\PINE is writable */
1085 build_path(buf2, ps->home_dir, DF_PINEDIR, sizeof(buf2));
1086 if(is_writable_dir(buf2) == 0)
1087 build_path(l_pinerc, buf2, SYSTEM_PINERC, sizeof(l_pinerc));
1088 else{ /* $HOME\PINE not a writable dir */
1089 /* use this unless registry redirects us */
1090 build_path(l_pinerc, ps->pine_dir, SYSTEM_PINERC,
1091 sizeof(l_pinerc));
1092 #ifdef _WINDOWS
1093 /* if in registry, use that value */
1094 if(mswin_reg(MSWR_OP_GET, MSWR_PINE_RC, buf2, sizeof(buf2))
1095 && !IS_REMOTE(buf2)){
1096 strncpy(l_pinerc, buf2, sizeof(l_pinerc)-1);
1097 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1099 #endif
1103 else{ /* searching for pinerc file to use */
1105 * Buf2 is $HOME\PINE. If $HOME is not explicitly set,
1106 * it defaults to the current working drive (often C:).
1107 * See alpine.c to see how it is initially set.
1110 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, searching...\n"));
1111 build_path(buf2, ps->home_dir, DF_PINEDIR, sizeof(buf2));
1112 mprint(2, (db, DSIZE-(db-(*debug_out)),
1113 " checking for writable %.100s dir \"%.100s\" off of homedir\n",
1114 DF_PINEDIR, buf2));
1115 if(is_writable_dir(buf2) == 0){
1117 * $HOME\PINE exists and is writable.
1118 * See if $HOME\PINE\PINERC exists.
1120 build_path(buf, buf2, SYSTEM_PINERC, sizeof(buf));
1121 strncpy(l_pinerc, buf, sizeof(l_pinerc)-1);
1122 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1123 mprint(2, (db, DSIZE-(db-(*debug_out)), " yes, now checking for file \"%.100s\"\n",
1124 buf));
1125 if(can_access(buf, ACCESS_EXISTS) == 0){ /* found it! */
1127 * Buf is what we were looking for.
1128 * It is local and can be used for the directory, too.
1130 mprint(2, (db, DSIZE-(db-(*debug_out)), " found it\n"));
1132 else{
1134 * No $HOME\PINE\PINERC, look for
1135 * one in same dir as PINE.EXE.
1137 build_path(buf2, ps->pine_dir, SYSTEM_PINERC,
1138 sizeof(buf2));
1139 mprint(2, (db, DSIZE-(db-(*debug_out)),
1140 " no, checking for \"%.100s\" in pine.exe dir\n",
1141 buf2));
1142 if(can_access(buf2, ACCESS_EXISTS) == 0){
1143 /* found it! */
1144 mprint(2, (db, DSIZE-(db-(*debug_out)), " found it\n"));
1145 strncpy(buf, buf2, sizeof(buf)-1);
1146 buf[sizeof(buf)-1] = '\0';
1147 strncpy(l_pinerc, buf2, sizeof(l_pinerc)-1);
1148 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1150 else{
1151 #ifdef _WINDOWS
1152 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, checking in registry\n"));
1153 if(mswin_reg(MSWR_OP_GET, MSWR_PINE_RC,
1154 buf2, sizeof(buf2))){
1155 strncpy(buf, buf2, sizeof(buf)-1);
1156 buf[sizeof(buf)-1] = '\0';
1157 if(!IS_REMOTE(buf2)){
1158 strncpy(l_pinerc, buf2, sizeof(l_pinerc)-1);
1159 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1162 * Now buf is the pinerc to be used, l_pinerc is
1163 * the directory, which may be either same as buf
1164 * or it may be $HOME\PINE if registry gives us
1165 * a remote pinerc.
1167 mprint(2, (db, DSIZE-(db-(*debug_out)), " found \"%.100s\" in registry\n",
1168 buf));
1170 else{
1171 nopinerc = 1;
1172 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found, asking user\n"));
1174 #else
1175 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found\n"));
1176 #endif
1181 * Buf is the pinerc (could be remote if from registry)
1182 * and l_pinerc is the local pinerc, which may not exist.
1185 else{ /* $HOME\PINE not a writable dir */
1187 * We notice that the order of checking in the registry
1188 * and checking in the ALPINE.EXE directory are different
1189 * in this case versus the is_writable_dir(buf2) case, and
1190 * that does sort of look like a bug. However,
1191 * we don't think this is a bug since we did it on purpose
1192 * a long time ago. So even though we can't remember why
1193 * it is this way, we think we would rediscover why if we
1194 * changed it! So we won't change it.
1198 * Change the default to use to the ALPINE.EXE directory.
1200 build_path(buf, ps->pine_dir, SYSTEM_PINERC, sizeof(buf));
1201 strncpy(l_pinerc, buf, sizeof(l_pinerc)-1);
1202 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1203 #ifdef _WINDOWS
1204 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, not writable, checking in registry\n"));
1205 /* if in registry, use that value */
1206 if(mswin_reg(MSWR_OP_GET, MSWR_PINE_RC, buf2, sizeof(buf2))){
1207 strncpy(buf, buf2, sizeof(buf)-1);
1208 buf[sizeof(buf)-1] = '\0';
1209 mprint(2, (db, DSIZE-(db-(*debug_out)), " found \"%.100s\" in registry\n",
1210 buf));
1211 if(!IS_REMOTE(buf)){
1212 strncpy(l_pinerc, buf, sizeof(l_pinerc)-1);
1213 l_pinerc[sizeof(l_pinerc)-1] = '\0';
1216 else{
1217 mprint(2, (db, DSIZE-(db-(*debug_out)),
1218 " no, checking for \"%.100s\" in alpine.exe dir\n",
1219 buf));
1221 if(can_access(buf, ACCESS_EXISTS) == 0){
1222 mprint(2, (db, DSIZE-(db-(*debug_out)), " found it\n"));
1224 else{
1225 nopinerc = 1;
1226 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found, asking user\n"));
1229 #else
1230 mprint(2, (db, DSIZE-(db-(*debug_out)),
1231 " no, checking for \"%.100s\" in alpine.exe dir\n",
1232 buf));
1234 if(can_access(buf, ACCESS_EXISTS) == 0){
1235 mprint(2, (db, DSIZE-(db-(*debug_out)), " found it\n"));
1237 else{
1238 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found, creating it\n"));
1240 #endif
1244 * When we get here we have buf set to the name of the
1245 * pinerc, which could be local or remote. We have l_pinerc
1246 * set to the same as buf if buf is local, and set to another
1247 * name otherwise, hopefully contained in a writable directory.
1249 #ifdef _WINDOWS
1250 if(nopinerc || ps_global->install_flag){
1251 char buf3[MAXPATH+1];
1253 confregset = 0;
1254 strncpy(buf3, buf, MAXPATH);
1255 buf3[MAXPATH] = '\0';
1256 if(os_config_dialog(buf3, MAXPATH,
1257 &confregset, nopinerc) == 0){
1258 strncpy(buf, buf3, MAXPATH);
1259 buf[MAXPATH] = '\0';
1260 mprint(2, (db, DSIZE-(db-(*debug_out)), " not found, creating it\n"));
1261 mprint(2, (db, DSIZE-(db-(*debug_out)), " user says use \"%.100s\"\n", buf));
1262 if(!IS_REMOTE(buf)){
1263 strncpy(l_pinerc, buf, MAXPATH);
1264 l_pinerc[MAXPATH] = '\0';
1267 else{
1268 exit(-1);
1271 #endif
1272 ps->prc = new_pinerc_s(buf);
1275 ps->pinerc = cpystr(l_pinerc);
1278 #if defined(DOS) || defined(OS2)
1280 * The goal here is to set the auxiliary directory in the pinerc variable.
1281 * We are making the assumption that any reference to the pinerc variable
1282 * after this point is used only as a directory in which to store things,
1283 * with the prc variable being the preferred place to store pinerc location.
1284 * If -aux isn't set, then there is no change. -jpf 08/2001
1286 if(ps->aux_files_dir){
1287 l_pinerc[0] = '\0';
1288 build_path(l_pinerc, ps->aux_files_dir, SYSTEM_PINERC,
1289 sizeof(l_pinerc));
1290 if(ps->pinerc) fs_give((void **)&ps->pinerc);
1291 ps->pinerc = cpystr(l_pinerc);
1292 mprint(2, (db, DSIZE-(db-(*debug_out)), "Setting aux_files_dir to \"%.100s\"\n",
1293 ps->aux_files_dir));
1295 #endif
1297 #ifdef _WINDOWS
1298 if(confregset && (ps->update_registry != UREG_NEVER_SET))
1299 mswin_reg(MSWR_OP_SET | ((ps->update_registry == UREG_ALWAYS_SET)
1300 || confregset == 1 ? MSWR_OP_FORCE : 0),
1301 MSWR_PINE_RC,
1302 (ps->prc && ps->prc->name) ?
1303 ps->prc->name : ps->pinerc, (size_t)NULL);
1304 #endif
1307 * Now that we know the default for the PINERC, build NEWSRC default.
1308 * Backward compatibility makes this kind of funky. If what the
1309 * c-client thinks the NEWSRC should be exists *AND* it doesn't
1310 * already exist in the PINERC's dir, use c-client's default, otherwise
1311 * use the one next to the PINERC...
1313 p = last_cmpnt(ps->pinerc);
1314 buf[0] = '\0';
1315 if(p != NULL){
1316 strncpy(buf, ps->pinerc, MIN(p - ps->pinerc, sizeof(buf)-1));
1317 buf[MIN(p - ps->pinerc, sizeof(buf)-1)] = '\0';
1320 mprint(2, (db, DSIZE-(db-(*debug_out)), "Using directory \"%.100s\" for auxiliary files\n", buf));
1321 strncat(buf, "NEWSRC", sizeof(buf)-1-strlen(buf));
1323 if(!(p = (void *) mail_parameters(NULL, GET_NEWSRC, (void *)NULL))
1324 || can_access(p, ACCESS_EXISTS) < 0
1325 || can_access(buf, ACCESS_EXISTS) == 0){
1326 mail_parameters(NULL, SET_NEWSRC, (void *)buf);
1327 GLO_NEWSRC_PATH = cpystr(buf);
1329 else
1330 GLO_NEWSRC_PATH = cpystr(p);
1332 if(ps->pconf){
1333 mprint(2, (db, DSIZE-(db-(*debug_out)), "Global config \"%.100s\" comes from command line\n",
1334 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1336 else{
1337 mprint(2, (db, DSIZE-(db-(*debug_out)),
1338 "Global config not set on cmdline, checking for $PINECONF\n"));
1341 if(!ps->pconf && (p = getenv("PINECONF"))){
1342 ps->pconf = new_pinerc_s(p);
1343 if(ps->pconf){
1344 mprint(2, (db, DSIZE-(db-(*debug_out)),
1345 " yes, global config \"%.100s\" comes from $PINECONF\n",
1346 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1349 #ifdef _WINDOWS
1350 else if(!ps->pconf
1351 && mswin_reg(MSWR_OP_GET, MSWR_PINE_CONF, buf2, sizeof(buf2))){
1352 ps->pconf = new_pinerc_s(buf2);
1353 if(ps->pconf){
1354 mprint(2, (db, DSIZE-(db-(*debug_out)),
1355 " yes, global config \"%.100s\" comes from Registry\n",
1356 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1359 #endif
1360 if(!ps->pconf){
1361 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, there is no global config\n"));
1363 #ifdef _WINDOWS
1364 else if (ps->pconf && ps->pconf->name &&
1365 (ps->update_registry != UREG_NEVER_SET)){
1366 mswin_reg(MSWR_OP_SET | ((ps->update_registry == UREG_ALWAYS_SET)
1367 ? MSWR_OP_FORCE : 0),
1368 MSWR_PINE_CONF,
1369 ps->pconf->name, (size_t)NULL);
1371 #endif
1373 if(!ps->prc)
1374 ps->prc = new_pinerc_s(ps->pinerc);
1376 if(ps->exceptions){
1377 mprint(2, (db, DSIZE-(db-(*debug_out)),
1378 "Exceptions config \"%.100s\" comes from command line\n",
1379 ps->exceptions));
1381 else{
1382 mprint(2, (db, DSIZE-(db-(*debug_out)),
1383 "Exceptions config not set on cmdline, checking for $PINERCEX\n"));
1387 * Exceptions is done slightly differently from pinerc. Instead of setting
1388 * post_prc in args.c we just set the string and use it here. We do
1389 * that so that we can put it in the same directory as the pinerc if
1390 * exceptions is a relative name, and pinerc may not be set until here.
1392 * First, just like for pinerc, check environment variable if it wasn't
1393 * set on the command line.
1395 if(!ps->exceptions && (p = getenv("PINERCEX")) && *p){
1396 ps->exceptions = cpystr(p);
1397 if(ps->exceptions){
1398 mprint(2, (db, DSIZE-(db-(*debug_out)),
1399 " yes, exceptions config \"%.100s\" comes from $PINERCEX\n",
1400 ps->exceptions));
1405 * If still not set, try specific file in same dir as pinerc.
1406 * Only use it if the file exists.
1408 if(!ps->exceptions){
1409 p = last_cmpnt(ps->pinerc);
1410 buf[0] = '\0';
1411 if(p != NULL){
1412 strncpy(buf, ps->pinerc, MIN(p - ps->pinerc, sizeof(buf)-1));
1413 buf[MIN(p - ps->pinerc, sizeof(buf)-1)] = '\0';
1416 strncat(buf, "PINERCEX", sizeof(buf)-1-strlen(buf));
1418 mprint(2, (db, DSIZE-(db-(*debug_out)),
1419 " no, checking for default \"%.100s\" in pinerc dir\n", buf));
1420 if(can_access(buf, ACCESS_EXISTS) == 0) /* found it! */
1421 ps->exceptions = cpystr(buf);
1423 if(ps->exceptions){
1424 mprint(2, (db, DSIZE-(db-(*debug_out)),
1425 " yes, exceptions config \"%.100s\" comes from default\n",
1426 ps->exceptions));
1428 else{
1429 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, there is no exceptions config\n"));
1433 #else /* unix */
1435 if(ps->pconf){
1436 mprint(2, (db, DSIZE-(db-(*debug_out)), "Global config \"%.100s\" comes from command line\n",
1437 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1440 if(!ps->pconf){
1441 ps->pconf = new_pinerc_s(SYSTEM_PINERC);
1442 if(ps->pconf){
1443 mprint(2, (db, DSIZE-(db-(*debug_out)), "Global config \"%.100s\" is default\n",
1444 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<no name>"));
1448 if(!ps->pconf){
1449 mprint(2, (db, DSIZE-(db-(*debug_out)), "No global config!\n"));
1452 if(ps->prc){
1453 mprint(2, (db, DSIZE-(db-(*debug_out)), "Personal config \"%.100s\" comes from command line\n",
1454 (ps->prc && ps->prc->name) ? ps->prc->name : "<no name>"));
1457 if(!ps->pinerc){
1458 build_path(buf, ps->home_dir, ".pinerc", sizeof(buf));
1459 ps->pinerc = cpystr(buf);
1462 if(!ps->prc){
1463 ps->prc = new_pinerc_s(ps->pinerc);
1464 if(ps->prc){
1465 mprint(2, (db, DSIZE-(db-(*debug_out)), "Personal config \"%.100s\" is default\n",
1466 (ps->prc && ps->prc->name) ? ps->prc->name : "<no name>"));
1470 if(!ps->prc){
1471 mprint(2, (db, DSIZE-(db-(*debug_out)), "No personal config!\n"));
1474 if(ps->exceptions){
1475 mprint(2, (db, DSIZE-(db-(*debug_out)),
1476 "Exceptions config \"%.100s\" comes from command line\n",
1477 ps->exceptions));
1481 * If not set, try specific file in same dir as pinerc.
1482 * Only use it if the file exists.
1484 if(!ps->exceptions){
1485 p = last_cmpnt(ps->pinerc);
1486 buf[0] = '\0';
1487 if(p != NULL){
1488 strncpy(buf, ps->pinerc, MIN(p - ps->pinerc, sizeof(buf)-1));
1489 buf[MIN(p - ps->pinerc, sizeof(buf)-1)] = '\0';
1492 strncat(buf, ".pinercex", sizeof(buf)-1-strlen(buf));
1493 mprint(2, (db, DSIZE-(db-(*debug_out)), "Exceptions config not set on cmdline\n checking for default \"%.100s\" in pinerc dir\n", buf));
1495 if(can_access(buf, ACCESS_EXISTS) == 0) /* found it! */
1496 ps->exceptions = cpystr(buf);
1498 if(ps->exceptions){
1499 mprint(2, (db, DSIZE-(db-(*debug_out)),
1500 " yes, exceptions config \"%.100s\" is default\n",
1501 ps->exceptions));
1503 else{
1504 mprint(2, (db, DSIZE-(db-(*debug_out)), " no, there is no exceptions config\n"));
1508 #endif /* unix */
1510 if(ps->exceptions){
1512 if(!IS_REMOTE(ps->exceptions) &&
1513 !is_absolute_path(ps->exceptions)){
1514 #if defined(DOS) || defined(OS2)
1515 p = last_cmpnt(ps->pinerc);
1516 buf[0] = '\0';
1517 if(p != NULL){
1518 strncpy(buf, ps->pinerc, MIN(p - ps->pinerc, sizeof(buf)-1));
1519 buf[MIN(p - ps->pinerc, sizeof(buf)-1)] = '\0';
1522 strncat(buf, ps->exceptions, sizeof(buf)-1-strlen(buf));
1523 #else
1524 build_path(buf, ps->home_dir, ps->exceptions, sizeof(buf));
1525 #endif
1527 else{
1528 strncpy(buf, ps->exceptions, sizeof(buf)-1);
1529 buf[sizeof(buf)-1] = '\0';
1532 ps->post_prc = new_pinerc_s(buf);
1534 fs_give((void **)&ps->exceptions);
1537 mprint(2, (db, DSIZE-(db-(*debug_out)), "\n Global config: %.100s\n",
1538 (ps->pconf && ps->pconf->name) ? ps->pconf->name : "<none>"));
1539 mprint(2, (db, DSIZE-(db-(*debug_out)), " Personal config: %.100s\n",
1540 (ps->prc && ps->prc->name) ? ps->prc->name : "<none>"));
1541 mprint(2, (db, DSIZE-(db-(*debug_out)), " Exceptions config: %.100s\n",
1542 (ps->post_prc && ps->post_prc->name) ? ps->post_prc->name
1543 : "<none>"));
1544 #if !defined(DOS) && !defined(OS2)
1545 if(SYSTEM_PINERC_FIXED){
1546 mprint(2, (db, DSIZE-(db-(*debug_out)), " Fixed config: %.100s\n", SYSTEM_PINERC_FIXED));
1548 #endif
1550 mprint(2, (db, DSIZE-(db-(*debug_out)), "\n"));
1554 /*----------------------------------------------------------------------
1555 Initialize the variables
1557 Args: ps -- The usual pine structure
1559 Result:
1561 This reads the system pine configuration file and the user's pine
1562 configuration file ".pinerc" and places the results in the variables
1563 structure. It sorts out what was read and sets a few other variables
1564 based on the contents.
1565 ----*/
1566 void
1567 init_vars(struct pine *ps, void (*cmds_f) (struct pine *, char **))
1569 char buf[MAXPATH+1], *p, *q, **s;
1570 register struct variable *vars = ps->vars;
1571 int obs_header_in_reply = 0, /* the obs_ variables are to */
1572 obs_old_style_reply = 0, /* support backwards compatibility */
1573 obs_save_by_sender, i, def_sort_rev;
1574 long rvl;
1575 PINERC_S *fixedprc = NULL;
1576 FeatureLevel obs_feature_level;
1577 char *fromcharset = NULL;
1578 char *err = NULL;
1580 dprint((5, "init_vars:\n"));
1582 /*--- The defaults here are defined in os-xxx.h so they can vary
1583 per machine ---*/
1585 GLO_PRINTER = cpystr(DF_DEFAULT_PRINTER);
1586 GLO_ELM_STYLE_SAVE = cpystr(DF_ELM_STYLE_SAVE);
1587 GLO_SAVE_BY_SENDER = cpystr(DF_SAVE_BY_SENDER);
1588 GLO_HEADER_IN_REPLY = cpystr(DF_HEADER_IN_REPLY);
1589 GLO_INBOX_PATH = cpystr("inbox");
1590 GLO_DEFAULT_FCC = cpystr(DF_DEFAULT_FCC);
1591 GLO_DEFAULT_SAVE_FOLDER = cpystr(DEFAULT_SAVE);
1592 GLO_POSTPONED_FOLDER = cpystr(POSTPONED_MSGS);
1593 GLO_TRASH_FOLDER = cpystr(TRASH_FOLDER);
1594 GLO_USE_ONLY_DOMAIN_NAME = cpystr(DF_USE_ONLY_DOMAIN_NAME);
1595 GLO_FEATURE_LEVEL = cpystr("sappling");
1596 GLO_OLD_STYLE_REPLY = cpystr(DF_OLD_STYLE_REPLY);
1597 GLO_SORT_KEY = cpystr(DF_SORT_KEY);
1598 GLO_SAVED_MSG_NAME_RULE = cpystr(DF_SAVED_MSG_NAME_RULE);
1599 GLO_FCC_RULE = cpystr(DF_FCC_RULE);
1600 GLO_AB_SORT_RULE = cpystr(DF_AB_SORT_RULE);
1601 GLO_FLD_SORT_RULE = cpystr(DF_FLD_SORT_RULE);
1602 GLO_SIGNATURE_FILE = cpystr(DF_SIGNATURE_FILE);
1603 GLO_MAIL_DIRECTORY = cpystr(DF_MAIL_DIRECTORY);
1604 GLO_REMOTE_ABOOK_HISTORY = cpystr(DF_REMOTE_ABOOK_HISTORY);
1605 GLO_REMOTE_ABOOK_VALIDITY = cpystr(DF_REMOTE_ABOOK_VALIDITY);
1606 GLO_GOTO_DEFAULT_RULE = cpystr(DF_GOTO_DEFAULT_RULE);
1607 GLO_INCOMING_STARTUP = cpystr(DF_INCOMING_STARTUP);
1608 GLO_PRUNING_RULE = cpystr(DF_PRUNING_RULE);
1609 GLO_REOPEN_RULE = cpystr(DF_REOPEN_RULE);
1610 GLO_THREAD_DISP_STYLE = cpystr(DF_THREAD_DISP_STYLE);
1611 GLO_THREAD_INDEX_STYLE = cpystr(DF_THREAD_INDEX_STYLE);
1612 GLO_THREAD_MORE_CHAR = cpystr(DF_THREAD_MORE_CHAR);
1613 GLO_THREAD_EXP_CHAR = cpystr(DF_THREAD_EXP_CHAR);
1614 GLO_THREAD_LASTREPLY_CHAR = cpystr(DF_THREAD_LASTREPLY_CHAR);
1615 GLO_BUGS_FULLNAME = cpystr("Sorry No Address");
1616 GLO_BUGS_ADDRESS = cpystr("nobody");
1617 GLO_SUGGEST_FULLNAME = cpystr("Sorry No Address");
1618 GLO_SUGGEST_ADDRESS = cpystr("nobody");
1619 GLO_LOCAL_FULLNAME = cpystr(DF_LOCAL_FULLNAME);
1620 GLO_LOCAL_ADDRESS = cpystr(DF_LOCAL_ADDRESS);
1621 GLO_OVERLAP = cpystr(DF_OVERLAP);
1622 GLO_SLEEP = cpystr("60");
1623 GLO_MAXREMSTREAM = cpystr(DF_MAXREMSTREAM);
1624 GLO_MARGIN = cpystr(DF_MARGIN);
1625 GLO_FILLCOL = cpystr(DF_FILLCOL);
1626 GLO_DEADLETS = cpystr(DF_DEADLETS);
1627 GLO_NMW_WIDTH = cpystr(DF_NMW_WIDTH);
1628 GLO_REPLY_STRING = cpystr("> ");
1629 GLO_REPLY_INTRO = cpystr(DEFAULT_REPLY_INTRO);
1630 GLO_EMPTY_HDR_MSG = cpystr("undisclosed-recipients");
1631 GLO_STATUS_MSG_DELAY = cpystr("0");
1632 GLO_ACTIVE_MSG_INTERVAL = cpystr("12");
1633 GLO_USERINPUTTIMEO = cpystr("0");
1634 GLO_INCCHECKTIMEO = cpystr("5");
1635 GLO_INCCHECKINTERVAL = cpystr("180");
1636 GLO_INC2NDCHECKINTERVAL = cpystr("180");
1637 GLO_MAILCHECK = cpystr(DF_MAILCHECK);
1638 GLO_MAILCHECKNONCURR = cpystr("0");
1639 GLO_MAILDROPCHECK = cpystr(DF_MAILDROPCHECK);
1640 GLO_NNTPRANGE = cpystr("0");
1641 GLO_KBLOCK_PASSWD_COUNT = cpystr(DF_KBLOCK_PASSWD_COUNT);
1642 GLO_INDEX_COLOR_STYLE = cpystr("flip-colors");
1643 GLO_TITLEBAR_COLOR_STYLE = cpystr("default");
1644 GLO_POST_CHAR_SET = cpystr("UTF-8");
1645 #ifdef DF_FOLDER_EXTENSION
1646 GLO_FOLDER_EXTENSION = cpystr(DF_FOLDER_EXTENSION);
1647 #endif
1648 #ifdef DF_SMTP_SERVER
1649 GLO_SMTP_SERVER = parse_list(DF_SMTP_SERVER, 1,
1650 PL_REMSURRQUOT, NULL);
1651 #endif
1653 #ifdef DF_SSHPATH
1654 GLO_SSHPATH = cpystr(DF_SSHPATH);
1655 #endif
1656 #ifdef DF_SSHCMD
1657 GLO_SSHCMD = cpystr(DF_SSHCMD);
1658 #endif
1660 #ifndef _WINDOWS
1661 GLO_COLOR_STYLE = cpystr("no-color");
1662 GLO_NORM_FORE_COLOR = cpystr(DEFAULT_NORM_FORE_RGB);
1663 GLO_NORM_BACK_COLOR = cpystr(DEFAULT_NORM_BACK_RGB);
1664 #endif
1665 GLO_TITLE_FORE_COLOR = cpystr(DEFAULT_TITLE_FORE_RGB);
1666 GLO_TITLE_BACK_COLOR = cpystr(DEFAULT_TITLE_BACK_RGB);
1667 GLO_TITLECLOSED_FORE_COLOR = cpystr(DEFAULT_TITLECLOSED_FORE_RGB);
1668 GLO_TITLECLOSED_BACK_COLOR = cpystr(DEFAULT_TITLECLOSED_BACK_RGB);
1669 GLO_FOLDER_FORE_COLOR = cpystr(DEFAULT_NORM_FORE_RGB);
1670 GLO_DIRECTORY_FORE_COLOR = cpystr(DEFAULT_NORM_FORE_RGB);
1671 GLO_FOLDER_LIST_FORE_COLOR = cpystr(DEFAULT_NORM_FORE_RGB);
1672 GLO_METAMSG_FORE_COLOR = cpystr(DEFAULT_METAMSG_FORE_RGB);
1673 GLO_METAMSG_BACK_COLOR = cpystr(DEFAULT_METAMSG_BACK_RGB);
1674 GLO_QUOTE1_FORE_COLOR = cpystr(DEFAULT_QUOTE1_FORE_RGB);
1675 GLO_QUOTE1_BACK_COLOR = cpystr(DEFAULT_QUOTE1_BACK_RGB);
1676 GLO_QUOTE2_FORE_COLOR = cpystr(DEFAULT_QUOTE2_FORE_RGB);
1677 GLO_QUOTE2_BACK_COLOR = cpystr(DEFAULT_QUOTE2_BACK_RGB);
1678 GLO_QUOTE3_FORE_COLOR = cpystr(DEFAULT_QUOTE3_FORE_RGB);
1679 GLO_QUOTE3_BACK_COLOR = cpystr(DEFAULT_QUOTE3_BACK_RGB);
1680 GLO_SIGNATURE_FORE_COLOR = cpystr(DEFAULT_SIGNATURE_FORE_RGB);
1681 GLO_SIGNATURE_BACK_COLOR = cpystr(DEFAULT_SIGNATURE_BACK_RGB);
1682 GLO_IND_PLUS_FORE_COLOR = cpystr(DEFAULT_IND_PLUS_FORE_RGB);
1683 GLO_IND_PLUS_BACK_COLOR = cpystr(DEFAULT_IND_PLUS_BACK_RGB);
1684 GLO_IND_IMP_FORE_COLOR = cpystr(DEFAULT_IND_IMP_FORE_RGB);
1685 GLO_IND_IMP_BACK_COLOR = cpystr(DEFAULT_IND_IMP_BACK_RGB);
1686 GLO_IND_ANS_FORE_COLOR = cpystr(DEFAULT_IND_ANS_FORE_RGB);
1687 GLO_IND_ANS_BACK_COLOR = cpystr(DEFAULT_IND_ANS_BACK_RGB);
1688 GLO_IND_NEW_FORE_COLOR = cpystr(DEFAULT_IND_NEW_FORE_RGB);
1689 GLO_IND_NEW_BACK_COLOR = cpystr(DEFAULT_IND_NEW_BACK_RGB);
1690 GLO_IND_OP_FORE_COLOR = cpystr(DEFAULT_IND_OP_FORE_RGB);
1691 GLO_IND_OP_BACK_COLOR = cpystr(DEFAULT_IND_OP_BACK_RGB);
1692 GLO_VIEW_MARGIN_LEFT = cpystr("0");
1693 GLO_VIEW_MARGIN_RIGHT = cpystr(DF_VIEW_MARGIN_RIGHT);
1694 GLO_QUOTE_SUPPRESSION = cpystr(DF_QUOTE_SUPPRESSION);
1695 GLO_KW_BRACES = cpystr("\"{\" \"} \"");
1696 GLO_OPENING_SEP = cpystr(" - ");
1697 GLO_WP_INDEXHEIGHT = cpystr("24");
1698 GLO_WP_AGGSTATE = cpystr("1");
1699 GLO_WP_STATE = cpystr("");
1700 #ifdef DF_VAR_SPELLER
1701 GLO_SPELLER = cpystr(DF_VAR_SPELLER);
1702 #endif
1703 #ifdef SMIME
1704 GLO_PUBLICCERT_DIR = cpystr(DF_PUBLICCERT_DIR);
1705 GLO_PRIVATEKEY_DIR = cpystr(DF_PRIVATEKEY_DIR);
1706 GLO_CACERT_DIR = cpystr(DF_CACERT_DIR);
1707 #endif /* SMIME */
1710 * Default first value for addrbook list if none set.
1711 * We also want to be sure to set global_val to the default
1712 * if is_fixed, so that address-book= will cause the default to happen.
1714 if(!GLO_ADDRESSBOOK && !FIX_ADDRESSBOOK)
1715 GLO_ADDRESSBOOK = parse_list(DF_ADDRESSBOOK, 1, 0, NULL);
1718 * Default first value if none set.
1720 if(!GLO_STANDARD_PRINTER && !FIX_STANDARD_PRINTER)
1721 GLO_STANDARD_PRINTER = parse_list(DF_STANDARD_PRINTER, 1, 0, NULL);
1724 * Defining this default sshpath should cause ssh to be preferred over rsh
1725 * when attempting imapd preauth calls.
1727 #ifdef DF_SSHPATH
1728 if(DF_SSHPATH
1729 && is_absolute_path(DF_SSHPATH)
1730 && can_access(DF_SSHPATH, EXECUTE_ACCESS) == 0){
1731 mail_parameters(NULL, SET_SSHPATH, (void *) DF_SSHPATH);
1733 #endif
1735 * It isn't usually necessary to define this.
1737 #ifdef DF_SSHCMD
1738 if(DF_SSHCMD){
1739 mail_parameters(NULL, SET_SSHCOMMAND, (void *) DF_SSHCMD);
1741 #endif
1743 #if !defined(DOS) && !defined(OS2)
1745 * This is here instead of in init_pinerc so that we can get by without
1746 * having a global fixedprc, since we don't need it anymore after this.
1748 fixedprc = new_pinerc_s(SYSTEM_PINERC_FIXED);
1749 #endif
1751 if(ps->pconf){
1752 read_pinerc(ps->pconf, vars, ParseGlobal);
1753 if(ps->pconf->type != Loc)
1754 rd_close_remote(ps->pconf->rd);
1757 if(ps->prc){
1758 read_pinerc(ps->prc, vars, ParsePers);
1759 if(ps->prc->type != Loc)
1760 rd_close_remote(ps->prc->rd);
1763 if(ps->post_prc){
1764 read_pinerc(ps->post_prc, vars, ParsePersPost);
1765 if(ps->post_prc->type != Loc)
1766 rd_close_remote(ps->post_prc->rd);
1769 if(fixedprc){
1770 read_pinerc(fixedprc, vars, ParseFixed);
1771 free_pinerc_s(&fixedprc);
1774 ps->ew_for_except_vars = ps->post_prc ? Post : Main;
1776 if(ps->exit_if_no_pinerc && ps->first_time_user){
1778 /* TRANSLATORS: -bail is a literal option name, don't change it. */
1779 exceptional_exit(_("Exiting because -bail option is set and config file doesn't exist."), -1);
1783 * Convert everything having to do with the config to UTF-8
1784 * in order to avoid having to worry about it all over the
1785 * place.
1786 * Set the character-set first so that we may use that in
1787 * the conversion process.
1789 set_collation(0, 1);
1791 #ifndef _WINDOWS
1792 #if (HAVE_LANGINFO_H && defined(CODESET))
1794 if(output_charset_is_supported(nl_langinfo_codeset_wrapper()))
1795 ps->GLO_CHAR_SET = cpystr(nl_langinfo_codeset_wrapper());
1796 else{
1797 ps->GLO_CHAR_SET = cpystr("UTF-8");
1798 dprint((1,"nl_langinfo(CODESET) returns unrecognized value=\"%s\", using UTF-8 as default\n", (p=nl_langinfo(CODESET)) ? p : ""));
1800 #else
1801 ps->GLO_CHAR_SET = cpystr("UTF-8");
1802 #endif
1804 set_current_val(&vars[V_CHAR_SET], TRUE, TRUE);
1805 set_current_val(&vars[V_OLD_CHAR_SET], TRUE, TRUE);
1806 set_current_val(&vars[V_KEY_CHAR_SET], TRUE, TRUE);
1807 #endif /* ! _WINDOWS */
1809 set_current_val(&vars[V_POST_CHAR_SET], TRUE, TRUE);
1812 * Also set up the feature list because we need the
1813 * Use-System-Translation feature to set up the charmaps.
1816 /* way obsolete, backwards compatibility */
1817 set_current_val(&vars[V_FEATURE_LEVEL], TRUE, TRUE);
1818 if(strucmp(VAR_FEATURE_LEVEL, "seedling") == 0)
1819 obs_feature_level = Seedling;
1820 else if(strucmp(VAR_FEATURE_LEVEL, "old-growth") == 0)
1821 obs_feature_level = Seasoned;
1822 else
1823 obs_feature_level = Sapling;
1825 /* obsolete, backwards compatibility */
1826 set_current_val(&vars[V_OLD_STYLE_REPLY], TRUE, TRUE);
1827 obs_old_style_reply = !strucmp(VAR_OLD_STYLE_REPLY, "yes");
1829 set_feature_list_current_val(&vars[V_FEATURE_LIST]);
1830 process_feature_list(ps, VAR_FEATURE_LIST,
1831 (obs_feature_level == Seasoned) ? 1 : 0,
1832 obs_header_in_reply, obs_old_style_reply);
1836 * Redo set_collation call with correct value for collation,
1837 * but we're hardwiring ctype on now. That's because nl_langinfo()
1838 * call needs it and system-dependent wcwidth and wcrtomb functions
1839 * need it.
1841 set_collation(F_OFF(F_DISABLE_SETLOCALE_COLLATE, ps_global), 1);
1844 * Set up to send the correct sequence of bytes to the display terminal.
1847 if(reset_character_set_stuff(&err) == -1)
1848 alpine_panic(err ? err : "trouble with character set setup");
1849 else if(err){
1850 init_error(ps, SM_ORDER | SM_DING, 3, 5, err);
1851 fs_give((void **) &err);
1855 * Now we use the configvars from above to convert the rest
1856 * to UTF-8. That should be ok because the ones above should
1857 * be ASCII.
1859 if(ps->keyboard_charmap && strucmp(ps->keyboard_charmap, "UTF-8")
1860 && strucmp(ps->keyboard_charmap, "US-ASCII"))
1861 fromcharset = ps->keyboard_charmap;
1862 else if(ps->display_charmap && strucmp(ps->display_charmap, "UTF-8")
1863 && strucmp(ps->display_charmap, "US-ASCII"))
1864 fromcharset = ps->display_charmap;
1865 #ifndef _WINDOWS
1866 else if(VAR_OLD_CHAR_SET && strucmp(VAR_OLD_CHAR_SET, "UTF-8")
1867 && strucmp(VAR_OLD_CHAR_SET, "US-ASCII"))
1868 fromcharset = VAR_OLD_CHAR_SET;
1869 #endif /* ! _WINDOWS */
1871 convert_configvars_to_utf8(vars, fromcharset);
1874 * If we already set this while reading the remote pinerc, don't
1875 * change it.
1877 if(!VAR_REMOTE_ABOOK_METADATA || !VAR_REMOTE_ABOOK_METADATA[0])
1878 set_current_val(&vars[V_REMOTE_ABOOK_METADATA], TRUE, TRUE);
1881 * mail-directory variable is obsolete, put its value in
1882 * default folder-collection list
1884 set_current_val(&vars[V_MAIL_DIRECTORY], TRUE, TRUE);
1885 if(!GLO_FOLDER_SPEC){
1886 build_path(tmp_20k_buf, VAR_MAIL_DIRECTORY, "[]", SIZEOF_20KBUF);
1887 GLO_FOLDER_SPEC = parse_list(tmp_20k_buf, 1, 0, NULL);
1890 set_current_val(&vars[V_FOLDER_SPEC], TRUE, TRUE);
1892 set_current_val(&vars[V_NNTP_SERVER], TRUE, TRUE);
1893 for(i = 0; VAR_NNTP_SERVER && VAR_NNTP_SERVER[i]; i++)
1894 removing_quotes(VAR_NNTP_SERVER[i]);
1896 set_news_spec_current_val(TRUE, TRUE);
1898 set_current_val(&vars[V_INBOX_PATH], TRUE, TRUE);
1900 set_current_val(&vars[V_USER_DOMAIN], TRUE, TRUE);
1901 if(VAR_USER_DOMAIN
1902 && VAR_USER_DOMAIN[0]
1903 && (p = strrindex(VAR_USER_DOMAIN, '@'))){
1904 if(*(++p)){
1905 char *q;
1907 snprintf(tmp_20k_buf, SIZEOF_20KBUF,
1908 "User-domain (%s) cannot contain \"@\", using \"%s\"",
1909 VAR_USER_DOMAIN, p);
1910 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
1911 q = VAR_USER_DOMAIN;
1912 while((*q++ = *p++) != '\0')
1913 ;/* do nothing */
1915 else{
1916 snprintf(tmp_20k_buf, SIZEOF_20KBUF,
1917 "User-domain (%s) cannot contain \"@\", deleting",
1918 VAR_USER_DOMAIN);
1919 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
1920 if(ps->vars[V_USER_DOMAIN].post_user_val.p){
1921 fs_give((void **)&ps->vars[V_USER_DOMAIN].post_user_val.p);
1922 set_current_val(&vars[V_USER_DOMAIN], TRUE, TRUE);
1925 if(VAR_USER_DOMAIN
1926 && VAR_USER_DOMAIN[0]
1927 && (p = strrindex(VAR_USER_DOMAIN, '@'))){
1928 if(ps->vars[V_USER_DOMAIN].main_user_val.p){
1929 fs_give((void **)&ps->vars[V_USER_DOMAIN].main_user_val.p);
1930 set_current_val(&vars[V_USER_DOMAIN], TRUE, TRUE);
1936 set_current_val(&vars[V_USE_ONLY_DOMAIN_NAME], TRUE, TRUE);
1937 set_current_val(&vars[V_REPLY_STRING], TRUE, TRUE);
1938 set_current_val(&vars[V_WORDSEPS], TRUE, TRUE);
1939 set_current_val(&vars[V_QUOTE_REPLACE_STRING], TRUE, TRUE);
1940 set_current_val(&vars[V_REPLY_INTRO], TRUE, TRUE);
1941 set_current_val(&vars[V_EMPTY_HDR_MSG], TRUE, TRUE);
1943 #ifdef ENABLE_LDAP
1944 set_current_val(&vars[V_LDAP_SERVERS], TRUE, TRUE);
1945 #endif /* ENABLE_LDAP */
1947 /* obsolete, backwards compatibility */
1948 set_current_val(&vars[V_HEADER_IN_REPLY], TRUE, TRUE);
1949 obs_header_in_reply=!strucmp(VAR_HEADER_IN_REPLY, "yes");
1951 set_current_val(&vars[V_PERSONAL_PRINT_COMMAND], TRUE, TRUE);
1952 set_current_val(&vars[V_STANDARD_PRINTER], TRUE, TRUE);
1953 set_current_val(&vars[V_PRINTER], TRUE, TRUE);
1954 if(vars[V_PERSONAL_PRINT_COMMAND].is_fixed && !vars[V_PRINTER].is_fixed)
1955 printer_value_check_and_adjust();
1957 set_current_val(&vars[V_LAST_TIME_PRUNE_QUESTION], TRUE, TRUE);
1958 if(VAR_LAST_TIME_PRUNE_QUESTION != NULL){
1959 /* The month value in the file runs from 1-12, the variable here
1960 runs from 0-11; the value in the file used to be 0-11, but we're
1961 fixing it in January */
1962 ps->last_expire_year = atoi(VAR_LAST_TIME_PRUNE_QUESTION);
1963 ps->last_expire_month =
1964 atoi(strindex(VAR_LAST_TIME_PRUNE_QUESTION, '.') + 1);
1965 if(ps->last_expire_month == 0){
1966 /* Fix for 0 because of old bug */
1967 snprintf(buf, sizeof(buf), "%d.%d", ps_global->last_expire_year,
1968 ps_global->last_expire_month + 1);
1969 set_variable(V_LAST_TIME_PRUNE_QUESTION, buf, 1, 1, Main);
1970 }else{
1971 ps->last_expire_month--;
1973 }else{
1974 ps->last_expire_year = -1;
1975 ps->last_expire_month = -1;
1978 set_current_val(&vars[V_BUGS_FULLNAME], TRUE, TRUE);
1979 set_current_val(&vars[V_BUGS_ADDRESS], TRUE, TRUE);
1980 set_current_val(&vars[V_SUGGEST_FULLNAME], TRUE, TRUE);
1981 set_current_val(&vars[V_SUGGEST_ADDRESS], TRUE, TRUE);
1982 set_current_val(&vars[V_LOCAL_FULLNAME], TRUE, TRUE);
1983 set_current_val(&vars[V_LOCAL_ADDRESS], TRUE, TRUE);
1984 set_current_val(&vars[V_BUGS_EXTRAS], TRUE, TRUE);
1985 set_current_val(&vars[V_KBLOCK_PASSWD_COUNT], TRUE, TRUE);
1986 set_current_val(&vars[V_DEFAULT_FCC], TRUE, TRUE);
1987 set_current_val(&vars[V_POSTPONED_FOLDER], TRUE, TRUE);
1988 set_current_val(&vars[V_TRASH_FOLDER], TRUE, TRUE);
1989 set_current_val(&vars[V_READ_MESSAGE_FOLDER], TRUE, TRUE);
1990 set_current_val(&vars[V_FORM_FOLDER], TRUE, TRUE);
1991 set_current_val(&vars[V_EDITOR], TRUE, TRUE);
1992 set_current_val(&vars[V_SPELLER], TRUE, TRUE);
1993 set_current_val(&vars[V_IMAGE_VIEWER], TRUE, TRUE);
1994 set_current_val(&vars[V_BROWSER], TRUE, TRUE);
1995 set_current_val(&vars[V_SMTP_SERVER], TRUE, TRUE);
1996 set_current_val(&vars[V_COMP_HDRS], TRUE, TRUE);
1997 set_current_val(&vars[V_CUSTOM_HDRS], TRUE, TRUE);
1998 set_current_val(&vars[V_SENDMAIL_PATH], TRUE, TRUE);
1999 set_current_val(&vars[V_DISPLAY_FILTERS], TRUE, TRUE);
2000 set_current_val(&vars[V_SEND_FILTER], TRUE, TRUE);
2001 set_current_val(&vars[V_ALT_ADDRS], TRUE, TRUE);
2002 set_current_val(&vars[V_ABOOK_FORMATS], TRUE, TRUE);
2003 set_current_val(&vars[V_KW_BRACES], TRUE, TRUE);
2004 set_current_val(&vars[V_OPENING_SEP], TRUE, TRUE);
2005 set_current_val(&vars[V_UNK_CHAR_SET], TRUE, TRUE);
2006 #ifdef SMIME
2007 set_current_val(&vars[V_PUBLICCERT_DIR], TRUE, TRUE);
2008 set_current_val(&vars[V_PUBLICCERT_CONTAINER], TRUE, TRUE);
2009 set_current_val(&vars[V_PRIVATEKEY_DIR], TRUE, TRUE);
2010 set_current_val(&vars[V_PRIVATEKEY_CONTAINER], TRUE, TRUE);
2011 set_current_val(&vars[V_CACERT_DIR], TRUE, TRUE);
2012 set_current_val(&vars[V_CACERT_CONTAINER], TRUE, TRUE);
2013 #endif /* SMIME */
2015 set_current_val(&vars[V_KEYWORDS], TRUE, TRUE);
2016 ps_global->keywords = init_keyword_list(VAR_KEYWORDS);
2018 set_current_val(&vars[V_OPER_DIR], TRUE, TRUE);
2019 if(VAR_OPER_DIR && !VAR_OPER_DIR[0]){
2020 init_error(ps, SM_ORDER | SM_DING, 3, 5,
2021 "Setting operating-dir to the empty string is not allowed. Will be ignored.");
2022 fs_give((void **)&VAR_OPER_DIR);
2023 if(FIX_OPER_DIR)
2024 fs_give((void **)&FIX_OPER_DIR);
2025 if(GLO_OPER_DIR)
2026 fs_give((void **)&GLO_OPER_DIR);
2027 if(COM_OPER_DIR)
2028 fs_give((void **)&COM_OPER_DIR);
2029 if(ps_global->vars[V_OPER_DIR].post_user_val.p)
2030 fs_give((void **)&ps_global->vars[V_OPER_DIR].post_user_val.p);
2031 if(ps_global->vars[V_OPER_DIR].main_user_val.p)
2032 fs_give((void **)&ps_global->vars[V_OPER_DIR].main_user_val.p);
2035 set_current_val(&vars[V_PERSONAL_PRINT_CATEGORY], TRUE, TRUE);
2036 ps->printer_category = -1;
2037 if(VAR_PERSONAL_PRINT_CATEGORY != NULL)
2038 ps->printer_category = atoi(VAR_PERSONAL_PRINT_CATEGORY);
2040 if(ps->printer_category < 1 || ps->printer_category > 3){
2041 char **tt;
2042 char aname[100], wname[100];
2044 strncpy(aname, ANSI_PRINTER, sizeof(aname));
2045 aname[sizeof(aname)-1] = '\0';
2046 strncat(aname, "-no-formfeed", sizeof(aname)-strlen(aname)-1);
2047 strncpy(wname, WYSE_PRINTER, sizeof(wname));
2048 wname[sizeof(wname)-1] = '\0';
2049 strncat(wname, "-no-formfeed", sizeof(wname)-strlen(wname)-1);
2050 if(strucmp(VAR_PRINTER, ANSI_PRINTER) == 0
2051 || strucmp(VAR_PRINTER, aname) == 0
2052 || strucmp(VAR_PRINTER, WYSE_PRINTER) == 0
2053 || strucmp(VAR_PRINTER, wname) == 0)
2054 ps->printer_category = 1;
2055 else if(VAR_STANDARD_PRINTER && VAR_STANDARD_PRINTER[0]){
2056 for(tt = VAR_STANDARD_PRINTER; *tt; tt++)
2057 if(strucmp(VAR_PRINTER, *tt) == 0)
2058 break;
2060 if(*tt)
2061 ps->printer_category = 2;
2064 /* didn't find it yet */
2065 if(ps->printer_category < 1 || ps->printer_category > 3){
2066 if(VAR_PERSONAL_PRINT_COMMAND && VAR_PERSONAL_PRINT_COMMAND[0]){
2067 for(tt = VAR_PERSONAL_PRINT_COMMAND; *tt; tt++)
2068 if(strucmp(VAR_PRINTER, *tt) == 0)
2069 break;
2071 if(*tt)
2072 ps->printer_category = 3;
2077 set_current_val(&vars[V_SLEEP], TRUE, TRUE);
2078 ps->sleep = i = 60;
2079 if(SVAR_SLEEP(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2080 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2081 else
2082 ps->sleep = i;
2084 set_current_val(&vars[V_OVERLAP], TRUE, TRUE);
2085 ps->viewer_overlap = i = atoi(DF_OVERLAP);
2086 if(SVAR_OVERLAP(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2087 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2088 else
2089 ps->viewer_overlap = i;
2091 set_current_val(&vars[V_MARGIN], TRUE, TRUE);
2092 ps->scroll_margin = i = atoi(DF_MARGIN);
2093 if(SVAR_MARGIN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2094 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2095 else
2096 ps->scroll_margin = i;
2098 set_current_val(&vars[V_FILLCOL], TRUE, TRUE);
2099 ps->composer_fillcol = i = atoi(DF_FILLCOL);
2100 if(SVAR_FILLCOL(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2101 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2102 else
2103 ps->composer_fillcol = i;
2105 set_current_val(&vars[V_QUOTE_SUPPRESSION], TRUE, TRUE);
2106 ps->quote_suppression_threshold = i = atoi(DF_QUOTE_SUPPRESSION);
2107 if(SVAR_QUOTE_SUPPRESSION(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2108 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2109 else{
2110 if(i > 0 && i < Q_SUPP_LIMIT){
2111 snprintf(tmp_20k_buf, SIZEOF_20KBUF,
2112 "Ignoring Quote-Suppression-Threshold value of %.50s, see help",
2113 VAR_QUOTE_SUPPRESSION);
2114 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2116 else{
2117 if(i < 0 && i != Q_DEL_ALL)
2118 ps->quote_suppression_threshold = -i;
2119 else
2120 ps->quote_suppression_threshold = i;
2124 set_current_val(&vars[V_DEADLETS], TRUE, TRUE);
2125 ps->deadlets = i = atoi(DF_DEADLETS);
2126 if(SVAR_DEADLETS(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2127 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2128 else
2129 ps->deadlets = i;
2131 set_current_val(&vars[V_STATUS_MSG_DELAY], TRUE, TRUE);
2132 ps->status_msg_delay = i = 0;
2133 if(SVAR_MSGDLAY(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2134 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2135 else
2136 ps->status_msg_delay = i;
2138 set_current_val(&vars[V_ACTIVE_MSG_INTERVAL], TRUE, TRUE);
2139 ps->active_status_interval = i = 8;
2140 if(SVAR_ACTIVEINTERVAL(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2141 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2142 else
2143 ps->active_status_interval = i;
2145 set_current_val(&vars[V_REMOTE_ABOOK_HISTORY], TRUE, TRUE);
2146 ps->remote_abook_history = i = atoi(DF_REMOTE_ABOOK_HISTORY);
2147 if(SVAR_AB_HIST(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2148 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2149 else
2150 ps->remote_abook_history = i;
2152 set_current_val(&vars[V_REMOTE_ABOOK_VALIDITY], TRUE, TRUE);
2153 ps->remote_abook_validity = i = atoi(DF_REMOTE_ABOOK_VALIDITY);
2154 if(SVAR_AB_VALID(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2155 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2156 else
2157 ps->remote_abook_validity = i;
2159 set_current_val(&vars[V_USERINPUTTIMEO], TRUE, TRUE);
2160 ps->hours_to_timeout = i = 0;
2161 if(SVAR_USER_INPUT(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2162 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2163 else
2164 ps->hours_to_timeout = i;
2166 /* timeo is a regular extern int because it is referenced in pico */
2167 set_current_val(&vars[V_MAILCHECK], TRUE, TRUE);
2168 set_input_timeout(i = 15);
2169 if(SVAR_MAILCHK(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2170 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2171 else
2172 set_input_timeout(i);
2174 set_current_val(&vars[V_MAILCHECKNONCURR], TRUE, TRUE);
2175 ps->check_interval_for_noncurr = i = 0;
2176 if(SVAR_MAILCHKNONCURR(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2177 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2178 else
2179 ps->check_interval_for_noncurr = i;
2181 #ifdef DEBUGJOURNAL
2182 ps->debugmem = 1;
2183 #else
2184 ps->debugmem = 0;
2185 #endif
2187 i = 30;
2188 set_current_val(&vars[V_TCPOPENTIMEO], TRUE, TRUE);
2189 /* this is just for the error, we don't save the result */
2190 if(VAR_TCPOPENTIMEO && SVAR_TCP_OPEN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2191 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2193 i = 15;
2194 set_current_val(&vars[V_TCPREADWARNTIMEO], TRUE, TRUE);
2195 /* this is just for the error, we don't save the result */
2196 if(VAR_TCPREADWARNTIMEO && SVAR_TCP_READWARN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2197 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2199 i = 0;
2200 set_current_val(&vars[V_TCPWRITEWARNTIMEO], TRUE, TRUE);
2201 /* this is just for the error, we don't save the result */
2202 if(VAR_TCPWRITEWARNTIMEO && SVAR_TCP_WRITEWARN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2203 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2205 i = 15;
2206 set_current_val(&vars[V_RSHOPENTIMEO], TRUE, TRUE);
2207 /* this is just for the error, we don't save the result */
2208 if(VAR_RSHOPENTIMEO && SVAR_RSH_OPEN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2209 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2211 i = 15;
2212 set_current_val(&vars[V_SSHOPENTIMEO], TRUE, TRUE);
2213 /* this is just for the error, we don't save the result */
2214 if(VAR_SSHOPENTIMEO && SVAR_SSH_OPEN(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2215 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2217 set_current_val(&vars[V_INCCHECKLIST], TRUE, TRUE);
2219 set_current_val(&vars[V_INCCHECKTIMEO], TRUE, TRUE);
2220 ps->inc_check_timeout = i = 5;
2221 if(SVAR_INC_CHECK_TIMEO(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2222 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2223 else
2224 ps->inc_check_timeout = i;
2226 set_current_val(&vars[V_INCCHECKINTERVAL], TRUE, TRUE);
2227 ps->inc_check_interval = i = 180;
2228 if(SVAR_INC_CHECK_INTERV(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2229 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2230 else
2231 ps->inc_check_interval = i;
2233 set_current_val(&vars[V_INC2NDCHECKINTERVAL], TRUE, TRUE);
2234 ps->inc_second_check_interval = i = 180;
2235 if(SVAR_INC_2NDCHECK_INTERV(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2236 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2237 else
2238 ps->inc_second_check_interval = i;
2240 rvl = 60L;
2241 set_current_val(&vars[V_MAILDROPCHECK], TRUE, TRUE);
2242 /* this is just for the error, we don't save the result */
2243 if(VAR_MAILDROPCHECK && SVAR_MAILDCHK(ps, rvl, tmp_20k_buf, SIZEOF_20KBUF))
2244 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2246 rvl = 0L;
2247 set_current_val(&vars[V_NNTPRANGE], TRUE, TRUE);
2248 /* this is just for the error, we don't save the result */
2249 if(VAR_NNTPRANGE && SVAR_NNTPRANGE(ps, rvl, tmp_20k_buf, SIZEOF_20KBUF))
2250 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2252 set_current_val(&vars[V_TCPQUERYTIMEO], TRUE, TRUE);
2253 ps->tcp_query_timeout = i = TO_BAIL_THRESHOLD;
2254 if(VAR_TCPQUERYTIMEO && SVAR_TCP_QUERY(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2255 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2256 else
2257 ps->tcp_query_timeout = i;
2259 set_current_val(&vars[V_NEWSRC_PATH], TRUE, TRUE);
2260 if(VAR_NEWSRC_PATH && VAR_NEWSRC_PATH[0])
2261 mail_parameters(NULL, SET_NEWSRC, (void *)VAR_NEWSRC_PATH);
2263 set_current_val(&vars[V_NEWS_ACTIVE_PATH], TRUE, TRUE);
2264 if(VAR_NEWS_ACTIVE_PATH)
2265 mail_parameters(NULL, SET_NEWSACTIVE,
2266 (void *)VAR_NEWS_ACTIVE_PATH);
2268 set_current_val(&vars[V_NEWS_SPOOL_DIR], TRUE, TRUE);
2269 if(VAR_NEWS_SPOOL_DIR)
2270 mail_parameters(NULL, SET_NEWSSPOOL,
2271 (void *)VAR_NEWS_SPOOL_DIR);
2273 /* guarantee a save default */
2274 set_current_val(&vars[V_DEFAULT_SAVE_FOLDER], TRUE, TRUE);
2275 if(!VAR_DEFAULT_SAVE_FOLDER || !VAR_DEFAULT_SAVE_FOLDER[0])
2276 set_variable(V_DEFAULT_SAVE_FOLDER,
2277 (GLO_DEFAULT_SAVE_FOLDER && GLO_DEFAULT_SAVE_FOLDER[0])
2278 ? GLO_DEFAULT_SAVE_FOLDER
2279 : DEFAULT_SAVE, 1, 0, Main);
2281 set_current_val(&vars[V_SIGNATURE_FILE], TRUE, TRUE);
2282 set_current_val(&vars[V_LITERAL_SIG], TRUE, TRUE);
2283 set_current_val(&vars[V_GLOB_ADDRBOOK], TRUE, TRUE);
2284 set_current_val(&vars[V_ADDRESSBOOK], TRUE, TRUE);
2285 set_current_val(&vars[V_FORCED_ABOOK_ENTRY], TRUE, TRUE);
2286 set_current_val(&vars[V_DISABLE_DRIVERS], TRUE, TRUE);
2287 set_current_val(&vars[V_DISABLE_AUTHS], TRUE, TRUE);
2289 set_current_val(&vars[V_VIEW_HEADERS], TRUE, TRUE);
2290 /* strip spaces and colons */
2291 if(ps->VAR_VIEW_HEADERS){
2292 for(s = ps->VAR_VIEW_HEADERS; (q = *s) != NULL; s++){
2293 if(q[0]){
2294 removing_leading_white_space(q);
2295 /* look for colon or space or end */
2296 for(p = q; *p && !isspace((unsigned char)*p) && *p != ':'; p++)
2297 ;/* do nothing */
2299 *p = '\0';
2300 if(strucmp(q, ALL_EXCEPT) == 0)
2301 ps->view_all_except = 1;
2306 set_current_val(&vars[V_VIEW_MARGIN_LEFT], TRUE, TRUE);
2307 set_current_val(&vars[V_VIEW_MARGIN_RIGHT], TRUE, TRUE);
2308 set_current_val(&vars[V_UPLOAD_CMD], TRUE, TRUE);
2309 set_current_val(&vars[V_UPLOAD_CMD_PREFIX], TRUE, TRUE);
2310 set_current_val(&vars[V_DOWNLOAD_CMD], TRUE, TRUE);
2311 set_current_val(&vars[V_DOWNLOAD_CMD_PREFIX], TRUE, TRUE);
2312 set_current_val(&vars[V_MAILCAP_PATH], TRUE, TRUE);
2313 set_current_val(&vars[V_MIMETYPE_PATH], TRUE, TRUE);
2314 #if !defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)
2315 set_current_val(&vars[V_FIFOPATH], TRUE, TRUE);
2316 #endif
2318 set_current_val(&vars[V_RSHPATH], TRUE, TRUE);
2319 if(VAR_RSHPATH
2320 && is_absolute_path(VAR_RSHPATH)
2321 && can_access(VAR_RSHPATH, EXECUTE_ACCESS) == 0){
2322 mail_parameters(NULL, SET_RSHPATH, (void *) VAR_RSHPATH);
2325 set_current_val(&vars[V_RSHCMD], TRUE, TRUE);
2326 if(VAR_RSHCMD){
2327 mail_parameters(NULL, SET_RSHCOMMAND, (void *) VAR_RSHCMD);
2330 set_current_val(&vars[V_SSHPATH], TRUE, TRUE);
2331 if(VAR_SSHPATH) {
2332 if(is_absolute_path(VAR_SSHPATH)
2333 && can_access(VAR_SSHPATH, EXECUTE_ACCESS) == 0){
2334 mail_parameters(NULL, SET_SSHPATH, (void *) VAR_SSHPATH);
2336 else {
2337 mail_parameters(NULL, SET_SSHPATH, (void *) NULL);
2341 set_current_val(&vars[V_SSHCMD], TRUE, TRUE);
2342 if(VAR_SSHCMD) {
2343 if(VAR_SSHCMD[0]) {
2344 mail_parameters(NULL, SET_SSHCOMMAND, (void *) VAR_SSHCMD);
2346 else {
2347 mail_parameters(NULL, SET_SSHCOMMAND, (void *) NULL);
2351 #if defined(DOS) || defined(OS2)
2353 set_current_val(&vars[V_FILE_DIR], TRUE, TRUE);
2355 #ifdef _WINDOWS
2356 set_current_val(&vars[V_FONT_NAME], TRUE, TRUE);
2357 set_current_val(&vars[V_FONT_SIZE], TRUE, TRUE);
2358 set_current_val(&vars[V_FONT_STYLE], TRUE, TRUE);
2359 set_current_val(&vars[V_FONT_CHAR_SET], TRUE, TRUE);
2360 set_current_val(&vars[V_CURSOR_STYLE], TRUE, TRUE);
2361 set_current_val(&vars[V_WINDOW_POSITION], TRUE, TRUE);
2363 if(F_OFF(F_STORE_WINPOS_IN_CONFIG, ps_global)){
2364 /* if win position is in the registry, use it */
2365 if(mswin_reg(MSWR_OP_GET, MSWR_PINE_POS, buf, sizeof(buf))){
2366 if(VAR_WINDOW_POSITION)
2367 fs_give((void **)&VAR_WINDOW_POSITION);
2369 VAR_WINDOW_POSITION = cpystr(buf);
2371 else if(VAR_WINDOW_POSITION
2372 && (ps->update_registry != UREG_NEVER_SET)){
2373 /* otherwise, put it there */
2374 mswin_reg(MSWR_OP_SET | ((ps->update_registry == UREG_ALWAYS_SET)
2375 ? MSWR_OP_FORCE : 0),
2376 MSWR_PINE_POS,
2377 VAR_WINDOW_POSITION, (size_t)NULL);
2381 mswin_setwindow (VAR_FONT_NAME, VAR_FONT_SIZE,
2382 VAR_FONT_STYLE, VAR_WINDOW_POSITION,
2383 VAR_CURSOR_STYLE, VAR_FONT_CHAR_SET);
2385 /* this is no longer used */
2386 if(VAR_WINDOW_POSITION)
2387 fs_give((void **)&VAR_WINDOW_POSITION);
2389 set_current_val(&vars[V_PRINT_FONT_NAME], TRUE, TRUE);
2390 set_current_val(&vars[V_PRINT_FONT_SIZE], TRUE, TRUE);
2391 set_current_val(&vars[V_PRINT_FONT_STYLE], TRUE, TRUE);
2392 set_current_val(&vars[V_PRINT_FONT_CHAR_SET], TRUE, TRUE);
2393 mswin_setprintfont (VAR_PRINT_FONT_NAME,
2394 VAR_PRINT_FONT_SIZE,
2395 VAR_PRINT_FONT_STYLE,
2396 VAR_PRINT_FONT_CHAR_SET);
2398 mswin_setgenhelptextcallback(pcpine_general_help);
2400 mswin_setclosetext ("Use the \"Q\" command to exit Alpine.");
2403 char foreColor[64], backColor[64];
2405 mswin_getwindow(NULL, 0, NULL, 0, NULL, 0, NULL, 0,
2406 foreColor, sizeof(foreColor), backColor, sizeof(backColor),
2407 NULL, 0, NULL, 0);
2408 if(!GLO_NORM_FORE_COLOR)
2409 GLO_NORM_FORE_COLOR = cpystr(foreColor);
2411 if(!GLO_NORM_BACK_COLOR)
2412 GLO_NORM_BACK_COLOR = cpystr(backColor);
2414 #endif /* _WINDOWS */
2415 #endif /* DOS */
2418 * We want the version number to start out as 1.0 for Alpine, but
2419 * we also want to use the same old config file that was used
2420 * with Pine. The Pine version numbers made it up to 4.64 and we
2421 * want Alpine's 1.0 to be larger than 4.64 so we keep a separate
2422 * internal version number which is the real version number
2423 * plus 4. That's what gets written in LAST_VERS_USED.
2425 strncpy(ps->vers_internal, ALPINE_VERSION, sizeof(ps->vers_internal));
2426 ps->vers_internal[sizeof(ps->vers_internal)-1] = '\0';
2427 if(isdigit(ps->vers_internal[0]) && ps->vers_internal[0] < '6')
2428 ps->vers_internal[0] = ps->vers_internal[0] + 4;
2430 set_current_val(&vars[V_LAST_VERS_USED], TRUE, TRUE);
2431 /* Check for special cases first */
2432 if(VAR_LAST_VERS_USED
2433 && (isdigit(ps->vers_internal[0])
2434 && ps->vers_internal[1] == '.'
2435 && isdigit((unsigned char)ps->vers_internal[2])
2436 && isdigit((unsigned char)ps->vers_internal[3])
2437 && isalpha((unsigned char)ps->vers_internal[4])
2438 && strncmp(VAR_LAST_VERS_USED, ps->vers_internal, 4) >= 0)){
2439 ps->show_new_version = 0;
2441 /* Otherwise just do lexicographic comparision... */
2442 else if(VAR_LAST_VERS_USED
2443 && strcmp(VAR_LAST_VERS_USED, ps->vers_internal) >= 0){
2444 ps->show_new_version = 0;
2446 else{
2447 #ifdef _WINDOWS
2449 * If this is the first time we've run a version > 4.40, and there
2450 * is evidence that the config file has not been used by unix pine,
2451 * then we convert color008 to colorlgr, color009 to colormgr, and
2452 * color010 to colordgr. If the config file is being used by
2453 * unix pine then color009 may really supposed to be red, etc.
2454 * Same if we've already run 4.41 or higher. We don't have to do
2455 * anything if we are new to alpine.
2457 ps->pre441 = (VAR_LAST_VERS_USED
2458 && strcmp(VAR_LAST_VERS_USED, "4.40") <= 0);
2459 #endif /* _WINDOWS */
2462 * Don't offer the new version message if we're told not to.
2464 set_current_val(&vars[V_NEW_VER_QUELL], TRUE, TRUE);
2465 ps->show_new_version = !(VAR_NEW_VER_QUELL
2466 && strcmp(ps->vers_internal,
2467 VAR_NEW_VER_QUELL) < 0);
2469 #ifdef _WINDOWS
2470 if(!ps_global->install_flag)
2471 #endif /* _WINDOWS */
2473 if(VAR_LAST_VERS_USED){
2474 strncpy(ps_global->pine_pre_vers, VAR_LAST_VERS_USED,
2475 sizeof(ps_global->pine_pre_vers));
2476 ps_global->pine_pre_vers[sizeof(ps_global->pine_pre_vers)-1] = '\0';
2479 set_variable(V_LAST_VERS_USED, ps->vers_internal, 1, 1,
2480 ps_global->ew_for_except_vars);
2484 /* Obsolete, backwards compatibility */
2485 set_current_val(&vars[V_ELM_STYLE_SAVE], TRUE, TRUE);
2486 /* Also obsolete */
2487 set_current_val(&vars[V_SAVE_BY_SENDER], TRUE, TRUE);
2488 if(!strucmp(VAR_ELM_STYLE_SAVE, "yes"))
2489 set_variable(V_SAVE_BY_SENDER, "yes", 1, 1, Main);
2490 obs_save_by_sender = !strucmp(VAR_SAVE_BY_SENDER, "yes");
2492 set_current_pattern_vals(ps);
2494 set_current_val(&vars[V_INDEX_FORMAT], TRUE, TRUE);
2495 init_index_format(VAR_INDEX_FORMAT, &ps->index_disp_format);
2497 /* this should come after pre441 is set or not */
2498 set_current_color_vals(ps);
2500 set_current_val(&vars[V_RSS_NEWS], TRUE, TRUE);
2501 set_current_val(&vars[V_RSS_WEATHER], TRUE, TRUE);
2502 set_current_val(&vars[V_WP_INDEXHEIGHT], TRUE, TRUE);
2503 set_current_val(&vars[V_WP_INDEXLINES], TRUE, TRUE);
2504 set_current_val(&vars[V_WP_AGGSTATE], TRUE, TRUE);
2505 set_current_val(&vars[V_WP_STATE], TRUE, TRUE);
2506 set_current_val(&vars[V_WP_COLUMNS], TRUE, TRUE);
2508 set_current_val(&vars[V_PRUNED_FOLDERS], TRUE, TRUE);
2509 set_current_val(&vars[V_ARCHIVED_FOLDERS], TRUE, TRUE);
2510 set_current_val(&vars[V_INCOMING_FOLDERS], TRUE, TRUE);
2511 set_current_val(&vars[V_SORT_KEY], TRUE, TRUE);
2512 if(decode_sort(VAR_SORT_KEY, &ps->def_sort, &def_sort_rev) == -1){
2513 snprintf(tmp_20k_buf, SIZEOF_20KBUF, "Sort type \"%.200s\" is invalid", VAR_SORT_KEY);
2514 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2515 ps->def_sort = SortArrival;
2516 ps->def_sort_rev = 0;
2518 else
2519 ps->def_sort_rev = def_sort_rev;
2521 cur_rule_value(&vars[V_SAVED_MSG_NAME_RULE], TRUE, TRUE);
2522 {NAMEVAL_S *v; int i;
2523 for(i = 0; (v = save_msg_rules(i)); i++)
2524 if(v->value == ps_global->save_msg_rule)
2525 break;
2527 /* if save_msg_rule is not default, or is explicitly set to default */
2528 if((ps_global->save_msg_rule != SAV_RULE_DEFLT) ||
2529 (v && v->name &&
2530 (!strucmp(ps_global->vars[V_SAVED_MSG_NAME_RULE].post_user_val.p,
2531 v->name) ||
2532 !strucmp(ps_global->vars[V_SAVED_MSG_NAME_RULE].main_user_val.p,
2533 v->name))))
2534 obs_save_by_sender = 0; /* don't overwrite */
2537 cur_rule_value(&vars[V_FCC_RULE], TRUE, TRUE);
2538 cur_rule_value(&vars[V_AB_SORT_RULE], TRUE, TRUE);
2540 #ifndef _WINDOWS
2541 cur_rule_value(&vars[V_COLOR_STYLE], TRUE, TRUE);
2542 #endif
2544 cur_rule_value(&vars[V_INDEX_COLOR_STYLE], TRUE, TRUE);
2545 cur_rule_value(&vars[V_TITLEBAR_COLOR_STYLE], TRUE, TRUE);
2546 cur_rule_value(&vars[V_FLD_SORT_RULE], TRUE, TRUE);
2547 cur_rule_value(&vars[V_INCOMING_STARTUP], TRUE, TRUE);
2548 cur_rule_value(&vars[V_PRUNING_RULE], TRUE, TRUE);
2549 cur_rule_value(&vars[V_REOPEN_RULE], TRUE, TRUE);
2550 cur_rule_value(&vars[V_GOTO_DEFAULT_RULE], TRUE, TRUE);
2551 cur_rule_value(&vars[V_THREAD_DISP_STYLE], TRUE, TRUE);
2552 cur_rule_value(&vars[V_THREAD_INDEX_STYLE], TRUE, TRUE);
2554 set_current_val(&vars[V_THREAD_MORE_CHAR], TRUE, TRUE);
2555 if(VAR_THREAD_MORE_CHAR[0] && VAR_THREAD_MORE_CHAR[1]){
2556 init_error(ps, SM_ORDER | SM_DING, 3, 5,
2557 _("Only using first character of threading-indicator-character option"));
2558 VAR_THREAD_MORE_CHAR[1] = '\0';
2561 set_current_val(&vars[V_THREAD_EXP_CHAR], TRUE, TRUE);
2562 if(VAR_THREAD_EXP_CHAR[0] && VAR_THREAD_EXP_CHAR[1]){
2563 init_error(ps, SM_ORDER | SM_DING, 3, 5,
2564 _("Only using first character of threading-expanded-character option"));
2565 VAR_THREAD_EXP_CHAR[1] = '\0';
2568 set_current_val(&vars[V_THREAD_LASTREPLY_CHAR], TRUE, TRUE);
2569 if(!VAR_THREAD_LASTREPLY_CHAR[0])
2570 VAR_THREAD_LASTREPLY_CHAR = cpystr(DF_THREAD_LASTREPLY_CHAR);
2572 if(VAR_THREAD_LASTREPLY_CHAR[0] && VAR_THREAD_LASTREPLY_CHAR[1]){
2573 init_error(ps, SM_ORDER | SM_DING, 3, 5,
2574 _("Only using first character of threading-lastreply-character option"));
2575 VAR_THREAD_LASTREPLY_CHAR[1] = '\0';
2578 set_current_val(&vars[V_MAXREMSTREAM], TRUE, TRUE);
2579 ps->s_pool.max_remstream = i = atoi(DF_MAXREMSTREAM);
2580 if(SVAR_MAXREMSTREAM(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2581 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2582 else
2583 ps->s_pool.max_remstream = i;
2585 set_current_val(&vars[V_PERMLOCKED], TRUE, TRUE);
2587 set_current_val(&vars[V_NMW_WIDTH], TRUE, TRUE);
2588 ps->nmw_width = i = atoi(DF_NMW_WIDTH);
2589 if(SVAR_NMW_WIDTH(ps, i, tmp_20k_buf, SIZEOF_20KBUF))
2590 init_error(ps, SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
2591 else
2592 ps->nmw_width = i;
2594 /* backwards compatibility */
2595 if(obs_save_by_sender){
2596 ps->save_msg_rule = SAV_RULE_FROM;
2597 set_variable(V_SAVED_MSG_NAME_RULE, "by-from", 1, 1, Main);
2600 /* this should come after process_feature_list because of use_fkeys */
2601 if(!ps->start_in_index)
2602 set_current_val(&vars[V_INIT_CMD_LIST], FALSE, TRUE);
2603 if(VAR_INIT_CMD_LIST && VAR_INIT_CMD_LIST[0] && VAR_INIT_CMD_LIST[0][0])
2604 if(cmds_f)
2605 (*cmds_f)(ps, VAR_INIT_CMD_LIST);
2607 #ifdef _WINDOWS
2608 mswin_set_quit_confirm (F_OFF(F_QUIT_WO_CONFIRM, ps_global));
2609 #endif /* _WINDOWS */
2611 #ifdef DEBUG
2612 dump_configuration(0);
2613 #endif /* DEBUG */
2617 void
2618 convert_configvars_to_utf8(struct variable *vars, char *fromcharset)
2620 struct variable *v;
2623 * Make sure that everything is UTF-8.
2625 for(v = vars; v->name; v++)
2626 convert_configvar_to_utf8(v, fromcharset);
2630 void
2631 convert_configvar_to_utf8(struct variable *v, char *fromcharset)
2633 char **p, *conv, **valptr;
2634 int i;
2637 * Make sure that everything is UTF-8.
2639 if(v->is_list){
2640 for(i = 0; i < 7; i++){
2641 switch(i){
2642 case 1: valptr = v->current_val.l; break;
2643 case 0: valptr = v->main_user_val.l; break;
2644 case 2: valptr = v->changed_val.l; break;
2645 case 3: valptr = v->post_user_val.l; break;
2646 case 4: valptr = v->global_val.l; break;
2647 case 5: valptr = v->fixed_val.l; break;
2648 case 6: valptr = v->cmdline_val.l; break;
2649 default: alpine_panic("bad case in convert_configvar");
2652 if(valptr){
2653 for(p = valptr; *p; p++){
2654 if(**p){
2655 conv = convert_to_utf8(*p, fromcharset, 0);
2656 if(conv){
2657 fs_give((void **) p);
2658 *p = conv;
2665 else{
2666 for(i = 0; i < 7; i++){
2667 switch(i){
2668 case 1: valptr = &v->current_val.p; break;
2669 case 0: valptr = &v->main_user_val.p; break;
2670 case 2: valptr = &v->changed_val.p; break;
2671 case 3: valptr = &v->post_user_val.p; break;
2672 case 4: valptr = &v->global_val.p; break;
2673 case 5: valptr = &v->fixed_val.p; break;
2674 case 6: valptr = &v->cmdline_val.p; break;
2675 default: alpine_panic("bad case in convert_configvar");
2678 if(valptr && *valptr && (*valptr)[0]){
2679 conv = convert_to_utf8(*valptr, fromcharset, 0);
2680 if(conv){
2681 fs_give((void **) valptr);
2682 *valptr = conv;
2692 * Standard feature name sections
2694 char *
2695 feature_list_section(FEATURE_S *feature)
2697 #define PREF_NONE -1
2698 static char *feat_sect[] = {
2699 #define PREF_MISC 0
2700 /* TRANSLATORS: section heading in configuration screen */
2701 N_("Advanced User Preferences"),
2702 #define PREF_FLDR 1
2703 /* TRANSLATORS: section heading in configuration screen */
2704 N_("Folder Preferences"),
2705 #define PREF_ADDR 2
2706 /* TRANSLATORS: section heading in configuration screen */
2707 N_("Address Book Preferences"),
2708 #define PREF_COMP 3
2709 /* TRANSLATORS: section heading in configuration screen */
2710 N_("Composer Preferences"),
2711 #define PREF_NEWS 4
2712 /* TRANSLATORS: section heading in configuration screen */
2713 N_("News Preferences"),
2714 #define PREF_VIEW 5
2715 /* TRANSLATORS: section heading in configuration screen */
2716 N_("Viewer Preferences"),
2717 #define PREF_ACMD 6
2718 /* TRANSLATORS: section heading in configuration screen */
2719 N_("Advanced Command Preferences"),
2720 #define PREF_PRNT 7
2721 /* TRANSLATORS: section heading in configuration screen */
2722 N_("Printer Preferences"),
2723 #define PREF_RPLY 8
2724 /* TRANSLATORS: section heading in configuration screen */
2725 N_("Reply Preferences"),
2726 #define PREF_SEND 9
2727 /* TRANSLATORS: section heading in configuration screen */
2728 N_("Sending Preferences"),
2729 #define PREF_INDX 10
2730 /* TRANSLATORS: section heading in configuration screen */
2731 N_("Message Index Preferences"),
2732 #define PREF_HIDDEN 11
2733 HIDDEN_PREF
2736 return((feature && feature->section > PREF_NONE
2737 && feature->section < (sizeof(feat_sect)/sizeof(feat_sect[0])))
2738 ? _(feat_sect[feature->section]) : NULL);
2742 /* any os-specific exclusions */
2743 #if defined(DOS) || defined(OS2)
2744 #define PREF_OS_LWSD PREF_NONE
2745 #define PREF_OS_LCLK PREF_NONE
2746 #define PREF_OS_STSP PREF_NONE
2747 #define PREF_OS_SPWN PREF_NONE
2748 #define PREF_OS_XNML PREF_NONE
2749 #define PREF_OS_USFK PREF_MISC
2750 #define PREF_OS_MOUSE PREF_NONE
2751 #else
2752 #define PREF_OS_LWSD PREF_MISC
2753 #define PREF_OS_LCLK PREF_COMP
2754 #define PREF_OS_STSP PREF_MISC
2755 #define PREF_OS_SPWN PREF_MISC
2756 #define PREF_OS_XNML PREF_MISC
2757 #define PREF_OS_USFK PREF_NONE
2758 #define PREF_OS_MOUSE PREF_MISC
2759 #endif
2763 * Standard way to get at feature list members...
2765 FEATURE_S *
2766 feature_list(int index)
2769 * This list is alphabatized by feature string, but the
2770 * macro values need not be ordered.
2772 static FEATURE_S feat_list[] = {
2773 /* Composer prefs */
2774 {"allow-changing-from", NULL,
2775 F_ALLOW_CHANGING_FROM, h_config_allow_chg_from, PREF_COMP, 1},
2776 {"alternate-compose-menu", NULL,
2777 F_ALT_COMPOSE_MENU, h_config_alt_compose_menu, PREF_COMP, 0},
2778 {"alternate-role-menu", "Alternate Role (#) Menu",
2779 F_ALT_ROLE_MENU, h_config_alt_role_menu, PREF_COMP, 0},
2780 {"compose-cancel-confirm-uses-yes", NULL,
2781 F_CANCEL_CONFIRM, h_config_cancel_confirm, PREF_COMP, 0},
2782 {"compose-rejects-unqualified-addrs", "Compose Rejects Unqualified Addresses",
2783 F_COMPOSE_REJECTS_UNQUAL, h_config_compose_rejects_unqual, PREF_COMP, 0},
2784 {"compose-send-offers-first-filter", NULL,
2785 F_FIRST_SEND_FILTER_DFLT, h_config_send_filter_dflt, PREF_COMP, 0},
2786 {"compose-cut-from-cursor", "Ctrl-K Cuts From Cursor",
2787 F_DEL_FROM_DOT, h_config_del_from_dot, PREF_COMP, 0},
2788 {"compose-maps-delete-key-to-ctrl-d", "Delete Key Maps to Ctrl-D",
2789 F_COMPOSE_MAPS_DEL, h_config_compose_maps_del, PREF_COMP, 0},
2790 {"quell-dead-letter-on-cancel", "Do Not Save to Deadletter on Cancel",
2791 F_QUELL_DEAD_LETTER, h_config_quell_dead_letter, PREF_COMP, 0},
2792 {"enable-alternate-editor-cmd", "Enable Alternate Editor Command",
2793 F_ENABLE_ALT_ED, h_config_enable_alt_ed, PREF_COMP, 1},
2794 {"enable-alternate-editor-implicitly", NULL,
2795 F_ALT_ED_NOW, h_config_alt_ed_now, PREF_COMP, 0},
2796 {"enable-search-and-replace", "Enable Search and Replace",
2797 F_ENABLE_SEARCH_AND_REPL, h_config_enable_search_and_repl, PREF_COMP, 1},
2798 {"enable-sigdashes", NULL,
2799 F_ENABLE_SIGDASHES, h_config_sigdashes, PREF_COMP, 0},
2800 {"quell-mailchecks-composing-except-inbox", "Prevent Mailchecks While Composing Except for INBOX",
2801 F_QUELL_PINGS_COMPOSING, h_config_quell_checks_comp, PREF_COMP, 0},
2802 {"quell-mailchecks-composing-inbox", "Prevent Mailchecks While Composing for INBOX",
2803 F_QUELL_PINGS_COMPOSING_INBOX, h_config_quell_checks_comp_inbox, PREF_COMP, 0},
2804 {"quell-user-lookup-in-passwd-file", "Prevent User Lookup in Password File",
2805 F_QUELL_LOCAL_LOOKUP, h_config_quell_local_lookup, PREF_OS_LCLK, 0},
2806 {"spell-check-before-sending", NULL,
2807 F_ALWAYS_SPELL_CHECK, h_config_always_spell_check, PREF_COMP, 0},
2809 /* Reply Prefs */
2810 {"copy-to-address-to-from-if-it-is-us", "Copy To Address to From if it is Us",
2811 F_COPY_TO_TO_FROM, h_config_copy_to_to_from, PREF_RPLY, 0},
2812 {"enable-reply-indent-string-editing", NULL,
2813 F_ENABLE_EDIT_REPLY_INDENT, h_config_prefix_editing, PREF_RPLY, 0},
2814 {"include-attachments-in-reply", "Include Attachments in Reply",
2815 F_ATTACHMENTS_IN_REPLY, h_config_attach_in_reply, PREF_RPLY, 0},
2816 {"include-header-in-reply", "Include Header in Reply",
2817 F_INCLUDE_HEADER, h_config_include_header, PREF_RPLY, 0},
2818 {"include-text-in-reply", "Include Text in Reply",
2819 F_AUTO_INCLUDE_IN_REPLY, h_config_auto_include_reply, PREF_RPLY, 0},
2820 {"reply-always-uses-reply-to", "Reply Always Uses Reply-To",
2821 F_AUTO_REPLY_TO, h_config_auto_reply_to, PREF_RPLY, 0},
2822 {"signature-at-bottom", "Signature at Bottom",
2823 F_SIG_AT_BOTTOM, h_config_sig_at_bottom, PREF_RPLY, 0},
2824 {"strip-from-sigdashes-on-reply", "Strip From Sigdashes on Reply",
2825 F_ENABLE_STRIP_SIGDASHES, h_config_strip_sigdashes, PREF_RPLY, 0},
2826 {"forward-as-attachment", "Forward messages as attachments",
2827 F_FORWARD_AS_ATTACHMENT, h_config_forward_as_attachment, PREF_RPLY, 0},
2828 {"preserve-original-fields", NULL,
2829 F_PRESERVE_ORIGINAL_FIELD, h_config_preserve_field, PREF_RPLY, 0},
2831 /* Sending Prefs */
2832 {"disable-sender", "Do Not Generate Sender Header",
2833 F_DISABLE_SENDER, h_config_disable_sender, PREF_SEND, 0},
2834 {"use-sender-not-x-sender", "Use Sender Instead of X-X-Sender",
2835 F_USE_SENDER_NOT_X, h_config_use_sender_not_x, PREF_SEND, 0},
2836 {"quell-flowed-text", "Do Not Send Flowed Text",
2837 F_QUELL_FLOWED_TEXT, h_config_quell_flowed_text, PREF_SEND, 0},
2838 {"downgrade-multipart-to-text", "Downgrade Multipart to Text",
2839 F_COMPOSE_ALWAYS_DOWNGRADE, h_downgrade_multipart_to_text, PREF_SEND, 0},
2840 {"enable-8bit-esmtp-negotiation", "Enable 8bit ESMTP Negotiation",
2841 F_ENABLE_8BIT, h_config_8bit_smtp, PREF_SEND, 1},
2842 #ifdef BACKGROUND_POST
2843 {"enable-background-sending", NULL,
2844 F_BACKGROUND_POST, h_config_compose_bg_post, PREF_SEND, 0},
2845 #endif
2846 {"enable-delivery-status-notification", NULL,
2847 F_DSN, h_config_compose_dsn, PREF_SEND, 0},
2848 {"enable-verbose-smtp-posting", "Enable Verbose SMTP Posting",
2849 F_VERBOSE_POST, h_config_verbose_post, PREF_SEND, 0},
2850 {"fcc-without-attachments", "Fcc Does Not Include Attachments",
2851 F_NO_FCC_ATTACH, h_config_no_fcc_attach, PREF_SEND, 0},
2852 {"fcc-on-bounce", "Include Fcc When Bouncing Messages",
2853 F_FCC_ON_BOUNCE, h_config_fcc_on_bounce, PREF_SEND, 0},
2854 {"mark-fcc-seen", NULL,
2855 F_MARK_FCC_SEEN, h_config_mark_fcc_seen, PREF_SEND, 0},
2856 {"fcc-only-without-confirm", "Send to Fcc Only Without Confirming",
2857 F_AUTO_FCC_ONLY, h_config_auto_fcc_only, PREF_SEND, 0},
2858 {"send-without-confirm", "Send Without Confirming",
2859 F_SEND_WO_CONFIRM, h_config_send_wo_confirm, PREF_SEND, 0},
2860 {"strip-whitespace-before-send", "Strip Whitespace Before Sending",
2861 F_STRIP_WS_BEFORE_SEND, h_config_strip_ws_before_send, PREF_SEND, 0},
2862 {"warn-if-blank-fcc", "Warn if Blank Fcc",
2863 F_WARN_ABOUT_NO_FCC, h_config_warn_if_fcc_blank, PREF_SEND, 0},
2864 {"warn-if-blank-subject", "Warn if Blank Subject",
2865 F_WARN_ABOUT_NO_SUBJECT, h_config_warn_if_subj_blank, PREF_SEND, 0},
2866 {"warn-if-blank-to-and-cc-and-newsgroups", "Warn if Blank To and CC and Newsgroups",
2867 F_WARN_ABOUT_NO_TO_OR_CC, h_config_warn_if_no_to_or_cc, PREF_SEND, 0},
2869 /* Folder */
2870 {"combined-folder-display", NULL,
2871 F_CMBND_FOLDER_DISP, h_config_combined_folder_display, PREF_FLDR, 0},
2872 {"combined-subdirectory-display", NULL,
2873 F_CMBND_SUBDIR_DISP, h_config_combined_subdir_display, PREF_FLDR, 0},
2874 {"enable-lame-list-mode", "Compensate for Deficient IMAP servers",
2875 F_FIX_BROKEN_LIST, h_config_lame_list_mode, PREF_FLDR, 0},
2876 {"enable-dot-folders", "Enable Hidden Folders",
2877 F_ENABLE_DOT_FOLDERS, h_config_enable_dot_folders, PREF_FLDR, 0},
2878 {"enable-incoming-folders", "Enable Incoming Folders Collection",
2879 F_ENABLE_INCOMING, h_config_enable_incoming, PREF_FLDR, 0},
2880 {"enable-incoming-folders-checking", NULL,
2881 F_ENABLE_INCOMING_CHECKING, h_config_enable_incoming_checking, PREF_FLDR, 0},
2882 {"incoming-checking-includes-total", NULL,
2883 F_INCOMING_CHECKING_TOTAL, h_config_incoming_checking_total, PREF_FLDR, 0},
2884 {"incoming-checking-uses-recent", NULL,
2885 F_INCOMING_CHECKING_RECENT, h_config_incoming_checking_recent, PREF_FLDR, 0},
2886 {"expanded-view-of-folders", "Expanded View of Folders",
2887 F_EXPANDED_FOLDERS, h_config_expanded_folders, PREF_FLDR, 0},
2888 {"quell-empty-directories", "Hide Empty Directories",
2889 F_QUELL_EMPTY_DIRS, h_config_quell_empty_dirs, PREF_FLDR, 0},
2890 {"separate-folder-and-directory-entries", "Separate Folder and Directory Entries",
2891 F_SEPARATE_FLDR_AS_DIR, h_config_separate_fold_dir_view, PREF_FLDR, 0},
2892 {"single-column-folder-list", NULL,
2893 F_SINGLE_FOLDER_LIST, h_config_single_list, PREF_FLDR, 0},
2894 {"sort-default-fcc-alpha", "Sort Default Fcc Folder Alphabetically",
2895 F_SORT_DEFAULT_FCC_ALPHA, h_config_sort_fcc_alpha, PREF_FLDR, 0},
2896 {"sort-default-save-alpha", "Sort Default Save Folder Alphabetically",
2897 F_SORT_DEFAULT_SAVE_ALPHA, h_config_sort_save_alpha, PREF_FLDR, 0},
2898 {"vertical-folder-list", "Use Vertical Folder List",
2899 F_VERTICAL_FOLDER_LIST, h_config_vertical_list, PREF_FLDR, 0},
2901 /* Addr book */
2902 {"combined-addrbook-display", "Combined Address Book Display",
2903 F_CMBND_ABOOK_DISP, h_config_combined_abook_display, PREF_ADDR, 0},
2904 {"expanded-view-of-addressbooks", "Expanded View of Address Books",
2905 F_EXPANDED_ADDRBOOKS, h_config_expanded_addrbooks, PREF_ADDR, 0},
2906 {"expanded-view-of-distribution-lists", "Expanded View of Distribution Lists",
2907 F_EXPANDED_DISTLISTS, h_config_expanded_distlists, PREF_ADDR, 0},
2908 #ifdef ENABLE_LDAP
2909 {"ldap-result-to-addrbook-add", "LDAP Result to Addressbook Add",
2910 F_ADD_LDAP_TO_ABOOK, h_config_add_ldap, PREF_ADDR, 0},
2911 #endif
2913 /* Index prefs */
2914 {"auto-open-next-unread", NULL,
2915 F_AUTO_OPEN_NEXT_UNREAD, h_config_auto_open_unread, PREF_INDX, 0},
2916 {"continue-tab-without-confirm", "Continue NextNew Without Confirming",
2917 F_TAB_NO_CONFIRM, h_config_tab_no_prompt, PREF_INDX, 0},
2918 {"convert-dates-to-localtime", NULL,
2919 F_DATES_TO_LOCAL, h_config_dates_to_local, PREF_INDX, 0},
2920 {"delete-skips-deleted", NULL,
2921 F_DEL_SKIPS_DEL, h_config_del_skips_del, PREF_INDX, 1},
2922 {"disable-index-locale-dates", NULL,
2923 F_DISABLE_INDEX_LOCALE_DATES, h_config_disable_index_locale_dates, PREF_INDX, 0},
2924 {"enable-cruise-mode", NULL,
2925 F_ENABLE_SPACE_AS_TAB, h_config_cruise_mode, PREF_INDX, 0},
2926 {"enable-cruise-mode-delete", "Enable Cruise Mode With Deleting",
2927 F_ENABLE_TAB_DELETES, h_config_cruise_mode_delete, PREF_INDX, 0},
2928 {"mark-for-cc", "Mark for CC",
2929 F_MARK_FOR_CC, h_config_mark_for_cc, PREF_INDX, 1},
2930 {"next-thread-without-confirm", "Read Next Thread Without Confirming",
2931 F_NEXT_THRD_WO_CONFIRM, h_config_next_thrd_wo_confirm, PREF_INDX, 0},
2932 {"return-to-inbox-without-confirm", "Return to INBOX Without Confirming",
2933 F_RET_INBOX_NO_CONFIRM, h_config_inbox_no_confirm, PREF_INDX, 0},
2934 {"show-sort", "Show Sort in Titlebar",
2935 F_SHOW_SORT, h_config_show_sort, PREF_INDX, 0},
2936 {"tab-uses-unseen-for-next-folder", "Tab Uses Unseen for Next Folder",
2937 F_TAB_USES_UNSEEN, h_config_tab_uses_unseen, PREF_INDX, 0},
2938 {"tab-visits-next-new-message-only", NULL,
2939 F_TAB_TO_NEW, h_config_tab_new_only, PREF_INDX, 0},
2940 {"thread-index-shows-important-color", NULL,
2941 F_COLOR_LINE_IMPORTANT, h_config_color_thrd_import, PREF_INDX, 0},
2942 {"thread-sorts-by-arrival", "Thread Sorts by Arrival",
2943 F_THREAD_SORTS_BY_ARRIVAL, h_config_thread_sorts_by_arrival, PREF_INDX, 0},
2945 /* Viewer prefs */
2946 {"enable-msg-view-addresses", "Enable Message View Address Links",
2947 F_SCAN_ADDR, h_config_enable_view_addresses, PREF_VIEW, 0},
2948 {"enable-msg-view-attachments", "Enable Message View Attachment Links",
2949 F_VIEW_SEL_ATTACH, h_config_enable_view_attach, PREF_VIEW, 0},
2950 {"enable-msg-view-urls", "Enable Message View URL Links",
2951 F_VIEW_SEL_URL, h_config_enable_view_url, PREF_VIEW, 1},
2952 {"enable-msg-view-web-hostnames", "Enable Message View Web Hostname Links",
2953 F_VIEW_SEL_URL_HOST, h_config_enable_view_web_host, PREF_VIEW, 1},
2954 {"enable-msg-view-forced-arrows", "Enable Message View Forced Arrows",
2955 F_FORCE_ARROWS, h_config_enable_view_arrows, PREF_VIEW, 0},
2956 /* set to TRUE for windows */
2957 {"pass-c1-control-characters-as-is", NULL,
2958 F_PASS_C1_CONTROL_CHARS, h_config_pass_c1_control, PREF_VIEW, 0},
2959 {"pass-control-characters-as-is", NULL,
2960 F_PASS_CONTROL_CHARS, h_config_pass_control, PREF_VIEW, 0},
2961 {"prefer-plain-text", NULL,
2962 F_PREFER_PLAIN_TEXT, h_config_prefer_plain_text, PREF_VIEW, 0},
2963 {"quell-charset-warning", "Suppress Character Set Warning",
2964 F_QUELL_CHARSET_WARNING, h_config_quell_charset_warning, PREF_VIEW, 0},
2965 {"quell-server-after-link-in-html", "Suppress Server After Link in HTML",
2966 F_QUELL_HOST_AFTER_URL, h_config_quell_host_after_url, PREF_VIEW, 0},
2968 /* News */
2969 {"compose-sets-newsgroup-without-confirm", "Compose Sets Newsgroup Without Confirming",
2970 F_COMPOSE_TO_NEWSGRP, h_config_compose_news_wo_conf, PREF_NEWS, 0},
2971 {"enable-8bit-nntp-posting", "Enable 8bit NNTP Posting",
2972 F_ENABLE_8BIT_NNTP, h_config_8bit_nntp, PREF_NEWS, 0},
2973 {"enable-multiple-newsrcs", NULL,
2974 F_ENABLE_MULNEWSRCS, h_config_enable_mulnewsrcs, PREF_NEWS, 0},
2975 {"mult-newsrc-hostnames-as-typed", "Multiple Newsrc Hostnames as Typed",
2976 F_MULNEWSRC_HOSTNAMES_AS_TYPED, h_config_mulnews_as_typed, PREF_NEWS, 0},
2977 {"hide-nntp-path", "Hide NNTP Path",
2978 F_HIDE_NNTP_PATH, h_config_hide_nntp_path, PREF_NEWS, 0},
2979 {"news-approximates-new-status", NULL,
2980 F_FAKE_NEW_IN_NEWS, h_config_news_uses_recent, PREF_NEWS, 1},
2981 {"news-deletes-across-groups", NULL,
2982 F_NEWS_CROSS_DELETE, h_config_news_cross_deletes, PREF_NEWS, 0},
2983 {"news-offers-catchup-on-close", "News Offers Catchup on Close",
2984 F_NEWS_CATCHUP, h_config_news_catchup, PREF_NEWS, 0},
2985 {"news-post-without-validation", NULL,
2986 F_NO_NEWS_VALIDATION, h_config_post_wo_validation, PREF_NEWS, 0},
2987 {"news-read-in-newsrc-order", "News Read in Newsrc Order",
2988 F_READ_IN_NEWSRC_ORDER, h_config_read_in_newsrc_order, PREF_NEWS, 0},
2989 {"nntp-search-uses-overview", "NNTP Search Uses Overview",
2990 F_NNTP_SEARCH_USES_OVERVIEW, h_config_nntp_search_uses_overview, PREF_NEWS, 1},
2991 {"predict-nntp-server", "Predict NNTP Server",
2992 F_PREDICT_NNTP_SERVER, h_config_predict_nntp_server, PREF_NEWS, 0},
2993 {"quell-extra-post-prompt", "Suppress Extra Posting Prompt",
2994 F_QUELL_EXTRA_POST_PROMPT, h_config_quell_post_prompt, PREF_NEWS, 0},
2996 /* Print */
2997 {"enable-print-via-y-command", NULL,
2998 F_ENABLE_PRYNT, h_config_enable_y_print, PREF_PRNT, 0},
2999 {"print-formfeed-between-messages", NULL,
3000 F_AGG_PRINT_FF, h_config_ff_between_msgs, PREF_PRNT, 0},
3001 {"print-includes-from-line", NULL,
3002 F_FROM_DELIM_IN_PRINT, h_config_print_from, PREF_PRNT, 0},
3003 {"print-index-enabled", NULL,
3004 F_PRINT_INDEX, h_config_print_index, PREF_PRNT, 0},
3005 {"print-offers-custom-cmd-prompt", "Print Offers Custom Command Prompt",
3006 F_CUSTOM_PRINT, h_config_custom_print, PREF_PRNT, 0},
3008 /* adv cmd prefs */
3009 {"enable-aggregate-command-set", NULL,
3010 F_ENABLE_AGG_OPS, h_config_enable_agg_ops, PREF_ACMD, 1},
3011 {"enable-arrow-navigation", NULL,
3012 F_ARROW_NAV, h_config_arrow_nav, PREF_ACMD, 1},
3013 {"enable-arrow-navigation-relaxed", NULL,
3014 F_RELAXED_ARROW_NAV, h_config_relaxed_arrow_nav, PREF_ACMD, 1},
3015 {"enable-bounce-cmd", "Enable Bounce Command",
3016 F_ENABLE_BOUNCE, h_config_enable_bounce, PREF_ACMD, 1},
3017 {"enable-exit-via-lessthan-command", NULL,
3018 F_ENABLE_LESSTHAN_EXIT, h_config_enable_lessthan_exit, PREF_ACMD, 1},
3019 {"enable-flag-cmd", "Enable Flag Command",
3020 F_ENABLE_FLAG, h_config_enable_flag, PREF_ACMD, 1},
3021 {"enable-flag-screen-implicitly", NULL,
3022 F_FLAG_SCREEN_DFLT, h_config_flag_screen_default, PREF_ACMD, 0},
3023 {"enable-flag-screen-keyword-shortcut", NULL,
3024 F_FLAG_SCREEN_KW_SHORTCUT, h_config_flag_screen_kw_shortcut,PREF_ACMD, 1},
3025 {"enable-full-header-and-text", "Enable Full Header and Text",
3026 F_ENABLE_FULL_HDR_AND_TEXT, h_config_enable_full_hdr_and_text, PREF_ACMD, 0},
3027 {"enable-full-header-cmd", "Enable Full Header Command",
3028 F_ENABLE_FULL_HDR, h_config_enable_full_hdr, PREF_ACMD, 1},
3029 {"enable-goto-in-file-browser", "Enable Goto in File Browser",
3030 F_ALLOW_GOTO, h_config_allow_goto, PREF_ACMD, 1},
3031 {"enable-jump-shortcut", NULL,
3032 F_ENABLE_JUMP, h_config_enable_jump, PREF_ACMD, 1},
3033 {"enable-partial-match-lists", NULL,
3034 F_ENABLE_SUB_LISTS, h_config_sub_lists, PREF_ACMD, 1},
3035 {"enable-tab-completion", NULL,
3036 F_ENABLE_TAB_COMPLETE, h_config_enable_tab_complete, PREF_ACMD, 1},
3037 {"enable-unix-pipe-cmd", "Enable Unix Pipe Command",
3038 F_ENABLE_PIPE, h_config_enable_pipe, PREF_ACMD, 1},
3039 {"quell-full-header-auto-reset", "Suppress Full Header Auto Reset",
3040 F_QUELL_FULL_HDR_RESET, h_config_quell_full_hdr_reset, PREF_ACMD, 0},
3042 /* Adv user prefs */
3043 #if !defined(DOS) && !defined(OS2)
3044 {"allow-talk", NULL,
3045 F_ALLOW_TALK, h_config_allow_talk, PREF_MISC, 0},
3046 #endif
3047 {"assume-slow-link", NULL,
3048 F_FORCE_LOW_SPEED, h_config_force_low_speed, PREF_OS_LWSD, 0},
3049 {"auto-move-read-msgs", "Auto Move Read Messages",
3050 F_AUTO_READ_MSGS, h_config_auto_read_msgs, PREF_MISC, 0},
3051 {"auto-unselect-after-apply", NULL,
3052 F_AUTO_UNSELECT, h_config_auto_unselect, PREF_MISC, 0},
3053 {"auto-unzoom-after-apply", NULL,
3054 F_AUTO_UNZOOM, h_config_auto_unzoom, PREF_MISC, 1},
3055 {"auto-zoom-after-select", NULL,
3056 F_AUTO_ZOOM, h_config_auto_zoom, PREF_MISC, 1},
3057 {"busy-cue-spinner-only", NULL,
3058 F_USE_BORING_SPINNER, h_config_use_boring_spinner, PREF_MISC, 0},
3059 {"check-newmail-when-quitting", NULL,
3060 F_CHECK_MAIL_ONQUIT, h_config_check_mail_onquit, PREF_MISC, 0},
3061 {"confirm-role-even-for-default", "Confirm Role Even for Default",
3062 F_ROLE_CONFIRM_DEFAULT, h_config_confirm_role, PREF_MISC, 0},
3063 {"disable-keymenu", NULL,
3064 F_BLANK_KEYMENU, h_config_blank_keymenu, PREF_MISC, 0},
3065 {"disable-password-caching", NULL,
3066 F_DISABLE_PASSWORD_CACHING, h_config_disable_password_caching,
3067 PREF_MISC, 0},
3068 {"disable-regular-expression-matching-for-alternate-addresses", NULL,
3069 F_DISABLE_REGEX, h_config_disable_regex, PREF_MISC, 0},
3070 {"disable-save-input-history", NULL,
3071 F_DISABLE_SAVE_INPUT_HISTORY, h_config_input_history, PREF_MISC, 0},
3072 {"disable-take-fullname-in-addresses", "Disable Take Fullname in Addresses",
3073 F_DISABLE_TAKE_FULLNAMES, h_config_take_fullname, PREF_MISC, 0},
3074 {"disable-take-last-comma-first", NULL,
3075 F_DISABLE_TAKE_LASTFIRST, h_config_take_lastfirst, PREF_MISC, 0},
3076 {"disable-terminal-reset-for-display-filters", "Disable Terminal Reset for Display Filters",
3077 F_DISABLE_TERM_RESET_DISP, h_config_disable_reset_disp, PREF_MISC, 0},
3078 {"enable-dot-files", NULL,
3079 F_ENABLE_DOT_FILES, h_config_enable_dot_files, PREF_MISC, 0},
3080 {"enable-fast-recent-test", NULL,
3081 F_ENABLE_FAST_RECENT, h_config_fast_recent, PREF_MISC, 0},
3082 {"enable-mail-check-cue", NULL,
3083 F_SHOW_DELAY_CUE, h_config_show_delay_cue, PREF_MISC, 0},
3084 {"enable-mailcap-param-substitution", "Enable Mailcap Parameter Substitution",
3085 F_DO_MAILCAP_PARAM_SUBST, h_config_mailcap_params, PREF_MISC, 0},
3086 {"enable-mouse-in-xterm", "Enable Mouse in Xterm",
3087 F_ENABLE_MOUSE, h_config_enable_mouse, PREF_OS_MOUSE, 0},
3088 {"enable-newmail-in-xterm-icon", "Enable Newmail in Xterm Icon",
3089 F_ENABLE_XTERM_NEWMAIL, h_config_enable_xterm_newmail, PREF_OS_XNML, 0},
3090 {"enable-newmail-short-text-in-icon", "Enable Newmail Short Text in Icon",
3091 F_ENABLE_NEWMAIL_SHORT_TEXT, h_config_enable_newmail_short_text, PREF_OS_XNML, 0},
3092 {"enable-suspend", NULL,
3093 F_CAN_SUSPEND, h_config_can_suspend, PREF_MISC, 0},
3094 {"enable-take-export", NULL,
3095 F_ENABLE_TAKE_EXPORT, h_config_enable_take_export, PREF_MISC, 0},
3096 {"enable-rules-under-take", "Enable Take Rules",
3097 F_ENABLE_ROLE_TAKE, h_config_enable_role_take, PREF_MISC, 0},
3098 #ifdef _WINDOWS
3099 {"enable-tray-icon", NULL,
3100 F_ENABLE_TRAYICON, h_config_tray_icon, PREF_MISC, 0},
3101 #endif
3102 {"expose-hidden-config", NULL,
3103 F_EXPOSE_HIDDEN_CONFIG, h_config_expose_hidden_config, PREF_MISC, 0},
3104 {"expunge-only-manually", NULL,
3105 F_EXPUNGE_MANUALLY, h_config_expunge_manually, PREF_MISC, 0},
3106 {"expunge-without-confirm", "Expunge Without Confirming",
3107 F_AUTO_EXPUNGE, h_config_auto_expunge, PREF_MISC, 0},
3108 {"expunge-without-confirm-everywhere", "Expunge Without Confirming Everywhere",
3109 F_FULL_AUTO_EXPUNGE, h_config_full_auto_expunge, PREF_MISC, 0},
3110 {"force-arrow-cursor", NULL,
3111 F_FORCE_ARROW, h_config_force_arrow, PREF_MISC, 0},
3112 {"maildrops-preserve-state", NULL,
3113 F_MAILDROPS_PRESERVE_STATE, h_config_maildrops_preserve_state,
3114 PREF_MISC, 0},
3115 {"offer-expunge-of-inbox", "Offer Expunge of INBOX",
3116 F_EXPUNGE_INBOX, h_config_expunge_inbox, PREF_MISC, 0},
3117 {"offer-expunge-of-stayopen-folders", "Offer Expunge of Stayopen Folders",
3118 F_EXPUNGE_STAYOPENS, h_config_expunge_stayopens, PREF_MISC, 0},
3119 {"preopen-stayopen-folders", NULL,
3120 F_PREOPEN_STAYOPENS, h_config_preopen_stayopens, PREF_MISC, 0},
3121 {"preserve-start-stop-characters", "Preserve Start/Stop Characters",
3122 F_PRESERVE_START_STOP, h_config_preserve_start_stop, PREF_OS_STSP, 0},
3123 {"quell-folder-internal-msg", "Prevent Folder Internal Message",
3124 F_QUELL_INTERNAL_MSG, h_config_quell_folder_internal_msg, PREF_MISC, 0},
3125 {"quell-partial-fetching", "Prevent Partial Fetching",
3126 F_QUELL_PARTIAL_FETCH, h_config_quell_partial, PREF_MISC, 0},
3127 {"prune-uses-yyyy-mm", "Prune Uses YYYY-MM",
3128 F_PRUNE_USES_ISO, h_config_prune_uses_iso, PREF_MISC, 0},
3129 {"quit-without-confirm", "Quit Without Confirming",
3130 F_QUIT_WO_CONFIRM, h_config_quit_wo_confirm, PREF_MISC, 0},
3131 {"quote-replace-nonflowed", NULL,
3132 F_QUOTE_REPLACE_NOFLOW, h_config_quote_replace_noflow, PREF_MISC, 0},
3133 {"save-aggregates-copy-sequence", "Save Combines Copies (may be out of order)",
3134 F_AGG_SEQ_COPY, h_config_save_aggregates, PREF_MISC, 1},
3135 {"save-partial-msg-without-confirm", "Save Partial Message Without Confirming",
3136 F_SAVE_PARTIAL_WO_CONFIRM, h_config_save_part_wo_confirm, PREF_MISC, 0},
3137 {"save-will-advance", NULL,
3138 F_SAVE_ADVANCES, h_config_save_advances, PREF_MISC, 0},
3139 {"save-will-not-delete", NULL,
3140 F_SAVE_WONT_DELETE, h_config_save_wont_delete, PREF_MISC, 0},
3141 {"save-will-quote-leading-froms", NULL,
3142 F_QUOTE_ALL_FROMS, h_config_quote_all_froms, PREF_MISC, 0},
3143 {"scramble-message-id", "Scramble the Message-ID When Sending",
3144 F_ROT13_MESSAGE_ID, h_config_scramble_message_id, PREF_MISC, 0},
3145 {"select-without-confirm", "Select Ctrl-T Foldername Without Confirming",
3146 F_SELECT_WO_CONFIRM, h_config_select_wo_confirm, PREF_MISC, 0},
3147 {"show-cursor", NULL,
3148 F_SHOW_CURSOR, h_config_show_cursor, PREF_MISC, 0},
3149 {"show-plain-text-internally", NULL,
3150 F_SHOW_TEXTPLAIN_INT, h_config_textplain_int, PREF_MISC, 0},
3151 {"show-selected-in-boldface", "Show Selected in Boldface",
3152 F_SELECTED_SHOWN_BOLD, h_config_select_in_bold, PREF_MISC, 0},
3153 {"slash-collapses-entire-thread", NULL,
3154 F_SLASH_COLL_ENTIRE, h_config_slash_coll_entire, PREF_MISC, 0},
3155 #ifdef _WINDOWS
3156 {"store-window-position-in-config", "Store Window Position in Config",
3157 F_STORE_WINPOS_IN_CONFIG, h_config_winpos_in_config, PREF_MISC, 0},
3158 #endif
3159 {"suppress-asterisks-in-password-prompt", "Suppress Asterisks in Password Prompt",
3160 F_QUELL_ASTERISKS, h_config_quell_asterisks,
3161 PREF_MISC, 0},
3162 {"quell-attachment-extension-warn", "Suppress Attachment Extension Warning",
3163 F_QUELL_ATTACH_EXT_WARN, h_config_quell_attach_ext_warn,
3164 PREF_MISC, 0},
3165 {"quell-attachment-extra-prompt", "Suppress Attachment Extra Prompt",
3166 F_QUELL_ATTACH_EXTRA_PROMPT, h_config_quell_attach_extra_prompt,
3167 PREF_MISC, 0},
3168 {"quell-berkeley-format-timezone", "Suppress Berkeley Format Timezone",
3169 F_QUELL_BEZERK_TIMEZONE, h_config_no_bezerk_zone, PREF_MISC, 0},
3170 {"quell-content-id", "Suppress Content-ID",
3171 F_QUELL_CONTENT_ID, h_config_quell_content_id, PREF_MISC, 0},
3172 {"quell-filtering-done-message", "Suppress Filtering Done Message",
3173 F_QUELL_FILTER_DONE_MSG, h_config_quell_filtering_done_message,
3174 PREF_MISC, 0},
3175 {"quell-filtering-messages", "Suppress Filtering Messages",
3176 F_QUELL_FILTER_MSGS, h_config_quell_filtering_messages,
3177 PREF_MISC, 0},
3178 {"quell-imap-envelope-update", "Suppress IMAP Envelope Update",
3179 F_QUELL_IMAP_ENV_CB, h_config_quell_imap_env, PREF_MISC, 0},
3180 {"quell-lock-failure-warnings", "Suppress Lock Failure Warnings",
3181 F_QUELL_LOCK_FAILURE_MSGS, h_config_quell_lock_failure_warnings,
3182 PREF_MISC, 0},
3183 {"quell-maildomain-warning", "Suppress Maildomain Warning",
3184 F_QUELL_MAILDOMAIN_WARNING, h_config_quell_domain_warn, PREF_MISC, 0},
3185 {"quell-news-envelope-update", "Suppress News Envelope Update",
3186 F_QUELL_NEWS_ENV_CB, h_config_quell_news_env, PREF_MISC, 0},
3187 #ifdef _WINDOWS
3188 {"quell-ssl-largeblocks", "Prevent SSL Largeblocks",
3189 F_QUELL_SSL_LARGEBLOCKS, h_config_quell_ssl_largeblocks, PREF_MISC, 0},
3190 #endif
3191 {"quell-status-message-beeping", "Suppress Status Message Beeping",
3192 F_QUELL_BEEPS, h_config_quell_beeps, PREF_MISC, 0},
3193 {"quell-timezone-comment-when-sending", "Suppress Timezone Comment When Sending",
3194 F_QUELL_TIMEZONE, h_config_quell_tz_comment, PREF_MISC, 0},
3195 {"suppress-user-agent-when-sending", NULL,
3196 F_QUELL_USERAGENT, h_config_suppress_user_agent, PREF_MISC, 0},
3197 {"tab-checks-recent", "Tab Checks for Recent Messages",
3198 F_TAB_CHK_RECENT, h_config_tab_checks_recent, PREF_MISC, 0},
3199 {"termdef-takes-precedence", NULL,
3200 F_TCAP_WINS, h_config_termcap_wins, PREF_MISC, 0},
3201 {"try-alternative-authentication-driver-first", NULL,
3202 F_PREFER_ALT_AUTH, h_config_alt_auth, PREF_MISC, 0},
3203 {"unselect-will-not-advance", NULL,
3204 F_UNSELECT_WONT_ADVANCE, h_config_unsel_wont_advance, PREF_MISC, 0},
3205 {"use-current-dir", "Use Current Directory",
3206 F_USE_CURRENT_DIR, h_config_use_current_dir, PREF_MISC, 0},
3207 {"use-function-keys", NULL,
3208 F_USE_FK, h_config_use_fk, PREF_OS_USFK, 0},
3209 {"use-regular-startup-rule-for-stayopen-folders", "Use Regular Startup Rule for Stayopen Folders",
3210 F_STARTUP_STAYOPEN, h_config_use_reg_start_for_stayopen, PREF_MISC, 0},
3211 {"use-resent-to-in-rules", "Use Resent-To in Rules",
3212 F_USE_RESENTTO, h_config_use_resentto, PREF_MISC, 0},
3213 {"use-subshell-for-suspend", "Use Subshell for Suspend",
3214 F_SUSPEND_SPAWNS, h_config_suspend_spawns, PREF_OS_SPWN, 0},
3215 #ifndef _WINDOWS
3216 {"use-system-translation", NULL,
3217 F_USE_SYSTEM_TRANS, h_config_use_system_translation, PREF_MISC, 0},
3218 #endif
3220 /* Hidden Features */
3221 {"old-growth", NULL,
3222 F_OLD_GROWTH, NO_HELP, PREF_NONE, 0},
3223 {"disable-config-cmd", NULL,
3224 F_DISABLE_CONFIG_SCREEN, h_config_disable_config_cmd, PREF_HIDDEN, 0},
3225 {"disable-keyboard-lock-cmd", NULL,
3226 F_DISABLE_KBLOCK_CMD, h_config_disable_kb_lock, PREF_HIDDEN, 0},
3227 {"disable-password-cmd", NULL,
3228 F_DISABLE_PASSWORD_CMD, h_config_disable_password_cmd, PREF_HIDDEN, 0},
3229 {"disable-pipes-in-sigs", NULL,
3230 F_DISABLE_PIPES_IN_SIGS, h_config_disable_pipes_in_sigs, PREF_HIDDEN, 0},
3231 {"disable-pipes-in-templates", NULL,
3232 F_DISABLE_PIPES_IN_TEMPLATES, h_config_disable_pipes_in_templates,
3233 PREF_HIDDEN, 0},
3234 {"disable-roles-setup-cmd", NULL,
3235 F_DISABLE_ROLES_SETUP, h_config_disable_roles_setup, PREF_HIDDEN, 0},
3236 {"disable-roles-sig-edit", NULL,
3237 F_DISABLE_ROLES_SIGEDIT, h_config_disable_roles_sigedit, PREF_HIDDEN, 0},
3238 {"disable-roles-template-edit", NULL,
3239 F_DISABLE_ROLES_TEMPLEDIT, h_config_disable_roles_templateedit,
3240 PREF_HIDDEN, 0},
3241 {"disable-setlocale-collate", NULL,
3242 F_DISABLE_SETLOCALE_COLLATE, h_config_disable_collate, PREF_HIDDEN, 0},
3243 {"disable-shared-namespaces", NULL,
3244 F_DISABLE_SHARED_NAMESPACES, h_config_disable_shared, PREF_HIDDEN, 0},
3245 {"disable-signature-edit-cmd", NULL,
3246 F_DISABLE_SIGEDIT_CMD, h_config_disable_signature_edit, PREF_HIDDEN, 0},
3247 {"new-thread-on-blank-subject", "New Thread on Blank Subject",
3248 F_NEW_THREAD_ON_BLANK_SUBJECT, h_config_new_thread_blank_subject, PREF_HIDDEN, 1},
3249 {"quell-personal-name-prompt", NULL,
3250 F_QUELL_PERSONAL_NAME_PROMPT, h_config_quell_personal_name_prompt, PREF_HIDDEN, 0},
3251 {"quell-user-id-prompt", "Quell User ID Prompt",
3252 F_QUELL_USER_ID_PROMPT, h_config_quell_user_id_prompt, PREF_HIDDEN, 0},
3253 #ifdef SMIME
3254 {"smime-dont-do-smime", "S/MIME -- Turn off S/MIME",
3255 F_DONT_DO_SMIME, h_config_smime_dont_do_smime, PREF_HIDDEN, 0},
3256 {"smime-encrypt-by-default", "S/MIME -- Encrypt by Default",
3257 F_ENCRYPT_DEFAULT_ON, h_config_smime_encrypt_by_default, PREF_HIDDEN, 0},
3258 {"smime-remember-passphrase", "S/MIME -- Remember S/MIME Passphrase",
3259 F_REMEMBER_SMIME_PASSPHRASE, h_config_smime_remember_passphrase, PREF_HIDDEN, 0},
3260 {"smime-sign-by-default", "S/MIME -- Sign by Default",
3261 F_SIGN_DEFAULT_ON, h_config_smime_sign_by_default, PREF_HIDDEN, 0},
3262 {"smime-use-store-only", "S/MIME -- Validate Using Certificate Store Only",
3263 F_USE_CERT_STORE_ONLY, h_config_smime_use_cert_store, PREF_HIDDEN, 1},
3264 #ifdef APPLEKEYCHAIN
3265 {"publiccerts-in-keychain", "S/MIME -- Public Certs in MacOS Keychain",
3266 F_PUBLICCERTS_IN_KEYCHAIN, h_config_smime_pubcerts_in_keychain, PREF_HIDDEN, 0},
3267 #endif
3268 #endif
3269 {"selectable-item-nobold", NULL,
3270 F_SLCTBL_ITEM_NOBOLD, NO_HELP, PREF_NONE, 0},
3271 {"send-confirms-only-expanded", NULL, /* exposed in Web Alpine */
3272 F_SEND_CONFIRM_ON_EXPAND, h_config_send_confirms_only_expanded, PREF_HIDDEN, 0},
3273 {"enable-jump-cmd", NULL, /* exposed in Web Alpine */
3274 F_ENABLE_JUMP_CMD, h_config_enable_jump_command, PREF_HIDDEN, 0},
3275 {"enable-newmail-sound", NULL, /* exposed in Web Alpine */
3276 F_ENABLE_NEWMAIL_SOUND, h_config_enable_newmail_sound, PREF_HIDDEN, 0},
3277 {"render-html-internally", NULL, /* exposed in Web Alpine */
3278 F_RENDER_HTML_INTERNALLY, h_config_render_html_internally, PREF_HIDDEN, 0}
3281 return((index >= 0 && index < (sizeof(feat_list)/sizeof(feat_list[0])))
3282 ? &feat_list[index] : NULL);
3287 * feature_list_index -- return index of given feature id in
3288 * feature list
3291 feature_list_index(int id)
3293 FEATURE_S *feature;
3294 int i;
3296 for(i = 0; (feature = feature_list(i)); i++)
3297 if(id == feature->id)
3298 return(i);
3300 return(-1);
3305 * feature_list_name -- return the given feature id's corresponding name
3307 char *
3308 feature_list_name(int id)
3310 FEATURE_S *f;
3312 return((f = feature_list(feature_list_index(id))) ? f->name : "");
3317 feature_list_id(char *name)
3319 FEATURE_S *f;
3320 int i;
3322 for(i = 0; (f = feature_list(i)); i++)
3323 if(!strucmp(f->name, name))
3324 return(f->id);
3326 return(-1);
3331 * feature_list_help -- return the given feature id's corresponding help
3333 HelpType
3334 feature_list_help(int id)
3336 FEATURE_S *f;
3338 return((f = feature_list(feature_list_index(id))) ? f->help : NO_HELP);
3343 * All the arguments past "list" are the backwards compatibility hacks.
3345 void
3346 process_feature_list(struct pine *ps, char **list, int old_growth, int hir, int osr)
3348 register char *q;
3349 char **p,
3350 *lvalue[BM_SIZE * 8];
3351 int i,
3352 yorn;
3353 long l;
3354 FEATURE_S *feat;
3357 /* clear all previous settings and reset them to default */
3358 for(i = 0; (feat = feature_list(i)) != NULL; i++)
3359 F_SET(feat->id, ps, feat->defval);
3361 /* backwards compatibility */
3362 if(hir)
3363 F_TURN_ON(F_INCLUDE_HEADER, ps);
3365 /* ditto */
3366 if(osr)
3367 F_TURN_ON(F_SIG_AT_BOTTOM, ps);
3369 /* ditto */
3370 if(old_growth)
3371 set_old_growth_bits(ps, 0);
3373 /* now run through the list (global, user, and cmd_line lists are here) */
3374 if(list){
3375 for(p = list; (q = *p) != NULL; p++){
3376 if(struncmp(q, "no-", 3) == 0){
3377 yorn = 0;
3378 q += 3;
3379 }else{
3380 yorn = 1;
3383 for(i = 0; (feat = feature_list(i)) != NULL; i++){
3384 if(strucmp(q, feat->name) == 0){
3385 if(feat->id == F_OLD_GROWTH){
3386 set_old_growth_bits(ps, yorn);
3387 }else{
3388 F_SET(feat->id, ps, yorn);
3390 break;
3394 /* if it wasn't in that list */
3395 if(feat == NULL)
3396 dprint((1,"Unrecognized feature in feature-list (%s%s)\n",
3397 (yorn ? "" : "no-"), q ? q : "?"));
3402 * Turn on gratuitous '>From ' quoting, if requested...
3404 mail_parameters(NULL, SET_FROMWIDGET,
3405 F_ON(F_QUOTE_ALL_FROMS, ps) ? VOIDT : NIL);
3408 * Turn off .lock creation complaints...
3410 if(F_ON(F_QUELL_LOCK_FAILURE_MSGS, ps))
3411 mail_parameters(NULL, SET_LOCKEACCESERROR, (void *) 0);
3414 * Turn on quelling of pseudo message.
3416 if(F_ON(F_QUELL_INTERNAL_MSG,ps_global))
3417 mail_parameters(NULL, SET_USERHASNOLIFE, (void *) 1);
3419 l = F_ON(F_MULNEWSRC_HOSTNAMES_AS_TYPED,ps_global) ? 0L : 1L;
3420 mail_parameters(NULL, SET_NEWSRCCANONHOST, (void *) l);
3422 ps->pass_ctrl_chars = F_ON(F_PASS_CONTROL_CHARS,ps_global) ? 1 : 0;
3423 ps->pass_c1_ctrl_chars = F_ON(F_PASS_C1_CONTROL_CHARS,ps_global) ? 1 : 0;
3425 #ifndef _WINDOWS
3426 if(F_ON(F_QUELL_BEZERK_TIMEZONE,ps_global))
3427 mail_parameters(NULL, SET_NOTIMEZONES, (void *) 1);
3428 #endif
3430 if(F_ON(F_USE_FK, ps))
3431 ps->orig_use_fkeys = 1;
3433 /* Will we have to build a new list? */
3434 if(!(old_growth || hir || osr))
3435 return;
3438 * Build a new list for feature-list. The only reason we ever need to
3439 * do this is if one of the obsolete options is being converted
3440 * into a feature-list item, and it isn't already included in the user's
3441 * feature-list.
3443 i = 0;
3444 for(p = LVAL(&ps->vars[V_FEATURE_LIST], Main);
3445 p && (q = *p); p++){
3446 /* already have it or cancelled it, don't need to add later */
3447 if(hir && (strucmp(q, "include-header-in-reply") == 0 ||
3448 strucmp(q, "no-include-header-in-reply") == 0)){
3449 hir = 0;
3450 }else if(osr && (strucmp(q, "signature-at-bottom") == 0 ||
3451 strucmp(q, "no-signature-at-bottom") == 0)){
3452 osr = 0;
3453 }else if(old_growth && (strucmp(q, "old-growth") == 0 ||
3454 strucmp(q, "no-old-growth") == 0)){
3455 old_growth = 0;
3457 lvalue[i++] = cpystr(q);
3460 /* check to see if we still need to build a new list */
3461 if(!(old_growth || hir || osr))
3462 return;
3464 if(hir)
3465 lvalue[i++] = "include-header-in-reply";
3466 if(osr)
3467 lvalue[i++] = "signature-at-bottom";
3468 if(old_growth)
3469 lvalue[i++] = "old-growth";
3470 lvalue[i] = NULL;
3471 set_variable_list(V_FEATURE_LIST, lvalue, TRUE, Main);
3475 void
3476 set_current_pattern_vals(struct pine *ps)
3478 struct variable *vars = ps->vars;
3480 set_current_val(&vars[V_PATTERNS], TRUE, TRUE);
3481 set_current_val(&vars[V_PAT_ROLES], TRUE, TRUE);
3482 set_current_val(&vars[V_PAT_FILTS], TRUE, TRUE);
3483 set_current_val(&vars[V_PAT_FILTS_OLD], TRUE, TRUE);
3484 set_current_val(&vars[V_PAT_SCORES], TRUE, TRUE);
3485 set_current_val(&vars[V_PAT_SCORES_OLD], TRUE, TRUE);
3486 set_current_val(&vars[V_PAT_INCOLS], TRUE, TRUE);
3487 set_current_val(&vars[V_PAT_OTHER], TRUE, TRUE);
3488 set_current_val(&vars[V_PAT_SRCH], TRUE, TRUE);
3491 * If old pattern variable (V_PATTERNS) is set and the new ones aren't
3492 * in the config file, then convert the old data into the new variables.
3493 * It isn't quite that simple, though, because we don't store unset
3494 * variables in remote pinercs. Check for the variables but if we
3495 * don't find any of them, also check the version number. This change was
3496 * made in version 4.30. We could just check that except that we're
3497 * worried somebody will make an incompatible version number change in
3498 * their local version, and will break this. So we check both the
3499 * version # and the var_in_pinerc things to be safer.
3501 if(vars[V_PATTERNS].current_val.l
3502 && vars[V_PATTERNS].current_val.l[0]
3503 && !var_in_pinerc(vars[V_PAT_ROLES].name)
3504 && !var_in_pinerc(vars[V_PAT_FILTS].name)
3505 && !var_in_pinerc(vars[V_PAT_FILTS_OLD].name)
3506 && !var_in_pinerc(vars[V_PAT_SCORES].name)
3507 && !var_in_pinerc(vars[V_PAT_SCORES_OLD].name)
3508 && !var_in_pinerc(vars[V_PAT_INCOLS].name)
3509 && isdigit((unsigned char) ps->pine_pre_vers[0])
3510 && ps->pine_pre_vers[1] == '.'
3511 && isdigit((unsigned char) ps->pine_pre_vers[2])
3512 && isdigit((unsigned char) ps->pine_pre_vers[3])
3513 && strncmp(ps->pine_pre_vers, "4.30", 4) < 0){
3514 convert_pattern_data();
3518 * Otherwise, if FILTS_OLD is set and FILTS isn't in the config file,
3519 * convert FILTS_OLD to FILTS. Same for SCORES.
3520 * The reason FILTS was changed was so we could change the
3521 * semantics of how rules work when there are pieces in the rule that
3522 * we don't understand. At the same time as the FILTS change we added
3523 * a rule to detect 8bitSubjects. So a user might have a filter that
3524 * deletes messages with 8bitSubjects. The problem is that that same
3525 * filter in a FILTS_OLD pine would match because it would ignore the
3526 * 8bitSubject part of the pattern and match on the rest. So we changed
3527 * the semantics so that rules with unknown bits would be ignored
3528 * instead of used. We had to change variable names at the same time
3529 * because we were adding the 8bit thing and the old pines are still
3530 * out there. Filters and Scores can both be dangerous. Roles, Colors,
3531 * and Other seem less dangerous so not worth adding a new variable.
3532 * This was changed in 4.50.
3534 else{
3535 if(vars[V_PAT_FILTS_OLD].current_val.l
3536 && vars[V_PAT_FILTS_OLD].current_val.l[0]
3537 && !var_in_pinerc(vars[V_PAT_FILTS].name)
3538 && !var_in_pinerc(vars[V_PAT_SCORES].name)
3539 && isdigit((unsigned char) ps->pine_pre_vers[0])
3540 && ps->pine_pre_vers[1] == '.'
3541 && isdigit((unsigned char) ps->pine_pre_vers[2])
3542 && isdigit((unsigned char) ps->pine_pre_vers[3])
3543 && strncmp(ps->pine_pre_vers, "4.50", 4) < 0){
3544 convert_filts_pattern_data();
3547 if(vars[V_PAT_SCORES_OLD].current_val.l
3548 && vars[V_PAT_SCORES_OLD].current_val.l[0]
3549 && !var_in_pinerc(vars[V_PAT_FILTS].name)
3550 && !var_in_pinerc(vars[V_PAT_SCORES].name)
3551 && isdigit((unsigned char) ps->pine_pre_vers[0])
3552 && ps->pine_pre_vers[1] == '.'
3553 && isdigit((unsigned char) ps->pine_pre_vers[2])
3554 && isdigit((unsigned char) ps->pine_pre_vers[3])
3555 && strncmp(ps->pine_pre_vers, "4.50", 4) < 0){
3556 convert_scores_pattern_data();
3560 if(vars[V_PAT_ROLES].post_user_val.l)
3561 ps_global->ew_for_role_take = Post;
3562 else
3563 ps_global->ew_for_role_take = Main;
3565 if(vars[V_PAT_FILTS].post_user_val.l)
3566 ps_global->ew_for_filter_take = Post;
3567 else
3568 ps_global->ew_for_filter_take = Main;
3570 if(vars[V_PAT_SCORES].post_user_val.l)
3571 ps_global->ew_for_score_take = Post;
3572 else
3573 ps_global->ew_for_score_take = Main;
3575 if(vars[V_PAT_INCOLS].post_user_val.l)
3576 ps_global->ew_for_incol_take = Post;
3577 else
3578 ps_global->ew_for_incol_take = Main;
3580 if(vars[V_PAT_OTHER].post_user_val.l)
3581 ps_global->ew_for_other_take = Post;
3582 else
3583 ps_global->ew_for_other_take = Main;
3585 if(vars[V_PAT_SRCH].post_user_val.l)
3586 ps_global->ew_for_srch_take = Post;
3587 else
3588 ps_global->ew_for_srch_take = Main;
3593 * Foreach of the config files;
3594 * transfer the data to the new variables.
3596 void
3597 convert_pattern_data(void)
3599 convert_pinerc_patterns(PAT_USE_MAIN);
3600 convert_pinerc_patterns(PAT_USE_POST);
3604 void
3605 convert_filts_pattern_data(void)
3607 convert_pinerc_filts_patterns(PAT_USE_MAIN);
3608 convert_pinerc_filts_patterns(PAT_USE_POST);
3612 void
3613 convert_scores_pattern_data(void)
3615 convert_pinerc_scores_patterns(PAT_USE_MAIN);
3616 convert_pinerc_scores_patterns(PAT_USE_POST);
3621 * Foreach of the four variables, transfer the data for this config file
3622 * from the old patterns variable. We don't have to convert OTHER patterns
3623 * or SRCH patterns because they didn't exist in pines without patterns-other.
3625 * If the original variable had patlines with type File then we convert
3626 * all of the individual patterns to type Lit, because each pattern can
3627 * be of any category. Lit patterns are better tested, anyway.
3629 void
3630 convert_pinerc_patterns(long int use_flags)
3632 long old_rflags;
3633 long rflags;
3634 PAT_S *pat;
3635 PAT_STATE pstate;
3636 ACTION_S *act;
3638 old_rflags = (ROLE_OLD_PAT | use_flags);
3640 rflags = 0L;
3641 if(any_patterns(old_rflags, &pstate)){
3642 dprint((2, "converting old patterns to new (%s)\n", (use_flags == PAT_USE_MAIN) ? "Main" : "Post"));
3643 for(pat = first_pattern(&pstate);
3644 pat;
3645 pat = next_pattern(&pstate)){
3646 if((act = pat->action) != NULL){
3647 if(act->is_a_role &&
3648 add_to_pattern(pat, ROLE_DO_ROLES | use_flags))
3649 rflags |= ROLE_DO_ROLES;
3650 if(act->is_a_incol &&
3651 add_to_pattern(pat, ROLE_DO_INCOLS | use_flags))
3652 rflags |= ROLE_DO_INCOLS;
3653 if(act->is_a_score &&
3654 add_to_pattern(pat, ROLE_DO_SCORES | use_flags))
3655 rflags |= ROLE_DO_SCORES;
3656 if(act->is_a_filter &&
3657 add_to_pattern(pat, ROLE_DO_FILTER | use_flags))
3658 rflags |= ROLE_DO_FILTER;
3662 if(rflags)
3663 if(write_patterns(rflags | use_flags))
3664 dprint((1,
3665 "Trouble converting patterns to new variable\n"));
3671 * If the original variable had patlines with type File then we convert
3672 * all of the individual patterns to type Lit, because each pattern can
3673 * be of any category. Lit patterns are better tested, anyway.
3675 void
3676 convert_pinerc_filts_patterns(long int use_flags)
3678 long old_rflags;
3679 long rflags;
3680 PAT_S *pat;
3681 PAT_STATE pstate;
3682 ACTION_S *act;
3684 old_rflags = (ROLE_OLD_FILT | use_flags);
3686 rflags = 0L;
3687 if(any_patterns(old_rflags, &pstate)){
3688 dprint((2, "converting old filter patterns to new (%s)\n", (use_flags == PAT_USE_MAIN) ? "Main" : "Post"));
3689 for(pat = first_pattern(&pstate);
3690 pat;
3691 pat = next_pattern(&pstate)){
3692 if((act = pat->action) != NULL){
3693 if(act->is_a_filter &&
3694 add_to_pattern(pat, ROLE_DO_FILTER | use_flags))
3695 rflags |= ROLE_DO_FILTER;
3699 if(rflags)
3700 if(write_patterns(rflags | use_flags))
3701 dprint((1,
3702 "Trouble converting filter patterns to new variable\n"));
3708 * If the original variable had patlines with type File then we convert
3709 * all of the individual patterns to type Lit, because each pattern can
3710 * be of any category. Lit patterns are better tested, anyway.
3712 void
3713 convert_pinerc_scores_patterns(long int use_flags)
3715 long old_rflags;
3716 long rflags;
3717 PAT_S *pat;
3718 PAT_STATE pstate;
3719 ACTION_S *act;
3721 old_rflags = (ROLE_OLD_SCORE | use_flags);
3723 rflags = 0L;
3724 if(any_patterns(old_rflags, &pstate)){
3725 dprint((2, "converting old scores patterns to new (%s)\n", (use_flags == PAT_USE_MAIN) ? "Main" : "Post"));
3726 for(pat = first_pattern(&pstate);
3727 pat;
3728 pat = next_pattern(&pstate)){
3729 if((act = pat->action) != NULL){
3730 if(act->is_a_score &&
3731 add_to_pattern(pat, ROLE_DO_SCORES | use_flags))
3732 rflags |= ROLE_DO_SCORES;
3736 if(rflags)
3737 if(write_patterns(rflags | use_flags))
3738 dprint((1,
3739 "Trouble converting scores patterns to new variable\n"));
3745 * set_old_growth_bits - Command used to set or unset old growth set
3746 * of features
3748 void
3749 set_old_growth_bits(struct pine *ps, int val)
3751 int i;
3753 for(i = 1; i <= F_FEATURE_LIST_COUNT; i++)
3754 if(test_old_growth_bits(ps, i))
3755 F_SET(i, ps, val);
3761 * test_old_growth_bits - Test to see if all the old growth bits are on,
3762 * *or* if a particular feature index is in the old
3763 * growth set.
3765 * WEIRD ALERT: if index == F_OLD_GROWTH bit values are tested
3766 * otherwise a bits existence in the set is tested!!!
3768 * BUG: this will break if an old growth feature number is ever >= 32.
3771 test_old_growth_bits(struct pine *ps, int index)
3774 * this list defines F_OLD_GROWTH set
3776 static unsigned long old_growth_bits = ((1 << F_ENABLE_FULL_HDR) |
3777 (1 << F_ENABLE_PIPE) |
3778 (1 << F_ENABLE_TAB_COMPLETE) |
3779 (1 << F_QUIT_WO_CONFIRM) |
3780 (1 << F_ENABLE_JUMP) |
3781 (1 << F_ENABLE_ALT_ED) |
3782 (1 << F_ENABLE_BOUNCE) |
3783 (1 << F_ENABLE_AGG_OPS) |
3784 (1 << F_ENABLE_FLAG) |
3785 (1 << F_CAN_SUSPEND));
3786 if(index >= 32)
3787 return(0);
3789 if(index == F_OLD_GROWTH){
3790 for(index = 1; index <= F_FEATURE_LIST_COUNT; index++)
3791 if(((1 << index) & old_growth_bits) && F_OFF(index, ps))
3792 return(0);
3794 return(1);
3796 else
3797 return((1 << index) & old_growth_bits);
3802 * Side effect is that the appropriate global variable is set, and the
3803 * appropriate current_val is set.
3805 void
3806 cur_rule_value(struct variable *var, int expand, int cmdline)
3808 int i;
3809 NAMEVAL_S *v;
3811 set_current_val(var, expand, cmdline);
3813 if(var == &ps_global->vars[V_SAVED_MSG_NAME_RULE]){
3814 if(ps_global->VAR_SAVED_MSG_NAME_RULE)
3815 for(i = 0; (v = save_msg_rules(i)); i++)
3816 if(!strucmp(ps_global->VAR_SAVED_MSG_NAME_RULE, S_OR_L(v))){
3817 ps_global->save_msg_rule = v->value;
3818 break;
3821 #ifndef _WINDOWS
3822 else if(var == &ps_global->vars[V_COLOR_STYLE]){
3823 if(ps_global->VAR_COLOR_STYLE)
3824 for(i = 0; (v = col_style(i)); i++)
3825 if(!strucmp(ps_global->VAR_COLOR_STYLE, S_OR_L(v))){
3826 ps_global->color_style = v->value;
3827 break;
3830 #endif
3831 else if(var == &ps_global->vars[V_INDEX_COLOR_STYLE]){
3832 if(ps_global->VAR_INDEX_COLOR_STYLE)
3833 for(i = 0; (v = index_col_style(i)); i++)
3834 if(!strucmp(ps_global->VAR_INDEX_COLOR_STYLE, S_OR_L(v))){
3835 ps_global->index_color_style = v->value;
3836 break;
3839 else if(var == &ps_global->vars[V_TITLEBAR_COLOR_STYLE]){
3840 if(ps_global->VAR_TITLEBAR_COLOR_STYLE)
3841 for(i = 0; (v = titlebar_col_style(i)); i++)
3842 if(!strucmp(ps_global->VAR_TITLEBAR_COLOR_STYLE, S_OR_L(v))){
3843 ps_global->titlebar_color_style = v->value;
3844 break;
3847 else if(var == &ps_global->vars[V_FCC_RULE]){
3848 if(ps_global->VAR_FCC_RULE)
3849 for(i = 0; (v = fcc_rules(i)); i++)
3850 if(!strucmp(ps_global->VAR_FCC_RULE, S_OR_L(v))){
3851 ps_global->fcc_rule = v->value;
3852 break;
3855 else if(var == &ps_global->vars[V_GOTO_DEFAULT_RULE]){
3856 if(ps_global->VAR_GOTO_DEFAULT_RULE)
3857 for(i = 0; (v = goto_rules(i)); i++)
3858 if(!strucmp(ps_global->VAR_GOTO_DEFAULT_RULE, S_OR_L(v))){
3859 ps_global->goto_default_rule = v->value;
3860 break;
3863 else if(var == &ps_global->vars[V_INCOMING_STARTUP]){
3864 if(ps_global->VAR_INCOMING_STARTUP)
3865 for(i = 0; (v = incoming_startup_rules(i)); i++)
3866 if(!strucmp(ps_global->VAR_INCOMING_STARTUP, S_OR_L(v))){
3867 ps_global->inc_startup_rule = v->value;
3868 break;
3871 else if(var == &ps_global->vars[V_PRUNING_RULE]){
3872 if(ps_global->VAR_PRUNING_RULE)
3873 for(i = 0; (v = pruning_rules(i)); i++)
3874 if(!strucmp(ps_global->VAR_PRUNING_RULE, S_OR_L(v))){
3875 ps_global->pruning_rule = v->value;
3876 break;
3879 else if(var == &ps_global->vars[V_REOPEN_RULE]){
3880 if(ps_global->VAR_REOPEN_RULE)
3881 for(i = 0; (v = reopen_rules(i)); i++)
3882 if(!strucmp(ps_global->VAR_REOPEN_RULE, S_OR_L(v))){
3883 ps_global->reopen_rule = v->value;
3884 break;
3887 else if(var == &ps_global->vars[V_FLD_SORT_RULE]){
3888 if(ps_global->VAR_FLD_SORT_RULE)
3889 for(i = 0; (v = fld_sort_rules(i)); i++)
3890 if(!strucmp(ps_global->VAR_FLD_SORT_RULE, S_OR_L(v))){
3891 ps_global->fld_sort_rule = v->value;
3892 break;
3895 else if(var == &ps_global->vars[V_AB_SORT_RULE]){
3896 if(ps_global->VAR_AB_SORT_RULE)
3897 for(i = 0; (v = ab_sort_rules(i)); i++)
3898 if(!strucmp(ps_global->VAR_AB_SORT_RULE, S_OR_L(v))){
3899 ps_global->ab_sort_rule = v->value;
3900 break;
3903 else if(var == &ps_global->vars[V_THREAD_DISP_STYLE]){
3904 if(ps_global->VAR_THREAD_DISP_STYLE)
3905 for(i = 0; (v = thread_disp_styles(i)); i++)
3906 if(!strucmp(ps_global->VAR_THREAD_DISP_STYLE, S_OR_L(v))){
3907 ps_global->thread_disp_style = v->value;
3908 break;
3911 else if(var == &ps_global->vars[V_THREAD_INDEX_STYLE]){
3912 if(ps_global->VAR_THREAD_INDEX_STYLE)
3913 for(i = 0; (v = thread_index_styles(i)); i++)
3914 if(!strucmp(ps_global->VAR_THREAD_INDEX_STYLE, S_OR_L(v))){
3915 ps_global->thread_index_style = v->value;
3916 break;
3923 * Standard way to get at save message rules...
3925 NAMEVAL_S *
3926 save_msg_rules(int index)
3928 static NAMEVAL_S save_rules[] = {
3929 {"by-from", NULL, SAV_RULE_FROM},
3930 {"by-nick-of-from", NULL, SAV_RULE_NICK_FROM_DEF},
3931 {"by-nick-of-from-then-from", NULL, SAV_RULE_NICK_FROM},
3932 {"by-fcc-of-from", NULL, SAV_RULE_FCC_FROM_DEF},
3933 {"by-fcc-of-from-then-from", NULL, SAV_RULE_FCC_FROM},
3934 {"by-realname-of-from", NULL, SAV_RULE_RN_FROM_DEF},
3935 {"by-realname-of-from-then-from", NULL, SAV_RULE_RN_FROM},
3936 {"by-sender", NULL, SAV_RULE_SENDER},
3937 {"by-nick-of-sender", NULL, SAV_RULE_NICK_SENDER_DEF},
3938 {"by-nick-of-sender-then-sender", NULL, SAV_RULE_NICK_SENDER},
3939 {"by-fcc-of-sender", NULL, SAV_RULE_FCC_SENDER_DEF},
3940 {"by-fcc-of-sender-then-sender", NULL, SAV_RULE_FCC_SENDER},
3941 {"by-realname-of-sender", NULL, SAV_RULE_RN_SENDER_DEF},
3942 {"by-realname-of-sender-then-sender", NULL, SAV_RULE_RN_SENDER},
3943 {"by-recipient", NULL, SAV_RULE_RECIP},
3944 {"by-nick-of-recip", NULL, SAV_RULE_NICK_RECIP_DEF},
3945 {"by-nick-of-recip-then-recip", NULL, SAV_RULE_NICK_RECIP},
3946 {"by-fcc-of-recip", NULL, SAV_RULE_FCC_RECIP_DEF},
3947 {"by-fcc-of-recip-then-recip", NULL, SAV_RULE_FCC_RECIP},
3948 {"by-realname-of-recip", NULL, SAV_RULE_RN_RECIP_DEF},
3949 {"by-realname-of-recip-then-recip", NULL, SAV_RULE_RN_RECIP},
3950 {"by-replyto", NULL, SAV_RULE_REPLYTO},
3951 {"by-nick-of-replyto", NULL, SAV_RULE_NICK_REPLYTO_DEF},
3952 {"by-nick-of-replyto-then-replyto", NULL, SAV_RULE_NICK_REPLYTO},
3953 {"by-fcc-of-replyto", NULL, SAV_RULE_FCC_REPLYTO_DEF},
3954 {"by-fcc-of-replyto-then-replyto", NULL, SAV_RULE_FCC_REPLYTO},
3955 {"by-realname-of-replyto", NULL, SAV_RULE_RN_REPLYTO_DEF},
3956 {"by-realname-of-replyto-then-replyto", NULL, SAV_RULE_RN_REPLYTO},
3957 {"last-folder-used", NULL, SAV_RULE_LAST},
3958 {"default-folder", NULL, SAV_RULE_DEFLT}
3961 return((index >= 0 && index < (sizeof(save_rules)/sizeof(save_rules[0])))
3962 ? &save_rules[index] : NULL);
3967 * Standard way to get at fcc rules...
3969 NAMEVAL_S *
3970 fcc_rules(int index)
3972 static NAMEVAL_S f_rules[] = {
3973 {"default-fcc", NULL, FCC_RULE_DEFLT},
3974 {"last-fcc-used", NULL, FCC_RULE_LAST},
3975 {"by-recipient", NULL, FCC_RULE_RECIP},
3976 {"by-nickname", NULL, FCC_RULE_NICK},
3977 {"by-nick-then-recip", NULL, FCC_RULE_NICK_RECIP},
3978 {"current-folder", NULL, FCC_RULE_CURRENT}
3981 return((index >= 0 && index < (sizeof(f_rules)/sizeof(f_rules[0])))
3982 ? &f_rules[index] : NULL);
3987 * Standard way to get at addrbook sort rules...
3989 NAMEVAL_S *
3990 ab_sort_rules(int index)
3992 static NAMEVAL_S ab_rules[] = {
3993 {"fullname-with-lists-last", NULL, AB_SORT_RULE_FULL_LISTS},
3994 {"fullname", NULL, AB_SORT_RULE_FULL},
3995 {"nickname-with-lists-last", NULL, AB_SORT_RULE_NICK_LISTS},
3996 {"nickname", NULL, AB_SORT_RULE_NICK},
3997 {"dont-sort", NULL, AB_SORT_RULE_NONE}
4000 return((index >= 0 && index < (sizeof(ab_rules)/sizeof(ab_rules[0])))
4001 ? &ab_rules[index] : NULL);
4006 * Standard way to get at color styles.
4008 NAMEVAL_S *
4009 col_style(int index)
4011 static NAMEVAL_S col_styles[] = {
4012 {"no-color", NULL, COL_NONE},
4013 {"use-termdef", NULL, COL_TERMDEF},
4014 {"force-ansi-8color", NULL, COL_ANSI8},
4015 {"force-ansi-16color", NULL, COL_ANSI16},
4016 {"force-xterm-256color", NULL, COL_ANSI256}
4019 return((index >= 0 && index < (sizeof(col_styles)/sizeof(col_styles[0])))
4020 ? &col_styles[index] : NULL);
4025 * Standard way to get at index color styles.
4027 NAMEVAL_S *
4028 index_col_style(int index)
4030 static NAMEVAL_S ind_col_styles[] = {
4031 {"flip-colors", NULL, IND_COL_FLIP},
4032 {"reverse", NULL, IND_COL_REV},
4033 {"reverse-fg", NULL, IND_COL_FG},
4034 {"reverse-fg-no-ambiguity", NULL, IND_COL_FG_NOAMBIG},
4035 {"reverse-bg", NULL, IND_COL_BG},
4036 {"reverse-bg-no-ambiguity", NULL, IND_COL_BG_NOAMBIG}
4039 return((index >= 0 && index < (sizeof(ind_col_styles)/sizeof(ind_col_styles[0]))) ? &ind_col_styles[index] : NULL);
4044 * Standard way to get at titlebar color styles.
4046 NAMEVAL_S *
4047 titlebar_col_style(int index)
4049 static NAMEVAL_S tbar_col_styles[] = {
4050 {"default", NULL, TBAR_COLOR_DEFAULT},
4051 {"indexline", NULL, TBAR_COLOR_INDEXLINE},
4052 {"reverse-indexline", NULL, TBAR_COLOR_REV_INDEXLINE}
4055 return((index >= 0 && index < (sizeof(tbar_col_styles)/sizeof(tbar_col_styles[0]))) ? &tbar_col_styles[index] : NULL);
4060 * Standard way to get at folder sort rules...
4062 NAMEVAL_S *
4063 fld_sort_rules(int index)
4065 static NAMEVAL_S fdl_rules[] = {
4066 {"alphabetical", NULL, FLD_SORT_ALPHA},
4067 {"alpha-with-dirs-last", NULL, FLD_SORT_ALPHA_DIR_LAST},
4068 {"alpha-with-dirs-first", NULL, FLD_SORT_ALPHA_DIR_FIRST}
4071 return((index >= 0 && index < (sizeof(fdl_rules)/sizeof(fdl_rules[0])))
4072 ? &fdl_rules[index] : NULL);
4077 * Standard way to get at incoming startup rules...
4079 NAMEVAL_S *
4080 incoming_startup_rules(int index)
4082 static NAMEVAL_S is_rules[] = {
4083 {"first-unseen", NULL, IS_FIRST_UNSEEN},
4084 {"first-recent", NULL, IS_FIRST_RECENT},
4085 {"first-important", NULL, IS_FIRST_IMPORTANT},
4086 {"first-important-or-unseen", NULL, IS_FIRST_IMPORTANT_OR_UNSEEN},
4087 {"first-important-or-recent", NULL, IS_FIRST_IMPORTANT_OR_RECENT},
4088 {"first", NULL, IS_FIRST},
4089 {"last", NULL, IS_LAST}
4092 return((index >= 0 && index < (sizeof(is_rules)/sizeof(is_rules[0])))
4093 ? &is_rules[index] : NULL);
4097 NAMEVAL_S *
4098 startup_rules(int index)
4100 static NAMEVAL_S is2_rules[] = {
4101 {"first-unseen", NULL, IS_FIRST_UNSEEN},
4102 {"first-recent", NULL, IS_FIRST_RECENT},
4103 {"first-important", NULL, IS_FIRST_IMPORTANT},
4104 {"first-important-or-unseen", NULL, IS_FIRST_IMPORTANT_OR_UNSEEN},
4105 {"first-important-or-recent", NULL, IS_FIRST_IMPORTANT_OR_RECENT},
4106 {"first", NULL, IS_FIRST},
4107 {"last", NULL, IS_LAST},
4108 {"default", NULL, IS_NOTSET}
4111 return((index >= 0 && index < (sizeof(is2_rules)/sizeof(is2_rules[0])))
4112 ? &is2_rules[index] : NULL);
4117 * Standard way to get at pruning-rule values.
4119 NAMEVAL_S *
4120 pruning_rules(int index)
4122 static NAMEVAL_S pr_rules[] = {
4123 {"ask about rename, ask about deleting","ask-ask", PRUNE_ASK_AND_ASK},
4124 {"ask about rename, don't delete", "ask-no", PRUNE_ASK_AND_NO},
4125 {"always rename, ask about deleting", "yes-ask", PRUNE_YES_AND_ASK},
4126 {"always rename, don't delete", "yes-no", PRUNE_YES_AND_NO},
4127 {"don't rename, ask about deleting", "no-ask", PRUNE_NO_AND_ASK},
4128 {"don't rename, don't delete", "no-no", PRUNE_NO_AND_NO}
4131 return((index >= 0 && index < (sizeof(pr_rules)/sizeof(pr_rules[0])))
4132 ? &pr_rules[index] : NULL);
4137 * Standard way to get at reopen-rule values.
4139 NAMEVAL_S *
4140 reopen_rules(int index)
4142 static NAMEVAL_S ro_rules[] = {
4143 /* TRANSLATORS: short description of a feature option */
4144 {"Always reopen", "yes-yes",
4145 REOPEN_YES_YES},
4146 /* TRANSLATORS: short description of a feature option, default in brackets */
4147 {"Yes for POP/NNTP, Ask about other remote [Yes]", "yes-ask-y",
4148 REOPEN_YES_ASK_Y},
4149 /* TRANSLATORS: short description of a feature option, default in brackets */
4150 {"Yes for POP/NNTP, Ask about other remote [No]", "yes-ask-n",
4151 REOPEN_YES_ASK_N},
4152 /* TRANSLATORS: short description of a feature option */
4153 {"Yes for POP/NNTP, No for other remote", "yes-no",
4154 REOPEN_YES_NO},
4155 /* TRANSLATORS: short description of a feature option, default in brackets */
4156 {"Always ask [Yes]", "ask-ask-y",
4157 REOPEN_ASK_ASK_Y},
4158 /* TRANSLATORS: short description of a feature option, default in brackets */
4159 {"Always ask [No]", "ask-ask-n",
4160 REOPEN_ASK_ASK_N},
4161 /* TRANSLATORS: short description of a feature option, default in brackets */
4162 {"Ask about POP/NNTP [Yes], No for other remote", "ask-no-y",
4163 REOPEN_ASK_NO_Y},
4164 /* TRANSLATORS: short description of a feature option, default in brackets */
4165 {"Ask about POP/NNTP [No], No for other remote", "ask-no-n",
4166 REOPEN_ASK_NO_N},
4167 /* TRANSLATORS: short description of a feature option */
4168 {"Never reopen", "no-no",
4169 REOPEN_NO_NO},
4172 return((index >= 0 && index < (sizeof(ro_rules)/sizeof(ro_rules[0])))
4173 ? &ro_rules[index] : NULL);
4178 * Standard way to get at thread_disp_style values.
4180 NAMEVAL_S *
4181 thread_disp_styles(int index)
4183 static NAMEVAL_S td_styles[] = {
4184 {"none", "none", THREAD_NONE},
4185 {"show-thread-structure", "struct", THREAD_STRUCT},
4186 {"mutt-like", "mutt", THREAD_MUTTLIKE},
4187 {"indent-subject-1", "subj1", THREAD_INDENT_SUBJ1},
4188 {"indent-subject-2", "subj2", THREAD_INDENT_SUBJ2},
4189 {"indent-from-1", "from1", THREAD_INDENT_FROM1},
4190 {"indent-from-2", "from2", THREAD_INDENT_FROM2},
4191 {"show-structure-in-from", "struct-from", THREAD_STRUCT_FROM}
4194 return((index >= 0 && index < (sizeof(td_styles)/sizeof(td_styles[0])))
4195 ? &td_styles[index] : NULL);
4200 * Standard way to get at thread_index_style values.
4202 NAMEVAL_S *
4203 thread_index_styles(int index)
4205 static NAMEVAL_S ti_styles[] = {
4206 {"regular-index-with-expanded-threads", "exp", THRDINDX_EXP},
4207 {"regular-index-with-collapsed-threads","coll", THRDINDX_COLL},
4208 {"separate-index-screen-always", "sep", THRDINDX_SEP},
4209 {"separate-index-screen-except-for-single-messages","sep-auto",
4210 THRDINDX_SEP_AUTO}
4213 return((index >= 0 && index < (sizeof(ti_styles)/sizeof(ti_styles[0])))
4214 ? &ti_styles[index] : NULL);
4219 * Standard way to get at goto default rules...
4221 NAMEVAL_S *
4222 goto_rules(int index)
4224 static NAMEVAL_S g_rules[] = {
4225 {"folder-in-first-collection", NULL, GOTO_FIRST_CLCTN},
4226 {"inbox-or-folder-in-first-collection", NULL, GOTO_INBOX_FIRST_CLCTN},
4227 {"inbox-or-folder-in-recent-collection", NULL, GOTO_INBOX_RECENT_CLCTN},
4228 {"first-collection-with-inbox-default", NULL, GOTO_FIRST_CLCTN_DEF_INBOX},
4229 {"most-recent-folder", NULL, GOTO_LAST_FLDR}
4232 return((index >= 0 && index < (sizeof(g_rules)/sizeof(g_rules[0])))
4233 ? &g_rules[index] : NULL);
4237 NAMEVAL_S *
4238 pat_fldr_types(int index)
4240 static NAMEVAL_S pat_fldr_list[] = {
4241 {"Any", "ANY", FLDR_ANY},
4242 {"News", "NEWS", FLDR_NEWS},
4243 {"Email", "EMAIL", FLDR_EMAIL},
4244 {"Specific (Enter Incoming Nicknames or use ^T)", "SPEC", FLDR_SPECIFIC}
4247 return((index >= 0 &&
4248 index < (sizeof(pat_fldr_list)/sizeof(pat_fldr_list[0])))
4249 ? &pat_fldr_list[index] : NULL);
4253 NAMEVAL_S *
4254 inabook_fldr_types(int indexarg)
4256 static NAMEVAL_S inabook_fldr_list[] = {
4257 {"Don't care, always matches", "E", IAB_EITHER},
4258 {"Yes, in any address book", "YES", IAB_YES},
4259 {"No, not in any address book", "NO", IAB_NO},
4260 {"Yes, in specific address books", "SYES", IAB_SPEC_YES},
4261 {"No, not in any of specific address books", "SNO", IAB_SPEC_NO}
4264 int index = indexarg & IAB_TYPE_MASK;
4266 return((index >= 0 &&
4267 index < (sizeof(inabook_fldr_list)/sizeof(inabook_fldr_list[0])))
4268 ? &inabook_fldr_list[index] : NULL);
4272 NAMEVAL_S *
4273 filter_types(int index)
4275 static NAMEVAL_S filter_type_list[] = {
4276 {"Just Set Message Status", "NONE", FILTER_STATE},
4277 {"Delete", "DEL", FILTER_KILL},
4278 {"Move (Enter folder name(s) in primary collection, or use ^T)",
4279 "FLDR", FILTER_FOLDER}
4282 return((index >= 0 &&
4283 index < (sizeof(filter_type_list)/sizeof(filter_type_list[0])))
4284 ? &filter_type_list[index] : NULL);
4288 NAMEVAL_S *
4289 role_repl_types(int index)
4291 static NAMEVAL_S role_repl_list[] = {
4292 {"Never", "NO", ROLE_REPL_NO},
4293 {"With confirmation", "YES", ROLE_REPL_YES},
4294 {"Without confirmation", "NC", ROLE_REPL_NOCONF}
4297 return((index >= 0 &&
4298 index < (sizeof(role_repl_list)/sizeof(role_repl_list[0])))
4299 ? &role_repl_list[index] : NULL);
4303 NAMEVAL_S *
4304 role_forw_types(int index)
4306 static NAMEVAL_S role_forw_list[] = {
4307 {"Never", "NO", ROLE_FORW_NO},
4308 {"With confirmation", "YES", ROLE_FORW_YES},
4309 {"Without confirmation", "NC", ROLE_FORW_NOCONF}
4312 return((index >= 0 &&
4313 index < (sizeof(role_forw_list)/sizeof(role_forw_list[0])))
4314 ? &role_forw_list[index] : NULL);
4318 NAMEVAL_S *
4319 role_comp_types(int index)
4321 static NAMEVAL_S role_comp_list[] = {
4322 {"Never", "NO", ROLE_COMP_NO},
4323 {"With confirmation", "YES", ROLE_COMP_YES},
4324 {"Without confirmation", "NC", ROLE_COMP_NOCONF}
4327 return((index >= 0 &&
4328 index < (sizeof(role_comp_list)/sizeof(role_comp_list[0])))
4329 ? &role_comp_list[index] : NULL);
4333 NAMEVAL_S *
4334 role_status_types(int index)
4336 static NAMEVAL_S role_status_list[] = {
4337 {"Don't care, always matches", "E", PAT_STAT_EITHER},
4338 {"Yes", "YES", PAT_STAT_YES},
4339 {"No", "NO", PAT_STAT_NO}
4342 return((index >= 0 &&
4343 index < (sizeof(role_status_list)/sizeof(role_status_list[0])))
4344 ? &role_status_list[index] : NULL);
4348 NAMEVAL_S *
4349 msg_state_types(int index)
4351 static NAMEVAL_S msg_state_list[] = {
4352 {"Don't change it", "LV", ACT_STAT_LEAVE},
4353 {"Set this state", "SET", ACT_STAT_SET},
4354 {"Clear this state", "CLR", ACT_STAT_CLEAR}
4357 return((index >= 0 &&
4358 index < (sizeof(msg_state_list)/sizeof(msg_state_list[0])))
4359 ? &msg_state_list[index] : NULL);
4363 #ifdef ENABLE_LDAP
4364 NAMEVAL_S *
4365 ldap_search_rules(int index)
4367 static NAMEVAL_S ldap_search_list[] = {
4368 {"contains", NULL, LDAP_SRCH_CONTAINS},
4369 {"equals", NULL, LDAP_SRCH_EQUALS},
4370 {"begins-with", NULL, LDAP_SRCH_BEGINS},
4371 {"ends-with", NULL, LDAP_SRCH_ENDS}
4374 return((index >= 0 &&
4375 index < (sizeof(ldap_search_list)/sizeof(ldap_search_list[0])))
4376 ? &ldap_search_list[index] : NULL);
4380 NAMEVAL_S *
4381 ldap_search_types(int index)
4383 static NAMEVAL_S ldap_types_list[] = {
4384 {"name", NULL, LDAP_TYPE_CN},
4385 {"surname", NULL, LDAP_TYPE_SUR},
4386 {"givenname", NULL, LDAP_TYPE_GIVEN},
4387 {"email", NULL, LDAP_TYPE_EMAIL},
4388 {"name-or-email", NULL, LDAP_TYPE_CN_EMAIL},
4389 {"surname-or-givenname", NULL, LDAP_TYPE_SUR_GIVEN},
4390 {"sur-or-given-or-name-or-email", NULL, LDAP_TYPE_SEVERAL}
4393 return((index >= 0 &&
4394 index < (sizeof(ldap_types_list)/sizeof(ldap_types_list[0])))
4395 ? &ldap_types_list[index] : NULL);
4399 NAMEVAL_S *
4400 ldap_search_scope(int index)
4402 static NAMEVAL_S ldap_scope_list[] = {
4403 {"base", NULL, LDAP_SCOPE_BASE},
4404 {"onelevel", NULL, LDAP_SCOPE_ONELEVEL},
4405 {"subtree", NULL, LDAP_SCOPE_SUBTREE}
4408 return((index >= 0 &&
4409 index < (sizeof(ldap_scope_list)/sizeof(ldap_scope_list[0])))
4410 ? &ldap_scope_list[index] : NULL);
4412 #endif
4416 * Choose from the global default, command line args, pinerc values to set
4417 * the actual value of the variable that we will use. Start at the top
4418 * and work down from higher to lower precedence.
4419 * For lists, we may inherit values from lower precedence
4420 * versions if that's the way the user specifies it.
4421 * The user can put INHERIT_DEFAULT as the first entry in a list and that
4422 * means it will inherit the current values, for example the values
4423 * from the global_val, or the value from the main_user_val could be
4424 * inherited in the post_user_val.
4426 void
4427 set_current_val(struct variable *var, int expand, int cmdline)
4429 int is_set[5], is_inherit[5];
4430 int i, j, k, cnt, start;
4431 char **tmp, **t, **list[5];
4432 char *p;
4434 dprint((9,
4435 "set_current_val(var=%s%s, expand=%d, cmdline=%d)\n",
4436 (var && var->name) ? var->name : "?",
4437 (var && var->is_list) ? " (list)" : "",
4438 expand, cmdline));
4440 if(!var)
4441 return;
4443 if(var->is_list){ /* variable is a list */
4445 for(j = 0; j < 5; j++){
4446 t = j==0 ? var->global_val.l :
4447 j==1 ? var->main_user_val.l :
4448 j==2 ? var->post_user_val.l :
4449 j==3 ? ((cmdline) ? var->cmdline_val.l : NULL) :
4450 var->fixed_val.l;
4452 is_set[j] = is_inherit[j] = 0;
4453 list[j] = NULL;
4455 if(t){
4456 if(!expand){
4457 is_set[j]++;
4458 list[j] = t;
4460 else{
4461 for(i = 0; t[i]; i++){
4462 if(expand_variables(tmp_20k_buf, SIZEOF_20KBUF, t[i],
4463 0)){
4464 /* successful expand */
4465 is_set[j]++;
4466 list[j] = t;
4467 break;
4472 if(list[j] && list[j][0] && !strcmp(list[j][0],INHERIT))
4473 is_inherit[j]++;
4477 cnt = 0;
4478 start = 0;
4479 /* count how many items in current_val list */
4480 /* Admin wants default, which is global_val. */
4481 if(var->is_fixed && var->fixed_val.l == NULL){
4482 cnt = 0;
4483 if(is_set[0]){
4484 for(; list[0][cnt]; cnt++)
4488 else{
4489 for(j = 0; j < 5; j++){
4490 if(is_set[j]){
4491 if(!is_inherit[j]){
4492 cnt = 0; /* reset */
4493 start = j;
4496 for(i = is_inherit[j] ? 1 : 0; list[j][i]; i++)
4497 cnt++;
4502 free_list_array(&var->current_val.l); /* clean up any old values */
4504 /* check to see if anything is set */
4505 if(is_set[0] + is_set[1] + is_set[2] + is_set[3] + is_set[4] > 0){
4506 var->current_val.l = (char **)fs_get((cnt+1)*sizeof(char *));
4507 tmp = var->current_val.l;
4508 if(var->is_fixed && var->fixed_val.l == NULL){
4509 if(is_set[0]){
4510 for(i = 0; list[0][i]; i++){
4511 if(!expand)
4512 *tmp++ = cpystr(list[0][i]);
4513 else if(expand_variables(tmp_20k_buf, SIZEOF_20KBUF,
4514 list[0][i], 0))
4515 *tmp++ = cpystr(tmp_20k_buf);
4519 else{
4520 for(j = start; j < 5; j++){
4521 if(is_set[j]){
4522 for(i = is_inherit[j] ? 1 : 0; list[j][i]; i++){
4523 if(!expand)
4524 *tmp++ = cpystr(list[j][i]);
4525 else if(expand_variables(tmp_20k_buf,SIZEOF_20KBUF,
4526 list[j][i], 0))
4527 *tmp++ = cpystr(tmp_20k_buf);
4533 *tmp = NULL;
4535 else
4536 var->current_val.l = NULL;
4538 else{ /* variable is not a list */
4539 char *strvar = NULL;
4541 for(j = 0; j < 5; j++){
4543 p = j==0 ? var->fixed_val.p :
4544 j==1 ? ((cmdline) ? var->cmdline_val.p : NULL) :
4545 j==2 ? var->post_user_val.p :
4546 j==3 ? var->main_user_val.p :
4547 var->global_val.p;
4549 is_set[j] = 0;
4551 if(p){
4552 if(!expand){
4553 is_set[j]++;
4554 if(!strvar)
4555 strvar = p;
4557 else if(expand_variables(tmp_20k_buf, SIZEOF_20KBUF, p,
4558 (var == &ps_global->vars[V_MAILCAP_PATH] ||
4559 var == &ps_global->vars[V_MIMETYPE_PATH]))){
4560 is_set[j]++;
4561 if(!strvar)
4562 strvar = p;
4567 /* Admin wants default, which is global_val. */
4568 if(var->is_fixed && var->fixed_val.p == NULL)
4569 strvar = var->global_val.p;
4571 if(var->current_val.p) /* free previous value */
4572 fs_give((void **)&var->current_val.p);
4574 if(strvar){
4575 if(!expand)
4576 var->current_val.p = cpystr(strvar);
4577 else{
4578 expand_variables(tmp_20k_buf, SIZEOF_20KBUF, strvar,
4579 (var == &ps_global->vars[V_MAILCAP_PATH] ||
4580 var == &ps_global->vars[V_MIMETYPE_PATH]));
4581 var->current_val.p = cpystr(tmp_20k_buf);
4584 else
4585 var->current_val.p = NULL;
4588 if(var->is_fixed && !is_inherit[4]){
4589 char **flist;
4590 int fixed_len, user_len;
4593 * sys mgr fixed this variable and user is trying to change it
4595 for(k = 1; !(ps_global->give_fixed_warning &&
4596 ps_global->fix_fixed_warning) && k <= 3; k++){
4597 if(is_set[k]){
4598 if(var->is_list){
4599 t = k==1 ? ((cmdline) ? var->cmdline_val.l : NULL) :
4600 k==2 ? var->post_user_val.l :
4601 var->main_user_val.l;
4603 /* If same length and same contents, don't warn. */
4604 for(flist=var->fixed_val.l; flist && *flist; flist++)
4605 ;/* just counting */
4607 fixed_len = var->fixed_val.l ? (flist - var->fixed_val.l)
4608 : 0;
4609 for(flist=t; flist && *flist; flist++)
4610 ;/* just counting */
4612 user_len = t ? (flist - t) : 0;
4613 if(user_len == fixed_len){
4614 for(i=0; i < user_len; i++){
4615 for(j=0; j < user_len; j++)
4616 if(!strucmp(t[i], var->fixed_val.l[j]))
4617 break;
4619 if(j == user_len){
4620 ps_global->give_fixed_warning = 1;
4621 if(k != 1)
4622 ps_global->fix_fixed_warning = 1;
4624 break;
4628 else{
4629 ps_global->give_fixed_warning = 1;
4630 if(k != 1)
4631 ps_global->fix_fixed_warning = 1;
4634 else{
4635 p = k==1 ? ((cmdline) ? var->cmdline_val.p : NULL) :
4636 k==2 ? var->post_user_val.p :
4637 var->main_user_val.p;
4639 if((var->fixed_val.p && !p) ||
4640 (!var->fixed_val.p && p) ||
4641 (var->fixed_val.p && p && strucmp(var->fixed_val.p, p))){
4642 ps_global->give_fixed_warning = 1;
4643 if(k != 1)
4644 ps_global->fix_fixed_warning = 1;
4653 void
4654 set_news_spec_current_val(int expand, int cmdline)
4656 struct variable *newsvar = &ps_global->vars[V_NEWS_SPEC];
4657 struct variable *fvar = &ps_global->vars[V_FOLDER_SPEC];
4659 /* check to see if it has a value */
4660 set_current_val(newsvar, expand, cmdline);
4663 * If no value, we might want to fake a value. We'll do that if
4664 * there is no news collection already defined in FOLDER_SPEC and if
4665 * there is also an NNTP_SERVER defined.
4667 if(!newsvar->current_val.l && ps_global->VAR_NNTP_SERVER &&
4668 ps_global->VAR_NNTP_SERVER[0] && ps_global->VAR_NNTP_SERVER[0][0] &&
4669 !news_in_folders(fvar)){
4670 char buf[MAXPATH];
4672 newsvar->global_val.l = (char **)fs_get(2 * sizeof(char *));
4673 snprintf(buf, sizeof(buf), "{%.*s/nntp}#news.[]", sizeof(buf)-20,
4674 ps_global->VAR_NNTP_SERVER[0]);
4675 newsvar->global_val.l[0] = cpystr(buf);
4676 newsvar->global_val.l[1] = NULL;
4677 set_current_val(newsvar, expand, cmdline);
4679 * But we're going to get rid of the fake global_val in case
4680 * things change.
4682 free_list_array(&newsvar->global_val.l);
4688 * Feature-list has to be handled separately from the other variables
4689 * because it is additive. The other variables choose one of command line,
4690 * or pine.conf, or pinerc. Feature list adds them. This could easily be
4691 * converted to a general purpose routine if we add more additive variables.
4693 * This works by replacing earlier values with later ones. That is, command
4694 * line settings have higher precedence than global settings and that is
4695 * accomplished by putting the command line features after the global
4696 * features in the list. When they are processed, the last one wins.
4698 * Feature-list also has a backwards compatibility hack.
4700 void
4701 set_feature_list_current_val(struct variable *var)
4703 char **list;
4704 char **list_fixed;
4705 char no_allow[50];
4706 int i, j, k, m,
4707 elems = 0;
4709 /* count the lists so we can allocate */
4710 for(m = 0; m < 6; m++){
4711 list = m==0 ? var->global_val.l :
4712 m==1 ? var->main_user_val.l :
4713 m==2 ? var->post_user_val.l :
4714 m==3 ? ps_global->feat_list_back_compat :
4715 m==4 ? var->cmdline_val.l :
4716 var->fixed_val.l;
4717 if(list)
4718 for(i = 0; list[i]; i++)
4719 elems++;
4722 list_fixed = var->fixed_val.l;
4724 if(var->current_val.l)
4725 free_list_array(&var->current_val.l);
4727 var->current_val.l = (char **)fs_get((elems+1) * sizeof(char *));
4730 * We need to warn the user if the sys mgr has restricted him or her
4731 * from changing a feature that he or she is trying to change.
4733 * We're not catching the old-growth macro since we're just comparing
4734 * strings. That is, it works correctly, but the user won't be warned
4735 * if the user old-growth and the mgr says no-quit-without-confirm.
4738 j = 0;
4739 strncpy(no_allow, "no-", 3);
4740 strncpy(no_allow+3, feature_list_name(F_ALLOW_CHANGING_FROM), sizeof(no_allow)-3-1);
4741 no_allow[sizeof(no_allow)-1] = '\0';
4743 for(m = 0; m < 6; m++){
4744 list = m==0 ? var->global_val.l :
4745 m==1 ? var->main_user_val.l :
4746 m==2 ? var->post_user_val.l :
4747 m==3 ? ps_global->feat_list_back_compat :
4748 m==4 ? var->cmdline_val.l :
4749 var->fixed_val.l;
4750 if(list)
4751 for(i = 0; list[i]; i++){
4752 var->current_val.l[j++] = cpystr(list[i]);
4754 /* this is the warning section */
4755 if(m >= 1 && m <= 4){
4756 for(k = 0; list_fixed && list_fixed[k]; k++){
4757 char *p, *q;
4758 p = list[i];
4759 q = list_fixed[k];
4760 if(!struncmp(p, "no-", 3))
4761 p += 3;
4762 if(!struncmp(q, "no-", 3))
4763 q += 3;
4764 if(!strucmp(q, p) && strucmp(list[i], list_fixed[k])){
4765 ps_global->give_fixed_warning = 1;
4766 if(m <= 2)
4767 ps_global->fix_fixed_warning = 1;
4771 else if(m == 5 && !strucmp(list[i], no_allow))
4772 ps_global->never_allow_changing_from = 1;
4776 #ifdef NEVER_ALLOW_CHANGING_FROM
4777 ps_global->never_allow_changing_from = 1;
4778 #endif
4780 var->current_val.l[j] = NULL;
4785 /*----------------------------------------------------------------------
4787 Expand Metacharacters/variables in file-names
4789 Read input line and expand shell-variables/meta-characters
4791 <input> <replaced by>
4792 $variable getenv("variable")
4793 ${variable} getenv("variable")
4794 ${variable:-defvalue} is getenv("variable") if variable is defined and
4795 is defvalue otherwise
4796 ~ getenv("HOME")
4797 \c c
4798 <others> <just copied>
4800 NOTE handling of braces in ${name} doesn't check much or do error recovery
4802 If colon_path is set, then we expand ~ not only at the start of linein,
4803 but also after each : in the path.
4805 ----*/
4806 #define is_allowed_envchar(C, S) ((S) == 0 ? !isspace((C)) && (C) != '/'\
4807 : (((C) >= 'a' && (C) <= 'z') \
4808 || ((C) >= 'A' && (C) <= 'Z') \
4809 || ((C) >= '0' && (C) <= '9')))
4811 char *
4812 expand_variables(char *lineout, size_t lineoutlen, char *linein, int colon_path)
4814 char *src = linein, *dest = lineout, *p;
4815 char *limit = lineout + lineoutlen;
4816 int envexpand = 0, sp;
4818 if(!linein)
4819 return(NULL);
4821 sp = strncmp(src,"LIT:pattern=\"/NICK=", strlen("LIT:pattern=\"/NICK=")) == 0;
4822 while(*src ){ /* something in input string */
4823 if(*src == '$' && *(src+1) == '$'){
4825 * $$ to escape chars we're interested in, else
4826 * it's up to the user of the variable to handle the
4827 * backslash...
4829 if(dest < limit)
4830 *dest++ = *++src; /* copy next as is */
4831 }else
4832 #if !(defined(DOS) || defined(OS2))
4833 if(*src == '\\' && *(src+1) == '$'){
4835 * backslash to escape chars we're interested in, else
4836 * it's up to the user of the variable to handle the
4837 * backslash...
4839 if(dest < limit)
4840 *dest++ = *++src; /* copy next as is */
4841 }else if(*src == '~' &&
4842 (src == linein || (colon_path && *(src-1) == ':'))){
4843 char buf[MAXPATH];
4844 int i;
4846 for(i = 0; i < sizeof(buf)-1 && src[i] && src[i] != '/'; i++)
4847 buf[i] = src[i];
4849 src += i; /* advance src pointer */
4850 buf[i] = '\0'; /* tie off buf string */
4851 fnexpand(buf, sizeof(buf)); /* expand the path */
4853 for(p = buf; dest < limit && (*dest = *p); p++, dest++)
4856 continue;
4857 }else
4858 #endif
4859 if(*src == '$'){ /* shell variable */
4860 char word[128+1], *colon = NULL, *rbrace = NULL;
4862 envexpand++; /* signal that we've expanded a var */
4863 src++; /* skip dollar */
4864 if(*src == '{'){ /* starts with brace? */
4865 src++;
4866 rbrace = strindex(src, '}');
4867 if(rbrace){
4868 /* look for default value */
4869 colon = strstr(src, ":-");
4870 if(colon && (rbrace < colon))
4871 colon = NULL;
4875 p = word;
4877 /* put the env variable to be looked up in word */
4878 if(rbrace){
4879 while(*src
4880 && (p-word < sizeof(word)-1)
4881 && ((colon && src < colon) || (!colon && src < rbrace))){
4882 if(isspace((unsigned char) *src)){
4884 * Illegal input. This should be an error of some
4885 * sort but instead of that we'll just backup to the
4886 * $ and treat it like it wasn't there.
4888 while(*src != '$')
4889 src--;
4891 envexpand--;
4892 goto just_copy;
4894 else
4895 *p++ = *src++;
4898 /* adjust src for next char */
4899 src = rbrace + 1;
4901 else{
4902 while(*src && is_allowed_envchar((unsigned char) *src, sp)
4903 && (p-word < sizeof(word)-1))
4904 *p++ = *src++;
4907 *p = '\0';
4909 if((p = getenv(word)) != NULL){ /* check for word in environment */
4910 while(*p && dest < limit)
4911 *dest++ = *p++;
4913 else if(colon){ /* else possible default value */
4914 p = colon + 2;
4915 while(*p && p < rbrace && dest < limit)
4916 *dest++ = *p++;
4919 continue;
4920 }else{ /* other cases: just copy */
4921 just_copy:
4922 if(dest < limit)
4923 *dest++ = *src;
4926 if(*src) /* next character (if any) */
4927 src++;
4930 if(dest < limit)
4931 *dest = '\0';
4932 else
4933 lineout[lineoutlen-1] = '\0';
4935 return((envexpand && lineout[0] == '\0') ? NULL : lineout);
4939 /*----------------------------------------------------------------------
4940 Sets login, full_username and home_dir
4942 Args: ps -- The Pine structure to put the user name, etc in
4944 Result: sets the fullname, login and home_dir field of the pine structure
4945 returns 0 on success, -1 if not.
4946 ----*/
4947 #define MAX_INIT_ERRS 10
4948 void
4949 init_error(struct pine *ps, int flags, int min_time, int max_time, char *message)
4951 int i;
4953 if(!ps->init_errs){
4954 ps->init_errs = (INIT_ERR_S *)fs_get((MAX_INIT_ERRS + 1) *
4955 sizeof(*ps->init_errs));
4956 memset(ps->init_errs, 0, (MAX_INIT_ERRS + 1) * sizeof(*ps->init_errs));
4959 for(i = 0; i < MAX_INIT_ERRS; i++)
4960 if(!(ps->init_errs)[i].message){
4961 (ps->init_errs)[i].message = cpystr(message);
4962 (ps->init_errs)[i].min_time = min_time;
4963 (ps->init_errs)[i].max_time = max_time;
4964 (ps->init_errs)[i].flags = flags;
4965 dprint((2, "%s\n", message ? message : "?"));
4966 break;
4971 /*----------------------------------------------------------------------
4972 Read and parse a pinerc file
4974 Args: Filename -- name of the .pinerc file to open and read
4975 vars -- The vars structure to store values in
4976 which_vars -- Whether the local or global values are being read
4978 Result:
4980 This may be the local file or the global file. The values found are
4981 merged with the values currently in vars. All values are strings and
4982 are malloced; and existing values will be freed before the assignment.
4983 Those that are <unset> will be left unset; their values will be NULL.
4984 ----*/
4985 void
4986 read_pinerc(PINERC_S *prc, struct variable *vars, ParsePinerc which_vars)
4988 char *filename, *file, *value, **lvalue, *line, *error;
4989 char *p, *p1, *free_file = NULL;
4990 struct variable *v;
4991 PINERC_LINE *pline = NULL;
4992 int line_count, was_quoted;
4993 int i;
4995 if(!prc)
4996 return;
4998 dprint((2, "reading_pinerc \"%s\"\n",
4999 prc->name ? prc->name : "?"));
5001 if(prc->type == Loc){
5002 filename = prc->name ? prc->name : "";
5003 file = free_file = read_file(filename, 0);
5006 * This is questionable. In case the user edits the pinerc
5007 * in Windows and adds a UTF-8 BOM, we skip it here. If the
5008 * user adds a Unicode BOM we're in trouble. We could write it
5009 * with the BOM ourselves but so far we leave it BOMless in
5010 * order that it's the same on Unix and Windows.
5012 if(BOM_UTF8(file))
5013 file += 3;
5015 else{
5016 if((file = read_remote_pinerc(prc, which_vars)) != NULL)
5017 ps_global->c_client_error[0] = '\0';
5019 free_file = file;
5022 if(file == NULL || *file == '\0'){
5023 #ifdef DEBUG
5024 if(file == NULL){
5025 dprint((2, "Open failed: %s\n", error_description(errno)));
5027 else{
5028 if(prc->type == Loc){
5029 dprint((1, "Read_pinerc: empty pinerc (new?)\n"));
5031 else{
5032 dprint((1, "Read_pinerc: new remote pinerc\n"));
5035 #endif /* DEBUG */
5037 if(which_vars == ParsePers){
5038 /* problems getting remote config */
5039 if(file == NULL && prc->type == RemImap){
5040 if(!pith_opt_remote_pinerc_failure
5041 || !(*pith_opt_remote_pinerc_failure)())
5042 exceptional_exit(_("Unable to read or write remote configuration"), -1);
5045 ps_global->first_time_user = 1;
5046 prc->outstanding_pinerc_changes = 1;
5049 return;
5051 else{
5052 if(prc->type == Loc &&
5053 (which_vars == ParseFixed || which_vars == ParseGlobal ||
5054 (can_access(filename, ACCESS_EXISTS) == 0 &&
5055 can_access(filename, EDIT_ACCESS) != 0))){
5056 prc->readonly = 1;
5057 if(prc == ps_global->prc)
5058 ps_global->readonly_pinerc = 1;
5062 * accept CRLF or LF newlines
5064 for(p = file; *p && *p != '\012'; p++)
5067 if(p > file && *p && *(p-1) == '\015') /* cvt crlf to lf */
5068 for(p1 = p - 1; (*p1 = *p) != '\0'; p++)
5069 if(!(*p == '\015' && *(p+1) == '\012'))
5070 p1++;
5073 dprint((2, "Read %d characters:\n", strlen(file)));
5075 if(which_vars == ParsePers || which_vars == ParsePersPost){
5076 /*--- Count up lines and allocate structures */
5077 for(line_count = 0, p = file; *p != '\0'; p++)
5078 if(*p == '\n')
5079 line_count++;
5081 prc->pinerc_lines = (PINERC_LINE *)
5082 fs_get((3 + line_count) * sizeof(PINERC_LINE));
5083 memset((void *)prc->pinerc_lines, 0,
5084 (3 + line_count) * sizeof(PINERC_LINE));
5085 pline = prc->pinerc_lines;
5088 for(p = file, line = file; *p != '\0';){
5089 /*----- Grab the line ----*/
5090 line = p;
5091 while(*p && *p != '\n')
5092 p++;
5093 if(*p == '\n'){
5094 *p++ = '\0';
5097 /*----- Comment Line -----*/
5098 if(*line == '#'){
5099 /* no comments in remote pinercs */
5100 if(pline && prc->type == Loc){
5101 pline->is_var = 0;
5102 pline->line = cpystr(line);
5103 pline++;
5105 continue;
5108 if(*line == '\0' || *line == '\t' || *line == ' '){
5109 p1 = line;
5110 while(*p1 == '\t' || *p1 == ' ')
5111 p1++;
5112 if(pline){
5114 * This could be a continuation line from some future
5115 * version of pine, or it could be a continuation line
5116 * from a PC-Pine variable we don't know about in unix.
5118 if(*p1 != '\0')
5119 pline->line = cpystr(line);
5120 else
5121 pline->line = cpystr("");
5122 pline->is_var = 0;
5123 pline++;
5125 continue;
5128 /*----- look up matching 'v' and leave "value" after '=' ----*/
5129 for(v = vars; *line && v->name; v++)
5130 if((i = strlen(v->name)) < strlen(line) && !struncmp(v->name,line,i)){
5131 int j;
5133 for(j = i; line[j] == ' ' || line[j] == '\t'; j++)
5136 if(line[j] == '='){ /* bingo! */
5137 for(value = &line[j+1];
5138 *value == ' ' || *value == '\t';
5139 value++)
5142 break;
5144 /* else either unrecognized var or bogus line */
5147 /*----- Didn't match any variable or bogus format -----*/
5149 * This could be a variable from some future
5150 * version of pine, or it could be a PC-Pine variable
5151 * we don't know about in unix. Either way, we want to preserve
5152 * it in the file.
5154 if(!v->name){
5155 if(pline){
5156 pline->is_var = 0;
5157 pline->line = cpystr(line);
5158 pline++;
5160 continue;
5164 * Previous versions have caused duplicate pinerc data to be
5165 * written to pinerc files. This clause erases the duplicate
5166 * information when we read it, and it will be removed from the file
5167 * if we call write_pinerc. We test to see if the same variable
5168 * appears later in the file, if so, we skip over it here.
5169 * We don't care about duplicates if this isn't a pinerc we might
5170 * write out, so include pline in the conditional.
5171 * Note that we will leave all of the duplicate comments and blank
5172 * lines in the file unless it is a remote pinerc. Luckily, the
5173 * bug that caused the duplicates only applied to remote pinercs,
5174 * so we should have that case covered.
5176 * If we find a duplicate, we point p to the start
5177 * of the next line that should be considered, and then skip back
5178 * to the top of the loop.
5180 if(pline && var_is_in_rest_of_file(v->name, p)){
5181 if(v->is_list)
5182 p = skip_over_this_var(line, p);
5184 continue;
5188 /*----- Obsolete variable, read it anyway below, might use it -----*/
5189 if(v->is_obsolete){
5190 if(pline){
5191 pline->obsolete_var = 1;
5192 pline->line = cpystr(line);
5193 pline->var = v;
5197 /*----- Variable is in the list but unused for some reason -----*/
5198 if(!v->is_used){
5199 if(pline){
5200 pline->is_var = 0;
5201 pline->line = cpystr(line);
5202 pline++;
5204 continue;
5207 /*--- Var is not user controlled, leave it alone for back compat ---*/
5208 if(!v->is_user && pline){
5209 pline->is_var = 0;
5210 pline->line = cpystr(line);
5211 pline++;
5212 continue;
5215 if(which_vars == ParseFixed)
5216 v->is_fixed = 1;
5218 /*---- variable is unset, or it's global but expands to nothing ----*/
5219 if(!*value
5220 || (which_vars == ParseGlobal
5221 && !expand_variables(tmp_20k_buf, SIZEOF_20KBUF, value,
5222 (v == &ps_global->vars[V_MAILCAP_PATH] ||
5223 v == &ps_global->vars[V_MIMETYPE_PATH])))){
5224 if(v->is_user && pline){
5225 pline->is_var = 1;
5226 pline->var = v;
5227 pline++;
5229 continue;
5232 /*--value is non-empty, store it handling quotes and trailing space--*/
5233 if(*value == '"' && !v->is_list && v->del_quotes){
5234 was_quoted = 1;
5235 value++;
5236 for(p1 = value; *p1 && *p1 != '"'; p1++);
5237 if(*p1 == '"')
5238 *p1 = '\0';
5239 else
5240 removing_trailing_white_space(value);
5241 }else
5242 was_quoted = 0;
5245 * List Entry Parsing
5247 * The idea is to parse a comma separated list of
5248 * elements, preserving quotes, and understanding
5249 * continuation lines (that is ',' == "\n ").
5250 * Quotes must be balanced within elements. Space
5251 * within elements is preserved, but leading and trailing
5252 * space is trimmed. This is a generic function, and it's
5253 * left to the the functions that use the lists to make sure
5254 * they contain valid data...
5256 if(v->is_list){
5258 was_quoted = 0;
5259 line_count = 0;
5260 p1 = value;
5261 while(1){ /* generous count of list elements */
5262 if(*p1 == '"') /* ignore ',' if quoted */
5263 was_quoted = (was_quoted) ? 0 : 1 ;
5265 if((*p1 == ',' && !was_quoted) || *p1 == '\n' || *p1 == '\0')
5266 line_count++; /* count this element */
5268 if(*p1 == '\0' || *p1 == '\n'){ /* deal with EOL */
5269 if(p1 < p || *p1 == '\n'){
5270 *p1++ = ','; /* fix null or newline */
5272 if(*p1 != '\t' && *p1 != ' '){
5273 *(p1-1) = '\0'; /* tie off list */
5274 p = p1; /* reset p */
5275 break;
5277 }else{
5278 p = p1; /* end of pinerc */
5279 break;
5281 }else
5282 p1++;
5285 error = NULL;
5286 lvalue = parse_list(value, line_count,
5287 v->del_quotes ? PL_REMSURRQUOT : PL_NONE,
5288 &error);
5289 if(error){
5290 dprint((1,
5291 "read_pinerc: ERROR: %s in %s = \"%s\"\n",
5292 error ? error : "?",
5293 v->name ? v->name : "?",
5294 value ? value : "?"));
5297 * Special case: turn "" strings into empty strings.
5298 * This allows users to turn off default lists. For example,
5299 * if smtp-server is set then a user could override smtp-server
5300 * with smtp-server="".
5302 for(i = 0; lvalue[i]; i++)
5303 if(lvalue[i][0] == '"' &&
5304 lvalue[i][1] == '"' &&
5305 lvalue[i][2] == '\0')
5306 lvalue[i][0] = '\0';
5309 if(pline){
5310 if(v->is_user && (which_vars == ParsePers || !v->is_onlymain)){
5311 if(v->is_list){
5312 char ***l;
5314 l = (which_vars == ParsePers) ? &v->main_user_val.l
5315 : &v->post_user_val.l;
5316 free_list_array(l);
5317 *l = lvalue;
5319 else{
5320 char **p;
5322 p = (which_vars == ParsePers) ? &v->main_user_val.p
5323 : &v->post_user_val.p;
5324 if(p && *p != NULL)
5325 fs_give((void **)p);
5327 *p = cpystr(value);
5330 if(pline){
5331 pline->is_var = 1;
5332 pline->var = v;
5333 pline->is_quoted = was_quoted;
5334 pline++;
5338 else if(which_vars == ParseGlobal){
5339 if(v->is_global){
5340 if(v->is_list){
5341 free_list_array(&v->global_val.l);
5342 v->global_val.l = lvalue;
5344 else{
5345 if(v->global_val.p != NULL)
5346 fs_give((void **) &(v->global_val.p));
5348 v->global_val.p = cpystr(value);
5352 else{ /* which_vars == ParseFixed */
5353 if(v->is_user || v->is_global){
5354 if(v->is_list){
5355 free_list_array(&v->fixed_val.l);
5356 v->fixed_val.l = lvalue;
5358 else{
5359 if(v->fixed_val.p != NULL)
5360 fs_give((void **) &(v->fixed_val.p));
5362 v->fixed_val.p = cpystr(value);
5367 #ifdef DEBUG
5368 if(v->is_list){
5369 char **l;
5370 l = (which_vars == ParsePers) ? v->main_user_val.l :
5371 (which_vars == ParsePersPost) ? v->post_user_val.l :
5372 (which_vars == ParseGlobal) ? v->global_val.l :
5373 v->fixed_val.l;
5374 if(l && *l && **l){
5375 dprint((5, " %20.20s : %s\n",
5376 v->name ? v->name : "?",
5377 *l ? *l : "?"));
5378 while(++l && *l && **l)
5379 dprint((5, " %20.20s : %s\n", "",
5380 *l ? *l : "?"));
5382 }else{
5383 char *p;
5384 p = (which_vars == ParsePers) ? v->main_user_val.p :
5385 (which_vars == ParsePersPost) ? v->post_user_val.p :
5386 (which_vars == ParseGlobal) ? v->global_val.p :
5387 v->fixed_val.p;
5388 if(p && *p)
5389 dprint((5, " %20.20s : %s\n",
5390 v->name ? v->name : "?",
5391 p ? p : "?"));
5393 #endif /* DEBUG */
5396 if(pline){
5397 pline->line = NULL;
5398 pline->is_var = 0;
5399 if(!prc->pinerc_written && prc->type == Loc){
5400 prc->pinerc_written = name_file_mtime(filename);
5401 dprint((5, "read_pinerc: time_pinerc_written = %ld\n",
5402 (long) prc->pinerc_written));
5406 if(free_file)
5407 fs_give((void **) &free_file);
5412 * Args varname The variable name we're looking for
5413 * begin Begin looking here
5415 * Returns 1 if variable varname appears in the rest of the file
5416 * 0 if not
5419 var_is_in_rest_of_file(char *varname, char *begin)
5421 char *p;
5423 if(!(varname && *varname && begin && *begin))
5424 return 0;
5426 p = begin;
5428 while((p = srchstr(p, varname)) != NULL){
5429 /* beginning of a line? */
5430 if(p > begin && (*(p-1) != '\n' && *(p-1) != '\r')){
5431 p++;
5432 continue;
5435 /* followed by [ SPACE ] < = > ? */
5436 p += strlen(varname);
5437 while(*p == ' ' || *p == '\t')
5438 p++;
5440 if(*p == '=')
5441 return 1;
5444 return 0;
5449 * Args begin Variable to skip starts here.
5450 * nextline This is where the next line starts. We need to know this
5451 * because the input has been mangled a little. A \0 has
5452 * replaced the \n at the end of the first line, but we can
5453 * use nextline to help us out of that quandry.
5455 * Return a pointer to the start of the first line after this variable
5456 * and all of its continuation lines.
5458 char *
5459 skip_over_this_var(char *begin, char *nextline)
5461 char *p;
5463 p = begin;
5465 while(1){
5466 if(*p == '\0' || *p == '\n'){ /* EOL */
5467 if(p < nextline || *p == '\n'){ /* there may be another line */
5468 p++;
5469 if(*p != ' ' && *p != '\t') /* no continuation line */
5470 return(p);
5472 else /* end of file */
5473 return(p);
5475 else
5476 p++;
5481 static char quotes[3] = {'"', '"', '\0'};
5482 /*----------------------------------------------------------------------
5483 Write out the .pinerc state information
5485 Args: ps -- The pine structure to take state to be written from
5486 which -- Which pinerc to write
5487 flags -- If bit WRP_NOUSER is set, then assume that there is
5488 not a user present to answer questions.
5490 This writes to a temporary file first, and then renames that to
5491 be the new .pinerc file to protect against disk error. This has the
5492 problem of possibly messing up file protections, ownership and links.
5493 ----*/
5495 write_pinerc(struct pine *ps, EditWhich which, int flags)
5497 char *p, *dir, *tmp = NULL, *pinrc;
5498 char *pval, **lval;
5499 char *linep = NULL, *lineq = NULL;
5500 int bc = 1;
5501 int buflen;
5502 PINERC_LINE *pline;
5503 struct variable *var;
5504 time_t mtime;
5505 char *filename;
5506 REMDATA_S *rd = NULL;
5507 PINERC_S *prc = NULL;
5508 STORE_S *so = NULL;
5509 #ifndef _WINDOWS
5510 struct stat sbuf;
5511 char *slink = NULL;
5512 #endif
5514 #define MAXPLINESIZE 10000
5516 dprint((2,"---- write_pinerc(%s) ----\n",
5517 (which == Main) ? "Main" : "Post"));
5519 switch(which){
5520 case Main:
5521 prc = ps ? ps->prc : NULL;
5522 break;
5523 case Post:
5524 prc = ps ? ps->post_prc : NULL;
5525 break;
5526 default:
5527 break;
5530 if(!prc)
5531 return(-1);
5533 if(prc->quit_to_edit){
5534 if(!(flags & WRP_NOUSER))
5535 quit_to_edit_msg(prc);
5537 return(-1);
5540 if(prc->type != Loc && !prc->readonly){
5542 bc = 0; /* don't do backcompat conversion */
5543 rd = prc->rd;
5544 if(!rd)
5545 return(-1);
5547 rd_check_remvalid(rd, -10L);
5549 if(rd->flags & REM_OUTOFDATE){
5550 if((flags & WRP_NOUSER) || unexpected_pinerc_change()){
5551 prc->outstanding_pinerc_changes = 1;
5552 if(!(flags & WRP_NOUSER))
5553 q_status_message1(SM_ORDER | SM_DING, 3, 3,
5554 "Pinerc \"%.200s\" NOT saved",
5555 prc->name ? prc->name : "");
5556 dprint((2, "write_pinerc: remote pinerc changed\n"));
5557 return(-1);
5559 else
5560 rd->flags &= ~REM_OUTOFDATE;
5563 rd_open_remote(rd);
5565 if(rd->access == ReadWrite){
5566 int ro;
5568 if((ro=rd_remote_is_readonly(rd)) || rd->flags & REM_OUTOFDATE){
5569 if(ro == 1){
5570 if(!(flags & WRP_NOUSER))
5571 q_status_message(SM_ORDER | SM_DING, 5, 15,
5572 _("Can't access remote config, changes NOT saved!"));
5573 dprint((1,
5574 "write_pinerc: Can't write to remote pinerc %s, aborting write\n",
5575 rd->rn ? rd->rn : "?"));
5577 else if(ro == 2){
5578 if(!(rd->flags & NO_META_UPDATE)){
5579 unsigned long save_chk_nmsgs;
5581 switch(rd->type){
5582 case RemImap:
5583 save_chk_nmsgs = rd->t.i.chk_nmsgs;
5584 rd->t.i.chk_nmsgs = 0;
5585 rd_write_metadata(rd, 0);
5586 rd->t.i.chk_nmsgs = save_chk_nmsgs;
5587 break;
5589 default:
5590 q_status_message(SM_ORDER | SM_DING, 3, 5,
5591 "Write_pinerc: Type not supported");
5592 break;
5596 if(!(flags & WRP_NOUSER))
5597 q_status_message1(SM_ORDER | SM_DING, 5, 15,
5598 _("No write permission for remote config %.200s, changes NOT saved!"),
5599 rd->rn);
5601 else{
5602 if(!(flags & WRP_NOUSER))
5603 q_status_message(SM_ORDER | SM_DING, 5, 15,
5604 _("Remote config changed, aborting our change to avoid damage..."));
5605 dprint((1,
5606 "write_pinerc: remote config %s changed since we started pine, aborting write\n",
5607 prc->name ? prc->name : "?"));
5610 rd->flags &= ~DO_REMTRIM;
5611 return(-1);
5614 filename = rd->lf;
5616 else{
5617 prc->readonly = 1;
5618 if(prc == ps->prc)
5619 ps->readonly_pinerc = 1;
5622 else
5623 filename = prc->name ? prc->name : "";
5625 pinrc = prc->name ? prc->name : "";
5627 if(prc->type == Loc){
5628 mtime = name_file_mtime(filename);
5629 if(prc->pinerc_written
5630 && prc->pinerc_written != mtime
5631 && ((flags & WRP_NOUSER) || unexpected_pinerc_change())){
5632 prc->outstanding_pinerc_changes = 1;
5634 if(!(flags & WRP_NOUSER))
5635 q_status_message1(SM_ORDER | SM_DING, 3, 3,
5636 "Pinerc \"%.200s\" NOT saved", pinrc);
5638 dprint((2,"write_pinerc: mtime mismatch: \"%s\": %ld != %ld\n",
5639 filename ? filename : "?",
5640 (long) prc->pinerc_written, (long) mtime));
5641 return(-1);
5645 /* don't write if pinerc is read-only */
5646 if(prc->readonly ||
5647 (filename &&
5648 can_access(filename, ACCESS_EXISTS) == 0 &&
5649 can_access(filename, EDIT_ACCESS) != 0)){
5650 prc->readonly = 1;
5651 if(prc == ps->prc)
5652 ps->readonly_pinerc = 1;
5654 if(!(flags & WRP_NOUSER))
5655 q_status_message1(SM_ORDER | SM_DING, 0, 5,
5656 _("Can't modify configuration file \"%.200s\": ReadOnly"),
5657 pinrc);
5658 dprint((2, "write_pinerc: fail because can't access pinerc\n"));
5660 if(rd)
5661 rd->flags &= ~DO_REMTRIM;
5663 return(-1);
5666 if(rd && rd->flags & NO_FILE){
5667 so = rd->sonofile;
5668 so_truncate(rd->sonofile, 0L); /* reset storage object */
5670 else{
5671 dir = ".";
5672 if((p = last_cmpnt(filename)) != NULL){
5673 *--p = '\0';
5674 dir = filename;
5677 #if defined(DOS) || defined(OS2)
5678 if(!(isalpha((unsigned char)dir[0]) && dir[1] == ':' && dir[2] == '\0')
5679 && (can_access(dir, EDIT_ACCESS) < 0 &&
5680 our_mkdir(dir, 0700) < 0))
5682 if(!(flags & WRP_NOUSER))
5683 q_status_message2(SM_ORDER | SM_DING, 3, 5,
5684 /* TRANSLATORS: first argument is a filename, second
5685 arg is the text of the error message */
5686 _("Error creating \"%.200s\" : %.200s"), dir,
5687 error_description(errno));
5688 if(rd)
5689 rd->flags &= ~DO_REMTRIM;
5691 return(-1);
5694 tmp = temp_nam(dir, "rc");
5696 if(*dir && tmp && !in_dir(dir, tmp)){
5697 our_unlink(tmp);
5698 fs_give((void **)&tmp);
5701 if(p)
5702 *p = '\\';
5704 if(tmp == NULL)
5705 goto io_err;
5707 #else /* !DOS */
5708 tmp = temp_nam((*dir) ? dir : "/", "pinerc");
5711 * If temp_nam can't write in dir it puts the temp file in a
5712 * temp directory, which won't help us when we go to rename.
5714 if(*dir && tmp && !in_dir(dir, tmp)){
5715 our_unlink(tmp);
5716 fs_give((void **)&tmp);
5719 if(p)
5720 *p = '/';
5722 if(tmp == NULL)
5723 goto io_err;
5725 #endif /* !DOS */
5727 if((so = so_get(FileStar, tmp, WRITE_ACCESS)) == NULL)
5728 goto io_err;
5731 if(!(flags & WRP_PRESERV_WRITTEN))
5732 for(var = ps->vars; var->name != NULL; var++)
5733 var->been_written = 0;
5735 if(prc->type == Loc && ps->first_time_user &&
5736 !so_puts(so, native_nl(cf_text_comment)))
5737 goto io_err;
5739 linep = fs_get((MAXPLINESIZE+1)*sizeof(char));
5740 lineq = fs_get((MAXPLINESIZE+1)*sizeof(char));
5741 buflen = MAXPLINESIZE;
5743 /* Write out what was in the .pinerc */
5744 for(pline = prc->pinerc_lines;
5745 pline && (pline->is_var || pline->line); pline++){
5746 if(pline->is_var){
5747 var = pline->var;
5749 if(var->is_list)
5750 lval = LVAL(var, which);
5751 else
5752 pval = PVAL(var, which);
5754 /* variable is not set */
5755 if((var->is_list && (!lval || !lval[0])) ||
5756 (!var->is_list && !pval)){
5757 /* leave null variables out of remote pinerc */
5758 if(prc->type == Loc &&
5759 (!so_puts(so, var->name) || !so_puts(so, "=") ||
5760 !so_puts(so, NEWLINE)))
5761 goto io_err;
5763 /* var is set to empty string */
5764 else if((var->is_list && lval[0][0] == '\0') ||
5765 (!var->is_list && pval[0] == '\0')){
5766 if(!so_puts(so, var->name) || !so_puts(so, "=") ||
5767 !so_puts(so, quotes) || !so_puts(so, NEWLINE))
5768 goto io_err;
5770 else{
5771 if(var->is_list){
5772 int i = 0;
5774 for(i = 0; lval[i]; i++){
5775 if(strlen(var->name)
5776 + (lval[i][0] ? strlen(lval[i]) : 5) > buflen){
5777 buflen = strlen(var->name)
5778 + (lval[i][0] ? strlen(lval[i]) : 5);
5779 fs_resize((void **)&linep, (buflen+1)*sizeof(char));
5780 fs_resize((void **)&lineq, (buflen+1)*sizeof(char));
5782 snprintf(linep, buflen+1, "%s%s%s%s%s",
5783 (i) ? "\t" : var->name,
5784 (i) ? "" : "=",
5785 lval[i][0] ? lval[i] : quotes,
5786 lval[i+1] ? "," : "", NEWLINE);
5787 linep[buflen] = '\0';
5788 if(!so_puts(so, bc ? backcompat_convert_from_utf8(&lineq, buflen+1, linep) : linep))
5789 goto io_err;
5792 else{
5793 if(strlen(var->name)
5794 + (pval[0] ? strlen(pval) : 5) > buflen){
5795 buflen = strlen(var->name)
5796 + (pval[0] ? strlen(pval) : 5);
5797 fs_resize((void **)&linep, (buflen+1)*sizeof(char));
5798 fs_resize((void **)&lineq, (buflen+1)*sizeof(char));
5800 snprintf(linep, buflen+1, "%s=%s%s%s%s",
5801 var->name,
5802 (pline->is_quoted && pval[0] != '\"')
5803 ? "\"" : "",
5804 pval,
5805 (pline->is_quoted && pval[0] != '\"')
5806 ? "\"" : "", NEWLINE);
5807 linep[buflen] = '\0';
5808 if(!so_puts(so, bc ? backcompat_convert_from_utf8(&lineq, buflen+1, linep) : linep))
5809 goto io_err;
5813 var->been_written = 1;
5815 }else{
5817 * The description text should be changed into a message
5818 * about the variable being obsolete when a variable is
5819 * moved to obsolete status. We add that message before
5820 * the variable unless it is already there. However, we
5821 * leave the variable itself in case the user runs an old
5822 * version of pine again. Note that we have read in the
5823 * value of the variable in read_pinerc and translated it
5824 * into a new variable if appropriate.
5826 if(pline->obsolete_var && prc->type == Loc){
5827 if(pline <= prc->pinerc_lines || (pline-1)->line == NULL ||
5828 strlen((pline-1)->line) < 3 ||
5829 strucmp((pline-1)->line+2, pline->var->descrip) != 0)
5830 if(!so_puts(so, "# ") ||
5831 !so_puts(so, native_nl(pline->var->descrip)) ||
5832 !so_puts(so, NEWLINE))
5833 goto io_err;
5836 /* remove comments from remote pinercs */
5837 if((prc->type == Loc ||
5838 (pline->line[0] != '#' && pline->line[0] != '\0')) &&
5839 (!so_puts(so, pline->line) || !so_puts(so, NEWLINE)))
5840 goto io_err;
5844 /* Now write out all the variables not in the .pinerc */
5845 for(var = ps->vars; var->name != NULL; var++){
5846 if(!var->is_user || var->been_written || !var->is_used ||
5847 var->is_obsolete || (var->is_onlymain && which != Main))
5848 continue;
5850 if(var->is_list)
5851 lval = LVAL(var, which);
5852 else
5853 pval = PVAL(var, which);
5856 * set description to NULL to eliminate preceding
5857 * blank and comment line.
5859 if(prc->type == Loc && var->descrip && *var->descrip &&
5860 (!so_puts(so, NEWLINE) || !so_puts(so, "# ") ||
5861 !so_puts(so, native_nl(var->descrip)) || !so_puts(so, NEWLINE)))
5862 goto io_err;
5864 /* variable is not set */
5865 /** Don't know what the global_val thing is for. SH, Mar 00 **/
5866 if((var->is_list && (!lval || (!lval[0] && !var->global_val.l))) ||
5867 (!var->is_list && !pval)){
5868 /* leave null variables out of remote pinerc */
5869 if(prc->type == Loc &&
5870 (!so_puts(so, var->name) || !so_puts(so, "=") ||
5871 !so_puts(so, NEWLINE)))
5872 goto io_err;
5874 /* var is set to empty string */
5875 else if((var->is_list && (!lval[0] || !lval[0][0]))
5876 || (!var->is_list && pval[0] == '\0')){
5877 if(!so_puts(so, var->name) || !so_puts(so, "=") ||
5878 !so_puts(so, quotes) || !so_puts(so, NEWLINE))
5879 goto io_err;
5881 else if(var->is_list){
5882 int i = 0;
5884 for(i = 0; lval[i] ; i++){
5885 if(strlen(var->name)
5886 + (lval[i][0] ? strlen(lval[i]) : 5) > buflen){
5887 buflen = strlen(var->name)
5888 + (lval[i][0] ? strlen(lval[i]) : 5);
5889 fs_resize((void **)&linep, (buflen+1)*sizeof(char));
5890 fs_resize((void **)&lineq, (buflen+1)*sizeof(char));
5892 snprintf(linep, buflen+1, "%s%s%s%s%s",
5893 (i) ? "\t" : var->name,
5894 (i) ? "" : "=",
5895 lval[i],
5896 lval[i+1] ? "," : "", NEWLINE);
5897 linep[buflen] = '\0';
5898 if(!so_puts(so, bc ? backcompat_convert_from_utf8(&lineq, buflen+1, linep) : linep))
5899 goto io_err;
5902 else{
5903 char *pconverted;
5905 if(strlen(pval) > buflen){
5906 buflen = strlen(pval) + 1;
5907 fs_resize((void **)&linep, (buflen+1)*sizeof(char));
5908 fs_resize((void **)&lineq, (buflen+1)*sizeof(char));
5910 pconverted = bc ? backcompat_convert_from_utf8(&lineq, buflen+1, pval) : pval;
5912 if(!so_puts(so, var->name) || !so_puts(so, "=") ||
5913 !so_puts(so, pconverted) || !so_puts(so, NEWLINE))
5914 goto io_err;
5918 if(!(rd && rd->flags & NO_FILE)){
5919 if(so_give(&so))
5920 goto io_err;
5922 #ifndef _WINDOWS
5923 /* if .pinerc is a symbolic link, override symbolic link */
5924 if(our_lstat(filename, &sbuf) == 0
5925 && ((sbuf.st_mode & S_IFMT) == S_IFLNK)){
5926 if((slink = fs_get((sbuf.st_size+1)*sizeof(char))) != NULL){
5927 int r = -1; /* assume error */
5928 if(readlink(filename, slink, sbuf.st_size + 1) >= 0){
5929 char *slpath;
5931 slink[sbuf.st_size] = '\0';
5932 if(*slink == '/')
5933 slpath = cpystr(slink);
5934 else{
5935 char * basep;
5936 basep = strrchr(filename, '/');
5937 if(basep == NULL){
5938 *basep = '\0';
5939 slpath = (char *) fs_get((strlen(filename) + strlen(slink) + 2)*sizeof(char));
5940 snprintf(slpath, sizeof(slpath), "%s/%s", filename, slink);
5941 *basep = '/';
5942 } else {
5943 slpath = (char *) fs_get((strlen(ps_global->home_dir) + strlen(slink) + 2)*sizeof(char));
5944 snprintf(slpath, sizeof(slpath), "%s/%s", ps_global->home_dir, slink);
5947 file_attrib_copy(tmp, slpath);
5948 r = rename_file(tmp, slpath);
5949 fs_give((void **)&slpath);
5951 fs_give((void **)&slink);
5952 if (r < 0) goto io_err;
5955 else
5956 #endif /* _WINDOWS */
5958 file_attrib_copy(tmp, filename);
5959 if(rename_file(tmp, filename) < 0)
5960 goto io_err;
5964 if(prc->type != Loc){
5965 int e, we_cancel;
5966 char datebuf[200];
5968 datebuf[0] = '\0';
5969 we_cancel = 0;
5971 if(!(flags & WRP_NOUSER))
5972 we_cancel = busy_cue(_("Copying to remote config"), NULL, 1);
5974 if((e = rd_update_remote(rd, datebuf)) != 0){
5975 dprint((1,
5976 "write_pinerc: error copying from %s to %s\n",
5977 rd->lf ? rd->lf : "<memory>", rd->rn ? rd->rn : "?"));
5978 if(!(flags & WRP_NOUSER)){
5979 q_status_message2(SM_ORDER | SM_DING, 3, 5,
5980 _("Error copying to %.200s: %.200s"),
5981 rd->rn, error_description(errno));
5983 q_status_message(SM_ORDER | SM_DING, 5, 5,
5984 _("Copy of config to remote folder failed, changes NOT saved remotely"));
5987 else{
5988 rd_update_metadata(rd, datebuf);
5989 rd->read_status = 'W';
5990 rd_trim_remdata(&rd);
5991 rd_close_remote(rd);
5994 if(we_cancel)
5995 cancel_busy_cue(-1);
5998 prc->outstanding_pinerc_changes = 0;
6000 if(prc->type == Loc){
6001 prc->pinerc_written = name_file_mtime(filename);
6002 dprint((2, "wrote pinerc: %s: time_pinerc_written = %ld\n",
6003 pinrc ? pinrc : "?", (long) prc->pinerc_written));
6005 else{
6006 dprint((2, "wrote pinerc: %s\n", pinrc ? pinrc : "?"));
6009 if(tmp){
6010 our_unlink(tmp);
6011 fs_give((void **)&tmp);
6014 if(linep) fs_give((void **)&linep);
6015 if(lineq) fs_give((void **)&lineq);
6017 return(0);
6019 io_err:
6020 if(!(flags & WRP_NOUSER))
6021 q_status_message2(SM_ORDER | SM_DING, 3, 5,
6022 _("Error saving configuration in \"%.200s\": %.200s"),
6023 pinrc, error_description(errno));
6025 dprint((1, "Error writing %s : %s\n", pinrc ? pinrc : "?",
6026 error_description(errno)));
6027 if(rd)
6028 rd->flags &= ~DO_REMTRIM;
6029 if(tmp){
6030 our_unlink(tmp);
6031 fs_give((void **)&tmp);
6034 if(linep) fs_give((void **)&linep);
6035 if(lineq) fs_give((void **)&lineq);
6037 return(-1);
6042 * The srcstr is UTF-8. In order to help the user with
6043 * running this pine and an old pre-alpine pine on the same config
6044 * file we attempt to convert the values of the config variables
6045 * to the user's character set before writing.
6046 * parameters: char **buf. Memory of size_t buflen allocated by caller.
6048 char *
6049 backcompat_convert_from_utf8(char **buf, size_t buflen, char *srcstr)
6051 char *converted = NULL;
6052 char *p;
6053 int its_ascii = 1;
6056 for(p = srcstr; *p && its_ascii; p++)
6057 if(*p & 0x80)
6058 its_ascii = 0;
6060 /* if it is ascii, go with that */
6061 if(its_ascii){
6062 strncpy(*buf, srcstr, buflen);
6063 converted = *buf;
6064 (*buf)[buflen-1] = '\0';
6066 else{
6067 char *trythischarset = NULL;
6070 * If it is possible to translate the UTF-8
6071 * string into the user's character set then
6072 * do that. For backwards compatibility with
6073 * old pines.
6075 if(ps_global->keyboard_charmap && ps_global->keyboard_charmap[0])
6076 trythischarset = ps_global->keyboard_charmap;
6077 else if(ps_global->display_charmap && ps_global->display_charmap[0])
6078 trythischarset = ps_global->display_charmap;
6080 if(trythischarset){
6081 SIZEDTEXT src, dst;
6083 src.data = (unsigned char *) srcstr;
6084 src.size = strlen(srcstr);
6085 memset(&dst, 0, sizeof(dst));
6086 if(utf8_cstext(&src, trythischarset, &dst, 0)){
6087 if(dst.data){
6088 strncpy(*buf, (char *) dst.data, buflen);
6089 (*buf)[buflen-1] = '\0';
6090 fs_give((void **) &dst.data);
6095 if(!converted){
6096 strncpy(*buf, srcstr, buflen);
6097 (*buf)[buflen-1] = '\0';
6098 converted = *buf;
6102 return(converted);
6107 * Given a unix-style source string which may contain LFs,
6108 * convert those to CRLFs if appropriate.
6110 * Returns a pointer to the converted string. This will be a string
6111 * stored in tmp_20k_buf.
6113 * This is just used for the variable descriptions in the pinerc file. It
6114 * could certainly be fancier. It simply converts all \n to NEWLINE.
6116 char *
6117 native_nl(char *src)
6119 char *q, *p;
6121 tmp_20k_buf[0] = '\0';
6123 if(src){
6124 for(q = (char *)tmp_20k_buf; *src; src++){
6125 if(*src == '\n'){
6126 for(p = NEWLINE; *p; p++)
6127 *q++ = *p;
6129 else
6130 *q++ = *src;
6133 *q = '\0';
6136 return((char *)tmp_20k_buf);
6140 void
6141 quit_to_edit_msg(PINERC_S *prc)
6143 /* TRANSLATORS: The %s is either "Postload " or nothing. A Postload config file
6144 is a type of config file. */
6145 q_status_message1(SM_ORDER, 3, 4, _("Must quit Alpine to change %sconfig file."),
6146 (prc == ps_global->post_prc) ? "Postload " : "");
6150 /*------------------------------------------------------------
6151 Return TRUE if the given string was a feature name present in the
6152 pinerc as it was when pine was started...
6153 ----*/
6155 var_in_pinerc(char *s)
6157 PINERC_LINE *pline;
6159 for(pline = ps_global->prc ? ps_global->prc->pinerc_lines : NULL;
6160 pline && (pline->var || pline->line); pline++)
6161 if(pline->var && pline->var->name && !strucmp(s, pline->var->name))
6162 return(1);
6164 for(pline = ps_global->post_prc ? ps_global->post_prc->pinerc_lines : NULL;
6165 pline && (pline->var || pline->line); pline++)
6166 if(pline->var && pline->var->name && !strucmp(s, pline->var->name))
6167 return(1);
6169 return(0);
6173 /*------------------------------------------------------------
6174 Free resources associated with pinerc_lines data
6175 ----*/
6176 void
6177 free_pinerc_lines(PINERC_LINE **pinerc_lines)
6179 PINERC_LINE *pline;
6181 if(pinerc_lines && *pinerc_lines){
6182 for(pline = *pinerc_lines; pline->var || pline->line; pline++)
6183 if(pline->line)
6184 fs_give((void **)&pline->line);
6186 fs_give((void **)pinerc_lines);
6191 /*------------------------------------------------------------
6192 Dump out a global pine.conf on the standard output with fresh
6193 comments. Preserves variables currently set in SYSTEM_PINERC, if any.
6194 ----*/
6195 void
6196 dump_global_conf(void)
6198 FILE *f;
6199 struct variable *var;
6200 PINERC_S *prc;
6202 prc = new_pinerc_s(SYSTEM_PINERC);
6203 read_pinerc(prc, variables, ParseGlobal);
6204 if(prc)
6205 free_pinerc_s(&prc);
6207 f = stdout;
6208 if(f == NULL)
6209 goto io_err;
6211 fprintf(f, "# %s -- system wide pine configuration\n#\n",
6212 SYSTEM_PINERC);
6213 fprintf(f, "# Values here affect all pine users unless they've overridden the values\n");
6214 fprintf(f, "# in their .pinerc files. A copy of this file with current comments may\n");
6215 fprintf(f, "# be obtained by running \"pine -conf\". It will be printed to standard output.\n#\n");
6216 fprintf(f,"# For a variable to be unset its value must be null/blank. This is not the\n");
6217 fprintf(f,"# same as the value of \"empty string\", which can be used to effectively\n");
6218 fprintf(f,"# \"unset\" a variable that has a default or previously assigned value.\n");
6219 fprintf(f,"# To set a variable to the empty string its value should be \"\".\n");
6220 fprintf(f,"# Switch variables are set to either \"yes\" or \"no\", and default to \"no\".\n");
6221 fprintf(f,"# Except for feature-list items, which are additive, values set in the\n");
6222 fprintf(f,"# .pinerc file replace those in pine.conf, and those in pine.conf.fixed\n");
6223 fprintf(f,"# over-ride all others. Features can be over-ridden in .pinerc or\n");
6224 fprintf(f,"# pine.conf.fixed by pre-pending the feature name with \"no-\".\n#\n");
6225 fprintf(f,"# (These comments are automatically inserted.)\n");
6227 for(var = variables; var->name != NULL; var++){
6228 if(!var->is_global || !var->is_used || var->is_obsolete)
6229 continue;
6231 if(var->descrip && *var->descrip){
6232 if(fprintf(f, "\n# %s\n", var->descrip) == EOF)
6233 goto io_err;
6236 if(var->is_list){
6237 if(var->global_val.l == NULL){
6238 if(fprintf(f, "%s=\n", var->name) == EOF)
6239 goto io_err;
6240 }else{
6241 int i;
6243 for(i=0; var->global_val.l[i]; i++)
6244 if(fprintf(f, "%s%s%s%s\n", (i) ? "\t" : var->name,
6245 (i) ? "" : "=", var->global_val.l[i],
6246 var->global_val.l[i+1] ? ",":"") == EOF)
6247 goto io_err;
6249 }else{
6250 if(var->global_val.p == NULL){
6251 if(fprintf(f, "%s=\n", var->name) == EOF)
6252 goto io_err;
6253 }else if(strlen(var->global_val.p) == 0){
6254 if(fprintf(f, "%s=\"\"\n", var->name) == EOF)
6255 goto io_err;
6256 }else{
6257 if(fprintf(f,"%s=%s\n",var->name,var->global_val.p) == EOF)
6258 goto io_err;
6262 exit(0);
6265 io_err:
6266 fprintf(stderr, "Error writing config to stdout: %s\n",
6267 error_description(errno));
6268 exit(-1);
6272 /*------------------------------------------------------------
6273 Dump out a pinerc to filename with fresh
6274 comments. Preserves variables currently set in pinerc, if any.
6275 ----*/
6276 void
6277 dump_new_pinerc(char *filename)
6279 FILE *f;
6280 struct variable *var;
6281 char buf[MAXPATH], *p;
6282 PINERC_S *prc;
6285 p = ps_global->pinerc;
6287 #if defined(DOS) || defined(OS2)
6288 if(!ps_global->pinerc){
6289 char *p;
6291 if(p = getenv("PINERC")){
6292 ps_global->pinerc = cpystr(p);
6293 }else{
6294 char buf2[MAXPATH];
6295 build_path(buf2, ps_global->home_dir, DF_PINEDIR, sizeof(buf2));
6296 build_path(buf, buf2, SYSTEM_PINERC, sizeof(buf));
6299 p = buf;
6301 #else /* !DOS */
6302 if(!ps_global->pinerc){
6303 build_path(buf, ps_global->home_dir, ".pinerc", sizeof(buf));
6304 p = buf;
6306 #endif /* !DOS */
6308 prc = new_pinerc_s(p);
6309 read_pinerc(prc, variables, ParsePers);
6310 if(prc)
6311 free_pinerc_s(&prc);
6313 f = NULL;;
6314 if(filename[0] == '\0'){
6315 fprintf(stderr, "Missing argument to \"-pinerc\".\n");
6316 }else if(!strcmp(filename, "-")){
6317 f = stdout;
6318 }else{
6319 f = our_fopen(filename, "wb");
6322 if(f == NULL)
6323 goto io_err;
6325 if(fprintf(f, "%s", cf_text_comment) == EOF)
6326 goto io_err;
6328 for(var = variables; var->name != NULL; var++){
6329 dprint((7,"write_pinerc: %s = %s\n",
6330 var->name ? var->name : "?",
6331 var->main_user_val.p ? var->main_user_val.p : "<not set>"));
6332 if(!var->is_user || !var->is_used || var->is_obsolete)
6333 continue;
6336 * set description to NULL to eliminate preceding
6337 * blank and comment line.
6339 if(var->descrip && *var->descrip){
6340 if(fprintf(f, "\n# %s\n", var->descrip) == EOF)
6341 goto io_err;
6344 if(var->is_list){
6345 if(var->main_user_val.l == NULL){
6346 if(fprintf(f, "%s=\n", var->name) == EOF)
6347 goto io_err;
6348 }else{
6349 int i;
6351 for(i=0; var->main_user_val.l[i]; i++)
6352 if(fprintf(f, "%s%s%s%s\n", (i) ? "\t" : var->name,
6353 (i) ? "" : "=", var->main_user_val.l[i],
6354 var->main_user_val.l[i+1] ? ",":"") == EOF)
6355 goto io_err;
6357 }else{
6358 if(var->main_user_val.p == NULL){
6359 if(fprintf(f, "%s=\n", var->name) == EOF)
6360 goto io_err;
6361 }else if(strlen(var->main_user_val.p) == 0){
6362 if(fprintf(f, "%s=\"\"\n", var->name) == EOF)
6363 goto io_err;
6364 }else{
6365 if(fprintf(f,"%s=%s\n",var->name,var->main_user_val.p) == EOF)
6366 goto io_err;
6370 exit(0);
6373 io_err:
6374 snprintf(buf, sizeof(buf), "Error writing config to %s: %s\n",
6375 filename, error_description(errno));
6376 exceptional_exit(buf, -1);
6380 /*----------------------------------------------------------------------
6381 Set a user variable and save the .pinerc
6383 Args: var -- The index of the variable to set from conftype.h (V_....)
6384 value -- The string to set the value to
6386 Result: -1 is returned on failure and 0 is returned on success
6388 The vars data structure is updated and the pinerc saved.
6389 ----*/
6391 set_variable(int var, char *value, int expand, int commit, EditWhich which)
6393 struct variable *v;
6394 char **apval;
6395 PINERC_S *prc;
6397 v = &ps_global->vars[var];
6399 if(!v->is_user)
6400 panic1("Trying to set non-user variable %s", v->name);
6402 /* Override value of which, at most one of these should be set */
6403 if(v->is_onlymain)
6404 which = Main;
6405 else if(v->is_outermost)
6406 which = ps_global->ew_for_except_vars;
6408 apval = APVAL(v, which);
6410 if(!apval)
6411 return(-1);
6413 if(*apval)
6414 fs_give((void **)apval);
6416 *apval = value ? cpystr(value) : NULL;
6417 set_current_val(v, expand, FALSE);
6419 switch(which){
6420 case Main:
6421 prc = ps_global->prc;
6422 break;
6423 case Post:
6424 prc = ps_global->post_prc;
6425 break;
6426 default:
6427 break;
6430 if(prc)
6431 prc->outstanding_pinerc_changes = 1;
6433 return(commit ? write_pinerc(ps_global, which, WRP_NONE) : 0);
6437 /*----------------------------------------------------------------------
6438 Set a user variable list and save the .pinerc
6440 Args: var -- The index of the variable to set from conftype.h (V_....)
6441 lvalue -- The list to set the value to
6443 Result: -1 is returned on failure and 0 is returned on success
6445 The vars data structure is updated and if write_it, the pinerc is saved.
6446 ----*/
6448 set_variable_list(int var, char **lvalue, int write_it, EditWhich which)
6450 char ***alval;
6451 int i;
6452 struct variable *v = &ps_global->vars[var];
6453 PINERC_S *prc;
6455 if(!v->is_user || !v->is_list)
6456 panic1("BOTCH: Trying to set non-user or non-list variable %s", v->name);
6458 /* Override value of which, at most one of these should be set */
6459 if(v->is_onlymain)
6460 which = Main;
6461 else if(v->is_outermost)
6462 which = ps_global->ew_for_except_vars;
6464 alval = ALVAL(v, which);
6465 if(!alval)
6466 return(-1);
6468 if(*alval)
6469 free_list_array(alval);
6471 if(lvalue){
6472 for(i = 0; lvalue[i] ; i++) /* count elements */
6475 *alval = (char **) fs_get((i+1) * sizeof(char *));
6477 for(i = 0; lvalue[i] ; i++)
6478 (*alval)[i] = cpystr(lvalue[i]);
6480 (*alval)[i] = NULL;
6483 set_current_val(v, TRUE, FALSE);
6485 switch(which){
6486 case Main:
6487 prc = ps_global->prc;
6488 break;
6489 case Post:
6490 prc = ps_global->post_prc;
6491 break;
6492 default:
6493 break;
6496 if(prc)
6497 prc->outstanding_pinerc_changes = 1;
6499 return(write_it ? write_pinerc(ps_global, which, WRP_NONE) : 0);
6503 void
6504 set_current_color_vals(struct pine *ps)
6506 struct variable *vars = ps->vars;
6507 int later_color_is_set = 0;
6509 set_current_val(&vars[V_NORM_FORE_COLOR], TRUE, TRUE);
6510 set_current_val(&vars[V_NORM_BACK_COLOR], TRUE, TRUE);
6511 pico_nfcolor(VAR_NORM_FORE_COLOR);
6512 pico_nbcolor(VAR_NORM_BACK_COLOR);
6514 set_current_val(&vars[V_REV_FORE_COLOR], TRUE, TRUE);
6515 set_current_val(&vars[V_REV_BACK_COLOR], TRUE, TRUE);
6516 pico_rfcolor(VAR_REV_FORE_COLOR);
6517 pico_rbcolor(VAR_REV_BACK_COLOR);
6519 set_color_val(&vars[V_TITLE_FORE_COLOR], 1);
6520 set_color_val(&vars[V_TITLECLOSED_FORE_COLOR], 0);
6521 set_color_val(&vars[V_FOLDER_FORE_COLOR], 0);
6522 set_color_val(&vars[V_DIRECTORY_FORE_COLOR], 0);
6523 set_color_val(&vars[V_FOLDER_LIST_FORE_COLOR], 0);
6524 set_color_val(&vars[V_STATUS_FORE_COLOR], 1);
6525 set_color_val(&vars[V_KEYLABEL_FORE_COLOR], 1);
6526 set_color_val(&vars[V_KEYNAME_FORE_COLOR], 1);
6527 set_color_val(&vars[V_SLCTBL_FORE_COLOR], 1);
6528 set_color_val(&vars[V_METAMSG_FORE_COLOR], 1);
6529 set_color_val(&vars[V_PROMPT_FORE_COLOR], 1);
6530 set_color_val(&vars[V_HEADER_GENERAL_FORE_COLOR], 1);
6531 set_color_val(&vars[V_IND_PLUS_FORE_COLOR], 0);
6532 set_color_val(&vars[V_IND_IMP_FORE_COLOR], 0);
6533 set_color_val(&vars[V_IND_DEL_FORE_COLOR], 0);
6534 set_color_val(&vars[V_IND_HIPRI_FORE_COLOR], 0);
6535 set_color_val(&vars[V_IND_LOPRI_FORE_COLOR], 0);
6536 set_color_val(&vars[V_IND_ANS_FORE_COLOR], 0);
6537 set_color_val(&vars[V_IND_NEW_FORE_COLOR], 0);
6538 set_color_val(&vars[V_IND_REC_FORE_COLOR], 0);
6539 set_color_val(&vars[V_IND_FWD_FORE_COLOR], 0);
6540 set_color_val(&vars[V_IND_UNS_FORE_COLOR], 0);
6541 set_color_val(&vars[V_IND_ARR_FORE_COLOR], 0);
6542 set_color_val(&vars[V_IND_SUBJ_FORE_COLOR], 0);
6543 set_color_val(&vars[V_IND_FROM_FORE_COLOR], 0);
6544 set_color_val(&vars[V_IND_OP_FORE_COLOR], 0);
6545 set_color_val(&vars[V_INCUNSEEN_FORE_COLOR], 0);
6546 set_color_val(&vars[V_SIGNATURE_FORE_COLOR], 0);
6548 set_current_val(&ps->vars[V_INDEX_TOKEN_COLORS], TRUE, TRUE);
6549 set_current_val(&ps->vars[V_VIEW_HDR_COLORS], TRUE, TRUE);
6550 set_current_val(&ps->vars[V_KW_COLORS], TRUE, TRUE);
6551 set_custom_spec_colors(ps);
6554 * Set up the quoting colors. If a later color is set but not an earlier
6555 * color we set the earlier color to Normal to make it easier when
6556 * we go to use the colors. However, if the only quote colors set are
6557 * Normal that is the same as no settings, so delete them.
6559 set_color_val(&vars[V_QUOTE1_FORE_COLOR], 0);
6560 set_color_val(&vars[V_QUOTE2_FORE_COLOR], 0);
6561 set_color_val(&vars[V_QUOTE3_FORE_COLOR], 0);
6563 if((!(VAR_QUOTE3_FORE_COLOR && VAR_QUOTE3_BACK_COLOR) ||
6564 (!strucmp(VAR_QUOTE3_FORE_COLOR, VAR_NORM_FORE_COLOR) &&
6565 !strucmp(VAR_QUOTE3_BACK_COLOR, VAR_NORM_BACK_COLOR))) &&
6566 (!(VAR_QUOTE2_FORE_COLOR && VAR_QUOTE2_BACK_COLOR) ||
6567 (!strucmp(VAR_QUOTE2_FORE_COLOR, VAR_NORM_FORE_COLOR) &&
6568 !strucmp(VAR_QUOTE2_BACK_COLOR, VAR_NORM_BACK_COLOR))) &&
6569 (!(VAR_QUOTE1_FORE_COLOR && VAR_QUOTE1_BACK_COLOR) ||
6570 (!strucmp(VAR_QUOTE1_FORE_COLOR, VAR_NORM_FORE_COLOR) &&
6571 !strucmp(VAR_QUOTE1_BACK_COLOR, VAR_NORM_BACK_COLOR)))){
6573 * They are all either Normal or not set. Delete them all.
6575 if(VAR_QUOTE3_FORE_COLOR)
6576 fs_give((void **)&VAR_QUOTE3_FORE_COLOR);
6577 if(VAR_QUOTE3_BACK_COLOR)
6578 fs_give((void **)&VAR_QUOTE3_BACK_COLOR);
6579 if(VAR_QUOTE2_FORE_COLOR)
6580 fs_give((void **)&VAR_QUOTE2_FORE_COLOR);
6581 if(VAR_QUOTE2_BACK_COLOR)
6582 fs_give((void **)&VAR_QUOTE2_BACK_COLOR);
6583 if(VAR_QUOTE1_FORE_COLOR)
6584 fs_give((void **)&VAR_QUOTE1_FORE_COLOR);
6585 if(VAR_QUOTE1_BACK_COLOR)
6586 fs_give((void **)&VAR_QUOTE1_BACK_COLOR);
6588 else{ /* something is non-Normal */
6589 if(VAR_QUOTE3_FORE_COLOR && VAR_QUOTE3_BACK_COLOR)
6590 later_color_is_set++;
6592 /* if 3 is set but not 2, set 2 to Normal */
6593 if(VAR_QUOTE2_FORE_COLOR && VAR_QUOTE2_BACK_COLOR)
6594 later_color_is_set++;
6595 else if(later_color_is_set)
6596 set_color_val(&vars[V_QUOTE2_FORE_COLOR], 1);
6598 /* if 3 or 2 is set but not 1, set 1 to Normal */
6599 if(VAR_QUOTE1_FORE_COLOR && VAR_QUOTE1_BACK_COLOR)
6600 later_color_is_set++;
6601 else if(later_color_is_set)
6602 set_color_val(&vars[V_QUOTE1_FORE_COLOR], 1);
6605 #ifdef _WINDOWS
6606 if(ps->pre441){
6607 int conv_main = 0, conv_post = 0;
6609 ps->pre441 = 0;
6610 if(ps->prc && !unix_color_style_in_pinerc(ps->prc)){
6611 conv_main = convert_pc_gray_names(ps, ps->prc, Main);
6612 if(conv_main)
6613 ps->prc->outstanding_pinerc_changes = 1;
6617 if(ps->post_prc && !unix_color_style_in_pinerc(ps->post_prc)){
6618 conv_post = convert_pc_gray_names(ps, ps->post_prc, Post);
6619 if(conv_post)
6620 ps->post_prc->outstanding_pinerc_changes = 1;
6623 if(conv_main || conv_post){
6624 if(conv_main)
6625 write_pinerc(ps, Main, WRP_NONE);
6627 if(conv_post)
6628 write_pinerc(ps, Post, WRP_NONE);
6630 set_current_color_vals(ps);
6633 #endif /* _WINDOWS */
6635 pico_set_normal_color();
6640 * Set current_val for the foreground and background color vars, which
6641 * are assumed to be in order. If a set_current_val on them doesn't
6642 * produce current_vals, then use the colors from defvar to set those
6643 * current_vals.
6645 void
6646 set_color_val(struct variable *v, int use_default)
6648 set_current_val(v, TRUE, TRUE);
6649 set_current_val(v+1, TRUE, TRUE);
6651 if(!(v->current_val.p && v->current_val.p[0] &&
6652 (v+1)->current_val.p && (v+1)->current_val.p[0])){
6653 struct variable *defvar;
6655 if(v->current_val.p)
6656 fs_give((void **)&v->current_val.p);
6657 if((v+1)->current_val.p)
6658 fs_give((void **)&(v+1)->current_val.p);
6660 if(!use_default)
6661 return;
6663 if(var_defaults_to_rev(v))
6664 defvar = &ps_global->vars[V_REV_FORE_COLOR];
6665 else
6666 defvar = &ps_global->vars[V_NORM_FORE_COLOR];
6668 /* use default vars values instead */
6669 if(defvar && defvar->current_val.p && defvar->current_val.p[0] &&
6670 (defvar+1)->current_val.p && (defvar+1)->current_val.p[0]){
6671 v->current_val.p = cpystr(defvar->current_val.p);
6672 (v+1)->current_val.p = cpystr((defvar+1)->current_val.p);
6679 var_defaults_to_rev(struct variable *v)
6681 return(v == &ps_global->vars[V_REV_FORE_COLOR] ||
6682 v == &ps_global->vars[V_TITLE_FORE_COLOR] ||
6683 v == &ps_global->vars[V_STATUS_FORE_COLOR] ||
6684 v == &ps_global->vars[V_KEYNAME_FORE_COLOR] ||
6685 v == &ps_global->vars[V_PROMPT_FORE_COLOR]);
6691 * Each item in the list looks like:
6693 * /HDR=<header>/FG=<foreground color>/BG=<background color>
6695 * We separate the three pieces into an array of structures to make
6696 * it easier to deal with later.
6698 void
6699 set_custom_spec_colors(struct pine *ps)
6701 if(ps->index_token_colors)
6702 free_spec_colors(&ps->index_token_colors);
6704 ps->index_token_colors = spec_colors_from_varlist(ps->VAR_INDEX_TOKEN_COLORS, 1);
6706 if(ps->hdr_colors)
6707 free_spec_colors(&ps->hdr_colors);
6709 ps->hdr_colors = spec_colors_from_varlist(ps->VAR_VIEW_HDR_COLORS, 1);
6711 /* fit keyword colors into the same structures for code re-use */
6712 if(ps->kw_colors)
6713 free_spec_colors(&ps->kw_colors);
6715 ps->kw_colors = spec_colors_from_varlist(ps->VAR_KW_COLORS, 1);
6720 * Input is one item from config variable.
6722 * Return value must be freed by caller. The return is a single SPEC_COLOR_S,
6723 * not a list.
6725 SPEC_COLOR_S *
6726 spec_color_from_var(char *t, int already_expanded)
6728 char *p, *spec, *fg, *bg;
6729 PATTERN_S *val;
6730 SPEC_COLOR_S *new_hcolor = NULL;
6732 if(t && t[0] && !strcmp(t, INHERIT)){
6733 new_hcolor = (SPEC_COLOR_S *)fs_get(sizeof(*new_hcolor));
6734 memset((void *)new_hcolor, 0, sizeof(*new_hcolor));
6735 new_hcolor->inherit = 1;
6737 else if(t && t[0]){
6738 char tbuf[10000];
6740 if(!already_expanded){
6741 tbuf[0] = '\0';
6742 if(expand_variables(tbuf, sizeof(tbuf), t, 0))
6743 t = tbuf;
6746 spec = fg = bg = NULL;
6747 val = NULL;
6748 if((p = srchstr(t, "/HDR=")) != NULL)
6749 spec = remove_backslash_escapes(p+5);
6750 if((p = srchstr(t, "/FG=")) != NULL)
6751 fg = remove_backslash_escapes(p+4);
6752 if((p = srchstr(t, "/BG=")) != NULL)
6753 bg = remove_backslash_escapes(p+4);
6754 val = parse_pattern("VAL", t, 0);
6756 if(spec && *spec){
6757 /* remove colons */
6758 if((p = strindex(spec, ':')) != NULL)
6759 *p = '\0';
6761 new_hcolor = (SPEC_COLOR_S *)fs_get(sizeof(*new_hcolor));
6762 memset((void *)new_hcolor, 0, sizeof(*new_hcolor));
6763 new_hcolor->spec = spec;
6764 new_hcolor->fg = fg;
6765 new_hcolor->bg = bg;
6766 new_hcolor->val = val;
6768 else{
6769 if(spec)
6770 fs_give((void **)&spec);
6771 if(fg)
6772 fs_give((void **)&fg);
6773 if(bg)
6774 fs_give((void **)&bg);
6775 if(val)
6776 free_pattern(&val);
6780 return(new_hcolor);
6785 * Input is a list from config file.
6787 * Return value may be a list of SPEC_COLOR_S and must be freed by caller.
6789 SPEC_COLOR_S *
6790 spec_colors_from_varlist(char **varlist, int already_expanded)
6792 char **s, *t;
6793 SPEC_COLOR_S *new_hc = NULL;
6794 SPEC_COLOR_S *new_hcolor, **nexthc;
6796 nexthc = &new_hc;
6797 if(varlist){
6798 for(s = varlist; (t = *s) != NULL; s++){
6799 if(t[0]){
6800 new_hcolor = spec_color_from_var(t, already_expanded);
6801 if(new_hcolor){
6802 *nexthc = new_hcolor;
6803 nexthc = &new_hcolor->next;
6809 return(new_hc);
6814 * Returns allocated charstar suitable for config var for a single
6815 * SPEC_COLOR_S.
6817 char *
6818 var_from_spec_color(SPEC_COLOR_S *hc)
6820 char *ret_val = NULL;
6821 char *p, *spec = NULL, *fg = NULL, *bg = NULL, *val = NULL;
6822 size_t len;
6824 if(hc && hc->inherit)
6825 ret_val = cpystr(INHERIT);
6826 else if(hc){
6827 if(hc->spec)
6828 spec = add_viewerhdr_escapes(hc->spec);
6829 if(hc->fg)
6830 fg = add_viewerhdr_escapes(hc->fg);
6831 if(hc->bg)
6832 bg = add_viewerhdr_escapes(hc->bg);
6833 if(hc->val){
6834 p = pattern_to_string(hc->val);
6835 if(p){
6836 val = add_viewerhdr_escapes(p);
6837 fs_give((void **)&p);
6841 len = strlen("/HDR=/FG=/BG=") + strlen(spec ? spec : "") +
6842 strlen(fg ? fg : "") + strlen(bg ? bg : "") +
6843 strlen(val ? "/VAL=" : "") + strlen(val ? val : "");
6844 ret_val = (char *) fs_get(len + 1);
6845 snprintf(ret_val, len+1, "/HDR=%s/FG=%s/BG=%s%s%s",
6846 spec ? spec : "", fg ? fg : "", bg ? bg : "",
6847 val ? "/VAL=" : "", val ? val : "");
6849 if(spec)
6850 fs_give((void **)&spec);
6851 if(fg)
6852 fs_give((void **)&fg);
6853 if(bg)
6854 fs_give((void **)&bg);
6855 if(val)
6856 fs_give((void **)&val);
6859 return(ret_val);
6864 * Returns allocated charstar suitable for config var for a single
6865 * SPEC_COLOR_S.
6867 char **
6868 varlist_from_spec_colors(SPEC_COLOR_S *hcolors)
6870 SPEC_COLOR_S *hc;
6871 char **ret_val = NULL;
6872 int i;
6874 /* count how many */
6875 for(hc = hcolors, i = 0; hc; hc = hc->next, i++)
6878 ret_val = (char **)fs_get((i+1) * sizeof(*ret_val));
6879 memset((void *)ret_val, 0, (i+1) * sizeof(*ret_val));
6880 for(hc = hcolors, i = 0; hc; hc = hc->next, i++)
6881 ret_val[i] = var_from_spec_color(hc);
6883 return(ret_val);
6887 void
6888 update_posting_charset(struct pine *ps, int revert)
6890 #ifndef _WINDOWS
6891 if(F_ON(F_USE_SYSTEM_TRANS, ps)){
6892 if(!revert)
6893 q_status_message(SM_ORDER, 5, 5, _("This change has no effect because feature Use-System-Translation is on"));
6895 else{
6896 #endif /* ! _WINDOWS */
6897 if(ps->posting_charmap)
6898 fs_give((void **) &ps->posting_charmap);
6900 if(ps->VAR_POST_CHAR_SET){
6901 ps->posting_charmap = cpystr(ps->VAR_POST_CHAR_SET);
6902 if(!posting_charset_is_supported(ps->posting_charmap)){
6903 snprintf(tmp_20k_buf, SIZEOF_20KBUF,
6904 _("Posting-Character set \"%s\" is unsupported, using UTF-8"),
6905 ps->posting_charmap);
6906 q_status_message(SM_ORDER | SM_DING, 3, 5, tmp_20k_buf);
6907 fs_give((void **) &ps->posting_charmap);
6908 ps->posting_charmap = cpystr("UTF-8");
6911 else
6912 ps->posting_charmap = cpystr("UTF-8");
6913 #ifndef _WINDOWS
6915 #endif /* ! _WINDOWS */
6919 #define FIXED_COMMENT _("(fixed)")
6920 #define DEFAULT_COMMENT _("(default)")
6921 #define OVERRIDE_COMMENT _("(overridden)")
6924 feature_gets_an_x(struct pine *ps, struct variable *var, FEATURE_S *feature,
6925 char **comment, EditWhich ew)
6927 char **lval, **lvalexc, **lvalnorm;
6928 char *def = DEFAULT_COMMENT;
6929 int j, done = 0;
6930 int feature_fixed_on = 0, feature_fixed_off = 0;
6932 if(comment)
6933 *comment = NULL;
6935 lval = LVAL(var, ew);
6936 lvalexc = LVAL(var, ps->ew_for_except_vars);
6937 lvalnorm = LVAL(var, Main);
6939 /* feature value is administratively fixed */
6940 if((j = feature_in_list(var->fixed_val.l, feature->name)) != 0){
6941 if(j == 1)
6942 feature_fixed_on++;
6943 else if(j == -1)
6944 feature_fixed_off++;
6946 done++;
6947 if(comment)
6948 *comment = FIXED_COMMENT;
6952 * We have an exceptions config setting which overrides anything
6953 * we do here, in the normal config.
6955 if(!done &&
6956 ps->ew_for_except_vars != Main && ew == Main &&
6957 feature_in_list(lvalexc, feature->name)){
6958 done++;
6959 if(comment)
6960 *comment = OVERRIDE_COMMENT;
6964 * Feature is set On in default but not set here.
6966 if(!done &&
6967 !feature_in_list(lval, feature->name) &&
6968 ((feature_in_list(var->global_val.l, feature->name) == 1) ||
6969 ((ps->ew_for_except_vars != Main &&
6970 ew == ps->ew_for_except_vars &&
6971 feature_in_list(lvalnorm, feature->name) == 1)))){
6972 done = 17;
6973 if(comment)
6974 *comment = def;
6977 if(!done &&
6978 feature->defval &&
6979 !feature_in_list(lval, feature->name) &&
6980 !feature_in_list(var->global_val.l, feature->name) &&
6981 (ps->ew_for_except_vars == Main ||
6982 ew != ps->ew_for_except_vars ||
6983 !feature_in_list(lvalnorm, feature->name))){
6984 done = 17;
6985 if(comment)
6986 *comment = def;
6989 return(feature_fixed_on ||
6990 (!feature_fixed_off &&
6991 (done == 17 ||
6992 test_feature(lval, feature->name,
6993 test_old_growth_bits(ps, feature->id)))));
6998 longest_feature_comment(struct pine *ps, EditWhich ew)
7000 int lc = 0;
7002 lc = MAX(lc, utf8_width(FIXED_COMMENT));
7003 lc = MAX(lc, utf8_width(DEFAULT_COMMENT));
7004 if(ps->ew_for_except_vars != Main && ew == Main)
7005 lc = MAX(lc, utf8_width(OVERRIDE_COMMENT));
7007 return(lc);
7011 void
7012 toggle_feature(struct pine *ps, struct variable *var, FEATURE_S *f,
7013 int just_flip_value, EditWhich ew)
7015 char **vp, *p, **lval, ***alval;
7016 int og, on_before, was_set;
7017 char *err;
7018 long l;
7020 og = test_old_growth_bits(ps, f->id);
7023 * if this feature is in the fixed set, or old-growth is in the fixed
7024 * set and this feature is in the old-growth set, don't alter it...
7026 for(vp = var->fixed_val.l; vp && *vp; vp++){
7027 p = (struncmp(*vp, "no-", 3)) ? *vp : *vp + 3;
7028 if(!strucmp(p, f->name) || (og && !strucmp(p, "old-growth"))){
7029 q_status_message(SM_ORDER, 3, 3,
7030 /* TRANSLATORS: In the configuration screen, telling the user we
7031 can't change this option because the system administrator
7032 prohibits it. */
7033 _("Can't change value fixed by sys-admin."));
7034 return;
7038 on_before = F_ON(f->id, ps);
7040 lval = LVAL(var, ew);
7041 alval = ALVAL(var, ew);
7042 if(just_flip_value)
7043 was_set = test_feature(lval, f->name, og);
7044 else
7045 was_set = feature_gets_an_x(ps, var, f, NULL, ew);
7047 if(alval)
7048 set_feature(alval, f->name, !was_set);
7050 set_feature_list_current_val(var);
7051 process_feature_list(ps, var->current_val.l, 0, 0, 0);
7054 * Handle any features that need special attention here...
7056 if(on_before != F_ON(f->id, ps))
7057 switch(f->id){
7058 case F_QUOTE_ALL_FROMS :
7059 mail_parameters(NULL,SET_FROMWIDGET,F_ON(f->id,ps) ? VOIDT : NIL);
7060 break;
7062 case F_FAKE_NEW_IN_NEWS :
7063 if(IS_NEWS(ps->mail_stream))
7064 q_status_message(SM_ORDER | SM_DING, 3, 4,
7065 "news-approximates-new-status won't affect current newsgroup until next open");
7067 break;
7069 case F_COLOR_LINE_IMPORTANT :
7070 case F_DATES_TO_LOCAL :
7071 clear_index_cache(ps->mail_stream, 0);
7072 break;
7074 case F_DISABLE_INDEX_LOCALE_DATES :
7075 reset_index_format();
7076 clear_index_cache(ps->mail_stream, 0);
7077 break;
7079 case F_MARK_FOR_CC :
7080 clear_index_cache(ps->mail_stream, 0);
7081 if(THREADING() && sp_viewing_a_thread(ps->mail_stream))
7082 unview_thread(ps, ps->mail_stream, ps->msgmap);
7084 break;
7086 case F_HIDE_NNTP_PATH :
7087 mail_parameters(NULL, SET_NNTPHIDEPATH,
7088 F_ON(f->id, ps) ? VOIDT : NIL);
7089 break;
7091 case F_MAILDROPS_PRESERVE_STATE :
7092 mail_parameters(NULL, SET_SNARFPRESERVE,
7093 F_ON(f->id, ps) ? VOIDT : NIL);
7094 break;
7096 case F_DISABLE_SHARED_NAMESPACES :
7097 mail_parameters(NULL, SET_DISABLEAUTOSHAREDNS,
7098 F_ON(f->id, ps) ? VOIDT : NIL);
7099 break;
7101 case F_QUELL_LOCK_FAILURE_MSGS :
7102 mail_parameters(NULL, SET_LOCKEACCESERROR,
7103 F_ON(f->id, ps) ? VOIDT : NIL);
7104 break;
7106 case F_MULNEWSRC_HOSTNAMES_AS_TYPED :
7107 l = F_ON(f->id, ps) ? 0L : 1L;
7108 mail_parameters(NULL, SET_NEWSRCCANONHOST, (void *) l);
7109 break;
7111 case F_QUELL_INTERNAL_MSG :
7112 mail_parameters(NULL, SET_USERHASNOLIFE,
7113 F_ON(f->id, ps) ? VOIDT : NIL);
7114 break;
7116 case F_DISABLE_SETLOCALE_COLLATE :
7117 set_collation(F_OFF(F_DISABLE_SETLOCALE_COLLATE, ps), 1);
7118 break;
7120 #ifndef _WINDOWS
7121 case F_USE_SYSTEM_TRANS :
7122 err = NULL;
7123 reset_character_set_stuff(&err);
7124 if(err){
7125 q_status_message(SM_ORDER | SM_DING, 3, 4, err);
7126 fs_give((void **) &err);
7129 break;
7130 #endif /* ! _WINDOWS */
7132 case F_ENABLE_INCOMING_CHECKING :
7133 if(!on_before && F_OFF(F_ENABLE_INCOMING, ps))
7134 q_status_message(SM_ORDER, 0, 3, _("This option has no effect without Enable-Incoming-Folders"));
7136 clear_incoming_valid_bits();
7137 break;
7139 case F_INCOMING_CHECKING_TOTAL :
7140 case F_INCOMING_CHECKING_RECENT :
7141 if(!on_before && F_OFF(F_ENABLE_INCOMING_CHECKING, ps))
7142 q_status_message(SM_ORDER, 0, 3, _("This option has no effect without Enable-Incoming-Folders-Checking"));
7144 clear_incoming_valid_bits();
7145 break;
7147 case F_THREAD_SORTS_BY_ARRIVAL :
7148 clear_index_cache(ps->mail_stream, 0);
7149 refresh_sort(ps->mail_stream, sp_msgmap(ps->mail_stream), SRT_NON);
7150 break;
7152 #ifdef SMIME
7153 case F_DONT_DO_SMIME :
7154 smime_deinit();
7155 break;
7157 #ifdef APPLEKEYCHAIN
7158 case F_PUBLICCERTS_IN_KEYCHAIN :
7159 smime_deinit();
7160 break;
7161 #endif
7162 #endif
7164 default :
7165 break;
7171 * Returns 1 -- Feature is in the list and positive
7172 * 0 -- Feature is not in the list at all
7173 * -1 -- Feature is in the list and negative (no-)
7176 feature_in_list(char **l, char *f)
7178 char *p;
7179 int rv = 0, forced_off;
7181 for(; l && *l; l++){
7182 p = (forced_off = !struncmp(*l, "no-", 3)) ? *l + 3 : *l;
7183 if(!strucmp(p, f))
7184 rv = forced_off ? -1 : 1;
7187 return(rv);
7192 * test_feature - runs thru a feature list, and returns:
7193 * 1 if feature explicitly set and matches 'v'
7194 * 0 if feature not explicitly set *or* doesn't match 'v'
7197 test_feature(char **l, char *f, int g)
7199 char *p;
7200 int rv = 0, forced_off;
7202 for(; l && *l; l++){
7203 p = (forced_off = !struncmp(*l, "no-", 3)) ? *l + 3 : *l;
7204 if(!strucmp(p, f))
7205 rv = !forced_off;
7206 else if(g && !strucmp(p, "old-growth"))
7207 rv = !forced_off;
7210 return(rv);
7214 void
7215 set_feature(char ***l, char *f, int v)
7217 char **list = l ? *l : NULL, newval[256];
7218 int count = 0;
7220 snprintf(newval, sizeof(newval), "%s%s", v ? "" : "no-", f);
7221 for(; list && *list; list++, count++)
7222 if((**list == '\0') /* anything can replace an empty value */
7223 || !strucmp(((!struncmp(*list, "no-", 3)) ? *list + 3 : *list), f)){
7224 fs_give((void **)list); /* replace with new value */
7225 *list = cpystr(newval);
7226 return;
7230 * if we got here, we didn't find it in the list, so grow the list
7231 * and add it..
7233 if(!*l)
7234 *l = (char **)fs_get((count + 2) * sizeof(char *));
7235 else
7236 fs_resize((void **)l, (count + 2) * sizeof(char *));
7238 (*l)[count] = cpystr(newval);
7239 (*l)[count + 1] = NULL;
7244 reset_character_set_stuff(char **err)
7246 int use_system = 0;
7247 char buf[1000];
7249 if(err)
7250 *err = NULL;
7252 if(ps_global->display_charmap)
7253 fs_give((void **) &ps_global->display_charmap);
7255 if(ps_global->keyboard_charmap)
7256 fs_give((void **) &ps_global->keyboard_charmap);
7258 if(ps_global->posting_charmap)
7259 fs_give((void **) &ps_global->posting_charmap);
7261 #ifdef _WINDOWS
7262 ps_global->display_charmap = cpystr("UTF-8");
7263 #else /* UNIX */
7264 if(ps_global->VAR_CHAR_SET)
7265 ps_global->display_charmap = cpystr(ps_global->VAR_CHAR_SET);
7266 else{
7267 #if HAVE_LANGINFO_H && defined(CODESET)
7268 ps_global->display_charmap = cpystr(nl_langinfo_codeset_wrapper());
7269 #else
7270 ps_global->display_charmap = cpystr("UTF-8");
7271 #endif
7273 #endif /* UNIX */
7275 if(!ps_global->display_charmap)
7276 ps_global->display_charmap = cpystr("US-ASCII");
7278 #ifdef _WINDOWS
7279 ps_global->keyboard_charmap = cpystr("UTF-8");
7280 #else /* UNIX */
7281 if(ps_global->VAR_KEY_CHAR_SET)
7282 ps_global->keyboard_charmap = cpystr(ps_global->VAR_KEY_CHAR_SET);
7283 else
7284 ps_global->keyboard_charmap = cpystr(ps_global->display_charmap);
7286 if(!ps_global->keyboard_charmap)
7287 ps_global->keyboard_charmap = cpystr("US-ASCII");
7289 if(F_ON(F_USE_SYSTEM_TRANS, ps_global)){
7290 #if PREREQ_FOR_SYS_TRANSLATION
7291 use_system++;
7292 /* This modifies its arguments */
7293 if(setup_for_input_output(use_system, &ps_global->display_charmap,
7294 &ps_global->keyboard_charmap,
7295 &ps_global->input_cs, (err && *err) ? NULL : err) == -1)
7296 return -1;
7297 #endif
7299 #endif /* UNIX */
7301 if(!use_system){
7302 if(setup_for_input_output(use_system, &ps_global->display_charmap,
7303 &ps_global->keyboard_charmap,
7304 &ps_global->input_cs, (err && *err) ? NULL : err) == -1)
7305 return -1;
7308 if(!use_system && ps_global->VAR_POST_CHAR_SET){
7309 ps_global->posting_charmap = cpystr(ps_global->VAR_POST_CHAR_SET);
7310 if(!posting_charset_is_supported(ps_global->posting_charmap)){
7311 if(err && !*err){
7312 snprintf(buf, sizeof(buf),
7313 _("Posting-Character-Set \"%s\" is unsupported, using UTF-8"),
7314 ps_global->posting_charmap);
7315 *err = cpystr(buf);
7318 fs_give((void **) &ps_global->posting_charmap);
7319 ps_global->posting_charmap = cpystr("UTF-8");
7322 else{
7323 if(use_system && ps_global->VAR_POST_CHAR_SET
7324 && strucmp(ps_global->VAR_POST_CHAR_SET, "UTF-8"))
7325 if(err && !*err)
7326 *err = cpystr(_("Posting-Character-Set is ignored with Use-System-Translation turned on"));
7328 ps_global->posting_charmap = cpystr("UTF-8");
7331 set_locale_charmap(ps_global->keyboard_charmap);
7333 return(0);
7338 * Given a single printer string from the config file, returns pointers
7339 * to alloc'd strings containing the printer nickname, the command,
7340 * the init string, the trailer string, everything but the nickname string,
7341 * and everything but the command string. All_but_cmd includes the trailing
7342 * space at the end (the one before the command) but all_but_nick does not
7343 * include the leading space (the one before the [).
7344 * If you pass in a pointer it is guaranteed to come back pointing to an
7345 * allocated string, even if it is just an empty string. It is ok to pass
7346 * NULL for any of the six return strings.
7348 void
7349 parse_printer(char *input, char **nick, char **cmd, char **init, char **trailer,
7350 char **all_but_nick, char **all_but_cmd)
7352 char *p, *q, *start, *saved_options = NULL;
7353 int tmpsave, cnt;
7355 if(!input)
7356 input = "";
7358 if(nick || all_but_nick){
7359 if((p = srchstr(input, " [")) != NULL){
7360 if(all_but_nick)
7361 *all_but_nick = cpystr(p+1);
7363 if(nick){
7364 while(p-1 > input && isspace((unsigned char)*(p-1)))
7365 p--;
7367 tmpsave = *p;
7368 *p = '\0';
7369 *nick = cpystr(input);
7370 *p = tmpsave;
7373 else{
7374 if(nick)
7375 *nick = cpystr("");
7377 if(all_but_nick)
7378 *all_but_nick = cpystr(input);
7382 if((p = srchstr(input, "] ")) != NULL){
7384 ++p;
7385 }while(isspace((unsigned char)*p));
7387 tmpsave = *p;
7388 *p = '\0';
7389 saved_options = cpystr(input);
7390 *p = tmpsave;
7392 else
7393 p = input;
7395 if(cmd)
7396 *cmd = cpystr(p);
7398 if(init){
7399 if(saved_options && (p = srchstr(saved_options, "INIT="))){
7400 start = p + strlen("INIT=");
7401 for(cnt=0, p = start; *p && *(p+1) && isxpair(p); p += 2)
7402 cnt++;
7404 q = *init = (char *)fs_get((cnt + 1) * sizeof(char));
7405 for(p = start; *p && *(p+1) && isxpair(p); p += 2)
7406 *q++ = read_hex(p);
7408 *q = '\0';
7410 else
7411 *init = cpystr("");
7414 if(trailer){
7415 if(saved_options && (p = srchstr(saved_options, "TRAILER="))){
7416 start = p + strlen("TRAILER=");
7417 for(cnt=0, p = start; *p && *(p+1) && isxpair(p); p += 2)
7418 cnt++;
7420 q = *trailer = (char *)fs_get((cnt + 1) * sizeof(char));
7421 for(p = start; *p && *(p+1) && isxpair(p); p += 2)
7422 *q++ = read_hex(p);
7424 *q = '\0';
7426 else
7427 *trailer = cpystr("");
7430 if(all_but_cmd){
7431 if(saved_options)
7432 *all_but_cmd = saved_options;
7433 else
7434 *all_but_cmd = cpystr("");
7436 else if(saved_options)
7437 fs_give((void **)&saved_options);
7442 copy_pinerc(char *local, char *remote, char **err_msg)
7444 return(copy_localfile_to_remotefldr(RemImap, local, remote,
7445 REMOTE_PINERC_SUBTYPE,
7446 err_msg));
7451 copy_abook(char *local, char *remote, char **err_msg)
7453 return(copy_localfile_to_remotefldr(RemImap, local, remote,
7454 REMOTE_ABOOK_SUBTYPE,
7455 err_msg));
7460 * Copy local file to remote folder.
7462 * Args remotetype -- type of remote folder
7463 * local -- name of local file
7464 * remote -- name of remote folder
7465 * subtype --
7467 * Returns 0 on success.
7470 copy_localfile_to_remotefldr(RemType remotetype, char *local, char *remote,
7471 char *subtype, char **err_msg)
7473 int retfail = -1;
7474 unsigned flags;
7475 REMDATA_S *rd;
7477 dprint((9, "copy_localfile_to_remotefldr(%s,%s)\n",
7478 local ? local : "<null>",
7479 remote ? remote : "<null>"));
7481 *err_msg = (char *)fs_get(MAXPATH * sizeof(char));
7483 if(!local || !*local){
7484 snprintf(*err_msg, MAXPATH, _("No local file specified"));
7485 return(retfail);
7488 if(!remote || !*remote){
7489 snprintf(*err_msg, MAXPATH, _("No remote folder specified"));
7490 return(retfail);
7493 if(!IS_REMOTE(remote)){
7494 snprintf(*err_msg, MAXPATH, _("Remote folder name \"%s\" %s"), remote,
7495 (*remote != '{') ? _("must begin with \"{\"") : _("not valid"));
7496 return(retfail);
7499 if(IS_REMOTE(local)){
7500 snprintf(*err_msg, MAXPATH, _("First argument \"%s\" must be a local filename"),
7501 local);
7502 return(retfail);
7505 if(can_access(local, ACCESS_EXISTS) != 0){
7506 snprintf(*err_msg, MAXPATH, _("Local file \"%s\" does not exist"), local);
7507 return(retfail);
7510 if(can_access(local, READ_ACCESS) != 0){
7511 snprintf(*err_msg, MAXPATH, _("Can't read local file \"%s\": %s"),
7512 local, error_description(errno));
7513 return(retfail);
7517 * Check if remote folder exists and create it if it doesn't.
7519 flags = 0;
7520 rd = rd_create_remote(remotetype, remote, subtype,
7521 &flags, _("Error: "), _("Can't copy to remote folder."));
7523 if(!rd || rd->access == NoExists){
7524 snprintf(*err_msg, MAXPATH, _("Can't create \"%s\""), remote);
7525 if(rd)
7526 rd_free_remdata(&rd);
7528 return(retfail);
7531 if(rd->access == MaybeRorW)
7532 rd->access = ReadWrite;
7534 rd->flags |= (NO_META_UPDATE | DO_REMTRIM);
7535 rd->lf = cpystr(local);
7537 rd_open_remote(rd);
7538 if(!rd_stream_exists(rd)){
7539 snprintf(*err_msg, MAXPATH, _("Can't open remote folder \"%s\""), rd->rn);
7540 rd_free_remdata(&rd);
7541 return(retfail);
7544 if(rd_remote_is_readonly(rd)){
7545 snprintf(*err_msg, MAXPATH, _("Remote folder \"%s\" is readonly"), rd->rn);
7546 rd_free_remdata(&rd);
7547 return(retfail);
7550 switch(rd->type){
7551 case RemImap:
7553 * Empty folder, add a header msg.
7555 if(rd->t.i.stream->nmsgs == 0){
7556 if(rd_init_remote(rd, 1) != 0){
7557 snprintf(*err_msg, MAXPATH,
7558 _("Failed initializing remote folder \"%s\", check debug file"),
7559 rd->rn);
7560 rd_free_remdata(&rd);
7561 return(retfail);
7565 fs_give((void **)err_msg);
7566 *err_msg = NULL;
7567 if(rd_chk_for_hdr_msg(&(rd->t.i.stream), rd, err_msg)){
7568 rd_free_remdata(&rd);
7569 return(retfail);
7572 break;
7574 default:
7575 break;
7578 if(rd_update_remote(rd, NULL) != 0){
7579 snprintf(*err_msg, MAXPATH, _("Error copying to remote folder \"%s\""), rd->rn);
7580 rd_free_remdata(&rd);
7581 return(retfail);
7584 rd_update_metadata(rd, NULL);
7585 rd_close_remdata(&rd);
7587 fs_give((void **)err_msg);
7588 return(0);
7592 /*----------------------------------------------------------------------
7593 Panic pine - call on detected programmatic errors to exit pine, with arg
7595 Input: message -- printf styule string for panic message (see above)
7596 arg -- argument for printf string
7598 Result: The various tty modes are restored
7599 If debugging is active a core dump will be generated
7600 Exits Pine
7601 ----*/
7602 void
7603 panic1(char *message, char *arg)
7605 char buf1[1001], buf2[1001];
7607 snprintf(buf1, sizeof(buf1), "%.*s", MAX(sizeof(buf1) - 1 - strlen(message), 0), arg);
7608 snprintf(buf2, sizeof(buf2), message, buf1);
7609 alpine_panic(buf2);
7616 HelpType
7617 config_help(int var, int feature)
7619 switch(var){
7620 case V_FEATURE_LIST :
7621 return(feature_list_help(feature));
7622 break;
7624 case V_PERSONAL_NAME :
7625 return(h_config_pers_name);
7626 case V_USER_ID :
7627 return(h_config_user_id);
7628 case V_USER_DOMAIN :
7629 return(h_config_user_dom);
7630 case V_SMTP_SERVER :
7631 return(h_config_smtp_server);
7632 case V_NNTP_SERVER :
7633 return(h_config_nntp_server);
7634 case V_INBOX_PATH :
7635 return(h_config_inbox_path);
7636 case V_PRUNED_FOLDERS :
7637 return(h_config_pruned_folders);
7638 case V_DEFAULT_FCC :
7639 return(h_config_default_fcc);
7640 case V_DEFAULT_SAVE_FOLDER :
7641 return(h_config_def_save_folder);
7642 case V_POSTPONED_FOLDER :
7643 return(h_config_postponed_folder);
7644 case V_READ_MESSAGE_FOLDER :
7645 return(h_config_read_message_folder);
7646 case V_FORM_FOLDER :
7647 return(h_config_form_folder);
7648 case V_ARCHIVED_FOLDERS :
7649 return(h_config_archived_folders);
7650 case V_SIGNATURE_FILE :
7651 return(h_config_signature_file);
7652 case V_LITERAL_SIG :
7653 return(h_config_literal_sig);
7654 case V_INIT_CMD_LIST :
7655 return(h_config_init_cmd_list);
7656 case V_COMP_HDRS :
7657 return(h_config_comp_hdrs);
7658 case V_CUSTOM_HDRS :
7659 return(h_config_custom_hdrs);
7660 case V_VIEW_HEADERS :
7661 return(h_config_viewer_headers);
7662 case V_VIEW_MARGIN_LEFT :
7663 return(h_config_viewer_margin_left);
7664 case V_VIEW_MARGIN_RIGHT :
7665 return(h_config_viewer_margin_right);
7666 case V_QUOTE_SUPPRESSION :
7667 return(h_config_quote_suppression);
7668 case V_SAVED_MSG_NAME_RULE :
7669 return(h_config_saved_msg_name_rule);
7670 case V_FCC_RULE :
7671 return(h_config_fcc_rule);
7672 case V_SORT_KEY :
7673 return(h_config_sort_key);
7674 case V_AB_SORT_RULE :
7675 return(h_config_ab_sort_rule);
7676 case V_FLD_SORT_RULE :
7677 return(h_config_fld_sort_rule);
7678 case V_POST_CHAR_SET :
7679 return(h_config_post_char_set);
7680 case V_UNK_CHAR_SET :
7681 return(h_config_unk_char_set);
7682 #ifndef _WINDOWS
7683 case V_KEY_CHAR_SET :
7684 return(h_config_key_char_set);
7685 case V_CHAR_SET :
7686 return(h_config_char_set);
7687 #endif /* ! _WINDOWS */
7688 case V_EDITOR :
7689 return(h_config_editor);
7690 case V_SPELLER :
7691 return(h_config_speller);
7692 case V_DISPLAY_FILTERS :
7693 return(h_config_display_filters);
7694 case V_SEND_FILTER :
7695 return(h_config_sending_filter);
7696 case V_ALT_ADDRS :
7697 return(h_config_alt_addresses);
7698 case V_KEYWORDS :
7699 return(h_config_keywords);
7700 case V_KW_BRACES :
7701 return(h_config_kw_braces);
7702 case V_OPENING_SEP :
7703 return(h_config_opening_sep);
7704 case V_KW_COLORS :
7705 return(h_config_kw_color);
7706 case V_ABOOK_FORMATS :
7707 return(h_config_abook_formats);
7708 case V_INDEX_FORMAT :
7709 return(h_config_index_format);
7710 case V_INCCHECKTIMEO :
7711 return(h_config_incoming_timeo);
7712 case V_INCCHECKINTERVAL :
7713 return(h_config_incoming_interv);
7714 case V_INC2NDCHECKINTERVAL :
7715 return(h_config_incoming_second_interv);
7716 case V_INCCHECKLIST :
7717 return(h_config_incoming_list);
7718 case V_SLEEP :
7719 return(h_config_psleep);
7720 case V_OVERLAP :
7721 return(h_config_viewer_overlap);
7722 case V_MAXREMSTREAM :
7723 return(h_config_maxremstream);
7724 case V_PERMLOCKED :
7725 return(h_config_permlocked);
7726 case V_MARGIN :
7727 return(h_config_scroll_margin);
7728 case V_DEADLETS :
7729 return(h_config_deadlets);
7730 case V_FILLCOL :
7731 return(h_config_composer_wrap_column);
7732 case V_TCPOPENTIMEO :
7733 return(h_config_tcp_open_timeo);
7734 case V_TCPREADWARNTIMEO :
7735 return(h_config_tcp_readwarn_timeo);
7736 case V_TCPWRITEWARNTIMEO :
7737 return(h_config_tcp_writewarn_timeo);
7738 case V_TCPQUERYTIMEO :
7739 return(h_config_tcp_query_timeo);
7740 case V_RSHOPENTIMEO :
7741 return(h_config_rsh_open_timeo);
7742 case V_SSHOPENTIMEO :
7743 return(h_config_ssh_open_timeo);
7744 case V_USERINPUTTIMEO :
7745 return(h_config_user_input_timeo);
7746 case V_REMOTE_ABOOK_VALIDITY :
7747 return(h_config_remote_abook_validity);
7748 case V_REMOTE_ABOOK_HISTORY :
7749 return(h_config_remote_abook_history);
7750 case V_INCOMING_FOLDERS :
7751 return(h_config_incoming_folders);
7752 case V_FOLDER_SPEC :
7753 return(h_config_folder_spec);
7754 case V_NEWS_SPEC :
7755 return(h_config_news_spec);
7756 case V_ADDRESSBOOK :
7757 return(h_config_address_book);
7758 case V_GLOB_ADDRBOOK :
7759 return(h_config_glob_addrbook);
7760 case V_LAST_VERS_USED :
7761 return(h_config_last_vers);
7762 case V_SENDMAIL_PATH :
7763 return(h_config_sendmail_path);
7764 case V_OPER_DIR :
7765 return(h_config_oper_dir);
7766 case V_RSHPATH :
7767 return(h_config_rshpath);
7768 case V_RSHCMD :
7769 return(h_config_rshcmd);
7770 case V_SSHPATH :
7771 return(h_config_sshpath);
7772 case V_SSHCMD :
7773 return(h_config_sshcmd);
7774 case V_NEW_VER_QUELL :
7775 return(h_config_new_ver_quell);
7776 case V_DISABLE_DRIVERS :
7777 return(h_config_disable_drivers);
7778 case V_DISABLE_AUTHS :
7779 return(h_config_disable_auths);
7780 case V_REMOTE_ABOOK_METADATA :
7781 return(h_config_abook_metafile);
7782 case V_REPLY_STRING :
7783 return(h_config_reply_indent_string);
7784 case V_WORDSEPS :
7785 return(h_config_wordseps);
7786 case V_QUOTE_REPLACE_STRING :
7787 return(h_config_quote_replace_string);
7788 case V_REPLY_INTRO :
7789 return(h_config_reply_intro);
7790 case V_EMPTY_HDR_MSG :
7791 return(h_config_empty_hdr_msg);
7792 case V_STATUS_MSG_DELAY :
7793 return(h_config_status_msg_delay);
7794 case V_ACTIVE_MSG_INTERVAL :
7795 return(h_config_active_msg_interval);
7796 case V_MAILCHECK :
7797 return(h_config_mailcheck);
7798 case V_MAILCHECKNONCURR :
7799 return(h_config_mailchecknoncurr);
7800 case V_MAILDROPCHECK :
7801 return(h_config_maildropcheck);
7802 case V_NNTPRANGE :
7803 return(h_config_nntprange);
7804 case V_NEWS_ACTIVE_PATH :
7805 return(h_config_news_active);
7806 case V_NEWS_SPOOL_DIR :
7807 return(h_config_news_spool);
7808 case V_IMAGE_VIEWER :
7809 return(h_config_image_viewer);
7810 case V_USE_ONLY_DOMAIN_NAME :
7811 return(h_config_domain_name);
7812 case V_LAST_TIME_PRUNE_QUESTION :
7813 return(h_config_prune_date);
7814 case V_UPLOAD_CMD:
7815 return(h_config_upload_cmd);
7816 case V_UPLOAD_CMD_PREFIX:
7817 return(h_config_upload_prefix);
7818 case V_DOWNLOAD_CMD:
7819 return(h_config_download_cmd);
7820 case V_DOWNLOAD_CMD_PREFIX:
7821 return(h_config_download_prefix);
7822 case V_GOTO_DEFAULT_RULE:
7823 return(h_config_goto_default);
7824 case V_INCOMING_STARTUP:
7825 return(h_config_inc_startup);
7826 case V_PRUNING_RULE:
7827 return(h_config_pruning_rule);
7828 case V_REOPEN_RULE:
7829 return(h_config_reopen_rule);
7830 case V_THREAD_DISP_STYLE:
7831 return(h_config_thread_disp_style);
7832 case V_THREAD_INDEX_STYLE:
7833 return(h_config_thread_index_style);
7834 case V_THREAD_MORE_CHAR:
7835 return(h_config_thread_indicator_char);
7836 case V_THREAD_EXP_CHAR:
7837 return(h_config_thread_exp_char);
7838 case V_THREAD_LASTREPLY_CHAR:
7839 return(h_config_thread_lastreply_char);
7840 case V_MAILCAP_PATH :
7841 return(h_config_mailcap_path);
7842 case V_MIMETYPE_PATH :
7843 return(h_config_mimetype_path);
7844 #if !defined(DOS) && !defined(OS2) && !defined(LEAVEOUTFIFO)
7845 case V_FIFOPATH :
7846 return(h_config_fifopath);
7847 #endif
7848 case V_NMW_WIDTH :
7849 return(h_config_newmailwidth);
7850 case V_NEWSRC_PATH :
7851 return(h_config_newsrc_path);
7852 case V_BROWSER :
7853 return(h_config_browser);
7854 #if defined(DOS) || defined(OS2)
7855 case V_FILE_DIR :
7856 return(h_config_file_dir);
7857 #endif
7858 case V_NORM_FORE_COLOR :
7859 case V_NORM_BACK_COLOR :
7860 return(h_config_normal_color);
7861 case V_REV_FORE_COLOR :
7862 case V_REV_BACK_COLOR :
7863 return(h_config_reverse_color);
7864 case V_TITLE_FORE_COLOR :
7865 case V_TITLE_BACK_COLOR :
7866 return(h_config_title_color);
7867 case V_TITLECLOSED_FORE_COLOR :
7868 case V_TITLECLOSED_BACK_COLOR :
7869 return(h_config_titleclosed_color);
7870 case V_FOLDER_FORE_COLOR:
7871 return(h_config_folder_color);
7872 case V_DIRECTORY_FORE_COLOR:
7873 return(h_config_directory_color);
7874 case V_FOLDER_LIST_FORE_COLOR:
7875 return(h_config_folder_list_color);
7876 case V_STATUS_FORE_COLOR :
7877 case V_STATUS_BACK_COLOR :
7878 return(h_config_status_color);
7879 case V_SLCTBL_FORE_COLOR :
7880 case V_SLCTBL_BACK_COLOR :
7881 return(h_config_slctbl_color);
7882 case V_QUOTE1_FORE_COLOR :
7883 case V_QUOTE2_FORE_COLOR :
7884 case V_QUOTE3_FORE_COLOR :
7885 case V_QUOTE1_BACK_COLOR :
7886 case V_QUOTE2_BACK_COLOR :
7887 case V_QUOTE3_BACK_COLOR :
7888 return(h_config_quote_color);
7889 case V_INCUNSEEN_FORE_COLOR :
7890 case V_INCUNSEEN_BACK_COLOR :
7891 return(h_config_incunseen_color);
7892 case V_SIGNATURE_FORE_COLOR :
7893 case V_SIGNATURE_BACK_COLOR :
7894 return(h_config_signature_color);
7895 case V_PROMPT_FORE_COLOR :
7896 case V_PROMPT_BACK_COLOR :
7897 return(h_config_prompt_color);
7898 case V_HEADER_GENERAL_FORE_COLOR :
7899 case V_HEADER_GENERAL_BACK_COLOR :
7900 return(h_config_header_general_color);
7901 case V_IND_PLUS_FORE_COLOR :
7902 case V_IND_IMP_FORE_COLOR :
7903 case V_IND_DEL_FORE_COLOR :
7904 case V_IND_ANS_FORE_COLOR :
7905 case V_IND_NEW_FORE_COLOR :
7906 case V_IND_UNS_FORE_COLOR :
7907 case V_IND_REC_FORE_COLOR :
7908 case V_IND_FWD_FORE_COLOR :
7909 case V_IND_PLUS_BACK_COLOR :
7910 case V_IND_IMP_BACK_COLOR :
7911 case V_IND_DEL_BACK_COLOR :
7912 case V_IND_ANS_BACK_COLOR :
7913 case V_IND_NEW_BACK_COLOR :
7914 case V_IND_UNS_BACK_COLOR :
7915 case V_IND_REC_BACK_COLOR :
7916 case V_IND_FWD_BACK_COLOR :
7917 return(h_config_index_color);
7918 case V_IND_OP_FORE_COLOR :
7919 case V_IND_OP_BACK_COLOR :
7920 return(h_config_index_opening_color);
7921 case V_IND_SUBJ_FORE_COLOR :
7922 case V_IND_SUBJ_BACK_COLOR :
7923 return(h_config_index_subject_color);
7924 case V_IND_FROM_FORE_COLOR :
7925 case V_IND_FROM_BACK_COLOR :
7926 return(h_config_index_from_color);
7927 case V_IND_HIPRI_FORE_COLOR :
7928 case V_IND_HIPRI_BACK_COLOR :
7929 case V_IND_LOPRI_FORE_COLOR :
7930 case V_IND_LOPRI_BACK_COLOR :
7931 return(h_config_index_pri_color);
7932 case V_IND_ARR_FORE_COLOR :
7933 case V_IND_ARR_BACK_COLOR :
7934 return(h_config_index_arrow_color);
7935 case V_KEYLABEL_FORE_COLOR :
7936 case V_KEYLABEL_BACK_COLOR :
7937 return(h_config_keylabel_color);
7938 case V_KEYNAME_FORE_COLOR :
7939 case V_KEYNAME_BACK_COLOR :
7940 return(h_config_keyname_color);
7941 case V_METAMSG_FORE_COLOR :
7942 case V_METAMSG_BACK_COLOR :
7943 return(h_config_metamsg_color);
7944 case V_VIEW_HDR_COLORS :
7945 return(h_config_customhdr_color);
7946 case V_INDEX_TOKEN_COLORS :
7947 return(h_config_indextoken_color);
7948 case V_PRINTER :
7949 return(h_config_printer);
7950 case V_PERSONAL_PRINT_CATEGORY :
7951 return(h_config_print_cat);
7952 case V_PERSONAL_PRINT_COMMAND :
7953 return(h_config_print_command);
7954 case V_PAT_ROLES :
7955 return(h_config_pat_roles);
7956 case V_PAT_FILTS :
7957 return(h_config_pat_filts);
7958 case V_PAT_SCORES :
7959 return(h_config_pat_scores);
7960 case V_PAT_INCOLS :
7961 return(h_config_pat_incols);
7962 case V_PAT_OTHER :
7963 return(h_config_pat_other);
7964 case V_PAT_SRCH :
7965 return(h_config_pat_srch);
7966 case V_INDEX_COLOR_STYLE :
7967 return(h_config_index_color_style);
7968 case V_TITLEBAR_COLOR_STYLE :
7969 return(h_config_titlebar_color_style);
7970 #ifdef _WINDOWS
7971 case V_FONT_NAME :
7972 return(h_config_font_name);
7973 case V_FONT_SIZE :
7974 return(h_config_font_size);
7975 case V_FONT_STYLE :
7976 return(h_config_font_style);
7977 case V_FONT_CHAR_SET :
7978 return(h_config_font_char_set);
7979 case V_PRINT_FONT_NAME :
7980 return(h_config_print_font_name);
7981 case V_PRINT_FONT_SIZE :
7982 return(h_config_print_font_size);
7983 case V_PRINT_FONT_STYLE :
7984 return(h_config_print_font_style);
7985 case V_PRINT_FONT_CHAR_SET :
7986 return(h_config_print_font_char_set);
7987 case V_WINDOW_POSITION :
7988 return(h_config_window_position);
7989 case V_CURSOR_STYLE :
7990 return(h_config_cursor_style);
7991 #else
7992 case V_COLOR_STYLE :
7993 return(h_config_color_style);
7994 #endif
7995 #ifdef ENABLE_LDAP
7996 case V_LDAP_SERVERS :
7997 return(h_config_ldap_servers);
7998 #endif
7999 #ifdef SMIME
8000 case V_PUBLICCERT_DIR :
8001 return(h_config_smime_pubcertdir);
8002 case V_PUBLICCERT_CONTAINER :
8003 return(h_config_smime_pubcertcon);
8004 case V_PRIVATEKEY_DIR :
8005 return(h_config_smime_privkeydir);
8006 case V_PRIVATEKEY_CONTAINER :
8007 return(h_config_smime_privkeycon);
8008 case V_CACERT_DIR :
8009 return(h_config_smime_cacertdir);
8010 case V_CACERT_CONTAINER :
8011 return(h_config_smime_cacertcon);
8012 #endif
8013 case V_RSS_NEWS :
8014 return(h_config_rss_news);
8015 case V_RSS_WEATHER :
8016 return(h_config_rss_weather);
8017 case V_WP_INDEXHEIGHT :
8018 return(h_config_wp_indexheight);
8019 case V_WP_INDEXLINES :
8020 return(h_config_wp_indexlines);
8021 case V_WP_AGGSTATE :
8022 return(h_config_wp_aggstate);
8023 case V_WP_STATE :
8024 return(h_config_wp_state);
8025 case V_WP_COLUMNS :
8026 return(h_config_wp_columns);
8027 default :
8028 return(NO_HELP);
8034 * We don't want the user to be able to edit their pinerc and set
8035 * printer to whatever they want if personal-print-command is fixed.
8036 * So make sure printer is set to something legitimate. If it isn't,
8037 * set it to something standard and return non-zero.
8040 printer_value_check_and_adjust(void)
8042 char **tt;
8043 char aname[100], wname[100];
8044 int ok = 0;
8045 struct variable *vars = ps_global->vars;
8047 if(vars[V_PERSONAL_PRINT_COMMAND].is_fixed && !vars[V_PRINTER].is_fixed){
8048 strncpy(aname, ANSI_PRINTER, sizeof(aname));
8049 aname[sizeof(aname)-1] = '\0';
8050 strncat(aname, "-no-formfeed", sizeof(aname)-strlen(aname)-1);
8051 strncpy(wname, WYSE_PRINTER, sizeof(wname));
8052 wname[sizeof(wname)-1] = '\0';
8053 strncat(wname, "-no-formfeed", sizeof(wname)-strlen(wname)-1);
8054 if(strucmp(VAR_PRINTER, ANSI_PRINTER) == 0
8055 || strucmp(VAR_PRINTER, aname) == 0
8056 || strucmp(VAR_PRINTER, WYSE_PRINTER) == 0
8057 || strucmp(VAR_PRINTER, wname) == 0)
8058 ok++;
8059 else if(VAR_STANDARD_PRINTER && VAR_STANDARD_PRINTER[0]){
8060 for(tt = VAR_STANDARD_PRINTER; *tt; tt++)
8061 if(strucmp(VAR_PRINTER, *tt) == 0)
8062 break;
8064 if(*tt)
8065 ok++;
8068 if(!ok){
8069 char *val;
8070 struct variable *v;
8072 if(VAR_STANDARD_PRINTER && VAR_STANDARD_PRINTER[0])
8073 val = VAR_STANDARD_PRINTER[0];
8074 else
8075 val = ANSI_PRINTER;
8077 v = &vars[V_PRINTER];
8078 if(v->main_user_val.p)
8079 fs_give((void **)&v->main_user_val.p);
8080 if(v->post_user_val.p)
8081 fs_give((void **)&v->post_user_val.p);
8082 if(v->current_val.p)
8083 fs_give((void **)&v->current_val.p);
8085 v->main_user_val.p = cpystr(val);
8086 v->current_val.p = cpystr(val);
8090 return(!ok);
8094 char **
8095 get_supported_options(void)
8097 char **config;
8098 DRIVER *d;
8099 AUTHENTICATOR *a;
8100 char *title = _("Supported features in this Alpine");
8101 char sbuf[MAX_SCREEN_COLS+1];
8102 int cnt, alcnt, len, cols, disabled, any_disabled = 0;;
8105 * Line count:
8106 * Title + blank = 2
8107 * SSL Title + SSL lines + blank = 5
8108 * Auth title + blank = 2
8109 * Driver title + blank = 2
8110 * LDAP title + LDAP line = 2
8111 * Disabled explanation + blank line = 4
8112 * end = 1
8114 cnt = 18;
8115 for(a = mail_lookup_auth(1); a; a = a->next)
8116 cnt++;
8117 for(d = (DRIVER *)mail_parameters(NIL, GET_DRIVERS, NIL);
8118 d; d = d->next)
8119 cnt++;
8121 alcnt = cnt;
8122 config = (char **) fs_get(alcnt * sizeof(char *));
8123 memset(config, 0, alcnt * sizeof(char *));
8125 cols = ps_global->ttyo ? ps_global->ttyo->screen_cols : 0;
8126 len = utf8_width(title);
8127 snprintf(sbuf, sizeof(sbuf), "%*s%s", cols > len ? (cols-len)/2 : 0, "", title);
8129 cnt = 0;
8130 if(cnt < alcnt)
8131 config[cnt] = cpystr(sbuf);
8133 if(++cnt < alcnt)
8134 config[cnt] = cpystr("");
8136 if(++cnt < alcnt)
8137 /* TRANSLATORS: headings */
8138 config[cnt] = cpystr(_("Encryption:"));
8140 if(++cnt < alcnt && mail_parameters(NIL, GET_SSLDRIVER, NIL))
8141 config[cnt] = cpystr(_(" TLS and SSL"));
8142 else
8143 config[cnt] = cpystr(_(" None (no TLS or SSL)"));
8144 #ifdef SSL_SUPPORTS_TLSV1_2
8145 if(++cnt < alcnt)
8146 config[cnt] = cpystr(" TLSv1.1, TLSv1.2, and DTLSv1");
8147 #endif
8148 #ifdef SMIME
8149 if(++cnt < alcnt)
8150 config[cnt] = cpystr(" S/MIME");
8151 #endif
8153 if(++cnt < alcnt)
8154 config[cnt] = cpystr("");
8156 if(++cnt < alcnt)
8157 config[cnt] = cpystr(_("Authenticators:"));
8159 for(a = mail_lookup_auth(1); a; a = a->next){
8160 disabled = (a->client == NULL && a->server == NULL);
8161 any_disabled += disabled;
8162 snprintf(sbuf, sizeof(sbuf), " %s%s", a->name, disabled ? " (disabled)" : "");
8163 if(++cnt < alcnt)
8164 config[cnt] = cpystr(sbuf);
8167 if(++cnt < alcnt)
8168 config[cnt] = cpystr("");
8170 if(++cnt < alcnt)
8171 config[cnt] = cpystr(_("Mailbox drivers:"));
8173 for(d = (DRIVER *)mail_parameters(NIL, GET_DRIVERS, NIL);
8174 d; d = d->next){
8175 disabled = (d->flags & DR_DISABLE);
8176 any_disabled += disabled;
8177 snprintf(sbuf, sizeof(sbuf), " %s%s", d->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(_("Directories:"));
8188 #ifdef ENABLE_LDAP
8189 if(++cnt < alcnt)
8190 config[cnt] = cpystr(" LDAP");
8191 #else
8192 if(++cnt < alcnt)
8193 config[cnt] = cpystr(" None (no LDAP)");
8194 #endif
8196 if(any_disabled){
8197 if(++cnt < alcnt)
8198 config[cnt] = cpystr("");
8200 if(ps_global->ttyo){
8201 if(++cnt < alcnt)
8202 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."));
8204 else{
8205 if(++cnt < alcnt)
8206 config[cnt] = cpystr(_("Authenticators may be disabled because of the \"disable-these-authenticators\""));
8207 if(++cnt < alcnt)
8208 config[cnt] = cpystr(_("hidden config option. Mailbox drivers may be disabled because of the"));
8209 if(++cnt < alcnt)
8210 config[cnt] = cpystr(_("\"disable-these-drivers\" hidden config option."));
8214 if(++cnt < alcnt)
8215 config[cnt] = NULL;
8217 return(config);
8221 unsigned
8222 reset_startup_rule(MAILSTREAM *stream)
8224 long rflags = ROLE_DO_OTHER;
8225 PAT_STATE pstate;
8226 PAT_S *pat;
8227 unsigned startup_rule;
8229 startup_rule = IS_NOTSET;
8231 if(stream && nonempty_patterns(rflags, &pstate)){
8232 for(pat = first_pattern(&pstate); pat; pat = next_pattern(&pstate)){
8233 if(match_pattern(pat->patgrp, stream, NULL, NULL, NULL,
8234 SE_NOSERVER|SE_NOPREFETCH))
8235 break;
8238 if(pat && pat->action && !pat->action->bogus)
8239 startup_rule = pat->action->startup_rule;
8242 return(startup_rule);
8246 #ifdef _WINDOWS
8248 char *
8249 transformed_color(old)
8250 char *old;
8252 if(!old)
8253 return("");
8255 if(!struncmp(old, "color008", 8))
8256 return("colorlgr");
8257 else if(!struncmp(old, "color009", 8))
8258 return("colormgr");
8259 else if(!struncmp(old, "color010", 8))
8260 return("colordgr");
8262 return("");
8267 * If this is the first time we've run a version > 4.40, and there
8268 * is evidence that the config file has not been used by unix pine,
8269 * then we convert color008 to colorlgr, color009 to colormgr, and
8270 * color010 to colordgr. If the config file is being used by
8271 * unix pine then color008 may really supposed to be color008, color009
8272 * may really supposed to be red, and color010 may really supposed to be
8273 * green. Same if we've already run 4.41 or higher previously.
8275 * Returns 0 if no changes, > 0 if something was changed.
8278 convert_pc_gray_names(ps, prc, which)
8279 struct pine *ps;
8280 PINERC_S *prc;
8281 EditWhich which;
8283 struct variable *v;
8284 int ret = 0, ic = 0;
8285 char **s, *t, *p, *pstr, *new, *pval, **apval, **lval;
8287 for(v = ps->vars; v->name; v++){
8288 if(!color_holding_var(ps, v) || v == &ps->vars[V_KW_COLORS])
8289 continue;
8291 if(v == &ps->vars[V_VIEW_HDR_COLORS]){
8293 if((lval = LVAL(v,which)) != NULL){
8294 /* fix these in place */
8295 for(s = lval; (t = *s) != NULL; s++){
8296 if((p = srchstr(t, "FG=color008")) ||
8297 (p = srchstr(t, "FG=color009")) ||
8298 (p = srchstr(t, "FG=color010"))){
8299 strncpy(p+3, transformed_color(p+3), 8);
8300 ret++;
8303 if((p = srchstr(t, "BG=color008")) ||
8304 (p = srchstr(t, "BG=color009")) ||
8305 (p = srchstr(t, "BG=color010"))){
8306 strncpy(p+3, transformed_color(p+3), 8);
8307 ret++;
8312 else{
8313 if((pval = PVAL(v,which)) != NULL){
8314 apval = APVAL(v,which);
8315 if(apval && (!strucmp(pval, "color008") ||
8316 !strucmp(pval, "color009") ||
8317 !strucmp(pval, "color010"))){
8318 new = transformed_color(pval);
8319 if(*apval)
8320 fs_give((void **)apval);
8322 *apval = cpystr(new);
8323 ret++;
8329 v = &ps->vars[V_PAT_INCOLS];
8330 if((lval = LVAL(v,which)) != NULL){
8331 for(s = lval; (t = *s) != NULL; s++){
8332 if((pstr = srchstr(t, "action=")) != NULL){
8333 if((p = srchstr(pstr, "FG=color008")) ||
8334 (p = srchstr(pstr, "FG=color009")) ||
8335 (p = srchstr(pstr, "FG=color010"))){
8336 strncpy(p+3, transformed_color(p+3), 8);
8337 ic++;
8340 if((p = srchstr(pstr, "BG=color008")) ||
8341 (p = srchstr(pstr, "BG=color009")) ||
8342 (p = srchstr(pstr, "BG=color010"))){
8343 strncpy(p+3, transformed_color(p+3), 8);
8344 ic++;
8350 if(ic)
8351 set_current_val(&ps->vars[V_PAT_INCOLS], TRUE, TRUE);
8353 return(ret+ic);
8358 unix_color_style_in_pinerc(prc)
8359 PINERC_S *prc;
8361 PINERC_LINE *pline;
8363 for(pline = prc ? prc->pinerc_lines : NULL;
8364 pline && (pline->var || pline->line); pline++)
8365 if(pline->line && !struncmp("color-style=", pline->line, 12))
8366 return(1);
8368 return(0);
8371 char *
8372 pcpine_general_help(titlebuf)
8373 char *titlebuf;
8375 if(titlebuf)
8376 strcpy(titlebuf, "PC Alpine For Windows");
8378 return(pcpine_help(h_pine_for_windows));
8381 #endif /* _WINDOWS */