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

  1. Newsgroups: comp.sources.misc
  2. From: iain%anl433.uucp@Germany.EU.net (Iain Lea)
  3. Subject:  v31i014:  tin - threaded full screen newsreader v1.1 PL4, Part14/15
  4. Message-ID: <1992Jul7.182101.8177@sparky.imd.sterling.com>
  5. X-Md4-Signature: f0a2c1fdbf89b4e5a840df7cf7412fff
  6. Date: Tue, 7 Jul 1992 18:21:01 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 14
  11. Archive-name: tin/part14
  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:  CHANGES curses.c hashstr.c inews.c memory.c nntplib.h
  22. #   search.c wildmat.c
  23. # Wrapped by kent@sparky on Mon Jun 29 23:35:15 1992
  24. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  25. echo If this archive is complete, you will see the following message:
  26. echo '          "shar: End of archive 14 (of 15)."'
  27. if test -f 'CHANGES' -a "${1}" != "-c" ; then 
  28.   echo shar: Will not clobber existing file \"'CHANGES'\"
  29. else
  30.   echo shar: Extracting \"'CHANGES'\" \(8432 characters\)
  31.   sed "s/^X//" >'CHANGES' <<'END_OF_FILE'
  32. XCHANGES tin v1.1 PL3 -> tin 1.1 PL4
  33. X-----------------------------------
  34. X
  35. X1)  Iain Lea (iain%anl433.uucp@Germany.EU.net)
  36. X    ADD. Makefile - added entry for Stratus FTX machines.
  37. X
  38. X2)  Hakan Lennestal (hakanl@lulea.telesoft.se)
  39. X    BUG. Certain setuid() & setgid() no longer needed & should be removed.
  40. X    FIX. Applied supplied patch.
  41. X
  42. X3)  Hakan Lennestal (hakanl@lulea.telesoft.se)
  43. X    BUG. Follows to articles should be checked that the header is seperated 
  44. X         from the body by a blank line.
  45. X    FIX. Applied supplied patch.
  46. X
  47. X4)  Ken Taylor (ken@cujo.curtin.edu.au)
  48. X    BUG. Moving up a line in a group with no arts in group causes SIGSEGV(11).
  49. X    FIX. group.c - added check to see if any articles before moving up a line.
  50. X    
  51. X5)  Iain Lea (iain%anl433.uucp@Germany.EU.net)
  52. X    ADD.  post.c - added setuid info to bug report entry sent with 'B' command.
  53. X
  54. X6)  Doug Sewell (doug@cc.ysu.edu)
  55. X    BUG. #include file unistd.h does not exist on NeXT machines.
  56. X    FIX. tin.h - applied supplied patch.
  57. X
  58. X7)  Doug Sewell (doug@cc.ysu.edu)
  59. X    BUG. Every time tin starts via NNTP 5 unknown command errors are written
  60. X         to the NNTP logfile.
  61. X    FIX. open.c - added #ifdef NO_NNTP_EXTS to stop tin asking NNTP server
  62. X         which extensions it supports so that it can auto configure itself.
  63. X         This addition is just a nicety - it is not really necessary.
  64. X
  65. X8)  Doug Sewell (doug@cc.ysu.edu)
  66. X    BUG. Makefile does not work correctly on NeXT machines.
  67. X    FIX. tin.h - applied supplied patch.
  68. X
  69. X9)  Wolfgang Prediger (wp@orion.erls01.siemens.de)
  70. X    BUG. Does not resize in xterm under SVR4.
  71. X    FIX. tin.h - applied supplied patch.
  72. X
  73. X10) Paul Vickers (Paul.Vickers@barclays.co.uk)
  74. X    BUG. IBM RS6000 needs #include file netdb.h 
  75. X    FIX. inews.c - applied supplied patch.
  76. X
  77. X11) Iain Lea (iain%anl433.uucp@Germany.EU.net)
  78. X    BUG. -c catchup option does not work when reading index files via NNTP.
  79. X    FIX. main.c - added condition to check if -c flag is specified.
  80. X
  81. X12) Tom Hite (thite@micrografix.com)
  82. X    BUG. Wrong logic is used for freeing active attributes in memory.c
  83. X    FIX. memory.c - applied supplied patch.
  84. X
  85. X13) Sean Brady (brady@sed.stel.com)
  86. X    BUG. Hitting End/Home key causes SIGSEGV(11) at group index level.
  87. X    FIX. group.c - added checks to see if any articles are displayed.
  88. X
  89. X14) Iain Lea (iain%anl433.uucp@Germany.EU.net)
  90. X    BUG. SVR4 does not compile because SIGTYPE is wrong.
  91. X    FIX. tin.h - changed SIGTYPE to void if SVR4 defined. 
  92. X
  93. X15) Jim Morris (jegm@cody.esd.sgi.com)
  94. X    ADD. Makefile - added support for SGI Irix machines.
  95. X
  96. X16) Iain Lea (iain%anl433.uucp@Germany.EU.net)
  97. X    BUG. Stratus FTX entry duplicates SVR4 entry.
  98. X    FIX. Makefile - deleted stratus entry because its the same as the SVR4 entry.
  99. X
  100. X17) Greg Woods (woods%robohack.uucp@uunet.UU.NET)
  101. X    BUG. Man page is not correctly formatted.
  102. X    FIX. tin.1 - applied supllied patch. 
  103. X
  104. X18) Iain Lea (iain%anl433.uucp@Germany.EU.net)
  105. X    BUG. Compile options are spread all over Makefile. Should be in one place.
  106. X    FIX. Makefile - made configuration easier.
  107. X
  108. X19) Dean Schrimpf (ds11129@medtronic.com)
  109. X    BUG. Multiple copies of tind index daemon can be running simultaneously.
  110. X    FIX. init.c - added check to see if tind index daemon is already running.
  111. X
  112. X20) Jeb Palmer (jpalmer@sierra.com)
  113. X    BUG. When posting an article with vi as editor vi always complains that
  114. X         the file is not long enough to position the cursor at line n.
  115. X    FIX. post.c - applied supplied patch.
  116. X
  117. X21) Paul Bauwens (paul@pphbau.hobby.nl)
  118. X    BUG. Indexing of group sometimes hangs requiring tin to be killed. 
  119. X    FIX. art.c - applied supplied patch.
  120. X
  121. X22) James Nugen (jcn@jcnpc.uucp)
  122. X    BUG. Group select screen is redrawn double spaced when yanking in groups
  123. X         with long filenames.
  124. X    FIX. select.c - applied supplied patch.
  125. X
  126. X23) Chris Davies (chris@visionware.co.uk)
  127. X    BUG. Subdomains should be hidable. If NNTP_INEWS_DOMAIN is ".vision.co.uk"
  128. X         then use "chris@host.vision.co.uk", but if not with leading '.' hid
  129. X         local hostname ie. "chris@vision.co.uk"
  130. X    FIX. inews.c - applied supplied patch.
  131. X
  132. X24) Tom Parry (parry@yoyo.cc.monash.edu.au)
  133. X    BUG. screen does not create utmp entries which causes username not to be 
  134. X         found.
  135. X    FIX. init.c - applied supplied patch.
  136. X
  137. X25) Alex Pakter (alex@brt.com)
  138. X    BUG. Mismatched protypes cause compile warning on ?? machine.
  139. X    FIX. prompt.c - changed char parameter to int in prompt_num(). 
  140. X
  141. X26) Jim Robinson (robinson@mdivax1.mdd.comm.mot.com)
  142. X    FIXES. art.c - parse_headers() bug whereby if errno had previous 
  143. X           value of EINTR and article was less than sizeof(buf) bytes
  144. X           would get infinite loop.
  145. X           group.c - group_page() removed unnecessary make_threads() 
  146. X           in 'r' command resulting in substantial toggle speed up in
  147. X           large groups.
  148. X    ENHANCEMENTS curses.c - added ToggleInverse() routine.
  149. X           kill.c - added auto_select_articles() to perform auto selection.
  150. X           NOTE: this routine is presently a kludge, but exists to make 
  151. X           future changes a touch easier
  152. X           group.c thread.c - Added coded to highlight selected (hot) arts. 
  153. X
  154. X           Added a bunch of commands to manipulate selected articles. 
  155. X           Note that the characters  associated with each new command were
  156. X           chosen to correspond to a trn or nn equivalent command.
  157. X
  158. X27) Bill Poitras (bill@polygen.com)
  159. X    BUG. Unthreading groups at startup causes SIGSEGV error.
  160. X    FIX. active.c - check that array index variable is not less than 0.
  161. X
  162. X28) Hakan Lennestal (hakanl@lulea.telesoft.se)
  163. X    BUG. Certain systems use the setreuid() call to set real & effective uid.
  164. X    FIX. misc.c INSTALL - Applied supplied patch.
  165. X
  166. X29) Iain Lea (iain%anl433.uucp@Germany.EU.net)
  167. X    BUG. Major outcry from users about 'i' command being removed at group level
  168. X    FIX. group.c - readded the 'i' command. It *WILL* be removed *FOREVER* in 
  169. X         a future version.        
  170. X
  171. X30) Callum Gibson (callum@bain3.bain.oz.au)
  172. X    BUG. Does not compile on Pyramid machines.
  173. X    FIX. tin.h - applied supplied patch.
  174. X
  175. X31) Tony Travis (ajt@doc.ic.ac.uk)
  176. X    BUG. Sequent Dynix requires -lseq lib because of getopt().
  177. X    FIX. Makefile - added dynix make entry to Makefile.
  178. X
  179. X32) Iain Lea (iain%anl433.uucp@Germany.EU.net)
  180. X    BUG. Last group in chain is not accessed because of wrong test logic.
  181. X    FIX. active.c - changed code so that last group in chain is marked.
  182. X
  183. X33) Dean Schrimpf (ds11129@medtronic.com)
  184. X    BUG. Cross device renaming fails and trashes .newsrc file.
  185. X    FIX. misc.c - changed rename_file() to handle cross-device filenames.
  186. X
  187. X34) Marty Leisner (leisner@eso.mc.xerox.com)
  188. X    BUG. Add address is not added to bug address if on internal network.
  189. X    FIX. post.c - added code to add add_addr varaible contents to bug address.
  190. X
  191. X35) Iain Lea (iain%anl433.uucp@Germany.EU.net)
  192. X    BUG. Saving, mailing etc. an expired article within a thread caused 
  193. X         SIGSEGV error.
  194. X    FIX. feed.c - check if article is available before accessing it.
  195. X
  196. X36) Hakan Lennestal (hakanl@lulea.telesoft.se)
  197. X    BUG. Child processes are not waited for and therefore cause zombies.
  198. X    FIX. Applied supplied patch.
  199. X
  200. X37) Daniel Hermans (dmh@superb.mel.cocam.oz.au)
  201. X    BUG. Arrow keys on HP type terminals don't work.
  202. X    FIX. curses.c - Applied supplied patch.
  203. X
  204. X38) Iain Lea (iain%anl433.uucp@Germany.EU.net)
  205. X    ADD. kill - added kill/hot file of people that I find interesting
  206. X         (ie. Larry Wall , Chris Torek etc.) so that the auto-selection
  207. X         of interesting people can be shown automatically to new users.
  208. X         The file requires installing in ~/.tin
  209. X
  210. X39) Iain Lea (iain%anl433.uucp@Germany.EU.net)
  211. X    BUG. Temp index files are not deleted from /tmp if a crash occurs.
  212. X    FIX. signal.c - delete temp index files from the signal handler.
  213. X
  214. X40) Iain Lea (iain%anl433.uucp@Germany.EU.net)
  215. X    BUG. Default mailer for DG Aviion is wrong (/usr/ucb/Mail).
  216. X    FIX. tin.h - changed default mailer to /bin/mail
  217. X
  218. X41) John Scmitz (schmitz@scd.hp.com)
  219. X    BUG. 'sigtype_t (*susp)() = (sigtype_t *) 0;' causes compiler problem 
  220. X         under HP-UX 7.0
  221. X    FIX. kill.c misc.c rcfile.c - set default value after variable declaration.
  222. X
  223. X42) David Ross (dave@naskiska.ucs.ualberta.ca)
  224. X    BUG. Vi users are used to Ctrl-F & Ctrl-B to page forwards & backwards. 
  225. X    FIX. Added key code to recognize Ctrl-F & Ctrl-B at all levels.
  226. X
  227. END_OF_FILE
  228.   if test 8432 -ne `wc -c <'CHANGES'`; then
  229.     echo shar: \"'CHANGES'\" unpacked with wrong size!
  230.   fi
  231.   # end of 'CHANGES'
  232. fi
  233. if test -f 'curses.c' -a "${1}" != "-c" ; then 
  234.   echo shar: Will not clobber existing file \"'curses.c'\"
  235. else
  236.   echo shar: Extracting \"'curses.c'\" \(8719 characters\)
  237.   sed "s/^X//" >'curses.c' <<'END_OF_FILE'
  238. X/*
  239. X *  Project   : tin - a threaded Netnews reader
  240. X *  Module    : curses.c
  241. X *  Author    : D.Taylor & I.Lea
  242. X *  Created   : ??-??-86
  243. X *  Updated   : 20-06-92
  244. X *  Notes     : This is a screen management library borrowed with permission
  245. X *              from the Elm mail system (a great mailer--I highly recommend
  246. X *              it!).This library was hacked to provide what tin needs.
  247. X *  Copyright : Copyright (c) 1986-92 Dave Taylor & Iain Lea
  248. X *              The Elm Mail System  -  $Revision: 2.1 $   $State: Exp $
  249. X */
  250. X
  251. X#include <stdio.h>
  252. X#include <curses.h>
  253. X#include <sys/errno.h>
  254. X
  255. X#define DEFAULT_LINES_ON_TERMINAL    24
  256. X#define DEFAULT_COLUMNS_ON_TERMINAL    80
  257. X
  258. Xint LINES = 23;
  259. Xint COLS  = 80;
  260. Xint inverse_okay = TRUE;
  261. Xstatic int _inraw = FALSE;                  /* are we IN rawmode?    */
  262. X
  263. X
  264. X#ifndef INDEX_DAEMON
  265. X
  266. X#define        BACKSPACE    '\b'
  267. X#define        VERY_LONG_STRING    2500
  268. X
  269. X#ifdef BSD 
  270. X#    ifndef BSD4_1
  271. X#        include <sgtty.h>
  272. X#    else
  273. X#        include <termio.h>
  274. X#    endif
  275. X#else
  276. X#    ifndef SYSV
  277. X#        ifndef MINIX
  278. X#            ifdef sinix
  279. X#                include <termios.h>
  280. X#            else
  281. X#                include <termio.h>
  282. X#            endif
  283. X#        else
  284. X#            include <sgtty.h>
  285. X#        endif
  286. X#    endif
  287. X#endif
  288. X
  289. X#define TTYIN    0
  290. X
  291. X#ifdef SHORTNAMES
  292. X# define _clearinverse    _clrinv
  293. X# define _cleartoeoln    _clrtoeoln
  294. X# define _cleartoeos    _clr2eos
  295. X#endif
  296. X
  297. X#if defined(BSD) || defined(MINIX)
  298. X#    define TCGETA    TIOCGETP
  299. X#    define TCSETAW    TIOCSETP
  300. X
  301. Xstruct sgttyb _raw_tty,
  302. X          _original_tty;
  303. X#else
  304. X#    ifdef sinix
  305. X#        ifndef TCGETA
  306. X#            define TCGETA    STCGETA
  307. X#        endif
  308. X#        ifndef TCSETA
  309. X#            define TCSETAW    STCSETAW
  310. X#        endif
  311. Xstruct termios _raw_tty, 
  312. X              _original_tty;
  313. X#    else
  314. Xstruct termio _raw_tty, 
  315. X              _original_tty;
  316. X#    endif
  317. X#endif
  318. X
  319. Xstatic char *_clearscreen, *_moveto, *_cleartoeoln, *_cleartoeos,
  320. X            *_setinverse, *_clearinverse, *_setunderline, *_clearunderline,
  321. X            *_terminalinit, *_terminalend, *_keypadlocal, *_keypadxmit;
  322. X
  323. Xstatic int _lines,_columns;
  324. X
  325. Xstatic char _terminal[1024];              /* Storage for terminal entry */
  326. Xstatic char _capabilities[1024];           /* String for cursor motion */
  327. X
  328. Xstatic char *ptr = _capabilities;    /* for buffering         */
  329. X
  330. Xstatic int in_inverse;            /* 1 when in inverse, 0 otherwise */
  331. X
  332. Xint    outchar ();            /* char output for tputs */
  333. Xextern char    *tgetstr ();        /* Get termcap capability */
  334. Xextern char    *tgoto ();        /* and the goto stuff    */
  335. X
  336. X#endif /* INDEX_DAEMON */
  337. X
  338. X#include "tin.h"
  339. X
  340. X
  341. Xint InitScreen ()
  342. X{
  343. X#ifndef INDEX_DAEMON
  344. X
  345. X    extern int tgetent();      /* get termcap entry */
  346. X    char termname[40], *p;
  347. X    
  348. X    if ((p = (char *) getenv ("TERM")) == NULL) {
  349. X        fprintf (stderr, "%s: TERM variable must be set to use screen capabilities\n", progname);
  350. X        return (FALSE);
  351. X    }
  352. X    if (strcpy (termname, p) == NULL) {
  353. X        fprintf (stderr,"%s: Can't get TERM variable\n", progname);
  354. X        return (FALSE);
  355. X    }
  356. X    if (tgetent (_terminal, termname) != 1) {
  357. X        fprintf (stderr,"%s: Can't get entry for TERM\n", progname);
  358. X        return (FALSE);
  359. X    }
  360. X
  361. X    /* load in all those pesky values */
  362. X    _clearscreen    = tgetstr ("cl", &ptr);
  363. X    _moveto         = tgetstr ("cm", &ptr);
  364. X    _cleartoeoln    = tgetstr ("ce", &ptr);
  365. X    _cleartoeos     = tgetstr ("cd", &ptr);
  366. X    _lines          = tgetnum ("li");
  367. X    _columns        = tgetnum ("co");
  368. X    _setinverse     = tgetstr ("so", &ptr);
  369. X    _clearinverse   = tgetstr ("se", &ptr);
  370. X    _setunderline   = tgetstr ("us", &ptr);
  371. X    _clearunderline = tgetstr ("ue", &ptr);
  372. X    _terminalinit   = tgetstr ("ti", &ptr);
  373. X    _terminalend    = tgetstr ("te", &ptr);
  374. X    _keypadlocal    = tgetstr ("ke", &ptr);
  375. X    _keypadxmit     = tgetstr ("ks", &ptr);
  376. X
  377. X    InitWin ();
  378. X
  379. X    if (!_clearscreen) {
  380. X        fprintf (stderr,
  381. X            "%s: Terminal must have clearscreen (cl) capability\n",progname);
  382. X        return (FALSE);
  383. X    }
  384. X    if (!_moveto) {
  385. X        fprintf (stderr,
  386. X            "%s: Terminal must have cursor motion (cm)\n", progname);
  387. X        return (FALSE);
  388. X    }
  389. X    if (!_cleartoeoln) {
  390. X        fprintf (stderr,
  391. X            "%s: Terminal must have clear to end-of-line (ce)\n", progname);
  392. X        return (FALSE);
  393. X    }
  394. X    if (!_cleartoeos) {
  395. X        fprintf (stderr,
  396. X            "%s: Terminal must have clear to end-of-screen (cd)\n", progname);
  397. X        return (FALSE);
  398. X    }
  399. X    if (_lines == -1)
  400. X        _lines = DEFAULT_LINES_ON_TERMINAL;
  401. X    if (_columns == -1)
  402. X        _columns = DEFAULT_COLUMNS_ON_TERMINAL;
  403. X    /* kludge to workaround no inverse */
  404. X    if (_setinverse == 0) {
  405. X        _setinverse = _setunderline;
  406. X        _clearinverse = _clearunderline;
  407. X        if (_setinverse == 0)
  408. X            draw_arrow_mark = 1;
  409. X    }
  410. X    return (TRUE);
  411. X
  412. X#else
  413. X
  414. X    return (FALSE);
  415. X
  416. X#endif /* INDEX_DAEMON */
  417. X}
  418. X
  419. X/*
  420. X *  returns the number of lines and columns on the display.
  421. X */
  422. Xvoid ScreenSize (num_lines, num_columns)
  423. X    int *num_lines, *num_columns;
  424. X{
  425. X#ifndef INDEX_DAEMON
  426. X
  427. X    if (_lines == 0) _lines = DEFAULT_LINES_ON_TERMINAL;
  428. X    if (_columns == 0) _columns = DEFAULT_COLUMNS_ON_TERMINAL;
  429. X
  430. X    *num_lines = _lines - 1;        /* assume index from zero*/
  431. X    *num_columns = _columns;        /* assume index from one */
  432. X
  433. X#endif /* INDEX_DAEMON */
  434. X}
  435. X
  436. Xvoid InitWin ()
  437. X{
  438. X#ifndef INDEX_DAEMON
  439. X
  440. X    if (_terminalinit) {
  441. X        tputs (_terminalinit, 1, outchar);
  442. X        fflush (stdout);
  443. X    }    
  444. X    set_keypad_on ();
  445. X
  446. X#endif /* INDEX_DAEMON */
  447. X}
  448. X
  449. Xvoid EndWin ()
  450. X{
  451. X#ifndef INDEX_DAEMON
  452. X
  453. X    if (_terminalend) {
  454. X        tputs (_terminalend, 1, outchar);
  455. X        fflush (stdout);
  456. X    }
  457. X    set_keypad_off ();
  458. X    
  459. X    
  460. X#endif /* INDEX_DAEMON */
  461. X}
  462. X
  463. Xvoid set_keypad_on ()
  464. X{
  465. X#ifndef INDEX_DAEMON
  466. X/*
  467. X     if (_keypadxmit) {
  468. X        tputs (_keypadxmit, 1, outchar);
  469. X        fflush (stdout);
  470. X    }
  471. X*/
  472. X#endif /* INDEX_DAEMON */
  473. X}
  474. X
  475. Xvoid set_keypad_off ()
  476. X{
  477. X#ifndef INDEX_DAEMON
  478. X/*
  479. X    if (_keypadlocal) {
  480. X        tputs (_keypadlocal, 1, outchar);
  481. X        fflush (stdout);
  482. X    }
  483. X*/
  484. X#endif /* INDEX_DAEMON */
  485. X}
  486. X
  487. X/*
  488. X *  clear the screen: returns -1 if not capable
  489. X */
  490. X
  491. Xvoid ClearScreen ()
  492. X{
  493. X#ifndef INDEX_DAEMON
  494. X
  495. X    tputs (_clearscreen, 1, outchar);
  496. X    fflush (stdout);      /* clear the output buffer */
  497. X
  498. X#endif /* INDEX_DAEMON */
  499. X}
  500. X
  501. X/*
  502. X *  move cursor to the specified row column on the screen.
  503. X *  0,0 is the top left!
  504. X */
  505. X
  506. Xvoid MoveCursor (row, col)
  507. X    int row, col;
  508. X{
  509. X#ifndef INDEX_DAEMON
  510. X
  511. X    char *stuff, *tgoto();
  512. X
  513. X    stuff = tgoto (_moveto, col, row);
  514. X    tputs (stuff, 1, outchar);
  515. X    fflush (stdout);
  516. X
  517. X#endif /* INDEX_DAEMON */
  518. X}
  519. X
  520. X/*
  521. X *  clear to end of line
  522. X */
  523. X
  524. Xvoid CleartoEOLN ()
  525. X{
  526. X#ifndef INDEX_DAEMON
  527. X
  528. X    tputs (_cleartoeoln, 1, outchar);
  529. X    fflush (stdout);  /* clear the output buffer */
  530. X
  531. X#endif /* INDEX_DAEMON */
  532. X}
  533. X
  534. X/*
  535. X *  clear to end of screen
  536. X */
  537. X
  538. Xvoid CleartoEOS ()
  539. X{
  540. X#ifndef INDEX_DAEMON
  541. X
  542. X    int i;
  543. X    
  544. X    if (_cleartoeos) {
  545. X        tputs (_cleartoeos, 1, outchar);
  546. X    } else {
  547. X        for (i=_lines ; i < _lines ; i++) {
  548. X            MoveCursor (i, 0);
  549. X            CleartoEOLN ();
  550. X        }
  551. X    }
  552. X    fflush (stdout);  /* clear the output buffer */
  553. X
  554. X#endif /* INDEX_DAEMON */
  555. X}
  556. X
  557. X/*
  558. X *  set inverse video mode
  559. X */
  560. X
  561. Xvoid StartInverse ()
  562. X{
  563. X#ifndef INDEX_DAEMON
  564. X
  565. X    in_inverse = 1;
  566. X    if (_setinverse && inverse_okay)
  567. X        tputs (_setinverse, 1, outchar);
  568. X    fflush (stdout);
  569. X
  570. X#endif /* INDEX_DAEMON */
  571. X}
  572. X
  573. X/*
  574. X *  compliment of startinverse
  575. X */
  576. X
  577. Xvoid EndInverse ()
  578. X{
  579. X#ifndef INDEX_DAEMON
  580. X
  581. X    in_inverse = 0;
  582. X    if (_clearinverse && inverse_okay)
  583. X        tputs (_clearinverse, 1, outchar);
  584. X    fflush (stdout);
  585. X
  586. X#endif /* INDEX_DAEMON */
  587. X}
  588. X
  589. X/*
  590. X *  toggle inverse video mode
  591. X */
  592. X
  593. Xvoid ToggleInverse ()
  594. X{
  595. X#ifndef INDEX_DAEMON
  596. X
  597. X    if (in_inverse == 0)
  598. X        StartInverse();
  599. X    else
  600. X        EndInverse();
  601. X
  602. X#endif /* INDEX_DAEMON */
  603. X}
  604. X
  605. X/*
  606. X *  returns either 1 or 0, for ON or OFF
  607. X */
  608. X
  609. Xint RawState()
  610. X{
  611. X    return (_inraw);
  612. X}
  613. X
  614. X/*
  615. X *  state is either TRUE or FALSE, as indicated by call
  616. X */
  617. X
  618. Xvoid Raw(state)
  619. X    int state;
  620. X{
  621. X#ifndef INDEX_DAEMON
  622. X
  623. X    if (state == FALSE && _inraw) {
  624. X      (void) ioctl(TTYIN, TCSETAW, &_original_tty);
  625. X      _inraw = 0;
  626. X    }
  627. X    else if (state == TRUE && ! _inraw) {
  628. X
  629. X      (void) ioctl(TTYIN, TCGETA, &_original_tty);    /** current setting **/
  630. X
  631. X      (void) ioctl(TTYIN, TCGETA, &_raw_tty);    /** again! **/
  632. X#if defined(BSD) || defined(MINIX)
  633. X      _raw_tty.sg_flags &= ~(ECHO | CRMOD);    /* echo off */
  634. X      _raw_tty.sg_flags |= CBREAK;    /* raw on    */
  635. X#else
  636. X      _raw_tty.c_lflag &= ~(ICANON | ECHO);    /* noecho raw mode        */
  637. X
  638. X      _raw_tty.c_cc[VMIN] = '\01';    /* minimum # of chars to queue    */
  639. X      _raw_tty.c_cc[VTIME] = '\0';    /* minimum time to wait for input */
  640. X#endif
  641. X
  642. X      (void) ioctl(TTYIN, TCSETAW, &_raw_tty);
  643. X
  644. X      _inraw = 1;
  645. X    }
  646. X    
  647. X#endif /* INDEX_DAEMON */
  648. X}
  649. X
  650. X/*
  651. X *  read a character with Raw mode set!
  652. X */
  653. X
  654. Xint ReadCh()
  655. X{
  656. X#ifndef INDEX_DAEMON
  657. X    extern int errno;
  658. X    char ch;
  659. X    register int result = 0;
  660. X    
  661. X#ifdef READ_CHAR_HACK
  662. X#undef getc
  663. X    while ((result = getc(stdin)) == EOF) {
  664. X        if (feof(stdin))
  665. X            break;
  666. X
  667. X        if (ferror(stdin) && errno != EINTR)
  668. X            break;
  669. X
  670. X        clearerr(stdin);
  671. X    }
  672. X
  673. X    return ((result == EOF) ? EOF : result & 0xFF);
  674. X#else
  675. X
  676. X    while ((result = read(0, &ch, 1)) < 0 && errno == EINTR)
  677. X        ;    /* spin on signal interrupts */
  678. X
  679. X        return((result <= 0 ) ? EOF : ch & 0xFF);
  680. X#endif        
  681. X
  682. X#endif /* INDEX_DAEMON */
  683. X}
  684. X
  685. X/*
  686. X *  output a character. From tputs... (Note: this CANNOT be a macro!)
  687. X */
  688. X
  689. Xint outchar(c)
  690. X    char c;
  691. X{
  692. X    fputc (c, stdout);
  693. X}
  694. END_OF_FILE
  695.   if test 8719 -ne `wc -c <'curses.c'`; then
  696.     echo shar: \"'curses.c'\" unpacked with wrong size!
  697.   fi
  698.   # end of 'curses.c'
  699. fi
  700. if test -f 'hashstr.c' -a "${1}" != "-c" ; then 
  701.   echo shar: Will not clobber existing file \"'hashstr.c'\"
  702. else
  703.   echo shar: Extracting \"'hashstr.c'\" \(2510 characters\)
  704.   sed "s/^X//" >'hashstr.c' <<'END_OF_FILE'
  705. X/*
  706. X *  Project   : tin - a threaded Netnews reader
  707. X *  Module    : hashstr.c
  708. X *  Author    : I.Lea & R.Skrenta
  709. X *  Created   : 01-04-91
  710. X *  Updated   : 21-03-92
  711. X *  Notes     :
  712. X *  Copyright : (c) Copyright 1991-92 by Iain Lea & Rich Skrenta
  713. X *              You may  freely  copy or  redistribute  this software,
  714. X *              so  long as there is no profit made from its use, sale
  715. X *              trade or  reproduction.  You may not change this copy-
  716. X *              right notice, and it must be included in any copy made
  717. X */
  718. X
  719. X#include    "tin.h"
  720. X
  721. X/*
  722. X *  Maintain a table of all strings we have seen.
  723. X *  If a new string comes in, add it to the table and return a pointer
  724. X *  to it.  If we've seen it before, just return the pointer to it.
  725. X *
  726. X *  Usage:  hash_str("some string") returns char *
  727. X *
  728. X *  Spillovers are chained on the end
  729. X */
  730. X
  731. X/*
  732. X *  Arbitrary table size, but make sure it's prime!
  733. X */
  734. X
  735. X#define        HASHNODE_TABLE_SIZE    2411
  736. X
  737. Xstruct hashnode *table[HASHNODE_TABLE_SIZE];
  738. X
  739. X
  740. Xchar *hash_str (s)
  741. X    char *s;
  742. X{
  743. X    long h;                /* result of hash:  index into hash table */
  744. X    struct hashnode *p;    /* used to descend the spillover structs */
  745. X
  746. X    if (s == (char *) 0) {
  747. X        return ((char *) 0);
  748. X    }
  749. X
  750. X    {
  751. X        unsigned char *t = (unsigned char *) s;
  752. X
  753. X        h = *t++;
  754. X        while (*t)
  755. X            h = ((h << 1) ^ *t++) % (long) HASHNODE_TABLE_SIZE;
  756. X    }
  757. X
  758. X    p = table[h];
  759. X
  760. X    if (p == (struct hashnode *) 0) {
  761. X        table[h] = add_string (s);
  762. X        return table[h]->s;
  763. X    }
  764. X
  765. X    while (1) {
  766. X        if (strcmp (s, p->s) == 0) {
  767. X            return (p->s);
  768. X        }
  769. X
  770. X        if (p->next == (struct hashnode *) 0) {
  771. X            p->next = add_string (s);
  772. X            return p->next->s;
  773. X        } else {
  774. X            p = p->next;
  775. X        }
  776. X    }
  777. X    /* NOTREACHED */
  778. X}
  779. X
  780. X
  781. Xstruct hashnode *add_string (s)
  782. X    char *s;
  783. X{
  784. X    int *iptr;
  785. X    struct hashnode *p;
  786. X
  787. X    p = (struct hashnode *) my_malloc ((unsigned) sizeof (struct hashnode));
  788. X
  789. X    p->next = (struct hashnode *) 0;
  790. X    iptr = (int *) my_malloc ((unsigned) strlen (s) + sizeof (int) + 1);
  791. X    *iptr++ = -1;
  792. X    p->s = (char *) iptr;
  793. X    strcpy (p->s, s);
  794. X    return (p);
  795. X}
  796. X
  797. X
  798. Xvoid hash_init ()
  799. X{
  800. X    int i;
  801. X
  802. X    for (i = 0; i < HASHNODE_TABLE_SIZE; i++) {
  803. X        table[i] = (struct hashnode *) 0;
  804. X    }
  805. X}
  806. X
  807. X
  808. Xvoid hash_reclaim ()
  809. X{
  810. X    int i;
  811. X    int *iptr;
  812. X    struct hashnode *p, *next;
  813. X
  814. X    for (i = 0; i < HASHNODE_TABLE_SIZE; i++)
  815. X        if (table[i] != (struct hashnode *) 0) {
  816. X            p = table[i];
  817. X            while (p != (struct hashnode *) 0) {
  818. X                next = p->next;
  819. X                if (p->s != (char *) 0) {
  820. X                    iptr = (int *) p->s;
  821. X                    iptr--;
  822. X                    free ((char *) iptr);
  823. X                }
  824. X                free ((char *) p);
  825. X                p = next;
  826. X            }
  827. X            table[i] = (struct hashnode *) 0;
  828. X        }
  829. X}
  830. END_OF_FILE
  831.   if test 2510 -ne `wc -c <'hashstr.c'`; then
  832.     echo shar: \"'hashstr.c'\" unpacked with wrong size!
  833.   fi
  834.   # end of 'hashstr.c'
  835. fi
  836. if test -f 'inews.c' -a "${1}" != "-c" ; then 
  837.   echo shar: Will not clobber existing file \"'inews.c'\"
  838. else
  839.   echo shar: Extracting \"'inews.c'\" \(4721 characters\)
  840.   sed "s/^X//" >'inews.c' <<'END_OF_FILE'
  841. X/*
  842. X *  Project   : tin - a threaded Netnews reader
  843. X *  Module    : inews.c
  844. X *  Author    : I.Lea
  845. X *  Created   : 17-03-92
  846. X *  Updated   : 20-06-92
  847. X *  Notes     : NNTP builtin version of inews
  848. X *  Copyright : (c) Copyright 1991-92 by Iain Lea
  849. X *              You may  freely  copy or  redistribute  this software,
  850. X *              so  long as there is no profit made from its use, sale
  851. X *              trade or  reproduction.  You may not change this copy-
  852. X *              right notice, and it must be included in any copy made
  853. X */
  854. X
  855. X#include    "tin.h"
  856. X
  857. X#if defined(BSD) || defined(RS6000)
  858. X#    ifdef apollo
  859. X#        include    </bsd4.3/usr/include/netdb.h>
  860. X#    else
  861. X#        include    <netdb.h>
  862. X#    endif
  863. X#endif
  864. X
  865. X
  866. Xint submit_inews (name)
  867. X    char *name;
  868. X{
  869. X    int    ret_code = FALSE;
  870. X
  871. X#if !defined(INDEX_DAEMON) && !defined(XSPOOLDIR)
  872. X
  873. X#ifdef NNTP_INEWS
  874. X    char    from_name[256];
  875. X    char    host_name[128];
  876. X    char    line[NNTP_STRLEN];
  877. X    FILE    *fp;
  878. X    int    len = 0;
  879. X    int    respcode;
  880. X
  881. X    if ((fp = fopen (name, "r")) == NULL) {
  882. X        return (ret_code);
  883. X    }
  884. X
  885. X    /*
  886. X     * Send POST command to NNTP server
  887. X     */
  888. X    put_server ("post");
  889. X
  890. X    /*
  891. X     * Receive CONT_POST or ERROR response code from NNTP server
  892. X     */
  893. X    if ((respcode = get_respcode ()) != CONT_POST) {
  894. X        error_message ("%s", nntp_respcode (respcode));
  895. X        debug_nntp ("submit_inews", nntp_respcode (respcode));
  896. X        return (ret_code);
  897. X    }
  898. X
  899. X    get_host_name (host_name);    
  900. X    get_from_name (from_name);
  901. X    
  902. X    /*
  903. X     * Send Path: and From: article headers
  904. X     */
  905. X#ifdef NNTP_INEWS_GATEWAY
  906. X    sprintf (line, "Path: %s", userid);
  907. X#else
  908. X    sprintf (line, "Path: %s!%s", host_name, userid);
  909. X#endif    
  910. X    put_server (line);
  911. X    sprintf (line, "From: %s", from_name);
  912. X    put_server (line);
  913. X
  914. X    /*
  915. X     * Send article 1 line at a time ending with "."
  916. X     */
  917. X    while (fgets (line, sizeof (line), fp) != NULL) {
  918. X        len = strlen (line);
  919. X        line[len-1] = '\0';
  920. X        fprintf (ser_wr_fp, "%s\r\n", line);
  921. X    }
  922. X    
  923. X    put_server (".");
  924. X
  925. X    /*
  926. X     * Receive OK_POSTED or ERROR response code from NNTP server
  927. X     */
  928. X    if ((respcode = get_respcode ()) != OK_POSTED) {
  929. X        error_message ("%s", nntp_respcode (respcode));
  930. X        debug_nntp ("submit_inews", nntp_respcode (respcode));
  931. X        return (ret_code);
  932. X      }
  933. X      
  934. X    ret_code = TRUE;
  935. X
  936. X#endif /* NNTP_ABLE */
  937. X
  938. X#endif /* INDEX_DAEMON */
  939. X
  940. X    return (ret_code);
  941. X}
  942. X
  943. X/*
  944. X * Find real hostname / substitute hostname if news gateway name 
  945. X */
  946. Xvoid get_host_name (host_name)
  947. X    char *host_name;
  948. X{
  949. X#ifndef INDEX_DAEMON
  950. X
  951. X    char host[PATH_LEN];
  952. X
  953. X#ifdef NNTP_INEWS_GATEWAY    
  954. X    FILE *fp;
  955. X
  956. X    host_name[0] = '\0';
  957. X
  958. X    /*
  959. X     * If 1st letter is '/' read gateway name from specified file
  960. X     */
  961. X    if (*(NNTP_INEWS_GATEWAY) == '/') {
  962. X        if ((fp = fopen (NNTP_INEWS_GATEWAY, "r")) != (FILE *) 0) {
  963. X            if (fgets (host, sizeof (host), fp) != (char *) 0) {
  964. X                my_strncpy (host_name, host, strlen (host)-1);
  965. X            }    
  966. X            fclose (fp);
  967. X        }
  968. X        if (! host_name[0]) {
  969. X            strcpy(host_name, "PROBLEM_WITH_INEWS_GATEWAY_FILE");
  970. X        }
  971. X    } else {
  972. X        strcpy (host_name, NNTP_INEWS_GATEWAY);
  973. X    }    
  974. X#else
  975. X#    if defined(BSD) || defined(sinix) || defined(RS6000) || defined(HPUX)
  976. X    {
  977. X        struct hostent *host_entry;
  978. X
  979. X        gethostname (host, sizeof (host)); 
  980. X        host_entry = gethostbyname (host);
  981. X        my_strncpy (host, host_entry->h_name, sizeof (host)); 
  982. X    }    
  983. X#    else    
  984. X    {
  985. X        struct utsname uts_name;
  986. X
  987. X        uname (&uts_name);
  988. X        my_strncpy (host, uts_name.nodename, sizeof (host));
  989. X    }
  990. X#    endif
  991. X
  992. X    strcpy (host_name, host);
  993. X#endif
  994. X
  995. X#endif /* INDEX_DAEMON */
  996. X}
  997. X
  998. X/*
  999. X * Find users & hosts name
  1000. X */
  1001. X
  1002. Xvoid get_from_name (from_name)
  1003. X    char *from_name;
  1004. X{
  1005. X#ifndef INDEX_DAEMON
  1006. X
  1007. X    char domain[256];
  1008. X    char full_name[128];
  1009. X    char host_name[256];
  1010. X    char *ptr;
  1011. X#ifdef NNTP_INEWS_DOMAIN
  1012. X    FILE *fp;
  1013. X#endif
  1014. X    
  1015. X    domain[0] = '\0';
  1016. X    
  1017. X    if ((ptr = (char *) getenv ("NAME")) != (char *) 0) {
  1018. X        my_strncpy (full_name, ptr, sizeof (full_name));
  1019. X    } else {    
  1020. X        my_strncpy (full_name, myentry->pw_gecos, sizeof (full_name));
  1021. X        if ((ptr = (char *) strchr (full_name, ','))) {
  1022. X            *ptr = '\0';            
  1023. X        }
  1024. X    }
  1025. X
  1026. X    get_host_name (host_name);
  1027. X
  1028. X#ifdef NNTP_INEWS_DOMAIN
  1029. X    /*
  1030. X     * If 1st letter is '/' read domain name from specified file
  1031. X     */
  1032. X    if (*(NNTP_INEWS_DOMAIN) == '/') {
  1033. X        if ((fp = fopen (NNTP_INEWS_DOMAIN, "r")) != (FILE *) 0) {
  1034. X            if (fgets (domain, sizeof (domain), fp) != (char *) 0) {
  1035. X                if (ptr = (char *) strchr (domain, '\n')) {
  1036. X                    *ptr = '\0';
  1037. X                }
  1038. X            }
  1039. X            fclose (fp);
  1040. X        }
  1041. X        if (! domain[0]) {
  1042. X            strcpy (domain, "PROBLEM_WITH_INEWS_DOMAIN_FILE");
  1043. X        }
  1044. X    } else {
  1045. X        my_strncpy (domain, NNTP_INEWS_DOMAIN, sizeof (domain));
  1046. X    }
  1047. X    
  1048. X    if (domain[0] == '.') {
  1049. X        sprintf (from_name, "%s@%s%s (%s)",
  1050. X            userid, host_name, domain, full_name);
  1051. X    } else {    
  1052. X        sprintf (from_name, "%s@%s (%s)", userid, domain, full_name);
  1053. X    }        
  1054. X#else    
  1055. X    sprintf (from_name, "%s@%s (%s)", userid, host_name, full_name);
  1056. X#endif
  1057. X
  1058. X    if (debug == 2) {
  1059. X        error_message ("FROM: %s", from_name);
  1060. X    }    
  1061. X
  1062. X#endif /* INDEX_DAEMON */
  1063. X}
  1064. END_OF_FILE
  1065.   if test 4721 -ne `wc -c <'inews.c'`; then
  1066.     echo shar: \"'inews.c'\" unpacked with wrong size!
  1067.   fi
  1068.   # end of 'inews.c'
  1069. fi
  1070. if test -f 'memory.c' -a "${1}" != "-c" ; then 
  1071.   echo shar: Will not clobber existing file \"'memory.c'\"
  1072. else
  1073.   echo shar: Extracting \"'memory.c'\" \(7855 characters\)
  1074.   sed "s/^X//" >'memory.c' <<'END_OF_FILE'
  1075. X/*
  1076. X *  Project   : tin - a threaded Netnews reader
  1077. X *  Module    : memory.c
  1078. X *  Author    : I.Lea & R.Skrenta
  1079. X *  Created   : 01-04-91
  1080. X *  Updated   : 03-06-92
  1081. X *  Notes     :
  1082. X *  Copyright : (c) Copyright 1991-92 by Iain Lea & Rich Skrenta
  1083. X *              You may  freely  copy or  redistribute  this software,
  1084. X *              so  long as there is no profit made from its use, sale
  1085. X *              trade or  reproduction.  You may not change this copy-
  1086. X *              right notice, and it must be included in any copy made
  1087. X */
  1088. X
  1089. X#include    "tin.h"
  1090. X
  1091. Xint *my_group;                    /* .newsrc --> active[] */
  1092. Xint *unread;                    /* highest art read in group */
  1093. Xlong *base;
  1094. Xstruct group_t *active;            /* active file */
  1095. Xstruct article_t *arts;
  1096. X
  1097. X/*
  1098. X *  Dynamic table management
  1099. X *  These settings are memory conservative:  small initial allocations
  1100. X *  and a 50% expansion on table overflow.  A fast vm system with
  1101. X *  much memory might want to start with higher initial allocations
  1102. X *  and a 100% expansion on overflow, especially for the arts[] array.
  1103. X */
  1104. X
  1105. Xvoid init_alloc ()
  1106. X{
  1107. X    max_active = DEFAULT_ACTIVE_NUM;
  1108. X    max_art = DEFAULT_ARTICLE_NUM;
  1109. X
  1110. X    active = (struct group_t *) my_malloc ((unsigned) sizeof(*active) * max_active);
  1111. X    my_group = (int *) my_malloc ((unsigned) sizeof(int) * max_active);
  1112. X    unread = (int *) my_malloc ((unsigned) sizeof(int) * max_active);
  1113. X
  1114. X    arts = (struct article_t *) my_malloc ((unsigned) sizeof(*arts) * max_art);
  1115. X    base = (long *) my_malloc ((unsigned) sizeof(long) * max_art);
  1116. X
  1117. X    max_kill = DEFAULT_KILL_NUM;
  1118. X    
  1119. X    killf = (struct kill_t *) my_malloc ((unsigned) sizeof(*killf) * max_kill);
  1120. X
  1121. X    max_save = DEFAULT_SAVE_NUM;
  1122. X    
  1123. X    save = (struct save_t *) my_malloc ((unsigned) sizeof(*save) * max_save);
  1124. X
  1125. X    screen = (struct screen_t *) 0;
  1126. X}
  1127. X
  1128. X
  1129. Xvoid expand_art()
  1130. X{
  1131. X    max_art += max_art / 2;        /* increase by 50% */
  1132. X
  1133. X    arts = (struct article_t *) my_realloc ((char *) arts, (unsigned) sizeof(*arts) * max_art);
  1134. X    base = (long *) my_realloc ((char *) base, (unsigned) sizeof(long) * max_art);
  1135. X}
  1136. X
  1137. X
  1138. Xvoid expand_active()
  1139. X{
  1140. X    max_active += max_active / 2;        /* increase by 50% */
  1141. X
  1142. X    if (active == (struct group_t *) 0) {
  1143. X        active = (struct group_t *) my_malloc ((unsigned) sizeof(*active) * max_active);
  1144. X        my_group = (int *) my_malloc ((unsigned) sizeof(int) * max_active);
  1145. X        unread = (int *) my_malloc ((unsigned) sizeof(int) * max_active);
  1146. X    } else {
  1147. X        active = (struct group_t *) my_realloc((char *) active,
  1148. X                 (unsigned) sizeof(*active) * max_active);
  1149. X        my_group = (int *) my_realloc((char *) my_group, (unsigned) sizeof(int) * max_active);
  1150. X        unread = (int *) my_realloc((char *) unread, (unsigned) sizeof(int) * max_active);
  1151. X    }
  1152. X}
  1153. X
  1154. X
  1155. Xvoid expand_kill()
  1156. X{
  1157. X    max_kill += max_kill / 2;        /* increase by 50% */
  1158. X
  1159. X    killf = (struct kill_t *) my_realloc((char *) killf, (unsigned) sizeof(struct kill_t) * max_kill);
  1160. X}
  1161. X
  1162. X
  1163. Xvoid expand_save()
  1164. X{
  1165. X    max_save += max_save / 2;        /* increase by 50% */
  1166. X
  1167. X    save = (struct save_t *) my_realloc((char *) save, (unsigned) sizeof(struct save_t) * max_save);
  1168. X}
  1169. X
  1170. X
  1171. Xvoid init_screen_array (allocate)
  1172. X    int allocate;
  1173. X{
  1174. X    int i;
  1175. X
  1176. X    if (allocate) {
  1177. X        screen = (struct screen_t *) my_malloc(
  1178. X            (unsigned) sizeof(struct screen_t) * LINES+1);
  1179. X
  1180. X        for (i=0 ; i < LINES ; i++) {
  1181. X            screen[i].col = (char *) my_malloc ((unsigned) COLS+2);
  1182. X        }
  1183. X    } else {
  1184. X        if (screen != (struct screen_t *) 0) {
  1185. X            for (i=0 ; i < LINES ; i++) {
  1186. X                if (screen[i].col != (char *) 0) {
  1187. X                    free ((char *) screen[i].col);
  1188. X                    screen[i].col = (char *) 0;
  1189. X                }
  1190. X            }    
  1191. X
  1192. X            free ((char *) screen);
  1193. X            screen = (struct screen_t *) 0;
  1194. X        }
  1195. X    }
  1196. X}
  1197. X
  1198. X
  1199. Xvoid free_all_arrays ()
  1200. X{
  1201. X    hash_reclaim ();
  1202. X    
  1203. X    init_screen_array (FALSE);
  1204. X
  1205. X    free_art_array ();
  1206. X
  1207. X    if (arts != (struct article_t *) 0) {
  1208. X        free ((char *) arts);
  1209. X        arts = (struct article_t *) 0;
  1210. X    }
  1211. X
  1212. X    free_active_arrays ();
  1213. X
  1214. X    if (base != (long *) 0) {
  1215. X        free ((char *) base);
  1216. X        base = (long *) 0;
  1217. X    }
  1218. X
  1219. X    if (killf != (struct kill_t *) 0) {
  1220. X        free_kill_array ();
  1221. X        if (killf != (struct kill_t *) 0) {
  1222. X            free ((char *) killf);
  1223. X            killf = (struct kill_t *) 0;
  1224. X        }
  1225. X    }
  1226. X
  1227. X    if (save != (struct save_t *) 0) {
  1228. X        free_save_array ();
  1229. X        if (save != (struct save_t *) 0) {
  1230. X            free ((char *) save);
  1231. X            save = (struct save_t *) 0;
  1232. X        }
  1233. X    }
  1234. X}
  1235. X
  1236. X
  1237. Xvoid free_art_array ()
  1238. X{
  1239. X    register int i;
  1240. X
  1241. X    for (i=0 ; i < top ; i++) {
  1242. X        arts[i].artnum = 0L;
  1243. X        arts[i].thread = ART_EXPIRED;
  1244. X        arts[i].inthread = FALSE;
  1245. X        arts[i].unread = ART_UNREAD;
  1246. X        arts[i].killed = FALSE;
  1247. X        arts[i].tagged = FALSE;
  1248. X        arts[i].hot = FALSE;
  1249. X        arts[i].date[0] = '\0';
  1250. X        if (arts[i].part != (char *) 0) {
  1251. X            free ((char *) arts[i].part);
  1252. X            arts[i].part = (char *) 0;
  1253. X        }
  1254. X        if (arts[i].patch != (char *) 0) {
  1255. X            free ((char *) arts[i].patch);
  1256. X            arts[i].patch = (char *) 0;
  1257. X        }
  1258. X        if (arts[i].xref != NULL) {
  1259. X            free ((char *) arts[i].xref);
  1260. X            arts[i].xref = NULL;
  1261. X        }
  1262. X    }
  1263. X}
  1264. X
  1265. X
  1266. Xvoid free_active_arrays ()
  1267. X{
  1268. X    register int i;
  1269. X    
  1270. X    if (my_group != (int *) 0) {            /* my_group[] */
  1271. X        free ((char *) my_group);
  1272. X        my_group = (int *) 0;
  1273. X    }
  1274. X
  1275. X    if (unread != (int *) 0) {                /* unread[] */
  1276. X        free ((char *) unread);
  1277. X        unread = (int *) 0;
  1278. X    }
  1279. X
  1280. X    if (active != (struct group_t *) 0) {    /* active[] */
  1281. X        for (i=0 ; i < num_active ; i++) {
  1282. X            if (active[i].name != (char *) 0) {
  1283. X                free ((char *) active[i].name);
  1284. X                active[i].name = (char *) 0;
  1285. X            }
  1286. X            if (active[i].description != (char *) 0) {
  1287. X                free ((char *) active[i].description);
  1288. X                active[i].description = (char *) 0;
  1289. X            }
  1290. X            if (active[i].attribute.server != (char *) 0) {
  1291. X                free ((char *) active[i].attribute.server);
  1292. X                active[i].attribute.server = (char *) 0;
  1293. X            }
  1294. X            if (active[i].attribute.maildir != (char *) 0 &&
  1295. X                active[i].attribute.maildir != default_maildir) {
  1296. X                free ((char *) active[i].attribute.maildir);
  1297. X                active[i].attribute.maildir = (char *) 0;
  1298. X            }
  1299. X            if (active[i].attribute.savedir != (char *) 0 &&
  1300. X                active[i].attribute.savedir != default_savedir) {
  1301. X                free ((char *) active[i].attribute.savedir);
  1302. X                active[i].attribute.savedir = (char *) 0;
  1303. X            }
  1304. X            if (active[i].attribute.sigfile != (char *) 0 &&
  1305. X                active[i].attribute.sigfile != default_sigfile) {
  1306. X                free ((char *) active[i].attribute.sigfile);
  1307. X                active[i].attribute.sigfile = (char *) 0;
  1308. X            }
  1309. X        }
  1310. X        if (active != (struct group_t *) 0) {
  1311. X            free ((char *) active);
  1312. X            active = (struct group_t *) 0;
  1313. X        }
  1314. X    }
  1315. X}
  1316. X
  1317. X
  1318. Xvoid free_kill_array ()
  1319. X{
  1320. X    int i;
  1321. X    
  1322. X    for (i=0 ; i < kill_num ; i++) {
  1323. X        if (killf[i].kill_subj != (char *) 0) {
  1324. X            free ((char *) killf[i].kill_subj);
  1325. X            killf[i].kill_subj = (char *) 0;
  1326. X        }
  1327. X        if (killf[i].kill_from != (char *) 0) {
  1328. X            free ((char *) killf[i].kill_from);
  1329. X            killf[i].kill_from = (char *) 0;
  1330. X        }
  1331. X    }
  1332. X}
  1333. X
  1334. X
  1335. X/*
  1336. X *  reset save list array to 0 and free's all its allocated memory
  1337. X */
  1338. Xvoid free_save_array ()
  1339. X{
  1340. X    int i;
  1341. X    
  1342. X    for (i=0 ; i < save_num ; i++) {
  1343. X        if (save[i].subject != (char *) 0) {
  1344. X            free ((char *) save[i].subject);
  1345. X            save[i].subject = (char *) 0;
  1346. X        }
  1347. X        if (save[i].archive != (char *) 0) {
  1348. X            free ((char *) save[i].archive);
  1349. X            save[i].archive = (char *) 0;
  1350. X        }
  1351. X        if (save[i].dir != (char *) 0) {
  1352. X            free ((char *) save[i].dir);
  1353. X            save[i].dir = (char *) 0;
  1354. X        }
  1355. X        if (save[i].file != (char *) 0) {
  1356. X            free ((char *) save[i].file);
  1357. X            save[i].file = (char *) 0;
  1358. X        }
  1359. X        if (save[i].part != (char *) 0) {
  1360. X            free ((char *) save[i].part);
  1361. X            save[i].part = (char *) 0;
  1362. X        }
  1363. X        if (save[i].patch != (char *) 0) {
  1364. X            free ((char *) save[i].patch);
  1365. X            save[i].patch = (char *) 0;
  1366. X        }
  1367. X        save[i].index   = -1;
  1368. X        save[i].saved   = FALSE;
  1369. X        save[i].is_mailbox = FALSE;
  1370. X    }
  1371. X    
  1372. X    save_num = 0;
  1373. X}
  1374. X
  1375. X
  1376. Xchar *my_malloc (size)
  1377. X    unsigned size;
  1378. X{
  1379. X    char *p;
  1380. X
  1381. X    if ((p = (char *) calloc (1, (int) size)) == NULL) {
  1382. X        error_message (txt_out_of_memory, progname);
  1383. X        tin_done (1);
  1384. X    }
  1385. X    return p;
  1386. X}
  1387. X
  1388. X
  1389. Xchar *my_realloc (p, size)
  1390. X    char *p;
  1391. X    unsigned size;
  1392. X{
  1393. X    if (! p) {
  1394. X        p = (char *) calloc (1, (int) size);
  1395. X    } else {
  1396. X        p = (char *) realloc (p, (int) size);
  1397. X    }
  1398. X
  1399. X    if (! p) {
  1400. X        error_message (txt_out_of_memory, progname);
  1401. X        tin_done (1);
  1402. X    }
  1403. X    return p;
  1404. X}
  1405. END_OF_FILE
  1406.   if test 7855 -ne `wc -c <'memory.c'`; then
  1407.     echo shar: \"'memory.c'\" unpacked with wrong size!
  1408.   fi
  1409.   # end of 'memory.c'
  1410. fi
  1411. if test -f 'nntplib.h' -a "${1}" != "-c" ; then 
  1412.   echo shar: Will not clobber existing file \"'nntplib.h'\"
  1413. else
  1414.   echo shar: Extracting \"'nntplib.h'\" \(4658 characters\)
  1415.   sed "s/^X//" >'nntplib.h' <<'END_OF_FILE'
  1416. X/*
  1417. X *  Project   : tin - a threaded Netnews reader
  1418. X *  Module    : nntplib.h
  1419. X *  Author    : I.Lea
  1420. X *  Created   : 01-04-91
  1421. X *  Updated   : 03-06-92
  1422. X *  Notes     : nntp.h 1.5.11/1.6 with extensions for tin & CD-ROM
  1423. X *  Copyright : You may  freely  copy or  redistribute  this software,
  1424. X *              so  long as there is no profit made from its use, sale
  1425. X *              trade or  reproduction.  You may not change this copy-
  1426. X *              right notice, and it must be included in any copy made
  1427. X */
  1428. X
  1429. X#ifndef    NNTP_SERVER_FILE
  1430. X#    define    NNTP_SERVER_FILE    "/etc/nntpserver"
  1431. X#endif
  1432. X
  1433. X/*
  1434. X *  External routine declarations
  1435. X */
  1436. X
  1437. Xextern char *getserverbyfile();
  1438. Xextern int server_init();
  1439. Xextern int get_tcp_socket();
  1440. Xextern int handle_server_response();
  1441. Xextern void put_server();
  1442. Xextern int get_server();
  1443. Xextern void close_server();
  1444. X
  1445. X/*
  1446. X *  External file descriptors for the server connection
  1447. X */
  1448. X
  1449. Xextern FILE *ser_wr_fp;
  1450. X
  1451. X/*
  1452. X * Response codes for NNTP server
  1453. X *
  1454. X * @(#)Header: nntp.h,v 1.81 92/03/12 02:08:31 sob Exp $
  1455. X *
  1456. X * First digit:
  1457. X *
  1458. X *    1xx    Informative message
  1459. X *    2xx    Command ok
  1460. X *    3xx    Command ok so far, continue
  1461. X *    4xx    Command was correct, but couldn't be performed
  1462. X *        for some specified reason.
  1463. X *    5xx    Command unimplemented, incorrect, or a
  1464. X *        program error has occured.
  1465. X *
  1466. X * Second digit:
  1467. X *
  1468. X *    x0x    Connection, setup, miscellaneous
  1469. X *    x1x    Newsgroup selection
  1470. X *    x2x    Article selection
  1471. X *    x3x    Distribution
  1472. X *    x4x    Posting
  1473. X */
  1474. X
  1475. X#define    CHAR_INF    '1'
  1476. X#define    CHAR_OK        '2'
  1477. X#define    CHAR_CONT    '3'
  1478. X#define    CHAR_ERR    '4'
  1479. X#define    CHAR_FATAL    '5'
  1480. X
  1481. X#define    INF_HELP        100    /* Help text on way */
  1482. X#define    INF_AUTH        180    /* Authorization capabilities */
  1483. X#define    INF_DEBUG        199    /* Debug output */
  1484. X
  1485. X#define    OK_CANPOST        200    /* Hello; you can post */
  1486. X#define    OK_NOPOST        201    /* Hello; you can't post */
  1487. X#define    OK_SLAVE        202    /* Slave status noted */
  1488. X#define    OK_GOODBYE        205    /* Closing connection */
  1489. X#define    OK_GROUP        211    /* Group selected */
  1490. X#define    OK_GROUPS        215    /* Newsgroups follow */
  1491. X
  1492. X#define OK_XINDEX        218    /* Tin index follows */
  1493. X
  1494. X#define    OK_ARTICLE        220    /* Article (head & body) follows */
  1495. X#define    OK_HEAD            221    /* Head follows */
  1496. X#define    OK_BODY            222    /* Body follows */
  1497. X#define    OK_NOTEXT        223    /* No text sent -- stat, next, last */
  1498. X#define    OK_NEWNEWS        230    /* New articles by message-id follow */
  1499. X#define    OK_NEWGROUPS        231    /* New newsgroups follow */
  1500. X#define    OK_XFERED        235    /* Article transferred successfully */
  1501. X#define    OK_POSTED        240    /* Article posted successfully */
  1502. X#define    OK_AUTHSYS        280    /* Authorization system ok */
  1503. X#define    OK_AUTH            281    /* Authorization (user/pass) ok */
  1504. X#define OK_BIN            282    /* binary data follows */
  1505. X#define OK_SPLIST        283    /* spooldir list follows */
  1506. X#define OK_SPSWITCH        284    /* Switching to a different spooldir */
  1507. X#define OK_SPNOCHANGE        285    /* Still using same spooldir */
  1508. X#define OK_SPLDIRCUR        286    /* Current spooldir */
  1509. X#define OK_SPLDIRAVL        287    /* Available spooldir */
  1510. X#define OK_SPLDIRERR        288    /* Unavailable spooldir or invalid entry */
  1511. X
  1512. X#define CONT_XFER        335    /* Continue to send article */
  1513. X#define    CONT_POST        340    /* Continue to post article */
  1514. X#define    NEED_AUTHINFO        380    /* authorization is required */
  1515. X#define    NEED_AUTHDATA        381    /* <type> authorization data required */
  1516. X
  1517. X#define    ERR_GOODBYE        400    /* Have to hang up for some reason */
  1518. X#define    ERR_NOGROUP        411    /* No such newsgroup */
  1519. X#define    ERR_NCING        412    /* Not currently in newsgroup */
  1520. X
  1521. X#define ERR_XINDEX        418    /* No tin index for this group */
  1522. X
  1523. X#define    ERR_NOCRNT        420    /* No current article selected */
  1524. X#define    ERR_NONEXT        421    /* No next article in this group */
  1525. X#define    ERR_NOPREV        422    /* No previous article in this group */
  1526. X#define    ERR_NOARTIG        423    /* No such article in this group */
  1527. X#define ERR_NOART        430    /* No such article at all */
  1528. X#define ERR_GOTIT        435    /* Already got that article, don't send */
  1529. X#define ERR_XFERFAIL        436    /* Transfer failed */
  1530. X#define    ERR_XFERRJCT        437    /* Article rejected, don't resend */
  1531. X#define    ERR_NOPOST        440    /* Posting not allowed */
  1532. X#define    ERR_POSTFAIL        441    /* Posting failed */
  1533. X#define    ERR_NOAUTH        480    /* authorization required for command */
  1534. X#define    ERR_AUTHSYS        481    /* Authorization system invalid */
  1535. X#define    ERR_AUTHREJ        482    /* Authorization data rejected */
  1536. X#define ERR_INVALIAS        483    /* Invalid alias on spooldir cmd */
  1537. X#define ERR_INVNOSPDIR        484    /* No spooldir file found */
  1538. X
  1539. X#define    ERR_COMMAND        500    /* Command not recognized */
  1540. X#define    ERR_CMDSYN        501    /* Command syntax error */
  1541. X#define    ERR_ACCESS        502    /* Access to server denied */
  1542. X#define ERR_FAULT        503    /* Program fault, command not performed */
  1543. X#define    ERR_AUTHBAD        580    /* Authorization Failed */
  1544. X    
  1545. X/*
  1546. X * RFC 977 defines this; don't change it.
  1547. X */
  1548. X
  1549. X#define    NNTP_STRLEN        512
  1550. X
  1551. END_OF_FILE
  1552.   if test 4658 -ne `wc -c <'nntplib.h'`; then
  1553.     echo shar: \"'nntplib.h'\" unpacked with wrong size!
  1554.   fi
  1555.   # end of 'nntplib.h'
  1556. fi
  1557. if test -f 'search.c' -a "${1}" != "-c" ; then 
  1558.   echo shar: Will not clobber existing file \"'search.c'\"
  1559. else
  1560.   echo shar: Extracting \"'search.c'\" \(7173 characters\)
  1561.   sed "s/^X//" >'search.c' <<'END_OF_FILE'
  1562. X/*
  1563. X *  Project   : tin - a threaded Netnews reader
  1564. X *  Module    : search.c
  1565. X *  Author    : I.Lea & R.Skrenta
  1566. X *  Created   : 01-04-91
  1567. X *  Updated   : 13-03-92
  1568. X *  Notes     :
  1569. X *  Copyright : (c) Copyright 1991-92 by Iain Lea & Rich Skrenta
  1570. X *              You may  freely  copy or  redistribute  this software,
  1571. X *              so  long as there is no profit made from its use, sale
  1572. X *              trade or  reproduction.  You may not change this copy-
  1573. X *              right notice, and it must be included in any copy made
  1574. X */
  1575. X
  1576. X#include    "tin.h"
  1577. X
  1578. Xextern FILE *note_fp;
  1579. Xextern int cur_groupnum;
  1580. Xextern int first_group_on_screen;
  1581. Xextern int last_group_on_screen;
  1582. Xextern int first_subj_on_screen;
  1583. Xextern int last_subj_on_screen;
  1584. Xextern int index_point;
  1585. Xextern int note_line;
  1586. Xextern int note_page;
  1587. Xextern int note_end;
  1588. Xextern long note_mark[MAX_PAGES];
  1589. X
  1590. X/*
  1591. X * last search patterns
  1592. X */
  1593. X
  1594. Xchar default_author_search[LEN];
  1595. Xchar default_group_search[LEN];
  1596. Xchar default_subject_search[LEN];
  1597. Xchar default_art_search[LEN];
  1598. X
  1599. X
  1600. X/*
  1601. X *  group.c & page.c
  1602. X */
  1603. Xint search_author (only_unread, current_art, forward)
  1604. X    int only_unread;
  1605. X    int current_art;
  1606. X    int forward;
  1607. X{
  1608. X    char buf[LEN];
  1609. X    char buf2[LEN];
  1610. X    int i, patlen;
  1611. X
  1612. X    clear_message ();
  1613. X
  1614. X    if (forward) {
  1615. X        sprintf (buf2, txt_author_search_forwards, default_author_search);
  1616. X    } else {
  1617. X        sprintf (buf2, txt_author_search_backwards, default_author_search);
  1618. X    }
  1619. X    
  1620. X    if (! prompt_string (buf2, buf)) {
  1621. X        return -1;
  1622. X    }
  1623. X    
  1624. X    if (strlen (buf)) {
  1625. X        strcpy (default_author_search, buf);
  1626. X    } else {
  1627. X        if (default_author_search[0]) {
  1628. X            strcpy (buf, default_author_search);
  1629. X        } else {
  1630. X            info_message (txt_no_search_string);    
  1631. X            return -1;
  1632. X        }
  1633. X    }
  1634. X
  1635. X    wait_message (txt_searching);
  1636. X
  1637. X    make_lower (default_author_search, buf);
  1638. X
  1639. X    patlen = strlen (default_author_search);
  1640. X
  1641. X    i = current_art;
  1642. X
  1643. X    do {
  1644. X        if (forward) {
  1645. X            i = next_response (i);
  1646. X            if (i < 0)
  1647. X                i = base[0];
  1648. X        } else {
  1649. X            i = prev_response (i);
  1650. X            if (i < 0)
  1651. X                i = base[top_base - 1] + 
  1652. X                    num_of_responses (top_base - 1);
  1653. X        }
  1654. X
  1655. X        if (only_unread && arts[i].unread != ART_UNREAD) {
  1656. X            continue;
  1657. X        }
  1658. X            
  1659. X        if (arts[i].name == (char *) 0) {
  1660. X            make_lower (arts[i].from, buf2);
  1661. X        } else {
  1662. X            sprintf (msg, "%s (%s)", arts[i].from, arts[i].name);
  1663. X            make_lower (msg, buf2);
  1664. X        }
  1665. X
  1666. X        if (str_str (buf2, buf, patlen) != 0) {
  1667. X            clear_message ();
  1668. X            return i;
  1669. X        }
  1670. X    } while (i != current_art);
  1671. X
  1672. X    info_message (txt_no_match);
  1673. X    return -1;
  1674. X}
  1675. X
  1676. X/*
  1677. X * select.c
  1678. X */
  1679. Xvoid search_group (forward)
  1680. X    int forward;
  1681. X{
  1682. X    char buf[LEN];
  1683. X    char buf2[LEN];
  1684. X    int i, patlen;
  1685. X
  1686. X    clear_message ();
  1687. X
  1688. X    if (forward) {
  1689. X        sprintf (buf2, txt_search_forwards, default_group_search);
  1690. X    } else {
  1691. X        sprintf (buf2, txt_search_backwards, default_group_search);
  1692. X    }
  1693. X
  1694. X    if (! prompt_string (buf2, buf)) {
  1695. X        return;
  1696. X    }
  1697. X
  1698. X    if (strlen (buf)) {
  1699. X        strcpy (default_group_search, buf);
  1700. X    } else {
  1701. X        if (default_group_search[0]) {
  1702. X            strcpy (buf, default_group_search);
  1703. X        } else {
  1704. X            info_message (txt_no_search_string);    
  1705. X            return;
  1706. X        }
  1707. X    }
  1708. X
  1709. X    wait_message (txt_searching);
  1710. X
  1711. X    make_lower (default_group_search, buf);
  1712. X
  1713. X    patlen = strlen (default_group_search);
  1714. X
  1715. X    i = cur_groupnum;
  1716. X
  1717. X    do {
  1718. X        if (forward)
  1719. X            i++;
  1720. X        else
  1721. X            i--;
  1722. X
  1723. X        if (i >= group_top)
  1724. X            i = 0;
  1725. X        if (i < 0)
  1726. X            i = group_top - 1;
  1727. X
  1728. X        make_lower (active[my_group[i]].name, buf2);
  1729. X
  1730. X        if (str_str (buf2, buf, patlen) != 0) {
  1731. X            if (i >= first_group_on_screen
  1732. X            &&  i < last_group_on_screen) {
  1733. X                clear_message ();
  1734. X                erase_group_arrow ();
  1735. X                cur_groupnum = i;
  1736. X                draw_group_arrow ();
  1737. X            } else {
  1738. X                cur_groupnum = i;
  1739. X                group_selection_page ();
  1740. X            }
  1741. X            return;
  1742. X        }
  1743. X    } while (i != cur_groupnum);
  1744. X
  1745. X    info_message (txt_no_match);
  1746. X}
  1747. X
  1748. X/*
  1749. X * group.c
  1750. X */
  1751. X
  1752. Xvoid search_subject (forward, group)
  1753. X    int forward;
  1754. X    char *group;
  1755. X{
  1756. X    char buf[LEN];
  1757. X    char buf2[LEN];
  1758. X    int i, j, patlen;
  1759. X
  1760. X    if (index_point < 0) {
  1761. X        info_message (txt_no_arts);
  1762. X        return;
  1763. X    }
  1764. X    
  1765. X    clear_message ();
  1766. X
  1767. X    if (forward) {
  1768. X        sprintf (buf2, txt_search_forwards, default_subject_search);
  1769. X    } else {
  1770. X        sprintf (buf2, txt_search_backwards, default_subject_search);
  1771. X    }
  1772. X
  1773. X    if (! prompt_string (buf2, buf)) {
  1774. X        return;
  1775. X    }
  1776. X
  1777. X    if (strlen (buf)) {
  1778. X        strcpy (default_subject_search, buf);
  1779. X    } else {
  1780. X        if (default_subject_search[0]) {
  1781. X            strcpy (buf, default_subject_search);
  1782. X        } else {
  1783. X            info_message (txt_no_search_string);    
  1784. X            return;
  1785. X        }
  1786. X    }
  1787. X
  1788. X    wait_message (txt_searching);
  1789. X
  1790. X    make_lower (default_subject_search, buf);
  1791. X
  1792. X    patlen = strlen (default_subject_search);
  1793. X
  1794. X    i = index_point;
  1795. X
  1796. X    do {
  1797. X        if (forward)
  1798. X            i++;
  1799. X        else
  1800. X            i--;
  1801. X
  1802. X        if (i >= top_base)
  1803. X            i = 0;
  1804. X        if (i < 0)
  1805. X            i = top_base - 1;
  1806. X
  1807. X        j = (int) base[i];
  1808. X
  1809. X        make_lower (arts[j].subject, buf2);
  1810. X
  1811. X        if (str_str (buf2, buf, patlen) != 0) {
  1812. X            if (i >= first_subj_on_screen
  1813. X                &&  i < last_subj_on_screen) {
  1814. X                clear_message ();
  1815. X                erase_subject_arrow ();
  1816. X                index_point = i;
  1817. X                draw_subject_arrow ();
  1818. X            } else {
  1819. X                index_point = i;
  1820. X                show_group_page (group);
  1821. X            }
  1822. X            return;
  1823. X        }
  1824. X    } while (i != index_point);
  1825. X
  1826. X    info_message (txt_no_match);
  1827. X}
  1828. X
  1829. X/*
  1830. X *  page.c (search article body)
  1831. X */
  1832. X
  1833. Xint search_article (forward)
  1834. X    int forward;
  1835. X{
  1836. X    char buf[LEN];
  1837. X    char buf2[LEN];
  1838. X    char string[LEN];
  1839. X    char pattern[LEN];
  1840. X    char *p, *q;
  1841. X    int ctrl_L;
  1842. X    int i, j, patlen;
  1843. X    int orig_note_end;
  1844. X    int orig_note_page;
  1845. X
  1846. X    clear_message ();
  1847. X
  1848. X    if (forward) {
  1849. X        sprintf (buf2, txt_search_forwards, default_art_search);
  1850. X    } else {
  1851. X        sprintf (buf2, txt_search_backwards, default_art_search);
  1852. X    }
  1853. X
  1854. X    if (! prompt_string (buf2, buf)) {
  1855. X        return FALSE;
  1856. X    }
  1857. X
  1858. X    if (strlen (buf)) {
  1859. X        strcpy (default_art_search, buf);
  1860. X    } else {
  1861. X        if (default_art_search[0]) {
  1862. X            strcpy (buf, default_art_search);
  1863. X        } else {
  1864. X            info_message (txt_no_search_string);    
  1865. X            return FALSE;
  1866. X        }
  1867. X    }
  1868. X
  1869. X    wait_message (txt_searching);
  1870. X    
  1871. X    make_lower (default_art_search, pattern);
  1872. X
  1873. X    patlen = strlen (default_art_search);
  1874. X
  1875. X    /*
  1876. X     *  save current position in article
  1877. X     */
  1878. X    orig_note_end = note_end;
  1879. X    orig_note_page = note_page;
  1880. X    
  1881. X    while (! note_end) {
  1882. X        note_line = 1;
  1883. X        ctrl_L = FALSE;
  1884. X
  1885. X        if (note_page == 0) {
  1886. X            note_line += 4;
  1887. X        } else {
  1888. X            note_line += 2;
  1889. X        }
  1890. X        while (note_line < LINES) {
  1891. X            if (fgets (buf, sizeof buf, note_fp) == NULL) {
  1892. X                note_end = TRUE;
  1893. X                break;
  1894. X            }
  1895. X            buf[LEN-1] = '\0';
  1896. X            for (p = buf, q = buf2;    *p && *p != '\n' && q<&buf2[LEN]; p++) {
  1897. X                if (*p == '\b' && q > buf2) {
  1898. X                    q--;
  1899. X                } else if (*p == '\f') {        /* ^L */
  1900. X                    *q++ = '^';
  1901. X                    *q++ = 'L';
  1902. X                    ctrl_L = TRUE;
  1903. X                } else if (*p == '\t') {
  1904. X                    i = q - buf2;
  1905. X                    j = (i|7) + 1;
  1906. X
  1907. X                    while (i++ < j) {
  1908. X                        *q++ = ' ';
  1909. X                    }
  1910. X                } else if (((*p) & 0xFF) < ' ') {
  1911. X                    *q++ = '^';
  1912. X                    *q++ = ((*p) & 0xFF) + '@';
  1913. X                } else {
  1914. X                    *q++ = *p;
  1915. X                }
  1916. X            }
  1917. X            *q = '\0';
  1918. X
  1919. X            make_lower (buf2, string);
  1920. X
  1921. X            if (str_str (string, pattern, patlen) != 0) {
  1922. X                fseek (note_fp, note_mark[note_page], 0);
  1923. X                return TRUE;
  1924. X            }
  1925. X
  1926. X            note_line += ((int) strlen(buf2) / COLS) + 1;
  1927. X
  1928. X            if (ctrl_L) {
  1929. X                break;
  1930. X            }
  1931. X        }
  1932. X        if (! note_end) {
  1933. X            note_mark[++note_page] = ftell (note_fp);
  1934. X        }
  1935. X    }
  1936. X
  1937. X    note_end = orig_note_end;
  1938. X    note_page = orig_note_page;
  1939. X    fseek (note_fp, note_mark[note_page], 0);
  1940. X    info_message (txt_no_match);
  1941. X    return FALSE;
  1942. X}
  1943. X
  1944. X
  1945. Xvoid make_lower (s, t)
  1946. X    char *s;
  1947. X    char *t;
  1948. X{
  1949. X
  1950. X    while (*s) {
  1951. X        if (isupper(*s))
  1952. X            *t = tolower(*s);
  1953. X        else
  1954. X            *t = *s;
  1955. X        s++;
  1956. X        t++;
  1957. X    }
  1958. X    *t = 0;
  1959. X}
  1960. END_OF_FILE
  1961.   if test 7173 -ne `wc -c <'search.c'`; then
  1962.     echo shar: \"'search.c'\" unpacked with wrong size!
  1963.   fi
  1964.   # end of 'search.c'
  1965. fi
  1966. if test -f 'wildmat.c' -a "${1}" != "-c" ; then 
  1967.   echo shar: Will not clobber existing file \"'wildmat.c'\"
  1968. else
  1969.   echo shar: Extracting \"'wildmat.c'\" \(4798 characters\)
  1970.   sed "s/^X//" >'wildmat.c' <<'END_OF_FILE'
  1971. X/*  $Revision: 1.5 $
  1972. X**
  1973. X**  Do shell-style pattern matching for ?, \, [], and * characters.
  1974. X**  Might not be robust in face of malformed patterns; e.g., "foo[a-"
  1975. X**  could cause a segmentation violation.  It is 8bit clean.
  1976. X**
  1977. X**  Written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986.
  1978. X**  Rich $alz is now <rsalz@bbn.com>.
  1979. X**  April, 1991:  Replaced mutually-recursive calls with in-line code
  1980. X**  for the star character.
  1981. X**
  1982. X**  Special thanks to Lars Mathiesen <thorinn@diku.dk> for the ABORT code.
  1983. X**  This can greatly speed up failing wildcard patterns.  For example:
  1984. X**    pattern: -*-*-*-*-*-*-12-*-*-*-m-*-*-*
  1985. X**    text 1:     -adobe-courier-bold-o-normal--12-120-75-75-m-70-iso8859-1
  1986. X**    text 2:     -adobe-courier-bold-o-normal--12-120-75-75-X-70-iso8859-1
  1987. X**  Text 1 matches with 51 calls, while text 2 fails with 54 calls.  Without
  1988. X**  the ABORT, then it takes 22310 calls to fail.  Ugh.  The following
  1989. X**  explanation is from Lars:
  1990. X**  The precondition that must be fulfilled is that DoMatch will consume
  1991. X**  at least one character in text.  This is true if *p is neither '*' nor
  1992. X**  '\0'.)  The last return has ABORT instead of FALSE to avoid quadratic
  1993. X**  behaviour in cases like pattern "*a*b*c*d" with text "abcxxxxx".  With
  1994. X**  FALSE, each star-loop has to run to the end of the text; with ABORT
  1995. X**  only the last one does.
  1996. X**
  1997. X**  Once the control of one instance of DoMatch enters the star-loop, that
  1998. X**  instance will return either TRUE or ABORT, and any calling instance
  1999. X**  will therefore return immediately after (without calling recursively
  2000. X**  again).  In effect, only one star-loop is ever active.  It would be
  2001. X**  possible to modify the code to maintain this context explicitly,
  2002. X**  eliminating all recursive calls at the cost of some complication and
  2003. X**  loss of clarity (and the ABORT stuff seems to be unclear enough by
  2004. X**  itself).  I think it would be unwise to try to get this into a
  2005. X**  released version unless you have a good test data base to try it out
  2006. X**  on.
  2007. X*/
  2008. X
  2009. X#define TRUE            1
  2010. X#define FALSE            0
  2011. X#define ABORT            -1
  2012. X
  2013. X
  2014. X    /* What character marks an inverted character class? */
  2015. X#define NEGATE_CLASS        '^'
  2016. X    /* Is "*" a common pattern? */
  2017. X#define OPTIMIZE_JUST_STAR
  2018. X    /* Do tar(1) matching rules, which ignore a trailing slash? */
  2019. X#undef MATCH_TAR_PATTERN
  2020. X
  2021. X
  2022. X/*
  2023. X**  Match text and p, return TRUE, FALSE, or ABORT.
  2024. X*/
  2025. Xstatic int
  2026. XDoMatch(text, p)
  2027. X    register char    *text;
  2028. X    register char    *p;
  2029. X{
  2030. X#ifndef INDEX_DAEMON
  2031. X
  2032. X    register int    last;
  2033. X    register int    matched;
  2034. X    register int    reverse;
  2035. X
  2036. X    for ( ; *p; text++, p++) {
  2037. X    if (*text == '\0' && *p != '*')
  2038. X        return ABORT;
  2039. X    switch (*p) {
  2040. X    case '\\':
  2041. X        /* Literal match with following character. */
  2042. X        p++;
  2043. X        /* FALLTHROUGH */
  2044. X    default:
  2045. X        if (*text != *p)
  2046. X        return FALSE;
  2047. X        continue;
  2048. X    case '?':
  2049. X        /* Match anything. */
  2050. X        continue;
  2051. X    case '*':
  2052. X        while (*++p == '*')
  2053. X        /* Consecutive stars act just like one. */
  2054. X        continue;
  2055. X        if (*p == '\0')
  2056. X        /* Trailing star matches everything. */
  2057. X        return TRUE;
  2058. X        while (*text)
  2059. X        if ((matched = DoMatch(text++, p)) != FALSE)
  2060. X            return matched;
  2061. X        return ABORT;
  2062. X    case '[':
  2063. X        reverse = p[1] == NEGATE_CLASS ? TRUE : FALSE;
  2064. X        if (reverse)
  2065. X        /* Inverted character class. */
  2066. X        p++;
  2067. X        matched = FALSE;
  2068. X        if (p[1] == ']' || p[1] == '-')
  2069. X        if (*++p == *text)
  2070. X            matched = TRUE;
  2071. X        for (last = *p; *++p && *p != ']'; last = *p)
  2072. X        /* This next line requires a good C compiler. */
  2073. X        if (*p == '-' && p[1] != ']'
  2074. X            ? *text <= *++p && *text >= last : *text == *p)
  2075. X            matched = TRUE;
  2076. X        if (matched == reverse)
  2077. X        return FALSE;
  2078. X        continue;
  2079. X    }
  2080. X    }
  2081. X
  2082. X#ifdef    MATCH_TAR_PATTERN
  2083. X    if (*text == '/')
  2084. X    return TRUE;
  2085. X#endif    /* MATCH_TAR_ATTERN */
  2086. X    return *text == '\0';
  2087. X
  2088. X#endif    /* INDEX_DAEMON */
  2089. X}
  2090. X
  2091. X
  2092. X/*
  2093. X**  User-level routine.  Returns TRUE or FALSE.
  2094. X*/
  2095. Xint
  2096. Xwildmat(text, p)
  2097. X    char    *text;
  2098. X    char    *p;
  2099. X{
  2100. X#ifdef    OPTIMIZE_JUST_STAR
  2101. X    if (p[0] == '*' && p[1] == '\0')
  2102. X    return TRUE;
  2103. X#endif    /* OPTIMIZE_JUST_STAR */
  2104. X    return DoMatch(text, p) == TRUE;
  2105. X}
  2106. X
  2107. X
  2108. X
  2109. X#ifdef    TEST
  2110. X#include <stdio.h>
  2111. X
  2112. X/* Yes, we use gets not fgets.  Sue me. */
  2113. Xextern char    *gets();
  2114. X
  2115. X
  2116. Xmain()
  2117. X{
  2118. X    char     p[80];
  2119. X    char     text[80];
  2120. X
  2121. X    printf("Wildmat tester.  Enter pattern, then strings to test.\n");
  2122. X    printf("A blank line gets prompts for a new pattern; a blank pattern\n");
  2123. X    printf("exits the program.\n");
  2124. X
  2125. X    for ( ; ; ) {
  2126. X    printf("\nEnter pattern:  ");
  2127. X    (void)fflush(stdout);
  2128. X    if (gets(p) == NULL || p[0] == '\0')
  2129. X        break;
  2130. X    for ( ; ; ) {
  2131. X        printf("Enter text:  ");
  2132. X        (void)fflush(stdout);
  2133. X        if (gets(text) == NULL)
  2134. X        exit(0);
  2135. X        if (text[0] == '\0')
  2136. X        /* Blank line; go back and get a new pattern. */
  2137. X        break;
  2138. X        printf("      %s\n", wildmat(text, p) ? "YES" : "NO");
  2139. X    }
  2140. X    }
  2141. X
  2142. X    exit(0);
  2143. X    /* NOTREACHED */
  2144. X}
  2145. X#endif    /* TEST */
  2146. END_OF_FILE
  2147.   if test 4798 -ne `wc -c <'wildmat.c'`; then
  2148.     echo shar: \"'wildmat.c'\" unpacked with wrong size!
  2149.   fi
  2150.   # end of 'wildmat.c'
  2151. fi
  2152. echo shar: End of archive 14 \(of 15\).
  2153. cp /dev/null ark14isdone
  2154. MISSING=""
  2155. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ; do
  2156.     if test ! -f ark${I}isdone ; then
  2157.     MISSING="${MISSING} ${I}"
  2158.     fi
  2159. done
  2160. if test "${MISSING}" = "" ; then
  2161.     echo You have unpacked all 15 archives.
  2162.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2163. else
  2164.     echo You still must unpack the following archives:
  2165.     echo "        " ${MISSING}
  2166. fi
  2167. exit 0
  2168. exit 0 # Just in case...
  2169.