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

  1. Newsgroups: comp.sources.misc
  2. From: iain%anl433.uucp@Germany.EU.net (Iain Lea)
  3. Subject:  v31i011:  tin - threaded full screen newsreader v1.1 PL4, Part11/15
  4. Message-ID: <1992Jul7.181932.7800@sparky.imd.sterling.com>
  5. X-Md4-Signature: aa53262013c4b711670dda375f1320aa
  6. Date: Tue, 7 Jul 1992 18:19:32 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: iain%anl433.uucp@Germany.EU.net (Iain Lea)
  10. Posting-number: Volume 31, Issue 11
  11. Archive-name: tin/part11
  12. Environment: BSD, SCO, ISC, SUNOS, SYSVR3, SYSVR4, ULTRIX, XENIX
  13. Supersedes: tin: Volume 30, Issue 1-14
  14.  
  15. #! /bin/sh
  16. # This is a shell archive.  Remove anything before this line, then feed it
  17. # into a shell via "sh file" or similar.  To overwrite existing files,
  18. # type "sh file -c".
  19. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  20. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  21. # Contents:  feed.c help.c open.c spooldir.c
  22. # Wrapped by kent@sparky on Mon Jun 29 23:35:14 1992
  23. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  24. echo If this archive is complete, you will see the following message:
  25. echo '          "shar: End of archive 11 (of 15)."'
  26. if test -f 'feed.c' -a "${1}" != "-c" ; then 
  27.   echo shar: Will not clobber existing file \"'feed.c'\"
  28. else
  29.   echo shar: Extracting \"'feed.c'\" \(14656 characters\)
  30.   sed "s/^X//" >'feed.c' <<'END_OF_FILE'
  31. X/*
  32. X *  Project   : tin - a threaded Netnews reader
  33. X *  Module    : feed.c
  34. X *  Author    : I.Lea
  35. X *  Created   : 31-08-91
  36. X *  Updated   : 18-06-92
  37. X *  Notes     : provides same interface to mail,pipe,print and save commands
  38. X *  Copyright : (c) Copyright 1991-92 by Iain Lea
  39. X *              You may  freely  copy or  redistribute  this software,
  40. X *              so  long as there is no profit made from its use, sale
  41. X *              trade or  reproduction.  You may not change this copy-
  42. X *              right notice, and it must be included in any copy made
  43. X */
  44. X
  45. X#include    "tin.h"
  46. X
  47. Xextern char *glob_group;            /* Group name */
  48. Xextern char note_h_date[LEN];        /* Date:    */
  49. Xextern char note_h_newsgroups[LEN];    /* Newsgroups:    */
  50. Xextern char note_h_subj[LEN];        /* Subject:    */
  51. Xextern FILE *note_fp;                /* the body of the current article */
  52. Xextern int note_end;                /* end of article ? */
  53. Xextern int note_page;                /* what page we're on */
  54. Xextern long note_mark[MAX_PAGES];    /* ftells on beginnings of pages */
  55. X
  56. Xchar default_mail_address[LEN];
  57. Xchar default_pipe_command[LEN];
  58. Xchar default_save_file[PATH_LEN];
  59. Xchar default_regex_pattern[LEN];
  60. Xchar default_crosspost_group[LEN];
  61. Xchar proc_ch_default;                /* set in change_rcfile () */
  62. X
  63. X
  64. Xvoid feed_articles (function, level, prompt, respnum, group_path)
  65. X    int function;
  66. X    int level;
  67. X    char *prompt;
  68. X    int respnum;
  69. X    char *group_path;
  70. X{
  71. X#ifndef INDEX_DAEMON
  72. X
  73. X    char address[LEN];
  74. X    char command[LEN];
  75. X    char filename[PATH_LEN], *p;
  76. X    char group[LEN];
  77. X    char mailbox[LEN];
  78. X    char pattern[LEN];
  79. X    char ch = 'a', ch_default = 'a';
  80. X    char proc_ch = proc_ch_default;
  81. X    FILE *fp = (FILE *) 0;
  82. X    int b, i, j;
  83. X    int confirm = TRUE;
  84. X    int processed_ok = TRUE;
  85. X    int proceed = FALSE;
  86. X    int is_mailbox = FALSE;
  87. X    int orig_note_end = 0;
  88. X    int orig_note_page = 0;
  89. X    int processed = 0;
  90. X    int ret1 = FALSE;
  91. X    int ret2 = FALSE;
  92. X    int redraw_screen = FALSE;
  93. X    
  94. X    if (level == PAGE_LEVEL) {
  95. X        orig_note_end = note_end;
  96. X        orig_note_page = note_page;
  97. X    }
  98. X
  99. X    b = which_thread (respnum);
  100. X
  101. X    /*
  102. X     * try and work out what default the user wants
  103. X     */
  104. X    if (num_of_tagged_arts) {
  105. X        ch_default = 'T';
  106. X    } else if (num_of_hot_arts) {
  107. X        ch_default = 'h';
  108. X    } else if (num_of_responses (b)) {
  109. X        ch_default = 't';
  110. X    }
  111. X
  112. X    if ((save_archive_name == FALSE || arts[respnum].archive == (char *) 0) ||
  113. X        (save_archive_name == TRUE && function != FEED_SAVE) ||
  114. X        ch_default == 'T') {
  115. X        do {
  116. X            sprintf (msg, "%s%s%c", prompt, txt_art_thread_regex_tag, ch_default);
  117. X            wait_message (msg);
  118. X            MoveCursor (LINES, (int) strlen (msg)-1);
  119. X            if ((ch = (char) ReadCh ()) == CR)
  120. X                ch = ch_default;
  121. X        } while (ch != ESC && ch != 'a' && ch != 't' && ch != 'T' && 
  122. X            ch != 'h' && ch != 'p' && ch != 'q');
  123. X    } else {
  124. X        filename[0] = '\0';
  125. X        ch = ch_default;
  126. X        if (proc_ch != 'n') {
  127. X            if (str_str (glob_group, "sources", 7)) {
  128. X                proc_ch = 's';        /* *source* group */ 
  129. X            } else if (str_str (glob_group, "binaries", 8)) {
  130. X                proc_ch = 'u';        /* *binaries* group */
  131. X            } else {
  132. X                proc_ch = 's';
  133. X            }
  134. X        }    
  135. X    }
  136. X
  137. X    if (ch == 'q' || ch == ESC) {    /* exit */
  138. X        clear_message ();
  139. X        return;
  140. X    }
  141. X    
  142. X    if (ch == 'p') {
  143. X        sprintf (msg, txt_feed_pattern, default_regex_pattern);
  144. X        if (! prompt_string (msg, pattern)) {
  145. X            clear_message ();
  146. X            return;
  147. X        }    
  148. X        if (strlen (pattern)) {
  149. X            my_strncpy (default_regex_pattern, pattern, 
  150. X                sizeof (default_regex_pattern));
  151. X        } else {
  152. X            if (default_regex_pattern[0]) {
  153. X                my_strncpy (pattern, default_regex_pattern, 
  154. X                    sizeof (default_regex_pattern));
  155. X            } else {
  156. X                info_message (txt_no_match);
  157. X                return;
  158. X            }
  159. X        }
  160. X    }
  161. X
  162. X    switch (function) {
  163. X        case FEED_MAIL:
  164. X            sprintf (msg, txt_mail_art_to, 
  165. X                COLS-(strlen(txt_mail_art_to)+30), default_mail_address);
  166. X            if (! prompt_string (msg, address)) {
  167. X                clear_message ();
  168. X                return;
  169. X            }    
  170. X            if (strlen (address)) {
  171. X                strcpy (default_mail_address, address);
  172. X            } else {
  173. X                if (default_mail_address[0]) {
  174. X                    strcpy (address, default_mail_address);
  175. X                } else {
  176. X                    info_message (txt_no_mail_address);    
  177. X                    return;
  178. X                }
  179. X            }
  180. X            break;
  181. X        case FEED_PIPE:
  182. X            sprintf (msg, txt_pipe_to_command, 
  183. X                COLS-(strlen(txt_pipe_to_command)+30), default_pipe_command);
  184. X            if (! prompt_string (msg, command)) {
  185. X                clear_message ();
  186. X                return;
  187. X            }
  188. X            if (strlen (command)) {
  189. X                strcpy (default_pipe_command, command);
  190. X            } else {
  191. X                if (default_pipe_command[0]) {
  192. X                    strcpy (command, default_pipe_command);
  193. X                } else {
  194. X                    info_message (txt_no_command);    
  195. X                    return;
  196. X                }
  197. X            }
  198. X
  199. X            if ((fp = (FILE *) popen (command, "w")) == NULL) {
  200. X                perror_message (txt_command_failed_s, command);
  201. X                return;
  202. X            }
  203. X            wait_message (txt_piping);
  204. X            Raw (FALSE);
  205. X            break;
  206. X        case FEED_PRINT:    
  207. X            if (default_printer) {
  208. X#ifdef sinix
  209. X                    sprintf (command, "%s -dru=%s %s",
  210. X                        printer, get_val ("PRINTER","ps"), redirect_output);
  211. X#else
  212. X                    sprintf (command, "%s -P%s %s",
  213. X                        printer, get_val ("PRINTER","ps"), redirect_output);
  214. X#endif
  215. X            } else {
  216. X                if (cmd_line_printer[0]) {
  217. X                    sprintf (command, "%s %s",
  218. X                        cmd_line_printer, redirect_output);
  219. X                } else {
  220. X                    sprintf (command, "%s %s",
  221. X                        printer, redirect_output);
  222. X                }
  223. X            }
  224. X            break;
  225. X        case FEED_SAVE:        /* ask user for filename */
  226. X            free_save_array ();
  227. X            if ((save_archive_name == FALSE || arts[respnum].archive == (char *) 0)) {
  228. X                sprintf (msg, txt_save_filename, default_save_file);
  229. X                if (! prompt_string (msg, filename)) {
  230. X                    clear_message ();
  231. X                    return;
  232. X                }
  233. X                if (strlen (filename)) {
  234. X                    my_strncpy (default_save_file, filename,
  235. X                        sizeof (default_save_file));
  236. X                } else {
  237. X                    if (default_save_file[0]) {
  238. X                        my_strncpy (filename, default_save_file,
  239. X                            sizeof (filename));
  240. X                    } else {
  241. X                        info_message (txt_no_filename);    
  242. X                        return;
  243. X                    }
  244. X                }
  245. X                for (p = filename; *p && (*p == ' ' || *p == '\t'); p++) {
  246. X                    continue;
  247. X                }
  248. X                if (! *p) {
  249. X                    info_message (txt_no_filename);
  250. X                    return;
  251. X                }
  252. X                if ((filename[0] == '~' || filename[0] == '+') && strlen (filename) == 1) {
  253. X                    info_message (txt_no_filename);
  254. X                    return;
  255. X                }
  256. X                is_mailbox = create_path (filename);
  257. X                if (is_mailbox) {
  258. X                    if ((int) strlen (filename) > 1) {
  259. X                        my_strncpy (mailbox, filename+1, sizeof (mailbox));        
  260. X                    } else {
  261. X                        my_strncpy (mailbox, glob_group, sizeof (mailbox));
  262. X                        /*
  263. X                         *  convert 1st letter to uppercase
  264. X                         */
  265. X                        if (mailbox[0] >= 'a' && mailbox[0] <= 'z') {
  266. X                            mailbox[0] = mailbox[0] - 32;
  267. X                        }
  268. X                    }
  269. X                    my_strncpy (filename, mailbox, sizeof (filename));
  270. X                } else {        /* ask for post processing type */
  271. X                    do {
  272. X                        sprintf (msg, "%s%c", txt_post_process_type, proc_ch_default);
  273. X                        wait_message (msg);
  274. X                        MoveCursor (LINES, (int) strlen (msg)-1);
  275. X                        if ((proc_ch = (char) ReadCh ()) == CR)
  276. X                            proc_ch = proc_ch_default;
  277. X                    } while (proc_ch != 'n' && proc_ch != 's' &&
  278. X                         proc_ch != 'u' && proc_ch != 'U');
  279. X                }
  280. X            }
  281. X            clear_message ();
  282. X            break;
  283. X        case FEED_XPOST:    /* ask user for newsgroups */
  284. X            sprintf (msg, txt_crosspost_group, default_crosspost_group);
  285. X    
  286. X            if (! prompt_string (msg, group)) {
  287. X                clear_message ();
  288. X                return;
  289. X            }
  290. X
  291. X            if (strlen (group)) {
  292. X                my_strncpy (default_crosspost_group, group,
  293. X                    sizeof (default_crosspost_group));
  294. X            } else {
  295. X                if (default_crosspost_group[0]) {
  296. X                    my_strncpy (group, default_crosspost_group, 
  297. X                        sizeof (group));
  298. X                } else {
  299. X                    info_message (txt_no_group);
  300. X                    return;
  301. X                }
  302. X            }
  303. X            break;
  304. X    }
  305. X    
  306. X    switch (ch) {
  307. X        case 'a':        /* article */
  308. X            if (level == GROUP_LEVEL) {
  309. X                note_page = art_open (arts[respnum].artnum, group_path);    
  310. X                if (note_page == ART_UNAVAILABLE) {
  311. X                    break;
  312. X                }
  313. X            }
  314. X            switch (function) {
  315. X                case FEED_MAIL:
  316. X                    redraw_screen = mail_to_someone (address, FALSE, TRUE, &processed_ok);
  317. X                    break;
  318. X                case FEED_PIPE:
  319. X                    fseek (note_fp, 0L, 0);
  320. X                    copy_fp (note_fp, fp, "");
  321. X                    break;
  322. X                case FEED_PRINT:
  323. X                    processed_ok = print_file (command, respnum, 1);
  324. X                    break;
  325. X                case FEED_SAVE:
  326. X                    wait_message (txt_saving);
  327. X                    add_to_save_list (0, &arts[respnum], is_mailbox, filename);
  328. X                    processed_ok = save_art_to_file (respnum, 0, FALSE, "");
  329. X                    break;
  330. X                case FEED_XPOST:
  331. X                    redraw_screen = crosspost_article (group, respnum);
  332. X                    break;
  333. X            }
  334. X            if (processed_ok) {
  335. X                processed++;
  336. X            }    
  337. X            if (mark_saved_read) {
  338. X                if (processed_ok) {
  339. X                    arts[respnum].unread = ART_READ;
  340. X                }
  341. X            }
  342. X            if (level == GROUP_LEVEL) {
  343. X                art_close ();
  344. X            }
  345. X            break;
  346. X            
  347. X        case 't':         /* thread */
  348. X            confirm = TRUE;
  349. X            for (i = (int) base[b]; i >= 0; i = arts[i].thread) {
  350. X                if (level == PAGE_LEVEL) {
  351. X                    art_close ();
  352. X                }
  353. X                note_page = art_open (arts[i].artnum, group_path);    
  354. X                if (note_page == ART_UNAVAILABLE) {
  355. X                    continue;
  356. X                }    
  357. X                switch (function) {
  358. X                    case FEED_MAIL:
  359. X                        processed_ok = TRUE;    
  360. X                        mail_to_someone (address, FALSE, confirm, &processed_ok);
  361. X                        confirm = FALSE;
  362. X                        break;
  363. X                    case FEED_PIPE:
  364. X                        fseek (note_fp, 0L, 0);
  365. X                        copy_fp (note_fp, fp, "");
  366. X                        break;
  367. X                    case FEED_PRINT:
  368. X                        processed_ok = print_file (command, i, processed+1);
  369. X                        break;
  370. X                    case FEED_SAVE:
  371. X                        add_to_save_list (i, &arts[i], is_mailbox, filename);
  372. X                        break;
  373. X                    case FEED_XPOST:
  374. X                        redraw_screen = crosspost_article (group, i);
  375. X                        break;
  376. X                }
  377. X                if (processed_ok) {
  378. X                    processed++;
  379. X                }
  380. X                if (mark_saved_read) {
  381. X                    if (processed_ok) {
  382. X                        arts[i].unread = ART_READ;
  383. X                    }    
  384. X                }
  385. X                art_close ();
  386. X            }
  387. X            if (function == FEED_SAVE) {
  388. X                sort_save_list ();
  389. X                (void) save_thread_to_file (is_mailbox, group_path);
  390. X            }
  391. X            break;
  392. X
  393. X        case 'T':         /* tagged articles */
  394. X            confirm = TRUE;
  395. X            for (i=1 ; i <= num_of_tagged_arts ; i++) {
  396. X                for (j=0 ; j < top ; j++) {
  397. X                    if (arts[j].tagged && arts[j].tagged == i) { 
  398. X                        if (level == PAGE_LEVEL) {
  399. X                            art_close ();
  400. X                        }
  401. X                        note_page = art_open (arts[j].artnum, group_path);    
  402. X                        if (note_page == ART_UNAVAILABLE) {
  403. X                            continue;
  404. X                        }    
  405. X                        switch (function) {
  406. X                            case FEED_MAIL:
  407. X                                processed_ok = TRUE;
  408. X                                mail_to_someone (address, FALSE, confirm, &processed_ok);
  409. X                                confirm = FALSE;
  410. X                                break;
  411. X                            case FEED_PIPE:
  412. X                                fseek (note_fp, 0L, 0);
  413. X                                copy_fp (note_fp, fp, "");
  414. X                                break;
  415. X                            case FEED_PRINT:
  416. X                                processed_ok = print_file (command, j, processed+1);
  417. X                                break;
  418. X                            case FEED_SAVE:
  419. X                                add_to_save_list (j, &arts[j], is_mailbox, filename);
  420. X                                break;
  421. X                            case FEED_XPOST:
  422. X                                redraw_screen = crosspost_article (group, j);
  423. X                                break;
  424. X                        }
  425. X                        if (processed_ok) {
  426. X                            processed++;
  427. X                        }    
  428. X                        if (mark_saved_read) {
  429. X                            if (processed_ok) {
  430. X                                arts[j].unread = ART_READ;
  431. X                            }    
  432. X                        }
  433. X                        art_close ();
  434. X                    }
  435. X                }
  436. X            }
  437. X            if (function == FEED_SAVE) {                
  438. X                (void) save_regex_arts (is_mailbox, group_path);
  439. X            }
  440. X            untag_all_articles ();
  441. X            break;
  442. X
  443. X        case 'h':         /* hot (auto-selected) articles */
  444. X        case 'p':         /* regex pattern matched articles */
  445. X            confirm = TRUE;
  446. X            for (i = 0 ; i < top_base ; i++) {
  447. X                for (j = (int) base[i]; j >= 0; j = arts[j].thread) {
  448. X                    if (ch == 'p') {
  449. X                        if (STR_MATCH(arts[j].subject, pattern)) {
  450. X                            proceed = TRUE;
  451. X                        }
  452. X                    } else if (arts[j].hot) {
  453. X                        proceed = TRUE;
  454. X                    }                
  455. X                    if (proceed) {
  456. X                        proceed = FALSE;
  457. X                        if (level == PAGE_LEVEL) {
  458. X                            art_close ();
  459. X                        }
  460. X                        note_page = art_open (arts[j].artnum, group_path);    
  461. X                        if (note_page == ART_UNAVAILABLE) {
  462. X                            continue;
  463. X                        }    
  464. X                        switch (function) {
  465. X                            case FEED_MAIL:
  466. X                                processed_ok = TRUE;
  467. X                                mail_to_someone (address, FALSE, confirm, &processed_ok);
  468. X                                /* confirm = FALSE; */
  469. X                                break;
  470. X                            case FEED_PIPE:
  471. X                                fseek (note_fp, 0L, 0);
  472. X                                copy_fp (note_fp, fp, "");
  473. X                                break;
  474. X                            case FEED_PRINT:
  475. X                                processed_ok = print_file (command, j, processed+1);
  476. X                                break;
  477. X                            case FEED_SAVE:
  478. X                                sprintf (filename, "%s.%02d", filename, processed+1);
  479. X                                add_to_save_list (0, &arts[j], is_mailbox, filename);
  480. X                                processed_ok = save_art_to_file (respnum, 0, FALSE, "");
  481. X                                break;
  482. X                            case FEED_XPOST:
  483. X                                redraw_screen = crosspost_article (group, j);
  484. X                                break;
  485. X                        }
  486. X                        if (processed_ok) {
  487. X                            processed++;
  488. X                        }    
  489. X                        if (mark_saved_read) {
  490. X                            if (processed_ok) {
  491. X                                arts[j].unread = ART_READ;
  492. X                                if (ch == 'h') {
  493. X                                    arts[j].hot = FALSE;
  494. X                                    num_of_hot_arts--;
  495. X                                }    
  496. X                            }    
  497. X                        }
  498. X                         art_close ();
  499. X                    }
  500. X                }    
  501. X            }
  502. X            break;
  503. X    }
  504. X
  505. X    redraw_screen = mail_check ();    /* in case of sending to oneself */
  506. X
  507. X    switch (function) {
  508. X        case FEED_PIPE:
  509. X            pclose (fp);        
  510. X            Raw (TRUE);
  511. X            continue_prompt ();
  512. X            redraw_screen = TRUE;
  513. X            break;
  514. X        case FEED_SAVE:
  515. X            if (proc_ch != 'n' && is_mailbox == FALSE) {
  516. X                ret2 = post_process_files (proc_ch);
  517. X            }
  518. X            free_save_array ();
  519. X            break;
  520. X    }
  521. X
  522. X    if (level == GROUP_LEVEL) {
  523. X        ret1 = (mark_saved_read ? TRUE : FALSE);
  524. X    }
  525. X    if ((ret1 || ret2) && is_mailbox == FALSE) {
  526. X        redraw_screen = TRUE;
  527. X    }
  528. X
  529. X    if (level == PAGE_LEVEL) {
  530. X        if (ch != 'a') {
  531. X            note_page = art_open (arts[respnum].artnum, group_path);
  532. X        }
  533. X        note_end = orig_note_end;
  534. X        note_page = orig_note_page;
  535. X        fseek (note_fp, note_mark[note_page], 0);
  536. X        if (redraw_screen) {
  537. X            if (note_page == 0) {
  538. X                show_note_page (respnum, glob_group);
  539. X            } else {
  540. X                redraw_page (respnum, glob_group);
  541. X            }
  542. X        } else {
  543. X            if (function == FEED_PIPE) {
  544. X                clear_message ();
  545. X            }
  546. X        }
  547. X    } else {
  548. X        if (redraw_screen) {
  549. X            show_group_page (glob_group);
  550. X        }
  551. X    }
  552. X    if (function == FEED_MAIL) {    
  553. X        sprintf (msg, txt_mailed, processed);
  554. X        info_message (msg);
  555. X    } else if (function == FEED_PRINT) {    
  556. X        sprintf (msg, txt_printed, processed);
  557. X        info_message (msg);
  558. X    } else if (function == FEED_SAVE) {    
  559. X        if (ch == 'a') {
  560. X            sprintf (msg, txt_saved, processed);
  561. X            info_message (msg);
  562. X        }    
  563. X    }
  564. X
  565. X#endif /* INDEX_DAEMON */
  566. X}
  567. X
  568. X
  569. Xint print_file (command, respnum, count)
  570. X    char *command;
  571. X    int respnum;
  572. X    int count;
  573. X{
  574. X    FILE *fp;
  575. X                                
  576. X    sprintf (msg, "%s%d", txt_printing, count);
  577. X    wait_message (msg);
  578. X    
  579. X    if ((fp = (FILE *) popen (command, "w")) == NULL) {
  580. X        perror_message (txt_command_failed_s, command);
  581. X        return FALSE;
  582. X    }
  583. X
  584. X    if (print_header) {
  585. X        fseek(note_fp, 0L, 0);
  586. X    } else {
  587. X        fprintf (fp, "Newsgroups: %s\n", note_h_newsgroups);
  588. X        if (arts[respnum].from == arts[respnum].name) {
  589. X            fprintf (fp, "From: %s\n", arts[respnum].from);
  590. X        } else {
  591. X            fprintf (fp, "From: %s (%s)\n",
  592. X                arts[respnum].from, arts[respnum].name);
  593. X        }        
  594. X        fprintf (fp, "Subject: %s\n", note_h_subj);
  595. X        fprintf (fp, "Date: %s\n\n", note_h_date);
  596. X        fseek (note_fp, note_mark[0], 0);
  597. X    }
  598. X    copy_fp (note_fp, fp, "");
  599. X
  600. X    pclose (fp);
  601. X    
  602. X    return (TRUE);    /* a hack that will check if file was really checked later */
  603. X}                        
  604. END_OF_FILE
  605.   if test 14656 -ne `wc -c <'feed.c'`; then
  606.     echo shar: \"'feed.c'\" unpacked with wrong size!
  607.   fi
  608.   # end of 'feed.c'
  609. fi
  610. if test -f 'help.c' -a "${1}" != "-c" ; then 
  611.   echo shar: Will not clobber existing file \"'help.c'\"
  612. else
  613.   echo shar: Extracting \"'help.c'\" \(5901 characters\)
  614.   sed "s/^X//" >'help.c' <<'END_OF_FILE'
  615. X/*
  616. X *  Project   : tin - a threaded Netnews reader
  617. X *  Module    : help.c
  618. X *  Author    : I.Lea
  619. X *  Created   : 01-04-91
  620. X *  Updated   : 20-06-92
  621. X *  Notes     :
  622. X *  Copyright : (c) Copyright 1991-92 by Iain Lea
  623. X *              You may  freely  copy or  redistribute  this software,
  624. X *              so  long as there is no profit made from its use, sale
  625. X *              trade or  reproduction.  You may not change this copy-
  626. X *              right notice, and it must be included in any copy made
  627. X */
  628. X
  629. X#include    "tin.h"
  630. X
  631. Xchar *help_select[] = {
  632. X    txt_help_g_4,
  633. X    txt_help_ctrl_d,
  634. X    txt_help_ctrl_f,
  635. X    txt_help_ctrl_l,
  636. X    txt_help_g_ctrl_k,
  637. X    txt_help_g_ctrl_r,
  638. X    txt_help_g_cr,
  639. X    txt_help_g_tab,
  640. X    txt_help_b,
  641. X    txt_help_bug_report,
  642. X    txt_help_sel_c,
  643. X    txt_help_g,
  644. X    txt_help_j,
  645. X    txt_help_h,
  646. X    txt_help_I,
  647. X    txt_help_g_l,
  648. X    txt_help_m,
  649. X    txt_help_M,
  650. X    txt_help_n,
  651. X    txt_help_g_q,
  652. X    txt_help_s,
  653. X    txt_help_S,
  654. X    txt_help_v,
  655. X    txt_help_w,
  656. X    txt_help_W,
  657. X    txt_help_g_y,
  658. X    txt_help_y,
  659. X    txt_help_g_z,
  660. X    txt_help_g_search,
  661. X#ifndef NO_SHELL_ESCAPE
  662. X    txt_help_shell,
  663. X#endif
  664. X    (char *) 0
  665. X};
  666. X
  667. Xchar *help_spooldir[] = {
  668. X    txt_help_4,
  669. X    txt_help_ctrl_d,
  670. X    txt_help_ctrl_f,
  671. X    txt_help_ctrl_l,
  672. X    txt_help_cr,
  673. X    txt_help_b,
  674. X    txt_help_bug_report,
  675. X    txt_help_h,
  676. X    txt_help_I,
  677. X    txt_help_j,
  678. X    txt_help_i,
  679. X    txt_help_q,
  680. X    txt_help_v,
  681. X    (char *) 0
  682. X};
  683. X
  684. Xchar *help_group[] = {
  685. X    txt_help_i_4,
  686. X    txt_help_ctrl_d,
  687. X    txt_help_ctrl_f,
  688. X    txt_help_ctrl_k,
  689. X    txt_help_ctrl_l,
  690. X    txt_help_i_cr,
  691. X    txt_help_i_tab,
  692. X    txt_help_a,
  693. X    txt_help_b,
  694. X    txt_help_bug_report,
  695. X    txt_help_c,
  696. X    txt_help_d,
  697. X    txt_help_g,
  698. X    txt_help_h,
  699. X    txt_help_I,
  700. X    txt_help_j,
  701. X    txt_help_K,
  702. X    txt_help_l,
  703. X    txt_help_p_m,
  704. X    txt_help_M,
  705. X    txt_help_o,
  706. X    txt_help_i_n,
  707. X    txt_help_i_p,
  708. X    txt_help_i,
  709. X    txt_help_q,
  710. X    txt_help_r,
  711. X    txt_help_p_s,
  712. X    txt_help_T,
  713. X    txt_help_u,
  714. X    txt_help_U,
  715. X    txt_help_v,
  716. X    txt_help_w,
  717. X    txt_help_W,
  718. X    txt_help_x,
  719. X    txt_help_p_z,
  720. X    txt_help_i_search,
  721. X#ifndef NO_SHELL_ESCAPE
  722. X    txt_help_shell,
  723. X#endif
  724. X    txt_help_dash,
  725. X    txt_help_pipe,
  726. X    txt_help_i_star,
  727. X    txt_help_i_dot,
  728. X    txt_help_i_coma,
  729. X    txt_help_i_tilda,
  730. X    txt_help_X,
  731. X    txt_help_plus,
  732. X    txt_help_equal,
  733. X    txt_help_semicolon,
  734. X    (char *) 0
  735. X};
  736. X
  737. Xchar *help_thread[] = {
  738. X    txt_help_t_0,
  739. X    txt_help_t_4,
  740. X    txt_help_ctrl_d,
  741. X    txt_help_ctrl_f,
  742. X    txt_help_ctrl_l,
  743. X    txt_help_t_cr,
  744. X    txt_help_p_tab,
  745. X    txt_help_b,
  746. X    txt_help_bug_report,
  747. X    txt_help_d,
  748. X    txt_help_h,
  749. X    txt_help_I,
  750. X    txt_help_j,
  751. X    txt_help_ck,
  752. X    txt_help_i,
  753. X    txt_help_q,
  754. X    txt_help_T,
  755. X    txt_help_v,
  756. X    txt_help_p_z,
  757. X    (char *) 0
  758. X};
  759. X
  760. Xchar *help_page[] = {
  761. X    txt_help_p_0,
  762. X    txt_help_p_4,
  763. X    txt_help_ctrl_d,
  764. X    txt_help_ctrl_f,
  765. X    txt_help_ctrl_h,
  766. X    txt_help_ctrl_k,
  767. X    txt_help_ctrl_l,
  768. X    txt_help_p_ctrl_r,
  769. X    txt_help_p_cr,
  770. X    txt_help_p_tab,
  771. X    txt_help_b,
  772. X    txt_help_a,
  773. X    txt_help_bug_report,
  774. X    txt_help_c,
  775. X    txt_help_C,
  776. X    txt_help_p_d,
  777. X    txt_help_p_f,
  778. X    txt_help_p_g,
  779. X    txt_help_h,
  780. X    txt_help_I,
  781. X    txt_help_p_k,
  782. X    txt_help_p_m,
  783. X    txt_help_M,
  784. X    txt_help_p_n,
  785. X    txt_help_o,
  786. X    txt_help_p_p,
  787. X    txt_help_i,
  788. X    txt_help_q,
  789. X    txt_help_p_r,
  790. X    txt_help_p_s,
  791. X    txt_help_t,
  792. X    txt_help_T,
  793. X    txt_help_v,
  794. X    txt_help_w,
  795. X    txt_help_W,
  796. X    txt_help_x,
  797. X    txt_help_p_z,
  798. X    txt_help_p_search,
  799. X#ifndef NO_SHELL_ESCAPE
  800. X    txt_help_shell,
  801. X#endif
  802. X    txt_help_dash,
  803. X    txt_help_pipe,
  804. X    txt_help_thread,
  805. X    txt_help_p_star,
  806. X    txt_help_p_dot,
  807. X    txt_help_p_coma,
  808. X    txt_help_p_tilda,
  809. X    (char *) 0
  810. X};
  811. X
  812. X
  813. Xvoid show_info_page (type, help, title)
  814. X    int type; 
  815. X    char *help[];
  816. X    char *title;
  817. X{
  818. X    char buf[LEN];
  819. X    char ch;
  820. X    int i, len;
  821. X    int group_len = 0;
  822. X    int old_page = 0;
  823. X    int cur_page = 1;
  824. X    int max_page = 1;
  825. X    int pos_help = 0;
  826. X
  827. X    if (NOTESLINES <= 0) {
  828. X        return;
  829. X    }
  830. X
  831. X    /*
  832. X     *  find how many elements in array
  833. X     */
  834. X    if (type == HELP_INFO) {
  835. X        for (i=0 ; help[i] ; i++) {
  836. X            continue;
  837. X        }
  838. X    } else {
  839. X        for (i=0 ; posted[i].date[0] ; i++) {
  840. X            len = strlen (posted[i].group);
  841. X            if (len > group_len) {
  842. X                 group_len = len;
  843. X            }
  844. X         }
  845. X    }
  846. X    
  847. X    max_page = i / NOTESLINES;
  848. X    if (i % NOTESLINES) {
  849. X        max_page++;
  850. X    }
  851. X
  852. X    while (1) {
  853. X        if (cur_page != old_page) {
  854. X            ClearScreen ();
  855. X            sprintf (buf, title, cur_page, max_page);
  856. X            center_line (0, TRUE, buf);
  857. X            MoveCursor (INDEX_TOP, 0);
  858. X
  859. X            if (type == HELP_INFO) { 
  860. X                for (i=pos_help ; i < (pos_help + NOTESLINES) && help[i] ; i++) {
  861. X                    fputs (help[i], stdout);
  862. X                }
  863. X            } else {
  864. X                for (i=pos_help ; i < (pos_help + NOTESLINES) && posted[i].date[0] ; i++) {
  865. X                    sprintf (msg, "%8s  %c  %-*s  %s",
  866. X                        posted[i].date, posted[i].action,  
  867. X                        group_len, posted[i].group, posted[i].subj);
  868. X                        msg[COLS-2] = '\0';
  869. X                    printf ("%s\r\n", msg);
  870. X                }
  871. X            }
  872. X        }
  873. X
  874. X        if (cur_page != old_page) {
  875. X            center_line (LINES, FALSE, txt_hit_space_for_more);
  876. X        }
  877. X
  878. X        old_page = cur_page;
  879. X        
  880. X        ch = (char) ReadCh ();
  881. X        switch (ch) {
  882. X            case ESC:    /* common arrow keys */
  883. X                switch (get_arrow_key ()) {
  884. X                    case KEYMAP_UP:
  885. X                    case KEYMAP_PAGE_UP:
  886. X                        if (cur_page > 1) {
  887. X                            cur_page--;
  888. X                            pos_help = (cur_page-1)*NOTESLINES;
  889. X                        }
  890. X                        break;
  891. X
  892. X                    case KEYMAP_DOWN:
  893. X                    case KEYMAP_PAGE_DOWN:
  894. X                        if (cur_page < max_page) {
  895. X                            pos_help = cur_page*NOTESLINES;
  896. X                            cur_page++;
  897. X                        }
  898. X                        break;
  899. X
  900. X                    case KEYMAP_HOME:
  901. X                        if (cur_page != 1) {
  902. X                            cur_page = 1;
  903. X                            pos_help = 0;
  904. X                        }
  905. X                        break;
  906. X                    
  907. X                    case KEYMAP_END:
  908. X                        if (cur_page != max_page) {
  909. X                            cur_page = max_page;
  910. X                            pos_help = (max_page-1) * NOTESLINES;
  911. X                        }
  912. X                        break;
  913. X                }
  914. X                break;
  915. X
  916. X            case ctrl('D'):            /* page down */
  917. X            case ' ':
  918. X            case 'j':
  919. X                if (cur_page < max_page) {
  920. X                    pos_help = cur_page*NOTESLINES;
  921. X                    cur_page++;
  922. X                }
  923. X                break;
  924. X            
  925. X            case ctrl('U'):            /* page up */
  926. X            case 'b':
  927. X            case 'k':
  928. X                if (cur_page > 1) {
  929. X                    cur_page--;
  930. X                    pos_help = (cur_page-1)*NOTESLINES;
  931. X                }
  932. X                break;
  933. X
  934. X            case ctrl('R'):            /* Home */
  935. X            case 'g':
  936. X                if (cur_page != 1) {
  937. X                    cur_page = 1;
  938. X                    pos_help = 0;
  939. X                }
  940. X                break;
  941. X
  942. X            case '$':                /* End */
  943. X            case 'G':
  944. X                if (cur_page != max_page) {
  945. X                    cur_page = max_page;
  946. X                    pos_help = (max_page-1) * NOTESLINES;
  947. X                }
  948. X                break;
  949. X
  950. X            default:
  951. X#ifndef USE_CLEARSCREEN
  952. X                ClearScreen ();
  953. X#endif    
  954. X                return;
  955. X        }    
  956. X    }
  957. X}
  958. END_OF_FILE
  959.   if test 5901 -ne `wc -c <'help.c'`; then
  960.     echo shar: \"'help.c'\" unpacked with wrong size!
  961.   fi
  962.   # end of 'help.c'
  963. fi
  964. if test -f 'open.c' -a "${1}" != "-c" ; then 
  965.   echo shar: Will not clobber existing file \"'open.c'\"
  966. else
  967.   echo shar: Extracting \"'open.c'\" \(14367 characters\)
  968.   sed "s/^X//" >'open.c' <<'END_OF_FILE'
  969. X/*
  970. X *  Project   : tin - a threaded Netnews reader
  971. X *  Module    : open.c
  972. X *  Author    : I.Lea & R.Skrenta
  973. X *  Created   : 01-04-91
  974. X *  Updated   : 04-06-92
  975. X *  Notes     : reads news locally (ie. /usr/spool/news) or via NNTP
  976. X *  Copyright : (c) Copyright 1991-92 by Iain Lea & Rich Skrenta
  977. X *              You may  freely  copy or  redistribute  this software,
  978. X *              so  long as there is no profit made from its use, sale
  979. X *              trade or  reproduction.  You may not change this copy-
  980. X *              right notice, and it must be included in any copy made
  981. X */
  982. X
  983. X#include    "tin.h"
  984. X
  985. X/*
  986. X * Directory handling code - Hopefully one of these is right for you. 
  987. X */
  988. X#ifdef BSD
  989. X#    ifdef sinix
  990. X#        include <dir.h>
  991. X#    else
  992. X#        include <sys/dir.h>
  993. X#    endif
  994. X#    define        DIR_BUF        struct direct
  995. X#    define        D_LENGTH    d_namlen
  996. X#endif
  997. X#ifdef M_XENIX
  998. X#    include <sys/ndir.h>
  999. X#    define        DIR_BUF        struct direct
  1000. X#    define        D_LENGTH    d_namlen
  1001. X#endif
  1002. X#ifndef DIR_BUF
  1003. X#    include    <dirent.h>
  1004. X#    define        DIR_BUF        struct dirent
  1005. X#    define        D_LENGTH    d_reclen
  1006. X#endif
  1007. X
  1008. Xint nntp_codeno = 0;
  1009. X
  1010. X#ifdef NNTP_ABLE
  1011. Xint compiled_with_nntp = TRUE;        /* used in mail_bug_report() info */
  1012. X#else
  1013. Xint compiled_with_nntp = FALSE;
  1014. X#endif
  1015. X
  1016. X#ifdef NO_POSTING
  1017. Xint    can_post = FALSE;
  1018. X#else
  1019. Xint    can_post = TRUE;
  1020. X#endif
  1021. X
  1022. Xchar server_name[LEN];
  1023. X
  1024. X
  1025. Xvoid nntp_open ()
  1026. X{
  1027. X#ifdef NNTP_ABLE    
  1028. X    char *server;
  1029. X    int ret;
  1030. X
  1031. X    if (read_news_via_nntp) {
  1032. X        debug_nntp ("nntp_open", "BEGIN");
  1033. X
  1034. X        if (nntp_server[0]) {
  1035. X            server = nntp_server;
  1036. X        } else {
  1037. X            server = getserverbyfile (NNTP_SERVER_FILE);
  1038. X        }
  1039. X
  1040. X        if (server == (char *) 0) {
  1041. X            error_message (txt_cannot_get_nntp_server_name, "");
  1042. X            error_message (txt_server_name_in_file_env_var, NNTP_SERVER_FILE);
  1043. X            exit(1);
  1044. X        }
  1045. X
  1046. X        if (update == FALSE) {
  1047. X            sprintf (msg, txt_connecting, server);
  1048. X            wait_message (msg);
  1049. X        }
  1050. X        
  1051. X        debug_nntp ("nntp_open", server);
  1052. X
  1053. X        ret = server_init (server);
  1054. X        if (update == FALSE) {
  1055. X            fputc ('\n', stdout);
  1056. X        }
  1057. X
  1058. X        debug_nntp_respcode (ret);
  1059. X
  1060. X        switch (ret) {
  1061. X        case OK_CANPOST:
  1062. X#ifndef NO_POSTING        
  1063. X            can_post = TRUE;
  1064. X#endif            
  1065. X            break;
  1066. X
  1067. X        case OK_NOPOST:
  1068. X            can_post = FALSE;
  1069. X            break;    
  1070. X
  1071. X        case -1:
  1072. X            error_message (txt_failed_to_connect_to_server, server);
  1073. X            exit (1);
  1074. X
  1075. X        default:
  1076. X            sprintf (msg, "%s: %s", progname, nntp_respcode (ret));
  1077. X            error_message (msg, "");
  1078. X            exit (1);
  1079. X        }
  1080. X
  1081. X        /*
  1082. X         * Find out if NNTP supports my XINDEX & XUSER commands
  1083. X         */
  1084. X#ifndef NO_NNTP_EXTS     
  1085. X        debug_nntp ("nntp_open", "xindex");
  1086. X        put_server ("xindex");    
  1087. X        if (get_respcode () != ERR_COMMAND) {
  1088. X            xindex_supported = TRUE;
  1089. X        }
  1090. X        debug_nntp ("nntp_open", "xuser");
  1091. X        put_server ("xuser");    
  1092. X        if (get_respcode () != ERR_COMMAND) {
  1093. X            xuser_supported = TRUE;
  1094. X        }
  1095. X#endif    /* NO_NNTP_EXTS */        
  1096. X        
  1097. X        /*
  1098. X         * If INN NNTP & XINDEX not supported switch to mode reader
  1099. X         */
  1100. X        if (! xindex_supported) {
  1101. X            debug_nntp ("nntp_open", "mode reader");
  1102. X            put_server ("mode reader");    
  1103. X            if (get_respcode () != ERR_COMMAND) {
  1104. X                inn_nntp_server = TRUE;
  1105. X            }
  1106. X        }
  1107. X    }
  1108. X#ifndef NO_NNTP_EXTS
  1109. X    /*
  1110. X     * Find out if NNTP supports SPOOLDIR command
  1111. X     */
  1112. X    get_spooldir ();
  1113. X#endif    /* NO_NNTP_EXTS */        
  1114. X
  1115. X#endif    
  1116. X}
  1117. X
  1118. X
  1119. Xvoid nntp_close ()
  1120. X{
  1121. X#ifdef NNTP_ABLE
  1122. X    if (read_news_via_nntp) {
  1123. X        debug_nntp ("nntp_close", "END");
  1124. X        close_server ();
  1125. X    }
  1126. X#endif    
  1127. X}
  1128. X
  1129. X
  1130. XFILE *open_active_fp ()
  1131. X{
  1132. X    if (read_news_via_nntp) {
  1133. X#ifdef NNTP_ABLE
  1134. X        put_server ("list");
  1135. X        if (get_respcode () != OK_GROUPS) {
  1136. X            debug_nntp ("open_active_fp", "NOT_OK");
  1137. X            return (FILE *) 0;
  1138. X        }
  1139. X        debug_nntp ("open_active_fp", "OK");
  1140. X        return nntp_to_fp ();
  1141. X#else
  1142. X        return (FILE *) 0;
  1143. X#endif        
  1144. X    } else {
  1145. X        return fopen (active_file, "r");
  1146. X    }
  1147. X}
  1148. X
  1149. X
  1150. XFILE *open_subscription_fp ()
  1151. X{
  1152. X    if (read_news_via_nntp) {
  1153. X#ifdef NNTP_ABLE
  1154. X        put_server ("list subscriptions");
  1155. X        if (get_respcode () != OK_GROUPS) {
  1156. X            debug_nntp ("open_subscription_fp", "NOT_OK");
  1157. X            return (FILE *) 0;
  1158. X        }
  1159. X        debug_nntp ("open_subscription_fp", "OK");
  1160. X        return nntp_to_fp ();
  1161. X#else
  1162. X        return (FILE *) 0;
  1163. X#endif        
  1164. X    } else {
  1165. X        return fopen (subscriptions_file, "r");
  1166. X    }
  1167. X}
  1168. X
  1169. X
  1170. XFILE *open_newsgroups_fp ()
  1171. X{
  1172. X    if (read_news_via_nntp) {
  1173. X#ifdef NNTP_ABLE
  1174. X        put_server ("list newsgroups");
  1175. X        if (get_respcode () != OK_GROUPS) {
  1176. X            debug_nntp ("open_newsgroups_fp", "NOT_OK");
  1177. X            return (FILE *) 0;
  1178. X        }
  1179. X        debug_nntp ("open_newsgroups_fp", "OK");
  1180. X        return nntp_to_fp ();
  1181. X#else
  1182. X        return (FILE *) 0;
  1183. X#endif        
  1184. X    } else {
  1185. X        return fopen (newsgroups_file, "r");
  1186. X    }
  1187. X}
  1188. X
  1189. X
  1190. XFILE *open_index_fp (group_name)
  1191. X    char *group_name;
  1192. X{
  1193. X    char line[NNTP_STRLEN];
  1194. X    extern char index_file[PATH_LEN];
  1195. X
  1196. X    find_index_file (group_name);
  1197. X    
  1198. X    if (read_news_via_nntp && xindex_supported) {
  1199. X        sprintf (line, "xindex %s", group_name);
  1200. X        debug_nntp ("open_index_fp", line);
  1201. X        put_server (line);
  1202. X        if (get_respcode () != OK_XINDEX) {
  1203. X            debug_nntp ("open_index_fp", "NOT_OK");
  1204. X            return (FILE *) 0;
  1205. X        }
  1206. X        debug_nntp ("open_index_fp", "OK");
  1207. X        return nntp_to_fp ();
  1208. X    } else {
  1209. X        return fopen (index_file, "r");
  1210. X    }
  1211. X}
  1212. X
  1213. X
  1214. XFILE *open_art_fp (group_path, art)
  1215. X    char *group_path;
  1216. X    long art;
  1217. X{
  1218. X    char buf[LEN];
  1219. X    int respcode;
  1220. X    struct stat sb;
  1221. X    extern long note_size;
  1222. X
  1223. X    if (read_news_via_nntp) {
  1224. X#ifdef NNTP_ABLE
  1225. X        sprintf (buf, "article %ld", art);
  1226. X        debug_nntp ("open_art_fp", buf);
  1227. X        put_server (buf);
  1228. X        if ((respcode = get_respcode ()) != OK_ARTICLE) {
  1229. X            error_message ("%s", nntp_respcode (respcode));
  1230. X            debug_nntp ("open_art_fp", buf);
  1231. X            return (FILE *) 0;
  1232. X        }
  1233. X
  1234. X        debug_nntp ("open_art_fp", "OK");
  1235. X
  1236. X        return nntp_to_fp ();
  1237. X#else
  1238. X        return (FILE *) 0;
  1239. X#endif
  1240. X    } else {
  1241. X        sprintf (buf, "%s/%s/%ld", spooldir, group_path, art);
  1242. X
  1243. X        if (stat (buf, &sb) < 0) {
  1244. X            note_size = 0;
  1245. X        } else {
  1246. X            note_size = sb.st_size;
  1247. X        }
  1248. X        return fopen (buf, "r");
  1249. X    }
  1250. X}
  1251. X
  1252. X
  1253. XFILE *open_header_fp (group_path, art)
  1254. X    char *group_path;
  1255. X    long art;
  1256. X{
  1257. X    char buf[LEN];
  1258. X    
  1259. X    if (read_news_via_nntp) {
  1260. X#ifdef NNTP_ABLE    
  1261. X        sprintf(buf, "head %ld", art);
  1262. X        
  1263. X        debug_nntp ("open_header_fp", buf);
  1264. X
  1265. X        put_server (buf);
  1266. X        if (get_respcode () != OK_HEAD) {
  1267. X            debug_nntp ("open_header_fp", "NOT_OK_HEAD");
  1268. X            return (FILE *) 0;
  1269. X        }
  1270. X
  1271. X        debug_nntp ("open_header_fp", "OK_HEAD");
  1272. X
  1273. X        return nntp_to_fp ();
  1274. X#else
  1275. X        return (FILE *) 0;
  1276. X#endif        
  1277. X    } else {
  1278. X        sprintf (buf, "%s/%s/%ld", spooldir, group_path, art);
  1279. X        return fopen (buf, "r");
  1280. X    }
  1281. X}
  1282. X
  1283. X/*
  1284. X *  Longword comparison routine for the qsort()
  1285. X */
  1286. X
  1287. Xint base_comp (p1, p2)
  1288. X    char *p1;
  1289. X    char *p2;
  1290. X{
  1291. X    long *a = (long *) p1;
  1292. X    long *b = (long *) p2;
  1293. X
  1294. X    if (*a < *b)
  1295. X        return -1;
  1296. X    if (*a > *b)
  1297. X        return 1;
  1298. X    return 0;
  1299. X}
  1300. X
  1301. X
  1302. X/*
  1303. X *  Read the article numbers existing in a group's spool directory
  1304. X *  into base[] and sort them.  top_base is one past top.
  1305. X */
  1306. X
  1307. Xvoid setup_base (group, group_path)
  1308. X    char *group;
  1309. X    char *group_path;
  1310. X{
  1311. X    char buf[LEN];
  1312. X#ifdef NNTP_ABLE
  1313. X    char line[NNTP_STRLEN];
  1314. X#endif
  1315. X    DIR *d;
  1316. X    DIR_BUF *e;
  1317. X    long art, start, last, dummy, count;
  1318. X
  1319. X    top_base = 0;
  1320. X
  1321. X    if (read_news_via_nntp) {
  1322. X
  1323. X#ifdef NNTP_ABLE
  1324. X        sprintf (buf, "group %s", group);
  1325. X
  1326. X        debug_nntp ("setup_base", buf);
  1327. X        
  1328. X        put_server (buf);
  1329. X
  1330. X        if (get_server (line, NNTP_STRLEN) == -1) {
  1331. X            error_message (txt_connection_to_server_broken, "");
  1332. X            tin_done (1);
  1333. X        }
  1334. X
  1335. X        if (atoi(line) != OK_GROUP) {
  1336. X            debug_nntp ("setup_base", "NOT_OK");
  1337. X            return;
  1338. X        }
  1339. X
  1340. X        debug_nntp ("setup_base", line);
  1341. X
  1342. X        sscanf (line,"%ld %ld %ld %ld", &dummy, &count, &start, &last);
  1343. X        if (last - count > start) {
  1344. X            start = last - count;
  1345. X        }
  1346. X
  1347. X        while (start <= last) {
  1348. X            if (top_base >= max_art) {
  1349. X                expand_art();
  1350. X            }
  1351. X            base[top_base++] = start++;
  1352. X        }
  1353. X#else
  1354. X        return; 
  1355. X#endif
  1356. X    } else {
  1357. X        sprintf (buf, "%s/%s", spooldir, group_path);
  1358. X
  1359. X        if (access (buf, 4) != 0) {
  1360. X            return;
  1361. X        }
  1362. X
  1363. X        d = opendir (buf);
  1364. X        if (d != NULL) {
  1365. X            while ((e = readdir (d)) != NULL) {
  1366. X                art = my_atol (e->d_name, (int) e->D_LENGTH);
  1367. X                if (art >= 0) {
  1368. X                    if (top_base >= max_art)
  1369. X                        expand_art ();
  1370. X                    base[top_base++] = art;
  1371. X                }
  1372. X            }
  1373. X            closedir (d);
  1374. X            qsort ((char *) base, top_base, sizeof (long), base_comp);
  1375. X        }
  1376. X    }
  1377. X}
  1378. X
  1379. X/*
  1380. X *  get a response code from the server and return it to the caller
  1381. X */
  1382. X
  1383. Xint get_respcode ()
  1384. X{
  1385. X#ifdef NNTP_ABLE
  1386. X    char line[NNTP_STRLEN];
  1387. X
  1388. X    if (get_server (line, NNTP_STRLEN) == -1) {
  1389. X        error_message (txt_connection_to_server_broken, "");
  1390. X        tin_done (1);
  1391. X    }
  1392. X
  1393. X    debug_nntp ("get_respcode", line);
  1394. X    
  1395. X    return atoi (line);
  1396. X#else
  1397. X    return (0);
  1398. X#endif
  1399. X}
  1400. X
  1401. X
  1402. Xint stuff_nntp (fnam)
  1403. X    char *fnam;
  1404. X{
  1405. X#ifdef NNTP_ABLE
  1406. X    FILE *fp;
  1407. X    char line[NNTP_STRLEN];
  1408. X    extern char *mktemp ();
  1409. X    struct stat sb;
  1410. X    extern long note_size;
  1411. X
  1412. X    strcpy (fnam, "/tmp/tin_nntpXXXXXX");
  1413. X    mktemp (fnam);
  1414. X
  1415. X    if ((fp = fopen (fnam, "w")) == (FILE *) 0) {
  1416. X        perror_message (txt_stuff_nntp_cannot_open, fnam);
  1417. X        return FALSE;
  1418. X    }
  1419. X
  1420. X    while (1) {
  1421. X        if (get_server (line, NNTP_STRLEN) == -1) {
  1422. X            error_message (txt_connection_to_server_broken, "");
  1423. X            tin_done (1);
  1424. X        }
  1425. X
  1426. X        debug_nntp ("stuff_nntp", line);
  1427. X        
  1428. X        if (strcmp (line, ".") == 0)
  1429. X            break;            /* end of text */
  1430. X        strcat (line, "\n");
  1431. X        if (line[0] == '.')        /* reduce leading .'s */
  1432. X            fputs (&line[1], fp);
  1433. X        else
  1434. X            fputs (line, fp);
  1435. X    }
  1436. X    fclose (fp);
  1437. X
  1438. X    if (stat (fnam, &sb) < 0)
  1439. X        note_size = 0;
  1440. X    else
  1441. X        note_size = sb.st_size;
  1442. X
  1443. X    return TRUE;
  1444. X#else
  1445. X    return TRUE;
  1446. X#endif
  1447. X}
  1448. X
  1449. X
  1450. XFILE *nntp_to_fp ()
  1451. X{
  1452. X#ifdef NNTP_ABLE
  1453. X    char fnam[LEN];
  1454. X    FILE *fp = (FILE *) 0;
  1455. X    
  1456. X    if (! stuff_nntp (fnam)) {
  1457. X        debug_nntp ("nntp_to_fp", "! stuff_nntp()");
  1458. X        return (FILE *) 0;
  1459. X    }
  1460. X
  1461. X    if ((fp = fopen (fnam, "r")) == (FILE *) 0) {
  1462. X        perror_message (txt_nntp_to_fp_cannot_reopen, fnam);
  1463. X        return (FILE *) 0;
  1464. X    }
  1465. X    
  1466. X    unlink (fnam);
  1467. X    return fp;
  1468. X#else
  1469. X    return (FILE *) 0;
  1470. X#endif
  1471. X}
  1472. X
  1473. X/*
  1474. X * Log user info to local file or NNTP logfile
  1475. X */
  1476. X
  1477. Xvoid log_user ()
  1478. X{
  1479. X    char buf[32], *ptr;
  1480. X    char line[NNTP_STRLEN];
  1481. X#ifdef LOG_USER
  1482. X    FILE *fp;
  1483. X    long epoch;
  1484. X#endif
  1485. X    extern struct passwd *myentry;
  1486. X
  1487. X    my_strncpy (buf, myentry->pw_gecos, sizeof (buf)-1);
  1488. X
  1489. X    if (read_news_via_nntp && xuser_supported) {
  1490. X        if ((ptr = (char *) strchr(buf, ','))) {
  1491. X            *ptr = '\0';
  1492. X        }
  1493. X        sprintf (line, "xuser %s (%s)", myentry->pw_name, buf);
  1494. X
  1495. X        debug_nntp ("log_user", line);
  1496. X        put_server (line);
  1497. X    } else {
  1498. X#ifdef LOG_USER
  1499. X        if ((fp = fopen (LOG_USER_FILE, "a+")) != (FILE *) 0) {
  1500. X            time (&epoch);
  1501. X            fprintf (fp, "%s%d: %-32s (%-8s) %s", VERSION, PATCHLEVEL,
  1502. X                    buf, myentry->pw_name, ctime (&epoch));
  1503. X            fclose (fp);
  1504. X            chmod (LOG_USER_FILE, 0666);
  1505. X        }    
  1506. X#endif
  1507. X    }
  1508. X}
  1509. X
  1510. X/*
  1511. X * NNTP strings for get_respcode()
  1512. X */
  1513. X
  1514. Xchar *nntp_respcode (respcode)
  1515. X    int respcode;
  1516. X{
  1517. X#ifdef NNTP_ABLE
  1518. X
  1519. X    static char *text;
  1520. X    
  1521. X    switch (respcode) {
  1522. X        case 0:
  1523. X            text = "";
  1524. X            break;
  1525. X        case INF_HELP:
  1526. X            text = "100  Help text on way";
  1527. X            break;
  1528. X        case INF_AUTH:
  1529. X            text = "180  Authorization capabilities";
  1530. X            break;
  1531. X        case INF_DEBUG:
  1532. X            text = "199  Debug output";
  1533. X            break;
  1534. X        case OK_CANPOST:
  1535. X            text = "200  Hello; you can post";
  1536. X            break;
  1537. X        case OK_NOPOST:
  1538. X            text = "201  Hello; you can't post";
  1539. X            break;
  1540. X        case OK_SLAVE:
  1541. X            text = "202  Slave status noted";
  1542. X            break;
  1543. X        case OK_GOODBYE:
  1544. X            text = "205  Closing connection";
  1545. X            break;
  1546. X        case OK_GROUP:
  1547. X            text = "211  Group selected";
  1548. X            break;
  1549. X        case OK_GROUPS:
  1550. X            text = "215  Newsgroups follow";
  1551. X            break;
  1552. X        case OK_XINDEX:
  1553. X            text = "218  Group index file follows";
  1554. X            break;
  1555. X        case OK_ARTICLE:
  1556. X            text = "220  Article (head & body) follows";
  1557. X            break;
  1558. X        case OK_HEAD:
  1559. X            text = "221  Head follows";
  1560. X            break;
  1561. X        case OK_BODY:
  1562. X            text = "222  Body follows";
  1563. X            break;
  1564. X        case OK_NOTEXT:
  1565. X            text = "223  No text sent -- stat, next, last";
  1566. X            break;
  1567. X        case OK_NEWNEWS:
  1568. X            text = "230  New articles by message-id follow";
  1569. X            break;
  1570. X        case OK_NEWGROUPS:
  1571. X            text = "231  New newsgroups follow";
  1572. X            break;
  1573. X        case OK_XFERED:
  1574. X            text = "235  Article transferred successfully";
  1575. X            break;
  1576. X        case OK_POSTED:
  1577. X            text = "240  Article posted successfully";
  1578. X            break;
  1579. X        case OK_AUTHSYS:
  1580. X            text = "280  Authorization system ok";
  1581. X            break;
  1582. X        case OK_AUTH:
  1583. X            text = "281  Authorization (user/pass) ok";
  1584. X            break;
  1585. X        case OK_BIN:
  1586. X            text = "282  binary data follows";
  1587. X            break;
  1588. X        case OK_SPLIST:
  1589. X            text = "283  spooldir list follows";
  1590. X            break;
  1591. X        case OK_SPSWITCH:
  1592. X            text = "284  Switching to a different spooldir";
  1593. X            break;
  1594. X        case OK_SPNOCHANGE:
  1595. X            text = "285  Still using same spooldir";
  1596. X            break;
  1597. X        case OK_SPLDIRCUR:
  1598. X            text = "286  Current spooldir";
  1599. X            break;
  1600. X        case OK_SPLDIRAVL:
  1601. X            text = "287  Available spooldir";
  1602. X            break;
  1603. X        case OK_SPLDIRERR:
  1604. X            text = "288  Unavailable spooldir or invalid entry";
  1605. X            break;
  1606. X        case CONT_XFER:
  1607. X            text = "335  Continue to send article";
  1608. X            break;
  1609. X        case CONT_POST:
  1610. X            text = "340  Continue to post article";
  1611. X            break;
  1612. X        case NEED_AUTHINFO:
  1613. X            text = "380  authorization is required";
  1614. X            break;
  1615. X        case NEED_AUTHDATA:
  1616. X            text = "381  <type> authorization data required";
  1617. X            break;
  1618. X        case ERR_GOODBYE:
  1619. X            text = "400  Have to hang up for some reason";
  1620. X            break;
  1621. X        case ERR_NOGROUP:
  1622. X            text = "411  No such newsgroup";
  1623. X            break;
  1624. X        case ERR_NCING:
  1625. X            text = "412  Not currently in newsgroup";
  1626. X            break;
  1627. X        case ERR_XINDEX:
  1628. X            text = "418  No index file for this group";
  1629. X            break;
  1630. X        case ERR_NOCRNT:
  1631. X            text = "420  No current article selected";
  1632. X            break;
  1633. X        case ERR_NONEXT:
  1634. X            text = "421  No next article in this group";
  1635. X            break;
  1636. X        case ERR_NOPREV:
  1637. X            text = "422  No previous article in this group";
  1638. X            break;
  1639. X        case ERR_NOARTIG:
  1640. X            text = "423  No such article in this group";
  1641. X            break;
  1642. X        case ERR_NOART:
  1643. X            text = "430  No such article at all";
  1644. X            break;
  1645. X        case ERR_GOTIT:
  1646. X            text = "435  Already got that article, don't send";
  1647. X            break;
  1648. X        case ERR_XFERFAIL:
  1649. X            text = "436  Transfer failed";
  1650. X            break;
  1651. X        case ERR_XFERRJCT:
  1652. X            text = "437  Article rejected, don't resend";
  1653. X            break;
  1654. X        case ERR_NOPOST:
  1655. X            text = "440  Posting not allowed";
  1656. X            break;
  1657. X        case ERR_POSTFAIL:
  1658. X            text = "441  Posting failed";
  1659. X            break;
  1660. X        case ERR_NOAUTH:
  1661. X            text = "480  authorization required for command";
  1662. X            break;
  1663. X        case ERR_AUTHSYS:
  1664. X            text = "481  Authorization system invalid";
  1665. X            break;
  1666. X        case ERR_AUTHREJ:
  1667. X            text = "482  Authorization data rejected";
  1668. X            break;
  1669. X        case ERR_INVALIAS:
  1670. X            text = "483  Invalid alias on spooldir cmd";
  1671. X            break;
  1672. X        case ERR_INVNOSPDIR:
  1673. X            text = "484  No spooldir file found";
  1674. X            break;
  1675. X        case ERR_COMMAND:
  1676. X            text = "500  Command not recognized";
  1677. X            break;
  1678. X        case ERR_CMDSYN:
  1679. X            text = "501  Command syntax error";
  1680. X            break;
  1681. X        case ERR_ACCESS:
  1682. X            text = "502  Access to server denied";
  1683. X            break;
  1684. X        case ERR_FAULT:
  1685. X            text = "503  Program fault, command not performed";
  1686. X            break;
  1687. X        case ERR_AUTHBAD:
  1688. X            text = "580  Authorization Failed";
  1689. X            break;
  1690. X        default:
  1691. X            text = "Unknown NNTP response code";
  1692. X            break;
  1693. X    }
  1694. X    return (text);
  1695. X#else
  1696. X    return ("");
  1697. X#endif
  1698. X}
  1699. END_OF_FILE
  1700.   if test 14367 -ne `wc -c <'open.c'`; then
  1701.     echo shar: \"'open.c'\" unpacked with wrong size!
  1702.   fi
  1703.   # end of 'open.c'
  1704. fi
  1705. if test -f 'spooldir.c' -a "${1}" != "-c" ; then 
  1706.   echo shar: Will not clobber existing file \"'spooldir.c'\"
  1707. else
  1708.   echo shar: Extracting \"'spooldir.c'\" \(14375 characters\)
  1709.   sed "s/^X//" >'spooldir.c' <<'END_OF_FILE'
  1710. X/*
  1711. X *  Project   : tin - a threaded Netnews reader
  1712. X *  Module    : spooldir.c
  1713. X *  Author    : I.Lea & Tom Theel
  1714. X *  Created   : 08-05-92
  1715. X *  Updated   : 20-06-92
  1716. X *  Notes     : Changes spooldir to read news from (ie. news, nntp, cdrom)
  1717. X *  Copyright : (c) Copyright 1991-92 by Iain Lea & Tom Theel
  1718. X *              You may  freely  copy or  redistribute  this software,
  1719. X *              so  long as there is no profit made from its use, sale
  1720. X *              trade or  reproduction.  You may not change this copy-
  1721. X *              right notice, and it must be included in any copy made
  1722. X */
  1723. X
  1724. X#include    "tin.h"
  1725. X
  1726. X#define NUM_SPOOLDIRS    50
  1727. X
  1728. Xint cur_spoolnum = 0;
  1729. Xint first_spooldir_on_screen;
  1730. Xint last_spooldir_on_screen;
  1731. Xint num_spooldirs = 0;
  1732. Xint spool_top = 0;
  1733. X
  1734. X/*
  1735. X * needs to be dynamic but no time 
  1736. X */
  1737. Xstruct spooldir_t spooldirs[NUM_SPOOLDIRS];
  1738. X
  1739. X
  1740. X/*
  1741. X * Change spooldir via menu of available choices
  1742. X */
  1743. X
  1744. Xint spooldir_index ()
  1745. X{
  1746. X#ifndef INDEX_DAEMON
  1747. X
  1748. X    char ch;
  1749. X    int n;
  1750. X    int scroll_lines;
  1751. X    
  1752. X    spool_top = num_spooldirs;
  1753. X
  1754. X    if (! xspooldir_supported) {
  1755. X        info_message ("Multiple spooldirs are not supported");
  1756. X        return FALSE;
  1757. X    }
  1758. X
  1759. X    if (! spool_top) {
  1760. X        info_message ("No spooldirs");
  1761. X        return FALSE;
  1762. X    }
  1763. X
  1764. X    
  1765. X    mail_setup ();        /* record mailbox size for "you have mail" */
  1766. X
  1767. X#ifndef USE_CLEARSCREEN
  1768. X    ClearScreen();
  1769. X#endif
  1770. X
  1771. X    show_spooldir_page ();        /* display spooldir selection page */
  1772. X    
  1773. X    while (TRUE) {
  1774. X        ch = (char) ReadCh ();
  1775. X
  1776. X        if (ch > '0' && ch <= '9') {
  1777. X            prompt_spooldir_num (ch);
  1778. X            continue;
  1779. X        }
  1780. X        switch (ch) {
  1781. X            case ESC:    /* (ESC) common arrow keys */
  1782. X                switch (get_arrow_key ()) {
  1783. X                    case KEYMAP_UP:
  1784. X                        goto spooldir_up;
  1785. X
  1786. X                    case KEYMAP_DOWN:
  1787. X                        goto spooldir_down;
  1788. X
  1789. X                    case KEYMAP_PAGE_UP:
  1790. X                        goto spooldir_page_up;
  1791. X
  1792. X                    case KEYMAP_PAGE_DOWN:
  1793. X                        goto spooldir_page_down;
  1794. X
  1795. X                    case KEYMAP_HOME:
  1796. X                        if (cur_spoolnum != 0) {
  1797. X                            if (0 < first_spooldir_on_screen) {
  1798. X#ifndef USE_CLEARSCREEN
  1799. X                                erase_spooldir_arrow ();
  1800. X#endif                    
  1801. X                                cur_spoolnum = 0;
  1802. X                                show_spooldir_page ();
  1803. X                            } else {
  1804. X                                erase_spooldir_arrow ();
  1805. X                                cur_spoolnum = 0;
  1806. X                                draw_spooldir_arrow ();
  1807. X                            }
  1808. X                        }
  1809. X                        break;
  1810. X                    
  1811. X                    case KEYMAP_END:
  1812. X                        goto end_of_list;
  1813. X                }
  1814. X                break;
  1815. X
  1816. X            case '$':    /* show last page of spooldirs */
  1817. Xend_of_list:
  1818. X                if (cur_spoolnum != spool_top - 1) {
  1819. X                    if (spool_top - 1 > last_spooldir_on_screen) {
  1820. X#ifndef USE_CLEARSCREEN
  1821. X                        erase_spooldir_arrow ();
  1822. X#endif                    
  1823. X                        cur_spoolnum = spool_top - 1;
  1824. X                        show_spooldir_page ();
  1825. X                    } else {
  1826. X                        erase_group_arrow ();
  1827. X                        cur_spoolnum = spool_top - 1;
  1828. X                        draw_spooldir_arrow ();
  1829. X                    }
  1830. X                }
  1831. X                break;
  1832. X
  1833. X            case '\r':    /* select spooldir */
  1834. X            case '\n':
  1835. X                if (set_spooldir (spooldirs[cur_spoolnum].name)) {
  1836. X                    wait_message (txt_reading_active_file);
  1837. X                    free_active_arrays ();
  1838. X                    max_active = DEFAULT_ACTIVE_NUM;
  1839. X                    expand_active ();
  1840. X                    read_active_file ();
  1841. X                    read_newsgroups_file ();
  1842. X                    read_newsrc (TRUE);
  1843. X                    return TRUE;
  1844. X                }    
  1845. X                break;
  1846. X
  1847. X            case ' ':        /* page down */
  1848. X            case ctrl('D'):
  1849. X            case ctrl('F'):        /* vi style */
  1850. Xspooldir_page_down:
  1851. X                if (cur_spoolnum == spool_top - 1) {
  1852. X#ifdef NO_LOOP_AROUND
  1853. X                    break;
  1854. X#else
  1855. X                    if (0 < first_spooldir_on_screen) {
  1856. X#    ifndef USE_CLEARSCREEN
  1857. X                        erase_spooldir_arrow ();
  1858. X#    endif                    
  1859. X                        cur_spoolnum = 0;
  1860. X                        show_spooldir_page ();
  1861. X                    } else {
  1862. X                        erase_spooldir_arrow ();
  1863. X                        cur_spoolnum = 0;
  1864. X                        draw_spooldir_arrow ();
  1865. X                    }
  1866. X                    break;
  1867. X#endif                    
  1868. X                }
  1869. X                erase_spooldir_arrow ();
  1870. X                scroll_lines = (full_page_scroll ? NOTESLINES : NOTESLINES / 2);
  1871. X                cur_spoolnum = ((cur_spoolnum + scroll_lines) / scroll_lines) * scroll_lines;
  1872. X                if (cur_spoolnum >= spool_top) {
  1873. X                    cur_spoolnum = (spool_top / scroll_lines) * scroll_lines;
  1874. X                    if (cur_spoolnum < spool_top - 1) {
  1875. X                        cur_spoolnum = spool_top - 1;
  1876. X                    }
  1877. X                }
  1878. X
  1879. X                if (cur_spoolnum <= first_spooldir_on_screen
  1880. X                ||  cur_spoolnum >= last_spooldir_on_screen)
  1881. X                    show_spooldir_page ();
  1882. X                else
  1883. X                    draw_spooldir_arrow ();
  1884. X                break;
  1885. X
  1886. X            case ctrl('L'):        /* redraw */
  1887. X#ifndef USE_CLEARSCREEN
  1888. X                ClearScreen ();
  1889. X#endif
  1890. X                show_spooldir_page ();
  1891. X                break;
  1892. X
  1893. X            case ctrl('N'):        /* line down */
  1894. X            case 'j':
  1895. Xspooldir_down:
  1896. X                if (cur_spoolnum + 1 >= spool_top) {
  1897. X#ifdef NO_LOOP_AROUND
  1898. X                    break;
  1899. X#else
  1900. X                    if (0 < first_spooldir_on_screen) {
  1901. X#    ifndef USE_CLEARSCREEN
  1902. X                        erase_spooldir_arrow ();
  1903. X#    endif                    
  1904. X                        cur_spoolnum = 0;
  1905. X                        show_spooldir_page ();
  1906. X                    } else {
  1907. X                        erase_spooldir_arrow ();
  1908. X                        cur_spoolnum = 0;
  1909. X                        draw_spooldir_arrow ();
  1910. X                    }
  1911. X                    break;
  1912. X#endif                    
  1913. X                }
  1914. X                if (cur_spoolnum + 1 >= last_spooldir_on_screen) {
  1915. X#ifndef USE_CLEARSCREEN
  1916. X                    erase_spooldir_arrow ();
  1917. X#endif                    
  1918. X                    cur_spoolnum++;
  1919. X                    show_spooldir_page ();
  1920. X                } else {
  1921. X                    erase_spooldir_arrow ();
  1922. X                    cur_spoolnum++;
  1923. X                    draw_spooldir_arrow ();
  1924. X                }
  1925. X                break;
  1926. X
  1927. X            case ctrl('P'):        /* line up */
  1928. X            case 'k':
  1929. Xspooldir_up:
  1930. X                if (cur_spoolnum == 0) {
  1931. X#ifdef NO_LOOP_AROUND
  1932. X                    break;
  1933. X#else
  1934. X                    if (spool_top > last_spooldir_on_screen) {
  1935. X                        cur_spoolnum = spool_top - 1;
  1936. X                        show_spooldir_page ();
  1937. X                    } else {
  1938. X                        erase_spooldir_arrow ();
  1939. X                        cur_spoolnum = spool_top - 1;
  1940. X                        draw_spooldir_arrow ();
  1941. X                    }
  1942. X                    break;
  1943. X#endif                    
  1944. X                }
  1945. X                if (cur_spoolnum <= first_spooldir_on_screen) {
  1946. X                    cur_spoolnum--;
  1947. X                    show_spooldir_page ();
  1948. X                } else {
  1949. X                    erase_spooldir_arrow ();
  1950. X                    cur_spoolnum--;
  1951. X                    draw_spooldir_arrow ();
  1952. X                }
  1953. X                break;
  1954. X
  1955. X            case 'b':        /* page up */
  1956. X            case ctrl('U'):
  1957. X            case ctrl('B'):        /* vi style */
  1958. Xspooldir_page_up:
  1959. X                if (cur_spoolnum == 0) {
  1960. X#ifdef NO_LOOP_AROUND
  1961. X                    break;
  1962. X#else
  1963. X                    if (spool_top > last_spooldir_on_screen) {
  1964. X                        cur_spoolnum = spool_top - 1;
  1965. X                        show_spooldir_page ();
  1966. X                    } else {
  1967. X                        erase_spooldir_arrow ();
  1968. X                        cur_spoolnum = spool_top - 1;
  1969. X                        draw_spooldir_arrow ();
  1970. X                    }
  1971. X                    break;
  1972. X#endif                    
  1973. X                }
  1974. X                erase_spooldir_arrow ();
  1975. X                scroll_lines = (full_page_scroll ? NOTESLINES : NOTESLINES / 2);
  1976. X                if ((n = cur_spoolnum % scroll_lines) > 0) {
  1977. X                    cur_spoolnum = cur_spoolnum - n;
  1978. X                } else {
  1979. X                    cur_spoolnum = ((cur_spoolnum - scroll_lines) / scroll_lines) * scroll_lines;
  1980. X                }
  1981. X                if (cur_spoolnum < 0) {
  1982. X                    cur_spoolnum = 0;
  1983. X                }
  1984. X                if (cur_spoolnum < first_spooldir_on_screen
  1985. X                ||  cur_spoolnum >= last_spooldir_on_screen)
  1986. X                    show_spooldir_page ();
  1987. X                else
  1988. X                    draw_spooldir_arrow ();
  1989. X                break;
  1990. X
  1991. X            case 'B':    /* bug/gripe/comment mailed to author */
  1992. X                mail_bug_report ();
  1993. X#ifndef USE_CLEARSCREEN
  1994. X                ClearScreen ();
  1995. X#endif
  1996. X                show_spooldir_page ();
  1997. X                break;
  1998. X                
  1999. X            case 'h':    /* help */
  2000. X                show_info_page (HELP_INFO, help_spooldir, txt_spooldir_com);
  2001. X                show_spooldir_page ();
  2002. X                break;
  2003. X
  2004. X            case 'I':    /* toggle inverse video */
  2005. X                erase_spooldir_arrow ();
  2006. X                toggle_inverse_video ();
  2007. X                show_spooldir_page ();
  2008. X                break;
  2009. X
  2010. X            case 'q':    /* quit */
  2011. X                return TRUE;
  2012. X                break;
  2013. X                
  2014. X            case 'Q':    /* quit */
  2015. X                write_rcfile ();
  2016. X                tin_done (0);
  2017. X                break;
  2018. X
  2019. X            case 'v':    /* show tin version */
  2020. X                info_message (cvers);
  2021. X                break;
  2022. X
  2023. X            default:
  2024. X                info_message(txt_bad_command);
  2025. X        }
  2026. X    }
  2027. X
  2028. X#endif    /* INDEX_DAEMON */
  2029. X}
  2030. X
  2031. X
  2032. Xvoid show_spooldir_page ()
  2033. X{
  2034. X#ifndef INDEX_DAEMON
  2035. X
  2036. X    char buf[PATH_LEN];
  2037. X    int i, j;
  2038. X    int spoolname_len;
  2039. X
  2040. X    set_signals_spooldir ();
  2041. X
  2042. X#ifdef USE_CLEARSCREEN
  2043. X    ClearScreen ();
  2044. X#else
  2045. X    MoveCursor (0, 0);        /* top left corner */
  2046. X    CleartoEOLN ();
  2047. X#endif
  2048. X
  2049. X    sprintf (buf, txt_spooldir_selection, num_spooldirs);
  2050. X    show_title (buf);
  2051. X
  2052. X#ifndef USE_CLEARSCREEN
  2053. X    MoveCursor (1, 0);
  2054. X    CleartoEOLN ();
  2055. X#endif
  2056. X
  2057. X    MoveCursor (INDEX_TOP, 0);
  2058. X
  2059. X    if (cur_spoolnum >= spool_top) {
  2060. X        cur_spoolnum = spool_top - 1;
  2061. X    }
  2062. X    if (cur_spoolnum < 0) {
  2063. X        cur_spoolnum = 0;
  2064. X    }
  2065. X    if (NOTESLINES <= 0) {
  2066. X        first_spooldir_on_screen = 0;
  2067. X    } else {
  2068. X        first_spooldir_on_screen = (cur_spoolnum / NOTESLINES) * NOTESLINES;
  2069. X        if (first_spooldir_on_screen < 0) {
  2070. X            first_spooldir_on_screen = 0;
  2071. X        }
  2072. X    }
  2073. X
  2074. X    last_spooldir_on_screen = first_spooldir_on_screen + NOTESLINES;
  2075. X
  2076. X    if (last_spooldir_on_screen >= spool_top) {
  2077. X        last_spooldir_on_screen = spool_top;
  2078. X        first_spooldir_on_screen = (cur_spoolnum / NOTESLINES) * NOTESLINES;
  2079. X
  2080. X        if (first_spooldir_on_screen == last_spooldir_on_screen ||
  2081. X            first_spooldir_on_screen < 0) {
  2082. X            if (first_spooldir_on_screen < 0) {
  2083. X                first_spooldir_on_screen = 0;
  2084. X            } else {
  2085. X                first_spooldir_on_screen = last_spooldir_on_screen - NOTESLINES;
  2086. X            }
  2087. X        }    
  2088. X    }
  2089. X
  2090. X    if (spool_top == 0) {
  2091. X        first_spooldir_on_screen = 0;
  2092. X        last_spooldir_on_screen = 0;
  2093. X    }
  2094. X
  2095. X    spoolname_len = COLS - 11;
  2096. X    
  2097. X    for (j=0, i = first_spooldir_on_screen; i < last_spooldir_on_screen; i++,j++) {
  2098. X        sprintf (buf, "%-16.16s  %s", spooldirs[i].name, spooldirs[i].comment);
  2099. X        sprintf (screen[j].col, "   %4.d  %-*.*s\r\n",
  2100. X            i+1, spoolname_len, spoolname_len, buf);
  2101. X        fputs (screen[j].col, stdout);
  2102. X    }
  2103. X#ifndef USE_CLEARSCREEN
  2104. X    CleartoEOS ();
  2105. X#endif
  2106. X
  2107. X    draw_spooldir_arrow ();
  2108. X
  2109. X#endif    /* INDEX_DAEMON */
  2110. X}
  2111. X
  2112. X
  2113. Xint prompt_spooldir_num (ch)
  2114. X    char ch;
  2115. X{
  2116. X    int num;
  2117. X
  2118. X    clear_message ();
  2119. X
  2120. X    if ((num = prompt_num (ch, txt_select_spooldir)) == -1) {
  2121. X        clear_message ();
  2122. X        return FALSE;
  2123. X    }
  2124. X    num--;        /* index from 0 (internal) vs. 1 (user) */
  2125. X
  2126. X    if (num < 0) {
  2127. X        num = 0;
  2128. X    }
  2129. X    if (num >= spool_top) {
  2130. X        num = spool_top - 1;
  2131. X    }
  2132. X
  2133. X    if (num >= first_spooldir_on_screen
  2134. X    &&  num < last_spooldir_on_screen) {
  2135. X        erase_spooldir_arrow ();
  2136. X        cur_spoolnum = num;
  2137. X        draw_spooldir_arrow ();
  2138. X    } else {
  2139. X#ifndef USE_CLEARSCREEN
  2140. X        erase_spooldir_arrow ();
  2141. X#endif        
  2142. X        cur_spoolnum = num;
  2143. X        show_spooldir_page ();
  2144. X    }
  2145. X
  2146. X    return TRUE;
  2147. X}
  2148. X
  2149. X
  2150. Xvoid erase_spooldir_arrow ()
  2151. X{
  2152. X    erase_arrow (INDEX_TOP + (cur_spoolnum-first_spooldir_on_screen));
  2153. X}
  2154. X
  2155. X
  2156. Xvoid draw_spooldir_arrow()
  2157. X{
  2158. X    draw_arrow (INDEX_TOP + (cur_spoolnum-first_spooldir_on_screen));
  2159. X}
  2160. X/*
  2161. X * Load all spooldirs into spooldir[] array
  2162. X */
  2163. Xint load_spooldirs ()
  2164. X{
  2165. X    char comment[PATH_LEN];
  2166. X    char line[NNTP_STRLEN];
  2167. X    char name[PATH_LEN];
  2168. X    char *ptr;
  2169. X    int i, state;
  2170. X
  2171. X#if 0
  2172. X    spooldirs = (struct spooldir_t *) 0;
  2173. X#else
  2174. X    for (i = 0 ; i < NUM_SPOOLDIRS ; i++) {
  2175. X        spooldirs[i].state = 0;
  2176. X        spooldirs[i].name = (char *) 0;
  2177. X    }
  2178. X#endif
  2179. X
  2180. X    xspooldir_supported = FALSE;
  2181. X    
  2182. X    if (! read_news_via_nntp) {
  2183. X        return (xspooldir_supported);
  2184. X    }
  2185. X
  2186. X    put_server ("spooldir list");
  2187. X    (void) get_server (line, NNTP_STRLEN);
  2188. X    if (*line != CHAR_OK) {
  2189. X        xspooldir_supported = FALSE;
  2190. X        if (debug > 0) {
  2191. X            fprintf (stderr, "%s", line);
  2192. X            fprintf (stderr, "Server does not appear to support the spooldir command\n");
  2193. X            fprintf (stderr, "Reconfigure the news reader or the server & try again.\n");
  2194. X        }
  2195. X        return (xspooldir_supported);
  2196. X    }
  2197. X    if (debug == 1) {
  2198. X        wait_message (line);
  2199. X    }
  2200. X    
  2201. X    xspooldir_supported = TRUE;
  2202. X    
  2203. X    do {
  2204. X        get_server (line, NNTP_STRLEN);
  2205. X        if (line[0] != '.') {
  2206. X            if (debug == 1) {
  2207. X                printf ("%s\n", line);
  2208. X            }    
  2209. X            state = atoi (line);
  2210. X
  2211. X            if ((ptr = strchr (line, ' ')) != (char *) 0) {
  2212. X                strncpy (name, ++ptr, sizeof (name));
  2213. X                ptr = strchr (name, ' ');
  2214. X                *ptr = '\0';                
  2215. X            }
  2216. X
  2217. X            if ((ptr = strchr (line, '[')) != (char *) 0) {
  2218. X                strncpy (comment, ++ptr, sizeof (comment));
  2219. X                ptr = strchr (comment, ']');
  2220. X                *ptr = '\0';                
  2221. X            }
  2222. X
  2223. X/*                
  2224. X            spooldirs = (struct spooldir_t *) my_realloc ((char *) spooldirs,
  2225. X                (unsigned) sizeof (struct spooldir_t) * num_spooldirs + 1);
  2226. X            if (spooldirs != (struct spooldir_t *) 0) {
  2227. X                spooldirs[num_spooldirs].state = state;
  2228. X                spooldirs[num_spooldirs].name = str_dup (name);
  2229. X                spooldirs[num_spooldirs].comment = str_dup (comment);
  2230. X                num_spooldirs++;
  2231. X            }    
  2232. X*/                
  2233. X
  2234. X            spooldirs[num_spooldirs].state = state;
  2235. X            spooldirs[num_spooldirs].name = str_dup (name);
  2236. X            spooldirs[num_spooldirs].comment = str_dup (comment);
  2237. X
  2238. X            if (debug == 1) {
  2239. X                printf ("ALIAS=[%s] COMMENT=[%s]\n", 
  2240. X                    spooldirs[num_spooldirs].name,
  2241. X                    spooldirs[num_spooldirs].comment);
  2242. X            }
  2243. X            num_spooldirs++;
  2244. X        }
  2245. X    } while (!((line[0] == '.') && ((line[1] == '\0') || (line[1] == '\r'))));
  2246. X
  2247. X    return (xspooldir_supported);
  2248. X}
  2249. X/*
  2250. X * Need to select a spooldir directory for reading news from and store all
  2251. X * spooldir's in an array for later use when changing spooldir's
  2252. X */
  2253. X
  2254. Xvoid get_spooldir ()
  2255. X{
  2256. X#ifdef NNTP_ABLE
  2257. X    char line[NNTP_STRLEN];
  2258. X    char alias[32];
  2259. X    char default_alias[32];
  2260. X    int i, set_alias = FALSE;
  2261. X    
  2262. X    default_alias[0] = '\0';
  2263. X
  2264. X    if (! load_spooldirs ()) {
  2265. X        if (! xspooldir_supported) {
  2266. X            strcpy (spooldir_alias, "news");
  2267. X            set_tindir ();
  2268. X        }    
  2269. X        return;
  2270. X    }    
  2271. X
  2272. X     /*
  2273. X      * default to current spooldir from last session or 1st in spooldirs[]
  2274. X      */
  2275. X    if (spooldir_alias[0]) {
  2276. X        my_strncpy (default_alias, spooldir_alias, sizeof (default_alias));
  2277. X    } else {
  2278. X        my_strncpy (default_alias, spooldirs[0].name, sizeof (default_alias));
  2279. X    }
  2280. X
  2281. X    /*
  2282. X     * Try to use default spooldir. If that fails go through spooldir list
  2283. X     * looking for first available spooldir.
  2284. X     */
  2285. X    if (! set_spooldir (spooldir_alias)) {
  2286. X        for (i = 0 ; spooldirs[i].name != (char *) 0 ; i++) {
  2287. X            if (set_spooldir (spooldirs[i].name)) {
  2288. X                set_alias = TRUE;
  2289. X                break;
  2290. X            }
  2291. X        }
  2292. X        if (! set_alias) {
  2293. X            error_message ("%s: Cannot change to valid spooldir. Exiting...", progname);
  2294. X            exit (1);            
  2295. X        }
  2296. X    }
  2297. X
  2298. X#if 0     
  2299. X    do {
  2300. X        printf ("Which spooldir [%s] ? ", default_alias);
  2301. X        gets (alias);
  2302. X        if (alias[0] == '\0') {
  2303. X            strcpy (alias, default_alias); 
  2304. X        } else if ((alias[0] == 'q') && (alias[1] == '\0')) {
  2305. X            exit(0); /* allow user to quit */
  2306. X        }    
  2307. X        sprintf (line, "spooldir %s", alias);
  2308. X        put_server (line);
  2309. X        (void) get_server (line, NNTP_STRLEN);
  2310. X        printf ("\r\n%s\r\n", line);
  2311. X    } while (line[0] != CHAR_OK);
  2312. X#endif
  2313. X
  2314. X    /*
  2315. X     * And now set tin to act as though it is reading via NNTP
  2316. X     */
  2317. X    read_news_via_nntp = TRUE;
  2318. X
  2319. X#endif /* NNTP_ABLE */
  2320. X}
  2321. X
  2322. X/*
  2323. X * Change to specified spooldir if everythings OK.
  2324. X */
  2325. Xint set_spooldir (name)
  2326. X    char *name;
  2327. X{
  2328. X    char line[NNTP_STRLEN];
  2329. X    int respcode;
  2330. X
  2331. X    if (cmd_line) {
  2332. X        sprintf (line, "Changing spooldir to %s...\n", name);
  2333. X    } else {
  2334. X        sprintf (line, "Changing spooldir to %s...", name);
  2335. X    }    
  2336. X    wait_message (line);
  2337. X
  2338. X    sprintf (line, "spooldir %s", name);
  2339. X    debug_nntp ("set_spooldir", line);
  2340. X    put_server (line);
  2341. X    debug_nntp ("set_spooldir", line);
  2342. X
  2343. X    respcode = get_respcode ();
  2344. X    switch (respcode) {
  2345. X        case OK_SPSWITCH:    /* Switching to a different spooldir */
  2346. X            my_strncpy (spooldir_alias, name, sizeof (spooldir_alias));
  2347. X            set_tindir ();
  2348. X            return TRUE;
  2349. X            break;
  2350. X        case OK_SPNOCHANGE:    /* Still using same spooldir */
  2351. X            break;
  2352. X        default:
  2353. X            error_message ("%s", nntp_respcode (respcode));
  2354. X            clear_message ();
  2355. X            return FALSE;
  2356. X            break;        
  2357. X    }
  2358. X}
  2359. END_OF_FILE
  2360.   if test 14375 -ne `wc -c <'spooldir.c'`; then
  2361.     echo shar: \"'spooldir.c'\" unpacked with wrong size!
  2362.   fi
  2363.   # end of 'spooldir.c'
  2364. fi
  2365. echo shar: End of archive 11 \(of 15\).
  2366. cp /dev/null ark11isdone
  2367. MISSING=""
  2368. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ; do
  2369.     if test ! -f ark${I}isdone ; then
  2370.     MISSING="${MISSING} ${I}"
  2371.     fi
  2372. done
  2373. if test "${MISSING}" = "" ; then
  2374.     echo You have unpacked all 15 archives.
  2375.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2376. else
  2377.     echo You still must unpack the following archives:
  2378.     echo "        " ${MISSING}
  2379. fi
  2380. exit 0
  2381. exit 0 # Just in case...
  2382.