X-Git-Url: http://andersk.mit.edu/gitweb/moira.git/blobdiff_plain/6ec81cbf62701f709b10d42fcdd90e54c53b3ccb..67805159a972397342c342ee735c8acd640e1399:/server/qrtn.qc diff --git a/server/qrtn.qc b/server/qrtn.qc index 10e31d36..55559c62 100644 --- a/server/qrtn.qc +++ b/server/qrtn.qc @@ -3,44 +3,9 @@ * $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 + * . * */ @@ -48,15 +13,23 @@ static char *rcsid_qrtn_qc = "$Header$"; #endif lint +#include #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. @@ -67,88 +40,91 @@ 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; + 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; @@ -157,85 +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 *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 */ @@ -260,21 +216,18 @@ sms_process_query(cl, name, argc, argv_ro, action, actarg) 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; @@ -283,23 +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->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; @@ -307,11 +265,14 @@ 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) { @@ -324,8 +285,16 @@ sms_process_query(cl, name, argc, argv_ro, action, actarg) /* 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") @@ -333,43 +302,78 @@ 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: /* 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); } @@ -383,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) { @@ -417,6 +422,7 @@ build_qual(fmt, argc, argv, qual) sprintf(qual, fmt, args[0], args[1], args[2], args[3]); break; } + return(MR_SUCCESS); } char * @@ -444,6 +450,69 @@ build_sort(v, sort) 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[]; @@ -459,123 +528,87 @@ check_query_access(q, argv, cl) 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; @@ -589,6 +622,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, 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; @@ -600,37 +649,37 @@ 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); ## } } } -## 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) @@ -643,7 +692,6 @@ do_update(q, argv, qual, action, actarg) ## char *rvar; ## char *rtable; ## char *cqual; -## int rowcount; ## int errorno; rvar = q->rvar; @@ -654,9 +702,8 @@ do_update(q, argv, qual, action, actarg) ## 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) @@ -682,9 +729,8 @@ 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) @@ -705,20 +751,131 @@ 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); + } +}