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