+static int cmd_init ( char *args[], WRBUF outbuff)
+{
+ zebra_init(zh);
+ return 0; /* ok */
+}
+
+static int cmd_select_database ( char *args[], WRBUF outbuff)
+{
+ char *db=defarg(args[1],DEFAULTDATABASE);
+ wrbuf_printf(outbuff,"Selecting database '%s'\n",db);
+ return zebra_select_database(zh, db);
+}
+
+static int cmd_create_database( char *args[], WRBUF outbuff)
+{
+ char *db=defarg(args[1],DEFAULTDATABASE);
+ wrbuf_printf(outbuff,"Creating database '%s'\n",db);
+
+ return zebra_create_database(zh, db);
+}
+
+static int cmd_drop_database( char *args[], WRBUF outbuff)
+{
+ char *db=args[1];
+ if (!db)
+ db="Default";
+ wrbuf_printf(outbuff,"Dropping database '%s'\n",db);
+ return zebra_drop_database(zh, db);
+}
+
+static int cmd_begin_trans( char *args[], WRBUF outbuff)
+{
+ int rw=0;
+ if (args[1] && ( (args[1][0]=='1') || (args[1][0]=='w') ))
+ rw=1;
+ return zebra_begin_trans(zh,rw);
+}
+
+static int cmd_end_trans( char *args[], WRBUF outbuff)
+{
+ return zebra_end_trans(zh);
+}
+/*************************************
+ * Inserting and deleting
+ */
+
+static int cmd_record_insert( char *args[], WRBUF outbuff)
+{
+ zint sysno = 0;
+ int rc;
+ char *rec=restargs(args,1);
+
+ rc = zebra_update_record(zh,
+ action_insert,
+ 0, /* record type */
+ &sysno,
+ 0, /* match */
+ 0, /* fname */
+ rec,
+ strlen(rec));
+ if (0==rc)
+ {
+ wrbuf_printf(outbuff,"ok sysno=" ZINT_FORMAT "\n",sysno);
+ }
+ return rc;
+}
+
+
+static int cmd_exchange_record( char *args[], WRBUF outbuff)
+{
+ char *id = args[1];
+ char *action = args[2];
+ int rc;
+ char *rec=restargs(args,3);
+ if (!(id && action && args[4] ))
+ {
+ wrbuf_puts(outbuff,"Missing arguments!\n");
+ onecommand("help exchange_record", outbuff, "");
+ return -90;
+ }
+
+ rc = zebra_update_record(zh, action_update, 0 /* record_type */,
+ 0 /* sysno */,
+ id /* match */,
+ 0 /* fname */,
+ rec, strlen(rec));
+ return rc;
+}
+
+/**********************************
+ * Searching and retrieving
+ */
+
+static int cmd_search_pqf(char *args[], WRBUF outbuff)
+{
+ zint hits = 0;
+ char *set = args[1];
+ char *qry = restargs(args,2);
+ int rc;
+ rc = zebra_search_PQF(zh, qry, set, &hits);
+ if (0==rc)
+ wrbuf_printf(outbuff, ZINT_FORMAT " hits found\n", hits);
+ return rc;
+}
+
+static int cmd_find( char *args[], WRBUF outbuff)
+{
+ char *setname=DEFAULTRESULTSET;
+ int rc;
+ zint hits = 0;
+ WRBUF qry = wrbuf_alloc();
+ if (0==strstr(args[0],"@attr"))
+ wrbuf_puts(qry, "@attr 1=/ ");
+ wrbuf_puts(qry,restargs(args,1));
+ if (!zh)
+ onecommand("quickstart", outbuff, "");
+ wrbuf_printf(outbuff, "find %s\n",wrbuf_cstr(qry));
+ rc = zebra_search_PQF(zh, wrbuf_cstr(qry), setname, &hits);
+ if (0==rc)
+ {
+ wrbuf_printf(outbuff, ZINT_FORMAT " hits found\n", hits);
+ nextrecno = 1;
+ }
+ wrbuf_destroy(qry);
+ return rc;
+}
+
+static int cmd_show( char *args[], WRBUF outbuff)
+{
+ int start=defargint(args[1], nextrecno);
+ int nrecs=defargint(args[2],1);
+ char *setname=defarg(args[3],DEFAULTRESULTSET);
+ int rc=0;
+ ZebraRetrievalRecord *recs;
+ ODR odr;
+ Z_RecordComposition *pcomp=0;
+ int i;
+
+ odr = odr_createmem(ODR_ENCODE);
+ recs= odr_malloc(odr,sizeof(ZebraRetrievalRecord)*nrecs);
+ rc =z_RecordComposition(odr, &pcomp, 0,"recordComposition");
+
+ for (i=0;i<nrecs;i++)
+ recs[i].position=start+i;
+
+ rc = zebra_records_retrieve(zh, odr, setname,
+ pcomp, yaz_oid_recsyn_xml, nrecs,recs);
+ if (0==rc)
+ {
+ for (i=0;i<nrecs;i++)
+ {
+ printf("Err %d: %d\n",i,recs[i].errCode);
+ if (recs[i].buf)
+ {
+ wrbuf_printf(outbuff,"Record %d\n", recs[i].position);
+ wrbuf_write(outbuff, recs[i].buf, recs[i].len);
+ wrbuf_puts(outbuff, "\n");
+ } else
+ wrbuf_printf(outbuff,"NO Record %d\n", recs[i].position);
+ }
+ nextrecno=start+nrecs;
+ }
+ odr_destroy(odr);
+ return rc;
+} /* cmd_show */
+
+static int cmd_sort( char *args[], WRBUF outbuff)
+{
+ int rc=0;
+ ODR odr;
+ int sortstatus=0;
+ Z_SortKeySpecList *spec=0;
+ const char * inpsets[]={ DEFAULTRESULTSET, 0};
+ /* FIXME - allow the user to specify result sets in/out */
+
+ odr=odr_createmem(ODR_ENCODE);
+ spec=yaz_sort_spec (odr, restargs(args,1));
+ if (!spec)
+ rc=1;
+ if (!rc)
+ rc=zebra_sort(zh, odr,
+ 1, inpsets,
+ DEFAULTRESULTSET,
+ spec,
+ &sortstatus);
+ if (!rc)
+ wrbuf_printf(outbuff, "sort returned status %d\n",sortstatus);
+
+ odr_destroy(odr);
+ return rc;
+} /* cmd_sort */
+/*
+ *
+ * int bend_sort (void *handle, bend_sort_rr *rr)
+ * {
+ * ZebraHandle zh = (ZebraHandle) handle;
+ *
+ * zebra_sort (zh, rr->stream,
+ * rr->num_input_setnames, (const char **)
+ * rr->input_setnames,
+ * rr->output_setname,
+ * rr->sort_sequence,
+ * &rr->sort_status);
+ * zebra_result (zh, &rr->errcode,
+ * &rr->errstring);
+ * return 0;
+ * }
+ *
+ */
+
+/**************************************)
+ * Command table, parser, and help
+ */
+
+struct cmdstruct
+{
+ char *cmd;
+ char *args;
+ char *explanation;
+ int (*testfunc)(char *args[], WRBUF outbuff);
+} ;
+
+
+struct cmdstruct cmds[] = {
+ /* special cases:
+ * if text is 0, does not list the command
+ * if cmd is "", adds the args (and newline) in command listing
+ */
+ { "", "Starting and stopping:", "", 0 },
+ { "zebra_start",
+ "[configfile]",
+ "starts the zebra service. You need to call this first\n"
+ "if no configfile is given, assumes " DEFAULTCONFIG,
+ cmd_zebra_start },
+ { "zebra_stop", "",
+ "stops the zebra service",
+ cmd_zebra_stop },
+ { "zebra_open", "",
+ "starts a zebra session. Once you have called zebra_start\n"
+ "you can call zebra_open to start working",
+ cmd_zebra_open },
+ { "zebra_close", "",
+ "closes a zebra session",
+ cmd_zebra_close },
+ { "quickstart", "[configfile]",
+ "Does a zebra_start, zebra_open, and sets up the log",
+ cmd_quickstart },
+
+ { "", "Log file:","", 0},
+ { "yaz_log_file",
+ "[filename]",
+ "Directs the log to filename (or stderr)",
+ cmd_yaz_log_file },
+ { "yaz_log_level",
+ "[level]",
+ "Sets the logging level (or returns to default)",
+ cmd_yaz_log_level },
+ { "yaz_log_prefix",
+ "[prefix]",
+ "Sets the log prefix",
+ cmd_yaz_log_prefix},
+ { "yaz_log",
+ "[level] text...",
+ "writes an entry in the log",
+ cmd_logf},
+
+ { "", "Error handling:","", 0},
+ { "err", "",
+ "Displays zebra's error status (code, str, add)",
+ cmd_err},
+ { "errcode", "",
+ "Displays zebra's error code",
+ cmd_errcode},
+ { "errstr", "",
+ "Displays zebra's error string",
+ cmd_errstr},
+ { "erradd", "",
+ "Displays zebra's additional error message",
+ cmd_erradd},
+
+ { "", "Admin:","", 0},
+ { "init", "",
+ "Initializes the zebra database, destroying all data in it",
+ cmd_init},
+ { "select_database", "basename",
+ "Selects a database",
+ cmd_select_database},
+ { "create_database", "basename",
+ "Create database",
+ cmd_create_database},
+ { "drop_database", "basename",
+ "Drop database",
+ cmd_drop_database},
+ { "begin_trans", "[rw]",
+ "Begins a transaction. rw=1 means write, otherwise read-only",
+ cmd_begin_trans},
+ { "end_trans","",
+ "Ends a transaction",
+ cmd_end_trans},
+
+ { "","Updating:","",0},
+ { "record_insert","record",
+ "inserts an sgml record into Default",
+ cmd_record_insert},
+ { "exchange_record","database record-id action record",
+ "inserts (1), updates (2), or deletes (3) a record \n"
+ "record-id must be a unique identifier for the record",
+ cmd_exchange_record},
+
+ { "","Searching and retrieving:","",0},
+ { "search_pqf","setname query",
+ "search ",
+ cmd_search_pqf},
+ { "find","query",
+ "simplified search",
+ cmd_find},
+ { "f","query",
+ "simplified search",
+ cmd_find},
+ { "show","[start] [numrecs] [resultset]",
+ "shows a result",
+ cmd_show},
+ { "s","[start] [numrecs] [resultset]",
+ "shows a result",
+ cmd_show},
+ { "sort","sortspec",
+ "sorts a result set. (example spec: 1=4 >)",
+ cmd_sort},
+
+ { "", "Misc:","", 0},
+ { "echo", "string",
+ "ouputs the string",
+ cmd_echo },
+ { "q", "",
+ "exits the program",
+ cmd_quit },
+ { "quit", "",
+ "exits the program",
+ cmd_quit },
+ { "help", "[command]",
+ "Gives help on command, or lists them all",
+ cmd_help },
+ { "", "help [command] gives more info on command", "",0 },
+
+ {0,0,0,0} /* end marker */
+};
+
+int onecommand(
+ char *line, /* input line */
+ WRBUF outbuff, /* output goes here */
+ const char *prevout) /* prev output, for 'expect' */
+{
+ int i;
+ char *args[MAX_NO_ARGS];
+ int nargs;
+ char argbuf[MAX_ARG_LEN];
+ yaz_log(log_level,"%s",line);
+ strncpy(argbuf,line, MAX_ARG_LEN-1);
+ argbuf[MAX_ARG_LEN-1]='\0'; /* just to be sure */
+ /*memset(args,'\0',MAX_NO_ARGS*sizeof(char *));*/
+ nargs=split_args(argbuf, args);
+
+#if 0
+ for (i = 0; i <= n; i++)
+ {
+ const char *cp = args[i];
+ printf ("args %d :%s:\n", i, cp ? cp : "<null>");
+ }
+#endif
+ if (0==nargs)
+ return -90; /* no command on line, too bad */
+
+ if (0==strcmp(args[0],"expect"))
+ {
+ char *rest;
+ if (nargs>1) /* args[0] is not yet set, can't use restargs */
+ rest= line + (args[1]-argbuf); /* rest of the line */
+ else
+ return -1; /* need something to expect */
+ if (0==strstr(prevout,rest))
+ {
+ printf( "Failed expectation, '%s' not found\n", rest);
+ exit(9);
+ }
+ return 0;
+ }
+ for (i=0;cmds[i].cmd;i++)
+ if (0==strcmp(cmds[i].cmd, args[0]))
+ {
+ if (nargs>1)
+ args[0]= line + (args[1]-argbuf); /* rest of the line */
+ else
+ args[0]="";
+ return ((cmds[i].testfunc)(args,outbuff));
+ }
+ wrbuf_printf(outbuff, "Unknown command '%s'. Try help\n",args[0]);
+ yaz_log(log_level,"Unknown command");
+ return -90;
+}
+
+static int cmd_help( char *args[], WRBUF outbuff)
+{
+ int i;
+ int linelen;
+ if (args[1])
+ { /* help for a single command */
+ for (i=0;cmds[i].cmd;i++)
+ if (0==strcmp(cmds[i].cmd, args[1]))
+ {
+ wrbuf_printf(outbuff,"%s %s\n%s\n",
+ cmds[i].cmd, cmds[i].args,
+ cmds[i].explanation);
+ return 0;
+ }
+ wrbuf_printf(outbuff, "Unknown command '%s'", args[1]);
+ }
+ else
+ { /* list all commands */
+ linelen=9999;
+ for (i=0;cmds[i].cmd;i++)
+ {
+ if (*cmds[i].cmd)
+ { /* ordinary command */
+ if (linelen>50)
+ {
+ wrbuf_puts(outbuff,"\n ");
+ linelen=0;
+ }
+ linelen += strlen(cmds[i].cmd) + 2;
+ wrbuf_printf(outbuff,"%s ", cmds[i].cmd);
+ } else
+ { /* section head */
+ wrbuf_printf(outbuff,"\n%s\n ",cmds[i].args);
+ linelen=0;
+ }
+ } /* for */
+ wrbuf_puts(outbuff,"\n");
+ }