home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 1 / 1464 < prev    next >
Internet Message Format  |  1990-12-28  |  63KB

  1. From: sob@lib.tmc.edu (Stan Barber)
  2. Newsgroups: alt.sources
  3. Subject: rrn/rn combo kit part 7 of 9
  4. Message-ID: <433@lib.tmc.edu>
  5. Date: 14 Jun 90 03:28:56 GMT
  6.  
  7. #! /bin/sh
  8.  
  9. # Make a new directory for the rn sources, cd to it, and run kits 1 thru 9 
  10. # through sh.  When all 9 kits have been run, read README.
  11.  
  12. echo "This is rn kit 7 (of 9).  If kit 7 is complete, the line"
  13. echo '"'"End of kit 7 (of 9)"'" will echo at the end.'
  14. echo ""
  15. export PATH || (echo "You didn't use sh, you clunch." ; kill $$)
  16. echo Extracting help.c
  17. cat >help.c <<'!STUFFY!FUNK!'
  18. /* $Header: help.c,v 4.3.2.1 90/03/22 23:10:10 sob Exp $
  19.  *
  20.  * $Log:    help.c,v $
  21.  * Revision 4.3.2.1  90/03/22  23:10:10  sob
  22.  * checkpoint
  23.  * 
  24.  * Revision 4.3.1.2  85/09/10  11:05:39  lwall
  25.  * Improved %m in in_char().
  26.  * 
  27.  * Revision 4.3.1.1  85/05/10  11:33:10  lwall
  28.  * Branch for patches.
  29.  * 
  30.  * Revision 4.3  85/05/01  11:38:59  lwall
  31.  * Baseline for release with 4.3bsd.
  32.  * 
  33.  */
  34.  
  35. #include "EXTERN.h"
  36. #include "common.h"
  37. #include "rn.h"
  38. #include "term.h"
  39. #include "INTERN.h"
  40. #include "help.h"
  41.  
  42. void
  43. help_init()
  44. {
  45.     ;
  46. }
  47.  
  48. int
  49. help_page()
  50. {
  51.     int cmd;
  52.  
  53. #ifdef PAGERHELP
  54.     doshell(sh,filexp(PAGERHELP));
  55. #else
  56.     page_init();
  57.     if ((cmd = print_lines("\
  58. Paging commands:\n\
  59. ",STANDOUT)) ||
  60.     (cmd = print_lines("\n\
  61. SP    Display the next page.\n\
  62. x    Display the next page decrypted (rot13).\n\
  63. d    Display half a page more.\n\
  64. CR    Display one more line.\n\
  65. ^R,v,^X    Restart the current article (v=verbose header, ^X=rot13).\n\
  66. ",NOMARKING)) ||
  67.     (cmd = print_lines("\
  68. ^B    Back up one page.\n\
  69. ^L,X    Refresh the screen (X=rot13).\n\
  70. g pat    Go to (search forward within article for) pattern.\n\
  71. G    Search again for current pattern within article.\n\
  72. ^G    Search for next line beginning with \"Subject:\".\n\
  73. TAB    Search for next line beginning with a different character.\n\
  74. q    Quit the pager, go to end of article.  Leave article read or unread.\n\
  75. j    Junk this article (mark it read).  Goes to end of article.\n\
  76. \n\
  77. ",NOMARKING)) ||
  78.     (cmd = print_lines("\
  79. The following commands skip the rest of the current article, then behave\n\
  80. just as if typed to the 'What next?' prompt at the end of the article:\n\
  81. ",STANDOUT)) ||
  82.     (cmd = print_lines("\n\
  83. n    Scan forward for next unread article.\n\
  84. N    Go to next article.\n\
  85. ^N    Scan forward for next unread article with same title.\n\
  86. p,P,^P    Same as n,N,^N, only going backwards.\n\
  87. -    Go to previously displayed article.\n\
  88. \n\
  89. ",NOMARKING)) ||
  90.     (cmd = print_lines("\
  91. The following commands also take you to the end of the article.\n\
  92. Type h at end of article for a description of these commands:\n\
  93. ",STANDOUT)) ||
  94.     (cmd = print_lines("\
  95.     # $ & / = ? c C f F k K ^K m M number r R ^R s S u v w W Y ^ |\n\
  96. \n\
  97. (To return to the middle of the article after one of these commands, type ^L.)\n\
  98. ",NOMARKING)) )
  99.     return cmd;
  100. #endif
  101.     return 0;
  102. }
  103.  
  104. int
  105. help_art()
  106. {
  107.     int cmd;
  108. #ifdef ARTHELP
  109.     doshell(sh,filexp(ARTHELP));
  110. #else
  111.     page_init();
  112.     if ((cmd = print_lines("\
  113. Article Selection commands:\n\
  114. ",STANDOUT)) ||
  115.     (cmd = print_lines("\n\
  116. n,SP    Scan forward for next unread article.\n\
  117. N    Go to next article.\n\
  118. ^N    Scan forward for next unread article with same subject.\n\
  119. p,P,^P    Same as n,N,^N, only going backwards.\n\
  120. -    Go to previously displayed article.\n\
  121. ",NOMARKING)) ||
  122.     (cmd = print_lines("\
  123. number    Go to specified article.\n\
  124. range{,range} command{:command}\n\
  125.     Apply one or more commands to one or more ranges of articles.\n\
  126.     Ranges are of the form: number | number-number.  You may use . for\n\
  127.     the current article, and $ for the last article.\n\
  128.      Valid commands are: j, m, M, s, S, and !.\n\
  129. ",NOMARKING)) ||
  130.     (cmd = print_lines("\
  131. /pattern/modifiers\n\
  132.     Scan forward for article containing pattern in the subject line.\n\
  133.     (Use ?pat? to scan backwards; append h to scan headers, a to scan\n\
  134.     entire articles, r to scan read articles, c to make case sensitive.\n\
  135. /pattern/modifiers:command{:command}\n\
  136.     Apply one or more commands to the set of articles matching pattern.\n\
  137.     Use a K modifier to save entire command to the KILL file for this\n\
  138.     newsgroup.  Commands m and M, if first, imply an r modifier.\n\
  139.      Valid commands are: j, m, M, s, S, and !.\n\
  140. ",NOMARKING)) ||
  141.     (cmd = print_lines("\
  142. f,F    Submit a followup article (F = include this article).\n\
  143. r,R    Reply through net mail (R = include this article).\n\
  144. s ...    Save to file or pipe via sh.\n\
  145. S ...    Save via preferred shell.\n\
  146. w,W    Like s and S but save without the header.\n\
  147. | ...    Same as s|...\n\
  148. C    Cancel this article, if yours.\n\
  149. ",NOMARKING)) ||
  150.     (cmd = print_lines("\
  151. ^R,v    Restart article (v=verbose).\n\
  152. ^X    Restart article, rot13 mode.\n\
  153. c    Catch up (mark all articles as read).\n\
  154. ^B    Back up one page.\n\
  155. ^L    Refresh the screen.  You can get back to the pager with this.\n\
  156. X    Refresh screen in rot13 mode.\n\
  157. ",NOMARKING)) ||
  158.     (cmd = print_lines("\
  159. ^    Go to first unread article.  Disables subject search mode.\n\
  160. $    Go to end of newsgroup.  Disables subject search mode.\n\
  161. ",NOMARKING)) ||
  162.     (cmd = print_lines("#       Print last article number.\n\
  163. &    Print current values of command-line switches.\n\
  164. &switch {switch}\n\
  165.     Set or unset more switches.\n\
  166. &&    Print current macro definitions.\n\
  167. &&def    Define a new macro.\n\
  168. j    Junk this article (mark it read).  Stays at end of article.\n\
  169. m    Mark article as still unread.\n\
  170. M    Mark article as still unread upon exiting newsgroup or Y command.\n\
  171. ",NOMARKING)) ||
  172.     (cmd = print_lines("\
  173. Y    Yank back articles marked temporarily read via M.\n\
  174. k    Mark current SUBJECT as read.\n\
  175. K    Mark current SUBJECT as read, and save command in KILL file.\n\
  176. =    List subjects of unread articles.\n\
  177. u    Unsubscribe to this newsgroup.\n\
  178. ^K    Edit local KILL file (the one for this newsgroup).\n\
  179. q    Quit this newsgroup for now.\n\
  180. Q    Quit newsgroup, staying at current newsgroup.\n\
  181. ",NOMARKING)) )
  182.     return cmd;
  183. #endif
  184.     return 0;
  185. }
  186.  
  187. int
  188. help_ng()
  189. {
  190.     int cmd;
  191. #ifdef NGHELP
  192.     doshell(sh,filexp(NGHELP));
  193. #else
  194.     page_init();
  195.     if (cmd = print_lines("\
  196. Newsgroup Selection commands:\n\
  197. ",STANDOUT) )
  198.     return cmd;
  199.     if (ng != nextrcline) {
  200.     if (cmd = print_lines("\
  201. \n\
  202. y,SP    Do this newsgroup now.\n\
  203. .cmd    Do this newsgroup, executing cmd as first command.\n\
  204. =    Equivalent to .=<carriage return>.\n\
  205. u    Unsubscribe from this newsgroup.\n\
  206. c    Catch up (mark this newsgroup all read).\n\
  207. ",NOMARKING) )
  208.         return cmd;
  209.     }
  210.     if ((cmd = print_lines("\
  211. \n\
  212. n    Go to the next newsgroup with unread news.\n\
  213. N    Go to the next newsgroup.\n\
  214. p    Go to the previous newsgroup with unread news.\n\
  215. P    Go to the previous newsgroup.\n\
  216. ",NOMARKING)) ||
  217.     (cmd = print_lines("\
  218. -    Go to the previously displayed newsgroup.\n\
  219. 1    Go to the first newsgroup.\n\
  220. ^    Go to the first newsgroup with unread news.\n\
  221. $    Go to the last newsgroup.\n\
  222. ",NOMARKING)) ||
  223.     (cmd = print_lines("\
  224. g name    Go to the named newsgroup.  Subscribe to new newsgroups this way too.\n\
  225. /pat    Search forward for newsgroup matching pattern.\n\
  226. ?pat    Search backward for newsgroup matching pattern.\n\
  227.     (Use * and ? style patterns.  Append r to include read newsgroups.)\n\
  228. ",NOMARKING)) ||
  229.     (cmd = print_lines("\
  230. l pat    List unsubscribed newsgroups containing pattern.\n\
  231. m name    Move named newsgroup elsewhere (no name moves current newsgroup).\n\
  232. o pat    Only display newsgroups matching pattern.  Omit pat to unrestrict.\n\
  233. a pat    Like o, but also scans for unsubscribed newsgroups matching pattern.\n\
  234. L    List current .newsrc.\n\
  235. ",NOMARKING)) ||
  236.     (cmd = print_lines("\
  237. &    Print current command-line switch settings.\n\
  238. &switch {switch}\n\
  239.     Set (or unset) more command-line switches.\n\
  240. &&    Print current macro definitions.\n\
  241. &&def    Define a new macro.\n\
  242. !cmd    Shell escape.\n\
  243. ",NOMARKING)) ||
  244.     (cmd = print_lines("\
  245. q    Quit rn.\n\
  246. ^K    Edit the global KILL file.  Use commands like /pattern/j to suppress\n\
  247.     pattern in every newsgroup.\n\
  248. v    Print version.\n\
  249. ",NOMARKING)) )
  250.     return cmd;
  251. #endif
  252. #ifdef PUSHBACK
  253.     if (cmd = get_anything())
  254.     return cmd;
  255.     show_macros();
  256. #endif
  257.     return 0;
  258. }
  259.  
  260. #ifdef ESCSUBS
  261. int
  262. help_subs()
  263. {
  264.     int cmd;
  265. #ifdef SUBSHELP
  266.     doshell(sh,filexp(SUBSHELP));
  267. #else
  268.     page_init();
  269.     if ((cmd = print_lines("\
  270. Valid substitutions are:\n\
  271. ",STANDOUT)) ||
  272.     (cmd = print_lines("\
  273. \n\
  274. a    Current article number\n\
  275. A    Full name of current article (%P/%c/%a)\n\
  276. b    Destination of last save command, often a mailbox\n\
  277. B    Bytes to ignore at beginning of last saved article\n\
  278. ",NOMARKING)) ||
  279.     (cmd = print_lines("\
  280. c    Current newsgroup, directory form\n\
  281. C    Current newsgroup, dot form\n\
  282. d    Full name of newsgroup directory (%P/%c)\n\
  283. D    Distribution line from current article\
  284. ",NOMARKING)) ||
  285.     (cmd = print_lines("\
  286. f    Who the current article is from\n\
  287. F    Newsgroups to followup to (from Newsgroups and Followup-To)\n\
  288. h    (This help message)\n\
  289. H    Host name (yours)\n\
  290. i    Message-I.D. line from current article, with <>\n\
  291. I    Reference indicator mark (see -F switch)\n\
  292. ",NOMARKING)) ||
  293.     (cmd = print_lines("\
  294. l    News administrator's login name, if any\n\
  295. L    Login name (yours)\n\
  296. m    Current mode, first letter of (init, newsgroup, article, pager,\n\
  297.         Add, Catchup, Delete bogus, Mailbox, Resubscribe)\n\
  298. M    Number of article marked with M\n\
  299. n    Newsgroups from current article\n\
  300. N    Full name (yours)\n\
  301. ",NOMARKING)) ||
  302.     (cmd = print_lines("\
  303. o    Organization (yours)\n\
  304. O    Original working directory (where you ran rn from)\n\
  305. p    Your private news directory (from -d)\n\
  306. P    Public news spool directory\n\
  307. ",NOMARKING)) ||
  308.     (cmd = print_lines("\
  309. r    Last reference (parent article id)\n\
  310. R    References list for followup article\n\
  311. s    Subject, with all Re's and (nf)'s stripped off\n\
  312. S    Subject, with one Re stripped off\
  313. ",NOMARKING)) ||
  314.     (cmd = print_lines("\
  315. t    New To line derived from From and Reply-To (Internet format)\n\
  316. T    New To line derived from Path\n\
  317. u    Number of unread articles\n\
  318. U    Number of unread articles not counting current article\n\
  319. x    News library directory\n\
  320. X    Rn library directory\n\
  321. z    Length of current article in bytes\n\
  322. ",NOMARKING)) ||
  323.     (cmd = print_lines("\
  324. ~    Your home directory\n\
  325. .    Directory containing . files\n\
  326. $    Current process number\n\
  327. /    Last search string\n\
  328. ESC    Run preceding command through % interpretation\n\
  329. ",NOMARKING)) )
  330.     return cmd;
  331. #endif
  332.     return 0;
  333. }
  334. #endif
  335.  
  336. !STUFFY!FUNK!
  337. echo Extracting head.c
  338. cat >head.c <<'!STUFFY!FUNK!'
  339. /* $Header: head.c,v 4.3.2.5 90/03/22 23:04:22 sob Exp $
  340.  *
  341.  * $Log:    head.c,v $
  342.  * Revision 4.3.2.5  90/03/22  23:04:22  sob
  343.  * Fixes provided by Wayne Davison <drivax!davison>
  344.  * 
  345.  * Revision 4.3.2.4  89/11/27  01:30:35  sob
  346.  * Altered NNTP code per ideas suggested by Bela Lubkin
  347.  * <filbo@gorn.santa-cruz.ca.us>
  348.  * 
  349.  * Revision 4.3.2.3  89/11/26  22:53:52  sob
  350.  * Add new patches to make RRN be faster.
  351.  * 
  352.  * Revision 4.3.2.2  89/11/08  01:17:46  sob
  353.  * Added changes to insure that this will compile for RN or RRN with no
  354.  * changes to the source code.
  355.  * 
  356.  * Revision 4.3.2.1  89/11/06  00:37:18  sob
  357.  * Added RRN support from NNTP 1.5
  358.  * 
  359.  * Revision 4.3.1.2  85/05/10  13:47:25  lwall
  360.  * Added debugging stuff.
  361.  * 
  362.  * Revision 4.3.1.1  85/05/10  11:32:30  lwall
  363.  * Branch for patches.
  364.  * 
  365.  * Revision 4.3  85/05/01  11:38:21  lwall
  366.  * Baseline for release with 4.3bsd.
  367.  * 
  368.  */
  369.  
  370. #include "EXTERN.h"
  371. #include "common.h"
  372. #include "artio.h"
  373. #include "bits.h"
  374. #ifdef SERVER
  375. #include "server.h"
  376. #endif
  377. #include "util.h"
  378. #include "INTERN.h"
  379. #include "head.h"
  380.  
  381. bool first_one;        /* is this the 1st occurance of this header line? */
  382.  
  383. static char htypeix[26] =
  384.     {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
  385.  
  386. void
  387. head_init()
  388. {
  389.     register int i;
  390.  
  391.     for (i=HEAD_FIRST+1; i<HEAD_LAST; i++)
  392.     htypeix[*htype[i].ht_name - 'a'] = i;
  393. }
  394.  
  395. #ifdef DEBUGGING
  396. dumpheader(where)
  397. char *where;
  398. {
  399.     register int i;
  400.  
  401.     printf("header: %d %s", parsed_art, where);
  402.  
  403.     for (i=0; i<HEAD_LAST; i++) {
  404.     printf("%15s %4d %4d %03o\n",htype[i].ht_name,
  405.         htype[i].ht_minpos,
  406.         htype[i].ht_maxpos,
  407.         htype[i].ht_flags) FLUSH;
  408.     }
  409. }
  410. #endif
  411.  
  412. int
  413. set_line_type(bufptr,colon)
  414. char *bufptr;
  415. register char *colon;
  416. {
  417.     char lc[LONGKEY+3];
  418.     register char *t, *f;
  419.     register int i, len;
  420.  
  421.     if (colon-bufptr > LONGKEY+2)
  422.     return SOME_LINE;
  423.  
  424.     for (t=lc,f=bufptr; f<colon; f++, t++) {
  425.     if (isspace(*f))
  426.     /* guard against space before : */
  427.         break;
  428.     *t = isupper(*f) ? tolower(*f) : *f;
  429.     }
  430.     *t = '\0';
  431.     f = lc;                /* get lc into register */
  432.     len = t - f;
  433.  
  434.     /* now scan the headtype table, backwards so we don't have to supply an
  435.      * extra terminating value, using first letter as index, and length as
  436.      * optimization to avoid calling subroutine strEQ unnecessarily.  Hauls.
  437.      */
  438.     
  439.     if (islower(*f)) {
  440.     for (i = htypeix[*f - 'a']; *htype[i].ht_name == *f; --i) {
  441.         if (len == htype[i].ht_length && strEQ(f, htype[i].ht_name)) {
  442.         return i;
  443.         }
  444.     }
  445.     }
  446.     return SOME_LINE;
  447. }
  448.  
  449. void
  450. start_header(artnum)
  451. ART_NUM artnum;
  452. {
  453.     register int i;
  454.  
  455. #ifdef DEBUGGING
  456.     if (debug & 4)
  457.     dumpheader("start_header\n");
  458. #endif
  459.     for (i=0; i<HEAD_LAST; i++) {
  460.     htype[i].ht_minpos = -1;
  461.     htype[i].ht_maxpos = 0;
  462.     }
  463.     in_header = SOME_LINE;
  464.     first_one = FALSE;
  465. #ifdef ASYNC_PARSE
  466.     parsed_art = artnum;
  467. #endif
  468. }
  469.  
  470. bool
  471. parseline(art_buf,newhide,oldhide)
  472. char *art_buf;
  473. int newhide, oldhide;
  474. {
  475.     if (*art_buf == ' ' || *art_buf == '\t')
  476.                     /* header continuation line? */
  477.     return oldhide;
  478.     else {                /* maybe another header line */
  479.     char *s;
  480.  
  481.     if (first_one) {        /* did we just pass 1st occurance? */
  482.         first_one = FALSE;
  483.         htype[in_header].ht_maxpos = artpos;
  484.                     /* remember where line left off */
  485.     }
  486.     s = index(art_buf,':');
  487.     if (s == Nullch) {
  488.                 /* is it the end of the header? */
  489.         htype[PAST_HEADER].ht_minpos =
  490.         (*art_buf == '\n') ? ftell(artfp) : artpos;
  491.                 /* remember where body starts */
  492.         in_header = PAST_HEADER;
  493.     }
  494.     else {    /* it is a new header line */
  495.         in_header = set_line_type(art_buf,s);
  496.         first_one = (htype[in_header].ht_minpos < 0);
  497.         if (first_one)
  498.         htype[in_header].ht_minpos = artpos;
  499. #ifdef DEBUGGING
  500.         if (debug & 4)
  501.         dumpheader(art_buf);
  502. #endif
  503.         if (htype[in_header].ht_flags & HT_HIDE)
  504.         return newhide;
  505.     }
  506.     }
  507.     return FALSE;            /* don't hide this line */
  508. }
  509.  
  510. #ifdef ASYNC_PARSE
  511. int
  512. parse_maybe(artnum)
  513. ART_NUM artnum;
  514. {
  515.     char tmpbuf[LBUFLEN];
  516.  
  517.     if (parsed_art == artnum)
  518.     return 0;
  519.     /* no maybe about it now */
  520. #ifdef SERVER
  521.     if (nntpopen(artnum,HEAD) == Nullfp) {
  522. #else
  523.     if (artopen(artnum) == Nullfp) {
  524. #endif
  525.     return -1;
  526.     }
  527.     start_header(artnum);
  528.     while (in_header) {
  529.     artpos = ftell(artfp);
  530.     if (fgets(tmpbuf,LBUFLEN,artfp) == Nullch)
  531.         break;
  532.     parseline(tmpbuf,FALSE,FALSE);
  533.     }
  534.     in_header = PAST_HEADER;
  535.     return 0;
  536. }
  537. #endif
  538.  
  539. /* get the subject line for an article */
  540.  
  541. char *
  542. fetchsubj(artnum,current_subject,copy)
  543. ART_NUM artnum;                /* article to get subject from */
  544. bool current_subject;            /* is it in a parsed header? */
  545. bool copy;                /* do you want it savestr()ed? */
  546. {
  547.     char *s = Nullch, *t;
  548. #ifdef SERVER
  549.     static int xhdr = 1;        /* Can we use xhdr command? */
  550.     int eoo;                /* End of server output */
  551.     char ser_line[256];
  552. #endif SERVER
  553.  
  554. #ifdef CACHESUBJ
  555.     if (!subj_list) {
  556.     register ART_NUM i;
  557.     
  558.  
  559. #ifndef lint
  560.     subj_list =
  561.       (char**)safemalloc((MEM_SIZE)((OFFSET(lastart)+2)*sizeof(char *)));
  562. #endif lint
  563.     for (i=0; i<=OFFSET(lastart); i++)
  564.         subj_list[i] = Nullch;
  565.     }
  566.     if (!artnum || artnum > lastart)
  567.     s = nullstr;
  568.     else
  569.     s = subj_list[OFFSET(artnum)];
  570. #endif
  571.     if (s == Nullch) {
  572.     if (current_subject) {
  573.         s = fetchlines(artnum,SUBJ_LINE);
  574. #ifdef CACHESUBJ
  575.         subj_list[OFFSET(artnum)] = s;
  576. #endif
  577.     }
  578.     else {
  579.         s = safemalloc((MEM_SIZE)256);
  580.         *s = '\0';
  581. #ifdef SERVER
  582.         if (xhdr) {
  583.             sprintf(ser_line, "XHDR subject %ld", artnum);
  584.             put_server(ser_line);
  585.         if (get_server(ser_line, sizeof (ser_line)) >= 0) {
  586.             if (ser_line[0] == CHAR_FATAL) {
  587.                 xhdr = 0;
  588.             } else {
  589.                 while (get_server(ser_line, sizeof (ser_line)) >= 0) {
  590.                 if (ser_line[0] == '.')
  591.                     break;
  592.                 else {
  593.                     t = index(ser_line, ' ');
  594.                     if (t++) {
  595.                     strcpy(s, t);
  596.                     if (t = index(s, '\r'))
  597.                         *t = '\0';
  598.                     }
  599.                 }
  600.                 }
  601.             }
  602.         } else {
  603.             fprintf(stderr,
  604.             "rrn: Unexpected close of server socket.\n");
  605.             finalize(1);
  606.         }
  607.         }
  608.  
  609.         if (!xhdr) {
  610.         sprintf(ser_line, "HEAD %ld", artnum);
  611.         put_server(ser_line);
  612.         eoo = 0;
  613.         if (get_server(ser_line, 256) >= 0 && ser_line[0] == CHAR_OK) {
  614.             do {
  615.             if (get_server(s, 256) < 0 || (*s == '.')) {
  616.             strcpy(s, "Title: \n");
  617.             eoo = 1;
  618.                 }
  619.             } while (strnNE(s,"Title:",6) && strnNE(s,"Subject:",8));
  620.  
  621.             if (!eoo)
  622.             while (get_server(ser_line, sizeof (ser_line)) >= 0 &&
  623.                 ser_line[0] != '.');
  624.             t = index(s,':')+1;
  625.             while (*t == ' ') t++;
  626.             strcpy(s, t);
  627.             }
  628.         }
  629. #else not SERVER
  630.         if (artopen(artnum) != Nullfp) {
  631.         do {
  632.             if (fgets(s,256,artfp) == Nullch)
  633.             strcpy(s, "Title: \n");
  634.         } while (strnNE(s,"Title:",6) && strnNE(s,"Subject:",8));
  635.  
  636.         s[strlen(s)-1] = '\0';
  637.         t = index(s,':')+1;
  638.         while (*t == ' ') t++;
  639.         strcpy(s, t);
  640.         }
  641. #endif
  642.         s = saferealloc(s, (MEM_SIZE)strlen(s)+1);
  643. #ifdef CACHESUBJ
  644.         subj_list[OFFSET(artnum)] = s;
  645. #endif 
  646.     }
  647.     }
  648. #ifdef CACHESUBJ
  649.     if (copy) {
  650.     t = savestr(s);
  651.     return t;
  652.     }
  653.     else
  654.     return s;
  655. #else
  656.     if (copy)
  657.     return s;
  658.     else {
  659.     safecpy(cmd_buf,s,CBUFLEN);    /* hope this is okay--we're */
  660.     free(s);
  661.     return cmd_buf;            /* really scraping for space here */
  662.     }
  663. #endif
  664. }
  665.  
  666. /* get header lines from an article */
  667.  
  668. char *
  669. fetchlines(artnum,which_line)
  670. ART_NUM artnum;                /* article to get line from */
  671. int which_line;                /* type of line desired */
  672. {
  673.     char *newbuf, *t, tmp_buf[LBUFLEN];
  674.     register ART_POS curpos;
  675.     int size;
  676.     register ART_POS firstpos;
  677.     register ART_POS lastpos;
  678.     
  679. #ifdef ASYNC_PARSE
  680.     if (parse_maybe(artnum))
  681.     artnum = 0;
  682. #endif
  683.     firstpos = htype[which_line].ht_minpos;
  684.     lastpos = htype[which_line].ht_maxpos;
  685. #ifdef SERVER
  686.     if (!artnum || firstpos < 0 || nntpopen(artnum,HEAD) == Nullfp) {
  687. #else
  688.     if (!artnum || firstpos < 0 || artopen(artnum) == Nullfp) {
  689. #endif
  690.     newbuf = safemalloc((unsigned int)1);
  691.     *newbuf = '\0';
  692.     return newbuf;
  693.     }
  694. #ifndef lint
  695.     size = lastpos - firstpos + 1;
  696. #else
  697.     size = Null(int);
  698. #endif lint
  699. #ifdef DEBUGGING
  700.     if (debug && (size < 1 || size > 1000)) {
  701.     printf("Firstpos = %ld, lastpos = %ld\n",(long)firstpos,(long)lastpos);
  702.     gets(tmp_buf);
  703.     }
  704. #endif
  705.     newbuf = safemalloc((unsigned int)size);
  706.     *newbuf = '\0';
  707.     fseek(artfp,firstpos,0);
  708.     for (curpos = firstpos; curpos < lastpos; curpos = ftell(artfp)) {
  709.     if (fgets(tmp_buf,LBUFLEN,artfp) == Nullch)
  710.         break;
  711.     if (*tmp_buf == ' ' || *tmp_buf == '\t')
  712.         t = tmp_buf;
  713.     else
  714.         t = index(tmp_buf,':')+1;
  715.     if (t == Nullch)
  716.         break;
  717.     else {
  718.         while (*t == ' ' || *t == '\t') t++;
  719.         safecat(newbuf,t,size);
  720.     }
  721.     }
  722.     return newbuf;
  723. }
  724.  
  725. !STUFFY!FUNK!
  726. echo Extracting init.c
  727. cat >init.c <<'!STUFFY!FUNK!'
  728. /* $Header: init.c,v 4.3.2.6 90/05/08 22:05:55 sob Exp $
  729.  *
  730.  * $Log:    init.c,v $
  731.  * Revision 4.3.2.6  90/05/08  22:05:55  sob
  732.  * Added quick startup (-q) flag.
  733.  * 
  734.  * Revision 4.3.2.5  90/05/04  23:10:01  sob
  735.  * Fix for exiting "second" rn such that tty will be left in correct state.
  736.  * Provided by glenn@mathcs.emory.edu
  737.  * 
  738.  * Revision 4.3.2.4  90/03/22  23:04:32  sob
  739.  * Fixes provided by Wayne Davison <drivax!davison>
  740.  * 
  741.  * Revision 4.3.2.3  90/03/17  21:34:04  sob
  742.  * Cleaned up a bit.
  743.  * 
  744.  * Revision 4.3.2.2  89/11/08  01:17:48  sob
  745.  * Added changes to insure that this will compile for RN or RRN with no
  746.  * changes to the source code.
  747.  * 
  748.  * Revision 4.3.2.1  89/11/06  00:39:14  sob
  749.  * Added RRN support from NNTP 1.5
  750.  * 
  751.  * Revision 4.3.1.4  86/09/05  14:24:02  lwall
  752.  * Removed net.announce dependency.
  753.  * 
  754.  * Revision 4.3.1.3  85/07/23  18:08:36  lwall
  755.  * Fixed up NOLINEBUF option to work.
  756.  * 
  757.  * Revision 4.3.1.2  85/05/21  14:22:46  lwall
  758.  * Sped up "rn -c" by avoiding unnecessary initialization.
  759.  * 
  760.  * Revision 4.3.1.1  85/05/10  11:33:39  lwall
  761.  * Branch for patches.
  762.  * 
  763.  * Revision 4.3  85/05/01  16:16:13  lwall
  764.  * Baseline for release with 4.3bsd.
  765.  * 
  766.  */
  767.  
  768. #include "EXTERN.h"
  769. #include "common.h"
  770. #include "util.h"
  771. #include "final.h"
  772. #include "term.h"
  773. #include "last.h"
  774. #include "rn.h"
  775. #include "rcstuff.h"
  776. #include "ngdata.h"
  777. #include "only.h"
  778. #include "intrp.h"
  779. #include "addng.h"
  780. #include "sw.h"
  781. #include "art.h"
  782. #include "artsrch.h"
  783. #include "artio.h"
  784. #include "backpage.h"
  785. #include "bits.h"
  786. #include "cheat.h"
  787. #include "head.h"
  788. #include "help.h"
  789. #include "kfile.h"
  790. #include "ngsrch.h"
  791. #include "ngstuff.h"
  792. #include "rcln.h"
  793. #include "respond.h"
  794. #ifdef SERVER
  795. #include "server.h"
  796. #endif
  797. #include "ng.h"
  798. #include "INTERN.h"
  799. #include "init.h"
  800.  
  801. bool
  802. initialize(argc,argv)
  803. int argc;
  804. char *argv[];
  805. {
  806.     char *tcbuf;
  807.     register bool foundany = FALSE;
  808.     long time();
  809. #ifdef SERVER
  810.     char *server;
  811.     int response;
  812. #endif SERVER
  813. #ifdef NOLINEBUF
  814.     static char std_out_buf[BUFSIZ];    /* must be static or malloced */
  815.  
  816.     setbuf(stdout, std_out_buf);
  817. #endif
  818.  
  819.     tcbuf = safemalloc(1024);        /* make temp buffer for termcap and */
  820.                     /* other initialization stuff */
  821.     
  822.     /* init terminal */
  823.     
  824.     term_init();            /* must precede sw_init() so that */
  825.                     /* ospeed is set for baud-rate */
  826.                     /* switches.  Actually terminal */
  827.                     /* mode setting is in term_set() */
  828.  
  829.     /* we have to know rnlib to look up global switches in %X/INIT */
  830.  
  831.     lib = savestr(filexp(LIB));
  832.     rnlib = savestr(filexp(RNLIB));
  833.  
  834.     /* decode switches */
  835.  
  836.     sw_init(argc,argv,&tcbuf);          /* must not do % interps! */
  837.                     /* (but may mung environment) */
  838.  
  839.     /* init signals, status flags */
  840.  
  841.     final_init();
  842.     
  843.     /* start up file expansion and the % interpreter */
  844.  
  845.     intrp_init(tcbuf);
  846.     
  847.     /* now make sure we have a current working directory */
  848.  
  849.     if (!checkflag)
  850.     cwd_check();
  851.     
  852.     /* now that we know where to save things, cd to news directory */
  853.  
  854.     if (chdir(spool)) {
  855.     printf(nocd,spool) FLUSH;
  856.     finalize(1);
  857.     }
  858.  
  859.     /* if we aren't just checking, turn off echo */
  860.  
  861.     if (!checkflag)
  862.     term_set(tcbuf);
  863.  
  864.     /* get info on last rn run, if any */
  865.  
  866.     if (!checkflag)
  867.     last_init(tcbuf);
  868.  
  869.     free(tcbuf);            /* recover 1024 bytes */
  870.  
  871.     /* make sure we are the sole possessors of .newsrc */
  872.  
  873.     if (!checkflag)
  874.     lock_check();
  875.  
  876.     /* check for news news */
  877.  
  878.     if (!checkflag)
  879.     newsnews_check();
  880.  
  881. #ifdef SERVER
  882.  
  883.     /* open connection to server if appropriate */
  884.  
  885.     server = getserverbyfile(SERVER_FILE);
  886.     if (server == NULL) {
  887.     fprintf(stderr, "Can't get the name of the news server from %s\n",
  888.         SERVER_FILE);
  889.     fprintf(stderr,
  890.       "Either fix this file, or put NNTPSERVER in your environment.\n");
  891.     finalize(1);
  892.     }
  893.  
  894.     response = server_init(server);
  895.     if (response < 0) {
  896.     fprintf(stderr,
  897.         "Couldn't connect to %s news server, try again later.\n",
  898.         server);
  899.     finalize(1);
  900.     }
  901.  
  902.     if (handle_server_response(response, server) < 0)
  903.     finalize(1);
  904.  
  905. #endif SERVER
  906.  
  907.     /* open active file, etc. */
  908.  
  909.     ngdata_init();
  910.  
  911.     /* now read in the .newsrc file */
  912.  
  913.     foundany = rcstuff_init();
  914.  
  915.     /* it looks like we will actually read something, so init everything */
  916.  
  917.     addng_init();
  918.     art_init();
  919.     artio_init();
  920.     artsrch_init();
  921.     backpage_init();
  922.     bits_init();
  923.     cheat_init();
  924.     head_init();
  925.     help_init();
  926.     kfile_init();
  927.     ng_init();
  928.     ngsrch_init();
  929.     ngstuff_init();
  930.     only_init();
  931.     rcln_init();
  932.     respond_init();
  933.     rn_init();
  934.     search_init();
  935.     util_init();
  936.  
  937. #ifdef FINDNEWNG
  938.     fstat(actfp->_file,&filestat);    /* did active file grow? */
  939.     /*
  940.      * Skip this check if the -q flag was given.
  941.      */
  942.     
  943.     if (!quickstart && filestat.st_size != lastactsiz) {
  944.     long actsiz = filestat.st_size;    /* remember new size */
  945.     NG_NUM oldnext = nextrcline;    /* remember # lines in newsrc */
  946. #ifdef FASTNEW
  947.     bool munged = writesoft || !lastactsiz;
  948.                     /* bad soft ptrs -> edited active */
  949. #else
  950.     bool munged = TRUE;        /* just assume .newsrc munged */
  951. #endif
  952.  
  953. #ifdef VERBOSE
  954.     IF(verbose)
  955.         fputs("\nChecking active list for new newsgroups...\n",stdout)
  956.           FLUSH;
  957.     ELSE
  958. #endif
  959. #ifdef TERSE
  960.         fputs("\nNew newsgroups:\n",stdout) FLUSH;
  961. #endif
  962. #ifdef FASTNEW
  963.     if (!munged) {            /* maybe just do tail of file? */
  964.         fseek(actfp,lastactsiz-1,0);
  965.         fgets(buf,LBUFLEN,actfp);
  966.         munged = (*buf != '\n');
  967.         if (!munged)
  968.         munged = newlist(munged,FALSE);
  969.     }
  970. #endif
  971.     if (munged) {            /* must we scan entire file? */
  972.         fseek(actfp,0L,0);        /* rewind active file */
  973.         newlist(munged,FALSE);      /* sure hope they use hashing... */
  974.     }
  975.     lastactsiz = actsiz;        /* remember for .rnlast */
  976.     if (nextrcline != oldnext) {    /* did we add any new groups? */
  977.         foundany = TRUE;        /* let main() know */
  978.         starthere = 0;              /* and start ng scan from the top */
  979.     }
  980.     }
  981. #endif
  982.     time(&lasttime);            /* remember when we inited-- */
  983.                     /* ends up back in .rnlast */
  984.     writelast();                       /* in fact, put it there now */
  985.     
  986. #ifdef FINDNEWNG
  987. # ifdef ONLY
  988.     if (maxngtodo)            /* patterns on command line? */
  989.     foundany |= scanactive();
  990. # endif
  991. #endif
  992.  
  993.     return foundany;
  994. }
  995.  
  996. /* make sure there is no rn out there already */
  997.  
  998. void
  999. lock_check()
  1000. {
  1001.     lockname = savestr(filexp(LOCKNAME));
  1002.     if (!checkflag) {
  1003.     tmpfp = fopen(lockname,"r");
  1004.     if (tmpfp != Nullfp) {
  1005.         int processnum;
  1006.     
  1007.         fgets(buf,LBUFLEN,tmpfp);
  1008.         fclose(tmpfp);
  1009.         processnum = atoi(buf);
  1010. #ifdef VERBOSE
  1011.         IF(verbose)
  1012.         printf("You seem to have left an rn running, process %d.\n",
  1013.             processnum) FLUSH;
  1014.         ELSE
  1015. #endif
  1016. #ifdef TERSE
  1017.         printf("Rn left running, #%d.\n", processnum) FLUSH;
  1018. #endif
  1019.         if (kill(processnum, SIGEMT)) {
  1020.                     /* does process not exist? */
  1021.                     /* (rn ignores SIGEMT) */
  1022.         sleep(2);
  1023. #ifdef VERBOSE
  1024.         IF(verbose)
  1025.             fputs("\n\
  1026. That process does not seem to exist anymore.  The count of read articles\n\
  1027. may be incorrect in the last newsgroup accessed by that other (defunct)\n\
  1028. process.\n\n",stdout) FLUSH;
  1029.         ELSE
  1030. #endif
  1031. #ifdef TERSE
  1032.             fputs("\nProcess crashed.\n",stdout) FLUSH;
  1033. #endif
  1034.         if (*lastngname) {
  1035. #ifdef VERBOSE
  1036.             IF(verbose)
  1037.             printf("(The last newsgroup accessed was %s.)\n\n",
  1038.             lastngname) FLUSH;
  1039.             ELSE
  1040. #endif
  1041. #ifdef TERSE
  1042.             printf("(In %s.)\n\n",lastngname) FLUSH;
  1043. #endif
  1044.         }
  1045.         get_anything();
  1046.         putchar('\n') FLUSH;
  1047.         }
  1048.         else {
  1049. #ifdef VERBOSE
  1050.         IF(verbose)
  1051.             fputs("\n\
  1052. You may not have two copies of rn running simultaneously.  Goodbye.\n\
  1053. ",stdout) FLUSH;
  1054.         ELSE
  1055. #endif
  1056. #ifdef TERSE
  1057.             fputs("\nCan't start another.\n",stdout) FLUSH;
  1058. #endif
  1059.                if (bizarre)
  1060.                  resetty();
  1061.         exit(0);
  1062.         }
  1063.     }
  1064.     tmpfp = fopen(lockname,"w");
  1065.     if (tmpfp == Nullfp) {
  1066.         printf(cantcreate,lockname) FLUSH;
  1067.         sig_catcher(0);
  1068.     }
  1069.     fprintf(tmpfp,"%d\n",getpid());
  1070.     fclose(tmpfp);
  1071.     }
  1072. }
  1073.  
  1074. void
  1075. newsnews_check()
  1076. {
  1077.     char *newsnewsname = filexp(NEWSNEWSNAME);
  1078.  
  1079.     if ((tmpfp = fopen(newsnewsname,"r")) != Nullfp) {
  1080.     fstat(tmpfp->_file,&filestat);
  1081.     if (filestat.st_mtime > lasttime) {
  1082.         while (fgets(buf,sizeof(buf),tmpfp) != Nullch)
  1083.         fputs(buf,stdout) FLUSH;
  1084.         get_anything();
  1085.         putchar('\n') FLUSH;
  1086.     }
  1087.     fclose(tmpfp);
  1088.     }
  1089. }
  1090. !STUFFY!FUNK!
  1091. echo Extracting ngdata.c
  1092. cat >ngdata.c <<'!STUFFY!FUNK!'
  1093. /* $Header: ngdata.c,v 4.3.2.10 90/04/14 22:05:15 sob Exp $
  1094.  *
  1095.  * $Log:    ngdata.c,v $
  1096.  * Revision 4.3.2.10  90/04/14  22:05:15  sob
  1097.  * Removed redundant declaration of active_name
  1098.  * 
  1099.  * Revision 4.3.2.9  90/03/22  23:04:55  sob
  1100.  * Fixes provided by Wayne Davison <drivax!davison>
  1101.  * 
  1102.  * Revision 4.3.2.8  90/03/17  20:50:51  sob
  1103.  * Fixes provided by stewart@netxcom.iad-nxe.global-mis.dhl.com to handle
  1104.  * flaky transfers of the active file from the server.
  1105.  * 
  1106.  * Revision 4.3.2.7  90/03/17  17:11:08  sob
  1107.  * Added support for CNEWS active file flags.
  1108.  *
  1109.  * Revision 4.3.2.6  89/12/08  22:42:04  sob
  1110.  * Corrected typo in an #ifdef statement pointed out by
  1111.  * jik@pit-manager.mit.edu
  1112.  * 
  1113.  * Revision 4.3.2.5  89/11/28  01:51:14  sob
  1114.  * Removed redundant #include directive.
  1115.  * 
  1116.  * Revision 4.3.2.4  89/11/27  01:31:07  sob
  1117.  * Altered NNTP code per ideas suggested by Bela Lubkin
  1118.  * <filbo@gorn.santa-cruz.ca.us>
  1119.  * 
  1120.  * Revision 4.3.2.3  89/11/08  02:41:40  sob
  1121.  * Removed unneeded subroutine.
  1122.  * 
  1123.  * Revision 4.3.2.2  89/11/08  02:24:31  sob
  1124.  * Integrated modifications from other RRN patches colleceted from USENET
  1125.  * 
  1126.  * Revision 4.3.2.1  89/11/06  00:42:43  sob
  1127.  * Added RRN support from NNTP 1.5
  1128.  * 
  1129.  * Revision 4.3  85/05/01  11:44:38  lwall
  1130.  * Baseline for release with 4.3bsd.
  1131.  * 
  1132.  */
  1133.  
  1134. #include "EXTERN.h"
  1135. #include "common.h"
  1136. #include "ndir.h"
  1137. #include "rcstuff.h"
  1138. #include "rn.h"
  1139. #include "intrp.h"
  1140. #include "final.h"
  1141. #include "rcln.h"
  1142. #include "util.h"
  1143. #ifdef SERVER
  1144. #include "server.h"
  1145. #endif
  1146. #include "INTERN.h"
  1147. #include "ngdata.h"
  1148.  
  1149. void
  1150. ngdata_init()
  1151. {
  1152. #ifdef SERVER
  1153.     char ser_line[256];
  1154.     char *cp;
  1155.     int entries;
  1156. #endif
  1157. /* The following is only for systems that do not zero globals properly */
  1158. #ifdef ZEROGLOB
  1159. # ifdef CACHEFIRST
  1160.     for (i=0; i<MAXRCLINE; i++)
  1161.     abs1st[i] = 0;
  1162. # endif
  1163. #endif    /* ZEROGLOB */
  1164.  
  1165.     /* open the active file */
  1166.  
  1167. #ifdef SERVER
  1168.  
  1169.     put_server("LIST");        /* tell server we want the active file */
  1170.     get_server(ser_line, sizeof(ser_line));
  1171.     if (*ser_line != CHAR_OK) {        /* and then see if that's ok */
  1172.     fprintf(stdout, "Can't get active file from server: \n%s\n", ser_line);
  1173.     finalize(1);
  1174.     }
  1175.  
  1176.     cp = filexp("/tmp/rrnact.%$");    /* make a temporary name */
  1177.     strcpy(active_name, cp);
  1178.     actfp = fopen(active_name, "w+");    /* and get ready */
  1179.     if (actfp == Nullfp) {
  1180.     printf(cantopen,active_name) FLUSH;
  1181.     finalize(1);
  1182.     }
  1183.  
  1184.     entries = 0;
  1185.     while (1) {
  1186.     if (get_server(ser_line, sizeof(ser_line)) < 0) {
  1187.         printf("Can't get active file from server:\ntransfer failed after %d entries\n", entries);
  1188.         finalize(1);
  1189.     }
  1190.     if (ser_line[0] == '.')        /* while there's another line */
  1191.         break;            /* get it and write it to */
  1192.     entries++;
  1193.     fputs(ser_line, actfp);
  1194.     putc('\n', actfp);
  1195.     }
  1196.  
  1197.     fseek(actfp,0L,0);        /* just get to the beginning */
  1198.  
  1199. #else not SERVER
  1200.  
  1201.     actfp = fopen(filexp(ACTIVE),"r");
  1202.     if (actfp == Nullfp) {
  1203.     printf(cantopen,filexp(ACTIVE)) FLUSH;
  1204.     finalize(1);
  1205.     }
  1206. #endif SERVER
  1207. }
  1208.  
  1209. /* find the maximum article number of a newsgroup */
  1210.  
  1211. ART_NUM
  1212. getngsize(num)
  1213. register NG_NUM num;
  1214. {
  1215.     register int len;
  1216.     register char *nam;
  1217.     char tmpbuf[80];
  1218.     ART_POS oldsoft;
  1219.  
  1220.     nam = rcline[num];
  1221.     len = rcnums[num] - 1;
  1222.     softtries++;
  1223. #ifdef DEBUGGING
  1224.     if (debug & DEB_SOFT_POINTERS)
  1225.     printf("Softptr = %ld\n",(long)softptr[num]) FLUSH;
  1226. #endif
  1227.     oldsoft = softptr[num];
  1228.     if ((softptr[num] = findact(tmpbuf, nam, len, (long)oldsoft)) >= 0) {
  1229.     if (softptr[num] != oldsoft) {
  1230.         softmisses++;
  1231.         writesoft = TRUE;
  1232.     }
  1233.     }
  1234.     else {
  1235.     softptr[num] = 0;
  1236.     if (rcchar[num] == ':')        /* unsubscribe quietly */
  1237.         rcchar[num] = NEGCHAR;
  1238.     return TR_BOGUS;        /* well, not so quietly, actually */
  1239.     }
  1240.     
  1241. #ifdef DEBUGGING
  1242.     if (debug & DEB_SOFT_POINTERS) {
  1243.     printf("Should be %ld\n",(long)softptr[num]) FLUSH;
  1244.     }
  1245. #endif
  1246. #ifdef MININACT
  1247.     {
  1248.     register char *s;
  1249.     ART_NUM tmp;
  1250.  
  1251.     for (s=tmpbuf+len+1; isdigit(*s); s++) ;
  1252.     if (tmp = atol(s))
  1253. #ifdef CACHEFIRST
  1254.         abs1st[num] = tmp;
  1255. #else
  1256.         abs1st = tmp;
  1257. #endif
  1258.     if (!in_ng) {
  1259.         for (s++; isdigit(*s); s++) ;
  1260.         while (isspace(*s)) s++;
  1261.         switch (*s) {
  1262.         case 'n': moderated = getval("NOPOSTRING"," (no posting)"); break;
  1263.         case 'm': moderated = getval("MODSTRING", " (moderated)"); break;
  1264.         /* This shouldn't even occur.  What are we doing in a non-existent
  1265.            group?  Disallow it. */
  1266.         case 'x': return TR_BOGUS;
  1267.         /* what should be done about refiled groups?  rn shouldn't even
  1268.            be in them (ie, if sci.aquaria is refiled to rec.aquaria, then
  1269.            get the news there) */
  1270.         case '=': return TR_BOGUS;
  1271.         default: moderated = nullstr;
  1272.         }
  1273.     }
  1274.     }
  1275. #endif
  1276.     return atol(tmpbuf+len+1);
  1277. }
  1278.  
  1279. ACT_POS
  1280. findact(outbuf,nam,len,suggestion)
  1281. char *outbuf;
  1282. char *nam;
  1283. int len;
  1284. long suggestion;
  1285. {
  1286.     ACT_POS retval;
  1287.  
  1288.     fseek(actfp,100000L,1);    /* hopefully this forces a reread */
  1289.     if (suggestion == 0L || fseek(actfp,suggestion,0) < 0 ||
  1290.       fgets(outbuf,80,actfp) == Nullch ||
  1291.       outbuf[len] != ' ' ||
  1292.       strnNE(outbuf,nam,len)) {
  1293. #ifdef DEBUGGING
  1294.     if (debug & DEB_SOFT_POINTERS)
  1295.         printf("Missed, looking for %s in %sLen = %d\n",nam,outbuf,len)
  1296.           FLUSH;
  1297. #endif
  1298.     fseek(actfp,0L,0);
  1299. #ifndef lint
  1300.     retval = (ACT_POS)ftell(actfp);
  1301. #else
  1302.     retval = Null(ACT_POS);
  1303. #endif lint
  1304.     while (fgets(outbuf,80,actfp) != Nullch) {
  1305.         if (outbuf[len] == ' ' && strnEQ(outbuf,nam,len))
  1306.         return retval;
  1307. #ifndef lint
  1308.         retval = (ACT_POS) ftell(actfp);
  1309. #endif lint
  1310.     }
  1311.     return (ACT_POS) -1;        /* well, not so quietly, actually */
  1312.     }
  1313.     else
  1314. #ifndef lint
  1315.     return (ACT_POS) suggestion;
  1316. #else
  1317.     return retval;
  1318. #endif lint
  1319.     /*NOTREACHED*/
  1320. }
  1321.  
  1322. /* determine the absolutely first existing article number */
  1323. #ifdef SERVER
  1324. ART_NUM
  1325. getabsfirst(ngnum,ngsize)
  1326. register NG_NUM ngnum;
  1327. ART_NUM ngsize;
  1328. {
  1329.     register ART_NUM a1st;
  1330. #ifndef MININACT
  1331.     char ser_line[256];
  1332.     ART_NUM x,y;
  1333. #endif
  1334.  
  1335. #ifdef CACHEFIRST
  1336.     if (a1st = abs1st[ngnum])
  1337.     return a1st;
  1338. #endif
  1339. #ifdef MININACT
  1340.     getngsize(ngnum);
  1341. # ifdef CACHEFIRST
  1342.     return abs1st[ngnum];
  1343. # else
  1344.     return abs1st;
  1345. # endif
  1346. #else
  1347.     sprintf(cp,"GROUP %s",rcline[ngnum]);
  1348.     put_server(cp);
  1349.     if (get_server(ser_line, sizeof(ser_line)) < 0) {
  1350.     fprintf(stderr, "rrn: Unexpected close of server socket.\n");
  1351.     finalize(1);
  1352.     }
  1353.     if (*ser_line != CHAR_OK) {        /* and then see if that's ok */
  1354.     a1st = ngsize+1;        /* nothing there */
  1355.     }
  1356.     (void) sscanf(ser_line,"%d%d%d",&x,&y,&a1st);
  1357. # ifdef CACHEFIRST
  1358.     abs1st[ngnum] = a1st;
  1359. # endif
  1360.     return a1st;
  1361. #endif
  1362. }
  1363. /* we already know the lowest article number with NNTP */
  1364. ART_NUM
  1365. getngmin(dirname,floor)
  1366. char *dirname;
  1367. ART_NUM floor;
  1368. {
  1369.     return(floor);
  1370. }
  1371. #else
  1372. ART_NUM
  1373. getabsfirst(ngnum,ngsize)
  1374. register NG_NUM ngnum;
  1375. ART_NUM ngsize;
  1376. {
  1377.     register ART_NUM a1st;
  1378. #ifndef MININACT
  1379.     char dirname[MAXFILENAME];
  1380. #endif
  1381.  
  1382. #ifdef CACHEFIRST
  1383.     if (a1st = abs1st[ngnum])
  1384.     return a1st;
  1385. #endif
  1386. #ifdef MININACT
  1387.     getngsize(ngnum);
  1388. # ifdef CACHEFIRST
  1389.     return abs1st[ngnum];
  1390. # else
  1391.     return abs1st;
  1392. # endif
  1393. #else not MININACT
  1394.     sprintf(dirname,"%s/%s",spool,getngdir(rcline[ngnum]));
  1395.     a1st = getngmin(dirname,0L);
  1396.     if (!a1st)                /* nothing there at all? */
  1397.     a1st = ngsize+1;        /* aim them at end of newsgroup */
  1398. # ifdef CACHEFIRST
  1399.     abs1st[ngnum] = a1st;
  1400. # endif
  1401.     return a1st;
  1402. #endif MININACT
  1403. }
  1404.  
  1405. /* scan a directory for minimum article number greater than floor */
  1406.  
  1407. ART_NUM
  1408. getngmin(dirname,floor)
  1409. char *dirname;
  1410. ART_NUM floor;
  1411. {
  1412.     register DIR *dirp;
  1413.     register struct DIRTYPE *dp;
  1414.     register ART_NUM min = 1000000;
  1415.     register ART_NUM maybe;
  1416.     register char *p;
  1417.     char tmpbuf[128];
  1418.     
  1419.     dirp = opendir(dirname);
  1420.     if (!dirp)
  1421.     return 0;
  1422.     while ((dp = readdir(dirp)) != Null(struct DIRTYPE *)) {
  1423.     if ((maybe = atol(dp->d_name)) < min && maybe > floor) {
  1424.         for (p = dp->d_name; *p; p++)
  1425.         if (!isdigit(*p))
  1426.             goto nope;
  1427.         if (*dirname == '.' && !dirname[1])
  1428.         stat(dp->d_name, &filestat);
  1429.         else {
  1430.         sprintf(tmpbuf,"%s/%s",dirname,dp->d_name);
  1431.         stat(tmpbuf, &filestat);
  1432.         }
  1433.         if (! (filestat.st_mode & S_IFDIR))
  1434.         min = maybe;
  1435.     }
  1436.       nope:
  1437.     ;
  1438.     }
  1439.     closedir(dirp);
  1440.     return min==1000000 ? 0 : min;
  1441. }
  1442. #endif
  1443. !STUFFY!FUNK!
  1444. echo Extracting artsrch.c
  1445. cat >artsrch.c <<'!STUFFY!FUNK!'
  1446. /* $Header: artsrch.c,v 4.3.2.4 89/11/27 01:30:00 sob Locked $
  1447.  *
  1448.  * $Log:    artsrch.c,v $
  1449.  * Revision 4.3.2.4  89/11/27  01:30:00  sob
  1450.  * Altered NNTP code per ideas suggested by Bela Lubkin
  1451.  * <filbo@gorn.santa-cruz.ca.us>
  1452.  * 
  1453.  * Revision 4.3.2.3  89/11/26  22:54:37  sob
  1454.  * Added new patches to make rrn faster.
  1455.  * 
  1456.  * Revision 4.3.2.2  89/11/26  22:20:57  sob
  1457.  * Added better NNTP support.
  1458.  * 
  1459.  * Revision 4.3.2.1  89/11/26  22:13:10  sob
  1460.  * Added support for NNTP
  1461.  * 
  1462.  * Revision 4.3  85/05/01  11:35:47  lwall
  1463.  * Baseline for release with 4.3bsd.
  1464.  * 
  1465.  */
  1466.  
  1467. #include "EXTERN.h"
  1468. #include "common.h"
  1469. #include "search.h"
  1470. #include "term.h"
  1471. #include "util.h"
  1472. #include "intrp.h"
  1473. #include "bits.h"
  1474. #include "kfile.h"
  1475. #include "head.h"
  1476. #include "final.h"
  1477. #include "cheat.h"
  1478. #ifdef SERVER
  1479. #include "server.h"
  1480. #endif
  1481. #include "ng.h"
  1482. #include "artio.h"
  1483. #include "INTERN.h"
  1484. #include "artsrch.h"
  1485.  
  1486. void
  1487. artsrch_init()
  1488. {
  1489. #ifdef ARTSEARCH
  1490. #ifdef ZEROGLOB
  1491.     init_compex(&sub_compex);
  1492.     init_compex(&art_compex);
  1493. #endif
  1494. #endif
  1495. }
  1496.  
  1497. /* search for an article containing some pattern */
  1498.  
  1499. #ifdef ARTSEARCH
  1500. int
  1501. art_search(patbuf,patbufsiz,get_cmd)
  1502. char *patbuf;                /* if patbuf != buf, get_cmd must */
  1503. int patbufsiz;
  1504. int get_cmd;                /*   be set to FALSE!!! */
  1505. {
  1506.     char *pattern;            /* unparsed pattern */
  1507.     register char cmdchr = *patbuf;    /* what kind of search? */
  1508.     register char *s;
  1509.     bool backward = cmdchr == '?' || cmdchr == Ctl('p');
  1510.                     /* direction of search */
  1511.     COMPEX *compex;            /* which compiled expression */
  1512.     char *cmdlst = Nullch;        /* list of commands to do */
  1513.     int normal_return = SRCH_NOTFOUND;    /* assume no commands */
  1514.     bool saltaway = FALSE;        /* store in KILL file? */
  1515.     char howmuch;            /* search just the subjects */
  1516.     bool doread;            /* search read articles? */
  1517.     bool foldcase = TRUE;        /* fold upper and lower case? */
  1518.  
  1519.     int_count = 0;
  1520.     if (cmdchr == '/' || cmdchr == '?') {    /* normal search? */
  1521.     if (get_cmd && buf == patbuf)
  1522.         if (!finish_command(FALSE))    /* get rest of command */
  1523.         return SRCH_ABORT;
  1524.     compex = &art_compex;
  1525.     if (patbuf[1]) {
  1526.         howmuch = 0;
  1527.         doread = FALSE;
  1528.     }
  1529.     else {
  1530.         howmuch = art_howmuch;
  1531.         doread = art_doread;
  1532.     }
  1533.     s = cpytill(buf,patbuf+1,cmdchr);/* ok to cpy buf+1 to buf */
  1534.     pattern = buf;
  1535.     if (*pattern) {
  1536.         if (*lastpat)
  1537.         free(lastpat);
  1538.         lastpat = savestr(pattern);
  1539.     }
  1540.     if (*s) {            /* modifiers or commands? */
  1541.         for (s++; *s && index("Kharc",*s); s++) {
  1542.         if (*s == 'h')        /* scan header */
  1543.             howmuch = 1;
  1544.         else if (*s == 'a')    /* scan article */
  1545.             howmuch = 2;
  1546.         else if (*s == 'r')    /* scan read articles */
  1547.             doread = TRUE;
  1548.         else if (*s == 'K')    /* put into KILL file */
  1549.             saltaway = TRUE;
  1550.         else if (*s == 'c')    /* make search case sensitive */
  1551.             foldcase = FALSE;
  1552.         }
  1553.     }
  1554.     while (isspace(*s) || *s == ':')
  1555.         s++;
  1556.     if (*s) {
  1557.         if (*s == 'm' || *s == 'M')
  1558.         doread = TRUE;
  1559.         if (*s == 'k')        /* grandfather clause */
  1560.         *s = 'j';
  1561.         cmdlst = savestr(s);
  1562.         normal_return = SRCH_DONE;
  1563.     }
  1564.     art_howmuch = howmuch;
  1565.     art_doread = doread;
  1566.     if (srchahead)
  1567.         srchahead = -1;
  1568.     }
  1569.     else {
  1570.     register char *h;
  1571.  
  1572.     howmuch = 0;            /* just search subjects */
  1573.     doread = (cmdchr == Ctl('p'));
  1574.     if (cmdchr == Ctl('n'))
  1575.         normal_return = SRCH_SUBJDONE;
  1576.     compex = &sub_compex;
  1577.     pattern = patbuf+1;
  1578.     strcpy(pattern,": *");
  1579.     h = pattern + strlen(pattern);
  1580.     interp(h,patbufsiz - (h-patbuf),"%s");    /* fetch current subject */
  1581.     if (cmdchr == 'K') {
  1582.         saltaway = TRUE;
  1583.         cmdchr = 'k';
  1584.     }
  1585.     if (cmdchr == 'k') {
  1586.         normal_return = SRCH_DONE;
  1587.         cmdlst = savestr("j");
  1588.         mark_as_read(art);        /* this article has this subject */
  1589.         if (!*h) {
  1590. #ifdef VERBOSE
  1591.         IF(verbose)
  1592.             fputs("\nCannot delete null subject.\n",stdout) FLUSH;
  1593.         ELSE
  1594. #endif
  1595. #ifdef TERSE
  1596.             fputs("\nNull subject.\n",stdout) FLUSH;
  1597. #endif
  1598.         return SRCH_ABORT;
  1599.         }
  1600. #ifdef VERBOSE
  1601.         else if (verbose)
  1602.         printf("\nMarking subject \"%s\" as read.\n",h) FLUSH;
  1603. #endif
  1604.     }
  1605.     else if (!srchahead)
  1606.         srchahead = -1;
  1607.     h[24] = '\0';        /* compensate for notesfiles */
  1608.     while (*h) {
  1609.         if (index("/\\[.^*$'\"",*h) != Nullch)
  1610.         *h++ = '.';
  1611.         else
  1612.         h++;
  1613.     }
  1614. #ifdef DEBUGGING
  1615.     if (debug) {
  1616.         printf("\npattern = %s\n",pattern) FLUSH;
  1617.     }
  1618. #endif
  1619.     }
  1620.     if ((s = compile(compex,pattern,TRUE,foldcase)) != Nullch) {
  1621.                     /* compile regular expression */
  1622.     printf("\n%s\n",s) FLUSH;
  1623.     return SRCH_ABORT;
  1624.     }
  1625. #ifdef KILLFILES
  1626.     if (saltaway) {
  1627.     char saltbuf[LBUFLEN];
  1628.  
  1629.     s = saltbuf;
  1630.     sprintf(s,"/%s/",pattern);
  1631.     s += strlen(s);
  1632.     if (doread)
  1633.         *s++ = 'r';
  1634.     if (howmuch==1)
  1635.         *s++ = 'h';
  1636.     else if (howmuch==2)
  1637.         *s++ = 'a';
  1638.     *s++ = ':';
  1639.     if (!cmdlst)
  1640.         cmdlst = savestr("j");
  1641.     safecpy(s,cmdlst,LBUFLEN-(s-saltbuf));
  1642.     kf_append(saltbuf);
  1643.     }
  1644. #endif
  1645.     if (cmdlst && index(cmdlst,'='))
  1646.     normal_return = SRCH_ERROR;    /* listing subjects is an error? */
  1647.     if (get_cmd) {
  1648.     fputs("\nSearching...\n",stdout) FLUSH;
  1649.                     /* give them something to read */
  1650.     }
  1651.     if (backward) {
  1652.     if (cmdlst && art < lastart)
  1653.         art++;            /* include current article */
  1654.     if (doread)
  1655.         check_first(absfirst);
  1656.     }
  1657.     else {
  1658.     if (art > lastart)
  1659.         art = (doread ? absfirst : firstart) - 1;
  1660.     else if (cmdlst && art > absfirst)
  1661.         art--;            /* include current article */
  1662.     check_first(art);
  1663.     }
  1664.     if (srchahead > 0) {
  1665.     if (!backward)
  1666.         art = srchahead - 1;
  1667.     srchahead = -1;
  1668.     }
  1669.     assert(!cmdlst || *cmdlst);
  1670.     for (;;) {
  1671.     if (int_count) {
  1672.         int_count = 0;
  1673.         if (cmdlst)
  1674.         free(cmdlst);
  1675.         return SRCH_INTR;
  1676.     }
  1677.     if (backward ?
  1678.         (--art < absfirst || (!doread && art < firstart)) :
  1679.         (++art > lastart)
  1680.       ) {            /* out of articles? */
  1681.         if (cmdlst)
  1682.         free(cmdlst);
  1683.         return normal_return;
  1684.     }
  1685.     /*NOSTRICT*/
  1686.     if (doread || !was_read(art)) {
  1687.         if (wanted(compex,art,howmuch)) {
  1688.                     /* does the shoe fit? */
  1689.         if (cmdlst) {
  1690.             if (perform(cmdlst,TRUE)) {
  1691.             if (cmdlst)
  1692.                 free(cmdlst);
  1693.             return SRCH_INTR;
  1694.             }
  1695.         }
  1696.         else {
  1697.             if (cmdlst)
  1698.             free(cmdlst);
  1699.             return SRCH_FOUND;
  1700.         }
  1701.         }
  1702.         else if (!cmdlst && ! (art%50)) {
  1703.         printf("...%ld",(long)art);
  1704.         fflush(stdout);
  1705.         }
  1706.     }
  1707.     }
  1708. }
  1709.  
  1710. /* determine if article fits pattern */
  1711. /* returns TRUE if it exists and fits pattern, FALSE otherwise */
  1712.  
  1713. bool
  1714. wanted(compex, artnum, scope)
  1715. COMPEX *compex;
  1716. ART_NUM artnum;
  1717. char scope;
  1718. {
  1719.     if (!scope) {
  1720.     char subj_buf[266];
  1721.     
  1722.     strcpy(subj_buf, "Subject: ");
  1723.     strncpy(subj_buf+9,fetchsubj(artnum,FALSE,FALSE),256);
  1724. #ifdef DEBUGGING
  1725.     if (debug & DEB_SEARCH_AHEAD)
  1726.         printf("%s\n",subj_buf) FLUSH;
  1727. #endif
  1728.     return execute(compex,subj_buf) != Nullch;
  1729.     }
  1730. #ifdef CACHESUBJ
  1731.     else
  1732.     fetchsubj(artnum,FALSE,FALSE);/* might as well get subject handy */
  1733. #endif
  1734.     
  1735. #ifdef SERVER
  1736.     if (scope == 1){
  1737.     if (nntpopen(artnum,HEAD) == Nullfp) /* we only need the header */
  1738.         return FALSE;
  1739.     }
  1740.     else
  1741. #endif
  1742.     if (artopen(artnum) == Nullfp)    /* ensure that article is open */
  1743.  
  1744.     return FALSE;            /* if not, return NO MATCH */
  1745.     scope--;
  1746.     while (fgets(buf,LBUFLEN,artfp) != Nullch) {
  1747.                     /* for each line of article */
  1748.     if (!scope && index(buf,':') == Nullch && *buf != ' ' && *buf != '\t')
  1749.                     /* if headers only and out of header */
  1750.         return FALSE;        /* say no go */
  1751.     if (execute(compex,buf) != Nullch) {
  1752.                     /* does pattern matcher match? */
  1753.         return TRUE;        /* say Eureka */
  1754.     }
  1755.     }
  1756.     return FALSE;            /* out of article, so no match */
  1757. }
  1758. #endif
  1759.  
  1760. !STUFFY!FUNK!
  1761. echo Extracting term.h
  1762. cat >term.h <<'!STUFFY!FUNK!'
  1763. /* $Header: term.h,v 4.3.2.2 90/04/06 20:35:34 sob Exp $
  1764.  *
  1765.  * $Log:    term.h,v $
  1766.  * Revision 4.3.2.2  90/04/06  20:35:34  sob
  1767.  * Added fixes for SCO Xenix sent by ronald@robobar.co.uk.
  1768.  * 
  1769.  * Revision 4.3.2.1  89/11/28  01:54:03  sob
  1770.  * Added better support for SIGWINCH.
  1771.  * 
  1772.  * Revision 4.3.1.2  85/05/13  15:52:05  lwall
  1773.  * Declared devtty on TERMIO system.
  1774.  * 
  1775.  * Revision 4.3.1.1  85/05/10  11:41:24  lwall
  1776.  * Branch for patches.
  1777.  * 
  1778.  * Revision 4.3  85/05/01  11:51:36  lwall
  1779.  * Baseline for release with 4.3bsd.
  1780.  * 
  1781.  */
  1782.  
  1783. #ifdef PUSHBACK
  1784. EXT char circlebuf[PUSHSIZE];
  1785. EXT int nextin INIT(0);
  1786. EXT int nextout INIT(0);
  1787. #ifdef PENDING
  1788. #ifdef FIONREAD
  1789. EXT long iocount INIT(0);
  1790. #ifndef lint
  1791. #define input_pending() (nextin!=nextout || (ioctl(0, FIONREAD, &iocount),(int)iocount))
  1792. #else
  1793. #define input_pending() bizarre
  1794. #endif lint
  1795. #else FIONREAD
  1796. #ifdef RDCHK
  1797. #define input_pending() (rdchk(0) > 0)        /* boolean only */
  1798. #else /*  RDCHK */
  1799. int circfill();
  1800. EXT int devtty INIT(0);
  1801. #ifndef lint
  1802. #define input_pending() (nextin!=nextout || circfill())
  1803. #else
  1804. #define input_pending() bizarre
  1805. #endif lint
  1806. #endif /* RDCHK */
  1807. #endif FIONREAD
  1808. #else PENDING
  1809. #ifndef lint
  1810. #define input_pending() (nextin!=nextout)
  1811. #else
  1812. #define input_pending() bizarre
  1813. #endif lint
  1814. #endif PENDING
  1815. #else PUSHBACK
  1816. #ifdef PENDING
  1817. #ifdef FIONREAD    /* must have FIONREAD or O_NDELAY for input_pending() */
  1818. #define read_tty(addr,size) read(0,addr,size)
  1819. #ifndef lint
  1820. #define input_pending() (ioctl(0, FIONREAD, &iocount),(int)iocount)
  1821. #else
  1822. #define input_pending() bizarre
  1823. #endif lint
  1824. EXT long iocount INIT(0);
  1825.  
  1826. #else FIONREAD
  1827.  
  1828. #ifdef RDCHK
  1829. #define input_pending() (rdchk(0) > 0)        /* boolean only */
  1830. #else /*  RDCHK */
  1831.  
  1832. EXT int devtty INIT(0);
  1833. EXT bool is_input INIT(FALSE);
  1834. EXT char pending_ch INIT(0);
  1835. #ifndef lint
  1836. #define input_pending() (is_input || (is_input=read(devtty,&pending_ch,1)))
  1837. #else
  1838. #define input_pending() bizarre
  1839. #endif lint
  1840. #endif /*  RDCHK */
  1841. #endif FIONREAD
  1842. #else PENDING
  1843. #define read_tty(addr,size) read(0,addr,size)
  1844. #define input_pending() (FALSE)
  1845. #endif PENDING
  1846. #endif PUSHBACK
  1847.  
  1848. /* stuff wanted by terminal mode diddling routines */
  1849.  
  1850. #ifdef TERMIO
  1851. EXT struct termio _tty, _oldtty;
  1852. #else
  1853. EXT struct sgttyb _tty;
  1854. EXT int _res_flg INIT(0);
  1855. #endif
  1856.  
  1857. EXT int _tty_ch INIT(2);
  1858. EXT bool bizarre INIT(FALSE);            /* do we need to restore terminal? */
  1859.  
  1860. /* terminal mode diddling routines */
  1861.  
  1862. #ifdef TERMIO
  1863.  
  1864. #define crmode() ((bizarre=1),_tty.c_lflag &=~ICANON,_tty.c_cc[VMIN] = 1,ioctl(_tty_ch,TCSETAF,&_tty))
  1865. #define nocrmode() ((bizarre=1),_tty.c_lflag |= ICANON,_tty.c_cc[VEOF] = CEOF,stty(_tty_ch,&_tty))
  1866. #define echo()     ((bizarre=1),_tty.c_lflag |= ECHO, ioctl(_tty_ch, TCSETA, &_tty))
  1867. #define noecho() ((bizarre=1),_tty.c_lflag &=~ECHO, ioctl(_tty_ch, TCSETA, &_tty))
  1868. #define nl()     ((bizarre=1),_tty.c_iflag |= ICRNL,_tty.c_oflag |= ONLCR,ioctl(_tty_ch, TCSETAW, &_tty))
  1869. #define nonl()     ((bizarre=1),_tty.c_iflag &=~ICRNL,_tty.c_oflag &=~ONLCR,ioctl(_tty_ch, TCSETAW, &_tty))
  1870. #define    savetty() (ioctl(_tty_ch, TCGETA, &_oldtty),ioctl(_tty_ch, TCGETA, &_tty))
  1871. #define    resetty() ((bizarre=0),ioctl(_tty_ch, TCSETAF, &_oldtty))
  1872. #define unflush_output()
  1873.  
  1874. #else
  1875.  
  1876. #define raw()     ((bizarre=1),_tty.sg_flags|=RAW, stty(_tty_ch,&_tty))
  1877. #define noraw()     ((bizarre=1),_tty.sg_flags&=~RAW,stty(_tty_ch,&_tty))
  1878. #define crmode() ((bizarre=1),_tty.sg_flags |= CBREAK, stty(_tty_ch,&_tty))
  1879. #define nocrmode() ((bizarre=1),_tty.sg_flags &= ~CBREAK,stty(_tty_ch,&_tty))
  1880. #define echo()     ((bizarre=1),_tty.sg_flags |= ECHO, stty(_tty_ch, &_tty))
  1881. #define noecho() ((bizarre=1),_tty.sg_flags &= ~ECHO, stty(_tty_ch, &_tty))
  1882. #define nl()     ((bizarre=1),_tty.sg_flags |= CRMOD,stty(_tty_ch, &_tty))
  1883. #define nonl()     ((bizarre=1),_tty.sg_flags &= ~CRMOD, stty(_tty_ch, &_tty))
  1884. #define    savetty() (gtty(_tty_ch, &_tty), _res_flg = _tty.sg_flags)
  1885. #define    resetty() ((bizarre=0),_tty.sg_flags = _res_flg, stty(_tty_ch, &_tty))
  1886. #ifdef LFLUSHO
  1887. #ifndef lint
  1888. EXT int lflusho INIT(LFLUSHO);
  1889. #else
  1890. EXT long lflusho INIT(LFLUSHO);
  1891. #endif lint
  1892. #define unflush_output() (ioctl(_tty_ch,TIOCLBIC,&lflusho))
  1893. #else
  1894. #define unflush_output()
  1895. #endif LFLUSHO
  1896. #endif TERMIO
  1897.  
  1898. #ifdef TIOCSTI
  1899. #ifdef lint
  1900. #define forceme(c) ioctl(_tty_ch,TIOCSTI,Null(long*))    /* ghad! */
  1901. #else
  1902. #define forceme(c) ioctl(_tty_ch,TIOCSTI,c) /* pass character in " " */
  1903. #endif lint
  1904. #else
  1905. #define forceme(c)
  1906. #endif
  1907.  
  1908. /* termcap stuff */
  1909.  
  1910. /*
  1911.  * NOTE: if you don't have termlib you'll either have to define these strings
  1912.  *    and the tputs routine, or you'll have to redefine the macros below
  1913.  */
  1914.  
  1915. #ifdef HAVETERMLIB
  1916. EXT char *BC INIT(Nullch);        /* backspace character */
  1917. EXT char *UP INIT(Nullch);        /* move cursor up one line */
  1918. EXT char *CR INIT(Nullch);        /* get to left margin, somehow */
  1919. EXT char *VB INIT(Nullch);        /* visible bell */
  1920. EXT char *CL INIT(Nullch);        /* home and clear screen */
  1921. EXT char *CE INIT(Nullch);        /* clear to end of line */
  1922. #ifdef CLEAREOL
  1923. EXT char *CM INIT(Nullch);        /* cursor motion -- PWP */
  1924. EXT char *HO INIT(Nullch);        /* home cursor -- PWP */
  1925. EXT char *CD INIT(Nullch);        /* clear to end of display -- PWP */
  1926. #endif CLEAREOL
  1927. EXT char *SO INIT(Nullch);        /* begin standout mode */
  1928. EXT char *SE INIT(Nullch);        /* end standout mode */
  1929. EXT int SG INIT(0);        /* blanks left by SO and SE */
  1930. EXT char *US INIT(Nullch);        /* start underline mode */
  1931. EXT char *UE INIT(Nullch);        /* end underline mode */
  1932. EXT char *UC INIT(Nullch);        /* underline a character, if that's how it's done */
  1933. EXT int UG INIT(0);        /* blanks left by US and UE */
  1934. EXT bool AM INIT(FALSE);        /* does terminal have automatic margins? */
  1935. EXT bool XN INIT(FALSE);        /* does it eat 1st newline after automatic wrap? */
  1936. EXT char PC INIT(0);        /* pad character for use by tputs() */
  1937. EXT short ospeed INIT(0);    /* terminal output speed, for use by tputs() */
  1938. EXT int LINES INIT(0), COLS INIT(0);    /* size of screen */
  1939. EXT int just_a_sec INIT(960);            /* 1 sec at current baud rate */
  1940.                     /* (number of nulls) */
  1941.  
  1942. /* define a few handy macros */
  1943.  
  1944. #define backspace() tputs(BC,0,putchr) FLUSH
  1945. #define clear() tputs(CL,LINES,putchr) FLUSH
  1946. #define erase_eol() tputs(CE,1,putchr) FLUSH
  1947. #ifdef CLEAREOL
  1948. #define clear_rest() tputs(CD,LINES,putchr) FLUSH    /* PWP */
  1949. #define maybe_eol() if(erase_screen&&can_home_clear)tputs(CE,1,putchr) FLUSH
  1950. #endif CLEAREOL
  1951. #define underline() tputs(US,1,putchr) FLUSH
  1952. #define un_underline() tputs(UE,1,putchr) FLUSH
  1953. #define underchar() tputs(UC,0,putchr) FLUSH
  1954. #define standout() tputs(SO,1,putchr) FLUSH
  1955. #define un_standout() tputs(SE,1,putchr) FLUSH
  1956. #define up_line() tputs(UP,1,putchr) FLUSH
  1957. #define carriage_return() tputs(CR,1,putchr) FLUSH
  1958. #define dingaling() tputs(VB,1,putchr) FLUSH
  1959. #else
  1960.   ????????        /* up to you */
  1961. #endif
  1962.  
  1963. EXT int page_line INIT(1);    /* line number for paging in print_line (origin 1) */
  1964.  
  1965. void    term_init();
  1966. void    term_set();
  1967. #ifdef PUSHBACK
  1968. void    pushchar();
  1969. void    mac_init();
  1970. void    mac_line();
  1971. void    show_macros();
  1972. #endif
  1973. char    putchr();    /* routine for tputs to call */
  1974. bool    finish_command();
  1975. void    eat_typeahead();
  1976. void    settle_down();
  1977. #ifndef read_tty
  1978.     int        read_tty();
  1979. #endif
  1980. void    underprint();
  1981. #ifdef NOFIREWORKS
  1982.     void    no_sofire();
  1983.     void    no_ulfire();
  1984. #endif
  1985. void    getcmd();
  1986. int    get_anything();
  1987. void    in_char();
  1988. int    print_lines();
  1989. void    page_init();
  1990. void    pad();
  1991. void    printcmd();
  1992. void    rubout();
  1993. void    reprint();
  1994. #ifdef CLEAREOL
  1995. void    home_cursor();
  1996. #endif CLEAREOL
  1997. #ifdef SIGWINCH
  1998. int    winch_catcher();
  1999. #endif /* SIGWINCH */
  2000. !STUFFY!FUNK!
  2001. echo Extracting Rnmail.SH
  2002. cat >Rnmail.SH <<'!STUFFY!FUNK!'
  2003. case $CONFIG in
  2004.     '') . config.sh ;;
  2005. esac
  2006. echo "Extracting Rnmail (with variable substitutions)"
  2007. $spitshell >Rnmail <<!GROK!THIS!
  2008. $startsh
  2009. # $Header: Rnmail.SH,v 4.3.2.1 89/11/06 00:30:54 sob Locked $
  2010. # $Log:    Rnmail.SH,v $
  2011. # Revision 4.3.2.1  89/11/06  00:30:54  sob
  2012. # Added RRN support from NNTP 1.5
  2013. # Revision 4.3.1.4  85/08/01  14:23:05  lwall
  2014. # Added MAILRECORD.  Temp file is no longer in /tmp.  'e editor' added.
  2015. # Revision 4.3.1.3  85/05/20  16:25:17  lwall
  2016. # Shouldn't ask editor if EDITOR or VISUAL defined.
  2017. # Revision 4.3.1.2  85/05/17  10:36:19  lwall
  2018. # Added "-- " before .signature.
  2019. # Revision 4.3.1.1  85/05/10  11:30:38  lwall
  2020. # Branch for patches.
  2021. # Revision 4.3  85/05/01  11:34:18  lwall
  2022. # Baseline for release with 4.3bsd.
  2023. #
  2024. # syntax: Rnmail -h headerfile [oldart]        or
  2025. #         Rnmail destination-list         or just
  2026. #         Rnmail
  2027.  
  2028. export PATH || (echo "OOPS, this isn't sh.  Desperation time.  I will feed myself to sh."; sh \$0; kill \$\$)
  2029.  
  2030. # System dependencies
  2031.  
  2032. mailer="${mailer-/bin/mail}"
  2033. # if you change this to something that does signatures, take out signature code
  2034.  
  2035. # your site name
  2036. case $portable in
  2037. define)
  2038.     sitename=\`$hostcmd\`
  2039.     case \$sitename in
  2040.         *.*)
  2041.             ;;
  2042.         *)
  2043.             sitename=\${sitename}.$domain
  2044.             ;;
  2045.     esac
  2046.     ;;
  2047. undef) sitename="$sitename" ;;
  2048. esac
  2049. # your organization name
  2050. orgname="$orgname"
  2051. # what pager you use--if you have kernal paging use cat
  2052. pager="\${PAGER-$pager}"
  2053. # how you derive full names, bsd, usg, or other
  2054. nametype="$nametype"
  2055. # default editor
  2056. defeditor="$defeditor"
  2057. # how not to do a newline with echo
  2058. n="$n"
  2059. c="$c"
  2060.  
  2061. test=${test-test}
  2062. sed=${sed-sed}
  2063. echo=${echo-echo}
  2064. cat=${cat-cat}
  2065. grep=${grep-grep}
  2066. rm=${rm-rm}
  2067.  
  2068. !GROK!THIS!
  2069. $spitshell >>Rnmail <<'!NO!SUBS!'
  2070. dotdir=${DOTDIR-${HOME-$LOGDIR}}
  2071. tmpart=$dotdir/.letter
  2072.  
  2073. headerfile=""
  2074. case $# in
  2075. 0) ;;
  2076. *)  case $1 in
  2077.     -h)
  2078.     headerfile="$2"
  2079.     case $# in
  2080.     3) oldart=$3 ;;
  2081.     esac
  2082.     ;;
  2083.     esac
  2084.     ;;
  2085. esac
  2086.  
  2087. case $headerfile in
  2088. '')
  2089.     case $# in
  2090.     0)
  2091.     to=h
  2092.     while $test "$to" = h ; do
  2093.         $echo ""
  2094.         $echo $n "To: $c"
  2095.         read to
  2096.         case $to in
  2097.         h)
  2098.         $cat <<'EOH'
  2099.  
  2100. Type the net address of those people that you wish the message sent to.
  2101. Additional recipients may be added on the Cc: line when you edit.
  2102.  
  2103. Separate multiple addresses with spaces.
  2104.  
  2105. EOH
  2106.         ;;
  2107.         esac
  2108.     done
  2109.     ;;
  2110.     *)
  2111.     to="$*"
  2112.     ;;
  2113.     esac
  2114.     to=`$echo "$to" | $sed 's/  */ /g'`
  2115.  
  2116.     title=h
  2117.     while $test "$title" = h ; do
  2118.     $echo ""
  2119.     $echo $n "Title/Subject: $c"
  2120.     read title
  2121.     case $title in
  2122.     h)
  2123.         $cat <<'EOH'
  2124.  
  2125. Type the title for your message.  
  2126. EOH
  2127.         ;;
  2128.     esac
  2129.     done
  2130.  
  2131. # now build a file with a header for them to edit
  2132.     
  2133.     orgname=${ORGANIZATION-$orgname}
  2134.     case $orgname in
  2135.     /*) orgname=`$cat $orgname` ;;
  2136.     esac
  2137.  
  2138.     $cat > $tmpart <<EOHeader
  2139. To: $to
  2140. Subject: $title
  2141. Organization: $orgname
  2142. Cc:
  2143. Bcc:
  2144.  
  2145. EOHeader
  2146.  
  2147.     ;;
  2148. *)
  2149.     $cat < $headerfile  > $tmpart
  2150.     ;;
  2151. esac
  2152.  
  2153.  
  2154. file=h
  2155. while $test "$file" = h ; do
  2156.     $echo ""
  2157.     $echo $n "Prepared file to include [none]: $c"
  2158.     read file
  2159.     case $file in
  2160.     h)
  2161.     $cat <<'EOH'
  2162.  
  2163. If you have already produced the body of your message, type the filename
  2164. for it here.  If you just want to proceed directly to the editor, type a
  2165. RETURN.  In any event, you will be allowed to edit as many times as you
  2166. want before you send off the message.
  2167. EOH
  2168.     ;;
  2169.     '')
  2170.     $echo "" >> $tmpart
  2171.     state=edit
  2172.     ;;
  2173.     *)
  2174.     $cat $file >>$tmpart
  2175.     state=ask
  2176.     ;;
  2177.     esac
  2178. done
  2179.  
  2180. $echo ""
  2181.  
  2182. while true ; do
  2183.     case $state in
  2184.     edit)
  2185.     rescue="sleep 1; $cat $tmpart >>${HOME-$LOGDIR}/dead.letter ; $echo Message appended to ${HOME-$LOGDIR}/dead.letter ; exit"
  2186.     trap "$rescue" 1
  2187.     trap : 2
  2188.     case "${VISUAL-${EDITOR-}}" in
  2189.     '')
  2190.         tmp=h
  2191.         ;;
  2192.     *)
  2193.         tmp=''
  2194.         ;;
  2195.     esac
  2196.     while $test "$tmp" = h ; do
  2197.         $echo $n "Editor [${VISUAL-${EDITOR-$defeditor}}]: $c"
  2198.         read tmp
  2199.         case $tmp in
  2200.         h)
  2201.         $cat <<'EOH'
  2202.  
  2203. Type a return to get the default editor, or type the name of the editor you
  2204. prefer.  The default editor depends on the VISUAL and EDITOR environment
  2205. variables.
  2206.  
  2207. EOH
  2208.         ;;
  2209.         '')
  2210.         ;;
  2211.         *)
  2212.         VISUAL=$tmp
  2213.         export VISUAL
  2214.         ;;
  2215.         esac
  2216.     done
  2217.     ${VISUAL-${EDITOR-$defeditor}} $tmpart $oldart
  2218.     trap "$rescue" 2
  2219.     state=ask
  2220.     ;;
  2221.     
  2222.     ask)
  2223.     $echo ""
  2224.     $echo $n "Send, abort, edit, or list? $c"
  2225.     read ans
  2226.     
  2227.     case $ans in
  2228.     a*)
  2229.         state=rescue
  2230.         ;;
  2231.     e*)
  2232.         set $ans
  2233.         case $# in
  2234.         2)  VISUAL="$2" ;;
  2235.         esac
  2236.         state=edit
  2237.         ;;
  2238.     l*)
  2239.         $pager $tmpart
  2240.         state=ask
  2241.         ;;
  2242.     s*)
  2243.         state=send
  2244.         ;;
  2245.     h*)
  2246.         $cat <<'EOH'
  2247.  
  2248. Type s to send the message, a to abort and append the message to dead.letter,
  2249. e to edit the message again, or l to list the message.
  2250.  
  2251. To invoke an alternate editor, type 'e editor'.
  2252. EOH
  2253.     esac
  2254.     ;;
  2255.     
  2256.     send)
  2257.     if $test -f $dotdir/.signature; then
  2258.         echo $n "Append .signature file? [y] $c"
  2259.         read ans
  2260.         case $ans in
  2261.         ''|y*)
  2262.         echo "-- " >> $tmpart
  2263.         cat $dotdir/.signature >> $tmpart
  2264.         ;;
  2265.         esac
  2266.     fi
  2267.     case $mailer in
  2268.     *sendmail)
  2269.         $mailer -t <$tmpart
  2270.         ;;
  2271. # but recmail does not know about Bcc, alas
  2272.     *recmail)
  2273.         $mailer <$tmpart
  2274.         ;;
  2275.     *)
  2276.         set X `$sed <$tmpart -n -e '/^To:/{' -e 's/To: *//p' -e q -e '}'`
  2277.         shift
  2278.         set X "$@" `$sed <$tmpart -n -e '/^Cc:/{' -e 's/Cc: *//p' -e q -e '}'`
  2279.         shift
  2280.         set X "$@" `$sed <$tmpart -n -e '/^Bcc:/{' -e 's/Bcc: *//p' -e q -e '}'`
  2281.         shift
  2282.         $grep -v "^Bcc:"  <$tmpart | $mailer "$@"
  2283.         ;;
  2284.     esac
  2285.     case $? in
  2286.     0)
  2287.         state=cleanup
  2288.         ;;
  2289.     *)
  2290.         state=rescue
  2291.         ;;
  2292.     esac
  2293.     ;;
  2294.     rescue)
  2295.     $cat $tmpart >> ${HOME-$LOGDIR}/dead.letter
  2296.     $echo "Message appended to ${HOME-$LOGDIR}/dead.letter"
  2297.     $echo "A copy may be temporarily found in $tmpart"
  2298.     exit
  2299.     ;;
  2300.     cleanup)
  2301.     case "${MAILRECORD-none}" in
  2302.     none)
  2303.         ;;
  2304.     *)  if $cat $tmpart >> $MAILRECORD; then
  2305.         $echo "Article appended to $MAILRECORD"
  2306.         else
  2307.         $echo "Cannot append to $MAILRECORD"
  2308.         fi
  2309.         ;;
  2310.     esac
  2311.     exit
  2312.     ;;
  2313.     esac
  2314. done
  2315. !NO!SUBS!
  2316. $eunicefix Rnmail
  2317. chmod 755 Rnmail
  2318. !STUFFY!FUNK!
  2319. echo Extracting kfile.c
  2320. cat >kfile.c <<'!STUFFY!FUNK!'
  2321. /* $Header: kfile.c,v 1.2 90/03/22 23:04:41 sob Exp $
  2322.  *
  2323.  * $Log:    kfile.c,v $
  2324.  * Revision 1.2  90/03/22  23:04:41  sob
  2325.  * Fixes provided by Wayne Davison <drivax!davison>
  2326.  * 
  2327.  * Revision 4.3.1.3  85/05/29  09:11:52  lwall
  2328.  * Suppressed some killing messages on -t.
  2329.  * 
  2330.  * Revision 4.3.1.2  85/05/10  14:21:29  lwall
  2331.  * Prevented THRU from setting art < absfirst.
  2332.  * 
  2333.  * Revision 4.3.1.1  85/05/10  11:34:33  lwall
  2334.  * Branch for patches.
  2335.  * 
  2336.  * Revision 4.3  85/05/01  11:41:53  lwall
  2337.  * Baseline for release with 4.3bsd.
  2338.  * 
  2339.  */
  2340.  
  2341. #include "EXTERN.h"
  2342. #include "common.h"
  2343. #include "term.h"
  2344. #include "util.h"
  2345. #include "artsrch.h"
  2346. #include "ng.h"
  2347. #include "bits.h"
  2348. #include "intrp.h"
  2349. #include "ngstuff.h"
  2350. #include "rcstuff.h"
  2351. #include "rn.h"
  2352. #include "INTERN.h"
  2353. #include "kfile.h"
  2354.  
  2355. static bool exitcmds = FALSE;
  2356.  
  2357. void
  2358. kfile_init()
  2359. {
  2360.     ;
  2361. }
  2362.  
  2363. #ifndef KILLFILES
  2364. int
  2365. edit_kfile()
  2366. {
  2367.     notincl("^K");
  2368.     return -1;
  2369. }
  2370.  
  2371. #else KILLFILES
  2372.  
  2373. char killglobal[] = KILLGLOBAL;
  2374. char killlocal[] = KILLLOCAL;
  2375.  
  2376. void
  2377. mention(str)
  2378. char *str;
  2379. {
  2380. #ifdef VERBOSE
  2381.     IF(verbose) {
  2382. #ifdef NOFIREWORKS
  2383.     no_sofire();
  2384. #endif
  2385.     standout();
  2386.     fputs(str,stdout);
  2387.     un_standout();
  2388.     putchar('\n');
  2389.     }
  2390.     ELSE
  2391. #endif
  2392. #ifdef TERSE
  2393.     putchar('.');
  2394. #endif
  2395.     fflush(stdout);
  2396. }
  2397.  
  2398. bool kill_mentioned;
  2399.  
  2400. int
  2401. do_kfile(kfp,entering)
  2402. FILE *kfp;
  2403. int entering;
  2404. {
  2405.     art = lastart+1;
  2406.     fseek(kfp,0L,0);            /* rewind file */
  2407.     while (fgets(buf,LBUFLEN,kfp) != Nullch) {
  2408.     buf[strlen(buf)-1] = '\0';
  2409.     if (strnEQ(buf,"THRU",4)) {
  2410.         ART_NUM tmpart;
  2411.  
  2412.         tmpart = atol(buf+4)+1;
  2413.         if (tmpart < absfirst)
  2414.         tmpart = absfirst;
  2415.         check_first(tmpart);
  2416.         firstart = tmpart;
  2417.         continue;
  2418.     }
  2419.     if (*buf == 'X') {        /* exit command? */
  2420.         if (entering) {
  2421.         exitcmds = TRUE;
  2422.         continue;
  2423.         }
  2424.         strcpy(buf,buf+1);
  2425.     }
  2426.     else {
  2427.         if (!entering)
  2428.         continue;
  2429.     }
  2430.     if (*buf == '&') {
  2431.         mention(buf);
  2432.         switcheroo();
  2433.     }
  2434.     else if (*buf == '/' && firstart <= lastart) {
  2435.         mention(buf);
  2436.         kill_mentioned = TRUE;
  2437.         switch (art_search(buf, (sizeof buf), FALSE)) {
  2438.         case SRCH_ABORT:
  2439.         continue;
  2440.         case SRCH_INTR:
  2441. #ifdef VERBOSE
  2442.         IF(verbose)
  2443.             printf("\n(Interrupted at article %ld)\n",(long)art)
  2444.               FLUSH;
  2445.         ELSE
  2446. #endif
  2447. #ifdef TERSE
  2448.             printf("\n(Intr at %ld)\n",(long)art) FLUSH;
  2449. #endif
  2450.         return -1;
  2451.         case SRCH_DONE:
  2452.         break;
  2453.         case SRCH_SUBJDONE:
  2454.         fputs("\tsubject not found (???)\n",stdout) FLUSH;
  2455.         break;
  2456.         case SRCH_NOTFOUND:
  2457.         fputs("\tnot found\n",stdout) FLUSH;
  2458.         break;
  2459.         case SRCH_FOUND:
  2460.         fputs("\tfound\n",stdout) FLUSH;
  2461.         }
  2462.     }
  2463.     }
  2464.     return 0;
  2465. }
  2466.  
  2467. void
  2468. kill_unwanted(starting,message,entering)
  2469. ART_NUM starting;
  2470. char *message;
  2471. int entering;
  2472. {
  2473.     bool intr = FALSE;            /* did we get an interrupt? */
  2474.     ART_NUM oldfirst;
  2475.     bool anytokill = (toread[ng] > 0);
  2476.  
  2477.     if (localkfp || globkfp) {
  2478.     if (!entering && !exitcmds)
  2479.         return;
  2480.     exitcmds = FALSE;
  2481.     oldfirst = firstart;
  2482.     firstart = starting;
  2483.     clear();
  2484. #ifdef VERBOSE
  2485. # ifdef TERSE
  2486.     if (message && (verbose || entering))
  2487. # else
  2488.     if (message)
  2489. # endif
  2490. #else
  2491.     if (message && entering)
  2492. #endif
  2493.         fputs(message,stdout) FLUSH;
  2494.  
  2495.     kill_mentioned = FALSE;
  2496.     if (localkfp)
  2497.         intr = do_kfile(localkfp,entering);
  2498.     if (globkfp && !intr)
  2499.         intr = do_kfile(globkfp,entering);
  2500.     if (entering && localkfp && !intr)
  2501.         setthru(lastart);
  2502.     putchar('\n') FLUSH;
  2503.     if (entering && kill_mentioned)
  2504. #ifdef VERBOSE
  2505.         IF(verbose)
  2506.         get_anything();
  2507.         ELSE
  2508. #endif
  2509. #ifdef TERSE
  2510.         pad(just_a_sec/3);
  2511. #endif
  2512.     if (anytokill)            /* if there was anything to kill */
  2513.         forcelast = FALSE;        /* allow for having killed it all */
  2514.     firstart = oldfirst;
  2515.     }
  2516. }
  2517.  
  2518. void
  2519. setthru(thru)
  2520. ART_NUM thru;
  2521. {
  2522.     FILE *newkfp;
  2523.  
  2524.     fseek(localkfp,0L,0);        /* rewind current file */
  2525.     strcpy(buf,filexp(getval("KILLLOCAL",killlocal)));
  2526.     UNLINK(buf);            /* to prevent file reuse */
  2527.     if (newkfp = fopen(buf,"w")) {
  2528.     fprintf(newkfp,"THRU %ld\n",(long)thru);
  2529.     while (fgets(buf,LBUFLEN,localkfp) != Nullch) {
  2530.         if (strnEQ(buf,"THRU",4))
  2531.         continue;
  2532.         fputs(buf,newkfp);
  2533.     }
  2534.     fclose(newkfp);
  2535.     open_kfile(KF_LOCAL);        /* and reopen local file */
  2536.     }
  2537.     else
  2538.     printf(cantcreate,buf) FLUSH;
  2539. }
  2540.  
  2541. /* edit KILL file for newsgroup */
  2542.  
  2543. int
  2544. edit_kfile()
  2545. {
  2546.     int r = -1;
  2547.  
  2548.     if (in_ng)
  2549.     strcpy(buf,filexp(getval("KILLLOCAL",killlocal)));
  2550.     else
  2551.     strcpy(buf,filexp(getval("KILLGLOBAL",killglobal)));
  2552.     if ((r = makedir(buf,MD_FILE)) >= 0) {
  2553.     sprintf(cmd_buf,"%s %s",
  2554.         filexp(getval("VISUAL",getval("EDITOR",defeditor))),buf);
  2555.     printf("\nEditing %s KILL file:\n%s\n",
  2556.         (in_ng?"local":"global"),cmd_buf) FLUSH;
  2557.     resetty();            /* make sure tty is friendly */
  2558.     r = doshell(sh,cmd_buf);/* invoke the shell */
  2559.     noecho();            /* and make terminal */
  2560.     crmode();            /*   unfriendly again */
  2561.     open_kfile(in_ng);
  2562.     }
  2563.     else
  2564.     printf("Can't make %s\n",buf) FLUSH;
  2565.     return r;
  2566. }
  2567.  
  2568. void
  2569. open_kfile(local)
  2570. int local;
  2571. {
  2572.     char *kname = filexp(local ?
  2573.     getval("KILLLOCAL",killlocal) :
  2574.     getval("KILLGLOBAL",killglobal)
  2575.     );
  2576.     
  2577.     stat(kname,&filestat);
  2578.     if (!filestat.st_size)        /* nothing in the file? */
  2579.     UNLINK(kname);            /* delete the file */
  2580.     if (local) {
  2581.     if (localkfp)
  2582.         fclose(localkfp);
  2583.     localkfp = fopen(kname,"r");
  2584.     }
  2585.     else {
  2586.     if (globkfp)
  2587.         fclose(globkfp);
  2588.     globkfp = fopen(kname,"r");
  2589.     }
  2590. }
  2591.  
  2592. void
  2593. kf_append(cmd)
  2594. char *cmd;
  2595. {
  2596.     strcpy(cmd_buf,filexp(getval("KILLLOCAL",killlocal)));
  2597.     if (makedir(cmd_buf,MD_FILE) >= 0) {
  2598. #ifdef VERBOSE
  2599.     IF(verbose)
  2600.         printf("\nDepositing command in %s...",cmd_buf);
  2601.     ELSE
  2602. #endif
  2603. #ifdef TERSE
  2604.         printf("\n--> %s...",cmd_buf);
  2605. #endif
  2606.     fflush(stdout);
  2607.     sleep(2);
  2608.     if ((tmpfp = fopen(cmd_buf,"a")) != Nullfp) {
  2609.         fseek(tmpfp,0L,2);        /* get to EOF for sure */
  2610.         fprintf(tmpfp,"%s\n",cmd);
  2611.         fclose(tmpfp);
  2612.         fputs("done\n",stdout) FLUSH;
  2613.     }
  2614.     else
  2615.         printf(cantopen,cmd_buf) FLUSH;
  2616.     }
  2617. }
  2618. #endif KILLFILES
  2619. !STUFFY!FUNK!
  2620. echo Extracting art.h
  2621. cat >art.h <<'!STUFFY!FUNK!'
  2622. /* $Header: art.h,v 4.3 85/05/01 11:35:29 lwall Exp $
  2623.  *
  2624.  * $Log:    art.h,v $
  2625.  * Revision 4.3  85/05/01  11:35:29  lwall
  2626.  * Baseline for release with 4.3bsd.
  2627.  * 
  2628.  */
  2629.  
  2630. /* do_article() return values */
  2631.  
  2632. #define DA_NORM 0
  2633. #define DA_RAISE 1
  2634. #define DA_CLEAN 2
  2635. #define DA_TOEND 3
  2636.  
  2637. void    art_init();
  2638. int    do_article();
  2639. int    page_switch();
  2640. bool    innermore();
  2641. !STUFFY!FUNK!
  2642. echo ""
  2643. echo "End of kit 7 (of 9)"
  2644. cat /dev/null >kit7isdone
  2645. config=true
  2646. for iskit in 1 2 3 4 5 6 7 8 9 ; do
  2647.     if test -f kit${iskit}isdone; then
  2648.     echo "You have run kit ${iskit}."
  2649.     else
  2650.     echo "You still need to run kit ${iskit}."
  2651.     config=false
  2652.     fi
  2653. done
  2654. case $config in
  2655.     true)
  2656.     echo "You have run all your kits.  Please read README and then type Configure."
  2657.     chmod 755 Configure
  2658.     ;;
  2659. esac
  2660. : I do not append .signature, but someone might mail this.
  2661. exit
  2662.