]> andersk Git - moira.git/blobdiff - server/qrtn.qc
Used /bin/sh format instead of /bin/csh format, by accident.
[moira.git] / server / qrtn.qc
index 8461bab4e4db5f8eeff645afd98d5402733ba135..55559c626555d00be4fd27b2f652293cf960b6a6 100644 (file)
@@ -3,18 +3,9 @@
  *     $Author$
  *     $Header$
  *
- *     Copyright (C) 1987 by the Massachusetts Institute of Technology
- *
- *     $Log$
- *     Revision 1.6  1987-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
+#include "mr_server.h"
 
 char *Argv[16];
 
-static int ingres_errno = 0;
+int ingres_errno = 0;
+int mr_errcode = 0;
+## int query_timeout = 30;
 extern char *whoami;
+extern FILE *journal;
+
+#define INGRES_BAD_INT 4111
+#define INGRES_BAD_DATE 4302
+#define INGRES_DEADLOCK 4700
+#define INGRES_TIMEOUT 4702
+#define INGRES_NO_RANGE 2109
 
 /*
  * ingerr: (supposedly) called when Ingres indicates an error.
@@ -41,85 +40,91 @@ extern char *whoami;
 static int ingerr(num)
     int *num;
 {
-    ingres_errno = SMS_INGRES_ERR;
-    return *num;
+    ingres_errno = *num;
+
+    switch (*num) {
+    case INGRES_BAD_INT:
+       mr_errcode = MR_INTEGER;
+       break;
+    case INGRES_BAD_DATE:
+       mr_errcode = MR_DATE;
+       break;
+    case INGRES_DEADLOCK:
+       mr_errcode = MR_DEADLOCK;
+       com_err(whoami, 0, "INGRES deadlock detected");
+       break;
+    case INGRES_TIMEOUT:
+       mr_errcode = MR_BUSY;
+       com_err(whoami, 0, "timed out getting lock");
+       break;
+    case INGRES_NO_RANGE:
+       mr_errcode = MR_INGRES_SOFTFAIL;
+       com_err(whoami, 0, "INGRES missing range statement");
+       break;
+    default:
+       mr_errcode = MR_INGRES_ERR;
+       com_err(whoami, MR_INGRES_ERR, " code %d\n", *num);
+       critical_alert("MOIRA", "Moira server encountered INGRES ERROR %d", *num);
+       return (*num);
+    }
+    return (0);
 }
 
-int sms_open_database()
+int mr_open_database()
 {
     register int i;
+    char *malloc();
+    static first_open = 1;
 
-    /* initialize local argv */
-    for (i = 0; i < 16; i++)
-       Argv[i] = (char *)malloc(128);
+    if (first_open) {
+       first_open = 0;
 
-    IIseterr(ingerr);
+       /* initialize local argv */
+       for (i = 0; i < 16; i++)
+         Argv[i] = malloc(ARGLEN);
+
+       IIseterr(ingerr);
+       incremental_init();
+       flush_cache();
+    }
        
     ingres_errno = 0;
-       
+    mr_errcode = 0;
+
     /* open the database */
 ##  ingres sms
+##  set lockmode session where level = table, timeout = query_timeout
+##  set lockmode on capacls where readlock = shared
+##  set lockmode on alias where readlock = shared
     return ingres_errno;
 }
 
-int sms_close_database()
+int mr_close_database()
 {
+    flush_cache();
 ##  exit
 }
 
