cdesktopenv/cde/lib/DtSearch/dtoe.c

905 lines
27 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: Opera_Engine
* alarm_signal_handler
* expired
* no_keytypes
* oe_unblob
* oe_write_audit_rec
* request_str
* retncode_str
* save_query
*
* ORIGINS: 27
*
*
* (C) COPYRIGHT International Business Machines Corp. 1991,1996
* 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.
*/
/******************************* DTOE.C ********************************
* $XConsortium: dtoe.c /main/6 1996/11/25 18:52:51 drk $
* Sept 1991.
* Universal Opera Engine code.
* Additional functions in modules named OE...
* See comments in OE.H for Opera_Engine() function descriptions.
* References to 'socblk' have all been replaced by usrblk,
* which is now the universal data structure.
*
* $Log$
* Revision 2.8 1996/03/20 19:25:31 miker
* Use new hilite_cleartext() function call.
*
* Revision 2.7 1996/03/13 22:51:39 miker
* Changed char to UCHAR several places.
* Revision 2.6 1996/03/05 19:20:58 miker
* Replaced vewords with boolyac, boolpars, and boolsrch.
* oe_unblob no longer converts to uppercase.
* Revision 2.5 1996/02/01 17:15:18 miker
* 2.1.11: Changes to support parsers using readchar cofunctions.
* Changed hiliting calls to hilite_cleartext.
* Obsoleted OE_FINDSTR_REC, OE_DITTO2KWIC, OE_FINDSTR_HITL.
* Revision 2.4 1995/12/27 16:47:12 miker
* Prolog update.
* Revision 2.3 1995/10/24 22:31:32 miker
* Renamed from oe.c. Added prolog.
* Log: oe.c,v
* Revision 2.2 1995/10/03 21:44:24 miker
* Deleted unsigned attrib from misc variables for portability.
* Revision 2.1 1995/09/22 21:29:45 miker
* Freeze DtSearch 0.1, AusText 2.1.8
* Revision 1.19 1995/09/05 18:49:45 miker
* Changed all socblk refs to usrblk. Obsoleted several globals.
* Conflated all msglists to one ausapi_msglist. Numerous name changes.
* Added DTSEARCH define. Remove password processing.
* Made usrblk a universal global. ...All for DtSearch.
* Revision 1.18 1995/07/19 21:02:59 miker
* 2.1.6c: Removed OE_mail_feature and OE_print_server.
* Revision 1.17 1995/06/22 20:49:33 miker
* 2.1.6: Additional debugging messages.
* Revision 1.16 1995/05/30 19:20:51 miker
* Print a little more of msglist when debugging engine return.
*/
#include "SearchE.h"
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <sys/stat.h>
#include <stdlib.h>
#define PROGNAME "DTOE"
#define MAX_LASTQRY 64
#define QRYBUFSZ 1024
#define MS_misc 1
#define MS_oe 10
/*******#define DUMP_HITWORDS*******/
typedef struct {
int num;
char *str;
} NUMSTR;
int boolean_parse (void);
void boolean_search (void);
void ve_delete (void);
/*------------------ OPERA ENGINE GLOBALS --------------------
* Default values set by init_globals() in oeinit.c
* (Some values preinitialized here by compiler because
* they may be used before the first call to init_globals()).
* Most can be overridden by site configuration file.
* Obviously any changes here should be reflected in init_globals().
* Other OE_... globals are located in loadocf.c
*/
extern int debugging_jpn;
extern int debugging_teskey;
char *global_memory_ptr = NULL; /* shared mem, dynam
* defrag */
int shm_id = 0; /* shared mem, dynam defrag */
int OE_bmhtab_strlen[DtSrMAX_STEMCOUNT] = { 0 };
size_t OE_bmhtables[DtSrMAX_STEMCOUNT][MAX_BMHTAB] = { { 0 } };
int OE_dbn = 0; /* dynamic */
int OE_enable_markdel = 0;
int OE_enable_usernotes = 0;
int OE_fastdecode = 0;
char *OE_fileio = NULL;
long OE_flags = 0L;
long OE_objsize = 0L;
char *OE_prodname = PRODNAME; /* reset only in main() */
float OE_prox_factor = 0.0;
int OE_search_type = 0;
char *OE_sitecnfg_fname = NULL;
time_t OE_sitecnfg_mtime = 0L; /* reset only in oeinitialize() */
int OE_uppercase_keys = 0;
long OE_words_hitlimit = 0L;
static time_t my_expiration = 0L;
time_t *OE_expiration = &my_expiration;
char *OEF_audit = NULL;
char *OEF_discard = NULL;
char *OEF_news = NULL;
char *OEF_notesnot = NULL;
char *OEF_notessem = NULL;
char *OEF_readme = NULL;
/*------------ OTHER GLOBALS -----------*/
SAVEUSR saveusr = { 0 };
/****************************************/
/* */
/* expired */
/* */
/****************************************/
/* This function permanently disables opera
* if the license to opera has expired.
*/
static void expired (char *sprintbuf)
{
sprintf (sprintbuf, CATGETS(dtsearch_catd, MS_oe, 71,
PROGNAME "71 %s has expired."),
OE_prodname);
DtSearchAddMessage (sprintbuf);
OE_flags |= OE_PERMERR;
usrblk.retncode = OE_ABORT;
return;
} /* expired() */
/************************************************/
/* */
/* alarm_signal_handler */
/* */
/************************************************/
/* Interrupt handler for SIGALRM */
static void alarm_signal_handler (int sig)
{
fprintf (aa_stderr, PROGNAME "32 "
"%s %s shutdown due to excessive user idle time.\n",
nowstring (NULL), aa_argv0);
DtSearchExit (100 + sig);
} /* alarm_signal_handler() */
/****************************************/
/* */
/* oe_unblob */
/* */
/****************************************/
/* Converts a list of compressed text blob records
* straight out of vista into a single string of clear text.
* input = OE_objsize, dblk.hufid, passed bloblist (freed after use!).
* output = usrblk.cleartext, usrblk.clearlen.
* Returns OE_OK if all goes well, else returns other appropriate retncode.
*/
int oe_unblob (LLIST *bloblist)
{
UCHAR *targ, *src, *stoploc;
short blobclearlen;
LLIST *lptr, *nextlptr;
long mallocsz;
struct or_blobrec
*bptr;
/* Free previous cleartext, if any, and allocate new buffer */
if (OE_objsize < 512)
mallocsz = 512L;
else
mallocsz = OE_objsize + 4L;
if (usrblk.cleartext != NULL)
free (usrblk.cleartext);
usrblk.cleartext = austext_malloc (mallocsz, PROGNAME "188", NULL);
usrblk.clearlen = OE_objsize;
/* Uncompress/decipher bloblist into cleartext,
* freeing the blobs as we go.
*/
targ = (UCHAR *) usrblk.cleartext;
stoploc = targ + OE_objsize;
lptr = bloblist;
while (lptr != NULL) {
/* Setup ptrs and counters for decoding */
bptr = (struct or_blobrec *) lptr->data;
src = (UCHAR *) bptr->or_blob;
blobclearlen = bptr->or_bloblen; /* len of cleartext in curr blob */
if (targ + blobclearlen > stoploc) {
DtSearchAddMessage (PROGNAME "242 Logical Error in database. "
"Object larger than stored size.");
free (usrblk.cleartext);
usrblk.clearlen = 0;
usrblk.retncode = OE_ABORT;
OE_flags |= OE_PERMERR;
return OE_ABORT;
}
/* Decode into clear text buffer */
hc_decode (src, targ, blobclearlen, usrblk.dblk->dbrec.or_hufid);
targ += blobclearlen;
/* free current blob, advance to next blob */
nextlptr = lptr->link; /* temp save next blob addr */
free (lptr);
lptr = nextlptr;
}
*targ = 0;
if (usrblk.debug & USRDBG_RETRVL)
fprintf (aa_stderr, PROGNAME "256 "
"oe_unblob: actual decompressed length = %ld.\n",
(long) (targ - (UCHAR *) usrblk.cleartext));
return OE_OK;
} /* oe_unblob() */
/************************************************/
/* */
/* save_query */
/* */
/************************************************/
/* If AUDIT switch is turned on, saves query and start_time in saveusr
* for later printing when search process has completed.
*/
static void save_query (char *prefix, time_t start_time)
{
char *src, *targ, *end;
if (saveusr.lastqry != NULL)
free (saveusr.lastqry);
saveusr.lastqry = austext_malloc (MAX_LASTQRY, PROGNAME "500", NULL);
/* First copy prefix and "=" */
targ = saveusr.lastqry;
src = prefix;
while (*src != 0)
*targ++ = *src++;
*targ++ = '=';
/* Copy query after '=', replacing any ctrl chars
* with a displayable funny character (tilde ~).
*/
if (usrblk.query == NULL)
strcpy (targ, CATGETS(dtsearch_catd, MS_misc, 1, "<null>"));
else {
end = saveusr.lastqry + MAX_LASTQRY - 2;
src = usrblk.query;
while (*src != 0 && targ < end) {
*targ = *src++;
if (*targ < 32)
*targ = '~';
targ++;
}
*targ = 0;
}
saveusr.start_time = start_time;
return;
} /* save_query() */
/************************************************/
/* */
/* oe_write_audit_rec */
/* */
/************************************************/
/* Writes out audit data after uninterrupted completion of a search.
* Caller checks if AUDIT flag is on.
* Argument is number of hits (may or may not = dittocount).
* By convention, numhits = -1 means search was canceled by user,
* numhits = -2 means system canceled search.
* Requires various saveusr and usrblk fields to be correct.
*/
void oe_write_audit_rec (long numhits)
{
char sprintbuf[1024];
time_t now_gmt;
FILE *stream;
if ((stream = fopen (OEF_audit, "a ")) == NULL)
/* the blank in "a " works around old aix bug */
{
sprintf (sprintbuf, CATGETS(dtsearch_catd, MS_misc, 1596,
PROGNAME "1596 Cannot open audit file %s: %s"),
OEF_audit, strerror (errno));
DtSearchAddMessage (sprintbuf);
OE_flags &= ~OE_AUDIT; /* don't try to audit anything else */
}
else {
time (&now_gmt);
fprintf (stream, AUDIT_FORMAT "%s\n",
usrblk.userid,
nowstring (&now_gmt),
now_gmt - saveusr.start_time, /* elapsed search time */
usrblk.dblk->name,
numhits,
(saveusr.lastqry == NULL) ? \
CATGETS(dtsearch_catd, MS_misc, 1, "<null>") : saveusr.lastqry);
if (saveusr.lastqry != NULL) {
free (saveusr.lastqry);
saveusr.lastqry = NULL;
}
fclose (stream);
}
return;
} /* oe_write_audit_rec() */
/************************************************/
/* */
/* no_keytypes */
/* */
/************************************************/
/* Returns FALSE if any keytype in usrblk.dblk is_selected.
* Otherwise appends an error msg, sets usrblk.retncode
* to OE_BAD_QUERY, and returns TRUE.
*/
static int no_keytypes (void)
{
int i = usrblk.dblk->ktcount;
char sprintbuf[256];
DtSrKeytype *keytypes = usrblk.dblk->keytypes;
while (--i >= 0)
if (keytypes[i].is_selected)
return FALSE;
sprintf (sprintbuf, CATGETS(dtsearch_catd, MS_oe, 440,
PROGNAME "440 No record keytypes were selected in database '%s'."),
usrblk.dblk->label);
DtSearchAddMessage (sprintbuf);
usrblk.retncode = OE_BAD_QUERY;
return TRUE;
} /* no_keytypes() */
/************************************************/
/* */
/* request_str */
/* */
/************************************************/
/* Returns string identifier for OE_... request numbers for debugging */
static char *request_str (int reqnum)
{
static NUMSTR numstr[] = {
{OE_INITIALIZE, "INITIALIZE"}, /* 1 */
{OE_TEXT2FZKEY, "TEXT2FZKEY"}, /* 2 */
{OE_SRCH_FZKEY, "SRCH_FZKEY"}, /* 3 */
{OE_SRCH_STEMS, "SRCH_STEMS"}, /* 4 */
{OE_SRCH_WORDS, "SRCH_WORDS"}, /* 5 */
{OE_STOP_SRCH, "STOP_SRCH"}, /* 6 */
{OE_APPEND_NOTES, "APPEND_NOTES"}, /* 7 */
{OE_GETREC, "GETREC"}, /* 8 */
{OE_GETREC_STEMS, "GETREC_STEMS"}, /* 9 */
{OE_GETREC_WORDS, "GETREC_WORDS"}, /* 10 */
{OE_NEXT_DBA, "NEXT_DBA"}, /* 11 */
{OE_PREV_DBA, "PREV_DBA"}, /* 12 */
{OE_RECKEY2DBA, "RECKEY2DBA"}, /* 13 */
{OE_MARK_DELETION, "MARK_DELETION"}, /* 14 */
{OE_GETREC_DIC, "GETREC_DIC"}, /* 15 */
{OE_DITTO2KWIC, "DITTO2KWIC"}, /* 16 */
{OE_VALIDATE_PWD, "VALIDATE_PWD"}, /* 17 */
{OE_CHANGE_PWD, "CHANGE_PWD"}, /* 18 */
{OE_DELETE_RECID, "DELETE_RECID"}, /* 19 */
{OE_DELETE_BATCH, "DELETE_BATCH"}, /* 20 */
{OE_ASSIST, "ASSIST"}, /* 21 */
{OE_FINDSTR_REC, "FINDSTR_REC"}, /* 22 */
{OE_FINDSTR_HITL, "FINDSTR_HITL"}, /* 23 */
{OE_SRCH_STATISTICAL, "SRCH_STATISTICAL"}, /* 24 */
{OE_HILITE_STEMS, "HILITE_STEMS"}, /* 25 */
{OE_GET_EXPIRE, "GET_EXPIRE"}, /* 26 */
{OE_KILL, "KILL"}, /* 9997 */
{OE_PING, "PING"}, /* 9998 */
{OE_SHUTDOWN, "SHUTDOWN"}, /* 9999 */
{0, "<unknown>"}
};
NUMSTR *ptr = numstr;
while (reqnum != ptr->num && ptr->num != 0)
ptr++;
return ptr->str;
} /* request_str() */
/************************************************/
/* */
/* retncode_str */
/* */
/************************************************/
/* Returns string identifier for OE_... retncode numbers for debugging */
char *retncode_str (int num)
{
static char buf [16];
static NUMSTR numstr[] = {
{OE_OK, "OE_OK"}, /* 1 */
{OE_REINIT, "OE_REINIT"}, /* 2 */
{OE_SEARCHING, "OE_SEARCHING"}, /* 3 */
{OE_BAD_DBLK, "OE_BAD_DBLK"}, /* 4 */
{OE_BAD_REQUEST,"OE_BAD_REQUEST"}, /* 5 */
{OE_BAD_QUERY, "OE_BAD_QUERY"}, /* 6 */
{OE_NOTAVAIL, "OE_NOTAVAIL"}, /* 7 */
{OE_TIMEOUT, "OE_TIMEOUT"}, /* 8 */
{OE_WRAPPED, "OE_WRAPPED"}, /* 9 */
{OE_SYSTEM_STOP,"OE_SYSTEM_STOP"}, /* 10 */
{OE_BAD_PASSWD, "OE_BAD_PASSWD"}, /* 11 */
{OE_BAD_HITLIST,"OE_BAD_HITLIST"}, /* 12 */
{OE_DISABLED, "OE_DISABLED"}, /* 13 */
{OE_USER_STOP, "OE_USER_STOP"}, /* 14 */
{OE_BAD_COMM, "OE_BAD_COMM"}, /* 15 */
{OE_NOOP, "OE_NOOP"}, /* 888 */
{OE_ABORT, "OE_ABORT"}, /* 999 */
{0, buf}
};
NUMSTR *ptr = numstr;
while (num != ptr->num && ptr->num != 0)
ptr++;
if (ptr->num == 0)
sprintf (buf, "%d(?)", num);
return ptr->str;
} /* retncode_str() */
/************************************************/
/* */
/* Opera_Engine */
/* */
/************************************************/
void Opera_Engine (void)
{
int i;
char sprintbuf [1024];
LLIST *bloblist;
DBLK *db;
DB_ADDR dba;
static time_t
start_time = 0L;
extern int database_has_changed (void);
time (&start_time); /* time that current call began */
if (usrblk.debug != 0L) {
if ((usrblk.debug & USRDBG_PARSE) != 0) {
debugging_jpn = TRUE;
debugging_teskey = TRUE;
}
/*
* Place strings for 3 interesting time stamps at sprintbuf
* +0, +100, and +200.
*/
strcpy (sprintbuf, nowstring (&start_time));
if (*OE_expiration != 0L)
strcpy (sprintbuf + 100, nowstring (OE_expiration));
else
strcpy (sprintbuf + 100, "0");
if (OE_sitecnfg_mtime != 0)
strcpy (sprintbuf + 200, nowstring (&OE_sitecnfg_mtime));
else
strcpy (sprintbuf + 200, "0");
fprintf (aa_stderr,
"\n" PROGNAME "444 Opera_Engine Request %d (%s) at %s.\n"
" user='%s', usrblk.flags=%ld(x%04lx), usrblk.debug=%ld(x%04lx).\n"
" OE_flags=%ld(x%04lx), exp=%s, sitecnfg=%s.\n"
,usrblk.request, request_str (usrblk.request), sprintbuf
,usrblk.userid, usrblk.flags, usrblk.flags
,usrblk.debug, usrblk.debug
,OE_flags, OE_flags, sprintbuf + 100, sprintbuf + 200
);
i = 0;
for (db = usrblk.dblist; db != NULL; db = db->link) {
if (db == usrblk.dblk)
break;
i++;
}
if (db == NULL)
fprintf (aa_stderr, " dblk is %s\n",
(i) ? "INVALID!" : "null.");
else
fprintf (aa_stderr, " dblk #%d: name='%s', vistano=%d.\n"
,i, usrblk.dblk->name, usrblk.dblk->vistano
);
fflush (aa_stderr);
}
/* Check if this copy of opera has expired.
* If *OE_expiration == 0, expiration checking disabled.
* If current time < expiration time, permit request.
* Otherwise disable this and all further requests.
*/
if (*OE_expiration != 0L)
if (start_time > *OE_expiration)
expired (sprintbuf);
if (OE_flags & OE_PERMERR) {
sprintf (sprintbuf, CATGETS(dtsearch_catd, MS_oe, 490,
PROGNAME "490 %s Engine permanently disabled."), OE_prodname);
DtSearchAddMessage (sprintbuf);
usrblk.retncode = OE_ABORT;
goto ENGINE_RETURN;
}
/* Ensure that the first call is always an OE_INITIALIZE call */
if ((usrblk.request != OE_INITIALIZE) && !(OE_flags & OE_INITOK)) {
DtSearchAddMessage (CATGETS(dtsearch_catd, MS_oe, 523,
PROGNAME "523 Request Denied: First request must "
"be Engine Initialization."));
usrblk.retncode = OE_NOOP;
goto ENGINE_RETURN;
}
/* Verify that none of the databases has changed since the last call. */
if (database_has_changed ())
goto ENGINE_RETURN;
/* Make usrblk ready. Basically ensure client side
* has not destroyed usrblk. Set OE_dbn to match user's dblk.
* The make-ready activity is not called for OE_INITIALIZE
* because the site's config file has not yet been called
* to create the OE's dblks.
*/
if (usrblk.request != OE_INITIALIZE) {
/* Set OE_dbn to match selected dblk */
for ( db = usrblk.dblist, OE_dbn = 0;
db != NULL;
db = db->link, OE_dbn++)
if (strcmp (usrblk.dblk->name, db->name) == 0)
break;
if (db == NULL) {
sprintf (sprintbuf, CATGETS(dtsearch_catd, MS_oe, 48,
PROGNAME "48 Request Aborted: "
"'%s' database not available at this site."),
usrblk.dblk->name);
DtSearchAddMessage (sprintbuf);
usrblk.retncode = OE_ABORT;
OE_flags |= OE_PERMERR;
goto ENGINE_RETURN;
}
/* Override user switches if required by the engine */
if ((OE_flags & OE_NO_ITERATE) != 0)
usrblk.flags |= USR_NO_ITERATE;
}
/*----------------- BIG SWITCH ON REQUEST CODE ------------------*/
switch (usrblk.request) {
case OE_SRCH_STEMS:
case OE_SRCH_WORDS:
/*
* Builds dittolist from query of stems/words +
* booleans. Swap stoplists to fool search functions.
*/
if (no_keytypes ())
break;
usrblk.search_type =
(usrblk.request == OE_SRCH_WORDS)? 'W' : 'S';
if (OE_flags & OE_AUDIT)
save_query ("WORDS", start_time);
/****ve_word_search ();*****/
if (!boolean_parse()) {
usrblk.retncode = OE_BAD_QUERY;
break;
}
boolean_search();
if (usrblk.debug & USRDBG_SRCHCMPL)
print_stems (usrblk.stemcount, usrblk.stems, PROGNAME"637");
if (usrblk.debug & (USRDBG_SRCHCMPL | USRDBG_HITLIST))
print_dittolist (usrblk.dittolist, PROGNAME "657");
break;
case OE_SRCH_STATISTICAL:
/*
* Builds dittolist from query string of natural
* language text whose words cause statistical doc
* retrieval.
*/
if (no_keytypes ())
break;
if (OE_flags & OE_AUDIT)
save_query ("STAT", start_time);
ve_statistical ();
if (usrblk.debug & USRDBG_SRCHCMPL)
print_stems (usrblk.stemcount, usrblk.stems,
PROGNAME"770 SRCH_STATISTICAL:");
if (usrblk.debug & (USRDBG_SRCHCMPL | USRDBG_HITLIST))
print_dittolist (usrblk.dittolist, PROGNAME "772");
break;
case OE_HILITE_STEMS:
if (usrblk.debug & (USRDBG_RETRVL | USRDBG_HILITE)) {
fprintf (aa_stderr, PROGNAME "819 HILITE_STEMS: "
"srchtyp=%c clrln=%ld clrtxt='%.30s'\n",
usrblk.search_type, usrblk.clearlen,
NULLORSTR (usrblk.cleartext));
print_stems (usrblk.stemcount, usrblk.stems, " ");
}
if (usrblk.cleartext == NULL || usrblk.clearlen <= 0) {
NO_TEXT:
DtSearchAddMessage (
PROGNAME "839 Client Error: No Text to highlight.");
usrblk.retncode = OE_BAD_QUERY;
break;
}
if (usrblk.cleartext[0] == '\0')
goto NO_TEXT;
if (usrblk.stemcount <= 0) {
DtSearchAddMessage (PROGNAME "846 Client Error: "
"Cannot highlight words, stemcount is zero.");
usrblk.retncode = OE_BAD_QUERY;
break;
}
/* Subswitch: depending on request, load hitwords array */
switch (usrblk.search_type) {
case 'W':
i = 'W';
break;
case 'S':
case 'P':
i = 'S';
break;
default:
i = 0;
DtSearchAddMessage (
PROGNAME "708 Word Highlighting is not available "
"for semantic searches.");
usrblk.retncode = OE_BAD_QUERY;
break;
}
if (!i)
break;
hilite_cleartext (i, (char *) usrblk.stems, usrblk.stemcount);
if (OE_flags & OE_PERMERR)
usrblk.retncode = OE_ABORT;
else
usrblk.retncode = OE_OK;
if (usrblk.debug & USRDBG_RETRVL) {
fprintf (aa_stderr,
PROGNAME "820 HILITE_STEMS: hitwcount=%ld\n",
usrblk.hitwcount);
}
break; /* end OE_HILITE_STEMS */
case OE_STOP_SRCH:
/* interrupts long, ongoing search of database */
usrblk.flags |= USR_STOPSRCH;
usrblk.retncode = OE_OK;
break;
case OE_GETREC:
case OE_GETREC_WORDS:
case OE_GETREC_STEMS:
case OE_GETREC_DIC:
/*
* Retrieve database record, text blobs, notes, etc.
* Note that ve_getrec_dba() may return OE_OK even if
* there are no blobs. That will happen when it can
* return everything else about the record, but by
* design the text itself is not stored in the
* repository. In other words, no blobs is not an error
* so check if blobs were returned and adjust retncode
* accordingly.
*/
usrblk.retncode = ve_getrec_dba (&bloblist);
if (usrblk.retncode != OE_OK)
break;
/*
* If no text blobs, ensure cleartext and hitwords
* array are empty (which will cause OE_NOTAVAIL return
* below). Don't create a "no text" msg because many
* clients will want to retrieve the record text
* locally and they won't want an "error" msg
* cluttering up the msglist.
*/
if (bloblist == NULL) {
usrblk.clearlen = 0;
if (usrblk.cleartext != NULL) {
free (usrblk.cleartext);
usrblk.cleartext = NULL;
}
clear_hitwords ();
}
/*
* Otherwise if text blobs do exist, convert them into
* clear text and a hitwords array for hiliting.
*/
else {
usrblk.retncode = oe_unblob (bloblist);
if (usrblk.retncode != OE_OK)
break;
/* Subswitch: depending on request, load hitwords array */
switch (usrblk.request) {
case OE_GETREC_WORDS:
hilite_cleartext ('W',
(char*) usrblk.stems, usrblk.stemcount);
break;
case OE_GETREC_STEMS:
hilite_cleartext ('S',
(char*) usrblk.stems, usrblk.stemcount);
break;
case OE_GETREC_DIC:
DtSearchAddMessage (PROGNAME "783 "
"Dictionary word hiliting function "
"is no longer supported.");
clear_hitwords ();
break;
case OE_GETREC:
default:
clear_hitwords (); /* ensure no hiliting */
} /* end hitwords subswitch */
#ifdef DUMP_HITWORDS /* dump the stems and hitwords arrays */
print_stems (usrblk.stemcount, usrblk.stems, "\nSTEMS:");
fprintf (aa_stderr, "HITWORDS: hitwcount = %d\n",
usrblk.hitwcount);
for (i = 0; i < usrblk.hitwcount; i++)
fprintf (aa_stderr, "offset = %4ld, len=%2d, '%.10s...'\n",
usrblk.hitwords[i].offset,
usrblk.hitwords[i].length,
usrblk.cleartext + usrblk.hitwords[i].offset);
#endif
} /* end if where blobs exist */
if (OE_flags & OE_PERMERR)
usrblk.retncode = OE_ABORT;
else {
usrblk.retncode = ((usrblk.clearlen) ? OE_OK : OE_NOTAVAIL);
if (usrblk.debug & USRDBG_RETRVL)
print_usrblk_record (PROGNAME "957 final: ");
}
break; /* end cases OE_GETREC... */
case OE_NEXT_DBA:
/*
* increments dba address field (not associated with
* hitlist)
*/
ve_browse_dba (+1);
break;
case OE_PREV_DBA:
/*
* decrements dba address field (not associated with
* hitlist)
*/
ve_browse_dba (-1);
break;
case OE_APPEND_NOTES:
/* appends user notes to record at dba */
usrblk.retncode = ve_append_notes ();
break;
case OE_RECKEY2DBA:
/* converts vista record key to database address */
usrblk.dba = ve_reckey2dba ();
if ((usrblk.debug & USRDBG_DELETE) != 0L)
fprintf (aa_stderr, PROGNAME "1089 RECKEY2DBA: "
"retncode=%d, reckey='%s' ->\tdba=%ld:%ld\n",
usrblk.retncode, usrblk.query,
(long) ((usrblk.dba) >> 24), (long) ((usrblk.dba) & 0xffffff));
break;
case OE_DELETE_RECID:
/*
* First converts recid to a db address. Then deletes
* entire record: blobs, notes, and words. Presumes
* only 2 retncodes from reckey2dba are OK and WRAPPED.
* (bad presumption).
*/
dba = ve_reckey2dba ();
if (usrblk.retncode != OE_OK) {
usrblk.retncode = OE_NOTAVAIL;
break;
}
usrblk.dba = dba;
usrblk.dbatab = &usrblk.dba;
usrblk.dbacount = 1;
ve_delete ();
break;
case OE_DELETE_BATCH:
/* deletes all records in a table of dba's */
ve_delete ();
break;
case OE_INITIALIZE:
/*
* first call from UI. returns info used to build
* users screen
*/
oe_initialize ();
break;
case OE_GET_EXPIRE:
usrblk.dba = *OE_expiration;
usrblk.retncode = OE_OK;
break;
case OE_PING:
/* Null function. Just does REINIT checks etc. */
usrblk.retncode = OE_OK;
break;
case OE_SHUTDOWN:
case OE_KILL:
case OE_VALIDATE_PWD:
case OE_CHANGE_PWD:
/* These functions are obsolete and harmless */
usrblk.retncode = OE_OK;
break;
case OE_FINDSTR_REC:
case OE_FINDSTR_HITL:
case OE_DITTO2KWIC:
/* These functions are just obsolete */
sprintf (sprintbuf,
PROGNAME"1027: User Interface Error. "
"%d is obsolete request code.\n",
usrblk.request);
DtSearchAddMessage (sprintbuf);
usrblk.retncode = OE_BAD_REQUEST;
break;
default:
sprintf (sprintbuf, CATGETS(dtsearch_catd, MS_oe, 367,
PROGNAME "367: User Interface Error. "
"%d is invalid request code.\n"),
usrblk.request);
DtSearchAddMessage (sprintbuf);
usrblk.retncode = OE_BAD_REQUEST;
break;
} /* end switch */
ENGINE_RETURN:
if (usrblk.debug != 0L) {
if (!DtSearchHasMessages())
fprintf (aa_stderr, PROGNAME"998 Msglist is empty.\n");
else {
fprintf (aa_stderr,
"mmmmmmmmmm Msglist mmmmmmmmm\n%s\n"
"mmmmmmmmmmmmmmmmmmmmmmmmmmmm\n",
DtSearchGetMessages());
}
fprintf (aa_stderr, PROGNAME "999 usrblk.retncode = %d (%s).\n",
usrblk.retncode, retncode_str (usrblk.retncode));
fflush (aa_stderr);
}
return;
} /* Opera_Engine() */
/******************************* DTOE.C ********************************/