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