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