]> andersk Git - moira.git/blob - server/mr_scall.c
close file descriptors before exec'ing the dcm
[moira.git] / server / mr_scall.c
1 /*
2  *      $Source$
3  *      $Author$
4  *      $Header$
5  *
6  *      Copyright (C) 1987 by the Massachusetts Institute of Technology
7  *      For copying and distribution information, please see the file
8  *      <mit-copyright.h>.
9  *
10  */
11
12 #ifndef lint
13 static char *rcsid_sms_scall_c = "$Header$";
14 #endif lint
15
16 #include <mit-copyright.h>
17 #include <krb.h>
18 #include <errno.h>
19 #include "query.h"
20 #include "sms_server.h"
21 extern char buf1[];
22 extern int nclients;
23 extern char *whoami;
24 extern char *malloc();
25 extern int errno;
26
27 extern void clist_delete(), do_auth(), do_shutdown();
28 void do_call();
29
30 /*
31  * Welcome to the (finite state) machine (highest level).
32  */
33 void
34 do_client(cp)
35         client *cp;
36 {
37         free_rtn_tuples(cp);
38         if (OP_STATUS(cp->pending_op) == OP_CANCELLED) {
39                 com_err(whoami, 0, "Closed connection (now %d client%s, %d new queries, %d old)",
40                         nclients-1,
41                         nclients!=2?"s":"",
42                         newqueries,
43                         oldqueries);
44                 clist_delete(cp);
45                 return;
46         }
47         switch (cp->action) {
48         case CL_ACCEPT:
49         case CL_SEND:
50                 /* Start recieving next request */
51                 initialize_operation(cp->pending_op, sms_start_recv,
52                                      (char *)&cp->args, (int (*)())NULL);
53                 queue_operation(cp->con, CON_INPUT, cp->pending_op);
54                 cp->action = CL_RECEIVE;
55                 break;
56         case CL_RECEIVE:
57                 /* Data is here. Process it & start it heading back */
58                 do_call(cp); /* This may block for a while. */
59                 sms_destroy_reply(cp->args);
60                 cp->args = NULL;
61                 initialize_operation(cp->pending_op, sms_start_send,
62                                      (char *)&cp->reply, (int (*)())NULL);
63                 queue_operation(cp->con, CON_OUTPUT, cp->pending_op);
64                 cp->action = CL_SEND;
65                 break;
66         }
67 }               
68
69 char *procnames[] = {
70          "noop",
71          "auth",
72          "shutdown",
73          "query",
74          "access",
75 };
76
77
78 void
79 do_call(cl)
80         client *cl;
81 {
82         int pn;
83         cl->reply.sms_argc = 0;
84         cl->reply.sms_status = 0;
85         cl->reply.sms_version_no = cl->args->sms_version_no;
86         if (((pn = cl->args->sms_procno) < 0) ||
87             (pn > SMS_MAX_PROC)) {
88                 com_err(whoami, 0, "procno out of range");
89                 cl->reply.sms_status = SMS_UNKNOWN_PROC;
90                 return;
91         }
92         if (log_flags & LOG_ARGS)
93                 log_args(procnames[pn], cl->args->sms_version_no,
94                          cl->args->sms_argc, cl->args->sms_argv);
95         else if (log_flags & LOG_REQUESTS)
96                 com_err(whoami, 0, "%s", procnames[pn]);
97
98         switch(pn) {
99         case SMS_NOOP:
100                 cl->reply.sms_status = 0;
101                 return;
102
103         case SMS_AUTH:
104                 do_auth(cl);
105                 return;
106
107         case SMS_QUERY:
108                 do_retr(cl);
109                 return;
110
111         case SMS_ACCESS:
112                 do_access(cl);
113                 return;
114                 
115         case SMS_SHUTDOWN:
116                 do_shutdown(cl);
117                 return;
118
119         case SMS_DO_UPDATE:
120                 trigger_dcm(0, 0, cl);
121                 return;
122         }
123 }
124
125 free_rtn_tuples(cp)
126         client *cp;
127 {
128         register returned_tuples *temp;
129         for (temp=cp->first; temp && OP_DONE(temp->op); ) {
130                 register returned_tuples *t1=temp;
131                 temp = t1->next;
132                 if (t1 == cp->last) cp->last = NULL;
133
134                 sms_destroy_reply(t1->retval);
135                 delete_operation(t1->op);
136                 free(t1);
137         }
138         cp->first = temp;
139 }       
140
141 retr_callback(argc, argv, p_cp)
142         register int argc;
143         register char **argv;
144         char *p_cp;
145 {
146         register client *cp = (client *)p_cp;
147         /*
148          * This takes too much advantage of the fact that
149          * serialization of the data happens during the queue operation.
150          */
151         sms_params *arg_tmp = (sms_params *)db_alloc(sizeof(sms_params));
152         returned_tuples *tp = (returned_tuples *)
153                 db_alloc(sizeof(returned_tuples));
154         register char **nargv = (char **)malloc(argc * sizeof(char *));
155         register int i;
156         
157         OPERATION op_tmp = create_operation();
158
159         if (sms_trim_args(argc, argv) == SMS_NO_MEM) {
160             com_err(whoami, SMS_NO_MEM, "while trimming args");
161         }
162         if (log_flags & LOG_RESP)
163                 log_args("return: ", cp->args->sms_version_no, argc, argv);
164
165         tp->op = op_tmp;
166         tp->retval = arg_tmp;
167         tp->next = NULL;
168         
169         arg_tmp->sms_status = SMS_MORE_DATA;
170         arg_tmp->sms_version_no = cp->args->sms_version_no;
171         arg_tmp->sms_argc = argc;
172         arg_tmp->sms_argv = nargv;
173         for (i = 0; i < argc; i++) {
174                 register int len = strlen(argv[i]) + 1;
175                 nargv[i] = malloc(len);
176                 bcopy(argv[i], nargv[i], len);
177         }
178         arg_tmp->sms_flattened = (char *)NULL;
179         arg_tmp->sms_argl = (int *)NULL;
180
181         if (cp->last) {
182                 cp->last->next = tp;
183                 cp->last = tp;
184         } else {
185                 cp->last = cp->first = tp;
186         }
187         
188         reset_operation(op_tmp);
189         initialize_operation(op_tmp, sms_start_send, (char *)arg_tmp,
190                              (int (*)())NULL);
191         queue_operation(cp->con, CON_OUTPUT, op_tmp);
192 }
193
194 list_users(callbk, callarg)
195         int (*callbk)();
196         char *callarg;
197 {
198         char *argv[6];
199         char buf[30];
200         char buf1[30];
201         int i;
202         extern client **clients;
203         extern char *inet_ntoa();
204         char *cp;
205         char *index();
206         char *ctime();
207
208         for (i = 0; i < nclients; i++) {
209                 register client *cl = clients[i];
210                 if (cl->clname) 
211                         argv[0] = cl->clname;
212                 else argv[0] = "unauthenticated";
213                 
214                 argv[1] = inet_ntoa(cl->haddr.sin_addr);
215                 argv[2] = buf;
216                 sprintf(buf, "port %d", ntohs(cl->haddr.sin_port));
217                 argv[3] = ctime(&cl->last_time_used);
218                 cp = index(argv[3], '\n');
219                 if (cp) *cp = '\0';
220                 argv[4] = buf1;
221                 sprintf(buf1, "[#%d]", cl->id);
222                 (*callbk)(5, argv, callarg);
223         }
224         return 0;
225 }
226
227 do_retr(cl)
228         register client *cl;
229 {
230         register char *queryname;
231
232         cl->reply.sms_argc = 0;
233         cl->reply.sms_status = 0;
234
235         queryname = cl->args->sms_argv[0];
236         
237         if (cl->args->sms_version_no == SMS_VERSION_2)
238           newqueries++;
239         else
240           oldqueries++;
241
242         if (strcmp(queryname, "_list_users") == 0)
243                 cl->reply.sms_status = list_users(retr_callback, (char *)cl);
244         else {
245                 cl->reply.sms_status = 
246                         sms_process_query(cl,
247                                           cl->args->sms_argv[0],
248                                           cl->args->sms_argc-1,
249                                           cl->args->sms_argv+1,
250                                           retr_callback,
251                                           (char *)cl);
252         }
253         if (log_flags & LOG_RES)
254                 com_err(whoami, 0, "Query complete.");
255 }
256
257 do_access(cl)
258         client *cl;
259 {
260         cl->reply.sms_argc = 0;
261
262         cl->reply.sms_status = 
263           sms_check_access(cl,
264                            cl->args->sms_argv[0],
265                            cl->args->sms_argc-1,
266                            cl->args->sms_argv+1);
267         
268         com_err(whoami, 0, "Access check complete.");
269 }
270
271
272 /* trigger_dcm is also used as a followup routine to the 
273  * set_server_host_override query, hence the two dummy arguments.
274  */
275
276 struct query pseudo_query = {
277         "trigger_dcm",
278         "tdcm",
279 };
280
281 trigger_dcm(dummy0, dummy1, cl)
282         int dummy0, dummy1;
283         client *cl;
284 {
285         register int pid;
286         
287         cl->reply.sms_argc = 0;
288
289         if (cl->reply.sms_status = check_query_access(&pseudo_query, 0, cl) )
290                 return(cl->reply.sms_status);
291
292         pid = vfork();
293         switch (pid) {
294         case 0:
295                 for (dummy0 = getdtablesize() - 1; dummy0 > 2; dummy0--)
296                   close(dummy0);
297                 execl("/u1/sms/bin/startdcm", "startdcm", 0);
298                 exit(1);
299                 
300         case -1:
301                 cl->reply.sms_status = errno;
302                 return(0);
303
304         default:
305                 return(0);
306         }
307 }
308
This page took 0.540244 seconds and 5 git commands to generate.