-sms_check_access(cl, name, argc, argv_ro)
+mr_check_access(cl, name, argc, argv_ro)
     client *cl;
     char *name;
     int argc;
     char *argv_ro[];
 {
-    register struct query *q;
-    register int argreq;
-    register int status;
-    register struct validate *v;
-    register int i;
-    register int privileged;
+    struct query *q;
     struct query *get_query_by_name();
-    int access_user();
-    int access_pop();
-
-    q = get_query_by_name(name);
-    if (q == (struct query *)0) return(SMS_NO_HANDLE);
-    v = q->validate;
-
-    /* copy the arguments into a local argv that we can modify */
-    for (i = 0; i < argc; i++)
-       strcpy(Argv[i], argv_ro[i]);
 
-    /* check initial query access */
-    status = check_query_access(q, Argv, cl);
-    privileged = (status == SMS_SUCCESS) ? 1 : 0;
-    if (status != SMS_SUCCESS && !(v && (v->pre_rtn == access_user ||
-                                        v->pre_rtn == access_pop))) 
-       return(status);
-
-    /* check argument count */
-    argreq = q->argc;
-    if (q->type == UPDATE || q->type == APPEND) argreq += q->vcnt;
-    if (argc != argreq) return(SMS_ARGS);
-
-    /* validate arguments */
-    if (v && v->valobj) {
-       status = validate_fields(q, Argv, v->valobj, v->objcnt);
-       if (status != SMS_SUCCESS) return(status);
-    }
+    ingres_errno = 0;
+    mr_errcode = 0;
 
-    /* perform special query access check */
-    if (v && v->pre_rtn) {
-       status = (*v->pre_rtn)(q, Argv, cl, 1);
-       if (status != SMS_SUCCESS && (status != SMS_PERM || !privileged)) 
-           return(status);
-    }
+    q = get_query_by_name(name, cl->args->mr_version_no);
+    if (q == (struct query *)0)
+       return(MR_NO_HANDLE);
 
-    return(SMS_SUCCESS);
+    return(mr_verify_query(cl, q, argc, argv_ro));
 }
 
-sms_process_query(cl, name, argc, argv_ro, action, actarg)
+mr_process_query(cl, name, argc, argv_ro, action, actarg)
     client *cl;
     char *name;
     int argc;
