]>
Commit | Line | Data |
---|---|---|
05cdd922 | 1 | /* |
2 | * $Source$ | |
3 | * $Author$ | |
4 | * $Header$ | |
5 | * | |
6 | * Copyright (C) 1987 by the Massachusetts Institute of Technology | |
7 | * | |
8 | * $Log$ | |
9 | * Revision 1.1 1987-07-29 15:13:57 wesommer | |
10 | * Initial revision | |
11 | * | |
12 | */ | |
13 | ||
14 | #ifndef lint | |
15 | static char *rcsid_qsupport_qc = "$Header$"; | |
16 | #endif lint | |
17 | ||
18 | #include "query.h" | |
19 | #include "sms_server.h" | |
20 | #include <ctype.h> | |
21 | ||
22 | #define SMS_SUCCESS 0 | |
23 | ||
24 | extern char *whoami; | |
25 | ||
26 | /* Specialized Access Routines */ | |
27 | ||
28 | /** | |
29 | ** access_user - verify that client name equals specified login name | |
30 | ** | |
31 | ** Used by: update_user_shell | |
32 | ** update_finger_by_login | |
33 | ** | |
34 | ** - since field validation routines are called first, a users_id is | |
35 | ** now in argv[0] instead of the login name. Therefore, we must | |
36 | ** convert the client name to a users_id. | |
37 | **/ | |
38 | ||
39 | access_user(q, argv, cl) | |
40 | struct query *q; | |
41 | char *argv[]; | |
42 | client *cl; | |
43 | ##{ | |
44 | register struct krbname *krb; | |
45 | ## int client_id; | |
46 | ## char *client_name; | |
47 | ## int rowcount; | |
48 | ||
49 | client_name = cl->kname.name; | |
50 | ## repeat retrieve (client_id = users.users_id) | |
51 | ## where users.login = @client_name | |
52 | ## inquire_equel (rowcount = "rowcount") | |
53 | if (rowcount != 1) return(SMS_PERM); | |
54 | if (client_id != *(int *)argv[0]) return(SMS_PERM); | |
55 | ||
56 | return(SMS_SUCCESS); | |
57 | ##} | |
58 | ||
59 | /** | |
60 | ** access_list - check access for adding or deleting list members | |
61 | ** | |
62 | ** Inputs: argv[0] - list_id | |
63 | ** cl->krb.name - client name | |
64 | ** | |
65 | ** - check that client is a member of the access control list | |
66 | ** - OR, if q->shortname == {amtl | dfml} and | |
67 | ** if list.flags & LF_PUBLIC, allow access if client = member | |
68 | ** | |
69 | **/ | |
70 | ||
71 | access_list(q, argv, cl) | |
72 | struct query *q; | |
73 | char *argv[]; | |
74 | client *cl; | |
75 | ##{ | |
76 | ## int list_id; | |
77 | ## int acl_id; | |
78 | ## int flags; | |
79 | int member_id; | |
80 | char *client_type; | |
81 | int client_id; | |
82 | int status; | |
83 | int exists; | |
84 | ||
85 | list_id = *(int *)argv[0]; | |
86 | ## repeat retrieve (acl_id = list.#acl_id, flags = list.#flags) | |
87 | ## where list.#list_id = @list_id | |
88 | ||
89 | /* parse client structure */ | |
90 | status = get_client(cl, &client_type, &client_id); | |
91 | if (status != SMS_SUCCESS) return(status); | |
92 | ||
93 | /* if amtl or dmfl and list is public allow client to add or delete self */ | |
94 | if (!bcmp("amtl", q->shortname, 4) || !bcmp("dmfl", q->shortname, 4)) { | |
95 | if ((flags & LF_PUBLIC) && !bcmp("USER", argv[1], 4)) { | |
96 | member_id = *(int *)argv[2]; | |
97 | if (member_id == client_id) return(SMS_SUCCESS); | |
98 | } | |
99 | } | |
100 | ||
101 | /* check for client in access control list */ | |
102 | exists = find_member(acl_id, client_type, client_id, 0); | |
103 | if (!exists) return(SMS_PERM); | |
104 | ||
105 | return(SMS_SUCCESS); | |
106 | ##} | |
107 | \f | |
108 | /** | |
109 | ** Setup routine for add_user | |
110 | ** | |
111 | ** Inputs: argv[0] - login | |
112 | ** argv[1] - uid | |
113 | ** | |
114 | ** Description: | |
115 | ** | |
116 | ** - if argv[1] == "#" then set argv[1] = next(uid) | |
117 | ** - if argv[0] == "#" then set argv[0] = "#<uid>" | |
118 | ** | |
119 | **/ | |
120 | ||
121 | setup_add_user(q, argv, cl, access_check) | |
122 | struct query *q; | |
123 | register char *argv[]; | |
124 | client *cl; | |
125 | int access_check; | |
126 | ##{ | |
127 | ## int nuid; | |
128 | ## int exists; | |
129 | ||
130 | if (access_check) return(SMS_SUCCESS); | |
131 | ||
132 | if (!bcmp(argv[1], "#", 2)) { | |
133 | ## range of u is users | |
134 | ## range of v is values | |
135 | ## repeat retrieve (nuid = v.value) where v.name = "uid" | |
136 | exists = 1; | |
137 | while (exists) { | |
138 | nuid++; | |
139 | ## repeat retrieve (exists = any(u.#uid where u.#uid = @nuid)) | |
140 | } | |
141 | ## repeat replace v (value = @nuid) where v.name = "uid" | |
142 | sprintf(argv[1], "%d", nuid); | |
143 | } | |
144 | ||
145 | if (!bcmp(argv[0], "#", 2)) { | |
146 | sprintf(argv[0], "#%s", argv[1]); | |
147 | } | |
148 | ||
149 | return(SMS_SUCCESS); | |
150 | ##} | |
151 | ||
152 | /** | |
153 | ** Setup routine for add_group | |
154 | ** | |
155 | ** Inputs: none | |
156 | ** | |
157 | ** Description: allocate next gid and store in values table | |
158 | ** | |
159 | **/ | |
160 | ||
161 | setup_add_group(q, argv, cl, access_check) | |
162 | struct query *q; | |
163 | char *argv[]; | |
164 | client *cl; | |
165 | int access_check; | |
166 | ##{ | |
167 | ## int ngid; | |
168 | ## int exists; | |
169 | ||
170 | if (access_check) return(SMS_SUCCESS); | |
171 | ||
172 | ## range of g is groups | |
173 | ## range of v is values | |
174 | ## repeat retrieve (ngid = v.value) where v.name = "gid" | |
175 | exists = 1; | |
176 | while (exists) { | |
177 | ngid++; | |
178 | ## repeat retrieve (exists = any(g.#gid where g.#gid = @ngid)) | |
179 | } | |
180 | ||
181 | ## repeat replace v (value = @ngid) where v.name = "gid" | |
182 | return(SMS_SUCCESS); | |
183 | ##} | |
184 | \f | |
185 | /* Followup Routines */ | |
186 | ||
187 | set_user_modtime(q, argv) | |
188 | struct query *q; | |
189 | char *argv[]; | |
190 | ##{ | |
191 | ## char *login; | |
192 | ||
193 | login = argv[0]; | |
194 | ## repeat replace u (modtime = "now") where u.#login = @login | |
195 | return(SMS_SUCCESS); | |
196 | ##} | |
197 | ||
198 | set_user_modtime_by_id(q, argv) | |
199 | struct query *q; | |
200 | char *argv[]; | |
201 | ##{ | |
202 | ## int users_id; | |
203 | ||
204 | users_id = *(int *)argv[0]; | |
205 | ## repeat replace users (modtime = "now") where users.#users_id = @users_id | |
206 | return(SMS_SUCCESS); | |
207 | ##} | |
208 | ||
209 | set_list_modtime(q, argv) | |
210 | struct query *q; | |
211 | char *argv[]; | |
212 | ##{ | |
213 | ## char *list_name; | |
214 | ||
215 | list_name = argv[0]; | |
216 | ## repeat replace list (modtime = "now") where list.name = @list_name | |
217 | return(SMS_SUCCESS); | |
218 | ##} | |
219 | ||
220 | set_list_modtime_by_id(q, argv) | |
221 | struct query *q; | |
222 | char *argv[]; | |
223 | ##{ | |
224 | ## int list_id; | |
225 | ||
226 | list_id = *(int *)argv[0]; | |
227 | ## repeat replace list (modtime = "now") where list.#list_id = @list_id | |
228 | return(SMS_SUCCESS); | |
229 | ##} | |
230 | ||
231 | set_finger_modtime(q, argv) | |
232 | struct query *q; | |
233 | char *argv[]; | |
234 | ##{ | |
235 | ## int users_id; | |
236 | ||
237 | users_id = *(int *)argv[0]; | |
238 | ## repeat replace f (modtime = "now") where f.#users_id = @users_id | |
239 | return(SMS_SUCCESS); | |
240 | ##} | |
241 | ||
242 | /** | |
243 | ** delete_list_members - called after the delete_list query to clean up | |
244 | ** members table. | |
245 | ** | |
246 | ** Inputs: argv[0] - list_id | |
247 | ** | |
248 | ** Description: | |
249 | ** - foreach string member: decr string refc; ifzero, delete string | |
250 | ** - delete all members entries for this list_id | |
251 | ** | |
252 | **/ | |
253 | ||
254 | delete_list_members(q, argv) | |
255 | struct query *q; | |
256 | register char *argv[]; | |
257 | ##{ | |
258 | ## int list_id; | |
259 | ## int string_id; | |
260 | ## int refc; | |
261 | ## int rowcount; | |
262 | struct save_queue *sq; | |
263 | struct save_queue *sq_create(); | |
264 | ||
265 | list_id = *(int *)argv[0]; | |
266 | sq = sq_create(); | |
267 | ||
268 | ## range of m is members | |
269 | ## repeat retrieve (string_id = m.member_id) | |
270 | ## where m.#list_id = @list_id and m.member_type = "STRING" | |
271 | ## { | |
272 | sq_save_data(sq, string_id); | |
273 | ## } | |
274 | ||
275 | while (sq_get_data(sq, &string_id)) { | |
276 | ## range of s is strings | |
277 | ## repeat retrieve (refc = s.#refc) where s.#string_id = @string_id | |
278 | ## inquire_equel (rowcount = "rowcount") | |
279 | if (rowcount == 0) continue; | |
280 | if (--refc == 0) { | |
281 | ## repeat delete s where s.#string_id = @string_id | |
282 | } else { | |
283 | ## repeat replace s (#refc = @refc) where s.#string_id = @string_id | |
284 | } | |
285 | } | |
286 | sq_destroy(sq); | |
287 | ||
288 | ## repeat delete m where m.#list_id = @list_id | |
289 | ||
290 | return(SMS_SUCCESS); | |
291 | ##} | |
292 | ||
293 | /** | |
294 | ** grvd_support - Support routine for get_rvd_servers query | |
295 | ** | |
296 | ** Inputs: | |
297 | ** q - grvd query structure | |
298 | ** sq - save_queue struture: contains list of {machine, oper_acl_id, | |
299 | ** admin_acl_id, shutdown_acl_id} records. | |
300 | ** v - validate structure (not used) | |
301 | ** action - action routine | |
302 | ** actarg - action routine argument | |
303 | ** | |
304 | ** Description: | |
305 | ** - translate acl_ids to list names | |
306 | ** | |
307 | **/ | |
308 | ||
309 | grvd_support(q, sq, v, action, actarg) | |
310 | struct query *q; | |
311 | struct save_queue *sq; | |
312 | struct validate *v; | |
313 | int (*action)(); | |
314 | int actarg; | |
315 | ##{ | |
316 | char **argv; | |
317 | char *targv[4]; | |
318 | ## char oper[33]; | |
319 | ## char admin[33]; | |
320 | ## char shutdown[33]; | |
321 | ## int list_id; | |
322 | ||
323 | targv[1] = oper; | |
324 | targv[2] = admin; | |
325 | targv[3] = shutdown; | |
326 | ||
327 | ## range of l is list | |
328 | ||
329 | while (sq_get_data(sq, &argv)) { | |
330 | sscanf(argv[1], "%d", &list_id); | |
331 | ## repeat retrieve (oper = l.name) where l.#list_id = @list_id | |
332 | sscanf(argv[2], "%d", &list_id); | |
333 | ## repeat retrieve (admin = l.name) where l.#list_id = @list_id | |
334 | sscanf(argv[3], "%d", &list_id); | |
335 | ## repeat retrieve (shutdown = l.name) where l.#list_id = @list_id | |
336 | ||
337 | targv[0] = argv[0]; | |
338 | (*action)(4, targv, actarg); | |
339 | free(argv[0]); | |
340 | free(argv[1]); | |
341 | free(argv[2]); | |
342 | free(argv[3]); | |
343 | } | |
344 | ||
345 | sq_destroy(sq); | |
346 | return(SMS_SUCCESS); | |
347 | ##} | |
348 | ||
349 | /** | |
350 | ** set_next_object_id - set next object id in values table | |
351 | ** | |
352 | ** Inputs: object - object name in values table | |
353 | ** | |
354 | ** - called before an APPEND operation to set the next object id to | |
355 | ** be used for the new record | |
356 | ** | |
357 | **/ | |
358 | ||
359 | set_next_object_id(object) | |
360 | char *object; | |
361 | ##{ | |
362 | ## char *name; | |
363 | ## int id; | |
364 | ||
365 | name = object; | |
366 | ## range of v is values | |
367 | ## repeat retrieve (id = v.value) where v.#name = @name | |
368 | id++; | |
369 | ## repeat replace v (value = @id) where v.#name = @name | |
370 | return(SMS_SUCCESS); | |
371 | ##} | |
372 | ||
373 | \f | |
374 | /** | |
375 | ** add_locker - special query routine for creating a user locker | |
376 | ** | |
377 | ** Inputs: | |
378 | ** argv[0] - users_id | |
379 | ** argv[1] - machine_id | |
380 | ** argv[2] - device | |
381 | ** argv[3] - initial quota | |
382 | ** | |
383 | ** Description: | |
384 | ** - get prefix directory (dir) for mount point on specified machine/device | |
385 | ** - create filesys entry (label=<login>, type=NFS, machine=<machine>, | |
386 | ** mount=<dir>/<login>, access=w, acl=dbadmin) | |
387 | ** - increment allocated in nfsphys by quota | |
388 | ** - create nfsquota entry | |
389 | ** | |
390 | ** Errors: | |
391 | ** - SMS_NFSPHYS - machine/device does not exist in nfsphys | |
392 | ** - SMS_FILESYS_EXISTS - file system already exists | |
393 | ** | |
394 | **/ | |
395 | ||
396 | add_locker(q, argv) | |
397 | register struct query *q; | |
398 | char *argv[]; | |
399 | ##{ | |
400 | ## int users_id; | |
401 | ## int mach_id; | |
402 | ## char *device; | |
403 | ## int quota; | |
404 | ## int rowcount; | |
405 | ## char *login; | |
406 | ## char dir[32]; | |
407 | ## int allocated; | |
408 | ## char locker[64]; | |
409 | ## char mount[64]; | |
410 | ## int user_acl; | |
411 | ||
412 | /* copy arguments */ | |
413 | users_id = *(int *)argv[0]; | |
414 | mach_id = *(int *)argv[1]; | |
415 | device = argv[2]; | |
416 | sscanf(argv[3], "%d", "a); | |
417 | ||
418 | ## range of u is users | |
419 | ## range of f is filesys | |
420 | ## range of np is nfsphys | |
421 | ||
422 | /* get login name */ | |
423 | ## repeat retrieve (login = u.#login) where u.#users_id = @users_id | |
424 | ||
425 | /* get user's acl id */ | |
426 | ## repeat retrieve (user_acl = list.list_id) where list.name = @login | |
427 | ||
428 | /* get filesystem directory prefix; give error if machine/device | |
429 | pair not in nfsphys table */ | |
430 | ## repeat retrieve (dir = np.#dir, allocated = np.#allocated) | |
431 | ## where np.#mach_id = @mach_id and np.#device = device | |
432 | ## inquire_equel (rowcount = "rowcount") | |
433 | if (rowcount == 0) return(SMS_NFSPHYS); | |
434 | ||
435 | /* make sure a filesys with user's name does not already exist */ | |
436 | ## repeat retrieve (rowcount = any(f.label where f.label = @login)) | |
437 | if (rowcount != 0) return(SMS_FILESYS_EXISTS); | |
438 | ||
439 | /* create a new filesys */ | |
440 | sprintf(locker, "%s/%s", dir, login); | |
441 | sprintf(mount, "/mit/%s", login); | |
442 | ## repeat append filesys | |
443 | ## (#users_id = @users_id, type = "NFS", #mach_id = @mach_id, | |
444 | ## name = @locker, access = "w", order = 1, #mount = @mount, | |
445 | ## acl_id = @user_acl) | |
446 | ||
447 | /* increment usage count in nfsphys table */ | |
448 | allocated += quota; | |
449 | ## replace np (#allocated = allocated) | |
450 | ## where np.#mach_id = mach_id and np.#device = device | |
451 | ||
452 | /* create nfsquota entry */ | |
453 | ## append nfsquota (#users_id = users_id, #mach_id = mach_id, | |
454 | ## device = #device, #quota = quota) | |
455 | ||
456 | return(SMS_SUCCESS); | |
457 | ##} | |
458 | \f | |
459 | /* Validation Routines */ | |
460 | ||
461 | validate_row(q, argv, v) | |
462 | register struct query *q; | |
463 | char *argv[]; | |
464 | register struct validate *v; | |
465 | ##{ | |
466 | ## char *rvar; | |
467 | ## char *table; | |
468 | ## char *name; | |
469 | ## char qual[128]; | |
470 | ## int rowcount; | |
471 | ||
472 | /* build where clause */ | |
473 | build_qual(v->qual, v->argc, argv, qual); | |
474 | ||
475 | /* setup ingres variables */ | |
476 | rvar = q->rvar; | |
477 | table = q->rtable; | |
478 | name = v->field; | |
479 | ||
480 | /* tell the logfile what we're doing */ | |
481 | com_err(whoami, 0, "validating row"); | |
482 | com_err(whoami, 0, qual); | |
483 | ||
484 | /* look for the record */ | |
485 | ## range of rvar is table | |
486 | ## retrieve (rowcount = count(rvar.name where qual)) | |
487 | com_err(whoami, 0, "row validated"); | |
488 | if (rowcount == 0) return(SMS_NO_MATCH); | |
489 | if (rowcount > 1) return(SMS_NOT_UNIQUE); | |
490 | return(SMS_EXISTS); | |
491 | ##} | |
492 | ||
493 | validate_fields(q, argv, vo, n) | |
494 | struct query *q; | |
495 | register char *argv[]; | |
496 | register struct valobj *vo; | |
497 | register int n; | |
498 | { | |
499 | register int status; | |
500 | char buf[64]; | |
501 | ||
502 | while (--n >= 0) { | |
503 | switch (vo->type) { | |
504 | case V_NAME: | |
505 | sprintf(buf, "validating %s in %s: %s", | |
506 | vo->namefield, vo->table, argv[vo->index]); | |
507 | com_err(whoami, 0, buf); | |
508 | status = validate_name(argv, vo); | |
509 | break; | |
510 | ||
511 | case V_ID: | |
512 | sprintf(buf, "validating %s in %s: %s", | |
513 | vo->idfield, vo->table, argv[vo->index]); | |
514 | com_err(whoami, 0, buf); | |
515 | status = validate_id(argv, vo); | |
516 | break; | |
517 | ||
518 | case V_TYPE: | |
519 | sprintf(buf, "validating %s type: %s", | |
520 | vo->table, argv[vo->index]); | |
521 | com_err(whoami, 0, buf); | |
522 | status = validate_type(argv, vo); | |
523 | break; | |
524 | ||
525 | case V_TYPEDATA: | |
526 | sprintf(buf, "validating type-specific data: %s", | |
527 | argv[vo->index]); | |
528 | com_err(whoami, 0, buf); | |
529 | status = validate_typedata(q, argv, vo); | |
530 | break; | |
531 | ||
532 | case V_FOLLOWUP: | |
533 | status = SMS_EXISTS; | |
534 | break; | |
535 | ||
536 | } | |
537 | ||
538 | if (status != SMS_EXISTS) return(status); | |
539 | vo++; | |
540 | } | |
541 | ||
542 | return(SMS_SUCCESS); | |
543 | } | |
544 | ||
545 | validate_id(argv, vo) | |
546 | char *argv[]; | |
547 | register struct valobj *vo; | |
548 | ##{ | |
549 | ## char *name; | |
550 | ## char *table; | |
551 | ## char *namefield; | |
552 | ## char *idfield; | |
553 | ## int id; | |
554 | ## int rowcount; | |
555 | ||
556 | name = argv[vo->index]; | |
557 | table = vo->table; | |
558 | namefield = vo->namefield; | |
559 | idfield = vo->idfield; | |
560 | ## retrieve (id = table.idfield) where table.namefield = name | |
561 | ## inquire_equel (rowcount = "rowcount") | |
562 | if (rowcount != 1) return(vo->error); | |
563 | *(int *)argv[vo->index] = id; | |
564 | return(SMS_EXISTS); | |
565 | ##} | |
566 | ||
567 | validate_name(argv, vo) | |
568 | char *argv[]; | |
569 | register struct valobj *vo; | |
570 | ##{ | |
571 | ## char *name; | |
572 | ## char *table; | |
573 | ## char *namefield; | |
574 | ## int rowcount; | |
575 | ||
576 | name = argv[vo->index]; | |
577 | table = vo->table; | |
578 | namefield = vo->namefield; | |
579 | ## retrieve (rowcount = countu(table.namefield | |
580 | ## where table.namefield = name)) | |
581 | return ((rowcount == 1) ? SMS_EXISTS : vo->error); | |
582 | ##} | |
583 | ||
584 | validate_type(argv, vo) | |
585 | char *argv[]; | |
586 | register struct valobj *vo; | |
587 | ##{ | |
588 | ## char *typename; | |
589 | ## char *value; | |
590 | ## int rowcount; | |
591 | register char *c; | |
592 | ||
593 | typename = vo->table; | |
594 | value = argv[vo->index]; | |
595 | ||
596 | /* uppercase type fields */ | |
597 | for (c = value; *c; c++) if (islower(*c)) *c = toupper(*c); | |
598 | ||
599 | ## range of a is alias | |
600 | ## repeat retrieve (rowcount = count(a.trans where a.name = @typename and | |
601 | ## a.type = "TYPE" and | |
602 | ## a.trans = @value)) | |
603 | return ((rowcount == 1) ? SMS_EXISTS : vo->error); | |
604 | ##} | |
605 | ||
606 | /* validate member or type-specific data field */ | |
607 | ||
608 | validate_typedata(q, argv, vo) | |
609 | register struct query *q; | |
610 | register char *argv[]; | |
611 | register struct valobj *vo; | |
612 | ##{ | |
613 | ## char *name; | |
614 | ## char *field_type; | |
615 | ## char data_type[17]; | |
616 | ## int id; | |
617 | ## int refc; | |
618 | ## int rowcount; | |
619 | ||
620 | /* get named object */ | |
621 | name = argv[vo->index]; | |
622 | ||
623 | /* get field type string (known to be at index-1) */ | |
624 | field_type = argv[vo->index-1]; | |
625 | ||
626 | /* get corresponding data type associated with field type name */ | |
627 | ## repeat retrieve (data_type = alias.trans) | |
628 | ## where alias.#name = @field_type and alias.type = "TYPEDATA" | |
629 | ## inquire_equel (rowcount = "rowcount") | |
630 | if (rowcount != 1) return(SMS_TYPE); | |
631 | ||
632 | /* now retrieve the record id corresponding to the named object */ | |
633 | ||
634 | if (!strcmp(data_type, "user")) { | |
635 | /* USER */ | |
636 | ## repeat retrieve (id = users.users_id) where users.login = @name | |
637 | ## inquire_equel (rowcount = "rowcount") | |
638 | if (rowcount != 1) return(SMS_USER); | |
639 | ||
640 | } else if (!strcmp(data_type, "list")) { | |
641 | /* LIST */ | |
642 | ## repeat retrieve (id = list.list_id) where list.#name = @name | |
643 | ## inquire_equel (rowcount = "rowcount") | |
644 | if (rowcount != 1) return(SMS_LIST); | |
645 | ||
646 | } else if (!strcmp(data_type, "machine")) { | |
647 | /* MACHINE */ | |
648 | ## repeat retrieve (id = machine.mach_id) where machine.#name = @name | |
649 | ## inquire_equel (rowcount = "rowcount") | |
650 | if (rowcount != 1) return(SMS_MACHINE); | |
651 | ||
652 | } else if (!strcmp(data_type, "string")) { | |
653 | /* STRING */ | |
654 | ## range of s is strings | |
655 | ## repeat retrieve (id = s.string_id, refc = s.#refc) | |
656 | ## where s.string = @name | |
657 | ## inquire_equel (rowcount = "rowcount") | |
658 | if (rowcount == 0) { | |
659 | if (q->type != APPEND) return(SMS_STRING); | |
660 | ## range of v is values | |
661 | ## retrieve (id = v.value) where v.#name = "strings_id" | |
662 | id++; | |
663 | ## replace v (value = id) where v.#name = "strings_id" | |
664 | ## append to strings (string_id = id, string = name, #refc = 1) | |
665 | } else if (rowcount == 1) { | |
666 | if (q->type == APPEND || q->type == DELETE) { | |
667 | refc += (q->type == APPEND) ? 1 : -1; | |
668 | if (refc > 0) { | |
669 | ## replace s (#refc = refc) where s.string_id = id | |
670 | } else { | |
671 | ## delete s where s.string_id = id | |
672 | } | |
673 | } | |
674 | } | |
675 | } else { | |
676 | return(SMS_TYPE); | |
677 | } | |
678 | ||
679 | /* now set value in argv */ | |
680 | *(int *)argv[vo->index] = id; | |
681 | ||
682 | return (SMS_EXISTS); | |
683 | ##} | |
684 | ||
685 | \f | |
686 | translate_ids(q, sq, v, action, actarg) | |
687 | register struct query *q; | |
688 | register struct save_queue *sq; | |
689 | register struct validate *v; | |
690 | register int (*action)(); | |
691 | int actarg; | |
692 | ##{ | |
693 | ## char *name; | |
694 | ## char *field_type; | |
695 | ## char data_type[17]; | |
696 | ## int id; | |
697 | ## int rowcount; | |
698 | register int i; | |
699 | struct valobj *vo; | |
700 | char **argv; | |
701 | ||
702 | for (i = 0; i < v->objcnt; i++) { | |
703 | vo = &v->valobj[i]; | |
704 | if (vo->type == V_FOLLOWUP) break; | |
705 | } | |
706 | ||
707 | /* for each row */ | |
708 | while (sq_get_data(sq, &argv)) { | |
709 | ||
710 | /* get object id */ | |
711 | i = vo->index; | |
712 | sscanf(argv[i], "%d", &id); | |
713 | free(argv[i]); | |
714 | name = (char *)malloc(129); | |
715 | argv[i] = name; | |
716 | ||
717 | /* get field type string (known to be at index-1) */ | |
718 | field_type = argv[vo->index-1]; | |
719 | ||
720 | /* get corresponding data type associated with field type name */ | |
721 | ## repeat retrieve (data_type = alias.trans) | |
722 | ## where alias.#name = @field_type and alias.type = "TYPEDATA" | |
723 | ## inquire_equel (rowcount = "rowcount") | |
724 | if (rowcount != 1) { | |
725 | sprintf(name, "%d", id); | |
726 | (*action)(q->vcnt, argv, actarg); | |
727 | continue; | |
728 | } | |
729 | ||
730 | /* retrieve object name */ | |
731 | ||
732 | if (!strcmp(data_type, "user")) { | |
733 | /* USER */ | |
734 | ## repeat retrieve (name = users.login) where users.users_id = @id | |
735 | ## inquire_equel (rowcount = "rowcount") | |
736 | ||
737 | } else if (!strcmp(data_type, "list")) { | |
738 | /* LIST */ | |
739 | ## repeat retrieve (name = list.#name) where list.list_id = @id | |
740 | ## inquire_equel (rowcount = "rowcount") | |
741 | ||
742 | } else if (!strcmp(data_type, "machine")) { | |
743 | /* MACHINE */ | |
744 | ## repeat retrieve (name = machine.#name) where machine.mach_id = @id | |
745 | ## inquire_equel (rowcount = "rowcount") | |
746 | ||
747 | } else if (!strcmp(data_type, "string")) { | |
748 | /* STRING */ | |
749 | ## repeat retrieve (name = strings.string) | |
750 | ## where strings.string_id = @id | |
751 | ## inquire_equel (rowcount = "rowcount") | |
752 | ||
753 | } else { | |
754 | rowcount = 0; | |
755 | } | |
756 | ||
757 | /* if there wasn't a corresponding object name, then use the id */ | |
758 | if (rowcount != 1) sprintf(name, "%d", id); | |
759 | ||
760 | /* send the data */ | |
761 | (*action)(q->vcnt, argv, actarg); | |
762 | ||
763 | /* free saved data */ | |
764 | for (i = 0; i < q->vcnt; i++) | |
765 | free(argv[i]); | |
766 | free(argv); | |
767 | } | |
768 | ||
769 | sq_destroy(sq); | |
770 | return (SMS_SUCCESS); | |
771 | ##} | |
772 | \f | |
773 | /* | |
774 | * Local Variables: | |
775 | * mode: c | |
776 | * c-indent-level: 4 | |
777 | * c-continued-statement-offset: 4 | |
778 | * c-brace-offset: -4 | |
779 | * c-argdecl-indent: 4 | |
780 | * c-label-offset: -4 | |
781 | * End: | |
782 | */ |