]> andersk Git - moira.git/blob - server/mr_scall.c
Fixes to build with `gcc' instead of `gcc -traditional' on suns. (Needed
[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 <sys/types.h>
18 #include <sys/stat.h>
19 #include <sys/file.h>
20 #include <fcntl.h>
21 #include <string.h>
22 #include <netinet/in.h>
23 #include <arpa/inet.h>
24 #include <krb.h>
25 #include <errno.h>
26 #include "mr_server.h"
27 #include "query.h"
28 extern char buf1[];
29 extern int nclients;
30 extern char *whoami;
31 extern int errno;
32
33 extern void clist_delete(), do_auth(), do_shutdown();
34 void do_call();
35 extern int dbms_errno, mr_errcode;
36 static int row_count;
37
38 /* Put this in a variable so that we can patch it if necessary */
39 int max_row_count = 4096;
40
41 /*
42  * Welcome to the (finite state) machine (highest level).
43  */
44 void
45 do_client(cp)
46         client *cp;
47 {
48         struct stat stbuf;
49
50         free_rtn_tuples(cp);
51         if (OP_STATUS(cp->pending_op) == OP_CANCELLED) {
52                 com_err(whoami, 0, "Closed connection (now %d client%s, %d new queries, %d old)",
53                         nclients-1,
54                         nclients!=2?"s":"",
55                         newqueries,
56                         oldqueries);
57                 clist_delete(cp);
58                 /* if we no longer have any clients, and we're supposed to
59                  * go down, then go down now.
60                  */
61                 if ((dormant == AWAKE) && (nclients == 0) &&
62                     (stat(MOIRA_MOTD_FILE, &stbuf) == 0)) {
63                     com_err(whoami, 0, "motd file exists, slumbertime");
64                     dormant = SLEEPY;
65                 }
66                 return;
67         }
68         switch (cp->action) {
69         case CL_ACCEPT:
70         case CL_SEND:
71                 /* Start recieving next request */
72                 initialize_operation(cp->pending_op, mr_start_recv,
73                                      (char *)&cp->args, (int (*)())NULL);
74                 queue_operation(cp->con, CON_INPUT, cp->pending_op);
75                 cp->action = CL_RECEIVE;
76                 break;
77         case CL_RECEIVE:
78                 /* Data is here. Process it & start it heading back */
79                 do_call(cp); /* This may block for a while. */
80                 mr_destroy_reply(cp->args);
81                 cp->args = NULL;
82                 initialize_operation(cp->pending_op, mr_start_send,
83                                      (char *)&cp->reply, (int (*)())NULL);
84                 queue_operation(cp->con, CON_OUTPUT, cp->pending_op);
85                 cp->action = CL_SEND;
86                 break;
87         }
88 }               
89
90 char *procnames[] = {
91          "noop",
92          "auth",
93          "shutdown",
94          "query",
95          "access",
96          "dcm",
97          "motd",
98 };
99
100
101 void
102 do_call(cl)
103         client *cl;
104 {
105         int pn;
106         cl->reply.mr_argc = 0;
107         cl->reply.mr_status = 0;
108         cl->reply.mr_version_no = cl->args->mr_version_no;
109         if (((pn = cl->args->mr_procno) < 0) ||
110             (pn > MR_MAX_PROC)) {
111                 com_err(whoami, 0, "procno out of range");
112                 cl->reply.mr_status = MR_UNKNOWN_PROC;
113                 return;
114         }
115         if (log_flags & LOG_ARGS)
116                 log_args(procnames[pn], cl->args->mr_version_no,
117                          cl->args->mr_argc, cl->args->mr_argv);
118         else if (log_flags & LOG_REQUESTS)
119                 com_err(whoami, 0, "%s", procnames[pn]);
120
121         if ((dormant == ASLEEP || dormant == GROGGY) &&
122             pn != MR_NOOP && pn != MR_MOTD) {
123             cl->reply.mr_status = MR_DOWN;
124             if (log_flags & LOG_RES)
125               com_err(whoami, MR_DOWN, "(query refused)");
126             return;
127         }
128
129         /* make sure this gets cleared before every operation */
130         dbms_errno = 0;
131
132         switch(pn) {
133         case MR_NOOP:
134                 cl->reply.mr_status = 0;
135                 return;
136
137         case MR_AUTH:
138                 do_auth(cl);
139                 return;
140
141         case MR_QUERY:
142                 do_retr(cl);
143                 return;
144
145         case MR_ACCESS:
146                 do_access(cl);
147                 return;
148                 
149         case MR_SHUTDOWN:
150                 do_shutdown(cl);
151                 return;
152
153         case MR_DO_UPDATE:
154                 trigger_dcm(0, 0, cl);
155                 return;
156
157         case MR_MOTD:
158                 get_motd(cl);
159                 return;
160         }
161 }
162
163 free_rtn_tuples(cp)
164         client *cp;
165 {
166         register returned_tuples *temp;
167         for (temp=cp->first; temp && OP_DONE(temp->op); ) {
168                 register returned_tuples *t1=temp;
169                 temp = t1->next;
170                 if (t1 == cp->last) cp->last = NULL;
171
172                 mr_destroy_reply(t1->retval);
173                 delete_operation(t1->op);
174                 free(t1);
175         }
176         cp->first = temp;
177 }       
178
179 retr_callback(argc, argv, p_cp)
180         register int argc;
181         register char **argv;
182         char *p_cp;
183 {
184         register client *cp = (client *)p_cp;
185         mr_params *arg_tmp;
186         returned_tuples *tp;
187         OPERATION op_tmp;
188         register char **nargv;
189         register int i;
190
191         if (row_count++ >= max_row_count) {
192             dbms_errno = mr_errcode = MR_NO_MEM;
193             return;
194         }
195
196         /*
197          * This takes too much advantage of the fact that
198          * serialization of the data happens during the queue operation.
199          */
200         arg_tmp = (mr_params *)db_alloc(sizeof(mr_params));
201         tp = (returned_tuples *)db_alloc(sizeof(returned_tuples));
202         nargv = (char **)malloc(argc * sizeof(char *));
203         
204         op_tmp = create_operation();
205
206         if (mr_trim_args(argc, argv) == MR_NO_MEM) {
207             com_err(whoami, MR_NO_MEM, "while trimming args");
208         }
209         if (log_flags & LOG_RESP)
210                 log_args("return: ", cp->args->mr_version_no, argc, argv);
211
212         tp->op = op_tmp;
213         tp->retval = arg_tmp;
214         tp->next = NULL;
215         
216         arg_tmp->mr_status = MR_MORE_DATA;
217         arg_tmp->mr_version_no = cp->args->mr_version_no;
218         arg_tmp->mr_argc = argc;
219         arg_tmp->mr_argv = nargv;
220         for (i = 0; i < argc; i++) {
221                 register int len = strlen(argv[i]) + 1;
222                 nargv[i] = malloc(len);
223                 memcpy(nargv[i], argv[i], len);
224         }
225         arg_tmp->mr_flattened = (char *)NULL;
226         arg_tmp->mr_argl = (int *)NULL;
227
228         if (cp->last) {
229                 cp->last->next = tp;
230                 cp->last = tp;
231         } else {
232                 cp->last = cp->first = tp;
233         }
234         
235         reset_operation(op_tmp);
236         initialize_operation(op_tmp, mr_start_send, (char *)arg_tmp,
237                              (int (*)())NULL);
238         queue_operation(cp->con, CON_OUTPUT, op_tmp);
239 }
240
241 list_users(callbk, callarg)
242         int (*callbk)();
243         char *callarg;
244 {
245         char *argv[6];
246         char buf[30];
247         char buf1[30];
248         int i;
249         extern client **clients;
250         char *cp;
251         char *ctime();
252
253         for (i = 0; i < nclients; i++) {
254                 register client *cl = clients[i];
255                 if (cl->clname) 
256                         argv[0] = cl->clname;
257                 else argv[0] = "unauthenticated";
258                 
259                 argv[1] = inet_ntoa(cl->haddr.sin_addr);
260                 argv[2] = buf;
261                 sprintf(buf, "port %d", ntohs(cl->haddr.sin_port));
262                 argv[3] = ctime(&cl->last_time_used);
263                 cp = strchr(argv[3], '\n');
264                 if (cp) *cp = '\0';
265                 argv[4] = buf1;
266                 sprintf(buf1, "[#%d]", cl->id);
267                 (*callbk)(5, argv, callarg);
268         }
269         return 0;
270 }
271
272 do_retr(cl)
273         register client *cl;
274 {
275         register char *queryname;
276
277         cl->reply.mr_argc = 0;
278         cl->reply.mr_status = 0;
279         row_count = 0;
280
281         if (cl->args->mr_argc < 1) {
282             cl->reply.mr_status = MR_ARGS;
283             com_err(whoami, MR_ARGS, "got nameless query");
284             return;
285         }
286         queryname = cl->args->mr_argv[0];
287         
288         if (cl->args->mr_version_no == MR_VERSION_2)
289           newqueries++;
290         else
291           oldqueries++;
292
293         if (strcmp(queryname, "_list_users") == 0)
294                 cl->reply.mr_status = list_users(retr_callback, (char *)cl);
295         else {
296                 cl->reply.mr_status = 
297                         mr_process_query(cl,
298                                           queryname,
299                                           cl->args->mr_argc-1,
300                                           cl->args->mr_argv+1,
301                                           retr_callback,
302                                           (char *)cl);
303         }
304         if (row_count >= max_row_count) {
305             critical_alert("moirad", "attempted query %s with %d rows\n",
306                            queryname, row_count);
307         }
308
309         if (log_flags & LOG_RES)
310                 com_err(whoami, 0, "Query complete.");
311 }
312
313 do_access(cl)
314         client *cl;
315 {
316         if (cl->args->mr_argc < 1) {
317             cl->reply.mr_status = MR_ARGS;
318             com_err(whoami, MR_ARGS, "got nameless access");
319             return;
320         }
321         cl->reply.mr_argc = 0;
322
323         cl->reply.mr_status = 
324           mr_check_access(cl,
325                            cl->args->mr_argv[0],
326                            cl->args->mr_argc-1,
327                            cl->args->mr_argv+1);
328         
329         com_err(whoami, 0, "Access check complete.");
330 }
331
332
333 /* trigger_dcm is also used as a followup routine to the 
334  * set_server_host_override query, hence the two dummy arguments.
335  */
336
337 struct query pseudo_query = {
338         "trigger_dcm",
339         "tdcm",
340 };
341
342 trigger_dcm(dummy0, dummy1, cl)
343         int dummy0, dummy1;
344         client *cl;
345 {
346         register int pid;
347         char prog[128];
348
349         cl->reply.mr_argc = 0;
350
351         if (cl->reply.mr_status = check_query_access(&pseudo_query, 0, cl) )
352                 return(cl->reply.mr_status);
353
354         sprintf(prog, "%s/startdcm", BIN_DIR);
355         pid = vfork();
356         switch (pid) {
357         case 0:
358                 execl(prog, "startdcm", 0);
359                 exit(1);
360                 
361         case -1:
362                 cl->reply.mr_status = errno;
363                 return(0);
364
365         default:
366                 return(0);
367         }
368 }
369
370
371 get_motd(cl)
372 client *cl;
373 {
374     int motd, len;
375     char buffer[1024];
376     char *arg[1];
377
378     arg[0] = buffer;
379     cl->reply.mr_status = 0;
380     motd = open(MOIRA_MOTD_FILE, 0, O_RDONLY);
381     if (motd < 0) return;
382     len = read(motd, buffer, sizeof(buffer) - 1);
383     close(motd);
384     buffer[len] = 0;
385     row_count = 0;
386     retr_callback(1, arg, cl);
387     cl->reply.mr_status = 0;
388 }
This page took 0.069252 seconds and 5 git commands to generate.