5be99a9a22aadd1120d4d88440f38646344e109d
[yaz-moved-to-github.git] / ztest / ztest.c
1 /*
2  * Copyright (c) 1995-1997, 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.2  1997-09-04 13:50:31  adam
11  * Bug fix in ztest.
12  *
13  */
14
15 /*
16  * Demonstration of simple server
17  */
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <ctype.h>
22 #include <assert.h>
23
24 #include <backend.h>
25 #include <xmalloc.h>
26 #include <proto.h>
27
28 /* Specifically for NT Services - Shouldn't cause problems on UNIX */
29 #include "service.h"
30
31 Z_GenericRecord *read_grs1(FILE *f, ODR o);
32
33 bend_initresult *bend_init(bend_initrequest *q)
34 {
35     static bend_initresult r;
36     static char *dummy = "Hej fister";
37
38     r.errcode = 0;
39     r.errstring = 0;
40     r.handle = dummy;
41     return &r;
42 }
43
44 bend_searchresult *bend_search(void *handle, bend_searchrequest *q, int *fd)
45 {
46     static bend_searchresult r;
47
48     r.errcode = 0;
49     r.errstring = 0;
50     r.hits = rand() % 22;
51     return &r;
52 }
53
54 static int atoin (const char *buf, int n)
55 {
56     int val = 0;
57     while (--n >= 0)
58     {
59         if (isdigit(*buf))
60             val = val*10 + (*buf - '0');
61         buf++;
62     }
63     return val;
64 }
65
66 char *marc_read(FILE *inf)
67 {
68     char length_str[5];
69     size_t size;
70     char *buf;
71
72     if (fread (length_str, 1, 5, inf) != 5)
73         return NULL;
74     size = atoin (length_str, 5);
75     if (size <= 6)
76         return NULL;
77     if (!(buf = xmalloc (size+1)))
78         return NULL;
79     if (fread (buf+5, 1, size-5, inf) != (size-5))
80     {
81         xfree (buf);
82         return NULL;
83     }
84     memcpy (buf, length_str, 5);
85     buf[size] = '\0';
86     return buf;
87 }
88
89 static char *dummy_database_record (int num)
90 {
91     FILE *inf = fopen ("dummy-records", "r");
92     char *buf = 0;
93
94     if (!inf)
95         return NULL;
96     while (--num >= 0)
97     {
98         if (buf)
99            xfree(buf);
100         if (num == 98)
101         {
102             assert(buf = xmalloc(2101));
103             memset(buf, 'A', 2100);
104             buf[2100] = '\0';
105             break;
106         }
107         else
108             buf = marc_read (inf);
109         if (!num || !buf)
110             break;
111     }
112     fclose(inf);
113     if (num < 0)
114         return 0;
115     return buf;
116 }
117
118 static Z_GenericRecord *dummy_grs_record (int num, ODR o)
119 {
120     FILE *f = fopen("dummy-grs", "r");
121     char line[512];
122     Z_GenericRecord *r = 0;
123     int n;
124
125     if (!f)
126         return 0;
127     while (fgets(line, 512, f))
128         if (*line == '#' && sscanf(line, "#%d", &n) == 1 && n == num)
129         {
130             r = read_grs1(f, o);
131             break;
132         }
133     fclose(f);
134     return r;
135 }
136
137 bend_fetchresult *bend_fetch(void *handle, bend_fetchrequest *q, int *num)
138 {
139     static bend_fetchresult r;
140     static char *bbb = 0;
141
142     r.errstring = 0;
143     r.last_in_set = 0;
144     r.basename = "DUMMY";
145     if (bbb)
146     {
147     xfree(bbb);
148         bbb = 0;
149     }
150     
151     if (q->format == VAL_SUTRS)
152     {
153         char buf[100];
154
155         sprintf(buf, "This is dummy SUTRS record number %d\n", q->number);
156         assert(r.record = bbb = xmalloc(strlen(buf)+1));
157         strcpy(bbb, buf);
158         r.len = strlen(buf);
159     }
160     else if (q->format == VAL_GRS1)
161     {
162         r.len = -1;
163         r.record = (char*) dummy_grs_record(q->number, q->stream);
164         if (!r.record)
165         {
166             r.errcode = 13;
167             return &r;
168         }
169     }
170     else if (!(r.record = bbb = dummy_database_record(q->number)))
171     {
172         r.errcode = 13;
173         return &r;
174     }
175     else
176         r.len = strlen(r.record);
177     r.format = q->format;
178     r.errcode = 0;
179     return &r;
180 }
181
182 bend_deleteresult *bend_delete(void *handle, bend_deleterequest *q, int *num)
183 {
184     return 0;
185 }
186
187 #if 0
188 bend_scanresult *bend_scan(void *handle, bend_scanrequest *q, int *num)
189 {
190     static struct scan_entry list[200];
191     static char buf[200][200];
192     static bend_scanresult r;
193     int i;
194
195     r.term_position = q->term_position;
196     r.num_entries = q->num_entries;
197     r.entries = list;
198     for (i = 0; i < r.num_entries; i++)
199     {
200         list[i].term = buf[i];
201         sprintf(list[i].term, "term-%d", i+1);
202         list[i].occurrences = rand() % 100000;
203     }
204     r.errcode = 0;
205     r.errstring = 0;
206     return &r;
207 }
208 #else
209 /*
210  * silly dummy-scan what reads words from a file.
211  */
212 bend_scanresult *bend_scan(void *handle, bend_scanrequest *q, int *num)
213 {
214     static bend_scanresult r;
215     static FILE *f = 0;
216     static struct scan_entry list[200];
217     static char entries[200][80];
218     int hits[200];
219     char term[80], *p;
220     int i, pos;
221
222     r.errstring = 0;
223     r.entries = list;
224     r.status = BEND_SCAN_SUCCESS;
225     if (!f && !(f = fopen("dummy-words", "r")))
226     {
227         perror("dummy-words");
228         exit(1);
229     }
230     if (q->term->term->which != Z_Term_general)
231     {
232         r.errcode = 229; /* unsupported term type */
233         return &r;
234     }
235     if (q->term->term->u.general->len >= 80)
236     {
237         r.errcode = 11; /* term too long */
238         return &r;
239     }
240     if (q->num_entries > 200)
241     {
242         r.errcode = 31;
243         return &r;
244     }
245     memcpy(term, q->term->term->u.general->buf, q->term->term->u.general->len);
246     term[q->term->term->u.general->len] = '\0';
247     for (p = term; *p; p++)
248         if (islower(*p))
249             *p = toupper(*p);
250
251     fseek(f, 0, 0);
252     r.num_entries = 0;
253     for (i = 0, pos = 0; fscanf(f, " %79[^:]:%d", entries[pos], &hits[pos]) == 2;
254         i++, pos < 199 ? pos++ : (pos = 0))
255     {
256         if (!r.num_entries && strcmp(entries[pos], term) >= 0) /* s-point fnd */
257         {
258             if ((r.term_position = q->term_position) > i + 1)
259             {
260                 r.term_position = i + 1;
261                 r.status = BEND_SCAN_PARTIAL;
262             }
263             for (; r.num_entries < r.term_position; r.num_entries++)
264             {
265                 int po;
266
267                 po = pos - r.term_position + r.num_entries + 1; /* find pos */
268                 if (po < 0)
269                     po += 200;
270                 list[r.num_entries].term = entries[po];
271                 list[r.num_entries].occurrences = hits[po];
272             }
273         }
274         else if (r.num_entries)
275         {
276             list[r.num_entries].term = entries[pos];
277             list[r.num_entries].occurrences = hits[pos];
278             r.num_entries++;
279         }
280         if (r.num_entries >= q->num_entries)
281             break;
282     }
283     if (feof(f))
284         r.status = BEND_SCAN_PARTIAL;
285     return &r;
286 }
287
288 #endif
289
290 void bend_close(void *handle)
291 {
292     return;
293 }
294
295 typedef struct _Args
296 {
297     char **argv;
298     int argc;
299 } Args; 
300
301 static Args ArgDetails;
302
303 /* name of the executable */
304 #define SZAPPNAME            "server"
305
306 /* internal name of the service */
307 #define SZSERVICENAME        "Z3950 Test Server"
308
309 /* displayed name of the service */
310 #define SZSERVICEDISPLAYNAME "Z3950 Test Server"
311
312 /* list of service dependencies - "dep1\0dep2\0\0" */
313 #define SZDEPENDENCIES       ""
314
315 int main(int argc, char **argv)
316 {
317     /* Lets setup the Arg structure */
318     ArgDetails.argc = argc;
319     ArgDetails.argv = argv;
320
321 #ifdef WIN32
322
323     /* Now setup the service with the service controller */
324     SetupService(argc, argv, &ArgDetails, SZAPPNAME, SZSERVICENAME, SZSERVICEDISPLAYNAME, SZDEPENDENCIES);
325
326 #else /* WIN32 */
327
328     /* The service controller does the following for us under windows */
329     if (StartAppService(NULL, argc, argv))
330         RunAppService(&ArgDetails);
331
332     /* Ensure the service has been stopped */
333     StopAppService(NULL);
334
335 #endif /* WIN32 */
336
337     return(0);
338 }
339
340 int StartAppService(void *pHandle, int argc, char **argv)
341 {
342     /* Initializes the App */
343     return 1;
344 }
345
346 void RunAppService(void *pHandle)
347 {
348     Args *pArgs = (Args *)pHandle;
349
350     /* Starts the app running */
351     statserv_main(pArgs->argc, pArgs->argv);
352 }
353
354 void StopAppService(void *pHandle)
355 {
356     /* Stops the app */
357     statserv_closedown();
358 }