Fixed memory leak - happened when fetching MARC records.
[yaz-moved-to-github.git] / ztest / ztest.c
1 /*
2  * Copyright (c) 1995-1998, Index Data.
3  * See the file LICENSE for details.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * NT Service interface by
7  *    Chas Woodfield, Fretwell Downing Datasystems.
8  *
9  * $Log: ztest.c,v $
10  * Revision 1.20  1998-12-14 14:48:05  adam
11  * Fixed memory leak - happened when fetching MARC records.
12  *
13  * Revision 1.19  1998/10/20 15:16:22  adam
14  * Minor change to prevent warning.
15  *
16  * Revision 1.18  1998/10/20 15:13:45  adam
17  * Minor fix regarding output for Item Order.
18  *
19  * Revision 1.17  1998/10/18 22:33:35  quinn
20  * Added diagnostic dump of Item Order Eservice.
21  *
22  * Revision 1.16  1998/10/15 08:26:23  adam
23  * Added type cast to make C++ happy.
24  *
25  * Revision 1.15  1998/10/13 20:05:57  adam
26  * Minor change.
27  *
28  * Revision 1.14  1998/10/13 16:12:25  adam
29  * Added support for Surrogate Diagnostics for Scan Term entries.
30  *
31  * Revision 1.13  1998/08/19 16:10:09  adam
32  * Changed som member names of DeleteResultSetRequest/Response.
33  *
34  * Revision 1.12  1998/07/20 12:38:44  adam
35  * Implemented delete result set service to server API.
36  *
37  * Revision 1.11  1998/06/09 13:55:08  adam
38  * Minor changes.
39  *
40  * Revision 1.10  1998/05/27 16:55:54  adam
41  * Minor changes.
42  *
43  * Revision 1.9  1998/03/31 11:07:45  adam
44  * Furhter work on UNIverse resource report.
45  * Added Extended Services handling in frontend server.
46  *
47  * Revision 1.8  1998/02/11 11:53:36  adam
48  * Changed code so that it compiles as C++.
49  *
50  * Revision 1.7  1998/02/10 11:03:57  adam
51  * Added support for extended handlers in backend server interface.
52  *
53  * Revision 1.6  1998/01/29 13:16:02  adam
54  * Added dummy sort in test server.
55  *
56  * Revision 1.5  1997/11/07 13:31:58  adam
57  * Added NT Service name part of statserv_options_block. Moved NT
58  * service utility to server library.
59  *
60  * Revision 1.4  1997/09/17 12:10:43  adam
61  * YAZ version 1.4.
62  *
63  * Revision 1.3  1997/09/09 10:10:20  adam
64  * Another MSV5.0 port. Changed projects to include proper
65  * library/include paths.
66  * Server starts server in test-mode when no options are given.
67  *
68  * Revision 1.2  1997/09/04 13:50:31  adam
69  * Bug fix in ztest.
70  *
71  */
72
73 /*
74  * Demonstration of simple server
75  */
76
77 #include <stdio.h>
78 #include <stdlib.h>
79 #include <ctype.h>
80 #include <assert.h>
81
82 #include <backend.h>
83 #include <proto.h>
84 #include <log.h>
85
86 Z_GenericRecord *read_grs1(FILE *f, ODR o);
87
88 int ztest_search (void *handle, bend_search_rr *rr);
89 int ztest_sort (void *handle, bend_sort_rr *rr);
90 int ztest_present (void *handle, bend_present_rr *rr);
91 int ztest_esrequest (void *handle, bend_esrequest_rr *rr);
92 int ztest_delete (void *handle, bend_delete_rr *rr);
93
94 bend_initresult *bend_init(bend_initrequest *q)
95 {
96     bend_initresult *r = (bend_initresult *) odr_malloc (q->stream, sizeof(*r));
97     static char *dummy = "Hej fister";
98
99     r->errcode = 0;
100     r->errstring = 0;
101     r->handle = dummy;
102     q->bend_sort = ztest_sort;       /* register sort handler */
103     q->bend_search = ztest_search;   /* register search handler */
104     q->bend_present = ztest_present; /* register present handle */
105     q->bend_esrequest = ztest_esrequest;
106     q->bend_delete = ztest_delete;
107     return r;
108 }
109
110 int ztest_search (void *handle, bend_search_rr *rr)
111 {
112     rr->hits = rand() % 22;
113     return 0;
114 }
115
116 int ztest_present (void *handle, bend_present_rr *rr)
117 {
118     return 0;
119 }
120
121 int ztest_esrequest (void *handle, bend_esrequest_rr *rr)
122 {
123     logf(LOG_LOG, "function: %d", *rr->esr->function);
124     if (rr->esr->packageName)
125         logf(LOG_LOG, "packagename: %s", rr->esr->packageName);
126     logf(LOG_LOG, "Waitaction: %d", *rr->esr->waitAction);
127
128     if (!rr->esr->taskSpecificParameters)
129     {
130         logf (LOG_WARN, "No task specific parameters");
131     }
132     else if (rr->esr->taskSpecificParameters->which != Z_External_itemOrder)
133     {
134         logf (LOG_WARN, "Not Item Order %d", rr->esr->taskSpecificParameters->which);
135     }
136     else
137     {
138         Z_ItemOrder *it = rr->esr->taskSpecificParameters->u.itemOrder;
139         switch (it->which)
140         {
141 #ifdef ASN_COMPILED
142         case Z_IOItemOrder_esRequest:
143 #else
144         case Z_ItemOrder_esRequest:
145 #endif
146         {
147             Z_IORequest *ir = it->u.esRequest;
148             Z_IOOriginPartToKeep *k = ir->toKeep;
149             Z_IOOriginPartNotToKeep *n = ir->notToKeep;
150             
151             if (k && k->contact)
152             {
153                 if (k->contact->name)
154                     logf(LOG_LOG, "contact name %s", k->contact->name);
155                 if (k->contact->phone)
156                     logf(LOG_LOG, "contact phone %s", k->contact->phone);
157                 if (k->contact->email)
158                     logf(LOG_LOG, "contact email %s", k->contact->email);
159             }
160             if (k->addlBilling)
161             {
162                 logf(LOG_LOG, "Billing info (not shown)");
163             }
164             
165             if (n->resultSetItem)
166             {
167                 logf(LOG_LOG, "resultsetItem");
168                 logf(LOG_LOG, "setId: %s", n->resultSetItem->resultSetId);
169                 logf(LOG_LOG, "item: %d", *n->resultSetItem->item);
170             }
171         }
172         break;
173         }
174     }
175     rr->errcode = 0;
176     return 0;
177 }
178
179 int ztest_delete (void *handle, bend_delete_rr *rr)
180 {
181     if (rr->num_setnames == 1 && !strcmp (rr->setnames[0], "1"))
182         rr->delete_status = Z_DeleteStatus_success;
183     else
184         rr->delete_status = Z_DeleteStatus_resultSetDidNotExist;
185     return 0;
186 }
187
188 /* Obsolete bend_search, never called because handler is registered */
189 bend_searchresult *bend_search(void *handle, bend_searchrequest *q, int *fd)
190 {
191     return 0;
192 }
193
194 /* Our sort handler really doesn't sort... */
195 int ztest_sort (void *handle, bend_sort_rr *rr)
196 {
197     rr->errcode = 0;
198     rr->sort_status = Z_SortStatus_success;
199     return 0;
200 }
201
202 static int atoin (const char *buf, int n)
203 {
204     int val = 0;
205     while (--n >= 0)
206     {
207         if (isdigit(*buf))
208             val = val*10 + (*buf - '0');
209         buf++;
210     }
211     return val;
212 }
213
214 char *marc_read(FILE *inf, ODR odr)
215 {
216     char length_str[5];
217     size_t size;
218     char *buf;
219
220     if (fread (length_str, 1, 5, inf) != 5)
221         return NULL;
222     size = atoin (length_str, 5);
223     if (size <= 6)
224         return NULL;
225     if (!(buf = (char*) odr_malloc (odr, size+1)))
226         return NULL;
227     if (fread (buf+5, 1, size-5, inf) != (size-5))
228     {
229         xfree (buf);
230         return NULL;
231     }
232     memcpy (buf, length_str, 5);
233     buf[size] = '\0';
234     return buf;
235 }
236
237 static char *dummy_database_record (int num, ODR odr)
238 {
239     FILE *inf = fopen ("dummy-records", "r");
240     char *buf;
241
242     if (!inf)
243         return NULL;
244     while (--num >= 0)
245     {
246         if (num == 98)
247         {
248             buf = (char*) odr_malloc(odr, 2101);
249             assert(buf);
250             memset(buf, 'A', 2100);
251             buf[2100] = '\0';
252             break;
253         }
254         else
255             buf = marc_read (inf, odr);
256         if (!num || !buf)
257             break;
258     }
259     fclose(inf);
260     if (num < 0)
261         return 0;
262     return buf;
263 }
264
265 static Z_GenericRecord *dummy_grs_record (int num, ODR o)
266 {
267     FILE *f = fopen("dummy-grs", "r");
268     char line[512];
269     Z_GenericRecord *r = 0;
270     int n;
271
272     if (!f)
273         return 0;
274     while (fgets(line, 512, f))
275         if (*line == '#' && sscanf(line, "#%d", &n) == 1 && n == num)
276         {
277             r = read_grs1(f, o);
278             break;
279         }
280     fclose(f);
281     return r;
282 }
283
284 bend_fetchresult *bend_fetch(void *handle, bend_fetchrequest *q, int *fd)
285 {
286     bend_fetchresult *r = (bend_fetchresult *)
287                         odr_malloc (q->stream, sizeof(*r));
288     char *cp;
289     r->errstring = 0;
290     r->last_in_set = 0;
291     r->basename = "DUMMY";
292     r->format = q->format;  
293     if (q->format == VAL_SUTRS)
294     {
295         char buf[100];
296
297         sprintf(buf, "This is dummy SUTRS record number %d\n", q->number);
298         r->len = strlen(buf);
299         r->record = (char *) odr_malloc (q->stream, r->len+1);
300         strcpy(r->record, buf);
301     }
302     else if (q->format == VAL_GRS1)
303     {
304         r->len = -1;
305         r->record = (char*) dummy_grs_record(q->number, q->stream);
306         if (!r->record)
307         {
308             r->errcode = 13;
309             return r;
310         }
311     }
312     else if ((cp = dummy_database_record(q->number, q->stream)))
313     {
314         r->len = strlen(cp);
315         r->record = (char *) odr_malloc (q->stream, 1+r->len);
316         strcpy (r->record, cp);
317         r->format = VAL_USMARC;
318     }
319     else
320     {
321         r->errcode = 13;
322         return r;
323     }
324     r->errcode = 0;
325     return r;
326 }
327
328 /*
329  * silly dummy-scan what reads words from a file.
330  */
331 bend_scanresult *bend_scan(void *handle, bend_scanrequest *q, int *fd)
332 {
333     bend_scanresult *r = (bend_scanresult *)
334         odr_malloc (q->stream, sizeof(*r));
335     static FILE *f = 0;
336     static struct scan_entry list[200];
337     static char entries[200][80];
338     int hits[200];
339     char term[80], *p;
340     int i, pos;
341
342     r->errcode = 0;
343     r->errstring = 0;
344     r->entries = list;
345     r->status = BEND_SCAN_SUCCESS;
346     if (!f && !(f = fopen("dummy-words", "r")))
347     {
348         perror("dummy-words");
349         exit(1);
350     }
351     if (q->term->term->which != Z_Term_general)
352     {
353         r->errcode = 229; /* unsupported term type */
354         return r;
355     }
356     if (q->term->term->u.general->len >= 80)
357     {
358         r->errcode = 11; /* term too long */
359         return r;
360     }
361     if (q->num_entries > 200)
362     {
363         r->errcode = 31;
364         return r;
365     }
366     memcpy(term, q->term->term->u.general->buf, q->term->term->u.general->len);
367     term[q->term->term->u.general->len] = '\0';
368     for (p = term; *p; p++)
369         if (islower(*p))
370             *p = toupper(*p);
371
372     fseek(f, 0, SEEK_SET);
373     r->num_entries = 0;
374     for (i = 0, pos = 0; fscanf(f, " %79[^:]:%d", entries[pos], &hits[pos]) == 2;
375         i++, pos < 199 ? pos++ : (pos = 0))
376     {
377         if (!r->num_entries && strcmp(entries[pos], term) >= 0) /* s-point fnd */
378         {
379             if ((r->term_position = q->term_position) > i + 1)
380             {
381                 r->term_position = i + 1;
382                 r->status = BEND_SCAN_PARTIAL;
383             }
384             for (; r->num_entries < r->term_position; r->num_entries++)
385             {
386                 int po;
387
388                 po = pos - r->term_position + r->num_entries + 1; /* find pos */
389                 if (po < 0)
390                     po += 200;
391
392                 if (!strcmp (term, "SD") && r->num_entries == 2)
393                 {
394                     list[r->num_entries].term = entries[pos];
395                     list[r->num_entries].occurrences = -1;
396                     list[r->num_entries].errcode = 233;
397                     list[r->num_entries].errstring = "SD for Scan Term";
398                 }
399                 else
400                 {
401                     list[r->num_entries].term = entries[po];
402                     list[r->num_entries].occurrences = hits[po];
403                 }
404             }
405         }
406         else if (r->num_entries)
407         {
408             list[r->num_entries].term = entries[pos];
409             list[r->num_entries].occurrences = hits[pos];
410             r->num_entries++;
411         }
412         if (r->num_entries >= q->num_entries)
413             break;
414     }
415     if (feof(f))
416         r->status = BEND_SCAN_PARTIAL;
417     return r;
418 }
419
420 void bend_close(void *handle)
421 {
422     return;
423 }
424
425 int main(int argc, char **argv)
426 {
427     return statserv_main(argc, argv);
428 }