X-Git-Url: http://git.indexdata.com/?p=yaz-moved-to-github.git;a=blobdiff_plain;f=util%2Fyaz-illclient.c;h=5cc39a8cb40eff27d9ba4a954e8dd1edc4f5b1b2;hp=3606e82ad8ab028abb84e25743e9dcfd0312749c;hb=cabcc223cd47503763e7c42969e3be30c58276af;hpb=4ef54cf7f0c56ebb62f1a4c9bfecc50feca18656 diff --git a/util/yaz-illclient.c b/util/yaz-illclient.c index 3606e82..5cc39a8 100644 --- a/util/yaz-illclient.c +++ b/util/yaz-illclient.c @@ -1,11 +1,9 @@ -/* - * Copyright (C) 1995-2006, Index Data ApS +/* This file is part of the YAZ toolkit. + * Copyright (C) 1995-2013 Index Data * See the file LICENSE for details. - * - * $Id: yaz-illclient.c,v 1.1 2007-04-16 15:33:51 heikki Exp $ */ -/* NOTE - This is work in progress - not at all ready */ +/* WARNING - This is work in progress - not at all ready */ /** \file yaz-illclient.c * \brief client for ILL requests (ISO 10161-1) @@ -15,7 +13,7 @@ * and yaz already provides the APDUS for it. * * This is not an interactive client like yaz-client, but driven by command- - * line arguments. Its output is a return code, and possibly some text on + * line arguments. Its output is a return code, and possibly some text on * stdout. * * Exit codes (note, the program exits as soon as it finds a good reason) @@ -33,6 +31,9 @@ * * */ +#if HAVE_CONFIG_H +#include +#endif #include #include @@ -56,42 +57,153 @@ #include #include #include +#include + + +/* A structure for holding name-value pairs in a linked list */ +struct nameval { + char *name; + char *val; + struct nameval *next; +}; /* A structure for storing all the arguments */ struct prog_args { char *host; + char *auth_userid; + char *auth_passwd; + char *oclc_recno; /* record number in oclc-mode */ + int oclc_auth; /* 1=use oclc-type auth */ + struct nameval* namevals; /* circular list, points to last */ } ; + /* Call-back to be called for every field in the ill-request */ /* It can set values to any field, perhaps from the prog_args */ const char *get_ill_element(void *clientData, const char *element) { - struct prog_args *args = clientData; + struct prog_args *args = (struct prog_args *) clientData; + struct nameval *nv=args->namevals; char *ret=0; - if (!strcmp(element,"foo")) { - ret=args->host; - } else if (!strcmp(element,"ill,protocol-version-num")) { - ret="2"; - } else if (!strcmp(element,"ill,transaction-id,initial-requester-id,person-or-institution-symbol,institution")) { - ret="IndexData"; - } - yaz_log(YLOG_DEBUG,"get_ill_element: '%s' -> '%s' ", element, ret ); + if (!nv) + return ""; + do { + nv=nv->next; + /* printf("comparing '%s' with '%s' \n",element, nv->name ); */ + if ( strcmp(element, nv->name) == 0 ) + ret = nv->val; + } while ( ( !ret) && ( nv != args->namevals) ); + yaz_log(YLOG_DEBUG,"get_ill_element:'%s'->'%s'", element, ret ); return ret; } /* * * * * * * * * * * * * * * * * */ + +/** \brief parse a parameter string */ +/* string is like 'name=value' */ +struct nameval *parse_nameval( char *arg ) { + struct nameval *nv = (struct nameval *) xmalloc(sizeof(*nv)); + char *p=arg; + int len; + if (!p || !*p) + return 0; /* yeah, leaks a bit of memory. so what */ + while ( *p && ( *p != '=' ) ) + p++; + len = p - arg; + if (!len) + return 0; + nv->name = (char *) xmalloc(len+1); + strncpy(nv->name, arg, len); + nv->name[len]='\0'; + if (*p == '=' ) + p++; /* skip the '=' */ + else + return 0; /* oops, no '=' */ + if (!*p) + return 0; /* no value */ + nv->val=xstrdup(p); + nv->next=0; + yaz_log(YLOG_DEBUG,"parse_nameval: n='%s' v='%s'", nv->name, nv->val ); + return nv; +} + +/** \brief append nv to the list of namevals */ +void append_nameval (struct prog_args *args, struct nameval *nv) { + if (!nv) + return; + if (args->namevals) { + nv->next=args->namevals->next; /* first */ + args->namevals->next=nv; + args->namevals=nv; + } else { + nv->next=nv; + args->namevals=nv; + } +} /* append_nameval */ + +/** \brief parse a parameter file */ +void parse_paramfile(char *arg, struct prog_args *args) { + FILE *f=fopen(arg,"r"); +#define BUFSIZE 4096 + char buf[BUFSIZE]; + int len; + struct nameval *nv; + if (!f) { + yaz_log(YLOG_FATAL,"Could not open param file '%s' ", arg); + printf("Could not open file '%s' \n",arg); + exit(1); + } + yaz_log(YLOG_DEBUG,"Opened input file '%s' ",arg ); + while (fgets(buf,BUFSIZE,f)) { + if (buf[0] != '#' ) { + len=strlen(buf)-1; + if (buf[len] == '\n') + buf[len] = '\0' ; + nv=parse_nameval(buf); + append_nameval(args, nv); + } /* not a comment */ + } + (void) fclose(f); + + if (0) { + nv=args->namevals; + printf("nv chain: ================ \n"); + printf("(last:) %p: '%s' = '%s' (%p) \n",nv, nv->name, nv->val, nv->next ); + do { + nv=nv->next; + printf("%p: '%s' = '%s' (%p)\n",nv, nv->name, nv->val, nv->next ); + } while (nv != args->namevals ); + exit(1); + } + +} /* parse_paramfile */ + + /** \brief Parse program arguments */ void parseargs( int argc, char * argv[], struct prog_args *args) { int ret; char *arg; char *prog=*argv; - char *version="$Id: yaz-illclient.c,v 1.1 2007-04-16 15:33:51 heikki Exp $"; /* from cvs */ - - args->host=0; /* not known (yet) */ + char version[60]; + struct nameval *nv; + + /* default values */ + args->host = 0; /* not known (yet) */ + args->namevals=0; /* none set up */ + args->oclc_auth=0; + args->oclc_recno=0; + args->auth_userid = 0; + args->auth_passwd = 0; +#if 0 + /* Example 3 - directly from OCLC, supposed to work on their test server*/ + args->auth_userid = "100-310-658" ; /* FIXME - get from cmd line */ + args->auth_passwd = "apii2test" ; /* FIXME - get from cmd line */ +#endif - while ((ret = options("k:c:q:a:b:m:v:p:u:t:Vxd:", argv, argc, &arg)) != -2) + while ((ret = options("Vov:p:u:D:f:r:l:", argv, argc, &arg)) != -2) { + yaz_log(YLOG_DEBUG,"parsing option '%c' '%s'",ret, arg); switch (ret) { case 0: @@ -101,7 +213,7 @@ void parseargs( int argc, char * argv[], struct prog_args *args) { } else { - fprintf(stderr, "%s: Specify most one server address\n", + fprintf(stderr, "%s: Specify at most one server address\n", prog); exit(1); } @@ -109,12 +221,38 @@ void parseargs( int argc, char * argv[], struct prog_args *args) { case 'v': yaz_log_init(yaz_log_mask_str(arg), "", 0); break; + case 'l': + yaz_log_init_file(arg); + break; case 'V': - printf("%s %s",prog, version ); + yaz_version(version, 0); + printf("%s %s\n",prog, version); + break; + case 'D': + nv=parse_nameval(arg); + append_nameval(args,nv); + break; + case 'f': + parse_paramfile(arg,args); + break; + case 'o': + args->oclc_auth=1; + break; + case 'u': + args->auth_userid=xstrdup(arg); + break; + case 'p': + args->auth_passwd=xstrdup(arg); + break; + case 'r': + args->oclc_recno=xstrdup(arg); break; default: fprintf (stderr, "Usage: %s " + " [-f filename]" " [-v loglevel...]" + " [-D name=value ]" + " [-o -u user -p passwd]" " [-V]" " \n", prog); @@ -131,6 +269,10 @@ void validateargs( struct prog_args *args) { "as in 'bagel.indexdata.dk:210' \n"); exit(1); } + if (args->oclc_auth && ((!args->auth_userid) || (!args->auth_passwd))){ + fprintf(stderr, "-o option requires -u and -p \n"); + exit(1); + } } /* validateargs */ @@ -148,7 +290,7 @@ COMSTACK connect_to( char *hostaddr ){ hostaddr ); exit(2); } - + yaz_log(YLOG_DEBUG,"Created stack ok "); status = cs_connect(stack, server_address_ip); @@ -161,46 +303,211 @@ COMSTACK connect_to( char *hostaddr ){ return stack; } + /* * * * * * * * * * * * * * * */ -ILL_APDU *createrequest( struct prog_args *args, ODR out_odr) { +/* Makes a Z39.50-like prompt package with username and password */ +Z_PromptObject1 *makeprompt(struct prog_args *args, ODR odr) { + Z_PromptObject1 *p = (Z_PromptObject1 *) odr_malloc(odr, sizeof(*p) ); + Z_ResponseUnit1 *ru = (Z_ResponseUnit1 *) odr_malloc(odr, sizeof(*ru) ); + + p->which=Z_PromptObject1_response; + p->u.response = (Z_Response1*) odr_malloc(odr, sizeof(*(p->u.response)) ); + p->u.response->num=2; + p->u.response->elements= (Z_ResponseUnit1 **) odr_malloc(odr, + p->u.response->num*sizeof(*(p->u.response->elements)) ); + /* user id, aka "oclc authorization number" */ + p->u.response->elements[0] = ru; + ru->promptId = (Z_PromptId *) odr_malloc(odr, sizeof(*(ru->promptId) )); + ru->promptId->which = Z_PromptId_enumeratedPrompt; + ru->promptId->u.enumeratedPrompt = (Z_PromptIdEnumeratedPrompt *) + odr_malloc(odr, sizeof(*(ru->promptId->u.enumeratedPrompt) )); + ru->promptId->u.enumeratedPrompt->type = + odr_intdup(odr,Z_PromptIdEnumeratedPrompt_userId); + ru->promptId->u.enumeratedPrompt->suggestedString = 0 ; + ru->which = Z_ResponseUnit1_string ; + ru->u.string = odr_strdup(odr, args->auth_userid); + /* password */ + ru = (Z_ResponseUnit1 *) odr_malloc(odr, sizeof(*ru) ); + p->u.response->elements[1] = ru; + ru->promptId = (Z_PromptId *) odr_malloc(odr, sizeof(*(ru->promptId) )); + ru->promptId->which = Z_PromptId_enumeratedPrompt; + ru->promptId->u.enumeratedPrompt = (Z_PromptIdEnumeratedPrompt *) + odr_malloc(odr, sizeof(*(ru->promptId->u.enumeratedPrompt) )); + ru->promptId->u.enumeratedPrompt->type = + odr_intdup(odr,Z_PromptIdEnumeratedPrompt_password); + ru->promptId->u.enumeratedPrompt->suggestedString = 0 ; + ru->which = Z_ResponseUnit1_string ; + ru->u.string = odr_strdup(odr, args->auth_passwd); + return p; +} /* makeprompt */ + +ILL_Extension *makepromptextension(struct prog_args *args, ODR odr) { + ODR odr_ext = odr_createmem(ODR_ENCODE); + ODR odr_prt = odr_createmem(ODR_PRINT); + ILL_Extension *e = (ILL_Extension *) odr_malloc(odr, sizeof(*e)); + Z_PromptObject1 *p = makeprompt(args,odr_ext); + char * buf; + int siz; + Z_External *ext = (Z_External *) odr_malloc(odr, sizeof(*ext)); + ext->direct_reference = odr_getoidbystr(odr,"1.2.840.10003.8.1"); + ext->indirect_reference=0; + ext->descriptor=0; + ext->which=Z_External_single; + if ( ! z_PromptObject1(odr_ext, &p, 0,0 ) ) { + yaz_log(YLOG_FATAL,"Encoding of z_PromptObject1 failed "); + exit (6); + } + + printf ("Prompt: \n"); /*!*/ + z_PromptObject1(odr_prt, &p, 0,0 ); /*!*/ + + buf= odr_getbuf(odr_ext,&siz,0); + ext->u.single_ASN1_type=(Odr_any *) + odr_malloc(odr,sizeof(*ext->u.single_ASN1_type)); + ext->u.single_ASN1_type->buf= (unsigned char *) odr_malloc(odr, siz); + memcpy(ext->u.single_ASN1_type->buf,buf, siz ); + ext->u.single_ASN1_type->len = siz; +#if OCT_SIZE + ext->u.single_ASN1_type->size = siz; +#endif + odr_reset(odr_ext); + odr_reset(odr_prt); /*!*/ + + e->identifier = odr_intdup(odr,1); + e->critical = odr_booldup(odr,0); + e->item = (Odr_any *) odr_malloc(odr,sizeof(*e->item)); + if ( ! z_External(odr_ext, &ext,0,0) ) { + yaz_log(YLOG_FATAL,"Encoding of z_External failed "); + exit (6); + } + printf("External: \n"); + z_External(odr_prt, &ext,0,0); /*!*/ + buf= odr_getbuf(odr_ext,&siz,0); + e->item->buf= (unsigned char *) odr_malloc(odr, siz); + memcpy(e->item->buf,buf, siz ); + e->item->len = siz; +#if OCT_SIZE + e->item->size = siz; +#endif + + odr_destroy(odr_prt); + odr_destroy(odr_ext); + return e; +} /* makepromptextension */ + +ILL_Extension *makeoclcextension(struct prog_args *args, ODR odr) { + /* The oclc extension is required, but only contains optional */ + /* fields. Here we just null them all out */ + ODR odr_ext = odr_createmem(ODR_ENCODE); + ODR odr_prt = odr_createmem(ODR_PRINT); + ILL_Extension *e = (ILL_Extension *) odr_malloc(odr, sizeof(*e)); + ILL_OCLCILLRequestExtension *oc = (ILL_OCLCILLRequestExtension *) + odr_malloc(odr_ext, sizeof(*oc)); + char * buf; + int siz; + Z_External *ext = (Z_External *) odr_malloc(odr, sizeof(*ext)); + oc->clientDepartment = 0; + oc->paymentMethod = 0; + oc->uniformTitle = 0; + oc->dissertation = 0; + oc->issueNumber = 0; + oc->volume = 0; + oc->affiliations = 0; + oc->source = 0; + ext->direct_reference = odr_getoidbystr(odr,"1.0.10161.13.2"); + ext->indirect_reference=0; + ext->descriptor=0; + ext->which=Z_External_single; + if ( ! ill_OCLCILLRequestExtension(odr_ext, &oc, 0,0 ) ) { + yaz_log(YLOG_FATAL,"Encoding of ill_OCLCILLRequestExtension failed "); + exit (6); + } + + printf ("OCLC: \n"); /*!*/ + ill_OCLCILLRequestExtension(odr_prt, &oc, 0,0 ); /*!*/ + + buf= odr_getbuf(odr_ext,&siz,0); + ext->u.single_ASN1_type = (Odr_any*) + odr_malloc(odr,sizeof(*ext->u.single_ASN1_type)); + ext->u.single_ASN1_type->buf = (unsigned char *) odr_malloc(odr, siz); + memcpy(ext->u.single_ASN1_type->buf,buf, siz ); + ext->u.single_ASN1_type->len = siz; +#if OCT_SIZE + ext->u.single_ASN1_type->size = siz; +#endif + odr_reset(odr_ext); + odr_reset(odr_prt); /*!*/ + + e->identifier = odr_intdup(odr,1); + e->critical = odr_booldup(odr,0); + e->item = (Odr_any *) odr_malloc(odr,sizeof(*e->item)); + if ( ! z_External(odr_ext, &ext,0,0) ) { + yaz_log(YLOG_FATAL,"Encoding of z_External failed "); + exit (6); + } + printf("External: \n"); + z_External(odr_prt, &ext,0,0); /*!*/ + buf= odr_getbuf(odr_ext,&siz,0); + e->item->buf= (unsigned char *) odr_malloc(odr, siz); + memcpy(e->item->buf, buf, siz); + e->item->len = siz; +#if OCT_SIZE + e->item->size = siz; +#endif + + odr_destroy(odr_prt); + odr_destroy(odr_ext); + return e; + +} /* makeoclcextension */ + +ILL_APDU *createrequest( struct prog_args *args, ODR odr) { struct ill_get_ctl ctl; ILL_APDU *apdu; ILL_Request *req; - ctl.odr = out_odr; - ctl.clientData = & args; + ctl.odr = odr; + ctl.clientData = args; ctl.f = get_ill_element; - apdu = odr_malloc( out_odr, sizeof(*apdu) ); + apdu = (ILL_APDU *) odr_malloc( odr, sizeof(*apdu) ); apdu->which=ILL_APDU_ILL_Request; req = ill_get_ILLRequest(&ctl, "ill", 0); apdu->u.illRequest=req; + if (args->oclc_auth) { + req->num_iLL_request_extensions=2; + req->iLL_request_extensions= + (ILL_Extension **) + odr_malloc(odr, req->num_iLL_request_extensions* + sizeof(*req->iLL_request_extensions)); + req->iLL_request_extensions[0]=makepromptextension(args,odr); + req->iLL_request_extensions[1]=makeoclcextension(args,odr); + } if (!req) { yaz_log(YLOG_FATAL,"Could not create ill request"); exit(2); } - return apdu; } /* createrequest */ /* * * * * * * * * * * * * * * */ /** \brief Send the request */ -void sendrequest(ILL_APDU *apdu, ODR out_odr, COMSTACK stack ) { +void sendrequest(ILL_APDU *apdu, ODR odr, COMSTACK stack ) { char *buf_out; int len_out; int res; - if (!ill_APDU (out_odr, &apdu, 0, 0)) { + if (!ill_APDU (odr, &apdu, 0, 0)) { yaz_log(YLOG_FATAL,"ill_Apdu failed"); exit(2); } - buf_out = odr_getbuf(out_odr, &len_out, 0); + buf_out = odr_getbuf(odr, &len_out, 0); if (0) { yaz_log(YLOG_DEBUG,"Request PDU Dump"); odr_dumpBER(yaz_log_file(), buf_out, len_out); } if (!buf_out) { yaz_log(YLOG_FATAL,"Encoding failed. Len=%d", len_out); - odr_perror(out_odr, "encoding failed"); + odr_perror(odr, "encoding failed"); exit(2); } yaz_log(YLOG_DEBUG,"About to send the request. Len=%d", len_out); @@ -209,6 +516,21 @@ void sendrequest(ILL_APDU *apdu, ODR out_odr, COMSTACK stack ) { yaz_log(YLOG_FATAL,"Could not send packet. code %d",res ); exit (4); } + if (1) { + FILE *F = fopen("req.apdu","w"); + if (!F) + { + yaz_log(YLOG_FATAL|YLOG_ERRNO, "open req.apdu failed"); + } + else + { + if (fwrite ( buf_out, 1, len_out, F) != len_out) + yaz_log(YLOG_FATAL|YLOG_ERRNO, "write req.apdu failed"); + if (fclose(F)) + yaz_log(YLOG_FATAL|YLOG_ERRNO, "write req.apdu failed"); + } + } + } /* sendrequest */ /* * * * * * * * * * * * * * * */ @@ -220,10 +542,10 @@ ILL_APDU *getresponse( COMSTACK stack, ODR in_odr ){ int len_in=0; yaz_log(YLOG_DEBUG,"About to wait for a response"); res = cs_get(stack, &buf_in, &len_in); - yaz_log(YLOG_DEBUG,"Got a response of %d bytes at %x. res=%d", len_in,buf_in, res); + yaz_log(YLOG_DEBUG,"Got a response of %d bytes at %p. res=%d", len_in,buf_in, res); if (res<0) { yaz_log(YLOG_FATAL,"Could not receive packet. code %d",res ); - yaz_log(YLOG_DEBUG,"%02x %02x %02x %02x %02x %02x %02x %02x ...", + yaz_log(YLOG_DEBUG,"%02x %02x %02x %02x %02x %02x %02x %02x ...", buf_in[0], buf_in[1], buf_in[2], buf_in[3], buf_in[4], buf_in[5], buf_in[6], buf_in[7] ); yaz_log(YLOG_DEBUG,"PDU Dump:"); @@ -240,7 +562,7 @@ ILL_APDU *getresponse( COMSTACK stack, ODR in_odr ){ sprintf(msg, "ODR code %d:%d element=%-20s", err, x, element ? element : ""); yaz_log(YLOG_FATAL,"Error decoding incoming packet: %s",msg); - yaz_log(YLOG_DEBUG,"%02x %02x %02x %02x %02x %02x %02x %02x ...", + yaz_log(YLOG_DEBUG,"%02x %02x %02x %02x %02x %02x %02x %02x ...", buf_in[0], buf_in[1], buf_in[2], buf_in[3], buf_in[4], buf_in[5], buf_in[6], buf_in[7] ); yaz_log(YLOG_DEBUG,"PDU Dump:"); @@ -263,7 +585,7 @@ void dumpapdu( ILL_APDU *apdu) { ILL_Status_Or_Error_Report *getstaterr( ILL_APDU *resp, ODR in_odr ) { if (resp->which != ILL_APDU_Status_Or_Error_Report ) { const char *element = odr_getelement(in_odr); - if (!element) + if (!element) element="unknown"; printf("Server returned wrong packet type: %d\n", resp->which); yaz_log(YLOG_FATAL,"Server returned a (%d) and " @@ -276,9 +598,9 @@ ILL_Status_Or_Error_Report *getstaterr( ILL_APDU *resp, ODR in_odr ) { /** \brief Return a printable string from an ILL_String */ char *getillstring( ILL_String *s) { - if (s->which == ILL_String_GeneralString ) + if (s->which == ILL_String_GeneralString ) return s->u.GeneralString; - else if (s->which == ILL_String_EDIFACTString ) + else if (s->which == ILL_String_EDIFACTString ) return s->u.EDIFACTString; else { yaz_log(YLOG_FATAL,"Invalid ILL_String "); @@ -291,7 +613,7 @@ char *getillstring( ILL_String *s) { /* Then the problem is to find the right message. We dig around */ /* until we find the first message, print that, and exit the program */ void checkerr( ILL_Status_Or_Error_Report *staterr ) { - yaz_log(YLOG_DEBUG, "err= %x ",staterr->error_report ); + yaz_log(YLOG_DEBUG, "err= %p ",staterr->error_report ); if (staterr->error_report) { ILL_Error_Report *err= staterr->error_report; if ( err->user_error_report) { @@ -301,16 +623,16 @@ void checkerr( ILL_Status_Or_Error_Report *staterr ) { printf("Already forwarded: \n"); break; case ILL_User_Error_Report_intermediary_problem: - printf("Intermediary problem: %d\n", - uerr->u.intermediary_problem); + printf("Intermediary problem: " ODR_INT_PRINTF "\n", + *uerr->u.intermediary_problem); break; case ILL_User_Error_Report_security_problem: - printf("Security problem: %s\n", + printf("Security problem: %s\n", getillstring(uerr->u.security_problem)); break; case ILL_User_Error_Report_unable_to_perform: - printf("Unable to perform: %d\n", - uerr->u.unable_to_perform); + printf("Unable to perform: " ODR_INT_PRINTF "\n", + *uerr->u.unable_to_perform); break; default: printf("Unknown problem"); @@ -321,24 +643,25 @@ void checkerr( ILL_Status_Or_Error_Report *staterr ) { ILL_Provider_Error_Report *perr= err->provider_error_report; switch( perr->which ) { case ILL_Provider_Error_Report_general_problem: - printf("General Problem: %d\n", - perr->u.general_problem); + printf("General Problem: " ODR_INT_PRINTF ":", + *perr->u.general_problem); break; case ILL_Provider_Error_Report_transaction_id_problem: - printf("Transaction Id Problem: %d\n", - perr->u.general_problem); + printf("Transaction Id Problem: " ODR_INT_PRINTF ":", + *perr->u.general_problem); break; case ILL_Provider_Error_Report_state_transition_prohibited: - printf("State Transition prohibited \n"); + printf("State Transition prohibited:"); break; } - exit(7); - } + /*exit(7);*/ + } /* fallbacks */ - if ( staterr->note ) + if ( staterr->note ) printf("%s", getillstring(staterr->note)); - else + else printf("Unknown error type"); + printf("\n"); exit(7); } } /* checkerr */ @@ -347,7 +670,7 @@ void checkerr( ILL_Status_Or_Error_Report *staterr ) { /* * * * * * * * * * * * * * * */ -/** \brief Main program +/** \brief Main program * * Parse arguments * Validate arguments @@ -372,9 +695,11 @@ int main (int argc, char * argv[]) { validateargs(&args); stack = connect_to(args.host); apdu = createrequest(&args, out_odr); - sendrequest(apdu, out_odr, stack ); + if (1) + dumpapdu(apdu); + sendrequest(apdu, out_odr, stack ); resp = getresponse(stack, in_odr ); - if (1) + if (1) dumpapdu(resp); staterr=getstaterr(resp, in_odr); checkerr(staterr); @@ -387,6 +712,7 @@ int main (int argc, char * argv[]) { /* * Local variables: * c-basic-offset: 4 + * c-file-style: "Stroustrup" * indent-tabs-mode: nil * End: * vim: shiftwidth=4 tabstop=8 expandtab