"Fossies" - the Fresh Open Source Software Archive

Member "tin-2.6.1/src/config.c" (22 Dec 2021, 68822 Bytes) of package /linux/misc/tin-2.6.1.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "config.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.6.0_vs_2.6.1.

    1 /*
    2  *  Project   : tin - a Usenet reader
    3  *  Module    : config.c
    4  *  Author    : I. Lea
    5  *  Created   : 1991-04-01
    6  *  Updated   : 2021-08-05
    7  *  Notes     : Configuration file routines
    8  *
    9  * Copyright (c) 1991-2022 Iain Lea <iain@bricbrac.de>
   10  * All rights reserved.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  *
   16  * 1. Redistributions of source code must retain the above copyright notice,
   17  *    this list of conditions and the following disclaimer.
   18  *
   19  * 2. Redistributions in binary form must reproduce the above copyright
   20  *    notice, this list of conditions and the following disclaimer in the
   21  *    documentation and/or other materials provided with the distribution.
   22  *
   23  * 3. Neither the name of the copyright holder nor the names of its
   24  *    contributors may be used to endorse or promote products derived from
   25  *    this software without specific prior written permission.
   26  *
   27  * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   28  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   30  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
   31  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   37  * POSSIBILITY OF SUCH DAMAGE.
   38  */
   39 
   40 
   41 #ifndef TIN_H
   42 #   include "tin.h"
   43 #endif /* !TIN_H */
   44 #ifndef VERSION_H
   45 #   include "version.h"
   46 #endif /* !VERSION_H */
   47 #ifndef TCURSES_H
   48 #   include "tcurses.h"
   49 #endif /* !TCURSES_H */
   50 #ifndef TNNTP_H
   51 #   include "tnntp.h"
   52 #endif /* TNNTP_H */
   53 
   54 /*
   55  * local prototypes
   56  */
   57 static t_bool match_item(char *line, const char *pat, char *dst, size_t dstlen);
   58 static t_bool rc_update(FILE *fp);
   59 static t_bool rc_post_update(FILE *fp/* , struct t_version *upgrade */);
   60 static void write_server_config(void);
   61 #ifdef HAVE_COLOR
   62     static t_bool match_color(char *line, const char *pat, int *dst, int max);
   63 #endif /* HAVE_COLOR */
   64 
   65 
   66 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
   67 #   define DASH_TO_SPACE(mark)  ((wchar_t) (mark == L'_' ? L' ' : mark))
   68 #   define SPACE_TO_DASH(mark)  ((wchar_t) (mark == L' ' ? L'_' : mark))
   69 #   define SET_RC_VAL(buf, rcval, defval) do { \
   70         wchar_t *wbuf; \
   71         if ((wbuf = char2wchar_t(buf))) { \
   72             wbuf[1] = (wchar_t) '\0'; \
   73             rcval = !wbuf[0] ? (wchar_t) defval : DASH_TO_SPACE(wbuf[0]); \
   74             if (art_mark_width < wcswidth(wbuf, 1)) \
   75                 art_mark_width = wcswidth(wbuf, 1); \
   76             free(wbuf); \
   77         } \
   78     } while (0)
   79 #else
   80 #   define DASH_TO_SPACE(mark)  ((char) (mark == '_' ? ' ' : mark))
   81 #   define SPACE_TO_DASH(mark)  ((char) (mark == ' ' ? '_' : mark))
   82 #   define SET_RC_VAL(buf, rcval, defval) do { \
   83         rcval = !buf[0] ? defval : DASH_TO_SPACE(buf[0]); \
   84     } while (0)
   85 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
   86 
   87 
   88 /*
   89  * read local & global configuration defaults
   90  */
   91 t_bool
   92 read_config_file(
   93     char *file,
   94     t_bool global_file) /* return value is always ignored */
   95 {
   96     FILE *fp;
   97     char buf[LEN], tmp[LEN];
   98     struct t_version *upgrade = NULL;
   99 #ifdef CHARSET_CONVERSION
  100     int i;
  101     t_bool is_7bit;
  102 #endif /* CHARSET_CONVERSION */
  103 
  104     if ((fp = fopen(file, "r")) == NULL)
  105         return FALSE;
  106 
  107     if (!batch_mode || verbose)
  108         wait_message(0, _(txt_reading_config_file), (global_file) ? _(txt_global) : "");
  109 
  110     while (fgets(buf, (int) sizeof(buf), fp) != NULL) {
  111         if (buf[0] == '\n')
  112             continue;
  113         if (buf[0] == '#') {
  114             if (upgrade == NULL && !global_file && match_string(buf, "# tin configuration file V", NULL, 0)) {
  115                 upgrade = check_upgrade(buf, "# tin configuration file V", TINRC_VERSION);
  116                 if (upgrade->state != RC_IGNORE)
  117                     upgrade_prompt_quit(upgrade, file); /* CONFIG_FILE */
  118                 if (upgrade->state == RC_UPGRADE)
  119                     rc_update(fp);
  120             }
  121             continue;
  122         }
  123 
  124         switch (my_tolower((unsigned char) buf[0])) {
  125         case 'a':
  126             if (match_boolean(buf, "abbreviate_groupname=", &tinrc.abbreviate_groupname))
  127                 break;
  128 
  129             if (match_boolean(buf, "add_posted_to_filter=", &tinrc.add_posted_to_filter))
  130                 break;
  131 
  132             if (match_boolean(buf, "advertising=", &tinrc.advertising))
  133                 break;
  134 
  135             if (match_boolean(buf, "alternative_handling=", &tinrc.alternative_handling))
  136                 break;
  137 
  138             if (match_string(buf, "art_marked_deleted=", tmp, sizeof(tmp))) {
  139                 SET_RC_VAL(tmp, tinrc.art_marked_deleted, ART_MARK_DELETED);
  140                 break;
  141             }
  142 
  143             if (match_string(buf, "art_marked_inrange=", tmp, sizeof(tmp))) {
  144                 SET_RC_VAL(tmp, tinrc.art_marked_inrange, MARK_INRANGE);
  145                 break;
  146             }
  147 
  148             if (match_string(buf, "art_marked_killed=", tmp, sizeof(tmp))) {
  149                 SET_RC_VAL(tmp, tinrc.art_marked_killed, ART_MARK_KILLED);
  150                 break;
  151             }
  152 
  153             if (match_string(buf, "art_marked_read=", tmp, sizeof(tmp))) {
  154                 SET_RC_VAL(tmp, tinrc.art_marked_read, ART_MARK_READ);
  155                 break;
  156             }
  157 
  158             if (match_string(buf, "art_marked_read_selected=", tmp, sizeof(tmp))) {
  159                 SET_RC_VAL(tmp, tinrc.art_marked_read_selected, ART_MARK_READ_SELECTED);
  160                 break;
  161             }
  162 
  163             if (match_string(buf, "art_marked_recent=", tmp, sizeof(tmp))) {
  164                 SET_RC_VAL(tmp, tinrc.art_marked_recent, ART_MARK_RECENT);
  165                 break;
  166             }
  167 
  168             if (match_string(buf, "art_marked_return=", tmp, sizeof(tmp))) {
  169                 SET_RC_VAL(tmp, tinrc.art_marked_return, ART_MARK_RETURN);
  170                 break;
  171             }
  172 
  173             if (match_string(buf, "art_marked_selected=", tmp, sizeof(tmp))) {
  174                 SET_RC_VAL(tmp, tinrc.art_marked_selected, ART_MARK_SELECTED);
  175                 break;
  176             }
  177 
  178             if (match_string(buf, "art_marked_unread=", tmp, sizeof(tmp))) {
  179                 SET_RC_VAL(tmp, tinrc.art_marked_unread, ART_MARK_UNREAD);
  180                 break;
  181             }
  182 
  183             if (match_boolean(buf, "ask_for_metamail=", &tinrc.ask_for_metamail))
  184                 break;
  185 
  186             if (match_integer(buf, "auto_cc_bcc=", &tinrc.auto_cc_bcc, AUTO_CC_BCC))
  187                 break;
  188 
  189             if (match_boolean(buf, "auto_list_thread=", &tinrc.auto_list_thread))
  190                 break;
  191 
  192             if (match_boolean(buf, "auto_reconnect=", &tinrc.auto_reconnect))
  193                 break;
  194 
  195             if (upgrade && upgrade->file_version < 10318) {
  196                 t_bool ignore;
  197                 /* option removed */
  198                 if (match_boolean(buf, "auto_save=", &ignore))
  199                     break;
  200             }
  201 
  202             break;
  203 
  204         case 'b':
  205             if (match_boolean(buf, "batch_save=", &tinrc.batch_save))
  206                 break;
  207 
  208             if (match_boolean(buf, "beginner_level=", &tinrc.beginner_level))
  209                 break;
  210 
  211             break;
  212 
  213         case 'c':
  214             if (match_boolean(buf, "cache_overview_files=", &tinrc.cache_overview_files))
  215                 break;
  216 
  217 #ifdef USE_CANLOCK
  218             if (match_list(buf, "cancel_lock_algo=", txt_cancel_lock_algos, &tinrc.cancel_lock_algo))
  219                 break;
  220 #endif /* USE_CANLOCK */
  221 
  222             if (match_boolean(buf, "catchup_read_groups=", &tinrc.catchup_read_groups))
  223                 break;
  224 
  225 #ifdef HAVE_COLOR
  226             if (match_color(buf, "col_back=", &tinrc.col_back, MAX_BACKCOLOR))
  227                 break;
  228 
  229             if (match_color(buf, "col_invers_bg=", &tinrc.col_invers_bg, MAX_BACKCOLOR))
  230                 break;
  231 
  232             if (match_color(buf, "col_invers_fg=", &tinrc.col_invers_fg, MAX_COLOR))
  233                 break;
  234 
  235             if (match_color(buf, "col_text=", &tinrc.col_text, MAX_COLOR))
  236                 break;
  237 
  238             if (match_color(buf, "col_minihelp=", &tinrc.col_minihelp, MAX_COLOR))
  239                 break;
  240 
  241             if (match_color(buf, "col_help=", &tinrc.col_help, MAX_COLOR))
  242                 break;
  243 
  244             if (match_color(buf, "col_message=", &tinrc.col_message, MAX_COLOR))
  245                 break;
  246 
  247             if (match_color(buf, "col_quote=", &tinrc.col_quote, MAX_COLOR))
  248                 break;
  249 
  250             if (match_color(buf, "col_quote2=", &tinrc.col_quote2, MAX_COLOR))
  251                 break;
  252 
  253             if (match_color(buf, "col_quote3=", &tinrc.col_quote3, MAX_COLOR))
  254                 break;
  255 
  256             if (match_color(buf, "col_extquote=", &tinrc.col_extquote, MAX_COLOR))
  257                 break;
  258 
  259             if (match_color(buf, "col_head=", &tinrc.col_head, MAX_COLOR))
  260                 break;
  261 
  262             if (match_color(buf, "col_newsheaders=", &tinrc.col_newsheaders, MAX_COLOR))
  263                 break;
  264 
  265             if (match_color(buf, "col_subject=", &tinrc.col_subject, MAX_COLOR))
  266                 break;
  267 
  268             if (match_color(buf, "col_response=", &tinrc.col_response, MAX_COLOR))
  269                 break;
  270 
  271             if (match_color(buf, "col_from=", &tinrc.col_from, MAX_COLOR))
  272                 break;
  273 
  274             if (match_color(buf, "col_normal=", &tinrc.col_normal, MAX_COLOR))
  275                 break;
  276 
  277             if (match_color(buf, "col_title=", &tinrc.col_title, MAX_COLOR))
  278                 break;
  279 
  280             if (match_color(buf, "col_signature=", &tinrc.col_signature, MAX_COLOR))
  281                 break;
  282 
  283             if (match_color(buf, "col_urls=", &tinrc.col_urls, MAX_COLOR))
  284                 break;
  285 
  286             if (match_color(buf, "col_verbatim=", &tinrc.col_verbatim, MAX_COLOR))
  287                 break;
  288 
  289             if (match_color(buf, "col_markstar=", &tinrc.col_markstar, MAX_COLOR))
  290                 break;
  291 
  292             if (match_color(buf, "col_markdash=", &tinrc.col_markdash, MAX_COLOR))
  293                 break;
  294 
  295             if (match_color(buf, "col_markslash=", &tinrc.col_markslash, MAX_COLOR))
  296                 break;
  297 
  298             if (match_color(buf, "col_markstroke=", &tinrc.col_markstroke, MAX_COLOR))
  299                 break;
  300 #endif /* HAVE_COLOR */
  301 
  302             if (upgrade && upgrade->file_version < 10316) {
  303                 if (match_list(buf, "confirm_choice=", txt_confirm_choices, &tinrc.confirm_choice))
  304                     break;
  305             } else {
  306                 if (match_integer(buf, "confirm_choice=", &tinrc.confirm_choice, TINRC_CONFIRM_MAX))
  307                     break;
  308             }
  309 
  310             break;
  311 
  312         case 'd':
  313             if (match_string(buf, "date_format=", tinrc.date_format, sizeof(tinrc.date_format)))
  314                 break;
  315 
  316             if (match_integer(buf, "default_filter_days=", &tinrc.filter_days, 0)) {
  317                 if (tinrc.filter_days <= 0)
  318                     tinrc.filter_days = 1;
  319                 break;
  320             }
  321 
  322             if (match_integer(buf, "default_filter_kill_header=", &tinrc.default_filter_kill_header, FILTER_LINES))
  323                 break;
  324 
  325             if (match_boolean(buf, "default_filter_kill_global=", &tinrc.default_filter_kill_global))
  326                 break;
  327 
  328             if (match_boolean(buf, "default_filter_kill_case=", &tinrc.default_filter_kill_case))
  329                 break;
  330 
  331             if (match_boolean(buf, "default_filter_kill_expire=", &tinrc.default_filter_kill_expire))
  332                 break;
  333 
  334             if (match_integer(buf, "default_filter_select_header=", &tinrc.default_filter_select_header, FILTER_LINES))
  335                 break;
  336 
  337             if (match_boolean(buf, "default_filter_select_global=", &tinrc.default_filter_select_global))
  338                 break;
  339 
  340             if (match_boolean(buf, "default_filter_select_case=", &tinrc.default_filter_select_case))
  341                 break;
  342 
  343             if (match_boolean(buf, "default_filter_select_expire=", &tinrc.default_filter_select_expire))
  344                 break;
  345 
  346             if (match_string(buf, "default_save_mode=", tmp, sizeof(tmp))) {
  347                 tinrc.default_save_mode = tmp[0];
  348                 break;
  349             }
  350 
  351             if (match_string(buf, "default_author_search=", tinrc.default_search_author, sizeof(tinrc.default_search_author)))
  352                 break;
  353 
  354             if (match_string(buf, "default_goto_group=", tinrc.default_goto_group, sizeof(tinrc.default_goto_group)))
  355                 break;
  356 
  357             if (match_string(buf, "default_config_search=", tinrc.default_search_config, sizeof(tinrc.default_search_config)))
  358                 break;
  359 
  360             if (match_string(buf, "default_group_search=", tinrc.default_search_group, sizeof(tinrc.default_search_group)))
  361                 break;
  362 
  363             if (match_string(buf, "default_subject_search=", tinrc.default_search_subject, sizeof(tinrc.default_search_subject)))
  364                 break;
  365 
  366             if (match_string(buf, "default_art_search=", tinrc.default_search_art, sizeof(tinrc.default_search_art)))
  367                 break;
  368 
  369             if (match_string(buf, "default_repost_group=", tinrc.default_repost_group, sizeof(tinrc.default_repost_group)))
  370                 break;
  371 
  372             if (match_string(buf, "default_mail_address=", tinrc.default_mail_address, sizeof(tinrc.default_mail_address)))
  373                 break;
  374 
  375             if (match_integer(buf, "default_move_group=", &tinrc.default_move_group, 0))
  376                 break;
  377 
  378 #ifndef DONT_HAVE_PIPING
  379             if (match_string(buf, "default_pipe_command=", tinrc.default_pipe_command, sizeof(tinrc.default_pipe_command)))
  380                 break;
  381 #endif /* !DONT_HAVE_PIPING */
  382 
  383             if (match_string(buf, "default_post_newsgroups=", tinrc.default_post_newsgroups, sizeof(tinrc.default_post_newsgroups)))
  384                 break;
  385 
  386             if (match_string(buf, "default_post_subject=", tinrc.default_post_subject, sizeof(tinrc.default_post_subject)))
  387                 break;
  388 
  389             if (match_string(buf, "default_pattern=", tinrc.default_pattern, sizeof(tinrc.default_pattern)))
  390                 break;
  391 
  392             if (match_string(buf, "default_range_group=", tinrc.default_range_group, sizeof(tinrc.default_range_group)))
  393                 break;
  394 
  395             if (match_string(buf, "default_range_select=", tinrc.default_range_select, sizeof(tinrc.default_range_select)))
  396                 break;
  397 
  398             if (match_string(buf, "default_range_thread=", tinrc.default_range_thread, sizeof(tinrc.default_range_thread)))
  399                 break;
  400 
  401             if (match_string(buf, "default_save_file=", tinrc.default_save_file, sizeof(tinrc.default_save_file)))
  402                 break;
  403 
  404             if (match_string(buf, "default_select_pattern=", tinrc.default_select_pattern, sizeof(tinrc.default_select_pattern)))
  405                 break;
  406 
  407             if (match_string(buf, "default_shell_command=", tinrc.default_shell_command, sizeof(tinrc.default_shell_command)))
  408                 break;
  409 
  410             if (match_boolean(buf, "draw_arrow=", &tinrc.draw_arrow))
  411                 break;
  412 
  413             break;
  414 
  415         case 'e':
  416             if (match_string(buf, "editor_format=", tinrc.editor_format, sizeof(tinrc.editor_format)))
  417                 break;
  418 
  419 #ifdef HAVE_COLOR
  420             if (match_boolean(buf, "extquote_handling=", &tinrc.extquote_handling))
  421                 break;
  422 
  423             if (match_string(buf, "extquote_regex=", tinrc.extquote_regex, sizeof(tinrc.extquote_regex)))
  424                 break;
  425 #endif /* HAVE_COLOR */
  426 
  427             break;
  428 
  429         case 'f':
  430             if (match_boolean(buf, "force_screen_redraw=", &tinrc.force_screen_redraw))
  431                 break;
  432 
  433             break;
  434 
  435         case 'g':
  436             if (match_integer(buf, "getart_limit=", &tinrc.getart_limit, 0))
  437                 break;
  438 
  439             if (match_integer(buf, "goto_next_unread=", &tinrc.goto_next_unread, NUM_GOTO_NEXT_UNREAD))
  440                 break;
  441 
  442             if (match_string(buf, "group_format=", tinrc.group_format, sizeof(tinrc.group_format)))
  443                 break;
  444 
  445             if (match_boolean(buf, "group_catchup_on_exit=", &tinrc.group_catchup_on_exit))
  446                 break;
  447 
  448             break;
  449 
  450         case 'h':
  451             if (match_integer(buf, "hide_uue=", &tinrc.hide_uue, UUE_ALL))
  452                 break;
  453 
  454             break;
  455 
  456         case 'i':
  457             if (match_boolean(buf, "info_in_last_line=", &tinrc.info_in_last_line))
  458                 break;
  459 
  460             if (match_boolean(buf, "inverse_okay=", &tinrc.inverse_okay))
  461                 break;
  462 
  463             if (match_string(buf, "inews_prog=", tinrc.inews_prog, sizeof(tinrc.inews_prog)))
  464                 break;
  465 
  466             if (match_integer(buf, "interactive_mailer=", &tinrc.interactive_mailer, (int) INTERACTIVE_NONE))
  467                 break;
  468 
  469             break;
  470 
  471         case 'k':
  472             if (match_boolean(buf, "keep_dead_articles=", &tinrc.keep_dead_articles))
  473                 break;
  474 
  475             if (match_integer(buf, "kill_level=", &tinrc.kill_level, KILL_NOTHREAD))
  476                 break;
  477 
  478             break;
  479 
  480         case 'm':
  481             if (match_string(buf, "maildir=", tinrc.maildir, sizeof(tinrc.maildir)))
  482                 break;
  483 
  484             if (match_string(buf, "mailer_format=", tinrc.mailer_format, sizeof(tinrc.mailer_format)))
  485                 break;
  486 
  487             if (match_list(buf, "mail_mime_encoding=", txt_mime_encodings, &tinrc.mail_mime_encoding))
  488                 break;
  489 
  490             if (match_boolean(buf, "mail_8bit_header=", &tinrc.mail_8bit_header))
  491                 break;
  492 
  493 #ifndef CHARSET_CONVERSION
  494             if (match_string(buf, "mm_charset=", tinrc.mm_charset, sizeof(tinrc.mm_charset)))
  495                 break;
  496 #else
  497             if (match_list(buf, "mm_charset=", txt_mime_charsets, &tinrc.mm_network_charset))
  498                 break;
  499             if (match_list(buf, "mm_network_charset=", txt_mime_charsets, &tinrc.mm_network_charset))
  500                 break;
  501 #   ifdef NO_LOCALE
  502             if (match_string(buf, "mm_local_charset=", tinrc.mm_local_charset, sizeof(tinrc.mm_local_charset)))
  503                 break;
  504 #   endif /* NO_LOCALE */
  505 #endif /* !CHARSET_CONVERSION */
  506 
  507             if (match_boolean(buf, "mark_ignore_tags=", &tinrc.mark_ignore_tags))
  508                 break;
  509 
  510             if (match_boolean(buf, "mark_saved_read=", &tinrc.mark_saved_read))
  511                 break;
  512 
  513             if (match_string(buf, "mail_address=", tinrc.mail_address, sizeof(tinrc.mail_address)))
  514                 break;
  515 
  516             if (match_string(buf, "mail_quote_format=", tinrc.mail_quote_format, sizeof(tinrc.mail_quote_format)))
  517                 break;
  518 
  519             if (match_list(buf, "mailbox_format=", txt_mailbox_formats, &tinrc.mailbox_format))
  520                 break;
  521 
  522             if (match_string(buf, "metamail_prog=", tinrc.metamail_prog, sizeof(tinrc.metamail_prog)))
  523                 break;
  524 
  525             if (match_integer(buf, "mono_markdash=", &tinrc.mono_markdash, MAX_ATTR))
  526                 break;
  527 
  528             if (match_integer(buf, "mono_markstar=", &tinrc.mono_markstar, MAX_ATTR))
  529                 break;
  530 
  531             if (match_integer(buf, "mono_markslash=", &tinrc.mono_markslash, MAX_ATTR))
  532                 break;
  533 
  534             if (match_integer(buf, "mono_markstroke=", &tinrc.mono_markstroke, MAX_ATTR))
  535                 break;
  536 
  537             break;
  538 
  539         case 'n':
  540             if (match_string(buf, "newnews=", tmp, sizeof(tmp))) {
  541                 load_newnews_info(tmp);
  542                 break;
  543             }
  544 
  545             /* pick which news headers to display */
  546             if (match_string(buf, "news_headers_to_display=", tinrc.news_headers_to_display, sizeof(tinrc.news_headers_to_display)))
  547                 break;
  548 
  549             /* pick which news headers to NOT display */
  550             if (match_string(buf, "news_headers_to_not_display=", tinrc.news_headers_to_not_display, sizeof(tinrc.news_headers_to_not_display)))
  551                 break;
  552 
  553             if (match_string(buf, "news_quote_format=", tinrc.news_quote_format, sizeof(tinrc.news_quote_format)))
  554                 break;
  555 
  556 #if defined(HAVE_ALARM) && defined(SIGALRM)
  557             /* the number of seconds is limited on some systems (e.g. Free/OpenBSD: 100000000) */
  558             if (match_integer(buf, "nntp_read_timeout_secs=", &tinrc.nntp_read_timeout_secs, 16383))
  559                 break;
  560 #endif /* HAVE_ALARM && SIGALRM */
  561 
  562 #ifdef HAVE_UNICODE_NORMALIZATION
  563             if (match_integer(buf, "normalization_form=", &tinrc.normalization_form, (int) NORMALIZE_MAX))
  564                 break;
  565 #endif /* HAVE_UNICODE_NORMALIZATION */
  566 
  567             break;
  568 
  569         case 'p':
  570             if (match_list(buf, "post_mime_encoding=", txt_mime_encodings, &tinrc.post_mime_encoding))
  571                 break;
  572 
  573             if (match_boolean(buf, "post_8bit_header=", &tinrc.post_8bit_header))
  574                 break;
  575 
  576 #ifndef DISABLE_PRINTING
  577             if (match_string(buf, "printer=", tinrc.printer, sizeof(tinrc.printer)))
  578                 break;
  579 
  580             if (match_boolean(buf, "print_header=", &tinrc.print_header))
  581                 break;
  582 #endif /* !DISABLE_PRINTING */
  583 
  584             if (match_boolean(buf, "pos_first_unread=", &tinrc.pos_first_unread))
  585                 break;
  586 
  587             if (match_integer(buf, "post_process_type=", &tinrc.post_process_type, POST_PROC_YES))
  588                 break;
  589 
  590             if (match_boolean(buf, "post_process_view=", &tinrc.post_process_view))
  591                 break;
  592 
  593             if (match_string(buf, "posted_articles_file=", tinrc.posted_articles_file, sizeof(tinrc.posted_articles_file)))
  594                 break;
  595 
  596             if (match_boolean(buf, "process_only_unread=", &tinrc.process_only_unread))
  597                 break;
  598 
  599             if (match_boolean(buf, "prompt_followupto=", &tinrc.prompt_followupto))
  600                 break;
  601 
  602             break;
  603 
  604         case 'q':
  605             if (match_string(buf, "quote_chars=", tinrc.quote_chars, sizeof(tinrc.quote_chars))) {
  606                 if (upgrade && upgrade->file_version < 10317) { /* %s/%S changed to %I */
  607                     char *q = tinrc.quote_chars;
  608 
  609                     while (*q) {
  610                         if (*q == '%' && (*(q + 1) == 's' || *(q + 1) == 'S'))
  611                             *(++q) = 'I';
  612 
  613                         q++;
  614                     }
  615                 }
  616                 quote_dash_to_space(tinrc.quote_chars);
  617                 break;
  618             }
  619 
  620             if (match_integer(buf, "quote_style=", &tinrc.quote_style, (QUOTE_COMPRESS|QUOTE_SIGS|QUOTE_EMPTY)))
  621                 break;
  622 
  623 #ifdef HAVE_COLOR
  624             if (match_string(buf, "quote_regex=", tinrc.quote_regex, sizeof(tinrc.quote_regex)))
  625                 break;
  626 
  627             if (match_string(buf, "quote_regex2=", tinrc.quote_regex2, sizeof(tinrc.quote_regex2)))
  628                 break;
  629 
  630             if (match_string(buf, "quote_regex3=", tinrc.quote_regex3, sizeof(tinrc.quote_regex3)))
  631                 break;
  632 #endif /* HAVE_COLOR */
  633 
  634             break;
  635 
  636         case 'r':
  637             if (match_integer(buf, "recent_time=", &tinrc.recent_time, 16383)) /* use INT_MAX? */
  638                 break;
  639 
  640 #if defined(HAVE_LIBICUUC) && defined(MULTIBYTE_ABLE) && defined(HAVE_UNICODE_UBIDI_H) && !defined(NO_LOCALE)
  641             if (match_boolean(buf, "render_bidi=", &tinrc.render_bidi))
  642                 break;
  643 #endif /* HAVE_LIBICUUC && MULTIBYTE_ABLE && HAVE_UNICODE_UBIDI_H && !NO_LOCALE */
  644 
  645             if (match_integer(buf, "reread_active_file_secs=", &tinrc.reread_active_file_secs, 16383)) /* use INT_MAX? */
  646                 break;
  647 
  648             break;
  649 
  650         case 's':
  651             if (match_string(buf, "savedir=", tinrc.savedir, sizeof(tinrc.savedir))) {
  652                 if (tinrc.savedir[0] == '.' && strlen(tinrc.savedir) == 1) {
  653                     char buff[PATH_LEN];
  654 
  655                     get_cwd(buff);
  656                     my_strncpy(tinrc.savedir, buff, sizeof(tinrc.savedir) - 1);
  657                 }
  658                 break;
  659             }
  660 
  661             if (match_integer(buf, "score_limit_kill=", &tinrc.score_limit_kill, 0))
  662                 break;
  663 
  664             if (match_integer(buf, "score_limit_select=", &tinrc.score_limit_select, 0))
  665                 break;
  666 
  667             if (match_integer(buf, "score_kill=", &tinrc.score_kill, 0)) {
  668                 check_score_defaults();
  669                 break;
  670             }
  671 
  672             if (match_integer(buf, "score_select=", &tinrc.score_select, 0)) {
  673                 check_score_defaults();
  674                 break;
  675             }
  676 
  677             if (match_string(buf, "select_format=", tinrc.select_format, sizeof(tinrc.select_format)))
  678                 break;
  679 
  680             if (match_integer(buf, "show_author=", &tinrc.show_author, SHOW_FROM_BOTH))
  681                 break;
  682 
  683             if (match_boolean(buf, "show_description=", &tinrc.show_description)) {
  684                 if (show_description)
  685                     show_description = tinrc.show_description;
  686                 break;
  687             }
  688 
  689             if (match_boolean(buf, "show_only_unread_arts=", &tinrc.show_only_unread_arts))
  690                 break;
  691 
  692             if (match_boolean(buf, "show_only_unread_groups=", &tinrc.show_only_unread_groups))
  693                 break;
  694 
  695             if (match_boolean(buf, "sigdashes=", &tinrc.sigdashes))
  696                 break;
  697 
  698             if (match_string(buf, "sigfile=", tinrc.sigfile, sizeof(tinrc.sigfile)))
  699                 break;
  700 
  701             if (match_boolean(buf, "signature_repost=", &tinrc.signature_repost))
  702                 break;
  703 
  704             if (match_string(buf, "spamtrap_warning_addresses=", tinrc.spamtrap_warning_addresses, sizeof(tinrc.spamtrap_warning_addresses)))
  705                 break;
  706 
  707             if (match_integer(buf, "sort_article_type=", &tinrc.sort_article_type, SORT_ARTICLES_BY_LINES_ASCEND))
  708                 break;
  709 
  710             if (match_integer(buf, "sort_threads_type=", &tinrc.sort_threads_type, SORT_THREADS_BY_LAST_POSTING_DATE_ASCEND))
  711                 break;
  712 
  713 #ifdef USE_HEAPSORT
  714             if (match_integer(buf, "sort_function=", &tinrc.sort_function, MAX_SORT_FUNCS))
  715                 break;
  716 #endif /* USE_HEAPSORT */
  717 
  718             if (match_integer(buf, "scroll_lines=", &tinrc.scroll_lines, 0))
  719                 break;
  720 
  721             if (match_boolean(buf, "show_signatures=", &tinrc.show_signatures))
  722                 break;
  723 
  724             if (match_string(buf, "slashes_regex=", tinrc.slashes_regex, sizeof(tinrc.slashes_regex)))
  725                 break;
  726 
  727             if (match_string(buf, "stars_regex=", tinrc.stars_regex, sizeof(tinrc.stars_regex)))
  728                 break;
  729 
  730             if (match_string(buf, "strokes_regex=", tinrc.strokes_regex, sizeof(tinrc.strokes_regex)))
  731                 break;
  732 
  733 #ifndef USE_CURSES
  734             if (match_boolean(buf, "strip_blanks=", &tinrc.strip_blanks))
  735                 break;
  736 #endif /* !USE_CURSES */
  737 
  738             if (match_integer(buf, "strip_bogus=", &tinrc.strip_bogus, BOGUS_SHOW))
  739                 break;
  740 
  741             if (match_boolean(buf, "strip_newsrc=", &tinrc.strip_newsrc))
  742                 break;
  743 
  744             /* Regexp used to strip "Re: "s and similar */
  745             if (match_string(buf, "strip_re_regex=", tinrc.strip_re_regex, sizeof(tinrc.strip_re_regex)))
  746                 break;
  747 
  748             if (match_string(buf, "strip_was_regex=", tinrc.strip_was_regex, sizeof(tinrc.strip_was_regex)))
  749                 break;
  750 
  751             break;
  752 
  753         case 't':
  754             if (match_integer(buf, "thread_articles=", &tinrc.thread_articles, THREAD_MAX))
  755                 break;
  756 
  757             if (match_integer(buf, "thread_perc=", &tinrc.thread_perc, 100))
  758                 break;
  759 
  760             if (match_string(buf, "thread_format=", tinrc.thread_format, sizeof(tinrc.thread_format)))
  761                 break;
  762 
  763             if (match_integer(buf, "thread_score=", &tinrc.thread_score, THREAD_SCORE_WEIGHT))
  764                 break;
  765 
  766             if (match_boolean(buf, "tex2iso_conv=", &tinrc.tex2iso_conv))
  767                 break;
  768 
  769             if (match_boolean(buf, "thread_catchup_on_exit=", &tinrc.thread_catchup_on_exit))
  770                 break;
  771 
  772 #if defined(HAVE_ICONV_OPEN_TRANSLIT) && defined(CHARSET_CONVERSION)
  773             if (match_boolean(buf, "translit=", &tinrc.translit))
  774                 break;
  775 #endif /* HAVE_ICONV_OPEN_TRANSLIT && CHARSET_CONVERSION */
  776 
  777             if (match_integer(buf, "trim_article_body=", &tinrc.trim_article_body, NUM_TRIM_ARTICLE_BODY))
  778                 break;
  779 
  780             break;
  781 
  782         case 'u':
  783             if (match_string(buf, "underscores_regex=", tinrc.underscores_regex, sizeof(tinrc.underscores_regex)))
  784                 break;
  785 
  786             if (match_boolean(buf, "unlink_article=", &tinrc.unlink_article))
  787                 break;
  788 
  789             if (match_string(buf, "url_handler=", tinrc.url_handler, sizeof(tinrc.url_handler)))
  790                 break;
  791 
  792             if (match_boolean(buf, "url_highlight=", &tinrc.url_highlight))
  793                 break;
  794 
  795             if (match_boolean(buf, "use_mouse=", &tinrc.use_mouse))
  796                 break;
  797 
  798 #ifdef HAVE_KEYPAD
  799             if (match_boolean(buf, "use_keypad=", &tinrc.use_keypad))
  800                 break;
  801 #endif /* HAVE_KEYPAD */
  802 
  803 #ifdef HAVE_COLOR
  804             if (match_boolean(buf, "use_color=", &tinrc.use_color)) {
  805                 use_color = (cmdline.args & CMDLINE_USE_COLOR) ? bool_not(tinrc.use_color) : tinrc.use_color;
  806                 break;
  807             }
  808 #endif /* HAVE_COLOR */
  809 
  810 #ifdef XFACE_ABLE
  811             if (match_boolean(buf, "use_slrnface=", &tinrc.use_slrnface))
  812                 break;
  813 #endif /* XFACE_ABLE */
  814 
  815 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
  816             if (match_boolean(buf, "utf8_graphics=", &tinrc.utf8_graphics)) {
  817                 /* only enable this when local charset is UTF-8 */
  818                 tinrc.utf8_graphics = tinrc.utf8_graphics ? IS_LOCAL_CHARSET("UTF-8") : FALSE;
  819                 break;
  820             }
  821 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
  822 
  823             break;
  824 
  825         case 'v':
  826             if (match_string(buf, "verbatim_begin_regex=", tinrc.verbatim_begin_regex, sizeof(tinrc.verbatim_begin_regex)))
  827                 break;
  828 
  829             if (match_string(buf, "verbatim_end_regex=", tinrc.verbatim_end_regex, sizeof(tinrc.verbatim_end_regex)))
  830                 break;
  831 
  832             if (match_boolean(buf, "verbatim_handling=", &tinrc.verbatim_handling))
  833                 break;
  834 
  835             break;
  836 
  837         case 'w':
  838             if (match_integer(buf, "wildcard=", &tinrc.wildcard, 2))
  839                 break;
  840 
  841             if (match_boolean(buf, "word_highlight=", &tinrc.word_highlight)) {
  842                 word_highlight = tinrc.word_highlight;
  843                 break;
  844             }
  845 
  846             if (match_integer(buf, "wrap_column=", &tinrc.wrap_column, 0))
  847                 break;
  848 
  849             if (match_boolean(buf, "wrap_on_next_unread=", &tinrc.wrap_on_next_unread))
  850                 break;
  851 
  852             if (match_integer(buf, "word_h_display_marks=", &tinrc.word_h_display_marks, MAX_MARK))
  853                 break;
  854 
  855             break;
  856 
  857         case 'x':
  858             if (match_string(buf, "xpost_quote_format=", tinrc.xpost_quote_format, sizeof(tinrc.xpost_quote_format)))
  859                 break;
  860 
  861             break;
  862 
  863         default:
  864             break;
  865         }
  866     }
  867     if (!global_file && upgrade && upgrade->state == RC_UPGRADE)
  868         rc_post_update(fp/* , upgrade */);
  869 
  870     FreeAndNull(upgrade);
  871     fclose(fp);
  872 
  873     /*
  874      * sort out conflicting settings
  875      */
  876 
  877     /* nobody likes to navigate blind */
  878     if (!(tinrc.draw_arrow || tinrc.inverse_okay))
  879         tinrc.draw_arrow = TRUE;
  880 
  881 #ifdef CHARSET_CONVERSION
  882     /*
  883      * check if we have a 7bit charset but a !7bit encoding
  884      * or a 8bit charset but a !8bit encoding, update encoding if needed
  885      */
  886     is_7bit = FALSE;
  887     for (i = 0; txt_mime_7bit_charsets[i] != NULL; i++) {
  888         if (!strcasecmp(txt_mime_charsets[tinrc.mm_network_charset], txt_mime_7bit_charsets[i])) {
  889             is_7bit = TRUE;
  890             break;
  891         }
  892     }
  893     if (is_7bit) {
  894         tinrc.mail_mime_encoding = tinrc.post_mime_encoding = MIME_ENCODING_7BIT;
  895     } else {
  896         if (tinrc.mail_mime_encoding == MIME_ENCODING_7BIT)
  897             tinrc.mail_mime_encoding = MIME_ENCODING_QP;
  898         if (tinrc.post_mime_encoding == MIME_ENCODING_7BIT)
  899             tinrc.post_mime_encoding = MIME_ENCODING_8BIT;
  900     }
  901 #endif /* CHARSET_CONVERSION */
  902 
  903     /* do not use 8 bit headers if mime encoding is not 8bit */
  904     if (tinrc.mail_mime_encoding != MIME_ENCODING_8BIT)
  905         tinrc.mail_8bit_header = FALSE;
  906     if (tinrc.post_mime_encoding != MIME_ENCODING_8BIT)
  907         tinrc.post_8bit_header = FALSE;
  908 
  909     /* set defaults if blank */
  910     if (!*tinrc.editor_format)
  911         STRCPY(tinrc.editor_format, TIN_EDITOR_FMT);
  912     if (!*tinrc.select_format)
  913         STRCPY(tinrc.select_format, DEFAULT_SELECT_FORMAT);
  914     if (!*tinrc.group_format)
  915         STRCPY(tinrc.group_format, DEFAULT_GROUP_FORMAT);
  916     if (!*tinrc.thread_format)
  917         STRCPY(tinrc.thread_format, DEFAULT_THREAD_FORMAT);
  918     if (!*tinrc.date_format)
  919         STRCPY(tinrc.date_format, DEFAULT_DATE_FORMAT);
  920     /* determine local charset */
  921 #if defined(NO_LOCALE) && !defined(CHARSET_CONVERSION)
  922     strcpy(tinrc.mm_local_charset, tinrc.mm_charset);
  923 #endif /* NO_LOCALE && !CHARSET_CONVERSION */
  924     return TRUE;
  925 }
  926 
  927 
  928 /*
  929  * write config defaults to file
  930  */
  931 void
  932 write_config_file(
  933     char *file)
  934 {
  935     FILE *fp;
  936     char *file_tmp;
  937     int i;
  938 
  939     if ((no_write || post_article_and_exit || post_postponed_and_exit) && file_size(file) != -1L)
  940         return;
  941 
  942     /* generate tmp-filename */
  943     file_tmp = get_tmpfilename(file);
  944 
  945     if ((fp = fopen(file_tmp, "w")) == NULL) {
  946         error_message(2, _(txt_filesystem_full_backup), CONFIG_FILE);
  947         free(file_tmp);
  948         return;
  949     }
  950 
  951     wait_message(0, _(txt_saving));
  952 
  953     fprintf(fp, txt_tinrc_header, PRODUCT, TINRC_VERSION, tin_progname, VERSION, RELEASEDATE, RELEASENAME);
  954 
  955     fprintf(fp, "%s", _(txt_savedir.tinrc));
  956     fprintf(fp, "savedir=%s\n\n", tinrc.savedir);
  957 
  958     fprintf(fp, "%s", _(txt_mark_saved_read.tinrc));
  959     fprintf(fp, "mark_saved_read=%s\n\n", print_boolean(tinrc.mark_saved_read));
  960 
  961     fprintf(fp, "%s", _(txt_post_process_type.tinrc));
  962     fprintf(fp, "post_process_type=%d\n\n", tinrc.post_process_type);
  963 
  964     fprintf(fp, "%s", _(txt_post_process_view.tinrc));
  965     fprintf(fp, "post_process_view=%s\n\n", print_boolean(tinrc.post_process_view));
  966 
  967     fprintf(fp, "%s", _(txt_process_only_unread.tinrc));
  968     fprintf(fp, "process_only_unread=%s\n\n", print_boolean(tinrc.process_only_unread));
  969 
  970     fprintf(fp, "%s", _(txt_prompt_followupto.tinrc));
  971     fprintf(fp, "prompt_followupto=%s\n\n", print_boolean(tinrc.prompt_followupto));
  972 
  973     fprintf(fp, "%s", _(txt_confirm_choice.tinrc));
  974     fprintf(fp, "confirm_choice=%d\n\n", tinrc.confirm_choice);
  975 
  976     fprintf(fp, "%s", _(txt_mark_ignore_tags.tinrc));
  977     fprintf(fp, "mark_ignore_tags=%s\n\n", print_boolean(tinrc.mark_ignore_tags));
  978 
  979     fprintf(fp, "%s", _(txt_auto_reconnect.tinrc));
  980     fprintf(fp, "auto_reconnect=%s\n\n", print_boolean(tinrc.auto_reconnect));
  981 
  982     fprintf(fp, "%s", _(txt_draw_arrow.tinrc));
  983     fprintf(fp, "draw_arrow=%s\n\n", print_boolean(tinrc.draw_arrow));
  984 
  985     fprintf(fp, "%s", _(txt_inverse_okay.tinrc));
  986     fprintf(fp, "inverse_okay=%s\n\n", print_boolean(tinrc.inverse_okay));
  987 
  988     fprintf(fp, "%s", _(txt_pos_first_unread.tinrc));
  989     fprintf(fp, "pos_first_unread=%s\n\n", print_boolean(tinrc.pos_first_unread));
  990 
  991     fprintf(fp, "%s", _(txt_show_only_unread_arts.tinrc));
  992     fprintf(fp, "show_only_unread_arts=%s\n\n", print_boolean(tinrc.show_only_unread_arts));
  993 
  994     fprintf(fp, "%s", _(txt_show_only_unread_groups.tinrc));
  995     fprintf(fp, "show_only_unread_groups=%s\n\n", print_boolean(tinrc.show_only_unread_groups));
  996 
  997     fprintf(fp, "%s", _(txt_kill_level.tinrc));
  998     fprintf(fp, "kill_level=%d\n\n", tinrc.kill_level);
  999 
 1000     fprintf(fp, "%s", _(txt_goto_next_unread.tinrc));
 1001     fprintf(fp, "goto_next_unread=%d\n\n", tinrc.goto_next_unread);
 1002 
 1003     fprintf(fp, "%s", _(txt_scroll_lines.tinrc));
 1004     fprintf(fp, "scroll_lines=%d\n\n", tinrc.scroll_lines);
 1005 
 1006     fprintf(fp, "%s", _(txt_catchup_read_groups.tinrc));
 1007     fprintf(fp, "catchup_read_groups=%s\n\n", print_boolean(tinrc.catchup_read_groups));
 1008 
 1009     fprintf(fp, "%s", _(txt_group_catchup_on_exit.tinrc));
 1010     fprintf(fp, "group_catchup_on_exit=%s\n", print_boolean(tinrc.group_catchup_on_exit));
 1011     fprintf(fp, "thread_catchup_on_exit=%s\n\n", print_boolean(tinrc.thread_catchup_on_exit));
 1012 
 1013     fprintf(fp, "%s", _(txt_thread_articles.tinrc));
 1014     fprintf(fp, "thread_articles=%d\n\n", tinrc.thread_articles);
 1015 
 1016     fprintf(fp, "%s", _(txt_thread_perc.tinrc));
 1017     fprintf(fp, "thread_perc=%d\n\n", tinrc.thread_perc);
 1018 
 1019     fprintf(fp, "%s", _(txt_show_description.tinrc));
 1020     fprintf(fp, "show_description=%s\n\n", print_boolean(tinrc.show_description));
 1021 
 1022     fprintf(fp, "%s", _(txt_show_author.tinrc));
 1023     fprintf(fp, "show_author=%d\n\n", tinrc.show_author);
 1024 
 1025     fprintf(fp, "%s", _(txt_news_headers_to_display.tinrc));
 1026     fprintf(fp, "news_headers_to_display=%s\n\n", tinrc.news_headers_to_display);
 1027 
 1028     fprintf(fp, "%s", _(txt_news_headers_to_not_display.tinrc));
 1029     fprintf(fp, "news_headers_to_not_display=%s\n\n", tinrc.news_headers_to_not_display);
 1030 
 1031     fprintf(fp, "%s", _(txt_tinrc_info_in_last_line));
 1032     fprintf(fp, "info_in_last_line=%s\n\n", print_boolean(tinrc.info_in_last_line));
 1033 
 1034     fprintf(fp, "%s", _(txt_sort_article_type.tinrc));
 1035     fprintf(fp, "sort_article_type=%d\n\n", tinrc.sort_article_type);
 1036 
 1037     fprintf(fp, "%s", _(txt_sort_threads_type.tinrc));
 1038     fprintf(fp, "sort_threads_type=%d\n\n", tinrc.sort_threads_type);
 1039 
 1040 #ifdef USE_HEAPSORT
 1041     fprintf(fp, "%s", _(txt_sort_function.tinrc));
 1042     fprintf(fp, "sort_function=%d\n\n", tinrc.sort_function);
 1043 #endif /* USE_HEAPSORT */
 1044 
 1045     fprintf(fp, "%s", _(txt_maildir.tinrc));
 1046     fprintf(fp, "maildir=%s\n\n", tinrc.maildir);
 1047 
 1048     fprintf(fp, "%s", _(txt_mailbox_format.tinrc));
 1049     fprintf(fp, "mailbox_format=%s\n\n", txt_mailbox_formats[tinrc.mailbox_format]);
 1050 
 1051 #ifndef DISABLE_PRINTING
 1052     fprintf(fp, "%s", _(txt_print_header.tinrc));
 1053     fprintf(fp, "print_header=%s\n\n", print_boolean(tinrc.print_header));
 1054 
 1055     fprintf(fp, "%s", _(txt_printer.tinrc));
 1056     fprintf(fp, "printer=%s\n\n", tinrc.printer);
 1057 #endif /* !DISABLE_PRINTING */
 1058 
 1059     fprintf(fp, "%s", _(txt_batch_save.tinrc));
 1060     fprintf(fp, "batch_save=%s\n\n", print_boolean(tinrc.batch_save));
 1061 
 1062     fprintf(fp, "%s", _(txt_editor_format.tinrc));
 1063     fprintf(fp, "editor_format=%s\n\n", tinrc.editor_format);
 1064 
 1065     fprintf(fp, "%s", _(txt_mailer_format.tinrc));
 1066     fprintf(fp, "mailer_format=%s\n\n", tinrc.mailer_format);
 1067 
 1068     fprintf(fp, "%s", _(txt_interactive_mailer.tinrc));
 1069     fprintf(fp, "interactive_mailer=%d\n\n", tinrc.interactive_mailer);
 1070 
 1071     fprintf(fp, "%s", _(txt_thread_score.tinrc));
 1072     fprintf(fp, "thread_score=%d\n\n", tinrc.thread_score);
 1073 
 1074     fprintf(fp, "%s", _(txt_unlink_article.tinrc));
 1075     fprintf(fp, "unlink_article=%s\n\n", print_boolean(tinrc.unlink_article));
 1076 
 1077     fprintf(fp, "%s", _(txt_keep_dead_articles.tinrc));
 1078     fprintf(fp, "keep_dead_articles=%s\n\n", print_boolean(tinrc.keep_dead_articles));
 1079 
 1080     fprintf(fp, "%s", _(txt_posted_articles_file.tinrc));
 1081     fprintf(fp, "posted_articles_file=%s\n\n", tinrc.posted_articles_file);
 1082 
 1083     fprintf(fp, "%s", _(txt_add_posted_to_filter.tinrc));
 1084     fprintf(fp, "add_posted_to_filter=%s\n\n", print_boolean(tinrc.add_posted_to_filter));
 1085 
 1086     fprintf(fp, "%s", _(txt_sigfile.tinrc));
 1087     fprintf(fp, "sigfile=%s\n\n", tinrc.sigfile);
 1088 
 1089     fprintf(fp, "%s", _(txt_sigdashes.tinrc));
 1090     fprintf(fp, "sigdashes=%s\n\n", print_boolean(tinrc.sigdashes));
 1091 
 1092     fprintf(fp, "%s", _(txt_signature_repost.tinrc));
 1093     fprintf(fp, "signature_repost=%s\n\n", print_boolean(tinrc.signature_repost));
 1094 
 1095     fprintf(fp, "%s", _(txt_spamtrap_warning_addresses.tinrc));
 1096     fprintf(fp, "spamtrap_warning_addresses=%s\n\n", tinrc.spamtrap_warning_addresses);
 1097 
 1098     fprintf(fp, "%s", _(txt_url_handler.tinrc));
 1099     fprintf(fp, "url_handler=%s\n\n", tinrc.url_handler);
 1100 
 1101     fprintf(fp, "%s", _(txt_advertising.tinrc));
 1102     fprintf(fp, "advertising=%s\n\n", print_boolean(tinrc.advertising));
 1103 
 1104     fprintf(fp, "%s", _(txt_reread_active_file_secs.tinrc));
 1105     fprintf(fp, "reread_active_file_secs=%d\n\n", tinrc.reread_active_file_secs);
 1106 
 1107 #if defined(HAVE_ALARM) && defined(SIGALRM)
 1108     fprintf(fp, "%s", _(txt_nntp_read_timeout_secs.tinrc));
 1109     fprintf(fp, "nntp_read_timeout_secs=%d\n\n", tinrc.nntp_read_timeout_secs);
 1110 #endif /* HAVE_ALARM && SIGALRM */
 1111 
 1112     fprintf(fp, "%s", _(txt_quote_chars.tinrc));
 1113     fprintf(fp, "quote_chars=%s\n\n", quote_space_to_dash(tinrc.quote_chars));
 1114 
 1115     fprintf(fp, "%s", _(txt_quote_style.tinrc));
 1116     fprintf(fp, "quote_style=%d\n\n", tinrc.quote_style);
 1117 
 1118 #ifdef HAVE_COLOR
 1119     fprintf(fp, "%s", _(txt_quote_regex.tinrc));
 1120     fprintf(fp, "quote_regex=%s\n\n", tinrc.quote_regex);
 1121     fprintf(fp, "%s", _(txt_quote_regex2.tinrc));
 1122     fprintf(fp, "quote_regex2=%s\n\n", tinrc.quote_regex2);
 1123     fprintf(fp, "%s", _(txt_quote_regex3.tinrc));
 1124     fprintf(fp, "quote_regex3=%s\n\n", tinrc.quote_regex3);
 1125 #endif /* HAVE_COLOR */
 1126 
 1127     fprintf(fp, "%s", _(txt_slashes_regex.tinrc));
 1128     fprintf(fp, "slashes_regex=%s\n\n", tinrc.slashes_regex);
 1129     fprintf(fp, "%s", _(txt_stars_regex.tinrc));
 1130     fprintf(fp, "stars_regex=%s\n\n", tinrc.stars_regex);
 1131     fprintf(fp, "%s", _(txt_strokes_regex.tinrc));
 1132     fprintf(fp, "strokes_regex=%s\n\n", tinrc.strokes_regex);
 1133     fprintf(fp, "%s", _(txt_underscores_regex.tinrc));
 1134     fprintf(fp, "underscores_regex=%s\n\n", tinrc.underscores_regex);
 1135 
 1136     fprintf(fp, "%s", _(txt_strip_re_regex.tinrc));
 1137     fprintf(fp, "strip_re_regex=%s\n\n", tinrc.strip_re_regex);
 1138     fprintf(fp, "%s", _(txt_strip_was_regex.tinrc));
 1139     fprintf(fp, "strip_was_regex=%s\n\n", tinrc.strip_was_regex);
 1140 
 1141     fprintf(fp, "%s", _(txt_verbatim_begin_regex.tinrc));
 1142     fprintf(fp, "verbatim_begin_regex=%s\n\n", tinrc.verbatim_begin_regex);
 1143     fprintf(fp, "%s", _(txt_verbatim_end_regex.tinrc));
 1144     fprintf(fp, "verbatim_end_regex=%s\n\n", tinrc.verbatim_end_regex);
 1145 
 1146 #ifdef HAVE_COLOR
 1147     fprintf(fp, "%s", _(txt_extquote_regex.tinrc));
 1148     fprintf(fp, "extquote_regex=%s\n\n", tinrc.extquote_regex);
 1149 #endif /* HAVE_COLOR */
 1150 
 1151     fprintf(fp, "%s", _(txt_show_signatures.tinrc));
 1152     fprintf(fp, "show_signatures=%s\n\n", print_boolean(tinrc.show_signatures));
 1153 
 1154     fprintf(fp, "%s", _(txt_tex2iso_conv.tinrc));
 1155     fprintf(fp, "tex2iso_conv=%s\n\n", print_boolean(tinrc.tex2iso_conv));
 1156 
 1157     fprintf(fp, "%s", _(txt_hide_uue.tinrc));
 1158     fprintf(fp, "hide_uue=%d\n\n", tinrc.hide_uue);
 1159 
 1160     fprintf(fp, "%s", _(txt_news_quote_format.tinrc));
 1161     fprintf(fp, "news_quote_format=%s\n", tinrc.news_quote_format);
 1162     fprintf(fp, "mail_quote_format=%s\n", tinrc.mail_quote_format);
 1163     fprintf(fp, "xpost_quote_format=%s\n\n", tinrc.xpost_quote_format);
 1164 
 1165     fprintf(fp, "%s", _(txt_auto_cc_bcc.tinrc));
 1166     fprintf(fp, "auto_cc_bcc=%d\n\n", tinrc.auto_cc_bcc);
 1167 
 1168 #if defined(MULTIBYTE_ABLE) && !defined(NO_LOCALE)
 1169     fprintf(fp, "%s", _(txt_utf8_graphics.tinrc));
 1170     fprintf(fp, "utf8_graphics=%s\n\n", print_boolean(tinrc.utf8_graphics));
 1171 #endif /* MULTIBYTE_ABLE && !NO_LOCALE */
 1172 
 1173     fprintf(fp, "%s", _(txt_art_marked_deleted.tinrc));
 1174     fprintf(fp, "art_marked_deleted=%"T_CHAR_FMT"\n\n", SPACE_TO_DASH(tinrc.art_marked_deleted));
 1175 
 1176     fprintf(fp, "%s", _(txt_art_marked_inrange.tinrc));
 1177     fprintf(fp, "art_marked_inrange=%"T_CHAR_FMT"\n\n", SPACE_TO_DASH(tinrc.art_marked_inrange));
 1178 
 1179     fprintf(fp, "%s", _(txt_art_marked_return.tinrc));
 1180     fprintf(fp, "art_marked_return=%"T_CHAR_FMT"\n\n", SPACE_TO_DASH(tinrc.art_marked_return));
 1181 
 1182     fprintf(fp, "%s", _(txt_art_marked_selected.tinrc));
 1183     fprintf(fp, "art_marked_selected=%"T_CHAR_FMT"\n\n", SPACE_TO_DASH(tinrc.art_marked_selected));
 1184 
 1185     fprintf(fp, "%s", _(txt_art_marked_recent.tinrc));
 1186     fprintf(fp, "art_marked_recent=%"T_CHAR_FMT"\n\n", SPACE_TO_DASH(tinrc.art_marked_recent));
 1187 
 1188     fprintf(fp, "%s", _(txt_art_marked_unread.tinrc));
 1189     fprintf(fp, "art_marked_unread=%"T_CHAR_FMT"\n\n", SPACE_TO_DASH(tinrc.art_marked_unread));
 1190 
 1191     fprintf(fp, "%s", _(txt_art_marked_read.tinrc));
 1192     fprintf(fp, "art_marked_read=%"T_CHAR_FMT"\n\n", SPACE_TO_DASH(tinrc.art_marked_read));
 1193 
 1194     fprintf(fp, "%s", _(txt_art_marked_killed.tinrc));
 1195     fprintf(fp, "art_marked_killed=%"T_CHAR_FMT"\n\n", SPACE_TO_DASH(tinrc.art_marked_killed));
 1196 
 1197     fprintf(fp, "%s", _(txt_art_marked_read_selected.tinrc));
 1198     fprintf(fp, "art_marked_read_selected=%"T_CHAR_FMT"\n\n", SPACE_TO_DASH(tinrc.art_marked_read_selected));
 1199 
 1200     fprintf(fp, "%s", _(txt_force_screen_redraw.tinrc));
 1201     fprintf(fp, "force_screen_redraw=%s\n\n", print_boolean(tinrc.force_screen_redraw));
 1202 
 1203     fprintf(fp, "%s", _(txt_inews_prog.tinrc));
 1204     fprintf(fp, "inews_prog=%s\n\n", tinrc.inews_prog);
 1205 
 1206 #ifdef USE_CANLOCK
 1207     fprintf(fp, "%s", _(txt_cancel_lock_algo.tinrc));
 1208     fprintf(fp, "cancel_lock_algo=%s\n\n", txt_cancel_lock_algos[tinrc.cancel_lock_algo]);
 1209 #endif /* USE_CANLOCK */
 1210 
 1211     fprintf(fp, "%s", _(txt_auto_list_thread.tinrc));
 1212     fprintf(fp, "auto_list_thread=%s\n\n", print_boolean(tinrc.auto_list_thread));
 1213 
 1214     fprintf(fp, "%s", _(txt_wrap_on_next_unread.tinrc));
 1215     fprintf(fp, "wrap_on_next_unread=%s\n\n", print_boolean(tinrc.wrap_on_next_unread));
 1216 
 1217     fprintf(fp, "%s", _(txt_use_mouse.tinrc));
 1218     fprintf(fp, "use_mouse=%s\n\n", print_boolean(tinrc.use_mouse));
 1219 
 1220 #ifndef USE_CURSES
 1221     fprintf(fp, "%s", _(txt_strip_blanks.tinrc));
 1222     fprintf(fp, "strip_blanks=%s\n\n", print_boolean(tinrc.strip_blanks));
 1223 #endif /* !USE_CURSES */
 1224 
 1225     fprintf(fp, "%s", _(txt_abbreviate_groupname.tinrc));
 1226     fprintf(fp, "abbreviate_groupname=%s\n\n", print_boolean(tinrc.abbreviate_groupname));
 1227 
 1228     fprintf(fp, "%s", _(txt_beginner_level.tinrc));
 1229     fprintf(fp, "beginner_level=%s\n\n", print_boolean(tinrc.beginner_level));
 1230 
 1231     fprintf(fp, "%s", _(txt_filter_days.tinrc));
 1232     fprintf(fp, "default_filter_days=%d\n\n", tinrc.filter_days);
 1233 
 1234     fprintf(fp, "%s", _(txt_cache_overview_files.tinrc));
 1235     fprintf(fp, "cache_overview_files=%s\n\n", print_boolean(tinrc.cache_overview_files));
 1236 
 1237     fprintf(fp, "%s", _(txt_getart_limit.tinrc));
 1238     fprintf(fp, "getart_limit=%d\n\n", tinrc.getart_limit);
 1239 
 1240     fprintf(fp, "%s", _(txt_recent_time.tinrc));
 1241     fprintf(fp, "recent_time=%d\n\n", tinrc.recent_time);
 1242 
 1243     fprintf(fp, "%s", _(txt_score_limit_kill.tinrc));
 1244     fprintf(fp, "score_limit_kill=%d\n\n", tinrc.score_limit_kill);
 1245 
 1246     fprintf(fp, "%s", _(txt_score_kill.tinrc));
 1247     fprintf(fp, "score_kill=%d\n\n", tinrc.score_kill);
 1248 
 1249     fprintf(fp, "%s", _(txt_score_limit_select.tinrc));
 1250     fprintf(fp, "score_limit_select=%d\n\n", tinrc.score_limit_select);
 1251 
 1252     fprintf(fp, "%s", _(txt_score_select.tinrc));
 1253     fprintf(fp, "score_select=%d\n\n", tinrc.score_select);
 1254 
 1255 #ifdef HAVE_COLOR
 1256     fprintf(fp, "%s", _(txt_use_color.tinrc));
 1257     fprintf(fp, "use_color=%s\n\n", print_boolean(tinrc.use_color));
 1258 
 1259     fprintf(fp, "%s", _(txt_tinrc_colors));
 1260 
 1261     fprintf(fp, "%s", _(txt_col_normal.tinrc));
 1262     fprintf(fp, "col_normal=%d\n\n", tinrc.col_normal);
 1263 
 1264     fprintf(fp, "%s", _(txt_col_back.tinrc));
 1265     fprintf(fp, "col_back=%d\n\n", tinrc.col_back);
 1266 
 1267     fprintf(fp, "%s", _(txt_col_invers_bg.tinrc));
 1268     fprintf(fp, "col_invers_bg=%d\n\n", tinrc.col_invers_bg);
 1269 
 1270     fprintf(fp, "%s", _(txt_col_invers_fg.tinrc));
 1271     fprintf(fp, "col_invers_fg=%d\n\n", tinrc.col_invers_fg);
 1272 
 1273     fprintf(fp, "%s", _(txt_col_text.tinrc));
 1274     fprintf(fp, "col_text=%d\n\n", tinrc.col_text);
 1275 
 1276     fprintf(fp, "%s", _(txt_col_minihelp.tinrc));
 1277     fprintf(fp, "col_minihelp=%d\n\n", tinrc.col_minihelp);
 1278 
 1279     fprintf(fp, "%s", _(txt_col_help.tinrc));
 1280     fprintf(fp, "col_help=%d\n\n", tinrc.col_help);
 1281 
 1282     fprintf(fp, "%s", _(txt_col_message.tinrc));
 1283     fprintf(fp, "col_message=%d\n\n", tinrc.col_message);
 1284 
 1285     fprintf(fp, "%s", _(txt_col_quote.tinrc));
 1286     fprintf(fp, "col_quote=%d\n\n", tinrc.col_quote);
 1287 
 1288     fprintf(fp, "%s", _(txt_col_quote2.tinrc));
 1289     fprintf(fp, "col_quote2=%d\n\n", tinrc.col_quote2);
 1290 
 1291     fprintf(fp, "%s", _(txt_col_quote3.tinrc));
 1292     fprintf(fp, "col_quote3=%d\n\n", tinrc.col_quote3);
 1293 
 1294     fprintf(fp, "%s", _(txt_col_head.tinrc));
 1295     fprintf(fp, "col_head=%d\n\n", tinrc.col_head);
 1296 
 1297     fprintf(fp, "%s", _(txt_col_newsheaders.tinrc));
 1298     fprintf(fp, "col_newsheaders=%d\n\n", tinrc.col_newsheaders);
 1299 
 1300     fprintf(fp, "%s", _(txt_col_subject.tinrc));
 1301     fprintf(fp, "col_subject=%d\n\n", tinrc.col_subject);
 1302 
 1303     fprintf(fp, "%s", _(txt_col_extquote.tinrc));
 1304     fprintf(fp, "col_extquote=%d\n\n", tinrc.col_extquote);
 1305 
 1306     fprintf(fp, "%s", _(txt_col_response.tinrc));
 1307     fprintf(fp, "col_response=%d\n\n", tinrc.col_response);
 1308 
 1309     fprintf(fp, "%s", _(txt_col_from.tinrc));
 1310     fprintf(fp, "col_from=%d\n\n", tinrc.col_from);
 1311 
 1312     fprintf(fp, "%s", _(txt_col_title.tinrc));
 1313     fprintf(fp, "col_title=%d\n\n", tinrc.col_title);
 1314 
 1315     fprintf(fp, "%s", _(txt_col_signature.tinrc));
 1316     fprintf(fp, "col_signature=%d\n\n", tinrc.col_signature);
 1317 
 1318     fprintf(fp, "%s", _(txt_col_urls.tinrc));
 1319     fprintf(fp, "col_urls=%d\n\n", tinrc.col_urls);
 1320 
 1321     fprintf(fp, "%s", _(txt_col_verbatim.tinrc));
 1322     fprintf(fp, "col_verbatim=%d\n\n", tinrc.col_verbatim);
 1323 #endif /* HAVE_COLOR */
 1324 
 1325     fprintf(fp, "%s", _(txt_url_highlight.tinrc));
 1326     fprintf(fp, "url_highlight=%s\n\n", print_boolean(tinrc.url_highlight));
 1327 
 1328     fprintf(fp, "%s", _(txt_word_highlight.tinrc));
 1329     fprintf(fp, "word_highlight=%s\n\n", print_boolean(tinrc.word_highlight));
 1330 
 1331     fprintf(fp, "%s", _(txt_word_h_display_marks.tinrc));
 1332     fprintf(fp, "word_h_display_marks=%d\n\n", tinrc.word_h_display_marks);
 1333 
 1334 #ifdef HAVE_COLOR
 1335     fprintf(fp, "%s", _(txt_col_markstar.tinrc));
 1336     fprintf(fp, "col_markstar=%d\n\n", tinrc.col_markstar);
 1337     fprintf(fp, "%s", _(txt_col_markdash.tinrc));
 1338     fprintf(fp, "col_markdash=%d\n\n", tinrc.col_markdash);
 1339     fprintf(fp, "%s", _(txt_col_markslash.tinrc));
 1340     fprintf(fp, "col_markslash=%d\n\n", tinrc.col_markslash);
 1341     fprintf(fp, "%s", _(txt_col_markstroke.tinrc));
 1342     fprintf(fp, "col_markstroke=%d\n\n", tinrc.col_markstroke);
 1343 #endif /* HAVE_COLOR */
 1344 
 1345     fprintf(fp, "%s", _(txt_mono_markstar.tinrc));
 1346     fprintf(fp, "mono_markstar=%d\n\n", tinrc.mono_markstar);
 1347     fprintf(fp, "%s", _(txt_mono_markdash.tinrc));
 1348     fprintf(fp, "mono_markdash=%d\n\n", tinrc.mono_markdash);
 1349     fprintf(fp, "%s", _(txt_mono_markslash.tinrc));
 1350     fprintf(fp, "mono_markslash=%d\n\n", tinrc.mono_markslash);
 1351     fprintf(fp, "%s", _(txt_mono_markstroke.tinrc));
 1352     fprintf(fp, "mono_markstroke=%d\n\n", tinrc.mono_markstroke);
 1353 
 1354     fprintf(fp, "%s", _(txt_mail_address.tinrc));
 1355     fprintf(fp, "mail_address=%s\n\n", tinrc.mail_address);
 1356 
 1357 #ifdef XFACE_ABLE
 1358     fprintf(fp, "%s", _(txt_use_slrnface.tinrc));
 1359     fprintf(fp, "use_slrnface=%s\n\n", print_boolean(tinrc.use_slrnface));
 1360 #endif /* XFACE_ABLE */
 1361 
 1362     fprintf(fp, "%s", _(txt_wrap_column.tinrc));
 1363     fprintf(fp, "wrap_column=%d\n\n", tinrc.wrap_column);
 1364 
 1365     fprintf(fp, "%s", _(txt_trim_article_body.tinrc));
 1366     fprintf(fp, "trim_article_body=%d\n\n", tinrc.trim_article_body);
 1367 
 1368 #ifndef CHARSET_CONVERSION
 1369     fprintf(fp, "%s", _(txt_mm_charset.tinrc));
 1370     fprintf(fp, "mm_charset=%s\n\n", tinrc.mm_charset);
 1371 #else
 1372     fprintf(fp, "%s", _(txt_mm_network_charset.tinrc));
 1373     fprintf(fp, "mm_network_charset=%s\n\n", txt_mime_charsets[tinrc.mm_network_charset]);
 1374 
 1375 #   ifdef NO_LOCALE
 1376     fprintf(fp, "%s", _(txt_mm_local_charset.tinrc));
 1377     fprintf(fp, "mm_local_charset=%s\n\n", tinrc.mm_local_charset);
 1378 #   endif /* NO_LOCALE */
 1379 #   ifdef HAVE_ICONV_OPEN_TRANSLIT
 1380     fprintf(fp, "%s", _(txt_translit.tinrc));
 1381     fprintf(fp, "translit=%s\n\n", print_boolean(tinrc.translit));
 1382 #   endif /* HAVE_ICONV_OPEN_TRANSLIT */
 1383 #endif /* !CHARSET_CONVERSION */
 1384 
 1385     fprintf(fp, "%s", _(txt_post_mime_encoding.tinrc));
 1386     fprintf(fp, "post_mime_encoding=%s\n", txt_mime_encodings[tinrc.post_mime_encoding]);
 1387     fprintf(fp, "mail_mime_encoding=%s\n\n", txt_mime_encodings[tinrc.mail_mime_encoding]);
 1388 
 1389     fprintf(fp, "%s", _(txt_post_8bit_header.tinrc));
 1390     fprintf(fp, "post_8bit_header=%s\n\n", print_boolean(tinrc.post_8bit_header));
 1391 
 1392     fprintf(fp, "%s", _(txt_mail_8bit_header.tinrc));
 1393     fprintf(fp, "mail_8bit_header=%s\n\n", print_boolean(tinrc.mail_8bit_header));
 1394 
 1395     fprintf(fp, "%s", _(txt_metamail_prog.tinrc));
 1396     fprintf(fp, "metamail_prog=%s\n\n", tinrc.metamail_prog);
 1397 
 1398     fprintf(fp, "%s", _(txt_ask_for_metamail.tinrc));
 1399     fprintf(fp, "ask_for_metamail=%s\n\n", print_boolean(tinrc.ask_for_metamail));
 1400 
 1401 #ifdef HAVE_KEYPAD
 1402     fprintf(fp, "%s", _(txt_use_keypad.tinrc));
 1403     fprintf(fp, "use_keypad=%s\n\n", print_boolean(tinrc.use_keypad));
 1404 #endif /* HAVE_KEYPAD */
 1405 
 1406     fprintf(fp, "%s", _(txt_alternative_handling.tinrc));
 1407     fprintf(fp, "alternative_handling=%s\n\n", print_boolean(tinrc.alternative_handling));
 1408 
 1409     fprintf(fp, "%s", _(txt_verbatim_handling.tinrc));
 1410     fprintf(fp, "verbatim_handling=%s\n\n", print_boolean(tinrc.verbatim_handling));
 1411 
 1412 #ifdef HAVE_COLOR
 1413     fprintf(fp, "%s", _(txt_extquote_handling.tinrc));
 1414     fprintf(fp, "extquote_handling=%s\n\n", print_boolean(tinrc.extquote_handling));
 1415 #endif /* HAVE_COLOR */
 1416 
 1417     fprintf(fp, "%s", _(txt_strip_newsrc.tinrc));
 1418     fprintf(fp, "strip_newsrc=%s\n\n", print_boolean(tinrc.strip_newsrc));
 1419 
 1420     fprintf(fp, "%s", _(txt_strip_bogus.tinrc));
 1421     fprintf(fp, "strip_bogus=%d\n\n", tinrc.strip_bogus);
 1422 
 1423     fprintf(fp, "%s", _(txt_select_format.tinrc));
 1424     fprintf(fp, "select_format=%s\n\n", tinrc.select_format);
 1425 
 1426     fprintf(fp, "%s", _(txt_group_format.tinrc));
 1427     fprintf(fp, "group_format=%s\n\n", tinrc.group_format);
 1428 
 1429     fprintf(fp, "%s", _(txt_thread_format.tinrc));
 1430     fprintf(fp, "thread_format=%s\n\n", tinrc.thread_format);
 1431 
 1432     fprintf(fp, "%s", _(txt_date_format.tinrc));
 1433     fprintf(fp, "date_format=%s\n\n", tinrc.date_format);
 1434 
 1435     fprintf(fp, "%s", _(txt_wildcard.tinrc));
 1436     fprintf(fp, "wildcard=%d\n\n", tinrc.wildcard);
 1437 
 1438 #ifdef HAVE_UNICODE_NORMALIZATION
 1439     fprintf(fp, "%s", _(txt_normalization_form.tinrc));
 1440     fprintf(fp, "normalization_form=%d\n\n", tinrc.normalization_form);
 1441 #endif /* HAVE_UNICODE_NORMALIZATION */
 1442 
 1443 #if defined(HAVE_LIBICUUC) && defined(MULTIBYTE_ABLE) && defined(HAVE_UNICODE_UBIDI_H) && !defined(NO_LOCALE)
 1444     fprintf(fp, "%s", _(txt_render_bidi.tinrc));
 1445     fprintf(fp, "render_bidi=%s\n\n", print_boolean(tinrc.render_bidi));
 1446 #endif /* HAVE_LIBICUUC && MULTIBYTE_ABLE && HAVE_UNICODE_UBIDI_H && !NO_LOCALE */
 1447 
 1448     fprintf(fp, "%s", _(txt_tinrc_filter));
 1449     fprintf(fp, "default_filter_kill_header=%d\n", tinrc.default_filter_kill_header);
 1450     fprintf(fp, "default_filter_kill_global=%s\n", print_boolean(tinrc.default_filter_kill_global));
 1451     fprintf(fp, "default_filter_kill_case=%s\n", print_boolean(tinrc.default_filter_kill_case));
 1452     fprintf(fp, "default_filter_kill_expire=%s\n", print_boolean(tinrc.default_filter_kill_expire));
 1453     fprintf(fp, "default_filter_select_header=%d\n", tinrc.default_filter_select_header);
 1454     fprintf(fp, "default_filter_select_global=%s\n", print_boolean(tinrc.default_filter_select_global));
 1455     fprintf(fp, "default_filter_select_case=%s\n", print_boolean(tinrc.default_filter_select_case));
 1456     fprintf(fp, "default_filter_select_expire=%s\n\n", print_boolean(tinrc.default_filter_select_expire));
 1457 
 1458     fprintf(fp, "%s", _(txt_tinrc_defaults));
 1459     fprintf(fp, "default_save_mode=%c\n", tinrc.default_save_mode);
 1460     fprintf(fp, "default_author_search=%s\n", tinrc.default_search_author);
 1461     fprintf(fp, "default_goto_group=%s\n", tinrc.default_goto_group);
 1462     fprintf(fp, "default_config_search=%s\n", tinrc.default_search_config);
 1463     fprintf(fp, "default_group_search=%s\n", tinrc.default_search_group);
 1464     fprintf(fp, "default_subject_search=%s\n", tinrc.default_search_subject);
 1465     fprintf(fp, "default_art_search=%s\n", tinrc.default_search_art);
 1466     fprintf(fp, "default_repost_group=%s\n", tinrc.default_repost_group);
 1467     fprintf(fp, "default_mail_address=%s\n", tinrc.default_mail_address);
 1468     fprintf(fp, "default_move_group=%d\n", tinrc.default_move_group);
 1469 #ifndef DONT_HAVE_PIPING
 1470     fprintf(fp, "default_pipe_command=%s\n", tinrc.default_pipe_command);
 1471 #endif /* !DONT_HAVE_PIPING */
 1472     fprintf(fp, "default_post_newsgroups=%s\n", tinrc.default_post_newsgroups);
 1473     fprintf(fp, "default_post_subject=%s\n", tinrc.default_post_subject);
 1474     fprintf(fp, "default_range_group=%s\n", tinrc.default_range_group);
 1475     fprintf(fp, "default_range_select=%s\n", tinrc.default_range_select);
 1476     fprintf(fp, "default_range_thread=%s\n", tinrc.default_range_thread);
 1477     fprintf(fp, "default_pattern=%s\n", tinrc.default_pattern);
 1478     fprintf(fp, "default_save_file=%s\n", tinrc.default_save_file);
 1479     fprintf(fp, "default_select_pattern=%s\n", tinrc.default_select_pattern);
 1480     fprintf(fp, "default_shell_command=%s\n\n", tinrc.default_shell_command);
 1481 
 1482     fprintf(fp, "%s", _(txt_tinrc_newnews));
 1483     {
 1484         char timestring[30];
 1485         int j = find_newnews_index(nntp_server);
 1486 
 1487         /*
 1488          * Newnews timestamps in tinrc are bogus as of tin 1.5.19 because they
 1489          * are now stored in a separate file to prevent overwriting them from
 1490          * another instance running concurrently. Except for the current server,
 1491          * however, we must remember them because otherwise we would lose them
 1492          * after the first start of a tin 1.5.19 (or later) version.
 1493          */
 1494         for (i = 0; i < num_newnews; i++) {
 1495             if (i == j)
 1496                 continue;
 1497             if (my_strftime(timestring, sizeof(timestring) - 1, "%Y-%m-%d %H:%M:%S UTC", gmtime(&(newnews[i].time))))
 1498                 fprintf(fp, "newnews=%s %lu (%s)\n", newnews[i].host, (unsigned long int) newnews[i].time, timestring);
 1499         }
 1500     }
 1501 
 1502 #ifdef HAVE_FCHMOD
 1503     fchmod(fileno(fp), (mode_t) (S_IRUSR|S_IWUSR)); /* rename_file() preserves mode */
 1504 #else
 1505 #   ifdef HAVE_CHMOD
 1506     chmod(file_tmp, (mode_t) (S_IRUSR|S_IWUSR)); /* rename_file() preserves mode */
 1507 #   endif /* HAVE_CHMOD */
 1508 #endif /* HAVE_FCHMOD */
 1509 
 1510     if ((i = ferror(fp)) || fclose(fp)) {
 1511         error_message(2, _(txt_filesystem_full), CONFIG_FILE);
 1512         if (i) {
 1513             clearerr(fp);
 1514             fclose(fp);
 1515         }
 1516     } else
 1517         rename_file(file_tmp, file);
 1518 
 1519     free(file_tmp);
 1520     write_server_config();
 1521 }
 1522 
 1523 
 1524 t_bool
 1525 match_boolean(
 1526     char *line,
 1527     const char *pat,
 1528     t_bool *dst)
 1529 {
 1530     size_t patlen = strlen(pat);
 1531 
 1532     if (STRNCASECMPEQ(line, pat, patlen)) {
 1533         *dst = (t_bool) (STRNCASECMPEQ(&line[patlen], "ON", 2) ? TRUE : FALSE);
 1534         return TRUE;
 1535     }
 1536     return FALSE;
 1537 }
 1538 
 1539 
 1540 #ifdef HAVE_COLOR
 1541 static t_bool
 1542 match_color(
 1543     char *line,
 1544     const char *pat,
 1545     int *dst,
 1546     int max)
 1547 {
 1548     size_t patlen = strlen(pat);
 1549 
 1550     if (STRNCMPEQ(line, pat, patlen)) {
 1551         int n;
 1552         t_bool found = FALSE;
 1553 
 1554         for (n = 0; n < MAX_COLOR + 1; n++) {
 1555             if (!strcasecmp(&line[patlen], txt_colors[n])) {
 1556                 found = TRUE;
 1557                 *dst = n;
 1558             }
 1559         }
 1560 
 1561         if (!found)
 1562             *dst = atoi(&line[patlen]);
 1563 
 1564         if (max) {
 1565             if (max == MAX_BACKCOLOR && *dst > max && *dst <= MAX_COLOR)
 1566                 *dst %= MAX_BACKCOLOR + 1;
 1567             else if ((*dst < -1) || (*dst > max)) {
 1568                 my_fprintf(stderr, _(txt_value_out_of_range), pat, *dst, max);
 1569                 *dst = 0;
 1570             }
 1571         } else
 1572             *dst = -1;
 1573         return TRUE;
 1574     }
 1575     return FALSE;
 1576 }
 1577 #endif /* HAVE_COLOR */
 1578 
 1579 
 1580 /*
 1581  * If pat matches the start of line, convert rest of line to an integer, dst
 1582  * If maxval is set, constrain value to 0 <= dst <= maxlen and return TRUE.
 1583  * If no match is made, return FALSE.
 1584  */
 1585 t_bool
 1586 match_integer(
 1587     char *line,
 1588     const char *pat,
 1589     int *dst,
 1590     int maxval)
 1591 {
 1592     size_t patlen = strlen(pat);
 1593 
 1594     if (STRNCMPEQ(line, pat, patlen)) {
 1595         *dst = atoi(&line[patlen]);
 1596 
 1597         if (maxval) {
 1598             if ((*dst < 0) || (*dst > maxval)) {
 1599                 my_fprintf(stderr, _(txt_value_out_of_range), pat, *dst, maxval);
 1600                 *dst = 0;
 1601             }
 1602         }
 1603         return TRUE;
 1604     }
 1605     return FALSE;
 1606 }
 1607 
 1608 
 1609 t_bool
 1610 match_long(
 1611     char *line,
 1612     const char *pat,
 1613     long *dst)
 1614 {
 1615     size_t patlen = strlen(pat);
 1616 
 1617     if (STRNCMPEQ(line, pat, patlen)) {
 1618         *dst = atol(&line[patlen]);
 1619         return TRUE;
 1620     }
 1621     return FALSE;
 1622 }
 1623 
 1624 
 1625 /*
 1626  * If the 'pat' keyword matches, lookup & return an index into the table
 1627  */
 1628 t_bool
 1629 match_list(
 1630     char *line,
 1631     constext *pat,
 1632     constext *const *table,
 1633     int *dst)
 1634 {
 1635     size_t patlen = strlen(pat);
 1636 
 1637     if (STRNCMPEQ(line, pat, patlen)) {
 1638         char temp[LEN];
 1639         size_t n;
 1640 
 1641         line += patlen;
 1642         *dst = 0;   /* default, if no match */
 1643         for (n = 0; table[n] != NULL; n++) {
 1644             if (match_item(line, table[n], temp, sizeof(temp))) {
 1645                 *dst = (int) n;
 1646                 break;
 1647             }
 1648         }
 1649         return TRUE;
 1650     }
 1651     return FALSE;
 1652 }
 1653 
 1654 
 1655 t_bool
 1656 match_string(
 1657     char *line,
 1658     const char *pat,
 1659     char *dst,
 1660     size_t dstlen)
 1661 {
 1662     size_t patlen = strlen(pat);
 1663 
 1664     if (STRNCMPEQ(line, pat, patlen) && (strlen(line) > patlen)) {
 1665         if (dst != NULL && dstlen >= 1)
 1666             my_strncpy(dst, &line[patlen], dstlen - 1);
 1667         return TRUE;
 1668     }
 1669     return FALSE;
 1670 }
 1671 
 1672 
 1673 /* like mach_string() but looks for 100% exact matches */
 1674 static t_bool
 1675 match_item(
 1676     char *line,
 1677     const char *pat,
 1678     char *dst,
 1679     size_t dstlen)
 1680 {
 1681     char *ptr;
 1682     char *nline = my_strdup(line);
 1683     size_t patlen = strlen(pat);
 1684 
 1685     if ((ptr = strchr(nline, '\n')) != NULL) /* terminate on \n */
 1686         *ptr = '\0';
 1687 
 1688     if (!strcasecmp(nline, pat)) {
 1689         if (dst != NULL) {
 1690             strncpy(dst, &nline[patlen], dstlen);
 1691             dst[dstlen ? (dstlen - 1) : 0] = '\0';
 1692         }
 1693         free(nline);
 1694         return TRUE;
 1695     }
 1696     free(nline);
 1697     return FALSE;
 1698 }
 1699 
 1700 
 1701 const char *
 1702 print_boolean(
 1703     t_bool value)
 1704 {
 1705     return txt_onoff[value != FALSE ? 1 : 0];
 1706 }
 1707 
 1708 
 1709 /*
 1710  * convert underlines to spaces in a string
 1711  */
 1712 void
 1713 quote_dash_to_space(
 1714     char *str)
 1715 {
 1716     char *ptr;
 1717 
 1718     for (ptr = str; *ptr; ptr++) {
 1719         if (*ptr == '_')
 1720             *ptr = ' ';
 1721     }
 1722 }
 1723 
 1724 
 1725 /*
 1726  * convert spaces to underlines in a string
 1727  */
 1728 char *
 1729 quote_space_to_dash(
 1730     char *str)
 1731 {
 1732     char *ptr, *dst;
 1733     static char buf[PATH_LEN];
 1734 
 1735     dst = buf;
 1736     for (ptr = str; *ptr; ptr++) {
 1737         if (*ptr == ' ')
 1738             *dst = '_';
 1739         else
 1740             *dst = *ptr;
 1741         dst++;
 1742     }
 1743     *dst = '\0';
 1744 
 1745     return buf;
 1746 }
 1747 
 1748 
 1749 /*
 1750  * Written by: Brad Viviano and Scott Powers (bcv & swp)
 1751  *
 1752  * Takes a 1d string and turns it into a 2d array of strings.
 1753  *
 1754  * Watch out for the frees! You must free(*argv) and then free(argv)!
 1755  * NOTHING ELSE! Do _NOT_ free the individual args of argv.
 1756  */
 1757 char **
 1758 ulBuildArgv(
 1759     char *cmd,
 1760     int *new_argc)
 1761 {
 1762     char **new_argv = NULL;
 1763     char *buf, *tmp;
 1764     int i = 0;
 1765 
 1766     if (!cmd || !*cmd) {
 1767         *new_argc = 0;
 1768         return NULL;
 1769     }
 1770 
 1771     for (tmp = cmd; isspace((int) *tmp); tmp++)
 1772         ;
 1773 
 1774     buf = my_strdup(tmp);
 1775     tmp = buf;
 1776 
 1777     new_argv = my_calloc(1, sizeof(char *));
 1778 
 1779     while (*tmp) {
 1780         if (!isspace((int) *tmp)) { /* found the beginning of a word */
 1781             new_argv[i] = tmp;
 1782             for (; *tmp && !isspace((int) *tmp); tmp++)
 1783                 ;
 1784             if (*tmp) {
 1785                 *tmp = '\0';
 1786                 tmp++;
 1787             }
 1788             i++;
 1789             new_argv = my_realloc(new_argv, ((size_t) (i + 1) * sizeof(char *)));
 1790             new_argv[i] = NULL;
 1791         } else
 1792             tmp++;
 1793     }
 1794     *new_argc = i;
 1795     return new_argv;
 1796 }
 1797 
 1798 
 1799 /*
 1800  * auto update tinrc
 1801  * called at the beginning of read_config_file()
 1802  */
 1803 static t_bool
 1804 rc_update(
 1805     FILE *fp)
 1806 {
 1807     char buf[LEN];
 1808     int show_info = 1;
 1809     t_bool auto_bcc = FALSE;
 1810     t_bool auto_cc = FALSE;
 1811     t_bool confirm_to_quit = FALSE;
 1812     t_bool confirm_action = FALSE;
 1813     t_bool compress_quotes = FALSE;
 1814     t_bool set_goto_next_unread = FALSE;
 1815     t_bool hide_uue = FALSE;
 1816     t_bool keep_posted_articles = FALSE;
 1817     t_bool pgdn_goto_next = FALSE;
 1818     t_bool quote_empty_lines = FALSE;
 1819     t_bool quote_signatures = FALSE;
 1820     t_bool save_to_mmdf_mailbox = FALSE;
 1821     t_bool show_last_line_prev_page = FALSE;
 1822     t_bool show_lines = FALSE;
 1823     t_bool show_score = FALSE;
 1824     t_bool show_lines_or_score = FALSE;
 1825     t_bool space_goto_next_unread = FALSE;
 1826     t_bool tab_goto_next_unread = FALSE;
 1827     t_bool use_builtin_inews = FALSE;
 1828     t_bool use_getart_limit = FALSE;
 1829     t_bool use_mailreader_i = FALSE;
 1830     t_bool use_metamail = FALSE;
 1831 
 1832     if (!fp)
 1833         return FALSE;
 1834 
 1835     /* rewind(fp); */
 1836     while (fgets(buf, (int) sizeof(buf), fp) != NULL) {
 1837         if (buf[0] == '#' || buf[0] == '\n')
 1838             continue;
 1839 
 1840         switch (my_tolower((unsigned char) buf[0])) {
 1841             case 'a':
 1842                 if (match_boolean(buf, "auto_bcc=", &auto_bcc))
 1843                     break;
 1844 
 1845                 if (match_boolean(buf, "auto_cc=", &auto_cc))
 1846                     break;
 1847                 break;
 1848 
 1849             case 'c':
 1850                 if (match_boolean(buf, "confirm_action=", &confirm_action))
 1851                     break;
 1852                 if (match_boolean(buf, "confirm_to_quit=", &confirm_to_quit))
 1853                     break;
 1854                 if (match_boolean(buf, "compress_quotes=", &compress_quotes))
 1855                     break;
 1856                 break;
 1857 
 1858             case 'd':
 1859                 /* simple rename */
 1860                 if (match_string(buf, "default_editor_format=", tinrc.editor_format, sizeof(tinrc.editor_format)))
 1861                     break;
 1862                 /* simple rename */
 1863                 if (match_string(buf, "default_maildir=", tinrc.maildir, sizeof(tinrc.maildir)))
 1864                     break;
 1865                 /* simple rename */
 1866                 if (match_string(buf, "default_mailer_format=", tinrc.mailer_format, sizeof(tinrc.mailer_format)))
 1867                     break;
 1868                 /* simple rename */
 1869 #ifndef DISABLE_PRINTING
 1870                 if (match_string(buf, "default_printer=", tinrc.printer, sizeof(tinrc.printer)))
 1871                     break;
 1872 #endif /* !DISABLE_PRINTING */
 1873                 /* simple rename */
 1874                 if (match_string(buf, "default_regex_pattern=", tinrc.default_pattern, sizeof(tinrc.default_pattern)))
 1875                     break;
 1876                 /* simple rename */
 1877                 if (match_string(buf, "default_savedir=", tinrc.savedir, sizeof(tinrc.savedir))) {
 1878                     if (tinrc.savedir[0] == '.' && strlen(tinrc.savedir) == 1) {
 1879                         char buff[PATH_LEN];
 1880 
 1881                         get_cwd(buff);
 1882                         my_strncpy(tinrc.savedir, buff, sizeof(tinrc.savedir) - 1);
 1883                     }
 1884                     break;
 1885                 }
 1886                 /* 1. simple rename
 1887                  *
 1888                  * 2. previous versions has always passed groupname to external
 1889                  *    commands, now we look for %G
 1890                  */
 1891                 if (match_string(buf, "default_sigfile=", tinrc.sigfile, sizeof(tinrc.sigfile))) {
 1892                     size_t l = strlen(tinrc.sigfile);
 1893 
 1894                     if (tinrc.sigfile[0] == '!' && (tinrc.sigfile[l - 2] != '%' || tinrc.sigfile[l - 1] != 'G')) {
 1895                         char *newbuf = my_malloc(sizeof(tinrc.sigfile) + 4);
 1896 
 1897                         sprintf(newbuf, "%s %s", tinrc.sigfile, "%G");
 1898                         my_strncpy(tinrc.sigfile, newbuf, sizeof(tinrc.sigfile) - 1);
 1899                         free(newbuf);
 1900                     }
 1901                     break;
 1902                 }
 1903                 break;
 1904 
 1905             case 'h':
 1906                 if (match_boolean(buf, "hide_uue=", &hide_uue))
 1907                     break;
 1908                 break;
 1909 
 1910             case 'k':
 1911                 if (match_boolean(buf, "keep_posted_articles=", &keep_posted_articles))
 1912                     break;
 1913                 break;
 1914 
 1915             case 'p':
 1916                 if (match_boolean(buf, "pgdn_goto_next=", &pgdn_goto_next)) {
 1917                     set_goto_next_unread = TRUE;
 1918                     break;
 1919                 }
 1920                 break;
 1921 
 1922             case 'q':
 1923                 if (match_boolean(buf, "quote_signatures=", &quote_signatures))
 1924                     break;
 1925                 if (match_boolean(buf, "quote_empty_lines=", &quote_empty_lines))
 1926                     break;
 1927                 break;
 1928 
 1929             case 's':
 1930                 if (match_boolean(buf, "space_goto_next_unread=", &space_goto_next_unread)) {
 1931                     set_goto_next_unread = TRUE;
 1932                     break;
 1933                 }
 1934                 if (match_boolean(buf, "save_to_mmdf_mailbox=", &save_to_mmdf_mailbox))
 1935                     break;
 1936                 if (match_integer(buf, "show_info=", &show_info, 3))
 1937                     break;
 1938                 if (match_boolean(buf, "show_last_line_prev_page=", &show_last_line_prev_page))
 1939                     break;
 1940                 if (match_boolean(buf, "show_lines=", &show_lines)) {
 1941                     show_lines_or_score = TRUE;
 1942                     break;
 1943                 }
 1944                 /* simple rename */
 1945                 if (match_boolean(buf, "show_only_unread=", &tinrc.show_only_unread_arts))
 1946                     break;
 1947                 if (match_boolean(buf, "show_score=", &show_score)) {
 1948                     show_lines_or_score = TRUE;
 1949                     break;
 1950                 }
 1951                 break;
 1952 
 1953             case 't':
 1954                 if (match_boolean(buf, "tab_goto_next_unread=", &tab_goto_next_unread)) {
 1955                     set_goto_next_unread = TRUE;
 1956                     break;
 1957                 }
 1958                 break;
 1959 
 1960             case 'u':
 1961                 if (match_boolean(buf, "use_builtin_inews=", &use_builtin_inews))
 1962                     break;
 1963                 if (match_boolean(buf, "use_getart_limit=", &use_getart_limit))
 1964                     break;
 1965                 if (match_boolean(buf, "use_mailreader_i=", &use_mailreader_i))
 1966                     break;
 1967                 if (match_boolean(buf, "use_metamail=", &use_metamail))
 1968                     break;
 1969                 break;
 1970 
 1971             default:
 1972                 break;
 1973         }
 1974     }
 1975 
 1976     /* update the values */
 1977     tinrc.auto_cc_bcc = (auto_cc ? 1 : 0) + (auto_bcc ? 2 : 0);
 1978     tinrc.confirm_choice = (confirm_action ? 1 : 0) + (confirm_to_quit ? 3 : 0);
 1979 
 1980     if (!use_getart_limit)
 1981         tinrc.getart_limit = 0;
 1982 
 1983     if (set_goto_next_unread) {
 1984         tinrc.goto_next_unread = 0;
 1985         if (pgdn_goto_next || space_goto_next_unread)
 1986             tinrc.goto_next_unread |= GOTO_NEXT_UNREAD_PGDN;
 1987         if (tab_goto_next_unread)
 1988             tinrc.goto_next_unread |= GOTO_NEXT_UNREAD_TAB;
 1989     }
 1990 
 1991     if (hide_uue)
 1992         tinrc.hide_uue = 1;
 1993 
 1994     if (keep_posted_articles)
 1995         STRCPY(tinrc.posted_articles_file, "posted");
 1996 
 1997     tinrc.quote_style = (compress_quotes ? QUOTE_COMPRESS : 0) + (quote_empty_lines ? QUOTE_EMPTY : 0) + (quote_signatures ? QUOTE_SIGS : 0);
 1998 
 1999     tinrc.mailbox_format = (save_to_mmdf_mailbox ? 2 : 0);
 2000 
 2001     if (show_lines_or_score)
 2002         show_info = (show_lines ? 1 : 0) + (show_score ? 2 : 0);
 2003 
 2004     switch (show_info) {
 2005         case 0:
 2006             STRCPY(tinrc.group_format, "%n %m %R  %s  %F");
 2007             STRCPY(tinrc.thread_format, "%n %m  %T  %F");
 2008             break;
 2009 
 2010         case 2:
 2011             STRCPY(tinrc.group_format, "%n %m %R %S  %s  %F");
 2012             STRCPY(tinrc.thread_format, "%n %m  [%S]  %T  %F");
 2013             break;
 2014 
 2015         case 3:
 2016             STRCPY(tinrc.group_format, "%n %m %R %L %S  %s  %F");
 2017             STRCPY(tinrc.thread_format, "%n %m  [%L,%S]  %T  %F");
 2018             break;
 2019 
 2020         default:
 2021             break;
 2022     }
 2023 
 2024     if (show_last_line_prev_page)
 2025         tinrc.scroll_lines = -1;
 2026 
 2027     if (use_builtin_inews)
 2028         STRCPY(tinrc.inews_prog, INTERNAL_CMD);
 2029 
 2030     if (use_mailreader_i)
 2031         tinrc.interactive_mailer = INTERACTIVE_WITHOUT_HEADERS;
 2032 
 2033     if (!use_metamail || getenv("NOMETAMAIL") != NULL)
 2034         STRCPY(tinrc.metamail_prog, INTERNAL_CMD);
 2035     else
 2036         my_strncpy(tinrc.metamail_prog, METAMAIL_CMD, sizeof(tinrc.metamail_prog) - 1);
 2037 
 2038     rewind(fp);
 2039     return TRUE;
 2040 }
 2041 
 2042 
 2043 /*
 2044  * auto update tinrc
 2045  * called at the end of read_config_file()
 2046  * useful to update variables which are already present in tinrc
 2047  *
 2048  * pass upgrade to this function once we need to exactly check
 2049  * upgrade->file_version, upgrade->current_version
 2050  */
 2051 static t_bool
 2052 rc_post_update(
 2053     FILE *fp
 2054     /* , struct t_version *upgrade */)
 2055 {
 2056     char buf[LEN];
 2057     int groupname_max_length = 0;
 2058 
 2059     if (!fp)
 2060         return FALSE;
 2061 
 2062     rewind(fp);
 2063     while (fgets(buf, (int) sizeof(buf), fp) != NULL) {
 2064         if (buf[0] == '#' || buf[0] == '\n')
 2065             continue;
 2066 
 2067         switch (my_tolower((unsigned char) buf[0])) {
 2068             case 'c':
 2069 #ifdef USE_CANLOCK
 2070                 {
 2071                     t_bool cancel_locks = TRUE;
 2072 
 2073                     if (match_boolean(buf, "cancel_locks=", &cancel_locks)) {
 2074                         if (!cancel_locks)
 2075                             tinrc.cancel_lock_algo = 0;
 2076                         break;
 2077                     }
 2078                 }
 2079 #endif /* USE_CANLOCK */
 2080                 break;
 2081 
 2082             case 'g':
 2083                 if (match_integer(buf, "groupname_max_length=", &groupname_max_length, 132))
 2084                     break;
 2085                 break;
 2086 
 2087             case 's':
 2088                 /*
 2089                  * previous versions has always passed groupname to external
 2090                  * commands, now we look for %G
 2091                  */
 2092                 if (match_string(buf, "sigfile=", tinrc.sigfile, sizeof(tinrc.sigfile))) {
 2093                     size_t l = strlen(tinrc.sigfile);
 2094 
 2095                     if (tinrc.sigfile[0] == '!' && (tinrc.sigfile[l - 2] != '%' || tinrc.sigfile[l - 1] != 'G')) {
 2096                         char *newbuf = my_malloc(sizeof(tinrc.sigfile) + 4);
 2097 
 2098                         sprintf(newbuf, "%s %s", tinrc.sigfile, "%G");
 2099                         my_strncpy(tinrc.sigfile, newbuf, sizeof(tinrc.sigfile) - 1);
 2100                         free(newbuf);
 2101                     }
 2102                     break;
 2103                 }
 2104                 break;
 2105 
 2106             default:
 2107                 break;
 2108         }
 2109     }
 2110 
 2111     /* update the values */
 2112     if (groupname_max_length > 0 && groupname_max_length != 32) {
 2113         char length[LEN];
 2114         char *dest, *d, *f, *l;
 2115 
 2116         snprintf(length, sizeof(length), ",%d", groupname_max_length);
 2117 
 2118         d = dest = my_malloc(strlen(tinrc.select_format) + strlen(length) + 1);
 2119         f = tinrc.select_format;
 2120         l = length;
 2121 
 2122         while (*f) {
 2123             if (*f == 'G') {
 2124                 while (*l)
 2125                     *d++ = *l++;
 2126             }
 2127             *d++ = *f++;
 2128         }
 2129         *d = '\0';
 2130         STRCPY(tinrc.select_format, dest);
 2131         free(dest);
 2132     }
 2133 
 2134     return TRUE;
 2135 }
 2136 
 2137 
 2138 void
 2139 read_server_config(
 2140     void)
 2141 {
 2142     FILE *fp;
 2143     char *line;
 2144     char file[PATH_LEN];
 2145     char newnews_info[LEN];
 2146     char serverdir[PATH_LEN];
 2147     struct t_version *upgrade = NULL;
 2148 
 2149 #ifdef NNTP_ABLE
 2150     if (read_news_via_nntp && !read_saved_news && nntp_tcp_port != IPPORT_NNTP)
 2151         snprintf(file, sizeof(file), "%s:%u", nntp_server, nntp_tcp_port);
 2152     else
 2153 #endif /* NNTP_ABLE */
 2154     {
 2155         STRCPY(file, quote_space_to_dash(nntp_server));
 2156     }
 2157     joinpath(serverdir, sizeof(serverdir), rcdir, file);
 2158     joinpath(file, sizeof(file), serverdir, SERVERCONFIG_FILE);
 2159     joinpath(local_newsgroups_file, sizeof(local_newsgroups_file), serverdir, NEWSGROUPS_FILE);
 2160 
 2161     if ((fp = fopen(file, "r")) == NULL)
 2162         return;
 2163 
 2164     while ((line = tin_fgets(fp, FALSE)) != NULL) {
 2165         if ((*line == '#') || (*line == '\0'))
 2166             continue;
 2167 
 2168         if (match_string(line, "last_newnews=", newnews_info, sizeof(newnews_info))) {
 2169             size_t tmp_len = strlen(nntp_server) + strlen(newnews_info) + 2;
 2170             char *tmp_info = my_malloc(tmp_len);
 2171 
 2172             snprintf(tmp_info, tmp_len, "%s %s", nntp_server, newnews_info);
 2173             load_newnews_info(tmp_info);
 2174             free(tmp_info);
 2175             continue;
 2176         }
 2177 
 2178         if (match_string(line, "version=", NULL, 0)) {
 2179             if (upgrade != NULL) /* ignore duplicate version lines; first match counts */
 2180                 continue;
 2181 
 2182             upgrade = check_upgrade(line, "version=", SERVERCONFIG_VERSION);
 2183             if (upgrade->state == RC_IGNORE) /* Expected version number; nothing to do -> continue */
 2184                 continue;
 2185 
 2186             /* Nothing to do yet for RC_UPGRADE and RC_DOWNGRADE */
 2187             continue;
 2188         }
 2189     }
 2190     fclose(fp);
 2191     FreeAndNull(upgrade);
 2192 }
 2193 
 2194 
 2195 static void
 2196 write_server_config(
 2197     void)
 2198 {
 2199     FILE *fp;
 2200     char *file_tmp;
 2201     char file[PATH_LEN];
 2202     char timestring[30];
 2203     char serverdir[PATH_LEN];
 2204     int i;
 2205     struct stat statbuf;
 2206 
 2207     if (read_saved_news)
 2208         /* don't update server files while reading locally stored articles */
 2209         return;
 2210 #ifdef NNTP_ABLE
 2211     if (read_news_via_nntp && nntp_tcp_port != IPPORT_NNTP)
 2212         snprintf(file, sizeof(file), "%s:%u", nntp_server, nntp_tcp_port);
 2213     else
 2214 #endif /* NNTP_ABLE */
 2215     {
 2216         STRCPY(file, nntp_server);
 2217     }
 2218     joinpath(serverdir, sizeof(serverdir), rcdir, file);
 2219     joinpath(file, sizeof(file), serverdir, SERVERCONFIG_FILE);
 2220 
 2221     if ((no_write || post_article_and_exit || post_postponed_and_exit) && file_size(file) != -1L)
 2222         return;
 2223 
 2224     if (stat(serverdir, &statbuf) == -1) {
 2225         if (my_mkdir(serverdir, (mode_t) (S_IRWXU)) == -1)
 2226             /* Can't create directory TODO: Add error handling */
 2227             return;
 2228     }
 2229 
 2230     /* generate tmp-filename */
 2231     file_tmp = get_tmpfilename(file);
 2232 
 2233     if ((fp = fopen(file_tmp, "w")) == NULL) {
 2234         error_message(2, _(txt_filesystem_full_backup), SERVERCONFIG_FILE);
 2235         free(file_tmp);
 2236         return;
 2237     }
 2238 
 2239     fprintf(fp, _(txt_serverconfig_header), PRODUCT, tin_progname, VERSION, RELEASEDATE, RELEASENAME, PRODUCT, PRODUCT);
 2240     fprintf(fp, "version=%s\n", SERVERCONFIG_VERSION);
 2241 
 2242     if ((i = find_newnews_index(nntp_server)) >= 0) {
 2243         if (my_strftime(timestring, sizeof(timestring) - 1, "%Y-%m-%d %H:%M:%S UTC", gmtime(&(newnews[i].time))))
 2244             fprintf(fp, "last_newnews=%lu (%s)\n", (unsigned long int) newnews[i].time, timestring);
 2245     }
 2246 
 2247 #ifdef HAVE_FCHMOD
 2248     fchmod(fileno(fp), (mode_t) (S_IRUSR|S_IWUSR)); /* rename_file() preserves mode */
 2249 #else
 2250 #   ifdef HAVE_CHMOD
 2251     chmod(file_tmp, (mode_t) (S_IRUSR|S_IWUSR)); /* rename_file() preserves mode */
 2252 #   endif /* HAVE_CHMOD */
 2253 #endif /* HAVE_FCHMOD */
 2254 
 2255     if ((i = ferror(fp)) || fclose(fp)) {
 2256         error_message(2, _(txt_filesystem_full), SERVERCONFIG_FILE);
 2257         if (i) {
 2258             clearerr(fp);
 2259             fclose(fp);
 2260         }
 2261     } else
 2262         rename_file(file_tmp, file);
 2263 
 2264     free(file_tmp);
 2265 }