]> andersk Git - moira.git/blobdiff - server/qrtn.qc
add mk_cmds
[moira.git] / server / qrtn.qc
index 2a5fe26033c2dade49f66a8f9386882ef1548bde..49e72b9ca77852e28b22fcd07e0524b7353d52d2 100644 (file)
@@ -3,58 +3,9 @@
  *     $Author$
  *     $Header$
  *
- *     Copyright (C) 1987 by the Massachusetts Institute of Technology
- *
- *     $Log$
- *     Revision 1.14  1988-01-14 13:37:57  mar
- *     1. separate access checking from setup routines
- *     2. check max argument length
- *
- * Revision 1.14  88/01/14  13:14:37  mar
- * 1. separate access checking from setup routines
- * 2. check max argument length
- * 
- * Revision 1.13  88/01/04  12:02:13  mar
- * moved transaction start before pre-routines (wesommer)
- * 
- * Revision 1.13  87/11/12  18:13:12  wesommer
- * Move transaction boundary to include the pre routine.
- * 
- * Revision 1.12  87/09/12  20:42:11  wesommer
- * Clean up after Gretzinger: cl->kname is not valid unless cl->clname is
- * non-NULL.
- * 
- * Revision 1.12  87/09/12  20:06:46  wesommer
- * Fix security hole/null dereference bug: if clname is NULL, return
- * permission denied in get_client.
- * 
- * Revision 1.11  87/09/01  16:10:01  wesommer
- * This change was made by Mike, who didn't feel like checking it in.
- * Temp hack: ignore instances.
- * 
- * Revision 1.10  87/08/28  14:57:51  mike
- * Modified sms_query to not enclose RETRIEVE queries in begin/end transaction.
- * This was necessary to allow get_all_poboxes and get_groups_of_all_users
- * to temporarily change the Ingres lockmode.
- * 
- * Revision 1.9  87/08/22  17:47:38  wesommer
- * Cleanup (these changes were by Mike).
- * 
- * Revision 1.8  87/08/10  16:22:26  mike
- * wesommer modified error reporting.
- * 
- * Revision 1.7  87/08/04  01:49:20  wesommer
- * Rearranged messages.
- * 
- * Revision 1.6  87/08/04  01:30:54  wesommer
- * Mike's changes; checked in prior to working over messages.
- * 
- * Revision 1.5  87/06/21  16:37:58  wesommer
- * Changed include files, reindented things.
- * 
- * 
- * Revision 1.4  87/06/08  05:03:27  wesommer
- * Reindented; added header and trailer.
+ *     Copyright (C) 1987, 1988 by the Massachusetts Institute of Technology
+ *     For copying and distribution information, please see the file
+ *     <mit-copyright.h>.
  * 
  */
 
 static char *rcsid_qrtn_qc = "$Header$";
 #endif lint
 
+#include <mit-copyright.h>
 #include "query.h"
 #include "sms_server.h"
 
-#define SMS_SUCCESS 0
-
 char *Argv[16];
 
 static int ingres_errno = 0;
 extern char *whoami;
+extern FILE *journal;
+
+#define INGRES_BAD_INT 4111
+#define INGRES_BAD_DATE 4302
+#define INGRES_DEADLOCK 4700
 
 /*
  * ingerr: (supposedly) called when Ingres indicates an error.
@@ -81,18 +36,36 @@ extern char *whoami;
 static int ingerr(num)
     int *num;
 {
-    ingres_errno = SMS_INGRES_ERR;
-    com_err(whoami, SMS_INGRES_ERR, " code %d\n", ingres_errno);
-    return *num;
+    char buf[256];
+
+    switch (*num) {
+    case INGRES_BAD_INT:
+       ingres_errno = SMS_INTEGER;
+       break;
+    case INGRES_BAD_DATE:
+       ingres_errno = SMS_DATE;
+       break;
+    case INGRES_DEADLOCK:
+       com_err(whoami, 0, "INGRES deadlock detected");
+       ingres_errno = SMS_DEADLOCK;
+       break;
+    default:
+       ingres_errno = SMS_INGRES_ERR;
+       com_err(whoami, SMS_INGRES_ERR, " code %d\n", *num);
+       critical_alert("SMS", "SMS server encountered INGRES ERROR %d", *num);
+       return (*num);
+    }
+    return (0);
 }
 
 int sms_open_database()
 {
     register int i;
+    char *malloc();
 
     /* initialize local argv */
     for (i = 0; i < 16; i++)
