]> andersk Git - moira.git/blobdiff - server/qrtn.qc
Clean up after Gretzinger: cl->kname is not valid unless cl->clname is
[moira.git] / server / qrtn.qc
index 31147897f8607a680143435225ccc95aad41e60e..10e31d36ddaaec52f4cb470f846815dfaf27c772 100644 (file)
+/*
+ *     $Source$
+ *     $Author$
+ *     $Header$
+ *
+ *     Copyright (C) 1987 by the Massachusetts Institute of Technology
+ *
+ *     $Log$
+ *     Revision 1.12  1987-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.
+ * 
+ */
+
+#ifndef lint
+static char *rcsid_qrtn_qc = "$Header$";
+#endif lint
+
 #include "query.h"
-#include "sms_private.h"
 #include "sms_server.h"
 
+#define SMS_SUCCESS 0
+
 char *Argv[16];
 
 static int ingres_errno = 0;
+extern char *whoami;
+
+/*
+ * ingerr: (supposedly) called when Ingres indicates an error.
+ * I have not yet been able to get this to work to intercept a
+ * database open error.
+ */
 
-static ingerr(num)
-       int *num;
+static int ingerr(num)
+    int *num;
 {
-       ingres_errno = SMS_INGRES_ERR; /* "Process lacks permission to */
-                                      /* alter device status.." */
-       return *num;
+    ingres_errno = SMS_INGRES_ERR;
+    com_err(whoami, SMS_INGRES_ERR, " code %d\n", ingres_errno);
+    return *num;
 }
 
-sms_open_database()
+int sms_open_database()
 {
-       register int i;
+    register int i;
 
-       /* initialize local argv */
-       for (i = 0; i < 16; i++)
-               Argv[i] = (char *)malloc(128);
+    /* initialize local argv */
+    for (i = 0; i < 16; i++)
+       Argv[i] = (char *)malloc(128);
 
-       IIseterr(ingerr);
+    IIseterr(ingerr);
        
-       ingres_errno = 0;
+    ingres_errno = 0;
        
-       /* open the database */
-##     ingres sms
-       return ingres_errno;
+    /* open the database */
+##  ingres sms
+    return ingres_errno;
 }
 
-sms_close_database()
+int sms_close_database()
 {
-##     exit
+##  exit
 }
 
