cdesktopenv/cde/programs/dtsr/tomita.c

927 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 librararies 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: browser
* change_database
* deleter
* kill_delete
* load_dbatab
* main
* parse_infbuf
* print_exit_code
* retncode_abort
*
* ORIGINS: 27
*
* (C) COPYRIGHT International Business Machines Corp. 1992,1995
* All Rights Reserved
* US Government Users Restricted Rights - Use, duplication or
* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
*/
/******************* TOMITA.C *******************
* $TOG: tomita.c /main/9 1998/04/17 11:23:38 mgreess $
* May 1992.
* Replaces original tomita but removes curses dependencies
* and uses Opera Engine for deletes rather than hard
* coding vista calls.
*
* In effect, tomita is two programs.
* Program #1 browses an input list of opera record ids and
* prompts user to confirm that they should be deleted from opera.
* The confirmed list is written to an output file that is identical in format.
* Program 1 can be run anytime because it only reads the database.
*
* Program #2 deletes record from an input list, presumably
* the output of program #1. Program #2 writes to vista and changes it.
* It MUST be run offline when no users are logged into opera,
* in order to prevent database corruption.
* Currently password is passed on command line.
* The password is maintained in an encrypted flat file.
* It can be changed from an undocumented Opera Engine function
* available in tuiopera.
*
* RECORD ID FILE FORMAT (shdscrd.lst format):
* One record to be deleted per line.
* 3 words per line separated by whitespace, everything thereafter is comments.
* (These programs only use the first 2 words).
* All words may be optionally enclosed in double quotes
* to capture embedded blanks ("xxx xxx").
* ...
* databasename recordid userid comments...\n
* ...
*
* $Log$
* Revision 2.2 1995/10/25 15:21:36 miker
* Added prolog.
*
* Revision 2.1 1995/09/22 22:17:11 miker
* Freeze DtSearch 0.1, AusText 2.1.8
*
* Revision 1.11 1995/09/05 19:14:39 miker
* Removed password requirement. DtSearch header file and function
* name changes. Made usrblk universal global.
*/
#include "SearchE.h"
#include <string.h>
#include <ctype.h>
#include <signal.h>
#include <sys/stat.h>
#include <locale.h>
#define PRINT_MESSAGES \
{ puts (DtSearchGetMessages()); DtSearchFreeMessages(); }
#define TOKEN_DELIM " \t\n"
#define PAUSE_ROWS 15
#define DBACOUNT 2000
#define PROGNAME "TOMITA"
#define MS_tomita 29
#define MS_misc 1
/*------------------ GLOBALS ------------------*/
static int debug_mode = FALSE;
static int prog = 'B'; /* 'D' = deleting, 'B' = browsing */
static int shutdown_now = FALSE;
static int yesarg = FALSE;
static int retncode = 0;
static int max_dbacount = DBACOUNT;
static FILE *inf, *outf;
static char *infname;
static char *outfname;
static long maxtime;
static long records_read;
static char parsed_dbname [24];
static DBLK *parsed_dblk;
char parsed_recid [2048];
/************************************************/
/* */
/* print_exit_code */
/* */
/************************************************/
/* Called from inside DtSearchExit() at austext_exit_last */
static void print_exit_code (int exit_code)
{
printf ( catgets(dtsearch_catd, MS_tomita, 3,
"%s: Exit Code = %d.\n") ,
aa_argv0, exit_code);
return;
} /* print_exit_code() */
/************************************************/
/* */
/* kill_delete */
/* */
/************************************************/
/* Interrupt handler for all termination signals
* in Delete mode. Just sets global flag so we
* can come down gracefully between deletions.
*/
static void kill_delete (int sig)
{
shutdown_now = TRUE;
printf ( catgets(dtsearch_catd, MS_tomita, 1,
"\n%s Received interrupt %d.\n"
" Program will stop after current batch of deletions.\n") ,
PROGNAME"069", sig);
return;
} /* kill_delete() */
/************************************************/
/* */
/* retncode_abort */
/* */
/************************************************/
static void retncode_abort (int location)
{
fputc ('\n', aa_stderr);
if (DtSearchHasMessages ())
fprintf (aa_stderr, "%s\n", DtSearchGetMessages ());
fprintf (aa_stderr,
PROGNAME "%d Program abort. usrblk.retncode = %d. Exit code = 3.\n",
location, usrblk.retncode);
DtSearchExit (3);
} /* retncode_abort() */
/****************************************/
/* */
/* change_database */
/* */
/****************************************/
/* Changes usrblk.dblk to point to passed database name.
* Returns TRUE if successful.
*/
static int change_database (char *newname)
{
DBLK *db;
for (db = usrblk.dblist; db != NULL; db = db->link)
if (strcmp (db->name, newname) == 0) {
usrblk.dblk = db;
return TRUE;
}
/* Invalid newname. If deleting, just say which database is invalid. */
retncode = 1;
fprintf (aa_stderr, catgets(dtsearch_catd, MS_tomita, 4,
"%s Database '%s' not found.\n") ,
PROGNAME"114", newname);
if (prog == 'D')
return FALSE;
/* If browsing, tell user his options */
fprintf (aa_stderr, catgets(dtsearch_catd, MS_tomita, 5,
"Available choices are:") );
for (db = usrblk.dblist; db != NULL; db = db->link)
fprintf (aa_stderr, " '%s'", db->name);
fputc ('\n', aa_stderr);
return FALSE;
} /* change_database() */
/****************************************/
/* */
/* parse_infbuf */
/* */
/****************************************/
/* Parses a line from a standard formatted discard file.
* If first word indicates different database from usrblk.dblk,
* changes it. First token loaded into parsed_dbname
* (and parsed_dblk will be made to track it), and
* second token is loaded into parsed_recid.
* Tokens are separated by blanks and/or tabs,
* except 2nd token may have embedded spaces if it is
* surrounded by double quotes. Returns TRUE unless
* database couldn't change or other error, then returns FALSE.
*/
static int parse_infbuf (char *infbuf)
{
char *ptr;
char mybuf[1024];
/* Do all parsing in my own buf so infbuf not peppered with \0's */
strncpy (mybuf, infbuf, sizeof (mybuf));
mybuf[sizeof (mybuf) - 1] = 0;
/* Parse first token (database name) */
if ((ptr = strtok (mybuf, " \t")) == NULL) {
/* Msg #8 is used in two places */
fprintf (aa_stderr, catgets(dtsearch_catd, MS_tomita, 8,
"%s Invalid input format: %.30s...\n") ,
PROGNAME"152", infbuf);
retncode = 1;
return FALSE;
}
/* Change database if necessary */
if (strcmp (ptr, usrblk.dblk->name) != 0)
if (!change_database (ptr)) {
retncode = 1;
return FALSE;
}
strcpy (parsed_dbname, ptr);
parsed_dblk = usrblk.dblk;
/* Hop over to beginning of 2nd token */
for (ptr += strlen (ptr) + 1; *ptr == ' ' || *ptr == '\t'; ptr++);
/* Get 2nd token (record id). Token delimiters depend
* on whether token begins with a double quote.
*/
ptr = strtok (ptr, (*ptr == '\"') ? "\"" : " \t");
if (ptr == NULL) {
/* Msg #8 is used in two places */
fprintf (aa_stderr, catgets(dtsearch_catd, MS_tomita, 8,
"%s Invalid input format: %.30s...\n") ,
PROGNAME"176", infbuf);
retncode = 1;
return FALSE;
}
strncpy (parsed_recid, ptr, sizeof (parsed_recid));
parsed_recid[sizeof (parsed_recid) - 1] = 0;
return TRUE;
} /* parse_infbuf() */
/****************************************/
/* */
/* browser */
/* */
/****************************************/
/* Program 1: displays records in input file,
* or user selected records, and if confirmed,
* writes their record ids to output file.
*/
static int browser (void)
{
int done = FALSE;
int pausing = FALSE;
int redisplay_rec = FALSE;
int pause_counter;
time_t stamp;
LLIST *llptr;
char *ptr;
char datestr[32]; /* "1946/04/17 13:03" */
char userbuf[1024];
char infbuf[1024];
/* All writes to output file will have same date string in comment */
time (&stamp);
strftime (datestr, sizeof (datestr), "%Y/%m/%d %H:%M", localtime (&stamp));
/* Main menu loop */
while (!done) {
if (DtSearchHasMessages ()) {
putchar ('\n');
PRINT_MESSAGES
}
/* Write main menu prompt */
printf ( catgets(dtsearch_catd, MS_tomita, 10,
"\n---------- SHOW NEXT RECORD ----------- Database = '%s'\n"
"q QUIT. Current Record Count = %ld\n"
"p Toggle PAUSE from %s.\n"
"n NEXT INPUT file record.\n"
"+ NEXT SEQUENTIAL database record.\n"
"- PRIOR SEQUENTIAL database record.\n"
"r REDISPLAY current record '%s'.\n"
"x CONFIRM DELETION of current record.\n"
"dxxx Change DATABASE to xxx.\n"
"\"xxx GET record id xxx (embedded blanks are ok).\n"
"> ") ,
usrblk.dblk->name,
usrblk.dblk->dbrec.or_reccount,
(pausing) ? "on to OFF" : "off to ON",
usrblk.objrec.or_objkey
);
/* Read user's response. Remove user's \n. */
*userbuf = '\0';
if ((fgets (userbuf, sizeof (userbuf), stdin)) == NULL) break;
if (strlen(userbuf) && userbuf[strlen(userbuf)-1] == '\n')
userbuf[strlen(userbuf)-1] = '\0';
putchar ('\n');
/* depending on response, get database address into usrblk */
redisplay_rec = FALSE;
switch (tolower (*userbuf)) {
case 'q':
done = TRUE;
break;
case 'd':
change_database (userbuf + 1);
continue;
break;
case 'p':
pausing = !pausing;
continue;
break;
case 'r':
if (usrblk.objrec.or_objkey[0] == 0) {
fprintf (aa_stderr,
catgets(dtsearch_catd, MS_tomita, 11,
"%s Record buffer empty.\n"),
PROGNAME"267");
continue;
}
redisplay_rec = FALSE;
break;
case '+':
case '-':
usrblk.request = (*userbuf == '+') ? OE_NEXT_DBA : OE_PREV_DBA;
Opera_Engine ();
break;
case 'n':
if (inf == NULL) {
fprintf (aa_stderr,
catgets(dtsearch_catd, MS_tomita, 12,
"%s Input file unavailable.\n"),
PROGNAME"282");
continue;
}
*infbuf = '\0';
if ((fgets (infbuf, sizeof (infbuf), inf)) == NULL)
{
fprintf (aa_stderr,
catgets(dtsearch_catd, MS_tomita, 13,
"%s No more records in input file.\n"),
PROGNAME"288");
fclose (inf);
inf = NULL;
continue;
}
if (strlen(infbuf) && infbuf[strlen(infbuf)-1] == '\n')
infbuf[strlen(infbuf)-1] = '\0';
if (!parse_infbuf (infbuf))
continue;
usrblk.request = OE_RECKEY2DBA;
usrblk.query = parsed_recid;
Opera_Engine ();
break;
case '\"':
ptr = strtok (userbuf, "\"");
if (ptr == NULL || *ptr == 0) {
fprintf (aa_stderr,
catgets(dtsearch_catd, MS_tomita, 14,
"%s Invalid Record ID.\n"),
PROGNAME"303");
continue;
}
usrblk.request = OE_RECKEY2DBA;
usrblk.query = ptr;
Opera_Engine ();
break;
case 'x':
/*
* Write record id to output file. Format:
* dbasename "recid" userid comments(date)...
*/
fprintf (outf, DISCARD_FORMAT, usrblk.dblk->name,
usrblk.objrec.or_objkey, usrblk.userid, datestr);
printf ( catgets(dtsearch_catd, MS_tomita, 15,
"%s '%s' appended to file of confirmed deletions.\n") ,
PROGNAME"317", usrblk.objrec.or_objkey);
continue;
default:
printf (catgets(dtsearch_catd, MS_tomita, 16, "...what?\n"));
continue;
} /* end switch */
if (done)
break;
/* if user requested redisplay, skip the following OE code */
if (redisplay_rec)
goto DISPLAY_RECORD;
/*
* check return code from attempt to get opera database
* address
*/
if (usrblk.retncode == OE_WRAPPED)
fprintf (aa_stderr, catgets(dtsearch_catd, MS_tomita, 17,
"%s %s Engine wrapped to next record.\n") ,
PROGNAME"333", OE_prodname);
else if (usrblk.retncode != OE_OK)
retncode_abort (334);
/* retrieve the record and uncompress it */
usrblk.request = OE_GETREC;
Opera_Engine ();
if (usrblk.retncode != OE_OK)
retncode_abort (339);
DISPLAY_RECORD:
/* display the record's cleartext, character by character */
printf ( catgets(dtsearch_catd, MS_tomita, 18,
"\n\n"
"Record: '%s'\n"
"Abstract: '%s'\n"
"--------------------------------------\n") ,
usrblk.objrec.or_objkey,
(usrblk.abstrbufsz > 0) ? usrblk.abstrbuf :
catgets (dtsearch_catd, MS_misc, 1, "<null>"));
pause_counter = 0;
for (ptr = usrblk.cleartext; *ptr != 0; ptr++) {
putchar (*ptr);
/*
* pause every so many lines so user can browse the
* output
*/
if (pausing && *ptr == '\n') {
if (++pause_counter >= PAUSE_ROWS) {
/* Msg 21 is used in two places */
printf ( catgets(dtsearch_catd, MS_tomita, 21,
"\n...push ENTER to continue... ") );
*userbuf = '\0';
fgets (userbuf, sizeof (userbuf), stdin);
if (strlen(userbuf) && userbuf[strlen(userbuf)-1] == '\n')
userbuf[strlen(userbuf)-1] = '\0';
putchar ('\n');
pause_counter = 0;
}
}
} /* end of cleartext printing */
/* display the user notes if any, character by character */
if (usrblk.notes != NULL) {
printf ( catgets(dtsearch_catd, MS_tomita, 20,
"--------------------------------------\n"
"End of Text Blob for '%s':\n\n"
"User Notes:\n"
"--------------------------------------\n") ,
usrblk.objrec.or_objkey);
pause_counter += 5;
for (llptr = usrblk.notes; llptr != NULL; llptr = llptr->link) {
for (ptr = llptr->data; *ptr != '\0'; ptr++) {
putchar (*ptr);
if (pausing && *ptr == '\n')
if (++pause_counter >= PAUSE_ROWS) {
/* Msg 21 is used in two places */
printf ( catgets(dtsearch_catd, MS_tomita, 21,
"\n...push ENTER to continue... ") );
*userbuf = '\0';
fgets (userbuf, sizeof (userbuf), stdin);
if (strlen(userbuf) &&
userbuf[strlen(userbuf)-1] == '\n')
userbuf[strlen(userbuf)-1] = '\0';
putchar ('\n');
pause_counter = 0;
}
}
}
} /* end of user notes printing */
printf ("--------------------------------------\n"
"End of Record '%s'.\n", usrblk.objrec.or_objkey);
} /* end of main menu loop */
return 0;
} /* browser() */
/****************************************/
/* */
/* load_dbatab */
/* */
/****************************************/
/* Subroutine of deleter(). Reads discard file containing
* record ids to be deleted, converts to database addresses,
* loads usrblk.dbatab up to max batch size.
* Returns number of dba's added to table.
* Returns 0 when file is empty after last batch.
*/
static int load_dbatab (void)
{
static int read_next_rec = TRUE;
static char last_dbname[24] = "";
static DBLK *last_dblk;
DB_ADDR *next_dba;
char buf[1024];
int first_err = TRUE;
if (inf == NULL)
return 0;
usrblk.dbacount = 0;
next_dba = usrblk.dbatab;
KEEP_READING:
/* MAIN LOOP - break it at EOF, max count, or dbname change */
while (usrblk.dbacount < max_dbacount) {
/*
* Skip the read of the first record if the reason we left
* main loop the last time was because of a database name
* change, and the data from the last read is still in
* parsed_dbname, _dblk, and _recid. Update usrblk.dblk
* because it's based on the last table's database.
*/
if (!read_next_rec) {
read_next_rec = TRUE;
usrblk.dblk = parsed_dblk;
}
else {
*buf = '\0';
if (fgets (buf, sizeof (buf), inf) == NULL)
{
fclose (inf);
inf = NULL;
break;
}
records_read++;
buf[sizeof (buf) - 1] = 0; /* guarantee termination */
if (strlen(buf) && buf[strlen(buf)-1] == '\n')
buf[strlen(buf)-1] = '\0';
/*
* Parse line into dbname and recid. Skip line if
* error.
*/
if (!parse_infbuf (buf))
continue;
/* on very first read, save the database name */
if (last_dbname[0] == 0) {
strcpy (last_dbname, parsed_dbname);
last_dblk = parsed_dblk;
}
} /* finished reading next rec in input file */
/*
* Test for change of database name. Restore usrblk.dblk
* to reflect all the records on the dba table so far. Then
* save the new dblk for when we are again called.
*/
if (strcmp (last_dbname, parsed_dbname) != 0) {
read_next_rec = FALSE;
strcpy (last_dbname, parsed_dbname);
usrblk.dblk = last_dblk;
last_dblk = parsed_dblk;
break;
}
/*
* Call OE to get record's db address. Turn off debug
* temporarily so won't flood output with messages.
*/
usrblk.query = parsed_recid;
usrblk.debug &= ~USRDBG_DELETE;
usrblk.request = OE_RECKEY2DBA;
Opera_Engine ();
if (debug_mode) /* restore */
usrblk.debug |= USRDBG_DELETE;
if (DtSearchHasMessages ()) {
putchar ('\n');
PRINT_MESSAGES
}
if (usrblk.retncode == OE_WRAPPED) {
if (first_err) {
first_err = FALSE;
fputc ('\n', aa_stderr);
}
fprintf (aa_stderr, catgets(dtsearch_catd, MS_tomita, 24,
"%s Database %s, '%s' not found.\n") ,
PROGNAME"482", parsed_dbname, parsed_recid);
continue;
}
else if (usrblk.retncode != OE_OK)
retncode_abort (486);
/* add db address to growing table */
*next_dba = usrblk.dba;
next_dba++;
usrblk.dbacount++;
} /* end of main record read loop */
/* It is possible to exit the main loop, because database changed
* or whatever, but no records were added to usrblk.dbatab.
* If there are still records to be read from the input file,
* go back and try another pass.
*/
if (inf != NULL && usrblk.dbacount == 0)
goto KEEP_READING;
return usrblk.dbacount;
} /* load_dbatab() */
/****************************************/
/* */
/* deleter */
/* */
/****************************************/
/* Program 2: deletes records specified in input file.
* Must be run offline when all online users have logged off.
*/
static void deleter (char *infname)
{
int i;
long records_deleted;
time_t start_time, minutes, hours, seconds, elapsed;
char buf[128];
if (!yesarg) {
printf ( catgets(dtsearch_catd, MS_tomita, 25,
"\nDO NOT CONTINUE under any of the following circumstances:\n"
"-> If the input file which lists record ids to be deleted is not\n"
" named '%s'.\n"
"-> If any users are still accessing the affected database(s).\n"
"-> If any database files have not been backed up.\n\n"
"If you are sure you are ready to start deleting, enter 'y' now... ") ,
infname, OE_prodname);
fgets (buf, sizeof(buf)-1, stdin);
if (tolower (*buf) != 'y')
return;
}
/* Make sure engine doesn't abort because of
* recurring changes to d99 files.
*/
OE_sitecnfg_mtime = 0L;
/* Init table of db addrs */
usrblk.dbatab = austext_malloc
(sizeof (DB_ADDR) * (max_dbacount + 2), PROGNAME "531", NULL);
usrblk.dbacount = 0; /* number of recs currently in table */
/* Init status msg stuff */
records_read = 0L;
records_deleted = 0L;
time (&start_time);
signal (SIGINT, kill_delete);
signal (SIGQUIT, kill_delete);
signal (SIGTRAP, kill_delete);
signal (SIGTERM, kill_delete);
signal (SIGPWR, kill_delete);
#ifdef _AIX
signal (SIGXCPU, kill_delete); /* cpu time limit exceeded */
signal (SIGDANGER, kill_delete); /* imminent paging space
* crash */
#endif
/* MAIN LOOP */
while (load_dbatab ()) {
/*
* Stop now if we have exceeded user specified time limit
* or if user sent termination or interrupt signal.
*/
if (shutdown_now)
break;
elapsed = time (NULL) - start_time;
if (maxtime > 0L && elapsed >= maxtime)
break;
/* echo status for humans who might be watching */
hours = elapsed / 3600L;
seconds = elapsed - (3600L * hours); /* remaining after hours */
minutes = seconds / 60L;
seconds = seconds - (60L * minutes);
printf ( catgets(dtsearch_catd, MS_tomita, 26,
"%s %ld read, %ld deleted, %ldh %2ldm %2lds elapsed.\n"
" Database '%s': Current record count = %ld, Batch size = %d.\n") ,
aa_argv0, records_read, records_deleted,
hours, minutes, seconds,
usrblk.dblk->name, usrblk.dblk->dbrec.or_reccount, usrblk.dbacount);
/*****fflush (stdout);*****/
/* call OE to delete batch of records */
usrblk.request = OE_DELETE_BATCH;
Opera_Engine ();
if (DtSearchHasMessages ()) {
putchar ('\n');
PRINT_MESSAGES
}
if (usrblk.retncode != OE_OK)
retncode_abort (572);
records_deleted += usrblk.dbacount;
} /* end main loop */
/* Print final status messages */
elapsed = time (NULL) - start_time; /* total elapsed time */
hours = elapsed / 3600L;
seconds = elapsed - (3600L * hours); /* remaining after hours */
minutes = seconds / 60L;
seconds = seconds - (60L * minutes); /* remaining after hours
* & mins */
printf ( catgets(dtsearch_catd, MS_tomita, 27,
"%s %ld records read from input file. %ld were deleted and\n"
" %ld were not found in %ld hours, %ld minutes, %ld seconds,\n") ,
aa_argv0, records_read, records_deleted,
records_read - records_deleted,
hours, minutes, seconds);
/* Figure average time for a deletion */
elapsed = (records_deleted) ? elapsed / records_deleted : 0L;
minutes = elapsed / 60L;
seconds = elapsed - (60L * minutes);
printf ( catgets(dtsearch_catd, MS_tomita, 28,
" or an average of %ld minutes, %ld seconds per record deleted.\n"),
minutes, seconds);
return;
} /* deleter() */
/****************************************/
/* */
/* main */
/* */
/****************************************/
int main (int argc, char *argv[])
{
char *arg;
time_t mytime;
char timebuf[80];
aa_argv0 = argv[0];
setlocale (LC_ALL, "");
dtsearch_catd = catopen (FNAME_DTSRCAT, 0);
time (&mytime);
strftime (timebuf, sizeof (timebuf),
catgets(dtsearch_catd, MS_misc, 22, "%A, %b %d %Y, %I:%M %p"),
localtime (&mytime));
printf (catgets(dtsearch_catd, MS_tomita, 29,
"%s. Run %s.\n") ,
aa_argv0, timebuf);
austext_exit_last = print_exit_code;
signal (SIGINT, DtSearchExit);
signal (SIGTERM, DtSearchExit);
/****memset (&usrblk, 0, sizeof(USRBLK));****/
/* Validate program number argument */
if (argc < 2) {
BAD_ARGS:
fprintf (aa_stderr, catgets(dtsearch_catd, MS_tomita, 30,
"\nUSAGE: %s [options]\n"
" -i Input file name. If not specified, defaults to %s.\n"
" -d[v] Print debug statements.\n"
" -dv turns on verbose (record-by-record) debugging.\n"
" -t<N> Max desired number of seconds of run time.\n"
" Ctrl-C/Break will also stop deletion at next record.\n"
" -n<N> Change number of records in a batch from %d to <N>.\n"
" -y Automatically answers 'yes' to Delete mode confirm prompt.\n"
" -d trace deletion operations.\n") ,
aa_argv0, FNAME_DISCARD_DATA,
FNAME_CONFIRM_LIST, FNAME_CONFIRM_LIST, DBACOUNT);
DtSearchExit (2);
}
prog = toupper (argv[1][0]);
if (prog != 'B' && prog != 'D')
goto BAD_ARGS;
/* Initialize defaults depending on program mode */
if (prog == 'B') {
infname = FNAME_DISCARD_DATA;
outfname = FNAME_CONFIRM_LIST;
}
else {
infname = FNAME_CONFIRM_LIST;
outfname = PROGNAME "654";
}
maxtime = 0L;
/* Save rest of command line arguments */
for (argc -= 2, argv += 2; argc > 0; argc--, argv++) {
arg = *argv;
switch (tolower (arg[1])) {
case 'i':
infname = arg + 2;
break;
case 'o':
outfname = arg + 2;
break;
case 'd':
debug_mode = TRUE;
usrblk.debug |= USRDBG_DELETE;
if (arg[2] == 'v')
usrblk.debug |= USRDBG_VERBOSE;
break;
case 'y':
yesarg = TRUE;
break;
case 't':
maxtime = atol (arg + 2);
break;
case 'n':
max_dbacount = atol (arg + 2);
break;
default:
fprintf (aa_stderr, catgets(dtsearch_catd, MS_tomita, 31,
"\n%s Unknown argument '%s'.\n") ,
PROGNAME"689", arg);
goto BAD_ARGS;
} /* end switch */
} /* end arg parsing */
/* Open input file to test for its existence.
* For the Browse program, file ptr 'inf' == NULL
* means the file is not open.
*/
if ((inf = fopen (infname, "r")) == NULL) {
if (prog == 'D') {
fprintf (aa_stderr, catgets(dtsearch_catd, MS_tomita, 32,
"%s Unable to open input file '%s'.\n") ,
PROGNAME"710", infname);
goto BAD_ARGS;
}
}
/* If browsing, get output file name and
* open it to test for write permission.
*/
if (prog == 'B') {
if ((outf = fopen (outfname, "a ")) == NULL)
/* the blank in "a " works around old aix bug */
{
fprintf (aa_stderr, catgets(dtsearch_catd, MS_tomita, 33,
"\n%s Unable to open output file '%s'.\n") ,
PROGNAME"721", outfname);
goto BAD_ARGS;
}
}
/* Initialize the opera engine, i.e. open the database */
printf ( catgets(dtsearch_catd, MS_tomita, 34,
"Initializing %s engine...\n"),
OE_prodname);
strcpy (usrblk.userid, "ToMiTa");
usrblk.request = OE_INITIALIZE;
usrblk.query = AUSAPI_VERSION;
Opera_Engine ();
if (usrblk.retncode != OE_OK)
retncode_abort (733);
PRINT_MESSAGES
if (prog == 'B')
browser ();
else
deleter (infname);
usrblk.request = OE_SHUTDOWN;
Opera_Engine ();
printf ( catgets(dtsearch_catd, MS_tomita, 36,
"Normal engine shutdown.\n") );
DtSearchExit (0);
} /* main() */
/******************* TOMITA.C *******************/