@@ -128,76 +133,65 @@ sms_process_query(cl, name, argc, argv_ro, action, actarg)
     char *actarg;
 {
     register struct query *q;
-    register int i;
     register int status;
-    register int argreq;
     register struct validate *v;
-    int privileged;
     char qual[256];
+    char sort[32];
     char *pqual;
-##  char *table;
+    char *psort;
+##  char *table, *rvar;
     struct save_queue *sq;
     struct query *get_query_by_name();
     int sq_save_args();
     struct save_queue *sq_create();
-    int access_user();
+    char *build_sort();
 
-    /* copy the arguments into a local argv that we can modify */
-    for (i = 0; i < argc; i++)
-       strcpy(Argv[i], argv_ro[i]);
+    ingres_errno = 0;
+    mr_errcode = 0;
 
     /* list queries command */
     if (!strcmp(name, "_list_queries")) {
-       list_queries(action, actarg);
-       return(SMS_SUCCESS);
+       list_queries(cl->args->mr_version_no, action, actarg);
+       return(MR_SUCCESS);
     }
 
     /* help query command */
     if (!strcmp(name, "_help")) {
-       q = get_query_by_name(Argv[0]);
-       if (q == (struct query *)0) return(SMS_NO_HANDLE);
+       if (argc < 1)
+           return(MR_ARGS);
+       q = get_query_by_name(argv_ro[0], cl->args->mr_version_no);
+       if (q == (struct query *)0) return(MR_NO_HANDLE);
        help_query(q, action, actarg);
-       return(SMS_SUCCESS);
+       return(MR_SUCCESS);
     }
 
     /* get query structure, return error if named query does not exist */
-    q = get_query_by_name(name);
-    if (q == (struct query *)0) return(SMS_NO_HANDLE);
+    q = get_query_by_name(name, cl->args->mr_version_no);
+    if (q == (struct query *)0) return(MR_NO_HANDLE);
     v = q->validate;
 
-    /* check query access */
-    status = check_query_access(q, Argv, cl);
-    privileged = (status == SMS_SUCCESS) ? 1 : 0;
-    if (status != SMS_SUCCESS && !(v && (v->pre_rtn == access_user)))
-       return(status);
-
-    /* check argument count */
-    argreq = q->argc;
-    if (q->type == UPDATE || q->type == APPEND) argreq += q->vcnt;
-    if (argc != argreq) return(SMS_ARGS);
-
-    /* validate arguments */
-    if (v && v->valobj) {
-       status = validate_fields(q, Argv, v->valobj, v->objcnt);
-       if (status != SMS_SUCCESS) return(status);
+    if (q->type != RETRIEVE) {
+##      begin transaction
     }
 
+    /* setup argument vector, verify access and arguments */
+    if ((status = mr_verify_query(cl, q, argc, argv_ro)) != MR_SUCCESS)
+       goto out;
+
     /* perform any special query pre-processing */
     if (v && v->pre_rtn) {
        status = (*v->pre_rtn)(q, Argv, cl, 0);
-       if (status != SMS_SUCCESS && (status != SMS_PERM || !privileged))
-           return(status);
+       if (status != MR_SUCCESS)
+           goto out;
     }
 
-##  begin transaction
-
     switch (q->type) {
     case RETRIEVE:
        /* for queries that do not permit wildcarding, check if row
           uniquely exists */
        if (v && v->field) {
            status = validate_row(q, Argv, v);
-           if (status != SMS_EXISTS) break;
+           if (status != MR_EXISTS) break;
        }
 
        /* build "where" clause if needed */
@@ -208,27 +202,32 @@ sms_process_query(cl, name, argc, argv_ro, action, actarg)
            pqual = 0;
        }
 
+       /* build "sort" clause if needed */
+       if (v && v->valobj) {
+           psort = build_sort(v, sort);
+       } else {
+           psort = 0;
+       }
+
        /* if there is a followup routine, then we must save the results */
        /* of the first query for use by the followup routine */
-       /* if q->rtable = NULL, perform post_rtn only */
-       if (table = q->rtable) {
+       /* if q->rvar = NULL, perform post_rtn only */
+       if (q->rvar) {
            if (v && v->post_rtn) {
                sq = sq_create();
-               status = do_retrieve(q, pqual, sq_save_args, sq);
-               if (status != SMS_SUCCESS) {
+               status = do_retrieve(q, pqual, psort, sq_save_args, sq);
+               if (status != MR_SUCCESS) {
                    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, action, actarg);
+               status = do_retrieve(q, pqual, psort, action, actarg);
            }
-           if (status != SMS_SUCCESS) break;
-##          repeat replace tblstats (retrieves = tblstats.retrieves + 1)
-##                 where tblstats.#table = @table
+           if (status != MR_SUCCESS) break;
        } else {
-           status = (*v->post_rtn)(q, Argv, action, actarg);
+           status = (*v->post_rtn)(q, Argv, cl, action, actarg);
        }
 
        break;
@@ -237,22 +236,28 @@ sms_process_query(cl, name, argc, argv_ro, action, actarg)
        /* see if row already exists */
        if (v->field) {
            status = validate_row(q, Argv, v);
-           if (status != SMS_EXISTS) break;
+           if (status != MR_EXISTS) break;
        }
 
        /* build "where" clause and perform update */
-       /* if q->rtable = NULL, perform post_rtn only */
-       if (table = q->rtable) {
+       /* if q->rvar = NULL, perform post_rtn only */
+       if (q->rvar) {
            build_qual(q->qual, q->argc, Argv, qual);
+           incremental_before(q->rtable, qual, argv_ro);
            status = do_update(q, &Argv[q->argc], qual, action, actarg);
-           if (status != SMS_SUCCESS) break;
-##         repeat replace tblstats (updates = tblstats.updates + 1,
-##                                  modtime = "now")
-##             where tblstats.#table = @table
+           incremental_after(q->rtable, qual, argv_ro);
+           if (status != MR_SUCCESS) break;
+           flush_name(argv_ro[0], q->rtable);
+           table = q->rtable;
+           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;
 
@@ -260,56 +265,116 @@ sms_process_query(cl, name, argc, argv_ro, action, actarg)
        /* see if row already exists */
        if (v->field) {
            status = validate_row(q, Argv, v);
-           if (status != SMS_NO_MATCH) break;
+           if (status != MR_NO_MATCH) break;
        }
 
        /* increment id number if necessary */
-       if (v->object_id) set_next_object_id(v->object_id);
+       if (v->object_id) {
+           status = set_next_object_id(v->object_id, q->rtable);
+           if (status != MR_SUCCESS) break;
+       }
+
+       /* build "where" clause if needed */
+       if (q->qual) {
+           build_qual(q->qual, q->argc, Argv, qual);
+           pqual = qual;
+       } else {
+           pqual = 0;
+       }
 
        /* perform the append */
-       /* if q->rtable = NULL, perform post_rtn only */
-       if (table = q->rtable) {
-           status = do_append(q, &Argv[q->argc], action, actarg);
-           if (status != SMS_SUCCESS) break;
+       /* if q->rvar = NULL, perform post_rtn only */
+       if (q->rvar) {
+           incremental_clear_before();
+           status = do_append(q, &Argv[q->argc], pqual, action, actarg);
+           if (status != MR_SUCCESS) break;
+           if (v && v->object_id) {
+               sprintf(qual, "%s.%s = values.value and values.name = \"%s\"",
+                       q->rvar, v->object_id, v->object_id);
+               incremental_after(q->rtable, qual, argv_ro);
+           } else
+             incremental_after(q->rtable, pqual, argv_ro);
+
+           table = q->rtable;
 ##         repeat replace tblstats (appends = tblstats.appends + 1,
 ##                                  modtime = "now")
 ##             where tblstats.#table = @table
        }
        
        /* 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:
        /* see if row already exists */
        if (v->field) {
            status = validate_row(q, Argv, v);
-           if (status != SMS_EXISTS) break;
+           if (status != MR_EXISTS) break;
        }
 
        /* build "where" clause and perform delete */
-       /* if q->rtable = NULL, perform post_rtn only */
-       if (table = q->rtable) {
+       /* if q->rvar = NULL, perform post_rtn only */
+       if (q->rvar) {
            build_qual(q->qual, q->argc, Argv, qual);
+           table = q->rtable;
+           rvar = q->rvar;
+##         range of rvar is table
+           incremental_before(q->rtable, qual, argv_ro);
            status = do_delete(q, qual, action, actarg);
-           if (status != SMS_SUCCESS) break;
+           incremental_clear_after();
+           if (status != MR_SUCCESS) break;
+           flush_name(argv_ro[0], q->rtable);
 ##         repeat replace tblstats (deletes = tblstats.deletes + 1,
 ##                                  modtime = "now")
 ##             where tblstats.#table = @table
        }
 
        /* 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;
 
     }
 
-    if (status == SMS_SUCCESS)
-##      end transaction
-    else
-##      abort
+out:
+    if (status == MR_SUCCESS && ingres_errno != 0) {
+       com_err(whoami, MR_INTERNAL, "Server didn't notice INGRES ERROR %d",
+                      ingres_errno);
+       status = mr_errcode;
+    }
 
-    if (status != SMS_SUCCESS) com_err(whoami, status, " (Query failed)");
+    if (q->type != RETRIEVE) {
+        if (status == MR_SUCCESS) {
+##          end transaction    /* commit to this */
+           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->mr_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);
+           }
+           incremental_update();
+       } else {
+           if (ingres_errno != INGRES_DEADLOCK) {
+##             abort           /* it never happened */
+           }
+           incremental_flush();
+       }
+##      set lockmode session where readlock = system
+    }
+
+    if (status != MR_SUCCESS && log_flags & LOG_RES)
+       com_err(whoami, status, " (Query failed)");
     return(status);
 }
 
@@ -322,17 +387,18 @@ 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, '%');
-       if (c++ == (char *)0) return(SMS_ARGS);
+       c = index(c, '%');
+       if (c++ == (char *)0) return(MR_ARGS);
        if (*c == 's')
            args[i] = argv[i];
        else if (*c == 'd')
            *(int *)&args[i] = *(int *)argv[i]; /* sigh */
        else
-           return(SMS_INGRES_ERR);
+           return(MR_INGRES_ERR);
     }
 
     switch (argc) {
@@ -356,8 +422,97 @@ build_qual(fmt, argc, argv, qual)
        sprintf(qual, fmt, args[0], args[1], args[2], args[3]);
        break;
     }
+    return(MR_SUCCESS);
+}
+
+char *
+build_sort(v, sort)
+    register struct validate *v;
+    char *sort;
+{
+    register struct valobj *vo;
+    register int n;
+    char elem[16];
+
+    n = v->objcnt;
+    vo = v->valobj;
+    *sort = 0;
+
+    while (--n >= 0) {
+       if (vo->type == V_SORT) {
+           sprintf(elem, "RET_VAR%d", vo->index + 1);
+           if (*sort) strcat(sort, ", ");
+           strcat(sort, elem);
+       }
+       vo++;
+    }
+
+    return ((*sort) ? sort : 0);
+}
+
+
+/* Build arguement vector, verify query and arguments */
+
+mr_verify_query(cl, q, argc, argv_ro)
+    client *cl;
+    struct query *q;
+    int argc;
+    char *argv_ro[];
+{
+    register int argreq;
+    register int status;
+    register struct validate *v = q->validate;
+    register int i;
+    register int privileged = 0;
+    int len;
+
+    /* copy the arguments into a local argv that we can modify */
+    if (argc >= QMAXARGS)
+      return(MR_ARGS);
+    for (i = 0; i < argc; i++) {
+       if ((len = strlen(argv_ro[i])) < ARGLEN)
+           strcpy(Argv[i], argv_ro[i]);
+       else
+           return(MR_ARG_TOO_LONG);
+       if (Argv[i][len-1] == '\\')
+         return(MR_BAD_CHAR);
+    }
+
+    /* check initial query access */
+    status = check_query_access(q, Argv, cl);
+    if (status != MR_SUCCESS && status != MR_PERM)
+       return(status);
+    if (status == MR_SUCCESS)
+       privileged++;
+
+    /* check argument count */
+    argreq = q->argc;
+    if (q->type == UPDATE || q->type == APPEND) argreq += q->vcnt;
+    if (argc != argreq) return(MR_ARGS);
+
+    /* validate arguments */
+    if (v && v->valobj) {
+       status = validate_fields(q, Argv, v->valobj, v->objcnt);
+       if (status != MR_SUCCESS) return(status);
+    }
+
+    /* perform special query access check */
+    if (!privileged && v && v->acs_rtn) {
+       status = (*v->acs_rtn)(q, Argv, cl);
+       if (status != MR_SUCCESS && status != MR_PERM)
+           return(status);
+       if (status == MR_SUCCESS)
+           privileged++;
+    }
+
+    return(privileged ? MR_SUCCESS : MR_PERM);
 }
 
