home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3961 < prev    next >
Internet Message Format  |  1991-09-03  |  51KB

  1. Path: wupost!uunet!mcsun!unido!estevax!norisc!iain
  2. From: iain@norisc.UUCP (Iain Lea)
  3. Newsgroups: alt.sources
  4. Subject: tin v1.0 Patchlevel 1 Newsreader (part 04/08)
  5. Message-ID: <602@norisc.UUCP>
  6. Date: 3 Sep 91 10:59:24 GMT
  7. Sender: iain@norisc.UUCP (Iain Lea)
  8. Organization: What organization?
  9. Lines: 2351
  10.  
  11. Submitted-by: iain@estevax.uucp
  12. Archive-name: tin1.0/part04
  13.  
  14. #!/bin/sh
  15. # this is tin.shar.04 (part 4 of tin1.0)
  16. # do not concatenate these parts, unpack them in order with /bin/sh
  17. # file main.c continued
  18. #
  19. if touch 2>&1 | fgrep '[-amc]' > /dev/null
  20.  then TOUCH=touch
  21.  else TOUCH=true
  22. fi
  23. if test ! -r shar3_seq_.tmp; then
  24.     echo "Please unpack part 1 first!"
  25.     exit 1
  26. fi
  27. (read Scheck
  28.  if test "$Scheck" != 4; then
  29.     echo "Please unpack part $Scheck next!"
  30.     exit 1
  31.  else
  32.     exit 0
  33.  fi
  34. ) < shar3_seq_.tmp || exit 1
  35. echo "x - Continuing file main.c"
  36. sed 's/^X//' << 'SHAR_EOF' >> main.c &&
  37. Xint start_line_offset;                /* used by invoke_editor for line no. */
  38. Xint read_news_via_nntp = FALSE;        /* read news locally or via NNTP */
  39. Xint max_art;
  40. Xint top = 0;
  41. Xint top_base;
  42. Xint tin_uid;
  43. Xint tin_gid;
  44. Xint real_uid;
  45. Xint real_gid;
  46. Xint local_index;                /* do private indexing? */
  47. X
  48. Xlong *base;
  49. X
  50. Xstruct group_ent *active;            /* active file */
  51. Xstruct header *arts;
  52. X
  53. X
  54. Xvoid main (argc, argv)
  55. X    int argc;    
  56. X    char *argv[];
  57. X{
  58. X    extern int optind, opterr;
  59. X    extern char *optarg;
  60. X    extern char author_search_string[LEN+1];
  61. X    extern char group_search_string[LEN+1];
  62. X    extern char subject_search_string[LEN+1];
  63. X    int c, i;
  64. X    struct stat st;
  65. X    
  66. X    debug = FALSE;
  67. X
  68. X    set_signal_handlers ();
  69. X
  70. X    strcpy (progname, argv[0]);
  71. X
  72. X    nntp_server[0] = '\0';
  73. X    group_search_string[0] = '\0';
  74. X    author_search_string[0] = '\0';
  75. X    subject_search_string[0] = '\0';
  76. X
  77. X    hash_init ();
  78. X    for (i = 0; i < TABLE_SIZE; i++) {
  79. X        group_hash[i] = -1;
  80. X    }
  81. X
  82. X    tin_uid = geteuid ();
  83. X    tin_gid = getegid ();
  84. X    real_uid = getuid ();
  85. X    real_gid = getgid ();
  86. X
  87. X    init_selfinfo ();    /* set up char *'s: homedir, newsrc, etc. */
  88. X    init_alloc ();        /* allocate initial array sizes */
  89. X
  90. X    if (tin_uid == real_uid) {    /* run out of someone's account */
  91. X        local_index = TRUE;        /* index in their home directory */
  92. X    } else {            /* we're setuid, index in /usr/spool/news */
  93. X        local_index = FALSE;
  94. X    }
  95. X
  96. X    while ((c = getopt (argc, argv, "cd:Df:hm:M:p:rS:uv")) != EOF) {
  97. X        switch(c) {
  98. X            case 'c':
  99. X                catchup = TRUE;
  100. X                update = TRUE;
  101. X                break;
  102. X                
  103. X            case 'd':
  104. X                my_strncpy (savedir, optarg, LEN);
  105. X                set_real_uid_gid ();
  106. X                if (stat (savedir, &st) == -1) {
  107. X                    mkdir (savedir, 0755);
  108. X                }
  109. X                set_tin_uid_gid ();
  110. X                break;
  111. X
  112. X            case 'D':        /* debug mode */
  113. X                debug = TRUE;
  114. X                break;
  115. X
  116. X            case 'f':
  117. X                my_strncpy (newsrc, optarg, LEN);
  118. X                break;
  119. X
  120. X            case 'm':
  121. X                my_strncpy (mailer, optarg, LEN);
  122. X                break;
  123. X
  124. X            case 'M':
  125. X                my_strncpy (maildir, optarg, LEN);
  126. X                set_real_uid_gid ();
  127. X                if (stat (maildir, &st) == -1) {
  128. X                    mkdir (maildir, 0755);
  129. X                }
  130. X                set_tin_uid_gid ();
  131. X                break;
  132. X
  133. X            case 'p':
  134. X                my_strncpy (printer, optarg, LEN);
  135. X                default_printer = FALSE;
  136. X                break;
  137. X
  138. X            case 'r':    /* read news remotely from default NNTP server */
  139. X#ifdef USE_NNTP            
  140. X                read_news_via_nntp = TRUE;
  141. X#else
  142. X                printf ("Option not enabled. Recompile %s with -DUSE_NNTP.\n", progname);
  143. X                exit (1);
  144. X#endif
  145. X                break;
  146. X
  147. X            case 'S':
  148. X                my_strncpy (spooldir, optarg, LEN);
  149. X                break;
  150. X
  151. X            case 'u':
  152. X                update = TRUE;
  153. X                break;
  154. X
  155. X            case 'v':
  156. X                verbose = TRUE;
  157. X                update = TRUE;
  158. X                break;
  159. X
  160. X            case 'h':
  161. X            case '?':
  162. X            default:
  163. X                usage (progname);
  164. X                exit (1);
  165. X        }
  166. X    }
  167. X
  168. X    sprintf (page_header, "%s %s PL%d%s", progname, version, PATCHLEVEL, is_remote ());     
  169. X    sprintf (cvers, "%s (c) Copyright 1991 Iain Lea.", page_header);
  170. X
  171. X    if (! update) {
  172. X        printf ("%s\n", cvers);
  173. X        fflush (stdout);
  174. X    }
  175. X
  176. X    nntp_startup ();    /* connect server if we are using nntp */
  177. X    read_active ();        /* load the active file into active[] */
  178. X
  179. X    if (optind < argc) {
  180. X        while (optind < argc) {
  181. X            if (add_group (argv[optind], TRUE) < 0) {
  182. X                fprintf (stderr, txt_not_in_active_file, argv[optind]);
  183. X                fprintf (stderr, "\n");
  184. X            }
  185. X            optind++;
  186. X        }
  187. X    } else {
  188. X        read_newsrc (TRUE);
  189. X    }
  190. X
  191. X    if (kill_articles) {            /* read in users kill file */
  192. X        read_kill_file ();
  193. X    }
  194. X    
  195. X    if (update) {                /* index file updater only */
  196. X        COLS = DEFAULT_COLS;    /* set because curses has not started */ 
  197. X        max_subj = (COLS/2) - 2;
  198. X        max_from = (COLS-max_subj) - 17;
  199. X        do_update ();
  200. X        exit (0);
  201. X    }
  202. X
  203. X    if (InitScreen () == FALSE) {
  204. X        fprintf (stderr,txt_screen_init_failed);
  205. X        exit (1);
  206. X    }
  207. X
  208. X    ScreenSize (&LINES, &COLS);        /* screen size from termcap entry */
  209. X    Raw (TRUE);
  210. X
  211. X    set_win_size (&LINES, &COLS);    /* screen size doing ioctl() call */
  212. X    
  213. X    max_subj = (COLS/2) - 2;
  214. X    max_from = (COLS-max_subj) - 17;
  215. X
  216. X    init_screen_array (TRUE);        /* allocate screen array */
  217. X    
  218. X    mail_setup ();        /* record mailbox size for "you have mail" */
  219. X
  220. X#ifndef USE_CLEARSCREEN
  221. X    ClearScreen();
  222. X#endif
  223. X
  224. X    selection_index ();
  225. X
  226. X    tin_done (0);
  227. X}
  228. X
  229. X/*
  230. X * usage
  231. X */
  232. X
  233. Xvoid usage (progname)
  234. X    char *progname;
  235. X{
  236. X    fprintf(stderr, "%s %s PL%d - threaded usenet newsreader. Copyright 1991 Iain Lea.\n\n", progname, version, PATCHLEVEL);
  237. X    fprintf(stderr, "Usage: %s [options] [newsgroups]\n",progname);
  238. X    fprintf(stderr, "  -c       mark all articles as read in subscribed newsgroups\n");
  239. X    fprintf(stderr, "  -d dir   save articles to directory [default=%s]\n",savedir);
  240. X    fprintf(stderr, "  -f file  subscribed newsgroups file [default=%s/.newsrc]\n", homedir);
  241. X    fprintf(stderr, "  -h       help\n");
  242. X    fprintf(stderr, "  -m file  mail program [default=%s]\n",DEFAULT_MAILER);
  243. X    fprintf(stderr, "  -M dir   mailbox directory [default=%s]\n",maildir);
  244. X    fprintf(stderr, "  -p file  print program with options [default=%s]\n",DEFAULT_PRINTER);
  245. X    fprintf(stderr, "  -r       read news remotely from default NNTP server\n",DEFAULT_PRINTER);
  246. X    fprintf(stderr, "  -S dir   spool directory [default=%s]\n",SPOOLDIR);
  247. X    fprintf(stderr, "  -u       update index files only\n");
  248. X    fprintf(stderr, "  -v       update index files only (verbose)\n");
  249. X}
  250. SHAR_EOF
  251. echo "File main.c is complete" &&
  252. $TOUCH -am 0903095091 main.c &&
  253. chmod 0600 main.c ||
  254. echo "restore of main.c failed"
  255. set `wc -c main.c`;Wc_c=$1
  256. if test "$Wc_c" != "6370"; then
  257.     echo original size 6370, current size $Wc_c
  258. fi
  259. # ============= memory.c ==============
  260. echo "x - extracting memory.c (Text)"
  261. sed 's/^X//' << 'SHAR_EOF' > memory.c &&
  262. X/*
  263. X *  Project   : tin - a visual threaded usenet newsreader
  264. X *  Module    : memory.c
  265. X *  Author    : R.Skrenta / I.Lea
  266. X *  Created   : 01-04-91
  267. X *  Updated   : 22-08-91
  268. X *  Release   : 1.0
  269. X *  Notes     :
  270. X *  Copyright : (c) Copyright 1991 by Rich Skrenta & Iain Lea
  271. X *                You may  freely  copy or  redistribute  this software,
  272. X *              so  long as there is no profit made from its use, sale
  273. X *              trade or  reproduction.  You may not change this copy-
  274. X *              right notice, and it must be included in any copy made
  275. X */
  276. X
  277. X#include    "tin.h"
  278. X
  279. Xint active_num = 0;
  280. Xint article_num = 0;
  281. X
  282. X/*
  283. X *  Dynamic table management
  284. X *  These settings are memory conservative:  small initial allocations
  285. X *  and a 50% expansion on table overflow.  A fast vm system with
  286. X *  much memory might want to start with higher initial allocations
  287. X *  and a 100% expansion on overflow, especially for the arts[] array.
  288. X */
  289. X
  290. Xvoid init_alloc ()
  291. X{
  292. X    if (active_num) {    /* initial alloc */
  293. X        max_active = active_num;
  294. X    } else {
  295. X        max_active = DEFAULT_ACTIVE_NUM;
  296. X    }
  297. X
  298. X    active = (struct group_ent *) my_malloc((unsigned) sizeof(*active) * max_active);
  299. X    my_group = (int *) my_malloc((unsigned) sizeof(int) * max_active);
  300. X    unread = (int *) my_malloc((unsigned) sizeof(int) * max_active);
  301. X
  302. X    if(article_num) {    /* initial alloc */
  303. X        max_art = article_num;
  304. X    } else {
  305. X        max_art = DEFAULT_ARTICLE_NUM;
  306. X    }
  307. X
  308. X    arts = (struct header *) my_malloc((unsigned) sizeof(*arts) * max_art);
  309. X    base = (long *) my_malloc((unsigned) sizeof(long) * max_art);
  310. X
  311. X    max_kill = DEFAULT_KILL_NUM;
  312. X    
  313. X    killf = (struct kill_t *) my_malloc((unsigned) sizeof(*killf) * max_kill);
  314. X
  315. X    max_save = DEFAULT_SAVE_NUM;
  316. X    
  317. X    save = (struct save_t *) my_malloc((unsigned) sizeof(*save) * max_save);
  318. X}
  319. X
  320. X
  321. Xvoid expand_art()
  322. X{
  323. X    max_art += max_art / 2;        /* increase by 50% */
  324. X
  325. X    arts = (struct header *) my_realloc((char *) arts, (unsigned) sizeof(*arts) * max_art);
  326. X    base = (long *) my_realloc((char *) base, (unsigned) sizeof(long) * max_art);
  327. X}
  328. X
  329. X
  330. Xvoid free_art_array ()
  331. X{
  332. X    register int i;
  333. X
  334. X    for (i=0 ; i < top ; i++) {
  335. X        arts[i].artnum = 0L;
  336. X        arts[i].thread = ART_NORMAL;
  337. X        arts[i].inthread = FALSE;
  338. X        arts[i].unread = ART_UNREAD;
  339. X        arts[i].tagged = FALSE;
  340. X        if (arts[i].part) {
  341. X            free (arts[i].part);
  342. X            arts[i].part = (char *) 0;
  343. X        }
  344. X        if (arts[i].patch) {
  345. X            free (arts[i].patch);
  346. X            arts[i].patch = (char *) 0;
  347. X        }
  348. X    }
  349. X}
  350. X
  351. X
  352. Xvoid expand_active()
  353. X{
  354. X    max_active += max_active / 2;        /* increase by 50% */
  355. X
  356. X    active = (struct group_ent *) my_realloc((char *) active,
  357. X                        (unsigned) sizeof(*active) * max_active);
  358. X    my_group = (int *) my_realloc((char *) my_group, (unsigned) sizeof(int) * max_active);
  359. X    unread = (int *) my_realloc((char *) unread, (unsigned) sizeof(int) * max_active);
  360. X}
  361. X
  362. X
  363. Xvoid expand_kill()
  364. X{
  365. X    max_kill += max_kill / 2;        /* increase by 50% */
  366. X
  367. X    killf = (struct kill_t *) my_realloc((char *) killf, (unsigned) sizeof(struct kill_t) * max_kill);
  368. X}
  369. X
  370. X
  371. Xvoid expand_save()
  372. X{
  373. X    max_save += max_save / 2;        /* increase by 50% */
  374. X
  375. X    save = (struct save_t *) my_realloc((char *) save, (unsigned) sizeof(struct save_t) * max_save);
  376. X}
  377. X
  378. X
  379. Xvoid init_screen_array (allocate)
  380. X    int allocate;
  381. X{
  382. X    int i;
  383. X
  384. X    if (allocate) {
  385. X        screen = (struct screen_t *) my_malloc((unsigned) sizeof(*screen) * LINES);
  386. X
  387. X        for (i=0 ; i < LINES ; i++) {
  388. X            screen[i].col = (char *) my_malloc ((unsigned) COLS+1);
  389. X        }
  390. X    } else {
  391. X        for (i=0 ; i < LINES ; i++) {
  392. X            if (screen[i].col) {
  393. X                free (screen[i].col);
  394. X                screen[i].col = (char *) 0;
  395. X            }
  396. X        }
  397. X
  398. X        free (screen);
  399. X    }
  400. X}
  401. X
  402. X
  403. Xvoid free_all_arrays ()
  404. X{
  405. X    register int i;
  406. X
  407. X    hash_reclaim ();
  408. X    
  409. X    init_screen_array (FALSE);
  410. X
  411. X    free_art_array ();
  412. X
  413. X    if (my_group) {
  414. X        free (my_group);
  415. X    }
  416. X
  417. X    if (unread) {
  418. X        free (unread);
  419. X    }
  420. X
  421. X    if (base) {
  422. X        free (base);
  423. X    }
  424. X
  425. X    if (killf) {
  426. X        free_kill_array ();
  427. X        if (killf) {
  428. X            free (killf);
  429. X        }
  430. X    }
  431. X
  432. X    if (save) {
  433. X        free_save_array ();
  434. X        if (save) {
  435. X            free (save);
  436. X        }
  437. X    }
  438. X
  439. X    if (active) { 
  440. X        for (i=0 ; i < max_active ; i++) {
  441. X            if (active[i].name) {
  442. X                free (active[i].name);
  443. X            }
  444. X        }
  445. X        free (active);
  446. X    }
  447. X
  448. X    if (arts) {
  449. X        free (arts);
  450. X    }
  451. X}
  452. X
  453. X
  454. Xvoid free_kill_array ()
  455. X{
  456. X    int i;
  457. X    
  458. X    for (i=0 ; i < kill_num ; i++) {
  459. X        if (killf[i].kill_subj) {
  460. X            free (killf[i].kill_subj);
  461. X            killf[i].kill_subj = (char *) 0;
  462. X        }
  463. X        if (killf[i].kill_from) {
  464. X            free (killf[i].kill_from);
  465. X            killf[i].kill_from = (char *) 0;
  466. X        }
  467. X    }
  468. X}
  469. X
  470. X
  471. X/*
  472. X *  reset save list array to 0 and free's all its allocated memory
  473. X */
  474. Xvoid free_save_array ()
  475. X{
  476. X    int i;
  477. X    
  478. X    for (i=0 ; i < save_num ; i++) {
  479. X        if (save[i].subject) {
  480. X            free (save[i].subject);
  481. X            save[i].subject = (char *) 0;
  482. X        }
  483. X        if (save[i].archive) {
  484. X            free (save[i].archive);
  485. X            save[i].archive = (char *) 0;
  486. X        }
  487. X        if (save[i].dir) {
  488. X            free (save[i].dir);
  489. X            save[i].dir = (char *) 0;
  490. X        }
  491. X        if (save[i].file) {
  492. X            free (save[i].file);
  493. X            save[i].file = (char *) 0;
  494. X        }
  495. X        if (save[i].part) {
  496. X            free (save[i].part);
  497. X            save[i].part = (char *) 0;
  498. X        }
  499. X        if (save[i].patch) {
  500. X            free (save[i].patch);
  501. X            save[i].patch = (char *) 0;
  502. X        }
  503. X        save[i].index   = -1;
  504. X        save[i].saved   = FALSE;
  505. X        save[i].is_mailbox = FALSE;
  506. X    }
  507. X    
  508. X    save_num = 0;
  509. X}
  510. X
  511. Xchar *my_malloc (size)
  512. X    unsigned size;
  513. X{
  514. X    char *p;
  515. X
  516. X    if ((p = (char *) calloc (1, (int) size)) == NULL) {
  517. X        fprintf (stderr, txt_out_of_memory, progname);
  518. X        exit (1);
  519. X    }
  520. X    return p;
  521. X}
  522. X
  523. X
  524. Xchar *my_realloc (p, size)
  525. X    char *p;
  526. X    unsigned size;
  527. X{
  528. X    if (! p) {
  529. X        p = (char *) calloc (1, (int) size);
  530. X    } else {
  531. X        p = (char *) realloc (p, (int) size);
  532. X    }
  533. X
  534. X    if (! p) {
  535. X        fprintf (stderr, txt_out_of_memory, progname);
  536. X        exit (1);
  537. X    }
  538. X    return p;
  539. X}
  540. X
  541. SHAR_EOF
  542. $TOUCH -am 0903095091 memory.c &&
  543. chmod 0600 memory.c ||
  544. echo "restore of memory.c failed"
  545. set `wc -c memory.c`;Wc_c=$1
  546. if test "$Wc_c" != "5489"; then
  547.     echo original size 5489, current size $Wc_c
  548. fi
  549. # ============= misc.c ==============
  550. echo "x - extracting misc.c (Text)"
  551. sed 's/^X//' << 'SHAR_EOF' > misc.c &&
  552. X/*
  553. X *  Project   : tin - a visual threaded usenet newsreader
  554. X *  Module    : misc.c
  555. X *  Author    : R.Skrenta / I.Lea
  556. X *  Created   : 01-04-91
  557. X *  Updated   : 31-08-91
  558. X *  Release   : 1.0
  559. X *  Notes     :
  560. X *  Copyright : (c) Copyright 1991 by Rich Skrenta & Iain Lea
  561. X *                You may  freely  copy or  redistribute  this software,
  562. X *              so  long as there is no profit made from its use, sale
  563. X *              trade or  reproduction.  You may not change this copy-
  564. X *              right notice, and it must be included in any copy made
  565. X */
  566. X
  567. X#include    "tin.h"
  568. X
  569. X
  570. Xchar rcdir[LEN+1];
  571. Xchar rcfile[LEN+1];
  572. Xchar indexdir[LEN+1];
  573. Xchar killfile[LEN+1];
  574. Xchar postfile[LEN+1];
  575. X
  576. Xchar active_file[LEN+1];
  577. Xchar homedir[LEN+1];
  578. Xchar userid[LEN+1];
  579. Xchar delgroups[LEN+1];
  580. Xchar newsrc[LEN+1];
  581. Xchar newnewsrc[LEN+1];
  582. Xchar add_addr[LEN+1];        /* address to add to rR reply to author with mail */
  583. Xchar bug_addr[LEN+1];        /* address to add send bug reports to */
  584. Xchar txt_help_bug_report[LEN+1];    /* address to add send bug reports to */
  585. Xchar reply_to[LEN+1];        /* reply-to address */
  586. Xchar my_org[LEN+1];            /* organization */
  587. Xchar sig[LEN+1];
  588. Xchar signature[LEN+1];
  589. Xchar killsubj[LEN+1];        /* contains Subject:'s not to be shown */
  590. Xchar killfrom[LEN+1];        /* conatins From:'s not to be shown */
  591. Xchar page_header[LEN+1];    /* page header of pgm name and version */
  592. Xchar savedir[LEN+1];        /* directory to save articles to */
  593. Xchar spooldir[LEN+1];        /* directory where new is */
  594. Xchar mailer[LEN+1];            /* mail program */
  595. Xchar maildir[LEN+1];        /* mailbox dir where = saves are stored */
  596. Xchar mailbox[LEN+1];        /* system mailbox for each user */
  597. Xchar printer[LEN+1];        /* printer program */
  598. Xchar dead_article[LEN+1];    /* ~/dead_article file */
  599. Xchar progname[LEN+1];        /* program name */
  600. Xint sort_art_type;            /* sort arts[] array by subject,from or date field */
  601. Xint save_separate;            /* save a each part of a thread to a separate file */
  602. Xint save_archive_name;        /* save thread with name from Archive-name: field */
  603. Xint print_header;            /* print all of mail header or just Subject: & From lines */
  604. Xint show_author;            /* show Subject & From or only Subject in group menu */
  605. Xint draw_arrow_mark;        /* draw -> or highlighted bar */
  606. Xint kill_articles;            /* kill articles matching kill file contents */
  607. Xint post_process;            /* post process (ie. unshar/uudecode) saved article/thread */
  608. Xint mark_saved_read;        /* mark saved article/thread as read */
  609. Xint post_proc_type;            /* type of post processing to be performed */
  610. Xint default_printer;        /* set to false if user give a printer with -p switch */
  611. Xint num_of_tagged_files;
  612. X
  613. X/*
  614. X * init_selfinfo
  615. X *   Deterimines users home directory, userid, and a path
  616. X *   for an rc file in the home directory
  617. X */
  618. X
  619. Xvoid init_selfinfo ()
  620. X{
  621. X    char nam[LEN+1];
  622. X    char *p;
  623. X    extern char *getenv();
  624. X    extern struct passwd *getpwuid();
  625. X    FILE *fp;
  626. X    struct passwd *myentry;
  627. X    struct stat sb;
  628. X
  629. X    myentry = getpwuid (getuid());
  630. X    strcpy (userid, myentry->pw_name);
  631. X
  632. X    if ((p = getenv("HOME")) != NULL) {
  633. X        strcpy (homedir, p);
  634. X    } else {
  635. X        strcpy (homedir, myentry->pw_dir);
  636. X    }
  637. X
  638. X#ifdef USE_INVERSE_HACK
  639. X    draw_arrow_mark = TRUE;
  640. X#else
  641. X    draw_arrow_mark = FALSE;
  642. X#endif
  643. X#ifdef BSD
  644. X    default_printer = TRUE;
  645. X#else    
  646. X    default_printer = FALSE;
  647. X#endif
  648. X    kill_articles = FALSE;
  649. X    mark_saved_read = TRUE;
  650. X    num_of_tagged_files = 0;
  651. X    post_process = FALSE;
  652. X    post_proc_type = POST_PROC_SH;
  653. X    print_header = FALSE;
  654. X    save_separate = TRUE;
  655. X    save_archive_name = TRUE;
  656. X    show_author = TRUE;
  657. X    sort_art_type = SORT_BY_NONE;
  658. X
  659. X    killsubj[0] = '\0';
  660. X    killfrom[0] = '\0';
  661. X    
  662. X    author_search_string[0] = '\0';
  663. X    group_search_string[0] = '\0';
  664. X    subject_search_string[0] = '\0';
  665. X    art_search_string[0] = '\0';
  666. X    default_regex_pattern[0] = '\0';
  667. X    
  668. X    sprintf (rcdir,  "%s/%s", homedir, RCDIR);
  669. X    sprintf (indexdir, "%s/%s", rcdir, INDEXDIR);
  670. X    sprintf (rcfile,   "%s/%s", rcdir, RCFILE);
  671. X    sprintf (killfile, "%s/%s", rcdir, KILLFILE);
  672. X    sprintf (postfile, "%s/%s", rcdir, POSTFILE);
  673. X
  674. X    sprintf (signature, "%s/.signature", homedir);
  675. X    sprintf (sig, "%s/.Sig", homedir);
  676. X    sprintf (newsrc, "%s/.newsrc", homedir);
  677. X    sprintf (newnewsrc, "%s/.newnewsrc", homedir);
  678. X    sprintf (delgroups, "%s/.delgroups", homedir);
  679. X    sprintf (active_file, "%s/active", LIBDIR);
  680. X    sprintf (savedir, "%s/News", homedir);
  681. X    sprintf (maildir, "%s/%s", homedir, DEFAULT_MAILDIR);
  682. X    sprintf (mailbox, "%s/%s", DEFAULT_MAILBOX, userid);
  683. X    sprintf (dead_article, "%s/dead.article", homedir);
  684. X
  685. X    strcpy (mailer, DEFAULT_MAILER);
  686. X    strcpy (printer, DEFAULT_PRINTER);
  687. X    strcpy (spooldir, SPOOLDIR);
  688. X    strcpy (bug_addr, BUG_REPORT_ADDRESS);
  689. X
  690. X    set_real_uid_gid ();
  691. X    
  692. X    if (stat (rcdir, &sb) == -1) {
  693. X        mkdir (rcdir, 0755);
  694. X        if (stat (indexdir, &sb) == -1) {
  695. X            mkdir (indexdir, 0755);
  696. X        }
  697. X    }
  698. X
  699. X    read_rcfile ();
  700. X
  701. X    if (stat (savedir,&sb) == -1) {
  702. X        mkdir (savedir, 0755);
  703. X    }
  704. X    if (stat (maildir,&sb) == -1) {
  705. X        mkdir (maildir, 0755);
  706. X    }
  707. X
  708. X    if (stat (active_file, &sb) >= 0)
  709. X        goto got_active;
  710. X
  711. X/*
  712. X *  I hate forgetting to define LIBDIR correctly.  Guess a
  713. X *  couple of likely places if it's not where LIBDIR says it is.
  714. X */
  715. X
  716. X    strcpy (active_file, "/usr/lib/news/active");
  717. X    if (stat (active_file, &sb) >= 0)
  718. X        goto got_active;
  719. X
  720. X    strcpy (active_file, "/usr/local/lib/news/active");
  721. X    if (stat (active_file, &sb) >= 0)
  722. X        goto got_active;
  723. X
  724. X    strcpy (active_file, "/usr/public/lib/news/active");
  725. X    if (stat (active_file, &sb) >= 0)
  726. X        goto got_active;
  727. X
  728. X/*
  729. X *  Oh well. Revert to what LIBDIR says it is to produce a
  730. X *  useful error message when read_active() fails later.
  731. X */
  732. X
  733. X    sprintf (active_file, "%s/active", LIBDIR);
  734. X
  735. Xgot_active:
  736. X
  737. X/*
  738. X *  check enviroment for organization
  739. X */
  740. X    my_org[0] = '\0';
  741. X    if ((p = getenv ("ORGANIZATION")) != NULL) {
  742. X        my_strncpy (my_org, p, LEN);
  743. X        goto got_org;
  744. X    }
  745. X
  746. X/*
  747. X *  check ~/.org for organization
  748. X */
  749. X    sprintf (nam, "%s/organization", rcdir);
  750. X    fp = fopen (nam, "r");
  751. X
  752. X/*
  753. X *  check LIBDIR/organization for system wide organization
  754. X */
  755. X    if (fp == NULL) {
  756. X        sprintf (nam, "%s/organization", LIBDIR);
  757. X        fp = fopen (nam, "r");
  758. X    }
  759. X
  760. X    if (fp == NULL) {
  761. X        sprintf (nam, "/usr/lib/news/organization");
  762. X        fp = fopen (nam, "r");
  763. X    }
  764. X
  765. X    if (fp == NULL) {
  766. X        sprintf (nam, "/usr/local/lib/news/organization");
  767. X        fp = fopen (nam, "r");
  768. X    }
  769. X
  770. X    if (fp == NULL) {
  771. X        sprintf (nam, "/usr/public/lib/news/organization");
  772. X        fp = fopen (nam, "r");
  773. X    }
  774. X
  775. X    if (fp == NULL) {
  776. X        sprintf (nam, "/etc/organization");
  777. X        fp = fopen (nam, "r");
  778. X    }
  779. X
  780. X    if (fp != NULL) {
  781. X        if (fgets (my_org, LEN, fp) != NULL) {
  782. X            for (p = my_org; *p && *p != '\n'; p++) ;
  783. X            *p = '\0';
  784. X        }
  785. X        fclose (fp);
  786. X    }
  787. X
  788. Xgot_org:;
  789. X
  790. X/*
  791. X *  check enviroment for REPLY_TO
  792. X */
  793. X    reply_to[0] = '\0';
  794. X    if ((p = getenv ("REPLY_TO")) != NULL) {
  795. X        my_strncpy (reply_to, p, LEN);
  796. X        goto got_reply;
  797. X    }
  798. X
  799. X    sprintf (nam, "%s/reply_to", rcdir);
  800. X    if ((fp = fopen (nam, "r")) != NULL) {
  801. X        if (fgets (reply_to, LEN, fp) != NULL) {
  802. X            for (p = reply_to; *p && *p != '\n'; p++) ;
  803. X            *p = '\0';
  804. X        }
  805. X        fclose (fp);
  806. X    }
  807. X
  808. Xgot_reply:;
  809. X
  810. X/*
  811. X *  check enviroment for ADD_ADDRESS
  812. X */
  813. X    add_addr[0] = '\0';
  814. X    if ((p = getenv ("ADD_ADDRESS")) != NULL) {
  815. X        my_strncpy (add_addr, p, LEN);
  816. X        goto got_add_addr;
  817. X    }
  818. X
  819. X    sprintf (nam, "%s/add_addr", rcdir);
  820. X    if ((fp = fopen (nam, "r")) != NULL) {
  821. X        if (fgets (add_addr, LEN, fp) != NULL) {
  822. X            for (p = add_addr; *p && *p != '\n'; p++) ;
  823. X            *p = '\0';
  824. X        }
  825. X        fclose (fp);
  826. X    }
  827. X
  828. Xgot_add_addr:;
  829. X
  830. X/*
  831. X *  check enviroment for BUG_ADDRESS
  832. X */
  833. X    if ((p = getenv ("BUG_ADDRESS")) != NULL) {
  834. X        my_strncpy (bug_addr, p, LEN);
  835. X        goto got_bug_addr;
  836. X    }
  837. X
  838. X    sprintf (nam, "%s/bug_address", rcdir);
  839. X    if ((fp = fopen (nam, "r")) != NULL) {
  840. X        if (fgets (bug_addr, LEN, fp) != NULL) {
  841. X            for (p = bug_addr; *p && *p != '\n'; p++) ;
  842. X            *p = '\0';
  843. X        }
  844. X        fclose (fp);
  845. X    }
  846. X
  847. Xgot_bug_addr:;
  848. X    sprintf (txt_help_bug_report, txt_help_bug, bug_addr);
  849. X
  850. X    set_tin_uid_gid ();
  851. X}
  852. X
  853. X
  854. X/*
  855. X *  Which base note (an index into base[]) does a respnum
  856. X *  (an index into arts[]) corresponsd to?
  857. X *
  858. X *  In other words, base[] points to an entry in arts[] which is
  859. X *  the head of a thread, linked with arts[].thread.  For any q: arts[q],
  860. X *  find i such that base[i]->arts[n]->arts[o]->...->arts[q]
  861. X */
  862. X
  863. Xint which_base (n)
  864. X    int n;
  865. X{
  866. X    register int i, j;
  867. X
  868. X    for (i = 0; i < top_base; i++) {
  869. X        for (j = base[i] ; j >= 0 ; j = arts[j].thread) {
  870. X            if (j == n) {
  871. X                return i;
  872. X            }
  873. X        }
  874. X    }
  875. X
  876. X    error_message (txt_cannot_find_base_art, (char *) atoi (n));
  877. X    return -1;
  878. X}
  879. X
  880. X/*
  881. X *  Find how deep in a thread a response is.  Start counting at zero
  882. X */
  883. X
  884. Xint which_resp (n)
  885. X    int n;
  886. X{
  887. X    int i, j;
  888. X    int num = 0;
  889. X
  890. X    i = which_base (n);
  891. X
  892. X    for (j = base[i]; j != -1; j = arts[j].thread)
  893. X        if (j == n)
  894. X            break;
  895. X        else
  896. X            num++;
  897. X
  898. X    return num;
  899. X}
  900. X
  901. X/*
  902. X *  Given an index into base[], find the number of responses for
  903. X *  that basenote
  904. X */
  905. X
  906. Xint nresp (n)
  907. X    int n;
  908. X{
  909. X    int i;
  910. X    int oldi = -3;
  911. X    int sum = 0;
  912. X
  913. X    assert(n < top_base);
  914. X
  915. X    for (i = base[n]; i != -1; i = arts[i].thread) {
  916. X        assert(i != -2);
  917. X        assert(i != oldi);
  918. X        oldi = i;
  919. X        sum++;
  920. X    }
  921. X
  922. X    return sum - 1;
  923. X}
  924. X
  925. X
  926. Xvoid asfail(file, line, cond)
  927. X    char    *file;
  928. X    int    line;
  929. X    char    *cond;
  930. X{
  931. X    fprintf(stderr, "%s: assertion failure: %s (%d): %s\n",
  932. X                            progname,file, line, cond);
  933. X    exit(1);
  934. X}
  935. X
  936. X
  937. Xvoid copy_fp(a, b, prefix)
  938. X    FILE *a;
  939. X    FILE *b;
  940. X    char *prefix;
  941. X{
  942. X    char buf[8192];
  943. X
  944. X    while (fgets(buf, 8192, a) != NULL)
  945. X        fprintf(b, "%s%s", prefix, buf);
  946. X}
  947. X
  948. X
  949. Xchar *get_val(env, def)
  950. X    char *env;        /* Environment variable we're looking for    */
  951. X    char *def;        /* Default value if no environ value found    */
  952. X{
  953. X    extern char *getenv();
  954. X    char *ptr;
  955. X
  956. X    if ((ptr = getenv(env)) != NULL)
  957. X        return(ptr);
  958. X    else
  959. X        return(def);
  960. X}
  961. X
  962. X
  963. Xint invoke_editor (nam)
  964. X    char *nam;
  965. X{
  966. X    char buf[LEN+1];
  967. X    static char editor[LEN+1];
  968. X    static int first = TRUE;
  969. X
  970. X    if (first) {
  971. X        strcpy (editor, get_val ("EDITOR", DEFAULT_EDITOR));
  972. X        first = FALSE;
  973. X    }
  974. X
  975. X#ifdef DONT_USE_START_LINE
  976. X    sprintf (buf, "%s %s", editor, nam);
  977. X#else
  978. X    sprintf (buf, "%s +%d %s", editor, start_line_offset, nam);
  979. X#endif
  980. X
  981. X    printf ("%s", buf);
  982. X    return invoke_cmd (buf);
  983. X}
  984. X
  985. X
  986. Xvoid shell_escape ()
  987. X{
  988. X    char shell[LEN+1];
  989. X    char *p;
  990. X
  991. X#ifdef SIGTSTP
  992. X    void (*susp)();
  993. X#endif
  994. X
  995. X    if (! parse_string (txt_shell_escape, shell))
  996. X        strcpy (shell, get_val ("SHELL", DEFAULT_SHELL));
  997. X
  998. X    for (p = shell; *p && (*p == ' ' || *p == '\t'); p++) ;
  999. X
  1000. X    if (! *p)
  1001. X        strcpy (shell, get_val ("SHELL", DEFAULT_SHELL));
  1002. X    
  1003. X    Raw (FALSE);
  1004. X
  1005. X    set_real_uid_gid ();
  1006. X
  1007. X    fputs ("\r\n", stdout);
  1008. X
  1009. X#ifdef SIGTSTP
  1010. X    if (do_sigtstp)
  1011. X        susp = signal (SIGTSTP, SIG_DFL);
  1012. X#endif
  1013. X
  1014. X    system (p);
  1015. X
  1016. X#ifdef SIGTSTP
  1017. X    if (do_sigtstp)
  1018. X        signal (SIGTSTP, susp);
  1019. X#endif
  1020. X
  1021. X    set_tin_uid_gid ();
  1022. X
  1023. X    Raw (TRUE);
  1024. X
  1025. X    mail_setup ();
  1026. X
  1027. X    continue_prompt ();
  1028. X
  1029. X    if (draw_arrow_mark) {
  1030. X        ClearScreen ();
  1031. X    }
  1032. X}
  1033. X
  1034. X
  1035. Xvoid tin_done (ret)
  1036. X    int ret;
  1037. X{
  1038. X    free_all_arrays ();        /* deallocate all arrays */
  1039. X    ClearScreen();
  1040. X    Raw(FALSE);
  1041. X    exit(ret);
  1042. X}
  1043. X
  1044. X/*
  1045. X *  Load the active file into active[]
  1046. X */
  1047. X
  1048. Xvoid read_active()
  1049. X{
  1050. X    FILE *fp;
  1051. X    char *p, *q;
  1052. X    char buf[LEN+1];
  1053. X    long h;
  1054. X    int i;
  1055. X
  1056. X    num_active = 0;
  1057. X
  1058. X    if ((fp = open_active_fp ()) == NULL) {
  1059. X        fprintf (stderr, txt_cannot_open, active_file);
  1060. X        fprintf (stderr, "\n");
  1061. X        exit(1);
  1062. X    }
  1063. X
  1064. X    while (fgets(buf, LEN, fp) != NULL) {
  1065. X        for (p = buf; *p && *p != ' '; p++) ;
  1066. X        if (*p != ' ') {
  1067. X            fprintf(stderr, txt_bad_active_file);
  1068. X            continue;
  1069. X        }
  1070. X        *p++ = '\0';
  1071. X
  1072. X        if (num_active >= max_active)
  1073. X            expand_active();
  1074. X
  1075. X        h = hash_groupname (buf);
  1076. X
  1077. X        if (group_hash[h] == -1) {
  1078. X            group_hash[h] = num_active;
  1079. X        } else {                /* hash linked list chaining */
  1080. X            for (i=group_hash[h]; active[i].next >= 0; i=active[i].next) {
  1081. X                if (strcmp(active[i].name, buf) == 0) {
  1082. X                    goto read_active_continue;        /* kill dups */
  1083. X                }
  1084. X            }
  1085. X            if (strcmp(active[i].name, buf) == 0)
  1086. X                goto read_active_continue;
  1087. X            active[i].next = num_active;
  1088. X        }
  1089. X
  1090. X        for (q = p; *q && *q != ' '; q++) ;
  1091. X        if (*q != ' ') {
  1092. X            fprintf(stderr, txt_bad_active_file);
  1093. X            continue;
  1094. X        }
  1095. X
  1096. X        active[num_active].name = str_dup (buf);
  1097. X        active[num_active].max = atol (p);
  1098. X        active[num_active].min = atol (q);
  1099. X        active[num_active].next = -1;        /* hash chaining */
  1100. X        active[num_active].flag = NOTGOT;   /* not in my_group[] yet */
  1101. X
  1102. X        num_active++;
  1103. X
  1104. Xread_active_continue:;
  1105. X
  1106. X    }
  1107. X
  1108. X#ifdef SORT_ACTIVE_FILE        /* DOES NOT WORK - ERROR */
  1109. X    if (num_active) {
  1110. X        qsort (active, num_active, sizeof (struct group_ent), active_comp);
  1111. X    }
  1112. X#endif    
  1113. X
  1114. X    debug_print_active ();
  1115. X
  1116. X    fclose(fp);
  1117. X}
  1118. X
  1119. X
  1120. X#ifdef SORT_ACTIVE_FILE        /* DOES NOT WORK - ERROR */
  1121. Xint active_comp (s1, s2)
  1122. X    struct group_ent *s1;
  1123. X    struct group_ent *s2;
  1124. X{
  1125. X    /* s1->name less than s2->name */
  1126. X    if (strcmp (s1->name, s2->name) < 0) {
  1127. X        return -1;
  1128. X    }
  1129. X    /* s1->name greater than s2->name */
  1130. X    if (strcmp (s1->name, s2->name) > 0) {
  1131. X        return 1;
  1132. X    }
  1133. X    return 0;
  1134. X}
  1135. X#endif
  1136. X
  1137. Xvoid add_signature (fp, flag)
  1138. X    FILE *fp;
  1139. X    int flag;
  1140. X{
  1141. X    FILE *sigf;
  1142. X
  1143. X    if ((sigf = fopen(signature, "r")) != NULL) {
  1144. X        if (flag) {
  1145. X            fprintf(fp, "\n--\n");
  1146. X            copy_fp(sigf, fp, "");
  1147. X        }
  1148. X        fclose(sigf);
  1149. X        return;
  1150. X    }
  1151. X
  1152. X    if ((sigf = fopen(sig, "r")) != NULL) {
  1153. X        fprintf(fp, "\n--\n");
  1154. X        copy_fp(sigf, fp, "");
  1155. X        fclose(sigf);
  1156. X    }
  1157. X}
  1158. X
  1159. X
  1160. X#ifdef USE_MKDIR
  1161. Xmkdir (path, mode)
  1162. X    char *path;
  1163. X    int mode;
  1164. X{
  1165. X    char buf[LEN+1];
  1166. X    struct stat sb;
  1167. X
  1168. X    sprintf(buf, "mkdir %s", path);
  1169. X    if (stat (path, &sb) == -1) {
  1170. X        system(buf);
  1171. X        chmod(path, mode);
  1172. X    }
  1173. X}
  1174. X#endif
  1175. X
  1176. X
  1177. Xlong hash_groupname(buf)        /* hash group name for fast lookup later */
  1178. X    char *buf;
  1179. X{
  1180. X    char *t = buf;
  1181. X    unsigned long h;
  1182. X
  1183. X    h = *t++;
  1184. X    while (*t)
  1185. X        h = ((h << 1) ^ *t++) % TABLE_SIZE;
  1186. X
  1187. X    return h;
  1188. X}
  1189. X
  1190. X
  1191. Xvoid rename_file (old_filename, new_filename)
  1192. X    char *old_filename;
  1193. X    char *new_filename;
  1194. X{    
  1195. X    char buf[LEN];
  1196. X    
  1197. X    if (unlink (new_filename) == -1) {
  1198. X/*
  1199. X        sprintf (buf, txt_rename_error, old_filename, new_filename);
  1200. X        error_message (buf, " ONE");
  1201. X*/        
  1202. X    }
  1203. X    if (link (old_filename, new_filename) == 1) {
  1204. X        sprintf (buf, txt_rename_error, old_filename, new_filename);
  1205. X        error_message (buf, "TWO");
  1206. X        return;
  1207. X    }
  1208. X    if (unlink (old_filename) == -1) {
  1209. X        sprintf (buf, txt_rename_error, old_filename, new_filename);
  1210. X        error_message (buf, "THREE");
  1211. X        return;
  1212. X    }
  1213. X}
  1214. X
  1215. X
  1216. Xchar *str_dup (str)
  1217. X    char *str;
  1218. X{
  1219. X    char *dup = (char *) 0;
  1220. X
  1221. X    assert (str != NULL);
  1222. X    
  1223. X    if (str) {
  1224. X        dup = my_malloc (strlen (str)+1);
  1225. X        strcpy (dup, str);
  1226. X    }
  1227. X    return dup;
  1228. X}
  1229. X
  1230. X
  1231. Xint invoke_cmd(nam)
  1232. X    char *nam;
  1233. X{
  1234. X    int ret;
  1235. X
  1236. X#ifdef SIGTSTP
  1237. X    void (*susp)();
  1238. X#endif
  1239. X
  1240. X    Raw (FALSE);
  1241. X    set_real_uid_gid ();
  1242. X
  1243. X#ifdef SIGTSTP
  1244. X    if (do_sigtstp)
  1245. X        susp = signal(SIGTSTP, SIG_DFL);
  1246. X#endif
  1247. X
  1248. X    ret = system (nam);
  1249. X
  1250. X#ifdef SIGTSTP
  1251. X    if (do_sigtstp)
  1252. X        signal (SIGTSTP, susp);
  1253. X#endif
  1254. X
  1255. X    set_tin_uid_gid ();
  1256. X    Raw (TRUE);
  1257. X
  1258. X    return ret == 0;
  1259. X}
  1260. X
  1261. X
  1262. Xdraw_percent_mark (cur_num, max_num)
  1263. X    int cur_num;
  1264. X    int max_num;
  1265. X{
  1266. X    char buf[32];
  1267. X    int percent = 0;
  1268. X
  1269. X    if (cur_num <= 0 && max_num <= 0) {
  1270. X        return;
  1271. X    }
  1272. X        
  1273. X    percent = cur_num * 100 / max_num;
  1274. X    sprintf (buf, "%s(%d%%) [%d/%d]", txt_more, percent, cur_num, max_num);
  1275. X    MoveCursor (LINES, (COLS - (int) strlen (buf))-(1+BLANK_PAGE_COLS));
  1276. X    StartInverse ();    
  1277. X    printf ("%s", buf);
  1278. X    fflush (stdout);
  1279. X    EndInverse ();
  1280. X}
  1281. X
  1282. X
  1283. Xvoid set_real_uid_gid ()
  1284. X{
  1285. X    setuid (real_uid);
  1286. X    setgid (real_gid);
  1287. X}
  1288. X
  1289. X
  1290. Xvoid set_tin_uid_gid ()
  1291. X{
  1292. X    setuid (tin_uid);
  1293. X    setgid (tin_gid);
  1294. X}
  1295. SHAR_EOF
  1296. $TOUCH -am 0903095091 misc.c &&
  1297. chmod 0600 misc.c ||
  1298. echo "restore of misc.c failed"
  1299. set `wc -c misc.c`;Wc_c=$1
  1300. if test "$Wc_c" != "14791"; then
  1301.     echo original size 14791, current size $Wc_c
  1302. fi
  1303. # ============= newsrc.c ==============
  1304. echo "x - extracting newsrc.c (Text)"
  1305. sed 's/^X//' << 'SHAR_EOF' > newsrc.c &&
  1306. X/*
  1307. X *  Project   : tin - a visual threaded usenet newsreader
  1308. X *  Module    : newsrc.c
  1309. X *  Author    : R.Skrenta / I.Lea
  1310. X *  Created   : 01-04-91
  1311. X *  Updated   : 30-08-91
  1312. X *  Release   : 1.0
  1313. X *  Notes     :
  1314. X *  Copyright : (c) Copyright 1991 by Rich Skrenta & Iain Lea
  1315. X *                You may  freely  copy or  redistribute  this software,
  1316. X *              so  long as there is no profit made from its use, sale
  1317. X *              trade or  reproduction.  You may not change this copy-
  1318. X *              right notice, and it must be included in any copy made
  1319. X */
  1320. X
  1321. X#include    "tin.h"
  1322. X
  1323. X/*
  1324. X *  Read $HOME/.newsrc into my_group[]. my_group[] ints point to
  1325. X *  active[] entries.  Sub_only determines  whether we just read
  1326. X *  subscribed groups or all of them.
  1327. X */
  1328. X
  1329. Xvoid read_newsrc (sub_only)
  1330. X    int sub_only;        /* TRUE=subscribed groups only, FALSE=all groups */
  1331. X{
  1332. X    char c, *p, buf[8192];
  1333. X    char old_groups[LEN];
  1334. X    FILE *fp, *fp_old;
  1335. X    int i;
  1336. X    int remove_old_groups = FALSE;
  1337. X
  1338. X    local_top = 0;
  1339. X
  1340. X    set_real_uid_gid ();
  1341. X    
  1342. X    if ((fp = fopen (newsrc, "r")) == NULL) {  /* attempt to make a .newsrc */
  1343. X        for (i = 0; i < num_active; i++) {
  1344. X            if (local_top >= max_active) {
  1345. X                expand_active ();
  1346. X            }
  1347. X            my_group[local_top] = i;
  1348. X            active[i].flag = 0;
  1349. X            unread[local_top] = -1;
  1350. X            local_top++;
  1351. X        }
  1352. X        write_newsrc ();
  1353. X        return;
  1354. X    }
  1355. X
  1356. X    sprintf (old_groups, "%s/.newsrc.%d", homedir, getpid ());
  1357. X
  1358. X    while (fgets (buf, 8192, fp) != NULL) {
  1359. X        p = buf;
  1360. X        while (*p && *p != '\n' && *p != ' ' && *p != ':' && *p != '!')
  1361. X            p++;
  1362. X        c = *p;
  1363. X        *p++ = '\0';
  1364. X        if (c == '!' && sub_only)
  1365. X            continue;        /* unsubscribed */
  1366. X
  1367. X        if ((i = add_group (buf, FALSE)) < 0) {
  1368. X            if (! remove_old_groups) {
  1369. X                if ((fp_old = fopen (old_groups, "w")) == NULL) {
  1370. X                    error_message (txt_cannot_open, old_groups);
  1371. X                    continue;
  1372. X                }
  1373. X                remove_old_groups = TRUE;
  1374. X            }
  1375. X            fprintf (fp_old, "%s\n", buf);
  1376. X            continue;
  1377. X        }
  1378. X
  1379. X        if (c != '!')        /* if we're subscribed to it */
  1380. X            active[my_group[i]].flag |= SUBS;
  1381. X
  1382. X        unread[i] = parse_unread (p, my_group[i]);
  1383. X    }
  1384. X    fclose (fp);
  1385. X
  1386. X    /*
  1387. X     *  rewrite newsrc to get rid of any non-existant groups 
  1388. X     */
  1389. X    if (remove_old_groups) {
  1390. X        fclose (fp_old);
  1391. X        rewrite_newsrc ();
  1392. X    }
  1393. X
  1394. X    set_tin_uid_gid ();
  1395. X}
  1396. X
  1397. X/*
  1398. X *  Write a new newsrc from my_group[] and active[] mygroup if
  1399. X *  rewriting to get rid of groups that don't exist any longer. Used
  1400. X *  to a create a new .newsrc if there isn't one already, or when
  1401. X *  the newsrc is reset.
  1402. X */
  1403. X
  1404. Xvoid write_newsrc ()
  1405. X{
  1406. X    FILE *fp;
  1407. X    int i;
  1408. X
  1409. X    set_real_uid_gid ();
  1410. X
  1411. X    if ((fp = fopen (newsrc, "w")) == NULL)
  1412. X        goto write_newsrc_done;
  1413. X
  1414. X    for (i=0 ; i < num_active ; i++) {
  1415. X        fprintf (fp, "%s: \n", active[i].name);
  1416. X    }
  1417. X
  1418. X    fclose (fp);
  1419. X
  1420. Xwrite_newsrc_done:
  1421. X    set_tin_uid_gid ();
  1422. X}
  1423. X
  1424. X/*
  1425. X *  Rewrite newsrc to get rid of groups that don't exist any longer.
  1426. X */
  1427. X
  1428. Xvoid rewrite_newsrc ()
  1429. X{
  1430. X    char buf[8192], old[LEN+1];
  1431. X    char old_groups[LEN];
  1432. X    FILE *fp, *fp_old, *fp_new;
  1433. X    int found_old_group, len;    
  1434. X
  1435. X    set_real_uid_gid ();
  1436. X
  1437. X    sprintf (old_groups, "%s/.newsrc.%d", homedir, getpid ());
  1438. X
  1439. X    if ((fp = fopen (newsrc, "r")) == NULL)
  1440. X        goto removed_old_groups_done;
  1441. X
  1442. X    if ((fp_old = fopen (old_groups, "r")) == NULL)
  1443. X        goto removed_old_groups_done;
  1444. X
  1445. X    if ((fp_new = fopen (newnewsrc, "w")) == NULL)
  1446. X        goto removed_old_groups_done;
  1447. X
  1448. X    while (fgets (buf, 8192, fp) != NULL) {            /* read group from newsrc */
  1449. X        rewind (fp_old);
  1450. X        found_old_group = FALSE;    
  1451. X        while (fgets (old, LEN, fp_old) != NULL) {    /* read group from oldgroups */
  1452. X            len = strlen (old)-1;
  1453. X            if ((buf[len] == ':' || buf[len] == '!') &&
  1454. X                strncmp (buf, old, len) == 0) {
  1455. X                old[len] = '\0';
  1456. X                fprintf (stderr, txt_not_in_active_file, old);
  1457. X                fprintf (stderr, ". Deleting.\n");
  1458. X                fflush (stderr);
  1459. X                found_old_group = TRUE;    
  1460. X            }
  1461. X        }
  1462. X        if (! found_old_group) {
  1463. X            fprintf (fp_new, "%s", buf);
  1464. X        }
  1465. X    }
  1466. X    
  1467. X    fclose (fp);
  1468. X    fclose (fp_old);
  1469. X    fclose (fp_new);
  1470. X
  1471. X    rename_file (newnewsrc, newsrc);
  1472. X    unlink (old_groups);
  1473. X
  1474. Xremoved_old_groups_done:
  1475. X    set_tin_uid_gid ();
  1476. X}
  1477. X
  1478. X/*
  1479. X *  Load the sequencer rang lists and mark arts[] according to the
  1480. X *  .newsrc info for a particular group.  i.e.  rec.arts.comics: 1-94,97
  1481. X */
  1482. X
  1483. Xvoid read_newsrc_line (group)
  1484. X    char *group;
  1485. X{
  1486. X    FILE *fp;
  1487. X    char buf[8192];
  1488. X    char *p;
  1489. X
  1490. X    if ((fp = fopen (newsrc, "r")) == NULL)
  1491. X        return;
  1492. X
  1493. X    while (fgets (buf, 8192, fp) != NULL) {
  1494. X        p = buf;
  1495. X        while (*p && *p != '\n' && *p != ' ' && *p != ':' && *p != '!')
  1496. X            p++;
  1497. X        *p++ = '\0';
  1498. X        if (strcmp (buf, group) != 0)
  1499. X            continue;
  1500. X        parse_seq (p);
  1501. X        break;
  1502. X    }
  1503. X
  1504. X    fclose (fp);
  1505. X}
  1506. X
  1507. X/*
  1508. X *  For our current group, update the sequencer information in .newsrc
  1509. X */
  1510. X
  1511. Xvoid update_newsrc (group, groupnum)
  1512. X    char *group;
  1513. X    int groupnum;            /* index into active[] for this group */
  1514. X{
  1515. X    FILE *fp;
  1516. X    FILE *newfp;
  1517. X    char buf[8192];
  1518. X    char *p;
  1519. X    char c;
  1520. X
  1521. X    set_real_uid_gid ();
  1522. X
  1523. X    if ((newfp = fopen (newnewsrc, "w")) == NULL)
  1524. X        goto update_done;
  1525. X
  1526. X    if ((fp = fopen (newsrc, "r")) != NULL) {
  1527. X        while (fgets (buf, 8192, fp) != NULL) {
  1528. X            for (p = buf; *p; p++)
  1529. X                if (*p == '\n') {
  1530. X                    *p = '\0';
  1531. X                    break;
  1532. X                }
  1533. X
  1534. X            p = buf;
  1535. X            while (*p && *p != ' ' && *p != ':' && *p != '!')
  1536. X                    p++;
  1537. X            c = *p;
  1538. X            if (c != '\0')
  1539. X                *p++ = '\0';
  1540. X
  1541. X            if (c != '!')
  1542. X                c = ':';
  1543. X
  1544. X            if (strcmp (buf, group) == 0) {
  1545. X                fprintf (newfp, "%s%c ", buf, c);
  1546. X                print_seq (newfp, groupnum);
  1547. X                fprintf (newfp, "\n");
  1548. X            } else
  1549. X                fprintf (newfp, "%s%c%s\n", buf, c, p);
  1550. X        }
  1551. X        fclose (fp);
  1552. X    }
  1553. X
  1554. X    fclose (newfp);
  1555. X    rename_file (newnewsrc, newsrc);
  1556. X
  1557. Xupdate_done:
  1558. X    set_tin_uid_gid ();
  1559. X}
  1560. X
  1561. X/*
  1562. X *  Subscribe/unsubscribe to a group in .newsrc.  ch should either be
  1563. X *  '!' to unsubscribe or ':' to subscribe.  num is the group's index
  1564. X *  in active[].
  1565. X */
  1566. X
  1567. Xvoid subscribe (group, ch, num, out_seq)
  1568. X    char *group;
  1569. X    char ch;
  1570. X    int num;
  1571. X    int out_seq;                /* output sequencer info? */
  1572. X{
  1573. X    FILE *fp;
  1574. X    FILE *newfp;
  1575. X    char buf[8192];
  1576. X    char *p;
  1577. X    char c;
  1578. X    int gotit = FALSE;
  1579. X
  1580. X    if (ch == '!')
  1581. X        active[num].flag &= ~SUBS;
  1582. X    else
  1583. X        active[num].flag |= SUBS;
  1584. X
  1585. X    set_real_uid_gid ();
  1586. X
  1587. X    if ((newfp = fopen (newnewsrc, "w")) == NULL)
  1588. X        goto subscribe_done;
  1589. X
  1590. X    if ((fp = fopen (newsrc, "r")) != NULL) {
  1591. X        while (fgets (buf, 8192, fp) != NULL) {
  1592. X            for (p = buf; *p; p++)
  1593. X                if (*p == '\n') {
  1594. X                    *p = '\0';
  1595. X                    break;
  1596. X                }
  1597. X
  1598. X            p = buf;
  1599. X            while (*p && *p != ' ' && *p != ':' && *p != '!')
  1600. X                    p++;
  1601. X            c = *p;
  1602. X            if (c != '\0')
  1603. X                *p++ = '\0';
  1604. X
  1605. X            if (c != '!')
  1606. X                c = ':';
  1607. X
  1608. X            if (strcmp (buf, group) == 0) {
  1609. X                fprintf (newfp, "%s%c%s\n", buf, ch, p);
  1610. X                gotit = TRUE;
  1611. X            } else
  1612. X                fprintf (newfp, "%s%c%s\n", buf, c, p);
  1613. X        }
  1614. X        fclose (fp);
  1615. X    }
  1616. X
  1617. X    if (! gotit) {
  1618. X        if (out_seq) {
  1619. X            fprintf (newfp, "%s%c ", group, ch);
  1620. X            print_seq (newfp, num);
  1621. X            fprintf (newfp, "\n");
  1622. X        } else
  1623. X            fprintf (newfp, "%s%c\n", group, ch);
  1624. X    }
  1625. X
  1626. X    fclose (newfp);
  1627. X    rename_file (newnewsrc, newsrc);
  1628. X
  1629. Xsubscribe_done:
  1630. X    set_tin_uid_gid ();
  1631. X}
  1632. X
  1633. X
  1634. Xvoid reset_newsrc ()
  1635. X{
  1636. X    FILE *fp;
  1637. X    FILE *newfp;
  1638. X    char buf[8192];
  1639. X    char *p;
  1640. X    char c;
  1641. X    int i;
  1642. X
  1643. X    set_real_uid_gid ();
  1644. X
  1645. X    if ((newfp = fopen (newnewsrc, "w")) == NULL)
  1646. X        goto update_done;
  1647. X
  1648. X    if ((fp = fopen (newsrc, "r")) != NULL) {
  1649. X        while (fgets (buf, 8192, fp) != NULL) {
  1650. X            for (p = buf; *p && *p != '\n'; p++) ;
  1651. X            *p = '\0';
  1652. X
  1653. X            p = buf;
  1654. X            while (*p && *p != ' ' && *p != ':' && *p != '!')
  1655. X                    p++;
  1656. X            c = *p;
  1657. X            if (c != '\0')
  1658. X                *p++ = '\0';
  1659. X
  1660. X            if (c != '!')
  1661. X                c = ':';
  1662. X
  1663. X            fprintf (newfp, "%s%c\n", buf, c);
  1664. X        }
  1665. X        fclose (fp);
  1666. X    }
  1667. X
  1668. X    fclose (newfp);
  1669. X    rename_file (newnewsrc, newsrc);
  1670. X
  1671. Xupdate_done:
  1672. X    set_tin_uid_gid ();
  1673. X
  1674. X    for (i = 0; i < local_top; i++)
  1675. X        unread[i] = -1;
  1676. X}
  1677. X
  1678. X
  1679. Xvoid delete_group (group)
  1680. X    char *group;
  1681. X{
  1682. X    FILE *fp;
  1683. X    FILE *newfp;
  1684. X    char buf[8192];
  1685. X    char *p;
  1686. X    char c;
  1687. X    int gotit = FALSE;
  1688. X    FILE *del;
  1689. X
  1690. X    set_real_uid_gid ();
  1691. X
  1692. X    if ((newfp = fopen (newnewsrc, "w")) == NULL)
  1693. X        goto del_done;
  1694. X
  1695. X    if ((del = fopen (delgroups, "a+")) == NULL)
  1696. X        goto del_done;
  1697. X
  1698. X    if ((fp = fopen (newsrc, "r")) != NULL) {
  1699. X        while (fgets (buf, 8192, fp) != NULL) {
  1700. X            for (p = buf; *p && *p != '\n'; p++) ;
  1701. X            *p = '\0';
  1702. X
  1703. X            p = buf;
  1704. X            while (*p && *p != ' ' && *p != ':' && *p != '!')
  1705. X                    p++;
  1706. X            c = *p;
  1707. X            if (c != '\0')
  1708. X                *p++ = '\0';
  1709. X
  1710. X            if (c != '!')
  1711. X                c = ':';
  1712. X
  1713. X            if (strcmp (buf, group) == 0) {
  1714. X                fprintf (del, "%s%c%s\n", buf, c, p);
  1715. X                gotit = TRUE;
  1716. X            } else
  1717. X                fprintf (newfp, "%s%c%s\n", buf, c, p);
  1718. X        }
  1719. X        fclose (fp);
  1720. X    }
  1721. X
  1722. X    fclose (newfp);
  1723. X
  1724. X    if (! gotit)
  1725. X        fprintf (del, "%s! \n", group);
  1726. X
  1727. X    fclose (del);
  1728. X    rename_file (newnewsrc, newsrc);
  1729. X
  1730. Xdel_done:
  1731. X    set_tin_uid_gid ();
  1732. X}
  1733. X
  1734. X
  1735. Xint undel_group ()
  1736. X{
  1737. X    FILE *del;
  1738. X    FILE *newfp;
  1739. X    FILE *fp;
  1740. X    char buf[2][8192];
  1741. X    char *p;
  1742. X    int which = 0;
  1743. X    long h;
  1744. X    extern int cur_groupnum;
  1745. X    int i, j;
  1746. X    char c;
  1747. X
  1748. X    set_real_uid_gid ();
  1749. X
  1750. X    if ((del = fopen(delgroups, "r")) == NULL) {
  1751. X        set_tin_uid_gid ();
  1752. X        return FALSE;
  1753. X    }
  1754. X
  1755. X    unlink(delgroups);
  1756. X    
  1757. X    if ((newfp = fopen(delgroups, "w")) == NULL) {
  1758. X        set_tin_uid_gid ();
  1759. X        return FALSE;
  1760. X    }
  1761. X
  1762. X    buf[0][0] = '\0';
  1763. X    buf[1][0] = '\0';
  1764. X
  1765. X    while (fgets(buf[which], 8192, del) != NULL) {
  1766. X        which = !which;
  1767. X        if (*buf[which])
  1768. X            fputs(buf[which], newfp);
  1769. X    }
  1770. X
  1771. X    fclose(del);
  1772. X    fclose(newfp);
  1773. X    which = !which;
  1774. X
  1775. X    if (!*buf[which]) {
  1776. X        set_tin_uid_gid ();
  1777. X        return FALSE;
  1778. X    }
  1779. X
  1780. X    for (p = buf[which]; *p && *p != '\n'; p++) ;
  1781. X    *p = '\0';
  1782. X
  1783. X    p = buf[which];
  1784. X    while (*p && *p != ' ' && *p != ':' && *p != '!')
  1785. X        p++;
  1786. X    c = *p;
  1787. X    if (c != '\0')
  1788. X        *p++ = '\0';
  1789. X
  1790. X    if (c != '!')
  1791. X        c = ':';
  1792. X
  1793. X    {            /* find the hash of the group name */
  1794. X        char *t = buf[which];
  1795. X
  1796. X        h = *t++;
  1797. X        while (*t)
  1798. X            h = (h * 64 + *t++) % TABLE_SIZE;
  1799. X    }
  1800. X
  1801. X    for (i = group_hash[h]; i >= 0; i = active[i].next) {
  1802. X        if (strcmp(buf[which], active[i].name) == 0) {
  1803. X            for (j = 0; j < local_top; j++)
  1804. X                if (my_group[j] == i) {
  1805. X                    set_tin_uid_gid ();
  1806. X                    return j;
  1807. X                }
  1808. X
  1809. X            active[i].flag &= ~NOTGOT;   /* mark that we got it */
  1810. X            if (c != '!')
  1811. X                active[i].flag |= SUBS;
  1812. X
  1813. X            if (local_top >= max_active)
  1814. X                expand_active();
  1815. X            local_top++;
  1816. X            for (j = local_top; j > cur_groupnum; j--) {
  1817. X                my_group[j] = my_group[j-1];
  1818. X                unread[j] = unread[j-1];
  1819. X            }
  1820. X            my_group[cur_groupnum] = i;
  1821. X            unread[cur_groupnum] = parse_unread(p, i);
  1822. X
  1823. X            if ((fp = fopen(newsrc, "r")) == NULL) {
  1824. X                set_tin_uid_gid ();
  1825. X                return FALSE;
  1826. X            }
  1827. X            if ((newfp = fopen(newnewsrc, "w")) == NULL) {
  1828. X                fclose(fp);
  1829. X                set_tin_uid_gid ();
  1830. X                return FALSE;
  1831. X            }
  1832. X            i = 0;
  1833. X            while (fgets(buf[!which], 8192, fp) != NULL) {
  1834. X                for (p = buf[!which]; *p && *p != '\n'; p++) ;
  1835. X                *p = '\0';
  1836. X
  1837. X                p = buf[!which];
  1838. X                while (*p && *p!=' ' && *p != ':' && *p != '!')
  1839. X                    p++;
  1840. X                c = *p;
  1841. X                if (c != '\0')
  1842. X                    *p++ = '\0';
  1843. X
  1844. X                if (c != '!')
  1845. X                    c = ':';
  1846. X
  1847. X                while (i < cur_groupnum) {
  1848. X                    if (strcmp(buf[!which],
  1849. X                      active[my_group[i]].name) == 0) {
  1850. X                        fprintf(newfp, "%s%c%s\n",
  1851. X                            buf[!which], c, p);
  1852. X                        goto foo_cont;
  1853. X                    }
  1854. X                    i++;
  1855. X                }
  1856. X                fprintf(newfp, "%s%c%s\n", buf[which], c, p);
  1857. X                fprintf(newfp, "%s%c%s\n", buf[!which], c, p);
  1858. X                break;
  1859. Xfoo_cont:;
  1860. X            }
  1861. X
  1862. X            while (fgets(buf[!which], 8192, fp) != NULL)
  1863. X                fputs(buf[!which], newfp);
  1864. X
  1865. X            fclose(newfp);
  1866. X            fclose(fp);
  1867. X            rename_file (newnewsrc, newsrc);
  1868. X            set_tin_uid_gid ();
  1869. X            return TRUE;
  1870. X        }
  1871. X    }
  1872. X    set_tin_uid_gid ();
  1873. X
  1874. X    return FALSE;
  1875. X}
  1876. X
  1877. X
  1878. Xvoid mark_group_read (group, groupnum)
  1879. X    char *group;
  1880. X    int groupnum;            /* index into active[] for this group */
  1881. X{
  1882. X    FILE *fp;
  1883. X    FILE *newfp;
  1884. X    char buf[8192];
  1885. X    char *p;
  1886. X    char c;
  1887. X
  1888. X    if (active[groupnum].max < 2)
  1889. X        return;
  1890. X
  1891. X    set_real_uid_gid ();
  1892. X
  1893. X    if ((newfp = fopen (newnewsrc, "w")) == NULL)
  1894. X        goto mark_group_read_done;
  1895. X
  1896. X    if ((fp = fopen (newsrc, "r")) != NULL) {
  1897. X        while (fgets(buf, 8192, fp) != NULL) {
  1898. X            for (p = buf; *p; p++)
  1899. X                if (*p == '\n') {
  1900. X                    *p = '\0';
  1901. X                    break;
  1902. X                }
  1903. X
  1904. X            p = buf;
  1905. X            while (*p && *p != ' ' && *p != ':' && *p != '!')
  1906. X                    p++;
  1907. X            c = *p;
  1908. X            if (c != '\0')
  1909. X                *p++ = '\0';
  1910. X
  1911. X            if (c != '!')
  1912. X                c = ':';
  1913. X
  1914. X            if (strcmp (buf, group) == 0) {
  1915. X                fprintf (newfp, "%s%c 1-%ld\n", buf, c, active[groupnum].max);
  1916. X            } else
  1917. X                fprintf(newfp, "%s%c%s\n", buf, c, p);
  1918. X        }
  1919. X        fclose (fp);
  1920. X    }
  1921. X
  1922. X    fclose (newfp);
  1923. X    rename_file (newnewsrc, newsrc);
  1924. X
  1925. Xmark_group_read_done:
  1926. X    set_tin_uid_gid ();
  1927. X}
  1928. X
  1929. X
  1930. Xvoid parse_seq(s)
  1931. X    char *s;
  1932. X{
  1933. X    long low, high;
  1934. X    int i;
  1935. X
  1936. X    while (*s) {
  1937. X        while (*s && (*s < '0' || *s > '9'))
  1938. X            s++;
  1939. X
  1940. X        if (*s && *s >= '0' && *s <= '9') {
  1941. X            low = atol(s);
  1942. X            while (*s && *s >= '0' && *s <= '9')
  1943. X                s++;
  1944. X            if (*s == '-') {
  1945. X                s++;
  1946. X                high = atol(s);
  1947. X                while (*s && *s >= '0' && *s <= '9')
  1948. X                    s++;
  1949. X            }  else
  1950. X                high = low;
  1951. X
  1952. X            for (i = 0; i < top; i++)
  1953. X                if (arts[i].artnum >= low && arts[i].artnum <= high)
  1954. X                    arts[i].unread = ART_READ;
  1955. X        }
  1956. X    }
  1957. X}
  1958. X
  1959. X
  1960. Xint parse_unread (s, groupnum)
  1961. X    char *s;
  1962. X    int groupnum;            /* index for group in active[] */
  1963. X{
  1964. X    long low, high;
  1965. X    long last_high;
  1966. X    int sum = 0;
  1967. X    int gotone = FALSE;
  1968. X    int n;
  1969. X
  1970. X/*
  1971. X *  Read the first range from the .newsrc sequencer information.  If the
  1972. X *  top of the first range is higher than what the active file claims is
  1973. X *  the bottom, use it as the new bottom instead
  1974. X */
  1975. X
  1976. X    high = 0;
  1977. X    if (*s) {
  1978. X        while (*s && (*s < '0' || *s > '9'))
  1979. X            s++;
  1980. X
  1981. X        if (*s && *s >= '0' && *s <= '9') {
  1982. X            low = atol(s);
  1983. X            while (*s && *s >= '0' && *s <= '9')
  1984. X                s++;
  1985. X            if (*s == '-') {
  1986. X                s++;
  1987. X                high = atol(s);
  1988. X                while (*s && *s >= '0' && *s <= '9')
  1989. X                    s++;
  1990. X            }  else
  1991. X                high = low;
  1992. X            gotone = TRUE;
  1993. X        }
  1994. X    }
  1995. X
  1996. X    if (high < active[groupnum].min)
  1997. X        high = active[groupnum].min;
  1998. X
  1999. X    while (*s) {
  2000. X        last_high = high;
  2001. X
  2002. X        while (*s && (*s < '0' || *s > '9'))
  2003. X            s++;
  2004. X
  2005. X        if (*s && *s >= '0' && *s <= '9') {
  2006. X            low = atol(s);
  2007. X            while (*s && *s >= '0' && *s <= '9')
  2008. X                s++;
  2009. X            if (*s == '-') {
  2010. X                s++;
  2011. X                high = atol(s);
  2012. X                while (*s && *s >= '0' && *s <= '9')
  2013. X                    s++;
  2014. X            }  else
  2015. X                high = low;
  2016. X
  2017. X            if (low > last_high)    /* otherwise seq out of order */
  2018. X                sum += (low - last_high) - 1;
  2019. X        }
  2020. X    }
  2021. X
  2022. X    if (gotone) {
  2023. X        if (active[groupnum].max > high)
  2024. X            sum += active[groupnum].max - high;
  2025. X        return sum;
  2026. X    }
  2027. X
  2028. X    n = (int) (active[groupnum].max - active[groupnum].min);
  2029. X    if (n < 2)
  2030. X        return 0;
  2031. X
  2032. X    return -1;
  2033. X}
  2034. X
  2035. X
  2036. Xint get_line_unread(group, groupnum)
  2037. X    char *group;
  2038. X    int groupnum;                /* index for group in active[] */
  2039. X{
  2040. X    FILE *fp;
  2041. X    char buf[8192];
  2042. X    char *p;
  2043. X    int ret = -1;
  2044. X
  2045. X    if ((fp = fopen(newsrc, "r")) == NULL)
  2046. X        return -1;
  2047. X
  2048. X    while (fgets(buf, 8192, fp) != NULL) {
  2049. X        p = buf;
  2050. X        while (*p && *p != '\n' && *p != ' ' && *p != ':' && *p != '!')
  2051. X            p++;
  2052. X        *p++ = '\0';
  2053. X        
  2054. X        if (strcmp (buf, group) != 0)
  2055. X            continue;
  2056. X            
  2057. X        ret = parse_unread (p, groupnum);
  2058. X        break;
  2059. X    }
  2060. X
  2061. X    fclose (fp);
  2062. X    return ret;
  2063. X}
  2064. X
  2065. X
  2066. Xvoid print_seq (fp, groupnum)
  2067. X    FILE *fp;
  2068. X    int groupnum;            /* index into active[] for this group */
  2069. X{
  2070. X    int i;
  2071. X    int flag = FALSE;
  2072. X
  2073. X    if (top <= 0) {
  2074. X        if (active[groupnum].min > 1) {
  2075. X            fprintf (fp, "1-%ld", active[groupnum].min);
  2076. X            fflush (fp);
  2077. X        }
  2078. X        return;
  2079. X    }
  2080. X
  2081. X    /*
  2082. X     *  sort into the same order as in the spool area for writing
  2083. X     *  read article numbers to ~/.newsrc
  2084. X     */
  2085. X    qsort (arts, top, sizeof (struct header), artnum_comp);
  2086. X
  2087. X    i = 0;
  2088. X    if (arts[0].artnum > 1) {
  2089. X        for (; i < top && !arts[i].unread; i++) ;
  2090. X        if (i > 0)
  2091. X            fprintf (fp, "1-%ld", arts[i-1].artnum);
  2092. X        else
  2093. X            fprintf (fp, "1-%ld", arts[0].artnum - 1);
  2094. X        flag = TRUE;
  2095. X    }
  2096. X
  2097. X    for (; i < top; i++) {
  2098. X        if (! arts[i].unread) {
  2099. X            if (flag)
  2100. X                fprintf(fp, ",");
  2101. X            else
  2102. X                flag = TRUE;
  2103. X            fprintf (fp, "%ld", arts[i].artnum);
  2104. X            if (i+1 < top && !arts[i+1].unread) {
  2105. X                while (i+1 < top && ! arts[i+1].unread)
  2106. X                    i++;
  2107. X                fprintf (fp, "-%ld", arts[i].artnum);
  2108. X            }
  2109. X        }
  2110. X    }
  2111. X
  2112. X    if (! flag && active[groupnum].min > 1)
  2113. X        fprintf (fp, "1-%ld", active[groupnum].min);
  2114. X    fflush (fp);
  2115. X
  2116. X    /*
  2117. X     *  resort into required sort order
  2118. X     */
  2119. X    switch (sort_art_type) {
  2120. X        case SORT_BY_NONE:        /* already sorted above */
  2121. X            break;
  2122. X        case SORT_BY_SUBJ:
  2123. X            qsort (arts, top, sizeof (struct header), subj_comp);
  2124. X            break;
  2125. X        case SORT_BY_FROM:
  2126. X            qsort (arts, top, sizeof (struct header), from_comp);
  2127. X            break;
  2128. X        case SORT_BY_DATE:
  2129. X            qsort (arts, top, sizeof (struct header), date_comp);
  2130. X            break;
  2131. X    }
  2132. X}
  2133. X
  2134. X/*
  2135. X *  rewrite .newsrc and position group at specifed position
  2136. X */
  2137. X
  2138. Xint pos_group_in_newsrc (group, pos)
  2139. X    char *group;
  2140. X    int pos;
  2141. X{
  2142. X    char sub[LEN+1];
  2143. X    char unsub[LEN+1];
  2144. X    char buf[LEN+1], *ptr;
  2145. X    char newsgroup[LEN+1];
  2146. X    extern int cur_groupnum;
  2147. X    FILE *fp_in, *fp_out;
  2148. X    FILE *fp_sub, *fp_unsub;
  2149. X    int repositioned = FALSE;
  2150. X    int subscribed_pos = 1;
  2151. X    int group_len;
  2152. X
  2153. X    if ((fp_in = fopen (newsrc, "r")) == NULL) {
  2154. X        return FALSE;
  2155. X    }
  2156. X    if ((fp_out = fopen (newnewsrc, "w")) == NULL) {
  2157. X        return FALSE;
  2158. X    }
  2159. X
  2160. X    sprintf (sub, "/tmp/.subrc%d", getpid ());
  2161. X    sprintf (unsub, "/tmp/.unsubrc.%d", getpid ());
  2162. X
  2163. X    if ((fp_sub = fopen (sub, "w")) == NULL) {
  2164. X        return FALSE;
  2165. X    }
  2166. X    if ((fp_unsub = fopen (unsub, "w")) == NULL) {
  2167. X        return FALSE;
  2168. X    }
  2169. X
  2170. X    /*
  2171. X     *  split newsrc into subscribed and unsubscribed to files
  2172. X     */
  2173. X    group_len = strlen (group);
  2174. X
  2175. X    while (fgets (buf, LEN, fp_in) != NULL) {
  2176. X        if (strncmp (group, buf, group_len) == 0 && buf[group_len] == ':') {
  2177. X            my_strncpy (newsgroup, buf, LEN);
  2178. X        } else if (ptr = (char *) strchr (buf, ':')) {
  2179. X            fprintf (fp_sub, "%s", buf);
  2180. X        } else {
  2181. X            fprintf (fp_unsub, "%s", buf);
  2182. X        }
  2183. X    }
  2184. X
  2185. X    fclose (fp_in);
  2186. X    fclose (fp_sub);
  2187. X    fclose (fp_unsub);
  2188. X
  2189. X    /*
  2190. X     *  write subscribed groups & position group to newnewsrc
  2191. X     */
  2192. X    if ((fp_sub = fopen (sub, "r")) == NULL) {
  2193. X        unlink (sub);
  2194. X        return FALSE;
  2195. X    }
  2196. X    while (fgets (buf, LEN, fp_sub) != NULL) {
  2197. X        if (pos == subscribed_pos) {
  2198. X            fprintf (fp_out, "%s\n", newsgroup);
  2199. X            repositioned = TRUE;
  2200. X        }
  2201. X        
  2202. X        fprintf (fp_out, "%s", buf);
  2203. X
  2204. X        subscribed_pos++;
  2205. X    }
  2206. X    if (! repositioned) {
  2207. X        fprintf (fp_out, "%s", newsgroup);
  2208. X        repositioned = TRUE;
  2209. X    }
  2210. X    
  2211. X    fclose (fp_sub);
  2212. X     unlink (sub);
  2213. X
  2214. X    /*
  2215. X     *  write unsubscribed groups to newnewsrc
  2216. X     */
  2217. X    if ((fp_unsub = fopen (unsub, "r")) == NULL) {
  2218. X        unlink (unsub);
  2219. X        return FALSE;
  2220. X    }
  2221. X    while (fgets (buf, LEN, fp_unsub) != NULL) {
  2222. X            fprintf (fp_out, "%s", buf);
  2223. X    }
  2224. X
  2225. X    fclose (fp_unsub);
  2226. X    unlink (unsub);
  2227. X    fclose (fp_out);
  2228. X
  2229. X    if (repositioned) {
  2230. X        cur_groupnum = pos;
  2231. X        rename_file (newnewsrc, newsrc);
  2232. X        return TRUE;
  2233. X    } else {
  2234. X        return FALSE;
  2235. X    }
  2236. X}
  2237. SHAR_EOF
  2238. $TOUCH -am 0903095091 newsrc.c &&
  2239. chmod 0600 newsrc.c ||
  2240. echo "restore of newsrc.c failed"
  2241. set `wc -c newsrc.c`;Wc_c=$1
  2242. if test "$Wc_c" != "17686"; then
  2243.     echo original size 17686, current size $Wc_c
  2244. fi
  2245. # ============= nntp.h ==============
  2246. echo "x - extracting nntp.h (Text)"
  2247. sed 's/^X//' << 'SHAR_EOF' > nntp.h &&
  2248. X/*
  2249. X *  Project   : tin - a visual threaded usenet newsreader
  2250. X *  Module    : nntp.h
  2251. X *  Author    : R.Skrenta
  2252. X *  Created   : 01-04-91
  2253. X *  Updated   : 10-08-91
  2254. X *  Release   : 1.0
  2255. X *  Notes     : Changed a bit so nntp knows about Tass
  2256. X *              This file is originally from the nntp 1.5 source.
  2257. X *  Copyright : (c) Copyright 1991 by Rich Skrenta
  2258. X *                You may  freely  copy or  redistribute  this software,
  2259. X *              so  long as there is no profit made from its use, sale
  2260. X *              trade or  reproduction.  You may not change this copy-
  2261. X *              right notice, and it must be included in any copy made
  2262. X */
  2263. X
  2264. X#define    NNTP_SERVER_FILE    "/etc/nntpserver"
  2265. X
  2266. X/*
  2267. X *  External routine declarations
  2268. X */
  2269. X
  2270. Xextern char *getserverbyfile();
  2271. Xextern int server_init();
  2272. Xextern int get_tcp_socket();
  2273. Xextern int handle_server_response();
  2274. Xextern void put_server();
  2275. Xextern int get_server();
  2276. Xextern void close_server();
  2277. X
  2278. X/*
  2279. X *  External file descriptors for the server connection
  2280. X */
  2281. X
  2282. Xextern FILE *ser_wr_fp;
  2283. Xextern FILE *ser_wr_fp;
  2284. X
  2285. X
  2286. X/*
  2287. X * Response codes for NNTP server
  2288. X *
  2289. X * @(#)nntp.h    1.7    (Berkeley) 1/11/88
  2290. X *
  2291. X * First digit:
  2292. X *
  2293. X *    1xx    Informative message
  2294. X *    2xx    Command ok
  2295. X *    3xx    Command ok so far, continue
  2296. X *    4xx    Command was correct, but couldn't be performed
  2297. X *        for some specified reason.
  2298. X *    5xx    Command unimplemented, incorrect, or a
  2299. X *        program error has occured.
  2300. X *
  2301. X * Second digit:
  2302. X *
  2303. X *    x0x    Connection, setup, miscellaneous
  2304. X *    x1x    Newsgroup selection
  2305. X *    x2x    Article selection
  2306. X *    x3x    Distribution
  2307. X *    x4x    Posting
  2308. X */
  2309. X
  2310. X#define    CHAR_INF    '1'
  2311. X#define    CHAR_OK        '2'
  2312. X#define    CHAR_CONT    '3'
  2313. X#define    CHAR_ERR    '4'
  2314. X#define    CHAR_FATAL    '5'
  2315. X
  2316. X#define    INF_HELP    100    /* Help text on way */
  2317. X#define    INF_DEBUG    199    /* Debug output */
  2318. X
  2319. X#define    OK_CANPOST    200    /* Hello; you can post */
  2320. X#define    OK_NOPOST    201    /* Hello; you can't post */
  2321. X#define    OK_SLAVE    202    /* Slave status noted */
  2322. X#define    OK_GOODBYE    205    /* Closing connection */
  2323. X#define    OK_GROUP    211    /* Group selected */
  2324. X#define    OK_GROUPS    215    /* Newsgroups follow */
  2325. X
  2326. X#define OK_TASSINDEX    218    /* Tass index follows */
  2327. X
  2328. X#define    OK_ARTICLE    220    /* Article (head & body) follows */
  2329. X#define    OK_HEAD        221    /* Head follows */
  2330. X#define    OK_BODY        222    /* Body follows */
  2331. X#define    OK_NOTEXT    223    /* No text sent -- stat, next, last */
  2332. X#define    OK_NEWNEWS    230    /* New articles by message-id follow */
  2333. X#define    OK_NEWGROUPS    231    /* New newsgroups follow */
  2334. X#define    OK_XFERED    235    /* Article transferred successfully */
  2335. X#define    OK_POSTED    240    /* Article posted successfully */
  2336. X
  2337. X#define CONT_XFER    335    /* Continue to send article */
  2338. X#define    CONT_POST    340    /* Continue to post article */
  2339. X
  2340. X#define    ERR_GOODBYE    400    /* Have to hang up for some reason */
  2341. X#define    ERR_NOGROUP    411    /* No such newsgroup */
  2342. X#define    ERR_NCING    412    /* Not currently in newsgroup */
  2343. X
  2344. X#define ERR_NOTASS    418    /* No tin index for this group */
  2345. X
  2346. X#define    ERR_NOCRNT    420    /* No current article selected */
  2347. X#define    ERR_NONEXT    421    /* No next article in this group */
  2348. X#define    ERR_NOPREV    422    /* No previous article in this group */
  2349. SHAR_EOF
  2350. echo "End of tin1.0 part 4"
  2351. echo "File nntp.h is continued in part 5"
  2352. echo "5" > shar3_seq_.tmp
  2353. exit 0
  2354.  
  2355.  
  2356. --
  2357. NAME   Iain Lea
  2358. EMAIL  norisc!iain@estevax.UUCP  ...!unido!estevax!norisc!iain
  2359. SNAIL  Siemens AG, AUT 922C, Postfach 4848, Nuernberg, Germany
  2360. PHONE  +49-911-895-3853, +49-911-895-3877, +49-911-331963
  2361.