* $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.
+ * 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.
static int ingerr(num)
int *num;
{
- ingres_errno = SMS_INGRES_ERR;
- com_err(whoami, SMS_INGRES_ERR, " code %d\n", ingres_errno);
- 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;
+
+ if (first_open) {
+ first_open = 0;
- /* 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] = malloc(ARGLEN);
- IIseterr(ingerr);
+ 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();
- 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);
+ ingres_errno = 0;
+ mr_errcode = 0;
- /* validate arguments */
- if (v && v->valobj) {
- status = validate_fields(q, Argv, v->valobj, v->objcnt);
- if (status != SMS_SUCCESS) return(status);
- }
+ q = get_query_by_name(name, cl->args->mr_version_no);
+ if (q == (struct query *)0)
+ return(MR_NO_HANDLE);
- /* 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);
+ 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;
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 *psort;
-## char *table;
+## char *table, *rvar;
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]);
+ 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 (!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);
+ 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;
}
- 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;
+ if (status != MR_EXISTS) break;
}
/* build "where" clause if needed */
if (v && v->post_rtn) {
sq = sq_create();
status = do_retrieve(q, pqual, psort, sq_save_args, sq);
- if (status != SMS_SUCCESS) {
+ 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, psort, action, actarg);
}
- if (status != SMS_SUCCESS) break;
- table = q->rtable;
-## 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;
/* 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->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;
+ incremental_after(q->rtable, qual, argv_ro);
+ if (status != MR_SUCCESS) break;
+ flush_name(argv_ro[0], q->rtable);
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;
/* 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) {
/* perform the append */
/* 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 != SMS_SUCCESS) break;
+ 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")
}
/* 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->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;
+ rvar = q->rvar;
+## range of rvar is table
+ incremental_before(q->rtable, qual, argv_ro);
+ status = do_delete(q, qual, action, actarg);
+ 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;
}
+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 (q->type != RETRIEVE) {
- if (status == SMS_SUCCESS) {
-## end transaction
+ 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 {
-## abort
+ if (ingres_errno != INGRES_DEADLOCK) {
+## abort /* it never happened */
+ }
+ incremental_flush();
}
+## set lockmode session where readlock = system
}
- if (status != SMS_SUCCESS && log_flags & LOG_RES)
+ if (status != MR_SUCCESS && log_flags & LOG_RES)
com_err(whoami, status, " (Query failed)");
return(status);
}
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) {
sprintf(qual, fmt, args[0], args[1], args[2], args[3]);
break;
}
+ return(MR_SUCCESS);
}
char *
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[];
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);
+ /* 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;
+ }
- /* parse client name */
- status = get_client(cl, &client_type, &client_id);
- if (status != SMS_SUCCESS) return(status);
+ if (q->everybody)
+ return(MR_SUCCESS);
- /* 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);
+ 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;
-
- 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
+{
+ 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? */
-## 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;
-
- /* 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, pqual, psort, action, actarg)
register struct query *q;
char *pqual;
## 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;
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);
## }
}
}
-## inquire_equel (rowcount = "rowcount", errorno = "errorno")
- if (errorno != 0) return(SMS_INGRES_ERR);
- return ((rowcount == 0) ? SMS_NO_MATCH : SMS_SUCCESS);
+ if (mr_errcode) return(mr_errcode);
+## inquire_equel (rowcount = "rowcount")
+ return ((rowcount == 0) ? MR_NO_MATCH : MR_SUCCESS);
##}
do_update(q, argv, qual, action, actarg)
## char *rvar;
## char *rtable;
## char *cqual;
-## int rowcount;
## int errorno;
rvar = q->rvar;
## replace rvar (param (q->tlist, argv))
## where cqual
-## inquire_equel (errorno = "errorno")
- if (errorno != 0) return(SMS_INGRES_ERR);
- return(SMS_SUCCESS);
+ if (mr_errcode) return(mr_errcode);
+ return(MR_SUCCESS);
##}
do_append(q, argv, pqual, action, actarg)
## append to rtable (param (q->tlist, argv))
}
-## inquire_equel (errorno = "errorno")
- if (errorno != 0) return(SMS_INGRES_ERR);
- return(SMS_SUCCESS);
+ if (mr_errcode) return(mr_errcode);
+ return(MR_SUCCESS);
##}
do_delete(q, qual, action, actarg)
cqual = qual;
## delete rvar where cqual
-## inquire_equel (errorno = "errorno")
- if (errorno != 0) return(SMS_INGRES_ERR);
- 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);
+ }
+}