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