-sms_process_query(name, argc, argv_ro, action, actarg)
-       char *name;
-       int argc;
-       char *argv_ro[];
-       int (*action)();
-       char *actarg;
+sms_check_access(cl, name, argc, argv_ro)
+    client *cl;
+    char *name;
+    int argc;
+    char *argv_ro[];
 {
-       register struct query *q;
-       register int i;
-       struct query *get_query_by_name();
-       char qual[128];
-
-       /* copy the arguments into a local argv that we can modify */
-       for (i = 0; i < argc; i++)
-               strcpy(Argv[i], argv_ro[i]);
-
-       q = get_query_by_name(name);
-
-       switch (q->type) {
-       case RETRIEVE:
-               if (q->qual) {
-                       build_qual(q->qual, q->argc, Argv, qual);
-                       do_retrieve_with_qual(q, qual, action, actarg);
-               } else
-                       do_retrieve(q, action, actarg);
-               break;
-
-       case UPDATE:
-               if (q->support_rtn) {
-                       if ((*q->support_rtn)(Argv, action, actarg) == -1) 
-                         break;
-               }
-               build_qual(q->qual, q->argc, &Argv[q->sargc], qual);
-               do_update(q, &Argv[q->sargc + q->argc], qual, action, actarg);
-               break;
-
-       case APPEND:
-               if (q->support_rtn) {
-                       if ((*q->support_rtn)(Argv, action, actarg) == -1) 
-                         break;
-               }
-               do_append(q, &Argv[q->sargc + q->argc], action, actarg);
-               break;
-
-       case DELETE:
-               if (q->support_rtn) {
-                       if ((*q->support_rtn)(Argv, action, actarg) == -1) 
-                         break;
-               }
-               build_qual(q->qual, q->argc, &Argv[q->sargc], qual);
-               do_delete(q, qual, action, actarg);
-               break;
-       }
+    register struct query *q;
+    register int argreq;
+    register int status;
+    register struct validate *v;
+    register int i;
+    register int privileged;
+    struct query *get_query_by_name();
+    int access_user();
+    int access_pop();
+    int access_list();
+
+    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 ||
+                                        v->pre_rtn == access_list))) 
+       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);
+    }
+
+    /* 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);
+    }
+
+    return(SMS_SUCCESS);
 }
 
-build_qual(fmt, argc, argv, qual)
-       char *fmt;
-       int argc;
-       char *argv[];
-       char *qual;
+sms_process_query(cl, name, argc, argv_ro, action, actarg)
+    client *cl;
+    char *name;
+    int argc;
+    char *argv_ro[];
+    int (*action)();
+    char *actarg;
 {
-       switch (argc) {
-       case 0:
-               strcpy(qual, fmt);
-               break;
-
-       case 1:
-               sprintf(qual, fmt, argv[0]);
-               break;
-
-       case 2:
-               sprintf(qual, fmt, argv[0], argv[1]);
-               break;
-
-       case 3:
-               sprintf(qual, fmt, argv[0], argv[1], argv[2]);
-               break;
-
-       case 4:
-               sprintf(qual, fmt, argv[0], argv[1], argv[2], argv[3]);
-               break;
+    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 *psort;
+##  char *table;
+    struct save_queue *sq;
+    struct query *get_query_by_name();
+    int sq_save_args();
+    struct save_queue *sq_create();
+    char *build_sort();
+    int access_user();
+    int access_pop();
+    int access_list();
+
+    /* copy the arguments into a local argv that we can modify */
+    for (i = 0; i < argc; i++)
+       strcpy(Argv[i], argv_ro[i]);
+
+    /* list queries command */
+    if (!strcmp(name, "_list_queries")) {
+       list_queries(action, actarg);
+       return(SMS_SUCCESS);
+    }
+
+    /* help query command */
+    if (!strcmp(name, "_help")) {
+       q = get_query_by_name(Argv[0]);
+       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);
+    if (q == (struct query *)0) return(SMS_NO_HANDLE);
+    v = q->validate;
+
+    /* check query access */
+    status = check_query_access(q, Argv, cl);
+    privileged = (status == SMS_SUCCESS) ? 1 : 0;
+    if (!privileged && !(status == SMS_PERM &&
+                        (v && (v->pre_rtn == access_user ||
+                               v->pre_rtn == access_pop ||
+                               v->pre_rtn == access_list))))
+       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);
+    }
+
+    /* 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 (q->type != RETRIEVE)
+##      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;
        }
-}
 
-do_retrieve(q, action, actarg)
-       register struct query *q;
-       int (*action)();
-        char *actarg;
-## {
-##     char *rvar;
-##     char *rtable;
-##     int rowcount;
-       char status[32];
-       char *sp = status;
+       /* build "where" clause if needed */
+       if (q->qual) {
+           build_qual(q->qual, q->argc, Argv, qual);
+           pqual = qual;
+       } else {
+           pqual = 0;
+       }
 
-       if (q->rvar) {
-               rvar = q->rvar;
-               rtable = q->rtable;
-##             range of rvar is rtable
+       /* build "sort" clause if needed */
+       if (v && v->valobj) {
+           psort = build_sort(v, sort);
+       } else {
+           psort = 0;
        }
 
-##     retrieve (param (q->tlist, q->vaddr))
-##     {
-              if (q->support_rtn)
-                      /* save result */
-                      (*q->support_rtn)(q->vcnt, q->vaddr, 0, 0); 
-              else
-                      (*action)(q->vcnt, q->vaddr, actarg);
-##     }
+       /* if there is a followup routine, then we must save the results */
+       /* of the first query for use by the followup routine */
+       /* if q->rvar = NULL, perform post_rtn only */
+       if (q->rvar) {
+           if (v && v->post_rtn) {
+               sq = sq_create();
+               status = do_retrieve(q, pqual, psort, sq_save_args, sq);
+               if (status != SMS_SUCCESS) {
+                   sq_destroy(sq);
+                   break;
+               }
+               status = (*v->post_rtn)(q, sq, v, action, actarg);
+           } 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);
+       }
 
-##     inquire_equel (rowcount = "rowcount")
+       break;
 
