2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
24 * COMPONENT_NAME: austext
26 * FUNCTIONS: add_a_keytype
47 * (C) COPYRIGHT International Business Machines Corp. 1991,1995
49 * US Government Users Restricted Rights - Use, duplication or
50 * disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
52 /*************************** OCF.C ***************************
53 * $TOG: ocf.c /main/9 1998/04/17 11:26:02 mgreess $
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.
68 * Revision 2.6 1996/03/05 21:12:01 miker
69 * Reversed meaning of ascii_charmap test.
71 * Revision 2.5 1996/03/05 18:02:46 miker
72 * Repl ctype functions with refs to ascii_charmap and COMMENT_CHARS.
74 * Revision 2.4 1996/02/05 16:34:57 miker
75 * Silently try old file name when looking for site config file.
77 * Revision 2.3 1995/10/25 15:39:33 miker
80 * Revision 2.2 1995/10/03 21:40:15 miker
81 * Cosmetic msg change only.
83 * Revision 2.1 1995/09/22 21:30:12 miker
84 * Freeze DtSearch 0.1, AusText 2.1.8
86 * Revision 1.3 1995/09/05 21:41:59 miker
87 * Changed environment variable OCFPATH to DTSROCFPATH.
89 * Revision 1.2 1995/09/05 18:46:13 miker
90 * Moved all documentation to ocf.doc.
92 * Revision 1.1 1995/08/31 21:07:25 miker
93 * Initial revision (renamed ocf.c from loadocf.c).
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.
100 * Revision 1.18 1995/07/18 22:52:17 miker
101 * Added ability to open prespecified OE_sitecnfg_fname.
106 #define X_INCLUDE_STRING_H
107 #define XOS_USE_NO_LOCKING
108 #include <X11/Xos_r.h>
110 #include <unistd.h> /* for POSIX getcwd() */
111 #include <sys/stat.h>
113 /*****#define DEBUG_DUMP******/
114 /********#define DEBUG_OEF**********/
116 #define PROGNAME "OCF"
117 #define DELIMITERS " =,\t\n"
118 #define NEGLOGHALF (-.69314718F) /* negative natural log of .5 */
119 #define FNAME_SITECONFIG_OLD "austext.ocf"
123 /*-------------------- STATIC GLOBALS ----------------------*/
124 static DBLK *db; /* curr database/dict */
125 static char *cfgfname;
126 static char *sprintbufp;
128 static int fatal_error;
129 static int debug_ocf = FALSE;
131 /*-------------------- ENGINE GLOBALS ----------------------
132 * These are globals which must be accessed by both sides.
133 * Globals unique to the engine are in oe.c.
135 char *OE_server_dir = NULL;
136 char *OE_inittab_dir = NULL;
138 /*-------------------- OEF TABLE ----------------------*/
139 /*** (struct typdef located in oe.h)
141 char *id; keyword identifier
142 char **OEFptr; addr of variable to change
143 char previously_specified; bool ensures only one spec
148 "AUDIT", &OEF_audit, FALSE,
149 "DISCARD", &OEF_discard, FALSE,
150 "NEWS", &OEF_news, FALSE,
151 "NOTESNOT", &OEF_notesnot, FALSE,
152 "NOTESSEM", &OEF_notessem, FALSE,
153 "README", &OEF_readme, FALSE,
154 NULL, NULL, FALSE /* end of list */
158 #ifdef DEBUG_DUMP /* for debugging only */
159 /****************************************/
163 /****************************************/
164 static void dumpboth (void)
166 char typestring[4 * MAX_KTCOUNT + 2];
172 printf ("\nDUMPBOTH> fatal_error=%d, msglist=%p, dblist=%p\n",
173 fatal_error, ausapi_msglist, usrblk.dblist);
174 printf ("%s\n", DtSrGetMessages ());
176 for (d = usrblk.dblist; d != NULL; d = d->link) {
178 for (i = 0; i < d->ktcount; i++) {
179 *ptr++ = (d->keytypes[i].is_selected) ? '*' : ' ';
180 *ptr++ = d->keytypes[i].ktchar;
184 printf ("DBLK at %p link=%p name='%s' max=%d\n"
185 " keytypes='%s', path='%s'\n",
186 d, d->link, d->name, d->maxhits,
187 typestring, NULLORSTR (d->path));
189 printf ("Push any key to continue...");
192 fgets (typestring, sizeof(typestring), stdin);
193 if (strlen(typestring) && typestring[strlen(typestring)-1] == '\n')
194 typestring[strlen(typestring)-1] = '\0';
202 #ifdef DEBUG_OEF /* for debugging only */
203 /****************************************/
207 /****************************************/
208 static void dumpoef (char *before_after)
212 "\toef_table[] %s (* = changed strings)\n",
214 for (oef = oef_table; oef->id != NULL; oef++) {
215 fprintf (aa_stderr, "\t%10s = %c'%s'\n",
217 (oef->previously_specified) ? '*' : ' ',
220 fputc ('\n', aa_stderr);
227 /****************************************/
231 /****************************************/
232 /* Forces token to upper case.
233 * Returns +1 for TRUE, -1 for FALSE, and 0 for neither.
235 static int parse_boolean (char *token)
237 /* Completely missing token defaults to affirmative */
243 case 'O': /* on, off */
246 else if (token[1] == 'F')
253 case 'E': /* enabled */
254 case '1': /* (one) */
257 case 'F': /* false */
259 case 'D': /* disabled */
260 case '0': /* (zero) */
266 } /* parse_boolean() */
268 /****************************************/
272 /****************************************/
273 /* Validates next token as database name.
274 * If not valid name, returns FALSE.
275 * Otherwise chains down through the database list
276 * looking for the one whose name matches the token.
277 * If a match is found, sets db to it, returns TRUE.
278 * If no match is found, creates and initializes
279 * new structure, sets db to it, returns TRUE.
281 static int read_database (char *keyword, _Xstrtokparams *strtok_buf)
285 if ((token = _XStrtok(NULL, DELIMITERS, *strtok_buf)) == NULL) {
287 catgets (dtsearch_catd, MS_loadocf, 477,
288 "%s %s: Missing database name after '%s' keyword.\n"),
289 PROGNAME"477", cfgfname, keyword);
290 DtSearchAddMessage (sprintbufp);
295 if (strlen (token) > 8) {
297 catgets (dtsearch_catd, MS_loadocf, 184,
298 "%s %s: More than 8 characters in Database name '%.16s'.\n"),
299 PROGNAME"184", cfgfname, token);
300 DtSearchAddMessage (sprintbufp);
305 /* Chain down the list looking for previously defined database structure */
306 linkptr = &usrblk.dblist;
307 for (db = usrblk.dblist; db != NULL; db = db->link) {
308 if (strcmp (db->name, token) == 0)
312 /* Didn't find matching dblk so allocate and initialize new one at
313 * end of list (linkptr). Use system defaults for most values.
316 fprintf (aa_stderr, PROGNAME "204 "
317 "%s: creating dblk for '%s'\n", cfgfname, token);
318 db = austext_malloc (sizeof (DBLK) + 8, PROGNAME "205", NULL);
319 memset (db, 0, sizeof (DBLK));
320 strcpy (db->name, token);
321 db->is_selected = TRUE;
325 } /* read_database() */
328 /****************************************/
332 /****************************************/
333 static void set_boolbit (long *flagvar, long mask, char *flagname,
334 _Xstrtokparams *strtok_buf)
338 token = _XStrtok(NULL, DELIMITERS, *strtok_buf);
339 i = parse_boolean (token);
341 *flagvar |= mask; /* switch ON */
343 *flagvar &= ~mask; /* switch OFF */
346 catgets (dtsearch_catd, MS_loadocf, 352,
347 "%s %s: Invalid %s value, line ignored.\n"),
348 PROGNAME"352", cfgfname, flagname);
349 DtSearchAddMessage (sprintbufp);
352 } /* set_boolbit() */
356 /****************************************/
360 /****************************************/
361 static void set_int (int *intvar, char *keyword, _Xstrtokparams *strtok_buf)
365 if ((token = _XStrtok(NULL, DELIMITERS, *strtok_buf)) == NULL) {
366 token = catgets (dtsearch_catd, MS_loadocf, 140, "(missing)");
368 sprintf (sprintbufp, catgets (dtsearch_catd, MS_loadocf, 610,
369 "%s %s: %s value is '%s'. "
370 "Should be positive integer. Line ignored."),
371 PROGNAME"844", cfgfname, keyword, token);
372 DtSearchAddMessage (sprintbufp);
375 if ((myint = atoi (token)) <= 0L)
382 /****************************************/
386 /****************************************/
387 static void set_long (long *longvar, char *keyword,
388 _Xstrtokparams *strtok_buf)
392 if ((token = _XStrtok(NULL, DELIMITERS, *strtok_buf)) == NULL) {
393 token = catgets (dtsearch_catd, MS_loadocf, 140, "(missing)");
395 sprintf (sprintbufp, catgets (dtsearch_catd, MS_loadocf, 610,
396 "%s %s: %s value is '%s'. "
397 "Should be positive integer. Line ignored."),
398 PROGNAME"610", cfgfname, keyword, token);
399 DtSearchAddMessage (sprintbufp);
402 if ((longi = atol (token)) <= 0L)
409 /****************************************/
413 /****************************************/
414 static void set_boolint (int *boolint, char *keyword,
415 _Xstrtokparams *strtok_buf)
419 token = _XStrtok(NULL, DELIMITERS, *strtok_buf);
420 i = parse_boolean (token);
422 *boolint = TRUE; /* switch ON */
424 *boolint = FALSE; /* switch OFF */
427 catgets (dtsearch_catd, MS_loadocf, 352,
428 "%s %s: Invalid %s value, line ignored.\n"),
429 PROGNAME"352", cfgfname, keyword);
430 DtSearchAddMessage (sprintbufp);
433 } /* set_boolint() */
435 /****************************************/
439 /****************************************/
440 /* sets OE_fileio string pointer */
441 static void set_fileio (_Xstrtokparams *strtok_buf)
445 /* if a value is missing, presume -ON */
446 if ((token = _XStrtok(NULL, DELIMITERS, *strtok_buf)) == NULL) {
451 /* check for hardcoded path name (anything that doesn't begin with '-') */
452 if (token[0] != '-') {
453 OE_fileio = austext_malloc (strlen (token) + 2, PROGNAME "592", NULL);
454 strcpy (OE_fileio, token);
459 if (strcmp (token, "-ON") == 0)
461 else if (strcmp (token, "-OFF") == 0)
463 else if (strcmp (token, "-HOME") == 0)
466 sprintf (sprintbufp, catgets (dtsearch_catd, MS_loadocf, 607,
467 "%s %s: Invalid FILEIO value. "
468 "User file reads and writes prohibited."),
469 PROGNAME"607", cfgfname);
470 DtSearchAddMessage (sprintbufp);
477 /****************************************/
479 /* read_rest_of_line */
481 /****************************************/
482 /* Malloc a copy of the rest of the input line after
483 * the current token and set passed string ptr to it.
485 static void read_rest_of_line (char *keyword, char **passed_ptr,
486 _Xstrtokparams *strtok_buf)
490 if ((token = _XStrtok(NULL, "\n", *strtok_buf)) == NULL) {
491 sprintf (sprintbufp, catgets (dtsearch_catd, MS_loadocf, 1007,
492 "%s%s: Empty %s string ignored."),
493 PROGNAME"1007 ", cfgfname, keyword);
494 DtSearchAddMessage (sprintbufp);
497 *passed_ptr = austext_malloc (strlen(token) + 4, PROGNAME"1020", NULL);
498 strcpy (*passed_ptr, token);
500 } /* read_rest_of_line() */
503 /****************************************/
507 /****************************************/
508 static void read_filepath (_Xstrtokparams *strtok_buf)
515 /* Second token on line should be valid id word.
516 * Set tabx to matching oef table entry.
518 if ((token = _XStrtok(NULL, DELIMITERS, *strtok_buf)) == NULL) {
519 token = catgets (dtsearch_catd, MS_loadocf, 142, "rest of line");
520 errp = catgets (dtsearch_catd, MS_loadocf, 143, "is empty");
524 catgets (dtsearch_catd, MS_loadocf, 903,
525 "%s %s: FILEPATH '%s' %s. Line ignored."),
526 PROGNAME"903", cfgfname, token, errp);
527 DtSearchAddMessage (sprintbufp);
531 for (tabx = 0; oef_table[tabx].id != NULL; tabx++) {
532 if (strcmp (oef_table[tabx].id, token) == 0)
535 if (oef_table[tabx].id == NULL) {
536 errp = catgets (dtsearch_catd, MS_loadocf, 165, "unknown id");
537 goto IGNORE_FILEPATH;
539 if (oef_table[tabx].previously_specified) {
540 errp = catgets (dtsearch_catd, MS_loadocf, 166, "previously specified");
541 goto IGNORE_FILEPATH;
544 /* Third token should be either a directory path (ends in slash)
545 * or a directory path plus a file name (does not end in slash).
547 if ((token = _XStrtok(NULL, DELIMITERS, *strtok_buf)) == NULL) {
548 token = oef_table[tabx].id;
549 errp = catgets (dtsearch_catd, MS_loadocf, 168,
550 "missing path specification");
551 goto IGNORE_FILEPATH;
553 toklen = strlen (token);
555 /* Allocate buffer for new path string and initialize it.
556 * Leave enough extra room for the default, dos-format file name,
557 * i.e. 8 chars, a period, and a 3 char extension.
559 newpath = austext_malloc (toklen + 20, PROGNAME "956", NULL);
560 strcpy (newpath, token);
561 if (token[toklen - 1] == LOCAL_SLASH) {
562 strncpy (newpath + toklen, *(oef_table[tabx].OEFptr), 12);
563 newpath[toklen + 12] = 0;
566 /* Setting the previously_specified flag not only prevents multiple
567 * specifications in a single file, but also permits user files
568 * to override site files for specific ids because loadocf is always
569 * called by the ui before it is called by oe initialization.
571 *(oef_table[tabx].OEFptr) = newpath;
572 oef_table[tabx].previously_specified = TRUE;
574 } /* read_filepath() */
577 /****************************************/
581 /****************************************/
582 static void read_path (_Xstrtokparams *strtok_buf)
585 printf (PROGNAME "217> Entering read_path().\n");
588 /* parse the path for this dictionary/database */
589 if ((token = _XStrtok(NULL, DELIMITERS, *strtok_buf)) == NULL) {
590 sprintf (sprintbufp, catgets (dtsearch_catd, MS_loadocf, 221,
591 "%s %s: Database '%s', No PATH specified, statement ignored.\n"),
592 PROGNAME"221", cfgfname, db->name);
593 DtSearchAddMessage (sprintbufp);
596 db->path = austext_malloc (strlen (token) + 4, PROGNAME "244", NULL);
597 strcpy (db->path, token);
598 ensure_end_slash (db->path);
603 /****************************************/
605 /* obsolete_keyword */
607 /****************************************/
608 /* append warning msg: passed keyword no longer used */
609 static void obsolete_keyword (char *keyword)
611 sprintf (sprintbufp, catgets (dtsearch_catd, MS_loadocf, 1,
612 "%1$s%2$s: %3$s keyword is obsolete."),
613 PROGNAME "001 ", cfgfname, keyword);
614 DtSearchAddMessage (sprintbufp);
616 } /* obsolete_keyword() */
619 /****************************************/
623 /****************************************/
624 static void read_maxhits (_Xstrtokparams *strtok_buf)
629 printf (PROGNAME "292> Entering read_maxhits().\n");
632 /* parse the max number of hits for this dictionary */
633 if ((token = _XStrtok(NULL, DELIMITERS, *strtok_buf)) == NULL) {
636 catgets (dtsearch_catd, MS_loadocf, 304,
637 "%s %s: Database '%s', invalid MAXHITS value.\n"),
638 PROGNAME"304", cfgfname, db->name);
639 DtSearchAddMessage (sprintbufp);
645 goto INVALID_MAXHITS;
649 } /* read_maxhits() */
652 /****************************************/
656 /****************************************/
657 /* Subroutine of read_keytypes().
658 * Concatenates a new DtSrKeytype node to end of current
659 * db->keytypes array (in effect, remallocs db->keytypes).
660 * Initializes ktchar with passed character.
661 * Initializes name string with a generic label derived
662 * from ktchar, which may later be changed by read_keytypes().
663 * Keeps db->ktcount current.
664 * If duplicate ktchar already exists, adds warning msg to
665 * msglist, but changes nothing and returns index of old node.
666 * Returns index of DtSrKeytype node or -1 on error.
668 static int add_a_keytype (char ktchar)
673 /* Make sure we have not exceeded max number of keytypes */
674 if (db->ktcount >= MAX_KTCOUNT) {
676 catgets (dtsearch_catd, MS_loadocf, 732,
677 "%s %s: Database '%s', No more than %d keytypes allowed.\n"),
678 PROGNAME"732", cfgfname, db->name, MAX_KTCOUNT);
679 DtSearchAddMessage (sprintbufp);
684 /* Make sure ktchar is alphanumeric */
685 if ( (ascii_charmap[ktchar] & (CONSONANT | VOWEL | NUMERAL)) == 0) {
686 if (!isprint (ktchar))
689 catgets (dtsearch_catd, MS_loadocf, 684,
690 "%s %s: Database '%s',\n Invalid KEYTYPE character '%c'."),
691 PROGNAME"684", cfgfname, db->name, ktchar);
692 DtSearchAddMessage (sprintbufp);
697 /* Test for duplicate, preexisting keytype */
699 for (i = 0; i < db->ktcount; i++)
700 if (ktchar == kt[i].ktchar) {
702 catgets (dtsearch_catd, MS_loadocf, 1002,
703 "%s %s: Database '%s', Duplicate KEYTYPE character '%c'.\n"),
704 PROGNAME"1002", cfgfname, db->name, ktchar);
705 DtSearchAddMessage (sprintbufp);
709 /* Append valid new keytype to the keytypes array */
710 i = sizeof(DtSrKeytype) * db->ktcount; /* size of current array */
711 kt = austext_malloc (i + sizeof(DtSrKeytype) + 4, PROGNAME "699", NULL);
712 if (db->keytypes != NULL) {
713 memcpy (kt, db->keytypes, i);
716 newindex = db->ktcount;
717 kt[newindex].is_selected = TRUE;
718 kt[newindex].ktchar = ktchar;
719 sprintf (kt[newindex].name,
720 catgets (dtsearch_catd, MS_loadocf, 457, "'%c' Records"), ktchar);
722 /* Warn about inaccessible lowercase ktchars */
723 if ( ((ascii_charmap[ktchar] & 0xff) != ktchar) && OE_uppercase_keys ) {
725 catgets (dtsearch_catd, MS_loadocf, 1011,
726 "%s %s: Database '%s': Records with lowercase\n"
727 " KEYTYPE character '%c' will be inaccessible.\n"
728 " Set UPPERKEYS = FALSE if lowercase keys are intended."),
729 PROGNAME"1011", cfgfname, db->name, ktchar);
730 DtSearchAddMessage (sprintbufp);
736 } /* add_a_keytype() */
739 /****************************************/
743 /****************************************/
744 /* Builds keytypes arrays in current dblk.
745 * Parameter 'how_many' limits the number keytype additions.
746 * For example if how_many == 1, only 1 keytype will be added
747 * and the balance of the line will be ignored.
748 * We also quit adding keytypes when the total reaches
749 * MAX_KTCOUNT or when we hit end of line or commments.
751 static void read_keytypes (int how_many, _Xstrtokparams *strtok_buf)
753 /* 'last_ktchar' is index to db->keytypes. if last_ktchar < 0
754 * then last token was not a ktchar, or it was an invalid ktchar.
756 int last_ktchar = -1;
761 printf (PROGNAME "361> Entering read_keytypes().\n");
764 /* parsing loop for each keytypes token */
765 while ((token = _XStrtok(NULL, DELIMITERS, *strtok_buf)) != NULL) {
766 /* quit when comments begin */
767 if (*token == '*' || *token == ':')
770 /* Test for ktchar token (beginning with a single quote) */
771 if (*token == '\'') {
773 break; /* don't exceed our quota */
774 last_ktchar = add_a_keytype (token[1]);
775 if (last_ktchar >= 0)
781 * Token is a name string. If the last token was NOT a ktchar in
782 * single quotes, or it was an invalid ktchar, then create a new
783 * keytypes entry with the ktchar equal to the first char of this
784 * label. If any err, don't update the name string.
786 if (last_ktchar < 0) {
788 break; /* don't exceed our quota */
789 last_ktchar = add_a_keytype (token[0]);
797 * Update the appropriate table entry with the label string.
798 * Convert underscores to spaces.
800 kt = &db->keytypes[last_ktchar];
801 strncpy (kt->name, token, DtSrMAX_KTNAME);
802 kt->name[DtSrMAX_KTNAME] = 0;
803 for (charptr = kt->name; *charptr != 0; charptr++)
808 } /* end token parsing loop */
811 } /* read_keytypes() */
814 /****************************************/
818 /****************************************/
819 /* Subroutine of load_ocf().
820 * Attempts to open config file created by concatenating
821 * file name to passed pathname prefix.
822 * If both fields are NULL, tries to open fully qualified
823 * fname prespecified in OE_sitecnfg_fname.
824 * Messages may be appended if some information, like an
825 * environment variable, was found but still couldn't open file.
826 * Loads OE_sitecnfg... fields after successful sitecnfg open.
827 * Returns TRUE if fopen() successful, else FALSE.
830 static int ocfopen (char *prefix, char *fname, FILE ** stream)
836 int is_prespecified_fname = (prefix == NULL && fname == NULL);
839 * Build a complete path/file name from passed args into fullname
842 if (is_prespecified_fname) {
843 strncpy (fullname, OE_sitecnfg_fname, sizeof (fullname));
844 fullname[sizeof (fullname) - 1] = 0;
848 if (prefix == NULL) {
850 fprintf (aa_stderr, " --> open not attempted: null prefix.\n");
854 strncpy (fullname, prefix, sizeof (fullname));
855 fullname[sizeof (fullname) - 2] = 0;
856 strcpy (ensure_end_slash (fullname), fname);
860 fptr = fopen (fullname, "rt");
863 fprintf (aa_stderr, " --> %s\n", strerror (errno));
865 fprintf (aa_stderr, " --> open succeeded!\n");
869 * If open failed: (1) Append information message if error is
870 * something other than 'cant find file'. (Always retn msg if user
871 * prespecified file name). (2) Return now.
874 if (errno != ENOENT || is_prespecified_fname) {
875 sprintf (sprintbufp, catgets (dtsearch_catd, MS_loadocf, 414,
876 "%s Unable to open configuration file '%s':\n %s."),
877 PROGNAME"414", fullname, strerror(errno));
878 DtSearchAddMessage (sprintbufp);
883 /* Load OE_... fields associated with site config */
884 if (!is_prespecified_fname) {
885 OE_sitecnfg_fname = austext_malloc (strlen (fullname) + 2,
886 PROGNAME "941", NULL);
887 strcpy (OE_sitecnfg_fname, fullname);
889 if (fstat (fileno (fptr), &statbuf) == -1) {
890 sprintf (sprintbufp, catgets (dtsearch_catd, MS_loadocf, 1404,
891 "%s Status unavailable for configuration file '%s': %s"),
892 PROGNAME"1404", fullname, strerror(errno));
893 DtSearchAddMessage (sprintbufp);
896 OE_sitecnfg_mtime = statbuf.st_mtime;
898 /* Save file name globally for error msgs */
899 strcpy (cfgfname, fullname);
905 /****************************************/
909 /****************************************/
910 /* This is the only function in this module seen by the outside world.
911 * Returns TRUE if .ocf file format is acceptable and everything worked.
912 * Returns FALSE if file contains fatal errors. If file is ok, also
913 * returns a list of dblks in global usrblk and sets some global variables.
919 char sprintbuf[1024];
920 char cfgfnamebuf[1024];
924 _Xstrtokparams strtok_buf;
926 /* Initialize program globals */
927 usrblk.dblist = NULL; /* just to be sure */
929 sprintbufp = sprintbuf;
930 cfgfname = cfgfnamebuf;
932 debug_ocf = (usrblk.debug & USRDBG_RARE);
935 puts ("\nentering load_ocf");
943 /* Construct the full pathname/filename and open it.
944 * Try various optional path prefixes depending on
945 * existence of certain environment and global variables.
946 * Also silently try the old filename in each directory.
947 * If the site config file is never found, return FALSE,
948 * meaning 'fatal error', and an error msg.
950 * (1) The first place to look is a prespecified, fully qualified
951 * name passed by the initialization function. That occurs when
952 * the global OE_sitecnfg_fname, which otherwise would be NULL,
953 * points to the passed arg. It's a fatal error if this name
954 * was specified but cannot be opened.
956 if (OE_sitecnfg_fname) {
959 PROGNAME "1446 ocfopen '%s', prespecified file name.\n",
961 if (ocfopen (NULL, NULL, &stream))
967 /* (2) try to find file in DTSROCFPATH directory */
968 p = getenv ("DTSROCFPATH");
970 fprintf (aa_stderr, PROGNAME "1753 ocfopen '%s'. DTSROCFPATH='%s'.\n",
971 FNAME_SITECONFIG, NULLORSTR (p));
972 if (ocfopen (p, FNAME_SITECONFIG, &stream))
974 if (ocfopen (p, FNAME_SITECONFIG_OLD, &stream))
977 /* (3) try to find file in current working directory */
978 if (getcwd (inbuf, sizeof (inbuf)) == NULL)
979 strcpy (inbuf, "./"); /* default to 'local' dir */
980 else if (inbuf[0] == 0)
981 strcpy (inbuf, "/"); /* presume 'root' dir */
983 fprintf (aa_stderr, PROGNAME "1771 ocfopen '%s'. cwd='%s'.\n",
984 FNAME_SITECONFIG, inbuf);
985 if (ocfopen (inbuf, FNAME_SITECONFIG, &stream))
987 if (ocfopen (inbuf, FNAME_SITECONFIG_OLD, &stream))
990 /* (4) try to find file in HOME directory */
993 fprintf (aa_stderr, "ocfopen '%s'. HOME='%s'.\n",
994 FNAME_SITECONFIG, NULLORSTR (q));
995 if (ocfopen (q, FNAME_SITECONFIG, &stream))
997 if (ocfopen (q, FNAME_SITECONFIG_OLD, &stream))
1000 /* (5) try to find file in server daemon's inittab directory */
1002 fprintf (aa_stderr, "ocfopen '%s'. OE_inittab_dir='%s'.\n",
1003 FNAME_SITECONFIG, NULLORSTR (OE_inittab_dir));
1004 if (ocfopen (OE_inittab_dir, FNAME_SITECONFIG, &stream))
1006 if (ocfopen (OE_inittab_dir, FNAME_SITECONFIG_OLD, &stream))
1009 /* (6) try to find file in server daemon's inetd.conf directory */
1011 fprintf (aa_stderr, "ocfopen '%s'. OE_server_dir='%s'.\n",
1012 FNAME_SITECONFIG, NULLORSTR (OE_server_dir));
1013 if (ocfopen (OE_server_dir, FNAME_SITECONFIG, &stream))
1015 if (ocfopen (OE_server_dir, FNAME_SITECONFIG_OLD, &stream))
1018 /* If we can't find site config on OE side we must quit. */
1019 sprintf (sprintbuf, catgets (dtsearch_catd, MS_loadocf, 1643,
1020 "%1$sCannot find or open '%2$s'\n"
1021 " configuration file in any of the following locations:\n"
1022 " DTSROCFPATH directory = %3$s,\n"
1023 " current working directory = %4$s,\n"
1024 " HOME directory = %5$s,\n"
1025 " /etc/inittab directory = %6$s\n"
1026 " /etc/inetd.conf directory = %7$s\n"
1030 ,(p) ? p : catgets (dtsearch_catd, MS_misc, 16,
1031 "<no environment variable>")
1033 ,(q) ? q : catgets (dtsearch_catd, MS_misc, 16,
1034 "<no environment variable>")
1035 ,(OE_inittab_dir) ? OE_inittab_dir :
1036 catgets (dtsearch_catd, MS_misc, 17,
1037 "<no server daemon>")
1038 ,(OE_server_dir) ? OE_server_dir :
1039 catgets (dtsearch_catd, MS_misc, 17,
1040 "<no server daemon>")
1042 DtSearchAddMessage (sprintbuf);
1047 /* MAIN LOOP ---- Read each line from file */
1049 while (fgets (inbuf, sizeof (inbuf) - 1, stream) != NULL) {
1050 /* terminate string just to be sure */
1051 if (strlen(inbuf) && inbuf[strlen(inbuf)-1] == '\n')
1052 inbuf[strlen(inbuf)-1] = '\0';
1054 /* test for comment line */
1055 if (strchr (COMMENT_CHARS, inbuf[0]))
1059 if ((token = _XStrtok(inbuf, DELIMITERS, strtok_buf)) == NULL)
1061 strcpy (uprtoken, token);
1064 if (strcmp (uprtoken, "PATH") == 0) {
1065 if (read_database (uprtoken, &strtok_buf))
1066 read_path (&strtok_buf);
1069 if (strcmp (uprtoken, "KEYTYPES") == 0) {
1070 if (read_database (uprtoken, &strtok_buf))
1071 read_keytypes (MAX_KTCOUNT, &strtok_buf);
1074 if (strcmp (uprtoken, "KEYTYPE") == 0) {
1075 if (read_database (uprtoken, &strtok_buf))
1076 read_keytypes (1, &strtok_buf);
1079 if (strcmp (uprtoken, "FILEIO") == 0) {
1080 set_fileio (&strtok_buf);
1083 if (strcmp (uprtoken, "USERNOTES") == 0) {
1084 set_boolint (&OE_enable_usernotes, uprtoken, &strtok_buf);
1087 if (strcmp (uprtoken, "MARKDEL") == 0) {
1088 set_boolint (&OE_enable_markdel, uprtoken, &strtok_buf);
1091 if (strcmp (uprtoken, "FASTDECODE") == 0) {
1092 set_boolint (&OE_fastdecode, uprtoken, &strtok_buf);
1095 if (strcmp (uprtoken, "NOITERATE") == 0) {
1096 set_boolbit (&OE_flags, OE_NO_ITERATE, uprtoken, &strtok_buf);
1099 if (strcmp (uprtoken, "UPPERKEYS") == 0) {
1100 set_boolint (&OE_uppercase_keys, uprtoken, &strtok_buf);
1103 if (strcmp (uprtoken, "AUDIT") == 0) {
1104 set_boolbit (&OE_flags, OE_AUDIT, uprtoken, &strtok_buf);
1107 if (strcmp (uprtoken, "FILEPATH") == 0) {
1108 read_filepath (&strtok_buf);
1111 if (strcmp (uprtoken, "WHITLIM") == 0) {
1112 set_long (&OE_words_hitlimit, uprtoken, &strtok_buf);
1115 if (strcmp (token, "d3bug") == 0) {
1116 usrblk.debug |= atol (token + strlen (token) + 1);
1117 printf (PROGNAME "1630 %s: usrblk.debug = %ld, x%08lx.\n",
1118 cfgfname, usrblk.debug, usrblk.debug);
1121 if (strcmp (uprtoken, "MAXHITS") == 0) {
1122 if (read_database (uprtoken, &strtok_buf))
1123 read_maxhits (&strtok_buf);
1126 if (strcmp (uprtoken, "LABEL") == 0) {
1127 if (read_database (uprtoken, &strtok_buf))
1128 read_rest_of_line (uprtoken, &db->label, &strtok_buf);
1132 /* if we made it this far, the first token is unknown */
1133 sprintf (sprintbufp,
1134 catgets (dtsearch_catd, MS_loadocf, 495,
1135 "%s %s: '%.16s' is invalid keyword.\n"),
1136 PROGNAME"495", cfgfname, token);
1137 DtSearchAddMessage (sprintbufp);
1142 } /* ...keep reading next line in file until eof */
1146 /* In a site config file, SOME database has to have been specified.
1147 * Also for each database, KEYTYPES must be present and perfect.
1148 * If no keytypes survived the KEYTYPES parse for each database,
1149 * or if there was no KEYTYPES line for a database
1150 * in site config file, remove the dblk and mark fatal error.
1152 if (usrblk.dblist == NULL) {
1153 sprintf (sprintbufp, catgets (dtsearch_catd, MS_loadocf, 1869,
1154 "%s %s: Configuration file must specify at least one database."),
1155 PROGNAME"1869", cfgfname);
1156 DtSearchAddMessage (sprintbufp);
1160 for (db = usrblk.dblist; db != NULL; db = db->link) {
1161 if (db->ktcount <= 0) {
1162 sprintf (sprintbufp, catgets (dtsearch_catd, MS_loadocf, 986,
1163 "%s %s: KEYTYPES missing for database '%s'."),
1164 PROGNAME"986", cfgfname, db->name);
1165 DtSearchAddMessage (sprintbufp);
1166 cutnode_llist ((LLIST *)db, (LLIST **)&usrblk.dblist);
1177 printf (PROGNAME "516 leaving load_ocf().\n");
1183 usrblk.dblk = usrblk.dblist; /* init usrblk.dblk */
1187 /*************************** OCF.C ****************************/