Partitioned server.
[yaz-moved-to-github.git] / server / statserv.c
1 /*
2  * Copyright (C) 1994, Index Data I/S 
3  * All rights reserved.
4  * Sebastian Hammer, Adam Dickmeiss
5  *
6  * $Log: statserv.c,v $
7  * Revision 1.7  1995-03-16 13:29:04  quinn
8  * Partitioned server.
9  *
10  * Revision 1.6  1995/03/15  15:18:52  quinn
11  * Little changes to better support nonblocking I/O
12  * Added backend.h
13  *
14  * Revision 1.5  1995/03/15  08:37:45  quinn
15  * Now we're pretty much set for nonblocking I/O.
16  *
17  * Revision 1.4  1995/03/14  16:59:48  quinn
18  * Bug-fixes
19  *
20  * Revision 1.3  1995/03/14  11:30:15  quinn
21  * Works better now.
22  *
23  * Revision 1.2  1995/03/14  10:28:03  quinn
24  * More work on demo server.
25  *
26  * Revision 1.1  1995/03/10  18:22:45  quinn
27  * The rudiments of an asynchronous server.
28  *
29  */
30
31 /*
32  * Simple, static server. I wouldn't advise a static server unless you
33  * really have to, but it's great for debugging memory management.  :)
34  */
35
36 #include <stdio.h>
37
38 #include <options.h>
39 #include <eventl.h>
40 #include <session.h>
41 #include <eventl.h>
42 #include <comstack.h>
43 #include <tcpip.h>
44 #include <xmosi.h>
45
46 #include <unistd.h>
47 #include <fcntl.h>
48
49 static char *me = "";
50
51 #define DEFAULT_LISTENER "tcp:localhost:9999"
52
53 /*
54  * handle incoming connect requests.
55  */
56 void listener(IOCHAN h, int event)
57 {
58     COMSTACK line = (COMSTACK) iochan_getdata(h);
59     association *newas;
60
61     if (event == EVENT_INPUT)
62     {
63         if (cs_listen(line, 0, 0) < 0)
64         {
65             if (cs_errno(line) == CSNODATA)
66                 return;
67             fprintf(stderr, "cs_listen failed.\n");
68             exit(1);
69         }
70         iochan_setevent(h, EVENT_OUTPUT);
71         iochan_setflags(h, EVENT_OUTPUT | EVENT_EXCEPT); /* set up for acpt */
72     }
73     else if (event == EVENT_OUTPUT)
74     {
75         COMSTACK new_line;
76         IOCHAN new_chan;
77
78         if (!(new_line = cs_accept(line)))
79         {
80             fprintf(stderr, "Accept failed.\n");
81             exit(1);
82         }
83         if (!(new_chan = iochan_create(cs_fileno(new_line), ir_session,
84             EVENT_INPUT)))
85         {
86             fprintf(stderr, "Failed to create iochan\n");
87             exit(1);
88         }
89         if (!(newas = create_association(new_chan, new_line)))
90         {
91             fprintf(stderr, "Failed to create new assoc.\n");
92             exit(1);
93         }
94         iochan_setdata(new_chan, newas);
95         iochan_setflags(h, EVENT_INPUT | EVENT_EXCEPT); /* reset for listen */
96     }
97     else
98     {
99         fprintf(stderr, "Bad event on listener.\n");
100         exit(1);
101     }
102 }
103
104 /*
105  * Set up a listening endpoint, and give it to the event-handler.
106  */
107 void add_listener(char *where)
108 {
109     COMSTACK l;
110     CS_TYPE type;
111     char mode[100], addr[100];
112     void *ap;
113     IOCHAN lst;
114
115     fprintf(stderr, "Adding listener on %s\n", where);
116     if (!where || sscanf(where, "%[^:]:%s", mode, addr) != 2)
117     {
118         fprintf(stderr, "%s: Address format: ('tcp'|'osi')':'<address>.\n",
119             me);
120         exit(1);
121     }
122     if (!strcmp(mode, "tcp"))
123     {
124         if (!(ap = tcpip_strtoaddr(addr)))
125         {
126             fprintf(stderr, "Address resolution failed for TCP.\n");
127             exit(1);
128         }
129         type = tcpip_type;
130     }
131 #if 0
132     else if (!strcmp(mode, "osi"))
133     {
134         if (!(ap = mosi_strtoaddr(addr)))
135         {
136             fprintf(stderr, "Address resolution failed for TCP.\n");
137             exit(1);
138         }
139         type = mosi_type;
140     }
141 #endif
142     else
143     {
144         fprintf(stderr, "You must specify either 'osi:' or 'tcp:'.\n");
145         exit(1);
146     }
147     if (!(l = cs_create(type, 0)))
148     {
149         fprintf(stderr, "Failed to create listener\n");
150         exit(1);
151     }
152     if (cs_bind(l, ap, CS_SERVER) < 0)
153     {
154         fprintf(stderr, "Failed to bind.\n");
155         perror(where);
156         exit(1);
157     }
158     if (!(lst = iochan_create(cs_fileno(l), listener, EVENT_INPUT |
159          EVENT_EXCEPT)))
160     {
161         fprintf(stderr, "Failed to create IOCHAN-type\n");
162         exit(1);
163     }
164     iochan_setdata(lst, l);
165 }
166
167 int statserv_main(int argc, char **argv)
168 {
169     int ret, listeners = 0;
170     char *arg;
171
172     me = argv[0];
173     while ((ret = options("l:", argv, argc, &arg)) != -2)
174         switch (ret)
175         {
176             case 0: me = arg; break;
177             case 'l': add_listener(arg); listeners++; break;
178             default:
179                 fprintf(stderr, "Usage: %s [-l <listener-addr>]\n", me);
180                 exit(1);
181         }
182     if (!listeners)
183         add_listener(DEFAULT_LISTENER);
184     return event_loop();
185 }