swish.c
上传用户:qin5330
上传日期:2007-01-05
资源大小:114k
文件大小:16k
源码类别:

搜索引擎

开发平台:

Perl

  1. /*
  2. ** Copyright (C) 1995, 1996, 1997, 1998 Hewlett-Packard Company
  3. ** Originally by Kevin Hughes, kev@kevcom.com, 3/11/94
  4. **
  5. ** This program and library is free software; you can redistribute it and/or
  6. ** modify it under the terms of the GNU (Library) General Public License
  7. ** as published by the Free Software Foundation; either version 2
  8. ** of the License, or any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU (Library) General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU (Library) General Public License
  16. ** along with this program; if not, write to the Free Software
  17. ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18. **---------------------------------------------------------
  19. ** Added support for METADATA
  20. ** G. Hill ghill@library.berkeley.edu 3/18/97
  21. **
  22. ** Added printing of common words
  23. ** G.Hill 4/7/97 ghill@library.berkeley.edu
  24. **
  25. */
  26. #define MAIN_FILE
  27. #include "swish.h"
  28. #include "error.h"
  29. #include "list.h"
  30. #include "search.h"
  31. #include "index.h"
  32. #include "string.h"
  33. #include "file.h"
  34. #include "merge.h"
  35. #include "docprop.h"
  36. /*
  37. ** This array has pointers to all the indexing data source
  38. ** structures
  39. */
  40. extern struct _indexing_data_source_def *data_sources[];
  41. int main(argc, argv)
  42. int argc;
  43. char **argv;
  44. {
  45. char c, word[MAXWORDLEN], wordlist[MAXSTRLEN],
  46. maxhitstr[MAXSTRLEN], structstr[MAXSTRLEN];
  47. char tmpindex1[MAXFILELEN], tmpindex2[MAXFILELEN],
  48. index1[MAXSTRLEN], index2[MAXSTRLEN],
  49. index3[MAXSTRLEN], index4[MAXSTRLEN];
  50. int i, j, hasindex, hasdir, hasconf, hasverbose, structure,
  51. totalfiles, stopwords, index, decode, merge, pos,
  52. hasMetaName;
  53. long offsetstart, starttime, stoptime, plimit, flimit;
  54. FILE *fp1, *fp2;
  55. struct file *filep;
  56. struct entry *entryp;
  57. struct swline *conflist, *tmplist;
  58. index = decode = merge = 0;
  59. hasindex = hasdir = hasconf = hasverbose = hasMetaName = 0;
  60. followsymlinks = stopwords = 0;
  61. totalwords = stopwords = stopPos = 0;
  62. applyStemmingRules = 0; /* added 11/24/98 */
  63. useCustomOutputDelimiter = 0; /* added 11/24/98 */
  64. customOutputDelimiter[0] = ''; /* added 11/24/98 */
  65. ignoreTotalWordCountWhenRanking = 0; /* added 11/24/98 */
  66. filelist = NULL;
  67. entrylist = NULL;
  68. dirlist = indexlist = conflist = tmplist = NULL;
  69. replacelist = NULL;
  70. metaEntryList = NULL;
  71. maxhits = -1;
  72. verbose = VERBOSE;
  73. plimit = PLIMIT;
  74. flimit = FLIMIT;
  75. minwordlimit = MINWORDLIMIT;
  76. maxwordlimit = MAXWORDLIMIT;
  77. indexComments = 1;
  78. nocontentslist = 0;
  79. strcpy(wordchars,WORDCHARS);
  80. strcpy(beginchars,BEGINCHARS);
  81. strcpy(endchars,ENDCHARS);
  82. strcpy(ignorelastchar, IGNORELASTCHAR);
  83. strcpy(ignorefirstchar, IGNOREFIRSTCHAR);
  84. structure = 1;
  85. wordlist[0] = '';
  86. structstr[0] = '';
  87. indexn[0] = '';
  88. indexd[0] = '';
  89. indexp[0] = '';
  90. indexa[0] = '';
  91. setlocale(LC_CTYPE,"");
  92. /* By default we are set up to use the first data source in the list */
  93.   IndexingDataSource = data_sources[0];
  94. if (argc == 1)
  95. usage();
  96. while (--argc > 0) 
  97. {
  98. ++argv;
  99. if ((*argv)[0] != '-')
  100. usage();
  101. c = (*argv)[1];
  102. if ((*argv)[2] != '' && isalpha((*argv)[2]))
  103. usage();
  104. if (c == 'i') 
  105. {
  106. index = 1;
  107. while ((argv + 1)[0] != '' && *(argv + 1)[0] != '-') {
  108. dirlist = (struct swline *)
  109. addswline(dirlist, (++argv)[0]);
  110. argc--;
  111. }
  112. }
  113. else if (c == 'w') 
  114. {
  115. while ((argv + 1)[0] != '' && *(argv + 1)[0] != '-') 
  116. {
  117. strcpy(word, (++argv)[0]);
  118. argc--;
  119. sprintf(wordlist, "%s%s%s", wordlist,
  120. (wordlist[0] == '') ? "" : " ", word);
  121. }
  122. }
  123. else if (c == 'S')
  124. {
  125.   struct _indexing_data_source_def **data_source;
  126.   const char* opt = (++argv)[0];
  127.   argc--;
  128.   for (data_source = data_sources; *data_source != 0; data_source++ )
  129.     {
  130.       if (strcmp(opt, (*data_source)->IndexingDataSourceId) == 0)
  131. {
  132.   break;
  133. }
  134.     }
  135.   
  136.   if (!*data_source)
  137.     {
  138.       sprintf(errorstr, "Unknown -S option "%s"", opt);
  139.       progerr(errorstr);
  140.     }
  141.   else
  142.     {
  143.       IndexingDataSource = *data_source;
  144.     }  
  145. }
  146. #ifdef SUPPORT_DOC_PROPERTIES
  147. else if (c == 'p') {
  148.   /* -p <property_to_display> [<property_to_display>]* */
  149.   while ((argv + 1)[0] != '' && *(argv + 1)[0] != '-') 
  150. {
  151. addSearchResultDisplayProperty((++argv)[0]);
  152. argc--;
  153. }
  154. }
  155. #endif
  156. else if (c == 'f') 
  157. {
  158. while ((argv + 1)[0] != '' && *(argv + 1)[0] != '-') 
  159. {
  160. indexlist = (struct swline *)
  161. addswline(indexlist, (++argv)[0]);
  162. argc--;
  163. }
  164. }
  165. else if (c == 'c') 
  166. {
  167. index = 1;
  168. hasconf = 1;
  169. while ((argv + 1)[0] != '' && *(argv + 1)[0] != '-') {
  170. conflist = (struct swline *)
  171. addswline(conflist, (++argv)[0]);
  172. argc--;
  173. }
  174. }
  175. else if (c == 'C') {
  176. while ((argv + 1)[0] != '' && *(argv + 1)[0] != '-')
  177. {
  178. conflist = (struct swline *)
  179. addswline(conflist, (++argv)[0]);
  180. argc--;
  181. }
  182. if (conflist == NULL)
  183. progerr("Specifiy the configuration file.");
  184. else
  185. hasMetaName = 1;
  186.       }
  187. else if (c == 'l') {
  188. followsymlinks = 1;
  189. argc--;
  190. }
  191. else if (c == 'm') {
  192. if ((argv + 1)[0] == '')
  193. maxhits = -1;
  194. else {
  195. strcpy(maxhitstr, (++argv)[0]);
  196. if (lstrstr(maxhitstr, "all"))
  197. maxhits = -1;
  198. else if (isdigit(maxhitstr[0]))
  199. maxhits = atoi(maxhitstr);
  200. else
  201. maxhits = -1;
  202. argc--;
  203. }
  204. }
  205. else if (c == 't') {
  206. if ((argv + 1)[0] == '')
  207. progerr("Specify tag fields (HBtheca).");
  208. else {
  209. structure = 0;
  210. strcpy(structstr, (++argv)[0]);
  211. argc--;
  212. }
  213. }
  214. else if (c == 'v') {
  215. hasverbose = 1;
  216. if ((argv + 1)[0] == '') {
  217. verbose = 3;
  218. break;
  219. }
  220. else if (!isdigit((argv + 1)[0][0]))
  221. verbose = 3;
  222. else
  223. verbose = atoi((++argv)[0]);
  224. argc--;
  225. }
  226. else if (c == 'V')
  227. printversion();
  228. else if (c == 'z' || c == 'h' || c == '?')
  229. usage();
  230. else if (c == 'M') {
  231. merge = 1;
  232. while ((argv + 1)[0] != '' && *(argv + 1)[0] != '-') {
  233. indexlist = (struct swline *)
  234. addswline(indexlist, (++argv)[0]);
  235. argc--;
  236. }
  237. }
  238. else if (c == 'D') {
  239. decode = 1;
  240. while ((argv + 1)[0] != '' && *(argv + 1)[0] != '-') {
  241. indexlist = (struct swline *)
  242. addswline(indexlist, (++argv)[0]);
  243. argc--;
  244. }
  245. }
  246. else if (c == 'd')
  247. {
  248. /* added 11/24/98 MG */
  249. if (((argv + 1)[0] != '') && (*(argv + 1)[0] != '-'))
  250. {
  251. useCustomOutputDelimiter = 1;
  252. strcpy(customOutputDelimiter, (++argv)[0]);
  253. if (strcmp(customOutputDelimiter, "dq") == 0)
  254. strcpy(customOutputDelimiter, """); /* double quote is cool */
  255. argc--;
  256. }
  257. }
  258. else
  259. usage();
  260. if (argc == 0)
  261. break;
  262. }
  263. hasdir = (dirlist == NULL) ? 0 : 1;
  264. hasindex = (indexlist == NULL) ? 0 : 1;
  265. if (index && merge)
  266. index = 0;
  267. if (decode) {
  268. if (!hasindex)
  269. progerr("Specify the index file to decode.");
  270. while (indexlist != NULL) {
  271. if ((fp1 = openIndexFileForRead(indexlist->line)) == NULL) {
  272. sprintf(errorstr,
  273. "Couldn't open the index file "%s".",
  274. indexlist->line);
  275. progerr(errorstr);
  276. }
  277. if (!isokindexheader(fp1)) {
  278. sprintf(errorstr,
  279. ""%s" has an unknown format.",
  280. indexlist->line);
  281. progerr(errorstr);
  282. }
  283. decompress(fp1);
  284. putchar('n');
  285. fclose(fp1);
  286. indexlist = indexlist->next;
  287. }
  288. exit(0);
  289. }
  290. else if (index) 
  291. {
  292. printf("Indexing Data Source: "%s"n", IndexingDataSource->IndexingDataSourceName);
  293. if (hasconf)
  294. {
  295. while (conflist != NULL) {
  296. getdefaults(conflist->line, &hasdir, &hasindex,
  297. &plimit, &flimit, hasverbose);
  298. conflist = conflist->next;
  299. }
  300. }
  301. if (!hasindex)
  302. indexlist = (struct swline *) addswline(indexlist, INDEXFILE);
  303. if (!hasdir)
  304. progerr("Specify directories or files to index.");
  305. if (verbose < 0)
  306. verbose = 0;
  307. if (verbose > 4)
  308. verbose = 4;
  309. if (verbose)
  310. starttime = getthetime();
  311. while (dirlist != NULL) {
  312. indexpath(dirlist->line);
  313. dirlist = dirlist->next;
  314. }
  315. if ((fp1 = openIndexFileForWrite(indexlist->line)) == NULL) {
  316. sprintf(errorstr,
  317. "Couldn't write the index file "%s".",
  318. indexlist->line);
  319. progerr(errorstr);
  320. }
  321. if (verbose > 1)
  322. putchar('n');
  323. if (verbose)
  324. printf("Removing very common words... ");
  325. filep = filelist;
  326. totalfiles = getfilecount(filep);
  327. entryp = entrylist;
  328. stopwords = removestops(entryp, totalfiles, plimit, flimit);
  329. if (verbose) {
  330. if (stopwords) {
  331. printf("%d word%s removed.n",
  332. stopwords, (stopwords == 1) ? "" : "s");
  333. printf("%d words removed not in common words array:n",
  334. stopPos);
  335. for (pos = 0; pos < stopPos; pos++) 
  336. printf("%s, ", stopList[pos]);
  337. printf("n");
  338. }
  339. else
  340. printf("no words removed.n");
  341. printf("Writing main index... ");
  342. }
  343. printheader(fp1, indexlist->line, totalwords, totalfiles, 0);
  344. offsetstart = ftell(fp1);
  345. for (i = 0; i < MAXCHARS; i++)
  346. fprintf(fp1, "%016li", offsets[i]);
  347. fputc('n', fp1);
  348. printindex(entrylist, fp1);
  349. printstopwords(fp1);
  350. if (verbose) {
  351. if (totalwords)
  352. printf("%d unique word%s indexed.n",
  353. totalwords, (totalwords == 1) ? "" : "s");
  354. else
  355. printf("no unique words indexed.n");
  356. printf("Writing file index... ");
  357. }
  358. printfilelist(filelist, fp1);
  359. printfileoffsets(fp1);
  360. printMetaNames(fp1);
  361. fclose(fp1);
  362. fp2 = openIndexFileForReadAndWrite(indexlist->line);
  363. fseek(fp2, offsetstart, 0);
  364. for (i = 0; i < MAXCHARS; i++)
  365. fprintf(fp2, "%016li", offsets[i]);
  366. fclose(fp2);
  367. if (verbose) 
  368. {
  369. if (totalfiles)
  370. printf("%d file%s indexed.n", totalfiles,
  371. (totalfiles == 1) ? "" : "s");
  372. else
  373. printf("no files indexed.n");
  374. stoptime = getthetime();
  375. printrunning(starttime, stoptime);
  376. printf("Indexing done!n");
  377. }
  378. #ifdef INDEXPERMS
  379. chmod(indexlist->line, INDEXPERMS);
  380. #endif
  381. exit(0);
  382. }
  383. else if (merge) 
  384. {
  385. if (indexlist == NULL)
  386. progerr("Specify index files and an output file.");
  387. if (hasconf)
  388. {
  389. while (conflist != NULL) 
  390. {
  391. getdefaults(conflist->line, &hasdir, &hasindex,
  392. &plimit, &flimit, hasverbose);
  393. conflist = conflist->next;
  394. }
  395. }
  396. tmplist = indexlist;
  397. for (i = 0; tmplist != NULL; i++) {
  398. strcpy(index4, tmplist->line);
  399. tmplist = tmplist->next;
  400. }
  401. j = i - 2;
  402. if (i < 3)
  403. progerr("Specify index files and an output file.");
  404. sprintf(tmpindex1, tmpnam(NULL));
  405. sprintf(tmpindex2, tmpnam(NULL));
  406. i = 1;
  407. strcpy(index1, indexlist->line);
  408. indexlist = indexlist->next;
  409. while (i <= j) {
  410. strcpy(index2, indexlist->line);
  411. if (i % 2) {
  412. if (i != 1)
  413. strcpy(index1, tmpindex2);
  414. strcpy(index3, tmpindex1);
  415. }
  416. else {
  417. strcpy(index1, tmpindex1);
  418. strcpy(index3, tmpindex2);
  419. }
  420. if (i == j)
  421. strcpy(index3, index4);
  422. readmerge(index1, index2, index3);
  423. indexlist = indexlist->next;
  424. i++;
  425. }
  426. #ifdef INDEXPERMS
  427. chmod(index3, INDEXPERMS);
  428. #endif
  429. if (isfile(tmpindex1))
  430. remove(tmpindex1);
  431. if (isfile(tmpindex2))
  432. remove(tmpindex2);
  433. }
  434. else 
  435. {
  436. for (i = 0; structstr[i] != ''; i++)
  437. {
  438. switch (structstr[i]) 
  439. {
  440. case 'H':
  441. structure |= IN_HEAD;
  442. break;
  443. case 'B':
  444. structure |= IN_BODY;
  445. break;
  446. case 't':
  447. structure |= IN_TITLE;
  448. break;
  449. case 'h':
  450. structure |= IN_HEADER;
  451. break;
  452. case 'e':
  453. structure |= IN_EMPHASIZED;
  454. break;
  455. case 'c':
  456. structure |= IN_COMMENTS;
  457. break;
  458. default:
  459. structure |= IN_FILE;
  460. break;
  461. }
  462. }
  463. if (maxhits <= 0)
  464. maxhits = -1;
  465. if (!hasindex)
  466. indexlist = (struct swline *)
  467. addswline(indexlist, INDEXFILE);
  468. if (hasMetaName)
  469. while (conflist != NULL) {
  470. getdefaults(conflist->line, &hasdir, &hasindex,
  471. &plimit, &flimit, hasverbose);
  472. conflist = conflist->next;
  473. }
  474. search(wordlist, indexlist, structure);
  475. }
  476. exit(0);
  477. return 0;
  478. }
  479. /* Gets the current time in seconds since the epoch.
  480. */
  481. long getthetime()
  482. {
  483. long thetime;
  484. time_t tp;
  485. thetime = (long) time(&tp);
  486. return thetime;
  487. }
  488. /* Prints the running time (the time it took for indexing).
  489. */
  490. void printrunning(starttime, stoptime)
  491.      long starttime;
  492.      long stoptime;
  493. {
  494. int minutes, seconds;
  495. minutes = (stoptime - starttime) / SECSPERMIN;
  496. seconds = (stoptime - starttime) % SECSPERMIN;
  497. printf("Running time: ");
  498. if (minutes)
  499. printf("%d minute%s", minutes, (minutes == 1) ? "" : "s");
  500. if (minutes && seconds)
  501. printf(", ");
  502. if (seconds)
  503. printf("%d second%s", seconds, (seconds == 1) ? "" : "s");
  504. if (!minutes && !seconds)
  505. printf("Less than a second");
  506. printf(".n");
  507. }
  508. /* Prints the SWISH usage.
  509. */
  510. void usage()
  511. {
  512. const char* defaultIndexingSystem = "";
  513. printf("  usage: swish [-i dir file ... ] [-S system] [-c file] [-f file] [-l] [-v (num)]n");
  514. printf("         swish -w word1 word2 ... [-f file1 file2 ...] [-p prop1 ...] [-m num] [-t str] [-d delim]n");
  515. printf("         swish -M index1 index2 ... outputfilen");
  516. printf("         swish -D filen");
  517. printf("         swish -Vn");
  518. putchar('n');
  519. printf("options: defaults are in bracketsn");
  520. printf("         -S : specify which indexing system to use.n");
  521. printf("              Valid options are:n");
  522. #ifdef ALLOW_FILESYSTEM_INDEXING_DATA_SOURCE
  523. printf("              "fs" - index local files in your File Systemn");
  524. if (!*defaultIndexingSystem)
  525. defaultIndexingSystem = "fs";
  526. #endif
  527. #ifdef ALLOW_HTTP_INDEXING_DATA_SOURCE
  528. printf("              "http" - index web site files using a web crawlern");
  529. if (!*defaultIndexingSystem)
  530. defaultIndexingSystem = "http";
  531. #endif
  532. printf("              The default value is: "%s"n", defaultIndexingSystem);
  533. printf("         -i : create an index from the specified filesn");
  534. printf("         -w : search for words "word1 word2 ..."n");
  535. printf("         -t : tags to search in - specify as a stringn");
  536. printf("              "HBthec" - in head, body, title, header,n");
  537. printf("              emphasized, commentsn");
  538. printf("         -f : index file to create or search from [%s]n", INDEXFILE);
  539. printf("         -c : configuration file to use for indexingn");
  540. printf("         -v : verbosity level (0 to 3) [%d]n", VERBOSE);
  541. printf("         -l : follow symbolic links when indexingn");
  542. printf("         -m : the maximum number of results to return [%d]n", MAXHITS);
  543. printf("         -M : merges index filesn");
  544. printf("         -D : decodes an index filen");
  545. #ifdef SUPPORT_DOC_PROPERTIES
  546. printf("         -p : include these document properties in the output "prop1 prop2 ..."n");
  547. #endif
  548. printf("         -d : next param is delimiter. use "-d dq" to use a double quoten");
  549. printf("         -V : prints the current versionnn");
  550. printf("version: %sn", VERSION);
  551. printf("   docs: http://sunsite.berkeley.edu/SWISH-E/n");
  552. exit(1);
  553. }
  554. void printversion()
  555. {
  556. printf("SWISH-E %sn", VERSION);
  557. exit(0);
  558. }
  559. /*
  560.  * Binary files must be open with the "b" option under Win32, so all
  561.  * fopen() calls to index files have to go through these routines to 
  562.  * keep the code portable. 
  563.  * Note: text files should be opened normally, without the "b" option,
  564.  * otherwise end-of-line processing is not done correctly (on Win32).
  565.  */
  566. #ifdef _WIN32
  567. #define FILEMODE_READ "rb"
  568. #define FILEMODE_WRITE "wb"
  569. #define FILEMODE_READWRITE "rb+"
  570. #else
  571. #define FILEMODE_READ "r"
  572. #define FILEMODE_WRITE "w"
  573. #define FILEMODE_READWRITE "r+"
  574. #endif
  575. FILE* openIndexFileForWrite(filename)
  576. char* filename;
  577. {
  578. return fopen(filename, FILEMODE_WRITE);
  579. }
  580. FILE* openIndexFileForRead(filename)
  581. char* filename;
  582. {
  583. return fopen(filename, FILEMODE_READ);
  584. }
  585. FILE* openIndexFileForReadAndWrite(filename)
  586. char* filename;
  587. {
  588. return fopen(filename, FILEMODE_READWRITE);
  589. }
  590. /*
  591.  * Invoke the methods of the current Indexing Data Source
  592.  */
  593. void indexpath(path)
  594. char *path;
  595. {
  596. /* invoke routine to index a "path" */
  597. (*IndexingDataSource->indexpath_fn)(path);
  598. }
  599. int vgetc(vp)
  600. void *vp;
  601. {
  602. /* invoke routine to get char from "file" */
  603. return (*IndexingDataSource->vgetc_fn)(vp);
  604. }
  605. int vsize(vp)
  606. void *vp;
  607. {
  608. /* invoke routine to get size of "file" */
  609. return (*IndexingDataSource->vsize_fn)(vp);
  610. }
  611. int parseconfline(line)
  612. char *line;
  613. {
  614. /* invoke routine to parse config file lines */
  615. return (*IndexingDataSource->parseconfline_fn)(line);
  616. }