home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume29 / tin / part08 < prev    next >
Encoding:
Text File  |  1992-03-27  |  50.4 KB  |  2,255 lines

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