-       if (q->support_rtn) {
-               /* process and send saved results */
-               (*q->support_rtn)(0, 0, &q->vnames[q->argc], action, actarg);
+    case UPDATE:
+       /* see if row already exists */
+       if (v->field) {
+           status = validate_row(q, Argv, v);
+           if (status != SMS_EXISTS) break;
        }
 
-#ifdef notdef
-       sprintf(status, "(%d row%s)", rowcount, (rowcount == 1)? "" : "s");
-       (*action)(1, &sp, actarg);
-#endif notdef
-## }
-
-do_retrieve_with_qual(q, qual, action, actarg)
-       register struct query *q;
-       char *qual;
-       int (*action)();
-        char *actarg;
-## {
-##     char *rvar;
-##     char *rtable;
-##     char *cqual;
-##     int rowcount;
-       char status[32];
-       char *sp = status;
-      
+       /* build "where" clause and perform update */
+       /* if q->rvar = NULL, perform post_rtn only */
        if (q->rvar) {
-               rvar = q->rvar;
-               rtable = q->rtable;
-##             range of rvar is rtable
+           build_qual(q->qual, q->argc, Argv, qual);
+           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
        }
 
-       cqual = qual;
-##     retrieve (param (q->tlist, q->vaddr))
-##      where cqual
-##     {
-               if (q->support_rtn)
-                       (*q->support_rtn)(q->vcnt, q->vaddr, 0, 0);
-               else
-                       (*action)(q->vcnt, q->vaddr, actarg);
-##     }
+       /* execute followup routine (if any) */
+       if (v->post_rtn) status = (*v->post_rtn)(q, Argv);
 
-##     inquire_equel (rowcount = "rowcount")
+       break;
 
-       if (q->support_rtn) {
-               (*q->support_rtn)(0, 0, &q->vnames[q->argc], action, actarg);
+    case APPEND:
+       /* see if row already exists */
+       if (v->field) {
+           status = validate_row(q, Argv, v);
+           if (status != SMS_NO_MATCH) break;
        }
 
-#ifdef notdef
-       sprintf(status, "(%d row%s)", rowcount, (rowcount == 1)? "" : "s");
-       (*action)(1, &sp, actarg);
-#endif notdef
-## }
+       /* increment id number if necessary */
+       if (v->object_id) set_next_object_id(v->object_id);
 
-do_update(q, argv, qual, action, actarg)
-       register struct query *q;
-       char *argv[];
-       char *qual;
-       int (*action)();
-        char *actarg;
-## {
-##    char *rvar;
-##    char *rtable;
-##    char *cqual;
-##    int rowcount;
-       char status[32];
-       char *sp = status;
-      
-       rvar = q->rvar;
-       rtable = q->rtable;
-##     range of rvar is rtable
+       /* build "where" clause if needed */
+       if (q->qual) {
+           build_qual(q->qual, q->argc, Argv, qual);
+           pqual = qual;
+       } else {
+           pqual = 0;
+       }
 
-       cqual = qual;
-##     replace rvar (param (q->tlist, argv))
-##      where cqual
+       /* perform the append */
+       /* if q->rvar = NULL, perform post_rtn only */
+       if (q->rvar) {
+           status = do_append(q, &Argv[q->argc], pqual, action, actarg);
+           if (status != SMS_SUCCESS) break;
+           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);
+       break;
+
+    case DELETE:
+       /* see if row already exists */
+       if (v->field) {
+           status = validate_row(q, Argv, v);
+           if (status != SMS_EXISTS) break;
+       }
 
-##     inquire_equel (rowcount = "rowcount")
-       sprintf(status, "(%d row%s)", rowcount, (rowcount == 1)? "" : "s");
-       (*action)(1, &sp, actarg);
-## }
+       /* build "where" clause and perform delete */
+       /* if q->rvar = NULL, perform post_rtn only */
+       if (q->rvar) {
+           build_qual(q->qual, q->argc, Argv, qual);
+           status = do_delete(q, qual, action, actarg);
+           if (status != SMS_SUCCESS) break;
+           table = q->rtable;
+##         repeat replace tblstats (deletes = tblstats.deletes + 1,
+##                                  modtime = "now")
+##             where tblstats.#table = @table
+       }
 
-do_append(q, argv, action, actarg)
-       register struct query *q;
-       char *argv[];
-       int (*action)();
-        char *actarg;
-## {
-##     char *rvar;
-##     char *rtable;
-##     int rowcount;
-       char status[32];
-       char *sp = status;
+       /* execute followup routine */
+       if (v->post_rtn) status = (*v->post_rtn)(q, Argv);
+       break;
 
-       rvar = q->rvar;
-       rtable = q->rtable;
-##      range of rvar is rtable
+    }
 
-##      append to rtable (param (q->tlist, argv))
+    if (q->type != RETRIEVE) {
+        if (status == SMS_SUCCESS) {
+##          end transaction
+       } else {
+##          abort
+       }
+    }
 
-#ifdef notdef
-##      inquire_equel (rowcount = "rowcount")
-       sprintf(status, "(%d row%s)", rowcount, (rowcount == 1)? "" : "s");
-       (*action)(1, &sp, actarg);
-#endif notdef
-## }
+    if (status != SMS_SUCCESS && log_flags & LOG_RES)
+       com_err(whoami, status, " (Query failed)");
+    return(status);
+}
 
