home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2951 < prev    next >
Internet Message Format  |  1991-03-03  |  44KB

  1. From: lee@sq.sq.com (Liam R. E. Quin)
  2. Newsgroups: alt.sources
  3. Subject: lq-text Full Text Retrieval Database Part 03/13
  4. Message-ID: <1991Mar4.020149.16222@sq.sq.com>
  5. Date: 4 Mar 91 02:01:49 GMT
  6.  
  7. : cut here --- cut here --
  8. : To unbundle, sh this file
  9. #! /bin/sh
  10. : part 03
  11. echo x - lq-text/src/UseHash
  12. cat > lq-text/src/UseHash << 'barefoot_choirboy'
  13. # Run this if you want to use the BSD hash package (ozmahash)
  14. cd src
  15. cp ozmahash/*.h h
  16. cp ozmahash/ndbm.h h/ozmahash.h
  17. barefoot_choirboy
  18. chmod +x UseHash
  19. echo x - lq-text/src/liblqtext/Defaults.c 1>&2
  20. sed 's/^X//' >lq-text/src/liblqtext/Defaults.c <<'@@@End of lq-text/src/liblqtext/Defaults.c'
  21. X/* Defaults.c -- Copyright 1989 Liam R. Quin.  All Rights Reserved.
  22. X * This code is NOT in the public domain.
  23. X * See the file COPYRIGHT for full details.
  24. X *
  25. X * $Id: Defaults.c,v 1.7 90/10/06 00:11:37 lee Rel1-10 $
  26. X *
  27. X * $Log:    Defaults.c,v $
  28. X * Revision 1.7  90/10/06  00:11:37  lee
  29. X * Prepared for first beta release.
  30. X * 
  31. X * Revision 1.6  90/08/29  21:46:25  lee
  32. X * Alpha release.
  33. X * 
  34. X * Revision 1.5  90/08/09  19:16:08  lee
  35. X * *** empty log message ***
  36. X * 
  37. X * Revision 1.4  90/04/21  17:26:26  lee
  38. X * now passes gcc -W (before Canada...)
  39. X * 
  40. X * Revision 1.3  90/03/23  17:58:57  lee
  41. X * Integrated with globals.h and added a few more comments.
  42. X * Also fixed a bug whereby the configuration file over-rode both
  43. X * command-line options and environment variables!
  44. X * 
  45. X * Revision 1.2  90/03/20  20:52:38  lee
  46. X * removed some globals...
  47. X * 
  48. X *
  49. X */
  50. X
  51. X#define DefineThem /* turn externs off so we do initialisations here */
  52. X# include "globals.h" /* defines and declarations for database filenames */
  53. X#undef DefineThem
  54. X#undef EXTERN
  55. X#include <fcntl.h>
  56. X#include <errno.h>
  57. X#ifdef SYSV
  58. Xextern int _filbuf(); /* this must appear before stdio.h is included... */
  59. X#endif
  60. X#include <stdio.h>
  61. X#include <malloc.h>
  62. X#include <ctype.h>
  63. X#include "emalloc.h"
  64. X#include <sys/types.h>
  65. X#include "fileinfo.h"
  66. X#include "wordinfo.h"
  67. X#include "phrase.h"
  68. X
  69. X/* $Id: Defaults.c,v 1.7 90/10/06 00:11:37 lee Rel1-10 $
  70. X *
  71. X * This file is part of nx-text, Liam Quin's text retrieval package.
  72. X *
  73. X * Defaults.c -- set up filenames etc. from defaults + cmd line + env.
  74. X *
  75. X * -DUNDERHOME is used here, as is DEFAULTCOMMONWORDS, etc. from Makefile.
  76. X * See comments in Makefile.
  77. X *
  78. X * $Log:    Defaults.c,v $
  79. X * Revision 1.7  90/10/06  00:11:37  lee
  80. X * Prepared for first beta release.
  81. X * 
  82. X * Revision 1.6  90/08/29  21:46:25  lee
  83. X * Alpha release.
  84. X * 
  85. X * Revision 1.5  90/08/09  19:16:08  lee
  86. X * *** empty log message ***
  87. X * 
  88. X * Revision 1.4  90/04/21  17:26:26  lee
  89. X * now passes gcc -W (before Canada...)
  90. X * 
  91. X * Revision 1.3  90/03/23  17:58:57  lee
  92. X * Integrated with globals.h and added a few more comments.
  93. X * Also fixed a bug whereby the configuration file over-rode both
  94. X * command-line options and environment variables!
  95. X * 
  96. X * Revision 1.2  90/03/20  20:52:38  lee
  97. X * removed some globals...
  98. X * 
  99. X *
  100. X */
  101. X
  102. X/* System and Library calls used in this function:
  103. X *
  104. X */
  105. Xextern int open(), close();
  106. Xextern void exit();
  107. X
  108. Xextern int atoi(), strcmp(), strlen();
  109. X#ifndef tolower
  110. X extern int tolower();
  111. X#endif
  112. Xextern char *strcpy();
  113. Xextern void perror();
  114. Xextern int ReadCommonWords(), IsDir();
  115. Xint cknatstr();
  116. Xstatic int NextChar();
  117. Xstatic void ReadDefaultFile();
  118. X
  119. X
  120. Xtypedef enum {
  121. X    FW_Cmdline,
  122. X    FW_Envvar,
  123. X    FW_Default, /* use the default */
  124. X    FW_File, /* from the config file */
  125. X    FW_None /* don't use any at all */
  126. X} t_FromWhere;
  127. X
  128. Xstatic t_FromWhere DirFromWhere = FW_Default;
  129. Xstatic t_FromWhere CommonFromWhere = FW_Default;
  130. Xstatic t_FromWhere DocFromWhere = FW_Default;
  131. X
  132. Xextern int MakeDocPath(); /* hand it DOCPATH... */
  133. Xextern int AsciiTrace;
  134. X
  135. Xchar *mkdbm();
  136. Xchar *joinstr3();
  137. X
  138. X/* should PCM_HalfCase be in globals.h??? */
  139. Xt_PhraseCaseMatch PhraseMatchLevel = PCM_HalfCase;
  140. X
  141. Xvoid
  142. XSetDefaults(argc, argv)
  143. X    int argc;
  144. X    char **argv;
  145. X{
  146. X    extern char *getenv();
  147. X    extern char *progname;
  148. X    char *p;
  149. X
  150. X    /* main() should have set progname.  If it didn't. we don't strip
  151. X     * the leading / as this is (I hope!) a testing and not a production
  152. X     * version... and an early test at that!
  153. X     */
  154. X    if (!progname || !*progname) progname = argv[0];
  155. X
  156. X    /* loop over arguments, looking for
  157. X     * -d -- set directory for database
  158. X     * -c -- common words file
  159. X     *
  160. X     * don't use getopts, as we'll be using that later in main(),
  161. X     * and it doesn't like being called twice.
  162. X     * As a result, main() should ignore the z: option.
  163. X     */
  164. X    while (--argc > 0) {
  165. X    if (**++argv == '-' || **argv == '+') {
  166. X        char TurnOn = (**argv == '-');
  167. X
  168. X        switch((*argv)[1]) {
  169. X        case 'm': /* precise matching */
  170. X        argv[0][1] = 'z'; /* so it gets ignored by getopt */
  171. X
  172. X        if (!*(p = &argv[0][2])) {
  173. X            if (argc > 1) {
  174. X            argc--; argv++;
  175. X            p = (*argv);
  176. X            } else {
  177. X            fprintf(stderr,
  178. X            "%s: -m must be followed by a, h or p; see -x\n",
  179. X                                progname);
  180. X            exit(1);
  181. X            }
  182. X        }
  183. X        if (p[1]) {
  184. X            fprintf(stderr,
  185. X            "%s: -m must be followed by a, h or p, not \"%s\"\n",
  186. X                                progname, p);
  187. X        }
  188. X
  189. X        switch (*p) {
  190. X        case 'p': /* precise */
  191. X            PhraseMatchLevel = PCM_SameCase;
  192. X            break;
  193. X        case 'h': /* heuristic */
  194. X            PhraseMatchLevel = PCM_HalfCase;
  195. X            break;
  196. X        case 'a': /* any, approxmate */
  197. X            PhraseMatchLevel = PCM_AnyCase;
  198. X            break;
  199. X        default:
  200. X            fprintf(stderr,
  201. X            "%s: -m must be followed by \"p\", \"h\" or \"a\";\n",
  202. X                                    progname);
  203. X            fprintf(stderr,
  204. X            "use %s -xv for more explanation.\n", progname);
  205. X            exit(1);
  206. X        }
  207. X        break;
  208. X
  209. X        case 'v': /* -v is the same as -t1 */
  210. X        argv[0][1] = 'Z'; /* so it gets ignored by getopt */
  211. X        ++AsciiTrace;
  212. X        break;
  213. X        case 't': /* trace level */
  214. X        argv[0][1] = 'z'; /* so it gets ignored by getopt */
  215. X        if (argv[0][2] != '\0') {
  216. X            p = &argv[0][2];
  217. X        } else {
  218. X            if (argc > 1) {
  219. X            argc--;
  220. X            p = (*++argv);
  221. X            } else {
  222. X            p = "1";
  223. X            }
  224. X        }
  225. X        if (cknatstr(p)) {
  226. X            AsciiTrace = atoi(p);
  227. X        } else {
  228. X            fprintf(stderr, "%s: -t: \"%s\" is not a number\n",
  229. X                                    progname, p);
  230. X            exit(1);
  231. X        }
  232. X        if (AsciiTrace <= 0) AsciiTrace = 1;
  233. X        fprintf(stderr, "%s: trace level set to %d\n",
  234. X                                progname, AsciiTrace);
  235. X
  236. X        break;
  237. X        case 'c': /* common file */
  238. X        if (TurnOn) {
  239. X            CommonFromWhere = FW_Cmdline;
  240. X            argv[0][1] = 'z'; /* so it gets ignored by getopt */
  241. X            if ((*argv)[2] != '\0') {
  242. X            CommonWordFile = &(*argv[2]);
  243. X            } else {
  244. X            if (argc > 1) {
  245. X                CommonWordFile = argv[1];
  246. X                argc--; argv++;
  247. X            } else {
  248. X                fprintf(stderr,
  249. X                "%s: -c option must be followed by a filename",
  250. X                                    progname);
  251. X                exit(1);
  252. X            }
  253. X            }
  254. X        } else { /* Turn off, +c, may be undocumented right now */
  255. X            CommonFromWhere = FW_None;
  256. X            break;
  257. X        }
  258. X        break;
  259. X        case 'd':
  260. X        argv[0][1] = 'z'; /* so it gets ignored by getopt */
  261. X        DirFromWhere = FW_Cmdline;
  262. X        if (argv[0][2] != '\0') {
  263. X            DatabaseDir = &argv[0][2];
  264. X        } else {
  265. X            if (argc > 1) {
  266. X            DatabaseDir = argv[1];
  267. X            argc--; argv++;
  268. X            } else {
  269. X            /* @error */
  270. X            fprintf(stderr,
  271. X                "%s: %cd must be followed by a directory name",
  272. X                        progname, TurnOn ? '-' : '+');
  273. X            exit(1);
  274. X            }
  275. X        }
  276. X        break;
  277. X        } /* end switch */
  278. X    } else {
  279. X        /* not an option, so stop looking */
  280. X        break;
  281. X    }
  282. X    } /* end while */
  283. X
  284. X    /* now we have parsed the command line arguments, so look for the
  285. X     * default directory
  286. X     */
  287. X    if (DirFromWhere == FW_Default) {
  288. X    char *t;
  289. X
  290. X    if ((t = getenv("LQTEXTDIR")) != (char *) 0) {
  291. X        DatabaseDir = emalloc(strlen(t) + 1);
  292. X        (void) strcpy(DatabaseDir, t);
  293. X        DirFromWhere = FW_Envvar;
  294. X    } else {
  295. X#ifdef UNDERHOME
  296. X        char *home = getenv("HOME");
  297. X
  298. X        if (home) {
  299. X        DatabaseDir = joinstr3(home, "/", UNDERHOME);
  300. X        if (!IsDir(DatabaseDir)) {
  301. X            fprintf(stderr,
  302. X                "%s: database directory \"%s\" inaccessible.\n",
  303. X                progname, DatabaseDir);
  304. X            exit(1);
  305. X        }
  306. X        } else {
  307. X        fprintf(stderr, "%s: can't find your login directory ($HOME)\n",
  308. X                    progname);
  309. X        exit(1);
  310. X        }
  311. X#endif /* UNDERHOME*/
  312. X        /* in either case it's the default... */
  313. X        DirFromWhere = FW_Default;
  314. X    }
  315. X    }
  316. X
  317. X    if (!DatabaseDir || !*DatabaseDir) {
  318. X    /* This can happen if there is no default, or if the user types
  319. X     * lqword -d ""
  320. X     * just to be malicious :-)
  321. X     */
  322. X    fprintf(stderr,
  323. X    "%s: You must give a database directory with -d or $LQTEXTDIR\n",
  324. X            progname);
  325. X    fprintf(stderr, "        use %s -xv for more details.\n", progname);
  326. X    exit(1);
  327. X    }
  328. X
  329. X    /* IsDir is in DocPath.c -- perhaps this should be, too. */
  330. X    if (!IsDir(DatabaseDir)) {
  331. X    char *msg = (char *) 0;
  332. X
  333. X    switch (DirFromWhere) {
  334. X    case FW_Cmdline:
  335. X        msg = " (specified with the -d option)";
  336. X        break;
  337. X    case FW_Envvar:
  338. X        msg = " (from $LQTEXTDIR)";
  339. X        break;
  340. X    }
  341. X    fprintf(stderr, "%s: \"%s\"%s is not a directory.\n",
  342. X                    progname, DatabaseDir, msg ? msg : " ");
  343. X    exit(1);
  344. X    }
  345. X
  346. X    /* set default filenames */
  347. X#define IfNot(x, y) ((x) ? (x) : (y))
  348. X
  349. X    FileIndex = mkdbm(DatabaseDir, IfNot(FileIndex, FILEINDEX));
  350. X    WordIndex = mkdbm(DatabaseDir, IfNot(WordIndex, WORDINDEX));
  351. X
  352. X    DataBase = joinstr3(DatabaseDir, "/", IfNot(DataBase, DATABASE));
  353. X    FidFile = joinstr3(DatabaseDir, "/", IfNot(FidFile, FIDFILE));
  354. X    WidFile = joinstr3(DatabaseDir, "/", IfNot(WidFile, WIDFILE));
  355. X    WidIndexFile =
  356. X        joinstr3(DatabaseDir, "/", IfNot(WidIndexFile, WIDINDEXFILE));
  357. X
  358. X    ReadDefaultFile();
  359. X
  360. X    if (AsciiTrace) {
  361. X    fprintf(stderr, "%s: lqtext directory \"%s\"\n",progname,DatabaseDir);
  362. X    }
  363. X
  364. X    if (CommonFromWhere == FW_Default) {
  365. X    char *c = getenv("LQCOMMON");
  366. X
  367. X    if (c) {
  368. X        CommonWordFile = emalloc(strlen(c) + 1);
  369. X        (void) strcpy(CommonWordFile, c);
  370. X        CommonFromWhere = FW_Envvar;
  371. X    }
  372. X    }
  373. X
  374. X    if (CommonFromWhere != FW_None && CommonWordFile && *CommonWordFile) {
  375. X    extern int errno;
  376. X    int c;
  377. X
  378. X    if (*CommonWordFile != '/') {
  379. X        CommonWordFile = joinstr3(DatabaseDir, "/", CommonWordFile);
  380. X    }
  381. X
  382. X    if ((c = open(CommonWordFile, O_RDONLY, 0)) < 0) {
  383. X        if (CommonFromWhere != FW_Default) {
  384. X        int e = errno;
  385. X        char *msg = " ";
  386. X
  387. X        switch (CommonFromWhere) {
  388. X        case FW_Cmdline:
  389. X            msg = " (from the -c option)";
  390. X            break;
  391. X        case FW_Envvar:
  392. X            msg = " (from $COMMONWORDS)";
  393. X            break;
  394. X        }
  395. X
  396. X        fprintf(stderr,"%s: can't read common-word file%s ",progname,msg);
  397. X        errno = e;
  398. X        if (errno) {
  399. X            perror(CommonWordFile);
  400. X        } else {
  401. X            fprintf(stderr, "\"%s\"\n", CommonWordFile);
  402. X        }
  403. X        exit(1);
  404. X        }
  405. X        CommonWordFile = (char *) 0;
  406. X    } else {
  407. X        (void) close(c); /* it's OK */
  408. X    }
  409. X    }
  410. X
  411. X    if ((p = getenv("DOCPATH")) != (char *) 0) {
  412. X    switch (DocFromWhere) {
  413. X    case FW_File:
  414. X        if (AsciiTrace > 1) {
  415. X        fprintf(stderr, "%s: DOCPATH (%s) overrides %s (%s)\n",
  416. X#ifdef CONFIGFILE
  417. X                progname, p, CONFIGFILE, DocPath
  418. X#else
  419. X                progname, p, "README", DocPath
  420. X#endif
  421. X        );
  422. X        }
  423. X        efree(DocPath);
  424. X        /* FALL THROUGH */
  425. X    case FW_Default:
  426. X    default: /* ? */
  427. X        DocPath = emalloc((unsigned) (strlen(p) + 1));
  428. X        (void) strcpy(DocPath, p);
  429. X        DocFromWhere = FW_Envvar;
  430. X        break;
  431. X    }
  432. X    }
  433. X
  434. X    if (!DocPath || !*DocPath) {
  435. X    DocPath = ".";
  436. X    }
  437. X
  438. X#define SetOrNot(s) ( (s && *s) ? s : (s ? "[empty]" : "[null]" ) )
  439. X
  440. X    /* this is always here -- it's only checked once, and is actually
  441. X     * rather useful.
  442. X     */
  443. X    if (AsciiTrace > 2) {
  444. X    fprintf(stderr, "%s: CommonWordFile = \"%s\"\n", progname,
  445. X        SetOrNot(CommonWordFile));
  446. X    fprintf(stderr, "%s: DatabaseDir = \"%s\"\n", progname,
  447. X        SetOrNot(DatabaseDir));
  448. X    fprintf(stderr, "%s: DocPath  = \"%s\"\n", progname,
  449. X        SetOrNot(DocPath));
  450. X    fprintf(stderr, "%s: FileIndex = \"%s\"\n", progname,
  451. X        SetOrNot(FileIndex));
  452. X    fprintf(stderr, "%s: WordIndex = \"%s\"\n", progname,
  453. X        SetOrNot(WordIndex));
  454. X    fprintf(stderr, "%s: DataBase = \"%s\"\n", progname,
  455. X        SetOrNot(DataBase));
  456. X    fprintf(stderr, "%s: FidFile = \"%s\"\n", progname,
  457. X        SetOrNot(FidFile));
  458. X    fprintf(stderr, "%s: WidFile = \"%s\"\n", progname,
  459. X        SetOrNot(WidFile));
  460. X    fprintf(stderr, "%s: WidIndexFile = \"%s\"\n", progname,
  461. X        SetOrNot(WidIndexFile));
  462. X    }
  463. X
  464. X    (void) MakeDocPath(DocPath);
  465. X    /* DocPath is no longer needed, so getenv() can be called again now */
  466. X
  467. X    if (CommonWordFile && *CommonWordFile) {
  468. X    (void) ReadCommonWords(CommonWordFile);
  469. X    }
  470. X}
  471. X
  472. Xvoid
  473. XDefaultUsage()
  474. X{
  475. X    fprintf(stderr, "\
  476. X    -c file    -- ignore words that are listed in the namd file\n\
  477. X    -d dir    -- use the lq-text database in the named directory\n\
  478. X    -m c    -- set matching criteria -- c is \"p\", \"h\" or \"a\"\n");
  479. X    if (AsciiTrace) {
  480. X    fprintf(stderr, "\
  481. X           -m p  uses precise matching, where CaSe is significant;\n\
  482. X           -m h  uses heuristic matching, which is the default, and\n\
  483. X           -m a  uses approximate matching.\n");
  484. X    }
  485. X
  486. X    fprintf(stderr, "\n\
  487. X    -t N    -- set trace level t N (default is zero)\n\
  488. X    -x    -- print %s explanation\n\
  489. X    -xv    -- print %s explanation\n\
  490. X    -V    -- print version information\n\
  491. X    -v    -- be verbose (same as -t 1)\n",
  492. X            AsciiTrace ? "a shorter" : "this",
  493. X            AsciiTrace ? "this" : "a longer");
  494. X    if (AsciiTrace) {
  495. X    fprintf(stderr, "\
  496. XThe current database directory is \"%s\";\n\
  497. X%s will search the path \"%s\" for documents.\n", DatabaseDir, progname, DocPath);
  498. X    }
  499. X}
  500. X
  501. X/* This should be in smalldb.c I think */
  502. Xchar *
  503. Xmkdbm(root, prefix)
  504. X    char *root; /* /tmp/lqtext */
  505. X    char *prefix; /* wordlist, --> /tmp/lqtext.{dir,pag} for dbm */
  506. X{
  507. X#if DBMCREAT == 0
  508. X    extern int errno;
  509. X#endif
  510. X    /* Although ndbm will create files automatically, gdbm and dbm will
  511. X     * not, so we do that here.
  512. X     * Also, it might take a while to get to here, so it will be a lot
  513. X     * better if we get an error message now.
  514. X     */
  515. X    char *p = joinstr3(root, "/", prefix);
  516. X
  517. X#if DBMCREAT == 0
  518. X    q = joinstr3(p, ".", "dir");
  519. X    errno = 0; /* paranoia */
  520. X
  521. X    if ((i = open(q)) < 0 && errno == ENOENT) {
  522. X    i = open(q, O_CREAT|O_RDWR, 0666); /* rw-rw-rw & umask */
  523. X
  524. X    if (i < 0) {
  525. X        fprintf(stderr, "%s: can't create \"%s\"\n", progname, q);
  526. X        (void) exit(1);
  527. X    }
  528. X
  529. X    (void) close(i);
  530. X    }
  531. X    (void) strcpy(&q[strlen(q) - 3], "pag");
  532. X
  533. X    if ((i = open(q)) < 0 && errno == ENOENT) {
  534. X    i = open(q, O_CREAT|O_RDWR, 0666); /* rw-rw-rw & umask */
  535. X
  536. X    if (i < 0) {
  537. X        fprintf(stderr, "%s: can't create \"%s\"\n", progname, q);
  538. X        (void) exit(1);
  539. X    }
  540. X
  541. X    (void) close(i);
  542. X    }
  543. X
  544. X    (void) efree(q);
  545. X
  546. X#endif /*DBMCREAT*/
  547. X
  548. X    return p; /* the prefix for dbm, not the whole path */
  549. X}
  550. X
  551. X/* this belongs in string.c or something */
  552. Xchar *
  553. Xjoinstr3(a, b, c)
  554. X    char *a, *b, *c;
  555. X{
  556. X    char *p;
  557. X    int i = strlen(a), j = (b[0] != '\0' && b[1] == '\0') ? 1 : strlen(b);
  558. X
  559. X    p = emalloc(i + j + strlen(c) + 1);
  560. X    /* ASSERT: p != 0 */
  561. X    (void) strcpy(p, a);
  562. X    (void) strcpy(&p[i], b);
  563. X    (void) strcpy(&p[i + j], c);
  564. X
  565. X    return p;
  566. X}
  567. X
  568. X#define LCNOMAP 0 /* Token -- leave case alone */
  569. X#define LCMAP 1  /* map to lower case */
  570. X
  571. Xstatic int RMLine = 0;
  572. X
  573. Xstatic void
  574. XReadDefaultFile()
  575. X{
  576. X    extern int errno;
  577. X
  578. X    static char *NextToken(); /* see below */
  579. X#ifdef CONFIGFILE
  580. X    char *ReadMe = joinstr3(DatabaseDir, "/", CONFIGFILE);
  581. X#else
  582. X    char *ReadMe = joinstr3(DatabaseDir, "/", "README");
  583. X#endif
  584. X    FILE *fp;
  585. X    char *Token;
  586. X
  587. X
  588. X    /* This is paranoid... */
  589. X    if (!ReadMe || !*ReadMe) {
  590. X    fprintf(stderr, "%s: Internal: %s: %d: ReadMe %s\n",
  591. X        progname, __FILE__, __LINE__, SetOrNot(ReadMe));
  592. X    exit(1);
  593. X    }
  594. X
  595. X    errno = 0;
  596. X    if ((fp = fopen(ReadMe, "r")) == (FILE *) 0) {
  597. X    if (errno == EPERM) {
  598. X        fprintf(stderr,
  599. X        "%s: Warning: you don't have permission to read \"%s\"\n",
  600. X                            progname, ReadMe);
  601. X    } else if (AsciiTrace) {
  602. X        int e = errno;
  603. X
  604. X        fprintf(stderr, "%s: warning: can't open config file ", progname);
  605. X        errno = e;
  606. X        perror(ReadMe);
  607. X    }
  608. X    return;
  609. X    }
  610. X
  611. X    /* Read README up to an "end" line, ignoring lines starting with # */
  612. X
  613. X    while ((Token = NextToken(fp, ReadMe, LCMAP)) != (char *) 0) {
  614. X    if (STREQ(Token, "end")) goto finish;
  615. X    if (STREQ(Token, "common")) {
  616. X        if (!(Token = NextToken(fp, ReadMe, LCNOMAP))) {
  617. X        fprintf(stderr, "%s: %s %d: unexpected eof at common file\n",
  618. X                progname, ReadMe, RMLine);
  619. X        exit(1);
  620. X        } else if (CommonFromWhere == FW_Default) {
  621. X            CommonWordFile = emalloc((unsigned) (strlen(Token) + 1));
  622. X            (void) strcpy(CommonWordFile, Token);
  623. X            CommonFromWhere = FW_File;
  624. X        }
  625. X    } else if (STREQ(Token, "path") || STREQ(Token, "docpath")) {
  626. X        if (!(Token = NextToken(fp, ReadMe, LCNOMAP))) {
  627. X        fprintf(stderr, "%s: %s: %d: unexpected eof at common file\n",
  628. X                progname, ReadMe, RMLine);
  629. X        exit(1);
  630. X        } else {
  631. X        DocPath = emalloc((unsigned) (strlen(Token) + 1));
  632. X        (void) strcpy(DocPath, Token);
  633. X        DocFromWhere = FW_File;
  634. X        }
  635. X    } else {
  636. X        fprintf(stderr, "%s: \"%s\": %d: token(\"%s\") unexpected\n",
  637. X                progname, ReadMe, RMLine, Token);
  638. X        exit(1);
  639. X    }
  640. X    } /* while */
  641. X
  642. Xfinish:
  643. X    (void) fclose(fp);
  644. X    return;
  645. X}
  646. X
  647. Xstatic char *
  648. XNextToken(fd, Name, Map)
  649. X    FILE *fd;
  650. X    char *Name;
  651. X    int Map;
  652. X{
  653. X    int ch;
  654. X    static char buf[50];
  655. X    register char *q = buf;
  656. X    int InQuote = 0;
  657. X    int OriginalMap = Map;
  658. X
  659. X    while ((ch = NextChar(fd, Name, Map)) != EOF) {
  660. X    switch (ch) {
  661. X    case '"': case '\'':
  662. X        if (q == buf && !InQuote) InQuote = ch;
  663. X        else if (ch == InQuote) {
  664. X        *q = '\0';
  665. X        if (AsciiTrace > 10) {
  666. X            fprintf(stderr, "RM[%s] ", buf);
  667. X        }
  668. X        return buf;
  669. X        }
  670. X        Map = 0; /* no case conversion inside strings */
  671. X        break;
  672. X    case '\\':
  673. X        if ((ch = NextChar(fd, Name, Map)) == EOF) {
  674. X        fprintf(stderr, "%s: %s; %d: EOF after \\ unexpected!\n",
  675. X                            progname, Name, RMLine);
  676. X        exit(1);
  677. X        }
  678. X        *q++ = ch;
  679. X        break;
  680. X    case ' ':
  681. X    case '\n':
  682. X        if (InQuote) {
  683. X        fprintf(stderr, "%s: %s: %d: missing quote -->%s<--\n",
  684. X                        progname, Name, RMLine, InQuote);
  685. X        exit(1);
  686. X        }
  687. X        *q = '\0';
  688. X        if (q > buf) return buf;
  689. X        else return NextToken(fd, Name, OriginalMap);
  690. X        /*NOTREACHED*/
  691. X        break;
  692. X    default:
  693. X        *q++ = ch;
  694. X    }
  695. X    }
  696. X    if (q > buf) {
  697. X    fprintf(stderr, "%s: %s: %d: unexpected end of file\n",
  698. X                            progname, Name, RMLine);
  699. X    exit(1);
  700. X    }
  701. X    return (char *) 0;
  702. X}
  703. X
  704. Xstatic int
  705. XNextChar(fd, Name, Map)
  706. X    FILE *fd;
  707. X    char *Name;
  708. X    int Map;
  709. X{
  710. X    int ch;
  711. X
  712. X    while ((ch = getc(fd)) != EOF) {
  713. X    switch (ch) {
  714. X    case '#':
  715. X        do {
  716. X        if ((ch = getc(fd)) == EOF) {
  717. X            fprintf(stderr, "%s: %s: %d: unexpected end of file\n",
  718. X                progname, Name, RMLine);
  719. X            exit(1);
  720. X        }
  721. X        } while (ch != '\n');
  722. X        /* ASSERT: ch == '\n' */
  723. X        ++RMLine;
  724. X        break;
  725. X    case '\n':
  726. X        ++RMLine; 
  727. X        if (!Map) return ch;
  728. X        /* else FALL THROUGH */
  729. X    case ' ': case '\t': case '\f': case '\r':
  730. X        if (!Map) {
  731. X        return ' ';
  732. X        }
  733. X
  734. X    default:
  735. X        return (Map && isupper(ch)) ? tolower(ch) : ch;
  736. X    }
  737. X    } /* while */
  738. X    return EOF;
  739. X}
  740. X
  741. Xint
  742. Xcknatstr(str)
  743. X    char *str;
  744. X{
  745. X    /* check that a string represents a positive or 0 number */
  746. X    register char *p = str;
  747. X
  748. X    /* skip leading white space */
  749. X    while (isspace(*p)) p++;
  750. X    if (!*p) return 0;
  751. X
  752. X    /* allow a leading sign */
  753. X    if (*p == '-' || *p == '+') p++;
  754. X    if (!*p) return 0;
  755. X
  756. X    /* now skip digits... */
  757. X    while (isdigit(*p)) p++;
  758. X
  759. X    return (p > str && *p == '\0');
  760. X}
  761. X
  762. X/* you can tell I am tired by the extra end-while etc. comments.
  763. X * wonder if it will work?
  764. X * perhaps if I took my socks off too.
  765. X *
  766. X * Hmm, yeah, that worked.
  767. X */
  768. @@@End of lq-text/src/liblqtext/Defaults.c
  769. echo x - lq-text/src/liblqtext/DocPath.c 1>&2
  770. sed 's/^X//' >lq-text/src/liblqtext/DocPath.c <<'@@@End of lq-text/src/liblqtext/DocPath.c'
  771. X/* DocPath.c -- Copyright 1989 Liam R. Quin.  All Rights Reserved.
  772. X * This code is NOT in the public domain.
  773. X * See the file COPYRIGHT for full details.
  774. X *
  775. X * $Id: DocPath.c,v 1.5 90/10/06 00:11:53 lee Rel1-10 $
  776. X *
  777. X *
  778. X * $Log:    DocPath.c,v $
  779. X * Revision 1.5  90/10/06  00:11:53  lee
  780. X * Prepared for first beta release.
  781. X * 
  782. X * Revision 1.4  90/10/05  23:43:19  lee
  783. X * Put the debugging in isfile() within ASCIITRACE ifdefs.
  784. X * 
  785. X * Revision 1.3  90/08/29  21:46:32  lee
  786. X * Alpha release.
  787. X * 
  788. X * Revision 1.2  90/08/09  19:16:12  lee
  789. X * *** empty log message ***
  790. X * 
  791. X *
  792. X */
  793. X
  794. X#include "globals.h" /* defines and declarations for database filenames */
  795. X
  796. X#include <sys/types.h>
  797. X#include <sys/stat.h>
  798. X#ifdef BSD
  799. X# include <sys/param.h>
  800. X# define PATH_MAX MAXPATHLEN
  801. X#else /*not BSD*/
  802. X# include <limits.h> /* for PATH_MAX */
  803. X#endif
  804. X#include <stdio.h>
  805. X#include "emalloc.h"
  806. X#include "fileinfo.h"
  807. X
  808. X/** Unix system calls: **/
  809. Xextern int stat();
  810. X/** C Library functions: **/
  811. Xextern int strlen();
  812. Xextern char *strcpy();
  813. X/** Within this file: **/
  814. Xextern int IsDir();
  815. X/** **/
  816. X
  817. X#ifdef ASCIITRACE
  818. Xextern int AsciiTrace;
  819. X#endif
  820. X
  821. Xtypedef struct s_DocPath {
  822. X    char *DirName;
  823. X    struct s_DocPath *Next;
  824. X} t_DocPath;
  825. X
  826. Xstatic t_DocPath *XDocPath = 0;
  827. X
  828. X#ifndef PATH_MAX
  829. X# define PATH_MAX 2048
  830. X#endif
  831. X
  832. Xchar *
  833. X_FindFile(Name)
  834. X    char *Name;
  835. X{
  836. X    int IsFile();
  837. X
  838. X    t_DocPath *p;
  839. X    static char Buffer[PATH_MAX + 3]; /* +1 for "\0" */
  840. X
  841. X    if (!XDocPath) {
  842. X#ifdef ASCIITRACE
  843. X    if (AsciiTrace > 4) {
  844. X        fprintf(stderr, "FindFile(%s) --> %s\n", Name,
  845. X                    IsFile(Name) ? Name : (char *) 0);
  846. X    }
  847. X#endif
  848. X    return IsFile(Name) ? Name : (char *) 0;
  849. X    }
  850. X
  851. X    for (p = XDocPath; p; p = p->Next) {
  852. X    (void) sprintf(Buffer, "%s/%s", p->DirName, Name);
  853. X    if (IsFile(Buffer)) {
  854. X#ifdef ASCIITRACE
  855. X        if (AsciiTrace > 4) {
  856. X        fprintf(stderr, "FindFile(%s) --> %s\n", Name, Buffer);
  857. X        }
  858. X#endif
  859. X        return Buffer;
  860. X    }
  861. X    }
  862. X
  863. X    return (char*) 0;
  864. X}
  865. X
  866. Xint
  867. XMakeDocPath(Path)
  868. X    char *Path;
  869. X{
  870. X    extern char *getenv();
  871. X
  872. X    char *Start, *End;
  873. X    t_DocPath **dpp;
  874. X
  875. X    if (XDocPath == (t_DocPath *) 0) {
  876. X    dpp = &XDocPath;
  877. X    *dpp = (t_DocPath *) 0;
  878. X
  879. X    /* For each element in DocPath, */
  880. X    for (Start = Path; Start && *Start; Start = End) {
  881. X        char SaveEnd;
  882. X
  883. X        /* find the end of this bit of the path */
  884. X        for (End = Start; *End && *End != ':'; End++)
  885. X        ;
  886. X        
  887. X        if (End == Start) break;
  888. X
  889. X        SaveEnd = (*End);
  890. X        *End = '\0';
  891. X
  892. X        /* if not a directory, delete from path */
  893. X        if (!IsDir(Start)) {
  894. X        *End = SaveEnd;
  895. X        continue;
  896. X        }
  897. X
  898. X        /* add to the linked list */
  899. X        *dpp = (t_DocPath *) emalloc(sizeof(t_DocPath));
  900. X        (*dpp)->DirName = emalloc(strlen(Start) + 1);
  901. X        (void) strcpy((*dpp)->DirName, Start);
  902. X        dpp = &(*dpp)->Next;
  903. X        (*dpp) = (t_DocPath *) 0;
  904. X        if ((*End = SaveEnd) != '\0') {
  905. X        End++;
  906. X        }
  907. X    }
  908. X    }
  909. X    return 0;
  910. X}
  911. X
  912. Xint
  913. XIsDir(Dir)
  914. X    char *Dir;
  915. X{
  916. X    struct stat statbuf;
  917. X
  918. X    if (!Dir || !*Dir) return 0;
  919. X    if (stat(Dir, &statbuf) < 0) return 0;
  920. X    if ((statbuf.st_mode & S_IFMT) != S_IFDIR) {
  921. X    return 0;
  922. X    }
  923. X    return 1;
  924. X}
  925. X
  926. Xint
  927. XIsFile(Path)
  928. X    char *Path;
  929. X{
  930. X    struct stat statbuf;
  931. X
  932. X#ifdef ASCIITRACE
  933. X    if (AsciiTrace > 20) {
  934. X    fprintf(stderr, "IsFile(%s)\n", Path);
  935. X    }
  936. X#endif
  937. X    if (stat(Path, &statbuf) < 0) return 0;
  938. X    if ((statbuf.st_mode & S_IFMT) != S_IFREG) {
  939. X    return 0;
  940. X    }
  941. X#ifdef ASCIITRACE
  942. X    if (AsciiTrace > 20) {
  943. X    fprintf(stderr, "\t\tIsFile(%s) returns true.\n", Path);
  944. X    }
  945. X#endif
  946. X    return 1;
  947. X}
  948. @@@End of lq-text/src/liblqtext/DocPath.c
  949. echo x - lq-text/src/liblqtext/FileList.c 1>&2
  950. sed 's/^X//' >lq-text/src/liblqtext/FileList.c <<'@@@End of lq-text/src/liblqtext/FileList.c'
  951. X/* FileList.c -- Copyright 1989 Liam R. Quin.  All Rights Reserved.
  952. X * This code is NOT in the public domain.
  953. X * See the file COPYRIGHT for full details.
  954. X */
  955. X
  956. X/*
  957. X *
  958. X * FileList -- operations on the list of files.  This is the Document
  959. X * Directory part of NX-Text.
  960. X *
  961. X * $Id: FileList.c,v 1.8 90/10/13 02:39:05 lee Rel1-10 $
  962. X *
  963. X * $Log:    FileList.c,v $
  964. X * Revision 1.8  90/10/13  02:39:05  lee
  965. X * deleted some incorrect code.
  966. X * 
  967. X * Revision 1.7  90/10/13  02:21:03  lee
  968. X * NEEDALIGN stuff
  969. X * 
  970. X * Revision 1.6  90/10/07  20:37:18  lee
  971. X * changed ifdef sparc to ifdef NEEDALIGN
  972. X * 
  973. X * Revision 1.5  90/10/06  00:11:55  lee
  974. X * Prepared for first beta release.
  975. X * 
  976. X * Revision 1.4  90/09/29  23:46:14  lee
  977. X * very minor speedup, and changed a free() to efree().
  978. X * 
  979. X * Revision 1.3  90/09/20  19:11:05  lee
  980. X * deleted unused locking code.
  981. X * removed a sun4-specific memory leak.  Other minor changes.
  982. X * 
  983. X * Revision 1.2  90/08/29  21:46:33  lee
  984. X * Alpha release.
  985. X * 
  986. X * Revision 1.1  90/08/09  19:16:15  lee
  987. X * Initial revision
  988. X * 
  989. X * Revision 2.2  89/10/08  20:29:10  lee
  990. X * Working version of nx-text engine.  Addfile and wordinfo work OK.
  991. X * 
  992. X * Revision 2.1  89/10/02  01:12:08  lee
  993. X * New index format, with Block/WordInBlock/Flags/BytesSkipped info.
  994. X * 
  995. X * Revision 1.2  89/09/16  21:15:54  lee
  996. X * First demonstratable version.
  997. X * 
  998. X * Revision 1.1  89/09/07  21:01:36  lee
  999. X * Initial revision
  1000. X * 
  1001. X *
  1002. X */
  1003. X
  1004. X#include "globals.h" /* defines and declarations for database filenames */
  1005. X
  1006. X#include <stdio.h>
  1007. X#include <malloc.h>
  1008. X#include <unistd.h>
  1009. X#include <sys/types.h>
  1010. X#include <sys/stat.h>
  1011. X#include <signal.h>
  1012. X#include <errno.h>
  1013. X#include <fcntl.h>
  1014. X#include <string.h>
  1015. X
  1016. X#include "smalldb.h"
  1017. X#include "fileinfo.h"
  1018. X#include "emalloc.h"
  1019. X
  1020. X/** Unix system calls that need to be declared: **/
  1021. Xextern int stat();
  1022. Xextern int open(), close(), creat();
  1023. Xextern void exit();
  1024. Xextern int read(), write();
  1025. Xextern unsigned alarm();
  1026. X/** library functions that need to be declared: */
  1027. Xextern int lockf();
  1028. Xextern unsigned sleep();
  1029. Xextern void perror();
  1030. Xextern long atol();
  1031. X
  1032. X/** other (lqtext) functions **/
  1033. Xt_FID GetNextFID();
  1034. Xt_FileInfo *GetFileInfo();
  1035. X/** **/
  1036. X
  1037. Xt_FID
  1038. XGetMaxFID()
  1039. X{
  1040. X    extern int errno;
  1041. X
  1042. X    int fd;
  1043. X    struct stat StatBuf;
  1044. X    char Buffer[20];
  1045. X
  1046. X    /* ensure that the file is there */
  1047. X    if (stat(FidFile, &StatBuf) == -1) {
  1048. X    return 0;
  1049. X    }
  1050. X
  1051. X    if ((fd = open(FidFile, O_RDWR, 0)) < 0) {
  1052. X    fprintf(stderr, "Warning: Can't open FID file");
  1053. X    return 0;
  1054. X    }
  1055. X
  1056. X    /* Read the file */
  1057. X    if (read(fd, Buffer, (unsigned int) StatBuf.st_size) < 0) {
  1058. X    fprintf(stderr, "Can't read from \"%s\"\n", FidFile);
  1059. X    exit(1);
  1060. X    }
  1061. X
  1062. X    (void) close(fd);
  1063. X
  1064. X    Buffer[StatBuf.st_size] = '\0';
  1065. X
  1066. X    return atol(Buffer);
  1067. X}
  1068. X
  1069. X/*ARGSUSED*/
  1070. Xt_FID
  1071. XGetNextFID(Size)
  1072. X    long Size; /* to let it keep short FIDs for huge files, execpt I don't */
  1073. X{
  1074. X    extern int errno;
  1075. X    extern long atol();
  1076. X    extern long lseek();
  1077. X
  1078. X    int fd;
  1079. X    char Buffer[21];
  1080. X    struct stat StatBuf;
  1081. X    t_FID Result;
  1082. X
  1083. X    /* ensure that the file is there */
  1084. X    if (stat(FidFile, &StatBuf) == -1) {
  1085. X    fprintf(stderr, "Creating FID file \"%s\"\n", FidFile);
  1086. X    if ((fd = creat(FidFile, 02666)) < 0) {
  1087. X        fprintf(stderr, "Can't create FID file \"%s\"\n", FidFile);
  1088. X        exit(1);
  1089. X    }
  1090. X    (void) close(fd);
  1091. X    return GetNextFID(Size);
  1092. X
  1093. X    /*NOTREACHED*/
  1094. X    }
  1095. X
  1096. X    if ((fd = open(FidFile, O_RDWR, 0)) < 0) {
  1097. X    fprintf(stderr, "Can't open FID file");
  1098. X    perror(FidFile);
  1099. X    exit(1);
  1100. X    }
  1101. X
  1102. X    errno = 0;
  1103. X
  1104. X    /* Read the file */
  1105. X    if (read(fd, Buffer, (unsigned int) StatBuf.st_size) < 0) {
  1106. X    fprintf(stderr, "Can't read from \"%s\"\n", FidFile);
  1107. X    exit(1);
  1108. X    }
  1109. X
  1110. X    Buffer[StatBuf.st_size] = '\0';
  1111. X
  1112. X    Result = atol(Buffer);
  1113. X
  1114. X    if (Result == 0L || *Buffer == '-') {
  1115. X    Result = 1L;
  1116. X    }
  1117. X
  1118. X    (void) sprintf(Buffer, "%lu\n", Result + 1);
  1119. X
  1120. X    /* Move to the start of the file and write the now value.
  1121. X     * No need to truncate the file, because it didn't shrink!
  1122. X     */
  1123. X    (void) lseek(fd, 0, 0L);
  1124. X    (void) write(fd, Buffer, (unsigned int) strlen(Buffer));
  1125. X    (void) close(fd);
  1126. X
  1127. X    return Result;
  1128. X}
  1129. X
  1130. Xtypedef struct {
  1131. X    t_FID FID;
  1132. X    time_t DateLastIndexed;
  1133. X    int FilterType;
  1134. X    unsigned NameLength;
  1135. X    char CurrentLocation[1];
  1136. X} t_PhysicalIndexEntry;
  1137. X
  1138. Xt_PhysicalIndexEntry *
  1139. XFileInfo2Phys(FileInfo)
  1140. X    t_FileInfo *FileInfo;
  1141. X{
  1142. X    t_PhysicalIndexEntry *PIE;
  1143. X    register int NameLength;
  1144. X
  1145. X    if (!FileInfo || !FileInfo->Name) return (t_PhysicalIndexEntry *) 0;
  1146. X
  1147. X    NameLength = strlen(FileInfo->Name);
  1148. X
  1149. X    PIE = (t_PhysicalIndexEntry *) emalloc(
  1150. X                sizeof(t_PhysicalIndexEntry) + NameLength + 1);
  1151. X
  1152. X    if (!PIE) return (t_PhysicalIndexEntry *) 0;
  1153. X
  1154. X    PIE->FID = FileInfo->FID;
  1155. X    PIE->DateLastIndexed = FileInfo->Date;
  1156. X    PIE->FilterType = FileInfo->FilterType;
  1157. X    PIE->NameLength = NameLength;
  1158. X    (void) strcpy(PIE->CurrentLocation, FileInfo->Name);
  1159. X    return PIE;
  1160. X}
  1161. X
  1162. Xt_FileInfo *
  1163. XPhys2FileInfo(PIE)
  1164. X    t_PhysicalIndexEntry *PIE;
  1165. X{
  1166. X    t_FileInfo *FileInfo;
  1167. X
  1168. X    if (!PIE || !PIE->NameLength) return (t_FileInfo *) 0;
  1169. X
  1170. X    FileInfo = (t_FileInfo *) emalloc(sizeof(t_FileInfo));
  1171. X    FileInfo->FID = PIE->FID;
  1172. X    FileInfo->Date = PIE->DateLastIndexed;
  1173. X    FileInfo->FilterType = PIE->FilterType;
  1174. X    FileInfo->Stream = (FILE *) 0;
  1175. X    if (PIE->NameLength) {
  1176. X#if 0
  1177. X    char *doc;
  1178. X#endif
  1179. X
  1180. X    FileInfo->Name = emalloc(PIE->NameLength + 1);
  1181. X    (void) strncpy(FileInfo->Name, PIE->CurrentLocation,
  1182. X                            PIE->NameLength);
  1183. X    FileInfo->Name[PIE->NameLength] = '\0';
  1184. X
  1185. X#if 0
  1186. X    /* with this in place, wordinfo spends over 40% of its time
  1187. X     * in stat!
  1188. X     */
  1189. X    if ((doc = FindFile(FileInfo->Name)) != (char *) 0) {
  1190. X        /* hence, we never retrieve non-existent files */
  1191. X        FileInfo->Name = erealloc(FileInfo->Name, strlen(doc) + 1);
  1192. X        (void) strcpy(FileInfo->Name, doc);
  1193. X    }
  1194. X#endif
  1195. X    } else {
  1196. X    FileInfo->Name = (char *) 0;
  1197. X    }
  1198. X
  1199. X    return FileInfo;
  1200. X}
  1201. X
  1202. Xint
  1203. XSaveFileInfo(FileInfo)
  1204. X    t_FileInfo *FileInfo;
  1205. X{
  1206. X    t_PhysicalIndexEntry *PIE;
  1207. X    datum key, data;
  1208. X    DBM *db;
  1209. X    int RetVal;
  1210. X    char Buffer[20];
  1211. X
  1212. X    if (!FileInfo) return -1;
  1213. X
  1214. X    if ((PIE = FileInfo2Phys(FileInfo)) == (t_PhysicalIndexEntry *) 0) {
  1215. X    return -1;
  1216. X    }
  1217. X
  1218. X    if ((db = startdb(FileIndex)) == (DBM *) 0) {
  1219. X    return -1;
  1220. X    }
  1221. X
  1222. X    if (FileInfo->Name && *(FileInfo->Name)) {
  1223. X    /* For the reverse mapping, FileName --> FID ... store an
  1224. X     * entry of the form ([\377]317, "hello").
  1225. X     * This scheme simply has to go.
  1226. X     * I favour a btree, but that may be needlessly complex.
  1227. X     */
  1228. X    int KeyLen = strlen(FileInfo->Name);
  1229. X    key.dptr = emalloc(KeyLen + 2); /* +2: "\375" and \0 */
  1230. X    /* Note: the N= is so that a file called "123" does not cause
  1231. X     * confusion with the reverse mapping
  1232. X     */
  1233. X    *(key.dptr) = '\375';
  1234. X    (void) strcpy(&(key.dptr[1]), FileInfo->Name);
  1235. X    key.dsize = KeyLen + 1;
  1236. X        /* length of name + length of "\375" -- the nul at the end
  1237. X         * is not included.
  1238. X         */
  1239. X
  1240. X    (void) sprintf(Buffer, "%lu", FileInfo->FID);
  1241. X    data.dptr = Buffer;
  1242. X    data.dsize = strlen(Buffer);
  1243. X    (void) dbm_store(db, key, data, DBM_REPLACE);
  1244. X    (void) efree(key.dptr);
  1245. X    }
  1246. X
  1247. X    (void) sprintf(Buffer, "F%lu", FileInfo->FID);
  1248. X
  1249. X    key.dptr = Buffer;
  1250. X    key.dsize = strlen(Buffer);
  1251. X
  1252. X    data.dptr = (char *) PIE;
  1253. X    data.dsize = sizeof(t_PhysicalIndexEntry) + PIE->NameLength;
  1254. X
  1255. X    RetVal = dbm_store(db, key, data, DBM_REPLACE);
  1256. X
  1257. X    enddb(db);
  1258. X
  1259. X    return RetVal;
  1260. X}
  1261. X
  1262. Xt_FID
  1263. XName2FID(Name)
  1264. X    char *Name;
  1265. X{
  1266. X    DBM *db;
  1267. X    datum key, result;
  1268. X    extern long atol();
  1269. X
  1270. X    key.dsize = strlen(Name);
  1271. X    /* see previous routine for comments about this +2 ugliness */
  1272. X    key.dptr = emalloc(key.dsize + 2);
  1273. X    *(key.dptr) = '\375';
  1274. X    (void) strcpy(&(key.dptr[1]), Name);
  1275. X    key.dsize += 1; /* for the cookie; we don't include the \0 */
  1276. X
  1277. X    if ((db = startdb(FileIndex)) == (DBM *) 0) {
  1278. X    fprintf(stderr, "Name2FID can't get FID for %s (database \"%s\"\n", Name, FileIndex);
  1279. X    (void) efree(key.dptr);
  1280. X    return -1;
  1281. X    }
  1282. X    result = dbm_fetch(db, key);
  1283. X    enddb(db);
  1284. X
  1285. X    (void) efree(key.dptr);
  1286. X
  1287. X    return (result.dsize == 0) ? (t_FID) 0 : atol(result.dptr);
  1288. X}
  1289. X
  1290. Xt_FileInfo *
  1291. XGetFileInfo(FID)
  1292. X    t_FID FID;
  1293. X{
  1294. X    t_FileInfo *FileInfo;
  1295. X    datum key, data;
  1296. X    DBM *db;
  1297. X    char Buffer[20];
  1298. X#ifdef NEEDALIGN
  1299. X    t_PhysicalIndexEntry *PIE;
  1300. X#endif
  1301. X
  1302. X    (void) sprintf(Buffer, "F%lu", FID);
  1303. X    key.dptr = Buffer;
  1304. X    key.dsize = strlen(Buffer);
  1305. X
  1306. X    if ((db = startdb(FileIndex)) == (DBM *) 0) {
  1307. X    return (t_FileInfo *) 0;
  1308. X    }
  1309. X
  1310. X    data = dbm_fetch(db, key);
  1311. X    enddb(db);
  1312. X
  1313. X    if (data.dsize == 0) {
  1314. X    return (t_FileInfo *) 0;
  1315. X    }
  1316. X
  1317. X#ifdef NEEDALIGN
  1318. X    PIE = (t_PhysicalIndexEntry *) emalloc(data.dsize + 1);
  1319. X    (void) memcpy((char *) PIE, data.dptr, data.dsize);
  1320. X    FileInfo = Phys2FileInfo(PIE);
  1321. X    (void) efree((char *) PIE);
  1322. X#else
  1323. X
  1324. X    /* Now we have a PIE, so we need a FileInfo... */
  1325. X    FileInfo = Phys2FileInfo(/*NOSTRICT*/(t_PhysicalIndexEntry *) data.dptr);
  1326. X#endif
  1327. X
  1328. X    return FileInfo;
  1329. X}
  1330. X
  1331. Xint
  1332. Xstrcontains(ShortString, LongString)
  1333. X    char *ShortString;
  1334. X    char *LongString;
  1335. X{
  1336. X    register char *p;
  1337. X
  1338. X    int strprefix();
  1339. X
  1340. X    for (p = LongString; *p; p++) {
  1341. X    if (*p == *ShortString && strprefix(ShortString, p)) {
  1342. X        return 1;
  1343. X    }
  1344. X    }
  1345. X    return 0;
  1346. X}
  1347. X
  1348. Xint
  1349. Xstrprefix(Prefix, String)
  1350. X    register char *Prefix;
  1351. X    register char *String;
  1352. X{
  1353. X    while (*String++ == *Prefix++)
  1354. X    if (!*Prefix) return 1;
  1355. X    return 0;
  1356. X}
  1357. @@@End of lq-text/src/liblqtext/FileList.c
  1358. echo x - lq-text/src/liblqtext/FilterType.c 1>&2
  1359. sed 's/^X//' >lq-text/src/liblqtext/FilterType.c <<'@@@End of lq-text/src/liblqtext/FilterType.c'
  1360. X/* FilterType.c -- Copyright 1989 Liam R. Quin.  All Rights Reserved.
  1361. X * This code is NOT in the public domain.
  1362. X * See the file COPYRIGHT for full details.
  1363. X */
  1364. X
  1365. X/* FilterType -- determine how to deal with a given file.
  1366. X * Part of Liam Quin's NX-Text text retrieval package.
  1367. X *
  1368. X * $Id: FilterType.c,v 1.6 90/10/06 00:11:56 lee Rel1-10 $
  1369. X *
  1370. X * $Log:    FilterType.c,v $
  1371. X * Revision 1.6  90/10/06  00:11:56  lee
  1372. X * Prepared for first beta release.
  1373. X * 
  1374. X * Revision 1.5  90/09/24  21:20:31  lee
  1375. X * changed a free() to an efree() -- the last one!
  1376. X * 
  1377. X * Revision 1.4  90/09/20  20:07:35  lee
  1378. X * fixed a tiny memory hole...
  1379. X * 
  1380. X * Revision 1.3  90/08/29  21:46:35  lee
  1381. X * Alpha release.
  1382. X * 
  1383. X * Revision 1.2  90/08/09  19:16:18  lee
  1384. X * BSD lint and fixes...
  1385. X * 
  1386. X * Revision 2.2  89/10/08  20:44:34  lee
  1387. X * Working version of nx-text engine.  Addfile and wordinfo work OK.
  1388. X * 
  1389. X *
  1390. X */
  1391. X
  1392. X#include <stdio.h>
  1393. X#include <malloc.h>
  1394. X#include "emalloc.h"
  1395. X#include <sys/types.h>
  1396. X#include <sys/stat.h>
  1397. X#include <errno.h>
  1398. X#include <fcntl.h>
  1399. X#include <string.h>
  1400. X#include <ctype.h>
  1401. X
  1402. X#include "fileinfo.h"
  1403. X#define FILTERDEF /* see filter.h */
  1404. X#include "filter.h"
  1405. X#include "wordrules.h" /* for min word length -- don't index files shorter */
  1406. X
  1407. X#define Prefix(pref,str) ((*(pref)==(*str))&&!strncmp(pref,str,strlen(pref)))
  1408. X
  1409. Xextern int open(), close();
  1410. Xextern int read();
  1411. Xextern int strcontains();
  1412. X
  1413. X/* The current filter types are:
  1414. X * FTYPE_NEWS  1
  1415. X * FTYPE_MAIL  2
  1416. X * FTYPE_CDMS  3
  1417. X * FTYPE_MOSTLYASCII 4
  1418. X * FTYPE_C_SOURCE 5
  1419. X */
  1420. X
  1421. X/* InitFilterTable might one day be called from Defaults.c....
  1422. X * At which point, it will read an ascii file that describes the
  1423. X * various filters, I suppose.
  1424. X *
  1425. X * For,now, it does nothing.  It is only called once, and should return 0
  1426. X * for success or -1 for failure.
  1427. X */
  1428. Xint
  1429. XInitFilterTable()
  1430. X{
  1431. X    return 0;
  1432. X}
  1433. X
  1434. Xint
  1435. XGetFilterType(FileInfo, StatBuf)
  1436. X    t_FileInfo *FileInfo;
  1437. X    struct stat *StatBuf;
  1438. X{
  1439. X    int Type = MaxFilterType + 1;
  1440. X    char Buffer[1024];
  1441. X    int fd = (-1); /* initialised for lint */
  1442. X    int AmountRead = 0; /* initialised for lint */
  1443. X    int ch;
  1444. X    int Length;
  1445. X    FILE *fp = (FILE *) 0;
  1446. X
  1447. X    /* GetFilterType() is called to determine which input filter (if any)
  1448. X     * should be used to read a given file.
  1449. X     * This routine should know about compressed files.
  1450. X     *
  1451. X     * It currently knows about mail, news and C files.
  1452. X     * There are also hooks for CDMS files (a word-processing package).
  1453. X     *
  1454. X     * If the file should not be indexed at all (e.g. it's a core dump),
  1455. X     * we return -1.
  1456. X     */
  1457. X
  1458. X    if (!FileInfo || !FileInfo->Name || !*(FileInfo->Name)) return (-1);
  1459. X
  1460. X    if (StatBuf->st_size < MinWordLength) return (-1);
  1461. X
  1462. X    Length = strlen(FileInfo->Name);
  1463. X
  1464. X    if (FileInfo->Name[Length - 1] == 'Z' && Length > 2 &&
  1465. X                    FileInfo->Name[Length - 2] == '.') {
  1466. X    char *Buf = emalloc(Length + 10);
  1467. X
  1468. X    (void) sprintf(Buf, "zcat < \"%s\"", FileInfo->Name);
  1469. X
  1470. X    fp = popen(Buf, "r");
  1471. X    (void) efree(Buf);
  1472. X    if (fp == (FILE *) 0) {
  1473. X        return (-1);
  1474. X    }
  1475. X    }
  1476. X
  1477. X    if (fp) {
  1478. X    if ((AmountRead = fread(fp, Buffer, sizeof(Buffer))) < MinWordLength) {
  1479. X        (void) pclose(fp);
  1480. X        fp = (FILE *) 0; /* try again with read() */
  1481. X    }
  1482. X    }
  1483. X
  1484. X    if (!fp) {
  1485. X    if ((fd = open(FileInfo->Name, O_RDONLY, 0)) < 0) {
  1486. X        return -1;
  1487. X    }
  1488. X    if ((AmountRead = read(fd, Buffer, sizeof(Buffer)-1)) < MinWordLength) {
  1489. X        (void) close(fd);
  1490. X        return -1;
  1491. X    }
  1492. X    }
  1493. X    if (fp) {
  1494. X    (void) pclose(fp);
  1495. X    } else {
  1496. X    (void) close(fd);
  1497. X    }
  1498. X
  1499. X    /* Check the magic table for CDMS: */
  1500. X    if ((unsigned char) Buffer[0] == 128 && Buffer[1] == 'M') {
  1501. X    if (AmountRead > 35) { /* size of CDMS file header */
  1502. X        Type = FTYPE_CDMS;
  1503. X        return (FileInfo->FilterType = Type);
  1504. X    }
  1505. X    }
  1506. X     
  1507. X    if (AmountRead < 30) {
  1508. X    register char *p = Buffer;
  1509. X
  1510. X    /* who cares if it's this small? */
  1511. X    for (; p - Buffer < AmountRead; p++) {
  1512. X        if (!isascii(*p)) {
  1513. X        return (-1);
  1514. X        }
  1515. X    }
  1516. X    return 0;
  1517. X    }
  1518. X
  1519. X    /* Not cdms -- try news/mail;
  1520. X     * mail files start with From;
  1521. X     * news starts with From, Path or Relay-Version
  1522. X     */
  1523. X    if (isupper(Buffer[0])) {
  1524. X    Buffer[AmountRead] = '\0';
  1525. X    AmountRead--;
  1526. X    if (Prefix("Xref: ", Buffer)) {
  1527. X        return (FileInfo->FilterType = FTYPE_NEWS);
  1528. X    } else if (Prefix("Newsgroups: ", Buffer)) {
  1529. X        return (FileInfo->FilterType = FTYPE_NEWS);
  1530. X    } else if (Prefix("Relay-Version: ", Buffer)) {
  1531. X        return (FileInfo->FilterType = FTYPE_NEWS);
  1532. X    } else if (Prefix("From", Buffer)) {
  1533. X        if (strcontains("\nPath: ", Buffer)) {
  1534. X        /* bug: should only check header, not body! */
  1535. X        return FTYPE_NEWS;
  1536. X        } else {
  1537. X        return FTYPE_MAIL;
  1538. X        }
  1539. X    } else if (Prefix("Path: ", Buffer)) {
  1540. X        if (strcontains("\nNewsgroups: ", Buffer)) {
  1541. X        return FTYPE_NEWS;
  1542. X        } else {
  1543. X        return FTYPE_MAIL;
  1544. X        }
  1545. X    } else if (Prefix("Return-Path: ", Buffer)) {
  1546. X        return FTYPE_MAIL; /* MH-style mail */
  1547. X    }
  1548. X    }
  1549. X
  1550. X    /* look for C, trying not to get muddled up with shell scripts */
  1551. X    ch = FileInfo->Name[Length - 1];
  1552. X
  1553. X    if ((ch == 'c' || ch == 'h') && (Length > 2) &&
  1554. X                FileInfo->Name[Length - 2] == '.') {
  1555. X    /* We could require one of
  1556. X     * . a comment
  1557. X     * . a #[ ^i]*(include|define|ifn?def|if)[ ^i]+
  1558. X     * . main[ ^i\n]*(
  1559. X     * . a declaration -- int, char, long, unsigned, static
  1560. X     * in the first block of the file.
  1561. X     * Can't be bothered today.
  1562. X     */
  1563. X    if (strcontains("#line", Buffer)) {
  1564. X        return (-1); /* preprocessed already, index the original! */
  1565. X        /* we ought to say why we are not indexing it! */
  1566. X    }
  1567. X
  1568. X    /* we are very predisposed to thinking of this as C... */
  1569. X    if (Prefix("#include", Buffer)        ||
  1570. X        strcontains("/*", Buffer)        ||
  1571. X        strcontains("#define", Buffer)    ||
  1572. X        strcontains("argc", Buffer)        ||
  1573. X        strcontains("()", Buffer)        ||
  1574. X        strcontains("#include", Buffer)) {
  1575. X        return FTYPE_C_SOURCE;
  1576. X    }
  1577. X    }
  1578. X
  1579. X    /* if still not done, choose between Don't Index and Ascii Filter
  1580. X     * (which simply strips non-ascii characters).
  1581. X     */
  1582. X    if (Type >= MaxFilterType) {
  1583. X    register char *p;
  1584. X    int AsciiCount = 0;
  1585. X    int OtherCount = 0;
  1586. X
  1587. X    for (p = Buffer; p - Buffer < AmountRead; p++) {
  1588. X        if (isascii(*p)) AsciiCount++;
  1589. X        else OtherCount++;
  1590. X        if (!*p) {
  1591. X        /* If it has nulls in it, it isn't a normal file,
  1592. X         * and we have no idea what to do with it!
  1593. X         * (if we did know, it would have had a magic number,
  1594. X         * so we wouldn't have got here)
  1595. X         */
  1596. X        Type = (-1);
  1597. X        break;
  1598. X        }
  1599. X        if (Type > 0) {
  1600. X        if (AsciiCount > OtherCount * 5) {
  1601. X            Type = (OtherCount) ? FTYPE_MOSTLYASCII : 0;
  1602. X        } else {
  1603. X            Type = (-1); /* too much garbage */
  1604. X        }
  1605. X        }
  1606. X    }
  1607. X    }
  1608. X
  1609. X    if (Type > MaxFilterType) Type = -1; /* don't index */
  1610. X    return Type;
  1611. X}
  1612. @@@End of lq-text/src/liblqtext/FilterType.c
  1613. echo x - lq-text/src/liblqtext/Makefile 1>&2
  1614. sed 's/^X//' >lq-text/src/liblqtext/Makefile <<'@@@End of lq-text/src/liblqtext/Makefile'
  1615. X# Makefile for LQ-Text, a full text retrieval package by Liam R. Quin
  1616. X#
  1617. X# This Makefile belongs in the src/liblqtext directory.
  1618. X# Note that most of the actual configuration is done in ../Makefile and
  1619. X# in ../h/global.h, and not here.  This file is for representing the
  1620. X# dependancies between source components and specifying the steps
  1621. X# required to build the library $(DESTDIR)/$(TEXTLIB)
  1622. X#
  1623. X# $Id: Makefile,v 1.3 90/10/06 00:06:22 lee Rel1-10 $
  1624. X#
  1625. X# $Log:    Makefile,v $
  1626. X# Revision 1.3  90/10/06  00:06:22  lee
  1627. X# deleted mkdep output.
  1628. X# 
  1629. X# Revision 1.2  90/09/29  23:48:33  lee
  1630. X# does cmp on the right file now...
  1631. X# 
  1632. X# Revision 1.1  90/08/09  19:17:07  lee
  1633. X# Initial revision
  1634. X# 
  1635. X# 
  1636. X#
  1637. X
  1638. XPWD=liblqtext
  1639. X
  1640. XTEXTLIB=liblqtext.a
  1641. XLIAMLIB=liblq.a
  1642. XDESTDIR=../lib
  1643. XRANLIB=ranlib
  1644. XTEXTLINTLIB=llib-llqtext.ln
  1645. XLIAMLINTLIB=llib-llq.ln
  1646. XLINT=lint
  1647. XLINTFLAGS=-a -b -c -h -x 
  1648. X
  1649. XEXTRA=-I../h
  1650. X
  1651. Xall: $(DESTDIR)/$(TEXTLIB) $(DESTDIR)/$(LIAMLIB)
  1652. X
  1653. Xinstall: all
  1654. X
  1655. Xlint: $(DESTDIR)/$(TEXTLINTLIB) $(DESTDIR)/$(LIAMLINTLIB)
  1656. X    -echo The lint libraries are up to date.
  1657. X
  1658. X$(DESTDIR)/$(TEXTLINTLIB): $(TEXTLINTLIB)
  1659. X    mv $(TEXTLINTLIB) $(DESTDIR)/$(TEXTLINTLIB)
  1660. X
  1661. X$(DESTDIR)/$(LIAMLINTLIB): $(LIAMLINTLIB)
  1662. X    mv $(LIAMLINTLIB) $(DESTDIR)/$(LIAMLINTLIB)
  1663. X
  1664. XNDBMCFILES=
  1665. XNDBMOFILES=
  1666. X
  1667. X## keep all of the following consistent: ###################################
  1668. X
  1669. XTEXTOBJS = WordInfo.o DocPath.o Defaults.o FileList.o Phrase.o Root.o \
  1670. X              numbers.o pblock.o smalldb.o system.o FilterType.o \
  1671. X              asciitrace.o $(NDBMOFILES)
  1672. X
  1673. XTEXTSRC = DocPath.c Defaults.c FileList.c Phrase.c Root.c WordInfo.c \
  1674. X              malloc.c numbers.c pblock.c smalldb.c system.c FilterType.c \
  1675. X              asciitrace.c $(NDBMCFILES)
  1676. X
  1677. XLIAMOBJS = malloc.o progname.o cmdname.o
  1678. XLIAMSRC = malloc.c progname.c cmdname.c
  1679. X
  1680. X## end of mutually related stuff  ##########################################
  1681. X
  1682. X$(TEXTLINTLIB): $(TEXTSRC)
  1683. X    $(LINT) -Clqtext $(LINTFLAGS) $(CFLAGS) $(TEXTSRC)
  1684. X
  1685. Xsaber_src:
  1686. X    #cd $(PWD)
  1687. X    #load $(CFLAGS) $(TEXTSRC) $(LIAMSRC)
  1688. X    #cd ..
  1689. X
  1690. Xsaber_obj:
  1691. X    #cd $(PWD)
  1692. X    #load $(CFLAGS) $(TEXTOBJS) $(LIAMOBJS)
  1693. X    #cd ..
  1694. X
  1695. X$(LIAMLINTLIB): $(LIAMSRC)
  1696. X    $(LINT) -Clq $(LINTFLAGS) $(CFLAGS) $(LIAMSRC)
  1697. X
  1698. X$(DESTDIR)/$(TEXTLIB): $(TEXTLIB)
  1699. X    -test -d $(DESTDIR) || mkdir $(DESTDIR)
  1700. X    -test -f $(DESTDIR)/$(TEXTLIB) || cp /dev/null $(DESTDIR)/$(TEXTLIB)
  1701. X    -( cmp $(TEXTLIB) $(DESTDIR)/$(TEXTLIB) || cp $(TEXTLIB) $(DESTDIR) )
  1702. X    -/bin/rm -f $(TEXTLIB)
  1703. X
  1704. X$(DESTDIR)/$(LIAMLIB): $(LIAMLIB)
  1705. X    -test -d $(DESTDIR) || mkdir $(DESTDIR)
  1706. X    -test -f $(DESTDIR)/$(LIAMLIB) || cp /dev/null $(DESTDIR)/$(LIAMLIB)
  1707. X    -( cmp $(LIAMLIB) $(DESTDIR)/$(LIAMLIB) || cp $(LIAMLIB) $(DESTDIR) )
  1708. X    -/bin/rm -f $(LIAMLIB)
  1709. X
  1710. X$(TEXTLIB): $(TEXTOBJS)
  1711. X    rm -f $(TEXTLIB)
  1712. X    ar rv $(TEXTLIB) $(TEXTOBJS)
  1713. X    $(RANLIB) $(TEXTLIB)
  1714. X
  1715. X$(LIAMLIB): $(LIAMOBJS)
  1716. X    rm -f $(LIAMLIB)
  1717. X    ar rv $(LIAMLIB) $(LIAMOBJS)
  1718. X    $(RANLIB) $(LIAMLIB)
  1719. X
  1720. Xtidy:
  1721. X    /bin/rm -f *.o core
  1722. X
  1723. Xclean: tidy
  1724. X    /bin/rm -f $(TARGETS) $(TEST)
  1725. X
  1726. Xdepend:
  1727. X    mkdep $(CFLAGS) *.c
  1728. X
  1729. X# DO NOT DELETE THIS LINE -- mkdep uses it.
  1730. X# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
  1731. X
  1732. X# IF YOU PUT ANYTHING HERE IT WILL GO AWAY
  1733. @@@End of lq-text/src/liblqtext/Makefile
  1734. echo end of part 03
  1735. -- 
  1736. Liam R. E. Quin,  lee@sq.com, SoftQuad Inc., Toronto, +1 (416) 963-8337
  1737.