2 * Copyright (c) 1998-2007, Index Data.
3 * See the file LICENSE for details.
5 * $Id: yaz-my-client.cpp,v 1.28 2007-04-16 21:54:23 adam Exp $
10 #include <yaz/options.h>
11 #include <yaz/diagbib1.h>
12 #include <yaz/marcdisp.h>
13 #include <yazpp/ir-assoc.h>
14 #include <yazpp/pdu-assoc.h>
15 #include <yazpp/socket-manager.h>
16 #include <yaz/oid_db.h>
19 #if HAVE_READLINE_READLINE_H
20 #include <readline/readline.h>
22 #if HAVE_READLINE_HISTORY_H
23 #include <readline/history.h>
27 using namespace yazpp_1;
29 class YAZ_EXPORT MyClient : public IR_Assoc {
31 int m_interactive_flag;
32 char m_thisCommand[1024];
33 char m_lastCommand[1024];
35 SocketManager *m_socketManager;
37 MyClient(IPDU_Observable *the_PDU_Observable,
38 SocketManager *the_SocketManager);
39 IPDU_Observer *sessionNotify(
40 IPDU_Observable *the_PDU_Observable, int fd);
41 int args(SocketManager *socketManager, int argc, char **argv);
42 int interactive(SocketManager *socketManager);
44 void recv_initResponse(Z_InitResponse *initResponse);
45 void recv_searchResponse(Z_SearchResponse *searchResponse);
46 void recv_presentResponse(Z_PresentResponse *presentResponse);
47 void recv_records (Z_Records *records);
48 void recv_diagrecs(Z_DiagRec **pp, int num);
49 void recv_namePlusRecord (Z_NamePlusRecord *zpr, int offset);
50 void recv_record(Z_DatabaseRecord *record, int offset,
51 const char *databaseName);
52 void recv_textRecord(const char *buf, size_t len);
53 void recv_genericRecord(Z_GenericRecord *r);
57 char *get_cookie (Z_OtherInformation **oi);
58 int processCommand(const char *cmd);
59 const char *getCommand();
60 int cmd_open(char *host);
61 int cmd_connect(char *host);
62 int cmd_quit(char *args);
63 int cmd_close(char *args);
64 int cmd_find(char *args);
65 int cmd_show(char *args);
66 int cmd_cookie(char *args);
67 int cmd_init(char *args);
68 int cmd_format(char *args);
69 int cmd_proxy(char *args);
73 void MyClient::connectNotify()
75 printf ("Connection accepted by target\n");
79 void MyClient::timeoutNotify()
81 printf ("Connection timeout\n");
85 void MyClient::failNotify()
87 printf ("Connection closed by target\n");
91 IPDU_Observer *MyClient::sessionNotify(IPDU_Observable *the_PDU_Observable,
94 return new MyClient(the_PDU_Observable, m_socketManager);
97 MyClient::MyClient(IPDU_Observable *the_PDU_Observable,
98 SocketManager *the_socketManager) :
99 IR_Assoc (the_PDU_Observable)
102 m_interactive_flag = 1;
103 m_thisCommand[0] = '\0';
104 m_lastCommand[0] = '\0';
105 m_socketManager = the_socketManager;
108 void usage(char *prog)
110 fprintf (stderr, "%s: [-v log] [-c cookie] [-p proxy] [zurl]\n", prog);
114 char *MyClient::get_cookie(Z_OtherInformation **otherInfo)
116 Z_OtherInformationUnit *oi =
117 update_otherInformation(otherInfo, 0, yaz_oid_userinfo_cookie, 1, 1);
119 if (oi->which == Z_OtherInfo_characterInfo)
120 return oi->information.characterInfo;
124 void MyClient::recv_initResponse(Z_InitResponse *initResponse)
126 printf ("Got InitResponse. Status ");
127 if (*initResponse->result)
131 const char *p = get_cookie (&initResponse->otherInfo);
134 printf ("cookie = %s\n", p);
142 void MyClient::recv_diagrecs(Z_DiagRec **pp, int num)
145 Z_DefaultDiagFormat *r;
147 printf("Diagnostic message(s) from database:\n");
148 for (i = 0; i<num; i++)
150 Z_DiagRec *p = pp[i];
151 if (p->which != Z_DiagRec_defaultFormat)
153 printf("Diagnostic record not in default format.\n");
157 r = p->u.defaultFormat;
158 printf(" [%d] %s", *r->condition, diagbib1_str(*r->condition));
161 case Z_DefaultDiagFormat_v2Addinfo:
162 printf (" -- v2 addinfo '%s'\n", r->u.v2Addinfo);
164 case Z_DefaultDiagFormat_v3Addinfo:
165 printf (" -- v3 addinfo '%s'\n", r->u.v3Addinfo);
171 void MyClient::recv_textRecord(const char *buf, size_t len)
173 fwrite (buf, 1, len, stdout);
174 fputc ('\n', stdout);
177 void MyClient::recv_genericRecord(Z_GenericRecord *r)
179 WRBUF w = wrbuf_alloc();
180 yaz_display_grs1(w, r, 0);
181 fwrite(wrbuf_buf(w), 1, wrbuf_len(w), stdout);
185 void MyClient::recv_record(Z_DatabaseRecord *record, int offset,
186 const char *databaseName)
188 Z_External *r = (Z_External*) record;
190 * Tell the user what we got.
192 if (r->direct_reference)
194 char name_oid_str[OID_STR_MAX];
195 const char *name_oid = yaz_oid_to_string_buf(r->direct_reference, 0,
197 printf("Record type: %s\n", name_oid ? name_oid : "unknown");
199 if (r->which == Z_External_octet && record->u.octet_aligned->len)
201 if (yaz_oid_is_iso2709(r->direct_reference))
203 yaz_marc_t mt = yaz_marc_create();
205 const char *result_buf;
207 yaz_marc_decode_buf(mt, (const char *)
208 record->u.octet_aligned->buf,
209 record->u.octet_aligned->len,
210 &result_buf, &result_size);
211 fwrite(result_buf, 1, result_size, stdout);
212 yaz_marc_destroy(mt);
216 recv_textRecord((const char *) record->u.octet_aligned->buf,
217 (size_t) record->u.octet_aligned->len);
220 else if (r->which == Z_External_sutrs)
221 recv_textRecord((const char *) r->u.sutrs->buf,
222 (size_t) r->u.sutrs->len);
223 else if (r->which == Z_External_grs1)
224 recv_genericRecord(r->u.grs1);
227 printf("Unknown record representation.\n");
228 if (!z_External(odr_print(), &r, 0, 0))
230 odr_perror(odr_print(), "Printing external");
231 odr_reset(odr_print());
236 void MyClient::recv_namePlusRecord (Z_NamePlusRecord *zpr, int offset)
238 if (zpr->databaseName)
239 printf("[%s]", zpr->databaseName);
240 if (zpr->which == Z_NamePlusRecord_surrogateDiagnostic)
241 recv_diagrecs(&zpr->u.surrogateDiagnostic, 1);
243 recv_record(zpr->u.databaseRecord, offset, zpr->databaseName);
246 void MyClient::recv_records (Z_Records *records)
248 Z_DiagRec dr, *dr_p = &dr;
252 switch (records->which)
254 case Z_Records_DBOSD:
255 for (i = 0; i < records->u.databaseOrSurDiagnostics->num_records; i++)
256 recv_namePlusRecord(records->u.databaseOrSurDiagnostics->
257 records[i], i + m_setOffset);
258 m_setOffset += records->u.databaseOrSurDiagnostics->num_records;
261 dr.which = Z_DiagRec_defaultFormat;
262 dr.u.defaultFormat = records->u.nonSurrogateDiagnostic;
263 recv_diagrecs (&dr_p, 1);
265 case Z_Records_multipleNSD:
266 recv_diagrecs (records->u.multipleNonSurDiagnostics->diagRecs,
267 records->u.multipleNonSurDiagnostics->num_diagRecs);
272 void MyClient::recv_searchResponse(Z_SearchResponse *searchResponse)
274 printf ("Got SearchResponse. Status ");
275 if (!*searchResponse->searchStatus)
282 printf ("Hits: %d\n", *searchResponse->resultCount);
284 recv_records (searchResponse->records);
287 void MyClient::recv_presentResponse(Z_PresentResponse *presentResponse)
289 printf ("Got PresentResponse\n");
290 recv_records (presentResponse->records);
296 while (m_socketManager->processEvent() > 0)
298 if (get_lastReceived())
305 #define C_PROMPT "Z>"
307 int MyClient::cmd_connect(char *host)
316 int MyClient::cmd_open(char *host)
327 int MyClient::cmd_init(char *args)
329 if (send_initRequest() >= 0)
336 int MyClient::cmd_quit(char *args)
341 int MyClient::cmd_close(char *args)
347 int MyClient::cmd_find(char *args)
351 if (query.set_rpn(args) <= 0)
353 printf ("Bad RPN query\n");
356 if (send_searchRequest(&query) >= 0)
359 printf ("Not connected\n");
363 int MyClient::cmd_show(char *args)
365 int start = m_setOffset, number = 1;
367 sscanf (args, "%d %d", &start, &number);
369 if (send_presentRequest(start, number) >= 0)
372 printf ("Not connected\n");
376 int MyClient::cmd_cookie(char *args)
378 set_cookie(*args ? args : 0);
382 int MyClient::cmd_format(char *args)
384 set_preferredRecordSyntax(args);
388 int MyClient::cmd_proxy(char *args)
394 int MyClient::processCommand(const char *commandLine)
396 char cmdStr[1024], cmdArgs[1024];
401 int (MyClient::*fun)(char *arg);
404 {"open", &MyClient::cmd_open, "<host>[':'<port>][/<database>]"},
405 {"connect", &MyClient::cmd_connect, "<host>[':'<port>][/<database>]"},
406 {"quit", &MyClient::cmd_quit, ""},
407 {"close", &MyClient::cmd_close, ""},
408 {"find", &MyClient::cmd_find, "<query>"},
409 {"show", &MyClient::cmd_show, "[<start> [<number>]]"},
410 {"cookie", &MyClient::cmd_cookie, "<cookie>"},
411 {"init", &MyClient::cmd_init, ""},
412 {"format", &MyClient::cmd_format, "<record-syntax>"},
413 {"proxy", &MyClient::cmd_proxy, "<host>:[':'<port>]"},
417 if (sscanf(commandLine, "%s %[^;]", cmdStr, cmdArgs) < 1)
420 for (i = 0; cmd[i].cmd; i++)
421 if (!strncmp(cmd[i].cmd, cmdStr, strlen(cmdStr)))
425 if (cmd[i].cmd) // Invoke command handler
426 res = (this->*cmd[i].fun)(cmdArgs);
427 else // Dump help screen
429 printf("Unknown command: %s.\n", cmdStr);
430 printf("Currently recognized commands:\n");
431 for (i = 0; cmd[i].cmd; i++)
432 printf(" %s %s\n", cmd[i].cmd, cmd[i].ad);
437 const char *MyClient::getCommand()
439 #if HAVE_READLINE_READLINE_H
440 // Read using GNU readline
442 line_in=readline(C_PROMPT);
445 #if HAVE_READLINE_HISTORY_H
447 add_history(line_in);
449 strncpy(m_thisCommand,line_in, 1023);
450 m_thisCommand[1023] = '\0';
453 // Read using fgets(3)
456 if (!fgets(m_thisCommand, 1023, stdin))
459 // Remove trailing whitespace
460 char *cp = m_thisCommand + strlen(m_thisCommand);
461 while (cp != m_thisCommand && strchr("\t \n", cp[-1]))
465 // Remove leading spaces...
466 while (*cp && strchr ("\t \n", *cp))
468 // Save command if non-empty
470 strcpy (m_lastCommand, cp);
471 return m_lastCommand;
474 int MyClient::interactive(SocketManager *socketManager)
477 if (!m_interactive_flag)
479 while ((cmd = getCommand()))
481 if (!processCommand(cmd))
487 int MyClient::args(SocketManager *socketManager, int argc, char **argv)
492 char *prog = argv[0];
495 while ((ret = options("c:p:v:q", argv, argc, &arg)) != -2)
519 yaz_log_init_level (yaz_log_mask_str(arg));
522 m_interactive_flag = 0;
541 int main(int argc, char **argv)
543 SocketManager mySocketManager;
544 PDU_Assoc *some = new PDU_Assoc(&mySocketManager);
546 MyClient z(some, &mySocketManager);
548 if (z.args(&mySocketManager, argc, argv))
550 if (z.interactive(&mySocketManager))
557 * indent-tabs-mode: nil
559 * vim: shiftwidth=4 tabstop=8 expandtab