home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume31 / tin / part13 < prev    next >
Encoding:
Text File  |  1992-07-07  |  53.6 KB  |  2,366 lines

  1. Newsgroups: comp.sources.misc
  2. From: iain%anl433.uucp@Germany.EU.net (Iain Lea)
  3. Subject:  v31i013:  tin - threaded full screen newsreader v1.1 PL4, Part13/15
  4. Message-ID: <1992Jul7.182024.7954@sparky.imd.sterling.com>
  5. X-Md4-Signature: 9ee573141d8ba83b5ab5bde6719d71d2
  6. Date: Tue, 7 Jul 1992 18:20:24 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: iain%anl433.uucp@Germany.EU.net (Iain Lea)
  10. Posting-number: Volume 31, Issue 13
  11. Archive-name: tin/part13
  12. Environment: BSD, SCO, ISC, SUNOS, SYSVR3, SYSVR4, ULTRIX, XENIX
  13. Supersedes: tin: Volume 30, Issue 1-14
  14.  
  15. #! /bin/sh
  16. # This is a shell archive.  Remove anything before this line, then feed it
  17. # into a shell via "sh file" or similar.  To overwrite existing files,
  18. # type "sh file -c".
  19. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  20. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  21. # Contents:  TODO active.c getline.c main.c signal.c
  22. # Wrapped by kent@sparky on Mon Jun 29 23:35:15 1992
  23. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  24. echo If this archive is complete, you will see the following message:
  25. echo '          "shar: End of archive 13 (of 15)."'
  26. if test -f 'TODO' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'TODO'\"
  28. else
  29.   echo shar: Extracting \"'TODO'\" \(5083 characters\)
  30.   sed "s/^X//" >'TODO' <<'END_OF_FILE'
  31. X!!! PLEASE NOTE THAT ON CERTAIN MACHINES (ie. mostly RISC DEC,HP) TIN
  32. X!!! WILL SOMETIMES CRASH WITH SIGBUS or SIGSEGV DUE TO THE HACK THAT
  33. X!!! IS USED IN HASHING STRINGS IN hashstr.c. SORRY BUT I HAVE NO TIME
  34. X!!! RIGHT NOW TO REIMPLEMENT THIS PART OF TIN WHICH IS A CARRY OVER
  35. X!!! FROM TASS v3.2 (Any takers ?)
  36. X
  37. XFIX FEATURES V1.x
  38. X-----------------
  39. X
  40. Xo  If 'a' in pipe to less and 423 error msg from NNTP it starts less with 
  41. X   no file.
  42. X
  43. Xo  Add Msg-Id: field contents to reply & followups.
  44. X
  45. Xo  Add code to decrement/increment counter of NEW killed & hot articles 
  46. X   so that 'h' is not offered as default when there are no NEW hot articles.
  47. X   Look at 'r' 'z' 'k' & code that marks arts read.
  48. X
  49. Xo  Add Followup-To: field header to 'fF' followup articles with groups
  50. X   copied from Newsgroups: field.
  51. X
  52. Xo  Fix spooldirs[] so it auto-expands as needed.
  53. X
  54. Xo  In inews.c also allow reply_to var to be used in From: field.
  55. X
  56. Xo  Fix -S option to create an active file when new articles are
  57. X   saved to <savedir>. Also fix -R option to read ACTIVE file created
  58. X   by -S command. Use minimax code from tony travis to help in -R cmd
  59. X   line option.
  60. X
  61. Xo  Fix Save in feed.c routines. 
  62. X   Also fix so SAVING routines just use save_art_to_file() and print
  63. X   *** X Articles saved *** & none of the BS done at the moment
  64. X
  65. Xo  Add option to 'M' menu to allow 'C' command to return/stay at
  66. X   group level.
  67. X
  68. Xo  Fix 'c' at article level when within thread level?
  69. X
  70. Xo  Fix -n option to hash the groups read in from ~/.tin/active and
  71. X   mark active[].flag as TRUE. then find flag=FALSE and ask user if
  72. X   they want to subscribe to group. On xenix386 takes 15 seconds on
  73. X   current -n option. Also of CNEWS just do a compare of active.times
  74. X   UNDER CNEWS USE active.times FILE FROM NNTPSERVER
  75. X   UNDER NNTP USE newnews COMMAND FROM NNTPSERVER
  76. X
  77. Xo  Add 'r' command to newsgroup level.
  78. X
  79. XFIX FEATURES V2.0
  80. X-----------------
  81. X
  82. Xo  If saving in mailbox format and mailbox does not exist query the user?
  83. X
  84. Xo  In kill.c should kill_both only kill when subj & from are matched?
  85. X
  86. Xo  Add file ~/.tin/tinheaders for following headers to be stored:
  87. X     Reply-To:
  88. X     Organisation:
  89. X     Distribution:
  90. Xo  Make binary as both standalone & NNTP as default
  91. X
  92. Xo  Add Ctrl-/ Ctrl-? to search the whole of an article (Subj,From & Body)
  93. X   at Group & Page level
  94. X
  95. Xo  Add elm like mini-menu to tin for first time users.
  96. X
  97. Xo  Add option to 'M' menu to allow unlinking/not of ~/.article
  98. X   after posting an article.
  99. X
  100. Xo  Add hashing to speedup valid_art() in big groups. Make it compile
  101. X   option so tin is still usable on Minix/small memory machines.
  102. X   -DSMALL_MEMORY_MACHINE
  103. X
  104. Xo  Add auto-aliasing of peoples mail addresses to mail aliases file.
  105. X
  106. Xo  Add Xref handling of articles so that read ones are marked read in 
  107. X   other groups. Use update_group() to do it?
  108. X   Needs to handle 'c' 'C' 'k' 'K' commands. Perhaps it should be an
  109. X   option so that performance is not impaired. (JIM).
  110. X
  111. Xo  Add ^G command to skip to next Subject: in digests.
  112. X
  113. Xo  Try compiling with -D_POSIX_SOURCE
  114. X
  115. Xo  Add filename & groupname completion (readline?).
  116. X
  117. Xo  Fix uuscram code in uudecode.
  118. X
  119. Xo  Fix code to sort arts. At page level funny things happen.
  120. X
  121. XADD FEATURES
  122. X------------
  123. X
  124. Xo  Add -P <pattern> or -P <file> to search for in new news and to
  125. X   notify user by mail. Should understand 'subject=text' 'from=text'
  126. X   'body=text' and .AND. && .OR. || for filtering purposes.
  127. X
  128. Xo  Add elm style print command with %s in it for printing in 'M'.
  129. X
  130. Xo  Add 'C' command at group level to catchup present group and
  131. X   enter next group with unread news in it.
  132. X
  133. Xo  Sort .newsrc according to preference. (sort active file as it is read)
  134. X
  135. Xo  Add time period to killing articles
  136. X
  137. XOTHER STUFF
  138. X-----------
  139. Xo  Add rebindable keymaps and provide different terminal keymaps
  140. X   (ie. keymap.ansi, keymap.wy50 etc.)
  141. X
  142. Xo  Add Virtual newsgroups (combination of newsgroups ie. virtual.ibm
  143. X   consists of comp.sys.ibm.* groups).
  144. X
  145. Xo  Add threading on References like trn with mthreads database.
  146. X
  147. Xo  Add full curses support instead of using printf()'s or joetty.
  148. X
  149. Xo  Sub all not empty groups by looking at min max values in active array
  150. X   and Unsub all empty groups by looking at min max values in active 
  151. X   array. have a command to do this in a toggle effect.
  152. X
  153. Xo  Run tests of my_strncpy() and system strncpy()
  154. X
  155. Xo  Add Virtual newsgroups (combination of newsgroups ie. virtual.ibm
  156. X   consists of comp.sys.ibm.* groups). ~/.tin/virtual
  157. X
  158. Xo  Change defaults on a per group basis
  159. XGroup        Connect   Read    Thread    Save  Savedir  Maildir  Sigfile    
  160. X                       Unread  Unthread  Mail  ProcTyp  Mailbox
  161. X-----------------------------------------------------------------------------
  162. Xjunk         local     Unread  Thread    None  Default  Default  Default
  163. Xalt.sources  1.3.3.3   Read    Thread    Save  $SRC/alt Default  ~/.Sig-alt
  164. X
  165. XAdd a menu interface to define all this. Also add edit menu for entries in
  166. Xkill file.
  167. X
  168. XEach group could have a field to say which NNTP/local connection to use so
  169. Xas to be able to plug into different NNTP servers for different newsgroups
  170. END_OF_FILE
  171.   if test 5083 -ne `wc -c <'TODO'`; then
  172.     echo shar: \"'TODO'\" unpacked with wrong size!
  173.   fi
  174.   # end of 'TODO'
  175. fi
  176. if test -f 'active.c' -a "${1}" != "-c" ; then 
  177.   echo shar: Will not clobber existing file \"'active.c'\"
  178. else
  179.   echo shar: Extracting \"'active.c'\" \(10048 characters\)
  180.   sed "s/^X//" >'active.c' <<'END_OF_FILE'
  181. X/*
  182. X *  Project   : tin - a threaded Netnews reader
  183. X *  Module    : active.c
  184. X *  Author    : I.Lea
  185. X *  Created   : 16-02-92
  186. X *  Updated   : 08-06-92
  187. X *  Notes     :
  188. X *  Copyright : (c) Copyright 1991-92 by Iain Lea
  189. X *              You may  freely  copy or  redistribute  this software,
  190. X *              so  long as there is no profit made from its use, sale
  191. X *              trade or  reproduction.  You may not change this copy-
  192. X *              right notice, and it must be included in any copy made
  193. X */
  194. X
  195. X#include    "tin.h"
  196. X
  197. Xint group_hash[TABLE_SIZE];            /* group name --> active[] */
  198. Xint reread_active_file = FALSE;
  199. X
  200. X
  201. X/*
  202. X *  Resync active file when SIGALRM signal received that
  203. X *  is triggered by alarm (RESYNC_ACTIVE_SECS) call.
  204. X */
  205. X
  206. Xvoid resync_active_file ()
  207. X{
  208. X    if (reread_active_file) {
  209. X        free_active_arrays ();
  210. X        max_active = DEFAULT_ACTIVE_NUM;
  211. X        expand_active ();
  212. X        read_active_file ();
  213. X        read_newsgroups_file ();
  214. X        read_newsrc (TRUE);
  215. X        set_alarm_signal ();
  216. X        mail_setup ();
  217. X        group_selection_page ();
  218. X    }
  219. X}
  220. X
  221. X/*
  222. X *  Load the active file into active[] and create copy of active ~/.tin/active
  223. X */
  224. X
  225. Xint read_active_file ()
  226. X{
  227. X    FILE *fp;
  228. X    char *p, *q, *r;
  229. X    char buf[LEN];
  230. X    char moderated = 'y';
  231. X    int created, i;
  232. X    long h;
  233. X    
  234. X    num_active = 0;
  235. X
  236. X    if (! update) {
  237. X        wait_message (txt_reading_active_file);
  238. X    }
  239. X
  240. X    if ((fp = open_active_fp ()) == NULL) {
  241. X        if (compiled_with_nntp) {
  242. X            sprintf (msg, txt_cannot_open_active_file, active_file, progname);
  243. X            wait_message (msg);
  244. X        } else {
  245. X            fputc ('\n', stderr);
  246. X            fprintf (stderr, txt_cannot_open, active_file);
  247. X            fputc ('\n', stderr);
  248. X            fflush (stderr);
  249. X        }
  250. X        exit (1);
  251. X    }
  252. X
  253. X    for (i = 0; i < TABLE_SIZE; i++) {
  254. X        group_hash[i] = -1;
  255. X    }
  256. X
  257. X    while (fgets (buf, sizeof (buf), fp) != NULL) {
  258. X        for (p = buf; *p && *p != ' '; p++)
  259. X            continue;
  260. X        if (*p != ' ') {
  261. X            error_message (txt_bad_active_file, buf);
  262. X            continue;
  263. X        }
  264. X        *p++ = '\0';
  265. X
  266. X        if (num_active >= max_active) {
  267. X            debug_nntp ("read_active_file", "EXPANDING active file");
  268. X            expand_active ();
  269. X        }
  270. X
  271. X        h = hash_groupname (buf);
  272. X
  273. X        if (group_hash[h] == -1) {
  274. X            group_hash[h] = num_active;
  275. X        } else {                /* hash linked list chaining */
  276. X            for (i=group_hash[h]; active[i].next >= 0; i=active[i].next) {
  277. X                if (strcmp(active[i].name, buf) == 0) {
  278. X                    goto read_active_continue;        /* kill dups */
  279. X                }
  280. X            }
  281. X            if (strcmp(active[i].name, buf) == 0)
  282. X                goto read_active_continue;
  283. X            active[i].next = num_active;
  284. X        }
  285. X
  286. X        for (q = p; *q && *q != ' '; q++)
  287. X            continue;
  288. X        if (*q != ' ') {
  289. X            error_message (txt_bad_active_file, buf);
  290. X            continue;
  291. X        }
  292. X        *q++ = '\0';
  293. X
  294. X        for (r = q; *r && *r != '\n'; r++) {
  295. X            if (*r == 'y' || *r == 'm') {
  296. X                moderated = *r;
  297. X                break;
  298. X            }
  299. X        }
  300. X
  301. X        /*
  302. X         * Group info.
  303. X         */
  304. X        active[num_active].name = str_dup (buf);
  305. X        active[num_active].description = (char *) 0;
  306. X        active[num_active].max = (long) atol (p);
  307. X        active[num_active].min = (long) atol (q);
  308. X        active[num_active].moderated = moderated;
  309. X        active[num_active].next = -1;            /* hash chaining */
  310. X        active[num_active].flag = UNSUBSCRIBED;    /* not in my_group[] yet */
  311. X        /*
  312. X         * Per group attributes
  313. X         */
  314. X        active[num_active].attribute.server  = (char *) 0;
  315. X        active[num_active].attribute.maildir = default_maildir;
  316. X        active[num_active].attribute.savedir = default_savedir;
  317. X        active[num_active].attribute.sigfile = default_sigfile;
  318. X        active[num_active].attribute.read    = FALSE;    /* read/unread */
  319. X        active[num_active].attribute.showall = show_only_unread;
  320. X        active[num_active].attribute.thread  = thread_arts;
  321. X        active[num_active].attribute.sortby  = sort_art_type;
  322. X        active[num_active].attribute.author  = show_author;
  323. X        active[num_active].attribute.autosave= save_archive_name;
  324. X        active[num_active].attribute.process = post_proc_type; 
  325. X
  326. X        num_active++;
  327. X
  328. Xread_active_continue:;
  329. X
  330. X    }
  331. X    fclose (fp);
  332. X
  333. X    /*
  334. X     *  exit if active file is empty
  335. X     */
  336. X    if (! num_active) {
  337. X        error_message (txt_active_file_is_empty, active_file);
  338. X        exit (1);
  339. X    }
  340. X
  341. X    /*
  342. X     * create backup of LIBDIR/active for use by -n option to notify new groups 
  343. X     */
  344. X    created = backup_active (TRUE);
  345. X
  346. X/*    if (cmd_line && (read_news_via_nntp && update == FALSE)) {
  347. X        if (! (update && ! verbose)) {
  348. X            wait_message ("\n");
  349. X        }
  350. X    }
  351. X*/
  352. X    if (cmd_line && ! update && ! verbose) {
  353. X        wait_message ("\n");
  354. X    }
  355. X
  356. X    return (created);
  357. X}
  358. X
  359. X/*
  360. X *  create ~/.tin/active from LIBDIR/active if it does not exist 
  361. X */
  362. X
  363. Xint backup_active (create)
  364. X    int create;
  365. X{
  366. X    char buf[LEN];
  367. X    FILE *fp;
  368. X    int created = FALSE;
  369. X    int i;
  370. X    struct stat sb;
  371. X    
  372. X    sprintf (buf, "%s/active", rcdir);
  373. X    
  374. X    if (create) {
  375. X        if (stat (buf, &sb) != -1) {
  376. X            goto backup_active_done;
  377. X        }
  378. X    }
  379. X    
  380. X    if ((fp = fopen (buf, "w")) != NULL) {
  381. X        for (i = 0; i < num_active ; i++) {    /* for each group */
  382. X            fprintf (fp, "%s\n", active[i].name);
  383. X        }
  384. X        fclose (fp);
  385. X        chmod (buf, 0644);
  386. X        created = TRUE;
  387. X    }
  388. X
  389. Xbackup_active_done:
  390. X    return (created);
  391. X}
  392. X
  393. X/*
  394. X *  Option -n to check for any newly created newsgroups.
  395. X */
  396. X
  397. Xvoid notify_groups ()
  398. X{
  399. X    char buf[LEN];
  400. X    FILE *fp;
  401. X    int group_not_found;
  402. X    int index;
  403. X    int num = 0;
  404. X    int update_old_active = FALSE;
  405. X    int max_old_active;
  406. X    register int i, j;
  407. X    struct notify_t {
  408. X        char name[LEN];
  409. X        int len;
  410. X        int visited;
  411. X    } *old_active = (struct notify_t *) 0;
  412. X    
  413. X    sprintf (buf, "%s/active", rcdir);
  414. X    
  415. X    if ((fp = fopen (buf, "r")) == NULL) {
  416. X        perror_message (txt_cannot_open, buf);
  417. X        goto notify_groups_done;
  418. X    }
  419. X
  420. X    Raw (TRUE);
  421. X    
  422. X    wait_message (txt_checking_active_file);
  423. X
  424. X    max_old_active = num_active;
  425. X    
  426. X    old_active = (struct notify_t *) my_malloc ((unsigned) sizeof (struct notify_t) * max_old_active);
  427. X    if (old_active == (struct notify_t *) 0) {
  428. X        error_message (txt_out_of_memory, progname);
  429. X        goto notify_groups_done;
  430. X    }
  431. X    
  432. X    while (fgets (old_active[num].name, sizeof (old_active[num].name), fp) != NULL) {
  433. X        old_active[num].len = strlen (old_active[num].name)-1;
  434. X        old_active[num].name[old_active[num].len] = '\0';
  435. X        old_active[num].visited = FALSE;
  436. X        num++;
  437. X        if (num >= max_old_active) {
  438. X            max_old_active= max_old_active + (max_old_active / 2);
  439. X            old_active= (struct notify_t*) my_realloc(
  440. X                (char *) old_active, 
  441. X                (unsigned) sizeof(struct notify_t) * max_old_active);
  442. X            if (old_active == (struct notify_t *) 0) {
  443. X                error_message (txt_out_of_memory, progname);
  444. X                goto notify_groups_done;
  445. X            }
  446. X        }
  447. X    }
  448. X
  449. X    for (i = 0 ; i < num_active ; i++) {    
  450. X        group_not_found = TRUE;
  451. X        for (j=0; j < num ; j++) {
  452. X            if (strcmp (old_active[j].name, active[i].name) == 0) {
  453. X                group_not_found = FALSE;    /* found it so read in next group */
  454. X                old_active[j].visited = TRUE;
  455. X                break;
  456. X            }
  457. X        }
  458. X
  459. X        if (group_not_found == FALSE) {
  460. X            continue;
  461. X        }    
  462. X
  463. X        update_old_active = TRUE;
  464. X        do {
  465. X            fputc ('\r', stdout);
  466. X            CleartoEOLN();
  467. X            printf (txt_subscribe_to_new_group, active[i].name);
  468. X            fflush (stdout);
  469. X            buf[0] = ReadCh();
  470. X        } while (buf[0] != 'y' && buf[0] != 'n');
  471. X            
  472. X        if (buf[0] == 'y') {
  473. X            index = add_group (active[i].name, TRUE);
  474. X            subscribe (active[my_group[index]].name, ':',
  475. X                   my_group[index], FALSE);
  476. X        }
  477. X        printf ("\r\n%s", txt_checking);
  478. X        fflush (stdout);
  479. X    }
  480. X    fclose (fp);
  481. X    fputc ('\r', stdout);
  482. X    fflush (stdout);
  483. X    CleartoEOLN();
  484. X
  485. X    /*
  486. X     * Look for bogus groups 
  487. X     */
  488. X    for (j = 0 ; j < num ; j++)  {
  489. X        if (old_active[j].visited) {
  490. X            continue;
  491. X        }
  492. X        do {    
  493. X            update_old_active= 1;
  494. X            fputc ('\r', stdout);
  495. X            CleartoEOLN ();
  496. X            printf (txt_delete_bogus_group, old_active[j].name);
  497. X            fflush (stdout);
  498. X            buf[0] = ReadCh ();
  499. X        } while (buf[0] != 'y' && buf[0] != 'n');
  500. X        if (buf[0] == 'y') {
  501. X            delete_group (old_active[j].name);
  502. X        }
  503. X        printf ("\r\n");
  504. X    }
  505. X    
  506. X    Raw (TRUE);
  507. X
  508. X    /*
  509. X     *  write active[] to ~/.tin/active
  510. X     */
  511. X    if (update_old_active) {
  512. X        backup_active (FALSE);
  513. X    }
  514. X
  515. Xnotify_groups_done:
  516. X    if (old_active != (struct notify_t *) 0) {
  517. X        free ((char *) old_active);
  518. X        old_active = (struct notify_t *) 0;
  519. X    }
  520. X}
  521. X
  522. X/*
  523. X *  Mark any groups in my_group[] that are in ~/.tin/unthread so they
  524. X *  will not be threaded
  525. X */
  526. Xvoid mark_unthreaded_groups ()
  527. X{
  528. X    FILE *fp;
  529. X    char buf[LEN];
  530. X    int i, len;
  531. X    long h;
  532. X
  533. X#ifndef INDEX_DAEMON
  534. X
  535. X    if ((fp = fopen (unthreadfile, "r")) == NULL) {
  536. X        perror_message (txt_cannot_open, unthreadfile);
  537. X        return;
  538. X    }
  539. X
  540. X    while (fgets (buf, sizeof (buf), fp) != NULL) {
  541. X        buf[strlen (buf)-1] = '\0'; 
  542. X        h = hash_groupname (buf);
  543. X        sprintf (msg, "Unthreading %s...\n", buf);
  544. X        wait_message (msg);
  545. X        
  546. X        i = group_hash[h];
  547. X        
  548. X        if (active[i].next == -1) {
  549. X            len = strlen (active[i].name);
  550. X            if (strncmp (active[i].name, buf, len) == 0) {
  551. X                active[i].attribute.thread = FALSE;
  552. X            }
  553. X        
  554. X        } else {
  555. X            for (i=group_hash[h] ; i >= 0 ; i=active[i].next) {
  556. X                len = strlen (active[i].name);
  557. X                if (strncmp (active[i].name, buf, len) == 0) {
  558. X                    active[i].attribute.thread = FALSE;
  559. X                    break;
  560. X                }
  561. X            }
  562. X        }    
  563. X    }
  564. X
  565. X    fclose (fp);
  566. X#endif /* INDEX_DAEMON */
  567. X}
  568. X
  569. X/*
  570. X *  Load the text description from LIBDIR/newsgroups for each group
  571. X *  into the active[] array.
  572. X */
  573. X
  574. Xvoid read_newsgroups_file ()
  575. X{
  576. X    FILE *fp;
  577. X    char *p, *q;
  578. X    char buf[LEN];
  579. X    char group[PATH_LEN];
  580. X    int i;
  581. X    long h;
  582. X    
  583. X    if (! show_description || update) {
  584. X        return;
  585. X    }
  586. X
  587. X    wait_message (txt_reading_newsgroups_file);
  588. X
  589. X    if ((fp = open_newsgroups_fp ()) == NULL) {
  590. X        return;
  591. X    }
  592. X
  593. X    while (fgets (buf, sizeof (buf), fp) != NULL) {
  594. X        buf[strlen (buf)-1] = '\0';
  595. X
  596. X        for (p = buf, q = group ; *p && *p != ' ' && *p != '\t' ; p++, q++) {
  597. X            *q = *p;
  598. X        }
  599. X        *q = '\0';
  600. X
  601. X        for (;*p == '\t' || *p == ' '; p++) {
  602. X            ;
  603. X        }    
  604. X                
  605. X        h = hash_groupname (group);
  606. X
  607. X        i = group_hash[h];
  608. X
  609. X        if (debug == 2) {
  610. X            fprintf (stderr, "HASH=[%5ld] IDX=[%5d] GRP=[%s] TXT=[%s]\n", h, i, group, p);
  611. X        }
  612. X        
  613. X        if (active[i].next == -1) {
  614. X            if (strcmp (active[i].name, group) == 0) {
  615. Xif (debug == 2) {
  616. X    fprintf (stderr, "FOUND HEAD\n");
  617. X}    
  618. X                if (active[i].description == (char *) 0) {
  619. X                    active[i].description = str_dup (p);
  620. X                }
  621. X            }
  622. X        } else {
  623. X            for (; i >= 0 ; i = active[i].next) {
  624. X                if (strcmp (active[i].name, group) == 0) {
  625. Xif (debug == 2) {
  626. X    fprintf (stderr, "FOUND LINK\n");
  627. X}    
  628. X                    if (active[i].description == (char *) 0) {
  629. X                        active[i].description = str_dup (p);
  630. X                        break;
  631. X                    }
  632. X                }
  633. X            }
  634. X        }
  635. X    }
  636. X    fclose (fp);
  637. X
  638. X    if (cmd_line && ! update && ! verbose) {
  639. X        wait_message ("\n");
  640. X    }
  641. X}
  642. END_OF_FILE
  643.   if test 10048 -ne `wc -c <'active.c'`; then
  644.     echo shar: \"'active.c'\" unpacked with wrong size!
  645.   fi
  646.   # end of 'active.c'
  647. fi
  648. if test -f 'getline.c' -a "${1}" != "-c" ; then 
  649.   echo shar: Will not clobber existing file \"'getline.c'\"
  650. else
  651.   echo shar: Extracting \"'getline.c'\" \(11458 characters\)
  652.   sed "s/^X//" >'getline.c' <<'END_OF_FILE'
  653. X/*
  654. X *  Project   : tin - a threaded Netnews reader
  655. X *  Module    : getline.c
  656. X *  Author    : Chris Thewalt & Iain Lea 
  657. X *  Created   : 09-11-91
  658. X *  Updated   : 29-03-92
  659. X *  Notes     : emacs style line editing input package.  
  660. X *  Copyright : (c) Copyright 1991-92 by Chris Thewalt & Iain Lea
  661. X *              Permission to use, copy, modify, and distribute this
  662. X *              software for any purpose and without fee is hereby
  663. X *              granted, provided that the above copyright notices
  664. X *              appear in all copies and that both the copyright
  665. X *              notice and this permission notice appear in supporting
  666. X *              documentation. This software is provided "as is" without
  667. X *              express or implied warranty.
  668. X */
  669. X
  670. X#include "tin.h"
  671. X
  672. Xextern int      isatty ();    
  673. X
  674. X#define BUF_SIZE    1024
  675. X#define SCROLL        30
  676. X#define TABSIZE        4
  677. X#ifndef HIST_SIZE
  678. X#define HIST_SIZE    100
  679. X#endif
  680. X
  681. X#define CTRL_A    '\001'
  682. X#define CTRL_B    '\002'
  683. X#define CTRL_D    '\004'
  684. X#define CTRL_E    '\005'
  685. X#define CTRL_F    '\006'
  686. X#define CTRL_H    '\010'
  687. X#define CTRL_K    '\013'
  688. X#define CTRL_L    '\014'
  689. X#define CTRL_R    '\022'
  690. X#define CTRL_N    '\016'
  691. X#define CTRL_P    '\020'
  692. X#define TAB        '\t'
  693. X#define DEL        '\177'
  694. X
  695. Xchar    *hist_buf[HIST_SIZE];
  696. Xint        hist_pos, hist_last;
  697. Xstatic char gl_buf[BUF_SIZE];       /* input buffer */
  698. Xstatic char *gl_prompt;                /* to save the prompt string */
  699. Xstatic int  gl_init_done = 0;        /* -1 is terminal, 1 is batch  */
  700. Xstatic int  gl_width = 0;            /* net size available for input */
  701. Xstatic int  gl_pos, gl_cnt = 0;     /* position and size of input */
  702. X
  703. X#if __STDC__
  704. X
  705. Xstatic int      gl_tab (char *, int, int *);
  706. Xstatic void        gl_redraw (void);
  707. Xstatic void     gl_addchar (int);
  708. Xstatic void     gl_newline (void);
  709. Xstatic void     gl_fixup (int, int);
  710. Xstatic void     gl_del (int);
  711. Xstatic void     gl_kill (void);
  712. Xstatic void     hist_add (void);
  713. Xstatic void     hist_init (void);
  714. Xstatic void     hist_next (void);
  715. Xstatic void     hist_prev (void);
  716. X
  717. Xint     (*gl_in_hook)(char *) = 0;
  718. Xint     (*gl_out_hook)(char *) = 0;
  719. Xint     (*gl_tab_hook)(char *, int, int *) = gl_tab;
  720. X
  721. X#else
  722. X
  723. Xstatic int      gl_tab ();
  724. Xstatic void        gl_redraw ();
  725. Xstatic void     gl_addchar ();
  726. Xstatic void     gl_newline ();
  727. Xstatic void     gl_fixup ();
  728. Xstatic void     gl_del ();
  729. Xstatic void     gl_kill ();
  730. Xstatic void     hist_add ();
  731. Xstatic void     hist_init ();
  732. Xstatic void     hist_next ();
  733. Xstatic void     hist_prev ();
  734. X
  735. Xint     (*gl_in_hook)() = 0;
  736. Xint     (*gl_out_hook)() = 0;
  737. Xint     (*gl_tab_hook)() = gl_tab;
  738. X
  739. X#endif
  740. X
  741. X
  742. X#if __STDC__
  743. Xchar *getline (char *prompt, int number_only, char *str)
  744. X#else
  745. Xchar *getline (prompt, number_only, str)
  746. X    char *prompt;
  747. X    int number_only;
  748. X    char *str;
  749. X#endif
  750. X{
  751. X    int c, i, loc, tmp;
  752. X
  753. X    if (! gl_init_done) {
  754. X        gl_init_done = 1;
  755. X        hist_init ();
  756. X    }
  757. X
  758. X    if (prompt == (char *) 0) {    
  759. X        prompt = "";
  760. X    }
  761. X    gl_buf[0] = 0;        /* used as end of input indicator */
  762. X    gl_fixup (-1, 0);    /* this resets gl_fixup */
  763. X    gl_width = COLS - strlen (prompt);
  764. X    gl_prompt = prompt;
  765. X    gl_pos = gl_cnt = 0;
  766. X
  767. X    fputs (prompt, stdout);
  768. X    fflush (stdout);
  769. X    
  770. X    if (gl_in_hook) {
  771. X        loc = gl_in_hook (gl_buf);
  772. X        if (loc >= 0)
  773. X            gl_fixup (0, BUF_SIZE);
  774. X    }
  775. X    if (str != (char *) 0) {
  776. X        for (i=0 ; str[i] ; i++) 
  777. X            gl_addchar (str[i]);
  778. X    }
  779. X    while ((c = ReadCh ()) != EOF) {
  780. X        c &= 0xff;    
  781. X        if (isprint (c)) {
  782. X            if (number_only) {
  783. X                if (isdigit (c) && gl_cnt < 6) {    /* num < 100000 */
  784. X                    gl_addchar (c);
  785. X                } else {
  786. X                    ring_bell ();
  787. X                }
  788. X            } else {
  789. X                gl_addchar (c);
  790. X            }
  791. X        } else {
  792. X            switch (c) {
  793. X                case ESC:             /* abort */
  794. X                    return (char *) 0;
  795. X                    break;
  796. X                case '\n':             /* newline */
  797. X                case '\r':
  798. X                    gl_newline ();
  799. X                    return gl_buf;
  800. X                    break;
  801. X                case CTRL_A:
  802. X                    gl_fixup (-1, 0);
  803. X                    break;
  804. X                case CTRL_B:
  805. X                    gl_fixup (-1, gl_pos-1);
  806. X                    break;
  807. X                case CTRL_D:
  808. X                    if (gl_cnt == 0) {
  809. X                        gl_buf[0] = 0;
  810. X                        fputc ('\n', stdout);
  811. X                        return gl_buf;
  812. X                    } else {
  813. X                        gl_del (0);
  814. X                    }
  815. X                    break;
  816. X                case CTRL_E:
  817. X                    gl_fixup (-1, gl_cnt);
  818. X                    break;
  819. X                case CTRL_F:
  820. X                    gl_fixup (-1, gl_pos+1);
  821. X                    break;
  822. X                case CTRL_H:
  823. X                case DEL:
  824. X                    gl_del (-1);
  825. X                    break;
  826. X                case TAB:
  827. X                    if (gl_tab_hook) {
  828. X                        tmp = gl_pos;
  829. X                        loc = gl_tab_hook (gl_buf, strlen (gl_prompt), &tmp);
  830. X                        if (loc >= 0 || tmp != gl_pos)
  831. X                            gl_fixup (loc, tmp);
  832. X                    }
  833. X                    break;
  834. X                case CTRL_K:
  835. X                    gl_kill ();
  836. X                    break;
  837. X                case CTRL_L:
  838. X                case CTRL_R:
  839. X                    gl_redraw ();
  840. X                    break;
  841. X                case CTRL_N:
  842. X                    hist_next ();
  843. X                    break;
  844. X                case CTRL_P:
  845. X                    hist_prev ();
  846. X                    break;
  847. X                default:
  848. X                    ring_bell ();
  849. X                    break;
  850. X            }
  851. X        }
  852. X    }
  853. X    return gl_buf;
  854. X}
  855. X
  856. X/*
  857. X * adds the character c to the input buffer at current location if
  858. X * the character is in the allowed template of characters
  859. X */
  860. X
  861. X#if __STDC__
  862. Xstatic void gl_addchar (int c)
  863. X#else
  864. Xstatic void gl_addchar (c)
  865. X    int c;
  866. X#endif
  867. X{
  868. X    int  i;
  869. X
  870. X    if (gl_cnt >= BUF_SIZE - 1) {
  871. X        error_message ("getline: input buffer overflow", "");
  872. X        exit (1);
  873. X    }
  874. X    
  875. X    for (i=gl_cnt; i >= gl_pos; i--) {
  876. X        gl_buf[i+1] = gl_buf[i];
  877. X    }
  878. X    gl_buf[gl_pos] = c;
  879. X    gl_fixup (gl_pos, gl_pos+1);
  880. X}
  881. X
  882. X/*
  883. X * Cleans up entire line before returning to caller. A \n is appended.
  884. X * If line longer than screen, we redraw starting at beginning
  885. X */
  886. X
  887. Xstatic void gl_newline ()
  888. X{
  889. X    int change = gl_cnt;
  890. X    int len = gl_cnt;
  891. X    int loc = gl_width - 5;    /* shifts line back to start position */
  892. X
  893. X    if (gl_cnt >= BUF_SIZE - 1) {
  894. X        error_message ("getline: input buffer overflow", "");
  895. X        exit (1);
  896. X    }
  897. X    hist_add ();            /* only adds if nonblank */
  898. X    if (gl_out_hook) {
  899. X        change = gl_out_hook (gl_buf);
  900. X        len = strlen (gl_buf);
  901. X    } 
  902. X    if (loc > len)
  903. X        loc = len;
  904. X    gl_fixup (change, loc);    /* must do this before appending \n */
  905. X    gl_buf[len] = '\0';
  906. X}
  907. X
  908. X/*
  909. X * Delete a character.  The loc variable can be:
  910. X *    -1 : delete character to left of cursor
  911. X *     0 : delete character under cursor
  912. X */
  913. X
  914. X#if __STDC__
  915. Xstatic void gl_del (int loc)
  916. X#else
  917. Xstatic void gl_del (loc)
  918. X    int loc;
  919. X#endif
  920. X{
  921. X    int i;
  922. X
  923. X    if ((loc == -1 && gl_pos > 0) || (loc == 0 && gl_pos < gl_cnt)) {
  924. X        for (i=gl_pos+loc; i < gl_cnt; i++)
  925. X            gl_buf[i] = gl_buf[i+1];
  926. X        gl_fixup (gl_pos+loc, gl_pos+loc);
  927. X    } else {
  928. X        ring_bell ();
  929. X    }
  930. X}
  931. X
  932. X/*
  933. X * delete from current position to the end of line
  934. X */
  935. Xstatic void gl_kill ()
  936. X{
  937. X    if (gl_pos < gl_cnt) {
  938. X        gl_buf[gl_pos] = '\0';
  939. X        gl_fixup (gl_pos, gl_pos);
  940. X    } else {
  941. X        ring_bell ();
  942. X    }
  943. X}
  944. X
  945. X/*
  946. X * emit a newline, reset and redraw prompt and current input line
  947. X */
  948. X
  949. Xstatic void gl_redraw ()
  950. X{
  951. X    if (gl_init_done == -1) {
  952. X        fputc ('\n', stdout);
  953. X        fputs (gl_prompt, stdout);
  954. X        gl_pos = 0;
  955. X        gl_fixup (0, BUF_SIZE);
  956. X    }
  957. X}
  958. X
  959. X/*
  960. X * This function is used both for redrawing when input changes or for
  961. X * moving within the input line.  The parameters are:
  962. X *   change : the index of the start of changes in the input buffer,
  963. X *            with -1 indicating no changes.
  964. X *   cursor : the desired location of the cursor after the call.
  965. X *            A value of BUF_SIZE can be used to indicate the cursor
  966. X *            should move just past the end of the input line.
  967. X */
  968. X
  969. X#if __STDC__
  970. Xstatic void gl_fixup (int change, int cursor)
  971. X#else
  972. Xstatic void gl_fixup (change, cursor)
  973. X    int change;
  974. X    int cursor;
  975. X#endif
  976. X{
  977. X    static int   gl_shift;    /* index of first on screen character */
  978. X    static int   off_right;    /* true if more text right of screen */
  979. X    static int   off_left;    /* true if more text left of screen */
  980. X    int          left = 0, right = -1;        /* bounds for redraw */
  981. X    int          pad;        /* how much to erase at end of line */
  982. X    int          backup;        /* how far to backup before fixing */
  983. X    int          new_shift;     /* value of shift based on cursor */
  984. X    int          extra;         /* adjusts when shift (scroll) happens */
  985. X    int          i;
  986. X
  987. X    if (change == -1 && cursor == 0 && gl_buf[0] == 0) {   /* reset */
  988. X        gl_shift = off_right = off_left = 0;
  989. X        return;
  990. X    }
  991. X    pad = (off_right) ? gl_width - 1 : gl_cnt - gl_shift;   /* old length */
  992. X    backup = gl_pos - gl_shift;
  993. X    if (change >= 0) {
  994. X        gl_cnt = strlen (gl_buf);
  995. X        if (change > gl_cnt)
  996. X            change = gl_cnt;
  997. X    }
  998. X    if (cursor > gl_cnt) {
  999. X        if (cursor != BUF_SIZE)        /* BUF_SIZE means end of line */
  1000. X            ring_bell ();
  1001. X            cursor = gl_cnt;
  1002. X    }
  1003. X    if (cursor < 0) {
  1004. X        ring_bell ();
  1005. X        cursor = 0;
  1006. X    }
  1007. X    if (off_right || off_left && (cursor < gl_shift + gl_width - SCROLL / 2))
  1008. X        extra = 2;            /* shift the scrolling boundary */
  1009. X    else 
  1010. X        extra = 0;
  1011. X    new_shift = cursor + extra + SCROLL - gl_width;
  1012. X    if (new_shift > 0) {
  1013. X        new_shift /= SCROLL;
  1014. X        new_shift *= SCROLL;
  1015. X    } else
  1016. X        new_shift = 0;
  1017. X    if (new_shift != gl_shift) {    /* scroll occurs */
  1018. X        gl_shift = new_shift;
  1019. X        off_left = (gl_shift) ? 1 : 0;
  1020. X        off_right = (gl_cnt > gl_shift + gl_width - 1)? 1 : 0;
  1021. X        left = gl_shift;
  1022. X        right = (off_right) ? gl_shift + gl_width - 2 : gl_cnt;
  1023. X    } else if (change >= 0) {        /* no scroll, but text changed */
  1024. X        if (change < gl_shift + off_left) {
  1025. X            left = gl_shift;
  1026. X        } else {
  1027. X            left = change;
  1028. X            backup = gl_pos - change;
  1029. X        }
  1030. X        off_right = (gl_cnt > gl_shift + gl_width - 1)? 1 : 0;
  1031. X        right = (off_right) ? gl_shift + gl_width - 2 : gl_cnt;
  1032. X    }
  1033. X    pad -= (off_right) ? gl_width - 1 : gl_cnt - gl_shift;
  1034. X    pad = (pad < 0)? 0 : pad;
  1035. X    if (left <= right) {        /* clean up screen */
  1036. X        for (i=0; i < backup; i++)
  1037. X            fputc ('\b', stdout);
  1038. X        if (left == gl_shift && off_left) {
  1039. X            fputc ('$', stdout);
  1040. X            left++;
  1041. X        }
  1042. X        for (i=left; i < right; i++)
  1043. X            fputc (gl_buf[i], stdout);
  1044. X        if (off_right) {
  1045. X            fputc ('$', stdout);
  1046. X            gl_pos = right + 1;
  1047. X        } else { 
  1048. X            for (i=0; i < pad; i++)    /* erase remains of prev line */
  1049. X                fputc (' ', stdout);
  1050. X            gl_pos = right + pad;
  1051. X        }
  1052. X    }
  1053. X    i = gl_pos - cursor;        /* move to final cursor location */
  1054. X    if (i > 0) {
  1055. X        while (i--)
  1056. X            fputc ('\b', stdout);
  1057. X    } else {
  1058. X        for (i=gl_pos; i < cursor; i++)
  1059. X            fputc (gl_buf[i], stdout);
  1060. X    }
  1061. X    fflush (stdout);
  1062. X    gl_pos = cursor;
  1063. X}
  1064. X    
  1065. X/*
  1066. X * default tab handler, acts like tabstops every TABSIZE cols
  1067. X */
  1068. X
  1069. X#if __STDC__
  1070. Xstatic int gl_tab (char *buf, int offset, int *loc)
  1071. X#else
  1072. Xstatic int gl_tab (buf, offset, loc)
  1073. X    char *buf;
  1074. X    int offset;
  1075. X    int *loc;
  1076. X#endif
  1077. X{
  1078. X    int i, count, len;
  1079. X    
  1080. X    len = strlen (buf);
  1081. X    count = TABSIZE - (offset + *loc) % TABSIZE;
  1082. X    for (i=len; i >= *loc; i--)
  1083. X        buf[i+count] = buf[i];
  1084. X    for (i=0; i < count; i++)
  1085. X        buf[*loc+i] = ' ';
  1086. X    i = *loc;
  1087. X    *loc = i + count;
  1088. X    return i;
  1089. X}
  1090. X
  1091. X/*
  1092. X * History functions
  1093. X */
  1094. X
  1095. Xstatic void hist_init ()
  1096. X{
  1097. X    int i;
  1098. X    
  1099. X    for (i=0; i < HIST_SIZE; i++)
  1100. X        hist_buf[i] = (char *) 0;
  1101. X}
  1102. X
  1103. X
  1104. Xstatic void hist_add ()
  1105. X{
  1106. X    char *p = gl_buf;
  1107. X
  1108. X    while (*p == ' ' || *p == '\t')    /* only save nonblank line */
  1109. X        p++;
  1110. X    if (*p) {
  1111. X        hist_buf[hist_last] = str_dup (gl_buf);
  1112. X        hist_last = (hist_last + 1) % HIST_SIZE;
  1113. X        if (hist_buf[hist_last]) {    /* erase next location */
  1114. X            free(hist_buf[hist_last]);
  1115. X            hist_buf[hist_last] = (char *) 0;
  1116. X        }
  1117. X    }
  1118. X    hist_pos = hist_last;
  1119. X}
  1120. X
  1121. X/*
  1122. X * loads previous hist entry into input buffer, sticks on first
  1123. X */
  1124. Xstatic void hist_prev ()
  1125. X{
  1126. X    int   next;
  1127. X
  1128. X    next = (hist_pos - 1 + HIST_SIZE) % HIST_SIZE;
  1129. X    if (next != hist_last) {
  1130. X        if (hist_buf[next]) {
  1131. X            hist_pos = next;
  1132. X            strcpy (gl_buf, hist_buf[hist_pos]);
  1133. X        } else {
  1134. X            ring_bell ();
  1135. X        }
  1136. X    } else {
  1137. X        ring_bell ();
  1138. X    }
  1139. X    if (gl_in_hook)
  1140. X        gl_in_hook (gl_buf);
  1141. X    gl_fixup (0, BUF_SIZE);
  1142. X}
  1143. X
  1144. X/*
  1145. X * loads next hist entry into input buffer, clears on last
  1146. X */
  1147. Xstatic void hist_next ()
  1148. X{
  1149. X    if (hist_pos != hist_last) {
  1150. X        hist_pos = (hist_pos + 1) % HIST_SIZE;
  1151. X        if (hist_buf[hist_pos]) {
  1152. X            strcpy (gl_buf, hist_buf[hist_pos]);
  1153. X        } else {
  1154. X            gl_buf[0] = 0;
  1155. X        }
  1156. X    } else {
  1157. X        ring_bell ();
  1158. X    }
  1159. X    if (gl_in_hook) 
  1160. X        gl_in_hook (gl_buf);
  1161. X    gl_fixup (0, BUF_SIZE);
  1162. X}
  1163. END_OF_FILE
  1164.   if test 11458 -ne `wc -c <'getline.c'`; then
  1165.     echo shar: \"'getline.c'\" unpacked with wrong size!
  1166.   fi
  1167.   # end of 'getline.c'
  1168. fi
  1169. if test -f 'main.c' -a "${1}" != "-c" ; then 
  1170.   echo shar: Will not clobber existing file \"'main.c'\"
  1171. else
  1172.   echo shar: Extracting \"'main.c'\" \(12528 characters\)
  1173.   sed "s/^X//" >'main.c' <<'END_OF_FILE'
  1174. X/*
  1175. X *  Project   : tin - a threaded Netnews reader
  1176. X *  Module    : main.c
  1177. X *  Author    : I.Lea & R.Skrenta
  1178. X *  Created   : 01-04-91
  1179. X *  Updated   : 04-06-92
  1180. X *  Notes     :
  1181. X *  Copyright : (c) Copyright 1991-92 by Iain Lea & Rich Skrenta
  1182. X *              You may  freely  copy or  redistribute  this software,
  1183. X *              so  long as there is no profit made from its use, sale
  1184. X *              trade or  reproduction.  You may not change this copy-
  1185. X *              right notice, and it must be included in any copy made
  1186. X */
  1187. X
  1188. X#include    "tin.h"
  1189. X
  1190. X/*
  1191. X * OK lets start the ball rolling...
  1192. X */
  1193. Xvoid main (argc, argv)
  1194. X    int argc;    
  1195. X    char *argv[];
  1196. X{
  1197. X    int created, i;
  1198. X    int start_groupnum = 0;
  1199. X
  1200. X    cmd_line = TRUE;
  1201. X    debug = 0;    /* debug OFF */
  1202. X
  1203. X    set_signal_handlers ();
  1204. X
  1205. X    basename (argv[0], progname);
  1206. X
  1207. X    sprintf (page_header, "%s %s PL%d", progname, VERSION, PATCHLEVEL);     
  1208. X    sprintf (cvers, "%s (c) Copyright 1991-92 Iain Lea.", page_header);
  1209. X
  1210. X#if defined(NNTP_ONLY) || defined(CDROM_ONLY)
  1211. X    read_news_via_nntp = TRUE;
  1212. X#else
  1213. X    /* 
  1214. X     * rtin/cdtin so read news remotely via NNTP 
  1215. X     */
  1216. X    if (progname[0] == 'r' || (progname[0] == 'c' && progname[1] == 'd' )) {
  1217. X#        ifdef NNTP_ABLE            
  1218. X            read_news_via_nntp = TRUE;
  1219. X#        else
  1220. X            error_message (txt_option_not_enabled, "-DNNTP_ABLE");
  1221. X            exit (1);
  1222. X#        endif
  1223. X    }
  1224. X#endif
  1225. X
  1226. X    /*
  1227. X     * set up char *'s: homedir, newsrc, etc. 
  1228. X     */
  1229. X    init_selfinfo ();
  1230. X
  1231. X    /*
  1232. X     * process command line options
  1233. X     */
  1234. X    read_cmd_line_options (argc, argv);
  1235. X    if (update_fork || (update && verbose) || !update) {
  1236. X        error_message (cvers, "");
  1237. X    }
  1238. X
  1239. X    /*
  1240. X     *  if specified connect to (cdrom pseudo) nntp server
  1241. X     */
  1242. X    nntp_open ();
  1243. X
  1244. X    /*
  1245. X     *  allocate initial array sizes
  1246. X     */
  1247. X    init_alloc ();
  1248. X    hash_init ();
  1249. X
  1250. X    /*
  1251. X     *  load the active file into active[]
  1252. X     */
  1253. X    created = read_active_file ();
  1254. X
  1255. X    /*
  1256. X     * read text descriptions for each group from LIBDIR/newsgroups
  1257. X     */
  1258. X    read_newsgroups_file ();
  1259. X    debug_print_active ();
  1260. X    
  1261. X    /*
  1262. X     *  log username info to local/central logfile (NNTP XUSER)
  1263. X     */
  1264. X    log_user ();
  1265. X
  1266. X    if (create_mail_save_dirs ()) {
  1267. X        write_rcfile ();
  1268. X    }    
  1269. X
  1270. X    if (optind < argc) {
  1271. X        while (optind < argc) {
  1272. X            for (i = 0 ; i < num_active ; i++) {
  1273. X                if (wildmat(active[i].name, argv[optind])) {        
  1274. X                    if (add_group (active[i].name, TRUE) < 0) {
  1275. X                        error_message (txt_not_in_active_file, active[i].name);
  1276. X                    }
  1277. X                }    
  1278. X            }    
  1279. X            optind++;
  1280. X        }
  1281. X    } else {
  1282. X        backup_newsrc ();
  1283. X        read_newsrc (TRUE);
  1284. X        mark_unthreaded_groups ();
  1285. X    }
  1286. X
  1287. X    /*
  1288. X     *  read in users kill/auto-select (hot) file
  1289. X     */
  1290. X    killed_articles = read_kill_file ();
  1291. X    
  1292. X    /*
  1293. X     *  check/start if any new/unread articles
  1294. X     */
  1295. X    start_groupnum = check_for_any_new_news (check_any_unread, start_any_unread);
  1296. X
  1297. X    /*
  1298. X     *  mail any new articles to specified user
  1299. X     *  or
  1300. X     *  save any new articles to savedir structure for later reading
  1301. X     */
  1302. X    save_or_mail_new_news ();
  1303. X    
  1304. X    /*
  1305. X     *  update index files
  1306. X     */
  1307. X    update_index_files ();
  1308. X    
  1309. X    if (! InitScreen ()) {
  1310. X        error_message (txt_screen_init_failed, progname);
  1311. X        exit (1);
  1312. X    }
  1313. X
  1314. X    /*
  1315. X     *   get screen size from termcap entry 
  1316. X     */
  1317. X    ScreenSize (&LINES, &COLS);
  1318. X    cmd_line = FALSE;
  1319. X    Raw (TRUE);
  1320. X
  1321. X    /* 
  1322. X     *  check & set actual screen size
  1323. X     */
  1324. X    set_win_size (&LINES, &COLS);
  1325. X
  1326. X    /*
  1327. X     *  check for any newly created newsgroups
  1328. X     */
  1329. X    if (notify_new_groups && ! created) {
  1330. X        notify_groups ();
  1331. X    }
  1332. X
  1333. X    /*
  1334. X     *  if first time print welcome screen
  1335. X      and auto-subscribe
  1336. X     *  to groups specified in /usr/lib/news/subscribe locally
  1337. X     *  or via NNTP if reading news remotely (LIST SUBSCRIBE)
  1338. X     */
  1339. X    if (created_rcdir && update == FALSE) {
  1340. X        show_intro_page ();
  1341. X    }
  1342. X    
  1343. X    selection_index (start_groupnum);
  1344. X
  1345. X    tin_done (0);
  1346. X}
  1347. X
  1348. X/*
  1349. X * process command line options
  1350. X */
  1351. X
  1352. Xvoid read_cmd_line_options (argc, argv)
  1353. X    int argc;
  1354. X    char *argv[];
  1355. X{
  1356. X    int ch;
  1357. X
  1358. X#ifdef INDEX_DAEMON
  1359. X    while ((ch = getopt (argc, argv, "D:f:hI:vV")) != EOF) {
  1360. X#else
  1361. X    while ((ch = getopt (argc, argv, "cD:f:hHI:m:M:np:rRs:SuUvVzZ")) != EOF) {
  1362. X#endif
  1363. X        switch (ch) {
  1364. X            case 'c':
  1365. X                catchup = TRUE;
  1366. X                update = TRUE;
  1367. X                break;
  1368. X                
  1369. X            case 'D':        /* debug mode 1=NNTP 2=ALL */
  1370. X#ifdef DEBUG            
  1371. X                redirect_output[0] = '\0';
  1372. X                debug = atoi (optarg);
  1373. X#else
  1374. X                error_message (txt_option_not_enabled, "-DDEBUG");
  1375. X                exit (1);
  1376. X#endif
  1377. X                break;
  1378. X
  1379. X            case 'f':
  1380. X                my_strncpy (newsrc, optarg, sizeof (newsrc));
  1381. X                break;
  1382. X
  1383. X            case 'H':
  1384. X                show_intro_page ();
  1385. X                exit (1);
  1386. X                break;
  1387. X
  1388. X#if !defined(NNTP_ONLY) || !defined(NNTP_XINDEX)
  1389. X            case 'I':
  1390. X                my_strncpy (indexdir, optarg, sizeof (indexdir));
  1391. X                mkdir (indexdir, 0777);
  1392. X                break;
  1393. X#endif
  1394. X            case 'm':
  1395. X                my_strncpy (default_maildir, optarg, sizeof (default_maildir));
  1396. X                break;
  1397. X
  1398. X            case 'M':    /* mail new news to specified user */
  1399. X                my_strncpy (mail_news_user, optarg, sizeof (mail_news_user));
  1400. X                mail_news = TRUE;
  1401. X                update = TRUE;
  1402. X                catchup = TRUE;
  1403. X                break;
  1404. X
  1405. X            case 'n':
  1406. X                notify_new_groups = TRUE;
  1407. X                break;
  1408. X
  1409. X            case 'p':
  1410. X                my_strncpy (cmd_line_printer, optarg, sizeof (cmd_line_printer));
  1411. X                default_printer = FALSE;
  1412. X                break;
  1413. X
  1414. X            case 'r':    /* read news remotely from default NNTP server */
  1415. X#ifdef NNTP_ABLE            
  1416. X                read_news_via_nntp = TRUE;
  1417. X#else
  1418. X                error_message (txt_option_not_enabled, "-DNNTP_ABLE");
  1419. X                exit (1);
  1420. X#endif
  1421. X                break;
  1422. X
  1423. X            case 'R':    /* read news saved by -S option */
  1424. X                error_message ("%s: Option -R not yet implemented.", progname);
  1425. X                exit (1);
  1426. X                break;
  1427. X
  1428. X            case 's':
  1429. X                my_strncpy (default_savedir, optarg, sizeof (default_savedir));
  1430. X                break;
  1431. X
  1432. X            case 'S':    /* save new news to dir structure */
  1433. X                save_news = TRUE;
  1434. X                update = TRUE;
  1435. X                break;
  1436. X
  1437. X            case 'u':    /* update index files */
  1438. X                update = TRUE;
  1439. X                break;
  1440. X
  1441. X            case 'U':    /* update index files in background */
  1442. X                update_fork = TRUE;
  1443. X                update = TRUE;
  1444. X                break;
  1445. X
  1446. X            case 'v':    /* verbose mode */
  1447. X                verbose = TRUE;
  1448. X                break;
  1449. X
  1450. X            case 'V':
  1451. X#if defined(__DATE__) && defined(__TIME__)            
  1452. X                sprintf (msg, "Version: %s PL%d  %s %s",
  1453. X                    VERSION, PATCHLEVEL, __DATE__, __TIME__);
  1454. X#else
  1455. X                sprintf (msg, "Version: %s PL%d",
  1456. X                    VERSION, PATCHLEVEL);
  1457. X#endif                    
  1458. X                error_message (msg, "");
  1459. X                exit (1);
  1460. X                break;
  1461. X
  1462. X            case 'z':
  1463. X                start_any_unread = TRUE;
  1464. X                update = TRUE;
  1465. X                break;
  1466. X
  1467. X            case 'Z':
  1468. X                check_any_unread = TRUE;
  1469. X                update = TRUE;
  1470. X                break;
  1471. X
  1472. X            case 'h':
  1473. X            case '?':
  1474. X            default:
  1475. X                usage (progname);
  1476. X                exit (1);
  1477. X        }
  1478. X    }
  1479. X}
  1480. X
  1481. X/*
  1482. X * usage
  1483. X */
  1484. X
  1485. Xvoid usage (progname)
  1486. X    char *progname;
  1487. X{
  1488. X#ifndef INDEX_DAEMON
  1489. X    error_message ("%s A threaded Netnews reader.\n", cvers);
  1490. X#else
  1491. X    error_message ("%s Tin index file daemon.\n", cvers);
  1492. X#endif
  1493. X    error_message ("Usage: %s [options] [newsgroups]", progname);
  1494. X#ifndef INDEX_DAEMON
  1495. X    error_message ("  -c       mark all news as read in subscribed newsgroups (batch mode)", "");
  1496. X#endif
  1497. X    error_message ("  -f file  subscribed to newsgroups file [default=%s]", newsrc);
  1498. X    error_message ("  -h       help", "");
  1499. X#ifndef INDEX_DAEMON
  1500. X    error_message ("  -H       help information about %s", progname);
  1501. X#endif
  1502. X    error_message ("  -I dir   index file directory [default=%s]", indexdir);
  1503. X#ifndef INDEX_DAEMON
  1504. X    error_message ("  -m dir   mailbox directory [default=%s]", default_maildir);
  1505. X    error_message ("  -M user  mail new news to specified user (batch mode)", "");
  1506. X    error_message ("  -n       notify user of any newly created newsgroups", "");
  1507. X    error_message ("  -p file  print program with options [default=%s]", DEFAULT_PRINTER);
  1508. X#  if defined(NNTP_ABLE) && !defined(NNTP_ONLY)
  1509. X    if (! read_news_via_nntp) {
  1510. X        error_message ("  -r       read news remotely from default NNTP server", "");
  1511. X    }
  1512. X#  endif /* NNTP_ABLE */    
  1513. X    error_message ("  -R       read news saved by -S option (not yet implemented)", "");
  1514. X    error_message ("  -s dir   save news directory [default=%s]", default_savedir);
  1515. X    error_message ("  -S       save new news for later reading (batch mode)", "");
  1516. X#  if !defined(NNTP_ONLY) || !defined(NNTP_XINDEX)
  1517. X    error_message ("  -u       update index files (batch mode)", "");
  1518. X    error_message ("  -U       update index files in the background while reading news", "");
  1519. X#  endif /* NNTP_XINDEX */
  1520. X#endif /* INDEX_DAEMON */
  1521. X    error_message ("  -v       verbose output for batch mode options", "");
  1522. X#ifndef INDEX_DAEMON
  1523. X    error_message ("  -z       start if any unread news", "");
  1524. X    error_message ("  -Z       return status indicating if any unread news (batch mode)", "");
  1525. X#endif
  1526. X    error_message ("\nMail bug reports/comments to %s", BUG_REPORT_ADDRESS);
  1527. X}
  1528. X
  1529. X/*
  1530. X *  check/start if any new/unread articles
  1531. X */
  1532. X
  1533. Xint check_for_any_new_news (check_any_unread, start_any_unread)
  1534. X    int check_any_unread;
  1535. X    int start_any_unread;
  1536. X{
  1537. X    int i = 0;
  1538. X    
  1539. X    if (check_any_unread) {
  1540. X        i = check_start_save_any_news (CHECK_ANY_NEWS);
  1541. X        exit (i);
  1542. X    }
  1543. X    
  1544. X    if (start_any_unread) {
  1545. X        i = check_start_save_any_news (START_ANY_NEWS);
  1546. X        if (i == -1) {        /* no new/unread news so exit */
  1547. X            exit (0);
  1548. X        }
  1549. X        update = FALSE;
  1550. X    }
  1551. X    return (i);
  1552. X}
  1553. X
  1554. X/*
  1555. X *  mail any new articles to specified user
  1556. X *  or
  1557. X *  save any new articles to savedir structure for later reading
  1558. X */
  1559. X
  1560. Xvoid save_or_mail_new_news ()
  1561. X{
  1562. X    int i;
  1563. X    
  1564. X    if (mail_news || save_news) {
  1565. X        i = catchup;            /* set catchup to FALSE */
  1566. X        catchup = FALSE;
  1567. X        do_update ();
  1568. X        catchup = i;            /* set catchup to previous value */
  1569. X        if (mail_news) {
  1570. X            check_start_save_any_news (MAIL_ANY_NEWS);
  1571. X        } else {
  1572. X            check_start_save_any_news (SAVE_ANY_NEWS);
  1573. X        }
  1574. X        tin_done (0);
  1575. X    }
  1576. X}
  1577. X
  1578. X/*
  1579. X *  update index files
  1580. X */
  1581. X
  1582. Xvoid update_index_files ()
  1583. X{
  1584. X    if (update || update_fork) {
  1585. X        if (read_news_via_nntp && xindex_supported) {
  1586. X            error_message ("%s: Updating of index files not supported", progname);
  1587. X            tin_done (1);
  1588. X        }
  1589. X
  1590. X        COLS = 132;                    /* set because curses has not started */ 
  1591. X        if (update_fork) {
  1592. X            catchup = FALSE;        /* turn off msgs when running forked */ 
  1593. X            verbose = FALSE;
  1594. X            switch (fork ()) {        /* fork child to update indexes in background */
  1595. X                case -1:    /* error forking */    
  1596. X                    perror_message ("Failed to start background indexing process", "");
  1597. X                    break;
  1598. X                case 0:        /* child process */    
  1599. X                    process_id = getpid ();
  1600. X#ifdef BSD
  1601. X                    setpgrp (0, process_id);    /* reset process group leader to this process */
  1602. X#    ifdef TIOCNOTTY
  1603. X                    {
  1604. X                        int fd;
  1605. X    
  1606. X                        if ((fd = open ("/dev/tty", O_RDWR)) >= 0) {
  1607. X                            ioctl (fd, TIOCNOTTY, (char *) NULL);
  1608. X                            close (fd);
  1609. X                        }    
  1610. X                    }    
  1611. X#    endif
  1612. X#else
  1613. X                    setpgrp ();
  1614. X                    signal (SIGHUP, SIG_IGN);    /* make immune from process group leader death */
  1615. X#endif
  1616. X                    signal (SIGQUIT, SIG_IGN);    /* stop indexing being interrupted */            
  1617. X                    signal (SIGALRM, SIG_IGN);    /* stop indexing resyning active file */            
  1618. X                    nntp_open ();            /* connect server if we are using nntp */
  1619. X                    thread_arts = FALSE;    /* stop threading to run faster */
  1620. X                    do_update ();
  1621. X                    nntp_close ();            /* connect server if we are using nntp */
  1622. X                    exit (0);
  1623. X                    break;
  1624. X                default:    /* parent process*/
  1625. X                    break;                    
  1626. X            }    
  1627. X            update = FALSE;
  1628. X        } else {
  1629. X            thread_arts = FALSE;    /* stop threading to run faster */
  1630. X            do_update ();
  1631. X            tin_done (0);
  1632. X        }
  1633. X    }
  1634. X}
  1635. X
  1636. X/*
  1637. X *  display page of general info. for first time user.
  1638. X */
  1639. X
  1640. Xvoid show_intro_page ()
  1641. X{
  1642. X    if (cmd_line) {
  1643. X        wait_message (cvers);     
  1644. X    } else {
  1645. X        ClearScreen ();
  1646. X        center_line (0, TRUE, cvers); 
  1647. X        Raw (FALSE);    
  1648. X    }
  1649. X
  1650. X    printf ("\n\nWelcome to tin, a full screen threaded Netnews reader. It can read news locally\n");
  1651. X    printf ("(ie. <spool>/news) or remotely (-r option) from a NNTP  (Network News Transport\n");
  1652. X    printf ("Protocol) server. tin -h lists the available command line options.\n\n");
  1653. X
  1654. X    printf ("Tin has four newsreading levels, the newsgroup selection page,  the group index\n");
  1655. X    printf ("page, the thread listing page and the article viewer. Help is available at each\n");
  1656. X    printf ("level by pressing the 'h' command.\n\n");
  1657. X
  1658. X    printf ("Move up/down by using the terminal arrow keys or 'j' and 'k'.  Use PgUp/PgDn or\n");
  1659. X    printf ("Ctrl-U and Ctrl-D to page up/down. Enter a newsgroup by pressing RETURN.\n\n");
  1660. X
  1661. X    printf ("Articles, threads, tagged articles or articles matching a pattern can be mailed\n");
  1662. X    printf ("('m' command), printed ('o' command), saved ('s' command), piped ('|' command).\n");
  1663. X    printf ("Use the 'w' command  to post  a news  article,  the 'f'/'F' commands to  post a\n");
  1664. X    printf ("follow-up  to  an existing  news article and the 'r'/'R' commands to  reply via\n");
  1665. X    printf ("mail to an existing news articles author.  The 'M' command allows the operation\n");
  1666. X    printf ("of tin to be configured via a menu.\n\n");
  1667. X
  1668. X    printf ("For more information read the manual page, README, INSTALL, TODO and FTP files.\n\n");
  1669. X    printf ("Please send bug reports/comments to the programs author with the 'B' command.\n");
  1670. X    fflush (stdout);
  1671. X
  1672. X    if (! cmd_line) {
  1673. X        Raw (TRUE);    
  1674. X        continue_prompt ();
  1675. X    }
  1676. X}
  1677. X
  1678. END_OF_FILE
  1679.   if test 12528 -ne `wc -c <'main.c'`; then
  1680.     echo shar: \"'main.c'\" unpacked with wrong size!
  1681.   fi
  1682.   # end of 'main.c'
  1683. fi
  1684. if test -f 'signal.c' -a "${1}" != "-c" ; then 
  1685.   echo shar: Will not clobber existing file \"'signal.c'\"
  1686. else
  1687.   echo shar: Extracting \"'signal.c'\" \(10115 characters\)
  1688.   sed "s/^X//" >'signal.c' <<'END_OF_FILE'
  1689. X/*
  1690. X *  Project   : tin - a threaded Netnews reader
  1691. X *  Module    : signal.c
  1692. X *  Author    : I.Lea
  1693. X *  Created   : 01-04-91
  1694. X *  Updated   : 22-06-92
  1695. X *  Notes     : signal handlers for different modes and window resizing
  1696. X *  Copyright : (c) Copyright 1991-92 by Iain Lea
  1697. X *              You may  freely  copy or  redistribute  this software,
  1698. X *              so  long as there is no profit made from its use, sale
  1699. X *              trade or  reproduction.  You may not change this copy-
  1700. X *              right notice, and it must be included in any copy made
  1701. X */
  1702. X
  1703. X#include    "tin.h"
  1704. X
  1705. Xextern char *glob_art_group;
  1706. Xextern char *glob_group;
  1707. Xextern char *glob_page_group;
  1708. Xextern char index_file[PATH_LEN];
  1709. Xextern int glob_respnum;
  1710. X
  1711. Xstatic int time_remaining;
  1712. X
  1713. X#ifdef SIGTSTP
  1714. Xint do_sigtstp = 0;
  1715. X#endif
  1716. X
  1717. X
  1718. X#ifdef POSIX_JOB_CONTROL
  1719. X
  1720. X/*
  1721. X * for POSIX systems we know SIGTYPE  is void 
  1722. X */
  1723. Xvoid (*sigdisp(sig, func))()
  1724. X    int sig;
  1725. X    void (*func)();
  1726. X{
  1727. X    struct sigaction sa, osa;
  1728. X
  1729. X    sa.sa_handler = func;
  1730. X    sigemptyset (&sa.sa_mask);
  1731. X    sa.sa_flags = 0;
  1732. X#ifdef SA_RESTART
  1733. X    sa.sa_flags |= SA_RESTART;
  1734. X#endif
  1735. X    if (sigaction (sig, &sa, &osa) < 0) {
  1736. X        return ((void (*)(int))(-1));
  1737. X    }
  1738. X    return (osa.sa_handler);
  1739. X}
  1740. X
  1741. X#else
  1742. X
  1743. Xsigtype_t (*sigdisp(sig, func))()
  1744. X    int sig;
  1745. X    sigtype_t (*func)();
  1746. X{
  1747. X    return (signal (sig, func));
  1748. X}
  1749. X
  1750. X#endif
  1751. X
  1752. Xvoid set_signal_handlers ()
  1753. X{
  1754. X    signal (SIGINT, signal_handler);    /* ctrl-C */
  1755. X    signal (SIGQUIT, signal_handler);    /* ctrl-\ */
  1756. X    signal (SIGHUP, signal_handler);    /* hangup */
  1757. X    signal (SIGILL, signal_handler);
  1758. X    signal (SIGBUS, signal_handler);    /* bus error */
  1759. X    signal (SIGSEGV, signal_handler);    /* segmentation violation */
  1760. X    signal (SIGPIPE, SIG_IGN);
  1761. X#ifdef SIGCHLD
  1762. X    signal (SIGCHLD, signal_handler);    /* death of a child process */
  1763. X#endif    
  1764. X#ifdef SIGPWR
  1765. X    signal (SIGPWR, signal_handler);    /* powerfail */
  1766. X#endif    
  1767. X#ifdef SIGWINCH
  1768. X    if (debug == 2) {
  1769. X        wait_message ("SIGWINCH setting signal...");
  1770. X        sleep (2);
  1771. X    }
  1772. X    signal (SIGWINCH, main_resize);
  1773. X#endif
  1774. X
  1775. X#if defined(SIGTSTP) && ! defined(MINIX)
  1776. X    {
  1777. X        sigtype_t (*ptr)();
  1778. X        ptr = signal (SIGTSTP, SIG_DFL);
  1779. X        signal (SIGTSTP, ptr);
  1780. X        if (ptr != SIG_IGN) {
  1781. X            /*
  1782. X             *  SIGTSTP is ignored when starting from shells
  1783. X             *  without job-control
  1784. X             */
  1785. X            do_sigtstp = 1; 
  1786. X            signal (SIGTSTP, main_suspend);
  1787. X        }
  1788. X    }
  1789. X#endif
  1790. X}
  1791. X
  1792. X
  1793. Xvoid set_alarm_signal ()
  1794. X{
  1795. X#ifndef NO_RESYNC_ACTIVE_FILE
  1796. X    /*
  1797. X     * Only reread active file if news is not static (ie. CD-ROM)
  1798. X     */
  1799. X    if (strcmp (spooldir_alias, "news") == 0) {
  1800. X        signal (SIGALRM, signal_handler);
  1801. X        alarm (RESYNC_ACTIVE_SECS);
  1802. X    }    
  1803. X    reread_active_file = FALSE;
  1804. X#endif
  1805. X}
  1806. X
  1807. X
  1808. Xvoid set_alarm_clock_on ()
  1809. X{
  1810. X#ifndef NO_RESYNC_ACTIVE_FILE
  1811. X    alarm (time_remaining);
  1812. X#endif
  1813. X}
  1814. X
  1815. X
  1816. Xvoid set_alarm_clock_off ()
  1817. X{
  1818. X#ifndef NO_RESYNC_ACTIVE_FILE
  1819. X    time_remaining = alarm (0);
  1820. X#endif
  1821. X}
  1822. X
  1823. X
  1824. Xvoid signal_handler (sig)
  1825. X    int sig;
  1826. X{
  1827. X    char *sigtext;
  1828. X#ifdef SIGCHLD            
  1829. X    int wait_status = 1;
  1830. X#endif
  1831. X    
  1832. X    switch (sig) {
  1833. X        case SIGINT:
  1834. X            if (update) {
  1835. X                sigtext = "SIGINT ";
  1836. X            } else {
  1837. X                signal (SIGINT, signal_handler);
  1838. X                return;
  1839. X            }
  1840. X            break;
  1841. X        case SIGQUIT:
  1842. X            sigtext = "SIGQUIT ";
  1843. X            break;
  1844. X        case SIGHUP:
  1845. X            sigtext = "SIGHUP ";
  1846. X            break;
  1847. X#ifdef SIGCHLD            
  1848. X        case SIGCHLD:
  1849. X            wait (&wait_status);
  1850. X#    ifdef WEXITSTATUS            
  1851. X            system_status = WEXITSTATUS(wait_status);
  1852. X#    endif            
  1853. X            return;
  1854. X#endif            
  1855. X#ifdef SIGPWR            
  1856. X        case SIGPWR:
  1857. X            sigtext = "SIGPWR ";
  1858. X            break;
  1859. X#endif            
  1860. X        case SIGBUS:
  1861. X            sigtext = "SIGBUS ";
  1862. X            break;
  1863. X        case SIGSEGV:
  1864. X            sigtext = "SIGSEGV ";
  1865. X            break;
  1866. X#ifndef NO_RESYNC_ACTIVE_FILE
  1867. X        case SIGALRM:
  1868. X            set_alarm_signal ();
  1869. X            reread_active_file = TRUE;
  1870. X            return;
  1871. X#endif
  1872. X        default:
  1873. X            sigtext = "";
  1874. X            break;
  1875. X    }
  1876. X    Raw (FALSE);
  1877. X    EndWin ();
  1878. X    fprintf (stderr, "\n%s: signal handler caught signal %s(%d).\n",
  1879. X        progname, sigtext, sig);
  1880. X    if (sig == SIGBUS || sig == SIGSEGV) {
  1881. X        fprintf (stderr, "%s: send a bug report to %s%s\n",
  1882. X            progname, BUG_REPORT_ADDRESS, add_addr);
  1883. X    }
  1884. X    fflush (stderr);
  1885. X
  1886. X    if (read_news_via_nntp && xindex_supported) {
  1887. X        unlink (index_file);
  1888. X    }
  1889. X
  1890. X#ifdef INDEX_DAEMON
  1891. X    unlink (LOCK_FILE);
  1892. X#endif
  1893. X    exit (1);
  1894. X}
  1895. X
  1896. X
  1897. Xint set_win_size (num_lines, num_cols)
  1898. X    int *num_lines;
  1899. X    int *num_cols;
  1900. X{
  1901. X    int    old_lines;
  1902. X    int    old_cols;
  1903. X#ifdef TIOCGSIZE
  1904. X    struct ttysize win;
  1905. X#else
  1906. X#  ifdef TIOCGWINSZ
  1907. X    struct winsize win;
  1908. X#  endif
  1909. X#endif
  1910. X
  1911. X    old_lines = *num_lines;
  1912. X    old_cols = *num_cols;
  1913. X
  1914. X    init_screen_array (FALSE);        /* deallocate screen array */
  1915. X
  1916. X#ifdef TIOCGSIZE
  1917. X    if (ioctl (0, TIOCGSIZE, &win) == 0) {
  1918. X        if (win.ts_lines != 0) {
  1919. X            *num_lines = win.ts_lines - 1;
  1920. X        }
  1921. X        if (win.ts_cols != 0) {
  1922. X            *num_cols = win.ts_cols;
  1923. X        }
  1924. X    }
  1925. X#else
  1926. X#  ifdef TIOCGWINSZ
  1927. X    if (ioctl (0, TIOCGWINSZ, &win) == 0) {
  1928. X        if (win.ws_row != 0) {
  1929. X            *num_lines = win.ws_row - 1;
  1930. X        }
  1931. X        if (win.ws_col != 0) {
  1932. X            *num_cols = win.ws_col;
  1933. X        }
  1934. X    }
  1935. X#  endif
  1936. X#endif
  1937. X
  1938. X    init_screen_array (TRUE);        /* allocate screen array for resize */
  1939. X
  1940. X    set_subj_from_size (*num_cols);
  1941. X
  1942. X    RIGHT_POS = *num_cols - 20;
  1943. X    MORE_POS  = *num_cols - 15;
  1944. X    NOTESLINES = *num_lines - INDEX_TOP - 1;
  1945. X    if (NOTESLINES <= 0) {
  1946. X        NOTESLINES = 1;
  1947. X    }
  1948. X
  1949. X    if (*num_lines != old_lines || *num_cols != old_cols) {
  1950. X        return TRUE;
  1951. X    } else {    
  1952. X        return FALSE;
  1953. X    }    
  1954. X}
  1955. X
  1956. X
  1957. X
  1958. Xvoid set_signals_art ()
  1959. X{
  1960. X#ifdef SIGTSTP
  1961. X    if (do_sigtstp) {
  1962. X        sigdisp (SIGTSTP, art_suspend);
  1963. X    }
  1964. X#endif
  1965. X
  1966. X#ifdef SIGWINCH
  1967. X    signal (SIGWINCH, art_resize);
  1968. X#endif
  1969. X}
  1970. X
  1971. X
  1972. Xvoid set_signals_group ()
  1973. X{
  1974. X#ifdef SIGTSTP
  1975. X    if (do_sigtstp) {
  1976. X        sigdisp (SIGTSTP, group_suspend);
  1977. X    }
  1978. X#endif
  1979. X
  1980. X#ifdef SIGWINCH
  1981. X    signal (SIGWINCH, group_resize);
  1982. X#endif
  1983. X}
  1984. X
  1985. X
  1986. Xvoid set_signals_page ()
  1987. X{
  1988. X#ifdef SIGTSTP
  1989. X    if (do_sigtstp) {
  1990. X        sigdisp (SIGTSTP, page_suspend);
  1991. X    }
  1992. X#endif
  1993. X
  1994. X#ifdef SIGWINCH
  1995. X    signal (SIGWINCH, page_resize);
  1996. X#endif
  1997. X}
  1998. X
  1999. X
  2000. Xvoid set_signals_select ()
  2001. X{
  2002. X#ifdef SIGTSTP
  2003. X    if (do_sigtstp) {
  2004. X        sigdisp (SIGTSTP, select_suspend);
  2005. X    }
  2006. X#endif
  2007. X
  2008. X#ifdef SIGWINCH
  2009. X    signal (SIGWINCH, select_resize);
  2010. X#endif
  2011. X}
  2012. X
  2013. X
  2014. Xvoid set_signals_spooldir ()
  2015. X{
  2016. X#ifdef SIGTSTP
  2017. X    if (do_sigtstp) {
  2018. X        sigdisp (SIGTSTP, spooldir_suspend);
  2019. X    }
  2020. X#endif
  2021. X
  2022. X#ifdef SIGWINCH
  2023. X    signal (SIGWINCH, spooldir_resize);
  2024. X#endif
  2025. X}
  2026. X
  2027. X
  2028. Xvoid set_signals_thread ()
  2029. X{
  2030. X#ifdef SIGTSTP
  2031. X    if (do_sigtstp) {
  2032. X        sigdisp (SIGTSTP, thread_suspend);
  2033. X    }
  2034. X#endif
  2035. X
  2036. X#ifdef SIGWINCH
  2037. X    signal (SIGWINCH, thread_resize);
  2038. X#endif
  2039. X}
  2040. X
  2041. X
  2042. X#ifdef SIGTSTP
  2043. X
  2044. X/* ARGSUSED0 */
  2045. Xvoid art_suspend (sig)
  2046. X    int sig;
  2047. X{
  2048. X    set_keypad_off ();
  2049. X    Raw (FALSE);
  2050. X    wait_message (txt_suspended_message);
  2051. X
  2052. X    kill (0, SIGSTOP);
  2053. X
  2054. X    sigdisp (SIGTSTP, art_suspend);
  2055. X
  2056. X    if (! update) {
  2057. X        Raw (TRUE);
  2058. X        art_resize (0);        
  2059. X    }
  2060. X    set_keypad_on ();
  2061. X}
  2062. X
  2063. X
  2064. X/* ARGSUSED0 */
  2065. Xvoid main_suspend (sig)
  2066. X    int sig;
  2067. X{
  2068. X    set_keypad_off ();
  2069. X    Raw (FALSE);
  2070. X    wait_message (txt_suspended_message);
  2071. X
  2072. X    kill (0, SIGSTOP);
  2073. X
  2074. X    sigdisp (SIGTSTP, main_suspend);
  2075. X
  2076. X    if (! update) {
  2077. X        Raw (TRUE);
  2078. X        main_resize (0);        
  2079. X    }
  2080. X    set_keypad_on ();
  2081. X}
  2082. X
  2083. X
  2084. X/* ARGSUSED0 */
  2085. Xvoid select_suspend (sig)
  2086. X    int sig;
  2087. X{
  2088. X    set_keypad_off ();
  2089. X    Raw (FALSE);
  2090. X    wait_message (txt_suspended_message);
  2091. X
  2092. X    kill (0, SIGSTOP);
  2093. X
  2094. X    sigdisp (SIGTSTP, select_suspend);
  2095. X
  2096. X    if (! update) {
  2097. X        Raw (TRUE);
  2098. X        select_resize (0);
  2099. X    }
  2100. X    set_keypad_on ();
  2101. X}
  2102. X
  2103. X
  2104. X/* ARGSUSED0 */
  2105. Xvoid spooldir_suspend (sig)
  2106. X    int sig;
  2107. X{
  2108. X    set_keypad_off ();
  2109. X    Raw (FALSE);
  2110. X    wait_message (txt_suspended_message);
  2111. X
  2112. X    kill (0, SIGSTOP);
  2113. X
  2114. X    sigdisp (SIGTSTP, spooldir_suspend);
  2115. X
  2116. X    if (! update) {
  2117. X        Raw (TRUE);
  2118. X        spooldir_resize (0);
  2119. X    }
  2120. X    set_keypad_on ();
  2121. X}
  2122. X
  2123. X
  2124. X/* ARGSUSED0 */
  2125. Xvoid group_suspend (sig)
  2126. X    int sig;
  2127. X{
  2128. X    set_keypad_off ();
  2129. X    Raw (FALSE);
  2130. X    wait_message (txt_suspended_message);
  2131. X
  2132. X    kill (0, SIGSTOP);
  2133. X
  2134. X    sigdisp (SIGTSTP, group_suspend);
  2135. X
  2136. X    if (! update) {
  2137. X        Raw (TRUE);
  2138. X        group_resize (0);        
  2139. X    }
  2140. X    set_keypad_on ();
  2141. X}
  2142. X
  2143. X
  2144. X/* ARGSUSED0 */
  2145. Xvoid page_suspend (sig)
  2146. X    int sig;
  2147. X{
  2148. X    set_keypad_off ();
  2149. X    Raw (FALSE);
  2150. X    wait_message (txt_suspended_message);
  2151. X
  2152. X    kill (0, SIGSTOP);
  2153. X
  2154. X    sigdisp (SIGTSTP, page_suspend);
  2155. X
  2156. X    if (! update) {
  2157. X        Raw (TRUE);
  2158. X        page_resize (0);        
  2159. X    }
  2160. X    set_keypad_on ();
  2161. X}
  2162. X
  2163. X
  2164. X/* ARGSUSED0 */
  2165. Xvoid thread_suspend (sig)
  2166. X    int sig;
  2167. X{
  2168. X    set_keypad_off ();
  2169. X    Raw (FALSE);
  2170. X    wait_message (txt_suspended_message);
  2171. X
  2172. X    kill (0, SIGSTOP);
  2173. X
  2174. X    sigdisp (SIGTSTP, thread_suspend);
  2175. X
  2176. X    if (! update) {
  2177. X        Raw (TRUE);
  2178. X        thread_resize (0);        
  2179. X    }    
  2180. X    set_keypad_on ();
  2181. X}
  2182. X
  2183. X
  2184. X/* ARGSUSED0 */
  2185. Xvoid rcfile_suspend (sig)
  2186. X    int sig;
  2187. X{
  2188. X    set_keypad_off ();
  2189. X    Raw (FALSE);
  2190. X    wait_message (txt_suspended_message);
  2191. X
  2192. X    kill (0, SIGSTOP);
  2193. X
  2194. X    sigdisp (SIGTSTP, rcfile_suspend);
  2195. X
  2196. X    Raw (TRUE);
  2197. X    set_keypad_on ();
  2198. X    show_rcfile_menu ();    
  2199. X}
  2200. X
  2201. X#endif /* SIGTSTP */    
  2202. X
  2203. X
  2204. X/* ARGSUSED0 */
  2205. Xvoid art_resize (sig)
  2206. X    int sig;
  2207. X{
  2208. X    char buf[LEN];
  2209. X
  2210. X#ifdef SIGWINCH
  2211. X    (void) set_win_size (&LINES, &COLS);
  2212. X    signal (SIGWINCH, art_resize);
  2213. X#endif
  2214. X    mail_setup ();
  2215. X    ClearScreen ();
  2216. X    sprintf (buf, txt_group, glob_art_group);
  2217. X    wait_message (buf);
  2218. X}
  2219. X
  2220. X
  2221. X/* ARGSUSED0 */
  2222. Xvoid main_resize (sig)
  2223. X    int sig;
  2224. X{
  2225. X#ifdef SIGWINCH
  2226. X    (void) set_win_size (&LINES, &COLS);
  2227. X    signal (SIGWINCH, main_resize);
  2228. X#endif
  2229. X    mail_setup ();
  2230. X}
  2231. X
  2232. X
  2233. X/* ARGSUSED0 */
  2234. Xvoid select_resize (sig)
  2235. X    int sig;
  2236. X{
  2237. X    int resized = TRUE;
  2238. X    
  2239. X#ifdef SIGWINCH
  2240. X    resized = set_win_size (&LINES, &COLS);
  2241. X    signal (SIGWINCH, select_resize);
  2242. X#endif
  2243. X    
  2244. X#ifndef USE_CLEARSCREEN
  2245. X    ClearScreen ();
  2246. X#endif
  2247. X    mail_setup ();
  2248. X    if (resized) {
  2249. X        group_selection_page ();
  2250. X    }    
  2251. X}
  2252. X
  2253. X
  2254. X/* ARGSUSED0 */
  2255. Xvoid spooldir_resize (sig)
  2256. X    int sig;
  2257. X{
  2258. X    int resized = TRUE;
  2259. X    
  2260. X#ifdef SIGWINCH
  2261. X    resized = set_win_size (&LINES, &COLS);
  2262. X    signal (SIGWINCH, spooldir_resize);
  2263. X#endif
  2264. X    
  2265. X#ifndef USE_CLEARSCREEN
  2266. X    ClearScreen ();
  2267. X#endif
  2268. X    mail_setup ();
  2269. X    if (resized) {
  2270. X        show_spooldir_page ();
  2271. X    }
  2272. X}
  2273. X
  2274. X
  2275. X/* ARGSUSED0 */
  2276. Xvoid group_resize (sig)
  2277. X    int sig;
  2278. X{
  2279. X    int resized = TRUE;
  2280. X    
  2281. X#ifdef SIGWINCH
  2282. X    resized = set_win_size (&LINES, &COLS);
  2283. X    signal (SIGWINCH, group_resize);
  2284. X#endif
  2285. X    
  2286. X#ifndef USE_CLEARSCREEN
  2287. X    ClearScreen ();
  2288. X#endif
  2289. X    mail_setup ();
  2290. X    if (resized) {
  2291. X        show_group_page (glob_group);
  2292. X    }    
  2293. X}
  2294. X
  2295. X
  2296. X/* ARGSUSED0 */
  2297. Xvoid page_resize (sig)
  2298. X    int sig;
  2299. X{
  2300. X    int resized = TRUE;
  2301. X    
  2302. X#ifdef SIGWINCH
  2303. X    resized = set_win_size (&LINES, &COLS);
  2304. X    signal (SIGWINCH, page_resize);
  2305. X#endif
  2306. X    
  2307. X#ifndef USE_CLEARSCREEN
  2308. X    ClearScreen ();
  2309. X#endif
  2310. X    mail_setup ();
  2311. X    if (resized) {
  2312. X        redraw_page (glob_respnum, glob_page_group);
  2313. X    }    
  2314. X}
  2315. X
  2316. X
  2317. X/* ARGSUSED0 */
  2318. Xvoid thread_resize (sig)
  2319. X    int sig;
  2320. X{
  2321. X    int resized = TRUE;
  2322. X    
  2323. X#ifdef SIGWINCH
  2324. X    resized = set_win_size (&LINES, &COLS);
  2325. X    signal (SIGWINCH, thread_resize);
  2326. X#endif
  2327. X    
  2328. X#ifndef USE_CLEARSCREEN
  2329. X    ClearScreen ();
  2330. X#endif
  2331. X    mail_setup ();
  2332. X    if (resized) {
  2333. X        show_thread_page ();
  2334. X    }    
  2335. X}
  2336. END_OF_FILE
  2337.   if test 10115 -ne `wc -c <'signal.c'`; then
  2338.     echo shar: \"'signal.c'\" unpacked with wrong size!
  2339.   fi
  2340.   # end of 'signal.c'
  2341. fi
  2342. echo shar: End of archive 13 \(of 15\).
  2343. cp /dev/null ark13isdone
  2344. MISSING=""
  2345. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ; do
  2346.     if test ! -f ark${I}isdone ; then
  2347.     MISSING="${MISSING} ${I}"
  2348.     fi
  2349. done
  2350. if test "${MISSING}" = "" ; then
  2351.     echo You have unpacked all 15 archives.
  2352.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2353. else
  2354.     echo You still must unpack the following archives:
  2355.     echo "        " ${MISSING}
  2356. fi
  2357. exit 0
  2358. exit 0 # Just in case...
  2359.