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