+
+/* This routine caches info from the database.  Each query acl is stored
+ * in the query structure, and whether that acl contains everybody.
+ */
+
 check_query_access(q, argv, cl)
     struct query *q;
     char *argv[];
@@ -367,139 +522,122 @@ check_query_access(q, argv, cl)
 ##  int acl_id;
 ##  int exists;
 ##  int rowcount;
+##  int errorno;
 ##  static int def_uid;
     int status;
     int client_id;
     char *client_type;
 
-    /* get query access control list */
-    name = q->shortname;
-##  repeat retrieve (acl_id = capacls.list_id) where capacls.tag = @name
-##  inquire_equel (rowcount = "rowcount")
-    if (rowcount == 0) return(SMS_PERM);
-
     /* initialize default uid */
     if (def_uid == 0) {
 ##     retrieve (def_uid = users.users_id) where users.login = "default"
     }
 
-    com_err(whoami, 0, "checking for default access");
-    /* check for default access */
-##  range of m is members
-##  repeat retrieve (exists = any(m.#member_id where m.list_id = @acl_id and
-##                   m.member_type = "USER" and m.#member_id = def_uid))
-    if (exists) return(SMS_SUCCESS);
-
-    /* parse client name */
-    status = get_client(cl, &client_type, &client_id);
-    if (status != SMS_SUCCESS) return(status);
-
-    com_err(whoami, 0, "checking for client in acl");
-    /* see if client is in the list (or any of its sub-lists) */
-    exists = find_member(acl_id, client_type, client_id, 0);
-    return ((exists) ? SMS_SUCCESS : SMS_PERM);
+    /* get query access control list */
+    if (q->acl != 0)
+      acl_id = q->acl;
+    else {
+       name = q->shortname;
+##     retrieve (acl_id = capacls.list_id) where capacls.tag = name
+##     inquire_equel (rowcount = "rowcount", errorno = "errorno")
+       if (errorno != 0) return(MR_INGRES_ERR);
+       if (rowcount == 0) return(MR_PERM);
+       q->acl = acl_id;
+
+       /* check for default access */
+##     retrieve (exists = any(imembers.#member_id where
+##                            imembers.list_id = acl_id and
+##                            imembers.member_type = "USER" and
+##                            imembers.#member_id = def_uid))
+       q->everybody = exists;
+    }
+
+    if (q->everybody)
+      return(MR_SUCCESS);
+
+    if (get_client(cl, &client_type, &client_id) != MR_SUCCESS)
+      return(MR_PERM);
+    if (find_member("LIST", acl_id, client_type, client_id, 0))
+      return(MR_SUCCESS);
+    else
+      return(MR_PERM);
 ##}
 
