Added routines
[simpleserver-moved-to-github.git] / SimpleServer.c
1 /*
2  * This file was generated automatically by xsubpp version 1.9507 from the 
3  * contents of SimpleServer.xs. Do not edit this file, edit SimpleServer.xs instead.
4  *
5  *      ANY CHANGES MADE HERE WILL BE LOST! 
6  *
7  */
8
9 #line 1 "SimpleServer.xs"
10 /*
11  * Copyright (c) 2000, Index Data.
12  *
13  * Permission to use, copy, modify, distribute, and sell this software and
14  * its documentation, in whole or in part, for any purpose, is hereby granted,
15  * provided that:
16  *
17  * 1. This copyright and permission notice appear in all copies of the
18  * software and its documentation. Notices of copyright or attribution
19  * which appear at the beginning of any file must remain unchanged.
20  *
21  * 2. The name of Index Data or the individual authors may not be used to
22  * endorse or promote products derived from this software without specific
23  * prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND,
26  * EXPRESS, IMPLIED, OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
27  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
28  * IN NO EVENT SHALL INDEX DATA BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
29  * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES
30  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR
31  * NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
32  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
33  * OF THIS SOFTWARE.
34  */
35
36 /*$Log: SimpleServer.c,v $
37 /*Revision 1.12  2001-08-29 11:48:35  sondberg
38 /*Added routines
39 /*
40 /*      Net::Z3950::SimpleServer::ScanSuccess
41 /*      Net::Z3950::SimpleServer::ScanPartial
42 /*
43 /*and a bit of documentation.
44 /*
45 /*Revision 1.9  2001/08/24 14:00:20  sondberg
46 /*Added support for scan.
47 /*
48 /*Revision 1.8  2001/05/21 11:07:02  sondberg
49 /*Extended maximum numbers of GRS-1 elements. Should be done dynamically.
50 /*
51 /*Revision 1.7  2001/03/13 14:17:15  sondberg
52 /*Added support for GRS-1.
53 /**/
54
55
56 #include "EXTERN.h"
57 #include "perl.h"
58 #include "XSUB.h"
59 #include <yaz/backend.h>
60 #include <yaz/log.h>
61 #include <yaz/wrbuf.h>
62 #include <stdio.h>
63 #include <unistd.h>
64 #include <stdlib.h>
65 #include <ctype.h>
66 #define GRS_MAX_FIELDS 500 
67 #ifdef ASN_COMPILED
68 #include <yaz/ill.h>
69 #endif
70 #ifndef sv_undef                /* To fix the problem with Perl 5.6.0 */
71 #define sv_undef PL_sv_undef
72 #endif
73
74 typedef struct {
75         SV *handle;
76
77         SV *init_ref;
78         SV *close_ref;
79         SV *sort_ref;
80         SV *search_ref;
81         SV *fetch_ref;
82         SV *present_ref;
83         SV *esrequest_ref;
84         SV *delete_ref;
85         SV *scan_ref;
86 } Zfront_handle;
87
88 SV *init_ref = NULL;
89 SV *close_ref = NULL;
90 SV *sort_ref = NULL;
91 SV *search_ref = NULL;
92 SV *fetch_ref = NULL;
93 SV *present_ref = NULL;
94 SV *esrequest_ref = NULL;
95 SV *delete_ref = NULL;
96 SV *scan_ref = NULL;
97 int MAX_OID = 15;
98
99
100 Z_GenericRecord *read_grs1(char *str, ODR o)
101 {
102         int type, ivalue;
103         char line[512], *buf, *ptr, *original;
104         char value[512];
105         Z_GenericRecord *r = 0;
106
107         original = str;
108         for (;;)
109         {
110                 Z_TaggedElement *t;
111                 Z_ElementData *c;
112         
113                 ptr = strchr(str, '\n');
114                 if (!ptr) {
115                         return r;
116                 }
117                 strncpy(line, str, ptr - str);
118                 line[ptr - str] = 0;
119                 buf = line;
120                 str = ptr + 1;
121                 while (*buf && isspace(*buf))
122                         buf++;
123                 if (*buf == '}') {
124                         memmove(original, str, strlen(str));
125                         return r;
126                 }
127                 if (sscanf(buf, "(%d,%[^)])", &type, value) != 2)
128                 {
129                         yaz_log(LOG_WARN, "Bad data in '%s'", buf);
130                         return 0;
131                 }
132                 if (!type && *value == '0')
133                         return r;
134                 if (!(buf = strchr(buf, ')')))
135                         return 0;
136                 buf++;
137                 while (*buf && isspace(*buf))
138                         buf++;
139                 if (!*buf)
140                         return 0;
141                 if (!r)
142                 {
143                         r = (Z_GenericRecord *)odr_malloc(o, sizeof(*r));
144                         r->elements = (Z_TaggedElement **)
145                         odr_malloc(o, sizeof(Z_TaggedElement*) * GRS_MAX_FIELDS);
146                         r->num_elements = 0;
147                 }
148                 if (r->num_elements > GRS_MAX_FIELDS)
149                 {
150                         yaz_log(LOG_WARN, "Max number of GRS-1 elements exceeded [GRS_MAX_FIELDS=%d]", GRS_MAX_FIELDS);
151                         exit(0);
152                 }
153                 r->elements[r->num_elements] = t = (Z_TaggedElement *) odr_malloc(o, sizeof(Z_TaggedElement));
154                 t->tagType = (int *)odr_malloc(o, sizeof(int));
155                 *t->tagType = type;
156                 t->tagValue = (Z_StringOrNumeric *)
157                         odr_malloc(o, sizeof(Z_StringOrNumeric));
158                 if ((ivalue = atoi(value)))
159                 {
160                         t->tagValue->which = Z_StringOrNumeric_numeric;
161                         t->tagValue->u.numeric = (int *)odr_malloc(o, sizeof(int));
162                         *t->tagValue->u.numeric = ivalue;
163                 }
164                 else
165                 {
166                         t->tagValue->which = Z_StringOrNumeric_string;
167                         t->tagValue->u.string = (char *)odr_malloc(o, strlen(value)+1);
168                         strcpy(t->tagValue->u.string, value);
169                 }
170                 t->tagOccurrence = 0;
171                 t->metaData = 0;
172                 t->appliedVariant = 0;
173                 t->content = c = (Z_ElementData *)odr_malloc(o, sizeof(Z_ElementData));
174                 if (*buf == '{')
175                 {
176                         c->which = Z_ElementData_subtree;
177                         c->u.subtree = read_grs1(str, o);
178                 }
179                 else
180                 {
181                         c->which = Z_ElementData_string;
182 /*                      buf[strlen(buf)-1] = '\0';*/
183                         buf[strlen(buf)] = '\0';
184                         c->u.string = odr_strdup(o, buf);
185                 }
186                 r->num_elements++;
187         }
188 }
189
190
191
192
193 static void oid2str(Odr_oid *o, WRBUF buf)
194 {
195     for (; *o >= 0; o++) {
196         char ibuf[16];
197         sprintf(ibuf, "%d", *o);
198         wrbuf_puts(buf, ibuf);
199         if (o[1] > 0)
200             wrbuf_putc(buf, '.');
201     }
202 }
203
204
205 static int rpn2pquery(Z_RPNStructure *s, WRBUF buf)
206 {
207     switch (s->which) {
208         case Z_RPNStructure_simple: {
209             Z_Operand *o = s->u.simple;
210
211             switch (o->which) {
212                 case Z_Operand_APT: {
213                     Z_AttributesPlusTerm *at = o->u.attributesPlusTerm;
214
215                     if (at->attributes) {
216                         int i;
217                         char ibuf[16];
218
219                         for (i = 0; i < at->attributes->num_attributes; i++) {
220                             wrbuf_puts(buf, "@attr ");
221                             if (at->attributes->attributes[i]->attributeSet) {
222                                 oid2str(at->attributes->attributes[i]->attributeSet, buf);
223                                 wrbuf_putc(buf, ' ');
224                             }
225                             sprintf(ibuf, "%d=", *at->attributes->attributes[i]->attributeType);
226                             assert(at->attributes->attributes[i]->which == Z_AttributeValue_numeric);
227                             wrbuf_puts(buf, ibuf);
228                             sprintf(ibuf, "%d ", *at->attributes->attributes[i]->value.numeric);
229                             wrbuf_puts(buf, ibuf);
230                         }
231                     }
232                     switch (at->term->which) {
233                         case Z_Term_general: {
234                             wrbuf_putc(buf, '"');
235                             wrbuf_write(buf, (char*) at->term->u.general->buf, at->term->u.general->len);
236                             wrbuf_puts(buf, "\" ");
237                             break;
238                         }
239                         default: abort();
240                     }
241                     break;
242                 }
243                 default: abort();
244             }
245             break;
246         }
247         case Z_RPNStructure_complex: {
248             Z_Complex *c = s->u.complex;
249
250             switch (c->roperator->which) {
251                 case Z_Operator_and: wrbuf_puts(buf, "@and "); break;
252                 case Z_Operator_or: wrbuf_puts(buf, "@or "); break;
253                 case Z_Operator_and_not: wrbuf_puts(buf, "@not "); break;
254                 case Z_Operator_prox: abort();
255                 default: abort();
256             }
257             if (!rpn2pquery(c->s1, buf))
258                 return 0;
259             if (!rpn2pquery(c->s2, buf))
260                 return 0;
261             break;
262         }
263         default: abort();
264     }
265     return 1;
266 }
267
268
269 WRBUF zquery2pquery(Z_Query *q)
270 {
271     WRBUF buf = wrbuf_alloc();
272
273     if (q->which != Z_Query_type_1 && q->which != Z_Query_type_101) 
274         return 0;
275     if (q->u.type_1->attributeSetId) {
276         /* Output attribute set ID */
277         wrbuf_puts(buf, "@attrset ");
278         oid2str(q->u.type_1->attributeSetId, buf);
279         wrbuf_putc(buf, ' ');
280     }
281     return rpn2pquery(q->u.type_1->RPNStructure, buf) ? buf : 0;
282 }
283
284
285 int bend_sort(void *handle, bend_sort_rr *rr)
286 {
287         HV *href;
288         AV *aref;
289         SV **temp;
290         SV *err_code;
291         SV *err_str;
292         SV *status;
293         STRLEN len;
294         char *ptr;
295         char *ODR_err_str;
296         char **input_setnames;
297         Zfront_handle *zhandle = (Zfront_handle *)handle;
298         int i;
299         
300         dSP;
301         ENTER;
302         SAVETMPS;
303         
304         aref = newAV();
305         input_setnames = rr->input_setnames;
306         for (i = 0; i < rr->num_input_setnames; i++)
307         {
308                 av_push(aref, newSVpv(*input_setnames++, 0));
309         }
310         href = newHV();
311         hv_store(href, "INPUT", 5, newRV( (SV*) aref), 0);
312         hv_store(href, "OUTPUT", 6, newSVpv(rr->output_setname, 0), 0);
313         hv_store(href, "HANDLE", 6, zhandle->handle, 0);
314         hv_store(href, "STATUS", 6, newSViv(0), 0);
315
316         PUSHMARK(sp);
317
318         XPUSHs(sv_2mortal(newRV( (SV*) href)));
319
320         PUTBACK;
321
322         perl_call_sv(sort_ref, G_SCALAR | G_DISCARD);
323
324         SPAGAIN;
325
326         temp = hv_fetch(href, "ERR_CODE", 8, 1);
327         err_code = newSVsv(*temp);
328
329         temp = hv_fetch(href, "ERR_STR", 7, 1);
330         err_str = newSVsv(*temp);
331
332         temp = hv_fetch(href, "STATUS", 6, 1);
333         status = newSVsv(*temp);
334
335
336         
337
338         PUTBACK;
339         FREETMPS;
340         LEAVE;
341
342         hv_undef(href),
343         av_undef(aref);
344         rr->errcode = SvIV(err_code);
345         rr->sort_status = SvIV(status);
346         ptr = SvPV(err_str, len);
347         ODR_err_str = (char *)odr_malloc(rr->stream, len + 1);
348         strcpy(ODR_err_str, ptr);
349         rr->errstring = ODR_err_str;
350
351         sv_free(err_code);
352         sv_free(err_str);
353         sv_free(status);
354         
355         return 0;
356 }
357
358
359 int bend_search(void *handle, bend_search_rr *rr)
360 {
361         HV *href;
362         AV *aref;
363         SV **temp;
364         SV *hits;
365         SV *err_code;
366         SV *err_str;
367         char *ODR_errstr;
368         STRLEN len;
369         int i;
370         char **basenames;
371         int n;
372         WRBUF query;
373         char *ptr;
374         SV *point;
375         SV *ODR_point;
376         Zfront_handle *zhandle = (Zfront_handle *)handle;
377
378         dSP;
379         ENTER;
380         SAVETMPS;
381
382         aref = newAV();
383         basenames = rr->basenames;
384         for (i = 0; i < rr->num_bases; i++)
385         {
386                 av_push(aref, newSVpv(*basenames++, 0));
387         }
388         href = newHV();         
389         hv_store(href, "SETNAME", 7, newSVpv(rr->setname, 0), 0);
390         hv_store(href, "REPL_SET", 8, newSViv(rr->replace_set), 0);
391         hv_store(href, "ERR_CODE", 8, newSViv(0), 0);
392         hv_store(href, "ERR_STR", 7, newSVpv("", 0), 0);
393         hv_store(href, "HITS", 4, newSViv(0), 0);
394         hv_store(href, "DATABASES", 9, newRV( (SV*) aref), 0);
395         hv_store(href, "HANDLE", 6, zhandle->handle, 0);
396         hv_store(href, "PID", 3, newSViv(getpid()), 0);
397         query = zquery2pquery(rr->query);
398         if (query)
399         {
400                 hv_store(href, "QUERY", 5, newSVpv((char *)query->buf, query->pos), 0);
401         }
402         else
403         {       
404                 rr->errcode = 108;
405         }
406         PUSHMARK(sp);
407         
408         XPUSHs(sv_2mortal(newRV( (SV*) href)));
409         
410         PUTBACK;
411
412         n = perl_call_sv(search_ref, G_SCALAR | G_DISCARD);
413
414         SPAGAIN;
415
416         temp = hv_fetch(href, "HITS", 4, 1);
417         hits = newSVsv(*temp);
418
419         temp = hv_fetch(href, "ERR_CODE", 8, 1);
420         err_code = newSVsv(*temp);
421
422         temp = hv_fetch(href, "ERR_STR", 7, 1);
423         err_str = newSVsv(*temp);
424
425         temp = hv_fetch(href, "HANDLE", 6, 1);
426         point = newSVsv(*temp);
427
428         PUTBACK;
429         FREETMPS;
430         LEAVE;
431         
432         hv_undef(href);
433         av_undef(aref);
434         rr->hits = SvIV(hits);
435         rr->errcode = SvIV(err_code);
436         ptr = SvPV(err_str, len);
437         ODR_errstr = (char *)odr_malloc(rr->stream, len + 1);
438         strcpy(ODR_errstr, ptr);
439         rr->errstring = ODR_errstr;
440 /*      ODR_point = (SV *)odr_malloc(rr->stream, sizeof(*point));
441         memcpy(ODR_point, point, sizeof(*point));
442         zhandle->handle = ODR_point;*/
443         zhandle->handle = point;
444         handle = zhandle;
445         sv_free(hits);
446         sv_free(err_code);
447         sv_free(err_str);
448         sv_free( (SV*) aref);
449         sv_free( (SV*) href);
450         /*sv_free(point);*/
451         wrbuf_free(query, 1);
452         return 0;
453 }
454
455
456 WRBUF oid2dotted(int *oid)
457 {
458
459         WRBUF buf = wrbuf_alloc();
460         int dot = 0;
461
462         for (; *oid != -1 ; oid++)
463         {
464                 char ibuf[16];
465                 if (dot)
466                 {
467                         wrbuf_putc(buf, '.');
468                 }
469                 else
470                 {
471                         dot = 1;
472                 }
473                 sprintf(ibuf, "%d", *oid);
474                 wrbuf_puts(buf, ibuf);
475         }
476         return buf;
477 }
478                 
479
480 int dotted2oid(char *dotted, int *buffer)
481 {
482         int *oid;
483         char ibuf[16];
484         char *ptr;
485         int n = 0;
486
487         ptr = ibuf;
488         oid = buffer;
489         while (*dotted)
490         {
491                 if (*dotted == '.')
492                 {
493                         n++;
494                         if (n == MAX_OID)  /* Terminate if more than MAX_OID entries */
495                         {
496                                 *oid = -1;
497                                 return -1;
498                         }
499                         *ptr = 0;
500                         sscanf(ibuf, "%d", oid++);
501                         ptr = ibuf;
502                         dotted++;
503
504                 }
505                 else
506                 {
507                         *ptr++ = *dotted++;
508                 }
509         }
510         if (n < MAX_OID)
511         {
512                 *ptr = 0;
513                 sscanf(ibuf, "%d", oid++);
514         }
515         *oid = -1;
516         return 0;
517 }
518
519
520 int bend_fetch(void *handle, bend_fetch_rr *rr)
521 {
522         HV *href;
523         SV **temp;
524         SV *basename;
525         SV *record;
526         SV *last;
527         SV *err_code;
528         SV *err_string;
529         SV *sur_flag;
530         SV *point;
531         SV *rep_form;
532         char *ptr;
533         char *ODR_record;
534         char *ODR_basename;
535         char *ODR_errstr;
536         int *ODR_oid_buf;
537         oident *oid;
538         WRBUF oid_dotted;
539         Zfront_handle *zhandle = (Zfront_handle *)handle;
540
541         Z_RecordComposition *composition;
542         Z_ElementSetNames *simple;
543         STRLEN length;
544
545         dSP;
546         ENTER;
547         SAVETMPS;
548
549         rr->errcode = 0;
550         href = newHV();
551         hv_store(href, "SETNAME", 7, newSVpv(rr->setname, 0), 0);
552         temp = hv_store(href, "OFFSET", 6, newSViv(rr->number), 0);
553         oid_dotted = oid2dotted(rr->request_format_raw);
554         hv_store(href, "REQ_FORM", 8, newSVpv((char *)oid_dotted->buf, oid_dotted->pos), 0);
555         hv_store(href, "REP_FORM", 8, newSVpv((char *)oid_dotted->buf, oid_dotted->pos), 0);
556         hv_store(href, "BASENAME", 8, newSVpv("", 0), 0);
557         hv_store(href, "RECORD", 6, newSVpv("", 0), 0);
558         hv_store(href, "LAST", 4, newSViv(0), 0);
559         hv_store(href, "ERR_CODE", 8, newSViv(0), 0);
560         hv_store(href, "ERR_STR", 7, newSVpv("", 0), 0);
561         hv_store(href, "SUR_FLAG", 8, newSViv(0), 0);
562         hv_store(href, "HANDLE", 6, zhandle->handle, 0);
563         hv_store(href, "PID", 3, newSViv(getpid()), 0);
564         if (rr->comp)
565         {
566                 composition = rr->comp;
567                 if (composition->which == Z_RecordComp_simple)
568                 {
569                         simple = composition->u.simple;
570                         if (simple->which == Z_ElementSetNames_generic)
571                         {
572                                 hv_store(href, "COMP", 4, newSVpv(simple->u.generic, 0), 0);
573                         } 
574                         else
575                         {
576                                 rr->errcode = 26;
577                         }
578                 }
579                 else
580                 {
581                         rr->errcode = 26;
582                 }
583         }
584
585         PUSHMARK(sp);
586
587         XPUSHs(sv_2mortal(newRV( (SV*) href)));
588
589         PUTBACK;
590         
591         perl_call_sv(fetch_ref, G_SCALAR | G_DISCARD);
592
593         SPAGAIN;
594
595         temp = hv_fetch(href, "BASENAME", 8, 1);
596         basename = newSVsv(*temp);
597
598         temp = hv_fetch(href, "RECORD", 6, 1);
599         record = newSVsv(*temp);
600
601         temp = hv_fetch(href, "LAST", 4, 1);
602         last = newSVsv(*temp);
603
604         temp = hv_fetch(href, "ERR_CODE", 8, 1);
605         err_code = newSVsv(*temp);
606
607         temp = hv_fetch(href, "ERR_STR", 7, 1),
608         err_string = newSVsv(*temp);
609
610         temp = hv_fetch(href, "SUR_FLAG", 8, 1);
611         sur_flag = newSVsv(*temp);
612
613         temp = hv_fetch(href, "REP_FORM", 8, 1);
614         rep_form = newSVsv(*temp);
615
616         temp = hv_fetch(href, "HANDLE", 6, 1);
617         point = newSVsv(*temp);
618
619         PUTBACK;
620         FREETMPS;
621         LEAVE;
622
623         hv_undef(href);
624         
625         ptr = SvPV(basename, length);
626         ODR_basename = (char *)odr_malloc(rr->stream, length + 1);
627         strcpy(ODR_basename, ptr);
628         rr->basename = ODR_basename;
629
630         ptr = SvPV(rep_form, length);
631         ODR_oid_buf = (int *)odr_malloc(rr->stream, (MAX_OID + 1) * sizeof(int));
632         if (dotted2oid(ptr, ODR_oid_buf) == -1)         /* Maximum number of OID elements exceeded */
633         {
634                 printf("Net::Z3950::SimpleServer: WARNING: OID structure too long, max length is %d\n", MAX_OID);
635         }
636         rr->output_format_raw = ODR_oid_buf;    
637         
638         ptr = SvPV(record, length);
639         oid = oid_getentbyoid(ODR_oid_buf);
640         if (oid->value == VAL_GRS1)             /* Treat GRS-1 records separately */
641         {
642                 rr->record = (char *) read_grs1(ptr, rr->stream);
643                 rr->len = -1;
644         }
645         else
646         {
647                 ODR_record = (char *)odr_malloc(rr->stream, length + 1);
648                 strcpy(ODR_record, ptr);
649                 rr->record = ODR_record;
650                 rr->len = length;
651         }
652         zhandle->handle = point;
653         handle = zhandle;
654         rr->last_in_set = SvIV(last);
655         
656         if (!(rr->errcode))
657         {
658                 rr->errcode = SvIV(err_code);
659                 ptr = SvPV(err_string, length);
660                 ODR_errstr = (char *)odr_malloc(rr->stream, length + 1);
661                 strcpy(ODR_errstr, ptr);
662                 rr->errstring = ODR_errstr;
663         }
664         rr->surrogate_flag = SvIV(sur_flag);
665
666         wrbuf_free(oid_dotted, 1);
667         sv_free((SV*) href);
668         sv_free(basename);
669         sv_free(record);
670         sv_free(last);
671         sv_free(err_string);
672         sv_free(err_code),
673         sv_free(sur_flag);
674         sv_free(rep_form);
675         
676         return 0;
677 }
678
679
680 int bend_present(void *handle, bend_present_rr *rr)
681 {
682
683         HV *href;
684         SV **temp;
685         SV *err_code;
686         SV *err_string;
687         SV *hits;
688         SV *point;
689         STRLEN len;
690         Z_RecordComposition *composition;
691         Z_ElementSetNames *simple;
692         char *ODR_errstr;
693         char *ptr;
694         Zfront_handle *zhandle = (Zfront_handle *)handle;
695
696 /*      WRBUF oid_dotted; */
697
698         dSP;
699         ENTER;
700         SAVETMPS;
701
702         href = newHV();
703         hv_store(href, "HANDLE", 6, zhandle->handle, 0);
704         hv_store(href, "ERR_CODE", 8, newSViv(0), 0);
705         hv_store(href, "ERR_STR", 7, newSVpv("", 0), 0);
706         hv_store(href, "START", 5, newSViv(rr->start), 0);
707         hv_store(href, "SETNAME", 7, newSVpv(rr->setname, 0), 0);
708         hv_store(href, "NUMBER", 6, newSViv(rr->number), 0);
709         /*oid_dotted = oid2dotted(rr->request_format_raw);
710         hv_store(href, "REQ_FORM", 8, newSVpv((char *)oid_dotted->buf, oid_dotted->pos), 0);*/
711         hv_store(href, "HITS", 4, newSViv(0), 0);
712         hv_store(href, "PID", 3, newSViv(getpid()), 0);
713         if (rr->comp)
714         {
715                 composition = rr->comp;
716                 if (composition->which == Z_RecordComp_simple)
717                 {
718                         simple = composition->u.simple;
719                         if (simple->which == Z_ElementSetNames_generic)
720                         {
721                                 hv_store(href, "COMP", 4, newSVpv(simple->u.generic, 0), 0);
722                         } 
723                         else
724                         {
725                                 rr->errcode = 26;
726                                 return 0;
727                         }
728                 }
729                 else
730                 {
731                         rr->errcode = 26;
732                         return 0;
733                 }
734         }
735
736         PUSHMARK(sp);
737         
738         XPUSHs(sv_2mortal(newRV( (SV*) href)));
739         
740         PUTBACK;
741         
742         perl_call_sv(present_ref, G_SCALAR | G_DISCARD);
743         
744         SPAGAIN;
745
746         temp = hv_fetch(href, "ERR_CODE", 8, 1);
747         err_code = newSVsv(*temp);
748
749         temp = hv_fetch(href, "ERR_STR", 7, 1);
750         err_string = newSVsv(*temp);
751
752         temp = hv_fetch(href, "HITS", 4, 1);
753         hits = newSVsv(*temp);
754
755         temp = hv_fetch(href, "HANDLE", 6, 1);
756         point = newSVsv(*temp);
757
758         PUTBACK;
759         FREETMPS;
760         LEAVE;
761         
762         hv_undef(href);
763         rr->errcode = SvIV(err_code);
764         rr->hits = SvIV(hits);
765
766         ptr = SvPV(err_string, len);
767         ODR_errstr = (char *)odr_malloc(rr->stream, len + 1);
768         strcpy(ODR_errstr, ptr);
769         rr->errstring = ODR_errstr;
770 /*      wrbuf_free(oid_dotted, 1);*/
771         zhandle->handle = point;
772         handle = zhandle;
773         sv_free(err_code);
774         sv_free(err_string);
775         sv_free(hits);
776         sv_free( (SV*) href);
777
778         return 0;
779 }
780
781
782 int bend_esrequest(void *handle, bend_esrequest_rr *rr)
783 {
784         perl_call_sv(esrequest_ref, G_VOID | G_DISCARD | G_NOARGS);
785         return 0;
786 }
787
788
789 int bend_delete(void *handle, bend_delete_rr *rr)
790 {
791         perl_call_sv(delete_ref, G_VOID | G_DISCARD | G_NOARGS);
792         return 0;
793 }
794
795
796 int bend_scan(void *handle, bend_scan_rr *rr)
797 {
798         HV *href;
799         AV *aref;
800         AV *list;
801         AV *entries;
802         HV *scan_item;
803         struct scan_entry *scan_list;
804         struct scan_entry *buffer;
805         int *step_size = rr->step_size;
806         int i;
807         char **basenames;
808         SV **temp;
809         SV *list_ref = sv_newmortal();
810         SV *err_code = sv_newmortal();
811         SV *err_str = sv_newmortal();
812         SV *point = sv_newmortal();
813         SV *status = sv_newmortal();
814         SV *number = sv_newmortal();
815         char *ptr;
816         char *ODR_errstr;
817         STRLEN len;
818         
819         Zfront_handle *zhandle = (Zfront_handle *)handle;
820
821         dSP;
822         ENTER;
823         SAVETMPS;
824         href = newHV();
825         list = newAV();
826         if (rr->term->term->which == Z_Term_general)
827         {
828                 hv_store(href, "TERM", 4, newSVpv(rr->term->term->u.general->buf, 0), 0);
829         } else {
830                 rr->errcode = 229;      /* Unsupported term type */
831                 return 0;
832         }
833         hv_store(href, "STEP", 4, newSViv(*step_size), 0);
834         hv_store(href, "NUMBER", 6, newSViv(rr->num_entries), 0);
835         hv_store(href, "POS", 3, newSViv(rr->term_position), 0);
836         hv_store(href, "ERR_CODE", 8, newSViv(0), 0);
837         hv_store(href, "ERR_STR", 7, newSVpv("", 0), 0);
838         hv_store(href, "HANDLE", 6, zhandle->handle, 0);
839         hv_store(href, "STATUS", 6, newSViv(BEND_SCAN_SUCCESS), 0);
840         hv_store(href, "ENTRIES", 7, newRV((SV *) list), 0);
841         aref = newAV();
842         basenames = rr->basenames;
843         for (i = 0; i < rr->num_bases; i++)
844         {
845                 av_push(aref, newSVpv(*basenames++, 0));
846         }
847         hv_store(href, "DATABASES", 9, newRV( (SV*) aref), 0);
848
849         PUSHMARK(sp);
850
851         XPUSHs(sv_2mortal(newRV( (SV*) href)));
852
853         PUTBACK;
854
855         perl_call_sv(scan_ref, G_SCALAR | G_DISCARD);
856
857         SPAGAIN;
858
859         temp = hv_fetch(href, "ERR_CODE", 8, 1);
860         err_code = newSVsv(*temp);
861
862         temp = hv_fetch(href, "ERR_STR", 7, 1);
863         err_str = newSVsv(*temp);
864
865         temp = hv_fetch(href, "HANDLE", 6, 1);
866         point = newSVsv(*temp);
867
868         temp = hv_fetch(href, "STATUS", 6, 1);
869         status = newSVsv(*temp);
870         
871         temp = hv_fetch(href, "NUMBER", 6, 1);
872         number = newSVsv(*temp);
873
874         temp = hv_fetch(href, "ENTRIES", 7, 1);
875         list_ref = newSVsv(*temp);
876         entries = (AV *)SvRV(list_ref);
877
878         PUTBACK;
879         FREETMPS;
880         LEAVE;
881
882         ptr = SvPV(err_str, len);
883         ODR_errstr = (char *)odr_malloc(rr->stream, len + 1);
884         strcpy(ODR_errstr, ptr);
885         rr->errstring = ODR_errstr;
886         rr->errcode = SvIV(err_code);
887         rr->num_entries = SvIV(number);
888         rr->status = SvIV(status);
889         scan_list = (struct scan_entry *) odr_malloc (rr->stream, rr->num_entries * sizeof(*scan_list));
890         buffer = scan_list;
891         for (i = 0; i < rr->num_entries; i++)
892         {
893                 scan_item = (HV *)SvRV(sv_2mortal(av_shift(entries)));
894                 temp = hv_fetch(scan_item, "TERM", 4, 1);
895                 ptr = SvPV(*temp, len);
896                 buffer->term = (char *) odr_malloc (rr->stream, len + 1); 
897                 strcpy(buffer->term, ptr);
898                 temp = hv_fetch(scan_item, "OCCURRENCE", 10, 1); 
899                 buffer->occurrences = SvIV(*temp);
900                 buffer++;
901                 hv_undef(scan_item);
902         }
903         rr->entries = scan_list;
904         zhandle->handle = point;
905         handle = zhandle;
906         /*sv_free(list_ref);*/
907         sv_free(err_code);
908         sv_free(err_str);
909         sv_free(status);
910         sv_free(number);
911         /*sv_free(point);*/
912         hv_undef(href);
913         av_undef(aref);
914         av_undef(list);
915         av_undef(entries);
916
917         return 0;
918 }
919
920
921 bend_initresult *bend_init(bend_initrequest *q)
922 {
923         bend_initresult *r = (bend_initresult *) odr_malloc (q->stream, sizeof(*r));
924         HV *href;
925         SV **temp;
926         SV *name;
927         SV *ver;
928         SV *err_str;
929         SV *status;
930         Zfront_handle *zhandle =  (Zfront_handle *) xmalloc (sizeof(*zhandle));
931         STRLEN len;
932         int n;
933         SV *handle;
934         /*char *name_ptr;
935         char *ver_ptr;*/
936         char *ptr;
937
938         dSP;
939         ENTER;
940         SAVETMPS;
941
942         /*q->bend_sort = bend_sort;*/
943         if (search_ref)
944         {
945                 q->bend_search = bend_search;
946         }
947         if (present_ref)
948         {
949                 q->bend_present = bend_present;
950         }
951         /*q->bend_esrequest = bend_esrequest;*/
952         /*q->bend_delete = bend_delete;*/
953         if (fetch_ref)
954         {
955                 q->bend_fetch = bend_fetch;
956         }
957         if (scan_ref)
958         {
959                 q->bend_scan = bend_scan;
960         }
961         href = newHV(); 
962         hv_store(href, "IMP_NAME", 8, newSVpv("", 0), 0);
963         hv_store(href, "IMP_VER", 7, newSVpv("", 0), 0);
964         hv_store(href, "ERR_CODE", 8, newSViv(0), 0);
965         hv_store(href, "PEER_NAME", 9, newSVpv(q->peer_name, 0), 0);
966         hv_store(href, "HANDLE", 6, newSVsv(&sv_undef), 0);
967         hv_store(href, "PID", 3, newSViv(getpid()), 0);
968
969         PUSHMARK(sp);   
970
971         XPUSHs(sv_2mortal(newRV( (SV*) href)));
972
973         PUTBACK;
974
975         if (init_ref != NULL)
976         {
977                 perl_call_sv(init_ref, G_SCALAR | G_DISCARD);
978         }
979
980         SPAGAIN;
981
982         temp = hv_fetch(href, "IMP_NAME", 8, 1);
983         name = newSVsv(*temp);
984
985         temp = hv_fetch(href, "IMP_VER", 7, 1);
986         ver = newSVsv(*temp);
987
988         temp = hv_fetch(href, "ERR_CODE", 8, 1);
989         status = newSVsv(*temp);
990
991         temp = hv_fetch(href, "HANDLE", 6, 1);
992         handle= newSVsv(*temp);
993
994         hv_undef(href);
995         PUTBACK;
996         FREETMPS;
997         LEAVE;
998         zhandle->handle = handle;
999         r->errcode = SvIV(status);
1000         r->handle = zhandle;
1001         ptr = SvPV(name, len);
1002         q->implementation_name = (char *)xmalloc(len + 1);
1003         strcpy(q->implementation_name, ptr);
1004 /*      q->implementation_name = SvPV(name, len);*/
1005         ptr = SvPV(ver, len);
1006         q->implementation_version = (char *)xmalloc(len + 1);
1007         strcpy(q->implementation_version, ptr);
1008         
1009         return r;
1010 }
1011
1012
1013 void bend_close(void *handle)
1014 {
1015         HV *href;
1016         Zfront_handle *zhandle = (Zfront_handle *)handle;
1017         SV **temp;
1018
1019         dSP;
1020         ENTER;
1021         SAVETMPS;
1022
1023         if (close_ref == NULL)
1024         {
1025                 return;
1026         }
1027
1028         href = newHV();
1029         hv_store(href, "HANDLE", 6, zhandle->handle, 0);
1030
1031         PUSHMARK(sp);
1032
1033         XPUSHs(sv_2mortal(newRV((SV *)href)));
1034
1035         PUTBACK;
1036         
1037         perl_call_sv(close_ref, G_SCALAR | G_DISCARD);
1038         
1039         SPAGAIN;
1040
1041         PUTBACK;
1042         FREETMPS;
1043         LEAVE;
1044
1045         xfree(handle);
1046         
1047         return;
1048 }
1049
1050
1051 #line 1044 "SimpleServer.c"
1052 XS(XS_Net__Z3950__SimpleServer_set_init_handler)
1053 {
1054     dXSARGS;
1055     if (items != 1)
1056         croak("Usage: Net::Z3950::SimpleServer::set_init_handler(arg)");
1057     {
1058         SV *    arg = ST(0);
1059 #line 1040 "SimpleServer.xs"
1060                 init_ref = newSVsv(arg);
1061 #line 1054 "SimpleServer.c"
1062     }
1063     XSRETURN_EMPTY;
1064 }
1065
1066 XS(XS_Net__Z3950__SimpleServer_set_close_handler)
1067 {
1068     dXSARGS;
1069     if (items != 1)
1070         croak("Usage: Net::Z3950::SimpleServer::set_close_handler(arg)");
1071     {
1072         SV *    arg = ST(0);
1073 #line 1047 "SimpleServer.xs"
1074                 close_ref = newSVsv(arg);
1075 #line 1068 "SimpleServer.c"
1076     }
1077     XSRETURN_EMPTY;
1078 }
1079
1080 XS(XS_Net__Z3950__SimpleServer_set_sort_handler)
1081 {
1082     dXSARGS;
1083     if (items != 1)
1084         croak("Usage: Net::Z3950::SimpleServer::set_sort_handler(arg)");
1085     {
1086         SV *    arg = ST(0);
1087 #line 1054 "SimpleServer.xs"
1088                 sort_ref = newSVsv(arg);
1089 #line 1082 "SimpleServer.c"
1090     }
1091     XSRETURN_EMPTY;
1092 }
1093
1094 XS(XS_Net__Z3950__SimpleServer_set_search_handler)
1095 {
1096     dXSARGS;
1097     if (items != 1)
1098         croak("Usage: Net::Z3950::SimpleServer::set_search_handler(arg)");
1099     {
1100         SV *    arg = ST(0);
1101 #line 1060 "SimpleServer.xs"
1102                 search_ref = newSVsv(arg);
1103 #line 1096 "SimpleServer.c"
1104     }
1105     XSRETURN_EMPTY;
1106 }
1107
1108 XS(XS_Net__Z3950__SimpleServer_set_fetch_handler)
1109 {
1110     dXSARGS;
1111     if (items != 1)
1112         croak("Usage: Net::Z3950::SimpleServer::set_fetch_handler(arg)");
1113     {
1114         SV *    arg = ST(0);
1115 #line 1067 "SimpleServer.xs"
1116                 fetch_ref = newSVsv(arg);
1117 #line 1110 "SimpleServer.c"
1118     }
1119     XSRETURN_EMPTY;
1120 }
1121
1122 XS(XS_Net__Z3950__SimpleServer_set_present_handler)
1123 {
1124     dXSARGS;
1125     if (items != 1)
1126         croak("Usage: Net::Z3950::SimpleServer::set_present_handler(arg)");
1127     {
1128         SV *    arg = ST(0);
1129 #line 1074 "SimpleServer.xs"
1130                 present_ref = newSVsv(arg);
1131 #line 1124 "SimpleServer.c"
1132     }
1133     XSRETURN_EMPTY;
1134 }
1135
1136 XS(XS_Net__Z3950__SimpleServer_set_esrequest_handler)
1137 {
1138     dXSARGS;
1139     if (items != 1)
1140         croak("Usage: Net::Z3950::SimpleServer::set_esrequest_handler(arg)");
1141     {
1142         SV *    arg = ST(0);
1143 #line 1081 "SimpleServer.xs"
1144                 esrequest_ref = newSVsv(arg);
1145 #line 1138 "SimpleServer.c"
1146     }
1147     XSRETURN_EMPTY;
1148 }
1149
1150 XS(XS_Net__Z3950__SimpleServer_set_delete_handler)
1151 {
1152     dXSARGS;
1153     if (items != 1)
1154         croak("Usage: Net::Z3950::SimpleServer::set_delete_handler(arg)");
1155     {
1156         SV *    arg = ST(0);
1157 #line 1088 "SimpleServer.xs"
1158                 delete_ref = newSVsv(arg);
1159 #line 1152 "SimpleServer.c"
1160     }
1161     XSRETURN_EMPTY;
1162 }
1163
1164 XS(XS_Net__Z3950__SimpleServer_set_scan_handler)
1165 {
1166     dXSARGS;
1167     if (items != 1)
1168         croak("Usage: Net::Z3950::SimpleServer::set_scan_handler(arg)");
1169     {
1170         SV *    arg = ST(0);
1171 #line 1095 "SimpleServer.xs"
1172                 scan_ref = newSVsv(arg);
1173 #line 1166 "SimpleServer.c"
1174     }
1175     XSRETURN_EMPTY;
1176 }
1177
1178 XS(XS_Net__Z3950__SimpleServer_start_server)
1179 {
1180     dXSARGS;
1181     {
1182 #line 1101 "SimpleServer.xs"
1183                 char **argv;
1184                 char **argv_buf;
1185                 char *ptr;
1186                 int i;
1187                 STRLEN len;
1188 #line 1181 "SimpleServer.c"
1189         int     RETVAL;
1190 #line 1107 "SimpleServer.xs"
1191                 argv_buf = (char **)xmalloc((items + 1) * sizeof(char *));
1192                 argv = argv_buf;
1193                 for (i = 0; i < items; i++)
1194                 {
1195                         ptr = SvPV(ST(i), len);
1196                         *argv_buf = (char *)xmalloc(len + 1);
1197                         strcpy(*argv_buf++, ptr); 
1198                 }
1199                 *argv_buf = NULL;
1200
1201                 RETVAL = statserv_main(items, argv, bend_init, bend_close);
1202 #line 1195 "SimpleServer.c"
1203         ST(0) = sv_newmortal();
1204         sv_setiv(ST(0), (IV)RETVAL);
1205     }
1206     XSRETURN(1);
1207 }
1208
1209 XS(XS_Net__Z3950__SimpleServer_ScanSuccess)
1210 {
1211     dXSARGS;
1212     if (items != 0)
1213         croak("Usage: Net::Z3950::SimpleServer::ScanSuccess()");
1214     {
1215         int     RETVAL;
1216 #line 1125 "SimpleServer.xs"
1217                 RETVAL = BEND_SCAN_SUCCESS;
1218 #line 1211 "SimpleServer.c"
1219         ST(0) = sv_newmortal();
1220         sv_setiv(ST(0), (IV)RETVAL);
1221     }
1222     XSRETURN(1);
1223 }
1224
1225 XS(XS_Net__Z3950__SimpleServer_ScanPartial)
1226 {
1227     dXSARGS;
1228     if (items != 0)
1229         croak("Usage: Net::Z3950::SimpleServer::ScanPartial()");
1230     {
1231         int     RETVAL;
1232 #line 1132 "SimpleServer.xs"
1233                 RETVAL = BEND_SCAN_PARTIAL;
1234 #line 1227 "SimpleServer.c"
1235         ST(0) = sv_newmortal();
1236         sv_setiv(ST(0), (IV)RETVAL);
1237     }
1238     XSRETURN(1);
1239 }
1240
1241 #ifdef __cplusplus
1242 extern "C"
1243 #endif
1244 XS(boot_Net__Z3950__SimpleServer)
1245 {
1246     dXSARGS;
1247     char* file = __FILE__;
1248
1249     XS_VERSION_BOOTCHECK ;
1250
1251         newXS("Net::Z3950::SimpleServer::set_init_handler", XS_Net__Z3950__SimpleServer_set_init_handler, file);
1252         newXS("Net::Z3950::SimpleServer::set_close_handler", XS_Net__Z3950__SimpleServer_set_close_handler, file);
1253         newXS("Net::Z3950::SimpleServer::set_sort_handler", XS_Net__Z3950__SimpleServer_set_sort_handler, file);
1254         newXS("Net::Z3950::SimpleServer::set_search_handler", XS_Net__Z3950__SimpleServer_set_search_handler, file);
1255         newXS("Net::Z3950::SimpleServer::set_fetch_handler", XS_Net__Z3950__SimpleServer_set_fetch_handler, file);
1256         newXS("Net::Z3950::SimpleServer::set_present_handler", XS_Net__Z3950__SimpleServer_set_present_handler, file);
1257         newXS("Net::Z3950::SimpleServer::set_esrequest_handler", XS_Net__Z3950__SimpleServer_set_esrequest_handler, file);
1258         newXS("Net::Z3950::SimpleServer::set_delete_handler", XS_Net__Z3950__SimpleServer_set_delete_handler, file);
1259         newXS("Net::Z3950::SimpleServer::set_scan_handler", XS_Net__Z3950__SimpleServer_set_scan_handler, file);
1260         newXS("Net::Z3950::SimpleServer::start_server", XS_Net__Z3950__SimpleServer_start_server, file);
1261         newXS("Net::Z3950::SimpleServer::ScanSuccess", XS_Net__Z3950__SimpleServer_ScanSuccess, file);
1262         newXS("Net::Z3950::SimpleServer::ScanPartial", XS_Net__Z3950__SimpleServer_ScanPartial, file);
1263     XSRETURN_YES;
1264 }
1265