X-Git-Url: http://andersk.mit.edu/gitweb/moira.git/blobdiff_plain/3630192bb4b8169ee6cba01dea7c7ffe5b587097..refs/heads/LOCKING:/server/mr_scall.c diff --git a/server/mr_scall.c b/server/mr_scall.c index 43b71a6a..eecc2d0d 100644 --- a/server/mr_scall.c +++ b/server/mr_scall.c @@ -4,39 +4,35 @@ * $Header$ * * Copyright (C) 1987 by the Massachusetts Institute of Technology + * For copying and distribution information, please see the file + * . * - * $Log$ - * Revision 1.5 1987-06-26 10:55:53 wesommer - * Added sms_access, now paiys attention to return code from - * sms_process_query, sms_check_access. - * - * Revision 1.4 87/06/21 16:42:00 wesommer - * Performance work, rearrangement of include files. - * - * Revision 1.3 87/06/04 01:35:01 wesommer - * Added a working query request handler. - * - * Revision 1.2 87/06/03 16:07:50 wesommer - * Fixes for lint. - * - * Revision 1.1 87/06/02 20:07:10 wesommer - * Initial revision - * */ #ifndef lint static char *rcsid_sms_scall_c = "$Header$"; #endif lint +#include +#include +#include +#include #include #include -#include "sms_server.h" +#include "query.h" +#include "mr_server.h" extern char buf1[]; extern int nclients; extern char *whoami; +extern int errno; extern void clist_delete(), do_auth(), do_shutdown(); void do_call(); +extern int ingres_errno, mr_errcode; +static int row_count; + +/* Put this in a variable so that we can patch it if necessary */ +int max_row_count = 2048; /* * Welcome to the (finite state) machine (highest level). @@ -45,19 +41,31 @@ void do_client(cp) client *cp; { + struct stat stbuf; + + free_rtn_tuples(cp); if (OP_STATUS(cp->pending_op) == OP_CANCELLED) { - (void) sprintf(buf1, "Closed connection (now %d client%s)", - nclients-1, - nclients!=2?"s":""); - com_err(whoami, 0, buf1); + 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; } switch (cp->action) { case CL_ACCEPT: case CL_SEND: /* Start recieving next request */ - initialize_operation(cp->pending_op, sms_start_recv, + 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; @@ -65,7 +73,9 @@ do_client(cp) case CL_RECEIVE: /* Data is here. Process it & start it heading back */ do_call(cp); /* This may block for a while. */ - initialize_operation(cp->pending_op, sms_start_send, + 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; @@ -73,138 +83,306 @@ do_client(cp) } } -#ifdef notdef char *procnames[] = { "noop", "auth", "shutdown", "query", - }; -#endif notdef + "access", + "dcm", + "motd", +}; + void do_call(cl) client *cl; { int pn; - cl->reply.sms_argc = 0; - cl->reply.sms_status = 0; - if (((pn = cl->args->sms_procno) < 0) || - (pn > SMS_MAX_PROC)) { + 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.sms_status = SMS_UNKNOWN_PROC; + cl->reply.mr_status = MR_UNKNOWN_PROC; return; } -#ifdef SMS_DBG - fprintf(stderr, "[#%d] %s(", cl->id, procnames[pn]); - for (i=0; i < cl->args->sms_argc; i++) { - if (i) fputc(',', stderr); - frequote(stderr,cl->args->sms_argv[i]); + 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; } - fprintf(stderr, ")\n"); -#endif SMS_DBG + + /* make sure this gets cleared before every operation */ + ingres_errno = 0; switch(pn) { - case SMS_NOOP: - cl->reply.sms_status = 0; - com_err(whoami, 0, "noop"); + case MR_NOOP: + cl->reply.mr_status = 0; return; - case SMS_AUTH: + case MR_AUTH: do_auth(cl); return; - case SMS_QUERY: + case MR_QUERY: do_retr(cl); return; - case SMS_ACCESS: + case MR_ACCESS: do_access(cl); return; - case SMS_SHUTDOWN: + 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; +{ + 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; +} + retr_callback(argc, argv, p_cp) - int argc; - char **argv; + register int argc; + register char **argv; char *p_cp; { register client *cp = (client *)p_cp; - /* XXX MEM when are these freed?? */ + mr_params *arg_tmp; + returned_tuples *tp; + OPERATION op_tmp; + register char **nargv; + register int i; + + if (row_count++ >= max_row_count) { + ingres_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. */ - sms_params *arg_tmp = (sms_params *)db_alloc(sizeof(sms_params)); - OPERATION op_tmp = create_operation(); + arg_tmp = (mr_params *)db_alloc(sizeof(mr_params)); + tp = (returned_tuples *)db_alloc(sizeof(returned_tuples)); + nargv = (char **)malloc(argc * sizeof(char *)); + + op_tmp = create_operation(); -#ifdef notdef /* We really don't want this logged */ - com_err(whoami, 0, "Returning next data:"); - log_args(argc, argv); -#endif notdef + 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; + } - arg_tmp->sms_status = SMS_MORE_DATA; - arg_tmp->sms_argc = argc; - arg_tmp->sms_argv = argv; - arg_tmp->sms_flattened = (char *)NULL; - arg_tmp->sms_argl = (int *)NULL; reset_operation(op_tmp); - initialize_operation(op_tmp, sms_start_send, (char *)arg_tmp, + initialize_operation(op_tmp, mr_start_send, (char *)arg_tmp, (int (*)())NULL); queue_operation(cp->con, CON_OUTPUT, op_tmp); } +list_users(callbk, callarg) + 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 *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; +} do_retr(cl) - client *cl; + register client *cl; { - cl->reply.sms_argc = 0; - cl->reply.sms_status = 0; -#ifdef notdef - if (!cl->clname) { - com_err(whoami, 0, "Unauthenticated query rejected"); - cl->reply.sms_status = EACCES; - return; + register 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; } -#endif notdef - com_err(whoami, 0, "Processing query: "); - log_args(cl->args->sms_argc, cl->args->sms_argv); + queryname = cl->args->mr_argv[0]; - cl->reply.sms_status = - sms_process_query(cl, - cl->args->sms_argv[0], - cl->args->sms_argc-1, - cl->args->sms_argv+1, - retr_callback, - (char *)cl); - - com_err(whoami, 0, "Query complete."); + 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, + 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; { - cl->reply.sms_argc = 0; - cl->reply.sms_status = 0; -#ifdef notdef - if (!cl->clname) { - com_err(whoami, 0, "Unauthenticated query rejected"); - cl->reply.sms_status = EACCES; - return; + if (cl->args->mr_argc < 1) { + cl->reply.mr_status = MR_ARGS; + com_err(whoami, MR_ARGS, "got nameless access"); + return; } -#endif notdef - com_err(whoami, 0, "Checking access: "); - log_args(cl->args->sms_argc, cl->args->sms_argv); - - cl->reply.sms_status = - sms_check_access(cl, - cl->args->sms_argv[0], - cl->args->sms_argc-1, - cl->args->sms_argv+1); + 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 + * set_server_host_override query, hence the two dummy arguments. + */ + +struct query pseudo_query = { + "trigger_dcm", + "tdcm", +}; + +trigger_dcm(dummy0, dummy1, cl) + int dummy0, 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); + } +} + + +get_motd(cl) +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; + row_count = 0; + retr_callback(1, arg, cl); + cl->reply.mr_status = 0; +}