+
 get_client(cl, client_type, client_id)
     client *cl;
     char **client_type;
     int *client_id;
-##{
-    struct krbname *krb;
-##  int member_id;
-##  char *name;
-##  int rowcount;
-
-    /* for now accept only null instances */
-    krb = &cl->kname;
-    if (krb->inst[0]) return(SMS_PERM);
-
-    /* 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
+{
+    if (cl->users_id > 0) {
+       *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(MR_SUCCESS);
     }
-       
-    /* make sure we found a users or string id */
-##  inquire_equel (rowcount = "rowcount")
-    if (rowcount == 0) return(SMS_PERM);
 
-    *client_id = member_id;
-    return(SMS_SUCCESS);
-##}
+    if (cl->client_id < 0) {
+       *client_id = -cl->users_id;
+       *client_type = "KERBEROS";
+       return(MR_SUCCESS);
+    }
+
+    return(MR_PERM);
+}
 
-##find_member(list_id, member_type, member_id, sq)
+##find_member(list_type, list_id, member_type, member_id)
+    char *list_type;
 ##  int list_id;
 ##  char *member_type;
 ##  int member_id;
-    struct save_queue *sq;
 ##{
-##  int exists;
-##  int sublist;
-    int child;
-    struct save_queue *sq_create();
+##  int exists, errorno;
 
