]> andersk Git - moira.git/blame_incremental - server/mr_scall.c
detect query with no args
[moira.git] / server / mr_scall.c
... / ...
CommitLineData
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
13static 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"
24extern char buf1[];
25extern int nclients;
26extern char *whoami;
27extern char *malloc();
28extern int errno;
29
30extern void clist_delete(), do_auth(), do_shutdown();
31void do_call();
32extern int ingres_errno, mr_errcode;
33static int row_count;
34
35/* Put this in a variable so that we can patch it if necessary */
36int max_row_count = 2048;
37
38/*
39 * Welcome to the (finite state) machine (highest level).
40 */
41void
42do_client(cp)
43 client *cp;
44{
45 struct stat stbuf;
46
47 free_rtn_tuples(cp);
48 if (OP_STATUS(cp->pending_op) == OP_CANCELLED) {
49 com_err(whoami, 0, "Closed connection (now %d client%s, %d new queries, %d old)",
50 nclients-1,
51 nclients!=2?"s":"",
52 newqueries,
53 oldqueries);
54 clist_delete(cp);
55 /* if we no longer have any clients, and we're supposed to
56 * go down, then go down now.
57 */
58 if ((dormant == AWAKE) && (nclients == 0) &&
59 (stat(MOIRA_MOTD_FILE, &stbuf) == 0)) {
60 com_err(whoami, 0, "motd file exists, slumbertime");
61 dormant = SLEEPY;
62 }
63 return;
64 }
65 switch (cp->action) {
66 case CL_ACCEPT:
67 case CL_SEND:
68 /* Start recieving next request */
69 initialize_operation(cp->pending_op, mr_start_recv,
70 (char *)&cp->args, (int (*)())NULL);
71 queue_operation(cp->con, CON_INPUT, cp->pending_op);
72 cp->action = CL_RECEIVE;
73 break;
74 case CL_RECEIVE:
75 /* Data is here. Process it & start it heading back */
76 do_call(cp); /* This may block for a while. */
77 mr_destroy_reply(cp->args);
78 cp->args = NULL;
79 initialize_operation(cp->pending_op, mr_start_send,
80 (char *)&cp->reply, (int (*)())NULL);
81 queue_operation(cp->con, CON_OUTPUT, cp->pending_op);
82 cp->action = CL_SEND;
83 break;
84 }
85}
86
87char *procnames[] = {
88 "noop",
89 "auth",
90 "shutdown",
91 "query",
92 "access",
93 "dcm",
94 "motd",
95};
96
97
98void
99do_call(cl)
100 client *cl;
101{
102 int pn;
103 extern int ingres_errno;
104 cl->reply.mr_argc = 0;
105 cl->reply.mr_status = 0;
106 cl->reply.mr_version_no = cl->args->mr_version_no;
107 if (((pn = cl->args->mr_procno) < 0) ||
108 (pn > MR_MAX_PROC)) {
109 com_err(whoami, 0, "procno out of range");
110 cl->reply.mr_status = MR_UNKNOWN_PROC;
111 return;
112 }
113 if (log_flags & LOG_ARGS)
114 log_args(procnames[pn], cl->args->mr_version_no,
115 cl->args->mr_argc, cl->args->mr_argv);
116 else if (log_flags & LOG_REQUESTS)
117 com_err(whoami, 0, "%s", procnames[pn]);
118
119 if ((dormant == ASLEEP || dormant == GROGGY) &&
120 pn != MR_NOOP && pn != MR_MOTD) {
121 cl->reply.mr_status = MR_DOWN;
122 if (log_flags & LOG_RES)
123 com_err(whoami, MR_DOWN, "(query refused)");
124 return;
125 }
126
127 /* make sure this gets cleared before every operation */
128 ingres_errno = 0;
129
130 switch(pn) {
131 case MR_NOOP:
132 cl->reply.mr_status = 0;
133 return;
134
135 case MR_AUTH:
136 do_auth(cl);
137 return;
138
139 case MR_QUERY:
140 do_retr(cl);
141 return;
142
143 case MR_ACCESS:
144 do_access(cl);
145 return;
146
147 case MR_SHUTDOWN:
148 do_shutdown(cl);
149 return;
150
151 case MR_DO_UPDATE:
152 trigger_dcm(0, 0, cl);
153 return;
154
155 case MR_MOTD:
156 get_motd(cl);
157 return;
158 }
159}
160
161free_rtn_tuples(cp)
162 client *cp;
163{
164 register returned_tuples *temp;
165 for (temp=cp->first; temp && OP_DONE(temp->op); ) {
166 register returned_tuples *t1=temp;
167 temp = t1->next;
168 if (t1 == cp->last) cp->last = NULL;
169
170 mr_destroy_reply(t1->retval);
171 delete_operation(t1->op);
172 free(t1);
173 }
174 cp->first = temp;
175}
176
177retr_callback(argc, argv, p_cp)
178 register int argc;
179 register char **argv;
180 char *p_cp;
181{
182 register client *cp = (client *)p_cp;
183 mr_params *arg_tmp;
184 returned_tuples *tp;
185 OPERATION op_tmp;
186 register char **nargv;
187 register int i;
188
189 if (row_count++ >= max_row_count) {
190 ingres_errno = mr_errcode = MR_NO_MEM;
191 return;
192 }
193
194 /*
195 * This takes too much advantage of the fact that
196 * serialization of the data happens during the queue operation.
197 */
198 arg_tmp = (mr_params *)db_alloc(sizeof(mr_params));
199 tp = (returned_tuples *)db_alloc(sizeof(returned_tuples));
200 nargv = (char **)malloc(argc * sizeof(char *));
201
202 op_tmp = create_operation();
203
204 if (mr_trim_args(argc, argv) == MR_NO_MEM) {
205 com_err(whoami, MR_NO_MEM, "while trimming args");
206 }
207 if (log_flags & LOG_RESP)
208 log_args("return: ", cp->args->mr_version_no, argc, argv);
209
210 tp->op = op_tmp;
211 tp->retval = arg_tmp;
212 tp->next = NULL;
213
214 arg_tmp->mr_status = MR_MORE_DATA;
215 arg_tmp->mr_version_no = cp->args->mr_version_no;
216 arg_tmp->mr_argc = argc;
217 arg_tmp->mr_argv = nargv;
218 for (i = 0; i < argc; i++) {
219 register int len = strlen(argv[i]) + 1;
220 nargv[i] = malloc(len);
221 bcopy(argv[i], nargv[i], len);
222 }
223 arg_tmp->mr_flattened = (char *)NULL;
224 arg_tmp->mr_argl = (int *)NULL;
225
226 if (cp->last) {
227 cp->last->next = tp;
228 cp->last = tp;
229 } else {
230 cp->last = cp->first = tp;
231 }
232
233 reset_operation(op_tmp);
234 initialize_operation(op_tmp, mr_start_send, (char *)arg_tmp,
235 (int (*)())NULL);
236 queue_operation(cp->con, CON_OUTPUT, op_tmp);
237}
238
239list_users(callbk, callarg)
240 int (*callbk)();
241 char *callarg;
242{
243 char *argv[6];
244 char buf[30];
245 char buf1[30];
246 int i;
247 extern client **clients;
248 extern char *inet_ntoa();
249 char *cp;
250 char *index();
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 = index(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
272do_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
313do_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
337struct query pseudo_query = {
338 "trigger_dcm",
339 "tdcm",
340};
341
342trigger_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 for (dummy0 = getdtablesize() - 1; dummy0 > 2; dummy0--)
359 close(dummy0);
360 execl(prog, "startdcm", 0);
361 exit(1);
362
363 case -1:
364 cl->reply.mr_status = errno;
365 return(0);
366
367 default:
368 return(0);
369 }
370}
371
372
373get_motd(cl)
374client *cl;
375{
376 int motd, len;
377 char buffer[1024];
378 char *arg[1];
379
380 arg[0] = buffer;
381 cl->reply.mr_status = 0;
382 motd = open(MOIRA_MOTD_FILE, 0, O_RDONLY);
383 if (motd < 0) return;
384 len = read(motd, buffer, sizeof(buffer) - 1);
385 close(motd);
386 buffer[len] = 0;
387 row_count = 0;
388 retr_callback(1, arg, cl);
389 cl->reply.mr_status = 0;
390}
This page took 0.063851 seconds and 5 git commands to generate.