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