]> andersk Git - moira.git/blobdiff - server/mr_scall.c
Command line printer manipulation client, and build goo.
[moira.git] / server / mr_scall.c
index 7a28bc0a88e65a28c80112cf40108d9dc837124b..4604334149e1a03e0caaf7506cbe55e1b7f90bbc 100644 (file)
-/*
- *     $Source$
- *     $Author$
- *     $Header$
+/* $Id$
  *
- *     Copyright (C) 1987 by the Massachusetts Institute of Technology
+ * Do RPC
  *
- *     $Log$
- *     Revision 1.9  1987-08-04 02:41:22  wesommer
- *     Clean up messages.
+ * Copyright (C) 1987-1998 by the Massachusetts Institute of Technology
+ * For copying and distribution information, please see the file
+ * <mit-copyright.h>.
  *
- * Revision 1.8  87/07/16  15:43:19  wesommer
- * Fixed bug where the argv was not copied to private storage
- * (it got changed out from under us before it got sent..).
- * 
- * Revision 1.7  87/07/14  00:39:01  wesommer
- * Rearranged loggin.
- * 
- * Revision 1.6  87/06/30  20:04:43  wesommer
- * Free returned tuples when possible.
- * 
- * Revision 1.5  87/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 <mit-copyright.h>
+#include "mr_server.h"
+#include "query.h"
+
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
 
-#include <krb.h>
 #include <errno.h>
-#include "sms_server.h"
-extern char buf1[];
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+RCSID("$Header$");
+
 extern int nclients;
+extern client **clients;
 extern char *whoami;
-extern char *malloc();
 
-extern void clist_delete(), do_auth(), do_shutdown();
-void do_call();
+extern int dbms_errno, mr_errcode;
 
-/*
- * Welcome to the (finite state) machine (highest level).
- */
-void
-do_client(cp)
-       client *cp;
-{
-       free_rtn_tuples(cp);
-       if (OP_STATUS(cp->pending_op) == OP_CANCELLED) {
-               com_err(whoami, 0, "Closed connection (now %d client%s)",
-                       nclients-1,
-                       nclients!=2?"s":"");
-               clist_delete(cp);
-               return;
-       }
-       switch (cp->action) {
-       case CL_ACCEPT:
-       case CL_SEND:
-               /* Start recieving next request */
-               initialize_operation(cp->pending_op, sms_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. */
-               initialize_operation(cp->pending_op, sms_start_send,
-                                    (char *)&cp->reply, (int (*)())NULL);
-               queue_operation(cp->con, CON_OUTPUT, cp->pending_op);
-               cp->action = CL_SEND;
-               break;
-       }
-}              
+int max_version;
+
+void do_call(client *cl);
+void free_rtn_tuples(client *cp);
+int retr_callback(int argc, char **argv, void *p_cl);
+int list_users(client *cl);
+void do_retr(client *cl);
+void do_access(client *cl);
+void get_motd(client *cl);
+void do_version(client *cl);
 
 char *procnames[] = {
-        "noop",
-        "auth",
-        "shutdown",
-        "query",
-        "access",
+  "noop",
+  "auth",
+  "shutdown",
+  "query",
+  "access",
+  "dcm",
+  "motd",
+  "proxy",
+  "version",
+  "auth_krb5",
 };
 
+int newqueries;
 
-void
-do_call(cl)
-       client *cl;
+void client_read(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)) {
-               com_err(whoami, 0, "procno out of range");
-               cl->reply.sms_status = SMS_UNKNOWN_PROC;
-               return;
-       }
-       if (log_flags & LOG_ARGS)
-               log_args(procnames[pn], cl->args->sms_argc,
-                        cl->args->sms_argv);
-       else if (log_flags & LOG_REQUESTS)
-               com_err(whoami, 0, "%s", procnames[pn]);
-
-       switch(pn) {
-       case SMS_NOOP:
-               cl->reply.sms_status = 0;
-               return;
-
-       case SMS_AUTH:
-               do_auth(cl);
-               return;
-
-       case SMS_QUERY:
-               do_retr(cl);
-               return;
-
-       case SMS_ACCESS:
-               do_access(cl);
-               return;
-               
-       case SMS_SHUTDOWN:
-               do_shutdown(cl);
-               return;
-       }
+  int status, pn;
+
+  status = mr_cont_receive(cl->con, &cl->req);
+  if (status == -1)
+    return;
+  else if (status != MR_SUCCESS)
+    {
+      cl->state = CL_CLOSING;
+      if (status != MR_NOT_CONNECTED)
+       com_err(whoami, status, "while reading from socket");
+      return;
+    }
+
+  pn = cl->req.u.mr_procno;
+  if (pn < 0 || pn > MR_MAX_PROC)
+    {
+      com_err(whoami, 0, "procno out of range");
+      client_reply(cl, MR_UNKNOWN_PROC);
+      goto out;
+    }
+  log_args(procnames[pn], 2, cl->req.mr_argc, cl->req.mr_argv);
+
+  if (dormant == ASLEEP && pn != MR_NOOP && pn != MR_MOTD)
+    {
+      client_reply(cl, MR_DOWN);
+      com_err(whoami, MR_DOWN, "(query refused)");
+      goto out;
+    }
+
+  /* make sure this gets cleared before every operation */
+  dbms_errno = 0;
+
+  switch (pn)
+    {
+    case MR_NOOP:
+      client_reply(cl, MR_SUCCESS);
+      break;
+
+    case MR_AUTH:
+      do_auth(cl);
+      break;
+
+    case MR_QUERY:
+      do_retr(cl);
+      break;
+
+    case MR_ACCESS:
+      do_access(cl);
+      break;
+
+    case MR_SHUTDOWN:
+      do_shutdown(cl);
+      break;
+
+    case MR_DO_UPDATE:
+      client_reply(cl, MR_PERM);
+      break;
+
+    case MR_MOTD:
+      get_motd(cl);
+      break;
+
+    case MR_PROXY:
+      do_proxy(cl);
+      break;
+
+    case MR_SETVERSION:
+      do_version(cl);
+      break;
+
+    case MR_KRB5_AUTH:
+      do_krb5_auth(cl);
+      break;
+
+    }
+
+out:
+  mr_destroy_reply(cl->req);
+  memset(&cl->req, 0, sizeof(mr_params));
 }
 
-free_rtn_tuples(cp)
-       client *cp;
+/* Set the final return status for a query. We always keep one more
+   free slot in cl->tuples[] than we're using so that this can't fail */
+void client_reply(client *cl, long status)
 {
-       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;
-
-               sms_destroy_reply(t1->retval);
-#ifdef notdef
-               if (t1->retval) {
-                       register sms_params *p = t1->retval;
-                       if (p->sms_flattened)
-                               free(p->sms_flattened);
-                       if (p->sms_argl)
-                               free(p->sms_argl);
-                       free(p);
-               }
-#endif notdef
-               delete_operation(t1->op);
-               free(t1);
-       }
-       cp->first = temp;
-}      
+  cl->tuples[cl->ntuples].u.mr_status = status;
+  cl->tuples[cl->ntuples].mr_argc = 0;
+  cl->tuples[cl->ntuples].mr_argl = NULL;
+  cl->tuples[cl->ntuples].mr_argv = NULL;
+  cl->ntuples++;
+}
 
-retr_callback(argc, argv, p_cp)
-       register int argc;
-       register char **argv;
-       char *p_cp;
+void client_return_tuple(client *cl, int argc, char **argv)
 {
-       register client *cp = (client *)p_cp;
-       /*
-        * 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));
-       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 (log_flags & LOG_RESP)
-               log_args("return: ", argc, argv);
-
-       tp->op = op_tmp;
-       tp->retval = arg_tmp;
-       tp->next = NULL;
-       
-       arg_tmp->sms_status = SMS_MORE_DATA;
-       arg_tmp->sms_argc = argc;
-       arg_tmp->sms_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->sms_flattened = (char *)NULL;
-       arg_tmp->sms_argl = (int *)NULL;
-
-       if (cp->last) {
-               cp->last->next = tp;
-               cp->last = tp;
-       } else {
-               cp->last = cp->first = tp;
+  if (cl->state == CL_CLOSING || dbms_errno)
+    return;
+
+  if (cl->ntuples == cl->tuplessize - 1)
+    {
+      int newsize = (cl->tuplessize + 4) * 2;
+      mr_params *newtuples;
+
+      newtuples = realloc(cl->tuples, newsize * sizeof(mr_params));
+      if (!newtuples)
+       {
+         free_rtn_tuples(cl);
+         dbms_errno = mr_errcode = MR_NO_MEM;
+         return;
        }
-       
-       reset_operation(op_tmp);
-       initialize_operation(op_tmp, sms_start_send, (char *)arg_tmp,
-                            (int (*)())NULL);
-       queue_operation(cp->con, CON_OUTPUT, op_tmp);
+      cl->tuplessize = newsize;
+      cl->tuples = newtuples;
+    }
+
+  cl->tuples[cl->ntuples].u.mr_status = MR_MORE_DATA;
+  cl->tuples[cl->ntuples].mr_argc = argc;
+  cl->tuples[cl->ntuples].mr_argl = NULL;
+  cl->tuples[cl->ntuples].mr_argv = mr_copy_args(argv, argc);
+  cl->ntuples++;
 }
 
+void client_write(client *cl)
+{
+  int status;
 
-do_retr(cl)
-       client *cl;
+  status = mr_send(cl->con, &cl->tuples[cl->nexttuple]);
+  if (status)
+    {
+      com_err(whoami, status, "writing to socket");
+      cl->state = CL_CLOSING;
+    }
+  else
+    {
+      cl->nexttuple++;
+      if (cl->nexttuple == cl->ntuples)
+       free_rtn_tuples(cl);
+    }
+}
+
+void free_rtn_tuples(client *cl)
 {
-       cl->reply.sms_argc = 0;
-       cl->reply.sms_status = 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);
-       if (log_flags & LOG_RES)
-               com_err(whoami, 0, "Query complete.");
+  for (cl->ntuples--; cl->ntuples >= 0; cl->ntuples--)
+    free_argv(cl->tuples[cl->ntuples].mr_argv,
+             cl->tuples[cl->ntuples].mr_argc);
+  free(cl->tuples);
+
+  cl->tuples = xmalloc(sizeof(mr_params));
+  cl->tuplessize = 1;
+  cl->ntuples = cl->nexttuple = 0;
 }
 
-do_access(cl)
-       client *cl;
+void do_retr(client *cl)
 {
-       cl->reply.sms_argc = 0;
-
-       cl->reply.sms_status = 
-         sms_check_access(cl,
-                          cl->args->sms_argv[0],
-                          cl->args->sms_argc-1,
-                          cl->args->sms_argv+1);
-       
-       com_err(whoami, 0, "Access check complete.");
+  char *queryname;
+  int status;
+
+  if (cl->req.mr_argc < 1)
+    {
+      client_reply(cl, MR_ARGS);
+      com_err(whoami, MR_ARGS, "got nameless query");
+      return;
+    }
+  queryname = cl->req.mr_argv[0];
+  newqueries++;
+
+  if (!strcmp(queryname, "_list_users"))
+    status = list_users(cl);
+  else
+    status = mr_process_query(cl, queryname, cl->req.mr_argc - 1,
+                             cl->req.mr_argv + 1, retr_callback, cl);
+
+  client_reply(cl, status);
+
+  com_err(whoami, 0, "Query complete.");
+}
+
+int retr_callback(int argc, char **argv, void *p_cl)
+{
+  client *cl = p_cl;
+
+  mr_trim_args(argc, argv);
+  client_return_tuple(cl, argc, argv);
+}
+
+void do_access(client *cl)
+{
+  int status;
+
+  if (cl->req.mr_argc < 1)
+    {
+      client_reply(cl, MR_ARGS);
+      com_err(whoami, MR_ARGS, "got nameless access");
+      return;
+    }
+
+  status = mr_check_access(cl, cl->req.mr_argv[0], cl->req.mr_argc - 1,
+                          cl->req.mr_argv + 1);
+  client_reply(cl, status);
+
+  com_err(whoami, 0, "Access check complete.");
 }
+
+void do_version(client *cl)
+{
+  if (cl->req.mr_argc != 1)
+    {
+      client_reply(cl, MR_ARGS);
+      com_err(whoami, MR_ARGS, "incorrect number of arguments");
+      return;
+    }
+
+  cl->version = atoi(cl->req.mr_argv[0]);
+  if (cl->version == -1)
+    cl->version = max_version;
+
+  client_reply(cl, cl->version == max_version ? MR_SUCCESS :
+              cl->version < max_version ? MR_VERSION_LOW : MR_VERSION_HIGH);
+}
+
+void get_motd(client *cl)
+{
+  int motd;
+  char *buffer;
+  struct stat statb;
+
+  if (stat(MOIRA_MOTD_FILE, &statb) == -1)
+    {
+      client_reply(cl, MR_SUCCESS);
+      return;
+    }
+  
+  buffer = malloc(statb.st_size + 1);
+  if (!buffer)
+    {
+      client_reply(cl, MR_NO_MEM);
+      return;
+    }
+
+  motd = open(MOIRA_MOTD_FILE, 0, O_RDONLY);
+  if (motd)
+    {
+      read(motd, buffer, statb.st_size);
+      close(motd);
+      buffer[statb.st_size] = '\0';
+      client_return_tuple(cl, 1, &buffer);
+      client_reply(cl, MR_SUCCESS);
+    }
+  else
+    client_reply(cl, errno);
+
+  free(buffer);
+}
+
+int list_users(client *cl)
+{
+  char *argv[5];
+  char buf[30];
+  char buf1[30];
+  int i;
+  char *cp;
+
+  for (i = 0; i < nclients; i++)
+    {
+      client *c = clients[i];
+      argv[0] = c->clname;
+      argv[1] = inet_ntoa(c->haddr.sin_addr);
+      argv[2] = buf;
+      sprintf(buf, "port %d", ntohs(c->haddr.sin_port));
+      argv[3] = ctime(&c->last_time_used);
+      cp = strchr(argv[3], '\n');
+      if (cp)
+       *cp = '\0';
+      argv[4] = buf1;
+      sprintf(buf1, "[#%d]", c->id);
+      client_return_tuple(cl, 5, argv);
+    }
+  return MR_SUCCESS;
+}
+
This page took 0.05414 seconds and 4 git commands to generate.