]> andersk Git - moira.git/blob - gdb/gdb_fserv.c
7275b4ef50d15830ff35df2c434c3a0012ae9894
[moira.git] / gdb / gdb_fserv.c
1 /*
2  * $Header$
3  */
4
5 #ifndef lint
6 static char *rcsid_gdb_fserv_c = "$Header$";
7 #endif
8
9
10 /************************************************************************
11  *      
12  *                         gdb_fserv.c
13  *      
14  *            GDB - Routines to implement forking servers.
15  *      
16  *      Author: Noah Mendelsohn
17  *      Copyright: 1986 MIT Project Athena 
18  *              For copying and distribution information, please see
19  *              the file <mit-copyright.h>.
20  *      
21  ************************************************************************/
22
23 #include <mit-copyright.h>
24 #include <stdio.h>
25 #include <sys/types.h>
26 #include <sys/uio.h>
27 #include <sys/socket.h>
28 #include <sys/wait.h>
29 #include <sys/signal.h>
30 #include "gdb.h"
31 #include <sys/resource.h>
32 #ifdef POSIX
33 #include <unistd.h>
34 #endif
35
36
37 /************************************************************************
38  *      
39  *                      create_forking_server (create_forking_server)
40  *      
41  *      Called by an application to turn itself into a forking model
42  *      server.  Returns from this routine occur only in the forked
43  *      children.  The parent lives in this routine forever, waiting
44  *      for incoming connection requests and doing the appropriate
45  *      forking.
46  *      
47  *      Children are expected to do their own cleanup, but this routine
48  *      does do the work of reaping the resulting zombie processes.
49  *      
50  *      ARGUMENTS:
51  *      ----------
52  *      
53  *              service-id      identifies the port to be used for
54  *                              listening.  Same rules as for
55  *                              create_listening_connection.
56  *      
57  *              validate-rtn    pointer to a function to be called to
58  *                              validate the incoming client.  Should
59  *                              return TRUE if client is acceptable,
60  *                              else false.  If this is NULL, all clients
61  *                              are accepted.
62  *      
63  *      GLOBAL VARIABLES
64  *      ----------------
65  *      
66  *      Children created by this routine inherit the global variables
67  *      gdb_sockaddr_of_client, which is of type sockaddr_in and 
68  *      gdb_socklen, which is the returned length of the sockaddr.
69  *      These are the Berkeley identifiers of the clients as accepted.
70  *      Use of this interface is non-portable to other than Berkeley 
71  *      systems.
72  *      
73  *      The client's request tuple may be found in gdb_client_tuple.
74  *      
75  ************************************************************************/
76
77
78 CONNECTION
79 create_forking_server(service, validate)
80 char *service;
81 int (*validate)();
82 {
83         void start_accepting_client();
84         CONNECTION incoming;                    /* listen for incoming */
85                                                 /* children here */
86         CONNECTION client = NULL;               /* connection to client */
87                                                 /* is created here */
88         OPERATION listenop;                     /* used to asynchronously */
89                                                 /* listen for a child */
90                                                 /* connection request */
91         GDB_INIT_CHECK
92
93         /*----------------------------------------------------------*/
94         /*      
95         /*      Set up parent execution environment
96         /*      
97         /*----------------------------------------------------------*/
98
99         g_do_signals();                         /* set up signal handling */
100
101         incoming = create_listening_connection(service);
102         if (incoming == NULL || connection_status(incoming) != CON_UP)
103                 GDB_GIVEUP("create_forking_server: can't create listening connection")
104
105         /*----------------------------------------------------------*/
106         /*      
107         /*      Repeatedly listen for incoming
108         /*      
109         /*----------------------------------------------------------*/
110
111         listenop = create_operation();
112         while (TRUE) {
113                 gdb_socklen = sizeof(gdb_sockaddr_of_client);
114                 client = NULL;
115                 (void) start_accepting_client(incoming, listenop, &client, 
116                                        gdb_sockaddr_of_client, &gdb_socklen,
117                                        &gdb_client_tuple);
118                 if(complete_operation(listenop) != OP_COMPLETE ||
119                    client == NULL) {
120                     gdb_perror("GDB create_forking_server: failed to accept client");
121                     reset_operation(listenop);
122                     (void) sever_connection(client);
123                     continue;
124                   }
125                 
126
127                 /*
128                  * Call the validate routine, if it fails, 
129                  * refuse the client.
130                  */
131                 if (validate != NULL && !(*validate)()) {
132                         reset_operation(listenop);
133                         start_replying_to_client(listenop, client, 
134                                                  GDB_REFUSED, "","");
135                         (void) complete_operation(listenop); 
136                         reset_operation(listenop);
137                         (void) sever_connection(client);
138                         continue;                       
139                 }
140                 /*
141                  * Create  the child for this client
142                  */
143                 if ((gdb_Debug & GDB_NOFORK) || fork() == 0) {
144                        /*
145                         * This is the child, or we're in noforking
146                         * debug mode.
147                         */
148                         reset_operation(listenop);
149                         start_replying_to_client(listenop, client, 
150                                                  GDB_ACCEPTED, "","");
151                         if (complete_operation(listenop) != OP_COMPLETE) 
152                                 exit(8);
153                         return client;          /* return to application */
154                                                 /* program */
155                 }
156                /*
157                 * Still in the parent
158                 */
159                 (void) sever_connection(client);
160                 reset_operation(listenop);
161         }
162 }
163 \f
164 /************************************************************************/
165 /*      
166 /*                              gdb_reaper
167 /*      
168 /*      Called on SIGCHILD to reap all dead children.
169 /*      
170 /************************************************************************/
171 #ifndef POSIX
172 int
173 #else
174 void
175 #endif
176 gdb_reaper()
177 {
178 #ifdef POSIX
179         int status;
180 #else
181         union wait status;
182 #endif
183        
184 #ifdef POSIX
185         while (waitpid(-1, &status, WNOHANG) >0);
186 #else
187         while (wait3(&status, WNOHANG, (struct rusage *)0) >0);
188 #endif
189 }
190 \f
191 /************************************************************************/
192 /*      
193 /*                              g_do_signals
194 /*      
195 /*      Set up signal handling for a forking server.
196 /*      
197 /************************************************************************/
198
199 int
200 g_do_signals()
201 {
202 #ifdef POSIX
203     struct sigaction act;
204
205     act.sa_handler = gdb_reaper;
206     sigemptyset(&act.sa_mask);
207     act.sa_flags = 0;
208     (void) sigaction(SIGCHLD, &act, (struct sigaction *)0);
209 #else /* sun */
210     (void) signal(SIGCHLD, gdb_reaper);
211 #endif 
212 }
This page took 0.041091 seconds and 3 git commands to generate.