ocf.c 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  6. * These libraries and programs are free software; you can
  7. * redistribute them and/or modify them under the terms of the GNU
  8. * Lesser General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * These libraries and programs are distributed in the hope that
  13. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. * PURPOSE. See the GNU Lesser General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these libraries and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. /*
  24. * COMPONENT_NAME: austext
  25. *
  26. * FUNCTIONS: add_a_keytype
  27. * dumpboth
  28. * dumpoef
  29. * load_ocf
  30. * obsolete_keyword
  31. * ocfopen
  32. * parse_boolean
  33. * read_database
  34. * read_filepath
  35. * read_keytypes
  36. * read_maxhits
  37. * read_path
  38. * read_rest_of_line
  39. * set_boolbit
  40. * set_boolint
  41. * set_fileio
  42. * set_int
  43. * set_long
  44. *
  45. * ORIGINS: 27
  46. *
  47. * (C) COPYRIGHT International Business Machines Corp. 1991,1995
  48. * All Rights Reserved
  49. * US Government Users Restricted Rights - Use, duplication or
  50. * disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  51. */
  52. /*************************** OCF.C ***************************
  53. * $TOG: ocf.c /main/9 1998/04/17 11:26:02 mgreess $
  54. * August 1991.
  55. * Load_ocf() reads an engine's "site configuration file" (.ocf),
  56. * parses its contents, and returns a ptr to a list of
  57. * DBLKs containing the file's info.
  58. * Returns TRUE if .ocf file format is acceptable and everything worked.
  59. * Returns FALSE if file contains fatal errors. If file is ok, also
  60. * returns a list of dblks in global usrblk and sets some global variables.
  61. * The name and path of config file can be specified
  62. * or generated in a number of convenient ways.
  63. * The theory is: as many options as possible are in the config file
  64. * rather than command lines, etc.
  65. * Note: User configuration files are no longer supported.
  66. *
  67. * $Log$
  68. * Revision 2.6 1996/03/05 21:12:01 miker
  69. * Reversed meaning of ascii_charmap test.
  70. *
  71. * Revision 2.5 1996/03/05 18:02:46 miker
  72. * Repl ctype functions with refs to ascii_charmap and COMMENT_CHARS.
  73. *
  74. * Revision 2.4 1996/02/05 16:34:57 miker
  75. * Silently try old file name when looking for site config file.
  76. *
  77. * Revision 2.3 1995/10/25 15:39:33 miker
  78. * Added prolog.
  79. *
  80. * Revision 2.2 1995/10/03 21:40:15 miker
  81. * Cosmetic msg change only.
  82. *
  83. * Revision 2.1 1995/09/22 21:30:12 miker
  84. * Freeze DtSearch 0.1, AusText 2.1.8
  85. *
  86. * Revision 1.3 1995/09/05 21:41:59 miker
  87. * Changed environment variable OCFPATH to DTSROCFPATH.
  88. *
  89. * Revision 1.2 1995/09/05 18:46:13 miker
  90. * Moved all documentation to ocf.doc.
  91. *
  92. * Revision 1.1 1995/08/31 21:07:25 miker
  93. * Initial revision (renamed ocf.c from loadocf.c).
  94. *
  95. * *Log: loadocf.c,v *
  96. * Revision 1.19 1995/07/19 21:12:34 miker
  97. * 2.1.6c: Cleaned up documentation to match actual current capabilities.
  98. * Obsoleted MAILFEATURE and PRINTSERVER keywords.
  99. *
  100. * Revision 1.18 1995/07/18 22:52:17 miker
  101. * Added ability to open prespecified OE_sitecnfg_fname.
  102. */
  103. #include "SearchE.h"
  104. #include <ctype.h>
  105. #include <stdlib.h>
  106. #define X_INCLUDE_STRING_H
  107. #define XOS_USE_NO_LOCKING
  108. #include <X11/Xos_r.h>
  109. #include <errno.h>
  110. #include <unistd.h> /* for POSIX getcwd() */
  111. #include <sys/stat.h>
  112. char *strupr (char *s);
  113. /*****#define DEBUG_DUMP******/
  114. /********#define DEBUG_OEF**********/
  115. #define PROGNAME "OCF"
  116. #define DELIMITERS " =,\t\n"
  117. #define NEGLOGHALF (-.69314718F) /* negative natural log of .5 */
  118. #define FNAME_SITECONFIG_OLD "austext.ocf"
  119. #define MS_misc 1
  120. #define MS_loadocf 8
  121. /*-------------------- STATIC GLOBALS ----------------------*/
  122. static DBLK *db; /* curr database/dict */
  123. static char *cfgfname;
  124. static char *sprintbufp;
  125. static char *token;
  126. static int fatal_error;
  127. static int debug_ocf = FALSE;
  128. /*-------------------- ENGINE GLOBALS ----------------------
  129. * These are globals which must be accessed by both sides.
  130. * Globals unique to the engine are in oe.c.
  131. */
  132. char *OE_server_dir = NULL;
  133. char *OE_inittab_dir = NULL;
  134. /*-------------------- OEF TABLE ----------------------*/
  135. /*** (struct typdef located in oe.h)
  136. {
  137. char *id; keyword identifier
  138. char **OEFptr; addr of variable to change
  139. char previously_specified; bool ensures only one spec
  140. } OEFTAB;
  141. ********/
  142. OEFTAB oef_table[] =
  143. {
  144. { "AUDIT", &OEF_audit, FALSE, },
  145. { "DISCARD", &OEF_discard, FALSE, },
  146. { "NEWS", &OEF_news, FALSE, },
  147. { "NOTESNOT", &OEF_notesnot, FALSE, },
  148. { "NOTESSEM", &OEF_notessem, FALSE, },
  149. { "README", &OEF_readme, FALSE, },
  150. { NULL, NULL, FALSE }, /* end of list */
  151. };
  152. #ifdef DEBUG_DUMP /* for debugging only */
  153. /****************************************/
  154. /* */
  155. /* dumpboth */
  156. /* */
  157. /****************************************/
  158. static void dumpboth (void)
  159. {
  160. char typestring[4 * MAX_KTCOUNT + 2];
  161. int i;
  162. char *ptr;
  163. LLIST *m;
  164. DBLK *d;
  165. printf ("\nDUMPBOTH> fatal_error=%d, msglist=%p, dblist=%p\n",
  166. fatal_error, ausapi_msglist, usrblk.dblist);
  167. printf ("%s\n", DtSrGetMessages ());
  168. DtSrFreeMessages ();
  169. for (d = usrblk.dblist; d != NULL; d = d->link) {
  170. ptr = typestring;
  171. for (i = 0; i < d->ktcount; i++) {
  172. *ptr++ = (d->keytypes[i].is_selected) ? '*' : ' ';
  173. *ptr++ = d->keytypes[i].ktchar;
  174. *ptr++ = ' ';
  175. }
  176. *ptr = 0;
  177. printf ("DBLK at %p link=%p name='%s' max=%d\n"
  178. " keytypes='%s', path='%s'\n",
  179. d, d->link, d->name, d->maxhits,
  180. typestring, NULLORSTR (d->path));
  181. }
  182. printf ("Push any key to continue...");
  183. *typestring = '\0';
  184. fgets (typestring, sizeof(typestring), stdin);
  185. if (strlen(typestring) && typestring[strlen(typestring)-1] == '\n')
  186. typestring[strlen(typestring)-1] = '\0';
  187. printf ("\n\n\n");
  188. return;
  189. } /* dumpboth() */
  190. #endif
  191. #ifdef DEBUG_OEF /* for debugging only */
  192. /****************************************/
  193. /* */
  194. /* dumpoef */
  195. /* */
  196. /****************************************/
  197. static void dumpoef (char *before_after)
  198. {
  199. OEFTAB *oef;
  200. fprintf (aa_stderr,
  201. "\toef_table[] %s (* = changed strings)\n",
  202. before_after);
  203. for (oef = oef_table; oef->id != NULL; oef++) {
  204. fprintf (aa_stderr, "\t%10s = %c'%s'\n",
  205. oef->id,
  206. (oef->previously_specified) ? '*' : ' ',
  207. *(oef->OEFptr));
  208. }
  209. fputc ('\n', aa_stderr);
  210. return;
  211. } /* dumpoef() */
  212. #endif
  213. /****************************************/
  214. /* */
  215. /* parse_boolean */
  216. /* */
  217. /****************************************/
  218. /* Forces token to upper case.
  219. * Returns +1 for TRUE, -1 for FALSE, and 0 for neither.
  220. */
  221. static int parse_boolean (char *token)
  222. {
  223. /* Completely missing token defaults to affirmative */
  224. if (token == NULL)
  225. return +1;
  226. strupr (token);
  227. switch (token[0]) {
  228. case 'O': /* on, off */
  229. if (token[1] == 'N')
  230. return +1;
  231. else if (token[1] == 'F')
  232. return -1;
  233. else
  234. return 0;
  235. case 'T': /* true */
  236. case 'Y': /* yes */
  237. case 'E': /* enabled */
  238. case '1': /* (one) */
  239. return +1;
  240. case 'F': /* false */
  241. case 'N': /* no */
  242. case 'D': /* disabled */
  243. case '0': /* (zero) */
  244. return -1;
  245. default:
  246. return 0;
  247. }
  248. } /* parse_boolean() */
  249. /****************************************/
  250. /* */
  251. /* read_database */
  252. /* */
  253. /****************************************/
  254. /* Validates next token as database name.
  255. * If not valid name, returns FALSE.
  256. * Otherwise chains down through the database list
  257. * looking for the one whose name matches the token.
  258. * If a match is found, sets db to it, returns TRUE.
  259. * If no match is found, creates and initializes
  260. * new structure, sets db to it, returns TRUE.
  261. */
  262. static int read_database (char *keyword, _Xstrtokparams *strtok_buf)
  263. {
  264. DBLK **linkptr;
  265. if ((token = _XStrtok(NULL, DELIMITERS, *strtok_buf)) == NULL) {
  266. sprintf (sprintbufp,
  267. CATGETS(dtsearch_catd, MS_loadocf, 477,
  268. "%s %s: Missing database name after '%s' keyword.\n"),
  269. PROGNAME"477", cfgfname, keyword);
  270. DtSearchAddMessage (sprintbufp);
  271. fatal_error = TRUE;
  272. return FALSE;
  273. }
  274. if (strlen (token) > 8) {
  275. sprintf (sprintbufp,
  276. CATGETS(dtsearch_catd, MS_loadocf, 184,
  277. "%s %s: More than 8 characters in Database name '%.16s'.\n"),
  278. PROGNAME"184", cfgfname, token);
  279. DtSearchAddMessage (sprintbufp);
  280. fatal_error = TRUE;
  281. return FALSE;
  282. }
  283. /* Chain down the list looking for previously defined database structure */
  284. linkptr = &usrblk.dblist;
  285. for (db = usrblk.dblist; db != NULL; db = db->link) {
  286. if (strcmp (db->name, token) == 0)
  287. return TRUE;
  288. linkptr = &db->link;
  289. }
  290. /* Didn't find matching dblk so allocate and initialize new one at
  291. * end of list (linkptr). Use system defaults for most values.
  292. */
  293. if (debug_ocf)
  294. fprintf (aa_stderr, PROGNAME "204 "
  295. "%s: creating dblk for '%s'\n", cfgfname, token);
  296. db = austext_malloc (sizeof (DBLK) + 8, PROGNAME "205", NULL);
  297. memset (db, 0, sizeof (DBLK));
  298. strcpy (db->name, token);
  299. db->is_selected = TRUE;
  300. *linkptr = db;
  301. return TRUE;
  302. } /* read_database() */
  303. /****************************************/
  304. /* */
  305. /* set_boolbit */
  306. /* */
  307. /****************************************/
  308. static void set_boolbit (long *flagvar, long mask, char *flagname,
  309. _Xstrtokparams *strtok_buf)
  310. {
  311. int i;
  312. token = _XStrtok(NULL, DELIMITERS, *strtok_buf);
  313. i = parse_boolean (token);
  314. if (i > 0)
  315. *flagvar |= mask; /* switch ON */
  316. else if (i < 0)
  317. *flagvar &= ~mask; /* switch OFF */
  318. else {
  319. sprintf (sprintbufp,
  320. CATGETS(dtsearch_catd, MS_loadocf, 352,
  321. "%s %s: Invalid %s value, line ignored.\n"),
  322. PROGNAME"352", cfgfname, flagname);
  323. DtSearchAddMessage (sprintbufp);
  324. }
  325. return;
  326. } /* set_boolbit() */
  327. /****************************************/
  328. /* */
  329. /* set_int */
  330. /* */
  331. /****************************************/
  332. static void set_int (int *intvar, char *keyword, _Xstrtokparams *strtok_buf)
  333. {
  334. int myint;
  335. if ((token = _XStrtok(NULL, DELIMITERS, *strtok_buf)) == NULL) {
  336. token = CATGETS(dtsearch_catd, MS_loadocf, 140, "(missing)");
  337. ERR_MSG:
  338. sprintf (sprintbufp, CATGETS(dtsearch_catd, MS_loadocf, 610,
  339. "%s %s: %s value is '%s'. "
  340. "Should be positive integer. Line ignored."),
  341. PROGNAME"844", cfgfname, keyword, token);
  342. DtSearchAddMessage (sprintbufp);
  343. return;
  344. }
  345. if ((myint = atoi (token)) <= 0L)
  346. goto ERR_MSG;
  347. *intvar = myint;
  348. return;
  349. } /* set_int() */
  350. /****************************************/
  351. /* */
  352. /* set_long */
  353. /* */
  354. /****************************************/
  355. static void set_long (long *longvar, char *keyword,
  356. _Xstrtokparams *strtok_buf)
  357. {
  358. long longi;
  359. if ((token = _XStrtok(NULL, DELIMITERS, *strtok_buf)) == NULL) {
  360. token = CATGETS(dtsearch_catd, MS_loadocf, 140, "(missing)");
  361. ERR_MSG:
  362. sprintf (sprintbufp, CATGETS(dtsearch_catd, MS_loadocf, 610,
  363. "%s %s: %s value is '%s'. "
  364. "Should be positive integer. Line ignored."),
  365. PROGNAME"610", cfgfname, keyword, token);
  366. DtSearchAddMessage (sprintbufp);
  367. return;
  368. }
  369. if ((longi = atol (token)) <= 0L)
  370. goto ERR_MSG;
  371. *longvar = longi;
  372. return;
  373. } /* set_long() */
  374. /****************************************/
  375. /* */
  376. /* set_boolint */
  377. /* */
  378. /****************************************/
  379. static void set_boolint (int *boolint, char *keyword,
  380. _Xstrtokparams *strtok_buf)
  381. {
  382. int i;
  383. token = _XStrtok(NULL, DELIMITERS, *strtok_buf);
  384. i = parse_boolean (token);
  385. if (i > 0)
  386. *boolint = TRUE; /* switch ON */
  387. else if (i < 0)
  388. *boolint = FALSE; /* switch OFF */
  389. else {
  390. sprintf (sprintbufp,
  391. CATGETS(dtsearch_catd, MS_loadocf, 352,
  392. "%s %s: Invalid %s value, line ignored.\n"),
  393. PROGNAME"352", cfgfname, keyword);
  394. DtSearchAddMessage (sprintbufp);
  395. }
  396. return;
  397. } /* set_boolint() */
  398. /****************************************/
  399. /* */
  400. /* set_fileio */
  401. /* */
  402. /****************************************/
  403. /* sets OE_fileio string pointer */
  404. static void set_fileio (_Xstrtokparams *strtok_buf)
  405. {
  406. /* if a value is missing, presume -ON */
  407. if ((token = _XStrtok(NULL, DELIMITERS, *strtok_buf)) == NULL) {
  408. OE_fileio = "-ON";
  409. return;
  410. }
  411. /* check for hardcoded path name (anything that doesn't begin with '-') */
  412. if (token[0] != '-') {
  413. OE_fileio = austext_malloc (strlen (token) + 2, PROGNAME "592", NULL);
  414. strcpy (OE_fileio, token);
  415. return;
  416. }
  417. strupr (token);
  418. if (strcmp (token, "-ON") == 0)
  419. OE_fileio = "-ON";
  420. else if (strcmp (token, "-OFF") == 0)
  421. OE_fileio = "-OFF";
  422. else if (strcmp (token, "-HOME") == 0)
  423. OE_fileio = "-HOME";
  424. else {
  425. sprintf (sprintbufp, CATGETS(dtsearch_catd, MS_loadocf, 607,
  426. "%s %s: Invalid FILEIO value. "
  427. "User file reads and writes prohibited."),
  428. PROGNAME"607", cfgfname);
  429. DtSearchAddMessage (sprintbufp);
  430. OE_fileio = "-OFF";
  431. }
  432. return;
  433. } /* set_fileio() */
  434. /****************************************/
  435. /* */
  436. /* read_rest_of_line */
  437. /* */
  438. /****************************************/
  439. /* Malloc a copy of the rest of the input line after
  440. * the current token and set passed string ptr to it.
  441. */
  442. static void read_rest_of_line (char *keyword, char **passed_ptr,
  443. _Xstrtokparams *strtok_buf)
  444. {
  445. if ((token = _XStrtok(NULL, "\n", *strtok_buf)) == NULL) {
  446. sprintf (sprintbufp, CATGETS(dtsearch_catd, MS_loadocf, 1007,
  447. "%s%s: Empty %s string ignored."),
  448. PROGNAME"1007 ", cfgfname, keyword);
  449. DtSearchAddMessage (sprintbufp);
  450. return;
  451. }
  452. *passed_ptr = austext_malloc (strlen(token) + 4, PROGNAME"1020", NULL);
  453. strcpy (*passed_ptr, token);
  454. return;
  455. } /* read_rest_of_line() */
  456. /****************************************/
  457. /* */
  458. /* read_filepath */
  459. /* */
  460. /****************************************/
  461. static void read_filepath (_Xstrtokparams *strtok_buf)
  462. {
  463. char *errp;
  464. char *newpath;
  465. int tabx;
  466. int toklen;
  467. /* Second token on line should be valid id word.
  468. * Set tabx to matching oef table entry.
  469. */
  470. if ((token = _XStrtok(NULL, DELIMITERS, *strtok_buf)) == NULL) {
  471. token = CATGETS(dtsearch_catd, MS_loadocf, 142, "rest of line");
  472. errp = CATGETS(dtsearch_catd, MS_loadocf, 143, "is empty");
  473. IGNORE_FILEPATH:
  474. sprintf (sprintbufp,
  475. CATGETS(dtsearch_catd, MS_loadocf, 903,
  476. "%s %s: FILEPATH '%s' %s. Line ignored."),
  477. PROGNAME"903", cfgfname, token, errp);
  478. DtSearchAddMessage (sprintbufp);
  479. return;
  480. }
  481. strupr (token);
  482. for (tabx = 0; oef_table[tabx].id != NULL; tabx++) {
  483. if (strcmp (oef_table[tabx].id, token) == 0)
  484. break;
  485. }
  486. if (oef_table[tabx].id == NULL) {
  487. errp = CATGETS(dtsearch_catd, MS_loadocf, 165, "unknown id");
  488. goto IGNORE_FILEPATH;
  489. }
  490. if (oef_table[tabx].previously_specified) {
  491. errp = CATGETS(dtsearch_catd, MS_loadocf, 166, "previously specified");
  492. goto IGNORE_FILEPATH;
  493. }
  494. /* Third token should be either a directory path (ends in slash)
  495. * or a directory path plus a file name (does not end in slash).
  496. */
  497. if ((token = _XStrtok(NULL, DELIMITERS, *strtok_buf)) == NULL) {
  498. token = oef_table[tabx].id;
  499. errp = CATGETS(dtsearch_catd, MS_loadocf, 168,
  500. "missing path specification");
  501. goto IGNORE_FILEPATH;
  502. }
  503. toklen = strlen (token);
  504. /* Allocate buffer for new path string and initialize it.
  505. * Leave enough extra room for the default, dos-format file name,
  506. * i.e. 8 chars, a period, and a 3 char extension.
  507. */
  508. newpath = austext_malloc (toklen + 20, PROGNAME "956", NULL);
  509. strcpy (newpath, token);
  510. if (token[toklen - 1] == LOCAL_SLASH) {
  511. strncpy (newpath + toklen, *(oef_table[tabx].OEFptr), 12);
  512. newpath[toklen + 12] = 0;
  513. }
  514. /* Setting the previously_specified flag not only prevents multiple
  515. * specifications in a single file, but also permits user files
  516. * to override site files for specific ids because loadocf is always
  517. * called by the ui before it is called by oe initialization.
  518. */
  519. *(oef_table[tabx].OEFptr) = newpath;
  520. oef_table[tabx].previously_specified = TRUE;
  521. return;
  522. } /* read_filepath() */
  523. /****************************************/
  524. /* */
  525. /* read_path */
  526. /* */
  527. /****************************************/
  528. static void read_path (_Xstrtokparams *strtok_buf)
  529. {
  530. #ifdef DEBUG_DUMP
  531. printf (PROGNAME "217> Entering read_path().\n");
  532. #endif
  533. /* parse the path for this dictionary/database */
  534. if ((token = _XStrtok(NULL, DELIMITERS, *strtok_buf)) == NULL) {
  535. sprintf (sprintbufp, CATGETS(dtsearch_catd, MS_loadocf, 221,
  536. "%s %s: Database '%s', No PATH specified, statement ignored.\n"),
  537. PROGNAME"221", cfgfname, db->name);
  538. DtSearchAddMessage (sprintbufp);
  539. return;
  540. }
  541. db->path = austext_malloc (strlen (token) + 4, PROGNAME "244", NULL);
  542. strcpy (db->path, token);
  543. ensure_end_slash (db->path);
  544. return;
  545. } /* read_path() */
  546. /****************************************/
  547. /* */
  548. /* obsolete_keyword */
  549. /* */
  550. /****************************************/
  551. /* append warning msg: passed keyword no longer used */
  552. static void obsolete_keyword (char *keyword)
  553. {
  554. sprintf (sprintbufp, CATGETS(dtsearch_catd, MS_loadocf, 1,
  555. "%1$s%2$s: %3$s keyword is obsolete."),
  556. PROGNAME "001 ", cfgfname, keyword);
  557. DtSearchAddMessage (sprintbufp);
  558. return;
  559. } /* obsolete_keyword() */
  560. /****************************************/
  561. /* */
  562. /* read_maxhits */
  563. /* */
  564. /****************************************/
  565. static void read_maxhits (_Xstrtokparams *strtok_buf)
  566. {
  567. int i;
  568. #ifdef DEBUG_DUMP
  569. printf (PROGNAME "292> Entering read_maxhits().\n");
  570. #endif
  571. /* parse the max number of hits for this dictionary */
  572. if ((token = _XStrtok(NULL, DELIMITERS, *strtok_buf)) == NULL) {
  573. INVALID_MAXHITS:
  574. sprintf (sprintbufp,
  575. CATGETS(dtsearch_catd, MS_loadocf, 304,
  576. "%s %s: Database '%s', invalid MAXHITS value.\n"),
  577. PROGNAME"304", cfgfname, db->name);
  578. DtSearchAddMessage (sprintbufp);
  579. fatal_error = TRUE;
  580. return;
  581. }
  582. i = atoi (token);
  583. if (i <= 0)
  584. goto INVALID_MAXHITS;
  585. else
  586. db->maxhits = i;
  587. return;
  588. } /* read_maxhits() */
  589. /****************************************/
  590. /* */
  591. /* add_a_keytype */
  592. /* */
  593. /****************************************/
  594. /* Subroutine of read_keytypes().
  595. * Concatenates a new DtSrKeytype node to end of current
  596. * db->keytypes array (in effect, remallocs db->keytypes).
  597. * Initializes ktchar with passed character.
  598. * Initializes name string with a generic label derived
  599. * from ktchar, which may later be changed by read_keytypes().
  600. * Keeps db->ktcount current.
  601. * If duplicate ktchar already exists, adds warning msg to
  602. * msglist, but changes nothing and returns index of old node.
  603. * Returns index of DtSrKeytype node or -1 on error.
  604. */
  605. static int add_a_keytype (char ktchar)
  606. {
  607. DtSrKeytype *kt;
  608. int i, newindex;
  609. /* Make sure we have not exceeded max number of keytypes */
  610. if (db->ktcount >= MAX_KTCOUNT) {
  611. sprintf (sprintbufp,
  612. CATGETS(dtsearch_catd, MS_loadocf, 732,
  613. "%s %s: Database '%s', No more than %d keytypes allowed.\n"),
  614. PROGNAME"732", cfgfname, db->name, MAX_KTCOUNT);
  615. DtSearchAddMessage (sprintbufp);
  616. fatal_error = TRUE;
  617. return -1;
  618. }
  619. /* Make sure ktchar is alphanumeric */
  620. if ( (ascii_charmap[ktchar] & (CONSONANT | VOWEL | NUMERAL)) == 0) {
  621. if (!isprint (ktchar))
  622. ktchar = '?';
  623. sprintf (sprintbufp,
  624. CATGETS(dtsearch_catd, MS_loadocf, 684,
  625. "%s %s: Database '%s',\n Invalid KEYTYPE character '%c'."),
  626. PROGNAME"684", cfgfname, db->name, ktchar);
  627. DtSearchAddMessage (sprintbufp);
  628. fatal_error = TRUE;
  629. return -1;
  630. }
  631. /* Test for duplicate, preexisting keytype */
  632. kt = db->keytypes;
  633. for (i = 0; i < db->ktcount; i++)
  634. if (ktchar == kt[i].ktchar) {
  635. sprintf (sprintbufp,
  636. CATGETS(dtsearch_catd, MS_loadocf, 1002,
  637. "%s %s: Database '%s', Duplicate KEYTYPE character '%c'.\n"),
  638. PROGNAME"1002", cfgfname, db->name, ktchar);
  639. DtSearchAddMessage (sprintbufp);
  640. return i;
  641. }
  642. /* Append valid new keytype to the keytypes array */
  643. i = sizeof(DtSrKeytype) * db->ktcount; /* size of current array */
  644. kt = austext_malloc (i + sizeof(DtSrKeytype) + 4, PROGNAME "699", NULL);
  645. if (db->keytypes != NULL) {
  646. memcpy (kt, db->keytypes, i);
  647. free (db->keytypes);
  648. }
  649. newindex = db->ktcount;
  650. kt[newindex].is_selected = TRUE;
  651. kt[newindex].ktchar = ktchar;
  652. sprintf (kt[newindex].name,
  653. CATGETS(dtsearch_catd, MS_loadocf, 457, "'%c' Records"), ktchar);
  654. /* Warn about inaccessible lowercase ktchars */
  655. if ( ((ascii_charmap[ktchar] & 0xff) != ktchar) && OE_uppercase_keys ) {
  656. sprintf (sprintbufp,
  657. CATGETS(dtsearch_catd, MS_loadocf, 1011,
  658. "%s %s: Database '%s': Records with lowercase\n"
  659. " KEYTYPE character '%c' will be inaccessible.\n"
  660. " Set UPPERKEYS = FALSE if lowercase keys are intended."),
  661. PROGNAME"1011", cfgfname, db->name, ktchar);
  662. DtSearchAddMessage (sprintbufp);
  663. }
  664. db->keytypes = kt;
  665. db->ktcount++;
  666. return newindex;
  667. } /* add_a_keytype() */
  668. /****************************************/
  669. /* */
  670. /* read_keytypes */
  671. /* */
  672. /****************************************/
  673. /* Builds keytypes arrays in current dblk.
  674. * Parameter 'how_many' limits the number keytype additions.
  675. * For example if how_many == 1, only 1 keytype will be added
  676. * and the balance of the line will be ignored.
  677. * We also quit adding keytypes when the total reaches
  678. * MAX_KTCOUNT or when we hit end of line or comments.
  679. */
  680. static void read_keytypes (int how_many, _Xstrtokparams *strtok_buf)
  681. {
  682. /* 'last_ktchar' is index to db->keytypes. if last_ktchar < 0
  683. * then last token was not a ktchar, or it was an invalid ktchar.
  684. */
  685. int last_ktchar = -1;
  686. DtSrKeytype *kt;
  687. char *charptr;
  688. #ifdef DEBUG_DUMP
  689. printf (PROGNAME "361> Entering read_keytypes().\n");
  690. #endif
  691. /* parsing loop for each keytypes token */
  692. while ((token = _XStrtok(NULL, DELIMITERS, *strtok_buf)) != NULL) {
  693. /* quit when comments begin */
  694. if (*token == '*' || *token == ':')
  695. break;
  696. /* Test for ktchar token (beginning with a single quote) */
  697. if (*token == '\'') {
  698. if (how_many <= 0)
  699. break; /* don't exceed our quota */
  700. last_ktchar = add_a_keytype (token[1]);
  701. if (last_ktchar >= 0)
  702. how_many--;
  703. continue;
  704. }
  705. /*
  706. * Token is a name string. If the last token was NOT a ktchar in
  707. * single quotes, or it was an invalid ktchar, then create a new
  708. * keytypes entry with the ktchar equal to the first char of this
  709. * label. If any err, don't update the name string.
  710. */
  711. if (last_ktchar < 0) {
  712. if (how_many <= 0)
  713. break; /* don't exceed our quota */
  714. last_ktchar = add_a_keytype (token[0]);
  715. if (last_ktchar < 0)
  716. continue;
  717. else
  718. how_many--;
  719. }
  720. /*
  721. * Update the appropriate table entry with the label string.
  722. * Convert underscores to spaces.
  723. */
  724. kt = &db->keytypes[last_ktchar];
  725. strncpy (kt->name, token, DtSrMAX_KTNAME);
  726. kt->name[DtSrMAX_KTNAME] = 0;
  727. for (charptr = kt->name; *charptr != 0; charptr++)
  728. if (*charptr == '_')
  729. *charptr = ' ';
  730. last_ktchar = -1;
  731. } /* end token parsing loop */
  732. return;
  733. } /* read_keytypes() */
  734. /****************************************/
  735. /* */
  736. /* ocfopen */
  737. /* */
  738. /****************************************/
  739. /* Subroutine of load_ocf().
  740. * Attempts to open config file created by concatenating
  741. * file name to passed pathname prefix.
  742. * If both fields are NULL, tries to open fully qualified
  743. * fname prespecified in OE_sitecnfg_fname.
  744. * Messages may be appended if some information, like an
  745. * environment variable, was found but still couldn't open file.
  746. * Loads OE_sitecnfg... fields after successful sitecnfg open.
  747. * Returns TRUE if fopen() successful, else FALSE.
  748. */
  749. static int ocfopen (char *prefix, char *fname, FILE ** stream)
  750. {
  751. char fullname[1024];
  752. FILE *fptr;
  753. struct stat statbuf;
  754. int is_prespecified_fname = (prefix == NULL && fname == NULL);
  755. /*
  756. * Build a complete path/file name from passed args into fullname
  757. * buffer.
  758. */
  759. if (is_prespecified_fname) {
  760. strncpy (fullname, OE_sitecnfg_fname, sizeof (fullname));
  761. fullname[sizeof (fullname) - 1] = 0;
  762. goto GOT_FULLNAME;
  763. }
  764. if (prefix == NULL) {
  765. if (debug_ocf)
  766. fprintf (aa_stderr, " --> open not attempted: null prefix.\n");
  767. return FALSE;
  768. }
  769. strncpy (fullname, prefix, sizeof (fullname));
  770. fullname[sizeof (fullname) - 2] = 0;
  771. strcpy (ensure_end_slash (fullname), fname);
  772. GOT_FULLNAME:
  773. fptr = fopen (fullname, "rt");
  774. if (debug_ocf) {
  775. if (fptr == NULL)
  776. fprintf (aa_stderr, " --> %s\n", strerror (errno));
  777. else
  778. fprintf (aa_stderr, " --> open succeeded!\n");
  779. }
  780. /*
  781. * If open failed: (1) Append information message if error is
  782. * something other than 'cant find file'. (Always retn msg if user
  783. * prespecified file name). (2) Return now.
  784. */
  785. if (fptr == NULL) {
  786. if (errno != ENOENT || is_prespecified_fname) {
  787. sprintf (sprintbufp, CATGETS(dtsearch_catd, MS_loadocf, 414,
  788. "%s Unable to open configuration file '%s':\n %s."),
  789. PROGNAME"414", fullname, strerror(errno));
  790. DtSearchAddMessage (sprintbufp);
  791. }
  792. return FALSE;
  793. }
  794. /* Load OE_... fields associated with site config */
  795. if (!is_prespecified_fname) {
  796. OE_sitecnfg_fname = austext_malloc (strlen (fullname) + 2,
  797. PROGNAME "941", NULL);
  798. strcpy (OE_sitecnfg_fname, fullname);
  799. }
  800. if (fstat (fileno (fptr), &statbuf) == -1) {
  801. sprintf (sprintbufp, CATGETS(dtsearch_catd, MS_loadocf, 1404,
  802. "%s Status unavailable for configuration file '%s': %s"),
  803. PROGNAME"1404", fullname, strerror(errno));
  804. DtSearchAddMessage (sprintbufp);
  805. fclose(fptr);
  806. return FALSE;
  807. }
  808. OE_sitecnfg_mtime = statbuf.st_mtime;
  809. /* Save file name globally for error msgs */
  810. strcpy (cfgfname, fullname);
  811. *stream = fptr;
  812. return TRUE;
  813. } /* ocfopen() */
  814. /****************************************/
  815. /* */
  816. /* load_ocf */
  817. /* */
  818. /****************************************/
  819. /* This is the only function in this module seen by the outside world.
  820. * Returns TRUE if .ocf file format is acceptable and everything worked.
  821. * Returns FALSE if file contains fatal errors. If file is ok, also
  822. * returns a list of dblks in global usrblk and sets some global variables.
  823. */
  824. int load_ocf (void)
  825. {
  826. char *p, *q;
  827. char sprintbuf[1024];
  828. char cfgfnamebuf[1024];
  829. char inbuf[1024];
  830. char uprtoken[128];
  831. FILE *stream;
  832. _Xstrtokparams strtok_buf;
  833. /* Initialize program globals */
  834. usrblk.dblist = NULL; /* just to be sure */
  835. fatal_error = FALSE;
  836. sprintbufp = sprintbuf;
  837. cfgfname = cfgfnamebuf;
  838. debug_ocf = (usrblk.debug & USRDBG_RARE);
  839. #ifdef DEBUG_DUMP
  840. puts ("\nentering load_ocf");
  841. dumpboth ();
  842. #endif
  843. #ifdef DEBUG_OEF
  844. dumpoef ("BEFORE");
  845. #endif
  846. /* Construct the full pathname/filename and open it.
  847. * Try various optional path prefixes depending on
  848. * existence of certain environment and global variables.
  849. * Also silently try the old filename in each directory.
  850. * If the site config file is never found, return FALSE,
  851. * meaning 'fatal error', and an error msg.
  852. *
  853. * (1) The first place to look is a prespecified, fully qualified
  854. * name passed by the initialization function. That occurs when
  855. * the global OE_sitecnfg_fname, which otherwise would be NULL,
  856. * points to the passed arg. It's a fatal error if this name
  857. * was specified but cannot be opened.
  858. */
  859. if (OE_sitecnfg_fname) {
  860. if (debug_ocf)
  861. fprintf (aa_stderr,
  862. PROGNAME "1446 ocfopen '%s', prespecified file name.\n",
  863. OE_sitecnfg_fname);
  864. if (ocfopen (NULL, NULL, &stream))
  865. goto OCFOPEN_OK;
  866. else
  867. return FALSE;
  868. }
  869. /* (2) try to find file in DTSROCFPATH directory */
  870. p = getenv ("DTSROCFPATH");
  871. if (debug_ocf)
  872. fprintf (aa_stderr, PROGNAME "1753 ocfopen '%s'. DTSROCFPATH='%s'.\n",
  873. FNAME_SITECONFIG, NULLORSTR (p));
  874. if (ocfopen (p, FNAME_SITECONFIG, &stream))
  875. goto OCFOPEN_OK;
  876. if (ocfopen (p, FNAME_SITECONFIG_OLD, &stream))
  877. goto OCFOPEN_OK;
  878. /* (3) try to find file in current working directory */
  879. if (getcwd (inbuf, sizeof (inbuf)) == NULL)
  880. strcpy (inbuf, "./"); /* default to 'local' dir */
  881. else if (inbuf[0] == 0)
  882. strcpy (inbuf, "/"); /* presume 'root' dir */
  883. if (debug_ocf)
  884. fprintf (aa_stderr, PROGNAME "1771 ocfopen '%s'. cwd='%s'.\n",
  885. FNAME_SITECONFIG, inbuf);
  886. if (ocfopen (inbuf, FNAME_SITECONFIG, &stream))
  887. goto OCFOPEN_OK;
  888. if (ocfopen (inbuf, FNAME_SITECONFIG_OLD, &stream))
  889. goto OCFOPEN_OK;
  890. /* (4) try to find file in HOME directory */
  891. q = getenv ("HOME");
  892. if (debug_ocf)
  893. fprintf (aa_stderr, "ocfopen '%s'. HOME='%s'.\n",
  894. FNAME_SITECONFIG, NULLORSTR (q));
  895. if (ocfopen (q, FNAME_SITECONFIG, &stream))
  896. goto OCFOPEN_OK;
  897. if (ocfopen (q, FNAME_SITECONFIG_OLD, &stream))
  898. goto OCFOPEN_OK;
  899. /* (5) try to find file in server daemon's inittab directory */
  900. if (debug_ocf)
  901. fprintf (aa_stderr, "ocfopen '%s'. OE_inittab_dir='%s'.\n",
  902. FNAME_SITECONFIG, NULLORSTR (OE_inittab_dir));
  903. if (ocfopen (OE_inittab_dir, FNAME_SITECONFIG, &stream))
  904. goto OCFOPEN_OK;
  905. if (ocfopen (OE_inittab_dir, FNAME_SITECONFIG_OLD, &stream))
  906. goto OCFOPEN_OK;
  907. /* (6) try to find file in server daemon's inetd.conf directory */
  908. if (debug_ocf)
  909. fprintf (aa_stderr, "ocfopen '%s'. OE_server_dir='%s'.\n",
  910. FNAME_SITECONFIG, NULLORSTR (OE_server_dir));
  911. if (ocfopen (OE_server_dir, FNAME_SITECONFIG, &stream))
  912. goto OCFOPEN_OK;
  913. if (ocfopen (OE_server_dir, FNAME_SITECONFIG_OLD, &stream))
  914. goto OCFOPEN_OK;
  915. /* If we can't find site config on OE side we must quit. */
  916. sprintf (sprintbuf, CATGETS(dtsearch_catd, MS_loadocf, 1643,
  917. "%1$sCannot find or open '%2$s'\n"
  918. " configuration file in any of the following locations:\n"
  919. " DTSROCFPATH directory = %3$s,\n"
  920. " current working directory = %4$s,\n"
  921. " HOME directory = %5$s,\n"
  922. " /etc/inittab directory = %6$s\n"
  923. " /etc/inetd.conf directory = %7$s\n"
  924. )
  925. ,PROGNAME "1643 "
  926. ,FNAME_SITECONFIG
  927. ,(p) ? p : CATGETS(dtsearch_catd, MS_misc, 16,
  928. "<no environment variable>")
  929. ,inbuf
  930. ,(q) ? q : CATGETS(dtsearch_catd, MS_misc, 16,
  931. "<no environment variable>")
  932. ,(OE_inittab_dir) ? OE_inittab_dir :
  933. CATGETS(dtsearch_catd, MS_misc, 17,
  934. "<no server daemon>")
  935. ,(OE_server_dir) ? OE_server_dir :
  936. CATGETS(dtsearch_catd, MS_misc, 17,
  937. "<no server daemon>")
  938. );
  939. DtSearchAddMessage (sprintbuf);
  940. return FALSE;
  941. OCFOPEN_OK:
  942. /* MAIN LOOP ---- Read each line from file */
  943. *inbuf = '\0';
  944. while (fgets (inbuf, sizeof (inbuf) - 1, stream) != NULL) {
  945. /* terminate string just to be sure */
  946. if (strlen(inbuf) && inbuf[strlen(inbuf)-1] == '\n')
  947. inbuf[strlen(inbuf)-1] = '\0';
  948. /* test for comment line */
  949. if (strchr (COMMENT_CHARS, inbuf[0]))
  950. continue;
  951. /* parse KEYWORD */
  952. if ((token = _XStrtok(inbuf, DELIMITERS, strtok_buf)) == NULL)
  953. continue;
  954. snprintf(uprtoken, sizeof(uprtoken), "%s", token);
  955. strupr (uprtoken);
  956. if (strcmp (uprtoken, "PATH") == 0) {
  957. if (read_database (uprtoken, &strtok_buf))
  958. read_path (&strtok_buf);
  959. continue;
  960. }
  961. if (strcmp (uprtoken, "KEYTYPES") == 0) {
  962. if (read_database (uprtoken, &strtok_buf))
  963. read_keytypes (MAX_KTCOUNT, &strtok_buf);
  964. continue;
  965. }
  966. if (strcmp (uprtoken, "KEYTYPE") == 0) {
  967. if (read_database (uprtoken, &strtok_buf))
  968. read_keytypes (1, &strtok_buf);
  969. continue;
  970. }
  971. if (strcmp (uprtoken, "FILEIO") == 0) {
  972. set_fileio (&strtok_buf);
  973. continue;
  974. }
  975. if (strcmp (uprtoken, "USERNOTES") == 0) {
  976. set_boolint (&OE_enable_usernotes, uprtoken, &strtok_buf);
  977. continue;
  978. }
  979. if (strcmp (uprtoken, "MARKDEL") == 0) {
  980. set_boolint (&OE_enable_markdel, uprtoken, &strtok_buf);
  981. continue;
  982. }
  983. if (strcmp (uprtoken, "FASTDECODE") == 0) {
  984. set_boolint (&OE_fastdecode, uprtoken, &strtok_buf);
  985. continue;
  986. }
  987. if (strcmp (uprtoken, "NOITERATE") == 0) {
  988. set_boolbit (&OE_flags, OE_NO_ITERATE, uprtoken, &strtok_buf);
  989. continue;
  990. }
  991. if (strcmp (uprtoken, "UPPERKEYS") == 0) {
  992. set_boolint (&OE_uppercase_keys, uprtoken, &strtok_buf);
  993. continue;
  994. }
  995. if (strcmp (uprtoken, "AUDIT") == 0) {
  996. set_boolbit (&OE_flags, OE_AUDIT, uprtoken, &strtok_buf);
  997. continue;
  998. }
  999. if (strcmp (uprtoken, "FILEPATH") == 0) {
  1000. read_filepath (&strtok_buf);
  1001. continue;
  1002. }
  1003. if (strcmp (uprtoken, "WHITLIM") == 0) {
  1004. set_long (&OE_words_hitlimit, uprtoken, &strtok_buf);
  1005. continue;
  1006. }
  1007. if (strcmp (token, "d3bug") == 0) {
  1008. usrblk.debug |= atol (token + strlen (token) + 1);
  1009. printf (PROGNAME "1630 %s: usrblk.debug = %ld, x%08lx.\n",
  1010. cfgfname, usrblk.debug, usrblk.debug);
  1011. continue;
  1012. }
  1013. if (strcmp (uprtoken, "MAXHITS") == 0) {
  1014. if (read_database (uprtoken, &strtok_buf))
  1015. read_maxhits (&strtok_buf);
  1016. continue;
  1017. }
  1018. if (strcmp (uprtoken, "LABEL") == 0) {
  1019. if (read_database (uprtoken, &strtok_buf))
  1020. read_rest_of_line (uprtoken, &db->label, &strtok_buf);
  1021. continue;
  1022. }
  1023. /* if we made it this far, the first token is unknown */
  1024. sprintf (sprintbufp,
  1025. CATGETS(dtsearch_catd, MS_loadocf, 495,
  1026. "%s %s: '%.16s' is invalid keyword.\n"),
  1027. PROGNAME"495", cfgfname, token);
  1028. DtSearchAddMessage (sprintbufp);
  1029. #ifdef DEBUG_DUMP
  1030. dumpboth ();
  1031. #endif
  1032. } /* ...keep reading next line in file until eof */
  1033. fclose (stream);
  1034. /* In a site config file, SOME database has to have been specified.
  1035. * Also for each database, KEYTYPES must be present and perfect.
  1036. * If no keytypes survived the KEYTYPES parse for each database,
  1037. * or if there was no KEYTYPES line for a database
  1038. * in site config file, remove the dblk and mark fatal error.
  1039. */
  1040. if (usrblk.dblist == NULL) {
  1041. sprintf (sprintbufp, CATGETS(dtsearch_catd, MS_loadocf, 1869,
  1042. "%s %s: Configuration file must specify at least one database."),
  1043. PROGNAME"1869", cfgfname);
  1044. DtSearchAddMessage (sprintbufp);
  1045. fatal_error = TRUE;
  1046. }
  1047. else
  1048. for (db = usrblk.dblist; db != NULL; db = db->link) {
  1049. if (db->ktcount <= 0) {
  1050. sprintf (sprintbufp, CATGETS(dtsearch_catd, MS_loadocf, 986,
  1051. "%s %s: KEYTYPES missing for database '%s'."),
  1052. PROGNAME"986", cfgfname, db->name);
  1053. DtSearchAddMessage (sprintbufp);
  1054. cutnode_llist ((LLIST *)db, (LLIST **)&usrblk.dblist);
  1055. free (db);
  1056. fatal_error = TRUE;
  1057. }
  1058. }
  1059. #ifdef DEBUG_OEF
  1060. dumpoef ("AFTER");
  1061. #endif
  1062. #ifdef DEBUG_DUMP
  1063. printf (PROGNAME "516 leaving load_ocf().\n");
  1064. dumpboth ();
  1065. #endif
  1066. if (fatal_error)
  1067. return FALSE;
  1068. usrblk.dblk = usrblk.dblist; /* init usrblk.dblk */
  1069. return TRUE;
  1070. } /* load_ocf() */
  1071. /*************************** OCF.C ****************************/