-do_delete(q, qual, action, actarg)
-       register struct query *q;
+build_qual(fmt, argc, argv, qual)
+       char *fmt;
+       int argc;
+       char *argv[];
        char *qual;
-       int (*action)();
-        char *actarg;
-## {
-##      char *rvar;
-##      char *rtable;
-##      char *cqual;
-##      int rowcount;
-       char status[32];
-       char *sp = status;
-
-       rvar = q->rvar;
-       rtable = q->rtable;
-##      range of rvar is rtable
-
-       cqual = qual;
-##      delete rvar where cqual
+{
+    register char *c;
+    register int i;
+    char *args[4];
+
+    c = fmt;
+    for (i = 0; i < argc; i++) {
+       c = (char *)index(c, '%');
+       if (c++ == (char *)0) return(SMS_ARGS);
+       if (*c == 's')
+           args[i] = argv[i];
+       else if (*c == 'd')
+           *(int *)&args[i] = *(int *)argv[i]; /* sigh */
+       else
+           return(SMS_INGRES_ERR);
+    }
+
+    switch (argc) {
+    case 0:
+       strcpy(qual, fmt);
+       break;
+
+    case 1:
+       sprintf(qual, fmt, args[0]);
+       break;
+
+    case 2:
+       sprintf(qual, fmt, args[0], args[1]);
+       break;
+
+    case 3:
+       sprintf(qual, fmt, args[0], args[1], args[2]);
+       break;
+
+    case 4:
+       sprintf(qual, fmt, args[0], args[1], args[2], args[3]);
+       break;
+    }
+}
 
-#ifdef notdef
-##      inquire_equel (rowcount = "rowcount")
-       sprintf(status, "(%d row%s)", rowcount, (rowcount == 1)? "" : "s");
-       (*action)(1, &sp, actarg);
-#endif notdef
-## }
+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++;
+    }
 
-/* Support Queries */
+    return ((*sort) ? sort : 0);
+}
 
