mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
CDE has relied upon catgets() implementations following a relaxed interpretation of the XPG internationalization standard that ignored -1, the standard error value returned by catopen, as the catalog argument. However, this same behavior causes segmentation faults with the musl C library. This patch: - Centralizes (with the exception of ToolTalk) all calls to catopen(), catgets(), and catclose() through MsgCat within the DtSvc library. - Prevents calls to catgets() and catclose() that rely upon undefined behavior. - Eliminates a number of bespoke catgets() wrappers, including multiple redundant caching implementations designed to work around a design peculiarity in HP/UX. - Eases building CDE without XPG internationalization support by providing the appropriate macros.
879 lines
26 KiB
C
879 lines
26 KiB
C
/*
|
|
* 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: DtSearchGetKeytypes
|
|
* DtSearchHighlight
|
|
* DtSearchInit
|
|
* DtSearchQuery
|
|
* DtSearchRetrieve
|
|
* aa_categories
|
|
* aa_is_semantic_db
|
|
* aa_netrc
|
|
* aa_reinit
|
|
* ausapi_get_hirec
|
|
* ausapi_getexpire
|
|
* ausapi_getnews
|
|
* both_valid_dates
|
|
* build_dbnames_array
|
|
* pack_navstr
|
|
* signal_abort
|
|
* valid_dbname
|
|
*
|
|
* ORIGINS: 27
|
|
*
|
|
*
|
|
* (C) COPYRIGHT International Business Machines Corp. 1993,1995
|
|
* All Rights Reserved
|
|
* Licensed Materials - Property of IBM
|
|
* US Government Users Restricted Rights - Use, duplication or
|
|
* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
|
|
*/
|
|
/**************************** DTSRAPI.C *************************
|
|
* $XConsortium: dtsrapi.c /main/9 1996/11/25 18:54:18 drk $
|
|
* Nov 1993. Originally called "calloe".
|
|
* Implements a simple DtSearch/AusText API at a higher level than OE calls.
|
|
* Substantially isolates caller from knowledge of usrblks,
|
|
* hiding details of searches, possible return codes, etc.
|
|
* Does its own mallocs and frees and controls the usrblk.
|
|
*
|
|
* Function descriptions (ie documentation) is in dtsearch.doc
|
|
* and Search.h.
|
|
*
|
|
* Revision 2.8 1996/03/14 22:54:41 miker
|
|
* Pass backdoor usrblk.debug into DtSearch.
|
|
*
|
|
* Revision 2.7 1996/02/01 18:09:24 miker
|
|
* Deleted ausapi_kwic, ausapi_ping, ausapi_shutdown, signal(SIGUSR1).
|
|
* DtSearchInit: usrblk.debug = high order 16 bits of init_switches arg.
|
|
*
|
|
* Revision 2.6 1995/12/27 16:08:22 miker
|
|
* Added DtSearchReinit().
|
|
*
|
|
* Revision 2.5 1995/10/26 17:34:52 miker
|
|
* Fixed duplicate messages catalog open.
|
|
*
|
|
* Revision 2.4 1995/10/25 21:39:45 miker
|
|
* Renamed from ausapi.c. Added prolog.
|
|
*
|
|
* Log: ausapi.c,v
|
|
* Revision 2.3 1995/10/19 20:19:34 miker
|
|
* Databases opened read-only unless DtSrInRDWR is specified.
|
|
*
|
|
* Revision 2.2 1995/10/02 20:51:32 miker
|
|
* Bug: Tried to free unmalloced version string after Init (Takuki Kamiya).
|
|
* Added symbolic msg catalog set numbers.
|
|
* Fixed erroneous dbnames assignment.
|
|
*
|
|
* Revision 2.1 1995/09/22 18:48:45 miker
|
|
* Freeze DtSearch 0.1, AusText 2.1.8
|
|
*
|
|
* Revision 1.20 1995/09/19 21:43:46 miker
|
|
* Fixed minor bug in debugging statements only.
|
|
*
|
|
* Revision 1.19 1995/08/31 21:36:39 miker
|
|
* Added #define to block out code not to be delivered to DtSearch.
|
|
* Changed all msgslists to one global one at ausapi_msglist.
|
|
* Moved function documentation to dtsearch.doc
|
|
* Public functions renamed to match DtSearch conventions.
|
|
* Rearranged some function args to eliminate public global variables.
|
|
* Broke messages catalog in two so DtSearch can have its own.
|
|
* Minor changes to accommodate portability.
|
|
* Reenabled user to change name of site config file.
|
|
*
|
|
* Revision 1.18 1995/07/18 22:05:10 miker
|
|
* Set OE_sitecnfg_fname to arg passed to ausapi_init().
|
|
*/
|
|
#include "SearchE.h"
|
|
#include <ctype.h>
|
|
#include <signal.h>
|
|
#include <locale.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <fcntl.h>
|
|
|
|
#define PROGNAME "DTSRAPI"
|
|
#define SPRINTBUFSZ 1024
|
|
#define MS_misc 1
|
|
#define MS_ausapi 2
|
|
|
|
/*------------------- PRIVATE GLOBALS ---------------------*/
|
|
/* Usrblk should not be visible to user interface code,
|
|
* but must be visible to real engine... */
|
|
USRBLK usrblk = { { 0 } };
|
|
static int save_search_type = '$';
|
|
static char *sprintbuf = NULL;
|
|
|
|
/*------------------- EXTERNS (aajoint.c) ---------------------*/
|
|
extern int aa_is_initialized;
|
|
extern void aa_check_initialization (void);
|
|
extern long save_init_switches;
|
|
|
|
#ifndef db_oflag
|
|
extern int db_oflag;
|
|
#endif
|
|
|
|
|
|
/************************************************/
|
|
/* */
|
|
/* signal_abort */
|
|
/* */
|
|
/************************************************/
|
|
/* Interrupt handler for all common 'abort' signals.
|
|
* Shuts down gracefully by ensuring database properly closed.
|
|
* The database close and write to the audit log occur in OE.
|
|
*/
|
|
static void signal_abort (int sig)
|
|
{
|
|
fputs (DtSearchGetMessages (), aa_stderr);
|
|
fprintf (aa_stderr, CATGETS(dtsearch_catd, MS_ausapi, 216,
|
|
"\n%s %s Caught signal %d.\n"),
|
|
PROGNAME"216",
|
|
(aa_argv0) ? aa_argv0 : OE_prodname,
|
|
sig);
|
|
fflush (aa_stderr);
|
|
DtSearchExit (100 + sig);
|
|
} /* signal_abort() */
|
|
|
|
|
|
/************************************************/
|
|
/* */
|
|
/* valid_dbname */
|
|
/* */
|
|
/************************************************/
|
|
/* Sets usrblk.dblk to passed dbname.
|
|
* Name must match dblk.label if it exists,
|
|
* otherwise it must match dblk.name (same
|
|
* algorithm that generates dbnamesv[]).
|
|
* If dbname == NULL, sets dblk to first dblist node.
|
|
* Returns TRUE on success.
|
|
* Returns FALSE and err msg if invalid dbname.
|
|
*/
|
|
static int valid_dbname (char *dbname)
|
|
{
|
|
DBLK *db;
|
|
aa_check_initialization ();
|
|
if (dbname == NULL) {
|
|
usrblk.dblk = usrblk.dblist;
|
|
return TRUE;
|
|
}
|
|
if (dbname[0] == 0) {
|
|
usrblk.dblk = usrblk.dblist;
|
|
return TRUE;
|
|
}
|
|
for (db = usrblk.dblist; db != NULL; db = db->link) {
|
|
if (db->label) {
|
|
if (strcmp (dbname, db->label) == 0)
|
|
break;
|
|
}
|
|
if (strcmp (dbname, db->name) == 0)
|
|
break;
|
|
}
|
|
if (db == NULL) {
|
|
sprintf (sprintbuf, CATGETS(dtsearch_catd, MS_ausapi, 1,
|
|
"%1$sInvalid or unavailable database '%2$s'."),
|
|
PROGNAME "48 ", dbname);
|
|
DtSearchAddMessage (sprintbuf);
|
|
if (DtSrInANY_DEBUG & save_init_switches) {
|
|
fputs (PROGNAME "49 Available Databases:\n", aa_stderr);
|
|
for (db = usrblk.dblist; db != NULL; db = db->link)
|
|
fprintf (aa_stderr, " name='%s'\tlabel='%s'\n",
|
|
db->name, db->label);
|
|
}
|
|
return FALSE;
|
|
}
|
|
else
|
|
usrblk.dblk = db;
|
|
return TRUE;
|
|
} /* valid_dbname() */
|
|
|
|
|
|
/************************************************/
|
|
/* */
|
|
/* build_dbnames_array */
|
|
/* */
|
|
/************************************************/
|
|
/* Builds array of database name string ptrs with same
|
|
* architecture as command line arguments argv and argc
|
|
* from the shell. Uses dblk.label if it exists,
|
|
* otherwise uses dblk.name.
|
|
* Called at initialization and reinitialization.
|
|
*/
|
|
static void build_dbnames_array (void)
|
|
{
|
|
char *targ, *src;
|
|
DBLK *db;
|
|
int i;
|
|
size_t mallocsz = 0L;
|
|
|
|
if (ausapi_dbnamesv)
|
|
free (ausapi_dbnamesv);
|
|
ausapi_dbnamesc = 0;
|
|
for (db = usrblk.dblist; db != NULL; db = db->link) {
|
|
ausapi_dbnamesc++;
|
|
mallocsz += ((db->label) ? strlen (db->label) : sizeof (db->name)) + 2L;
|
|
}
|
|
ausapi_dbnamesv = austext_malloc (
|
|
mallocsz + (sizeof (char *) * (2 + ausapi_dbnamesc)) + 4,
|
|
PROGNAME "106", NULL);
|
|
/* The first part of the malloc is the array of pointers.
|
|
* The strings start just after the array. Set 'targ' to
|
|
* the beginning of the strings, while 'i' indexes the ptrs.
|
|
*/
|
|
targ = (char *) ausapi_dbnamesv + (sizeof (char *) * (1 + ausapi_dbnamesc));
|
|
for (i = 0, db = usrblk.dblist; db != NULL; i++, db = db->link) {
|
|
ausapi_dbnamesv[i] = targ;
|
|
src = (db->label) ? db->label : db->name;
|
|
while (*src != 0)
|
|
*targ++ = *src++;
|
|
*targ++ = 0;
|
|
|
|
if (save_init_switches & DtSrInIDEBUG) {
|
|
fprintf (aa_stderr, PROGNAME "490 "
|
|
"dbnames[%d] = '%s': dname='%s', dlabel='%s'\n",
|
|
i, ausapi_dbnamesv[i], db->name, db->label);
|
|
fflush (aa_stderr);
|
|
}
|
|
|
|
}
|
|
ausapi_dbnamesv[i] = NULL; /* terminate the list this way too */
|
|
return;
|
|
} /* build_dbnames_array() */
|
|
|
|
|
|
/************************************************/
|
|
/* */
|
|
/* aa_reinit */
|
|
/* */
|
|
/************************************************/
|
|
/* Performs all reinitialization functions required by OE_REINIT.
|
|
* Always returns DtSrREINIT.
|
|
*/
|
|
static int aa_reinit (void)
|
|
{
|
|
clear_usrblk_record ();
|
|
clear_hitwords ();
|
|
usrblk.dba = 0;
|
|
DtSearchFreeResults (&usrblk.dittolist);
|
|
usrblk.dittocount = 0;
|
|
build_dbnames_array ();
|
|
return DtSrREINIT;
|
|
} /* aa_reinit() */
|
|
|
|
|
|
/************************************************/
|
|
/* */
|
|
/* DtSearchInit */
|
|
/* */
|
|
/************************************************/
|
|
/* Initializes ausapi and the AusText engine (performs OE_INIT).
|
|
* Must be first ausapi call. Must be called only once (reinit?).
|
|
* See dtsearch.doc for specs.
|
|
*/
|
|
int DtSearchInit (
|
|
char *argv0,
|
|
char *userid,
|
|
long switches,
|
|
char *config_file,
|
|
FILE *err_file,
|
|
char ***dbnames,
|
|
int *dbcount)
|
|
{
|
|
if (aa_is_initialized) {
|
|
sprintf (sprintbuf, CATGETS(dtsearch_catd, MS_ausapi, 621,
|
|
"%1$s %2%s has already been initialized."),
|
|
PROGNAME"621", PRODNAME);
|
|
DtSearchAddMessage (sprintbuf);
|
|
return DtSrFAIL;
|
|
}
|
|
|
|
aa_is_initialized = TRUE;
|
|
save_init_switches = switches;
|
|
if (argv0)
|
|
aa_argv0 = argv0;
|
|
if (err_file)
|
|
aa_stderr = err_file;
|
|
else
|
|
aa_stderr = stderr;
|
|
|
|
sprintbuf = austext_malloc (SPRINTBUFSZ, PROGNAME "135", NULL);
|
|
|
|
/* Open msgs and help text catalogs. */
|
|
if (switches & (DtSrInNOLOCALE == 0)) {
|
|
setlocale (LC_ALL, "");
|
|
dtsearch_catd = CATOPEN(FNAME_DTSRCAT, 0);
|
|
}
|
|
|
|
/* Register AusText abort signal handlers.
|
|
* This ensures that if caller is killed,
|
|
* engine will shutdown gracefully.
|
|
*/
|
|
if (switches & DtSrInSIGNAL) {
|
|
if (!(switches & DtSrInENAB_NOHUP))
|
|
signal (SIGHUP, signal_abort); /* trap hangups */
|
|
signal (SIGINT, signal_abort); /* interrupt, ctrl-c */
|
|
signal (SIGQUIT, signal_abort); /* quit, ctrl-d */
|
|
signal (SIGKILL, signal_abort); /* (kill -9, cannot be trapped) */
|
|
signal (SIGTERM, signal_abort); /* kill [-15], sfwr terminate */
|
|
#ifdef SIGPWR
|
|
signal (SIGPWR, signal_abort); /* power failure imminent */
|
|
#endif
|
|
#ifdef _AIX
|
|
signal (SIGXCPU, signal_abort); /* cpu time limit exceeded */
|
|
signal (SIGDANGER, signal_abort); /* imminent paging space crash */
|
|
#endif
|
|
}
|
|
|
|
/* If user name was not passed, get it from LOGNAME environment var */
|
|
if (userid == NULL || *userid == 0)
|
|
if ((userid = (char *) getenv ("LOGNAME")) == NULL) {
|
|
sprintf (sprintbuf, CATGETS(dtsearch_catd, MS_ausapi, 187,
|
|
"%1$s Missing both userid and LOGNAME environment variable."),
|
|
PROGNAME "187 ");
|
|
DtSearchAddMessage (sprintbuf);
|
|
return DtSrFAIL;
|
|
}
|
|
|
|
/* initialize usrblk fields */
|
|
memset (&usrblk, 0, sizeof (USRBLK));
|
|
strncpy (usrblk.userid, userid, 8);
|
|
usrblk.userid[8] = 0;
|
|
usrblk.flags |= USR_NO_INFOMSGS; /* standard for ausapi */
|
|
usrblk.flags |= USR_SORT_WHITL; /* standard for ausapi */
|
|
usrblk.flags |= USR_NO_ITERATE; /* must ALWAYS be on in
|
|
* this api */
|
|
|
|
if (switches & DtSrInIDEBUG)
|
|
usrblk.debug |= USRDBG_RARE;
|
|
if (switches & DtSrInSDEBUG)
|
|
usrblk.debug |= USRDBG_SRCHCMPL;
|
|
if (switches & DtSrInRDEBUG)
|
|
usrblk.debug |= USRDBG_RETRVL;
|
|
/* Secret unadvertised feature. High order 2 bytes
|
|
* are direct settings of lower 2 bytes of usrblk.debug.
|
|
*/
|
|
usrblk.debug |= switches >> 16;
|
|
|
|
/* Set vista's db_oflag from DtSrInRDWR switch.
|
|
* Note the vista flag and the switch are inverses
|
|
* of each other (RDWR vs. RDONLY).
|
|
*/
|
|
if ((switches & DtSrInRDWR) == 0)
|
|
db_oflag = O_RDONLY;
|
|
|
|
/* Prespecify site config file to engine */
|
|
if (config_file)
|
|
OE_sitecnfg_fname = (char *) strdup (config_file);
|
|
|
|
/* initialize AusText Engine */
|
|
usrblk.request = OE_INITIALIZE;
|
|
usrblk.query = AUSAPI_VERSION;
|
|
Opera_Engine ();
|
|
usrblk.query = NULL; /* so we don't try to free it at query time */
|
|
if (usrblk.retncode != OE_OK)
|
|
return DtSrFAIL;
|
|
|
|
build_dbnames_array ();
|
|
if (dbnames) {
|
|
*dbnames = ausapi_dbnamesv;
|
|
if (!dbcount) {
|
|
sprintf (sprintbuf, CATGETS(dtsearch_catd, MS_ausapi, 7,
|
|
"%s dbnames specified but not dbcount."),
|
|
PROGNAME"304");
|
|
DtSearchAddMessage (sprintbuf);
|
|
return DtSrFAIL;
|
|
}
|
|
*dbcount = ausapi_dbnamesc;
|
|
}
|
|
|
|
return DtSrOK;
|
|
} /* DtSearchInit() */
|
|
|
|
|
|
/************************************************/
|
|
/* */
|
|
/* DtSearchReinit */
|
|
/* */
|
|
/************************************************/
|
|
/* Returns pointer to dbnames array.
|
|
* Used after database or config file changes to trigger
|
|
* engine reinitialization and to reaccess the database names.
|
|
*/
|
|
int DtSearchReinit (char ***dbnames, int *dbcount)
|
|
{
|
|
aa_check_initialization();
|
|
usrblk.request = OE_PING;
|
|
Opera_Engine();
|
|
switch (usrblk.retncode) {
|
|
case OE_REINIT:
|
|
if (save_init_switches & DtSrInANY_DEBUG) {
|
|
fputs (PROGNAME"755 "
|
|
"DtSearchReinit: Engine did return REINIT.\n",
|
|
aa_stderr);
|
|
fflush (aa_stderr);
|
|
}
|
|
aa_reinit();
|
|
/* fall thru to OK... */
|
|
|
|
case OE_OK:
|
|
*dbnames = ausapi_dbnamesv;
|
|
*dbcount = ausapi_dbnamesc;
|
|
return DtSrOK;
|
|
|
|
default:
|
|
return DtSrERROR;
|
|
}
|
|
} /* DtSearchReinit() */
|
|
|
|
|
|
/************************************************/
|
|
/* */
|
|
/* DtSearchGetKeytypes */
|
|
/* */
|
|
/************************************************/
|
|
/* Returns pointer to keytypes array of specified database.
|
|
* If dbname == NULL, returns keytypes of first dblist node.
|
|
* Caller may modify is_selected field but should
|
|
* not alter other keytypes fields or pointers.
|
|
*/
|
|
int DtSearchGetKeytypes (
|
|
char *dbname, /* 1 - 8 char database name */
|
|
int *ktcount, /* number entries in array */
|
|
DtSrKeytype **keytypes) /* array of database types */
|
|
{
|
|
if (!valid_dbname (dbname))
|
|
return DtSrREINIT;
|
|
*ktcount = usrblk.dblk->ktcount;
|
|
*keytypes = usrblk.dblk->keytypes;
|
|
return DtSrOK;
|
|
} /* DtSearchGetKeytypes() */
|
|
|
|
|
|
/************************************************/
|
|
/* */
|
|
/* both_valid_dates */
|
|
/* */
|
|
/************************************************/
|
|
/* Subroutine of DtSearchQuery().
|
|
* Sets usrblk.objdate1 and objdate2 from passed date strings.
|
|
* Returns TRUE on successful parse and conversion.
|
|
* Returns FALSE and err msg if either date string is invalid.
|
|
*/
|
|
static int both_valid_dates (char *date1, char *date2)
|
|
{
|
|
int convert_error = FALSE;
|
|
|
|
if ((usrblk.objdate1 = DtSearchValidDateString (date1)) == -1L)
|
|
convert_error = TRUE;
|
|
|
|
if ((usrblk.objdate2 = DtSearchValidDateString (date2)) == -1L)
|
|
convert_error = TRUE;
|
|
|
|
if (!convert_error &&
|
|
usrblk.objdate1 != 0L &&
|
|
usrblk.objdate2 != 0L &&
|
|
usrblk.objdate1 >= usrblk.objdate2) {
|
|
sprintf (sprintbuf, CATGETS(dtsearch_catd, MS_ausapi, 198,
|
|
"%s 'Before' date is equal to or after 'After' date.\n"
|
|
" No records would be returned."),
|
|
PROGNAME "198");
|
|
DtSearchAddMessage (sprintbuf);
|
|
convert_error = TRUE;
|
|
}
|
|
|
|
return !convert_error;
|
|
} /* both_valid_dates() */
|
|
|
|
|
|
/************************************************/
|
|
/* */
|
|
/* DtSearchQuery */
|
|
/* */
|
|
/************************************************/
|
|
/* Returns hitlist (dittolist) if search successful.
|
|
* If dbname is NULL, assumes name from first dblk on dblist.
|
|
* Will work correctly even if arg dittolist == &usrblk.dittolist.
|
|
* Only return hits 'after' date1 and 'before' date2.
|
|
* NULL in one date field means search not limited in that direction.
|
|
* NULL in both date fields means search not restricted by dates.
|
|
* NULL is also permitted in stems, but if stems is
|
|
* not NULL, the passed stems array MUST be defined:
|
|
* char stems [DtSrMAX_STEMCOUNT] [DtSrMAXWIDTH_HWORD].
|
|
* If query is fzkeyi, it must point to
|
|
* array of FZKEYSZ integers.
|
|
* DtSearchQuery() was formerly named ausapi_search().
|
|
*/
|
|
int DtSearchQuery (
|
|
void *qry, /* query, fzkeyi, nav string */
|
|
char *dbname, /* database name from dbnamesv */
|
|
int search_type, /* 'P', 'W', 'S', 'T', 'Z', or 'N' */
|
|
char *date1, /* "yyyy mm dd", 3 numeric tokens */
|
|
char *date2, /* date1 earlier than date2 */
|
|
DtSrResult
|
|
**dittolist, /* put hitlist here */
|
|
long *dittocount, /* put num items on returned hitlist */
|
|
char *stems, /* put stems array here */
|
|
int *stemcount) /* put size of stems array */
|
|
{
|
|
int final_request;
|
|
int i;
|
|
char *ptr;
|
|
DBLK *db;
|
|
LLIST *llp;
|
|
enum { TEXT, NAVSTRING, FZKEYI }
|
|
qryarg;
|
|
# define _DATE1STR_LEN (24)
|
|
char date1str[_DATE1STR_LEN];
|
|
|
|
if (!valid_dbname (dbname))
|
|
return DtSrREINIT;
|
|
|
|
/* Verify valid search_type and set flag
|
|
* to tell us how to interpret 'qry' arg.
|
|
*/
|
|
switch (search_type) {
|
|
case 'P': /* statistical search */
|
|
qryarg = TEXT;
|
|
final_request = OE_SRCH_STATISTICAL;
|
|
break;
|
|
|
|
case 'W': /* exact words search */
|
|
qryarg = TEXT;
|
|
final_request = OE_SRCH_WORDS;
|
|
break;
|
|
|
|
case 'S': /* exact stems search */
|
|
qryarg = TEXT;
|
|
final_request = OE_SRCH_STEMS;
|
|
break;
|
|
|
|
default:
|
|
sprintf (sprintbuf, CATGETS(dtsearch_catd, MS_ausapi, 20,
|
|
"%1$s Invalid search_type '%2$c'."),
|
|
PROGNAME "172 ", search_type);
|
|
DtSearchAddMessage (sprintbuf);
|
|
return DtSrERROR;
|
|
|
|
} /* end switch on search_type */
|
|
|
|
/* Validate the 'qry' argument */
|
|
if (qry == NULL) {
|
|
QUERY_ERROR:
|
|
sprintf (sprintbuf, CATGETS(dtsearch_catd, MS_ausapi, 30,
|
|
"%s Null query. No search performed."),
|
|
PROGNAME"81");
|
|
DtSearchAddMessage (sprintbuf);
|
|
return DtSrFAIL;
|
|
}
|
|
|
|
/* If qry is a char string, it must be nonempty. */
|
|
if (qryarg != FZKEYI && ((char *) qry)[0] == 0)
|
|
goto QUERY_ERROR;
|
|
|
|
/* If qry is text to be sent as is to engine,
|
|
* copy it over now to userblk.
|
|
*/
|
|
if (qryarg == TEXT && qry != usrblk.query) {
|
|
if (usrblk.query != NULL)
|
|
free (usrblk.query);
|
|
usrblk.query = austext_malloc (strlen (qry) + 16, PROGNAME "102", NULL);
|
|
strcpy (usrblk.query, qry);
|
|
}
|
|
|
|
/* Validate the 'date' args and place them into usrblk. */
|
|
if (!both_valid_dates (date1, date2))
|
|
return DtSrFAIL;
|
|
|
|
/* Finish setup usrblk for final search */
|
|
usrblk.flags |= USR_NO_ITERATE; /* must ALWAYS be ON in this api */
|
|
usrblk.request = final_request;
|
|
db = usrblk.dblk;
|
|
db->maxhits = aa_maxhits;
|
|
if (qryarg == TEXT)
|
|
save_search_type = usrblk.search_type = search_type;
|
|
|
|
if (usrblk.debug & USRDBG_SRCHCMPL) {
|
|
ptr = sprintbuf;
|
|
for (i = 0; i < db->ktcount; i++) {
|
|
if (db->keytypes[i].is_selected)
|
|
*ptr++ = '*';
|
|
*ptr++ = db->keytypes[i].ktchar;
|
|
*ptr++ = ' ';
|
|
}
|
|
*(--ptr) = 0;
|
|
strncpy(date1str, objdate2fzkstr (usrblk.objdate1), _DATE1STR_LEN);
|
|
date1str[_DATE1STR_LEN - 1] = 0;
|
|
fprintf (aa_stderr,
|
|
PROGNAME "353 DtSearchQuery(): dbname='%s' srchtype='%c'\n"
|
|
" maxhits=%d keytypes='%s'\n"
|
|
" date1='%s' -> %s. date2='%s' -> %s.\n"
|
|
" query='%.60s'\n",
|
|
db->name, search_type, db->maxhits, sprintbuf,
|
|
NULLORSTR (date1), date1str,
|
|
NULLORSTR (date2), objdate2fzkstr (usrblk.objdate2),
|
|
NULLORSTR (usrblk.query));
|
|
fflush (aa_stderr);
|
|
}
|
|
|
|
/* Final engine call, the search itself... */
|
|
Opera_Engine ();
|
|
|
|
END_OF_SEARCH:
|
|
if (usrblk.debug & USRDBG_SRCHCMPL) {
|
|
/* count msgs */
|
|
i = 0;
|
|
for (llp = ausapi_msglist; llp != NULL; llp = llp->link)
|
|
i++;
|
|
fprintf (aa_stderr, PROGNAME "380 Return from Search: "
|
|
"retncode=%d hitcount=%ld srchmsgs=%d.\n",
|
|
usrblk.retncode, usrblk.dittocount, i);
|
|
fflush (aa_stderr);
|
|
}
|
|
|
|
/* Set this func's retn value based on engine's retncode, and return. */
|
|
switch (usrblk.retncode) {
|
|
case OE_OK:
|
|
/*
|
|
* Transfer usrblk.dittolist to user's own dittolist
|
|
* pointer. Also he MUST use DtSearchFreeResults()
|
|
* between calls. Otherwise the code below will cause a
|
|
* memory leak.
|
|
*/
|
|
*dittolist = usrblk.dittolist;
|
|
*dittocount = usrblk.dittocount;
|
|
usrblk.dittolist = NULL;
|
|
usrblk.dittocount = 0;
|
|
if (stems) {
|
|
*stemcount = usrblk.stemcount;
|
|
for (i = 0; i < *stemcount; i++) {
|
|
strcpy (stems, usrblk.stems[i]);
|
|
stems += DtSrMAXWIDTH_HWORD;
|
|
}
|
|
}
|
|
return DtSrOK;
|
|
|
|
case OE_NOTAVAIL:
|
|
return DtSrNOTAVAIL;
|
|
|
|
case OE_ABORT:
|
|
return DtSrABORT;
|
|
|
|
case OE_REINIT:
|
|
return aa_reinit ();
|
|
|
|
case OE_BAD_QUERY:
|
|
/* Query was invalid. Tell the user why. */
|
|
if (ausapi_msglist == NULL) {
|
|
sprintf (sprintbuf,
|
|
CATGETS(dtsearch_catd, MS_ausapi, 806,
|
|
"%s Query insufficient or search options "
|
|
"incompatible with database '%s' to commence search."),
|
|
PROGNAME "806", usrblk.dblk->name);
|
|
DtSearchAddMessage (sprintbuf);
|
|
}
|
|
return DtSrFAIL;
|
|
|
|
case OE_NOOP:
|
|
/* Search was unsuccessful. Msgs should say why. */
|
|
return DtSrFAIL;
|
|
|
|
default:
|
|
/*
|
|
* Includes OE_SEARCHING, OE_USER_STOP, etc. Probable
|
|
* program error. Msgs may or may not say why.
|
|
*/
|
|
return DtSrERROR;
|
|
} /* end switch */
|
|
} /* DtSearchQuery() */
|
|
|
|
|
|
/************************************************/
|
|
/* */
|
|
/* DtSearchRetrieve */
|
|
/* */
|
|
/************************************************/
|
|
/* Mallocs and returns cleartext of a record given database address (dba).
|
|
* fzkey integers start at bkt #2, just like categories.
|
|
* WARNING! USER SHOULD NEITHER MALLOC NOR FREE HIS CLEARTEXT POINTER!
|
|
*/
|
|
int DtSearchRetrieve (
|
|
char *dbname, /* 1 - 8 char database name */
|
|
DB_ADDR dba, /* database address from dittolist */
|
|
char **cleartext, /* cleartext put here (freed first) */
|
|
long *clearlen, /* length of returned cleartext */
|
|
int *fzkeyi) /* ptr to array of FZKEYSZ integers */
|
|
{
|
|
if (!valid_dbname (dbname))
|
|
return DtSrREINIT;
|
|
usrblk.dba = dba;
|
|
usrblk.request = OE_GETREC;
|
|
Opera_Engine ();
|
|
|
|
/* Set this func's retn value based on engine's retncode, and return. */
|
|
switch (usrblk.retncode) {
|
|
case OE_OK:
|
|
/*
|
|
* WARNING! USER SHOULD NEITHER MALLOC NOR FREE HIS
|
|
* CLEARTEXT POINTER.
|
|
*/
|
|
*cleartext = usrblk.cleartext; /* user MUST leave
|
|
* cleartext alone */
|
|
*clearlen = usrblk.clearlen;
|
|
return DtSrOK;
|
|
|
|
case OE_NOTAVAIL:
|
|
return DtSrNOTAVAIL;
|
|
|
|
case OE_ABORT:
|
|
return DtSrABORT;
|
|
|
|
case OE_REINIT:
|
|
return aa_reinit ();
|
|
|
|
case OE_NOOP:
|
|
return DtSrFAIL;
|
|
|
|
default:
|
|
/*
|
|
* Includes all unexpected return codes. Probable
|
|
* program error. Msgs may or may not say why.
|
|
*/
|
|
return DtSrERROR;
|
|
} /* end switch */
|
|
} /* DtSearchRetrieve() */
|
|
|
|
|
|
|
|
/************************************************/
|
|
/* */
|
|
/* DtSearchHighlight */
|
|
/* */
|
|
/************************************************/
|
|
/* Mallocs and returns hitwords array for passed text string
|
|
* using database and stems array from last search.
|
|
* The stems ptr may be NULL, but if specified
|
|
* the passed stems array MUST be defined:
|
|
* char stems [DtSrMAX_STEMCOUNT] [DtSrMAXWIDTH_HWORD].
|
|
*/
|
|
int DtSearchHighlight (
|
|
char *dbname, /* database name */
|
|
char *cleartext, /* text to be hilited */
|
|
DtSrHitword ** hitwords,
|
|
/* where to put hitwords array */
|
|
long *hitwcount, /* num items in hitwords array */
|
|
int search_type, /* [opt] override save_search_type */
|
|
char *stems, /* [opt] override last search stems */
|
|
int stemcount /* num stems in stems array */
|
|
)
|
|
{
|
|
int i;
|
|
char *cptr;
|
|
|
|
if (!valid_dbname (dbname))
|
|
return DtSrREINIT;
|
|
|
|
/* copy cleartext to usrblk if necessary */
|
|
if (cleartext == NULL || cleartext[0] == 0) {
|
|
sprintf (sprintbuf, CATGETS(dtsearch_catd, MS_ausapi, 40,
|
|
"%1$s Null cleartext. No highlighting performed."),
|
|
PROGNAME "349 ", dbname);
|
|
DtSearchAddMessage (sprintbuf);
|
|
return DtSrERROR;
|
|
}
|
|
if (cleartext != usrblk.cleartext) {
|
|
if (usrblk.cleartext != NULL)
|
|
free (usrblk.cleartext);
|
|
usrblk.clearlen = strlen (cleartext);
|
|
usrblk.cleartext = austext_malloc (usrblk.clearlen + 16,
|
|
PROGNAME "267", NULL);
|
|
strcpy (usrblk.cleartext, cleartext);
|
|
}
|
|
|
|
if (search_type)
|
|
usrblk.search_type = search_type;
|
|
else
|
|
usrblk.search_type = save_search_type;
|
|
|
|
if (stems) {
|
|
if (stemcount > DtSrMAX_STEMCOUNT) {
|
|
sprintf (sprintbuf, CATGETS(dtsearch_catd, MS_ausapi, 1072,
|
|
"%s Program Error: Stem count (%d) greater than maximum (%d)."),
|
|
PROGNAME"1072", stemcount, DtSrMAX_STEMCOUNT);
|
|
DtSearchAddMessage (sprintbuf);
|
|
return DtSrERROR;
|
|
}
|
|
usrblk.stemcount = stemcount;
|
|
cptr = stems;
|
|
for (i = 0; i < stemcount; i++) {
|
|
snprintf(usrblk.stems[i], sizeof(usrblk.stems[i]), "%s", cptr);
|
|
cptr += DtSrMAXWIDTH_HWORD;
|
|
}
|
|
}
|
|
|
|
usrblk.request = OE_HILITE_STEMS;
|
|
Opera_Engine ();
|
|
|
|
/* Set this func's retn value based on engine's retncode, and return. */
|
|
switch (usrblk.retncode) {
|
|
case OE_OK:
|
|
/*
|
|
* Note that the following assignment works even if the
|
|
* user's hitwords arg is in fact &usrblk.hitwords and
|
|
* hitwcount is in fact &usrblk.hitwcount.
|
|
*/
|
|
*hitwords = usrblk.hitwords;
|
|
*hitwcount = usrblk.hitwcount;
|
|
return DtSrOK;
|
|
|
|
case OE_ABORT:
|
|
return DtSrABORT;
|
|
|
|
case OE_REINIT:
|
|
return aa_reinit ();
|
|
|
|
case OE_NOOP:
|
|
case OE_NOTAVAIL:
|
|
return DtSrFAIL;
|
|
|
|
default:
|
|
/*
|
|
* Includes OE_BAD_QUERY and all unexpected return
|
|
* codes. Probable program error. Msgs may or may not
|
|
* say why. In case they don't, put OE's retncode on
|
|
* msglist.
|
|
*/
|
|
if (!ausapi_msglist) {
|
|
sprintf (sprintbuf, CATGETS(dtsearch_catd, MS_ausapi, 1342,
|
|
"%s Search Engine Error %d for highlight request for "
|
|
"database '%s', hit word count=%ld, search type='%c', text='%.30s'"),
|
|
PROGNAME "1342",
|
|
usrblk.retncode, dbname, *hitwcount, search_type,
|
|
NULLORSTR (cleartext));
|
|
DtSearchAddMessage (sprintbuf);
|
|
}
|
|
return DtSrERROR;
|
|
} /* end switch */
|
|
} /* DtSearchHighlight() */
|
|
|
|
/**************************** DTSRAPI.C *************************/
|