home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume30 / tin / part12 / main.c < prev    next >
C/C++ Source or Header  |  1992-05-20  |  12KB  |  500 lines

  1. /*
  2.  *  Project   : tin - a threaded Netnews reader
  3.  *  Module    : main.c
  4.  *  Author    : I.Lea & R.Skrenta
  5.  *  Created   : 01-04-91
  6.  *  Updated   : 15-05-92
  7.  *  Notes     :
  8.  *  Copyright : (c) Copyright 1991-92 by Iain Lea & Rich Skrenta
  9.  *              You may  freely  copy or  redistribute  this software,
  10.  *              so  long as there is no profit made from its use, sale
  11.  *              trade or  reproduction.  You may not change this copy-
  12.  *              right notice, and it must be included in any copy made
  13.  */
  14.  
  15. #include    "tin.h"
  16.  
  17. /*
  18.  * OK lets start the ball rolling...
  19.  */
  20.  
  21. void main (argc, argv)
  22.     int argc;    
  23.     char *argv[];
  24. {
  25.     int created, i;
  26.     int start_groupnum = 0;
  27.  
  28.     cmd_line = TRUE;
  29.     debug = 0;    /* debug OFF */
  30.  
  31.     set_signal_handlers ();
  32.  
  33.     basename (argv[0], progname);
  34.  
  35.     sprintf (page_header, "%s %s PL%d", progname, VERSION, PATCHLEVEL);     
  36.     sprintf (cvers, "%s (c) Copyright 1991-92 Iain Lea.", page_header);
  37.  
  38. #if defined(NNTP_ONLY) || defined(CDROM_ONLY)
  39.     read_news_via_nntp = TRUE;
  40. #else
  41.     /* 
  42.      * rtin/cdtin so read news remotely via NNTP 
  43.      */
  44.     if (progname[0] == 'r' || (progname[0] == 'c' && progname[1] == 'd' )) {
  45. #        ifdef NNTP_ABLE            
  46.             read_news_via_nntp = TRUE;
  47. #        else
  48.             error_message (txt_option_not_enabled, "-DNNTP_ABLE");
  49.             exit (1);
  50. #        endif
  51.     }
  52. #endif
  53.  
  54.     /*
  55.      * set up char *'s: homedir, newsrc, etc. 
  56.      */
  57.     init_selfinfo ();
  58.  
  59.     /*
  60.      * process command line options
  61.      */
  62.     read_cmd_line_options (argc, argv);
  63.     if (update_fork || (update && verbose) || !update) {
  64.         error_message (cvers, "");
  65.     }
  66.  
  67.     /*
  68.      *  if specified connect to (cdrom pseudo) nntp server
  69.      */
  70.     nntp_open ();
  71.  
  72.     /*
  73.      *  allocate initial array sizes
  74.      */
  75.     init_alloc ();
  76.     hash_init ();
  77.  
  78.     /*
  79.      *  load the active file into active[]
  80.      */
  81.     created = read_active_file ();
  82.  
  83.     /*
  84.      *  log username info to local/central logfile (NNTP XUSER)
  85.      */
  86.     log_user ();
  87.  
  88.     if (create_mail_save_dirs ()) {
  89.         write_rcfile ();
  90.     }    
  91.  
  92.     if (optind < argc) {
  93.         while (optind < argc) {
  94.             for (i = 0 ; i < num_active ; i++) {
  95.                 if (wildmat(active[i].name, argv[optind])) {        
  96.                     if (add_group (active[i].name, TRUE) < 0) {
  97.                         error_message (txt_not_in_active_file, active[i].name);
  98.                     }
  99.                 }    
  100.             }    
  101.             optind++;
  102.         }
  103.     } else {
  104.         backup_newsrc ();
  105.         read_newsrc (TRUE);
  106.         mark_unthreaded_groups ();
  107.     }
  108.  
  109.     /*
  110.      *  read in users kill/auto-select (hot) file
  111.      */
  112.     killed_articles = read_kill_file ();
  113.     
  114.     /*
  115.      *  check/start if any new/unread articles
  116.      */
  117.     start_groupnum = check_for_any_new_news (check_any_unread, start_any_unread);
  118.  
  119.     /*
  120.      *  mail any new articles to specified user
  121.      *  or
  122.      *  save any new articles to savedir structure for later reading
  123.      */
  124.     save_or_mail_new_news ();
  125.     
  126.     /*
  127.      *  update index files
  128.      */
  129.     update_index_files ();
  130.     
  131.     if (! InitScreen ()) {
  132.         error_message (txt_screen_init_failed, progname);
  133.         exit (1);
  134.     }
  135.  
  136.     /*
  137.      *   get screen size from termcap entry 
  138.      */
  139.     ScreenSize (&LINES, &COLS);
  140.     cmd_line = FALSE;
  141.     Raw (TRUE);
  142.  
  143.     /* 
  144.      *  check & set actual screen size
  145.      */
  146.     set_win_size (&LINES, &COLS);
  147.  
  148.     /*
  149.      *  check for any newly created newsgroups
  150.      */
  151.     if (notify_new_groups && ! created) {
  152.         notify_groups ();
  153.     }
  154.  
  155.     /*
  156.      *  if first time print welcome screen
  157.       and auto-subscribe
  158.      *  to groups specified in /usr/lib/news/subscribe locally
  159.      *  or via NNTP if reading news remotely (LIST SUBSCRIBE)
  160.      */
  161.     if (created_rcdir && update == FALSE) {
  162.         show_intro_page ();
  163.     }
  164.     
  165.     selection_index (start_groupnum);
  166.  
  167.     tin_done (0);
  168. }
  169.  
  170. /*
  171.  * process command line options
  172.  */
  173.  
  174. void read_cmd_line_options (argc, argv)
  175.     int argc;
  176.     char *argv[];
  177. {
  178.     int ch;
  179.  
  180. #ifdef INDEX_DAEMON
  181.     while ((ch = getopt (argc, argv, "D:f:hI:vV")) != EOF) {
  182. #else
  183.     while ((ch = getopt (argc, argv, "cD:f:hHI:m:M:np:rRs:SuUvVzZ")) != EOF) {
  184. #endif
  185.         switch (ch) {
  186.             case 'c':
  187.                 catchup = TRUE;
  188.                 update = TRUE;
  189.                 break;
  190.                 
  191.             case 'D':        /* debug mode 1=NNTP 2=ALL */
  192. #ifdef DEBUG            
  193.                 redirect_output[0] = '\0';
  194.                 debug = atoi (optarg);
  195. #else
  196.                 error_message (txt_option_not_enabled, "-DDEBUG");
  197.                 exit (1);
  198. #endif
  199.                 break;
  200.  
  201.             case 'f':
  202.                 my_strncpy (newsrc, optarg, sizeof (newsrc));
  203.                 break;
  204.  
  205.             case 'H':
  206.                 show_intro_page ();
  207.                 exit (1);
  208.                 break;
  209.  
  210. #if !defined(NNTP_ONLY) || !defined(NNTP_XINDEX)
  211.             case 'I':
  212.                 my_strncpy (indexdir, optarg, sizeof (indexdir));
  213.                 mkdir (indexdir, 0777);
  214.                 break;
  215. #endif
  216.             case 'm':
  217.                 my_strncpy (default_maildir, optarg, sizeof (default_maildir));
  218.                 break;
  219.  
  220.             case 'M':    /* mail new news to specified user */
  221.                 my_strncpy (mail_news_user, optarg, sizeof (mail_news_user));
  222.                 mail_news = TRUE;
  223.                 update = TRUE;
  224.                 catchup = TRUE;
  225.                 break;
  226.  
  227.             case 'n':
  228.                 notify_new_groups = TRUE;
  229.                 break;
  230.  
  231.             case 'p':
  232.                 my_strncpy (cmd_line_printer, optarg, sizeof (cmd_line_printer));
  233.                 default_printer = FALSE;
  234.                 break;
  235.  
  236.             case 'r':    /* read news remotely from default NNTP server */
  237. #ifdef NNTP_ABLE            
  238.                 read_news_via_nntp = TRUE;
  239. #else
  240.                 error_message (txt_option_not_enabled, "-DNNTP_ABLE");
  241.                 exit (1);
  242. #endif
  243.                 break;
  244.  
  245.             case 'R':    /* read news saved by -S option */
  246.                 error_message ("%s: Option -R not yet implemented.", progname);
  247.                 exit (1);
  248.                 break;
  249.  
  250.             case 's':
  251.                 my_strncpy (default_savedir, optarg, sizeof (default_savedir));
  252.                 break;
  253.  
  254.             case 'S':    /* save new news to dir structure */
  255.                 save_news = TRUE;
  256.                 update = TRUE;
  257.                 break;
  258.  
  259.             case 'u':    /* update index files */
  260.                 update = TRUE;
  261.                 break;
  262.  
  263.             case 'U':    /* update index files in background */
  264.                 update_fork = TRUE;
  265.                 update = TRUE;
  266.                 break;
  267.  
  268.             case 'v':    /* verbose mode */
  269.                 verbose = TRUE;
  270.                 break;
  271.  
  272.             case 'V':
  273. #if defined(__DATE__) && defined(__TIME__)            
  274.                 sprintf (msg, "Version: %s PL%d  %s %s",
  275.                     VERSION, PATCHLEVEL, __DATE__, __TIME__);
  276. #else
  277.                 sprintf (msg, "Version: %s PL%d",
  278.                     VERSION, PATCHLEVEL);
  279. #endif                    
  280.                 error_message (msg, "");
  281.                 exit (1);
  282.                 break;
  283.  
  284.             case 'z':
  285.                 start_any_unread = TRUE;
  286.                 update = TRUE;
  287.                 break;
  288.  
  289.             case 'Z':
  290.                 check_any_unread = TRUE;
  291.                 update = TRUE;
  292.                 break;
  293.  
  294.             case 'h':
  295.             case '?':
  296.             default:
  297.                 usage (progname);
  298.                 exit (1);
  299.         }
  300.     }
  301. }
  302.  
  303. /*
  304.  * usage
  305.  */
  306.  
  307. void usage (progname)
  308.     char *progname;
  309. {
  310. #ifndef INDEX_DAEMON
  311.     error_message ("%s A threaded Netnews reader.\n", cvers);
  312. #else
  313.     error_message ("%s Tin index file daemon.\n", cvers);
  314. #endif
  315.     error_message ("Usage: %s [options] [newsgroups]", progname);
  316. #ifndef INDEX_DAEMON
  317.     error_message ("  -c       mark all news as read in subscribed newsgroups (batch mode)", "");
  318. #endif
  319.     error_message ("  -f file  subscribed to newsgroups file [default=%s]", newsrc);
  320.     error_message ("  -h       help", "");
  321. #ifndef INDEX_DAEMON
  322.     error_message ("  -H       help information about %s", progname);
  323. #endif
  324.     error_message ("  -I dir   index file directory [default=%s]", indexdir);
  325. #ifndef INDEX_DAEMON
  326.     error_message ("  -m dir   mailbox directory [default=%s]", default_maildir);
  327.     error_message ("  -M user  mail new news to specified user (batch mode)", "");
  328.     error_message ("  -n       notify user of any newly created newsgroups", "");
  329.     error_message ("  -p file  print program with options [default=%s]", DEFAULT_PRINTER);
  330. #  if defined(NNTP_ABLE) && !defined(NNTP_ONLY)
  331.     if (! read_news_via_nntp) {
  332.         error_message ("  -r       read news remotely from default NNTP server", "");
  333.     }
  334. #  endif /* NNTP_ABLE */    
  335.     error_message ("  -R       read news saved by -S option (not yet implemented)", "");
  336.     error_message ("  -s dir   save news directory [default=%s]", default_savedir);
  337.     error_message ("  -S       save new news for later reading (batch mode)", "");
  338. #  if !defined(NNTP_ONLY) || !defined(NNTP_XINDEX)
  339.     error_message ("  -u       update index files (batch mode)", "");
  340.     error_message ("  -U       update index files in the background while reading news", "");
  341. #  endif /* NNTP_XINDEX */
  342. #endif /* INDEX_DAEMON */
  343.     error_message ("  -v       verbose output for batch mode options", "");
  344. #ifndef INDEX_DAEMON
  345.     error_message ("  -z       start if any unread news", "");
  346.     error_message ("  -Z       return status indicating if any unread news (batch mode)", "");
  347. #endif
  348.     error_message ("\nMail bug reports/comments to %s", BUG_REPORT_ADDRESS);
  349. }
  350.  
  351. /*
  352.  *  check/start if any new/unread articles
  353.  */
  354.  
  355. int check_for_any_new_news (check_any_unread, start_any_unread)
  356.     int check_any_unread;
  357.     int start_any_unread;
  358. {
  359.     int i = 0;
  360.     
  361.     if (check_any_unread) {
  362.         i = check_start_save_any_news (CHECK_ANY_NEWS);
  363.         exit (i);
  364.     }
  365.     
  366.     if (start_any_unread) {
  367.         i = check_start_save_any_news (START_ANY_NEWS);
  368.         if (i == -1) {        /* no new/unread news so exit */
  369.             exit (0);
  370.         }
  371.         update = FALSE;
  372.     }
  373.     return (i);
  374. }
  375.  
  376. /*
  377.  *  mail any new articles to specified user
  378.  *  or
  379.  *  save any new articles to savedir structure for later reading
  380.  */
  381.  
  382. void save_or_mail_new_news ()
  383. {
  384.     int i;
  385.     
  386.     if (mail_news || save_news) {
  387.         i = catchup;            /* set catchup to FALSE */
  388.         catchup = FALSE;
  389.         do_update ();
  390.         catchup = i;            /* set catchup to previous value */
  391.         if (mail_news) {
  392.             check_start_save_any_news (MAIL_ANY_NEWS);
  393.         } else {
  394.             check_start_save_any_news (SAVE_ANY_NEWS);
  395.         }
  396.         tin_done (0);
  397.     }
  398. }
  399.  
  400. /*
  401.  *  update index files
  402.  */
  403.  
  404. void update_index_files ()
  405. {
  406.     if (update || update_fork) {
  407.         if (read_news_via_nntp && xindex_supported) {
  408.             error_message ("%s: Updating of index files not supported", progname);
  409.             tin_done (1);
  410.         }
  411.  
  412.         COLS = 132;                    /* set because curses has not started */ 
  413.         if (update_fork) {
  414.             catchup = FALSE;        /* turn off msgs when running forked */ 
  415.             verbose = FALSE;
  416.             switch (fork ()) {        /* fork child to update indexes in background */
  417.                 case -1:    /* error forking */    
  418.                     perror_message ("Failed to start background indexing process", "");
  419.                     break;
  420.                 case 0:        /* child process */    
  421.                     process_id = getpid ();
  422. #ifdef BSD
  423.                     setpgrp (0, process_id);    /* reset process group leader to this process */
  424. #    ifdef TIOCNOTTY
  425.                     {
  426.                         int fd;
  427.     
  428.                         if ((fd = open ("/dev/tty", O_RDWR)) >= 0) {
  429.                             ioctl (fd, TIOCNOTTY, (char *) NULL);
  430.                             close (fd);
  431.                         }    
  432.                     }    
  433. #    endif
  434. #else
  435.                     setpgrp ();
  436.                     signal (SIGHUP, SIG_IGN);    /* make immune from process group leader death */
  437. #endif
  438.                     signal (SIGQUIT, SIG_IGN);    /* stop indexing being interrupted */            
  439.                     signal (SIGALRM, SIG_IGN);    /* stop indexing resyning active file */            
  440.                     nntp_open ();            /* connect server if we are using nntp */
  441.                     thread_arts = FALSE;    /* stop threading to run faster */
  442.                     do_update ();
  443.                     nntp_close ();            /* connect server if we are using nntp */
  444.                     exit (0);
  445.                     break;
  446.                 default:    /* parent process*/
  447.                     break;                    
  448.             }    
  449.             update = FALSE;
  450.         } else {
  451.             thread_arts = FALSE;    /* stop threading to run faster */
  452.             do_update ();
  453.             exit (0);
  454.         }
  455.     }
  456. }
  457.  
  458. /*
  459.  *  display page of general info. for first time user.
  460.  */
  461.  
  462. void show_intro_page ()
  463. {
  464.     if (cmd_line) {
  465.         wait_message (cvers);     
  466.     } else {
  467.         ClearScreen ();
  468.         center_line (0, TRUE, cvers); 
  469.         Raw (FALSE);    
  470.     }
  471.  
  472.     printf ("\n\nWelcome to tin, a full screen threaded Netnews reader. It can read news locally\n");
  473.     printf ("(ie. <spool>/news) or remotely (-r option) from a NNTP  (Network News Transport\n");
  474.     printf ("Protocol) server. tin -h lists the available command line options.\n\n");
  475.  
  476.     printf ("Tin has four newsreading levels, the newsgroup selection page,  the group index\n");
  477.     printf ("page, the thread listing page and the article viewer. Help is available at each\n");
  478.     printf ("level by pressing the 'h' command.\n\n");
  479.  
  480.     printf ("Move up/down by using the terminal arrow keys or 'j' and 'k'.  Use PgUp/PgDn or\n");
  481.     printf ("Ctrl-U and Ctrl-D to page up/down. Enter a newsgroup by pressing RETURN.\n\n");
  482.  
  483.     printf ("Articles, threads, tagged articles or articles matching a pattern can be mailed\n");
  484.     printf ("('m' command), printed ('o' command), saved ('s' command), piped ('|' command).\n");
  485.     printf ("Use the 'w' command  to post  a news  article,  the 'f'/'F' commands to  post a\n");
  486.     printf ("follow-up  to  an existing  news article and the 'r'/'R' commands to  reply via\n");
  487.     printf ("mail to an existing news articles author.  The 'M' command allows the operation\n");
  488.     printf ("of tin to be configured via a menu.\n\n");
  489.  
  490.     printf ("For more information read the manual page, README, INSTALL, TODO and FTP files.\n\n");
  491.     printf ("Please send bug reports/comments to the programs author with the 'B' command.\n");
  492.     fflush (stdout);
  493.  
  494.     if (! cmd_line) {
  495.         Raw (TRUE);    
  496.         continue_prompt ();
  497.     }
  498. }
  499.  
  500.