-support_alis(argv, action, actarg)
-       char *argv[];
-       int (*action)();
-        char *actarg;
-## {
-##     static int list_id;
-
-##     range of tbi is tbinfo
-
-##     repeat retrieve (list_id = tbi.value1) where tbi.table = "list"
-       list_id++;
-##     repeat replace tbi (value1 = @list_id) where tbi.table = "list"
-
-       argv[0] = (char *)&list_id;
-## }
-
-/**
- ** support_member():
- **
- ** support for ADD_MEMBER_TO_LIST
- ** support for DELETE_MEMBER_FROM_LIST
- ** support for UPDATE_MEMBER_STATUS
- **
- **           Input                     Output
- ** argv[0]   List Type       argv[4]   List ID
- ** argv[1]   List Name       argv[5]   Member ID
- ** argv[2]   Member Type     argv[6]   Member Type
- ** argv[3]   Member Name
- **/
-
-support_member(argv, action, actarg)
-       char *argv[];
-       int (*action)();
-        char *actarg;
-## {
-##    char *list_name;
-##    char *list_type;
-##    char *member_name;
-##    char *member_type;
-##    int list_id;
-##    int value;
-##    int rowcount;
-      char errmsg[64];
-      char *p_errmsg = errmsg;
-
-      list_type = argv[0];
-      list_name = argv[1];
-      member_type = argv[2];
-      member_name = argv[3];
-
-##    range of l is list
-##    repeat retrieve (list_id = l.id) 
-##        where l.name = @list_name and l.type = @list_type
-      sprintf(argv[4], "%d", list_id);
-
-      if (!strcmp(member_type, "acl") || !strcmp(member_type, "group") ||
-         !strcmp(member_type, "mail")) {
-##       repeat retrieve (value = l.id)
-##            where l.name = @member_name and l.type = @member_type
-##       inquire_equel (rowcount = "rowcount")
-         if (rowcount == 0) {
-             sprintf(errmsg, "(No such list: %s)", member_name);
-             (*action)(1, p_errmsg, actarg);
-             return(-1);
-           }
-       } else if (!strcmp(member_type, "user")) {
-##        range of u is users
-##        repeat retrieve (value = u.id) where u.login = @member_name
-##       inquire_equel (rowcount = "rowcount")
-         if (rowcount == 0) {
-             sprintf(errmsg, "(No such user: %s)", member_name);
-             (*action)(1, p_errmsg, actarg);
-             return(-1);
-           }
-       } else if (!strcmp(member_type, "string")) {
-##       range of s is strings
-##       repeat retrieve (value = s.id) where s.string = @member_name
-##        inquire_equel (rowcount = "rowcount")
-         if (rowcount == 0) {
-##            range of tbi is tbinfo
-##            retrieve (value = tbi.value1) where tbi.table = "strings"
-             value++;
-##            replace tbi (value1 = value) where tbi.table = "strings"
-##           append to strings (id = value, string = member_name)
-           }
+check_query_access(q, argv, cl)
+    struct query *q;
+    char *argv[];
+    client *cl;
+##{
+##  char *name;
+##  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", errorno = "errorno")
+    if (errorno != 0) return(SMS_INGRES_ERR);
+    if (rowcount == 0) return(SMS_PERM);
+
+    /* initialize default uid */
+    if (def_uid == 0) {
+##     retrieve (def_uid = users.users_id) where users.login = "default"
+    }
+
+    /* 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);
+
+    /* 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_client(cl, client_type, client_id)
+    client *cl;
+    char **client_type;
+    int *client_id;
+##{
+    struct krbname *krb;
+##  int member_id;
+##  char *name;
+##  int rowcount;
+
+    if (cl->clname == NULL)
+       return SMS_PERM;
+    
+    /* for now ignore instances */
+    krb = &cl->kname;
+
+    /* 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_type = "USER";
+    } else {
+       /* otherwise use string_id */
+       name = cl->clname;
+##     repeat retrieve (member_id = strings.string_id) 
+##          where strings.string = @name
+       *client_type = "STRING";
+    }
+       
+    /* 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);
+##}
+
+##find_member(list_id, member_type, member_id, sq)
+##  int list_id;
+##  char *member_type;
+##  int member_id;
+    struct save_queue *sq;
+##{
+##  int exists;
+##  int sublist;
+    int child;
+    struct save_queue *sq_create();
+
+    /* 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? */
+##  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;
+    }
+
+    /* 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;
+
+    /* 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);
+       }
+    }
+##}
+
+do_retrieve(q, pqual, psort, action, actarg)
+    register struct query *q;
+    char *pqual;
+    char *psort;
+    int (*action)();
+    char *actarg;
+##{
+##  char *rvar;
+##  char *rtable;
+##  char *cqual;
+##  char *csort;
+##  int rowcount;
+##  int errorno;
+
+    if (q->rvar) {
+       rvar = q->rvar;
+       rtable = q->rtable;
+##             range of rvar is rtable
+    }
+
+    if (psort) {
+       csort = psort;
+       if (pqual) {
+           cqual = pqual;
+##          retrieve unique (param (q->tlist, q->vaddr)) where cqual
+##                   sort by csort
+##          {
+                (*action)(q->vcnt, q->vaddr, actarg);
+##          }
        } else {
-         sprintf(errmsg, "(Unknown member type: %s)", member_type);
-         (*action)(1, p_errmsg, actarg);
-         return(-1);
+##          retrieve unique (param (q->tlist, q->vaddr))
+##                   sort by csort
+##          {
+                (*action)(q->vcnt, q->vaddr, actarg);
+##          }
        }
 
-      sprintf(argv[5], "%d", value);
-      strcpy(argv[6], member_type);
-## }
-
-/**
- ** support for GET_LIST_MEMBERS
- **
- **           Input           Output
- ** argv[0]   Member Type     Member Type
- ** argv[1]   Member Id       Member Name (ACL, Group, Maillist, User, String)
- ** argv[2]   Member Status   Member Status
- **
- ** This routine performs two functions:
- **   When called with argc > 0, it copies and saves argv in a queue
- **   When called with argc = 0, it does post-processing on the saved
- **     data, and sends the data to the client using the supplied action
- **     routine.
- **/
-
-support_gmol(argc, argv, vnames, action, actarg)
-       int argc;
-       char *argv[];
-       char *vnames[];
-       int (*action)();
-        char *actarg;
-## {
-##      char *member_type;
-##      int member_id;
-##      char member_name[33];
-       char **sargv;
-       char *nargv[3];
-       register int n;
-       static struct save_queue *sq = (struct save_queue *)0;
-       struct save_queue *sq_create();
-
-       if (argc > 0) {
-               if (sq == (struct save_queue *)0) {
-                       sq = sq_create();
-               }
-               sargv = (char **)malloc(3 * sizeof (char *));
-               /* copy member_type */
-               n = strlen(argv[0]) + 1;
-               sargv[0] = (char *)malloc(n);
-               bcopy(argv[0], sargv[0], n);
-               /* copy member_id */
-               sargv[1] = (char *)malloc(sizeof (int));
-               *(int *)sargv[1] = *(int *)argv[1];
-               /* copy member_status */
-               n = strlen(argv[2]) + 1;
-               sargv[2] = (char *)malloc(n);
-               bcopy(argv[2], sargv[2], n);
-               /* store data */
-               sq_save_data(sq, sargv);
-               return;
+    } else {
+       if (pqual) {
+           cqual = pqual;
+##          retrieve unique (param (q->tlist, q->vaddr)) where cqual
+##          {
+                (*action)(q->vcnt, q->vaddr, actarg);
+##          }
+       } else {
+##          retrieve unique (param (q->tlist, q->vaddr))
+##          {
+                (*action)(q->vcnt, q->vaddr, actarg);
+##          }
        }
+    }
 
