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