-    /* see if client is a direct member of list */
-##  repeat retrieve (exists = any(m.#member_id where 
-##                               m.#list_id = @list_id and
-##                               m.#member_type = @member_type and 
-##                               m.#member_id = @member_id))
-    if (exists) return(1);
-
-    /* are there any sub-lists? */
-    com_err(whoami, 0, "checking for sub-lists");
-##  repeat retrieve (exists = any(m.#member_id where m.#list_id = @list_id and
-##                   m.#member_type = "LIST"))
-    if (!exists) return(0);
-
-    /* yes; now recurse through sublists */
-
-    /* create a save queue */
-    if (sq == (struct save_queue *)0) {
-       sq = sq_create();
-       child = 0;
-    } else {
-       child = 1;
-    }
+    if (!strcmp(strtrim(list_type), strtrim(member_type)) &&
+       list_id == member_id)
+       return(1);
 
-    /* save all sublist ids */
-##  range of m is members
-##  retrieve (sublist = m.#member_id) 
-##      where m.#list_id = list_id and m.#member_type = "LIST"
-##  {
-        sq_save_unique_data(sq, sublist);
-##  }
-
-    if (child) return;
-
-    com_err(whoami, 0, "checking for client in sub-lists");
-    /* 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);
-       if (exists) {
-           sq_destroy(sq);
-           return(1);
-       }
-    }
+    /* see if client is a direct member of list */
+##  repeat retrieve (exists = any(imembers.#member_id where 
+##                               imembers.#list_id = @list_id and
+##                               imembers.#member_type = @member_type and 
+##                               imembers.#member_id = @member_id))
+##  inquire_equel(errorno = "errorno")
+    if (errorno == 0)
+      return(exists);
+    else
+      return(0);
 ##}
 