-       while (sq_get_data(sq, &sargv)) {
-               member_type = sargv[0];
-               member_id = *(int *)sargv[1];
-
-               nargv[0] = member_type;
-               nargv[1] = member_name;
-               nargv[2] = sargv[2];
-
-               if (!strcmp(member_type, "acl") ||
-                   !strcmp(member_type, "group") ||
-                   !strcmp(member_type, "mail")) {
-##                     range of l is list
-##                     repeat retrieve (member_name = l.name)
-##                     where l.id = @member_id
-               } else if (!strcmp(member_type, "user")) {
-##                     range of u is users
-##                     repeat retrieve (member_name = u.login) 
-##                             where u.id = @member_id
-               } else if (!strcmp(member_type, "string")) {
-##                     range of s is strings
-##                     repeat retrieve (member_name = s.string)
-##                     where s.id = @member_id
-               } else {
-                       sprintf(member_name, "%d", member_id);
-               }
+##  inquire_equel (rowcount = "rowcount", errorno = "errorno")
+    if (errorno != 0) return(SMS_INGRES_ERR);
+    return ((rowcount == 0) ? SMS_NO_MATCH : SMS_SUCCESS);
+##}
 
-               (*action)(3, nargv, vnames, actarg);
-               free(sargv[0]);
-               free(sargv[1]);
-               free(sargv[2]);
-       }
+do_update(q, argv, qual, action, actarg)
+    register struct query *q;
+    char *argv[];
+    char *qual;
+    int (*action)();
+    char *actarg;
+##{
+##  char *rvar;
+##  char *rtable;
+##  char *cqual;
+##  int rowcount;
+##  int errorno;
+      
+    rvar = q->rvar;
+    rtable = q->rtable;
+##  range of rvar is rtable
+
+    cqual = qual;
+##  replace rvar (param (q->tlist, argv))
+##  where cqual
+
+##  inquire_equel (errorno = "errorno")
+    if (errorno != 0) return(SMS_INGRES_ERR);
+    return(SMS_SUCCESS);
+##}
+
+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 (pqual) {
+       cqual = pqual;
+##      append to rtable (param (q->tlist, argv)) where cqual
+    } else {
+##      append to rtable (param (q->tlist, argv))
+    }
+
+##  inquire_equel (errorno = "errorno")
+    if (errorno != 0) return(SMS_INGRES_ERR);
+    return(SMS_SUCCESS);
+##}
+
+do_delete(q, qual, action, actarg)
+    register struct query *q;
+    char *qual;
+    int (*action)();
+    char *actarg;
+##{
+##  char *rvar;
+##  char *rtable;
+##  char *cqual;
+##  int errorno;
+
+    rvar = q->rvar;
+    rtable = q->rtable;
+##  range of rvar is rtable
+
+    cqual = qual;
+##  delete rvar where cqual
+
+##  inquire_equel (errorno = "errorno")
+    if (errorno != 0) return(SMS_INGRES_ERR);
+    return(SMS_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:
+ */
 
-       sq_destroy(sq);
-       sq = (struct save_queue *)0;
-## }
This page took 0.07062 seconds and 4 git commands to generate.