-       Argv[i] = (char *)malloc(ARGLEN);
+       Argv[i] = malloc(ARGLEN);
 
     IIseterr(ingerr);
        
@@ -117,7 +90,7 @@ sms_check_access(cl, name, argc, argv_ro)
     struct query *q;
     struct query *get_query_by_name();
 
-    q = get_query_by_name(name);
+    q = get_query_by_name(name, cl->args->sms_version_no);
     if (q == (struct query *)0)
        return(SMS_NO_HANDLE);
 
@@ -148,25 +121,29 @@ sms_process_query(cl, name, argc, argv_ro, action, actarg)
 
     /* list queries command */
     if (!strcmp(name, "_list_queries")) {
-       list_queries(action, actarg);
+       list_queries(cl->args->sms_version_no, action, actarg);
        return(SMS_SUCCESS);
     }
 
     /* help query command */
     if (!strcmp(name, "_help")) {
-       q = get_query_by_name(argv_ro[0]);
+       if (argc < 1)
+           return(SMS_ARGS);
+       q = get_query_by_name(argv_ro[0], cl->args->sms_version_no);
        if (q == (struct query *)0) return(SMS_NO_HANDLE);
        help_query(q, action, actarg);
        return(SMS_SUCCESS);
     }
 
     /* get query structure, return error if named query does not exist */
-    q = get_query_by_name(name);
+    q = get_query_by_name(name, cl->args->sms_version_no);
     if (q == (struct query *)0) return(SMS_NO_HANDLE);
     v = q->validate;
 
-    if (q->type != RETRIEVE)
+    if (q->type != RETRIEVE) {
+##     set lockmode session where readlock = exclusive
 ##      begin transaction
+    }
 
     /* setup argument vector, verify access and arguments */
     if ((status = sms_verify_query(cl, q, argc, argv_ro)) != SMS_SUCCESS)
@@ -214,17 +191,14 @@ sms_process_query(cl, name, argc, argv_ro, action, actarg)
                    sq_destroy(sq);
                    break;
                }
-               status = (*v->post_rtn)(q, sq, v, action, actarg);
+               status = (*v->post_rtn)(q, sq, v, action, actarg, cl);
            } else {
                /* normal retrieve */
                status = do_retrieve(q, pqual, psort, action, actarg);
            }
            if (status != SMS_SUCCESS) break;
-           table = q->rtable;
-##          repeat replace tblstats (retrieves = tblstats.retrieves + 1)
-##                 where tblstats.#table = @table
        } else {
-           status = (*v->post_rtn)(q, Argv, action, actarg);
+           status = (*v->post_rtn)(q, Argv, cl, action, actarg);
        }
 
        break;
@@ -243,13 +217,15 @@ sms_process_query(cl, name, argc, argv_ro, action, actarg)
            status = do_update(q, &Argv[q->argc], qual, action, actarg);
            if (status != SMS_SUCCESS) break;
            table = q->rtable;
-##         repeat replace tblstats (updates = tblstats.updates + 1,
-##                                  modtime = "now")
-##             where tblstats.#table = @table
+           if (strcmp(q->shortname, "sshi") && strcmp(q->shortname, "ssif")) {
+##             repeat replace tblstats (updates = tblstats.updates + 1,
+##                                      modtime = "now")
+##                 where tblstats.#table = @table
+           }
        }
 
        /* execute followup routine (if any) */
-       if (v->post_rtn) status = (*v->post_rtn)(q, Argv);
+       if (v->post_rtn) status = (*v->post_rtn)(q, Argv, cl);
 
        break;
 
