home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume28 / tin / part07 < prev    next >
Text File  |  1992-02-23  |  52KB  |  2,331 lines

  1. Newsgroups: comp.sources.misc
  2. From: iain%estevax.uucp@unido.Informatik.Uni-Dortmund.DE (Iain Lea)
  3. Subject:  v28i051:  tin - threaded full screen newsreader v1.1, Part07/11
  4. Message-ID: <1992Feb18.043811.13229@sparky.imd.sterling.com>
  5. X-Md4-Signature: 60c986a8347296f9f337b85b58ff1012
  6. Date: Tue, 18 Feb 1992 04:38:11 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: iain%estevax.uucp@unido.Informatik.Uni-Dortmund.DE (Iain Lea)
  10. Posting-number: Volume 28, Issue 51
  11. Archive-name: tin/part07
  12. Environment: BSD, SCO, ISC, SUNOS, SYSVR3, SYSVR4, ULTRIX, XENIX
  13. Supersedes: tin: Volume 23, Issue 15-23
  14.  
  15. #!/bin/sh
  16. # this is tin.shar.07 (part 7 of tin1.1)
  17. # do not concatenate these parts, unpack them in order with /bin/sh
  18. # file newsrc.c continued
  19. #
  20. if test ! -r _shar_seq_.tmp; then
  21.     echo 'Please unpack part 1 first!'
  22.     exit 1
  23. fi
  24. (read Scheck
  25.  if test "$Scheck" != 7; then
  26.     echo Please unpack part "$Scheck" next!
  27.     exit 1
  28.  else
  29.     exit 0
  30.  fi
  31. ) < _shar_seq_.tmp || exit 1
  32. if test ! -f _shar_wnt_.tmp; then
  33.     echo 'x - still skipping newsrc.c'
  34. else
  35. echo 'x - continuing file newsrc.c'
  36. sed 's/^X//' << 'SHAR_EOF' >> 'newsrc.c' &&
  37. X *  the bottom, use it as the new bottom instead
  38. X */
  39. X
  40. X    high = 0;
  41. X    if (*s) {
  42. X        while (*s && (*s < '0' || *s > '9'))
  43. X            s++;
  44. X
  45. X        if (*s && *s >= '0' && *s <= '9') {
  46. X            low = (long) atol (s);
  47. X            while (*s && *s >= '0' && *s <= '9')
  48. X                s++;
  49. X            if (*s == '-') {
  50. X                s++;
  51. X                high = (long) atol (s);
  52. X                while (*s && *s >= '0' && *s <= '9')
  53. X                    s++;
  54. X            }  else
  55. X                high = low;
  56. X            gotone = TRUE;
  57. X        }
  58. X    }
  59. X
  60. X    if (high < active[groupnum].min)
  61. X        high = active[groupnum].min;
  62. X
  63. X    while (*s) {
  64. X        last_high = high;
  65. X
  66. X        while (*s && (*s < '0' || *s > '9'))
  67. X            s++;
  68. X
  69. X        if (*s && *s >= '0' && *s <= '9') {
  70. X            low = (long) atol (s);
  71. X            while (*s && *s >= '0' && *s <= '9')
  72. X                s++;
  73. X            if (*s == '-') {
  74. X                s++;
  75. X                high = (long) atol (s);
  76. X                while (*s && *s >= '0' && *s <= '9')
  77. X                    s++;
  78. X            }  else
  79. X                high = low;
  80. X
  81. X            if (low > last_high)    /* otherwise seq out of order */
  82. X                sum += (low - last_high) - 1;
  83. X        }
  84. X    }
  85. X
  86. X    if (gotone) {
  87. X        if (active[groupnum].max > high)
  88. X            sum += active[groupnum].max - high;
  89. X        return sum;
  90. X    }
  91. X
  92. X    n = (int) (active[groupnum].max - active[groupnum].min);
  93. X    if (n < 2)
  94. X        return 0;
  95. X
  96. X    return -1;
  97. }
  98. X
  99. X
  100. int get_line_unread(group, groupnum)
  101. X    char *group;
  102. X    int groupnum;                /* index for group in active[] */
  103. {
  104. X    FILE *fp;
  105. X    char buf[8192];
  106. X    char *p;
  107. X    int ret = -1;
  108. X
  109. X    if ((fp = fopen(newsrc, "r")) == NULL)
  110. X        return -1;
  111. X
  112. X    while (fgets(buf, sizeof (buf), fp) != NULL) {
  113. X        p = buf;
  114. X        while (*p && *p != '\n' && *p != ' ' && *p != ':' && *p != '!')
  115. X            p++;
  116. X        *p++ = '\0';
  117. X        
  118. X        if (strcmp (buf, group) != 0)
  119. X            continue;
  120. X            
  121. X        ret = parse_unread (p, groupnum);
  122. X        break;
  123. X    }
  124. X
  125. X    fclose (fp);
  126. X    return ret;
  127. }
  128. X
  129. X
  130. void print_seq (fp, groupnum)
  131. X    FILE *fp;
  132. X    int groupnum;            /* index into active[] for this group */
  133. {
  134. X    int i;
  135. X    int flag = FALSE;
  136. X
  137. X    if (top <= 0) {
  138. X        if (active[groupnum].min > 1) {
  139. X            fprintf (fp, "1-%ld", active[groupnum].min);
  140. X            fflush (fp);
  141. X        }
  142. X        return;
  143. X    }
  144. X
  145. X    /*
  146. X     *  sort into the same order as in the spool area for writing
  147. X     *  read article numbers to ~/.newsrc
  148. X     */
  149. X    qsort ((char *) arts, top, sizeof (struct article_t), artnum_comp);
  150. X
  151. X    i = 0;
  152. X    if (arts[0].artnum > 1) {
  153. X        for (; i < top && !arts[i].unread; i++)
  154. X            continue;
  155. X        if (i > 0)
  156. X            fprintf (fp, "1-%ld", arts[i-1].artnum);
  157. X        else
  158. X            fprintf (fp, "1-%ld", arts[0].artnum - 1);
  159. X        flag = TRUE;
  160. X    }
  161. X
  162. X    for (; i < top; i++) {
  163. X        if (! arts[i].unread) {
  164. X            if (flag)
  165. X                fprintf(fp, ",");
  166. X            else
  167. X                flag = TRUE;
  168. X            fprintf (fp, "%ld", arts[i].artnum);
  169. X            if (i+1 < top && !arts[i+1].unread) {
  170. X                while (i+1 < top && ! arts[i+1].unread)
  171. X                    i++;
  172. X                fprintf (fp, "-%ld", arts[i].artnum);
  173. X            }
  174. X        }
  175. X    }
  176. X
  177. X    if (! flag && active[groupnum].min > 1)
  178. X        fprintf (fp, "1-%ld", active[groupnum].min);
  179. X    fflush (fp);
  180. X
  181. X    /*
  182. X     *  resort into required sort order
  183. X     */
  184. X    switch (sort_art_type) {
  185. X        case SORT_BY_NOTHING:        /* already sorted above */
  186. X            break;
  187. X        case SORT_BY_SUBJ_DESCEND:
  188. X        case SORT_BY_SUBJ_ASCEND:
  189. X            qsort ((char *) arts, top, sizeof (struct article_t), subj_comp);
  190. X            break;
  191. X        case SORT_BY_FROM_DESCEND:
  192. X        case SORT_BY_FROM_ASCEND:
  193. X            qsort ((char *) arts, top, sizeof (struct article_t), from_comp);
  194. X            break;
  195. X        case SORT_BY_DATE_DESCEND:
  196. X        case SORT_BY_DATE_ASCEND:
  197. X            qsort ((char *) arts, top, sizeof (struct article_t), date_comp);
  198. X            break;
  199. X    }
  200. }
  201. X
  202. /*
  203. X *  rewrite .newsrc and position group at specifed position
  204. X */
  205. X
  206. int pos_group_in_newsrc (group, pos)
  207. X    char *group;
  208. X    int pos;
  209. {
  210. X    char sub[1024];
  211. X    char unsub[1024];
  212. X    char buf[1024];
  213. X    char newsgroup[1024];
  214. X    extern int cur_groupnum;
  215. X    FILE *fp_in, *fp_out;
  216. X    FILE *fp_sub, *fp_unsub;
  217. X    int repositioned = FALSE;
  218. X    int subscribed_pos = 1;
  219. X    int group_len;
  220. X    int option_line = FALSE;
  221. X    int ret_code = FALSE;
  222. X
  223. X    set_real_uid_gid ();
  224. X    
  225. X    if ((fp_in = fopen (newsrc, "r")) == NULL) {
  226. X        goto rewrite_group_done;
  227. X    }
  228. X    if ((fp_out = fopen (newnewsrc, "w")) == NULL) {
  229. X        goto rewrite_group_done;
  230. X    }
  231. X
  232. X    sprintf (sub, "/tmp/.subrc.%d", getpid ());
  233. X    sprintf (unsub, "/tmp/.unsubrc.%d", getpid ());
  234. X
  235. X    if ((fp_sub = fopen (sub, "w")) == NULL) {
  236. X        goto rewrite_group_done;
  237. X    }
  238. X    if ((fp_unsub = fopen (unsub, "w")) == NULL) {
  239. X        goto rewrite_group_done;
  240. X    }
  241. X
  242. X    /*
  243. X     *  split newsrc into subscribed and unsubscribed to files
  244. X     */
  245. X    group_len = strlen (group);
  246. X
  247. X    while (fgets (buf, sizeof (buf), fp_in) != NULL) {
  248. X        if (strncmp (group, buf, group_len) == 0 && buf[group_len] == ':') {
  249. X            my_strncpy (newsgroup, buf, LEN);
  250. X        } else if (strchr (buf, ':') != NULL) {
  251. X            fprintf (fp_sub, "%s", buf);
  252. X        } else if (strchr (buf, '!') != NULL) {
  253. X            fprintf (fp_unsub, "%s", buf);
  254. X        } else {    /* options line at beginning of .newsrc */
  255. X            fprintf (fp_sub, "%s", buf);
  256. X            option_line = TRUE;
  257. X        }
  258. X    }
  259. X
  260. X    fclose (fp_in);
  261. X    fclose (fp_sub);
  262. X    fclose (fp_unsub);
  263. X
  264. X    /*
  265. X     *  write subscribed groups & position group to newnewsrc
  266. X     */
  267. X    if ((fp_sub = fopen (sub, "r")) == NULL) {
  268. X        unlink (sub);
  269. X        goto rewrite_group_done;
  270. X    }
  271. X    while (fgets (buf, LEN, fp_sub) != NULL) {
  272. X        if (option_line) {
  273. X            if (strchr (buf, ':') == NULL && strchr (buf, '!') == NULL) {
  274. X                fprintf (fp_out, "%s", buf);
  275. X                continue;
  276. X            } else {
  277. X                option_line = FALSE;
  278. X            }
  279. X        }
  280. X
  281. X        if (pos == subscribed_pos) {
  282. X            fprintf (fp_out, "%s\n", newsgroup);
  283. X            repositioned = TRUE;
  284. X        }
  285. X        
  286. X        fprintf (fp_out, "%s", buf);
  287. X
  288. X        subscribed_pos++;
  289. X    }
  290. X    if (! repositioned) {
  291. X        fprintf (fp_out, "%s\n", newsgroup);
  292. X        repositioned = TRUE;
  293. X    }
  294. X    
  295. X    fclose (fp_sub);
  296. X     unlink (sub);
  297. X
  298. X    /*
  299. X     *  write unsubscribed groups to newnewsrc
  300. X     */
  301. X    if ((fp_unsub = fopen (unsub, "r")) == NULL) {
  302. X        unlink (unsub);
  303. X        goto rewrite_group_done;
  304. X    }
  305. X    while (fgets (buf, LEN, fp_unsub) != NULL) {
  306. X        fprintf (fp_out, "%s", buf);
  307. X    }
  308. X
  309. X    fclose (fp_unsub);
  310. X    unlink (unsub);
  311. X    fclose (fp_out);
  312. X
  313. X    if (repositioned) {
  314. X        cur_groupnum = pos;
  315. X        rename_file (newnewsrc, newsrc);
  316. X        ret_code = TRUE;
  317. X    }
  318. X
  319. rewrite_group_done:
  320. X    set_tin_uid_gid ();
  321. X    return ret_code;
  322. }
  323. X
  324. /*
  325. X *  mark all orther Xref: articles as read when one article read
  326. X *  Xref: sitename newsgroup:artnum newsgroup:artnum [newsgroup:artnum ...]
  327. X */
  328. void mark_all_xref_read (xref_line)
  329. X    char *xref_line; 
  330. {
  331. X    char group[LEN];
  332. X    long artnum;
  333. X    
  334. X    if (xref_line == (char *) 0) {
  335. X        return;
  336. X    }
  337. X
  338. X    /*
  339. X     *  check sitename macthes nodename of current machine
  340. X     */
  341. X
  342. X    /*
  343. X     *  tokenize each pair and update that newsgroup if it
  344. X     *  is in users my_group[].
  345. X     */
  346. X     
  347. }
  348. SHAR_EOF
  349. echo 'File newsrc.c is complete' &&
  350. chmod 0600 newsrc.c ||
  351. echo 'restore of newsrc.c failed'
  352. Wc_c="`wc -c < 'newsrc.c'`"
  353. test 19837 -eq "$Wc_c" ||
  354.     echo 'newsrc.c: original size 19837, current size' "$Wc_c"
  355. rm -f _shar_wnt_.tmp
  356. fi
  357. # ============= open.c ==============
  358. if test -f 'open.c' -a X"$1" != X"-c"; then
  359.     echo 'x - skipping open.c (File already exists)'
  360.     rm -f _shar_wnt_.tmp
  361. else
  362. > _shar_wnt_.tmp
  363. echo 'x - extracting open.c (Text)'
  364. sed 's/^X//' << 'SHAR_EOF' > 'open.c' &&
  365. /*
  366. X *  Project   : tin - a threaded Netnews reader
  367. X *  Module    : open.c
  368. X *  Author    : R.Skrenta / I.Lea
  369. X *  Created   : 01-04-91
  370. X *  Updated   : 08-02-92
  371. X *  Notes     : reads news locally (ie. /usr/spool/news) or via NNTP
  372. X *  Copyright : (c) Copyright 1991-92 by Rich Skrenta & Iain Lea
  373. X *                You may  freely  copy or  redistribute  this software,
  374. X *              so  long as there is no profit made from its use, sale
  375. X *              trade or  reproduction.  You may not change this copy-
  376. X *              right notice, and it must be included in any copy made
  377. X */
  378. X
  379. #include    "tin.h"
  380. #ifdef USE_NNTP
  381. #    include    "nntp.h"
  382. #endif
  383. X
  384. /* Hopefully one of these is right for you. */
  385. X
  386. #ifdef BSD
  387. #    ifdef SINIX
  388. #        include <dir.h>
  389. #    else
  390. #        include <sys/dir.h>
  391. #    endif
  392. #    define        DIR_BUF        struct direct
  393. #    define        D_LENGTH    d_namlen
  394. #endif
  395. #ifdef M_XENIX
  396. #    include <sys/ndir.h>
  397. #    define        DIR_BUF        struct direct
  398. #    define        D_LENGTH    d_namlen
  399. #endif
  400. #ifndef DIR_BUF
  401. #    ifdef sorix960
  402. #        include    <sys/dirent.h>
  403. #    else
  404. #        include    <dirent.h>
  405. #    endif
  406. #    define        DIR_BUF        struct dirent
  407. #    define        D_LENGTH    d_reclen
  408. #endif
  409. X
  410. #ifdef USE_NNTP
  411. int compiled_with_nntp = TRUE;        /* used in mail_bug_report() info */
  412. #else
  413. int compiled_with_nntp = FALSE;
  414. #endif
  415. X
  416. #ifdef NO_POSTING
  417. int    can_post = FALSE;
  418. #else
  419. int    can_post = TRUE;
  420. #endif
  421. X
  422. char server_name[LEN];
  423. X
  424. X
  425. char *is_remote ()
  426. {
  427. X    server_name[0] = '\0';
  428. X    
  429. #ifdef USE_NNTP
  430. X    if (read_news_via_nntp) {
  431. X        if (nntp_server[0]) {
  432. X            sprintf (server_name, " (%s)", nntp_server);
  433. X        } else {
  434. X            if (getserverbyfile (NNTP_SERVER_FILE)) {
  435. X                sprintf (server_name, " (%s)", getserverbyfile (NNTP_SERVER_FILE));
  436. X            } else {
  437. X                strcpy (server_name, " (NO SERVER)");
  438. X            }
  439. X        }
  440. X    }
  441. #endif
  442. X
  443. X    return (server_name);
  444. }
  445. X
  446. X
  447. void nntp_startup ()
  448. {
  449. #ifdef USE_NNTP    
  450. X    char *server;
  451. X    int ret;
  452. X    extern char *getenv();
  453. X
  454. X    if (read_news_via_nntp) {
  455. X        if (nntp_server[0]) {
  456. X            server = nntp_server;
  457. X        } else {
  458. X            server = getserverbyfile (NNTP_SERVER_FILE);
  459. X        }
  460. X        if (server == (char *) 0) {
  461. X            fprintf (stderr, txt_cannot_get_nntp_server_name);
  462. X            fprintf (stderr, txt_server_name_in_file_env_var, NNTP_SERVER_FILE);
  463. X            exit(1);
  464. X        }
  465. X
  466. X        if (update == FALSE) {
  467. X            printf (txt_connecting, server);
  468. X            fflush (stdout);
  469. X        }
  470. X        
  471. X        ret = server_init (server);
  472. X        if (update == FALSE) {
  473. X            putchar ('\n');
  474. X        }
  475. /*
  476. X        handle_server_response (ret, server);
  477. */        
  478. X        switch (ret) {
  479. X        case OK_CANPOST:
  480. #ifndef NO_POSTING        
  481. X            can_post = TRUE;
  482. #endif            
  483. X            break;
  484. X
  485. X        case OK_NOPOST:
  486. X            can_post = FALSE;
  487. X            break;    
  488. X
  489. X        case -1:
  490. X            fprintf (stderr, txt_failed_to_connect_to_server, server);
  491. X            exit (1);
  492. X
  493. X        default:
  494. X            fprintf (stderr, txt_rejected_by_nntpserver, ret);
  495. X            exit (1);
  496. X        }
  497. X    }
  498. #endif    
  499. }
  500. X
  501. X
  502. void nntp_finish ()
  503. {
  504. #ifdef USE_NNTP
  505. X    if (read_news_via_nntp) {
  506. X        close_server ();
  507. X    }
  508. #endif    
  509. }
  510. X
  511. X
  512. FILE *open_active_fp ()
  513. {
  514. X    if (read_news_via_nntp) {
  515. #ifdef USE_NNTP
  516. X        put_server ("list");
  517. X        if (get_respcode () != OK_GROUPS) {
  518. X            return NULL;
  519. X        }
  520. X        return nntp_to_fp ();
  521. #else
  522. X        return NULL;
  523. #endif        
  524. X    } else {
  525. X        return fopen (active_file, "r");
  526. X    }
  527. }
  528. X
  529. X
  530. FILE *open_art_fp (group_path, art)
  531. X    char *group_path;
  532. X    long art;
  533. {
  534. X    char buf[LEN];
  535. X    int respcode;
  536. X    struct stat sb;
  537. X    extern long note_size;
  538. X
  539. X    if (read_news_via_nntp) {
  540. #ifdef USE_NNTP
  541. X        sprintf (buf, "article %ld", art);
  542. X
  543. X        put_server (buf);
  544. X        if ((respcode = get_respcode ()) != OK_ARTICLE) {
  545. X            sprintf (msg, "Cannot open art on NNTP server. Respcode %d", respcode);
  546. X            error_message (msg);
  547. X            return (FILE *) 0;
  548. X        }
  549. X
  550. X        return nntp_to_fp ();
  551. #else
  552. X        return (FILE *) 0;
  553. #endif
  554. X    } else {
  555. X        sprintf (buf, "%s/%s/%ld", SPOOLDIR, group_path, art);
  556. X
  557. X        if (stat (buf, &sb) < 0) {
  558. X            note_size = 0;
  559. X        } else {
  560. X            note_size = sb.st_size;
  561. X        }
  562. X        return fopen (buf, "r");
  563. X    }
  564. }
  565. X
  566. X
  567. int open_header_fd (group_path, art)
  568. X    char *group_path;
  569. X    long art;
  570. {
  571. X    char buf[LEN];
  572. X
  573. X    if (read_news_via_nntp) {
  574. #ifdef USE_NNTP    
  575. X        sprintf(buf, "head %ld", art);
  576. X        
  577. X        put_server (buf);
  578. X        if (get_respcode () != OK_HEAD) {
  579. X            return -1;
  580. X        }
  581. X
  582. X        return nntp_to_fd ();
  583. #else
  584. X        return -1;
  585. #endif        
  586. X    } else {
  587. X        sprintf (buf, "%s/%s/%ld", SPOOLDIR, group_path, art);
  588. X        return open (buf, 0);
  589. X    }
  590. }
  591. X
  592. /*
  593. X *  Longword comparison routine for the qsort()
  594. X */
  595. X
  596. int base_comp (p1, p2)
  597. X    char *p1;
  598. X    char *p2;
  599. {
  600. X    long *a = (long *) p1;
  601. X    long *b = (long *) p2;
  602. X
  603. X    if (*a < *b)
  604. X        return -1;
  605. X    if (*a > *b)
  606. X        return 1;
  607. X    return 0;
  608. }
  609. X
  610. X
  611. /*
  612. X *  Read the article numbers existing in a group's spool directory
  613. X *  into base[] and sort them.  top_base is one past top.
  614. X */
  615. X
  616. void setup_base (group, group_path)
  617. X    char *group;
  618. X    char *group_path;
  619. {
  620. X    char buf[LEN];
  621. #ifdef USE_NNTP
  622. X    char line[NNTP_STRLEN];
  623. #endif
  624. X    DIR *d;
  625. X    DIR_BUF *e;
  626. X    long art, start, last, dummy, count;
  627. X
  628. X    top_base = 0;
  629. X
  630. X    if (read_news_via_nntp) {
  631. #ifdef USE_NNTP
  632. X        sprintf (buf, "group %s", group);
  633. X        put_server (buf);
  634. X
  635. X        if (get_server (line, NNTP_STRLEN) == -1) {
  636. X            fprintf (stderr, txt_connection_to_server_broken);
  637. X            tin_done (1);
  638. X        }
  639. X
  640. X        if (atoi(line) != OK_GROUP) {
  641. X            return;
  642. X        }
  643. X
  644. X        sscanf (line,"%ld %ld %ld %ld", &dummy, &count, &start, &last);
  645. X        if (last - count > start) {
  646. X            start = last - count;
  647. X        }
  648. X
  649. X        while (start <= last) {
  650. X            if (top_base >= max_art) {
  651. X                expand_art();
  652. X            }
  653. X            base[top_base++] = start++;
  654. X        }
  655. #else
  656. X        return; 
  657. #endif
  658. X    } else {
  659. X        sprintf (buf, "%s/%s", SPOOLDIR, group_path);
  660. X
  661. X        if (access (buf, 4) != 0) {
  662. X            return;
  663. X        }
  664. X
  665. X        d = opendir (buf);
  666. X        if (d != NULL) {
  667. X            while ((e = readdir (d)) != NULL) {
  668. X                art = my_atol (e->d_name, (int) e->D_LENGTH);
  669. X                if (art >= 0) {
  670. X                    if (top_base >= max_art)
  671. X                        expand_art ();
  672. X                    base[top_base++] = art;
  673. X                }
  674. X            }
  675. X            closedir (d);
  676. X            qsort ((char *) base, top_base, sizeof (long), base_comp);
  677. X        }
  678. X    }
  679. }
  680. X
  681. /*
  682. X *  get_respcode
  683. X *  get a response code from the server and return it to the caller
  684. X */
  685. X
  686. int get_respcode ()
  687. {
  688. #ifdef USE_NNTP
  689. X    char line[NNTP_STRLEN];
  690. X
  691. X    if (get_server (line, NNTP_STRLEN) == -1) {
  692. X        fprintf (stderr, txt_connection_to_server_broken);
  693. X        tin_done (1);
  694. X    }
  695. X
  696. X    return atoi (line);
  697. #endif
  698. }
  699. X
  700. X
  701. int stuff_nntp (fnam)
  702. X    char *fnam;
  703. {
  704. #ifdef USE_NNTP
  705. X    FILE *fp;
  706. X    char line[NNTP_STRLEN];
  707. X    extern char *mktemp();
  708. X    struct stat sb;
  709. X    extern long note_size;
  710. X
  711. X    strcpy(fnam, "/tmp/tin_nntpXXXXXX");
  712. X    mktemp(fnam);
  713. X
  714. X    if ((fp = fopen(fnam, "w")) == NULL) {
  715. X        error_message (txt_stuff_nntp_cannot_open, fnam);
  716. X        return FALSE;
  717. X    }
  718. X
  719. X    while (1) {
  720. X        if (get_server(line, NNTP_STRLEN) == -1) {
  721. X            fprintf(stderr, txt_connection_to_server_broken);
  722. X            tin_done (1);
  723. X        }
  724. X        if (strcmp(line, ".") == 0)
  725. X            break;            /* end of text */
  726. X        strcat(line, "\n");
  727. X        if (line[0] == '.')        /* reduce leading .'s */
  728. X            fputs(&line[1], fp);
  729. X        else
  730. X            fputs(line, fp);
  731. X    }
  732. X    fclose(fp);
  733. X
  734. X    if (stat(fnam, &sb) < 0)
  735. X        note_size = 0;
  736. X    else
  737. X        note_size = sb.st_size;
  738. X
  739. X    return TRUE;
  740. #else
  741. X    return TRUE;
  742. #endif
  743. }
  744. X
  745. X
  746. FILE *nntp_to_fp ()
  747. {
  748. #ifdef USE_NNTP
  749. X    char fnam[LEN];
  750. X    static FILE *fp = NULL;
  751. X
  752. X    if (fp != NULL) {
  753. X        fclose (fp);
  754. X    }
  755. X    
  756. X    if (! stuff_nntp (fnam)) {
  757. X        return NULL;
  758. X    }
  759. X
  760. X    if ((fp = fopen (fnam, "r")) == NULL) {
  761. X        error_message (txt_nntp_to_fp_cannot_reopen, fnam);
  762. X        return NULL;
  763. X    }
  764. X    
  765. X    unlink (fnam);
  766. X    return fp;
  767. #else
  768. X    return NULL;
  769. #endif
  770. }
  771. X
  772. X
  773. int nntp_to_fd ()
  774. {
  775. #ifdef USE_NNTP
  776. X    char fnam[LEN];
  777. X    static int fd = -1;
  778. X
  779. X    if (fd != -1) {
  780. X        close (fd);
  781. X    }
  782. X    
  783. X    if (! stuff_nntp (fnam)) {
  784. X        return -1;
  785. X    }
  786. X
  787. X    if ((fd = open (fnam, 0)) == -1) {
  788. X        error_message (txt_nntp_to_fd_cannot_reopen, fnam);
  789. X        return -1;
  790. X    }
  791. X    
  792. X    unlink (fnam);
  793. X    return fd;
  794. #else
  795. X    return -1;
  796. #endif
  797. }
  798. SHAR_EOF
  799. chmod 0600 open.c ||
  800. echo 'restore of open.c failed'
  801. Wc_c="`wc -c < 'open.c'`"
  802. test 7366 -eq "$Wc_c" ||
  803.     echo 'open.c: original size 7366, current size' "$Wc_c"
  804. rm -f _shar_wnt_.tmp
  805. fi
  806. # ============= page.c ==============
  807. if test -f 'page.c' -a X"$1" != X"-c"; then
  808.     echo 'x - skipping page.c (File already exists)'
  809.     rm -f _shar_wnt_.tmp
  810. else
  811. > _shar_wnt_.tmp
  812. echo 'x - extracting page.c (Text)'
  813. sed 's/^X//' << 'SHAR_EOF' > 'page.c' &&
  814. /*
  815. X *  Project   : tin - a threaded Netnews reader
  816. X *  Module    : page.c
  817. X *  Author    : R.Skrenta / I.Lea
  818. X *  Created   : 01-04-91
  819. X *  Updated   : 30-01-92
  820. X *  Notes     :
  821. X *  Copyright : (c) Copyright 1991-92 by Rich Skrenta & Iain Lea
  822. X *                You may  freely  copy or  redistribute  this software,
  823. X *              so  long as there is no profit made from its use, sale
  824. X *              trade or  reproduction.  You may not change this copy-
  825. X *              right notice, and it must be included in any copy made
  826. X */
  827. X
  828. #include    "tin.h"
  829. X
  830. #define        ART_UNAVAILABLE    -1
  831. X
  832. extern int cur_groupnum;
  833. X
  834. char note_h_path[LEN];            /* Path:    */
  835. char note_h_date[LEN];            /* Date:    */
  836. char note_h_subj[LEN];            /* Subject:    */
  837. char note_h_org[LEN];            /* Organization: */
  838. char note_h_newsgroups[LEN];    /* Newsgroups:    */
  839. char note_h_messageid[LEN];        /* Message-ID:    */
  840. char note_h_distrib[LEN];        /* Distribution: */
  841. char note_h_followup[LEN];        /* Followup-To: */
  842. X
  843. char *glob_page_group;
  844. X
  845. FILE *note_fp;                    /* the body of the current article */
  846. X
  847. int glob_respnum;
  848. int last_resp;                    /* current & previous article for - command */
  849. int    note_end;                    /* we're done showing this article */
  850. int    note_line;
  851. int    note_page;                    /* what page we're on */
  852. int    rotate;                        /* 0=normal, 13=rot13 decode */
  853. int this_resp;
  854. X
  855. long note_mark[MAX_PAGES];        /* ftells on beginnings of pages */
  856. long note_size;                    /* stat size in bytes of article */
  857. X
  858. X
  859. int show_page (respnum, group, group_path)
  860. X    int respnum;
  861. X    char *group;
  862. X    char *group_path;
  863. {
  864. X    char ch;
  865. X    int i, n;
  866. X    int kill_state = NO_KILLING;
  867. X    int old_sort_art_type = sort_art_type;
  868. X    int old_top;
  869. X    int posted;
  870. X    int ret_code;
  871. X    long old_artnum;
  872. X    long art;
  873. X
  874. restart:
  875. X
  876. X    glob_respnum = respnum;
  877. X    glob_page_group = group;
  878. X
  879. X    set_signals_page ();
  880. X    
  881. X    if (respnum != this_resp) {       /* remember current & previous */
  882. X        last_resp = this_resp;       /* articles for - command */
  883. X        this_resp = respnum;
  884. X    }
  885. X
  886. X    rotate = 0;            /* normal mode, not rot13 */
  887. X    art = arts[respnum].artnum;
  888. X    arts[respnum].unread = ART_READ;    /* mark article as read */
  889. X    art_open (art, group_path);
  890. X
  891. X    if (note_page == ART_UNAVAILABLE) {
  892. X        ClearScreen ();
  893. X        printf (txt_art_unavailable, art);
  894. X        fflush (stdout);
  895. X    } else {
  896. X        show_note_page (respnum, group);
  897. X    }
  898. X
  899. X    while (TRUE) {
  900. X        ch = (char) ReadCh();
  901. X
  902. X        if (ch >= '0' && ch <= '9') {
  903. X
  904. X            n = prompt_response (ch, respnum);
  905. X            if (n != -1) {
  906. X                respnum = n;
  907. X                goto restart;
  908. X            }
  909. X
  910. X        } else switch (ch) {
  911. X            case ESC:
  912. X                switch (get_arrow_key ()) {
  913. X                    case KEYMAP_PAGE_UP:
  914. X                        goto page_up;
  915. X
  916. X                    case KEYMAP_PAGE_DOWN:
  917. X                        goto page_down;
  918. X
  919. X                    case KEYMAP_HOME:
  920. X                        goto begin_of_article;
  921. X
  922. X                    case KEYMAP_END:
  923. X                        goto end_of_article;
  924. X                }
  925. X                break;
  926. X
  927. #ifndef NO_SHELL_ESCAPE
  928. X            case '!':
  929. X                shell_escape ();
  930. X                redraw_page (respnum, group);
  931. X                break;
  932. #endif
  933. X
  934. X            case '$':    /* goto end of article */
  935. X            case 'G':    /* 'less' compatible */
  936. end_of_article:            
  937. X                if (show_last_page ()) {
  938. X                    show_note_page (respnum, group);
  939. X                }
  940. X                break;
  941. X
  942. X            case '-':    /* show last viewed article */
  943. X                if (last_resp < 0) {
  944. X                    info_message(txt_no_last_message);
  945. X                    break;
  946. X                }
  947. X                art_close();
  948. X                respnum = last_resp;
  949. X                goto restart;
  950. X
  951. X            case '|':    /* pipe article/thread/tagged arts to command */
  952. X                set_real_uid_gid ();
  953. X                feed_articles (FEED_PIPE, PAGE_LEVEL, "Pipe", respnum, group_path);
  954. X                set_tin_uid_gid ();
  955. X                break;
  956. X
  957. X            case '/':    /* search forwards in article */
  958. X                if (search_article (TRUE)) {
  959. X                    show_note_page (respnum, group);
  960. X                }
  961. X                break;
  962. X
  963. X            case '<':    /* goto first article in current thread */
  964. X                if (arts[respnum].inthread) {
  965. X                    n = which_thread (respnum);
  966. X                    if (n != respnum && n >= 0) {
  967. X                        respnum = n;
  968. X                        art_close ();
  969. X                        goto restart;
  970. X                    }
  971. X                }
  972. X                break;
  973. X
  974. X            case '>':    /* goto last article in current thread */
  975. X                for (i = respnum; i >= 0; i = arts[i].thread) {
  976. X                    n = i;
  977. X                }
  978. X                if (n != respnum) {
  979. X                    respnum = n;
  980. X                    art_close ();
  981. X                    goto restart;
  982. X                }
  983. X                break;
  984. X
  985. X            case ' ':             /* next page or response */
  986. X            case ctrl('D'):        /* vi style */
  987. X            case ctrl('V'):        /* emacs style */
  988. page_down:
  989. X                if (note_page == ART_UNAVAILABLE) {
  990. X                    n = next_response (respnum);
  991. X                    if (n == -1) {
  992. X                        return (which_thread (respnum));
  993. X                    }
  994. X                    respnum = n;
  995. X                    goto restart;
  996. X                } else if (note_end) {
  997. X                    art_close ();
  998. X                    n = next_response (respnum);
  999. X                    if (n == -1) {
  1000. X                        return (which_thread (respnum));
  1001. X                    }
  1002. X                    respnum = n;
  1003. X                    goto restart;
  1004. X                } else
  1005. X                    show_note_page (respnum, group);
  1006. X                break;
  1007. X
  1008. X            case '\r':
  1009. X            case '\n':    /* go to start of next thread */
  1010. X                art_close ();
  1011. X                n = next_thread (respnum);
  1012. X                if (n == -1)
  1013. X                    return (which_thread (respnum));
  1014. X
  1015. X                respnum = n;
  1016. X                goto restart;
  1017. X
  1018. X            case '\t':     /* goto next unread article */
  1019. X                if (note_page != ART_UNAVAILABLE) {
  1020. X                    art_close();
  1021. X                }
  1022. X                n = next_unread (next_response (respnum));
  1023. X                if (n == -1) {
  1024. X                    return (which_thread (respnum));
  1025. X                }
  1026. X                respnum = n;
  1027. X                goto restart;
  1028. X                break;
  1029. X
  1030. X            case ctrl('H'):    /* show article headers */
  1031. X                if (note_page == ART_UNAVAILABLE) {
  1032. X                    n = next_response (respnum);
  1033. X                    if (n == -1)
  1034. X                        return (which_thread (respnum));
  1035. X
  1036. X                    respnum = n;
  1037. X                    goto restart;
  1038. X                } else {
  1039. X                    note_page = 0;
  1040. X                    note_end = FALSE;
  1041. X                    fseek(note_fp, 0L, 0);
  1042. X                    show_note_page(respnum, group);
  1043. X                }
  1044. X                break;
  1045. X
  1046. X            case ctrl('K'):        /* kill article */
  1047. X                if (kill_articles) {
  1048. X                    if (kill_art_menu (group, respnum)) {
  1049. X                        if (kill_any_articles (group)) {
  1050. X                            reload_index_file (group, TRUE);
  1051. X                        }
  1052. X                    }
  1053. X                    redraw_page(respnum, group);
  1054. X                } else {
  1055. X                    info_message (txt_switch_on_kill_art_menu);
  1056. X                }
  1057. X                break;
  1058. X
  1059. X            case ctrl('L'):        /* redraw current page of article */
  1060. X                redraw_page (respnum, group);
  1061. X                break;
  1062. X
  1063. X            case ctrl('R'):        /* redraw beginning of article */
  1064. X            case 'g':            /* 'less' compatible */
  1065. begin_of_article:            
  1066. X                if (note_page == ART_UNAVAILABLE) {
  1067. X                    ClearScreen ();
  1068. X                    printf (txt_art_unavailable,arts[respnum].artnum);
  1069. X                    fflush (stdout);
  1070. X                } else {
  1071. X                    note_page = 0;
  1072. X                    note_end = FALSE;
  1073. X                    fseek (note_fp, note_mark[0], 0);
  1074. X                    show_note_page (respnum, group);
  1075. X                }
  1076. X                break;
  1077. X
  1078. X            case ctrl('X'):
  1079. X            case '%':
  1080. X            case 'd':    /* toggle rot-13 mode */
  1081. X                if (rotate)
  1082. X                    rotate = 0;
  1083. X                else
  1084. X                    rotate = 13;
  1085. X                redraw_page (respnum, group);
  1086. X                info_message (txt_toggled_rot13);
  1087. X                break;
  1088. X
  1089. X            case 'a':    /* author search forward */
  1090. X            case 'A':    /* author search backward */
  1091. X                i = (ch == 'a');
  1092. X                n = search_author (top, respnum, i);
  1093. X                if (n < 0)
  1094. X                    break;
  1095. X                respnum = n;
  1096. X                goto restart;
  1097. X                /* NOTREACHED */
  1098. X
  1099. X            case ctrl('U'):
  1100. X            case 'b':        /* back a page */
  1101. page_up:
  1102. X                if (note_page == ART_UNAVAILABLE) {
  1103. X                    art_close();
  1104. X                    n = prev_response (respnum);
  1105. X                    if (n == -1)
  1106. X                        return (which_response (respnum));
  1107. X
  1108. X                    respnum = n;
  1109. X                    goto restart;
  1110. X
  1111. X                } else {
  1112. X                    if (note_page <= 1) {
  1113. X                        info_message (txt_begin_of_art);
  1114. X                    } else {
  1115. X                        note_page -= 2;
  1116. X                        note_end = FALSE;
  1117. X                        fseek (note_fp, note_mark[note_page], 0);
  1118. X                        show_note_page (respnum, group);
  1119. X                    }
  1120. X                }
  1121. X                break;
  1122. X
  1123. X            case 'B':    /* bug/gripe/comment mailed to author */
  1124. X                mail_bug_report ();
  1125. X                redraw_page (respnum, group);
  1126. X                break;
  1127. X                
  1128. X            case 'c':    /* catchup--mark all articles as read */
  1129. X                if (prompt_yn (LINES, txt_mark_all_read, 'y')) {
  1130. X                    for (n = 0; n < top; n++) {
  1131. X                        arts[n].unread = ART_READ;
  1132. X                    }
  1133. X                    fix_new_highest(cur_groupnum);
  1134. X                    if (cur_groupnum + 1 < group_top) {
  1135. X                        cur_groupnum++;
  1136. X                    }
  1137. X                    art_close();
  1138. X                    return -1;
  1139. X                }
  1140. X                break;
  1141. X
  1142. X            case 'C':    /* cancel an article */
  1143. X                if (cancel_article ()) {
  1144. X                    redraw_page (respnum, group);
  1145. X                }
  1146. X                break;
  1147. X    
  1148. X            case 'f':    /* post a followup to this article */
  1149. X                if (! can_post) {
  1150. X                    info_message (txt_cannot_post);
  1151. X                    break;
  1152. X                }
  1153. X                ret_code = post_response (group, respnum, FALSE);
  1154. X                if (ret_code >= POSTED_REDRAW) {
  1155. X                    update_newsrc (group, my_group[cur_groupnum], FALSE);
  1156. X                    if (ret_code == POSTED_OK) {
  1157. X                        n = which_thread (respnum);
  1158. X                        art_close ();
  1159. X                        index_group (group, group_path);
  1160. X                        read_newsrc_line (group);
  1161. X                        respnum = choose_response (n, num_of_responses (n));
  1162. X                        goto restart;
  1163. X                    } else {
  1164. X                        redraw_page (respnum, group);
  1165. X                    }
  1166. X                } else {
  1167. X                    redraw_page (respnum, group);
  1168. X                }
  1169. X                break;
  1170. X
  1171. X            case 'F':    /* post a followup to this article */
  1172. X                if (! can_post) {
  1173. X                    info_message (txt_cannot_post);
  1174. X                    break;
  1175. X                }
  1176. X                ret_code = post_response (group, respnum, TRUE);
  1177. X
  1178. X                if (ret_code >= POSTED_REDRAW) {
  1179. X                    update_newsrc (group, my_group[cur_groupnum], FALSE);
  1180. X                    if (ret_code == POSTED_OK) {
  1181. X                        n = which_thread (respnum);
  1182. X                        art_close ();
  1183. X                        index_group (group, group_path);
  1184. X                        read_newsrc_line (group);
  1185. X                        respnum = choose_response (n, num_of_responses (n));
  1186. X                        goto restart;
  1187. X                    } else {
  1188. X                        redraw_page (respnum, group);
  1189. X                    }
  1190. X                } else {
  1191. X                    redraw_page (respnum, group);
  1192. X                }
  1193. X                break;
  1194. X
  1195. X            case 'h':    /* help */
  1196. X                show_info_page (HELP_INFO, help_page, txt_art_pager_com);
  1197. X                redraw_page (respnum, group);
  1198. X                break;
  1199. X
  1200. X            case 'i':    /* return to index page */
  1201. return_to_index:
  1202. X                art_close ();
  1203. X                if (kill_state == NO_KILLING &&
  1204. X                    sort_art_type != old_sort_art_type) {
  1205. X                    make_threads (TRUE);
  1206. X                    find_base (show_only_unread);
  1207. X                }
  1208. X                if (kill_state == KILLING) {
  1209. X                    old_top = top;
  1210. X                    old_artnum = arts[respnum].artnum;
  1211. X                    if (kill_articles) {
  1212. X                        kill_any_articles (group);
  1213. X                        reload_index_file (group, TRUE);    /* kill arts */
  1214. X                    } else {
  1215. X                        reload_index_file (group, FALSE);    /* unkill arts */
  1216. X                    }
  1217. X                    return find_new_pos (old_top, old_artnum, respnum);
  1218. X                }
  1219. X                return (which_thread (respnum));
  1220. X
  1221. X            case 'I':    /* toggle inverse video */
  1222. X                toggle_inverse_video ();
  1223. X                redraw_page (respnum, group);
  1224. X                break;
  1225. X
  1226. X            case 'k':
  1227. X                if (note_page == ART_UNAVAILABLE) {
  1228. X                    n = next_unread (next_response(respnum));
  1229. X                    if (n == -1)
  1230. X                        return (which_thread (respnum));
  1231. X                } else {
  1232. X                    art_close ();
  1233. X                    n = next_unread (next_response (respnum));
  1234. X                    if (n == -1)
  1235. X                        return (which_thread (respnum));
  1236. X                }
  1237. X                respnum = n;
  1238. X                goto restart;
  1239. X                /* NOTREACHED */
  1240. X
  1241. X            case 'K':    /* mark rest of thread as read */
  1242. X                for (n = respnum; n >= 0; n = arts[n].thread)
  1243. X                    arts[n].unread = ART_READ;
  1244. X                n = next_unread (next_response (respnum));
  1245. X                if (n == -1)
  1246. X                    goto return_to_index;
  1247. X                art_close ();
  1248. X                respnum = n;
  1249. X                goto restart;
  1250. X                /* NOTREACHED */
  1251. #ifdef NYI
  1252. X            case 'l':    /* list articles within current thread */
  1253. X                if (show_thread (respnum, group, group_path)) {
  1254. X                    redraw_page (respnum, group);
  1255. X                }
  1256. X                break;    
  1257. #endif
  1258. X
  1259. X            case 'm':    /* mail article/thread/tagged articles to somebody */
  1260. X                set_real_uid_gid ();
  1261. X                feed_articles (FEED_MAIL, PAGE_LEVEL, "Mail", respnum, group_path);
  1262. X                set_tin_uid_gid ();
  1263. X                break;
  1264. X
  1265. X            case 'M':    /* options menu */
  1266. X                if (change_rcfile (group, FALSE) == KILLING) {
  1267. X                    kill_state = KILLING;
  1268. X                } 
  1269. X                redraw_page (respnum, group);
  1270. X                break;
  1271. X
  1272. X            case 'n':    /* skip to next article */
  1273. X                art_close ();
  1274. X                n = next_response (respnum);
  1275. X                if (n == -1)
  1276. X                    return (which_thread(respnum));
  1277. X
  1278. X                respnum = n;
  1279. X                goto restart;
  1280. X                /* NOTREACHED */
  1281. X                
  1282. X            case 'N':    /* next unread article */
  1283. X                n = next_unread(next_response(respnum));
  1284. X                if (n == -1)
  1285. X                    info_message(txt_no_next_unread_art);
  1286. X                else {
  1287. X                    art_close();
  1288. X                    respnum = n;
  1289. X                    goto restart;
  1290. X                }
  1291. X                break;
  1292. X
  1293. X            case 'o':    /* output art/thread/tagged arts to printer */
  1294. X                set_real_uid_gid ();
  1295. X                feed_articles (FEED_PRINT, PAGE_LEVEL, "Print", respnum, group_path);
  1296. X                set_tin_uid_gid ();
  1297. X                break;
  1298. X
  1299. X            case 'p':    /* previous article */
  1300. X                art_close ();
  1301. X                n = prev_response (respnum);
  1302. X                if (n == -1)
  1303. X                    return (which_response (respnum));
  1304. X
  1305. X                respnum = n;
  1306. X                goto restart;
  1307. X
  1308. X            case 'P':    /* previous unread article */
  1309. X                n = prev_unread (prev_response (respnum));
  1310. X                if (n == -1)
  1311. X                    info_message (txt_no_prev_unread_art);
  1312. X                else {
  1313. X                    art_close ();
  1314. X                    respnum = n;
  1315. X                    goto restart;
  1316. X                }
  1317. X                break;
  1318. X
  1319. X            case 'q':    /* quit */
  1320. X                if (prompt_yn (LINES, txt_quit, 'y')) {
  1321. X                    return -2;
  1322. X                }
  1323. X                break;
  1324. X    
  1325. X            case 'r':    /* reply to author through mail */
  1326. X                mail_to_author (respnum, FALSE);
  1327. X                redraw_page (respnum, group);
  1328. X                break;
  1329. X
  1330. X            case 'R':    /* reply to author, copy text */
  1331. X                mail_to_author (respnum, TRUE);
  1332. X                redraw_page (respnum, group);
  1333. X                break;
  1334. X
  1335. X            case 's':    /* save article/thread/tagged articles */
  1336. X                set_real_uid_gid ();
  1337. X                feed_articles (FEED_SAVE, PAGE_LEVEL, "Save", respnum, group_path);
  1338. X                set_tin_uid_gid ();
  1339. X                break;
  1340. X
  1341. X            case 't':    /* return to group selection page */
  1342. X                art_close ();
  1343. X                if (kill_state == KILLING) {
  1344. X                    if (kill_articles) {
  1345. X                        kill_any_articles (group);
  1346. X                        reload_index_file (group, TRUE);    /* kill arts */
  1347. X                    } else {
  1348. X                        reload_index_file (group, FALSE);    /* unkill arts */
  1349. X                    }
  1350. X                }
  1351. X                update_newsrc (group, my_group[cur_groupnum], FALSE);
  1352. X                fix_new_highest (cur_groupnum);
  1353. X                return -1;
  1354. X
  1355. X            case 'T':    /* tag/untag article for saving */
  1356. X                if (arts[respnum].tagged) {
  1357. X                    arts[respnum].tagged = 0;
  1358. X                    info_message (txt_untagged_art);
  1359. X                } else {
  1360. X                    arts[respnum].tagged = ++num_of_tagged_files;
  1361. X                    info_message (txt_tagged_art);
  1362. X                }
  1363. X                break;
  1364. X
  1365. X            case 'v':
  1366. X                info_message (cvers);
  1367. X                break;
  1368. X
  1369. X            case 'w':    /* post a basenote */
  1370. X                if (! can_post) {
  1371. X                    info_message (txt_cannot_post);
  1372. X                    break;
  1373. X                }
  1374. X                if (post_base (group, &posted)) {
  1375. X                    if (posted) {
  1376. X                        update_newsrc (group, my_group[cur_groupnum], FALSE);
  1377. X                        index_group (group, group_path);
  1378. X                        read_newsrc_line (group);
  1379. X                    }
  1380. X                    redraw_page (respnum, group);
  1381. X                }
  1382. X                break;
  1383. X
  1384. X            case 'W':    /* display messages posted by user */
  1385. X                if (user_posted_messages ()) {
  1386. X                    redraw_page (respnum, group);
  1387. X                }
  1388. X                break;
  1389. X
  1390. X            case 'z':    /* mark article as unread (to return) */
  1391. X                arts[respnum].unread = ART_WILL_RETURN;
  1392. X                info_message (txt_art_marked_as_unread);
  1393. X                break;
  1394. X
  1395. X            default:
  1396. X                info_message(txt_bad_command);
  1397. X        }
  1398. X    }
  1399. }
  1400. X
  1401. X
  1402. void redraw_page (respnum, group)
  1403. X    int respnum;
  1404. X    char *group;
  1405. {
  1406. X
  1407. X    if (note_page == ART_UNAVAILABLE) {
  1408. X        ClearScreen ();
  1409. X        printf (txt_art_unavailable, arts[respnum].artnum);
  1410. X        fflush (stdout);
  1411. X    } else if (note_page > 0) {
  1412. X        note_page--;
  1413. X        fseek (note_fp, note_mark[note_page], 0);
  1414. X        show_note_page (respnum, group);
  1415. X    }
  1416. }
  1417. X
  1418. X
  1419. void show_note_page (respnum, group)
  1420. X    int respnum;
  1421. X    char *group;
  1422. {
  1423. X    char buf[LEN];
  1424. X    char buf2[LEN+50];
  1425. X    char *p, *q;
  1426. X    int i, j;
  1427. X    int ctrl_L;        /* form feed character detected */
  1428. X    long tmp_pos;
  1429. X
  1430. X    ClearScreen ();
  1431. X
  1432. X    note_line = 1;
  1433. X
  1434. X    if (note_size == 0L) {
  1435. X        tmp_pos = ftell (note_fp);
  1436. X        fseek (note_fp, 0L, 2);            /* goto end of article */
  1437. X        note_size = ftell (note_fp);
  1438. X        fseek (note_fp, tmp_pos, 0);    /* goto old position */
  1439. X    }
  1440. X    
  1441. X    if (note_page == 0)
  1442. X        show_first_header (respnum, group);
  1443. X    else
  1444. X        show_cont_header (respnum);
  1445. X
  1446. X    ctrl_L = FALSE;
  1447. X    while (note_line < LINES) {
  1448. X        if (fgets (buf, sizeof (buf), note_fp) == NULL) {
  1449. X            note_end = TRUE;
  1450. X            break;
  1451. X        }
  1452. X
  1453. X        buf[LEN-1] = '\0';
  1454. X        if (rotate)
  1455. X            for (p = buf, q = buf2; *p && *p != '\n' && q < &buf2[LEN]; p++) {
  1456. X                if (*p == '\b' && q > buf2) {
  1457. X                    q--;
  1458. X                } else if (*p == 12) {        /* ^L */
  1459. X                    *q++ = '^';
  1460. X                    *q++ = 'L';
  1461. X                    ctrl_L = TRUE;
  1462. X                } else if (*p == '\t') {
  1463. X                    i = q - buf2;
  1464. X                    j = (i|7) + 1;
  1465. X
  1466. X                    while (i++ < j)
  1467. X                        *q++ = ' ';
  1468. X                } else if (((*p) & 0xFF) < ' ') {
  1469. X                    *q++ = '^';
  1470. X                    *q++ = ((*p) & 0xFF) + '@';
  1471. X                } else if (*p >= 'A' && *p <= 'Z')
  1472. X                    *q++ = 'A' + (*p - 'A' + rotate) % 26;
  1473. X                else if (*p >= 'a' && *p <= 'z')
  1474. X                    *q++ = 'a' + (*p - 'a' + rotate) % 26;
  1475. X                else
  1476. X                    *q++ = *p;
  1477. X            }
  1478. X        else
  1479. X            for (p = buf, q = buf2; *p && *p != '\n' && q < &buf2[LEN]; p++) {
  1480. X                if (*p == '\b' && q > buf2) {
  1481. X                    q--;
  1482. X                } else if (*p == 12) {        /* ^L */
  1483. X                    *q++ = '^';
  1484. X                    *q++ = 'L';
  1485. X                    ctrl_L = TRUE;
  1486. X                } else if (*p == '\t') {
  1487. X                    i = q - buf2;
  1488. X                    j = (i|7) + 1;
  1489. X
  1490. X                    while (i++ < j)
  1491. X                        *q++ = ' ';
  1492. X                } else if (((*p) & 0xFF) < ' ') {
  1493. X                    *q++ = '^';
  1494. X                    *q++ = ((*p) & 0xFF) + '@';
  1495. X                } else
  1496. X                    *q++ = *p;
  1497. X            }
  1498. X
  1499. X        *q = '\0';
  1500. X
  1501. X        printf("%s\r\n", buf2);
  1502. X
  1503. X        note_line += ((int) strlen (buf2) / COLS) + 1;
  1504. X
  1505. X        if (ctrl_L) {
  1506. X            break;
  1507. X        }
  1508. X    }
  1509. X
  1510. X    note_mark[++note_page] = ftell (note_fp);
  1511. X
  1512. X    if (note_mark[note_page] == note_size) {
  1513. X        note_end = TRUE;
  1514. X    }
  1515. X
  1516. X    if (note_end) {
  1517. X        MoveCursor (LINES, MORE_POS-(5+BLANK_PAGE_COLS));
  1518. X        StartInverse ();    
  1519. X        if (arts[respnum].thread != -1) {
  1520. X            printf (txt_next_resp);
  1521. X            fflush (stdout);
  1522. X        } else {
  1523. X            printf (txt_last_resp);
  1524. X            fflush (stdout);
  1525. X        }
  1526. X        EndInverse ();
  1527. X    } else {
  1528. X        if (note_size > 0) {
  1529. X            draw_percent_mark ((int) note_mark[note_page], (int) note_size);
  1530. X        } else {
  1531. X            MoveCursor (LINES, MORE_POS-BLANK_PAGE_COLS);
  1532. X            StartInverse ();    
  1533. X            printf (txt_more);
  1534. X            fflush (stdout);
  1535. X            EndInverse ();
  1536. X        }
  1537. X    }
  1538. X    MoveCursor (LINES, 0);
  1539. }
  1540. X
  1541. X
  1542. void show_first_header (respnum, group)
  1543. X    int respnum;
  1544. X    char *group;
  1545. {
  1546. X    int whichresp;
  1547. X    int x_resp;
  1548. X    char buf[LEN];
  1549. X    char tmp[LEN];
  1550. X    int pos, i;
  1551. X    int n;
  1552. X
  1553. X    whichresp = which_response (respnum);
  1554. X    x_resp = num_of_responses (which_thread (respnum));
  1555. X
  1556. X    ClearScreen ();
  1557. X
  1558. X    strcpy (buf, note_h_date);
  1559. X    pos = (COLS - (int) strlen (group)) / 2;
  1560. X    for (i = strlen(buf); i < pos; i++)
  1561. X        buf[i] = ' ';
  1562. X    buf[i] = '\0';
  1563. X
  1564. X    strcat (buf, group);
  1565. X
  1566. X    for (i = strlen(buf); i < RIGHT_POS ; i++)
  1567. X        buf[i] = ' ';
  1568. X    buf[i] = '\0';
  1569. X
  1570. X    printf (txt_thread_x_of_n, buf, which_thread (respnum) + 1, top_base);
  1571. X
  1572. X    sprintf (buf, txt_art, arts[respnum].artnum);
  1573. X    n = strlen (buf);
  1574. X    fputs (buf, stdout);
  1575. X
  1576. X    strcpy (buf, note_h_subj);
  1577. X    buf[RIGHT_POS - 5 - n] = '\0';
  1578. X
  1579. X    pos = ((COLS - (int) strlen (buf)) / 2) - 2;
  1580. X
  1581. X    if (pos > n) {
  1582. X        MoveCursor (1, pos);
  1583. X    } else {
  1584. X        MoveCursor (1, n);
  1585. X    }
  1586. X
  1587. X    StartInverse ();
  1588. X    fputs (buf, stdout);
  1589. X    EndInverse ();
  1590. X
  1591. X    MoveCursor (1, RIGHT_POS);
  1592. X    if (whichresp)
  1593. X        printf (txt_resp_x_of_n, whichresp, x_resp);
  1594. X    else {
  1595. X        if (x_resp == 0)
  1596. X            printf (txt_no_resp);
  1597. X        else if (x_resp == 1)
  1598. X            printf (txt_1_resp);
  1599. X        else
  1600. X            printf (txt_x_resp, x_resp);
  1601. X    }
  1602. X
  1603. X    if (*note_h_org) {
  1604. X        if (strcmp (arts[respnum].from, arts[respnum].name) == 0) {
  1605. X            strcpy (tmp, note_h_org);
  1606. X        } else {
  1607. X            sprintf (tmp, txt_s_at_s, arts[respnum].name, note_h_org);
  1608. X        }
  1609. X    } else {
  1610. X        strcpy (tmp, arts[respnum].name);
  1611. X    }
  1612. X
  1613. X    tmp[LEN-1] = '\0';
  1614. X
  1615. X    sprintf (buf, "%s  ", arts[respnum].from);
  1616. X
  1617. X    pos = COLS - 1 - (int) strlen(tmp);
  1618. X    if ((int) strlen (buf) + (int) strlen (tmp) >= COLS - 1) {
  1619. X        strncat (buf, tmp, COLS - 1 - (int) strlen(buf));
  1620. X        buf[COLS-1] = '\0';
  1621. X    } else {
  1622. X        for (i = strlen(buf); i < pos; i++)
  1623. X            buf[i] = ' ';
  1624. X        buf[i] = '\0';
  1625. X        strcat (buf, tmp);
  1626. X    }
  1627. X    printf ("%s\r\n\r\n", buf);
  1628. X
  1629. X    note_line += 4;
  1630. }
  1631. X
  1632. X
  1633. void show_cont_header (respnum)
  1634. X    int respnum;
  1635. {
  1636. X    int whichresp;
  1637. X    int whichbase;
  1638. X    char buf[LEN];
  1639. X
  1640. X    whichresp = which_response (respnum);
  1641. X    whichbase = which_thread (respnum);
  1642. X
  1643. X    assert (whichbase < top_base);
  1644. X
  1645. X    if (whichresp)
  1646. X        sprintf(buf, txt_thread_resp_page,
  1647. X            whichbase + 1,
  1648. X            top_base,
  1649. X            whichresp,
  1650. X            note_page + 1,
  1651. X            note_h_subj);
  1652. X    else
  1653. X        sprintf(buf, txt_thread_page,
  1654. X            whichbase + 1,
  1655. X            top_base,
  1656. X            note_page + 1,
  1657. X            note_h_subj);
  1658. X
  1659. X    buf[COLS-1] = '\0';
  1660. X    printf("%s\r\n\r\n", buf);
  1661. X
  1662. X    note_line += 2;
  1663. }
  1664. X
  1665. X
  1666. void art_open (art, group_path)
  1667. X    long art;
  1668. X    char *group_path;
  1669. {
  1670. X    char buf[1025];
  1671. X    char *p;
  1672. X
  1673. X    note_page = 0;
  1674. X
  1675. X    art_close ();    /* just in case */
  1676. X
  1677. X    if ((note_fp = open_art_fp (group_path, art)) == NULL) {
  1678. X        error_message ("art %d not opened", "");
  1679. X        note_page = ART_UNAVAILABLE;
  1680. X        return;
  1681. X    }
  1682. X
  1683. X    note_h_path[0] = '\0';
  1684. X    note_h_subj[0] = '\0';
  1685. X    note_h_org[0] = '\0';
  1686. X    note_h_date[0] = '\0';
  1687. X    note_h_newsgroups[0] = '\0';
  1688. X    note_h_messageid[0] = '\0';
  1689. X    note_h_distrib[0] = '\0';
  1690. X    note_h_followup[0] = '\0';
  1691. X
  1692. X    while (fgets(buf, sizeof buf, note_fp) != NULL) {
  1693. X        buf[1024] = '\0';
  1694. X
  1695. X        for (p=buf ; *p && *p != '\n' ; p++) {
  1696. X            if (((*p) & 0xFF) < ' ')
  1697. X                *p = ' ';
  1698. X        }
  1699. X        *p = '\0';
  1700. X        
  1701. X        if (*buf == '\0')
  1702. X            break;
  1703. X
  1704. X          if (match_header (buf, "Path", note_h_path, LEN))
  1705. X              continue;
  1706. X          if (match_header (buf, "Subject", note_h_subj, LEN))
  1707. X              continue;
  1708. X          if (match_header (buf, "Organization", note_h_org, LEN))
  1709. X              continue;
  1710. X          if (match_header (buf, "Date", note_h_date, LEN))
  1711. X              continue;
  1712. X          if (match_header (buf, "Newsgroups", note_h_newsgroups, LEN))
  1713. X              continue;
  1714. X          if (match_header (buf, "Message-ID", note_h_messageid, LEN))
  1715. X              continue;
  1716. X          if (match_header (buf, "Message-Id", note_h_messageid, LEN))
  1717. X              continue;
  1718. X          if (match_header (buf, "Distribution", note_h_distrib, LEN))
  1719. X              continue;
  1720. X          if (match_header (buf, "Followup-To", note_h_followup, LEN))
  1721. X              continue;
  1722. X    }
  1723. X
  1724. X    note_page = 0;
  1725. X    note_mark[0] = ftell (note_fp);
  1726. X    note_end = FALSE;
  1727. X
  1728. X    return;
  1729. }
  1730. X
  1731. X
  1732. void art_close ()
  1733. {
  1734. X    if (note_fp && note_page != ART_UNAVAILABLE) {
  1735. X        fclose (note_fp);
  1736. X        note_fp = (FILE *) 0;
  1737. X    }
  1738. }
  1739. X
  1740. X
  1741. int prompt_response (ch, respnum)
  1742. X    int respnum;
  1743. {
  1744. X    int num;
  1745. X
  1746. X    clear_message ();
  1747. X
  1748. X    if ((num = prompt_num (ch, txt_read_resp)) == -1) {
  1749. X        clear_message ();
  1750. X        return -1;
  1751. X    }
  1752. X
  1753. X    return choose_response (which_thread (respnum), num);
  1754. }
  1755. X
  1756. X
  1757. void yank_to_addr (orig, addr)
  1758. X    char *orig;
  1759. X    char *addr;
  1760. {
  1761. X    char *p;
  1762. X
  1763. X    for (p = orig; *p; p++)
  1764. X        if (((*p) & 0xFF) < ' ')
  1765. X            *p = ' ';
  1766. X
  1767. X    while (*addr)
  1768. X        addr++;
  1769. X
  1770. X    while (*orig) {
  1771. X        while (*orig && (*orig == ' ' || *orig == '"' || *orig == ','))
  1772. X            orig++;
  1773. X        *addr++ = ' ';
  1774. X        while (*orig && (*orig != ' ' && *orig != ',' && *orig != '"'))
  1775. X            *addr++ = *orig++;
  1776. X        while (*orig && (*orig == ' ' || *orig == '"' || *orig == ','))
  1777. X            orig++;
  1778. X        if (*orig == '(') {
  1779. X            while (*orig && *orig != ')')
  1780. X                orig++;
  1781. X            if (*orig == ')')
  1782. X                orig++;
  1783. X        }
  1784. X    }
  1785. X    *addr = '\0';
  1786. }
  1787. X
  1788. X
  1789. int show_last_page ()
  1790. {
  1791. X    char buf[LEN];
  1792. X    char buf2[LEN+50];
  1793. X    char *p, *q;
  1794. X    int ctrl_L;        /* form feed character detected */
  1795. X    int i, j;
  1796. X    long tmp_pos;
  1797. X    
  1798. X    if (note_end) {
  1799. X        return FALSE;
  1800. X    }
  1801. X
  1802. X    if (note_size == 0L) {
  1803. X        tmp_pos = ftell (note_fp);
  1804. X        fseek (note_fp, 0L, 2);            /* goto end of article */
  1805. X        note_size = ftell (note_fp);
  1806. X        fseek (note_fp, tmp_pos, 0);    /* goto old position */
  1807. X    }
  1808. X
  1809. X    while (! note_end) {
  1810. X        note_line = 1;
  1811. X        ctrl_L = FALSE;
  1812. X
  1813. X        if (note_page == 0) {
  1814. X            note_line += 4;
  1815. X        } else {
  1816. X            note_line += 2;
  1817. X        }
  1818. X        while (note_line < LINES) {
  1819. X            if (fgets (buf, sizeof buf, note_fp) == NULL) {
  1820. X                note_end = TRUE;
  1821. X                break;
  1822. X            }
  1823. X            buf[LEN-1] = '\0';
  1824. X            for (p = buf, q = buf2;    *p && *p != '\n' && q<&buf2[LEN]; p++) {
  1825. X                if (*p == '\b' && q > buf2) {
  1826. X                    q--;
  1827. X                } else if (*p == 12) {        /* ^L */
  1828. X                    *q++ = '^';
  1829. X                    *q++ = 'L';
  1830. X                    ctrl_L = TRUE;
  1831. X                } else if (*p == '\t') {
  1832. X                    i = q - buf2;
  1833. X                    j = (i|7) + 1;
  1834. X
  1835. X                    while (i++ < j) {
  1836. X                        *q++ = ' ';
  1837. X                    }
  1838. X                } else if (((*p) & 0xFF) < ' ') {
  1839. X                    *q++ = '^';
  1840. X                    *q++ = ((*p) & 0xFF) + '@';
  1841. X                } else {
  1842. X                    *q++ = *p;
  1843. X                }
  1844. X            }
  1845. X            *q = '\0';
  1846. X            note_line += ((int) strlen (buf2) / COLS) + 1;
  1847. X
  1848. X            if (ctrl_L) {
  1849. X                break;
  1850. X            }
  1851. X        }
  1852. X        if (note_mark[note_page] == note_size) {
  1853. X            note_end = TRUE;
  1854. X            note_page--;
  1855. X            break;
  1856. X        } else if (! note_end) {
  1857. X            note_mark[++note_page] = ftell(note_fp);
  1858. X        }
  1859. X    }
  1860. X    fseek (note_fp, note_mark[note_page], 0);
  1861. X    return TRUE;
  1862. }
  1863. X
  1864. X
  1865. int match_header (buf, pat, body, len)
  1866. X    char *buf;
  1867. X    char *pat;
  1868. X    char *body;
  1869. X    int    len;
  1870. {
  1871. X    int    plen = strlen (pat);
  1872. X
  1873. X    if(strncmp (buf, pat, plen) == 0 && buf[plen] == ':' && buf[plen + 1] == ' ') {
  1874. X        plen += 2;
  1875. X        while (buf[plen] == ' ')
  1876. X            plen++;
  1877. X        strncpy (body, &buf[plen], len);
  1878. X        body[len - 1] = '\0';
  1879. X        return TRUE;
  1880. X    }
  1881. X    return FALSE;
  1882. }
  1883. SHAR_EOF
  1884. chmod 0600 page.c ||
  1885. echo 'restore of page.c failed'
  1886. Wc_c="`wc -c < 'page.c'`"
  1887. test 23335 -eq "$Wc_c" ||
  1888.     echo 'page.c: original size 23335, current size' "$Wc_c"
  1889. rm -f _shar_wnt_.tmp
  1890. fi
  1891. # ============= post.c ==============
  1892. if test -f 'post.c' -a X"$1" != X"-c"; then
  1893.     echo 'x - skipping post.c (File already exists)'
  1894.     rm -f _shar_wnt_.tmp
  1895. else
  1896. > _shar_wnt_.tmp
  1897. echo 'x - extracting post.c (Text)'
  1898. sed 's/^X//' << 'SHAR_EOF' > 'post.c' &&
  1899. /*
  1900. X *  Project   : tin - a threaded Netnews reader
  1901. X *  Module    : post.c
  1902. X *  Author    : I.Lea
  1903. X *  Created   : 01-04-91
  1904. X *  Updated   : 22-01-92
  1905. X *  Notes     : mailing/posting/replying/followup & cancel article routines
  1906. X *  Copyright : (c) Copyright 1991-92 by Rich Skrenta & Iain Lea
  1907. X *                You may  freely  copy or  redistribute  this software,
  1908. X *              so  long as there is no profit made from its use, sale
  1909. X *              trade or  reproduction.  You may not change this copy-
  1910. X *              right notice, and it must be included in any copy made
  1911. X */
  1912. X
  1913. #include    "tin.h"
  1914. X
  1915. extern char note_h_distrib[LEN];        /* Distribution: */
  1916. extern char note_h_followup[LEN];        /* Followup-To: */
  1917. extern char note_h_messageid[LEN];        /* Message-ID:    */
  1918. extern char note_h_newsgroups[LEN];        /* Newsgroups:    */
  1919. extern char note_h_subj[LEN];            /* Subject:    */
  1920. extern FILE *note_fp;                    /* the body of the current article */
  1921. extern int cur_groupnum;
  1922. extern long note_mark[MAX_PAGES];        /* ftells on beginnings of pages */
  1923. X
  1924. char default_post_subject[LEN];        /* offers user default choice */
  1925. X
  1926. struct posted_t *posted;
  1927. X
  1928. X
  1929. int user_posted_messages ()
  1930. {
  1931. X    char buf[LEN];
  1932. X    FILE *fp;
  1933. X    int i, j, k;
  1934. X    int no_of_lines = 0;
  1935. X
  1936. X    set_real_uid_gid ();
  1937. X        
  1938. X    if ((fp = fopen (postfile, "r")) == NULL) {
  1939. X        clear_message ();
  1940. X        set_tin_uid_gid ();
  1941. X        return FALSE;
  1942. X    } else {
  1943. X        while (fgets (buf, sizeof (buf), fp) != NULL) {
  1944. X            no_of_lines++;
  1945. X        }
  1946. X        if (! no_of_lines) {
  1947. X            fclose (fp);
  1948. X            info_message (txt_no_arts_posted);
  1949. X            return FALSE;
  1950. X        }
  1951. X        rewind (fp);
  1952. X        posted = (struct posted_t *) my_malloc ((unsigned) (no_of_lines+1) * sizeof (struct posted_t));
  1953. X        for (i=0 ; fgets (buf, sizeof (buf), fp) != NULL ; i++) {
  1954. X            for (j=0 ; buf[j] != '|' && buf[j] != '\n' ; j++) {
  1955. X                posted[i].date[j] = buf[j];        /* posted date */
  1956. X            }
  1957. X            if (buf[j] == '\n') {    
  1958. X                error_message ("Corrupted file %s", postfile);
  1959. X                sleep (1);
  1960. X                fclose (fp);
  1961. X                clear_message ();
  1962. X                return FALSE;
  1963. X            }
  1964. X            posted[i].date[j++] = '\0';
  1965. X            for (k=j,j=0 ; buf[k] != '|' && buf[k] != ',' ; k++, j++) {
  1966. X                posted[i].group[j] = buf[k];
  1967. X            }
  1968. X            if (buf[k] == ',') {
  1969. X                while (buf[k] != '|' && buf[k] != '\n') {
  1970. X                    k++;
  1971. X                }
  1972. X                posted[i].group[j++] = ',';
  1973. X                posted[i].group[j++] = '.';
  1974. X                posted[i].group[j++] = '.';
  1975. X                posted[i].group[j++] = '.';
  1976. X            }
  1977. X            posted[i].group[j++] = '\0';
  1978. X            k++;
  1979. X            for (j=k,k=0 ; buf[j] != '\n' ; j++, k++) {
  1980. X                posted[i].subj[k] = buf[j];
  1981. X            }
  1982. X            posted[i].subj[k++] = '\0';
  1983. X        }
  1984. X        fclose (fp);
  1985. X        set_tin_uid_gid ();
  1986. X
  1987. X        show_info_page (POST_INFO, (char **) 0, txt_post_history_menu);
  1988. X        if (posted != (struct posted_t *) 0) {
  1989. X            free ((char *) posted);
  1990. X            posted = (struct posted_t *) 0;
  1991. X        }
  1992. X        return TRUE;
  1993. X    }
  1994. }
  1995. X
  1996. X
  1997. void update_art_posted_file (group, subj)
  1998. X    char *group;
  1999. X    char *subj;
  2000. {
  2001. X    char buf[LEN];
  2002. X    char tmp_post[LEN];
  2003. X    FILE *fp, *tmp_fp;
  2004. X    long epoch;
  2005. X    struct tm *tm;
  2006. X
  2007. X    sprintf (tmp_post, "%s.%d", postfile, getpid ());
  2008. X
  2009. X    set_real_uid_gid ();
  2010. X
  2011. X    if ((tmp_fp = fopen (tmp_post, "w")) != NULL) {
  2012. X        time (&epoch);
  2013. X        tm = localtime (&epoch);
  2014. X        fprintf (tmp_fp, "%02d-%02d-%02d|%s|%s\n",
  2015. X            tm->tm_mday, tm->tm_mon+1, tm->tm_year, group, subj);
  2016. X        fclose (tmp_fp);
  2017. X    }
  2018. X
  2019. X    if ((tmp_fp = fopen (tmp_post, "a+")) != NULL) {
  2020. X        if ((fp = fopen (postfile, "r")) != NULL) {
  2021. X            while (fgets (buf, sizeof buf, fp) != NULL) {
  2022. X                fprintf (tmp_fp, "%s", buf);
  2023. X            }    
  2024. X            fclose (fp);
  2025. X            rename_file (tmp_post, postfile);
  2026. X        }
  2027. X        fclose (tmp_fp);
  2028. X    }
  2029. X    set_tin_uid_gid ();
  2030. }
  2031. X
  2032. /*
  2033. X *  Post an original article (not a followup)
  2034. X */
  2035. X
  2036. int post_base (group, posted)
  2037. X    char *group;
  2038. X    int *posted;
  2039. {
  2040. X    FILE *fp;
  2041. X    char ch;
  2042. X    char ch_default = 'p';
  2043. X    char subj[LEN];
  2044. X    char buf[LEN];
  2045. X    int redraw_screen = FALSE;
  2046. X
  2047. X    *posted = FALSE;
  2048. X    start_line_offset = 4;
  2049. X
  2050. X    if (active[my_group[cur_groupnum]].moderated == 'm') {
  2051. X        sprintf (msg, "Group %s is moderated. Continue? (y/n): ", group);
  2052. X        if (! prompt_yn (LINES, msg, 'y')) {
  2053. X            clear_message ();
  2054. X            return (redraw_screen);
  2055. X        }
  2056. X    }
  2057. X
  2058. X    sprintf (msg, txt_post_subject, default_post_subject);
  2059. X    
  2060. X    if (! prompt_string (msg, subj)) {
  2061. X        clear_message ();
  2062. X        return (redraw_screen);
  2063. X    }
  2064. X
  2065. X    if (strlen (subj)) {
  2066. X        my_strncpy (default_post_subject, subj, LEN);
  2067. X    } else {
  2068. X        if (default_post_subject[0]) {
  2069. X            my_strncpy (subj, default_post_subject, LEN);
  2070. X        } else {
  2071. X            info_message (txt_no_subject);
  2072. X            return (redraw_screen);
  2073. X        }
  2074. X    }
  2075. X    
  2076. X    wait_message (txt_post_an_article);
  2077. X
  2078. X    set_real_uid_gid ();
  2079. X
  2080. X    if ((fp = fopen (article, "w")) == NULL) {
  2081. X        error_message (txt_cannot_open, article);
  2082. X        set_tin_uid_gid ();
  2083. X        return (redraw_screen);
  2084. X    }
  2085. X    chmod (article, 0600);
  2086. X
  2087. X    fprintf (fp, "Subject: %s\n", subj);
  2088. X    fprintf (fp, "Newsgroups: %s\n", group);
  2089. X    fprintf (fp, "Distribution: \n");
  2090. X    if (*my_org) {
  2091. X        fprintf (fp, "Organization: %s\n", my_org);
  2092. X        start_line_offset++;
  2093. X    }
  2094. X    if (*reply_to) {
  2095. X        fprintf (fp, "Reply-To: %s\n", reply_to);
  2096. X        start_line_offset++;
  2097. X    }
  2098. X    fprintf (fp, "\n");
  2099. X
  2100. X    add_signature (fp, FALSE);
  2101. X    fclose (fp);
  2102. X
  2103. X    ch = 'e';
  2104. X    while (1) {
  2105. X        switch (ch) {
  2106. X        case 'e':
  2107. X            invoke_editor (article);
  2108. X             set_real_uid_gid ();
  2109. X            redraw_screen = TRUE;
  2110. X            break;
  2111. X
  2112. X        case 'a':
  2113. X        case ESC:
  2114. X            unlink (article);
  2115. X            clear_message ();
  2116. X            set_tin_uid_gid ();
  2117. X            return (redraw_screen);
  2118. X
  2119. X        case 'p':
  2120. X            wait_message (txt_posting);
  2121. X            if (submit_file (article)) {
  2122. X                info_message (txt_art_posted);
  2123. X                *posted = TRUE;
  2124. X                goto post_base_done;
  2125. X            } else {
  2126. X                rename_file (article, dead_article);
  2127. X                sprintf (buf, txt_art_rejected, dead_article);
  2128. X                info_message (buf);
  2129. X                sleep (3);
  2130. X                set_tin_uid_gid ();
  2131. X                return (redraw_screen);
  2132. X            }
  2133. X        }
  2134. X
  2135. X        do {
  2136. X            sprintf (msg, "%s%c", txt_abort_edit_post, ch_default);
  2137. X            wait_message (msg);
  2138. X            MoveCursor (LINES, (int) strlen (txt_abort_edit_post));
  2139. X            if ((ch = (char) ReadCh ()) == CR)
  2140. X                ch = ch_default;
  2141. X        } while (ch != ESC && ch != 'a' && ch != 'e' && ch != 'p');
  2142. X    }
  2143. X
  2144. post_base_done:
  2145. X    find_mail_header (HEADER_SUBJECT, article, subj);
  2146. X    unlink (article);
  2147. X    set_tin_uid_gid ();
  2148. X    update_art_posted_file (group, subj);
  2149. X    return (redraw_screen);
  2150. }
  2151. X
  2152. X
  2153. int post_response (group, respnum, copy_text)
  2154. X    char *group;
  2155. X    int respnum;
  2156. X    int copy_text;
  2157. {
  2158. X    FILE *fp;
  2159. X    char ch, *ptr;
  2160. X    char ch_default = 'p';
  2161. X    char buf[LEN];
  2162. X    int ret_code = POSTED_NONE;
  2163. X    
  2164. X    start_line_offset = 4;
  2165. X
  2166. X    wait_message (txt_post_a_followup);
  2167. X    
  2168. X    if (*note_h_followup && strcmp (note_h_followup, "poster") == 0) {
  2169. X        clear_message ();
  2170. X        if (! prompt_yn (LINES, txt_resp_to_poster, 'y')) {
  2171. X            return (ret_code);
  2172. X        }
  2173. X        *note_h_followup = '\0';
  2174. X    } else if (*note_h_followup && strcmp(note_h_followup, group) != 0) {
  2175. X        MoveCursor (LINES/2, 0);
  2176. X        CleartoEOS ();
  2177. X        center_line ((LINES/2)+2, TRUE, txt_resp_redirect);
  2178. X        MoveCursor ((LINES/2)+4, 0);
  2179. X
  2180. X        printf ("    ");
  2181. X        ptr = note_h_followup;
  2182. X        while (*ptr) {
  2183. X            if (*ptr != ',') {
  2184. X                putc (*ptr, stdout);
  2185. X            } else {
  2186. X                printf ("\r\n    ");
  2187. X            }
  2188. X            fflush (stdout);
  2189. X            ptr++;
  2190. X        }
  2191. X
  2192. X        if (! prompt_yn (LINES, txt_continue, 'y')) {
  2193. X            return (ret_code);
  2194. X        }
  2195. X    }
  2196. X
  2197. X    set_real_uid_gid ();
  2198. X
  2199. X    if ((fp = fopen (article, "w")) == NULL) {
  2200. X        error_message (txt_cannot_open, article);
  2201. X        set_tin_uid_gid ();
  2202. X        return (ret_code);
  2203. X    }
  2204. X    chmod (article, 0600);
  2205. X
  2206. X    fprintf (fp, "Subject: Re: %s\n", eat_re (note_h_subj));
  2207. X
  2208. X    if (*note_h_followup && strcmp(note_h_followup, "poster") != 0) {
  2209. X        fprintf (fp, "Newsgroups: %s\n", note_h_followup);
  2210. X    } else {
  2211. X        fprintf (fp, "Newsgroups: %s\n", note_h_newsgroups);
  2212. X    }
  2213. X    if (note_h_distrib != '\0') {
  2214. X        fprintf (fp, "Distribution: %s\n", note_h_distrib);
  2215. X        start_line_offset++;
  2216. X    }
  2217. X    fprintf (fp, "References: %s\n", note_h_messageid);
  2218. X
  2219. X    if (*my_org) {
  2220. X        fprintf (fp, "Organization: %s\n", my_org);
  2221. X        start_line_offset++;
  2222. X    }
  2223. X    if (*reply_to) {
  2224. X        fprintf (fp, "Reply-To: %s\n", reply_to);
  2225. X        start_line_offset++;
  2226. X    }
  2227. X    fprintf (fp, "\n");
  2228. X
  2229. X    if (copy_text) {    /* if "copy_text" */
  2230. X        if (arts[respnum].from != (char *) 0) {     
  2231. X            if (arts[respnum].name == arts[respnum].from) {     
  2232. X                fprintf (fp, txt_writes, arts[respnum].from);
  2233. X            } else {
  2234. X                fprintf (fp, txt_writes_name, arts[respnum].from, arts[respnum].name);
  2235. X            }
  2236. X        }
  2237. X        fseek (note_fp, note_mark[0], 0);
  2238. X        copy_fp (note_fp, fp, DEFAULT_COMMENT);
  2239. X    }
  2240. X
  2241. X    add_signature (fp, FALSE);
  2242. X    fclose (fp);
  2243. X
  2244. X    ch = 'e';
  2245. X    while (1) {
  2246. X        switch (ch) {
  2247. X        case 'e':
  2248. X            invoke_editor (article);
  2249. X             set_real_uid_gid ();
  2250. X            ret_code = POSTED_REDRAW;
  2251. X            break;
  2252. X
  2253. X        case 'a':
  2254. X        case ESC:
  2255. X            unlink (article);
  2256. X            clear_message ();
  2257. X            set_tin_uid_gid ();
  2258. X            return (ret_code);
  2259. X
  2260. X        case 'p':
  2261. X            wait_message (txt_posting);
  2262. X            if (submit_file (article)) {
  2263. X                ret_code = POSTED_OK;
  2264. X                info_message (txt_art_posted);
  2265. X                goto post_response_done;
  2266. X            } else {
  2267. X                rename_file (article, dead_article);
  2268. X                sprintf (buf, txt_art_rejected, dead_article);
  2269. X                info_message (buf);
  2270. X                sleep (3);
  2271. X                set_tin_uid_gid ();
  2272. X                return (ret_code);
  2273. X            }
  2274. X        }
  2275. X
  2276. X        do {
  2277. X            sprintf (msg, "%s%c", txt_abort_edit_post, ch_default);
  2278. X            wait_message (msg);
  2279. X            MoveCursor(LINES, (int) strlen (txt_abort_edit_post));
  2280. X            if ((ch = (char) ReadCh()) == CR)
  2281. X                ch = ch_default;
  2282. X        } while (ch != ESC && ch != 'a' && ch != 'e' && ch != 'p');
  2283. X    }
  2284. X
  2285. post_response_done:
  2286. X    if (*note_h_followup && strcmp(note_h_followup, "poster") != 0) {
  2287. X        find_mail_header (HEADER_SUBJECT, article, note_h_subj);
  2288. X        update_art_posted_file (note_h_followup, note_h_subj);
  2289. X    } else {
  2290. X        find_mail_header (HEADER_SUBJECT, article, note_h_subj);
  2291. X        update_art_posted_file (note_h_newsgroups, note_h_subj);
  2292. X    }
  2293. X
  2294. X    set_real_uid_gid ();
  2295. X    unlink (article);
  2296. X    set_tin_uid_gid ();
  2297. X
  2298. X    return (ret_code);
  2299. }
  2300. X
  2301. X
  2302. int mail_to_someone (address)
  2303. X    char *address;
  2304. {
  2305. X    char nam[100];
  2306. X    char ch, ch_default = 's';
  2307. X    char buf[LEN];
  2308. X    char mail_to[LEN];
  2309. X    FILE *fp;
  2310. X    int redraw_screen = FALSE;
  2311. SHAR_EOF
  2312. true || echo 'restore of post.c failed'
  2313. fi
  2314. echo 'End of tin1.1 part 7'
  2315. echo 'File post.c is continued in part 8'
  2316. echo 8 > _shar_seq_.tmp
  2317. exit 0
  2318.  
  2319. --
  2320. NAME   Iain Lea
  2321. EMAIL  iain%estevax.uucp@unido.Informatik.Uni-Dortmund.DE
  2322. SNAIL  Bruecken Strasse 12, 8500 Nuernberg 90, Germany
  2323. PHONE  +49-911-331963 (home)  +49-911-3089-407 (work)
  2324. -- 
  2325.  Dr. med. dipl.-math Dieter Becker           Tel.: (0 / +49) 6841 - 16 3046
  2326.  Medizinische Universitaets- und Poliklinik  Fax.: (0 / +49) 6841 - 16 3369
  2327.  Innere Medizin III                         
  2328.  D - 6650 Homburg / Saar                     Email: becker@med-in.uni-sb.de
  2329. exit 0 # Just in case...
  2330.