6 * Copyright (C) 1987 by the Massachusetts Institute of Technology
7 * For copying and distribution information, please see the file
13 static char *rcsid_sms_scall_c = "$Header$";
16 #include <mit-copyright.h>
17 #include <sys/types.h>
24 #include "mr_server.h"
31 extern void clist_delete(), do_auth(), do_shutdown();
33 extern int dbms_errno, mr_errcode;
36 /* Put this in a variable so that we can patch it if necessary */
37 int max_row_count = 2048;
40 * Welcome to the (finite state) machine (highest level).
49 if (OP_STATUS(cp->pending_op) == OP_CANCELLED) {
50 com_err(whoami, 0, "Closed connection (now %d client%s, %d new queries, %d old)",
56 /* if we no longer have any clients, and we're supposed to
57 * go down, then go down now.
59 if ((dormant == AWAKE) && (nclients == 0) &&
60 (stat(MOIRA_MOTD_FILE, &stbuf) == 0)) {
61 com_err(whoami, 0, "motd file exists, slumbertime");
69 /* Start recieving next request */
70 initialize_operation(cp->pending_op, mr_start_recv,
71 (char *)&cp->args, (int (*)())NULL);
72 queue_operation(cp->con, CON_INPUT, cp->pending_op);
73 cp->action = CL_RECEIVE;
76 /* Data is here. Process it & start it heading back */
77 do_call(cp); /* This may block for a while. */
78 mr_destroy_reply(cp->args);
80 initialize_operation(cp->pending_op, mr_start_send,
81 (char *)&cp->reply, (int (*)())NULL);
82 queue_operation(cp->con, CON_OUTPUT, cp->pending_op);
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;
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]);
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)");
127 /* make sure this gets cleared before every operation */
132 cl->reply.mr_status = 0;
152 trigger_dcm(0, 0, cl);
164 register returned_tuples *temp;
165 for (temp=cp->first; temp && OP_DONE(temp->op); ) {
166 register returned_tuples *t1=temp;
168 if (t1 == cp->last) cp->last = NULL;
170 mr_destroy_reply(t1->retval);
171 delete_operation(t1->op);
177 retr_callback(argc, argv, p_cp)
179 register char **argv;
182 register client *cp = (client *)p_cp;
186 register char **nargv;
189 if (row_count++ >= max_row_count) {
190 dbms_errno = mr_errcode = MR_NO_MEM;
195 * This takes too much advantage of the fact that
196 * serialization of the data happens during the queue operation.
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 *));
202 op_tmp = create_operation();
204 if (mr_trim_args(argc, argv) == MR_NO_MEM) {
205 com_err(whoami, MR_NO_MEM, "while trimming args");
207 if (log_flags & LOG_RESP)
208 log_args("return: ", cp->args->mr_version_no, argc, argv);
211 tp->retval = arg_tmp;
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 memcpy(nargv[i], argv[i], len);
223 arg_tmp->mr_flattened = (char *)NULL;
224 arg_tmp->mr_argl = (int *)NULL;
230 cp->last = cp->first = tp;
233 reset_operation(op_tmp);
234 initialize_operation(op_tmp, mr_start_send, (char *)arg_tmp,
236 queue_operation(cp->con, CON_OUTPUT, op_tmp);
239 list_users(callbk, callarg)
247 extern client **clients;
248 extern char *inet_ntoa();
252 for (i = 0; i < nclients; i++) {
253 register client *cl = clients[i];
255 argv[0] = cl->clname;
256 else argv[0] = "unauthenticated";
258 argv[1] = inet_ntoa(cl->haddr.sin_addr);
260 sprintf(buf, "port %d", ntohs(cl->haddr.sin_port));
261 argv[3] = ctime(&cl->last_time_used);
262 cp = strchr(argv[3], '\n');
265 sprintf(buf1, "[#%d]", cl->id);
266 (*callbk)(5, argv, callarg);
274 register char *queryname;
276 cl->reply.mr_argc = 0;
277 cl->reply.mr_status = 0;
280 if (cl->args->mr_argc < 1) {
281 cl->reply.mr_status = MR_ARGS;
282 com_err(whoami, MR_ARGS, "got nameless query");
285 queryname = cl->args->mr_argv[0];
287 if (cl->args->mr_version_no == MR_VERSION_2)
292 if (strcmp(queryname, "_list_users") == 0)
293 cl->reply.mr_status = list_users(retr_callback, (char *)cl);
295 cl->reply.mr_status =
303 if (row_count >= max_row_count) {
304 critical_alert("moirad", "attempted query %s with %d rows\n",
305 queryname, row_count);
308 if (log_flags & LOG_RES)
309 com_err(whoami, 0, "Query complete.");
315 if (cl->args->mr_argc < 1) {
316 cl->reply.mr_status = MR_ARGS;
317 com_err(whoami, MR_ARGS, "got nameless access");
320 cl->reply.mr_argc = 0;
322 cl->reply.mr_status =
324 cl->args->mr_argv[0],
326 cl->args->mr_argv+1);
328 com_err(whoami, 0, "Access check complete.");
332 /* trigger_dcm is also used as a followup routine to the
333 * set_server_host_override query, hence the two dummy arguments.
336 struct query pseudo_query = {
341 trigger_dcm(dummy0, dummy1, cl)
348 cl->reply.mr_argc = 0;
350 if (cl->reply.mr_status = check_query_access(&pseudo_query, 0, cl) )
351 return(cl->reply.mr_status);
353 sprintf(prog, "%s/startdcm", BIN_DIR);
357 execl(prog, "startdcm", 0);
361 cl->reply.mr_status = errno;
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);
385 retr_callback(1, arg, cl);
386 cl->reply.mr_status = 0;