Towards GPL
[idzebra-moved-to-github.git] / index / zserver.c
1 /* $Id: zserver.c,v 1.90 2002-08-02 19:26:56 adam Exp $
2    Copyright (C) 1995,1996,1997,1998,1999,2000,2001,2002
3    Index Data Aps
4
5 This file is part of the Zebra server.
6
7 Zebra is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
11
12 Zebra is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with Zebra; see the file LICENSE.zebra.  If not, write to the
19 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA.
21 */
22
23
24
25 #include <stdio.h>
26 #include <assert.h>
27 #include <fcntl.h>
28 #ifdef WIN32
29 #include <io.h>
30 #include <process.h>
31 #else
32 #include <unistd.h>
33 #endif
34
35 #include <yaz/data1.h>
36 #ifdef ASN_COMPILED
37 #include <yaz/ill.h>
38 #endif
39
40 #include "zserver.h"
41
42 static int bend_sort (void *handle, bend_sort_rr *rr);
43 static int bend_delete (void *handle, bend_delete_rr *rr);
44 static int bend_esrequest (void *handle, bend_esrequest_rr *rr);
45 static int bend_segment (void *handle, bend_segment_rr *rr);
46 static int bend_search (void *handle, bend_search_rr *r);
47 static int bend_fetch (void *handle, bend_fetch_rr *r);
48 static int bend_scan (void *handle, bend_scan_rr *r);
49
50 bend_initresult *bend_init (bend_initrequest *q)
51 {
52     bend_initresult *r = (bend_initresult *)
53         odr_malloc (q->stream, sizeof(*r));
54     ZebraHandle zh;
55     struct statserv_options_block *sob;
56     char *user = NULL;
57     char *passwd = NULL;
58
59     r->errcode = 0;
60     r->errstring = 0;
61     q->bend_sort = bend_sort;
62     q->bend_delete = bend_delete;
63     q->bend_esrequest = bend_esrequest;
64     q->bend_segment = bend_segment;
65     q->bend_search = bend_search;
66     q->bend_fetch = bend_fetch;
67     q->bend_scan = bend_scan;
68
69 #if ZMBOL
70     q->implementation_name = "Z'mbol Information Server";
71     q->implementation_version = "Z'mbol " ZEBRAVER;
72 #else
73     q->implementation_name = "Zebra Information Server";
74     q->implementation_version = "Zebra " ZEBRAVER;
75 #endif
76
77     logf (LOG_DEBUG, "bend_init");
78
79     sob = statserv_getcontrol ();
80     if (!(zh = zebra_open (sob->handle)))
81     {
82         yaz_log (LOG_FATAL, "Failed to open config `%s'", sob->configname);
83         r->errcode = 1;
84         return r;
85     }
86     if (q->auth)
87     {
88         if (q->auth->which == Z_IdAuthentication_open)
89         {
90             char *openpass = xstrdup (q->auth->u.open);
91             char *cp = strchr (openpass, '/');
92             if (cp)
93             {
94                 *cp = '\0';
95                 user = nmem_strdup (odr_getmem (q->stream), openpass);
96                 passwd = nmem_strdup (odr_getmem (q->stream), cp+1);
97             }
98             xfree (openpass);
99         }
100     }
101     if (zebra_auth (zh, user, passwd))
102     {
103         r->errcode = 222;
104         r->errstring = user;
105         zebra_close (zh);
106         return r;
107     }
108     r->handle = zh;
109     if (q->charneg_request) /* characater set and langauge negotiation? */
110     {
111         char **charsets = 0;
112         int num_charsets;
113         char **langs = 0;
114         int num_langs = 0;
115         int selected = 0;
116         int i;
117
118         NMEM nmem = nmem_create ();
119         yaz_log (LOG_LOG, "character set and language negotiation");
120
121         yaz_get_proposal_charneg (nmem, q->charneg_request,
122                                   &charsets, &num_charsets,
123                                   &langs, &num_langs, &selected);
124         for (i = 0; i < num_charsets; i++)
125         {
126             yaz_log (LOG_LOG, "charset %d %s", i, charsets[i]);
127             
128             if (odr_set_charset (q->decode, "UTF-8", charsets[i]) == 0)
129             {
130                 odr_set_charset (q->stream, charsets[i], "UTF-8");
131                 if (selected)
132                     zebra_record_encoding (zh, charsets[i]);
133                 q->charneg_response =
134                     yaz_set_response_charneg (q->stream, charsets[i],
135                                               0, selected);
136                 break;
137             }
138         }
139         nmem_destroy (nmem);
140     }
141     return r;
142 }
143
144 static void search_terms (ZebraHandle zh, bend_search_rr *r)
145 {
146     int count;
147     int no_terms;
148     int i;
149     int type;
150     struct Z_External *ext;
151     Z_SearchInfoReport *sr;
152
153     /* get no of terms for result set */
154     no_terms = zebra_resultSetTerms (zh, r->setname, 0, 0, 0, 0, 0);
155     if (!no_terms)
156         return;
157
158     r->search_info = odr_malloc (r->stream, sizeof(*r->search_info));
159
160     r->search_info->num_elements = 1;
161     r->search_info->list =
162         odr_malloc (r->stream, sizeof(*r->search_info->list));
163     r->search_info->list[0] =
164         odr_malloc (r->stream, sizeof(**r->search_info->list));
165     r->search_info->list[0]->category = 0;
166     r->search_info->list[0]->which = Z_OtherInfo_externallyDefinedInfo;
167     ext = odr_malloc (r->stream, sizeof(*ext));
168     r->search_info->list[0]->information.externallyDefinedInfo = ext;
169     ext->direct_reference =
170         yaz_oidval_to_z3950oid (r->stream, CLASS_USERINFO, VAL_SEARCHRES1);
171     ext->indirect_reference = 0;
172     ext->descriptor = 0;
173     ext->which = Z_External_searchResult1;
174     sr = odr_malloc (r->stream, sizeof(Z_SearchInfoReport));
175     ext->u.searchResult1 = sr;
176     sr->num = no_terms;
177     sr->elements = odr_malloc (r->stream, sr->num *
178                                sizeof(*sr->elements));
179     for (i = 0; i<no_terms; i++)
180     {
181         Z_Term *term;
182         char outbuf[1024];
183         size_t len = sizeof(outbuf);
184         zebra_resultSetTerms (zh, r->setname, i,
185                               &count, &type, outbuf, &len);
186         
187         sr->elements[i] = odr_malloc (r->stream, sizeof(**sr->elements));
188         sr->elements[i]->subqueryId = 0;
189         sr->elements[i]->fullQuery = odr_malloc (r->stream, 
190                                                  sizeof(bool_t));
191         *sr->elements[i]->fullQuery = 0;
192         sr->elements[i]->subqueryExpression = 
193             odr_malloc (r->stream, sizeof(Z_QueryExpression));
194         sr->elements[i]->subqueryExpression->which = 
195             Z_QueryExpression_term;
196         sr->elements[i]->subqueryExpression->u.term =
197             odr_malloc (r->stream, sizeof(Z_QueryExpressionTerm));
198         term = odr_malloc (r->stream, sizeof(Z_Term));
199         sr->elements[i]->subqueryExpression->u.term->queryTerm = term;
200         switch (type)
201         {
202         case Z_Term_characterString:
203             yaz_log (LOG_LOG, "term as characterString");
204             term->which = Z_Term_characterString;
205             term->u.characterString = odr_strdup (r->stream, outbuf);
206             break;
207         case Z_Term_general:
208             yaz_log (LOG_LOG, "term as general");
209             term->which = Z_Term_general;
210             term->u.general = odr_malloc (r->stream, sizeof(*term->u.general));
211             term->u.general->size = term->u.general->len = len;
212             term->u.general->buf = odr_malloc (r->stream, len);
213             memcpy (term->u.general->buf, outbuf, len);
214             break;
215         default:
216             term->which = Z_Term_general;
217             term->u.null = odr_nullval();
218         }
219         sr->elements[i]->subqueryExpression->u.term->termComment = 0;
220         sr->elements[i]->subqueryInterpretation = 0;
221         sr->elements[i]->subqueryRecommendation = 0;
222         sr->elements[i]->subqueryCount = odr_intdup (r->stream, count);
223         sr->elements[i]->subqueryWeight = 0;
224         sr->elements[i]->resultsByDB = 0;
225     }
226 }
227
228 int bend_search (void *handle, bend_search_rr *r)
229 {
230     ZebraHandle zh = (ZebraHandle) handle;
231
232     r->hits = 0;
233     r->errcode = 0;
234     r->errstring = NULL;
235     
236     if (zebra_select_databases (zh, r->num_bases,
237                                 (const char **) r->basenames))
238     {
239         zebra_result (zh, &r->errcode, &r->errstring);
240         return 0;
241     }
242     logf (LOG_LOG, "ResultSet '%s'", r->setname);
243     switch (r->query->which)
244     {
245     case Z_Query_type_1: case Z_Query_type_101:
246         zebra_search_rpn (zh, r->decode, r->stream, r->query->u.type_1,
247                           r->setname, &r->hits);
248         zebra_result (zh, &r->errcode, &r->errstring);
249         if (!r->errcode)
250             search_terms (zh, r);
251         break;
252     case Z_Query_type_2:
253         r->errcode = 107;
254         r->errstring = "type-2";
255         break;
256     default:
257         r->errcode = 107;
258     }
259     return 0;
260 }
261
262
263 int bend_fetch (void *handle, bend_fetch_rr *r)
264 {
265     ZebraHandle zh = (ZebraHandle) handle;
266     ZebraRetrievalRecord retrievalRecord;
267
268     retrievalRecord.position = r->number;
269     
270     r->last_in_set = 0;
271     zebra_records_retrieve (zh, r->stream, r->setname, r->comp,
272                             r->request_format, 1, &retrievalRecord);
273     zebra_result (zh, &r->errcode, &r->errstring);
274     /*  non Surrogate Diagnostic OR Surrogate Diagnostic */
275     if (r->errcode == 0 && retrievalRecord.errCode)
276     {
277         r->surrogate_flag = 1;
278         r->errcode = retrievalRecord.errCode;
279         r->errstring = retrievalRecord.errString;
280         r->basename = retrievalRecord.base;
281     }
282     else if (r->errcode == 0)        /* Database Record */
283     {
284         r->errcode = 0;
285         r->basename = retrievalRecord.base;
286         r->record = retrievalRecord.buf;
287         r->len = retrievalRecord.len;
288         r->output_format = retrievalRecord.format;
289     }
290     return 0;
291 }
292
293 static int bend_scan (void *handle, bend_scan_rr *r)
294 {
295     ZebraScanEntry *entries;
296     ZebraHandle zh = (ZebraHandle) handle;
297     int is_partial, i;
298
299     if (zebra_select_databases (zh, r->num_bases, 
300                                 (const char **) r->basenames))
301     {
302         zebra_result (zh, &r->errcode, &r->errstring);
303         return 0;
304     }
305     r->entries = (struct scan_entry *)
306         odr_malloc (r->stream, sizeof(*r->entries) * r->num_entries);
307     zebra_scan (zh, r->stream, r->term,
308                 r->attributeset,
309                 &r->term_position,
310                 &r->num_entries, &entries, &is_partial);
311     if (is_partial)
312         r->status = BEND_SCAN_PARTIAL;
313     else
314         r->status = BEND_SCAN_SUCCESS;
315     for (i = 0; i < r->num_entries; i++)
316     {
317         r->entries[i].term = entries[i].term;
318         r->entries[i].occurrences = entries[i].occurrences;
319     }
320     zebra_result (zh, &r->errcode, &r->errstring);
321     return 0;
322 }
323
324 void bend_close (void *handle)
325 {
326     zebra_close ((ZebraHandle) handle);
327     xmalloc_trav("bend_close");
328     nmem_print_list();
329 }
330
331 int bend_sort (void *handle, bend_sort_rr *rr)
332 {
333     ZebraHandle zh = (ZebraHandle) handle;
334
335     zebra_sort (zh, rr->stream,
336                 rr->num_input_setnames, (const char **) rr->input_setnames,
337                 rr->output_setname, rr->sort_sequence, &rr->sort_status);
338     zebra_result (zh, &rr->errcode, &rr->errstring);
339     return 0;
340 }
341
342 int bend_delete (void *handle, bend_delete_rr *rr)
343 {
344     ZebraHandle zh = (ZebraHandle) handle;
345
346     rr->delete_status = zebra_deleleResultSet(zh, rr->function,
347                                               rr->num_setnames, rr->setnames,
348                                               rr->statuses);
349     return 0;
350 }
351
352 static int es_admin_request (ZebraHandle zh, Z_AdminEsRequest *r)
353 {
354     switch (r->toKeep->which)
355     {
356     case Z_ESAdminOriginPartToKeep_reIndex:
357         yaz_log(LOG_LOG, "adm-reindex");
358         break;
359     case Z_ESAdminOriginPartToKeep_truncate:
360         yaz_log(LOG_LOG, "adm-truncate");
361         break;
362     case Z_ESAdminOriginPartToKeep_drop:
363         yaz_log(LOG_LOG, "adm-drop");
364         break;
365     case Z_ESAdminOriginPartToKeep_create:
366         yaz_log(LOG_LOG, "adm-create");
367         zebra_admin_create (zh, r->toKeep->databaseName);
368         break;
369     case Z_ESAdminOriginPartToKeep_import:
370         yaz_log(LOG_LOG, "adm-import");
371         zebra_admin_import_begin (zh, r->toKeep->databaseName);
372         break;
373     case Z_ESAdminOriginPartToKeep_refresh:
374         yaz_log(LOG_LOG, "adm-refresh");
375         break;
376     case Z_ESAdminOriginPartToKeep_commit:
377         yaz_log(LOG_LOG, "adm-commit");
378         break;
379     case Z_ESAdminOriginPartToKeep_shutdown:
380         yaz_log(LOG_LOG, "shutdown");
381         zebra_admin_shutdown(zh);
382         break;
383     case Z_ESAdminOriginPartToKeep_start:
384         yaz_log(LOG_LOG, "start");
385         zebra_admin_start(zh);
386         break;
387     default:
388         yaz_log(LOG_LOG, "unknown admin");
389     }
390     if (r->toKeep->databaseName)
391     {
392         yaz_log(LOG_LOG, "database %s", r->toKeep->databaseName);
393     }
394     return 0;
395 }
396
397 static int es_admin (ZebraHandle zh, Z_Admin *r)
398 {
399     switch (r->which)
400     {
401     case Z_Admin_esRequest:
402         es_admin_request (zh, r->u.esRequest);
403         break;
404     case Z_Admin_taskPackage:
405         yaz_log (LOG_LOG, "adm taskpackage (unhandled)");
406         break;
407     default:
408         break;
409     }
410
411     return 0;
412 }
413
414 int bend_segment (void *handle, bend_segment_rr *rr)
415 {
416     ZebraHandle zh = (ZebraHandle) handle;
417     Z_Segment *segment = rr->segment;
418
419     if (segment->num_segmentRecords)
420         zebra_admin_import_segment (zh, rr->segment);
421     else
422         zebra_admin_import_end (zh);
423     return 0;
424 }
425
426 int bend_esrequest (void *handle, bend_esrequest_rr *rr)
427 {
428     ZebraHandle zh = (ZebraHandle) handle;
429     
430     yaz_log(LOG_LOG, "function: %d", *rr->esr->function);
431     if (rr->esr->packageName)
432         yaz_log(LOG_LOG, "packagename: %s", rr->esr->packageName);
433     yaz_log(LOG_LOG, "Waitaction: %d", *rr->esr->waitAction);
434
435     if (!rr->esr->taskSpecificParameters)
436     {
437         yaz_log (LOG_WARN, "No task specific parameters");
438     }
439     else if (rr->esr->taskSpecificParameters->which == Z_External_ESAdmin)
440     {
441         es_admin (zh, rr->esr->taskSpecificParameters->u.adminService);
442
443         zebra_result (zh, &rr->errcode, &rr->errstring);
444     }
445     else if (rr->esr->taskSpecificParameters->which == Z_External_itemOrder)
446     {
447         Z_ItemOrder *it = rr->esr->taskSpecificParameters->u.itemOrder;
448         yaz_log (LOG_LOG, "Received ItemOrder");
449         switch (it->which)
450         {
451 #ifdef ASN_COMPILED
452         case Z_IOItemOrder_esRequest:
453 #else
454         case Z_ItemOrder_esRequest:
455 #endif
456         {
457             Z_IORequest *ir = it->u.esRequest;
458             Z_IOOriginPartToKeep *k = ir->toKeep;
459             Z_IOOriginPartNotToKeep *n = ir->notToKeep;
460             
461             if (k && k->contact)
462             {
463                 if (k->contact->name)
464                     yaz_log(LOG_LOG, "contact name %s", k->contact->name);
465                 if (k->contact->phone)
466                     yaz_log(LOG_LOG, "contact phone %s", k->contact->phone);
467                 if (k->contact->email)
468                     yaz_log(LOG_LOG, "contact email %s", k->contact->email);
469             }
470             if (k->addlBilling)
471             {
472                 yaz_log(LOG_LOG, "Billing info (not shown)");
473             }
474             
475             if (n->resultSetItem)
476             {
477                 yaz_log(LOG_LOG, "resultsetItem");
478                 yaz_log(LOG_LOG, "setId: %s", n->resultSetItem->resultSetId);
479                 yaz_log(LOG_LOG, "item: %d", *n->resultSetItem->item);
480             }
481 #ifdef ASN_COMPILED
482             if (n->itemRequest)
483             {
484                 Z_External *r = (Z_External*) n->itemRequest;
485                 ILL_ItemRequest *item_req = 0;
486                 ILL_Request *ill_req = 0;
487                 if (r->direct_reference)
488                 {
489                     oident *ent = oid_getentbyoid(r->direct_reference);
490                     if (ent)
491                         yaz_log(LOG_LOG, "OID %s", ent->desc);
492                     if (ent && ent->value == VAL_ISO_ILL_1)
493                     {
494                         yaz_log (LOG_LOG, "ItemRequest");
495                         if (r->which == ODR_EXTERNAL_single)
496                         {
497                             odr_setbuf(rr->decode,
498                                        r->u.single_ASN1_type->buf,
499                                        r->u.single_ASN1_type->len, 0);
500                             
501                             if (!ill_ItemRequest (rr->decode, &item_req, 0, 0))
502                             {
503                                 yaz_log (LOG_LOG,
504                                     "Couldn't decode ItemRequest %s near %d",
505                                        odr_errmsg(odr_geterror(rr->decode)),
506                                        odr_offset(rr->decode));
507                                 yaz_log(LOG_LOG, "PDU dump:");
508                                 odr_dumpBER(yaz_log_file(),
509                                      r->u.single_ASN1_type->buf,
510                                      r->u.single_ASN1_type->len);
511                             }
512                             if (rr->print)
513                             {
514                                 ill_ItemRequest (rr->print, &item_req, 0,
515                                     "ItemRequest");
516                                 odr_reset (rr->print);
517                             }
518                         }
519                         if (!item_req && r->which == ODR_EXTERNAL_single)
520                         {
521                             yaz_log (LOG_LOG, "ILLRequest");
522                             odr_setbuf(rr->decode,
523                                        r->u.single_ASN1_type->buf,
524                                        r->u.single_ASN1_type->len, 0);
525                             
526                             if (!ill_Request (rr->decode, &ill_req, 0, 0))
527                             {
528                                 yaz_log (LOG_LOG,
529                                     "Couldn't decode ILLRequest %s near %d",
530                                        odr_errmsg(odr_geterror(rr->decode)),
531                                        odr_offset(rr->decode));
532                                 yaz_log(LOG_LOG, "PDU dump:");
533                                 odr_dumpBER(yaz_log_file(),
534                                      r->u.single_ASN1_type->buf,
535                                      r->u.single_ASN1_type->len);
536                             }
537                             if (rr->print)
538                             {
539                                 ill_Request (rr->print, &ill_req, 0,
540                                     "ILLRequest");
541                                 odr_reset (rr->print);
542                             }
543                         }
544                     }
545                 }
546                 if (item_req)
547                 {
548                     yaz_log (LOG_LOG, "ILL protocol version = %d",
549                              *item_req->protocol_version_num);
550                 }
551             }
552 #endif
553         }
554         break;
555         }
556     }
557     else if (rr->esr->taskSpecificParameters->which == Z_External_update)
558     {
559         Z_IUUpdate *up = rr->esr->taskSpecificParameters->u.update;
560         yaz_log (LOG_LOG, "Received DB Update");
561         if (up->which == Z_IUUpdate_esRequest)
562         {
563             Z_IUUpdateEsRequest *esRequest = up->u.esRequest;
564             Z_IUOriginPartToKeep *toKeep = esRequest->toKeep;
565             Z_IUSuppliedRecords *notToKeep = esRequest->notToKeep;
566             
567             yaz_log (LOG_LOG, "action");
568             if (toKeep->action)
569             {
570                 switch (*toKeep->action)
571                 {
572                 case Z_IUOriginPartToKeep_recordInsert:
573                     yaz_log (LOG_LOG, "recordInsert");
574                     break;
575                 case Z_IUOriginPartToKeep_recordReplace:
576                     yaz_log (LOG_LOG, "recordUpdate");
577                     break;
578                 case Z_IUOriginPartToKeep_recordDelete:
579                     yaz_log (LOG_LOG, "recordDelete");
580                     break;
581                 case Z_IUOriginPartToKeep_elementUpdate:
582                     yaz_log (LOG_LOG, "elementUpdate");
583                     break;
584                 case Z_IUOriginPartToKeep_specialUpdate:
585                     yaz_log (LOG_LOG, "specialUpdate");
586                     break;
587                 case Z_ESAdminOriginPartToKeep_shutdown:
588                     yaz_log (LOG_LOG, "shutDown");
589                     break;
590                 case Z_ESAdminOriginPartToKeep_start:
591                     yaz_log (LOG_LOG, "start");
592                     break;
593                 default:
594                     yaz_log (LOG_LOG, " unknown (%d)", *toKeep->action);
595                 }
596             }
597             if (toKeep->databaseName)
598             {
599                 yaz_log (LOG_LOG, "database: %s", toKeep->databaseName);
600                 if (!strcmp(toKeep->databaseName, "fault"))
601                 {
602                     rr->errcode = 109;
603                     rr->errstring = toKeep->databaseName;
604                 }
605                 if (!strcmp(toKeep->databaseName, "accept"))
606                     rr->errcode = -1;
607             }
608             if (notToKeep)
609             {
610                 int i;
611                 for (i = 0; i < notToKeep->num; i++)
612                 {
613                     Z_External *rec = notToKeep->elements[i]->record;
614
615                     if (rec->direct_reference)
616                     {
617                         struct oident *oident;
618                         oident = oid_getentbyoid(rec->direct_reference);
619                         if (oident)
620                             yaz_log (LOG_LOG, "record %d type %s", i,
621                                      oident->desc);
622                     }
623                     switch (rec->which)
624                     {
625                     case Z_External_sutrs:
626                         if (rec->u.octet_aligned->len > 170)
627                             yaz_log (LOG_LOG, "%d bytes:\n%.168s ...",
628                                      rec->u.sutrs->len,
629                                      rec->u.sutrs->buf);
630                         else
631                             yaz_log (LOG_LOG, "%d bytes:\n%s",
632                                      rec->u.sutrs->len,
633                                      rec->u.sutrs->buf);
634                         break;
635                     case Z_External_octet:
636                         if (rec->u.octet_aligned->len > 170)
637                             yaz_log (LOG_LOG, "%d bytes:\n%.168s ...",
638                                      rec->u.octet_aligned->len,
639                                      rec->u.octet_aligned->buf);
640                         else
641                             yaz_log (LOG_LOG, "%d bytes\n%s",
642                                      rec->u.octet_aligned->len,
643                                      rec->u.octet_aligned->buf);
644                     }
645                 }
646             }
647         }
648     }
649     else
650     {
651         yaz_log (LOG_WARN, "Unknown Extended Service(%d)",
652                  rr->esr->taskSpecificParameters->which);
653         
654     }
655     return 0;
656 }
657
658 static void bend_start (struct statserv_options_block *sob)
659 {
660 #ifdef WIN32
661     
662 #else
663     if (!sob->inetd) 
664     {
665         char *pidfile = "zebrasrv.pid";
666         int fd = creat (pidfile, 0666);
667         if (fd == -1)
668             logf (LOG_WARN|LOG_ERRNO, "creat %s", pidfile);
669         else
670         {
671             char pidstr[30];
672         
673             sprintf (pidstr, "%ld", (long) getpid ());
674             write (fd, pidstr, strlen(pidstr));
675             close (fd);
676         }
677     }
678 #endif
679     if (sob->handle)
680         zebra_stop((ZebraService) sob->handle);
681     sob->handle = zebra_start(sob->configname);
682 }
683
684 static void bend_stop(struct statserv_options_block *sob)
685 {
686 #ifdef WIN32
687
688 #else
689     if (!sob->inetd) 
690         unlink ("zebrasrv.pid");
691 #endif
692     if (sob->handle)
693     {
694         ZebraService service = sob->handle;
695         zebra_stop(service);
696     }
697 }
698
699 int main (int argc, char **argv)
700 {
701     struct statserv_options_block *sob;
702
703     sob = statserv_getcontrol ();
704     strcpy (sob->configname, "zebra.cfg");
705     sob->bend_start = bend_start;
706     sob->bend_stop = bend_stop;
707
708     statserv_setcontrol (sob);
709
710     return statserv_main (argc, argv, bend_init, bend_close);
711 }