@@ -262,7 +238,7 @@ sms_process_query(cl, name, argc, argv_ro, action, actarg)
 
        /* increment id number if necessary */
        if (v->object_id) {
-           status = set_next_object_id(v->object_id);
+           status = set_next_object_id(v->object_id, q->rtable);
            if (status != SMS_SUCCESS) break;
        }
 
@@ -286,7 +262,7 @@ sms_process_query(cl, name, argc, argv_ro, action, actarg)
        }
        
        /* execute followup routine */
-       if (v->post_rtn) status = (*v->post_rtn)(q, Argv);
+       if (v->post_rtn) status = (*v->post_rtn)(q, Argv, cl);
        break;
 
     case DELETE:
@@ -309,7 +285,7 @@ sms_process_query(cl, name, argc, argv_ro, action, actarg)
        }
 
        /* execute followup routine */
-       if (v->post_rtn) status = (*v->post_rtn)(q, Argv);
+       if (v->post_rtn) status = (*v->post_rtn)(q, Argv, cl);
        break;
 
     }
@@ -318,8 +294,29 @@ out:
     if (q->type != RETRIEVE) {
         if (status == SMS_SUCCESS) {
 ##          end transaction    /* commit to this */
+##         set lockmode session where readlock = system
+           if (journal) {
+               char buf[1024], *bp;
+               int i;
+               extern time_t now;
+
+               fprintf(journal, "%% %s %s %s",
+                       cl->clname, cl->entity, ctime(&now));
+               fprintf(journal, "%s[%d] ", q->name, cl->args->sms_version_no);
+               for (i = 0; i < argc; i++) {
+                   if (i != 0) {
+                       putc(' ', journal);
+                   }
+                   requote(buf, argv_ro[i], sizeof(buf));
+                   fputs(buf, journal);
+               }
+               putc('\n', journal);
+               fflush(journal);
+           }
        } else {
-##          abort              /* it never happened */
+           if (status != SMS_DEADLOCK) {
+##             abort           /* it never happened */
+           }
        }
     }
 
@@ -337,10 +334,11 @@ build_qual(fmt, argc, argv, qual)
     register char *c;
     register int i;
     char *args[4];
+    char *index();
 
     c = fmt;
     for (i = 0; i < argc; i++) {
-       c = (char *)index(c, '%');
+       c = index(c, '%');
        if (c++ == (char *)0) return(SMS_ARGS);
        if (*c == 's')
            args[i] = argv[i];
@@ -371,6 +369,7 @@ build_qual(fmt, argc, argv, qual)
        sprintf(qual, fmt, args[0], args[1], args[2], args[3]);
        break;
     }
+    return(SMS_SUCCESS);
 }
 
 char *
@@ -414,6 +413,8 @@ sms_verify_query(cl, q, argc, argv_ro)
     register int privileged = 0;
 
     /* copy the arguments into a local argv that we can modify */
