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