/* * CDE - Common Desktop Environment * * Copyright (c) 1993-2012, The Open Group. All rights reserved. * * These libraries and programs are free software; you can * redistribute them and/or modify them under the terms of the GNU * Lesser General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) * any later version. * * These libraries and programs are distributed in the hope that * they will be useful, but WITHOUT ANY WARRANTY; without even the * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public * License along with these libraries and programs; if not, write * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth * Floor, Boston, MA 02110-1301 USA */ /* * COMPONENT_NAME: austext * * FUNCTIONS: add_a_keytype * dumpboth * dumpoef * load_ocf * obsolete_keyword * ocfopen * parse_boolean * read_database * read_filepath * read_keytypes * read_maxhits * read_path * read_rest_of_line * set_boolbit * set_boolint * set_fileio * set_int * set_long * * ORIGINS: 27 * * (C) COPYRIGHT International Business Machines Corp. 1991,1995 * All Rights Reserved * US Government Users Restricted Rights - Use, duplication or * disclosure restricted by GSA ADP Schedule Contract with IBM Corp. */ /*************************** OCF.C *************************** * $TOG: ocf.c /main/9 1998/04/17 11:26:02 mgreess $ * August 1991. * Load_ocf() reads an engine's "site configuration file" (.ocf), * parses its contents, and returns a ptr to a list of * DBLKs containing the file's info. * Returns TRUE if .ocf file format is acceptable and everything worked. * Returns FALSE if file contains fatal errors. If file is ok, also * returns a list of dblks in global usrblk and sets some global variables. * The name and path of config file can be specified * or generated in a number of convenient ways. * The theory is: as many options as possible are in the config file * rather than command lines, etc. * Note: User configuration files are no longer supported. * * $Log$ * Revision 2.6 1996/03/05 21:12:01 miker * Reversed meaning of ascii_charmap test. * * Revision 2.5 1996/03/05 18:02:46 miker * Repl ctype functions with refs to ascii_charmap and COMMENT_CHARS. * * Revision 2.4 1996/02/05 16:34:57 miker * Silently try old file name when looking for site config file. * * Revision 2.3 1995/10/25 15:39:33 miker * Added prolog. * * Revision 2.2 1995/10/03 21:40:15 miker * Cosmetic msg change only. * * Revision 2.1 1995/09/22 21:30:12 miker * Freeze DtSearch 0.1, AusText 2.1.8 * * Revision 1.3 1995/09/05 21:41:59 miker * Changed environment variable OCFPATH to DTSROCFPATH. * * Revision 1.2 1995/09/05 18:46:13 miker * Moved all documentation to ocf.doc. * * Revision 1.1 1995/08/31 21:07:25 miker * Initial revision (renamed ocf.c from loadocf.c). * * *Log: loadocf.c,v * * Revision 1.19 1995/07/19 21:12:34 miker * 2.1.6c: Cleaned up documentation to match actual current capabilities. * Obsoleted MAILFEATURE and PRINTSERVER keywords. * * Revision 1.18 1995/07/18 22:52:17 miker * Added ability to open prespecified OE_sitecnfg_fname. */ #include "SearchE.h" #include #include #define X_INCLUDE_STRING_H #define XOS_USE_NO_LOCKING #include #include #include /* for POSIX getcwd() */ #include char *strupr (char *s); /*****#define DEBUG_DUMP******/ /********#define DEBUG_OEF**********/ #define PROGNAME "OCF" #define DELIMITERS " =,\t\n" #define NEGLOGHALF (-.69314718F) /* negative natural log of .5 */ #define FNAME_SITECONFIG_OLD "austext.ocf" #define MS_misc 1 #define MS_loadocf 8 /*-------------------- STATIC GLOBALS ----------------------*/ static DBLK *db; /* curr database/dict */ static char *cfgfname; static char *sprintbufp; static char *token; static int fatal_error; static int debug_ocf = FALSE; /*-------------------- ENGINE GLOBALS ---------------------- * These are globals which must be accessed by both sides. * Globals unique to the engine are in oe.c. */ char *OE_server_dir = NULL; char *OE_inittab_dir = NULL; /*-------------------- OEF TABLE ----------------------*/ /*** (struct typdef located in oe.h) { char *id; keyword identifier char **OEFptr; addr of variable to change char previously_specified; bool ensures only one spec } OEFTAB; ********/ OEFTAB oef_table[] = { { "AUDIT", &OEF_audit, FALSE, }, { "DISCARD", &OEF_discard, FALSE, }, { "NEWS", &OEF_news, FALSE, }, { "NOTESNOT", &OEF_notesnot, FALSE, }, { "NOTESSEM", &OEF_notessem, FALSE, }, { "README", &OEF_readme, FALSE, }, { NULL, NULL, FALSE }, /* end of list */ }; #ifdef DEBUG_DUMP /* for debugging only */ /****************************************/ /* */ /* dumpboth */ /* */ /****************************************/ static void dumpboth (void) { char typestring[4 * MAX_KTCOUNT + 2]; int i; char *ptr; LLIST *m; DBLK *d; printf ("\nDUMPBOTH> fatal_error=%d, msglist=%p, dblist=%p\n", fatal_error, ausapi_msglist, usrblk.dblist); printf ("%s\n", DtSrGetMessages ()); DtSrFreeMessages (); for (d = usrblk.dblist; d != NULL; d = d->link) { ptr = typestring; for (i = 0; i < d->ktcount; i++) { *ptr++ = (d->keytypes[i].is_selected) ? '*' : ' '; *ptr++ = d->keytypes[i].ktchar; *ptr++ = ' '; } *ptr = 0; printf ("DBLK at %p link=%p name='%s' max=%d\n" " keytypes='%s', path='%s'\n", d, d->link, d->name, d->maxhits, typestring, NULLORSTR (d->path)); } printf ("Push any key to continue..."); *typestring = '\0'; fgets (typestring, sizeof(typestring), stdin); if (strlen(typestring) && typestring[strlen(typestring)-1] == '\n') typestring[strlen(typestring)-1] = '\0'; printf ("\n\n\n"); return; } /* dumpboth() */ #endif #ifdef DEBUG_OEF /* for debugging only */ /****************************************/ /* */ /* dumpoef */ /* */ /****************************************/ static void dumpoef (char *before_after) { OEFTAB *oef; fprintf (aa_stderr, "\toef_table[] %s (* = changed strings)\n", before_after); for (oef = oef_table; oef->id != NULL; oef++) { fprintf (aa_stderr, "\t%10s = %c'%s'\n", oef->id, (oef->previously_specified) ? '*' : ' ', *(oef->OEFptr)); } fputc ('\n', aa_stderr); return; } /* dumpoef() */ #endif /****************************************/ /* */ /* parse_boolean */ /* */ /****************************************/ /* Forces token to upper case. * Returns +1 for TRUE, -1 for FALSE, and 0 for neither. */ static int parse_boolean (char *token) { /* Completely missing token defaults to affirmative */ if (token == NULL) return +1; strupr (token); switch (token[0]) { case 'O': /* on, off */ if (token[1] == 'N') return +1; else if (token[1] == 'F') return -1; else return 0; case 'T': /* true */ case 'Y': /* yes */ case 'E': /* enabled */ case '1': /* (one) */ return +1; case 'F': /* false */ case 'N': /* no */ case 'D': /* disabled */ case '0': /* (zero) */ return -1; default: return 0; } } /* parse_boolean() */ /****************************************/ /* */ /* read_database */ /* */ /****************************************/ /* Validates next token as database name. * If not valid name, returns FALSE. * Otherwise chains down through the database list * looking for the one whose name matches the token. * If a match is found, sets db to it, returns TRUE. * If no match is found, creates and initializes * new structure, sets db to it, returns TRUE. */ static int read_database (char *keyword, _Xstrtokparams *strtok_buf) { DBLK **linkptr; if ((token = _XStrtok(NULL, DELIMITERS, *strtok_buf)) == NULL) { sprintf (sprintbufp, CATGETS(dtsearch_catd, MS_loadocf, 477, "%s %s: Missing database name after '%s' keyword.\n"), PROGNAME"477", cfgfname, keyword); DtSearchAddMessage (sprintbufp); fatal_error = TRUE; return FALSE; } if (strlen (token) > 8) { sprintf (sprintbufp, CATGETS(dtsearch_catd, MS_loadocf, 184, "%s %s: More than 8 characters in Database name '%.16s'.\n"), PROGNAME"184", cfgfname, token); DtSearchAddMessage (sprintbufp); fatal_error = TRUE; return FALSE; } /* Chain down the list looking for previously defined database structure */ linkptr = &usrblk.dblist; for (db = usrblk.dblist; db != NULL; db = db->link) { if (strcmp (db->name, token) == 0) return TRUE; linkptr = &db->link; } /* Didn't find matching dblk so allocate and initialize new one at * end of list (linkptr). Use system defaults for most values. */ if (debug_ocf) fprintf (aa_stderr, PROGNAME "204 " "%s: creating dblk for '%s'\n", cfgfname, token); db = austext_malloc (sizeof (DBLK) + 8, PROGNAME "205", NULL); memset (db, 0, sizeof (DBLK)); strcpy (db->name, token); db->is_selected = TRUE; *linkptr = db; return TRUE; } /* read_database() */ /****************************************/ /* */ /* set_boolbit */ /* */ /****************************************/ static void set_boolbit (long *flagvar, long mask, char *flagname, _Xstrtokparams *strtok_buf) { int i; token = _XStrtok(NULL, DELIMITERS, *strtok_buf); i = parse_boolean (token); if (i > 0) *flagvar |= mask; /* switch ON */ else if (i < 0) *flagvar &= ~mask; /* switch OFF */ else { sprintf (sprintbufp, CATGETS(dtsearch_catd, MS_loadocf, 352, "%s %s: Invalid %s value, line ignored.\n"), PROGNAME"352", cfgfname, flagname); DtSearchAddMessage (sprintbufp); } return; } /* set_boolbit() */ /****************************************/ /* */ /* set_int */ /* */ /****************************************/ static void set_int (int *intvar, char *keyword, _Xstrtokparams *strtok_buf) { int myint; if ((token = _XStrtok(NULL, DELIMITERS, *strtok_buf)) == NULL) { token = CATGETS(dtsearch_catd, MS_loadocf, 140, "(missing)"); ERR_MSG: sprintf (sprintbufp, CATGETS(dtsearch_catd, MS_loadocf, 610, "%s %s: %s value is '%s'. " "Should be positive integer. Line ignored."), PROGNAME"844", cfgfname, keyword, token); DtSearchAddMessage (sprintbufp); return; } if ((myint = atoi (token)) <= 0L) goto ERR_MSG; *intvar = myint; return; } /* set_int() */ /****************************************/ /* */ /* set_long */ /* */ /****************************************/ static void set_long (long *longvar, char *keyword, _Xstrtokparams *strtok_buf) { long longi; if ((token = _XStrtok(NULL, DELIMITERS, *strtok_buf)) == NULL) { token = CATGETS(dtsearch_catd, MS_loadocf, 140, "(missing)"); ERR_MSG: sprintf (sprintbufp, CATGETS(dtsearch_catd, MS_loadocf, 610, "%s %s: %s value is '%s'. " "Should be positive integer. Line ignored."), PROGNAME"610", cfgfname, keyword, token); DtSearchAddMessage (sprintbufp); return; } if ((longi = atol (token)) <= 0L) goto ERR_MSG; *longvar = longi; return; } /* set_long() */ /****************************************/ /* */ /* set_boolint */ /* */ /****************************************/ static void set_boolint (int *boolint, char *keyword, _Xstrtokparams *strtok_buf) { int i; token = _XStrtok(NULL, DELIMITERS, *strtok_buf); i = parse_boolean (token); if (i > 0) *boolint = TRUE; /* switch ON */ else if (i < 0) *boolint = FALSE; /* switch OFF */ else { sprintf (sprintbufp, CATGETS(dtsearch_catd, MS_loadocf, 352, "%s %s: Invalid %s value, line ignored.\n"), PROGNAME"352", cfgfname, keyword); DtSearchAddMessage (sprintbufp); } return; } /* set_boolint() */ /****************************************/ /* */ /* set_fileio */ /* */ /****************************************/ /* sets OE_fileio string pointer */ static void set_fileio (_Xstrtokparams *strtok_buf) { /* if a value is missing, presume -ON */ if ((token = _XStrtok(NULL, DELIMITERS, *strtok_buf)) == NULL) { OE_fileio = "-ON"; return; } /* check for hardcoded path name (anything that doesn't begin with '-') */ if (token[0] != '-') { OE_fileio = austext_malloc (strlen (token) + 2, PROGNAME "592", NULL); strcpy (OE_fileio, token); return; } strupr (token); if (strcmp (token, "-ON") == 0) OE_fileio = "-ON"; else if (strcmp (token, "-OFF") == 0) OE_fileio = "-OFF"; else if (strcmp (token, "-HOME") == 0) OE_fileio = "-HOME"; else { sprintf (sprintbufp, CATGETS(dtsearch_catd, MS_loadocf, 607, "%s %s: Invalid FILEIO value. " "User file reads and writes prohibited."), PROGNAME"607", cfgfname); DtSearchAddMessage (sprintbufp); OE_fileio = "-OFF"; } return; } /* set_fileio() */ /****************************************/ /* */ /* read_rest_of_line */ /* */ /****************************************/ /* Malloc a copy of the rest of the input line after * the current token and set passed string ptr to it. */ static void read_rest_of_line (char *keyword, char **passed_ptr, _Xstrtokparams *strtok_buf) { if ((token = _XStrtok(NULL, "\n", *strtok_buf)) == NULL) { sprintf (sprintbufp, CATGETS(dtsearch_catd, MS_loadocf, 1007, "%s%s: Empty %s string ignored."), PROGNAME"1007 ", cfgfname, keyword); DtSearchAddMessage (sprintbufp); return; } *passed_ptr = austext_malloc (strlen(token) + 4, PROGNAME"1020", NULL); strcpy (*passed_ptr, token); return; } /* read_rest_of_line() */ /****************************************/ /* */ /* read_filepath */ /* */ /****************************************/ static void read_filepath (_Xstrtokparams *strtok_buf) { char *errp; char *newpath; int tabx; int toklen; /* Second token on line should be valid id word. * Set tabx to matching oef table entry. */ if ((token = _XStrtok(NULL, DELIMITERS, *strtok_buf)) == NULL) { token = CATGETS(dtsearch_catd, MS_loadocf, 142, "rest of line"); errp = CATGETS(dtsearch_catd, MS_loadocf, 143, "is empty"); IGNORE_FILEPATH: sprintf (sprintbufp, CATGETS(dtsearch_catd, MS_loadocf, 903, "%s %s: FILEPATH '%s' %s. Line ignored."), PROGNAME"903", cfgfname, token, errp); DtSearchAddMessage (sprintbufp); return; } strupr (token); for (tabx = 0; oef_table[tabx].id != NULL; tabx++) { if (strcmp (oef_table[tabx].id, token) == 0) break; } if (oef_table[tabx].id == NULL) { errp = CATGETS(dtsearch_catd, MS_loadocf, 165, "unknown id"); goto IGNORE_FILEPATH; } if (oef_table[tabx].previously_specified) { errp = CATGETS(dtsearch_catd, MS_loadocf, 166, "previously specified"); goto IGNORE_FILEPATH; } /* Third token should be either a directory path (ends in slash) * or a directory path plus a file name (does not end in slash). */ if ((token = _XStrtok(NULL, DELIMITERS, *strtok_buf)) == NULL) { token = oef_table[tabx].id; errp = CATGETS(dtsearch_catd, MS_loadocf, 168, "missing path specification"); goto IGNORE_FILEPATH; } toklen = strlen (token); /* Allocate buffer for new path string and initialize it. * Leave enough extra room for the default, dos-format file name, * i.e. 8 chars, a period, and a 3 char extension. */ newpath = austext_malloc (toklen + 20, PROGNAME "956", NULL); strcpy (newpath, token); if (token[toklen - 1] == LOCAL_SLASH) { strncpy (newpath + toklen, *(oef_table[tabx].OEFptr), 12); newpath[toklen + 12] = 0; } /* Setting the previously_specified flag not only prevents multiple * specifications in a single file, but also permits user files * to override site files for specific ids because loadocf is always * called by the ui before it is called by oe initialization. */ *(oef_table[tabx].OEFptr) = newpath; oef_table[tabx].previously_specified = TRUE; return; } /* read_filepath() */ /****************************************/ /* */ /* read_path */ /* */ /****************************************/ static void read_path (_Xstrtokparams *strtok_buf) { #ifdef DEBUG_DUMP printf (PROGNAME "217> Entering read_path().\n"); #endif /* parse the path for this dictionary/database */ if ((token = _XStrtok(NULL, DELIMITERS, *strtok_buf)) == NULL) { sprintf (sprintbufp, CATGETS(dtsearch_catd, MS_loadocf, 221, "%s %s: Database '%s', No PATH specified, statement ignored.\n"), PROGNAME"221", cfgfname, db->name); DtSearchAddMessage (sprintbufp); return; } db->path = austext_malloc (strlen (token) + 4, PROGNAME "244", NULL); strcpy (db->path, token); ensure_end_slash (db->path); return; } /* read_path() */ /****************************************/ /* */ /* obsolete_keyword */ /* */ /****************************************/ /* append warning msg: passed keyword no longer used */ static void obsolete_keyword (char *keyword) { sprintf (sprintbufp, CATGETS(dtsearch_catd, MS_loadocf, 1, "%1$s%2$s: %3$s keyword is obsolete."), PROGNAME "001 ", cfgfname, keyword); DtSearchAddMessage (sprintbufp); return; } /* obsolete_keyword() */ /****************************************/ /* */ /* read_maxhits */ /* */ /****************************************/ static void read_maxhits (_Xstrtokparams *strtok_buf) { int i; #ifdef DEBUG_DUMP printf (PROGNAME "292> Entering read_maxhits().\n"); #endif /* parse the max number of hits for this dictionary */ if ((token = _XStrtok(NULL, DELIMITERS, *strtok_buf)) == NULL) { INVALID_MAXHITS: sprintf (sprintbufp, CATGETS(dtsearch_catd, MS_loadocf, 304, "%s %s: Database '%s', invalid MAXHITS value.\n"), PROGNAME"304", cfgfname, db->name); DtSearchAddMessage (sprintbufp); fatal_error = TRUE; return; } i = atoi (token); if (i <= 0) goto INVALID_MAXHITS; else db->maxhits = i; return; } /* read_maxhits() */ /****************************************/ /* */ /* add_a_keytype */ /* */ /****************************************/ /* Subroutine of read_keytypes(). * Concatenates a new DtSrKeytype node to end of current * db->keytypes array (in effect, remallocs db->keytypes). * Initializes ktchar with passed character. * Initializes name string with a generic label derived * from ktchar, which may later be changed by read_keytypes(). * Keeps db->ktcount current. * If duplicate ktchar already exists, adds warning msg to * msglist, but changes nothing and returns index of old node. * Returns index of DtSrKeytype node or -1 on error. */ static int add_a_keytype (char ktchar) { DtSrKeytype *kt; int i, newindex; /* Make sure we have not exceeded max number of keytypes */ if (db->ktcount >= MAX_KTCOUNT) { sprintf (sprintbufp, CATGETS(dtsearch_catd, MS_loadocf, 732, "%s %s: Database '%s', No more than %d keytypes allowed.\n"), PROGNAME"732", cfgfname, db->name, MAX_KTCOUNT); DtSearchAddMessage (sprintbufp); fatal_error = TRUE; return -1; } /* Make sure ktchar is alphanumeric */ if ( (ascii_charmap[ktchar] & (CONSONANT | VOWEL | NUMERAL)) == 0) { if (!isprint (ktchar)) ktchar = '?'; sprintf (sprintbufp, CATGETS(dtsearch_catd, MS_loadocf, 684, "%s %s: Database '%s',\n Invalid KEYTYPE character '%c'."), PROGNAME"684", cfgfname, db->name, ktchar); DtSearchAddMessage (sprintbufp); fatal_error = TRUE; return -1; } /* Test for duplicate, preexisting keytype */ kt = db->keytypes; for (i = 0; i < db->ktcount; i++) if (ktchar == kt[i].ktchar) { sprintf (sprintbufp, CATGETS(dtsearch_catd, MS_loadocf, 1002, "%s %s: Database '%s', Duplicate KEYTYPE character '%c'.\n"), PROGNAME"1002", cfgfname, db->name, ktchar); DtSearchAddMessage (sprintbufp); return i; } /* Append valid new keytype to the keytypes array */ i = sizeof(DtSrKeytype) * db->ktcount; /* size of current array */ kt = austext_malloc (i + sizeof(DtSrKeytype) + 4, PROGNAME "699", NULL); if (db->keytypes != NULL) { memcpy (kt, db->keytypes, i); free (db->keytypes); } newindex = db->ktcount; kt[newindex].is_selected = TRUE; kt[newindex].ktchar = ktchar; sprintf (kt[newindex].name, CATGETS(dtsearch_catd, MS_loadocf, 457, "'%c' Records"), ktchar); /* Warn about inaccessible lowercase ktchars */ if ( ((ascii_charmap[ktchar] & 0xff) != ktchar) && OE_uppercase_keys ) { sprintf (sprintbufp, CATGETS(dtsearch_catd, MS_loadocf, 1011, "%s %s: Database '%s': Records with lowercase\n" " KEYTYPE character '%c' will be inaccessible.\n" " Set UPPERKEYS = FALSE if lowercase keys are intended."), PROGNAME"1011", cfgfname, db->name, ktchar); DtSearchAddMessage (sprintbufp); } db->keytypes = kt; db->ktcount++; return newindex; } /* add_a_keytype() */ /****************************************/ /* */ /* read_keytypes */ /* */ /****************************************/ /* Builds keytypes arrays in current dblk. * Parameter 'how_many' limits the number keytype additions. * For example if how_many == 1, only 1 keytype will be added * and the balance of the line will be ignored. * We also quit adding keytypes when the total reaches * MAX_KTCOUNT or when we hit end of line or comments. */ static void read_keytypes (int how_many, _Xstrtokparams *strtok_buf) { /* 'last_ktchar' is index to db->keytypes. if last_ktchar < 0 * then last token was not a ktchar, or it was an invalid ktchar. */ int last_ktchar = -1; DtSrKeytype *kt; char *charptr; #ifdef DEBUG_DUMP printf (PROGNAME "361> Entering read_keytypes().\n"); #endif /* parsing loop for each keytypes token */ while ((token = _XStrtok(NULL, DELIMITERS, *strtok_buf)) != NULL) { /* quit when comments begin */ if (*token == '*' || *token == ':') break; /* Test for ktchar token (beginning with a single quote) */ if (*token == '\'') { if (how_many <= 0) break; /* don't exceed our quota */ last_ktchar = add_a_keytype (token[1]); if (last_ktchar >= 0) how_many--; continue; } /* * Token is a name string. If the last token was NOT a ktchar in * single quotes, or it was an invalid ktchar, then create a new * keytypes entry with the ktchar equal to the first char of this * label. If any err, don't update the name string. */ if (last_ktchar < 0) { if (how_many <= 0) break; /* don't exceed our quota */ last_ktchar = add_a_keytype (token[0]); if (last_ktchar < 0) continue; else how_many--; } /* * Update the appropriate table entry with the label string. * Convert underscores to spaces. */ kt = &db->keytypes[last_ktchar]; strncpy (kt->name, token, DtSrMAX_KTNAME); kt->name[DtSrMAX_KTNAME] = 0; for (charptr = kt->name; *charptr != 0; charptr++) if (*charptr == '_') *charptr = ' '; last_ktchar = -1; } /* end token parsing loop */ return; } /* read_keytypes() */ /****************************************/ /* */ /* ocfopen */ /* */ /****************************************/ /* Subroutine of load_ocf(). * Attempts to open config file created by concatenating * file name to passed pathname prefix. * If both fields are NULL, tries to open fully qualified * fname prespecified in OE_sitecnfg_fname. * Messages may be appended if some information, like an * environment variable, was found but still couldn't open file. * Loads OE_sitecnfg... fields after successful sitecnfg open. * Returns TRUE if fopen() successful, else FALSE. */ static int ocfopen (char *prefix, char *fname, FILE ** stream) { char fullname[1024]; FILE *fptr; struct stat statbuf; int is_prespecified_fname = (prefix == NULL && fname == NULL); /* * Build a complete path/file name from passed args into fullname * buffer. */ if (is_prespecified_fname) { strncpy (fullname, OE_sitecnfg_fname, sizeof (fullname)); fullname[sizeof (fullname) - 1] = 0; goto GOT_FULLNAME; } if (prefix == NULL) { if (debug_ocf) fprintf (aa_stderr, " --> open not attempted: null prefix.\n"); return FALSE; } strncpy (fullname, prefix, sizeof (fullname)); fullname[sizeof (fullname) - 2] = 0; strcpy (ensure_end_slash (fullname), fname); GOT_FULLNAME: fptr = fopen (fullname, "rt"); if (debug_ocf) { if (fptr == NULL) fprintf (aa_stderr, " --> %s\n", strerror (errno)); else fprintf (aa_stderr, " --> open succeeded!\n"); } /* * If open failed: (1) Append information message if error is * something other than 'cant find file'. (Always retn msg if user * prespecified file name). (2) Return now. */ if (fptr == NULL) { if (errno != ENOENT || is_prespecified_fname) { sprintf (sprintbufp, CATGETS(dtsearch_catd, MS_loadocf, 414, "%s Unable to open configuration file '%s':\n %s."), PROGNAME"414", fullname, strerror(errno)); DtSearchAddMessage (sprintbufp); } return FALSE; } /* Load OE_... fields associated with site config */ if (!is_prespecified_fname) { OE_sitecnfg_fname = austext_malloc (strlen (fullname) + 2, PROGNAME "941", NULL); strcpy (OE_sitecnfg_fname, fullname); } if (fstat (fileno (fptr), &statbuf) == -1) { sprintf (sprintbufp, CATGETS(dtsearch_catd, MS_loadocf, 1404, "%s Status unavailable for configuration file '%s': %s"), PROGNAME"1404", fullname, strerror(errno)); DtSearchAddMessage (sprintbufp); fclose(fptr); return FALSE; } OE_sitecnfg_mtime = statbuf.st_mtime; /* Save file name globally for error msgs */ strcpy (cfgfname, fullname); *stream = fptr; return TRUE; } /* ocfopen() */ /****************************************/ /* */ /* load_ocf */ /* */ /****************************************/ /* This is the only function in this module seen by the outside world. * Returns TRUE if .ocf file format is acceptable and everything worked. * Returns FALSE if file contains fatal errors. If file is ok, also * returns a list of dblks in global usrblk and sets some global variables. */ int load_ocf (void) { char *p, *q; char sprintbuf[1024]; char cfgfnamebuf[1024]; char inbuf[1024]; char uprtoken[128]; FILE *stream; _Xstrtokparams strtok_buf; /* Initialize program globals */ usrblk.dblist = NULL; /* just to be sure */ fatal_error = FALSE; sprintbufp = sprintbuf; cfgfname = cfgfnamebuf; debug_ocf = (usrblk.debug & USRDBG_RARE); #ifdef DEBUG_DUMP puts ("\nentering load_ocf"); dumpboth (); #endif #ifdef DEBUG_OEF dumpoef ("BEFORE"); #endif /* Construct the full pathname/filename and open it. * Try various optional path prefixes depending on * existence of certain environment and global variables. * Also silently try the old filename in each directory. * If the site config file is never found, return FALSE, * meaning 'fatal error', and an error msg. * * (1) The first place to look is a prespecified, fully qualified * name passed by the initialization function. That occurs when * the global OE_sitecnfg_fname, which otherwise would be NULL, * points to the passed arg. It's a fatal error if this name * was specified but cannot be opened. */ if (OE_sitecnfg_fname) { if (debug_ocf) fprintf (aa_stderr, PROGNAME "1446 ocfopen '%s', prespecified file name.\n", OE_sitecnfg_fname); if (ocfopen (NULL, NULL, &stream)) goto OCFOPEN_OK; else return FALSE; } /* (2) try to find file in DTSROCFPATH directory */ p = getenv ("DTSROCFPATH"); if (debug_ocf) fprintf (aa_stderr, PROGNAME "1753 ocfopen '%s'. DTSROCFPATH='%s'.\n", FNAME_SITECONFIG, NULLORSTR (p)); if (ocfopen (p, FNAME_SITECONFIG, &stream)) goto OCFOPEN_OK; if (ocfopen (p, FNAME_SITECONFIG_OLD, &stream)) goto OCFOPEN_OK; /* (3) try to find file in current working directory */ if (getcwd (inbuf, sizeof (inbuf)) == NULL) strcpy (inbuf, "./"); /* default to 'local' dir */ else if (inbuf[0] == 0) strcpy (inbuf, "/"); /* presume 'root' dir */ if (debug_ocf) fprintf (aa_stderr, PROGNAME "1771 ocfopen '%s'. cwd='%s'.\n", FNAME_SITECONFIG, inbuf); if (ocfopen (inbuf, FNAME_SITECONFIG, &stream)) goto OCFOPEN_OK; if (ocfopen (inbuf, FNAME_SITECONFIG_OLD, &stream)) goto OCFOPEN_OK; /* (4) try to find file in HOME directory */ q = getenv ("HOME"); if (debug_ocf) fprintf (aa_stderr, "ocfopen '%s'. HOME='%s'.\n", FNAME_SITECONFIG, NULLORSTR (q)); if (ocfopen (q, FNAME_SITECONFIG, &stream)) goto OCFOPEN_OK; if (ocfopen (q, FNAME_SITECONFIG_OLD, &stream)) goto OCFOPEN_OK; /* (5) try to find file in server daemon's inittab directory */ if (debug_ocf) fprintf (aa_stderr, "ocfopen '%s'. OE_inittab_dir='%s'.\n", FNAME_SITECONFIG, NULLORSTR (OE_inittab_dir)); if (ocfopen (OE_inittab_dir, FNAME_SITECONFIG, &stream)) goto OCFOPEN_OK; if (ocfopen (OE_inittab_dir, FNAME_SITECONFIG_OLD, &stream)) goto OCFOPEN_OK; /* (6) try to find file in server daemon's inetd.conf directory */ if (debug_ocf) fprintf (aa_stderr, "ocfopen '%s'. OE_server_dir='%s'.\n", FNAME_SITECONFIG, NULLORSTR (OE_server_dir)); if (ocfopen (OE_server_dir, FNAME_SITECONFIG, &stream)) goto OCFOPEN_OK; if (ocfopen (OE_server_dir, FNAME_SITECONFIG_OLD, &stream)) goto OCFOPEN_OK; /* If we can't find site config on OE side we must quit. */ sprintf (sprintbuf, CATGETS(dtsearch_catd, MS_loadocf, 1643, "%1$sCannot find or open '%2$s'\n" " configuration file in any of the following locations:\n" " DTSROCFPATH directory = %3$s,\n" " current working directory = %4$s,\n" " HOME directory = %5$s,\n" " /etc/inittab directory = %6$s\n" " /etc/inetd.conf directory = %7$s\n" ) ,PROGNAME "1643 " ,FNAME_SITECONFIG ,(p) ? p : CATGETS(dtsearch_catd, MS_misc, 16, "") ,inbuf ,(q) ? q : CATGETS(dtsearch_catd, MS_misc, 16, "") ,(OE_inittab_dir) ? OE_inittab_dir : CATGETS(dtsearch_catd, MS_misc, 17, "") ,(OE_server_dir) ? OE_server_dir : CATGETS(dtsearch_catd, MS_misc, 17, "") ); DtSearchAddMessage (sprintbuf); return FALSE; OCFOPEN_OK: /* MAIN LOOP ---- Read each line from file */ *inbuf = '\0'; while (fgets (inbuf, sizeof (inbuf) - 1, stream) != NULL) { /* terminate string just to be sure */ if (strlen(inbuf) && inbuf[strlen(inbuf)-1] == '\n') inbuf[strlen(inbuf)-1] = '\0'; /* test for comment line */ if (strchr (COMMENT_CHARS, inbuf[0])) continue; /* parse KEYWORD */ if ((token = _XStrtok(inbuf, DELIMITERS, strtok_buf)) == NULL) continue; snprintf(uprtoken, sizeof(uprtoken), "%s", token); strupr (uprtoken); if (strcmp (uprtoken, "PATH") == 0) { if (read_database (uprtoken, &strtok_buf)) read_path (&strtok_buf); continue; } if (strcmp (uprtoken, "KEYTYPES") == 0) { if (read_database (uprtoken, &strtok_buf)) read_keytypes (MAX_KTCOUNT, &strtok_buf); continue; } if (strcmp (uprtoken, "KEYTYPE") == 0) { if (read_database (uprtoken, &strtok_buf)) read_keytypes (1, &strtok_buf); continue; } if (strcmp (uprtoken, "FILEIO") == 0) { set_fileio (&strtok_buf); continue; } if (strcmp (uprtoken, "USERNOTES") == 0) { set_boolint (&OE_enable_usernotes, uprtoken, &strtok_buf); continue; } if (strcmp (uprtoken, "MARKDEL") == 0) { set_boolint (&OE_enable_markdel, uprtoken, &strtok_buf); continue; } if (strcmp (uprtoken, "FASTDECODE") == 0) { set_boolint (&OE_fastdecode, uprtoken, &strtok_buf); continue; } if (strcmp (uprtoken, "NOITERATE") == 0) { set_boolbit (&OE_flags, OE_NO_ITERATE, uprtoken, &strtok_buf); continue; } if (strcmp (uprtoken, "UPPERKEYS") == 0) { set_boolint (&OE_uppercase_keys, uprtoken, &strtok_buf); continue; } if (strcmp (uprtoken, "AUDIT") == 0) { set_boolbit (&OE_flags, OE_AUDIT, uprtoken, &strtok_buf); continue; } if (strcmp (uprtoken, "FILEPATH") == 0) { read_filepath (&strtok_buf); continue; } if (strcmp (uprtoken, "WHITLIM") == 0) { set_long (&OE_words_hitlimit, uprtoken, &strtok_buf); continue; } if (strcmp (token, "d3bug") == 0) { usrblk.debug |= atol (token + strlen (token) + 1); printf (PROGNAME "1630 %s: usrblk.debug = %ld, x%08lx.\n", cfgfname, usrblk.debug, usrblk.debug); continue; } if (strcmp (uprtoken, "MAXHITS") == 0) { if (read_database (uprtoken, &strtok_buf)) read_maxhits (&strtok_buf); continue; } if (strcmp (uprtoken, "LABEL") == 0) { if (read_database (uprtoken, &strtok_buf)) read_rest_of_line (uprtoken, &db->label, &strtok_buf); continue; } /* if we made it this far, the first token is unknown */ sprintf (sprintbufp, CATGETS(dtsearch_catd, MS_loadocf, 495, "%s %s: '%.16s' is invalid keyword.\n"), PROGNAME"495", cfgfname, token); DtSearchAddMessage (sprintbufp); #ifdef DEBUG_DUMP dumpboth (); #endif } /* ...keep reading next line in file until eof */ fclose (stream); /* In a site config file, SOME database has to have been specified. * Also for each database, KEYTYPES must be present and perfect. * If no keytypes survived the KEYTYPES parse for each database, * or if there was no KEYTYPES line for a database * in site config file, remove the dblk and mark fatal error. */ if (usrblk.dblist == NULL) { sprintf (sprintbufp, CATGETS(dtsearch_catd, MS_loadocf, 1869, "%s %s: Configuration file must specify at least one database."), PROGNAME"1869", cfgfname); DtSearchAddMessage (sprintbufp); fatal_error = TRUE; } else for (db = usrblk.dblist; db != NULL; db = db->link) { if (db->ktcount <= 0) { sprintf (sprintbufp, CATGETS(dtsearch_catd, MS_loadocf, 986, "%s %s: KEYTYPES missing for database '%s'."), PROGNAME"986", cfgfname, db->name); DtSearchAddMessage (sprintbufp); cutnode_llist ((LLIST *)db, (LLIST **)&usrblk.dblist); free (db); fatal_error = TRUE; } } #ifdef DEBUG_OEF dumpoef ("AFTER"); #endif #ifdef DEBUG_DUMP printf (PROGNAME "516 leaving load_ocf().\n"); dumpboth (); #endif if (fatal_error) return FALSE; usrblk.dblk = usrblk.dblist; /* init usrblk.dblk */ return TRUE; } /* load_ocf() */ /*************************** OCF.C ****************************/