"Fossies" - the Fresh Open Source Software Archive

Member "tin-2.4.1/src/main.c" (12 Oct 2016, 26402 Bytes) of package /linux/misc/tin-2.4.1.tar.gz:


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 "main.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.4.0_vs_2.4.1.

    1 /*
    2  *  Project   : tin - a Usenet reader
    3  *  Module    : main.c
    4  *  Author    : I. Lea & R. Skrenta
    5  *  Created   : 1991-04-01
    6  *  Updated   : main.c
    7  *  Notes     :
    8  *
    9  * Copyright (c) 1991-2017 Iain Lea <iain@bricbrac.de>, Rich Skrenta <skrenta@pbm.com>
   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  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. The name of the author may not be used to endorse or promote
   21  *    products derived from this software without specific prior written
   22  *    permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
   25  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   26  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
   28  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
   30  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   31  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   32  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   33  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   34  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   35  */
   36 
   37 
   38 #ifndef TIN_H
   39 #   include "tin.h"
   40 #endif /* !TIN_H */
   41 #ifndef TCURSES_H
   42 #   include "tcurses.h"
   43 #endif /* !TCURSES_H */
   44 #ifndef VERSION_H
   45 #   include "version.h"
   46 #endif /* !VERSION_H */
   47 
   48 signed long int read_newsrc_lines = -1;
   49 
   50 static char **cmdargs;
   51 static int num_cmdargs;
   52 static int max_cmdargs;
   53 
   54 static t_bool catchup = FALSE;      /* mark all arts read in all subscribed groups */
   55 static t_bool update_index = FALSE;     /* update local overviews */
   56 static t_bool check_any_unread = FALSE; /* print/return status if any unread */
   57 static t_bool mail_news = FALSE;        /* mail all arts to specified user */
   58 static t_bool save_news = FALSE;        /* save all arts to savedir structure */
   59 static t_bool start_any_unread = FALSE; /* only start if unread news */
   60 
   61 
   62 /*
   63  * Local prototypes
   64  */
   65 static void create_mail_save_dirs(void);
   66 static void read_cmd_line_options(int argc, char *argv[]);
   67 static void show_intro_page(void);
   68 static void update_index_files(void);
   69 static void usage(char *theProgname);
   70 
   71 
   72 /*
   73  * OK lets start the ball rolling...
   74  */
   75 int
   76 main(
   77     int argc,
   78     char *argv[])
   79 {
   80     int count, start_groupnum;
   81     int num_cmd_line_groups = 0;
   82     t_bool tmp_no_write;
   83 
   84     cmd_line = TRUE;
   85 
   86     /* initialize locale support */
   87 #if defined(HAVE_SETLOCALE) && !defined(NO_LOCALE)
   88     if (setlocale(LC_ALL, "")) {
   89 #   ifdef ENABLE_NLS
   90         bindtextdomain(NLS_TEXTDOMAIN, LOCALEDIR);
   91         textdomain(NLS_TEXTDOMAIN);
   92 #   endif /* ENABLE_NLS */
   93     } else
   94         error_message(4, txt_error_locale);
   95 #endif /* HAVE_SETLOCALE && !NO_LOCALE */
   96 
   97     /*
   98      * determine local charset
   99      */
  100 #ifndef NO_LOCALE
  101     {
  102         const char *p;
  103 
  104         if ((p = tin_nl_langinfo(CODESET)) != NULL) {
  105             if (!strcasecmp(p, "ANSI_X3.4-1968"))
  106                 STRCPY(tinrc.mm_local_charset, "US-ASCII");
  107             else
  108                 STRCPY(tinrc.mm_local_charset, p);
  109         }
  110     }
  111 #endif /* !NO_LOCALE */
  112     /* always set a default value */
  113     if (!*tinrc.mm_local_charset)
  114         STRCPY(tinrc.mm_local_charset, "US-ASCII");
  115 
  116     set_signal_handlers();
  117 
  118     debug = 0;  /* debug OFF */
  119 
  120     tin_progname = my_malloc(strlen(argv[0]) + 1);
  121     base_name(argv[0], tin_progname);
  122 
  123 #ifdef NNTP_ONLY
  124     read_news_via_nntp = TRUE;
  125 #else
  126     /*
  127      * If called as rtin, read news remotely via NNTP
  128      */
  129     if (tin_progname[0] == 'r') {
  130 #   ifdef NNTP_ABLE
  131         read_news_via_nntp = TRUE;
  132 #   else
  133         error_message(2, _(txt_option_not_enabled), "-DNNTP_ABLE");
  134         free(tin_progname);
  135         giveup();
  136 #   endif /* NNTP_ABLE */
  137     }
  138 #endif /* NNTP_ONLY */
  139 
  140     /*
  141      * Set up initial array sizes, char *'s: homedir, newsrc, etc.
  142      */
  143     init_alloc();
  144     hash_init();
  145     init_selfinfo();
  146     init_group_hash();
  147 
  148     /*
  149      * Process envargs & command line options
  150      * These override the configured in values
  151      */
  152     read_cmd_line_options(argc, argv);
  153 
  154     /* preinit keybindings if interactive */
  155     if (!batch_mode)
  156         setup_default_keys();
  157 
  158     /*
  159      * Read user local & global config files
  160      * These override the compiled in defaults
  161      *
  162      * must be called before setup_screen()
  163      */
  164     read_config_file(global_config_file, TRUE);
  165     read_config_file(local_config_file, FALSE);
  166 
  167     tmp_no_write = no_write; /* keep no_write */
  168     no_write = TRUE;        /* don't allow any writing back during startup */
  169 
  170     if (!batch_mode) {
  171 #ifdef M_UNIX
  172 #   ifndef USE_CURSES
  173         if (!get_termcaps()) {
  174             error_message(2, _(txt_screen_init_failed), tin_progname);
  175             free_all_arrays();
  176             giveup();
  177         }
  178 #   endif /* !USE_CURSES */
  179 #endif /* M_UNIX */
  180 
  181         /*
  182          * Init curses emulation
  183          */
  184         if (!InitScreen()) {
  185             error_message(2, _(txt_screen_init_failed), tin_progname);
  186             free_all_arrays();
  187             giveup();
  188         }
  189 
  190         EndInverse();
  191 
  192         /*
  193          * This depends on various things in tinrc
  194          */
  195         setup_screen();
  196     }
  197 
  198     if (!batch_mode || verbose)
  199         wait_message(0, "%s\n", cvers);
  200 
  201     /*
  202      * Connect to nntp server?
  203      */
  204     if (!nntp_server || !*nntp_server)
  205         nntp_server = getserverbyfile(NNTP_SERVER_FILE);
  206     if (read_news_via_nntp && !read_saved_news && nntp_open()) {
  207         nntp_close();
  208         free_all_arrays();
  209         giveup();
  210     }
  211 
  212     read_server_config();
  213 
  214     /*
  215      * exit early - unfortunately we can't do that in read_cmd_line_options()
  216      * as nntp_caps.over_cmd is set in nntp_open()
  217      *
  218      * TODO: does the logic make sense? what
  219      * if (update_index && !nntp_caps.over_cmd && !tinrc.cache_overview_files)
  220      * no error message? why?
  221      */
  222     if (update_index && nntp_caps.over_cmd && !tinrc.cache_overview_files) {
  223         error_message(2, _(txt_batch_update_unavail), tin_progname, print_boolean(tinrc.cache_overview_files));
  224         free_all_arrays();
  225         giveup();
  226     }
  227 
  228     /*
  229      * Check if overview indexes contain Xref: lines
  230      */
  231 #ifdef NNTP_ABLE
  232     if ((read_news_via_nntp && nntp_caps.over_cmd) || !read_news_via_nntp)
  233 #endif /* NNTP_ABLE */
  234         xref_supported = overview_xref_support();
  235 
  236     /*
  237      * avoid empty regexp, we also need to do this in batch_mode
  238      * as read_overview() calls eat_re() which uses a regexp to
  239      * modify the subject *sigh*
  240      */
  241     postinit_regexp();
  242 
  243     if (!(batch_mode || post_postponed_and_exit)) {
  244         /*
  245          * Read user specific keybindings and input history
  246          */
  247         wait_message(0, _(txt_reading_keymap_file));
  248         read_keymap_file();
  249         read_input_history_file();
  250 
  251         /*
  252          * Load the mail & news active files into active[]
  253          *
  254          * create_save_active_file cannot write to active.save
  255          * if no_write != FALSE, so restore original value temporarily
  256          */
  257         if (read_saved_news) {
  258             no_write = tmp_no_write;
  259             create_save_active_file();
  260             no_write = TRUE;
  261         }
  262     }
  263 
  264 #ifdef HAVE_MH_MAIL_HANDLING
  265     read_mail_active_file();
  266 #endif /* HAVE_MH_MAIL_HANDLING */
  267 
  268     /*
  269      * Initialise active[] and add new newsgroups to start of my_group[]
  270      * also reads global/local attributes
  271      */
  272     selmenu.max = 0;
  273     /*
  274      * we need to restore the original no_write mode to be able to handle
  275      * $AUTOSUBSCRIBE groups
  276      */
  277     no_write = tmp_no_write;
  278     read_attributes_file(TRUE);
  279     read_attributes_file(FALSE);
  280     start_groupnum = read_news_active_file();
  281 #ifdef DEBUG
  282     debug_print_active();
  283 #endif /* DEBUG */
  284 
  285     /*
  286      * Read in users filter preferences file. This has to be done before
  287      * quick post because the filters might be updated.
  288      */
  289     read_filter_file(filter_file);
  290 
  291     no_write = TRUE;
  292 #ifdef DEBUG
  293     debug_print_filters();
  294 #endif /* DEBUG */
  295 
  296     /*
  297      * Preloads active[] with command line groups. They will follow any
  298      * new newsgroups
  299      */
  300     if (!post_postponed_and_exit)
  301         num_cmd_line_groups = read_cmd_line_groups();
  302 
  303     /*
  304      * Quick post an article and exit if -w or -o specified
  305      */
  306     if (post_article_and_exit || post_postponed_and_exit) {
  307         no_write = tmp_no_write; /* restore original value */
  308         quick_post_article(post_postponed_and_exit);
  309         wait_message(2, _(txt_exiting));
  310         no_write = TRUE; /* disable newsrc updates */
  311         tin_done(EXIT_SUCCESS, NULL);
  312     }
  313 
  314     /* TODO: replace hardcoded key-name in txt_info_postponed */
  315     if ((count = count_postponed_articles()))
  316         wait_message(3, _(txt_info_postponed), count, PLURAL(count, txt_article));
  317 
  318     /*
  319      * Read text descriptions for mail and/or news groups
  320      */
  321     if (show_description && !batch_mode) {
  322         no_write = tmp_no_write; /* restore original value */
  323         read_descriptions(TRUE);
  324         no_write = TRUE; /* disable newsrc updates */
  325     }
  326 
  327     /* what about "if (!no_write)" here? */
  328     create_mail_save_dirs();
  329     if (created_rcdir) /* first start */
  330         write_config_file(local_config_file);
  331 
  332     if (!tmp_no_write)  /* do not (over)write oldnewsrc with -X */
  333         backup_newsrc();
  334 
  335     /*
  336      * Load my_groups[] from the .newsrc file. We append these groups to any
  337      * new newsgroups and command line newsgroups already loaded. Also does
  338      * auto-subscribe to groups specified in /usr/lib/news/subscriptions
  339      * locally or via NNTP if reading news remotely (LIST SUBSCRIPTIONS)
  340      */
  341     /*
  342      * TODO:
  343      * if (num_cmd_line_groups != 0 && check_any_unread)
  344      * don't read newsrc.
  345      * This makes -Z handle command line newsgroups. Test & document
  346      */
  347     read_newsrc_lines = read_newsrc(newsrc, FALSE);
  348     no_write = tmp_no_write; /* restore old value */
  349 
  350     /*
  351      * We have to show all groups with command line groups
  352      */
  353     if (num_cmd_line_groups)
  354         tinrc.show_only_unread_groups = FALSE;
  355     else
  356         toggle_my_groups(NULL);
  357 
  358     /*
  359      * Check/start if any new/unread articles
  360      */
  361     if (check_any_unread)
  362         tin_done(check_start_save_any_news(CHECK_ANY_NEWS, catchup), NULL);
  363 
  364     if (start_any_unread) {
  365         batch_mode = TRUE;          /* Suppress some unwanted on-screen garbage */
  366         if ((start_groupnum = check_start_save_any_news(START_ANY_NEWS, catchup)) == -1) {
  367             batch_mode = FALSE;
  368             tin_done(EXIT_SUCCESS, NULL);
  369         }
  370         batch_mode = FALSE;
  371     }
  372 
  373     /*
  374      * Mail any new articles to specified user
  375      * or
  376      * Save any new articles to savedir structure for later reading
  377      *
  378      * TODO: should we temporarely set
  379      *       getart_limit=-1,thread_articles=0,sort_article_type=0
  380      *       for speed reasons?
  381      */
  382     if (mail_news || save_news) {
  383         check_start_save_any_news(mail_news ? MAIL_ANY_NEWS : SAVE_ANY_NEWS, catchup);
  384         tin_done(EXIT_SUCCESS, NULL);
  385     }
  386 
  387     /*
  388      * Catchup newsrc file (-c option)
  389      */
  390     if (batch_mode && catchup && !update_index) {
  391         catchup_newsrc_file();
  392         tin_done(EXIT_SUCCESS, NULL);
  393     }
  394 
  395     /*
  396      * Update index files (-u option), also does catchup if requested
  397      */
  398     if (update_index)
  399         update_index_files();
  400 
  401     /*
  402      * the code below this point can't be reached in batch mode
  403      */
  404 
  405     /*
  406      * If first time print welcome screen
  407      */
  408     if (created_rcdir)
  409         show_intro_page();
  410 
  411 #ifdef XFACE_ABLE
  412     if (tinrc.use_slrnface && !batch_mode)
  413         slrnface_start();
  414 #endif /* XFACE_ABLE */
  415 
  416 #ifdef USE_CURSES
  417     /* Turn scrolling off now the startup messages have been displayed */
  418     scrollok(stdscr, FALSE);
  419 #endif /* USE_CURSES */
  420 
  421     /*
  422      * Work loop
  423      */
  424     selection_page(start_groupnum, num_cmd_line_groups);
  425     /* NOTREACHED */
  426     return 0;
  427 }
  428 
  429 
  430 /*
  431  * process command line options
  432  * [01235789beEFijJkKLOtTyY] are unused
  433  * [W] is reserved
  434  * [BCPU] have been in use at some time, but now are unused
  435  */
  436 #define OPTIONS "46aAcdD:f:g:G:hHI:lm:M:nNop:qQrRs:SuvVwxXzZ"
  437 
  438 static void
  439 read_cmd_line_options(
  440     int argc,
  441     char *argv[])
  442 {
  443     int ch;
  444     t_bool newsrc_set = FALSE;
  445 
  446     envargs(&argc, &argv, "TINRC");
  447 
  448     while ((ch = getopt(argc, argv, OPTIONS)) != -1) {
  449         switch (ch) {
  450 
  451             case '4':
  452 #if defined(NNTP_ABLE) && defined(INET6)
  453                 force_ipv4 = TRUE;
  454                 read_news_via_nntp = TRUE;
  455 #else
  456 #   ifdef NNTP_ABLE
  457                 error_message(2, _(txt_option_not_enabled), "-DENABLE_IPV6");
  458 #   else
  459                 error_message(2, _(txt_option_not_enabled), "-DNNTP_ABLE");
  460 #   endif /* NNTP_ABLE */
  461                 free_all_arrays();
  462                 giveup();
  463                 /* keep lint quiet: */
  464                 /* NOTREACHED */
  465 #endif /* NNTP_ABLE && INET6 */
  466                 break;
  467 
  468             case '6':
  469 #if defined(NNTP_ABLE) && defined(INET6)
  470                 force_ipv6 = TRUE;
  471                 read_news_via_nntp = TRUE;
  472 #   else
  473 #   ifdef NNTP_ABLE
  474                 error_message(2, _(txt_option_not_enabled), "-DENABLE_IPV6");
  475 #   else
  476                 error_message(2, _(txt_option_not_enabled), "-DNNTP_ABLE");
  477 #   endif /* NNTP_ABLE */
  478                 free_all_arrays();
  479                 giveup();
  480                 /* keep lint quiet: */
  481                 /* NOTREACHED */
  482 #endif /* NNTP_ABLE && INET6 */
  483                 break;
  484 
  485             case 'a':
  486 #ifdef HAVE_COLOR
  487                 cmdline.args |= CMDLINE_USE_COLOR;
  488 #else
  489                 error_message(2, _(txt_option_not_enabled), "-DHAVE_COLOR");
  490                 free_all_arrays();
  491                 giveup();
  492                 /* keep lint quiet: */
  493                 /* NOTREACHED */
  494 #endif /* HAVE_COLOR */
  495                 break;
  496 
  497             case 'A':
  498 #ifdef NNTP_ABLE
  499                 force_auth_on_conn_open = TRUE;
  500                 read_news_via_nntp = TRUE;
  501 #else
  502                 error_message(2, _(txt_option_not_enabled), "-DNNTP_ABLE");
  503                 free_all_arrays();
  504                 giveup();
  505                 /* keep lint quiet: */
  506                 /* NOTREACHED */
  507 #endif /* NNTP_ABLE */
  508                 break;
  509 
  510             case 'c':
  511                 batch_mode = TRUE;
  512                 catchup = TRUE;
  513                 break;
  514 
  515             case 'd':
  516                 show_description = FALSE;
  517                 break;
  518 
  519             case 'D':       /* debug mode */
  520 #ifdef DEBUG
  521                 debug = atoi(optarg);
  522                 debug_delete_files();
  523 #else
  524                 error_message(2, _(txt_option_not_enabled), "-DDEBUG");
  525                 free_all_arrays();
  526                 giveup();
  527                 /* keep lint quiet: */
  528                 /* NOTREACHED */
  529 #endif /* DEBUG */
  530                 break;
  531 
  532             case 'f':   /* newsrc file */
  533                 my_strncpy(newsrc, optarg, sizeof(newsrc) - 1);
  534                 newsrc_set = TRUE;
  535                 break;
  536 
  537             case 'G':
  538                 cmdline.getart_limit = atoi(optarg);
  539                 cmdline.args |= CMDLINE_GETART_LIMIT;
  540                 break;
  541 
  542             case 'g':   /* select alternative NNTP-server, implies -r */
  543 #ifdef NNTP_ABLE
  544                 my_strncpy(cmdline.nntpserver, optarg, sizeof(cmdline.nntpserver) - 1);
  545                 cmdline.args |= CMDLINE_NNTPSERVER;
  546                 read_news_via_nntp = TRUE;
  547 #else
  548                 error_message(2, _(txt_option_not_enabled), "-DNNTP_ABLE");
  549                 free_all_arrays();
  550                 giveup();
  551                 /* keep lint quiet: */
  552                 /* NOTREACHED */
  553 #endif /* NNTP_ABLE */
  554                 break;
  555 
  556             case 'H':
  557                 show_intro_page();
  558                 free_all_arrays();
  559                 exit(EXIT_SUCCESS);
  560                 /* keep lint quiet: */
  561                 /* FALLTHROUGH */
  562 
  563             case 'I':
  564                 my_strncpy(index_newsdir, optarg, sizeof(index_newsdir) - 1);
  565                 break;
  566 
  567             case 'l':
  568                 list_active = TRUE;
  569                 break;
  570 
  571             case 'm':
  572                 my_strncpy(cmdline.maildir, optarg, sizeof(cmdline.maildir) - 1);
  573                 cmdline.args |= CMDLINE_MAILDIR;
  574                 break;
  575 
  576             case 'M':   /* mail new news to specified user */
  577                 my_strncpy(mail_news_user, optarg, sizeof(mail_news_user) - 1);
  578                 mail_news = TRUE;
  579                 batch_mode = TRUE;
  580                 break;
  581 
  582             case 'n':
  583                 newsrc_active = TRUE;
  584                 break;
  585 
  586             case 'N':   /* mail new news to your posts */
  587                 my_strncpy(mail_news_user, userid, sizeof(mail_news_user) - 1);
  588                 mail_news = TRUE;
  589                 batch_mode = TRUE;
  590                 break;
  591 
  592             case 'o':   /* post postponed articles & exit */
  593 #ifndef NO_POSTING
  594                 /*
  595                  * TODO: autoposting currently does some screen output, so we
  596                  *       can't set batch_mode
  597                  */
  598                 post_postponed_and_exit = TRUE;
  599                 check_for_new_newsgroups = FALSE;
  600 #else
  601                 error_message(2, _(txt_option_not_enabled), "-UNO_POSTING");
  602                 free_all_arrays();
  603                 giveup();
  604                 /* keep lint quiet: */
  605                 /* NOTREACHED */
  606 #endif /* !NO_POSTING */
  607                 break;
  608 
  609             case 'p': /* implies -r */
  610 #ifdef NNTP_ABLE
  611                 read_news_via_nntp = TRUE;
  612                 if (atoi(optarg) != 0)
  613                     nntp_tcp_port = (unsigned short) atoi(optarg);
  614 #else
  615                 error_message(2, _(txt_option_not_enabled), "-DNNTP_ABLE");
  616                 free_all_arrays();
  617                 giveup();
  618                 /* keep lint quiet: */
  619                 /* NOTREACHED */
  620 #endif /* NNTP_ABLE */
  621                 break;
  622 
  623             case 'q':
  624                 check_for_new_newsgroups = FALSE;
  625                 break;
  626 
  627             case 'Q':
  628                 newsrc_active = TRUE;
  629                 check_for_new_newsgroups = FALSE;
  630                 show_description = FALSE;
  631                 break;
  632 
  633             case 'r':   /* read news remotely from default NNTP server */
  634 #ifdef NNTP_ABLE
  635                 read_news_via_nntp = TRUE;
  636 #else
  637                 error_message(2, _(txt_option_not_enabled), "-DNNTP_ABLE");
  638                 free_all_arrays();
  639                 giveup();
  640                 /* keep lint quiet: */
  641                 /* NOTREACHED */
  642 #endif /* NNTP_ABLE */
  643                 break;
  644 
  645             case 'R':   /* read news saved by -S option */
  646                 read_saved_news = TRUE;
  647                 list_active = TRUE;
  648                 newsrc_active = FALSE;
  649                 check_for_new_newsgroups = FALSE;
  650                 my_strncpy(news_active_file, save_active_file, sizeof(news_active_file) - 1);
  651                 break;
  652 
  653             case 's':
  654                 my_strncpy(cmdline.savedir, optarg, sizeof(cmdline.savedir) - 1);
  655                 cmdline.args |= CMDLINE_SAVEDIR;
  656                 break;
  657 
  658             case 'S':   /* save new news to dir structure */
  659                 save_news = TRUE;
  660                 batch_mode = TRUE;
  661                 break;
  662 
  663             case 'u':   /* update index files */
  664                 batch_mode = TRUE;
  665                 update_index = TRUE;
  666                 break;
  667 
  668             case 'v':   /* verbose mode */
  669                 verbose = TRUE;
  670                 break;
  671 
  672             case 'V':
  673                 tin_version_info(stderr);
  674                 free_all_arrays();
  675                 exit(EXIT_SUCCESS);
  676                 /* keep lint quiet: */
  677                 /* FALLTHROUGH */
  678 
  679             case 'w':   /* post article & exit */
  680 #ifndef NO_POSTING
  681                 post_article_and_exit = TRUE;
  682                 check_for_new_newsgroups = FALSE;
  683 #else
  684                 error_message(2, _(txt_option_not_enabled), "-UNO_POSTING");
  685                 free_all_arrays();
  686                 giveup();
  687                 /* keep lint quiet: */
  688                 /* NOTREACHED */
  689 #endif /* !NO_POSTING */
  690                 break;
  691 
  692 #if 0
  693             case 'W':   /* reserved according to SUSV3 XDB Utility Syntax Guidelines, Guideline 3 */
  694                 break;
  695 #endif /* 0 */
  696 
  697             case 'x':   /* enter no_posting mode */
  698                 force_no_post = TRUE;
  699                 break;
  700 
  701             case 'X':   /* don't save ~/.newsrc on exit */
  702                 no_write = TRUE;
  703                 break;
  704 
  705             case 'z':
  706                 start_any_unread = TRUE;
  707                 break;
  708 
  709             case 'Z':
  710                 check_any_unread = TRUE;
  711                 batch_mode = TRUE;
  712                 break;
  713 
  714             case 'h':
  715             case '?':
  716             default:
  717                 usage(tin_progname);
  718                 free_all_arrays();
  719                 exit(EXIT_SUCCESS);
  720         }
  721     }
  722     cmdargs = argv;
  723     num_cmdargs = optind;
  724     max_cmdargs = argc;
  725     if (!newsrc_set) {
  726         if (read_news_via_nntp) {
  727             nntp_server = getserverbyfile(NNTP_SERVER_FILE);
  728             get_newsrcname(newsrc, sizeof(newsrc), nntp_server);
  729         } else {
  730 #if defined(HAVE_SYS_UTSNAME_H) && defined(HAVE_UNAME)
  731             struct utsname uts;
  732             (void) uname(&uts);
  733             get_newsrcname(newsrc, sizeof(newsrc), uts.nodename);
  734 #else
  735             char nodenamebuf[256]; /* SUSv2 limit; better use HOST_NAME_MAX */
  736 #ifdef HAVE_GETHOSTNAME
  737             (void) gethostname(nodenamebuf, sizeof(nodenamebuf));
  738 #endif /* HAVE_GETHOSTNAME */
  739             get_newsrcname(newsrc, sizeof(newsrc), nodenamebuf);
  740 #endif /* HAVE_SYS_UTSNAME_H && HAVE_UNAME */
  741         }
  742     }
  743 
  744     /*
  745      * Sort out option conflicts
  746      */
  747     if (!batch_mode) {
  748         if (verbose) {
  749             wait_message(2, _(txt_useful_with_batch_mode), "-v");
  750             verbose = FALSE;
  751         }
  752         if (catchup) {
  753             wait_message(2, _(txt_useful_with_batch_mode), "-c");
  754             catchup = FALSE;
  755         }
  756     } else {
  757         if (read_saved_news) {
  758             wait_message(2, _(txt_useful_without_batch_mode), "-R");
  759             read_saved_news = FALSE;
  760         }
  761     }
  762     if (post_postponed_and_exit && force_no_post) {
  763         wait_message(2, _(txt_useless_combination), "-o", "-x", "-x");
  764         force_no_post = FALSE;
  765     }
  766     if (post_article_and_exit && force_no_post) {
  767         wait_message(2, _(txt_useless_combination), "-w", "-x", "-x");
  768         force_no_post = FALSE;
  769     }
  770     if (catchup && start_any_unread) {
  771         wait_message(2, _(txt_useless_combination), "-c", "-z", "-c");
  772         catchup = FALSE;
  773     }
  774     if (catchup && no_write) {
  775         wait_message(2, _(txt_useless_combination), "-c", "-X", "-c");
  776         catchup = FALSE;
  777     }
  778     if (catchup && check_any_unread) {
  779         wait_message(2, _(txt_useless_combination), "-c", "-Z", "-c");
  780         catchup = FALSE;
  781     }
  782     if (newsrc_active && read_saved_news) {
  783         wait_message(2, _(txt_useless_combination), "-n", "-R", "-n");
  784         newsrc_active = read_news_via_nntp = FALSE;
  785     }
  786     if (start_any_unread && save_news) {
  787         wait_message(2, _(txt_useless_combination), "-z", "-S", "-z");
  788         start_any_unread = FALSE;
  789     }
  790     if (save_news && check_any_unread) {
  791         wait_message(2, _(txt_useless_combination), "-S", "-Z", "-S");
  792         save_news = FALSE;
  793     }
  794     if (start_any_unread && check_any_unread) {
  795         wait_message(2, _(txt_useless_combination), "-Z", "-z", "-Z");
  796         check_any_unread = FALSE;
  797     }
  798 #   ifdef DEBUG
  799     if ((debug & DEBUG_NNTP) && !read_news_via_nntp) {
  800         /* TODO: lang.c */
  801         wait_message(3, _(txt_useless_combination), _("reading from local spool"), "-D nntp", "-D nntp");
  802         debug &= ~DEBUG_NNTP;
  803     }
  804 #   endif /* DEBUG */
  805 
  806 #if defined(NNTP_ABLE) && defined(INET6)
  807     if (force_ipv4 && force_ipv6) {
  808         wait_message(2, _(txt_useless_combination), "-4", "-6", "-6");
  809         force_ipv6 = FALSE;
  810     }
  811 #endif /* NNTP_ABLE && INET6 */
  812 
  813     if (mail_news || save_news || update_index || check_any_unread || catchup)
  814         batch_mode = TRUE;
  815     else
  816         batch_mode = FALSE;
  817     if (batch_mode && (post_article_and_exit || post_postponed_and_exit))
  818         batch_mode = FALSE;
  819 
  820     /*
  821      * When updating index files set getart_limit to 0 in order to get overview
  822      * information for all article; this overwrites '-G limit' and disables
  823      * tinrc.getart_limit temporary
  824      */
  825     if (update_index) {
  826         cmdline.getart_limit = 0;
  827         cmdline.args |= CMDLINE_GETART_LIMIT;
  828     }
  829 #ifdef NNTP_ABLE
  830     /*
  831      * If we're reading from an NNTP server and we've been asked not to look
  832      * for new newsgroups, trust our cached copy of the newsgroups file.
  833      */
  834     if (read_news_via_nntp)
  835         read_local_newsgroups_file = bool_not(check_for_new_newsgroups);
  836 #endif /* NNTP_ABLE */
  837     /*
  838      * If we use neither list_active nor newsrc_active,
  839      * we use both of them.
  840      */
  841     if (!list_active && !newsrc_active)
  842         list_active = newsrc_active = TRUE;
  843 }
  844 
  845 
  846 /*
  847  * usage
  848  */
  849 static void
  850 usage(
  851     char *theProgname)
  852 {
  853     error_message(2, _(txt_usage_tin), theProgname);
  854 
  855 #if defined(NNTP_ABLE) && defined(INET6)
  856         error_message(2, _(txt_usage_force_ipv4));
  857         error_message(2, _(txt_usage_force_ipv6));
  858 #endif /* NNTP_ABLE && INET6 */
  859 
  860 #ifdef HAVE_COLOR
  861         error_message(2, _(txt_usage_toggle_color));
  862 #endif /* HAVE_COLOR */
  863 #ifdef NNTP_ABLE
  864         error_message(2, _(txt_usage_force_authentication));
  865 #endif /* NNTP_ABLE */
  866 
  867     error_message(2, _(txt_usage_catchup));
  868     error_message(2, _(txt_usage_dont_show_descriptions));
  869 
  870 #ifdef DEBUG
  871     error_message(2, _(txt_usage_debug));
  872 #endif /* DEBUG */
  873 
  874     error_message(2, _(txt_usage_newsrc_file), newsrc);
  875     error_message(2, _(txt_usage_getart_limit));
  876 
  877 #ifdef NNTP_ABLE
  878 #   ifdef NNTP_DEFAULT_SERVER
  879     error_message(2, _(txt_usage_newsserver), get_val("NNTPSERVER", NNTP_DEFAULT_SERVER));
  880 #   else
  881     error_message(2, _(txt_usage_newsserver), get_val("NNTPSERVER", "news"));
  882 #   endif /* NNTP_DEFAULT_SERVER */
  883 #endif /* NNTP_ABLE */
  884 
  885     error_message(2, _(txt_usage_help_message));
  886     error_message(2, _(txt_usage_help_information), theProgname);
  887     error_message(2, _(txt_usage_index_newsdir), index_newsdir);
  888     error_message(2, _(txt_usage_read_only_active));
  889     error_message(2, _(txt_usage_maildir), tinrc.maildir);
  890     error_message(2, _(txt_usage_mail_new_news_to_user));
  891     error_message(2, _(txt_usage_read_only_subscribed));
  892     error_message(2, _(txt_usage_mail_new_news));
  893     error_message(2, _(txt_usage_post_postponed_arts));
  894 
  895 #ifdef NNTP_ABLE
  896     error_message(2, _(txt_usage_port), nntp_tcp_port);
  897 #endif /* NNTP_ABLE */
  898 
  899     error_message(2, _(txt_usage_dont_check_new_newsgroups));
  900     error_message(2, _(txt_usage_quickstart));
  901 
  902 #ifdef NNTP_ABLE
  903     if (!read_news_via_nntp)
  904         error_message(2, _(txt_usage_read_news_remotely));
  905 #endif /* NNTP_ABLE */
  906 
  907     error_message(2, _(txt_usage_read_saved_news));
  908     error_message(2, _(txt_usage_savedir), tinrc.savedir);
  909     error_message(2, _(txt_usage_save_new_news));
  910     error_message(2, _(txt_usage_update_index_files));
  911     error_message(2, _(txt_usage_verbose));
  912     error_message(2, _(txt_usage_version));
  913     error_message(2, _(txt_usage_post_article));
  914     error_message(2, _(txt_usage_no_posting));
  915     error_message(2, _(txt_usage_dont_save_files_on_quit));
  916     error_message(2, _(txt_usage_start_if_unread_news));
  917     error_message(2, _(txt_usage_check_for_unread_news));
  918 
  919     error_message(2, _(txt_usage_mail_bugreport), bug_addr);
  920 }
  921 
  922 
  923 /*
  924  * update index files
  925  */
  926 static void
  927 update_index_files(
  928     void)
  929 {
  930     cCOLS = 132;                            /* set because curses has not started */
  931     create_index_lock_file(lock_file);
  932     tinrc.thread_articles = THREAD_NONE;    /* stop threading to run faster */
  933     do_update(catchup);
  934     tin_done(EXIT_SUCCESS, NULL);
  935 }
  936 
  937 
  938 /*
  939  * display page of general info. for first time user.
  940  */
  941 static void
  942 show_intro_page(
  943     void)
  944 {
  945     char buf[4096];
  946 
  947     if (!cmd_line) {
  948         ClearScreen();
  949         center_line(0, TRUE, cvers);
  950         Raw(FALSE);
  951         my_printf("\n");
  952     }
  953 
  954     snprintf(buf, sizeof(buf), _(txt_intro_page), PRODUCT, PRODUCT, PRODUCT, bug_addr);
  955 
  956     my_fputs(buf, stdout);
  957     my_flush();
  958 
  959     if (!cmd_line) {
  960         Raw(TRUE);
  961         prompt_continue();
  962     }
  963 }
  964 
  965 
  966 /*
  967  * Wildcard match any newsgroups on the command line. Sort of like a limited
  968  * yank at startup. Return number of groups that were matched.
  969  */
  970 int
  971 read_cmd_line_groups(
  972     void)
  973 {
  974     int matched = 0;
  975     int num;
  976     int i;
  977 
  978     if (num_cmdargs < max_cmdargs) {
  979         selmenu.max = skip_newgroups();     /* Reposition after any newgroups */
  980 
  981         for (num = num_cmdargs; num < max_cmdargs; num++) {
  982             if (!batch_mode)
  983                 wait_message(0, _(txt_matching_cmd_line_groups), cmdargs[num]);
  984 
  985             for_each_group(i) {
  986                 if (match_group_list(active[i].name, cmdargs[num])) {
  987                     if (my_group_add(active[i].name, TRUE) != -1) {
  988                         matched++;
  989                         if (post_article_and_exit) {
  990                             my_strncpy(tinrc.default_post_newsgroups, active[i].name, sizeof(tinrc.default_post_newsgroups) - 1);
  991                             break;
  992                         }
  993                     }
  994                 }
  995             }
  996         }
  997     }
  998     return matched;
  999 }
 1000 
 1001 
 1002 /*
 1003  * Create default mail & save directories if they do not exist
 1004  */
 1005 static void
 1006 create_mail_save_dirs(
 1007     void)
 1008 {
 1009     char path[PATH_LEN];
 1010     struct stat sb;
 1011 
 1012     if (!strfpath(tinrc.maildir, path, sizeof(path), NULL, FALSE))
 1013         joinpath(path, sizeof(path), homedir, DEFAULT_MAILDIR);
 1014 
 1015     if (stat(path, &sb) == -1)
 1016         my_mkdir(path, (mode_t) (S_IRWXU));
 1017 
 1018     if (!strfpath(tinrc.savedir, path, sizeof(path), NULL, FALSE))
 1019         joinpath(path, sizeof(path), homedir, DEFAULT_SAVEDIR);
 1020 
 1021     if (stat(path, &sb) == -1)
 1022         my_mkdir(path, (mode_t) (S_IRWXU));
 1023 }
 1024 
 1025 
 1026 /*
 1027  * we don't try do free() any previously malloc()ed mem here as exit via
 1028  * giveup() indicates a serious error and keeping track of what we've
 1029  * already malloc()ed would be a PITA.
 1030  */
 1031 /* coverity[+kill] */
 1032 void
 1033 giveup(
 1034     void)
 1035 {
 1036     static int nested;
 1037 
 1038 #ifdef XFACE_ABLE
 1039     slrnface_stop();
 1040 #endif /* XFACE_ABLE */
 1041 
 1042     if (!cmd_line && !nested++) {
 1043         cursoron();
 1044         EndWin();
 1045         Raw(FALSE);
 1046     }
 1047     exit(EXIT_FAILURE);
 1048 }