+    if (argc >= QMAXARGS)
+      return(SMS_ARGS);
     for (i = 0; i < argc; i++) {
        if (strlen(argv_ro[i]) < ARGLEN)
            strcpy(Argv[i], argv_ro[i]);
@@ -489,7 +490,7 @@ check_query_access(q, argv, cl)
     if (status != SMS_SUCCESS) return(status);
 
     /* see if client is in the list (or any of its sub-lists) */
-    exists = find_member(acl_id, client_type, client_id, 0);
+    exists = find_member("LIST", acl_id, client_type, client_id, 0);
     return ((exists) ? SMS_SUCCESS : SMS_PERM);
 ##}
 
@@ -511,26 +512,27 @@ get_client(cl, client_type, client_id)
 
     /* if client is from local realm, get users_id */
     if (!strcmp(krb->realm, krb_realm)) {
-       name = krb->name;
-##     repeat retrieve (member_id = users.users_id) where users.login = @name
+       *client_id = cl->users_id;
        *client_type = "USER";
-    } else {
-       /* otherwise use string_id */
-       name = cl->clname;
-##     repeat retrieve (member_id = strings.string_id) 
-##          where strings.string = @name
-       *client_type = "STRING";
+       return(SMS_SUCCESS);
     }
+
+    /* otherwise use string_id */
+    name = cl->clname;
+##  repeat retrieve (member_id = strings.string_id) 
+##      where strings.string = @name
        
     /* make sure we found a users or string id */
 ##  inquire_equel (rowcount = "rowcount")
     if (rowcount == 0) return(SMS_PERM);
 
+    *client_type = "STRING";
     *client_id = member_id;
     return(SMS_SUCCESS);
 ##}
 
-##find_member(list_id, member_type, member_id, sq)
+##find_member(list_type, list_id, member_type, member_id, sq)
+    char *list_type;
 ##  int list_id;
 ##  char *member_type;
 ##  int member_id;
@@ -541,6 +543,10 @@ get_client(cl, client_type, client_id)
     int child;
     struct save_queue *sq_create();
 
+    if (!strcmp(strtrim(list_type), strtrim(member_type)) &&
+       list_id == member_id)
+       return(1);
+
     /* see if client is a direct member of list */
 ##  repeat retrieve (exists = any(m.#member_id where 
 ##                               m.#list_id = @list_id and
@@ -571,18 +577,21 @@ get_client(cl, client_type, client_id)
         sq_save_unique_data(sq, sublist);
 ##  }
 
-    if (child) return;
+    if (child) return(0);
 
     /* at top-level, check sub-lists for client (breadth-first search) */
     while (sq_get_data(sq, &sublist)) {
-       exists = find_member(sublist, member_type, member_id, sq);
+       exists = find_member(list_type, sublist, member_type, member_id, sq);
        if (exists) {
            sq_destroy(sq);
            return(1);
        }
     }
+    sq_destroy(sq);
+    return(0);
 ##}
 
+
 do_retrieve(q, pqual, psort, action, actarg)
     register struct query *q;
     char *pqual;
@@ -596,6 +605,22 @@ do_retrieve(q, pqual, psort, action, actarg)
 ##  char *csort;
 ##  int rowcount;
 ##  int errorno;
+    static char **vaddrs = (char **)NULL;
+
+    if (!vaddrs) {
+       register int i;
+
+       if ((vaddrs = (char **)malloc(sizeof(char *) * QMAXARGS)) == NULL) {
+           com_err(whoami, SMS_NO_MEM, "setting up static argv");
+           exit(1);
+       }
+       for (i = 0; i < QMAXARGS; i++) {
+           if ((vaddrs[i] = malloc(QMAXARGSIZE)) == NULL) {
+               com_err(whoami, SMS_NO_MEM, "setting up static argv");
+               exit(1);
+           }
+       }
+    }
 
     if (q->rvar) {
        rvar = q->rvar;
@@ -607,30 +632,30 @@ do_retrieve(q, pqual, psort, action, actarg)
        csort = psort;
        if (pqual) {
            cqual = pqual;
-##          retrieve unique (param (q->tlist, q->vaddr)) where cqual
+##          retrieve unique (param (q->tlist, vaddrs)) where cqual
 ##                   sort by csort
 ##          {
-                (*action)(q->vcnt, q->vaddr, actarg);
+                (*action)(q->vcnt, vaddrs, actarg);
 ##          }
        } else {
-##          retrieve unique (param (q->tlist, q->vaddr))
+##          retrieve unique (param (q->tlist, vaddrs))
 ##                   sort by csort
 ##          {
-                (*action)(q->vcnt, q->vaddr, actarg);
+                (*action)(q->vcnt, vaddrs, actarg);
 ##          }
        }
 
     } else {
        if (pqual) {
            cqual = pqual;
-##          retrieve unique (param (q->tlist, q->vaddr)) where cqual
+##          retrieve unique (param (q->tlist, vaddrs)) where cqual
 ##          {
-                (*action)(q->vcnt, q->vaddr, actarg);
+                (*action)(q->vcnt, vaddrs, actarg);
 ##          }
        } else {
-##          retrieve unique (param (q->tlist, q->vaddr))
+##          retrieve unique (param (q->tlist, vaddrs))
 ##          {
-                (*action)(q->vcnt, q->vaddr, actarg);
+                (*action)(q->vcnt, vaddrs, actarg);
 ##          }
        }
     }
@@ -650,7 +675,6 @@ do_update(q, argv, qual, action, actarg)
 ##  char *rvar;
 ##  char *rtable;
 ##  char *cqual;
-##  int rowcount;
 ##  int errorno;
       
     rvar = q->rvar;
@@ -662,7 +686,10 @@ do_update(q, argv, qual, action, actarg)
 ##  where cqual
 
 ##  inquire_equel (errorno = "errorno")
-    if (errorno != 0) return(SMS_INGRES_ERR);
+    if (errorno == INGRES_BAD_INT)
+       return(SMS_INTEGER);
+    else if (errorno != 0)
+       return(SMS_INGRES_ERR);
     return(SMS_SUCCESS);
 ##}
 
@@ -690,7 +717,10 @@ do_append(q, argv, pqual, action, actarg)
     }
 
 ##  inquire_equel (errorno = "errorno")
