X-Git-Url: http://git.indexdata.com/?p=yaz-moved-to-github.git;a=blobdiff_plain;f=client%2Fclient.c;h=c158b00acb45c749c94b037c0bda9274679e5b25;hp=396be27b5a91663ab8331441b21bdf0a7e1061f4;hb=a92ea4f2be422ed5f52f0fc1c8b6416aebfe0c5a;hpb=e8b504e6b88e1254fb1c329a74fd1afaf973570b diff --git a/client/client.c b/client/client.c index 396be27..c158b00 100644 --- a/client/client.c +++ b/client/client.c @@ -1,8 +1,8 @@ /* - * Copyright (C) 1995-2006, Index Data ApS + * Copyright (C) 1995-2007, Index Data ApS * See the file LICENSE for details. * - * $Id: client.c,v 1.318 2006-11-08 08:55:50 adam Exp $ + * $Id: client.c,v 1.350 2007-08-21 13:19:44 adam Exp $ */ /** \file client.c * \brief yaz-client program @@ -13,6 +13,9 @@ #include #include #include +#ifndef WIN32 +#include +#endif #if HAVE_SYS_TYPES_H #include #endif @@ -53,11 +56,14 @@ #include +#include +#define NO_OID 1 #include #include #include #include #include +#include #include #include @@ -78,9 +84,12 @@ #include "admin.h" #include "tabcomplete.h" +#include "fhistory.h" #define C_PROMPT "Z> " +static file_history_t file_history = 0; + static char *sru_method = "soap"; static char *codeset = 0; /* character set for output */ static int hex_dump = 0; @@ -105,8 +114,8 @@ static Z_ElementSetNames *elementSetNames = 0; static int setno = 1; /* current set offset */ static enum oid_proto protocol = PROTO_Z3950; /* current app protocol */ #define RECORDSYNTAX_MAX 20 -static enum oid_value recordsyntax_list[RECORDSYNTAX_MAX] = { VAL_USMARC }; -static int recordsyntax_size = 1; +static char *recordsyntax_list[RECORDSYNTAX_MAX]; +static int recordsyntax_size = 0; static char *record_schema = 0; static int sent_close = 0; @@ -125,6 +134,7 @@ static int negotiationCharsetRecords = 1; static int negotiationCharsetVersion = 3; static char *outputCharset = 0; static char *marcCharset = 0; +static char *queryCharset = 0; static char* yazLang = 0; static char last_cmd[32] = "?"; @@ -152,7 +162,7 @@ typedef enum { static QueryType queryType = QueryType_Prefix; static CCL_bibset bibset; /* CCL bibset handle */ -static cql_transform_t cqltrans; /* CQL context-set handle */ +static cql_transform_t cqltrans = 0; /* CQL context-set handle */ #if HAVE_READLINE_COMPLETION_OVER @@ -161,15 +171,11 @@ static cql_transform_t cqltrans; /* CQL context-set handle */ int rl_attempted_completion_over = 0; #endif -/* set this one to 1, to avoid decode of unknown MARCs */ -#define AVOID_MARC_DECODE 1 - #define maxOtherInfosSupported 10 -struct { - int oidval; +struct eoi { + Odr_oid oid[OID_SIZE]; char* value; } extraOtherInfos[maxOtherInfosSupported]; - void process_cmd_line(char* line); #if HAVE_READLINE_READLINE_H @@ -177,6 +183,7 @@ char **readline_completer(char *text, int start, int end); #endif static char *command_generator(const char *text, int state); int cmd_register_tab(const char* arg); +int cmd_querycharset(const char *arg); static void close_session (void); @@ -238,8 +245,8 @@ void add_otherInfos(Z_APDU *a) yaz_oi_APDU(a, &oi); for(i=0; i 0) + yaz_oi_set_string_oid(oi, out, extraOtherInfos[i].oid, 1, extraOtherInfos[i].value); } } @@ -330,9 +337,11 @@ static void send_initRequest(const char* type_and_host) req->referenceId = set_refid (out); - if (yazProxy && type_and_host) - yaz_oi_set_string_oidval(&req->otherInfo, out, VAL_PROXY, - 1, type_and_host); + if (yazProxy && type_and_host) + { + yaz_oi_set_string_oid(&req->otherInfo, out, yaz_oid_userinfo_proxy, + 1, type_and_host); + } if (negotiationCharset || yazLang) { Z_OtherInformation **p; @@ -340,7 +349,8 @@ static void send_initRequest(const char* type_and_host) yaz_oi_APDU(apdu, &p); - if ((p0=yaz_oi_update(p, out, NULL, 0, 0))) { + if ((p0=yaz_oi_update(p, out, NULL, 0, 0))) + { ODR_MASK_SET(req->options, Z_Options_negotiationModel); p0->which = Z_OtherInfo_externallyDefinedInfo; @@ -351,7 +361,21 @@ static void send_initRequest(const char* type_and_host) negotiationCharsetRecords); } } - + else if (ODR_MASK_GET(req->options, Z_Options_negotiationModel)) + { + Z_OtherInformation **p; + Z_OtherInformationUnit *p0; + + yaz_oi_APDU(apdu, &p); + + if ((p0=yaz_oi_update(p, out, NULL, 0, 0))) + { + p0->which = Z_OtherInfo_externallyDefinedInfo; + p0->information.externallyDefinedInfo = + yaz_set_proposal_charneg(out, 0, 0, 0, 0, 0); + } + + } if (send_apdu(apdu)) printf("Sent initrequest.\n"); } @@ -407,8 +431,9 @@ static int process_initResponse(Z_InitResponse *res) else if (uif->which == Z_External_single) { Odr_any *sat = uif->u.single_ASN1_type; - oident *oid = oid_getentbyoid(uif->direct_reference); - if (oid->value == VAL_OCLCUI) { + if (!oid_oidcmp(uif->direct_reference, + yaz_oid_userinfo_oclc_userinfo)) + { Z_OCLC_UserInformation *oclc_ui; ODR decode = odr_createmem(ODR_DECODE); odr_setbuf(decode, (char *) sat->buf, sat->len, 0); @@ -441,27 +466,32 @@ static int process_initResponse(Z_InitResponse *res) Z_CharSetandLanguageNegotiation *p = yaz_get_charneg_record(res->otherInfo); - - if (p) { - + + if (p) + { char *charset=NULL, *lang=NULL; int selected; yaz_get_response_charneg(session_mem, p, &charset, &lang, &selected); - if (outputCharset && negotiationCharset) { - odr_set_charset (out, charset, outputCharset); - odr_set_charset (in, outputCharset, charset); + printf("Accepted character set : %s\n", charset ? charset:"none"); + printf("Accepted code language : %s\n", lang ? lang:"none"); + printf("Accepted records in ...: %d\n", selected ); + + if (outputCharset && charset) + { + printf("Converting between %s and %s\n", + outputCharset, charset); + odr_set_charset(out, charset, outputCharset); + odr_set_charset(in, outputCharset, charset); + cmd_querycharset(charset); } - else { - odr_set_charset (out, 0, 0); - odr_set_charset (in, 0, 0); + else + { + odr_set_charset(out, 0, 0); + odr_set_charset(in, 0, 0); } - - printf("Accepted character set : %s\n", charset); - printf("Accepted code language : %s\n", lang ? lang : "none"); - printf("Accepted records in ...: %d\n", selected ); } } fflush (stdout); @@ -610,7 +640,7 @@ static int parse_cmd_doc(const char **arg, ODR out, char **buf, return 0; } *len = fsize; - *buf = odr_malloc(out, fsize); + *buf = (char *) odr_malloc(out, fsize); if (fread(*buf, 1, fsize, inf) != fsize) { printf("Unable to read %s\n", fname); @@ -845,27 +875,26 @@ static void print_record(const unsigned char *buf, size_t len) static void display_record(Z_External *r) { - oident *ent = oid_getentbyoid(r->direct_reference); - + const Odr_oid *oid = r->direct_reference; + record_last = r; /* * Tell the user what we got. */ - if (r->direct_reference) + if (oid) { + oid_class oclass; + char oid_name_buf[OID_STR_MAX]; + const char *oid_name + = yaz_oid_to_string_buf(oid, &oclass, oid_name_buf); printf("Record type: "); - if (ent) - printf("%s\n", ent->desc); - else if (!odr_oid(print, &r->direct_reference, 0, 0)) - { - odr_perror(print, "print oid"); - odr_reset(print); - } + if (oid_name) + printf("%s\n", oid_name); } /* Check if this is a known, ASN.1 type tucked away in an octet string */ - if (ent && r->which == Z_External_octet) + if (r->which == Z_External_octet) { - Z_ext_typeent *type = z_ext_getentbyref(ent->value); + Z_ext_typeent *type = z_ext_getentbyref(r->direct_reference); char *rr; if (type) @@ -895,25 +924,24 @@ static void display_record(Z_External *r) } } } - if (ent && ent->value == VAL_SOIF) + if (oid && !oid_oidcmp(oid, yaz_oid_recsyn_soif)) { print_record((const unsigned char *) r->u.octet_aligned->buf, r->u.octet_aligned->len); if (marc_file) fwrite (r->u.octet_aligned->buf, 1, r->u.octet_aligned->len, marc_file); } - else if (r->which == Z_External_octet) + else if (oid && r->which == Z_External_octet) { const char *octet_buf = (char*)r->u.octet_aligned->buf; - if (ent->oclass == CLASS_RECSYN && - (ent->value == VAL_TEXT_XML || - ent->value == VAL_APPLICATION_XML || - ent->value == VAL_HTML)) + if (oid && (!oid_oidcmp(oid, yaz_oid_recsyn_xml) + || !oid_oidcmp(oid, yaz_oid_recsyn_xml) + || !oid_oidcmp(oid, yaz_oid_recsyn_html))) { print_record((const unsigned char *) octet_buf, r->u.octet_aligned->len); } - else if (ent->value == VAL_POSTSCRIPT) + else if (oid && !oid_oidcmp(oid, yaz_oid_recsyn_postscript)) { int size = r->u.octet_aligned->len; if (size > 100) @@ -922,76 +950,47 @@ static void display_record(Z_External *r) } else { - if ( -#if AVOID_MARC_DECODE - /* primitive check for a marc OID 5.1-29 except 16 */ - ent->oidsuffix[0] == 5 && ent->oidsuffix[1] < 30 && - ent->oidsuffix[1] != 16 -#else - 1 -#endif - ) + if (oid && yaz_oid_is_iso2709(oid)) { - char *result; - int rlen; + const char *result; + size_t rlen; yaz_iconv_t cd = 0; yaz_marc_t mt = yaz_marc_create(); - - if (yaz_marc_decode_buf(mt, octet_buf,r->u.octet_aligned->len, - &result, &rlen)> 0) + const char *from = 0; + + if (marcCharset && !strcmp(marcCharset, "auto")) { - char *from = 0; - if (marcCharset && !strcmp(marcCharset, "auto")) + if (!oid_oidcmp(oid, yaz_oid_recsyn_usmarc)) { - if (ent->value == VAL_USMARC) - { - if (octet_buf[9] == 'a') - from = "UTF-8"; - else - from = "MARC-8"; - } - else - from = "ISO-8859-1"; - } - else if (marcCharset) - from = marcCharset; - if (outputCharset && from) - { - cd = yaz_iconv_open(outputCharset, from); - printf ("convert from %s to %s", from, - outputCharset); - if (!cd) - printf (" unsupported\n"); + if (octet_buf[9] == 'a') + from = "UTF-8"; else - printf ("\n"); + from = "MARC-8"; } + else + from = "ISO-8859-1"; + } + else if (marcCharset) + from = marcCharset; + if (outputCharset && from) + { + cd = yaz_iconv_open(outputCharset, from); + printf ("convert from %s to %s", from, + outputCharset); if (!cd) - fwrite (result, 1, rlen, stdout); + printf (" unsupported\n"); else { - char outbuf[6]; - size_t inbytesleft = rlen; - const char *inp = result; - - while (inbytesleft) - { - size_t outbytesleft = sizeof(outbuf); - char *outp = outbuf; - size_t r; - - r = yaz_iconv (cd, (char**) &inp, - &inbytesleft, - &outp, &outbytesleft); - if (r == (size_t) (-1)) - { - int e = yaz_iconv_error(cd); - if (e != YAZ_ICONV_E2BIG) - break; - } - fwrite (outbuf, outp - outbuf, 1, stdout); - } + yaz_marc_iconv(mt, cd); + printf ("\n"); } } + + if (yaz_marc_decode_buf(mt, octet_buf, r->u.octet_aligned->len, + &result, &rlen)> 0) + { + fwrite (result, rlen, 1, stdout); + } else { printf ("bad MARC. Dumping as it is:\n"); @@ -1011,7 +1010,7 @@ static void display_record(Z_External *r) if (marc_file) fwrite (octet_buf, 1, r->u.octet_aligned->len, marc_file); } - else if (ent && ent->value == VAL_SUTRS) + else if (oid && !oid_oidcmp(oid, yaz_oid_recsyn_sutrs)) { if (r->which != Z_External_sutrs) { @@ -1022,7 +1021,7 @@ static void display_record(Z_External *r) if (marc_file) fwrite (r->u.sutrs->buf, 1, r->u.sutrs->len, marc_file); } - else if (ent && ent->value == VAL_GRS1) + else if (oid && !oid_oidcmp(oid, yaz_oid_recsyn_grs_1)) { WRBUF w; if (r->which != Z_External_grs1) @@ -1032,10 +1031,10 @@ static void display_record(Z_External *r) } w = wrbuf_alloc(); yaz_display_grs1(w, r->u.grs1, 0); - puts (wrbuf_buf(w)); - wrbuf_free(w, 1); + puts (wrbuf_cstr(w)); + wrbuf_destroy(w); } - else if (ent && ent->value == VAL_OPAC) + else if (oid && !oid_oidcmp(oid, yaz_oid_recsyn_opac)) { int i; if (r->u.opac->bibliographicRecord) @@ -1151,7 +1150,6 @@ static void display_record(Z_External *r) static void display_diagrecs(Z_DiagRec **pp, int num) { int i; - oident *ent; Z_DefaultDiagFormat *r; printf("Diagnostic message(s) from database:\n"); @@ -1165,9 +1163,19 @@ static void display_diagrecs(Z_DiagRec **pp, int num) } else r = p->u.defaultFormat; - if (!(ent = oid_getentbyoid(r->diagnosticSetId)) || - ent->oclass != CLASS_DIAGSET || ent->value != VAL_BIB1) - printf("Missing or unknown diagset\n"); + + if (!r->diagnosticSetId) + printf("Missing diagset\n"); + else + { + oid_class oclass; + char diag_name_buf[OID_STR_MAX]; + const char *diag_name = 0; + diag_name = yaz_oid_to_string_buf + (r->diagnosticSetId, &oclass, diag_name_buf); + if (oid_oidcmp(r->diagnosticSetId, yaz_oid_diagset_bib_1)) + printf("Unknown diagset: %s\n", diag_name); + } printf(" [%d] %s", *r->condition, diagbib1_str(*r->condition)); switch (r->which) { @@ -1259,7 +1267,7 @@ static int send_srw(Z_SRW_PDU *sr) Z_GDU *gdu; char *path = 0; - path = odr_malloc(out, 2+strlen(databaseNames[0])); + path = (char *) odr_malloc(out, 2+strlen(databaseNames[0])); *path = '/'; strcpy(path+1, databaseNames[0]); @@ -1317,19 +1325,16 @@ static char *encode_SRW_term(ODR o, const char *q) cd = yaz_iconv_open("UTF-8", in_charset); if (!cd) { - wrbuf_free(w, 1); + wrbuf_destroy(w); return odr_strdup(o, q); } wrbuf_iconv_write(w, cd, q, strlen(q)); if (wrbuf_len(w)) - { - int len = wrbuf_len(w); - res = odr_strdupn(o, wrbuf_buf(w), len); - } + res = odr_strdup(o, wrbuf_cstr(w)); else res = odr_strdup(o, q); yaz_iconv_close(cd); - wrbuf_free(w, 1); + wrbuf_destroy(w); return res; } @@ -1403,12 +1408,28 @@ static int send_SRW_searchRequest(const char *arg) if (record_schema) sr->u.request->recordSchema = record_schema; - if (recordsyntax_size == 1 && recordsyntax_list[0] == VAL_TEXT_XML) + if (recordsyntax_size == 1 && !yaz_matchstr(recordsyntax_list[0], "xml")) sr->u.request->recordPacking = "xml"; return send_srw(sr); } #endif +static void query_charset_convert(Z_RPNQuery *q) +{ + if (queryCharset && outputCharset) + { + yaz_iconv_t cd = yaz_iconv_open(queryCharset, outputCharset); + if (!cd) + { + printf("Conversion from %s to %s unsupported\n", + outputCharset, queryCharset); + return; + } + yaz_query_charset_convert_rpnquery(q, out, cd); + yaz_iconv_close(cd); + } +} + static int send_searchRequest(const char *arg) { Z_APDU *apdu = zget_APDU(out, Z_APDU_searchRequest); @@ -1482,9 +1503,11 @@ static int send_searchRequest(const char *arg) if (smallSetUpperBound > 0 || (largeSetLowerBound > 1 && mediumSetPresentNumber > 0)) { - if (recordsyntax_size > 0) + if (recordsyntax_size) req->preferredRecordSyntax = - yaz_oidval_to_z3950oid(out, CLASS_RECSYN, recordsyntax_list[0]); + yaz_string_to_oid_odr(yaz_oid_std(), + CLASS_RECSYN, recordsyntax_list[0], out); + req->smallSetElementSetNames = req->mediumSetElementSetNames = elementSetNames; } @@ -1512,6 +1535,7 @@ static int send_searchRequest(const char *arg) return 0; } yaz_pqf_destroy (pqf_parser); + query_charset_convert(RPNquery); query.u.type_1 = RPNquery; break; case QueryType_CCL: @@ -1528,6 +1552,7 @@ static int send_searchRequest(const char *arg) printf ("Couldn't convert from CCL to RPN\n"); return 0; } + query_charset_convert(RPNquery); query.u.type_1 = RPNquery; ccl_rpn_delete (rpn); break; @@ -1633,7 +1658,25 @@ static int process_searchResponse(Z_SearchResponse *res) last_hit_count = *res->resultCount; if (setnumber >= 0) printf (", setno %d", setnumber); - printf ("\n"); + putchar('\n'); + if (res->resultSetStatus) + { + printf("Result Set Status: "); + switch(*res->resultSetStatus) + { + case Z_SearchResponse_subset: + printf("subset"); break; + case Z_SearchResponse_interim: + printf("interim"); break; + case Z_SearchResponse_none: + printf("none"); break; + case Z_SearchResponse_estimate: + printf("estimate"); break; + default: + printf("%d", *res->resultSetStatus); + } + putchar('\n'); + } display_searchResult (res->additionalSearchInfo); printf("records returned: %d\n", *res->numberOfRecordsReturned); @@ -1672,7 +1715,7 @@ static void print_oid(int iLevel, const char *pTag, Odr_oid *pOid) { if (pOid != NULL) { - int *pInt = pOid; + Odr_oid *pInt = pOid; print_level(iLevel); printf("%s:", pTag); @@ -1872,6 +1915,20 @@ void process_ESResponse(Z_ExtendedServicesResponse *res) } } } + if (ext->which == Z_External_itemOrder) + { + Z_IOTaskPackage *otp = ext->u.itemOrder->u.taskPackage; + if (otp && otp->targetPart && otp->targetPart->itemRequest) + { + Z_External *ext = otp->targetPart->itemRequest; + if (ext->which == Z_External_octet) + { + Odr_oct *doc = ext->u.octet_aligned; + printf("Got itemRequest doc %.*s\n", + doc->len, doc->buf); + } + } + } } if (res->taskPackage && res->taskPackage->which == Z_External_octet) { @@ -1916,15 +1973,8 @@ static Z_External *create_external_itemRequest(void) } else { - oident oid; - - item_request_buf = odr_getbuf (out, &item_request_size, 0); - oid.proto = PROTO_GENERAL; - oid.oclass = CLASS_GENERAL; - oid.value = VAL_ISO_ILL_1; - r = (Z_External *) odr_malloc (out, sizeof(*r)); - r->direct_reference = odr_oiddup(out,oid_getoidbyent(&oid)); + r->direct_reference = odr_oiddup(out, yaz_oid_general_isoill_1); r->indirect_reference = 0; r->descriptor = 0; r->which = Z_External_single; @@ -1974,15 +2024,10 @@ static Z_External *create_external_ILL_APDU(int which) } else { - oident oid; ill_request_buf = odr_getbuf (out, &ill_request_size, 0); - oid.proto = PROTO_GENERAL; - oid.oclass = CLASS_GENERAL; - oid.value = VAL_ISO_ILL_1; - r = (Z_External *) odr_malloc (out, sizeof(*r)); - r->direct_reference = odr_oiddup(out,oid_getoidbyent(&oid)); + r->direct_reference = odr_oiddup(out, yaz_oid_general_isoill_1); r->indirect_reference = 0; r->descriptor = 0; r->which = Z_External_single; @@ -2006,13 +2051,7 @@ static Z_External *create_external_ILL_APDU(int which) static Z_External *create_ItemOrderExternal(const char *type, int itemno) { Z_External *r = (Z_External *) odr_malloc(out, sizeof(Z_External)); - oident ItemOrderRequest; - - ItemOrderRequest.proto = PROTO_Z3950; - ItemOrderRequest.oclass = CLASS_EXTSERV; - ItemOrderRequest.value = VAL_ITEMORDER; - - r->direct_reference = odr_oiddup(out,oid_getoidbyent(&ItemOrderRequest)); + r->direct_reference = odr_oiddup(out, yaz_oid_extserv_item_order); r->indirect_reference = 0; r->descriptor = 0; @@ -2060,14 +2099,14 @@ static Z_External *create_ItemOrderExternal(const char *type, int itemno) } else if (!strcmp(type, "xml") || !strcmp(type, "3")) { - const char *xml_buf = - "\n" - " request\n" - " 000200\n" - " 1212 \n" - ""; + const char *xml_buf = + "\n" + " request\n" + " 000200\n" + " 1212 \n" + ""; r->u.itemOrder->u.esRequest->notToKeep->itemRequest = - z_ext_record (out, VAL_TEXT_XML, xml_buf, strlen(xml_buf)); + z_ext_record_oid(out, yaz_oid_recsyn_xml, xml_buf, strlen(xml_buf)); } else r->u.itemOrder->u.esRequest->notToKeep->itemRequest = 0; @@ -2079,15 +2118,10 @@ static int send_itemorder(const char *type, int itemno) { Z_APDU *apdu = zget_APDU(out, Z_APDU_extendedServicesRequest); Z_ExtendedServicesRequest *req = apdu->u.extendedServicesRequest; - oident ItemOrderRequest; - req->referenceId = set_refid (out); - ItemOrderRequest.proto = PROTO_Z3950; - ItemOrderRequest.oclass = CLASS_EXTSERV; - ItemOrderRequest.value = VAL_ITEMORDER; - req->packageType = odr_oiddup(out,oid_getoidbyent(&ItemOrderRequest)); + req->packageType = odr_oiddup(out, yaz_oid_extserv_item_order); req->packageName = esPackageName; req->taskSpecificParameters = create_ItemOrderExternal(type, itemno); @@ -2123,28 +2157,30 @@ static int cmd_update0(const char *arg) return cmd_update_common(arg, 0); } +static int cmd_update_Z3950(int version, int action_no, const char *recid, + char *rec_buf, int rec_len); + +static int cmd_update_SRW(int action_no, const char *recid, + char *rec_buf, int rec_len); + static int cmd_update_common(const char *arg, int version) { - Z_APDU *apdu = zget_APDU(out, Z_APDU_extendedServicesRequest ); - Z_ExtendedServicesRequest *req = apdu->u.extendedServicesRequest; - Z_External *r; - char action[20], recid[20]; + char action[20], recid_buf[20]; + const char *recid = 0; char *rec_buf; int rec_len; int action_no; int noread = 0; - Z_External *record_this = 0; - if (only_z3950()) - return 1; *action = 0; - *recid = 0; - sscanf (arg, "%19s %19s%n", action, recid, &noread); + *recid_buf = 0; + sscanf (arg, "%19s %19s%n", action, recid_buf, &noread); if (noread == 0) { - printf("Update must be followed by action and recid\n"); + printf("Use: update action recid [fname]\n"); printf(" where action is one of insert,replace,delete.update\n"); - printf(" recid is some record ID (any string)\n"); + printf(" recid is some record ID. Use none for no ID\n"); + printf(" fname is file of record to be updated\n"); return 0; } @@ -2163,12 +2199,69 @@ static int cmd_update_common(const char *arg, int version) return 0; } + if (strcmp(recid_buf, "none")) /* none means no record ID */ + recid = recid_buf; + arg += noread; if (parse_cmd_doc(&arg, out, &rec_buf, &rec_len, 1) == 0) return 0; +#if YAZ_HAVE_XML2 + if (protocol == PROTO_HTTP) + return cmd_update_SRW(action_no, recid, rec_buf, rec_len); +#endif + return cmd_update_Z3950(version, action_no, recid, rec_buf, rec_len); +} + +#if YAZ_HAVE_XML2 +static int cmd_update_SRW(int action_no, const char *recid, + char *rec_buf, int rec_len) +{ + if (!conn) + cmd_open(0); + if (!conn) + return 0; + else + { + Z_SRW_PDU *srw = yaz_srw_get(out, Z_SRW_update_request); + Z_SRW_updateRequest *sr = srw->u.update_request; + + switch(action_no) + { + case Z_IUOriginPartToKeep_recordInsert: + sr->operation = "info:srw/action/1/create"; + break; + case Z_IUOriginPartToKeep_recordReplace: + sr->operation = "info:srw/action/1/replace"; + break; + case Z_IUOriginPartToKeep_recordDelete: + sr->operation = "info:srw/action/1/delete"; + break; + } + if (rec_buf) + { + sr->record = yaz_srw_get_record(out); + sr->record->recordData_buf = rec_buf; + sr->record->recordData_len = rec_len; + sr->record->recordSchema = record_schema; + } + if (recid) + sr->recordId = odr_strdup(out, recid); + return send_srw(srw); + } +} +#endif + +static int cmd_update_Z3950(int version, int action_no, const char *recid, + char *rec_buf, int rec_len) +{ + Z_APDU *apdu = zget_APDU(out, Z_APDU_extendedServicesRequest ); + Z_ExtendedServicesRequest *req = apdu->u.extendedServicesRequest; + Z_External *r; + Z_External *record_this = 0; if (rec_buf) - record_this = z_ext_record (out, VAL_TEXT_XML, rec_buf, rec_len); + record_this = z_ext_record_oid(out, yaz_oid_recsyn_xml, + rec_buf, rec_len); else { if (!record_last) @@ -2179,9 +2272,9 @@ static int cmd_update_common(const char *arg, int version) record_this = record_last; } - req->packageType = - yaz_oidval_to_z3950oid(out, CLASS_EXTSERV, - version == 0 ? VAL_DBUPDATE0 : VAL_DBUPDATE); + req->packageType = odr_oiddup(out, (version == 0 ? + yaz_oid_extserv_database_update_first_version : + yaz_oid_extserv_database_update)); req->packageName = esPackageName; @@ -2220,7 +2313,7 @@ static int cmd_update_common(const char *arg, int version) notToKeep->elements[0] = (Z_IU0SuppliedRecords_elem *) odr_malloc(out, sizeof(**notToKeep->elements)); notToKeep->elements[0]->which = Z_IUSuppliedRecords_elem_opaque; - if (*recid) + if (recid) { notToKeep->elements[0]->u.opaque = (Odr_oct *) odr_malloc (out, sizeof(Odr_oct)); @@ -2262,7 +2355,7 @@ static int cmd_update_common(const char *arg, int version) notToKeep->elements[0] = (Z_IUSuppliedRecords_elem *) odr_malloc(out, sizeof(**notToKeep->elements)); notToKeep->elements[0]->which = Z_IUSuppliedRecords_elem_opaque; - if (*recid) + if (recid) { notToKeep->elements[0]->u.opaque = (Odr_oct *) odr_malloc (out, sizeof(Odr_oct)); @@ -2290,8 +2383,8 @@ static int cmd_xmles(const char *arg) { char *asn_buf = 0; int noread = 0; + Odr_oid *oid; char oid_str[51]; - int oid_value_xmles = VAL_XMLES; Z_APDU *apdu = zget_APDU(out, Z_APDU_extendedServicesRequest); Z_ExtendedServicesRequest *req = apdu->u.extendedServicesRequest; @@ -2311,24 +2404,24 @@ static int cmd_xmles(const char *arg) return 0; } arg += noread; - oid_value_xmles = oid_getvalbyname(oid_str); - if (oid_value_xmles == VAL_NONE) - { - printf("Bad OID: %s\n", oid_str); - return 0; - } - if (parse_cmd_doc(&arg, out, &asn_buf, &ext->u.single_ASN1_type->len, 0) == 0) return 0; ext->u.single_ASN1_type->buf = (unsigned char *) asn_buf; - req->packageType = yaz_oidval_to_z3950oid(out, CLASS_EXTSERV, - oid_value_xmles); + oid = yaz_string_to_oid_odr(yaz_oid_std(), + CLASS_EXTSERV, oid_str, out); + if (!oid) + { + printf("Bad OID: %s\n", oid_str); + return 0; + } + + req->packageType = oid; - ext->direct_reference = yaz_oidval_to_z3950oid(out, CLASS_EXTSERV, - oid_value_xmles); + ext->direct_reference = oid; + send_apdu(apdu); return 2; @@ -2398,7 +2491,8 @@ static int cmd_explain(const char *arg) /* save this for later .. when fetching individual records */ sr = yaz_srw_get(out, Z_SRW_explain_request); - if (recordsyntax_size > 0 && recordsyntax_list[0] == VAL_TEXT_XML) + if (recordsyntax_size == 1 + && !yaz_matchstr(recordsyntax_list[0], "xml")) sr->u.explain_request->recordPacking = "xml"; send_srw(sr); return 2; @@ -2587,9 +2681,10 @@ static int send_presentRequest(const char *arg) req->resultSetStartPoint = &setno; req->numberOfRecordsRequested = &nos; - if (recordsyntax_size == 1) + if (recordsyntax_size) req->preferredRecordSyntax = - yaz_oidval_to_z3950oid(out, CLASS_RECSYN, recordsyntax_list[0]); + yaz_string_to_oid_odr(yaz_oid_std(), + CLASS_RECSYN, recordsyntax_list[0], out); if (record_schema || recordsyntax_size >= 2) { @@ -2610,13 +2705,15 @@ static int send_presentRequest(const char *arg) else { compo.u.complex->generic->schema.oid = - yaz_str_to_z3950oid(out, CLASS_SCHEMA, record_schema); + yaz_string_to_oid_odr(yaz_oid_std(), + CLASS_SCHEMA, record_schema, out); if (!compo.u.complex->generic->schema.oid) { /* OID wasn't a schema! Try record syntax instead. */ compo.u.complex->generic->schema.oid = (Odr_oid *) - yaz_str_to_z3950oid(out, CLASS_RECSYN, record_schema); + yaz_string_to_oid_odr(yaz_oid_std(), + CLASS_RECSYN, record_schema, out); } } if (!elementSetNames) @@ -2632,6 +2729,9 @@ static int send_presentRequest(const char *arg) } compo.u.complex->num_dbSpecific = 0; compo.u.complex->dbSpecific = 0; + + compo.u.complex->num_recordSyntax = 0; + compo.u.complex->recordSyntax = 0; if (recordsyntax_size >= 2) { int i; @@ -2640,13 +2740,8 @@ static int send_presentRequest(const char *arg) odr_malloc(out, recordsyntax_size * sizeof(Odr_oid*)); for (i = 0; i < recordsyntax_size; i++) compo.u.complex->recordSyntax[i] = - yaz_oidval_to_z3950oid(out, CLASS_RECSYN, - recordsyntax_list[i]); - } - else - { - compo.u.complex->num_recordSyntax = 0; - compo.u.complex->recordSyntax = 0; + yaz_string_to_oid_odr(yaz_oid_std(), + CLASS_RECSYN, recordsyntax_list[i], out); } } else if (elementSetNames) @@ -2674,7 +2769,7 @@ static int send_SRW_presentRequest(const char *arg) sr->u.request->maximumRecords = odr_intdup(out, nos); if (record_schema) sr->u.request->recordSchema = record_schema; - if (recordsyntax_size == 1 && recordsyntax_list[0] == VAL_TEXT_XML) + if (recordsyntax_size == 1 && !yaz_matchstr(recordsyntax_list[0], "xml")) sr->u.request->recordPacking = "xml"; return send_srw(sr); } @@ -2752,11 +2847,18 @@ static int cmd_show(const char *arg) return 2; } +void exit_client(int code) +{ + file_history_save(file_history); + file_history_destroy(&file_history); + exit(code); +} + int cmd_quit(const char *arg) { printf("See you later, alligator.\n"); xmalloc_trav (""); - exit(0); + exit_client(0); return 0; } @@ -2801,7 +2903,8 @@ int cmd_cancel_find(const char *arg) { return fres; } -int send_scanrequest(const char *query, int pp, int num, const char *term) +int send_scanrequest(const char *set, const char *query, + int pp, int num, const char *term) { Z_APDU *apdu = zget_APDU(out, Z_APDU_scanRequest); Z_ScanRequest *req = apdu->u.scanRequest; @@ -2820,7 +2923,8 @@ int send_scanrequest(const char *query, int pp, int num, const char *term) return -1; } req->attributeSet = - yaz_oidval_to_z3950oid(out, CLASS_ATTSET, VAL_BIB1); + yaz_string_to_oid_odr(yaz_oid_std(), + CLASS_ATTSET, "Bib-1", out); if (!(req->termListAndStartPoint = ccl_scan_query (out, rpn))) { printf("Couldn't convert CCL to Scan term\n"); @@ -2846,6 +2950,18 @@ int send_scanrequest(const char *query, int pp, int num, const char *term) } yaz_pqf_destroy (pqf_parser); } + if (queryCharset && outputCharset) + { + yaz_iconv_t cd = yaz_iconv_open(queryCharset, outputCharset); + if (!cd) + { + printf("Conversion from %s to %s unsupported\n", + outputCharset, queryCharset); + return -1; + } + yaz_query_charset_convert_apt(req->termListAndStartPoint, out, cd); + yaz_iconv_close(cd); + } if (term && *term) { if (req->termListAndStartPoint->term && @@ -2865,6 +2981,11 @@ int send_scanrequest(const char *query, int pp, int num, const char *term) req->numberOfTermsRequested = # req->preferredPositionInResponse = &pp; req->stepSize = odr_intdup(out, scan_stepSize); + + if (set) + yaz_oi_set_string_oid(&req->otherInfo, out, + yaz_oid_userinfo_scan_set, 1, set); + send_apdu(apdu); return 2; } @@ -2911,13 +3032,13 @@ void display_term(Z_TermInfo *t) if (t->displayTerm) printf("%s", t->displayTerm); else if (t->term->which == Z_Term_general) - { printf("%.*s", t->term->u.general->len, t->term->u.general->buf); - sprintf(last_scan_line, "%.*s", t->term->u.general->len, - t->term->u.general->buf); - } else printf("Term (not general)"); + if (t->term->which == Z_Term_general) + sprintf(last_scan_line, "%.*s", t->term->u.general->len, + t->term->u.general->buf); + if (t->globalOccurrences) printf (" (%d)\n", *t->globalOccurrences); else @@ -3045,7 +3166,7 @@ int cmd_scansize(const char *arg) return 0; } -int cmd_scan(const char *arg) +static int cmd_scan_common(const char *set, const char *arg) { if (protocol == PROTO_HTTP) { @@ -3089,18 +3210,37 @@ int cmd_scan(const char *arg) if (*arg) { strcpy (last_scan_query, arg); - if (send_scanrequest(arg, scan_position, scan_size, 0) < 0) + if (send_scanrequest(set, arg, + scan_position, scan_size, 0) < 0) return 0; } else { - if (send_scanrequest(last_scan_query, 1, scan_size, last_scan_line) < 0) + if (send_scanrequest(set, last_scan_query, + 1, scan_size, last_scan_line) < 0) return 0; } return 2; } } +int cmd_scan(const char *arg) +{ + return cmd_scan_common(0, arg); +} + +int cmd_setscan(const char *arg) +{ + char setstring[100]; + int nor; + if (sscanf(arg, "%99s%n", setstring, &nor) < 1) + { + printf("missing set for setscan\n"); + return 0; + } + return cmd_scan_common(setstring, arg + nor); +} + int cmd_schema(const char *arg) { xfree(record_schema); @@ -3115,29 +3255,29 @@ int cmd_format(const char *arg) const char *cp = arg; int nor; int idx = 0; - oid_value nsyntax[RECORDSYNTAX_MAX]; + int i; char form_str[41]; if (!arg || !*arg) { printf("Usage: format \n"); return 0; } + for (i = 0; i < recordsyntax_size; i++) + { + xfree(recordsyntax_list[i]); + recordsyntax_list[i] = 0; + } + while (sscanf(cp, "%40s%n", form_str, &nor) >= 1 && nor > 0 && idx < RECORDSYNTAX_MAX) { - nsyntax[idx] = oid_getvalbyname(form_str); if (!strcmp(form_str, "none")) break; - if (nsyntax[idx] == VAL_NONE) - { - printf ("unknown record syntax: %s\n", form_str); - return 0; - } + recordsyntax_list[idx] = xstrdup(form_str); cp += nor; idx++; } recordsyntax_size = idx; - memcpy(recordsyntax_list, nsyntax, idx * sizeof(*nsyntax)); return 1; } @@ -3158,24 +3298,6 @@ int cmd_elements(const char *arg) return 1; } -int cmd_attributeset(const char *arg) -{ - char what[100]; - - if (!arg || !*arg) - { - printf("Usage: attributeset \n"); - return 0; - } - sscanf(arg, "%s", what); - if (p_query_attset (what)) - { - printf("Unknown attribute set name\n"); - return 0; - } - return 1; -} - int cmd_querytype (const char *arg) { if (!strcmp (arg, "ccl")) @@ -3256,11 +3378,29 @@ int cmd_marccharset(const char *arg) } xfree (marcCharset); marcCharset = 0; - if (strcmp(l1, "-")) + if (strcmp(l1, "-") && strcmp(l1, "none")) marcCharset = xstrdup(l1); return 1; } +int cmd_querycharset(const char *arg) +{ + char l1[30]; + + *l1 = 0; + if (sscanf(arg, "%29s", l1) < 1) + { + printf("Query character set is `%s'\n", + queryCharset ? queryCharset: "none"); + return 1; + } + xfree (queryCharset); + queryCharset = 0; + if (strcmp(l1, "-") && strcmp(l1, "none")) + queryCharset = xstrdup(l1); + return 1; +} + int cmd_displaycharset(const char *arg) { char l1[30]; @@ -3299,11 +3439,14 @@ int cmd_negcharset(const char *arg) if (sscanf(arg, "%29s %d %d", l1, &negotiationCharsetRecords, &negotiationCharsetVersion) < 1) { - printf("Current negotiation character set is `%s'\n", + printf("Negotiation character set `%s'\n", negotiationCharset ? negotiationCharset: "none"); - printf("Records in charset %s\n", negotiationCharsetRecords ? - "yes" : "no"); - printf("Charneg version %d\n", negotiationCharsetVersion); + if (negotiationCharset) + { + printf("Records in charset %s\n", negotiationCharsetRecords ? + "yes" : "no"); + printf("Charneg version %d\n", negotiationCharsetVersion); + } } else { @@ -3320,14 +3463,15 @@ int cmd_negcharset(const char *arg) int cmd_charset(const char* arg) { - char l1[30], l2[30], l3[30]; + char l1[30], l2[30], l3[30], l4[30]; - *l1 = *l2 = *l3 = 0; - if (sscanf(arg, "%29s %29s %29s", l1, l2, l3) < 1) + *l1 = *l2 = *l3 = *l4 = '\0'; + if (sscanf(arg, "%29s %29s %29s %29s", l1, l2, l3, l4) < 1) { cmd_negcharset(""); cmd_displaycharset(""); cmd_marccharset(""); + cmd_querycharset(""); } else { @@ -3336,6 +3480,8 @@ int cmd_charset(const char* arg) cmd_displaycharset(l2); if (*l3) cmd_marccharset(l3); + if (*l4) + cmd_querycharset(l4); } return 1; } @@ -3343,7 +3489,7 @@ int cmd_charset(const char* arg) int cmd_lang(const char* arg) { if (*arg == '\0') { - printf("Current language is `%s'\n", (yazLang)?yazLang:NULL); + printf("Current language is `%s'\n", yazLang ? yazLang : "none"); return 1; } xfree (yazLang); @@ -3571,12 +3717,10 @@ int cmd_register_oid(const char* args) { {0,(enum oid_class) 0} }; char oname_str[101], oclass_str[101], oid_str[101]; - char* name; int i; oid_class oidclass = CLASS_GENERAL; - int val = 0, oid[OID_SIZE]; - struct oident * new_oident=NULL; - + Odr_oid oid[OID_SIZE]; + if (sscanf (args, "%100[^ ] %100[^ ] %100s", oname_str,oclass_str, oid_str) < 1) { printf("Error in register command \n"); @@ -3596,31 +3740,12 @@ int cmd_register_oid(const char* args) { return 0; } - i = 0; - name = oid_str; - val = 0; - - while (isdigit (*(unsigned char *) name)) - { - val = val*10 + (*name - '0'); - name++; - if (*name == '.') - { - if (i < OID_SIZE-1) - oid[i++] = val; - val = 0; - name++; - } - } - oid[i] = val; - oid[i+1] = -1; - - new_oident = oid_addent (oid, PROTO_GENERAL, oidclass, oname_str, - VAL_DYNAMIC); - if(strcmp(new_oident->desc,oname_str)) + oid_dotstring_to_oid(oid_str, oid); + + if (yaz_oid_add(yaz_oid_std(), oidclass, oname_str, oid)) { - fprintf(stderr,"oid is already named as %s, registration failed\n", - new_oident->desc); + printf("oid %s already exists, registration failed\n", + oname_str); } return 1; } @@ -3636,30 +3761,53 @@ int cmd_push_command(const char* arg) return 1; } -void source_rcfile(void) +void source_rc_file(const char *rc_file) { - /* Look for a $HOME/.yazclientrc and source it if it exists */ + /* If rc_file != NULL, source that. Else + Look for .yazclientrc and read it if it exists. + If it does not exist, read $HOME/.yazclientrc instead */ struct stat statbuf; - char buffer[1000]; - char* homedir=getenv("HOME"); - - if( homedir ) { - - sprintf(buffer,"%s/.yazclientrc",homedir); - if(stat(buffer,&statbuf)==0) { - cmd_source(buffer, 0 ); + if (rc_file) + { + if (stat(rc_file, &statbuf) == 0) + cmd_source(rc_file, 0); + else + { + fprintf(stderr, "yaz_client: cannot source '%s'\n", rc_file); + exit(1); + } + } + else + { + char fname[1000]; + strcpy(fname, ".yazclientrc"); + if (stat(fname, &statbuf)==0) + { + cmd_source(fname, 0); + } + else + { + const char* homedir = getenv("HOME"); + if (homedir) + { + sprintf(fname, "%.800s/%s", homedir, ".yazclientrc"); + if (stat(fname, &statbuf)==0) + cmd_source(fname, 0); + } } - - }; - - if(stat(".yazclientrc",&statbuf)==0) { - cmd_source(".yazclientrc", 0 ); } } +void add_to_readline_history(void *client_data, const char *line) +{ +#if HAVE_READLINE_HISTORY_H + if (strlen(line)) + add_history(line); +#endif +} -static void initialize(void) +static void initialize(const char *rc_file) { FILE *inf; int i; @@ -3671,7 +3819,6 @@ static void initialize(void) fprintf(stderr, "failed to allocate ODR streams\n"); exit(1); } - oid_init(); setvbuf(stdout, 0, _IONBF, 0); if (apdu_file) @@ -3689,13 +3836,21 @@ static void initialize(void) /* If this fails, no problem: we detect cqltrans == 0 later */ #if HAVE_READLINE_READLINE_H - rl_attempted_completion_function = (CPPFunction*)readline_completer; + rl_attempted_completion_function = + (char **(*)(const char *, int, int)) readline_completer; #endif for(i = 0; i < maxOtherInfosSupported; ++i) { - extraOtherInfos[i].oidval = -1; + extraOtherInfos[i].oid[0] = -1; + extraOtherInfos[i].value = 0; } + + cmd_format("usmarc"); - source_rcfile(); + source_rc_file(rc_file); + + file_history = file_history_new(); + file_history_load(file_history); + file_history_trav(file_history, 0, add_to_readline_history); } @@ -3799,37 +3954,39 @@ static void handle_srw_scan_response(Z_SRW_scanResponse *res) static void http_response(Z_HTTP_Response *hres) { int ret = -1; - const char *content_type = z_HTTP_header_lookup(hres->headers, - "Content-Type"); const char *connection_head = z_HTTP_header_lookup(hres->headers, "Connection"); - if (content_type && !yaz_strcmp_del("text/xml", content_type, "; ")) + if (!yaz_srw_check_content_type(hres)) + printf("Content type does not appear to be XML\n"); + else { Z_SOAP *soap_package = 0; ODR o = odr_createmem(ODR_DECODE); - Z_SOAP_Handler soap_handlers[2] = { - {"http://www.loc.gov/zing/srw/", 0, - (Z_SOAP_fun) yaz_srw_codec}, + Z_SOAP_Handler soap_handlers[3] = { + {YAZ_XMLNS_SRU_v1_1, 0, (Z_SOAP_fun) yaz_srw_codec}, + {YAZ_XMLNS_UPDATE_v0_9, 0, (Z_SOAP_fun) yaz_ucp_codec}, {0, 0, 0} }; ret = z_soap_codec(o, &soap_package, &hres->content_buf, &hres->content_len, soap_handlers); - if (!ret && soap_package->which == Z_SOAP_generic && - soap_package->u.generic->no == 0) + if (!ret && soap_package->which == Z_SOAP_generic) { - Z_SRW_PDU *sr = soap_package->u.generic->p; + Z_SRW_PDU *sr = (Z_SRW_PDU *) soap_package->u.generic->p; if (sr->which == Z_SRW_searchRetrieve_response) handle_srw_response(sr->u.response); else if (sr->which == Z_SRW_explain_response) handle_srw_explain_response(sr->u.explain_response); else if (sr->which == Z_SRW_scan_response) handle_srw_scan_response(sr->u.scan_response); + else if (sr->which == Z_SRW_update_response) + printf("Got update response. Status: %s\n", + sr->u.update_response->operationStatus); else ret = -1; } else if (soap_package && (soap_package->which == Z_SOAP_fault - || soap_package->which == Z_SOAP_error)) + || soap_package->which == Z_SOAP_error)) { printf ("HTTP Error Status=%d\n", hres->code); printf ("SOAP Fault code %s\n", @@ -3841,7 +3998,10 @@ static void http_response(Z_HTTP_Response *hres) soap_package->u.fault->details); } else + { + printf("z_soap_codec failed. (no SOAP error)\n"); ret = -1; + } odr_destroy(o); } if (ret) @@ -4066,42 +4226,42 @@ int cmd_set_otherinfo(const char* args) char oidstr[101], otherinfoString[101]; int otherinfoNo; int sscan_res; - int oidval; sscan_res = sscanf (args, "%d %100[^ ] %100s", &otherinfoNo, oidstr, otherinfoString); - if (sscan_res==1) { + + if (sscan_res > 0 && otherinfoNo >= maxOtherInfosSupported) { + printf("Error otherinfo index too large (%d>=%d)\n", + otherinfoNo,maxOtherInfosSupported); + return 0; + } + + + if (sscan_res==1) + { /* reset this otherinfo */ - if(otherinfoNo>=maxOtherInfosSupported) { - printf("Error otherinfo index to large (%d>%d)\n", - otherinfoNo,maxOtherInfosSupported); - } - extraOtherInfos[otherinfoNo].oidval = -1; - if (extraOtherInfos[otherinfoNo].value) - xfree(extraOtherInfos[otherinfoNo].value); + extraOtherInfos[otherinfoNo].oid[0] = -1; + xfree(extraOtherInfos[otherinfoNo].value); extraOtherInfos[otherinfoNo].value = 0; return 0; } - if (sscan_res<3) { + if (sscan_res != 3) { printf("Error in set_otherinfo command \n"); return 0; } - - if (otherinfoNo>=maxOtherInfosSupported) { - printf("Error otherinfo index too large (%d>=%d)\n", - otherinfoNo,maxOtherInfosSupported); - } - - oidval = oid_getvalbyname (oidstr); - if (oidval == VAL_NONE) + else { - printf("Error in set_otherinfo command unknown oid %s \n",oidstr); - return 0; - } - extraOtherInfos[otherinfoNo].oidval = oidval; - if (extraOtherInfos[otherinfoNo].value) + NMEM oid_tmp = nmem_create(); + const Odr_oid *oid = + yaz_string_to_oid_nmem(yaz_oid_std(), + CLASS_GENERAL, oidstr, oid_tmp); + oid_oidcpy(extraOtherInfos[otherinfoNo].oid, oid); + xfree(extraOtherInfos[otherinfoNo].value); - extraOtherInfos[otherinfoNo].value = xstrdup(otherinfoString); + extraOtherInfos[otherinfoNo].value = xstrdup(otherinfoString); + + nmem_destroy(oid_tmp); + } return 0; } @@ -4124,32 +4284,43 @@ int cmd_list_otherinfo(const char* args) { int i; - if(strlen(args)>0) { + if (strlen(args)>0) + { i = atoi(args); - if( i >= maxOtherInfosSupported ) { + if (i >= maxOtherInfosSupported) + { printf("Error otherinfo index to large (%d>%d)\n",i,maxOtherInfosSupported); return 0; } - - if(extraOtherInfos[i].oidval != -1) + if (extraOtherInfos[i].value) + { + char name_oid[OID_STR_MAX]; + oid_class oclass; + const char *name = + yaz_oid_to_string_buf(extraOtherInfos[i].oid, &oclass, + name_oid); printf(" otherinfo %d %s %s\n", - i, - yaz_z3950_oid_value_to_str( - (enum oid_value) extraOtherInfos[i].oidval, - CLASS_RECSYN), + i, name ? name : "null", extraOtherInfos[i].value); + } - } else { - for(i=0; i 0) ? - yaz_z3950_oid_value_to_str(recordsyntax_list[0], CLASS_RECSYN) : - "none"); + if (recordsyntax_size > 0) + { + printf("Format : %s\n", recordsyntax_list[0]); + } printf("Schema : %s\n",record_schema ? record_schema : "not set"); printf("Elements : %s\n",elementSetNames?elementSetNames->u.generic:""); @@ -4237,20 +4408,22 @@ int cmd_clear_otherinfo(const char* args) otherinfoNo, maxOtherInfosSupported); return 0; } - if (extraOtherInfos[otherinfoNo].oidval != -1) + if (extraOtherInfos[otherinfoNo].value) { /* only clear if set. */ - extraOtherInfos[otherinfoNo].oidval = -1; + extraOtherInfos[otherinfoNo].oid[0] = -1; xfree(extraOtherInfos[otherinfoNo].value); + extraOtherInfos[otherinfoNo].value = 0; } } else { int i; for(i = 0; i < maxOtherInfosSupported; ++i) { - if (extraOtherInfos[i].oidval != -1) + if (extraOtherInfos[i].value) { - extraOtherInfos[i].oidval = -1; + extraOtherInfos[i].oid[0] = -1; xfree(extraOtherInfos[i].value); + extraOtherInfos[i].value = 0; } } } @@ -4281,7 +4454,7 @@ static struct { char *ad; completerFunctionType rl_completerfunction; int complete_filenames; - char **local_tabcompletes; + const char **local_tabcompletes; } cmd_array[] = { {"open", cmd_open, "('tcp'|'ssl')':[':'][/]",NULL,0,NULL}, {"quit", cmd_quit, "",NULL,0,NULL}, @@ -4289,6 +4462,7 @@ static struct { {"delete", cmd_delete, "",NULL,0,NULL}, {"base", cmd_base, "",NULL,0,NULL}, {"show", cmd_show, "['+'<#recs>['+']]",NULL,0,NULL}, + {"setscan", cmd_setscan, "",NULL,0,NULL}, {"scan", cmd_scan, "",NULL,0,NULL}, {"scanstep", cmd_scanstep, "",NULL,0,NULL}, {"scanpos", cmd_scanpos, "",NULL,0,NULL}, @@ -4307,7 +4481,6 @@ static struct { {"schema", cmd_schema, "",complete_schema,0,NULL}, {"elements", cmd_elements, "",NULL,0,NULL}, {"close", cmd_close, "",NULL,0,NULL}, - {"attributeset", cmd_attributeset, "",complete_attributeset,0,NULL}, {"querytype", cmd_querytype, "",complete_querytype,0,NULL}, {"refid", cmd_refid, "",NULL,0,NULL}, {"itemorder", cmd_itemorder, "ill|item|xml ",NULL,0,NULL}, @@ -4320,7 +4493,9 @@ static struct { {"negcharset", cmd_negcharset, "",NULL,0,NULL}, {"displaycharset", cmd_displaycharset, "",NULL,0,NULL}, {"marccharset", cmd_marccharset, "",NULL,0,NULL}, + {"querycharset", cmd_querycharset, "",NULL,0,NULL}, {"lang", cmd_lang, "",NULL,0,NULL}, + {"source", cmd_source_echo, "",NULL,1,NULL}, {".", cmd_source_echo, "",NULL,1,NULL}, {"!", cmd_subshell, "Subshell command",NULL,1,NULL}, {"set_apdufile", cmd_set_apdufile, "",NULL,1,NULL}, @@ -4425,7 +4600,7 @@ int cmd_register_tab(const char* arg) char command[101], tabargument[101]; int i; int num_of_tabs; - char** tabslist; + const char** tabslist; if (sscanf (arg, "%100s %100s", command, tabargument) < 1) { return 0; @@ -4445,7 +4620,7 @@ int cmd_register_tab(const char* arg) if (!cmd_array[i].local_tabcompletes) - cmd_array[i].local_tabcompletes = (char **) calloc(1,sizeof(char**)); + cmd_array[i].local_tabcompletes = (const char **) calloc(1,sizeof(char**)); num_of_tabs=0; @@ -4454,7 +4629,7 @@ int cmd_register_tab(const char* arg) num_of_tabs++; } - cmd_array[i].local_tabcompletes = (char **) + cmd_array[i].local_tabcompletes = (const char **) realloc(cmd_array[i].local_tabcompletes, (num_of_tabs+2)*sizeof(char**)); tabslist = cmd_array[i].local_tabcompletes; @@ -4540,7 +4715,7 @@ static char *command_generator(const char *text, int state) } #if HAVE_READLINE_READLINE_H -static char** default_completer_list = NULL; +static const char** default_completer_list = NULL; static char* default_completer(const char* text, int state) { @@ -4608,12 +4783,23 @@ char **readline_completer(char *text, int start, int end) } #endif +#ifndef WIN32 +void ctrl_c_handler(int x) +{ + exit_client(0); +} +#endif + static void client(void) { char line[10240]; line[10239] = '\0'; +#ifndef WIN32 + signal(SIGINT, ctrl_c_handler); +#endif + #if HAVE_GETTIMEOFDAY gettimeofday (&tv_start, 0); #endif @@ -4631,7 +4817,7 @@ static void client(void) if (*line_in) add_history(line_in); #endif - strncpy(line, line_in, 10239); + strncpy(line, line_in, sizeof(line)-1); free(line_in); } #endif @@ -4640,11 +4826,13 @@ static void client(void) char *end_p; printf (C_PROMPT); fflush(stdout); - if (!fgets(line, 10239, stdin)) + if (!fgets(line, sizeof(line)-1, stdin)) break; if ((end_p = strchr (line, '\n'))) *end_p = '\0'; } + if (isatty(0)) + file_history_add_line(file_history, line); process_cmd_line(line); } } @@ -4666,6 +4854,7 @@ int main(int argc, char **argv) char *open_command = 0; char *auth_command = 0; char *arg; + const char *rc_file = 0; int ret; #if HAVE_LOCALE_H @@ -4688,8 +4877,9 @@ int main(int argc, char **argv) ODR_MASK_SET(&z3950_options, Z_Options_sort); ODR_MASK_SET(&z3950_options, Z_Options_extendedServices); ODR_MASK_SET(&z3950_options, Z_Options_delSet); + ODR_MASK_SET(&z3950_options, Z_Options_negotiationModel); - while ((ret = options("k:c:q:a:b:m:v:p:u:t:Vxd:", argv, argc, &arg)) != -2) + while ((ret = options("k:c:q:a:b:m:v:p:u:t:Vxd:f:", argv, argc, &arg)) != -2) { switch (ret) { @@ -4707,9 +4897,28 @@ int main(int argc, char **argv) exit(1); } break; + case 'a': + if (!strcmp(arg, "-")) + apdu_file=stderr; + else + apdu_file=fopen(arg, "a"); + break; + case 'b': + if (!strcmp(arg, "-")) + ber_file=stderr; + else + ber_file=fopen(arg, "a"); + break; + case 'c': + strncpy (ccl_fields, arg, sizeof(ccl_fields)-1); + ccl_fields[sizeof(ccl_fields)-1] = '\0'; + break; case 'd': dump_file_prefix = arg; break; + case 'f': + rc_file = arg; + break; case 'k': kilobytes = atoi(arg); break; @@ -4720,34 +4929,15 @@ int main(int argc, char **argv) exit (1); } break; - case 't': - outputCharset = xstrdup(arg); - break; - case 'c': - strncpy (ccl_fields, arg, sizeof(ccl_fields)-1); - ccl_fields[sizeof(ccl_fields)-1] = '\0'; + case 'p': + yazProxy = xstrdup(arg); break; case 'q': strncpy (cql_fields, arg, sizeof(cql_fields)-1); cql_fields[sizeof(cql_fields)-1] = '\0'; break; - case 'b': - if (!strcmp(arg, "-")) - ber_file=stderr; - else - ber_file=fopen(arg, "a"); - break; - case 'a': - if (!strcmp(arg, "-")) - apdu_file=stderr; - else - apdu_file=fopen(arg, "a"); - break; - case 'x': - hex_dump = 1; - break; - case 'p': - yazProxy = xstrdup(arg); + case 't': + outputCharset = xstrdup(arg); break; case 'u': if (!auth_command) @@ -4763,24 +4953,31 @@ int main(int argc, char **argv) case 'V': show_version(); break; + case 'x': + hex_dump = 1; + break; default: fprintf (stderr, "Usage: %s " - " [-a ]" + " [-a apdulog]" " [-b berdump]" - " [-d dump]\n" - " [-c cclfields]" + " [-c cclfile]" + " [-d dump]" + " [-f cmdfile]" " [-k size]" - " [-m ]\n" - " [-p ]" - " [-q cqlfields]" - " [-u ]" + " [-m marclog]" + " [-p proxy-addr]" + " [-q cqlfile]" + " [-t dispcharset]" + " [-u auth]" + " [-v loglevel]" " [-V]" - " []\n", + " [-x]" + " [server-addr]\n", prog); exit (1); } } - initialize(); + initialize(rc_file); if (auth_command) { #ifdef HAVE_GETTIMEOFDAY @@ -4803,8 +5000,9 @@ int main(int argc, char **argv) #endif xfree(open_command); } - client (); - exit (0); + client(); + exit_client(0); + return 0; } /* * Local variables: