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