-    if (errorno != 0) return(SMS_INGRES_ERR);
+    if (errorno == INGRES_BAD_INT)
+       return(SMS_INTEGER);
+    else if (errorno != 0)
+       return(SMS_INGRES_ERR);
     return(SMS_SUCCESS);
 ##}
 
@@ -718,14 +748,72 @@ do_delete(q, qual, action, actarg)
 ##}
 
 
-/*
- * Local Variables:
- * mode: c
- * c-indent-level: 4
- * c-continued-statement-offset: 4
- * c-brace-offset: -4
- * c-argdecl-indent: 4
- * c-label-offset: -4
- * End:
+/**
+ ** set_next_object_id - set next object id in values table
+ **
+ ** Inputs: object - object name in values table and in objects
+ **        table - name of table objects are found in
+ **
+ ** - called before an APPEND operation to set the next object id to
+ **   be used for the new record to the next free value
+ **
+ **/
+
+set_next_object_id(object, table)
+    char *object;
+    char *table;
+##{
+##  char *name, *tbl;
+##  int rowcount, exists, value;
+
+    name = object;
+    tbl = table;
+##  range of v is values
+##  repeat retrieve (value = v.#value) where v.#name = @name
+##  inquire_equel(rowcount = "rowcount")
+    if (rowcount != 1)
+       return(SMS_NO_ID);
+
+##  retrieve (exists = any(tbl.name where tbl.name = value))
+##  inquire_equel(rowcount = "rowcount")
+    if (rowcount != 1)
+       return(SMS_NO_ID);
+    while (exists) {
+       value++;
+       if (value > MAX_ID_VALUE)
+           value = MIN_ID_VALUE;
+##     retrieve (exists = any(tbl.name where tbl.name = value))
+    }
+
+    if (LOG_RES)
+        com_err(whoami, 0, "setting ID %s to %d", name, value);
+##  repeat replace v (#value = @value) where v.#name = @name
+    return(SMS_SUCCESS);
+##}
+
+
+/* For now this just checks the argc's.  It should also see that there
+ * are no duplicate names.
  */
 
+sanity_check_queries()
+{
+    register int i;
+    int maxv = 0, maxa = 0;
+    extern int QueryCount1, QueryCount2;
+    extern struct query Queries1[], Queries2[];
+#define MAX(x,y) ((x) > (y) ? (x) : (y))
+
+    for (i = 0; i < QueryCount1; i++) {
+       maxv = MAX(maxv, Queries1[i].vcnt);
+       maxa = MAX(maxa, Queries1[i].argc);
+    }
+    for (i = 0; i < QueryCount2; i++) {
+       maxv = MAX(maxv, Queries2[i].vcnt);
+       maxa = MAX(maxa, Queries2[i].argc);
+    }
+    if (MAX(maxv, maxa) > QMAXARGS) {
+       com_err(whoami, 0, "A query has more args than QMAXARGS");
+       exit(1);
+    }
+}
This page took 0.945824 seconds and 4 git commands to generate.