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