-do_retrieve(q, qual, action, actarg)
+
+do_retrieve(q, pqual, psort, action, actarg)
     register struct query *q;
-    char *qual;
+    char *pqual;
+    char *psort;
     int (*action)();
     char *actarg;
 ##{
 ##  char *rvar;
 ##  char *rtable;
 ##  char *cqual;
+##  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, MR_NO_MEM, "setting up static argv");
+           exit(1);
+       }
+       for (i = 0; i < QMAXARGS; i++) {
+           if ((vaddrs[i] = malloc(QMAXARGSIZE)) == NULL) {
+               com_err(whoami, MR_NO_MEM, "setting up static argv");
+               exit(1);
+           }
+       }
+    }
 
     if (q->rvar) {
        rvar = q->rvar;
@@ -507,22 +645,41 @@ do_retrieve(q, qual, action, actarg)
 ##             range of rvar is rtable
     }
 
-    if (qual) {
-       cqual = qual;
-##      retrieve unique (param (q->tlist, q->vaddr)) where cqual
-##      {
-            (*action)(q->vcnt, q->vaddr, actarg);
-##      }
+    if (psort) {
+       csort = psort;
+       if (pqual) {
+           cqual = pqual;
+##          retrieve unique (param (q->tlist, vaddrs)) where cqual
+##                   sort by csort
+##          {
+                (*action)(q->vcnt, vaddrs, actarg);
+##          }
+       } else {
+##          retrieve unique (param (q->tlist, vaddrs))
+##                   sort by csort
+##          {
+                (*action)(q->vcnt, vaddrs, actarg);
+##          }
+       }
+
     } else {
-##      retrieve unique (param (q->tlist, q->vaddr))
-##      {
-            (*action)(q->vcnt, q->vaddr, actarg);
-##      }
+       if (pqual) {
+           cqual = pqual;
+##          retrieve unique (param (q->tlist, vaddrs)) where cqual
+##          {
+                (*action)(q->vcnt, vaddrs, actarg);
+##          }
+       } else {
+##          retrieve unique (param (q->tlist, vaddrs))
+##          {
+                (*action)(q->vcnt, vaddrs, actarg);
+##          }
+       }
     }
 
+    if (mr_errcode) return(mr_errcode);
 ##  inquire_equel (rowcount = "rowcount")
-
-    return ((rowcount == 0) ? SMS_NO_MATCH : SMS_SUCCESS);
+    return ((rowcount == 0) ? MR_NO_MATCH : MR_SUCCESS);
 ##}
 
 do_update(q, argv, qual, action, actarg)
@@ -535,7 +692,7 @@ do_update(q, argv, qual, action, actarg)
 ##  char *rvar;
 ##  char *rtable;
 ##  char *cqual;
-##  int rowcount;
+##  int errorno;
       
     rvar = q->rvar;
     rtable = q->rtable;
@@ -545,31 +702,35 @@ do_update(q, argv, qual, action, actarg)
 ##  replace rvar (param (q->tlist, argv))
 ##  where cqual
 
-    return(SMS_SUCCESS);
+    if (mr_errcode) return(mr_errcode);
+    return(MR_SUCCESS);
 ##}
 
-do_append(q, argv, action, actarg)
+do_append(q, argv, pqual, action, actarg)
     register struct query *q;
     char *argv[];
+    char *pqual;
     int (*action)();
     char *actarg;
 ##{
 ##  char *rvar;
 ##  char *rtable;
 ##  char *cqual;
+##  int errorno;
 
     rvar = q->rvar;
     rtable = q->rtable;
 ##  range of rvar is rtable
 
-    if (q->qual) {
-       cqual = q->qual;
+    if (pqual) {
+       cqual = pqual;
 ##      append to rtable (param (q->tlist, argv)) where cqual
     } else {
 ##      append to rtable (param (q->tlist, argv))
     }
 
-    return(SMS_SUCCESS);
+    if (mr_errcode) return(mr_errcode);
+    return(MR_SUCCESS);
 ##}
 
 do_delete(q, qual, action, actarg)
@@ -581,6 +742,7 @@ do_delete(q, qual, action, actarg)
 ##  char *rvar;
 ##  char *rtable;
 ##  char *cqual;
+##  int errorno;
 
     rvar = q->rvar;
     rtable = q->rtable;
@@ -589,18 +751,131 @@ do_delete(q, qual, action, actarg)
     cqual = qual;
 ##  delete rvar where cqual
 
-    return(SMS_SUCCESS);
+    if (mr_errcode) return(mr_errcode);
+    return(MR_SUCCESS);
 ##}
 
 
-/*
- * 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;
+##  repeat retrieve (value = values.#value) where values.#name = @name
+##  inquire_equel(rowcount = "rowcount")
+    if (rowcount != 1)
+       return(MR_NO_ID);
+
+##  retrieve (exists = any(tbl.name where tbl.name = value))
+##  inquire_equel(rowcount = "rowcount")
+    if (rowcount != 1)
+       return(MR_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 values (#value = @value) where values.#name = @name
+    return(MR_SUCCESS);
+##}
+
+
+/* Turn a kerberos name into the user's ID of the account that principal
+ * owns.  Sets the kerberos ID and user ID.
+ */
+
+int set_krb_mapping(name, login, ok, kid, uid)
+char *name;
+char *login;
+int ok;
+int *kid;
+int *uid;
+##{
+##  int u_id, k_id, rowcount;
+##  char *krbname;
+
+    krbname = name;
+    *kid = 0;
+    *uid = 0;
+
+##  repeat retrieve (u_id = krbmap.#users_id, k_id = krbmap.#string_id)
+##     where krbmap.string_id = strings.string_id and strings.string = @krbname
+##  inquire_equel (rowcount = "rowcount")
+    if (ingres_errno) return(mr_errcode);
+    
+    if (rowcount == 1) {
+       *kid = -k_id;
+       *uid = u_id;
+       return(MR_SUCCESS);
+    }
+
+    if (name_to_id(name, "STRINGS", &k_id) == MR_SUCCESS)
+      *kid = -k_id;
+
+    if (!ok) {
+       *uid = *kid;
+       return(MR_SUCCESS);
+    }
+
+    if (name_to_id(login, "USERS", uid) != MR_SUCCESS)
+      *uid = 0;
+
+    if (*kid == 0)
+      *kid = *uid;
+    if (ingres_errno) return(mr_errcode);
+    return(MR_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;
+#ifdef MULTIPROTOCOLS
+    extern int QueryCount1, QueryCount2;
+    extern struct query Queries1[], Queries2[];
+#else
+    extern int QueryCount2;
+    extern struct query Queries2[];
+#endif MULTIPROTOCOLS
+
+#define MAX(x,y) ((x) > (y) ? (x) : (y))
+
+#ifdef MULTIPROTOCOLS
+    for (i = 0; i < QueryCount1; i++) {
+       maxv = MAX(maxv, Queries1[i].vcnt);
+       maxa = MAX(maxa, Queries1[i].argc);
+    }
+#endif MULTIPROTOCOLS
+    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.082152 seconds and 4 git commands to generate.