6 * Copyright (C) 1987 by the Massachusetts Institute of Technology
9 * Revision 1.8 1987-08-10 16:22:26 mike
10 * wesommer modified error reporting.
12 * Revision 1.7 87/08/04 01:49:20 wesommer
13 * Rearranged messages.
15 * Revision 1.6 87/08/04 01:30:54 wesommer
16 * Mike's changes; checked in prior to working over messages.
18 * Revision 1.5 87/06/21 16:37:58 wesommer
19 * Changed include files, reindented things.
22 * Revision 1.4 87/06/08 05:03:27 wesommer
23 * Reindented; added header and trailer.
28 static char *rcsid_qrtn_qc = "$Header$";
32 #include "sms_server.h"
38 static int ingres_errno = 0;
42 * ingerr: (supposedly) called when Ingres indicates an error.
43 * I have not yet been able to get this to work to intercept a
44 * database open error.
47 static int ingerr(num)
50 ingres_errno = SMS_INGRES_ERR;
51 com_err(whoami, SMS_INGRES_ERR, " code %d\n", ingres_errno);
55 int sms_open_database()
59 /* initialize local argv */
60 for (i = 0; i < 16; i++)
61 Argv[i] = (char *)malloc(128);
67 /* open the database */
72 int sms_close_database()
77 sms_check_access(cl, name, argc, argv_ro)
83 register struct query *q;
86 register struct validate *v;
88 register int privileged;
89 struct query *get_query_by_name();
93 q = get_query_by_name(name);
94 if (q == (struct query *)0) return(SMS_NO_HANDLE);
97 /* copy the arguments into a local argv that we can modify */
98 for (i = 0; i < argc; i++)
99 strcpy(Argv[i], argv_ro[i]);
101 /* check initial query access */
102 status = check_query_access(q, Argv, cl);
103 privileged = (status == SMS_SUCCESS) ? 1 : 0;
104 if (status != SMS_SUCCESS && !(v && (v->pre_rtn == access_user ||
105 v->pre_rtn == access_pop)))
108 /* check argument count */
110 if (q->type == UPDATE || q->type == APPEND) argreq += q->vcnt;
111 if (argc != argreq) return(SMS_ARGS);
113 /* validate arguments */
114 if (v && v->valobj) {
115 status = validate_fields(q, Argv, v->valobj, v->objcnt);
116 if (status != SMS_SUCCESS) return(status);
119 /* perform special query access check */
120 if (v && v->pre_rtn) {
121 status = (*v->pre_rtn)(q, Argv, cl, 1);
122 if (status != SMS_SUCCESS && (status != SMS_PERM || !privileged))
129 sms_process_query(cl, name, argc, argv_ro, action, actarg)
137 register struct query *q;
141 register struct validate *v;
146 struct save_queue *sq;
147 struct query *get_query_by_name();
149 struct save_queue *sq_create();
152 /* copy the arguments into a local argv that we can modify */
153 for (i = 0; i < argc; i++)
154 strcpy(Argv[i], argv_ro[i]);
156 /* list queries command */
157 if (!strcmp(name, "_list_queries")) {
158 list_queries(action, actarg);
162 /* help query command */
163 if (!strcmp(name, "_help")) {
164 q = get_query_by_name(Argv[0]);
165 if (q == (struct query *)0) return(SMS_NO_HANDLE);
166 help_query(q, action, actarg);
170 /* get query structure, return error if named query does not exist */
171 q = get_query_by_name(name);
172 if (q == (struct query *)0) return(SMS_NO_HANDLE);
175 /* check query access */
176 status = check_query_access(q, Argv, cl);
177 privileged = (status == SMS_SUCCESS) ? 1 : 0;
178 if (status != SMS_SUCCESS && !(v && (v->pre_rtn == access_user)))
181 /* check argument count */
183 if (q->type == UPDATE || q->type == APPEND) argreq += q->vcnt;
184 if (argc != argreq) return(SMS_ARGS);
186 /* validate arguments */
187 if (v && v->valobj) {
188 status = validate_fields(q, Argv, v->valobj, v->objcnt);
189 if (status != SMS_SUCCESS) return(status);
192 /* perform any special query pre-processing */
193 if (v && v->pre_rtn) {
194 status = (*v->pre_rtn)(q, Argv, cl, 0);
195 if (status != SMS_SUCCESS && (status != SMS_PERM || !privileged))
203 /* for queries that do not permit wildcarding, check if row
206 status = validate_row(q, Argv, v);
207 if (status != SMS_EXISTS) break;
210 /* build "where" clause if needed */
212 build_qual(q->qual, q->argc, Argv, qual);
218 /* if there is a followup routine, then we must save the results */
219 /* of the first query for use by the followup routine */
220 /* if q->rtable = NULL, perform post_rtn only */
221 if (table = q->rtable) {
222 if (v && v->post_rtn) {
224 status = do_retrieve(q, pqual, sq_save_args, sq);
225 if (status != SMS_SUCCESS) {
229 status = (*v->post_rtn)(q, sq, v, action, actarg);
231 /* normal retrieve */
232 status = do_retrieve(q, pqual, action, actarg);
234 if (status != SMS_SUCCESS) break;
235 ## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
236 ## where tblstats.#table = @table
238 status = (*v->post_rtn)(q, Argv, action, actarg);
244 /* see if row already exists */
246 status = validate_row(q, Argv, v);
247 if (status != SMS_EXISTS) break;
250 /* build "where" clause and perform update */
251 /* if q->rtable = NULL, perform post_rtn only */
252 if (table = q->rtable) {
253 build_qual(q->qual, q->argc, Argv, qual);
254 status = do_update(q, &Argv[q->argc], qual, action, actarg);
255 if (status != SMS_SUCCESS) break;
256 ## repeat replace tblstats (updates = tblstats.updates + 1,
258 ## where tblstats.#table = @table
261 /* execute followup routine (if any) */
262 if (v->post_rtn) status = (*v->post_rtn)(q, Argv);
267 /* see if row already exists */
269 status = validate_row(q, Argv, v);
270 if (status != SMS_NO_MATCH) break;
273 /* increment id number if necessary */
274 if (v->object_id) set_next_object_id(v->object_id);
276 /* perform the append */
277 /* if q->rtable = NULL, perform post_rtn only */
278 if (table = q->rtable) {
279 status = do_append(q, &Argv[q->argc], action, actarg);
280 if (status != SMS_SUCCESS) break;
281 ## repeat replace tblstats (appends = tblstats.appends + 1,
283 ## where tblstats.#table = @table
286 /* execute followup routine */
287 if (v->post_rtn) status = (*v->post_rtn)(q, Argv);
291 /* see if row already exists */
293 status = validate_row(q, Argv, v);
294 if (status != SMS_EXISTS) break;
297 /* build "where" clause and perform delete */
298 /* if q->rtable = NULL, perform post_rtn only */
299 if (table = q->rtable) {
300 build_qual(q->qual, q->argc, Argv, qual);
301 status = do_delete(q, qual, action, actarg);
302 if (status != SMS_SUCCESS) break;
303 ## repeat replace tblstats (deletes = tblstats.deletes + 1,
305 ## where tblstats.#table = @table
308 /* execute followup routine */
309 if (v->post_rtn) status = (*v->post_rtn)(q, Argv);
314 if (status == SMS_SUCCESS)
319 if (status != SMS_SUCCESS && log_flags & LOG_RES)
320 com_err(whoami, status, " (Query failed)");
324 build_qual(fmt, argc, argv, qual)
335 for (i = 0; i < argc; i++) {
336 c = (char *)index(c, '%');
337 if (c++ == (char *)0) return(SMS_ARGS);
341 *(int *)&args[i] = *(int *)argv[i]; /* sigh */
343 return(SMS_INGRES_ERR);
352 sprintf(qual, fmt, args[0]);
356 sprintf(qual, fmt, args[0], args[1]);
360 sprintf(qual, fmt, args[0], args[1], args[2]);
364 sprintf(qual, fmt, args[0], args[1], args[2], args[3]);
369 check_query_access(q, argv, cl)
378 ## static int def_uid;
383 /* get query access control list */
385 ## repeat retrieve (acl_id = capacls.list_id) where capacls.tag = @name
386 ## inquire_equel (rowcount = "rowcount")
387 if (rowcount == 0) return(SMS_PERM);
389 /* initialize default uid */
391 ## retrieve (def_uid = users.users_id) where users.login = "default"
394 /* check for default access */
395 ## range of m is members
396 ## repeat retrieve (exists = any(m.#member_id where m.list_id = @acl_id and
397 ## m.member_type = "USER" and m.#member_id = def_uid))
398 if (exists) return(SMS_SUCCESS);
400 /* parse client name */
401 status = get_client(cl, &client_type, &client_id);
402 if (status != SMS_SUCCESS) return(status);
404 /* see if client is in the list (or any of its sub-lists) */
405 exists = find_member(acl_id, client_type, client_id, 0);
406 return ((exists) ? SMS_SUCCESS : SMS_PERM);
409 get_client(cl, client_type, client_id)
419 /* for now accept only null instances */
421 if (krb->inst[0]) return(SMS_PERM);
423 /* if client is from local realm, get users_id */
424 if (!strcmp(krb->realm, krb_realm)) {
426 ## repeat retrieve (member_id = users.users_id) where users.login = @name
427 *client_type = "USER";
429 /* otherwise use string_id */
431 ## repeat retrieve (member_id = strings.string_id)
432 ## where strings.string = @name
433 *client_type = "STRING";
436 /* make sure we found a users or string id */
437 ## inquire_equel (rowcount = "rowcount")
438 if (rowcount == 0) return(SMS_PERM);
440 *client_id = member_id;
444 ##find_member(list_id, member_type, member_id, sq)
446 ## char *member_type;
448 struct save_queue *sq;
453 struct save_queue *sq_create();
455 /* see if client is a direct member of list */
456 ## repeat retrieve (exists = any(m.#member_id where
457 ## m.#list_id = @list_id and
458 ## m.#member_type = @member_type and
459 ## m.#member_id = @member_id))
460 if (exists) return(1);
462 /* are there any sub-lists? */
463 ## repeat retrieve (exists = any(m.#member_id where m.#list_id = @list_id and
464 ## m.#member_type = "LIST"))
465 if (!exists) return(0);
467 /* yes; now recurse through sublists */
469 /* create a save queue */
470 if (sq == (struct save_queue *)0) {
477 /* save all sublist ids */
478 ## range of m is members
479 ## retrieve (sublist = m.#member_id)
480 ## where m.#list_id = list_id and m.#member_type = "LIST"
482 sq_save_unique_data(sq, sublist);
487 /* at top-level, check sub-lists for client (breadth-first search) */
488 while (sq_get_data(sq, &sublist)) {
489 exists = find_member(sublist, member_type, member_id, sq);
497 do_retrieve(q, qual, action, actarg)
498 register struct query *q;
511 ## range of rvar is rtable
516 ## retrieve unique (param (q->tlist, q->vaddr)) where cqual
518 (*action)(q->vcnt, q->vaddr, actarg);
521 ## retrieve unique (param (q->tlist, q->vaddr))
523 (*action)(q->vcnt, q->vaddr, actarg);
527 ## inquire_equel (rowcount = "rowcount")
529 return ((rowcount == 0) ? SMS_NO_MATCH : SMS_SUCCESS);
532 do_update(q, argv, qual, action, actarg)
533 register struct query *q;
546 ## range of rvar is rtable
549 ## replace rvar (param (q->tlist, argv))
555 do_append(q, argv, action, actarg)
556 register struct query *q;
567 ## range of rvar is rtable
571 ## append to rtable (param (q->tlist, argv)) where cqual
573 ## append to rtable (param (q->tlist, argv))
579 do_delete(q, qual, action, actarg)
580 register struct query *q;
591 ## range of rvar is rtable
594 ## delete rvar where cqual
604 * c-continued-statement-offset: 4
606 * c-argdecl-indent: 4