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