1
0
Fork 0
mirror of git://git.code.sf.net/p/cdesktopenv/code synced 2025-03-09 15:50:02 +00:00
cde/cde/lib/DtSearch/dtsrapi.c
Lev Kujawski 7010b2c11b Centralize catgets() calls through MsgCat
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.
2021-01-31 16:17:13 -07:00

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 *************************/