X-Git-Url: http://andersk.mit.edu/gitweb/moira.git/blobdiff_plain/4ce8321c959682cfafd2200fce4bc99fa2949a58..59ec8daed689fed26f4fc6cbd94d5e4d1961c407:/server/mr_scall.c diff --git a/server/mr_scall.c b/server/mr_scall.c index a3671b97..2b4a7c4d 100644 --- a/server/mr_scall.c +++ b/server/mr_scall.c @@ -10,350 +10,374 @@ */ #ifndef lint -static char *rcsid_sms_scall_c = "$Header$"; +static char *rcsid_mr_scall_c = "$Header$"; #endif lint #include #include #include #include +#include +#include +#include +#include #include #include -#include "query.h" #include "mr_server.h" +#include "query.h" extern char buf1[]; extern int nclients; extern char *whoami; -extern char *malloc(); extern int errno; extern void clist_delete(), do_auth(), do_shutdown(); void do_call(); +extern int dbms_errno, mr_errcode; +static int row_count; + +/* Put this in a variable so that we can patch it if necessary */ +int max_row_count = 4096; /* * Welcome to the (finite state) machine (highest level). */ -void -do_client(cp) - client *cp; +void do_client(client *cp) { - struct stat stbuf; - - free_rtn_tuples(cp); - if (OP_STATUS(cp->pending_op) == OP_CANCELLED) { - com_err(whoami, 0, "Closed connection (now %d client%s, %d new queries, %d old)", - nclients-1, - nclients!=2?"s":"", - newqueries, - oldqueries); - clist_delete(cp); - /* if we no longer have any clients, and we're supposed to - * go down, then go down now. - */ - if ((dormant == AWAKE) && (nclients == 0) && - (stat(MOIRA_MOTD_FILE, &stbuf) == 0)) { - com_err(whoami, 0, "motd file exists, slumbertime"); - dormant = SLEEPY; - } - return; + struct stat stbuf; + + free_rtn_tuples(cp); + if (OP_STATUS(cp->pending_op) == OP_CANCELLED) + { + com_err(whoami, 0, + "Closed connection (now %d client%s, %d new queries, %d old)", + nclients - 1, nclients != 2 ? "s" : "", newqueries, oldqueries); + clist_delete(cp); + /* if we no longer have any clients, and we're supposed to + * go down, then go down now. + */ + if ((dormant == AWAKE) && (nclients == 0) && + (stat(MOIRA_MOTD_FILE, &stbuf) == 0)) + { + com_err(whoami, 0, "motd file exists, slumbertime"); + dormant = SLEEPY; } - switch (cp->action) { - case CL_ACCEPT: - case CL_SEND: - /* Start recieving next request */ - initialize_operation(cp->pending_op, mr_start_recv, - (char *)&cp->args, (int (*)())NULL); - queue_operation(cp->con, CON_INPUT, cp->pending_op); - cp->action = CL_RECEIVE; - break; - case CL_RECEIVE: - /* Data is here. Process it & start it heading back */ - do_call(cp); /* This may block for a while. */ - mr_destroy_reply(cp->args); - cp->args = NULL; - initialize_operation(cp->pending_op, mr_start_send, - (char *)&cp->reply, (int (*)())NULL); - queue_operation(cp->con, CON_OUTPUT, cp->pending_op); - cp->action = CL_SEND; - break; - } -} + return; + } + switch (cp->action) + { + case CL_ACCEPT: + case CL_SEND: + /* Start recieving next request */ + initialize_operation(cp->pending_op, mr_start_recv, + (char *)&cp->args, NULL); + queue_operation(cp->con, CON_INPUT, cp->pending_op); + cp->action = CL_RECEIVE; + break; + case CL_RECEIVE: + /* Data is here. Process it & start it heading back */ + do_call(cp); /* This may block for a while. */ + mr_destroy_reply(cp->args); + cp->args = NULL; + initialize_operation(cp->pending_op, mr_start_send, + (char *)&cp->reply, NULL); + queue_operation(cp->con, CON_OUTPUT, cp->pending_op); + cp->action = CL_SEND; + break; + } +} char *procnames[] = { - "noop", - "auth", - "shutdown", - "query", - "access", - "dcm", - "motd", + "noop", + "auth", + "shutdown", + "query", + "access", + "dcm", + "motd", }; -void -do_call(cl) - client *cl; +void do_call(client *cl) { - int pn; - extern int ingres_errno; - cl->reply.mr_argc = 0; - cl->reply.mr_status = 0; - cl->reply.mr_version_no = cl->args->mr_version_no; - if (((pn = cl->args->mr_procno) < 0) || - (pn > MR_MAX_PROC)) { - com_err(whoami, 0, "procno out of range"); - cl->reply.mr_status = MR_UNKNOWN_PROC; - return; - } - if (log_flags & LOG_ARGS) - log_args(procnames[pn], cl->args->mr_version_no, - cl->args->mr_argc, cl->args->mr_argv); - else if (log_flags & LOG_REQUESTS) - com_err(whoami, 0, "%s", procnames[pn]); - - if ((dormant == ASLEEP || dormant == GROGGY) && - pn != MR_NOOP && pn != MR_MOTD) { - cl->reply.mr_status = MR_DOWN; - if (log_flags & LOG_RES) - com_err(whoami, MR_DOWN, "(query refused)"); - return; - } - - /* make sure this gets cleared before every operation */ - ingres_errno = 0; - - switch(pn) { - case MR_NOOP: - cl->reply.mr_status = 0; - return; - - case MR_AUTH: - do_auth(cl); - return; - - case MR_QUERY: - do_retr(cl); - return; - - case MR_ACCESS: - do_access(cl); - return; - - case MR_SHUTDOWN: - do_shutdown(cl); - return; - - case MR_DO_UPDATE: - trigger_dcm(0, 0, cl); - return; - - case MR_MOTD: - get_motd(cl); - return; - } + int pn; + cl->reply.mr_argc = 0; + cl->reply.mr_status = 0; + cl->reply.mr_version_no = cl->args->mr_version_no; + if (((pn = cl->args->mr_procno) < 0) || (pn > MR_MAX_PROC)) + { + com_err(whoami, 0, "procno out of range"); + cl->reply.mr_status = MR_UNKNOWN_PROC; + return; + } + if (log_flags & LOG_ARGS) + { + log_args(procnames[pn], cl->args->mr_version_no, + cl->args->mr_argc, cl->args->mr_argv); + } + else if (log_flags & LOG_REQUESTS) + com_err(whoami, 0, "%s", procnames[pn]); + + if ((dormant == ASLEEP || dormant == GROGGY) && + pn != MR_NOOP && pn != MR_MOTD) + { + cl->reply.mr_status = MR_DOWN; + if (log_flags & LOG_RES) + com_err(whoami, MR_DOWN, "(query refused)"); + return; + } + + /* make sure this gets cleared before every operation */ + dbms_errno = 0; + + switch (pn) + { + case MR_NOOP: + cl->reply.mr_status = 0; + return; + + case MR_AUTH: + do_auth(cl); + return; + + case MR_QUERY: + do_retr(cl); + return; + + case MR_ACCESS: + do_access(cl); + return; + + case MR_SHUTDOWN: + do_shutdown(cl); + return; + + case MR_DO_UPDATE: + trigger_dcm(0, 0, cl); + return; + + case MR_MOTD: + get_motd(cl); + return; + } } -free_rtn_tuples(cp) - client *cp; +free_rtn_tuples(client *cp) { - register returned_tuples *temp; - for (temp=cp->first; temp && OP_DONE(temp->op); ) { - register returned_tuples *t1=temp; - temp = t1->next; - if (t1 == cp->last) cp->last = NULL; - - mr_destroy_reply(t1->retval); - delete_operation(t1->op); - free(t1); - } - cp->first = temp; -} + returned_tuples *temp; + for (temp = cp->first; temp && OP_DONE(temp->op); ) + { + returned_tuples *t1 = temp; + temp = t1->next; + if (t1 == cp->last) + cp->last = NULL; + + mr_destroy_reply(t1->retval); + delete_operation(t1->op); + free(t1); + } + cp->first = temp; +} -retr_callback(argc, argv, p_cp) - register int argc; - register char **argv; - char *p_cp; +retr_callback(int argc, char **argv, char *p_cp) { - register client *cp = (client *)p_cp; - /* - * This takes too much advantage of the fact that - * serialization of the data happens during the queue operation. - */ - mr_params *arg_tmp = (mr_params *)db_alloc(sizeof(mr_params)); - returned_tuples *tp = (returned_tuples *) - db_alloc(sizeof(returned_tuples)); - register char **nargv = (char **)malloc(argc * sizeof(char *)); - register int i; - - OPERATION op_tmp = create_operation(); - - if (mr_trim_args(argc, argv) == MR_NO_MEM) { - com_err(whoami, MR_NO_MEM, "while trimming args"); - } - if (log_flags & LOG_RESP) - log_args("return: ", cp->args->mr_version_no, argc, argv); - - tp->op = op_tmp; - tp->retval = arg_tmp; - tp->next = NULL; - - arg_tmp->mr_status = MR_MORE_DATA; - arg_tmp->mr_version_no = cp->args->mr_version_no; - arg_tmp->mr_argc = argc; - arg_tmp->mr_argv = nargv; - for (i = 0; i < argc; i++) { - register int len = strlen(argv[i]) + 1; - nargv[i] = malloc(len); - bcopy(argv[i], nargv[i], len); - } - arg_tmp->mr_flattened = (char *)NULL; - arg_tmp->mr_argl = (int *)NULL; - - if (cp->last) { - cp->last->next = tp; - cp->last = tp; - } else { - cp->last = cp->first = tp; - } - - reset_operation(op_tmp); - initialize_operation(op_tmp, mr_start_send, (char *)arg_tmp, - (int (*)())NULL); - queue_operation(cp->con, CON_OUTPUT, op_tmp); + client *cp = (client *)p_cp; + mr_params *arg_tmp; + returned_tuples *tp; + OPERATION op_tmp; + char **nargv; + int i; + + if (row_count++ >= max_row_count) + { + dbms_errno = mr_errcode = MR_NO_MEM; + return; + } + + /* + * This takes too much advantage of the fact that + * serialization of the data happens during the queue operation. + */ + arg_tmp = db_alloc(sizeof(mr_params)); + tp = db_alloc(sizeof(returned_tuples)); + nargv = malloc(argc * sizeof(char *)); + + op_tmp = create_operation(); + + if (mr_trim_args(argc, argv) == MR_NO_MEM) + com_err(whoami, MR_NO_MEM, "while trimming args"); + if (log_flags & LOG_RESP) + log_args("return: ", cp->args->mr_version_no, argc, argv); + + tp->op = op_tmp; + tp->retval = arg_tmp; + tp->next = NULL; + + arg_tmp->mr_status = MR_MORE_DATA; + arg_tmp->mr_version_no = cp->args->mr_version_no; + arg_tmp->mr_argc = argc; + arg_tmp->mr_argv = nargv; + for (i = 0; i < argc; i++) + { + int len = strlen(argv[i]) + 1; + nargv[i] = malloc(len); + memcpy(nargv[i], argv[i], len); + } + arg_tmp->mr_flattened = NULL; + arg_tmp->mr_argl = NULL; + + if (cp->last) + { + cp->last->next = tp; + cp->last = tp; + } else + cp->last = cp->first = tp; + + reset_operation(op_tmp); + initialize_operation(op_tmp, mr_start_send, (char *)arg_tmp, NULL); + queue_operation(cp->con, CON_OUTPUT, op_tmp); } -list_users(callbk, callarg) - int (*callbk)(); - char *callarg; +int list_users(int (*callbk)(), char *callarg) { - char *argv[6]; - char buf[30]; - char buf1[30]; - int i; - extern client **clients; - extern char *inet_ntoa(); - char *cp; - char *index(); - char *ctime(); - - for (i = 0; i < nclients; i++) { - register client *cl = clients[i]; - if (cl->clname) - argv[0] = cl->clname; - else argv[0] = "unauthenticated"; - - argv[1] = inet_ntoa(cl->haddr.sin_addr); - argv[2] = buf; - sprintf(buf, "port %d", ntohs(cl->haddr.sin_port)); - argv[3] = ctime(&cl->last_time_used); - cp = index(argv[3], '\n'); - if (cp) *cp = '\0'; - argv[4] = buf1; - sprintf(buf1, "[#%d]", cl->id); - (*callbk)(5, argv, callarg); - } - return 0; + char *argv[6]; + char buf[30]; + char buf1[30]; + int i; + extern client **clients; + char *cp; + char *ctime(); + + for (i = 0; i < nclients; i++) + { + client *cl = clients[i]; + if (cl->clname) + argv[0] = cl->clname; + else argv[0] = "unauthenticated"; + + argv[1] = inet_ntoa(cl->haddr.sin_addr); + argv[2] = buf; + sprintf(buf, "port %d", ntohs(cl->haddr.sin_port)); + argv[3] = ctime(&cl->last_time_used); + cp = strchr(argv[3], '\n'); + if (cp) + *cp = '\0'; + argv[4] = buf1; + sprintf(buf1, "[#%d]", cl->id); + (*callbk)(5, argv, callarg); + } + return 0; } -do_retr(cl) - register client *cl; +do_retr(client *cl) { - register char *queryname; - - cl->reply.mr_argc = 0; - cl->reply.mr_status = 0; - - queryname = cl->args->mr_argv[0]; - - if (cl->args->mr_version_no == MR_VERSION_2) - newqueries++; - else - oldqueries++; - - if (strcmp(queryname, "_list_users") == 0) - cl->reply.mr_status = list_users(retr_callback, (char *)cl); - else { - cl->reply.mr_status = - mr_process_query(cl, - cl->args->mr_argv[0], - cl->args->mr_argc-1, - cl->args->mr_argv+1, - retr_callback, - (char *)cl); - } - if (log_flags & LOG_RES) - com_err(whoami, 0, "Query complete."); + char *queryname; + + cl->reply.mr_argc = 0; + cl->reply.mr_status = 0; + row_count = 0; + + if (cl->args->mr_argc < 1) + { + cl->reply.mr_status = MR_ARGS; + com_err(whoami, MR_ARGS, "got nameless query"); + return; + } + queryname = cl->args->mr_argv[0]; + + if (cl->args->mr_version_no == MR_VERSION_2) + newqueries++; + else + oldqueries++; + + if (!strcmp(queryname, "_list_users")) + cl->reply.mr_status = list_users(retr_callback, (char *)cl); + else + { + cl->reply.mr_status = mr_process_query(cl, queryname, + cl->args->mr_argc - 1, + cl->args->mr_argv + 1, + retr_callback, (char *)cl); + } + if (row_count >= max_row_count) + { + critical_alert("moirad", "attempted query %s with %d rows\n", + queryname, row_count); + } + + if (log_flags & LOG_RES) + com_err(whoami, 0, "Query complete."); } -do_access(cl) - client *cl; +do_access(client *cl) { - cl->reply.mr_argc = 0; - - cl->reply.mr_status = - mr_check_access(cl, - cl->args->mr_argv[0], - cl->args->mr_argc-1, - cl->args->mr_argv+1); - - com_err(whoami, 0, "Access check complete."); + if (cl->args->mr_argc < 1) + { + cl->reply.mr_status = MR_ARGS; + com_err(whoami, MR_ARGS, "got nameless access"); + return; + } + cl->reply.mr_argc = 0; + + cl->reply.mr_status = mr_check_access(cl, cl->args->mr_argv[0], + cl->args->mr_argc - 1, + cl->args->mr_argv + 1); + + com_err(whoami, 0, "Access check complete."); } -/* trigger_dcm is also used as a followup routine to the +/* trigger_dcm is also used as a followup routine to the * set_server_host_override query, hence the two dummy arguments. */ struct query pseudo_query = { - "trigger_dcm", - "tdcm", + "trigger_dcm", + "tdcm", }; -trigger_dcm(dummy0, dummy1, cl) - int dummy0, dummy1; - client *cl; +int trigger_dcm(int dummy0, int dummy1, client *cl) { - register int pid; - char prog[128]; - - cl->reply.mr_argc = 0; - - if (cl->reply.mr_status = check_query_access(&pseudo_query, 0, cl) ) - return(cl->reply.mr_status); - - sprintf(prog, "%s/startdcm", BIN_DIR); - pid = vfork(); - switch (pid) { - case 0: - for (dummy0 = getdtablesize() - 1; dummy0 > 2; dummy0--) - close(dummy0); - execl(prog, "startdcm", 0); - exit(1); - - case -1: - cl->reply.mr_status = errno; - return(0); - - default: - return(0); - } + int pid; + char prog[128]; + + cl->reply.mr_argc = 0; + + if ((cl->reply.mr_status = check_query_access(&pseudo_query, 0, cl))) + return cl->reply.mr_status; + + sprintf(prog, "%s/startdcm", BIN_DIR); + pid = vfork(); + switch (pid) + { + case 0: + execl(prog, "startdcm", 0); + exit(1); + + case -1: + cl->reply.mr_status = errno; + return 0; + + default: + return 0; + } } -get_motd(cl) -client *cl; +get_motd(client *cl) { - int motd, len; - char buffer[1024]; - char *arg[1]; - - arg[0] = buffer; - cl->reply.mr_status = 0; - motd = open(MOIRA_MOTD_FILE, 0, O_RDONLY); - if (motd < 0) return; - len = read(motd, buffer, sizeof(buffer) - 1); - close(motd); - buffer[len] = 0; - retr_callback(1, arg, cl); - cl->reply.mr_status = 0; + int motd, len; + char buffer[1024]; + char *arg[1]; + + arg[0] = buffer; + cl->reply.mr_status = 0; + motd = open(MOIRA_MOTD_FILE, 0, O_RDONLY); + if (motd < 0) + return; + len = read(motd, buffer, sizeof(buffer) - 1); + close(motd); + buffer[len] = 0; + row_count = 0; + retr_callback(1, arg, cl); + cl->reply.mr_status = 0; }