]> andersk Git - moira.git/blame - server/mr_scall.c
Change `SMS' to `Moira' where possible.
[moira.git] / server / mr_scall.c
CommitLineData
a3cf6921 1/*
2 * $Source$
3 * $Author$
4 * $Header$
5 *
6 * Copyright (C) 1987 by the Massachusetts Institute of Technology
c801de4c 7 * For copying and distribution information, please see the file
8 * <mit-copyright.h>.
a3cf6921 9 *
a3cf6921 10 */
11
12#ifndef lint
59ec8dae 13static char *rcsid_mr_scall_c = "$Header$";
a3cf6921 14#endif lint
15
c801de4c 16#include <mit-copyright.h>
57c08162 17#include <sys/types.h>
18#include <sys/stat.h>
9cad7c8f 19#include <sys/file.h>
03c05291 20#include <fcntl.h>
21#include <string.h>
98a7b0ee 22#include <netinet/in.h>
960b073b 23#include <arpa/inet.h>
a3cf6921 24#include <krb.h>
78849033 25#include <errno.h>
d548a4e7 26#include "mr_server.h"
03c05291 27#include "query.h"
a3cf6921 28extern char buf1[];
29extern int nclients;
30extern char *whoami;
8165c536 31extern int errno;
a3cf6921 32
33extern void clist_delete(), do_auth(), do_shutdown();
34void do_call();
03c05291 35extern int dbms_errno, mr_errcode;
78543660 36static int row_count;
37
38/* Put this in a variable so that we can patch it if necessary */
50e114e1 39int max_row_count = 4096;
a3cf6921 40
41/*
42 * Welcome to the (finite state) machine (highest level).
43 */
5eaef520 44void do_client(client *cp)
a3cf6921 45{
5eaef520 46 struct stat stbuf;
47
48 free_rtn_tuples(cp);
49 if (OP_STATUS(cp->pending_op) == OP_CANCELLED)
50 {
51 com_err(whoami, 0,
52 "Closed connection (now %d client%s, %d new queries, %d old)",
53 nclients - 1, nclients != 2 ? "s" : "", newqueries, 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 {
61 com_err(whoami, 0, "motd file exists, slumbertime");
62 dormant = SLEEPY;
a3cf6921 63 }
5eaef520 64 return;
65 }
66 switch (cp->action)
67 {
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, 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, NULL);
83 queue_operation(cp->con, CON_OUTPUT, cp->pending_op);
84 cp->action = CL_SEND;
85 break;
86 }
87}
a3cf6921 88
a3cf6921 89char *procnames[] = {
5eaef520 90 "noop",
91 "auth",
92 "shutdown",
93 "query",
94 "access",
95 "dcm",
96 "motd",
630e8323 97};
98
a3cf6921 99
5eaef520 100void do_call(client *cl)
a3cf6921 101{
5eaef520 102 int pn;
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) || (pn > MR_MAX_PROC))
107 {
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 {
114 log_args(procnames[pn], cl->args->mr_version_no,
115 cl->args->mr_argc, cl->args->mr_argv);
116 }
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 {
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 {
134 case MR_NOOP:
135 cl->reply.mr_status = 0;
136 return;
137
138 case MR_AUTH:
139 do_auth(cl);
140 return;
141
142 case MR_QUERY:
143 do_retr(cl);
144 return;
145
146 case MR_ACCESS:
147 do_access(cl);
148 return;
149
150 case MR_SHUTDOWN:
151 do_shutdown(cl);
152 return;
153
154 case MR_DO_UPDATE:
155 trigger_dcm(0, 0, cl);
156 return;
157
158 case MR_MOTD:
159 get_motd(cl);
160 return;
161 }
a3cf6921 162}
163
5eaef520 164free_rtn_tuples(client *cp)
ed31e0d1 165{
44d12d58 166 returned_tuples *temp;
5eaef520 167 for (temp = cp->first; temp && OP_DONE(temp->op); )
168 {
44d12d58 169 returned_tuples *t1 = temp;
5eaef520 170 temp = t1->next;
171 if (t1 == cp->last)
172 cp->last = NULL;
173
174 mr_destroy_reply(t1->retval);
175 delete_operation(t1->op);
176 free(t1);
177 }
178 cp->first = temp;
179}
ed31e0d1 180
44d12d58 181retr_callback(int argc, char **argv, char *p_cp)
78849033 182{
44d12d58 183 client *cp = (client *)p_cp;
5eaef520 184 mr_params *arg_tmp;
185 returned_tuples *tp;
186 OPERATION op_tmp;
44d12d58 187 char **nargv;
188 int i;
5eaef520 189
190 if (row_count++ >= max_row_count)
191 {
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 = db_alloc(sizeof(mr_params));
201 tp = db_alloc(sizeof(returned_tuples));
202 nargv = 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 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 {
44d12d58 221 int len = strlen(argv[i]) + 1;
5eaef520 222 nargv[i] = malloc(len);
223 memcpy(nargv[i], argv[i], len);
224 }
225 arg_tmp->mr_flattened = NULL;
226 arg_tmp->mr_argl = NULL;
227
228 if (cp->last)
229 {
230 cp->last->next = tp;
231 cp->last = tp;
232 } else
233 cp->last = cp->first = tp;
234
235 reset_operation(op_tmp);
236 initialize_operation(op_tmp, mr_start_send, (char *)arg_tmp, NULL);
237 queue_operation(cp->con, CON_OUTPUT, op_tmp);
78849033 238}
239
5eaef520 240int list_users(int (*callbk)(), char *callarg)
de24f12d 241{
5eaef520 242 char *argv[6];
243 char buf[30];
244 char buf1[30];
245 int i;
246 extern client **clients;
247 char *cp;
248 char *ctime();
249
250 for (i = 0; i < nclients; i++)
251 {
44d12d58 252 client *cl = clients[i];
5eaef520 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 = strchr(argv[3], '\n');
262 if (cp)
263 *cp = '\0';
264 argv[4] = buf1;
265 sprintf(buf1, "[#%d]", cl->id);
266 (*callbk)(5, argv, callarg);
267 }
268 return 0;
de24f12d 269}
78849033 270
44d12d58 271do_retr(client *cl)
a3cf6921 272{
44d12d58 273 char *queryname;
5eaef520 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 {
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"))
293 cl->reply.mr_status = list_users(retr_callback, (char *)cl);
294 else
295 {
296 cl->reply.mr_status = mr_process_query(cl, queryname,
297 cl->args->mr_argc - 1,
298 cl->args->mr_argv + 1,
299 retr_callback, (char *)cl);
300 }
301 if (row_count >= max_row_count)
302 {
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.");
a3cf6921 309}
78849033 310
5eaef520 311do_access(client *cl)
3630192b 312{
5eaef520 313 if (cl->args->mr_argc < 1)
314 {
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 = mr_check_access(cl, cl->args->mr_argv[0],
322 cl->args->mr_argc - 1,
323 cl->args->mr_argv + 1);
324
325 com_err(whoami, 0, "Access check complete.");
3630192b 326}
8165c536 327
a36b5bd7 328
5eaef520 329/* trigger_dcm is also used as a followup routine to the
a36b5bd7 330 * set_server_host_override query, hence the two dummy arguments.
331 */
332
8165c536 333struct query pseudo_query = {
5eaef520 334 "trigger_dcm",
335 "tdcm",
8165c536 336};
337
5eaef520 338int trigger_dcm(int dummy0, int dummy1, client *cl)
8165c536 339{
44d12d58 340 int pid;
5eaef520 341 char prog[128];
342
343 cl->reply.mr_argc = 0;
344
345 if ((cl->reply.mr_status = check_query_access(&pseudo_query, 0, cl)))
346 return cl->reply.mr_status;
347
348 sprintf(prog, "%s/startdcm", BIN_DIR);
349 pid = vfork();
350 switch (pid)
351 {
352 case 0:
353 execl(prog, "startdcm", 0);
354 exit(1);
355
356 case -1:
357 cl->reply.mr_status = errno;
358 return 0;
359
360 default:
361 return 0;
362 }
8165c536 363}
364
57c08162 365
5eaef520 366get_motd(client *cl)
57c08162 367{
5eaef520 368 int motd, len;
369 char buffer[1024];
370 char *arg[1];
371
372 arg[0] = buffer;
373 cl->reply.mr_status = 0;
374 motd = open(MOIRA_MOTD_FILE, 0, O_RDONLY);
375 if (motd < 0)
376 return;
377 len = read(motd, buffer, sizeof(buffer) - 1);
378 close(motd);
379 buffer[len] = 0;
380 row_count = 0;
381 retr_callback(1, arg, cl);
382 cl->reply.mr_status = 0;
57c08162 383}
This page took 0.205067 seconds and 5 git commands to generate.