6 * Copyright (C) 1987 by the Massachusetts Institute of Technology
9 * Revision 1.6 1987-08-04 01:30:54 wesommer
10 * Mike's changes; checked in prior to working over messages.
12 * Revision 1.5 87/06/21 16:37:58 wesommer
13 * Changed include files, reindented things.
16 * Revision 1.4 87/06/08 05:03:27 wesommer
17 * Reindented; added header and trailer.
22 static char *rcsid_qrtn_qc = "$Header$";
26 #include "sms_server.h"
32 static int ingres_errno = 0;
36 * ingerr: (supposedly) called when Ingres indicates an error.
37 * I have not yet been able to get this to work to intercept a
38 * database open error.
41 static int ingerr(num)
44 ingres_errno = SMS_INGRES_ERR;
48 int sms_open_database()
52 /* initialize local argv */
53 for (i = 0; i < 16; i++)
54 Argv[i] = (char *)malloc(128);
60 /* open the database */
65 int sms_close_database()
70 sms_check_access(cl, name, argc, argv_ro)
76 register struct query *q;
79 register struct validate *v;
81 register int privileged;
82 struct query *get_query_by_name();
86 q = get_query_by_name(name);
87 if (q == (struct query *)0) return(SMS_NO_HANDLE);
90 /* copy the arguments into a local argv that we can modify */
91 for (i = 0; i < argc; i++)
92 strcpy(Argv[i], argv_ro[i]);
94 /* check initial query access */
95 status = check_query_access(q, Argv, cl);
96 privileged = (status == SMS_SUCCESS) ? 1 : 0;
97 if (status != SMS_SUCCESS && !(v && (v->pre_rtn == access_user ||
98 v->pre_rtn == access_pop)))
101 /* check argument count */
103 if (q->type == UPDATE || q->type == APPEND) argreq += q->vcnt;
104 if (argc != argreq) return(SMS_ARGS);
106 /* validate arguments */
107 if (v && v->valobj) {
108 status = validate_fields(q, Argv, v->valobj, v->objcnt);
109 if (status != SMS_SUCCESS) return(status);
112 /* perform special query access check */
113 if (v && v->pre_rtn) {
114 status = (*v->pre_rtn)(q, Argv, cl, 1);
115 if (status != SMS_SUCCESS && (status != SMS_PERM || !privileged))
122 sms_process_query(cl, name, argc, argv_ro, action, actarg)
130 register struct query *q;
134 register struct validate *v;
139 struct save_queue *sq;
140 struct query *get_query_by_name();
142 struct save_queue *sq_create();
145 /* copy the arguments into a local argv that we can modify */
146 for (i = 0; i < argc; i++)
147 strcpy(Argv[i], argv_ro[i]);
149 /* list queries command */
150 if (!strcmp(name, "_list_queries")) {
151 list_queries(action, actarg);
155 /* help query command */
156 if (!strcmp(name, "_help")) {
157 q = get_query_by_name(Argv[0]);
158 if (q == (struct query *)0) return(SMS_NO_HANDLE);
159 help_query(q, action, actarg);
163 /* get query structure, return error if named query does not exist */
164 q = get_query_by_name(name);
165 if (q == (struct query *)0) return(SMS_NO_HANDLE);
168 /* check query access */
169 status = check_query_access(q, Argv, cl);
170 privileged = (status == SMS_SUCCESS) ? 1 : 0;
171 if (status != SMS_SUCCESS && !(v && (v->pre_rtn == access_user)))
174 /* check argument count */
176 if (q->type == UPDATE || q->type == APPEND) argreq += q->vcnt;
177 if (argc != argreq) return(SMS_ARGS);
179 /* validate arguments */
180 if (v && v->valobj) {
181 status = validate_fields(q, Argv, v->valobj, v->objcnt);
182 if (status != SMS_SUCCESS) return(status);
185 /* perform any special query pre-processing */
186 if (v && v->pre_rtn) {
187 status = (*v->pre_rtn)(q, Argv, cl, 0);
188 if (status != SMS_SUCCESS && (status != SMS_PERM || !privileged))
196 /* for queries that do not permit wildcarding, check if row
199 status = validate_row(q, Argv, v);
200 if (status != SMS_EXISTS) break;
203 /* build "where" clause if needed */
205 build_qual(q->qual, q->argc, Argv, qual);
211 /* if there is a followup routine, then we must save the results */
212 /* of the first query for use by the followup routine */
213 /* if q->rtable = NULL, perform post_rtn only */
214 if (table = q->rtable) {
215 if (v && v->post_rtn) {
217 status = do_retrieve(q, pqual, sq_save_args, sq);
218 if (status != SMS_SUCCESS) {
222 status = (*v->post_rtn)(q, sq, v, action, actarg);
224 /* normal retrieve */
225 status = do_retrieve(q, pqual, action, actarg);
227 if (status != SMS_SUCCESS) break;
228 ## repeat replace tblstats (retrieves = tblstats.retrieves + 1)
229 ## where tblstats.#table = @table
231 status = (*v->post_rtn)(q, Argv, action, actarg);
237 /* see if row already exists */
239 status = validate_row(q, Argv, v);
240 if (status != SMS_EXISTS) break;
243 /* build "where" clause and perform update */
244 /* if q->rtable = NULL, perform post_rtn only */
245 if (table = q->rtable) {
246 build_qual(q->qual, q->argc, Argv, qual);
247 status = do_update(q, &Argv[q->argc], qual, action, actarg);
248 if (status != SMS_SUCCESS) break;
249 ## repeat replace tblstats (updates = tblstats.updates + 1,
251 ## where tblstats.#table = @table
254 /* execute followup routine (if any) */
255 if (v->post_rtn) status = (*v->post_rtn)(q, Argv);
260 /* see if row already exists */
262 status = validate_row(q, Argv, v);
263 if (status != SMS_NO_MATCH) break;
266 /* increment id number if necessary */
267 if (v->object_id) set_next_object_id(v->object_id);
269 /* perform the append */
270 /* if q->rtable = NULL, perform post_rtn only */
271 if (table = q->rtable) {
272 status = do_append(q, &Argv[q->argc], action, actarg);
273 if (status != SMS_SUCCESS) break;
274 ## repeat replace tblstats (appends = tblstats.appends + 1,
276 ## where tblstats.#table = @table
279 /* execute followup routine */
280 if (v->post_rtn) status = (*v->post_rtn)(q, Argv);
284 /* see if row already exists */
286 status = validate_row(q, Argv, v);
287 if (status != SMS_EXISTS) break;
290 /* build "where" clause and perform delete */
291 /* if q->rtable = NULL, perform post_rtn only */
292 if (table = q->rtable) {
293 build_qual(q->qual, q->argc, Argv, qual);
294 status = do_delete(q, qual, action, actarg);
295 if (status != SMS_SUCCESS) break;
296 ## repeat replace tblstats (deletes = tblstats.deletes + 1,
298 ## where tblstats.#table = @table
301 /* execute followup routine */
302 if (v->post_rtn) status = (*v->post_rtn)(q, Argv);
307 if (status == SMS_SUCCESS)
312 if (status != SMS_SUCCESS) com_err(whoami, status, " (Query failed)");
316 build_qual(fmt, argc, argv, qual)
327 for (i = 0; i < argc; i++) {
328 c = (char *)index(c, '%');
329 if (c++ == (char *)0) return(SMS_ARGS);
333 *(int *)&args[i] = *(int *)argv[i]; /* sigh */
335 return(SMS_INGRES_ERR);
344 sprintf(qual, fmt, args[0]);
348 sprintf(qual, fmt, args[0], args[1]);
352 sprintf(qual, fmt, args[0], args[1], args[2]);
356 sprintf(qual, fmt, args[0], args[1], args[2], args[3]);
361 check_query_access(q, argv, cl)
370 ## static int def_uid;
375 /* get query access control list */
377 ## repeat retrieve (acl_id = capacls.list_id) where capacls.tag = @name
378 ## inquire_equel (rowcount = "rowcount")
379 if (rowcount == 0) return(SMS_PERM);
381 /* initialize default uid */
383 ## retrieve (def_uid = users.users_id) where users.login = "default"
386 com_err(whoami, 0, "checking for default access");
387 /* check for default access */
388 ## range of m is members
389 ## repeat retrieve (exists = any(m.#member_id where m.list_id = @acl_id and
390 ## m.member_type = "USER" and m.#member_id = def_uid))
391 if (exists) return(SMS_SUCCESS);
393 /* parse client name */
394 status = get_client(cl, &client_type, &client_id);
395 if (status != SMS_SUCCESS) return(status);
397 com_err(whoami, 0, "checking for client in acl");
398 /* see if client is in the list (or any of its sub-lists) */
399 exists = find_member(acl_id, client_type, client_id, 0);
400 return ((exists) ? SMS_SUCCESS : SMS_PERM);
403 get_client(cl, client_type, client_id)
413 /* for now accept only null instances */
415 if (krb->inst[0]) return(SMS_PERM);
417 /* if client is from local realm, get users_id */
418 if (!strcmp(krb->realm, krb_realm)) {
420 ## repeat retrieve (member_id = users.users_id) where users.login = @name
421 *client_type = "USER";
423 /* otherwise use string_id */
425 ## repeat retrieve (member_id = strings.string_id)
426 ## where strings.string = @name
427 *client_type = "STRING";
430 /* make sure we found a users or string id */
431 ## inquire_equel (rowcount = "rowcount")
432 if (rowcount == 0) return(SMS_PERM);
434 *client_id = member_id;
438 ##find_member(list_id, member_type, member_id, sq)
440 ## char *member_type;
442 struct save_queue *sq;
447 struct save_queue *sq_create();
449 /* see if client is a direct member of list */
450 ## repeat retrieve (exists = any(m.#member_id where
451 ## m.#list_id = @list_id and
452 ## m.#member_type = @member_type and
453 ## m.#member_id = @member_id))
454 if (exists) return(1);
456 /* are there any sub-lists? */
457 com_err(whoami, 0, "checking for sub-lists");
458 ## repeat retrieve (exists = any(m.#member_id where m.#list_id = @list_id and
459 ## m.#member_type = "LIST"))
460 if (!exists) return(0);
462 /* yes; now recurse through sublists */
464 /* create a save queue */
465 if (sq == (struct save_queue *)0) {
472 /* save all sublist ids */
473 ## range of m is members
474 ## retrieve (sublist = m.#member_id)
475 ## where m.#list_id = list_id and m.#member_type = "LIST"
477 sq_save_unique_data(sq, sublist);
482 com_err(whoami, 0, "checking for client in sub-lists");
483 /* at top-level, check sub-lists for client (breadth-first search) */
484 while (sq_get_data(sq, &sublist)) {
485 exists = find_member(sublist, member_type, member_id, sq);
493 do_retrieve(q, qual, action, actarg)
494 register struct query *q;
507 ## range of rvar is rtable
512 ## retrieve unique (param (q->tlist, q->vaddr)) where cqual
514 (*action)(q->vcnt, q->vaddr, actarg);
517 ## retrieve unique (param (q->tlist, q->vaddr))
519 (*action)(q->vcnt, q->vaddr, actarg);
523 ## inquire_equel (rowcount = "rowcount")
525 return ((rowcount == 0) ? SMS_NO_MATCH : SMS_SUCCESS);
528 do_update(q, argv, qual, action, actarg)
529 register struct query *q;
542 ## range of rvar is rtable
545 ## replace rvar (param (q->tlist, argv))
551 do_append(q, argv, action, actarg)
552 register struct query *q;
563 ## range of rvar is rtable
567 ## append to rtable (param (q->tlist, argv)) where cqual
569 ## append to rtable (param (q->tlist, argv))
575 do_delete(q, qual, action, actarg)
576 register struct query *q;
587 ## range of rvar is rtable
590 ## delete rvar where cqual
600 * c-continued-statement-offset: 4
602 * c-argdecl-indent: 4